The `map` user preference ("Show the large map in an extra window") was
saved to users.map but never applied in-game. When enabled, the large-map
button on the map now opens karte2.php in a separate browser window
instead of the in-page iframe overlay (default behaviour kept when the
preference is off).
Also drop the "(not coded yet)" marker from the Large map section of the
preferences page and wire its title to the existing LARGE_MAP constant.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
On a fresh install several strings were still hardcoded in English
(reported on the live server, RO locale):
- statistiken.php: the page <title>, the <h1> and the tab bar
(Player / Alliances / Villages / Heroes / General) were literal English.
- Templates/Ranking/ranksearch.tpl: the "back | forward" pagination links.
- Templates/troops.tpl: the "Hero" troop-row label.
Wire them to language constants. Reuse existing ones
(STATISTICS, PLAYER, PLAYERS, VILLAGES, BACK, FORWARD, U0) and add three
new constants (ALLIANCES, HEROES, GENERAL) to en/fr/ro. WW is kept as-is
(universal acronym).
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 "no tasks" quest mode delivers a Plus + gold shipment on claim
(case '91', and the final case '97'). The reward was granted with a
non-atomic read-modify-write:
$gold = getUserField('gold'); $gold += 15; updateUserField('gold', $gold);
and the quest pointer / timer were advanced unconditionally. Under the
many concurrent ajax requests the game fires, a request that read gold/
plus before the claim and wrote the user row back after it would clobber
the freshly granted reward. The quest_time write (a literal value) still
survived, so the UI advanced to the next shipment countdown while the
player received neither Plus nor gold -- exactly the sporadic symptom in
the report.
Fix: gate the grant on an atomic conditional advance
(UPDATE ... SET quest = 91 WHERE quest = 90) and apply the reward with
in-place SQL increments (gold = gold + 15, plus = IF(plus > now, ...)),
matching the idiom already used in Templates/Plus/*.tpl. This makes the
claim idempotent (duplicate/concurrent requests grant nothing extra) and
immune to the lost-update race. Also fixes a latent case where an expired
Plus timestamp was extended in the past instead of reset to now.
Applied to both quest_core.tpl and quest_core25.tpl.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Localize the 17 "new features" manual pages (Templates/Manual/1111-1126.tpl
and the 1331.tpl index, typ=11/13) so they render in the player's language
instead of hardcoded English.
- Replace hardcoded page titles, descriptions and nav tooltips with constants.
- The 1331 index reuses the per-page title constants and gains
MANUAL_NF_ENABLED / MANUAL_NF_DISABLED for the on/off status labels.
- Add 33 constants each to GameEngine/Lang/{en,fr,ro}.php
(2 status labels + 15 page titles + 16 descriptions).
- en.php uses tz_def() as the English fallback; fr/ro use define().
- Reuse existing constants where they already exist: VACATION_MODE (page 19),
NEW_FEATURES, FORWARD, BACK, OVERVIEW.
it/zh fall back to English. RO strings pending native review.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Localize the 51 in-game manual unit detail pages (Templates/Manual/1*.tpl,
typ=1) so they render in the player's language instead of English, continuing
the manual l10n started in the building pages PR.
What changed:
- 51 unit pages (Romans/Teutons/Gauls/Nature/Natars) now use translation
constants for every hardcoded string: tribe tags -> TRIBE1..5, the stat
labels (attack value, defence vs infantry/cavalry, Velocity, fields/hour,
Can carry, Duration of training), the unit descriptions, the NPC reference
notes and the "forward" nav.
- 48 new constants added to en/fr/ro:
* 7 shared stat labels (MANUAL_ATTACK_VALUE, MANUAL_DEF_INFANTRY,
MANUAL_DEF_CAVALRY, MANUAL_VELOCITY, MANUAL_FIELDS_HOUR, MANUAL_CAN_CARRY,
MANUAL_TRAINING_DURATION)
* 2 NPC reference notes (MANUAL_NPC_NATARS, MANUAL_NPC_NATURE)
* 1 templated Nature-animal blurb (MANUAL_UDESC_ANIMAL_EXP, used via
printf with the animal name + xp value, so the 10 animal pages share it)
* 38 unit descriptions (MANUAL_UDESC_*). Identical descriptions are shared:
settlers (110/120/130) and rams (117/127) reuse one constant each.
- Reuses constants already present upstream and in the building pages branch:
TRIBE1..5, LEVEL, FORWARD, CROP_CONSUMPTION, PREREQUISITES, UPKEEP, DURATION,
RESOURCES, U1..U50.
English render is unchanged: the English constant values are the existing page
text extracted verbatim (whitespace-collapsed). it/zh are intentionally left to
fall back to English via the en.php fallback wired up earlier.
Scope note: this builds on the manual building-pages l10n branch (reuses
CROP_CONSUMPTION). The 17 "new features" pages (typ=11/13) are out of scope and
will be a follow-up PR. RO strings are functional but would benefit from a
native review.
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>
The profile already had a language selector (Templates/Profile/preference.tpl)
that saved the choice into users.lang and $_SESSION['lang'], but the saved
preference was never used to actually load the language: every page loads
include("Lang/".LANG.".php") with the server-wide LANG constant, so changing
the language in the profile had no visible effect.
This wires it up:
- Introduce SERVER_LANG (the server default) and make LANG the EFFECTIVE
display language, resolved from the player's saved preference
($_SESSION['lang']) with a fallback to SERVER_LANG
(install/data/constant_format.tpl).
SECURITY: the value is sanitized to [a-z_] and the target Lang/<x>.php
file must exist, otherwise we fall back to the server default. This
prevents Local File Inclusion via include("Lang/".LANG.".php").
- Seed $_SESSION['lang'] from users.lang on login (GameEngine/Session.php,
PopulateVar), so the chosen language applies right after logging in.
- Keep the SERVER default intact when an admin saves settings: the admin
config regenerators and the "Server Settings"/config displays now use
SERVER_LANG (the server default) instead of the per-user LANG, so an
admin browsing in their own language can't accidentally overwrite the
server default (6 Admin/Mods/edit*.php + editServerSet.tpl + config.tpl).
Note: existing installs must also add SERVER_LANG + the LANG resolution to
their generated GameEngine/config.php (and the Admin/Mods/constant_format.tpl
copy) since config is generated at install time.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The admin panel had a "Create System Message" page (admin.php?p=sysmessage
-> Admin/Templates/sysmessage.tpl) whose form posts to
GameEngine/Admin/Mods/sysmessage.php, but that backend file never existed,
so submitting returned a 404 (Not Found).
Add the handler implementing the prepare -> confirm -> execute flow used by
the template. On execute it displays a global system message to all players
using the existing mechanism (writes Templates/text.tpl from
text_format.tpl and sets users.ok = 1), same as the legacy sysmsg.php.
%TEKST% is escaped for the PHP double-quoted string context to avoid
breakage/injection.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The timezone lists are hardcoded. Add "Europe (Switzerland)" =
Europe/Zurich to:
- Admin/Templates/editServerSet.tpl (admin: edit server settings)
- install/templates/config.tpl (install wizard, index 14)
- install/index.php (install wizard tz index->name mapping, case 14)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The language dropdowns are hardcoded (they don't scan GameEngine/Lang/),
so the existing fr.php never appeared. Add a French option to:
- install/templates/config.tpl (install wizard)
- Admin/Templates/editServerSet.tpl (admin: edit server settings)
- Admin/Templates/config.tpl (admin: server config display)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace GameEngine/Lang/fr.php with a complete, reviewed French
translation:
- Full coverage: all 1439 language keys present (matches en.php), none
missing or extra.
- Valid PHP: all French apostrophes properly escaped, no unterminated
strings.
- Months localized, quest tutorial numbering kept consistent with en.php.
- Fixed gender agreement on EMAIL_TAKEN ("Cet e-mail ... utilisé").
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>