/// <summary> /// Draws out the primary weapon debug info /// </summary> protected void DrawWeaponDebug(ICombatant rCombatant, IWeaponCore rWeapon, ICombatStyle rAttackStyle, Color rColor) { #if UNITY_EDITOR if (rCombatant == null) { return; } if (rWeapon == null) { return; } if (ShowDebug) { if (rWeapon.HasColliders) { WeaponCore lWeaponCore = rWeapon as WeaponCore; if (lWeaponCore != null) { Graphics.GraphicsManager.DrawCollider(lWeaponCore.Collider as BoxCollider, rColor); } } else if (rAttackStyle != null) { float lMinReach = (rAttackStyle.MinRange > 0f ? rAttackStyle.MinRange : rCombatant.MinMeleeReach + rWeapon.MinRange); float lMaxReach = (rAttackStyle.MaxRange > 0f ? rAttackStyle.MaxRange : rCombatant.MaxMeleeReach + rWeapon.MaxRange); Vector3 lCombatOrigin = rCombatant.CombatOrigin; Graphics.GraphicsManager.DrawSolidFrustum(lCombatOrigin, rCombatant.Transform.rotation * Quaternion.LookRotation(rAttackStyle.Forward, rCombatant.Transform.up), rAttackStyle.HorizontalFOA, rAttackStyle.VerticalFOA, lMinReach, lMaxReach, rColor); } } #endif }
/// <summary> /// Clear this instance. /// </summary> public override void Clear() { Attacker = null; Defender = null; Weapon = null; StyleIndex = -1; CombatStyle = null; HitTransform = null; base.Clear(); }
/// <summary> /// Test each of the combatants to determine if an impact occured /// </summary> /// <param name="rCombatTargets">Targets who we may be impacting</param> /// <param name="rAttackStyle">ICombatStyle that details the combat style being used.</param> /// <returns>The number of impacts that occurred</returns> public virtual int TestImpact(List <CombatTarget> rCombatTargets, ICombatStyle rAttackStyle = null) { mImpactCount = 0; float lMaxReach = 0f; if (mOwner != null) { ICombatant lCombatant = mOwner.GetComponent <ICombatant>(); if (lCombatant != null) { lMaxReach = lCombatant.MaxMeleeReach; } } for (int i = 0; i < rCombatTargets.Count; i++) { CombatTarget lTarget = rCombatTargets[i]; if (lTarget == CombatTarget.EMPTY) { continue; } float lDistance = Vector3.Distance(lTarget.ClosestPoint, mTransform.position); if (lDistance > _MaxRange + lMaxReach) { continue; } Vector3 lVector = (mTransform.position - mLastPosition).normalized; if (lVector.sqrMagnitude == 0 && mOwner != null) { lVector = mOwner.transform.forward; } mLastHit.Collider = lTarget.Collider; mLastHit.Point = lTarget.ClosestPoint; mLastHit.Normal = -lVector; mLastHit.Vector = lVector; mLastHit.Distance = lTarget.Distance; mLastHit.Index = mImpactCount; OnImpact(mLastHit, rAttackStyle); } return(mImpactCount); }
/// <summary> /// Clear this instance. /// </summary> public virtual void Clear() { mType = ""; mSender = null; mRecipient = null; mID = 0; mData = null; mIsSent = false; mIsHandled = false; mDelay = 0.0f; Attacker = null; Defender = null; Weapon = null; CombatStyle = null; HitTransform = null; }
/// <summary> /// Raised when the impact occurs /// </summary> /// <param name="rHitInfo">CombatHit structure detailing the hit information.</param> /// <param name="rAttackStyle">ICombatStyle that details the combat style being used.</param> protected override void OnImpact(CombatHit rHitInfo, ICombatStyle rAttackStyle = null) { // Test impact is now rolling up to the parent object but this means we are trying to apply the damage to the actorcore rather than the collider actually hit // see Test impact below IHealthManager lHealthManager = rHitInfo.Collider.gameObject.GetComponentInParent <IHealthManager>(); GameObject defender = ((MonoBehaviour)lHealthManager).gameObject; mDefenders.Add(defender); mImpactCount++; Transform lHitTransform = GetClosestTransform(rHitInfo.Point, rHitInfo.Collider.transform); Vector3 lHitDirection = Quaternion.Inverse(lHitTransform.rotation) * (rHitInfo.Point - lHitTransform.position).normalized; CombatMessage lMessage = CombatMessage.Allocate(); lMessage.Attacker = mOwner; lMessage.Defender = rHitInfo.Collider.gameObject; lMessage.Weapon = this; lMessage.Damage = GetAttackDamage(Random.value, (rAttackStyle != null ? rAttackStyle.DamageModifier : 1f)); lMessage.ImpactPower = GetAttackImpactPower(); lMessage.HitPoint = rHitInfo.Point; lMessage.HitDirection = lHitDirection; lMessage.HitVector = rHitInfo.Vector; lMessage.HitTransform = lHitTransform; lMessage.AttackIndex = mAttackStyleIndex; lMessage.CombatStyle = rAttackStyle; ActorCore lAttackerCore = (mOwner != null ? mOwner.GetComponentInParent <ActorCore>() : null); ActorCore lDefenderCore = defender.gameObject.GetComponentInParent <ActorCore>(); lMessage.ID = CombatMessage.MSG_ATTACKER_ATTACKED; if (lAttackerCore != null) { lAttackerCore.SendMessage(lMessage); } #if USE_MESSAGE_DISPATCHER || OOTII_MD MessageDispatcher.SendMessage(lMessage); #endif lMessage.ID = CombatMessage.MSG_DEFENDER_ATTACKED; if (lDefenderCore != null) { lDefenderCore.SendMessage(lMessage); #if USE_MESSAGE_DISPATCHER || OOTII_MD MessageDispatcher.SendMessage(lMessage); #endif } if (lAttackerCore != null) { lAttackerCore.SendMessage(lMessage); #if USE_MESSAGE_DISPATCHER || OOTII_MD MessageDispatcher.SendMessage(lMessage); #endif } OnImpactComplete(lMessage); CombatMessage.Release(lMessage); }
/// <summary> /// Test each of the combatants to determine if an impact occured. /// /// FIXME: A Neo FPS character /// has multiple possible hit zones, therefore we should have a way of determining /// which is actually hit. Right now we just hit the first found. This might be /// enough depending on how they are ordered coming into this method. /// </summary> /// <param name="rCombatTargets">Targets who we may be impacting</param> /// <param name="rAttackStyle">ICombatStyle that details the combat style being used.</param> /// <returns>The number of impacts that occurred</returns> public override int TestImpact(List <CombatTarget> rCombatTargets, ICombatStyle rAttackStyle = null) { mImpactCount = 0; float lMaxReach = 0f; if (mOwner != null) { ICombatant lCombatant = mOwner.GetComponent <ICombatant>(); if (lCombatant != null) { lMaxReach = lCombatant.MaxMeleeReach; } } for (int i = 0; i < rCombatTargets.Count; i++) { CombatTarget lTarget = rCombatTargets[i]; // Stop if we don't have a valid target if (lTarget == CombatTarget.EMPTY) { continue; } // Stop if we already hit the Neo FPS Character IHealthManager lHealthManager = lTarget.Collider.gameObject.GetComponentInParent <IHealthManager>(); if (lHealthManager == null) { Debug.LogError("Testing for weapon impact impact on " + lTarget.Collider + " but cannot find an IHealthManager in parents. Ignoring."); continue; } GameObject go = ((MonoBehaviour)lHealthManager).gameObject; if (mDefenders.Contains(go)) { continue; } // Stop if we're out of range float lDistance = Vector3.Distance(lTarget.ClosestPoint, mTransform.position); if (lDistance > _MaxRange + lMaxReach) { continue; } Vector3 lVector = (mTransform.position - mLastPosition).normalized; if (lVector.sqrMagnitude == 0 && mOwner != null) { lVector = mOwner.transform.forward; } mLastHit.Collider = lTarget.Collider; mLastHit.Point = lTarget.ClosestPoint; mLastHit.Normal = -lVector; mLastHit.Vector = lVector; mLastHit.Distance = lTarget.Distance; mLastHit.Index = mImpactCount; OnImpact(mLastHit, rAttackStyle); } return(mImpactCount); }
/// <summary> /// Raised when the impact occurs /// </summary> /// <param name="rHitInfo">CombatHit structure detailing the hit information.</param> /// <param name="rAttackStyle">ICombatStyle that details the combat style being used.</param> protected virtual void OnImpact(CombatHit rHitInfo, ICombatStyle rAttackStyle = null) { // If we get here, there's an impact mImpactCount++; // Extract out information about the hit Transform lHitTransform = GetClosestTransform(rHitInfo.Point, rHitInfo.Collider.transform); Vector3 lHitDirection = Quaternion.Inverse(lHitTransform.rotation) * (rHitInfo.Point - lHitTransform.position).normalized; // Put together the combat info. This will will be modified over time CombatMessage lMessage = CombatMessage.Allocate(); lMessage.Attacker = mOwner; lMessage.Defender = rHitInfo.Collider.gameObject; lMessage.Weapon = this; lMessage.Damage = GetAttackDamage(1f, (rAttackStyle != null ? rAttackStyle.DamageModifier : 1f)); lMessage.ImpactPower = GetAttackImpactPower(); lMessage.HitPoint = rHitInfo.Point; lMessage.HitDirection = lHitDirection; lMessage.HitVector = rHitInfo.Vector; lMessage.HitTransform = lHitTransform; // Grab cores for processing ActorCore lAttackerCore = (mOwner != null ? mOwner.GetComponent <ActorCore>() : null); ActorCore lDefenderCore = rHitInfo.Collider.gameObject.GetComponent <ActorCore>(); // Pre-Attack lMessage.ID = CombatMessage.MSG_ATTACKER_ATTACKED; if (lAttackerCore != null) { lAttackerCore.SendMessage(lMessage); } #if USE_MESSAGE_DISPATCHER || OOTII_MD MessageDispatcher.SendMessage(lMessage); #endif // Attack Defender lMessage.ID = CombatMessage.MSG_DEFENDER_ATTACKED; if (lDefenderCore != null) { ICombatant lDefenderCombatant = rHitInfo.Collider.gameObject.GetComponent <ICombatant>(); if (lDefenderCombatant != null) { lMessage.HitDirection = Quaternion.Inverse(lDefenderCore.Transform.rotation) * (rHitInfo.Point - lDefenderCombatant.CombatOrigin).normalized; } lDefenderCore.SendMessage(lMessage); #if USE_MESSAGE_DISPATCHER || OOTII_MD MessageDispatcher.SendMessage(lMessage); #endif } else { lMessage.HitDirection = Quaternion.Inverse(lHitTransform.rotation) * (rHitInfo.Point - lHitTransform.position).normalized; IDamageable lDefenderDamageable = rHitInfo.Collider.gameObject.GetComponent <IDamageable>(); if (lDefenderDamageable != null) { lDefenderDamageable.OnDamaged(lMessage); } Rigidbody lRigidBody = rHitInfo.Collider.gameObject.GetComponent <Rigidbody>(); if (lRigidBody != null) { lRigidBody.AddForceAtPosition(rHitInfo.Vector * lMessage.ImpactPower, rHitInfo.Point, ForceMode.Impulse); } } // Attacker response if (lAttackerCore != null) { lAttackerCore.SendMessage(lMessage); #if USE_MESSAGE_DISPATCHER || OOTII_MD MessageDispatcher.SendMessage(lMessage); #endif } // Finish up any impact processing (like sound) OnImpactComplete(lMessage); // Release the combatant to the pool CombatMessage.Release(lMessage); }
/// <summary> /// Draws out the primary weapon debug info /// </summary> protected void DrawWeaponDebug(IWeaponCore rWeapon, ICombatStyle rAttackStyle, Color rColor) { #if UNITY_EDITOR DrawWeaponDebug(mCombatant, rWeapon, rAttackStyle, rColor); #endif }