/// <summary> /// Called each frame /// </summary> private void Update() { if (!IsActive) { return; } if (mCombatant == null) { return; } if (Target == null) { return; } MotionControllerMotion lMotion = mMotionController.ActiveMotion; if (lMotion == null) { return; } MotionControllerMotion lTargetMotion = mTargetMotionController.ActiveMotion; // Determine if we rotate to the target bool lRotate = true; // Ensure our weapon is equipped //if (!mBasicInventory.IsWeaponSetEquipped(2)) //{ // if (mLastEquipTime + AttackDelay < Time.time) // { // mBasicInventory.EquipWeaponSet(2); // mLastEquipTime = Time.time; // } //} //// The main AI loop //else //{ Vector3 lToTarget = Target._Transform.position - transform.position; lToTarget.y = 0f; Vector3 lToTargetDirection = lToTarget.normalized; float lToTargetDistance = lToTarget.magnitude; bool lIsTargetAimingAtMe = false; #if USE_ARCHERY_MP || OOTII_AYMP //float lTargetToMeHorizontalAngle = NumberHelper.GetHorizontalAngle(Target._Transform.forward, -lToTargetDirection, Target._Transform.up); //lIsTargetAimingAtMe = ((lTargetMotion is Bow_WalkRunTarget || lTargetMotion is Bow_BasicAttacks) && Mathf.Abs(lTargetToMeHorizontalAngle) < 10f); #endif // Determine if we should move to the target float lRange = Range; if (!mFollow && lToTargetDistance > lRange + 1f) { mFollow = true; } if (mFollow && lToTargetDistance <= lRange) { mFollow = false; } if (mFollow && (lMotion.Category != EnumMotionCategories.IDLE && lMotion.Category != EnumMotionCategories.WALK)) { mFollow = false; } if (mFollow && lIsTargetAimingAtMe) { mFollow = false; } if (!Move) { mFollow = false; } // Ensure we're not casting if (mMotionController.ActiveMotion is BasicSpellCasting) { } // Cast a healing spell else if (Cast && mLastCastTime + CastDelay < Time.time && mBasicAttributes != null && mBasicAttributes.GetAttributeValue <float>("Health", 100f) < 40f && mSpellInventory != null && mSpellInventory.GetSpellIndex("Heal Self") >= 0) { int lSpellIndex = mSpellInventory.GetSpellIndex("Heal Self"); if (lSpellIndex >= 0) { BasicSpellCasting lCastMotion = mMotionController.GetMotion <BasicSpellCasting>(); mMotionController.ActivateMotion(lCastMotion, lSpellIndex); mLastCastTime = Time.time; } } // Move to the target else if (mFollow) { float lSpeed = Mathf.Min(MovementSpeed * Time.deltaTime, lToTargetDistance); transform.position = transform.position + (lToTargetDirection * lSpeed); } // If we're being shot at, block else if (Block && lIsTargetAimingAtMe) { mFollow = false; CombatMessage lMessage = CombatMessage.Allocate(); lMessage.ID = CombatMessage.MSG_COMBATANT_BLOCK; lMessage.Attacker = null; lMessage.Defender = gameObject; mMotionController.SendMessage(lMessage); CombatMessage.Release(lMessage); } // Let the movement finish up else if (lMotion.Category == EnumMotionCategories.WALK) { } // Attack with the sword else if (Attack && lMotion.Category == EnumMotionCategories.IDLE && (mLastAttackTime + AttackDelay < Time.time)) { CombatMessage lMessage = CombatMessage.Allocate(); lMessage.ID = CombatMessage.MSG_COMBATANT_ATTACK; lMessage.Attacker = gameObject; lMessage.Defender = Target.gameObject; mMotionController.SendMessage(lMessage); CombatMessage.Release(lMessage); mLastAttackTime = Time.time; } // Block with the shield else if (Block && lMotion.Category == EnumMotionCategories.IDLE && lMotion.Age > 0.5f) { CombatMessage lMessage = CombatMessage.Allocate(); lMessage.ID = CombatMessage.MSG_COMBATANT_BLOCK; lMessage.Attacker = null; lMessage.Defender = gameObject; mMotionController.SendMessage(lMessage); CombatMessage.Release(lMessage); } // Free the block else if (lMotion.Category == EnumMotionCategories.COMBAT_MELEE_BLOCK && (lToTargetDistance > lRange + 1f || lMotion.Age > BlockHold)) { CombatMessage lMessage = CombatMessage.Allocate(); lMessage.ID = CombatMessage.MSG_COMBATANT_CANCEL; lMessage.Attacker = null; lMessage.Defender = gameObject; mMotionController.SendMessage(lMessage); CombatMessage.Release(lMessage); } // Allow rotation only if (mMotionController.enabled && lRotate) { float lAngle = NumberHelper.GetHorizontalAngle(transform.forward, lToTargetDirection, transform.up); if (lAngle != 0f) { float lRotationSpeed = Mathf.Sign(lAngle) * Mathf.Min(RotationSpeed * Time.deltaTime, Mathf.Abs(lAngle)); transform.rotation = transform.rotation * Quaternion.AngleAxis(lRotationSpeed, transform.up); } } //} // If we're dead, we can just stop if (lMotion.Category == EnumMotionCategories.DEATH) { IsActive = false; } // Clear the target if they are dead else if (Target != null && !Target.enabled) { Target = null; //StartCoroutine(WaitAndStoreEquipment(2f)); } }