// this file contains the game logic of the fight club
function|script|fightclub_sendrequest
{
goto L_try;
L_try:
set @loop, 0;
goto L_Loop;
L_Loop:
if(@Duel_Queue$[@loop] == @caster_name$) goto L_Exists;
if((@Duel_Queue$[@loop] == "") && (@Duel_Queue$[(@loop + 1)] == "")) goto L_Proceed;
if((@Duel_Queue$[@loop] == "") && (@Duel_Queue$[(@loop + 1)] != "")) goto L_ShiftQueue;
set @loop, (@loop + 1);
if(@loop >= getarraysize(@Duel_Queue)) goto L_Full; // this shouldn't happen since we check in magic but we still handle it
goto L_Loop;
L_ShiftQueue:
set @Duel_Queue$[@loop], @Duel_Queue$[(@loop + 1)];
set @Duel_Queue[@loop], @Duel_Queue[(@loop + 1)];
set @Duel_Queue$[(@loop + 1)], "";
set @Duel_Queue[(@loop + 1)], 0;
set @loop, (@loop + 1);
if(@loop >= getarraysize(@Duel_Queue)) goto L_try;
goto L_ShiftQueue;
L_Full:
message @caster_name$, "There is already "+ $@Duel_PlayerQueueLimit +" duel request(s) in the queue of this player, which is the maximum.";
return;
L_Exists:
message @caster_name$, "You already requested a duel with this player.";
return;
L_Proceed:
misceffect FX_MAGIC_DARKRED, @caster_name$;
message @caster_name$, "Your request has been sent.";
set @Duel_Queue$[@loop], @caster_name$;
set @Duel_Queue[@loop], gettimetick(2);
if(@Duel_Fighter == 0) message strcharinfo(0), "You have received a new duel request. Talk to Rouge to accept or decline.";
if(@Duel_Fighter == 0) misceffect FX_MAGIC_DARKRED, strcharinfo(0);
if(@Duel_Fighter == 1) set @Duel_HasPendingRequest, 1;
return;
}
function|script|fightclub_getrules
{
set $@fightclub_myself, getcharid(3);
if(@target < 1) goto L_Proceed; // get our own rules
if(attachrid(@target) == 1) goto L_Proceed;
goto L_Missing;
L_Proceed:
set $@Temp_NoMagic, (DUELS & $@NoMagicBit);
if($@fightclub_myself == getcharid(3)) goto L_Proceed2; // the target is ourselves
if(attachrid($@fightclub_myself) == 1) goto L_Proceed2;
goto L_Missing;
L_Missing:
end;
L_Proceed2:
set $@fightclub_myself, 0;
set @target, 0;
if($@Temp_NoMagic == 0)
mes "(no rules)";
if($@Temp_NoMagic != 0) mes "- No Magic";
set $@Temp_NoMagic, 0; // now we clean these vars ASAP because they're globals
return;
}
// ** called when someone agree to duel
function|script|fightclub_AddToQueue
{
set @ATQ_Loop, 0;
goto L_Loop;
L_Loop:
if(($@Duel_Queue_Blue$[@ATQ_Loop] == @caster_name$) && ($@Duel_Queue_Red$[@ATQ_Loop] == @target_name$)) goto L_Exists;
if(($@Duel_Queue_Red$[@ATQ_Loop] == @caster_name$) && ($@Duel_Queue_Blue$[@ATQ_Loop] == @target_name$)) goto L_Exists;
set @ATQ_Loop, (@ATQ_Loop + 1);
if(@ATQ_Loop >= getarraysize($@Duel_Queue_ID)) goto L_Proceed2;
goto L_Loop;
L_Exists:
mes "This battle is already in the queue.";
return;
L_Full:
mes "There is already " + $@Duel_QueueLimit + " battles in the queue, which is the maximum. Please try again later.";
return;
L_Proceed2:
if(getarraysize($@Duel_Queue_ID) >= ($@Duel_QueueLimit + 1)) goto L_Full;
set @index, getarraysize($@Duel_Queue_ID);
if(@index >= 1) goto L_Proceed22;
set @index, 1;
goto L_Proceed22;
L_Proceed22:
if($@Duel_Queue_Red$[@index] != "") goto L_NotClean;
set $@Duel_Queue_Red$[@index], @caster_name$;
if($@Duel_Queue_Blue$[@index] != "") goto L_NotClean;
set $@Duel_Queue_Blue$[@index], @target_name$;
if($@Duel_Queue_ID[@index] != 0) goto L_NotClean;
set $@Duel_Queue_ID[@index], ($@Duel_Queue_ID[(@index - 1)] + 1);
if($@Duel_Queue_ID[@index] <= $Duel_LastDuel) goto L_FixId;
return;
L_NotClean:
message @caster_name$, "An error occured: array element not empty. Try again in 5 seconds.";
return;
L_FixId:
set $@Duel_Queue_ID[@index], ($Duel_LastDuel + 1);
return;
}
// ** called when a duel is finished
function|script|fightclub_NextBattle
{
set $@Duel_Queue_Blue$[0], ""; // clean the 0 index
set $@Duel_Queue_Red$[0], "";
set $@Duel_Queue_ID[0], 0;
set $@Duel_Loop, 1; // start the loop at 1
goto L_Loop;
L_Loop: // here we shift the array to the left
if($@Duel_Queue_ID[$@Duel_Loop] < 1) goto L_Empty;
set $@Duel_Queue_Red$[($@Duel_Loop - 1)], $@Duel_Queue_Red$[$@Duel_Loop];
set $@Duel_Queue_Red$[$@Duel_Loop], ""; // it is always important to clean
set $@Duel_Queue_Blue$[($@Duel_Loop - 1)], $@Duel_Queue_Blue$[$@Duel_Loop];
set $@Duel_Queue_Blue$[$@Duel_Loop], "";
set $@Duel_Queue_ID[($@Duel_Loop - 1)], $@Duel_Queue_ID[$@Duel_Loop];
set $@Duel_Queue_ID[$@Duel_Loop], 0;
set $@Duel_Loop, ($@Duel_Loop + 1);
if($@Duel_Loop >= getarraysize($@Duel_Queue_ID)) goto L_Proceed;
goto L_Loop;
L_Empty:
// the queue is now empty
return;
L_Proceed:
callfunc "fightclub_CleanStage";
set $@Duel_CurrentDuel, $@Duel_Queue_ID[0]; // since the array is shifted, the index is always 0
set $Duel_LastDuel, $@Duel_Queue_ID[0]; // this is used to keep the same index across reboots
set $@Duel_BluePlayer, getcharid(3,$@Duel_Queue_Blue$[0]);
set $@Duel_RedPlayer, getcharid(3,$@Duel_Queue_Red$[0]);
if(attachrid($@Duel_BluePlayer) != 1) goto L_Missing;
if(attachrid($@Duel_RedPlayer) == 1) goto L_Proceed2;
goto L_Missing;
L_Missing:
callfunc "fightclub_CleanStage";
callfunc "fightclub_NextBattle";
return;
L_Proceed2:
addtimer ($@Duel_TimeBeforeNext * 1000), "#FightClubUtils::OnDelayedNextBattle";
return;
}
// ** called after the delay
function|script|fightclub_NextBattleProceed
{
set $@Duel_NoMagic, 0;
if((DUELS & $@NoMagicBit) != 0) set $@Duel_NoMagic, 1; // get the rules of the caster
donpcevent "Rouge#Duels::OnAnnounceNext";
set $@Duel_Started, 0;
addtimer ($@Duel_TimeBeforeWarp * 1000), "#FightClubUtils::OnDelayedStart";
return;
}
function|script|fightclub_StartBattle
{
set $@Duel_Started, 1;
npcwarp 40, 45, "Rouge#Duels";
donpcevent "#FightClubTimeLimit::OnStartTimer";
if(attachrid($@Duel_RedPlayer) != 1) goto L_Missing;
callfunc "fightclub_enter";
if(attachrid($@Duel_BluePlayer) != 1) goto L_Missing;
callfunc "fightclub_enter";
return;
L_Missing:
callfunc "fightclub_CleanStage";
callfunc "fightclub_NextBattle";
return;
}
function|script|fightclub_TimeOut
{
donpcevent "Rouge#Duels::OnAnnounceTimeOut";
if(attachrid($@Duel_RedPlayer) != 1) goto L_Missing;
callfunc "fightclub_exit";
if(attachrid($@Duel_BluePlayer) != 1) goto L_Missing;
callfunc "fightclub_exit";
callfunc "fightclub_CleanStage";
callfunc "fightclub_NextBattle";
return;
L_Missing:
callfunc "fightclub_CleanStage";
callfunc "fightclub_NextBattle";
return;
}
// ** called when someone uninvited is on stage
function|script|fightclub_Intrusion
{
// nothing to do here (yet)
return;
}
function|script|fightclub_EmergencyWipe
{
callfunc "fightclub_CleanStage";
callfunc "fightclub_StartUp";
// TODO: check if everything is clean (function) and mapexit otherwise
return;
}
// ** called whenever someone wins (to handle rewards and bids)
function|script|fightclub_Victory
{
// TODO: give some sort of reward
// TODO: increase score
// TODO: update leaderboard
return;
}
// ** called when the player needs to be reset
function|script|fightclub_DestroyMe
{
set @Duel_Fighter, 0;
setpvpchannel @previous_channel;
sc_end 132; sc_end 14; sc_end 37; sc_end 185; sc_end 194; sc_end 195; sc_end 196; sc_end 197; sc_end 198; sc_end 199; // remove effects
heal MaxHp, MaxSp; // refill hp/mana
if(getmap() == "009-7") warp "009-7", rand($@fightclub_x1, $@fightclub_x2), rand(($@fightclub_y1 - 2), ($@fightclub_y1 - 3));
return;
}
// ** called when the red or blue player disappears from stage
function|script|fightclub_Missing
{
// $@Duel_Missing 1 = red, 2 = blue
if (attachrid($@Duel_BluePlayer) == 1) goto L_Proceed; // we need to attach to at least one player
if (attachrid($@Duel_RedPlayer) == 1) goto L_Proceed;
goto L_Resume; // can't attach either of them (this is not a problem since it means they are offline so their vars are clean anyway)
L_Proceed:
if($@Duel_Missing == 1) goto L_BlueWins;
goto L_RedWins;
L_BlueWins:
donpcevent "Rouge#Duels::OnAnnounceBlueForfeit";
set $@duel_winner, $@Duel_BluePlayer;
callfunc "fightclub_Victory";
goto L_Clean;
L_RedWins:
donpcevent "Rouge#Duels::OnAnnounceRedForfeit";
set $@duel_winner, $@Duel_RedPlayer;
callfunc "fightclub_Victory";
goto L_Clean;
L_KillBlue:
callfunc "fightclub_exit";
if(attachrid($@Duel_RedPlayer) == 1) goto L_KillRed;
goto L_Resume;
L_KillRed:
callfunc "fightclub_exit";
goto L_Resume;
L_Clean:
if(attachrid($@Duel_BluePlayer) == 1) goto L_KillBlue;
if(attachrid($@Duel_RedPlayer) == 1) goto L_KillRed;
goto L_Resume; // couldn't kill them
L_Resume:
callfunc "fightclub_CleanStage";
callfunc "fightclub_NextBattle";
return;
}
// ** called after the server boots up
function|script|fightclub_StartUp
{
if($@Duel_TimeBeforeNext < 1) set $@Duel_TimeBeforeNext, 5; // init the (temporary) TimeBeforeNext global
if($@Duel_TimeBeforeWarp < 1) set $@Duel_TimeBeforeWarp, 5; // init the (temporary) TimeBeforeWarp global
if($@Duel_TimeBeforeStart < 1) set $@Duel_TimeBeforeStart, 3; // init the (temporary) TimeBeforeStart global
if($@Duel_TimeLimit < 1) set $@Duel_TimeLimit, 120; // init the (temporary) TimeLimit global
if($@Duel_QueueLimit < 1) set $@Duel_QueueLimit, 5; // init the (temporary) QueueLimit global
if($@Duel_PlayerQueueLimit < 1) set $@Duel_PlayerQueueLimit, 2; // init the (temporary) PlayerQueueLimit global
if($@Duel_PlayerQueueTimeOut < 1) set $@Duel_PlayerQueueTimeOut, 300; // init the (temporary) PlayerQueueTimeOut global
setarray $@Duel_Queue_ID, 0;
cleararray $@Duel_Queue_ID, 0, ($@Duel_QueueLimit + 1);
setarray $@Duel_Queue_Blue$, "";
cleararray $@Duel_Queue_Blue$, "", ($@Duel_QueueLimit + 1);
setarray $@Duel_Queue_Red$, "";
cleararray $@Duel_Queue_Red$, "", ($@Duel_QueueLimit + 1);
set $@Duel_TotalTime, 0;
set $@Duel_Channel, 20;
if($fightclub_enabled) set $fightclub_enabled, 0; // this var moved to $SANGUINE
// DUELS flags below
set $@DuelPvpBit, (1 << 1);
set $@NoMagicBit, (1 << 2);
// $SANGUINE flags below
set $@SV_FCDBit, (1 << 1);
set $@SV_BMDBit, (1 << 2);
return;
}
// ** called before and after each duel to wipe the vars
function|script|fightclub_CleanStage
{
if($@Duel_NoWarp != 1) areawarp "009-7", $@fightclub_x1, $@fightclub_y1, $@fightclub_x2, $@fightclub_y2, "009-7", 31, 40; // kick all players from stage
set $@Duel_NoWarp, 0;
set $@Duel_NoMagic, 0; // clean the Duel parameters
set $@Duel_CurrentDuel, 0; // no duel atm
set $@Duel_Started, 0; // no duel atm
set $@Duel_RedPlayer, 0;
set $@Duel_BluePlayer, 0;
set $@Duel_Missing, 0;
set $@Duel_TotalTime, 0;
npcwarp 32, 45, "Rouge#Duels";
donpcevent "#FightClubTimeLimit::OnStopTimer";
killmonster "009-7", "All";
return;
}
// ** called by npc; allows the player to change their custom rules
function|script|fightclub_setrules
{
goto L_Main;
L_Main:
mes "Your rules are the following: "; mes "";
callfunc "fightclub_getrules";
mes ""; mes "What do you want to do?";
menu
"Change my rules.", L_Start,
"Nevermind.", L_Return;
L_Start:
set DUELS, DUELS | $@NoMagicBit;
goto L_NoMagic;
L_NoMagic:
mes "Do you want to allow magic?";
mes "If disabled, the fighters will not be able to use any kind of spell.";
menu
"Yes.", L_NoMagicYes,
"No.", L_Done;
L_NoMagicYes:
set DUELS, DUELS &~ $@NoMagicBit;
goto L_Done;
L_Done:
next;
mes "You have succesfully changed your options.";
goto L_Main;
L_Return:
return;
}
// ** called by event handler whenever someone dies
function|script|fightclub_death
{
if(@Duel_Fighter != 1) goto L_NoDuel;
if(($@Duel_CurrentDuel < 1) || ($@Duel_Started != 1)) goto L_Reset;
if(@killerrid != 0) goto L_Murdered;
goto L_Killed;
L_Killed:
if(getcharid(3) == $@Duel_RedPlayer) goto L_BlueWins;
goto L_RedWins;
L_RedWins:
donpcevent "Rouge#Duels::OnAnnounceRedWins";
set $@duel_winner, $@Duel_RedPlayer;
callfunc "fightclub_Victory";
callfunc "fightclub_exit";
if(attachrid($@Duel_RedPlayer) == 1) goto L_RedWins2;
goto L_Missing;
L_RedWins2:
callfunc "fightclub_exit";
goto L_Proceed;
L_BlueWins:
donpcevent "Rouge#Duels::OnAnnounceBlueWins";
set $@duel_winner, $@Duel_BluePlayer;
callfunc "fightclub_Victory";
callfunc "fightclub_exit";
if(attachrid($@Duel_BluePlayer) == 1) goto L_BlueWins2;
goto L_Missing;
L_Missing:
goto L_Proceed;
L_BlueWins2:
callfunc "fightclub_exit";
goto L_Proceed;
L_Proceed:
callfunc "fightclub_CleanStage";
return;
L_Murdered:
if(($@Duel_RedPlayer != @killerrid) && ($@Duel_BluePlayer != @killerrid)) goto L_Stranger;
goto L_Killed; // now we proceed the same way as L_Killed
L_Stranger:
// the victim was not murdered by its adversary (wtf)
if(debug) donpcevent "Debug#Duels::OnKillerNotInDuel";
callfunc "fightclub_EmergencyWipe";
return;
L_NoDuel:
if(debug) donpcevent "Debug#Duels::OnVictimNotInDuel";
return;
L_Reset: // the player has duel_fighter but no duel is ongoing (happens if the player quit before fightclub_exit can be called)
if(debug) donpcevent "Debug#Duels::OnVictimInDuelNoDuel";
callfunc "fightclub_DestroyMe"; // here we attempt to resume the interrupted procedure
return;
}
// ** called every time a player enters the ring
function|script|fightclub_enter
{
set @Duel_Fighter, 1;
warp "009-7", rand($@fightclub_x1,$@fightclub_x2), rand($@fightclub_y1,$@fightclub_y2);
heal MaxHp, MaxSp; // ensure that you can't duel wih a corpse
sc_end 132; sc_end 14; sc_end 37; sc_end 185; sc_end 194; sc_end 195; sc_end 196; sc_end 197; sc_end 198; sc_end 199; // remove effects
message strcharinfo(0), "Get Ready.";
addtimer ($@Duel_TimeBeforeStart * 1000), "#FightClubUtils::OnBecomeKiller"; // call fightclub_enter_killer in 3 seconds
return;
}
// ** called 3 seconds after a player enters the ring
function|script|fightclub_enter_killer
{
if(getpvpflag(0) != $@Duel_Channel) set @previous_channel, getpvpflag(0);
setpvpchannel $@Duel_Channel;
message strcharinfo(0), "GO !";
return;
}
// ** called every time a player exits the ring
function|script|fightclub_exit
{
callfunc "fightclub_DestroyMe"; // kill and reset state
message strcharinfo(0), "Thank you for participating in the fight club!";
if(@Duel_HasPendingRequest) message strcharinfo(0), "You have received a new duel request.";
return;
}
// ** called on OnPCKilledEvent
function|script|fightclub_event_killed
{
set @duel_killer, 0;
if(@Duel_Fighter != 1) goto L_End;
if(getmap() != "009-7") goto L_End;
set $@duel_loser, getcharid(3); // grab the rid of the victim
set $@duel_winner, @killerrid; // grab the rid of the killer
set @killerrid, 0; // reset killerid
callfunc "fightclub_death";
goto L_End;
L_End:
if(getpvpflag(0) == $@Duel_Channel) setpvpflag @previous_channel;
return;
}
// ** called on OnPCDieEvent
function|script|fightclub_event_die
{
set @duel_killer, 0;
if(@Duel_Fighter != 1) goto L_End;
if(getmap() != "009-7") goto L_End;
set @killerrid, 0; // since the player was not murdered, the killerrid is 0
set $@duel_loser, getcharid(3); // grab the rid of the victim
callfunc "fightclub_death";
goto L_End;
L_End:
if(getpvpflag(0) == $@Duel_Channel) setpvpflag @previous_channel;
return;
}