init
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
# Discord Matching Relay
|
||||
|
||||
A TERA Proxy Server mod that relays instance matching (dungeon and battleground) queue activity to a Discord channel via a webhook. It keeps a single Discord message updated in real time as players join or leave the matching queue.
|
||||
|
||||
## Features
|
||||
|
||||
- **Real-time updates** — Automatically posts to Discord when a player adds or removes themselves from the matching queue.
|
||||
- **Dungeon & Battleground support** — Displays separate sections for instance and battleground queues, including player counts and role composition (Tank / DPS / Healer).
|
||||
- **Player name visibility** — Optionally shows or hides player names in the Discord embed (controlled via config).
|
||||
- **Single-message editing** — Uses Discord's edit endpoint to keep a single message up to date, avoiding spam.
|
||||
|
||||
## Required Data Files
|
||||
|
||||
The mod reads server-side XML data dumps placed under the `data/` directory. These files are included with the mod and map numeric IDs to human-readable names and role configurations:
|
||||
|
||||
| File / Directory | Description |
|
||||
|---|---|
|
||||
| `data/DungeonMatching.xml` | Dungeon matching configuration containing class position definitions (role assignments per class). |
|
||||
| `data/MatchingRoleTemplate.xml` | Role templates defining the required number of Tanks, DPS, and Healers per matching group (e.g., 5-player dungeons, battlegrounds, etc.). |
|
||||
| `data/BattleFieldData.xml` | Battleground data including matching rules, and team sizes. |
|
||||
| `data/StrSheet_Dungeon/` | String table XML files mapping dungeon IDs to their display names (e.g., `StrSheet_Dungeon-00000.xml`). |
|
||||
| `data/StrSheet_BattleField/` | String table XML files mapping battleground string IDs to their display names (e.g., `StrSheet_BattleField-00000.xml`). |
|
||||
|
||||
> **Note:** These XML files are extracted from the game client's data sheets (`StrSheet_Dungeon` and `StrSheet_BattleField`) and server's data sheets (`DungeonMatching.xml`, `BattleFieldData.xml` and `MatchingRoleTemplate.xml`) and must be kept up to date with the server version for correct role and name resolution.
|
||||
|
||||
## Configuration
|
||||
|
||||
All configuration is in `module.config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"enabled": true,
|
||||
"webhook": "https://discord.com/api/webhooks/...",
|
||||
"showPlayerNames": false
|
||||
}
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `enabled` | boolean | `true` | Set to `false` to disable the mod without removing it. |
|
||||
| `webhook` | string | `""` | Discord webhook URL. The mod will create and continuously edit a single message in the channel this webhook belongs to. |
|
||||
| `showPlayerNames` | boolean | `false` | When `true`, player names and their selected roles are displayed in the Discord message. |
|
||||
|
||||
## Requirements
|
||||
|
||||
- [TERA Proxy](https://github.com/justkeepquiet/tera-proxy-server) or compatible proxy
|
||||
- A Discord webhook URL
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,532 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<DungeonMatching>
|
||||
<!-- Position definition for each class 1 is the damage dealer, 0 is the tank, 2 is the healer, the basic selection position, and up to 3 selectable positions! -->
|
||||
<ClassPosition>
|
||||
<Class name="Warrior" defaultPosition="1" secondPosition="0" thirdPosition="1"/>
|
||||
<Class name="Lancer" defaultPosition="0" secondPosition="0" thirdPosition="0"/>
|
||||
<Class name="Slayer" defaultPosition="1" secondPosition="1" thirdPosition="1"/>
|
||||
<Class name="Berserker" defaultPosition="1" secondPosition="0" thirdPosition="1" secondPositionLevel="65"/>
|
||||
<Class name="Sorcerer" defaultPosition="1" secondPosition="1" thirdPosition="1"/>
|
||||
<Class name="Archer" defaultPosition="1" secondPosition="1" thirdPosition="1"/>
|
||||
<Class name="Priest" defaultPosition="2" secondPosition="2" thirdPosition="2"/>
|
||||
<Class name="Elementalist" defaultPosition="2" secondPosition="2" thirdPosition="2"/>
|
||||
<Class name="Soulless" defaultPosition="1" secondPosition="1" thirdPosition="1" />
|
||||
<Class name="Engineer" defaultPosition="1" secondPosition="1" thirdPosition="1"/>
|
||||
<Class name="Fighter" defaultPosition="0" secondPosition="1" thirdPosition="0" secondPositionLevel="69"/>
|
||||
<Class name="Assassin" defaultPosition="1" secondPosition="1" thirdPosition="1"/>
|
||||
<Class name="Glaiver" defaultPosition="1" secondPosition="1" thirdPosition="1"/>
|
||||
</ClassPosition>
|
||||
|
||||
<!-- Defining the contents of the mail that sends the Valkyon summoning order, rewards received by characters who respond to additional recruitment, dungeon clear bonus rewards, and rewards-->
|
||||
<Compensation>
|
||||
<PositionCall addItemTemplateId="" addItemAmount=""/>
|
||||
<PositionCallMail sender="@DungeonMatchingMail:10" title="@DungeonMatchingMail:11" body="@DungeonMatchingMail:12"/>
|
||||
<AddEntry addItemTemplateId="" addItemAmount=""/>
|
||||
<AddEntryMail sender="@DungeonMatchingMail:20" title="@DungeonMatchingMail:21" body="@DungeonMatchingMail:22"/>
|
||||
<!-- In the case of a dungeon clear reward, an item to be displayed on the UI is designated. In reality, the specified item is paid for each Dungeon. !-->
|
||||
<DungeonClear addItemTemplateId="" addItemAmount=""/>
|
||||
<DungeonClearMail sender="@DungeonMatchingMail:30" title="@DungeonMatchingMail:31" body="@DungeonMatchingMail:32"/>
|
||||
<!-- Blast from the Past -->
|
||||
<SupportMatchingClear addItemTemplateId="96474" addItemAmount="1"/>
|
||||
<SupportMatchingClearMail sender="@DungeonMatchingMail:30" title="@DungeonMatchingMail:31" body="@DungeonMatchingMail:32"/>
|
||||
</Compensation>
|
||||
|
||||
<!-- Added node for matching status notification function (I removed the Icon setting property because it is set to output the icon specified in the UI according to the value sent by the server) !-->
|
||||
<MatchingTimeDisplay standardTime="600" refreshTime="60" checkTime1="20" checkTime2="180" />
|
||||
|
||||
<!-- Added a node to notify the current matching status information (I removed the Icon setting property because it is set to output the icon specified in the UI according to the value sent by the server) !-->
|
||||
<MatchingStateDisplay refreshTime="10" checkNum1Min="0" checkNum1Max="1" checkNum2Min="2" checkNum2Max="6" checkNum3Min="7" checkNum3Max="14" />
|
||||
|
||||
<!-- Blast from the Past -->
|
||||
<PartyMatchBonus>
|
||||
<Bonus countOfRegistration="1" classGroup="defence" abnormalityId="4800"/>
|
||||
<Bonus countOfRegistration="1" classGroup="attack" abnormalityId="4801"/>
|
||||
<Bonus countOfRegistration="1" classGroup="heal" abnormalityId="4802"/>
|
||||
<Bonus countOfRegistration="2" classGroup="defence" abnormalityId="4800"/>
|
||||
<Bonus countOfRegistration="2" classGroup="attack" abnormalityId="4801"/>
|
||||
<Bonus countOfRegistration="2" classGroup="heal" abnormalityId="4802"/>
|
||||
<Bonus countOfRegistration="3" classGroup="defence" abnormalityId="4810"/>
|
||||
<Bonus countOfRegistration="3" classGroup="attack" abnormalityId="4811"/>
|
||||
<Bonus countOfRegistration="3" classGroup="heal" abnormalityId="4812"/>
|
||||
<Bonus countOfRegistration="4" classGroup="defence" abnormalityId="4820"/>
|
||||
<Bonus countOfRegistration="4" classGroup="attack" abnormalityId="4821"/>
|
||||
<Bonus countOfRegistration="4" classGroup="heal" abnormalityId="4822"/>
|
||||
</PartyMatchBonus>
|
||||
|
||||
<Penalty withdrawalAbnormalitySec="180" withdrawalAbnormalityId="999994"/>
|
||||
|
||||
<!-- Blast from the Past (WorldData@SupportMatching was judged to be inappropriate to have in WorldData, so the data was moved)-->
|
||||
<SupportMatchingEnterLimit enterLimitCount="100" enterLimitCountForAccountTrait="100" />
|
||||
|
||||
<!-- Blast from the Past -->
|
||||
<SupportMatching id="9999" dungeonMinLevel="60" dungeonMaxLevel="70" increaseSupportUserTime="60" maxSupportUser="2">
|
||||
<MatchingDungeon id="9087" name="Bastion of Lok"/>
|
||||
<MatchingDungeon id="9088" name="Sinestral Manor"/>
|
||||
<MatchingDungeon id="9089" name="Cultists' Refuge"/>
|
||||
<MatchingDungeon id="9071" name="Necromancer Tomb"/>
|
||||
<MatchingDungeon id="9072" name="Golden Labyrinth"/>
|
||||
<MatchingDungeon id="9093" name="Akasha's Hideout"/> <!-- Removed from Dungeon Matching -->
|
||||
<MatchingDungeon id="9094" name="Saleron's Sky Garden"/>
|
||||
<MatchingDungeon id="9076" name="Labyrinth of Terror"/>
|
||||
<MatchingDungeon id="9073" name="Ebon Tower"/>
|
||||
</SupportMatching>
|
||||
|
||||
<!-- Dungeon ID, dungeon matching min-max level, minimum equipment level, required items (maximum 3 types), completion conditions (maximum 3 types can be specified)!-->
|
||||
<!-- Item level is not only bet when the dungeon difficulty is high, but must be cast in all dungeons. In dungeons with low difficulty, you can hang it down a little more comfortably. -->
|
||||
<!-- Current reward items are doubled (events and tokens are doubled) !-->
|
||||
<!-- If hide="true" is used, the corresponding dungeon is not visible in the dungeon matching UI (dungeon matching cannot be used). In the dungeon stats information window of the character window, hide="true" dungeon stats are also displayed. -->
|
||||
|
||||
<!-- The matchingRoleId="23" in the Blast from the Past System is a rule implemented so that dungeon matching is possible without a tank. -->
|
||||
<!-- 20~64 Party Dungeon -->
|
||||
<Dungeon id="9087" name="Bastion of Lok" dungeonLevel="20" dungeonMinLevel="20" dungeonMaxLevel="25" minItemLevel="51" matchingRoleId="32">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="408" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9088" name="Sinestral Manor" dungeonLevel="26" dungeonMinLevel="26" dungeonMaxLevel="31" minItemLevel="66" matchingRoleId="32">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="408" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9979" name="Saravash's Ascent" dungeonLevel="32" dungeonMinLevel="32" dungeonMaxLevel="36" minItemLevel="77" matchingRoleId="32">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="408" itemAmount="1"/>
|
||||
<ClearCondition huntingZoneId="979" templateId="47954" amount="1" killCount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9089" name="Cultists' Refuge" dungeonLevel="35" dungeonMinLevel="35" dungeonMaxLevel="42" minItemLevel="96" matchingRoleId="32">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="409" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9071" name="Necromancer Tomb" dungeonLevel="41" dungeonMinLevel="41" dungeonMaxLevel="47" minItemLevel="118" matchingRoleId="32">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="409" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9072" name="Golden Labyrinth" dungeonLevel="48" dungeonMinLevel="48" dungeonMaxLevel="53" minItemLevel="146" matchingRoleId="32">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="410" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9093" name="Akasha's Hideout" dungeonLevel="48" dungeonMinLevel="48" dungeonMaxLevel="54" minItemLevel="146" matchingRoleId="23">
|
||||
<NeedItem id="103"/>
|
||||
<DungeonClearCompensation itemTemplateId="410" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9094" name="Saleron's Sky Garden" dungeonLevel="53" dungeonMinLevel="53" dungeonMaxLevel="57" minItemLevel="166" matchingRoleId="32">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="410" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9076" name="Labyrinth of Terror" dungeonLevel="56" dungeonMinLevel="56" dungeonMaxLevel="58" minItemLevel="200" matchingRoleId="32">
|
||||
<NeedItem id="5126"/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9073" name="Ebon Tower" dungeonLevel="58" dungeonMinLevel="58" dungeonMaxLevel="64" minItemLevel="200" matchingRoleId="32">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9075" name="Kelsaik's Nest" dungeonLevel="58" dungeonMinLevel="58" dungeonMaxLevel="64" minItemLevel="200" matchingRoleId="23">
|
||||
<NeedItem id="5123"/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9025" name="Balder's Temple" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="242" matchingRoleId="23">
|
||||
<NeedItem id="45323"/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="2"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9026" name="Argon Corpus" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="242" matchingRoleId="23">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9727" name="Manaya's Core" dungeonLevel="64" dungeonMinLevel="64" dungeonMaxLevel="70" minItemLevel="309" matchingRoleId="23">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<!--Solo dungeons -->
|
||||
<!--Dungeon id="9126" name="Pit of Petrax" dungeonLevel="99" dungeonMinLevel="99" dungeonMaxLevel="99" minItemLevel="999" matchingRoleId="1000" >
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon-->
|
||||
<!--Dungeon id="9713" name="Ghillieglade" dungeonLevel="99" dungeonMinLevel="99" dungeonMaxLevel="99" minItemLevel="999" matchingRoleId="1000" >
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon-->
|
||||
<!--Dungeon id="9714" name="Velik's Sanctuary" dungeonLevel="99" dungeonMinLevel="99" dungeonMaxLevel="99" minItemLevel="999" matchingRoleId="999" >
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon-->
|
||||
<!-- 65~70 Party Dungeon Patch 92.04 -->
|
||||
<!--Dungeon id="9047" name="Harvest Festival Hall" dungeonLevel="10" dungeonMinLevel="10" dungeonMaxLevel="70" minItemLevel="0" matchingRoleId="32">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="2"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon-->
|
||||
<Dungeon id="9809" name="Macellarius Catacombs" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="448" matchingRoleId="11" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9053" name="Kezzel's Gorge (5-Person)" dungeonLevel="68" dungeonMinLevel="68" dungeonMaxLevel="70" minItemLevel="452" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9781" name="Velik's Sanctuary" dungeonLevel="68" dungeonMinLevel="68" dungeonMaxLevel="70" minItemLevel="453" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9780" name="Velik's Hold (5-Person)" dungeonLevel="68" dungeonMinLevel="68" dungeonMaxLevel="70" minItemLevel="453" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9739" name="Red Refuge" dungeonLevel="68" dungeonMinLevel="68" dungeonMaxLevel="70" minItemLevel="457" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9735" name="RK-9 Kennel" dungeonLevel="68" dungeonMinLevel="68" dungeonMaxLevel="70" minItemLevel="457" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9982" name="Grotto of Lost Souls (Hard)" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="463" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9920" name="Antaroth's Abyss (Hard)" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="463" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="3201" name="Gossamer Vault (Hard)" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="463" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="3023" name="Akalath Quarantine" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="463" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9044" name="Bahaar's Sanctum" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="473" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="3027" name="Forbidden Arena [Hagufna]" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="473" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="3026" name="Corrupted Skynest" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="473" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="3126" name="Corrupted Skynest (Hard) Entrance" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="484" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<!-- 60~70 Legacy Dungeons -->
|
||||
<Dungeon id="9066" name="Demon's Wheel" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="446" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9777" name="Channelworks (3-Person)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="412" matchingRoleId="11">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9766" name="Shattered Fleet" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="412" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9643" name="Wonderholme (10-Person) Lv.65" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="409" matchingRoleId="26">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9050" name="Rift's Edge (Hard)" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="450" matchingRoleId="15">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9750" name="Rift's Edge" dungeonLevel="68" dungeonMinLevel="68" dungeonMaxLevel="70" minItemLevel="452" matchingRoleId="13">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9810" name="Lakan's Prison" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="159" matchingRoleId="1">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<!--Dungeon id="9511" name="The Abscess (7-Person)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="412" matchingRoleId="28">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon-->
|
||||
<Dungeon id="9611" name="The Abscess (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="409" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9808" name="Sabex Armory" dungeonLevel="61" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="302" matchingRoleId="23" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9055" name="Ravenous Gorge (3-Person)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="412" matchingRoleId="11" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9054" name="Bathysmal Rise (Hard)" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="423" matchingRoleId="17" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9916" name="Sky Cruiser Endeavor (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="417" matchingRoleId="17" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9029" name="Vault of Kaprima" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="410" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9057" name="Akeron's Inferno (Hard)" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="423" matchingRoleId="26">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9056" name="Timescape (Hard)" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="397" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9060" name="Kalivan's Dreadnaught (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="423" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9759" name="Forsaken Island (Hard)" dungeonLevel="66" dungeonMinLevel="66" dungeonMaxLevel="70" minItemLevel="453" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="150013" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9067" name="Demokron Factory (Hard)" dungeonLevel="67" dungeonMinLevel="67" dungeonMaxLevel="70" minItemLevel="456" matchingRoleId="29">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9068" name="Shadow Sanguinary (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="446" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9070" name="Manglemire" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="439" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9969" name="Lilith's Keep (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="439" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9970" name="Ruinous Manor (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="451" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9981" name="Velik's Sanctuary (Hard)" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="450" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9710" name="Broken Prison" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="443" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9027" name="Manaya's Core (Hard)" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="153">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9994" name="Thaumetal Refinery (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="440" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9935" name="RK-9 Kennel (Hard)" dungeonLevel="70" dungeonMinLevel="70" dungeonMaxLevel="70" minItemLevel="453" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9939" name="Red Refuge (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="448" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9983" name="Dark Reach Citadel (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="447" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<!--
|
||||
<Dungeon id="9754" name="Bathysmal Rise" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="417" matchingRoleId="17" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9716" name="Sky Cruiser Endeavor" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="438" matchingRoleId="17" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9757" name="Akeron's Inferno" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="190" matchingRoleId="26">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="96964" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="96967" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9756" name="Timescape" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="423" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9760" name="Kalivan's Dreadnaught" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="431" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9860" name="Kalivan's Challenge" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="412" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9059" name="Forsaken Island" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="438" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="150013" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9767" name="Demokron Factory" dungeonLevel="66" dungeonMinLevel="66" dungeonMaxLevel="70" minItemLevel="453" matchingRoleId="29">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9768" name="Shadow Sanguinary" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="437" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9769" name="Lilith's Keep" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="431" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9811" name="The Abscess (7-Person)" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="159" matchingRoleId="12">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9711" name="The Abscess (Hard)" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="175" matchingRoleId="1">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9043" name="Wonderholme (Hard) (10-Person)" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="159" matchingRoleId="13">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9743" name="Wonderholme (10-Person)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="171" matchingRoleId="13">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9770" name="Ruinous Manor" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="441" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9980" name="Velik's Hold (Hard)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="423" matchingRoleId="31">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9794" name="Thaumetal Refinery" dungeonLevel="68" dungeonMinLevel="68" dungeonMaxLevel="70" minItemLevel="457" matchingRoleId="11">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9720" name="Antaroth's Abyss" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="445" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9783" name="Dark Reach Citadel" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="436" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9782" name="Grotto of Lost Souls" dungeonLevel="68" dungeonMinLevel="68" dungeonMaxLevel="70" minItemLevel="453" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="3018" name="Dark Reach Citadel (7-person)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="444" matchingRoleId="29">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="3019" name="Grotto of Lost Souls (7-person)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="446" matchingRoleId="29">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="3017" name="Antaroth's Abyss (7-person)" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="447" matchingRoleId="29">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="3101" name="Gossamer Vault" dungeonLevel="66" dungeonMinLevel="66" dungeonMaxLevel="70" minItemLevel="453" matchingRoleId="17">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon> -->
|
||||
|
||||
<!-- Lvl 60 Dungeons -->
|
||||
<!--<Dungeon id="9950" name="Harrowhold" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="450" matchingRoleId="30" hide="true"/> -->
|
||||
<!--Dungeon id="9885" name="Dreadspire" dungeonLevel="65" dungeonMinLevel="65" dungeonMaxLevel="70" minItemLevel="409" matchingRoleId="17" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1" />
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1" />
|
||||
</Dungeon-->
|
||||
<!-- newbieBonusOff "true" If this is the case, the 'Bellik's Abundance Blessing' abnormal state is not visible for the corresponding dungeon, and the 'Butterfly' next to the character is not visible. Same as false if no parameters -->
|
||||
<!-- <Dungeon id="9975" name="Kelsaik's Raid (20-Person)" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="153" matchingRoleId="8">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
</Dungeon> -->
|
||||
<!-- <Dungeon id="9911" name="Kelsaik's Raid (10-Person)" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="147" matchingRoleId="7">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
</Dungeon> -->
|
||||
<!-- T3+ Activates the original Dungeons list that was temporarily removed before the December 1st update version -->
|
||||
<!--Dungeon id="9079" name="Saravash's Ascent" dungeonLevel="58" dungeonMinLevel="58" dungeonMaxLevel="63" minItemLevel="134">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="356" itemAmount="2"/>
|
||||
</Dungeon-->
|
||||
<Dungeon id="9080" name="Sigil Adstringo" dungeonLevel="58" dungeonMinLevel="58" dungeonMaxLevel="63" minItemLevel="134">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="356" itemAmount="2"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9082" name="Temple of Temerity" dungeonLevel="58" dungeonMinLevel="58" dungeonMaxLevel="63" minItemLevel="124" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="356" itemAmount="2"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9773" name="Ebon Tower (Hard)" dungeonLevel="58" dungeonMinLevel="58" dungeonMaxLevel="63" minItemLevel="131">
|
||||
<NeedItem id="5127"/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="356" itemAmount="2"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9775" name="Kelsaik's Nest (Hard)" dungeonLevel="58" dungeonMinLevel="58" dungeonMaxLevel="63" minItemLevel="132">
|
||||
<NeedItem id="5123"/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="356" itemAmount="2"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9776" name="Labyrinth of Terror (Hard)" dungeonLevel="58" dungeonMinLevel="58" dungeonMaxLevel="63" minItemLevel="131">
|
||||
<NeedItem id="5126"/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="356" itemAmount="2"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9078" name="Suryati's Peak" dungeonLevel="58" dungeonMinLevel="58" dungeonMaxLevel="63" minItemLevel="126">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="346" itemAmount="20"/>
|
||||
</Dungeon>
|
||||
<!--<Dungeon id="9024" name="Fane of Kaprima" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="138" >
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="2"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
<ClearCondition huntingZoneId="424" templateId="2000" amount="1" killCount="1" />
|
||||
</Dungeon>-->
|
||||
<!--<Dungeon id="9825" name="Balder's Temple (Solo)" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="138" matchingRoleId="14">
|
||||
<ClearCondition huntingZoneId="825" templateId="6000" amount="1" killCount="1" />
|
||||
</Dungeon>-->
|
||||
<!--<Dungeon id="9724" name="Fane of Kaprima (Hard))" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="142">
|
||||
<NeedItem id=""/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
<ClearCondition huntingZoneId="724" templateId="2000" amount="1" killCount="1" />
|
||||
</Dungeon>-->
|
||||
<Dungeon id="9725" name="Balder's Temple (Hard)" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="142">
|
||||
<NeedItem id="45323"/>
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
<ClearCondition huntingZoneId="725" templateId="8005" amount="1" killCount="1" />
|
||||
</Dungeon>
|
||||
<Dungeon id="9095" name="Crucible of Flame" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="142">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9096" name="Sirjuka Gallery" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="147">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="" itemAmount=""/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9793" name="Akasha's Hideout (Hard)" dungeonLevel="48" dungeonMinLevel="48" dungeonMaxLevel="56" minItemLevel="110">
|
||||
<NeedItem id="103"/>
|
||||
<DungeonClearCompensation itemTemplateId="410" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="54" itemAmount="12"/>
|
||||
</Dungeon>
|
||||
<Dungeon id="9726" name="Argon Corpus (Hard)" dungeonLevel="60" dungeonMinLevel="60" dungeonMaxLevel="70" minItemLevel="147">
|
||||
<DungeonClearCompensation itemTemplateId="411" itemAmount="1"/>
|
||||
<DungeonClearCompensation itemTemplateId="364" itemAmount="1"/>
|
||||
<ClearCondition huntingZoneId="726" templateId="20000" amount="1" killCount="1" />
|
||||
</Dungeon>
|
||||
</DungeonMatching>
|
||||
@@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<MatchRole>
|
||||
|
||||
<!-- OLD -->
|
||||
<Role id="1">
|
||||
<RoleData totalUser="5" tankerMin="1" tankerMax="1" dealerMin="1" dealerMax="3" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="2">
|
||||
<RoleData totalUser="15" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="3" healerMax="5" />
|
||||
</Role>
|
||||
<Role id="3">
|
||||
<RoleData totalUser="10" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="1" healerMax="3" />
|
||||
</Role>
|
||||
<Role id="4">
|
||||
<RoleData totalUser="3" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="0" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="5">
|
||||
<RoleData totalUser="15" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="" />
|
||||
</Role>
|
||||
<Role id="6">
|
||||
<RoleData totalUser="10" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="" />
|
||||
</Role>
|
||||
<Role id="7">
|
||||
<RoleData totalUser="10" tankerMin="2" tankerMax="2" dealerMin="4" dealerMax="5" healerMin="2" healerMax="3" />
|
||||
</Role>
|
||||
<Role id="8">
|
||||
<RoleData totalUser="20" tankerMin="2" tankerMax="2" dealerMin="14" dealerMax="15" healerMin="3" healerMax="4" />
|
||||
</Role>
|
||||
<Role id="9">
|
||||
<RoleData totalUser="20" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="3" healerMax="4" />
|
||||
</Role>
|
||||
<Role id="10">
|
||||
<RoleData totalUser="3" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="11">
|
||||
<RoleData totalUser="3" tankerMin="0" tankerMax="1" dealerMin="1" dealerMax="3" healerMin="0" healerMax="1" minMatchingMember="1" maxMatchingMember="3"/>
|
||||
</Role>
|
||||
<Role id="12">
|
||||
<RoleData totalUser="7" tankerMin="0" tankerMax="1" dealerMin="5" dealerMax="6" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="13">
|
||||
<RoleData totalUser="10" tankerMin="1" tankerMax="2" dealerMin="4" dealerMax="7" healerMin="2" healerMax="2" />
|
||||
</Role>
|
||||
<Role id="14" blueTeamFirstComposition="true" >
|
||||
<BlueTeamRoleData totalUser="10" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="2" healerMax="2" />
|
||||
<RedTeamRoleData totalUser="3" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="15">
|
||||
<RoleData totalUser="10" tankerMin="1" tankerMax="1" dealerMin="7" dealerMax="7" healerMin="2" healerMax="2" />
|
||||
</Role>
|
||||
<Role id="16">
|
||||
<RoleData totalUser="20" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="" />
|
||||
</Role>
|
||||
<Role id="17">
|
||||
<RoleData totalUser="5" totalUserQa="3" tankerMin="1" tankerMax="1" dealerMin="1" dealerMax="3" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
<!-- PVE 경쟁형 전장용 -->
|
||||
<Role id="18">
|
||||
<RoleData totalUser="3" tankerMax="1" healerMin="" healerMax="1" />
|
||||
</Role>
|
||||
<!-- 추억의 투지의 전장용 -->
|
||||
<Role id="19">
|
||||
<RoleData totalUser="5" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="20">
|
||||
<RoleData totalUser="5" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="0" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="21"><!-- 대혼전 -->
|
||||
<RoleData totalUser="15" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="2" healerMax="3" />
|
||||
</Role>
|
||||
<Role id="22"><!--탱커 없는 5인, 붉은 해적단의 함정 리파인-->
|
||||
<RoleData totalUser="5" totalUserQa="3" tankerMin="0" tankerMax="1" dealerMin="3" dealerMax="4" healerMin="1" healerMinQa="1" healerMax="1" healerMaxQa="1" />
|
||||
</Role>
|
||||
<Role id="23" changeRoleTime="30" changeRoleId="24" changeLimit=""> <!-- 성장구간 탱커없는 던전 매칭용 룰. changeRoleTime="sec" 대기 후 changeRoleId="24" 으로 변경 -->
|
||||
<RoleData totalUser="5" totalUserQa="3" tankerMin="1" tankerMax="1" dealerMin="1" dealerMax="3" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="24"> <!-- 성장구간 탱커/딜러/힐러 상관없는 던전 매칭용 룰. 23, 24번 -->
|
||||
<RoleData totalUser="5" totalUserQa="3" tankerMin="0" tankerMax="5" dealerMin="0" dealerMax="5" healerMin="0" healerMinQa="1" healerMax="5" healerMaxQa="1" />
|
||||
</Role>
|
||||
<Role id="25">
|
||||
<RoleData totalUser="7" totalUserQa="3" tankerMin="1" tankerMax="1" dealerMin="1" dealerMax="5" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="26"> <!-- 아케론 하급 동일 직업 5명 까지 매칭 가능 -->
|
||||
<RoleData totalUser="10" tankerMin="1" tankerMax="1" dealerMin="7" dealerMax="7" healerMin="2" healerMax="2" />
|
||||
</Role>
|
||||
<Role id="27"> <!-- 켈리반 중/하급용 3인 매칭 제한 -->
|
||||
<RoleData totalUser="10" tankerMin="1" tankerMax="1" dealerMin="7" dealerMax="7" healerMin="2" healerMax="2" minMatchingMember="1" maxMatchingMember="3"/>
|
||||
</Role>
|
||||
<Role id="28"> <!--베르노의 실험실용 -->
|
||||
<RoleData totalUser="7" tankerMin="1" tankerMax="1" dealerMin="1" dealerMax="5" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="29"> <!--베르노의 실험실용 -->
|
||||
<RoleData totalUser="7" tankerMin="1" tankerMax="1" dealerMin="4" dealerMax="5" healerMin="1" healerMax="2" />
|
||||
</Role>
|
||||
<Role id="30">
|
||||
<RoleData totalUser="20" tankerMin="4" tankerMax="4" dealerMin="11" dealerMax="11" healerMin="5" healerMax="5" />
|
||||
</Role>
|
||||
<Role id="31"> <!--벨리카 지하 관문용 -->
|
||||
<RoleData totalUser="7" tankerMin="1" tankerMax="1" dealerMin="1" dealerMax="4" healerMin="1" healerMax="2" />
|
||||
</Role>
|
||||
<Role id="32"> <!-- 성장구간 탱커/딜러/힐러 상관없는 3인용 매칭룰 -->
|
||||
<RoleData totalUser="3" totalUserQa="3" tankerMin="0" tankerMax="3" dealerMin="0" dealerMax="3" healerMin="0" healerMinQa="0" healerMax="3" healerMaxQa="1" />
|
||||
</Role>
|
||||
<!--전장용 매칭 롤 100번대 사용-->
|
||||
<!--전장 매칭에서는 탱커를 따로 구분하지 않는다 딜러로 구분해서 매칭 구성함.-->
|
||||
<Role id="101"> <!--눈싸움 전장-->
|
||||
<RoleData totalUser="7" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="" maxMatchingMember="2"/>
|
||||
</Role>
|
||||
<Role id="102" blueTeamFirstComposition="true" > <!--쿠마스는 개인 매칭만 됨-->
|
||||
<BlueTeamRoleData totalUser="10" totalUserQa="6" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="2" healerMax="2" />
|
||||
<RedTeamRoleData totalUser="3" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="103"> <!--포화의 전장--><!--maxHealerMatchingMember="": 신청할 수 있는 파티인원 중 최대 힐러 인원 / maxMatchingMember를 넘을 수 없음.-->
|
||||
<RoleData totalUser="20" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="3" healerMinQa="1" healerMax="4" minMatchingMember="1" maxMatchingMember="2" minHealerMatchingMember="" maxHealerMatchingMember="1" adjMPFor1="1.0" adjMPFor2="1.2" adjMPFor3="1.3" adjMPFor4="1.4" adjMPFor5="1.5" />
|
||||
</Role>
|
||||
<Role id="104"> <!--20vs20 포화의 전장-->
|
||||
<RoleData totalUser="20" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="" minMatchingMember="20" maxMatchingMember="20"/>
|
||||
</Role>
|
||||
<Role id="105"> <!--명예의 전장-->
|
||||
<RoleData totalUser="15" totalUserQa="3" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="3" healerMinQa="1" healerMax="5" minMatchingMember="1" maxMatchingMember="5" minHealerMatchingMember="" maxHealerMatchingMember="1" />
|
||||
</Role>
|
||||
<Role id="106"> <!--15vs15 명예의 전장-->
|
||||
<RoleData totalUser="15" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="" minMatchingMember="15" maxMatchingMember="15"/>
|
||||
</Role>
|
||||
<Role id="107"> <!--투지의 전장-->
|
||||
<RoleData totalUser="3" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="0" healerMax="1" healerMaxQa="1" minMatchingMember="3" maxMatchingMember="3"/>
|
||||
</Role>
|
||||
<Role id="108"> <!--개인매칭 투지의 전장-->
|
||||
<RoleData totalUser="3" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="1" healerMax="1" minMatchingMember="1" maxMatchingMember="1"/>
|
||||
</Role>
|
||||
<Role id="109"> <!--5vs5 투지의 전장-->
|
||||
<RoleData totalUser="5" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="0" healerMax="1" healerMaxQa="1" minMatchingMember="5" maxMatchingMember="5" />
|
||||
</Role>
|
||||
<Role id="110"> <!--개인매칭 5vs5 투지의 전장-->
|
||||
<RoleData totalUser="5" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="0" healerMax="1" healerMaxQa="1" minMatchingMember="1" maxMatchingMember="1" />
|
||||
</Role>
|
||||
<Role id="111"> <!-- 지하의 격전장 -->
|
||||
<RoleData totalUser="10" totalUserQa="3" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="2" healerMinQa="1" healerMax="2" maxMatchingMember="1" adjMPFor1="1.0" adjMPFor2="1.2" adjMPFor3="1.3" adjMPFor4="1.4" adjMPFor5="1.5" />
|
||||
</Role>
|
||||
<Role id="112"> <!--팀매칭 PVE 경쟁형 전장용 -->
|
||||
<RoleData totalUser="3" tankerMax="1" healerMin="" healerMax="1" minMatchingMember="3" maxMatchingMember="3"/>
|
||||
</Role>
|
||||
<Role id="113"> <!-- PVE 경쟁형 전장용 -->
|
||||
<RoleData totalUser="3" tankerMax="1" healerMin="" healerMax="1" minMatchingMember="1" maxMatchingMember="3"/>
|
||||
</Role>
|
||||
<Role id="115"> <!--10vs10 쿠마스 전장-->
|
||||
<RoleData totalUser="5" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="" maxMatchingMember="1" adjMPFor1="1.0" adjMPFor2="1.2" adjMPFor3="1.3" adjMPFor4="1.4" adjMPFor5="1.5" />
|
||||
</Role>
|
||||
<Role id="116"> <!--해안 점령지-->
|
||||
<RoleData totalUser="7" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="1" healerMinQa="1" healerMax="1" minMatchingMember="1" maxMatchingMember="1" minHealerMatchingMember="" maxHealerMatchingMember="" adjMPFor1="1.0" adjMPFor2="1.2" adjMPFor3="1.3" adjMPFor4="1.4" adjMPFor5="1.5" />
|
||||
</Role>
|
||||
<Role id="909"> <!-- 월탱용 매칭 -->
|
||||
<RoleData totalUser="8" totalUserQa="2" tankerMin="" tankerMax="" dealerMin="" dealerMax="" healerMin="" healerMax="" maxMatchingMember="1"/>
|
||||
</Role>
|
||||
<Role id="999">
|
||||
<RoleData totalUser="99" tankerMin="1" tankerMax="1" dealerMin="97" dealerMax="97" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
<Role id="1000">
|
||||
<RoleData totalUser="1" tankerMin="1" tankerMax="1" dealerMin="1" dealerMax="1" healerMin="1" healerMax="1" />
|
||||
</Role>
|
||||
</MatchRole>
|
||||
@@ -0,0 +1,167 @@
|
||||
<StrSheet_BattleField xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://vezel.dev/novadrop/dc/StrSheet_BattleField StrSheet_BattleField.xsd" xmlns="https://vezel.dev/novadrop/dc/StrSheet_BattleField">
|
||||
<String id="1" string="In battle." />
|
||||
<String id="2" string="Entering..." />
|
||||
<String id="3" string="Standing by..." />
|
||||
<String id="4" string="Commander" />
|
||||
<String id="5" string="Resurrection Location" />
|
||||
<String id="6" string="Meteor Skill" />
|
||||
<String id="7" string="Valkyon Reward Coordinator" />
|
||||
<String id="8" string="Reward based on battleground valor" />
|
||||
<String id="9" string="I commend you on behalf of the Valkyon Federation for your victories on the field!" />
|
||||
<String id="10" string="Targony Base" />
|
||||
<String id="11" string="PvPvE in Targony Base" />
|
||||
<String id="20" string="Fraywind Canyon" />
|
||||
<String id="21" string="Join alone or with a party of up to 5 members. If your item level is at or below 448, you will receive equalized PvP gear. Score points by defeating opponents or monsters, or controlling pyres. You must reach the target score first to win." />
|
||||
<String id="22" string="Central Pyre (1)" />
|
||||
<String id="23" string="Southern Pyre (2)" />
|
||||
<String id="24" string="Northern Pyre (3)" />
|
||||
<String id="25" string="Your Base" />
|
||||
<String id="26" string="Enemy's Base" />
|
||||
<String id="27" string="Fraywind Canyon (15-player pre-made raid)" />
|
||||
<String id="28" string="[RAID] Does not progress quests! Join with your own 15-player raid. Score points by defeating opponents, monsters, and controlling pyres. Pyres generate points while burning blue. First raid to reach the target score, wins." />
|
||||
<String id="29" string="Fraywind Canyon—Equalized" />
|
||||
<String id="290" string="[Equalized] Does not progress quests! Players enter the battle wearing superior equalized PvP gear. You can customize the gear and jewelry with crystals. Score points by defeating opponents, monsters, and controlling pyres. First side to reach the target score, wins." />
|
||||
<String id="291" string="Seize 3 sites. Reward varies depending on your result.<BR><FONT COLOR='#1000FF'>[Win]</FONT><BR>8 Champion's Enchanting Chests<BR><FONT COLOR='#FF0000'>[Lose]</FONT><BR>5 Champion's Enchanting Chests" />
|
||||
<String id="60" string="[Unified Gear] Gridiron" />
|
||||
<String id="61" string="A team with higher score wins." />
|
||||
<String id="62" string="[Victory Reward]<BR>216,000 Bellicarium Credits<BR>Veteran’s <FONT COLOR='#0B610B'>Shard</FONT> Chest ×3<BR><BR>[Defeat Reward]<BR>72,000 Bellicarium Credits<BR>Veteran’s <FONT COLOR='#0B610B'>Shard</FONT> Chest ×1<BR>" />
|
||||
<String id="63" string="Gridiron Academy" />
|
||||
<String id="64" string="Defeat enemy team within the time limit. Earn the Battle Points for your team. Killing enemies earns more Battle Points. Only available to players levels 40–64." />
|
||||
<String id="65" string="Check the battleground description to confirm which versions will not progress quests. Different battlegrounds have different queue requirements. Skilled or experienced players can queue as group leader. If your group changes, you need to cancel your current request and queue again. Your character profile displays your PvP record for all battlegrounds. Have fun, and try not to die!" />
|
||||
<String id="30" string="Champions' Skyring (Unranked)" />
|
||||
<String id="31" string="Join as a team to go up against other teams. Your Champions' Skyring personal ranking applies to both team and solo matches." />
|
||||
<String id="32" string="[Personal Gear] Champions' Skyring" />
|
||||
<String id="33" string="Champions' Skyring Mark V (Team)" />
|
||||
<String id="34" string="Champions' Skyring Mark V Equalized (Solo)" />
|
||||
<String id="35" string="Join with a 5 player party of all different classes and no more than one healing class. Defeat all opponents to win a round. First team to win two rounds is the victor. " />
|
||||
<String id="36" string="Join as a solo player and be matched with a party. Defeat all opponents to win a round. First team to win two rounds is the victor." />
|
||||
<String id="38" string="[Unified Gear] Champions' Skyring (Solo)" />
|
||||
<String id="39" string="Join as a solo player to go up against other solos. All players receive equalized PvP gear. Your Champions' Skyring personal ranking applies to both team and solo matches." />
|
||||
<String id="100" string="All" />
|
||||
<String id="101" string="My Server" />
|
||||
<String id="40" string="[Unified Gear] Corsairs' Stronghold" />
|
||||
<String id="41" string="Both teams take turns to attack and defend the Anchorstone. The first team to destroy the opponents’ Anchorstone wins." />
|
||||
<String id="42" string="Resurrection Point" />
|
||||
<String id="43" string="Corsairs' Stronghold (20-player raid)" />
|
||||
<String id="44" string="Join with your own 20-player raid. In round one, the defenders' goal is to protect the anchorstone for 15 minutes. In round two, the teams switch roles, and the attackers must destroy it before time runs out. " />
|
||||
<String id="45" string="Resurrection Point" />
|
||||
<String id="46" string="Resurrection Point" />
|
||||
<String id="47" string="[Victory Reward]<BR>216,000 Bellicarium Credits<BR>Veteran’s <FONT COLOR='#0B610B'>Shard</FONT> Chest ×4<BR><BR>[Defeat Reward]<BR>72,000 Bellicarium Credits<BR>Veteran’s <FONT COLOR='#0B610B'>Shard</FONT> Chest ×2<BR>" />
|
||||
<String id="50" string="Kumasylum" />
|
||||
<String id="51" string="Join as a solo player. A team of federation players battles a trio of kumas players. The federation players must find and return three pieces of kumas rock candy within the time limit. The kumas players must stop them from reaching a loading dock with the rock candy." />
|
||||
<String id="52" string="Resurrection Point" />
|
||||
<String id="53" string="Rock Candy" />
|
||||
<String id="54" string="Kumas Trio" />
|
||||
<String id="55" string="Federation Team" />
|
||||
<String id="11801" string="Kumas Royale" />
|
||||
<String id="11802" string="Join solo or with a party of up to 2 members. All combatants become kumases. Your team wins if your Kumas Boss has more HP at the end of the match than your enemies' Kumas Boss. Work together to protect your Kumas Boss, and damage the enemies' Courser!" />
|
||||
<String id="11803" string="Starting Area" />
|
||||
<String id="11804" string="Kumas Boss" />
|
||||
<String id="11805" string="Team 1" />
|
||||
<String id="11806" string="Team 2" />
|
||||
<String id="11807" string="Resurrection Point" />
|
||||
<String id="11901" string="Kumas Royale" />
|
||||
<String id="90" string="Wintera Snowfield" />
|
||||
<String id="91" string="Available only during Wintera! You win the round when the entire opposing team is dead. If both teams are not eliminated until the timer runs out, the team with more survivors will win." />
|
||||
<String id="92" string="[Seasonal Battleground] <BR><BR> Regular character skills cannot be used on the Wintera Snowfield. All characters have the same HP regardless of level. (HP recovery may vary depending on character level.)<BR> Gather snowballs scattered on the snowfield. Use them to damage your opponents, open ice chests for more attacks, and open warm-up boxes for defenses." />
|
||||
<String id="93" string="A chance to go back to your childhood during Wintera! You win the round when the entire opposing team is dead. If both teams are not eliminated until the timer runs out, the team with more survivors will win." />
|
||||
<String id="94" string="[Seasonal Battleground] <BR><BR> Regular character skills cannot be used on the Wintera Snowfield. All characters have the same HP regardless of level. (HP recovery may vary depending on character level.)<BR> Gather snowballs scattered on the snowfield. Use them to damage your opponents, open ice chests for more attacks, and open warm-up boxes for defenses." />
|
||||
<String id="110" string="Monkeydrome" />
|
||||
<String id="111" string="Compete against another team to defeat monsters and earn points. Leaders buy skills to buff teammates, debuff opponents, or harry opponents with more monsters." />
|
||||
<String id="112" string="Monkeydrome (Lv. 60-65, Equalized)" />
|
||||
<String id="201" string="Buff: Power" />
|
||||
<String id="202" string="Buff: Recover HP" />
|
||||
<String id="203" string="Buff: Attack Speed" />
|
||||
<String id="204" string="Buff: Crit Factor" />
|
||||
<String id="205" string="Debuff: Defense" />
|
||||
<String id="206" string="Debuff: Movement Speed" />
|
||||
<String id="207" string="Debuff: Knockdown Resistance" />
|
||||
<String id="208" string="Debuff: Power" />
|
||||
<String id="209" string="Summon: Kobold I" />
|
||||
<String id="210" string="Summon: Kobold II" />
|
||||
<String id="211" string="Summon: Kobold III" />
|
||||
<String id="212" string="Summon: Kobold IV" />
|
||||
<String id="213" string="Summon: Kobold V" />
|
||||
<String id="214" string="Summon: Naga I" />
|
||||
<String id="215" string="Summon: Naga II" />
|
||||
<String id="216" string="Summon: Naga III" />
|
||||
<String id="217" string="Summon: Naga IV" />
|
||||
<String id="218" string="Summon: Naga V" />
|
||||
<String id="219" string="Buff: Monsters HP" />
|
||||
<String id="220" string="Buff: Monsters Power" />
|
||||
<String id="221" string="Debuff: Life Leech" />
|
||||
<String id="222" string="Debuff: Stun Wave" />
|
||||
<String id="301" string="Your allies' Power increases by 15%." />
|
||||
<String id="302" string="Your allies recover 8% of max HP every 10 seconds." />
|
||||
<String id="303" string="Your allies' Attack Speed increases by 15%." />
|
||||
<String id="304" string="Allies' Crit Factor increases by 50%." />
|
||||
<String id="305" string="Decreases opponents' Defense by 15%." />
|
||||
<String id="306" string="Decreases opponents' Movement Speed by 20%." />
|
||||
<String id="307" string="Decreases opponents' resistance to knockdown by 20%." />
|
||||
<String id="308" string="Decreases opponents' Power by 15%." />
|
||||
<String id="309" string="Summons swift minions to the opponents' ring for 12 seconds 1 minute into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="310" string="Summons swift minions to the opponents' ring for 12 seconds 2 minutes into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="311" string="Summons swift minions to the opponents' ring for 12 seconds 3 minutes into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="312" string="Summons swift minions to the opponents' ring for 12 seconds 4 minutes into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="313" string="Summons swift minions to the opponents' ring for 12 seconds 5 minutes into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="314" string="Summons powerful minions to the opponents' ring for 12 seconds 1 minute into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="315" string="Summons powerful minions to the opponents' ring for 12 seconds 2 minutes into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="316" string="Summons powerful minions to the opponents' ring for 12 seconds 3 minutes into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="317" string="Summons powerful minions to the opponents' ring for 12 seconds 4 minutes into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="318" string="Summons powerful minions to the opponents' ring for 12 seconds 5 minutes into the round. Failing to kill each minion will deduct 100 points." />
|
||||
<String id="319" string="Increases max HP of all monsters spawned in opponent's ring by 25%." />
|
||||
<String id="320" string="Increases power of all monsters spawned in opponent's ring by 30%." />
|
||||
<String id="321" string="Ongoing damage decreases opponents' HP by 10% of max every 5 seconds." />
|
||||
<String id="322" string="Stuns opponents every 15 seconds." />
|
||||
<String id="401" string="Ally Buffs" />
|
||||
<String id="402" string="Opponent Debuffs" />
|
||||
<String id="403" string="Summon Minions" />
|
||||
<String id="90900" string="Iron Battleground" />
|
||||
<String id="90901" string="Join as a solo player, and destroy opponents using tanks. The team with the most players left alive after 6 minutes wins the round, and winning two out of three rounds wins the match. (Can be entered a maximum of 8 times per day.)" />
|
||||
<String id="90902" string=" Regular character skills cannot be used in Iron Battleground. All characters have the same HP regardless of level. (HP recovery may vary depending on character level.) Attack opponents with tanks, artillery, or mines. Damaged tanks can be repaired by ramming a Repair Pylon. Players receive equalized Conflict gear. Players on foot have anti-tank skills, but are vulnerable to enemy tanks." />
|
||||
<String id="5000" string="<FONT COLOR='#FF0000'>Attacker Guide </FONT>" />
|
||||
<String id="5001" string="<FONT COLOR='#1000FF'>Defender Guide </FONT>" />
|
||||
<String id="5002" string="<FONT COLOR='#1000FF'>Kumas Team Guide </FONT>" />
|
||||
<String id="5003" string="<FONT COLOR='#FF0000'>Federation Team Guide </FONT>" />
|
||||
<String id="9001" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won: </FONT>Your team destroyed the anchorstone faster than your opponents." />
|
||||
<String id="9002" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost: </FONT>Your team took longer to destroy the anchorstone." />
|
||||
<String id="9003" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won: </FONT>The opponent team's time ran out." />
|
||||
<String id="9004" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost: </FONT>Your time ran out." />
|
||||
<String id="9005" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won: </FONT>Your team fended off the enemies longer than the opponent team did." />
|
||||
<String id="9006" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost: </FONT>Your team was slower than your opponents." />
|
||||
<String id="9007" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won: </FONT>You took all the candies." />
|
||||
<String id="9008" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost: </FONT>All your candy are belong to them." />
|
||||
<String id="9009" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won: </FONT>Time ran out." />
|
||||
<String id="9010" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost: </FONT>Time ran out." />
|
||||
<String id="9011" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won: </FONT>Got the desired score." />
|
||||
<String id="9012" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost: </FONT>Your opponents got the desired score." />
|
||||
<String id="9013" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won:</FONT> Eliminated all opponents or have more survivors in your group." />
|
||||
<String id="9014" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost:</FONT> Your team has been eliminated or have less survivors in your group." />
|
||||
<String id="9015" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won: </FONT>Got the desired kill counts." />
|
||||
<String id="9016" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost: </FONT>Your opponents got the desired kill count." />
|
||||
<String id="9017" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won: </FONT>You scored higher than your opponents." />
|
||||
<String id="9018" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost: </FONT>You scored lower than your opponents." />
|
||||
<String id="9019" string="<FONT SIZE='18' COLOR='#FFA100'>Why You Drew: </FONT>You and your opponents had the same number of survivors." />
|
||||
<String id="9020" string="<FONT SIZE='18' COLOR='#FFA100'>Why You Drew: </FONT>Time expired." />
|
||||
<String id="9021" string="<FONT SIZE='18' COLOR='#FFA100'>Why You Drew: </FONT>Your opponents don't have enough players." />
|
||||
<String id="9022" string="<FONT SIZE='18' COLOR='#FFA100'>Why You Drew: </FONT>Your team doesn't have enough players." />
|
||||
<String id="9023" string="<FONT SIZE='18' COLOR='#80E71C'>Why You Won: </FONT>Your team won more rounds." />
|
||||
<String id="9024" string="<FONT SIZE='18' COLOR='#FF0000'>Why You Lost: </FONT>Your opponents won more rounds." />
|
||||
<String id="9025" string="<FONT SIZE='18' COLOR='#FFA100'>Why You Drew: </FONT>One of the teams doesn't have enough players." />
|
||||
<String id="9026" string="<FONT SIZE='18' COLOR='#80E71C'>Draw : </FONT>The teams performed equally well." />
|
||||
<String id="9027" string="<FONT SIZE='18' COLOR='#FFA100'>Victory : </FONT>Your team outperformed the other team!" />
|
||||
<String id="9028" string="<FONT SIZE='18' COLOR='#FFA100'>Lose : </FONT>The other team outperformed your team." />
|
||||
<String id="10001" string="Kill Score" />
|
||||
<String id="10002" string="Attack Score" />
|
||||
<String id="10003" string="Heal Score" />
|
||||
<String id="10004" string="Assist Score" />
|
||||
<String id="10051" string="[Personal Gear] Shore Hold" />
|
||||
<String id="10052" string="Earn points by capturing sites and defeating monsters. Reach the target score before the opponent team." />
|
||||
<String id="10053" string="Pyre 1" />
|
||||
<String id="10054" string="Pyre 2" />
|
||||
<String id="10055" string="Pyre 3" />
|
||||
<String id="10056" string="Your base" />
|
||||
<String id="10057" string="Enemy base" />
|
||||
<String id="10058" string="Join a battlefield fight to win 3 pyres. You must reach the target score first to win.<BR>Rewards vary depending on your results: <FONT COLOR='#1000FF'>[Victory]</FONT> or <BR><FONT COLOR='#FF0000'>[Defeat]</FONT>." />
|
||||
<String id="10059" string="[Victory Reward]<BR>135,000 Bellicarium Credits<BR>Veteran’s <FONT COLOR='#1000FF'>Plate</FONT> Chest ×4<BR><BR>[Defeat Reward]<BR>45,000 Bellicarium Credits<BR>Veteran’s <FONT COLOR='#1000FF'>Plate</FONT> Chest ×2<BR>" />
|
||||
</StrSheet_BattleField>
|
||||
@@ -0,0 +1,217 @@
|
||||
<StrSheet_Dungeon xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://vezel.dev/novadrop/dc/StrSheet_Dungeon StrSheet_Dungeon.xsd" xmlns="https://vezel.dev/novadrop/dc/StrSheet_Dungeon">
|
||||
<String id="9999" string="Blast from the Past" />
|
||||
<String id="8999" string="Velik's Sanctuary" />
|
||||
<String id="9001" string="Samael's Residence" />
|
||||
<String id="9002" string="Fountain of Shara" />
|
||||
<String id="9003" string="Fyrmount Abyss" />
|
||||
<String id="9005" string="Jester's Villa" />
|
||||
<String id="9006" string="Genuine Throne of Nightmares" />
|
||||
<String id="9007" string="Hidden Shrine" />
|
||||
<String id="9008" string="Malachai's Lab" />
|
||||
<String id="9010" string="Kaiator Command Center" />
|
||||
<String id="9011" string="Muhrak's Workshop" />
|
||||
<String id="9012" string="Three Towers Spires" />
|
||||
<String id="9013" string="Cyasma Spire" />
|
||||
<String id="9014" string="Khanovar Gauntlet" />
|
||||
<String id="9016" string="Island of Dawn Clifftops" />
|
||||
<String id="9017" string="Lighthouse of the Sun" />
|
||||
<String id="9018" string="Argon Catacombs" />
|
||||
<String id="9019" string="Sanctum Mysterium Forecourt" />
|
||||
<String id="9020" string="Cultist's Armory" />
|
||||
<String id="9021" string="Hidden Tunnel" />
|
||||
<String id="9022" string="Vault of Glory" />
|
||||
<String id="9023" string="Kutmaschuk's Hideout" />
|
||||
<String id="9024" string="Fane of Kaprima" />
|
||||
<String id="9025" string="Balder's Temple" />
|
||||
<String id="9028" string="Malachai's Lab" />
|
||||
<String id="9031" string="Akasha's Trial" />
|
||||
<String id="9032" string="Baracos' Trial" />
|
||||
<String id="9033" string="Krakatox's Trial" />
|
||||
<String id="9036" string="Karascha's Lair" />
|
||||
<String id="9037" string="Tainted Gorge Bridge" />
|
||||
<String id="9038" string="Mysterious Jungle" />
|
||||
<String id="9039" string="Caravan Ambush Site" />
|
||||
<String id="9040" string="Velika Plaza" />
|
||||
<String id="9041" string="Velika Eastern Gate" />
|
||||
<String id="9042" string="Velika Headquarters" />
|
||||
<String id="9046" string="Accursed Oasis" />
|
||||
<String id="9050" string="Rift's Edge (Hard) (10-Person)" />
|
||||
<String id="9750" string="Rift's Edge (10-Person)" />
|
||||
<String id="9061" string="Ruin of the Giants" />
|
||||
<String id="9062" string="Jester's Villa" />
|
||||
<String id="9063" string="Raven Altar" />
|
||||
<String id="9064" string="Molten Chamber" />
|
||||
<String id="9065" string="Twilight Valley " />
|
||||
<String id="9071" string="Necromancer Tomb" />
|
||||
<String id="9072" string="Golden Labyrinth" />
|
||||
<String id="9073" string="Ebon Tower" />
|
||||
<String id="9074" string="Sanctum of Resurrection" />
|
||||
<String id="9075" string="Kelsaik's Nest" />
|
||||
<String id="9076" string="Labyrinth of Terror" />
|
||||
<String id="9077" string="Batu Desert" />
|
||||
<String id="9078" string="Suryati's Peak" />
|
||||
<String id="9079" string="Saravash's Ascent" />
|
||||
<String id="9080" string="Sigil Adstringo" />
|
||||
<String id="9081" string="Training Grounds" />
|
||||
<String id="9082" string="Temple of Temerity" />
|
||||
<String id="9083" string="Breaching Grounds" />
|
||||
<String id="9087" string="Bastion of Lok" />
|
||||
<String id="9088" string="Sinestral Manor" />
|
||||
<String id="9089" string="Cultists' Refuge" />
|
||||
<String id="9090" string="Woodland Path" />
|
||||
<String id="9091" string="Altar of Vadoma" />
|
||||
<String id="9092" string="Dagon's Chantry" />
|
||||
<String id="9093" string="Akasha's Hideout" />
|
||||
<String id="9094" string="Saleron's Sky Garden" />
|
||||
<String id="9096" string="Sirjuka Gallery" />
|
||||
<String id="9724" string="Fane of Kaprima (Hard)" />
|
||||
<String id="9725" string="Balder's Temple (Hard)" />
|
||||
<String id="9793" string="Akasha's Hideout (Hard)" />
|
||||
<String id="9773" string="Ebon Tower (Hard)" />
|
||||
<String id="9775" string="Kelsaik's Nest (Hard)" />
|
||||
<String id="9776" string="Labyrinth of Terror (Hard)" />
|
||||
<String id="9801" string="Nexus Traverse" />
|
||||
<String id="9802" string="Nexus Traverse" />
|
||||
<String id="9803" string="Nexus Traverse" />
|
||||
<String id="9026" string="Argon Corpus" />
|
||||
<String id="9726" string="Argon Corpus (Hard)" />
|
||||
<String id="9027" string="Manaya's Core (Hard)" />
|
||||
<String id="9727" string="Manaya's Core" />
|
||||
<String id="9095" string="Crucible of Flame" />
|
||||
<String id="9795" string="Crucible of Fame" />
|
||||
<String id="9045" string="Bluefirst Mountain" />
|
||||
<String id="9047" string="Harvest Festival Hall" />
|
||||
<String id="9126" string="Pit of Petrax" />
|
||||
<String id="9975" string="Kelsaik's Raid (20-Person)" />
|
||||
<String id="9911" string="Kelsaik's Raid (10-Person)" />
|
||||
<String id="9051" string="Squalid Temple" />
|
||||
<String id="9052" string="Banquet of Blood" />
|
||||
<String id="9711" string="The Abscess (Hard)" />
|
||||
<String id="9611" string="The Abscess (Hard)" />
|
||||
<String id="9777" string="Channelworks (3-Person)" />
|
||||
<String id="9766" string="Shattered Fleet" />
|
||||
<String id="9043" string="Wonderholme (Hard) (10-Person)" />
|
||||
<String id="9643" string="Wonderholme (10-Person)" />
|
||||
<String id="9743" string="Wonderholme (10-Person)" />
|
||||
<String id="9053" string="Kezzel's Gorge (7-Person)" />
|
||||
<String id="9511" string="The Abscess (7-Person)" />
|
||||
<String id="9811" string="The Abscess (7-Person)" />
|
||||
<String id="9810" string="Lakan's Prison" />
|
||||
<String id="9813" string="Ghillieglade (Solo)" />
|
||||
<String id="9821" string="Dakuryon's Sanctum" />
|
||||
<String id="9822" string="Archdeva Listening Post" />
|
||||
<String id="9814" string="The Vault of Oriyn" />
|
||||
<String id="9818" string="Energia Celo" />
|
||||
<String id="9827" string="Stepstone Isle" />
|
||||
<String id="9828" string="Shadetree" />
|
||||
<String id="9829" string="Tiaran the Sorrow Tree" />
|
||||
<String id="9833" string="Wyrmgorge" />
|
||||
<String id="9887" string="Bastion of Lok (Solo)" />
|
||||
<String id="9888" string="Sinestral Manor (Solo)" />
|
||||
<String id="9889" string="Cultists' Refuge (Solo)" />
|
||||
<String id="9871" string="Necromancer Tomb (Solo)" />
|
||||
<String id="9872" string="Golden Labyrinth (Solo)" />
|
||||
<String id="9894" string="Saleron's Sky Garden (Solo)" />
|
||||
<String id="9876" string="Labyrinth of Terror (Solo)" />
|
||||
<String id="9873" string="Ebon Tower (Solo)" />
|
||||
<String id="9879" string="Saravash's Ascent (Solo)" />
|
||||
<String id="9820" string="Resistance Secret Camp" />
|
||||
<String id="9880" string="Sigil Adstringo (Solo)" />
|
||||
<String id="9824" string="Fane of Kaprima (Solo)" />
|
||||
<String id="9825" string="Balder's Temple (Solo)" />
|
||||
<String id="9151" string="Noctenium Research Grounds" />
|
||||
<String id="9808" string="Sabex Armory" />
|
||||
<String id="9809" string="Macellarius Catacombs" />
|
||||
<String id="9054" string="Bathysmal Rise (Hard)" />
|
||||
<String id="9754" string="Bathysmal Rise" />
|
||||
<String id="9055" string="Ravenous Gorge (3-Person)" />
|
||||
<String id="9823" string="Sky Cruiser Intrepid" />
|
||||
<String id="9826" string="Vaelsiar Chambers" />
|
||||
<String id="9916" string="Sky Cruiser Endeavor (Hard)" />
|
||||
<String id="9716" string="Sky Cruiser Endeavor" />
|
||||
<String id="9885" string="Dreadspire" />
|
||||
<String id="9886" string="Dreadspire: Upper Levels" />
|
||||
<String id="9713" string="Ghillieglade" />
|
||||
<String id="9714" string="Velik's Sanctuary" />
|
||||
<String id="9804" string="Kelsaik's Nest_For Japan Tournaments" />
|
||||
<String id="9979" string="Saravash's Ascent" />
|
||||
<String id="9057" string="Akeron's Inferno (Hard)" />
|
||||
<String id="9757" string="Akeron's Inferno" />
|
||||
<String id="9029" string="Vault of Kaprima" />
|
||||
<String id="9056" string="Timescape (Hard)" />
|
||||
<String id="9756" string="Timescape" />
|
||||
<String id="9060" string="Kalivan's Dreadnaught (Hard)" />
|
||||
<String id="9760" string="Kalivan's Dreadnaught" />
|
||||
<String id="9860" string="Kalivan's Challenge" />
|
||||
<String id="9059" string="Forsaken Island" />
|
||||
<String id="9759" string="Forsaken Island (Hard)" />
|
||||
<String id="9830" string="Celestial Arena" />
|
||||
<String id="9067" string="Demokron Factory (Hard)" />
|
||||
<String id="9767" string="Demokron Factory" />
|
||||
<String id="9769" string="Lilith's Keep" />
|
||||
<String id="9969" string="Lilith's Keep (Hard)" />
|
||||
<String id="9068" string="Shadow Sanguinary (Hard)" />
|
||||
<String id="9768" string="Shadow Sanguinary" />
|
||||
<String id="9070" string="Manglemire" />
|
||||
<String id="9069" string="Echoes of Aranea" />
|
||||
<String id="9970" string="Ruinous Manor (Hard)" />
|
||||
<String id="9770" string="Ruinous Manor" />
|
||||
<String id="9950" string="Harrowhold" />
|
||||
<String id="9710" string="Broken Prison" />
|
||||
<String id="9780" string="Velik's Hold (7-Person)" />
|
||||
<String id="9980" string="Velik's Hold (Hard)" />
|
||||
<String id="9981" string="Velik's Sanctuary (Hard)" />
|
||||
<String id="9781" string="Velik's Sanctuary" />
|
||||
<String id="9681" string="Velik's Dream" />
|
||||
<String id="9066" string="Demon's Wheel" />
|
||||
<String id="9794" string="Thaumetal Refinery" />
|
||||
<String id="9994" string="Thaumetal Refinery (Hard)" />
|
||||
<String id="9735" string="RK-9 Kennel" />
|
||||
<String id="9935" string="RK-9 Kennel (Hard)" />
|
||||
<String id="9505" string="Ruined Velika Banquet" />
|
||||
<String id="9506" string="Velika Banquet" />
|
||||
<String id="9507" string="Dragon's Landing" />
|
||||
<String id="9508" string="Soulscape" />
|
||||
<String id="9509" string="Velika Banquet Redux" />
|
||||
<String id="9739" string="Red Refuge" />
|
||||
<String id="9939" string="Red Refuge (Hard)" />
|
||||
<String id="9920" string="Antaroth's Abyss (Hard)" />
|
||||
<String id="9720" string="Antaroth's Abyss" />
|
||||
<String id="9034" string="Dreadspire" />
|
||||
<String id="9783" string="Dark Reach Citadel" />
|
||||
<String id="9983" string="Dark Reach Citadel (Hard)" />
|
||||
<String id="9782" string="Grotto of Lost Souls" />
|
||||
<String id="9982" string="Grotto of Lost Souls (Hard)" />
|
||||
<String id="9044" string="Bahaar's Sanctum" />
|
||||
<String id="3012" string="Training Ground" />
|
||||
<String id="3016" string="Lilith's Trial" />
|
||||
<String id="3018" string="Dark Reach Citadel (7-person)" />
|
||||
<String id="3019" string="Grotto of Lost Souls (7-person)" />
|
||||
<String id="3017" string="Antaroth's Abyss (7-person)" />
|
||||
<String id="3001" string="Bastion of Lok (Solo)" />
|
||||
<String id="3002" string="Sinestral Manor (Solo)" />
|
||||
<String id="3003" string="Cultists' Refuge (Solo)" />
|
||||
<String id="3004" string="Necromancer Tomb (Solo)" />
|
||||
<String id="3005" string="Golden Labyrinth (Solo)" />
|
||||
<String id="3006" string="Akasha's Hideout (Solo)" />
|
||||
<String id="3007" string="Saleron's Sky Garden (Solo)" />
|
||||
<String id="3008" string="Labyrinth of Terror (Solo)" />
|
||||
<String id="3009" string="Ebon Tower (Solo)" />
|
||||
<String id="3010" string="Kelsaik's Nest (Solo)" />
|
||||
<String id="3011" string="Manaya's Core (Solo)" />
|
||||
<String id="9503" string="Federation Commander Residence" />
|
||||
<String id="3101" string="Gossamer Vault" />
|
||||
<String id="3201" string="Gossamer Vault (Hard)" />
|
||||
<String id="3020" string="Sea of Honor" />
|
||||
<String id="3024" string="Azart Hatchery" />
|
||||
<String id="3025" string="Azart Hatchery (Hard)" />
|
||||
<String id="3023" string="Akalath Quarantine" />
|
||||
<String id="3026" string="Corrupted Skynest" />
|
||||
<String id="2000" string="Exodor Archipelago" />
|
||||
<String id="2100" string="Akalath Quarantine" />
|
||||
<String id="2101" string="Larvae Hatchery" />
|
||||
<String id="2102" string="Cliffside Prison" />
|
||||
<String id="2103" string="Black Core Engine Room" />
|
||||
<String id="3126" string="Corrupted Skynest (Hard) Entrance" />
|
||||
<String id="3027" string="Forbidden Arena" />
|
||||
</StrSheet_Dungeon>
|
||||
@@ -0,0 +1,397 @@
|
||||
const https = require("https");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const ROLE_NAMES = { 0: "T", 1: "D", 2: "H" };
|
||||
const ROLE_FULL = { 0: "Tank", 1: "DPS", 2: "Healer" };
|
||||
|
||||
// Shared in-memory state (all module instances in the same Node.js process)
|
||||
if (!global.__discordMatching) {
|
||||
global.__discordMatching = {
|
||||
matchState: {},
|
||||
lastMessageId: null,
|
||||
sending: false,
|
||||
pendingAction: null
|
||||
};
|
||||
}
|
||||
const G = global.__discordMatching;
|
||||
|
||||
module.exports = function DiscordMatchingRelay(mod) {
|
||||
const config = loadConfig();
|
||||
let webhookUrl = config.webhook || null;
|
||||
const showPlayerNames = config.showPlayerNames !== false;
|
||||
const enabled = config.enabled !== false;
|
||||
|
||||
// Data caches
|
||||
const dungeonNames = {};
|
||||
const dungeonRoleMap = {};
|
||||
const battleFieldNames = {};
|
||||
const battleFieldData = {};
|
||||
const roleTemplates = {};
|
||||
|
||||
// Shared state is in G (global.__discordMatching)
|
||||
let knownPlayerName = (mod.game && mod.game.me && mod.game.me.name) || "";
|
||||
|
||||
function loadConfig() {
|
||||
try { delete require.cache[require.resolve("./module.config.json")]; return require("./module.config.json"); }
|
||||
catch (e) { return { enabled: true, webhook: "" }; }
|
||||
}
|
||||
|
||||
function readFileString(filePath) {
|
||||
try { return fs.readFileSync(filePath, "utf-8"); } catch (e) { mod.error(`[DiscordMatching] Failed to read ${filePath}: ${e.message}`); return ""; }
|
||||
}
|
||||
|
||||
function loadDungeonNames() {
|
||||
const dir = path.join(__dirname, "data", "StrSheet_Dungeon");
|
||||
let files;
|
||||
try { files = fs.readdirSync(dir); } catch (e) { mod.error(`[DiscordMatching] Cannot read StrSheet_Dungeon dir: ${e.message}`); return; }
|
||||
for (const file of files) {
|
||||
if (!file.startsWith("StrSheet_Dungeon-") || !file.endsWith(".xml")) continue;
|
||||
const content = readFileString(path.join(dir, file));
|
||||
const regex = /<String\s+id="(\d+)"\s+string="([^"]+)"\s*\/>/g;
|
||||
let m; while ((m = regex.exec(content)) !== null) dungeonNames[parseInt(m[1], 10)] = m[2];
|
||||
}
|
||||
mod.log(`[DiscordMatching] Loaded ${Object.keys(dungeonNames).length} dungeon names`);
|
||||
}
|
||||
|
||||
function loadDungeonMatching() {
|
||||
const content = readFileString(path.join(__dirname, "data", "DungeonMatching.xml"));
|
||||
const regex = /<Dungeon\s+id="(\d+)"[^>]*>/g;
|
||||
let m; while ((m = regex.exec(content)) !== null) {
|
||||
const fullTag = m[0], id = parseInt(m[1], 10);
|
||||
if (content.substring(Math.max(0, m.index - 10), m.index).includes("<!--")) continue;
|
||||
const rm = fullTag.match(/matchingRoleId="(\d+)"/);
|
||||
dungeonRoleMap[id] = rm ? parseInt(rm[1], 10) : 23;
|
||||
}
|
||||
mod.log(`[DiscordMatching] Loaded ${Object.keys(dungeonRoleMap).length} dungeon matching entries`);
|
||||
}
|
||||
|
||||
function loadRoleTemplates() {
|
||||
const content = readFileString(path.join(__dirname, "data", "MatchingRoleTemplate.xml"));
|
||||
const roleRegex = /<Role\s+id="(\d+)"[^>]*>/g;
|
||||
let roleMatch; while ((roleMatch = roleRegex.exec(content)) !== null) {
|
||||
const roleId = parseInt(roleMatch[1], 10);
|
||||
const remaining = content.substring(roleMatch.index);
|
||||
const rd = remaining.match(/<RoleData\s+([^>]+)\/>/);
|
||||
if (!rd) continue;
|
||||
const attrs = rd[1];
|
||||
const ga = (name, def) => { const x = attrs.match(new RegExp("\\b" + name + '="([^"]*)"')); return x ? (x[1] === "" ? undefined : parseInt(x[1], 10)) : def; };
|
||||
roleTemplates[roleId] = {
|
||||
totalUser: ga("totalUser"), tanker: ga("tanker", ga("tankerMax")), dealer: ga("dealer", ga("dealerMax")), healer: ga("healer", ga("healerMax")),
|
||||
tankerMin: ga("tankerMin"), tankerMax: ga("tankerMax"), dealerMin: ga("dealerMin"), dealerMax: ga("dealerMax"),
|
||||
healerMin: ga("healerMin"), healerMax: ga("healerMax")
|
||||
};
|
||||
}
|
||||
mod.log(`[DiscordMatching] Loaded ${Object.keys(roleTemplates).length} role templates`);
|
||||
}
|
||||
|
||||
function loadBattleFieldNames() {
|
||||
const dir = path.join(__dirname, "data", "StrSheet_BattleField");
|
||||
let files;
|
||||
try { files = fs.readdirSync(dir); } catch (e) { mod.error(`[DiscordMatching] Cannot read StrSheet_BattleField dir: ${e.message}`); return; }
|
||||
for (const file of files) {
|
||||
if (!file.startsWith("StrSheet_BattleField-") || !file.endsWith(".xml")) continue;
|
||||
const content = readFileString(path.join(dir, file));
|
||||
const regex = /<String\s+id="(\d+)"\s+string="([^"]+)"\s*\/>/g;
|
||||
let m; while ((m = regex.exec(content)) !== null) battleFieldNames[parseInt(m[1], 10)] = m[2];
|
||||
}
|
||||
mod.log(`[DiscordMatching] Loaded ${Object.keys(battleFieldNames).length} battlefield strings`);
|
||||
}
|
||||
|
||||
function loadBattleFieldData() {
|
||||
const content = readFileString(path.join(__dirname, "data", "BattleFieldData.xml"));
|
||||
const regex = /<BattleField\s+[^>]*id="(\d+)"[^>]*>/g;
|
||||
let m; while ((m = regex.exec(content)) !== null) {
|
||||
const id = parseInt(m[1], 10);
|
||||
if (content.substring(Math.max(0, m.index - 10), m.index).includes("<!--")) continue;
|
||||
const nm = m[0].match(/name="(\d+)"/);
|
||||
const nameId = nm ? parseInt(nm[1], 10) : null;
|
||||
const rm = content.substring(m.index).match(/<RuleData\s+ruleId="(\d+)"/);
|
||||
battleFieldData[id] = { nameId, ruleId: rm ? parseInt(rm[1], 10) : null };
|
||||
}
|
||||
mod.log(`[DiscordMatching] Loaded ${Object.keys(battleFieldData).length} battlefield entries`);
|
||||
}
|
||||
|
||||
function getDungeonName(id) { return dungeonNames[id] || `Unknown (${id})`; }
|
||||
function getBFName(bfId) {
|
||||
const bf = battleFieldData[bfId]; const nid = bf ? bf.nameId : null;
|
||||
return nid ? (battleFieldNames[nid] || `Unknown (${bfId})`) : `Unknown (${bfId})`;
|
||||
}
|
||||
function getRoleInfo(instanceId, type) {
|
||||
const roleId = type === 1 ? (battleFieldData[instanceId] ? battleFieldData[instanceId].ruleId : null) : (dungeonRoleMap[instanceId] || 23);
|
||||
const tmpl = roleTemplates[roleId];
|
||||
if (!tmpl) mod.warn(`[DiscordMatching] No matching role template found for roleId ${roleId} (instance ${instanceId})`);
|
||||
return tmpl;
|
||||
}
|
||||
function makeStateKey(instanceId, type) { return (type === 1 ? "b_" : "d_") + instanceId; }
|
||||
|
||||
// Build plain text content
|
||||
function buildContent(mState, action) {
|
||||
const dungeons = [], bgs = [];
|
||||
for (const state of Object.values(mState)) {
|
||||
if (Object.keys(state.players).length === 0) continue;
|
||||
if (state.type === 1) bgs.push(state); else dungeons.push(state);
|
||||
}
|
||||
const allPlayers = new Set();
|
||||
for (const s of [...dungeons, ...bgs]) for (const n of Object.keys(s.players)) allPlayers.add(n);
|
||||
|
||||
const lines = [];
|
||||
lines.push("**Matching Queue**");
|
||||
lines.push("");
|
||||
lines.push(`**${allPlayers.size}** total player${allPlayers.size > 1 ? "s" : ""} in queue.`);
|
||||
lines.push("");
|
||||
|
||||
if (dungeons.length > 0) {
|
||||
dungeons.sort((a, b) => (a.name || "").localeCompare(b.name || ""));
|
||||
lines.push("**Instance Matching Queue**");
|
||||
lines.push("");
|
||||
const dp = new Set();
|
||||
for (const state of dungeons) for (const n of Object.keys(state.players)) dp.add(n);
|
||||
lines.push(`**${dp.size}** player${dp.size > 1 ? "s" : ""} currently in queue.`);
|
||||
lines.push("");
|
||||
for (const state of dungeons) {
|
||||
const groups = splitIntoGroups(state.players, state.tankLimit, state.dealerLimit, state.healerLimit, state.maxPlayers);
|
||||
for (let gi = 0; gi < groups.length; gi++) {
|
||||
const g = groups[gi]; const gc = Object.keys(g.players).length;
|
||||
const tl = state.tankLimit !== undefined ? state.tankLimit : (state.tankerMax || "?");
|
||||
const dl2 = state.dealerLimit !== undefined ? state.dealerLimit : (state.dealerMax || "?");
|
||||
const hl = state.healerLimit !== undefined ? state.healerLimit : (state.healerMax || "?");
|
||||
const rl = `T:${g.tankCount}/${tl} D:${g.dpsCount}/${dl2} H:${g.healerCount}/${hl}`;
|
||||
const lb = groups.length > 1 ? ` #${gi + 1}` : "";
|
||||
lines.push(`**${state.name}${lb}**`);
|
||||
lines.push(`${rl} [${gc}/${state.maxPlayers}]`);
|
||||
if (showPlayerNames) {
|
||||
for (const [n, p] of Object.entries(g.players)) lines.push(`**${n}** (${ROLE_FULL[p.role]})`);
|
||||
}
|
||||
lines.push("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bgs.length > 0) {
|
||||
bgs.sort((a, b) => (a.name || "").localeCompare(b.name || ""));
|
||||
lines.push("**Battleground Matching Queue**");
|
||||
lines.push("");
|
||||
const bp = new Set();
|
||||
for (const state of bgs) for (const n of Object.keys(state.players)) bp.add(n);
|
||||
lines.push(`**${bp.size}** player${bp.size > 1 ? "s" : ""} currently in queue.`);
|
||||
lines.push("");
|
||||
for (const state of bgs) {
|
||||
const entries = Object.entries(state.players); const bfTotal = state.maxPlayers * 2;
|
||||
let tc = 0, dc = 0, hc = 0;
|
||||
for (const [, p] of entries) { if (p.role === 0) tc++; else if (p.role === 1) dc++; else if (p.role === 2) hc++; }
|
||||
const fm = (cnt, min, max, lim) => { if (min !== undefined) return `${cnt}/${min}/${max || "?"}`; if (lim) return `${cnt}/${lim}`; return `${cnt}/?`; };
|
||||
const rl = `T:${fm(tc, state.tankerMin, state.tankerMax, state.tankLimit)} D:${fm(dc, state.dealerMin, state.dealerMax, state.dealerLimit)} H:${fm(hc, state.healerMin, state.healerMax, state.healerLimit)}`;
|
||||
lines.push(`**${state.name}**`);
|
||||
lines.push(`${rl} [${entries.length}/${bfTotal}]`);
|
||||
if (showPlayerNames) {
|
||||
for (const [n, p] of entries) lines.push(`**${n}** (${ROLE_FULL[p.role]})`);
|
||||
}
|
||||
lines.push("");
|
||||
}
|
||||
}
|
||||
|
||||
if (dungeons.length === 0 && bgs.length === 0) {
|
||||
lines.push("*No players currently in any instance queue.*");
|
||||
lines.push("");
|
||||
}
|
||||
|
||||
lines.push(`Last action: ${action} | ${new Date().toLocaleTimeString()}`);
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
function splitIntoGroups(players, tankLimit, dealerLimit, healerLimit, maxPlayers) {
|
||||
const partyGroups = new Map();
|
||||
for (const [name, p] of Object.entries(players)) {
|
||||
const pid = p.partyId || name;
|
||||
if (!partyGroups.has(pid)) partyGroups.set(pid, { players: {}, tankCount: 0, dpsCount: 0, healerCount: 0 });
|
||||
const grp = partyGroups.get(pid);
|
||||
grp.players[name] = { role: p.role };
|
||||
if (p.role === 0) grp.tankCount++; else if (p.role === 1) grp.dpsCount++; else if (p.role === 2) grp.healerCount++;
|
||||
}
|
||||
const sorted = [...partyGroups.values()].sort((a, b) => {
|
||||
const ar = a.healerCount + a.tankCount, br = b.healerCount + b.tankCount;
|
||||
if (br !== ar) return br - ar;
|
||||
return (b.tankCount + b.dpsCount + b.healerCount) - (a.tankCount + a.dpsCount + a.healerCount);
|
||||
});
|
||||
const groups = [];
|
||||
for (const party of sorted) {
|
||||
let placed = false;
|
||||
for (const g of groups) {
|
||||
const nt = g.tankCount + party.tankCount, nd = g.dpsCount + party.dpsCount, nh = g.healerCount + party.healerCount;
|
||||
if (nt <= tankLimit && nd <= dealerLimit && nh <= healerLimit && (nt + nd + nh) <= maxPlayers) {
|
||||
Object.assign(g.players, party.players); g.tankCount = nt; g.dpsCount = nd; g.healerCount = nh; placed = true; break;
|
||||
}
|
||||
}
|
||||
if (!placed) groups.push({ players: { ...party.players }, tankCount: party.tankCount, dpsCount: party.dpsCount, healerCount: party.healerCount });
|
||||
}
|
||||
return groups;
|
||||
}
|
||||
|
||||
// Main update: build text -> send with mutex (one HTTP request at a time)
|
||||
function sendDiscordUpdate(action) {
|
||||
if (!webhookUrl) return;
|
||||
|
||||
// If already sending, just queue the next action
|
||||
if (G.sending) {
|
||||
G.pendingAction = action;
|
||||
return;
|
||||
}
|
||||
|
||||
G.sending = true;
|
||||
|
||||
const text = buildContent(G.matchState, action).substring(0, 2000);
|
||||
const payload = JSON.stringify({ content: text });
|
||||
const isEdit = !!G.lastMessageId;
|
||||
const url = isEdit ? `${webhookUrl}/messages/${G.lastMessageId}` : `${webhookUrl}?wait=true`;
|
||||
|
||||
const opts = {
|
||||
method: isEdit ? "PATCH" : "POST",
|
||||
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(payload) }
|
||||
};
|
||||
|
||||
function onDone() {
|
||||
G.sending = false;
|
||||
if (G.pendingAction !== null) {
|
||||
const next = G.pendingAction;
|
||||
G.pendingAction = null;
|
||||
sendDiscordUpdate(next);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const req = https.request(url, opts, (res) => {
|
||||
let body = "";
|
||||
res.on("data", (chunk) => (body += chunk));
|
||||
|
||||
if (res.statusCode === 404 && isEdit) {
|
||||
res.on("end", () => {
|
||||
G.lastMessageId = null;
|
||||
G.sending = false;
|
||||
sendDiscordUpdate(action);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
res.on("end", () => {
|
||||
if (res.statusCode === 200 || res.statusCode === 204) {
|
||||
if (!isEdit && res.statusCode === 200) {
|
||||
try { const d = JSON.parse(body); if (d && d.id) G.lastMessageId = d.id; } catch (_) {}
|
||||
}
|
||||
} else {
|
||||
mod.error(`[DiscordMatching] Webhook error ${res.statusCode}: ${body.substring(0, 200)}`);
|
||||
}
|
||||
onDone();
|
||||
});
|
||||
});
|
||||
|
||||
req.on("error", (err) => {
|
||||
mod.error(`[DiscordMatching] Webhook request error: ${err.message}`);
|
||||
onDone();
|
||||
});
|
||||
|
||||
req.write(payload);
|
||||
req.end();
|
||||
} catch (e) {
|
||||
mod.error(`[DiscordMatching] Webhook exception: ${e.message}`);
|
||||
onDone();
|
||||
}
|
||||
}
|
||||
|
||||
// ---------- INIT ----------
|
||||
if (!enabled) { mod.log("[DiscordMatching] Mod disabled"); return; }
|
||||
|
||||
loadDungeonNames(); loadDungeonMatching(); loadRoleTemplates(); loadBattleFieldNames(); loadBattleFieldData();
|
||||
|
||||
mod.log(`[DiscordMatching] Webhook: ${webhookUrl ? "Configured" : "NOT configured"}${G.lastMessageId ? " (msgId: " + G.lastMessageId + ")" : ""}`);
|
||||
if (!webhookUrl) mod.warn('[DiscordMatching] No webhook URL configured! Set "webhook" in module.config.json');
|
||||
|
||||
// ---------- HOOKS ----------
|
||||
try {
|
||||
mod.hook("C_ADD_INTER_PARTY_MATCH_POOL", "raw", () => {
|
||||
try {
|
||||
const pName = (mod.game && mod.game.me && mod.game.me.name) || knownPlayerName || "Unknown";
|
||||
if (pName !== "Unknown") knownPlayerName = pName;
|
||||
} catch (e) { mod.error(`[DiscordMatching] C_ADD error: ${e.message}`); }
|
||||
});
|
||||
mod.log("[DiscordMatching] Hooked C_ADD_INTER_PARTY_MATCH_POOL");
|
||||
} catch (e) { mod.warn(`[DiscordMatching] Could not hook C_ADD: ${e.message}`); }
|
||||
|
||||
try {
|
||||
mod.hook("C_DEL_INTER_PARTY_MATCH_POOL", 1, (event) => {
|
||||
try {
|
||||
const pName = knownPlayerName || (mod.game && mod.game.me && mod.game.me.name) || "";
|
||||
if (!pName) return true;
|
||||
const mState = G.matchState;
|
||||
const evType = event.type;
|
||||
let changed = false;
|
||||
// Remove only this player from queues matching evType
|
||||
for (const [key, state] of Object.entries(mState)) {
|
||||
if (evType === 2 || state.type === evType) {
|
||||
if (state.players[pName]) { delete state.players[pName]; changed = true; }
|
||||
}
|
||||
}
|
||||
if (changed) sendDiscordUpdate("REMOVE");
|
||||
} catch (e) { mod.error(`[DiscordMatching] C_DEL error: ${e.message}`); }
|
||||
return true;
|
||||
});
|
||||
mod.log("[DiscordMatching] Hooked C_DEL_INTER_PARTY_MATCH_POOL");
|
||||
} catch (e) { mod.warn(`[DiscordMatching] Could not hook C_DEL: ${e.message}`); }
|
||||
|
||||
try {
|
||||
mod.hook("S_ADD_INTER_PARTY_MATCH_POOL", 1, (event) => {
|
||||
try {
|
||||
const type = event.type || 0;
|
||||
if (type !== 0 && type !== 1) return true;
|
||||
const mState = G.matchState;
|
||||
let changed = false;
|
||||
for (const player of event.players) {
|
||||
const pName = player.name || "Unknown";
|
||||
for (const rawId of event.instances) {
|
||||
const id = rawId.id;
|
||||
const key = makeStateKey(id, type);
|
||||
if (!mState[key]) {
|
||||
const info = getRoleInfo(id, type);
|
||||
mState[key] = {
|
||||
name: type === 1 ? getBFName(id) : getDungeonName(id), type,
|
||||
maxPlayers: info.totalUser, tankLimit: info.tanker, dealerLimit: info.dealer, healerLimit: info.healer,
|
||||
tankerMin: info.tankerMin, tankerMax: info.tankerMax, dealerMin: info.dealerMin, dealerMax: info.dealerMax,
|
||||
healerMin: info.healerMin, healerMax: info.healerMax, players: {}
|
||||
};
|
||||
}
|
||||
if (!mState[key].players[pName]) { mState[key].players[pName] = { role: player.role, partyId: 0 }; changed = true; }
|
||||
}
|
||||
}
|
||||
if (changed) sendDiscordUpdate("ADD");
|
||||
} catch (e) { mod.error(`[DiscordMatching] S_ADD error: ${e.message}`); }
|
||||
return true;
|
||||
});
|
||||
mod.log("[DiscordMatching] Hooked S_ADD_INTER_PARTY_MATCH_POOL");
|
||||
} catch (e) { mod.warn(`[DiscordMatching] Could not hook S_ADD: ${e.message}`); }
|
||||
|
||||
try {
|
||||
mod.hook("S_DEL_INTER_PARTY_MATCH_POOL", 1, (event) => {
|
||||
try {
|
||||
const evType = event.type;
|
||||
if (evType !== 0 && evType !== 1 && evType !== 2) return true;
|
||||
// C_DEL already handles removal by player name for normal leaves.
|
||||
// When the game closes abruptly, the server sends S_DEL with type=2
|
||||
// (remove from all pools). Handle this to clean up the Discord queue.
|
||||
const pName = knownPlayerName || (mod.game && mod.game.me && mod.game.me.name) || "";
|
||||
if (!pName) return true;
|
||||
const mState = G.matchState;
|
||||
let changed = false;
|
||||
for (const [key, state] of Object.entries(mState)) {
|
||||
if (evType === 2 || state.type === evType) {
|
||||
if (state.players[pName]) { delete state.players[pName]; changed = true; }
|
||||
}
|
||||
}
|
||||
if (changed) sendDiscordUpdate("REMOVE");
|
||||
} catch (e) { mod.error(`[DiscordMatching] S_DEL error: ${e.message}`); }
|
||||
return true;
|
||||
});
|
||||
mod.log("[DiscordMatching] Hooked S_DEL_INTER_PARTY_MATCH_POOL");
|
||||
} catch (e) { mod.warn(`[DiscordMatching] Could not hook S_DEL: ${e.message}`); }
|
||||
|
||||
mod.log("[DiscordMatching] Mod loaded successfully");
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"enabled": true,
|
||||
"webhook": "https://discord.com/api/webhooks/...",
|
||||
"showPlayerNames": false
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"disableAutoUpdate": true,
|
||||
"name": "discord-matching-relay",
|
||||
"author": "Archgeus",
|
||||
"description": "Relays instance matching queue activity (add/remove) to Discord via webhook.",
|
||||
"options": {
|
||||
"guiName": "Discord Matching Relay"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user