/// <summary> /// Sends the projectile flying /// </summary> public virtual void Launch(float rHAngle = 0f, float rVAngle = 0f, float rForce = 0f) { mAge = 0f; mIsActive = true; mHasExpired = false; mIsShuttingDown = false; mImpactCount = 0; mLastImpact = CombatHit.EMPTY; // Apply any rotation adjustment Quaternion lRotation = Quaternion.AngleAxis(rHAngle, _Transform.up) * Quaternion.AngleAxis(rVAngle, _Transform.right); _Transform.rotation = lRotation * _Transform.rotation; // Set the launch particles mLaunchPosition = _Transform.position; if (_LaunchRoot != null) { mLaunchInstance = GameObject.Instantiate(_LaunchRoot); mLaunchInstance.transform.position = _Transform.position; mLaunchInstance.transform.rotation = _Transform.rotation; StartEffects(mLaunchInstance); } if (_FlyRoot != null) { mFlyInstance = GameObject.Instantiate(_FlyRoot); mFlyInstance.transform.parent = _Transform; mFlyInstance.transform.localRotation = Quaternion.identity; mFlyInstance.transform.localPosition = Vector3.zero; StartEffects(mFlyInstance); } // Add twice so we can create a trajectory from the start mLastPosition = _Transform.position; // If we're dealing with a rigidbody, add the force if (mRigidbody != null) { mRigidbody.useGravity = true; mRigidbody.isKinematic = false; if (rForce == 0f) { rForce = _Speed; } Vector3 lForce = _Transform.forward * rForce; mRigidbody.AddForce(lForce); } }
/// <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> /// 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> /// Raised when the impact occurs /// </summary> /// <param name="rHitInfo">RaycastHit data about the hit itself</param> /// <param name="rClosestTransform">Closets transform to the hit position</param> /// <param name="rLocalPosition">Position of the hit relative to the closest transform</param> /// <param name="rLocalForward">Direction the hit came from relative to the closest transform</param> protected virtual void OnImpact(CombatHit rHitInfo) { mAge = 0f; mIsActive = false; mImpactCount++; ClearPhysics(); // Stop the flight particles StopEffects(mLaunchInstance); StopEffects(mFlyInstance); // Play the particles if (_ImpactRoot != null) { mImpactInstance = GameObject.Instantiate(_ImpactRoot); mImpactInstance.transform.position = rHitInfo.Point; mImpactInstance.transform.rotation = Quaternion.LookRotation(rHitInfo.Normal, Vector3.up); StartEffects(mImpactInstance); } //// Combatant that is attacking //ICombatant lDefender = null; //// Determine who we're colliding with //lDefender = rHitInfo.Collider.gameObject.GetComponent<ICombatant>(); //IDamageable lHitActorCore = rHitInfo.Collider.gameObject.GetComponent<IDamageable>(); //if (lDefender == null) //{ // IWeaponCore lWeaponCore = rHitInfo.Collider.gameObject.GetComponent<IWeaponCore>(); // if (lWeaponCore != null) // { // lDefender = lWeaponCore.Owner.GetComponent<ICombatant>(); // if (lHitActorCore == null) { lHitActorCore = lWeaponCore.Owner.GetComponent<IDamageable>(); } // } //} // Save the hit information Transform lHitTransform = GetClosestTransform(rHitInfo.Point, rHitInfo.Collider.transform); //Vector3 lCombatCenter = lHitTransform.position; //Vector3 lHitDirection = Vector3.zero; //if (lDefender != null) //{ // //lHitDirection = Quaternion.Inverse(lDefender.Transform.rotation) * (rHitInfo.Point - lDefender.CombatOrigin).normalized; //} //else //{ // //lHitDirection = Quaternion.Inverse(lHitTransform.rotation) * (rHitInfo.Point - lCombatCenter).normalized; //} // Determine if the projectile sticks around after impact if (_EmbedOnImpact) { // To compensate for scaling, we use a "connector". This way, // the projectile doesn't scale even if the target does Vector3 lLocalScale = lHitTransform.lossyScale; lLocalScale.x = 1f / Mathf.Max(Mathf.Abs(lLocalScale.x), 0.0001f); lLocalScale.y = 1f / Mathf.Max(Mathf.Abs(lLocalScale.y), 0.0001f); lLocalScale.z = 1f / Mathf.Max(Mathf.Abs(lLocalScale.z), 0.0001f); GameObject lConnector = new GameObject(); lConnector.name = name + " connector"; lConnector.transform.parent = lHitTransform; lConnector.transform.localScale = lLocalScale; lConnector.transform.localPosition = lHitTransform.InverseTransformPoint(rHitInfo.Point); lConnector.transform.localRotation = Quaternion.identity; _Transform.parent = lConnector.transform; _Transform.localScale = Vector3.one; _Transform.localPosition = Vector3.zero; _Transform.forward = rHitInfo.Vector; } // Raise the impact event //mSpellAction.OnSuccess(); if (OnImpactEvent != null) { OnImpactEvent(this, rHitInfo); } }