383 lines
No EOL
12 KiB
Text
383 lines
No EOL
12 KiB
Text
----------------------------------------------------------------------------------------------------
|
|
-- Physic door control
|
|
----------------------------------------------------------------------------------------------------
|
|
-- Èñõîäíûé ñêðèïò: Evgeniy Negrobov (Jon) jon@gsc-game.kiev.ua
|
|
-- Ïåðåâîä íà xr_logic: Andrey Fidrya (Zmey) af@svitonline.com
|
|
-- Äîðàáîòêà: Oleg Kreptul (Haron) haronk@ukr.net
|
|
----------------------------------------------------------------------------------------------------
|
|
|
|
|
|
class "action_door"
|
|
function action_door:__init(obj, storage)
|
|
--printf ("action_door::action_door() called")
|
|
self.object = obj
|
|
self.st = storage
|
|
self.snd_obj = nil
|
|
|
|
storage.door_action = self
|
|
end
|
|
function action_door:reset_scheme(loading)
|
|
--printf("_bp: action_door:reset_scheme: self.object:name()='%s'", self.object:name())
|
|
|
|
self.st.signals = {}
|
|
|
|
self.initialized = false
|
|
|
|
local ph_shell = self.object:get_physics_shell()
|
|
if not ph_shell then
|
|
return
|
|
end
|
|
self.joint = ph_shell:get_joint_by_bone_name("door")
|
|
|
|
self.low_limits, self.hi_limits = 0, 0
|
|
self.low_limits, self.hi_limits = self.joint:get_limits(self.low_limits, self.hi_limits, 0)
|
|
|
|
self.block = false
|
|
self.soundless_block = false
|
|
|
|
self.show_tips = self.st.show_tips
|
|
|
|
local disable_snd
|
|
-- Çâóê íóæíî îòêëþ÷èòü, òîëüêî åñëè ñêðèïò äâåðè äëÿ ýòîãî îáúåêòà èñïîëüçóåòñÿ
|
|
-- âïåðâûå (ò.å. ïîñëå çàãðóçêè óðîâíÿ èëè ïîñëå çàãðóçêè ñîõðàíåííîé èãðû),
|
|
-- èíà÷å èãðîê óñëûøèò õëîïîê...
|
|
if not self.st.script_used_more_than_once then
|
|
disable_snd = true
|
|
self.st.script_used_more_than_once = true
|
|
end
|
|
|
|
if self.st.closed then
|
|
--' Åñëè äâåðü óæå çàêðûòà - òî íóæíî çàêðûòü áåç çâóêà
|
|
if self:is_closed() then
|
|
disable_snd = true
|
|
end
|
|
self:close_door(disable_snd)
|
|
else
|
|
self:open_door(disable_snd)
|
|
end
|
|
|
|
self.object:set_nonscript_usable(false)
|
|
|
|
self.initialized = true
|
|
end
|
|
|
|
function action_door:update(delta)
|
|
--printf("_bp: action_door:update()", delta)
|
|
if not self.initialized then
|
|
abort("object '%s': door failed to initialize", self.object:name())
|
|
end
|
|
|
|
if xr_logic.try_switch_to_another_section(self.object, self.st, db.actor) then
|
|
return
|
|
end
|
|
end
|
|
|
|
function action_door:fastcall()
|
|
if not self.initialized then
|
|
return false
|
|
end
|
|
|
|
if self.block and self:is_closed() then
|
|
self:close_action()
|
|
self.object:on_door_is_closed()
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function action_door:open_fastcall()
|
|
if not self.initialized then
|
|
return false
|
|
end
|
|
|
|
if self:is_open() then
|
|
local ph_obj = self.object:get_physics_object()
|
|
ph_obj:unset_door_ignore_dynamics() --'Èãíîðèðîâàíèå äèíàìèêè íà ìîìåíò îòêðûòèÿ/çàêðûòèÿ
|
|
self.object:on_door_is_open()
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
function action_door:close_action()
|
|
--printf("_bp: close_action(): %d", time_global())
|
|
|
|
-- Çàêðûëè äî ïðåäåëà, áóäåì áëîêèðîâàòü
|
|
if self.st.no_force == true then
|
|
self.joint:set_max_force_and_velocity(0, 0, 0)
|
|
else
|
|
self.joint:set_max_force_and_velocity(10000, 1, 0)
|
|
|
|
--!!! Ôèêñèðóåì êîñòü.
|
|
local ph_shell = self.object:get_physics_shell()
|
|
if ph_shell then
|
|
local ph_element = ph_shell:get_element_by_bone_name("door")
|
|
if not ph_element:is_fixed() then
|
|
--printf("FIX")
|
|
ph_element:fix()
|
|
end
|
|
end
|
|
end
|
|
|
|
local ph_obj = self.object:get_physics_object()
|
|
ph_obj:unset_door_ignore_dynamics() --'Èãíîðèðîâàíèå äèíàìèêè íà ìîìåíò îòêðûòèÿ/çàêðûòèÿ
|
|
self.block = false
|
|
-- Îòûãðàòü çâóê êîãäà äâåðü çàõëîïíóëàñü:
|
|
if not self.soundless_block and self.st.snd_close_stop then
|
|
xr_sound.set_sound_play(self.object:id(), self.st.snd_close_stop)
|
|
end
|
|
end
|
|
|
|
function action_door:open_door(disable_snd)
|
|
--printf("_bp: [%s] action_door:open_door()", self.object:name())
|
|
if not disable_snd then
|
|
if self.st.snd_open_start then
|
|
xr_sound.set_sound_play(self.object:id(), self.st.snd_open_start)
|
|
end
|
|
end
|
|
|
|
self.object:set_fastcall(self.open_fastcall,self)
|
|
|
|
--!!! Òóò íàäî ñíÿòü ôèêñàöèþ êîñòè
|
|
local ph_shell = self.object:get_physics_shell()
|
|
if ph_shell then
|
|
local ph_element = ph_shell:get_element_by_bone_name("door")
|
|
if ph_element:is_fixed() then
|
|
--printf("RELEASE")
|
|
ph_element:release_fixed()
|
|
|
|
local ph_obj = self.object:get_physics_object()
|
|
ph_obj:set_door_ignore_dynamics() --'Èãíîðèðîâàíèå äèíàìèêè íà ìîìåíò îòêðûòèÿ/çàêðûòèÿ
|
|
end
|
|
end
|
|
|
|
|
|
if self.st.no_force == true then
|
|
self.joint:set_max_force_and_velocity(0, 0, 0)
|
|
else
|
|
self.joint:set_max_force_and_velocity(2100, -3, 0)
|
|
end
|
|
self.block = false
|
|
|
|
if self.show_tips and self.st.tip_close then
|
|
self.object:set_tip_text(self.st.tip_close)
|
|
end
|
|
end
|
|
|
|
function action_door:is_closed()
|
|
local angle
|
|
if self.st.slider then
|
|
angle = -self.joint:get_axis_angle(0)
|
|
else
|
|
angle = self.joint:get_axis_angle(90)
|
|
end
|
|
--printf("_bp[%s]: action_door:update(): angle %f limits %f, %f",
|
|
-- self.object:name(), angle, self.low_limits, self.hi_limits)
|
|
|
|
if angle <= self.low_limits + 0.02 then
|
|
--printf("_bp: close_check(): true")
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function action_door:is_open()
|
|
local angle
|
|
if self.st.slider then
|
|
angle = -self.joint:get_axis_angle(0)
|
|
else
|
|
angle = self.joint:get_axis_angle(90)
|
|
end
|
|
|
|
--printf("_bp[%s]: action_door:update(): angle %f limits %f, %f",
|
|
-- self.object:name(), angle, self.low_limits, self.hi_limits)
|
|
|
|
if angle >= self.hi_limits - 0.02 then
|
|
--printf("_bp: open_check(): true")
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
function action_door:close_door(disable_snd)
|
|
--printf("_bp: [%s] action_door:close_door()", self.object:name())
|
|
-- local disable_snd = self:is_closed()
|
|
if not disable_snd then
|
|
if self.st.snd_close_start then
|
|
xr_sound.set_sound_play(self.object:id(), self.st.snd_close_start)
|
|
end
|
|
end
|
|
|
|
-- Ñòàâèì êîëëáåê äëÿ îòëîâà îêîí÷àíèÿ çàêðûòèÿ äâåðè (÷òîáû çàáëîêèðîâàòü åå è ïðîèãðàòü çâóê, åñëè íóæíî):
|
|
self.object:set_fastcall(self.fastcall,self)
|
|
|
|
--printf("_bp: action_door:close_door()")
|
|
if self.st.no_force == true then
|
|
self.joint:set_max_force_and_velocity(0, 0, 0)
|
|
else
|
|
self.joint:set_max_force_and_velocity(200, 3, 0)
|
|
end
|
|
self.block = true -- Çàêðûâàåì è áëîêèðóåì
|
|
self.soundless_block = disable_snd
|
|
|
|
local ph_obj = self.object:get_physics_object()
|
|
ph_obj:set_door_ignore_dynamics() --'Èãíîðèðîâàíèå äèíàìèêè íà ìîìåíò îòêðûòèÿ/çàêðûòèÿ
|
|
|
|
if self.show_tips then
|
|
if self.st.locked == true and self.st.tip_unlock then
|
|
self.object:set_tip_text(self.st.tip_unlock)
|
|
return
|
|
end
|
|
|
|
if self.st.tip_open then
|
|
self.object:set_tip_text(self.st.tip_open)
|
|
end
|
|
end
|
|
end
|
|
|
|
function action_door:try_switch()
|
|
--printf("_bp: action_door: object '%s': try_switch", self.object:name())
|
|
if self.st.on_use then
|
|
if xr_logic.switch_to_section(self.object, self.st.ini,
|
|
xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.on_use.condlist)) then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function action_door:use_callback(door, actor)
|
|
if self.st.locked then
|
|
if self.st.snd_open_start then
|
|
xr_sound.set_sound_play(self.object:id(), self.st.snd_open_start)
|
|
end
|
|
end
|
|
|
|
if self:try_switch() then
|
|
return
|
|
end
|
|
|
|
-- local angle = self.joint:get_axis_angle(90)
|
|
|
|
-- if angle - self.low_limits > self.hi_limits - angle then
|
|
-- self:open_door(false)
|
|
-- else
|
|
-- self:close_door(false)
|
|
-- end
|
|
end
|
|
function action_door:hit_callback(obj, amount, local_direction, who, bone_index)
|
|
local who_name
|
|
if who then
|
|
who_name = who:name()
|
|
else
|
|
who_name = "nil"
|
|
end
|
|
|
|
--printf("DOOR: hit_callback: obj='%s', amount=%d, who='%s', bone='%s'", obj:name(), amount, who_name, bone_index)
|
|
print_table(self.st.hit_on_bone)
|
|
if self.st.hit_on_bone[bone_index] ~= nil then
|
|
local section = xr_logic.pick_section_from_condlist(db.actor, self.object, self.st.hit_on_bone[bone_index].state)
|
|
xr_logic.switch_to_section(obj, self.st.ini, section)
|
|
return
|
|
end
|
|
end
|
|
function action_door:deactivate()
|
|
self.object:set_tip_text("")
|
|
end
|
|
|
|
---------------------------------------------------------------------------------------------------------------------
|
|
function add_to_binder(npc, ini, scheme, section, storage)
|
|
--printf("DEBUG: add_to_binder: scheme='%s', section='%s'", scheme, section)
|
|
|
|
npc:register_door_for_npc ( )
|
|
|
|
local new_action = action_door(npc, storage)
|
|
|
|
-- Çàðåãèñòðèðîâàòü âñå actions, â êîòîðûõ äîëæåí áûòü âûçâàí ìåòîä reset_scheme ïðè èçìåíåíèè íàñòðîåê ñõåìû:
|
|
xr_logic.subscribe_action_for_events(npc, storage, new_action)
|
|
end
|
|
|
|
function set_scheme(npc, ini, scheme, section, gulag_name)
|
|
local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section)
|
|
|
|
st.logic = xr_logic.cfg_get_switch_conditions(ini, section, npc)
|
|
|
|
st.closed = utils.cfg_get_bool(ini, section, "closed", npc, false, true)
|
|
st.locked = utils.cfg_get_bool(ini, section, "locked", npc, false)
|
|
st.no_force = utils.cfg_get_bool(ini, section, "no_force", npc, false, false)
|
|
|
|
st.not_for_npc = utils.cfg_get_bool(ini, section, "not_for_npc", npc, false, false)
|
|
|
|
st.show_tips = utils.cfg_get_bool(ini, section, "show_tips", npc, false, true)
|
|
|
|
st.tip_open = utils.cfg_get_string(ini, section, "tip_open", npc, false, "", "tip_door_open")
|
|
st.tip_unlock = utils.cfg_get_string(ini, section, "tip_open", npc, false, "", "tip_door_locked")
|
|
st.tip_close = utils.cfg_get_string(ini, section, "tip_close", npc, false, "", "tip_door_close")
|
|
|
|
st.slider = utils.cfg_get_bool(ini, section, "slider", npc, false, false)
|
|
|
|
|
|
-- st.snd_init = utils.cfg_get_string(ini, section, "snd_init", npc, false, "")
|
|
st.snd_open_start = utils.cfg_get_string(ini, section, "snd_open_start", npc, false, "", "trader_door_open_start")
|
|
st.snd_close_start = utils.cfg_get_string(ini, section, "snd_close_start", npc, false, "", "trader_door_close_start")
|
|
st.snd_close_stop = utils.cfg_get_string(ini, section, "snd_close_stop", npc, false, "", "trader_door_close_stop")
|
|
|
|
st.on_use = xr_logic.cfg_get_condlist(ini, section, "on_use", npc)
|
|
|
|
if st.locked == true or st.not_for_npc == true then
|
|
if not npc:is_door_locked_for_npc() then
|
|
npc:lock_door_for_npc()
|
|
end
|
|
else
|
|
if npc:is_door_locked_for_npc() then
|
|
npc:unlock_door_for_npc()
|
|
end
|
|
end
|
|
|
|
|
|
|
|
st.hit_on_bone = utils.parse_data_1v(npc, utils.cfg_get_string(ini, section, "hit_on_bone", npc, false, ""))
|
|
end
|
|
|
|
|
|
-- Âûçûâàåòñÿ íà àïäåéòå ÍÏÑ
|
|
-- ïðîáåãàåòñÿ ïî âñåì äâåðÿì è ïûòàåòñÿ îòêðûòü òå, êîòîðûå íàõîäÿòñÿ ðÿäîì ñ ÍÏÑ
|
|
-- âîçâðàùàåò ñïèñîê äâåðåé, êîòîðóþ îòêðûë äàííûé ÍÏÑ
|
|
function try_to_open_door(npc)
|
|
if true then return {} end
|
|
local opened_doors = {}
|
|
local npc_position = npc:position()
|
|
for id,position in pairs(db.level_doors) do
|
|
if npc_position:distance_to_sqr(position) <= 9 then
|
|
if db.storage[id].ph_door ~= nil then
|
|
local action = db.storage[id].ph_door.door_action
|
|
if action.st.not_for_npc == false and action.st.closed == true then
|
|
--printf("OPEN DOOR")
|
|
action:use_callback()
|
|
opened_doors[id] = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return opened_doors
|
|
end
|
|
|
|
function try_to_close_door(npc, doors)
|
|
if true then return {} end
|
|
local npc_position = npc:position()
|
|
local closed_doors = {}
|
|
for id, v in pairs(doors) do
|
|
if npc_position:distance_to_sqr(db.level_doors[id]) > 9 then
|
|
if db.storage[id].ph_door ~= nil then
|
|
local action = db.storage[id].ph_door.door_action
|
|
if action.st.not_for_npc == false and action.st.closed ~= true then
|
|
--printf("CLOSE DOOR")
|
|
action:use_callback()
|
|
closed_doors[id] = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return closed_doors
|
|
end |