option to treat waistworks as public + refactoring

This commit is contained in:
Lilian Jónsdóttir 2020-08-23 22:02:33 -07:00
parent 1e4c733b0a
commit ad4a113642
9 changed files with 269 additions and 219 deletions

View file

@ -10,7 +10,12 @@ this.modInfo = "Move NPCs to their homes, or public houses (or just disable them
"and prevent interaction after hours, selectively disable NPCs in inclement weather"
this.configPath = "NPCSGOHOME"
-- for config
this.logLevels = {none = 0, small = 1, medium = 2, large = 3}
this.waist = {neither = 0, exterior = 1, public = 2}
-- for runtime data
this.publicHouseTypes = {inns = "Inns", guildhalls = "Guildhalls", temples = "Temples", houses = "Houses", cantonworks = "Cantonworks"}
-- }}}
-- {{{ Filled at runtime
@ -53,6 +58,21 @@ this.vowel = function(str)
return n
end
-- todo: pick this better
this.pickPublicHouseType = function(cell)
if cell.id:match("Guild") then
return this.publicHouseTypes.guildhalls
elseif cell.id:match("Temple") then
return this.publicHouseTypes.temples
elseif cell.id:match("[Cc]analworks") or cell.id:match("[Ww]aistworks") then
return this.publicHouseTypes.cantonworks
-- elseif cell.id:match("House") then
-- return publicHouseTypes.houses
else
return this.publicHouseTypes.inns
end
end
-- }}}
return this

View file

@ -22,7 +22,7 @@ local defaultConfig = {
disableInteraction = true,
-- door settings
lockDoors = true,
waistWorks = true,
waistWorks = common.waist.interior,
-- debug settings
logLevel = common.logLevels.none,
}

View file

