gc = game.translate_string ---@param id number ---@return bind_hf_base.hf_binder_wrapper|nil function get_wrapper(id) local obj = get_object_by_id(id) if not obj then return end local binder = obj:binded_object() if not binder then return end return binder.wrapper end function freeze_obj(id) local obj = level.object_by_id(id) if not obj then return end local phys = obj:get_physics_shell() if not phys then return end phys:freeze() local wrapper = get_wrapper(id) if wrapper then wrapper.is_frozen = true end return true end function init(obj) obj:bind_object(hf_binder_wrapper(obj).binder) end ---@param obj game_object ---@param field string ---@return function function get_function_from_field(obj, field) local func_string = ini_sys:r_string_ex(obj:section(), field) if not func_string then return end local func_split = {} for s in string.gmatch(func_string, "([^.]+)") do table.insert(func_split, s) end return _G[func_split[1]][func_split[2]] end -------------------------------------------------------------------------------- -- Class "hf_binder_wrapper" -------------------------------------------------------------------------------- class "hf_binder_wrapper" -- Class constructor function hf_binder_wrapper:__init(obj) local binder = base_binder(obj) binder.wrapper = self obj:bind_object(binder) self.binder = binder ---@type game_object self.object = obj -- *hopefully* source of truth of frozenness since objects are not frozen by default self.is_frozen = false end function hf_binder_wrapper:update(delta) end function hf_binder_wrapper:net_spawn() CreateTimeEvent("hf_freeze", self.object:id(), 0, freeze_obj, self.object:id()) end function hf_binder_wrapper:net_destroy() -- Remove time event just in case object is released before freezing RemoveTimeEvent("hf_freeze", self.object:id()) -- Clean up references self.binder.wrapper = nil self.binder = nil self.object = nil end function hf_binder_wrapper:use_callback() local callback = get_function_from_field(self.object, "ui_on_interaction") if callback then callback(self.object:id()) end end function hf_binder_wrapper:use_callback_simple() local callback = get_function_from_field(self.object, "ui_on_simple_interaction") if callback then callback(self.object:id()) end end function hf_binder_wrapper:is_pickupable() local data = hf_obj_manager.get_data(self.object:id()) if data.is_world_obj then return false end return true end function hf_binder_wrapper:pickup() local item_section = ini_sys:r_string_ex(self.object:section(), "item_section") local condition = self.fuel alife_create_item(item_section, db.actor, {cond=condition}) alife_release(self.object) return true end ---@param bool boolean function hf_binder_wrapper:set_frozen(bool) local data = hf_obj_manager.get_data(self.object:id()) if data.is_world_obj then return end local phys = self.object:get_physics_shell() if not phys then return end -- idk how an object wouldn't have a physics shell if bool then phys:freeze() else phys:unfreeze() end self.is_frozen = bool end -------------------------------------------------------------------------------- -- Class "base_binder" -------------------------------------------------------------------------------- class "base_binder" (object_binder) -- Class constructor function base_binder:__init(obj) super(obj) self.object:set_tip_text(gc("st_interact")) ---@type bind_hf_base.hf_binder_wrapper self.wrapper = nil end -- Class update function base_binder:update(delta) object_binder.update(self, delta) -- self.object:set_callback(callback.use_object, self.use_callback, self) if self.wrapper and self.wrapper.update then self.wrapper:update(delta) end end -- Reload object function base_binder:reload(section) object_binder.reload(self, section) if self.wrapper and self.wrapper.reload then self.wrapper:reload(section) end end -- Reinitialize object function base_binder:reinit() object_binder.reinit(self) if self.wrapper and self.wrapper.reinit then self.wrapper:reinit() end end -- Net spawn function base_binder:net_spawn(se_abstract) if not(object_binder.net_spawn(self, se_abstract)) then return false end if self.wrapper and self.wrapper.net_spawn then self.wrapper:net_spawn() end return true end -- Net destroy function base_binder:net_destroy() self:save_data() object_binder.net_destroy(self) if self.wrapper and self.wrapper.net_destroy then self.wrapper:net_destroy() end end -- Standart function for save function base_binder:net_save_relevant() return true end -- Saving container function base_binder:save(stpk) object_binder.save(self, stpk) if self.wrapper and self.wrapper.save then self.wrapper:save(stpk) end end -- Loading container function base_binder:load(stpk) object_binder.load(self, stpk) end -- Save to mdata by calling hf_obj_manager.update_data function base_binder:save_data() if self.wrapper and self.wrapper.save_data then self.wrapper:save_data() end end