Exemple #1
0
    /// <summary>
    /// Take damage from an attacker
    /// </summary>
    /// <param name="attacker">Stats controller of the attacking entity</param>
    /// <param name="damageValue">Approximate damage value to apply to enemy health</param>
    /// <param name="timeDelta">Time since last damage calculation</param>
    public override void TakeDamage(EntityStatsController attacker, float damageValue, float timeDelta = 1f)
    {
        // Ignore attacks if already dead or invincible
        if (isDead || invincible)
        {
            return;
        }

        float colourDamagePercentage = characterColour == CharacterColour.All || attacker.characterColour == characterColour ? 1 : colourResistanceModifier;

        // Calculate any changes based on stats and modifiers here first
        float hitValue = Mathf.Max(colourDamagePercentage * (damageValue - ComputeDefenseModifier()), 0) * timeDelta;

        health.Subtract(hitValue);
        ShowDamage(hitValue);
        Anim.SetTrigger("TakeDamage");

        // Pass damage information to brain
        Brain.OnDamageTaken(attacker.gameObject, hitValue);

        if (Mathf.Approximately(health.CurrentValue, 0f))
        {
            Die();
        }
    }
Exemple #2
0
        public void Interactable_CanInteract_FalseIfOutOfRange()
        {
            GameObject gameObject = new GameObject();
            Transform  objPos     = gameObject.GetComponent <Transform>();

            objPos.position = Vector3.up; //position (0,1,0)
            Interactable interactable = gameObject.AddComponent <Interactable>();

            interactable.colour = CharacterColour.Red; //set target and 'player' colour to RED

            //variables for 'player'
            GameObject player    = new GameObject();
            Transform  playerPos = player.GetComponent <Transform>();

            playerPos.position = Vector3.zero; //position (0,0,0)
            EntityStatsController playerControl = player.AddComponent <EntityStatsController>();

            playerControl.characterColour = CharacterColour.Red;//set player colour to Red to start
            Assert.False(interactable.CanInteract(playerPos));


            objPos.position = new Vector3(0, 2, 0); //position (0,2,0)
            //interactible radius is still 1, test it is now out of range
            Assert.False(interactable.CanInteract(playerPos));


            objPos.position = new Vector3(235463, 235463, 235463); //arbitrarily far
            //interactible radius is still 1, test it is now out of range
            Assert.False(interactable.CanInteract(playerPos));

            Object.DestroyImmediate(gameObject);
            //Object.Destroy(player);
        }
    /// <summary>
    /// Take damage from an attacker
    /// </summary>
    /// <param name="attacker">Stats controller of the attacking entity</param>
    /// <param name="damageValue">Approximate damage value to apply to enemy health</param>
    /// <param name="timeDelta">Time since last damage calculation</param>
    public override void TakeDamage(EntityStatsController attacker, float damageValue, float timeDelta = 1f)
    {
        // Ignore attacks if already dead
        if (isDead)
        {
            return;
        }

        if (characterColour != CharacterColour.All && attacker.characterColour != characterColour)
        {
            return;
        }

        // Calculate any changes based on stats and modifiers here first
        float hitValue = Mathf.Max(damageValue - ComputeDefenseModifier(), 0) * timeDelta;

        health.Subtract(hitValue);
        ShowDamage(hitValue);
        Anim.SetTrigger("TakeDamage");

        // Pass damage information to brain
        _brain.OnDamageTaken(attacker.gameObject, hitValue);

        if (Mathf.Approximately(health.CurrentValue, 0f))
        {
            Die();
        }
    }
    private void OnTriggerEnter(Collider other)
    {
        GameObject col = other.gameObject;

        // if other object is a player then deal damage
        if (col.CompareTag("Player"))
        {
            EntityStatsController target = col.GetComponent <EntityStatsController>();
            target.TakeDamage(Random.Range(minDamage, maxDamage));
            gameObject.SetActive(false);
        }
        else if (col.CompareTag("Ground"))
        {
            // Damage any players within impact radius
            float damage = Random.Range(minDamage, maxDamage);
            foreach (GameObject player in PlayerManager.Instance.AlivePlayers)
            {
                if (Vector3.Distance(transform.position, col.transform.position) <= impactRadius)
                {
                    player.GetComponent <EntityStatsController>().TakeDamage(damage);
                }
            }

            gameObject.SetActive(false);
        }
    }
