From 88a4a5769b365ee38e6038ea0fb97353e94a415c Mon Sep 17 00:00:00 2001
From: Blank_Alt <12406-Blank_Alt@users.noreply.gitgud.io>
Date: Sat, 3 Jul 2021 11:02:16 +0000
Subject: [PATCH] Sec exp js conversion handlers

---
 src/005-passages/eventsPassages.js         |   5 +
 src/Mods/SecExp/events/attackHandler.tw    | 480 ------------------
 src/Mods/SecExp/events/attackOptions.js    |   4 +-
 src/Mods/SecExp/events/conflictHandler.js  | 546 +++++++++++++++++++++
 src/Mods/SecExp/events/rebellionHandler.tw | 326 ------------
 src/Mods/SecExp/events/rebellionOptions.tw |   4 +-
 6 files changed, 555 insertions(+), 810 deletions(-)
 delete mode 100644 src/Mods/SecExp/events/attackHandler.tw
 create mode 100644 src/Mods/SecExp/events/conflictHandler.js
 delete mode 100644 src/Mods/SecExp/events/rebellionHandler.tw

diff --git a/src/005-passages/eventsPassages.js b/src/005-passages/eventsPassages.js
index 23f3c9a7655..1de72b4c438 100644
--- a/src/005-passages/eventsPassages.js
+++ b/src/005-passages/eventsPassages.js
@@ -16,6 +16,11 @@ new App.DomPassage("rebellionReport",
 		return App.Events.rebellionReport();
 	}
 );
+new App.DomPassage("conflictHandler",
+	() => {
+		return App.Events.conflictHandler();
+	}
+);
 
 /* ### Random Events ### */
 
