Commit Graph

91 Commits

Author SHA1 Message Date
Acentech Dev
a76708c899 chore(hs): statue spawn coordinate message in English 2026-07-21 13:27:37 +03:00
Acentech Dev
ae68e15f77 feat(hs): announce statue spawn coordinates as yellow center message to event players 2026-07-21 13:25:02 +03:00
Acentech Dev
d41d46f24f chore(hs): rename event display name 'Heykel Savasi' -> 'TvT Event' (strings only)
Display strings/messages/designations changed everywhere (Name, entrance
messages, NPC designation, HUD title). Code identifiers/namespaces/commands
unchanged. DB rows updated separately.
2026-07-21 13:01:36 +03:00
Acentech Dev
7312b0e20d fix(minigame): announce entrance-opened for sub-minute registration windows
SendOpenedNotificationsAsync only looped per full minute, so a <1min entrance
(e.g. a 30s test window) sent no golden 'event opened' notification. Now sends
one up front when TotalMinutes==0. >=1min windows unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 12:55:00 +03:00
Acentech Dev
e45ad4f8d7 feat(hs): spawn statues+guards at random walkable spots (hunt-the-statue)
Instead of a fixed lane, each statue (and its 4 guards) now spawns at a random
walkable coordinate anywhere on the map; breaking one reveals the next at a new
random spot, so players must search for it. Falls back to the fixed positions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 12:35:17 +03:00
Acentech Dev
fcf2e80570 feat(hs): disable monster transform (EventFormSkin=0); team look via client cape override 2026-07-21 11:16:50 +03:00
Acentech Dev
1e8478fe70 feat(hs): raise statue HP, transform players in-battle, per-player team roster packet, drop wing-unequip
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 10:25:07 +03:00
Acentech Dev
7aae9dff0c feat(hs): disable wings in-event + periodic HUD-state packet/broadcast
- HeykelSavasiContext.IsItemAllowedToEquip disallows wings/capes during
  Playing only (so entry is never rejected for wearing wings); auto-unequips
  any equipped wing/cape into a free inventory slot in OnGameStartAsync.
- New S2C packet HeykelSavasiHudState (C1, code FB, length 11) carrying
  phase, team, counts, statue progress and remaining seconds, plus its view
  plugin/interface, broadcast once per second across registration/prep/
  battle and one-shot on join/statue-break/game-end.
2026-07-21 03:16:29 +03:00
Acentech Dev
5750ab6511 fix(hs): no PvP before battle + clean team assignment on leave
#1: block all player-vs-player damage while State != Playing (registration/
prep), keep same-team friendly-fire off during battle. Prevents pre-battle
kills (which also caused deaths to route to Lorencia instead of a base).
#3: remove a player from their team on OnObjectRemovedFromMapAsync (real
leave to another map), not on same-map death-respawn, so team counts stay
accurate and re-joining works.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 02:18:49 +03:00
Acentech Dev
a174c1a29f fix(hs): robust team-base gate selection by Y-position (not exact coords)
GetTeamSpawnGate matched gates by exact X1/Y1 anchors, which threw
'Sequence contains no matching element' when the DB gate coords drifted a
tile from the code anchors. Now selects the two spawn gates by Y-order
(red=top, blue=bottom) so it works regardless of exact coordinates.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 01:53:58 +03:00
Acentech Dev
583df657fb feat(hs): web-applicable update plugin for the Heykel Savasi event
AddHeykelSavasiEventUpdateSeason6 (version 100): adds map 92 + terrain,
statue/guard monsters, red/blue base gates, event NPC 560 in Lorencia, and
the mini-game definition to an EXISTING config via the admin Updates page
(no DB wipe). Reuses HeykelSavasiMap/HeykelSavasiInitializer; idempotent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 01:22:51 +03:00
Acentech Dev
917831e198 feat(hs): import LoL map (server 92 / World93) + real base & statue coords
- Embed Terrain93.att (server map No 92 -> loads Terrain93); map Number 90->92.
- Real walkable coords from the LoL arena diamond (center lane x=42):
  Red base (42,10) top tip, Blue base (42,92) bottom tip; 7 statues per team along x=42.
