[zone_campfire_mp_nolight]
GroupControlSection = spawn_group_zone
$spawn = "zones\campfire_mp_nolight"
$prefetch = 16
class = Z_MBALD
hit_impulse_scale = 0.00
effective_radius = 1.3 ;размер радиуса в процентах от оригинального, где действует зона
ef_anomaly_type = 1
ef_weapon_type = 13
sound =
postprocess = postprocess_flame
artefacts =
BirthProbability = 0.0
;----------- Anomaly settings -----------------------
min_start_power = 0.99
max_start_power = 1.00
attenuation = 1
period = 1
min_artefact_count = 0
max_artefact_count = 0
idle_particles = explosions\campfire_05
blowout_particles = explosions\campfire_blowout
hit_small_particles = damage_fx\burn_creatures00
hit_big_particles = damage_fx\burn_creatures00
idle_small_particles = damage_fx\burn_creatures00
idle_big_particles = damage_fx\burn_creatures00
idle_particles_dont_stop = true;
idle_sound = ambient\fire2 ;постоянный звук
blowout_sound = ambient\fire2 ;во время выброса(удара) в центре аномалии
hit_sound = ambient\fire2 ;на персонаже, когда тот получает хит
entrance_sound = ambient\fire2 ;при попадании объекта в аномалию
hit_type = burn
disable_time = 10000 ;время игнорирования неживого объекта в зоне (-1 если не нужно)
disable_time_small = -1 ;время игнорирования маленького неживого объекта в зоне (-1 если не нужно)
disable_idle_time = 50000 ;время отключения idle партиклов
ignore_nonalive = false
ignore_small = true
ignore_artefacts = true
blowout_light = on
light_color = 1.8,1.7,1.4
light_animation = koster
light_range = 4
light_time = 0.35
light_height = 0.75 ;подъем источника света на высоту
idle_light = off
idle_light_range = 8.0
idle_light_range_delta = 0.25
idle_light_anim = koster_00
idle_light_height = 0.70 ;подъем источника света на высоту
awaking_time = 0
blowout_time = 1000
accamulate_time = 0
visible_by_detector = off
blowout_wind = off
blowout_wind_time_start = 0
blowout_wind_time_peak = 600
blowout_wind_time_end = 899
blowout_wind_power = 0.5 ;сила поднимаего ветра (от 0 до 1), в момент blowout_wind_time_peak
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;рождение артефактов во время срабатывания
spawn_blowout_artefacts = off
[zone_campfire_grill]
GroupControlSection = spawn_group_zone
$spawn = "zones\campfire_grill"
$prefetch = 16
class = Z_MBALD
hit_impulse_scale = 0.00
effective_radius = 1.0 ;размер радиуса в процентах от оригинального, где действует зона
ef_anomaly_type = 1
ef_weapon_type = 13
sound =
postprocess = postprocess_flame
artefacts =
BirthProbability = 0.0
;----------- Anomaly settings -----------------------
min_start_power = 0.39
max_start_power = 0.40
attenuation = 1
period = 1
min_artefact_count = 0
max_artefact_count = 0
idle_particles = explosions\campfire_boar_grill
blowout_particles = explosions\campfire_blowout
hit_small_particles = damage_fx\burn_creatures00
hit_big_particles = damage_fx\burn_creatures00
idle_small_particles = damage_fx\burn_creatures00
idle_big_particles = damage_fx\burn_creatures00
idle_particles_dont_stop = true;
idle_sound = ambient\fire2 ;постоянный звук
blowout_sound = ambient\fire2 ;во время выброса(удара) в центре аномалии
hit_sound = ambient\fire2 ;на персонаже, когда тот получает хит
entrance_sound = ambient\fire2 ;при попадании объекта в аномалию
hit_type = burn
disable_time = 10000 ;время игнорирования неживого объекта в зоне (-1 если не нужно)
disable_time_small = -1 ;время игнорирования маленького неживого объекта в зоне (-1 если не нужно)
disable_idle_time = 50000 ;время отключения idle партиклов
ignore_nonalive = false
ignore_small = true
ignore_artefacts = true
blowout_light = off
light_color = 1.8,1.7,1.4
light_animation = koster
light_range = 8
light_time = 0.35
light_height = 0.35 ;подъем источника света на высоту
idle_light = off
idle_light_range = 8.0
idle_light_range_delta = 0.25
idle_light_anim = koster_00
idle_light_height = 0.70 ;подъем источника света на высоту
awaking_time = 500
blowout_time = 1000
accamulate_time = 0
visible_by_detector = off
blowout_wind = off
blowout_wind_time_start = 0
blowout_wind_time_peak = 600
blowout_wind_time_end = 899
blowout_wind_power = 0.5 ;сила поднимаего ветра (от 0 до 1), в момент blowout_wind_time_peak
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;рождение артефактов во время срабатывания
spawn_blowout_artefacts = off
[zone_flame]
GroupControlSection = spawn_group_zone
$spawn = "zones\flame"
$prefetch = 16
class = Z_MBALD
hit_impulse_scale = 0.0
effective_radius = 1.3 ;размер радиуса в процентах от оригинального, где действует зона
sound = zone_mosquito_bald
postprocess = postprocess_flame
ef_anomaly_type = 1
ef_weapon_type = 13
artefacts =
BirthProbability = 0.0
;----------- Anomaly settings -----------------------
min_start_power = 0.39
max_start_power = 0.40
attenuation = 1
period = 1
min_artefact_count = 0
max_artefact_count = 0
idle_particles = explosions\campfire_04
blowout_particles = explosions\campfire_blowout
hit_small_particles = damage_fx\burn_creatures
hit_big_particles = damage_fx\burn_creatures00
idle_small_particles = damage_fx\burn_creatures
idle_big_particles = damage_fx\burn_creatures00
idle_particles_dont_stop = true;
idle_sound = ambient\fire2 ;постоянный звук
blowout_sound = ambient\fire2 ;во время выброса(удара) в центре аномалии
hit_sound = ambient\fire2 ;на персонаже, когда тот получает хит
entrance_sound = ambient\fire2 ;при попадании объекта в аномалию
hit_type = burn
disable_time = 10000 ;время игнорирования неживого объекта в зоне (-1 если не нужно)
disable_time_small = -1 ;время игнорирования маленького неживого объекта в зоне (-1 если не нужно)
disable_idle_time = 50000 ;время отключения idle партиклов
ignore_nonalive = false
ignore_small = true
ignore_artefacts = true
blowout_light = off
light_color = 1.8,1.7,1.4
light_range = 8.0
light_time = 0.35
light_height = 0.75 ;подъем источника света на высоту
idle_light = off
idle_light_range = 8.0
idle_light_range_delta = 0.2
idle_light_anim = koster_01
idle_light_height = 0.70 ;подъем источника света на высоту
awaking_time = 1000
blowout_time = 300
accamulate_time = 1000
visible_by_detector = off
blowout_wind = off
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;рождение артефактов во время срабатывания
spawn_blowout_artefacts = off
[zone_zhar]
GroupControlSection = spawn_group_zone
$spawn = "zones\zhar"
$prefetch = 16
class = Z_MBALD
hit_impulse_scale = 0.0
effective_radius = 1.3 ;?acia? ?aaeona a i?ioaioao io i?eaeiaeuiiai, aaa aaenoaoao ciia
sound = zone_mosquito_bald
postprocess = postprocess_flame
ef_anomaly_type = 1
ef_weapon_type = 13
artefacts =
BirthProbability = 0.0
;----------- Anomaly settings -----------------------
min_start_power = 0.39
max_start_power = 0.40
attenuation = 1
period = 1
min_artefact_count = 0
max_artefact_count = 0
idle_particles =
blowout_particles =
hit_small_particles = damage_fx\burn_creatures
hit_big_particles = damage_fx\burn_creatures00
idle_small_particles = damage_fx\burn_creatures
idle_big_particles = damage_fx\burn_creatures00
idle_particles_dont_stop = true;
idle_sound = ambient\zhar ;iinoiyiiue caoe
blowout_sound = ambient\zhar ;ai a?aiy aua?ina(oaa?a) a oaio?a aiiiaeee
hit_sound = ambient\zhar ;ia ia?niia?a, eiaaa oio iieo?aao oeo
entrance_sound = ambient\zhar ;i?e iiiaaaiee iauaeoa a aiiiaee?
hit_type = burn
disable_time = 10000 ;a?aiy eaii?e?iaaiey ia?eaiai iauaeoa a ciia (-1 anee ia io?ii)
disable_time_small = -1 ;a?aiy eaii?e?iaaiey iaeaiueiai ia?eaiai iauaeoa a ciia (-1 anee ia io?ii)
disable_idle_time = 50000 ;a?aiy ioee??aiey idle ia?oeeeia
ignore_nonalive = false
ignore_small = false
ignore_artefacts = true
blowout_light = off
light_color = 1.8,1.7,1.4
light_range = 8.0
light_time = 0.35
light_height = 0.75 ;iiauai enoi?ieea naaoa ia aunioo
idle_light = off
idle_light_range = 8.0
idle_light_range_delta = 0.2
idle_light_anim = koster_01
idle_light_height = 0.70 ;iiauai enoi?ieea naaoa ia aunioo
awaking_time = 10
blowout_time = 50
accamulate_time = 10
visible_by_detector = off
blowout_wind = off
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;?i?aaiea a?oaoaeoia ai a?aiy n?aaaouaaiey
spawn_blowout_artefacts = off
[zone_emi]
GroupControlSection = spawn_group_zone
$spawn = "zones\emi"
$prefetch = 16
class = Z_MBALD
hit_impulse_scale = .01
effective_radius = 1 ;размер радиуса в процентах от оригинального, где действует зона
sound = zone_mosquito_bald
postprocess = postprocess_electra
ef_anomaly_type = 1
ef_weapon_type = 13
artefacts =
BirthProbability = 0.0
;----------- Anomaly settings -----------------------
min_start_power = 0.39
max_start_power = 0.40
attenuation = 1
period = 1
min_artefact_count = 0
max_artefact_count = 0
idle_particles = anomaly2\emi_idle_00
blowout_particles = anomaly2\tornado_00
hit_small_particles = hit_fx\hit_metal_02
hit_big_particles = anomaly2\emi_damage_big_smoke
idle_small_particles = anomaly2\electra_damage_01_smoke
idle_big_particles = anomaly2\emi_damage_big_smoke
entrance_small_particles = anomaly2\electra_entrance_small
entrance_big_particles = anomaly2\emi_entrance_big_00
idle_sound = anomaly\emi_idle; anomaly_gravy_idle
blowout_sound = anomaly\emi_blowout
hit_sound = anomaly\electra_blast
entrance_sound = anomaly\emi_entrance
blowout_light = on
light_color = 1.4,1.5,1.8
light_range = 80.0
light_time = 1;0.35
light_height = 15 ;подъем источника света на высоту
idle_light = off
hit_type = strike
awaking_time = 0
blowout_time = 6000
accamulate_time = 5000
blowout_light_time = 5600
blowout_explosion_time = 5000
blowout_particles_time = 0
blowout_sound_time = 0
disable_time = -1 ;время игнорирования неживого объекта в зоне (-1 если не нужно)
disable_time_small = 500 ;время игнорирования маленького неживого объекта в зоне (-1 если не нужно)
disable_idle_time = 1000 ;время отключения idle партиклов
ignore_nonalive = false
ignore_small = false
ignore_artefacts = true
visible_by_detector = on
blowout_wind = off
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;рождение артефактов во время срабатывания
spawn_blowout_artefacts = off
[zone_flame_small]
GroupControlSection = spawn_group_zone
$spawn = "zones\campfire"
$prefetch = 16
class = Z_MBALD
hit_impulse_scale = 0.0
effective_radius = 1.3 ;размер радиуса в процентах от оригинального, где действует зона
ef_anomaly_type = 1
ef_weapon_type = 13
sound =
postprocess = postprocess_flame
artefacts =
BirthProbability = 0.0
;----------- Anomaly settings -----------------------
min_start_power = 0.39
max_start_power = 0.40
attenuation = 1
period = 1
min_artefact_count = 0
max_artefact_count = 0
idle_particles = explosions\campfire_05
blowout_particles = explosions\campfire_blowout
hit_small_particles = damage_fx\burn_creatures00
hit_big_particles = damage_fx\burn_creatures00
idle_small_particles = damage_fx\burn_creatures00
idle_big_particles = damage_fx\burn_creatures00
idle_particles_dont_stop = true;
idle_sound = ambient\fire2 ;постоянный звук
blowout_sound = ambient\fire2 ;во время выброса(удара) в центре аномалии
hit_sound = ambient\fire2 ;на персонаже, когда тот получает хит
entrance_sound = ambient\fire2 ;при попадании объекта в аномалию
hit_type = burn
disable_time = 10000 ;время игнорирования неживого объекта в зоне (-1 если не нужно)
disable_time_small = -1 ;время игнорирования маленького неживого объекта в зоне (-1 если не нужно)
disable_idle_time = 50000 ;время отключения idle партиклов
ignore_nonalive = false
ignore_small = true
ignore_artefacts = true
blowout_light = on
light_color = 1.8,1.7,1.4
light_animation = koster
light_range = 8
light_time = 0.35
light_height = 0.75 ;подъем источника света на высоту
idle_light = off
idle_light_range = 8.0
idle_light_range_delta = 0.25
idle_light_anim = koster_00
idle_light_height = 0.70 ;подъем источника света на высоту
awaking_time = 0
blowout_time = 1000
accamulate_time = 0
visible_by_detector = off
blowout_wind = off
blowout_wind_time_start = 0
blowout_wind_time_peak = 600
blowout_wind_time_end = 899
blowout_wind_power = 0.5 ;сила поднимаего ветра (от 0 до 1), в момент blowout_wind_time_peak
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;рождение артефактов во время срабатывания
spawn_blowout_artefacts = off
function init (obj)
xr_motivator.AddToMotivator(obj)
end
function actor_init (npc)
npc:bind_object(actor_binder(npc))
end
local game_difficulty_by_num = {
[0] = "gd_novice",
[1] = "gd_stalker",
[2] = "gd_veteran",
[3] = "gd_master"
}
lasthealth = 0
lasttime = 0
post_process = 0
local weapon_hide = false
-->> Dynamic campfire mod
local scan_flag
local upd_time
--<< Dynamic campfire mod
----------------------------------------------------------------------------------------------------------------------
class "actor_binder" (object_binder)
----------------------------------------------------------------------------------------------------------------------
function actor_binder:__init (obj) super(obj)
self.bCheckStart = false
self.weather_manager = level_weathers.WeatherManager()
self.actor_detector = xr_detector.actor_detector()
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_spawn(data)
printf("actor net spawn")
level.show_indicators()
self.bCheckStart = true
self.weapon_hide = false -- спрятано или нет оружие при разговоре.
weapon_hide = false -- устанавливаем глобальный дефолтовый флаг.
if object_binder.net_spawn(self,data) == false then
return false
end
db.add_actor(self.object)
if self.st.disable_input_time == nil then
level.enable_input()
end
self.weather_manager:reset()
-- game_stats.initialize ()
if(actor_stats.add_to_ranking~=nil)then
actor_stats.add_to_ranking(self.object:id())
end
--' Загружаем настройки дропа
death_manager.init_drop_settings()
return true
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_destroy()
if(actor_stats.remove_from_ranking~=nil)then
actor_stats.remove_from_ranking(self.object:id())
end
-- game_stats.shutdown ()
db.del_actor(self.object)
sr_light.clean_up ()
self.object:set_callback(callback.inventory_info, nil)
self.object:set_callback(callback.article_info, nil)
self.object:set_callback(callback.on_item_take, nil)
self.object:set_callback(callback.on_item_drop, nil)
--self.object:set_callback(callback.actor_sleep, nil)
self.object:set_callback(callback.task_state, nil)
self.object:set_callback(callback.level_border_enter, nil)
self.object:set_callback(callback.level_border_exit, nil)
self.object:set_callback(callback.take_item_from_box, nil)
if sr_psy_antenna.psy_antenna then
sr_psy_antenna.psy_antenna:destroy()
sr_psy_antenna.psy_antenna = false
end
xr_sound.stop_all_sound_object()
object_binder.net_destroy(self)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:reinit()
object_binder.reinit(self)
local npc_id = self.object:id()
db.storage[npc_id] = { }
self.st = db.storage[npc_id]
self.st.pstor = nil
self.next_restrictors_update_time = -10000
self.object:set_callback(callback.inventory_info, self.info_callback, self)
self.object:set_callback(callback.article_info, self.article_callback, self)
self.object:set_callback(callback.on_item_take, self.on_item_take, self)
self.object:set_callback(callback.on_item_drop, self.on_item_drop, self)
self.object:set_callback(callback.trade_sell_buy_item, self.on_trade, self) -- for game stats
--self.object:set_callback(callback.actor_sleep, self.sleep_callback, self)
self.object:set_callback(callback.task_state, self.task_callback, self)
--self.object:set_callback(callback.map_location_added, self.map_location_added_callback, self)
self.object:set_callback(callback.level_border_enter, self.level_border_enter, self)
self.object:set_callback(callback.level_border_exit, self.level_border_exit, self)
self.object:set_callback(callback.take_item_from_box, self.take_item_from_box, self)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:take_item_from_box(box, item)
local story_id = box:story_id()
if story_id == nil then
return
end
treasure_manager.take_item_from_box(box, story_id)
--[[
local respawner = se_respawn.get_respawner_by_parent(story_id)
if respawner == nil then
return
end
--' Необходимо уменьшить счетчик в респавнере
respawner:remove_spawned(item:id())
local smart_terrain = db.strn_by_respawn[respawner:name()]
if smart_terrain == nil then
return
end
local npc = smart_terrain.gulag:get_nearest_online_obj(db.actor:position())
if npc ~= nil then
xr_sound.set_sound_play(npc, "reac_box")
xr_gulag.setGulagEnemy(smart_terrain:name() , db.actor)
end
]]
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:level_border_enter(npc, info_id)
self.actor_detector:actor_enter()
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:level_border_exit(npc, info_id)
self.actor_detector:actor_exit()
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:info_callback(npc, info_id)
printf("*INFO*: npc='%s' id='%s'", npc:name(), info_id)
--' Сюжет
level_tasks.proceed(self.object)
-- Отметки на карте
level_tasks.process_info_portion(info_id)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_trade (item, sell_bye, money)
if sell_bye == true then
game_stats.money_trade_update (money)
else
game_stats.money_trade_update (-money)
end
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:article_callback(npc, group, name)
--printf("article_callback [%s][%s]", group, name)
if device().precache_frame >1 then return end
if group == "Diary" then
news_manager.send_encyclopedy("diary", group)
else
news_manager.send_encyclopedy("encyclopedy", group)
end
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_item_take (obj)
level_tasks.proceed(self.object)
--game_stats.update_take_item (obj, self.object)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_item_drop (obj)
level_tasks.proceed(self.object)
--game_stats.update_drop_item (obj, self.object)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:task_callback(_task, _objective, _state)
task_manager.task_callback(_task:get_id(), _objective:get_idx(), _state)
if _objective:get_idx() == 0 then
if _state == task.fail then
news_manager.send_task(db.actor, "fail", _task, _objective)
elseif _state == task.completed then
task_manager.reward_by_task(_task)
news_manager.send_task(db.actor, "complete", _task, _objective)
else
news_manager.send_task(db.actor, "new", _task, _objective)
end
else
if _task:get_objective(0):get_state() == task.in_progress then
news_manager.send_task(db.actor, "update", _task, _objective)
end
end
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:map_location_added_callback(spot_type_str, object_id)
if (false==app_ready()) or (device().precache_frame>1) then return end
--'news_manager.send_task(db.actor, "new")
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:update(delta)
object_binder.update(self, delta)
-- DEBUG slowdown
-- slowdown.update()
local time = time_global()
game_stats.update (delta, self.object)
-- апдейт погоды
self.weather_manager:update()
-- апдейт схемы детектора
self.actor_detector:update()
-- апдейт звуковой схемы актера
xr_sound.update_actor()
--' Проверка потери жизни
--[[
if self.object.health - lasthealth > 0.001 or
self.object.health - lasthealth < -0.001 then
printf("%f | %f", self.object.health, self.object.health - lasthealth, game.time() - lasttime)
lasthealth = self.object.health
lasttime = game.time()
end
]]
-- Обновление отключения ввода с клавиатуры.
if self.st.disable_input_time ~= nil and
game.get_game_time():diffSec(self.st.disable_input_time) >= self.st.disable_input_idle
then
level.enable_input()
self.st.disable_input_time = nil
end
-- Обновление сна с переносом чувака в указанную позицию
if self.st.sleep_relocate_time ~= nil and
game.get_game_time():diffSec(self.st.sleep_relocate_time) >= self.st.sleep_relocate_idle
then
self.object:set_actor_position(self.st.sleep_relocate_point)
local dir = self.st.sleep_relocate_point:sub(self.st.sleep_relocate_look)
self.object:set_actor_direction(dir:getH())
self.st.sleep_relocate_time = nil
end
-- Апдейт прятание оружия игрока во время диалога
if weapon_hide == true or self.object:is_talking() then
if self.weapon_hide == false then
self.object:hide_weapon()
self.weapon_hide = true
end
else
if self.weapon_hide == true then
self.object:restore_weapon()
self.weapon_hide = false
end
end
-- обновление рестрикторов, которые под логикой, срабатывает через интервалы времени
if self.next_restrictors_update_time < time then
bind_restrictor.actor_update(delta)
self.next_restrictors_update_time = time + 200
task_manager.actor_update()
end
-- обновление постпроцессов
if post_process ~= 0 then
if post_process:update () == true then
post_process = 0
end
end
-- обновление пси-антенны
if sr_psy_antenna.psy_antenna then
sr_psy_antenna.psy_antenna:update(delta)
end
--' Вывод сообщения о большой радиации
if self.object.radiation >= 0.7 then
local hud = get_hud()
local custom_static = hud:GetCustomStatic("cs_radiation_danger")
if custom_static == nil then
hud:AddCustomStatic("cs_radiation_danger", true)
hud:GetCustomStatic("cs_radiation_danger"):wnd():SetTextST("st_radiation_danger")
end
else
local hud = get_hud()
local custom_static = hud:GetCustomStatic("cs_radiation_danger")
if custom_static ~= nil then
hud:RemoveCustomStatic("cs_radiation_danger")
end
end
if self.bCheckStart then
printf("SET DEFAULT INFOS")
if not has_alife_info("storyline_actor_start") and
(level.name() == "l01_escape")
then
self.object:give_info_portion("storyline_actor_start")
_G.g_start_avi = true
printf("*AVI* RUN START AVI")
end
-- if not has_alife_info("encyclopedy") then
-- self.object:give_info_portion("encyclopedy")
-- end
if not has_alife_info("global_dialogs") then
self.object:give_info_portion("global_dialogs")
end
if not has_alife_info("level_changer_icons") then
self.object:give_info_portion("level_changer_icons")
end
level_tasks.add_lchanger_location()
self.bCheckStart = false
end
-->> Dynamic campfire mod
if scan_flag == nil then
scan_flag = 1
local lvl = level.name()
local exc_tbl = {
["zone_flame_small_0002"] = {"l05_bar"},
["zone_flame_small_0005"] = {"l06_rostok"},
["zone_flame_small_0006"] = {"l06_rostok"},
["zone_flame_small_0007"] = {"l06_rostok"},
["zone_flame_small_0008"] = {"l06_rostok"},
["zone_flame_small_0010"] = {"l06_rostok"},
["zone_flame_small_0012"] = {"l11_pripyat"},
["zone_flame_small_0013"] = {"l11_pripyat"},
["zone_flame_small_0024"] = {"l11_pripyat"},
["zone_flame_small_0025"] = {"l11_pripyat"},
["lights_camp_fire_omni_r1_r2_0002"] = {"l05_bar"},
["lights_camp_fire_omni_r1_r2_0011"] = {"l11_pripyat"},
["lights_camp_fire_omni_r1_r2_0012"] = {"l11_pripyat"},
["lights_camp_fire_omni_r1_r2_0031"] = {"l08_yantar"}
-- МОЖЕТ БЫТЬ ТАК: ["zone_flame_small_9999"] = {"l01_escapel02_garbagel05_barl07_military"},
-- МОЖЕТ БЫТЬ ТАК: ["lights_camp_fire_omni_r1_r2_9999"] = {"l01_escapel02_garbagel05_barl07_military"}
}
for id=1, 65535 do
local obj = level.object_by_id(id)
if obj then
local name = obj:name()
local exc_obj = exc_tbl[name]
if exc_obj and string.find(exc_obj[1], lvl) then
-- printf("EXEPTIONS: OBJ:[%s] LEVELS:[%s]", name, exc_obj[1])
else
if obj:section() == "zone_flame_small" then
table.insert(xr_kamp.lvl_objs, obj)
obj:disable_anomaly()
elseif string.find(name, "r1_r2") then
table.insert(xr_kamp.lvl_objs, obj)
obj:get_hanging_lamp():turn_off()
-- Масляные горелки (требуется доп. правка particles.xr)
-- elseif string.find(name, "light_gas") then
-- obj:get_hanging_lamp():turn_off()
end
end
end
end
end
if upd_time == nil then
upd_time = time + 10000
elseif upd_time < time then
upd_time = time + 10000
xr_kamp.update(time)
end
--<< Dynamic campfire mod
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:save(packet)
local save_treasure_manager = true
printf("actor_binder:save(): self.object:name()='%s'", self.object:name())
object_binder.save(self, packet)
--' Сохраняем уровень сложности
if save_treasure_manager == true then
packet:w_u8(level.get_game_difficulty() + 128)
else
packet:w_u8(level.get_game_difficulty())
end
--' Сохраняем данные об отключенном вводе
if self.st.disable_input_time == nil then
packet:w_bool(false)
else
packer:w_bool(true)
utils.w_CTime(packet, self.st.disable_input_time)
end
xr_logic.pstor_save_all(self.object, packet)
self.weather_manager:save(packet)
sr_psy_antenna.save( packet )
if save_treasure_manager == true then
treasure_manager.save(packet)
end
task_manager.save(packet)
self.actor_detector:save(packet)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:load(reader)
printf("actor_binder:load(): self.object:name()='%s'", self.object:name())
object_binder.load(self, reader)
printf("actor_binder:object_binder.load(): self.object:name()='%s'", self.object:name())
--' Загружаем уровень сложности
local game_difficulty = reader:r_u8()
local load_treasure_manager = false
if game_difficulty >= 128 then
game_difficulty = game_difficulty - 128
load_treasure_manager = true
end
get_console():execute("g_game_difficulty "..game_difficulty_by_num[game_difficulty])
if reader:r_eof() then
abort("SAVE FILE IS CORRUPT")
end
local stored_input_time = reader:r_u8()
if stored_input_time == true then
self.st.disable_input_time = utils.r_CTime(reader)
end
xr_logic.pstor_load_all(self.object, reader)
self.weather_manager:load(reader)
sr_psy_antenna.load(reader)
if load_treasure_manager == true then
treasure_manager.load(reader)
end
task_manager.load(reader)
self.actor_detector:load(reader)
end
----------------------------------------------------------------------------------------------------------------------
--старт префетча звуков
--if string.find(command_line(), "-noprefetch") == nil then
-- sound_prefetch.prefetch_sounds()
--end
-- Weapon functions
function hide_weapon()
weapon_hide = true
end
function restore_weapon()
weapon_hide = false
end
// this is test for section iteration
/**
local function test_section_iteration(file_name, section_name)
printf ("file : %s",file_name)
printf ("section : %s",section_name)
local file = ini_file(file_name)
local n = file:line_count(section_name)
printf ("lines : %d",n)
local id, value = "", "", result
for i=0,n-1 do
result, id, value = file:r_line(section_name,i,"","")
printf ("line %d : %s = %s",i,id,value)
end
end
test_section_iteration("system.ltx","space_restrictor")
/**/[/spoiler]
plik:[spoiler=xr_campfire.script]----------------------------------------------------------------------------------------------------------------------
-- Схема лагерь. Чудак(и) у костра.
-- автор: Диденко Руслан (Stohe)
-- TODO:
----------------------------------------------------------------------------------------------------------------------
function printf(fmt, ...)
-- local msg = string.format(fmt, ...)
-- local msg_no_ws = string.gsub(msg, "%s", "_")
-- get_console():execute("dbg:" .. msg_no_ws)
end
kamps = {}
kamp_stalkers = {} -- могут ли сталкеры в лагере юзаться игроком.
-- Объявления итераторов
local k,v,kk,vv = 0,0,0,0
---------------------------------------------------------------------------------------------------------------------
--Evaluators
----------------------------------------------------------------------------------------------------------------------
--' Условие завершения скрипта
class "evaluator_kamp_end" (property_evaluator)
function evaluator_kamp_end:__init(name, storage) super (nil, name)
self.a = storage
end
function evaluator_kamp_end:evaluate()
return not xr_logic.is_active(self.object, self.a)
end
--' Находимся ли мы на заданной позиции
class "evaluator_on_position" (property_evaluator)
function evaluator_on_position:__init(name, storage) super (nil, name)
self.a = storage
end
function evaluator_on_position:evaluate()
if self.object:level_vertex_id() == self.a.pos_vertex then
return true
end
return false
end
----------------------------------------------------------------------------------------------------------------------
--Actions
----------------------------------------------------------------------------------------------------------------------
--' Идет в заданную область
class "action_go_position" (action_base)
function action_go_position:__init (npc_name,action_name,storage) super (nil,action_name)
self.a = storage
end
function action_go_position:initialize()
action_base.initialize(self)
-- self.object:set_node_evaluator()
-- self.object:set_path_evaluator()
self.object:set_desired_position()
self.object:set_desired_direction()
self.a.pos_vertex = nil
end
function action_go_position:execute ()
action_base.execute (self)
if db.actor then
if xr_logic.try_switch_to_another_section(self.object, self.a, db.actor) then
return
end
end
local tmp_pos_vertex = kamps[self.a.center_point]:getDestVertex(self.object:id(), self.a.radius)
if self.a.pos_vertex ~= tmp_pos_vertex then
self.a.pos_vertex = tmp_pos_vertex
if not self.object:accessible(self.a.pos_vertex) then
--'printf("[%s] KAMP NODE NOT ACCESSIBLE. Get accessible nearest", self.object:name())
local ttp = vector():set(0,0,0)
self.a.pos_vertex = self.object:accessible_nearest(level.vertex_position(self.a.pos_vertex), ttp)
end
self.a.pp = patrol(self.a.center_point):level_vertex_id(0)
self.a.pp = level.vertex_in_direction(self.a.pp, vector():set(math.random(-1,1), 0, math.random(-1,1)), math.random(0,0.5))
self.object:set_dest_level_vertex_id(self.a.pos_vertex)
self.object:set_desired_direction(vector():sub(level.vertex_position(self.a.pp),level.vertex_position(self.a.pos_vertex)))
self.object:set_path_type(game_object.level_path)
state_mgr.set_state(self.object, self.a.def_state_moving)
end
end
function action_go_position:finalize ()
action_base.finalize (self)
end
--' Просто сидит и втыкает
class "action_wait" (action_base)
function action_wait:__init (npc_name,action_name,storage) super (nil,action_name)
self.a = storage
end
function action_wait:initialize()
action_base.initialize(self)
-- self.object:set_node_evaluator()
-- self.object:set_path_evaluator()
self.object:set_desired_position()
self.object:set_desired_direction()
kamps[self.a.center_point]:increasePops(self.object)
end
function action_wait:activate_scheme()
end
function action_wait:execute()
action_base.execute (self)
if db.actor then
if xr_logic.try_switch_to_another_section(self.object, self.a, db.actor) then
return
end
end
local state, sound, substate = kamps[self.a.center_point]:updateNpc(self.object)
--' повернуть его лицом к центру
state_mgr.set_state(self.object, state, nil, nil, {look_position = level.vertex_position(self.a.pp)}, nil, nil, {subanim = substate})
xr_sound.set_sound(self.object, sound)
end
function action_wait:finalize()
kamps[self.a.center_point]:decreasePops(self.object)
action_base.finalize (self)
end
function action_wait:deactivate(npc)
kamps[self.a.center_point]:removeNpc(npc)
end
function action_wait:death_callback(npc)
kamps[self.a.center_point]:removeNpc(npc)
end
function action_wait:net_destroy(npc)
kamps[self.a.center_point]:decreasePops(self.object) --<< Dynamic campfire mod
kamps[self.a.center_point]:removeNpc(npc)
end
class "CKampManager"
function CKampManager:__init(path)
self.kamp_name = path
self.patrol = patrol(path)
self.center = self.patrol:level_vertex_id(0)
self.position = {{dir = vector():set(1, 0, 0), used = nil},
{dir = vector():set(1, 0, 1), used = nil},
{dir = vector():set(0, 0, 1), used = nil},
{dir = vector():set(-1, 0, 1), used = nil},
{dir = vector():set(-1, 0, 0), used = nil},
{dir = vector():set(-1, 0, -1),used = nil},
{dir = vector():set(0, 0, -1), used = nil},
{dir = vector():set(1, 0, -1), used = nil}}
self.npc = {}
self.population = 0
self.kamp_state = "idle"
-- Где то здесь распарсим патрульный путь и проапдейтим вектор позиций.
-- 0 вершина - центр лагеря.
-- 1 флаг - сектор занят, в поинте можно сидеть.
-- 2 флаг - сектор занят, в поинте нельзя сидеть.
for k = 1, self.patrol:count() - 1 do
-- если есть 1 или 2 флажок - отметить сектор как занятый
if self.patrol:flag(k,1) or
self.patrol:flag(k,2)
then
-- отметить сектор как занятый
for key,value in pairs(self.position) do
dir = vector():sub(level.vertex_position(self.patrol:level_vertex_id(k)), level.vertex_position(self.center))
if value.dir then
yaw = yaw_degree(dir, value.dir)
if yaw <=23 then
--'printf("KAMP node[%s], sector[%s,] yaw[%s]", k, key, yaw_degree(dir, value.dir))
value.used = -1
break
end
end
end
end
-- если есть 1 флажок - создать место для сидения в точке пути
if self.patrol:flag(k,1) then
-- создать точку для сидения
table.insert(self.position, {vertex = self.patrol:level_vertex_id(k)})
end
end
--print_table(self.position)
--Таблица соответствий состояния лагеря и допустимых анимаций и звуков.
self.avail_state = {idle = { directed = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
pre_harmonica = { directed = { "wait_harmonica"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
harmonica = { directed = { "play_harmonica"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
post_harmonica = { directed = { "wait_harmonica"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
pre_guitar = { directed = { "wait_guitar"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
guitar = { directed = { "play_guitar"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
post_guitar = { directed = { "wait_guitar"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
story = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
post_story = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
pre_joke = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
joke = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
post_joke = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}}}
self.avail_sound = {idle = { directed = "idle"},
pre_harmonica = { directed = "pre_harmonica", undirected = ""},
harmonica = { directed = "play_harmonica", undirected = ""},
post_harmonica = { directed = "", undirected = "reac_harmonica"},
pre_guitar = { directed = "pre_guitar", undirected = ""},
guitar = { directed = "play_guitar", undirected = ""},
post_guitar = { directed = "", undirected = "reac_guitar"},
story = { directed = "play_story", undirected = ""},
post_story = { directed = "", undirected = "reac_story"},
pre_joke = { directed = "pre_joke", undirected = ""},
joke = { directed = "play_joke", undirected = ""},
post_joke = { directed = "", undirected = "reac_joke"}}
-- Таблица таймаутов по состоянию. Если состояние установилось, то некоторое время оно не может быт изменено.
self.timeout = {idle = { min = 30000 },
pre_harmonica = { min = 3000 },
harmonica = { min = 5000, soundstart = true },
post_harmonica = { min = 3000 },
pre_guitar = { min = 3000 },
guitar = { min = 5000, soundstart = true },
post_guitar = { min = 3000 },
story = { min = 1000, soundstart = true },
post_story = { min = 3000 },
pre_joke = { min = 3000 },
joke = { min = 5000, soundstart = true },
post_joke = { min = 3000 }}
-- Таблица глобальных состояний лагеря.
self.kamp_states = { idle = true,
pre_harmonica = false, harmonica = false, post_harmonica = false,
pre_guitar = false, guitar = false, post_guitar = false,
story = false, post_story = false,
pre_joke = true, joke = true, post_joke = true}
-- Таблица допустимых переходов между состояниями с вероятностями.
self.trans_kamp = { idle = { idle = 0, pre_harmonica = 30, pre_guitar = 30, story = 0, pre_joke = 40 },
pre_harmonica = { harmonica = 100 },
harmonica = { post_harmonica = 100 },
post_harmonica = { idle = 70, harmonica = 30 },
pre_guitar = { guitar = 100 },
guitar = { post_guitar = 100 },
post_guitar = { idle = 70, guitar = 30 },
story = { post_story = 100 },
post_story = { idle = 100 },
pre_joke = { joke = 100 },
joke = { post_joke = 100 },
post_joke = { idle = 100 }}
-- Хранилище для режиссера лагеря. Режиссерем является сталкер, затеявший необычное поведение
self.director = nil
end
function CKampManager:selectPosition(npc_id)
-- создаем список доступных позиций
--printf("KAMP. [%s] called select position", npc_id)
local free = {}
for k,v in pairs(self.position) do
if v.used == nil then
table.insert(free, k)
end
end
--' затем из доступных позиций выбрать рандомно одну.
if table.getn(free) > 0 then
--printf("KAMP [%s] free node > 0", npc_id)
local rr = math.random(table.getn(free))
self.position[free[rr]].used = npc_id
self.npc[npc_id].position = free[rr]
end
--printf("KAMP [%s] npc table", npc_id)
--print_table(self.npc)
--printf("KAMP [%s] position table", npc_id)
--print_table(self.position)
end
function CKampManager:getDestVertex(npc_id, radius)
--printf("get dest Vertex called [%s]", npc_id)
if self.npc[npc_id].position == nil then
--printf("-------debug_info-------------")
--print_table(self.npc)
--printf("-------debug_info-------------")
--print_table(self.position)
--printf("-------debug_info-------------")
abort("get dest Vertex: nil [%s]", npc_id)
return nil
end
local position = self.position[self.npc[npc_id].position]
if position.vertex ~= nil then
--printf("vertex preselected [%s]", npc_id)
return position.vertex
end
-- высчитываем вертех по направлению
local pp = level.vertex_in_direction(self.center, self.position[self.npc[npc_id].position].dir, radius)
pp = level.vertex_in_direction(pp, vector():set(math.random(-1,1), 0, math.random(-1,1)), math.random(0,0.5))
--printf("vertex selected [%s]", npc_id)
return pp
end
function CKampManager:proceedState(npc)
-- Проверка на таймаут
local npc_id = npc:id()
local active_sound_count = npc:active_sound_count()
if self.npc[npc_id].need_sound_begin == true then
if active_sound_count == 0 then
return
else
self.npc[npc_id].need_sound_begin = false
end
end
if self.begin ~= nil and
time_global() - self.begin < self.timeout[self.kamp_state].min
then
return
end
-- Если режиссер не закончил говорить - ждем конца фразы.
if active_sound_count > 0 then
return
end
--printf("Proceed state for [%s]", npc_id)
-- В случае с историей переход обрабатывается отдельно
if self.kamp_state == "post_story" then
if self.story_last < self.story_max - 1 then
self.npc[npc_id].begin = nil
self.npc[npc_id].need_sound_begin = true
self.director = npc_id
self.kamp_state = "story"
self.begin = time_global()
for kk,vv in pairs(self.npc) do
vv.new = true
end
return
else
self.selected_story = nil
end
end
-- Определяются допустимые в данный момент переходы.
local temp = {}
local max_rnd = 0
for k,v in pairs(self.trans_kamp[self.kamp_state]) do
-- Определяются допустимые состояния для лагеря.
if self.kamp_states[k] == true then
temp[k] = v
max_rnd = max_rnd + v
end
end
-- Осуществляется рандомный взвешенный переход.
if max_rnd == 0 then
-- Если переходить некуда - переходим в айдл
temp["idle"] = 100
max_rnd = 100
end
local p = math.random(0,max_rnd)
for k,v in pairs(temp) do
p = p - v
if p <= 0 then
--printf("Selected [%s]", k)
if k == "idle" then
self.director = nil
if self.kamp_state ~= "idle" then
self.npc[npc_id].begin = nil
end
else
self.npc[npc_id].begin = nil
if self.timeout[k].soundstart == true then
self.npc[npc_id].need_sound_begin = true
end
self.director = npc_id
self.censor = nil
end
self.kamp_state = k
self.begin = time_global()
-- Меняем таймаут для истории
if k == "post_story" then
local dep = sound_theme.theme[self.selected_story].depence[self.story_last]
if dep and dep.min and dep.max then
self.timeout["post_story"].min = math.random(dep.min, dep.max)*1000
end
end
for kk,vv in pairs(self.npc) do
vv.new = true
end
return
end
end
end
function CKampManager:proceedRole(npc, director)
--printf("Proceed Role for [%s]", npc:id())
-- Определить список доступных анимаций по состоянию лагеря.
-- определить список доступных анимаций по наличию предметов
-- выбрать одну из них (то же самое со звуком).
local states = 0
local sound = ""
local state = ""
local npc_id = npc:id()
if self.npc[npc_id].begin == nil or
time_global() - self.npc[npc_id].begin >= self.npc[npc_id].state_idle
then
if director then
states = self.avail_state[self.kamp_state].directed
sound = self.avail_sound[self.kamp_state].directed
else
states = self.avail_state[self.kamp_state].undirected
sound = self.avail_sound[self.kamp_state].undirected
end
-- Выбирать новое состояние только раз в какое то время.
local temp = {}
for k,v in pairs(states) do
if self.npc[npc_id].states[v] == true then
table.insert(temp, v)
end
end
-- Если мы решили говорить историю, надо выбрать какую именно говорить.
if sound == "play_story" and self.selected_story == nil and db.story_by_id[npc_id] ~= nil then
local story_num = table.getn(db.story_by_id[npc_id])
if story_num > 0 then
self.selected_story = db.story_by_id[npc_id][math.random(story_num)]
end
end
self.npc[npc_id].begin = time_global()
state = temp[math.random(table.getn(temp))]
self.npc[npc_id].state_selected = state
self.npc[npc_id].state_idle = math.random(15000,20000)
else
if director then
sound = self.avail_sound[self.kamp_state].directed
else
sound = self.avail_sound[self.kamp_state].undirected
end
state = self.npc[npc_id].state_selected
end
--printf("Proceed Role state [%s] sound [%s]", state, sound)
return state, sound
end
function CKampManager:updateNpc(npc)
-- Проверка что сталкер может делать, а что нет.
self:checkNpcAbility(npc)
-- Просим лагерь выбрать текущее состояние. Менять состояние лагеря
-- имеет право только режиссер.
local npc_id = npc:id()
local director = self.director == nil or self.director == npc_id
if director then
self:proceedState(npc)
end
-- Говорим чудаку выбрать себе состояние для текущего состояния лагеря.
local state, sound = self:proceedRole(npc, director)
local substate = nil
if state == "wait_harmonica" then
if sound == "pre_harmonica" and self.npc[npc_id].new == true then
xr_sound.set_sound_play(npc, "intro_music", math.random(2000,3000))
self.npc[npc_id].new = false
end
state = "harmonica"
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "play_harmonica" then
state = "harmonica"
substate = 1
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "wait_guitar" then
if sound == "pre_guitar" and self.npc[npc_id].new == true then
xr_sound.set_sound_play(npc, "intro_music", math.random(2000,3000))
self.npc[npc_id].new = false
end
state = "guitar"
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "play_guitar" then
state = "guitar"
substate = 1
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "declarate" then
if self.npc[npc_id].new == true then
if sound == "pre_joke" then
xr_sound.set_sound_play(npc, "intro_joke", math.random(2000,3000))
elseif sound == "play_joke" then
xr_sound.set_sound_play(npc, "joke", math.random(2000,3000))
elseif sound == "play_story" then
xr_sound.set_sound_play(npc, self.selected_story)
self.story_last, self.story_max = xr_sound.get_last_IDS(npc, self.selected_story)
end
self.npc[npc_id].new = false
end
if npc:character_community() == "monolith" then
local t = math.mod(npc_id, 2)
if t == 0 then
state = "trans_0"
else
state = "trans_1"
end
elseif npc:character_community() == "zombied" then
state = "trans_zombied"
else
local t = math.mod(npc_id, 3)
if t == 0 then
state = "sit"
elseif t == 1 then
state = "sit_ass"
else
state = "sit_knee"
end
end
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "trans" then
if npc:character_community() == "monolith" then
local t = math.mod(npc_id, 2)
if t == 0 then
state = "trans_0"
else
state = "trans_1"
end
elseif npc:character_community() == "zombied" then
state = "trans_zombied"
end
xr_kamp.kamp_stalkers[npc_id] = false
else
xr_kamp.kamp_stalkers[npc_id] = true
end
-- Выбор реальных звуков
if sound == "idle" then
sound = "weather, state"
elseif sound == "reac_guitar" then
sound = "reac_music"
elseif sound == "reac_harmonica" then
sound = "reac_music"
elseif sound == "reac_joke" then
sound = ""
if self.npc[npc_id].new == true then
if self.censor == nil then
xr_sound.set_sound_play(npc, "reac_joke", math.random(2000,3000))
self.censor = npc_id
else
xr_sound.set_sound_play(npc, "story_reac_laughter", math.random(100,300))
end
self.npc[npc_id].new = false
end
elseif sound == "reac_story" then
sound = ""
if self.npc[npc_id].new == true then
local dep = sound_theme.theme[self.selected_story].depence[self.story_last+1]
if dep then
if dep.type == "all" then
xr_sound.set_sound_play(npc, dep.theme, math.random(100,300))
else
sound = dep.theme
end
end
end
elseif sound == "reac_story" then
sound = ""
else
sound = ""
end
--printf("Proceed Update Npc [%s] sound [%s]", state, sound)
return state, sound, substate
end
function CKampManager:checkNpcAbility(npc)
local npc_id = npc:id()
if npc:character_community() ~= "monolith" and
npc:character_community() ~= "zombied"
then
-- есть колбасу
if npc:object("kolbasa") then
self.npc[npc_id].states["eat_kolbasa"] = true
else
self.npc[npc_id].states["eat_kolbasa"] = false
end
-- пить водку
if npc:object("vodka") then
self.npc[npc_id].states["eat_vodka"] = true
else
self.npc[npc_id].states["eat_vodka"] = false
end
-- пить енергитический напиток
if npc:object("energy_drink") then
self.npc[npc_id].states["eat_energy"] = true
else
self.npc[npc_id].states["eat_energy"] = false
end
-- есть хлеб
if npc:object("bread") then
self.npc[npc_id].states["eat_bread"] = true
else
self.npc[npc_id].states["eat_bread"] = false
end
-- играть на гармошке
-- if npc:object("harmonica_a") then
-- self.npc[npc_id].states["play_harmonica"] = true
-- self.npc[npc_id].states["wait_harmonica"] = true
-- self.kamp_states["pre_harmonica"] = true
-- self.kamp_states["harmonica"] = true
-- self.kamp_states["post_harmonica"] = true
-- else
self.npc[npc_id].states["play_harmonica"] = false
self.npc[npc_id].states["wait_harmonica"] = false
self.kamp_states["pre_harmonica"] = false
self.kamp_states["harmonica"] = false
self.kamp_states["post_harmonica"] = false
-- end
-- играть на гитаре
if npc:object("guitar_a") then
self.npc[npc_id].states["play_guitar"] = true
self.npc[npc_id].states["wait_guitar"] = true
self.kamp_states["pre_guitar"] = true
self.kamp_states["guitar"] = true
self.kamp_states["post_guitar"] = true
else
self.npc[npc_id].states["play_guitar"] = false
self.npc[npc_id].states["wait_guitar"] = false
self.kamp_states["pre_guitar"] = false
self.kamp_states["guitar"] = false
self.kamp_states["post_guitar"] = false
end
-- анекдоты
if self.population > 1 then
self.kamp_states["pre_joke"] = true
self.kamp_states["joke"] = true
self.kamp_states["post_joke"] = true
else
self.kamp_states["pre_joke"] = false
self.kamp_states["joke"] = false
self.kamp_states["post_joke"] = false
end
end
-- Если чувак знает истории, надо добавить их к лагерю
--[[
if self.population > 1 and db.story_by_id[npc:id()] ~= nil then
self.kamp_states["story"] = true
self.kamp_states["post_story"] = true
else
self.kamp_states["story"] = false
self.kamp_states["post_story"] = false
end
]]
end
function CKampManager:addNpc(npc)
--printf("KAMP [%s] add npc", npc:name())
if self.npc[npc:id()] ~= nil then
--printf("NPC is already exist")
return
end
if npc:character_community() == "monolith" or
npc:character_community() == "zombied"
then
self.npc[npc:id()] = {name = npc:name(), position = nil, current = nil, speak = 0, states = {
stand_wait = false, sit = false, sit_ass = false, sit_knee = false, declarate = true,
eat_kolbasa = false, eat_vodka = false, eat_energy = false, eat_bread = false, trans = true,
play_harmonica = false, play_guitar = false, play_joke = false, play_story = false}}
else
self.npc[npc:id()] = {name = npc:name(), position = nil, current = nil, speak = 0, states = {
stand_wait = true, sit = true, sit_ass = true, sit_knee = true, declarate = true,
eat_kolbasa = false, eat_vodka = false, eat_energy = false, eat_bread = false, trans = false,
play_harmonica = false, play_guitar = false, play_joke = false, play_story = false}}
end
self:selectPosition(npc:id())
end
function CKampManager:removeNpc(npc)
--printf("KAMP [%s] remove npc", npc:name())
local npc_id = npc:id()
if self.npc[npc_id] ~= nil then
-- Если удаляем режиссера - необходимо форсированно перевести лагерь в идловое состояние.
if self.director == npc_id then
self.director = nil
self.npc[npc_id].begin = nil
self.censor = nil
self.kamp_state = "idle"
self.begin = time_global()
for kk,vv in pairs(self.npc) do
vv.new = true
end
xr_sound.set_sound(npc, nil)
stop_play_sound(npc)
end
self.position[self.npc[npc_id].position].used = nil
self.npc[npc_id] = nil
end
end
-->> Dynamic campfire mod
local camp_tbl = {
["esc2_st_fabric_kamp_1"] = {"zone_flame_small_0001", "lights_camp_fire_omni_r1_r2_0001"},
["esc_bridge_kamp_point"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0002"},
["esc_lager_camp_center"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0004"},
["esc_killers_kamp"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0004"},
["esc_blokpost_kamp"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["esc2_most_kamp_1"] = {"zone_flame_small_0006", "lights_camp_fire_omni_r1_r2_0006"},
["esc_assault_kamp_center1"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["esc_fabrika_bandit_camp_center"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["esc2_st_fabric_kamp_2"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["esc2_bandit_les_kamp_1"] = {"zone_flame_small_0008", "lights_camp_fire_omni_r1_r2_0008"},
["esc_stalker_camp_esc_fox_kamp"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["esc2_st_fox_place_kamp_1"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["esc_stalker_camp_camp_point"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["gar_angar_gar_seryi_kamp"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0003"},
["gar_smart_garage_kamp_1"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0003"},
["gar_smart_graveyard_kamp_1"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0004"},
["gar_bandit_agr_kamp_point1"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0004"},
["gar_bandit_agr_kamp_point"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0004"},
["gar_hellcar_group_kamp_point"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0004"},
["gar_smart_bandit_kamp_1"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0005"},
["gar_smart_stalkers_1_kamp_1"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0005"},
["gar_dolg_blokpost_kamp_point"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0006"},
["val_smart_bandit_2_kamp_2"] = {"zone_flame_small_0006", "lights_camp_fire_omni_r1_r2_0006"},
["val_smart_bandit_2_kamp_1"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["val_lager_bandits_kamp2"] = {"zone_flame_small_0010", "lights_camp_fire_omni_r1_r2_0010"},
["val_lager_bandits_kamp3"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["val_lager_bandits_kamp1"] = {"zone_flame_small_0012", "lights_camp_fire_omni_r1_r2_0012"},
["val_smart_bandit_1_kamp_1"] = {"zone_flame_small_0015", "lights_camp_fire_omni_r1_r2_0015"},
["val_rob_kamp"] = {"zone_flame_small_0015", "lights_camp_fire_omni_r1_r2_0015"},
["val_exit1_ambush_kamp_1"] = {"zone_flame_small_0017", "lights_camp_fire_omni_r1_r2_0017"},
["val_smart_bandit_3_kamp_1"] = {"zone_flame_small_0017", "lights_camp_fire_omni_r1_r2_0017"},
["bar_visitors_kamp_1"] = {"zone_flame_small_0000", "lights_camp_fire_omni_r1_r2_0000"},
["bar_visitors_kamp_2"] = {"zone_flame_small_0001", "lights_camp_fire_omni_r1_r2_0001"},
["bar_visitors_kamp_3"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["bar_dolg_general_kamp_center"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0003"},
["bar_visitors_kamp_4"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0004"},
["ros_smart_stalker_bandits1_kamp_1"] = {"zone_flame_small_0000", "lights_camp_fire_omni_r1_r2_0000"},
["yan_st_stalker2_kamp_1"] = {"zone_flame_small_0008", "lights_camp_fire_omni_r1_r2_0008"},
["mil_monolit_kamp1"] = {"zone_flame_small_0000", "lights_camp_fire_omni_r1_r2_0000"},
["mil_fneutral_kamp"] = {"zone_flame_small_0000", "lights_camp_fire_omni_r1_r2_0000"},
["mil_monolit_kamp2"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0002"},
["mil_khutor_kamp_center"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0003"},
["mil_smart_dolg_kamp_kamp_1"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["mil_dolg_camp_center"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["mil_village_kamp"] = {"zone_flame_small_0006", "lights_camp_fire_omni_r1_r2_0006"},
["mil_fblockpost_kamp"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["mil_monolit_kamp3"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["mil_lager_kamp_1"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["mil_mercs_kamp_1"] = {"zone_flame_small_0010", "lights_camp_fire_omni_r1_r2_0010"},
["mil_bandit_kamp_1"] = {"zone_flame_small_0011", "lights_camp_fire_omni_r1_r2_0011"},
["mil_freedom_camp_center1"] = {"zone_flame_small_0012", "lights_camp_fire_omni_r1_r2_0012"},
["rad_prip_teleport_kamp_center"] = {"zone_flame_small_0001", "lights_camp_fire_omni_r1_r2_0001"},
["rad2_prip_teleport_kamp_1"] = {"zone_flame_small_0001", "lights_camp_fire_omni_r1_r2_0001"},
["rad_valley_kamp"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0002"},
["rad_entrance_kamp"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["rad2_prip_teleport_kamp_2"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["rad_mil_entrance_kamp_center"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["rad_prip_road_kamp_center"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["rad_freedom_vs_duty_kamp_center1"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["rad_freedom_vs_duty_kamp_center"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["rad2_loner_0001_kamp_1"] = {"zone_flame_small_0008", "lights_camp_fire_omni_r1_r2_0008"},
["rad2_loner_0002_kamp_1"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["rad_antenna_monolith_kamp"] = {"zone_flame_small_0010", "lights_camp_fire_omni_r1_r2_0010"},
["rad_antenna_patrol_kamp"] = {"zone_flame_small_0010", "lights_camp_fire_omni_r1_r2_0010"},
["rad2_loner_0000_kamp_1"] = {"zone_flame_small_0013", "lights_camp_fire_omni_r1_r2_0013"},
["pri_smart_monolith_stalker5_kamp_1"] = {"zone_flame_small_0018", "lights_camp_fire_omni_r1_r2_0005"},
["pri_smart_dolg_stalker1_kamp_1"] = {"zone_flame_small_0021", "lights_camp_fire_omni_r1_r2_0008"},
["pri_wave7_kamp_1"] = {"pri_zone_flame_small_0003", "pri_r1_r2_0001"},
["pri_sideway_left_kamp"] = {"pri_zone_flame_small_0043", "pri_r1_r2_00002"},
["pri_smart_freedom_stalker1_kamp_1"] = {"pri_zone_flame_small_0043", "pri_r1_r2_0002"},
["pri_smart_monolith_stalker4_kamp_1"] = {"pri_zone_flame_small_0044", "pri_r1_r2_0003"},
["pri_monolith_kamp2"] = {"pri_zone_flame_small_0026", "pri_r1_r2_0004"},
["pri_monolith_kamp3"] = {"pri_zone_flame_small_0021", "pri_r1_r2_0005"},
["pri_monolith_kamp5"] = {"pri_zone_flame_small_0045", "pri_r1_r2_0006"},
["pri_monolith_kamp7"] = {"pri_zone_flame_small_0000", "pri_r1_r2_0007"},
["pri_smart_monolith_stalker6_kamp_1"] = {"pri_zone_flame_small_0035", "pri_r1_r2_0008"}
}
lvl_objs = {}
local kamps_info = {}
function CKampManager:increasePops(npc)
self.population = self.population + 1
local camp_name = camp_tbl[self.kamp_name]
if self.population == 1 and camp_name then
local flame = camp_name[1]
local light = camp_name[2]
-- kamps_info[self.kamp_name] = nil
-- if not kamps_info[self.kamp_name] then
kamps_info[self.kamp_name] = {}
kamps_info[self.kamp_name].time = time_global()
kamps_info[self.kamp_name].prtcl = nil
kamps_info[self.kamp_name].state = nil
-- end
for i,o in pairs(lvl_objs) do
local obj = o
if obj and obj:name() == flame then
kamps_info[self.kamp_name].obj_fire = obj
obj:enable_anomaly()
end
if obj and obj:name() == light then
kamps_info[self.kamp_name].obj_light = obj
end
end
end
end
function CKampManager:decreasePops(npc)
self.population = self.population - 1
local camp_name = camp_tbl[self.kamp_name]
if self.population < 1 and camp_name then
local flame = camp_name[1]
local light = camp_name[2]
-- if not kamps_info[self.kamp_name] then
kamps_info[self.kamp_name] = {}
kamps_info[self.kamp_name].time = time_global()
kamps_info[self.kamp_name].prtcl = particles_object("dyn_kfire\\dyingfire")
kamps_info[self.kamp_name].state = nil
-- end
for i,o in pairs(lvl_objs) do
local obj = o
if obj and obj:name() == flame then
kamps_info[self.kamp_name].obj_fire = obj
end
if obj and obj:name() == light then
kamps_info[self.kamp_name].obj_light = obj
end
end
end
end
function update(time)
for i,v in pairs(kamps_info) do
local kamp_name = i
local kamp_fire = v.obj_fire
local kamp_light = v.obj_light
local kamp_time = v.time
local kamp_prtcl = v.prtcl
local kamp_state = v.state
if kamp_fire and kamp_light then
if kamp_prtcl == nil and kamp_time + 5000 < time then
kamp_light:get_hanging_lamp():turn_on()
kamps_info[kamp_name] = nil
end
if kamp_prtcl then
if kamp_state == nil and kamp_time + 10000 < time then
kamps_info[kamp_name].state = 1
kamp_prtcl:play_at_pos(kamp_fire:position())
end
if kamp_time + 15000 < time then
kamp_fire:disable_anomaly()
end
if kamp_time + 48000 < time then
kamp_light:get_hanging_lamp():turn_off()
end
if kamp_time + 120000 < time then
kamp_prtcl:stop()
kamps_info[kamp_name] = nil
end
end
end
end
end
--<< Dynamic campfire mod
----------------------------------------------------------------------------------------------------------------------
--Kamp binder
----------------------------------------------------------------------------------------------------------------------
function add_to_binder(object, ini, scheme, section, storage)
local operators = {}
local properties = {}
local manager = object:motivation_action_manager()
properties["kamp_end"] = xr_evaluators_id.stohe_kamp_base + 1
properties["on_position"] = xr_evaluators_id.stohe_kamp_base + 2
properties["contact"] = xr_evaluators_id.stohe_meet_base + 1
operators["go_position"] = xr_actions_id.stohe_kamp_base + 1
operators["wait"] = xr_actions_id.stohe_kamp_base + 3
-- Evaluators
manager:add_evaluator (properties["kamp_end"], this.evaluator_kamp_end ("kamp_end", storage, "kamp_end"))
manager:add_evaluator (properties["on_position"], this.evaluator_on_position ("kamp_on_position", storage, "kamp_on_position"))
--printf("PRP %s", stalker_ids.property_script)
-- Actions
local action = this.action_wait (object:name(),"action_kamp_wait", storage)
action:add_precondition (world_property(stalker_ids.property_alive, true))
action:add_precondition (world_property(stalker_ids.property_danger,false))
action:add_precondition (world_property(stalker_ids.property_enemy, false))
action:add_precondition (world_property(stalker_ids.property_anomaly,false))
xr_motivator.addCommonPrecondition(action)
action:add_precondition (world_property(properties["on_position"], true))
action:add_effect (world_property(properties["kamp_end"], true))
manager:add_action (operators["wait"], action)
xr_logic.subscribe_action_for_events(object, storage, action)
action = this.action_go_position (object:name(),"action_go_kamp", storage)
action:add_precondition (world_property(stalker_ids.property_alive, true))
action:add_precondition (world_property(stalker_ids.property_danger,false))
action:add_precondition (world_property(stalker_ids.property_enemy, false))
action:add_precondition (world_property(stalker_ids.property_anomaly,false))
xr_motivator.addCommonPrecondition(action)
action:add_precondition (world_property(properties["on_position"], false))
action:add_effect (world_property(properties["on_position"], true))
manager:add_action (operators["go_position"], action)
action = manager:action (xr_actions_id.alife)
action:add_precondition (world_property(properties["kamp_end"], true))
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.center_point = utils.cfg_get_string(ini, section, "center_point", npc, true, gulag_name)
st.radius = utils.cfg_get_number(ini, section, "radius", npc, false, 2)
if kamps[st.center_point] == nil then
kamps[st.center_point] = CKampManager(st.center_point)
end
kamps[st.center_point]:addNpc(npc)
st.pos_vertex = nil
st.def_state_moving = utils.cfg_get_string(ini, section, "def_state_moving", npc, false, "", "walk")
end
lvl_objs = {}
local kamps_info = {}
local name_anom = ""
function con(msg)
get_console():execute(msg)
end
function is_anomaly_near_actor(name_anom,anomy,distance)
local iana = false
if anomy:position():distance_to(db.actor:position()) < distance then
iana = true
end
--[[
if name_anom == "mil_lager_kamp_1" then
iana = true
end
]]
return iana
end
function set_enable_anom(a,b,c,d)
kamps_info[a].timez = c + d
end
local timex = time_global()
set_enable_anom(self.kamp_name,obj,timex,5000)
if kamp_timez ~= nil then
if kamp_timez > time and kamp_timez_restart > time then
kamps_info[kamp_name].timez = nil
kamps_info[kamp_name].timez_restart = time + 10000
kamp_fire:enable_anomaly()
end
end
--[[
local kamp_restart = v.restart
local kamp_res_tim = v.restart_timer
local kamp_fired = v.fired or false
if is_anomaly_near_actor(i,kamp_fire,125) and not kamp_fired then
if i == "mil_lager_kamp_1" then
con("disable_an_anomaly")
con(i)
end
kamp_fire:disable_anomaly()
kamps_info[kamp_name].fired = true
kamps_info[kamp_name].restart = true
kamps_info[kamp_name].restart_timer = time + 5000
end
if kamp_restart then
if kamp_res_tim < time then
if i == "mil_lager_kamp_1" then
con("enable_an_anomaly")
con(i)
end
kamps_info[kamp_name].restart = nil
kamps_info[kamp_name].restart_timer = 0
kamp_fire:enable_anomaly()
end
end
if not is_anomaly_near_actor(i,kamp_fire,50) then
kamps_info[kamp_name].fired = false
end
Wheeljack napisał(a):Tylko nie pamiętam gdzie to jest, może w actor.ltx? Nawet nie mam przed sobą gamedaty żeby znaleźć.
function con(msg)
get_console():execute(msg)
end
function init (obj)
xr_motivator.AddToMotivator(obj)
end
function actor_init (npc)
npc:bind_object(actor_binder(npc))
end
local game_difficulty_by_num = {
[0] = "gd_novice",
[1] = "gd_stalker",
[2] = "gd_veteran",
[3] = "gd_master"
}
lasthealth = 0
lasttime = 0
post_process = 0
local weapon_hide = false
-->> Dynamic campfire mod
local scan_flag
local upd_time
--<< Dynamic campfire mod
----------------------------------------------------------------------------------------------------------------------
class "actor_binder" (object_binder)
----------------------------------------------------------------------------------------------------------------------
function actor_binder:__init (obj) super(obj)
self.bCheckStart = false
self.weather_manager = level_weathers.WeatherManager()
self.actor_detector = xr_detector.actor_detector()
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_spawn(data)
printf("actor net spawn")
level.show_indicators()
self.bCheckStart = true
self.weapon_hide = false -- спрятано или нет оружие при разговоре.
weapon_hide = false -- устанавливаем глобальный дефолтовый флаг.
if object_binder.net_spawn(self,data) == false then
return false
end
db.add_actor(self.object)
if self.st.disable_input_time == nil then
level.enable_input()
end
self.weather_manager:reset()
-- game_stats.initialize ()
if(actor_stats.add_to_ranking~=nil)then
actor_stats.add_to_ranking(self.object:id())
end
--' Загружаем настройки дропа
death_manager.init_drop_settings()
return true
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_destroy()
if(actor_stats.remove_from_ranking~=nil)then
actor_stats.remove_from_ranking(self.object:id())
end
-- game_stats.shutdown ()
db.del_actor(self.object)
sr_light.clean_up ()
self.object:set_callback(callback.inventory_info, nil)
self.object:set_callback(callback.article_info, nil)
self.object:set_callback(callback.on_item_take, nil)
self.object:set_callback(callback.on_item_drop, nil)
--self.object:set_callback(callback.actor_sleep, nil)
self.object:set_callback(callback.task_state, nil)
self.object:set_callback(callback.level_border_enter, nil)
self.object:set_callback(callback.level_border_exit, nil)
self.object:set_callback(callback.take_item_from_box, nil)
if sr_psy_antenna.psy_antenna then
sr_psy_antenna.psy_antenna:destroy()
sr_psy_antenna.psy_antenna = false
end
xr_sound.stop_all_sound_object()
object_binder.net_destroy(self)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:reinit()
object_binder.reinit(self)
local npc_id = self.object:id()
db.storage[npc_id] = { }
self.st = db.storage[npc_id]
self.st.pstor = nil
self.next_restrictors_update_time = -10000
self.object:set_callback(callback.inventory_info, self.info_callback, self)
self.object:set_callback(callback.article_info, self.article_callback, self)
self.object:set_callback(callback.on_item_take, self.on_item_take, self)
self.object:set_callback(callback.on_item_drop, self.on_item_drop, self)
self.object:set_callback(callback.trade_sell_buy_item, self.on_trade, self) -- for game stats
--self.object:set_callback(callback.actor_sleep, self.sleep_callback, self)
self.object:set_callback(callback.task_state, self.task_callback, self)
--self.object:set_callback(callback.map_location_added, self.map_location_added_callback, self)
self.object:set_callback(callback.level_border_enter, self.level_border_enter, self)
self.object:set_callback(callback.level_border_exit, self.level_border_exit, self)
self.object:set_callback(callback.take_item_from_box, self.take_item_from_box, self)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:take_item_from_box(box, item)
local story_id = box:story_id()
if story_id == nil then
return
end
treasure_manager.take_item_from_box(box, story_id)
--[[
local respawner = se_respawn.get_respawner_by_parent(story_id)
if respawner == nil then
return
end
--' Необходимо уменьшить счетчик в респавнере
respawner:remove_spawned(item:id())
local smart_terrain = db.strn_by_respawn[respawner:name()]
if smart_terrain == nil then
return
end
local npc = smart_terrain.gulag:get_nearest_online_obj(db.actor:position())
if npc ~= nil then
xr_sound.set_sound_play(npc, "reac_box")
xr_gulag.setGulagEnemy(smart_terrain:name() , db.actor)
end
]]
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:level_border_enter(npc, info_id)
self.actor_detector:actor_enter()
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:level_border_exit(npc, info_id)
self.actor_detector:actor_exit()
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:info_callback(npc, info_id)
printf("*INFO*: npc='%s' id='%s'", npc:name(), info_id)
--' Сюжет
level_tasks.proceed(self.object)
-- Отметки на карте
level_tasks.process_info_portion(info_id)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_trade (item, sell_bye, money)
if sell_bye == true then
game_stats.money_trade_update (money)
else
game_stats.money_trade_update (-money)
end
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:article_callback(npc, group, name)
--printf("article_callback [%s][%s]", group, name)
if device().precache_frame >1 then return end
if group == "Diary" then
news_manager.send_encyclopedy("diary", group)
else
news_manager.send_encyclopedy("encyclopedy", group)
end
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_item_take (obj)
level_tasks.proceed(self.object)
--game_stats.update_take_item (obj, self.object)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_item_drop (obj)
level_tasks.proceed(self.object)
-- NGC REPAIR MOD START
ngc_mod.itemuse(obj)
-- NGC REPAIR MOD END
use_mod_a.itemuse_mod(obj)
remove_item.remove_mod(obj)
--game_stats.update_drop_item (obj, self.object)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:task_callback(_task, _objective, _state)
task_manager.task_callback(_task:get_id(), _objective:get_idx(), _state)
if _objective:get_idx() == 0 then
if _state == task.fail then
news_manager.send_task(db.actor, "fail", _task, _objective)
elseif _state == task.completed then
task_manager.reward_by_task(_task)
news_manager.send_task(db.actor, "complete", _task, _objective)
else
news_manager.send_task(db.actor, "new", _task, _objective)
end
else
if _task:get_objective(0):get_state() == task.in_progress then
news_manager.send_task(db.actor, "update", _task, _objective)
end
end
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:map_location_added_callback(spot_type_str, object_id)
if (false==app_ready()) or (device().precache_frame>1) then return end
--'news_manager.send_task(db.actor, "new")
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:update(delta)
object_binder.update(self, delta)
-- DEBUG slowdown
-- slowdown.update()
local time = time_global()
game_stats.update (delta, self.object)
-- апдейт погоды
self.weather_manager:update()
-- апдейт схемы детектора
self.actor_detector:update()
-- апдейт звуковой схемы актера
xr_sound.update_actor()
--' Проверка потери жизни
--[[
if self.object.health - lasthealth > 0.001 or
self.object.health - lasthealth < -0.001 then
printf("%f | %f", self.object.health, self.object.health - lasthealth, game.time() - lasttime)
lasthealth = self.object.health
lasttime = game.time()
end
]]
-- Обновление отключения ввода с клавиатуры.
if self.st.disable_input_time ~= nil and
game.get_game_time():diffSec(self.st.disable_input_time) >= self.st.disable_input_idle
then
level.enable_input()
self.st.disable_input_time = nil
end
-- Обновление сна с переносом чувака в указанную позицию
if self.st.sleep_relocate_time ~= nil and
game.get_game_time():diffSec(self.st.sleep_relocate_time) >= self.st.sleep_relocate_idle
then
self.object:set_actor_position(self.st.sleep_relocate_point)
local dir = self.st.sleep_relocate_point:sub(self.st.sleep_relocate_look)
self.object:set_actor_direction(dir:getH())
self.st.sleep_relocate_time = nil
end
-- Апдейт прятание оружия игрока во время диалога
if weapon_hide == true or self.object:is_talking() then
if self.weapon_hide == false then
self.object:hide_weapon()
self.weapon_hide = true
end
else
if self.weapon_hide == true then
self.object:restore_weapon()
self.weapon_hide = false
end
end
-- обновление рестрикторов, которые под логикой, срабатывает через интервалы времени
if self.next_restrictors_update_time < time then
bind_restrictor.actor_update(delta)
self.next_restrictors_update_time = time + 200
task_manager.actor_update()
end
-- обновление постпроцессов
if post_process ~= 0 then
if post_process:update () == true then
post_process = 0
end
end
-- обновление пси-антенны
if sr_psy_antenna.psy_antenna then
sr_psy_antenna.psy_antenna:update(delta)
end
--' Вывод сообщения о большой радиации
if self.object.radiation >= 0.7 then
local hud = get_hud()
local custom_static = hud:GetCustomStatic("cs_radiation_danger")
if custom_static == nil then
hud:AddCustomStatic("cs_radiation_danger", true)
hud:GetCustomStatic("cs_radiation_danger"):wnd():SetTextST("st_radiation_danger")
end
else
local hud = get_hud()
local custom_static = hud:GetCustomStatic("cs_radiation_danger")
if custom_static ~= nil then
hud:RemoveCustomStatic("cs_radiation_danger")
end
end
if self.bCheckStart then
printf("SET DEFAULT INFOS")
if not has_alife_info("storyline_actor_start") and
(level.name() == "l01_escape")
then
self.object:give_info_portion("storyline_actor_start")
_G.g_start_avi = true
printf("*AVI* RUN START AVI")
end
-- if not has_alife_info("encyclopedy") then
-- self.object:give_info_portion("encyclopedy")
-- end
if not has_alife_info("global_dialogs") then
self.object:give_info_portion("global_dialogs")
end
if not has_alife_info("level_changer_icons") then
self.object:give_info_portion("level_changer_icons")
end
level_tasks.add_lchanger_location()
self.bCheckStart = false
end
if save_time == nil then
save_time = time + 30000
elseif save_time < time then
save_time = time + 30000
save_manager.autosave()
end
-->> Dynamic campfire mod
if scan_flag == nil then
scan_flag = 1
local lvl = level.name()
local exc_tbl = {
["zone_flame_small_0002"] = {"l05_bar"},
["zone_flame_small_0005"] = {"l06_rostok"},
["zone_flame_small_0006"] = {"l06_rostok"},
["zone_flame_small_0007"] = {"l06_rostok"},
["zone_flame_small_0008"] = {"l06_rostok"},
["zone_flame_small_0010"] = {"l06_rostok"},
["zone_flame_small_0012"] = {"l11_pripyat"},
["zone_flame_small_0013"] = {"l11_pripyat"},
["zone_flame_small_0024"] = {"l11_pripyat"},
["zone_flame_small_0025"] = {"l11_pripyat"},
["lights_camp_fire_omni_r1_r2_0002"] = {"l05_bar"},
["lights_camp_fire_omni_r1_r2_0011"] = {"l11_pripyat"},
["lights_camp_fire_omni_r1_r2_0012"] = {"l11_pripyat"},
["lights_camp_fire_omni_r1_r2_0031"] = {"l08_yantar"}
-- МОЖЕТ БЫТЬ ТАК: ["zone_flame_small_9999"] = {"l01_escapel02_garbagel05_barl07_military"},
-- МОЖЕТ БЫТЬ ТАК: ["lights_camp_fire_omni_r1_r2_9999"] = {"l01_escapel02_garbagel05_barl07_military"}
}
for id=1, 65535 do
local obj = level.object_by_id(id)
if obj then
local name = obj:name()
local exc_obj = exc_tbl[name]
if exc_obj and string.find(exc_obj[1], lvl) then
-- printf("EXEPTIONS: OBJ:[%s] LEVELS:[%s]", name, exc_obj[1])
else
if obj:section() == "zone_flame_small" then
table.insert(xr_kamp.lvl_objs, obj)
obj:disable_anomaly()
elseif string.find(name, "r1_r2") then
table.insert(xr_kamp.lvl_objs, obj)
obj:get_hanging_lamp():turn_off()
-- Масляные горелки (требуется доп. правка particles.xr)
-- elseif string.find(name, "light_gas") then
-- obj:get_hanging_lamp():turn_off()
end
end
end
end
end
if upd_time == nil then
upd_time = time + 500
elseif upd_time < time then
upd_time = time + 500
--con("DCM-upd_time")
xr_kamp.update(time)
end
--<< Dynamic campfire mod
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:save(packet)
local save_treasure_manager = true
printf("actor_binder:save(): self.object:name()='%s'", self.object:name())
object_binder.save(self, packet)
--' Сохраняем уровень сложности
if save_treasure_manager == true then
packet:w_u8(level.get_game_difficulty() + 128)
else
packet:w_u8(level.get_game_difficulty())
end
--' Сохраняем данные об отключенном вводе
if self.st.disable_input_time == nil then
packet:w_bool(false)
else
packer:w_bool(true)
utils.w_CTime(packet, self.st.disable_input_time)
end
xr_logic.pstor_save_all(self.object, packet)
self.weather_manager:save(packet)
sr_psy_antenna.save( packet )
if save_treasure_manager == true then
treasure_manager.save(packet)
end
task_manager.save(packet)
self.actor_detector:save(packet)
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:load(reader)
printf("actor_binder:load(): self.object:name()='%s'", self.object:name())
object_binder.load(self, reader)
printf("actor_binder:object_binder.load(): self.object:name()='%s'", self.object:name())
--' Загружаем уровень сложности
local game_difficulty = reader:r_u8()
local load_treasure_manager = false
if game_difficulty >= 128 then
game_difficulty = game_difficulty - 128
load_treasure_manager = true
end
get_console():execute("g_game_difficulty "..game_difficulty_by_num[game_difficulty])
if reader:r_eof() then
abort("SAVE FILE IS CORRUPT")
end
local stored_input_time = reader:r_u8()
if stored_input_time == true then
self.st.disable_input_time = utils.r_CTime(reader)
end
xr_logic.pstor_load_all(self.object, reader)
self.weather_manager:load(reader)
sr_psy_antenna.load(reader)
if load_treasure_manager == true then
treasure_manager.load(reader)
end
task_manager.load(reader)
self.actor_detector:load(reader)
end
----------------------------------------------------------------------------------------------------------------------
--старт префетча звуков
--if string.find(command_line(), "-noprefetch") == nil then
-- sound_prefetch.prefetch_sounds()
--end
-- Weapon functions
function hide_weapon()
weapon_hide = true
end
function restore_weapon()
weapon_hide = false
end
// this is test for section iteration
/**
local function test_section_iteration(file_name, section_name)
printf ("file : %s",file_name)
printf ("section : %s",section_name)
local file = ini_file(file_name)
local n = file:line_count(section_name)
printf ("lines : %d",n)
local id, value = "", "", result
for i=0,n-1 do
result, id, value = file:r_line(section_name,i,"","")
printf ("line %d : %s = %s",i,id,value)
end
end
test_section_iteration("system.ltx","space_restrictor")
/**/
lvl_objs = {}
local kamps_info = {}
local name_anom = ""
function con(msg)
get_console():execute(msg)
end
function is_anomaly_near_actor(name_anom,anomy,distance)
local iana = false
if anomy:position():distance_to(db.actor:position()) < distance then
iana = true
end
--[[
if name_anom == "mil_lager_kamp_1" then
iana = true
end
]]
return iana
end
function set_enable_anom(a,b,c,d)
kamps_info[a].timez = c + d
end
----------------------------------------------------------------------------------------------------------------------
-- Схема лагерь. Чудак(и) у костра.
-- автор: Диденко Руслан (Stohe)
-- TODO:
----------------------------------------------------------------------------------------------------------------------
function printf(fmt, ...)
-- local msg = string.format(fmt, ...)
-- local msg_no_ws = string.gsub(msg, "%s", "_")
-- get_console():execute("dbg:" .. msg_no_ws)
end
kamps = {}
kamp_stalkers = {} -- могут ли сталкеры в лагере юзаться игроком.
-- Объявления итераторов
local k,v,kk,vv = 0,0,0,0
---------------------------------------------------------------------------------------------------------------------
--Evaluators
----------------------------------------------------------------------------------------------------------------------
--' Условие завершения скрипта
class "evaluator_kamp_end" (property_evaluator)
function evaluator_kamp_end:__init(name, storage) super (nil, name)
self.a = storage
end
function evaluator_kamp_end:evaluate()
return not xr_logic.is_active(self.object, self.a)
end
--' Находимся ли мы на заданной позиции
class "evaluator_on_position" (property_evaluator)
function evaluator_on_position:__init(name, storage) super (nil, name)
self.a = storage
end
function evaluator_on_position:evaluate()
if self.object:level_vertex_id() == self.a.pos_vertex then
return true
end
return false
end
----------------------------------------------------------------------------------------------------------------------
--Actions
----------------------------------------------------------------------------------------------------------------------
--' Идет в заданную область
class "action_go_position" (action_base)
function action_go_position:__init (npc_name,action_name,storage) super (nil,action_name)
self.a = storage
end
function action_go_position:initialize()
action_base.initialize(self)
-- self.object:set_node_evaluator()
-- self.object:set_path_evaluator()
self.object:set_desired_position()
self.object:set_desired_direction()
self.a.pos_vertex = nil
end
function action_go_position:execute ()
action_base.execute (self)
if db.actor then
if xr_logic.try_switch_to_another_section(self.object, self.a, db.actor) then
return
end
end
local tmp_pos_vertex = kamps[self.a.center_point]:getDestVertex(self.object:id(), self.a.radius)
if self.a.pos_vertex ~= tmp_pos_vertex then
self.a.pos_vertex = tmp_pos_vertex
if not self.object:accessible(self.a.pos_vertex) then
--'printf("[%s] KAMP NODE NOT ACCESSIBLE. Get accessible nearest", self.object:name())
local ttp = vector():set(0,0,0)
self.a.pos_vertex = self.object:accessible_nearest(level.vertex_position(self.a.pos_vertex), ttp)
end
self.a.pp = patrol(self.a.center_point):level_vertex_id(0)
self.a.pp = level.vertex_in_direction(self.a.pp, vector():set(math.random(-1,1), 0, math.random(-1,1)), math.random(0,0.5))
self.object:set_dest_level_vertex_id(self.a.pos_vertex)
self.object:set_desired_direction(vector():sub(level.vertex_position(self.a.pp),level.vertex_position(self.a.pos_vertex)))
self.object:set_path_type(game_object.level_path)
state_mgr.set_state(self.object,"sprint",nil,nil,nil,{animation=true})
end
end
function action_go_position:finalize ()
action_base.finalize (self)
end
--' Просто сидит и втыкает
class "action_wait" (action_base)
function action_wait:__init (npc_name,action_name,storage) super (nil,action_name)
self.a = storage
end
function action_wait:initialize()
action_base.initialize(self)
-- self.object:set_node_evaluator()
-- self.object:set_path_evaluator()
self.object:set_desired_position()
self.object:set_desired_direction()
kamps[self.a.center_point]:increasePops(self.object)
end
function action_wait:activate_scheme()
end
function action_wait:execute()
action_base.execute (self)
if db.actor then
if xr_logic.try_switch_to_another_section(self.object, self.a, db.actor) then
return
end
end
local state, sound, substate = kamps[self.a.center_point]:updateNpc(self.object)
--' повернуть его лицом к центру
state_mgr.set_state(self.object, state, nil, nil, {look_position = level.vertex_position(self.a.pp)}, nil, nil, {subanim = substate})
xr_sound.set_sound(self.object, sound)
end
function action_wait:finalize()
kamps[self.a.center_point]:decreasePops(self.object)
action_base.finalize (self)
end
function action_wait:deactivate(npc)
kamps[self.a.center_point]:removeNpc(npc)
end
function action_wait:death_callback(npc)
kamps[self.a.center_point]:removeNpc(npc)
end
function action_wait:net_destroy(npc)
kamps[self.a.center_point]:decreasePops(self.object) --<< Dynamic campfire mod
kamps[self.a.center_point]:removeNpc(npc)
end
class "CKampManager"
function CKampManager:__init(path)
self.kamp_name = path
self.patrol = patrol(path)
self.center = self.patrol:level_vertex_id(0)
self.position = {{dir = vector():set(1, 0, 0), used = nil},
{dir = vector():set(1, 0, 1), used = nil},
{dir = vector():set(0, 0, 1), used = nil},
{dir = vector():set(-1, 0, 1), used = nil},
{dir = vector():set(-1, 0, 0), used = nil},
{dir = vector():set(-1, 0, -1),used = nil},
{dir = vector():set(0, 0, -1), used = nil},
{dir = vector():set(1, 0, -1), used = nil}}
self.npc = {}
self.population = 0
self.kamp_state = "idle"
-- Где то здесь распарсим патрульный путь и проапдейтим вектор позиций.
-- 0 вершина - центр лагеря.
-- 1 флаг - сектор занят, в поинте можно сидеть.
-- 2 флаг - сектор занят, в поинте нельзя сидеть.
for k = 1, self.patrol:count() - 1 do
-- если есть 1 или 2 флажок - отметить сектор как занятый
if self.patrol:flag(k,1) or
self.patrol:flag(k,2)
then
-- отметить сектор как занятый
for key,value in pairs(self.position) do
dir = vector():sub(level.vertex_position(self.patrol:level_vertex_id(k)), level.vertex_position(self.center))
if value.dir then
yaw = yaw_degree(dir, value.dir)
if yaw <=23 then
--'printf("KAMP node[%s], sector[%s,] yaw[%s]", k, key, yaw_degree(dir, value.dir))
value.used = -1
break
end
end
end
end
-- если есть 1 флажок - создать место для сидения в точке пути
if self.patrol:flag(k,1) then
-- создать точку для сидения
table.insert(self.position, {vertex = self.patrol:level_vertex_id(k)})
end
end
--print_table(self.position)
--Таблица соответствий состояния лагеря и допустимых анимаций и звуков.
self.avail_state = {idle = { directed = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
pre_harmonica = { directed = { "wait_harmonica"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
harmonica = { directed = { "play_harmonica"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
post_harmonica = { directed = { "wait_harmonica"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
pre_guitar = { directed = { "wait_guitar"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
guitar = { directed = { "play_guitar"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
post_guitar = { directed = { "wait_guitar"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
story = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
post_story = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
pre_joke = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
joke = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}},
post_joke = { directed = { "declarate"},
undirected = { "wait", "sit", "sit_ass", "sit_knee", "eat_kolbasa", "eat_vodka", "eat_energy", "eat_bread", "trans"}}}
self.avail_sound = {idle = { directed = "idle"},
pre_harmonica = { directed = "pre_harmonica", undirected = ""},
harmonica = { directed = "play_harmonica", undirected = ""},
post_harmonica = { directed = "", undirected = "reac_harmonica"},
pre_guitar = { directed = "pre_guitar", undirected = ""},
guitar = { directed = "play_guitar", undirected = ""},
post_guitar = { directed = "", undirected = "reac_guitar"},
story = { directed = "play_story", undirected = ""},
post_story = { directed = "", undirected = "reac_story"},
pre_joke = { directed = "pre_joke", undirected = ""},
joke = { directed = "play_joke", undirected = ""},
post_joke = { directed = "", undirected = "reac_joke"}}
-- Таблица таймаутов по состоянию. Если состояние установилось, то некоторое время оно не может быт изменено.
self.timeout = {idle = { min = 30000 },
pre_harmonica = { min = 3000 },
harmonica = { min = 5000, soundstart = true },
post_harmonica = { min = 3000 },
pre_guitar = { min = 3000 },
guitar = { min = 5000, soundstart = true },
post_guitar = { min = 3000 },
story = { min = 1000, soundstart = true },
post_story = { min = 3000 },
pre_joke = { min = 3000 },
joke = { min = 5000, soundstart = true },
post_joke = { min = 3000 }}
-- Таблица глобальных состояний лагеря.
self.kamp_states = { idle = true,
pre_harmonica = false, harmonica = false, post_harmonica = false,
pre_guitar = false, guitar = false, post_guitar = false,
story = false, post_story = false,
pre_joke = true, joke = true, post_joke = true}
-- Таблица допустимых переходов между состояниями с вероятностями.
self.trans_kamp = { idle = { idle = 0, pre_harmonica = 30, pre_guitar = 30, story = 0, pre_joke = 40 },
pre_harmonica = { harmonica = 100 },
harmonica = { post_harmonica = 100 },
post_harmonica = { idle = 70, harmonica = 30 },
pre_guitar = { guitar = 100 },
guitar = { post_guitar = 100 },
post_guitar = { idle = 70, guitar = 30 },
story = { post_story = 100 },
post_story = { idle = 100 },
pre_joke = { joke = 100 },
joke = { post_joke = 100 },
post_joke = { idle = 100 }}
-- Хранилище для режиссера лагеря. Режиссерем является сталкер, затеявший необычное поведение
self.director = nil
end
function CKampManager:selectPosition(npc_id)
-- создаем список доступных позиций
--printf("KAMP. [%s] called select position", npc_id)
local free = {}
for k,v in pairs(self.position) do
if v.used == nil then
table.insert(free, k)
end
end
--' затем из доступных позиций выбрать рандомно одну.
if table.getn(free) > 0 then
--printf("KAMP [%s] free node > 0", npc_id)
local rr = math.random(table.getn(free))
self.position[free[rr]].used = npc_id
self.npc[npc_id].position = free[rr]
end
--printf("KAMP [%s] npc table", npc_id)
--print_table(self.npc)
--printf("KAMP [%s] position table", npc_id)
--print_table(self.position)
end
function CKampManager:getDestVertex(npc_id, radius)
--printf("get dest Vertex called [%s]", npc_id)
if self.npc[npc_id].position == nil then
--printf("-------debug_info-------------")
--print_table(self.npc)
--printf("-------debug_info-------------")
--print_table(self.position)
--printf("-------debug_info-------------")
abort("get dest Vertex: nil [%s]", npc_id)
return nil
end
local position = self.position[self.npc[npc_id].position]
if position.vertex ~= nil then
--printf("vertex preselected [%s]", npc_id)
return position.vertex
end
-- высчитываем вертех по направлению
local pp = level.vertex_in_direction(self.center, self.position[self.npc[npc_id].position].dir, radius)
pp = level.vertex_in_direction(pp, vector():set(math.random(-1,1), 0, math.random(-1,1)), math.random(0,0.5))
--printf("vertex selected [%s]", npc_id)
return pp
end
function CKampManager:proceedState(npc)
-- Проверка на таймаут
local npc_id = npc:id()
local active_sound_count = npc:active_sound_count()
if self.npc[npc_id].need_sound_begin == true then
if active_sound_count == 0 then
return
else
self.npc[npc_id].need_sound_begin = false
end
end
if self.begin ~= nil and
time_global() - self.begin < self.timeout[self.kamp_state].min
then
return
end
-- Если режиссер не закончил говорить - ждем конца фразы.
if active_sound_count > 0 then
return
end
--printf("Proceed state for [%s]", npc_id)
-- В случае с историей переход обрабатывается отдельно
if self.kamp_state == "post_story" then
if self.story_last < self.story_max - 1 then
self.npc[npc_id].begin = nil
self.npc[npc_id].need_sound_begin = true
self.director = npc_id
self.kamp_state = "story"
self.begin = time_global()
for kk,vv in pairs(self.npc) do
vv.new = true
end
return
else
self.selected_story = nil
end
end
-- Определяются допустимые в данный момент переходы.
local temp = {}
local max_rnd = 0
for k,v in pairs(self.trans_kamp[self.kamp_state]) do
-- Определяются допустимые состояния для лагеря.
if self.kamp_states[k] == true then
temp[k] = v
max_rnd = max_rnd + v
end
end
-- Осуществляется рандомный взвешенный переход.
if max_rnd == 0 then
-- Если переходить некуда - переходим в айдл
temp["idle"] = 100
max_rnd = 100
end
local p = math.random(0,max_rnd)
for k,v in pairs(temp) do
p = p - v
if p <= 0 then
--printf("Selected [%s]", k)
if k == "idle" then
self.director = nil
if self.kamp_state ~= "idle" then
self.npc[npc_id].begin = nil
end
else
self.npc[npc_id].begin = nil
if self.timeout[k].soundstart == true then
self.npc[npc_id].need_sound_begin = true
end
self.director = npc_id
self.censor = nil
end
self.kamp_state = k
self.begin = time_global()
-- Меняем таймаут для истории
if k == "post_story" then
local dep = sound_theme.theme[self.selected_story].depence[self.story_last]
if dep and dep.min and dep.max then
self.timeout["post_story"].min = math.random(dep.min, dep.max)*1000
end
end
for kk,vv in pairs(self.npc) do
vv.new = true
end
return
end
end
end
function CKampManager:proceedRole(npc, director)
--printf("Proceed Role for [%s]", npc:id())
-- Определить список доступных анимаций по состоянию лагеря.
-- определить список доступных анимаций по наличию предметов
-- выбрать одну из них (то же самое со звуком).
local states = 0
local sound = ""
local state = ""
local npc_id = npc:id()
if self.npc[npc_id].begin == nil or
time_global() - self.npc[npc_id].begin >= self.npc[npc_id].state_idle
then
if director then
states = self.avail_state[self.kamp_state].directed
sound = self.avail_sound[self.kamp_state].directed
else
states = self.avail_state[self.kamp_state].undirected
sound = self.avail_sound[self.kamp_state].undirected
end
-- Выбирать новое состояние только раз в какое то время.
local temp = {}
for k,v in pairs(states) do
if self.npc[npc_id].states[v] == true then
table.insert(temp, v)
end
end
-- Если мы решили говорить историю, надо выбрать какую именно говорить.
if sound == "play_story" and self.selected_story == nil and db.story_by_id[npc_id] ~= nil then
local story_num = table.getn(db.story_by_id[npc_id])
if story_num > 0 then
self.selected_story = db.story_by_id[npc_id][math.random(story_num)]
end
end
self.npc[npc_id].begin = time_global()
state = temp[math.random(table.getn(temp))]
self.npc[npc_id].state_selected = state
self.npc[npc_id].state_idle = math.random(15000,20000)
else
if director then
sound = self.avail_sound[self.kamp_state].directed
else
sound = self.avail_sound[self.kamp_state].undirected
end
state = self.npc[npc_id].state_selected
end
--printf("Proceed Role state [%s] sound [%s]", state, sound)
return state, sound
end
function CKampManager:updateNpc(npc)
-- Проверка что сталкер может делать, а что нет.
self:checkNpcAbility(npc)
-- Просим лагерь выбрать текущее состояние. Менять состояние лагеря
-- имеет право только режиссер.
local npc_id = npc:id()
local director = self.director == nil or self.director == npc_id
if director then
self:proceedState(npc)
end
-- Говорим чудаку выбрать себе состояние для текущего состояния лагеря.
local state, sound = self:proceedRole(npc, director)
local substate = nil
if state == "wait_harmonica" then
if sound == "pre_harmonica" and self.npc[npc_id].new == true then
xr_sound.set_sound_play(npc, "intro_music", math.random(2000,3000))
self.npc[npc_id].new = false
end
state = "harmonica"
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "play_harmonica" then
state = "harmonica"
substate = 1
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "wait_guitar" then
if sound == "pre_guitar" and self.npc[npc_id].new == true then
xr_sound.set_sound_play(npc, "intro_music", math.random(2000,3000))
self.npc[npc_id].new = false
end
state = "guitar"
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "play_guitar" then
state = "guitar"
substate = 1
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "declarate" then
if self.npc[npc_id].new == true then
if sound == "pre_joke" then
xr_sound.set_sound_play(npc, "intro_joke", math.random(2000,3000))
elseif sound == "play_joke" then
xr_sound.set_sound_play(npc, "joke", math.random(2000,3000))
elseif sound == "play_story" then
xr_sound.set_sound_play(npc, self.selected_story)
self.story_last, self.story_max = xr_sound.get_last_IDS(npc, self.selected_story)
end
self.npc[npc_id].new = false
end
if npc:character_community() == "monolith" then
local t = math.mod(npc_id, 2)
if t == 0 then
state = "trans_0"
else
state = "trans_1"
end
elseif npc:character_community() == "zombied" then
state = "trans_zombied"
else
local t = math.mod(npc_id, 3)
if t == 0 then
state = "sit"
elseif t == 1 then
state = "sit_ass"
else
state = "sit_knee"
end
end
xr_kamp.kamp_stalkers[npc_id] = false
elseif state == "trans" then
if npc:character_community() == "monolith" then
local t = math.mod(npc_id, 2)
if t == 0 then
state = "trans_0"
else
state = "trans_1"
end
elseif npc:character_community() == "zombied" then
state = "trans_zombied"
end
xr_kamp.kamp_stalkers[npc_id] = false
else
xr_kamp.kamp_stalkers[npc_id] = true
end
-- Выбор реальных звуков
if sound == "idle" then
sound = "weather, state"
elseif sound == "reac_guitar" then
sound = "reac_music"
elseif sound == "reac_harmonica" then
sound = "reac_music"
elseif sound == "reac_joke" then
sound = ""
if self.npc[npc_id].new == true then
if self.censor == nil then
xr_sound.set_sound_play(npc, "reac_joke", math.random(2000,3000))
self.censor = npc_id
else
xr_sound.set_sound_play(npc, "story_reac_laughter", math.random(100,300))
end
self.npc[npc_id].new = false
end
elseif sound == "reac_story" then
sound = ""
if self.npc[npc_id].new == true then
local dep = sound_theme.theme[self.selected_story].depence[self.story_last+1]
if dep then
if dep.type == "all" then
xr_sound.set_sound_play(npc, dep.theme, math.random(100,300))
else
sound = dep.theme
end
end
end
elseif sound == "reac_story" then
sound = ""
else
sound = ""
end
--printf("Proceed Update Npc [%s] sound [%s]", state, sound)
return state, sound, substate
end
function CKampManager:checkNpcAbility(npc)
local npc_id = npc:id()
if npc:character_community() ~= "monolith" and
npc:character_community() ~= "zombied"
then
-- есть колбасу
if npc:object("kolbasa") then
self.npc[npc_id].states["eat_kolbasa"] = true
else
self.npc[npc_id].states["eat_kolbasa"] = false
end
-- пить водку
if npc:object("vodka") then
self.npc[npc_id].states["eat_vodka"] = true
else
self.npc[npc_id].states["eat_vodka"] = false
end
-- пить енергитический напиток
if npc:object("energy_drink") then
self.npc[npc_id].states["eat_energy"] = true
else
self.npc[npc_id].states["eat_energy"] = false
end
-- есть хлеб
if npc:object("bread") then
self.npc[npc_id].states["eat_bread"] = true
else
self.npc[npc_id].states["eat_bread"] = false
end
-- играть на гармошке
-- if npc:object("harmonica_a") then
-- self.npc[npc_id].states["play_harmonica"] = true
-- self.npc[npc_id].states["wait_harmonica"] = true
-- self.kamp_states["pre_harmonica"] = true
-- self.kamp_states["harmonica"] = true
-- self.kamp_states["post_harmonica"] = true
-- else
self.npc[npc_id].states["play_harmonica"] = false
self.npc[npc_id].states["wait_harmonica"] = false
self.kamp_states["pre_harmonica"] = false
self.kamp_states["harmonica"] = false
self.kamp_states["post_harmonica"] = false
-- end
-- играть на гитаре
if npc:object("guitar_a") then
self.npc[npc_id].states["play_guitar"] = true
self.npc[npc_id].states["wait_guitar"] = true
self.kamp_states["pre_guitar"] = true
self.kamp_states["guitar"] = true
self.kamp_states["post_guitar"] = true
else
self.npc[npc_id].states["play_guitar"] = false
self.npc[npc_id].states["wait_guitar"] = false
self.kamp_states["pre_guitar"] = false
self.kamp_states["guitar"] = false
self.kamp_states["post_guitar"] = false
end
-- анекдоты
if self.population > 1 then
self.kamp_states["pre_joke"] = true
self.kamp_states["joke"] = true
self.kamp_states["post_joke"] = true
else
self.kamp_states["pre_joke"] = false
self.kamp_states["joke"] = false
self.kamp_states["post_joke"] = false
end
end
-- Если чувак знает истории, надо добавить их к лагерю
--[[
if self.population > 1 and db.story_by_id[npc:id()] ~= nil then
self.kamp_states["story"] = true
self.kamp_states["post_story"] = true
else
self.kamp_states["story"] = false
self.kamp_states["post_story"] = false
end
]]
end
function CKampManager:addNpc(npc)
--printf("KAMP [%s] add npc", npc:name())
if self.npc[npc:id()] ~= nil then
--printf("NPC is already exist")
return
end
if npc:character_community() == "monolith" or
npc:character_community() == "zombied"
then
self.npc[npc:id()] = {name = npc:name(), position = nil, current = nil, speak = 0, states = {
stand_wait = false, sit = false, sit_ass = false, sit_knee = false, declarate = true,
eat_kolbasa = false, eat_vodka = false, eat_energy = false, eat_bread = false, trans = true,
play_harmonica = false, play_guitar = false, play_joke = false, play_story = false}}
else
self.npc[npc:id()] = {name = npc:name(), position = nil, current = nil, speak = 0, states = {
stand_wait = true, sit = true, sit_ass = true, sit_knee = true, declarate = true,
eat_kolbasa = false, eat_vodka = false, eat_energy = false, eat_bread = false, trans = false,
play_harmonica = false, play_guitar = false, play_joke = false, play_story = false}}
end
self:selectPosition(npc:id())
end
function CKampManager:removeNpc(npc)
--printf("KAMP [%s] remove npc", npc:name())
local npc_id = npc:id()
if self.npc[npc_id] ~= nil then
-- Если удаляем режиссера - необходимо форсированно перевести лагерь в идловое состояние.
if self.director == npc_id then
self.director = nil
self.npc[npc_id].begin = nil
self.censor = nil
self.kamp_state = "idle"
self.begin = time_global()
for kk,vv in pairs(self.npc) do
vv.new = true
end
xr_sound.set_sound(npc, nil)
stop_play_sound(npc)
end
self.position[self.npc[npc_id].position].used = nil
self.npc[npc_id] = nil
end
end
-->> Dynamic campfire mod
local camp_tbl = {
["esc2_st_fabric_kamp_1"] = {"zone_flame_small_0001", "lights_camp_fire_omni_r1_r2_0001"},
["esc_bridge_kamp_point"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0002"},
["esc_lager_camp_center"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0004"},
["esc_killers_kamp"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0004"},
["esc_blokpost_kamp"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["esc2_most_kamp_1"] = {"zone_flame_small_0006", "lights_camp_fire_omni_r1_r2_0006"},
["esc_assault_kamp_center1"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["esc_fabrika_bandit_camp_center"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["esc2_st_fabric_kamp_2"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["esc2_bandit_les_kamp_1"] = {"zone_flame_small_0008", "lights_camp_fire_omni_r1_r2_0008"},
["esc_stalker_camp_esc_fox_kamp"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["esc2_st_fox_place_kamp_1"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["esc_stalker_camp_camp_point"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["gar_angar_gar_seryi_kamp"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0003"},
["gar_smart_garage_kamp_1"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0003"},
["gar_smart_graveyard_kamp_1"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0004"},
["gar_bandit_agr_kamp_point1"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0004"},
["gar_bandit_agr_kamp_point"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0004"},
["gar_hellcar_group_kamp_point"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0004"},
["gar_smart_bandit_kamp_1"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0005"},
["gar_smart_stalkers_1_kamp_1"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0005"},
["gar_dolg_blokpost_kamp_point"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0006"},
["val_smart_bandit_2_kamp_2"] = {"zone_flame_small_0006", "lights_camp_fire_omni_r1_r2_0006"},
["val_smart_bandit_2_kamp_1"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["val_lager_bandits_kamp2"] = {"zone_flame_small_0010", "lights_camp_fire_omni_r1_r2_0010"},
["val_lager_bandits_kamp3"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["val_lager_bandits_kamp1"] = {"zone_flame_small_0012", "lights_camp_fire_omni_r1_r2_0012"},
["val_smart_bandit_1_kamp_1"] = {"zone_flame_small_0015", "lights_camp_fire_omni_r1_r2_0015"},
["val_rob_kamp"] = {"zone_flame_small_0015", "lights_camp_fire_omni_r1_r2_0015"},
["val_exit1_ambush_kamp_1"] = {"zone_flame_small_0017", "lights_camp_fire_omni_r1_r2_0017"},
["val_smart_bandit_3_kamp_1"] = {"zone_flame_small_0017", "lights_camp_fire_omni_r1_r2_0017"},
["bar_visitors_kamp_1"] = {"zone_flame_small_0000", "lights_camp_fire_omni_r1_r2_0000"},
["bar_visitors_kamp_2"] = {"zone_flame_small_0001", "lights_camp_fire_omni_r1_r2_0001"},
["bar_visitors_kamp_3"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["bar_dolg_general_kamp_center"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0003"},
["bar_visitors_kamp_4"] = {"zone_flame_small_0004", "lights_camp_fire_omni_r1_r2_0004"},
["ros_smart_stalker_bandits1_kamp_1"] = {"zone_flame_small_0000", "lights_camp_fire_omni_r1_r2_0000"},
["yan_st_stalker2_kamp_1"] = {"zone_flame_small_0008", "lights_camp_fire_omni_r1_r2_0008"},
["mil_monolit_kamp1"] = {"zone_flame_small_0000", "lights_camp_fire_omni_r1_r2_0000"},
["mil_fneutral_kamp"] = {"zone_flame_small_0000", "lights_camp_fire_omni_r1_r2_0000"},
["mil_monolit_kamp2"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0002"},
["mil_khutor_kamp_center"] = {"zone_flame_small_0003", "lights_camp_fire_omni_r1_r2_0003"},
["mil_smart_dolg_kamp_kamp_1"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["mil_dolg_camp_center"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["mil_village_kamp"] = {"zone_flame_small_0006", "lights_camp_fire_omni_r1_r2_0006"},
["mil_fblockpost_kamp"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["mil_monolit_kamp3"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["mil_lager_kamp_1"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["mil_mercs_kamp_1"] = {"zone_flame_small_0010", "lights_camp_fire_omni_r1_r2_0010"},
["mil_bandit_kamp_1"] = {"zone_flame_small_0011", "lights_camp_fire_omni_r1_r2_0011"},
["mil_freedom_camp_center1"] = {"zone_flame_small_0012", "lights_camp_fire_omni_r1_r2_0012"},
["rad_prip_teleport_kamp_center"] = {"zone_flame_small_0001", "lights_camp_fire_omni_r1_r2_0001"},
["rad2_prip_teleport_kamp_1"] = {"zone_flame_small_0001", "lights_camp_fire_omni_r1_r2_0001"},
["rad_valley_kamp"] = {"zone_flame_small_0002", "lights_camp_fire_omni_r1_r2_0002"},
["rad_entrance_kamp"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["rad2_prip_teleport_kamp_2"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["rad_mil_entrance_kamp_center"] = {"zone_flame_small_0005", "lights_camp_fire_omni_r1_r2_0005"},
["rad_prip_road_kamp_center"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["rad_freedom_vs_duty_kamp_center1"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["rad_freedom_vs_duty_kamp_center"] = {"zone_flame_small_0007", "lights_camp_fire_omni_r1_r2_0007"},
["rad2_loner_0001_kamp_1"] = {"zone_flame_small_0008", "lights_camp_fire_omni_r1_r2_0008"},
["rad2_loner_0002_kamp_1"] = {"zone_flame_small_0009", "lights_camp_fire_omni_r1_r2_0009"},
["rad_antenna_monolith_kamp"] = {"zone_flame_small_0010", "lights_camp_fire_omni_r1_r2_0010"},
["rad_antenna_patrol_kamp"] = {"zone_flame_small_0010", "lights_camp_fire_omni_r1_r2_0010"},
["rad2_loner_0000_kamp_1"] = {"zone_flame_small_0013", "lights_camp_fire_omni_r1_r2_0013"},
["pri_smart_monolith_stalker5_kamp_1"] = {"zone_flame_small_0018", "lights_camp_fire_omni_r1_r2_0005"},
["pri_smart_dolg_stalker1_kamp_1"] = {"zone_flame_small_0021", "lights_camp_fire_omni_r1_r2_0008"},
["pri_wave7_kamp_1"] = {"pri_zone_flame_small_0003", "pri_r1_r2_0001"},
["pri_sideway_left_kamp"] = {"pri_zone_flame_small_0043", "pri_r1_r2_00002"},
["pri_smart_freedom_stalker1_kamp_1"] = {"pri_zone_flame_small_0043", "pri_r1_r2_0002"},
["pri_smart_monolith_stalker4_kamp_1"] = {"pri_zone_flame_small_0044", "pri_r1_r2_0003"},
["pri_monolith_kamp2"] = {"pri_zone_flame_small_0026", "pri_r1_r2_0004"},
["pri_monolith_kamp3"] = {"pri_zone_flame_small_0021", "pri_r1_r2_0005"},
["pri_monolith_kamp5"] = {"pri_zone_flame_small_0045", "pri_r1_r2_0006"},
["pri_monolith_kamp7"] = {"pri_zone_flame_small_0000", "pri_r1_r2_0007"},
["pri_smart_monolith_stalker6_kamp_1"] = {"pri_zone_flame_small_0035", "pri_r1_r2_0008"}
}
function CKampManager:increasePops(npc)
self.population = self.population + 1
local camp_name = camp_tbl[self.kamp_name]
local timex = time_global()
if self.population == 1 and camp_name then
local flame = camp_name[1]
local light = camp_name[2]
-- kamps_info[self.kamp_name] = nil
-- if not kamps_info[self.kamp_name] then
kamps_info[self.kamp_name] = {}
kamps_info[self.kamp_name].time = timex
kamps_info[self.kamp_name].prtcl = nil
kamps_info[self.kamp_name].state = nil
-- end
for i,o in pairs(lvl_objs) do
local obj = o
if obj and obj:name() == flame then
kamps_info[self.kamp_name].obj_fire = obj
set_enable_anom(self.kamp_name,obj,timex,5000)
end
if obj and obj:name() == light then
kamps_info[self.kamp_name].obj_light = obj
end
end
end
end
function CKampManager:decreasePops(npc)
self.population = self.population - 1
local camp_name = camp_tbl[self.kamp_name]
if self.population < 1 and camp_name then
local flame = camp_name[1]
local light = camp_name[2]
-- if not kamps_info[self.kamp_name] then
kamps_info[self.kamp_name] = {}
kamps_info[self.kamp_name].time = time_global()
kamps_info[self.kamp_name].prtcl = particles_object("explosions\\explosion_01")
kamps_info[self.kamp_name].state = nil
-- end
for i,o in pairs(lvl_objs) do
local obj = o
if obj and obj:name() == flame then
kamps_info[self.kamp_name].obj_fire = obj
obj:disable_anomaly()
kamps_info[self.kamp_name].aenabled = false
end
if obj and obj:name() == light then
kamps_info[self.kamp_name].obj_light = obj
end
end
end
end
function update(time)
for i,v in pairs(kamps_info) do
local kamp_name = i
local kamp_fire = v.obj_fire
local kamp_light = v.obj_light
local kamp_time = v.time
local kamp_prtcl = v.prtcl
local kamp_state = v.state
local kamp_timez = v.timez
local kamp_aon = v.aenabled or false
if kamp_timez ~= nil then
if kamp_timez > time and not kamp_aon then
kamps_info[kamp_name].timez = nil
kamps_info[kamp_name].aenabled = true
kamp_fire:enable_anomaly()
end
end
--[[
local kamp_restart = v.restart
local kamp_res_tim = v.restart_timer
local kamp_fired = v.fired or false
if is_anomaly_near_actor(i,kamp_fire,125) and not kamp_fired then
if i == "mil_lager_kamp_1" then
con("disable_an_anomaly")
con(i)
end
kamp_fire:disable_anomaly()
kamps_info[kamp_name].fired = true
kamps_info[kamp_name].restart = true
kamps_info[kamp_name].restart_timer = time + 5000
end
if kamp_restart then
if kamp_res_tim < time then
if i == "mil_lager_kamp_1" then
con("enable_an_anomaly")
con(i)
end
kamps_info[kamp_name].restart = nil
kamps_info[kamp_name].restart_timer = 0
kamp_fire:enable_anomaly()
end
end
if not is_anomaly_near_actor(i,kamp_fire,50) then
kamps_info[kamp_name].fired = false
end
]]
end
end
--<< Dynamic campfire mod
----------------------------------------------------------------------------------------------------------------------
--Kamp binder
----------------------------------------------------------------------------------------------------------------------
function add_to_binder(object, ini, scheme, section, storage)
local operators = {}
local properties = {}
local manager = object:motivation_action_manager()
properties["kamp_end"] = xr_evaluators_id.stohe_kamp_base + 1
properties["on_position"] = xr_evaluators_id.stohe_kamp_base + 2
properties["contact"] = xr_evaluators_id.stohe_meet_base + 1
operators["go_position"] = xr_actions_id.stohe_kamp_base + 1
operators["wait"] = xr_actions_id.stohe_kamp_base + 3
-- Evaluators
manager:add_evaluator (properties["kamp_end"], this.evaluator_kamp_end ("kamp_end", storage, "kamp_end"))
manager:add_evaluator (properties["on_position"], this.evaluator_on_position ("kamp_on_position", storage, "kamp_on_position"))
--printf("PRP %s", stalker_ids.property_script)
-- Actions
local action = this.action_wait (object:name(),"action_kamp_wait", storage)
action:add_precondition (world_property(stalker_ids.property_alive, true))
action:add_precondition (world_property(stalker_ids.property_danger,false))
action:add_precondition (world_property(stalker_ids.property_enemy, false))
action:add_precondition (world_property(stalker_ids.property_anomaly,false))
xr_motivator.addCommonPrecondition(action)
action:add_precondition (world_property(properties["on_position"], true))
action:add_effect (world_property(properties["kamp_end"], true))
manager:add_action (operators["wait"], action)
xr_logic.subscribe_action_for_events(object, storage, action)
action = this.action_go_position (object:name(),"action_go_kamp", storage)
action:add_precondition (world_property(stalker_ids.property_alive, true))
action:add_precondition (world_property(stalker_ids.property_danger,false))
action:add_precondition (world_property(stalker_ids.property_enemy, false))
action:add_precondition (world_property(stalker_ids.property_anomaly,false))
xr_motivator.addCommonPrecondition(action)
action:add_precondition (world_property(properties["on_position"], false))
action:add_effect (world_property(properties["on_position"], true))
manager:add_action (operators["go_position"], action)
action = manager:action (xr_actions_id.alife)
action:add_precondition (world_property(properties["kamp_end"], true))
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.center_point = utils.cfg_get_string(ini, section, "center_point", npc, true, gulag_name)
st.radius = utils.cfg_get_number(ini, section, "radius", npc, false, 2)
if kamps[st.center_point] == nil then
kamps[st.center_point] = CKampManager(st.center_point)
end
kamps[st.center_point]:addNpc(npc)
st.pos_vertex = nil
st.def_state_moving = utils.cfg_get_string(ini, section, "def_state_moving", npc, false, "", "walk")
end
Użytkownicy przeglądający to forum: Brak zarejestrowanych użytkowników oraz 3 gości