123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886 |
- enum EMeleeHitType
- {
- NONE = -1,
- LIGHT,
- HEAVY,
- SPRINT,
- KICK,
- FINISHER_LIVERSTAB,
- FINISHER_NECKSTAB,
- FINISHER_GENERIC,
- WPN_HIT,
- WPN_HIT_BUTTSTOCK,
- WPN_STAB,
- WPN_STAB_FINISHER,
- }
- class DayZPlayerImplementMeleeCombat
- {
- //! Target selection settings
- protected const float TARGETING_ANGLE_NORMAL = 30.0; //!< Second Pass: Half angle of cone
- protected const float TARGETING_ANGLE_SPRINT = 15.0; //!< Second Pass: Half angle of cone during sprint
- protected const float TARGETING_MIN_HEIGHT = -2.0; //!< Second Pass: How deep the cone goes in meters from player position
- protected const float TARGETING_MAX_HEIGHT = 2.0; //!< Second Pass: How high the cone goes in meters from player position
- protected const float TARGETING_RAY_RADIUS_EX = 0.5; //!< Second Pass: Max distance from ray projected from player looking direction
- protected const float TARGETING_RAY_RADIUS = 0.25; //!< DEPRECATED: "HitZoneSelection"
- protected const float TARGETING_RAY_DIST = 5.0; //!< DEPRECATED: "HitZoneSelection"
- protected const float TARGETING_RAY_DIST_SHORT= 2.0; //!< DEPRECATED: "HitZoneSelection"
- protected const float RANGE_EXTENDER_NORMAL = 0.65; //!< General range extension
- protected const float RANGE_EXTENDER_SPRINT = 1.35; //!< General range extension while in sprint
-
- protected const string DEFAULT_HIT_ZONE = "Torso"; //!< DEPRECATED: "HitZoneSelection"
-
- //! Target selecting "component"
- protected ref MeleeTargeting m_MeleeTargeting; //!< Contains logic for Second Pass
-
- //! Targets - types
- protected Object m_TargetObject; //!< Main target found during most recent TargetSelection
- protected EMeleeTargetType m_TargetType; //!< DEPRECATED: Was added but never used..?
- protected ref array<Object> m_AllTargetObjects; //!< All potential targets found during most recent TargetSelection
-
- #ifdef DIAG_DEVELOPER
- protected Object m_PreviousTargetObject; //!< Main target found during most recent TargetSelection
- protected ref array<Object> m_AllPreviousTargetObjects; //!< All potential targets found during most recent TargetSelection
- #endif
-
- protected ref array<typename> m_TargetableObjects; //!< Typenames of all directly/preferred targetable objects (1st Pass + 2nd Pass)
- protected ref array<typename> m_NonAlignableObjects; //!< Typenames of objects that can be targeted, but are not a priority (3rd Pass)
- protected ref array<string> m_BlacklistedDamageZones; //!< List of blacklisted damage zone names (cannot use indices due to the possible changes when p3d components are recalculated)
-
- //! Parent
- protected DayZPlayerImplement m_DZPlayer; //!< Player executing the melee
- //! Weapons - cache
- protected InventoryItem m_Weapon; //!< Weapon used during most recent Update
- protected int m_WeaponMode; //!< WeaponMode used during most recent Update
- protected float m_WeaponRange; //!< WeaponRange used during most recent Update
-
- //! Misc - cache
- protected bool m_ForceUntargetable; //!< Forcing current target as untargetable
- protected bool m_SprintAttack; //!< If most recent attack was a sprint attack
- protected bool m_WasHit; //!< If most recent attack was
-
- protected vector m_RayStart; //!< Start position of most recent HitZoneSelectionRaycast
- protected vector m_RayEnd; //!< End position of most recent HitZoneSelectionRaycast
- protected vector m_RayEndShort; //!< DEPRECATED: "HitZoneSelection"
-
- protected EMeleeHitType m_HitType; //!< Hit type of the most recent attack
- //! Hit result - cache
- protected int m_HitZoneIdx; //!< Most recent target HitZone index
- protected int m_FinisherType;
- protected string m_HitZoneName; //!< Most recent target HitZone name
- protected vector m_HitPositionWS; //!< Most recent target position
-
- #ifdef DIAG_DEVELOPER
- protected int m_PreviousHitZoneIdx; //!< Most recent target HitZone index
- protected string m_PreviousHitZoneName; //!< Most recent target HitZone name
- protected vector m_PreviousHitPositionWS; //!< Most recent target position
- #endif
-
- private int m_DebugForcedFinisherType;
- // ------------------------------------------------------------
- // CONSTRUCTOR
- // ------------------------------------------------------------
- void DayZPlayerImplementMeleeCombat(DayZPlayerImplement player)
- {
- Init(player);
- }
-
- void Init(DayZPlayerImplement player)
- {
- m_DZPlayer = player;
-
- m_MeleeTargeting = new MeleeTargeting;
-
- m_HitZoneName = "";
- m_HitZoneIdx = -1;
- m_FinisherType = -1;
- m_HitPositionWS = vector.Zero;
-
- m_SprintAttack = false;
- m_WasHit = false;
-
- m_TargetObject = null;
- m_TargetType = EMeleeTargetType.ALIGNABLE;
- m_AllTargetObjects = new array<Object>;
- #ifdef DIAG_DEVELOPER
- m_AllPreviousTargetObjects = new array<Object>;
- #endif
-
- m_DebugForcedFinisherType = -1;
- m_TargetableObjects = new array<typename>; //checks against CONFIG hierarchy
- m_TargetableObjects.Insert(DayZPlayer);
- m_TargetableObjects.Insert(DayZInfected);
- m_TargetableObjects.Insert(DayZAnimal);
- m_NonAlignableObjects = new array<typename>;
- m_NonAlignableObjects.Insert(Building);
- m_NonAlignableObjects.Insert(Transport);
- m_NonAlignableObjects.Insert(CarWheel);
- m_NonAlignableObjects.Insert(CarDoor);
- m_NonAlignableObjects.Insert(TentBase);
- m_NonAlignableObjects.Insert(BaseBuildingBase);
-
- m_BlacklistedDamageZones = new array<string>;
- m_BlacklistedDamageZones.Insert("Brain");
- }
- void ~DayZPlayerImplementMeleeCombat() {}
- // ------------------------------------------------------------
- // PUBLIC
- // ------------------------------------------------------------
- EMeleeHitType GetHitType()
- {
- return m_HitType;
- }
- void SetHitZoneIdx(int pHitZone)
- {
- m_HitZoneIdx = pHitZone;
- }
-
- EntityAI GetTargetEntity()
- {
- return EntityAI.Cast(m_TargetObject);
- }
- void SetTargetObject(Object pTarget)
- {
- m_TargetObject = pTarget;
- }
-
- //! component idx
- int GetHitZoneIdx()
- {
- return m_HitZoneIdx;
- }
-
- vector GetHitPos()
- {
- return m_HitPositionWS;
- }
- void SetHitPos(vector pHitPos)
- {
- m_HitPositionWS = pHitPos;
- }
-
- int GetFinisherType()
- {
- return m_FinisherType;
- }
-
- void SetFinisherType(int pFinisherType)
- {
- m_FinisherType = pFinisherType;
- }
-
- int GetWeaponMode()
- {
- return m_WeaponMode;
- }
-
- void Reset(InventoryItem weapon, EMeleeHitType hitMask, bool wasHitEvent = false)
- {
- m_Weapon = weapon;
- m_HitType = hitMask;
- m_TargetType = EMeleeTargetType.ALIGNABLE;
- m_SprintAttack = hitMask == EMeleeHitType.SPRINT;
- m_WeaponMode = SelectWeaponMode(weapon);
- m_WeaponRange = GetWeaponRange(weapon, m_WeaponMode);
- m_WasHit = wasHitEvent;
-
- #ifdef DIAG_DEVELOPER
- m_AllPreviousTargetObjects = m_AllTargetObjects;
- #endif
- m_AllTargetObjects.Clear();
- }
-
- void ResetTarget()
- {
- #ifdef DIAG_DEVELOPER
- m_PreviousTargetObject = m_TargetObject;
- m_PreviousHitPositionWS = m_HitPositionWS;
- m_PreviousHitZoneIdx = m_HitZoneIdx;
- m_PreviousHitZoneName = m_HitZoneName;
- #endif
-
- InternalResetTarget();
- }
- void Update(InventoryItem weapon, EMeleeHitType hitMask, bool wasHitEvent = false)
- {
- Reset(weapon, hitMask, wasHitEvent);
-
- #ifndef SERVER
- if (!ScriptInputUserData.CanStoreInputUserData())
- {
- //Error("DayZPlayerImplementMeleeCombat - ScriptInputUserData already posted");
- return;
- }
-
- TargetSelection();
- SetFinisherType(TrySelectFinisherType(weapon, GetTargetEntity()));
- //! Store target into input packet
- if (GetGame().IsMultiplayer())
- {
- ScriptInputUserData ctx = new ScriptInputUserData();
- ctx.Write(INPUT_UDT_MELEE_TARGET);
- ctx.Write(m_TargetObject);
- ctx.Write(m_HitPositionWS);
- ctx.Write(m_HitZoneIdx);
- ctx.Write(m_FinisherType);
- ctx.Send();
- }
- #endif
- }
-
- void CheckMeleeItem()
- {
- if (m_Weapon)
- {
- ItemBase item = ItemBase.Cast(m_Weapon.ProcessMeleeItemDamage(GetWeaponMode()));
-
- if (item && item.GetHierarchyRootPlayer())
- {
- PlayerBase.Cast(item.GetHierarchyRootPlayer()).SetCheckMeleeItem(item);
- }
- else if (m_Weapon && m_Weapon.GetHierarchyRootPlayer())
- {
- PlayerBase.Cast(m_Weapon.GetHierarchyRootPlayer()).SetCheckMeleeItem(ItemBase.Cast(m_Weapon));
- }
- }
- }
-
- // ------------------------------------------------------------
- // protected
- // ------------------------------------------------------------
- protected int SelectWeaponMode(InventoryItem weapon)
- {
- if (weapon)
- {
- //! melee with firearm
- if (weapon.IsInherited(Weapon))
- {
- switch (m_HitType)
- {
- case EMeleeHitType.WPN_HIT:
- return 0;
- case EMeleeHitType.WPN_HIT_BUTTSTOCK:
- return 1;
- case EMeleeHitType.WPN_STAB:
- return 2;
- }
- }
- else
- {
- //! melee weapon attacks - gets mode from the item
- switch (m_HitType)
- {
- case EMeleeHitType.LIGHT:
- return weapon.GetMeleeMode();
- case EMeleeHitType.HEAVY:
- return weapon.GetMeleeHeavyMode();
- case EMeleeHitType.SPRINT:
- return weapon.GetMeleeSprintMode();
- }
- }
- }
- //! bare hand melee mode selection
- switch (m_HitType)
- {
- case EMeleeHitType.HEAVY:
- return 1;
- case EMeleeHitType.SPRINT:
- return 2;
- }
- return 0; //! default bare-hand light attack
- }
-
- protected float GetWeaponRange(InventoryItem weapon, int weaponMode)
- {
- if ( weapon )
- return weapon.GetMeleeCombatData().GetModeRange(weaponMode);
- else
- return m_DZPlayer.GetMeleeCombatData().GetModeRange(weaponMode);
- }
-
- protected float GetRange()
- {
- return m_WeaponRange + RANGE_EXTENDER_NORMAL;
- }
-
- protected float GetAngle()
- {
- if (m_SprintAttack)
- return TARGETING_ANGLE_SPRINT;
- else
- return TARGETING_ANGLE_NORMAL;
- }
-
- protected void TargetSelection()
- {
- // Prepare common variables
- PlayerBase player = PlayerBase.Cast(m_DZPlayer);
- vector pos = m_DZPlayer.GetPosition();
- vector rayStart = m_DZPlayer.GetBonePositionWS(m_DZPlayer.GetBoneIndexByName("Head"));
- vector cameraPos, cameraRot, cameraDir;
- m_DZPlayer.GetCurrentCameraTransform(cameraPos, cameraDir, cameraRot);
- vector dir = MiscGameplayFunctions.GetHeadingVector(player);
- dir[1] = cameraDir[1];
- // Calculate max distances
- float dist = GetRange();
- float angle = GetAngle();
- float dist2 = Math.SqrFloat(dist);
-
- // There's generally 2 TargetSelection calls per animation
- // First to obtain target to move towards during animation
- // Second one is to see if that target is still in range before applying damage to it
- // m_WasHit means the hit event occured, so this is the second call
- if (m_WasHit && GetFinisherType() == -1)
- {
- // See if the component is still in range
- if (CanObjectBeTargeted(m_TargetObject) && ( vector.DistanceSq(rayStart, m_TargetObject.GetDamageZonePos(m_HitZoneName)) <= dist2 ))
- {
- m_AllTargetObjects.Insert(m_TargetObject);
- // This result should still be cached, so no need to fill it in again
- return;
- }
- }
-
- // Find a new target
- InternalResetTarget();
-
- Object target;
- vector hitPos;
- int hitZone;
-
- // First pass - Prefer what the player is looking at (only aligneable ones, we will try for nonaligneable later)
- if (HitZoneSelectionRaycastHelper(hitPos, hitZone, target))
- {
- if (m_ForceUntargetable)
- {
- SetTarget(target, hitPos, hitZone);
- return;
- }
- if (CanObjectBeTargeted(target) && vector.DistanceSq(rayStart, hitPos) <= dist2)
- {
- m_AllTargetObjects.Insert(target);
-
- SetTarget(target, hitPos, hitZone);
- return;
- }
- }
-
- // Second pass - Try to obtain something aligneable closeby the player watching direction
- MeleeTargetData targetData = m_MeleeTargeting.GetMeleeTargetEx(new MeleeTargetSettings(pos, dist*0.75, angle, TARGETING_MIN_HEIGHT, TARGETING_MAX_HEIGHT, rayStart, dir, TARGETING_RAY_RADIUS_EX, m_DZPlayer, m_TargetableObjects), m_AllTargetObjects, m_BlacklistedDamageZones);
- if (targetData)
- {
- SetTarget(targetData.Obj, targetData.HitPos, targetData.HitComponent);
- return;
- }
-
- // Third pass - We found no aligneable target, check if the target that we are directly looking at is nonalignable (big)
- if (CanObjectBeTargeted(target, true) && vector.DistanceSq(rayStart, hitPos) <= dist2)
- {
- m_AllTargetObjects.Insert(target);
- SetTarget(target, hitPos, hitZone);
- return;
- }
- }
-
- /**
- \brief General condition for finisher attacks
- \param weapon \p Weapon used in the attack
- \param target \p Target entity
- \return \p int - type of finisher (-1 == no finisher)
- */
- protected int TrySelectFinisherType(InventoryItem weapon, EntityAI target)
- {
- if (m_WasHit)
- return -1;
-
- if (target)
- {
- vector dir = target.GetPosition() - m_DZPlayer.GetPosition();
- IEntity hitEntity;
- vector hitPos, hitNormal;
-
- float moveFraction = m_DZPlayer.CollisionMoveTest(dir, vector.Zero, 1.0, target, hitEntity, hitPos, hitNormal);
- if (moveFraction < 1.0)
- return -1;
- }
- //! perform only for finisher suitable weapons
- if (target && target.CanBeBackstabbed() && weapon && (weapon.IsMeleeFinisher() || m_HitType == EMeleeHitType.WPN_STAB) && !weapon.IsRuined() )
- {
- bool playGenericFinisherAnimation = false;
- ZombieBase targetZombie = ZombieBase.Cast(target);
- if (targetZombie && m_DebugForcedFinisherType == -1)
- {
- //! check if attacker is in right pos and angle against victim
- if (!IsEntityBehindEntityInAngle(m_DZPlayer, target, 60))
- {
- return -1;
- }
-
- int mindState = targetZombie.GetMindStateSynced();
- //! Check if the infected is aware of the player
- if (mindState >= DayZInfectedConstants.MINDSTATE_DISTURBED)
- {
- return -1;
- }
- }
- PlayerBase targetPlayer = PlayerBase.Cast(target);
- //! prone checks
- if (targetZombie)
- {
- playGenericFinisherAnimation = targetZombie.IsCrawling();
- }
- else if (targetPlayer)
- {
- playGenericFinisherAnimation = targetPlayer.IsInProne();
- }
- else
- {
- playGenericFinisherAnimation = true;
- }
-
- //! firearm
- if (weapon.IsWeapon())
- {
- return EMeleeHitType.WPN_STAB_FINISHER;
- }
- else if (playGenericFinisherAnimation)
- {
- return EMeleeHitType.FINISHER_GENERIC;
- }
- else //specific hit depending on the component hit (gotten from the target)
- {
- return DetermineSpecificFinisherType(ItemBase.Cast(weapon));
- }
- }
- return -1;
- }
-
- protected int DetermineSpecificFinisherType(ItemBase weapon)
- {
- if (m_DebugForcedFinisherType > -1)
- {
- array<int> finishers = {
- EMeleeHitType.FINISHER_LIVERSTAB,
- EMeleeHitType.FINISHER_NECKSTAB
- };
- return finishers[m_DebugForcedFinisherType];
- }
-
- if (!weapon || !weapon.GetValidFinishers() || weapon.GetValidFinishers().Count() == 0)
- {
- return EMeleeHitType.FINISHER_LIVERSTAB;
- }
-
- PlayerBase player = PlayerBase.Cast(m_DZPlayer);
- int idx = Math.Round(Math.Lerp(0, weapon.GetValidFinishers().Count() - 1, player.GetRandomGeneratorSyncManager().GetRandom01(RandomGeneratorSyncUsage.RGSGeneric)));
- return weapon.GetValidFinishers()[idx];
- }
-
- protected void InternalResetTarget()
- {
- m_TargetObject = null;
- m_HitPositionWS = vector.Zero;
- m_HitZoneIdx = -1;
- m_HitZoneName = "";
- SetFinisherType(-1);
- }
-
- protected void SetTarget(Object obj, vector hitPos, int hitZone)
- {
- if (obj)
- {
- m_TargetObject = obj;
- m_HitPositionWS = hitPos;
- m_HitZoneIdx = hitZone;
- m_HitZoneName = m_TargetObject.GetDamageZoneNameByComponentIndex(m_HitZoneIdx);
- }
- }
-
- protected bool CanObjectBeTargeted(Object obj, bool checkNonAligneAble = false)
- {
- return obj && obj.IsAlive() && ( obj.IsAnyInherited(m_TargetableObjects) || (checkNonAligneAble && obj.IsAnyInherited(m_NonAlignableObjects)) );
- }
-
- protected bool HitZoneSelectionRaycastHelper(out vector hitPos, out int hitZone, out Object target)
- {
- return HitZoneSelectionRaycast(hitPos, hitZone, target, false);
- // Not sure if desired, as it can give some results that feel a little odd
- // But it will depend entirely on the player and situation..
- // I guess the crosshair is hidden while melee anyways though
- // || ( m_DZPlayer.IsInThirdPerson() && HitZoneSelectionRaycast(hitPos, hitZone, target, true);
- }
-
- protected bool HitZoneSelectionRaycast(out vector hitPos, out int hitZone, out Object target, bool useCamera)
- {
- PlayerBase player = PlayerBase.Cast(m_DZPlayer);
-
- vector pos;
- vector dir;
- vector playerDir;
- if (useCamera)
- { // What the player camera is looking at (crosshair)
- vector cameraRotation;
- player.GetCurrentCameraTransform(pos, dir, cameraRotation);
- playerDir = dir;
- }
- else
- { // What the player himself is looking at
- playerDir = MiscGameplayFunctions.GetHeadingVector(player);
- dir = GetGame().GetCurrentCameraDirection();
- MiscGameplayFunctions.GetHeadBonePos(player, pos);
- }
-
- //! Prevents targeting of objects behind player
- if (vector.Dot(dir, playerDir) < 0.5)
- {
- return false;
- }
- m_RayStart = pos;
- m_RayEnd = m_RayStart + GetRange() * dir;
-
- // raycast
- set<Object> hitObjects = new set<Object>;
- vector hitNormal;
-
- if ( DayZPhysics.RaycastRV(m_RayStart, m_RayEnd, hitPos, hitNormal, hitZone, hitObjects, null, player, false, false, ObjIntersectIFire) && hitObjects.Count() > 0 )
- {
- target = hitObjects[0];
- m_ForceUntargetable = false;
- //! Opponent is inside car - targeting range is shorter in that case
- PlayerBase playerTarget = PlayerBase.Cast(target);
- if (playerTarget && playerTarget.IsInVehicle())
- {
- if (vector.DistanceSq(pos, hitPos) > Math.SqrFloat(GetRange() * 0.5))
- {
- m_ForceUntargetable = true;
- target = null;
- hitPos = vector.Zero;
- hitZone = -1;
- }
- }
- return true;
- }
-
- return false;
- }
- //! DEPRECATED
- protected void HitZoneSelection()
- {
- Object cursorTarget = null;
- PlayerBase player = PlayerBase.Cast(m_DZPlayer);
- // ray properties
- vector pos;
- vector cameraDirection = GetGame().GetCurrentCameraDirection();
- MiscGameplayFunctions.GetHeadBonePos(player, pos);
- m_RayStart = pos;
- m_RayEnd = pos + cameraDirection * TARGETING_RAY_DIST;
- m_RayEndShort = pos + cameraDirection * TARGETING_RAY_DIST_SHORT;
- // raycast
- set<Object> hitObjects = new set<Object>;
- int hitComponentIndex;
- float hitFraction;
- vector start, end, hitNormal, hitPosObstructed;
- PhxInteractionLayers collisionLayerMask = PhxInteractionLayers.DEFAULT;
-
- if ( !DayZPhysics.RaycastRV(m_RayStart, m_RayEndShort, m_HitPositionWS, hitNormal, m_HitZoneIdx, hitObjects, null, player, false, false, ObjIntersectIFire) && !DayZPhysics.RaycastRV(m_RayStart, m_RayEnd, m_HitPositionWS, hitNormal, m_HitZoneIdx, hitObjects, null, player, false, false, ObjIntersectIFire, TARGETING_RAY_RADIUS) )
- {
- m_HitZoneIdx = -1;
- //Print("HitZoneSelection failed");
- }
- else if ( hitObjects.Count() > 0 )
- {
- cursorTarget = hitObjects.Get(0);
- //! make sure we are in range of the current weapon;
- vector playerPos = m_DZPlayer.GetPosition();
- vector hitPos = m_HitPositionWS;
- //! 2d only
- playerPos[1] = 0;
- hitPos[1] = 0;
- //! just for building and transports (big objects)
- if ( cursorTarget.IsAnyInherited(m_NonAlignableObjects) && vector.Distance(playerPos, hitPos) <= GetWeaponRange(m_Weapon, GetWeaponMode()))
- {
- //! if no object in cone, set this object from raycast for these special cases
- if (m_TargetObject == null)
- {
- m_TargetObject = cursorTarget;
- }
- }
- if (cursorTarget == m_TargetObject)
- {
- m_HitZoneName = cursorTarget.GetDamageZoneNameByComponentIndex(m_HitZoneIdx);
- //Print("hit object: " + m_TargetObject + " | component idx: " + m_HitZoneIdx + " | hitzone name: " + m_HitZoneName);
- }
- else
- {
- if (m_TargetObject == DayZInfected.Cast(m_TargetObject) || m_TargetObject == PlayerBase.Cast(m_TargetObject))
- m_HitZoneName = DEFAULT_HIT_ZONE; //Default to torso if no zone is targeted
- }
- }
- else
- {
- m_HitZoneIdx = -1;
- //Print("HitZoneSelection failed");
- }
- }
- //! DEPRECATED - New function in MeleeTargeting
- protected bool IsObstructed(Object object)
- {
- // check direct visibility of object (obstruction check)
- PhxInteractionLayers collisionLayerMask = PhxInteractionLayers.BUILDING|PhxInteractionLayers.DOOR|PhxInteractionLayers.VEHICLE|PhxInteractionLayers.ROADWAY|PhxInteractionLayers.TERRAIN|PhxInteractionLayers.ITEM_SMALL|PhxInteractionLayers.ITEM_LARGE|PhxInteractionLayers.FENCE;
- int hitComponentIndex;
- float hitFraction;
- vector start, end, hitNormal, hitPosObstructed;
- Object hitObject = null;
- PlayerBase player = PlayerBase.Cast(m_DZPlayer);
- if (object)
- {
- MiscGameplayFunctions.GetHeadBonePos(player, start);
- end = start + MiscGameplayFunctions.GetHeadingVector(player) * vector.Distance(player.GetPosition(), object.GetPosition());
-
- if ( end == start )
- return true; //! not possible to trace when this happens (zero length raycast)
- return DayZPhysics.RayCastBullet( start, end, collisionLayerMask, null, hitObject, hitPosObstructed, hitNormal, hitFraction);
- }
- return false;
- }
-
- private bool IsEntityBehindEntityInAngle(EntityAI source, EntityAI target, float angle)
- {
- vector targetDirection = target.GetDirection();
- ZombieBase targetZombie;
- if (Class.CastTo(targetZombie, target))
- {
- targetDirection = Vector(targetZombie.GetOrientationSynced(),0,0);
- targetDirection = targetDirection.AnglesToVector();
- }
- vector toSourceDirection = (source.GetPosition() - target.GetPosition());
- targetDirection[1] = 0;
- toSourceDirection[1] = 0;
- targetDirection.Normalize();
- toSourceDirection.Normalize();
- float cosFi = vector.Dot(targetDirection, toSourceDirection);
- vector cross = targetDirection * toSourceDirection;
- int hitDir = Math.Acos(cosFi) * Math.RAD2DEG;
-
- if (cross[1] < 0)
- hitDir = -hitDir;
-
- return hitDir <= (-180 + angle) || hitDir >= (180 - angle);
- }
-
- #ifdef DIAG_DEVELOPER
- // ------------------------------------------------------------
- // DEBUG
- // ------------------------------------------------------------
- protected ref array<Shape> dbgConeShapes = new array<Shape>();
- protected ref array<Shape> dbgTargets = new array<Shape>();
- protected ref array<Shape> hitPosShapes = new array<Shape>();
-
- void Debug(InventoryItem weapon, EMeleeHitType hitType)
- {
- CleanAllDebugShapes();
-
- if (!DiagMenu.GetBool(DiagMenuIDs.MELEE_DEBUG))
- return;
- if (DiagMenu.GetBool(DiagMenuIDs.MELEE_CONTINUOUS) && (!GetGame().IsMultiplayer() || !GetGame().IsServer()))
- Update(weapon, hitType);
- if (DiagMenu.GetBool(DiagMenuIDs.MELEE_SHOW_TARGETS))
- ShowDebugMeleeTarget();
-
- if (DiagMenu.GetBool(DiagMenuIDs.MELEE_DRAW_TARGETS))
- DrawDebugTargets();
-
- if (DiagMenu.GetBool(DiagMenuIDs.MELEE_DRAW_RANGE))
- {
- DrawDebugMeleeHitPosition();
- DrawDebugMeleeCone();
- }
-
- if (DiagMenu.GetBool(DiagMenuIDs.MELEE_DRAW_BLOCK_RANGE_AI))
- DrawDebugBlockCone(GameConstants.AI_MAX_BLOCKABLE_ANGLE, COLOR_GREEN);
-
- if (DiagMenu.GetBool(DiagMenuIDs.MELEE_DRAW_BLOCK_RANGE_PVP))
- DrawDebugBlockCone(GameConstants.PVP_MAX_BLOCKABLE_ANGLE, COLOR_YELLOW);
- }
-
- int DebugGetForcedFinisherType()
- {
- return m_DebugForcedFinisherType;
- }
-
- void DebugSetForcedFinisherType(int pFinisherType)
- {
- m_DebugForcedFinisherType = pFinisherType;
- }
- //! shows target in DbgUI 'window'
- protected void ShowDebugMeleeTarget()
- {
- int windowPosX = 0;
- int windowPosY = 500;
- DbgUI.Begin("Melee Target", windowPosX, windowPosY);
- HumanCommandMelee2 hmc2 = m_DZPlayer.GetCommand_Melee2();
- if (hmc2)
- {
- DbgUI.Text("Current combo: " + hmc2.GetComboCount());
- }
- if (m_PreviousTargetObject)
- {
- DbgUI.Text("Previous Character: " + m_PreviousTargetObject.GetDisplayName());
- DbgUI.Text("Previous HitZone: " + m_PreviousHitZoneName + "(" + m_PreviousHitZoneIdx + ")");
- DbgUI.Text("Previous HitPosWS:" + m_PreviousHitPositionWS);
- DbgUI.Text("Previous Distance:" + vector.Distance(m_PreviousHitPositionWS, m_DZPlayer.GetPosition()));
- }
- if (m_TargetObject)
- {
- DbgUI.Text("Character: " + m_TargetObject.GetDisplayName());
- DbgUI.Text("HitZone: " + m_HitZoneName + "(" + m_HitZoneIdx + ")");
- DbgUI.Text("HitPosWS:" + m_HitPositionWS);
- DbgUI.Text("Distance:" + vector.Distance(m_HitPositionWS, m_DZPlayer.GetPosition()));
- }
- DbgUI.End();
- }
- //! shows debug sphere above the target
- protected void DrawDebugTargets()
- {
- DrawDebugTargetsHelper(m_AllPreviousTargetObjects, m_PreviousTargetObject, COLOR_RED_A, COLOR_YELLOW_A);
- DrawDebugTargetsHelper(m_AllTargetObjects, m_TargetObject, COLOR_RED, COLOR_YELLOW);
- }
-
- protected void DrawDebugTargetsHelper(array<Object> allTargets, Object target, int colorMainTarget, int colorTarget)
- {
- for (int i = 0; i < allTargets.Count(); ++i )
- {
- if ( m_TargetObject && allTargets.Count() )
- {
- Object obj = allTargets[i];
- vector w_pos = obj.GetPosition();
- // sphere pos tweaks
- vector w_pos_sphr = w_pos;
- w_pos_sphr[1] = w_pos_sphr[1] + 1.8;
- // line pos tweaks
- vector w_pos_lend = w_pos;
- w_pos_lend[1] = w_pos_lend[1] + 1.8;
-
- if ( obj == m_TargetObject )
- {
- dbgTargets.Insert( Debug.DrawSphere(w_pos_sphr, 0.05, colorMainTarget, ShapeFlags.NOOUTLINE) );
- dbgTargets.Insert( Debug.DrawLine(w_pos, w_pos_lend, colorMainTarget) );
- }
- else
- {
- dbgTargets.Insert( Debug.DrawSphere(w_pos_sphr, 0.05, colorTarget, ShapeFlags.NOOUTLINE) );
- dbgTargets.Insert( Debug.DrawLine(w_pos, w_pos_lend, colorTarget) );
- }
- }
- }
- }
-
- protected void DrawDebugMeleeHitPosition()
- {
- if (m_PreviousTargetObject)
- hitPosShapes.Insert( Debug.DrawSphere(m_PreviousHitPositionWS, 0.15, COLOR_YELLOW_A, ShapeFlags.NOOUTLINE|ShapeFlags.TRANSP) );
-
- if (m_TargetObject)
- hitPosShapes.Insert( Debug.DrawSphere(m_HitPositionWS, 0.15, COLOR_YELLOW, ShapeFlags.NOOUTLINE|ShapeFlags.TRANSP) );
- }
-
- protected void DrawDebugMeleeCone()
- {
- // cone settings
- float dist = GetRange();
- vector start = m_DZPlayer.GetPosition();
-
- vector normDir = MiscGameplayFunctions.GetHeadingVector(PlayerBase.Cast(m_DZPlayer));
- normDir[1] = 0;
- normDir.Normalize();
- float playerAngle = -Math.Atan2(normDir[0], normDir[2]);
-
- dbgConeShapes.InsertArray(Debug.DrawCone(start, dist, GetAngle() * Math.DEG2RAD, playerAngle + Math.PI_HALF, COLOR_BLUE));
- }
- protected void DrawDebugBlockCone(float angle, int color)
- {
- // cone settings
- float dist = 3;
- vector start = m_DZPlayer.GetPosition();
-
- vector dir = GetGame().GetCurrentCameraDirection();
- dir[1] = 0;
- dir.Normalize();
- float playerAngle = -Math.Atan2(dir[0], dir[2]);
-
- dbgConeShapes.InsertArray(Debug.DrawCone(start, dist, angle * Math.DEG2RAD, playerAngle + Math.PI_HALF, color));
- }
-
- protected void CleanAllDebugShapes()
- {
- CleanupDebugShapes(dbgTargets);
- CleanupDebugShapes(dbgConeShapes);
- CleanupDebugShapes(hitPosShapes);
- }
- protected void CleanupDebugShapes(array<Shape> shapes)
- {
- for ( int it = 0; it < shapes.Count(); ++it )
- Debug.RemoveShape( shapes[it] );
- shapes.Clear();
- }
- #endif
- }
|