public function setCombatIndex($defenderId) { $combatLog = ""; /* @var JagCore $battle */ $battle = Battle::getBattle(); $scenario = $battle->scenario; $combats = $battle->combatRules->combats->{$defenderId}; $combats->dieShift = 0; $attackingForceId = $battle->force->attackingForceId; $attackingForceName = preg_replace("/ /", "-", Battle::$forceName[$attackingForceId]); $defendingForceId = $battle->force->defendingForceId; $defendingForceName = preg_replace("/ /", "-", Battle::$forceName[$defendingForceId]); if (count((array) $combats->attackers) == 0) { $combats->index = null; $combats->attackStrength = null; $combats->defenseStrength = null; $combats->terrainCombatEffect = null; return; } $defenders = $combats->defenders; $isFrozenSwamp = $isTown = $isHill = $isForest = $isSwamp = $attackerIsSunkenRoad = $isRedoubt = $isElevated = false; foreach ($defenders as $defId => $defender) { $hexagon = $battle->force->units[$defId]->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $isTown |= $battle->terrain->terrainIs($hexpart, 'town'); $isHill |= $battle->terrain->terrainIs($hexpart, 'hill'); $isForest |= $battle->terrain->terrainIs($hexpart, 'forest'); $isSwamp |= $battle->terrain->terrainIs($hexpart, 'swamp'); if ($battle->terrain->terrainIs($hexpart, 'frozenswamp')) { if ($battle->terrain->getDefenderTerrainCombatEffect($hexagon)) { $isFrozenSwamp |= true; } } if ($battle->terrain->terrainIs($hexpart, 'elevation1')) { $isElevated = 1; } if ($battle->terrain->terrainIs($hexpart, 'elevation2')) { $isElevated = 2; } } $isClear = true; if ($isTown || $isForest || $isHill || $isSwamp || $isFrozenSwamp) { $isClear = false; } $attackers = $combats->attackers; $attackStrength = 0; $attackersCav = false; $combinedArms = ['infantry' => 0, 'artillery' => 0, 'cavalry' => 0]; $arnold = $morgan = false; $combatLog .= "<br><span class='{$attackingForceName} combatants'>Attackers</span><br>"; $attackStrengths = ""; foreach ($attackers as $attackerId => $attacker) { $terrainReason = ""; $unit = $battle->force->units[$attackerId]; $unitStrength = $unit->strength; if ($unit->class === "wagon") { $unitStrength = 0; } if (!empty($scenario->americanRevolution) && $unit->class === "hq") { $combatLog .= " <br><span class='crtDetailComment'>Arnold was here</span> <br>"; $arnold = true; } if ($unit->name === "morgan") { $combatLog .= " <br><span class='crtDetailComment'>Morgan was here</span> <br>"; $morgan = true; } $hexagon = $unit->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $attackerIsSwamp = false; if (empty($scenario->wimpySwamps)) { $attackerIsSwamp = $battle->terrain->terrainIs($hexpart, 'swamp'); } $attackerIsFrozenSwamp = $battle->terrain->terrainIs($hexpart, 'frozenswamp'); $attackerIsSunkenRoad = $battle->terrain->terrainIs($hexpart, 'sunkenroad'); if ($attackerIsSwamp) { $terrainReason .= "attacker is in swamp "; } if ($attackerIsSunkenRoad) { $terrainReason .= "attacker is in sunken road "; } if ($attackerIsFrozenSwamp) { $terrainReason .= "attacker is frozen swamp "; } if ($isFrozenSwamp) { $terrainReason .= "Frozen Swamp "; } $attackerIsElevated = false; if ($battle->terrain->terrainIs($hexpart, 'elevation1')) { $attackerIsElevated = 1; } if ($battle->terrain->terrainIs($hexpart, 'elevation2')) { $attackerIsElevated = 2; } $attackUpHill = false; if ($isElevated && $isElevated > $attackerIsElevated) { /* Special case for elevation 2 and attack no elevated, can be from be behind */ if ($isElevated == 2 && $attackerIsElevated === false) { if ($battle->combatRules->thisAttackAcrossTwoType($defId, $attackerId, "elevation1")) { $terrainReason .= "attack uphill "; $attackUpHill = true; } } else { $terrainReason .= "attack uphill "; $attackUpHill = true; } } $acrossRiver = false; foreach ($defenders as $defId => $defender) { if ($battle->combatRules->thisAttackAcrossRiver($defId, $attackerId)) { $terrainReason .= "attack across river or wadi"; $acrossRiver = true; } } $acrossRedoubt = false; foreach ($defenders as $defId => $defender) { $isRedoubt = false; $hexagon = $battle->force->units[$defId]->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $isRedoubt |= $battle->terrain->terrainIs($hexpart, 'redoubt'); if ($isRedoubt && $battle->combatRules->thisAttackAcrossType($defId, $attackerId, "redoubt")) { $acrossRedoubt = true; $terrainReason .= "across redoubt "; } } if ($unit->class == "hq") { $combatLog .= "{$unitStrength} HQ Leardership"; } if ($unit->class == "infantry") { $combinedArms[$battle->force->units[$attackerId]->class]++; $combatLog .= "{$unitStrength} Infantry"; if (!empty($scenario->jagersdorfCombat)) { if ($unit->nationality == "Prussian" && $isClear && !$acrossRiver) { $unitStrength++; $combatLog .= " <br><span class='crtDetailComment'>+1 for attack into clear</span> <br>"; } if ($unit->nationality == "Russian" && ($isTown || $isForest) && !$acrossRiver) { $unitStrength++; $combatLog .= " <br><span class='crtDetailComment'>+1 for attack into town or forest</span> <br>"; } } if (!empty($scenario->americanRevolution)) { if ($unit->forceId == LOYALIST_FORCE && $isClear && !$acrossRiver) { if ($unit->name !== "sharpshooter") { $unitStrength++; $combatLog .= " <br><span class='crtDetailComment'>+1 for attack into clear</span> <br>"; } } } if (($unit->nationality == "Beluchi" || $unit->nationality == "Sikh") && ($isTown || $isForest) && !$acrossRiver) { $unitStrength++; $combatLog .= "+1 for attack into town or forest<br>"; } if ($isSwamp || $isFrozenSwamp || $attackerIsFrozenSwamp || $attackerIsSwamp || $acrossRiver || $attackerIsSunkenRoad || $acrossRedoubt || $attackUpHill) { if (!$terrainReason) { $terrainReason = " terrain "; } if (($attackUpHill || $isFrozenSwamp || $attackerIsFrozenSwamp) && !($isSwamp || $attackerIsSwamp || $acrossRiver || $attackerIsSunkenRoad || $acrossRedoubt)) { // $unitStrength *= .75; // $combats->dieShift = -1; $unitStrength -= 1; $combatLog .= "<span class='crtDetailComment'>unit strength -1 for {$terrainReason}</span> <br>"; } else { if (empty($scenario->weakRedoubts)) { $unitStrength /= 2; $combatLog .= " <br><span class='crtDetailComment'>attack halved <br>{$terrainReason}</span> <br>"; } } } $combatLog .= " {$unitStrength}<br>"; } if ($unit->class == "cavalry") { $combatLog .= "{$unitStrength} Cavalry"; $attackersCav = true; if ($attackerIsSwamp || $acrossRiver || !$isClear || $attackerIsSunkenRoad || $acrossRedoubt) { if (!$terrainReason) { $terrainReason = " terrain "; } $combatLog .= " <br><span class='crtDetailComment'>loses combined arms bonus <br>"; $unitStrength /= 2; $combatLog .= "attack halved <br>{$terrainReason}</span> <br>"; } elseif ($attackUpHill || $attackerIsFrozenSwamp) { // $unitStrength *= .75; // $combats->dieShift = -1; $unitStrength -= 1; $combatLog .= " <br><span class='crtDetailComment'>unit strength -1 for {$terrainReason}</span> <br>"; if ($unit->nationality != "Beluchi" && $unit->nationality != "Sikh") { $combinedArms[$battle->force->units[$attackerId]->class]++; } else { $combatLog .= " <br><span class='crtDetailComment'>no combined arms bonus for " . $unit->nationality . " cavalry</span> <br>"; } } else { if (!empty($scenario->angloCavBonus) && $unit->nationality == "AngloAllied") { $unitStrength++; $combatLog .= " <br><span class='crtDetailComment'>+1 for attack into clear</span> <br>"; } if ($unit->nationality != "Beluchi" && $unit->nationality != "Sikh") { $combinedArms[$battle->force->units[$attackerId]->class]++; } else { $combatLog .= " <br><span class='crtDetailComment'>no combined arms bonus for " . $unit->nationality . " cavalry</span> <br>"; } } $combatLog .= " {$unitStrength}<br>"; } if ($unit->class == "artillery" || $unit->class == "horseartillery") { $combatLog .= "{$unitStrength} " . ucfirst($unit->class); if ($isSwamp || $acrossRedoubt || $attackUpHill || $isFrozenSwamp || $attackerIsFrozenSwamp) { if ($attackUpHill || $isFrozenSwamp || $attackerIsFrozenSwamp) { // $unitStrength *= .75; // $combats->dieShift = -1; $unitStrength -= 1; $combatLog .= " <br><span class='crtDetailComment'>unit strength -1 for {$terrainReason}</span>  <br>"; } else { $unitStrength /= 2; $combatLog .= " <br><span class='crtDetailComment'>attacker halved for {$terrainReason}</span> <br>"; } if (!$terrainReason) { $terrainReason = " terrain "; } } $class = $unit->class; if ($class == 'horseartillery') { $class = 'artillery'; } if ($unit->nationality != "Beluchi") { $combinedArms[$class]++; } else { $combatLog .= " <br><span class='crtDetailComment'>no combined arms bonus for Beluchi</span>  <br>"; } $combatLog .= " {$unitStrength}<br>"; } if ($attackStrengths) { $attackStrengths .= " + {$unitStrength}"; } else { $attackStrengths = $unitStrength; } $attackStrength += $unitStrength; } $combatLog .= "{$attackStrengths} = {$attackStrength}<br>"; $defenseStrength = 0; $defenseStrengths = ''; $defendersAllCav = true; $combatLog .= "<br><span class='{$defendingForceName} combatants'>Defenders</span><br>"; foreach ($defenders as $defId => $defender) { $unit = $battle->force->units[$defId]; $class = $unit->class; $unitDefense = $unit->defStrength; $combatLog .= " {$unitDefense} " . $unit->class; /* set to true to disable for not scenario->doubleArt */ $clearHex = false; $artInNonTown = false; $notClearHex = false; $hexagon = $unit->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $isTown = $battle->terrain->terrainIs($hexpart, 'town'); $isHill = $battle->terrain->terrainIs($hexpart, 'hill'); $isForest = $battle->terrain->terrainIs($hexpart, 'forest'); $isSwamp = $battle->terrain->terrainIs($hexpart, 'swamp'); $notClearHex = false; if ($isTown || $isForest || $isHill || $isSwamp) { $notClearHex = true; } $clearHex = !$notClearHex; if (($unit->class == 'artillery' || $unit->class == 'horseartillery') && !$isTown) { $combatLog .= " <br><span class='crtDetailComment'>doubled for defending in non town</span> <br>"; $artInNonTown = true; } if ($unit->class != 'cavalry') { $defendersAllCav = false; } if (!empty($scenario->jagersdorfCombat)) { if ($unit->forceId == PRUSSIAN_FORCE && $class == "infantry" && $isClear) { $unitDefense += 1; $combatLog .= " <br><span class='crtDetailComment'>+1 for defending in clear 1</span><br>"; } if ($unit->forceId == RUSSIAN_FORCE && $class == "infantry" && ($isTown || $isForest)) { $unitDefense += 1; $combatLog .= " <br><span class='crtDetailComment'>+1 for defending in town or forest</span><br>"; } } if (!empty($scenario->americanRevolution)) { if ($unit->forceId == LOYALIST_FORCE && $class == "infantry" && $isClear) { if ($unit->name !== "sharpshooter") { $unitDefense += 1; $combatLog .= " <br><span class='crtDetailComment'>+1 for defending in clear</span><br>"; } } if ($unit->forceId == REBEL_FORCE && $class == "infantry" && (!$isClear || $battle->combatRules->allAreAttackingThisAcrossRiver($defId))) { $unitDefense += 1; $combatLog .= " <br><span class='crtDetailComment'>+1 for defending in town or forest</span><br>"; } } if (($unit->nationality == "Beluchi" || $unit->nationality == "Sikh") && $class == "infantry" && ($isTown || $isForest)) { $unitDefense++; $combatLog .= " <br><span class='crtDetailComment'>+1 in town or forest</span><br>"; } $defMultiplier = 1; if ($isTown && $class !== 'cavalry' || $artInNonTown || $isHill) { $defMultiplier = 2.0; if ($isTown && $class !== 'cavalry' || $isHill) { $defMultiplier = 2; $combatLog .= " <br><span class='crtDetailComment'>2x for terrain</span><br>"; } } $combatLog .= " " . $unitDefense * $defMultiplier . "<br>"; if ($defenseStrengths) { $defenseStrengths .= " + " . $unitDefense * $defMultiplier; } else { $defenseStrengths = $unitDefense * $defMultiplier; } $defenseStrength += $unitDefense * $defMultiplier; } $combatLog .= "{$defenseStrengths} = {$defenseStrength}<br><br>"; $armsShift = 0; $combinedLog = ''; if ($attackStrength >= $defenseStrength) { foreach ($combinedArms as $key => $arms) { if ($arms > 0) { if ($combinedLog) { $combinedLog .= " + {$key}"; } else { $combinedLog .= "{$key}"; } $armsShift++; } } $armsShift--; } if ($armsShift) { $combatLog .= "Combined Arms Bonus<br> {$combinedLog}<br>Column Shift +{$armsShift}<br><br>"; } if ($armsShift < 0) { $armsShift = 0; } $combatIndex = $this->getCombatIndex($attackStrength, $defenseStrength); /* Do this before terrain effects */ $combatIndex += $armsShift; if ($morgan || $arnold) { $combatIndex++; } if ($combatIndex >= $this->maxCombatIndex) { $combatIndex = $this->maxCombatIndex; } // $terrainCombatEffect = $battle->combatRules->getDefenderTerrainCombatEffect($defenderId); // $combatIndex -= $terrainCombatEffect; $combats->attackStrength = $attackStrength; $combats->defenseStrength = $defenseStrength; $combats->terrainCombatEffect = $armsShift; if ($combats->pinCRT !== false) { $pinIndex = $combats->pinCRT; if ($combatIndex > $pinIndex) { $combatLog .= "<br>Pinned to {$this->combatResultsHeader[$pinIndex]} "; } else { $combats->pinCRT = false; } } $combats->index = $combatIndex; $combats->useAlt = false; if ($defendersAllCav && !$attackersCav) { $combats->useAlt = true; $combats->useDetermined = false; $combatLog .= "using cavalry table "; } $combats->combatLog = $combatLog; }
public function postCombatResults($args) { list($defenderId, $attackers, $combatResults, $dieRoll) = $args; $b = Battle::getBattle(); $cr = $b->combatRules; $f = $b->force; foreach ($attackers as $attackId => $v) { $unit = $f->units[$attackId]; $hexagon = $unit->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); if ($b->terrain->terrainIs($hexpart, 'town') || $b->terrain->terrainIs($hexpart, 'forest')) { $cr->sighted($hexagon->name); } } }
public function setCombatIndex($defenderId) { $combatLog = ""; $battle = Battle::getBattle(); $scenario = $battle->scenario; $combats = $battle->combatRules->combats->{$defenderId}; if (count((array) $combats->attackers) == 0) { $combats->index = null; $combats->attackStrength = null; $combats->defenseStrength = null; $combats->terrainCombatEffect = null; return; } $defenders = $combats->defenders; $isCrest = $isCavalry = $isTown = $isHill = $isForest = $isSwamp = $attackerIsSunkenRoad = $isRedoubt = $isElevated = false; $combats->index = []; foreach ($defenders as $defId => $defender) { $defUnit = $battle->force->units[$defId]; $hexagon = $defUnit->hexagon; if ($defUnit->class === 'cavalry') { $isCavalry = true; } $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $isTown |= $battle->terrain->terrainIs($hexpart, 'town'); $isForest |= $battle->terrain->terrainIs($hexpart, 'forest'); if ($battle->terrain->terrainIs($hexpart, 'elevation')) { $isElevated = 1; } if ($battle->terrain->terrainIs($hexpart, 'elevation2')) { $isElevated = 2; } $defenseStrength = $defUnit->defenseStrength; } $isClear = true; if ($isTown || $isForest || $isHill || $isSwamp) { $isClear = false; } $attackers = $combats->attackers; $attackStrength = 0; $attackersCav = false; $combinedArms = array(); $combatLog .= "<br>"; foreach ($attackers as $attackerId => $attacker) { $terrainReason = ""; $unit = $battle->force->units[$attackerId]; $unitStrength = $unit->strength; $hexagon = $unit->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $los = new Los(); $los->setOrigin($battle->force->getUnitHexagon($attackerId)); $los->setEndPoint($battle->force->getUnitHexagon($defenderId)); $range = $los->getRange(); $hexParts = $los->getlosList(); $targetHex = array_pop($hexParts); $targetHexSide = array_pop($hexParts); if ($battle->terrain->terrainIs($targetHexSide, "crest")) { $isCrest = true; } $combatLog .= $unit->strength . " " . $unit->class . " = " . $unit->strength . "<br>"; if ($range == 1) { $isCloseAssault = false; if ($unit->weapons === ModernTacticalUnit::SM_WEAPONS) { if ($defenderId !== false) { $defUnit = $battle->force->units[$defenderId]; if ($defUnit->target === ModernTacticalUnit::HARD_TARGET) { $isCloseAssault = true; } } } if (!$isCloseAssault) { $unitStrength *= 2; $combatLog .= "range 1, doubled = {$unitStrength}<br>"; } else { $combatLog .= "close assult no range attenuation = {$unitStrength}<br>"; } } if ($range >= 4 && $range <= 5) { $unitStrength -= 1; $combatLog .= " -1 range attentuation = {$unitStrength}<br>"; } if ($range >= 6 && $range <= 8) { $unitStrength -= 2; $combatLog .= " -2 range attentuation = {$unitStrength}<br>"; } if ($range >= 9 && $range <= 10) { $unitStrength -= 3; $combatLog .= " -3 range attentuation = {$unitStrength}<br>"; } if ($range >= 11) { $unitStrength -= 6; $combatLog .= "-6 range attentuation = {$unitStrength}<br>"; } $attackerIsElevated = false; if ($battle->terrain->terrainIs($hexpart, 'elevation')) { $attackerIsElevated = 1; } if ($battle->terrain->terrainIs($hexpart, 'elevation2')) { $attackerIsElevated = 2; } $unitStrength -= $defenseStrength; $combatLog .= " - {$defenseStrength} defender = {$unitStrength}<br>"; if ($isForest) { $unitStrength--; $combatLog .= " in forest - 1 = <span class='fixed-width' >{$unitStrength}</span><br>"; } if ($isTown) { $unitStrength -= 2; $combatLog .= " in town - 2 = <span class='fixed-width' >{$unitStrength}</span><br>"; } if ($isCrest) { $unitStrength -= 1; $combatLog .= " in crest - 1 = <span class='fixed-width' >{$unitStrength}</span><br>"; } $combatLog .= "final = {$unitStrength}<br><br>"; $combats->index[] = $unitStrength; } $combats->combatLog = $combatLog; }
function getDefenderTraverseCombatEffect($startHexagon, $endHexagon, $attackingForceId) { $combatEffect = 0; $hexsideX = ($startHexagon->getX() + $endHexagon->getX()) / 2; $hexsideY = ($startHexagon->getY() + $endHexagon->getY()) / 2; $hexpart = new Hexpart($hexsideX, $hexsideY); $terrains = $this->getTerrainCodeXY($hexpart->getX(), $hexpart->getY()); foreach ($terrains as $terrainFeature) { $combatEffect += $this->terrainFeatures->{$terrainFeature}->combatEffect; } return $combatEffect; }
public function setCombatIndex($defenderId) { $combatLog = ""; /* @var JagCore $battle */ $battle = Battle::getBattle(); $scenario = $battle->scenario; $combats = $battle->combatRules->combats->{$defenderId}; if (count((array) $combats->attackers) == 0) { $combats->index = null; $combats->attackStrength = null; $combats->defenseStrength = null; $combats->terrainCombatEffect = null; return; } $defenders = $combats->defenders; $isCavalry = $isTown = $isHill = $isForest = $isSwamp = $attackerIsSunkenRoad = $isRedoubt = $isElevated = false; foreach ($defenders as $defId => $defender) { $defUnit = $battle->force->units[$defId]; $hexagon = $defUnit->hexagon; if ($defUnit->class === 'cavalry') { $isCavalry = true; } $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $isTown |= $battle->terrain->terrainIs($hexpart, 'town'); $isForest |= $battle->terrain->terrainIs($hexpart, 'forest'); if ($battle->terrain->terrainIs($hexpart, 'elevation')) { $isElevated = 1; } if ($battle->terrain->terrainIs($hexpart, 'elevation2')) { $isElevated = 2; } } $isClear = true; if ($isTown || $isForest || $isHill || $isSwamp) { $isClear = false; } $attackers = $combats->attackers; $attackStrength = 0; $attackersCav = false; $combinedArms = array(); $combatLog .= "Attackers<br>"; foreach ($attackers as $attackerId => $attacker) { $terrainReason = ""; $unit = $battle->force->units[$attackerId]; $unitStrength = $unit->strength; $hexagon = $unit->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $los = new Los(); $los->setOrigin($battle->force->getUnitHexagon($attackerId)); $los->setEndPoint($battle->force->getUnitHexagon($defenderId)); $range = $los->getRange(); $combatLog .= $unit->strength . " " . $unit->class . " "; if ($isCavalry) { $combatLog .= "defender is cavalry, doubled "; $unitStrength *= 2; } if ($unit->class === "infantry" && $range == 1) { $combatLog .= "infantry at range 1, doubled "; $unitStrength *= 2; } if ($unit->class === "mg" && $range <= 3) { $combatLog .= "machine gun at range 3 or less, doubled "; $unitStrength *= 2; } if ($isTown || $isForest) { if ($range > 1) { $combatLog .= "using observation fire, halved "; $unitStrength /= 2; } } $attackerIsElevated = false; if ($battle->terrain->terrainIs($hexpart, 'elevation')) { $attackerIsElevated = 1; } if ($battle->terrain->terrainIs($hexpart, 'elevation2')) { $attackerIsElevated = 2; } $combatLog .= "<br>"; $attackStrength += $unitStrength; } $combatLog .= " = {$attackStrength}<br>Defenders<br>"; $defenseStrength = 0; foreach ($defenders as $defId => $defender) { $unitStrength = 2; $terrain = ''; $unit = $battle->force->units[$defId]; $class = $unit->class; $clearHex = false; $notClearHex = false; $hexagon = $unit->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $isTown = $battle->terrain->terrainIs($hexpart, 'town'); // $isHill = $battle->terrain->terrainIs($hexpart, 'hill'); $isForest = $battle->terrain->terrainIs($hexpart, 'forest'); $isSwamp = $battle->terrain->terrainIs($hexpart, 'swamp'); $terran = ""; if ($attackerIsElevated < $isElevated) { $unitStrength = 4; $terrain = "uphill "; } if ($isTown) { $terrain = "in town "; $unitStrength = 8; } if ($isForest) { $terrain = "in forest "; $unitStrength = 5; } if ($unit->isImproved) { $unitStrength *= 2; $terrain .= "Improved "; } $combatLog .= "{$unitStrength} " . $unit->class . " {$terrain}"; $defenseStrength += $unitStrength; $combatLog .= "<br>"; } $combatLog .= " = {$defenseStrength}"; $combatIndex = $this->getCombatIndex($attackStrength, $defenseStrength); /* Do this before terrain effects */ if ($combatIndex >= $this->maxCombatIndex) { $combatIndex = $this->maxCombatIndex; } // $terrainCombatEffect = $battle->combatRules->getDefenderTerrainCombatEffect($defenderId); // $combatIndex -= $terrainCombatEffect; $combats->attackStrength = $attackStrength; $combats->defenseStrength = $defenseStrength; $combats->terrainCombatEffect = 0; // // if($combats->pinCRT !== false){ // $pinIndex = $combats->pinCRT; // if($combatIndex > $pinIndex){ // $combatLog .= "<br>Pinned to {$this->combatResultsHeader[$pinIndex]} "; // }else{ // $combats->pinCRT = false; // } // } $combats->index = $combatIndex; $combats->useAlt = false; $combats->combatLog = $combatLog; }
public function setCombatIndex($defenderId) { /* @var Jagersdorf $battle */ $battle = Battle::getBattle(); $combats = $battle->combatRules->combats->{$defenderId}; $hexagon = $battle->force->units[$defenderId]->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); if (count((array) $combats->attackers) == 0) { $combats->index = null; $combats->attackStrength = null; $combats->defenseStrength = null; $combats->terrainCombatEffect = null; return; } $isClear = $battle->terrain->terrainIs($hexpart, 'clear'); $isTown = $battle->terrain->terrainIs($hexpart, 'town'); $isHill = $battle->terrain->terrainIs($hexpart, 'hill'); $isForest = $battle->terrain->terrainIs($hexpart, 'forest'); $defenders = $combats->defenders; $attackers = $combats->attackers; $attackStrength = 0; $attackersCav = false; $combinedArms = ['infantry' => 0, 'artillery' => 0, 'cavalry' => 0]; foreach ($attackers as $attackerId => $attacker) { $unit = $battle->force->units[$attackerId]; $unitStrength = $unit->strength; if ($unit->class == "infantry") { // if($unit->forceId == PRUSSIAN_FORCE && $isClear){ // $unitStrength++; // } // if($unit->forceId == RUSSIAN_FORCE && ($isTown || $isForest)){ // $unitStrength++; // } if ($battle->combatRules->thisAttackAcrossRiver($defenderId, $attackerId)) { $unitStrength /= 2; } } if ($unit->class == "cavalry") { $attackersCav = true; if ($battle->combatRules->thisAttackAcrossRiver($defenderId, $attackerId) || !$isClear) { $unitStrength /= 2; } } $attackStrength += $unitStrength; } // $attackStrength = $battle->force->getAttackerStrength($combats->attackers); $defenseStrength = 0; $defendersAllCav = true; foreach ($defenders as $defId => $defender) { $unit = $battle->force->units[$defId]; $class = $unit->class; $unitDefense = $unit->defStrength; if ($unit->class != 'cavalry') { $defendersAllCav = false; } // if($unit->forceId == PRUSSIAN_FORCE && $class == "infantry" && $isClear){ // $unitDefense += 1; // } // if($unit->forceId == RUSSIAN_FORCE && $class == "infantry" && ($isTown || $isForest)){ // $unitDefense += 1; // } $defenseStrength += $unitDefense * ($isTown && $class != 'cavalry' || $isHill ? 2 : 1); } if ($attackStrength >= $defenseStrength) { foreach ($combats->attackers as $attackerId => $attacker) { $combinedArms[$battle->force->units[$attackerId]->class]++; } if (!$isClear) { unset($combinedArms['cavalry']); } } $armsShift = 0; if ($attackStrength >= $defenseStrength) { foreach ($combinedArms as $arms) { if ($arms > 0) { $armsShift++; } } $armsShift--; } if ($armsShift < 0) { $armsShift = 0; } $combatIndex = $this->getCombatIndex($attackStrength, $defenseStrength); /* Do this before terrain effects */ $combatIndex += $armsShift; if ($combatIndex >= $this->maxCombatIndex) { $combatIndex = $this->maxCombatIndex; } // $terrainCombatEffect = $battle->combatRules->getDefenderTerrainCombatEffect($defenderId); // $combatIndex -= $terrainCombatEffect; $combats->attackStrength = $attackStrength; $combats->defenseStrength = $defenseStrength; $combats->terrainCombatEffect = $armsShift; $combats->index = $combatIndex; $combats->useAlt = false; if ($defendersAllCav && !$attackersCav) { $combats->useAlt = true; } }
function setCombatIndex($defenderId) { $combatLog = ""; $battle = Battle::getBattle(); $combatRules = $battle->combatRules; $terrain = $battle->terrain; $combats = $battle->combatRules->combats->{$defenderId}; /* @var Force $force */ $force = $battle->force; $hexagon = $battle->force->units[$defenderId]->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); if (count((array) $combats->attackers) == 0) { $combats->index = null; $combats->attackStrength = null; $combats->defenseStrength = null; $combats->terrainCombatEffect = null; return; } $defenders = $combats->defenders; $attackStrength = 0; // $attackStrength = $this->force->getAttackerStrength($combats->attackers); $defenseStrength = 0; $defMarsh = false; $defArt = false; $combatLog .= "<br>Defenders<br> "; foreach ($defenders as $defId => $defender) { $unit = $battle->force->units[$defId]; $unitStr = $unit->defStrength; $combatLog .= $unit->class . " {$unitStr}"; $unit = $force->units[$defId]; $unitHex = $unit->hexagon; if ($unit->class == "artillery") { $defArt = true; } if ($terrain->terrainIsHex($unitHex->name, "rough") || $terrain->terrainIsHex($unitHex->name, "hills")) { $unitStr *= 2; $combatLog .= " 2x rough {$unitStr}"; } if ($terrain->terrainIsHex($unitHex->name, "marsh")) { $defMarsh = true; if ($unit->class == "inf" || $unit->class == "cavalry") { $unitStr *= 2; $combatLog .= " 2x marsh {$unitStr}"; } } $combatLog .= "<br>"; $defenseStrength += $unitStr; } $defHex = $unitHex; $combatLog .= "Total {$defenseStrength}<br>"; $combatLog .= "<br>Attackers<br>"; foreach ($combats->attackers as $id => $v) { $unit = $force->units[$id]; $unitStr = $unit->strength; $combatLog .= $unit->class . " " . $unit->strength; if ($unit->class != 'artillery' && $terrain->terrainIsHexSide($defHex->name, $unit->hexagon->name, "blocked")) { $unitStr = 0; } if ($unit->class != 'artillery' && ($terrain->terrainIsHexSide($defHex->name, $unit->hexagon->name, "river") || $terrain->terrainIsHexSide($defHex->name, $unit->hexagon->name, "ford"))) { $unitStr /= 2; } if ($defMarsh && $force->units[$id]->class == 'mech') { $unitStr /= 2; $combatLog .= " mech into marsh halved {$unitStr}"; } if ($defArt && $force->units[$id]->class != 'artillery') { $unitStr *= 2; } $combatLog .= "<br>"; $attackStrength += $unitStr; } $combatLog .= "Total {$attackStrength}<br><br>"; $terrainCombatEffect = 0; $combatIndex = $this->getCombatIndex($attackStrength, $defenseStrength); /* Do this before terrain effects */ if ($combatIndex >= $this->maxCombatIndex) { $combatIndex = $this->maxCombatIndex; } $combatIndex -= $terrainCombatEffect; $combats->attackStrength = $attackStrength; $combats->defenseStrength = $defenseStrength; $combats->terrainCombatEffect = $terrainCombatEffect; $combats->index = $combatIndex; $combats->combatLog = $combatLog; // $this->force->storeCombatIndex($defenderId, $combatIndex); }
function setupCombat($id, $shift = false) { $battle = Battle::getBattle(); $victory = $battle->victory; $unit = $battle->force->units[$id]; $cd = $this->currentDefender; if ($this->force->unitIsEnemy($id) == true) { $isHidden = false; $hexagon = $battle->force->units[$id]->hexagon; $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $isHidden |= $battle->terrain->terrainIs($hexpart, 'town'); $isHidden |= $battle->terrain->terrainIs($hexpart, 'forest'); if ($isHidden && !$battle->force->unitIsAdjacent($id) && !$this->isSighted($hexagon->name, $id)) { return false; } // $this->sighted($hexagon->name); // defender is already in combatRules, so make it currently selected // if(isset($this->defenders->$id)){ // $id = $this->defenders->$id; // } $combats = isset($this->combats->{$id}) ? $this->combats->{$id} : []; $combatId = $id; if (isset($this->defenders->{$id})) { $combatId = $this->defenders->{$id}; // $cd = $this->defenders->$id; $combats = $this->combats->{$combatId}; } if ($combats) { // if(count($this->combats->$this->currnetDefender->attackers) == 0){ // unset($this->currnetDefender[$id]); // } if ($this->currentDefender === false) { $this->currentDefender = $this->defenders->{$id}; } else { if ($shift) { if (isset($this->defenders->{$id})) { if ($combatId === $this->currentDefender) { foreach ($combats->attackers as $attackerId => $attacker) { $this->force->undoAttackerSetup($attackerId); unset($this->attackers->{$attackerId}); $victory->postUnsetAttacker($this->units[$attackerId]); } foreach ($combats->defenders as $defenderId => $defender) { $unit = $this->force->getUnit($defenderId); $unit->setStatus(STATUS_READY); unset($this->defenders->{$defenderId}); $victory->postUnsetDefender($unit); } unset($this->combats->{$combatId}); $this->currentDefender = false; } else { $this->currentDefender = $combatId; } } } else { if ($combatId === $this->currentDefender) { $this->currentDefender = false; } else { $this->currentDefender = $combatId; } } } } else { if ($shift) { if ($this->currentDefender !== false) { foreach ($this->combats->{$this->currentDefender}->attackers as $attackerId => $attacker) { $this->force->undoAttackerSetup($attackerId); unset($this->attackers->{$attackerId}); unset($this->combats->{$cd}->attackers->{$attackerId}); unset($this->combats->{$cd}->thetas->{$attackerId}); $victory->postUnsetAttacker($this->units[$attackerId]); } $this->defenders->{$id} = $this->currentDefender; } else { $this->currentDefender = $id; $this->defenders->{$id} = $id; } } else { $mapHex = $battle->mapData->getHex($unit->hexagon->getName()); $forces = $mapHex->getForces($unit->forceId); $this->currentDefender = $id; foreach ($forces as $force) { if ($this->force->units[$force]->class !== "air" && ($battle->gameRules->phase == RED_AIR_COMBAT_PHASE || $battle->gameRules->phase == BLUE_AIR_COMBAT_PHASE)) { continue; } $this->defenders->{$force} = $id; if ($force != $id) { $cd = $this->currentDefender; $this->force->setupDefender($force); if (!$this->combats) { $this->combats = new stdClass(); } if (!$this->combats->{$cd}) { $this->combats->{$cd} = new Combat(); } $this->combats->{$cd}->defenders->{$force} = $id; } } } $cd = $this->currentDefender; // $this->defenders->{$this->currentDefender} = $id; $this->force->setupDefender($id); if (!$this->combats) { $this->combats = new stdClass(); } if (empty($this->combats->{$cd})) { $this->combats->{$cd} = new Combat(); } $this->combats->{$cd}->defenders->{$id} = $id; // $victory->postSetDefender($this->force->units[$id]); } } else { if ($this->currentDefender !== false && $this->force->units[$id]->status != STATUS_UNAVAIL_THIS_PHASE) { if (isset($this->combats->{$cd}->attackers->{$id}) && $this->attackers->{$id} === $cd) { $this->force->undoAttackerSetup($id); unset($this->attackers->{$id}); unset($this->combats->{$cd}->attackers->{$id}); unset($this->combats->{$cd}->thetas->{$id}); $victory->postUnsetAttacker($this->force->units[$id]); $this->crt->setCombatIndex($cd); } else { $good = true; foreach ($this->combats->{$this->currentDefender}->defenders as $defenderId => $defender) { $los = new Los(); $los->setOrigin($this->force->getUnitHexagon($id)); $los->setEndPoint($this->force->getUnitHexagon($defenderId)); $range = $los->getRange(); if ($range > $unit->getRange($id)) { $good = false; break; } if ($range > 1) { $good = $this->checkBlocked($los, $id); if ($good) { $isHidden = false; $hexagon = $this->force->getUnitHexagon($defenderId); $hexpart = new Hexpart(); $hexpart->setXYwithNameAndType($hexagon->name, HEXAGON_CENTER); $isHidden |= $battle->terrain->terrainIs($hexpart, 'town'); $isHidden |= $battle->terrain->terrainIs($hexpart, 'forest'); if ($isHidden && !$this->isSighted($hexagon->name, $cd)) { /* confirm observer is in los too */ $bad = true; $adjacentUnits = $this->force->getAdjacentUnits($defenderId); $observerLos = new Los(); $observerLos->setOrigin($this->force->getUnitHexagon($id)); foreach ($adjacentUnits as $adjacentUnitId => $v) { $observerLos->setEndPoint($this->force->getUnitHexagon($adjacentUnitId)); if ($this->checkBlocked($observerLos, $adjacentUnitId)) { $bad = false; break; } } if ($bad) { $good = false; } } } } if ($range == 1) { if ($this->terrain->terrainIsHexSide($this->force->getUnitHexagon($id)->name, $this->force->getUnitHexagon($defenderId)->name, "blocked") && !($unit->class === "artillery" || $unit->class === "horseartillery")) { $good = false; } } if (method_exists($unit, "checkLos")) { if ($unit->checkLos($los, $defenderId) === false) { $good = false; } } } if ($good) { foreach ($this->combats->{$this->currentDefender}->defenders as $defenderId => $defender) { $los = new Los(); $los->setOrigin($this->force->getUnitHexagon($id)); $los->setEndPoint($this->force->getUnitHexagon($defenderId)); $range = $los->getRange(); $bearing = $los->getBearing(); if ($range <= $unit->getRange($id)) { $this->force->setupAttacker($id, $range); if (isset($this->attackers->{$id}) && $this->attackers->{$id} !== $cd) { /* move unit to other attack */ $oldCd = $this->attackers->{$id}; unset($this->combats->{$oldCd}->attackers->{$id}); unset($this->combats->{$oldCd}->thetas->{$id}); $this->crt->setCombatIndex($oldCd); $this->checkBombardment($oldCd); } $this->attackers->{$id} = $cd; $this->combats->{$cd}->attackers->{$id} = $bearing; $this->combats->{$cd}->defenders->{$defenderId} = $bearing; if (empty($this->combats->{$cd}->thetas->{$id})) { $this->combats->{$cd}->thetas->{$id} = new stdClass(); } $this->combats->{$cd}->thetas->{$id}->{$defenderId} = $bearing; $victory->postSetDefender($this->force->units[$defenderId]); $this->crt->setCombatIndex($cd); } } $victory->postSetAttacker($this->force->units[$id]); } } $this->checkBombardment(); } } $this->cleanUpAttacklessDefenders(); }