-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathraces_sv.lua
244 lines (216 loc) · 8.53 KB
/
races_sv.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
-- Server side array of active races
local races = {}
-- Cleanup thread
Citizen.CreateThread(function()
-- Loop forever and check status every 100ms
while true do
Citizen.Wait(100)
-- Check active races and remove any that become inactive
for index, race in pairs(races) do
-- Get time and players in race
local time = GetGameTimer()
local players = race.players
-- Check start time and player count
if (time > race.startTime) and (#players == 0) then
-- Race past start time with no players, remove race and send event to all clients
table.remove(races, index)
TriggerClientEvent("StreetRaces:removeRace_cl", -1, index)
-- Check if race has finished and expired
elseif (race.finishTime ~= 0) and (time > race.finishTime + race.finishTimeout) then
-- Did not finish, notify players still racing
for _, player in pairs(players) do
notifyPlayer(player, "DNF (timeout)")
end
-- Remove race and send event to all clients
table.remove(races, index)
TriggerClientEvent("StreetRaces:removeRace_cl", -1, index)
end
end
end
end)
-- Server event for creating a race
RegisterNetEvent("StreetRaces:createRace_sv")
AddEventHandler("StreetRaces:createRace_sv", function(amount, startDelay, startCoords, checkpoints, finishTimeout)
-- Add fields to race struct and add to races array
local race = {
owner = source,
amount = amount,
startTime = GetGameTimer() + startDelay,
startCoords = startCoords,
checkpoints = checkpoints,
finishTimeout = config_sv.finishTimeout,
players = {},
prize = 0,
finishTime = 0
}
table.insert(races, race)
-- Send race data to all clients
local index = #races
TriggerClientEvent("StreetRaces:createRace_cl", -1, index, amount, startDelay, startCoords, checkpoints)
end)
-- Server event for canceling a race
RegisterNetEvent("StreetRaces:cancelRace_sv")
AddEventHandler("StreetRaces:cancelRace_sv", function()
-- Iterate through races
for index, race in pairs(races) do
-- Find if source player owns a race that hasn't started
local time = GetGameTimer()
if source == race.owner and time < race.startTime then
-- Send notification and refund money for all entered players
for _, player in pairs(race.players) do
-- Refund money to player and remove from prize pool
addMoney(player, race.amount)
race.prize = race.prize - race.amount
-- Notify player race has been canceled
local msg = "Race canceled"
notifyPlayer(player, msg)
end
-- Remove race from table and send client event
table.remove(races, index)
TriggerClientEvent("StreetRaces:removeRace_cl", -1, index)
end
end
end)
-- Server event for joining a race
RegisterNetEvent("StreetRaces:joinRace_sv")
AddEventHandler("StreetRaces:joinRace_sv", function(index)
-- Validate and deduct player money
local race = races[index]
local amount = race.amount
local playerMoney = getMoney(source)
if playerMoney >= amount then
-- Deduct money from player and add to prize pool
removeMoney(source, amount)
race.prize = race.prize + amount
-- Add player to race and send join event back to client
table.insert(races[index].players, source)
TriggerClientEvent("StreetRaces:joinedRace_cl", source, index)
else
-- Insufficient money, send notification back to client
local msg = "Insuffient funds to join race"
notifyPlayer(source, msg)
end
end)
-- Server event for leaving a race
RegisterNetEvent("StreetRaces:leaveRace_sv")
AddEventHandler("StreetRaces:leaveRace_sv", function(index)
-- Validate player is part of the race
local race = races[index]
local players = race.players
for index, player in pairs(players) do
if source == player then
-- Remove player from race and break
table.remove(players, index)
break
end
end
end)
-- Server event for finishing a race
RegisterNetEvent("StreetRaces:finishedRace_sv")
AddEventHandler("StreetRaces:finishedRace_sv", function(index, time)
-- Check player was part of the race
local race = races[index]
local players = race.players
for index, player in pairs(players) do
if source == player then
-- Calculate finish time
local time = GetGameTimer()
local timeSeconds = (time - race.startTime)/1000.0
local timeMinutes = math.floor(timeSeconds/60.0)
timeSeconds = timeSeconds - 60.0*timeMinutes
-- If race has not finished already
if race.finishTime == 0 then
-- Winner, set finish time and award prize money
race.finishTime = time
addMoney(source, race.prize)
-- Send winner notification to players
for _, pSource in pairs(players) do
if pSource == source then
local msg = ("You won [%02d:%06.3f]"):format(timeMinutes, timeSeconds)
notifyPlayer(pSource, msg)
elseif config_sv.notifyOfWinner then
local msg = ("%s won [%02d:%06.3f]"):format(getName(source), timeMinutes, timeSeconds)
notifyPlayer(pSource, msg)
end
end
else
-- Loser, send notification to only the player
local msg = ("You lost [%02d:%06.3f]"):format(timeMinutes, timeSeconds)
notifyPlayer(source, msg)
end
-- Remove player form list and break
table.remove(players, index)
break
end
end
end)
-- Server event for saving recorded checkpoints as a race
RegisterNetEvent("StreetRaces:saveRace_sv")
AddEventHandler("StreetRaces:saveRace_sv", function(name, checkpoints)
-- Cleanup data so it can be serialized
for _, checkpoint in pairs(checkpoints) do
checkpoint.blip = nil
checkpoint.coords = {x = checkpoint.coords.x, y = checkpoint.coords.y, z = checkpoint.coords.z}
end
-- Get saved player races, add race and save
local playerRaces = loadPlayerData(source)
playerRaces[name] = checkpoints
savePlayerData(source, playerRaces)
-- Send notification to player
local msg = "Saved " .. name
notifyPlayer(source, msg)
end)
-- Server event for deleting recorded race
RegisterNetEvent("StreetRaces:deleteRace_sv")
AddEventHandler("StreetRaces:deleteRace_sv", function(name)
-- Get saved player races
local playerRaces = loadPlayerData(source)
-- Check if race with name exists
if playerRaces[name] ~= nil then
-- Delete race and save data
playerRaces[name] = nil
savePlayerData(source, playerRaces)
-- Send notification to player
local msg = "Deleted " .. name
notifyPlayer(source, msg)
else
local msg = "No race found with name " .. name
notifyPlayer(source, msg)
end
end)
-- Server event for listing recorded races
RegisterNetEvent("StreetRaces:listRaces_sv")
AddEventHandler("StreetRaces:listRaces_sv", function()
-- Get saved player races and iterate through saved races
local msg = "Saved races: "
local count = 0
local playerRaces = loadPlayerData(source)
for name, race in pairs(playerRaces) do
msg = msg .. name .. ", "
count = count + 1
end
-- Fix string formatting
if count > 0 then
msg = string.sub(msg, 1, -3)
end
-- Send notification to player with listing
notifyPlayer(source, msg)
end)
-- Server event for loaded recorded race
RegisterNetEvent("StreetRaces:loadRace_sv")
AddEventHandler("StreetRaces:loadRace_sv", function(name)
-- Get saved player races and load race
local playerRaces = loadPlayerData(source)
local race = playerRaces[name]
-- If race was found send it to the client
if race ~= nil then
-- Send race data to client
TriggerClientEvent("StreetRaces:loadRace_cl", source, race)
-- Send notification to player
local msg = "Loaded " .. name
notifyPlayer(source, msg)
else
local msg = "No race found with name " .. name
notifyPlayer(source, msg)
end
end)