Explorar el Código

Implemented the Battleground Queue System (#3995)

* Fixes #1310.
* Added a battle config which allows toggling of the Battleground Queue client feature and also toggles between the modes of scripts.
* Added script commands bg_reserve, bg_unbook, and bg_desert.
* Removed old custom Battleground scripts.
Thanks to @Lemongrass3110, @Locien, @secretdataz, @InusualZ, @Normynator, @Atemo, @iubantot, @admkakaroto, and @noobzter003!
Aleos hace 5 años
padre
commit
2931c00bd4
Se han modificado 44 ficheros con 2671 adiciones y 4788 borrados
  1. 4 0
      conf/battle/feature.conf
  2. 5 0
      conf/msg_conf/map_msg.conf
  3. 174 0
      db/battleground_db.yml
  4. 52 0
      db/import-tmpl/battleground_db.yml
  5. 44 3
      doc/script_commands.txt
  6. 53 24
      npc/battleground/flavius/flavius01.txt
  7. 53 24
      npc/battleground/flavius/flavius02.txt
  8. 35 58
      npc/battleground/flavius/flavius_enter.txt
  9. 42 14
      npc/battleground/kvm/kvm01.txt
  10. 41 13
      npc/battleground/kvm/kvm02.txt
  11. 40 12
      npc/battleground/kvm/kvm03.txt
  12. 65 34
      npc/battleground/kvm/kvm_enter.txt
  13. 4 10
      npc/battleground/kvm/kvm_item_pay.txt
  14. 55 24
      npc/battleground/tierra/tierra01.txt
  15. 55 24
      npc/battleground/tierra/tierra02.txt
  16. 35 62
      npc/battleground/tierra/tierra_enter.txt
  17. 0 1288
      npc/custom/battleground/unofficial/bg_common.txt
  18. 0 428
      npc/custom/battleground/unofficial/bg_flavius_01.txt
  19. 0 428
      npc/custom/battleground/unofficial/bg_flavius_02.txt
  20. 0 378
      npc/custom/battleground/unofficial/bg_kvm01.txt
  21. 0 378
      npc/custom/battleground/unofficial/bg_kvm02.txt
  22. 0 378
      npc/custom/battleground/unofficial/bg_kvm03.txt
  23. 0 476
      npc/custom/battleground/unofficial/bg_tierra_01.txt
  24. 0 476
      npc/custom/battleground/unofficial/bg_tierra_02.txt
  25. 13 0
      src/common/utilities.hpp
  26. 39 0
      src/map/battle.cpp
  27. 1 0
      src/map/battle.hpp
  28. 1286 131
      src/map/battleground.cpp
  29. 122 23
      src/map/battleground.hpp
  30. 202 4
      src/map/clif.cpp
  31. 10 2
      src/map/clif.hpp
  32. 13 1
      src/map/clif_packetdb.hpp
  33. 1 0
      src/map/map-server.vcxproj
  34. 6 3
      src/map/map.cpp
  35. 1 1
      src/map/mob.hpp
  36. 14 4
      src/map/pc.cpp
  37. 7 1
      src/map/pc.hpp
  38. 159 76
      src/map/script.cpp
  39. 11 0
      src/map/script_constants.hpp
  40. 3 0
      src/map/skill.cpp
  41. 20 4
      src/map/status.cpp
  42. 3 0
      src/map/status.hpp
  43. 2 5
      tools/ci/npc.bat
  44. 1 1
      tools/ci/npc.sh

+ 4 - 0
conf/battle/feature.conf

@@ -59,6 +59,10 @@ feature.autotrade_sit: 1
 // Delay in miliseconds to open vending/buyingsotre after player logged in.
 feature.autotrade_open_delay: 5000
 
+// Battlegrounds queue interface. Makes it possible to queue for a battleground anywhere using the battle menu.
+// Requires: 2012-04-10aRagexe or later
+feature.bgqueue: on
+
 // Roulette (Note 1)
 // Requires: 2014-10-22bRagexe or later
 feature.roulette: on

+ 5 - 0
conf/msg_conf/map_msg.conf

@@ -353,6 +353,11 @@
 // 334: Thirty-Four Castles
 334: Total Domination
 
+// Battlegrounds Queue
+337: You may not join a battleground queue when you're in a battleground map.
+338: You can't apply to a battleground queue due to recently deserting a battleground. Time remaining: %d minutes and %d seconds.
+339: You can't apply to a battleground queue for %d seconds due to recently leaving one.
+
 // Templates for @who output
 343: Name: %s
 344: (%s)

+ 174 - 0
db/battleground_db.yml

@@ -0,0 +1,174 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Battleground Queue Database
+###########################################################################
+#
+# Battleground Queue Settings
+#
+###########################################################################
+# - Id                Unique ID for the battleground type.
+#   Name              Name of the battleground. Must be the exact same as in the client for players to be able to join.
+#   MinPlayers        Minimum number of players required on each team. (Default: 1)
+#   MaxPlayers        Maximum number of players on each team. (Default: MAX_BG_MEMBERS / 2)
+#   MinLevel          Minimum level required to join the battleground. (Default: 1)
+#   MaxLevel          Maximum level to join the battleground. (Default: MAX_LEVEL value)
+#   Deserter          Amount of time in seconds a player is marked deserter. (Default: 600)
+#   StartDelay        Amount of time in seconds once a queue is filled before a start message is sent to players. (Default: 30)
+#   Locations:        Battleground location settings.
+#     - Map           The map on which the battleground will be played.
+#       StartEvent    NPC event triggered when the battleground starts.
+#       TeamA:        TeamA settings.
+#         RespawnX    X coordinate for warping on death.
+#         RespawnY    Y coordinate for warping on death.
+#         DeathEvent  NPC event triggered when a player dies.
+#         QuitEvent   NPC event triggered when a player quits.
+#         Variable    Name of BG ID variable used in the battleground script.
+#       TeamB:        TeamB settings.
+#         RespawnX    X coordinate for warping on death.
+#         RespawnY    Y coordinate for warping on death.
+#         DeathEvent  NPC event triggered when a player dies.
+#         QuitEvent   NPC event triggered when a player quits.
+#         Variable    Name of BG ID variable used in the battleground script.
+###########################################################################
+
+Header:
+  Type: BATTLEGROUND_DB
+  Version: 1
+
+Body:
+  - Id: 1
+    Name: "Tierra Gorge"
+    MinPlayers: 6
+    MinLevel: 80
+    Locations:
+      - Map: "bat_a01"
+        StartEvent: "start#bat_a01::OnReadyCheck"
+        TeamA:
+          RespawnX: 50
+          RespawnY: 374
+          QuitEvent: "start#bat_a01::OnGuillaumeQuit"
+          Variable: "$@TierraBG1_id1"
+        TeamB:
+          RespawnX: 42
+          RespawnY: 16
+          QuitEvent: "start#bat_a01::OnCroixQuit"
+          Variable: "$@TierraBG1_id2"
+      - Map: "bat_a02"
+        StartEvent: "start#bat_a02::OnReadyCheck"
+        TeamA:
+          RespawnX: 50
+          RespawnY: 374
+          QuitEvent: "start#bat_a02::OnGuillaumeQuit"
+          Variable: "$@TierraBG2_id1"
+        TeamB:
+          RespawnX: 42
+          RespawnY: 16
+          QuitEvent: "start#bat_a02::OnCroixQuit"
+          Variable: "$@TierraBG2_id2"
+  - Id: 2
+    Name: "Flavius"
+    MinPlayers: 6
+    MinLevel: 80
+    Locations:
+      - Map: "bat_b01"
+        StartEvent: "start#bat_b01::OnReadyCheck"
+        TeamA:
+          RespawnX: 10
+          RespawnY: 290
+          QuitEvent: "start#bat_b01::OnGuillaumeQuit"
+          Variable: "$@FlaviusBG1_id1"
+        TeamB:
+          RespawnX: 390
+          RespawnY: 10
+          QuitEvent: "start#bat_b01::OnCroixQuit"
+          Variable: "$@FlaviusBG1_id2"
+      - Map: "bat_b02"
+        StartEvent: "start#bat_b02::OnReadyCheck"
+        TeamA:
+          RespawnX: 10
+          RespawnY: 290
+          QuitEvent: "start#bat_b02::OnGuillaumeQuit"
+          Variable: "$@FlaviusBG2_id1"
+        TeamB:
+          RespawnX: 390
+          RespawnY: 10
+          QuitEvent: "start#bat_b02::OnCroixQuit"
+          Variable: "$@FlaviusBG2_id2"
+  - Id: 3
+    Name: "KVM (Level 80 and up)"
+    MinPlayers: 5
+    MinLevel: 80
+    Locations:
+      - Map: "bat_c01"
+        StartEvent: "KvM01_BG::OnStart"
+        TeamA:
+          RespawnX: 52
+          RespawnY: 129
+          DeathEvent: "KvM01_BG::OnGuillaumeDie"
+          QuitEvent: "KvM01_BG::OnGuillaumeQuit"
+          Variable: "$@KvM01BG_id1"
+        TeamB:
+          RespawnX: 147
+          RespawnY: 55
+          DeathEvent: "KvM01_BG::OnCroixDie"
+          QuitEvent: "KvM01_BG::OnCroixQuit"
+          Variable: "$@KvM01BG_id2"
+  - Id: 4
+    Name: "KVM (Level 60~79)"
+    MinPlayers: 5
+    MinLevel: 60
+    MaxLevel: 79
+    Locations:
+      - Map: "bat_c02"
+        StartEvent: "KvM02_BG::OnStart"
+        TeamA:
+          RespawnX: 52
+          RespawnY: 129
+          DeathEvent: "KvM02_BG::OnGuillaumeDie"
+          QuitEvent: "KvM02_BG::OnGuillaumeQuit"
+          Variable: "$@KvM02BG_id1"
+        TeamB:
+          RespawnX: 147
+          RespawnY: 55
+          DeathEvent: "KvM02_BG::OnCroixDie"
+          QuitEvent: "KvM02_BG::OnCroixQuit"
+          Variable: "$@KvM02BG_id2"
+  - Id: 5
+    Name: "KVM (Level 59 and below"
+    MinPlayers: 5
+    MaxLevel: 59
+    Locations:
+      - Map: "bat_c03"
+        StartEvent: "KvM03_BG::OnStart"
+        TeamA:
+          RespawnX: 52
+          RespawnY: 129
+          DeathEvent: "KvM03_BG::OnGuillaumeDie"
+          QuitEvent: "KvM03_BG::OnGuillaumeQuit"
+          Variable: "$@KvM03BG_id1"
+        TeamB:
+          RespawnX: 147
+          RespawnY: 55
+          DeathEvent: "KvM03_BG::OnCroixDie"
+          QuitEvent: "KvM03_BG::OnCroixQuit"
+          Variable: "$@KvM03BG_id2"
+
+Footer:
+  Imports:
+  - Path: db/import/battleground_db.yml

+ 52 - 0
db/import-tmpl/battleground_db.yml

@@ -0,0 +1,52 @@
+# This file is a part of rAthena.
+#   Copyright(C) 2019 rAthena Development Team
+#   https://rathena.org - https://github.com/rathena
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###########################################################################
+# Battleground Queue Database
+###########################################################################
+#
+# Battleground Queue Settings
+#
+###########################################################################
+# - Id                Unique ID for the battleground type.
+#   Name              Name of the battleground. Must be the exact same as in the client for players to be able to join.
+#   MinPlayers        Minimum number of players required on each team. (Default: 1)
+#   MaxPlayers        Maximum number of players on each team. (Default: MAX_BG_MEMBERS / 2)
+#   MinLevel          Minimum level required to join the battleground. (Default: 1)
+#   MaxLevel          Maximum level to join the battleground. (Default: MAX_LEVEL value)
+#   Deserter          Amount of time in seconds a player is marked deserter. (Default: 600)
+#   StartDelay        Amount of time in seconds once a queue is filled before a start message is sent to players. (Default: 30)
+#   Locations:        Battleground location settings.
+#     - Map           The map on which the battleground will be played.
+#       StartEvent    NPC event triggered when the battleground starts.
+#       TeamA:        TeamA settings.
+#         RespawnX    X coordinate for warping on death.
+#         RespawnY    Y coordinate for warping on death.
+#         DeathEvent  NPC event triggered when a player dies.
+#         QuitEvent   NPC event triggered when a player quits.
+#         Variable    Name of BG ID variable used in the battleground script.
+#       TeamB:        TeamB settings.
+#         RespawnX    X coordinate for warping on death.
+#         RespawnY    Y coordinate for warping on death.
+#         DeathEvent  NPC event triggered when a player dies.
+#         QuitEvent   NPC event triggered when a player quits.
+#         Variable    Name of BG ID variable used in the battleground script.
+###########################################################################
+
+Header:
+  Type: BATTLEGROUND_DB
+  Version: 1

+ 44 - 3
doc/script_commands.txt

@@ -9305,7 +9305,8 @@ QMARK_PURPLE - Purple Marker
 *waitingroom2bg_single(<battle group>,{"<map name>",<x>,<y>{,"<npc name>"}});
 
 Adds the first waiting player from the chat room of the given NPC to an existing battleground group.
-The player will also be warped to the default spawn point of the battle group or to the specified coordinates <x> and <y> on the given <map>.
+The player will also be warped to the default spawn point of the battle group or to the specified coordinates
+<x> and <y> on the given <map>.
 
 ---------------------------------------
 
@@ -9349,7 +9350,8 @@ Returns battle group ID on success. Returns 0 on failure.
 
 *bg_join(<battle group>,{"<map name>",{<x>,<y>{,<char id>}});
 
-Adds an attached player or <char id> if specified to an existing battleground group. The player will also be warped to the default spawn point of the battle group or to the specified coordinates <x> and <y> on the given <map>.
+Adds an attached player or <char id> if specified to an existing battleground group. The player will also be warped
+to the default spawn point of the battle group or to the specified coordinates <x> and <y> on the given <map>.
 
 Returns true on success. Returns false on failure.
 
@@ -9357,7 +9359,8 @@ Returns true on success. Returns false on failure.
 
 *bg_team_setxy <Battle Group ID>,<x>,<y>;
 
-Updates the respawn point of the given Battle Group to x,y on the same map. <Battle Group ID> can be retrieved using getcharid(4).
+Updates the respawn point of the given Battle Group to x,y on the same map. <Battle Group ID> can be retrieved
+using getcharid(4).
 
 Example:
 	bg_team_setxy getcharid(4),56,212;
@@ -9366,6 +9369,29 @@ Example:
 
 ---------------------------------------
 
+*bg_reserve("<battleground_name>");
+
+Reserves a slot for the given Battleground for the Battleground UI System.
+
+Note: 'bg_reserve' and 'bg_unbook' prevent the Battlegrounds queue from joining players in an active Battleground.
+
+---------------------------------------
+
+*bg_unbook("<battleground_name>");
+
+Removes a spot for the given Battleground for the Battleground UI System.
+
+Note: 'bg_reserve' and 'bg_unbook' prevent the Battlegrounds queue from joining players in an active Battleground.
+
+---------------------------------------
+
+*bg_desert({<char_id>});
+
+Same as 'bg_leave' but slaps the player with a deserter status so they can't enter another queue for the time
+defined in battleground_db (10 minutes by default).
+
+---------------------------------------
+
 *bg_warp <Battle Group>,"<map name>",<x>,<y>;
 
 Similar to the 'warp' command.
@@ -9469,6 +9495,21 @@ mapflag	<map name>	battleground	2
 
 ---------------------------------------
 
+*bg_info("<battleground name>", <type>);
+
+Retrieves data related to given <battleground name> from the database. Requires feature.bgqueue
+to be enabled. <Type> can be one of the following:
+
+	BG_INFO_ID: Battleground ID.
+	BG_INFO_REQUIRED_PLAYERS: Required players to start a battleground (per side).
+	BG_INFO_MAX_PLAYERS: Maximum players allowed in a battleground.
+	BG_INFO_MIN_LEVEL: Minimum level allowed to join a battleground.
+	BG_INFO_MAX_LEVEL: Maximum level allowed to join a battleground.
+	BG_INFO_MAPS: Number of maps in a battleground. Stores an array of map names in @bgmaps[] and a count in @bgmapscount.
+	BG_INFO_DESERTER_TIME: Amount of time in seconds a player is marked deserter.
+
+---------------------------------------
+
 ====================
 |10.- Pet commands.|
 ====================

+ 53 - 24
npc/battleground/flavius/flavius01.txt

@@ -1,18 +1,12 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= BattleGround System - Flavius
-//===== By: ================================================== 
-//= L0ne_W0lf
-//===== Current Version: ===================================== 
-//= 1.7
-//===== Compatible With: ===================================== 
-//= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= Flavius Battleground.
 //= - Winning Team: 9 badges (11 if VIP)
 //= - Losing Team: 3 badges (5 if VIP)
-//===== Additional Comments: ================================= 
-//= 1.0 First Version.
+//===== Changelogs: ==========================================
+//= 1.0 First Version. [L0ne_W0lf]
 //= 1.1 Fixed pink crystal spawning as blue. [L0ne_W0lf]
 //= 1.2 Updated 'waitingroom' to support required zeny/lvl. [Kisuka]
 //= 1.3 Removed MaxLvl check in waitingrooms. Replaced setwall with setcell.
@@ -20,6 +14,7 @@
 //= 1.5 Added GM management function. [Euphy]
 //= 1.6 Added VIP features and created a reward function. [Euphy]
 //= 1.7 Made Crystals immune to attacks until Guardians are defeated. [Cydh/Aleos]
+//= 1.8 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
 //============================================================
 
 // Waiting Room NPCs
@@ -51,6 +46,8 @@ bat_room,2,151,3	script	#bat_b01_timer	844,{
 	end;
 
 OnInit:
+	if (getbattleflag("feature.bgqueue"))
+		end;
 OnEnable:
 	initnpctimer;
 	end;
@@ -61,14 +58,21 @@ OnStop:
 
 OnTimer1000:
 	stopnpctimer;
-	initnpctimer;
+	if (!getbattleflag("feature.bgqueue"))
+		initnpctimer;
 	set .@chk_bat_a01,getmapusers("bat_b01");
 	if (.@chk_bat_a01 < 1) {
 		set $@FlaviusBG1, 0;
 		if( $@FlaviusBG1_id1 ) { bg_destroy $@FlaviusBG1_id1; set $@FlaviusBG1_id1, 0; }
 		if( $@FlaviusBG1_id2 ) { bg_destroy $@FlaviusBG1_id2; set $@FlaviusBG1_id2, 0; }
-		donpcevent "start#bat_b01::OnReadyCheck";
+		if (getbattleflag("feature.bgqueue")) {
+			bg_unbook "bat_b01";
+			end;
+		} else
+			donpcevent "start#bat_b01::OnReadyCheck";
 	}
+	if (getbattleflag("feature.bgqueue"))
+		initnpctimer;
 	end;
 }
 
@@ -83,22 +87,26 @@ OnInit:
 OnReadyCheck:
 	if( $@FlaviusBG1 )
 		end;
-	set .@Guillaume, getwaitingroomstate(0,"Lieutenant Ator");
-	set .@Croix, getwaitingroomstate(0,"Lieutenant Thelokus");
-	if( !.@Guillaume && !.@Croix ) {
-		donpcevent "#bat_b01_timer::OnStop";
-		end;
+	if (!getbattleflag("feature.bgqueue")) {
+		set .@Guillaume, getwaitingroomstate(0,"Lieutenant Ator");
+		set .@Croix, getwaitingroomstate(0,"Lieutenant Thelokus");
+		if( !.@Guillaume && !.@Croix ) {
+			donpcevent "#bat_b01_timer::OnStop";
+			end;
+		}
+		if( .@Guillaume < 10 || .@Croix < 10 )
+			end;
 	}
-	if( .@Guillaume < 10 || .@Croix < 10 )
-		end;
 	set $@FlaviusBG1, 1;
 	set $@FlaviusBG1_Victory, 0;
 	set $@Croix_ScoreBG1, 0;
 	set $@Guill_ScoreBG1, 0;
 	bg_updatescore "bat_b01",$@Guill_ScoreBG1,$@Croix_ScoreBG1;
 
-	donpcevent "Lieutenant Ator::OnEnterBG";
-	donpcevent "Lieutenant Thelokus::OnEnterBG";
+	if (!getbattleflag("feature.bgqueue")) {
+		donpcevent "Lieutenant Ator::OnEnterBG";
+		donpcevent "Lieutenant Thelokus::OnEnterBG";
+	}
 	donpcevent "OBJ#bat_b01_a::OnKill";
 	donpcevent "OBJ#bat_b01_a::OnEnable";
 	donpcevent "OBJ#bat_b01_b::OnKill";
@@ -142,7 +150,10 @@ OnReset:
 
 OnGuillaumeQuit:
 OnCroixQuit:
-	bg_leave;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+	else
+		bg_leave;
 	end;
 
 OnTimer10000:
@@ -405,7 +416,8 @@ bat_b01,10,294,3	script	Guillaume Vintenar#b01_a	934,{
 			callfunc "F_BG_Badge",0,"Guillaume","Flavius";
 	}
 	bg_leave;
-	warp "bat_room",154,150;
+	if (!getbattleflag("feature.bgqueue"))
+		warp "bat_room",154,150;
 	end;
 
 OnInit:
@@ -421,7 +433,8 @@ bat_b01,389,14,3	script	Croix Vintenar#b01_b	934,{
 			callfunc "F_BG_Badge",0,"Croix","Flavius";
 	}
 	bg_leave;
-	warp "bat_room",154,150;
+	if (!getbattleflag("feature.bgqueue"))
+		warp "bat_room",154,150;
 	end;
 
 OnInit:
@@ -579,3 +592,19 @@ bat_b01,1,10,3	script	Release all#b01	81,{
 		}
 	}
 }
+
+// BG Queue makes these scripts useless
+-	script	BGQueueInit#flavius01	-1,{
+	end;
+
+OnInit:
+	if (getbattleflag("feature.bgqueue")) {
+		unloadnpc "Lieutenant Ator";
+		unloadnpc "Lieutenant Thelokus";
+		unloadnpc "back_bgroomb01a";
+		unloadnpc "back_bgroomb01b";
+		unloadnpc "A_CODE#bat_b01";
+		unloadnpc "B_CODE#bat_b01";
+	}
+	end;
+}

+ 53 - 24
npc/battleground/flavius/flavius02.txt

@@ -1,18 +1,12 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= BattleGround System - Flavius Second
-//===== By: ================================================== 
-//= L0ne_W0lf
-//===== Current Version: ===================================== 
-//= 1.8
-//===== Compatible With: ===================================== 
-//= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= Flavius Battleground.
 //= - Winning Team: 9 badges (11 if VIP)
 //= - Losing Team: 3 badges (5 if VIP)
-//===== Additional Comments: ================================= 
-//= 1.0 First Version.
+//===== Changelogs: ==========================================
+//= 1.0 First Version. [L0ne_W0lf]
 //= 1.1 Fixed NPCs being called for waiting rooms. (bugreport:4395)
 //= 1.2 Fixed pink crystal spawning as blue. [L0ne_W0lf]
 //= 1.3 Updated 'waitingroom' to support required zeny/lvl. [Kisuka]
@@ -21,6 +15,7 @@
 //= 1.6 Added GM management function. [Euphy]
 //= 1.7 Added VIP features and created a reward function. [Euphy]
 //= 1.8 Made Crystals immune to attacks until Guardians are defeated. [Cydh/Aleos]
+//= 1.9 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
 //============================================================
 
 // Waiting Room NPCs
@@ -52,6 +47,8 @@ bat_room,2,151,3	script	#bat_b02_timer	844,{
 	end;
 
 OnInit:
+	if (getbattleflag("feature.bgqueue"))
+		end;
 OnEnable:
 	initnpctimer;
 	end;
@@ -62,14 +59,21 @@ OnStop:
 
 OnTimer1000:
 	stopnpctimer;
-	initnpctimer;
+	if (!getbattleflag("feature.bgqueue"))
+		initnpctimer;
 	set .@chk_bat_a01,getmapusers("bat_b02");
 	if (.@chk_bat_a01 < 1) {
 		set $@FlaviusBG2, 0;
 		if( $@FlaviusBG2_id1 ) { bg_destroy $@FlaviusBG2_id1; set $@FlaviusBG2_id1, 0; }
 		if( $@FlaviusBG2_id2 ) { bg_destroy $@FlaviusBG2_id2; set $@FlaviusBG2_id2, 0; }
-		donpcevent "start#bat_b02::OnReadyCheck";
+		if (getbattleflag("feature.bgqueue")) {
+			bg_unbook "bat_b01";
+			end;
+		} else
+			donpcevent "start#bat_b01::OnReadyCheck";
 	}
+	if (getbattleflag("feature.bgqueue"))
+		initnpctimer;
 	end;
 }
 
@@ -84,22 +88,26 @@ OnInit:
 OnReadyCheck:
 	if( $@FlaviusBG2 )
 		end;
-	set .@Guillaume, getwaitingroomstate(0,"Lieutenant Huvas");
-	set .@Croix, getwaitingroomstate(0,"Lieutenant Yukon");
-	if( !.@Guillaume && !.@Croix ) {
-		donpcevent "#bat_b02_timer::OnStop";
-		end;
+	if (!getbattleflag("feature.bgqueue")) {
+			set .@Guillaume, getwaitingroomstate(0,"Lieutenant Huvas");
+		set .@Croix, getwaitingroomstate(0,"Lieutenant Yukon");
+		if( !.@Guillaume && !.@Croix ) {
+			donpcevent "#bat_b02_timer::OnStop";
+			end;
+		}
+		if( .@Guillaume < 10 || .@Croix < 10 )
+			end;
 	}
-	if( .@Guillaume < 10 || .@Croix < 10 )
-		end;
 	set $@FlaviusBG2, 1;
 	set $@FlaviusBG2_Victory, 0;
 	set $@Croix_ScoreBG2, 0;
 	set $@Guill_ScoreBG2, 0;
 
 	bg_updatescore "bat_b02",$@Guill_ScoreBG2,$@Croix_ScoreBG2;
-	donpcevent "Lieutenant Huvas::OnEnterBG";
-	donpcevent "Lieutenant Yukon::OnEnterBG";
+	if (!getbattleflag("feature.bgqueue")) {
+		donpcevent "Lieutenant Huvas::OnEnterBG";
+		donpcevent "Lieutenant Yukon::OnEnterBG";
+	}
 	donpcevent "OBJ#bat_b02_a::OnKill";
 	donpcevent "OBJ#bat_b02_a::OnEnable";
 	donpcevent "OBJ#bat_b02_b::OnKill";
@@ -143,7 +151,10 @@ OnReset:
 
 OnGuillaumeQuit:
 OnCroixQuit:
-	bg_leave;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+	else
+		bg_leave;
 	end;
 
 OnTimer10000:
@@ -406,7 +417,8 @@ bat_b02,10,294,3	script	Guillaume Vintenar#b02_a	934,{
 			callfunc "F_BG_Badge",0,"Guillaume","Flavius";
 	}
 	bg_leave;
-	warp "bat_room",154,150;
+	if (!getbattleflag("feature.bgqueue"))
+		warp "bat_room",154,150;
 	end;
 
 OnInit:
@@ -422,7 +434,8 @@ bat_b02,389,14,3	script	Croix Vintenar#b02_b	934,{
 			callfunc "F_BG_Badge",0,"Croix","Flavius";
 	}
 	bg_leave;
-	warp "bat_room",154,150;
+	if (!getbattleflag("feature.bgqueue"))
+		warp "bat_room",154,150;
 	end;
 
 OnInit:
@@ -580,3 +593,19 @@ bat_b02,1,10,3	script	Release all#b02	81,{
 		}
 	}
 }
+
+// BG Queue makes these scripts useless
+-	script	BGQueueInit#flavius02	-1,{
+	end;
+
+OnInit:
+	if (getbattleflag("feature.bgqueue")) {
+		unloadnpc "Lieutenant Huvas";
+		unloadnpc "Lieutenant Yukon";
+		unloadnpc "back_bgroomb02a";
+		unloadnpc "back_bgroomb02b";
+		unloadnpc "A_CODE#bat_b02";
+		unloadnpc "B_CODE#bat_b02";
+	}
+	end;
+}

+ 35 - 58
npc/battleground/flavius/flavius_enter.txt

@@ -1,21 +1,18 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= BattleGround System - Flavius Entrance NPCs
-//===== By: ================================================== 
-//= L0ne_W0lf
-//===== Current Version: ===================================== 
-//= 1.0
-//===== Compatible With: ===================================== 
-//= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= Flavius Battleground Entrance NPCs
-//===== Additional Comments: ================================= 
-//= 1.0 First Version.
+//===== Changelogs: ==========================================
+//= 1.0 First Version. [L0ne_W0lf]
+//= 1.1 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
 //============================================================
 
 // Flavius Officer - Guillaume
 //============================================================
 bat_room,133,178,5	script	Flavius Officer#01a	418,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	if (checkweight(1201,1) == 0) {
 		mes "- Wait a minute !! -";
 		mes "- Currently you're carrying -";
@@ -83,6 +80,8 @@ bat_room,133,178,5	script	Flavius Officer#01a	418,{
 }
 
 bat_room,133,121,1	script	Flavius Officer#01b	414,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	if (checkweight(1201,1) == 0) {
 		mes "- Wait a minute !! -";
 		mes "- Currently you're carrying -";
@@ -163,35 +162,22 @@ bat_room,135,178,5	script	Guillaume Knight#3	417,{
 	mes "The crystals are immune to every type of skill; your physical attacks are the only choice for destroying your enemy's crystal.";
 	next;
 	mes "[Guillaume Knight]";
-	mes "Please remember: when you join a battle, you will be receiving a token which indicates the set duration for which you cannot participate in the same type of battle.";
-	mes "You may check the duration by pressing the Alt+U keys.";
+	if (getbattleflag("feature.bgqueue"))
+		mes "If you are ready, start by clicking the ^0000FFbattle button from the interface^000000.";
+	else {
+		mes "Please remember: when you join a battle, you will be receiving a token which indicates the set duration for which you cannot participate in the same type of battle.";
+		mes "You may check the duration by pressing the Alt+U keys.";
+	}
 	next;
 	mes "[Guillaume Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
+	if (getbattleflag("feature.bgqueue"))
+		mes "Please bear in mind once you cancel, ^0000FFyou may not reapply for 1 minute^000000!";
+	else
+		mes "Are you ready for battle? Then apply with the recruiter next to me!";
 	close;
 }
 
-bat_room,151,178,5	script	Guillaume Knight#4	417,{
-	mes "[Guillaume Knight]";
-	mes "The objective of the Flavius Battle is to score 2 points before your enemy by destroying their crystal.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The crystals for both armies are protected by special barricades that cannot be destroyed by direct attacks.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "But they can be removed by destroying the Guardians that protect the enemy army base.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The crystals are immune to every type of skill; your physical attacks are the only choice for destroying your enemy's crystal.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Please remember: when you join a battle, you will be receiving a token which indicates the set duration for which you cannot participate in the same type of battle.";
-	mes "You may check the duration by pressing the Alt+U keys.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
+bat_room,151,178,5	duplicate(Guillaume Knight#3)	Guillaume Knight#4	417
 
 bat_room,135,121,1	script	Croix Knight#3	413,{
 	mes "[Croix Knight]";
@@ -207,39 +193,28 @@ bat_room,135,121,1	script	Croix Knight#3	413,{
 	mes "The crystals are immune to every type of skill; your physical attacks are the only choice for destroying your enemy's crystal.";
 	next;
 	mes "[Croix Knight]";
-	mes "Please remember: when you join a battle, you will be receiving a token which indicates the set duration for which you cannot participate in the same type of battle.";
-	mes "You may check the duration by pressing the Alt+U keys.";
+	if (getbattleflag("feature.bgqueue"))
+		mes "If you are ready, start by clicking the ^0000FFbattle button from the interface^000000.";
+	else {
+		mes "Please remember: when you join a battle, you will be receiving a token which indicates the set duration for which you cannot participate in the same type of battle.";
+		mes "You may check the duration by pressing the Alt+U keys.";
+	}
 	next;
 	mes "[Croix Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
+	if (getbattleflag("feature.bgqueue"))
+		mes "Please bear in mind once you cancel, ^0000FFyou may not reapply for 1 minute^000000!";
+	else
+		mes "Are you ready for battle? Then apply with the recruiter next to me!";
 	close;
 }
 
-bat_room,151,121,1	script	Croix Knight#4	413,{
-	mes "[Croix Knight]";
-	mes "The objective of the Flavius Battle is to score 2 points before your enemy by destroying their crystal.";
-	next;
-	mes "[Croix Knight]";
-	mes "The crystals for both armies are protected by special barricades that cannot be destroyed by direct attacks.";
-	next;
-	mes "[Croix Knight]";
-	mes "But they can be removed by destroying the Guardians that protect the enemy army base.";
-	next;
-	mes "[Croix Knight]";
-	mes "The crystals are immune to every type of skill; your physical attacks are the only choice for destroying your enemy's crystal.";
-	next;
-	mes "[Croix Knight]";
-	mes "Please remember: when you join a battle, you will be receiving a token which indicates the set duration for which you cannot participate in the same type of battle.";
-	mes "You may check the duration by pressing the Alt+U keys.";
-	next;
-	mes "[Croix Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
+bat_room,151,121,1	duplicate(Croix Knight#3)	Croix Knight#4	413
 
 // Flavius Officer - Croix
 //============================================================
 bat_room,148,178,5	script	Flavius Officer#02a	418,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	if (checkweight(1201,1) == 0) {
 		mes "- Wait a minute !! -";
 		mes "- Currently you're carrying -";
@@ -307,6 +282,8 @@ bat_room,148,178,5	script	Flavius Officer#02a	418,{
 }
 
 bat_room,148,121,1	script	Flavius Officer#02b	414,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	if (checkweight(1201,1) == 0) {
 		mes "- Wait a minute !! -";
 		mes "- Currently you're carrying -";

+ 42 - 14
npc/battleground/kvm/kvm01.txt

@@ -11,7 +11,8 @@
 //= 1.2 Upated some announces and dialogs from iRO.
 //=     Changed how the scoreboard works slightly.
 //=     Removed the areapercentheals, and minor things.
-//============================================================s
+//= 1.3 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
+//============================================================
 
 // Waiting Room NPCs
 //============================================================
@@ -81,7 +82,8 @@ OnDisable:
 	end;
 OnTouch:
 	set Bat_Team,1;
-	setquest 6025;
+	if (!getbattleflag("feature.bgqueue"))
+		setquest 6025;
 	end;
 }
 
@@ -98,7 +100,8 @@ OnDisable:
 	end;
 OnTouch:
 	set Bat_Team,2;
-	setquest 6025;
+	if (!getbattleflag("feature.bgqueue"))
+		setquest 6025;
 	end;
 }
 
@@ -117,7 +120,10 @@ OnInit:
 	end;
 
 OnGuillaumeQuit:
-	//set BG_Delay_Tick, gettimetick(2) + 1200;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+//	else
+//		set BG_Delay_Tick, gettimetick(2) + 1200;
 OnGuillaumeDie:
 	if( $@KvM01BG == 2 )
 	{
@@ -132,7 +138,10 @@ OnGuillaumeDie:
 	end;
 
 OnCroixQuit:
-	//set BG_Delay_Tick, gettimetick(2) + 1200;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+//	else
+//		set BG_Delay_Tick, gettimetick(2) + 1200;
 OnCroixDie:
 	if( $@KvM01BG == 2 )
 	{
@@ -204,14 +213,16 @@ OnTimer61000:
 	// Team Members
 	set .Guillaume_Count, bg_get_data($@KvM01BG_id1, 0);
 	set .Croix_Count, bg_get_data($@KvM01BG_id2, 0);
-	if( .Guillaume_Count < 5 || .Croix_Count < 5 )
-	{
-		set $@KvM01BG_Victory, 3;
-		set $@KvM01BG, 3;
-		mapannounce "bat_c01","There are not enough players to start the battle",1,0x696969;
-		stopnpctimer;
-		donpcevent "KvM01_BG::OnStop";
-		end;
+
+	if (!getbattleflag("feature.bgqueue")) {
+		if (.Guillaume_Count < 5 || .Croix_Count < 5) {
+			set $@KvM01BG_Victory, 3;
+			set $@KvM01BG, 3;
+			mapannounce "bat_c01","There are not enough players to start the battle",1,0x696969;
+			stopnpctimer;
+			donpcevent "KvM01_BG::OnStop";
+			end;
+		}
 	}
 	set $@KvM01BG, 2; // Playing
 	bg_warp $@KvM01BG_id1,"bat_c01",61,120;
@@ -316,6 +327,8 @@ OnTimer60000:
 	set $@KvM01BG_Victory, 0;
 	if( $@KvM01BG_id1 ) { bg_destroy $@KvM01BG_id1; set $@KvM01BG_id1, 0; }
 	if( $@KvM01BG_id2 ) { bg_destroy $@KvM01BG_id2; set $@KvM01BG_id2, 0; }
+	if (getbattleflag("feature.bgqueue"))
+		bg_unbook "bat_c01";
 	disablenpc "KVM Officer#KVM01A";
 	disablenpc "KVM Officer#KVM01B";
 	mapwarp "bat_c01","bat_room",154,150;
@@ -361,8 +374,23 @@ bat_c01,51,130,5	script	KVM Officer#KVM01A	419,{
 		}
 		bg_leave;
 		set Bat_Team,0;
-		warp "bat_room",154,150;
+		if (!getbattleflag("feature.bgqueue"))
+			warp "bat_room",154,150;
 	}
 	end;
 }
 bat_c01,148,53,1	duplicate(KVM Officer#KVM01A)	KVM Officer#KVM01B	415
+
+// BG Queue makes these scripts useless
+-	script	BGQueueInit#kvm01	-1,{
+	end;
+
+OnInit:
+	if (getbattleflag("feature.bgqueue")) {
+		unloadnpc "KvM01R_Guillaume";
+		unloadnpc "KvM01R_Croix";
+		unloadnpc "#kvm801";
+		unloadnpc "#kvm802";
+	}
+	end;
+}

+ 41 - 13
npc/battleground/kvm/kvm02.txt

@@ -13,6 +13,7 @@
 //=     Removed the areapercentheals, and minor things.
 //= 1.3 Fixed wrong names for disablenpc/enablenpc. [Ai4rei]
 //=     Fixed points in text and actual points differing.
+//= 1.4 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
 //============================================================
 
 // Waiting Room NPCs
@@ -81,7 +82,8 @@ OnDisable:
 	end;
 OnTouch:
 	set Bat_Team,1;
-	setquest 6025;
+	if (!getbattleflag("feature.bgqueue"))
+		setquest 6025;
 	end;
 }
 
@@ -98,7 +100,8 @@ OnDisable:
 	end;
 OnTouch:
 	set Bat_Team,2;
-	setquest 6025;
+	if (!getbattleflag("feature.bgqueue"))
+		setquest 6025;
 	end;
 }
 
@@ -117,7 +120,10 @@ OnInit:
 	end;
 
 OnGuillaumeQuit:
-	//set BG_Delay_Tick, gettimetick(2) + 1200;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+//	else
+//		set BG_Delay_Tick, gettimetick(2) + 1200;
 OnGuillaumeDie:
 	if( $@KvM02BG == 2 )
 	{
@@ -132,7 +138,10 @@ OnGuillaumeDie:
 	end;
 
 OnCroixQuit:
-	//set BG_Delay_Tick, gettimetick(2) + 1200;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+//	else
+//		set BG_Delay_Tick, gettimetick(2) + 1200;
 OnCroixDie:
 	if( $@KvM02BG == 2 )
 	{
@@ -204,14 +213,16 @@ OnTimer61000:
 	// Team Members
 	set .Guillaume_Count, bg_get_data($@KvM02BG_id1, 0);
 	set .Croix_Count, bg_get_data($@KvM02BG_id2, 0);
-	if( .Guillaume_Count < 5 || .Croix_Count < 5 )
-	{
-		set $@KvM02BG_Victory, 3;
-		set $@KvM02BG, 3;
-		mapannounce "bat_c02","There are not enough players to start the battle",1,0x808080;
-		stopnpctimer;
-		donpcevent "KvM02_BG::OnStop";
-		end;
+
+	if (!getbattleflag("feature.bgqueue")) {
+		if (.Guillaume_Count < 5 || .Croix_Count < 5) {
+			set $@KvM02BG_Victory, 3;
+			set $@KvM02BG, 3;
+			mapannounce "bat_c02","There are not enough players to start the battle",1,0x808080;
+			stopnpctimer;
+			donpcevent "KvM02_BG::OnStop";
+			end;
+		}
 	}
 	set $@KvM02BG, 2; // Playing
 	bg_warp $@KvM02BG_id1,"bat_c02",62,119;
@@ -316,6 +327,8 @@ OnTimer60000:
 	set $@KvM02BG_Victory, 0;
 	if( $@KvM02BG_id1 ) { bg_destroy $@KvM02BG_id1; set $@KvM02BG_id1, 0; }
 	if( $@KvM02BG_id2 ) { bg_destroy $@KvM02BG_id2; set $@KvM02BG_id2, 0; }
+	if (getbattleflag("feature.bgqueue"))
+		bg_unbook "bat_c02";
 	disablenpc "KVM Officer#KVM02A";
 	disablenpc "KVM Officer#KVM02B";
 	mapwarp "bat_c02","bat_room",154,150;
@@ -360,8 +373,23 @@ bat_c02,51,130,5	script	KVM Officer#KVM02A	419,{
 		}
 		bg_leave;
 		set Bat_Team,0;
-		warp "bat_room",154,150;
+		if (!getbattleflag("feature.bgqueue"))
+			warp "bat_room",154,150;
 		end;
 	}
 }
 bat_c02,148,53,1	duplicate(KVM Officer#KVM02A)	KVM Officer#KVM02B	415
+
+// BG Queue makes these scripts useless
+-	script	BGQueueInit#kvm02	-1,{
+	end;
+
+OnInit:
+	if (getbattleflag("feature.bgqueue")) {
+		unloadnpc "KvM02R_Guillaume";
+		unloadnpc "KvM02R_Croix";
+		unloadnpc "#kvm601";
+		unloadnpc "#kvm602";
+	}
+	end;
+}

+ 40 - 12
npc/battleground/kvm/kvm03.txt

@@ -12,6 +12,7 @@
 //=     Changed how the scoreboard works slightly.
 //=     Removed the areapercentheals, and minor things.
 //= 1.3 Fixed wrong names for disablenpc/enablenpc. [Ai4rei]
+//= 1.4 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
 //============================================================
 
 // Waiting Room NPCs
@@ -81,7 +82,8 @@ OnDisable:
 	end;
 OnTouch:
 	set Bat_Team,1;
-	setquest 6025;
+	if (!getbattleflag("feature.bgqueue"))
+		setquest 6025;
 	end;
 }
 
@@ -98,7 +100,8 @@ OnDisable:
 	end;
 OnTouch:
 	set Bat_Team,2;
-	setquest 6025;
+	if (!getbattleflag("feature.bgqueue"))
+		setquest 6025;
 	end;
 }
 
@@ -117,7 +120,10 @@ OnInit:
 	end;
 
 OnGuillaumeQuit:
-	//set BG_Delay_Tick, gettimetick(2) + 1200;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+//	else
+//		set BG_Delay_Tick, gettimetick(2) + 1200;
 OnGuillaumeDie:
 	if( $@KvM03BG == 2 ) {
 		set .Guillaume_Count, .Guillaume_Count - 1;
@@ -132,7 +138,10 @@ OnGuillaumeDie:
 	end;
 
 OnCroixQuit:
-	//set BG_Delay_Tick, gettimetick(2) + 1200;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+//	else
+//	set BG_Delay_Tick, gettimetick(2) + 1200;
 OnCroixDie:
 	if( $@KvM03BG == 2 ) {
 		set .Croix_Count, .Croix_Count - 1;
@@ -204,14 +213,16 @@ OnTimer61000:
 	// Team Members
 	set .Guillaume_Count, bg_get_data($@KvM03BG_id1, 0);
 	set .Croix_Count, bg_get_data($@KvM03BG_id2, 0);
-	if( .Guillaume_Count < 5 || .Croix_Count < 5 )
-	{
-		set $@KvM03BG_Victory, 3;
-		set $@KvM03BG, 3;
-		mapannounce "bat_c03","There are not enough players to start the battle",1,0xC0C0C0;
-		stopnpctimer;
-		donpcevent "KvM03_BG::OnStop";
-		end;
+
+	if (!getbattleflag("feature.bgqueue")) {
+		if (.Guillaume_Count < 5 || .Croix_Count < 5) {
+			set $@KvM03BG_Victory, 3;
+			set $@KvM03BG, 3;
+			mapannounce "bat_c03","There are not enough players to start the battle",1,0xC0C0C0;
+			stopnpctimer;
+			donpcevent "KvM03_BG::OnStop";
+			end;
+		}
 	}
 	set $@KvM03BG, 2; // Playing
 	bg_warp $@KvM03BG_id1,"bat_c03",62,119;
@@ -316,6 +327,8 @@ OnTimer60000:
 	set $@KvM03BG_Victory, 0;
 	if( $@KvM03BG_id1 ) { bg_destroy $@KvM03BG_id1; set $@KvM03BG_id1, 0; }
 	if( $@KvM03BG_id2 ) { bg_destroy $@KvM03BG_id2; set $@KvM03BG_id2, 0; }
+	if (getbattleflag("feature.bgqueue"))
+		bg_unbook "bat_c03";
 	disablenpc "KVM Officer#KVM03A";
 	disablenpc "KVM Officer#KVM03B";
 	mapwarp "bat_c03","bat_room",154,150;
@@ -361,8 +374,23 @@ bat_c03,51,130,5	script	KVM Officer#KVM03A	419,{
 		}
 		bg_leave;
 		set Bat_Team,0;
+	if (!getbattleflag("feature.bgqueue"))
 		warp "bat_room",154,150;
 	}
 	end;
 }
 bat_c03,148,53,1	duplicate(KVM Officer#KVM03A)	KVM Officer#KVM03B	415
+
+// BG Queue makes these scripts useless
+-	script	BGQueueInit#kvm03	-1,{
+	end;
+
+OnInit:
+	if (getbattleflag("feature.bgqueue")) {
+		unloadnpc "KvM03R_Guillaume";
+		unloadnpc "KvM03R_Croix";
+		unloadnpc "#kvm701";
+		unloadnpc "#kvm702";
+	}
+	end;
+}

+ 65 - 34
npc/battleground/kvm/kvm_enter.txt

@@ -1,25 +1,22 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= BattleGround System - KvM Entrance NPCs
-//===== By: ================================================== 
-//= L0ne_W0lf
-//===== Current Version: ===================================== 
-//= 1.1
-//===== Compatible With: ===================================== 
-//= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= Kreiger Von Midgard Battleground Entrance NPCs
 //= Original NPCs scrapped from bg_common.
-//===== Additional Comments: ================================= 
-//= 1.0 First Version.
+//===== Changelogs: ==========================================
+//= 1.0 First Version. [L0ne_W0lf]
 //= 1.1 Corrected some typos, and shifted messages around.
 //=     Corrected iRO style quest log entries, however it's
 //=     advisable that you not use them, as they conflict.
+//= 1.2 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
 //============================================================
 
 // KvM Officer - Guillaume
 //============================================================
 bat_room,164,178,5	script	KVM Mercenary Officer#1	418,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	/*
 	set .@kvm,checkquest(6026,PLAYTIME);
 	if ((.@kvm == 0) || (.@kvm == 1)) {
@@ -67,8 +64,12 @@ bat_room,167,178,5	script	Guillaume Knight#kvm	417,{
 	switch(select("Apply for KVM.:What is KVM?:How do I participate in KVM?:I want to know my Kreiger Points.")) {
 	case 1:
 		mes "[Guillaume Knight]";
-		mes "Applications are not available yet.";
-		mes "To apply, you need to go to a KVM Mercenary Officer.";
+		if (getbattleflag("feature.bgqueue"))
+			mes "If you are ready for battle, click the ^0000FFbattle button from the interface^000000 to apply for KVM battle!";
+		else {
+			mes "Applications are not available yet.";
+			mes "To apply, you need to go to a KVM Mercenary Officer.";
+		}
 		close;
 	case 2:
 		mes "[Guillaume Knight]";
@@ -93,21 +94,33 @@ bat_room,167,178,5	script	Guillaume Knight#kvm	417,{
 		close;
 	case 3:
 		mes "[Guillaume Knight]";
-		mes "Basically, KVM is a 5 on 5 battle.";
-		mes "First, you apply with a KVM receptionist, in a group or individually.";
+		if (getbattleflag("feature.bgqueue")) {
+			mes "Basically, KVM is a 3 on 3 battle.";
+			mes "Apply by clicking on the ^0000FFbattle button from the interface^000000, as a group or individually.";
+		} else {
+			mes "Basically, KVM is a 5 on 5 battle.";
+			mes "First, you apply with a KVM receptionist, in a group or individually.";
+		}
 		next;
 		mes "[Guillaume Knight]";
-		mes "Group applications are for when you intend to enter the KVM with your party members,";
+		if (getbattleflag("feature.bgqueue"))
+			mes "Group applications are for when you intend to enter the KVM with your party or guild members,";
+		else
+			mes "Group applications are for when you intend to enter the KVM with your party members,";
 		mes "and a personal application is for when you intend to enter the KVM individually.";
 		next;
 		mes "[Guillaume Knight]";
-		mes "Please apply with a KVM officer, and he will contact you later when you are in Prontera.";
-		next;
-		mes "[Guillaume Knight]";
-		mes "Then you enter and follow the instructions in the battlefield.";
-		next;
-		mes "[Guillaume Knight]";
-		mes "However, please be advised that unless you are in the KVM office, he cannot contact you.";
+		if (getbattleflag("feature.bgqueue"))
+			mes "Please be noted, once you cancel you ^0000FFcannot apply again for 1 minute^000000.";
+		else {
+			mes "Please apply with a KVM officer, and he will contact you later when you are in Prontera.";
+			next;
+			mes "[Guillaume Knight]";
+			mes "Then you enter and follow the instructions in the battlefield.";
+			next;
+			mes "[Guillaume Knight]";
+			mes "However, please be advised that unless you are in the KVM office, he cannot contact you.";
+		}
 		close;
 	case 4:
 		mes "[Guillaume Knight]";
@@ -120,6 +133,8 @@ bat_room,167,178,5	script	Guillaume Knight#kvm	417,{
 // KvM Officer - Croix
 //============================================================
 bat_room,164,121,1	script	KVM Mercenary Officer#2	414,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	/*
 	set .@kvm,checkquest(6025,PLAYTIME);
 	if ((.@kvm == 0) || (.@kvm == 1)) {
@@ -167,8 +182,12 @@ bat_room,167,121,1	script	Croix Knight#kvm	413,{
 	switch(select("Apply for KVM.:What is KVM?:How do I participate in KVM?:I want to know my Kreiger Points.")) {
 	case 1:
 		mes "[Croix Knight]";
-		mes "Applications are not available yet.";
-		mes "To apply, you need to go to a KVM Mercenary Officer.";
+		if (getbattleflag("feature.bgqueue"))
+			mes "If you are ready for battle, click the ^0000FFbattle button from the interface^000000 to apply for KVM battle!";
+		else {
+			mes "Applications are not available yet.";
+			mes "To apply, you need to go to a KVM Mercenary Officer.";
+		}
 		close;
 	case 2:
 		mes "[Croix Knight]";
@@ -193,21 +212,33 @@ bat_room,167,121,1	script	Croix Knight#kvm	413,{
 		close;
 	case 3:
 		mes "[Croix Knight]";
-		mes "Basically, KVM is a 5 on 5 battle.";
-		mes "First, you apply with a KVM receptionist, in a group or individually.";
+		if (getbattleflag("feature.bgqueue")) {
+			mes "Basically, KVM is a 3 on 3 battle.";
+			mes "Apply by clicking on the ^0000FFbattle button from the interface^000000, as a group or individually.";
+		} else {
+			mes "Basically, KVM is a 5 on 5 battle.";
+			mes "First, you apply with a KVM receptionist, in a group or individually.";
+		}
 		next;
 		mes "[Croix Knight]";
-		mes "Group applications are for when you intend to enter the KVM with your party members,";
+		if (getbattleflag("feature.bgqueue"))
+			mes "Group applications are for when you intend to enter the KVM with your party or guild members,";
+		else
+			mes "Group applications are for when you intend to enter the KVM with your party members,";
 		mes "and a personal application is for when you intend to enter the KVM individually.";
 		next;
 		mes "[Croix Knight]";
-		mes "Please apply with a KVM officer, and he will contact you later when you are in Prontera.";
-		next;
-		mes "[Croix Knight]";
-		mes "Then you enter and follow the instructions in the battlefield.";
-		next;
-		mes "[Croix Knight]";
-		mes "However, please be advised that unless you are in the KVM office, he cannot contact you.";
+		if (getbattleflag("feature.bgqueue"))
+			mes "Please be noted, once you cancel you ^0000FFcannot apply again for 1 minute^000000.";
+		else {
+			mes "Please apply with a KVM officer, and he will contact you later when you are in Prontera.";
+			next;
+			mes "[Croix Knight]";
+			mes "Then you enter and follow the instructions in the battlefield.";
+			next;
+			mes "[Croix Knight]";
+			mes "However, please be advised that unless you are in the KVM office, he cannot contact you.";
+		}
 		close;
 	case 4:
 		mes "[Croix Knight]";

+ 4 - 10
npc/battleground/kvm/kvm_item_pay.txt

@@ -1,12 +1,6 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= BattleGround System - KvM Item Dealer
-//===== By: ================================================== 
-//= L0ne_W0lf
-//===== Current Version: ===================================== 
-//= 1.0
-//===== Compatible With: ===================================== 
-//= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= Kreiger Von Midgard Battleground Point redemption NPC
 //= * NOTE * 
@@ -14,8 +8,8 @@
 //= keep track of points. This NPC when talked to will
 //= convert already-given tokens and convert them to points.
 //= under the player variable kvm_point.
-//===== Additional Comments: ================================= 
-//= 1.0 First Version.
+//===== Changelogs: ==========================================
+//= 1.0 First Version. [L0ne_W0lf]
 //============================================================
 
 bat_room,151,144,3	script	KVM Logistic Officer#a	734,{

+ 55 - 24
npc/battleground/tierra/tierra01.txt

@@ -1,24 +1,19 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= BattleGround System - Tierra Gorge
-//===== By: ================================================== 
-//= L0ne_W0lf
-//===== Current Version: ===================================== 
-//= 1.6
-//===== Compatible With: ===================================== 
-//= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= Tierra Gorge Battleground.
 //= - Winning Team: 3 badges (5 if VIP)
 //= - Losing Team: 1 badge (3 if VIP)
-//===== Additional Comments: ================================= 
-//= 1.0 First Version.
+//===== Changelogs: ==========================================
+//= 1.0 First Version. [L0ne_W0lf]
 //= 1.1 Corrected setwalls for barricades. [L0ne_W0lf]
 //= 1.2 Updated 'waitingroom' to support required zeny/lvl. [Kisuka]
 //= 1.3 Removed MaxLvl check in waitingrooms.
 //= 1.4 Label standardization. [Euphy]
 //= 1.5 Added GM management function. [Euphy]
 //= 1.6 Added VIP features and created a reward function. [Euphy]
+//= 1.7 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
 //============================================================
 
 // Waiting Room NPCs
@@ -51,6 +46,8 @@ bat_room,1,151,3	script	#bat_a01_timer	844,{
 	end;
 
 OnInit:
+	if (getbattleflag("feature.bgqueue"))
+		end;
 OnEnable:
 	initnpctimer;
 	end;
@@ -61,14 +58,21 @@ OnStop:
 
 OnTimer1000:
 	stopnpctimer;
-	initnpctimer;
+	if (!getbattleflag("feature.bgqueue"))
+		initnpctimer;
 	set .@chk_bat_a01,getmapusers("bat_a01");
 	if (.@chk_bat_a01 < 1) {
 		set $@TierraBG1,0; set $@TierraBG1_Victory, 0;
 		if( $@TierraBG1_id1 ) { bg_destroy $@TierraBG1_id1; set $@TierraBG1_id1, 0; }
 		if( $@TierraBG1_id2 ) { bg_destroy $@TierraBG1_id2; set $@TierraBG1_id2, 0; }
-		donpcevent "start#bat_a01::OnReadyCheck";
+		if (getbattleflag("feature.bgqueue")) {
+			bg_unbook "bat_a01";
+			end;
+		} else
+			donpcevent "start#bat_a01::OnReadyCheck";
 	}
+	if (getbattleflag("feature.bgqueue"))
+		initnpctimer;
 	end;
 }
 
@@ -124,23 +128,30 @@ OnEnable:
 
 OnGuillaumeQuit:
 OnCroixQuit:
-	bg_leave;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+	else
+		bg_leave;
 	end;
 
 OnReadyCheck:
 	if( $@TierraBG1 )
 		end;
-	set .@Guillaume, getwaitingroomstate(0,"Lieutenant Kalos");
-	set .@Croix, getwaitingroomstate(0,"Lieutenant Eyor");
-	if( !.@Guillaume && !.@Croix ) {
-		donpcevent "#bat_a01_timer::OnStop";
-		end;
+	if (!getbattleflag("feature.bgqueue")) {
+		set .@Guillaume, getwaitingroomstate(0,"Lieutenant Kalos");
+		set .@Croix, getwaitingroomstate(0,"Lieutenant Eyor");
+		if( !.@Guillaume && !.@Croix ) {
+			donpcevent "#bat_a01_timer::OnStop";
+			end;
+		}
+		else if( .@Guillaume < 10 || .@Croix < 10 )
+			end;
 	}
-	else if( .@Guillaume < 10 || .@Croix < 10 )
-		end;
 	set $@TierraBG1,1;
-	donpcevent "Lieutenant Kalos::OnEnterBG";
-	donpcevent "Lieutenant Eyor::OnEnterBG";
+	if (!getbattleflag("feature.bgqueue")) {
+		donpcevent "Lieutenant Kalos::OnEnterBG";
+		donpcevent "Lieutenant Eyor::OnEnterBG";
+	}
 	donpcevent "start#bat_a01::OnEnable";
 	bg_warp $@TierraBG1_id1,"bat_a01",352,342;
 	bg_warp $@TierraBG1_id2,"bat_a01",353,52;
@@ -690,7 +701,8 @@ bat_a01,53,377,3	script	Guillaume Vintenar#a01_a	419,{
 			callfunc "F_BG_Badge",1,"Guillaume","Tierra";
 	}
 	bg_leave;
-	warp "bat_room",154,150;
+	if (!getbattleflag("feature.bgqueue"))
+		warp "bat_room",154,150;
 	end;
 
 OnInit:
@@ -712,7 +724,8 @@ bat_a01,45,19,3	script	Croix Vintenar#a01_b	415,{
 			callfunc "F_BG_Badge",1,"Croix","Tierra";
 	}
 	bg_leave;
-	warp "bat_room",154,150;
+	if (!getbattleflag("feature.bgqueue"))
+		warp "bat_room",154,150;
 	end;
 
 OnInit:
@@ -797,3 +810,21 @@ bat_a01,1,1,3	script	Release all#a01	81,{
 		}
 	}
 }
+
+// BG Queue makes these scripts useless
+-	script	BGQueueInit#tierra01	-1,{
+	end;
+
+OnInit:
+	if (getbattleflag("feature.bgqueue")) {
+		unloadnpc "Lieutenant Kalos";
+		unloadnpc "Lieutenant Eyor";
+		unloadnpc "#bat_a01_quest_a";
+		unloadnpc "#bat_a01_quest_b";
+		unloadnpc "back_bgrooma01a";
+		unloadnpc "back_bgrooma01b";
+		unloadnpc "A_CODE#bat_a01";
+		unloadnpc "B_CODE#bat_a01";
+	}
+	end;
+}

+ 55 - 24
npc/battleground/tierra/tierra02.txt

@@ -1,23 +1,18 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= BattleGround System - Tierra Gorge 2
-//===== By: ================================================== 
-//= L0ne_W0lf
-//===== Current Version: ===================================== 
-//= 1.5
-//===== Compatible With: ===================================== 
-//= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= Second Tierra Gorge Battleground.
 //= - Winning Team: 3 badges (5 if VIP)
 //= - Losing Team: 1 badge (3 if VIP)
-//===== Additional Comments: ================================= 
-//= 1.0 First Version.
+//===== Changelogs: ==========================================
+//= 1.0 First Version. [L0ne_W0lf]
 //= 1.1 Updated 'waitingroom' to support required zeny/lvl. [Kisuka]
 //= 1.2 Removed MaxLvl check in waitingrooms.
 //= 1.3 Label standardization. [Euphy]
 //= 1.4 Added GM management function. [Euphy]
 //= 1.5 Added VIP features and created a reward function. [Euphy]
+//= 1.6 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
 //============================================================
 
 // Waiting Room NPCs
@@ -50,6 +45,8 @@ bat_room,1,151,3	script	#bat_a02_timer	844,{
 	end;
 
 OnInit:
+	if (getbattleflag("feature.bgqueue"))
+		end;
 OnEnable:
 	initnpctimer;
 	end;
@@ -60,14 +57,21 @@ OnStop:
 
 OnTimer1000:
 	stopnpctimer;
-	initnpctimer;
+	if (!getbattleflag("feature.bgqueue"))
+		initnpctimer;
 	set .@chk_bat_a02,getmapusers("bat_a02");
 	if (.@chk_bat_a02 < 1) {
 		set $@TierraBG2,0; set $@TierraBG2_Victory, 0;
 		if( $@TierraBG2_id1 ) { bg_destroy $@TierraBG2_id1; set $@TierraBG2_id1, 0; }
 		if( $@TierraBG2_id2 ) { bg_destroy $@TierraBG2_id2; set $@TierraBG2_id2, 0; }
-		donpcevent "start#bat_a02::OnReadyCheck";
+		if (getbattleflag("feature.bgqueue")) {
+			bg_unbook "bat_a02";
+			end;
+		} else
+			donpcevent "start#bat_a02::OnReadyCheck";
 	}
+	if (getbattleflag("feature.bgqueue"))
+		initnpctimer;
 	end;
 }
 
@@ -123,23 +127,30 @@ OnEnable:
 
 OnGuillaumeQuit:
 OnCroixQuit:
-	bg_leave;
+	if (getbattleflag("feature.bgqueue"))
+		bg_desert;
+	else
+		bg_leave;
 	end;
 
 OnReadyCheck:
 	if( $@TierraBG2 )
 		end;
-	set .@Guillaume, getwaitingroomstate(0,"Lieutenant Rundel");
-	set .@Croix, getwaitingroomstate(0,"Lieutenant Guerrit");
-	if( !.@Guillaume && !.@Croix ) {
-		donpcevent "#bat_a02_timer::OnStop";
-		end;
+	if (!getbattleflag("feature.bgqueue")) {
+		set .@Guillaume, getwaitingroomstate(0,"Lieutenant Rundel");
+		set .@Croix, getwaitingroomstate(0,"Lieutenant Guerrit");
+		if( !.@Guillaume && !.@Croix ) {
+			donpcevent "#bat_a02_timer::OnStop";
+			end;
+		}
+		else if( .@Guillaume < 10 || .@Croix < 10 )
+			end;
 	}
-	else if( .@Guillaume < 10 || .@Croix < 10 )
-		end;
 	set $@TierraBG2,1;
-	donpcevent "Lieutenant Rundel::OnEnterBG";
-	donpcevent "Lieutenant Guerrit::OnEnterBG";
+	if (!getbattleflag("feature.bgqueue")) {
+		donpcevent "Lieutenant Rundel::OnEnterBG";
+		donpcevent "Lieutenant Guerrit::OnEnterBG";
+	}
 	donpcevent "start#bat_a02::OnEnable";
 	bg_warp $@TierraBG2_id1,"bat_a02",352,342;
 	bg_warp $@TierraBG2_id2,"bat_a02",353,52;
@@ -689,7 +700,8 @@ bat_a02,53,377,3	script	Guillaume Vintenar#a02_a	419,{
 			callfunc "F_BG_Badge",1,"Guillaume","Tierra";
 	}
 	bg_leave;
-	warp "bat_room",154,150;
+	if (!getbattleflag("feature.bgqueue"))
+		warp "bat_room",154,150;
 	end;
 
 OnInit:
@@ -711,7 +723,8 @@ bat_a02,45,19,3	script	Croix Vintenar#a02_b	415,{
 			callfunc "F_BG_Badge",1,"Croix","Tierra";
 	}
 	bg_leave;
-	warp "bat_room",154,150;
+	if (getbattleflag("feature.bgqueue"))
+		warp "bat_room",154,150;
 	end;
 
 OnInit:
@@ -796,3 +809,21 @@ bat_a02,1,1,3	script	Release all#a02	81,{
 		}
 	}
 }
+
+// BG Queue makes these scripts useless
+-	script	BGQueueInit#tierra02	-1,{
+	end;
+
+OnInit:
+	if (getbattleflag("feature.bgqueue")) {
+		unloadnpc "Lieutenant Rundel";
+		unloadnpc "Lieutenant Guerrit";
+		unloadnpc "#bat_a02_quest_a";
+		unloadnpc "#bat_a02_quest_b";
+		unloadnpc "back_bgrooma02a";
+		unloadnpc "back_bgrooma02b";
+		unloadnpc "A_CODE#bat_a02";
+		unloadnpc "B_CODE#bat_a02";
+	}
+	end;
+}

+ 35 - 62
npc/battleground/tierra/tierra_enter.txt

@@ -1,22 +1,19 @@
-//===== rAthena Script ======================================= 
+//===== rAthena Script =======================================
 //= BattleGround System - Tierra Gorge Entrance NPCs
-//===== By: ================================================== 
-//= L0ne_W0lf
-//===== Current Version: ===================================== 
-//= 1.0
-//===== Compatible With: ===================================== 
-//= rAthena Project
-//===== Description: ========================================= 
+//===== Description: =========================================
 //= [Official Conversion]
 //= Tierra Gorge Battleground Entrance NPCs
-//===== Additional Comments: ================================= 
-//= 1.0 First Version.
+//===== Additional Comments: =================================
+//= 1.0 First Version. [L0ne_W0lf]
 //= 1.1 Fixed silly copy paste errors. (bugreport:4401)
+//= 1.2 Added battle_config checks to allow this script to use the new queue interface or the previous method. [Aleos]
 //============================================================
 
 // First Tierra Gorge Officers - Guillaume
 //============================================================
 bat_room,124,178,5	script	Tierra Gorge Officer#01a	418,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	if (checkweight(1201,1) == 0) {
 		mes "- Wait a minute !! -";
 		mes "- Currently you're carrying -";
@@ -84,6 +81,8 @@ bat_room,124,178,5	script	Tierra Gorge Officer#01a	418,{
 }
 
 bat_room,140,178,5	script	Tierra Gorge Officer#02a	418,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	if (checkweight(1201,1) == 0) {
 		mes "- Wait a minute !! -";
 		mes "- Currently you're carrying -";
@@ -166,37 +165,22 @@ bat_room,127,178,5	script	Guillaume Knight#1	417,{
 	mes "Think and move as quickly as you can. The victory of your army relies on your contribution.";
 	next;
 	mes "[Guillaume Knight]";
-	mes "Please remember: when you join a battle, you will receive a token which indicates the set duration for which you cannot participate in the same type of battle.";
-	mes "You may check the duration by pressing the Alt+U keys.";
+	if (getbattleflag("feature.bgqueue"))
+		mes "If you are ready, start by clicking the ^0000FFbattle button from the interface^000000.";
+	else {
+		mes "Please remember: when you join a battle, you will receive a token which indicates the set duration for which you cannot participate in the same type of battle.";
+		mes "You may check the duration by pressing the Alt+U keys.";
+	}
 	next;
 	mes "[Guillaume Knight]";
-	mes "Are you ready to battle? Then apply with the recruiter next to me!";
+	if (getbattleflag("feature.bgqueue"))
+		mes "Please bear in mind once you cancel, ^0000FFyou may not reapply for 1 minute^000000!";
+	else
+		mes "Are you ready to battle? Then apply with the recruiter next to me!";
 	close;
 }
 
-bat_room,143,178,5	script	Guillaume Knight#2	417,{
-	mes "[Guillaume Knight]";
-	mes "Tierra Gorge consists of two steep sides placed vertically, and has ration depots for the Guillaume and Croix Armies at the 11 and 7 o'clock directions.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The battle starts at your army's ship, and the goal is to advance and destroy your enemy's rations depot faster than they can destroy yours.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The healer of the battlefield will resurrect soldiers once every 25 seconds so that they can rejoin the battle.";
-	mes "The army that captures the neutral flag in the center of the battlefield will be rewarded with extra regeneration points, meaning their soldiers will resurrect more than the other side, giving them an advantage.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Those two rations depots are connected to each other through short and narrow paths, but the gates are blocked with barricades.";
-	mes "Think and move as quickly as you can. The victory of your army relies on your contribution.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Please remember: when you join a battle, you will receive a token which indicates the set duration for which you cannot participate in the same type of battle.";
-	mes "You may check the duration by pressing the Alt+U keys.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Are you ready to battle? Then apply with the recruiter next to me!";
-	close;
-}
+bat_room,143,178,5	duplicate(Guillaume Knight#1)	Guillaume Knight#2	417
 
 bat_room,127,121,1	script	Croix Knight#1	413,{
 	mes "[Croix Knight]";
@@ -214,41 +198,28 @@ bat_room,127,121,1	script	Croix Knight#1	413,{
 	mes "Think and move as quickly as you can. The victory of your army relies on your contribution.";
 	next;
 	mes "[Croix Knight]";
-	mes "Please remember: when you join a battle, you will receive a token which indicates the set duration for which you cannot participate in the same type of battle.";
-	mes "You may check the duration by pressing the Alt+U keys.";
+	if (getbattleflag("feature.bgqueue"))
+		mes "If you are ready, start by clicking the ^0000FFbattle button from the interface^000000.";
+	else {
+		mes "Please remember: when you join a battle, you will receive a token which indicates the set duration for which you cannot participate in the same type of battle.";
+		mes "You may check the duration by pressing the Alt+U keys.";
+	}
 	next;
 	mes "[Croix Knight]";
-	mes "Are you ready to battle? Then apply with the recruiter next to me!";
+	if (getbattleflag("feature.bgqueue"))
+		mes "Please bear in mind once you cancel, ^0000FFyou may not reapply for 1 minute^000000!";
+	else
+		mes "Are you ready to battle? Then apply with the recruiter next to me!";
 	close;
 }
 
-bat_room,143,121,1	script	Croix Knight#2	413,{
-	mes "[Croix Knight]";
-	mes "Tierra Gorge consists of two steep sides placed vertically, and has ration depots for the Guillaume and Croix Armies at the 11 and 7 o'clock directions.";
-	next;
-	mes "[Croix Knight]";
-	mes "The battle starts at your army's ship, and the goal is to advance and destroy your enemy's rations depot faster than they can destroy yours.";
-	next;
-	mes "[Croix Knight]";
-	mes "The healer of the battlefield will resurrect soldiers once every 25 seconds so that they can rejoin the battle.";
-	mes "The army that captures the neutral flag in the center of the battlefield will be rewarded with extra regeneration points, meaning their soldiers will resurrect more than the other side, giving them an advantage.";
-	next;
-	mes "[Croix Knight]";
-	mes "Those two rations depots are connected to each other through short and narrow paths, but the gates are blocked with barricades.";
-	mes "Think and move as quickly as you can. The victory of your army relies on your contribution.";
-	next;
-	mes "[Croix Knight]";
-	mes "Please remember: when you join a battle, you will receive a token which indicates the set duration for which you cannot participate in the same type of battle.";
-	mes "You may check the duration by pressing the Alt+U keys.";
-	next;
-	mes "[Croix Knight]";
-	mes "Are you ready to battle? Then apply with the recruiter next to me!";
-	close;
-}
+bat_room,143,121,1	duplicate(Croix Knight#1)	Croix Knight#2	413
 
 // Second Tierra Gorge Officers - Croix
 //============================================================
 bat_room,125,121,1	script	Tierra Gorge Officer#01b	414,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	if (checkweight(1201,1) == 0) {
 		mes "- Wait a minute !! -";
 		mes "- Currently you're carrying -";
@@ -316,6 +287,8 @@ bat_room,125,121,1	script	Tierra Gorge Officer#01b	414,{
 }
 
 bat_room,140,121,1	script	Tierra Gorge Officer#02b	414,{
+	if (getbattleflag("feature.bgqueue"))
+		end;
 	if (checkweight(1201,1) == 0) {
 		mes "- Wait a minute !! -";
 		mes "- Currently you're carrying -";

+ 0 - 1288
npc/custom/battleground/unofficial/bg_common.txt

@@ -1,1288 +0,0 @@
-// ==============================================================================
-// BattleGround System - Common NPCs
-// ==============================================================================
-
-// BattleGround Warper - Entrance
-// *********************************************************************
-
--	script	Maroll Battle Recruiter::BatRecruit	728,{
-	mes "[Maroll Battle Recruiter]";
-	mes "Good day, adventurer.";
-	mes "I'm a knight from a far country called Maroll Kingdom.";
-	next;
-	mes "[Maroll Battle Recruiter]";
-	mes "The two princes of the kingdom are now battling for the throne of Maroll, and are in need of experienced soldiers like you. How would you like to lend your power to one of the princes in the Maroll Kingdom?";
-	next;
-	if( select("Join:Don't Join") == 2 )
-	{
-		mes "[Maroll Battle Recruiter]";
-		mes "I'll always be stationed here for more soldiers. Feel free to come back whenever you're interested.";
-		close;
-	}
-	mes "[Maroll Battle Recruiter]";
-	mes "May the war god bless you.";
-	close2;
-	warp "bat_room",155,150;
-	end;
-}
-
-payon,189,104,3	duplicate(BatRecruit)	Maroll Battle Recruiter::BatRecruit1	728
-prontera,123,83,5	duplicate(BatRecruit)	Maroll Battle Recruiter::BatRecruit2	728
-rachel,149,138,5	duplicate(BatRecruit)	Maroll Battle Recruiter::BatRecruit3	728
-moc_ruins,75,162,5	duplicate(BatRecruit)	Maroll Battle Recruiter::BatRecruit4	728
-aldebaran,146,109,5	duplicate(BatRecruit)	Maroll Battle Recruiter::BatRecruit5	728
-lighthalzen,153,86,5	duplicate(BatRecruit)	Maroll Battle Recruiter::BatRecruit6	728
-
-// BattleGround Warper - Exit
-// *********************************************************************
-
-bat_room,148,150,4	script	Teleporter#bat	124,{
-	mes "[Teleporter]";
-	mes "Do you wish to leave the battlefield? Use my service to return to town.";
-	next;
-	if( select("Leave:Don't Leave") == 2 )
-	{
-		mes "[Teleporter]";
-		mes "I'll be here whenever you're in need of my service.";
-		close;
-	}
-
-	set .@spoint$, getsavepoint(0);
-	set .@x, getsavepoint(1);
-	set .@y, getsavepoint(2);
-	mes "[Teleporter]";
-	mes "You will be sent back to " + .@spoint$ + ".";
-	close2;
-	warp .@spoint$, .@x, .@y;
-	end;
-}
-
-// Kafra
-// *********************************************************************
-bat_room,148,147,4	script	Kafra Staff::kaf_bat	861,{
-	cutin "kafra_09",2;
-	callfunc "F_Kafra",0,2,1,150,0;
-}
-
-// General Guillaume
-// *********************************************************************
-bat_room,160,159,3	script	General Guillaume	420,{
-	cutin "bat_kiyom2",2;
-	mes "[General Guillaume]";
-	mes "Hot-blooded adventurer, we need your ability to win this battle.";
-	next;
-	cutin "bat_kiyom1",2;
-	mes "[General Guillaume]";
-	mes "Our great king, Marcel Marollo VII, is very sick lately. His Majesty has declared that he chosen either me or Prince Croix as the next king amongst his 9 sons.";
-	next;
-	mes "[General Guillaume]";
-	mes "Two kings can't share a nation!";
-	mes "Only the one victorious from His Majesty's appointed battle will be enthroned.";
-	next;
-	mes "[General Guillaume]";
-	mes "This is however, not just a battle between us. This battle will determine the future of this country. I pledge on my honor to prove that I'm the one who can protect this Maroll from outside threats.";
-	next;
-	if( select("Yes, I want to join you.:End Conversation") == 2 )
-	{
-		mes "[General Guillaume]";
-		mes "I'll be the one who will capture the flag!";
-		close2;
-		cutin "",255;
-		end;
-	}
-	cutin "bat_kiyom2",2;
-	mes "[General Guillaume]";
-	mes "Welcome to my army, comrade.";
-	mes "Your eyes tell me that you're a soldier that I can trust.";
-	set Bat_Team,1;
-	next;
-	mes "[General Guillaume]";
-	mes "Now, go upstairs and apply for battle with your comrades. I'm sure they'll welcome you whole-heartedly!";
-	close2;
-	cutin "",255;
-	end;
-}
-
-// General Croix
-// *********************************************************************
-bat_room,160,140,3	script	Prince Croix	416,{
-	cutin "bat_crua1",2;
-	mes "[Prince Croix]";
-	mes "Wise adventurer, why don't you lend us your power for victory?";
-	next;
-	cutin "bat_crua2",2;
-	mes "[Prince Croix]";
-	mes "I do not wish to shed blood, but I have no choice but to fight for the possibility of peace and for the sake of my people.";
-	next;
-	mes "[Prince Croix]";
-	mes "General Guillaume may have an advantage in this battle as he is the great general of Maroll, but that doesn't automatically mean he'll win. I want to win this battle so that I can grant a better future for my people.";
-	next;
-	if( select("Yes, I want to join you!:End Conversation") == 2 )
-	{
-		mes "[Prince Croix]";
-		mes "For Maroll!";
-		close2;
-		cutin "",255;
-		end;
-	}
-	mes "[Prince Croix]";
-	mes "Thank you so much. I feel like I can win with the help of adventurers like you. Now, please go downstairs and join your comrades in sharpening their skills to fight the enemy!";
-	set Bat_Team,2;
-	close2;
-	cutin "",255;
-	end;
-}
-
-// Guillaume Knight - Tierra Valley
-// *********************************************************************
-bat_room,159,178,5	script	Guillaume Knight#1	417,{
-	mes "[Guillaume Knight]";
-	mes "Tierra Gorge is a very steep canyon with two forts residing in the north and south ends of the map.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "There is a ration depot for the Guillaume and Croix armies at the 11 and 8 o'clock directions.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The battle starts at your army's ship, and the goal is to advance and destroy your enemy's rations depot faster than they can destroy yours.";
-	mes "The army that captures the neutral flag in the center of the battlefield will be rewarded with extra regeneration points, meaning their soldiers will resurrect more than the other side, giving them an advantage.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// Tierra Officer - Guillaume
-// *********************************************************************
-bat_room,156,178,5	script	Tierra Valley Officer#1	418,{
-	mes "[Tierra Officer]";
-	if( Bat_Team == 2 )
-	{
-		mes "Get out of here you stinky Croix!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-	
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Guillaume Army to those stinky Croixs!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[Tierra Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(2069,PLAYTIME) == 2 ) erasequest 2069;
-	if( checkquest(2069,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at Tierra Gorge. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[Tierra Officer]";
-		mes "Stand-by for Tierra Gorge Battle until the time limit passes.";
-		close;
-	}
-	
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: I can't send a rookie like you to die on the cruel battlefield";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",85,224;
-	end;
-}
-
-// Croix Knight - Tierra Valley
-// *********************************************************************
-bat_room,159,121,1	script	Croix Knight#1	413,{
-	mes "[Croix Knight]";
-	mes "Tierra Gorge is a very steep canyon with two forts residing in the north and south ends of the map.";
-	next;
-	mes "[Croix Knight]";
-	mes "There is a ration depot for the Guillaume and Croix armies at the 11 and 8 o'clock directions.";
-	next;
-	mes "[Croix Knight]";
-	mes "The battle starts at your army's ship, and the goal is to advance and destroy your enemy's rations depot faster than they can destroy yours.";
-	mes "The army that captures the neutral flag in the center of the battlefield will be rewarded with extra regeneration points, meaning their soldiers will resurrect more than the other side, giving them an advantage.";
-	next;
-	mes "[Croix Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// Tierra Officer - Croix
-// *********************************************************************
-bat_room,156,121,1	script	Tierra Valley Officer#2	414,{
-	mes "[Tierra Officer]";
-	if( Bat_Team == 1 )
-	{
-		mes "Get out of here you stupid Guillaume!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Croix Army to those stinky Guillaumes!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[Tierra Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(2069,PLAYTIME) == 2 ) erasequest 2069;
-	if( checkquest(2069,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at Tierra Gorge. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[Tierra Officer]";
-		mes "Stand-by for Tierra Gorge Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: I can't send a rookie like you to die on the cruel battlefield";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",85,208;
-	end;
-}
-
-// Guillaume Knight - Tierra
-// *********************************************************************
-bat_room,167,178,5	script	Guillaume Knight#2	417,{
-	mes "[Guillaume Knight]";
-	mes "Tierra Gorge is a very steep canyon with two forts residing in the north and south ends of the map.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "There is a ration depot for the Guillaume and Croix armies at the 11 and 8 o'clock directions.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The battle starts at your army's ship, and the goal is to advance and destroy your enemy's rations depot faster than they can destroy yours.";
-	mes "The army that captures the neutral flag in the center of the battlefield will be rewarded with extra regeneration points, meaning their soldiers will resurrect more than the other side, giving them an advantage.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// Tierra Officer - Guillaume
-// *********************************************************************
-bat_room,164,178,5	script	Tierra Valley Officer#3	418,{
-	mes "[Tierra Officer]";
-	if( Bat_Team == 2 )
-	{
-		mes "Get out of here you stinky Croix!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-	
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Guillaume Army to those stinky Croixs!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[Tierra Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(2069,PLAYTIME) == 2 ) erasequest 2069;
-	if( checkquest(2069,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at Tierra Gorge. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[Tierra Officer]";
-		mes "Stand-by for Tierra Gorge Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: I can't send a rookie like you to die on the cruel battlefield";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",57,94;
-	end;
-}
-
-// Croix Knight - Tierra
-// *********************************************************************
-bat_room,167,121,1	script	Croix Knight#2	413,{
-	mes "[Croix Knight]";
-	mes "Tierra Gorge is a very steep canyon with two forts residing in the north and south ends of the map.";
-	next;
-	mes "[Croix Knight]";
-	mes "There is a ration depot for the Guillaume and Croix armies at the 11 and 8 o'clock directions.";
-	next;
-	mes "[Croix Knight]";
-	mes "The battle starts at your army's ship, and the goal is to advance and destroy your enemy's rations depot faster than they can destroy yours.";
-	mes "The army that captures the neutral flag in the center of the battlefield will be rewarded with extra regeneration points, meaning their soldiers will resurrect more than the other side, giving them an advantage.";
-	next;
-	mes "[Croix Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// Tierra Officer - Croix
-// *********************************************************************
-bat_room,164,121,1	script	Tierra Valley Officer#4	414,{
-	mes "[Tierra Officer]";
-	if( Bat_Team == 1 )
-	{
-		mes "Get out of here you stupid Guillaume!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Croix Army to those stinky Guillaumes!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[Tierra Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(2069,PLAYTIME) == 2 ) erasequest 2069;
-	if( checkquest(2069,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at Tierra Gorge. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[Tierra Officer]";
-		mes "Stand-by for Tierra Gorge Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: I can't send a rookie like you to die on the cruel battlefield";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",57,77;
-	end;
-}
-
-// Guillaune Knight - Flavius
-// *********************************************************************
-bat_room,175,178,5	script	Guillaume Knight#3	417,{
-	mes "[Guillaume Knight]";
-	mes "The objective of the Flavius Battle is to score 2 points before your enemy by destroying their crystal.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The crystals for both armies are protected by special barricades that cannot be destroyed by direct attacks.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "But they can be removed by destroying the Guardians that protect the enemy army base.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The crystals are immune to every type of skill; your physical attacks are the only choice for destroying your enemy's crystal.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// Flavius Officer - Guillaume
-// *********************************************************************
-bat_room,172,178,5	script	Flavius Officer#1	418,{
-	mes "[Flavius Officer]";
-	if( Bat_Team == 2 )
-	{
-		mes "Get out of here you stupid Croix!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Guillaume Army to those stinky Croixs!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[Flavius Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(2070,PLAYTIME) == 2 ) erasequest 2070;
-	if( checkquest(2070,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at Flavius. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[Flavius Officer]";
-		mes "Stand-by for Flavius Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: I can't send a rookie like you to die on the cruel battlefield";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",85,94;
-	end;
-}
-
-// Croix Knight - Flavius
-// *********************************************************************
-bat_room,175,121,1	script	Croix Knight#3	413,{
-	mes "[Croix Knight]";
-	mes "The objective of the Flavius Battle is to score 2 points before your enemy by destroying their crystal.";
-	next;
-	mes "[Croix Knight]";
-	mes "The crystals for both armies are protected by special barricades that cannot be destroyed by direct attacks.";
-	next;
-	mes "[Croix Knight]";
-	mes "But they can be removed by destroying the Guardians that protect the enemy army base.";
-	next;
-	mes "[Croix Knight]";
-	mes "The crystals are immune to every type of skill; your physical attacks are the only choice for destroying your enemy's crystal.";
-	next;
-	mes "[Croix Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// Flavius Officerer - Croix
-// *********************************************************************
-bat_room,172,121,1	script	Flavius Officer#2	414,{
-	mes "[Flavius Officer]";
-	if( Bat_Team == 1 )
-	{
-		mes "Get out of here you stupid Guillaume!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Croix Army to those stinky Guillaumes!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[Flavius Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(2070,PLAYTIME) == 2 ) erasequest 2070;
-	if( checkquest(2070,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at Flavius. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[Flavius Officer]";
-		mes "Stand-by for Flavius Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: I can't send a rookie like you to die on the cruel battlefield";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",85,77;
-	end;
-}
-
-// Guillaune Knight - Flavius
-// *********************************************************************
-bat_room,151,178,5	script	Guillaume Knight#4	417,{
-	mes "[Guillaume Knight]";
-	mes "The objective of the Flavius Battle is to score 2 points before your enemy by destroying their crystal.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The crystals for both armies are protected by special barricades that cannot be destroyed by direct attacks.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "But they can be removed by destroying the Guardians that protect the enemy army base.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The crystals are immune to every type of skill; your physical attacks are the only choice for destroying your enemy's crystal.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// Flavius Officerer - Guillaume
-// *********************************************************************
-bat_room,148,178,5	script	Flavius Officer#3	418,{
-	mes "[Flavius Officer]";
-	if( Bat_Team == 2 )
-	{
-		mes "Get out of here you stupid Croix!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Guillaume Army to those stinky Croixs!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[Flavius Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(2070,PLAYTIME) == 2 ) erasequest 2070;
-	if( checkquest(2070,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at Flavius. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[Flavius Officer]";
-		mes "Stand-by for Flavius Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: I can't send a rookie like you to die on the cruel battlefield";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",253,94;
-	end;
-}
-
-// Croix Knight - Flavius
-// *********************************************************************
-bat_room,151,121,1	script	Croix Knight#4	413,{
-	mes "[Croix Knight]";
-	mes "The objective of the Flavius Battle is to score 2 points before your enemy by destroying their crystal.";
-	next;
-	mes "[Croix Knight]";
-	mes "The crystals for both armies are protected by special barricades that cannot be destroyed by direct attacks.";
-	next;
-	mes "[Croix Knight]";
-	mes "But they can be removed by destroying the Guardians that protect the enemy army base.";
-	next;
-	mes "[Croix Knight]";
-	mes "The crystals are immune to every type of skill; your physical attacks are the only choice for destroying your enemy's crystal.";
-	next;
-	mes "[Croix Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// Flavius Officerer - Croix
-// *********************************************************************
-bat_room,148,121,1	script	Flavius Officer#4	414,{
-	mes "[Flavius Officer]";
-	if( Bat_Team == 1 )
-	{
-		mes "Get out of here you stupid Guillaume!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Croix Army to those stinky Guillaumes!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[Flavius Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(2070,PLAYTIME) == 2 ) erasequest 2070;
-	if( checkquest(2070,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at Flavius. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[Flavius Officer]";
-		mes "Stand-by for Flavius Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: I can't send a rookie like you to die on the cruel battlefield";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",253,77;
-	end;
-}
-
-// Guillaume Knight - KvM
-// *********************************************************************
-bat_room,143,178,5	script	Guillaume Knight#5	417,{
-	mes "[Guillaume Knight]";
-	mes "To win the Battle of Kriger Von Midgard you and your team must kill all the other opponents before all of you die.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The first team to lose all their soldiers loses.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Since you cannot come back to battle after you die, taking care on the battlefield is essential.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// KvM Officerer - Guillaume
-// *********************************************************************
-bat_room,140,178,5	script	KVM [80-99] Officer#1	418,{
-	mes "[KVM Officer]";
-	if( Bat_Team == 2 )
-	{
-		mes "Get out of here you stinky Croix!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Guillaume Army to those stinky Croixs!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[KVM Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(6025,PLAYTIME) == 2 ) erasequest 6025;
-	if( checkquest(6025,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at KvM. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[KVM Officer]";
-		mes "Stand-by for KvM Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: This arena is for players with baselevel from 80 to 99.";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",253,224;
-	end;
-}
-
-// Croix Knight - KvM
-// *********************************************************************
-bat_room,143,121,1	script	Croix Knight#5	413,{
-	mes "[Croix Knight]";
-	mes "To win the Battle of Kriger Von Midgard you and your team must kill all the other opponents before all of you die.";
-	next;
-	mes "[Croix Knight]";
-	mes "The first team to lose all their soldiers loses.";
-	next;
-	mes "[Croix Knight]";
-	mes "Since you cannot come back to battle after you die, taking care on the battlefield is essential.";
-	next;
-	mes "[Croix Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// KvM Officer - Croix
-// *********************************************************************
-bat_room,140,121,1	script	KVM [80-99] Officer#2	414,{
-	mes "[KVM Officer]";
-	if( Bat_Team == 1 )
-	{
-		mes "Get out of here you stupid Guillaume!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Croix Army to those stinky Guillaumes!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[KVM Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(6025,PLAYTIME) == 2 ) erasequest 6025;
-	if( checkquest(6025,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at KvM. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[KVM Officer]";
-		mes "Stand-by for KvM Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 80 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: This arena is for players with baselevel from 80 to 99.";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",253,208;
-	end;
-}
-
-// Guillaume Knight - KvM
-// *********************************************************************
-bat_room,135,178,5	script	Guillaume Knight#6	417,{
-	mes "[Guillaume Knight]";
-	mes "To win the Battle of Kriger Von Midgard you and your team must kill all the other opponents before all of you die.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The first team to lose all their soldiers loses.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Since you cannot come back to battle after you die, taking care on the battlefield is essential.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// KvM Officerer - Guillaume
-// *********************************************************************
-bat_room,132,178,5	script	KVM [60-79] Officer#1	418,{
-	mes "[KVM Officer]";
-	if( Bat_Team == 2 )
-	{
-		mes "Get out of here you stinky Croix!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Guillaume Army to those stinky Croixs!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[KVM Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(6025,PLAYTIME) == 2 ) erasequest 6025;
-	if( checkquest(6025,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at KvM. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[KVM Officer]";
-		mes "Stand-by for KvM Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 60 || BaseLevel > 79 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: This arena is for players with baselevel from 60 to 79.";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",225,224;
-	end;
-}
-
-// Croix Knight - KvM
-// *********************************************************************
-bat_room,135,121,1	script	Croix Knight#6	413,{
-	mes "[Croix Knight]";
-	mes "To win the Battle of Kriger Von Midgard you and your team must kill all the other opponents before all of you die.";
-	next;
-	mes "[Croix Knight]";
-	mes "The first team to lose all their soldiers loses.";
-	next;
-	mes "[Croix Knight]";
-	mes "Since you cannot come back to battle after you die, taking care on the battlefield is essential.";
-	next;
-	mes "[Croix Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// KvM Officer - Croix
-// *********************************************************************
-bat_room,132,121,1	script	KVM [60-79] Officer#2	414,{
-	mes "[KVM Officer]";
-	if( Bat_Team == 1 )
-	{
-		mes "Get out of here you stupid Guillaume!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Croix Army to those stinky Guillaumes!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[KVM Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(6025,PLAYTIME) == 2 ) erasequest 6025;
-	if( checkquest(6025,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at KvM. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[KVM Officer]";
-		mes "Stand-by for KvM Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel < 60 || BaseLevel > 79 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: This arena is for players with baselevel from 60 to 79.";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",225,208;
-	end;
-}
-
-// Guillaume Knight - KvM
-// *********************************************************************
-bat_room,127,178,5	script	Guillaume Knight#7	417,{
-	mes "[Guillaume Knight]";
-	mes "To win the Battle of Kriger Von Midgard you and your team must kill all the other opponents before all of you die.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "The first team to lose all their soldiers loses.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Since you cannot come back to battle after you die, taking care on the battlefield is essential.";
-	next;
-	mes "[Guillaume Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// KvM Officerer - Guillaume
-// *********************************************************************
-bat_room,124,178,5	script	KVM [1-59] Officer#1	418,{
-	mes "[KVM Officer]";
-	if( Bat_Team == 2 )
-	{
-		mes "Get out of here you stinky Croix!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Guillaume Army to those stinky Croixs!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[KVM Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(6025,PLAYTIME) == 2 ) erasequest 6025;
-	if( checkquest(6025,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at KvM. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[KVM Officer]";
-		mes "Stand-by for KvM Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel > 59 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: This arena is for players with baselevel from 1 to 59.";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",197,224;
-	end;
-}
-
-// Croix Knight - KvM
-// *********************************************************************
-bat_room,127,121,1	script	Croix Knight#7	413,{
-	mes "[Croix Knight]";
-	mes "To win the Battle of Kriger Von Midgard you and your team must kill all the other opponents before all of you die.";
-	next;
-	mes "[Croix Knight]";
-	mes "The first team to lose all their soldiers loses.";
-	next;
-	mes "[Croix Knight]";
-	mes "Since you cannot come back to battle after you die, taking care on the battlefield is essential.";
-	next;
-	mes "[Croix Knight]";
-	mes "Are you ready for battle? Then apply with the recruiter next to me!";
-	close;
-}
-
-// KvM Officer - Croix
-// *********************************************************************
-bat_room,124,121,1	script	KVM [1-59] Officer#2	414,{
-	mes "[KVM Officer]";
-	if( Bat_Team == 1 )
-	{
-		mes "Get out of here you stupid Guillaume!";
-		close;
-	}
-
-	if( Bat_Team == 0 )
-	{
-		mes "Please sign up for an army with Prince Croix or General Guillaume!";
-		close;
-	}
-
-	mes "Hello " + strcharinfo(0) + ", let's show the power of the Croix Army to those stinky Guillaumes!";
-	next;
-	if( select("I want to join your army!:End Conversation") == 2 )
-		close;
-
-	mes "[KVM Officer]";
-	if( BG_Delay_Tick >= gettimetick(2) )
-	{
-		mes "You are a Deserter!!";
-		mes "Because of running away, you need to wait ^0000FF" + callfunc("Time2Str",BG_Delay_Tick) + "^000000 to join again a BattleGround.";
-		close;
-	}
-
-	if( checkquest(6025,PLAYTIME) == 2 ) erasequest 6025;
-	if( checkquest(6025,PLAYTIME) != -1 )
-	{
-		mes "You have received an indicator showing that you've participated in the Battle at KvM. I can't let you participate in any other battles until the indicator goes off.";
-		next;
-		mes "[KVM Officer]";
-		mes "Stand-by for KvM Battle until the time limit passes.";
-		close;
-	}
-
-	if( BaseLevel > 59 )
-	{
-		mes "I'm very please you want to join our army, but I'm sorry: This arena is for players with baselevel from 1 to 59.";
-		close;
-	}
-
-	mes "Good luck!";
-	close2;
-	warp "bat_room",197,208;
-	end;
-}
-
-// Guard Dummy
-// *********************************************************************
-
-bat_room,161,141,3	script	Prince Croix's Aid::bat_aid	415,{ end; }
-bat_room,161,139,3	duplicate(bat_aid)	Prince Croix's Aid::bat_aid2	415
-bat_room,161,160,3	duplicate(bat_aid)	General Guillaume's Aid::bat_aid3	419
-bat_room,161,158,3	duplicate(bat_aid)	General Guillaume's Aid::bat_aid4	419
-
-// Flags
-// *********************************************************************
-
--	script	Guillaume camp#bat	973,{ end; }
--	script	Croix camp#bat	974,{ end; }
-
-// Exit from Registration
-// *********************************************************************
--	script	warp2bat_room	-1,{
-	end;
-
-OnTouch:
-	set BG_Delay_Tick, gettimetick(2) + 30;
-	warp "bat_room",154,149;
-	end;
-}
-
-// Flavius bat_b02
-bat_room,57,81,0	duplicate(warp2bat_room)	bat1	45,1,1
-bat_room,57,90,0	duplicate(warp2bat_room)	bat2	45,1,1
-// Free BG
-bat_room,57,220,0	duplicate(warp2bat_room)	bat3	45,1,1
-bat_room,57,211,0	duplicate(warp2bat_room)	bat4	45,1,1
-// Tierra Valley bat_a02
-bat_room,85,81,0	duplicate(warp2bat_room)	bat5	45,1,1
-bat_room,85,90,0	duplicate(warp2bat_room)	bat6	45,1,1
-// Tierra Valley bat_a01
-bat_room,85,220,0	duplicate(warp2bat_room)	bat7	45,1,1
-bat_room,85,211,0	duplicate(warp2bat_room)	bat8	45,1,1
-// Free BG
-bat_room,113,81,0	duplicate(warp2bat_room)	bat9	45,1,1
-bat_room,113,90,0	duplicate(warp2bat_room)	bat10	45,1,1
-// Free BG
-bat_room,113,220,0	duplicate(warp2bat_room)	bat11	45,1,1
-bat_room,113,211,0	duplicate(warp2bat_room)	bat12	45,1,1
-// Free BG
-bat_room,141,81,0	duplicate(warp2bat_room)	bat13	45,1,1
-bat_room,141,90,0	duplicate(warp2bat_room)	bat14	45,1,1
-// Free BG
-bat_room,141,220,0	duplicate(warp2bat_room)	bat15	45,1,1
-bat_room,141,211,0	duplicate(warp2bat_room)	bat16	45,1,1
-// Free BG
-bat_room,169,81,0	duplicate(warp2bat_room)	bat17	45,1,1
-bat_room,169,90,0	duplicate(warp2bat_room)	bat18	45,1,1
-// Free BG
-bat_room,169,220,0	duplicate(warp2bat_room)	bat19	45,1,1
-bat_room,169,211,0	duplicate(warp2bat_room)	bat20	45,1,1
-// Free BG
-bat_room,197,81,0	duplicate(warp2bat_room)	bat21	45,1,1
-bat_room,197,90,0	duplicate(warp2bat_room)	bat22	45,1,1
-// KvM bat_c03
-bat_room,197,220,0	duplicate(warp2bat_room)	bat23	45,1,1
-bat_room,197,211,0	duplicate(warp2bat_room)	bat24	45,1,1
-// Free BG
-bat_room,225,81,0	duplicate(warp2bat_room)	bat25	45,1,1
-bat_room,225,90,0	duplicate(warp2bat_room)	bat26	45,1,1
-// KvM bat_c02
-bat_room,225,220,0	duplicate(warp2bat_room)	bat27	45,1,1
-bat_room,225,211,0	duplicate(warp2bat_room)	bat28	45,1,1
-// Flavius bat_b01
-bat_room,253,81,0	duplicate(warp2bat_room)	bat29	45,1,1
-bat_room,253,90,0	duplicate(warp2bat_room)	bat30	45,1,1
-// KvM bat_c01
-bat_room,253,220,0	duplicate(warp2bat_room)	bat31	45,1,1
-bat_room,253,211,0	duplicate(warp2bat_room)	bat32	45,1,1
-
-// Badges Repairman
-// *********************************************************************
-
-bat_room,138,144,5	script	Repairman#bg	99,{
-	callfunc "repairmain","Repairman";
-	end;
-}
-
-// Badges Exchange
-// *********************************************************************
-
-bat_room,160,150,3	script	Erundek	109,{
-	mes "[Erundek]";
-	mes "Welcome, mighty warrior.";
-	mes "What can I do for you today ?";
-	next;
-	switch( select("Check the Catalog","Exchange Bravery Badges","Exchange Valor Badges","Exchange Heroism Badges","Hmm, nothing I guess.") )
-	{
-		case 1:
-			mes "[Erundek]";
-			mes "We have many items, so please take a look and purchase deliberately.";
-			close2;
-			readbook 11010,1;
-			end;
-		case 5:
-			mes "[Erundek]";
-			mes "As you wish.";
-			mes "See you later.";
-			close;
-		case 2: // Bravery Badges
-			mes "[Erundek]";
-			mes "So you want to exchange ^0000FFBravery Badges^000000 from the Battle of Tierra Valley.";
-			mes "What kind of item do you want to exchange?";
-			next;
-			deletearray .@Item_DB[0],127;
-			set .@Badge, 7828;
-
-			switch( select("Weapons:Garment:Footgear:Armor:Accessory") )
-			{
-				case 1: setarray .@Item_DB[0],13036,13411,1425,1632,1634,1543,1924,1978,1574,1824,1183,1380,13305,1279,1739,13108,13172; set .@Value, 100; break;
-				case 2: setarray .@Item_DB[0],2538,2539,2540; set .@Value, 50; break;
-				case 3: setarray .@Item_DB[0],2435,2436,2437; set .@Value, 50; break;
-				case 4: setarray .@Item_DB[0],2376,2377,2378,2379,2380,2381,2382; set .@Value, 80; break;
-				case 5: setarray .@Item_DB[0],2720,2721,2722,2723,2724,2725,2733; set .@Value, 500; break;
-			}
-			
-			break;
-		case 3: // Valor Badges
-			mes "[Erundek]";
-			mes "So you want to exchange ^FF0000Valor Badges^000000 from the Battle of Flavius.";
-			mes "What kind of item do you want to exchange?";
-			next;
-			deletearray .@Item_DB[0],127;
-			set .@Badge, 7829;
-
-			switch( select("Weapons:Garment:Footgear:Armor:Accessory") )
-			{
-				case 1: setarray .@Item_DB[0],13037,13410,1633,1635,1542,1923,1977,1575,1823,1184,1482,1379,13306,1280,1738,13171,13173,13174; set .@Value, 100; break;
-				case 2: setarray .@Item_DB[0],2538,2539,2540; set .@Value, 50; break;
-				case 3: setarray .@Item_DB[0],2435,2436,2437; set .@Value, 50; break;
-				case 4: setarray .@Item_DB[0],2376,2377,2378,2379,2380,2381,2382; set .@Value, 80; break;
-				case 5: setarray .@Item_DB[0],2720,2721,2722,2723,2724,2725,2733; set .@Value, 500; break;
-			}
-			
-			break;
-		case 4: // Heroism Badge
-			mes "[Erundek]";
-			mes "So you want to exchange ^FFA500Heroism Badges^000000 from the Battle of Kriger Von Midgard.";
-			mes "This shop is not available at the moment.";
-			close;
-	}
-	
-	mes "[Erundek]";
-	mes "What item do you want to exchange?";
-	mes "If you are not sure, check the catalog.";
-	next;
-
-	set .@Menu$, "";
-	set .@Count, getarraysize(.@Item_DB);
-	for( set .@i, 0; .@i < .@Count; set .@i, .@i + 1 )
-		set .@Menu$, .@Menu$ + getitemname(.@Item_DB[.@i]) + ":";
-
-	set .@Item_ID, .@Item_DB[select(.@Menu$) - 1];
-
-	mes "[Erundek]";
-	mes "Would you like to exchange ^FF0000" + .@Value + " " + getitemname(.@Badge) + "^000000 for a ^0000FF" + getitemname(.@Item_ID) + "^000000?";
-	next;
-	mes "Remember, Battleground Reward Items are ^FF0000Character Bound^000000.";
-	mes "Are you sure you want this item?";
-	next;
-	
-	if( select("Yes:No") == 2 )
-	{
-		mes "[Erundek]";
-		mes "Do you need more time to check the items?";
-		close;
-	}
-	
-	if( countitem(.@Badge) < .@Value )
-	{
-		mes "[Erundek]";
-		mes "I'm sorry, but you don't have enough badges to exchange.";
-		close;
-	}
-	
-	delitem .@Badge,.@Value;
-	getitem .@Item_ID,1;
-	mes "[Erundek]";
-	mes "Thank you for exchanging.";
-	close;
-}

+ 0 - 428
npc/custom/battleground/unofficial/bg_flavius_01.txt

@@ -1,428 +0,0 @@
-// ==============================================================================
-// BattleGround System - Flavius 1
-// ==============================================================================
-
-// Registration NPC's
-// *********************************************************************
-
-bat_room,86,227,4	script	Registration::Fl1R_Guillaume	418,{
-	end;
-OnInit:
-	waitingroom "Battle Station 10 Players",10,"Flavius_BG1::OnGuillaumeJoin",1;
-	end;
-OnEnterBG:
-	set $@FlaviusBG1_id1, waitingroom2bg("bat_b01",390,10,"Flavius_BG1::OnGuillaumeQuit","");
-	end;
-}
-
-bat_room,85,204,0	script	Registration::Fl1R_Croix	414,{
-	end;
-OnInit:
-	waitingroom "Battle Station 10 Players",10,"Flavius_BG1::OnCroixJoin",1;
-	end;
-OnEnterBG:
-	set $@FlaviusBG1_id2, waitingroom2bg("bat_b01",10,290,"Flavius_BG1::OnCroixQuit","");
-	end;
-}
-
-// Battleground Engine
-// *********************************************************************
-
--	script	Flavius_BG1	-1,{
-	end;
-
-OnInit:
-	disablenpc "Guillaume Vintenar#fl1";
-	disablenpc "Croix Vintenar#fl1";
-	disablenpc "Therapist in battle#fl11";
-	disablenpc "Therapist in battle#fl12";
-	end;
-
-OnGuillaumeQuit:
-OnCroixQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-	end;
-
-OnGuillaumeJoin:
-OnCroixJoin:
-	if( $@FlaviusBG1 == 0 )
-		donpcevent "Flavius_BG1::OnReadyCheck";
-	end;
-
-OnReadyCheck:
-	if( $@FlaviusBG1 )
-		end;
-	set .@Guillaume, getwaitingroomstate(0,"Fl1R_Guillaume");
-	set .@Croix, getwaitingroomstate(0,"Fl1R_Croix");
-	
-	if( .@Guillaume < 10 || .@Croix < 10 )
-	{
-		mapannounce "bat_room","Battleground -- Flavius [80-99] G: " + .@Guillaume + "/10, C: " + .@Croix + "/10",1,0x006400;
-		end;
-	}
-
-	// BG Variables
-	set $@FlaviusBG1, 1;
-	set $@FlaviusBG1_Victory, 0;
-	set .Guillaume_Score, 0;
-	set .Guillaume_Loss, 0;
-	set .Croix_Score, 0;
-	set .Croix_Loss, 0;
-	set .Match, 0;
-	// Prepare NPC
-	donpcevent "#gfl1_respawn::OnBGStart";
-	donpcevent "#cfl1_respawn::OnBGStart";
-	enablenpc "Therapist in battle#fl11";
-	enablenpc "Therapist in battle#fl12";
-	disablenpc "Guillaume Vintenar#fl1";
-	disablenpc "Croix Vintenar#fl1";
-	// Build and Warp Teams
-	donpcevent "Fl1R_Guillaume::OnEnterBG";
-	donpcevent "Fl1R_Croix::OnEnterBG";
-	announce "Battleground -- Flavius [80-99] has started!",0,0x006400;
-	initnpctimer;
-	// Start Match!!
-
-OnRoundStart:
-	sleep 2000;
-	if( $@FlaviusBG1 != 1 ) end;
-
-	areapercentheal "bat_b01",382,2,397,17,100,100;
-	areapercentheal "bat_b01",2,282,17,297,100,100;
-	bg_warp $@FlaviusBG1_id1,"bat_b01",311,224;
-	bg_warp $@FlaviusBG1_id2,"bat_b01",87,75;
-
-	sleep 2000;
-	if( $@FlaviusBG1 != 1 ) end;
-
-	set .Match, .Match + 1;
-	// Crystal Spawn
-	set .Guillaume_Crystal, bg_monster($@FlaviusBG1_id1,"bat_b01",328,150,"Crystal Guillaume",1914,"Flavius_BG1::OnGuillaumeBreak");
-	setcell "bat_b01",327,151,329,149,cell_basilica,1;
-	setcell "bat_b01",327,151,329,149,cell_walkable,1;
-
-	set .Croix_Crystal, bg_monster($@FlaviusBG1_id2,"bat_b01",62,150,"Crystal Croix",1915,"Flavius_BG1::OnCroixBreak");
-	setcell "bat_b01",62,149,60,151,cell_basilica,1;
-	setcell "bat_b01",62,149,60,151,cell_walkable,1;
-
-	// Guardian Spawns
-	bg_monster $@FlaviusBG1_id1,"bat_b01",328,160,"Guillaume Guardian",1949,"Flavius_BG1::OnGuiGuardian";
-	bg_monster $@FlaviusBG1_id1,"bat_b01",328,140,"Guillaume Guardian",1950,"Flavius_BG1::OnGuiGuardian";
-	set .Guillaume_Guardian, 2;
-	bg_monster $@FlaviusBG1_id2,"bat_b01",62,160,"Croix Guardian",1949,"Flavius_BG1::OnCroGuardian";
-	bg_monster $@FlaviusBG1_id2,"bat_b01",61,140,"Croix Guardian",1950,"Flavius_BG1::OnCroGuardian";
-	set .Croix_Guardian, 2;
-	// Announces
-	mapannounce "bat_b01","The Battle of Flavius [ " + .Match + " ] Round has begun!!",1,0x006400;
-	end;
-
-OnRoundStop:
-	// Remove Monsters
-	killmonster "bat_b01","Flavius_BG1::OnGuiGuardian";
-	killmonster "bat_b01","Flavius_BG1::OnCroGuardian";
-	setcell "bat_b01",327,151,329,149,cell_walkable,0;
-	setcell "bat_b01",327,151,329,149,cell_basilica,0;
-	killmonster "bat_b01","Flavius_BG1::OnGuillaumeBreak";
-	setcell "bat_b01",62,149,60,151,cell_walkable,0;
-	setcell "bat_b01",62,149,60,151,cell_basilica,0;
-	killmonster "bat_b01","Flavius_BG1::OnCroixBreak";
-	end;
-
-OnGuiGuardian:
-	if( set(.Guillaume_Guardian, .Guillaume_Guardian - 1) <= 0 )
-	{
-		setcell "bat_b01",327,151,329,149,cell_walkable,0;
-		setcell "bat_b01",327,151,329,149,cell_basilica,0;
-		mapannounce "bat_b01","The Guillaume Crystal is vulnerable to attack!",1,0x0000FF;
-	}
-	end;
-
-OnCroGuardian:
-	if( set(.Croix_Guardian, .Croix_Guardian - 1) <= 0 )
-	{
-		setcell "bat_b01",62,149,60,151,cell_walkable,0;
-		setcell "bat_b01",62,149,60,151,cell_basilica,0;
-		mapannounce "bat_b01","The Croix Crystal is vulnerable to attack!",1,0xFF0000;
-	}
-	end;
-
-OnGuillaumeBreak:
-	donpcevent "Flavius_BG1::OnRoundStop";
-	set .Guillaume_Loss, .Guillaume_Loss + 1;
-	if( set(.Croix_Score, .Croix_Score + 1) < 2 )
-	{
-		bg_updatescore "bat_b01",.Guillaume_Score,.Croix_Score;
-		mapannounce "bat_b01","The Guillaume Crystal has been destroyed!",1,0x0000FF;
-		donpcevent "Flavius_BG1::OnRoundStart";
-	}
-	else
-	{
-		bg_updatescore "bat_b01",.Guillaume_Score,.Croix_Score;
-		mapannounce "bat_b01","The Croix army has won the Battle of Flavius!",1,0xFF0000;
-		set $@FlaviusBG1_Victory, 2;
-		donpcevent "Flavius_BG1::OnMatchEnd";
-	}
-	end;
-
-OnCroixBreak:
-	donpcevent "Flavius_BG1::OnRoundStop";
-	set .Croix_Loss, .Croix_Loss + 1;
-	if( set(.Guillaume_Score, .Guillaume_Score + 1) < 2 )
-	{
-		bg_updatescore "bat_b01",.Guillaume_Score,.Croix_Score;
-		mapannounce "bat_b01","The Croix Crystal has been destroyed!",1,0xFF0000;
-		donpcevent "Flavius_BG1::OnRoundStart";
-	}
-	else
-	{
-		bg_updatescore "bat_b01",.Guillaume_Score,.Croix_Score;
-		mapannounce "bat_b01","The Guillaume army has won the Battle of Flavius!",1,0x0000FF;
-		set $@FlaviusBG1_Victory, 1;
-		donpcevent "Flavius_BG1::OnMatchEnd";
-	}
-	end;
-
-OnTimer2400000:
-	mapannounce "bat_b01","Battle of Flavius will ends in 5 minutes",1,0x006400;
-	end;
-OnTimer2640000:
-	mapannounce "bat_b01","Battle of Flavius will ends in 1 minute",1,0x006400;
-	end;
-
-OnTimer2700000:
-	if( .Croix_Score > .Guillaume_Score )
-	{
-		mapannounce "bat_b01","The Croix army has won the Battle of Flavius!",1,0xFF0000;
-		set $@FlaviusBG1_Victory, 2;
-	}
-	else if( .Croix_Score < .Guillaume_Score )
-	{
-		mapannounce "bat_b01","The Guillaume army has won the Battle of Flavius!",1,0x0000FF;
-		set $@FlaviusBG1_Victory, 1;
-	}
-	else
-	{
-		mapannounce "bat_b01","The Battle of Flavius is over. The time is out, this is a Tie",1,0x006400;
-		set $@FlaviusBG1_Victory, 3;
-	}
-
-OnMatchEnd:
-	set $@FlaviusBG1, 2;
-	stopnpctimer;
-	donpcevent "#gfl1_respawn::OnBGStop";
-	donpcevent "#cfl1_respawn::OnBGStop";
-	disablenpc "Therapist in battle#fl11";
-	disablenpc "Therapist in battle#fl12";
-	enablenpc "Guillaume Vintenar#fl1";
-	enablenpc "Croix Vintenar#fl1";
-	sleep 2000;
-	bg_warp $@FlaviusBG1_id1,"bat_b01",390,10;
-	bg_warp $@FlaviusBG1_id2,"bat_b01",10,290;
-	sleep 3000;
-	mapannounce "bat_b01","Battle of Flavius will close in 1 minute!",1,0x006400;
-	initnpctimer;
-	end;
-
-OnTimer30000:
-	if( $@FlaviusBG1 == 2 )
-		mapannounce "bat_b01","Battle of Flavius will close in 30 seconds!",1,0x006400;
-	end;
-OnTimer50000:
-	if( $@FlaviusBG1 == 2 )
-		mapannounce "bat_b01","Battle of Flavius will close in 10 seconds!",1,0x006400;
-	end;
-
-OnTimer60000:
-	if( $@FlaviusBG1 != 2 )
-		end;
-OnReset:
-	stopnpctimer;
-	donpcevent "Flavius_BG1::OnRoundStop";
-	set .Guillaume_Score, 0;
-	set .Guillaume_Crystal, 0;
-	set .Guillaume_Loss, 0;
-	set .Croix_Score, 0;
-	set .Croix_Crystal, 0;
-	set .Croix_Loss, 0;
-	set .Match, 0;
-	set $@FlaviusBG1_Victory, 0;
-	// NPC's
-	disablenpc "Guillaume Vintenar#fl1";
-	disablenpc "Croix Vintenar#fl1";
-	disablenpc "Therapist in battle#fl11";
-	disablenpc "Therapist in battle#fl12";
-
-	if( $@FlaviusBG1_id1 ) { bg_destroy $@FlaviusBG1_id1; set $@FlaviusBG1_id1, 0; }
-	if( $@FlaviusBG1_id2 ) { bg_destroy $@FlaviusBG1_id2; set $@FlaviusBG1_id2, 0; }
-	sleep 1000;
-	mapwarp "bat_b01","bat_room",155,150;
-	sleep 2000;
-	maprespawnguildid "bat_b01",0,3; // Just in case someone else
-	sleep 2000;
-	bg_updatescore "bat_b01",0,0;
-	set $@FlaviusBG1, 0;
-	donpcevent "Flavius_BG1::OnReadyCheck";
-	end;
-}
-
-// Battleground rewards
-// *********************************************************************
-
-bat_b01,390,13,5	script	Guillaume Vintenar#fl1	419,{
-	if( $@FlaviusBG1_Victory )
-	{
-		if( $@FlaviusBG1_Victory == Bat_Team )
-		{ // Victory
-			mes "[Swandery]";
-			mes "Blessed Guillaume!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-			set .@Reward, 9;
-		}
-		else
-		{ // 
-			mes "[Swandery]";
-			mes "You lost, but you're dedicated to this battle.";
-			mes "This is a reward for your great dedication by Guillaume Marollo!";
-			mes "Just take this defeat a lesson, and later you would definitely learn.";
-			close2;
-			set .@Reward, 3;
-		}
-
-		setquest 2070;
-		getitem 7829, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-bat_b01,10,293,5	script	Croix Vintenar#fl1	415,{
-	if( $@FlaviusBG1_Victory )
-	{
-		if( $@FlaviusBG1_Victory == Bat_Team )
-		{ // Victory
-			mes "[Swandery]";
-			mes "Blessed Croax!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-			set .@Reward, 9;
-		}
-		else
-		{ // 
-			mes "[Swandery]";
-			mes "Oh, " + strcharinfo(0) + ". Don't be sad.";
-			mes "Even though we didn't win, we did our best.";
-			mes "This is a Royal gift from Croix, and please don't forget this battle. We can win the next.";
-			close2;
-			set .@Reward, 3;
-		}
-
-		setquest 2070;
-		getitem 7829, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-// Battleground Therapist
-// *********************************************************************
-
-bat_b01,390,13,5	script	Therapist in battle#fl12	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-bat_b01,10,293,5	script	Therapist in battle#fl11	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-// Battleground Respawn
-// *********************************************************************
-
-bat_b01,390,10,0	script	#gfl1_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer24000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer25000:
-	areapercentheal "bat_b01",382,2,397,17,100,100;
-	areawarp "bat_b01",382,2,397,17,"bat_b01",311,224;
-	initnpctimer;
-	end;
-}
-
-bat_b01,10,290,0	script	#cfl1_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer24000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer25000:
-	areapercentheal "bat_b01",2,282,17,297,100,100;
-	areawarp "bat_b01",2,282,17,297,"bat_b01",87,75;
-	initnpctimer;
-	end;
-}
-
-// Flags
-// *********************************************************************
-
-bat_b01,304,231,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat1	973
-bat_b01,319,231,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat2	973
-bat_b01,304,218,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat3	973
-bat_b01,319,218,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat4	973
-bat_b01,304,231,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat5	973
-bat_b01,304,231,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat6	973
-bat_b01,335,142,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat7	973
-bat_b01,335,157,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat8	973
-bat_b01,390,16,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat9	973
-bat_b01,292,163,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat19	973
-bat_b01,292,136,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat20	973
-bat_b01,241,185,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat21	973
-bat_b01,247,179,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat22	973
-
-bat_b01,96,81,1	duplicate(Croix camp#bat)	Croix camp#bat1	974
-bat_b01,96,68,1	duplicate(Croix camp#bat)	Croix camp#bat2	974
-bat_b01,79,81,1	duplicate(Croix camp#bat)	Croix camp#bat3	974
-bat_b01,79,68,1	duplicate(Croix camp#bat)	Croix camp#bat4	974
-bat_b01,96,81,1	duplicate(Croix camp#bat)	Croix camp#bat5	974
-bat_b01,96,81,1	duplicate(Croix camp#bat)	Croix camp#bat6	974
-bat_b01,59,164,1	duplicate(Croix camp#bat)	Croix camp#bat7	974
-bat_b01,59,137,1	duplicate(Croix camp#bat)	Croix camp#bat8	974
-bat_b01,10,296,1	duplicate(Croix camp#bat)	Croix camp#bat9	974
-bat_b01,110,162,1	duplicate(Croix camp#bat)	Croix camp#bat18	974
-bat_b01,110,137,1	duplicate(Croix camp#bat)	Croix camp#bat19	974
-bat_b01,152,120,1	duplicate(Croix camp#bat)	Croix camp#bat20	974
-bat_b01,158,114,1	duplicate(Croix camp#bat)	Croix camp#bat21	974

+ 0 - 428
npc/custom/battleground/unofficial/bg_flavius_02.txt

@@ -1,428 +0,0 @@
-// ==============================================================================
-// BattleGround System - Flavius 2
-// ==============================================================================
-
-// Registration NPC's
-// *********************************************************************
-
-bat_room,142,227,4	script	Registration::Fl2R_Guillaume	418,{
-	end;
-OnInit:
-	waitingroom "Battle Station 10 Players",10,"Flavius_BG2::OnGuillaumeJoin",1;
-	end;
-OnEnterBG:
-	set $@FlaviusBG2_id1, waitingroom2bg("bat_b02",390,10,"Flavius_BG2::OnGuillaumeQuit","");
-	end;
-}
-
-bat_room,142,204,0	script	Registration::Fl2R_Croix	414,{
-	end;
-OnInit:
-	waitingroom "Battle Station 10 Players",10,"Flavius_BG2::OnCroixJoin",1;
-	end;
-OnEnterBG:
-	set $@FlaviusBG2_id2, waitingroom2bg("bat_b02",10,290,"Flavius_BG2::OnCroixQuit","");
-	end;
-}
-
-// Battleground Engine
-// *********************************************************************
-
--	script	Flavius_BG2	-1,{
-	end;
-
-OnInit:
-	disablenpc "Guillaume Vintenar#fl2";
-	disablenpc "Croix Vintenar#fl2";
-	disablenpc "Therapist in battle#fl21";
-	disablenpc "Therapist in battle#fl22";
-	end;
-
-OnGuillaumeQuit:
-OnCroixQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-	end;
-
-OnGuillaumeJoin:
-OnCroixJoin:
-	if( $@FlaviusBG2 == 0 )
-		donpcevent "Flavius_BG2::OnReadyCheck";
-	end;
-
-OnReadyCheck:
-	if( $@FlaviusBG2 )
-		end;
-	set .@Guillaume, getwaitingroomstate(0,"Fl2R_Guillaume");
-	set .@Croix, getwaitingroomstate(0,"Fl2R_Croix");
-	
-	if( .@Guillaume < 10 || .@Croix < 10 )
-	{
-		mapannounce "bat_room","Battleground -- Flavius [80-99] G: " + .@Guillaume + "/10, C: " + .@Croix + "/10",1,0x808000;
-		end;
-	}
-
-	// BG Variables
-	set $@FlaviusBG2, 1;
-	set $@FlaviusBG2_Victory, 0;
-	set .Guillaume_Score, 0;
-	set .Guillaume_Loss, 0;
-	set .Croix_Score, 0;
-	set .Croix_Loss, 0;
-	set .Match, 0;
-	// Prepare NPC
-	donpcevent "#gfl2_respawn::OnBGStart";
-	donpcevent "#cfl2_respawn::OnBGStart";
-	enablenpc "Therapist in battle#fl21";
-	enablenpc "Therapist in battle#fl22";
-	disablenpc "Guillaume Vintenar#fl2";
-	disablenpc "Croix Vintenar#fl2";
-	// Build and Warp Teams
-	donpcevent "Fl2R_Guillaume::OnEnterBG";
-	donpcevent "Fl2R_Croix::OnEnterBG";
-	announce "Battleground -- Flavius [80-99] has started!",0,0x808000;
-	initnpctimer;
-	// Start Match!!
-
-OnRoundStart:
-	sleep 2000;
-	if( $@FlaviusBG2 != 1 ) end;
-
-	areapercentheal "bat_b02",382,2,397,17,100,100;
-	areapercentheal "bat_b02",2,282,17,297,100,100;
-	bg_warp $@FlaviusBG2_id1,"bat_b02",311,224;
-	bg_warp $@FlaviusBG2_id2,"bat_b02",87,75;
-
-	sleep 2000;
-	if( $@FlaviusBG2 != 1 ) end;
-
-	set .Match, .Match + 1;
-	// Crystal Spawn
-	set .Guillaume_Crystal, bg_monster($@FlaviusBG2_id1,"bat_b02",328,150,"Crystal Guillaume",1914,"Flavius_BG2::OnGuillaumeBreak");
-	setcell "bat_b02",327,151,329,149,cell_basilica,1;
-	setcell "bat_b02",327,151,329,149,cell_walkable,1;
-
-	set .Croix_Crystal, bg_monster($@FlaviusBG2_id2,"bat_b02",62,150,"Crystal Croix",1915,"Flavius_BG2::OnCroixBreak");
-	setcell "bat_b02",62,149,60,151,cell_basilica,1;
-	setcell "bat_b02",62,149,60,151,cell_walkable,1;
-
-	// Guardian Spawns
-	bg_monster $@FlaviusBG2_id1,"bat_b02",328,160,"Guillaume Guardian",1949,"Flavius_BG2::OnGuiGuardian";
-	bg_monster $@FlaviusBG2_id1,"bat_b02",328,140,"Guillaume Guardian",1950,"Flavius_BG2::OnGuiGuardian";
-	set .Guillaume_Guardian, 2;
-	bg_monster $@FlaviusBG2_id2,"bat_b02",62,160,"Croix Guardian",1949,"Flavius_BG2::OnCroGuardian";
-	bg_monster $@FlaviusBG2_id2,"bat_b02",61,140,"Croix Guardian",1950,"Flavius_BG2::OnCroGuardian";
-	set .Croix_Guardian, 2;
-	// Announces
-	mapannounce "bat_b02","The Battle of Flavius [ " + .Match + " ] Round has begun!!",1,0x808000;
-	end;
-
-OnRoundStop:
-	// Remove Monsters
-	killmonster "bat_b02","Flavius_BG2::OnGuiGuardian";
-	killmonster "bat_b02","Flavius_BG2::OnCroGuardian";
-	setcell "bat_b02",327,151,329,149,cell_walkable,0;
-	setcell "bat_b02",327,151,329,149,cell_basilica,0;
-	killmonster "bat_b02","Flavius_BG2::OnGuillaumeBreak";
-	setcell "bat_b02",62,149,60,151,cell_walkable,0;
-	setcell "bat_b02",62,149,60,151,cell_basilica,0;
-	killmonster "bat_b02","Flavius_BG2::OnCroixBreak";
-	end;
-
-OnGuiGuardian:
-	if( set(.Guillaume_Guardian, .Guillaume_Guardian - 1) <= 0 )
-	{
-		setcell "bat_b02",327,151,329,149,cell_walkable,0;
-		setcell "bat_b02",327,151,329,149,cell_basilica,0;
-		mapannounce "bat_b02","The Guillaume Crystal is vulnerable to attack!",1,0x0000FF;
-	}
-	end;
-
-OnCroGuardian:
-	if( set(.Croix_Guardian, .Croix_Guardian - 1) <= 0 )
-	{
-		setcell "bat_b02",62,149,60,151,cell_walkable,0;
-		setcell "bat_b02",62,149,60,151,cell_basilica,0;
-		mapannounce "bat_b02","The Croix Crystal is vulnerable to attack!",1,0xFF0000;
-	}
-	end;
-
-OnGuillaumeBreak:
-	donpcevent "Flavius_BG2::OnRoundStop";
-	set .Guillaume_Loss, .Guillaume_Loss + 1;
-	if( set(.Croix_Score, .Croix_Score + 1) < 2 )
-	{
-		bg_updatescore "bat_b02",.Guillaume_Score,.Croix_Score;
-		mapannounce "bat_b02","The Guillaume Crystal has been destroyed!",1,0x0000FF;
-		donpcevent "Flavius_BG2::OnRoundStart";
-	}
-	else
-	{
-		bg_updatescore "bat_b02",.Guillaume_Score,.Croix_Score;
-		mapannounce "bat_b02","The Croix army has won the Battle of Flavius!",1,0xFF0000;
-		set $@FlaviusBG2_Victory, 2;
-		donpcevent "Flavius_BG2::OnMatchEnd";
-	}
-	end;
-
-OnCroixBreak:
-	donpcevent "Flavius_BG2::OnRoundStop";
-	set .Croix_Loss, .Croix_Loss + 1;
-	if( set(.Guillaume_Score, .Guillaume_Score + 1) < 2 )
-	{
-		bg_updatescore "bat_b02",.Guillaume_Score,.Croix_Score;
-		mapannounce "bat_b02","The Croix Crystal has been destroyed!",1,0xFF0000;
-		donpcevent "Flavius_BG2::OnRoundStart";
-	}
-	else
-	{
-		bg_updatescore "bat_b02",.Guillaume_Score,.Croix_Score;
-		mapannounce "bat_b02","The Guillaume army has won the Battle of Flavius!",1,0x0000FF;
-		set $@FlaviusBG2_Victory, 1;
-		donpcevent "Flavius_BG2::OnMatchEnd";
-	}
-	end;
-
-OnTimer2400000:
-	mapannounce "bat_b02","Battle of Flavius will ends in 5 minutes",1,0x808000;
-	end;
-OnTimer2640000:
-	mapannounce "bat_b02","Battle of Flavius will ends in 1 minute",1,0x808000;
-	end;
-
-OnTimer2700000:
-	if( .Croix_Score > .Guillaume_Score )
-	{
-		mapannounce "bat_b02","The Croix army has won the Battle of Flavius!",1,0xFF0000;
-		set $@FlaviusBG2_Victory, 2;
-	}
-	else if( .Croix_Score < .Guillaume_Score )
-	{
-		mapannounce "bat_b02","The Guillaume army has won the Battle of Flavius!",1,0x0000FF;
-		set $@FlaviusBG2_Victory, 1;
-	}
-	else
-	{
-		mapannounce "bat_b02","The Battle of Flavius is over. The time is out, this is a Tie",1,0x808000;
-		set $@FlaviusBG2_Victory, 3;
-	}
-
-OnMatchEnd:
-	set $@FlaviusBG2, 2;
-	stopnpctimer;
-	donpcevent "#gfl2_respawn::OnBGStop";
-	donpcevent "#cfl2_respawn::OnBGStop";
-	disablenpc "Therapist in battle#fl21";
-	disablenpc "Therapist in battle#fl22";
-	enablenpc "Guillaume Vintenar#fl2";
-	enablenpc "Croix Vintenar#fl2";
-	sleep 2000;
-	bg_warp $@FlaviusBG2_id1,"bat_b02",390,10;
-	bg_warp $@FlaviusBG2_id2,"bat_b02",10,290;
-	sleep 3000;
-	mapannounce "bat_b02","Battle of Flavius will close in 1 minute!",1,0x808000;
-	initnpctimer;
-	end;
-
-OnTimer30000:
-	if( $@FlaviusBG2 == 2 )
-		mapannounce "bat_b02","Battle of Flavius will close in 30 seconds!",1,0x808000;
-	end;
-OnTimer50000:
-	if( $@FlaviusBG2 == 2 )
-		mapannounce "bat_b02","Battle of Flavius will close in 10 seconds!",1,0x808000;
-	end;
-
-OnTimer60000:
-	if( $@FlaviusBG2 != 2 )
-		end;
-OnReset:
-	stopnpctimer;
-	donpcevent "Flavius_BG2::OnRoundStop";
-	set .Guillaume_Score, 0;
-	set .Guillaume_Crystal, 0;
-	set .Guillaume_Loss, 0;
-	set .Croix_Score, 0;
-	set .Croix_Crystal, 0;
-	set .Croix_Loss, 0;
-	set .Match, 0;
-	set $@FlaviusBG2_Victory, 0;
-	// NPC's
-	disablenpc "Guillaume Vintenar#fl2";
-	disablenpc "Croix Vintenar#fl2";
-	disablenpc "Therapist in battle#fl21";
-	disablenpc "Therapist in battle#fl22";
-
-	if( $@FlaviusBG2_id1 ) { bg_destroy $@FlaviusBG2_id1; set $@FlaviusBG2_id1, 0; }
-	if( $@FlaviusBG2_id2 ) { bg_destroy $@FlaviusBG2_id2; set $@FlaviusBG2_id2, 0; }
-	sleep 1000;
-	mapwarp "bat_b02","bat_room",155,150;
-	sleep 2000;
-	maprespawnguildid "bat_b02",0,3; // Just in case someone else
-	sleep 2000;
-	bg_updatescore "bat_b02",0,0;
-	set $@FlaviusBG2, 0;
-	donpcevent "Flavius_BG2::OnReadyCheck";
-	end;
-}
-
-// Battleground rewards
-// *********************************************************************
-
-bat_b02,390,13,5	script	Guillaume Vintenar#fl2	419,{
-	if( $@FlaviusBG2_Victory )
-	{
-		if( $@FlaviusBG2_Victory == Bat_Team )
-		{ // Victory
-			mes "[Swandery]";
-			mes "Blessed Guillaume!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-			set .@Reward, 9;
-		}
-		else
-		{ // 
-			mes "[Swandery]";
-			mes "You lost, but you're dedicated to this battle.";
-			mes "This is a reward for your great dedication by Guillaume Marollo!";
-			mes "Just take this defeat a lesson, and later you would definitely learn.";
-			close2;
-			set .@Reward, 3;
-		}
-
-		setquest 2070;
-		getitem 7829, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-bat_b02,10,293,5	script	Croix Vintenar#fl2	415,{
-	if( $@FlaviusBG2_Victory )
-	{
-		if( $@FlaviusBG2_Victory == Bat_Team )
-		{ // Victory
-			mes "[Swandery]";
-			mes "Blessed Croax!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-			set .@Reward, 9;
-		}
-		else
-		{ // 
-			mes "[Swandery]";
-			mes "Oh, " + strcharinfo(0) + ". Don't be sad.";
-			mes "Even though we didn't win, we did our best.";
-			mes "This is a Royal gift from Croix, and please don't forget this battle. We can win the next.";
-			close2;
-			set .@Reward, 3;
-		}
-
-		setquest 2070;
-		getitem 7829, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-// Battleground Therapist
-// *********************************************************************
-
-bat_b02,390,13,5	script	Therapist in battle#fl22	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-bat_b02,10,293,5	script	Therapist in battle#fl21	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-// Battleground Respawn
-// *********************************************************************
-
-bat_b02,390,10,0	script	#gfl2_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer24000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer25000:
-	areapercentheal "bat_b02",382,2,397,17,100,100;
-	areawarp "bat_b02",382,2,397,17,"bat_b02",311,224;
-	initnpctimer;
-	end;
-}
-
-bat_b02,10,290,0	script	#cfl2_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer24000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer25000:
-	areapercentheal "bat_b02",2,282,17,297,100,100;
-	areawarp "bat_b02",2,282,17,297,"bat_b02",87,75;
-	initnpctimer;
-	end;
-}
-
-// Flags
-// *********************************************************************
-
-bat_b02,304,231,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat32	973
-bat_b02,319,231,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat33	973
-bat_b02,304,218,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat34	973
-bat_b02,319,218,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat35	973
-bat_b02,304,231,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat36	973
-bat_b02,304,231,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat37	973
-bat_b02,335,142,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat38	973
-bat_b02,335,157,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat39	973
-bat_b02,390,16,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat40	973
-bat_b02,292,163,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat41	973
-bat_b02,292,136,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat42	973
-bat_b02,241,185,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat43	973
-bat_b02,247,179,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat44	973
-
-bat_b02,96,81,1	duplicate(Croix camp#bat)	Croix camp#bat30	974
-bat_b02,96,68,1	duplicate(Croix camp#bat)	Croix camp#bat31	974
-bat_b02,79,81,1	duplicate(Croix camp#bat)	Croix camp#bat32	974
-bat_b02,79,68,1	duplicate(Croix camp#bat)	Croix camp#bat33	974
-bat_b02,96,81,1	duplicate(Croix camp#bat)	Croix camp#bat34	974
-bat_b02,96,81,1	duplicate(Croix camp#bat)	Croix camp#bat35	974
-bat_b02,59,164,1	duplicate(Croix camp#bat)	Croix camp#bat36	974
-bat_b02,59,137,1	duplicate(Croix camp#bat)	Croix camp#bat37	974
-bat_b02,10,296,1	duplicate(Croix camp#bat)	Croix camp#bat38	974
-bat_b02,110,162,1	duplicate(Croix camp#bat)	Croix camp#bat39	974
-bat_b02,110,137,1	duplicate(Croix camp#bat)	Croix camp#bat40	974
-bat_b02,152,120,1	duplicate(Croix camp#bat)	Croix camp#bat41	974
-bat_b02,158,114,1	duplicate(Croix camp#bat)	Croix camp#bat42	974

+ 0 - 378
npc/custom/battleground/unofficial/bg_kvm01.txt

@@ -1,378 +0,0 @@
-// ==============================================================================
-// BattleGround System - KvM 80~99
-// ==============================================================================
-
-// Registration NPC's
-// *********************************************************************
-
-bat_room,253,227,4	script	Registration::KvM01R_Guillaume	418,{ // KvM Guillaume
-	end;
-
-OnInit:
-	waitingroom "Battle Station 5 Players",5,"KvM01_BG::OnGuillaumeJoin",1;
-	end;
-	
-OnEnterBG:
-	set $@KvM01BG_id1, waitingroom2bg("bat_c01",53,128,"KvM01_BG::OnGuillaumeQuit","KvM01_BG::OnGuillaumeDie");
-	end;
-}
-
-bat_room,253,204,0	script	Registration::KvM01R_Croix	414,{ // KvM Croix
-	end;
-
-OnInit:
-	waitingroom "Battle Station 5 Players",5,"KvM01_BG::OnCroixJoin",1;
-	end;
-
-OnEnterBG:
-	set $@KvM01BG_id2, waitingroom2bg("bat_c01",146,55,"KvM01_BG::OnCroixQuit","KvM01_BG::OnCroixDie");
-	end;
-}
-
-// Light Effects
-// *********************************************************************
-
-bat_c01,54,123,0	script	#bat_c01a	111,{
-	end;
-
-OnKvM01LightA: specialeffect EF_BEGINSPELL2; end;
-OnKvM01LightB: specialeffect EF_BEGINSPELL3; end;
-OnKvM01LightC: specialeffect EF_BEGINSPELL4; end;
-}
-
-bat_c01,56,125,0	duplicate(#bat_c01a)	#bat_c01b	111
-bat_c01,58,127,0	duplicate(#bat_c01a)	#bat_c01c	111
-bat_c01,141,56,0	duplicate(#bat_c01a)	#bat_c01d	111
-bat_c01,143,58,0	duplicate(#bat_c01a)	#bat_c01e	111
-bat_c01,145,60,0	duplicate(#bat_c01a)	#bat_c01f	111
-
-// Battleground Engine
-// *********************************************************************
-
--	script	KvM01_BG	-1,{
-	end;
-
-OnInit:
-	setwall "bat_c01",54,122,6,7,0,"batc01wall_a";
-	setwall "bat_c01",55,122,5,7,0,"batc01wall_b";
-	setwall "bat_c01",140,56,6,7,0,"batc01wall_c";
-	setwall "bat_c01",140,57,5,7,0,"batc01wall_d";
-	disablenpc "TherapistKvM01a";
-	disablenpc "TherapistKvM01b";
-	disablenpc "VintenarKvM01a";
-	disablenpc "VintenarKvM01b";
-	end;
-
-OnGuillaumeJoin:
-OnCroixJoin:
-	donpcevent "KvM01_BG::OnReadyCheck";
-	end;
-
-OnGuillaumeQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-OnGuillaumeDie:
-	if( $@KvM01BG == 2 )
-	{
-		set .Guillaume_Count, .Guillaume_Count - 1;
-		set .Croix_Score, .Croix_Score + 1;
-		bg_updatescore "bat_c01",.Guillaume_Score,.Croix_Score;
-		if( .Guillaume_Count < 1 ) donpcevent "KvM01_BG::OnCroixWin";
-	}
-	end;
-
-OnCroixQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-OnCroixDie:
-	if( $@KvM01BG == 2 )
-	{
-		set .Croix_Count, .Croix_Count - 1;
-		set .Guillaume_Score, .Guillaume_Score + 1;
-		bg_updatescore "bat_c01",.Guillaume_Score,.Croix_Score;
-		if( .Croix_Count < 1 ) donpcevent "KvM01_BG::OnGuillaumeWin";
-	}
-	end;
-
-OnReadyCheck:
-	if( $@KvM01BG )
-		end;
-	set .@Guillaume, getwaitingroomstate(0,"KvM01R_Guillaume");
-	set .@Croix, getwaitingroomstate(0,"KvM01R_Croix");
-
-	if( .@Guillaume < 5 || .@Croix < 5 )
-	{
-		if( .@Guillaume > 3 && .@Croix > 3 && !agitcheck() && !agitcheck2() && $@KvM_Flood < gettimetick(2) )
-		{
-			announce "Battleground -- Kreiger Von Midgard [80-99] G: " + .@Guillaume + "/5, C: " + .@Croix + "/5",0,0x696969;
-			set $@KvM_Flood, gettimetick(2) + 15;
-		}
-		else
-			mapannounce "bat_room","Battleground -- Kreiger Von Midgard [80-99] G: " + .@Guillaume + "/5, C: " + .@Croix + "/5",1,0x696969;
-		end;
-	}
-
-	set $@KvM01BG, 1; // Starting
-	donpcevent "KvM01R_Croix::OnEnterBG";
-	donpcevent "KvM01R_Guillaume::OnEnterBG";
-	donpcevent "KvM01_BG::OnStart";
-	end;
-
-OnStart:
-	announce "Battleground -- Kreiger Von Midgard [80-99] has started!",0,0x696969;
-	enablenpc "TherapistKvM01a";
-	enablenpc "TherapistKvM01b";
-	disablenpc "VintenarKvM01a";
-	disablenpc "VintenarKvM01b";
-	set $@KvM01BG_Victory, 0;
-	sleep 2000;
-	// Warp Teams
-	bg_warp $@KvM01BG_id1,"bat_c01",53,128;
-	bg_warp $@KvM01BG_id2,"bat_c01",146,55;
-	// ScoreBoard
-	set .Guillaume_Score, 0;
-	set .Croix_Score, 0;
-	initnpctimer;
-	end;
-
-OnTimer5000:
-	areapercentheal "bat_c01",50,123,58,131,100,100;
-	areapercentheal "bat_c01",141,52,149,60,100,100;
-	mapannounce "bat_c01","The Battle will start in 25 seconds!!",1,0x696969;
-	end;
-
-OnTimer26000:
-	mapannounce "bat_c01","The Battle will start in 4 seconds!!",1,0x696969;
-	end;
-
-OnTimer27000:
-	donpcevent "::OnKvM01LightA";
-	end;
-
-OnTimer28000:
-	donpcevent "::OnKvM01LightB";
-	end;
-	
-OnTimer29000:
-	donpcevent "::OnKvM01LightC";
-	end;
-
-OnTimer30000:
-	// Team Members
-	set .Guillaume_Count, bg_get_data($@KvM01BG_id1, 0);
-	set .Croix_Count, bg_get_data($@KvM01BG_id2, 0);
-	if( .Guillaume_Count < 5 || .Croix_Count < 5 )
-	{
-		set $@KvM01BG_Victory, 3;
-		set $@KvM01BG, 3;
-		mapannounce "bat_c01","There are not enough players to start the battle",1,0x696969;
-		stopnpctimer;
-		sleep 2000;
-		donpcevent "KvM01_BG::OnStop";
-		end;
-	}
-
-	set $@KvM01BG, 2; // Playing
-	areapercentheal "bat_c01",50,123,58,131,100,100;
-	bg_warp $@KvM01BG_id1,"bat_c01",62,119;
-	areapercentheal "bat_c01",141,52,149,60,100,100;
-	bg_warp $@KvM01BG_id2,"bat_c01",137,64;
-	end;
-
-OnTimer32000:
-	mapannounce "bat_c01","The Battle of Kreiger Von Midgard has begun!!",1,0x696969;
-	end;
-
-OnTimer300000:
-	mapannounce "bat_c01","The Battle will ends in 30 seconds!!",1,0x696969;
-	end;
-
-OnTimer330000:
-	if( .Croix_Count > .Guillaume_Count )
-		donpcevent "KvM01_BG::OnCroixWin";
-	else if( .Croix_Count < .Guillaume_Count )
-		donpcevent "KvM01_BG::OnGuillaumeWin";
-	else
-	{ // Draw Game
-		set $@KvM01BG, 3;
-		set $@KvM01BG_Victory, 3;
-
-		stopnpctimer;
-		sleep 2000;
-		mapannounce "bat_c01","The time is out! This is a Tie...",1,0x696969;
-		donpcevent "KvM01_BG::OnStop";
-	}
-	end;
-
-OnGuillaumeWin:
-	set $@KvM01BG, 3;
-	set $@KvM01BG_Victory, 1;
-	
-	stopnpctimer;
-	sleep 2000;
-	mapannounce "bat_c01","The Guillaume Army has won the Battle of Kreiger Von Midgard",1,0x0000FF;
-	donpcevent "KvM01_BG::OnStop";
-	end;
-
-OnCroixWin:
-	set $@KvM01BG, 3;
-	set $@KvM01BG_Victory, 2;
-
-	stopnpctimer;
-	sleep 2000;
-	mapannounce "bat_c01","The Croix Army has won the Battle of Kreiger Von Midgard",1,0xFF0000;
-	donpcevent "KvM01_BG::OnStop";
-	end;
-
-OnStop:
-	disablenpc "TherapistKvM01a";
-	disablenpc "TherapistKvM01b";
-	enablenpc "VintenarKvM01a";
-	enablenpc "VintenarKvM01b";
-	// Warp Teams
-	bg_warp $@KvM01BG_id1,"bat_c01",53,128;
-	bg_warp $@KvM01BG_id2,"bat_c01",146,55;
-	donpcevent "KvM01_BG_Out::OnBegin";
-	end;
-
-OnReset:
-	stopnpctimer;
-	stopnpctimer "KvM01_BG_Out";
-	set .Croix_Count, 0;
-	set .Guillaume_Count, 0;
-	set .Croix_Score, 0;
-	set .Guillaume_Score, 0;
-	set $@KvM01BG_Victory, 0;
-	if( $@KvM01BG_id1 ) { bg_destroy $@KvM01BG_id1; set $@KvM01BG_id1, 0; }
-	if( $@KvM01BG_id2 ) { bg_destroy $@KvM01BG_id2; set $@KvM01BG_id2, 0; }
-	disablenpc "TherapistKvM01a";
-	disablenpc "TherapistKvM01b";
-	disablenpc "VintenarKvM01a";
-	disablenpc "VintenarKvM01b";
-	sleep 1000;
-	mapwarp "bat_c01","bat_room",155,150;
-	sleep 2000;
-	maprespawnguildid "bat_c01",0,3; // Just in case someone else
-	bg_updatescore "bat_c01",0,0;
-	sleep 2000;
-	set $@KvM01BG, 0;
-	donpcevent "KvM01_BG::OnReadyCheck"; // Maybe a game is ready to start
-	end;
-}
-
--	script	KvM01_BG_Out	-1,{
-	end;
-
-OnBegin:
-	initnpctimer;
-	end;
-
-OnTimer3000:
-	mapannounce "bat_c01","Battle of Kreiger Von Midgard will close in 1 minute!",1,0x696969;
-	end;
-OnTimer30000:
-	mapannounce "bat_c01","Battle of Kreiger Von Midgard will close in 30 seconds!",1,0x696969;
-	end;
-OnTimer50000:
-	mapannounce "bat_c01","Battle of Kreiger Von Midgard will close in 10 seconds!",1,0x696969;
-	end;
-OnTimer60000:
-	donpcevent "KvM01_BG::OnReset";
-	end;
-}
-
-// Battleground Therapist
-// *********************************************************************
-
-bat_c01,51,130,5	script	Therapist in battle::TherapistKvM01a	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-bat_c01,148,53,1	script	Therapist in battle::TherapistKvM01b	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-// Battleground rewards
-// *********************************************************************
-
-bat_c01,51,130,5	script	Guillaume Vintenar::VintenarKvM01a	419,{
-	if( $@KvM01BG_Victory )
-	{
-		if( $@KvM01BG_Victory == 3 )
-		{
-			setquest 6025;
-			bg_leave;
-			warp "bat_room",155,150;
-			end;
-		}
-		else if( $@KvM01BG_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 5;
-			mes "[Swandery]";
-			mes "Blessed Guillaume!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "You lost, but you're dedicated to this battle.";
-			mes "This is a reward for your great dedication by Guillaume Marollo!";
-			mes "Just take this defeat a lesson, and later you would definitely learn.";
-			close2;
-		}
-
-		setquest 6025;
-		getitem 6376, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-bat_c01,148,53,1	script	Croix Vintenar::VintenarKvM01b	415,{
-	if( $@KvM01BG_Victory )
-	{
-		if( $@KvM01BG_Victory == 3 )
-		{
-			setquest 6025;
-			bg_leave;
-			warp "bat_room",155,150;
-			end;
-		}
-		else if( $@KvM01BG_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 5;
-			mes "[Swandery]";
-			mes "Blessed Croax!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "Oh, " + strcharinfo(0) + ". Don't be sad.";
-			mes "Even though we didn't win, we did our best.";
-			mes "This is a Royal gift from Croix, and please don't forget this battle. We can win the next.";
-			close2;
-		}
-
-		setquest 6025;
-		getitem 6376, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}

+ 0 - 378
npc/custom/battleground/unofficial/bg_kvm02.txt

@@ -1,378 +0,0 @@
-// ==============================================================================
-// BattleGround System - KvM 60~79
-// ==============================================================================
-
-// Registration NPC's
-// *********************************************************************
-
-bat_room,225,227,4	script	Registration::KvM02R_Guillaume	418,{ // KvM Guillaume
-	end;
-
-OnInit:
-	waitingroom "Battle Station 5 Players",5,"KvM02_BG::OnGuillaumeJoin",1;
-	end;
-	
-OnEnterBG:
-	set $@KvM02BG_id1, waitingroom2bg("bat_c02",53,128,"KvM02_BG::OnGuillaumeQuit","KvM02_BG::OnGuillaumeDie");
-	end;
-}
-
-bat_room,225,204,0	script	Registration::KvM02R_Croix	414,{ // KvM Croix
-	end;
-
-OnInit:
-	waitingroom "Battle Station 5 Players",5,"KvM02_BG::OnCroixJoin",1;
-	end;
-
-OnEnterBG:
-	set $@KvM02BG_id2, waitingroom2bg("bat_c02",146,55,"KvM02_BG::OnCroixQuit","KvM02_BG::OnCroixDie");
-	end;
-}
-
-// Light Effects
-// *********************************************************************
-
-bat_c02,54,123,0	script	#bat_c02a	111,{
-	end;
-
-OnKvM02LightA: specialeffect EF_BEGINSPELL2; end;
-OnKvM02LightB: specialeffect EF_BEGINSPELL3; end;
-OnKvM02LightC: specialeffect EF_BEGINSPELL4; end;
-}
-
-bat_c02,56,125,0	duplicate(#bat_c02a)	#bat_c02b	111
-bat_c02,58,127,0	duplicate(#bat_c02a)	#bat_c02c	111
-bat_c02,141,56,0	duplicate(#bat_c02a)	#bat_c02d	111
-bat_c02,143,58,0	duplicate(#bat_c02a)	#bat_c02e	111
-bat_c02,145,60,0	duplicate(#bat_c02a)	#bat_c02f	111
-
-// Battleground Engine
-// *********************************************************************
-
--	script	KvM02_BG	-1,{
-	end;
-
-OnInit:
-	setwall "bat_c02",54,122,6,7,0,"batc02wall_a";
-	setwall "bat_c02",55,122,5,7,0,"batc02wall_b";
-	setwall "bat_c02",140,56,6,7,0,"batc02wall_c";
-	setwall "bat_c02",140,57,5,7,0,"batc02wall_d";
-	disablenpc "TherapistKvM02a";
-	disablenpc "TherapistKvM02b";
-	disablenpc "VintenarKvM02a";
-	disablenpc "VintenarKvM02b";
-	end;
-
-OnGuillaumeJoin:
-OnCroixJoin:
-	donpcevent "KvM02_BG::OnReadyCheck";
-	end;
-
-OnGuillaumeQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-OnGuillaumeDie:
-	if( $@KvM02BG == 2 )
-	{
-		set .Guillaume_Count, .Guillaume_Count - 1;
-		set .Croix_Score, .Croix_Score + 1;
-		bg_updatescore "bat_c02",.Guillaume_Score,.Croix_Score;
-		if( .Guillaume_Count < 1 ) donpcevent "KvM02_BG::OnCroixWin";
-	}
-	end;
-
-OnCroixQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-OnCroixDie:
-	if( $@KvM02BG == 2 )
-	{
-		set .Croix_Count, .Croix_Count - 1;
-		set .Guillaume_Score, .Guillaume_Score + 1;
-		bg_updatescore "bat_c02",.Guillaume_Score,.Croix_Score;
-		if( .Croix_Count < 1 ) donpcevent "KvM02_BG::OnGuillaumeWin";
-	}
-	end;
-
-OnReadyCheck:
-	if( $@KvM02BG )
-		end;
-	set .@Guillaume, getwaitingroomstate(0,"KvM02R_Guillaume");
-	set .@Croix, getwaitingroomstate(0,"KvM02R_Croix");
-
-	if( .@Guillaume < 5 || .@Croix < 5 )
-	{
-		if( .@Guillaume > 3 && .@Croix > 3 && !agitcheck() && !agitcheck2() && $@KvM_Flood < gettimetick(2) )
-		{
-			announce "Battleground -- Kreiger Von Midgard [60-79] G: " + .@Guillaume + "/5, C: " + .@Croix + "/5",0,0x808080;
-			set $@KvM_Flood, gettimetick(2) + 15;
-		}
-		else
-			mapannounce "bat_room","Battleground -- Kreiger Von Midgard [60-79] G: " + .@Guillaume + "/5, C: " + .@Croix + "/5",1,0x808080;
-		end;
-	}
-
-	set $@KvM02BG, 1; // Starting
-	donpcevent "KvM02R_Croix::OnEnterBG";
-	donpcevent "KvM02R_Guillaume::OnEnterBG";
-	donpcevent "KvM02_BG::OnStart";
-	end;
-
-OnStart:
-	announce "Battleground -- Kreiger Von Midgard [60-79] has started!",0,0x808080;
-	enablenpc "TherapistKvM02a";
-	enablenpc "TherapistKvM02b";
-	disablenpc "VintenarKvM02a";
-	disablenpc "VintenarKvM02b";
-	set $@KvM02BG_Victory, 0;
-	sleep 2000;
-	// Warp Teams
-	bg_warp $@KvM02BG_id1,"bat_c02",53,128;
-	bg_warp $@KvM02BG_id2,"bat_c02",146,55;
-	// ScoreBoard
-	set .Guillaume_Score, 0;
-	set .Croix_Score, 0;
-	initnpctimer;
-	end;
-
-OnTimer5000:
-	areapercentheal "bat_c02",50,123,58,131,100,100;
-	areapercentheal "bat_c02",141,52,149,60,100,100;
-	mapannounce "bat_c02","The Battle will start in 25 seconds!!",1,0x808080;
-	end;
-
-OnTimer26000:
-	mapannounce "bat_c02","The Battle will start in 4 seconds!!",1,0x808080;
-	end;
-
-OnTimer27000:
-	donpcevent "::OnKvM02LightA";
-	end;
-
-OnTimer28000:
-	donpcevent "::OnKvM02LightB";
-	end;
-	
-OnTimer29000:
-	donpcevent "::OnKvM02LightC";
-	end;
-
-OnTimer30000:
-	// Team Members
-	set .Guillaume_Count, bg_get_data($@KvM02BG_id1, 0);
-	set .Croix_Count, bg_get_data($@KvM02BG_id2, 0);
-	if( .Guillaume_Count < 5 || .Croix_Count < 5 )
-	{
-		set $@KvM02BG_Victory, 3;
-		set $@KvM02BG, 3;
-		mapannounce "bat_c02","There are not enough players to start the battle",1,0x808080;
-		stopnpctimer;
-		sleep 2000;
-		donpcevent "KvM02_BG::OnStop";
-		end;
-	}
-
-	set $@KvM02BG, 2; // Playing
-	areapercentheal "bat_c02",50,123,58,131,100,100;
-	bg_warp $@KvM02BG_id1,"bat_c02",62,119;
-	areapercentheal "bat_c02",141,52,149,60,100,100;
-	bg_warp $@KvM02BG_id2,"bat_c02",137,64;
-	end;
-
-OnTimer32000:
-	mapannounce "bat_c02","The Battle of Kreiger Von Midgard has begun!!",1,0x808080;
-	end;
-
-OnTimer300000:
-	mapannounce "bat_c02","The Battle will ends in 30 seconds!!",1,0x808080;
-	end;
-
-OnTimer330000:
-	if( .Croix_Count > .Guillaume_Count )
-		donpcevent "KvM02_BG::OnCroixWin";
-	else if( .Croix_Count < .Guillaume_Count )
-		donpcevent "KvM02_BG::OnGuillaumeWin";
-	else
-	{ // Draw Game
-		set $@KvM02BG, 3;
-		set $@KvM02BG_Victory, 3;
-
-		stopnpctimer;
-		sleep 2000;
-		mapannounce "bat_c02","The time is out! This is a Tie...",1,0x808080;
-		donpcevent "KvM02_BG::OnStop";
-	}
-	end;
-
-OnGuillaumeWin:
-	set $@KvM02BG, 3;
-	set $@KvM02BG_Victory, 1;
-	
-	stopnpctimer;
-	sleep 2000;
-	mapannounce "bat_c02","The Guillaume Army has won the Battle of Kreiger Von Midgard",1,0x0000FF;
-	donpcevent "KvM02_BG::OnStop";
-	end;
-
-OnCroixWin:
-	set $@KvM02BG, 3;
-	set $@KvM02BG_Victory, 2;
-
-	stopnpctimer;
-	sleep 2000;
-	mapannounce "bat_c02","The Croix Army has won the Battle of Kreiger Von Midgard",1,0xFF0000;
-	donpcevent "KvM02_BG::OnStop";
-	end;
-
-OnStop:
-	disablenpc "TherapistKvM02a";
-	disablenpc "TherapistKvM02b";
-	enablenpc "VintenarKvM02a";
-	enablenpc "VintenarKvM02b";
-	// Warp Teams
-	bg_warp $@KvM02BG_id1,"bat_c02",53,128;
-	bg_warp $@KvM02BG_id2,"bat_c02",146,55;
-	donpcevent "KvM02_BG_Out::OnBegin";
-	end;
-
-OnReset:
-	stopnpctimer;
-	stopnpctimer "KvM02_BG_Out";
-	set .Croix_Count, 0;
-	set .Guillaume_Count, 0;
-	set .Croix_Score, 0;
-	set .Guillaume_Score, 0;
-	set $@KvM02BG_Victory, 0;
-	if( $@KvM02BG_id1 ) { bg_destroy $@KvM02BG_id1; set $@KvM02BG_id1, 0; }
-	if( $@KvM02BG_id2 ) { bg_destroy $@KvM02BG_id2; set $@KvM02BG_id2, 0; }
-	disablenpc "TherapistKvM02a";
-	disablenpc "TherapistKvM02b";
-	disablenpc "VintenarKvM02a";
-	disablenpc "VintenarKvM02b";
-	sleep 1000;
-	mapwarp "bat_c02","bat_room",155,150;
-	sleep 2000;
-	maprespawnguildid "bat_c02",0,3; // Just in case someone else
-	bg_updatescore "bat_c02",0,0;
-	sleep 2000;
-	set $@KvM02BG, 0;
-	donpcevent "KvM02_BG::OnReadyCheck"; // Maybe a game is ready to start
-	end;
-}
-
--	script	KvM02_BG_Out	-1,{
-	end;
-
-OnBegin:
-	initnpctimer;
-	end;
-
-OnTimer3000:
-	mapannounce "bat_c02","Battle of Kreiger Von Midgard will close in 1 minute!",1,0x808080;
-	end;
-OnTimer30000:
-	mapannounce "bat_c02","Battle of Kreiger Von Midgard will close in 30 seconds!",1,0x808080;
-	end;
-OnTimer50000:
-	mapannounce "bat_c02","Battle of Kreiger Von Midgard will close in 10 seconds!",1,0x808080;
-	end;
-OnTimer60000:
-	donpcevent "KvM02_BG::OnReset";
-	end;
-}
-
-// Battleground Therapist
-// *********************************************************************
-
-bat_c02,51,130,5	script	Therapist in battle::TherapistKvM02a	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-bat_c02,148,53,1	script	Therapist in battle::TherapistKvM02b	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-// Battleground rewards
-// *********************************************************************
-
-bat_c02,51,130,5	script	Guillaume Vintenar::VintenarKvM02a	419,{
-	if( $@KvM02BG_Victory )
-	{
-		if( $@KvM02BG_Victory == 3 )
-		{
-			setquest 6025;
-			bg_leave;
-			warp "bat_room",155,150;
-			end;
-		}
-		else if( $@KvM02BG_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 3;
-			mes "[Swandery]";
-			mes "Blessed Guillaume!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "You lost, but you're dedicated to this battle.";
-			mes "This is a reward for your great dedication by Guillaume Marollo!";
-			mes "Just take this defeat a lesson, and later you would definitely learn.";
-			close2;
-		}
-
-		setquest 6025;
-		getitem 6376, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-bat_c02,148,53,1	script	Croix Vintenar::VintenarKvM02b	415,{
-	if( $@KvM02BG_Victory )
-	{
-		if( $@KvM02BG_Victory == 3 )
-		{
-			setquest 6025;
-			bg_leave;
-			warp "bat_room",155,150;
-			end;
-		}
-		else if( $@KvM02BG_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 3;
-			mes "[Swandery]";
-			mes "Blessed Croax!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "Oh, " + strcharinfo(0) + ". Don't be sad.";
-			mes "Even though we didn't win, we did our best.";
-			mes "This is a Royal gift from Croix, and please don't forget this battle. We can win the next.";
-			close2;
-		}
-
-		setquest 6025;
-		getitem 6376, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}

+ 0 - 378
npc/custom/battleground/unofficial/bg_kvm03.txt

@@ -1,378 +0,0 @@
-// ==============================================================================
-// BattleGround System - KvM 1~59
-// ==============================================================================
-
-// Registration NPC's
-// *********************************************************************
-
-bat_room,197,227,4	script	Registration::KvM03R_Guillaume	418,{ // KvM Guillaume
-	end;
-
-OnInit:
-	waitingroom "Battle Station 5 Players",5,"KvM03_BG::OnGuillaumeJoin",1;
-	end;
-	
-OnEnterBG:
-	set $@KvM03BG_id1, waitingroom2bg("bat_c03",53,128,"KvM03_BG::OnGuillaumeQuit","KvM03_BG::OnGuillaumeDie");
-	end;
-}
-
-bat_room,197,204,0	script	Registration::KvM03R_Croix	414,{ // KvM Croix
-	end;
-
-OnInit:
-	waitingroom "Battle Station 5 Players",5,"KvM03_BG::OnCroixJoin",1;
-	end;
-
-OnEnterBG:
-	set $@KvM03BG_id2, waitingroom2bg("bat_c03",146,55,"KvM03_BG::OnCroixQuit","KvM03_BG::OnCroixDie");
-	end;
-}
-
-// Light Effects
-// *********************************************************************
-
-bat_c03,54,123,0	script	#bat_c03a	111,{
-	end;
-
-OnKvM03LightA: specialeffect EF_BEGINSPELL2; end;
-OnKvM03LightB: specialeffect EF_BEGINSPELL3; end;
-OnKvM03LightC: specialeffect EF_BEGINSPELL4; end;
-}
-
-bat_c03,56,125,0	duplicate(#bat_c03a)	#bat_c03b	111
-bat_c03,58,127,0	duplicate(#bat_c03a)	#bat_c03c	111
-bat_c03,141,56,0	duplicate(#bat_c03a)	#bat_c03d	111
-bat_c03,143,58,0	duplicate(#bat_c03a)	#bat_c03e	111
-bat_c03,145,60,0	duplicate(#bat_c03a)	#bat_c03f	111
-
-// Battleground Engine
-// *********************************************************************
-
--	script	KvM03_BG	-1,{
-	end;
-
-OnInit:
-	setwall "bat_c03",54,122,6,7,0,"batc03wall_a";
-	setwall "bat_c03",55,122,5,7,0,"batc03wall_b";
-	setwall "bat_c03",140,56,6,7,0,"batc03wall_c";
-	setwall "bat_c03",140,57,5,7,0,"batc03wall_d";
-	disablenpc "TherapistKvM03a";
-	disablenpc "TherapistKvM03b";
-	disablenpc "VintenarKvM03a";
-	disablenpc "VintenarKvM03b";
-	end;
-
-OnGuillaumeJoin:
-OnCroixJoin:
-	donpcevent "KvM03_BG::OnReadyCheck";
-	end;
-
-OnGuillaumeQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-OnGuillaumeDie:
-	if( $@KvM03BG == 2 )
-	{
-		set .Guillaume_Count, .Guillaume_Count - 1;
-		set .Croix_Score, .Croix_Score + 1;
-		bg_updatescore "bat_c03",.Guillaume_Score,.Croix_Score;
-		if( .Guillaume_Count < 1 ) donpcevent "KvM03_BG::OnCroixWin";
-	}
-	end;
-
-OnCroixQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-OnCroixDie:
-	if( $@KvM03BG == 2 )
-	{
-		set .Croix_Count, .Croix_Count - 1;
-		set .Guillaume_Score, .Guillaume_Score + 1;
-		bg_updatescore "bat_c03",.Guillaume_Score,.Croix_Score;
-		if( .Croix_Count < 1 ) donpcevent "KvM03_BG::OnGuillaumeWin";
-	}
-	end;
-
-OnReadyCheck:
-	if( $@KvM03BG )
-		end;
-	set .@Guillaume, getwaitingroomstate(0,"KvM03R_Guillaume");
-	set .@Croix, getwaitingroomstate(0,"KvM03R_Croix");
-
-	if( .@Guillaume < 5 || .@Croix < 5 )
-	{
-		if( .@Guillaume > 3 && .@Croix > 3 && !agitcheck() && !agitcheck2() && $@KvM_Flood < gettimetick(2) )
-		{
-			announce "Battleground -- Kreiger Von Midgard [1-59] G: " + .@Guillaume + "/5, C: " + .@Croix + "/5",0,0xC0C0C0;
-			set $@KvM_Flood, gettimetick(2) + 15;
-		}
-		else
-			mapannounce "bat_room","Battleground -- Kreiger Von Midgard [1-59] G: " + .@Guillaume + "/5, C: " + .@Croix + "/5",1,0xC0C0C0;
-		end;
-	}
-
-	set $@KvM03BG, 1; // Starting
-	donpcevent "KvM03R_Croix::OnEnterBG";
-	donpcevent "KvM03R_Guillaume::OnEnterBG";
-	donpcevent "KvM03_BG::OnStart";
-	end;
-
-OnStart:
-	announce "Battleground -- Kreiger Von Midgard [1-59] has started!",0,0xC0C0C0;
-	enablenpc "TherapistKvM03a";
-	enablenpc "TherapistKvM03b";
-	disablenpc "VintenarKvM03a";
-	disablenpc "VintenarKvM03b";
-	set $@KvM03BG_Victory, 0;
-	sleep 2000;
-	// Warp Teams
-	bg_warp $@KvM03BG_id1,"bat_c03",53,128;
-	bg_warp $@KvM03BG_id2,"bat_c03",146,55;
-	// ScoreBoard
-	set .Guillaume_Score, 0;
-	set .Croix_Score, 0;
-	initnpctimer;
-	end;
-
-OnTimer5000:
-	areapercentheal "bat_c03",50,123,58,131,100,100;
-	areapercentheal "bat_c03",141,52,149,60,100,100;
-	mapannounce "bat_c03","The Battle will start in 25 seconds!!",1,0xC0C0C0;
-	end;
-
-OnTimer26000:
-	mapannounce "bat_c03","The Battle will start in 4 seconds!!",1,0xC0C0C0;
-	end;
-
-OnTimer27000:
-	donpcevent "::OnKvM03LightA";
-	end;
-
-OnTimer28000:
-	donpcevent "::OnKvM03LightB";
-	end;
-	
-OnTimer29000:
-	donpcevent "::OnKvM03LightC";
-	end;
-
-OnTimer30000:
-	// Team Members
-	set .Guillaume_Count, bg_get_data($@KvM03BG_id1, 0);
-	set .Croix_Count, bg_get_data($@KvM03BG_id2, 0);
-	if( .Guillaume_Count < 5 || .Croix_Count < 5 )
-	{
-		set $@KvM03BG_Victory, 3;
-		set $@KvM03BG, 3;
-		mapannounce "bat_c03","There are not enough players to start the battle",1,0xC0C0C0;
-		stopnpctimer;
-		sleep 2000;
-		donpcevent "KvM03_BG::OnStop";
-		end;
-	}
-
-	set $@KvM03BG, 2; // Playing
-	areapercentheal "bat_c03",50,123,58,131,100,100;
-	bg_warp $@KvM03BG_id1,"bat_c03",62,119;
-	areapercentheal "bat_c03",141,52,149,60,100,100;
-	bg_warp $@KvM03BG_id2,"bat_c03",137,64;
-	end;
-
-OnTimer32000:
-	mapannounce "bat_c03","The Battle of Kreiger Von Midgard has begun!!",1,0xC0C0C0;
-	end;
-
-OnTimer300000:
-	mapannounce "bat_c03","The Battle will ends in 30 seconds!!",1,0xC0C0C0;
-	end;
-
-OnTimer330000:
-	if( .Croix_Count > .Guillaume_Count )
-		donpcevent "KvM03_BG::OnCroixWin";
-	else if( .Croix_Count < .Guillaume_Count )
-		donpcevent "KvM03_BG::OnGuillaumeWin";
-	else
-	{ // Draw Game
-		set $@KvM03BG, 3;
-		set $@KvM03BG_Victory, 3;
-
-		stopnpctimer;
-		sleep 2000;
-		mapannounce "bat_c03","The time is out! This is a Tie...",1,0xC0C0C0;
-		donpcevent "KvM03_BG::OnStop";
-	}
-	end;
-
-OnGuillaumeWin:
-	set $@KvM03BG, 3;
-	set $@KvM03BG_Victory, 1;
-	
-	stopnpctimer;
-	sleep 2000;
-	mapannounce "bat_c03","The Guillaume Army has won the Battle of Kreiger Von Midgard",1,0x0000FF;
-	donpcevent "KvM03_BG::OnStop";
-	end;
-
-OnCroixWin:
-	set $@KvM03BG, 3;
-	set $@KvM03BG_Victory, 2;
-
-	stopnpctimer;
-	sleep 2000;
-	mapannounce "bat_c03","The Croix Army has won the Battle of Kreiger Von Midgard",1,0xFF0000;
-	donpcevent "KvM03_BG::OnStop";
-	end;
-
-OnStop:
-	disablenpc "TherapistKvM03a";
-	disablenpc "TherapistKvM03b";
-	enablenpc "VintenarKvM03a";
-	enablenpc "VintenarKvM03b";
-	// Warp Teams
-	bg_warp $@KvM03BG_id1,"bat_c03",53,128;
-	bg_warp $@KvM03BG_id2,"bat_c03",146,55;
-	donpcevent "KvM03_BG_Out::OnBegin";
-	end;
-
-OnReset:
-	stopnpctimer;
-	stopnpctimer "KvM03_BG_Out";
-	set .Croix_Count, 0;
-	set .Guillaume_Count, 0;
-	set .Croix_Score, 0;
-	set .Guillaume_Score, 0;
-	set $@KvM03BG_Victory, 0;
-	if( $@KvM03BG_id1 ) { bg_destroy $@KvM03BG_id1; set $@KvM03BG_id1, 0; }
-	if( $@KvM03BG_id2 ) { bg_destroy $@KvM03BG_id2; set $@KvM03BG_id2, 0; }
-	disablenpc "TherapistKvM03a";
-	disablenpc "TherapistKvM03b";
-	disablenpc "VintenarKvM03a";
-	disablenpc "VintenarKvM03b";
-	sleep 1000;
-	mapwarp "bat_c03","bat_room",155,150;
-	sleep 2000;
-	maprespawnguildid "bat_c03",0,3; // Just in case someone else
-	bg_updatescore "bat_c03",0,0;
-	sleep 2000;
-	set $@KvM03BG, 0;
-	donpcevent "KvM03_BG::OnReadyCheck"; // Maybe a game is ready to start
-	end;
-}
-
--	script	KvM03_BG_Out	-1,{
-	end;
-
-OnBegin:
-	initnpctimer;
-	end;
-
-OnTimer3000:
-	mapannounce "bat_c03","Battle of Kreiger Von Midgard will close in 1 minute!",1,0xC0C0C0;
-	end;
-OnTimer30000:
-	mapannounce "bat_c03","Battle of Kreiger Von Midgard will close in 30 seconds!",1,0xC0C0C0;
-	end;
-OnTimer50000:
-	mapannounce "bat_c03","Battle of Kreiger Von Midgard will close in 10 seconds!",1,0xC0C0C0;
-	end;
-OnTimer60000:
-	donpcevent "KvM03_BG::OnReset";
-	end;
-}
-
-// Battleground Therapist
-// *********************************************************************
-
-bat_c03,51,130,5	script	Therapist in battle::TherapistKvM03a	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-bat_c03,148,53,1	script	Therapist in battle::TherapistKvM03b	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-// Battleground rewards
-// *********************************************************************
-
-bat_c03,51,130,5	script	Guillaume Vintenar::VintenarKvM03a	419,{
-	if( $@KvM03BG_Victory )
-	{
-		if( $@KvM03BG_Victory == 3 )
-		{
-			setquest 6025;
-			bg_leave;
-			warp "bat_room",155,150;
-			end;
-		}
-		else if( $@KvM03BG_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "Blessed Guillaume!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 0;
-			mes "[Swandery]";
-			mes "You lost, but you're dedicated to this battle.";
-			mes "This is a reward for your great dedication by Guillaume Marollo!";
-			mes "Just take this defeat a lesson, and later you would definitely learn.";
-			close2;
-		}
-
-		setquest 6025;
-		getitem 6376, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-bat_c03,148,53,1	script	Croix Vintenar::VintenarKvM03b	415,{
-	if( $@KvM03BG_Victory )
-	{
-		if( $@KvM03BG_Victory == 3 )
-		{
-			setquest 6025;
-			bg_leave;
-			warp "bat_room",155,150;
-			end;
-		}
-		else if( $@KvM03BG_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "Blessed Croax!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 0;
-			mes "[Swandery]";
-			mes "Oh, " + strcharinfo(0) + ". Don't be sad.";
-			mes "Even though we didn't win, we did our best.";
-			mes "Please don't forget this battle. We can win the next.";
-			close2;
-		}
-
-		setquest 6025;
-		getitem 6376, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}

+ 0 - 476
npc/custom/battleground/unofficial/bg_tierra_01.txt

@@ -1,476 +0,0 @@
-// ==============================================================================
-// BattleGround System - Tierra Valley 1
-// ==============================================================================
-
-// Registration NPC's
-// *********************************************************************
-
-bat_room,58,227,4	script	Registration::TV1R_Guillaume	418,{
-	end;
-OnInit:
-	waitingroom "Battle Station 10 Players",10,"Tierra_BG1::OnGuillaumeJoin",1;
-	end;
-OnEnterBG:
-	set $@TierraBG1_id1, waitingroom2bg("bat_a01",50,374,"Tierra_BG1::OnGuillaumeQuit","");
-	end;
-}
-
-bat_room,58,204,0	script	Registration::TV1R_Croix	414,{
-	end;
-OnInit:
-	waitingroom "Battle Station 10 Players",10,"Tierra_BG1::OnCroixJoin",1;
-	end;
-OnEnterBG:
-	set $@TierraBG1_id2, waitingroom2bg("bat_a01",42,16,"Tierra_BG1::OnCroixQuit","");
-	end;
-}
-
-// Battleground Engine
-// *********************************************************************
-
--	script	Tierra_BG1	-1,{
-	end;
-
-OnInit:
-	disablenpc "Croix Vintenar#tv1";
-	disablenpc "Guillaume Vintenar#tv1";
-	disablenpc "Therapist in battle#tv11";
-	disablenpc "Therapist in battle#tv12";
-	end;
-
-OnGuillaumeQuit:
-OnCroixQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-	end;
-
-OnGuillaumeJoin:
-OnCroixJoin:
-	if( $@TierraBG1 == 0 )
-		donpcevent "Tierra_BG1::OnReadyCheck";
-	end;
-
-OnReadyCheck:
-	if( $@TierraBG1 )
-		end;
-	set .@Guillaume, getwaitingroomstate(0,"TV1R_Guillaume");
-	set .@Croix, getwaitingroomstate(0,"TV1R_Croix");
-
-	if( .@Guillaume < 10 || .@Croix < 10 )
-	{
-		mapannounce "bat_room","Battleground -- Tierra Valley [80-99] G: " + .@Guillaume + "/10, C: " + .@Croix + "/10",1,0xFFA500;
-		end;
-	}
-
-	set $@TierraBG1, 1;
-	donpcevent "TV1R_Croix::OnEnterBG";
-	donpcevent "TV1R_Guillaume::OnEnterBG";
-	donpcevent "Guillaume_TV1B::OnBuild";
-	donpcevent "Croix_TV1B::OnBuild";
-	bg_monster $@TierraBG1_id1,"bat_a01",176,345,"Food Depot",1909,"Tierra_BG1::OnGuillaumeBreak";
-	bg_monster $@TierraBG1_id2,"bat_a01",167,50,"Food Storage",1910,"Tierra_BG1::OnCroixBreak";
-	bg_monster 0,"bat_a01",273,204,"Neutrality Flag",1911,"Tierra_BG1::OnNeutralBreak";
-	
-	set .Neutral_Base, 0;
-	set $@TierraBG1_Victory, 0;
-
-	set .Guardian_1, 0;
-	set .Guardian_2, 0;
-	set .Guardian_3, 0;
-
-	enablenpc "Therapist in battle#tv11";
-	enablenpc "Therapist in battle#tv12";
-	disablenpc "Croix Vintenar#tv1";
-	disablenpc "Guillaume Vintenar#tv1";
-	// Respawner
-	donpcevent "#gtv1_respawn::OnBGStart";
-	donpcevent "#ctv1_respawn::OnBGStart";
-	donpcevent "#ntv1_respawn::OnBGStart";
-	// Warp Teams
-	announce "Battleground -- Tierra Valley [80-99] has started!",0,0xFFA500;
-	bg_warp $@TierraBG1_id1,"bat_a01",353,344;
-	bg_warp $@TierraBG1_id2,"bat_a01",353,52;
-	// Final Messages
-	sleep 6000;
-	mapannounce "bat_a01","Guillaume Vintenar Axl Rose : Let's attack to burn down Croix's food storage",1,0x0000FF;
-	sleep 2000;
-	mapannounce "bat_a01","Croix Vintenar Swandery : Master of Valhalla! Let us be gifted with unfailing faith and courage",1,0xFF0000;
-	
-	initnpctimer;
-	end;
-
-OnNeutralBreak:
-	if( getcharid(4) == $@TierraBG1_id1 )
-	{
-		mapannounce "bat_a01","Guillaume obtained a neurality banner, so they have an advantage.",1,0x0000FF;
-		bg_team_setxy $@TierraBG1_id2,42,16;
-		areawarp "bat_a01",52,208,61,217,"bat_a01",42,16;
-	}
-	else if( getcharid(4) == $@TierraBG1_id2 )
-	{
-		mapannounce "bat_a01","Croix obtained a neutrality banner, so they have an advantage.",1,0xFF0000;
-		bg_team_setxy $@TierraBG1_id1,50,374;
-		areawarp "bat_a01",52,208,61,217,"bat_a01",50,374;
-	}
-	else end;
-
-	set .Neutral_Base, getcharid(4);
-	bg_team_setxy .Neutral_Base,56,212;
-
-	if( .Guardian_1 == 0 )
-		set .Guardian_1, bg_monster(.Neutral_Base,"bat_a01",280,233,"Guardian",1949,"Tierra_BG1::OnGuardian1");
-	else
-		bg_monster_set_team .Guardian_1, .Neutral_Base;
-	
-	if( .Guardian_2 == 0 )
-		set .Guardian_2, bg_monster(.Neutral_Base,"bat_a01",287,203,"Guardian",1950,"Tierra_BG1::OnGuardian2");
-	else
-		bg_monster_set_team .Guardian_2, .Neutral_Base;
-
-	if( .Guardian_3 == 0 )
-		set .Guardian_3, bg_monster(.Neutral_Base,"bat_a01",268,204,"Guardian",1949,"Tierra_BG1::OnGuardian3");
-	else
-		bg_monster_set_team .Guardian_3, .Neutral_Base;
-
-	sleep 10000;
-	if( $@TierraBG1 != 1 ) end;
-
-	if( .Neutral_Base == $@TierraBG1_id1 )
-		bg_monster .Neutral_Base,"bat_a01",273,204,"Guillaume Flag",1912,"Tierra_BG1::OnNeutralBreak";
-	else if( .Neutral_Base == $@TierraBG1_id2 )
-		bg_monster .Neutral_Base,"bat_a01",273,204,"Croix Flag",1913,"Tierra_BG1::OnNeutralBreak";
-	end;
-
-OnGuardian1: set .Guardian_1, 0; end;
-OnGuardian2: set .Guardian_2, 0; end;
-OnGuardian3: set .Guardian_3, 0; end;
-
-OnGuillaumeBreak:
-	set $@TierraBG1_Victory, 2;
-	mapannounce "bat_a01","Croix Vintenar Swandery: We destroyed Guillaume's food storehouse. We won that! Wow!",1,0xFF0000;
-	donpcevent "Tierra_BG1::OnStop";
-	end;
-
-OnCroixBreak:
-	set $@TierraBG1_Victory, 1;
-	mapannounce "bat_a01","Guillaume Vintenar Axl Rose: We destroyed Croix's food storehouse. We won that! Wow!",1,0x0000FF;
-	donpcevent "Tierra_BG1::OnStop";
-	end;
-
-OnTimer2400000:
-	mapannounce "bat_a01","Battle of Tierra Gorge will ends in 5 minutes",1,0xFFA500;
-	end;
-OnTimer2640000:
-	mapannounce "bat_a01","Battle of Tierra Gorge will ends in 1 minute",1,0xFFA500;
-	end;
-
-OnTimer2700000:
-	set $@TierraBG1_Victory, 3; // Draw Game
-	mapannounce "bat_a01","Battle of Tierra Gorge is over. The time is out, this is a Tie",1,0xFFA500;
-	donpcevent "Tierra_BG1::OnStop";
-	end;
-
-OnStop:
-	set $@TierraBG1, 2;
-	disablenpc "Therapist in battle#tv11";
-	disablenpc "Therapist in battle#tv12";
-	donpcevent "#gtv1_respawn::OnBGStop";
-	donpcevent "#ctv1_respawn::OnBGStop";
-	donpcevent "#ntv1_respawn::OnBGStop";
-	enablenpc "Croix Vintenar#tv1";
-	enablenpc "Guillaume Vintenar#tv1";
-	killmonster "bat_a01","Tierra_BG1::OnGuillaumeBreak";
-	killmonster "bat_a01","Tierra_BG1::OnCroixBreak";
-	killmonster "bat_a01","Tierra_BG1::OnNeutralBreak";
-	killmonster "bat_a01","Tierra_BG1::OnGuardian1";
-	killmonster "bat_a01","Tierra_BG1::OnGuardian2";
-	killmonster "bat_a01","Tierra_BG1::OnGuardian3";
-	stopnpctimer;
-	sleep 3000;
-	bg_warp $@TierraBG1_id1,"bat_a01",50,374;
-	bg_warp $@TierraBG1_id2,"bat_a01",42,16;
-	sleep 3000;
-	mapannounce "bat_a01","Battle of Tierra Gorge will close in 1 minute!",1,0xFFA500;
-	initnpctimer;
-	end;
-
-OnTimer30000:
-	if( $@TierraBG1 == 2 )
-		mapannounce "bat_a01","Battle of Tierra Valley will close in 30 seconds!",1,0xFFA500;
-	end;
-OnTimer50000:
-	if( $@TierraBG1 == 2 )
-		mapannounce "bat_a01","Battle of Tierra Valley will close in 10 seconds!",1,0xFFA500;
-	end;
-
-OnTimer60000:
-	if( $@TierraBG1 != 2 )
-		end;
-OnReset:
-	stopnpctimer;
-	set .Neutral_Base, 0;
-	disablenpc "Croix Vintenar#tv1";
-	disablenpc "Guillaume Vintenar#tv1";
-	disablenpc "Therapist in battle#tv11";
-	disablenpc "Therapist in battle#tv12";
-	donpcevent "#gtv1_respawn::OnBGStop";
-	donpcevent "#ctv1_respawn::OnBGStop";
-	donpcevent "#ntv1_respawn::OnBGStop";
-
-	killmonster "bat_a01","Tierra_BG1::OnGuillaumeBreak";
-	killmonster "bat_a01","Tierra_BG1::OnCroixBreak";
-	killmonster "bat_a01","Tierra_BG1::OnNeutralBreak";
-	killmonster "bat_a01","Tierra_BG1::OnGuardian1";
-	killmonster "bat_a01","Tierra_BG1::OnGuardian2";
-	killmonster "bat_a01","Tierra_BG1::OnGuardian3";
-	donpcevent "Guillaume_TV1B::OnDestroy";
-	donpcevent "Croix_TV1B::OnDestroy";
-
-	set $@TierraBG1_Victory, 0;
-	if( $@TierraBG1_id1 ) { bg_destroy $@TierraBG1_id1; set $@TierraBG1_id1, 0; }
-	if( $@TierraBG1_id2 ) { bg_destroy $@TierraBG1_id2; set $@TierraBG1_id2, 0; }
-	sleep 1000;
-	mapwarp "bat_a01","bat_room",155,150;
-	sleep 2000;
-	maprespawnguildid "bat_a01",0,3; // Just in case someone else
-	sleep 2000;
-	set $@TierraBG1, 0;
-	donpcevent "Tierra_BG1::OnReadyCheck"; // Maybe a game is ready to start
-	end;
-}
-
-// Other Flags
-// *********************************************************************
-
-bat_a01,148,85,1	duplicate(Croix camp#bat)	Croix camp#bat10	974
-bat_a01,155,85,1	duplicate(Croix camp#bat)	Croix camp#bat11	974
-bat_a01,357,75,1	duplicate(Croix camp#bat)	Croix camp#bat12	974
-bat_a01,348,74,1	duplicate(Croix camp#bat)	Croix camp#bat13	974
-bat_a01,199,49,1	duplicate(Croix camp#bat)	Croix camp#bat14	974
-bat_a01,168,16,1	duplicate(Croix camp#bat)	Croix camp#bat15	974
-bat_a01,138,12,1	duplicate(Croix camp#bat)	Croix camp#bat16	974
-bat_a01,108,35,1	duplicate(Croix camp#bat)	Croix camp#bat17	974
-bat_a01,164,308,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat10	973
-bat_a01,157,308,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat11	973
-bat_a01,359,327,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat12	973
-bat_a01,350,326,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat13	973
-bat_a01,209,344,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat14	973
-bat_a01,173,380,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat15	973
-bat_a01,150,380,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat16	973
-bat_a01,118,357,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat17	973
-bat_a01,119,336,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat18	973
-
-// Barricades
-// *********************************************************************
-
--	script	Guillaume_TV1B	-1,{
-	end;
-
-OnBuild:
-	for( set .@i, 0; .@i < 16; set .@i, .@i + 1 )
-		bg_monster 0,"bat_a01",170+.@i,130,"Barricade",1906,"Guillaume_TV1B::OnWall";
-
-	setwall "bat_a01",170,130,16,6,1,"bat_a01_g1";
-	set .MyMobCount,16;
-	end;
-
-OnDestroy:
-	killmonster "bat_a01","Guillaume_TV1B::OnWall";
-	if (checkwall("bat_a01_g1") == true)
-		delwall "bat_a01_g1";
-	set .MyMobCount,0;
-	end;
-
-OnWall:
-	if( set(.MyMobCount,.MyMobCount - 1) < 1 )
-	{
-		delwall "bat_a01_g1";
-		mapannounce "bat_a01","South Gate : The Gate has been Destroy!!",1,0xFFA500;
-	}
-	end;
-}
-
--	script	Croix_TV1B	-1,{
-	end;
-
-OnBuild:
-	for( set .@i, 0; .@i < 16; set .@i, .@i + 1 )
-		bg_monster 0,"bat_a01",186+.@i,266,"Barricade",1906,"Croix_TV1B::OnWall";
-	
-	setwall "bat_a01",186,266,16,6,1,"bat_a01_c1";
-	set .MyMobCount,16;
-	end;
-
-OnDestroy:
-	killmonster "bat_a01","Croix_TV1B::OnWall";
-	delwall "bat_a01_c1";
-	set .MyMobCount,0;
-	end;
-
-OnWall:
-	if( set(.MyMobCount,.MyMobCount - 1) < 1 )
-	{
-		delwall "bat_a01_c1";
-		mapannounce "bat_a01","North Gate : A Gate has been Destroy!!",1,0xFFA500;
-	}
-	end;
-}
-
-// Battleground rewards
-// *********************************************************************
-
-bat_a01,45,19,3	script	Croix Vintenar#tv1	415,{
-	if( $@TierraBG1_Victory )
-	{
-		if( $@TierraBG1_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 3;
-			mes "[Swandery]";
-			mes "Blessed Croax!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "Oh, " + strcharinfo(0) + ". Don't be sad.";
-			mes "Even though we didn't win, we did our best.";
-			mes "This is a Royal gift from Croix, and please don't forget this battle. We can win the next.";
-			close2;
-		}
-
-		setquest 2069;
-		getitem 7828, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-bat_a01,53,377,3	script	Guillaume Vintenar#tv1	419,{
-	if( $@TierraBG1_Victory )
-	{
-		if( $@TierraBG1_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 3;
-			mes "[Swandery]";
-			mes "Blessed Guillaume!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "You lost, but you're dedicated to this battle.";
-			mes "This is a reward for your great dedication by Guillaume Marollo!";
-			mes "Just take this defeat a lesson, and later you would definitely learn.";
-			close2;
-		}
-
-		setquest 2069;
-		getitem 7828, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-// Battleground Therapist
-// *********************************************************************
-
-bat_a01,60,216,3	script	Ghost#tv13	950,{
-	mes "[Ghost in valley]";
-	mes "Boo...Boo...";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-bat_a01,53,377,3	script	Therapist in battle#tv12	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-bat_a01,45,18,3	script	Therapist in battle#tv11	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-// Battleground Respawn
-// *********************************************************************
-
-bat_a01,57,213,0	script	#ntv1_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer19000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer20000:
-	areapercentheal "bat_a01",52,208,61,217,100,100;
-	areawarp "bat_a01",52,208,61,217,"bat_a01",301,208;
-	initnpctimer;
-	end;
-}
-
-bat_a01,50,374,0	script	#gtv1_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer24000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer25000:
-	areapercentheal "bat_a01",46,370,54,378,100,100;
-	areawarp "bat_a01",46,370,54,378,"bat_a01",354,340;
-	initnpctimer;
-	end;
-}
-
-bat_a01,42,16,0	script	#ctv1_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer24000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer25000:
-	areapercentheal "bat_a01",38,12,47,21,100,100;
-	areawarp "bat_a01",38,12,47,21,"bat_a01",354,57;
-	initnpctimer;
-	end;
-}

+ 0 - 476
npc/custom/battleground/unofficial/bg_tierra_02.txt

@@ -1,476 +0,0 @@
-// ==============================================================================
-// BattleGround System - Tierra Valley 2
-// ==============================================================================
-
-// Registration NPC's
-// *********************************************************************
-
-bat_room,114,227,4	script	Registration::TV2R_Guillaume	418,{
-	end;
-OnInit:
-	waitingroom "Battle Station 10 Players",10,"Tierra_BG2::OnGuillaumeJoin",1;
-	end;
-OnEnterBG:
-	set $@TierraBG2_id1, waitingroom2bg("bat_a02",50,374,"Tierra_BG2::OnGuillaumeQuit","");
-	end;
-}
-
-bat_room,114,204,0	script	Registration::TV2R_Croix	414,{
-	end;
-OnInit:
-	waitingroom "Battle Station 10 Players",10,"Tierra_BG2::OnCroixJoin",1;
-	end;
-OnEnterBG:
-	set $@TierraBG2_id2, waitingroom2bg("bat_a02",42,16,"Tierra_BG2::OnCroixQuit","");
-	end;
-}
-
-// Battleground Engine
-// *********************************************************************
-
--	script	Tierra_BG2	-1,{
-	end;
-
-OnInit:
-	disablenpc "Croix Vintenar#tv2";
-	disablenpc "Guillaume Vintenar#tv2";
-	disablenpc "Therapist in battle#tv21";
-	disablenpc "Therapist in battle#tv22";
-	end;
-
-OnGuillaumeQuit:
-OnCroixQuit:
-	set BG_Delay_Tick, gettimetick(2) + 1200;
-	end;
-
-OnGuillaumeJoin:
-OnCroixJoin:
-	if( $@TierraBG2 == 0 )
-		donpcevent "Tierra_BG2::OnReadyCheck";
-	end;
-
-OnReadyCheck:
-	if( $@TierraBG2 )
-		end;
-	set .@Guillaume, getwaitingroomstate(0,"TV2R_Guillaume");
-	set .@Croix, getwaitingroomstate(0,"TV2R_Croix");
-
-	if( .@Guillaume < 10 || .@Croix < 10 )
-	{
-		mapannounce "bat_room","Battleground -- Tierra Valley [80-99] G: " + .@Guillaume + "/10, C: " + .@Croix + "/10",1,0xF4A460;
-		end;
-	}
-
-	set $@TierraBG2, 1;
-	donpcevent "TV2R_Croix::OnEnterBG";
-	donpcevent "TV2R_Guillaume::OnEnterBG";
-	donpcevent "Guillaume_TV2B::OnBuild";
-	donpcevent "Croix_TV2B::OnBuild";
-	bg_monster $@TierraBG2_id1,"bat_a02",176,345,"Food Depot",1909,"Tierra_BG2::OnGuillaumeBreak";
-	bg_monster $@TierraBG2_id2,"bat_a02",167,50,"Food Storage",1910,"Tierra_BG2::OnCroixBreak";
-	bg_monster 0,"bat_a02",273,204,"Neutrality Flag",1911,"Tierra_BG2::OnNeutralBreak";
-	
-	set .Neutral_Base, 0;
-	set $@TierraBG2_Victory, 0;
-
-	set .Guardian_1, 0;
-	set .Guardian_2, 0;
-	set .Guardian_3, 0;
-
-	enablenpc "Therapist in battle#tv21";
-	enablenpc "Therapist in battle#tv22";
-	disablenpc "Croix Vintenar#tv2";
-	disablenpc "Guillaume Vintenar#tv2";
-	// Respawner
-	donpcevent "#gtv2_respawn::OnBGStart";
-	donpcevent "#ctv2_respawn::OnBGStart";
-	donpcevent "#ntv2_respawn::OnBGStart";
-	// Warp Teams
-	announce "Battleground -- Tierra Valley [80-99] has started!",0,0xF4A460;
-	bg_warp $@TierraBG2_id1,"bat_a02",353,344;
-	bg_warp $@TierraBG2_id2,"bat_a02",353,52;
-	// Final Messages
-	sleep 6000;
-	mapannounce "bat_a02","Guillaume Vintenar Axl Rose : Let's attack to burn down Croix's food storage",1,0x0000FF;
-	sleep 2000;
-	mapannounce "bat_a02","Croix Vintenar Swandery : Master of Valhalla! Let us be gifted with unfailing faith and courage",1,0xFF0000;
-	
-	initnpctimer;
-	end;
-
-OnNeutralBreak:
-	if( getcharid(4) == $@TierraBG2_id1 )
-	{
-		mapannounce "bat_a02","Guillaume obtained a neurality banner, so they have an advantage.",1,0x0000FF;
-		bg_team_setxy $@TierraBG2_id2,42,16;
-		areawarp "bat_a02",52,208,61,217,"bat_a02",42,16;
-	}
-	else if( getcharid(4) == $@TierraBG2_id2 )
-	{
-		mapannounce "bat_a02","Croix obtained a neutrality banner, so they have an advantage.",1,0xFF0000;
-		bg_team_setxy $@TierraBG2_id1,50,374;
-		areawarp "bat_a02",52,208,61,217,"bat_a02",50,374;
-	}
-	else end;
-
-	set .Neutral_Base, getcharid(4);
-	bg_team_setxy .Neutral_Base,56,212;
-
-	if( .Guardian_1 == 0 )
-		set .Guardian_1, bg_monster(.Neutral_Base,"bat_a02",280,233,"Guardian",1949,"Tierra_BG2::OnGuardian1");
-	else
-		bg_monster_set_team .Guardian_1, .Neutral_Base;
-	
-	if( .Guardian_2 == 0 )
-		set .Guardian_2, bg_monster(.Neutral_Base,"bat_a02",287,203,"Guardian",1950,"Tierra_BG2::OnGuardian2");
-	else
-		bg_monster_set_team .Guardian_2, .Neutral_Base;
-
-	if( .Guardian_3 == 0 )
-		set .Guardian_3, bg_monster(.Neutral_Base,"bat_a02",268,204,"Guardian",1949,"Tierra_BG2::OnGuardian3");
-	else
-		bg_monster_set_team .Guardian_3, .Neutral_Base;
-
-	sleep 10000;
-	if( $@TierraBG2 != 1 ) end;
-
-	if( .Neutral_Base == $@TierraBG2_id1 )
-		bg_monster .Neutral_Base,"bat_a02",273,204,"Guillaume Flag",1912,"Tierra_BG2::OnNeutralBreak";
-	else if( .Neutral_Base == $@TierraBG2_id2 )
-		bg_monster .Neutral_Base,"bat_a02",273,204,"Croix Flag",1913,"Tierra_BG2::OnNeutralBreak";
-	end;
-
-OnGuardian1: set .Guardian_1, 0; end;
-OnGuardian2: set .Guardian_2, 0; end;
-OnGuardian3: set .Guardian_3, 0; end;
-
-OnGuillaumeBreak:
-	set $@TierraBG2_Victory, 2;
-	mapannounce "bat_a02","Croix Vintenar Swandery: We destroyed Guillaume's food storehouse. We won that! Wow!",1,0xFF0000;
-	donpcevent "Tierra_BG2::OnStop";
-	end;
-
-OnCroixBreak:
-	set $@TierraBG2_Victory, 1;
-	mapannounce "bat_a02","Guillaume Vintenar Axl Rose: We destroyed Croix's food storehouse. We won that! Wow!",1,0x0000FF;
-	donpcevent "Tierra_BG2::OnStop";
-	end;
-
-OnTimer2400000:
-	mapannounce "bat_a02","Battle of Tierra Gorge will ends in 5 minutes",1,0xF4A460;
-	end;
-OnTimer2640000:
-	mapannounce "bat_a02","Battle of Tierra Gorge will ends in 1 minute",1,0xF4A460;
-	end;
-
-OnTimer2700000:
-	set $@TierraBG2_Victory, 3; // Draw Game
-	mapannounce "bat_a02","Battle of Tierra Gorge is over. The time is out, this is a Tie",1,0xF4A460;
-	donpcevent "Tierra_BG2::OnStop";
-	end;
-
-OnStop:
-	set $@TierraBG2, 2;
-	disablenpc "Therapist in battle#tv21";
-	disablenpc "Therapist in battle#tv22";
-	donpcevent "#gtv2_respawn::OnBGStop";
-	donpcevent "#ctv2_respawn::OnBGStop";
-	donpcevent "#ntv2_respawn::OnBGStop";
-	enablenpc "Croix Vintenar#tv2";
-	enablenpc "Guillaume Vintenar#tv2";
-	killmonster "bat_a02","Tierra_BG2::OnGuillaumeBreak";
-	killmonster "bat_a02","Tierra_BG2::OnCroixBreak";
-	killmonster "bat_a02","Tierra_BG2::OnNeutralBreak";
-	killmonster "bat_a02","Tierra_BG2::OnGuardian1";
-	killmonster "bat_a02","Tierra_BG2::OnGuardian2";
-	killmonster "bat_a02","Tierra_BG2::OnGuardian3";
-	stopnpctimer;
-	sleep 3000;
-	bg_warp $@TierraBG2_id1,"bat_a02",50,374;
-	bg_warp $@TierraBG2_id2,"bat_a02",42,16;
-	sleep 3000;
-	mapannounce "bat_a02","Battle of Tierra Gorge will close in 1 minute!",1,0xF4A460;
-	initnpctimer;
-	end;
-
-OnTimer30000:
-	if( $@TierraBG2 == 2 )
-		mapannounce "bat_a02","Battle of Tierra Valley will close in 30 seconds!",1,0xF4A460;
-	end;
-OnTimer50000:
-	if( $@TierraBG2 == 2 )
-		mapannounce "bat_a02","Battle of Tierra Valley will close in 10 seconds!",1,0xF4A460;
-	end;
-
-OnTimer60000:
-	if( $@TierraBG2 != 2 )
-		end;
-OnReset:
-	stopnpctimer;
-	set .Neutral_Base, 0;
-	disablenpc "Croix Vintenar#tv2";
-	disablenpc "Guillaume Vintenar#tv2";
-	disablenpc "Therapist in battle#tv21";
-	disablenpc "Therapist in battle#tv22";
-	donpcevent "#gtv2_respawn::OnBGStop";
-	donpcevent "#gtv2_respawn::OnBGStop";
-	donpcevent "#ctv2_respawn::OnBGStop";
-
-	killmonster "bat_a02","Tierra_BG2::OnGuillaumeBreak";
-	killmonster "bat_a02","Tierra_BG2::OnCroixBreak";
-	killmonster "bat_a02","Tierra_BG2::OnNeutralBreak";
-	killmonster "bat_a02","Tierra_BG2::OnGuardian1";
-	killmonster "bat_a02","Tierra_BG2::OnGuardian2";
-	killmonster "bat_a02","Tierra_BG2::OnGuardian3";
-	donpcevent "Guillaume_TV2B::OnDestroy";
-	donpcevent "Croix_TV2B::OnDestroy";
-
-	set $@TierraBG2_Victory, 0;
-	if( $@TierraBG2_id1 ) { bg_destroy $@TierraBG2_id1; set $@TierraBG2_id1, 0; }
-	if( $@TierraBG2_id2 ) { bg_destroy $@TierraBG2_id2; set $@TierraBG2_id2, 0; }
-	sleep 1000;
-	mapwarp "bat_a02","bat_room",155,150;
-	sleep 2000;
-	maprespawnguildid "bat_a02",0,3; // Just in case someone else
-	sleep 2000;
-	set $@TierraBG2, 0;
-	donpcevent "Tierra_BG2::OnReadyCheck"; // Maybe a game is ready to start
-	end;
-}
-
-// Other Flags
-// *********************************************************************
-
-bat_a02,148,85,1	duplicate(Croix camp#bat)	Croix camp#bat22	974
-bat_a02,155,85,1	duplicate(Croix camp#bat)	Croix camp#bat23	974
-bat_a02,357,75,1	duplicate(Croix camp#bat)	Croix camp#bat24	974
-bat_a02,348,74,1	duplicate(Croix camp#bat)	Croix camp#bat25	974
-bat_a02,199,49,1	duplicate(Croix camp#bat)	Croix camp#bat26	974
-bat_a02,168,16,1	duplicate(Croix camp#bat)	Croix camp#bat27	974
-bat_a02,138,12,1	duplicate(Croix camp#bat)	Croix camp#bat28	974
-bat_a02,108,35,1	duplicate(Croix camp#bat)	Croix camp#bat29	974
-bat_a02,164,308,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat23	973
-bat_a02,157,308,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat24	973
-bat_a02,359,327,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat25	973
-bat_a02,350,326,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat26	973
-bat_a02,209,344,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat27	973
-bat_a02,173,380,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat28	973
-bat_a02,150,380,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat29	973
-bat_a02,118,357,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat30	973
-bat_a02,119,336,1	duplicate(Guillaume camp#bat)	Guillaume camp#bat31	973
-
-// Barricades
-// *********************************************************************
-
--	script	Guillaume_TV2B	-1,{
-	end;
-
-OnBuild:
-	for( set .@i, 0; .@i < 16; set .@i, .@i + 1 )
-		bg_monster 0,"bat_a02",170+.@i,130,"Barricade",1906,"Guillaume_TV2B::OnWall";
-
-	setwall "bat_a02",170,130,16,6,1,"bat_a02_g1";
-	set .MyMobCount,16;
-	end;
-
-OnDestroy:
-	killmonster "bat_a02","Guillaume_TV2B::OnWall";
-	if (checkwall("bat_a02_g1") == true)
-		delwall "bat_a02_g1";
-	set .MyMobCount,0;
-	end;
-
-OnWall:
-	if( set(.MyMobCount,.MyMobCount - 1) < 1 )
-	{
-		delwall "bat_a02_g1";
-		mapannounce "bat_a02","South Gate : The Gate has been Destroy!!",1,0xF4A460;
-	}
-	end;
-}
-
--	script	Croix_TV2B	-1,{
-	end;
-
-OnBuild:
-	for( set .@i, 0; .@i < 16; set .@i, .@i + 1 )
-		bg_monster 0,"bat_a02",186+.@i,266,"Barricade",1906,"Croix_TV2B::OnWall";
-	
-	setwall "bat_a02",186,266,16,6,1,"bat_a02_c1";
-	set .MyMobCount,16;
-	end;
-
-OnDestroy:
-	killmonster "bat_a02","Croix_TV2B::OnWall";
-	delwall "bat_a02_c1";
-	set .MyMobCount,0;
-	end;
-
-OnWall:
-	if( set(.MyMobCount,.MyMobCount - 1) < 1 )
-	{
-		delwall "bat_a02_c1";
-		mapannounce "bat_a02","North Gate : A Gate has been Destroy!!",1,0xF4A460;
-	}
-	end;
-}
-
-// Battleground rewards
-// *********************************************************************
-
-bat_a02,45,19,3	script	Croix Vintenar#tv2	415,{
-	if( $@TierraBG2_Victory )
-	{
-		if( $@TierraBG2_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 3;
-			mes "[Swandery]";
-			mes "Blessed Croax!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "Oh, " + strcharinfo(0) + ". Don't be sad.";
-			mes "Even though we didn't win, we did our best.";
-			mes "This is a Royal gift from Croix, and please don't forget this battle. We can win the next.";
-			close2;
-		}
-
-		setquest 2069;
-		getitem 7828, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-bat_a02,53,377,3	script	Guillaume Vintenar#tv2	419,{
-	if( $@TierraBG2_Victory )
-	{
-		if( $@TierraBG2_Victory == Bat_Team )
-		{ // Victory
-			set .@Reward, 3;
-			mes "[Swandery]";
-			mes "Blessed Guillaume!!";
-			mes "Let's enjoy our glorious victory!";
-			mes "" + strcharinfo(0) + ", its a sign reflecting victory";
-			close2;
-		}
-		else
-		{ // 
-			set .@Reward, 1;
-			mes "[Swandery]";
-			mes "You lost, but you're dedicated to this battle.";
-			mes "This is a reward for your great dedication by Guillaume Marollo!";
-			mes "Just take this defeat a lesson, and later you would definitely learn.";
-			close2;
-		}
-
-		setquest 2069;
-		getitem 7828, .@Reward;
-		bg_leave;
-		warp "bat_room",155,150;
-		end;
-	}
-	end;
-}
-
-// Battleground Therapist
-// *********************************************************************
-
-bat_a02,60,216,3	script	Ghost#tv23	950,{
-	mes "[Ghost in valley]";
-	mes "Boo...Boo...";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-bat_a02,53,377,3	script	Therapist in battle#tv22	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-bat_a02,45,18,3	script	Therapist in battle#tv21	95,{
-	mes "[Therapist in battle]";
-	mes "Just close your eyes, and take a deep breathe.";
-	mes "You can be free from pain.";
-	specialeffect2 EF_HEAL;
-	close;
-}
-
-// Battleground Respawn
-// *********************************************************************
-
-bat_a02,57,213,0	script	#ntv2_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer19000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer20000:
-	areapercentheal "bat_a02",52,208,61,217,100,100;
-	areawarp "bat_a02",52,208,61,217,"bat_a02",301,208;
-	initnpctimer;
-	end;
-}
-
-bat_a02,50,374,0	script	#gtv2_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer24000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer25000:
-	areapercentheal "bat_a02",46,370,54,378,100,100;
-	areawarp "bat_a02",46,370,54,378,"bat_a02",354,340;
-	initnpctimer;
-	end;
-}
-
-bat_a02,42,16,0	script	#ctv2_respawn	139,{
-	end;
-
-OnBGStart:
-	initnpctimer;
-	end;
-
-OnBGStop:
-	stopnpctimer;
-	end;
-
-OnTimer24000:
-	misceffect EF_SANCTUARY;
-	end;
-
-OnTimer25000:
-	areapercentheal "bat_a02",38,12,47,21,100,100;
-	areawarp "bat_a02",38,12,47,21,"bat_a02",354,57;
-	initnpctimer;
-	end;
-}

+ 13 - 0
src/common/utilities.hpp

@@ -162,6 +162,19 @@ namespace rathena {
 				return false;
 		}
 
+		/**
+		 * Erase an index value from a vector
+		 * @param vector: Vector to erase value from
+		 * @param index: Index value to remove
+		 */
+		template <typename K> void erase_at(std::vector<K>& vector, size_t index) {
+			if (vector.size() == 1) {
+				vector.clear();
+				vector.shrink_to_fit();
+			} else
+				vector.erase(vector.begin() + index);
+		}
+
 		bool safe_addition( int64 a, int64 b, int64& result );
 		bool safe_substraction( int64 a, int64 b, int64& result );
 		bool safe_multiplication( int64 a, int64 b, int64& result );

+ 39 - 0
src/map/battle.cpp

@@ -1620,6 +1620,34 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 	return damage;
 }
 
+/**
+ * Determines whether battleground target can be hit
+ * @param src: Source of attack
+ * @param bl: Target of attack
+ * @param skill_id: Skill ID used
+ * @param flag: Special flags
+ * @return Can be hit (true) or can't be hit (false)
+ */
+bool battle_can_hit_bg_target(struct block_list *src, struct block_list *bl, uint16 skill_id, int flag)
+{
+	struct mob_data* md = BL_CAST(BL_MOB, bl);
+	struct unit_data *ud = unit_bl2ud(bl);
+
+	if (ud && ud->immune_attack)
+		return false;
+	if (md && md->bg_id) {
+		if (status_bl_has_mode(bl, MD_SKILL_IMMUNE) && flag&BF_SKILL) //Skill immunity.
+			return false;
+		if (src->type == BL_PC) {
+			struct map_session_data *sd = map_id2sd(src->id);
+
+			if (sd && sd->bg_id == md->bg_id)
+				return false;
+		}
+	}
+	return true;
+}
+
 /**
  * Calculates BG related damage adjustments.
  * @param src
@@ -1638,6 +1666,9 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64
 	if( !damage )
 		return 0;
 
+	if (!battle_can_hit_bg_target(src, bl, skill_id, flag))
+		return 0;
+
 	if(skill_get_inf2(skill_id, INF2_IGNOREBGREDUCTION))
 		return damage; //skill that ignore bg map reduction
 
@@ -8591,6 +8622,7 @@ static const struct _battle_data {
 	{ "boss_nopc_move_rate",                &battle_config.boss_nopc_move_rate,             100,    0,    100,              },
 	{ "hom_idle_no_share",                  &battle_config.hom_idle_no_share,               0,      0,      INT_MAX,        },
 	{ "devotion_standup_fix",               &battle_config.devotion_standup_fix,            1,      0,      1,              },
+	{ "feature.bgqueue",                    &battle_config.feature_bgqueue,                 1,      0,      1,              },
 
 #include "../custom/battle_config_init.inc"
 };
@@ -8679,6 +8711,13 @@ void battle_adjust_conf()
 	}
 #endif
 
+#if PACKETVER < 20120101
+	if (battle_config.feature_bgqueue) {
+		ShowWarning("conf/battle/feature.conf:bgqueue is enabled but it requires PACKETVER 2012-01-01 or newer, disabling...\n");
+		battle_config.feature_bgqueue = 0;
+	}
+#endif
+
 #if PACKETVER > 20120000 && PACKETVER < 20130515 /* Exact date (when it started) not known */
 	if (battle_config.feature_auction) {
 		ShowWarning("conf/battle/feature.conf:feature.auction is enabled but it is not stable on PACKETVER " EXPAND_AND_QUOTE(PACKETVER) ", disabling...\n");

+ 1 - 0
src/map/battle.hpp

@@ -671,6 +671,7 @@ struct Battle_Config
 	int boss_nopc_move_rate;
 	int hom_idle_no_share;
 	int devotion_standup_fix;
+	int feature_bgqueue;
 
 #include "../custom/battle_config_struct.inc"
 };

+ 1286 - 131
src/map/battleground.cpp

@@ -3,194 +3,527 @@
 
 #include "battleground.hpp"
 
+#include <unordered_map>
+#include <yaml-cpp/yaml.h>
+
 #include "../common/cbasetypes.hpp"
 #include "../common/malloc.hpp"
 #include "../common/nullpo.hpp"
+#include "../common/random.hpp"
 #include "../common/showmsg.hpp"
 #include "../common/strlib.hpp"
 #include "../common/timer.hpp"
+#include "../common/utilities.hpp"
 
 #include "battle.hpp"
 #include "clif.hpp"
 #include "guild.hpp"
 #include "homunculus.hpp"
+#include "mapreg.hpp"
 #include "mercenary.hpp"
 #include "mob.hpp"
 #include "npc.hpp"
+#include "party.hpp"
 #include "pc.hpp"
 #include "pet.hpp"
 
-static DBMap* bg_team_db; // int bg_id -> struct battleground_data*
-static unsigned int bg_team_counter = 0; // Next bg_id
+using namespace rathena;
 
-struct battleground_data* bg_team_search(int bg_id)
-{ // Search a BG Team using bg_id
-	if( !bg_id )
-		return NULL;
+BattlegroundDatabase battleground_db;
+std::unordered_map<int, std::shared_ptr<s_battleground_data>> bg_team_db;
+std::vector<std::shared_ptr<s_battleground_queue>> bg_queues;
 
-	return (struct battleground_data *)idb_get(bg_team_db, bg_id);
+const std::string BattlegroundDatabase::getDefaultLocation() {
+	return std::string(db_path) + "/battleground_db.yml";
 }
 
-struct map_session_data* bg_getavailablesd(struct battleground_data *bg)
-{
-	int i;
+/**
+ * Reads and parses an entry from the battleground_db
+ * @param node: The YAML node containing the entry
+ * @return count of successfully parsed rows
+ */
+uint64 BattlegroundDatabase::parseBodyNode(const YAML::Node &node) {
+	uint32 id;
 
-	nullpo_retr(NULL, bg);
+	if (!this->asUInt32(node, "Id", id))
+		return 0;
 
-	ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd != NULL);
+	std::shared_ptr<s_battleground_type> bg = this->find(id);
+	bool exists = bg != nullptr;
 
-	return ( i < MAX_BG_MEMBERS ) ? bg->members[i].sd : NULL;
-}
+	if (!exists) {
+		if (!this->nodesExist(node, { "Name", "Locations" }))
+			return 0;
 
-int bg_team_delete(int bg_id)
-{ // Deletes BG Team from db
-	int i;
-	struct battleground_data *bg = bg_team_search(bg_id);
+		bg = std::make_shared<s_battleground_type>();
+		bg->id = id;
+	}
 
-	if( bg == NULL )
-		return 0;
+	if (this->nodeExists(node, "Name")) {
+		std::string name;
+
+		if (!this->asString(node, "Name", name))
+			return 0;
+
+		name.resize(NAME_LENGTH);
+		bg->name = name;
+	}
+
+	if (this->nodeExists(node, "MinPlayers")) {
+		int min;
+
+		if (!this->asInt32(node, "MinPlayers", min))
+			return 0;
+
+		if (min * 2 > MAX_BG_MEMBERS) {
+			this->invalidWarning(node["MinPlayers"], "Minimum players %d exceeds MAX_BG_MEMBERS, capping to %d.\n", min, MAX_BG_MEMBERS / 2);
+			min = MAX_BG_MEMBERS / 2;
+		}
+
+		bg->required_players = min;
+	} else {
+		if (!exists)
+			bg->required_players = 1;
+	}
+
+	if (this->nodeExists(node, "MaxPlayers")) {
+		int max;
+
+		if (!this->asInt32(node, "MaxPlayers", max))
+			return 0;
+
+		if (max * 2 > MAX_BG_MEMBERS) {
+			this->invalidWarning(node["MaxPlayers"], "Maximum players %d exceeds MAX_BG_MEMBERS, capping to %d.\n", max, MAX_BG_MEMBERS / 2);
+			max = MAX_BG_MEMBERS / 2;
+		}
+
+		bg->max_players = max;
+	} else {
+		if (!exists)
+			bg->max_players = MAX_BG_MEMBERS / 2;
+	}
+
+	if (this->nodeExists(node, "MinLevel")) {
+		int min;
+
+		if (!this->asInt32(node, "MinLevel", min))
+			return 0;
+
+		if (min > MAX_LEVEL) {
+			this->invalidWarning(node["MinLevel"], "Minimum level %d exceeds MAX_LEVEL, capping to %d.\n", min, MAX_LEVEL);
+			min = MAX_LEVEL;
+		}
+
+		bg->min_lvl = min;
+	} else {
+		if (!exists)
+			bg->min_lvl = 1;
+	}
+
+	if (this->nodeExists(node, "MaxLevel")) {
+		int max;
+
+		if (!this->asInt32(node, "MaxLevel", max))
+			return 0;
+
+		if (max > MAX_LEVEL) {
+			this->invalidWarning(node["MaxLevel"], "Maximum level %d exceeds MAX_LEVEL, capping to %d.\n", max, MAX_LEVEL);
+			max = MAX_LEVEL;
+		}
+
+		bg->max_lvl = max;
+	} else {
+		if (!exists)
+			bg->max_lvl = MAX_LEVEL;
+	}
+
+	if (this->nodeExists(node, "Deserter")) {
+		uint32 deserter;
+
+		if (!this->asUInt32(node, "Deserter", deserter))
+			return 0;
+
+		bg->deserter_time = deserter;
+	} else {
+		if (!exists)
+			bg->deserter_time = 600;
+	}
+
+	if (this->nodeExists(node, "StartDelay")) {
+		uint32 delay;
+
+		if (!this->asUInt32(node, "StartDelay", delay))
+			return 0;
+
+		bg->start_delay = delay;
+	} else {
+		if (!exists)
+			bg->start_delay = 30;
+	}
+
+	if (this->nodeExists(node, "Locations")) {
+		int count = 0;
+
+		for (const auto &locationit : node["Locations"]) {
+			const YAML::Node &location = locationit;
+			s_battleground_map map_entry;
+
+			if (this->nodeExists(location, "Map")) {
+				std::string map_name;
+
+				if (!this->asString(location, "Map", map_name))
+					return 0;
+
+				map_entry.mapid = map_mapname2mapid(map_name.c_str());
+
+				if (map_entry.mapid == -1) {
+					this->invalidWarning(location["Map"], "Invalid battleground map name %s, skipping.\n", map_name.c_str());
+					return 0;
+				}
+			}
+
+			if (this->nodeExists(location, "StartEvent")) {
+				if (!this->asString(location, "StartEvent", map_entry.bgcallscript))
+					return 0;
+
+				map_entry.bgcallscript.resize(EVENT_NAME_LENGTH);
+
+				if (map_entry.bgcallscript.find("::On") == std::string::npos) {
+					this->invalidWarning(location["StartEvent"], "Battleground StartEvent label %s should begin with '::On', skipping.\n", map_entry.bgcallscript.c_str());
+					return 0;
+				}
+			}
 
-	for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
-		struct map_session_data *sd;
+			std::vector<std::string> team_list = { "TeamA", "TeamB" };
 
-		if( (sd = bg->members[i].sd) == NULL )
-			continue;
+			for (const auto &it : team_list) {
+				const YAML::Node &team = location;
 
-		bg_send_dot_remove(sd);
-		sd->bg_id = 0;
+				if (this->nodeExists(team, it)) {
+					s_battleground_team *team_ptr;
+
+					if (it.find("TeamA") != std::string::npos)
+						team_ptr = &map_entry.team1;
+					else if (it.find("TeamB") != std::string::npos)
+						team_ptr = &map_entry.team2;
+					else {
+						this->invalidWarning(team[it], "An invalid Team is defined.\n");
+						return 0;
+					}
+
+					if (this->nodeExists(team[it], "RespawnX")) {
+						if (!this->asInt16(team[it], "RespawnX", team_ptr->warp_x))
+							return 0;
+					}
+
+					if (this->nodeExists(team[it], "RespawnY")) {
+						if (!this->asInt16(team[it], "RespawnY", team_ptr->warp_y))
+							return 0;
+					}
+
+					if (this->nodeExists(team[it], "DeathEvent")) {
+						if (!this->asString(team[it], "DeathEvent", team_ptr->death_event))
+							return 0;
+
+						team_ptr->death_event.resize(EVENT_NAME_LENGTH);
+
+						if (team_ptr->death_event.find("::On") == std::string::npos) {
+							this->invalidWarning(team["DeathEvent"], "Battleground DeathEvent label %s should begin with '::On', skipping.\n", team_ptr->death_event.c_str());
+							return 0;
+						}
+					}
+
+					if (this->nodeExists(team[it], "QuitEvent")) {
+						if (!this->asString(team[it], "QuitEvent", team_ptr->quit_event))
+							return 0;
+
+						team_ptr->quit_event.resize(EVENT_NAME_LENGTH);
+
+						if (team_ptr->quit_event.find("::On") == std::string::npos) {
+							this->invalidWarning(team["QuitEvent"], "Battleground QuitEvent label %s should begin with '::On', skipping.\n", team_ptr->quit_event.c_str());
+							return 0;
+						}
+					}
+
+					if (this->nodeExists(team[it], "Variable")) {
+						if (!this->asString(team[it], "Variable", team_ptr->bg_id_var))
+							return 0;
+
+						team_ptr->bg_id_var.resize(NAME_LENGTH);
+					}
+
+					map_entry.id = count++;
+					map_entry.isReserved = false;
+				}
+			}
+
+			bg->maps.push_back(map_entry);
+		}
 	}
 
-	idb_remove(bg_team_db, bg_id);
+	if (!exists)
+		this->put(id, bg);
 
 	return 1;
 }
 
-int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y)
-{ // Warps a Team
-	int i;
-	struct battleground_data *bg = bg_team_search(bg_id);
+/**
+ * Search for a battleground based on the given name
+ * @param name: Battleground name
+ * @return s_battleground_type on success or nullptr on failure
+ */
+std::shared_ptr<s_battleground_type> bg_search_name(const char *name)
+{
+	for (const auto &entry : battleground_db) {
+		auto bg = entry.second;
 
-	if( bg == NULL )
-		return 0;
+		if (!stricmp(bg->name.c_str(), name))
+			return bg;
+	}
 
-	for( i = 0; i < MAX_BG_MEMBERS; i++ )
-		if( bg->members[i].sd != NULL ) pc_setpos(bg->members[i].sd, mapindex, x, y, CLR_TELEPORT);
-	return 1;
+	return nullptr;
+}
+
+/**
+ * Search for an available player in Battleground
+ * @param bg: Battleground data
+ * @return map_session_data
+ */
+struct map_session_data* bg_getavailablesd(s_battleground_data *bg)
+{
+	nullpo_retr(nullptr, bg);
+
+	return (bg->members.size() != 0) ? bg->members[0].sd : nullptr;
 }
 
-int bg_send_dot_remove(struct map_session_data *sd)
+/**
+ * Delete a Battleground team from the db
+ * @param bg_id: Battleground ID
+ * @return True on success or false otherwise
+ */
+bool bg_team_delete(int bg_id)
+{
+	std::shared_ptr<s_battleground_data> bgteam = util::umap_find(bg_team_db, bg_id);
+
+	if (bgteam) {
+		for (const auto &pl_sd : bgteam->members) {
+			bg_send_dot_remove(pl_sd.sd);
+			pl_sd.sd->bg_id = 0;
+		}
+
+		bg_team_db.erase(bg_id);
+
+		return true;
+	}
+	
+	return false;
+}
+
+/**
+ * Warps a Battleground team
+ * @param bg_id: Battleground ID
+ * @param mapindex: Map Index
+ * @param x: X coordinate
+ * @param y: Y coordinate
+ * @return True on success or false otherwise
+ */
+bool bg_team_warp(int bg_id, unsigned short mapindex, short x, short y)
 {
+	std::shared_ptr<s_battleground_data> bgteam = util::umap_find(bg_team_db, bg_id);
+
+	if (bgteam) {
+		for (const auto &pl_sd : bgteam->members)
+			pc_setpos(pl_sd.sd, mapindex, x, y, CLR_TELEPORT);
+
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * Remove a player's Battleground map marker
+ * @param sd: Player data
+ */
+void bg_send_dot_remove(struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
 	if( sd && sd->bg_id )
 		clif_bg_xy_remove(sd);
-	return 0;
+	return;
 }
 
-int bg_team_join(int bg_id, struct map_session_data *sd)
-{ // Player joins team
-	int i;
-	struct battleground_data *bg = bg_team_search(bg_id);
+/**
+ * Join a player to a Battleground team
+ * @param bg_id: Battleground ID
+ * @param sd: Player data
+ * @param is_queue: Joined from queue
+ * @return True on success or false otherwise
+ */
+bool bg_team_join(int bg_id, struct map_session_data *sd, bool is_queue)
+{
+	if (!sd || sd->bg_id)
+		return false;
+
+	std::shared_ptr<s_battleground_data> bgteam = util::umap_find(bg_team_db, bg_id);
 
-	if( bg == NULL || sd == NULL || sd->bg_id )
-		return 0;
+	if (bgteam) {
+		if (bgteam->members.size() == MAX_BG_MEMBERS)
+			return false; // No free slots
 
-	ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == NULL);
-	if( i == MAX_BG_MEMBERS )
-		return 0; // No free slots
+		s_battleground_member_data member = {};
 
-	sd->bg_id = bg_id;
-	bg->members[i].sd = sd;
-	bg->members[i].x = sd->bl.x;
-	bg->members[i].y = sd->bl.y;
-	bg->count++;
+		sd->bg_id = bg_id;
+		member.sd = sd;
+		member.x = sd->bl.x;
+		member.y = sd->bl.y;
+		if (is_queue) { // Save the location from where the person entered the battleground
+			member.entry_point.map = sd->mapindex;
+			member.entry_point.x = sd->bl.x;
+			member.entry_point.y = sd->bl.y;
+		}
+		bgteam->members.push_back(member);
 
-	guild_send_dot_remove(sd);
+		guild_send_dot_remove(sd);
 
-	for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
-		struct map_session_data *pl_sd;
+		for (const auto &pl_sd : bgteam->members) {
+			if (pl_sd.sd != sd)
+				clif_hpmeter_single(sd->fd, pl_sd.sd->bl.id, pl_sd.sd->battle_status.hp, pl_sd.sd->battle_status.max_hp);
+		}
 
-		if( (pl_sd = bg->members[i].sd) != NULL && pl_sd != sd )
-			clif_hpmeter_single(sd->fd, pl_sd->bl.id, pl_sd->battle_status.hp, pl_sd->battle_status.max_hp);
+		clif_bg_hp(sd);
+		clif_bg_xy(sd);
+		return true;
 	}
 
-	clif_bg_hp(sd);
-	clif_bg_xy(sd);
-	return 1;
+	return false;
 }
 
-int bg_team_leave(struct map_session_data *sd, int flag)
-{ // Single Player leaves team
-	int i, bg_id;
-	struct battleground_data *bg;
-	char output[128];
-
-	if( sd == NULL || !sd->bg_id )
-		return 0;
+/**
+ * Remove a player from Battleground team
+ * @param sd: Player data
+ * @param quit: True if closed client or false otherwise
+ * @param deserter: Whether to apply the deserter status or not
+ * @return Remaining count in Battleground team or -1 on failure
+ */
+int bg_team_leave(struct map_session_data *sd, bool quit, bool deserter)
+{
+	if (!sd || !sd->bg_id)
+		return -1;
 
 	bg_send_dot_remove(sd);
-	bg_id = sd->bg_id;
+
+	int bg_id = sd->bg_id;
+	std::shared_ptr<s_battleground_data> bgteam = util::umap_find(bg_team_db, bg_id);
+
 	sd->bg_id = 0;
 
-	if( (bg = bg_team_search(bg_id)) == NULL )
-		return 0;
+	if (bgteam) {
+		char output[CHAT_SIZE_MAX];
+		int i;
+
+		ARR_FIND(0, bgteam->members.size(), i, bgteam->members[i].sd == sd);
+		if (i < bgteam->members.size()) { // Removes member from BG
+			if (bgteam->members[i].entry_point.map != 0) {
+				int16 map_id = map_mapindex2mapid(bgteam->members[i].entry_point.map);
+
+				if (!map_getmapflag(map_id, MF_NOSAVE))
+					pc_setpos(sd, bgteam->members[i].entry_point.map, bgteam->members[i].entry_point.x, bgteam->members[i].entry_point.y, CLR_TELEPORT);
+				else
+					pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); // Warp to save point if the entry map has no save flag.
+			}
+			util::erase_at(bgteam->members, i);
+		}
 
-	ARR_FIND(0, MAX_BG_MEMBERS, i, bg->members[i].sd == sd);
-	if( i < MAX_BG_MEMBERS ) // Removes member from BG
-		memset(&bg->members[i], 0, sizeof(bg->members[0]));
+		if (quit)
+			sprintf(output, "Server: %s has quit the game...", sd->status.name);
+		else
+			sprintf(output, "Server: %s is leaving the battlefield...", sd->status.name);
 
-	bg->count--;
+		clif_bg_message(bgteam.get(), 0, "Server", output, strlen(output) + 1);
 
-	if( flag )
-		sprintf(output, "Server : %s has quit the game...", sd->status.name);
-	else
-		sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name);
+		if (!bgteam->logout_event.empty() && quit)
+			npc_event(sd, bgteam->logout_event.c_str(), 0);
 
-	clif_bg_message(bg, 0, "Server", output, strlen(output) + 1);
+		if (deserter) {
+			std::shared_ptr<s_battleground_type> bg = battleground_db.find(bg_id);
 
-	if( bg->logout_event[0] && flag )
-		npc_event(sd, bg->logout_event, 0);
+			if (bg)
+				sc_start(nullptr, &sd->bl, SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT, 100, 1, static_cast<t_tick>(bg->deserter_time) * 1000); // Deserter timer
+		}
 
-	return bg->count;
+		return bgteam->members.size();
+	}
+
+	return -1;
 }
 
-int bg_member_respawn(struct map_session_data *sd)
-{ // Respawn after killed
-	struct battleground_data *bg;
+/**
+ * Respawn a Battleground player
+ * @param sd: Player data
+ * @return True on success or false otherwise
+ */
+bool bg_member_respawn(struct map_session_data *sd)
+{
+	if (!sd || !sd->bg_id || !pc_isdead(sd))
+		return false;
 
-	if( sd == NULL || !pc_isdead(sd) || !sd->bg_id || (bg = bg_team_search(sd->bg_id)) == NULL )
-		return 0;
+	std::shared_ptr<s_battleground_data> bgteam = util::umap_find(bg_team_db, sd->bg_id);
 
-	if( bg->mapindex == 0 )
-		return 0; // Respawn not handled by Core
+	if (bgteam) {
+		if (bgteam->cemetery.map == 0)
+			return false; // Respawn not handled by Core
 
-	pc_setpos(sd, bg->mapindex, bg->x, bg->y, CLR_OUTSIGHT);
-	status_revive(&sd->bl, 1, 100);
+		pc_setpos(sd, bgteam->cemetery.map, bgteam->cemetery.x, bgteam->cemetery.y, CLR_OUTSIGHT);
+		status_revive(&sd->bl, 1, 100);
 
-	return 1; // Warped
+		return true; // Warped
+	}
+
+	return false;
 }
 
-int bg_create(unsigned short mapindex, short rx, short ry, const char *ev, const char *dev)
+/**
+ * Initialize Battleground data
+ * @param mapindex: Map Index
+ * @param rx: Return X coordinate (on death)
+ * @param ry: Return Y coordinate (on death)
+ * @param ev: Logout NPC Event
+ * @param dev: Death NPC Event
+ * @return Battleground ID
+ */
+int bg_create(uint16 mapindex, s_battleground_team* team)
 {
-	struct battleground_data *bg;
-	bg_team_counter++;
+	int bg_team_counter = 1;
+
+	while (bg_team_db.find(bg_team_counter) != bg_team_db.end())
+		bg_team_counter++;
 
-	CREATE(bg, struct battleground_data, 1);
-	bg->bg_id = bg_team_counter;
-	bg->count = 0;
-	bg->mapindex = mapindex;
-	bg->x = rx;
-	bg->y = ry;
-	safestrncpy(bg->logout_event, ev, sizeof(bg->logout_event));
-	safestrncpy(bg->die_event, dev, sizeof(bg->die_event));
+	bg_team_db[bg_team_counter] = std::make_shared<s_battleground_data>();
 
-	memset(&bg->members, 0, sizeof(bg->members));
-	idb_put(bg_team_db, bg_team_counter, bg);
+	std::shared_ptr<s_battleground_data> bg = util::umap_find(bg_team_db, bg_team_counter);
 
-	return bg->bg_id;
+	bg->id = bg_team_counter;
+	bg->cemetery.map = mapindex;
+	bg->cemetery.x = team->warp_x;
+	bg->cemetery.y = team->warp_y;
+	bg->logout_event = team->quit_event.c_str();
+	bg->die_event = team->death_event.c_str();
+	bg->members.clear();
+
+	return bg->id;
 }
 
+/**
+ * Get an object's Battleground ID
+ * @param bl: Object
+ * @return Battleground ID
+ */
 int bg_team_get_id(struct block_list *bl)
 {
 	nullpo_ret(bl);
+
 	switch( bl->type ) {
 		case BL_PC:
 			return ((TBL_PC*)bl)->bg_id;
@@ -202,7 +535,7 @@ int bg_team_get_id(struct block_list *bl)
 			struct map_session_data *msd;
 			struct mob_data *md = (TBL_MOB*)bl;
 
-			if( md->special_state.ai && (msd = map_id2sd(md->master_id)) != NULL )
+			if( md->special_state.ai && !(msd = map_id2sd(md->master_id)) )
 				return msd->bg_id;
 
 			return md->bg_id;
@@ -222,38 +555,41 @@ int bg_team_get_id(struct block_list *bl)
 	return 0;
 }
 
-int bg_send_message(struct map_session_data *sd, const char *mes, int len)
+/**
+ * Send a Battleground chat message
+ * @param sd: Player data
+ * @param mes: Message
+ * @param len: Message length
+ */
+void bg_send_message(struct map_session_data *sd, const char *mes, int len)
 {
-	struct battleground_data *bg;
-
-	nullpo_ret(sd);
+	nullpo_retv(sd);
 
-	if( sd->bg_id == 0 || (bg = bg_team_search(sd->bg_id)) == NULL )
-		return 0;
+	if (!sd->bg_id)
+		return;
 	
-	clif_bg_message(bg, sd->bl.id, sd->status.name, mes, len);
+	std::shared_ptr<s_battleground_data> bgteam = util::umap_find(bg_team_db, sd->bg_id);
 
-	return 0;
+	if (bgteam)
+		clif_bg_message(bgteam.get(), sd->bl.id, sd->status.name, mes, len);
+
+	return;
 }
 
 /**
+ * Update a player's Battleground minimap icon
  * @see DBApply
  */
-int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap)
+int bg_send_xy_timer_sub(std::shared_ptr<s_battleground_data> bg)
 {
-	struct battleground_data *bg = (struct battleground_data *)db_data2ptr(data);
 	struct map_session_data *sd;
-	int i;
-
-	nullpo_ret(bg);
 
-	for( i = 0; i < MAX_BG_MEMBERS; i++ ) {
-		if( (sd = bg->members[i].sd) == NULL )
-			continue;
+	for (auto &pl_sd : bg->members) {
+		sd = pl_sd.sd;
 
-		if( sd->bl.x != bg->members[i].x || sd->bl.y != bg->members[i].y ) { // xy update
-			bg->members[i].x = sd->bl.x;
-			bg->members[i].y = sd->bl.y;
+		if (sd->bl.x != pl_sd.x || sd->bl.y != pl_sd.y) { // xy update
+			pl_sd.x = sd->bl.x;
+			pl_sd.y = sd->bl.y;
 			clif_bg_xy(sd);
 		}
 	}
@@ -261,20 +597,839 @@ int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap)
 	return 0;
 }
 
-TIMER_FUNC(bg_send_xy_timer){
-	bg_team_db->foreach(bg_team_db, bg_send_xy_timer_sub, tick);
+/**
+ * Update a player's Battleground minimap icon
+ * @param tid: Timer ID
+ * @param tick: Timer
+ * @param id: ID
+ * @return 0 on success or 1 otherwise
+ */
+TIMER_FUNC(bg_send_xy_timer)
+{
+	for (const auto &entry : bg_team_db)
+		bg_send_xy_timer_sub(entry.second);
+
+	return 0;
+}
+
+/**
+ * Mark a Battleground as ready to begin queuing
+ * @param tid: Timer ID
+ * @param tick: Timer
+ * @param id: ID
+ * @return 0 on success or 1 otherwise
+ */
+static TIMER_FUNC(bg_on_ready_loopback)
+{
+	s_battleground_queue *queue = (s_battleground_queue*)data;
+
+	nullpo_retr(1, queue);
+
+	std::shared_ptr<s_battleground_type> bg = battleground_db.find(queue->id);
+
+	if (bg) {
+		bg_queue_on_ready(bg->name.c_str(), std::shared_ptr<s_battleground_queue>(queue));
+		return 0;
+	} else {
+		ShowError("bg_on_ready_loopback: Can't find battleground %d in the battlegrounds database.\n", queue->id);
+		return 1;
+	}
+}
+
+/**
+ * Reset Battleground queue data
+ * @param tid: Timer ID
+ * @param tick: Timer
+ * @param id: ID
+ * @return 0 on success or 1 otherwise
+ */
+static TIMER_FUNC(bg_on_ready_expire)
+{
+	s_battleground_queue *queue = (s_battleground_queue*)data;
+
+	nullpo_retr(1, queue);
+
+	queue->in_ready_state = false;
+	queue->map->isReserved = false; // Remove reservation to free up for future queue
+	queue->map = nullptr;
+	queue->accepted_players = 0; // Reset the queue count
+
+	std::string bg_name = battleground_db.find(queue->id)->name;
+
+	for (const auto &sd : queue->teama_members) {
+		sd->bg_queue_accept_state = false;
+		clif_bg_queue_apply_result(BG_APPLY_QUEUE_FINISHED, bg_name.c_str(), sd);
+	}
+
+	for (const auto &sd : queue->teamb_members) {
+		sd->bg_queue_accept_state = false;
+		clif_bg_queue_apply_result(BG_APPLY_QUEUE_FINISHED, bg_name.c_str(), sd);
+	}
+	return 0;
+}
+
+/**
+ * Start a Battleground
+ * @param tid: Timer ID
+ * @param tick: Timer
+ * @param id: ID
+ * @return 0 on success or 1 otherwise
+ */
+static TIMER_FUNC(bg_on_ready_start)
+{
+	s_battleground_queue *queue = (s_battleground_queue*)data;
 
+	nullpo_retr(1, queue);
+
+	bg_queue_start_battleground(std::shared_ptr<s_battleground_queue>(queue));
 	return 0;
 }
 
+/**
+ * Check if the given player is in a battleground
+ * @param sd: Player data
+ * @return True if in a battleground or false otherwise
+ */
+bool bg_player_is_in_bg_map(struct map_session_data *sd)
+{
+	nullpo_retr(false, sd);
+
+	for (const auto &pair : battleground_db) {
+		for (const auto &it : pair.second->maps) {
+			if (it.mapid == sd->bl.m)
+				return true;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * Battleground status change check
+ * @param sd: Player data
+ * @param name: Battleground name
+ * @return True if the player is good to join a queue or false otherwise
+ */
+static bool bg_queue_check_status(struct map_session_data* sd, const char *name)
+{
+	nullpo_retr(false, sd);
+
+	if (sd->sc.count) {
+		if (sd->sc.data[SC_ENTRY_QUEUE_APPLY_DELAY]) { // Exclude any player who's recently left a battleground queue
+			char buf[CHAT_SIZE_MAX];
+
+			sprintf(buf, msg_txt(sd, 339), (get_timer(sd->sc.data[SC_ENTRY_QUEUE_APPLY_DELAY]->timer)->tick - gettick()) / 1000); // You can't apply to a battleground queue for %d seconds due to recently leaving one.
+			clif_bg_queue_apply_result(BG_APPLY_NONE, name, sd);
+			clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], buf, false, SELF);
+			return false;
+		}
+
+		if (sd->sc.data[SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT]) { // Exclude any player who's recently deserted a battleground
+			char buf[CHAT_SIZE_MAX];
+			t_tick status_tick = get_timer(sd->sc.data[SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT]->timer)->tick, tick = gettick();
+
+			sprintf(buf, msg_txt(sd, 338), ((status_tick - tick) / 1000) / 60, ((status_tick - tick) / 1000) % 60); // You can't apply to a battleground queue due to recently deserting a battleground. Time remaining: %d minutes and %d seconds.
+			clif_bg_queue_apply_result(BG_APPLY_NONE, name, sd);
+			clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], buf, false, SELF);
+			return false;
+		}
+	}
+
+	return true;
+}
+
+/**
+ * Check to see if a Battleground is joinable
+ * @param bg: Battleground data
+ * @param sd: Player data
+ * @param name: Battleground name
+ * @return True on success or false otherwise
+ */
+bool bg_queue_check_joinable(std::shared_ptr<s_battleground_type> bg, struct map_session_data *sd, const char *name)
+{
+	nullpo_retr(false, sd);
+
+	if (bg->min_lvl && sd->status.base_level < bg->min_lvl) { // Check min level if min_lvl isn't 0
+		clif_bg_queue_apply_result(BG_APPLY_PLAYER_LEVEL, name, sd);
+		return false;
+	}
+
+	if (bg->max_lvl && sd->status.base_level > bg->max_lvl) { // Check max level if max_lvl isn't 0
+		clif_bg_queue_apply_result(BG_APPLY_PLAYER_LEVEL, name, sd);
+		return false;
+	}
+
+	if (!bg_queue_check_status(sd, name))
+		return false;
+
+	if (bg_player_is_in_bg_map(sd)) { // Is the player currently in a battleground map? Reject them.
+		clif_bg_queue_apply_result(BG_APPLY_NONE, name, sd);
+		clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 337), false, SELF); // You may not join a battleground queue when you're in a battleground map.
+		return false;
+	}
+
+	return true; // Return true if all conditions are met.
+}
+
+/**
+ * Sub function for reserving a slot in the Battleground if it's joinable
+ * @param name: Battleground map name
+ * @param state: Whether to mark reserved or not
+ * @return True on success or false otherwise
+ */
+bool bg_queue_reservation(const char *name, bool state)
+{
+	int16 mapid = map_mapname2mapid(name);
+
+	for (const auto &pair : battleground_db) {
+		// Bound checking isn't needed since we iterate within battleground_db's bound.
+		for (auto &it : pair.second->maps) {
+			if (it.mapid == mapid) {
+				it.isReserved = state;
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
+/**
+ * Initialize a Battleground queue
+ * @param bg_id: Battleground ID
+ * @param req_players: Required amount of players
+ * @return s_battleground_queue*
+ */
+std::shared_ptr<s_battleground_queue> bg_queue_create(int bg_id, int req_players)
+{
+	auto queue = std::make_shared<s_battleground_queue>();
+
+	queue->id = bg_id;
+	queue->required_players = req_players;
+	queue->accepted_players = 0;
+	queue->tid_expire = INVALID_TIMER;
+	queue->tid_start = INVALID_TIMER;
+	queue->tid_requeue = INVALID_TIMER;
+	queue->in_ready_state = false;
+
+	return queue;
+}
+
+/**
+ * Allow a player to join a Battleground queue
+ * @param name: Battleground name
+ * @param sd: Player data
+ * @return @see e_bg_queue_apply_ack
+ */
+e_bg_queue_apply_ack bg_queue_join(const char *name, struct map_session_data *sd)
+{
+	if (!sd) {
+		ShowError("bg_queue_join: Tried to join non-existent player.\n.");
+		return BG_APPLY_NONE;
+	}
+
+	if (!bg_queue_check_status(sd, name))
+		return BG_APPLY_NONE;
+
+	if (bg_player_is_in_bg_map(sd)) {
+		clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 337), false, SELF); // You may not join a battleground queue when you're in a battleground map.
+		return BG_APPLY_NONE;
+	}
+
+	std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
+
+	if (!bg) {
+		ShowWarning("bq_queue_join: Could not find battleground \"%s\" requested by %s (AID: %d / CID: %d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id);
+		return BG_APPLY_INVALID_NAME;
+	}
+
+	if (bg->min_lvl && sd->status.base_level < bg->min_lvl)
+		return BG_APPLY_PLAYER_LEVEL; // Level too low
+
+	if (bg->max_lvl && sd->status.base_level > bg->max_lvl)
+		return BG_APPLY_PLAYER_LEVEL; // Level too high
+
+	std::shared_ptr<s_battleground_queue> queue;
+	bool r;
+
+	if (bg_queues.empty()) {
+		r = rnd() % 2 != 0;
+
+		queue = bg_queue_create(bg->id, bg->required_players);
+
+		if (!r)
+			queue->teama_members.push_back(sd);
+		else
+			queue->teamb_members.push_back(sd);
+
+		sd->bg_queue = queue;
+		bg_queues.insert(bg_queues.begin(), queue);
+		return BG_APPLY_ACCEPT;
+	} else {
+		r = rnd() % 2 != 0;
+
+		for (const auto &it : bg_queues) {
+			try {
+				queue = it;
+			} catch (std::out_of_range &) {
+				continue;
+			}
+
+			if (queue->in_ready_state)
+				continue;
+			if (!r) {
+				if (queue->teama_members.size() != queue->required_players) {
+					sd->bg_queue = queue;
+					queue->teama_members.push_back(sd);
+
+					if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined
+						bg_queue_on_ready(name, queue);
+					return BG_APPLY_ACCEPT;
+				} else if (queue->teamb_members.size() != queue->required_players) {
+					sd->bg_queue = queue;
+					queue->teamb_members.push_back(sd);
+
+					if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined
+						bg_queue_on_ready(name, queue);
+					return BG_APPLY_ACCEPT;
+				}
+			} else {
+				if (queue->teamb_members.size() != queue->required_players) {
+					sd->bg_queue = queue;
+					queue->teamb_members.push_back(sd);
+
+					if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined
+						bg_queue_on_ready(name, queue);
+					return BG_APPLY_ACCEPT;
+				} else if (queue->teama_members.size() != queue->required_players) {
+					sd->bg_queue = queue;
+					queue->teama_members.push_back(sd);
+
+					if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined
+						bg_queue_on_ready(name, queue);
+					return BG_APPLY_ACCEPT;
+				}
+			}
+		}
+	}
+
+	queue = bg_queue_create(bg->id, bg->required_players);
+	r = rnd() % 2 != 0;
+
+	if (!r)
+		queue->teama_members.push_back(sd);
+	else
+		queue->teamb_members.push_back(sd);
+
+	sd->bg_queue = queue;
+	bg_queues.insert(bg_queues.begin(), queue);
+	return BG_APPLY_ACCEPT;
+}
+
+/**
+ * Join a party onto the same side of a Battleground
+ * @param name: Battleground name
+ * @param sd: Player who requested to join the battlegrounds
+ * @return @see e_bg_queue_apply_ack
+ */
+e_bg_queue_apply_ack bg_queue_join_party(const char *name, struct map_session_data *sd)
+{
+	struct party_data *p = party_search(sd->status.party_id);
+
+	if (!p)
+		return BG_APPLY_INVALID_APP; // Someone has bypassed the client check for being in a party
+
+	for (const auto &it : p->party.member) {
+		if (it.leader && sd->status.char_id != it.char_id)
+			return BG_APPLY_PARTYGUILD_LEADER; // Not the party leader
+	}
+
+	std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
+
+	if (bg) {
+		int p_online = 0;
+
+		for (const auto &it : p->party.member) {
+			if (it.online)
+				p_online++;
+		}
+
+		if (p_online > bg->max_players)
+			return BG_APPLY_PLAYER_COUNT; // Too many party members online
+		
+		std::vector<struct map_session_data *> list;
+
+		for (const auto &it : p->party.member) {
+			if (list.size() == bg->max_players)
+				break;
+
+			if (it.online) {
+				struct map_session_data *pl_sd = map_charid2sd(it.char_id);
+
+				if (pl_sd)
+					list.push_back(pl_sd);
+			}
+		}
+
+		return bg_queue_join_multi(name, sd, list); // Join as party, all on the same side of the BG
+	} else {
+		ShowWarning("clif_parse_bg_queue_apply_request: Could not find Battleground: \"%s\" requested by player: %s (AID:%d CID:%d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id);
+		return BG_APPLY_INVALID_NAME; // Invalid BG name
+	}
+}
+
+/**
+ * Join a guild onto the same side of a Battleground
+ * @param name: Battleground name
+ * @param sd: Player who requested to join the battlegrounds
+ * @return @see e_bg_queue_apply_ack
+ */
+e_bg_queue_apply_ack bg_queue_join_guild(const char *name, struct map_session_data *sd)
+{
+	if (!sd->guild)
+		return BG_APPLY_INVALID_APP; // Someone has bypassed the client check for being in a guild
+	
+	if (strcmp(sd->status.name, sd->guild->master) != 0)
+		return BG_APPLY_PARTYGUILD_LEADER; // Not the guild leader
+
+	std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
+
+	if (bg) {
+		struct guild *g = guild_search(sd->status.guild_id);
+		int g_online = 0;
+
+		for (const auto &it : g->member) {
+			if (it.online)
+				g_online++;
+		}
+
+		if (g_online > bg->max_players)
+			return BG_APPLY_PLAYER_COUNT; // Too many guild members online
+
+		std::vector<struct map_session_data *> list;
+
+		for (const auto &it : g->member) {
+			if (list.size() == bg->max_players)
+				break;
+
+			if (it.online) {
+				struct map_session_data *pl_sd = map_charid2sd(it.char_id);
+
+				if (pl_sd)
+					list.push_back(pl_sd);
+			}
+		}
+
+		return bg_queue_join_multi(name, sd, list); // Join as guild, all on the same side of the BG
+	} else {
+		ShowWarning("clif_parse_bg_queue_apply_request: Could not find Battleground: \"%s\" requested by player: %s (AID:%d CID:%d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id);
+		return BG_APPLY_INVALID_NAME; // Invalid BG name
+	}
+}
+
+/**
+ * Join multiple players onto the same side of a Battleground
+ * @param name: Battleground name
+ * @param sd: Player who requested to join the battlegrounds
+ * @param list: Contains all players including the player who requested to join
+ * @return @see e_bg_queue_apply_ack
+ */
+e_bg_queue_apply_ack bg_queue_join_multi(const char *name, struct map_session_data *sd, std::vector <map_session_data *> list)
+{
+	if (!sd) {
+		ShowError("bg_queue_join_multi: Tried to join non-existent player\n.");
+		return BG_APPLY_NONE;
+	}
+
+	if (!bg_queue_check_status(sd, name))
+		return BG_APPLY_NONE;
+
+	if (bg_player_is_in_bg_map(sd)) {
+		clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 337), false, SELF); // You may not join a battleground queue when you're in a battleground map.
+		return BG_APPLY_NONE;
+	}
+
+	std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
+
+	if (!bg) {
+		ShowWarning("bq_queue_join_multi: Could not find battleground \"%s\" requested by %s (AID: %d / CID: %d)\n", name, sd->status.name, sd->status.account_id, sd->status.char_id);
+		return BG_APPLY_INVALID_NAME;
+	}
+
+	if (bg->min_lvl && sd->status.base_level < bg->min_lvl)
+		return BG_APPLY_PLAYER_LEVEL; // Level too low
+	
+	if (bg->max_lvl && sd->status.base_level > bg->max_lvl)
+		return BG_APPLY_PLAYER_LEVEL; // Level too high
+
+	if (bg_queues.empty()) {
+		std::shared_ptr<s_battleground_queue> queue = bg_queue_create(bg->id, bg->required_players);
+		bool r = rnd() % 2 != 0;
+
+		if (!r) {
+			while (!list.empty() && queue->teama_members.size() < bg->required_players) {
+				struct map_session_data *sd2 = list.back();
+
+				list.pop_back();
+
+				if (!sd2 || sd2->bg_queue)
+					continue;
+
+				if (!bg_queue_check_joinable(bg, sd2, name))
+					continue;
+
+				sd2->bg_queue = queue;
+				clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
+				clif_bg_queue_apply_notify(name, sd2);
+				queue->teama_members.insert(queue->teama_members.begin(), sd2);
+			}
+		} else {
+			while (!list.empty() && queue->teamb_members.size() < bg->required_players) {
+				struct map_session_data *sd2 = list.back();
+
+				list.pop_back();
+
+				if (!sd2 || sd2->bg_queue)
+					continue;
+
+				if (!bg_queue_check_joinable(bg, sd2, name))
+					continue;
+
+				sd2->bg_queue = queue;
+				clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
+				clif_bg_queue_apply_notify(name, sd2);
+				queue->teamb_members.insert(queue->teamb_members.begin(), sd2);
+			}
+		}
+
+		bg_queues.insert(bg_queues.begin(), queue);
+
+		return BG_APPLY_ACCEPT;
+	} else {
+		std::shared_ptr<s_battleground_queue> queue;
+		bool r = rnd() % 2 != 0;
+
+		for (const auto &it : bg_queues) {
+			try {
+				queue = it;
+			} catch (std::out_of_range &) {
+				continue;
+			}
+
+			if (queue->in_ready_state)
+				continue;
+
+			if (queue->teama_members.size() + list.size() <= bg->required_players || queue->teamb_members.size() + list.size() <= bg->required_players) { // Make sure there's enough space on one side to join as a party/guild in this queue
+				if (!r && queue->teama_members.size() + list.size() <= bg->required_players) {
+					while (!list.empty() && queue->teama_members.size() < bg->required_players) {
+						struct map_session_data *sd2 = list.back();
+
+						list.pop_back();
+
+						if (!sd2 || sd2->bg_queue)
+							continue;
+
+						if (!bg_queue_check_joinable(bg, sd2, name))
+							continue;
+
+						sd2->bg_queue = queue;
+						clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
+						clif_bg_queue_apply_notify(name, sd2);
+						queue->teama_members.insert(queue->teama_members.begin(), sd2);
+					}
+
+					if (queue->teama_members.size() == bg->required_players && queue->teamb_members.size() == bg->required_players) // Enough players have joined
+						bg_queue_on_ready(name, queue);
+
+					return BG_APPLY_ACCEPT;
+				} else {
+					while (!list.empty() && queue->teamb_members.size() < bg->required_players) {
+						struct map_session_data *sd2 = list.back();
+
+						list.pop_back();
+
+						if (!sd2)
+							continue;
+
+						if (!bg_queue_check_joinable(bg, sd2, name))
+							continue;
+
+						sd2->bg_queue = queue;
+						clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
+						clif_bg_queue_apply_notify(name, sd2);
+						queue->teamb_members.insert(queue->teamb_members.begin(), sd2);
+					}
+				}
+
+				return BG_APPLY_ACCEPT;
+			}
+		}
+
+		// Create a new queue if none of the existing ones are joinable for this party/guild
+		queue = nullptr;
+		queue = bg_queue_create(bg->id, bg->required_players);
+		r = rnd() % 2 != 0;
+
+		if (!r) {
+			while (!list.empty() && queue->teama_members.size() < bg->required_players) {
+				struct map_session_data *sd2 = list.back();
+
+				list.pop_back();
+
+				if (!sd2 || sd2->bg_queue)
+					continue;
+
+				if (!bg_queue_check_joinable(bg, sd2, name))
+					continue;
+
+				sd2->bg_queue = queue;
+				clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
+				clif_bg_queue_apply_notify(name, sd2);
+				queue->teama_members.insert(queue->teama_members.begin(), sd2);
+			}
+		} else {
+			while (!list.empty() && queue->teamb_members.size() < bg->required_players) {
+				struct map_session_data *sd2 = list.back();
+
+				list.pop_back();
+
+				if (!sd2 || sd2->bg_queue)
+					continue;
+
+				if (!bg_queue_check_joinable(bg, sd2, name))
+					continue;
+
+				sd2->bg_queue = queue;
+				clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
+				clif_bg_queue_apply_notify(name, sd2);
+				queue->teamb_members.insert(queue->teamb_members.begin(), sd2);
+			}
+		}
+
+		bg_queues.insert(bg_queues.begin(), queue);
+
+		return BG_APPLY_ACCEPT;
+	}
+
+	return BG_APPLY_RECONNECT; // Something went wrong, sends reconnect and then reapply message to client.
+}
+
+/**
+ * Sub function for leaving a Battleground queue
+ * @param sd: Player leaving
+ * @param lista: List of players in queue data
+ * @param listb: List of players in second queue data
+ * @return True on success or false otherwise
+ */
+static bool bg_queue_leave_sub(struct map_session_data *sd, std::vector<map_session_data *> lista, std::vector<map_session_data *> listb)
+{
+	if (!sd)
+		return false;
+
+	auto list_it = lista.begin();
+
+	while (list_it != lista.end()) {
+		struct map_session_data *player = *list_it;
+
+		if (player == sd) {
+			if (sd->bg_queue->in_ready_state) {
+				sd->bg_queue->accepted_players = 0;
+				sd->bg_queue->in_ready_state = false;
+				sd->bg_queue_accept_state = false;
+			}
+
+			list_it = lista.erase(list_it);
+
+			if (lista.empty() && listb.empty()) { // If there are no players left in the queue, discard it
+				auto queue_it = bg_queues.begin();
+
+				while (queue_it != bg_queues.end()) {
+					std::shared_ptr<s_battleground_queue> q = *queue_it;
+
+					if (sd->bg_queue == q) {
+						if (q->tid_requeue != INVALID_TIMER && get_timer(q->tid_requeue)) {
+							delete_timer(q->tid_requeue, bg_on_ready_loopback);
+							q->tid_requeue = INVALID_TIMER;
+						}
+
+						queue_it = bg_queues.erase(queue_it);
+					}
+				}
+			}
+
+			sc_start(nullptr, &sd->bl, SC_ENTRY_QUEUE_APPLY_DELAY, 100, 1, 60000);
+			sd->bg_queue = nullptr;
+			return true;
+		} else {
+			list_it++;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * Leave a Battleground queue
+ * @param sd: Player data
+ * @return True on success or false otherwise
+ */
+bool bg_queue_leave(struct map_session_data *sd)
+{
+	if (!sd || !sd->bg_queue)
+		return false;
+
+	if (!bg_queue_leave_sub(sd, sd->bg_queue->teama_members, sd->bg_queue->teamb_members) && !bg_queue_leave_sub(sd, sd->bg_queue->teamb_members, sd->bg_queue->teama_members)) {
+		ShowError("bg_queue_leave: Couldn't find player %s in battlegrounds queue.\n", sd->status.name);
+		return false;
+	} else
+		return true;
+}
+
+/**
+ * Send packets to all clients in queue to notify them that the battleground is ready to be joined
+ * @param name: Battleground name
+ * @param queue: Battleground queue
+ * @return True on success or false otherwise
+ */
+bool bg_queue_on_ready(const char *name, std::shared_ptr<s_battleground_queue> queue)
+{
+	std::shared_ptr<s_battleground_type> bg = battleground_db.find(queue->id);
+
+	if (!bg) {
+		ShowError("bg_queue_on_ready: Couldn't find battleground ID %d in battlegrounds database.\n", queue->id);
+		return false;
+	}
+
+	queue->accepted_players = 0; // Reset the counter just in case.
+
+	if (queue->teama_members.size() != queue->required_players || queue->teamb_members.size() != queue->required_players)
+		return false; // Return players to the queue and stop reapplying the timer
+
+	s_battleground_map *bgmap = nullptr;
+
+	for (auto &it : bg->maps) {
+		if (!it.isReserved) {
+			it.isReserved = true;
+			bgmap = &it;
+			queue->map = &it;
+			break;
+		}
+	}
+
+	if (!bgmap) { // All the battleground maps are reserved. Set a timer to check for an open battleground every 10 seconds.
+		queue->tid_requeue = add_timer(gettick() + 10000, bg_on_ready_loopback, 0, (intptr_t)queue.get());
+		return false;
+	}
+
+	queue->in_ready_state = true;
+	queue->tid_expire = add_timer(gettick() + 20000, bg_on_ready_expire, 0, (intptr_t)queue.get());
+
+	for (const auto &sd : queue->teama_members)
+		clif_bg_queue_lobby_notify(name, sd);
+
+	for (const auto &sd : queue->teamb_members)
+		clif_bg_queue_lobby_notify(name, sd);
+
+	return true;
+}
+
+/**
+ * Update the Battleground queue when the player accepts the invite
+ * @param queue: Battleground queue
+ * @param sd: Player data
+ */
+void bg_queue_on_accept_invite(std::shared_ptr<s_battleground_queue> queue, struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	sd->bg_queue_accept_state = true;
+	queue->accepted_players++;
+	clig_bg_queue_ack_lobby(true, map_mapid2mapname(queue->map->mapid), map_mapid2mapname(queue->map->mapid), sd);
+
+	if (queue->accepted_players == queue->required_players * 2) {
+		queue->tid_start = add_timer(gettick() + battleground_db.find(queue->id)->start_delay * 1000, bg_on_ready_start, 0, (intptr_t)queue.get());
+
+		if (queue->tid_expire != INVALID_TIMER && get_timer(queue->tid_expire)) {
+			delete_timer(queue->tid_expire, bg_on_ready_expire);
+			queue->tid_expire = INVALID_TIMER;
+		}
+	}
+}
+
+/**
+ * Begin the Battleground from the given queue
+ * @param queue: Battleground queue
+ */
+void bg_queue_start_battleground(std::shared_ptr<s_battleground_queue> queue)
+{
+	if (queue->tid_start != INVALID_TIMER && get_timer(queue->tid_start)) {
+		delete_timer(queue->tid_start, bg_on_ready_start);
+		queue->tid_start = INVALID_TIMER;
+	}
+
+	std::shared_ptr<s_battleground_type> bg = battleground_db.find(queue->id);
+
+	if (!bg) {
+		queue->map->isReserved = false; // Remove reservation to free up for future queue
+		queue->map = nullptr;
+		ShowError("bg_queue_start_battleground: Could not find battleground ID %d in battlegrounds database.\n", queue->id);
+		return;
+	}
+
+	uint16 map_idx = map_id2index(queue->map->mapid);
+	int bg_team_1 = bg_create(map_idx, &queue->map->team1);
+	int bg_team_2 = bg_create(map_idx, &queue->map->team2);
+
+	for (const auto &sd : queue->teama_members) {
+		sd->bg_queue = nullptr;
+		sd->bg_queue_accept_state = false;
+		clif_bg_queue_entry_init(sd);
+		bg_team_join(bg_team_1, sd, true);
+	}
+
+	for (const auto &sd : queue->teamb_members) {
+		sd->bg_queue = nullptr;
+		sd->bg_queue_accept_state = false;
+		clif_bg_queue_entry_init(sd);
+		bg_team_join(bg_team_2, sd, true);
+	}
+
+	mapreg_setreg(add_str(queue->map->team1.bg_id_var.c_str()), bg_team_1);
+	mapreg_setreg(add_str(queue->map->team2.bg_id_var.c_str()), bg_team_2);
+	npc_event_do(queue->map->bgcallscript.c_str());
+	queue->teama_members.clear();
+	queue->teamb_members.clear();
+	queue->teama_members.shrink_to_fit();
+	queue->teamb_members.shrink_to_fit();
+
+	auto queue_it = bg_queues.begin();
+
+	while (queue_it != bg_queues.end()) {
+		if (*queue_it == queue)
+			queue_it = bg_queues.erase(queue_it);
+	}
+
+	return;
+}
+
+/**
+ * Initialize the Battleground data
+ */
 void do_init_battleground(void)
 {
-	bg_team_db = idb_alloc(DB_OPT_RELEASE_DATA);
+	if (battle_config.feature_bgqueue)
+		battleground_db.load();
+
 	add_timer_func_list(bg_send_xy_timer, "bg_send_xy_timer");
+	add_timer_func_list(bg_on_ready_loopback, "bg_on_ready_loopback");
+	add_timer_func_list(bg_on_ready_expire, "bg_on_ready_expire");
+	add_timer_func_list(bg_on_ready_start, "bg_on_ready_start");
 	add_timer_interval(gettick() + battle_config.bg_update_interval, bg_send_xy_timer, 0, 0, battle_config.bg_update_interval);
 }
 
+/**
+ * Clear the Battleground data from memory
+ */
 void do_final_battleground(void)
 {
-	bg_team_db->destroy(bg_team_db, NULL);
 }

+ 122 - 23
src/map/battleground.hpp

@@ -4,42 +4,141 @@
 #ifndef BATTLEGROUND_HPP
 #define BATTLEGROUND_HPP
 
+#include <memory>
+#include <string>
+#include <vector>
+
 #include "../common/cbasetypes.hpp"
+#include "../common/database.hpp"
 #include "../common/mmo.hpp" // struct party
 
 #define MAX_BG_MEMBERS 30
 
-struct battleground_member_data {
+struct s_battleground_member_data {
 	unsigned short x, y;
 	struct map_session_data *sd;
 	unsigned afk : 1;
+	struct point entry_point; ///< Battleground queue entry point
 };
 
-struct battleground_data {
-	unsigned int bg_id;
-	unsigned char count;
-	struct battleground_member_data members[MAX_BG_MEMBERS];
-	// BG Cementery
-	unsigned short mapindex, x, y;
-	// Logout Event
-	char logout_event[EVENT_NAME_LENGTH];
-	char die_event[EVENT_NAME_LENGTH];
+struct s_battleground_data {
+	int id; ///< Battleground ID
+	std::vector<s_battleground_member_data> members; ///< List of players in battleground
+	struct point cemetery; ///< Respawn point for players who die
+	std::string logout_event; ///< NPC Event to call on log out events
+	std::string die_event; ///< NPC Event to call on death events
 };
 
-void do_init_battleground(void);
-void do_final_battleground(void);
+struct s_battleground_team {
+	int16 warp_x, warp_y; ///< Team respawn coordinates
+	std::string quit_event, ///< Team NPC Event to call on log out events
+		death_event, ///< Team NPC Event to call on death events
+		bg_id_var; ///< Team NPC variable name
+};
+
+struct s_battleground_map {
+	int id; ///< Battleground ID
+	int16 mapid; ///< ID of the map
+	s_battleground_team team1, team2; ///< Team data
+	std::string bgcallscript; ///< Script to be called when players join the battleground
+	bool isReserved; ///< Reserve BG maps that are used so that the system won't create multiple BG instances on the same map
+};
+
+/// Battlegrounds client interface queue system [MasterOfMuppets]
+struct s_battleground_queue {
+	int id; ///< Battlegrounds database ID
+	std::vector<map_session_data *> teama_members; ///< List of members on team A
+	std::vector<map_session_data *> teamb_members; ///< List of members on team B
+	int required_players; ///< Amount of players required on each side to start
+	int max_players; ///< Maximum amount of players on each side
+	int accepted_players; ///< Amount of players who accepted the offer to enter the battleground
+	bool in_ready_state; ///< Is this BG queue waiting for players to enter the BG?
+	int tid_expire; ///< Timer ID associated with the time out at the ready to enter window
+	int tid_start; ///< Timer ID associated with the start delay
+	int tid_requeue; ///< Timer ID associated with requeuing this group if all BG maps are reserved
+	s_battleground_map *map; ///< Map this BG queue has been assigned to
+};
+
+struct s_battleground_type {
+	int id; ///< Battlegrounds database ID
+	std::string name; ///< Name of the battleground type
+	int required_players; ///< Amount of players required on each side to start
+	int max_players; ///< Maximum amount of players on each side
+	int min_lvl; ///< Minimum level to participate in this battleground type
+	int max_lvl; ///< Maximum level to participate in this battleground type
+	std::vector<s_battleground_map> maps; ///< List of battleground locations
+	uint32 deserter_time; ///< Amount of time a player is marked deserter (seconds)
+	uint32 start_delay; ///< Amount of time before the start message is sent to players (seconds)
+};
+
+/// Enum of responses when applying for a Battleground
+enum e_bg_queue_apply_ack : uint16 {
+	BG_APPLY_NONE = 0,
+	BG_APPLY_ACCEPT, ///< Accept
+	BG_APPLY_QUEUE_FINISHED, ///< Queuing has finished
+	BG_APPLY_INVALID_NAME, ///< Invalid name of Battleground
+	BG_APPLY_INVALID_APP, ///< Invalid application
+	BG_APPLY_PLAYER_COUNT, ///< Too many players in party/guild
+	BG_APPLY_PLAYER_LEVEL, ///< Level too low/high
+	BG_APPLY_DUPLICATE, ///< Duplicate application
+	BG_APPLY_RECONNECT, ///< Reconnect then apply
+	BG_APPLY_PARTYGUILD_LEADER, ///< Only party/guild leader can apply
+	BG_APPLY_PLAYER_CLASS, ///< Your class can't apply
+};
 
-struct battleground_data* bg_team_search(int bg_id);
-int bg_send_dot_remove(struct map_session_data *sd);
+/// Enum of script command bg_info types
+enum e_bg_info : uint16 {
+	BG_INFO_ID = 0,
+	BG_INFO_REQUIRED_PLAYERS,
+	BG_INFO_MAX_PLAYERS,
+	BG_INFO_MIN_LEVEL,
+	BG_INFO_MAX_LEVEL,
+	BG_INFO_MAPS,
+	BG_INFO_DESERTER_TIME,
+};
+
+class BattlegroundDatabase : public TypesafeYamlDatabase<uint32, s_battleground_type> {
+public:
+	BattlegroundDatabase() : TypesafeYamlDatabase("BATTLEGROUND_DB", 1) {
+
+	}
+
+	const std::string getDefaultLocation();
+	uint64 parseBodyNode(const YAML::Node& node);
+};
+
+extern BattlegroundDatabase battleground_db;
+extern std::unordered_map<int, std::shared_ptr<s_battleground_data>> bg_team_db;
+
+std::shared_ptr<s_battleground_type> bg_search_name(const char *name);
+void bg_send_dot_remove(struct map_session_data *sd);
 int bg_team_get_id(struct block_list *bl);
-struct map_session_data* bg_getavailablesd(struct battleground_data *bg);
-
-int bg_create(unsigned short mapindex, short rx, short ry, const char *ev, const char *dev);
-int bg_team_join(int bg_id, struct map_session_data *sd);
-int bg_team_delete(int bg_id);
-int bg_team_leave(struct map_session_data *sd, int flag);
-int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y);
-int bg_member_respawn(struct map_session_data *sd);
-int bg_send_message(struct map_session_data *sd, const char *mes, int len);
+struct map_session_data *bg_getavailablesd(s_battleground_data *bg);
+
+bool bg_queue_reservation(const char *name, bool state);
+#define bg_queue_reserve(name) (bg_queue_reservation(name, true))
+#define bg_queue_unbook(name) (bg_queue_reservation(name, false))
+
+int bg_create(uint16 mapindex, s_battleground_team* team);
+bool bg_team_join(int bg_id, struct map_session_data *sd, bool is_queue);
+bool bg_team_delete(int bg_id);
+int bg_team_leave(struct map_session_data *sd, bool quit, bool deserter);
+bool bg_team_warp(int bg_id, unsigned short mapindex, short x, short y);
+bool bg_player_is_in_bg_map(struct map_session_data *sd);
+bool bg_queue_check_joinable(std::shared_ptr<s_battleground_type> bg, struct map_session_data *sd, const char *name);
+std::shared_ptr<s_battleground_queue> bg_queue_create(int bg_id, int req_players);
+e_bg_queue_apply_ack bg_queue_join(const char *name, struct map_session_data *sd);
+e_bg_queue_apply_ack bg_queue_join_party(const char *name, struct map_session_data *sd);
+e_bg_queue_apply_ack bg_queue_join_guild(const char *name, struct map_session_data *sd);
+e_bg_queue_apply_ack bg_queue_join_multi(const char *name, struct map_session_data *sd, std::vector<map_session_data *> list);
+bool bg_queue_leave(struct map_session_data *sd);
+bool bg_queue_on_ready(const char *name, std::shared_ptr<s_battleground_queue> queue);
+void bg_queue_on_accept_invite(std::shared_ptr<s_battleground_queue> queue, struct map_session_data *sd);
+void bg_queue_start_battleground(std::shared_ptr<s_battleground_queue> queue);
+bool bg_member_respawn(struct map_session_data *sd);
+void bg_send_message(struct map_session_data *sd, const char *mes, int len);
+
+void do_init_battleground(void);
+void do_final_battleground(void);
 
 #endif /* BATTLEGROUND_HPP */

+ 202 - 4
src/map/clif.cpp

@@ -20,6 +20,7 @@
 #include "../common/socket.hpp"
 #include "../common/strlib.hpp"
 #include "../common/timer.hpp"
+#include "../common/utilities.hpp"
 #include "../common/utils.hpp"
 
 #include "achievement.hpp"
@@ -57,6 +58,8 @@
 #include "unit.hpp"
 #include "vending.hpp"
 
+using namespace rathena;
+
 static inline uint32 client_tick( t_tick tick ){
 	return (uint32)tick;
 }
@@ -391,7 +394,7 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
 	struct map_session_data *sd, *tsd;
 	struct party_data *p = NULL;
 	struct guild *g = NULL;
-	struct battleground_data *bg = NULL;
+	std::shared_ptr<s_battleground_data> bg;
 	int x0 = 0, x1 = 0, y0 = 0, y1 = 0, fd;
 	struct s_mapiterator* iter;
 
@@ -603,9 +606,9 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target
 	case BG_SAMEMAP_WOS:
 	case BG:
 	case BG_WOS:
-		if( sd && sd->bg_id && (bg = bg_team_search(sd->bg_id)) != NULL )
+		if( sd && sd->bg_id && (bg = util::umap_find(bg_team_db, sd->bg_id)))
 		{
-			for( i = 0; i < MAX_BG_MEMBERS; i++ )
+			for( i = 0; i < bg->members.size(); i++ )
 			{
 				if( (sd = bg->members[i].sd) == NULL || !(fd = sd->fd) )
 					continue;
@@ -17374,7 +17377,7 @@ void clif_bg_xy_remove(struct map_session_data *sd)
 
 /// Notifies clients of a battleground message.
 /// 02DC <packet len>.W <account id>.L <name>.24B <message>.?B (ZC_BATTLEFIELD_CHAT)
-void clif_bg_message( struct battleground_data *bg, int src_id, const char *name, const char *mes, int len ){
+void clif_bg_message( struct s_battleground_data *bg, int src_id, const char *name, const char *mes, int len ){
 	struct map_session_data *sd = bg_getavailablesd( bg );
 
 	if( sd == nullptr ){
@@ -17467,6 +17470,201 @@ void clif_sendbgemblem_single(int fd, struct map_session_data *sd)
 	WFIFOSET(fd,packet_len(0x2dd));
 }
 
+/// Battlegrounds queue incoming apply request from client.
+/// Queue types: 1 solo queue, 2 party queue, 4 guild queue.
+/// 0x8d7 <queue type>.W <battleground name>.24B (CZ_REQ_ENTRY_QUEUE_APPLY)
+void clif_parse_bg_queue_apply_request(int fd, struct map_session_data *sd)
+{
+	if (!battle_config.feature_bgqueue)
+		return;
+
+	nullpo_retv(sd);
+
+	short type = RFIFOW(fd,2);
+	char name[NAME_LENGTH];
+	e_bg_queue_apply_ack result;
+
+	safestrncpy(name, RFIFOCP(fd, 4), NAME_LENGTH);
+
+	if (sd->bg_queue) {
+		ShowWarning("clif_parse_bg_queue_apply_request: Received duplicate queue application: %d from player %s (AID:%d CID:%d).\n", type, sd->status.name, sd->status.account_id, sd->status.char_id);
+		clif_bg_queue_apply_result(BG_APPLY_DUPLICATE, name, sd); // Duplicate application warning
+		return;
+	} else if (type == 1) // Solo
+		result = bg_queue_join(name, sd);
+	else if (type == 2) // Party
+		result = bg_queue_join_party(name, sd);
+	else if (type == 4) // Guild
+		result = bg_queue_join_guild(name, sd);
+	else {
+		ShowWarning("clif_parse_bg_queue_apply_request: Received invalid queue type: %d from player %s (AID:%d CID:%d).\n", type, sd->status.name, sd->status.account_id, sd->status.char_id);
+		clif_bg_queue_apply_result(BG_APPLY_INVALID_APP, name, sd); // Someone sent an invalid queue type packet
+		return;
+	}
+
+	clif_bg_queue_apply_result(result, name, sd);
+	if (result == BG_APPLY_ACCEPT)
+		clif_bg_queue_apply_notify(name, sd);
+}
+
+/// Outgoing battlegrounds queue apply result.
+/// Result types: @see e_bg_queue_apply_ack
+/// 0x8d8 <result>.B <battleground name>.24B (ZC_ACK_ENTRY_QUEUE_APPLY)
+void clif_bg_queue_apply_result(e_bg_queue_apply_ack result, const char *name, struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	int fd = sd->fd;
+
+	WFIFOHEAD(fd, packet_len(0x8d8));
+	WFIFOW(fd,0) = 0x8d8;
+	WFIFOB(fd,2) = result;
+	safestrncpy(WFIFOCP(fd,3), name, NAME_LENGTH);
+	WFIFOSET(fd, packet_len(0x8d8));
+}
+
+/// Outgoing battlegrounds queue apply notification.
+/// Sends a notification at the start of the battlegrounds queue and is also used to update the queue number.
+/// 0x8d9 <battleground name>.24B <queue number>.L (ZC_NOTIFY_ENTRY_QUEUE_APPLY)
+void clif_bg_queue_apply_notify(const char *name, struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	std::shared_ptr<s_battleground_queue> queue = sd->bg_queue;
+
+	if (!queue) {
+		ShowError("clif_bg_queue_apply_notify: Player is not in a battleground queue.\n");
+		return;
+	}
+
+	int fd = sd->fd;
+
+	WFIFOHEAD(fd, packet_len(0x8d9));
+	WFIFOW(fd,0) = 0x8d9;
+	safestrncpy(WFIFOCP(fd,2), name, NAME_LENGTH);
+	WFIFOL(fd,2+NAME_LENGTH) = queue->teama_members.size() + queue->teamb_members.size();
+	WFIFOSET(fd, packet_len(0x8d9));
+}
+
+/// Battlegrounds queue outgoing cancel result.
+/// 0x8db <result>.B <battleground name>.24B (ZC_ACK_ENTRY_QUEUE_CANCEL)
+void clif_bg_queue_cancel_result(bool success, const char *name, struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	int fd = sd->fd;
+
+	WFIFOHEAD(fd, packet_len(0x8d8));
+	WFIFOW(fd,0) = 0x8db;
+	WFIFOB(fd,2) = success;
+	safestrncpy(WFIFOCP(fd,3), name, NAME_LENGTH);
+	WFIFOSET(fd, packet_len(0x8d8));
+}
+
+/// Battlegrounds queue incoming cancel request from client.
+/// 0x8da <battleground name>.24B (CZ_REQ_ENTRY_QUEUE_CANCEL)
+void clif_parse_bg_queue_cancel_request(int fd, struct map_session_data *sd)
+{
+	if (!battle_config.feature_bgqueue)
+		return;
+
+	nullpo_retv(sd);
+
+	bool success;
+
+	if (sd->bg_queue) {
+		if (sd->bg_queue->in_ready_state)
+			return; // Make the cancel button do nothing if the entry window is open. Otherwise it'll crash the game when you click on both the queue status and entry status window.
+		else
+			success = bg_queue_leave(sd);
+	} else {
+		ShowWarning("clif_parse_bg_queue_cancel_request: Player trying to request leaving non-existent queue with name: %s (AID:%d CID:%d).\n", sd->status.name, sd->status.account_id, sd->status.char_id);
+		success = false;
+	}
+
+	char name[NAME_LENGTH];
+
+	safestrncpy( name, RFIFOCP( fd, 2 ), NAME_LENGTH );
+
+	clif_bg_queue_cancel_result(success, name, sd);
+}
+
+/// Battleground is ready to be joined, send a window asking for players to accept or decline.
+/// 0x8df <battleground name>.24B <lobby name>.24B (ZC_NOTIFY_LOBBY_ADMISSION)
+void clif_bg_queue_lobby_notify(const char *name, struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	int fd = sd->fd;
+
+	WFIFOHEAD(fd, packet_len(0x8df));
+	WFIFOW(fd,0) = 0x8df;
+	safestrncpy(WFIFOCP(fd,2), name, NAME_LENGTH);
+	safestrncpy(WFIFOCP(fd,2+NAME_LENGTH), name, NAME_LENGTH);
+	WFIFOSET(fd, packet_len(0x8df));
+}
+
+/// Incoming packet from client telling server whether player wants to enter battleground or cancel.
+/// Result types: 1(Accept), 2(Decline).
+/// 0x8e0 <result>.B <battleground name>.24B <lobby name>.24B (CZ_REPLY_LOBBY_ADMISSION)
+void clif_parse_bg_queue_lobby_reply(int fd, struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	if(sd->bg_queue) {
+		uint8 result = RFIFOB(fd, 2);
+
+		if(result == 1) { // Accept
+			bg_queue_on_accept_invite(sd->bg_queue, sd);
+		} else if(result == 2) { // Decline
+			bg_queue_leave(sd);
+			clif_bg_queue_entry_init(sd);
+		}
+	}
+}
+
+/// Plays a gong sound, signaling that someone has accepted the invite to enter a battleground.
+/// 0x8e1 <result>.B <battleground name>.24B <lobby name>.24B (ZC_REPLY_ACK_LOBBY_ADMISSION)
+void clig_bg_queue_ack_lobby(bool result, const char *name, const char *lobbyname, struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	int fd = sd->fd;
+
+	WFIFOHEAD(fd, packet_len(0x8e1));
+	WFIFOW(fd,0) = 0x8e1;
+	WFIFOB(fd,2) = result;
+	safestrncpy(WFIFOCP(fd,3), name, NAME_LENGTH);
+	safestrncpy(WFIFOCP(fd,3+NAME_LENGTH), lobbyname, NAME_LENGTH);
+	WFIFOSET(fd, packet_len(0x8e1));
+}
+
+/// Battlegrounds queue incoming queue number request from client.
+/// 0x90a <battleground name>.24B (CZ_REQ_ENTRY_QUEUE_RANKING)
+void clif_parse_bg_queue_request_queue_number(int fd, struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	char name[NAME_LENGTH];
+
+	safestrncpy( name, RFIFOCP(fd, 2), NAME_LENGTH );
+
+	clif_bg_queue_apply_notify(name, sd);
+}
+
+/// Silently removes all the battlegrounds stuff client side so that you will open the first BG window when you press battle on the interface.
+/// Send this when a player joins a battleground so that it will remove all the queue stuff upon warping in.
+/// 0x90e (ZC_ENTRY_QUEUE_INIT)
+void clif_bg_queue_entry_init(struct map_session_data *sd)
+{
+	nullpo_retv(sd);
+
+	int fd = sd->fd;
+
+	WFIFOHEAD(fd, packet_len(0x90e));
+	WFIFOW(fd,0) = 0x90e;
+	WFIFOSET(fd, packet_len(0x90e));
+}
 
 /// Custom Fonts (ZC_NOTIFY_FONT).
 /// 02ef <account_id>.L <font id>.W

+ 10 - 2
src/map/clif.hpp

@@ -34,7 +34,7 @@ struct s_vending;
 struct party;
 struct party_data;
 struct guild;
-struct battleground_data;
+struct s_battleground_data;
 struct quest;
 struct party_booking_ad_info;
 struct sale_item_data;
@@ -42,6 +42,7 @@ struct mail_message;
 struct achievement;
 struct guild_log_entry;
 enum e_guild_storage_log : uint16;
+enum e_bg_queue_apply_ack : uint16;
 
 enum e_PacketDBVersion { // packet DB
 	MIN_PACKET_DB  = 0x064,
@@ -818,12 +819,19 @@ void clif_guild_xy_remove(struct map_session_data *sd);
 void clif_bg_hp(struct map_session_data *sd);
 void clif_bg_xy(struct map_session_data *sd);
 void clif_bg_xy_remove(struct map_session_data *sd);
-void clif_bg_message(struct battleground_data *bg, int src_id, const char *name, const char *mes, int len);
+void clif_bg_message(struct s_battleground_data *bg, int src_id, const char *name, const char *mes, int len);
 void clif_bg_updatescore(int16 m);
 void clif_bg_updatescore_single(struct map_session_data *sd);
 void clif_sendbgemblem_area(struct map_session_data *sd);
 void clif_sendbgemblem_single(int fd, struct map_session_data *sd);
 
+// Battleground Queue
+void clif_bg_queue_apply_result(e_bg_queue_apply_ack result, const char *name, struct map_session_data *sd);
+void clif_bg_queue_apply_notify(const char *name, struct map_session_data *sd);
+void clif_bg_queue_entry_init(struct map_session_data *sd);
+void clif_bg_queue_lobby_notify(const char *name, struct map_session_data *sd);
+void clig_bg_queue_ack_lobby(bool result, const char *name, const char *lobbyname, struct map_session_data *sd);
+
 // Instancing
 void clif_instance_create(unsigned short instance_id, int num);
 void clif_instance_changewait(unsigned short instance_id, int num);

+ 13 - 1
src/map/clif_packetdb.hpp

@@ -1968,7 +1968,19 @@
 	parseable_packet(0x08fb,6,NULL,2);
 	parseable_packet(0x0907,5,clif_parse_MoveItem,2,4);
 	packet(0x0908,5);
-	parseable_packet(0x08d7,28,NULL,2,4);
+	parseable_packet(0x08D7,28,clif_parse_bg_queue_apply_request,2,4);
+	packet(0x08D8,27);
+	packet(0x08D9,30);
+	parseable_packet(0x08DA,26,clif_parse_bg_queue_cancel_request,2);
+	packet(0x08DB,27);
+	packet(0x08DC,26);
+	parseable_packet(0x08DD,27,clif_parse_dull,2,3);
+	packet(0x08DE,27);
+	packet(0x08DF,50);
+	parseable_packet(0x08E0,51,clif_parse_bg_queue_lobby_reply,2,3,27);
+	packet(0x08E1,51);
+	parseable_packet(0x090A,26,clif_parse_bg_queue_request_queue_number,2);
+	packet(0x090E,2);
 	packet(0x0977,14); //Monster HP Bar
 	parseable_packet(0x0916,26,clif_parse_GuildInvite2,2);
 	parseable_packet(0x091d,41,clif_parse_PartyBookingRegisterReq,2,4,6);

+ 1 - 0
src/map/map-server.vcxproj

@@ -296,6 +296,7 @@
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\achievement_level_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\achievement_level_db.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\attendance.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\attendance.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\attr_fix.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\attr_fix.txt')" />
+    <Copy SourceFiles="$(SolutionDir)db\import-tmpl\battleground_db.yml" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\battleground_db.yml')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\castle_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\castle_db.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\const.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\const.txt')" />
     <Copy SourceFiles="$(SolutionDir)db\import-tmpl\create_arrow_db.txt" DestinationFolder="$(SolutionDir)db\import\" ContinueOnError="true" Condition="!Exists('$(SolutionDir)db\import\create_arrow_db.txt')" />

+ 6 - 3
src/map/map.cpp

@@ -2058,8 +2058,11 @@ int map_quit(struct map_session_data *sd) {
 	if (sd->npc_id)
 		npc_event_dequeue(sd);
 
-	if( sd->bg_id )
-		bg_team_leave(sd,1);
+	if (sd->bg_id)
+		bg_team_leave(sd, true, true);
+
+	if (sd->bg_queue != nullptr)
+		bg_queue_leave(sd);
 
 	if( sd->status.clan_id )
 		clan_member_left(sd);
@@ -5242,9 +5245,9 @@ int do_init(int argc, char *argv[])
 	do_init_elemental();
 	do_init_quest();
 	do_init_achievement();
+	do_init_battleground();
 	do_init_npc();
 	do_init_unit();
-	do_init_battleground();
 	do_init_duel();
 	do_init_vending();
 	do_init_buyingstore();

+ 1 - 1
src/map/mob.hpp

@@ -219,7 +219,7 @@ struct mob_data {
 	int level;
 	int target_id,attacked_id,norm_attacked_id;
 	int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs)
-	unsigned int bg_id; // BattleGround System
+	int bg_id; // BattleGround System
 
 	t_tick next_walktime,last_thinktime,last_linktime,last_pcneartime,dmgtick;
 	short move_fail_count;

+ 14 - 4
src/map/pc.cpp

@@ -1529,6 +1529,10 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
 	sd->bonus_script.head = NULL;
 	sd->bonus_script.count = 0;
 
+	// Initialize BG queue pointer
+	sd->bg_queue = nullptr;
+	sd->bg_queue_accept_state = false;
+
 #if PACKETVER >= 20150513
 	sd->hatEffectIDs = NULL;
 	sd->hatEffectCount = 0;
@@ -5758,6 +5762,9 @@ enum e_setpos pc_setpos(struct map_session_data* sd, unsigned short mapindex, in
 				instance_addusers(new_map_instance_id);
 		}
 
+		if (sd->bg_id && !mapdata->flag[MF_BATTLEGROUND]) // Moving to a map that isn't a Battlegrounds
+			bg_team_leave(sd, false, true);
+
 		sd->state.pmap = sd->bl.m;
 		if (sd->sc.count) { // Cancel some map related stuff.
 			if (sd->sc.data[SC_JAILED])
@@ -8306,10 +8313,13 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
 		return 1|8;
 	}
 	else if( sd->bg_id ) {
-		struct battleground_data *bg = bg_team_search(sd->bg_id);
-		if( bg && bg->mapindex > 0 ) { // Respawn by BG
-			sd->respawn_tid = add_timer(tick+1000, pc_respawn_timer, sd->bl.id, 0);
-			return 1|8;
+		std::shared_ptr<s_battleground_data> bg = util::umap_find(bg_team_db, sd->bg_id);
+
+		if (bg) {
+			if (bg->cemetery.map > 0) { // Respawn by BG
+				sd->respawn_tid = add_timer(tick + 1000, pc_respawn_timer, sd->bl.id, 0);
+				return 1|8;
+			}
 		}
 	}
 

+ 7 - 1
src/map/pc.hpp

@@ -4,12 +4,14 @@
 #ifndef PC_HPP
 #define PC_HPP
 
+#include <memory>
 #include <vector>
 
 #include "../common/mmo.hpp" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus
 #include "../common/strlib.hpp"// StringBuf
 #include "../common/timer.hpp"
 
+#include "battleground.hpp"
 #include "buyingstore.hpp" // struct s_buyingstore
 #include "clif.hpp" //e_wip_block
 #include "itemdb.hpp" // MAX_ITEMGROUP
@@ -623,6 +625,10 @@ struct map_session_data {
 		bool changed; // if true, should sync with charserver on next mailbox request
 	} mail;
 
+	// Battlegrounds queue system [MasterOfMuppets]
+	std::shared_ptr<s_battleground_queue> bg_queue;
+	bool bg_queue_accept_state; // Set this to true when someone has accepted the invite to join BGs
+
 	//Quest log system
 	int num_quests;          ///< Number of entries in quest_log
 	int avail_quests;        ///< Number of Q_ACTIVE and Q_INACTIVE entries in quest log (index of the first Q_COMPLETE entry)
@@ -651,7 +657,7 @@ struct map_session_data {
 	int debug_line;
 	const char* debug_func;
 
-	unsigned int bg_id;
+	int bg_id;
 
 #ifdef SECURE_NPCTIMEOUT
 	/**

+ 159 - 76
src/map/script.cpp

@@ -19662,9 +19662,10 @@ BUILDIN_FUNC(waitingroom2bg)
 {
 	struct npc_data *nd;
 	struct chat_data *cd;
-	const char *map_name, *ev = "", *dev = "";
-	int x, y, mapindex = 0, bg_id;
+	const char *map_name;
+	int mapindex = 0, bg_id;
 	unsigned char i,c=0;
+	struct s_battleground_team team;
 
 	if( script_hasdata(st,7) )
 		nd = npc_name2id(script_getstr(st,7));
@@ -19684,17 +19685,20 @@ BUILDIN_FUNC(waitingroom2bg)
 		return SCRIPT_CMD_SUCCESS;
 	}
 
-	x = script_getnum(st,3);
-	y = script_getnum(st,4);
-	if(script_hasdata(st,5))
-		ev = script_getstr(st,5); // Logout Event
-	if(script_hasdata(st,6))
-		dev = script_getstr(st,6); // Die Event
-
-	check_event(st, ev);
-	check_event(st, dev);
+	team.warp_x = script_getnum(st,3);
+	team.warp_y = script_getnum(st,4);
+	if (script_hasdata(st,5)) {
+		team.quit_event = script_getstr(st,5); // Logout Event
+		check_event(st, team.quit_event.c_str());
+	} else
+		team.quit_event = "";
+	if (script_hasdata(st,6)) {
+		team.death_event = script_getstr(st,6); // Die Event
+		check_event(st, team.death_event.c_str());
+	} else
+		team.death_event = "";
 
-	if( (bg_id = bg_create(mapindex, x, y, ev, dev)) == 0 )
+	if( (bg_id = bg_create(mapindex, &team)) == 0 )
 	{ // Creation failed
 		script_pushint(st,0);
 		return SCRIPT_CMD_SUCCESS;
@@ -19702,7 +19706,7 @@ BUILDIN_FUNC(waitingroom2bg)
 
 	for (i = 0; i < cd->users; i++) { // Only add those who are in the chat room
 		struct map_session_data *sd;
-		if( (sd = cd->usersd[i]) != NULL && bg_team_join(bg_id, sd) ){
+		if( (sd = cd->usersd[i]) != NULL && bg_team_join(bg_id, sd, false) ){
 			mapreg_setreg(reference_uid(add_str("$@arenamembers"), c), sd->bl.id);
 			++c;
 		}
@@ -19719,11 +19723,10 @@ BUILDIN_FUNC(waitingroom2bg_single)
 	struct npc_data *nd;
 	struct chat_data *cd;
 	struct map_session_data *sd;
-	struct battleground_data *bg;
-	int x, y, mapindex, bg_id;
+	int x, y, mapindex, bg_id = script_getnum(st,2);
+	std::shared_ptr<s_battleground_data> bg = util::umap_find(bg_team_db, bg_id);
 
-	bg_id = script_getnum(st,2);
-	if ((bg = bg_team_search(bg_id)) == NULL) {
+	if (!bg) {
 		script_pushint(st, false);
 		return SCRIPT_CMD_SUCCESS;
 	}
@@ -19737,9 +19740,9 @@ BUILDIN_FUNC(waitingroom2bg_single)
 		y = script_getnum(st, 5);
 	}
 	else {
-		mapindex = bg->mapindex;
-		x = bg->x;
-		y = bg->y;
+		mapindex = bg->cemetery.map;
+		x = bg->cemetery.x;
+		y = bg->cemetery.y;
 	}
 
 	nd = npc_name2id(script_getstr(st,6));
@@ -19750,7 +19753,7 @@ BUILDIN_FUNC(waitingroom2bg_single)
 	if( (sd = cd->usersd[0]) == NULL )
 		return SCRIPT_CMD_SUCCESS;
 
-	if( bg_team_join(bg_id, sd) && pc_setpos(sd, mapindex, x, y, CLR_TELEPORT) == SETPOS_OK)
+	if( bg_team_join(bg_id, sd, false) && pc_setpos(sd, mapindex, x, y, CLR_TELEPORT) == SETPOS_OK)
 	{
 		script_pushint(st, true);
 	}
@@ -19765,8 +19768,9 @@ BUILDIN_FUNC(waitingroom2bg_single)
 /// *bg_create("<map name>",<x>,<y>{,"<On Quit Event>","<On Death Event>"});
 /// @author [secretdataz]
 BUILDIN_FUNC(bg_create) {
-	const char *map_name, *ev = "", *dev = "";
-	int x, y, mapindex = 0;
+	const char *map_name;
+	int mapindex = 0;
+	struct s_battleground_team team;
 
 	map_name = script_getstr(st, 2);
 	if (strcmp(map_name, "-") != 0 && (mapindex = mapindex_name2id(map_name)) == 0)
@@ -19775,17 +19779,20 @@ BUILDIN_FUNC(bg_create) {
 		return SCRIPT_CMD_SUCCESS;
 	}
 
-	x = script_getnum(st, 3);
-	y = script_getnum(st, 4);
-	if(script_hasdata(st, 5))
-		ev = script_getstr(st, 5); // Logout Event
-	if(script_hasdata(st, 6))
-		dev = script_getstr(st, 6); // Die Event
-
-	check_event(st, ev);
-	check_event(st, dev);
+	team.warp_x = script_getnum(st,3);
+	team.warp_y = script_getnum(st,4);
+	if (script_hasdata(st,5)) {
+		team.quit_event = script_getstr(st,5); // Logout Event
+		check_event(st, team.quit_event.c_str());
+	} else
+		team.quit_event = "";
+	if (script_hasdata(st,6)) {
+		team.death_event = script_getstr(st,6); // Die Event
+		check_event(st, team.death_event.c_str());
+	} else
+		team.death_event = "";
 
-	script_pushint(st, bg_create(mapindex, x, y, ev, dev));
+	script_pushint(st, bg_create(mapindex, &team));
 	return SCRIPT_CMD_SUCCESS;
 }
 
@@ -19797,11 +19804,10 @@ BUILDIN_FUNC(bg_create) {
 BUILDIN_FUNC(bg_join) {
 	const char* map_name;
 	struct map_session_data *sd;
-	struct battleground_data *bg;
-	int x, y, bg_id, mapindex;
+	int x, y, mapindex, bg_id = script_getnum(st, 2);
+	std::shared_ptr<s_battleground_data> bg = util::umap_find(bg_team_db, bg_id);
 
-	bg_id = script_getnum(st, 2);
-	if ((bg = bg_team_search(bg_id)) == NULL) {
+	if (!bg) {
 		script_pushint(st, false);
 		return SCRIPT_CMD_SUCCESS;
 	}
@@ -19814,9 +19820,9 @@ BUILDIN_FUNC(bg_join) {
 		x = script_getnum(st, 4);
 		y = script_getnum(st, 5);
 	} else {
-		mapindex = bg->mapindex;
-		x = bg->x;
-		y = bg->y;
+		mapindex = bg->cemetery.map;
+		x = bg->cemetery.x;
+		y = bg->cemetery.y;
 	}
 
 	if (!script_charid2sd(6, sd)) {
@@ -19824,7 +19830,7 @@ BUILDIN_FUNC(bg_join) {
 		return SCRIPT_CMD_FAILURE;
 	}
 
-	if (bg_team_join(bg_id, sd) && pc_setpos(sd, mapindex, x, y, CLR_TELEPORT) == SETPOS_OK)
+	if (bg_team_join(bg_id, sd, false) && pc_setpos(sd, mapindex, x, y, CLR_TELEPORT) == SETPOS_OK)
 	{
 		script_pushint(st, true);
 	}
@@ -19836,15 +19842,14 @@ BUILDIN_FUNC(bg_join) {
 
 BUILDIN_FUNC(bg_team_setxy)
 {
-	struct battleground_data *bg;
-	int bg_id;
+	int bg_id = script_getnum(st,2);
+	std::shared_ptr<s_battleground_data> bg = util::umap_find(bg_team_db, bg_id);
 
-	bg_id = script_getnum(st,2);
-	if( (bg = bg_team_search(bg_id)) == NULL )
-		return SCRIPT_CMD_SUCCESS;
+	if (bg) {
+		bg->cemetery.x = script_getnum(st, 3);
+		bg->cemetery.y = script_getnum(st, 4);
+	}
 
-	bg->x = script_getnum(st,3);
-	bg->y = script_getnum(st,4);
 	return SCRIPT_CMD_SUCCESS;
 }
 
@@ -19903,10 +19908,15 @@ BUILDIN_FUNC(bg_monster_set_team)
 BUILDIN_FUNC(bg_leave)
 {
 	struct map_session_data *sd = NULL;
+	bool deserter = false;
+
 	if( !script_charid2sd(2,sd) || !sd->bg_id )
 		return SCRIPT_CMD_SUCCESS;
 
-	bg_team_leave(sd,0);
+	if (!strcmp(script_getfuncname(st), "bg_desert"))
+		deserter = true;
+
+	bg_team_leave(sd, false, deserter);
 	return SCRIPT_CMD_SUCCESS;
 }
 
@@ -19919,17 +19929,13 @@ BUILDIN_FUNC(bg_destroy)
 
 BUILDIN_FUNC(bg_getareausers)
 {
-	const char *str;
+	const char *str = script_getstr(st, 3);
 	int16 m, x0, y0, x1, y1;
-	int bg_id;
+	int bg_id = script_getnum(st, 2);
 	int i = 0, c = 0;
-	struct battleground_data *bg = NULL;
-
-	bg_id = script_getnum(st,2);
-	str = script_getstr(st,3);
+	std::shared_ptr<s_battleground_data> bg = util::umap_find(bg_team_db, bg_id);
 
-	if( (bg = bg_team_search(bg_id)) == NULL || (m = map_mapname2mapid(str)) < 0 )
-	{
+	if (!bg || (m = map_mapname2mapid(str)) < 0) {
 		script_pushint(st,0);
 		return SCRIPT_CMD_SUCCESS;
 	}
@@ -19939,7 +19945,7 @@ BUILDIN_FUNC(bg_getareausers)
 	x1 = script_getnum(st,6);
 	y1 = script_getnum(st,7);
 
-	for( i = 0; i < MAX_BG_MEMBERS; i++ )
+	for( i = 0; i < bg->members.size(); i++ )
 	{
 		struct map_session_data *sd;
 		if( (sd = bg->members[i].sd) == NULL )
@@ -19973,29 +19979,102 @@ BUILDIN_FUNC(bg_updatescore)
 
 BUILDIN_FUNC(bg_get_data)
 {
-	struct battleground_data *bg = bg_team_search( script_getnum(st, 2) );
+	int bg_id = script_getnum(st,2), type = script_getnum(st,3), i;
+	std::shared_ptr<s_battleground_data> bg = util::umap_find(bg_team_db, bg_id);
 
-	if (bg == NULL) {
+	if (bg) {
+		switch (type) {
+		case 0:
+			script_pushint(st, bg->members.size());
+			break;
+		case 1:
+			for (i = 0; bg->members[i].sd != NULL; i++)
+				mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), bg->members[i].sd->bl.id);
+			mapreg_setreg(add_str("$@arenamemberscount"), i);
+			script_pushint(st, i);
+			break;
+		default:
+			ShowError("script:bg_get_data: unknown data identifier %d\n", type);
+			break;
+		}
+	} else
 		script_pushint(st, 0);
-		return SCRIPT_CMD_SUCCESS;
+
+	return SCRIPT_CMD_SUCCESS;
+}
+
+/**
+ * Reserves a slot for the given Battleground.
+ * bg_reserve(<"bg_name">);
+ */
+BUILDIN_FUNC(bg_reserve)
+{
+	const char *str = script_getstr(st, 2);
+
+	if (!bg_queue_reserve(str))
+		ShowWarning("buildin_bg_reserve: Could not reserve battleground with name %s\n", str);
+	return SCRIPT_CMD_SUCCESS;
+}
+
+/**
+ * Removes a spot for the given Battleground.
+ * bg_unbook(<"bg_name">);
+ */
+BUILDIN_FUNC(bg_unbook)
+{
+	const char *str = script_getstr(st, 2);
+
+	if (!bg_queue_unbook(str))
+		ShowWarning("buildin_bg_unbook: Could not unreserve battleground with name %s\n", str);
+	return SCRIPT_CMD_SUCCESS;
+}
+
+/**
+ * Gets battleground database information.
+ * bg_info("<battleground name>", <type>);
+ */
+BUILDIN_FUNC(bg_info)
+{
+	std::shared_ptr<s_battleground_type> bg = bg_search_name(script_getstr(st, 2));
+
+	if (!bg) {
+		ShowError("bg_info: Invalid Battleground name %s.\n", script_getstr(st, 2));
+		return SCRIPT_CMD_FAILURE;
 	}
-	int i, j, type = script_getnum(st, 3);
 
-	switch( type ) {
-	case 0:
-		script_pushint(st, bg->count);
-		break;
-	case 1:
-		for (i = 0, j = 0; i < ARRAYLENGTH(bg->members); i++) {
-			if (bg->members[i].sd != NULL)
-				mapreg_setreg(reference_uid(add_str("$@arenamembers"), j++), bg->members[i].sd->bl.id);
+	int type = script_getnum(st, 3);
+
+	switch (type) {
+		case BG_INFO_ID:
+			script_pushint(st, bg->id);
+			break;
+		case BG_INFO_REQUIRED_PLAYERS:
+			script_pushint(st, bg->required_players);
+			break;
+		case BG_INFO_MAX_PLAYERS:
+			script_pushint(st, bg->max_players);
+			break;
+		case BG_INFO_MIN_LEVEL:
+			script_pushint(st, bg->min_lvl);
+			break;
+		case BG_INFO_MAX_LEVEL:
+			script_pushint(st, bg->max_lvl);
+			break;
+		case BG_INFO_MAPS: {
+			size_t i;
+
+			for (i = 0; i < bg->maps.size(); i++)
+				setd_sub_str(st, nullptr, ".@bgmaps$", i, map_mapid2mapname(bg->maps[i].mapid), nullptr);
+			setd_sub_num(st, nullptr, ".@bgmapscount", 0, i, nullptr);
+			script_pushint(st, i);
+			break;
 		}
-		mapreg_setreg(add_str("$@arenamemberscount"), j);
-		script_pushint(st, j);
-		break;
-	default:
-		ShowError("script:bg_get_data: unknown data identifier %d\n", type);
-		break;
+		case BG_INFO_DESERTER_TIME:
+			script_pushint(st, bg->deserter_time);
+			break;
+		default:
+			ShowError("bg_info: Unknown battleground info type %d given.\n", type);
+			return SCRIPT_CMD_FAILURE;
 	}
 
 	return SCRIPT_CMD_SUCCESS;
@@ -25028,6 +25107,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(bg_monster,"isiisi?"),
 	BUILDIN_DEF(bg_monster_set_team,"ii"),
 	BUILDIN_DEF(bg_leave,"?"),
+	BUILDIN_DEF2(bg_leave,"bg_desert","?"),
 	BUILDIN_DEF(bg_destroy,"i"),
 	BUILDIN_DEF(areapercentheal,"siiiiii"),
 	BUILDIN_DEF(bg_get_data,"ii"),
@@ -25035,6 +25115,9 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(bg_updatescore,"sii"),
 	BUILDIN_DEF(bg_join,"i????"),
 	BUILDIN_DEF(bg_create,"sii??"),
+	BUILDIN_DEF(bg_reserve,"s"),
+	BUILDIN_DEF(bg_unbook,"s"),
+	BUILDIN_DEF(bg_info,"si"),
 
 	// Instancing
 	BUILDIN_DEF(instance_create,"s??"),

+ 11 - 0
src/map/script_constants.hpp

@@ -1542,6 +1542,8 @@
 	export_constant(SC_ANCILLA);
 	export_constant(SC_EARTHSHAKER);
 	export_constant(SC_WEAPONBLOCK_ON);
+	export_constant(SC_ENTRY_QUEUE_APPLY_DELAY);
+	export_constant(SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT);
 #ifdef RENEWAL
 	export_constant(SC_EXTREMITYFIST2);
 #endif
@@ -7689,6 +7691,15 @@
 	export_constant(UNT_GD_SOULCOLD);
 	export_constant(UNT_GD_HAWKEYES);
 
+	/* battleground info types */
+	export_constant(BG_INFO_ID);
+	export_constant(BG_INFO_REQUIRED_PLAYERS);
+	export_constant(BG_INFO_MAX_PLAYERS);
+	export_constant(BG_INFO_MIN_LEVEL);
+	export_constant(BG_INFO_MAX_LEVEL);
+	export_constant(BG_INFO_MAPS);
+	export_constant(BG_INFO_DESERTER_TIME);
+
 	#undef export_constant
 	#undef export_constant2
 	#undef export_parameter

+ 3 - 0
src/map/skill.cpp

@@ -2027,6 +2027,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 					case SC_WEDDING:		case SC_XMAS:			case SC_SUMMER:
 					case SC_DRESSUP:		case SC_HANBOK:			case SC_OKTOBERFEST:
 					case SC_LHZ_DUN_N1:		case SC_LHZ_DUN_N2:			case SC_LHZ_DUN_N3:			case SC_LHZ_DUN_N4:
+					case SC_ENTRY_QUEUE_APPLY_DELAY:	case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
 						continue;
 					case SC_WHISTLE:		case SC_ASSNCROS:		case SC_POEMBRAGI:
 					case SC_APPLEIDUN:		case SC_HUMMING:		case SC_DONTFORGETME:
@@ -7997,6 +7998,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 					case SC_SPRITEMABLE:		case SC_BITESCAR:	case SC_CRUSHSTRIKE:
 					case SC_QUEST_BUFF1:	case SC_QUEST_BUFF2:	case SC_QUEST_BUFF3:
 					case SC_ARMOR_ELEMENT_EARTH:	case SC_ARMOR_ELEMENT_FIRE:	case SC_ARMOR_ELEMENT_WIND:
+					case SC_ENTRY_QUEUE_APPLY_DELAY:	case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
 					// Clans
 					case SC_CLAN_INFO:
 					case SC_SWORDCLAN:
@@ -9455,6 +9457,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 					case SC_WEDDING:		case SC_XMAS:			case SC_SUMMER:
 					case SC_DRESSUP:		case SC_HANBOK:			case SC_OKTOBERFEST:
 					case SC_LHZ_DUN_N1:		case SC_LHZ_DUN_N2:			case SC_LHZ_DUN_N3:			case SC_LHZ_DUN_N4:
+					case SC_ENTRY_QUEUE_APPLY_DELAY:	case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
 					continue;
 				case SC_ASSUMPTIO:
 					if( bl->type == BL_MOB )

+ 20 - 4
src/map/status.cpp

@@ -17,6 +17,7 @@
 #include "../common/showmsg.hpp"
 #include "../common/strlib.hpp"
 #include "../common/timer.hpp"
+#include "../common/utilities.hpp"
 #include "../common/utils.hpp"
 
 #include "battle.hpp"
@@ -36,6 +37,8 @@
 #include "pet.hpp"
 #include "script.hpp"
 
+using namespace rathena;
+
 // Regen related flags.
 enum e_regen {
 	RGN_NONE = 0x00,
@@ -1179,6 +1182,10 @@ void initChangeTables(void)
 	StatusIconChangeTable[SC_ANCILLA] = EFST_ANCILLA;
 	StatusIconChangeTable[SC_WEAPONBLOCK_ON] = EFST_WEAPONBLOCK_ON;
 
+	// Battleground Queue
+	StatusIconChangeTable[SC_ENTRY_QUEUE_APPLY_DELAY] = EFST_ENTRY_QUEUE_APPLY_DELAY;
+	StatusIconChangeTable[SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT] = EFST_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT;
+
 	/* Other SC which are not necessarily associated to skills */
 	StatusChangeFlagTable[SC_ASPDPOTION0] |= SCB_ASPD;
 	StatusChangeFlagTable[SC_ASPDPOTION1] |= SCB_ASPD;
@@ -1333,6 +1340,10 @@ void initChangeTables(void)
 	StatusChangeFlagTable[SC_GLASTHEIM_ITEMDEF] |= SCB_DEF|SCB_MDEF;
 	StatusChangeFlagTable[SC_GLASTHEIM_HPSP] |= SCB_MAXHP|SCB_MAXSP;
 
+	// Battleground Queue
+	StatusChangeFlagTable[SC_ENTRY_QUEUE_APPLY_DELAY] |= SCB_NONE;
+	StatusChangeFlagTable[SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT] |= SCB_NONE;
+
 	// Summoner
 	StatusChangeFlagTable[SC_DORAM_WALKSPEED] |= SCB_SPEED;
 	StatusChangeFlagTable[SC_DORAM_MATK] |= SCB_MATK;
@@ -1864,14 +1875,15 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
 	}
 
 	// Always run NPC scripts for players last
-	//FIXME those ain't always run if a player die if he was resurect meanwhile
+	//FIXME those ain't always run if a player die if he was resurrect meanwhile
 	//cf SC_REBIRTH, SC_KAIZEL, pc_dead...
 	if(target->type == BL_PC) {
 		TBL_PC *sd = BL_CAST(BL_PC,target);
 		if( sd->bg_id ) {
-			struct battleground_data *bg;
-			if( (bg = bg_team_search(sd->bg_id)) != NULL && bg->die_event[0] )
-				npc_event(sd, bg->die_event, 0);
+			std::shared_ptr<s_battleground_data> bg = util::umap_find(bg_team_db, sd->bg_id);
+
+			if( bg && !(bg->die_event.empty()) )
+				npc_event(sd, bg->die_event.c_str(), 0);
 		}
 
 		npc_script_event(sd,NPCE_DIE);
@@ -12016,6 +12028,8 @@ int status_change_clear(struct block_list* bl, int type)
 			case SC_LHZ_DUN_N2:
 			case SC_LHZ_DUN_N3:
 			case SC_LHZ_DUN_N4:
+			case SC_ENTRY_QUEUE_APPLY_DELAY:
+			case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
 			// Costumes
 			case SC_MOONSTAR:
 			case SC_SUPER_STAR:
@@ -12050,6 +12064,8 @@ int status_change_clear(struct block_list* bl, int type)
 			case SC_PUSH_CART:
 			case SC_ALL_RIDING:
 			case SC_STYLE_CHANGE:
+			case SC_ENTRY_QUEUE_APPLY_DELAY:
+			case SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT:
 			// Costumes
 			case SC_MOONSTAR:
 			case SC_SUPER_STAR:

+ 3 - 0
src/map/status.hpp

@@ -864,6 +864,9 @@ enum sc_type : int16 {
 	SC_WEAPONBLOCK_ON,
 	SC_SPORE_EXPLOSION,
 
+	SC_ENTRY_QUEUE_APPLY_DELAY,
+	SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT,
+
 #ifdef RENEWAL
 	SC_EXTREMITYFIST2, //! NOTE: This SC should be right before SC_MAX, so it doesn't disturb if RENEWAL is disabled
 #endif

+ 2 - 5
tools/ci/npc.bat

@@ -26,11 +26,8 @@ for /R . %%f in (*.txt) do (
 	set B=%%f
 	rem store relative path for compare
 	set R=!B:%C%\=!
-	
-	rem all except the battleground scripts
-	if "!R:~0,12!" neq "battleground" (
-		echo npc: npc\custom\!R!>>!OUT!
-	)
+
+	echo npc: npc\custom\!R!>>!OUT!
 )
 
 rem switch to the test folder

+ 1 - 1
tools/ci/npc.sh

@@ -5,7 +5,7 @@ out=npc/scripts_custom.conf
 printf "\n" >> $out
 echo "// Custom Scripts" >> $out
 
-find npc/custom \( -name "*.txt" -and -not -wholename "*/battleground/*" \) | xargs -I % echo "npc: %" >> $out
+find npc/custom \( -name "*.txt" \) | xargs -I % echo "npc: %" >> $out
 
 echo "// Test Scripts" >> $out