diff options
| author | navewindre <nw@moneybot.cc> | 2023-12-04 18:06:10 +0100 |
|---|---|---|
| committer | navewindre <nw@moneybot.cc> | 2023-12-04 18:06:10 +0100 |
| commit | aef0d1c1268ab7d4bc18996c9c6b4da16a40aadc (patch) | |
| tree | 43e766b51704f4ab8b383583bdc1871eeeb9c698 /sourcemod/scripting/gokz-racing/racer.sp | |
| parent | 38f1140c11724da05a23a10385061200b907cf6e (diff) | |
bbbbbbbbwaaaaaaaaaaa
Diffstat (limited to 'sourcemod/scripting/gokz-racing/racer.sp')
| -rw-r--r-- | sourcemod/scripting/gokz-racing/racer.sp | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/sourcemod/scripting/gokz-racing/racer.sp b/sourcemod/scripting/gokz-racing/racer.sp new file mode 100644 index 0000000..eb4ff3f --- /dev/null +++ b/sourcemod/scripting/gokz-racing/racer.sp @@ -0,0 +1,439 @@ +/* + Functions that affect the state of clients participating in a race. + See the RacerStatus enum for possible states. +*/ + + + +static int racerStatus[MAXPLAYERS + 1]; +static int racerRaceID[MAXPLAYERS + 1]; +static float lastTimerStartTime[MAXPLAYERS + 1]; +static float lastCheckpointTime[MAXPLAYERS + 1]; + + + +// =====[ EVENTS ]===== + +Action OnTimerStart_Racer(int client, int course) +{ + if (InCountdown(client) + || InStartedRace(client) && (!InRaceMode(client) || !IsRaceCourse(client, course))) + { + return Plugin_Stop; + } + + return Plugin_Continue; +} + +Action OnTimerStart_Post_Racer(int client) +{ + lastTimerStartTime[client] = GetGameTime(); + return Plugin_Continue; +} + +Action OnMakeCheckpoint_Racer(int client) +{ + if (GOKZ_GetTimerRunning(client) && InStartedRace(client)) + { + int checkpointRule = GetRaceInfo(GetRaceID(client), RaceInfo_CheckpointRule); + if (checkpointRule == 0) + { + GOKZ_PrintToChat(client, true, "%t", "Checkpoints Not Allowed During Race"); + GOKZ_PlayErrorSound(client); + return Plugin_Handled; + } + else if (checkpointRule != -1 && GOKZ_GetCheckpointCount(client) >= checkpointRule) + { + GOKZ_PrintToChat(client, true, "%t", "No Checkpoints Left"); + GOKZ_PlayErrorSound(client); + return Plugin_Handled; + } + + float cooldownRule = float(GetRaceInfo(GetRaceID(client), RaceInfo_CooldownRule)); + float timeSinceLastCheckpoint = FloatMin( + GetGameTime() - lastTimerStartTime[client], + GetGameTime() - lastCheckpointTime[client]); + if (timeSinceLastCheckpoint < cooldownRule) + { + GOKZ_PrintToChat(client, true, "%t", "Checkpoint On Cooldown", (cooldownRule - timeSinceLastCheckpoint)); + GOKZ_PlayErrorSound(client); + return Plugin_Handled; + } + } + + return Plugin_Continue; +} + +void OnMakeCheckpoint_Post_Racer(int client) +{ + lastCheckpointTime[client] = GetGameTime(); +} + +Action OnUndoTeleport_Racer(int client) +{ + if (GOKZ_GetTimerRunning(client) + && InStartedRace(client) + && GetRaceInfo(GetRaceID(client), RaceInfo_CheckpointRule) != -1) + { + GOKZ_PrintToChat(client, true, "%t", "Undo TP Not Allowed During Race"); + GOKZ_PlayErrorSound(client); + return Plugin_Handled; + } + + return Plugin_Continue; +} + + + +// =====[ GENERAL ]===== + +int GetStatus(int client) +{ + return racerStatus[client]; +} + +int GetRaceID(int client) +{ + return racerRaceID[client]; +} + +bool InRace(int client) +{ + return GetStatus(client) != RacerStatus_Available; +} + +bool InStartedRace(int client) +{ + return GetStatus(client) == RacerStatus_Racing; +} + +bool InCountdown(int client) +{ + return GetRaceInfo(GetRaceID(client), RaceInfo_Status) == RaceStatus_Countdown; +} + +bool InRaceMode(int client) +{ + return GOKZ_GetCoreOption(client, Option_Mode) == GetRaceInfo(GetRaceID(client), RaceInfo_Mode); +} + +bool IsRaceCourse(int client, int course) +{ + return course == GetRaceInfo(GetRaceID(client), RaceInfo_Course); +} + +bool IsFinished(int client) +{ + int status = GetStatus(client); + return status == RacerStatus_Finished || status == RacerStatus_Surrendered; +} + +bool IsAccepted(int client) +{ + return GetStatus(client) == RacerStatus_Accepted; +} + +bool IsRaceHost(int client) +{ + return GetRaceHost(GetRaceID(client)) == client; +} + +static void ResetRacer(int client) +{ + racerStatus[client] = RacerStatus_Available; + racerRaceID[client] = -1; + lastTimerStartTime[client] = 0.0; + lastCheckpointTime[client] = 0.0; +} + +static void ResetRacersInRace(int raceID) +{ + for (int client = 1; client <= MaxClients; client++) + { + if (racerRaceID[client] == raceID) + { + ResetRacer(client); + } + } +} + + + +// =====[ RACING ]===== + +void StartRacer(int client) +{ + if (racerStatus[client] == RacerStatus_Pending) + { + DeclineRequest(client, true); + return; + } + + if (racerStatus[client] != RacerStatus_Accepted) + { + return; + } + + racerStatus[client] = RacerStatus_Racing; + + // Prepare the racer + GOKZ_StopTimer(client); + GOKZ_SetCoreOption(client, Option_Mode, GetRaceInfo(racerRaceID[client], RaceInfo_Mode)); + + int course = GetRaceInfo(racerRaceID[client], RaceInfo_Course); + if (GOKZ_SetStartPositionToMapStart(client, course)) + { + GOKZ_TeleportToStart(client); + } + else + { + GOKZ_PrintToChat(client, true, "%t", "No Start Found", course); + } +} + +bool FinishRacer(int client, int course) +{ + if (racerStatus[client] != RacerStatus_Racing || + course != GetRaceInfo(racerRaceID[client], RaceInfo_Course)) + { + return false; + } + + racerStatus[client] = RacerStatus_Finished; + + int raceID = racerRaceID[client]; + int place = IncrementFinishedRacerCount(raceID); + + Call_OnFinish(client, raceID, place); + + CheckRaceFinished(raceID); + + return true; +} + +bool SurrenderRacer(int client) +{ + if (racerStatus[client] == RacerStatus_Available + || racerStatus[client] == RacerStatus_Surrendered) + { + return false; + } + + racerStatus[client] = RacerStatus_Surrendered; + + int raceID = racerRaceID[client]; + + Call_OnSurrender(client, raceID); + + CheckRaceFinished(raceID); + + return true; +} + +// Auto-finish last remaining racer, and reset everyone if no one is left +static void CheckRaceFinished(int raceID) +{ + ArrayList remainingRacers = GetUnfinishedRacers(raceID); + if (remainingRacers.Length == 1) + { + int lastRacer = remainingRacers.Get(0); + FinishRacer(lastRacer, GetRaceInfo(racerRaceID[lastRacer], RaceInfo_Course)); + } + else if (remainingRacers.Length == 0) + { + ResetRacersInRace(raceID); + } + delete remainingRacers; +} + +bool AbortRacer(int client) +{ + if (racerStatus[client] == RacerStatus_Available) + { + return false; + } + + ResetRacer(client); + + return true; +} + + + +// =====[ HOSTING ]===== + +int HostRace(int client, int type, int course, int mode, int checkpointRule, int cooldownRule) +{ + if (InRace(client)) + { + return -1; + } + + int raceID = RegisterRace(client, type, course, mode, checkpointRule, cooldownRule); + racerRaceID[client] = raceID; + racerStatus[client] = RacerStatus_Accepted; + + return raceID; +} + +bool StartHostedRace(int client) +{ + if (!InRace(client) || !IsRaceHost(client)) + { + GOKZ_PrintToChat(client, true, "%t", "You Are Not Hosting A Race"); + GOKZ_PlayErrorSound(client); + return false; + } + + int raceID = racerRaceID[client]; + + if (GetRaceInfo(raceID, RaceInfo_Status) != RaceStatus_Pending) + { + GOKZ_PrintToChat(client, true, "%t", "Race Already Started"); + GOKZ_PlayErrorSound(client); + return false; + } + + if (GetAcceptedRacersCount(raceID) <= 1) + { + GOKZ_PrintToChat(client, true, "%t", "No One Accepted"); + GOKZ_PlayErrorSound(client); + return false; + } + + return StartRace(raceID); +} + +bool AbortHostedRace(int client) +{ + if (!InRace(client) || !IsRaceHost(client)) + { + GOKZ_PrintToChat(client, true, "%t", "You Are Not Hosting A Race"); + GOKZ_PlayErrorSound(client); + return false; + } + + int raceID = racerRaceID[client]; + + return AbortRace(raceID); +} + + + +// =====[ REQUESTS ]===== + +bool SendRequest(int host, int target) +{ + if (IsFakeClient(target) || target == host || InRace(target) + || !IsRaceHost(host) || GetRaceInfo(racerRaceID[host], RaceInfo_Status) != RaceStatus_Pending) + { + return false; + } + + int raceID = racerRaceID[host]; + + racerRaceID[target] = raceID; + racerStatus[target] = RacerStatus_Pending; + + // Host callback + DataPack data = new DataPack(); + data.WriteCell(GetClientUserId(host)); + data.WriteCell(GetClientUserId(target)); + data.WriteCell(raceID); + CreateTimer(RC_REQUEST_TIMEOUT_TIME, Timer_RequestTimeout, data); + + Call_OnRequestReceived(target, raceID); + + return true; +} + +public Action Timer_RequestTimeout(Handle timer, DataPack data) +{ + data.Reset(); + int host = GetClientOfUserId(data.ReadCell()); + int target = GetClientOfUserId(data.ReadCell()); + int raceID = data.ReadCell(); + delete data; + + if (!IsValidClient(host) || racerRaceID[host] != raceID + || !IsValidClient(target) || racerRaceID[target] != raceID) + { + return Plugin_Continue; + } + + // If haven't accepted by now, auto decline the race + if (racerStatus[target] == RacerStatus_Pending) + { + DeclineRequest(target, true); + } + return Plugin_Continue; +} + +int SendRequestAll(int host) +{ + int sentCount = 0; + for (int target = 1; target <= MaxClients; target++) + { + if (IsClientInGame(target) && SendRequest(host, target)) + { + sentCount++; + } + } + return sentCount; +} + +bool AcceptRequest(int client) +{ + if (GetStatus(client) != RacerStatus_Pending) + { + return false; + } + + racerStatus[client] = RacerStatus_Accepted; + + Call_OnRequestAccepted(client, racerRaceID[client]); + + return true; +} + +bool DeclineRequest(int client, bool timeout = false) +{ + if (GetStatus(client) != RacerStatus_Pending) + { + return false; + } + + int raceID = racerRaceID[client]; + ResetRacer(client); + + Call_OnRequestDeclined(client, raceID, timeout); + + return true; +} + + + +// =====[ EVENTS ]===== + +void OnClientPutInServer_Racer(int client) +{ + ResetRacer(client); +} + +void OnClientDisconnect_Racer(int client) +{ + // Abort if player was the host of the race, else surrender + if (InRace(client)) + { + if (IsRaceHost(client) && GetRaceInfo(racerRaceID[client], RaceInfo_Status) == RaceStatus_Pending) + { + AbortRace(racerRaceID[client]); + } + else + { + SurrenderRacer(client); + } + } + + ResetRacer(client); +}
\ No newline at end of file |
