Skip to content

Commit

Permalink
Draft implementation of spell damage calcuation
Browse files Browse the repository at this point in the history
  • Loading branch information
nickynick committed Jul 15, 2013
1 parent 331c274 commit ececfe6
Show file tree
Hide file tree
Showing 20 changed files with 1,477 additions and 232 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,7 @@ packages/
*.dbmdl

#Test files
*.testsettings
*.testsettings

#ILMerge
ILMerge/
2 changes: 2 additions & 0 deletions H3Calc/CombatDamagePanel.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

164 changes: 122 additions & 42 deletions H3Calc/CombatDamagePanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,30 @@ namespace H3Calc
{
public partial class CombatDamagePanel : UserControl
{
public event EventHandler DataChanged;

private CombatDamageCalculatorInputData data;

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public CombatDamageCalculatorInputData Data
{
get
{
if (data == null)
{
data = new CombatDamageCalculatorInputData();
}
return data;
}
set
{
data = value;
SetControlsWithData(value);
UpdateCalculatedDamage();
}
}


private List<Unit> units;
public List<Unit> Units
{
Expand All @@ -23,7 +47,9 @@ public List<Unit> Units
{
units = value;

dataUpdateSuspended = true;
attackerPickPanel.Units = defenderPickPanel.Units = units;
dataUpdateSuspended = false;
}
}

Expand All @@ -38,7 +64,9 @@ public List<Hero> Heroes
{
heroes = value;

dataUpdateSuspended = true;
attackerPickPanel.Heroes = defenderPickPanel.Heroes = heroes;
dataUpdateSuspended = false;
}
}

Expand All @@ -53,8 +81,10 @@ public List<Terrain> Terrains
{
terrains = value;

dataUpdateSuspended = true;
terrainComboBox.DataSource = terrains;
terrainComboBox.DisplayMember = "Name";
dataUpdateSuspended = false;
}
}

Expand All @@ -77,8 +107,8 @@ public ApplicationMode Mode
protected CombatDamageCalculator calculator;

protected Control[] AttackerHeroControls;
protected Control[] DefenderHeroControls;

protected Control[] DefenderHeroControls;
protected bool dataUpdateSuspended;

public CombatDamagePanel()
{
Expand Down Expand Up @@ -107,70 +137,123 @@ private void UpdateControlsOnModeChange()
//resultPanel.Top = terrainGroupBox.Top = attackerGroupBox.Top + attackerGroupBox.Height + 6;

this.Height = attackerGroupBox.Bottom + terrainGroupBox.Height + 16;
}
private void UpdateCalculatedDamage()
}

private void UpdateData()
{
CombatDamageCalculatorInputData inputData = new CombatDamageCalculatorInputData();
if (!dataUpdateSuspended)
{
attackerPickPanel.OpponentHeroStats = defenderPickPanel.Data.HeroStats;
defenderPickPanel.OpponentHeroStats = attackerPickPanel.Data.HeroStats;

inputData.Attacker = attackerPickPanel.Data.Unit;
inputData.Defender = defenderPickPanel.Data.Unit;
UpdateDataFromControls(Data);

bool haveInputData = ((inputData.Attacker != null) && (inputData.Defender != null));
if (DataChanged != null)
{
DataChanged(this, null);
}

resultPanel.Visible = haveInputData;
UpdateCalculatedDamage();
}
}

if (!haveInputData)
void UpdateDataFromControls(CombatDamageCalculatorInputData data)
{
data.Attacker = attackerPickPanel.Data.Unit;
data.Defender = defenderPickPanel.Data.Unit;

data.Terrain = (Terrain)terrainComboBox.SelectedValue;
if (data.Terrain.Id == -1)
{
return;
}
data.Terrain = null;
}

data.AttackerHeroStats = attackerPickPanel.Data.HeroStats;
data.AttackerSpells = attackerPickPanel.Data.Spells;

data.DefenderHeroStats = defenderPickPanel.Data.HeroStats;
data.DefenderSpells = defenderPickPanel.Data.Spells;

data.AttackerCount = (int)attackerCountUpDn.Value;
data.DefenderCount = (int)defenderCountUpDn.Value;
}

