Dayz Explorer 1.28.160049
Loading...
Searching...
No Matches
itembase.c
Go to the documentation of this file.
3
4class DummyItem extends ItemBase
5{
6 override bool CanPutAsAttachment(EntityAI parent)
7 {
8 return true;
9 }
10};
11
12//const bool QUANTITY_DEBUG_REMOVE_ME = false;
13
15{
19
21
22 static int m_DebugActionsMask;
24 // ============================================
25 // Variable Manipulation System
26 // ============================================
27 // Quantity
28
29 float m_VarQuantity;
30 float m_VarQuantityPrev;//for client to know quantity changed during synchronization
34 int m_Count;
35 float m_VarStackMax;
36 float m_StoreLoadedQuantity = float.LOWEST;
37 // Wet
38 float m_VarWet;
39 float m_VarWetPrev;//for client to know wetness changed during synchronization
40 float m_VarWetInit;
41 float m_VarWetMin;
42 float m_VarWetMax;
43 // Cleanness
44 int m_Cleanness;
48 // impact sounds
50 bool m_CanPlayImpactSound = true;
51 float m_ImpactSpeed;
53 //
54 float m_HeatIsolation;
56 float m_ItemAttachOffset; // Offset length for when the item is attached e.g. to weapon
59 int m_ItemBehaviour; // -1 = not specified; 0 = heavy item; 1= onehanded item; 2 = twohanded item
61 bool m_IsBeingPlaced;
62 bool m_IsHologram;
63 bool m_IsTakeable;
67 bool m_FixDamageSystemInit = false; //can be changed on storage version check
68 bool can_this_be_combined; //Check if item can be combined
69 bool m_CanThisBeSplit; //Check if item can be split
70 bool m_IsStoreLoad = false;
73 protected bool m_CanBeDigged;
74 protected bool m_IsResultOfSplit
75
77 // items color variables
82 //-------------------------------------------------------
83
84 // light source managing
86
90
91 //==============================================
92 // agent system
93 private int m_AttachedAgents;
94
96 void TransferModifiers(PlayerBase reciever);
97
98
99 // Weapons & suppressors particle effects
100 ref static map<int, ref array<ref WeaponParticlesOnFire>> m_OnFireEffect;
101 ref static map<int, ref array<ref WeaponParticlesOnBulletCasingEject>> m_OnBulletCasingEjectEffect;
103 ref static map<string, int> m_WeaponTypeToID;
104 static int m_LastRegisteredWeaponID = 0;
105
106 // Overheating effects
107 bool m_IsOverheatingEffectActive;
108 float m_OverheatingShots;
109 ref Timer m_CheckOverheating;
110 int m_ShotsToStartOverheating = 0; // After these many shots, the overheating effect begins
111 int m_MaxOverheatingValue = 0; // Limits the number of shots that will be tracked
112 float m_OverheatingDecayInterval = 1; // Timer's interval for decrementing overheat effect's lifespan
113 ref array <ref OverheatingParticle> m_OverheatingParticles;
114
117
118 // Admin Log
119 PluginAdminLog m_AdminLog;
120
121 // misc
123
124 // Attachment Locking variables
126 protected int m_LockType;
128 protected string m_LockSoundSet;
129
130 // ItemSoundHandler
131 protected const int ITEM_SOUNDS_MAX = 63; // optimize network synch
132 protected int m_SoundSyncPlay; // id for sound to play
133 protected int m_SoundSyncStop; // id for sound to stop
134 private ref ItemSoundHandler m_ItemSoundHandler;
135
136 //temperature
137 private float m_TemperaturePerQuantityWeight;
138
139 // -------------------------------------------------------------------------
140 void ItemBase()
141 {
142 SetEventMask(EntityEvent.INIT); // Enable EOnInit event
146
147 if (!GetGame().IsDedicatedServer())
148 {
149 if (HasMuzzle())
150 {
151 LoadParticleConfigOnFire(GetMuzzleID());
152
153 if (m_ShotsToStartOverheating == 0)
154 {
155 LoadParticleConfigOnOverheating(GetMuzzleID());
156 }
157 }
158
160 m_ActionsInitialize = false;
161 }
162
163 m_OldLocation = null;
164
165 if (GetGame().IsServer())
166 {
167 m_AdminLog = PluginAdminLog.Cast(GetPlugin(PluginAdminLog));
168 }
169
170 if (ConfigIsExisting("headSelectionsToHide"))
171 {
173 ConfigGetTextArray("headSelectionsToHide",m_HeadHidingSelections);
174 }
175
177 if (ConfigIsExisting("hideSelectionsByinventorySlot"))
178 {
179 m_HideSelectionsBySlot = ConfigGetBool("hideSelectionsByinventorySlot");
180 }
181
182 m_QuickBarBonus = Math.Max(0, ConfigGetInt("quickBarBonus"));
183
184 m_IsResultOfSplit = false;
185
186 SetActionAnimOverrides();
187 }
188
189 override void InitItemVariables()
190 {
191 super.InitItemVariables();
192
193 m_VarQuantityInit = ConfigGetInt("varQuantityInit");
194 m_VarQuantity = m_VarQuantityInit;//should be by the CE, this is just a precaution
195 m_VarQuantityMin = ConfigGetInt("varQuantityMin");
196 m_VarQuantityMax = ConfigGetInt("varQuantityMax");
197 m_VarStackMax = ConfigGetFloat("varStackMax");
198 m_Count = ConfigGetInt("count");
199
200 m_CanShowQuantity = ConfigGetBool("quantityShow");
201 m_HasQuantityBar = ConfigGetBool("quantityBar");
202
203 m_CleannessInit = ConfigGetInt("varCleannessInit");
205 m_CleannessMin = ConfigGetInt("varCleannessMin");
206 m_CleannessMax = ConfigGetInt("varCleannessMax");
207
208 m_WantPlayImpactSound = false;
209 m_ImpactSpeed = 0.0;
210
211 m_VarWetInit = ConfigGetFloat("varWetInit");
213 m_VarWetMin = ConfigGetFloat("varWetMin");
214 m_VarWetMax = ConfigGetFloat("varWetMax");
215
216 m_LiquidContainerMask = ConfigGetInt("liquidContainerType");
217 if (IsLiquidContainer() && GetQuantity() != 0)
219 m_IsBeingPlaced = false;
220 m_IsHologram = false;
221 m_IsTakeable = true;
222 m_CanBeMovedOverride = false;
226 m_CanBeDigged = ConfigGetBool("canBeDigged");
227
229 ConfigGetIntArray("compatibleLocks", m_CompatibleLocks);
230 m_LockType = ConfigGetInt("lockType");
231
232 //Define if item can be split and set ability to be combined accordingly
233 m_CanThisBeSplit = false;
234 can_this_be_combined = false;
235 if (ConfigIsExisting("canBeSplit"))
236 {
237 can_this_be_combined = ConfigGetBool("canBeSplit");
239 }
240
241 m_ItemBehaviour = -1;
242 if (ConfigIsExisting("itemBehaviour"))
243 m_ItemBehaviour = ConfigGetInt("itemBehaviour");
244
245 //RegisterNetSyncVariableInt("m_VariablesMask");
246 if (HasQuantity()) RegisterNetSyncVariableFloat("m_VarQuantity", GetQuantityMin(), m_VarQuantityMax);
247 RegisterNetSyncVariableFloat("m_VarWet", GetWetMin(), GetWetMax(), 2);
248 RegisterNetSyncVariableInt("m_VarLiquidType");
249 RegisterNetSyncVariableInt("m_Cleanness",0,1);
250
251 RegisterNetSyncVariableBoolSignal("m_WantPlayImpactSound");
252 RegisterNetSyncVariableFloat("m_ImpactSpeed");
253 RegisterNetSyncVariableInt("m_ImpactSoundSurfaceHash");
254
255 RegisterNetSyncVariableInt("m_ColorComponentR", 0, 255);
256 RegisterNetSyncVariableInt("m_ColorComponentG", 0, 255);
257 RegisterNetSyncVariableInt("m_ColorComponentB", 0, 255);
258 RegisterNetSyncVariableInt("m_ColorComponentA", 0, 255);
259
260 RegisterNetSyncVariableBool("m_IsBeingPlaced");
261 RegisterNetSyncVariableBool("m_IsTakeable");
262 RegisterNetSyncVariableBool("m_IsHologram");
263
265 if (m_ItemSoundHandler)
266 {
267 RegisterNetSyncVariableInt("m_SoundSyncPlay", 0, ITEM_SOUNDS_MAX);
268 RegisterNetSyncVariableInt("m_SoundSyncStop", 0, ITEM_SOUNDS_MAX);
269 }
270
271 m_LockSoundSet = ConfigGetString("lockSoundSet");
272
273 m_TemperaturePerQuantityWeight = 1.0;;
274 if (ConfigIsExisting("temperaturePerQuantityWeight"))
275 m_TemperaturePerQuantityWeight = ConfigGetFloat("temperaturePerQuantityWeight");
276
277 }
278
279 override int GetQuickBarBonus()
280 {
281 return m_QuickBarBonus;
282 }
283
284 void InitializeActions()
285 {
286 m_InputActionMap = m_ItemTypeActionsMap.Get(this.Type());
287 if (!m_InputActionMap)
288 {
290 m_InputActionMap = iam;
291 SetActions();
292 m_ItemTypeActionsMap.Insert(this.Type(), m_InputActionMap);
293 }
294 }
295
296 override void GetActions(typename action_input_type, out array<ActionBase_Basic> actions)
297 {
299 {
300 m_ActionsInitialize = true;
302 }
303
304 actions = m_InputActionMap.Get(action_input_type);
305 }
306
307 void SetActions()
308 {
312 AddAction(ActionDropItem);
314 }
315
316 void SetActionAnimOverrides(); // Override action animation for specific item
317
318 void AddAction(typename actionName)
319 {
320 ActionBase action = ActionManagerBase.GetAction(actionName);
321
322 if (!action)
323 {
324 Debug.LogError("Action " + actionName + " dosn't exist!");
325 return;
326 }
327
328 typename ai = action.GetInputType();
329 if (!ai)
330 {
331 m_ActionsInitialize = false;
332 return;
333 }
334
335 array<ActionBase_Basic> action_array = m_InputActionMap.Get(ai);
336 if (!action_array)
337 {
338 action_array = new array<ActionBase_Basic>;
339 m_InputActionMap.Insert(ai, action_array);
340 }
341 if (LogManager.IsActionLogEnable())
342 {
343 Debug.ActionLog(action.ToString() + " -> " + ai, this.ToString() , "n/a", "Add action");
344 }
345
346 if (action_array.Find(action) != -1)
347 {
348 Debug.Log("Action " + action.Type() + " already added to " + this + ", skipping!");
349 }
350 else
351 {
352 action_array.Insert(action);
353 }
354 }
355
356 void RemoveAction(typename actionName)
357 {
358 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
359 ActionBase action = player.GetActionManager().GetAction(actionName);
360 typename ai = action.GetInputType();
361 array<ActionBase_Basic> action_array = m_InputActionMap.Get(ai);
362
363 if (action_array)
364 {
365 action_array.RemoveItem(action);
366 }
367 }
368
369 // Allows override of default action command per item, defined in the SetActionAnimOverrides() of the item's class
370 // Set -1 for params which should stay in default state
371 void OverrideActionAnimation(typename action, int commandUID, int stanceMask = -1, int commandUIDProne = -1)
372 {
373 ActionOverrideData overrideData = new ActionOverrideData();
374 overrideData.m_CommandUID = commandUID;
375 overrideData.m_CommandUIDProne = commandUIDProne;
376 overrideData.m_StanceMask = stanceMask;
377
378 TActionAnimOverrideMap actionMap = m_ItemActionOverrides.Get(action);
379 if (!actionMap) // create new map of action > overidables map
380 {
381 actionMap = new TActionAnimOverrideMap();
382 m_ItemActionOverrides.Insert(action, actionMap);
383 }
384
385 actionMap.Insert(this.Type(), overrideData); // insert item -> overrides
386
387 }
388
389 void OnItemInHandsPlayerSwimStart(PlayerBase player);
390
391 ScriptedLightBase GetLight();
392
393 // Loads muzzle flash particle configuration from config and saves it to a map for faster access
394 void LoadParticleConfigOnFire(int id)
395 {
396 if (!m_OnFireEffect)
398
399 if (!m_OnBulletCasingEjectEffect)
400 m_OnBulletCasingEjectEffect = new map<int, ref array<ref WeaponParticlesOnBulletCasingEject>>;
401
402 string config_to_search = "CfgVehicles";
403 string muzzle_owner_config;
404
405 if (!m_OnFireEffect.Contains(id))
406 {
407 if (IsInherited(Weapon))
408 config_to_search = "CfgWeapons";
409
410 muzzle_owner_config = config_to_search + " " + GetType() + " ";
411
412 string config_OnFire_class = muzzle_owner_config + "Particles " + "OnFire ";
413
414 int config_OnFire_subclass_count = GetGame().ConfigGetChildrenCount(config_OnFire_class);
415
416 if (config_OnFire_subclass_count > 0)
417 {
419
420 for (int i = 0; i < config_OnFire_subclass_count; i++)
421 {
422 string particle_class = "";
423 GetGame().ConfigGetChildName(config_OnFire_class, i, particle_class);
424 string config_OnFire_entry = config_OnFire_class + particle_class;
425 WeaponParticlesOnFire WPOF = new WeaponParticlesOnFire(this, config_OnFire_entry);
426 WPOF_array.Insert(WPOF);
427 }
428
429
430 m_OnFireEffect.Insert(id, WPOF_array);
431 }
432 }
433
434 if (!m_OnBulletCasingEjectEffect.Contains(id))
435 {
436 config_to_search = "CfgWeapons"; // Bullet Eject efect is supported on weapons only.
437 muzzle_owner_config = config_to_search + " " + GetType() + " ";
438
439 string config_OnBulletCasingEject_class = muzzle_owner_config + "Particles " + "OnBulletCasingEject ";
440
441 int config_OnBulletCasingEject_count = GetGame().ConfigGetChildrenCount(config_OnBulletCasingEject_class);
442
443 if (config_OnBulletCasingEject_count > 0 && IsInherited(Weapon))
444 {
446
447 for (i = 0; i < config_OnBulletCasingEject_count; i++)
448 {
449 string particle_class2 = "";
450 GetGame().ConfigGetChildName(config_OnBulletCasingEject_class, i, particle_class2);
451 string config_OnBulletCasingEject_entry = config_OnBulletCasingEject_class + particle_class2;
452 WeaponParticlesOnBulletCasingEject WPOBE = new WeaponParticlesOnBulletCasingEject(this, config_OnBulletCasingEject_entry);
453 WPOBE_array.Insert(WPOBE);
454 }
455
456
457 m_OnBulletCasingEjectEffect.Insert(id, WPOBE_array);
458 }
459 }
460 }
461
462 // Loads muzzle flash particle configuration from config and saves it to a map for faster access
463 void LoadParticleConfigOnOverheating(int id)
464 {
465 if (!m_OnOverheatingEffect)
466 m_OnOverheatingEffect = new map<int, ref array<ref WeaponParticlesOnOverheating>>;
467
468 if (!m_OnOverheatingEffect.Contains(id))
469 {
470 string config_to_search = "CfgVehicles";
471
472 if (IsInherited(Weapon))
473 config_to_search = "CfgWeapons";
474
475 string muzzle_owner_config = config_to_search + " " + GetType() + " ";
476 string config_OnOverheating_class = muzzle_owner_config + "Particles " + "OnOverheating ";
477
478 if (GetGame().ConfigIsExisting(config_OnOverheating_class))
479 {
480
481 m_ShotsToStartOverheating = GetGame().ConfigGetFloat(config_OnOverheating_class + "shotsToStartOverheating");
482
483 if (m_ShotsToStartOverheating == 0)
484 {
485 m_ShotsToStartOverheating = -1; // This prevents futher readings from config for future creations of this item
486 string error = "Error reading config " + GetType() + ">Particles>OnOverheating - Parameter shotsToStartOverheating is configured wrong or is missing! Its value must be 1 or higher!";
487 Error(error);
488 return;
489 }
490
491 m_OverheatingDecayInterval = GetGame().ConfigGetFloat(config_OnOverheating_class + "overheatingDecayInterval");
492 m_MaxOverheatingValue = GetGame().ConfigGetFloat(config_OnOverheating_class + "maxOverheatingValue");
493
494
495
496 int config_OnOverheating_subclass_count = GetGame().ConfigGetChildrenCount(config_OnOverheating_class);
498
499 for (int i = 0; i < config_OnOverheating_subclass_count; i++)
500 {
501 string particle_class = "";
502 GetGame().ConfigGetChildName(config_OnOverheating_class, i, particle_class);
503 string config_OnOverheating_entry = config_OnOverheating_class + particle_class;
504 int entry_type = GetGame().ConfigGetType(config_OnOverheating_entry);
505
506 if (entry_type == CT_CLASS)
507 {
508 WeaponParticlesOnOverheating WPOF = new WeaponParticlesOnOverheating(this, config_OnOverheating_entry);
509 WPOOH_array.Insert(WPOF);
510 }
511 }
512
513
514 m_OnOverheatingEffect.Insert(id, WPOOH_array);
515 }
516 }
517 }
518
519 float GetOverheatingValue()
520 {
521 return m_OverheatingShots;
522 }
523
524 void IncreaseOverheating(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
525 {
526 if (m_MaxOverheatingValue > 0)
527 {
528 m_OverheatingShots++;
529
530 if (!m_CheckOverheating)
531 m_CheckOverheating = new Timer(CALL_CATEGORY_SYSTEM);
532
533 m_CheckOverheating.Stop();
534 m_CheckOverheating.Run(m_OverheatingDecayInterval, this, "OnOverheatingDecay");
535
536 CheckOverheating(weapon, ammoType, muzzle_owner, suppressor, config_to_search);
537 }
538 }
539
540 void CheckOverheating(ItemBase weapon = null, string ammoType = "", ItemBase muzzle_owner = null, ItemBase suppressor = null, string config_to_search = "")
541 {
542 if (m_OverheatingShots >= m_ShotsToStartOverheating && IsOverheatingEffectActive())
543 UpdateOverheating(weapon, ammoType, muzzle_owner, suppressor, config_to_search);
544
545 if (m_OverheatingShots >= m_ShotsToStartOverheating && !IsOverheatingEffectActive())
546 StartOverheating(weapon, ammoType, muzzle_owner, suppressor, config_to_search);
547
548 if (m_OverheatingShots < m_ShotsToStartOverheating && IsOverheatingEffectActive())
549 StopOverheating(weapon, ammoType, muzzle_owner, suppressor, config_to_search);
550
551 if (m_OverheatingShots > m_MaxOverheatingValue)
552 {
553 m_OverheatingShots = m_MaxOverheatingValue;
554 }
555 }
556
557 bool IsOverheatingEffectActive()
558 {
559 return m_IsOverheatingEffectActive;
560 }
561
562 void OnOverheatingDecay()
563 {
564 if (m_MaxOverheatingValue > 0)
565 m_OverheatingShots -= 1 + m_OverheatingShots / m_MaxOverheatingValue; // The hotter a barrel is, the faster it needs to cool down.
566 else
567 m_OverheatingShots--;
568
569 if (m_OverheatingShots <= 0)
570 {
571 m_CheckOverheating.Stop();
572 m_OverheatingShots = 0;
573 }
574 else
575 {
576 if (!m_CheckOverheating)
577 m_CheckOverheating = new Timer(CALL_CATEGORY_GAMEPLAY);
578
579 m_CheckOverheating.Stop();
580 m_CheckOverheating.Run(m_OverheatingDecayInterval, this, "OnOverheatingDecay");
581 }
582
583 CheckOverheating(this, "", this);
584 }
585
586 void StartOverheating(ItemBase weapon = null, string ammoType = "", ItemBase muzzle_owner = null, ItemBase suppressor = null, string config_to_search = "")
587 {
588 m_IsOverheatingEffectActive = true;
589 ItemBase.PlayOverheatingParticles(this, ammoType, this, suppressor, "CfgWeapons");
590 }
591
592 void UpdateOverheating(ItemBase weapon = null, string ammoType = "", ItemBase muzzle_owner = null, ItemBase suppressor = null, string config_to_search = "")
593 {
594 KillAllOverheatingParticles();
595 ItemBase.UpdateOverheatingParticles(this, ammoType, this, suppressor, "CfgWeapons");
596 UpdateAllOverheatingParticles();
597 }
598
599 void StopOverheating(ItemBase weapon = null, string ammoType = "", ItemBase muzzle_owner = null, ItemBase suppressor = null, string config_to_search = "")
600 {
601 m_IsOverheatingEffectActive = false;
602 ItemBase.StopOverheatingParticles(weapon, ammoType, muzzle_owner, suppressor, config_to_search);
603 }
604
605 void RegisterOverheatingParticle(Particle p, float min_heat_coef, float max_heat_coef, int particle_id, Object parent, vector local_pos, vector local_ori)
606 {
607 if (!m_OverheatingParticles)
608 m_OverheatingParticles = new array<ref OverheatingParticle>;
609
611 OP.RegisterParticle(p);
612 OP.SetOverheatingLimitMin(min_heat_coef);
613 OP.SetOverheatingLimitMax(max_heat_coef);
614 OP.SetParticleParams(particle_id, parent, local_pos, local_ori);
615
616 m_OverheatingParticles.Insert(OP);
617 }
618
619 float GetOverheatingCoef()
620 {
621 if (m_MaxOverheatingValue > 0)
622 return (m_OverheatingShots - m_ShotsToStartOverheating) / m_MaxOverheatingValue;
623
624 return -1;
625 }
626
627 void UpdateAllOverheatingParticles()
628 {
629 if (m_OverheatingParticles)
630 {
631 float overheat_coef = GetOverheatingCoef();
632 int count = m_OverheatingParticles.Count();
633
634 for (int i = count; i > 0; --i)
635 {
636 int id = i - 1;
637 OverheatingParticle OP = m_OverheatingParticles.Get(id);
638 Particle p = OP.GetParticle();
639
640 float overheat_min = OP.GetOverheatingLimitMin();
641 float overheat_max = OP.GetOverheatingLimitMax();
642
643 if (overheat_coef < overheat_min && overheat_coef >= overheat_max)
644 {
645 if (p)
646 {
647 p.Stop();
648 OP.RegisterParticle(null);
649 }
650 }
651 }
652 }
653 }
654
655 void KillAllOverheatingParticles()
656 {
657 if (m_OverheatingParticles)
658 {
659 for (int i = m_OverheatingParticles.Count(); i > 0; i--)
660 {
661 int id = i - 1;
662 OverheatingParticle OP = m_OverheatingParticles.Get(id);
663
664 if (OP)
665 {
666 Particle p = OP.GetParticle();
667
668 if (p)
669 {
670 p.Stop();
671 }
672
673 delete OP;
674 }
675 }
676
677 m_OverheatingParticles.Clear();
678 delete m_OverheatingParticles;
679 }
680 }
681
683 float GetInfectionChance(int system = 0, Param param = null)
684 {
685 return 0.0;
686 }
687
688
689 float GetDisinfectQuantity(int system = 0, Param param1 = null)
690 {
691 return 250;//default value
692 }
693
694 float GetFilterDamageRatio()
695 {
696 return 0;
697 }
698
700 bool HasMuzzle()
701 {
702 if (IsInherited(Weapon) || IsInherited(SuppressorBase))
703 return true;
704
705 return false;
706 }
707
709 int GetMuzzleID()
710 {
711 if (!m_WeaponTypeToID)
712 m_WeaponTypeToID = new map<string, int>;
713
714 if (m_WeaponTypeToID.Contains(GetType()))
715 {
716 return m_WeaponTypeToID.Get(GetType());
717 }
718 else
719 {
720 // Register new weapon ID
721 m_WeaponTypeToID.Insert(GetType(), ++m_LastRegisteredWeaponID);
722 }
723
724 return m_LastRegisteredWeaponID;
725 }
726
733 {
734 return -1;
735 }
736
737
738
739 // -------------------------------------------------------------------------
740 void ~ItemBase()
741 {
742 if (GetGame() && GetGame().GetPlayer() && (!GetGame().IsDedicatedServer()))
743 {
744 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
745 int r_index = player.GetHumanInventory().FindUserReservedLocationIndex(this);
746
747 if (r_index >= 0)
748 {
750 player.GetHumanInventory().GetUserReservedLocation(r_index,r_il);
751
752 player.GetHumanInventory().ClearUserReservedLocationAtIndex(r_index);
753 int r_type = r_il.GetType();
754 if (r_type == InventoryLocationType.CARGO || r_type == InventoryLocationType.PROXYCARGO)
755 {
756 r_il.GetParent().GetOnReleaseLock().Invoke(this);
757 }
758 else if (r_type == InventoryLocationType.ATTACHMENT)
759 {
760 r_il.GetParent().GetOnAttachmentReleaseLock().Invoke(this, r_il.GetSlot());
761 }
762
763 }
764
765 player.GetHumanInventory().ClearUserReservedLocation(this);
766 }
767
768 if (m_LockingSound)
770 }
771
772
773
774 // -------------------------------------------------------------------------
775 static int GetDebugActionsMask()
776 {
777 return ItemBase.m_DebugActionsMask;
778 }
779
780 static bool HasDebugActionsMask(int mask)
781 {
782 return ItemBase.m_DebugActionsMask & mask;
783 }
784
785 static void SetDebugActionsMask(int mask)
786 {
787 ItemBase.m_DebugActionsMask = mask;
788 }
789
790 static void AddDebugActionsMask(int mask)
791 {
792 ItemBase.m_DebugActionsMask |= mask;
793 }
794
795 static void RemoveDebugActionsMask(int mask)
796 {
797 ItemBase.m_DebugActionsMask &= ~mask;
798 }
799
800 static void ToggleDebugActionsMask(int mask)
801 {
802 if (HasDebugActionsMask(mask))
803 {
804 RemoveDebugActionsMask(mask);
805 }
806 else
807 {
808 AddDebugActionsMask(mask);
809 }
810 }
811
812 // -------------------------------------------------------------------------
813 void SetCEBasedQuantity()
814 {
815 if (GetEconomyProfile())
816 {
817 float q_max = GetEconomyProfile().GetQuantityMax();
818 if (q_max > 0)
819 {
820 float q_min = GetEconomyProfile().GetQuantityMin();
821 float quantity_randomized = Math.RandomFloatInclusive(q_min, q_max);
822
823 if (HasComponent(COMP_TYPE_ENERGY_MANAGER))//more direct access for speed
824 {
825 ComponentEnergyManager comp = GetCompEM();
826 if (comp && (comp.GetEnergyMaxPristine() || comp.GetEnergyAtSpawn()))//checking for a potential for energy, we need to check both values, as both are optional, only when both are set to 0, we know the item can't have energy
827 {
828 comp.SetEnergy0To1(quantity_randomized);
829 }
830 }
831 else if (HasQuantity())
832 {
833 SetQuantityNormalized(quantity_randomized, false);
834 //PrintString("<==> Normalized quantity for item: "+ GetType()+", qmin:"+q_min.ToString()+"; qmax:"+q_max.ToString()+";quantity:" +quantity_randomized.ToString());
835 }
836
837 }
838 }
839 }
840
842 void LockToParent()
843 {
844 EntityAI parent = GetHierarchyParent();
845
846 if (parent)
847 {
848 InventoryLocation inventory_location_to_lock = new InventoryLocation;
849 GetInventory().GetCurrentInventoryLocation(inventory_location_to_lock);
850 parent.GetInventory().SetSlotLock(inventory_location_to_lock.GetSlot(), true);
851 }
852 }
853
855 void UnlockFromParent()
856 {
857 EntityAI parent = GetHierarchyParent();
858
859 if (parent)
860 {
861 InventoryLocation inventory_location_to_unlock = new InventoryLocation;
862 GetInventory().GetCurrentInventoryLocation(inventory_location_to_unlock);
863 parent.GetInventory().SetSlotLock(inventory_location_to_unlock.GetSlot(), false);
864 }
865 }
866
867 override void CombineItemsClient(EntityAI entity2, bool use_stack_max = true)
868 {
869 /*
870 ref Param1<EntityAI> item = new Param1<EntityAI>(entity2);
871 RPCSingleParam(ERPCs.RPC_ITEM_COMBINE, item, GetGame().GetPlayer());
872 */
873 ItemBase item2 = ItemBase.Cast(entity2);
874
875 if (GetGame().IsClient())
876 {
877 if (ScriptInputUserData.CanStoreInputUserData())
878 {
881 ctx.Write(-1);
882 ItemBase i1 = this; // @NOTE: workaround for correct serialization
883 ctx.Write(i1);
884 ctx.Write(item2);
885 ctx.Write(use_stack_max);
886 ctx.Write(-1);
887 ctx.Send();
888
889 if (IsCombineAll(item2, use_stack_max))
890 {
891 GetGame().GetPlayer().GetInventory().AddInventoryReservationEx(item2,null,GameInventory.c_InventoryReservationTimeoutShortMS);
892 }
893 }
894 }
895 else if (!GetGame().IsMultiplayer())
896 {
897 CombineItems(item2, use_stack_max);
898 }
899 }
900
901 bool IsLiquidPresent()
902 {
903 return (GetLiquidType() != 0 && HasQuantity());
904 }
905
906 bool IsLiquidContainer()
907 {
908 return m_LiquidContainerMask != 0;
909 }
910
911 int GetLiquidContainerMask()
912 {
914 }
915
916 bool IsBloodContainer()
917 {
918 //m_LiquidContainerMask & GROUP_LIQUID_BLOOD ???
919 return false;
920 }
921
922 bool IsNVG()
923 {
924 return false;
925 }
926
929 bool IsExplosive()
930 {
931 return false;
932 }
933
934 string GetExplosiveTriggerSlotName()
935 {
936 return "";
937 }
938
940
941 bool IsLightSource()
942 {
943 return false;
944 }
945
947 {
948 return true;
949 }
950
951 //--- ACTION CONDITIONS
952 //direction
953 bool IsFacingPlayer(PlayerBase player, string selection)
954 {
955 return true;
956 }
957
958 bool IsPlayerInside(PlayerBase player, string selection)
959 {
960 return true;
961 }
962
963 override bool CanObstruct()
964 {
965 PlayerBase player = PlayerBase.Cast(g_Game.GetPlayer());
966 return !player || !IsPlayerInside(player, "");
967 }
968
969 override bool IsBeingPlaced()
970 {
971 return m_IsBeingPlaced;
972 }
973
974 void SetIsBeingPlaced(bool is_being_placed)
975 {
976 m_IsBeingPlaced = is_being_placed;
977 if (!is_being_placed)
979 SetSynchDirty();
980 }
981
982 //server-side
983 void OnEndPlacement() {}
984
985 override bool IsHologram()
986 {
987 return m_IsHologram;
988 }
989
990 bool CanBeDigged()
991 {
992 return m_CanBeDigged;
993 }
994
995 int GetOnDigWormsAmount()
996 {
997 return 1;
998 }
999
1000 bool CanMakeGardenplot()
1001 {
1002 return false;
1003 }
1004
1005 void SetIsHologram(bool is_hologram)
1006 {
1007 m_IsHologram = is_hologram;
1008 SetSynchDirty();
1009 }
1010 /*
1011 protected float GetNutritionalEnergy()
1012 {
1013 Edible_Base edible = Edible_Base.Cast(this);
1014 return edible.GetFoodEnergy();
1015 }
1016
1017 protected float GetNutritionalWaterContent()
1018 {
1019 Edible_Base edible = Edible_Base.Cast(this);
1020 return edible.GetFoodWater();
1021 }
1022
1023 protected float GetNutritionalIndex()
1024 {
1025 Edible_Base edible = Edible_Base.Cast(this);
1026 return edible.GetFoodNutritionalIndex();
1027 }
1028
1029 protected float GetNutritionalFullnessIndex()
1030 {
1031 Edible_Base edible = Edible_Base.Cast(this);
1032 return edible.GetFoodTotalVolume();
1033 }
1034
1035 protected float GetNutritionalToxicity()
1036 {
1037 Edible_Base edible = Edible_Base.Cast(this);
1038 return edible.GetFoodToxicity();
1039
1040 }
1041 */
1042
1043
1044 // -------------------------------------------------------------------------
1045 override void OnMovedInsideCargo(EntityAI container)
1046 {
1047 super.OnMovedInsideCargo(container);
1048
1049 MiscGameplayFunctions.RemoveAllAttachedChildrenByTypename(this, {Bolt_Base});
1050 }
1051
1052 override void EEItemLocationChanged(notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc)
1053 {
1054 super.EEItemLocationChanged(oldLoc,newLoc);
1055
1056 PlayerBase new_player = null;
1057 PlayerBase old_player = null;
1058
1059 if (newLoc.GetParent())
1060 new_player = PlayerBase.Cast(newLoc.GetParent().GetHierarchyRootPlayer());
1061
1062 if (oldLoc.GetParent())
1063 old_player = PlayerBase.Cast(oldLoc.GetParent().GetHierarchyRootPlayer());
1064
1065 if (old_player && oldLoc.GetType() == InventoryLocationType.HANDS)
1066 {
1067 int r_index = old_player.GetHumanInventory().FindUserReservedLocationIndex(this);
1068
1069 if (r_index >= 0)
1070 {
1072 old_player.GetHumanInventory().GetUserReservedLocation(r_index,r_il);
1073
1074 old_player.GetHumanInventory().ClearUserReservedLocationAtIndex(r_index);
1075 int r_type = r_il.GetType();
1076 if (r_type == InventoryLocationType.CARGO || r_type == InventoryLocationType.PROXYCARGO)
1077 {
1078 r_il.GetParent().GetOnReleaseLock().Invoke(this);
1079 }
1080 else if (r_type == InventoryLocationType.ATTACHMENT)
1081 {
1082 r_il.GetParent().GetOnAttachmentReleaseLock().Invoke(this, r_il.GetSlot());
1083 }
1084
1085 }
1086 }
1087
1088 if (newLoc.GetType() == InventoryLocationType.HANDS)
1089 {
1090 if (new_player)
1091 new_player.ForceStandUpForHeavyItems(newLoc.GetItem());
1092
1093 if (new_player == old_player)
1094 {
1095
1096 if (oldLoc.GetParent() && new_player.GetHumanInventory().LocationGetEntity(oldLoc) == NULL)
1097 {
1098 if (oldLoc.GetType() == InventoryLocationType.CARGO)
1099 {
1100 if (oldLoc.GetParent().GetInventory().TestAddEntityInCargoExLoc(oldLoc, false, false, false, true, false, false))
1101 {
1102 new_player.GetHumanInventory().SetUserReservedLocation(this,oldLoc);
1103 }
1104 }
1105 else
1106 {
1107 new_player.GetHumanInventory().SetUserReservedLocation(this,oldLoc);
1108 }
1109 }
1110
1111 if (new_player.GetHumanInventory().FindUserReservedLocationIndex(this) >= 0)
1112 {
1113 int type = oldLoc.GetType();
1114 if (type == InventoryLocationType.CARGO || type == InventoryLocationType.PROXYCARGO)
1115 {
1116 oldLoc.GetParent().GetOnSetLock().Invoke(this);
1117 }
1118 else if (type == InventoryLocationType.ATTACHMENT)
1119 {
1120 oldLoc.GetParent().GetOnAttachmentSetLock().Invoke(this, oldLoc.GetSlot());
1121 }
1122 }
1123 if (!m_OldLocation)
1124 {
1125 m_OldLocation = new InventoryLocation;
1126 }
1127 m_OldLocation.Copy(oldLoc);
1128 }
1129 else
1130 {
1131 if (m_OldLocation)
1132 {
1133 m_OldLocation.Reset();
1134 }
1135 }
1136
1137 GetGame().GetAnalyticsClient().OnItemAttachedAtPlayer(this,"Hands");
1138 }
1139 else
1140 {
1141 if (new_player)
1142 {
1143 int res_index = new_player.GetHumanInventory().FindCollidingUserReservedLocationIndex(this, newLoc);
1144 if (res_index >= 0)
1145 {
1147 new_player.GetHumanInventory().GetUserReservedLocation(res_index,il);
1148 ItemBase it = ItemBase.Cast(il.GetItem());
1149 new_player.GetHumanInventory().ClearUserReservedLocationAtIndex(res_index);
1150 int rel_type = il.GetType();
1151 if (rel_type == InventoryLocationType.CARGO || rel_type == InventoryLocationType.PROXYCARGO)
1152 {
1153 il.GetParent().GetOnReleaseLock().Invoke(it);
1154 }
1155 else if (rel_type == InventoryLocationType.ATTACHMENT)
1156 {
1157 il.GetParent().GetOnAttachmentReleaseLock().Invoke(it, il.GetSlot());
1158 }
1159 //it.GetOnReleaseLock().Invoke(it);
1160 }
1161 }
1162 else if (old_player && newLoc.GetType() == InventoryLocationType.GROUND && m_ThrowItemOnDrop)
1163 {
1164 //ThrowPhysically(old_player, vector.Zero);
1165 m_ThrowItemOnDrop = false;
1166 }
1167
1168 if (m_OldLocation)
1169 {
1170 m_OldLocation.Reset();
1171 }
1172 }
1173 }
1174
1175 override void EOnContact(IEntity other, Contact extra)
1176 {
1178 {
1179 int liquidType = -1;
1180 float impactSpeed = ProcessImpactSoundEx(other, extra, m_ConfigWeight, m_ImpactSoundSurfaceHash, liquidType);
1181 if (impactSpeed > 0.0)
1182 {
1183 m_ImpactSpeed = impactSpeed;
1184 #ifndef SERVER
1185 PlayImpactSound(m_ConfigWeight, m_ImpactSpeed, m_ImpactSoundSurfaceHash);
1186 #else
1187 m_WantPlayImpactSound = true;
1188 SetSynchDirty();
1189 #endif
1190 m_CanPlayImpactSound = (liquidType == -1);// prevents further playing of the sound when the surface is a liquid type
1191 }
1192 }
1193
1194 #ifdef SERVER
1195 if (GetCompEM() && GetCompEM().IsPlugged())
1196 {
1197 if (GetCompEM().GetCordLength() < vector.Distance(GetPosition(), GetCompEM().GetEnergySource().GetPosition()))
1198 GetCompEM().UnplugThis();
1199 }
1200 #endif
1201 }
1202
1203 void RefreshPhysics();
1204
1205 override void OnCreatePhysics()
1206 {
1208 }
1209
1210 override void OnItemAttachmentSlotChanged(notnull InventoryLocation oldLoc, notnull InventoryLocation newLoc)
1211 {
1212
1213 }
1214 // -------------------------------------------------------------------------
1215 override void OnItemLocationChanged(EntityAI old_owner, EntityAI new_owner)
1216 {
1217 super.OnItemLocationChanged(old_owner, new_owner);
1218
1219 PlayerBase relatedPlayer = PlayerBase.Cast(old_owner);
1220 PlayerBase playerNew = PlayerBase.Cast(new_owner);
1221
1222 if (!relatedPlayer && playerNew)
1223 relatedPlayer = playerNew;
1224
1225 if (relatedPlayer && relatedPlayer.GetPerformedActionID() != -1)
1226 {
1227 ActionManagerBase actionMgr = relatedPlayer.GetActionManager();
1228 if (actionMgr)
1229 {
1230 ActionBase currentAction = actionMgr.GetRunningAction();
1231 if (currentAction)
1232 currentAction.OnItemLocationChanged(this);
1233 }
1234 }
1235
1236 Man ownerPlayerOld = null;
1237 Man ownerPlayerNew = null;
1238
1239 if (old_owner)
1240 {
1241 if (old_owner.IsMan())
1242 {
1243 ownerPlayerOld = Man.Cast(old_owner);
1244 }
1245 else
1246 {
1247 ownerPlayerOld = Man.Cast(old_owner.GetHierarchyRootPlayer());
1248 }
1249 }
1250 else
1251 {
1252 if (new_owner && IsElectricAppliance() && GetCompEM() && GetCompEM().IsPlugged())
1253 {
1254 ActionBase action = ActionManagerBase.GetAction(ActionRepositionPluggedItem);
1255
1256 if (!action || !playerNew || playerNew.GetPerformedActionID() != action.GetID())
1257 {
1258 GetCompEM().UnplugThis();
1259 }
1260 }
1261 }
1262
1263 if (new_owner)
1264 {
1265 if (new_owner.IsMan())
1266 {
1267 ownerPlayerNew = Man.Cast(new_owner);
1268 }
1269 else
1270 {
1271 ownerPlayerNew = Man.Cast(new_owner.GetHierarchyRootPlayer());
1272 }
1273 }
1274
1275 if (ownerPlayerOld != ownerPlayerNew)
1276 {
1277 if (ownerPlayerOld)
1278 {
1279 array<EntityAI> subItemsExit = new array<EntityAI>;
1280 GetInventory().EnumerateInventory(InventoryTraversalType.PREORDER,subItemsExit);
1281 for (int i = 0; i < subItemsExit.Count(); i++)
1282 {
1283 ItemBase itemExit = ItemBase.Cast(subItemsExit.Get(i));
1284 itemExit.OnInventoryExit(ownerPlayerOld);
1285 }
1286 }
1287
1288 if (ownerPlayerNew)
1289 {
1290 array<EntityAI> subItemsEnter = new array<EntityAI>;
1291 GetInventory().EnumerateInventory(InventoryTraversalType.PREORDER,subItemsEnter);
1292 for (int j = 0; j < subItemsEnter.Count(); j++)
1293 {
1294 ItemBase itemEnter = ItemBase.Cast(subItemsEnter.Get(j));
1295 itemEnter.OnInventoryEnter(ownerPlayerNew);
1296 }
1297 }
1298 }
1299 else if (ownerPlayerNew != null)
1300 {
1301 PlayerBase nplayer;
1302 if (PlayerBase.CastTo(nplayer, ownerPlayerNew))
1303 {
1304 array<EntityAI> subItemsUpdate = new array<EntityAI>;
1305 GetInventory().EnumerateInventory(InventoryTraversalType.PREORDER,subItemsUpdate);
1306 for (int k = 0; k < subItemsUpdate.Count(); k++)
1307 {
1308 ItemBase itemUpdate = ItemBase.Cast(subItemsUpdate.Get(k));
1309 itemUpdate.UpdateQuickbarShortcutVisibility(nplayer);
1310 }
1311 }
1312 }
1313
1314 if (old_owner)
1315 old_owner.OnChildItemRemoved(this);
1316 if (new_owner)
1317 new_owner.OnChildItemReceived(this);
1318 }
1319
1320 // -------------------------------------------------------------------------------
1321 override void EEDelete(EntityAI parent)
1322 {
1323 super.EEDelete(parent);
1324 PlayerBase player = PlayerBase.Cast(GetHierarchyRootPlayer());
1325 if (player)
1326 {
1327 OnInventoryExit(player);
1328
1329 if (player.IsAlive())
1330 {
1331 int r_index = player.GetHumanInventory().FindUserReservedLocationIndex(this);
1332 if (r_index >= 0)
1333 {
1335 player.GetHumanInventory().GetUserReservedLocation(r_index,r_il);
1336
1337 player.GetHumanInventory().ClearUserReservedLocationAtIndex(r_index);
1338 int r_type = r_il.GetType();
1339 if (r_type == InventoryLocationType.CARGO || r_type == InventoryLocationType.PROXYCARGO)
1340 {
1341 r_il.GetParent().GetOnReleaseLock().Invoke(this);
1342 }
1343 else if (r_type == InventoryLocationType.ATTACHMENT)
1344 {
1345 r_il.GetParent().GetOnAttachmentReleaseLock().Invoke(this, r_il.GetSlot());
1346 }
1347
1348 }
1349
1350 player.RemoveQuickBarEntityShortcut(this);
1351 }
1352 }
1353 }
1354 // -------------------------------------------------------------------------------
1355 override void EEKilled(Object killer)
1356 {
1357 super.EEKilled(killer);
1358
1360 if (killer && killer.IsFireplace() && CanExplodeInFire())
1361 {
1362 if (GetTemperature() >= GameConstants.ITEM_TEMPERATURE_TO_EXPLODE_MIN)
1363 {
1364 if (IsMagazine())
1365 {
1366 if (Magazine.Cast(this).GetAmmoCount() > 0)
1367 {
1368 ExplodeAmmo();
1369 }
1370 }
1371 else
1372 {
1373 Explode(DamageType.EXPLOSION);
1374 }
1375 }
1376 }
1377 }
1378
1379 override void OnWasAttached(EntityAI parent, int slot_id)
1380 {
1381 MiscGameplayFunctions.RemoveAllAttachedChildrenByTypename(this, {Bolt_Base});
1382
1383 super.OnWasAttached(parent, slot_id);
1384
1385 if (HasQuantity())
1386 UpdateNetSyncVariableFloat("m_VarQuantity", GetQuantityMin(), m_VarQuantityMax);
1387
1388 PlayAttachSound(InventorySlots.GetSlotName(slot_id));
1389 }
1390
1391 override void OnWasDetached(EntityAI parent, int slot_id)
1392 {
1393 super.OnWasDetached(parent, slot_id);
1394
1395 if (HasQuantity())
1396 UpdateNetSyncVariableFloat("m_VarQuantity", GetQuantityMin(), m_VarQuantityMax);
1397 }
1398
1399 override string ChangeIntoOnAttach(string slot)
1400 {
1401 int idx;
1402 TStringArray inventory_slots = new TStringArray;
1403 TStringArray attach_types = new TStringArray;
1404
1405 ConfigGetTextArray("ChangeInventorySlot",inventory_slots);
1406 if (inventory_slots.Count() < 1) //is string
1407 {
1408 inventory_slots.Insert(ConfigGetString("ChangeInventorySlot"));
1409 attach_types.Insert(ConfigGetString("ChangeIntoOnAttach"));
1410 }
1411 else //is array
1412 {
1413 ConfigGetTextArray("ChangeIntoOnAttach",attach_types);
1414 }
1415
1416 idx = inventory_slots.Find(slot);
1417 if (idx < 0)
1418 return "";
1419
1420 return attach_types.Get(idx);
1421 }
1422
1423 override string ChangeIntoOnDetach()
1424 {
1425 int idx = -1;
1426 string slot;
1427
1428 TStringArray inventory_slots = new TStringArray;
1429 TStringArray detach_types = new TStringArray;
1430
1431 this.ConfigGetTextArray("ChangeInventorySlot",inventory_slots);
1432 if (inventory_slots.Count() < 1) //is string
1433 {
1434 inventory_slots.Insert(this.ConfigGetString("ChangeInventorySlot"));
1435 detach_types.Insert(this.ConfigGetString("ChangeIntoOnDetach"));
1436 }
1437 else //is array
1438 {
1439 this.ConfigGetTextArray("ChangeIntoOnDetach",detach_types);
1440 if (detach_types.Count() < 1)
1441 detach_types.Insert(this.ConfigGetString("ChangeIntoOnDetach"));
1442 }
1443
1444 for (int i = 0; i < inventory_slots.Count(); i++)
1445 {
1446 slot = inventory_slots.Get(i);
1447 }
1448
1449 if (slot != "")
1450 {
1451 if (detach_types.Count() == 1)
1452 idx = 0;
1453 else
1454 idx = inventory_slots.Find(slot);
1455 }
1456 if (idx < 0)
1457 return "";
1458
1459 return detach_types.Get(idx);
1460 }
1461
1462 void ExplodeAmmo()
1463 {
1464 //timer
1465 ref Timer explode_timer = new Timer(CALL_CATEGORY_SYSTEM);
1466
1467 //min/max time
1468 float min_time = 1;
1469 float max_time = 3;
1470 float delay = Math.RandomFloat(min_time, max_time);
1471
1472 explode_timer.Run(delay, this, "DoAmmoExplosion");
1473 }
1474
1475 void DoAmmoExplosion()
1476 {
1477 Magazine magazine = Magazine.Cast(this);
1478 int pop_sounds_count = 6;
1479 string pop_sounds[ 6 ] = { "ammopops_1","ammopops_2","ammopops_3","ammopops_4","ammopops_5","ammopops_6" };
1480
1481 //play sound
1482 int sound_idx = Math.RandomInt(0, pop_sounds_count - 1);
1483 string sound_name = pop_sounds[ sound_idx ];
1484 GetGame().CreateSoundOnObject(this, sound_name, 20, false);
1485
1486 //remove ammo count
1487 magazine.ServerAddAmmoCount(-1);
1488
1489 //if condition then repeat -> ExplodeAmmo
1490 float min_temp_to_explode = 100; //min temperature for item to explode
1491
1492 if (magazine.GetAmmoCount() > 0 && GetTemperature() >= min_temp_to_explode) //TODO ? add check for parent -> fireplace
1493 {
1494 ExplodeAmmo();
1495 }
1496 }
1497
1498 // -------------------------------------------------------------------------------
1499 override void EEHitBy(TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos, float speedCoef)
1500 {
1501 super.EEHitBy(damageResult, damageType, source, component, dmgZone, ammo, modelPos, speedCoef);
1502
1503 const int CHANCE_DAMAGE_CARGO = 4;
1504 const int CHANCE_DAMAGE_ATTACHMENT = 1;
1505 const int CHANCE_DAMAGE_NOTHING = 2;
1506
1507 if (IsClothing() || IsContainer() || IsItemTent())
1508 {
1509 float dmg = damageResult.GetDamage("","Health") * -0.5;
1510 int chances;
1511 int rnd;
1512
1513 if (GetInventory().GetCargo())
1514 {
1515 chances = CHANCE_DAMAGE_CARGO + CHANCE_DAMAGE_ATTACHMENT + CHANCE_DAMAGE_NOTHING;
1516 rnd = Math.RandomInt(0,chances);
1517
1518 if (rnd < CHANCE_DAMAGE_CARGO)
1519 {
1520 DamageItemInCargo(dmg);
1521 }
1522 else if (rnd < (chances - CHANCE_DAMAGE_NOTHING))
1523 {
1524 DamageItemAttachments(dmg);
1525 }
1526 }
1527 else
1528 {
1529 chances = CHANCE_DAMAGE_ATTACHMENT + CHANCE_DAMAGE_NOTHING;
1530 rnd = Math.RandomInt(0,chances);
1531
1532 if (rnd < CHANCE_DAMAGE_ATTACHMENT)
1533 {
1534 DamageItemAttachments(dmg);
1535 }
1536 }
1537 }
1538 }
1539
1540 bool DamageItemInCargo(float damage)
1541 {
1542 if (GetInventory().GetCargo())
1543 {
1544 int item_count = GetInventory().GetCargo().GetItemCount();
1545 if (item_count > 0)
1546 {
1547 int random_pick = Math.RandomInt(0, item_count);
1548 ItemBase item = ItemBase.Cast(GetInventory().GetCargo().GetItem(random_pick));
1549 if (!item.IsExplosive())
1550 {
1551 item.AddHealth("","",damage);
1552 return true;
1553 }
1554 }
1555 }
1556 return false;
1557 }
1558
1559 bool DamageItemAttachments(float damage)
1560 {
1561 int attachment_count = GetInventory().AttachmentCount();
1562 if (attachment_count > 0)
1563 {
1564 int random_pick = Math.RandomInt(0, attachment_count);
1565 ItemBase attachment = ItemBase.Cast(GetInventory().GetAttachmentFromIndex(random_pick));
1566 if (!attachment.IsExplosive())
1567 {
1568 attachment.AddHealth("","",damage);
1569 return true;
1570 }
1571 }
1572 return false;
1573 }
1574
1575 override bool IsSplitable()
1576 {
1577 return m_CanThisBeSplit;
1578 }
1579 //----------------
1580 override bool CanBeSplit()
1581 {
1582 if (IsSplitable() && (GetQuantity() > 1))
1583 return GetInventory().CanRemoveEntity();
1584
1585 return false;
1586 }
1587
1588 protected bool ShouldSplitQuantity(float quantity)
1589 {
1590 // don't call 'CanBeSplit' here, too strict and will introduce a freeze-crash when dismantling fence with a fireplace nearby
1591 if (!IsSplitable())
1592 return false;
1593
1594 // nothing to split?
1595 if (GetQuantity() <= 1)
1596 return false;
1597
1598 // check if we should re-use the item instead of creating a new copy?
1599 // implicit cast to int, if 'IsSplitable' returns true, these values are assumed ints
1600 int delta = GetQuantity() - quantity;
1601 if (delta == 0)
1602 return false;
1603
1604 // valid to split
1605 return true;
1606 }
1607
1608 override void SplitIntoStackMaxClient(EntityAI destination_entity, int slot_id )
1609 {
1610 if (GetGame().IsClient())
1611 {
1612 if (ScriptInputUserData.CanStoreInputUserData())
1613 {
1615 ctx.Write(INPUT_UDT_ITEM_MANIPULATION);
1616 ctx.Write(1);
1617 ItemBase i1 = this; // @NOTE: workaround for correct serialization
1618 ctx.Write(i1);
1619 ctx.Write(destination_entity);
1620 ctx.Write(true);
1621 ctx.Write(slot_id);
1622 ctx.Send();
1623 }
1624 }
1625 else if (!GetGame().IsMultiplayer())
1626 {
1627 SplitIntoStackMax(destination_entity, slot_id, PlayerBase.Cast(GetGame().GetPlayer()));
1628 }
1629 }
1630
1631 void SplitIntoStackMax(EntityAI destination_entity, int slot_id, PlayerBase player)
1632 {
1633 float split_quantity_new;
1634 ItemBase new_item;
1635 float quantity = GetQuantity();
1636 float stack_max = GetTargetQuantityMax(slot_id);
1638
1639 if (destination_entity && slot_id != -1 && InventorySlots.IsSlotIdValid(slot_id))
1640 {
1641 if (stack_max <= GetQuantity())
1642 split_quantity_new = stack_max;
1643 else
1644 split_quantity_new = GetQuantity();
1645
1646 if (ShouldSplitQuantity(split_quantity_new))
1647 {
1648 new_item = ItemBase.Cast(destination_entity.GetInventory().CreateAttachmentEx(this.GetType(), slot_id));
1649 if (new_item)
1650 {
1651 new_item.SetResultOfSplit(true);
1652 MiscGameplayFunctions.TransferItemProperties(this, new_item);
1653 AddQuantity(-split_quantity_new, false, true);
1654 new_item.SetQuantity(split_quantity_new, false, true);
1655 }
1656 }
1657 }
1658 else if (destination_entity && slot_id == -1)
1659 {
1660 if (quantity > stack_max)
1661 split_quantity_new = stack_max;
1662 else
1663 split_quantity_new = quantity;
1664
1665 if (ShouldSplitQuantity(split_quantity_new))
1666 {
1667 if (destination_entity.GetInventory().FindFreeLocationFor(this, FindInventoryLocationType.ANY, loc))
1668 {
1669 Object o = destination_entity.GetInventory().LocationCreateEntity(loc, GetType(), ECE_IN_INVENTORY, RF_DEFAULT);
1670 new_item = ItemBase.Cast(o);
1671 }
1672
1673 if (new_item)
1674 {
1675 new_item.SetResultOfSplit(true);
1676 MiscGameplayFunctions.TransferItemProperties(this, new_item);
1677 AddQuantity(-split_quantity_new, false, true);
1678 new_item.SetQuantity(split_quantity_new, false, true);
1679 }
1680 }
1681 }
1682 else
1683 {
1684 if (stack_max != 0)
1685 {
1686 if (stack_max < GetQuantity())
1687 {
1688 split_quantity_new = GetQuantity() - stack_max;
1689 }
1690
1691 if (split_quantity_new == 0)
1692 {
1693 if (!GetGame().IsMultiplayer())
1694 player.PhysicalPredictiveDropItem(this);
1695 else
1696 player.ServerDropEntity(this);
1697 return;
1698 }
1699
1700 if (ShouldSplitQuantity(split_quantity_new))
1701 {
1702 new_item = ItemBase.Cast(GetGame().CreateObjectEx(GetType(), player.GetWorldPosition(), ECE_PLACE_ON_SURFACE));
1703
1704 if (new_item)
1705 {
1706 new_item.SetResultOfSplit(true);
1707 MiscGameplayFunctions.TransferItemProperties(this, new_item);
1708 SetQuantity(split_quantity_new, false, true);
1709 new_item.SetQuantity(stack_max, false, true);
1710 new_item.PlaceOnSurface();
1711 }
1712 }
1713 }
1714 }
1715 }
1716
1717 override void SplitIntoStackMaxEx(EntityAI destination_entity, int slot_id)
1718 {
1719 float split_quantity_new;
1720 ItemBase new_item;
1721 float quantity = GetQuantity();
1722 float stack_max = GetTargetQuantityMax(slot_id);
1724
1725 if (destination_entity && slot_id != -1 && InventorySlots.IsSlotIdValid(slot_id))
1726 {
1727 if (stack_max <= GetQuantity())
1728 split_quantity_new = stack_max;
1729 else
1730 split_quantity_new = GetQuantity();
1731
1732 if (ShouldSplitQuantity(split_quantity_new))
1733 {
1734 new_item = ItemBase.Cast(destination_entity.GetInventory().CreateAttachmentEx(this.GetType(), slot_id));
1735 if (new_item)
1736 {
1737 new_item.SetResultOfSplit(true);
1738 MiscGameplayFunctions.TransferItemProperties(this, new_item);
1739 AddQuantity(-split_quantity_new, false, true);
1740 new_item.SetQuantity(split_quantity_new, false, true);
1741 }
1742 }
1743 }
1744 else if (destination_entity && slot_id == -1)
1745 {
1746 if (quantity > stack_max)
1747 split_quantity_new = stack_max;
1748 else
1749 split_quantity_new = quantity;
1750
1751 if (ShouldSplitQuantity(split_quantity_new))
1752 {
1753 if (destination_entity.GetInventory().FindFreeLocationFor(this, FindInventoryLocationType.ANY, loc))
1754 {
1755 Object o = destination_entity.GetInventory().LocationCreateEntity(loc, GetType(), ECE_IN_INVENTORY, RF_DEFAULT);
1756 new_item = ItemBase.Cast(o);
1757 }
1758
1759 if (new_item)
1760 {
1761 new_item.SetResultOfSplit(true);
1762 MiscGameplayFunctions.TransferItemProperties(this, new_item);
1763 AddQuantity(-split_quantity_new, false, true);
1764 new_item.SetQuantity(split_quantity_new, false, true);
1765 }
1766 }
1767 }
1768 else
1769 {
1770 if (stack_max != 0)
1771 {
1772 if (stack_max < GetQuantity())
1773 {
1774 split_quantity_new = GetQuantity() - stack_max;
1775 }
1776
1777 if (ShouldSplitQuantity(split_quantity_new))
1778 {
1779 new_item = ItemBase.Cast(GetGame().CreateObjectEx(GetType(),GetWorldPosition(), ECE_PLACE_ON_SURFACE));
1780
1781 if (new_item)
1782 {
1783 new_item.SetResultOfSplit(true);
1784 MiscGameplayFunctions.TransferItemProperties(this, new_item);
1785 SetQuantity(split_quantity_new, false, true);
1786 new_item.SetQuantity(stack_max, false, true);
1787 new_item.PlaceOnSurface();
1788 }
1789 }
1790 }
1791 }
1792 }
1793
1795 {
1796 if (GetGame().IsClient())
1797 {
1798 if (ScriptInputUserData.CanStoreInputUserData())
1799 {
1801 ctx.Write(INPUT_UDT_ITEM_MANIPULATION);
1802 ctx.Write(4);
1803 ItemBase thiz = this; // @NOTE: workaround for correct serialization
1804 ctx.Write(thiz);
1805 dst.WriteToContext(ctx);
1806 ctx.Send();
1807 }
1808 }
1809 else if (!GetGame().IsMultiplayer())
1810 {
1812 }
1813 }
1814
1815 void SplitIntoStackMaxCargoClient(EntityAI destination_entity, int idx, int row, int col)
1816 {
1817 if (GetGame().IsClient())
1818 {
1819 if (ScriptInputUserData.CanStoreInputUserData())
1820 {
1822 ctx.Write(INPUT_UDT_ITEM_MANIPULATION);
1823 ctx.Write(2);
1824 ItemBase dummy = this; // @NOTE: workaround for correct serialization
1825 ctx.Write(dummy);
1826 ctx.Write(destination_entity);
1827 ctx.Write(true);
1828 ctx.Write(idx);
1829 ctx.Write(row);
1830 ctx.Write(col);
1831 ctx.Send();
1832 }
1833 }
1834 else if (!GetGame().IsMultiplayer())
1835 {
1836 SplitIntoStackMaxCargo(destination_entity, idx, row, col);
1837 }
1838 }
1839
1844
1846 {
1847 float quantity = GetQuantity();
1848 float split_quantity_new;
1849 ItemBase new_item;
1850 if (dst.IsValid())
1851 {
1852 int slot_id = dst.GetSlot();
1853 float stack_max = GetTargetQuantityMax(slot_id);
1854
1855 if (quantity > stack_max)
1856 split_quantity_new = stack_max;
1857 else
1858 split_quantity_new = quantity;
1859
1860 if (ShouldSplitQuantity(split_quantity_new))
1861 {
1862 new_item = ItemBase.Cast(GameInventory.LocationCreateEntity(dst, this.GetType(), ECE_IN_INVENTORY, RF_DEFAULT));
1863
1864 if (new_item)
1865 {
1866 new_item.SetResultOfSplit(true);
1867 MiscGameplayFunctions.TransferItemProperties(this,new_item);
1868 AddQuantity(-split_quantity_new, false, true);
1869 new_item.SetQuantity(split_quantity_new, false, true);
1870 }
1871
1872 return new_item;
1873 }
1874 }
1875
1876 return null;
1877 }
1878
1879 void SplitIntoStackMaxCargo(EntityAI destination_entity, int idx, int row, int col)
1880 {
1881 float quantity = GetQuantity();
1882 float split_quantity_new;
1883 ItemBase new_item;
1884 if (destination_entity)
1885 {
1886 float stackable = GetTargetQuantityMax();
1887 if (quantity > stackable)
1888 split_quantity_new = stackable;
1889 else
1890 split_quantity_new = quantity;
1891
1892 if (ShouldSplitQuantity(split_quantity_new))
1893 {
1894 new_item = ItemBase.Cast(destination_entity.GetInventory().CreateEntityInCargoEx(this.GetType(), idx, row, col, false));
1895 if (new_item)
1896 {
1897 new_item.SetResultOfSplit(true);
1898 MiscGameplayFunctions.TransferItemProperties(this,new_item);
1899 AddQuantity(-split_quantity_new, false, true);
1900 new_item.SetQuantity(split_quantity_new, false, true);
1901 }
1902 }
1903 }
1904 }
1905
1907 {
1908 if (GetGame().IsClient())
1909 {
1910 if (ScriptInputUserData.CanStoreInputUserData())
1911 {
1913 ctx.Write(INPUT_UDT_ITEM_MANIPULATION);
1914 ctx.Write(3);
1915 ItemBase i1 = this; // @NOTE: workaround for correct serialization
1916 ctx.Write(i1);
1917 ItemBase destination_entity = this;
1918 ctx.Write(destination_entity);
1919 ctx.Write(true);
1920 ctx.Write(0);
1921 ctx.Send();
1922 }
1923 }
1924 else if (!GetGame().IsMultiplayer())
1925 {
1926 SplitIntoStackMaxHands(player);
1927 }
1928 }
1929
1931 {
1932 float quantity = GetQuantity();
1933 float split_quantity_new;
1934 ref ItemBase new_item;
1935 if (player)
1936 {
1937 float stackable = GetTargetQuantityMax();
1938 if (quantity > stackable)
1939 split_quantity_new = stackable;
1940 else
1941 split_quantity_new = quantity;
1942
1943 if (ShouldSplitQuantity(split_quantity_new))
1944 {
1945 EntityAI in_hands = player.GetHumanInventory().CreateInHands(this.GetType());
1946 new_item = ItemBase.Cast(in_hands);
1947 if (new_item)
1948 {
1949 new_item.SetResultOfSplit(true);
1950 MiscGameplayFunctions.TransferItemProperties(this,new_item);
1951 AddQuantity(-split_quantity_new, false, true);
1952 new_item.SetQuantity(split_quantity_new, false, true);
1953 }
1954 }
1955 }
1956 }
1957
1959 {
1960 float quantity = GetQuantity();
1961 float split_quantity_new = Math.Floor(quantity * 0.5);
1962
1963 if (!ShouldSplitQuantity(split_quantity_new))
1964 return;
1965
1967
1968 if (new_item)
1969 {
1970 if (new_item.GetQuantityMax() < split_quantity_new)
1971 {
1972 split_quantity_new = new_item.GetQuantityMax();
1973 }
1974
1975 new_item.SetResultOfSplit(true);
1976 MiscGameplayFunctions.TransferItemProperties(this, new_item);
1977
1978 if (dst.IsValid() && dst.GetType() == InventoryLocationType.ATTACHMENT && split_quantity_new > 1)
1979 {
1980 AddQuantity(-1, false, true);
1981 new_item.SetQuantity(1, false, true);
1982 }
1983 else
1984 {
1985 AddQuantity(-split_quantity_new, false, true);
1986 new_item.SetQuantity(split_quantity_new, false, true);
1987 }
1988 }
1989 }
1990
1992 {
1993 float quantity = GetQuantity();
1994 float split_quantity_new = Math.Floor(quantity / 2);
1995
1996 if (!ShouldSplitQuantity(split_quantity_new))
1997 return;
1998
2000 bool found = player.GetInventory().FindFirstFreeLocationForNewEntity(GetType(), FindInventoryLocationType.ATTACHMENT, invloc);
2001
2002 ItemBase new_item;
2003 new_item = player.CreateCopyOfItemInInventoryOrGroundEx(this, true);
2004
2005 if (new_item)
2006 {
2007 if (new_item.GetQuantityMax() < split_quantity_new)
2008 {
2009 split_quantity_new = new_item.GetQuantityMax();
2010 }
2011 if (found && invloc.IsValid() && invloc.GetType() == InventoryLocationType.ATTACHMENT && split_quantity_new > 1)
2012 {
2013 AddQuantity(-1, false, true);
2014 new_item.SetQuantity(1, false, true);
2015 }
2016 else if (split_quantity_new > 1)
2017 {
2018 AddQuantity(-split_quantity_new, false, true);
2019 new_item.SetQuantity(split_quantity_new, false, true);
2020 }
2021 }
2022 }
2023
2025 void OnQuantityChanged(float delta)
2026 {
2027 SetWeightDirty();
2028 ItemBase parent = ItemBase.Cast(GetHierarchyParent());
2029
2030 if (parent)
2031 parent.OnAttachmentQuantityChangedEx(this, delta);
2032
2033 if (IsLiquidContainer())
2034 {
2035 if (GetQuantityNormalized() <= 0.0)
2036 {
2038 }
2039 else if (GetLiquidType() == LIQUID_NONE)
2040 {
2041 ErrorEx("Undefined liquid type quantity changed, please define liquid type first! Using init value.",ErrorExSeverity.INFO);
2043 }
2044 }
2045
2046 }
2047
2050 {
2051 // insert code here
2052 }
2053
2056 {
2058 }
2059
2060 override void EEHealthLevelChanged(int oldLevel, int newLevel, string zone)
2061 {
2062 super.EEHealthLevelChanged(oldLevel,newLevel,zone);
2063
2064 if (GetGame().IsServer())
2065 {
2066 if (newLevel == GameConstants.STATE_RUINED)
2067 {
2069 EntityAI parent = GetHierarchyParent();
2070 if (parent && parent.IsFireplace())
2071 {
2072 CargoBase cargo = GetInventory().GetCargo();
2073 if (cargo)
2074 {
2075 for (int i = 0; i < cargo.GetItemCount(); ++i)
2076 {
2077 parent.GetInventory().TakeEntityToInventory(InventoryMode.SERVER, FindInventoryLocationType.CARGO, cargo.GetItem(i));
2078 }
2079 }
2080 }
2081 }
2082
2083 if (IsResultOfSplit())
2084 {
2085 // reset the splitting result flag, return to normal item behavior
2086 SetResultOfSplit(false);
2087 return;
2088 }
2089
2090 if (m_Cleanness != 0 && oldLevel < newLevel && newLevel != 0)
2091 {
2092 SetCleanness(0);//unclean the item upon damage dealt
2093 }
2094 }
2095 }
2096
2097 // just the split? TODO: verify
2098 override void OnRightClick()
2099 {
2100 super.OnRightClick();
2101
2102 if (CanBeSplit() && !GetDayZGame().IsLeftCtrlDown() && !GetGame().GetPlayer().GetInventory().HasInventoryReservation(this,null))
2103 {
2104 if (GetGame().IsClient())
2105 {
2106 if (ScriptInputUserData.CanStoreInputUserData())
2107 {
2108 EntityAI root = GetHierarchyRoot();
2109 Man playerOwner = GetHierarchyRootPlayer();
2111
2112 // If we have no hierarchy root player and the root is the same as this item the source item is in the vicinity so we want to create the new split item there also
2113 if (!playerOwner && root && root == this)
2114 {
2116 }
2117 else
2118 {
2119 // Check if we can place the new split item in the same parent where the source item is placed in or otherwise drop it in vicinity
2120 GetInventory().GetCurrentInventoryLocation(dst);
2121 if (!dst.GetParent() || dst.GetParent() && !dst.GetParent().GetInventory().FindFreeLocationFor(this, FindInventoryLocationType.CARGO, dst))
2122 {
2123 PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
2124 if (!player.GetInventory().FindFreeLocationFor(this, FindInventoryLocationType.CARGO, dst) || !playerOwner)
2125 {
2127 }
2128 else
2129 {
2130 dst.SetCargo(dst.GetParent(), this, dst.GetIdx(), dst.GetRow(), dst.GetCol(), dst.GetFlip());
2131 /* hacky solution to check reservation of "this" item instead of null since the gamecode is checking null against null and returning reservation=true incorrectly
2132 this shouldnt cause issues within this scope*/
2133 if (GetGame().GetPlayer().GetInventory().HasInventoryReservation(this, dst))
2134 {
2136 }
2137 else
2138 {
2139 GetGame().GetPlayer().GetInventory().AddInventoryReservationEx(null, dst, GameInventory.c_InventoryReservationTimeoutShortMS);
2140 }
2141 }
2142 }
2143 }
2144
2146 ctx.Write(INPUT_UDT_ITEM_MANIPULATION);
2147 ctx.Write(4);
2148 ItemBase thiz = this; // @NOTE: workaround for correct serialization
2149 ctx.Write(thiz);
2150 dst.WriteToContext(ctx);
2151 ctx.Write(true); // dummy
2152 ctx.Send();
2153 }
2154 }
2155 else if (!GetGame().IsMultiplayer())
2156 {
2158 }
2159 }
2160 }
2161
2163 {
2164 if (root)
2165 {
2166 vector m4[4];
2167 root.GetTransform(m4);
2168 dst.SetGround(this, m4);
2169 }
2170 else
2171 {
2172 GetInventory().GetCurrentInventoryLocation(dst);
2173 }
2174 }
2175
2176 override bool CanBeCombined(EntityAI other_item, bool reservation_check = true, bool stack_max_limit = false)
2177 {
2178 //TODO: delete check zero quantity check after fix double posts hands fsm events
2179 if (!other_item || GetType() != other_item.GetType() || (IsFullQuantity() && other_item.GetQuantity() > 0) || other_item == this)
2180 return false;
2181
2182 if (GetHealthLevel() == GameConstants.STATE_RUINED || other_item.GetHealthLevel() == GameConstants.STATE_RUINED)
2183 return false;
2184
2185 //can_this_be_combined = ConfigGetBool("canBeSplit");
2187 return false;
2188
2189
2190 Magazine mag = Magazine.Cast(this);
2191 if (mag)
2192 {
2193 if (mag.GetAmmoCount() >= mag.GetAmmoMax())
2194 return false;
2195
2196 if (stack_max_limit)
2197 {
2198 Magazine other_mag = Magazine.Cast(other_item);
2199 if (other_item)
2200 {
2201 if (mag.GetAmmoCount() + other_mag.GetAmmoCount() > mag.GetAmmoMax())
2202 return false;
2203 }
2204
2205 }
2206 }
2207 else
2208 {
2209 //TODO: delete check zero quantity check after fix double posts hands fsm events
2210 if (GetQuantity() >= GetQuantityMax() && other_item.GetQuantity() > 0 )
2211 return false;
2212
2213 if (stack_max_limit && (GetQuantity() + other_item.GetQuantity() > GetQuantityMax()))
2214 return false;
2215 }
2216
2217 PlayerBase player = null;
2218 if (CastTo(player, GetHierarchyRootPlayer())) //false when attached to player's attachment slot
2219 {
2220 if (player.GetInventory().HasAttachment(this))
2221 return false;
2222
2223 if (player.IsItemsToDelete())
2224 return false;
2225 }
2226
2227 if (reservation_check && (GetInventory().HasInventoryReservation(this, null) || other_item.GetInventory().HasInventoryReservation(other_item, null)))
2228 return false;
2229
2230 int slotID;
2231 string slotName;
2232 if (GetInventory().GetCurrentAttachmentSlotInfo(slotID,slotName) && GetHierarchyParent().GetInventory().GetSlotLock(slotID))
2233 return false;
2234
2235 return true;
2236 }
2237
2238 bool IsCombineAll(ItemBase other_item, bool use_stack_max = false)
2239 {
2240 return ComputeQuantityUsed(other_item, use_stack_max) == other_item.GetQuantity();
2241 }
2242
2244 {
2245 return m_IsResultOfSplit;
2246 }
2247
2248 void SetResultOfSplit(bool value)
2249 {
2250 m_IsResultOfSplit = value;
2251 }
2252
2253 int ComputeQuantityUsed(ItemBase other_item, bool use_stack_max = true)
2254 {
2255 return ComputeQuantityUsedEx(other_item, use_stack_max);
2256 }
2257
2258 float ComputeQuantityUsedEx(ItemBase other_item, bool use_stack_max = true)
2259 {
2260 float other_item_quantity = other_item.GetQuantity();
2261 float this_free_space;
2262
2263 float stack_max = GetQuantityMax();
2264
2265 this_free_space = stack_max - GetQuantity();
2266
2267 if (other_item_quantity > this_free_space)
2268 {
2269 return this_free_space;
2270 }
2271 else
2272 {
2273 return other_item_quantity;
2274 }
2275 }
2276
2277 override void CombineItemsEx(EntityAI entity2, bool use_stack_max = true)
2278 {
2279 CombineItems(ItemBase.Cast(entity2),use_stack_max);
2280 }
2281
2282 void CombineItems(ItemBase other_item, bool use_stack_max = true)
2283 {
2284 if (!CanBeCombined(other_item, false))
2285 return;
2286
2287 if (!IsMagazine() && other_item)
2288 {
2289 float quantity_used = ComputeQuantityUsedEx(other_item,use_stack_max);
2290 if (quantity_used != 0)
2291 {
2292 float hp1 = GetHealth01("","");
2293 float hp2 = other_item.GetHealth01("","");
2294 float hpResult = ((hp1*GetQuantity()) + (hp2*quantity_used));
2295 hpResult = hpResult / (GetQuantity() + quantity_used);
2296
2297 hpResult *= GetMaxHealth();
2298 Math.Round(hpResult);
2299 SetHealth("", "Health", hpResult);
2300
2301 AddQuantity(quantity_used);
2302 other_item.AddQuantity(-quantity_used);
2303 }
2304 }
2305 OnCombine(other_item);
2306 }
2307
2308 void OnCombine(ItemBase other_item)
2309 {
2310 #ifdef SERVER
2311 if (!GetHierarchyRootPlayer() && GetHierarchyParent())
2312 GetHierarchyParent().IncreaseLifetimeUp();
2313 #endif
2314 };
2315
2316 void GetRecipesActions(Man player, out TSelectableActionInfoArray outputList)
2317 {
2318 PlayerBase p = PlayerBase.Cast(player);
2319
2320 array<int> recipesIds = p.m_Recipes;
2321 PluginRecipesManager moduleRecipesManager = PluginRecipesManager.Cast(GetPlugin(PluginRecipesManager));
2322 if (moduleRecipesManager)
2323 {
2324 EntityAI itemInHands = player.GetHumanInventory().GetEntityInHands();
2325 moduleRecipesManager.GetValidRecipes(ItemBase.Cast(this), ItemBase.Cast(itemInHands), recipesIds, p);
2326 }
2327
2328 for (int i = 0;i < recipesIds.Count(); i++)
2329 {
2330 int key = recipesIds.Get(i);
2331 string recipeName = moduleRecipesManager.GetRecipeName(key);
2332 outputList.Insert(new TSelectableActionInfo(SAT_CRAFTING, key, recipeName));
2333 }
2334 }
2335
2336 // -------------------------------------------------------------------------
2337 override void GetDebugActions(out TSelectableActionInfoArrayEx outputList)
2338 {
2339 super.GetDebugActions(outputList);
2340
2341 //quantity
2342 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.ADD_QUANTITY, "Quantity +20%", FadeColors.LIGHT_GREY));
2343 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.REMOVE_QUANTITY, "Quantity -20%", FadeColors.LIGHT_GREY));
2344 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SET_QUANTITY_0, "Set Quantity 0", FadeColors.LIGHT_GREY));
2345 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SET_MAX_QUANTITY, "Set Quantity Max", FadeColors.LIGHT_GREY));
2346 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
2347
2348 //health
2349 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.ADD_HEALTH, "Health +20%", FadeColors.LIGHT_GREY));
2350 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.REMOVE_HEALTH, "Health -20%", FadeColors.LIGHT_GREY));
2351 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.DESTROY_HEALTH, "Health 0", FadeColors.LIGHT_GREY));
2352 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
2353 //temperature
2354 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.ADD_TEMPERATURE, "Temperature +20", FadeColors.LIGHT_GREY));
2355 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.REMOVE_TEMPERATURE, "Temperature -20", FadeColors.LIGHT_GREY));
2356 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.FLIP_FROZEN, "Toggle Frozen", FadeColors.LIGHT_GREY));
2357 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
2358
2359 //wet
2360 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.ADD_WETNESS, "Wetness +20", FadeColors.LIGHT_GREY));
2361 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.REMOVE_WETNESS, "Wetness -20", FadeColors.LIGHT_GREY));
2362 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
2363
2364 //liquidtype
2365 if (IsLiquidContainer())
2366 {
2367 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.LIQUIDTYPE_UP, "LiquidType Next", FadeColors.LIGHT_GREY));
2368 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.LIQUIDTYPE_DOWN, "LiquidType Previous", FadeColors.LIGHT_GREY));
2369 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
2370 }
2371
2372 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.MAKE_SPECIAL, "Make Special", FadeColors.LIGHT_GREY));
2373 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
2374
2375 // watch
2376 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.WATCH_ITEM, "Watch (CTRL-Z)", FadeColors.LIGHT_GREY));
2377 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.WATCH_PLAYER, "Watch Player", FadeColors.LIGHT_GREY));
2378 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
2379
2380 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.DELETE, "Delete", FadeColors.RED));
2381
2383 GetInventory().GetCurrentInventoryLocation(loc);
2384 if (!loc || loc.GetType() == InventoryLocationType.GROUND)
2385 {
2386 if (Gizmo_IsSupported())
2387 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.GIZMO_OBJECT, "Gizmo Object", FadeColors.LIGHT_GREY));
2388 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.GIZMO_PHYSICS, "Gizmo Physics (SP Only)", FadeColors.LIGHT_GREY)); // intentionally allowed for testing physics desync
2389 }
2390
2391 outputList.Insert(new TSelectableActionInfoWithColor(SAT_DEBUG_ACTION, EActions.SEPARATOR, "___________________________", FadeColors.RED));
2392 }
2393
2394 // -------------------------------------------------------------------------
2395 // -------------------------------------------------------------------------
2396 // -------------------------------------------------------------------------
2397 override bool OnAction(int action_id, Man player, ParamsReadContext ctx)
2398 {
2399 super.OnAction(action_id, player, ctx);
2400
2401 if (GetGame().IsClient() || !GetGame().IsMultiplayer())
2402 {
2403 switch (action_id)
2404 {
2405 case EActions.GIZMO_OBJECT:
2406 GetGame().GizmoSelectObject(this);
2407 return true;
2408 case EActions.GIZMO_PHYSICS:
2409 GetGame().GizmoSelectPhysics(GetPhysics());
2410 return true;
2411 }
2412 }
2413
2414 if (GetGame().IsServer())
2415 {
2416 switch (action_id)
2417 {
2418 case EActions.DELETE:
2419 Delete();
2420 return true;
2421 }
2422 }
2423
2424 if (action_id >= EActions.RECIPES_RANGE_START && action_id < EActions.RECIPES_RANGE_END)
2425 {
2426 PluginRecipesManager plugin_recipes_manager = PluginRecipesManager.Cast(GetPlugin(PluginRecipesManager));
2427 int idWithoutOffset = action_id - EActions.RECIPES_RANGE_START;
2428 PlayerBase p = PlayerBase.Cast(player);
2429 if (EActions.RECIPES_RANGE_START < 1000)
2430 {
2431 float anim_length = plugin_recipes_manager.GetRecipeLengthInSecs(idWithoutOffset);
2432 float specialty_weight = plugin_recipes_manager.GetRecipeSpecialty(idWithoutOffset);
2433 }
2434 }
2435 #ifndef SERVER
2436 else if (action_id == EActions.WATCH_PLAYER)
2437 {
2438 PluginDeveloper.SetDeveloperItemClientEx(player);
2439 }
2440 #endif
2441 if (GetGame().IsServer())
2442 {
2443 if (action_id >= EActions.DEBUG_ITEM_WATCH_BUTTON_RANGE_START && action_id < EActions.DEBUG_ITEM_WATCH_BUTTON_RANGE_END)
2444 {
2445 int id = action_id - EActions.DEBUG_ITEM_WATCH_BUTTON_RANGE_START;
2446 OnDebugButtonPressServer(id + 1);
2447 }
2448
2449 else if (action_id >= EActions.DEBUG_AGENTS_RANGE_INJECT_START && action_id < EActions.DEBUG_AGENTS_RANGE_INJECT_END)
2450 {
2451 int agent_id = action_id - EActions.DEBUG_AGENTS_RANGE_INJECT_START;
2452 InsertAgent(agent_id,100);
2453 }
2454
2455 else if (action_id >= EActions.DEBUG_AGENTS_RANGE_REMOVE_START && action_id < EActions.DEBUG_AGENTS_RANGE_REMOVE_END)
2456 {
2457 int agent_id2 = action_id - EActions.DEBUG_AGENTS_RANGE_REMOVE_START;
2458 RemoveAgent(agent_id2);
2459 }
2460
2461 else if (action_id == EActions.ADD_QUANTITY)
2462 {
2463 if (IsMagazine())
2464 {
2465 Magazine mag = Magazine.Cast(this);
2466 mag.ServerSetAmmoCount(mag.GetAmmoCount() + mag.GetAmmoMax() * 0.2);
2467 }
2468 else
2469 {
2470 AddQuantity(GetQuantityMax() * 0.2);
2471 }
2472
2473 if (m_EM)
2474 {
2475 m_EM.AddEnergy(m_EM.GetEnergyMax() * 0.2);
2476 }
2477 //PrintVariables();
2478 }
2479
2480 else if (action_id == EActions.REMOVE_QUANTITY) //Quantity -20%
2481 {
2482 if (IsMagazine())
2483 {
2484 Magazine mag2 = Magazine.Cast(this);
2485 mag2.ServerSetAmmoCount(mag2.GetAmmoCount() - mag2.GetAmmoMax() * 0.2);
2486 }
2487 else
2488 {
2489 AddQuantity(- GetQuantityMax() * 0.2);
2490 }
2491 if (m_EM)
2492 {
2493 m_EM.AddEnergy(- m_EM.GetEnergyMax() * 0.2);
2494 }
2495 //PrintVariables();
2496 }
2497
2498 else if (action_id == EActions.SET_QUANTITY_0) //SetMaxQuantity
2499 {
2500 SetQuantity(0);
2501
2502 if (m_EM)
2503 {
2504 m_EM.SetEnergy(0);
2505 }
2506 }
2507
2508 else if (action_id == EActions.SET_MAX_QUANTITY) //SetMaxQuantity
2509 {
2511
2512 if (m_EM)
2513 {
2514 m_EM.SetEnergy(m_EM.GetEnergyMax());
2515 }
2516 }
2517
2518 else if (action_id == EActions.ADD_HEALTH)
2519 {
2520 AddHealth("","",GetMaxHealth("","Health")/5);
2521 }
2522 else if (action_id == EActions.REMOVE_HEALTH)
2523 {
2524 AddHealth("","",-GetMaxHealth("","Health")/5);
2525 }
2526 else if (action_id == EActions.DESTROY_HEALTH)
2527 {
2528 SetHealth01("","",0);
2529 }
2530 else if (action_id == EActions.WATCH_ITEM)
2531 {
2533 mid.RegisterDebugItem(ItemBase.Cast(this), PlayerBase.Cast(player));
2534 #ifdef DEVELOPER
2535 SetDebugDeveloper_item(this);
2536 #endif
2537 }
2538
2539 else if (action_id == EActions.ADD_TEMPERATURE)
2540 {
2541 AddTemperature(20);
2542 //PrintVariables();
2543 }
2544
2545 else if (action_id == EActions.REMOVE_TEMPERATURE)
2546 {
2547 AddTemperature(-20);
2548 //PrintVariables();
2549 }
2550
2551 else if (action_id == EActions.FLIP_FROZEN)
2552 {
2553 SetFrozen(!GetIsFrozen());
2554 //PrintVariables();
2555 }
2556
2557 else if (action_id == EActions.ADD_WETNESS)
2558 {
2559 AddWet(GetWetMax()/5);
2560 //PrintVariables();
2561 }
2562
2563 else if (action_id == EActions.REMOVE_WETNESS)
2564 {
2565 AddWet(-GetWetMax()/5);
2566 //PrintVariables();
2567 }
2568
2569 else if (action_id == EActions.LIQUIDTYPE_UP)
2570 {
2571 int curr_type = GetLiquidType();
2572 SetLiquidType(curr_type * 2);
2573 //AddWet(1);
2574 //PrintVariables();
2575 }
2576
2577 else if (action_id == EActions.LIQUIDTYPE_DOWN)
2578 {
2579 int curr_type2 = GetLiquidType();
2580 SetLiquidType(curr_type2 / 2);
2581 }
2582
2583 else if (action_id == EActions.MAKE_SPECIAL)
2584 {
2585 auto debugParams = DebugSpawnParams.WithPlayer(player);
2586 OnDebugSpawnEx(debugParams);
2587 }
2588
2589 }
2590
2591
2592 return false;
2593 }
2594
2595 // -------------------------------------------------------------------------
2596
2597
2601
2603 void OnActivatedByItem(notnull ItemBase item);
2604
2605 //----------------------------------------------------------------
2606 //returns true if item is able to explode when put in fire
2608 {
2609 return false;
2610 }
2611
2612 //----------------------------------------------------------------
2613 bool CanEat()
2614 {
2615 return true;
2616 }
2617
2618 //----------------------------------------------------------------
2620 {
2621 return true;
2622 }
2623
2624 //----------------------------------------------------------------
2625 //has FoodStages in config?
2627 {
2628 string config_path = string.Format("CfgVehicles %1 Food FoodStages", GetType());
2629 return GetGame().ConfigIsExisting(config_path);
2630 }
2631
2633 FoodStage GetFoodStage()
2634 {
2635 return null;
2636 }
2637
2639 {
2640 return false;
2641 }
2642
2644 {
2645 return false;
2646 }
2647
2649 void RefreshAudioVisualsOnClient( CookingMethodType cooking_method, bool is_done, bool is_empty, bool is_burned );
2651
2652 //----------------------------------------------------------------
2653 bool CanRepair(ItemBase item_repair_kit)
2654 {
2655 PluginRepairing module_repairing = PluginRepairing.Cast(GetPlugin(PluginRepairing));
2656 return module_repairing.CanRepair(this, item_repair_kit);
2657 }
2658
2659 //----------------------------------------------------------------
2660 bool Repair(PlayerBase player, ItemBase item_repair_kit, float specialty_weight)
2661 {
2662 PluginRepairing module_repairing = PluginRepairing.Cast(GetPlugin(PluginRepairing));
2663 return module_repairing.Repair(player, this, item_repair_kit, specialty_weight);
2664 }
2665
2666 //----------------------------------------------------------------
2668 {
2669 /*
2670 vector v_size = this.ConfigGetVector("itemSize");
2671 int v_size_x = v_size[0];
2672 int v_size_y = v_size[1];
2673 int size = v_size_x * v_size_y;
2674 return size;
2675 */
2676
2677 return 1;
2678 }
2679
2680 //----------------------------------------------------------------
2681 //Override for allowing seemingly unallowed moves when two clients send a conflicting message simultaneously
2683 {
2684 return m_CanBeMovedOverride;
2685 }
2686
2687 //----------------------------------------------------------------
2688 //Override for allowing seemingly unallowed moves when two clients send a conflicting message simultaneously
2689 void SetCanBeMovedOverride(bool setting)
2690 {
2691 m_CanBeMovedOverride = setting;
2692 }
2693
2694 //----------------------------------------------------------------
2702 void MessageToOwnerStatus(string text)
2703 {
2704 PlayerBase player = PlayerBase.Cast(this.GetHierarchyRootPlayer());
2705
2706 if (player)
2707 {
2708 player.MessageStatus(text);
2709 }
2710 }
2711
2712 //----------------------------------------------------------------
2720 void MessageToOwnerAction(string text)
2721 {
2722 PlayerBase player = PlayerBase.Cast(this.GetHierarchyRootPlayer());
2723
2724 if (player)
2725 {
2726 player.MessageAction(text);
2727 }
2728 }
2729
2730 //----------------------------------------------------------------
2738 void MessageToOwnerFriendly(string text)
2739 {
2740 PlayerBase player = PlayerBase.Cast(this.GetHierarchyRootPlayer());
2741
2742 if (player)
2743 {
2744 player.MessageFriendly(text);
2745 }
2746 }
2747
2748 //----------------------------------------------------------------
2756 void MessageToOwnerImportant(string text)
2757 {
2758 PlayerBase player = PlayerBase.Cast(this.GetHierarchyRootPlayer());
2759
2760 if (player)
2761 {
2762 player.MessageImportant(text);
2763 }
2764 }
2765
2766 override bool IsItemBase()
2767 {
2768 return true;
2769 }
2770
2771 // Checks if item is of questioned kind
2772 override bool KindOf(string tag)
2773 {
2774 bool found = false;
2775 string item_name = this.GetType();
2776 ref TStringArray item_tag_array = new TStringArray;
2777 GetGame().ConfigGetTextArray("cfgVehicles " + item_name + " itemInfo", item_tag_array);
2778
2779 int array_size = item_tag_array.Count();
2780 for (int i = 0; i < array_size; i++)
2781 {
2782 if (item_tag_array.Get(i) == tag)
2783 {
2784 found = true;
2785 break;
2786 }
2787 }
2788 return found;
2789 }
2790
2791
2792 override void OnRPC(PlayerIdentity sender, int rpc_type,ParamsReadContext ctx)
2793 {
2794 //Debug.Log("OnRPC called");
2795 super.OnRPC(sender, rpc_type,ctx);
2796
2797 //Play soundset for attachment locking (ActionLockAttachment.c)
2798 switch (rpc_type)
2799 {
2800 #ifndef SERVER
2801 case ERPCs.RPC_SOUND_LOCK_ATTACH:
2802 Param2<bool, string> p = new Param2<bool, string>(false, "");
2803
2804 if (!ctx.Read(p))
2805 return;
2806
2807 bool play = p.param1;
2808 string soundSet = p.param2;
2809
2810 if (play)
2811 {
2812 if (m_LockingSound)
2813 {
2815 {
2816 m_LockingSound = SEffectManager.PlaySound(soundSet, GetPosition(), 0, 0, true);
2817 }
2818 }
2819 else
2820 {
2821 m_LockingSound = SEffectManager.PlaySound(soundSet, GetPosition(), 0, 0, true);
2822 }
2823 }
2824 else
2825 {
2827 }
2828
2829 break;
2830 #endif
2831
2832 }
2833
2834 if (GetWrittenNoteData())
2835 {
2836 GetWrittenNoteData().OnRPC(sender, rpc_type,ctx);
2837 }
2838 }
2839
2840 //-----------------------------
2841 // VARIABLE MANIPULATION SYSTEM
2842 //-----------------------------
2843 int NameToID(string name)
2844 {
2845 PluginVariables plugin = PluginVariables.Cast(GetPlugin(PluginVariables));
2846 return plugin.GetID(name);
2847 }
2848
2849 string IDToName(int id)
2850 {
2851 PluginVariables plugin = PluginVariables.Cast(GetPlugin(PluginVariables));
2852 return plugin.GetName(id);
2853 }
2854
2856 void OnSyncVariables(ParamsReadContext ctx)//with ID optimization
2857 {
2858 //Debug.Log("OnSyncVariables called for item: "+ ToString(this.GetType()),"varSync");
2859 //read the flags
2860 int varFlags;
2861 if (!ctx.Read(varFlags))
2862 return;
2863
2864 if (varFlags & ItemVariableFlags.FLOAT)
2865 {
2866 ReadVarsFromCTX(ctx);
2867 }
2868 }
2869
2870 override void SerializeNumericalVars(array<float> floats_out)
2871 {
2872 //some variables handled on EntityAI level already!
2873 super.SerializeNumericalVars(floats_out);
2874
2875 // the order of serialization must be the same as the order of de-serialization
2876 //--------------------------------------------
2877 if (IsVariableSet(VARIABLE_QUANTITY))
2878 {
2879 floats_out.Insert(m_VarQuantity);
2880 }
2881 //--------------------------------------------
2882 if (IsVariableSet(VARIABLE_WET))
2883 {
2884 floats_out.Insert(m_VarWet);
2885 }
2886 //--------------------------------------------
2887 if (IsVariableSet(VARIABLE_LIQUIDTYPE))
2888 {
2889 floats_out.Insert(m_VarLiquidType);
2890 }
2891 //--------------------------------------------
2892 if (IsVariableSet(VARIABLE_COLOR))
2893 {
2894 floats_out.Insert(m_ColorComponentR);
2895 floats_out.Insert(m_ColorComponentG);
2896 floats_out.Insert(m_ColorComponentB);
2897 floats_out.Insert(m_ColorComponentA);
2898 }
2899 //--------------------------------------------
2900 if (IsVariableSet(VARIABLE_CLEANNESS))
2901 {
2902 floats_out.Insert(m_Cleanness);
2903 }
2904 }
2905
2907 {
2908 //some variables handled on EntityAI level already!
2909 super.DeSerializeNumericalVars(floats);
2910
2911 // the order of serialization must be the same as the order of de-serialization
2912 int index = 0;
2913 int mask = Math.Round(floats.Get(index));
2914
2915 index++;
2916 //--------------------------------------------
2917 if (mask & VARIABLE_QUANTITY)
2918 {
2919 if (m_IsStoreLoad)
2920 {
2921 SetStoreLoadedQuantity(floats.Get(index));
2922 }
2923 else
2924 {
2925 float quantity = floats.Get(index);
2926 SetQuantity(quantity, true, false, false, false);
2927 }
2928 index++;
2929 }
2930 //--------------------------------------------
2931 if (mask & VARIABLE_WET)
2932 {
2933 float wet = floats.Get(index);
2934 SetWet(wet);
2935 index++;
2936 }
2937 //--------------------------------------------
2938 if (mask & VARIABLE_LIQUIDTYPE)
2939 {
2940 int liquidtype = Math.Round(floats.Get(index));
2941 SetLiquidType(liquidtype);
2942 index++;
2943 }
2944 //--------------------------------------------
2945 if (mask & VARIABLE_COLOR)
2946 {
2947 m_ColorComponentR = Math.Round(floats.Get(index));
2948 index++;
2949 m_ColorComponentG = Math.Round(floats.Get(index));
2950 index++;
2951 m_ColorComponentB = Math.Round(floats.Get(index));
2952 index++;
2953 m_ColorComponentA = Math.Round(floats.Get(index));
2954 index++;
2955 }
2956 //--------------------------------------------
2957 if (mask & VARIABLE_CLEANNESS)
2958 {
2959 int cleanness = Math.Round(floats.Get(index));
2960 SetCleanness(cleanness);
2961 index++;
2962 }
2963 }
2964
2966 {
2967 super.WriteVarsToCTX(ctx);
2968
2969 //--------------------------------------------
2970 if (IsVariableSet(VARIABLE_QUANTITY))
2971 {
2972 ctx.Write(GetQuantity());
2973 }
2974 //--------------------------------------------
2975 if (IsVariableSet(VARIABLE_WET))
2976 {
2977 ctx.Write(GetWet());
2978 }
2979 //--------------------------------------------
2980 if (IsVariableSet(VARIABLE_LIQUIDTYPE))
2981 {
2982 ctx.Write(GetLiquidType());
2983 }
2984 //--------------------------------------------
2985 if (IsVariableSet(VARIABLE_COLOR))
2986 {
2987 int r,g,b,a;
2988 GetColor(r,g,b,a);
2989 ctx.Write(r);
2990 ctx.Write(g);
2991 ctx.Write(b);
2992 ctx.Write(a);
2993 }
2994 //--------------------------------------------
2995 if (IsVariableSet(VARIABLE_CLEANNESS))
2996 {
2997 ctx.Write(GetCleanness());
2998 }
2999 }
3000
3001 override bool ReadVarsFromCTX(ParamsReadContext ctx, int version = -1)//with ID optimization
3002 {
3003 if (!super.ReadVarsFromCTX(ctx,version))
3004 return false;
3005
3006 int intValue;
3007 float value;
3008
3009 if (version < 140)
3010 {
3011 if (!ctx.Read(intValue))
3012 return false;
3013
3014 m_VariablesMask = intValue;
3015 }
3016
3017 if (m_VariablesMask & VARIABLE_QUANTITY)
3018 {
3019 if (!ctx.Read(value))
3020 return false;
3021
3022 if (IsStoreLoad())
3023 {
3025 }
3026 else
3027 {
3028 SetQuantity(value, true, false, false, false);
3029 }
3030 }
3031 //--------------------------------------------
3032 if (version < 140)
3033 {
3034 if (m_VariablesMask & VARIABLE_TEMPERATURE)
3035 {
3036 if (!ctx.Read(value))
3037 return false;
3038 SetTemperatureDirect(value);
3039 }
3040 }
3041 //--------------------------------------------
3042 if (m_VariablesMask & VARIABLE_WET)
3043 {
3044 if (!ctx.Read(value))
3045 return false;
3046 SetWet(value);
3047 }
3048 //--------------------------------------------
3049 if (m_VariablesMask & VARIABLE_LIQUIDTYPE)
3050 {
3051 if (!ctx.Read(intValue))
3052 return false;
3053 SetLiquidType(intValue);
3054 }
3055 //--------------------------------------------
3056 if (m_VariablesMask & VARIABLE_COLOR)
3057 {
3058 int r,g,b,a;
3059 if (!ctx.Read(r))
3060 return false;
3061 if (!ctx.Read(g))
3062 return false;
3063 if (!ctx.Read(b))
3064 return false;
3065 if (!ctx.Read(a))
3066 return false;
3067
3068 SetColor(r,g,b,a);
3069 }
3070 //--------------------------------------------
3071 if (m_VariablesMask & VARIABLE_CLEANNESS)
3072 {
3073 if (!ctx.Read(intValue))
3074 return false;
3075 SetCleanness(intValue);
3076 }
3077 //--------------------------------------------
3078 if (version >= 138 && version < 140)
3079 {
3080 if (m_VariablesMask & VARIABLE_TEMPERATURE)
3081 {
3082 if (!ctx.Read(intValue))
3083 return false;
3084 SetFrozen(intValue);
3085 }
3086 }
3087
3088 return true;
3089 }
3090
3091 //----------------------------------------------------------------
3092 override bool OnStoreLoad(ParamsReadContext ctx, int version)
3093 {
3094 m_IsStoreLoad = true;
3096 {
3097 m_FixDamageSystemInit = true;
3098 }
3099
3100 if (!super.OnStoreLoad(ctx, version))
3101 {
3102 m_IsStoreLoad = false;
3103 return false;
3104 }
3105
3106 if (version >= 114)
3107 {
3108 bool hasQuickBarIndexSaved;
3109
3110 if (!ctx.Read(hasQuickBarIndexSaved))
3111 {
3112 m_IsStoreLoad = false;
3113 return false;
3114 }
3115
3116 if (hasQuickBarIndexSaved)
3117 {
3118 int itmQBIndex;
3119
3120 //Load quickbar item bind
3121 if (!ctx.Read(itmQBIndex))
3122 {
3123 m_IsStoreLoad = false;
3124 return false;
3125 }
3126
3127 PlayerBase parentPlayer = PlayerBase.Cast(GetHierarchyRootPlayer());
3128 if (itmQBIndex != -1 && parentPlayer)
3129 parentPlayer.SetLoadedQuickBarItemBind(this, itmQBIndex);
3130 }
3131 }
3132 else
3133 {
3134 // Backup of how it used to be
3135 PlayerBase player;
3136 int itemQBIndex;
3137 if (version == int.MAX)
3138 {
3139 if (!ctx.Read(itemQBIndex))
3140 {
3141 m_IsStoreLoad = false;
3142 return false;
3143 }
3144 }
3145 else if (Class.CastTo(player, GetHierarchyRootPlayer()))
3146 {
3147 //Load quickbar item bind
3148 if (!ctx.Read(itemQBIndex))
3149 {
3150 m_IsStoreLoad = false;
3151 return false;
3152 }
3153 if (itemQBIndex != -1 && player)
3154 player.SetLoadedQuickBarItemBind(this,itemQBIndex);
3155 }
3156 }
3157
3158 if (version < 140)
3159 {
3160 // variable management system
3161 if (!LoadVariables(ctx, version))
3162 {
3163 m_IsStoreLoad = false;
3164 return false;
3165 }
3166 }
3167
3168 //agent trasmission system
3169 if (!LoadAgents(ctx, version))
3170 {
3171 m_IsStoreLoad = false;
3172 return false;
3173 }
3174 if (version >= 132)
3175 {
3177 if (raib)
3178 {
3179 if (!raib.OnStoreLoad(ctx,version))
3180 {
3181 m_IsStoreLoad = false;
3182 return false;
3183 }
3184 }
3185 }
3186
3187 m_IsStoreLoad = false;
3188 return true;
3189 }
3190
3191 //----------------------------------------------------------------
3192
3194 {
3195 super.OnStoreSave(ctx);
3196
3197 PlayerBase player;
3198 if (PlayerBase.CastTo(player,GetHierarchyRootPlayer()))
3199 {
3200 ctx.Write(true); // Keep track of if we should actually read this in or not
3201 //Save quickbar item bind
3202 int itemQBIndex = -1;
3203 itemQBIndex = player.FindQuickBarEntityIndex(this);
3204 ctx.Write(itemQBIndex);
3205 }
3206 else
3207 {
3208 ctx.Write(false); // Keep track of if we should actually read this in or not
3209 }
3210
3211 SaveAgents(ctx);//agent trasmission system
3212
3214 if (raib)
3215 {
3216 raib.OnStoreSave(ctx);
3217 }
3218 }
3219 //----------------------------------------------------------------
3220
3221 override void AfterStoreLoad()
3222 {
3223 super.AfterStoreLoad();
3224
3226 {
3228 }
3229
3230 if (GetStoreLoadedQuantity() != float.LOWEST)
3231 {
3232 SetQuantity(GetStoreLoadedQuantity());
3233 SetStoreLoadedQuantity(float.LOWEST);//IMPORTANT to do this !! we use 'm_StoreLoadedQuantity' inside SetQuantity to distinguish between initial quantity setting and the consequent(normal gameplay) calls
3234 }
3235 }
3236
3237 override void EEOnAfterLoad()
3238 {
3239 super.EEOnAfterLoad();
3240
3242 {
3243 m_FixDamageSystemInit = false;
3244 }
3245
3248 }
3249
3251 {
3252 return false;
3253 }
3254
3255
3256 //----------------------------------------------------------------
3258 {
3259 if (m_Initialized)
3260 {
3261 #ifdef PLATFORM_CONSOLE
3262 //bruteforce it is
3263 if (IsSplitable())
3264 {
3265 UIScriptedMenu menu = GetGame().GetUIManager().FindMenu(MENU_INVENTORY);
3266 if (menu)
3267 {
3268 menu.Refresh();
3269 }
3270 }
3271 #endif
3272 }
3273
3275 {
3276 PlayImpactSound(m_ConfigWeight, m_ImpactSpeed, m_ImpactSoundSurfaceHash);
3277 m_WantPlayImpactSound = false;
3278 }
3279
3281 {
3282 SetWeightDirty();
3284 }
3285 if (m_VarWet != m_VarWetPrev)
3286 {
3289 }
3290
3291 if (m_SoundSyncPlay != 0)
3292 {
3293 m_ItemSoundHandler.PlayItemSoundClient(m_SoundSyncPlay);
3294 m_SoundSyncPlay = 0;
3295 }
3296 if (m_SoundSyncStop != 0)
3297 {
3298 m_ItemSoundHandler.StopItemSoundClient(m_SoundSyncStop);
3299 m_SoundSyncStop = 0;
3300 }
3301
3302 super.OnVariablesSynchronized();
3303 }
3304
3305 //------------------------- Quantity
3306 //----------------------------------------------------------------
3308 override bool SetQuantity(float value, bool destroy_config = true, bool destroy_forced = false, bool allow_client = false, bool clamp_to_stack_max = true)
3309 {
3310 if (!IsServerCheck(allow_client))
3311 return false;
3312
3313 if (!HasQuantity())
3314 return false;
3315
3316 float min = GetQuantityMin();
3317 float max = GetQuantityMax();
3318
3319 if (value <= (min + 0.001))
3320 value = min;
3321
3322 if (value == min)
3323 {
3324 if (destroy_config)
3325 {
3326 bool dstr = ConfigGetBool("varQuantityDestroyOnMin");
3327 if (dstr)
3328 {
3329 m_VarQuantity = Math.Clamp(value, min, max);
3330 this.Delete();
3331 return true;
3332 }
3333 }
3334 else if (destroy_forced)
3335 {
3336 m_VarQuantity = Math.Clamp(value, min, max);
3337 this.Delete();
3338 return true;
3339 }
3340 // we get here if destroy_config IS true AND dstr(config destroy param) IS false;
3341 RemoveAllAgents();//we remove all agents when we got to the min value, but the item is not getting deleted
3342 }
3343
3344 float delta = m_VarQuantity;
3345 m_VarQuantity = Math.Clamp(value, min, max);
3346
3347 if (GetStoreLoadedQuantity() == float.LOWEST)//any other value means we are setting quantity from storage
3348 {
3349 delta = m_VarQuantity - delta;
3350
3351 if (delta)
3352 OnQuantityChanged(delta);
3353 }
3354
3355 SetVariableMask(VARIABLE_QUANTITY);
3356
3357 return false;
3358 }
3359
3360 //----------------------------------------------------------------
3362 bool AddQuantity(float value, bool destroy_config = true, bool destroy_forced = false)
3363 {
3364 return SetQuantity(GetQuantity() + value, destroy_config, destroy_forced);
3365 }
3366 //----------------------------------------------------------------
3368 {
3369 float max = GetQuantityMax();
3370 SetQuantity(max);
3371 }
3372
3373 override void SetQuantityToMinimum()
3374 {
3375 float min = GetQuantityMin();
3376 SetQuantity(min);
3377 }
3378 //----------------------------------------------------------------
3380 override void SetQuantityNormalized(float value, bool destroy_config = true, bool destroy_forced = false)
3381 {
3382 float value_clamped = Math.Clamp(value, 0, 1);//just to make sure
3383 int result = Math.Round(Math.Lerp(GetQuantityMin(), GetQuantityMax(), value_clamped));
3384 SetQuantity(result, destroy_config, destroy_forced);
3385 }
3386
3387 //----------------------------------------------------------------
3389 override float GetQuantityNormalized()
3390 {
3391 return Math.InverseLerp(GetQuantityMin(), GetQuantityMax(),m_VarQuantity);
3392 }
3393
3395 {
3396 return GetQuantityNormalized();
3397 }
3398
3399 /*void SetAmmoNormalized(float value)
3400 {
3401 float value_clamped = Math.Clamp(value, 0, 1);
3402 Magazine this_mag = Magazine.Cast(this);
3403 int max_rounds = this_mag.GetAmmoMax();
3404 int result = value * max_rounds;//can the rounded if higher precision is required
3405 this_mag.SetAmmoCount(result);
3406 }*/
3407 //----------------------------------------------------------------
3408 override int GetQuantityMax()
3409 {
3410 int slot = -1;
3411 if (GetInventory())
3412 {
3414 GetInventory().GetCurrentInventoryLocation(il);
3415 slot = il.GetSlot();
3416 }
3417
3418 return GetTargetQuantityMax(slot);
3419 }
3420
3421 override int GetTargetQuantityMax(int attSlotID = -1)
3422 {
3423 float quantity_max = 0;
3424
3425 if (IsSplitable()) //only stackable/splitable items can check for stack size
3426 {
3427 if (attSlotID != -1)
3428 quantity_max = InventorySlots.GetStackMaxForSlotId(attSlotID);
3429
3430 if (quantity_max <= 0)
3431 quantity_max = m_VarStackMax;
3432 }
3433
3434 if (quantity_max <= 0)
3435 quantity_max = m_VarQuantityMax;
3436
3437 return quantity_max;
3438 }
3439 //----------------------------------------------------------------
3440 override int GetQuantityMin()
3441 {
3442 return m_VarQuantityMin;
3443 }
3444 //----------------------------------------------------------------
3446 {
3447 return m_VarQuantityInit;
3448 }
3449
3450 //----------------------------------------------------------------
3451 override bool HasQuantity()
3452 {
3453 return !(GetQuantityMax() - GetQuantityMin() == 0);
3454 }
3455
3456 override float GetQuantity()
3457 {
3458 return m_VarQuantity;
3459 }
3460
3462 {
3463 return GetQuantity() >= GetQuantityMax();
3464 }
3465
3466 //Calculates weight of single item without attachments and cargo
3468 {
3469 //this needs to be first stored inside local variables, when returned directly during inside return call, the result is completely different due to enforce script bug
3470 float weightEx = GetWeightEx();//overall weight of the item
3471 float special = GetInventoryAndCargoWeight();//cargo and attachment weight
3472 return weightEx - special;
3473 }
3474
3475 // Obsolete, use GetSingleInventoryItemWeightEx() instead
3480
3481 override protected float GetWeightSpecialized(bool forceRecalc = false)
3482 {
3483 if (IsSplitable()) //quantity determines size of the stack
3484 {
3485 #ifdef DEVELOPER
3486 if (WeightDebug.m_VerbosityFlags & WeightDebugType.RECALC_FORCED)
3487 {
3488 WeightDebugData data1 = WeightDebug.GetWeightDebug(this);
3489 data1.SetCalcDetails("TIB1: " + GetConfigWeightModifiedDebugText() +" * " + GetQuantity()+"(quantity)");
3490 }
3491 #endif
3492
3493 return GetQuantity() * GetConfigWeightModified();
3494 }
3495 else if (HasEnergyManager())// items with energy manager
3496 {
3497 #ifdef DEVELOPER
3498 if (WeightDebug.m_VerbosityFlags & WeightDebugType.RECALC_FORCED)
3499 {
3500 WeightDebugData data2 = WeightDebug.GetWeightDebug(this);
3501 data2.SetCalcDetails("TIB2: "+super.GetWeightSpecialized(forceRecalc)+"(contents weight) + " + GetConfigWeightModifiedDebugText() +" + " + GetCompEM().GetEnergy()+"(energy) * " + ConfigGetFloat("weightPerQuantityUnit") +"(weightPerQuantityUnit)");
3502 }
3503 #endif
3504 return super.GetWeightSpecialized(forceRecalc) + (GetCompEM().GetEnergy() * ConfigGetFloat("weightPerQuantityUnit")) + GetConfigWeightModified();
3505 }
3506 else//everything else
3507 {
3508 #ifdef DEVELOPER
3509 if (WeightDebug.m_VerbosityFlags & WeightDebugType.RECALC_FORCED)
3510 {
3511 WeightDebugData data3 = WeightDebug.GetWeightDebug(this);
3512 data3.SetCalcDetails("TIB3: "+super.GetWeightSpecialized(forceRecalc)+"(contents weight) + " + GetConfigWeightModifiedDebugText() +" + " + GetQuantity()+"(quantity) * " + ConfigGetFloat("weightPerQuantityUnit") +"(weightPerQuantityUnit))");
3513 }
3514 #endif
3515 return super.GetWeightSpecialized(forceRecalc) + (GetQuantity() * ConfigGetFloat("weightPerQuantityUnit")) + GetConfigWeightModified();
3516 }
3517 }
3518
3521 {
3522 int item_count = 0;
3523 ItemBase item;
3524
3525 if (GetInventory().GetCargo() != NULL)
3526 {
3527 item_count = GetInventory().GetCargo().GetItemCount();
3528 }
3529
3530 for (int i = 0; i < GetInventory().AttachmentCount(); i++)
3531 {
3532 Class.CastTo(item,GetInventory().GetAttachmentFromIndex(i));
3533 if (item)
3534 item_count += item.GetNumberOfItems();
3535 }
3536 return item_count;
3537 }
3538
3540 float GetUnitWeight(bool include_wetness = true)
3541 {
3542 float weight = 0;
3543 float wetness = 1;
3544 if (include_wetness)
3545 wetness += GetWet();
3546 if (IsSplitable()) //quantity determines size of the stack
3547 {
3548 weight = wetness * m_ConfigWeight;
3549 }
3550 else if (IsLiquidContainer()) //is a liquid container, default liquid weight is set to 1. May revisit later?
3551 {
3552 weight = 1;
3553 }
3554 return weight;
3555 }
3556
3557 //-----------------------------------------------------------------
3558
3559 override void ClearInventory()
3560 {
3561 if ((GetGame().IsServer() || !GetGame().IsMultiplayer()) && GetInventory())
3562 {
3563 GameInventory inv = GetInventory();
3564 array<EntityAI> items = new array<EntityAI>;
3565 inv.EnumerateInventory(InventoryTraversalType.INORDER, items);
3566 for (int i = 0; i < items.Count(); i++)
3567 {
3568 ItemBase item = ItemBase.Cast(items.Get(i));
3569 if (item)
3570 {
3571 GetGame().ObjectDelete(item);
3572 }
3573 }
3574 }
3575 }
3576
3577 //------------------------- Energy
3578
3579 //----------------------------------------------------------------
3581 {
3582 float energy = 0;
3583 if (HasEnergyManager())
3584 {
3585 energy = GetCompEM().GetEnergy();
3586 }
3587 return energy;
3588 }
3589
3590
3591 override void OnEnergyConsumed()
3592 {
3593 super.OnEnergyConsumed();
3594
3596 }
3597
3598 override void OnEnergyAdded()
3599 {
3600 super.OnEnergyAdded();
3601
3603 }
3604
3605 // Converts energy (from Energy Manager) to quantity, if enabled.
3607 {
3608 if (GetGame().IsServer() && HasEnergyManager() && GetCompEM().HasConversionOfEnergyToQuantity())
3609 {
3610 if (HasQuantity())
3611 {
3612 float energy_0to1 = GetCompEM().GetEnergy0To1();
3613 SetQuantityNormalized(energy_0to1);
3614 }
3615 }
3616 }
3617
3618 //----------------------------------------------------------------
3620 {
3621 return ConfigGetFloat("heatIsolation");
3622 }
3623
3625 {
3626 return m_HeatIsolation;
3627 }
3628
3629 float GetDryingIncrement(string pIncrementName)
3630 {
3631 string paramPath = string.Format("CfgVehicles %1 EnvironmentWetnessIncrements Drying %2", GetType(), pIncrementName);
3632 if (GetGame().ConfigIsExisting(paramPath))
3633 return GetGame().ConfigGetFloat(paramPath);
3634
3635 return 0.0;
3636 }
3637
3638 float GetSoakingIncrement(string pIncrementName)
3639 {
3640 string paramPath = string.Format("CfgVehicles %1 EnvironmentWetnessIncrements Soaking %2", GetType(), pIncrementName);
3641 if (GetGame().ConfigIsExisting(paramPath))
3642 return GetGame().ConfigGetFloat(paramPath);
3643
3644 return 0.0;
3645 }
3646 //----------------------------------------------------------------
3647 override void SetWet(float value, bool allow_client = false)
3648 {
3649 if (!IsServerCheck(allow_client))
3650 return;
3651
3652 float min = GetWetMin();
3653 float max = GetWetMax();
3654
3655 float previousValue = m_VarWet;
3656
3657 m_VarWet = Math.Clamp(value, min, max);
3658
3659 if (previousValue != m_VarWet)
3660 {
3661 SetVariableMask(VARIABLE_WET);
3662 OnWetChanged(m_VarWet, previousValue);
3663 }
3664 }
3665 //----------------------------------------------------------------
3666 override void AddWet(float value)
3667 {
3668 SetWet(GetWet() + value);
3669 }
3670 //----------------------------------------------------------------
3671 override void SetWetMax()
3672 {
3674 }
3675 //----------------------------------------------------------------
3676 override float GetWet()
3677 {
3678 return m_VarWet;
3679 }
3680 //----------------------------------------------------------------
3681 override float GetWetMax()
3682 {
3683 return m_VarWetMax;
3684 }
3685 //----------------------------------------------------------------
3686 override float GetWetMin()
3687 {
3688 return m_VarWetMin;
3689 }
3690 //----------------------------------------------------------------
3691 override float GetWetInit()
3692 {
3693 return m_VarWetInit;
3694 }
3695 //----------------------------------------------------------------
3696 override void OnWetChanged(float newVal, float oldVal)
3697 {
3698 EWetnessLevel newLevel = GetWetLevelInternal(newVal);
3699 EWetnessLevel oldLevel = GetWetLevelInternal(oldVal);
3700 if (newLevel != oldLevel)
3701 {
3702 OnWetLevelChanged(newLevel,oldLevel);
3703 }
3704 }
3705
3706 override void OnWetLevelChanged(EWetnessLevel newLevel, EWetnessLevel oldLevel)
3707 {
3708 SetWeightDirty();
3709 }
3710
3712 {
3713 return GetWetLevelInternal(m_VarWet);
3714 }
3715
3716 //----------------------------------------------------------------
3717
3718 override void SetStoreLoad(bool value)
3719 {
3720 m_IsStoreLoad = value;
3721 }
3722
3723 override bool IsStoreLoad()
3724 {
3725 return m_IsStoreLoad;
3726 }
3727
3728 override void SetStoreLoadedQuantity(float value)
3729 {
3730 m_StoreLoadedQuantity = value;
3731 }
3732
3733 override float GetStoreLoadedQuantity()
3734 {
3735 return m_StoreLoadedQuantity;
3736 }
3737
3738 //----------------------------------------------------------------
3739
3741 {
3742 if (ConfigIsExisting("itemModelLength"))
3743 {
3744 return ConfigGetFloat("itemModelLength");
3745 }
3746 return 0;
3747 }
3748
3750 {
3751 if (ConfigIsExisting("itemAttachOffset"))
3752 {
3753 return ConfigGetFloat("itemAttachOffset");
3754 }
3755 return 0;
3756 }
3757
3758 override void SetCleanness(int value, bool allow_client = false)
3759 {
3760 if (!IsServerCheck(allow_client))
3761 return;
3762
3763 int previousValue = m_Cleanness;
3764
3766
3767 if (previousValue != m_Cleanness)
3768 SetVariableMask(VARIABLE_CLEANNESS);
3769 }
3770
3771 override int GetCleanness()
3772 {
3773 return m_Cleanness;
3774 }
3775
3777 {
3778 return true;
3779 }
3780
3781 //----------------------------------------------------------------
3782 // ATTACHMENT LOCKING
3783 // Getters relevant to generic ActionLockAttachment
3785 {
3786 return m_LockType;
3787 }
3788
3790 {
3791 return m_LockSoundSet;
3792 }
3793
3794 //----------------------------------------------------------------
3795 //------------------------- Color
3796 // sets items color variable given color components
3797 override void SetColor(int r, int g, int b, int a)
3798 {
3803 SetVariableMask(VARIABLE_COLOR);
3804 }
3806 override void GetColor(out int r,out int g,out int b,out int a)
3807 {
3812 }
3813
3815 {
3816 return IsVariableSet(VARIABLE_COLOR);
3817 }
3818
3821 {
3822 int r,g,b,a;
3823 GetColor(r,g,b,a);
3824 r = r/255;
3825 g = g/255;
3826 b = b/255;
3827 a = a/255;
3828 return MiscGameplayFunctions.GetColorString(r, g, b, a);
3829 }
3830 //----------------------------------------------------------------
3831 //------------------------- LiquidType
3832
3833 override void SetLiquidType(int value, bool allow_client = false)
3834 {
3835 if (!IsServerCheck(allow_client))
3836 return;
3837
3838 int old = m_VarLiquidType;
3839 m_VarLiquidType = value;
3840 OnLiquidTypeChanged(old,value);
3841 SetVariableMask(VARIABLE_LIQUIDTYPE);
3842 }
3843
3845 {
3846 return ConfigGetInt("varLiquidTypeInit");
3847 }
3848
3849 override int GetLiquidType()
3850 {
3851 return m_VarLiquidType;
3852 }
3853
3854 protected void OnLiquidTypeChanged(int oldType, int newType)
3855 {
3856 if (newType == LIQUID_NONE && GetIsFrozen())
3857 SetFrozen(false);
3858 }
3859
3862 {
3863 player.SetEnableQuickBarEntityShortcut(this,!GetHierarchyParent() || GetHierarchyParent().GetInventory().AreChildrenAccessible());
3864 }
3865
3866 // -------------------------------------------------------------------------
3868 void OnInventoryEnter(Man player)
3869 {
3870 PlayerBase nplayer;
3871 if (PlayerBase.CastTo(nplayer, player))
3872 {
3873 m_CanPlayImpactSound = true;
3874 //nplayer.OnItemInventoryEnter(this);
3875 nplayer.SetEnableQuickBarEntityShortcut(this,!GetHierarchyParent() || GetHierarchyParent().GetInventory().AreChildrenAccessible());
3876 }
3877 }
3878
3879 // -------------------------------------------------------------------------
3881 void OnInventoryExit(Man player)
3882 {
3883 PlayerBase nplayer;
3884 if (PlayerBase.CastTo(nplayer,player))
3885 {
3886 //nplayer.OnItemInventoryExit(this);
3887 nplayer.SetEnableQuickBarEntityShortcut(this,false);
3888
3889 }
3890
3891 //if (!GetGame().IsDedicatedServer())
3892 player.GetHumanInventory().ClearUserReservedLocationForContainer(this);
3893
3894
3895 if (HasEnergyManager())
3896 {
3897 GetCompEM().UpdatePlugState(); // Unplug the el. device if it's necesarry.
3898 }
3899 }
3900
3901 // ADVANCED PLACEMENT EVENTS
3902 override void OnPlacementStarted(Man player)
3903 {
3904 super.OnPlacementStarted(player);
3905
3906 SetTakeable(false);
3907 }
3908
3909 override void OnPlacementComplete(Man player, vector position = "0 0 0", vector orientation = "0 0 0")
3910 {
3911 if (m_AdminLog)
3912 {
3913 m_AdminLog.OnPlacementComplete(player, this);
3914 }
3915
3916 super.OnPlacementComplete(player, position, orientation);
3917 }
3918
3919 //-----------------------------
3920 // AGENT SYSTEM
3921 //-----------------------------
3922 //--------------------------------------------------------------------------
3923 bool ContainsAgent(int agent_id)
3924 {
3925 if (agent_id & m_AttachedAgents)
3926 {
3927 return true;
3928 }
3929 else
3930 {
3931 return false;
3932 }
3933 }
3934
3935 //--------------------------------------------------------------------------
3936 override void RemoveAgent(int agent_id)
3937 {
3938 if (ContainsAgent(agent_id))
3939 {
3940 m_AttachedAgents = ~agent_id & m_AttachedAgents;
3941 }
3942 }
3943
3944 //--------------------------------------------------------------------------
3945 override void RemoveAllAgents()
3946 {
3947 m_AttachedAgents = 0;
3948 }
3949 //--------------------------------------------------------------------------
3950 override void RemoveAllAgentsExcept(int agent_to_keep)
3951 {
3952 m_AttachedAgents = m_AttachedAgents & agent_to_keep;
3953 }
3954 // -------------------------------------------------------------------------
3955 override void InsertAgent(int agent, float count = 1)
3956 {
3957 if (count < 1)
3958 return;
3959 //Debug.Log("Inserting Agent on item: " + agent.ToString() +" count: " + count.ToString());
3960 m_AttachedAgents = (agent | m_AttachedAgents);
3961 }
3962
3964 void TransferAgents(int agents)
3965 {
3966 m_AttachedAgents = (m_AttachedAgents | agents);
3967 }
3968
3969 // -------------------------------------------------------------------------
3970 override int GetAgents()
3971 {
3972 return m_AttachedAgents;
3973 }
3974 //----------------------------------------------------------------------
3975
3976 /*int GetContaminationType()
3977 {
3978 int contamination_type;
3979
3980 const int CONTAMINATED_MASK = eAgents.CHOLERA | eAgents.INFLUENZA | eAgents.SALMONELLA | eAgents.BRAIN;
3981 const int POISONED_MASK = eAgents.FOOD_POISON | eAgents.CHEMICAL_POISON;
3982 const int NERVE_GAS_MASK = eAgents.CHEMICAL_POISON;
3983 const int DIRTY_MASK = eAgents.WOUND_AGENT;
3984
3985 Edible_Base edible = Edible_Base.Cast(this);
3986 int agents = GetAgents();
3987 if (edible)
3988 {
3989 NutritionalProfile profile = Edible_Base.GetNutritionalProfile(edible);
3990 if (profile)
3991 {
3992 agents = agents | profile.GetAgents();//merge item's agents with nutritional agents
3993 }
3994 }
3995 if (agents & CONTAMINATED_MASK)
3996 {
3997 contamination_type = contamination_type | EContaminationTypes.ITEM_BADGE_CONTAMINATED;
3998 }
3999 if (agents & POISONED_MASK)
4000 {
4001 contamination_type = contamination_type | EContaminationTypes.ITEM_BADGE_POISONED;
4002 }
4003 if (agents & NERVE_GAS_MASK)
4004 {
4005 contamination_type = contamination_type | EContaminationTypes.ITEM_BADGE_NERVE_GAS;
4006 }
4007 if (agents & DIRTY_MASK)
4008 {
4009 contamination_type = contamination_type | EContaminationTypes.ITEM_BADGE_DIRTY;
4010 }
4011
4012 return agents;
4013 }*/
4014
4015 // -------------------------------------------------------------------------
4016 bool LoadAgents(ParamsReadContext ctx, int version)
4017 {
4018 if (!ctx.Read(m_AttachedAgents))
4019 return false;
4020 return true;
4021 }
4022 // -------------------------------------------------------------------------
4024 {
4025
4026 ctx.Write(m_AttachedAgents);
4027 }
4028 // -------------------------------------------------------------------------
4029
4031 override void CheckForRoofLimited(float timeTresholdMS = 3000)
4032 {
4033 super.CheckForRoofLimited(timeTresholdMS);
4034
4035 float time = GetGame().GetTime();
4036 if ((time - m_PreviousRoofTestTime) >= timeTresholdMS)
4037 {
4038 m_PreviousRoofTestTime = time;
4039 SetRoofAbove(MiscGameplayFunctions.IsUnderRoof(this));
4040 }
4041 }
4042
4043 // returns item's protection level against enviromental hazard, for masks with filters, returns the filters protection for valid filter, otherwise 0
4044 float GetProtectionLevel(int type, bool consider_filter = false, int system = 0)
4045 {
4046 if (IsDamageDestroyed() || (HasQuantity() && GetQuantity() <= 0))
4047 {
4048 return 0;
4049 }
4050
4051 if (GetInventory().GetAttachmentSlotsCount() != 0)//is it an item with attachable filter ?
4052 {
4053 ItemBase filter = ItemBase.Cast(FindAttachmentBySlotName("GasMaskFilter"));
4054 if (filter)
4055 return filter.GetProtectionLevel(type, false, system);//it's a valid filter, return the protection
4056 else
4057 return 0;//otherwise return 0 when no filter attached
4058 }
4059
4060 string subclassPath, entryName;
4061
4062 switch (type)
4063 {
4064 case DEF_BIOLOGICAL:
4065 entryName = "biological";
4066 break;
4067 case DEF_CHEMICAL:
4068 entryName = "chemical";
4069 break;
4070 default:
4071 entryName = "biological";
4072 break;
4073 }
4074
4075 subclassPath = "CfgVehicles " + this.GetType() + " Protection ";
4076
4077 return GetGame().ConfigGetFloat(subclassPath + entryName);
4078 }
4079
4080
4081
4083 override void EEOnCECreate()
4084 {
4085 if (!IsMagazine())
4086 SetCEBasedQuantity();
4087
4089 }
4090
4091
4092 //-------------------------
4093 // OPEN/CLOSE USER ACTIONS
4094 //-------------------------
4096 void Open();
4097 void Close();
4098 bool IsOpen()
4099 {
4100 return true;
4101 }
4102
4103 override bool CanDisplayCargo()
4104 {
4105 return IsOpen();
4106 }
4107
4108
4109 // ------------------------------------------------------------
4110 // CONDITIONS
4111 // ------------------------------------------------------------
4112 override bool CanPutInCargo(EntityAI parent)
4113 {
4114 if (parent)
4115 {
4116 if (parent.IsInherited(DayZInfected))
4117 return true;
4118
4119 if (!parent.IsRuined())
4120 return true;
4121 }
4122
4123 return true;
4124 }
4125
4126 override bool CanPutAsAttachment(EntityAI parent)
4127 {
4128 if (!super.CanPutAsAttachment(parent))
4129 {
4130 return false;
4131 }
4132
4133 if (!IsRuined() && !parent.IsRuined())
4134 {
4135 return true;
4136 }
4137
4138 return false;
4139 }
4140
4142 {
4143 //removed 15.06. coz of loading from storage -> after load items in cargo was lost -> waiting for proper solution
4144 //if (GetHealthLevel() == GameConstants.STATE_RUINED)
4145 // return false;
4146
4147 return super.CanReceiveItemIntoCargo(item);
4148 }
4149
4150 override bool CanReceiveAttachment(EntityAI attachment, int slotId)
4151 {
4152 //removed 15.06. coz of loading from storage -> after load items in cargo was lost -> waiting for proper solution
4153 //if (GetHealthLevel() == GameConstants.STATE_RUINED)
4154 // return false;
4155
4156 GameInventory attachmentInv = attachment.GetInventory();
4157 if (attachmentInv && attachmentInv.GetCargo() && attachmentInv.GetCargo().GetItemCount() > 0)
4158 {
4159 if (GetHierarchyParent() && !GetHierarchyParent().IsInherited(PlayerBase))
4160 return false;
4161 }
4162
4164 attachment.GetInventory().GetCurrentInventoryLocation(loc);
4165 if (loc && loc.IsValid() && !GetInventory().AreChildrenAccessible())
4166 return false;
4167
4168 return super.CanReceiveAttachment(attachment, slotId);
4169 }
4170
4171 override bool CanReleaseAttachment(EntityAI attachment)
4172 {
4173 if (!super.CanReleaseAttachment(attachment))
4174 return false;
4175
4176 return GetInventory().AreChildrenAccessible();
4177 }
4178
4179 /*override bool CanLoadAttachment(EntityAI attachment)
4180 {
4181 //removed 15.06. coz of loading from storage -> after load items in cargo was lost -> waiting for proper solution
4182 //if (GetHealthLevel() == GameConstants.STATE_RUINED)
4183 // return false;
4184
4185 GameInventory attachmentInv = attachment.GetInventory();
4186 if (attachmentInv && attachmentInv.GetCargo() && attachmentInv.GetCargo().GetItemCount() > 0)
4187 {
4188 bool boo = (GetHierarchyParent() && !GetHierarchyParent().IsInherited(PlayerBase));
4189 ErrorEx("CanLoadAttachment | this: " + this + " | attachment: " + attachment + " | boo: " + boo,ErrorExSeverity.INFO);
4190
4191 if (GetHierarchyParent() && !GetHierarchyParent().IsInherited(PlayerBase))
4192 return false;
4193 }
4194
4195 return super.CanLoadAttachment(attachment);
4196 }*/
4197
4198 // Plays muzzle flash particle effects
4199 static void PlayFireParticles(ItemBase weapon, int muzzle_index, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
4200 {
4201 int id = muzzle_owner.GetMuzzleID();
4202 array<ref WeaponParticlesOnFire> WPOF_array = m_OnFireEffect.Get(id);
4203
4204 if (WPOF_array)
4205 {
4206 for (int i = 0; i < WPOF_array.Count(); i++)
4207 {
4208 WeaponParticlesOnFire WPOF = WPOF_array.Get(i);
4209
4210 if (WPOF)
4211 {
4212 WPOF.OnActivate(weapon, muzzle_index, ammoType, muzzle_owner, suppressor, config_to_search);
4213 }
4214 }
4215 }
4216 }
4217
4218 // Plays bullet eject particle effects (usually just smoke, the bullet itself is a 3D model and is not part of this function)
4219 static void PlayBulletCasingEjectParticles(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
4220 {
4221 int id = muzzle_owner.GetMuzzleID();
4222 array<ref WeaponParticlesOnBulletCasingEject> WPOBE_array = m_OnBulletCasingEjectEffect.Get(id);
4223
4224 if (WPOBE_array)
4225 {
4226 for (int i = 0; i < WPOBE_array.Count(); i++)
4227 {
4228 WeaponParticlesOnBulletCasingEject WPOBE = WPOBE_array.Get(i);
4229
4230 if (WPOBE)
4231 {
4232 WPOBE.OnActivate(weapon, 0, ammoType, muzzle_owner, suppressor, config_to_search);
4233 }
4234 }
4235 }
4236 }
4237
4238 // Plays all weapon overheating particles
4239 static void PlayOverheatingParticles(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
4240 {
4241 int id = muzzle_owner.GetMuzzleID();
4242 array<ref WeaponParticlesOnOverheating> WPOOH_array = weapon.m_OnOverheatingEffect.Get(id);
4243
4244 if (WPOOH_array)
4245 {
4246 for (int i = 0; i < WPOOH_array.Count(); i++)
4247 {
4248 WeaponParticlesOnOverheating WPOOH = WPOOH_array.Get(i);
4249
4250 if (WPOOH)
4251 {
4252 WPOOH.OnActivate(weapon, 0, ammoType, muzzle_owner, suppressor, config_to_search);
4253 }
4254 }
4255 }
4256 }
4257
4258 // Updates all weapon overheating particles
4259 static void UpdateOverheatingParticles(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
4260 {
4261 int id = muzzle_owner.GetMuzzleID();
4262 array<ref WeaponParticlesOnOverheating> WPOOH_array = weapon.m_OnOverheatingEffect.Get(id);
4263
4264 if (WPOOH_array)
4265 {
4266 for (int i = 0; i < WPOOH_array.Count(); i++)
4267 {
4268 WeaponParticlesOnOverheating WPOOH = WPOOH_array.Get(i);
4269
4270 if (WPOOH)
4271 {
4272 WPOOH.OnUpdate(weapon, ammoType, muzzle_owner, suppressor, config_to_search);
4273 }
4274 }
4275 }
4276 }
4277
4278 // Stops overheating particles
4279 static void StopOverheatingParticles(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
4280 {
4281 int id = muzzle_owner.GetMuzzleID();
4282 array<ref WeaponParticlesOnOverheating> WPOOH_array = weapon.m_OnOverheatingEffect.Get(id);
4283
4284 if (WPOOH_array)
4285 {
4286 for (int i = 0; i < WPOOH_array.Count(); i++)
4287 {
4288 WeaponParticlesOnOverheating WPOOH = WPOOH_array.Get(i);
4289
4290 if (WPOOH)
4291 {
4292 WPOOH.OnDeactivate(weapon, ammoType, muzzle_owner, suppressor, config_to_search);
4293 }
4294 }
4295 }
4296 }
4297
4298 //----------------------------------------------------------------
4299 //Item Behaviour - unified approach
4300 override bool IsHeavyBehaviour()
4301 {
4302 if (m_ItemBehaviour == 0)
4303 {
4304 return true;
4305 }
4306
4307 return false;
4308 }
4309
4310 override bool IsOneHandedBehaviour()
4311 {
4312 if (m_ItemBehaviour == 1)
4313 {
4314 return true;
4315 }
4316
4317 return false;
4318 }
4319
4320 override bool IsTwoHandedBehaviour()
4321 {
4322 if (m_ItemBehaviour == 2)
4323 {
4324 return true;
4325 }
4326
4327 return false;
4328 }
4329
4331 {
4332 return false;
4333 }
4334
4337 {
4338 return UATimeSpent.DEFAULT_DEPLOY;
4339 }
4340
4341
4342 //----------------------------------------------------------------
4343 // Item Targeting (User Actions)
4344 override void SetTakeable(bool pState)
4345 {
4346 m_IsTakeable = pState;
4347 SetSynchDirty();
4348 }
4349
4350 override bool IsTakeable()
4351 {
4352 return m_IsTakeable;
4353 }
4354
4355 // For cases where we want to show object widget which cant be taken to hands
4357 {
4358 return false;
4359 }
4360
4363 {
4364 string att_type = "None";
4365
4366 if (ConfigIsExisting("soundAttType"))
4367 {
4368 att_type = ConfigGetString("soundAttType");
4369 }
4370
4371 m_SoundAttType = att_type;
4372 }
4373
4374 override string GetAttachmentSoundType()
4375 {
4376 return m_SoundAttType;
4377 }
4378
4379 //----------------------------------------------------------------
4380 //SOUNDS - ItemSoundHandler
4381 //----------------------------------------------------------------
4382
4383 string GetPlaceSoundset(); // played when deploy starts
4384 string GetLoopDeploySoundset(); // played when deploy starts and stopped when it finishes
4385 string GetDeploySoundset(); // played when deploy sucessfully finishes
4386 string GetLoopFoldSoundset(); // played when fold starts and stopped when it finishes
4387 string GetFoldSoundset(); // played when fold sucessfully finishes
4388
4390 {
4391 if (!m_ItemSoundHandler)
4392 m_ItemSoundHandler = new ItemSoundHandler(this);
4393
4394 return m_ItemSoundHandler;
4395 }
4396
4397 // override to initialize sounds
4398 protected void InitItemSounds()
4399 {
4400 if (GetPlaceSoundset() == string.Empty && GetDeploySoundset() == string.Empty && GetLoopDeploySoundset() == string.Empty)
4401 return;
4402
4404
4405 if (GetPlaceSoundset() != string.Empty)
4406 handler.AddSound(SoundConstants.ITEM_PLACE, GetPlaceSoundset());
4407
4408 if (GetDeploySoundset() != string.Empty)
4409 handler.AddSound(SoundConstants.ITEM_DEPLOY, GetDeploySoundset());
4410
4411 SoundParameters params = new SoundParameters();
4412 params.m_Loop = true;
4413 if (GetLoopDeploySoundset() != string.Empty)
4414 handler.AddSound(SoundConstants.ITEM_DEPLOY_LOOP, GetLoopDeploySoundset(), params);
4415 }
4416
4417 // Start sound using ItemSoundHandler
4419 {
4420 if (!GetGame().IsServer())
4421 return;
4422
4423 m_SoundSyncPlay = id;
4424 SetSynchDirty();
4425
4426 GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Remove(ClearStartItemSoundServer); // in case one is queued already
4427 GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(ClearStartItemSoundServer, 100);
4428 }
4429
4430 // Stop sound using ItemSoundHandler
4432 {
4433 if (!GetGame().IsServer())
4434 return;
4435
4436 m_SoundSyncStop = id;
4437 SetSynchDirty();
4438
4439 GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Remove(ClearStopItemSoundServer); // in case one is queued already
4440 GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).CallLater(ClearStopItemSoundServer, 100);
4441 }
4442
4444 {
4445 m_SoundSyncPlay = 0;
4446 }
4447
4449 {
4450 m_SoundSyncStop = 0;
4451 }
4452
4454 void PlayAttachSound(string slot_type)
4455 {
4456 if (!GetGame().IsDedicatedServer())
4457 {
4458 if (ConfigIsExisting("attachSoundSet"))
4459 {
4460 string cfg_path = "";
4461 string soundset = "";
4462 string type_name = GetType();
4463
4464 TStringArray cfg_soundset_array = new TStringArray;
4465 TStringArray cfg_slot_array = new TStringArray;
4466 ConfigGetTextArray("attachSoundSet",cfg_soundset_array);
4467 ConfigGetTextArray("attachSoundSlot",cfg_slot_array);
4468
4469 if (cfg_soundset_array.Count() > 0 && cfg_soundset_array.Count() == cfg_slot_array.Count())
4470 {
4471 for (int i = 0; i < cfg_soundset_array.Count(); i++)
4472 {
4473 if (cfg_slot_array[i] == slot_type)
4474 {
4475 soundset = cfg_soundset_array[i];
4476 break;
4477 }
4478 }
4479 }
4480
4481 if (soundset != "")
4482 {
4483 EffectSound sound = SEffectManager.PlaySound(soundset, GetPosition());
4484 sound.SetAutodestroy(true);
4485 }
4486 }
4487 }
4488 }
4489
4490 void PlayDetachSound(string slot_type)
4491 {
4492 //TODO - evaluate if needed and devise universal config structure if so
4493 }
4494
4495 void OnApply(PlayerBase player);
4496
4498 {
4499 return 1.0;
4500 };
4501 //returns applicable selection
4506
4508 {
4510 }
4511
4513
4515 {
4516 SetDynamicPhysicsLifeTime(0.01);
4517 m_ItemBeingDroppedPhys = false;
4518 }
4519
4521 {
4522 array<string> zone_names = new array<string>;
4523 GetDamageZones(zone_names);
4524 for (int i = 0; i < zone_names.Count(); i++)
4525 {
4526 SetHealthMax(zone_names.Get(i),"Health");
4527 }
4528 SetHealthMax("","Health");
4529 }
4530
4533 {
4534 float global_health = GetHealth01("","Health");
4535 array<string> zones = new array<string>;
4536 GetDamageZones(zones);
4537 //set damage of all zones to match global health level
4538 for (int i = 0; i < zones.Count(); i++)
4539 {
4540 SetHealth01(zones.Get(i),"Health",global_health);
4541 }
4542 }
4543
4545 bool IsCoverFaceForShave(string slot_name)
4546 {
4547 return IsExclusionFlagPresent(PlayerBase.GetFaceCoverageShaveValues());
4548 }
4549
4550 void ProcessItemWetness(float delta, bool hasParent, bool hasRootAsPlayer, ItemBase refParentIB)
4551 {
4552 if (!hasRootAsPlayer)
4553 {
4554 if (refParentIB)
4555 {
4556 // parent is wet
4557 if ((refParentIB.GetWet() >= GameConstants.STATE_SOAKING_WET) && (m_VarWet < m_VarWetMax))
4558 AddWet(delta * GameConstants.WETNESS_RATE_WETTING_INSIDE);
4559 // parent has liquid inside
4560 else if ((refParentIB.GetLiquidType() != 0) && (refParentIB.GetQuantity() > 0) && (m_VarWet < m_VarWetMax))
4561 AddWet(delta * GameConstants.WETNESS_RATE_WETTING_LIQUID);
4562 // drying
4563 else if (m_VarWet > m_VarWetMin)
4564 AddWet(-1 * delta * GetDryingIncrement("ground") * 2);
4565 }
4566 else
4567 {
4568 // drying on ground or inside non-itembase (car, ...)
4569 if (m_VarWet > m_VarWetMin)
4570 AddWet(-1 * delta * GetDryingIncrement("ground"));
4571 }
4572 }
4573 }
4574
4575 void ProcessItemTemperature(float delta, bool hasParent, bool hasRootAsPlayer, ItemBase refParentIB)
4576 {
4578 {
4579 float target = g_Game.GetMission().GetWorldData().GetBaseEnvTemperatureAtObject(this);
4580 if (GetTemperature() != target || !IsFreezeThawProgressFinished())
4581 {
4582 float heatPermCoef = 1.0;
4583 EntityAI ent = this;
4584 while (ent)
4585 {
4586 heatPermCoef *= ent.GetHeatPermeabilityCoef();
4587 ent = ent.GetHierarchyParent();
4588 }
4589
4590 SetTemperatureEx(new TemperatureDataInterpolated(target,ETemperatureAccessTypes.ACCESS_WORLD,delta,GameConstants.TEMP_COEF_WORLD,heatPermCoef));
4591 }
4592 }
4593 }
4594
4595 void HierarchyCheck(out bool hasParent, out bool hasRootAsPlayer, out ItemBase refParentIB)
4596 {
4597 // hierarchy check for an item to decide whether it has some parent and it is in some player inventory
4598 EntityAI parent = GetHierarchyParent();
4599 if (!parent)
4600 {
4601 hasParent = false;
4602 hasRootAsPlayer = false;
4603 }
4604 else
4605 {
4606 hasParent = true;
4607 hasRootAsPlayer = (GetHierarchyRootPlayer() != null);
4608 refParentIB = ItemBase.Cast(parent);
4609 }
4610 }
4611
4612 protected void ProcessDecay(float delta, bool hasRootAsPlayer)
4613 {
4614 // this is stub, implemented on Edible_Base
4615 }
4616
4618 {
4619 // return true used on selected food clases so they can decay
4620 return false;
4621 }
4622
4623 protected bool CanProcessDecay()
4624 {
4625 // this is stub, implemented on Edible_Base class
4626 // used to determine whether it is still necessary for the food to decay
4627 return false;
4628 }
4629
4630 protected bool CanHaveWetness()
4631 {
4632 // return true used on selected items that have a wetness effect
4633 return false;
4634 }
4635
4638 {
4639 return !GetIsFrozen() && IsOpen();
4640 }
4641
4642 override void ProcessVariables()
4643 {
4644 bool hasParent = false, hasRootAsPlayer = false;
4645 ItemBase refParentIB;
4646
4647 bool wwtu = g_Game.IsWorldWetTempUpdateEnabled();
4648 bool foodDecay = g_Game.IsFoodDecayEnabled();
4649
4650 if (wwtu || foodDecay)
4651 {
4652 bool processWetness = wwtu && CanHaveWetness();
4653 bool processTemperature = wwtu && CanHaveTemperature();
4654 bool processDecay = foodDecay && CanDecay() && CanProcessDecay();
4655
4656 if (processWetness || processTemperature || processDecay)
4657 {
4658 HierarchyCheck(hasParent, hasRootAsPlayer, refParentIB);
4659
4660 if (processWetness)
4661 ProcessItemWetness(m_ElapsedSinceLastUpdate, hasParent, hasRootAsPlayer, refParentIB);
4662
4663 if (processTemperature)
4664 ProcessItemTemperature(m_ElapsedSinceLastUpdate, hasParent, hasRootAsPlayer, refParentIB);
4665
4666 if (processDecay)
4667 ProcessDecay(m_ElapsedSinceLastUpdate, hasRootAsPlayer);
4668 }
4669 }
4670 }
4671
4674 {
4675 return m_TemperaturePerQuantityWeight * GameConstants.ITEM_TEMPERATURE_QUANTITY_WEIGHT_MULTIPLIER;
4676 }
4677
4679 {
4680 if (IsLiquidContainer() && GetLiquidType() != LIQUID_NONE)
4681 return Liquid.GetFreezeThreshold(GetLiquidType());
4682
4683 return super.GetTemperatureFreezeThreshold();
4684 }
4685
4687 {
4688 if (IsLiquidContainer() && GetLiquidType() != LIQUID_NONE)
4689 return Liquid.GetThawThreshold(GetLiquidType());
4690
4691 return super.GetTemperatureThawThreshold();
4692 }
4693
4695 {
4696 if (IsLiquidContainer() && GetLiquidType() != LIQUID_NONE)
4697 return Liquid.GetBoilThreshold(GetLiquidType());
4698
4699 return super.GetItemOverheatThreshold();
4700 }
4701
4703 {
4704 if (HasQuantity())
4705 return Math.Lerp(GameConstants.TEMPERATURE_TIME_FREEZE_MIN,Math.Max(GameConstants.TEMPERATURE_TIME_FREEZE_MIN,super.GetTemperatureFreezeTime()),GetQuantityNormalized());
4706
4707 return super.GetTemperatureFreezeTime();
4708 }
4709
4710 override float GetTemperatureThawTime()
4711 {
4712 if (HasQuantity())
4713 return Math.Lerp(GameConstants.TEMPERATURE_TIME_THAW_MIN,Math.Max(GameConstants.TEMPERATURE_TIME_FREEZE_MIN,super.GetTemperatureThawTime()),GetQuantityNormalized());
4714
4715 return super.GetTemperatureThawTime();
4716 }
4717
4719 void AffectLiquidContainerOnFill(int liquid_type, float amount);
4721 void AffectLiquidContainerOnTransfer(int liquidType, float amount, float sourceLiquidTemperature);
4722
4724 {
4725 return (item.IsKindOf("Cauldron") || item.IsKindOf("Pot") || item.IsKindOf("FryingPan") || item.IsKindOf("SmallProtectorCase") || (item.IsKindOf("PortableGasStove") && item.FindAttachmentBySlotName("CookingEquipment")));
4726 }
4727
4729 {
4730 MiscGameplayFunctions.TransferItemProperties(oldItem, this);
4731 }
4732
4735 {
4736 m_LightSourceItem = lightsource;
4737 }
4738
4740 {
4741 m_LightSourceItem = null;
4742 }
4743
4745 {
4746 return m_LightSourceItem;
4747 }
4748
4751 {
4752 return null;
4753 }
4754
4757 {
4758 return false;
4759 }
4760
4761 bool PairWithDevice(notnull ItemBase otherDevice)
4762 {
4763 if (GetGame().IsServer())
4764 {
4765 ItemBase explosive = otherDevice;
4767 if (!trg)
4768 {
4769 trg = RemoteDetonatorTrigger.Cast(otherDevice);
4770 explosive = this;
4771 }
4772
4773 explosive.PairRemote(trg);
4774 trg.SetControlledDevice(explosive);
4775
4777 trg.SetPersistentPairID(persistentID);
4778 explosive.SetPersistentPairID(persistentID);
4779
4780 return true;
4781 }
4782 return false;
4783 }
4784
4787 {
4788 float ret = 1.0;
4789 if (HasQuantity())
4790 ret *= GetQuantityNormalized();
4791 ret *= GetHealth01();
4792
4793 return ret;
4794 }
4795
4796 #ifdef DEVELOPER
4797 override void SetDebugItem()
4798 {
4799 super.SetDebugItem();
4800 _itemBase = this;
4801 }
4802
4803 override string GetDebugText()
4804 {
4805 string text = super.GetDebugText();
4806
4807 text += string.Format("Heat isolation(raw): %1\n", GetHeatIsolation());
4808 text += string.Format("Heat isolation(modified): %1\n", MiscGameplayFunctions.GetCurrentItemHeatIsolation(this));
4809
4810 return text;
4811 }
4812 #endif
4813
4815 {
4816 return true;
4817 }
4818
4820 //DEPRECATED BELOW
4822 // Backwards compatibility
4823 void ProcessItemWetnessAndTemperature(float delta, bool hasParent, bool hasRootAsPlayer, ItemBase refParentIB)
4824 {
4825 ProcessItemWetness(delta, hasParent, hasRootAsPlayer, refParentIB);
4826 ProcessItemTemperature(delta, hasParent, hasRootAsPlayer, refParentIB);
4827 }
4828
4829 // replaced by ItemSoundHandler
4837
4846 bool UsesGlobalDeploy(){return false;}
4847 bool CanPlayDeployLoopSound(){return false;}
4851 void SetIsPlaceSound(bool is_place_sound);
4852 void SetIsDeploySound(bool is_deploy_sound);
4853}
4854
4855EntityAI SpawnItemOnLocation(string object_name, notnull InventoryLocation loc, bool full_quantity)
4856{
4857 EntityAI entity = SpawnEntity(object_name, loc, ECE_IN_INVENTORY, RF_DEFAULT);
4858 if (entity)
4859 {
4860 bool is_item = entity.IsInherited(ItemBase);
4861 if (is_item && full_quantity)
4862 {
4863 ItemBase item = ItemBase.Cast(entity);
4864 item.SetQuantity(item.GetQuantityInit());
4865 }
4866 }
4867 else
4868 {
4869 ErrorEx("Cannot spawn entity: " + object_name,ErrorExSeverity.INFO);
4870 return NULL;
4872 return entity;
4875void SetupSpawnedItem(ItemBase item, float health, float quantity)
4877 if (item)
4879 if (health > 0)
4880 item.SetHealth("", "", health);
4882 if (item.CanHaveTemperature())
4883 {
4884 item.SetTemperatureDirect(GameConstants.ITEM_TEMPERATURE_NEUTRAL_ZONE_MIDDLE);
4885 if (item.CanFreeze())
4886 item.SetFrozen(false);
4888
4889 if (item.HasEnergyManager())
4891 if (quantity >= 0)
4893 item.GetCompEM().SetEnergy0To1(quantity);
4895 else
4897 item.GetCompEM().SetEnergy(Math.AbsFloat(quantity));
4900 else if (item.IsMagazine())
4902 Magazine mag = Magazine.Cast(item);
4903 if (quantity >= 0)
4905 mag.ServerSetAmmoCount(mag.GetAmmoMax() * quantity);
4907 else
4909 mag.ServerSetAmmoCount(Math.AbsFloat(quantity));
4913 else
4914 {
4915 if (quantity >= 0)
4917 item.SetQuantityNormalized(quantity, false);
4919 else
4921 item.SetQuantity(Math.AbsFloat(quantity));
4922 }
4923
4924 }
4926}
4928#ifdef DEVELOPER
4929ItemBase _itemBase;//watched item goes here(LCTRL+RMB->Watch)
4930#endif
Param4< int, int, string, int > TSelectableActionInfoWithColor
Definition entityai.c:97
Param3 TSelectableActionInfo
EWetnessLevel
Definition entityai.c:2
bool m_Initialized
InventoryMode
NOTE: PREDICTIVE is not to be used at all in multiplayer.
Definition inventory.c:22
const int INPUT_UDT_ITEM_MANIPULATION
Definition _constants.c:8
eBleedingSourceType GetType()
map< typename, ref array< ActionBase_Basic > > TInputActionMap
void AddAction(typename actionName)
void RemoveAction(typename actionName)
TInputActionMap m_InputActionMap
bool m_ActionsInitialize
override void GetActions(typename action_input_type, out array< ActionBase_Basic > actions)
void InitializeActions()
int GetLiquidType()
const int ECE_PLACE_ON_SURFACE
const int ECE_IN_INVENTORY
const int RF_DEFAULT
PlayerSpawnPresetDiscreteItemSetSlotData name
one set for cargo
PlayerSpawnPreset slotName
void OnItemLocationChanged(ItemBase item)
Definition actionbase.c:998
proto int GetTime()
returns mission time in milliseconds
AnalyticsManagerClient GetAnalyticsClient()
Definition game.c:1568
represents base for cargo storage for entities
Definition cargo.c:7
Super root of all classes in Enforce script.
Definition enscript.c:11
void SetEnergy0To1(float energy01)
Energy manager: Sets stored energy for this device between 0 and MAX based on relative input value be...
float GetEnergyMaxPristine()
Energy manager: Returns the maximum amount of energy this device can store. It's damage is NOT taken ...
Definition debug.c:2
Wrapper class for managing sound through SEffectManager.
Definition effectsound.c:5
override void SetAutodestroy(bool auto_destroy)
Sets whether Effect automatically cleans up when it stops.
bool IsSoundPlaying()
Get whether EffectSound is currently playing.
script counterpart to engine's class Inventory
Definition inventory.c:79
proto native bool EnumerateInventory(InventoryTraversalType tt, out array< EntityAI > items)
enumerate inventory using traversal type and filling items array
proto native CargoBase GetCargo()
cargo
const int c_InventoryReservationTimeoutShortMS
Definition inventory.c:713
static proto native EntityAI LocationCreateEntity(notnull InventoryLocation inv_loc, string type, int iSetupFlags, int iRotation)
creates new item directly at location
string m_LockSoundSet
Definition itembase.c:128
override string GetAttachmentSoundType()
Definition itembase.c:4374
void PlayDeploySound()
bool IsActionTargetVisible()
Definition itembase.c:4356
bool IsOpen()
Definition itembase.c:4098
override float GetQuantity()
Definition itembase.c:3456
void SetZoneDamageCEInit()
Sets zone damages to match randomized global health set by CE (CE spawn only)
Definition itembase.c:4532
override void OnEnergyConsumed()
Definition itembase.c:3591
string GetLoopDeploySoundset()
override void ClearInventory()
Definition itembase.c:3559
void SoundSynchRemoteReset()
void PlayDeployLoopSoundEx()
override void EEOnCECreate()
Called when entity is being created as new by CE/ Debug.
Definition itembase.c:4083
void OnActivatedByItem(notnull ItemBase item)
Called when this item is activated by other.
EffectSound m_SoundDeployFinish
Definition itembase.c:4830
ItemBase GetLightSourceItem()
Definition itembase.c:4744
override bool IsOneHandedBehaviour()
Definition itembase.c:4310
int m_ColorComponentB
Definition itembase.c:80
override void SetColor(int r, int g, int b, int a)
Definition itembase.c:3797
override int GetCleanness()
Definition itembase.c:3771
int m_SoundSyncPlay
Definition itembase.c:132
bool m_IsPlaceSound
Definition itembase.c:4834
float ComputeQuantityUsedEx(ItemBase other_item, bool use_stack_max=true)
Definition itembase.c:2258
override void GetDebugActions(out TSelectableActionInfoArrayEx outputList)
Definition itembase.c:2337
override float GetTemperatureThawThreshold()
Definition itembase.c:4686
FoodStage GetFoodStage()
overridden on Edible_Base; so we don't have to parse configs all the time
Definition itembase.c:2633
void SplitItemToInventoryLocation(notnull InventoryLocation dst)
Definition itembase.c:1958
void PlayPlaceSound()
override bool HasQuantity()
Definition itembase.c:3451
override float GetTemperatureThawTime()
Definition itembase.c:4710
void StopItemDynamicPhysics()
Definition itembase.c:4514
void UpdateQuickbarShortcutVisibility(PlayerBase player)
To be called on moving item within character's inventory; 'player' should never be null.
Definition itembase.c:3861
override bool IsStoreLoad()
Definition itembase.c:3723
override bool CanReceiveAttachment(EntityAI attachment, int slotId)
Definition itembase.c:4150
override float GetWetMin()
Definition itembase.c:3686
override bool CanDisplayCargo()
Definition itembase.c:4103
override void SetWetMax()
Definition itembase.c:3671
float GetHeatIsolation()
Definition itembase.c:3624
bool CanPlayDeployLoopSound()
Definition itembase.c:4847
bool CanExplodeInFire()
Definition itembase.c:2607
array< string > GetHeadHidingSelection()
Definition itembase.c:4502
float GetHeatIsolationInit()
Definition itembase.c:3619
void OnAttachmentQuantityChanged(ItemBase item)
Called on server side when some attachment's quantity is changed. Call super.OnAttachmentQuantityChan...
Definition itembase.c:2049
int GetQuantityInit()
Definition itembase.c:3445
override void ProcessVariables()
Definition itembase.c:4642
bool HidesSelectionBySlot()
Definition itembase.c:4507
override void OnPlacementComplete(Man player, vector position="0 0 0", vector orientation="0 0 0")
Definition itembase.c:3909
bool m_IsSoundSynchRemote
Definition itembase.c:4836
void RemoveAudioVisualsOnClient()
void MessageToOwnerAction(string text)
Send message to owner player in yellow color.
Definition itembase.c:2720
void SetIsPlaceSound(bool is_place_sound)
void ClearStopItemSoundServer()
Definition itembase.c:4448
override void RemoveAllAgents()
Definition itembase.c:3945
bool AddQuantity(float value, bool destroy_config=true, bool destroy_forced=false)
add item quantity[related to varQuantity... config entry], destroy_config = true > if the quantity re...
Definition itembase.c:3362
override void OnStoreSave(ParamsWriteContext ctx)
Definition itembase.c:3193
string GetLoopFoldSoundset()
override bool CanPutInCargo(EntityAI parent)
Definition itembase.c:4112
override void SetQuantityToMinimum()
Definition itembase.c:3373
WrittenNoteData GetWrittenNoteData()
Definition itembase.c:4512
float GetTemperaturePerQuantityWeight()
Used in heat comfort calculations only!
Definition itembase.c:4673
ref TIntArray m_SingleUseActions
Definition itembase.c:87
override void SetTakeable(bool pState)
Definition itembase.c:4344
array< int > GetValidFinishers()
returns an array of possible finishers
Definition itembase.c:4750
bool IsDeployable()
Definition itembase.c:4330
bool CanBeCookedOnStick()
Definition itembase.c:2643
string GetColorString()
Returns item's PROCEDURAL color as formated string, i.e. "#(argb,8,8,3)color(0.15,...
Definition itembase.c:3820
float GetBaitEffectivity()
generic effectivity as a bait for animal catching
Definition itembase.c:4786
bool CanBeConsumed(ConsumeConditionData data=null)
Items cannot be consumed if frozen by default. Override for exceptions.
Definition itembase.c:4637
override void SetWet(float value, bool allow_client=false)
Definition itembase.c:3647
bool CanDecay()
Definition itembase.c:4617
float GetSoakingIncrement(string pIncrementName)
Definition itembase.c:3638
override void CheckForRoofLimited(float timeTresholdMS=3000)
Roof check for entity, limited by time (anti-spam solution)
Definition itembase.c:4031
void SplitIntoStackMaxHandsClient(PlayerBase player)
Definition itembase.c:1906
bool m_IsDeploySound
Definition itembase.c:4835
void ProcessItemTemperature(float delta, bool hasParent, bool hasRootAsPlayer, ItemBase refParentIB)
Definition itembase.c:4575
void CombineItems(ItemBase other_item, bool use_stack_max=true)
Definition itembase.c:2282
void OnInventoryExit(Man player)
Event called on item when it is removed from the player(Man) inventory, passes the old owner as a par...
Definition itembase.c:3881
override float GetTemperatureFreezeTime()
Definition itembase.c:4702
void TransferAgents(int agents)
transfer agents from another item
Definition itembase.c:3964
float GetUnitWeight(bool include_wetness=true)
Obsolete, use GetWeightEx instead.
Definition itembase.c:3540
override bool CanPutAsAttachment(EntityAI parent)
Definition itembase.c:4126
ref EffectSound m_LockingSound
Definition itembase.c:127
void HierarchyCheck(out bool hasParent, out bool hasRootAsPlayer, out ItemBase refParentIB)
Definition itembase.c:4595
int GetNumberOfItems()
Returns the number of items in cargo, otherwise returns 0(non-cargo objects). Recursive.
Definition itembase.c:3520
ItemSoundHandler GetItemSoundHandler()
Definition itembase.c:4389
bool Repair(PlayerBase player, ItemBase item_repair_kit, float specialty_weight)
Definition itembase.c:2660
void SaveAgents(ParamsWriteContext ctx)
Definition itembase.c:4023
void AffectLiquidContainerOnFill(int liquid_type, float amount)
from enviro source
int m_ColorComponentA
Definition itembase.c:81
bool CanProcessDecay()
Definition itembase.c:4623
override void SetQuantityNormalized(float value, bool destroy_config=true, bool destroy_forced=false)
Sets quantity in normalized 0..1 form between the item's Min a Max values as defined by item's config...
Definition itembase.c:3380
void SplitIntoStackMaxHands(PlayerBase player)
Definition itembase.c:1930
override void OnEnergyAdded()
Definition itembase.c:3598
void StopDeployLoopSoundEx()
bool IsDeploySound()
Definition itembase.c:4850
void SplitIntoStackMaxCargo(EntityAI destination_entity, int idx, int row, int col)
Definition itembase.c:1879
override bool KindOf(string tag)
Definition itembase.c:2772
override void InsertAgent(int agent, float count=1)
Definition itembase.c:3955
override EWetnessLevel GetWetLevel()
Definition itembase.c:3711
override int GetQuantityMax()
Definition itembase.c:3408
void SplitIntoStackMaxToInventoryLocationClient(notnull InventoryLocation dst)
Definition itembase.c:1794
void ConvertEnergyToQuantity()
Definition itembase.c:3606
void PlayAttachSound(string slot_type)
Plays sound on item attach. Be advised, the config structure may slightly change in 1....
Definition itembase.c:4454
override float GetWetInit()
Definition itembase.c:3691
void SetQuantityMax()
Definition itembase.c:3367
override void SetStoreLoadedQuantity(float value)
Definition itembase.c:3728
override void SplitIntoStackMaxEx(EntityAI destination_entity, int slot_id)
Definition itembase.c:1717
void SetIsDeploySound(bool is_deploy_sound)
override void RemoveAllAgentsExcept(int agent_to_keep)
Definition itembase.c:3950
override void OnPlacementStarted(Man player)
Definition itembase.c:3902
int m_ColorComponentG
Definition itembase.c:79
override int GetLiquidType()
Definition itembase.c:3849
void PerformDamageSystemReinit()
Definition itembase.c:4520
EffectSound m_SoundPlace
Definition itembase.c:4831
override bool SetQuantity(float value, bool destroy_config=true, bool destroy_forced=false, bool allow_client=false, bool clamp_to_stack_max=true)
Set item quantity[related to varQuantity... config entry], destroy_config = true > if the quantity re...
Definition itembase.c:3308
static void PlayBulletCasingEjectParticles(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
Definition itembase.c:4219
void RefreshAudioVisualsOnClient(CookingMethodType cooking_method, bool is_done, bool is_empty, bool is_burned)
cooking-related effect methods
int m_SoundSyncStop
Definition itembase.c:133
bool GetActionWidgetOverride(out typename name)
If we need a different (handheld)item action widget displayed, the logic goes in here.
Definition itembase.c:4756
override int GetTargetQuantityMax(int attSlotID=-1)
Definition itembase.c:3421
void StartItemSoundServer(int id)
Definition itembase.c:4418
override bool OnAction(int action_id, Man player, ParamsReadContext ctx)
Definition itembase.c:2397
bool IsCargoException4x3(EntityAI item)
Definition itembase.c:4723
override void EEOnAfterLoad()
Definition itembase.c:3237
override void SetLiquidType(int value, bool allow_client=false)
Definition itembase.c:3833
override void OnVariablesSynchronized()
Definition itembase.c:3257
void OnInventoryEnter(Man player)
Event called on item when it is placed in the player(Man) inventory, passes the owner as a parameter.
Definition itembase.c:3868
override float GetSingleInventoryItemWeightEx()
Definition itembase.c:3467
override bool IsIgnoredByConstruction()
Definition itembase.c:2619
void OnActivatedByTripWire()
bool ContainsAgent(int agent_id)
Definition itembase.c:3923
bool CanBeMovedOverride()
Definition itembase.c:2682
void Open()
Implementations only.
bool m_HideSelectionsBySlot
Definition itembase.c:116
bool m_IsResultOfSplit string m_SoundAttType
distinguish if item has been created as new or it came from splitting (server only flag)
Definition itembase.c:76
override bool IsItemBase()
Definition itembase.c:2766
bool IsResultOfSplit()
Definition itembase.c:2243
override bool IsTwoHandedBehaviour()
Definition itembase.c:4320
override float GetItemOverheatThreshold()
Definition itembase.c:4694
static void StopOverheatingParticles(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
Definition itembase.c:4279
float GetWeightSpecialized(bool forceRecalc=false)
Definition itembase.c:3481
float GetDeployTime()
how long it takes to deploy this item in seconds
Definition itembase.c:4336
override float GetStoreLoadedQuantity()
Definition itembase.c:3733
float GetBandagingEffectivity()
Definition itembase.c:4497
bool CanBeUsedForSuicide()
Definition itembase.c:4814
override void OnWetLevelChanged(EWetnessLevel newLevel, EWetnessLevel oldLevel)
Definition itembase.c:3706
override bool IsTakeable()
Definition itembase.c:4350
override void SetCleanness(int value, bool allow_client=false)
Definition itembase.c:3758
override void SetStoreLoad(bool value)
Definition itembase.c:3718
int GetLockType()
Definition itembase.c:3784
int ComputeQuantityUsed(ItemBase other_item, bool use_stack_max=true)
Definition itembase.c:2253
override bool ReadVarsFromCTX(ParamsReadContext ctx, int version=-1)
Definition itembase.c:3001
bool IsCombineAll(ItemBase other_item, bool use_stack_max=false)
Definition itembase.c:2238
override void DeSerializeNumericalVars(array< float > floats)
Definition itembase.c:2906
bool HasFoodStage()
Definition itembase.c:2626
EffectSound m_SoundDeploy
Definition itembase.c:4833
bool ShouldSplitQuantity(float quantity)
Definition itembase.c:1588
override float GetTemperatureFreezeThreshold()
Definition itembase.c:4678
void ProcessItemWetness(float delta, bool hasParent, bool hasRootAsPlayer, ItemBase refParentIB)
Definition itembase.c:4550
override void AfterStoreLoad()
Definition itembase.c:3221
string GetLockSoundSet()
Definition itembase.c:3789
bool CanBeCooked()
Definition itembase.c:2638
int GetItemSize()
Definition itembase.c:2667
float GetSingleInventoryItemWeight()
Definition itembase.c:3476
bool CanEat()
Definition itembase.c:2613
void OnSyncVariables(ParamsReadContext ctx)
DEPRECATED (most likely)
Definition itembase.c:2856
override int GetQuantityMin()
Definition itembase.c:3440
void StopItemSoundServer(int id)
Definition itembase.c:4431
string GetPlaceSoundset()
void InitItemSounds()
Definition itembase.c:4398
void SplitIntoStackMaxToInventoryLocation(notnull InventoryLocation dst)
Definition itembase.c:1840
override void WriteVarsToCTX(ParamsWriteContext ctx)
Definition itembase.c:2965
void PlayDeployFinishSound()
bool IsFullQuantity()
Definition itembase.c:3461
float GetDryingIncrement(string pIncrementName)
Definition itembase.c:3629
override void RemoveAgent(int agent_id)
Definition itembase.c:3936
static void PlayFireParticles(ItemBase weapon, int muzzle_index, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
Definition itembase.c:4199
float GetProtectionLevel(int type, bool consider_filter=false, int system=0)
Definition itembase.c:4044
void SplitIntoStackMaxCargoClient(EntityAI destination_entity, int idx, int row, int col)
Definition itembase.c:1815
void ProcessItemWetnessAndTemperature(float delta, bool hasParent, bool hasRootAsPlayer, ItemBase refParentIB)
Definition itembase.c:4823
override void SerializeNumericalVars(array< float > floats_out)
Definition itembase.c:2870
override void SplitIntoStackMaxClient(EntityAI destination_entity, int slot_id)
Definition itembase.c:1608
void SetCanBeMovedOverride(bool setting)
Definition itembase.c:2689
static void PlayOverheatingParticles(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
Definition itembase.c:4239
int m_ColorComponentR
Definition itembase.c:78
override bool CanReceiveItemIntoCargo(EntityAI item)
Definition itembase.c:4141
void GetRecipesActions(Man player, out TSelectableActionInfoArray outputList)
Definition itembase.c:2316
int GetLiquidTypeInit()
Definition itembase.c:3844
bool IsSoundSynchRemote()
Definition itembase.c:4848
void CopyScriptPropertiesFrom(EntityAI oldItem)
Definition itembase.c:4728
PluginAdminLog m_AdminLog
Definition itembase.c:119
bool IsColorSet()
Definition itembase.c:3814
override void OnRPC(PlayerIdentity sender, int rpc_type, ParamsReadContext ctx)
Definition itembase.c:2792
override int GetAgents()
Definition itembase.c:3970
float GetItemModelLength()
Definition itembase.c:3740
override void EEHealthLevelChanged(int oldLevel, int newLevel, string zone)
Definition itembase.c:2060
void ClearStartItemSoundServer()
Definition itembase.c:4443
void OnCombine(ItemBase other_item)
Definition itembase.c:2308
void SetResultOfSplit(bool value)
Definition itembase.c:2248
void SplitItem(PlayerBase player)
Definition itembase.c:1991
bool UsesGlobalDeploy()
Definition itembase.c:4846
override bool OnStoreLoad(ParamsReadContext ctx, int version)
Definition itembase.c:3092
static void UpdateOverheatingParticles(ItemBase weapon, string ammoType, ItemBase muzzle_owner, ItemBase suppressor, string config_to_search)
Definition itembase.c:4259
override float GetWet()
Definition itembase.c:3676
override void OnWetChanged(float newVal, float oldVal)
Definition itembase.c:3696
bool CanBeDisinfected()
Definition itembase.c:3250
void OnLiquidTypeChanged(int oldType, int newType)
Definition itembase.c:3854
override bool CanBeCombined(EntityAI other_item, bool reservation_check=true, bool stack_max_limit=false)
Definition itembase.c:2176
void MessageToOwnerStatus(string text)
Send message to owner player in grey color.
Definition itembase.c:2702
bool IsCoverFaceForShave(string slot_name)
DEPRECATED in use, but returns correct values nontheless. Check performed elsewhere.
Definition itembase.c:4545
int NameToID(string name)
Definition itembase.c:2843
void MessageToOwnerFriendly(string text)
Send message to owner player in green color.
Definition itembase.c:2738
bool m_CanBeDigged
Definition itembase.c:73
ref array< int > m_CompatibleLocks
Definition itembase.c:125
ref TIntArray m_ContinuousActions
Definition itembase.c:88
float GetItemAttachOffset()
Definition itembase.c:3749
bool CanRepair(ItemBase item_repair_kit)
Definition itembase.c:2653
float GetEnergy()
Definition itembase.c:3580
void AffectLiquidContainerOnTransfer(int liquidType, float amount, float sourceLiquidTemperature)
from other liquid container source
bool PairWithDevice(notnull ItemBase otherDevice)
Definition itembase.c:4761
string GetFoldSoundset()
bool IsPlaceSound()
Definition itembase.c:4849
void SoundSynchRemote()
override void GetColor(out int r, out int g, out int b, out int a)
gets item's color variable as components
Definition itembase.c:3806
override void CombineItemsEx(EntityAI entity2, bool use_stack_max=true)
Definition itembase.c:2277
void SetInventoryLocationToVicinityOrCurrent(EntityAI root, inout InventoryLocation dst)
Definition itembase.c:2162
EffectSound m_DeployLoopSoundEx
Definition itembase.c:4832
void SplitIntoStackMax(EntityAI destination_entity, int slot_id, PlayerBase player)
Definition itembase.c:1631
bool AllowFoodConsumption()
Definition itembase.c:3776
string GetDeploySoundset()
void PlayDetachSound(string slot_type)
Definition itembase.c:4490
void OnAttachmentQuantityChangedEx(ItemBase item, float delta)
Called on server side when some attachment's quantity is changed. Call super.OnAttachmentQuantityChan...
Definition itembase.c:2055
ItemBase SplitIntoStackMaxToInventoryLocationEx(notnull InventoryLocation dst)
Definition itembase.c:1845
override void OnRightClick()
Definition itembase.c:2098
string IDToName(int id)
Definition itembase.c:2849
void ProcessDecay(float delta, bool hasRootAsPlayer)
Definition itembase.c:4612
override bool CanReleaseAttachment(EntityAI attachment)
Definition itembase.c:4171
void AddLightSourceItem(ItemBase lightsource)
Adds a light source child.
Definition itembase.c:4734
ItemBase m_LightSourceItem
Definition itembase.c:85
void OnQuantityChanged(float delta)
Called on server side when this item's quantity is changed. Call super.OnQuantityChanged(); first whe...
Definition itembase.c:2025
override float GetQuantityNormalized()
Gets quantity in normalized 0..1 form between the item's Min a Max values as defined by item's config...
Definition itembase.c:3389
bool LoadAgents(ParamsReadContext ctx, int version)
Definition itembase.c:4016
void PreLoadSoundAttachmentType()
Attachment Sound Type getting from config file.
Definition itembase.c:4362
ref TIntArray m_InteractActions
Definition itembase.c:89
bool CanHaveWetness()
Definition itembase.c:4630
override bool IsHeavyBehaviour()
Definition itembase.c:4300
void MessageToOwnerImportant(string text)
Send message to owner player in red color.
Definition itembase.c:2756
float GetQuantityNormalizedScripted()
Definition itembase.c:3394
ref Timer m_PhysDropTimer
Definition itembase.c:122
void RemoveLightSourceItem()
Definition itembase.c:4739
string GetDeployFinishSoundset()
override float GetWetMax()
Definition itembase.c:3681
ref TStringArray m_HeadHidingSelections
Definition itembase.c:115
void OnApply(PlayerBase player)
override void AddWet(float value)
Definition itembase.c:3666
InventoryLocation.
provides access to slot configuration
override void OnInventoryEnter(Man player)
Definition barbedwire.c:203
override void EEDelete(EntityAI parent)
override bool CanBeRepairedByCrafting()
Definition tentbase.c:86
override void OnItemLocationChanged(EntityAI old_owner, EntityAI new_owner)
Definition barbedwire.c:357
override bool IsElectricAppliance()
override bool IsItemTent()
Definition tentbase.c:81
override WrittenNoteData GetWrittenNoteData()
Definition paper.c:30
override int GetDamageSystemVersionChange()
override void OnCreatePhysics()
override string GetDeploySoundset()
Definition barbedwire.c:392
override bool IsSelfAdjustingTemperature()
override bool IsPlayerInside(PlayerBase player, string selection)
override void RefreshPhysics()
override bool CanObstruct()
override string GetLoopDeploySoundset()
Definition barbedwire.c:397
override void OnInventoryExit(Man player)
override void InitItemSounds()
override bool IsFacingPlayer(PlayerBase player, string selection)
override void OnEndPlacement()
Definition kitbase.c:65
Definition enmath.c:7
Base Param Class with no parameters. Used as general purpose parameter overloaded with Param1 to Para...
Definition param.c:12
Legacy way of using particles in the game.
Definition particle.c:7
void Stop()
Legacy function for backwards compatibility with 1.14 and below.
Definition particle.c:266
The class that will be instanced (moddable)
Definition gameplay.c:389
void SetControlledDevice(EntityAI pDevice)
bool OnStoreLoad(ParamsReadContext ctx, int version)
Manager class for managing Effect (EffectParticle, EffectSound)
static EffectSound PlaySound(string sound_set, vector position, float play_fade_in=0, float stop_fade_out=0, bool loop=false)
Create and play an EffectSound.
static void DestroyEffect(Effect effect)
Unregisters, stops and frees the Effect.
Serialization general interface. Serializer API works with:
Definition serializer.c:56
script counterpart to engine's class Weapon
void OnRPC(PlayerIdentity sender, int rpc_type, ParamsReadContext ctx)
Result for an object found in CGame.IsBoxCollidingGeometryProxy.
CookingMethodType
Definition cooking.c:2
DamageType
exposed from C++ (do not change)
DayZGame g_Game
Definition dayzgame.c:3868
DayZGame GetDayZGame()
Definition dayzgame.c:3870
EActions
Definition eactions.c:2
PluginAdminLog m_AdminLog
const int MAX
Definition enconvert.c:27
float GetTemperature()
ERPCs
Definition erpcs.c:2
override bool IsExplosive()
override bool CanHaveTemperature()
InventoryTraversalType
tree traversal type, for more see http://en.wikipedia.org/wiki/Tree_traversal
Definition gameplay.c:6
proto native CGame GetGame()
class GP5GasMask extends MaskBase ItemBase
const int DEF_BIOLOGICAL
Definition constants.c:512
const int DEF_CHEMICAL
Definition constants.c:513
const int COMP_TYPE_ENERGY_MANAGER
Definition component.c:9
ErrorExSeverity
Definition endebug.c:62
void Error(string err)
Messagebox with error message.
Definition endebug.c:90
enum ShapeType ErrorEx
proto native void SetColor(int color)
array< string > TStringArray
Definition enscript.c:709
array< int > TIntArray
Definition enscript.c:711
EntityEvent
Entity events for event-mask, or throwing event from code.
Definition enentity.c:45
const int VARIABLE_LIQUIDTYPE
Definition constants.c:632
const int VARIABLE_CLEANNESS
Definition constants.c:635
const int VARIABLE_COLOR
Definition constants.c:634
const int VARIABLE_TEMPERATURE
Definition constants.c:630
const int VARIABLE_QUANTITY
Definition constants.c:628
const int VARIABLE_WET
Definition constants.c:631
const int LIQUID_NONE
Definition constants.c:529
const int MENU_INVENTORY
Definition constants.c:180
proto native bool dBodyIsDynamic(notnull IEntity ent)
const int SAT_CRAFTING
Definition constants.c:453
const int SAT_DEBUG_ACTION
Definition constants.c:454
class JsonUndergroundAreaTriggerData GetPosition
const int CALL_CATEGORY_GAMEPLAY
Definition tools.c:10
const int CALL_CATEGORY_SYSTEM
Definition tools.c:8
Empty
Definition hand_states.c:14
FindInventoryLocationType
flags for searching locations in inventory
InventoryLocationType
types of Inventory Location
class BoxCollidingParams component
ComponentInfo for BoxCollidingResult.
float m_VarWetMin
Definition itembase.c:4881
void SplitItem(PlayerBase player)
Definition itembase.c:6831
override void InsertAgent(int agent, float count=1)
Definition itembase.c:8795
override float GetQuantityNormalized()
Gets quantity in normalized 0..1 form between the item's Min a Max values as defined by item's config...
Definition itembase.c:8229
bool IsOpen()
Definition itembase.c:8938
void ClearStartItemSoundServer()
Definition itembase.c:9283
float m_VarWet
Definition itembase.c:4878
void ProcessItemTemperature(float delta, bool hasParent, bool hasRootAsPlayer, ItemBase refParentIB)
Definition itembase.c:9415
map< typename, ref ActionOverrideData > TActionAnimOverrideMap
Definition itembase.c:2
override void SetWet(float value, bool allow_client=false)
Definition itembase.c:8487
ref TIntArray m_SingleUseActions
Definition itembase.c:4927
ref TStringArray m_HeadHidingSelections
Definition itembase.c:4955
bool LoadAgents(ParamsReadContext ctx, int version)
Definition itembase.c:8856
bool m_IsSoundSynchRemote
Definition itembase.c:9676
ref array< int > m_CompatibleLocks
Definition itembase.c:4965
bool m_RecipesInitialized
Definition itembase.c:4863
void SplitIntoStackMax(EntityAI destination_entity, int slot_id, PlayerBase player)
Definition itembase.c:6471
ref TIntArray m_InteractActions
Definition itembase.c:4929
float m_VarQuantity
Definition itembase.c:4869
override float GetWetMax()
Definition itembase.c:8521
bool m_CanBeMovedOverride
Definition itembase.c:4906
bool CanDecay()
Definition itembase.c:9457
string GetPlaceSoundset()
bool AddQuantity(float value, bool destroy_config=true, bool destroy_forced=false)
add item quantity[related to varQuantity... config entry], destroy_config = true > if the quantity re...
Definition itembase.c:8202
void SetQuantityMax()
Definition itembase.c:8207
override float GetQuantity()
Definition itembase.c:8296
int m_ColorComponentR
Definition itembase.c:4918
override void OnWetChanged(float newVal, float oldVal)
Definition itembase.c:8536
float GetDryingIncrement(string pIncrementName)
Definition itembase.c:8469
int m_Cleanness
Definition itembase.c:4884
int m_ItemBehaviour
Definition itembase.c:4899
float m_HeatIsolation
Definition itembase.c:4894
float m_VarWetInit
Definition itembase.c:4880
bool m_CanPlayImpactSound
Definition itembase.c:4890
void PlayAttachSound(string slot_type)
Plays sound on item attach. Be advised, the config structure may slightly change in 1....
Definition itembase.c:9294
override bool IsStoreLoad()
Definition itembase.c:8563
int ComputeQuantityUsed(ItemBase other_item, bool use_stack_max=true)
Definition itembase.c:7093
bool m_HasQuantityBar
Definition itembase.c:4912
void SetResultOfSplit(bool value)
Definition itembase.c:7088
void SplitIntoStackMaxCargo(EntityAI destination_entity, int idx, int row, int col)
Definition itembase.c:6719
void OnAttachmentQuantityChanged(ItemBase item)
Called on server side when some attachment's quantity is changed. Call super.OnAttachmentQuantityChan...
Definition itembase.c:6889
override float GetStoreLoadedQuantity()
Definition itembase.c:8573
int m_LockType
Definition itembase.c:4966
const int ITEM_SOUNDS_MAX
Definition itembase.c:4971
bool m_CanBeDigged
Definition itembase.c:4913
float m_ItemAttachOffset
Definition itembase.c:4896
float GetItemModelLength()
Definition itembase.c:8580
bool m_ThrowItemOnDrop
Definition itembase.c:4904
override bool ReadVarsFromCTX(ParamsReadContext ctx, int version=-1)
Definition itembase.c:7841
float GetHeatIsolation()
Definition itembase.c:8464
void CombineItems(ItemBase other_item, bool use_stack_max=true)
Definition itembase.c:7122
bool CanHaveWetness()
Definition itembase.c:9470
int m_CleannessMin
Definition itembase.c:4886
float GetHeatIsolationInit()
Definition itembase.c:8459
override bool HasQuantity()
Definition itembase.c:8291
float m_VarWetPrev
Definition itembase.c:4879
int m_SoundSyncStop
Definition itembase.c:4973
ref TIntArray m_ContinuousActions
Definition itembase.c:4928
int m_VarLiquidType
Definition itembase.c:4898
int m_QuickBarBonus
Definition itembase.c:4900
void PreLoadSoundAttachmentType()
Attachment Sound Type getting from config file.
Definition itembase.c:9202
int m_ImpactSoundSurfaceHash
Definition itembase.c:4892
int m_SoundSyncPlay
Definition itembase.c:4972
void SetupSpawnedItem(ItemBase item, float health, float quantity)
Definition itembase.c:4875
bool m_IsTakeable
Definition itembase.c:4903
bool ShouldSplitQuantity(float quantity)
Definition itembase.c:6428
class ItemBase extends InventoryItem SpawnItemOnLocation(string object_name, notnull InventoryLocation loc, bool full_quantity)
Definition itembase.c:4855
ItemSoundHandler GetItemSoundHandler()
Definition itembase.c:9229
override int GetQuantityMin()
Definition itembase.c:8280
override void SetTakeable(bool pState)
Definition itembase.c:9184
void HierarchyCheck(out bool hasParent, out bool hasRootAsPlayer, out ItemBase refParentIB)
Definition itembase.c:9435
bool CanProcessDecay()
Definition itembase.c:9463
bool can_this_be_combined
Definition itembase.c:4908
int m_Count
Definition itembase.c:4874
void ConvertEnergyToQuantity()
Definition itembase.c:8446
override void RemoveAllAgents()
Definition itembase.c:8785
bool m_WantPlayImpactSound
Definition itembase.c:4889
int m_ColorComponentG
Definition itembase.c:4919
float m_StoreLoadedQuantity
Definition itembase.c:4876
int m_ColorComponentA
Definition itembase.c:4921
int m_VarQuantityInit
Definition itembase.c:4871
override void SetLiquidType(int value, bool allow_client=false)
Definition itembase.c:8673
void OnQuantityChanged(float delta)
Called on server side when this item's quantity is changed. Call super.OnQuantityChanged(); first whe...
Definition itembase.c:6865
override void SetQuantityNormalized(float value, bool destroy_config=true, bool destroy_forced=false)
Sets quantity in normalized 0..1 form between the item's Min a Max values as defined by item's config...
Definition itembase.c:8220
bool m_HideSelectionsBySlot
Definition itembase.c:4956
void SetInventoryLocationToVicinityOrCurrent(EntityAI root, inout InventoryLocation dst)
Definition itembase.c:7002
float GetEnergy()
Definition itembase.c:8420
void SetZoneDamageCEInit()
Sets zone damages to match randomized global health set by CE (CE spawn only)
Definition itembase.c:9372
bool m_IsDeploySound
Definition itembase.c:9675
override float GetSingleInventoryItemWeightEx()
Definition itembase.c:8307
void SaveAgents(ParamsWriteContext ctx)
Definition itembase.c:8863
override int GetTargetQuantityMax(int attSlotID=-1)
Definition itembase.c:8261
int m_CleannessInit
Definition itembase.c:4885
int m_VarQuantityMax
Definition itembase.c:4873
float GetItemAttachOffset()
Definition itembase.c:8589
void ProcessDecay(float delta, bool hasRootAsPlayer)
Definition itembase.c:9452
bool IsCombineAll(ItemBase other_item, bool use_stack_max=false)
Definition itembase.c:7078
bool ContainsAgent(int agent_id)
Definition itembase.c:8763
override void AddWet(float value)
Definition itembase.c:8506
bool IsFullQuantity()
Definition itembase.c:8301
void SplitIntoStackMaxHands(PlayerBase player)
Definition itembase.c:6770
int m_CleannessMax
Definition itembase.c:4887
float m_VarStackMax
Definition itembase.c:4875
override void SetStoreLoadedQuantity(float value)
Definition itembase.c:8568
bool m_IsResultOfSplit string m_SoundAttType
distinguish if item has been created as new or it came from splitting (server only flag)
Definition itembase.c:4916
void OnLiquidTypeChanged(int oldType, int newType)
Definition itembase.c:8694
int m_LiquidContainerMask
Definition itembase.c:4897
void ProcessItemWetness(float delta, bool hasParent, bool hasRootAsPlayer, ItemBase refParentIB)
Definition itembase.c:9390
override int GetCleanness()
Definition itembase.c:8611
int m_VarQuantityMin
Definition itembase.c:4872
void PerformDamageSystemReinit()
Definition itembase.c:9360
bool m_CanThisBeSplit
Definition itembase.c:4909
ItemBase SplitIntoStackMaxToInventoryLocationEx(notnull InventoryLocation dst)
Definition itembase.c:6685
float m_ItemModelLength
Definition itembase.c:4895
bool m_IsHologram
Definition itembase.c:4902
override int GetQuantityMax()
Definition itembase.c:8248
override void RemoveAgent(int agent_id)
Definition itembase.c:8776
bool m_ItemBeingDroppedPhys
Definition itembase.c:4905
override bool CanPutAsAttachment(EntityAI parent)
Definition itembase.c:8966
ItemBase Inventory_Base
Definition itembase.c:1
float ComputeQuantityUsedEx(ItemBase other_item, bool use_stack_max=true)
Definition itembase.c:7098
bool IsResultOfSplit()
Definition itembase.c:7083
bool m_FixDamageSystemInit
Definition itembase.c:4907
float m_ImpactSpeed
Definition itembase.c:4891
bool m_IsStoreLoad
Definition itembase.c:4910
int GetLiquidTypeInit()
Definition itembase.c:8684
ItemBase m_LightSourceItem
Definition itembase.c:4925
string m_LockSoundSet
Definition itembase.c:4968
float m_VarQuantityPrev
Definition itembase.c:4870
bool m_CanShowQuantity
Definition itembase.c:4911
int m_ColorComponentB
Definition itembase.c:4920
bool m_IsBeingPlaced
Definition itembase.c:4901
override void OnWetLevelChanged(EWetnessLevel newLevel, EWetnessLevel oldLevel)
Definition itembase.c:8546
void ClearStopItemSoundServer()
Definition itembase.c:9288
float m_VarWetMax
Definition itembase.c:4882
void SplitIntoStackMaxToInventoryLocation(notnull InventoryLocation dst)
Definition itembase.c:6680
override float GetWet()
Definition itembase.c:8516
override void SetCleanness(int value, bool allow_client=false)
Definition itembase.c:8598
bool m_IsPlaceSound
Definition itembase.c:9674
override float GetWetMin()
Definition itembase.c:8526
void ItemSoundHandler(ItemBase parent)
string Type
EffectSound m_LockingSound
string GetDebugText()
PlayerBase GetPlayer()
void PluginItemDiagnostic()
PluginBase GetPlugin(typename plugin_type)
@ LOWEST
EntityAI GetItem()
override RemotelyActivatedItemBehaviour GetRemotelyActivatedItemBehaviour()
int particle_id
override void Explode(int damageType, string ammoType="")