2000 30.71 KB 808
void CombatCalculation(Unit attacker, Unit defender) { // diplomacy relation change diplomacyHandler.ModifyRelation(defender.GetOwner().GetPlayerId(), attacker.GetOwner().GetPlayerId(), -4);
Node currentNode = attacker.GetCurrentNode();
// this is completely arbitrary but it seems to give good results
float attackerStatDiff = 1f + (attacker.GetAttack() - (int)(0.60 * defender.GetDefence())) / 60;
float defenderStatDiff = 1f + (defender.GetAttack() - (int)(0.60 * attacker.GetDefence())) / 60;
int attackerRoll = (int)(0.12 * Random.Range((int)(attacker.GetSize() * 0.6), attacker.GetSize()) * attackerStatDiff);
int defenderRoll = (int)(0.12 * Random.Range((int)(defender.GetSize() * 0.6), defender.GetSize()) * defenderStatDiff);
Officer attackerCenter = attacker.GetCenterOfficer();
Officer attackerFlank1 = attacker.GetFlank1Officer();
Officer attackerFlank2 = attacker.GetFlank2Officer();
Officer defenderCenter = defender.GetCenterOfficer();
Officer defenderFlank1 = defender.GetFlank1Officer();
Officer defenderFlank2 = defender.GetFlank2Officer();
// store damage rolls for battle report
int aCAttack = 0;
int dCAttack = 0;
int aCDefence = 0;
int dCDefence = 0;
int aF1Attack = 0;
int dF1Attack = 0;
int aF1Defence = 0;
int dF1Defence = 0;
int aF2Attack = 0;
int dF2Attack = 0;
int aF2Defence = 0;
int dF2Defence = 0;
string aCTactic = "None";
string dCTactic = "None";
string aF1Tactic = "None";
string aF2Tactic = "None";
string dF1Tactic = "None";
string dF2Tactic = "None";
float aCAttackModifier = 1f;
float aCDefenceModifier = 1f;
float dCAttackModifier = 1f;
float dCDefenceModifier = 1f;
float aF1AttackModifier = 1f;
float aF1DefenceModifier = 1f;
float dF1AttackModifier = 1f;
float dF1DefenceModifier = 1f;
float aF2AttackModifier = 1f;
float aF2DefenceModifier = 1f;
float dF2AttackModifier = 1f;
float dF2DefenceModifier = 1f;
//
// choose tactic
//
if (attackerCenter != null)
{
aCTactic = ChooseCombatTactic(attackerCenter);
aCAttackModifier = GetTacticAttackBonus(aCTactic);
aCDefenceModifier = GetTacticDefenceBonus(aCTactic);
}
if (defenderCenter != null)
{
dCTactic = ChooseCombatTactic(defenderCenter);
dCAttackModifier = GetTacticAttackBonus(dCTactic);
dCDefenceModifier = GetTacticDefenceBonus(dCTactic);
}
if (attackerFlank1 != null)
{
aF1Tactic = ChooseCombatTactic(attackerFlank1);
aF1AttackModifier = GetTacticAttackBonus(aF1Tactic);
aF1DefenceModifier = GetTacticDefenceBonus(aF1Tactic);
}
if (attackerFlank2 != null)
{
aF2Tactic = ChooseCombatTactic(attackerFlank2);
aF2AttackModifier = GetTacticAttackBonus(aF2Tactic);
aF2DefenceModifier = GetTacticDefenceBonus(aF2Tactic);
}
if (defenderFlank1 != null)
{
dF1Tactic = ChooseCombatTactic(defenderFlank1);
dF1AttackModifier = GetTacticAttackBonus(dF1Tactic);
dF1DefenceModifier = GetTacticDefenceBonus(dF1Tactic);
}
if (defenderFlank2 != null)
{
dF2Tactic = ChooseCombatTactic(defenderFlank2);
dF2AttackModifier = GetTacticAttackBonus(dF2Tactic);
dF2DefenceModifier = GetTacticDefenceBonus(dF2Tactic);
}
if (attackerCenter != null)
{
aCAttack = (int)(attackerCenter.GetPow() * Random.Range(2, 4) * attackerStatDiff * aCAttackModifier);
int finalAttack = aCAttack;
attackerCenter.AddXp("pow", 10 + (int)(attackerCenter.GetPow() * 0.1));
if (defenderCenter != null)
{
dCDefence = (int)(defenderCenter.GetFri() * Random.Range(1, 3) * defenderStatDiff * dCDefenceModifier);
finalAttack -= dCDefence;
defenderCenter.AddXp("fri", 10 + (int)(defenderCenter.GetFri() * 0.1));
}
if (finalAttack < 0)
{
finalAttack = 0;
}
attackerRoll += finalAttack;
attackerCenter.ProgressFriendship(attackerFlank1, 5);
attackerCenter.ProgressFriendship(attackerFlank2, 5);
}
if (attackerFlank1 != null)
{
aF1Attack = (int)(attackerFlank1.GetPow() * Random.Range(2, 4) * attackerStatDiff * aF1AttackModifier);
int finalAttack = aF1Attack;
attackerFlank1.AddXp("pow", 10 + (int)(attackerFlank1.GetPow() * 0.1));
if (defenderFlank2 != null)
{
dF2Defence = (int)(defenderFlank2.GetFri() * Random.Range(1, 3) * defenderStatDiff * dF2DefenceModifier);
finalAttack -= dF2Defence;
defenderFlank2.AddXp("fri", 10 + (int)(defenderFlank2.GetFri() * 0.1));
}
if (finalAttack < 0)
{
finalAttack = 0;
}
attackerRoll += finalAttack;
attackerFlank1.ProgressFriendship(attackerCenter, 5);
attackerFlank1.ProgressFriendship(attackerFlank2, 5);
}
if (attackerFlank2 != null)
{
aF2Attack = (int)(attackerFlank2.GetPow() * Random.Range(2, 4) * attackerStatDiff * aF2AttackModifier);
int finalAttack = aF1Attack;
attackerFlank2.AddXp("pow", 10 + (int)(attackerFlank2.GetPow() * 0.1));
if (defenderFlank1 != null)
{
dF1Defence = (int)(defenderFlank1.GetFri() * Random.Range(1, 3) * defenderStatDiff * dF1DefenceModifier);
finalAttack -= dF1Defence;
defenderFlank1.AddXp("fri", 10 + (int)(defenderFlank1.GetFri() * 0.1));
}
if (finalAttack < 0)
{
finalAttack = 0;
}
attackerRoll += finalAttack;
attackerFlank2.ProgressFriendship(attackerCenter, 5);
attackerFlank2.ProgressFriendship(attackerFlank1, 5);
}
if (defenderCenter != null)
{
dCAttack = (int)(defenderCenter.GetPow() * Random.Range(2, 4) * defenderStatDiff * dCAttackModifier);
int finalAttack = dCAttack;
defenderCenter.AddXp("pow", 10 + (int)(defenderCenter.GetPow() * 0.1));
if (attackerCenter != null)
{
aCDefence = (int)(attackerCenter.GetFri() * Random.Range(1, 3) * attackerStatDiff * aCDefenceModifier);
finalAttack -= aCDefence;
attackerCenter.AddXp("fri", 10 + (int)(attackerCenter.GetFri() * 0.1));
}
if (finalAttack < 0)
{
finalAttack = 0;
}
defenderRoll += finalAttack;
defenderCenter.ProgressFriendship(defenderFlank1, 5);
defenderCenter.ProgressFriendship(defenderFlank2, 5);
}
if (defenderFlank1 != null)
{
dF1Attack = (int)(defenderFlank1.GetPow() * Random.Range(2, 4) * defenderStatDiff * dF1AttackModifier);
int finalAttack = dF1Attack;
defenderFlank1.AddXp("pow", 10 + (int)(defenderFlank1.GetPow() * 0.1));
if (attackerFlank2 != null)
{
aF2Defence = (int)(attackerFlank2.GetFri() * Random.Range(1, 3) * attackerStatDiff * aF2DefenceModifier);
finalAttack -= aF2Defence;
attackerFlank2.AddXp("fri", 10 + (int)(attackerFlank2.GetFri() * 0.1));
}
if (finalAttack < 0)
{
finalAttack = 0;
}
defenderRoll += finalAttack;
defenderFlank1.ProgressFriendship(defenderCenter, 5);
defenderFlank1.ProgressFriendship(defenderFlank2, 5);
}
if (defenderFlank2 != null)
{
dF2Attack = (int)(defenderFlank2.GetPow() * Random.Range(2, 4) * defenderStatDiff * dF2AttackModifier);
int finalAttack = dF2Attack;
defenderFlank2.AddXp("pow", 10 + (int)(defenderFlank2.GetPow() * 0.1));
if (attackerFlank1 != null)
{
aF1Defence = (int)(attackerFlank1.GetFri() * Random.Range(1, 2) * attackerStatDiff * aF1DefenceModifier);
finalAttack -= aF1Defence;
attackerFlank1.AddXp("fri", 10 + (int)(attackerFlank1.GetFri() * 0.1));
}
if (finalAttack < 0)
{
finalAttack = 0;
}
defenderRoll += finalAttack;
defenderFlank2.ProgressFriendship(defenderCenter, 5);
defenderFlank2.ProgressFriendship(defenderFlank1, 5);
}
float attackerFortificationBonus = 1;
float defenderFortificationBonus = 1;
if (attacker.GetOwner() == currentNode.GetOwner())
{
attackerFortificationBonus = 1 - (currentNode.GetFortificationsLevel() / 10);
}
else if (defender.GetOwner() == currentNode.GetOwner())
{
defenderFortificationBonus = 1 - (currentNode.GetFortificationsLevel() / 10);
}
attackerRoll = (int)(attackerRoll * defenderFortificationBonus);
defenderRoll = (int)(defenderRoll * attackerFortificationBonus);
if (attackerRoll > defender.GetSize())
{
attackerRoll = defender.GetSize();
}
if (defenderRoll > attacker.GetSize())
{
defenderRoll = attacker.GetSize();
}
if (attackerRoll < 0)
{
attackerRoll = 0;
}
if (defenderRoll < 0)
{
defenderRoll = 0;
}
if (defender != null)
{
defender.ModifySize((int)(-attackerRoll));
defender.SetActionPoints(defender.GetActionPoints() - 2); // unit spends 2 action points for fighting
}
if (attacker != null)
{
attacker.ModifySize((int)(-defenderRoll));
attacker.SetActionPoints(attacker.GetActionPoints() - 2); // unit spends 2 action points for fighting
}
/// officer loyalty change and capture chance
// should turn this into a loop
if (attacker.GetSize() == 0)
{
if (attackerCenter != null)
{
attackerCenter.ModifyLoyalty(-15);
if (attackerCenter.GetLoyalty() < 25)
{
int captureRoll = Random.Range(0, 2);
if (captureRoll == 0)
{
defender.GetOwner().AddOfficer(attackerCenter);
attacker.GetOwner().RemoveOfficer(attackerCenter);
attackerCenter.ModifyLoyalty(15);
if (defender.GetOwner().isHuman)
{
uiHandler.OfficerGained(attackerCenter);
}
if (attacker.GetOwner().isHuman)
{
string logMessage = $"{attackerCenter.GetName()} was captured and persuaded to join {defender.GetOwner().GetFactionLeader().GetName()}!";
uiHandler.LogMessage(logMessage, defender.GetOwner().GetPlayerColor());
}
}
}
}
if (attackerFlank1 != null)
{
attackerFlank1.ModifyLoyalty(-15);
if (attackerFlank1.GetLoyalty() < 25)
{
int captureRoll = Random.Range(0, 2);
if (captureRoll == 0)
{
defender.GetOwner().AddOfficer(attackerFlank1);
attacker.GetOwner().RemoveOfficer(attackerFlank1);
attackerFlank1.ModifyLoyalty(15);
if (defender.GetOwner().isHuman)
{
uiHandler.OfficerGained(attackerFlank1);
}
if (attacker.GetOwner().isHuman)
{
string logMessage = $"{attackerFlank1.GetName()} was captured and persuaded to join {defender.GetOwner().GetFactionLeader().GetName()}!";
uiHandler.LogMessage(logMessage, defender.GetOwner().GetPlayerColor());
}
}
}
}
if (attackerFlank2 != null)
{
attackerFlank2.ModifyLoyalty(-15);
if (attackerFlank2.GetLoyalty() < 25)
{
int captureRoll = Random.Range(0, 2);
if (captureRoll == 0)
{
defender.GetOwner().AddOfficer(attackerFlank2);
attacker.GetOwner().RemoveOfficer(attackerFlank2);
attackerFlank2.ModifyLoyalty(15);
if (defender.GetOwner().isHuman)
{
uiHandler.OfficerGained(attackerFlank2);
}
if (attacker.GetOwner().isHuman)
{
string logMessage = $"{attackerFlank2.GetName()} was captured and persuaded to join {defender.GetOwner().GetFactionLeader().GetName()}!";
uiHandler.LogMessage(logMessage, defender.GetOwner().GetPlayerColor());
}
}
}
}
}
if (defender.GetSize() == 0)
{
if (defenderCenter != null)
{
defenderCenter.ModifyLoyalty(-15);
if (defenderCenter.GetLoyalty() < 25)
{
int captureRoll = Random.Range(0, 2);
if (captureRoll == 0)
{
attacker.GetOwner().AddOfficer(defenderCenter);
defender.GetOwner().RemoveOfficer(defenderCenter);
defenderCenter.ModifyLoyalty(15);
if (attacker.GetOwner().isHuman)
{
uiHandler.OfficerGained(defenderCenter);
}
if (defender.GetOwner().isHuman)
{
string logMessage = $"{defenderCenter.GetName()} was captured and persuaded to join {attacker.GetOwner().GetFactionLeader().GetName()}!";
uiHandler.LogMessage(logMessage, attacker.GetOwner().GetPlayerColor());
}
}
}
}
if (defenderFlank1 != null)
{
defenderFlank1.ModifyLoyalty(-15);
if (defenderFlank1.GetLoyalty() < 25)
{
int captureRoll = Random.Range(0, 2);
if (captureRoll == 0)
{
attacker.GetOwner().AddOfficer(defenderFlank1);
defender.GetOwner().RemoveOfficer(defenderFlank1);
defenderFlank1.ModifyLoyalty(15);
if (attacker.GetOwner().isHuman)
{
uiHandler.OfficerGained(defenderFlank1);
}
if (defender.GetOwner().isHuman)
{
string logMessage = $"{defenderFlank1.GetName()} was captured and persuaded to join {attacker.GetOwner().GetFactionLeader().GetName()}!";
uiHandler.LogMessage(logMessage, attacker.GetOwner().GetPlayerColor());
}
}
}
}
if (defenderFlank2 != null)
{
defenderFlank2.ModifyLoyalty(-15);
if (defenderFlank2.GetLoyalty() < 25)
{
int captureRoll = Random.Range(0, 2);
if (captureRoll == 0)
{
attacker.GetOwner().AddOfficer(defenderFlank2);
defender.GetOwner().RemoveOfficer(defenderFlank2);
defenderFlank2.ModifyLoyalty(15);
if (attacker.GetOwner().isHuman)
{
uiHandler.OfficerGained(defenderFlank2);
}
if (defender.GetOwner().isHuman)
{
string logMessage = $"{defenderFlank2.GetName()} was captured and persuaded to join {attacker.GetOwner().GetFactionLeader().GetName()}!";
uiHandler.LogMessage(logMessage, attacker.GetOwner().GetPlayerColor());
}
}
}
}
}
// battle report for human player
if (attacker.GetOwner().isHuman || defender.GetOwner().isHuman)
{
uiHandler.ShowBattleReport(attacker, defender, attackerRoll, defenderRoll, aCAttack, aCDefence, aF1Attack, aF1Defence, aF2Attack, aF2Defence, dCAttack, dCDefence, dF1Attack, dF1Defence, dF2Attack, dF2Defence,
aCTactic, dCTactic, aF1Tactic, dF1Tactic, aF2Tactic, dF2Tactic
);
mainCamera.transform.position = new Vector3(currentNode.transform.position.x, currentNode.transform.position.y, mainCamera.transform.position.z);
requirePlayerInput = true;
}
}
string ChooseCombatTactic(Officer officer) { List<string>availableTactics = new List<string>();
foreach (string trait in officer.GetTraits())
{
switch (trait)
{
case "Brave":
availableTactics.Add("Charge");
availableTactics.Add("First Strike");
break;
case "Calm":
availableTactics.Add("Adaptive");
availableTactics.Add("Skirmish");
break;
case "Siren":
availableTactics.Add("Alluring Song");
availableTactics.Add("Piercing Screech");
availableTactics.Add("Alluring Song");
availableTactics.Add("Piercing Screech");
break;
case "Princess of the Moon":
availableTactics.Add("Nightmare");
availableTactics.Add("Nightmare");
break;
case "Princess of the Sun":
availableTactics.Add("To The Moon");
availableTactics.Add("To The Moon");
break;
case "Princess of Love":
availableTactics.Add("Crystal Shield");
availableTactics.Add("Crystal Shield");
break;
case "Princess of Friendship":
availableTactics.Add("Friendship Laser");
availableTactics.Add("Friendship Laser");
break;
case "Great and Powerful":
availableTactics.Add("Smokescreen");
availableTactics.Add("Disrupt");
availableTactics.Add("Gamble Cast");
break;
case "God of Chaos":
availableTactics.Add("Discord");
availableTactics.Add("Disrupt");
availableTactics.Add("Timewarp");
availableTactics.Add("Gamble Cast");
break;
case "Yak":
availableTactics.Add("Smash");
availableTactics.Add("Crush");
availableTactics.Add("Smash");
availableTactics.Add("Crush");
break;
case "Dragon":
availableTactics.Add("Scorch");
availableTactics.Add("Smokescreen");
break;
case "Alicorn":
availableTactics.Add("Magical Barrier");
availableTactics.Add("Alicorn Magic");
break;
case "Kirin":
availableTactics.Add("Bamboo Dance");
break;
case "Changeling":
availableTactics.Add("Deceive");
availableTactics.Add("Infiltrate");
break;
case "Adept Commander":
availableTactics.Add("Feint");
availableTactics.Add("Taunt");
availableTactics.Add("Raid");
availableTactics.Add("Shieldwall");
break;
case "Expert Commander":
availableTactics.Add("Fire Attack");
availableTactics.Add("Pincer");
availableTactics.Add("Unyielding");
break;
case "Adept Mage":
availableTactics.Add("Protective Bubble");
availableTactics.Add("Magical Artillery");
availableTactics.Add("Enchanted Weapons");
break;
case "Expert Mage":
availableTactics.Add("Teleportation");
availableTactics.Add("Elemental Beam");
availableTactics.Add("Firestorm");
availableTactics.Add("Earthquake");
break;
case "Charged":
availableTactics.Add("Lightning Strike");
break;
case "Musician":
availableTactics.Add("Inspire");
break;
case "Trickster":
availableTactics.Add("Decoy");
availableTactics.Add("Feint");
if (officer.magic > 80)
{
availableTactics.Add("Gamble Cast");
}
break;
case "Queen of the Changelings":
availableTactics.Add("Overwhelm");
break;
case "Timelord":
availableTactics.Add("Timewarp");
break;
case "Cutie Mark Crusader":
availableTactics.Add("Rousing Speech");
availableTactics.Add("Lead By Example");
break;
case "Father of Monsters":
availableTactics.Add("Grogar's Bell");
availableTactics.Add("Grogar's Bell");
break;
case "Mystic":
availableTactics.Add("Eldritch Horror");
break;
case "Cheerleader":
availableTactics.Add("Inspire");
availableTactics.Add("Dance");
break;
case "Inspiring Leader":
availableTactics.Add("Rousing Speech");
availableTactics.Add("First Strike");
availableTactics.Add("Maintain Order");
break;
case "Examplary Leader":
availableTactics.Add("Rousing Speech");
availableTactics.Add("Hold The Line");
availableTactics.Add("Lead By Example");
break;
}
}
if (availableTactics.Count == 0)
{
availableTactics.Add("Aggressive");
availableTactics.Add("Defensive");
}
return availableTactics[Random.Range(0, availableTactics.Count)];
}
float GetTacticAttackBonus(string tactic)
{
switch (tactic)
{
case "Aggressive":
return 1.05f;
case "Defensive":
return 0.95f;
case "Charge":
return 1.2f;
case "Adaptive":
return 1.05f;
case "Alluring Song":
return 1.05f;
case "Piercing Screech":
return 1.2f;
case "Nightmare":
return 1.7f;
case "To The Moon":
return 1.7f;
case "Crystal Shield":
return 1f;
case "Friendship Laser":
return 1.7f;
case "Smokescreen":
return 0.7f;
case "Disrupt":
return 1.2f;
case "Discord":
return 1.5f;
case "Timewarp":
return 1.5f;
case "Smash":
return 1.2f;
case "Crush":
return 1.3f;
case "Scorch":
return 1.2f;
case "Magical Barrier":
return 1f;
case "Alicorn Magic":
return 1.4f;
case "Bamboo Dance":
return 1f;
case "Deceive":
return 1.15f;
case "Infiltrate":
return 1.25f;
case "Feint":
return 0.8f;
case "Taunt":
return 1.35f;
case "Raid":
return 1.3f;
case "Shieldwall":
return 0.8f;
case "Fire Attack":
return 1.6f;
case "Pincer":
return 1.5f;
case "Unyielding":
return 1f;
case "Protective Bubble":
return 0.95f;
case "Magical Artillery":
return 1.1f;
case "Enchanted Weapons":
return 1.15f;
case "Teleportation":
return 1.25f;
case "Elemental Beam":
return 1.4f;
case "Firestorm":
return 1.4f;
case "Earthquake":
return 1.4f;
case "Lightning Strike":
return 1.4f;
case "Inspire":
return 1.1f;
case "Decoy":
return 1.1f;
case "Overwhelm":
return 1.7f;
case "Grogar's Bell":
return 2f;
case "Eldritch Horror":
return 1.5f;
case "Dance":
return 1.15f;
case "Lead By Example":
return 1.15f;
case "First Strike":
return 1.15f;
case "Rousing Speech":
return 1.1f;
case "Maintain Order":
return 0.8f;
case "Hold The Line":
return 1.1f;
case "Gamble Cast":
return Random.Range(0.2f, 2f);
default:
return 1f;
}
}
float GetTacticDefenceBonus(string tactic)
{
switch (tactic)
{
case "Aggressive":
return 0.95f;
case "Defensive":
return 1.05f;
case "Charge":
return 0.9f;
case "Adaptive":
return 1.05f;
case "Alluring Song":
return 1.2f;
case "Piercing Screech":
return 1.05f;
case "Nightmare":
return 1.2f;
case "To The Moon":
return 1.2f;
case "Crystal Shield":
return 2.5f;
case "Friendship Laser":
return 1.2f;
case "Smokescreen":
return 1.7f;
case "Disrupt":
return 1f;
case "Discord":
return 1.2f;
case "Timewarp":
return 1.5f;
case "Smash":
return 1f;
case "Crush":
return 0.9f;
case "Scorch":
return 1f;
case "Magical Barrier":
return 2f;
case "Alicorn Magic":
return 1.1f;
case "Bamboo Dance":
return 1.5f;
case "Deceive":
return 1.15f;
case "Infiltrate":
return 1f;
case "Feint":
return 1.2f;
case "Taunt":
return 0.85f;
case "Raid":
return 1f;
case "Shieldwall":
return 1.6f;
case "Fire Attack":
return 0.7f;
case "Pincer":
return 1f;
case "Unyielding":
return 1.8f;
case "Protective Bubble":
return 1.8f;
case "Magical Artillery":
return 1.3f;
case "Enchanted Weapons":
return 1.15f;
case "Teleportation":
return 1.25f;
case "Elemental Beam":
return 1.2f;
case "Firestorm":
return 1.2f;
case "Earthquake":
return 1.2f;
case "Lightning Strike":
return 1.2f;
case "Inspire":
return 1.1f;
case "Decoy":
return 1.15f;
case "Overwhelm":
return 1.2f;
case "Grogar's Bell":
return 1.5f;
case "Eldritch Horror":
return 1f;
case "Dance":
return 1.15f;
case "Lead By Example":
return 1.15f;
case "First Strike":
return 1f;
case "Rousing Speech":
return 1.10f;
case "Maintain Order":
return 1.4f;
case "Hold The Line":
return 1.6f;
case "Skirmish":
return 1.1f;
case "Gamble Cast":
return Random.Range(0.2f, 2f);
default:
return 1f;
}
}
by Guest
by Guest
by Guest
by Guest
by Guest