Exemple #5
0
        public void Collectable_StartInteract_ObjectDeletedAfterInteract()
        {
            GameObject gameObject = new GameObject();
            Transform  objPos     = gameObject.GetComponent <Transform>();

            objPos.position = Vector3.zero; //position (0,0,0)
            Collectable collectable = gameObject.AddComponent <Collectable>();

            collectable.radius = 0f;                  //will not test as many for this
            collectable.colour = CharacterColour.Red; //set target and 'player' colour to same colour

            //variables for 'player'
            GameObject player    = new GameObject();
            Transform  playerPos = player.GetComponent <Transform>();

            playerPos.position = Vector3.zero; //position (0,0,0)
            EntityStatsController playerControl = player.AddComponent <EntityStatsController>();

            playerControl.characterColour = CharacterColour.Red;//set player colour to Red to start

            Assert.IsNotNull(gameObject);
            //we will have the player and collectable interact
            collectable.StartInteract(playerPos);
            Assert.IsNull(gameObject);

            Object.Destroy(gameObject);
            Object.Destroy(player);
        }
Exemple #6
0
        public void Interactable_CanInteract_FalseIfOutOfRangeAndWrongColour() //test a few to make sure double negative does not result in positive
        {
            GameObject gameObject = new GameObject();
            Transform  objPos     = gameObject.GetComponent <Transform>();

            objPos.position = Vector3.up; //position (0,1,0)
            Interactable interactable = gameObject.AddComponent <Interactable>();

            interactable.colour = CharacterColour.Red; //set target and 'player' colour to different colours

            //variables for 'player'
            GameObject player    = new GameObject();
            Transform  playerPos = player.GetComponent <Transform>();

            playerPos.position = Vector3.zero; //position (0,0,0)
            EntityStatsController playerControl = player.AddComponent <EntityStatsController>();

            playerControl.characterColour = CharacterColour.Green;//set player colour to Green to start

            Assert.False(interactable.CanInteract(playerPos));

            objPos.position = new Vector3(0, 2, 0); //position (0,2,0)
            //interactible radius is still 1, test it is out of range
            Assert.False(interactable.CanInteract(playerPos));

            //arbitrarily large number 235463
            objPos.position = new Vector3(732363, 732363, 732363); //arbitrarily far
            //interactible radius is still 0.9999, test it is now out of range
            Assert.False(interactable.CanInteract(playerPos));


            Object.DestroyImmediate(gameObject);
            Object.DestroyImmediate(player);
        }
 public void Launch(EntityStatsController launcherStats, Vector3 direction, float launchForce, float range, float damageAmount, float healAmount)
 {
     // Store the damage amount and call the base launch function
     _damageAmount = damageAmount;
     _healAmount   = healAmount;
     Launch(launcherStats, direction, launchForce, range);
 }
Exemple #8
0
    protected override void OnTriggerEnter(Collider other)
    {
        GameObject col = other.gameObject;

        // Ignore collisions with launcher or if currently being held
        if (col == LauncherStats.gameObject || _interactable.IsPickedUp)
        {
            return;
        }

        // if other object is a player, deal damage
        if (col.CompareTag("Player"))
        {
            EntityStatsController target = col.GetComponent <EntityStatsController>();
            target.TakeDamage(LauncherStats, Damage);
        }
        else if (col.CompareTag("Enemy") && LaunchedByPlayer)
        {
            RhakStatsController target = col.GetComponent <RhakStatsController>();

            // Ensure that the boss was hit
            if (target)
            {
                target.TakeDamageFromOrb(_colour);
            }
        }

        // Don't worry about collisions with colliders that are triggers
        if (!other.isTrigger)
        {
            gameObject.SetActive(false);
        }
    }
Exemple #9
0
    /// <summary>
    /// Perform damage on a target
    /// </summary>
    /// <param name="targetStats">Target's stats</param>
    /// <param name="damageValue">Damage value to apply</param>
    /// <param name="damageDelay">Time to wait before damage is applied</param>
    protected IEnumerator PerformDamage(EntityStatsController targetStats, float damageValue, float damageDelay = 0f)
    {
        if (damageDelay > 0f)
        {
            yield return(new WaitForSeconds(damageDelay));
        }

        // Applies damage to targetStats
        targetStats.TakeDamage(Stats, damageValue);
    }