void SetControlsWithData(CombatDamageCalculatorInputData data)
{
dataUpdateSuspended = true;

PickPanelData panelData = attackerPickPanel.Data;
panelData.Unit = data.Attacker;
panelData.HeroStats = data.AttackerHeroStats;
panelData.Spells = data.AttackerSpells;
attackerPickPanel.Data = panelData;

panelData = defenderPickPanel.Data;
panelData.Unit = data.Defender;
panelData.HeroStats = data.DefenderHeroStats;
panelData.Spells = data.DefenderSpells;
defenderPickPanel.Data = panelData;

inputData.Terrain = (Terrain)terrainComboBox.SelectedValue;
if (inputData.Terrain.Id == -1)
if (data.Terrain != null)
{
terrainComboBox.SelectedValue = data.Terrain;
}
else
{
inputData.Terrain = null;
terrainComboBox.SelectedIndex = 0;
}

inputData.AttackerHeroStats = attackerPickPanel.Data.HeroStats;
inputData.AttackerSpells = attackerPickPanel.Data.Spells;
attackerCountUpDn.Value = data.AttackerCount;
defenderCountUpDn.Value = data.DefenderCount;

dataUpdateSuspended = false;
}

inputData.DefenderHeroStats = defenderPickPanel.Data.HeroStats;
inputData.DefenderSpells = defenderPickPanel.Data.Spells;

inputData.AttackerCount = (int)attackerCountUpDn.Value;
private void UpdateCalculatedDamage()
{
bool hasInputData = ((Data.Attacker != null) && (Data.Defender != null));
resultPanel.Visible = hasInputData;
if (!hasInputData)
{
return;
}

int minDamage, maxDamage;
string notes;
calculator.CalculateDamage(inputData, out minDamage, out maxDamage, out notes);
calculator.CalculateDamage(Data, out minDamage, out maxDamage, out notes);

int minKills = minDamage / inputData.Defender.InitialStats.Health;
int maxKills = maxDamage / inputData.Defender.InitialStats.Health;
int minKills = minDamage / Data.Defender.InitialStats.Health;
int maxKills = maxDamage / Data.Defender.InitialStats.Health;

calculatedDamageLbl.Text = FormatRange(minDamage, maxDamage);
calculatedKillsLbl.Text = FormatRange(minKills, maxKills);
notesLbl.Text = (notes != null) ? "(" + notes + ")" : null;

//// TODO: refactor this crap

inputData.Attacker = defenderPickPanel.Data.Unit;
inputData.AttackerHeroStats = defenderPickPanel.Data.HeroStats;
inputData.AttackerSpells = defenderPickPanel.Data.Spells;
CombatDamageCalculatorInputData retData = new CombatDamageCalculatorInputData();

inputData.Defender = attackerPickPanel.Data.Unit;
inputData.DefenderHeroStats = attackerPickPanel.Data.HeroStats;
inputData.DefenderSpells = attackerPickPanel.Data.Spells;
retData.Attacker = Data.Defender;
retData.AttackerHeroStats = Data.DefenderHeroStats;
retData.AttackerSpells = Data.DefenderSpells;

retData.Defender = Data.Attacker;
retData.DefenderHeroStats = Data.AttackerHeroStats;
retData.DefenderSpells = Data.AttackerSpells;
retData.DefenderCount = Data.AttackerCount;

int minRetDamage, tempRetDamage, maxRetDamage;
string retNotes;

inputData.AttackerCount = Math.Max(0, (int)defenderCountUpDn.Value - minKills);
calculator.CalculateDamage(inputData, out tempRetDamage, out maxRetDamage, out retNotes);
retData.AttackerCount = Math.Max(0, Data.DefenderCount - minKills);
calculator.CalculateDamage(retData, out tempRetDamage, out maxRetDamage, out retNotes);

inputData.AttackerCount = Math.Max(0, (int)defenderCountUpDn.Value - maxKills);
calculator.CalculateDamage(inputData, out minRetDamage, out tempRetDamage, out retNotes);
retData.AttackerCount = Math.Max(0, Data.DefenderCount - maxKills);
calculator.CalculateDamage(retData, out minRetDamage, out tempRetDamage, out retNotes);

int minRetKills = minRetDamage / inputData.Defender.InitialStats.Health;
int maxRetKills = maxRetDamage / inputData.Defender.InitialStats.Health;
int minRetKills = minRetDamage / Data.Defender.InitialStats.Health;
int maxRetKills = maxRetDamage / Data.Defender.InitialStats.Health;

calculatedRetDamageLbl.Text = FormatRange(minRetDamage, maxRetDamage);
calculatedRetKillsLbl.Text = FormatRange(minRetKills, maxRetKills);
Expand All @@ -190,16 +273,13 @@ private string FormatRange(int min, int max)
}

