feat(tvt): 4 arena bosses at 3 statues, robust guard/boss spawn, reliable GM restart, English strings
- Bosses: 306/309/357/459 spawn once at (55,42)/(32,42)/(31,59)/(56,58) after 3 total statues broken. - Guards/bosses spawn in a walkable BOX (retry) instead of a fixed point; several statue-guard offsets landed on non-walkable terrain and silently failed, leaving statues unbreakable. - Guard-alive gate uses the ACTUAL spawned count so a statue can always reach 0 -> breakable. - HeykelSavasiStartPlugIn.OnStartedAsync force-disposes a lingering finished context so GM /starths restarts the event immediately (no server restart). - Statue-break + join messages translated to English.
This commit is contained in:
@@ -30,4 +30,31 @@ public sealed class HeykelSavasiStartPlugIn : MiniGameStartBasePlugIn<HeykelSava
|
||||
{
|
||||
return new HeykelSavasiGameServerState(gameContext);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async ValueTask OnStartedAsync(HeykelSavasiGameServerState state)
|
||||
{
|
||||
// A GM /starths must work even immediately after a previous run ended. When the event finishes, its
|
||||
// MiniGameContext lingers in a terminal state (Ended/Closed) for its exit ceremony (~60s) BEFORE it
|
||||
// disposes; during that window GetMiniGameAsync (which only skips disposed/disposing contexts) would
|
||||
// return that stale, already-finished context instead of opening a fresh event - so nothing starts
|
||||
// until a server restart clears it. Force-dispose any lingering non-running context here first, so the
|
||||
// base implementation then creates a brand-new event. A genuinely running game (Open/Playing) is left
|
||||
// untouched (the base call just reuses it - no double start).
|
||||
var definitions = state.Context.Configuration.MiniGameDefinitions
|
||||
.Where(d => d.Type == this.Key && d.MapCreationPolicy == MiniGameMapCreationPolicy.Shared)
|
||||
.ToList();
|
||||
|
||||
foreach (var definition in definitions)
|
||||
{
|
||||
var existing = await state.Context.GetMiniGameAsync(definition, null!).ConfigureAwait(false);
|
||||
if (existing is { IsDisposed: false, IsDisposing: false }
|
||||
&& existing.State is not MiniGameState.Open and not MiniGameState.Playing)
|
||||
{
|
||||
await existing.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
await base.OnStartedAsync(state).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user