Move the attacker/defender total-population computation (and the two
getProfileVillages() lookups that feed it) out of the per-attack loop into a
dedicated private method. Behaviour-preserving: the method takes the initial
$defpop/$attpop (0 for villages, 500 for the oasis branch) and accumulates onto
them exactly as before, and returns the village lists ($varray/$varray1) used
later for the can-destroy check and handleConquest().
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract the pre-casualty defender report block into a new private method
collectReinforcementReport(): reset and rebuild the reinforcement unit totals
($DefenderEnf) and per-tribe hero totals from a fresh re-select, fold
reinforcement heroes into the defender's hero count, build the "units sent"
report rows (own troops + reinforcements and their masked variants), and
(re)initialise the per-tribe dead-hero accumulator. The bundle is returned to
the caller and the defender's folded hero count is reassigned at the call site.
Pure behaviour-preserving extraction. Method name matches the maintainer's
roadmap for #155.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract the "kill other defence in village" block (reinforcement casualties)
into a new private method applyReinforcementCasualties(): compute each
reinforcement's dead units/hero, persist them (modifyEnforce), notify the
reinforcing players, and delete fully-wiped reinforcements. Dead counts are
accumulated into $alldead and dead heroes into $DefenderHeroesDeadArray (both
passed by reference); the tribe-presence flags (rom/ger/gal/nat/natar) are
returned to the caller.
Pure behaviour-preserving extraction. Also drops two dead recomputations of
$totalsend_att/$totaldead_att that sat inside the loop and were immediately
overwritten right after it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Move the in-village defender casualty handling (kill ratio applied to the
defender's own troops + hero, persisted via modifyUnit) out of the giant
sendunitsComplete() loop into a dedicated private method returning the
$owndead map. Pure behaviour-preserving extraction; also drops a dead $u
variable that was assigned but never read.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The #155 refactor that extracted buildCombatReport() turned one comma
into a literal dot in the non-scout data2 string:
...$info_chief.'.'.(isset($info_spy) ? ... // was ','
That dropped one CSV field, shifting every following field left by one
(hero troops t11, casualties, prisoners 182-192) and injecting a stray
"." into a numeric cell. Visible attack reports rendered with misplaced
hero/prisoner data, and the shifted text in the prisoner slots is what
made Templates/Notice/1.tpl array_sum() warn under PHP 8.
Restore the comma so the layout matches what the report template
(Notice/1.tpl) and the pre-refactor code expect. Reports stored before
this fix keep their corrupted string; the int-cast guard added in the
previous commit keeps them from re-emitting the warning.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PHP 8.x turned several long-standing implicit accesses into runtime
warnings that flooded the error log during attacks and report viewing:
- Battle.report (Templates/Notice/1.tpl): the prisoner check ran
array_sum() over slots that may hold non-numeric text (the
"Information" line can shift indices), raising
"Addition is not supported on type string". Sum int-cast values.
- Database::getUnitsNumber(): movement/reinforcement arrays can be null
or miss tribe-specific unit keys, raising "Undefined array key" and
"Trying to access array offset on null". Null-coalesce to 0.
- Automation (combat resolver): $scout was only defined for scouting
attacks (type 1) yet always passed to buildCombatReport(), raising
"Undefined variable $scout". Initialize it for every attack type.
- Automation: the destroy-village check read $to['natar'] which is not
always set, raising "Undefined array key". Use empty().
Pure null-safety / behaviour-preserving changes; no gameplay logic
altered.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Honour the per-user report-filter checkboxes in marketComplete():
- v4: recipient gets no report for transfers between own villages
- v6: recipient gets no report for transfers from foreign villages
- v5: sender gets no report for transfers to foreign villages
The user row is already fully loaded by getUserFields(), so the prefs
are read without extra queries. Removes the "not coded yet" tag from
the report-filter section in the preferences form.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Phase C of the sendunitsComplete() refactor (issue #155).
- handlePrisoners(): extracts the ~100-line block that releases troops
trapped in the defender's traps during a conquest attack (type 3),
sends them home with 25% casualties, repairs destroyed traps, and
returns the HTML fragment for the battle-report trap line.
- buildCombatReport(): extracts the assembly of the $data2 (main report)
and $data_fail (all-attacker-dead fallback) CSV strings, including the
"village destroyed" annotation in $info_cat and the final appending of
$info_trap / $info_troop / $info_hero.
Pure behaviour-preserving extractions — no logic change.
Validated by deterministic A/B harness (infantry, evasion, conquest).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The #182 merge resolution left buildScoutReport() defined but never called,
while the original inline scout-report block was kept at the call site — so
the method was dead code and the scout-report logic was duplicated.
This wires it up: the inline block in the `if (!empty($scout))` branch is
replaced by a single `$info_spy = $this->buildScoutReport(...)` call. The
method already exists and its body is identical to the removed inline block,
so behaviour is unchanged — this just removes the duplication and makes the
extraction actually take effect. Brace balance even (634/634).
Co-authored-by: TravianZ Patcher <patcher@localhost>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The merge of #180 (applyBounty) and #181 (buildScoutReport) — both of which
inserted a new private method just before sendunitsComplete() — dropped the
closing brace of buildScoutReport(). As a result applyBounty() was declared
INSIDE buildScoutReport(), producing:
PHP Parse error: syntax error, unexpected token "private"
in GameEngine/Automation.php
This crashes Automation.php entirely (HTTP 500), so the whole game automation
stops: troop movements never resolve, buildings never finish, etc.
Fix: restore the missing `}` closing buildScoutReport() before the applyBounty()
docblock. Brace balance is now even again (634/634). One-character structural
fix, no logic change.
Co-authored-by: TravianZ Patcher <patcher@localhost>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Catalin Novgorodschi <cata7007@gmail.com>
Phase B — pure behaviour-preserving extraction (issue #155).
buildScoutReport(): extracts the scout-report (info_spy) HTML assembly
(~25 lines) into a helper returning the info_spy string. Handles both
spy modes: resources (spy=1) and defence/buildings (spy=2). The block's
body is moved verbatim (multi-line strings with their exact embedded
whitespace preserved). The reassigned $walllevel/$residencelevel/
$palacelevel were local to this block and never read downstream. No
logic change.
Co-authored-by: TravianZ Patcher <patcher@localhost>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Catalin Novgorodschi <cata7007@gmail.com>
1. Fix a bug in Admin Panel that you can edit by yourself your rank, now you cannot edit your rank anymore.
2. Now Alliance Leader can edit his own Position
3. Fix negative value on Demolition Building, now in database at lvl is appear new level not -1
4. Refactor Ajax map, now all is alligned (Ajax folder and Map folder)
5. Fix bug from Palace (when change capital now Automation recount population automaticaly on old capital and new capital)
Incremental Refactor Automation (starvation split in more methods) & Database (cache & checkAllianceEmbassiesStatus refactor), Fix a bug in Alliance.php (now you cannot kick alliance leader)
+Fixed a bug that didn't return reinforcements in counquered oasis, if
it was released by the owner, or from the admin panel
+Changed the catapults and rams formulas (still not completed at 100%),
thanks to Kirilloid!
+Changed the Natars' capital default coordinates
+Fixed a bug that showed "The village has been destroyed" two times, if
an artifact was conquered from Natars (or from a 0 popped village) and
there were catapults in the attack
+Added the "Artifacts" section in the Admin Panel, which contains two
options: return a deleted artifact to the Natars and create new
Artifacts, assigned to a specified player
+Return to Natars coded, in the village section of the Admin Panel
+Moved a lot of functions and costants from Automation.php to the "new"
class Artifacts.php
+Optimized a lot the whole Natars creation process, decreased the number
of query of about 600
+Optimized a lot the function which deletes a player's account, it's now
executed almost instantly, even with players with a lot of villages
+Redesigned the map spawn system, using a more Travian-like village
distribution
+Fixed a bug that did show a broken village in the artifact chronology,
if that village was destroyed
+Reduced the amount of redundant code (about 230 lines) for
27_1.tpl/27_2.tpl and 27_3.tpl
+Fixed a bug that permitted to build the Great Granary and the Great
Warehouse in the whole account, with only a village effect artifact
+Fixed a bug in the Admin Panel map that didn't permit to show village
informations, if that village contained single quotes in its name
+Fixed a bug that didn't delete artifacts when a player deleted his
account
+Added "(artifact)" if a village has an artifact in the village overview
+Added the artifact section in the multihunter panel (return to natars
doesn't work yet)
NOTE: To play this version of the game, you have to run this query first
(where "s1_" is the prefix of your server):
ALTER TABLE `s1_artefacts` ADD `del` TINYINT(1) NULL DEFAULT '0' AFTER
`lastupdate`;
ALTER TABLE `testtravian`.`s1_artefacts` ADD INDEX
`active-owner-conquered-del` (`active`, `owner`, `conquered`, `del`);
+You can no longer build WW if your and your alliance building plans
aren't active yet
+You can no longer remove the WW from the village if you remove it from
the building queue
+Spies from every tribe will now consume crop correctly, when returning
from a scouting attacks
+Spies from every tribe will now be displayed correctly, in the "Troops"
tab of dorf3.php, when returning from a scouting attack
+Building levels will now not be downgraded by 1 level, when conquering
a Natars' village
+Natars' villages with an artifact inside, will now be deleted if the
artifact is conquered (even if the pop isn't 0)
+Fixed a bug that didn't permit to change the name or the Tag of the
alliance individually
+Fixed a bug that didn't count the population growth sometimes
+Fixed a bug that didn't halve the population consumption in WW villages
+Fixed a bug that didn't permit to show to the defender "None of your
soldiers returned." under certain circumnstances
+Fixed a bug that showed a wrong report icon if the defender had 0
defences and all attacker's units were trapped/killed during the battle
+Fixed a bug that counted a wrong percentage bonus for the horse
drinking trough
+Fixed the (in)famous "doubling troops bug", this has been the oldest
bug I can remember, it lasted 7 years!!!
+Reworked the whole lock system, it's more maintanable and easy to read
now
+Removed some useless class fields, reworked some methods that depended
on them
+Fixed a bug that didn't permit to attack with catapults with the new
automation system
+Fixed a warning that could have been displayed in certain cases
+Separated Automation.php from the UI and users classes
NOTE: This is only a test, it'll not absolutely be as it is in this commit in the final version.
+Moved "isWinner()" method from Automation.php to Session.php, it's now
triggered when activating plus function or entering in
plus1.php/build.php
+General clean-up and better indentation
+The tournament square bonus is now displayed correctly