diff --git a/src/Mods/SecExp/events/attackHandler.tw b/src/Mods/SecExp/events/attackHandler.tw
deleted file mode 100644
index 53a34b487e3..00000000000
--- a/src/Mods/SecExp/events/attackHandler.tw
+++ /dev/null
@@ -1,480 +0,0 @@
-:: attackHandler [nobr]
-
-<<set $nextButton = " ", $nextLink = "attackReport", $encyclopedia = "Battles">>
-<<set _isMajorBattle = $SecExp.war.type.includes("Major")>>
-
-<<if $SecExp.war.result == 1 || $SecExp.war.result == -1>>	/* bribery/surrender check */
-	<<if $SecExp.settings.showStats == 1>>
-		<<if $SecExp.war.result == 1>>Bribery<<else>>Surrender<</if>> chosen
-	<</if>>
-	<<if $SecExp.war.result == 1>>
-		<<if $cash >= App.SecExp.battle.bribeCost()>> /* if there's enough cash there's a 10% chance bribery fails. If there isn't there's instead a 50% chance it fails */
-			<<if $SecExp.war.attacker.type == "freedom fighters" && random(1,100) <= 50 || random(1,100) <= 10>>
-				<<set $SecExp.war.result = 0>>
-			<</if>>
-		<<else>>
-			<<if random(1,100) <= 50>> <<set $SecExp.war.result = 0>> <</if>>
-		<</if>>
-		<<if $SecExp.settings.showStats == 1>>
-			<br>Bribery <<if $SecExp.war.result == 0>>failed<<else>>Successful<</if>>!
-			<br><br>[[proceed|attackReport]]
-		<<else>>
-			<<goto "attackReport">>
-		<</if>>
-	<<else>>
-		<<goto "attackReport">>
-	<</if>>
-<<else>>
-	/*Init*/
-	<<set _turns = 10>>
-	<<set _attack = 0>>
-	<<set _defense = 0>>
-	<<set _morale = 0>>
-	<<set _hp = 0>>
-	<<set _baseHp = 0>>
-	<<set _enemyAttack = 0>>
-	<<set _enemyDefense = 0>>
-	<<set _enemyMorale = 0>>
-	<<set _enemyHp = 0>>
-	<<set _enemyBaseHp = 0>>
-	<<set _tacChance = 0.5>>								/* by default tactics have a 50% chance of succeeding */
-	<<set _atkMod = 1>>
-	<<set _defMod = 1>>
-	<<set _militiaMod = 1>>
-	<<set _slaveMod = 1>>
-	<<set _mercMod = 1>>
-	<<set _enemyMod = 1>>
-	<<set _SFMod = 1>>
-	<<set _armyMod = 0>>
-
-	/* major battle */
-	<<if _isMajorBattle>>
-		<<set _militiaMod = 1.5>>
-		<<set _slaveMod = 1.5>>
-		<<set _mercMod = 1.5>>
-		<<set _enemyMod = 1.5>>
-		<<set _SFMod = 1.5>>
-		<<set _turns *= 2>>
-		<<if $SF.Toggle && $SF.Active >= 1>>
-			<<if $SF.Squad.Firebase >= 7>>
-				<<set _atkMod += ($SF.Squad.Firebase - 6) * 0.05>>
-			<</if>>
-			<<if $SF.Squad.GunS >= 1>>
-				<<set _defMod += $SF.Squad.GunS * 0.05>>
-			<</if>>
-			<<if $SF.Squad.Satellite >= 5 && $SF.SatLaunched > 0>>
-				<<set _atkMod += ($SF.Squad.Satellite - 5) * 0.05>>
-			<</if>>
-			<<if $SF.Squad.GiantRobot >= 6>>
-				<<set _defMod += ($SF.Squad.GiantRobot - 5) * 0.05>>
-			<</if>>
-			<<if $SF.Squad.MissileSilo >= 1>>
-				<<set _atkMod += $SF.Squad.MissileSilo * 0.05>>
-			<</if>>
-		<</if>>
-	<</if>>
-
-	<<set _commanderEffectiveness = App.SecExp.commanderEffectiveness("handler")>>
-	<<set _slaveMod += _commanderEffectiveness.slaveMod>>
-	<<set _militiaMod += _commanderEffectiveness.militiaMod>>
-	<<set _mercMod += _commanderEffectiveness.mercMod>>
-	<<set _SFMod += _commanderEffectiveness.SFMod>>
-	<<set _enemyMod += _commanderEffectiveness.enemyMod>>
-	<<set _atkMod += _commanderEffectiveness.atkMod>>
-	<<set _defMod += _commanderEffectiveness.defMod>>
-	<<set _tacChance += _commanderEffectiveness.tacChance>>
-
-	/* Terrain and Tactics */
-	<<set _tacticsObj = App.Data.SecExp.TerrainAndTactics.get($SecExp.war.terrain)[$SecExp.war.chosenTactic]>>
-	<<set _atkMod += _tacticsObj.atkMod>>
-	<<set _defMod += _tacticsObj.defMod>>
-	<<set _tacChance += _tacticsObj.tacChance>>
-
-	<<if $SecExp.war.chosenTactic == "Bait and Bleed">>
-		<<if $SecExp.war.attacker.type == "raiders">>
-			<<set _tacChance -= 0.10>>
-		<<elseif $SecExp.war.attacker.type == "free city">>
-			<<set _tacChance += 0.10>>
-		<<elseif $SecExp.war.attacker.type == "old world">>
-			<<set _tacChance += 0.25>>
-		<<elseif $SecExp.war.attacker.type == "freedom fighters">>
-			<<set _tacChance -= 0.15>>
-		<</if>>
-	<<elseif $SecExp.war.chosenTactic == "Guerrilla">>
-		<<if $SecExp.war.attacker.type == "raiders">>
-			<<set _tacChance -= 0.20>>
-		<<elseif $SecExp.war.attacker.type == "free city">>
-			<<set _tacChance += 0.15>>
-		<<elseif $SecExp.war.attacker.type == "old world">>
-			<<set _tacChance += 0.25>>
-		<<elseif $SecExp.war.attacker.type == "freedom fighters">>
-			<<set _tacChance -= 0.25>>
-		<</if>>
-	<<elseif $SecExp.war.chosenTactic == "Choke Points">>
-		<<if $SecExp.war.attacker.type == "raiders">>
-			<<set _tacChance += 0.25>>
-		<<elseif $SecExp.war.attacker.type == "free city">>
-			<<set _tacChance -= 0.05>>
-		<<elseif $SecExp.war.attacker.type == "old world">>
-			<<set _tacChance -= 0.10>>
-		<<elseif $SecExp.war.attacker.type == "freedom fighters">>
-			<<set _tacChance += 0.05>>
-		<</if>>
-	<<elseif $SecExp.war.chosenTactic == "Interior Lines">>
-		<<if $SecExp.war.attacker.type == "raiders">>
-			<<set _tacChance -= 0.15>>
-		<<elseif $SecExp.war.attacker.type == "free city">>
-			<<set _tacChance += 0.15>>
-		<<elseif $SecExp.war.attacker.type == "old world">>
-			<<set _tacChance += 0.20>>
-		<<elseif $SecExp.war.attacker.type == "freedom fighters">>
-			<<set _tacChance -= 0.10>>
-		<</if>>
-	<<elseif $SecExp.war.chosenTactic == "Pincer Maneuver">>
-		<<if $SecExp.war.attacker.type == "raiders">>
-			<<set _tacChance += 0.15>>
-		<<elseif $SecExp.war.attacker.type == "free city">>
-			<<set _tacChance += 0.10>>
-		<<elseif $SecExp.war.attacker.type == "old world">>
-			<<set _tacChance -= 0.10>>
-		<<elseif $SecExp.war.attacker.type == "freedom fighters">>
-			<<set _tacChance += 0.15>>
-		<</if>>
-	<<elseif $SecExp.war.chosenTactic == "Defense In Depth">>
-		<<if $SecExp.war.attacker.type == "raiders">>
-			<<set _tacChance -= 0.20>>
-		<<elseif $SecExp.war.attacker.type == "free city">>
-			<<set _tacChance += 0.10>>
-		<<elseif $SecExp.war.attacker.type == "old world">>
-			<<set _tacChance += 0.20>>
-		<<elseif $SecExp.war.attacker.type == "freedom fighters">>
-			<<set _tacChance -= 0.05>>
-		<</if>>
-	<<elseif $SecExp.war.chosenTactic == "Blitzkrieg">>
-		<<if $SecExp.war.attacker.type == "raiders">>
-			<<set _tacChance += 0.10>>
-		<<elseif $SecExp.war.attacker.type == "free city">>
-			<<set _tacChance -= 0.20>>
-		<<elseif $SecExp.war.attacker.type == "old world">>
-			<<set _tacChance += 0.25>>
-		<<elseif $SecExp.war.attacker.type == "freedom fighters">>
-			<<set _tacChance -= 0.10>>
-		<</if>>
-	<<elseif $SecExp.war.chosenTactic == "Human Wave">>
-		<<if $SecExp.war.attacker.type == "raiders">>
-			<<set _tacChance -= 0.10>>
-		<<elseif $SecExp.war.attacker.type == "free city">>
-			<<set _tacChance += 0.10>>
-		<<elseif $SecExp.war.attacker.type == "old world">>
-			<<set _tacChance -= 0.15>>
-		<<elseif $SecExp.war.attacker.type == "freedom fighters">>
-			<<set _tacChance += 0.10>>
-		<</if>>
-	<</if>>
-
-	/* Calculates if tactics are successful */
-	/* minimum chance is 10% */
-	<<if _tacChance <= 0>>
-		<<set _tacChance = 0.1>>
-	<</if>>
-	<<if random(1,100) <= _tacChance * 100>>
-		<<set _enemyMod -= 0.30>>
-		<<set _militiaMod += 0.20>>
-		<<set _slaveMod += 0.20>>
-		<<set _mercMod += 0.20>>
-		<<set _atkMod += 0.10>>
-		<<set _defMod += 0.10>>
-		<<set $SecExp.war.tacticsSuccessful = 1>>
-	<<else>>
-		<<set _enemyMod += 0.20>>
-		<<set _militiaMod -= 0.20>>
-		<<set _slaveMod -= 0.20>>
-		<<set _mercMod -= 0.20>>
-		<<set _atkMod -= 0.10>>
-		<<set _defMod -= 0.10>>
-	<</if>>
-
-	/* enemy morale mods */
-	<<if $week < 30>>
-		<<set _enemyMod += 0.15>>
-	<<elseif $week < 60>>
-		<<set _enemyMod += 0.30>>
-	<<elseif $week < 90>>
-		<<set _enemyMod += 0.45>>
-	<<elseif $week < 120>>
-		<<set _enemyMod += 0.60>>
-	<<else>>
-		<<set _enemyMod += 0.75>>
-	<</if>>
-
-	/* calculates PC army stats */
-	<<if App.SecExp.battle.deployedUnits('bots')>>
-		<<set _unit = App.SecExp.getUnit("bots")>>
-		<<set _attack += _unit.attack * _atkMod>>
-		<<set _defense += _unit.defense * _defMod>>
-		<<set _hp += _unit.hp>>
-	<</if>>
-	<<for _i = 0; _i < $SecExp.units.militia.squads.length; _i++>>
-		<<if $SecExp.units.militia.squads[_i].isDeployed == 1>>
-			<<set _unit = App.SecExp.getUnit("militia", _i)>>
-			<<set _attack += _unit.attack * _atkMod>>
-			<<set _defense += _unit.defense * _defMod>>
-			<<set _hp += _unit.hp>>
-		<</if>>
-	<</for>>
-	<<for _i = 0; _i < $SecExp.units.slaves.squads.length; _i++>>
-		<<if $SecExp.units.slaves.squads[_i].isDeployed == 1>>
-			<<set _unit = App.SecExp.getUnit("slaves", _i)>>
-			<<set _attack += _unit.attack * _atkMod>>
-			<<set _defense += _unit.defense * _defMod>>
-			<<set _hp += _unit.hp>>
-		<</if>>
-	<</for>>
-	<<for _i = 0; _i < $SecExp.units.mercs.squads.length; _i++>>
-		<<if $SecExp.units.mercs.squads[_i].isDeployed == 1>>
-			<<set _unit = App.SecExp.getUnit("mercs", _i)>>
-			<<set _attack += _unit.attack * _atkMod>>
-			<<set _defense += _unit.defense * _defMod>>
-			<<set _hp += _unit.hp>>
-		<</if>>
-	<</for>>
-
-	<<if $SF.Toggle && $SF.Active >= 1 && $SecExp.war.deploySF>>
-		<<set _unit = App.SecExp.getUnit("SF")>>
-		<<set _attack += _unit.attack>>
-		<<set _defense += _unit.defense>>
-		<<set _hp += _unit.hp>>
-	<</if>>
-
-	/* morale and baseHp calculation */
-	/* minimum modifier is -50%, maximum is +50% */
-	<<if _militiaMod < 0.5>>
-		<<set _militiaMod = 0.5>>
-	<<elseif _militiaMod > 1.5>>
-		<<set _militiaMod = 1.5>>
-	<</if>>
-	<<if _slaveMod < 0.5>>
-		<<set _slaveMod = 0.5>>
-	<<elseif _slaveMod > 1.5>>
-		<<set _slaveMod = 1.5>>
-	<</if>>
-	<<if _mercMod < 0.5>>
-		<<set _mercMod = 0.5>>
-	<<elseif _mercMod > 1.5>>
-		<<set _mercMod = 1.5>>
-	<</if>>
-	<<if _SFMod < 0.5>>
-		<<set _SFMod = 0.5>>
-	<<elseif _SFMod > 1.5>>
-		<<set _SFMod = 1.5>>
-	<</if>>
-
-	<<set _moraleTroopMod = Math.clamp(App.SecExp.battle.troopCount() / 100,1,5)>>
-
-	<<set _morale = (App.SecExp.BaseDroneUnit.morale * $SecExp.units.bots.isDeployed + App.SecExp.BaseMilitiaUnit.morale * _militiaMod * App.SecExp.battle.deployedUnits('militia') + App.SecExp.BaseSlaveUnit.morale * _slaveMod * App.SecExp.battle.deployedUnits('slaves') + App.SecExp.BaseMercUnit.morale * _mercMod * App.SecExp.battle.deployedUnits('mercs') + App.SecExp.BaseSpecialForcesUnit.morale * $SecExp.war.deploySF * _SFMod) / ($SecExp.units.bots.isDeployed + App.SecExp.battle.deployedUnits('militia') + App.SecExp.battle.deployedUnits('slaves') + App.SecExp.battle.deployedUnits('mercs') + $SecExp.war.deploySF)>>
-	<<if $SecExp.buildings.barracks>>
-		<<set _morale = _morale + _morale * $SecExp.buildings.barracks.luxury * 0.05>>	/* barracks bonus */
-	<</if>>
-	<<set _morale *= _moraleTroopMod>>
-	<<set _baseHp = (App.SecExp.BaseDroneUnit.hp * $SecExp.units.bots.isDeployed + App.SecExp.BaseMilitiaUnit.hp * App.SecExp.battle.deployedUnits('militia') + App.SecExp.BaseSlaveUnit.hp * App.SecExp.battle.deployedUnits('slaves') + App.SecExp.BaseMercUnit.hp * App.SecExp.battle.deployedUnits('mercs') + App.SecExp.BaseSpecialForcesUnit.hp * $SecExp.war.deploySF) / ($SecExp.units.bots.isDeployed + App.SecExp.battle.deployedUnits('militia') + App.SecExp.battle.deployedUnits('slaves') + App.SecExp.battle.deployedUnits('mercs') + $SecExp.war.deploySF)>>
-
-	/* calculates enemy army stats */
-	<<if $week <= 30>>
-		<<set _armyMod = $SecExp.war.attacker.troops / 80>>
-	<<elseif $week <= 60>>
-		<<set _armyMod = $SecExp.war.attacker.troops / 75>>
-	<<elseif $week <= 90>>
-		<<set _armyMod = $SecExp.war.attacker.troops / 70>>
-	<<elseif $week <= 120>>
-		<<set _armyMod = $SecExp.war.attacker.troops / 65>>
-	<<else>>
-		<<set _armyMod = $SecExp.war.attacker.troops / 60>>
-	<</if>>
-	<<set _armyMod = Math.trunc(_armyMod)>>
-	<<if _isMajorBattle>>
-		<<set _armyMod *= 2>>
-	<</if>>
-	<<if _armyMod <= 0>>
-		<<set _armyMod = 1>>
-	<</if>>
-
-	<<set _enemyMoraleTroopMod = Math.clamp($SecExp.war.attacker.troops / 100,1,5)>>
-
-	<<set _unit = App.SecExp.getEnemyUnit($SecExp.war.attacker.type, $SecExp.war.attacker.troops, $SecExp.war.attacker.equip)>>
-	<<set _enemyAttack = _unit.attack * _armyMod>>
-	<<set _enemyDefense = _unit.defense * _armyMod>>
-	<<set _enemyMorale = _unit.morale * _enemyMod * _enemyMoraleTroopMod>>
-	<<set _enemyHp = _unit.hp>>
-	<<set _enemyBaseHp = _unit.hp / $SecExp.war.attacker.troops>>
-
-	/* difficulty */
-	<<set _enemyAttack *= $SecExp.settings.difficulty>>
-	<<set _enemyDefense *= $SecExp.settings.difficulty>>
-	<<set _enemyMorale *= $SecExp.settings.difficulty>>
-	<<set _enemyHp *= $SecExp.settings.difficulty>>
-	<<set _enemyBaseHp *= $SecExp.settings.difficulty>>
-
-	<<if isNaN(_attack)>>
-		<br>@@.red;Error: attack value reported NaN@@
-	<</if>>
-	<<if isNaN(_defense)>>
-		<br>@@.red;Error: defense value reported NaN@@
-	<</if>>
-	<<if isNaN(_hp)>>
-		<br>@@.red;Error: hp value reported NaN@@
-	<</if>>
-	<<if isNaN(_morale)>>
-		<br>@@.red;Error: morale value reported NaN@@
-	<</if>>
-	<<if isNaN(_enemyAttack)>>
-		<br>@@.red;Error: enemy attack value reported NaN@@
-	<</if>>
-	<<if isNaN(_enemyDefense)>>
-		<br>@@.red;Error: enemy defense value reported NaN@@
-	<</if>>
-	<<if isNaN(_enemyHp)>>
-		<br>@@.red;Error: enemy hp value reported NaN@@
-	<</if>>
-	<<if isNaN(_enemyMorale)>>
-		<br>@@.red;Error: enemy morale value reported NaN@@
-	<</if>>
-
-	<<if $SecExp.settings.showStats == 1>>
-		<<set _atkMod -= 1, _defMod -= 1, _militiaMod -= 1, _mercMod -= 1, _slaveMod -= 1, _SFMod -= 1, _enemyMod -= 1, _moraleTroopMod -= 1, _enemyMoraleTroopMod -= 1, _difficulty = $SecExp.settings.difficulty -1>>
-		<<set _atkMod = Math.round(_atkMod * 100)>>
-		<<set _defMod = Math.round(_defMod * 100)>>
-		<<set _militiaMod = Math.round(_militiaMod * 100)>>
-		<<set _mercMod = Math.round(_mercMod * 100)>>
-		<<set _slaveMod = Math.round(_slaveMod * 100)>>
-		<<set _SFMod = Math.round(_SFMod * 100)>>
-		<<set _enemyMod = Math.round(_enemyMod * 100)>>
-		<<if $SecExp.buildings.barracks>>
-			<<set _barracksBonus = $SecExp.buildings.barracks.luxury * 5>>
-		<</if>>
-		<<set _moraleTroopMod = Math.round(_moraleTroopMod * 100)>>
-		<<set _enemyMoraleTroopMod = Math.round(_enemyMoraleTroopMod * 100)>>
-		<<set _difficulty *= 100>>
-
-		__Difficulty__:<br>
-		<<if $SecExp.settings.difficulty == 0.5>>
-			Very easy
-		<<elseif $SecExp.settings.difficulty == 0.75>>
-			Easy
-		<<elseif $SecExp.settings.difficulty == 1>>
-			Normal
-		<<elseif $SecExp.settings.difficulty == 1.25>>
-			Hard
-		<<elseif $SecExp.settings.difficulty == 1.5>>
-			Very hard
-		<<else>>
-			Extremely hard
-		<</if>>
-		<br><br>__Army__:
-		<br>troops: <<print num(Math.round(App.SecExp.battle.troopCount()))>>
-		<br>attack: <<print num(Math.round(_attack))>>
-		<br>defense: <<print num(Math.round(_defense))>>
-		<br>hp: <<print num(Math.round(_hp))>>
-		<br>morale: <<print num(Math.round(_morale))>>
-		<br>attack modifier: <<if _atkMod > 0>>+<</if>>_atkMod%
-		<br>defense modifier: <<if _defMod > 0>>+<</if>>_defMod%
-		<br>average base HP: <<print num(Math.round(_baseHp))>>
-		<br>militia morale modifier: <<if _militiaMod > 0>>+<</if>>_militiaMod%
-		<br>slaves morale modifier: <<if _slaveMod > 0>>+<</if>>_slaveMod%
-		<br>mercenaries morale modifier: <<if _mercMod > 0>>+<</if>>_mercMod%
-		<<if $SF.Toggle && $SF.Active >= 1 && $SecExp.war.deploySF>>
-		<br>special force morale modifier: <<if _SFMod > 0>>+<</if>>_SFMod%
-		<</if>>
-		<<if $SecExp.buildings.barracks && $SecExp.buildings.barracks.luxury >= 1>>
-			<br>Barracks bonus morale modifier: +<<print _barracksBonus>>%
-		<</if>>
-		<<if _moraleTroopMod>>
-			<br>morale increase due to troop numbers: +<<print _moraleTroopMod>>%
-		<</if>>
-		<br><br>__Tactics__:
-		<br>tactic chance of success: <<print num(Math.round(_tacChance * 100))>>%
-		<br>was tactic chosen successful?: <<if $SecExp.war.tacticsSuccessful == 1>> yes <<else>> no<</if>>
-		<br><br>__Enemy__:
-		<br>enemy troops: <<print num(Math.round($SecExp.war.attacker.troops))>>
-		<br>enemy attack: <<print num(Math.round(_enemyAttack))>>
-		<br>enemy defense: <<print num(Math.round(_enemyDefense))>>
-		<br>enemy Hp: <<print num(Math.round(_enemyHp))>>
-		<br>enemy morale: <<print num(Math.round(_enemyMorale))>>
-		<br>enemy base Hp: <<print num(Math.round(_enemyBaseHp))>>
-		<br>enemy morale modifier: <<if _enemyMod > 0>>+<</if>>_enemyMod%
-		<<if _enemyMoraleTroopMod > 0>>
-			<br>enemy morale increase due to troop numbers: +<<print _enemyMoraleTroopMod>>%
-		<</if>>
-		<br>Difficulty modifier: <<if _difficulty > 0>>+<</if>><<print _difficulty>>%
-	<</if>>
-
-	/* simulates the combat by pitting attk against def */
-	<<for _i = 0; _i < _turns; _i++>>
-		<<if $SecExp.settings.showStats == 1>> <br><br>turn: <<print _i + 1>><</if>>
-		/* player army attacks */
-		<<set _damage = Math.clamp(_attack - _enemyDefense,_attack * 0.1,_attack)>>
-		<<if $SecExp.settings.showStats == 1>> <br>player damage: <<print num(Math.round(_damage))>><</if>>
-		<<set _enemyHp -= _damage>>
-		<<if $SecExp.settings.showStats == 1>> <br>remaining enemy Hp: <<print num(Math.round(_enemyHp))>><</if>>
-		<<set $SecExp.war.attacker.losses += _damage / _enemyBaseHp>>
-		<<set _moraleDamage = Math.clamp(_damage / 2 + _damage / _enemyBaseHp,0,_damage*1.5)>>
-		<<set _enemyMorale -= _moraleDamage>>
-		<<if $SecExp.settings.showStats == 1>> <br>remaining enemy morale: <<print num(Math.round(_enemyMorale))>><</if>>
-		<<if _enemyHp <= 0 || _enemyMorale <= 0>>
-			<<if $SecExp.settings.showStats == 1>> <br><br>Victory!<</if>>
-			<<set $SecExp.war.result = 3>>
-			<<set $SecExp.war.turns = _i>>
-			<<break>>
-		<</if>>
-
-		/* attacker army attacks */
-		<<set _damage = _enemyAttack - _defense>>
-		<<if _damage < _enemyAttack * 0.1>>
-			<<set _damage = _enemyAttack * 0.1>>
-		<</if>>
-		<<if $SecExp.settings.showStats == 1>> <br>enemy damage: <<print num(Math.round(_damage))>><</if>>
-		<<set _hp -= _damage>>
-		<<if $SecExp.settings.showStats == 1>> <br>remaining hp: <<print num(Math.round(_hp))>><</if>>
-		<<set $SecExp.war.losses += _damage / _baseHp>>
-		<<set _moraleDamage = Math.clamp(_damage / 2 + _damage / _baseHp,0,_damage*1.5)>>
-		<<set _morale -= _moraleDamage>>
-		<<if $SecExp.settings.showStats == 1>> <br>remaining morale: <<print Math.round(_morale)>><</if>>
-		<<if _hp <= 0 || _morale <= 0>>
-			<<if $SecExp.settings.showStats == 1>> <br><br>Defeat!<</if>>
-			<<set $SecExp.war.result = -3>>
-			<<set $SecExp.war.turns = _i>>
-			<<break>>
-		<</if>>
-	<</for>>
-	<<if $SecExp.war.result != 3 && $SecExp.war.result != -3>>
-		<<if _morale > _enemyMorale>>
-			<<if $SecExp.settings.showStats == 1>> <br><br>Partial victory!<</if>>
-			<<set $SecExp.war.result = 2>>
-		<<elseif _morale < _enemyMorale>>
-			<<if $SecExp.settings.showStats == 1>> <br><br>Partial defeat!<</if>>
-			<<set $SecExp.war.result = -2>>
-		<</if>>
-	<</if>>
-
-	<<if $SecExp.settings.showStats == 1>>
-		<br><br>Losses: <<print num(Math.trunc($SecExp.war.losses))>>
-		<br>Enemy losses: <<print num(Math.trunc($SecExp.war.attacker.losses))>>
-	<</if>>
-
-	<<if $SecExp.war.result > 3 || $SecExp.war.result < -3>>
-		<br><br>@@.red;Error: failed to determine battle result@@
-	<</if>>
-
-	<<if $SecExp.settings.showStats == 1>>
-		<<if _isMajorBattle && $SecExp.settings.battle.major.gameOver == 1 && $SecExp.war.result == -3>>
-			<br><br>[[Proceed|Gameover][$gameover = "major battle defeat"]]
-		<<else>>
-			<br><br>[[Proceed|attackReport]]
-		<</if>>
-	<<else>>
-		<<if _isMajorBattle && $SecExp.settings.battle.major.gameOver == 1 && $SecExp.war.result == -3>>
-			<<set $gameover = "major battle defeat">> <<goto "Gameover">>
-		<<else>>
-			<<goto "attackReport">>
-		<</if>>
-	<</if>>
-<</if>> /* closes check for bribery */
diff --git a/src/Mods/SecExp/events/attackOptions.js b/src/Mods/SecExp/events/attackOptions.js
index 5dba892c3bb..6c9ca8efa90 100644
--- a/src/Mods/SecExp/events/attackOptions.js
+++ b/src/Mods/SecExp/events/attackOptions.js
@@ -370,7 +370,7 @@ App.Events.attackOptions = class attackOptions extends App.Events.BaseEvent {
 				V.SecExp.war.result = 4;
 				V.SecExp.war.foughtThisWeek = 1;
 				/* sets V.SecExp.war.result value outside accepted range (-3, 3) to avoid evaluation problems */
-			}, `attackHandler`);
+			}, `conflictHandler`);
 		} else {
 			App.UI.DOM.appendNewElement("div", node, `You need at least a unit in your roster to proceed to battle.`, "red");
 		}
