123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- enum SoundTypeTrap
- {
- ACTIVATING = 5,
- }
- class TrapBase extends ItemBase
- {
- #ifdef SERVER
- protected const int SPAWN_FLAGS = ECE_CREATEPHYSICS;
- #else
- protected const int SPAWN_FLAGS = ECE_LOCAL;
- #endif
-
- protected const int DAMAGE_TRIGGER_MINE = 75;
- protected const float UPDATE_TIMER_INTERVAL = 0.05;
- float m_InitWaitTime; //After this time after deployment, the trap is activated
- bool m_NeedActivation; //If activation of trap is needed
- float m_DefectRate; //Added damage after trap activation
- float m_DamagePlayers; //How much damage player gets when caught
- float m_DamageOthers; //How much damage player gets when caught
- bool m_AddActivationDefect; // Damage trap after activation
- bool m_AddDeactivationDefect; // Damage trap after deactivation
- protected bool m_IsActive; // True means that the trap is ready to detonate
- protected bool m_IsInProgress;
- protected bool m_Disarmed = false; //! DEPRECATED Used for explosive traps to prevent detonation after destroying through disarm action
- bool m_WasActivatedOrDeactivated;
- string m_AnimationPhaseGrounded;
- string m_AnimationPhaseSet;
- string m_AnimationPhaseTriggered;
- string m_InfoSetup;
- string m_InfoDeactivated;
- string m_InfoDamageManipulation;
- string m_InfoDamage;
- string m_InfoActivationTime;
- protected ref Timer m_Timer;
- protected ref Timer m_UpdateTimer;
- protected TrapTrigger m_TrapTrigger;
-
- protected ref array<int> m_ClothingDmg;
- void TrapBase()
- {
- m_IsInProgress = false;
- m_NeedActivation = true;
- m_InitWaitTime = 5; //After this time after deployment, the trap is activated
- m_DefectRate = 15; //Added damage after trap activation
- m_DamagePlayers = 25; //How much damage player gets when caught
- m_DamageOthers = 100; //How much damage others gets when caught
-
- m_AddActivationDefect = false;
- m_AddDeactivationDefect = false;
- m_WasActivatedOrDeactivated = false;
- m_AnimationPhaseGrounded = "";
- m_AnimationPhaseSet = "";
- m_AnimationPhaseTriggered = "";
-
- m_InfoSetup = "#STR_TrapBase0";
- m_InfoDeactivated = "#STR_TrapBase1";
- m_InfoDamageManipulation = "#STR_TrapBase2";
- m_InfoDamage = "#STR_TrapBase3";
- m_InfoActivationTime = "#STR_TrapBase4" + m_InitWaitTime.ToString() + "#STR_TrapBase5";
-
- m_UpdateTimer = new ref Timer(); //! timer calling OnUpdate in configured interval
-
- RegisterNetSyncVariableBool("m_IsActive");
- RegisterNetSyncVariableBool("m_IsInProgress");
- }
-
- void OnUpdate(EntityAI victim);
-
- TrapTrigger GetTrapTrigger()
- {
- return m_TrapTrigger;
- }
-
- //! this event is called all variables are synchronized on client
- override void OnVariablesSynchronized()
- {
- super.OnVariablesSynchronized();
-
- if (GetGame().IsMultiplayer())
- {
- if (m_IsActive && !m_IsInProgress)
- SetActive();
-
- if (m_IsInProgress && !m_IsActive)
- StartActivate(null);
- }
- }
-
- override void EEDelete(EntityAI parent)
- {
- super.EEDelete(parent);
- if (GetGame() && m_TrapTrigger)
- {
- GetGame().ObjectDelete(m_TrapTrigger);
- m_TrapTrigger = null;
- }
- }
- override void OnStoreSave(ParamsWriteContext ctx)
- {
- super.OnStoreSave(ctx);
-
- ctx.Write(m_IsActive);
- ctx.Write(m_IsInProgress);
- }
-
- //----------------------------------------------------------------
- override bool OnStoreLoad(ParamsReadContext ctx, int version)
- {
- if ( !super.OnStoreLoad(ctx, version) )
- return false;
-
- bool b_is_active = false;
- if ( !ctx.Read( b_is_active ) )
- b_is_active = false;
-
- bool b_is_in_progress = false;
- if ( !ctx.Read( b_is_in_progress ) )
- b_is_in_progress = false;
-
- if ( b_is_active )
- {
- SetActive();
- }
-
- if (b_is_in_progress && !b_is_active)
- {
- StartActivate(null);
- }
- return true;
- }
-
- bool IsActive()
- {
- return m_IsActive && m_IsInProgress == false && GetHierarchyRootPlayer() == null;
- }
- bool IsInactive()
- {
- return !IsActive() && m_IsInProgress == false && GetHierarchyRootPlayer() == null;
- }
- // trap cannot be taken when is activated
- override bool IsTakeable()
- {
- if ( m_IsInProgress == false && !IsActive() )
- {
- return true;
- }
-
- return false;
- }
- bool IsActivable()
- {
- return !IsActive() && GetHierarchyRootPlayer() == null && GetHierarchyParent() == null && m_IsInProgress == false && !IsRuined() && m_NeedActivation;
- }
- bool IsPlaceable()
- {
- if ( GetHierarchyRootPlayer() != null && GetHierarchyRootPlayer().GetHumanInventory().GetEntityInHands() == this )
- {
- PlayerBase player = PlayerBase.Cast( GetHierarchyRootPlayer() );
-
- vector player_pos = player.GetPosition();
- vector aim_pos = player.GetAimPosition();
-
- if ( vector.DistanceSq( player_pos, aim_pos ) <= ( Math.SqrFloat( 1.5 ) ) )
- {
- return IsPlaceableAtPosition( aim_pos );
- }
- }
-
- return false;
- }
- bool IsPlaceableAtPosition( vector position )
- {
- if ( position[1] < g_Game.SurfaceGetSeaLevelMax() + 0.03 )
- {
- return false;
- }
- else if ( GetGame().SurfaceIsPond( position[0], position[2] ) )
- {
- return false;
- }
-
- return true;
- }
-
- void Disarm()
- {
- SetInactive(false);
- RefreshState();
- GetGame().RPCSingleParam(this, ERPCs.RPC_TRAP_DISARM, null, true);
- OnDisarm();
- }
-
- //! also called from RPC on client
- void OnDisarm();
-
- void SnapOnObject(EntityAI victim)
- {
- if ( GetGame().IsServer() )
- {
- if ( m_Timer )
- {
- m_Timer.Stop();
- }
-
- RefreshState();
- if (m_DamagePlayers > 0)
- {
- if (victim)
- {
- if ( victim.IsInherited(SurvivorBase))
- {
- victim.DecreaseHealth("", "", m_DamagePlayers);
- }
- else if (victim.IsInherited(DayZCreatureAI))
- {
- victim.DecreaseHealth("", "", m_DamageOthers);
- }
- else if (victim.IsInherited(ItemBase))
- {
- ItemBase victim_item = ItemBase.Cast(victim);
- float damage_coef = 1;
-
- if (victim_item.HasQuantity() && victim_item.GetQuantityMax() != 0 && victim_item.GetQuantity() > 0)
- {
- damage_coef = victim_item.GetQuantityMax() / victim_item.GetQuantity(); // Lower quantity increases damage exposure
- }
-
- if (damage_coef > 0)
- {
- int item_size_x = 1;
- int item_size_y = 1;
- GetGame().GetInventoryItemSize(victim_item, item_size_x, item_size_y);
-
- float add_damage = 300 * damage_coef / Math.Clamp(item_size_x * item_size_y, 1, int.MAX);
- victim_item.DecreaseHealth("", "", add_damage);
- }
- }
- }
- }
-
- Synch(victim);
- }
- OnSteppedOn(victim);
- }
-
- void RemoveFromObject(EntityAI victim)
- {
- OnSteppedOut(victim);
- }
-
- void OnSteppedOn(EntityAI victim)
- {
- SetInactive(false);
- }
-
- void OnSteppedOut(EntityAI victim); //! keeping "step" here for consistency only
- // Synchronizes states
- protected void Synch(EntityAI victim)
- {
- if (GetGame().IsServer())
- {
- if (victim && !victim.GetAllowDamage())
- return;
- Param1<EntityAI> p = new Param1<EntityAI>(victim);
- GetGame().RPCSingleParam(this, ERPCs.RPC_TRAP_VICTIM, p, true);
- }
-
- }
-
- // On server -> client synchronization
- override void OnRPC(PlayerIdentity sender, int rpc_type, ParamsReadContext ctx)
- {
- super.OnRPC(sender, rpc_type, ctx);
-
- if ( !GetGame().IsDedicatedServer() )
- {
- switch (rpc_type)
- {
- case ERPCs.RPC_TRAP_VICTIM:
- Param1<EntityAI> victim = new Param1<EntityAI>(null);
-
- if (ctx.Read(victim))
- {
- if (victim.param1)
- SnapOnObject(victim.param1);
- }
-
- break;
-
- case ERPCs.RPC_TRAP_DISARM:
- OnDisarm();
- break;
-
- case SoundTypeTrap.ACTIVATING:
-
- Param1<bool> p = new Param1<bool>(false);
-
- bool isActivating = false;
- if (ctx.Read(p))
- isActivating = p.param1;
-
- break;
- }
- }
- }
-
- void RefreshState()
- {
- if ( !m_WasActivatedOrDeactivated )
- {
- return;
- }
-
- if ( GetGame().IsServer() )
- {
- // item is owned by player
- if ( GetHierarchyRootPlayer() != NULL && m_AnimationPhaseGrounded != "" )
- {
- SetAnimationPhase( m_AnimationPhaseSet, 1 );
- if ( m_AnimationPhaseTriggered != m_AnimationPhaseGrounded )
- {
- SetAnimationPhase( m_AnimationPhaseTriggered, 1 );
- }
- SetAnimationPhase( m_AnimationPhaseGrounded, 0 );
- }
- // item is set active
- else if ( IsActive() )
- {
- if ( m_AnimationPhaseGrounded != "" )
- {
- SetAnimationPhase( m_AnimationPhaseGrounded, 1 );
- }
- if ( m_AnimationPhaseSet != "" && m_AnimationPhaseTriggered != "" )
- {
- SetAnimationPhase( m_AnimationPhaseTriggered, 1 );
- SetAnimationPhase( m_AnimationPhaseSet, 0 );
- }
- }
- // item is inactive and not owned by player (on the ground)
- else if ( IsInactive() )
- {
- if ( m_AnimationPhaseGrounded != "" && m_AnimationPhaseTriggered != m_AnimationPhaseGrounded )
- {
- SetAnimationPhase( m_AnimationPhaseGrounded, 1 );
- }
- if ( m_AnimationPhaseSet != "" && m_AnimationPhaseTriggered != "" )
- {
- SetAnimationPhase( m_AnimationPhaseSet, 1 );
- SetAnimationPhase( m_AnimationPhaseTriggered, 0 );
- }
- }
- }
- }
- void SetupTrap()
- {
- if (GetGame().IsServer())
- {
- if (GetHierarchyRootPlayer() && GetHierarchyRootPlayer().CanDropEntity(this))
- SetupTrapPlayer(PlayerBase.Cast(GetHierarchyRootPlayer()));
- }
- }
- void SetupTrapPlayer( PlayerBase player, bool set_position = true )
- {
- if (GetGame().IsServer())
- {
- if (set_position)
- {
- player.LocalDropEntity(this);
-
- vector trapPos = player.GetDirection() * 1.5;
- trapPos[1] = 0;
- SetPosition(player.GetPosition() + trapPos);
- }
-
- if (m_NeedActivation == false)
- SetActive();
- }
- }
- void AddDefect()
- {
- if ( GetGame().IsServer() )
- {
- DecreaseHealth( "", "", m_DefectRate );
- }
- }
-
- void SetActive()
- {
- m_WasActivatedOrDeactivated = true;
-
- m_IsInProgress = false;
- m_IsActive = true;
-
- if (m_AddActivationDefect)
- {
- AddDefect();
- }
-
- if (GetGame().IsServer())
- {
- CreateTrigger();
- RefreshState();
- SetSynchDirty();
- }
-
- OnActivate();
- }
- void OnActivate();
- void StartActivate(PlayerBase player)
- {
- if (GetGame().IsServer())
- {
- m_Timer = new Timer(CALL_CATEGORY_SYSTEM);
- HideSelection("safety_pin");
-
- if (m_InitWaitTime > 0)
- {
- m_IsInProgress = true;
- m_Timer.Run(m_InitWaitTime, this, "SetActive");
-
- SetSynchDirty();
- }
- else
- SetActive();
- }
- }
-
- void StartDeactivate(PlayerBase player);
- void SetInactive(bool stop_timer = true)
- {
- m_WasActivatedOrDeactivated = true;
-
- m_IsActive = false;
- if (m_Timer && stop_timer)
- m_Timer.Stop();
-
- if (m_AddDeactivationDefect)
- AddDefect();
- SetSynchDirty();
- DeleteTrigger();
- RefreshState();
- }
-
- void CreateTrigger()
- {
- if (Class.CastTo(m_TrapTrigger, GetGame().CreateObjectEx("TrapTrigger", GetPosition(), SPAWN_FLAGS)))
- {
- vector mins = "-0.01 -0.05 -0.01";
- vector maxs = "0.01 0.5 0.01";
- m_TrapTrigger.SetOrientation(GetOrientation());
- m_TrapTrigger.SetExtents(mins, maxs);
- m_TrapTrigger.SetParentObject(this);
- GetGame().GetCallQueue(CALL_CATEGORY_SYSTEM).Call(DeferredEnableTrigger);
- }
- }
-
- void DeleteTrigger()
- {
- if (m_TrapTrigger)
- {
- m_TrapTrigger.SetParentObject(null);
- m_TrapTrigger.DeleteSafe();
- }
- }
-
- void DeferredEnableTrigger()
- {
- if (m_TrapTrigger)
- m_TrapTrigger.SetEnabled();
- }
- override void OnItemLocationChanged(EntityAI old_owner, EntityAI new_owner)
- {
- super.OnItemLocationChanged(old_owner, new_owner);
-
- if (GetGame().IsServer())
- {
- RefreshState();
- // TAKE ACTIVE TRAP FROM VICINITY
- if (old_owner == NULL && new_owner != NULL && IsActive())
- {
- // TAKE INTO HANDS
- if ( new_owner.IsPlayer() )
- {
- SnapOnObject(new_owner);
- }
- else if (new_owner.GetHierarchyRootPlayer())
- {
- SnapOnObject(new_owner.GetHierarchyRootPlayer());
- }
- }
- }
-
- }
- override void EEItemAttached(EntityAI item, string slot_name)
- {
- super.EEItemAttached(item, slot_name);
-
- if (GetGame().IsServer())
- RefreshState();
- }
-
- override void EEItemDetached(EntityAI item, string slot_name)
- {
- super.EEItemDetached(item, slot_name);
-
- if (GetGame().IsServer())
- RefreshState();
- }
-
- override void OnPlacementComplete(Man player, vector position = "0 0 0", vector orientation = "0 0 0")
- {
- super.OnPlacementComplete(player, position, orientation);
-
- if (GetGame().IsServer())
- {
- SetOrientation(orientation);
- SetPosition(position);
- PlaceOnSurface();
- SetSynchDirty();
- }
- }
-
- override bool CanPutInCargo( EntityAI parent )
- {
- if ( !super.CanPutInCargo(parent) )
- {
- return false;
- }
- return IsTakeable();
- }
-
- override bool CanPutIntoHands( EntityAI parent )
- {
- if ( !super.CanPutIntoHands( parent ) )
- {
- return false;
- }
- return IsTakeable();
- }
- override bool CanRemoveFromHands( EntityAI parent )
- {
- return IsTakeable();
- }
-
- override bool CanBePlaced( Man player, vector position )
- {
- return IsPlaceableAtPosition( position );
- }
-
- //! DEPRECATED Set if trap can be disarmed using ActionClapBearTrapWithThisItem
- bool CanBeClapped()
- {
- return true;
- }
-
- //Set if trap can be disarmed using trap-specific action
- bool CanBeDisarmed()
- {
- return false;
- }
-
- //! DEPRECATED
- void SetDisarmed( bool disarmed )
- {
- m_Disarmed = disarmed;
- }
-
- //! DEPRECATED
- bool GetDisarmed()
- {
- return m_Disarmed;
- }
-
- //================================================================
- // ADVANCED PLACEMENT
- //================================================================
-
- override void SetActions()
- {
- super.SetActions();
-
- AddAction(ActionActivateTrap);
- }
-
- // HELPERS
- protected EntityAI GetClosestCarWheel(EntityAI victim)
- {
- //! carscript specific handling (not all traps are uses this)
- vector trapPosXZ = GetPosition();
- trapPosXZ[1] = 0;
- GameInventory inv = victim.GetInventory();
- for (int i = 0; i < inv.AttachmentCount(); i++)
- {
- //! ruined wheel, bail out
- EntityAI wheelEntity = inv.GetAttachmentFromIndex(i);
- if (wheelEntity && wheelEntity.Type() == CarWheel_Ruined)
- {
- continue;
- }
-
- //! ignore all spare wheel
- int slotId;
- string slotName;
- wheelEntity.GetInventory().GetCurrentAttachmentSlotInfo(slotId, slotName);
- slotName.ToLower();
- if (slotName.Contains("spare"))
- {
- continue
- }
- //! actual, healthy wheel, let it pass
- if (wheelEntity && wheelEntity.IsInherited(CarWheel))
- {
- vector entPosXZ = wheelEntity.GetPosition();
- entPosXZ[1] = 0;
- if (vector.Distance(trapPosXZ, entPosXZ) < 1)
- {
- return wheelEntity;
- }
- }
- }
-
- return null;
- }
-
- protected void DamageClothing(PlayerBase player)
- {
- //Array used to find all relevant information about currently equipped clothes
- array<ClothingBase> equippedClothes = new array<ClothingBase>;
- equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("LEGS")));
- equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("BACK")));
- equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("VEST")));
- equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("HeadGear")));
- equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("Mask")));
- equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("BODY")));
- equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("FEET")));
- equippedClothes.Insert(ClothingBase.Cast(player.GetItemOnSlot("GLOVES")));
- //Damage all currently equipped clothes
- for (int i = 0; i < equippedClothes.Count(); i++)
- {
- //If no item is equipped on slot, slot is ignored
- if (equippedClothes[i] == null)
- {
- continue;
- }
- equippedClothes[i].DecreaseHealth(m_ClothingDmg[i], false);
- }
- }
-
- //!DEPRECATED
- protected ref EffectSound m_DeployLoopSound; //DEPRECATED in favor of m_DeployLoopSoundEx
-
- void PlayDeployLoopSound(); //!DEPRECATED
- void StopDeployLoopSound(); //!DEPRECATED
- }
|