public override void Update(Microsoft.Xna.Framework.GameTime gameTime, BoundingFrustum cameraFrustum, SwimmingObject[] enemies, int enemiesSize, SwimmingObject[] fish, int fishSize, int changeDirection, HydroBot tank, List<DamageBullet> enemyBullet) { EffectHelpers.GetEffectConfiguration(ref fogColor, ref ambientColor, ref diffuseColor, ref specularColor); if (lastPower != HydroBot.turtlePower) { float lastMaxHealth = maxHealth; maxHealth = GameConstants.TurtleStartingHealth * HydroBot.turtlePower; health += (maxHealth - lastMaxHealth); speedFactor = 1.5f + (HydroBot.turtlePower - 1) / 4; lastPower = HydroBot.turtlePower; } BaseEnemy potentialEnemy = lookForEnemy(enemies, enemiesSize); if (!isReturnBot && !isCasting && potentialEnemy != null) { // It is OK to cast? if (PoseidonGame.playTime.TotalSeconds - lastCast.TotalSeconds > coolDown.TotalSeconds)// && HydroBot.currentHitPoint < HydroBot.maxHitPoint) { isCasting = true; isReturnBot = false; isWandering = false; isChasing = false; isFighting = false; // For this case, I choose to set the forward direction statically rather than // facing different enemy since potentialEnemy may die, run away, etc Vector3 facingDirection = potentialEnemy.Position - Position; ForwardDirection = (float)Math.Atan2(facingDirection.X, facingDirection.Z); firstCast = true; startCasting = PoseidonGame.playTime; PoseidonGame.audio.frozenBreathe.Play(); } } if (isCasting == true) { // Casting timeout if (PoseidonGame.playTime.TotalSeconds - startCasting.TotalSeconds > standingTime.TotalSeconds) { isCasting = false; // Done casting isWandering = true; // Let the wander state do the wandering task, (and also lock enemy is potential enemy != null) lastCast = PoseidonGame.playTime; } // Effect during cast else { FrozenBreathe(enemies, enemiesSize, firstCast); firstCast = false; } RestoreNormalAnimation(); } Vector3 destination = tank.Position + new Vector3(AfterX, 0, AfterZ); if (isWandering == true) { // If the fish is far from the point after the bot's back or is the bot moving if (Vector3.Distance(tank.Position, Position) > HydroBot.controlRadius || (tank.isMoving() && Vector3.Distance(tank.Position, Position) > 50f)) { isWandering = false; isReturnBot = true; isChasing = false; isFighting = false; seekDestination(destination, enemies, enemiesSize, fish, fishSize, tank, speedFactor); } else { currentTarget = potentialEnemy; if (currentTarget == null) // See no enemy randomWalk(changeDirection, enemies, enemiesSize, fish, fishSize, tank); else { // Hunt him down isWandering = false; isReturnBot = false; isChasing = true; isFighting = false; seekDestination(currentTarget.Position, enemies, enemiesSize, fish, fishSize, tank, speedFactor); } } }// End wandering // If return is the current state else if (isReturnBot == true) { // If the fish is near the point after the bot's back, wander if (Vector3.Distance(destination, Position) < HydroBot.controlRadius * 0.5 && Vector3.Distance(tank.Position, Position) < HydroBot.controlRadius) { float test = Vector3.Distance(destination, Position); isWandering = true; isReturnBot = false; isChasing = false; isFighting = false; randomWalk(changeDirection, enemies, enemiesSize, fish, fishSize, tank); } else seekDestination(destination, enemies, enemiesSize, fish, fishSize, tank, speedFactor); } // If the fish is chasing some enemy else if (isChasing == true) { if (Vector3.Distance(tank.Position, Position) > HydroBot.controlRadius * 1.25f) { // If too far, return to bot isWandering = false; isReturnBot = true; isChasing = false; isFighting = false; currentTarget = null; seekDestination(destination, enemies, enemiesSize, fish, fishSize, tank, speedFactor); } else if (Vector3.Distance(Position, currentTarget.Position) < 5f + BoundingSphere.Radius + currentTarget.BoundingSphere.Radius) // Too close then attack { isWandering = false; isReturnBot = false; isChasing = false; isFighting = true; attack(); } else seekDestination(currentTarget.Position, enemies, enemiesSize, fish, fishSize, tank, speedFactor); } // If fighting some enemy else if (isFighting == true) { // Enemy is down, return to bot if (currentTarget == null || currentTarget.health <= 0) { isWandering = false; isReturnBot = true; isChasing = false; isFighting = false; currentTarget = null; seekDestination(destination, enemies, enemiesSize, fish, fishSize, tank, speedFactor); } else { // If the enemy ran away and the fish is not too far from bot if (Vector3.Distance(tank.Position, Position) >= HydroBot.controlRadius) { isWandering = false; isReturnBot = true; isChasing = false; isFighting = false; currentTarget = null; seekDestination(destination, enemies, enemiesSize, fish, fishSize, tank, speedFactor); } // Or enemy ran away else if (Vector3.Distance(Position, currentTarget.Position) >= 10f + BoundingSphere.Radius + currentTarget.BoundingSphere.Radius) { isWandering = false; isReturnBot = false; isChasing = true; isFighting = false; seekDestination(currentTarget.Position, enemies, enemiesSize, fish, fishSize, tank, speedFactor); } else attack(); } } // if clip player has been initialized, update it if (clipPlayer != null || BoundingSphere.Intersects(cameraFrustum)) { qRotation = Quaternion.CreateFromAxisAngle( Vector3.Up, ForwardDirection); float scale = 0.7f; if (isBigBoss) scale *= 2.0f; fishMatrix = Matrix.CreateScale(scale) * Matrix.CreateRotationY((float)MathHelper.Pi * 2) * Matrix.CreateFromQuaternion(qRotation) * Matrix.CreateTranslation(Position); clipPlayer.update(gameTime.ElapsedGameTime, true, fishMatrix); } }