Exemple #10
0
        public void Interactable_CanInteract_TrueIfInRangeAndColourMatches()
        {//set up testing variables for 'target'
            GameObject gameObject = new GameObject();
            Transform  objPos     = gameObject.GetComponent <Transform>();

            objPos.position = Vector3.one; //set both this and the 'player' to the same position
            Interactable interactable = gameObject.AddComponent <Interactable>();

            interactable.colour = CharacterColour.Red; //set target and 'player' colour to red

            //target.GetComponent<EntityStatsController>().characterColour

            //variables for 'player'
            GameObject player    = new GameObject();
            Transform  playerPos = player.GetComponent <Transform>();

            playerPos.position = Vector3.one;
            EntityStatsController playerControl = player.AddComponent <EntityStatsController>();

            playerControl.characterColour = CharacterColour.Red;//set player colour to red as well

            //assert that we can pick up an object in the same position as us, which matches colour
            Assert.True(interactable.CanInteract(playerPos));

            //assert for each additional colour
            interactable.colour           = CharacterColour.Green;
            playerControl.characterColour = CharacterColour.Green;
            Assert.True(interactable.CanInteract(playerPos));

            interactable.colour           = CharacterColour.Yellow;
            playerControl.characterColour = CharacterColour.Yellow;
            Assert.True(interactable.CanInteract(playerPos));

            interactable.colour           = CharacterColour.Blue;
            playerControl.characterColour = CharacterColour.Blue;
            Assert.True(interactable.CanInteract(playerPos));

            //assert for COLOURLESS object, with each player colour

            //at this point, player colour is still purple, so we don't need to set it again
            interactable.colour = CharacterColour.All;
            Assert.True(interactable.CanInteract(playerPos));
            //then check for each other colour with the interactable being NONE
            playerControl.characterColour = CharacterColour.Red;
            Assert.True(interactable.CanInteract(playerPos));

            playerControl.characterColour = CharacterColour.Yellow;
            Assert.True(interactable.CanInteract(playerPos));

            playerControl.characterColour = CharacterColour.Green;
            Assert.True(interactable.CanInteract(playerPos));

            Object.DestroyImmediate(gameObject);
            Object.DestroyImmediate(player);
        }
Exemple #11
0
    /// <summary>
    /// Perform explosive damage on a target
    /// </summary>
    /// <param name="targetStats">Target's stats</param>
    /// <param name="maxDamage">Maximum damage able to be dealt</param>
    /// <param name="stunTime">Number of seconds to stun damaged targets for</param>
    /// <param name="explosionForce">Force of the explosion</param>
    /// <param name="explosionPoint">Explosion origin</param>
    /// <param name="explosionRadius">Explosion effect radius</param>
    /// <param name="explosionDelay">Number of seconds before explosion affects targets</param>
    protected IEnumerator PerformExplosiveDamage(EntityStatsController targetStats, float maxDamage, float stunTime,
                                                 float explosionForce, Vector3 explosionPoint, float explosionRadius, float explosionDelay = 0f)
    {
        if (explosionDelay > 0f)
        {
            yield return(new WaitForSeconds(explosionDelay));
        }

        // Applies damage to targetStats
        targetStats.TakeExplosionDamage(Stats, maxDamage, stunTime, explosionForce, explosionPoint, explosionRadius);
    }
 /// <summary>
 /// Launch the damage projectile
 /// </summary>
 /// <param name="launcherStats">Stats of the entity that launched the projectile</param>
 /// <param name="direction">Direction to launch in</param>
 /// <param name="launchForce">Force to apply to the projectile upon launch</param>
 /// <param name="range">Maximum range that the projectile can fly</param>
 /// <param name="damage">Damage of the projectile</param>
 /// <param name="targetTag">The tag of the target type</param>
 public virtual void Launch(EntityStatsController launcherStats, Vector3 direction, float launchForce, float range, float damage, string targetTag = "Enemy")
 {
     // Store the damage amount and call the base launch function
     Damage    = damage;
     TargetTag = targetTag;
     if (targetTag == "Player")
     {
         AllyTag = "Enemy";
     }
     Launch(launcherStats, direction, launchForce, range);
 }
