Resolves some Battleground issues (#4725)
* Queue data will now be kept available until a Battleground event is over. * Players can now join an active Battleground. * Adds a more detailed queue state tracking feature. * When a battleground is being prepared and not enough players click accept, stop the battleground from beginning. * When a player logs off or leaves a queue they will now properly be removed from the queue. * Cleans up MinPlayers and MaxPlayers parsing to not accept values less than 1. * Resolves players not being able to join an active battleground (up to MaxPlayers) unless someone quit early. * Adds a team size priority check to avoid adding more players to a larger team. * Fixes battlechat messages. * Adds a battle_config to disable the ability for players on maps with MF_NOWARP to join Battlegrounds. * Adds a new optional ActiveEvent label to the database. * Fixes a typo in Flavius 2 during unbooking process. * Cleans up the behavior of the Battle Therapists to use areapercentheal and areawarp. * Fixes KVM score not properly set on the first Battleground. * Fixes the global timer checks not ending the main timers on Flavius and Tierra Gorge. * Added an extra bg_reserve on global timer checks in case someone tries to join the battleground just before it's ended. * Fixed OnReadyCheck being called on global timer checks, causing the battlegrounds to start when there were no players on the map. * Fixed a bug on Tierra Gorge where multiple barricade walls could be stacked. * Fixes Croix also receiving 9 badges when Guillaume wins. * Adjusts StartDelay default to 0. * Add a database setting to give the ability to enable or disable joining as an individual, party, or guild. * Add a database setting to restrict jobs from entering Battlegrounds. * Better documents script commands bg_reserve and bg_unbook. * Other fixes and cleanups. Thanks to @roSBK and @Daegaladh, @admkakaroto, @Artuvazro, and @Atemo! Co-authored-by: Daegaladh <Daegaladh@users.noreply.github.com> Co-authored-by: Atemo <Atemo@users.noreply.github.com>
This commit is contained in:
parent
e6bffc11fe
commit
14c388b401
@ -30,3 +30,7 @@ bg_flee_penalty: 20
|
||||
|
||||
// Interval before updating the bg-member map mini-dots (milliseconds)
|
||||
bg_update_interval: 1000
|
||||
|
||||
// Before a player is warped into a Battleground from the Battleground Queue,
|
||||
// check to see if the player's current map has MF_NOWARP.
|
||||
bgqueue_nowarp_mapflag: no
|
||||
|
@ -354,9 +354,10 @@
|
||||
334: Total Domination
|
||||
|
||||
// Battlegrounds Queue
|
||||
337: You may not join a battleground queue when you're in a battleground map.
|
||||
337: You can't apply to a battleground queue from this 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.
|
||||
340: Participants were unable to join. Delaying entry for more participants.
|
||||
|
||||
// Templates for @who output
|
||||
343: Name: %s
|
||||
|
@ -29,7 +29,12 @@
|
||||
# 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)
|
||||
# StartDelay Amount of time in seconds once a queue is filled before players are warped. (Default: 0)
|
||||
# Join: Which application type is accepted. The entryqueuelist.lub can visually disable these options.
|
||||
# Solo Able to join a queue as an individual. (Default: true)
|
||||
# Party Able to join a queue as a party. (Default: true)
|
||||
# Guild Able to join a queue as a guild. (Default: true)
|
||||
# JobRestrictions List of jobs that are unable to join the battleground.
|
||||
# Locations: Battleground location settings.
|
||||
# - Map The map on which the battleground will be played.
|
||||
# StartEvent NPC event triggered when the battleground starts.
|
||||
@ -38,12 +43,14 @@
|
||||
# RespawnY Y coordinate for warping on death.
|
||||
# DeathEvent NPC event triggered when a player dies.
|
||||
# QuitEvent NPC event triggered when a player quits.
|
||||
# ActiveEvent NPC event triggered when a player joints an active battleground.
|
||||
# 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.
|
||||
# ActiveEvent NPC event triggered when a player joints an active battleground.
|
||||
# Variable Name of BG ID variable used in the battleground script.
|
||||
###########################################################################
|
||||
|
||||
@ -53,121 +60,151 @@ Header:
|
||||
|
||||
Body:
|
||||
- Id: 1
|
||||
Name: "Tierra Gorge"
|
||||
Name: Tierra Gorge
|
||||
MinPlayers: 6
|
||||
MinLevel: 80
|
||||
JobRestrictions:
|
||||
Novice: true
|
||||
SuperNovice: true
|
||||
Novice_High: true
|
||||
Baby: true
|
||||
Super_Baby: true
|
||||
Super_Novice_E: true
|
||||
Super_Baby_E: true
|
||||
Locations:
|
||||
- Map: "bat_a01"
|
||||
StartEvent: "start#bat_a01::OnReadyCheck"
|
||||
- Map: bat_a01
|
||||
StartEvent: start#bat_a01::OnReadyCheck
|
||||
TeamA:
|
||||
RespawnX: 50
|
||||
RespawnY: 374
|
||||
QuitEvent: "start#bat_a01::OnGuillaumeQuit"
|
||||
Variable: "$@TierraBG1_id1"
|
||||
QuitEvent: start#bat_a01::OnGuillaumeQuit
|
||||
ActiveEvent: start#bat_a01::OnGuillaumeActive
|
||||
Variable: $@TierraBG1_id1
|
||||
TeamB:
|
||||
RespawnX: 42
|
||||
RespawnY: 16
|
||||
QuitEvent: "start#bat_a01::OnCroixQuit"
|
||||
Variable: "$@TierraBG1_id2"
|
||||
- Map: "bat_a02"
|
||||
StartEvent: "start#bat_a02::OnReadyCheck"
|
||||
QuitEvent: start#bat_a01::OnCroixQuit
|
||||
ActiveEvent: start#bat_a01::OnCroixActive
|
||||
Variable: $@TierraBG1_id2
|
||||
- Map: bat_a02
|
||||
StartEvent: start#bat_a02::OnReadyCheck
|
||||
TeamA:
|
||||
RespawnX: 50
|
||||
RespawnY: 374
|
||||
QuitEvent: "start#bat_a02::OnGuillaumeQuit"
|
||||
Variable: "$@TierraBG2_id1"
|
||||
QuitEvent: start#bat_a02::OnGuillaumeQuit
|
||||
ActiveEvent: start#bat_a02::OnGuillaumeActive
|
||||
Variable: $@TierraBG2_id1
|
||||
TeamB:
|
||||
RespawnX: 42
|
||||
RespawnY: 16
|
||||
QuitEvent: "start#bat_a02::OnCroixQuit"
|
||||
Variable: "$@TierraBG2_id2"
|
||||
QuitEvent: start#bat_a02::OnCroixQuit
|
||||
ActiveEvent: start#bat_a02::OnCroixActive
|
||||
Variable: $@TierraBG2_id2
|
||||
- Id: 2
|
||||
Name: "Flavius"
|
||||
Name: Flavius
|
||||
MinPlayers: 6
|
||||
MinLevel: 80
|
||||
JobRestrictions:
|
||||
Novice: true
|
||||
SuperNovice: true
|
||||
Novice_High: true
|
||||
Baby: true
|
||||
Super_Baby: true
|
||||
Super_Novice_E: true
|
||||
Super_Baby_E: true
|
||||
Locations:
|
||||
- Map: "bat_b01"
|
||||
StartEvent: "start#bat_b01::OnReadyCheck"
|
||||
- Map: bat_b01
|
||||
StartEvent: start#bat_b01::OnReadyCheck
|
||||
TeamA:
|
||||
RespawnX: 10
|
||||
RespawnY: 290
|
||||
QuitEvent: "start#bat_b01::OnGuillaumeQuit"
|
||||
Variable: "$@FlaviusBG1_id1"
|
||||
QuitEvent: start#bat_b01::OnGuillaumeQuit
|
||||
ActiveEvent: start#bat_b01::OnGuillaumeActive
|
||||
Variable: $@FlaviusBG1_id1
|
||||
TeamB:
|
||||
RespawnX: 390
|
||||
RespawnY: 10
|
||||
QuitEvent: "start#bat_b01::OnCroixQuit"
|
||||
Variable: "$@FlaviusBG1_id2"
|
||||
- Map: "bat_b02"
|
||||
StartEvent: "start#bat_b02::OnReadyCheck"
|
||||
QuitEvent: start#bat_b01::OnCroixQuit
|
||||
ActiveEvent: start#bat_b01::OnCroixActive
|
||||
Variable: $@FlaviusBG1_id2
|
||||
- Map: bat_b02
|
||||
StartEvent: start#bat_b02::OnReadyCheck
|
||||
TeamA:
|
||||
RespawnX: 10
|
||||
RespawnY: 290
|
||||
QuitEvent: "start#bat_b02::OnGuillaumeQuit"
|
||||
Variable: "$@FlaviusBG2_id1"
|
||||
QuitEvent: start#bat_b02::OnGuillaumeQuit
|
||||
ActiveEvent: start#bat_b02::OnGuillaumeActive
|
||||
Variable: $@FlaviusBG2_id1
|
||||
TeamB:
|
||||
RespawnX: 390
|
||||
RespawnY: 10
|
||||
QuitEvent: "start#bat_b02::OnCroixQuit"
|
||||
Variable: "$@FlaviusBG2_id2"
|
||||
QuitEvent: start#bat_b02::OnCroixQuit
|
||||
ActiveEvent: start#bat_b02::OnCroixActive
|
||||
Variable: $@FlaviusBG2_id2
|
||||
- Id: 3
|
||||
Name: "KVM (Level 80 and up)"
|
||||
Name: KVM (Level 80 and up)
|
||||
MinPlayers: 5
|
||||
MinLevel: 80
|
||||
Locations:
|
||||
- Map: "bat_c01"
|
||||
StartEvent: "KvM01_BG::OnStart"
|
||||
- Map: bat_c01
|
||||
StartEvent: KvM01_BG::OnStart
|
||||
TeamA:
|
||||
RespawnX: 52
|
||||
RespawnY: 129
|
||||
DeathEvent: "KvM01_BG::OnGuillaumeDie"
|
||||
QuitEvent: "KvM01_BG::OnGuillaumeQuit"
|
||||
Variable: "$@KvM01BG_id1"
|
||||
DeathEvent: KvM01_BG::OnGuillaumeDie
|
||||
QuitEvent: KvM01_BG::OnGuillaumeQuit
|
||||
ActiveEvent: KvM01_BG::OnGuillaumeActive
|
||||
Variable: $@KvM01BG_id1
|
||||
TeamB:
|
||||
RespawnX: 147
|
||||
RespawnY: 55
|
||||
DeathEvent: "KvM01_BG::OnCroixDie"
|
||||
QuitEvent: "KvM01_BG::OnCroixQuit"
|
||||
Variable: "$@KvM01BG_id2"
|
||||
DeathEvent: KvM01_BG::OnCroixDie
|
||||
QuitEvent: KvM01_BG::OnCroixQuit
|
||||
ActiveEvent: KvM01_BG::OnCroixActive
|
||||
Variable: $@KvM01BG_id2
|
||||
- Id: 4
|
||||
Name: "KVM (Level 60~79)"
|
||||
Name: KVM (Level 60~79)
|
||||
MinPlayers: 5
|
||||
MinLevel: 60
|
||||
MaxLevel: 79
|
||||
Locations:
|
||||
- Map: "bat_c02"
|
||||
StartEvent: "KvM02_BG::OnStart"
|
||||
- Map: bat_c02
|
||||
StartEvent: KvM02_BG::OnStart
|
||||
TeamA:
|
||||
RespawnX: 52
|
||||
RespawnY: 129
|
||||
DeathEvent: "KvM02_BG::OnGuillaumeDie"
|
||||
QuitEvent: "KvM02_BG::OnGuillaumeQuit"
|
||||
Variable: "$@KvM02BG_id1"
|
||||
DeathEvent: KvM02_BG::OnGuillaumeDie
|
||||
QuitEvent: KvM02_BG::OnGuillaumeQuit
|
||||
ActiveEvent: KvM02_BG::OnGuillaumeActive
|
||||
Variable: $@KvM02BG_id1
|
||||
TeamB:
|
||||
RespawnX: 147
|
||||
RespawnY: 55
|
||||
DeathEvent: "KvM02_BG::OnCroixDie"
|
||||
QuitEvent: "KvM02_BG::OnCroixQuit"
|
||||
Variable: "$@KvM02BG_id2"
|
||||
DeathEvent: KvM02_BG::OnCroixDie
|
||||
QuitEvent: KvM02_BG::OnCroixQuit
|
||||
ActiveEvent: KvM02_BG::OnCroixActive
|
||||
Variable: $@KvM02BG_id2
|
||||
- Id: 5
|
||||
Name: "KVM (Level 59 and below"
|
||||
Name: KVM (Level 59 and below
|
||||
MinPlayers: 5
|
||||
MaxLevel: 59
|
||||
Locations:
|
||||
- Map: "bat_c03"
|
||||
StartEvent: "KvM03_BG::OnStart"
|
||||
- Map: bat_c03
|
||||
StartEvent: KvM03_BG::OnStart
|
||||
TeamA:
|
||||
RespawnX: 52
|
||||
RespawnY: 129
|
||||
DeathEvent: "KvM03_BG::OnGuillaumeDie"
|
||||
QuitEvent: "KvM03_BG::OnGuillaumeQuit"
|
||||
Variable: "$@KvM03BG_id1"
|
||||
DeathEvent: KvM03_BG::OnGuillaumeDie
|
||||
QuitEvent: KvM03_BG::OnGuillaumeQuit
|
||||
ActiveEvent: KvM03_BG::OnGuillaumeActive
|
||||
Variable: $@KvM03BG_id1
|
||||
TeamB:
|
||||
RespawnX: 147
|
||||
RespawnY: 55
|
||||
DeathEvent: "KvM03_BG::OnCroixDie"
|
||||
QuitEvent: "KvM03_BG::OnCroixQuit"
|
||||
Variable: "$@KvM03BG_id2"
|
||||
DeathEvent: KvM03_BG::OnCroixDie
|
||||
QuitEvent: KvM03_BG::OnCroixQuit
|
||||
ActiveEvent: KvM03_BG::OnCroixActive
|
||||
Variable: $@KvM03BG_id2
|
||||
|
||||
Footer:
|
||||
Imports:
|
||||
|
@ -29,7 +29,12 @@
|
||||
# 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)
|
||||
# StartDelay Amount of time in seconds once a queue is filled before players are warped. (Default: 0)
|
||||
# Join: Which application type is accepted. The entryqueuelist.lub can visually disable these options.
|
||||
# Solo Able to join a queue as an individual. (Default: true)
|
||||
# Party Able to join a queue as a party. (Default: true)
|
||||
# Guild Able to join a queue as a guild. (Default: true)
|
||||
# JobRestrictions List of jobs that are unable to join the battleground.
|
||||
# Locations: Battleground location settings.
|
||||
# - Map The map on which the battleground will be played.
|
||||
# StartEvent NPC event triggered when the battleground starts.
|
||||
@ -38,12 +43,14 @@
|
||||
# RespawnY Y coordinate for warping on death.
|
||||
# DeathEvent NPC event triggered when a player dies.
|
||||
# QuitEvent NPC event triggered when a player quits.
|
||||
# ActiveEvent NPC event triggered when a player joints an active battleground.
|
||||
# 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.
|
||||
# ActiveEvent NPC event triggered when a player joints an active battleground.
|
||||
# Variable Name of BG ID variable used in the battleground script.
|
||||
###########################################################################
|
||||
|
||||
|
@ -9393,19 +9393,19 @@ Example:
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*bg_reserve("<battleground_name>");
|
||||
*bg_reserve("<battleground_map_name>"{,<ended>});
|
||||
|
||||
Reserves a slot for the given Battleground for the Battleground UI System.
|
||||
Reserves a Battleground map for the Battleground UI System. When a map is booked it prevents another similar
|
||||
queue from being created and will allow players to join an active Battlegrounds event.
|
||||
|
||||
Note: 'bg_reserve' and 'bg_unbook' prevent the Battlegrounds queue from joining players in an active Battleground.
|
||||
If <ended> is true, then the Battleground is marked as over to prevent new players from joining. This state is meant
|
||||
for the period where players can get their Badges.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*bg_unbook("<battleground_name>");
|
||||
*bg_unbook("<battleground_map_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.
|
||||
Removes a Battleground map for the Battleground UI System. When a map is unbooked it allows a queue to be created.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
|
@ -58,25 +58,21 @@ OnStop:
|
||||
|
||||
OnTimer1000:
|
||||
stopnpctimer;
|
||||
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; }
|
||||
if (getbattleflag("feature.bgqueue")) {
|
||||
if (bg_get_data($@FlaviusBG1_id1, 0) == 0 && bg_get_data($@FlaviusBG1_id2, 0) == 0) {
|
||||
donpcevent "countdown#bat_b01::OnStop";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_b01", true;
|
||||
$@FlaviusBG1 = 0;
|
||||
if( $@FlaviusBG1_id1 ) { bg_destroy $@FlaviusBG1_id1; $@FlaviusBG1_id1 = 0; }
|
||||
if( $@FlaviusBG1_id2 ) { bg_destroy $@FlaviusBG1_id2; $@FlaviusBG1_id2 = 0; }
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_unbook "bat_b01";
|
||||
end;
|
||||
} else
|
||||
donpcevent "start#bat_b01::OnReadyCheck";
|
||||
end;
|
||||
}
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
initnpctimer;
|
||||
initnpctimer;
|
||||
end;
|
||||
}
|
||||
|
||||
|
||||
// Flavius Battleground Engine
|
||||
//============================================================
|
||||
bat_b01,15,15,3 script start#bat_b01 844,{
|
||||
@ -139,13 +135,14 @@ OnReset:
|
||||
donpcevent "guardian#bat_b01_b::OnEnable";
|
||||
donpcevent "cell#bat_b01_a::OnRed";
|
||||
donpcevent "cell#bat_b01_b::OnRed";
|
||||
donpcevent "time#bat_b01::OnEnable";
|
||||
disablenpc "Guillaume Vintenar#b01_a";
|
||||
disablenpc "Croix Vintenar#b01_b";
|
||||
disablenpc "Vintenar#bat_b01_aover";
|
||||
disablenpc "Vintenar#bat_b01_bover";
|
||||
bg_warp $@FlaviusBG1_id1,"bat_b01",87,75;
|
||||
bg_warp $@FlaviusBG1_id2,"bat_b01",311,224;
|
||||
end;
|
||||
|
||||
OnGuillaumeActive:
|
||||
warp "bat_b01",87,75;
|
||||
end;
|
||||
|
||||
OnCroixActive:
|
||||
warp "bat_b01",311,224;
|
||||
end;
|
||||
|
||||
OnGuillaumeQuit:
|
||||
@ -181,6 +178,8 @@ OnMyMobDead:
|
||||
enablenpc "Guillaume Vintenar#b01_a";
|
||||
enablenpc "Croix Vintenar#b01_b";
|
||||
donpcevent "time#bat_b01::OnStop";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_b01", true;
|
||||
}
|
||||
else {
|
||||
set $@Croix_ScoreBG1,1;
|
||||
@ -215,6 +214,8 @@ OnMyMobDead:
|
||||
enablenpc "Guillaume Vintenar#b01_a";
|
||||
enablenpc "Croix Vintenar#b01_b";
|
||||
donpcevent "time#bat_b01::OnStop";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_b01", true;
|
||||
}
|
||||
else {
|
||||
set $@Guill_ScoreBG1,1;
|
||||
@ -314,12 +315,14 @@ bat_b01,10,294,3 script Battle Therapist#b01_a 95,{
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_b01_rp1_a_warp";
|
||||
// enablenpc "bat_b01_rp1_a_warp";
|
||||
areapercentheal "bat_b01",0,280,20,300,100,100;
|
||||
areawarp "bat_b01",0,280,20,300,"bat_b01",87,73;
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_b01_rp1_a_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_b01_rp1_a_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
stopnpctimer;
|
||||
@ -332,22 +335,25 @@ OnEnable:
|
||||
end;
|
||||
|
||||
OnStop:
|
||||
disablenpc "bat_b01_rp1_a_warp";
|
||||
// disablenpc "bat_b01_rp1_a_warp";
|
||||
disablenpc "Battle Therapist#b01_a";
|
||||
stopnpctimer;
|
||||
end;
|
||||
}
|
||||
|
||||
/*
|
||||
// replaced by areapercentheal and areawarp to prevent enqueue issue
|
||||
bat_b01,10,290,0 script bat_b01_rp1_a_warp 45,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_b01_rp1_a_warp";
|
||||
end;
|
||||
|
||||
OnTouch_:
|
||||
OnTouch:
|
||||
percentheal 100,100;
|
||||
warp "bat_b01",87,73;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_b01,389,14,3 script Battle Therapist#b01_b 95,{
|
||||
specialeffect2 EF_HEAL;
|
||||
@ -359,12 +365,14 @@ bat_b01,389,14,3 script Battle Therapist#b01_b 95,{
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_b01_rp1_b_warp";
|
||||
// enablenpc "bat_b01_rp1_b_warp";
|
||||
areapercentheal "bat_b01",379,0,399,20,100,100;
|
||||
areawarp "bat_b01",379,0,399,20,"bat_b01",312,225;
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_b01_rp1_b_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_b01_rp1_b_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
stopnpctimer;
|
||||
@ -377,15 +385,16 @@ OnEnable:
|
||||
end;
|
||||
|
||||
OnStop:
|
||||
disablenpc "bat_b01_rp1_b_warp";
|
||||
// disablenpc "bat_b01_rp1_b_warp";
|
||||
disablenpc "Battle Therapist#b01_b";
|
||||
stopnpctimer;
|
||||
end;
|
||||
}
|
||||
|
||||
bat_b01,389,10,0 script bat_b01_rp1_b_warp 45,9,9,{
|
||||
/*
|
||||
bat_b01,389,10,0 script bat_b01_rp1_b_warp 45,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_b01_rp1_a_warp";
|
||||
disablenpc "bat_b01_rp1_b_warp";
|
||||
end;
|
||||
|
||||
OnTouch:
|
||||
@ -393,6 +402,7 @@ OnTouch:
|
||||
warp "bat_b01",312,225;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_b01,87,76,0 script A_CODE#bat_b01 -1,5,5,{
|
||||
OnTouch:
|
||||
@ -490,6 +500,8 @@ OnTimer1830000:
|
||||
bg_warp $@FlaviusBG1_id2,"bat_b01",390,10;
|
||||
enablenpc "Vintenar#bat_b01_aover";
|
||||
enablenpc "Vintenar#bat_b01_bover";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_b01", true;
|
||||
end;
|
||||
|
||||
OnTimer1900000:
|
||||
@ -526,11 +538,11 @@ bat_b01,10,294,3 script Vintenar#bat_b01_aover 419,{
|
||||
set .@A_B_gap,$@Guill_ScoreBG1 - $@Croix_ScoreBG1;
|
||||
if ($@FlaviusBG1_id1 == getcharid(4)) {
|
||||
if (.@A_B_gap > 0)
|
||||
callfunc "F_BG_Badge",1,"Guillaume","Flavius";
|
||||
callfunc "F_BG_Badge",1,"Guillaume","Flavius"; //Guillaume wins
|
||||
else if (.@A_B_gap == 0)
|
||||
callfunc "F_BG_Badge",0,"Guillaume","Flavius";
|
||||
callfunc "F_BG_Badge",0,"Guillaume","Flavius"; //Tie
|
||||
else
|
||||
callfunc "F_BG_Badge",0,"Guillaume","Flavius";
|
||||
callfunc "F_BG_Badge",0,"Guillaume","Flavius"; //Croix wins
|
||||
}
|
||||
else {
|
||||
mes "[Axl Rose]";
|
||||
@ -551,11 +563,11 @@ bat_b01,389,14,3 script Vintenar#bat_b01_bover 415,{
|
||||
set .@A_B_gap,$@Guill_ScoreBG1 - $@Croix_ScoreBG1;
|
||||
if ($@FlaviusBG1_id2 == getcharid(4)) {
|
||||
if (.@A_B_gap > 0)
|
||||
callfunc "F_BG_Badge",1,"Croix","Flavius";
|
||||
callfunc "F_BG_Badge",0,"Croix","Flavius"; //Guillaume wins
|
||||
else if (.@A_B_gap == 0)
|
||||
callfunc "F_BG_Badge",0,"Croix","Flavius";
|
||||
callfunc "F_BG_Badge",0,"Croix","Flavius"; //Tie
|
||||
else
|
||||
callfunc "F_BG_Badge",1,"Croix","Flavius";
|
||||
callfunc "F_BG_Badge",1,"Croix","Flavius"; //Croix wins
|
||||
}
|
||||
else {
|
||||
mes "[Swandery]";
|
||||
|
@ -59,21 +59,18 @@ OnStop:
|
||||
|
||||
OnTimer1000:
|
||||
stopnpctimer;
|
||||
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; }
|
||||
if (getbattleflag("feature.bgqueue")) {
|
||||
bg_unbook "bat_b01";
|
||||
end;
|
||||
} else
|
||||
donpcevent "start#bat_b01::OnReadyCheck";
|
||||
if (bg_get_data($@FlaviusBG2_id1, 0) == 0 && bg_get_data($@FlaviusBG2_id2, 0) == 0) {
|
||||
donpcevent "countdown#bat_b02::OnStop";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_b02", true;
|
||||
$@FlaviusBG2 = 0;
|
||||
if( $@FlaviusBG2_id1 ) { bg_destroy $@FlaviusBG2_id1; $@FlaviusBG2_id1 = 0; }
|
||||
if( $@FlaviusBG2_id2 ) { bg_destroy $@FlaviusBG2_id2; $@FlaviusBG2_id2 = 0; }
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_unbook "bat_b02";
|
||||
end;
|
||||
}
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
initnpctimer;
|
||||
initnpctimer;
|
||||
end;
|
||||
}
|
||||
|
||||
@ -89,7 +86,7 @@ OnReadyCheck:
|
||||
if( $@FlaviusBG2 )
|
||||
end;
|
||||
if (!getbattleflag("feature.bgqueue")) {
|
||||
set .@Guillaume, getwaitingroomstate(0,"Lieutenant Huvas");
|
||||
set .@Guillaume, getwaitingroomstate(0,"Lieutenant Huvas");
|
||||
set .@Croix, getwaitingroomstate(0,"Lieutenant Yukon");
|
||||
if( !.@Guillaume && !.@Croix ) {
|
||||
donpcevent "#bat_b02_timer::OnStop";
|
||||
@ -102,8 +99,8 @@ OnReadyCheck:
|
||||
set $@FlaviusBG2_Victory, 0;
|
||||
set $@Croix_ScoreBG2, 0;
|
||||
set $@Guill_ScoreBG2, 0;
|
||||
|
||||
bg_updatescore "bat_b02",$@Guill_ScoreBG2,$@Croix_ScoreBG2;
|
||||
|
||||
if (!getbattleflag("feature.bgqueue")) {
|
||||
donpcevent "Lieutenant Huvas::OnEnterBG";
|
||||
donpcevent "Lieutenant Yukon::OnEnterBG";
|
||||
@ -140,13 +137,14 @@ OnReset:
|
||||
donpcevent "guardian#bat_b02_b::OnEnable";
|
||||
donpcevent "cell#bat_b02_a::OnRed";
|
||||
donpcevent "cell#bat_b02_b::OnRed";
|
||||
donpcevent "time#bat_b02::OnEnable";
|
||||
disablenpc "Guillaume Vintenar#b02_a";
|
||||
disablenpc "Croix Vintenar#b02_b";
|
||||
disablenpc "Vintenar#bat_b02_aover";
|
||||
disablenpc "Vintenar#bat_b02_bover";
|
||||
bg_warp $@FlaviusBG2_id1,"bat_b02",87,75;
|
||||
bg_warp $@FlaviusBG2_id2,"bat_b02",311,224;
|
||||
end;
|
||||
|
||||
OnGuillaumeActive:
|
||||
warp "bat_b02",87,75;
|
||||
end;
|
||||
|
||||
OnCroixActive:
|
||||
warp "bat_b02",311,224;
|
||||
end;
|
||||
|
||||
OnGuillaumeQuit:
|
||||
@ -182,6 +180,8 @@ OnMyMobDead:
|
||||
enablenpc "Guillaume Vintenar#b02_a";
|
||||
enablenpc "Croix Vintenar#b02_b";
|
||||
donpcevent "time#bat_b02::OnStop";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_b02", true;
|
||||
}
|
||||
else {
|
||||
set $@Croix_ScoreBG2,1;
|
||||
@ -216,6 +216,8 @@ OnMyMobDead:
|
||||
enablenpc "Guillaume Vintenar#b02_a";
|
||||
enablenpc "Croix Vintenar#b02_b";
|
||||
donpcevent "time#bat_b02::OnStop";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_b02", true;
|
||||
}
|
||||
else {
|
||||
set $@Guill_ScoreBG2,1;
|
||||
@ -315,12 +317,14 @@ bat_b02,10,294,3 script Battle Therapist#b02_a 95,{
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_b02_rp1_a_warp";
|
||||
// enablenpc "bat_b02_rp1_a_warp";
|
||||
areapercentheal "bat_b02",0,280,20,300,100,100;
|
||||
areawarp "bat_b02",0,280,20,300,"bat_b02",87,73;
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_b02_rp1_a_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_b02_rp1_a_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
stopnpctimer;
|
||||
@ -333,22 +337,24 @@ OnEnable:
|
||||
end;
|
||||
|
||||
OnStop:
|
||||
disablenpc "bat_b02_rp1_a_warp";
|
||||
// disablenpc "bat_b02_rp1_a_warp";
|
||||
disablenpc "Battle Therapist#b02_a";
|
||||
stopnpctimer;
|
||||
end;
|
||||
}
|
||||
|
||||
/*
|
||||
bat_b02,10,290,0 script bat_b02_rp1_a_warp 45,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_b02_rp1_a_warp";
|
||||
end;
|
||||
|
||||
OnTouch_:
|
||||
OnTouch:
|
||||
percentheal 100,100;
|
||||
warp "bat_b02",87,73;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_b02,389,14,3 script Battle Therapist#b02_b 95,{
|
||||
specialeffect2 EF_HEAL;
|
||||
@ -360,12 +366,14 @@ bat_b02,389,14,3 script Battle Therapist#b02_b 95,{
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_b02_rp1_b_warp";
|
||||
areapercentheal "bat_b02",379,0,399,20,100,100;
|
||||
areawarp "bat_b02",379,0,399,20,"bat_b02",312,225;
|
||||
// enablenpc "bat_b02_rp1_b_warp";
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_b02_rp1_b_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_b02_rp1_b_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
stopnpctimer;
|
||||
@ -378,15 +386,16 @@ OnEnable:
|
||||
end;
|
||||
|
||||
OnStop:
|
||||
disablenpc "bat_b02_rp1_b_warp";
|
||||
// disablenpc "bat_b02_rp1_b_warp";
|
||||
disablenpc "Battle Therapist#b02_b";
|
||||
stopnpctimer;
|
||||
end;
|
||||
}
|
||||
|
||||
bat_b02,389,10,0 script bat_b02_rp1_b_warp 45,9,9,{
|
||||
/*
|
||||
bat_b02,389,10,0 script bat_b02_rp1_b_warp 45,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_b02_rp1_a_warp";
|
||||
disablenpc "bat_b02_rp1_b_warp";
|
||||
end;
|
||||
|
||||
OnTouch:
|
||||
@ -394,18 +403,19 @@ OnTouch:
|
||||
warp "bat_b02",312,225;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_b02,87,76,0 script A_CODE#bat_b02 -1,5,5,{
|
||||
OnTouch:
|
||||
if (checkquest(2070) < 0)
|
||||
//setquest 2070;
|
||||
setquest 2070;
|
||||
end;
|
||||
}
|
||||
|
||||
bat_b02,312,224,0 script B_CODE#bat_b02 -1,5,5,{
|
||||
OnTouch:
|
||||
if (checkquest(2070) < 0)
|
||||
//setquest 2070;
|
||||
setquest 2070;
|
||||
end;
|
||||
}
|
||||
|
||||
@ -491,6 +501,8 @@ OnTimer1830000:
|
||||
bg_warp $@FlaviusBG2_id2,"bat_b02",390,10;
|
||||
enablenpc "Vintenar#bat_b02_aover";
|
||||
enablenpc "Vintenar#bat_b02_bover";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_b02", true;
|
||||
end;
|
||||
|
||||
OnTimer1900000:
|
||||
@ -527,11 +539,11 @@ bat_b02,10,294,3 script Vintenar#bat_b02_aover 419,{
|
||||
set .@A_B_gap,$@Guill_ScoreBG2 - $@Croix_ScoreBG2;
|
||||
if ($@FlaviusBG2_id1 == getcharid(4)) {
|
||||
if (.@A_B_gap > 0)
|
||||
callfunc "F_BG_Badge",1,"Guillaume","Flavius";
|
||||
callfunc "F_BG_Badge",1,"Guillaume","Flavius"; //Guillaume wins
|
||||
else if (.@A_B_gap == 0)
|
||||
callfunc "F_BG_Badge",0,"Guillaume","Flavius";
|
||||
callfunc "F_BG_Badge",0,"Guillaume","Flavius"; //Tie
|
||||
else
|
||||
callfunc "F_BG_Badge",0,"Guillaume","Flavius";
|
||||
callfunc "F_BG_Badge",0,"Guillaume","Flavius"; //Croix wins
|
||||
}
|
||||
else {
|
||||
mes "[Axl Rose]";
|
||||
@ -552,11 +564,11 @@ bat_b02,389,14,3 script Vintenar#bat_b02_bover 415,{
|
||||
set .@A_B_gap,$@Guill_ScoreBG2 - $@Croix_ScoreBG2;
|
||||
if ($@FlaviusBG2_id2 == getcharid(4)) {
|
||||
if (.@A_B_gap > 0)
|
||||
callfunc "F_BG_Badge",1,"Croix","Flavius";
|
||||
callfunc "F_BG_Badge",0,"Croix","Flavius"; //Guillaume wins
|
||||
else if (.@A_B_gap == 0)
|
||||
callfunc "F_BG_Badge",0,"Croix","Flavius";
|
||||
callfunc "F_BG_Badge",0,"Croix","Flavius"; //Tie
|
||||
else
|
||||
callfunc "F_BG_Badge",1,"Croix","Flavius";
|
||||
callfunc "F_BG_Badge",1,"Croix","Flavius"; //Croix wins
|
||||
}
|
||||
else {
|
||||
mes "[Swandery]";
|
||||
|
@ -155,6 +155,14 @@ OnCroixDie:
|
||||
}
|
||||
end;
|
||||
|
||||
OnGuillaumeActive:
|
||||
warp "bat_c01",61,120;
|
||||
end;
|
||||
|
||||
OnCroixActive:
|
||||
warp "bat_c01",138,63;
|
||||
end;
|
||||
|
||||
OnStart:
|
||||
disablenpc "KVM Officer#KVM01A";
|
||||
disablenpc "KVM Officer#KVM01B";
|
||||
@ -224,6 +232,7 @@ OnTimer61000:
|
||||
end;
|
||||
}
|
||||
}
|
||||
bg_updatescore "bat_c01",.Guillaume_Count,.Croix_Count;
|
||||
set $@KvM01BG, 2; // Playing
|
||||
bg_warp $@KvM01BG_id1,"bat_c01",61,120;
|
||||
bg_warp $@KvM01BG_id2,"bat_c01",138,63;
|
||||
@ -292,6 +301,8 @@ OnStop:
|
||||
bg_warp $@KvM01BG_id1,"bat_c01",53,128;
|
||||
bg_warp $@KvM01BG_id2,"bat_c01",146,55;
|
||||
donpcevent "KvM01_BG_Out::OnBegin";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_c01", true;
|
||||
end;
|
||||
}
|
||||
|
||||
@ -333,7 +344,6 @@ OnTimer60000:
|
||||
disablenpc "KVM Officer#KVM01B";
|
||||
mapwarp "bat_c01","bat_room",154,150;
|
||||
maprespawnguildid "bat_c01",0,3; // Just in case someone else
|
||||
bg_updatescore "bat_c01",5,5;
|
||||
set $@KvM01BG, 0;
|
||||
|
||||
OnGuillaumeJoin:
|
||||
|
@ -155,6 +155,14 @@ OnCroixDie:
|
||||
}
|
||||
end;
|
||||
|
||||
OnGuillaumeActive:
|
||||
warp "bat_c02",62,119;
|
||||
end;
|
||||
|
||||
OnCroixActive:
|
||||
warp "bat_c02",137,64;
|
||||
end;
|
||||
|
||||
OnStart:
|
||||
disablenpc "KVM Officer#KVM02A";
|
||||
disablenpc "KVM Officer#KVM02B";
|
||||
@ -224,6 +232,7 @@ OnTimer61000:
|
||||
end;
|
||||
}
|
||||
}
|
||||
bg_updatescore "bat_c02",.Guillaume_Count,.Croix_Count;
|
||||
set $@KvM02BG, 2; // Playing
|
||||
bg_warp $@KvM02BG_id1,"bat_c02",62,119;
|
||||
bg_warp $@KvM02BG_id2,"bat_c02",137,64;
|
||||
@ -292,6 +301,8 @@ OnStop:
|
||||
bg_warp $@KvM02BG_id1,"bat_c02",53,128;
|
||||
bg_warp $@KvM02BG_id2,"bat_c02",146,55;
|
||||
donpcevent "KvM02_BG_Out::OnBegin";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_c02", true;
|
||||
end;
|
||||
}
|
||||
|
||||
@ -333,7 +344,6 @@ OnTimer60000:
|
||||
disablenpc "KVM Officer#KVM02B";
|
||||
mapwarp "bat_c02","bat_room",154,150;
|
||||
maprespawnguildid "bat_c02",0,3; // Just in case someone else
|
||||
bg_updatescore "bat_c02",5,5;
|
||||
set $@KvM02BG, 0;
|
||||
|
||||
OnGuillaumeJoin:
|
||||
|
@ -155,6 +155,14 @@ OnCroixDie:
|
||||
}
|
||||
end;
|
||||
|
||||
OnGuillaumeActive:
|
||||
warp "bat_c03",62,119;
|
||||
end;
|
||||
|
||||
OnCroixActive:
|
||||
warp "bat_c03",137,64;
|
||||
end;
|
||||
|
||||
OnStart:
|
||||
disablenpc "KVM Officer#KVM03A";
|
||||
disablenpc "KVM Officer#KVM03B";
|
||||
@ -224,6 +232,7 @@ OnTimer61000:
|
||||
end;
|
||||
}
|
||||
}
|
||||
bg_updatescore "bat_c03",.Guillaume_Count,.Croix_Count;
|
||||
set $@KvM03BG, 2; // Playing
|
||||
bg_warp $@KvM03BG_id1,"bat_c03",62,119;
|
||||
bg_warp $@KvM03BG_id2,"bat_c03",137,64;
|
||||
@ -292,6 +301,8 @@ OnStop:
|
||||
bg_warp $@KvM03BG_id1,"bat_c03",53,128;
|
||||
bg_warp $@KvM03BG_id2,"bat_c03",146,55;
|
||||
donpcevent "KvM03_BG_Out::OnBegin";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_c03", true;
|
||||
end;
|
||||
}
|
||||
|
||||
@ -333,7 +344,6 @@ OnTimer60000:
|
||||
disablenpc "KVM Officer#KVM03B";
|
||||
mapwarp "bat_c03","bat_room",154,150;
|
||||
maprespawnguildid "bat_c03",0,3; // Just in case someone else
|
||||
bg_updatescore "bat_c03",5,5;
|
||||
set $@KvM03BG, 0;
|
||||
|
||||
OnGuillaumeJoin:
|
||||
|
@ -58,21 +58,18 @@ OnStop:
|
||||
|
||||
OnTimer1000:
|
||||
stopnpctimer;
|
||||
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; }
|
||||
if (getbattleflag("feature.bgqueue")) {
|
||||
if (bg_get_data($@TierraBG1_id1, 0) == 0 && bg_get_data($@TierraBG1_id2, 0) == 0) {
|
||||
donpcevent "countdown#bat_a01::OnStop";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_a01", true;
|
||||
$@TierraBG1 = 0; $@TierraBG1_Victory = 0;
|
||||
if( $@TierraBG1_id1 ) { bg_destroy $@TierraBG1_id1; $@TierraBG1_id1 = 0; }
|
||||
if( $@TierraBG1_id2 ) { bg_destroy $@TierraBG1_id2; $@TierraBG1_id2 = 0; }
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_unbook "bat_a01";
|
||||
end;
|
||||
} else
|
||||
donpcevent "start#bat_a01::OnReadyCheck";
|
||||
end;
|
||||
}
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
initnpctimer;
|
||||
initnpctimer;
|
||||
end;
|
||||
}
|
||||
|
||||
@ -126,6 +123,14 @@ OnEnable:
|
||||
disablenpc "Croix Vintenar#a01_b";
|
||||
end;
|
||||
|
||||
OnGuillaumeActive:
|
||||
warp "bat_a01",352,342;
|
||||
end;
|
||||
|
||||
OnCroixActive:
|
||||
warp "bat_a01",353,52;
|
||||
end;
|
||||
|
||||
OnGuillaumeQuit:
|
||||
OnCroixQuit:
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
@ -183,6 +188,8 @@ OnMyMobDead:
|
||||
mapannounce "bat_a01", "Croix Vintenar Swandery: We destroyed Guillaume's Food Storage. We won that! Wow!",bc_map,"0xFFCE00";
|
||||
bg_warp $@TierraBG1_id1,"bat_a01",50,374;
|
||||
bg_warp $@TierraBG1_id2,"bat_a01",42,16;
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_a01", true;
|
||||
}
|
||||
end;
|
||||
}
|
||||
@ -206,6 +213,8 @@ OnMyMobDead:
|
||||
mapannounce "bat_a01", "Guillaume Vintenar Axl Rose : We destroyed Croix's Food Storage. We won that! Wow!",bc_map,"0xFFCE00";
|
||||
bg_warp $@TierraBG1_id1,"bat_a01",50,374;
|
||||
bg_warp $@TierraBG1_id2,"bat_a01",42,16;
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_a01", true;
|
||||
}
|
||||
end;
|
||||
}
|
||||
@ -364,8 +373,10 @@ bat_a01,185,270,1 script Guillaume Blacksmith#a01 851,{
|
||||
mes "[Guillaume Blacksmith]";
|
||||
mes "Wow! It's done.";
|
||||
mes "We are relieved.";
|
||||
delitem 7049,50; //Stone
|
||||
donpcevent "barricade#bat_a01_a::OnEnable";
|
||||
if (mobcount("bat_a01","barricade#bat_a01_a::OnMyMobDead") < 17) {
|
||||
delitem 7049,50; //Stone
|
||||
donpcevent "barricade#bat_a01_a::OnEnable";
|
||||
}
|
||||
close2;
|
||||
disablenpc "Guillaume Blacksmith#a01";
|
||||
end;
|
||||
@ -448,8 +459,10 @@ bat_a01,170,121,5 script Croix Blacksmith#bat_a01 851,{
|
||||
mes "[Croix Blacksmith]";
|
||||
mes "Wow! It's done.";
|
||||
mes "We are relieved.";
|
||||
delitem 7049,50; //Stone
|
||||
donpcevent "barricade#bat_a01_b::OnEnable";
|
||||
if (mobcount("bat_a01","barricade#bat_a01_b::OnMyMobDead") < 17) {
|
||||
delitem 7049,50; //Stone
|
||||
donpcevent "barricade#bat_a01_b::OnEnable";
|
||||
}
|
||||
close2;
|
||||
disablenpc "Croix Blacksmith#bat_a01";
|
||||
end;
|
||||
@ -500,35 +513,39 @@ OnEnable:
|
||||
end;
|
||||
|
||||
OnStop:
|
||||
disablenpc "bat_a01_rp1_a_warp";
|
||||
// disablenpc "bat_a01_rp1_a_warp";
|
||||
disablenpc "Battle Therapist#a01_a";
|
||||
stopnpctimer;
|
||||
end;
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_a01_rp1_a_warp";
|
||||
// enablenpc "bat_a01_rp1_a_warp";
|
||||
areapercentheal "bat_a01",41,365,61,385,100,100;
|
||||
areawarp "bat_a01",41,365,61,385,"bat_a01",352,342;
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_a01_rp1_a_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_a01_rp1_a_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
donpcevent "Battle Therapist#a01_a::OnEnable";
|
||||
end;
|
||||
}
|
||||
|
||||
/*
|
||||
bat_a01,51,375,0 script bat_a01_rp1_a_warp -1,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_a01_rp1_a_warp";
|
||||
end;
|
||||
|
||||
OnTouch_:
|
||||
OnTouch:
|
||||
percentheal 100,100;
|
||||
warp "bat_a01",352,342;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_a01,45,19,3 script Battle Therapist#a01_b 95,{
|
||||
specialeffect2 EF_HEAL;
|
||||
@ -550,25 +567,28 @@ OnEnable:
|
||||
end;
|
||||
|
||||
OnStop:
|
||||
disablenpc "bat_a01_rp1_b_warp";
|
||||
// disablenpc "bat_a01_rp1_b_warp";
|
||||
disablenpc "Battle Therapist#a01_b";
|
||||
stopnpctimer;
|
||||
end;
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_a01_rp1_b_warp";
|
||||
areapercentheal "bat_a01",33,7,53,27,100,100;
|
||||
areawarp "bat_a01",33,7,53,27,"bat_a01",353,52;
|
||||
// enablenpc "bat_a01_rp1_b_warp";
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_a01_rp1_b_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_a01_rp1_b_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
donpcevent "Battle Therapist#a01_b::OnEnable";
|
||||
end;
|
||||
}
|
||||
|
||||
/*
|
||||
bat_a01,43,17,0 script bat_a01_rp1_b_warp -1,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_a01_rp1_b_warp";
|
||||
@ -579,6 +599,7 @@ OnTouch:
|
||||
warp "bat_a01",353,52;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_a01,60,216,3 script Valley Ghost#bat_a01_n 950,{
|
||||
specialeffect2 EF_HEAL;
|
||||
@ -597,18 +618,21 @@ OnEnable:
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_a01_rp1_n_warp";
|
||||
areapercentheal "bat_a01",45,203,65,223,100,100;
|
||||
areawarp "bat_a01",45,203,65,223,"bat_a01",301,209;
|
||||
// enablenpc "bat_a01_rp1_n_warp";
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_a01_rp1_n_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_a01_rp1_n_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
donpcevent "Valley Ghost#bat_a01_n::OnEnable";
|
||||
end;
|
||||
}
|
||||
|
||||
/*
|
||||
bat_a01,55,213,0 script bat_a01_rp1_n_warp -1,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_a01_rp1_n_warp";
|
||||
@ -619,6 +643,7 @@ OnTouch:
|
||||
warp "bat_a01",301,209;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_a01,194,267,0 script barri_warp_up#bat_a01_a -1,7,0,{
|
||||
OnTouch:
|
||||
|
@ -57,21 +57,19 @@ OnStop:
|
||||
|
||||
OnTimer1000:
|
||||
stopnpctimer;
|
||||
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; }
|
||||
if (getbattleflag("feature.bgqueue")) {
|
||||
if (!bg_get_data($@TierraBG2_id1, 0) && !bg_get_data($@TierraBG2_id2, 0)) {
|
||||
donpcevent "countdown#bat_a02::OnStop";
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_a02", true;
|
||||
mapwarp "bat_a02","bat_room",154,150;
|
||||
$@TierraBG2 = 0; $@TierraBG2_Victory = 0;
|
||||
if( $@TierraBG2_id1 ) { bg_destroy $@TierraBG2_id1; $@TierraBG2_id1 = 0; }
|
||||
if( $@TierraBG2_id2 ) { bg_destroy $@TierraBG2_id2; $@TierraBG2_id2 = 0; }
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_unbook "bat_a02";
|
||||
end;
|
||||
} else
|
||||
donpcevent "start#bat_a02::OnReadyCheck";
|
||||
end;
|
||||
}
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
initnpctimer;
|
||||
initnpctimer;
|
||||
end;
|
||||
}
|
||||
|
||||
@ -125,6 +123,14 @@ OnEnable:
|
||||
disablenpc "Croix Vintenar#a02_b";
|
||||
end;
|
||||
|
||||
OnGuillaumeActive:
|
||||
warp "bat_a02",352,342;
|
||||
end;
|
||||
|
||||
OnCroixActive:
|
||||
warp "bat_a02",353,52;
|
||||
end;
|
||||
|
||||
OnGuillaumeQuit:
|
||||
OnCroixQuit:
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
@ -182,6 +188,8 @@ OnMyMobDead:
|
||||
mapannounce "bat_a02", "Croix Vintenar Swandery: We destroyed Guillaume's Food Storage. We won that! Wow!",bc_map,"0xFFCE00";
|
||||
bg_warp $@TierraBG2_id1,"bat_a02",50,374;
|
||||
bg_warp $@TierraBG2_id2,"bat_a02",42,16;
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_a02", true;
|
||||
}
|
||||
end;
|
||||
}
|
||||
@ -205,6 +213,8 @@ OnMyMobDead:
|
||||
mapannounce "bat_a02", "Guillaume Vintenar Axl Rose : We destroyed Croix's Food Storage. We won that! Wow!",bc_map,"0xFFCE00";
|
||||
bg_warp $@TierraBG2_id1,"bat_a02",50,374;
|
||||
bg_warp $@TierraBG2_id2,"bat_a02",42,16;
|
||||
if (getbattleflag("feature.bgqueue"))
|
||||
bg_reserve "bat_a02", true;
|
||||
}
|
||||
end;
|
||||
}
|
||||
@ -363,8 +373,10 @@ bat_a02,185,270,1 script Guillaume Blacksmith#a02 851,{
|
||||
mes "[Guillaume Blacksmith]";
|
||||
mes "Wow! It's done.";
|
||||
mes "We are relieved.";
|
||||
delitem 7049,50; //Stone
|
||||
donpcevent "barricade#bat_a02_a::OnEnable";
|
||||
if (mobcount("bat_a02","barricade#bat_a02_a::OnMyMobDead") < 17) {
|
||||
delitem 7049,50; //Stone
|
||||
donpcevent "barricade#bat_a02_a::OnEnable";
|
||||
}
|
||||
close2;
|
||||
disablenpc "Guillaume Blacksmith#a02";
|
||||
end;
|
||||
@ -447,8 +459,10 @@ bat_a02,170,121,5 script Croix Blacksmith#bat_a02 851,{
|
||||
mes "[Croix Blacksmith]";
|
||||
mes "Wow! It's done.";
|
||||
mes "We are relieved.";
|
||||
delitem 7049,50; //Stone
|
||||
donpcevent "barricade#bat_a02_b::OnEnable";
|
||||
if (mobcount("bat_a02","barricade#bat_a02_b::OnMyMobDead") < 17) {
|
||||
delitem 7049,50; //Stone
|
||||
donpcevent "barricade#bat_a02_b::OnEnable";
|
||||
}
|
||||
close2;
|
||||
disablenpc "Croix Blacksmith#bat_a02";
|
||||
end;
|
||||
@ -499,35 +513,39 @@ OnEnable:
|
||||
end;
|
||||
|
||||
OnStop:
|
||||
disablenpc "bat_a02_rp1_a_warp";
|
||||
// disablenpc "bat_a02_rp1_a_warp";
|
||||
disablenpc "Battle Therapist#a02_a";
|
||||
stopnpctimer;
|
||||
end;
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_a02_rp1_a_warp";
|
||||
// enablenpc "bat_a02_rp1_a_warp";
|
||||
areapercentheal "bat_a02",41,365,61,385,100,100;
|
||||
areawarp "bat_a02",41,365,61,385,"bat_a02",352,342;
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_a02_rp1_a_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_a02_rp1_a_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
donpcevent "Battle Therapist#a02_a::OnEnable";
|
||||
end;
|
||||
}
|
||||
|
||||
/*
|
||||
bat_a02,51,375,0 script bat_a02_rp1_a_warp -1,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_a02_rp1_a_warp";
|
||||
end;
|
||||
|
||||
OnTouch_:
|
||||
OnTouch:
|
||||
percentheal 100,100;
|
||||
warp "bat_a02",352,342;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_a02,45,19,3 script Battle Therapist#a02_b 95,{
|
||||
specialeffect2 EF_HEAL;
|
||||
@ -549,25 +567,28 @@ OnEnable:
|
||||
end;
|
||||
|
||||
OnStop:
|
||||
disablenpc "bat_a02_rp1_b_warp";
|
||||
// disablenpc "bat_a02_rp1_b_warp";
|
||||
disablenpc "Battle Therapist#a02_b";
|
||||
stopnpctimer;
|
||||
end;
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_a02_rp1_b_warp";
|
||||
// enablenpc "bat_a02_rp1_b_warp";
|
||||
areapercentheal "bat_a02",33,7,53,27,100,100;
|
||||
areawarp "bat_a02",33,7,53,27,"bat_a02",353,52;
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_a02_rp1_b_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_a02_rp1_b_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
donpcevent "Battle Therapist#a02_b::OnEnable";
|
||||
end;
|
||||
}
|
||||
|
||||
/*
|
||||
bat_a02,43,17,0 script bat_a02_rp1_b_warp -1,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_a02_rp1_b_warp";
|
||||
@ -578,6 +599,7 @@ OnTouch:
|
||||
warp "bat_a02",353,52;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_a02,60,216,3 script Valley Ghost#bat_a02_n 950,{
|
||||
specialeffect2 EF_HEAL;
|
||||
@ -596,18 +618,21 @@ OnEnable:
|
||||
|
||||
OnTimer25000:
|
||||
specialeffect EF_SANCTUARY;
|
||||
enablenpc "bat_a02_rp1_n_warp";
|
||||
// enablenpc "bat_a02_rp1_n_warp";
|
||||
areapercentheal "bat_a02",45,203,65,223,100,100;
|
||||
areawarp "bat_a02",45,203,65,223,"bat_a02",301,209;
|
||||
end;
|
||||
|
||||
OnTimer26000:
|
||||
disablenpc "bat_a02_rp1_n_warp";
|
||||
end;
|
||||
// OnTimer26000:
|
||||
// disablenpc "bat_a02_rp1_n_warp";
|
||||
// end;
|
||||
|
||||
OnTimer26500:
|
||||
donpcevent "Valley Ghost#bat_a02_n::OnEnable";
|
||||
end;
|
||||
}
|
||||
|
||||
/*
|
||||
bat_a02,55,213,0 script bat_a02_rp1_n_warp -1,10,10,{
|
||||
OnInit:
|
||||
disablenpc "bat_a02_rp1_n_warp";
|
||||
@ -618,6 +643,7 @@ OnTouch:
|
||||
warp "bat_a02",301,209;
|
||||
end;
|
||||
}
|
||||
*/
|
||||
|
||||
bat_a02,194,267,0 script barri_warp_up#bat_a02_a -1,7,0,{
|
||||
OnTouch:
|
||||
|
@ -8951,6 +8951,7 @@ static const struct _battle_data {
|
||||
{ "idletime_hom_option", &battle_config.idletime_hom_option, 0x1F, 0x1, 0xFFF, },
|
||||
{ "devotion_standup_fix", &battle_config.devotion_standup_fix, 1, 0, 1, },
|
||||
{ "feature.bgqueue", &battle_config.feature_bgqueue, 1, 0, 1, },
|
||||
{ "bgqueue_nowarp_mapflag", &battle_config.bgqueue_nowarp_mapflag, 0, 0, 1, },
|
||||
{ "homunculus_exp_gain", &battle_config.homunculus_exp_gain, 10, 0, 100, },
|
||||
{ "rental_item_novalue", &battle_config.rental_item_novalue, 1, 0, 1, },
|
||||
|
||||
|
@ -675,6 +675,7 @@ struct Battle_Config
|
||||
int idletime_hom_option;
|
||||
int devotion_standup_fix;
|
||||
int feature_bgqueue;
|
||||
int bgqueue_nowarp_mapflag;
|
||||
int homunculus_exp_gain;
|
||||
int rental_item_novalue;
|
||||
|
||||
|
@ -32,6 +32,7 @@ using namespace rathena;
|
||||
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;
|
||||
int bg_queue_count = 1;
|
||||
|
||||
const std::string BattlegroundDatabase::getDefaultLocation() {
|
||||
return std::string(db_path) + "/battleground_db.yml";
|
||||
@ -75,6 +76,11 @@ uint64 BattlegroundDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
if (!this->asInt32(node, "MinPlayers", min))
|
||||
return 0;
|
||||
|
||||
if (min < 1) {
|
||||
this->invalidWarning(node["MinPlayers"], "Minimum players %d cannot be less than 1, capping to 1.\n", min);
|
||||
min = 1;
|
||||
}
|
||||
|
||||
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;
|
||||
@ -92,6 +98,11 @@ uint64 BattlegroundDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
if (!this->asInt32(node, "MaxPlayers", max))
|
||||
return 0;
|
||||
|
||||
if (max < 1) {
|
||||
this->invalidWarning(node["MaxPlayers"], "Maximum players %d cannot be less than 1, capping to 1.\n", max);
|
||||
max = 1;
|
||||
}
|
||||
|
||||
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;
|
||||
@ -158,7 +169,77 @@ uint64 BattlegroundDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
bg->start_delay = delay;
|
||||
} else {
|
||||
if (!exists)
|
||||
bg->start_delay = 30;
|
||||
bg->start_delay = 0;
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "Join")) {
|
||||
const YAML::Node &joinNode = node["Join"];
|
||||
|
||||
if (this->nodeExists(joinNode, "Solo")) {
|
||||
bool active;
|
||||
|
||||
if (!this->asBool(joinNode, "Solo", active))
|
||||
return 0;
|
||||
|
||||
bg->solo = active;
|
||||
} else {
|
||||
if (!exists)
|
||||
bg->solo = true;
|
||||
}
|
||||
|
||||
if (this->nodeExists(joinNode, "Party")) {
|
||||
bool active;
|
||||
|
||||
if (!this->asBool(joinNode, "Party", active))
|
||||
return 0;
|
||||
|
||||
bg->party = active;
|
||||
} else {
|
||||
if (!exists)
|
||||
bg->party = true;
|
||||
}
|
||||
|
||||
if (this->nodeExists(joinNode, "Guild")) {
|
||||
bool active;
|
||||
|
||||
if (!this->asBool(joinNode, "Guild", active))
|
||||
return 0;
|
||||
|
||||
bg->guild = active;
|
||||
} else {
|
||||
if (!exists)
|
||||
bg->guild = true;
|
||||
}
|
||||
} else {
|
||||
if (!exists) {
|
||||
bg->solo = true;
|
||||
bg->party = true;
|
||||
bg->guild = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "JobRestrictions")) {
|
||||
const YAML::Node &jobsNode = node["JobRestrictions"];
|
||||
|
||||
for (const auto &jobit : jobsNode) {
|
||||
std::string job_name = jobit.first.as<std::string>(), job_name_constant = "JOB_" + job_name;
|
||||
int64 constant;
|
||||
|
||||
if (!script_get_constant(job_name_constant.c_str(), &constant)) {
|
||||
this->invalidWarning(node["JobRestrictions"], "Job %s does not exist.\n", job_name.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
bool active;
|
||||
|
||||
if (!this->asBool(jobsNode, job_name, active))
|
||||
return 0;
|
||||
|
||||
if (active)
|
||||
bg->job_restrictions.push_back(static_cast<int32>(constant));
|
||||
else
|
||||
util::vector_erase_if_exists(bg->job_restrictions, static_cast<int32>(constant));
|
||||
}
|
||||
}
|
||||
|
||||
if (this->nodeExists(node, "Locations")) {
|
||||
@ -174,9 +255,9 @@ uint64 BattlegroundDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
if (!this->asString(location, "Map", map_name))
|
||||
return 0;
|
||||
|
||||
map_entry.mapid = map_mapname2mapid(map_name.c_str());
|
||||
map_entry.mapindex = mapindex_name2id(map_name.c_str());
|
||||
|
||||
if (map_entry.mapid == -1) {
|
||||
if (map_entry.mapindex == 0) {
|
||||
this->invalidWarning(location["Map"], "Invalid battleground map name %s, skipping.\n", map_name.c_str());
|
||||
return 0;
|
||||
}
|
||||
@ -245,6 +326,18 @@ uint64 BattlegroundDatabase::parseBodyNode(const YAML::Node &node) {
|
||||
}
|
||||
}
|
||||
|
||||
if (this->nodeExists(team[it], "ActiveEvent")) {
|
||||
if (!this->asString(team[it], "ActiveEvent", team_ptr->active_event))
|
||||
return 0;
|
||||
|
||||
team_ptr->active_event.resize(EVENT_NAME_LENGTH);
|
||||
|
||||
if (team_ptr->active_event.find("::On") == std::string::npos) {
|
||||
this->invalidWarning(team["ActiveEvent"], "Battleground ActiveEvent label %s should begin with '::On', skipping.\n", team_ptr->active_event.c_str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->nodeExists(team[it], "Variable")) {
|
||||
if (!this->asString(team[it], "Variable", team_ptr->bg_id_var))
|
||||
return 0;
|
||||
@ -284,6 +377,21 @@ std::shared_ptr<s_battleground_type> bg_search_name(const char *name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a Battleground queue based on the given queue ID
|
||||
* @param queue_id: Queue ID
|
||||
* @return s_battleground_queue on success or nullptr on failure
|
||||
*/
|
||||
std::shared_ptr<s_battleground_queue> bg_search_queue(int queue_id)
|
||||
{
|
||||
for (const auto &queue : bg_queues) {
|
||||
if (queue_id == queue->queue_id)
|
||||
return queue;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for an available player in Battleground
|
||||
* @param bg: Battleground data
|
||||
@ -293,7 +401,12 @@ struct map_session_data* bg_getavailablesd(s_battleground_data *bg)
|
||||
{
|
||||
nullpo_retr(nullptr, bg);
|
||||
|
||||
return (bg->members.size() != 0) ? bg->members[0].sd : nullptr;
|
||||
for (const auto &member : bg->members) {
|
||||
if (member.sd != nullptr)
|
||||
return member.sd;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -514,7 +627,7 @@ int bg_create(uint16 mapindex, s_battleground_team* team)
|
||||
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();
|
||||
bg->active_event = team->active_event.c_str();
|
||||
|
||||
return bg->id;
|
||||
}
|
||||
@ -569,7 +682,7 @@ void bg_send_message(struct map_session_data *sd, const char *mes, int len)
|
||||
{
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (!sd->bg_id)
|
||||
if (sd->bg_id == 0)
|
||||
return;
|
||||
|
||||
std::shared_ptr<s_battleground_data> bgteam = util::umap_find(bg_team_db, sd->bg_id);
|
||||
@ -617,7 +730,7 @@ TIMER_FUNC(bg_send_xy_timer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a Battleground as ready to begin queuing
|
||||
* Mark a Battleground as ready to begin queuing for a free map
|
||||
* @param tid: Timer ID
|
||||
* @param tick: Timer
|
||||
* @param id: ID
|
||||
@ -625,14 +738,18 @@ TIMER_FUNC(bg_send_xy_timer)
|
||||
*/
|
||||
static TIMER_FUNC(bg_on_ready_loopback)
|
||||
{
|
||||
s_battleground_queue *queue = (s_battleground_queue*)data;
|
||||
int queue_id = (int)data;
|
||||
std::shared_ptr<s_battleground_queue> queue = bg_search_queue(queue_id);
|
||||
|
||||
nullpo_retr(1, queue);
|
||||
if (queue == nullptr) {
|
||||
ShowError("bg_on_ready_loopback: Invalid battleground queue %d.\n", queue_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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));
|
||||
bg_queue_on_ready(bg->name.c_str(), queue);
|
||||
return 0;
|
||||
} else {
|
||||
ShowError("bg_on_ready_loopback: Can't find battleground %d in the battlegrounds database.\n", queue->id);
|
||||
@ -641,7 +758,7 @@ static TIMER_FUNC(bg_on_ready_loopback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset Battleground queue data
|
||||
* Reset Battleground queue data if players don't accept in time
|
||||
* @param tid: Timer ID
|
||||
* @param tick: Timer
|
||||
* @param id: ID
|
||||
@ -649,31 +766,32 @@ static TIMER_FUNC(bg_on_ready_loopback)
|
||||
*/
|
||||
static TIMER_FUNC(bg_on_ready_expire)
|
||||
{
|
||||
s_battleground_queue *queue = (s_battleground_queue*)data;
|
||||
int queue_id = (int)data;
|
||||
std::shared_ptr<s_battleground_queue> queue = bg_search_queue(queue_id);
|
||||
|
||||
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
|
||||
if (queue == nullptr) {
|
||||
ShowError("bg_on_ready_expire: Invalid battleground queue %d.\n", queue_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
clif_bg_queue_entry_init(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);
|
||||
clif_bg_queue_entry_init(sd);
|
||||
}
|
||||
|
||||
bg_queue_clear(queue, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a Battleground
|
||||
* Start a Battleground when all players have accepted
|
||||
* @param tid: Timer ID
|
||||
* @param tick: Timer
|
||||
* @param id: ID
|
||||
@ -681,9 +799,13 @@ static TIMER_FUNC(bg_on_ready_expire)
|
||||
*/
|
||||
static TIMER_FUNC(bg_on_ready_start)
|
||||
{
|
||||
s_battleground_queue *queue = (s_battleground_queue*)data;
|
||||
int queue_id = (int)data;
|
||||
std::shared_ptr<s_battleground_queue> queue = bg_search_queue(queue_id);
|
||||
|
||||
nullpo_retr(1, queue);
|
||||
if (queue == nullptr) {
|
||||
ShowError("bg_on_ready_start: Invalid battleground queue %d.\n", queue_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
queue->tid_start = INVALID_TIMER;
|
||||
bg_queue_start_battleground(queue);
|
||||
@ -702,7 +824,7 @@ bool bg_player_is_in_bg_map(struct map_session_data *sd)
|
||||
|
||||
for (const auto &pair : battleground_db) {
|
||||
for (const auto &it : pair.second->maps) {
|
||||
if (it.mapid == sd->bl.m)
|
||||
if (it.mapindex == sd->mapindex)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -724,7 +846,7 @@ static bool bg_queue_check_status(struct map_session_data* sd, const char *name)
|
||||
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.
|
||||
sprintf(buf, msg_txt(sd, 339), static_cast<int32>((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;
|
||||
@ -732,9 +854,9 @@ static bool bg_queue_check_status(struct map_session_data* sd, const char *name)
|
||||
|
||||
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();
|
||||
int32 status_tick = static_cast<int32>(DIFF_TICK(get_timer(sd->sc.data[SC_ENTRY_QUEUE_NOTIFY_ADMISSION_TIME_OUT]->timer)->tick, gettick()) / 1000);
|
||||
|
||||
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.
|
||||
sprintf(buf, msg_txt(sd, 338), status_tick / 60, status_tick % 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;
|
||||
@ -755,43 +877,64 @@ bool bg_queue_check_joinable(std::shared_ptr<s_battleground_type> bg, struct map
|
||||
{
|
||||
nullpo_retr(false, sd);
|
||||
|
||||
if (bg->min_lvl && sd->status.base_level < bg->min_lvl) { // Check min level if min_lvl isn't 0
|
||||
for (const auto &job : bg->job_restrictions) { // Check class requirement
|
||||
if (sd->class_ == job) {
|
||||
clif_bg_queue_apply_result(BG_APPLY_PLAYER_CLASS, name, sd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bg->min_lvl > 0 && sd->status.base_level < bg->min_lvl) { // Check minimum level requirement
|
||||
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
|
||||
if (bg->max_lvl > 0 && sd->status.base_level > bg->max_lvl) { // Check maximum level requirement
|
||||
clif_bg_queue_apply_result(BG_APPLY_PLAYER_LEVEL, name, sd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bg_queue_check_status(sd, name))
|
||||
if (!bg_queue_check_status(sd, name)) // Check status blocks
|
||||
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.
|
||||
clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 337), false, SELF); // You can't apply to a battleground queue from this map.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // Return true if all conditions are met.
|
||||
if (battle_config.bgqueue_nowarp_mapflag > 0 && map_getmapflag(sd->bl.m, MF_NOWARP)) { // Check player's current position for mapflag check
|
||||
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 can't apply to a battleground queue from this map.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub function for reserving a slot in the Battleground if it's joinable
|
||||
* Mark a map as reserved for a Battleground
|
||||
* @param name: Battleground map name
|
||||
* @param state: Whether to mark reserved or not
|
||||
* @param ended: Whether the Battleground event is complete; players getting prize
|
||||
* @return True on success or false otherwise
|
||||
*/
|
||||
bool bg_queue_reservation(const char *name, bool state)
|
||||
bool bg_queue_reservation(const char *name, bool state, bool ended)
|
||||
{
|
||||
int16 mapid = map_mapname2mapid(name);
|
||||
uint16 mapindex = mapindex_name2id(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;
|
||||
for (auto &pair : battleground_db) {
|
||||
for (auto &map : pair.second->maps) {
|
||||
if (map.mapindex == mapindex) {
|
||||
map.isReserved = state;
|
||||
for (auto &queue : bg_queues) {
|
||||
if (queue->map == &map) {
|
||||
if (ended) // The ended flag is applied from bg_reserve (bg_unbook clears it for the next queue)
|
||||
queue->state = QUEUE_STATE_ENDED;
|
||||
if (!state)
|
||||
bg_queue_clear(queue, true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -800,6 +943,33 @@ bool bg_queue_reservation(const char *name, bool state)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join as an individual into a Battleground
|
||||
* @param name: Battleground name
|
||||
* @param sd: Player who requested to join the battlegrounds
|
||||
*/
|
||||
void bg_queue_join_solo(const char *name, struct map_session_data *sd)
|
||||
{
|
||||
if (!sd) {
|
||||
ShowError("bg_queue_join_solo: Tried to join non-existent player\n.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
|
||||
|
||||
if (!bg) {
|
||||
ShowWarning("bq_queue_join_solo: 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;
|
||||
}
|
||||
|
||||
if (!bg->solo) {
|
||||
clif_bg_queue_apply_result(BG_APPLY_INVALID_APP, name, sd);
|
||||
return;
|
||||
}
|
||||
|
||||
bg_queue_join_multi(name, sd, { sd }); // Join as solo
|
||||
}
|
||||
|
||||
/**
|
||||
* Join a party onto the same side of a Battleground
|
||||
* @param name: Battleground name
|
||||
@ -807,6 +977,11 @@ bool bg_queue_reservation(const char *name, bool state)
|
||||
*/
|
||||
void bg_queue_join_party(const char *name, struct map_session_data *sd)
|
||||
{
|
||||
if (!sd) {
|
||||
ShowError("bg_queue_join_party: Tried to join non-existent player\n.");
|
||||
return;
|
||||
}
|
||||
|
||||
struct party_data *p = party_search(sd->status.party_id);
|
||||
|
||||
if (!p) {
|
||||
@ -824,6 +999,11 @@ void bg_queue_join_party(const char *name, struct map_session_data *sd)
|
||||
std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
|
||||
|
||||
if (bg) {
|
||||
if (!bg->party) {
|
||||
clif_bg_queue_apply_result(BG_APPLY_INVALID_APP, name, sd);
|
||||
return;
|
||||
}
|
||||
|
||||
int p_online = 0;
|
||||
|
||||
for (const auto &it : p->party.member) {
|
||||
@ -835,7 +1015,7 @@ void bg_queue_join_party(const char *name, struct map_session_data *sd)
|
||||
clif_bg_queue_apply_result(BG_APPLY_PLAYER_COUNT, name, sd);
|
||||
return; // Too many party members online
|
||||
}
|
||||
|
||||
|
||||
std::vector<struct map_session_data *> list;
|
||||
|
||||
for (const auto &it : p->party.member) {
|
||||
@ -865,6 +1045,11 @@ void bg_queue_join_party(const char *name, struct map_session_data *sd)
|
||||
*/
|
||||
void bg_queue_join_guild(const char *name, struct map_session_data *sd)
|
||||
{
|
||||
if (!sd) {
|
||||
ShowError("bg_queue_join_guild: Tried to join non-existent player\n.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sd->guild) {
|
||||
clif_bg_queue_apply_result(BG_APPLY_INVALID_APP, name, sd);
|
||||
return; // Someone has bypassed the client check for being in a guild
|
||||
@ -878,6 +1063,11 @@ void bg_queue_join_guild(const char *name, struct map_session_data *sd)
|
||||
std::shared_ptr<s_battleground_type> bg = bg_search_name(name);
|
||||
|
||||
if (bg) {
|
||||
if (!bg->guild) {
|
||||
clif_bg_queue_apply_result(BG_APPLY_INVALID_APP, name, sd);
|
||||
return;
|
||||
}
|
||||
|
||||
struct guild* g = sd->guild;
|
||||
|
||||
if (g->connect_member > bg->max_players) {
|
||||
@ -932,43 +1122,55 @@ void bg_queue_join_multi(const char *name, struct map_session_data *sd, std::vec
|
||||
}
|
||||
|
||||
for (const auto &queue : bg_queues) {
|
||||
if (queue->id != bg->id)
|
||||
continue;
|
||||
if (queue->in_ready_state)
|
||||
if (queue->id != bg->id || queue->state == QUEUE_STATE_SETUP_DELAY || queue->state == QUEUE_STATE_ENDED)
|
||||
continue;
|
||||
|
||||
// Make sure there's enough space on one side to join as a party/guild in this queue
|
||||
if (queue->teama_members.size() + list.size() > bg->required_players && queue->teamb_members.size() + list.size() > bg->required_players) {
|
||||
if (queue->teama_members.size() + list.size() > bg->max_players && queue->teamb_members.size() + list.size() > bg->max_players) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool r = rnd() % 2 != 0;
|
||||
std::vector<map_session_data *>* team = r ? &queue->teamb_members : &queue->teama_members;
|
||||
std::vector<map_session_data *> *team = r ? &queue->teamb_members : &queue->teama_members;
|
||||
|
||||
// If the designated team is full, put the player into the other team
|
||||
if (team->size() + list.size() > bg->required_players) {
|
||||
team = r ? &queue->teama_members : &queue->teamb_members;
|
||||
if (queue->state == QUEUE_STATE_ACTIVE) {
|
||||
// If one team has lesser members try to balance (on an active BG)
|
||||
if (r && queue->teama_members.size() < queue->teamb_members.size())
|
||||
team = &queue->teama_members;
|
||||
else if (!r && queue->teamb_members.size() < queue->teama_members.size())
|
||||
team = &queue->teamb_members;
|
||||
} else {
|
||||
// If the designated team is full, put the player into the other team
|
||||
if (team->size() + list.size() > bg->required_players)
|
||||
team = r ? &queue->teama_members : &queue->teamb_members;
|
||||
}
|
||||
|
||||
while (!list.empty() && team->size() < bg->required_players) {
|
||||
while (!list.empty() && team->size() < bg->max_players) {
|
||||
struct map_session_data *sd2 = list.back();
|
||||
|
||||
list.pop_back();
|
||||
|
||||
if (!sd2 || sd2->bg_queue)
|
||||
if (!sd2 || sd2->bg_queue_id > 0)
|
||||
continue;
|
||||
|
||||
if (!bg_queue_check_joinable(bg, sd2, name))
|
||||
continue;
|
||||
|
||||
sd2->bg_queue = queue;
|
||||
sd2->bg_queue_id = queue->queue_id;
|
||||
team->push_back(sd2);
|
||||
clif_bg_queue_apply_result(BG_APPLY_ACCEPT, name, sd2);
|
||||
clif_bg_queue_apply_notify(name, sd2);
|
||||
}
|
||||
|
||||
// Enough players have joined
|
||||
if (queue->teamb_members.size() == bg->required_players && queue->teama_members.size() == bg->required_players)
|
||||
if (queue->state == QUEUE_STATE_ACTIVE) { // Battleground is already active
|
||||
for (auto &pl_sd : *team) {
|
||||
if (queue->map->mapindex == pl_sd->mapindex)
|
||||
continue;
|
||||
|
||||
pc_set_bg_queue_timer(pl_sd);
|
||||
clif_bg_queue_lobby_notify(name, pl_sd);
|
||||
}
|
||||
} else if (queue->state == QUEUE_STATE_SETUP && queue->teamb_members.size() >= bg->required_players && queue->teama_members.size() >= bg->required_players) // Enough players have joined
|
||||
bg_queue_on_ready(name, queue);
|
||||
|
||||
return;
|
||||
@ -981,10 +1183,11 @@ void bg_queue_join_multi(const char *name, struct map_session_data *sd, std::vec
|
||||
/**
|
||||
* Clear Battleground queue for next one
|
||||
* @param queue: Queue to clean up
|
||||
* @param ended: If a Battleground has ended through normal means (by script command bg_unbook)
|
||||
*/
|
||||
static void bg_queue_clear(s_battleground_queue *queue)
|
||||
void bg_queue_clear(std::shared_ptr<s_battleground_queue> queue, bool ended)
|
||||
{
|
||||
if (!queue)
|
||||
if (queue == nullptr)
|
||||
return;
|
||||
|
||||
if (queue->tid_requeue != INVALID_TIMER) {
|
||||
@ -1002,49 +1205,47 @@ static void bg_queue_clear(s_battleground_queue *queue)
|
||||
queue->tid_start = INVALID_TIMER;
|
||||
}
|
||||
|
||||
if (queue->map != nullptr) {
|
||||
queue->map->isReserved = false; // Remove reservation to free up for future queue
|
||||
queue->map = nullptr;
|
||||
if (ended) {
|
||||
if (queue->map != nullptr) {
|
||||
queue->map->isReserved = false; // Remove reservation to free up for future queue
|
||||
queue->map = nullptr;
|
||||
}
|
||||
|
||||
for (const auto &sd : queue->teama_members)
|
||||
sd->bg_queue_id = 0;
|
||||
|
||||
for (const auto &sd : queue->teamb_members)
|
||||
sd->bg_queue_id = 0;
|
||||
|
||||
queue->teama_members.clear();
|
||||
queue->teamb_members.clear();
|
||||
queue->teama_members.shrink_to_fit();
|
||||
queue->teamb_members.shrink_to_fit();
|
||||
queue->accepted_players = 0;
|
||||
queue->state = QUEUE_STATE_SETUP;
|
||||
}
|
||||
queue->in_ready_state = false;
|
||||
queue->accepted_players = 0; // Reset the queue count
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param members: List of players in 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)
|
||||
static bool bg_queue_leave_sub(struct map_session_data *sd, std::vector<map_session_data *> &members)
|
||||
{
|
||||
if (!sd)
|
||||
return false;
|
||||
|
||||
auto list_it = lista.begin();
|
||||
auto list_it = members.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;
|
||||
}
|
||||
|
||||
lista.erase(list_it);
|
||||
|
||||
if (lista.empty() && listb.empty()) { // If there are no players left in the queue, discard it
|
||||
for (auto &queue : bg_queues) {
|
||||
if (sd->bg_queue == queue)
|
||||
bg_queue_clear(queue.get());
|
||||
}
|
||||
}
|
||||
while (list_it != members.end()) {
|
||||
if (*list_it == sd) {
|
||||
members.erase(list_it);
|
||||
|
||||
sc_start(nullptr, &sd->bl, SC_ENTRY_QUEUE_APPLY_DELAY, 100, 1, 60000);
|
||||
sd->bg_queue = nullptr;
|
||||
sd->bg_queue_id = 0;
|
||||
pc_delete_bg_queue_timer(sd);
|
||||
return true;
|
||||
} else {
|
||||
list_it++;
|
||||
@ -1061,14 +1262,26 @@ static bool bg_queue_leave_sub(struct map_session_data *sd, std::vector<map_sess
|
||||
*/
|
||||
bool bg_queue_leave(struct map_session_data *sd)
|
||||
{
|
||||
if (!sd || !sd->bg_queue)
|
||||
if (!sd || sd->bg_queue_id == 0)
|
||||
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;
|
||||
pc_delete_bg_queue_timer(sd);
|
||||
|
||||
for (auto &queue : bg_queues) {
|
||||
if (sd->bg_queue_id == queue->queue_id) {
|
||||
if (!bg_queue_leave_sub(sd, queue->teama_members) && !bg_queue_leave_sub(sd, queue->teamb_members)) {
|
||||
ShowError("bg_queue_leave: Couldn't find player %s in battlegrounds queue.\n", sd->status.name);
|
||||
return false;
|
||||
} else {
|
||||
if ((queue->state == QUEUE_STATE_SETUP || queue->state == QUEUE_STATE_SETUP_DELAY) && queue->teama_members.empty() && queue->teamb_members.empty()) // If there are no players left in the queue (that hasn't started), discard it
|
||||
bg_queue_clear(queue, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1086,29 +1299,27 @@ bool bg_queue_on_ready(const char *name, std::shared_ptr<s_battleground_queue> q
|
||||
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)
|
||||
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;
|
||||
bool map_reserved = false;
|
||||
|
||||
for (auto &it : bg->maps) {
|
||||
if (!it.isReserved) {
|
||||
it.isReserved = true;
|
||||
bgmap = ⁢
|
||||
queue->map = ⁢
|
||||
for (auto &map : bg->maps) {
|
||||
if (!map.isReserved) {
|
||||
map.isReserved = true;
|
||||
map_reserved = true;
|
||||
queue->map = ↦
|
||||
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());
|
||||
if (!map_reserved) { // 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->queue_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
queue->in_ready_state = true;
|
||||
queue->tid_expire = add_timer(gettick() + 20000, bg_on_ready_expire, 0, (intptr_t)queue.get());
|
||||
queue->state = QUEUE_STATE_SETUP_DELAY;
|
||||
queue->tid_expire = add_timer(gettick() + 20000, bg_on_ready_expire, 0, (intptr_t)queue->queue_id);
|
||||
|
||||
for (const auto &sd : queue->teama_members)
|
||||
clif_bg_queue_lobby_notify(name, sd);
|
||||
@ -1119,25 +1330,150 @@ bool bg_queue_on_ready(const char *name, std::shared_ptr<s_battleground_queue> q
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a player into an active Battleground
|
||||
* @param sd: Player to send in
|
||||
* @param queue: Queue data
|
||||
*/
|
||||
void bg_join_active(map_session_data *sd, std::shared_ptr<s_battleground_queue> queue)
|
||||
{
|
||||
if (sd == nullptr || queue == nullptr)
|
||||
return;
|
||||
|
||||
// Check player's current position for mapflag check
|
||||
if (battle_config.bgqueue_nowarp_mapflag > 0 && map_getmapflag(sd->bl.m, MF_NOWARP)) {
|
||||
clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 337), false, SELF); // You can't apply to a battleground queue from this map.
|
||||
bg_queue_leave(sd);
|
||||
clif_bg_queue_entry_init(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
int bg_id_team_1 = static_cast<int>(mapreg_readreg(add_str(queue->map->team1.bg_id_var.c_str())));
|
||||
std::shared_ptr<s_battleground_data> bgteam_1 = util::umap_find(bg_team_db, bg_id_team_1);
|
||||
|
||||
for (auto &pl_sd : queue->teama_members) {
|
||||
if (sd != pl_sd)
|
||||
continue;
|
||||
|
||||
if (bgteam_1 == nullptr) {
|
||||
bg_queue_leave(sd);
|
||||
clif_bg_queue_apply_result(BG_APPLY_RECONNECT, battleground_db.find(queue->id)->name.c_str(), sd);
|
||||
clif_bg_queue_entry_init(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
clif_bg_queue_entry_init(pl_sd);
|
||||
bg_team_join(bg_id_team_1, pl_sd, true);
|
||||
npc_event(pl_sd, bgteam_1->active_event.c_str(), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
int bg_id_team_2 = static_cast<int>(mapreg_readreg(add_str(queue->map->team2.bg_id_var.c_str())));
|
||||
std::shared_ptr<s_battleground_data> bgteam_2 = util::umap_find(bg_team_db, bg_id_team_2);
|
||||
|
||||
for (auto &pl_sd : queue->teamb_members) {
|
||||
if (sd != pl_sd)
|
||||
continue;
|
||||
|
||||
if (bgteam_2 == nullptr) {
|
||||
bg_queue_leave(sd);
|
||||
clif_bg_queue_apply_result(BG_APPLY_RECONNECT, battleground_db.find(queue->id)->name.c_str(), sd);
|
||||
clif_bg_queue_entry_init(sd);
|
||||
return;
|
||||
}
|
||||
|
||||
clif_bg_queue_entry_init(pl_sd);
|
||||
bg_team_join(bg_id_team_2, pl_sd, true);
|
||||
npc_event(pl_sd, bgteam_2->active_event.c_str(), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if any players in the queue are on a map with MF_NOWARP and remove them from the queue
|
||||
* @param queue: Queue data
|
||||
* @return True if the player is on a map with MF_NOWARP or false otherwise
|
||||
*/
|
||||
bool bg_mapflag_check(std::shared_ptr<s_battleground_queue> queue) {
|
||||
if (queue == nullptr || battle_config.bgqueue_nowarp_mapflag == 0)
|
||||
return false;
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (const auto &sd : queue->teama_members) {
|
||||
if (map_getmapflag(sd->bl.m, MF_NOWARP)) {
|
||||
clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 337), false, SELF); // You can't apply to a battleground queue from this map.
|
||||
bg_queue_leave(sd);
|
||||
clif_bg_queue_entry_init(sd);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &sd : queue->teamb_members) {
|
||||
if (map_getmapflag(sd->bl.m, MF_NOWARP)) {
|
||||
clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 337), false, SELF); // You can't apply to a battleground queue from this map.
|
||||
bg_queue_leave(sd);
|
||||
clif_bg_queue_entry_init(sd);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
queue->state = QUEUE_STATE_SETUP; // Set back to queueing state
|
||||
queue->accepted_players = 0; // Reset acceptance count
|
||||
|
||||
// Free map to avoid creating a reservation delay
|
||||
if (queue->map != nullptr) {
|
||||
queue->map->isReserved = false;
|
||||
queue->map = nullptr;
|
||||
}
|
||||
|
||||
// Announce failure to remaining players
|
||||
for (const auto &sd : queue->teama_members)
|
||||
clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 340), false, SELF); // Participants were unable to join. Delaying entry for more participants.
|
||||
|
||||
for (const auto &sd : queue->teamb_members)
|
||||
clif_messagecolor(&sd->bl, color_table[COLOR_LIGHT_GREEN], msg_txt(sd, 340), false, SELF); // Participants were unable to join. Delaying entry for more participants.
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
void bg_queue_on_accept_invite(struct map_session_data *sd)
|
||||
{
|
||||
nullpo_retv(sd);
|
||||
|
||||
sd->bg_queue_accept_state = true;
|
||||
std::shared_ptr<s_battleground_queue> queue = bg_search_queue(sd->bg_queue_id);
|
||||
|
||||
if (queue == nullptr) {
|
||||
ShowError("bg_queue_on_accept_invite: Couldn't find player %s in battlegrounds queue.\n", sd->status.name);
|
||||
return;
|
||||
}
|
||||
|
||||
queue->accepted_players++;
|
||||
clig_bg_queue_ack_lobby(true, map_mapid2mapname(queue->map->mapid), map_mapid2mapname(queue->map->mapid), sd);
|
||||
clif_bg_queue_ack_lobby(true, mapindex_id2name(queue->map->mapindex), mapindex_id2name(queue->map->mapindex), 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->state == QUEUE_STATE_ACTIVE) // Battleground is already active
|
||||
bg_join_active(sd, queue);
|
||||
else if (queue->state == QUEUE_STATE_SETUP_DELAY) {
|
||||
if (queue->accepted_players == queue->required_players * 2) {
|
||||
if (queue->tid_expire != INVALID_TIMER) {
|
||||
delete_timer(queue->tid_expire, bg_on_ready_expire);
|
||||
queue->tid_expire = INVALID_TIMER;
|
||||
}
|
||||
|
||||
if (queue->tid_expire != INVALID_TIMER) {
|
||||
delete_timer(queue->tid_expire, bg_on_ready_expire);
|
||||
queue->tid_expire = INVALID_TIMER;
|
||||
// Check player's current position for mapflag check
|
||||
if (battle_config.bgqueue_nowarp_mapflag > 0 && bg_mapflag_check(queue))
|
||||
return;
|
||||
|
||||
queue->tid_start = add_timer(gettick() + battleground_db.find(queue->id)->start_delay * 1000, bg_on_ready_start, 0, (intptr_t)queue->queue_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1146,31 +1482,33 @@ void bg_queue_on_accept_invite(std::shared_ptr<s_battleground_queue> queue, stru
|
||||
* Begin the Battleground from the given queue
|
||||
* @param queue: Battleground queue
|
||||
*/
|
||||
void bg_queue_start_battleground(s_battleground_queue *queue)
|
||||
void bg_queue_start_battleground(std::shared_ptr<s_battleground_queue> queue)
|
||||
{
|
||||
if (queue == nullptr)
|
||||
return;
|
||||
|
||||
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;
|
||||
bg_queue_clear(queue, true);
|
||||
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);
|
||||
// Check player's current position for mapflag check
|
||||
if (battle_config.bgqueue_nowarp_mapflag > 0 && bg_mapflag_check(queue))
|
||||
return;
|
||||
|
||||
uint16 map_idx = queue->map->mapindex;
|
||||
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);
|
||||
}
|
||||
@ -1178,11 +1516,9 @@ void bg_queue_start_battleground(s_battleground_queue *queue)
|
||||
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();
|
||||
bg_queue_clear(queue);
|
||||
queue->state = QUEUE_STATE_ACTIVE;
|
||||
|
||||
bg_queue_clear(queue, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1195,13 +1531,14 @@ static void bg_queue_create(int bg_id, int req_players)
|
||||
{
|
||||
auto queue = std::make_shared<s_battleground_queue>();
|
||||
|
||||
queue->queue_id = bg_queue_count++;
|
||||
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;
|
||||
queue->state = QUEUE_STATE_SETUP;
|
||||
|
||||
bg_queues.push_back(queue);
|
||||
}
|
||||
|
@ -27,32 +27,43 @@ struct s_battleground_data {
|
||||
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
|
||||
std::string active_event; ///< NPC Event to call on players joining an active battleground
|
||||
};
|
||||
|
||||
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
|
||||
active_event, ///< Team NPC Event to call on players joining an active battleground
|
||||
bg_id_var; ///< Team NPC variable name
|
||||
};
|
||||
|
||||
struct s_battleground_map {
|
||||
int id; ///< Battleground ID
|
||||
int16 mapid; ///< ID of the map
|
||||
uint16 mapindex; ///< Index 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
|
||||
};
|
||||
|
||||
/// Enum for queue state tracking
|
||||
enum e_queue_state : uint16 {
|
||||
QUEUE_STATE_SETUP = 0, ///< The initial setup of a queue (a required amount of players hasn't been met)
|
||||
QUEUE_STATE_SETUP_DELAY, ///< The initial setup of a queue but a required amount of players have accepted and the delay timer is active
|
||||
QUEUE_STATE_ACTIVE, ///< The queue is active script side and more players can join (players may or may not be on the field)
|
||||
QUEUE_STATE_ENDED, ///< The queue is no longer joinable (players are getting prizes)
|
||||
};
|
||||
|
||||
/// Battlegrounds client interface queue system [MasterOfMuppets]
|
||||
struct s_battleground_queue {
|
||||
int queue_id; ///< Battlegrounds Queue ID
|
||||
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?
|
||||
e_queue_state state; ///< See @e_queue_state
|
||||
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
|
||||
@ -69,6 +80,10 @@ struct s_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)
|
||||
bool solo; ///< Ability to join a queue as an individual.
|
||||
bool party; ///< Ability to join a queue as a party.
|
||||
bool guild; ///< Ability to join a queue as a guild.
|
||||
std::vector<int32> job_restrictions; ///< List of jobs that are unable to join.
|
||||
};
|
||||
|
||||
/// Enum of responses when applying for a Battleground
|
||||
@ -109,15 +124,17 @@ public:
|
||||
|
||||
extern BattlegroundDatabase battleground_db;
|
||||
extern std::unordered_map<int, std::shared_ptr<s_battleground_data>> bg_team_db;
|
||||
extern std::vector<std::shared_ptr<s_battleground_queue>> bg_queues;
|
||||
|
||||
std::shared_ptr<s_battleground_type> bg_search_name(const char *name);
|
||||
std::shared_ptr<s_battleground_queue> bg_search_queue(int queue_id);
|
||||
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(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))
|
||||
bool bg_queue_reservation(const char *name, bool state, bool ended);
|
||||
#define bg_queue_reserve(name, end) (bg_queue_reservation(name, true, end))
|
||||
#define bg_queue_unbook(name) (bg_queue_reservation(name, false, 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);
|
||||
@ -126,13 +143,15 @@ 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);
|
||||
void bg_queue_join_solo(const char *name, struct map_session_data *sd);
|
||||
void bg_queue_join_party(const char *name, struct map_session_data *sd);
|
||||
void bg_queue_join_guild(const char *name, struct map_session_data *sd);
|
||||
void bg_queue_join_multi(const char *name, struct map_session_data *sd, std::vector<map_session_data *> list);
|
||||
void bg_queue_clear(std::shared_ptr<s_battleground_queue> queue, bool ended);
|
||||
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(s_battleground_queue *queue);
|
||||
void bg_queue_on_accept_invite(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);
|
||||
|
||||
|
@ -609,13 +609,12 @@ 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 = util::umap_find(bg_team_db, sd->bg_id)))
|
||||
if( sd && sd->bg_id > 0 && (bg = util::umap_find(bg_team_db, sd->bg_id)))
|
||||
{
|
||||
for( i = 0; i < bg->members.size(); i++ )
|
||||
{
|
||||
if( (sd = bg->members[i].sd) == NULL || !(fd = sd->fd) )
|
||||
for (const auto &member : bg->members) {
|
||||
if((sd = member.sd) == nullptr || (fd = sd->fd) == 0)
|
||||
continue;
|
||||
if( sd->bl.id == bl->id && (type == BG_WOS || type == BG_SAMEMAP_WOS || type == BG_AREA_WOS) )
|
||||
if(sd->bl.id == bl->id && (type == BG_WOS || type == BG_SAMEMAP_WOS || type == BG_AREA_WOS) )
|
||||
continue;
|
||||
if( type != BG && type != BG_WOS && sd->bl.m != bl->m )
|
||||
continue;
|
||||
@ -17630,12 +17629,12 @@ void clif_parse_bg_queue_apply_request(int fd, struct map_session_data *sd)
|
||||
|
||||
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);
|
||||
if (sd->bg_queue_id > 0) {
|
||||
//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
|
||||
bg_queue_join_multi(name, sd, { sd });
|
||||
bg_queue_join_solo(name, sd);
|
||||
else if (type == 2) // Party
|
||||
bg_queue_join_party(name, sd);
|
||||
else if (type == 4) // Guild
|
||||
@ -17670,9 +17669,9 @@ 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;
|
||||
std::shared_ptr<s_battleground_queue> queue = bg_search_queue(sd->bg_queue_id);
|
||||
|
||||
if (!queue) {
|
||||
if (queue == nullptr) {
|
||||
ShowError("clif_bg_queue_apply_notify: Player is not in a battleground queue.\n");
|
||||
return;
|
||||
}
|
||||
@ -17712,8 +17711,10 @@ void clif_parse_bg_queue_cancel_request(int fd, struct map_session_data *sd)
|
||||
|
||||
bool success;
|
||||
|
||||
if (sd->bg_queue) {
|
||||
if (sd->bg_queue->in_ready_state)
|
||||
if (sd->bg_queue_id > 0) {
|
||||
std::shared_ptr<s_battleground_queue> queue = bg_search_queue(sd->bg_queue_id);
|
||||
|
||||
if (queue && queue->state == QUEUE_STATE_SETUP_DELAY)
|
||||
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);
|
||||
@ -17751,11 +17752,11 @@ void clif_parse_bg_queue_lobby_reply(int fd, struct map_session_data *sd)
|
||||
{
|
||||
nullpo_retv(sd);
|
||||
|
||||
if(sd->bg_queue) {
|
||||
if(sd->bg_queue_id > 0) {
|
||||
uint8 result = RFIFOB(fd, 2);
|
||||
|
||||
if(result == 1) { // Accept
|
||||
bg_queue_on_accept_invite(sd->bg_queue, sd);
|
||||
bg_queue_on_accept_invite(sd);
|
||||
} else if(result == 2) { // Decline
|
||||
bg_queue_leave(sd);
|
||||
clif_bg_queue_entry_init(sd);
|
||||
@ -17765,7 +17766,7 @@ void clif_parse_bg_queue_lobby_reply(int fd, struct map_session_data *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)
|
||||
void clif_bg_queue_ack_lobby(bool result, const char *name, const char *lobbyname, struct map_session_data *sd)
|
||||
{
|
||||
nullpo_retv(sd);
|
||||
|
||||
|
@ -833,7 +833,7 @@ void clif_bg_queue_apply_result(e_bg_queue_apply_ack result, const char *name, s
|
||||
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);
|
||||
void clif_bg_queue_ack_lobby(bool result, const char *name, const char *lobbyname, struct map_session_data *sd);
|
||||
|
||||
// Instancing
|
||||
void clif_instance_create(int instance_id, int num);
|
||||
|
@ -2063,7 +2063,7 @@ int map_quit(struct map_session_data *sd) {
|
||||
if (sd->bg_id)
|
||||
bg_team_leave(sd, true, true);
|
||||
|
||||
if (sd->bg_queue != nullptr)
|
||||
if (sd->bg_queue_id > 0)
|
||||
bg_queue_leave(sd);
|
||||
|
||||
if( sd->status.clan_id )
|
||||
|
@ -354,6 +354,54 @@ int pc_get_group_level(struct map_session_data *sd) {
|
||||
return sd->group_level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a player from queue after timeout
|
||||
* @param tid: Timer ID
|
||||
* @param tick: Timer
|
||||
* @param id: ID
|
||||
* @return 0 on success or 1 otherwise
|
||||
*/
|
||||
static TIMER_FUNC(pc_on_expire_active)
|
||||
{
|
||||
map_session_data *sd = (map_session_data *)data;
|
||||
|
||||
nullpo_retr(1, sd);
|
||||
|
||||
sd->tid_queue_active = INVALID_TIMER;
|
||||
|
||||
bg_queue_leave(sd);
|
||||
clif_bg_queue_entry_init(sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to set timer externally
|
||||
* @param sd: Player data
|
||||
*/
|
||||
void pc_set_bg_queue_timer(map_session_data *sd) {
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (sd->tid_queue_active != INVALID_TIMER) {
|
||||
delete_timer(sd->tid_queue_active, pc_on_expire_active);
|
||||
sd->tid_queue_active = INVALID_TIMER;
|
||||
}
|
||||
|
||||
sd->tid_queue_active = add_timer(gettick() + 20000, pc_on_expire_active, 0, (intptr_t)sd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to delete timer externally
|
||||
* @param sd: Player data
|
||||
*/
|
||||
void pc_delete_bg_queue_timer(map_session_data *sd) {
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (sd->tid_queue_active != INVALID_TIMER) {
|
||||
delete_timer(sd->tid_queue_active, pc_on_expire_active);
|
||||
sd->tid_queue_active = INVALID_TIMER;
|
||||
}
|
||||
}
|
||||
|
||||
static TIMER_FUNC(pc_invincible_timer){
|
||||
struct map_session_data *sd;
|
||||
|
||||
@ -1471,6 +1519,7 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
|
||||
sd->expiration_tid = INVALID_TIMER;
|
||||
sd->autotrade_tid = INVALID_TIMER;
|
||||
sd->respawn_tid = INVALID_TIMER;
|
||||
sd->tid_queue_active = INVALID_TIMER;
|
||||
|
||||
#ifdef SECURE_NPCTIMEOUT
|
||||
// Initialize to defaults/expected
|
||||
@ -1617,9 +1666,8 @@ 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;
|
||||
// Initialize BG queue
|
||||
sd->bg_queue_id = 0;
|
||||
|
||||
#if PACKETVER >= 20150513
|
||||
sd->hatEffectIDs = NULL;
|
||||
@ -13417,6 +13465,7 @@ void do_init_pc(void) {
|
||||
add_timer_func_list(pc_global_expiration_timer, "pc_global_expiration_timer");
|
||||
add_timer_func_list(pc_expiration_timer, "pc_expiration_timer");
|
||||
add_timer_func_list(pc_autotrade_timer, "pc_autotrade_timer");
|
||||
add_timer_func_list(pc_on_expire_active, "pc_on_expire_active");
|
||||
|
||||
add_timer(gettick() + autosave_interval, pc_autosave, 0, 0);
|
||||
|
||||
|
@ -634,10 +634,6 @@ 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)
|
||||
@ -668,7 +664,9 @@ struct map_session_data {
|
||||
int debug_line;
|
||||
const char* debug_func;
|
||||
|
||||
int bg_id;
|
||||
// Battlegrounds queue system [MasterOfMuppets]
|
||||
int bg_id, bg_queue_id;
|
||||
int tid_queue_active; ///< Timer ID associated with players joining an active BG
|
||||
|
||||
#ifdef SECURE_NPCTIMEOUT
|
||||
/**
|
||||
@ -1296,6 +1294,9 @@ struct sg_data {
|
||||
};
|
||||
extern const struct sg_data sg_info[MAX_PC_FEELHATE];
|
||||
|
||||
void pc_set_bg_queue_timer(map_session_data *sd);
|
||||
void pc_delete_bg_queue_timer(map_session_data *sd);
|
||||
|
||||
void pc_setinvincibletimer(struct map_session_data* sd, int val);
|
||||
void pc_delinvincibletimer(struct map_session_data* sd);
|
||||
|
||||
|
@ -20016,20 +20016,21 @@ BUILDIN_FUNC(bg_get_data)
|
||||
|
||||
/**
|
||||
* Reserves a slot for the given Battleground.
|
||||
* bg_reserve(<"bg_name">);
|
||||
* bg_reserve("<battleground_map_name>"{,<ended>});
|
||||
*/
|
||||
BUILDIN_FUNC(bg_reserve)
|
||||
{
|
||||
const char *str = script_getstr(st, 2);
|
||||
bool ended = script_hasdata(st, 3) ? script_getnum(st, 3) != 0 : false;
|
||||
|
||||
if (!bg_queue_reserve(str))
|
||||
if (!bg_queue_reserve(str, ended))
|
||||
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">);
|
||||
* bg_unbook("<battleground_map_name>");
|
||||
*/
|
||||
BUILDIN_FUNC(bg_unbook)
|
||||
{
|
||||
@ -20075,7 +20076,7 @@ BUILDIN_FUNC(bg_info)
|
||||
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_str(st, nullptr, ".@bgmaps$", i, mapindex_id2name(bg->maps[i].mapindex), nullptr);
|
||||
setd_sub_num(st, nullptr, ".@bgmapscount", 0, i, nullptr);
|
||||
script_pushint(st, i);
|
||||
break;
|
||||
@ -25143,7 +25144,7 @@ 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_reserve,"s?"),
|
||||
BUILDIN_DEF(bg_unbook,"s"),
|
||||
BUILDIN_DEF(bg_info,"si"),
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user