max1071
04 gru 2016, 17:53
Regulamin forum
Dział "Tworzenie Modyfikacji" służy do zadawania pytań odnośnie tworzenia modyfikacji, edytowania plików gry, oraz pisania tzw. tutoriali, czyli poradników odnośnie modyfikowania gry.
Nie zadajemy tutaj pytań odnośnie modyfikacji gotowych (nie dyskutujemy o nich!), prócz prób ich połączenia etc.
Przy cytowaniu plików *.LTX stosować tag [SYNTAX="ini"], przy cytowaniu plików *.script [SYNTAX="lua"] a przy cytowaniu plików *.xml - [SYNTAX="xml"].
Nie zadajemy tutaj pytań odnośnie modyfikacji gotowych (nie dyskutujemy o nich!), prócz prób ich połączenia etc.
Przy cytowaniu plików *.LTX stosować tag [SYNTAX="ini"], przy cytowaniu plików *.script [SYNTAX="lua"] a przy cytowaniu plików *.xml - [SYNTAX="xml"].
Posty: 8• Strona 1 z 1
Witajcie.
Mam problem i potrzebuję moda na to by wyłączyć zadawanie obrażeń przez ogniska..
Mam problem i potrzebuję moda na to by wyłączyć zadawanie obrażeń przez ogniska..
Gdzieś kiedyś mi się migło, że ogniska są w plikach razem z anomaliami, ale jak to dokłanie było to nie pamiętam.
okej poszukam i dam znać jak to mi wyszło..
--------------------- edit 1 ------------
szukam szukam i nie mogę znaleźć
może możliwe jest po protu przesunięcie spawnu stalkerów od ogniska o np 2 (dwa) metry ??
------------- edit 2 -------------
znalazłem coś na jakimś forum że za ogniska odpowiada ten plik In gamedata\config\misc\zone_kampfire.ltx
załączam go tutaj
tylko że ja nawet nie wiem co właściwie edytować by ogniska nie zadawały obrażeń
albo zadawały tylko w małym stopniu..
------- edit 4 -------
można by było zrobić moda który po opuszczeniu danego obozowiska automatycznie by wyłączał to ognisko ?
------ edit 5 ---------
ściągnołem sobie moda na dynamics campfire co prawda na początku dobrze się zapowiadało ..
co prawda automatycznie włącza ogniska na mapie ale ich nie gasi ...
i jak wracam od bazy wolności w magazynach wojskowych koło wilka to go ten płomień z ogniska zabija
próbowałem edytować plik xr_campfire czy jakoś tak ... robiłem robiłem i nic co chwila crash czy coś ....
zaczeło nawet ładnie działać jak zrobiłem czy w danej odległości znajduje się gracz to znaczy obiekty przechodzą w stan online... to wtedy resetowało ognisko w sensie wyłączało z automatu jak byłem od niego na początku 20 nic nie dawało zginoł od razu, 50 to samo, 75 jak dobiegałem to akurat widziałem jak ginie mi na oczach, 125 i tutaj grało ok.. po pięciu(5) sekundach uruchamiało je ponownie.
do czasu jak wracasz z misji zabicia tych z Powinności w gospodarstwie.
załączam tego moda dynamics fire może i on się komuś przyda a nawet wykona mi jakieś zmiany czy jakoś pomoże w tym by ogarnąć te ogniska.
plik:
dodam jeszcze że nie wgrywałem folderu textures (nie widziałem potrzeby) i pliku particles.xr tylko zamieniłem 'particles_object("dyn_kfire\\dyingfire")' na 'particles_object("explosions\\explosion_01")'
a tutaj niektóre ścinki ze skryptu co wykonywałem ..
może jeszce komuś cos z tego uda się wykrzesać :C
prosżę pomagicie :C
--------------------- edit 1 ------------
szukam szukam i nie mogę znaleźć
może możliwe jest po protu przesunięcie spawnu stalkerów od ogniska o np 2 (dwa) metry ??
------------- edit 2 -------------
znalazłem coś na jakimś forum że za ogniska odpowiada ten plik In gamedata\config\misc\zone_kampfire.ltx
załączam go tutaj
Kod: Zaznacz cały
[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 = offalbo zadawały tylko w małym stopniu..
------- edit 4 -------
można by było zrobić moda który po opuszczeniu danego obozowiska automatycznie by wyłączał to ognisko ?
------ edit 5 ---------
ściągnołem sobie moda na dynamics campfire co prawda na początku dobrze się zapowiadało ..
co prawda automatycznie włącza ogniska na mapie ale ich nie gasi ...
i jak wracam od bazy wolności w magazynach wojskowych koło wilka to go ten płomień z ogniska zabija
próbowałem edytować plik xr_campfire czy jakoś tak ... robiłem robiłem i nic co chwila crash czy coś ....
zaczeło nawet ładnie działać jak zrobiłem czy w danej odległości znajduje się gracz to znaczy obiekty przechodzą w stan online... to wtedy resetowało ognisko w sensie wyłączało z automatu jak byłem od niego na początku 20 nic nie dawało zginoł od razu, 50 to samo, 75 jak dobiegałem to akurat widziałem jak ginie mi na oczach, 125 i tutaj grało ok.. po pięciu(5) sekundach uruchamiało je ponownie.
do czasu jak wracasz z misji zabicia tych z Powinności w gospodarstwie.
załączam tego moda dynamics fire może i on się komuś przyda a nawet wykona mi jakieś zmiany czy jakoś pomoże w tym by ogarnąć te ogniska.
plik:
Kod: Zaznacz cały
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")
enda tutaj niektóre ścinki ze skryptu co wykonywałem ..
Kod: Zaznacz cały
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
endprosżę pomagicie :C
Jeżeli zależy Ci na przeżyciu Wilka to do czasu aż wyjdzie z ogniska możesz zwiększyć odporność npc na obrażenia zadawane przez ogień. Tylko nie pamiętam gdzie to jest, może w actor.ltx? Nawet nie mam przed sobą gamedaty żeby znaleźć.
I na drugi raz dla kodu użyj
I na drugi raz dla kodu użyj
Kod: Zaznacz cały
zamiast spojlera, poprawiłem.Jak sama nazwa wskazuje, actor.ltx jest plikiem definiującym cechy gracza, a nie jakiegokolwiek NPCWheeljack pisze:Tylko nie pamiętam gdzie to jest, może w actor.ltx? Nawet nie mam przed sobą gamedaty żeby znaleźć.
Proszę państwa, sto pięćdziesiąt kilometrów na godzinę w ciągu kilku sekund, wspaniały wynik. Gdyby w ten sposób można było wypie*dolić z polskiej polityki tych wszystkich śmieci z Okrągłego Stołu, Leszka Millera, byłoby… cudownie i każdemu bym ku*wa kupił po takim Ferrari, byleby w piz*u pojechali tym PROSTO do swojego ukochanego… Izraela. SYJONIŚCI Europy, jedźcie do siebie! Pozdrawiam, Zbigniew Stonoga. Nie jestem antysemitą!
Chłopcy a nie lepiej powiedzieć mu jak zmienić trasę przejścia Wilka?
Zwiększenie wytrzymałości Wilka nic nie da bo i tak czasem utknie na dobre w ognisku i prędzej czy później go sfajczy.
Lizać stópki, niuchać stópki, wielbić stópki.
W zone_kampfire.ltx znajduje się sekcja "zone_flame_small". Odszukaj ją, a potem linijki "min_start_power" i "max_start_power". Następnie wyzeruj je tzn. ustaw wartości na 0.00. Powinno zadziałać.
@Alchemik, zmiana trasy wymaga grzebania w spawnie, co jest jeszcze trudniejsze niż zmiana configu.
@Alchemik, zmiana trasy wymaga grzebania w spawnie, co jest jeszcze trudniejsze niż zmiana configu.
Postawili kozaka za ten post (1):
Dzięki stalkiery 
zrobiłem małe coś ale niestety czasem krzaczy się nie wiem z jakiego powodu ale musi być dość poważny bo nawet loga nie zapisuje
otóż zrobiłem znowu ten timeout na 5 sekund po zrespieniu się danej postaci koło ogniska (ognisko wyłączone) po 5 sekundach ognisko się zapala. ( set_enable_anom(self.kamp_name,obj,timex,5000))
to odpowiada za włączenie po tych pięcu sekundach:
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
po ilości (self.population < 1) wyłącza ognisko (obj.disable_anomaly())
obj:disable_anomaly()
kamps_info[self.kamp_name].aenabled = false
daję skrypty tutaj ponieważ działa a krzaczy .. jak to wheeljack powiedział w code nie w spojla
bind_stalker.script:
xr_kamp.script:
zrobiłem małe coś ale niestety czasem krzaczy się nie wiem z jakiego powodu ale musi być dość poważny bo nawet loga nie zapisuje
otóż zrobiłem znowu ten timeout na 5 sekund po zrespieniu się danej postaci koło ogniska (ognisko wyłączone) po 5 sekundach ognisko się zapala. ( set_enable_anom(self.kamp_name,obj,timex,5000))
to odpowiada za włączenie po tych pięcu sekundach:
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
po ilości (self.population < 1) wyłącza ognisko (obj.disable_anomaly())
obj:disable_anomaly()
kamps_info[self.kamp_name].aenabled = false
daję skrypty tutaj ponieważ działa a krzaczy .. jak to wheeljack powiedział w code nie w spojla
bind_stalker.script:
Kod: Zaznacz cały
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")
/**/
Kod: Zaznacz cały
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
Posty: 8• Strona 1 z 1