Exemple #13
0
    /// <summary>
    /// Place the explosive trap
    /// </summary>
    /// <param name="thrower">Stats of the entity that placed the trap</param>
    /// <param name="position">Position to place the trap</param>
    /// <returns></returns>
    public void PlaceTrap(EntityStatsController thrower, Vector3 position)
    {
        _thrower           = thrower;
        _isDetonated       = false;
        transform.position = position;
        _isArmed           = false;

        // Set self active
        gameObject.SetActive(true);
        StartCoroutine("ArmTrap");
    }
Exemple #14
0
        public void Setup()
        {
            entityStats         = new GameObject().AddComponent <EntityStatsController>();
            entityStats.damage  = new Stat();
            entityStats.defense = new Stat();
            entityStats.health  = new RegenerableStat();

            entityStats.damage.BaseValue  = 10;
            entityStats.defense.BaseValue = 10;
            entityStats.health.maxValue   = 100f;
            entityStats.health.Init();
        }
    protected override void OnTriggerEnter(Collider other)
    {
        GameObject col = other.gameObject;

        // if other object is an enemy, deal damage
        if (col.CompareTag(TargetTag))
        {
            EntityStatsController target = col.GetComponent <EntityStatsController>();
            target.TakeDamage(LauncherStats, Damage);
        }

        // Don't worry about collisions with the launcher or colliders that are triggers
        if (col != LauncherStats.gameObject && !other.isTrigger && other.tag != AllyTag)
        {
            gameObject.SetActive(false);
        }
    }
Exemple #16
0
 protected virtual void Awake()
 {
     Stats = GetComponent <EntityStatsController>();
     Anim  = GetComponentInChildren <Animator>();
     Audio = GetComponents <AudioSource>();
     // Assign audio sources for weapon and vocal SFX
     // There should be 2 audio sources to handle both SFX types playing concurrently
     if (Audio.Length == 2)
     {
         WeaponAudio = Audio[0];
         VocalAudio  = Audio[1];
     }
     else if (Audio.Length < 2)
     {
         WeaponAudio = Audio[0];
         VocalAudio  = Audio[0];
     }
 }
    protected override void OnTriggerEnter(Collider other)
    {
        GameObject col = other.gameObject;

        // if other object is an enemy, deal damage
        if (col.CompareTag(TargetTag))
        {
            EntityStatsController target = col.GetComponent <EntityStatsController>();
            target.StartCoroutine(other.transform.GetComponent <PlayerMotorController>().ApplyTimedMovementModifier(0.35f, 1.5f));
            target.TakeDamage(LauncherStats, Damage);
        }

        // Don't worry about collisions with the launcher or colliders that are triggers
        if (col != LauncherStats.gameObject && !other.isTrigger && other.tag != AllyTag)
        {
            InstantiateExplosion();
            gameObject.SetActive(false);
        }
    }
    /// <summary>
    /// Launch the damage projectile
    /// </summary>
    /// <param name="launcherStats">Stats of the entity that launched the projectile</param>
    /// <param name="direction">Direction to launch in</param>
    /// <param name="launchForce">Force to apply to the projectile upon launch</param>
    /// <param name="range">Maximum range that the projectile can fly</param>
    public void Launch(EntityStatsController launcherStats, Vector3 direction, float launchForce, float range)
    {
        LauncherStats = launcherStats;
        _range        = range;

        // Set position just in front of launcher
        _initialPosition   = launcherStats.transform.position + launcherStats.transform.forward;
        _initialPosition.y = launchHeight;
        transform.position = _initialPosition;

        // Set rotation to launch direction
        transform.rotation = Quaternion.LookRotation(direction);

        // Set self active and begin launch
        gameObject.SetActive(true);

        // Apply launch force to the rigidbody
        _rb.velocity        = Vector3.zero;
        _rb.angularVelocity = Vector3.zero;
        _rb.AddForce(launchForce * transform.forward);
    }
    /// <summary>
    /// Take damage from an attacker
    /// </summary>
    /// <param name="attacker">Stats controller of the attacking entity</param>
    /// <param name="maxDamage">Maximum amount of damage able to be dealt</param>
    /// <param name="stunTime">Amount of time to stun the enemy</param>
    /// <param name="explosionForce">Value to display</param>
    /// <param name="explosionPoint">Where the explosion originates from</param>
    /// <param name="explosionRadius">Explosion effect radius</param>
    public virtual void TakeExplosionDamage(EntityStatsController attacker, float maxDamage, float stunTime,
                                            float explosionForce, Vector3 explosionPoint, float explosionRadius)
    {
        // Ignore explosions if already dead or invincible
        if (isDead || invincible)
        {
            return;
        }

        // Calculate damage based on distance from the explosion point
        float proximity = (col.ClosestPoint(explosionPoint) - explosionPoint).magnitude;
        float effect    = 1 - (proximity / explosionRadius);

        if (effect < 0f)
        {
            return;
        }

        TakeDamage(attacker, maxDamage * effect);

        StartCoroutine(ApplyExplosiveForce(explosionForce, explosionPoint, explosionRadius, stunTime));
    }