@@ -381,7 +381,7 @@ App.Events.attackOptions = class attackOptions extends App.Events.BaseEvent {
 		option.addButton(`Attempt to bribe`, () => {
 			V.SecExp.war.result = 1;
 			V.SecExp.war.foughtThisWeek = 1;
-		}, `attackHandler`);
+		}, `conflictHandler`);
 		option.addComment(`Will cost around ${cashFormat(Math.round(App.SecExp.battle.bribeCost() * (1 + either(-1, 1) * random(2) * 0.1)))} (estimate).`);
 		node.append(options.render());
 
diff --git a/src/Mods/SecExp/events/conflictHandler.js b/src/Mods/SecExp/events/conflictHandler.js
new file mode 100644
index 00000000000..bce5b4a15b1
--- /dev/null
+++ b/src/Mods/SecExp/events/conflictHandler.js
@@ -0,0 +1,546 @@
+App.Events.conflictHandler = function() {
+	V.nextButton = " ";
+	V.encyclopedia = "Battles";
+
+	const node = new DocumentFragment();
+	const showStats = V.SecExp.settings.showStats === 1;
+	const inBattle = V.SecExp.war.type.includes("Attack");
+	const isMajorBattle = inBattle && V.SecExp.war.type.includes("Major");
+	const inRebellion = V.SecExp.war.type.includes("Rebellion");
+	const turns = (isMajorBattle || inRebellion) ? 20 : 10;
+	const showProgress = function(message, tag = "div") {
+		if (showStats) {
+			App.UI.DOM.appendNewElement(tag, node, message);
+		}
+	};
+	const setResult = function(varA, varB, text, value, count) {
+		if (varA <= 0 || varB <= 0) {
+			showProgress(`${text}!`, "div");
+			V.SecExp.war.result = value;
+			V.SecExp.war.turns = count;
+		}
+	};
+	const atEnd = function(passage) {
+		if (showStats) {
+			App.UI.DOM.appendNewElement("div", node, App.UI.DOM.passageLink("Proceed", passage));
+		} else {
+			setTimeout(() => Engine.play(passage), Engine.minDomActionDelay);
+		}
+	};
+	const enemy = function() {
+		const node = new DocumentFragment();
+		App.UI.DOM.appendNewElement("div", node, `${inBattle ? 'Enemy' : 'Rebels'}`, "underline");
+		App.UI.DOM.appendNewElement("div", node, `Troops: ${num(Math.round(V.SecExp.war.attacker.troops))}`);
+		App.UI.DOM.appendNewElement("div", node, `Attack: ${num(Math.round(enemyAttack))}`);
+		App.UI.DOM.appendNewElement("div", node, `Defense: ${num(Math.round(enemyDefense))}`);
+		App.UI.DOM.appendNewElement("div", node, `HP: ${num(Math.round(enemyHp))}. Base: ${num(Math.round(enemyBaseHp))}`);
+		App.UI.DOM.appendNewElement("div", node, `Morale: ${num(Math.round(enemyMorale))}. ${inBattle ? `Modifier: ${num(Math.round(enemyMod))}.` : ``} Increase due to troop numbers: +${enemyMoraleTroopMod}%.`);
+		return node;
+	};
+	const turnReport = function() {
+		showProgress(`Turn: ${i + 1}`);
+		// player army attacks
+		damage = Math.clamp(attack -enemyDefense, attack * 0.1, attack);
+		showProgress(`Player damage: ${num(Math.round(damage))}`);
+		enemyHp -= damage;
+		showProgress(`Remaining enemy Hp: ${num(Math.round(enemyHp))}`);
+		V.SecExp.war.attacker.losses += damage / enemyBaseHp;
+		moraleDamage = Math.clamp(damage / 2 + damage / enemyBaseHp, 0, damage * 1.5);
+		enemyMorale -= moraleDamage;
+		showProgress(`Remaining enemy morale: ${num(Math.round(enemyMorale))}`);
+		setResult(enemyHp, enemyMorale, 'Victory', 3, i);
+
+		// attacker army attacks
+		damage = enemyAttack - defense;
+		if (damage < enemyAttack * 0.1) {
+			damage = enemyAttack * 0.1;
+		}
+		showProgress(`Enemy damage: ${num(Math.round(damage))}`);
+		hp -= damage * (inRebellion && V.SecExp.rebellions.sfArmor ? 0.85 : 1);
+		showProgress(`Remaining hp: ${num(Math.round(hp))}`);
+		V.SecExp.war.losses += damage / baseHp;
+		moraleDamage = Math.clamp(damage / 2 + damage / baseHp, 0, damage * 1.5);
+		morale -= moraleDamage;
+		showProgress(`Remaining morale: ${num(Math.round(morale))}`);
+		setResult(hp, morale, 'Defeat', -3, i);
+	};
+
+	let unitData;
+	let damage;
+	let moraleDamage;
+	let baseHp;
+	let enemyBaseHp;
+	let enemyMorale;
+	let attack = 0;
+	let defense = 0;
+	let morale = 0;
+	let hp = 0;
+	let enemyAttack = 0;
+	let enemyDefense = 0;
+	let enemyHp = 0;
+	let atkMod = 1;
+	let defMod = 1;
+	let armyMod = V.SecExp.war.attacker.troops / (inBattle ? 80 : 100);
+	// Battles
+	let militiaMod = (isMajorBattle) ? 1.5 : 1;
+	let slaveMod = (isMajorBattle) ? 1.5 : 1;
+	let mercMod = (isMajorBattle) ? 1.5 : 1;
+	let enemyMod = (isMajorBattle) ? 1.5 : 1;
+	let SFMod = (isMajorBattle) ? 1.5 : 1;
+	let tacChance = 0.5; // by default tactics have a 50% chance of succeeding
+	// Rebellions
+	let irregularMod = V.SecExp.war.irregulars / 60;
+	let engageMod = 0.5; // V.SecExp.war.engageRule === 0
+	let rebellingSlaves = 0;
+	let rebellingMilitia = 0;
+	let rebellingMercs = 0;
+
+	if (inBattle && V.SecExp.war.result === 1 || V.SecExp.war.result === -1) { // bribery/surrender check
+		showProgress(`${V.SecExp.war.result === 1 ? 'Bribery' : 'Surrender'} chosen`);
+		if (inBattle && V.SecExp.war.result === 1) {
+			if (V.cash >= App.SecExp.battle.bribeCost()) { // if there's enough cash there's a 10% chance bribery fails. If there isn't there's instead a 50% chance it fails
+				if (V.SecExp.war.attacker.type === "freedom fighters" && random(1, 100) <= 50 || random(1, 100) <= 10) {
+					V.SecExp.war.result = 0;
+				}
+			} else {
+				if (random(1, 100) <= 50) {
+					V.SecExp.war.result = 0;
+				}
+			}
+			showProgress(`${V.SecExp.war.result === 0 ? 'Failed' : 'Successful'}!`, "span");
+		}
+	}
+
+	if (inBattle) {
+		if (isMajorBattle) {
+			if (V.SF.Toggle && V.SF.Active >= 1) {
+				if (V.SF.Squad.Firebase >= 7) {
+					atkMod += (V.SF.Squad.Firebase - 6) * 0.05;
+				}
+				if (V.SF.Squad.GunS >= 1) {
+					defMod += V.SF.Squad.GunS * 0.05;
+				}
+				if (V.SF.Squad.Satellite >= 5 && V.SF.SatLaunched > 0) {
+					atkMod += (V.SF.Squad.Satellite - 5) * 0.05;
+				}
+				if (V.SF.Squad.GiantRobot >= 6) {
+					defMod += (V.SF.Squad.GiantRobot - 5) * 0.05;
+				}
+				if (V.SF.Squad.MissileSilo >= 1) {
+					atkMod += V.SF.Squad.MissileSilo * 0.05;
+				}
+			}
+		}
+
+		const commanderEffectiveness = App.SecExp.commanderEffectiveness("handler");
+		slaveMod += commanderEffectiveness.slaveMod;
+		militiaMod += commanderEffectiveness.militiaMod;
+		mercMod += commanderEffectiveness.mercMod;
+		SFMod += commanderEffectiveness.SFMod;
+		enemyMod += commanderEffectiveness.enemyMod;
+		atkMod += commanderEffectiveness.atkMod;
+		defMod += commanderEffectiveness.defMod;
+		tacChance += commanderEffectiveness.tacChance;
+
+		// Terrain and Tactics
+		const tacticsObj = App.Data.SecExp.TerrainAndTactics.get(V.SecExp.war.terrain)[V.SecExp.war.chosenTactic];
+		atkMod += tacticsObj.atkMod;
+		defMod += tacticsObj.defMod;
+		tacChance += tacticsObj.tacChance;
+
+		if (V.SecExp.war.chosenTactic === "Bait and Bleed") {
+			if (V.SecExp.war.attacker.type === "raiders") {
+				tacChance -= 0.10;
+			} else if (V.SecExp.war.attacker.type === "free city") {
+				tacChance += 0.10;
+			} else if (V.SecExp.war.attacker.type === "old world") {
+				tacChance += 0.25;
+			} else if (V.SecExp.war.attacker.type === "freedom fighters") {
+				tacChance -= 0.15;
+			}
+		} else if (V.SecExp.war.chosenTactic === "Guerrilla") {
+			if (V.SecExp.war.attacker.type === "raiders") {
+				tacChance -= 0.20;
+			} else if (V.SecExp.war.attacker.type === "free city") {
+				tacChance += 0.15;
+			} else if (V.SecExp.war.attacker.type === "old world") {
+				tacChance += 0.25;
+			} else if (V.SecExp.war.attacker.type === "freedom fighters") {
+				tacChance -= 0.25;
+			}
+		} else if (V.SecExp.war.chosenTactic === "Choke Points") {
+			if (V.SecExp.war.attacker.type === "raiders") {
+				tacChance += 0.25;
+			} else if (V.SecExp.war.attacker.type === "free city") {
+				tacChance -= 0.05;
+			} else if (V.SecExp.war.attacker.type === "old world") {
+				tacChance -= 0.10;
+			} else if (V.SecExp.war.attacker.type === "freedom fighters") {
+				tacChance += 0.05;
+			}
+		} else if (V.SecExp.war.chosenTactic === "Interior Lines") {
+			if (V.SecExp.war.attacker.type === "raiders") {
+				tacChance -= 0.15;
+			} else if (V.SecExp.war.attacker.type === "free city") {
+				tacChance += 0.15;
+			} else if (V.SecExp.war.attacker.type === "old world") {
+				tacChance += 0.20;
+			} else if (V.SecExp.war.attacker.type === "freedom fighters") {
+				tacChance -= 0.10;
+			}
+		} else if (V.SecExp.war.chosenTactic === "Pincer Maneuver") {
+			if (V.SecExp.war.attacker.type === "raiders") {
+				tacChance += 0.15;
+			} else if (V.SecExp.war.attacker.type === "free city") {
+				tacChance += 0.10;
+			} else if (V.SecExp.war.attacker.type === "old world") {
+				tacChance -= 0.10;
+			} else if (V.SecExp.war.attacker.type === "freedom fighters") {
+				tacChance += 0.15;
+			}
+		} else if (V.SecExp.war.chosenTactic === "Defense In Depth") {
+			if (V.SecExp.war.attacker.type === "raiders") {
+				tacChance -= 0.20;
+			} else if (V.SecExp.war.attacker.type === "free city") {
+				tacChance += 0.10;
+			} else if (V.SecExp.war.attacker.type === "old world") {
+				tacChance += 0.20;
+			} else if (V.SecExp.war.attacker.type === "freedom fighters") {
+				tacChance -= 0.05;
+			}
+		} else if (V.SecExp.war.chosenTactic === "Blitzkrieg") {
+			if (V.SecExp.war.attacker.type === "raiders") {
+				tacChance += 0.10;
+			} else if (V.SecExp.war.attacker.type === "free city") {
+				tacChance -= 0.20;
+			} else if (V.SecExp.war.attacker.type === "old world") {
+				tacChance += 0.25;
+			} else if (V.SecExp.war.attacker.type === "freedom fighters") {
+				tacChance -= 0.10;
+			}
+		} else if (V.SecExp.war.chosenTactic === "Human Wave") {
+			if (V.SecExp.war.attacker.type === "raiders") {
+				tacChance -= 0.10;
+			} else if (V.SecExp.war.attacker.type === "free city") {
+				tacChance += 0.10;
+			} else if (V.SecExp.war.attacker.type === "old world") {
+				tacChance -= 0.15;
+			} else if (V.SecExp.war.attacker.type === "freedom fighters") {
+				tacChance += 0.10;
+			}
+		}
+		tacChance = Math.clamp(tacChance, 0.1, tacChance); // Calculates if tactics are successful - minimum chance is 10%
+
+		if (random(1, 100) <= tacChance * 100) {
+			enemyMod -= 0.30;
+			militiaMod += 0.20;
+			slaveMod += 0.20;
+			mercMod += 0.20;
+			atkMod += 0.10;
+			defMod += 0.10;
+			V.SecExp.war.tacticsSuccessful = 1;
+		} else {
+			enemyMod += 0.20;
+			militiaMod -= 0.20;
+			slaveMod -= 0.20;
+			mercMod -= 0.20;
+			atkMod -= 0.10;
+			defMod -= 0.10;
+		}
+
+		// enemy morale mods
+		if (V.week < 30) {
+			enemyMod += 0.15;
+		} else if (V.week < 60) {
+			enemyMod += 0.30;
+		} else if (V.week < 90) {
+			enemyMod += 0.45;
+		} else if (V.week < 120) {
+			enemyMod += 0.60;
+		} else {
+			enemyMod += 0.75;
+		}
+	}
+
+	// calculates PC army stats
+	if (inRebellion) {
+		if (V.SecExp.war.engageRule === 1) {
+			engageMod = 0.75;
+		} else if (V.SecExp.war.engageRule === 2) {
+			engageMod = 1;
+		} else if (V.SecExp.war.engageRule > 2) {
+			engageMod = 1.4;
+		}
+
+		if (V.week > 30 && V.week <= 60) {
+			irregularMod = V.SecExp.war.irregulars / 50;
+		} else if (V.week <= 90) {
+			irregularMod = V.SecExp.war.irregulars / 40;
+		} else if (V.week <= 120) {
+			irregularMod = V.SecExp.war.irregulars / 30;
+		} else {
+			irregularMod = V.SecExp.war.irregulars / 20;
+		}
+		if (V.SecExp.war.irregulars > 0) {
+			irregularMod = Math.trunc(irregularMod);
+			unitData = App.SecExp.getIrregularUnit("militia", V.SecExp.war.irregulars, V.SecExp.war.attacker.equip);
+			attack += unitData.attack * irregularMod * 0.80;
+			defense += unitData.defense * irregularMod * 0.80;
+			hp += unitData.hp;
+		}
+	}
+
+	if (inBattle && App.SecExp.battle.deployedUnits('bots') || inRebellion && V.SecExp.units.bots.active === 1) {
+		unitData = App.SecExp.getUnit("bots");
+		attack += unitData.attack * atkMod;
+		defense += unitData.defense * defMod;
+		hp += unitData.hp;
+	}
+
+	for (const unit of App.SecExp.unit.list().slice(1)) {
+		for (let i = 0; i < V.SecExp.units[unit].squads.length; i++) {
+			if (App.SecExp.unit.isDeployed(V.SecExp.units[unit].squads[i])) {
+				unitData = App.SecExp.getUnit(unit, i);
+				attack += unitData.attack * atkMod;
+				defense += unitData.defense * defMod;
+				hp += unitData.hp;
+			}
+		}
+	}
+
+	if (V.SF.Toggle && V.SF.Active >= 1 && (inBattle && V.SecExp.war.deploySF || inRebellion)) {
+		unitData = App.SecExp.getUnit("SF");
+		attack += unitData.attack;
+		defense += unitData.defense;
+		hp += unitData.hp;
+	}
+
+	if (inRebellion && V.SecExp.war.assistantDefense) {
+		attack *= 0.95;
+		defense *= 0.95;
+		hp *= 0.95;
+	}
+	if (inRebellion && V.SecExp.war.reactorDefense) {
+		attack *= 0.95;
+		defense *= 0.95;
+		hp *= 0.95;
+	}
+	if (inRebellion && V.SecExp.war.penthouseDefense) {
+		attack *= 0.95;
+		defense *= 0.95;
+		hp *= 0.95;
+	}
+	if (inRebellion && V.SecExp.war.waterwayDefense) {
+		attack *= 0.95;
+		defense *= 0.95;
+		hp *= 0.95;
+	}
+
+	// morale and baseHp calculation
+	if (inBattle) { // minimum modifier is -50%, maximum is +50%
+		slaveMod = Math.clamp(slaveMod, 0.5, 1.5);
+		militiaMod = Math.clamp(militiaMod, 0.5, 1.5);
+		mercMod = Math.clamp(mercMod, 0.5, 1.5);
+		SFMod = Math.clamp(SFMod, 0.5, 1.5);
+	}
+	let moraleTroopMod = Math.clamp(App.SecExp.battle.troopCount() / 100, 1, (inBattle ? 5 : 10));
+
+	if (inBattle) {
+		morale += (App.SecExp.BaseDroneUnit.morale * V.SecExp.units.bots.isDeployed + App.SecExp.BaseMilitiaUnit.morale * militiaMod * App.SecExp.battle.deployedUnits('militia') + App.SecExp.BaseSlaveUnit.morale * slaveMod * App.SecExp.battle.deployedUnits('slaves') + App.SecExp.BaseMercUnit.morale * mercMod * App.SecExp.battle.deployedUnits('mercs') + App.SecExp.BaseSpecialForcesUnit.morale * V.SecExp.war.deploySF * SFMod) / (V.SecExp.units.bots.isDeployed + App.SecExp.battle.deployedUnits('militia') + App.SecExp.battle.deployedUnits('slaves') + App.SecExp.battle.deployedUnits('mercs') + V.SecExp.war.deploySF);
+		if (V.SecExp.buildings.barracks) {
+			morale = morale + morale * V.SecExp.buildings.barracks.luxury * 0.05;	// barracks bonus
+		}
+	} else {
+		morale += (App.SecExp.BaseDroneUnit.morale * V.SecExp.units.bots.active + App.SecExp.BaseMilitiaUnit.morale * App.SecExp.battle.deployedUnits('militia') + App.SecExp.BaseSlaveUnit.morale * App.SecExp.battle.deployedUnits('slaves') + App.SecExp.BaseMercUnit.morale * App.SecExp.battle.deployedUnits('mercs') + App.SecExp.BaseSpecialForcesUnit.morale * V.SF.Active) / (V.SecExp.units.bots.active + App.SecExp.battle.deployedUnits('militia') + App.SecExp.battle.deployedUnits('slaves') + App.SecExp.battle.deployedUnits('mercs') + V.SF.Active);
+		morale += morale * (V.SecExp.buildings.barracks ? V.SecExp.buildings.barracks.luxury * 0.05 : 0);	// barracks bonus
+	}
+	morale *= moraleTroopMod;
+	if (inBattle) {
+		baseHp = (App.SecExp.BaseDroneUnit.hp * V.SecExp.units.bots.isDeployed + App.SecExp.BaseMilitiaUnit.hp * App.SecExp.battle.deployedUnits('militia') + App.SecExp.BaseSlaveUnit.hp * App.SecExp.battle.deployedUnits('slaves') + App.SecExp.BaseMercUnit.hp * App.SecExp.battle.deployedUnits('mercs') + App.SecExp.BaseSpecialForcesUnit.hp * V.SecExp.war.deploySF) / (V.SecExp.units.bots.isDeployed + App.SecExp.battle.deployedUnits('militia') + App.SecExp.battle.deployedUnits('slaves') + App.SecExp.battle.deployedUnits('mercs') + V.SecExp.war.deploySF);
+	} else {
+		baseHp = (App.SecExp.BaseDroneUnit.hp * (V.SecExp.units.bots.active ? V.SecExp.units.bots.active : 0) + App.SecExp.BaseMilitiaUnit.hp * App.SecExp.battle.deployedUnits('militia') + App.SecExp.BaseSlaveUnit.hp * App.SecExp.battle.deployedUnits('slaves') + App.SecExp.BaseMercUnit.hp * App.SecExp.battle.deployedUnits('mercs') + App.SecExp.BaseSpecialForcesUnit.hp * V.SF.Active) / ((V.SecExp.units.bots.active ? V.SecExp.units.bots.active : 0) + App.SecExp.battle.deployedUnits('militia') + App.SecExp.battle.deployedUnits('slaves') + App.SecExp.battle.deployedUnits('mercs') + V.SF.Active);
+	}
+
+	// calculates opposing army stats
+	if (V.week > 30 && V.week <= 60) {
+		armyMod = V.SecExp.war.attacker.troops / (inBattle ? 75 : 90);
+	} else if (V.week <= 90) {
+		armyMod = V.SecExp.war.attacker.troops / (inBattle ? 70 : 80);
+	} else if (V.week <= 120) {
+		armyMod = V.SecExp.war.attacker.troops / (inBattle ? 65 : 70);
+	} else {
+		armyMod = V.SecExp.war.attacker.troops / 60;
+	}
+	armyMod = Math.trunc(armyMod);
+	if (isMajorBattle) {
+		armyMod *= 2;
+	}
+	if (inBattle && armyMod <= 0) {
+		armyMod = 1;
+	}
+
+	if (inRebellion) {
+		if (V.SecExp.war.type.includes("Slave")) {
+			rebellingSlaves = 1;
+			unitData = App.SecExp.getIrregularUnit("slaves", V.SecExp.war.attacker.troops, V.SecExp.war.attacker.equip);
+		} else {
+			rebellingMilitia = 1;
+			unitData = App.SecExp.getIrregularUnit("militia", V.SecExp.war.attacker.troops, V.SecExp.war.attacker.equip);
+		}
+		enemyAttack += unitData.attack * armyMod;
+		enemyDefense += unitData.defense * armyMod;
+		enemyHp += unitData.hp;
+
+		for (const unit of App.SecExp.unit.list().slice(1)) {
+			for (let i = 0; i < V.SecExp.units[unit].squads.length; i++) {
+				if (App.SecExp.unit.isDeployed(V.SecExp.units[unit].squads[i])) {
+					if (unit === "slaves") {
+						rebellingSlaves = 1;
+					} else if (unit === "militia") {
+						rebellingMilitia = 1;
+					} else if (unit === "mercs") {
+						rebellingMercs = 1;
+					}
+
+					V.SecExp.war.attacker.troops += V.SecExp.units[unit].squads[i].troops;
+					V.SecExp.units[unit].squads[i].loyalty = 0;
+					unitData = App.SecExp.getUnit(unit, i);
+					enemyAttack += unitData.attack;
+					enemyDefense += unitData.defense;
+					enemyHp += unitData.hp;
+				}
+			}
+		}
+	}
+
+	// calculates opposing army stats
+	let enemyMoraleTroopMod = Math.clamp(V.SecExp.war.attacker.troops / 100, 1, (inBattle ? 5 : 10));
+	if (inBattle) {
+		unitData = App.SecExp.getEnemyUnit(V.SecExp.war.attacker.type, V.SecExp.war.attacker.troops, V.SecExp.war.attacker.equip);
+		enemyAttack = unitData.attack * armyMod;
+		enemyDefense = unitData.defense * armyMod;
+		enemyMorale = unitData.morale * enemyMod * enemyMoraleTroopMod;
+		enemyHp = unitData.hp;
+		enemyBaseHp = unitData.hp / V.SecExp.war.attacker.troops;
+	} else {
+		enemyMorale = 1.5 * (App.SecExp.BaseMilitiaUnit.morale * rebellingMilitia + App.SecExp.BaseSlaveUnit.morale * rebellingSlaves + App.SecExp.BaseMercUnit.morale * rebellingMercs) / (rebellingMilitia + rebellingSlaves + rebellingMercs);
+		enemyMorale *= enemyMoraleTroopMod;
+		enemyBaseHp = (App.SecExp.BaseMilitiaUnit.hp * rebellingMilitia + App.SecExp.BaseSlaveUnit.hp * rebellingSlaves + App.SecExp.BaseMercUnit.hp * rebellingMercs) / (rebellingMilitia + rebellingSlaves + rebellingMercs);
+	}
+
+	if (isNaN(attack)) {
+		throw Error(`Attack value reported NaN`);
+	}
+	if (isNaN(defense)) {
+		throw Error(`Defense value reported NaN`);
+	}
+	if (isNaN(hp)) {
+		throw Error(`Hp value reported NaN`);
+	}
+	if (isNaN(morale)) {
+		throw Error(`Morale value reported NaN`);
+	}
+	if (isNaN(enemyAttack)) {
+		throw Error(`Enemy attack value reported NaN`);
+	}
+	if (isNaN(enemyDefense)) {
+		throw Error(`Enemy defense value reported NaN`);
+	}
+	if (isNaN(enemyHp)) {
+		throw Error(`Enemy hp value reported NaN`);
+	}
+	if (isNaN(enemyMorale)) {
+		throw Error(`Enemy morale value reported NaN`);
+	}
+
+	enemyAttack *= V.SecExp.settings.difficulty;
+	enemyDefense *= V.SecExp.settings.difficulty;
+	enemyMorale *= V.SecExp.settings.difficulty;
+	enemyHp *= V.SecExp.settings.difficulty;
+	enemyBaseHp *= V.SecExp.settings.difficulty;
+
+	if (showStats) {
+		if (inBattle) {
+			atkMod = Math.round((atkMod-1) * 100);
+			defMod = Math.round((defMod-1) * 100);
+			militiaMod = Math.round((militiaMod-1) * 100);
+			mercMod = Math.round((mercMod-1) * 100);
+			slaveMod = Math.round((slaveMod-1) * 100);
+			SFMod = Math.round((SFMod-1) * 100);
+			enemyMod = Math.round((enemyMod-1) * 100);
+			moraleTroopMod = Math.round((moraleTroopMod-1) * 100);
+			enemyMoraleTroopMod = Math.round((enemyMoraleTroopMod-1) * 100);
+		} else {
+			engageMod = Math.round((engageMod-1) * 100);
+		}
+
+		if (V.SecExp.settings.difficulty === 0.5) {
+			App.UI.DOM.appendNewElement("div", node, `Difficulty: Very easy. Modifier: x${V.SecExp.settings.difficulty}`);
+		} else if (V.SecExp.settings.difficulty === 0.75) {
+			App.UI.DOM.appendNewElement("div", node, `Difficulty: Easy. Modifier: x${V.SecExp.settings.difficulty}`);
+		} else if (V.SecExp.settings.difficulty === 1) {
+			App.UI.DOM.appendNewElement("div", node, `Difficulty: Normal. Modifier: x${V.SecExp.settings.difficulty}`);
+		} else if (V.SecExp.settings.difficulty === 1.25) {
+			App.UI.DOM.appendNewElement("div", node, `Difficulty: Hard. Modifier: x${V.SecExp.settings.difficulty}`);
+		} else if (V.SecExp.settings.difficulty === 1.5) {
+			App.UI.DOM.appendNewElement("div", node, `Difficulty: Very hard. Modifier: x${V.SecExp.settings.difficulty}`);
+		} else {
+			App.UI.DOM.appendNewElement("div", node, `Difficulty: Extremely hard. Modifier: x${V.SecExp.settings.difficulty}`);
+		}
+
+		App.UI.DOM.appendNewElement("div", node, `Army`, "underline");
+		App.UI.DOM.appendNewElement("div", node, `Troops: ${num(Math.round(App.SecExp.battle.troopCount()))}`);
+		App.UI.DOM.appendNewElement("div", node, `Attack: ${num(Math.round(attack))}. ${inBattle ? `Modifier: +${atkMod}%` : ``}`);
+		App.UI.DOM.appendNewElement("div", node, `Defense: ${num(Math.round(defense))}. ${inBattle ? `Modifier: +${defMod}%`: ``}`);
+		if (inRebellion) {
+			App.UI.DOM.appendNewElement("div", node, `Engagement rule modifier: +${engageMod}%`);
+		}
+		App.UI.DOM.appendNewElement("div", node, `HP: ${num(Math.round(hp))}. ${inRebellion ? `Base: ${num(Math.round(baseHp))}`: ``}`);
+		App.UI.DOM.appendNewElement("div", node, `Morale: ${num(Math.round(morale))}. Increase due to troop numbers: +${moraleTroopMod}%`);
+		if (inBattle) {
+			App.UI.DOM.appendNewElement("div", node, `Slaves morale modifier: +${slaveMod}%`);
+			App.UI.DOM.appendNewElement("div", node, `Militia morale modifier: +${militiaMod}%`);
+			App.UI.DOM.appendNewElement("div", node, `Mercenaries morale modifier: +${mercMod}%`);
+			if (V.SF.Toggle && V.SF.Active >= 1 && V.SecExp.war.deploySF) {
+				App.UI.DOM.appendNewElement("div", node, `Special Force morale modifier: +${SFMod}%`);
+			}
+			if (V.SecExp.buildings.barracks && V.SecExp.buildings.barracks.luxury >= 1) {
+				App.UI.DOM.appendNewElement("div", node, `Barracks bonus morale modifier: +${V.SecExp.buildings.barracks.luxury * 5}%`);
+			}
+		}
+		if (inBattle) {
+			App.UI.DOM.appendNewElement("div", node, `Tactics`, "underline");
+			App.UI.DOM.appendNewElement("div", node, `Chance of success: ${num(Math.round(tacChance * 100))}%. Was successful?: ${V.SecExp.war.tacticsSuccessful ? 'Yes' : 'No'}`);
+		}
+
+		App.UI.DOM.appendNewElement("p", node, enemy());
+	}
+
+	let i = 0; // simulates the combat by pitting attk against def
+	while (i < turns && ![3, -3].includes(V.SecExp.war.result)) {
+		App.UI.DOM.appendNewElement("p", node, turnReport());
+		i++;
+	}
+
+	if (![3, -3].includes(V.SecExp.war.result)) {
+		showProgress(`Partial ${morale > enemyMorale ? 'victory' : 'defeat'}!`, "div");
+		V.SecExp.war.result = morale > enemyMorale ? 2 : -2;
+	}
+
+	if (V.SecExp.war.result > 3 || V.SecExp.war.result < -3) {
+		throw Error(`Failed to determine battle result`);
+	}
+
+	if (inBattle && showStats) {
+		App.UI.DOM.appendNewElement("div", node, `Losses: ${num(Math.trunc(V.SecExp.war.losses))}`);
+		App.UI.DOM.appendNewElement("div", node, `Enemy losses: ${num(Math.trunc(V.SecExp.war.attacker.losses))}`);
+	}
+
+	if (V.SecExp.war.result === -3 && (isMajorBattle && V.SecExp.settings.battle.major.gameOver === 1 || inRebellion && V.SecExp.settings.rebellion.gameOver === 1)) {
+		V.gameover = `${isMajorBattle ? "major battle" : "Rebellion"} defeat`;
+		atEnd("Gameover");
+	} else {
+		atEnd(inBattle ? "attackReport" : "rebellionReport");
+	}
+	return node;
+};
diff --git a/src/Mods/SecExp/events/rebellionHandler.tw b/src/Mods/SecExp/events/rebellionHandler.tw
deleted file mode 100644
index 4d6531b7e8e..00000000000
--- a/src/Mods/SecExp/events/rebellionHandler.tw
+++ /dev/null
@@ -1,326 +0,0 @@
-:: rebellionHandler [nobr]
-
-<<set $nextButton = " ", $nextLink = "attackReport", $encyclopedia = "Battles">>
-
-<<set _turns = 10 * 2>>
-<<set _attack = 0>>
-<<set _defense = 0>>
-<<set _morale = 0>>
-<<set _hp = 0>>
-<<set _baseHp = 0>>
-<<set _enemyAttack = 0>>
-<<set _enemyDefense = 0>>
-<<set _enemyMorale = 0>>
-<<set _enemyHp = 0>>
-<<set _enemyBaseHp = 0>>
-<<set _woundChance = 5>>								/* leader has a base chance of 5% to get wounded */
-<<set _irregularMod = 0>>
-<<set _armyMod = 0>>
-
-/* calculates PC army stats */
-<<if $SecExp.war.engageRule == 0>>
-	<<set _engageMod = 0.5>>
-<<elseif $SecExp.war.engageRule == 1>>
-	<<set _engageMod = 0.75>>
-<<elseif $SecExp.war.engageRule == 2>>
-	<<set _engageMod = 1>>
-<<else>>
-	<<set _engageMod = 1.4>>
-<</if>>
-
-<<if $week <= 30>>
-	<<set _irregularMod = $SecExp.war.irregulars / 60>>
-<<elseif $week <= 60>>
-	<<set _irregularMod = $SecExp.war.irregulars / 50>>
-<<elseif $week <= 90>>
-	<<set _irregularMod = $SecExp.war.irregulars / 40>>
-<<elseif $week <= 120>>
-	<<set _irregularMod = $SecExp.war.irregulars / 30>>
-<<else>>
-	<<set _irregularMod = $SecExp.war.irregulars / 20>>
-<</if>>
-<<if $SecExp.war.irregulars > 0>>
-	<<set _irregularMod = Math.trunc(_irregularMod)>>
-	<<set _unit = App.SecExp.getIrregularUnit("militia", $SecExp.war.irregulars, $SecExp.war.attacker.equip)>>
-	<<set _attack += _unit.attack * _irregularMod * 0.80>>
-	<<set _defense += _unit.defense * _irregularMod * 0.80>>
-	<<set _hp += _unit.hp>>
-<</if>>
-
-<<if $SecExp.units.bots.active == 1>>
-	<<set _unit = App.SecExp.getUnit("bots")>>
-	<<set _attack += _unit.attack>>
-	<<set _defense += _unit.defense>>
-	<<set _hp += _unit.hp>>
-<</if>>
-
-<<for _i = 0; _i < $SecExp.units.militia.squads.length; _i++>>
-	<<if $SecExp.units.militia.squads[_i].active == 1 && (!$SecExp.war.rebellingID.includes($SecExp.units.militia.squads[_i].ID))>>
-		<<set _unit = App.SecExp.getUnit("militia", _i)>>
-		<<set _attack += _unit.attack>>
-		<<set _defense += _unit.defense>>
-		<<set _hp += _unit.hp>>
-	<</if>>
-<</for>>
-<<for _i = 0; _i < $SecExp.units.slaves.squads.length; _i++>>
-	<<if $SecExp.units.slaves.squads[_i].active == 1 && (!$SecExp.war.rebellingID.includes($SecExp.units.slaves.squads[_i].ID))>>
-		<<set _unit = App.SecExp.getUnit("slaves", _i)>>
-		<<set _attack += _unit.attack>>
-		<<set _defense += _unit.defense>>
-		<<set _hp += _unit.hp>>
-	<</if>>
-<</for>>
-<<for _i = 0; _i < $SecExp.units.mercs.squads.length; _i++>>
-	<<if $SecExp.units.mercs.squads[_i].active == 1 && (!$SecExp.war.rebellingID.includes($SecExp.units.mercs.squads[_i].ID))>>
-		<<set _unit = App.SecExp.getUnit("mercs", _i)>>
-		<<set _attack += _unit.attack>>
-		<<set _defense += _unit.defense>>
-		<<set _hp += _unit.hp>>
-	<</if>>
-<</for>>
-
-<<if $SF.Toggle && $SF.Active >= 1>>
-	<<set _unit = App.SecExp.getUnit("SF")>>
-	<<set _attack += _unit.attack>>
-	<<set _defense += _unit.defense>>
-	<<set _hp += _unit.hp>>
-<</if>>
-
-<<set _attack *= _engageMod>>
-<<set _defense *= _engageMod>>
-<<set _hp *= _engageMod>>
-
-<<if $SecExp.war.assistantDefense>>
-	<<set _attack *= 0.95>>
-	<<set _defense *= 0.95>>
-	<<set _hp *= 0.95>>
-<</if>>
-<<if $SecExp.war.reactorDefense>>
-	<<set _attack *= 0.95>>
-	<<set _defense *= 0.95>>
-	<<set _hp *= 0.95>>
-<</if>>
-<<if $SecExp.war.penthouseDefense>>
-	<<set _attack *= 0.95>>
-	<<set _defense *= 0.95>>
-	<<set _hp *= 0.95>>
-<</if>>
-<<if $SecExp.war.waterwayDefense>>
-	<<set _attack *= 0.95>>
-	<<set _defense *= 0.95>>
-	<<set _hp *= 0.95>>
-<</if>>
-
-<<set _moraleTroopMod = Math.clamp(App.SecExp.battle.troopCount() / 100,1,10)>>
-
-/* morale and baseHp calculation */
-<<set _morale += (App.SecExp.BaseDroneUnit.morale * $SecExp.units.bots.active + App.SecExp.BaseMilitiaUnit.morale * App.SecExp.battle.deployedUnits('militia') + App.SecExp.BaseSlaveUnit.morale * App.SecExp.battle.deployedUnits('slaves') + App.SecExp.BaseMercUnit.morale * App.SecExp.battle.deployedUnits('mercs') + App.SecExp.BaseSpecialForcesUnit.morale * $SF.Active) / ($SecExp.units.bots.active + App.SecExp.battle.deployedUnits('militia') + App.SecExp.battle.deployedUnits('slaves') + App.SecExp.battle.deployedUnits('mercs') + $SF.Active)>>
-<<set _morale += _morale * $SecExp.buildings.barracks ? $SecExp.buildings.barracks.luxury * 0.05 : 0>>	/* barracks bonus */
-<<set _morale *= _moraleTroopMod>>
-<<set _baseHp = (App.SecExp.BaseDroneUnit.hp * ($SecExp.units.bots.active ? $SecExp.units.bots.active : 0) + App.SecExp.BaseMilitiaUnit.hp * App.SecExp.battle.deployedUnits('militia') + App.SecExp.BaseSlaveUnit.hp * App.SecExp.battle.deployedUnits('slaves') + App.SecExp.BaseMercUnit.hp * App.SecExp.battle.deployedUnits('mercs') + App.SecExp.BaseSpecialForcesUnit.hp * $SF.Active) / (($SecExp.units.bots.active ? $SecExp.units.bots.active : 0) + App.SecExp.battle.deployedUnits('militia') + App.SecExp.battle.deployedUnits('slaves') + App.SecExp.battle.deployedUnits('mercs') + $SF.Active)>>
-
-/* calculates rebelling army stats */
-<<if $week <= 30>>
-	<<set _armyMod = $SecExp.war.attacker.troops / 100>>
-<<elseif $week <= 60>>
-	<<set _armyMod = $SecExp.war.attacker.troops / 90>>
-<<elseif $week <= 90>>
-	<<set _armyMod = $SecExp.war.attacker.troops / 80>>
-<<elseif $week <= 120>>
-	<<set _armyMod = $SecExp.war.attacker.troops / 70>>
-<<else>>
-	<<set _armyMod = $SecExp.war.attacker.troops / 60>>
-<</if>>
-<<set _armyMod = Math.trunc(_armyMod)>>
-
-<<set _rebellingSlaves = 0, _rebellingMilitia = 0, _rebellingMercs = 0>>
-<<if $SecExp.war.type.includes("Slave")>>
-	<<set _rebellingSlaves = 1>>
-	<<set _unit = App.SecExp.getIrregularUnit("slaves", $SecExp.war.attacker.troops, $SecExp.war.attacker.equip)>>
-<<else>>
-	<<set _rebellingMilitia = 1>>
-	<<set _unit = App.SecExp.getIrregularUnit("militia", $SecExp.war.attacker.troops, $SecExp.war.attacker.equip)>>
-<</if>>
-<<set _enemyAttack += _unit.attack * _armyMod>>
-<<set _enemyDefense += _unit.defense * _armyMod>>
-<<set _enemyHp += _unit.hp>>
-
-<<for _i = 0; _i < $SecExp.units.militia.squads.length; _i++>>
-	<<if $SecExp.units.militia.squads[_i].active == 1 && $SecExp.war.rebellingID.includes($SecExp.units.militia.squads[_i].ID)>>
-		<<set _rebellingMilitia = 1>>
-		<<set $SecExp.war.attacker.troops += $SecExp.units.militia.squads[_i].troops>>
-		<<set $SecExp.units.militia.squads[_i].loyalty = 0>>
-		<<set _unit = App.SecExp.getUnit("militia", _i)>>
-		<<set _enemyAttack += _unit.attack>>
-		<<set _enemyDefense += _unit.defense>>
-		<<set _enemyHp += _unit.hp>>
-	<</if>>
-<</for>>
-<<for _i = 0; _i < $SecExp.units.slaves.squads.length; _i++>>
-	<<if $SecExp.units.slaves.squads[_i].active == 1 && $SecExp.war.rebellingID.includes($SecExp.units.slaves.squads[_i].ID)>>
-		<<set _rebellingSlaves = 1>>
-		<<set $SecExp.war.attacker.troops += $SecExp.units.slaves.squads[_i].troops>>
-		<<set $SecExp.units.slaves.squads[_i].loyalty = 0>>
-		<<set _unit = App.SecExp.getUnit("slaves", _i)>>
-		<<set _enemyAttack += _unit.attack>>
-		<<set _enemyDefense += _unit.defense>>
-		<<set _enemyHp += _unit.hp>>
-	<</if>>
-<</for>>
-<<for _i = 0; _i < $SecExp.units.mercs.squads.length; _i++>>
-	<<if $SecExp.units.mercs.squads[_i].active == 1 && $SecExp.war.rebellingID.includes($SecExp.units.mercs.squads[_i].ID)>>
-		<<set _rebellingMercs = 1>>
-		<<set $SecExp.war.attacker.troops += $SecExp.units.mercs.squads[_i].troops>>
-		<<set $SecExp.units.mercs.squads[_i].loyalty = 0>>
-		<<set _unit = App.SecExp.getUnit("mercs", _i)>>
-		<<set _enemyAttack += _unit.attack>>
-		<<set _enemyDefense += _unit.defense>>
-		<<set _enemyHp += _unit.hp>>
-	<</if>>
-<</for>>
-
-<<set _enemyMoraleTroopMod = Math.clamp($SecExp.war.attacker.troops / 100,1,10)>>
-<<set _enemyMorale = 1.5 * (App.SecExp.BaseMilitiaUnit.morale * _rebellingMilitia + App.SecExp.BaseSlaveUnit.morale * _rebellingSlaves + App.SecExp.BaseMercUnit.morale * _rebellingMercs) / (_rebellingMilitia + _rebellingSlaves + _rebellingMercs)>>
-<<set _enemyMorale *= _enemyMoraleTroopMod>>
-<<set _enemyBaseHp = (App.SecExp.BaseMilitiaUnit.hp * _rebellingMilitia + App.SecExp.BaseSlaveUnit.hp * _rebellingSlaves + App.SecExp.BaseMercUnit.hp * _rebellingMercs) / (_rebellingMilitia + _rebellingSlaves + _rebellingMercs)>>
-
-<<if isNaN(_attack)>>
-	<br>@@.red;Error: attack value reported NaN@@
-<</if>>
-<<if isNaN(_defense)>>
-	<br>@@.red;Error: defense value reported NaN@@
-<</if>>
-<<if isNaN(_hp)>>
-	<br>@@.red;Error: hp value reported NaN@@
-<</if>>
-<<if isNaN(_morale)>>
-	<br>@@.red;Error: morale value reported NaN@@
-<</if>>
-<<if isNaN(_enemyAttack)>>
-	<br>@@.red;Error: enemy attack value reported NaN@@
-<</if>>
-<<if isNaN(_enemyDefense)>>
-	<br>@@.red;Error: enemy defense value reported NaN@@
-<</if>>
-<<if isNaN(_enemyHp)>>
-	<br>@@.red;Error: enemy hp value reported NaN@@
-<</if>>
-<<if isNaN(_enemyMorale)>>
-	<br>@@.red;Error: enemy morale value reported NaN@@
-<</if>>
-
-/* difficulty */
-<<set _enemyAttack *= $SecExp.settings.difficulty>>
-<<set _enemyDefense *= $SecExp.settings.difficulty>>
-<<set _enemyMorale *= $SecExp.settings.difficulty>>
-<<set _enemyHp *= $SecExp.settings.difficulty>>
-<<set _enemyBaseHp *= $SecExp.settings.difficulty>>
-
-<<if $SecExp.settings.showStats == 1>>
-<<set _engageMod -= 1>>
-<<set _engageMod = Math.round(_engageMod * 100)>>
-<<set _difficulty = ($SecExp.settings.difficulty -1) * 100>>
-
-__Difficulty__:<br>
-<<if $SecExp.settings.difficulty == 0.5>>
-	Very easy
-<<elseif $SecExp.settings.difficulty == 0.75>>
-	Easy
-<<elseif $SecExp.settings.difficulty == 1>>
-	Normal
-<<elseif $SecExp.settings.difficulty == 1.25>>
-	Hard
-<<elseif $SecExp.settings.difficulty == 1.5>>
-	Very hard
-<<else>>
-	Extremely hard
-<</if>>
-<br><br>__Army__:
-<br>troops: <<print num(Math.round(App.SecExp.battle.troopCount()))>>
-<br>attack: <<print num(Math.round(_attack))>>
-<br>defense: <<print num(Math.round(_defense))>>
-<br>engagement rule modifier: <<if _engageMod > 0>>+<</if>><<print _engageMod>>%
-<br>Hp: <<print num(Math.round(_hp))>>
-<br>base HP: <<print num(Math.round(_baseHp))>>
-<br>morale: <<print num(Math.round(_morale))>>
-<<if _enemyMoraleTroopMod > 0>>
-	<br>morale increase due to troop numbers: +<<print _moraleTroopMod>>%
-<</if>>
-<br><br>__Rebels__:
-<br>enemy troops: <<print num(Math.round($SecExp.war.attacker.troops))>>
-<br>enemy attack: <<print num(Math.round(_enemyAttack))>>
-<br>enemy defense: <<print num(Math.round(_enemyDefense))>>
-<br>enemy Hp: <<print num(Math.round(_enemyHp))>>
-<br>enemy base Hp: <<print num(Math.round(_enemyBaseHp))>>
-<br>enemy morale: <<print num(Math.round(_enemyMorale))>>
-<<if _enemyMoraleTroopMod > 0>>
-	<br>enemy morale increase due to troop numbers: +<<print _enemyMoraleTroopMod>>%
-<</if>>
-<br>Difficulty modifier: <<if _difficulty > 0>>+<</if>><<print _difficulty>>%
-<</if>>
-
-/* simulates the combat by pitting attk against def */
-<<for _i = 0; _i < _turns; _i++>>
-	<<if $SecExp.settings.showStats == 1>> <br><br>turn: <<print _i + 1>><</if>>
-	/* player army attacks */
-	<<set _damage = Math.clamp(_attack - _enemyDefense,_attack * 0.1,_attack)>>
-	<<if $SecExp.settings.showStats == 1>> <br>player damage: <<print num(Math.round(_damage))>><</if>>
-	<<set _enemyHp -= _damage>>
-	<<if $SecExp.settings.showStats == 1>> <br>remaining enemy Hp: <<print num(Math.round(_enemyHp))>><</if>>
-	<<set $SecExp.war.attacker.losses += _damage / _enemyBaseHp>>
-	<<set _moraleDamage = Math.clamp(_damage/ 2 + _damage / _enemyBaseHp,0,_damage*1.5)>>
-	<<set _enemyMorale -= _moraleDamage>>
-	<<if $SecExp.settings.showStats == 1>> <br>remaining enemy morale: <<print num(Math.round(_enemyMorale))>><</if>>
-	<<if _enemyHp <= 0 || _enemyMorale <= 0>>
-		<<if $SecExp.settings.showStats == 1>> <br>Victory!<</if>>
-		<<set $SecExp.war.result = 3>>
-		<<set $SecExp.war.turns = _i>>
-		<<break>>
-	<</if>>
-
-	/* attacker army attacks */
-	<<set _damage = _enemyAttack - _defense>>
-	<<if _damage < _enemyAttack * 0.1>>
-		<<set _damage = _enemyAttack * 0.1>>
-	<</if>>
-	<<if $SecExp.settings.showStats == 1>> <br>enemy damage: <<print num(Math.round(_damage))>><</if>>
-	<<set _hp -= _damage*($SecExp.rebellions.sfArmor ? 0.85 : 1)>>
-	<<if $SecExp.settings.showStats == 1>> <br>remaining hp: <<print num(Math.round(_hp))>><</if>>
-	<<set $SecExp.war.losses += _damage / _baseHp>>
-	<<set _moraleDamage = Math.clamp(_damage / 2 + _damage / _baseHp,0,_damage*1.5)>>
-	<<set _morale -= _moraleDamage>>
-	<<if $SecExp.settings.showStats == 1>> <br>remaining morale: <<print num(Math.round(_morale))>><</if>>
-	<<if _hp <= 0 || _morale <= 0>>
-		<<if $SecExp.settings.showStats == 1>> <br>Defeat!<</if>>
-		<<set $SecExp.war.result = -3>>
-		<<set $SecExp.war.turns = _i>>
-		<<break>>
-	<</if>>
-<</for>>
-<<if $SecExp.war.result != 3 && $SecExp.war.result != -3>>
-	<<if _morale > _enemyMorale>>
-		<<if $SecExp.settings.showStats == 1>> <br>Partial victory!<</if>>
-		<<set $SecExp.war.result = 2>>
-	<<elseif _morale < _enemyMorale>>
-		<<if $SecExp.settings.showStats == 1>> <br>Partial defeat!<</if>>
-		<<set $SecExp.war.result = -2>>
-	<</if>>
-<</if>>
-
-<<if $SecExp.war.result > 3 || $SecExp.war.result < -3>>
-	<br><br>@@.red;Error: failed to determine battle result@@
-<</if>>
-
-<<if $SecExp.settings.showStats == 1>>
-	<<if $SecExp.settings.rebellion.gameOver == 1 && $SecExp.war.result == -3>>
-		<br>[[Proceed|Gameover][$gameover = "Rebellion defeat"]]
-	<<else>>
-		<br>[[Proceed|rebellionReport]]
-	<</if>>
-<<else>>
-	<<if $SecExp.settings.rebellion.gameOver == 1 && $SecExp.war.result == -3>>
-		<<set $gameover = "Rebellion defeat">> <<goto "Gameover">>
-	<<else>>
-		<<goto "rebellionReport">>
-	<</if>>
-<</if>>
diff --git a/src/Mods/SecExp/events/rebellionOptions.tw b/src/Mods/SecExp/events/rebellionOptions.tw
index 6a6617cb0d5..1712764df4d 100644
--- a/src/Mods/SecExp/events/rebellionOptions.tw
+++ b/src/Mods/SecExp/events/rebellionOptions.tw
@@ -106,5 +106,5 @@ In order to preserve the structural integrity of the building and the lives of o
 <</if>>
 
 <br><br> <<includeDOM App.SecExp.unit.replenishAll()>>
-[[Proceed|rebellionHandler][$SecExp.war.result = 4, $SecExp.war.foughtThisWeek = 1]] /* sets $SecExp.war.result to a value outside accepted range (-3,3) to avoid evaluation problems */
-<br>[[Surrender|rebellionReport][$SecExp.war.result = -1, $SecExp.war.foughtThisWeek = 1]]
+[[Proceed|conflictHandler][$SecExp.war.result = 4, $SecExp.war.foughtThisWeek = 1]] /* sets $SecExp.war.result to a value outside accepted range (-3,3) to avoid evaluation problems */
+<br>[[Surrender|rebellionReport][$SecExp.war.result = -1, $SecExp.war.foughtThisWeek = 1]]
\ No newline at end of file
-- 
GitLab