@ -1,14 +1,14 @@
local common = require("celediel.NPCsGoHome.common")
local config = require("celediel.NPCsGoHome.config").getConfig()
local housing = require("celediel.NPCsGoHome.functions.housing")
local entry = require("celediel.NPCsGoHome.functions.entry")
-- {{{ local variables and such
-- Waistworks string match
local waistworks = {
"[Cc]analworks", -- These will match Vivec and Molag Mar
"[Ww]aistworks" -- and Almas Thirr from Tamriel Rebuilt
}
-- these are separate because doors to underworks should be ignored
-- Canton string matches
-- move NPCs into waistworks
local waistworks = "[Ww]aistworks"
-- don't lock canalworks
local canalworks = "[Cc]analworks"
-- doors to underworks should be ignored
-- but NPCs in underworks should not be disabled
local underworks = "[Uu]nderworks"
@ -30,7 +30,6 @@ end
local function getFightFromSpawnedReference(id)
-- Spawn a reference of the given id in toddtest
local toddTest = tes3.getCell("toddtest")
log(common.logLevels.medium, "Spawning %s in %s", id, toddTest.id)
local ref = tes3.createReference({
@ -39,7 +38,7 @@ local function getFightFromSpawnedReference(id)
cell = tes3.getPlayerCell(),
-- position = zeroVector,
position = {0, 0, 10000},
orientation = housing.zeroVector
orientation = tes3vector3.new(0, 0, 0)
})
local fight = ref.mobile.fight
@ -97,8 +96,18 @@ this.isIgnoredCell = function(cell)
return config.ignored[cell.id] or config.ignored[cell.sourceMod] -- or wilderness
end
this.isCantonCell = function(cellName)
for _, str in pairs(waistworks) do if cellName:match(str) then return true end end
this.isCantonWorksCell = function(cell)
-- for _, str in pairs(waistworks) do if cell.id:match(str) then return true end end
return cell.id:match(waistworks) or cell.id:match(canalworks) or cell.id:match(underworks)
end
this.isCantonCell = function(cell)
if this.isInteriorCell(cell) then return false end
for door in cell:iterateReferences(tes3.objectType.door) do
if door.destination and this.isCantonWorksCell(door.destination.cell) then
return true
end
end
return false
end
@ -177,7 +186,7 @@ this.isPublicHouse = function(cell)
-- only interior cells are public "houses"
if not this.isInteriorCell(cell) then return false end
local typeOfPub = housing.pickPublicHouseType(cell)
local typeOfPub = common.pickPublicHouseType(cell)
local city, publicHouseName
if cell.name and string.match(cell.name, ",") then
@ -191,6 +200,12 @@ this.isPublicHouse = function(cell)
-- don't iterate NPCs in the cell if we've already marked it public
if common.runtimeData.publicHouses[city] and (common.runtimeData.publicHouses[city][typeOfPub] and common.runtimeData.publicHouses[city][typeOfPub][cell.id]) then return true end
-- if it's a waistworks cell, it's public, with no proprietor
if config.waistWorks == common.waist.public and cell.id:match(waistworks) then
entry.createPublicHouseTableEntry(cell, nil, city, publicHouseName)
return true
end
local npcs = {factions = {}, total = 0}
for npc in cell:iterateReferences(tes3.objectType.npc) do
-- Check for NPCS of ignored classes first
@ -199,7 +214,7 @@ this.isPublicHouse = function(cell)
log(common.logLevels.medium, "NPC:\'%s\' of class:\'%s\' made %s public", npc.object.name,
npc.object.class and npc.object.class.id or "none", cell.name)
housing.createPublicHouseTableEntry(cell, npc, city, publicHouseName)
entry.createPublicHouseTableEntry(cell, npc, city, publicHouseName)
return true
end
@ -233,7 +248,7 @@ this.isPublicHouse = function(cell)
config.factionIgnorePercentage then
log(common.logLevels.medium, "%s is %s%% faction %s, marking public.", cell.name, info.percentage, faction)
housing.createPublicHouseTableEntry(cell, npcs.factions[faction].master, city, publicHouseName)
entry.createPublicHouseTableEntry(cell, npcs.factions[faction].master, city, publicHouseName)
return true
end
end
@ -268,8 +283,8 @@ this.isIgnoredDoor = function(door, homeCellId)
end
end
-- don't lock doors to underworks in addition to other canton cells
local isCanton = this.isCantonCell(dest.id) or dest.id:match(underworks)
-- don't lock doors to canton cells
local isCantonWorks = this.isCantonWorksCell(dest)
log(common.logLevels.large, "%s is %s, (%sin a city, is %spublic, %soccupied)", --
dest.id, this.isIgnoredCell(dest) and "ignored" or "not ignored", -- destination is ignored
@ -277,7 +292,7 @@ this.isIgnoredDoor = function(door, homeCellId)
return this.isIgnoredCell(dest) or
not this.isInteriorCell(dest) or
isCanton or
isCantonWorks or
not inCity or
leadsToPublicCell or
not hasOccupants

View file

@ -0,0 +1,150 @@
local common = require("celediel.NPCsGoHome.common")
local interop = require("celediel.NPCsGoHome.interop")
local positions = require("celediel.NPCsGoHome.data.positions")
local config = require("celediel.NPCsGoHome.config").getConfig()
local zeroVector = tes3vector3.new(0, 0, 0)
local function log(level, ...) if config.logLevel >= level then common.log(...) end end
local this = {}
-- {{{ npc evaluators
-- NPCs barter gold + value of all inventory items
this.calculateNPCWorth = function(npc, merchantCell)
local worth = npc.object.barterGold
local obj = npc.baseObject and npc.baseObject or npc.object
if npc.object.inventory then
for _, item in pairs(npc.object.inventory) do worth = worth + (item.object.value or 0) end
end
if merchantCell then -- if we pass a cell argument
for box in merchantCell:iterateReferences(tes3.objectType.container) do -- loop over each container
if box.inventory then -- if it's not empty
for item in tes3.iterate(box.inventory) do -- loop over its items
if obj:tradesItemType(item.objectType) then -- if the NPC sells that type
worth = worth + item.object.value -- add its value to the NPCs total value
end
end
end
end
end
return worth
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)
if npc.object and (npc.object.name == nil or npc.object.name == "") then return end
local pickedPosition, pickedOrientation, pos, ori
-- mod support for different positions in cells
local id = this.checkModdedCell(home.id)
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)
if isHome and positions.npcs[npc.object.name] then
pos = positions.npcs[npc.object.name].position
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()
-- pickedOrientation = positions.npcs[npc.object.name] and tes3vector3.new(o[1], o[2], o[3]) or zeroVector:copy()
elseif positions.cells[id] then
pos = table.choice(positions.cells[id]).position
ori = table.choice(positions.cells[id]).orientation
-- pickedPosition = positions.cells[id] and tes3vector3.new(p[1], p[2], p[3]) or zeroVector:copy()
-- pickedOrientation = positions.cells[id] and tes3vector3.new(o[1], o[2], o[3]) or zeroVector:copy()
-- pickedPosition = tes3vector3.new(p[1], p[2], p[3])
-- pickedOrientation = tes3vector3.new(o[1], o[2], o[3])
else
pos = {0,0,0}
ori = {0,0,0}
-- pickedPosition = zeroVector:copy()
-- pickedOrientation = zeroVector:copy()
end
pickedPosition = tes3vector3.new(pos[1], pos[2], pos[3])
pickedOrientation = tes3vector3.new(ori[1], ori[2], ori[3])
local ogPosition = position and
(tes3vector3.new(position.x, position.y, position.z)) or
(npc.position and npc.position:copy() or zeroVector:copy())
local ogOrientation = orientation and
(tes3vector3.new(orientation.x, orientation.y, orientation.z)) or
(npc.orientation and npc.orientation:copy() or zeroVector:copy())
local entry = {
name = npc.object.name, -- string
npc = npc, -- tes3npc
isHome = isHome, -- bool
home = home, -- tes3cell
homeName = home.id, -- string
ogPlace = startingPlace, -- tes3cell
ogPlaceName = startingPlace.id,
ogPosition = ogPosition, -- tes3vector3
ogOrientation = ogOrientation, -- tes3vector3
homePosition = pickedPosition, -- tes3vector3
homeOrientation = pickedOrientation, -- tes3vector3
worth = this.calculateNPCWorth(npc) -- int
}
common.runtimeData.homes.byName[npc.object.name] = entry
if isHome then common.runtimeData.homes.byCell[home.id] = entry end
interop.setRuntimeData(common.runtimeData)
return entry
end
this.createPublicHouseTableEntry = function(publicCell, proprietor, city, name)
local typeOfPub = common.pickPublicHouseType(publicCell)
local worth = 0
-- cell worth is combined worth of all NPCs
for innard in publicCell:iterateReferences(tes3.objectType.npc) do
if innard == proprietor then
worth = worth + this.calculateNPCWorth(innard, publicCell)
else
worth = worth + this.calculateNPCWorth(innard)
end
end
local proprietorName = proprietor and proprietor.object.name or "no one"
if not common.runtimeData.publicHouses[city] then common.runtimeData.publicHouses[city] = {} end
if not common.runtimeData.publicHouses[city][typeOfPub] then common.runtimeData.publicHouses[city][typeOfPub] = {} end
common.runtimeData.publicHouses[city][typeOfPub][publicCell.id] = {
name = name,
city = city,
cell = publicCell,
proprietor = proprietor,
proprietorName = proprietorName,
worth = worth
}
interop.setRuntimeData(common.runtimeData)
end
return this

View file

@ -1,75 +1,15 @@
local common = require("celediel.NPCsGoHome.common")
local config = require("celediel.NPCsGoHome.config").getConfig()
local interop = require("celediel.NPCsGoHome.interop")
local positions = require("celediel.NPCsGoHome.data.positions")
local checks = require("celediel.NPCsGoHome.functions.checks")
local entry = require("celediel.NPCsGoHome.functions.entry")
local function log(level, ...) if config.logLevel >= level then common.log(...) end end
local publicHouseTypes = {inns = "Inns", guildhalls = "Guildhalls", temples = "Temples", houses = "Houses"}
-- animated morrowind NPCs are contextual
local contextualNPCs = {"^AM_"}
local this = {}
this.zeroVector = tes3vector3.new(0, 0, 0)
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
-- {{{ npc evaluators
-- NPCs barter gold + value of all inventory items
this.calculateNPCWorth = function(npc, merchantCell)
local worth = npc.object.barterGold
local obj = npc.baseObject and npc.baseObject or npc.object
if npc.object.inventory then
for _, item in pairs(npc.object.inventory) do worth = worth + (item.object.value or 0) end
end
if merchantCell then -- if we pass a cell argument
for box in merchantCell:iterateReferences(tes3.objectType.container) do -- loop over each container
if box.inventory then -- if it's not empty
for item in tes3.iterate(box.inventory) do -- loop over its items
if obj:tradesItemType(item.objectType) then -- if the NPC sells that type
worth = worth + item.object.value -- add its value to the NPCs total value
end
end
end
end
end
return worth
end
-- }}}
-- todo: pick this better
this.pickPublicHouseType = function(cell)
if cell.id:match("Guild") then
return publicHouseTypes.guildhalls
elseif cell.id:match("Temple") then
return publicHouseTypes.temples
-- elseif cell.id:match("House") then
-- return publicHouseTypes.houses
else
return publicHouseTypes.inns
end
end
-- ? I honestly don't know if there are any wandering NPCs that "live" in close-by manors, but I wrote this anyway
this.livesInManor = function(cellName, npcName)
if not cellName or (cellName and not string.find(cellName, "Manor")) then return end
@ -94,9 +34,9 @@ this.pickInnForNPC = function(npc, city)
-- ? for others, pick based on value of equipment
-- but for now pick one at random
if common.runtimeData.publicHouses[city] and common.runtimeData.publicHouses[city][publicHouseTypes.inns] then
local choice = table.choice(common.runtimeData.publicHouses[city][publicHouseTypes.inns])
if not choice then return end
if common.runtimeData.publicHouses[city] and common.runtimeData.publicHouses[city][common.publicHouseTypes.inns] then
local choice = table.choice(common.runtimeData.publicHouses[city][common.publicHouseTypes.inns])
if not choice then return nil end
log(common.logLevels.medium, "Picking inn %s, %s for %s", choice.city, choice.name, npc.object.name)
return choice.cell
end
@ -104,8 +44,8 @@ end
this.pickPublicHouseForNPC = function(npc, city)
-- look for wandering guild members
if common.runtimeData.publicHouses[city] and common.runtimeData.publicHouses[city][publicHouseTypes.guildhalls] then
for _, data in pairs(common.runtimeData.publicHouses[city][publicHouseTypes.guildhalls]) do
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
-- if npc's faction and proprietor's faction match, pick that one
if npc.object.faction == data.proprietor.object.faction then
log(common.logLevels.medium, "Picking %s for %s based on faction", data.cell.id, npc.object.name)
@ -115,8 +55,8 @@ this.pickPublicHouseForNPC = function(npc, city)
end
-- temple members go to the temple
if common.runtimeData.publicHouses[city] and common.runtimeData.publicHouses[city][publicHouseTypes.temples] then
for _, data in pairs(common.runtimeData.publicHouses[city][publicHouseTypes.temples]) do
if common.runtimeData.publicHouses[city] and common.runtimeData.publicHouses[city][common.publicHouseTypes.temples] then
for _, data in pairs(common.runtimeData.publicHouses[city][common.publicHouseTypes.temples]) do
if npc.object.faction == data.proprietor.object.faction then
log(common.logLevels.medium, "Picking temple %s for %s based on faction", data.cell.id, npc.object.name)
return data.cell
@ -128,104 +68,6 @@ this.pickPublicHouseForNPC = function(npc, city)
return this.pickInnForNPC(npc, city)
end
this.createHomedNPCTableEntry = function(npc, home, startingPlace, isHome, position, orientation)
if npc.object and (npc.object.name == nil or npc.object.name == "") then return end
local pickedPosition, pickedOrientation, pos, ori
-- mod support for different positions in cells
local id = this.checkModdedCell(home.id)
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)
if isHome and positions.npcs[npc.object.name] then
pos = positions.npcs[npc.object.name].position
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()
-- pickedOrientation = positions.npcs[npc.object.name] and tes3vector3.new(o[1], o[2], o[3]) or zeroVector:copy()
elseif positions.cells[id] then
pos = table.choice(positions.cells[id]).position
ori = table.choice(positions.cells[id]).orientation
-- pickedPosition = positions.cells[id] and tes3vector3.new(p[1], p[2], p[3]) or zeroVector:copy()
-- pickedOrientation = positions.cells[id] and tes3vector3.new(o[1], o[2], o[3]) or zeroVector:copy()
-- pickedPosition = tes3vector3.new(p[1], p[2], p[3])
-- pickedOrientation = tes3vector3.new(o[1], o[2], o[3])
else
pos = {0,0,0}
ori = {0,0,0}
-- pickedPosition = zeroVector:copy()
-- pickedOrientation = zeroVector:copy()
end
pickedPosition = tes3vector3.new(pos[1], pos[2], pos[3])
pickedOrientation = tes3vector3.new(ori[1], ori[2], ori[3])
local ogPosition = position and
(tes3vector3.new(position.x, position.y, position.z)) or
(npc.position and npc.position:copy() or zeroVector:copy())
local ogOrientation = orientation and
(tes3vector3.new(orientation.x, orientation.y, orientation.z)) or
(npc.orientation and npc.orientation:copy() or zeroVector:copy())
local this = {
name = npc.object.name, -- string
npc = npc, -- tes3npc
isHome = isHome, -- bool
home = home, -- tes3cell
homeName = home.id, -- string
ogPlace = startingPlace, -- tes3cell
ogPlaceName = startingPlace.id,
ogPosition = ogPosition, -- tes3vector3
ogOrientation = ogOrientation, -- tes3vector3
homePosition = pickedPosition, -- tes3vector3
homeOrientation = pickedOrientation, -- tes3vector3
worth = this.calculateNPCWorth(npc) -- int
}
common.runtimeData.homes.byName[npc.object.name] = this
if isHome then common.runtimeData.homes.byCell[home.id] = this end
interop.setHomedNPCTable(common.runtimeData.homes.byName)
return this
end
this.createPublicHouseTableEntry = function(publicCell, proprietor, city, name)
local typeOfPub = this.pickPublicHouseType(publicCell)
local worth = 0
-- for houses, worth is equal to NPC who lives there
-- if typeOfPub == publicHouseTypes.houses then
-- worth = calculateNPCWorth(proprietor)
-- else
-- for other types, worth is combined worth of all NPCs
for innard in publicCell:iterateReferences(tes3.objectType.npc) do
if innard == proprietor then
worth = worth + this.calculateNPCWorth(innard, publicCell)
else
worth = worth + this.calculateNPCWorth(innard)
end
end
-- end
if not common.runtimeData.publicHouses[city] then common.runtimeData.publicHouses[city] = {} end
if not common.runtimeData.publicHouses[city][typeOfPub] then common.runtimeData.publicHouses[city][typeOfPub] = {} end
common.runtimeData.publicHouses[city][typeOfPub][publicCell.id] = {
name = name,
city = city,
cell = publicCell,
proprietor = proprietor,
proprietorName = proprietor.object.name,
worth = worth
}
interop.setPublicHouseTable(common.runtimeData.publicHouses)
end
-- looks through doors to find a cell that matches a wandering NPCs name
this.pickHomeForNPC = function(cell, npc)
-- wilderness cells don't have name
@ -234,6 +76,9 @@ this.pickHomeForNPC = function(cell, npc)
-- don't move contextual, such as Animated Morrowind, NPCs at all
for _, str in pairs(contextualNPCs) do if npc.object.id:match(str) then return end end
-- time to pick the "home"
local picked = nil
local name = npc.object.name
local city = common.split(cell.name, ",")[1]
for door in cell:iterateReferences(tes3.objectType.door) do
@ -243,23 +88,34 @@ this.pickHomeForNPC = function(cell, npc)
-- essentially, if npc full name, or surname matches the cell name
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 entry again
return common.runtimeData.homes.byName[name]
picked = common.runtimeData.homes.byName[name]
else
return this.createHomedNPCTableEntry(npc, dest, cell, true)
picked = entry.createHomedNPCTableEntry(npc, dest, cell, true)
end
end
end
end
-- haven't found a home, so put them in an inn or guildhall
-- haven't found a home, so put them in an inn or guildhall, or inside a canton
if config.homelessWanderersToPublicHouses then
log(common.logLevels.medium, "Didn't find a home for %s, trying inns", npc.object.name)
local dest = this.pickPublicHouseForNPC(npc, city)
-- return createHomedNPCTableEntry(npc, dest, door)
if dest then return this.createHomedNPCTableEntry(npc, dest, cell, false) end
if dest then picked = entry.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 checks.isCantonCell(cell) then
if common.runtimeData.publicHouses[city] and common.runtimeData.publicHouses[city][common.publicHouseTypes.cantonworks] then
-- todo: maybe poorer NPCs in canalworks, others in waistworks ?
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)
if canton then picked = entry.createHomedNPCTableEntry(npc, canton.cell, cell, false) end
end
end
end
return nil
return picked
end
return this

View file

@ -3,6 +3,7 @@ local config = require("celediel.NPCsGoHome.config").getConfig()
local checks = require("celediel.NPCsGoHome.functions.checks")
local interop = require("celediel.NPCsGoHome.interop")
local housing = require("celediel.NPCsGoHome.functions.housing")
local entry = require("celediel.NPCsGoHome.functions.entry")
local function log(level, ...) if config.logLevel >= level then common.log(...) end end
@ -16,7 +17,7 @@ this.checkForMovedNPCs = function(cell)
log(common.logLevels.medium, "Looking for moved NPCs in cell %s", cell.id)
for npc in cell:iterateReferences(tes3.objectType.npc) do
if npc.data and npc.data.NPCsGoHome then
housing.createHomedNPCTableEntry(npc, cell, tes3.getCell(npc.data.NPCsGoHome.cell), true, npc.data.NPCsGoHome.position, npc.data.NPCsGoHome.orientation)
entry.createHomedNPCTableEntry(npc, cell, tes3.getCell(npc.data.NPCsGoHome.cell), true, npc.data.NPCsGoHome.position, npc.data.NPCsGoHome.orientation)
end
end
end
@ -37,7 +38,7 @@ end
this.moveNPC = function(homeData)
-- add to in memory table
table.insert(common.runtimeData.movedNPCs, homeData)
interop.setMovedNPCTable(common.runtimeData.movedNPCs)
interop.setRuntimeData(common.runtimeData)
-- set npc data, so we can move NPCs back after a load
local npc = homeData.npc
@ -83,7 +84,7 @@ this.putNPCsBack = function()
orientation = data.ogPlace
})
end
interop.setMovedNPCTable(common.runtimeData.movedNPCs)
interop.setRuntimeData(common.runtimeData)
end
this.processNPCs = function(cell)

View file

@ -1,18 +1,8 @@
local this = {}
-- access to the NPCs that have homes or have been assigned a public house
local homedNPCs = {}
this.setHomedNPCTable = function(t) homedNPCs = t end
this.getHomedNPCTable = function() return homedNPCs end
-- access to any cells that have been marked public
local pubs = {}
this.setPublicHouseTable = function(t) pubs = t end
this.getPublicHouseTable = function() return pubs end
-- access to NPCs that have been moved
local moved = {}
this.setMovedNPCTable = function(t) moved = t end
this.getMovedNPCTable = function() return moved end
-- access to runtime data
local runtimeData = {}
this.setRuntimeData = function(t) runtimeData = t end
this.getRuntimeData = function() return runtimeData end
return this

View file

@ -46,14 +46,18 @@ local function checkEnteredNPCHome(cell)
end
local function checkEnteredPublicHouse(cell, city)
local typeOfPub = housing.pickPublicHouseType(cell)
local typeOfPub = common.pickPublicHouseType(cell)
local publicHouse = publicHouses[city] and (publicHouses[city][typeOfPub] and publicHouses[city][typeOfPub][cell.name])
if publicHouse then
local msg = string.format("Entering public space %s, a%s %s in the town of %s. Talk to %s, %s for services.",
publicHouse.name, common.vowel(typeOfPub), typeOfPub:gsub("s$", ""), publicHouse.city,
publicHouse.proprietor.object.name, publicHouse.proprietor.object.class)
local msg = string.format("Entering public space %s, a%s %s in the town of %s.",
publicHouse.name, common.vowel(typeOfPub), typeOfPub:gsub("s$", ""), publicHouse.city)
if publicHouse.proprietor then
msg = msg .. string.format(" Talk to %s, %s for services.", publicHouse.proprietor.object.name, publicHouse.proprietor.object.class)
end
log(common.logLevels.small, msg)
message(msg) -- this one is more informative, and not entirely for debugging, and reminiscent of Daggerfall's messages
end
@ -67,7 +71,9 @@ local function applyChanges(cell)
if checks.isIgnoredCell(cell) then return end
-- Interior cell, except Canton cells, don't do anything
if checks.isInteriorCell(cell) and not (config.waistWorks and checks.isCantonCell(cell.id)) then return end
if checks.isInteriorCell(cell) and not (config.waistWorks == common.waist.exterior and checks.isCantonWorksCell(cell)) then
return
end
-- don't do anything to public houses
if checks.isPublicHouse(cell) then return end
@ -161,15 +167,18 @@ local function onInitialized()
followers = common.runtimeData.followers
-- Register events
log(common.logLevels.small, "Registering events...")
event.register("loaded", onLoaded)
event.register("cellChanged", onCellChanged)
event.register("activate", onActivated)
-- MCM
event.register("modConfigReady", function() mwse.mcm.register(require("celediel.NPCsGoHome.mcm")) end)
log(common.logLevels.none, "Successfully initialized")
end
event.register("initialized", onInitialized)
-- MCM
event.register("modConfigReady", function() mwse.mcm.register(require("celediel.NPCsGoHome.mcm")) end)
-- }}}
-- vim:fdm=marker