private void ControlValueChanged(object sender, EventArgs e)
{
UpdateCalculatedDamage();
{
UpdateData();
}

private void PickPanelDataChanged(object sender, EventArgs e)
{
attackerPickPanel.OpponentHeroStats = defenderPickPanel.Data.HeroStats;
defenderPickPanel.OpponentHeroStats = attackerPickPanel.Data.HeroStats;

UpdateCalculatedDamage();
UpdateData();
}

private void swapBtn_Click(object sender, EventArgs e)
Expand Down
6 changes: 5 additions & 1 deletion H3Calc/Engine/CombatDamageCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ public class CombatDamageCalculatorInputData
public Unit Attacker { get; set; }
public Unit Defender { get; set; }

public int AttackerCount { get; set; }
public int AttackerCount { get; set; }
public int DefenderCount { get; set; }

public HeroStats AttackerHeroStats { get; set; }
public HeroStats DefenderHeroStats { get; set; }
Expand All @@ -170,6 +171,9 @@ public class CombatDamageCalculatorInputData

public CombatDamageCalculatorInputData()
{
AttackerCount = 1;
DefenderCount = 1;

AttackerSpells = new List<ModifierSpell>();
DefenderSpells = new List<ModifierSpell>();
}
Expand Down
8 changes: 4 additions & 4 deletions H3Calc/Engine/DamageSpells.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ protected DamageSpell(string name, Type secondarySkillType, int level) : base(na

public virtual int BaseDamage(Unit unit)
{
if (SkillLevel <= SecondarySkillLevel.Basic)
if (CasterStats.SkillLevel <= SecondarySkillLevel.Basic)
{
return BasicBaseDamage();
}
else if (SkillLevel == SecondarySkillLevel.Advanced)
else if (CasterStats.SkillLevel == SecondarySkillLevel.Advanced)
{
return AdvancedBaseDamage();
}
Expand All @@ -29,7 +29,7 @@ public virtual SpellDamageModifier BaseModifier(Unit unit)
{
SpellDamageModifier damageModifier = new SpellDamageModifier();

if (IsSpecialized)
if (CasterStats.IsSpecialized)
{
damageModifier.DamageMultipliers.Add(SpecializationMultiplier(unit));
}
Expand All @@ -42,7 +42,7 @@ public virtual SpellDamageModifier BaseModifier(Unit unit)
protected abstract int ExpertBaseDamage();
protected virtual double SpecializationMultiplier(Unit unit)
{
return 1 + 0.03 * (CasterStats.Level / unit.Level);
return 1 + 0.03 * (CasterStats.SpecializationLevel / unit.Level);
}
}

Expand Down
61 changes: 61 additions & 0 deletions H3Calc/Engine/Hero.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,67 @@ public HeroStats()
SecondarySkills = new List<SecondarySkill>();
}

private SecondarySkill ExistingSecondarySkillOfType(Type secondarySkillType)
{
return SecondarySkills.FirstOrDefault(s => s.GetType() == secondarySkillType);
}

public SecondarySkillLevel LevelForSecondarySkillType(Type secondarySkillType)
{
SecondarySkill skill = ExistingSecondarySkillOfType(secondarySkillType);
return (skill != null) ? skill.SkillLevel : SecondarySkillLevel.None;
}

public void SetLevelForSecondarySkillType(Type secondarySkillType, SecondarySkillLevel level)
{
SecondarySkill skill = ExistingSecondarySkillOfType(secondarySkillType);

if (level == SecondarySkillLevel.None)
{
if (skill != null)
{
SecondarySkills.Remove(skill);
}
}
else
{
if (skill == null)
{
skill = (SecondarySkill)Activator.CreateInstance(secondarySkillType);
SecondarySkills.Add(skill);
}

skill.SkillLevel = level;
}
}

public SpellCasterStats SpellCasterStatsForSpell(Spell spell)
{
SpellCasterStats stats = new SpellCasterStats();

stats.SpellPower = SpellPower;

stats.SkillLevel = SecondarySkillLevel.None;
foreach (SecondarySkill skill in SecondarySkills)
{
if (spell.IsAffectedBySecondarySkillType(skill.GetType()))
{
if (stats.SkillLevel < skill.SkillLevel)
{
stats.SkillLevel = skill.SkillLevel;
}
}
}

if (spell.GetType() == Hero.SpecializedSpell)
{
stats.IsSpecialized = true;
stats.SpecializationLevel = Level;
}

return stats;
}

public void ApplyPermanently(Unit unit, UnitStats modifiedStats)
{
modifiedStats.Attack += Attack;
Expand Down
Loading

0 comments on commit ececfe6

Please sign in to comment.