don't move multiple NPCs into the same spot
This commit is contained in:
parent
4ed6648ca8
commit
ec2a570b30
|
@ -29,6 +29,8 @@ this.runtimeData = {
|
||||||
},
|
},
|
||||||
-- NPCs who have been moved
|
-- NPCs who have been moved
|
||||||
movedNPCs = {},
|
movedNPCs = {},
|
||||||
|
-- positions that haven't been used
|
||||||
|
positions = {},
|
||||||
-- player companions
|
-- player companions
|
||||||
followers = {}
|
followers = {}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +75,22 @@ this.pickPublicHouseType = function(cell)
|
||||||
return this.publicHouseTypes.inns
|
return this.publicHouseTypes.inns
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
this.checkModdedCell = function(cellId)
|
||||||
|
local id
|
||||||
|
|
||||||
|
if cellId == "Balmora, South Wall Cornerclub" and tes3.isModActive("South Wall.ESP") then
|
||||||
|
id = "Balmora, South Wall Den Of Iniquity"
|
||||||
|
elseif cellId == "Balmora, Eight Plates" and tes3.isModActive("Eight Plates.esp") then
|
||||||
|
id = "Balmora, Seedy Eight Plates"
|
||||||
|
elseif cellId == "Hla Oad, Fatleg's Drop Off" and tes3.isModActive("Clean DR115_TheDropoff_HlaOadDocks.ESP") then
|
||||||
|
id = "Hla Oad, The Drop Off"
|
||||||
|
else
|
||||||
|
id = cellId
|
||||||
|
end
|
||||||
|
|
||||||
|
return id
|
||||||
|
end
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
|
|
@ -37,29 +37,13 @@ end
|
||||||
|
|
||||||
-- }}}
|
-- }}}
|
||||||
|
|
||||||
this.checkModdedCell = function(cellId)
|
|
||||||
local id
|
|
||||||
|
|
||||||
if cellId == "Balmora, South Wall Cornerclub" and tes3.isModActive("South Wall.ESP") then
|
|
||||||
id = "Balmora, South Wall Den Of Iniquity"
|
|
||||||
elseif cellId == "Balmora, Eight Plates" and tes3.isModActive("Eight Plates.esp") then
|
|
||||||
id = "Balmora, Seedy Eight Plates"
|
|
||||||
elseif cellId == "Hla Oad, Fatleg's Drop Off" and tes3.isModActive("Clean DR115_TheDropoff_HlaOadDocks.ESP") then
|
|
||||||
id = "Hla Oad, The Drop Off"
|
|
||||||
else
|
|
||||||
id = cellId
|
|
||||||
end
|
|
||||||
|
|
||||||
return id
|
|
||||||
end
|
|
||||||
|
|
||||||
this.createHomedNPCTableEntry = function(npc, home, startingPlace, isHome, position, orientation)
|
this.createHomedNPCTableEntry = function(npc, home, startingPlace, isHome, position, orientation)
|
||||||
if npc.object and (npc.object.name == nil or npc.object.name == "") then return end
|
if npc.object and (npc.object.name == nil or npc.object.name == "") then return end
|
||||||
|
|
||||||
local pickedPosition, pickedOrientation, pos, ori
|
local pickedPosition, pickedOrientation, pos, ori
|
||||||
|
|
||||||
-- mod support for different positions in cells
|
-- mod support for different positions in cells
|
||||||
local id = this.checkModdedCell(home.id)
|
local id = common.checkModdedCell(home.id)
|
||||||
|
|
||||||
log(common.logLevels.medium, "Found %s for %s: %s... adding it to in memory table...",
|
log(common.logLevels.medium, "Found %s for %s: %s... adding it to in memory table...",
|
||||||
isHome and "home" or "public house", npc.object.name, id)
|
isHome and "home" or "public house", npc.object.name, id)
|
||||||
|
@ -67,22 +51,21 @@ this.createHomedNPCTableEntry = function(npc, home, startingPlace, isHome, posit
|
||||||
if isHome and positions.npcs[npc.object.name] then
|
if isHome and positions.npcs[npc.object.name] then
|
||||||
pos = positions.npcs[npc.object.name].position
|
pos = positions.npcs[npc.object.name].position
|
||||||
ori = positions.npcs[npc.object.name].orientation
|
ori = positions.npcs[npc.object.name].orientation
|
||||||
-- pickedPosition = positions.npcs[npc.object.name] and tes3vector3.new(p[1], p[2], p[3]) or zeroVector:copy()
|
-- elseif positions.cells[id] then
|
||||||
-- pickedOrientation = positions.npcs[npc.object.name] and tes3vector3.new(o[1], o[2], o[3]) or zeroVector:copy()
|
elseif common.runtimeData.positions[id] then
|
||||||
elseif positions.cells[id] then
|
-- pos = table.choice(positions.cells[id]).position
|
||||||
pos = table.choice(positions.cells[id]).position
|
-- ori = table.choice(positions.cells[id]).orientation
|
||||||
ori = table.choice(positions.cells[id]).orientation
|
local choice, index = table.choice(common.runtimeData.positions[id])
|
||||||
-- pickedPosition = positions.cells[id] and tes3vector3.new(p[1], p[2], p[3]) or zeroVector:copy()
|
pos = choice.position
|
||||||
-- pickedOrientation = positions.cells[id] and tes3vector3.new(o[1], o[2], o[3]) or zeroVector:copy()
|
ori = choice.orientation
|
||||||
-- pickedPosition = tes3vector3.new(p[1], p[2], p[3])
|
table.remove(common.runtimeData.positions[id], index)
|
||||||
-- pickedOrientation = tes3vector3.new(o[1], o[2], o[3])
|
|
||||||
else
|
else
|
||||||
pos = {0,0,0}
|
pos = {0,0,0}
|
||||||
ori = {0,0,0}
|
ori = {0,0,0}
|
||||||
-- pickedPosition = zeroVector:copy()
|
|
||||||
-- pickedOrientation = zeroVector:copy()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
log(common.logLevels.large, "Settled on position:%s, orientation:%s for %s in %s", pos, ori, npc.object.name, id)
|
||||||
|
|
||||||
pickedPosition = tes3vector3.new(pos[1], pos[2], pos[3])
|
pickedPosition = tes3vector3.new(pos[1], pos[2], pos[3])
|
||||||
pickedOrientation = tes3vector3.new(ori[1], ori[2], ori[3])
|
pickedOrientation = tes3vector3.new(ori[1], ori[2], ori[3])
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,8 @@ end
|
||||||
|
|
||||||
this.pickPublicHouseForNPC = function(npc, city)
|
this.pickPublicHouseForNPC = function(npc, city)
|
||||||
-- look for wandering guild members
|
-- look for wandering guild members
|
||||||
if common.runtimeData.publicHouses[city] and common.runtimeData.publicHouses[city][common.publicHouseTypes.guildhalls] then
|
if common.runtimeData.publicHouses[city] and
|
||||||
|
common.runtimeData.publicHouses[city][common.publicHouseTypes.guildhalls] then
|
||||||
for _, data in pairs(common.runtimeData.publicHouses[city][common.publicHouseTypes.guildhalls]) do
|
for _, data in pairs(common.runtimeData.publicHouses[city][common.publicHouseTypes.guildhalls]) do
|
||||||
-- if npc's faction and proprietor's faction match, pick that one
|
-- if npc's faction and proprietor's faction match, pick that one
|
||||||
if npc.object.faction == data.proprietor.object.faction then
|
if npc.object.faction == data.proprietor.object.faction then
|
||||||
|
@ -78,8 +79,6 @@ this.pickHomeForNPC = function(cell, npc)
|
||||||
for _, str in pairs(contextualNPCs) do if npc.object.id:match(str) then return end end
|
for _, str in pairs(contextualNPCs) do if npc.object.id:match(str) then return end end
|
||||||
|
|
||||||
-- time to pick the "home"
|
-- time to pick the "home"
|
||||||
local picked = nil
|
|
||||||
|
|
||||||
local name = npc.object.name
|
local name = npc.object.name
|
||||||
local city = common.split(cell.name, ",")[1]
|
local city = common.split(cell.name, ",")[1]
|
||||||
for door in cell:iterateReferences(tes3.objectType.door) do
|
for door in cell:iterateReferences(tes3.objectType.door) do
|
||||||
|
@ -88,11 +87,9 @@ this.pickHomeForNPC = function(cell, npc)
|
||||||
|
|
||||||
-- essentially, if npc full name, or surname matches the cell name
|
-- essentially, if npc full name, or surname matches the cell name
|
||||||
if dest.id:match(name) or this.livesInManor(dest.name, name) then
|
if dest.id:match(name) or this.livesInManor(dest.name, name) then
|
||||||
if common.runtimeData.homes.byName[name] then -- already have a home, don't create the table dataTables again
|
-- already have a home, don't create the table dataTables again
|
||||||
picked = common.runtimeData.homes.byName[name]
|
return common.runtimeData.homes.byName[name] and common.runtimeData.homes.byName[name] or
|
||||||
else
|
dataTables.createHomedNPCTableEntry(npc, dest, cell, true)
|
||||||
picked = dataTables.createHomedNPCTableEntry(npc, dest, cell, true)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -102,21 +99,23 @@ this.pickHomeForNPC = function(cell, npc)
|
||||||
log(common.logLevels.medium, "Didn't find a home for %s, trying inns", npc.object.name)
|
log(common.logLevels.medium, "Didn't find a home for %s, trying inns", npc.object.name)
|
||||||
local dest = this.pickPublicHouseForNPC(npc, city)
|
local dest = this.pickPublicHouseForNPC(npc, city)
|
||||||
|
|
||||||
if dest then picked = dataTables.createHomedNPCTableEntry(npc, dest, cell, false) end
|
if dest then return dataTables.createHomedNPCTableEntry(npc, dest, cell, false) end
|
||||||
|
|
||||||
-- if nothing was found, then we'll settle on Canton works cell, if the cell is a Canton
|
-- if nothing was found, then we'll settle on Canton works cell, if the cell is a Canton
|
||||||
if checks.isCantonCell(cell) then
|
if checks.isCantonCell(cell) then
|
||||||
if common.runtimeData.publicHouses[city] and common.runtimeData.publicHouses[city][common.publicHouseTypes.cantonworks] then
|
if common.runtimeData.publicHouses[city] and
|
||||||
|
common.runtimeData.publicHouses[city][common.publicHouseTypes.cantonworks] then
|
||||||
-- todo: maybe poorer NPCs in canalworks, others in waistworks ?
|
-- todo: maybe poorer NPCs in canalworks, others in waistworks ?
|
||||||
local canton = table.choice(common.runtimeData.publicHouses[city][common.publicHouseTypes.cantonworks])
|
local canton = table.choice(common.runtimeData.publicHouses[city][common.publicHouseTypes.cantonworks])
|
||||||
log(common.logLevels.medium, "Picking works %s, %s for %s", canton.city, canton.name, npc.object.name)
|
log(common.logLevels.medium, "Picking works %s, %s for %s", canton.city, canton.name, npc.object.name)
|
||||||
|
|
||||||
if canton then picked = dataTables.createHomedNPCTableEntry(npc, canton.cell, cell, false) end
|
if canton then return dataTables.createHomedNPCTableEntry(npc, canton.cell, cell, false) end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return picked
|
-- didn't find anything
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
|
|
@ -5,11 +5,40 @@ local checks = require("celediel.NPCsGoHome.functions.checks")
|
||||||
local interop = require("celediel.NPCsGoHome.interop")
|
local interop = require("celediel.NPCsGoHome.interop")
|
||||||
local housing = require("celediel.NPCsGoHome.functions.housing")
|
local housing = require("celediel.NPCsGoHome.functions.housing")
|
||||||
local dataTables = require("celediel.NPCsGoHome.functions.dataTables")
|
local dataTables = require("celediel.NPCsGoHome.functions.dataTables")
|
||||||
|
local positions = require("celediel.NPCsGoHome.data.positions")
|
||||||
|
|
||||||
local function log(level, ...) if config.logLevel >= level then common.log(...) end end
|
local function log(level, ...) if config.logLevel >= level then common.log(...) end end
|
||||||
|
|
||||||
local this = {}
|
local this = {}
|
||||||
|
|
||||||
|
this.updatePositions = function(cell)
|
||||||
|
local id = cell.id
|
||||||
|
-- update runtime positions in cell, but don't overwrite loaded positions
|
||||||
|
if not common.runtimeData.positions[id] and positions.cells[id] then
|
||||||
|
common.runtimeData.positions[id] = {}
|
||||||
|
for _, data in pairs(positions.cells[id]) do
|
||||||
|
table.insert(common.runtimeData.positions[id], data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
this.searchCellsForPositions = function()
|
||||||
|
for _, cell in pairs(tes3.getActiveCells()) do
|
||||||
|
-- check active cells
|
||||||
|
this.updatePositions(cell)
|
||||||
|
for door in cell:iterateReferences(tes3.objectType.door) do
|
||||||
|
if door.destination then
|
||||||
|
-- then check cells attached to active cells
|
||||||
|
this.updatePositions(door.destination.cell)
|
||||||
|
-- one more time
|
||||||
|
for internalDoor in door.destination.cell:iterateReferences(tes3.objectType.door) do
|
||||||
|
if internalDoor.destination then this.updatePositions(internalDoor.destination.cell) end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- search in a specific cell for moved NPCs
|
-- search in a specific cell for moved NPCs
|
||||||
this.checkForMovedNPCs = function(cell)
|
this.checkForMovedNPCs = function(cell)
|
||||||
-- NPCs don't get moved to exterior cells, so no need to check them for moved NPCs
|
-- NPCs don't get moved to exterior cells, so no need to check them for moved NPCs
|
||||||
|
|
|
@ -91,6 +91,7 @@ local function updateCells()
|
||||||
log(common.logLevels.medium, "Updating active cells!")
|
log(common.logLevels.medium, "Updating active cells!")
|
||||||
|
|
||||||
followers = buildFollowerList()
|
followers = buildFollowerList()
|
||||||
|
processors.searchCellsForPositions()
|
||||||
|
|
||||||
for _, cell in pairs(tes3.getActiveCells()) do
|
for _, cell in pairs(tes3.getActiveCells()) do
|
||||||
log(common.logLevels.large, "Applying changes to cell %s", cell.id)
|
log(common.logLevels.large, "Applying changes to cell %s", cell.id)
|
||||||
|
|
|
@ -16,6 +16,7 @@ ignored class or faction will not be locked, or have its NPCS disabled.
|
||||||
* NPC "homes"
|
* NPC "homes"
|
||||||
* Outside NPCs who have homes are currently paired with the inside cell of their home
|
* Outside NPCs who have homes are currently paired with the inside cell of their home
|
||||||
* Other NPCs are configurably paired with local public houses (Inns, temples, and guildhalls of their faction)
|
* Other NPCs are configurably paired with local public houses (Inns, temples, and guildhalls of their faction)
|
||||||
|
* Moved NPCs persist on save/load
|
||||||
|
|
||||||
## WIP ##
|
## WIP ##
|
||||||
|
|
||||||
|
@ -29,3 +30,8 @@ ignored class or faction will not be locked, or have its NPCS disabled.
|
||||||
|
|
||||||
* move non-faction NPCs who don't have homes to temples or inns based on their "worth"
|
* move non-faction NPCs who don't have homes to temples or inns based on their "worth"
|
||||||
* pick temple for the poorest NPCs, or classed inns based on NPC/inn "worth"
|
* pick temple for the poorest NPCs, or classed inns based on NPC/inn "worth"
|
||||||
|
|
||||||
|
## Known issues ##
|
||||||
|
|
||||||
|
* If NPCs in a town are moved, and the player moves far away from that town before they're moved back, then
|
||||||
|
saves and reloads, those NPCs will probably stay moved.
|
Loading…
Reference in a new issue