View file

@ -39,12 +39,12 @@ category:createYesNoButton({
})
category:createYesNoButton({
label = "Move NPCs with homes instead of disabling them?",
label = "Move NPCs into their homes at night and in bad weather instead of disabling them?",
variable = createTableVar("moveNPCs")
})
category:createYesNoButton({
label = "Move \"homeless\" NPCs to Inns at night and in bad weather instead of disabling them?",
label = "Move \"homeless\" NPCs to public spaces at night and in bad weather instead of disabling them?",
variable = createTableVar("homelessWanderersToPublicHouses")
})
@ -53,8 +53,17 @@ category:createYesNoButton({
variable = createTableVar("disableInteraction")
})
category:createYesNoButton({
label = "Treat Canton waistworks and canalworks as exteriors (lock doors and disable NPCs)",
category:createDropdown({
label = "Treat Canton waistworks and canalworks as exteriors, public spaces, or neither",
description = "If canton cells are treated as exterior, inside NPCs will be disabled, and doors will be locked.\n" ..
"If they're treated as public spaces, inside NPCs won't be disabled, and homeless NPCs will be moved inside "..
"(if configured to do so).\n\nIf neither, canton cells will be treated as any other.",
options = {
{label = "Neither", value = common.waist.neither},
{label = "Exterior", value = common.waist.exterior},
{label = "Public", value = common.waist.public},
},
defaultSetting = common.waist.neither,
variable = createTableVar("waistWorks")
})