morrowind-npcs-go-home/MWSE/mods/celediel/NPCsGoHome/functions/housing.lua

122 lines
5.4 KiB
Lua

-- handles finding homes or picking public spaces NPCs
local common = require("celediel.NPCsGoHome.common")
local config = require("celediel.NPCsGoHome.config").getConfig()
local checks = require("celediel.NPCsGoHome.functions.checks")
local dataTables = require("celediel.NPCsGoHome.functions.dataTables")
local function log(level, ...) if config.logLevel >= level then common.log(...) end end
-- animated morrowind NPCs are contextual
local contextualNPCs = {"^AM_"}
local this = {}
-- ? 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
local splitName = common.split(npcName)
local given = splitName[1]
local sur = splitName[2]
-- surnameless peasants don't live in manors
if not sur then return end
log(common.logLevels.large, "Checking if %s %s lives in %s", given, sur, cellName)
return string.match(cellName, sur)
end
this.pickInnForNPC = function(npc, city)
-- todo: pick in Inn intelligently ?
-- high class inns for nobles and rich merchants and such
-- lower class inns for middle class npcs and merchants
-- temple for commoners and the poorest people
-- ? pick based on barterGold and value of equipment for merchants ?
-- ? 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][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
end
this.pickPublicHouseForNPC = function(npc, city)
-- look for wandering guild members
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)
return data.cell
end
end
end
-- temple members go to the temple
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
end
end
end
-- found nothing so pick an inn
return this.pickInnForNPC(npc, city)
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
if not cell.name then return end
-- 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
if door.destination then
local dest = door.destination.cell
-- 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 dataTables again
picked = common.runtimeData.homes.byName[name]
else
picked = dataTables.createHomedNPCTableEntry(npc, dest, cell, true)
end
end
end
end
-- 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)
if dest then picked = 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 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 = dataTables.createHomedNPCTableEntry(npc, canton.cell, cell, false) end
end
end
end
return picked
end
return this