Files
AdamuSw/src/Persistence/Initialization/Updates/AddHeykelSavasiEventUpdateSeason6.cs
Acentech Dev ede52f4176
Some checks failed
.NET Core / build (push) Has been cancelled
feat(tvt): rename the Lorencia event NPC to "TvT Guard"
The NPC (560) that opens the TvT registration stands in Lorencia and was seeded as
"TvT Event Gorevlisi". Renaming the seed only helps fresh databases, so update 106
renames it on existing ones too - that name is what the admin panel lists.

The name players see over its head comes from the client's own table
(Data\Local\<lang>\Npcname(<lang>).txt), not from this designation, and is changed
there separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 02:23:02 +03:00

125 lines
5.1 KiB
C#

// <copyright file="AddHeykelSavasiEventUpdateSeason6.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.Updates;
using System.Runtime.InteropServices;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Events;
using MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Maps;
using MUnique.OpenMU.PlugIns;
/// <summary>
/// Adds the TvT Event team event data to an existing configuration: the imported LoL arena map
/// (server number 92 / client World93) with its terrain, the statue (561) and guard (580) monster
/// definitions, the red/blue base spawn gates, the event NPC (560) placed in Lorencia, and the
/// mini-game definition. The event logic (context, packet handlers, chat commands, buffs) ships in
/// the game-logic assemblies and needs no configuration update.
/// </summary>
[PlugIn]
[Display(Name = PlugInName, Description = PlugInDescription)]
[Guid("F2A7C4D9-3E1B-4A86-9C0D-5B7E2A1F8D42")]
public class AddHeykelSavasiEventUpdateSeason6 : UpdatePlugInBase
{
internal const string PlugInName = "Add TvT Event event (map 92)";
internal const string PlugInDescription = "Adds the TvT Event team-vs-team event: the LoL arena map (server 92 / World93) with terrain, statue+guard monsters, red/blue base spawn gates, the event NPC (560) in Lorencia, and the mini-game definition.";
/// <inheritdoc />
public override UpdateVersion Version => UpdateVersion.AddHeykelSavasiEventSeason6;
/// <inheritdoc />
public override string DataInitializationKey => VersionSeasonSix.DataInitialization.Id;
/// <inheritdoc />
public override string Name => PlugInName;
/// <inheritdoc />
public override string Description => PlugInDescription;
/// <inheritdoc />
public override bool IsMandatory => true;
/// <inheritdoc />
public override DateTime CreatedAt => new(2026, 07, 21, 12, 0, 0, DateTimeKind.Utc);
/// <inheritdoc />
protected override async ValueTask ApplyAsync(IContext context, GameConfiguration gameConfiguration)
{
// Idempotency guard: skip if the TvT Event map (92) already exists.
if (gameConfiguration.Maps.Any(m => m.Number == HeykelSavasiMap.Number))
{
return;
}
// 1. Map (No 92) + terrain (Terrain93.att) + statue (561) / guard (580) monster definitions.
var mapInitializer = new HeykelSavasiMap(context, gameConfiguration);
mapInitializer.Initialize();
mapInitializer.SetSafezoneMap();
var map = gameConfiguration.Maps.First(m => m.Number == HeykelSavasiMap.Number);
// 2. Host the map on every game server configuration (fresh seeds do this automatically,
// but existing databases need it added explicitly).
var serverConfigs = await context.GetAsync<GameServerConfiguration>().ConfigureAwait(false);
foreach (var serverConfig in serverConfigs)
{
if (serverConfig.Maps.All(m => m.Number != HeykelSavasiMap.Number))
{
serverConfig.Maps.Add(map);
}
}
// 3. Red/Blue base spawn gates. The X1/Y1 anchors MUST match HeykelSavasiContext.GetTeamSpawnGate
// (Red = 42,10 top tip of the arena diamond; Blue = 42,92 bottom tip).
var redBase = context.CreateNew<ExitGate>();
map.ExitGates.Add(redBase);
redBase.Map = map;
redBase.X1 = 42;
redBase.Y1 = 10;
redBase.X2 = 42;
redBase.Y2 = 10;
redBase.Direction = Direction.South;
redBase.IsSpawnGate = true;
var blueBase = context.CreateNew<ExitGate>();
map.ExitGates.Add(blueBase);
blueBase.Map = map;
blueBase.X1 = 42;
blueBase.Y1 = 92;
blueBase.X2 = 42;
blueBase.Y2 = 92;
blueBase.Direction = Direction.North;
blueBase.IsSpawnGate = true;
// 4. Event NPC (560) placed in Lorencia.
if (gameConfiguration.Monsters.All(m => m.Number != 560))
{
var npc = context.CreateNew<MonsterDefinition>();
gameConfiguration.Monsters.Add(npc);
npc.Number = 560;
npc.Designation = "TvT Guard";
npc.NpcWindow = NpcWindow.Undefined;
npc.ObjectKind = NpcObjectKind.PassiveNpc;
npc.SetGuid(npc.Number);
var lorencia = gameConfiguration.Maps.First(m => m.Number == Lorencia.Number);
var spawn = context.CreateNew<MonsterSpawnArea>();
lorencia.MonsterSpawns.Add(spawn);
spawn.GameMap = lorencia;
spawn.MonsterDefinition = npc;
spawn.Quantity = 1;
spawn.X1 = 140;
spawn.X2 = 140;
spawn.Y1 = 120;
spawn.Y2 = 120;
spawn.Direction = Direction.SouthEast;
spawn.SpawnTrigger = SpawnTrigger.Automatic;
}
// 5. Mini-game definition (its Entrance references a spawn gate on the map -> after step 3).
new HeykelSavasiInitializer(context, gameConfiguration).Initialize();
}
}