Skip to content

Commit

Permalink
clear enemy status cache for makeown
Browse files Browse the repository at this point in the history
and allow fix/loyaltycascade to work on non-dwarves
  • Loading branch information
myk002 committed Oct 4, 2024
1 parent dd9592c commit 2bf2c24
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 30 deletions.
2 changes: 2 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ Template for new versions:

## Fixes
- `gui/quickfort`: only print a help blueprint's text once even if the repeat setting is enabled
- `makeown`: quell any active enemy relationships with the converted creature
- `fix/loyaltycascade`: allow the fix to work on non-dwarven citizens
- `control-panel`: fix setting numeric preferences from the commandline

## Misc Improvements
Expand Down
2 changes: 1 addition & 1 deletion docs/fix/loyaltycascade.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ fix/loyaltycascade
:summary: Halts loyalty cascades where dwarves are fighting dwarves.
:tags: fort bugfix units

This tool aborts loyalty cascades by fixing units who consider their own
This tool neutralizes loyalty cascades by fixing units who consider their own
civilization to be the enemy.

Usage
Expand Down
40 changes: 11 additions & 29 deletions fix/loyaltycascade.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
-- Prevents a "loyalty cascade" (intra-fort civil war) when a citizen is killed.

local makeown = reqscript('makeown')

-- Checks if a unit is a former member of a given entity as well as it's
-- current enemy.
local function getUnitRenegade(unit, entity_id)
Expand All @@ -14,9 +16,9 @@ local function getUnitRenegade(unit, entity_id)
goto skipentity
end

if link_type == df.histfig_entity_link_type.FORMER_MEMBER then
if link_type == df.histfig_entity_link_type.FORMER_MEMBER then
former_index = index
elseif link_type == df.histfig_entity_link_type.ENEMY then
elseif link_type == df.histfig_entity_link_type.ENEMY then
enemy_index = index
end

Expand All @@ -42,11 +44,7 @@ end
local function fixUnit(unit)
local fixed = false

if not dfhack.units.isOwnCiv(unit) or not dfhack.units.isDwarf(unit) then
return fixed
end

local unit_name = dfhack.TranslateName(dfhack.units.getVisibleName(unit))
local unit_name = dfhack.units.getReadableName(unit)
local former_civ_index, enemy_civ_index = getUnitRenegade(unit, df.global.plotinfo.civ_id)
local former_group_index, enemy_group_index = getUnitRenegade(unit, df.global.plotinfo.group_id)

Expand All @@ -57,7 +55,8 @@ local function fixUnit(unit)

convertUnit(unit, df.global.plotinfo.civ_id, former_civ_index, enemy_civ_index)

dfhack.gui.showAnnouncement(('loyaltycascade: %s is now a member of %s again'):format(unit_name, civ_name), COLOR_WHITE)
dfhack.gui.showAnnouncement(
('loyaltycascade: %s is now a happy member of %s again'):format(unit_name, civ_name), COLOR_WHITE)

fixed = true
end
Expand All @@ -67,31 +66,14 @@ local function fixUnit(unit)

convertUnit(unit, df.global.plotinfo.group_id, former_group_index, enemy_group_index)

dfhack.gui.showAnnouncement(('loyaltycascade: %s is now a member of %s again'):format(unit_name, group_name), COLOR_WHITE)
dfhack.gui.showAnnouncement(
('loyaltycascade: %s is now a happy member of %s again'):format(unit_name, group_name), COLOR_WHITE)

fixed = true
end

if fixed and unit.enemy.enemy_status_slot ~= -1 then
local status_cache = df.global.world.enemy_status_cache
local status_slot = unit.enemy.enemy_status_slot

unit.enemy.enemy_status_slot = -1
status_cache.slot_used[status_slot] = false

for index, _ in pairs(status_cache.rel_map[status_slot]) do
status_cache.rel_map[status_slot][index] = -1
end

for index, _ in pairs(status_cache.rel_map) do
status_cache.rel_map[index][status_slot] = -1
end

-- TODO: what if there were status slots taken above status_slot?
-- does everything need to be moved down by one?
if status_cache.next_slot > status_slot then
status_cache.next_slot = status_slot
end
if fixed then
makeown.clear_enemy_status(unit)
end

return false
Expand Down
26 changes: 26 additions & 0 deletions makeown.lua
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,30 @@ local function fix_clothing_ownership(unit)
unit.uniform.uniform_drop:resize(0)
end

function clear_enemy_status(unit)
if unit.enemy.enemy_status_slot <= -1 then return end

local status_cache = df.global.world.enemy_status_cache
local status_slot = unit.enemy.enemy_status_slot

unit.enemy.enemy_status_slot = -1
status_cache.slot_used[status_slot] = false

for index in ipairs(status_cache.rel_map[status_slot]) do
status_cache.rel_map[status_slot][index] = -1
end

for index in ipairs(status_cache.rel_map) do
status_cache.rel_map[index][status_slot] = -1
end

-- TODO: what if there were status slots taken above status_slot?
-- does everything need to be moved down by one to fill the gap?
if status_cache.next_slot > status_slot then
status_cache.next_slot = status_slot
end
end

local function fix_unit(unit)
unit.flags1.marauder = false;
unit.flags1.merchant = false;
Expand All @@ -82,6 +106,8 @@ local function fix_unit(unit)

if unit.profession == df.profession.MERCHANT then unit.profession = df.profession.TRADER end
if unit.profession2 == df.profession.MERCHANT then unit.profession2 = df.profession.TRADER end

clear_enemy_status(unit)
end

local function add_to_entity(hf, eid)
Expand Down

0 comments on commit 2bf2c24

Please sign in to comment.