7.5 KiB
CS P3 — Kuşatma Savaşı — Uygulama Planı
For agentic workers: REQUIRED SUB-SKILL: superpowers:subagent-driven-development or superpowers:executing-plans. Steps use checkbox (
- [ ]) tracking.
Goal: Castle Siege'i oynanabilir yapmak. İlk increment: Siege fazı başlayınca kayıtlı guild üyelerini CS haritasına (Valley of Loren) al, orada PvP aç, bir Taht ele geçirme noktası koy; kuşatma bitince tahtı tutan guild kazanır ve kale sahibi olur. Kapılar/kristaller/tam S6 protokolü sonraki increment'ler.
Architecture: P1 state machine'in Siege fazına giriş/çıkışına kanca takılır (CastleSiegeContext faz-değişim event'i zaten var: PhaseChanged). Siege başlayınca CastleSiegeEventPlugIn (server-side, GameContext erişimli) kayıtlı oyuncuları warp'lar + PvP açar; Taht bir NPC (talk → guild'i "occupier" yapar); Settlement'ta occupier = kazanan → context.SetOwner. Reuse: player.WarpToAsync(ExitGate), Map.Definition.BattleZone (PvP), IPlayerTalkToNpcPlugIn (Taht), P1 CastleSiegeContext.
Tech Stack: .NET 10, OpenMU GameLogic/PlugIns, NUnit.
Global Constraints
- Depo:
d:/OpenMU/MU Client_Mobile 1.04d - Season 6E3/AdamuSw(bash tırnak içinde). - Additive-first; core dokunuşu
// ADAMU-CUSTOM. - Lokal derleme
-p:ci=true. Commit yazarıAcentech Dev <acentech_dev@affinitybox.com>. - CS map = Valley of Loren (WorldIndex 30) — implementation'da
Persistence/Initialization'dan tam numarayı + entrance gate'i doğrula. - Zaman/rastgele state machine mantığında enjekte (P1 deseni).
Investigation notları (implementation başında doğrula)
- Warp:
player.WarpToAsync(ExitGate gate)(Player.cs:1088). CS map entrance gate'i gerekir — Initialization'da Valley of Loren spawn/exit gate'ini bul veya oluştur. - PvP: kill izni
GameContext.PvpEnabled || Map.Definition.BattleZone != null || CurrentMiniGame.AllowPlayerKilling(Player.cs:725). CS map'e Siege sırasında PvP açmak için: ya map Definition'aBattleZoneekle, ya da CS'ye özel birAllowPlayerKillingcontext (MiniGame benzeri). Karar (impl): BattleZone en temiz — Valley of Loren Definition'a BattleZone tanımı (Initialization). - Taht NPC: yeni bir NPC number (S6 CS'de "Crown/Throne switch").
IPlayerTalkToNpcPlugInile ele geçirme (remote-NPC/Guardsman deseni). - CastleSiegeContext'e occupier alanı + kazanan mantığı eklenir (P1'de OwnerGuildName string; occupier de string guild adı).
Task 1: State machine — occupier + settlement kazananı
Files:
- Modify:
src/GameLogic/CastleSiege/CastleSiegeContext.cs - Test:
tests/MUnique.OpenMU.Tests/CastleSiege/CastleSiegeContextTest.cs
Interfaces:
-
Produces:
CastleSiegeContext.CaptureThrone(string guildName)(sadece Siege fazında occupier'ı set eder),OccupierGuildName(get), Settlement'ta occupier varsaOwnerGuildName = occupier. -
Step 1: Test yaz — Siege fazında
CaptureThrone("A")→OccupierGuildName=="A"; Settlement tick sonrasıOwnerGuildName=="A". Ownership fazında CaptureThrone no-op.
[Test]
public async Task ThroneCaptureDuringSiegeBecomesOwnerOnSettlementAsync()
{
var ctx = new CastleSiegeContext(Config());
await ctx.ForceStartRegistrationAsync(T0);
await ctx.ForcePhaseAsync(CastleSiegePhase.Siege, T0);
ctx.CaptureThrone("Attackers");
Assert.That(ctx.OccupierGuildName, Is.EqualTo("Attackers"));
await ctx.TickAsync(T0.AddMinutes(20)); // Siege -> Settlement
await ctx.TickAsync(T0.AddMinutes(20)); // Settlement -> Ownership (owner atanir)
Assert.That(ctx.OwnerGuildName, Is.EqualTo("Attackers"));
}
- Step 2: Çalıştır → fail (CaptureThrone/OccupierGuildName yok).
- Step 3: Implement —
CastleSiegeContext'e:private string? _occupier;+public string? OccupierGuildName => this._occupier;public void CaptureThrone(string g){ if(this.Phase==CastleSiegePhase.Siege) this._occupier = g; }ForceStartRegistrationAsync/ResetAsync'te_occupier=null.- Settlement→Ownership geçişinde (TickAsync Settlement case):
if(this._occupier is {} occ){ this.SetOwner(occ); } this._occupier=null;(TransitionAsync'ten önce).
- Step 4: Test geçsin. Step 5: Commit.
Task 2: Siege başlarken warp + PvP; bitince güvenli bölgeye al
Files:
- Modify:
src/GameLogic/PlugIns/PeriodicTasks/CastleSiegeEventPlugIn.cs - (Belki) Create:
src/GameLogic/CastleSiege/CastleSiegeMapController.cs(warp/PvP yardımcıları)
Interfaces:
-
Consumes:
CastleSiegeContext.PhaseChanged(P1),player.WarpToAsync, CS map (Valley of Loren). -
Produces: Siege fazına girince kayıtlı guild üyeleri CS map'e warp; Ownership'e dönünce map'ten güvenli bölgeye.
-
Step 1:
CastleSiegeEventPlugIn.ExecuteTaskAsynciçinde faz değişimini yakala (context.Phase önceki-değerle karşılaştır ya daPhaseChangedevent'ine abone ol). Siege'e GİRİŞTE:gameContext'teki tüm oyunculardanGuildStatus.GuildId'si kayıtlı guild'lerden biri olanları CS map entrance gate'ineWarpToAsync. -
Step 2: PvP: CS map Definition'a
BattleZone(Initialization'da) — Siege boyunca kill serbest. (Alternatif: CS context'iAllowPlayerKilling=truemini-game gibi kaydet.) Impl'de en az riskli yolu seç, doğrula. -
Step 3: Siege bitince (Ownership'e dönüş): CS map'teki oyuncuları
WarpToSafezoneAsync. -
Step 4: Derle + smoke. Step 5: Commit.
Not: kayıtlı-guild üye eşleştirmesi için context'te guild ADI tutuyoruz; warp'ta oyuncunun guild adını
GuildServer.GetGuildAsync(guildId).Nameile çözüp kayıtlı listeyle karşılaştır (Guardsman handler'daki desen).
Task 3: Taht NPC — ele geçirme
Files:
- Create:
src/GameLogic/CastleSiege/CastleSiegeThroneTalkPlugIn.cs - (Initialization) Taht NPC'sini CS map'e yerleştir (number ata).
Interfaces:
-
Consumes:
IPlayerTalkToNpcPlugIn,CastleSiegeEventPlugIn.TryGetContext,context.CaptureThrone. -
Step 1:
CastleSiegeThroneTalkPlugIn : IPlayerTalkToNpcPlugIn(Guardsman deseni). Taht NPC number kontrolü →eventArgs.HasBeenHandled=true→ Siege fazındaysa + oyuncu kayıtlı guild master/üyesiyse →context.CaptureThrone(guildName)+ "Your guild captured the throne!" mesajı. -
Step 2: Taht NPC'sini CS map'e ekle (Initialization'da MonsterSpawn; number ata, örn. 277 "Castle Gate switch" S6 referansına bak).
-
Step 3: Derle. Step 4: Commit.
Task 4: Uçtan uca test + server image + admin akışı
- Step 1: Tüm CS testleri geçsin (
--filter CastleSiege). - Step 2: Image rebuild + container restart.
- Step 3 (manuel/emülatör): GM ile
/csstart→ Guardsman'de kayıt →/csphase Siege→ oyuncu CS map'e warp olmalı, PvP açık, Taht'a konuş → "captured throne" →/csphase Settlement→/csstatusowner = guild. (Not: Taht ele geçirme akışı client↔server canlı doğrulanır.) - Step 4: Gitea push.
Sonraki increment'ler (P3 devamı)
- Kapılar (Destructible, HP, kırılınca terrain açılır — MiniGame terrain-change deseni).
- Kristaller / Guardian Statue'lar (Destructible; taht'a erişim için yıkılmalı).
- Kontenjan/giriş kısıtı (Siege'de sadece kayıtlı guild üyeleri map'e girebilir).
- Tam S6 CS protokolü (server→client CS state/time paketleri → client'ın native kuşatma UI'ı + geri sayım çalışır; client UI'ı hazır).
- Contention (tek ele geçirme yerine tutma süresi/skor ile kazanan).