# pvp-events > Implements PvP event systems including TvT, CTF, DeathMatch, LastMan, and Tournament modes for L2J Interlude. Use when: creating new events, modifying event behavior, fixing event bugs, configuring event rewards, or adding event registration handlers - Author: valeriybaranyshyn-pixel - Repository: valeriybaranyshyn-pixel/Tales-of-Aden - Version: 20260202145225 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/valeriybaranyshyn-pixel/Tales-of-Aden - Web: https://mule.run/skillshub/@@valeriybaranyshyn-pixel/Tales-of-Aden~pvp-events:20260202145225 --- --- name: pvp-events description: | Implements PvP event systems including TvT, CTF, DeathMatch, LastMan, and Tournament modes for L2J Interlude. Use when: creating new events, modifying event behavior, fixing event bugs, configuring event rewards, or adding event registration handlers allowed-tools: Read, Edit, Write, Glob, Grep, Bash --- # PvP Events Skill L2J PvP events follow a 3-tier architecture: **Config** (loads `.properties`), **Manager** (schedules lifecycle), and **Event** (state machine + game logic). All events use the same `EventState` enum pattern and cross-validate player registration to prevent multi-event participation. ## Quick Start ### Creating a Basic Event Structure ```java // 1. Config class - loads from properties file public class MyEventConfig { public static boolean MY_EVENT_ENABLED; public static String[] MY_EVENT_INTERVAL; public static void init() { ExProperties events = load("./config/events/MyEvent.properties"); MY_EVENT_ENABLED = events.getProperty("MyEventEnabled", false); MY_EVENT_INTERVAL = events.getProperty("MyEventInterval", "20:00").split(","); } } // 2. Manager class - singleton with scheduling public class MyEventManager { public static MyEventManager getInstance() { return SingletonHolder._instance; } public void scheduleEventStart() { // Parse intervals, schedule via ThreadPool } private static class SingletonHolder { protected static final MyEventManager _instance = new MyEventManager(); } } // 3. Event class - state machine + logic public class MyEvent { private static EventState _state = EventState.INACTIVE; public static boolean startParticipation() { /* spawn NPC */ } public static boolean startFight() { /* teleport, balance teams */ } public static void stopFight() { /* rewards, cleanup */ } } ``` ### Registering Voice Commands ```java public class VoicedMyEvent implements IVoicedCommandHandler { private static final String[] VOICED_COMMANDS = { "myeventjoin", "myeventleave", "myeventinfo" }; @Override public boolean useVoicedCommand(String command, Player player, String target) { if (command.equals("myeventjoin")) { MyEvent.onBypass("my_event_participation", player); } return true; } } ``` ## Key Concepts | Concept | Purpose | Location | |---------|---------|----------| | `EventState` | State machine: INACTIVE → PARTICIPATING → STARTING → STARTED → REWARDING | Each `*Event.java` | | `*Manager` | Singleton lifecycle controller with `ThreadPool` scheduling | `*Manager.java` | | `*Config` | `ExProperties` loader from `.properties` files | `*Config.java` | | `IPManager` | Multi-box protection via IP validation | `event/bossevent/IPManager.java` | | `RewardHolder` | Reward definition (id, min, max, chance) | `event/partyfarm/RewardHolder.java` | ## Common Patterns ### Cross-Event Validation **When:** Player tries to register for an event ```java // In onBypass() - prevent multi-event registration if (TvTEvent.isPlayerParticipant(player.getObjectId())) { player.sendMessage("You already participated in another event!"); return; } if (CTFEvent.isPlayerParticipant(player.getObjectId())) { /* same */ } if (DMEvent.isPlayerParticipant(player.getObjectId())) { /* same */ } ``` ### Team Balancing by Level **When:** Starting team-based events (TvT, CTF) ```java int[] balance = {0, 0}; int priority = 0; while (!allParticipants.isEmpty()) { int highestId = highestLevelPcInstanceOf(allParticipants); Player highest = allParticipants.remove(highestId); _teams[priority].addPlayer(highest); balance[priority] += highest.getLevel(); priority = balance[0] > balance[1] ? 1 : 0; } ``` ## See Also - [patterns](references/patterns.md) - Event architecture, state machine, rewards - [workflows](references/workflows.md) - Adding new events, configuration, testing ## Related Skills - See the **l2j-gameserver** skill for core server architecture - See the **configuration-management** skill for event `.properties` files - See the **database-schema** skill for event participation tracking - See the **npc-scripting** skill for registration NPC dialogs