And now I have a new problem. When the Player is killed by an animal, the player does not transition to death state for some reason, 100% of the time, and naturally no respawning either, and it’s driving me nuts as of why (the enemy does not have this problem. In other words, if the player gets killed by an NPC, there’s no problems with that. If the Player is killed by an animal, the bug happens)
(along with an ‘Animal does not chase down the NPC that attacked them, if it’s not the player’ problem, but I’ll get to that later)
I’m not sure if this is relevant or not, but here it goes anyway. For the Horse, I haven’t done any tests yet, but for the Raven, the attacks are done either through the beak of the bird, or it’s legs. I modified ‘Fighter.TryHit’ a little to adjust for accepting legs and beak, but I’m not 100% sure if that’s the reason of the failure of the death state of the player or not, so here’s the code. Would appreciate any sort of help @Brian_Trotter
// For the brand new Attack Array System (part of the Point-And-Click -> Third Person System implementation)
// this function is called by animations to perform hits, based on the hand/foot/weapon, doing the hit:
private void TryHit(int slot)
{
// if no current attack (or follow up) exists, return null:
if (currentAttack == null)
{
if (AnimalMountManager.isOnAnimalMount)
{
// Assign the correct 'currentAttack' for the animal mount:
currentAttack = GetCurrentWeaponConfig().OnAnimalAttacks[0];
}
else
{
Debug.Log($"TryHit is called, but current attack is null");
return;
}
}
Debug.Log($"TryHit has been called");
// radius of the damage of the weapon:
float damageRadius = 0.5f;
// To trigger this animation, the event in the animation takes the 1 and 2 values in 'Int' slot
Vector3 transformPoint;
switch (slot)
{
case 0:
transformPoint = currentWeapon.value.DamagePoint; // weapon damage
if (AnimalMountManager.isOnAnimalMount) // for cases when you need a larger hit radius whilst attacking by mounting
{
damageRadius = currentWeapon.value.DamageRadius * 2.0f; // you'll need a bigger radius to strike others whilst on the run on a mount
}
else damageRadius = currentWeapon.value.DamageRadius; // weapon damage radius
break;
case 1: transformPoint = rightHandTransform.position; // for right-handed cases
break;
case 2: transformPoint = leftHandTransform.position; // for left-handed cases
break;
case 3:
if (GetComponent<PlayerStateMachine>()) return; // the player's Parrying is handled in 'ShieldTriggerEnter.cs'
if (GetCurrentShieldConfig() != null && GetComponent<EnemyStateMachine>() != null)
{
// use this call on the Animation Event Line on Shield Parrying animations
Debug.Log($"{GetCurrentShieldConfig().name} has been found in shield hand");
transformPoint = currentEquippedShield.value.DamagePoint;
damageRadius = currentEquippedShield.value.DamageRadius;
}
else
{
transformPoint = rightHandTransform.position; // no shield? Just use your rightHandTransform
}
break;
case 4: transformPoint = rightLegTransform.position;
break;
case 5: transformPoint = leftLegTransform.position;
break;
case 6:
transformPoint = beakTransform.position; // The beak of the animal, a Raven for example or something (OPTIONAL)
break;
default: transformPoint = rightHandTransform.position; // for cases when things make no sense
break;
}
Debug.Log($"Attacking with slot {slot}, position {transformPoint}");
// This list ensures that the health component of the player is accessed once only. This problem
// came up when I introduced a second Capsule Collider on my player, so he can mount animals using
// Malbers' Scripts (basically, 2 colliders on the player = 2x damage dealt to him...
// we needed to get rid of that by ensuring the health component is accessed once, through this list):
List<Health> alreadyHit = new List<Health>();
foreach (Collider other in Physics.OverlapSphere(transformPoint, damageRadius))
{
if (other.gameObject == gameObject) continue; // don't hit yourself
// Stop the player from hitting the animal he's currently mounting:
if (AnimalMountManager.isOnAnimalMount && this.gameObject.CompareTag("Player"))
{
var mountedAnimal = GetComponent<PlayerOnAnimalStateMachine>()?.GetAnimal();
if (other.gameObject == mountedAnimal.gameObject)
{
// If you got this far, it means the player is mounted to an animal, and he's
// trying to hit his mount with a melee weapon, which should be ignored!
continue;
}
}
if (other.TryGetComponent(out Health otherHealth) && !otherHealth.IsDead())
{
// If one of the players' colliders (he has a Character Controller and a Capsule Collider
// on him) is hit, don't take damage again (fixes the 2 colliders-on-player-taking-damage problem):
if (alreadyHit.Contains(otherHealth)) continue;
// if you didn't take a hit yet, go ahead and do so now:
alreadyHit.Add(otherHealth);
float damage = GetDamage();
damage *= currentAttack.DamageModifier;
// player/enemy
if (other.TryGetComponent(out BaseStats otherBaseStats))
{
float defence;
// if its the player (the only in-game character with a skillStore)
if (other.TryGetComponent(out SkillStore skillStore))
{
Debug.Log($"{other.gameObject.name} has a SkillStore");
defence = otherBaseStats.GetStatBySpecifiedLevel(Stat.Defence, skillStore.GetSkillLevel(Skill.Defence));
}
// the enemy
else
{
if (other.GetComponent<Fighter>().GetCurrentShieldConfig() != null)
{
Debug.Log($"{other.gameObject.name} is an enemy with a shield");
defence = otherBaseStats.GetStat(Stat.Defence) + (other.GetComponent<Fighter>().GetCurrentShieldConfig().GetDefenseBonus() * (1 + other.GetComponent<Fighter>().GetCurrentShieldConfig().GetPercentageBonus()/100));
}
else
{
Debug.Log($"{other.gameObject.name} has no shield");
defence = otherBaseStats.GetStat(Stat.Defence);
}
}
damage /= 1 + defence/damage; // Replaced by a 'TEST' below
// Randomize the Damage:
// damage *= UnityEngine.Random.Range(0f, 1.25f);
// if (UnityEngine.Random.Range(0,100) > 95) damage *= 2.0f;
}
// if the player is invulnerable, ignore trying to damage him, and continue to the next cycle of damaging enemies in the radius, which was hurt by the sword:
if (other.CompareTag("Player") && other.GetComponent<Health>().GetInvulnerable())
{
continue; // later on, integrate logic here to accept a percentage of damage, before continuing to the next Foreach loop
}
// (TEMP - GetComponent<Health>().IsDead()) Temporarily here, to ensure ghost enemies deal no damage and mess with the NPC hunting for enemies system:
if (otherHealth.IsDead() || GetComponent<Health>().IsDead())
{
return;
}
otherHealth.TakeDamage(gameObject, damage, currentWeaponConfig.GetSkill());
TryApplyHitForce(other, transform.position);
}
}
}
and a screenshot of the hierarchy of the Raven’s fighter.cs script (in case the differences in there are of any help):