Exemple #20
0
    protected override void OnTriggerEnter(Collider other)
    {
        GameObject col = other.gameObject;

        // if collision is with a player then deal damage
        if (col.CompareTag("Player"))
        {
            EntityStatsController target = col.GetComponent <EntityStatsController>();
            target.StartCoroutine(other.transform.GetComponent <PlayerMotorController>().ApplyTimedMovementModifier(0.5f, 1.5f));
            target.TakeDamage(Damage);
            gameObject.SetActive(false);
        }
        else if (col.CompareTag("Ground"))
        {
            // Possibly spawn a random plant
            if (Random.Range(0f, 1f) < spawnPlantProbability)
            {
                int   maxIndex         = 1;
                float healthPercentage = LauncherStats.health.CurrentValue / LauncherStats.health.maxValue;
                if (healthPercentage < 0.35f)
                {
                    maxIndex = 4;
                }
                else if (healthPercentage < 0.7f)
                {
                    maxIndex = 3;
                }
                TreantBossCombatController treatCombat = LauncherStats.GetComponent <TreantBossCombatController>();
                if (treatCombat && treatCombat.CanSpawnNewPlant())
                {
                    GameObject plantPrefab = plantPrefabs[Random.Range(0, maxIndex)];
                    GameObject plant       = Instantiate(plantPrefab, new Vector3(transform.position.x, 0, transform.position.z), Quaternion.identity);
                    treatCombat.AddPlantToSpawnList(plant);
                }
            }

            gameObject.SetActive(false);
        }
    }
    /// <summary>
    /// Take damage from an attacker
    /// </summary>
    /// <param name="attacker">Stats controller of the attacking entity</param>
    /// <param name="damageValue">Approximate damage value to apply to enemy health</param>
    /// <param name="timeDelta">Time since last damage calculation</param>
    public virtual void TakeDamage(EntityStatsController attacker, float damageValue, float timeDelta = 1f)
    {
        // Ignore attacks if already dead
        if (isDead)
        {
            return;
        }
        Anim.ResetTrigger("TakeDamage");
        Anim.SetTrigger("TakeDamage");
        if (takeDamageVocalSFX != null)
        {
            StartCoroutine(AudioHelper.PlayAudioOverlap(VocalAudio, takeDamageVocalSFX));
        }
        // Calculate any changes based on stats and modifiers here first
        float hitValue = (damageValue - ComputeDefenseModifier()) * timeDelta;

        health.Subtract(hitValue < 0 ? 0 : hitValue);

        if (Mathf.Approximately(health.CurrentValue, 0f))
        {
            Die();
        }
    }
    /// <summary>
    /// Take damage from an attacker
    /// </summary>
    /// <param name="attacker">Stats controller of the attacking entity</param>
    /// <param name="maxDamage">Maximum amount of damage able to be dealt</param>
    /// <param name="stunTime">Amount of time to stun the enemy</param>
    /// <param name="explosionForce">Value to display</param>
    /// <param name="explosionPoint">Where the explosion originates from</param>
    /// <param name="explosionRadius">Explosion effect radius</param>
    public virtual void TakeExplosionDamage(EntityStatsController attacker, float maxDamage, float stunTime,
                                            float explosionForce, Vector3 explosionPoint, float explosionRadius)
    {
        // Ignore explosions if already dead
        if (isDead)
        {
            return;
        }

        // Calculate damage based on distance from the explosion point
        float proximity = (col.ClosestPoint(explosionPoint) - explosionPoint).magnitude;
        float effect    = 1 - (proximity / explosionRadius);

        // TODO slightly strange bug where enemies just beyond the explosion take negative damage? This is a temp fix.
        if (effect < 0f)
        {
            return;
        }

        TakeDamage(attacker, maxDamage * effect);

        StartCoroutine(ApplyExplosiveForce(explosionForce, explosionPoint, explosionRadius, stunTime));
    }