- Client World93 + Object93 deployed to PC client separately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 01:18:54 +03:00
Acentech Dev
790d944757 docs(hs): generated packet docs for HeykelSavasi FA packets
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 00:58:44 +03:00
Acentech Dev
e6e93450b7 fix(hs): make statues immune to friendly (same-team) damage
A player could destroy their own team's Heykel Savasi statue: the win-condition
attribution (OnDestructibleDied) trusts geometry alone (attacker = Opponent of
defender), and the old friendly-fire guard only covered Player targets, not
Destructible statues. Block same-team damage at the NPC damage intake instead
so only the enemy team can ever land a hit on a statue.
2026-07-21 00:57:15 +03:00
Acentech Dev
e0fafe7e03 feat(hs): /starths force-start command + /hsteam GM test-join command 2026-07-21 00:44:00 +03:00
Acentech Dev
b674e5a2cb feat(hs): periodic scheduled start plugin + config + state
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 00:38:57 +03:00
Acentech Dev
5f03a011db feat(hs): grant fixed Zen to winning team at game end 2026-07-21 00:34:08 +03:00
Acentech Dev
83cb9b9fe4 feat(hs): team-base respawn + reapply earned buffs on respawn
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 00:25:44 +03:00
Acentech Dev
89aef08bed feat(hs): block friendly-fire within the same team 2026-07-21 00:19:43 +03:00
Acentech Dev
ceacc11446 feat(hs): apply mapped class buffs to team on statue break 2026-07-21 00:15:52 +03:00
Acentech Dev
712773c332 feat(hs): sequential statue spawn + guard mobs + win detection
Adds HeykelSavasiContext runtime logic for Task 4.2: per-team statue
break progress/winner tracking (extracted into a pure, testable
StatueProgressState), OnDestructibleDied wiring against the base
MiniGameContext's existing Destructible->Died auto-subscription, and
SpawnStatueAsync which spawns the next statue (561) + 4 guards (580)
via the map initializer using placeholder line-of-statues coordinates.
OnGameStartAsync now spawns each team's first statue after the warp.
2026-07-21 00:07:00 +03:00
Acentech Dev
32e05e2bc1 feat(hs): define statue (destructible) + guard monster definitions 2026-07-20 23:52:34 +03:00
Acentech Dev
372929a8d1 fix(hs): roll back team reservation if TryEnterAsync throws 2026-07-20 23:48:36 +03:00
Acentech Dev
cd55e726f1 feat(hs): team-select handler + join action with atomic balance reserve and base warp 2026-07-20 23:42:07 +03:00
Acentech Dev
7e954b610f feat(hs): NPC talk plugin opens team panel when registration is open 2026-07-20 23:33:55 +03:00
Acentech Dev
2efe1ef84d feat(hs): view plugin to open team-select panel 2026-07-20 23:28:04 +03:00
Acentech Dev
f5e1f46444 feat(hs): add open-team-panel (S2C) and team-select (C2S) packets 2026-07-20 23:22:33 +03:00
Acentech Dev
cc0b7abb44 feat(hs): add event NPC 560 and place it in Lorencia
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 23:15:52 +03:00
Acentech Dev
5bc5f461e5 feat(hs): warp teams to base on start + cancel if a team is empty
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 23:09:39 +03:00
Acentech Dev
8295c30b71 feat(hs): wire HeykelSavasiContext in GetMiniGameAsync + team gate resolver 2026-07-20 23:04:21 +03:00
Acentech Dev
968eb0c155 feat(hs): HeykelSavasiContext team tracking + balance rule
Adds the HeykelSavasiTeam enum (None/Red/Blue) and the HeykelSavasiContext
skeleton (subclass of MiniGameContext) with team registration
(AssignTeam/GetTeam/PlayersOf/TeamCount) and a join-balance rule
(|Red-Blue| <= 2 after the prospective join), exposed as a pure static
IsJoinAllowed for fast unit testing without constructing the full context.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 22:59:15 +03:00
Acentech Dev
5d0f475472 feat(hs): add HeykelSavasi MiniGameDefinition initializer 2026-07-20 22:44:38 +03:00
Acentech Dev
b90013c4bb feat(hs): add MiniGameType.HeykelSavasi 2026-07-20 22:41:00 +03:00
Acentech Dev
732196f623 feat(hs): add red/blue base exit gates on Heykel Savasi map 2026-07-20 22:38:20 +03:00
Acentech Dev
5a354fb419 feat(hs): add Heykel Savasi event map skeleton (map 90)
Adds HeykelSavasiMap (BaseMapInitializer, Number=90/World91) as an empty
terrain-only skeleton and registers it in GameMapsInitializer. Statue/guard
monster definitions and spawns are added by later Heykel Savasi tasks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 22:31:46 +03:00
Acentech Dev
3d5d40b753 Add Warrior Wings & Cape (12/242-247)
Some checks failed
.NET Core / build (push) Has been cancelled
Six high-tier imported wings, one per class line: Wizard (242, Soul Master),
Magic (243, Duel Master), Elf (244, High Elf), Summoner (245, Dimension Master),
Warrior Cape (246, Lord Emperor + Fist Master) and Knight (247, Blade Master).
Each: base defense + defense-per-level, 3rd Wing Options, damage increase and
fast flight. Applied via update v99 (AddWarriorWingsUpdateSeason6), reusing the
shared "3rd Wing Options" option set to avoid Guid collisions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 23:27:22 +03:00
Acentech Dev
1cadaa08ab fix(items): reuse shared 3rd Wing Options + level tables for Poison wings (avoid Guid collision) 2026-07-19 18:36:38 +03:00
Acentech Dev
3e8cd8fdae feat(items): Poison Wing/Cape as high-tier wings (defense + options + level bonuses)
Switch from the basic CreateWing overload to the full one: base
defense 65/60, defense-per-level, wing options (HP recover / phys
damage / defense), damage increase, fast flight. Level req 100.
2026-07-19 18:14:46 +03:00
Acentech Dev
affa4bd73b feat(items): add Poison Wing (12/240) and Poison Cape (12/241)
Basic wings via the simple CreateWing overload (base defense, class
restriction, CanFly; no options). Poison Wing=Dark Knight, Poison
Cape=Dark Lord+Rage Fighter. Update-plugin v98 + fresh-seed via
Wings.Initialize().
2026-07-19 16:54:33 +03:00
Acentech Dev
fc9ba0e594 docs: design spec for Poison Wing & Poison Cape (wings 12/240, 12/241) 2026-07-19 16:44:35 +03:00
Acentech Dev
d84b29eac3 feat(maps): add Acheron, Debenter, Uruk, Ferea (maps 83-86)
Same pattern as Arkania: terrain resources Terrain84-87.att, map
initializer classes, registration, and update-plugin (v97) that
creates each map + spawn gate + /move warp AND assigns it to the
game server configuration so it is hosted. Also fix the Arkania
update-plugin to assign the game server config (was missing).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 15:47:05 +03:00
Acentech Dev
80ec466ab1 fix(maps): Arkania is map number 82 (client World = number+1 off-by-one)
Client tried to load World84 for map 83; MU client world index is
server map number + 1 (Lorencia 0 -> World1). Arkania client assets
are World83, so the server map number is 82 and the terrain resource
is Terrain83.att (number+1).
2026-07-19 14:08:01 +03:00
Acentech Dev
e3d37467d5 feat(maps): add Arkania DB update-plugin with spawn gate and /move warp 2026-07-19 13:45:37 +03:00
Acentech Dev
7e21fc1fb3 feat(maps): add Arkania map initializer (number 83) and register it 2026-07-19 13:43:26 +03:00
Acentech Dev
4628902f11 feat(maps): add Arkania (map 83) terrain resource Terrain84.att 2026-07-19 13:42:46 +03:00
Acentech Dev
a61890ef6e docs: implementation plan for Arkania map pilot
7 tasks: terrain resource (Terrain84.att, off-by-one), map class +
registration, update-plugin with spawn gate + /move warp, docker
build/verify, deploy + panel verify, client assets, client verify.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 13:31:34 +03:00
Acentech Dev
3b2e26b27c docs: design spec for new maps import (pilot: Arkania/World83)
End-to-end import of one pilot map across server (OpenMU C# map
initializer + Terrain83.att resource + DB update-plugin), PC client
(World83/Object83 assets), and web (no changes; MapEditor renders
seeded terrain, user adds spawns/NPCs). Other 4 maps + mobile are
follow-up from the proven template.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 13:21:40 +03:00
Acentech Dev
1de06d83ab fix(reset): warp the player home instead of moving him silently
Some checks failed
.NET Core / build (push) Has been cancelled
MoveHomeAsync wrote PositionX/PositionY/CurrentMap/Rotation on the character
record directly, which is a partial copy of Player.PlaceAtGateAsync: it placed
the player but skipped removing him from the map and telling the client.

Player.Position is backed by those very fields, so the coordinates jumped on the
server while the client never got a map change. The client then interpolated a
walk to the new spot and the character visibly slid across the map after a reset.

WarpToAsync does the same placement plus the map removal and the map change
notification, and it handles respawning on the same map. It is the path every
other caller uses (duel room, gate NPCs, mini games, castle siege portal).

The existing tests all ran with MoveHome = false, which is why this path was
never covered. The new test pins the notification: it fails on the old code
because MapChangeAsync is never invoked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 00:26:04 +03:00
Acentech Dev
2927be1ba9 chore(docs): regenerate QuestProgressExtended packet doc as C2
Some checks failed
.NET Core / build (push) Has been cancelled
The packet definition declares C2HeaderWithSubCode, but the committed
doc was generated from an older C1 header and never refreshed. This is
the doc generator's output for the current XML, so the tree stays clean
after a build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:04:13 +03:00
Acentech Dev
16752f3649 chore(deploy): default RESOLVE_IP to the emulator host alias
Without RESOLVE_IP the ConnectServer advertises the public IP, which the
emulator cannot reach, so server select hangs. Default to 10.0.2.2 and
allow an override for real devices on the LAN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 22:04:13 +03:00