[NEW TOPIC, but relevant to skills, hence why it’s here]
hi again @bixarrio and @Brian_Trotter. Something I noticed during combat, considering that we shifted the whole game to a ‘Skill-based system’, is that no matter what you do so far, your final XP runs to whatever XP is relevant to which weapon you used to cast the final blow. In other words, you can have a ranged fight that is 99% done in ranged, but the last 1% is done in attack, then attack gets all the experience, and ranged gets nothing… kind of like the kid that gets all the credit in high school, but originally he copied the smart guy’s homework, and the smart guy unfortunately got no credit for his work
To counter this, I want to develop an algorithm that keeps track of what weapon did what damage, and average the damage out in the end, for each combat skill (the skills will be attack, ranged and magic). The Skill that dealt the most damage will get the XP, the rest gets nothing. Any suggestions on how can I start working on this? (I know this is not a topic that is as easy as it sounds)
Edit: OK so here’s what I tried doing, but this was a complete, utter failure:
- I created a new script, called ‘DamageComponent’, which starts with a private dictionary, which I attached to my player, and that script contains two functions.
The first is a dictionary, which I called ‘DealDamage()’, which adds damage dealt to a dictionary responsible for carrying the damage dealt by the player
The second function was known as ‘GetMostDamagingSkill()’, and that one accumulates the damage of the values in the dictionary, adds them up, and returns the mostDamagingSkill, and both functions are shown below:
using System.Collections.Generic;
using RPG.Skills;
using UnityEngine;
namespace RPG.Combat {
public class DamageComponent : MonoBehaviour {
private Dictionary<Skill, float> damagePerSkill = new Dictionary<Skill, float>();
public void DealDamage(Skill skill, float damage) {
if (damagePerSkill.ContainsKey(skill)) {
damagePerSkill[skill] += damage;
}
else damagePerSkill.Add(skill, damage);
}
public Skill GetMostDamagingSkill() {
Skill mostDamagingSkill = Skill.None; // I know this is supposed to be null, I'm just not sure how to create a null Skill type... the compiler returns errors
float maxDamage = 0;
foreach (var keyValuePair in damagePerSkill) {
if (keyValuePair.Value > maxDamage) {
maxDamage = keyValuePair.Value;
mostDamagingSkill = keyValuePair.Key;
}
}
return mostDamagingSkill;
}
}
}
- Next up, I introduced a variable called ‘playerDamageComponent’, which I initialized in ‘Awake()’, and the function known as ‘GetDamage()’ in ‘Fighter.cs’ about a week ago was tuned, and this function was responsible for splitting up the XP to reward whoever had the final hit the experience needed, and it’s eventually called in ‘Fighter.Hit()’. I tuned this function a little bit, to compensate for the new function, as shown below:
public DamageComponent playerDamageComponent;
private void Awake() {
// some code here...
playerDamageComponent = GetComponent<DamageComponent>();
// some other code...
}
public int GetDamage() {
if (currentWeaponConfig.GetSkill() == Skill.Attack) {
// return (int)(GetComponent<BaseStats>().GetStat(Stat.Attack) + (currentWeaponConfig.GetDamage() * (1 + currentWeaponConfig.GetPercentageBonus() / 100)));
int attackDamage = (int) (GetComponent<BaseStats>().GetStat(Stat.Attack) + (currentWeaponConfig.GetDamage() * (1 + currentWeaponConfig.GetPercentageBonus()/100)));
playerDamageComponent.DealDamage(Skill.Attack, attackDamage);
return attackDamage;
}
else if (currentWeaponConfig.GetSkill() == Skill.Ranged) {
// return (int) (GetComponent<BaseStats>().GetStat(Stat.Ranged) + (currentWeaponConfig.GetDamage() * (1 + currentWeaponConfig.GetPercentageBonus()/100)));
int rangedDamage = (int)(GetComponent<BaseStats>().GetStat(Stat.Ranged) + (currentWeaponConfig.GetDamage() * (1 + currentWeaponConfig.GetPercentageBonus() / 100)));
playerDamageComponent.DealDamage(Skill.Ranged, rangedDamage);
return rangedDamage;
}
else {
// return (int) (GetComponent<BaseStats>().GetStat(Stat.Magic) + (currentWeaponConfig.GetDamage() * (1 + currentWeaponConfig.GetPercentageBonus()/100)));
int magicDamage = (int)(GetComponent<BaseStats>().GetStat(Stat.Magic) + (currentWeaponConfig.GetDamage() * (1 + currentWeaponConfig.GetPercentageBonus() / 100)));
playerDamageComponent.DealDamage(Skill.Magic, magicDamage);
return magicDamage;
}
}
- Finally, in ‘Health.AwardExperience()’, I tried to award the experience to whoever did the most damage, as shown below:
private void AwardExperience(GameObject instigator, Skill skill, Skill otherSkill = Skill.Defence) {
if (instigator.TryGetComponent(out SkillExperience skillExperience)) {
if (instigator.TryGetComponent(out Health otherHealth) && !otherHealth.IsDead()) {
// This line sends 2/3rd of the XP Reward to whichever skill is associated to the Players' weapon:
// skillExperience.GainExperience(skill, 2*Mathf.RoundToInt(GetComponent<AIController>().GetXPReward()/3));
skillExperience.GainExperience(GetComponent<DamageComponent>().GetMostDamagingSkill(), 2*Mathf.RoundToInt(GetComponent<AIController>().GetXPReward()/3));
// This line sends 1/3rd of the XP Reward to the defence XP, which is always 1/3rd of whatever the AI Reward XP is assigned to:
skillExperience.GainExperience(otherSkill, Mathf.RoundToInt(GetComponent<AIController>().GetXPReward()/3));
}
}
}
These are all the changes I tried doing, but the system somehow still failed. Where did I go wrong…?