Exemple #23
0
        public void Interactable_CanInteract_FalseIfInRangeAndWrongColour()
        {//set up testing variables for 'target'
            GameObject gameObject = new GameObject();
            Transform  objPos     = gameObject.GetComponent <Transform>();

            objPos.position = Vector3.one; //set both this and the 'player' to the same position
            Interactable interactable = gameObject.AddComponent <Interactable>();

            interactable.colour = CharacterColour.Red; //set target and 'player' colour to NOT MATCH

            //target.GetComponent<EntityStatsController>().characterColour

            //variables for 'player'
            GameObject player    = new GameObject();
            Transform  playerPos = player.GetComponent <Transform>();

            playerPos.position = Vector3.one;
            EntityStatsController playerControl = player.AddComponent <EntityStatsController>();

            playerControl.characterColour = CharacterColour.Green;//set player colour to Green to start

            //assert that we cannot pick up an object in the same position as us, if it doesn't match colour
            //Red object, Green Player
            Assert.False(interactable.CanInteract(playerPos));

            //Blue object, Green Player
            interactable.colour = CharacterColour.Blue;
            Assert.False(interactable.CanInteract(playerPos));

            //Yellow object, Green Player
            interactable.colour = CharacterColour.Yellow;
            Assert.False(interactable.CanInteract(playerPos));


            playerControl.characterColour = CharacterColour.Red;//set player colour to red now
            //Yellow object, Red player
            Assert.False(interactable.CanInteract(playerPos));

            //Blue object, Red Player
            interactable.colour = CharacterColour.Blue;
            Assert.False(interactable.CanInteract(playerPos));

            //Green object, Red Player
            interactable.colour = CharacterColour.Green;
            Assert.False(interactable.CanInteract(playerPos));


            playerControl.characterColour = CharacterColour.Blue;//set player colour to Blue now

            //Green object, Blue Player
            Assert.False(interactable.CanInteract(playerPos));

            //Yellow object, Blue Player
            interactable.colour = CharacterColour.Yellow;
            Assert.False(interactable.CanInteract(playerPos));

            //Red object, Blue Player
            interactable.colour = CharacterColour.Red;
            Assert.False(interactable.CanInteract(playerPos));


            playerControl.characterColour = CharacterColour.Yellow;//Finally set player colour to Yellow

            //Red object, Yellow Player
            Assert.False(interactable.CanInteract(playerPos));

            //Blue object, Yellow Player
            interactable.colour = CharacterColour.Blue;
            Assert.False(interactable.CanInteract(playerPos));

            //Green object, Yellow Player
            interactable.colour = CharacterColour.Green;
            Assert.False(interactable.CanInteract(playerPos));

            Object.DestroyImmediate(gameObject);
            Object.DestroyImmediate(player);
        }
 /// <summary>
 /// Take damage from an attacker, with reference to who the attacker is
 /// </summary>
 /// <param name="attacker">Stats controller of the attacking entity</param>
 /// <param name="damageValue">Approximate damage value to apply to enemy health</param>
 /// <param name="timeDelta">Time since last damage calculation</param>
 public virtual void TakeDamage(EntityStatsController attacker, float damageValue, float timeDelta = 1f)
 {
     // By default ignore the launcher stats
     TakeDamage(damageValue, timeDelta);
 }
 public override void Launch(EntityStatsController launcherStats, Vector3 direction, float launchForce, float range, float damage, string targetTag = "Enemy")
 {
     ObjectPooler.Instance.StartCoroutine(timedExplosion()); // Just need something that always exists, don't know whats a good choice
     base.Launch(launcherStats, direction, launchForce, range, damage, targetTag);
 }