· 4 years ago · Apr 13, 2021, 02:38 PM
1
2--[[
3 itms_manager
4 by Alundaio
5
6 Copyright (C) 2012 Alundaio
7 This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
8
9 Modified by Tronex:
10 2018/7/18 - Added support for new usable items (maps,craft)
11 2018/7/21 - Added the ability to gather/separate muti-use items
12 2018/7/26 - Added the ability to disassemble misc items
13 2018/7/26 - Rewrote a lot of function with better codes
14 2018/7/31 - Added new items, battery consumption for geiger counter and gps tracker
15 2018/8/2 - Drag artefacts on containers to put them in, container tool is no longer used
16 2019/2/16 - Organized the items in tables for global use
17 2019/9/19 - Bolt count manager
18 2020/3/18 - Cleaning
19--]]
20
21-- local uses = obj:get_remaining_uses()
22-- local max_uses = obj:get_max_uses()
23-- obj:set_remaining_uses(num)
24
25
26-- Prepare ini files
27ini_manager = ini_file("items\\settings\\itms_manager.ltx")
28ini_container = ini_file("items\\settings\\arty_container.ltx")
29ini_parts = ini_file("items\\settings\\parts.ltx")
30ini_craft = ini_file("items\\settings\\craft.ltx")
31ini_death = ini_file("items\\settings\\death_generic.ltx")
32ini_reward = ini_file("items\\settings\\item_rewards.ltx")
33
34local n = 0
35local result,id,value = "","",""
36local string_find = string.find
37local string_gsub = string.gsub
38
39-- Collect item sections of main tools
40itms_arty_container = utils_data.collect_section(ini_container,"containers",true) or {}
41
42local empty_syringe_items = {}
43n = ini_manager:line_count("empty_syringe_items")
44for i=0,n-1 do
45 result, id, value = ini_manager:r_line_ex("empty_syringe_items",i,"","")
46 if ini_sys:section_exist(id) then
47 empty_syringe_items[id] = true
48 end
49end
50
51item_rewards = {}
52ini_reward:section_for_each(function(section)
53 if (not item_rewards[section]) then
54 item_rewards[section] = {}
55 end
56
57 n = ini_reward:line_count(section)
58 for i=0,n-1 do
59 result, id, value = ini_reward:r_line_ex(section,i,"","")
60 if ini_sys:section_exist(id) then
61 item_rewards[section][id] = ini_sys:r_float_ex(id,"tier") or 1
62 end
63 end
64end)
65
66item_combine = {}
67n = ini_craft:line_count("item_combination")
68for i=0,n-1 do
69 result, id, value = ini_craft:r_line_ex("item_combination",i,"","")
70 if id and value then
71 local str = str_explode(id,":")
72 if str[1] and str[2] and ini_sys:section_exist(str[1]) and ini_sys:section_exist(str[2]) and ini_sys:section_exist(value) then
73 if (not item_combine[str[1]]) then
74 item_combine[str[1]] = {}
75 end
76 item_combine[str[1]][str[2]] = value
77 else
78 printe("!ERROR item_combination | wrong section names")
79 end
80 end
81end
82
83
84-------------------------------
85-- CALLBACKS
86-------------------------------
87function on_game_start()
88 RegisterScriptCallback("actor_on_item_before_use",actor_on_item_before_use)
89 RegisterScriptCallback("actor_on_first_update",actor_on_first_update)
90 RegisterScriptCallback("actor_on_item_drop",actor_on_item_drop)
91 RegisterScriptCallback("actor_on_item_use",actor_on_item_use)
92 RegisterScriptCallback("actor_on_item_take",actor_on_item_take)
93 RegisterScriptCallback("ActorMenu_on_item_drag_drop",ActorMenu_on_item_drag_drop)
94 RegisterScriptCallback("ActorMenu_on_item_focus_receive",ActorMenu_on_item_focus_receive)
95 RegisterScriptCallback("save_state",save_state)
96end
97
98local old_booster = {}
99local boost_min = 0.00005
100local booster_string = {
101 ["pwr"] = "ui_inv_power",
102 ["psy"] = "ui_inv_outfit_telepatic_protection",
103 ["bld"] = "ui_inv_bleeding",
104 ["hp"] = "ui_inv_health",
105 ["rad"] = "ui_inv_radiation",
106}
107function actor_on_item_before_use(obj,flags)
108 local sec = obj:section()
109
110 -- no need to check for tools
111 if IsItem("tool",sec) then
112 --printf("- actor_on_item_before_use [%s] | ignore utility item", sec)
113 flags.ret_value = true
114 return
115 end
116
117 local curr_booster = {}
118 local time_g = time_global()
119 local str = ""
120 local pass = true
121
122 -- read important boosts
123 local period = ini_sys:r_float_ex(sec, "boost_time") or 0
124 local rad_boost = ini_sys:r_float_ex(sec, "boost_radiation_restore") or 0
125 local psy_boost = ini_sys:r_float_ex(sec, "boost_telepat_protection") or 0
126 local bld_boost = ini_sys:r_float_ex(sec, "boost_bleeding_restore") or 0
127 local hp_boost = ini_sys:r_float_ex(sec, "boost_health_restore") or 0
128 local pwr_boost = ini_sys:r_float_ex(sec, "boost_power_restore") or 0
129
130 -- if an item is required
131 local require_tool = ini_sys:r_string_ex(sec, "required_tool")
132 local obj_tool = require_tool and ini_sys:section_exist(require_tool) and db.actor:object(require_tool)
133
134 -- store boosts in a table
135 curr_booster["section"] = sec
136 curr_booster["period"] = (period > 0) and (time_g + period*1000) or time_g
137 curr_booster["pwr"] = (pwr_boost > boost_min) and pwr_boost or 0
138 curr_booster["psy"] = (psy_boost > boost_min) and psy_boost or 0
139 curr_booster["bld"] = (bld_boost > boost_min) and bld_boost or 0
140 curr_booster["hp"] = (hp_boost > boost_min) and hp_boost or 0
141 curr_booster["rad"] = (rad_boost > boost_min) and rad_boost or 0
142
143 -- A required tool is missing -> no eat
144 if require_tool and (not obj_tool) then
145 --printf("~ actor_on_item_before_use [%s] | require_tool [%s] is missing", sec, require_tool)
146 str = strformat(game.translate_string("st_itm_manager_missing_requirements"), ui_item.get_sec_name(require_tool))
147 pass = false
148
149 -- older booster is still active
150 elseif old_booster["period"] and (old_booster["period"] > time_g) then
151 --printf("~ actor_on_item_before_use [%s] | older booster [%s] is still active", sec, old_booster['section'])
152 local weaker_effect
153 local stronger_effect
154 for k,v in pairs(curr_booster) do
155 if (k ~= "section") and (k ~= "period") then
156 local v2 = old_booster[k]
157 if v2 and (v > boost_min) and (v2 > boost_min) then
158 if (v <= v2) then
159 weaker_effect = k
160 else
161 stronger_effect = k
162 end
163 elseif (v2 == 0) and (v > boost_min) then
164 stronger_effect = k
165 end
166 end
167 end
168
169 -- older booster has some stronger effect, while new one doesn't have any stronger effect
170 if weaker_effect and (not stronger_effect) then
171 --printf("~ actor_on_item_before_use [%s] | older booster [%s] has stronger effect: %s", sec, old_booster['section'], weaker_effect)
172 local boost_str = game.translate_string(booster_string[weaker_effect])
173 str = strformat(game.translate_string("st_itm_manager_greater_effect"),boost_str)
174 pass = false
175 end
176 -- prevent player to take anabiotic during combat
177 elseif sec == "drug_anabiotic" then
178 if (not is_empty(xr_combat_ignore.fighting_with_actor_npcs)) then
179 str = game.translate_string("st_anabiotic_combat")
180 pass = false
181 end
182 end
183
184 -- to eat or not to eat
185 if pass then
186 --printf("- actor_on_item_before_use [%s] | pass = true", sec)
187 flags.ret_value = true
188 copy_table(old_booster, curr_booster)
189 if obj_tool then
190 utils_item.discharge(obj_tool)
191 end
192 else
193 --printf("! actor_on_item_before_use [%s] | pass = false", sec)
194 flags.ret_value = false
195 --alife_release(obj)
196 --alife_create_item(sec,db.actor)
197
198 utils_xml.hide_menu()
199 actor_menu.set_msg(1, str,3)
200 end
201end
202
203function actor_on_first_update()
204
205 -- Delete base pda
206 local sim = alife()
207 local obj, se_obj
208 --[[
209 for i=1,65534 do
210 se_obj = sim:object(i)
211 if se_obj and (se_obj:section_name() == "device_pda") then
212 sim:release(se_obj,true)
213 end
214 end
215 --]]
216
217 -- Delete animation items on actor
218 for sec,_ in pairs(GetItemList("release")) do
219 obj = db.actor:object(sec)
220 if obj then
221 alife_release(obj)
222 end
223 end
224
225 -- Spawn bolts
226 local m_data = alife_storage_manager.get_state()
227 local bolt_first = m_data.bolt_first
228 if bolt_first then
229 alife_create_item(bolt_first, db.actor)
230 m_data.bolt_first = nil
231 end
232
233 local bolt_slot = m_data.bolt_slot
234 if bolt_slot then
235 alife_create_item(bolt_slot, db.actor)
236 end
237
238 local bolts = m_data.bolts
239 if bolts then
240 for sec,cnt in pairs(bolts) do
241 for i=1,cnt do
242 alife_create_item(sec, db.actor)
243 end
244 end
245 end
246
247 -- Damage equipment
248 if (not has_alife_info("start_equippment_handled")) and (not IsTestMode()) then
249 CreateTimeEvent(0,"delay_new_game_autosave",4,new_game_equippment)
250 end
251
252 -- Bolt manager
253 CreateTimeEvent("cycle","bolt_manager",60,bolt_manager)
254end
255
256function actor_on_item_drop(obj)
257 if not (obj) then
258 return
259 end
260
261 if (db.actor:has_info("actor_made_wish_for_riches")) then
262 db.actor:transfer_item(obj,db.actor)
263 elseif IsWeapon(obj) then
264 se_save_var(obj:id(), nil, "strapped_item", obj:condition())
265 end
266end
267
268function actor_on_item_use(obj)
269 if (db.actor:has_info("actor_made_wish_for_riches")) then
270 return
271 end
272
273 local sec = obj:section()
274
275
276 -- Strelok Notes
277 if (sec == "mlr_strelok_item_01") then
278 txr_routes.open_route("val","x18")
279 return
280
281 -- Deployable mgun
282 elseif (sec == "itm_deployable_mgun") then
283 use_deployable_mgun(obj)
284 return
285
286 -- Watch
287 elseif (sec == "hand_watch") then
288 use_watch(obj)
289 return
290
291 -- Chocolate Bar
292 elseif (sec == "chocolate") then
293 alife_create_item("chocolate_p", db.actor)
294 return
295
296 -- Bolts pack
297 elseif (sec == "bolts_pack") then
298 local bolts = {}
299 local n = math.random(20,30)
300 for i=1,n do
301 local actor = db.actor
302 if math.random(1,100) > 50 then
303 bolts[#bolts + 1] = "bolt"
304 else
305 bolts[#bolts + 1] = "bolt_bullet"
306 end
307 end
308 utils_item.delay_event(bolts, nil, "bolts_pack", false, 5)
309 return
310
311 -- give empty syringe on using some medical items
312 elseif empty_syringe_items[sec] then
313 alife_create_item("e_syringe", db.actor)
314
315 -- weather radar
316 elseif (sec == "device_weather_radar") then
317 ui_debug_weather.activate()
318 return
319 end
320
321 -- don't discharge items with no removal
322 if IsItem("multiuse_r",sec) then
323 local uses = obj:get_remaining_uses()
324 local max_uses = obj:get_max_uses()
325 if uses and max_uses and (uses < max_uses) then
326 obj:set_remaining_uses(uses + 1)
327 end
328 end
329end
330
331local str_itm_taken = game.translate_string("st_item_taken")
332function actor_on_item_take(obj)
333 local sec = obj:section()
334
335 -- Play sound effect for item taking
336 play_item_sound(obj)
337
338 if IsWeapon(obj) and se_load_var(item_id, nil, "strapped_item") then
339 se_save_var(obj:id(), nil, "strapped_item", nil)
340
341 -- Explosive barrels
342 elseif (sec == "explosive_mobiltank") or (sec == "explosive_tank") then
343 local se_obj = alife_object(obj:id())
344 local fuel = tostring(math.random(6,8))
345 if se_obj then
346 alife_release(se_obj)
347 alife_create_item("explo_jerrycan_fuel", db.actor, {uses = 2})
348 end
349
350 -- Story special
351 elseif (sec == "main_story_1_quest_case") and (not has_alife_info("agr_u_bloodsucker_on_case")) then
352 db.actor:give_info_portion("agr_u_bloodsucker_on_case")
353 xr_effects.create_squad(nil,nil,{"agr_u_bloodsucker_3_squad","agr_u_bloodsucker"})
354 end
355
356 -- Show notification
357 --local str = strformat(str_itm_taken, ui_item.get_sec_name(sec))
358 --actor_menu.set_msg(2, str)
359end
360
361function dropdrop_ArtyContainer(obj_1, obj_2, sec_1, sec_2) -- Put artefact in container
362 local cont = sec_2
363 local arty = sec_1
364 if ini_sys:section_exist(arty .. "_" .. cont) then
365 local cond = obj_1 and obj_1:condition()
366
367 actor_effects.play_item_fx("container_tool_" .. cont .. "_dummy")
368
369 alife_create_item(arty .. "_" .. cont, db.actor, { cond = cond } )
370 alife_release(obj_1)
371 alife_release(obj_2)
372 end
373end
374function dropdrop_Basic_Combination(obj_1, obj_2, sec_1, sec_2) -- Combine basic items
375 local sec_new = item_combine[sec_1][sec_2]
376 actor_effects.play_item_fx("item_combination")
377 alife_create_item(sec_new, db.actor)
378 alife_release(obj_1)
379 alife_release(obj_2)
380end
381function ActorMenu_on_item_drag_drop(obj_1, obj_2, slot_from, slot_to)
382
383 -- Check capability
384 if not (slot_from == EDDListType.iActorBag and slot_to == EDDListType.iActorBag) then
385 return
386 end
387
388 local sec_1 = obj_1:section()
389 local sec_2 = obj_2:section()
390
391 if itms_arty_container[sec_2] then
392 if (ini_sys:r_string_ex(sec_1,"class") == "ARTEFACT") or (ini_sys:r_string_ex(sec_1,"class") == "SCRPTART") then
393 dropdrop_ArtyContainer(obj_1, obj_2, sec_1, sec_2)
394 end
395
396 elseif item_combine[sec_1] and item_combine[sec_1][sec_2] then
397 dropdrop_Basic_Combination(obj_1, obj_2, sec_1, sec_2)
398 end
399end
400
401local focus_last_sec
402local focus_tbl = {}
403local focus_upgr = {}
404function ActorMenu_on_item_focus_receive(obj) -- highlight compatible items
405 --[[
406 local parent = obj:parent()
407 if not (parent and parent:id() == AC_ID) then
408 return
409 end
410 --]]
411
412 local sec_focus = obj:section()
413 if (focus_last_sec ~= sec_focus) then
414 local id = obj:id()
415 focus_last_sec = sec_focus
416 empty_table(focus_tbl)
417
418 local parent_sec = ini_sys:r_string_ex(sec_focus,"parent_section") or sec_focus
419
420 -- For weapons
421 if IsWeapon(obj) then
422
423 -- Ammo
424 local ammo = utils_item.get_ammo(sec_focus, id)
425 for i=1,#ammo do
426 focus_tbl[#focus_tbl + 1] = ammo[i]
427 end
428
429 -- Scopes
430 local scopes = parse_list(ini_sys, parent_sec, "scopes")
431 for i=1,#scopes do
432 focus_tbl[#focus_tbl + 1] = scopes[i]
433 end
434
435 local scope = utils_item.get_wpn_param(obj, sec_focus, "scopes_sect")
436 if scope and (obj:weapon_scope_status() == 2) then
437 focus_tbl[#focus_tbl + 1] = scope
438 end
439
440 -- Silencer
441 local sil = utils_item.get_wpn_param(obj, sec_focus, "silencer_name")
442 if sil and (obj:weapon_silencer_status() == 2) then
443 focus_tbl[#focus_tbl + 1] = sil
444 end
445
446 -- Grenade Launcher
447 local gl = utils_item.get_wpn_param(obj, sec_focus, "grenade_launcher_name")
448 if gl and (obj:weapon_grenadelauncher_status() == 2) then
449 focus_tbl[#focus_tbl + 1] = gl
450 end
451 end
452
453 -- Parts
454 local parts_str = ini_parts:r_string_ex("con_parts_list",parent_sec)
455 local parts = parts_str and (parts_str ~= "") and str_explode(parts_str,",")
456 if parts then
457 for i=1,#parts do
458 focus_tbl[#focus_tbl + 1] = parts[i]
459 end
460 end
461
462 -- Repair kits
463 local repair_type = ini_sys:r_string_ex(parent_sec,"repair_type")
464 if repair_type and repair_type ~= "" then
465 for kit,v in pairs(GetItemList("repair")) do
466 if v[repair_type] then
467 focus_tbl[#focus_tbl + 1] = kit
468 end
469 end
470 --[[
471 for kit,v in pairs(GetItemList("workshop")) do
472 if v[repair_type] then
473 focus_tbl[#focus_tbl + 1] = kit
474 end
475 end
476 --]]
477 end
478
479 -- Upgrade parts
480 local upgr_str = ini_sys:r_string_ex(parent_sec,"upgrades")
481 if upgr_str and upgr_str ~= "" then
482 if (not focus_upgr[parent_sec]) then
483 local upgr = parse_list(ini_sys,parent_sec,"upgrades")
484 focus_upgr[parent_sec] = {}
485 for i=1,#upgr do
486 extract_upgr_tools(focus_upgr[parent_sec], upgr[i])
487 end
488 end
489 for tool,_ in pairs(focus_upgr[parent_sec]) do
490 --printf("- upgrade part for [%s] -> [%s]", parent_sec, tool)
491 focus_tbl[#focus_tbl + 1] = tool
492 end
493 end
494
495 end
496
497 local inventory = GetActorMenu()
498 if not ((#focus_tbl > 0) or (inventory and inventory:IsShown())) then
499 return
500 end
501
502 for i=1,#focus_tbl do
503 inventory:highlight_section_in_slot(focus_tbl[i],EDDListType.iActorBag)
504 inventory:highlight_section_in_slot(focus_tbl[i],EDDListType.iPartnerTradeBag)
505 inventory:highlight_section_in_slot(focus_tbl[i],EDDListType.iDeadBodyBag)
506 inventory:highlight_section_in_slot(focus_tbl[i],EDDListType.iActorTrade)
507 inventory:highlight_section_in_slot(focus_tbl[i],EDDListType.iPartnerTrade)
508 end
509end
510
511function save_state(m_data) --// NOTE: bolts aren't saved in alife, so this is a temp solution
512 local bolts = {}
513 local function itr(obj)
514 local sec = obj:section()
515 if (sec == "bolt") or (sec == "bolt_bullet") then
516 if (not bolts[sec]) then
517 bolts[sec] = 0
518 end
519 bolts[sec] = bolts[sec] + 1
520 end
521 return false
522 end
523 db.actor:inventory_for_each(itr)
524
525 m_data.bolts = bolts
526 m_data.bolt_slot = db.actor:item_in_slot(6) and db.actor:item_in_slot(6):section() or nil
527end
528
529
530-------------------------------
531-- ITEM OPTIONS (MENU)
532-------------------------------
533function menu_open(itm) -- return "open" name
534 local p = itm:parent()
535 if not (p and p:id() == AC_ID) then return end
536 if itms_arty_container[itm:section()] then return end -- default containers
537
538 return game.translate_string("st_item_open")
539end
540
541function menu_unpack(itm) -- return "unpack" name
542 local p = itm:parent()
543 if not (p and p:id() == AC_ID) then return end
544
545 return game.translate_string("st_item_unpack")
546end
547
548function menu_play(itm) -- return "Play" name
549 local p = itm:parent()
550 if not (p and p:id() == AC_ID) then return end
551
552 return game.translate_string("st_item_play")
553end
554
555function menu_place(obj) -- return "Place" name
556 return game.translate_string("st_item_place")
557end
558
559
560-------------------------------
561-- ITEM OPTIONS (FUNCTOR)
562-------------------------------
563function use_package(obj)
564 local sec = obj:section()
565 local content = parse_list(ini_manager, "package_content", sec)
566 if #content > 0 then
567 utils_item.delay_event(content, {obj:id()}, "package_content", false, 5)
568 end
569end
570
571function use_package_random(obj)
572 local sec = obj:section()
573 local content = ini_manager:r_string_ex("package_content",sec)
574 if not content then return end
575
576 local t = str_explode(content,",")
577 local pick = {}
578 for i=1,#t do
579 if (#pick < 6) and (math.random(100) < 50) then
580 pick[#pick+1] = t[i]
581 end
582 end
583 pick = #pick > 1 and pick or {t[1],t[2],t[3],t[4]}
584
585 utils_item.delay_event(pick, {obj:id()}, "package_content", true, 5)
586end
587
588function use_deployable_mgun(obj)
589 local pos = vector():set(device().cam_pos)
590 pos:add(device().cam_dir:mul(3))
591 alife_create("deployable_mgun",pos,level.vertex_id(pos),db.actor:game_vertex_id())
592end
593
594function use_guitar(obj)
595 local n = math.random(28)
596 local snd = sound_object("music\\guitar_" .. tostring(n))
597 if (not snd) then return end
598 local period = snd:length()
599 snd:play_no_feedback(db.actor, 0, 0, db.actor:position(), 1.0, 1.0)
600 actor_effects.play_continuous_effect(period)
601end
602
603function use_harmonica(obj)
604 local n = math.random(5)
605 local snd = sound_object("music\\harmonica_" .. tostring(n))
606 if (not snd) then return end
607 local period = snd:length()
608 snd:play_no_feedback(db.actor, 0, 0, db.actor:position(), 1.0, 1.0)
609 actor_effects.play_continuous_effect(period)
610end
611
612function use_arty_container(obj)
613 local break_con
614 local break_arty
615 local sec = obj:section()
616
617 if (string.find(sec, "(lead.-_box)",3)) then
618 break_con = "lead_box"
619 break_arty = sec:gsub("_lead_box", "")
620 elseif (string.find(sec, "(af.-_iam)",3)) then
621 break_con = "af_iam"
622 break_arty = sec:gsub("_af_iam", "")
623 elseif (string.find(sec, "(af.-_aac)",3)) then
624 break_con = "af_aac"
625 break_arty = sec:gsub("_af_aac", "")
626 elseif (string.find(sec, "(af.-_aam)",3)) then
627 break_con = "af_aam"
628 break_arty = sec:gsub("_af_aam", "")
629 end
630
631 if break_con and break_arty and ini_sys:section_exist(break_con) and ini_sys:section_exist(break_arty) then
632 local cond = obj:condition()
633
634 _G.ARTY_FROM_CONT = true -- Hack to prevent player from exploting Artefacts Containers (gaining rank by recieving artefacts)
635 actor_effects.play_item_fx(break_con .. "_dummy")
636 alife_create_item(break_con, db.actor)
637 alife_create_item(break_arty, db.actor, { cond = cond } )
638 alife_release(obj)
639 end
640end
641
642function use_watch(obj)
643 local Y, M, D, h, mint, sec, ms = game.get_game_time():get()
644 local pharse = game.translate_string("st_dyn_news_day_part_am")
645 local mints = tostring(mint)
646 if (h > 12) then
647 h = h - 12
648 pharse = game.translate_string("st_dyn_news_day_part_pm")
649 elseif (h == 12) then
650 pharse = game.translate_string("st_dyn_news_day_part_pm")
651 elseif (h == 0) then
652 h = 12
653 end
654 if (mint < 10) then
655 mints = "0" .. tostring(mint)
656 end
657 utils_xml.hide_menu()
658 actor_menu.set_msg(1, tostring(h) .. ":" .. mints .. " " .. pharse , 3)
659end
660
661function use_place(obj)
662 local p = obj:parent()
663 if not (p and p:id() == AC_ID) then
664 return
665 end
666
667 local section = obj:section()
668 alife_release_id(obj:id())
669
670 local pos = db.actor:position()
671 pos:add(device().cam_dir:mul(1.2))
672 pos.y = db.actor:position().y + 1
673 local lvid = db.actor:level_vertex_id()
674 local gvid = db.actor:game_vertex_id()
675 local se_obj = alife_create(section,pos,lvid,gvid)
676
677 local rot = device().cam_dir:getH()
678 se_obj.angle = vector():set(0,rot,0)
679end
680
681
682-------------------------------
683-- OTHERS
684-------------------------------
685function actor_on_trade(obj,sell_bye,money) -- bind_stalker on_trade
686
687end
688
689function actor_item_take(obj) -- bind_stalker on_item_take
690
691end
692
693function npc_on_item_take_from_box(npc,box,item)
694
695end
696
697function new_game_equippment()
698 -- Damage equipment
699 local function damage_items(actor,itm)
700 local sec = itm:section()
701 if (IsWeapon(itm) and (sec ~= "wpn_binoc_inv")) or IsOutfit(itm) or IsHeadgear(itm) or IsItem("device",sec) then
702 itm:set_condition(math.random(75,85)/100)
703 end
704 end
705 db.actor:iterate_inventory(damage_items,db.actor)
706
707 give_info("start_equippment_handled")
708
709 -- Override autosave
710 exec_console_cmd("save " .. user_name() .. " - autosave")
711 printf("- Autosaved new game")
712
713 -- Override ammo type if required
714 local start_wpn_tbl = alife_storage_manager.get_state().start_wpn_ammo
715 if start_wpn_tbl then
716 for id, ammo_sec in pairs(start_wpn_tbl) do
717 local wpn = level.object_by_id(id)
718 if wpn then
719 local ammo_list = utils_item.get_ammo(wpn:section(), wpn:id())
720 local ammo_type
721 for i=1,#ammo_list do
722 if (ammo_list[i] == ammo_sec) then
723 ammo_type = i-1
724 break
725 end
726 end
727 if ammo_type then
728 local wpn_ammo_mag_size = ini_sys:r_u32(wpn:section(), "ammo_mag_size")
729 if wpn_ammo_mag_size then
730 wpn:unload_magazine()
731 wpn:set_ammo_type(ammo_type)
732 wpn:set_ammo_elapsed(wpn_ammo_mag_size )
733 printdbg("- New game weapon | [%s] - ammo type used: %s", wpn:section(), ammo_type)
734 end
735 end
736 end
737 end
738 end
739
740 return true
741end
742
743function bolt_manager() -- limit bolt count in actor inventory
744 ResetTimeEvent("cycle","bolt_manager",60)
745
746 local sim = alife()
747 local bolt_max_num = ini_manager:r_float_ex("settings","bolt_max_num") or 99
748 local cnt = 0
749 local id, sec, se_obj
750
751 local function itr(temp, obj)
752 sec = obj:section()
753 if (sec == "bolt") or (sec == "bolt_bullet") then
754 cnt = cnt + 1
755 if (cnt > bolt_max_num) then
756 local se_obj = alife_object(obj:id())
757 if se_obj then
758 alife_release(se_obj)
759 end
760 end
761 end
762 end
763 db.actor:iterate_ruck(itr, nil)
764
765 return false
766end
767
768function give_item_reward(num_of_items)
769 num_of_items = num_of_items or 1
770 local prior = {
771 ["health"] = 2,
772 ["rad"] = 2,
773 ["drink"] = 2,
774 ["food"] = 2,
775 ["ammo"] = 2,
776 ["battery"] = 0,
777 }
778
779 local tot_power,tot_devices = 0,0
780 local ammo_suitable = {}
781 local ammo_avail = {}
782 local function itr(obj)
783 local sec = obj:section()
784
785 -- Evaluate medkits
786 if item_rewards["items_health"][sec] then
787 prior["health"] = prior["health"] - 1
788 end
789
790 -- Evaluate anti-rads
791 if item_rewards["items_rad"][sec] then
792 prior["rad"] = prior["rad"] - 1
793 end
794
795 -- Evaluate drink
796 if item_rewards["items_drink"][sec] then
797 prior["drink"] = prior["drink"] - 1
798 end
799
800 -- Evaluate food
801 if item_rewards["items_food"][sec] then
802 prior["food"] = prior["food"] - 1
803 end
804
805 -- Evaluate devices power
806 if IsItem("device",sec) then
807 tot_devices = tot_devices + 1
808 tot_power = tot_power + (obj:condition() * 100)
809 end
810
811 -- Evaluate weapons and ammo
812 if (sec ~= "wpn_binoc") and IsWeapon(obj) and (not IsMelee(obj)) then
813 local ammo = utils_item.get_ammo(obj:section(), obj:id())
814 if ammo and #ammo > 1 then
815 for i=1,#ammo do
816 local sec_ammo = ammo[i]
817 if item_rewards["items_ammo"][sec_ammo] then
818 ammo_suitable[sec_ammo] = true
819 end
820 end
821 end
822 end
823
824 if IsItem("ammo",sec) then
825 ammo_avail[sec] = { cnt = obj:ammo_get_count() , box = IsItem("ammo",sec) }
826 --printf("ammo_avail[%s] = { cnt = %s | box = %s", sec, ammo_avail[sec].cnt, ammo_avail[sec].box)
827 end
828
829 return false
830 end
831 db.actor:inventory_for_each(itr)
832
833 -- Total power of devices is less than %50 -> need battery
834 if (tot_power < (50 * tot_devices)) then
835 prior["battery"] = 1
836 end
837
838 -- No enough ammo found for existing weapons -> need ammo
839 for sec,_ in pairs(ammo_suitable) do
840 local ammo = ammo_avail[sec]
841 if ammo and (ammo.cnt >= ammo.box) then
842 prior["ammo"] = prior["ammo"] - 1
843 end
844 end
845
846 --[[
847 for k,p in pairs(prior) do
848 printf("- Prior[%s] = %s",k,p)
849 end
850 --]]
851
852 -- Give actor items
853 for i=1,num_of_items do
854
855 -- Search from higher to lower priority
856 local picker = {}
857 local pick_prior
858 local functor = function(t,a,b) return t[a] > t[b] end
859 for k,p in spairs(prior,functor) do
860 if (p > 0) then
861 if (not pick_prior) or (pick_prior == p) then
862 pick_prior = p
863 picker[#picker + 1] = k
864 end
865 end
866 end
867
868 if pick_prior and (#picker > 0) then
869
870 -- Pick random type of this priority
871 local item_reward
872 local k = picker[math.random(#picker)]
873
874 -- Pick random item
875 if k == "health" then
876 item_reward = random_key_table(item_rewards["items_health"])
877 elseif k == "rad" then
878 item_reward = random_key_table(item_rewards["items_rad"])
879 elseif k == "drink" then
880 item_reward = random_key_table(item_rewards["items_drink"])
881 elseif k == "food" then
882 item_reward = random_key_table(item_rewards["items_food"])
883 elseif k == "battery" then
884 item_reward = item_device.device_battery
885 elseif k == "ammo" then
886 item_reward = random_key_table(ammo_suitable)
887 end
888
889 if item_reward then
890
891 -- Reduce priority
892 prior[k] = prior[k] - 1
893 local amount = 1
894
895 -- Give items
896 local box_size = IsItem("ammo",item_reward)
897 local max_uses = IsItem("multiuse",item_reward)
898 local uses = max_uses and (max_uses >= 2) and 2 or 1
899 if uses then
900 amount = math.random(1,uses)
901 end
902 alife_create_item(item_reward, db.actor, {uses = amount , ammo = box_size})
903
904 -- Send news
905 news_manager.relocate_item(db.actor, "in", item_reward, amount)
906 end
907 break
908 end
909 end
910end
911
912function send_itm_msg(sec)
913 local str = strformat(game.translate_string("st_item_taken"), ui_item.get_sec_name(sec))
914 actor_menu.set_msg(2, str)
915end
916
917local upg_gr = {
918 ["first"] = 1,
919 ["secon"] = 2,
920 ["third"] = 3,
921 ["fourt"] = 4,
922 ["fifth"] = 5,
923}
924local upg_ind = {
925 ["a"] = 1,
926 ["b"] = 2,
927 ["c"] = 3,
928 ["d"] = 4,
929 ["e"] = 5,
930 ["f"] = 6,
931}
932function extract_upgr_tools(t1, current_grp)
933
934 local elements = parse_list(ini_sys, current_grp, "elements")
935
936 -- Gather groups and indexes
937 for i=1,#elements do -- search in upgrade group elements
938 for k,v in pairs(upg_gr) do
939 if string_find(elements[i],k) then -- if we found a legit element
940 local indx = elements[i]:sub(9,9) -- get the index
941 local upg_idx = indx and upg_ind[indx]
942 if upg_idx then
943 local prop = ini_sys:r_string_ex(elements[i],"property")
944 if prop then
945 local pr = str_explode(prop,",")
946 local tool = utils_item.get_upgrade_prop_tool(pr[1])
947 local num = ((upg_idx <= 2) and 1) or ((upg_idx <= 4) and 2) or 3
948 local sec_tool = tool and tool:gsub("%^d", tostring(num)) or nil
949 if sec_tool then
950 t1[sec_tool] = true
951 else
952 local sec = ini_sys:r_string_ex(elements[i],"section")
953 printdbg("! extract_upgr | can't generate tool for upgrade [%s], property: %s", sec, pr[1])
954 end
955 end
956 end
957 end
958 end
959 end
960
961 -- Repeat
962 for i=1,#elements do
963 local next_grp = ini_sys:r_string_ex(elements[i],"effects")
964 if next_grp and (next_grp ~= "") then
965 extract_upgr_tools(t1,next_grp)
966 end
967 end
968end
969
970
971-------------------------------
972-- MULTI-USE ITEMS
973-------------------------------
974function relocate_item_to_actor(actor, npc, section, amount)
975 if (not actor) then
976 return
977 end
978
979 amount = amount or 1
980 local npc_inv = npc and (not IsItem("anim",section)) and utils_item.collect_amount(npc, section, 1) or {}
981 local sim = alife()
982 local cnt = amount
983 local max_uses = IsItem("multiuse",section) or 1
984
985 while cnt > 0 do
986 -- Create or transfer object from npc
987 local id
988 if not is_empty(npc_inv) then
989 local id_pick = random_key_table(npc_inv)
990 local obj = id_pick and level.object_by_id(id_pick)
991 if obj then
992 npc:transfer_item(obj, actor)
993 npc_inv[id_pick] = nil
994 id = id_pick
995 end
996 else
997 local se_obj = alife_create_item(section, db.actor)
998 id = se_obj and se_obj.id
999
1000 -- Register PDA if found
1001 if npc and id and item_device.device_npc_pda[section] then
1002 ui_pda_npc_tab.register_pda(npc, section, id)
1003 end
1004 end
1005
1006 -- Set remaining uses if needed
1007 if id then
1008 cnt = cnt - max_uses
1009 if cnt < 0 then
1010 local uses = (max_uses - (-cnt))
1011 process_item(section , id, {uses = uses} )
1012 end
1013 else
1014 printe("!ERROR: relocate_item_to_actor | object for section [%s] is bugged!", section)
1015 break
1016 end
1017 end
1018
1019 local box_size = IsItem("ammo",section)
1020 if box_size then
1021 amount = amount * box_size
1022 end
1023 news_manager.relocate_item(actor, "in", section, amount)
1024end
1025
1026function relocate_item_from_actor(actor, npc, section, amount)
1027 if (not actor) then
1028 return
1029 end
1030
1031 if (npc == nil) then
1032 --printe("!ERROR: Couldn't relocate_item_from_actor | no npc found!")
1033 end
1034
1035 amount = amount or 1
1036 local cnt = amount
1037 local max_uses = IsItem("multiuse",section)
1038 local keep_itr = true
1039 local function itr(temp, obj)
1040 --printf("~relocate_item_from_actor | checked [%s]", obj:section())
1041 if keep_itr and (obj and obj:section() == section) then
1042 --printf("-relocate_item_from_actor | found needed section [%s]", section)
1043 local uses = max_uses and obj:get_remaining_uses() or 1
1044 cnt = cnt - uses
1045 if (cnt >= 0) then
1046 if npc then
1047 actor:transfer_item(obj, npc)
1048 else
1049 alife_release_id(obj:id())
1050 end
1051
1052 if (cnt == 0) then
1053 keep_itr = false
1054 end
1055 else
1056 local remain_1 = -cnt
1057 local remain_2 = max_uses - remain_1
1058 process_item(section, obj:id(), {uses = remain_1})
1059 if npc then
1060 alife_create_item(section, npc, {uses = remain_2})
1061 end
1062 keep_itr = false
1063 end
1064 end
1065 end
1066 actor:iterate_inventory(itr, nil)
1067
1068 if cnt > 0 then
1069 printe("! ERROR: Couldn't relocate_item_from_actor | not enough item [%s] recolated! need %s more", section, cnt)
1070 end
1071
1072 local box_size = IsItem("ammo",section)
1073 if box_size then
1074 amount = amount * box_size
1075 end
1076 news_manager.relocate_item(actor, "out", section, amount)
1077end
1078
1079
1080-------------------------------
1081-- Sound Effects
1082-------------------------------
1083local time_snd_prev = 0
1084local snd_on_take = {
1085 ["coin"] = {"interface\\items\\inv_items_money_coin_2"},
1086 ["bolt"] = {"interface\\items\\inv_items_ammo_1"},
1087 ["paper"] = {"interface\\items\\inv_items_money_paper"},
1088 ["bottle"] = {"interface\\items\\inv_items_bottle_",1,2},
1089 ["pills"] = {"interface\\items\\inv_items_pills_2"},
1090 ["part"] = {"interface\\items\\inv_items_parts_",1,2},
1091 ["outfit"] = {"interface\\items\\inv_items_cloth_",1,3},
1092 ["ammo"] = {"interface\\items\\inv_items_ammo_",4,7},
1093 ["grenade"] = {"interface\\items\\inv_items_grenade_",1,2},
1094 ["knife"] = {"interface\\items\\inv_items_knife_",1,2},
1095 ["weapon"] = {"interface\\items\\inv_items_wpn_",1,2},
1096 ["other"] = {"interface\\items\\inv_items_generic_",2,5},
1097}
1098
1099function play_item_sound(item, vol)
1100 if (not item) then
1101 printe("!ERROR itms_manager | play_item_sound | no object recieved!")
1102 end
1103
1104 local snd_type = SYS_GetParam(0,item:section(),"snd_on_take")
1105 if not (snd_type and snd_type ~= "") then
1106 return
1107 end
1108
1109 local snd = snd_on_take[snd_type]
1110 if (not snd) then
1111 return
1112 end
1113
1114 local snd_obj
1115 if (#snd == 1) then
1116 snd_obj = sound_object(snd[1])
1117 else
1118 snd_obj = sound_object(snd[1] .. tostring(math.random(snd[2],snd[3])))
1119 end
1120
1121 local time_g = time_global()
1122 if snd_obj and (time_g > time_snd_prev + 25) then
1123 snd_obj:play(db.actor,0,sound_object.s2d)
1124 snd_obj.volume = vol or 1
1125 end
1126 time_snd_prev = time_g
1127end
1128
1129
1130
1131-------------------------------
1132-- Item Processor
1133-------------------------------
1134local c_instance
1135function get_item_processor()
1136 if c_instance == nil then
1137 c_instance = ItemProcessor()
1138 end
1139 return c_instance
1140end
1141
1142function process_item(...)
1143 if c_instance == nil then
1144 c_instance = ItemProcessor()
1145 end
1146 return c_instance:Process_Item(...)
1147end
1148
1149function create_item(...)
1150 if c_instance == nil then
1151 c_instance = ItemProcessor()
1152 end
1153 return c_instance:Create_Item(...)
1154end
1155
1156class "ItemProcessor"
1157function ItemProcessor:__init()
1158 self.Remove = {}
1159 self.Cond = {}
1160 self.Uses = {}
1161 self.Ammo = {}
1162
1163 self.Debug = false -- true to debug
1164 self.Cycles = 10
1165end
1166
1167function ItemProcessor:update()
1168 -- Process Condition
1169 for id,con in pairs(self.Cond) do
1170 local obj = level.object_by_id(id)
1171 if obj then
1172 if self.Debug then
1173 printf("* ItemProcessor | processing condition | id: %s - con: %s", id, con)
1174 end
1175
1176 obj:set_condition(con)
1177 local new_con = obj:condition()
1178
1179 if (new_con < con + 0.02) and (new_con > con - 0.02) then -- range check
1180 self.Cond[id] = nil
1181
1182 if self.Debug then
1183 printf("# ItemProcessor | processing condition done | id: %s - con: %s", id, new_con)
1184 end
1185 else
1186 self:Remove_Process(id,"!","can't set condition!")
1187 end
1188
1189 elseif alife_object(id) then
1190 self:Remove_Process(id,"~","server object exists, no game object yet")
1191
1192 else
1193 self:Remove_Process(id,"!","no game object!")
1194 end
1195 end
1196
1197 -- Process Uses
1198 for id,uses in pairs(self.Uses) do
1199 local obj = level.object_by_id(id)
1200 if obj then
1201 if self.Debug then
1202 printf("* ItemProcessor | processing uses | id: %s - uses: %s", id, uses)
1203 end
1204
1205 obj:set_remaining_uses(uses)
1206
1207 if (obj:get_remaining_uses() == uses) then
1208 self.Uses[id] = nil
1209
1210 if self.Debug then
1211 printf("# ItemProcessor | processing uses done | id: %s - con: %s", id, uses)
1212 end
1213 else
1214 self:Remove_Process(id,"!","can't set uses!")
1215 end
1216
1217 elseif alife_object(id) then
1218 self:Remove_Process(id,"~","server object exists, no game object yet")
1219
1220 else
1221 self:Remove_Process(id,"!","no game object!")
1222 end
1223 end
1224
1225 -- Process Ammo
1226 for id,ammo in pairs(self.Ammo) do
1227 local obj = level.object_by_id(id)
1228 if obj then
1229 if self.Debug then
1230 printf("* ItemProcessor | processing ammo | id: %s - ammo: %s", id, ammo)
1231 end
1232
1233 obj:ammo_set_count(ammo)
1234
1235 if (obj:ammo_get_count() == ammo) then -- range
1236 self.Ammo[id] = nil
1237
1238 if self.Debug then
1239 printf("# ItemProcessor | processing ammo done | id: %s - con: %s", id, new_con)
1240 end
1241 else
1242 self:Remove_Process(id,"!","can't set ammo!")
1243 end
1244
1245 elseif alife_object(id) then
1246 self:Remove_Process(id,"~","server object exists, no game object yet")
1247
1248 else
1249 self:Remove_Process(id,"!","no game object!")
1250 end
1251 end
1252end
1253
1254function ItemProcessor:Create_Item(section, owner, t)
1255
1256 t = t or {}
1257
1258 if section then
1259 local uses
1260 section, uses = self:Extract_Uses(section)
1261
1262 if (ini_sys:section_exist(section)) then
1263
1264 -- Spawn object
1265 local se_itm
1266 if owner then
1267
1268 -- Collect spawn data
1269 local pos, lvi, gvi, pid, spawn_typ
1270 if (type(owner) == "table") then
1271 pos, lvi, gvi, pid = owner[1], owner[2], owner[3], owner[4]
1272 if pid then
1273 spawn_typ = "on custom object"
1274 else
1275 spawn_typ = "in world"
1276 end
1277 elseif (type(owner.id) == "function") then
1278 pos, lvi, gvi, pid = owner:position(), owner:level_vertex_id(), owner:game_vertex_id(), owner:id()
1279 spawn_typ = "on game object"
1280 elseif owner.id then
1281 pos, lvi, gvi, pid = owner.position, owner.m_level_vertex_id, owner.m_game_vertex_id, owner.id
1282 spawn_typ = "on server object"
1283 end
1284
1285 -- Validate
1286 if not (pos and lvi and gvi) then
1287 callstack()
1288 printe("! ItemProcessor | Missing spawn properties for [%s] | Spawn type: %s | pos: %s, lvi: %s, gvi: %s", section, spawn_typ, pos , lvi , gvi)
1289 return nil
1290 end
1291 if self.Debug then
1292 local obj_p = pid and alife_object(pid)
1293 local name_p = obj_p and (obj_p.id == AC_ID and "actor" or obj_p:name()) or ""
1294 spawn_typ = spawn_typ .. (obj_p and (" (".. name_p .. ")") or "")
1295 end
1296
1297 -- Ammo need unique process to spawn multi-objects, return result from here
1298 if t.ammo and t.ammo > 0 and IsItem("ammo",section) then
1299
1300--:::::::::::::::::::::::::::::::
1301--edits for Less Items start here
1302--:::::::::::::::::::::::::::::::
1303
1304--[[ disabled for Less Items -- Replace damaged items with old if _NO_DAMAGED_AMMO allows it
1305 if _NO_DAMAGED_AMMO and string_find(section,"verybad") then
1306 local new_section = string_gsub(section,"verybad","bad")
1307 if ini_sys:section_exist(new_section) then
1308 section = new_section
1309 end
1310 end --]]
1311
1312 -- Replace damaged items with new if _NO_DAMAGED_AMMO allows it
1313 if _NO_DAMAGED_AMMO and string_find(section,"_verybad") then
1314 local new_section = string_gsub(section,"_verybad","")
1315 if ini_sys:section_exist(new_section) then
1316 section = new_section
1317 end
1318 end
1319
1320 -- Replace old items with new if _NO_DAMAGED_AMMO allows it
1321 if _NO_DAMAGED_AMMO and string_find(section,"_bad") then
1322 local new_section = string_gsub(section,"_bad","")
1323 if ini_sys:section_exist(new_section) then
1324 section = new_section
1325 end
1326 end
1327--:::::::::::::::::::::::::::::::
1328--edits for Less Items end here
1329--:::::::::::::::::::::::::::::::
1330 local num_in_box = ini_sys:r_u32(section, "box_size")
1331 local num = t.ammo
1332 local se_tbl = {}
1333 local sim = alife()
1334
1335 local p_id = pid or 65535 -- because xray
1336 while (num > num_in_box) do
1337 se_tbl[#se_tbl+1] = sim:create_ammo(section, pos, lvi, gvi, p_id, num_in_box)
1338 alife_record( se_tbl[#se_tbl] , true )
1339 num = num - num_in_box
1340
1341 if self.Debug then
1342 local se_ammo = se_tbl[#se_tbl]
1343 printf("/ alife_create [%s] (%s) x%s ammo %s", section, se_ammo and se_ammo.id, num_in_box, spawn_typ)
1344 end
1345 end
1346
1347 se_tbl[#se_tbl+1] = sim:create_ammo(section, pos, lvi, gvi, p_id, num)
1348 alife_record( se_tbl[#se_tbl] , true )
1349
1350 if self.Debug then
1351 local se_ammo = se_tbl[#se_tbl]
1352 printf("/ alife_create [%s] (%s) x%s ammo %s", section, se_ammo and se_ammo.id, num, spawn_typ)
1353 end
1354
1355 return se_tbl
1356
1357 -- Other items
1358 else
1359
1360 if pid then
1361 se_itm = alife():create(section, pos, lvi, gvi, pid)
1362 else
1363 se_itm = alife():create(section, pos, lvi, gvi)
1364 end
1365
1366 if self.Debug then
1367 printf("/ alife_create [%s] (%s) on %s", section, se_itm and se_itm.id, spawn_typ)
1368 end
1369 end
1370 else
1371 printe("! ItemProcessor | Missing spawn owner for [%s]!", section)
1372 end
1373
1374 -- Process
1375 if se_itm then
1376 alife_record(se_itm,true)
1377
1378 -- Multiuse items
1379 if IsItem("multiuse",section) then
1380 uses = uses or t.uses
1381
1382 -- Send to process
1383 if uses then
1384 self.Uses[se_itm.id] = uses --self:Process_Item(section, se_itm.id, { uses = uses })
1385 end
1386
1387 -- Degradable items
1388 elseif utils_item.is_degradable(nil, section) then
1389 local cond = t.cond
1390
1391 -- Parts
1392 if t.cond_cr and t.cond_ct and IsItem(cond_ct,section) then
1393 cond = (#t.cond_cr > 2) and self:Random_Choice(t.cond_cr) or self:Random_Condition(t.cond_cr)
1394
1395 -- others
1396 elseif t.cond_r then
1397 cond = (#t.cond_r > 2) and self:Random_Choice(t.cond_r) or self:Random_Condition(t.cond_r)
1398
1399 end
1400
1401 -- Send to process
1402 if cond then
1403 self.Cond[se_itm.id] = cond --self:Process_Item(section, se_itm.id, { cond = cond })
1404 end
1405 end
1406
1407 return se_itm
1408
1409 else
1410 printe("!ERROR [%s] is not spawned by ItemProcessor",section)
1411 end
1412
1413 else
1414 printe("! ItemProcessor | section [%s] doesn't exist!", section)
1415 end
1416
1417 else
1418 printf("~ ItemProcessor | nothing is passed to process!")
1419 end
1420
1421 return nil
1422end
1423
1424function ItemProcessor:Process_Item(section, id, t)
1425 if t then
1426 if t.uses then
1427 self.Uses[id] = t.uses
1428
1429 elseif t.cond then
1430 self.Cond[id] = t.cond
1431
1432 elseif t.ammo then
1433 self.Ammo[id] = t.ammo
1434
1435 elseif self.Debug then
1436 --printf("* ItemProcessor | no process done for [%s] (%s)", section, id)
1437 end
1438 end
1439end
1440
1441function ItemProcessor:Remove_Process(id, mark, str)
1442 mark = mark or "~"
1443 self.Remove[id] = self.Remove[id] and (self.Remove[id] + 1) or 0
1444 if (self.Remove[id] > self.Cycles) then
1445 self.Cond[id] = nil
1446 self.Uses[id] = nil
1447 self.Ammo[id] = nil
1448 self.Remove[id] = nil
1449
1450 if self.Debug then
1451 local obj = level.object_by_id(id)
1452 local p = obj and obj:parent()
1453 printf("%s ItemProcessor | %s: (%s) [%s] - owner: (%s) [%s]", mark, str, id, obj and obj:section(), p and p:id() or "-", p and p:section())
1454 end
1455 end
1456end
1457
1458function ItemProcessor:Random_Choice(arg)
1459 if arg and (#arg > 0) then
1460 local r = math.random(1, #arg)
1461 return arg[r]
1462 end
1463end
1464
1465function ItemProcessor:Random_Condition(arg)
1466 if arg and (#arg > 0) then
1467 return (math.random(arg[1], arg[2])/100)
1468 end
1469end
1470
1471function ItemProcessor:Extract_Uses(sec_d)
1472 local _, __, sec_u, uses = string_find(sec_d,"(.*)__(%d)")
1473 if sec_u and uses and tonumber(uses) and ini_sys:section_exist(sec_u) then
1474 return sec_u, tonumber(uses)
1475 end
1476 return sec_d
1477end
1478
1479--------------------------------------------------------------------------------
1480
1481
1482-------------------------------
1483-- DEBUG
1484-------------------------------
1485function generate_boosters_list()
1486 local config = ini_file_ex("booster_stats.ltx",true)
1487
1488 ini_sys:section_for_each(function(section)
1489 local cls = ini_sys:r_string_ex(section,"class")
1490 if (cls == "II_FOOD") and (ini_sys:r_float_ex(section,"boost_time") > 0) then
1491 local str = ""
1492 str = str .. ("cost:" .. ini_sys:r_float_ex(section,"cost") .. "|")
1493 str = str .. (ini_sys:r_float_ex(section,"max_uses") and ("uses:" .. ini_sys:r_float_ex(section,"max_uses") .. "|") or ("uses:1|"))
1494 str = str .. ("boost_time:" .. ini_sys:r_float_ex(section,"boost_time") .. "|")
1495
1496 if ini_sys:r_float_ex(section,"boost_max_weight") ~= 0 then
1497 str = str .. ("boost_max_weight:" .. ini_sys:r_float_ex(section,"boost_max_weight") .. "|")
1498 end
1499 if ini_sys:r_float_ex(section,"boost_health_restore") ~= 0 then
1500 str = str .. ("boost_health_restore:" .. ini_sys:r_float_ex(section,"boost_health_restore") .. "|")
1501 end
1502 if ini_sys:r_float_ex(section,"boost_power_restore") ~= 0 then
1503 str = str .. ("boost_power_restore:" .. ini_sys:r_float_ex(section,"boost_power_restore") .. "|")
1504 end
1505 if ini_sys:r_float_ex(section,"boost_radiation_restore") ~= 0 then
1506 str = str .. ("boost_radiation_restore:" .. ini_sys:r_float_ex(section,"boost_radiation_restore") .. "|")
1507 end
1508 if ini_sys:r_float_ex(section,"boost_bleeding_restore") ~= 0 then
1509 str = str .. ("boost_bleeding_restore:" .. ini_sys:r_float_ex(section,"boost_bleeding_restore") .. "|")
1510 end
1511
1512 if ini_sys:r_float_ex(section,"boost_radiation_protection") ~= 0 then
1513 str = str .. ("boost_radiation_protection:" .. ini_sys:r_float_ex(section,"boost_radiation_protection") .. "|")
1514 end
1515 if ini_sys:r_float_ex(section,"boost_telepat_protection") ~= 0 then
1516 str = str .. ("boost_telepat_protection:" .. ini_sys:r_float_ex(section,"boost_telepat_protection") .. "|")
1517 end
1518 if ini_sys:r_float_ex(section,"boost_chemburn_protection") ~= 0 then
1519 str = str .. ("boost_chemburn_protection:" .. ini_sys:r_float_ex(section,"boost_chemburn_protection") .. "|")
1520 end
1521
1522 if ini_sys:r_float_ex(section,"boost_burn_immunity") ~= 0 then
1523 str = str .. ("boost_burn_immunity:" .. ini_sys:r_float_ex(section,"boost_burn_immunity") .. "|")
1524 end
1525 if ini_sys:r_float_ex(section,"boost_shock_immunity") ~= 0 then
1526 str = str .. ("boost_shock_immunity:" .. ini_sys:r_float_ex(section,"boost_shock_immunity") .. "|")
1527 end
1528 if ini_sys:r_float_ex(section,"boost_radiation_immunity") ~= 0 then
1529 str = str .. ("boost_radiation_immunity:" .. ini_sys:r_float_ex(section,"boost_radiation_immunity") .. "|")
1530 end
1531 if ini_sys:r_float_ex(section,"boost_telepat_immunity") ~= 0 then
1532 str = str .. ("boost_telepat_immunity:" .. ini_sys:r_float_ex(section,"boost_telepat_immunity") .. "|")
1533 end
1534 if ini_sys:r_float_ex(section,"boost_chemburn_immunity") ~= 0 then
1535 str = str .. ("boost_chemburn_immunity:" .. ini_sys:r_float_ex(section,"boost_chemburn_immunity") .. "|")
1536 end
1537 if ini_sys:r_float_ex(section,"boost_strike_immunity") ~= 0 then
1538 str = str .. ("boost_strike_immunity:" .. ini_sys:r_float_ex(section,"boost_strike_immunity") .. "|")
1539 end
1540 if ini_sys:r_float_ex(section,"boost_wound_immunity") ~= 0 then
1541 str = str .. ("boost_wound_immunity:" .. ini_sys:r_float_ex(section,"boost_wound_immunity") .. "|")
1542 end
1543 if ini_sys:r_float_ex(section,"boost_explosion_immunity") ~= 0 then
1544 str = str .. ("boost_explosion_immunity:" .. ini_sys:r_float_ex(section,"boost_explosion_immunity") .. "|")
1545 end
1546 if ini_sys:r_float_ex(section,"boost_fire_wound_immunity") ~= 0 then
1547 str = str .. ("boost_fire_wound_immunity:" .. ini_sys:r_float_ex(section,"boost_fire_wound_immunity") .. "|")
1548 end
1549
1550 config:w_value("temp", section, str)
1551 end
1552 end)
1553
1554 config:save()
1555end