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