Exemple #1
0
    void IGameActor.TakeDamage(float damage, IGameActor attacker)
    {
        damagedThisFrame = true;

        // TODO Loot.
        CurrentHealth -= damage;
        if (CurrentHealth <= 0.0f && CurrentAiState == EAiState.WalkingAndFighting)
        {
            CurrentAiState = EAiState.Dying;
            if (isBoss)
            {
                CrashdownGameRoot.TotalBossesKilled++;
            }
            else
            {
                CrashdownGameRoot.TotalEnemiesKilled++;
            }
            if (deathEffect != null)
            {
                CosmeticEffect.Spawn(deathEffect, deathEffect.defaultLifetime, transform.position, Quaternion.identity);
            }
        }
        else if (CurrentAiState == EAiState.WalkingAndFighting)
        {
            if (hurtEffect != null)
            {
                CosmeticEffect.Spawn(hurtEffect, hurtEffect.defaultLifetime, transform.position, Quaternion.identity);
            }
        }
        if (CurrentAggroTarget == null)
        {
            CurrentAggroTarget = attacker;
        }
        RemainingEnrageDuration = enrageDuration;
        float staggerSign = Mathf.Sign(UnityEngine.Random.Range(-1.0f, 1.0f));

        CurrentSidewaysStaggerAmount = enrageSidewaysStaggerSpeed * staggerSign;
    }
Exemple #2
0
 private void Initialize(WeaponDefinition weapon, IGameActor owner, uint projectileId)
 {
     MyWeaponData      = weapon;
     MyOwner           = owner;
     RemainingLifetime = weapon.lifetime;
     RemainingHits     = weapon.maximumEnemiesHit;
     MyId = projectileId;
     if (weapon.projectileLockedEffect != null)
     {
         spawnedEffect = CosmeticEffect.Spawn(weapon.projectileLockedEffect, weapon.lifetime, transform.position, transform.rotation, this.transform);
         dummyRenderer.SetActive(false);
     }
     else
     {
         dummyRenderer.SetActive(!weapon.hiddenAttack);
     }
     // Don't spawn the actorsHitByProjectile array until it actually hits something.
     if (weapon.reflectsOtherAttacks)
     {
         reflectionCollider.gameObject.SetActive(true);
         reflectionCollider.radius = weapon.radius;
         reflectingColliders[reflectionCollider] = MyOwner;
     }
 }
