-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfirecontrol.lua
More file actions
136 lines (114 loc) · 4.36 KB
/
firecontrol.lua
File metadata and controls
136 lines (114 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
-- firecontrol.lua
-- Prevents fire from consuming the entire map by freezing fire flows
-- (setting expanding=false) after a ~150-tick grace period.
-- New fire from incendiary hits spreads freely during the grace period,
-- then stops spreading and burns out naturally.
--
-- explode.lua and flamethrower.lua call _G.__firecontrol.register_fire(x,y,z)
-- immediately after spawning fire flows, starting the grace clock without a
-- map scan. The background scan (every CHECK_INTERVAL ticks) is a fallback
-- for volcanic fire, magma, and burning items.
local GRACE_CALLS = 3 -- calls before freezing; CHECK_INTERVAL * GRACE_CALLS ≈ 150 ticks
local CHECK_INTERVAL = 50 -- ticks between fallback map scans
local enabled = false
local call_tick = 0 -- incremented each scan; used as a lightweight clock
local fire_ages = {} -- pos_key -> call_tick when first seen on fire
---------------------------------------------------------------------------
-- HELPERS
---------------------------------------------------------------------------
local function pos_key(x, y, z)
return x .. "," .. y .. "," .. z
end
local function count_table(t)
local n = 0
for _ in pairs(t) do n = n + 1 end
return n
end
---------------------------------------------------------------------------
-- COLLABORATIVE NOTIFICATION
-- Called by explode.lua and flamethrower.lua after spawning fire flows so
-- firecontrol starts the grace clock immediately without waiting for the
-- next background scan.
---------------------------------------------------------------------------
_G.__firecontrol = _G.__firecontrol or {}
_G.__firecontrol.register_fire = function(x, y, z)
if not enabled then return end
local key = pos_key(x, y, z)
if not fire_ages[key] then
fire_ages[key] = call_tick
end
end
---------------------------------------------------------------------------
-- CORE SCAN
---------------------------------------------------------------------------
local function check_fire()
if not enabled then return end
call_tick = call_tick + 1
local seen = {}
for _, block in ipairs(df.global.world.map.map_blocks) do
for _, flow in ipairs(block.flows) do
if flow.type == df.flow_type.Fire then
local wx = block.map_pos.x + flow.pos.x
local wy = block.map_pos.y + flow.pos.y
local wz = block.map_pos.z
local key = pos_key(wx, wy, wz)
seen[key] = true
if not fire_ages[key] then
-- Newly detected fire tile: start the clock, leave it free
fire_ages[key] = call_tick
elseif (call_tick - fire_ages[key]) >= GRACE_CALLS then
-- Grace period expired: freeze this tile
flow.expanding = false
end
end
end
end
-- Drop entries for positions that are no longer on fire
for key in pairs(fire_ages) do
if not seen[key] then
fire_ages[key] = nil
end
end
dfhack.timeout(CHECK_INTERVAL, "ticks", check_fire)
end
---------------------------------------------------------------------------
-- ENABLE / DISABLE / STATUS
---------------------------------------------------------------------------
local function enable()
if enabled then
print("[firecontrol] Already enabled")
return
end
enabled = true
call_tick = 0
fire_ages = {}
dfhack.timeout(CHECK_INTERVAL, "ticks", check_fire)
print("[firecontrol] Enabled - fire tiles freeze after ~150 ticks")
end
local function disable()
if not enabled then
print("[firecontrol] Already disabled")
return
end
enabled = false
fire_ages = {}
print("[firecontrol] Disabled")
end
local function status()
print(("[firecontrol] Status: %s | Tracked fire tiles: %d"):format(
enabled and "ENABLED" or "DISABLED", count_table(fire_ages)))
end
---------------------------------------------------------------------------
-- ARGUMENT PARSING
---------------------------------------------------------------------------
local args = { ... }
local command = args[1] or "enable"
if command == "enable" then
enable()
elseif command == "disable" then
disable()
elseif command == "status" then
status()
else
print("[firecontrol] Usage: firecontrol [enable|disable|status]")
end