185 lines
4.8 KiB
Plaintext
185 lines
4.8 KiB
Plaintext
|
--[[
|
||
|
Full rewrite of Rotten Meat addon by HarukaSai for EFP (visit at: https://discord.com/invite/stalker-efp)
|
||
|
|
||
|
Created: 13-11-2022
|
||
|
|
||
|
Credits for original addon: Arszi
|
||
|
|
||
|
Features:
|
||
|
- Rewritten logic
|
||
|
- Refrigiration
|
||
|
- MCM configuration
|
||
|
]]
|
||
|
|
||
|
local mcm_id = "meat_spoiling"
|
||
|
|
||
|
local expiration_time = nil
|
||
|
local expiration_table = {}
|
||
|
|
||
|
local ini_meat = ini_file_ex("plugins\\meat_spoiling_settings.ltx")
|
||
|
meats = utils_data.collect_section(ini_meat.ini, "meats", true)
|
||
|
|
||
|
local function t2c(t)
|
||
|
if not t then return nil end
|
||
|
local ct = game.CTime()
|
||
|
ct:set(t.Y,t.M,t.D,t.h,t.m,t.s,t.ms)
|
||
|
return ct
|
||
|
end
|
||
|
|
||
|
local function c2t(ct)
|
||
|
if not ct then return nil end
|
||
|
local Y, M, D, h, m, s, ms = 0, 0, 0, 0, 0, 0, 0
|
||
|
Y, M, D, h, m, s, ms = ct:get(Y, M, D, h, m, s, ms)
|
||
|
return { Y=Y, M=M, D=D, h=h, m=m, s=s, ms=ms }
|
||
|
end
|
||
|
|
||
|
local previous_time = nil
|
||
|
|
||
|
function actor_on_update()
|
||
|
local curr_time = game.get_game_time()
|
||
|
|
||
|
if (previous_time == nil) then previous_time = curr_time end
|
||
|
|
||
|
if not (curr_time:diffSec(previous_time) > 1) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
previous_time = curr_time
|
||
|
|
||
|
tick_expiration()
|
||
|
end
|
||
|
|
||
|
function actor_on_item_take(item)
|
||
|
local id = item:id()
|
||
|
local sec = item:section()
|
||
|
|
||
|
if not (meats[sec] and (not expiration_table[id])) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
expiration_table[id] = {
|
||
|
duration = string.match(sec, "meat_") and expiration_time.cooked or expiration_time.raw,
|
||
|
last_update = c2t(game.get_game_time())
|
||
|
}
|
||
|
end
|
||
|
|
||
|
function actor_on_item_use(obj)
|
||
|
if (obj and expiration_table[obj:id()]) then
|
||
|
expiration_table[obj:id()] = nil
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function get_meat_is_frozen(se_obj)
|
||
|
if (not se_obj) then return false end
|
||
|
|
||
|
local se_parent = se_obj.parent_id and se_obj.parent_id < 65535 and alife_object(se_obj.parent_id)
|
||
|
|
||
|
if (not se_parent) or (se_parent:section_name() ~= "placeable_fridge") then
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
return true
|
||
|
end
|
||
|
|
||
|
function tick_expiration()
|
||
|
local curr_time = game.get_game_time()
|
||
|
|
||
|
for id, data in pairs(expiration_table) do
|
||
|
repeat
|
||
|
local se_obj = alife_object(id)
|
||
|
|
||
|
if (not se_obj) or (not meats[se_obj:section_name()]) then
|
||
|
expiration_table[id] = nil
|
||
|
do break end
|
||
|
end
|
||
|
|
||
|
if (not get_meat_is_frozen(se_obj)) then
|
||
|
data.duration = data.duration - curr_time:diffSec(t2c(data.last_update))
|
||
|
end
|
||
|
|
||
|
data.last_update = c2t(curr_time)
|
||
|
|
||
|
if (data.duration <= 0) then
|
||
|
expire_food(se_obj)
|
||
|
expiration_table[id] = nil
|
||
|
end
|
||
|
until true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function expire_food(se_obj)
|
||
|
if (not se_obj.parent_id) or se_obj.parent_id >= 65535 then
|
||
|
alife_release(se_obj)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local se_parent = alife_object(se_obj.parent_id)
|
||
|
|
||
|
alife_release(se_obj)
|
||
|
|
||
|
if se_parent and (IsInvbox(se_parent) or se_parent.id == AC_ID) then
|
||
|
alife_create_item("rotten_meat", se_parent)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function save_state(m_data)
|
||
|
m_data.expiration_table = expiration_table
|
||
|
end
|
||
|
|
||
|
function load_state(m_data)
|
||
|
expiration_table = m_data.expiration_table or {}
|
||
|
end
|
||
|
|
||
|
function on_option_change()
|
||
|
expiration_time = {
|
||
|
raw = ui_mcm and ui_mcm.get(mcm_id .. "/expiration_hours_raw") * 60 * 60 or 48 * 60 * 60,
|
||
|
cooked = ui_mcm and ui_mcm.get(mcm_id .. "/expiration_hours_cooked") * 60 * 60 or 120 * 60 * 60
|
||
|
}
|
||
|
end
|
||
|
|
||
|
local clr_frozen = GetARGB(40,0,197,255)
|
||
|
|
||
|
function get_meat_is_frozen_cell(cell)
|
||
|
local se_obj = cell.ID and expiration_table[cell.ID] and alife_object(cell.ID)
|
||
|
|
||
|
if get_meat_is_frozen(se_obj) then
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function on_game_start()
|
||
|
RegisterScriptCallback("actor_on_item_use", actor_on_item_use)
|
||
|
RegisterScriptCallback("save_state",save_state)
|
||
|
RegisterScriptCallback("load_state",load_state)
|
||
|
RegisterScriptCallback("actor_on_item_take",actor_on_item_take)
|
||
|
RegisterScriptCallback("actor_on_update", actor_on_update)
|
||
|
RegisterScriptCallback("on_option_change", on_option_change)
|
||
|
|
||
|
rax_persistent_highlight.register("frozen_meat", function(cell)
|
||
|
return get_meat_is_frozen_cell(cell) and clr_frozen or false
|
||
|
end)
|
||
|
|
||
|
local anchor_x = function(axis, margin, w)
|
||
|
return (axis.w - w) - margin
|
||
|
end
|
||
|
|
||
|
local anchor_y = function(axis, margin, h)
|
||
|
return margin
|
||
|
end
|
||
|
|
||
|
rax_icon_layers.register("frozen_meat", function(cell, obj, sec)
|
||
|
if get_meat_is_frozen_cell(cell) then
|
||
|
local axis = utils_xml.get_item_axis(sec)
|
||
|
|
||
|
return {
|
||
|
texture = "ui_icon_freeze",
|
||
|
x = anchor_x(axis, 2, 13),
|
||
|
y = anchor_y(axis, 2, 13),
|
||
|
w = 13,
|
||
|
h = 13
|
||
|
}
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
on_option_change()
|
||
|
end
|