Biomes C: terrain move-cost (marsh slow) for all movers #138
Labels
No labels
alpha:wave-0
alpha:wave-1
alpha:wave-2
alpha:wave-3
area:assets
area:combat
area:ecology
area:infra
area:render
area:scripting
area:ui
area:world
enhancement
epic
migration
post-alpha
roadmap
tech-debt
type:bug
type:chore
type:design
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
marco/IsoMmo#138
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Depends on #136. Adds the marsh slow as a server-authoritative per-terrain move-cost, applied to every grounded mover. Design:
docs/game-design/systems/biomes.md(parent #135).Scope
Shared:TileMap.MoveCostTicks(from, into)=base * max(cost(from), cost(into))(direction-independent; no free exit step).MovementSystem: scale the player move cooldown by the transition cost (today's gate:currentTick - LastMoveTick < moveCooldownTicks). Logic stays inMovementSystem(World-owned component), notWorld.cs.CreatureSystem: scale the creature chase/wander cadence by the same helper (today a fixed cadence) -> marsh chases are symmetric.IgnoresTerrainMoveCostmover capability (flying/floating), default false;Teleport//tpstays cost-exempt.moveCostlocally for movement feel (authority stays server-side).SystemNoticeon first marsh step -- newSystemMessageId+SystemMessageCatalogtemplate (no loose strings).Definition of Done (delta)
⏭️ Heads-up @andrea: #143 (full tiledata data-file) is being implemented now as the foundation for the #113 map editor (owner's call). It absorbs
TerrainInfo+BiomeVisuals+StaticCatalog+ the terrain legend into onecontent/tiledata.txtand replaces theTerrainTypeenum with string ids. This touches the #142 foundation this issue builds on — when you pick it up you'll rebase onto the new model (terrain = string id, flags/art/tint read fromTileData). NoProtocolVersionchange. Design + invariants recorded on #143.⏭️ Post-#143 note: the terrain foundation changed under this.
TerrainType/TerrainInfoare gone — terrain is now a string id defined incontent/tiledata.txt, read as aTerrainDefviaTileData. So the marsh move-cost becomes a column on theterrainrow (aTerrainDeffield), not aTerrainInfochange. The server-sideMoveCostTicks/MovementSystem/CreatureSystemscaling still applies; just source the per-terrain cost fromTileData. NoProtocolVersionchange (terrain isn't wire).Technical design review — agreed (go-with-changes)
Ran
critical-design-reviewbefore implementation (branchfeat/biomes-art).Design:
TerrainDefgains aMoveCostfloat (default 1); a trailing optional column incontent/tiledata.txt(marsh1.6).TileMap.MoveCostTicks(baseTicks, from, into) = ceil(baseTicks * max(cost(from), cost(into)))— direction-independent, so any step touching marsh isslow (no free exit step).
MovementSystem.ApplyPendingandCreatureSystem.Stepreplace the fixedcooldown/cadence with the scaled one. All server-side.
Decisions: (1) add the
IgnoresTerrainMoveCostexemption hook now (on the creature, defaultfalse; players always affected). (2) #138 = server core (players + creatures + tests) + verify/fix
rubber-band; the marsh ripple VFX + one-time
SystemNoticeare a separate follow-up.Invariants Check (vs CLAUDE.md ## Design checklist)
MovementSystem.ApplyPending(authoritative tick); client sends onlyMoveRequest; early move rejected./tpstays cost-exempt.PlayerMoved/MobileState→ no bump.SystemMessageId).TileMap.MoveCostTicksis a pure read of immutable terrain; no new lock/state.MovementSystem/CreatureSystem+TileMap; World keeps delegating.TileMap.MoveCostTicks(Shared).Gameplay/+TileMap; networking untouched.LastMoveTick.TerrainDefdata field;MoveCostTicksis amax()formula, no switch.moveCooldownTicksis a boundGameOptions; multipliers live in tiledata, noIConfigurationread.TileDatamovement flags; diverges with a simplemax(from,into)cooldown scale (no full stamina/movement system).No ✗, no HARD GATE tripped.
Definition of Done (delta)
IgnoresTerrainMoveCostcrosses marsh at normal speed (unit test; no such creature ships yet).#138 — Done (server move-cost + client feedback)
Landed on
feat/biomes-art(PR #155), CI green. Whole solution builds 0 warnings; 507 tests green.TileMap.MoveCostTicks(base, from, into) = ceil(base * max(cost(from), cost(into)))(symmetric — no free exit step).MovementSystemscales the player cooldown;CreatureSystemscales the creature cadence;BaseCreature.IgnoresTerrainMoveCost(default false) exempts flying kinds; teleport stays exempt. MarshmoveCost = 1.6via a new optional column incontent/tiledata.txt.PlayerMoved+ the sharedTileMap(no wire event).MarshFeedback.Decide(destMoveCost, isSelf, hintShown)(pure, Client.Core) → per-step ground ripple (RippleEffect, authoredeffect/marsh_ripple) for any mover, plus a one-timeSystemMessageId.MarshSlowsYoufor the local player.ProtocolVersion11→12 (new protocol enum value).Note / divergence from the scope checklist: the "mirror move-cost client-side for feel" item was dropped as unnecessary — the client does not predict movement (it renders authoritative positions from
PlayerMoved), so there is no rubber-band to correct. Confirmed by inspection ofGameInputController/ServerMessageDispatcher.Invariants Check (client-feedback delta — server part reviewed when the move-cost landed)
PlayerMoved; the slow itself stays server-enforced.ProtocolVersion11→12 for the newSystemMessageId.MarshSlowsYou(protocol enum).SystemMessageId+ catalog template; no loose literal.World.World.csHARD GATE N/A — untouched.ScreenHARD GATE ✓ logic inServerMessageDispatcher(component) + a pure Client.Core helper; nothing added toGameScreen; latch onClientWorld.MarshFeedback(Client.Core, unit-tested); only the draw (RippleEffect/Journal) lives in theClientproject.boolonClientWorld(session state), not a side-collection mirroring entity state.MoveCost > 1flag, not a terrain-type check — every future slow terrain inherits the feedback.RippleEffectconstants local; tint isColor.White).PlayerMoved(already AoI-filtered, absolute positions).effect/marsh_ripple; missing art no-ops (no PlaceholderArt shape); notice needs no art.effect/marsh_rippleis descriptive<material>_<kind>.content/tiledata.txtheader + CLAUDE.md tiledata line updated with themoveCostcolumn; this DoD confirmation.Definition of Done
MarshSlowTests.MarshSlowCreatureTests.FastClientCannotBeatTheMarshCooldown.MarshFeedbackTests+ screenshots on PR #155.Completata: move-cost per-terrain server-authoritative —
TileMap.MoveCostTicks(base, from, into)conmax(cost(from),cost(into)), applicato a player e creature (testMarshSlowTests+MarshSlowCreatureTests), feedback clientmarsh_ripple+ hint one-time (MarshFeedback). La parità creature/player è stata finalizzata da #182 (5313140). Chiudo — completata.