· 4 years ago · May 24, 2021, 11:20 PM
1
2local MAGAZINE_CALCULATE_WEIGHT = true
3
4local iMAG_SLOT = 1
5local iMAG_COUNT = 2
6local iMAG_FILL = 3
7
8local iWEP_MSLOT = 1
9local iWEP_MSEC = 2
10local iWEP_COUNT = 3
11local iWEP_FILL = 4
12
13local wuutdebugLog=false
14function print_f( text )
15 if(wuutdebugLog) then
16 printf( "wuut_mags.script: " .. text )
17 end
18end
19
20
21--MCM and QOL
22--Pepsifan04
23--===========================================
24
25-- holds multidimensional table with weapons and matching mags found in inv
26-- it looks like this: table[weapon][int]=magName
27local tInvWepMags={}
28
29local keepMagActive=1
30local activeMagTreshold=10 -- that's in %
31local dropMags=false --option to drop magazines to the floor when below condition
32-- 0 always keep mag active
33-- 1 deactivate when below treshold
34-- 2 always deactivate after reload
35
36local ignoreMagCond_trade=0
37local ignoreMagCond=0
38local ignoreMagCond_val=50
39-- 0 mag condition functions as usual
40-- 1 mags have always custom condition
41
42
43
44
45local magLoadTime=400
46local magUnloadTime=400
47--Mag load and unload time
48--defaults for when not using MCM
49--400 is default from wuut's orginal script
50
51
52--load settings from MCM if MCM is installed
53function load_mcm_settings()
54 if ui_mcm then
55 magLoadTime = ui_mcm.get("wuut_mags/optMagLoadTime")
56 magUnloadTime = ui_mcm.get("wuut_mags/optMagUnloadTime")
57
58 keepMagActive = ui_mcm.get("wuut_mags/optRemoveMagOnReload")
59 activeMagTreshold = ui_mcm.get("wuut_mags/optRemoveMagOnReload_tresholdVal")
60
61 dropMags = ui_mcm.get("wuut_mags/optDropMagOnReload")
62
63 wuutdebugLog = ui_mcm.get("wuut_mags/optDebugLog")
64
65 ignoreMagCond_trade = ui_mcm.get("wuut_mags/optIgnoreConditionForTrade")
66
67 ignoreMagCond = ui_mcm.get("wuut_mags/optIgnoreCondition")
68 ignoreMagCond_val = ui_mcm.get("wuut_mags/optIgnoreCondition_customVal")
69 end
70end
71
72
73function on_game_start()
74
75 --Pepsifan04
76 --===========================================
77 --
78 --registers callbacks for loading MCM and inv iteration for hovering
79 RegisterScriptCallback("actor_on_first_update", load_mcm_settings)
80 RegisterScriptCallback("on_option_change", load_mcm_settings)
81
82 -- iterate inventory on open
83 -- only player and npc for now
84 -- I dunno how to get stash contents
85 -- if you happen to know how, tell me, pls
86 --RegisterScriptCallback("GUI_on_show", iterateInventory)
87 RegisterScriptCallback("ActorMenu_on_mode_changed", iterateInventory)
88
89 --===========================================
90
91
92 RegisterScriptCallback("on_key_release", on_key_release)
93 RegisterScriptCallback("on_key_press", on_key_press)
94
95 RegisterScriptCallback("actor_on_weapon_fired", actor_on_weapon_fired)
96 RegisterScriptCallback("actor_on_weapon_reload", actor_on_weapon_reload)
97
98 RegisterScriptCallback("actor_on_weapon_jammed", weapon_jammed)
99
100 --sRegisterScriptCallback("CUIActorMenu_OnItemFocusReceive", on_item_focus)
101 RegisterScriptCallback("ActorMenu_on_item_focus_receive", on_item_focus)
102
103
104 --RegisterScriptCallback("CUIActorMenu_OnItemDropped", on_item_drag_dropped)
105 RegisterScriptCallback("ActorMenu_on_item_drag_drop", on_item_drag_dropped)
106
107 RegisterScriptCallback("actor_on_hud_animation_end", animation_end)
108
109 RegisterScriptCallback("npc_on_death_callback", wuut_npc_on_death_callback)
110
111 --RegisterScriptCallback("TrdWndOpened",wuut_OnTrdWndOpened)
112 RegisterScriptCallback("ActorMenu_on_trade_started",wuut_OnTrdWndOpened)
113
114
115
116 RegisterScriptCallback("actor_item_to_ruck", UpdateMagazineUI)
117
118 RegisterScriptCallback("InventoryWndClosed", wuut_InventoryWndClosed)
119 --RegisterScriptCallback("actor_menu_mode_changed", wuut_actor_menu_mode_changed)
120 RegisterScriptCallback("DeadBodySearchWndClosed", wuut_DeadBodySearchWndClosed)
121
122
123
124 RegisterScriptCallback("actor_on_first_update", actor_on_first_update)
125
126 RegisterScriptCallback("save_state",save_state)
127 RegisterScriptCallback("load_state",load_state)
128
129 AddUniqueCall(main_loop)
130
131end
132
133
134--Pepsifan04
135--===========================================
136-- anomaly renames weapons if you atttach things to it
137-- for ex. ump with eotech will be named wpn_ump45_eotech
138-- we need weapon basename (w/o attachment name) to find it's mathching mag
139-- this function returns that, weapon base name
140local function getWeaponBaseName(string)
141 local result=nil
142 local tString = str_explode(string,"_")
143 if(tString[1] and tString[2])then
144 result = tString[1] .. "_" .. tString[2]
145 end
146
147 -- sganon begin
148 -- make an exception for the Duty AEK which has a different ammo section
149 -- this fixes an impossibility to define AK47-compatible AEK mags in 7.62x39
150 if(tString[3] ~= nil) then
151 if(tString[3] == "duty" and result == "wpn_aek") then
152 result = result .. "duty"
153 print_f("sganon AEK duty patched in function getWeaponBaseName: " .. result)
154 end
155 end
156 -- sganon end
157
158 return result
159end
160
161function iterateInventory( mode, last_mode)
162
163 -- we're not oop so i've had to improvise
164 -- this is a rewrite of existing function exclusive to inerateInvetory functions
165 -- changes some strings
166
167 --sganon edit begin
168 -- Diphenhydramine-HCl (sps bratan!) made me aware of the registered callback can lead to crashes when it's loaded, but the user
169 -- isn't in the inventory, but the MCM (Mod Configuration Menu) GUI.
170 -- This can happen when the user loads a game, chooses "Quit Game" from the main menu, then enters the MCM menu.
171 -- Result is a CTD: "attempt to index local 'player' (a nil value)"
172 -- The following code just lets the function return without any code executed.
173 -- code by Diphenhydramine-HCl, a more elegant solution than I had in mind when fixing this
174 -- see actor_menu.script for detail
175 -- dph
176 if (mode > 0) and (mode < 5) then
177 return
178 end
179 --sganon edit end
180
181 local function matchWeaponMag(weaponObj, magString)
182 local result=false
183
184 local weaponNameString = getWeaponBaseName(weaponObj:section())
185 local magAmmo = parse_list(system_ini(),magString,"mag_ammo_class")
186 local weaponAmmo = utils_item.get_ammo(weaponObj:section(), weaponObj:id())
187 local magGroup = parse_list(system_ini(),magString,"magazine_group",true)
188
189 if (magGroup[weaponNameString] and magAmmo[1] == weaponAmmo[1]) then
190 result=true
191 end
192
193 return result
194 end
195
196 local invMags={}
197
198 tInvWepMags={}
199
200 -- gets all mags inside player inv
201 -- and puts them inside invMags for later usage
202 local function getMags(dmp,item)
203 if(item and isMagazine(item))then
204 -- updates magazine condition when opening inventory
205 -- added to support 100% on trading
206 UpdateMagazineUI(item)
207
208 -- finds "active" mag and adds it's inactive version to the highlight table alongisde active one
209 local magName=item:section()
210 if(string.match(magName,'_ready'))then
211 local inactiveMag=string.gsub(magName,"_ready","")
212 table.insert(invMags,inactiveMag)
213 end
214 table.insert(invMags,magName)
215 end
216 end
217
218 -- builds out multidimensional table
219 -- table gets rebuild on every inv open
220 local function constructWepMagsTable(dmp,item)
221 if(item and IsWeapon(item))then
222 if(invMags)then
223 local baseWeaponName=getWeaponBaseName(item:section())
224 if(tInvWepMags[baseWeaponName]==nil)then
225 tInvWepMags[baseWeaponName]={}
226 end
227 for i=1,#invMags do
228 if(matchWeaponMag(item,invMags[i]))then
229 local id=#tInvWepMags[baseWeaponName]+1
230
231 tInvWepMags[baseWeaponName][id]=invMags[i]
232 end
233 end
234 end
235 end
236 end
237
238
239 --here goes stash iterator if I find one
240 --help
241 local player=db.actor
242 player:iterate_inventory(getMags,nil)
243
244
245 --sganon edit begin
246 -- Diphenhydramine-HCl sent me a modified portion to augment the function to work with stashes
247 -- get NPC from ActorMenu, this works for inventory boxes (stashes) as well
248 -- dph
249 local hud = GetActorMenu()
250 if hud then
251 local npc = hud:GetPartner()
252 if npc and (not IsInvbox(npc)) then
253 npc:iterate_inventory(getMags,nil)
254 npc:iterate_inventory(constructWepMagsTable,nil)
255 end
256 -- stash iterator
257 if npc and IsInvbox(npc) then
258 npc:iterate_inventory_box(getMags,nil)
259 npc:iterate_inventory_box(constructWepMagsTable,nil)
260 end
261 npc=nil
262 end
263 --sganon edit end
264
265 player:iterate_inventory(constructWepMagsTable,nil)
266 player=nil
267
268end
269--===========================================
270
271
272local wuut_mags_storage = {}
273
274
275function save_state(m_data)
276 m_data.wuut_mags_storage = wuut_mags_storage
277end
278
279function load_state(m_data)
280 wuut_mags_storage = m_data.wuut_mags_storage or {}
281end
282
283function GetMagStorage(id)
284 return wuut_mags_storage[id] or ""
285end
286
287function SetMagStorage(id, data)
288 wuut_mags_storage[id] = data
289end
290
291local state_test = 7
292
293local flag_weapon_jammed = false
294
295
296function wuut_actor_menu_mode_changed(mode, last_mode )
297
298 print_f("actor_menu_mode_changed mode: " .. mode .. "last_mode" .. last_mode)
299
300
301end
302
303function wuut_InventoryWndClosed()
304 print_f("wuut_InventoryWndClosed")
305
306 LoadCurrentWeapon()
307
308end
309
310function wuut_DeadBodySearchWndClosed()
311 print_f("wuut_DeadBodySearchWndClosed")
312
313 LoadCurrentWeapon()
314
315end
316
317function weapon_jammed()
318
319 flag_weapon_jammed = true
320
321 print_f("weapon_jammed")
322
323 --SetHudMsg(game.translate_string("st_mag_weapon_jammed"), 2)
324 actor_menu.set_msg(1, game.translate_string("st_mag_weapon_jammed"),4)
325
326end
327
328function actor_on_first_update()
329 local function itr_inv(temp,inv_mag)
330
331 if ( isMagazine(inv_mag) ) then
332
333 MagazineCalculateWeight(inv_mag)
334
335 end
336
337 end
338
339 if(MAGAZINE_CALCULATE_WEIGHT) then
340 db.actor:iterate_inventory(itr_inv)
341 end
342end
343
344function on_key_release(key)
345
346
347 --[[
348 local bind = dik_to_bind(key)
349 if (bind == key_bindings.kWPN_RELOAD) then
350
351 print_f("spawn docs")
352
353 --alife():create("main_story_2_lab_x18_documents",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
354 --alife():create("main_story_1_quest_case",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
355 --alife():create("combat_scientific_outfit",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
356 --alife():create("af_ring_lead_box",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
357 --alife():create("itm_repairkit_tier_1",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
358 --alife():create("itm_repairkit_tier_2",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
359 --alife():create("itm_repairkit_tier_3",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
360 --alife():create("merc_exo_outfit",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
361
362
363
364 end
365 ]]
366
367 if (key == DIK_keys.DIK_T) then
368
369 --print_f("spawn some items")
370
371 --alife():create("mag_wpn_ak74_5.45x39_fmj",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
372 --alife():create("mag_wpn_ak74_5.56x45_fmj",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
373
374 --weapon:switch_state(stateReload)
375
376 end
377
378 if (key == DIK_keys.DIK_E) then
379
380 if( IsWeaponInHands() ) then
381
382 --[[
383 local weapon = db.actor:item_in_slot(db.actor:active_slot())
384 weapon:switch_state(state_test)
385 print_f("switch_state " .. state_test)
386
387 weapon:unload_magazine()
388 weapon:set_ammo_type(100)
389 weapon:set_ammo_elapsed(0)
390
391 --state_test = state_test + 1
392 ]]
393 end
394
395
396
397 --alife():create("mag_wpn_ak74_5.45x39_fmj",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
398 --alife():create("mag_wpn_ak74_5.56x45_fmj",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
399
400 end
401
402end
403
404function on_key_press(key)
405
406 StopLoading()
407
408end
409
410function IsWeaponInHands()
411 local wpn = db.actor:item_in_slot(db.actor:active_slot())
412 if (wpn and IsWeapon(wpn) and (not IsMelee(wpn))) then
413 return true
414 end
415
416 return false
417end
418
419function GetWeaponInHands()
420 local wpn = db.actor:item_in_slot(db.actor:active_slot())
421 if (wpn and IsWeapon(wpn) and (not IsMelee(wpn))) then
422 return wpn
423 end
424
425 return nil
426end
427
428
429local ignore_list = {
430 wpn_mp412 = true,
431 wpn_g43 = true,
432
433}
434
435local cancelReloadTimer = -1
436
437local reload_Weapon = nil
438local reload_Magazine = nil
439
440local grenadeMode = false
441
442function actor_on_weapon_reload(actor, weapon, ammo_total)
443
444
445 if(true) then
446
447 local weapon = db.actor:item_in_slot(db.actor:active_slot())
448 --if(weapon and ignore_list[weapon:section()]) then return end
449 local magData = WeaponGetMagData(weapon)
450
451 --print_f("actor_on_weapon_reload: " .. magData[iWEP_MSEC])
452
453 -- cancel reload only if we have a valid mag
454 if(system_ini():section_exist(WeaponGetDefaulMagSection(weapon)) == false ) then return end
455
456
457 --if(flag_weapon_jammed == false) then
458 if(grenadeMode == false) then
459
460 cancelReloadTimer = 0
461
462 end
463
464 end
465
466
467 --local weapon = db.actor:item_in_slot(db.actor:active_slot())
468 --weapon:switch_state(2)
469
470
471
472 --[[
473 if( IsWeaponInHands() ) then
474
475 print_f("IsWeaponInHands")
476
477 local weapon = db.actor:item_in_slot(db.actor:active_slot())
478 weapon:switch_state(2)
479 --print_f("switch_state " .. state_test)
480
481 --state_test = state_test + 1
482 end
483 ]]
484end
485
486--Diphenhydramine-HCl edit begin
487--dph cleaned and corrected this function (which seems not to be called by any addon I've used yet)
488function WeaponIsMagazineFed(weapon)
489 if weapon
490 and IsWeapon(weapon)
491 and (not IsMelee(weapon))
492 and system_ini():section_exist(WeaponGetDefaulMagSection(weapon))
493 then
494 return true
495 end
496 return false
497end
498--Diphenhydramine-HCl edit end
499
500
501function actor_on_weapon_fired(obj, weapon, ammo_elapsed, grenade_elapsed, ammo_type, grenade_type)
502 --print_f("actor_on_weapon_fired ")
503 if (obj:id() ~= AC_ID) then
504 return
505 end
506
507 LoadWeapon(weapon, true)
508end
509
510function LoadCurrentWeapon()
511
512 print_f("LoadCurrentWeapon")
513
514 if(grenadeMode) then return -1 end
515
516 local weapon = db.actor:item_in_slot(db.actor:active_slot())
517
518 if(weapon == nil or db.actor == nil) then return -1 end
519
520 if(system_ini():section_exist(WeaponGetDefaulMagSection(weapon)) == false ) then return end
521
522 print_f("LoadCurrentWeapon D2")
523
524 if (weapon and IsWeapon(weapon) and (not IsMelee(weapon))) then
525
526 --local currentState = weapon:get_state()
527
528 LoadWeapon(weapon, false)
529 print_f("LoadCurrentWeapon D3")
530 end
531
532
533end
534
535function LoadWeapon(weapon, feedNextRound)
536
537 local sec = weapon:section()
538 --print_f("pew " .. sec)
539
540 local id = weapon:id()
541 local wObj = alife_object(id)
542
543 local data = GetMagStorage(id) --utils_stpk.get_weapon_data(wObj)
544
545 --local ammos = txr_utils.get_weapon_ammo_list(wObj)
546
547 local ammo = utils_item.get_ammo(weapon:section(), weapon:id())-- txr_utils.get_weapon_ammo_list(weapon)
548 --print_f("" .. tostring(ammo))
549
550 --[[
551 if ammo and #ammo > 1 then
552 for i=1,#ammo do
553 local sec_ammo = ammo[i]
554
555 print_f("" .. sec_ammo)
556
557 end
558 end
559 ]]
560
561 --data.ammo_mag_size = 12
562
563 --print_f("wpn %s", data.inv_weight)
564
565 --data.inv_weight = 1.0
566
567 --data.ammo_current = 10
568 --data.custom = "asd"
569 --data.condition = 0.9
570
571 --utils_stpk.set_weapon_data(data,wObj)
572
573 --print_f("1" .. weapon.custom)
574 if (data ~= nil) then
575 --print_f("actor_on_weapon_fired " .. data.custom_data)
576
577 end
578
579 --wep1 = wep1 + 1
580 --data.custom_data = "" .. wep1
581
582 --[[
583 if (data.custom_data == "") then
584
585 data.custom_data = "5:44325"
586 utils_stpk.set_weapon_data(data,wObj)
587 end
588 ]]
589
590 -- feed next round
591
592 local dataWeapon = GetMagStorage(id) --utils_stpk.get_weapon_data(wObj)
593
594 local magData = str_explode(dataWeapon,":")
595 local magSlot = magData[iWEP_MSLOT]
596 local magSection = magData[iWEP_MSEC]
597
598 -- make sure we handle valid mag
599 if(magSlot == nil or magSection == nil) then return -1 end
600
601 if(system_ini():section_exist(magSection) == false) then
602
603 return -1
604
605 end
606
607 local magData_ammoCount = tonumber(magData[iWEP_COUNT]) - 1
608 local magData_ammoRounds = magData[iWEP_FILL]
609 local magData_ammoRounds_Next = string.sub(magData_ammoRounds,1,-2) -- string minus last char
610
611 if(feedNextRound == false) then
612 magData_ammoCount = magData_ammoCount + 1
613 magData_ammoRounds_Next = magData_ammoRounds
614
615 end
616
617
618 --local magData_ammoRounds_Next2 = string.sub(magData_ammoRounds_Next,1,-2)
619
620 if(magData_ammoCount > 0) then
621 local nextRound = string.sub(magData_ammoRounds_Next, -1)
622
623 --print_f("nextRound " .. nextRound)
624
625 local nextRoundIndex = tonumber(nextRound)
626
627 -- set next ammo type
628 local ammoType = nextRoundIndex
629 weapon:unload_magazine()
630 weapon:set_ammo_type(ammoType)
631 weapon:set_ammo_elapsed(tonumber(magData[iWEP_COUNT]))
632 end
633
634
635
636 -- update mag data
637 dataWeapon = magSlot .. ":" .. magSection .. ":" .. magData_ammoCount .. ":" .. magData_ammoRounds_Next
638
639 SetMagStorage(id, dataWeapon) -- utils_stpk.set_weapon_data(dataWeapon,wObj)
640
641 print_f("next mag data : " .. dataWeapon)
642
643
644end
645
646
647function CountAmmoBySection(section)
648
649
650 local count = 0
651
652 db.actor:inventory_for_each(function (item)
653 if (section == item:section() ) then
654 --ammos[#ammos+1] = item:id()
655 count = count + item:ammo_get_count()
656 end
657 end)
658
659 print_f("CountAmmoBySection " .. section .. " Count: " .. count)
660
661
662 return count
663
664end
665
666
667
668local is_loading = false
669
670local loading_mode = ""
671
672local timer = 0;
673
674
675local lastState = 0
676
677local stateReload = 7
678
679local reloading = false
680
681local lastAmmoIndex = 0
682local lastAmmoCount = 0
683
684local lastAmmoTable = {}
685
686local lastSlot = nil
687
688
689function animation_end(item,section,motion,state,slot)
690--function animation_end()
691
692 print_f("hud_animation_end [" .. tostring(item and item:name()) .. "] sec=" .. tostring(section) .. " motion=" .. tostring(motion) .. " state=" .. tostring(state) .. " slot=" .. tostring(state) .. "")
693
694end
695
696function IsGrenadeMode()
697 print_f("IS_GRENADE_MODE ")
698
699 local weapon = db.actor:item_in_slot(db.actor:active_slot())
700 if(weapon) then
701 local currentState = weapon:get_state()
702 if(currentState == 10) then
703 print_f("TRUE " .. currentState)
704
705 return true
706 end
707 print_f("FALSE " .. currentState)
708 return false
709 end
710 print_f("FALSE ")
711 return false
712end
713
714function main_loop()
715
716 -- checking states
717 if(db.actor) then
718
719 -- slot stuff
720 local currentSlot = db.actor:active_slot()
721 if(lastSlot ~= currentSlot) then
722 reload_Weapon = nil
723 reload_Magazine = nil
724
725 print_f("ReLOAD RESET weapon")
726
727 LoadCurrentWeapon()
728
729 end
730 lastSlot = currentSlot
731
732
733 local weapon = db.actor:item_in_slot(db.actor:active_slot())
734
735 --if(weapon == nil) then weapon = reload_Weapon end
736 if(reload_Weapon ~= nil) then weapon = reload_Weapon end
737
738
739 if (weapon and IsWeapon(weapon) and (not IsMelee(weapon))) then
740
741 local currentState = weapon:get_state()
742
743 --sprint_f("checking states current: " .. currentState .. " lastState " .. lastState)
744
745 if(currentState ~= lastState) then
746
747 print_f("NEW STATE: " .. currentState)
748
749 if(currentState == 10) then
750
751 if(grenadeMode == true) then
752 grenadeMode = false
753 else
754 grenadeMode = true
755 end
756
757 end
758
759 end
760
761
762 --
763 if(currentState ~= lastState and currentState == stateReload) then
764
765 empty_table(lastAmmoTable)
766
767 local wep_ammos = utils_item.get_ammo(weapon:section(), weapon:id()) --txr_utils.get_weapon_ammo_list(weapon) --alun_utils.parse_list(system_ini(),weapon:section(),"mag_ammo_class")
768 for i=1,#wep_ammos do
769 local ammo_sec = wep_ammos[i]
770 print_f("ammo_sec: " .. ammo_sec)
771 local ammo_count = CountAmmoBySection(ammo_sec)
772 print_f("ammo_count: " .. ammo_count)
773 lastAmmoTable[tostring(ammo_sec)] = ammo_count
774 end
775
776 for ammoType, lastAmmoCount in pairs(lastAmmoTable) do
777
778 print_f("-- ammoType: " .. tostring(ammoType))
779 end
780
781 --[[
782
783 local ammoIndex = weapon:get_ammo_type() -- GetAmmoIndexBySection(defaultMagSection, ammoName)
784
785 --
786 local current_ammo = weapon:get_ammo_in_magazine()
787 --if(current_ammo == 0) then ammoIndex = 0 end
788 lastAmmoIndex = ammoIndex
789 local ammoType = wep_ammos[ammoIndex + 1]
790 ]]
791
792 print_f("Reload: Start")
793 print_f("checking states currentState: " .. currentState .. " lastState " .. lastState)
794
795 reloading = true
796 --lastAmmoCount = CountAmmoBySection(ammoType)
797
798 --[[
799 if(lastAmmoCount == 0) then
800 ammoIndex = 0
801 ammoType = wep_ammos[ammoIndex + 1]
802 lastAmmoCount = CountAmmoBySection(ammoType)
803 lastAmmoIndex = ammoIndex
804 end
805 ]]
806
807 elseif(currentState ~= lastState and lastState == stateReload and currentState == 0) then
808
809 --[[
810 local ammoIndex = lastAmmoIndex -- weapon:get_ammo_type() -- GetAmmoIndexBySection(defaultMagSection, ammoName)
811 local wep_ammos = txr_utils.get_weapon_ammo_list(weapon) --alun_utils.parse_list(system_ini(),weapon:section(),"mag_ammo_class")
812
813 local ammoType = wep_ammos[ammoIndex + 1]
814 ]]
815
816 print_f("Reload: End")
817 print_f("checking states currentState: " .. currentState .. " lastState " .. lastState)
818
819 reloading = false
820
821 --[[
822 local count = CountAmmoBySection(ammoType)
823
824 local ammoRefund = lastAmmoCount - count
825
826 if(ammoRefund > 0 and reload_Weapon ~= nil) then
827 create_ammo(ammoType, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), AC_ID, ammoRefund)
828 end
829 ]]
830
831 for ammoType, lastAmmoCount in pairs(lastAmmoTable) do
832
833 print_f("-- ammoType: " .. tostring(ammoType))
834
835 local count = CountAmmoBySection(ammoType)
836
837 local ammoRefund = lastAmmoCount - count
838
839 if(ammoRefund > 0 and reload_Weapon ~= nil) then
840 create_ammo(ammoType, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), AC_ID, ammoRefund)
841 end
842 end
843
844 -----------------------------
845 print_f("PROPER ReLOAD Finalize")
846
847 if(reload_Weapon ~= nil) then
848
849 local loading_state = WeaponAttemptToLoadMagazine(reload_Weapon, reload_Magazine, true)
850
851 --if(loading_state == false) then
852 -- local weapon = db.actor:item_in_slot(db.actor:active_slot())
853 -- reload_Weapon:switch_state(2)
854 --end
855
856 reload_Weapon = nil
857 reload_Magazine = nil
858 end
859
860
861 end
862
863 lastState = currentState
864
865 end
866 end
867
868
869 if(cancelReloadTimer > -1) then
870
871
872 if(cancelReloadTimer == 0) then
873
874 print_f("cancelReloadTimer == 0")
875
876 --if(reloading ~= true) then
877
878 --xr_sound.stop_all_sounds()
879
880 local loading_state = false
881 local weapon = db.actor:item_in_slot(db.actor:active_slot())
882
883 if(flag_weapon_jammed) then
884
885 --print_f("Unjamming weapon")
886
887 -- eject only valid magazines
888 if(MagazineInWeaponIsValid(weapon)) then
889
890
891 local mag = weapon_eject_mag_functor(weapon)
892 --local data = utils_stpk.get_weapon_data(mag)
893 --data.custom_data = ammoCount .. ":" .. ammoFill
894 --utils_stpk.set_weapon_data(data,mag)
895
896
897 --reload_Weapon = weapon
898 --reload_Magazine = mag
899 PlayReloadAnimation(weapon)
900
901 --loading_state = true
902
903 end
904
905 flag_weapon_jammed = false
906
907
908 else
909
910 -- fake reload with animation
911 local function itr_inv(temp,inv_mag)
912
913 if ( isMagazine(inv_mag) == true and IsMagazineForWeapon(weapon, inv_mag) and string_ends_with(inv_mag:section(), "_ready") ) then
914 print_f("attempting reload " .. inv_mag:section() .. " ID: " .. inv_mag:id())
915
916 loading_state = WeaponAttemptToLoadMagazine(weapon, inv_mag, false)
917
918 if(loading_state) then
919 reload_Weapon = weapon
920 reload_Magazine = inv_mag
921 PlayReloadAnimation(weapon)
922 print_f("attempting reload Check is OK for " .. inv_mag:section() .. " ID: " .. inv_mag:id())
923
924 --cancelReloadTimer = cancelReloadTimer -1
925 return 0 --do return end-- return
926 end
927
928 end
929
930 end
931
932 db.actor:iterate_inventory(itr_inv)
933
934 end
935
936 if(loading_state == false) then
937 print_f("canceling reload")
938 local weapon = db.actor:item_in_slot(db.actor:active_slot())
939 weapon:switch_state(2)
940 end
941
942 --end
943
944 ---------------------------------------------
945 if(true) then
946
947 --print_f("PROPER ReLOAD Start")
948
949 --[[
950 local function itr_inv(temp,inv_mag)
951
952 if ( isMagazine(inv_mag) == true and IsMagazineForWeapon(weapon, inv_mag) and string_ends_with(inv_mag:section(), "_ready") ) then
953 print_f("attempting reload " .. inv_mag:section())
954
955 local loading_state = WeaponAttemptToLoadMagazine(weapon, inv_mag, true)
956
957
958
959 if(loading_state) then
960 --PlayReloadAnimation(weapon)
961 return
962 end
963
964 end
965
966 end
967
968 db.actor:iterate_inventory(itr_inv)
969 ]]
970
971
972 end
973
974 end
975
976 cancelReloadTimer = cancelReloadTimer -1
977
978 end
979
980
981 --print_f("asd")
982
983 --[[
984 if(db.actor) then
985 local wpn = db.actor:item_in_slot(db.actor:active_slot())
986 if (wpn) then
987
988 local current_weapon_state = wpn:get_state()
989
990 if(last_weapon_state == stateReload and last_weapon_state ~= current_weapon_state and IsWeaponInHands()) then
991
992 --wpn:set_ammo_elapsed(next_ammo_count)
993
994 print_f("final reload")
995
996 end
997
998 last_weapon_state = current_weapon_state
999
1000 --print_f("switch state to (%s) ", tostring(state_test))
1001 --wpn:switch_state(state_test)
1002
1003 --state_test = state_test + 1
1004 end
1005 end
1006 ]]
1007
1008 --[[
1009 local wpn = db.actor:item_in_slot(db.actor:active_slot())
1010 if (wpn) then
1011
1012 if(wpn:get_state() == stateReload) then
1013
1014 print_f("7")
1015
1016 end
1017
1018
1019 --print_f("switch state to (%s) ", tostring(state_test))
1020 --wpn:switch_state(state_test)
1021
1022 --state_test = state_test + 1
1023 end
1024 ]]
1025
1026 local tg = time_global()
1027
1028
1029
1030 if(is_loading) then
1031
1032 --print_f("main_loop " .. tostring(tg))
1033
1034 if(timer < tg) then
1035
1036 -- timer = tg + 400
1037
1038 --xr_sound.set_sound_play(db.actor:id(),"inv_stack")
1039 --xr_sound.set_sound_play(AC_ID,"reload_shell")
1040
1041 if(loading_mode == "ammo_to_mag") then
1042 timer = tg + magLoadTime
1043 MagazineAttemptLoadingWithBullets(loading_item1, loading_item2)
1044
1045 end
1046
1047 if(loading_mode == "mag_to_inv") then
1048 timer = tg + magUnloadTime
1049 MagazineAttemptUnloadBullet(loading_item2)
1050
1051 end
1052
1053
1054 else
1055
1056 timer = timer - 1
1057
1058
1059 end
1060
1061
1062 end
1063
1064 --[[
1065 local tg = time_global()
1066 if (_tmr and tg < _tmr) then
1067 return false
1068 end
1069 _tmr = tg + 2000 -- if you change this value timed artefact multipliers will need changes
1070
1071 if not (db.actor) then
1072 return false
1073 end
1074
1075 ]]
1076
1077 return
1078end
1079
1080function MagazineInWeaponIsValid(weapon)
1081
1082 local magData = WeaponGetMagData(weapon)
1083
1084 local magSection = magData[iWEP_MSEC]
1085
1086
1087 -- make sure we have a valid mag string here
1088 if(magSection ~= nil and system_ini():section_exist(magSection)) then
1089 print_f("MagazineInWeaponIsValid " .. magSection )
1090
1091 return true
1092
1093 end
1094
1095 return false
1096end
1097
1098function weapon_eject_mag_precondition(weapon)
1099
1100 print_f("weapon_eject_mag_precondition")
1101
1102 --check if there is a valid mag in weapon
1103 if (weapon and IsWeapon(weapon) and (not IsMelee(weapon))) then
1104
1105 print_f("weapon_eject_mag_precondition1")
1106
1107 if(MagazineInWeaponIsValid(weapon)) then
1108
1109 print_f("MagazineInWeaponIsValid")
1110
1111 return game.translate_string("st_mag_eject_magazine")
1112
1113 end
1114
1115 end
1116
1117end
1118
1119function weapon_eject_mag_functor(weapon)
1120
1121 local magData = WeaponGetMagData(weapon)
1122 local magSlot = magData[iWEP_MSLOT]
1123 local magSection_ready = magData[iWEP_MSEC]
1124 local ammoCount = tonumber(magData[iWEP_COUNT])
1125 local ammoFill = magData[iWEP_FILL]
1126
1127 -- empty magazine
1128 WeaponSetMagData(weapon, "N:no_mag:0:")
1129 weapon:unload_magazine()
1130 --weapon:set_ammo_type(ammo_type)
1131 weapon:set_ammo_elapsed(0)
1132
1133
1134 local magSection=string.gsub(magSection_ready, "_ready", "")
1135
1136 local mag=nil
1137 local inUI=false
1138 if(ui_inventory.GUI) then
1139 if(ui_inventory.GUI:IsShown()) then
1140 --if we're in the inventory, don't drop the mag.
1141 inUI=true
1142 end
1143 end
1144
1145 if((dropMags==true) and (ammoCount==0) and not(inUI)) then
1146 --magazine will be dropped to the floor for more operator experience! But only if you're not in the inventory
1147 mag = alife():create(magSection,db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id())
1148 else
1149 -- This is the standard path for Pepsifan04's options
1150 -- 0 always keep mag active
1151 -- 1 deactivate when below treshold
1152 -- 2 always deactivate after reload
1153 -- create magazine in inventory
1154 if(keepMagActive==0) then
1155 magSection=magSection_ready
1156 elseif(keepMagActive==1) then
1157 local currentAmmo=ammoCount / system_ini():r_u32(magSection, "max_mag_size")
1158 if( ((currentAmmo) *100) >=activeMagTreshold) then
1159 magSection=magSection_ready
1160 end
1161 end
1162 mag = alife():create(magSection,db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
1163 end
1164
1165 --WeaponSetMagData(mag, ammoCount .. ":" .. ammoFill)
1166 local data = GetMagStorage(mag.id) --utils_stpk.get_weapon_data(mag)
1167 data = magSlot .. ":" .. ammoCount .. ":" .. ammoFill
1168 print_f("weapon_eject_mag_functor create mag " .. data)
1169 SetMagStorage(mag.id, data) -- utils_stpk.set_weapon_data(data,mag)
1170
1171
1172 --alife():register(mag)
1173
1174 --local mag2 = level.object_by_id( mag.id )
1175 if(MAGAZINE_CALCULATE_WEIGHT) then
1176 --MagazineCalculateWeight(mag.object)
1177 --CreateTimeEvent(mag.id,"delayed_weight_calc",1,delayed_weight_calc,mag.id)
1178 CreateTimeEvent("delayed_weight_calc", "delayed_weight_calc", 1, delayed_weight_calc, mag.id)
1179 end
1180
1181 return mag
1182end
1183
1184function delayed_weight_calc(id)
1185 local itm = id and level.object_by_id(id)
1186 if (itm) then
1187 MagazineCalculateWeight(itm)
1188 return true
1189 end
1190 return false
1191end
1192
1193function mag_unload_ammo_precondition(item)
1194
1195 -- TODO:
1196 --return "unload_ammo"
1197
1198
1199 local is_mag = isMagazine(item)
1200 --local is_weapon = IsWeapon(weapon)
1201
1202 if(is_mag) then
1203
1204 local magData = WeaponGetMagData(item)
1205 local magCount = tonumber(magData[iMAG_COUNT])
1206
1207 if(magCount > 0) then
1208 --return "unload ammo (" .. magCount .. ")"
1209
1210 return game.translate_string("st_mag_unload_ammo") .. " (" .. magCount .. ")"
1211
1212
1213 end
1214
1215 end
1216
1217
1218
1219end
1220
1221local asd = 0
1222
1223function mag_unload_ammo_functor(weapon)
1224
1225 print_f("unload_mag_functor")
1226
1227 --[[
1228 local id = weapon:id()
1229 local wObj = alife_object(id)
1230
1231 local dataWeapon = utils_stpk.get_weapon_data(wObj)
1232
1233 print_f("old mag data : " .. dataWeapon.custom_data)
1234
1235 dataWeapon.custom_data = "" .. 1 .. ":" .. asd
1236
1237 utils_stpk.set_weapon_data(dataWeapon,wObj)
1238
1239 print_f("next mag data : " .. dataWeapon.custom_data)
1240
1241 asd = asd + 1
1242 ]]
1243
1244 StopLoading()
1245
1246 is_loading = true
1247 loading_item1 = nil
1248 loading_item2 = weapon
1249 loading_mode = "mag_to_inv"
1250
1251
1252end
1253
1254--[[
1255function round(num, numDecimalPlaces)
1256 local mult = 10^(numDecimalPlaces or 0)
1257 return math.floor(num * mult + 0.5) / mult
1258end
1259]]
1260
1261function GetMagazineSlot(item)
1262
1263 local magData = WeaponGetMagData(item)
1264 local magSlot = magData[iMAG_SLOT]
1265 return magSlot
1266end
1267
1268function GetNextAvailableMagazineSlotFor(item)
1269 if(isMagazine(item)) then
1270
1271 local mag_limit_small = 0
1272 local mag_limit_medium = 0
1273 local mag_limit_large = 0
1274
1275
1276 local magCountSmall = 0
1277 local magCountMedium = 0
1278 local magCountLarge = 0
1279
1280 -- get the slot limits for our outfit
1281 local outfit = db.actor:item_in_slot(7)
1282
1283 if(outfit == nil) then
1284 mag_limit_small = system_ini():r_u32("wlc_none", "mag_limit_small")
1285 mag_limit_medium = system_ini():r_u32("wlc_none", "mag_limit_medium")
1286 mag_limit_large = system_ini():r_u32("wlc_none", "mag_limit_large")
1287 else
1288
1289 --print_f("outfit sec " .. outfit:section())
1290
1291
1292 local outfitType = system_ini():r_string_ex(outfit:section(), "kind")
1293 --print_f("outfitType " .. outfitType)
1294
1295 -- see if we have a specific outfit config
1296 if(system_ini():section_exist("wlc_" .. outfit:section())) then
1297 mag_limit_small = system_ini():r_u32("wlc_" .. outfit:section(), "mag_limit_small")
1298 mag_limit_medium = system_ini():r_u32("wlc_" .. outfit:section(), "mag_limit_medium")
1299 mag_limit_large = system_ini():r_u32("wlc_" .. outfit:section(), "mag_limit_large")
1300 else -- we don't load default values
1301
1302 local outfitSectionDefault = ""
1303
1304 if(outfitType == "o_light") then
1305 outfitSectionDefault = "wlc_light"
1306 elseif(outfitType == "o_medium") then
1307 outfitSectionDefault = "wlc_medium"
1308 elseif(outfitType == "o_heavy") then
1309 outfitSectionDefault = "wlc_heavy"
1310 elseif(outfitType == "o_sci") then
1311 outfitSectionDefault = "wlc_sci"
1312 end
1313
1314 print_f("outfitSectionDefault " .. outfitSectionDefault)
1315
1316 mag_limit_small = system_ini():r_u32(outfitSectionDefault, "mag_limit_small")
1317 mag_limit_medium = system_ini():r_u32(outfitSectionDefault, "mag_limit_medium")
1318 mag_limit_large = system_ini():r_u32(outfitSectionDefault, "mag_limit_large")
1319
1320 end
1321
1322 end
1323
1324
1325 local function itr_inv(temp, inv_mag)
1326
1327 if ( isMagazine(inv_mag) == true ) then
1328 --print_f("test " .. inv_mag:section())
1329 --if (db.actor:is_on_belt(inv_mag) == false and is_in_slot(inv_mag) == false) then
1330
1331 --local mag_size = ini_sys:r_string_ex(inv_mag:section(),"mag_size",false)
1332
1333 --print_f("mag_size " .. mag_size)
1334
1335 local magSlot = GetMagazineSlot(inv_mag)
1336
1337 if (magSlot == "S" and string_ends_with(inv_mag:section(), "_ready")) then
1338 magCountSmall = magCountSmall + 1
1339
1340 elseif (magSlot == "M" and string_ends_with(inv_mag:section(), "_ready")) then
1341 magCountMedium = magCountMedium + 1
1342
1343 elseif (magSlot == "L" and string_ends_with(inv_mag:section(), "_ready")) then
1344 magCountLarge = magCountLarge + 1
1345
1346 end
1347 end
1348
1349 --print_f("mags found: " .. magCountSmall .. " - " .. magCountMedium)
1350 --return magCountSmall, magCountMedium
1351
1352 end
1353
1354 db.actor:iterate_inventory(itr_inv)
1355
1356 -----------
1357
1358 print_f("mags found: " .. magCountSmall .. " - " .. magCountMedium)
1359
1360 local mag_size = ini_sys:r_string_ex(item:section(),"mag_size",false)
1361
1362 local nextAvailableSlot = "N"
1363
1364 --check space in small pouches (for small mags only)
1365 if (nextAvailableSlot == "N" and magCountSmall < mag_limit_small and mag_size == "small") then
1366 nextAvailableSlot = "S"
1367 return nextAvailableSlot
1368 end
1369 --check space in medium pouches (for small and medium mags)
1370 if (nextAvailableSlot == "N" and magCountMedium < mag_limit_medium and (mag_size == "small" or mag_size == "medium") ) then
1371 nextAvailableSlot = "M"
1372 return nextAvailableSlot
1373 end
1374 --check space in large pouches (for small and medium and large mags)
1375 if (nextAvailableSlot == "N" and magCountLarge < mag_limit_large and (mag_size == "small" or mag_size == "medium" or mag_size == "large") ) then
1376 nextAvailableSlot = "L"
1377 return nextAvailableSlot
1378 end
1379
1380 -- return default "N"
1381 return nextAvailableSlot
1382 end
1383end
1384
1385
1386function add_mag_to_loadout_precondition(item)
1387 local parent = item:parent()
1388 if not (parent and parent:id() == AC_ID) then
1389 return
1390 end
1391 --print_f("add_mag_to_loadout_precondition")
1392
1393 if(isMagazine(item)) then
1394
1395 local magData = WeaponGetMagData(item)
1396 local magSlot = magData[iMAG_SLOT]
1397 local nextSlot = GetNextAvailableMagazineSlotFor(item)
1398
1399 --
1400 if( string_ends_with(item:section(), "_ready")) then
1401 --return "remove (" .. magSlot .. ")"
1402 return game.translate_string("st_mag_loadout_remove") .. " (" .. magSlot .. ")"
1403
1404 elseif(nextSlot ~= "N") then
1405 --return "add to loadout (" .. nextSlot .. ")"
1406 return game.translate_string("st_mag_loadout_add") .. " (" .. nextSlot .. ")"
1407
1408 end
1409
1410 end
1411
1412
1413end
1414
1415function add_mag_to_loadout_functor(item)
1416
1417 local nextSlot = GetNextAvailableMagazineSlotFor(item)
1418 local magData = WeaponGetMagData(item)
1419 local ammoCount = tonumber(magData[iMAG_COUNT])
1420 local ammoFill = magData[iMAG_FILL]
1421
1422 local newMagSec = ""
1423
1424 if( string_ends_with(item:section(), "_ready")) then
1425 newMagSec = string.gsub(item:section(), "%_ready", "")
1426 else
1427 newMagSec = item:section() .. "_ready"
1428 end
1429
1430 print_f("newMagSec " .. newMagSec)
1431
1432
1433 if(system_ini():section_exist(newMagSec)) then
1434
1435 -- kill old mag
1436 alife():release(alife_object(item:id()), true)
1437 SetMagStorage(item:id(), nil)
1438
1439 -- make new one
1440 local newMag = alife():create(newMagSec,db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
1441 local data = GetMagStorage(newMag.id) --utils_stpk.get_weapon_data(newMag)
1442 -- transfer mag data
1443 data = nextSlot .. ":" .. ammoCount .. ":" .. ammoFill
1444 SetMagStorage(newMag.id, data) -- utils_stpk.set_weapon_data(data, newMag)
1445
1446 end
1447
1448end
1449
1450
1451function isMagazine(item)
1452
1453 --print_f("isMagazine")
1454
1455 local is_mag = system_ini():r_bool_ex(item:section(),"is_mag")
1456
1457 if(is_mag == true) then
1458
1459 --print_f("val %s", is_mag)
1460
1461 return true
1462
1463 end
1464
1465 return false
1466
1467end
1468
1469function StopLoading()
1470
1471 is_loading = false
1472 loading_item1 = nil
1473 loading_item2 = nil
1474
1475end
1476
1477
1478function MagazineAttemptUnloadBullet(magazine)
1479
1480 local magData = WeaponGetMagData(magazine)
1481 local magSlot = magData[iMAG_SLOT]
1482 local currentAmmoCount = tonumber(magData[iMAG_COUNT])
1483 local ammoFill = magData[iMAG_FILL]
1484 --local ammoIndex = GetAmmoIndexBySection(magazine, item)
1485
1486
1487 if( currentAmmoCount > 0 ) then
1488
1489 -- get last bullet
1490 local nextRound = string.sub(ammoFill, -1)
1491 local nextRoundIndex = tonumber(nextRound)
1492 local ammoType = GetAmmoTypeByIndex(magazine, nextRoundIndex)
1493
1494 print_f("MagazineAttemptUnloadBullet creating " .. ammoType)
1495
1496 -- update ammo count and fill
1497 local magData_ammoRounds_Next = string.sub(ammoFill,1,-2)
1498
1499 WeaponSetMagData(magazine, magSlot .. ":" .. currentAmmoCount -1 .. ":" .. magData_ammoRounds_Next)
1500
1501 if(MAGAZINE_CALCULATE_WEIGHT) then
1502 MagazineCalculateWeight(magazine)
1503 end
1504
1505 --magData.custom_data = "" .. currentAmmoCount -1 .. ":" .. magData_ammoRounds_Next
1506 --utils_stpk.set_weapon_data(magData,magazine)
1507
1508 -- create according round in inventory
1509 create_ammo(ammoType, db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id(), AC_ID, 1)
1510
1511 UpdateMagazineUI(magazine)
1512
1513 else
1514
1515 StopLoading()
1516
1517
1518 end
1519
1520end
1521
1522function MagazineCalculateWeight(magazine)
1523 local mag_weight_empty = system_ini():r_float_ex(magazine:section(), "inv_weight")
1524
1525 local magData = WeaponGetMagData(magazine)
1526 local magSlot = magData[iMAG_SLOT]
1527 local currentAmmoCount = tonumber(magData[iMAG_COUNT])
1528 local ammoFill = magData[iMAG_FILL]
1529
1530 for i = 1, #ammoFill do
1531 local index = ammoFill:sub(i,i)
1532
1533 local ammoType = GetAmmoTypeByIndex(magazine, tonumber(index))
1534 local box_size = system_ini():r_float_ex(ammoType, "box_size")
1535 local box_weight = system_ini():r_float_ex(ammoType, "inv_weight")
1536 local cartridge_weight = box_weight / box_size
1537
1538 mag_weight_empty = mag_weight_empty + cartridge_weight
1539
1540 end
1541
1542 magazine:set_weight(mag_weight_empty)
1543
1544end
1545
1546function MagazineAttemptLoadingWithBullets(item, magazine)
1547
1548 local magData = WeaponGetMagData(magazine)
1549 local magSlot = magData[iMAG_SLOT]
1550 local currentAmmoCount = tonumber(magData[iMAG_COUNT])
1551 local ammoFill = magData[iMAG_FILL]
1552 local ammoIndex = GetAmmoIndexBySection(magazine:section(), item:section()) - 1
1553
1554 --madgamer98 - wuut I've passed these along as a gloabl variable so that the inventory loop function can use them later
1555 ammoName = item:section()
1556 ammoId = item:id()
1557 true_ammo_box_size = 0
1558 -- end added code madgamer98
1559 local ammo_box_size = item:ammo_get_count()
1560 --local wpn_ammo_size = GetMagAmmo(magazine)--magazine:get_ammo_in_magazine()
1561
1562 local wpn_ammo_max = system_ini():r_u32(magazine:section(), "max_mag_size")
1563
1564 --print_f("ammo to mag " .. ammo_box_size .. " / " .. wpn_ammo_size)
1565
1566 local check = IsAmmoForMagazine(magazine, item) and currentAmmoCount < wpn_ammo_max
1567
1568 --print_f("mag ammo class: " .. magazine:get_ammo_name())
1569
1570 print_f("currentAmmoCount: " .. currentAmmoCount)
1571 print_f("ammoIndex: " .. ammoIndex)
1572 print_f("ammoFill: " .. ammoFill)
1573
1574
1575 ammoFill = ammoFill .. ammoIndex
1576
1577 if(ammoIndex == -1) then check = false end
1578
1579 --local current_mag_ammo_name = magData[2]
1580
1581 --local same_ammo = magazine:get_ammo_name() == item:section()
1582 --local same_ammo = current_mag_ammo_name == item:section()
1583
1584 --print_f("%s = %s", current_mag_ammo_name , item:section())
1585
1586 if(check) then
1587
1588 --[[
1589 -- different ammo and ammo count is 0
1590 if (same_ammo == false and wpn_ammo_size == 0) then
1591
1592 -- change ammo type before loading
1593
1594
1595
1596 local ammo_type = magazine:get_ammo_type()
1597 ammo_type = math.abs(ammo_type-1)
1598 magazine:set_ammo_type(ammo_type)
1599
1600
1601 --print_f("changing ammo:" .. tostring(ammo_type))
1602 end
1603
1604 if (same_ammo == false and wpn_ammo_size > 0) then
1605
1606 --print_f("wrong ammo type")
1607
1608 StopLoading()
1609
1610 else
1611 ]]
1612 --print_f("ammocheck OK")
1613
1614 -- Update ammo box count
1615 item:ammo_set_count(ammo_box_size - 1)
1616
1617 -- Update mag count
1618 --magazine:set_ammo_elapsed(wpn_ammo_size + 1)
1619 --SetMagAmmo(magazine, wpn_ammo_size + 1)
1620
1621 --WeaponSetMagData(magazine, magazine:section() .. ":" .. magazine:get_ammo_name() .. ":" .. wpn_ammo_size + 1)
1622 --WeaponSetMagData(magazine, magazine:section() .. ":" .. item:section() .. ":" .. wpn_ammo_size + 1)
1623 WeaponSetMagData(magazine, magSlot .. ":" .. currentAmmoCount + 1 .. ":" .. ammoFill)
1624
1625 if(MAGAZINE_CALCULATE_WEIGHT) then
1626 MagazineCalculateWeight(magazine)
1627 end
1628
1629 --xr_sound.set_sound_play(db.actor:id(),"inv_stack")
1630 xr_sound.set_sound_play(AC_ID,"reload_shell")
1631 --xr_sound.set_sound_play(AC_ID, "pda_task")
1632
1633 -- remove empty ammo
1634 if ((ammo_box_size - 1) == 0 ) then
1635
1636
1637 --madgamer98 - hey wuut this here is the calling the function below to search through the players inventory right as the ammo runs out
1638 if (db.actor) then
1639 local npc = db.actor
1640 npc:iterate_inventory(grab_inv_items, npc)
1641 end
1642 --end added code madgamer98
1643 local ammo_box_object = alife_object(item:id())
1644 alife():release(ammo_box_object, true)
1645
1646 StopLoading()
1647
1648 --madgamer98 - wuut this if statement checks if you still have more ammo in your inventory through the variable set ealier when we lopped through the inventory If you do have more ammo it sets up the main loops to run again with the new ammo selected and the old magazine that was being loaded. This allows it to continue loading after one of the ammo boxes gets consumed/deleted if you still have remaining ammo loadable
1649 if ((true_ammo_box_size) ~= 0) then
1650 is_loading = true
1651 loading_item1 = newAmmo
1652 loading_item2 = magazine
1653 loading_mode = "ammo_to_mag"
1654 end
1655 --end added code madgamer98
1656 end
1657
1658 --end
1659
1660 UpdateMagazineUI(magazine)
1661
1662 else
1663 StopLoading()
1664 end
1665
1666
1667
1668end
1669
1670--madgamer98 - wuut function to go through the inventory grab another ammo box that has the same name as the one currently being loaded and grabbing the ammo count of all of them as well as a single id of the same ammo type
1671function grab_inv_items(npc, item)
1672 local isAmmo = IsAmmo(item)
1673
1674 if(isAmmo) then
1675 print_f(": " .. item:section())
1676 if(ammoName == item:section()) then
1677 true_ammo_box_size = true_ammo_box_size + item:ammo_get_count()
1678 print_f("ammo-size: " .. true_ammo_box_size)
1679 if (ammoId ~= item:id()) then
1680 newAmmo = item
1681 end
1682 end
1683 end
1684end
1685--end added code madgamer98
1686function GetAmmoTypeByIndex(item, index)
1687
1688 local ammo = parse_list(system_ini(),item:section(),"mag_ammo_class")
1689
1690 return ammo[index + 1]
1691
1692end
1693
1694function GetAmmoIndexBySection(item_section, ammo_section)
1695
1696 print_f("GetAmmoIndexBySection " .. item_section .. " - " .. ammo_section)
1697
1698 --local ammo = alun_utils.parse_list(system_ini(),"ag_ammo_5.45x39","mag_ammo_class",true)
1699 local ammo = parse_list(system_ini(),item_section,"mag_ammo_class")
1700 --local ammo = txr_utils.get_weapon_ammo_list(item_section)
1701
1702 --print_f(" sec" .. ammo[ "" .. ammo_box:section()])
1703
1704 if ammo and #ammo > 1 then
1705 for i=1,#ammo do
1706 local sec_ammo = ammo[i]
1707
1708 --print_f("parsing " .. sec_ammo .. " for " .. ammo_box:section())
1709
1710 if(sec_ammo == ammo_section) then
1711
1712 return i
1713 end
1714 end
1715 end
1716
1717 --[[
1718 if (ammos[ammo_box:section()]) then
1719 return ammos[""..ammo_box:section()]
1720 end
1721 ]]
1722
1723 return -1
1724end
1725
1726function IsAmmoForMagazine(weapon_mag, ammo_box)
1727
1728 local ammos = parse_list(system_ini(),weapon_mag:section(),"mag_ammo_class",true)
1729 if (ammos[ammo_box:section()]) then
1730 return true
1731 end
1732 --[[
1733 local sim = alife()
1734 for i=2,3 do
1735 local wpn = db.actor:item_in_slot(i)
1736 if (wpn) then
1737 local ammos = alun_utils.parse_list(system_ini(),wpn:section(),"mag_ammo_class",true)
1738 if (ammos[sec]) then
1739 return true
1740 end
1741 end
1742 end
1743 ]]
1744 return false
1745end
1746
1747function DEBUG_PrintAmmoClass(ammo)
1748 if ammo and #ammo > 1 then
1749 for i=1,#ammo do
1750 local sec_ammo = ammo[i]
1751
1752 print_f("" .. sec_ammo)
1753
1754 end
1755 end
1756end
1757
1758function IsMagazineForWeapon(weapon, magazine)
1759
1760 -- get weapon prefix
1761 local weaponBaseParts = str_explode(weapon:section(),"_")
1762
1763 local weaponBase = weaponBaseParts[1] .. "_" .. weaponBaseParts[2]
1764
1765 -- sganon begin
1766 -- make an exception for the Duty AEK which has a different ammo section
1767 -- this fixes an impossibility to define AK47-compatible AEK mags in 7.62x39
1768 if(weaponBaseParts[3] ~= nil) then
1769 if(weaponBaseParts[3] == "duty" and weaponBase == "wpn_aek") then
1770 weaponBase = weaponBase .. "duty"
1771 print_f("sganon AEK duty patched in function IsMagazineForWeapon: " .. weaponBase)
1772 end
1773 end
1774 -- sganon end
1775
1776 local mag_ammos = parse_list(system_ini(),magazine:section(),"mag_ammo_class")
1777 --local wep_ammos = txr_utils.get_weapon_ammo_list(weapon) --alun_utils.parse_list(system_ini(),weapon:section(),"mag_ammo_class")
1778
1779 local wep_ammos = utils_item.get_ammo(weapon:section(), weapon:id())
1780
1781
1782 --print_f("mag_ammos")
1783 --DEBUG_PrintAmmoClass(mag_ammos)
1784 --print_f("wep_ammos")
1785 --DEBUG_PrintAmmoClass(wep_ammos)
1786
1787
1788 local magazine_group = parse_list(system_ini(),magazine:section(),"magazine_group",true)
1789 if (magazine_group[weaponBase] and mag_ammos[1] == wep_ammos[1]) then
1790 return true
1791 end
1792
1793 return false
1794end
1795
1796function WeaponAttemptToLoadMagazine(weapon, mag, properReload)
1797
1798 -- validate weapon
1799 if (weapon and IsWeapon(weapon) and (not IsMelee(weapon))) then
1800
1801 -- validate mag
1802 if(IsMagazineForWeapon(weapon, mag)) then
1803
1804 -- only load magazines that are not empty
1805 local magData = WeaponGetMagData(mag)
1806 if(tonumber(magData[iMAG_COUNT]) == 0) then return false end
1807
1808
1809 -- eject mag if necessary also only on preper reload
1810 if(MagazineInWeaponIsValid(weapon) and properReload) then
1811
1812 weapon_eject_mag_functor(weapon)
1813
1814 end
1815
1816 if(properReload) then
1817 -- get mag data
1818 local magData = WeaponGetMagData(mag)
1819 local magSlot = magData[iMAG_SLOT]
1820 local ammoCount = tonumber(magData[iMAG_COUNT])
1821 local ammoFill = magData[iMAG_FILL]
1822
1823 WeaponSetMagData(weapon, magSlot .. ":" .. mag:section() .. ":" .. ammoCount .. ":" .. ammoFill)
1824
1825 -- adjust ammo type and load weapon
1826 local nextRound = string.sub(ammoFill, -1)
1827 local nextRoundIndex = tonumber(nextRound)
1828 local ammoType = GetAmmoTypeByIndex(mag, nextRoundIndex)
1829 weapon:unload_magazine()
1830 weapon:set_ammo_type(nextRoundIndex)
1831 weapon:set_ammo_elapsed(ammoCount)
1832
1833 -- remove magazine from inventory
1834 --alife():release(mag, true)
1835 alife():release(alife_object(mag:id()), true)
1836 SetMagStorage(mag:id(), nil)
1837
1838 end
1839
1840 return true
1841 end
1842
1843
1844 end
1845
1846 return false
1847
1848end
1849
1850
1851function PlayReloadAnimation(weapon)
1852
1853 print_f("PlayReloadAnimation")
1854
1855 --[[
1856 local sec2 = weapon:section()
1857
1858 local reload_type = "rifle_reload"
1859 if (system_ini():r_string_ex(sec2, "repair_type") == "pistol") then reload_type = "pistol_reload" end
1860 local snd = sound_object(system_ini():r_string_ex(sec2, "snd_reload"))
1861 snd:play(db.actor,0,sound_object.s2d)
1862 actor_effects.use_item(reload_type)
1863 ]]
1864
1865 weapon:switch_state(stateReload)
1866
1867
1868 --xr_effects.disable_ui_inventory(db.actor, nil)
1869 --xr_effects.disable_ui_lite_with_imput(db.actor, nil)
1870
1871 --level.disable_input()
1872
1873 --local hud = get_hud()
1874 --hud:HideActorMenu()
1875
1876
1877
1878 --weapon:set_ammo_elapsed(3)
1879end
1880
1881local weaponTemp = nil
1882
1883function on_item_drag_dropped(item, weapon, from_slot, to_slot)
1884
1885 print_f("on_item_drag_dropped " .. item:section() .. " on " .. weapon:section() .. " to_slot " .. to_slot)
1886
1887 -- Check capability
1888 if not (from_slot == EDDListType.iActorBag and (to_slot == EDDListType.iActorBag or to_slot == EDDListType.iActorSlot ) ) then
1889 return
1890 end
1891
1892 if(item:id() == weapon:id()) then
1893 return
1894 end
1895
1896 --print_f(IsAmmo(item))
1897
1898 --print_f(isMagazine(weapon))
1899
1900 if(IsAmmo(item) and isMagazine(weapon)) then
1901
1902 if(is_loading) then
1903 StopLoading()
1904 end
1905
1906 is_loading = true
1907 loading_item1 = item
1908 loading_item2 = weapon
1909 loading_mode = "ammo_to_mag"
1910
1911 else
1912
1913 StopLoading()
1914
1915
1916
1917 end
1918
1919 local stateLessReload = false
1920
1921
1922 if(from_slot == EDDListType.iActorBag and to_slot == EDDListType.iActorBag) then
1923
1924 stateLessReload = true
1925
1926 end
1927
1928 if(from_slot == EDDListType.iActorBag and to_slot == EDDListType.iActorSlot) then
1929
1930 local activeWeapon = GetWeaponInHands()
1931
1932 if(activeWeapon ~= nil and activeWeapon:id() == weapon:id()) then
1933 stateLessReload = false
1934 else
1935 stateLessReload = false
1936 end
1937
1938 end
1939
1940
1941
1942
1943 if(stateLessReload) then
1944
1945 print_f("STATELESSRELOAD TRUE")
1946
1947 local loading_state = WeaponAttemptToLoadMagazine(weapon, item, true)
1948
1949 if(loading_state) then
1950 PlayReloadAnimation(weapon)
1951 end
1952
1953 else
1954 print_f("STATELESSRELOAD FALSE")
1955
1956 -- mag dropped on weapon
1957 local loading_state = WeaponAttemptToLoadMagazine(weapon, item, false)
1958
1959 --[[
1960 if(loading_state) then
1961 PlayReloadAnimation(weapon)
1962 end
1963 ]]
1964 if(loading_state) then
1965 reload_Weapon = weapon
1966 reload_Magazine = item
1967 PlayReloadAnimation(weapon)
1968 print_f("(2) attempting reload Check is OK for " .. item:section() .. " ID: " .. item:id())
1969 end
1970
1971
1972 end
1973
1974
1975
1976 --[[
1977 local sec_1 = obj_1:section()
1978 local sec_2 = obj_2:section()
1979
1980 if itms_arty_container[sec_2] then
1981 if (ini_sys:r_string_ex(sec_1,"class") == "ARTEFACT") or (ini_sys:r_string_ex(sec_1,"class") == "SCRPTART") then
1982 dropdrop_ArtyContainer(obj_1, obj_2, sec_1, sec_2)
1983 end
1984
1985 elseif itms_disassemble[sec_1] and itms_disassembly.ui_menu(obj_2) then -- Disassemble
1986 itms_disassembly.tool_action(obj_2, obj_1)
1987
1988 elseif IsWeapon(obj_2) and is_ammo(nil,sec_1) then
1989 --dropdrop_AmmoInjection(obj_1, obj_2, sec_1, sec_2)
1990
1991 elseif item_combine[sec_1] and item_combine[sec_1][sec_2] then
1992 dropdrop_Basic_Combination(obj_1, obj_2, sec_1, sec_2)
1993
1994 else
1995 dropdrop_Multi_Combination(obj_1, obj_2, sec_1, sec_2)
1996 end
1997 ]]
1998end
1999
2000function WeaponGetDefaulMagSection(weapon)
2001
2002 -- assemble magazine section from weapon section and calibre section
2003 local weaponSection = weapon:section()
2004
2005 local weaponBaseParts = str_explode(weapon:section(),"_")
2006
2007 if(weaponBaseParts[1] == nil or weaponBaseParts[2] == nil) then return "invalid_weapon" end
2008
2009
2010 --print_f("weaponBaseParts1" .. weaponBaseParts[1])
2011 --print_f("weaponBaseParts2" .. weaponBaseParts[2])
2012
2013 local weaponBase = weaponBaseParts[1] .. "_" .. weaponBaseParts[2]
2014 -- sganon begin
2015 -- make an exception for the Duty AEK which has a different ammo section
2016 -- this fixes an impossibility to define AK47-compatible AEK mags in 7.62x39
2017 if(weaponBaseParts[3] ~= nil) then
2018 if(weaponBaseParts[3] == "duty" and weaponBase == "wpn_aek") then
2019 weaponBase = weaponBase .. "duty"
2020 print_f("sganon AEK duty patched in function WeaponGetDefaulMagSection: " .. weaponBase)
2021 end
2022 end
2023 -- sganon end
2024
2025 --local ammo = txr_utils.get_weapon_ammo_list(weapon)
2026 local ammo = utils_item.get_ammo(weapon:section(), weapon:id())
2027
2028 -- Check for corrupted weapons
2029
2030 if(ammo[1] ~= nil) then
2031
2032 local ammoName = string.gsub(ammo[1], "%ammo_", "") --alun_utils.str_explode(ammo[1],"ammo_")
2033
2034 --ammoName =
2035
2036
2037 local defaultMagSection = "mag_" .. weaponBase .. "_" .. ammoName
2038
2039 return defaultMagSection
2040
2041 else
2042 print_f( "corrupted_weapon: " .. weaponSection )
2043 return "corrupted_weapon"
2044 end
2045
2046end
2047
2048function FixOldDataFormat(item)
2049
2050 print_f("FixOldDataFormat")
2051
2052 local isMag = isMagazine(item)
2053 local isWep = IsWeapon(item)
2054
2055 if(isMag or isWep) then
2056
2057 -- fix old mag data
2058 if(isMag or isWep) then
2059
2060 local data = GetMagStorage(item:id()) --utils_stpk.get_weapon_data(alife_object(item:id()))
2061
2062 local _, count = string.gsub(data, "%:", "")
2063
2064 --print_f("count" .. count)
2065
2066 --local oldMagData = WeaponGetMagData(item)
2067 --if(tonumber(oldMagData[1]) == nil) then
2068 --old mag found, fix it
2069 if(isMag and count == 1) then
2070 --[[
2071 local magSlot = oldMagData[iMAG_SLOT]
2072 local magCount = oldMagData[iMAG_COUNT]
2073 local magFill = oldMagData[iMAG_FILL]
2074
2075 WeaponSetMagData(item, magSlot .. ":" .. magCount .. ":" .. magFill )
2076 ]]
2077
2078 print_f("Fixing mag")
2079
2080 WeaponSetMagData(item, "N:" .. data )
2081 end
2082
2083 if(isWep and count == 2) then
2084 --[[
2085 local magSlot = oldMagData[iWEP_MSLOT]
2086 local magSection = oldMagData[iWEP_MSEC]
2087 local magCount = oldMagData[iWEP_COUNT]
2088 local magFill = oldMagData[iWEP_FILL]
2089
2090 WeaponSetMagData(item, magSlot .. ":" .. magSection .. ":" .. magCount .. ":" .. magFill)
2091 ]]
2092
2093 print_f("Fixing weapon")
2094
2095 WeaponSetMagData(item, "N:" .. data )
2096 end
2097 --end
2098
2099 end
2100 end
2101end
2102
2103
2104
2105function getMagCompatibleAmmo(magObj)
2106 local result={}
2107 result=parse_list(system_ini(),magObj:section(),"mag_ammo_class",false)
2108 return result
2109end
2110
2111function getWeaponCompatibleMags(weapon)
2112 local result={}
2113 local weaponBaseName=getWeaponBaseName(weapon:section())
2114 if(tInvWepMags[weaponBaseName])then
2115 result=tInvWepMags[weaponBaseName]
2116 end
2117 return result
2118end
2119
2120function on_item_focus(item)
2121
2122 print_f("on_item_focus")
2123
2124 local validItem = false
2125
2126 local isMag = isMagazine(item)
2127 local isWep = IsWeapon(item)
2128 local isAmmo = IsAmmo(item)
2129
2130 if(isMag or isWep or isAmmo) then
2131 validItem = true
2132 end
2133
2134 if(validItem == false) then return end
2135
2136
2137 -- Pepsifan04
2138 -- new code for mags and weapon highlights
2139 -- highlights all compatible mags, everywhere
2140 -- compatible mags only in player and and npc inv
2141 if(isMag or isWep) then
2142 local hTable={}
2143 local inventory = GetActorMenu();
2144
2145 if(isMag)then
2146 hTable=getMagCompatibleAmmo(item)
2147
2148 end
2149 if(isWep) then
2150 hTable=getWeaponCompatibleMags(item)
2151 end
2152
2153 if(inventory and inventory:IsShown() and hTable) then
2154 for i=1,#hTable do
2155 inventory:highlight_section_in_slot(hTable[i],EDDListType.iActorBag)
2156 inventory:highlight_section_in_slot(hTable[i],EDDListType.iPartnerTradeBag)
2157 inventory:highlight_section_in_slot(hTable[i],EDDListType.iDeadBodyBag)
2158 inventory:highlight_section_in_slot(hTable[i],EDDListType.iActorTrade)
2159 inventory:highlight_section_in_slot(hTable[i],EDDListType.iPartnerTrade)
2160 end
2161 end
2162 end
2163
2164
2165 -- update weapon without magazine but with bullets
2166 --print_f("WeaponGetMagData")
2167 local magData = WeaponGetMagData(item)
2168
2169 if(magData == nil) then return -1 end
2170
2171 --print_f("WeaponGetMagData 2")
2172 local validMagIsInWeapon = false
2173
2174 --print_f("SECTION : " .. magData[iWEP_MSEC])
2175
2176
2177 if( magData[iWEP_MSEC] ~= nil and system_ini():section_exist(magData[iWEP_MSEC])) then
2178 validMagIsInWeapon = true
2179 end
2180
2181 local defaultMagSection = WeaponGetDefaulMagSection(item)
2182 local defaultMagSectionExists = system_ini():section_exist(defaultMagSection)
2183
2184 if (item and IsWeapon(item) and (not IsMelee(item)) and validMagIsInWeapon == false ) then
2185
2186
2187
2188
2189 if(defaultMagSectionExists and magData[iWEP_MSEC] ~= "no_mag") then
2190
2191 print_f("mag section found: " .. defaultMagSection)
2192
2193
2194 local obj = alife_object(item:id())
2195
2196 --local maxAmmo = system_ini():r_u32(defaultMagSection, "max_mag_size") -- item:get_ammo_in_magazine() -- system_ini():r_u32(defaultMagSection, "max_mag_size")
2197 local maxAmmo = item:get_ammo_in_magazine()
2198
2199 local ammoIndex = item:get_ammo_type() -- GetAmmoIndexBySection(defaultMagSection, ammoName)
2200
2201 local ammoFill = ""
2202
2203 for i = 1,maxAmmo,1
2204 do
2205 ammoFill = ammoFill .. "" .. ammoIndex
2206 end
2207
2208 if(maxAmmo == 0) then
2209 defaultMagSection = "no_mag" -- no mag
2210 end
2211
2212
2213 WeaponSetMagData(item, "N:" .. defaultMagSection .. ":" .. maxAmmo .. ":" .. ammoFill)
2214
2215 --item:unload_magazine()
2216 --weapon:set_ammo_type(ammo_type)
2217 --item:set_ammo_elapsed(tonumber(maxAmmo))
2218
2219
2220
2221
2222
2223
2224 else
2225
2226 print_f("ERROR: mag section invalid: " .. defaultMagSection)
2227
2228 end
2229
2230
2231
2232
2233
2234
2235
2236 --[[
2237 local weaponBase = item:section()
2238
2239 --local weaponBaseParts = alun_utils.str_explode(item:section(),"_")
2240
2241 --local scopeClass = weaponBaseParts[table.getn(weaponBaseParts)]
2242
2243 local weapon_ammo = item:get_ammo_in_magazine()
2244
2245 if(weapon_ammo == 0) then return end
2246
2247 local lastPart = GetLastSectionPart(weaponBase)
2248
2249 --print_f("on_item_focus")
2250
2251 local tempData = WeaponGetMagData(item)
2252
2253 --print_f("on_item_focus2")
2254
2255
2256 local tempMagClass = tempData[1]
2257
2258 -- get old mag data if available
2259 if(IsMagInPlace(item) and system_ini():section_exist(tempMagClass)) then
2260
2261
2262 local currentMagClass = tempData[1]
2263
2264 local currentAmmoName = tempData[2]
2265
2266 local currentMagAmmo = weapon_ammo
2267
2268 WeaponSetMagData(item, currentMagClass .. ":" .. currentAmmoName .. ":" .. currentMagAmmo)
2269
2270 else
2271
2272 -- remove the scope part
2273 if((WeaponRemovableScopeAttached(item) or lastPart == "short" or lastPart == "nimble") and not system_ini():section_exist("mag_" .. weaponBase)) then
2274
2275 -- lets strip the scope postfix
2276 --local nameparts =
2277
2278
2279
2280 --print_f("WeaponRemovableScopeAttached: %s", nameparts[table.getn(nameparts)])
2281
2282 local basetemp = alun_utils.str_explode(weaponBase,"_" .. lastPart)
2283
2284 weaponBase = basetemp[1]
2285
2286 --print_f("WeaponRemovableScopeAttached: base class : " .. weaponBase)
2287
2288
2289 end
2290
2291
2292 lastPart = GetLastSectionPart(weaponBase)
2293 -- remove nimble part if exists (those can occur like weapon_nimble_scope)
2294 if(lastPart == "nimble" and not system_ini():section_exist("mag_" .. weaponBase)) then
2295
2296 local basetemp = alun_utils.str_explode(weaponBase,"_" .. lastPart)
2297
2298 weaponBase = basetemp[1]
2299
2300
2301
2302 end
2303
2304 local currentMagClass = "mag_" .. weaponBase
2305
2306 local currentAmmoName = item:get_ammo_name()
2307
2308 local currentMagAmmo = weapon_ammo
2309
2310 WeaponSetMagData(item, currentMagClass .. ":" .. currentAmmoName .. ":" .. currentMagAmmo)
2311
2312 end
2313
2314 ]]
2315
2316 --local mag_ammo_count = GetMagAmmo(item) --item:get_ammo_in_magazine()
2317 --local mag_class_name = "mag_" .. weaponBase --item:section() -- store this in custom_data of the weapon
2318 --local mag_current_ammo_type = item:get_ammo_name()
2319
2320 -- check if there is a magazine already
2321
2322 -- local currentMag = WeaponGetMagData(weapon)
2323
2324
2325
2326 end
2327
2328 print_f("D1")
2329
2330 if(defaultMagSectionExists) then
2331 print_f("UNLOADING")
2332
2333 -- unload weapon to get rid of the "unload" button
2334 item:unload_magazine()
2335 --weapon:set_ammo_type(ammo_type)
2336 item:set_ammo_elapsed(0)
2337
2338 end
2339
2340
2341 print_f("D2")
2342 UpdateMagazineUI(item)
2343 print_f("D3")
2344 --[[
2345 if (RepairTools[section]) then
2346 local ini = system_ini()
2347 local repair_type = ini:r_string_ex(section,"repair_type")
2348 if not (repair_type) then
2349 return
2350 end
2351
2352 local function itr(obj)
2353 if (repair_type == "weapon" and IsWeapon(obj)) then
2354 return true
2355 elseif (repair_type == "outfit") and (IsOutfit(obj) or IsHeadgear(obj)) then
2356 return true
2357 elseif (repair_type == "all") then
2358 local cls = obj:clsid()
2359 if (IsWeapon(nil,cls) or IsOutfit(nil,cls) or IsHeadgear(nil,cls)) then
2360 return true
2361 end
2362 end
2363 return false
2364 end
2365
2366 ActorMenu.get_actor_menu():highlight_for_each_in_slot(itr)
2367 end
2368 --]]
2369end
2370
2371function AmmoWheel_GetMagazineListAndLoad(weapon, loadAndReturn)
2372
2373 print_f("AmmoWheel_GetMagazineListAndLoad " .. loadAndReturn)
2374
2375 local ammo_inv = {}
2376
2377 local function itr_inv(temp,inv_mag)
2378
2379 if ( isMagazine(inv_mag) == true and IsMagazineForWeapon(weapon, inv_mag) and string_ends_with(inv_mag:section(), "_ready") ) then
2380 --print_f("attempting reload " .. inv_mag:section() .. " ID: " .. inv_mag:id())
2381
2382 --loading_state = WeaponAttemptToLoadMagazine(weapon, inv_mag, false)
2383
2384 local magData = WeaponGetMagData(inv_mag)
2385
2386 local magFill = magData[iMAG_FILL]
2387
2388 local magCount = tonumber(magData[iMAG_COUNT])
2389
2390 if(magCount > 0) then
2391
2392 local firstRoundIndex = tonumber(string.sub(magFill, 1, 1))
2393 local ammoSec = GetAmmoTypeByIndex(inv_mag, firstRoundIndex)
2394
2395 if(loadAndReturn ~= -1) then
2396
2397 if(firstRoundIndex == loadAndReturn - 1) then
2398 -- attempt to load mag here
2399 local loading_state = WeaponAttemptToLoadMagazine(weapon, inv_mag, false)
2400
2401 if(loading_state) then
2402 reload_Weapon = weapon
2403 reload_Magazine = inv_mag
2404 PlayReloadAnimation(weapon)
2405 print_f("attempting reload Check is OK for " .. inv_mag:section() .. " ID: " .. inv_mag:id())
2406
2407 --cancelReloadTimer = cancelReloadTimer -1
2408 return 0 --do return end-- return
2409 end
2410
2411
2412 end
2413 else
2414
2415 ammo_inv[ammoSec] = (ammo_inv[ammoSec] or 0) + 1
2416
2417 end
2418 end
2419
2420 end
2421
2422 end
2423
2424 db.actor:iterate_inventory(itr_inv)
2425
2426 return ammo_inv
2427end
2428
2429
2430function UpdateMagazineUI(item)
2431
2432 if(grenadeMode) then return -1 end
2433
2434 print_f("UpdateMagazineUI:isMagazine" )
2435
2436 if(isMagazine(item)) then
2437
2438 print_f("ValidateMag" )
2439
2440 ValidateMag(item)
2441
2442 if(MAGAZINE_CALCULATE_WEIGHT) then
2443 MagazineCalculateWeight(item)
2444 end
2445
2446 --print_f("UpdateMagazineUI" )
2447
2448 local currentMag = WeaponGetMagData(item)
2449
2450 --print_f("UpdateMagazineUI2")
2451
2452 --print_f("currentMag data" .. currentMag)
2453
2454 local curretnAmmoCount = tonumber(currentMag[iMAG_COUNT])
2455 if (curretnAmmoCount == nil) then return -1 end
2456
2457 --local currentMagAmmo = currentMag[3]
2458
2459 -- disable
2460 --item:set_ammo_elapsed(currentMagAmmo)
2461
2462
2463 --local ammo_box_size = item:ammo_get_count()
2464 --local current_ammo = currentMagAmmo --item:get_ammo_in_magazine()
2465 local wpn_ammo_max = system_ini():r_u32(item:section(), "max_mag_size")
2466
2467 --print_f(current_ammo)
2468 --print_f(wpn_ammo_max)
2469
2470 print_f("curretnAmmoCount: " .. tostring(curretnAmmoCount))
2471
2472
2473 -- Pepsifan04
2474 -- custom mag condition and 100% for trading
2475
2476 -- 0 mag condition functions as usual
2477 -- 1 mags have always custom condition
2478 local magCondition=curretnAmmoCount / wpn_ammo_max
2479 local npc=GetTalkingNpc()
2480 if(ignoreMagCond_trade and npc and IsTrader(npc) )then
2481 magCondition=1
2482 else
2483 if(ignoreMagCond==1)then
2484 magCondition=ignoreMagCond_val/100
2485 end
2486 end
2487 npc=nil
2488
2489
2490
2491 -- ----print_r(tostring(new_condition))
2492 item:set_condition(magCondition)
2493
2494
2495 if(ui_inventory.GUI and ui_inventory.GUI.CC["picker"]) then
2496 --print_f("ui_inventory.GUI.CC[]")
2497 if(ui_inventory.GUI.CC["picker"]:IsShown()) then
2498 --print_f("-- refreshing picker")
2499 --ui_inventory.GUI:Picker_Refresh()
2500
2501 ui_inventory.GUI.CC["picker"]:UpdateItem(item, nil)
2502
2503 --ui_inventory.GUI:UpdateItems()
2504 end
2505 end
2506
2507 --[[
2508 -- adjust ammo type
2509 if(item:get_ammo_name() ~= curretnAmmoName) then
2510 local ammo_type = item:get_ammo_type()
2511 ammo_type = math.abs(ammo_type-1)
2512 item:set_ammo_type(ammo_type)
2513 end
2514 ]]
2515
2516 --print_f("ammo to mag " .. ammo_box_size .. " / " .. wpn_ammo_size)
2517
2518
2519 -- Pepsifan04
2520 -- this code was usless, it did not work
2521 --===================================================
2522 -- Highlight ammo for magazine
2523 -- local ammo = parse_list(system_ini(),item:section(),"mag_ammo_class")
2524
2525
2526 -- local inventory = ActorMenu.get_actor_menu()
2527 -- if not ((#ammo > 0) or (inventory and inventory:IsShown())) then return end
2528 -- for i=1,#ammo do
2529 -- inventory:highlight_section_in_slot(ammo[i],EDDListType.iActorBag)
2530 -- end
2531 --===================================================
2532 end
2533
2534end
2535
2536
2537function ValidateMag(mag)
2538
2539 local id = mag:id()
2540 local wObj = alife_object(id)
2541
2542 local data = GetMagStorage(id) --utils_stpk.get_weapon_data(wObj)
2543
2544 print_f("ValidateMag old data: " .. tostring(data) .. " - ")
2545
2546 if(data == "" or nil) then
2547
2548 print_f("ValidateMag Set new data N:0:")
2549
2550 WeaponSetMagData(mag, "N:0:")
2551
2552
2553 --sganon edit begin
2554 -- this adds runtime patching of corrupt magazines
2555 -- function ValidateMag outside of this courtesy of wuut
2556 --if we have a magazine that has mag data of an empty weapon,
2557 --we force it to be an empty mag. It must be corrupted.
2558 --This fixes the hover over magazine crash to desktop.
2559 --TLDR: If a mag data looks like this: N:mag_wpn_beretta_9x19_fmj:15:000000000000000 or
2560 -- N:no_mag:0:
2561 -- it has by error been spawned and looks like a weapon's mag data to wuut_mags.script!
2562 -- All we can do at this point is make it an empty mag like
2563 -- N:0:
2564 else
2565 if (string.find(data,"no_mag") or string.find(data,"mag_wpn")) then
2566 print_f("sganon duct tape fix applied")
2567 WeaponSetMagData(mag, "N:0:")
2568 end
2569 end
2570 -- sganon end( ...if(data=="" or nil) then )
2571
2572end
2573
2574
2575function WeaponSetMagData(weapon, magClass)
2576
2577 print_f("WeaponSetMagData " .. magClass)
2578
2579 local wObj = alife_object(weapon:id())
2580 local data = GetMagStorage(weapon:id()) --utils_stpk.get_weapon_data(wObj)
2581 data = magClass
2582 SetMagStorage(weapon:id(), data) -- utils_stpk.set_weapon_data(data,wObj)
2583
2584end
2585
2586function WeaponGetMagData(weapon)
2587
2588 print_f("WeaponGetMagData: (" .. weapon:section() .. ") ID: " .. weapon:id())
2589
2590 --FixOldDataFormat(weapon)
2591
2592
2593 local wObj = alife_object(weapon:id())
2594 local data = GetMagStorage(weapon:id()) --utils_stpk.get_weapon_data(wObj)
2595
2596 print_f("WeaponGetMagData: (" .. tostring(data) .. ")")
2597
2598
2599 if(data == nil) then return nil end
2600
2601
2602 --return data.custom_data
2603
2604 return str_explode(data,":")
2605end
2606
2607function wuut_npc_on_death_callback(npc,who)
2608 --se_stalker_on_spawn
2609 --TrdWndOpened
2610 update_inventory(npc, false)
2611
2612
2613end
2614
2615function update_inventory(npc, is_trader)
2616
2617 local function search(temp, item)
2618
2619 if (item and IsWeapon(item) and (not IsMelee(item))) then
2620 --print_f("DEATH: " .. item:section())
2621 local defaultMagSection = WeaponGetDefaulMagSection(item)
2622
2623 if( system_ini():section_exist(defaultMagSection)) then
2624
2625 local npc_id = npc:id()
2626
2627 -- create magazine in inventory
2628 --print_f(" CREATING MAG " .. defaultMagSection)
2629
2630 --WeaponSetMagData(mag, ammoCount .. ":" .. ammoFill)
2631 --local data = utils_stpk.get_weapon_data(mag)
2632 --data.custom_data = ammoCount .. ":" .. ammoFill
2633 --utils_stpk.set_weapon_data(data,mag)
2634 --npc:transfer_item(mag,db.actor)
2635
2636 local createItem = false
2637
2638 if( is_trader ) then
2639
2640
2641
2642 local count = 0
2643
2644 local function search_pop(temp, item2)
2645 --print_f("DEATH: " .. item:section())
2646 if(defaultMagSection == item2:section()) then
2647 count = count + 1
2648 end
2649
2650 end
2651
2652 npc:iterate_inventory(search_pop, nil)
2653
2654 if(count == 0 ) then
2655 createItem = true
2656
2657 end
2658
2659 --print_f("COUNT: " .. defaultMagSection .. " " .. count)
2660
2661 end
2662
2663 if(createItem or is_trader == false) then
2664 local mag = alife():create(defaultMagSection,npc:position(),npc:level_vertex_id(),npc:game_vertex_id(), npc_id)
2665 --sganon edit begin
2666 -- Hopefully this is ending the cause of so many broken mags. The duct tape fixes in this script will still take care of existing savegame problems,
2667 -- but with this simple code we should never encounter random or broken data mags again
2668 --WeaponSetMagData(mag, "N:0:")
2669 SetMagStorage(mag.id, "N:0:")
2670 print_f("Mag data in NPC inventory forced empty")
2671 --sganon edit end
2672 end
2673
2674 end
2675
2676 end
2677
2678
2679 end
2680 npc:iterate_inventory(search, nil)
2681end
2682
2683
2684function GetTalkingNpc()
2685 --log("~GetTalkingNpc:->:tData.oNpc:clsid() == clsid.script_trader")
2686 for k,v in pairs(db.storage) do
2687 local oNpc = v.object
2688 if oNpc ~= nil then
2689 if oNpc:is_talking() and oNpc:id() ~= AC_ID then
2690 return oNpc
2691 end
2692 end
2693 end
2694end
2695
2696function IsTrader(npc)
2697 --local st = rx_ai.get_storage(npc:id())
2698 --local st = get_storage(npc:id(),"in_cover")
2699 if not npc then
2700 return
2701 end
2702 local st = db.storage[npc:id()]
2703 if st.is_trader == nil then
2704 local trader = false
2705 if npc:character_community() == "trader" or npc:clsid() == clsid.script_trader or npc:clsid() == clsid.trader then
2706 trader = true
2707 end
2708 if string.find(npc:section(),"trader") then
2709 trader = true
2710 end
2711 local cini = db.storage[npc:id()].ini
2712 local logic = db.storage[npc:id()].section_logic
2713 if not logic and not trader then
2714 return false
2715 end
2716 if cini and logic and cini:section_exist(logic) and cini:line_exist(logic,"trade") then
2717 trader = true
2718 end
2719 st.is_trader = trader
2720 end
2721 return st.is_trader == true
2722end
2723
2724
2725function wuut_OnTrdWndOpened()
2726 --log("1~OnTrdWndOpened:->:npc:clsid() == clsid.script_trader")
2727 local npc = GetTalkingNpc()
2728 --print_f("OnTrdWndOpened npc=%s", npc:name())
2729 if(IsTrader(npc)) then
2730
2731 update_inventory(npc, true)
2732 end
2733end
2734
2735
2736function is_in_slot(obj)
2737 for k,_ in pairs(SCANNED_SLOTS) do
2738 local item = db.actor:item_in_slot(k)
2739 if (item and item:id() == obj:id()) then
2740 return true
2741 end
2742 end
2743 return false
2744end
2745
2746function string_starts_with(str, start)
2747 return str:sub(1, #start) == start
2748end
2749
2750function string_ends_with(str, ending)
2751 return ending == "" or str:sub(-#ending) == ending
2752end
2753
2754
2755function getMagazineInfo(mag)
2756 -- print_f("getMagazineInfo - WeaponGetMagData")
2757
2758 ValidateMag(mag)
2759
2760 local magData = WeaponGetMagData(mag)
2761 local ammoTotalCount = tonumber(magData[iMAG_COUNT])
2762 local ammoFill = magData[iMAG_FILL]
2763 local result = {
2764 ["compatibleWeapons"] = str_explode(system_ini():r_string_ex(mag:section(), "magazine_group"),","),
2765 ["ammoMax"] = system_ini():r_u32(mag:section(), "max_mag_size"),
2766 ["ammoTotalCount"] = ammoTotalCount,
2767 ["ammoFill"] = {}
2768 }
2769
2770 print_f("magData: " .. tostring(magData) .. " ammoTotalCount: " .. tostring(ammoTotalCount) .. " ammoFill: " .. tostring(ammoFill) .. " result: " .. tostring(result))
2771
2772 if ammoTotalCount > 0 then
2773 local ammoIndex
2774 local counter = {
2775 ["ammoIndex"] = tonumber(string.sub(ammoFill, -1)),
2776 ["count"] = 0
2777 }
2778
2779 while ammoFill ~= '' do
2780 ammoIndex = tonumber(string.sub(ammoFill, -1))
2781 ammoFill = string.sub(ammoFill, 1, -2)
2782
2783 if counter.ammoIndex == ammoIndex then
2784 counter.count = counter.count + 1
2785 end
2786
2787 if counter.ammoIndex ~= ammoIndex or ammoFill == '' then
2788 table.insert(result.ammoFill, {
2789 ["section"] = GetAmmoTypeByIndex(mag, counter.ammoIndex),
2790 ["count"] = counter.count
2791 })
2792
2793 counter.ammoIndex = ammoIndex
2794 counter.count = 1
2795 end
2796 end
2797 end
2798
2799 return result
2800
2801end