protected static void UpdateAnimation(float deltaTime, BaseGameplayRule gameplayRule, CharacterAnimationComponent animationData, BaseCharacterEntity characterEntity, Transform transform) { if (characterEntity.isRecaching) { return; } // Update current velocity animationData.velocityCalculationDeltaTime += deltaTime; if (animationData.velocityCalculationDeltaTime >= UPDATE_VELOCITY_DURATION) { if (!animationData.previousPosition.HasValue) { animationData.previousPosition = transform.position; } var currentMoveDistance = transform.position - animationData.previousPosition.Value; animationData.currentVelocity = currentMoveDistance / animationData.velocityCalculationDeltaTime; animationData.previousPosition = transform.position; animationData.velocityCalculationDeltaTime = 0f; } var model = characterEntity.Model; if (model != null) { model.UpdateAnimation(characterEntity.CurrentHp <= 0, animationData.currentVelocity, gameplayRule.GetMoveSpeed(characterEntity) / characterEntity.CacheBaseMoveSpeed); } }
public static void SetWanderDestination(float time, BaseGameplayRule gameplayRule, MonsterCharacterEntity monsterCharacterEntity, NavMeshAgent navMeshAgent, Vector3 destination) { monsterCharacterEntity.setDestinationTime = time; monsterCharacterEntity.isWandering = true; monsterCharacterEntity.wanderDestination = destination; navMeshAgent.speed = gameplayRule.GetMoveSpeed(monsterCharacterEntity); navMeshAgent.obstacleAvoidanceType = ObstacleAvoidanceType.NoObstacleAvoidance; navMeshAgent.SetDestination(monsterCharacterEntity.wanderDestination.Value); navMeshAgent.isStopped = false; }
public static void SetDestination(float time, BaseGameplayRule gameplayRule, MonsterCharacterEntity monsterCharacterEntity, NavMeshAgent navMeshAgent, Vector3 targetPosition) { monsterCharacterEntity.setDestinationTime = time; monsterCharacterEntity.isWandering = false; navMeshAgent.speed = gameplayRule.GetMoveSpeed(monsterCharacterEntity); navMeshAgent.obstacleAvoidanceType = ObstacleAvoidanceType.MedQualityObstacleAvoidance; navMeshAgent.SetDestination(targetPosition); navMeshAgent.isStopped = false; monsterCharacterEntity.oldDestination = targetPosition; }
protected static void UpdateRecovery(float deltaTime, BaseGameplayRule gameplayRule, CharacterRecoveryComponent recoveryData, BaseCharacterEntity characterEntity) { if (characterEntity.isRecaching || characterEntity.CurrentHp <= 0 || !characterEntity.IsServer) { return; } recoveryData.recoveryUpdateDeltaTime += deltaTime; if (recoveryData.recoveryUpdateDeltaTime >= RECOVERY_UPDATE_DURATION) { // Hp recoveryData.recoveryingHp += recoveryData.recoveryUpdateDeltaTime * gameplayRule.GetRecoveryHpPerSeconds(characterEntity); if (characterEntity.CurrentHp < characterEntity.CacheMaxHp) { if (recoveryData.recoveryingHp >= 1) { var intRecoveryingHp = (int)recoveryData.recoveryingHp; characterEntity.CurrentHp += intRecoveryingHp; characterEntity.RequestCombatAmount(CombatAmountType.HpRecovery, intRecoveryingHp); recoveryData.recoveryingHp -= intRecoveryingHp; } } else { recoveryData.recoveryingHp = 0; } // Decrease Hp recoveryData.decreasingHp += recoveryData.recoveryUpdateDeltaTime * gameplayRule.GetDecreasingHpPerSeconds(characterEntity); if (characterEntity.CurrentHp > 0) { if (recoveryData.decreasingHp >= 1) { var intDecreasingHp = (int)recoveryData.decreasingHp; characterEntity.CurrentHp -= intDecreasingHp; recoveryData.decreasingHp -= intDecreasingHp; } } else { recoveryData.decreasingHp = 0; } // Mp recoveryData.recoveryingMp += recoveryData.recoveryUpdateDeltaTime * gameplayRule.GetRecoveryMpPerSeconds(characterEntity); if (characterEntity.CurrentMp < characterEntity.CacheMaxMp) { if (recoveryData.recoveryingMp >= 1) { var intRecoveryingMp = (int)recoveryData.recoveryingMp; characterEntity.CurrentMp += intRecoveryingMp; characterEntity.RequestCombatAmount(CombatAmountType.MpRecovery, intRecoveryingMp); recoveryData.recoveryingMp -= intRecoveryingMp; } } else { recoveryData.recoveryingMp = 0; } // Decrease Mp recoveryData.decreasingMp += recoveryData.recoveryUpdateDeltaTime * gameplayRule.GetDecreasingMpPerSeconds(characterEntity); if (characterEntity.CurrentMp > 0) { if (recoveryData.decreasingMp >= 1) { var intDecreasingMp = (int)recoveryData.decreasingMp; characterEntity.CurrentMp -= intDecreasingMp; recoveryData.decreasingMp -= intDecreasingMp; } } else { recoveryData.decreasingMp = 0; } // Stamina recoveryData.recoveryingStamina += recoveryData.recoveryUpdateDeltaTime * gameplayRule.GetRecoveryStaminaPerSeconds(characterEntity); if (characterEntity.CurrentStamina < characterEntity.CacheMaxStamina) { if (recoveryData.recoveryingStamina >= 1) { var intRecoveryingStamina = (int)recoveryData.recoveryingStamina; characterEntity.CurrentStamina += intRecoveryingStamina; characterEntity.RequestCombatAmount(CombatAmountType.StaminaRecovery, intRecoveryingStamina); recoveryData.recoveryingStamina -= intRecoveryingStamina; } } else { recoveryData.recoveryingStamina = 0; } // Decrease Stamina while sprinting recoveryData.decreasingStamina += recoveryData.recoveryUpdateDeltaTime * gameplayRule.GetDecreasingStaminaPerSeconds(characterEntity); if (characterEntity.isSprinting && characterEntity.CurrentStamina > 0) { if (recoveryData.decreasingStamina >= 1) { var intDecreasingStamina = (int)recoveryData.decreasingStamina; characterEntity.CurrentStamina -= intDecreasingStamina; recoveryData.decreasingStamina -= intDecreasingStamina; } } else { recoveryData.decreasingStamina = 0; } // Food if (characterEntity.CurrentFood < characterEntity.CacheMaxFood) { if (recoveryData.recoveryingFood >= 1) { var intRecoveryingFood = (int)recoveryData.recoveryingFood; characterEntity.CurrentFood += intRecoveryingFood; characterEntity.RequestCombatAmount(CombatAmountType.FoodRecovery, intRecoveryingFood); recoveryData.recoveryingFood -= intRecoveryingFood; } } else { recoveryData.recoveryingFood = 0; } // Decrease Food recoveryData.decreasingFood += recoveryData.recoveryUpdateDeltaTime * gameplayRule.GetDecreasingFoodPerSeconds(characterEntity); if (characterEntity.CurrentFood > 0) { if (recoveryData.decreasingFood >= 1) { var intDecreasingFood = (int)recoveryData.decreasingFood; characterEntity.CurrentFood -= intDecreasingFood; recoveryData.decreasingFood -= intDecreasingFood; } } else { recoveryData.decreasingFood = 0; } // Water if (characterEntity.CurrentWater < characterEntity.CacheMaxWater) { if (recoveryData.recoveryingWater >= 1) { var intRecoveryingWater = (int)recoveryData.recoveryingWater; characterEntity.CurrentWater += intRecoveryingWater; characterEntity.RequestCombatAmount(CombatAmountType.WaterRecovery, intRecoveryingWater); recoveryData.recoveryingWater -= intRecoveryingWater; } } else { recoveryData.recoveryingWater = 0; } // Decrease Water recoveryData.decreasingWater += recoveryData.recoveryUpdateDeltaTime * gameplayRule.GetDecreasingWaterPerSeconds(characterEntity); if (characterEntity.CurrentWater > 0) { if (recoveryData.decreasingWater >= 1) { var intDecreasingWater = (int)recoveryData.decreasingWater; characterEntity.CurrentWater -= intDecreasingWater; recoveryData.decreasingWater -= intDecreasingWater; } } else { recoveryData.decreasingWater = 0; } recoveryData.recoveryUpdateDeltaTime = 0; } characterEntity.ValidateRecovery(); }
protected static void UpdateActivity(float time, GameInstance gameInstance, BaseGameplayRule gameplayRule, MonsterCharacterEntity monsterCharacterEntity, Transform transform, NavMeshAgent navMeshAgent) { if (!monsterCharacterEntity.IsServer || monsterCharacterEntity.MonsterDatabase == null) { return; } var monsterDatabase = monsterCharacterEntity.MonsterDatabase; if (monsterCharacterEntity.CurrentHp <= 0) { monsterCharacterEntity.StopMove(); monsterCharacterEntity.SetTargetEntity(null); if (time - monsterCharacterEntity.deadTime >= monsterDatabase.deadHideDelay) { monsterCharacterEntity.isHidding.Value = true; } if (time - monsterCharacterEntity.deadTime >= monsterDatabase.deadRespawnDelay) { monsterCharacterEntity.Respawn(); } return; } var currentPosition = transform.position; BaseCharacterEntity targetEntity; if (monsterCharacterEntity.TryGetTargetEntity(out targetEntity)) { if (targetEntity.CurrentHp <= 0) { monsterCharacterEntity.StopMove(); monsterCharacterEntity.SetTargetEntity(null); return; } // If it has target then go to target var targetEntityPosition = targetEntity.CacheTransform.position; var attackDistance = monsterCharacterEntity.GetAttackDistance(); attackDistance -= attackDistance * 0.1f; attackDistance -= navMeshAgent.stoppingDistance; attackDistance += targetEntity.CacheCapsuleCollider.radius; if (Vector3.Distance(currentPosition, targetEntityPosition) <= attackDistance) { SetStartFollowTargetTime(time, monsterCharacterEntity); // Lookat target then do anything when it's in range navMeshAgent.updateRotation = false; navMeshAgent.isStopped = true; var lookAtDirection = (targetEntityPosition - currentPosition).normalized; // slerp to the desired rotation over time if (lookAtDirection.magnitude > 0) { transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(lookAtDirection), navMeshAgent.angularSpeed * Time.deltaTime); } monsterCharacterEntity.RequestAttack(); // TODO: Random to use skills } else { // Following target navMeshAgent.updateRotation = true; if (monsterCharacterEntity.oldDestination != targetEntityPosition && time - monsterCharacterEntity.setDestinationTime >= SET_TARGET_DESTINATION_DELAY) { SetDestination(time, gameplayRule, monsterCharacterEntity, navMeshAgent, targetEntityPosition); } // Stop following target if (time - monsterCharacterEntity.startFollowTargetTime >= FOLLOW_TARGET_DURATION) { monsterCharacterEntity.StopMove(); monsterCharacterEntity.SetTargetEntity(null); return; } } } else { // Update rotation while wandering navMeshAgent.updateRotation = true; // While character is moving then random next wander time // To let character stop movement some time before random next wander time if ((monsterCharacterEntity.wanderDestination.HasValue && Vector3.Distance(currentPosition, monsterCharacterEntity.wanderDestination.Value) > navMeshAgent.stoppingDistance) || monsterCharacterEntity.oldDestination != currentPosition) { RandomNextWanderTime(time, monsterCharacterEntity, transform); } // Wandering when it's time if (time >= monsterCharacterEntity.wanderTime) { // If stopped then random var randomX = Random.Range(RANDOM_WANDER_AREA_MIN, RANDOM_WANDER_AREA_MAX) * (Random.value > 0.5f ? -1 : 1); var randomZ = Random.Range(RANDOM_WANDER_AREA_MIN, RANDOM_WANDER_AREA_MAX) * (Random.value > 0.5f ? -1 : 1); var randomPosition = monsterCharacterEntity.respawnPosition + new Vector3(randomX, 0, randomZ); NavMeshHit navMeshHit; if (NavMesh.SamplePosition(randomPosition, out navMeshHit, RANDOM_WANDER_AREA_MAX, 1)) { SetWanderDestination(time, gameplayRule, monsterCharacterEntity, navMeshAgent, navMeshHit.position); } } else { // If it's aggressive character, finding attacking target if (monsterDatabase.characteristic == MonsterCharacteristic.Aggressive && time >= monsterCharacterEntity.findTargetTime) { SetFindTargetTime(time, monsterCharacterEntity); BaseCharacterEntity targetCharacter; // If no target enenmy or target enemy is dead if (!monsterCharacterEntity.TryGetTargetEntity(out targetCharacter) || targetCharacter.CurrentHp <= 0) { // Find nearby character by layer mask var foundObjects = new List <Collider>(Physics.OverlapSphere(currentPosition, monsterDatabase.visualRange, gameInstance.characterLayer.Mask)); foundObjects = foundObjects.OrderBy(a => System.Guid.NewGuid()).ToList(); foreach (var foundObject in foundObjects) { var characterEntity = foundObject.GetComponent <BaseCharacterEntity>(); if (characterEntity != null && monsterCharacterEntity.IsEnemy(characterEntity)) { SetStartFollowTargetTime(time, monsterCharacterEntity); monsterCharacterEntity.SetAttackTarget(characterEntity); return; } } } } } } }