Exemple #3
0
    private void UpdatePlayers()
    {
        Vector3 cameraAveragedTargetPosition = Vector3.zero;
        int     numberOfCameraTargets        = 0;

        // Flatten out inputs relative to the camera.
        Vector3 inputRight = Camera.main.transform.right;

        inputRight.y = 0.0f;
        inputRight   = inputRight.normalized;
        Vector3 inputUp = Camera.main.transform.up;

        inputUp.y = 0.0f;
        inputUp   = inputUp.normalized;

        bool allPlayersDead = true;

        foreach (CrashdownPlayerController player in CrashdownPlayerController.activePlayerInstances)
        {
            if (!player.IsDead())
            {
                allPlayersDead = false;

                bool debugPlayerIsWalkingAround = true;
                if (debugPlayerIsWalkingAround)
                {
                    Vector3 playerMovementThisFrame = Vector3.zero;

                    bool isDodging = player.RemainingDodgeTime > 0.0f;
                    if (player.CrashdownTarget.HasValue)
                    {
                        // Don't take any input or do any lateral movement.
                    }
                    else if (!isDodging)
                    {
                        Vector2 input = player.InputMovementThisFrame;
                        // Don't make diagonal walking any faster.
                        if (input.sqrMagnitude > 1.0f)
                        {
                            input = input.normalized;
                        }

                        Vector3 worldspaceInput = inputRight * input.x + inputUp * input.y;
                        if (worldspaceInput != Vector3.zero)
                        {
                            player.CurrentFacing = worldspaceInput.normalized;
                        }

                        playerMovementThisFrame = worldspaceInput * player.GetMaxSpeed() * Time.deltaTime;
                    }
                    else
                    {
                        playerMovementThisFrame = player.CurrentFacing * player.GetDodgeSpeed() * Time.deltaTime;
                    }
                    float previousDodgeTime = player.RemainingDodgeTime;
                    player.RemainingDodgeTime -= Time.deltaTime;
                    if (previousDodgeTime >= -player.playerDodgeRefreshDuration && player.RemainingDodgeTime < -player.playerDodgeRefreshDuration)
                    {
                        player.RemainingNumberOfDodges = player.MaximumNumberOfDodges;
                        if (player.RemainingNumberOfDodges > 0)
                        {
                            CosmeticEffect.Spawn(player.playerDodgeRefreshEffect, player.playerDodgeRefreshEffect.defaultLifetime,
                                                 player.transform.position, Quaternion.identity, player.transform);
                        }
                    }

                    // Move on the X and Z axes separately so the player can slide along walls.
                    for (int i = 0; i < 2; i++)
                    {
                        Vector3 newPosition;
                        switch (i)
                        {
                        case 0:
                            newPosition = player.transform.position + new Vector3(playerMovementThisFrame.x, 0.0f, 0.0f);
                            break;

                        default:
                            newPosition = player.transform.position + new Vector3(0.0f, 0.0f, playerMovementThisFrame.z);
                            break;
                        }
                        if (playerMovementThisFrame.sqrMagnitude > 0.0f)
                        {
                            bool targetPositionIsOccupied  = false;
                            int  numberOfThingsInFrontOfMe = Physics.OverlapSphereNonAlloc(newPosition, player.height / 2.0f, cachedColliderHitArray, actorsLayer.value);
                            if (numberOfThingsInFrontOfMe > 0)
                            {
                                for (int q = 0; q < numberOfThingsInFrontOfMe; q++)
                                {
                                    Collider possibleBlocker = cachedColliderHitArray[q];
                                    if (actorColliders.TryGetValue(possibleBlocker, out IGameActor blockerActor))
                                    {
                                        if (blockerActor is CrashdownEnemyActor &&
                                            (blockerActor as CrashdownEnemyActor).aiType == CrashdownEnemyActor.EAiType.InanimateObject)
                                        {
                                            targetPositionIsOccupied = true;
                                            if (debugPhysics)
                                            {
                                                Debug.Log("Player " + player.gameObject.name + " tried to walk into " + (blockerActor as CrashdownEnemyActor).gameObject.name, (blockerActor as CrashdownEnemyActor).gameObject);
                                            }
                                            break;
                                        }
                                    }
                                }
                            }
                            bool targetPositionIsOverFloor = Physics.Raycast(newPosition, Vector3.down, out RaycastHit floorHit, player.height * 2.0f, terrainLayer.value);

                            if (!targetPositionIsOccupied)
                            {
                                if (targetPositionIsOverFloor)
                                {
                                    newPosition = floorHit.point + Vector3.up * (player.height / 2.0f);
                                    player.transform.position = newPosition;
                                    if (debugPhysics)
                                    {
                                        Debug.Log("Player " + player.gameObject.name + " is walking on " + floorHit.collider.gameObject.name + " and moved to " + newPosition, floorHit.collider.gameObject);
                                    }
                                }
                                else
                                {
                                    // Player tried to walk off an edge, so they should stop and not move there.
                                    if (debugPhysics)
                                    {
                                        Debug.Log("Player " + player.gameObject.name + " tried to walk off an edge.", player.gameObject);
                                    }
                                }
                            }
                        }
                    }

                    if (_currentControlScheme == _mouseAndKeyboardScheme)
                    {
                        Vector2 mousePosition = _aimAction.ReadValue <Vector2>();

                        Plane plane = new Plane(Vector3.up, player.transform.position);

                        float distance;
                        Ray   ray = Camera.main.ScreenPointToRay(mousePosition);

                        if (plane.Raycast(ray, out distance))
                        {
                            var point  = ray.GetPoint(distance);
                            var vector = point - player.transform.position;
                            player.CurrentAiming = vector.normalized;
                        }
                        else
                        {
                            player.CurrentAiming = player.CurrentFacing;
                        }
                    }
                    else
                    {
                        player.CurrentAiming = player.CurrentFacing;
                    }

                    player.UpdateFacingAndRenderer();

                    // Player Attacks
                    if (player.RemainingWeaponCooldown <= 0.0f && player.InputAttackDownThisFrame && player.TryGetCurrentWeapon(out WeaponDefinition weapon))
                    {
                        // TODO Cooldowns and so on.
                        ActorUsesWeapon(player, weapon, projectilePrefab);
                        player.RemainingWeaponCooldown = weapon.cooldown;
                    }
                    else
                    {
                        player.RemainingWeaponCooldown -= Time.deltaTime;
                    }

                    // Player Dodges
                    if (player.InputDodgeDownThisFrame)
                    {
                        bool canDodge = true;
                        if (player.IsDodging() ||
                            player.RemainingNumberOfDodges <= 0)
                        {
                            canDodge = false;
                        }

                        if (canDodge)
                        {
                            player.RemainingDodgeTime      = player.GetDodgeDuration();
                            player.StartedDodgingThisFrame = true;
                            player.RemainingNumberOfDodges--;
                            CosmeticEffect.Spawn(player.playerDodgeEffect, player.playerDodgeEffect.defaultLifetime,
                                                 player.transform.position, player.transform.rotation);
                        }
                    }

                    // Player Crashdown
                    if (player.CrashdownTarget.HasValue)
                    {
                        const float kDefaultCrashdownDuration = 1.5f;
                        if (player.CurrentCrashdownTime <= kDefaultCrashdownDuration)
                        {
                            // Crashdown Update Tick
                            player.CurrentCrashdownTime += Time.deltaTime;
                            const float kCrashdownPhaseOneDuration = 1.0f;
                            const float kPlayerRiseDuringCrashdown = 20.0f;
                            if (player.CurrentCrashdownTime < kCrashdownPhaseOneDuration)
                            {
                                player.transform.position += Vector3.up * Time.deltaTime * kPlayerRiseDuringCrashdown / kCrashdownPhaseOneDuration;
                            }
                            else
                            {
                                float distanceToMoveThisFrame = (CrashdownLevelParent.kExpectedDistanceBetweenFloors + kPlayerRiseDuringCrashdown) / (kDefaultCrashdownDuration - kCrashdownPhaseOneDuration) * Time.deltaTime;
                                player.transform.position = Vector3.MoveTowards(player.transform.position, player.CrashdownTarget.Value, distanceToMoveThisFrame);;
                            }
                        }
                        else
                        {
                            // Crashdown Exit
                            player.transform.position = player.CrashdownTarget.Value + Vector3.up * player.height / 2.0f;
                            ActorUsesWeapon(player, player.crashdownSmashWeapon, projectilePrefab);
                            // spawn here.
                            CosmeticEffect.Spawn(crashdownCosmeticEffect, 2, player.transform.position, Quaternion.identity);
                            player.CrashdownTarget = null;

                            foreach (GameObject o in DisposeOnLevelChange)
                            {
                                if (o != null)
                                {
                                    o.SetActive(false);
                                }
                            }
                            DisposeOnLevelChange.Clear();

                            float levelCutoff = player.transform.position.y + CrashdownLevelParent.kExpectedDistanceBetweenFloors / 2.0f;
                            while (CrashdownLevelParent.activeCrashdownLevels.Count > 0 &&
                                   CrashdownLevelParent.activeCrashdownLevels.Values[0].transform.position.y > levelCutoff)
                            {
                                CrashdownLevelParent.activeCrashdownLevels.Values[0].Dispose();
                            }
                        }
                    }
                    else if (player.HasCrashdownAttack)
                    {
                        if (player.InputCrashdownDownThisFrame)
                        {
                            if (Physics.Raycast(player.transform.position + Vector3.down * player.height * 2.0f, Vector3.down,
                                                out RaycastHit raycastHit, CrashdownLevelParent.kExpectedDistanceBetweenFloors * 1.5f, terrainLayer.value))
                            {
                                // Crashdown Start
                                player.StartedCrashdownThisFrame = true;
                                Vector3 targetPoint = raycastHit.point;
                                player.CrashdownTarget      = targetPoint;
                                player.CurrentCrashdownTime = 0.0f;
                                player.HasCrashdownAttack   = false;
                                crashdownPromptRoot.SetActive(false);
                                player.CurrentFacing = Vector3.back;
                                AudioManager.instance.PlaySound(crashdownStartToFinishSound, player.transform.position);
                            }
                            else
                            {
                                AudioManager.instance.PlaySound(sound_UiFailToCrashdown, player.transform.position);
                            }
                        }
                        _currentCrashdownPromptFlash = Mathf.Repeat(_currentCrashdownPromptFlash + Time.deltaTime, 1.0f);
                        crashdownText.color          = crashdownTextColorGradient.Evaluate(_currentCrashdownPromptFlash);
                        // Force the player to use the ability by slowly draining their health while they have it.
                        player.CurrentHealth          -= player.crashdownHealthDrainPerSecond * Time.deltaTime;
                        player.CurrentHealthRegenDelay = 1.0f;
                    }

                    // Player Interactions & Secret Areas
                    int numberOfInteractions = Physics.OverlapSphereNonAlloc(player.transform.position, player.height / 2.0f, cachedColliderHitArray, interactionsLayer.value);
                    if (numberOfInteractions > 0)
                    {
                        // Only handle the first interaction, overlapping could get messy.
                        bool hasFoundAnInteraction = false;
                        for (int interactionIndex = 0; interactionIndex < numberOfInteractions; interactionIndex++)
                        {
                            Collider thisInteractionCollider = cachedColliderHitArray[interactionIndex];
                            if (!hasFoundAnInteraction && PlayerInteraction.activeInteractions.TryGetValue(thisInteractionCollider, out PlayerInteraction thisInteraction))
                            {
                                thisInteraction.OnPlayerStaysThisFrame();
                                hasFoundAnInteraction = true;
                                if (player.InputInteractDownThisFrame)
                                {
                                    switch (thisInteraction.interactionType)
                                    {
                                    case PlayerInteraction.EInteractionType.HealthPowerUp:
                                        player.MaxHealth    *= player.playerHealthBoostMultiplier;
                                        player.CurrentHealth = player.MaxHealth;
                                        float playerHealthRatio = player.MaxHealth / player.playerStartingHealth;
                                        AudioManager.instance.PlaySound(getPowerupSound, player.transform.position);
                                        break;

                                    case PlayerInteraction.EInteractionType.WeaponPickup:
                                        player.SetCurrentWeapon(thisInteraction.weaponDefinition);
                                        FinalWeaponUsed = thisInteraction.weaponDefinition?.hudAndHighScoreName;
                                        currentWeaponSprites[0].sprite = thisInteraction.weaponDefinition.pickupAndHudSprite;
                                        currentWeaponSprites[0].color  = Color.white;
                                        AudioManager.instance.PlaySound(getPowerupSound, player.transform.position);
                                        break;

                                    case PlayerInteraction.EInteractionType.DodgePowerUp:
                                        player.MaximumNumberOfDodges++;
                                        player.RemainingNumberOfDodges = player.MaximumNumberOfDodges;
                                        AudioManager.instance.PlaySound(getPowerupSound, player.transform.position);
                                        break;

                                    case PlayerInteraction.EInteractionType.CrashdownKey:
                                        player.HasCrashdownAttack = true;
                                        player.CurrentHealth      = player.MaxHealth; // Fully heal the player so the key can't instakill them.
                                        AudioManager.instance.PlaySound(getPowerupSound, player.transform.position);
                                        crashdownPromptRoot.gameObject.SetActive(true);
                                        break;

                                    case PlayerInteraction.EInteractionType.WinTheGame:
                                        AudioManager.instance.PlaySound(getPowerupSound, player.transform.position);
                                        AudioManager.instance.PlaySound(gameGlitchSound, player.transform.position);
                                        nextSceneIndexToLoad    = thisInteraction.targetSceneIndex;
                                        glitchRenderer.enabled  = true;
                                        glitchRenderer.material = glitchRendererStages[0];
                                        break;

                                    case PlayerInteraction.EInteractionType.Nothing:
                                        // This object is not interactable, but it can show a tutorial text message when the player is near it.
                                        break;

                                    case PlayerInteraction.EInteractionType.ToggleSomething:
                                        if (thisInteraction.interactionCoolDown <= 0f)
                                        {
                                            thisInteraction.interactionCoolDown = buttonInteractCoolDown;
                                            AudioManager.instance.PlaySound(buttonPressSound, player.transform.position);
                                            foreach (GameObject thing in thisInteraction.objectsToToggle)
                                            {
                                                bool toggle = thing.activeInHierarchy;
                                                thing.SetActive(!toggle);
                                            }
                                        }
                                        break;

                                    default:
                                        Debug.LogError("TODO: " + thisInteraction.interactionType.ToString());
                                        break;
                                    }
                                    if (thisInteraction.removeAfterActivation)
                                    {
                                        GameObject.Destroy(thisInteraction.gameObject);
                                    }
                                    else
                                    {
                                        thisInteraction.interactedWithThisFrame = true;
                                    }
                                }
                            }
                            else if (SecretAreaTrigger.activeSecretAreas.TryGetValue(thisInteractionCollider, out SecretAreaTrigger secretArea))
                            {
                                // But do check for all secret areas, don't want to miss one because you landed on a weapon but skipped it.
                                // Trigger Secret Areas On Enter
                                if (!SecretAreasFound.Contains(secretArea))
                                {
                                    SecretAreasFound.Add(secretArea);
                                }
                            }
                        }
                    }

                    // Player Health Regen

                    if (player.CurrentHealthRegenDelay <= 0.0f)
                    {
                        if (player.CurrentHealth < player.MaxHealth)
                        {
                            float regenThisFrame = player.MaxHealth / player.playerFullRegenWait * Time.deltaTime;
                            if (debugCombat)
                            {
                                Debug.Log("Player is regenerating " + regenThisFrame);
                            }
                            player.CurrentHealth = Mathf.Min(player.MaxHealth, player.CurrentHealth + regenThisFrame);
                        }
                    }
                    else
                    {
                        player.CurrentHealthRegenDelay -= Time.deltaTime;
                        if (debugCombat)
                        {
                            Debug.Log("Player has " + player.CurrentHealthRegenDelay + " seconds until they begin to regenerate.");
                        }
                    }
                }

                cameraAveragedTargetPosition += player.transform.position;
                numberOfCameraTargets++;
            }
            //player.InputAttackDownThisFrame = false;
            //player.InputDodgeDownThisFrame = false;
            //player.InputCrashdownDownThisFrame = false;
            //player.InputInteractDownThisFrame = false;

            float playerHealthAmount = player.CurrentHealth / player.MaxHealth;
            playerHealthBar.SetMaxHealth((int)player.MaxHealth);
            playerHealthBar.SetHealth((int)player.CurrentHealth);

            if (player.HasCrashdownAttack)
            {
                playerHealthBar.SetColor(crashdownText.color = crashdownTextColorGradient.Evaluate(_currentCrashdownPromptFlash));
            }
        }