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);
        }
    }
Пример #2
0
 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;
 }
Пример #3
0
 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;
 }
Пример #4
0
    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();
    }
Пример #5
0
    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;
                            }
                        }
                    }
                }
            }
        }
    }