diff --git a/GameEngine/HeroBattleBonus.php b/GameEngine/HeroBattleBonus.php index e1f18aa6..f1365d1b 100644 --- a/GameEngine/HeroBattleBonus.php +++ b/GameEngine/HeroBattleBonus.php @@ -469,19 +469,23 @@ class HeroBattleBonus $used = array_sum($captured); $heroItems->removeItem((int) $uid, (int) $cageRow['id'], $used); - // Station the animals at home: reuse the self-enforcement row if one - // exists (vref = from = home), otherwise create it. + // Station the animals at home as a NATURE reinforcement: `from` = 0 is + // the engine's existing convention for non-player enforcements (the + // "taskmaster" rows) - 16.tpl renders those with tribe 4 columns + // (u31-u40, the animal icons) and disables the normal Send back flow, + // which would otherwise crash on speed lookup for nature units. + // Reuse the row if one exists, otherwise create it. $homeWref = (int) $homeWref; $res = mysqli_query( $database->dblink, "SELECT id FROM " . TB_PREFIX . "enforcement - WHERE vref = $homeWref AND `from` = $homeWref LIMIT 1" + WHERE vref = $homeWref AND `from` = 0 LIMIT 1" ); $rowE = $res ? mysqli_fetch_assoc($res) : null; if (!$rowE) { mysqli_query( $database->dblink, - "INSERT INTO " . TB_PREFIX . "enforcement (vref, `from`) VALUES ($homeWref, $homeWref)" + "INSERT INTO " . TB_PREFIX . "enforcement (vref, `from`) VALUES ($homeWref, 0)" ); $enfId = (int) mysqli_insert_id($database->dblink); } else { diff --git a/GameEngine/Lang/en.php b/GameEngine/Lang/en.php index 71ec7470..a942c88e 100755 --- a/GameEngine/Lang/en.php +++ b/GameEngine/Lang/en.php @@ -2821,3 +2821,7 @@ tz_def('HB_TXT_CAGE', 'Captures 1 oasis animal per cage'); tz_def('HB_TXT_NEEDS_HORSE','requires an equipped horse'); tz_def('HB_TXT_ONLY', 'only for a'); tz_def('HB_TXT_HERO', 'hero'); + +/* T4 hero port - captured animals release action */ +tz_def('HERO_RELEASE_ANIMALS', 'Release'); +tz_def('HERO_RELEASE_CONFIRM', 'Release these animals? They will be gone for good.'); diff --git a/GameEngine/Units.php b/GameEngine/Units.php index 1ef20ea0..46e84a9b 100755 --- a/GameEngine/Units.php +++ b/GameEngine/Units.php @@ -692,6 +692,33 @@ class Units { * @param int the ID of the prisoners you want to release */ + /** + * T4 hero port: destroy a NATURE enforcement row (captured oasis animals, + * `from` = 0) stationed in the CURRENT village. Mirrors deletePrisoners' + * ownership model: the row must belong to the village the player is + * viewing, which the session already validated as theirs. Nature rows + * never travel back (no owner village to walk to) - releasing kills them. + */ + public function releaseNatureEnforcement($id){ + global $village, $database; + + $id = (int) $id; + if ($id <= 0) { + return false; + } + + $stmt = $database->dblink->prepare( + "DELETE FROM " . TB_PREFIX . "enforcement + WHERE id = ? AND `from` = 0 AND vref = ? LIMIT 1" + ); + $wid = (int) $village->wid; + $stmt->bind_param('ii', $id, $wid); + $stmt->execute(); + $ok = $stmt->affected_rows > 0; + $stmt->close(); + return $ok; + } + public function deletePrisoners($id){ global $village, $database, $session, $building, $bid19, $u99; @@ -796,6 +823,16 @@ class Units { $speeds[] = $GLOBALS['u'.$heroUnit]['speed']; } + // Defensive: the tribe-offset loop above only inspects the owner's + // own 10 unit columns, so an army made purely of foreign/nature units + // (e.g. captured oasis animals) yields no speeds and min() would + // fatal (the "Send back" crash). Unreachable through normal flows + // now that nature rows disable Send back, but never crash movement + // creation - fall back to the slowest common speed. + if (empty($speeds)) { + $speeds[] = 3; + } + $walkTime = $generator->procDistanceTime($fromCor, $toCor, min($speeds), $mode, $from); // T4 hero port (Phase 5): boots (>20 tiles), pennant (own villages) diff --git a/Templates/Build/16.tpl b/Templates/Build/16.tpl index a421fb48..5493414d 100644 --- a/Templates/Build/16.tpl +++ b/Templates/Build/16.tpl @@ -93,7 +93,7 @@ $hasRally = $village->resarray['f39'] > 0;
getUpkeep($e,$tribe) ?>
-
+
diff --git a/a2b.php b/a2b.php index 65ae8199..6ef535a9 100644 --- a/a2b.php +++ b/a2b.php @@ -60,6 +60,11 @@ if(isset($_GET['r'])) $r = preg_replace("/[^a-zA-Z0-9_-]/", "", $_GET['r']); if(isset($_GET['delprisoners'])){ $delprisoners = preg_replace("/[^a-zA-Z0-9_-]/", "", $_GET['delprisoners']); } +// T4 hero port: release (destroy) captured oasis animals from a nature +// enforcement row (from = 0). Same sanitization as delprisoners. +if(isset($_GET['releaseanimals'])){ + $releaseanimals = preg_replace("/[^0-9]/", "", $_GET['releaseanimals']); +} if(isset($_GET['o'])){ $o = preg_replace("/[^a-zA-Z0-9_-]/", "", $_GET['o']); $oid = preg_replace("/[^a-zA-Z0-9_-]/", "", $_GET['z']); @@ -156,6 +161,12 @@ if(!empty($id)){ include("Templates/a2b/search.tpl"); } }else if(isset($delprisoners) && !empty($delprisoners)) $units->deletePrisoners($delprisoners); +else if(isset($releaseanimals) && !empty($releaseanimals)){ + // T4 hero port: destroy captured animals, then back to the rally point. + $units->releaseNatureEnforcement($releaseanimals); + header("Location: build.php?id=39"); + exit; +} else{ if(isset($process['0'])){ $coor = $database->getCoor($process['0']);