AND… Now I’m in a new, and probably unrelated problem. I never thought of equipping my NPCs with shields, so this problem was under the radar for a long time. So, I gave it a go in ‘RespawnManager.cs’:
// If the enemy has a shield that's supposed to be in his hand, make him wear it:
if (spawnedEnemy.GetComponent<Fighter>().GetCurrentShieldConfig() != null)
{
ShieldConfig enemyShieldConfig = spawnedEnemy.GetComponent<Fighter>().GetCurrentShieldConfig();
spawnedEnemy.GetComponent<Fighter>().AttachShield(enemyShieldConfig);
}
But for some reason (again, I can’t identify where the logic error is from, yet), my enemy does not get the defence and percentage bonus he is supposed to get from holding the shield for some reason (I needed this to help get a reaction attack for any shield holder against any sword abuse). Where can I check to try and solve this?
Edit: Ahh nevermind, I just allowed the enemy to have a parameter for the shield config, and I was missing an if statement in ‘TryHit’ to compensate for that. Here’s what I ended up writing:
// the enemy
else
{
if (GetCurrentShieldConfig() != null)
{
Debug.Log($"{other.gameObject.name} is an enemy with a shield");
defence = otherBaseStats.GetStat(Stat.Defence) + (GetCurrentShieldConfig().GetDefenseBonus() * (1 + GetCurrentShieldConfig().GetPercentageBonus()/100));
}
else
{
Debug.Log($"{other.gameObject.name} has no shield");
defence = otherBaseStats.GetStat(Stat.Defence);
}
}
Edit 2: This is becoming a serious problem… I don’t know what’s wrong here:
// 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))
{
defence = otherBaseStats.GetStatBySpecifiedLevel(Stat.Defence, skillStore.GetSkillLevel(Skill.Defence));
}
// the enemy
else
{
if (GetCurrentShieldConfig() != null)
{
Debug.Log($"{other.gameObject.name} is an enemy with a shield");
defence = otherBaseStats.GetStat(Stat.Defence) + (GetCurrentShieldConfig().GetDefenseBonus() * (1 + GetCurrentShieldConfig().GetPercentageBonus()/100));
}
else
{
Debug.Log($"{other.gameObject.name} has no shield");
defence = otherBaseStats.GetStat(Stat.Defence);
}
}
damage /= 1 + defence/damage;
// Randomize the Damage:
// damage *= UnityEngine.Random.Range(0f, 1.25f);
// if (UnityEngine.Random.Range(0,100) > 95) damage *= 2.0f;
}
This is part of my ‘Fighter.OnTakenHit()’, and my problem here is, is that whether AN ENEMY has a shield or not, when my player punches him, DEPENDS ON WHETHER THE PLAYER HIMSELF IS WIELDING A SHIELD OR NOT
The logic is completely twisted here, and I desperately need help to identify what’s going on, and how to fix it… If it helps, here’s the entire ‘TryHit()’ function:
// 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:
void TryHit(int slot)
{
// if no current attack (or follow up) exists, return null:
if (currentAttack == null) return;
// 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
damageRadius = currentWeapon.value.DamageRadius;
break;
case 1: transformPoint = rightHandTransform.position; // for right-handed cases
break;
case 2: transformPoint = leftHandTransform.position; // for left-handed cases
break;
// case 3: for right foot, but after you got the animation intact and the transform setup
// case 4: for left foot. Again, after the animation is intact and the transform is setup
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
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;
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))
{
defence = otherBaseStats.GetStatBySpecifiedLevel(Stat.Defence, skillStore.GetSkillLevel(Skill.Defence));
}
// the enemy
else
{
if (GetCurrentShieldConfig() != null)
{
Debug.Log($"{other.gameObject.name} is an enemy with a shield");
defence = otherBaseStats.GetStat(Stat.Defence) + (GetCurrentShieldConfig().GetDefenseBonus() * (1 + GetCurrentShieldConfig().GetPercentageBonus()/100));
}
else
{
Debug.Log($"{other.gameObject.name} has no shield");
defence = otherBaseStats.GetStat(Stat.Defence);
}
}
damage /= 1 + defence/damage;
// 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);
}
}
}
Edit 3: that was another dumb mistake from my side that lead to an NRE… Fixed it