├── server
├── exports
│ ├── events.lua
│ └── info.lua
├── default_events.lua
├── system
│ ├── cooldown.lua
│ ├── events.lua
│ └── lobby.lua
├── main.lua
└── module
│ └── arena.lua
├── .gitattributes
├── fxmanifest.lua
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── html
├── css
│ ├── style.css
│ └── reset.css
├── scripts
│ └── listener.js
└── index.html
├── client
├── exports
│ ├── events.lua
│ └── info.lua
├── events.lua
├── client.lua
└── system
│ └── events.lua
├── config.lua
├── LICENSE
└── readme.md
/server/exports/events.lua:
--------------------------------------------------------------------------------
1 | exports("On", On)
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/fxmanifest.lua:
--------------------------------------------------------------------------------
1 | fx_version 'adamant'
2 | games { 'gta5' }
3 |
4 | client_scripts {
5 | "client/system/*.lua",
6 | "client/exports/*.lua",
7 | "client/*.lua",
8 | }
9 |
10 | server_script {
11 | "server/main.lua",
12 | "server/default_events.lua",
13 | "server/exports/*.lua",
14 | "server/module/*.lua",
15 | "server/system/*.lua",
16 | }
17 |
18 | shared_scripts {
19 | "config.lua",
20 | }
21 |
22 | files {
23 | "html/*.html",
24 | "html/css/*.css",
25 | "html/scripts/*.js",
26 | }
27 |
28 | ui_page "html/index.html"
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Additional context**
27 | Add any other context about the problem here.
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/html/css/style.css:
--------------------------------------------------------------------------------
1 | *{
2 | color: black;
3 | user-select: none; /* supported by Chrome and Opera */
4 | -webkit-user-select: none; /* Safari */
5 | -khtml-user-select: none; /* Konqueror HTML */
6 | -moz-user-select: none; /* Firefox */
7 | -ms-user-select: none; /* Internet Explorer/Edge */
8 | }
9 |
10 | body {
11 | font-family: 'Montserrat', sans-serif;
12 | background: url(../Screenshot_2.png);
13 | background-repeat: no-repeat;
14 | background-size: 100% 100%;
15 | }
16 |
17 | i{
18 | color: white;
19 | }
20 |
21 | .box{
22 | background: #0000009e;
23 | color: white;
24 | text-align: left;
25 | padding-right: 9px;
26 | padding-top: 5px;
27 | padding-bottom: 5px;
28 | padding-left: 5px;
29 | }
--------------------------------------------------------------------------------
/client/exports/events.lua:
--------------------------------------------------------------------------------
1 | exports("On", On)
2 |
3 | -- will register callback for this event
4 | function OnArenaRoundEnd(arena, cb)
5 | On(arena, "roundend", cb)
6 | end
7 |
8 | exports("OnArenaRoundEnd", OnArenaRoundEnd)
9 |
10 | -- will register callback for this event
11 | function OnPlayerJoinLobby(arena, cb)
12 | On(arena, "join", cb)
13 | end
14 |
15 | exports("OnPlayerJoinLobby", OnPlayerJoinLobby)
16 |
17 | -- will register callback for this event
18 | function OnPlayerExitLobby(arena, cb)
19 | On(arena, "leave", cb)
20 | end
21 |
22 | exports("OnPlayerExitLobby", OnPlayerExitLobby)
23 |
24 | -- will register callback for this event
25 | function OnArenaStart(arena, cb)
26 | On(arena, "start", cb)
27 | end
28 |
29 | exports("OnArenaStart", OnArenaStart)
30 |
31 | -- will register callback for this event
32 | function OnArenaEnd(arena, cb)
33 | On(arena, "end", cb)
34 | end
35 |
36 | exports("OnArenaEnd", OnArenaEnd)
--------------------------------------------------------------------------------
/html/scripts/listener.js:
--------------------------------------------------------------------------------
1 | $(function(){
2 | function display(bool) {
3 | if (bool) {
4 | $("#body").show();
5 | } else {
6 | $("#body").hide();
7 | }
8 | }
9 | display(false);
10 |
11 | window.addEventListener('message', function(event) {
12 | var item = event.data;
13 | if (item.type === "ui"){
14 | display(item.status);
15 | $("#seconds").text("Waiting for people");
16 | }
17 |
18 | if (item.type === "arenaName"){
19 | $("#arenaName").text(item.arenaName);
20 | }
21 |
22 | if (item.type === "updateTime"){
23 | $("#seconds").text("Wait please: "+ item.time +" seconds");
24 | }
25 |
26 | if (item.type === "playerNameList"){
27 | $("#players").text("");
28 | for (var index in item.Names) {
29 | $("#players").append("
" + item.Names[index] + "
");
30 | }
31 | }
32 | })
33 |
34 | });
--------------------------------------------------------------------------------
/server/default_events.lua:
--------------------------------------------------------------------------------
1 | -- When player leave the game we will detele his instance/remove him from arena he is playing
2 | AddEventHandler("playerDropped", function()
3 | local arenaID = PlayerInfo[source]
4 | if arenaID and arenaID ~= "none" then
5 | CreateArena(arenaID).RemovePlayer(source)
6 | end
7 | CooldownPlayers[source] = nil
8 | end)
9 |
10 | -- When player client side load we will write his ID + basic stuff into predefined variables in main
11 | RegisterNetEvent("ArenaAPI:PlayerJoinedFivem")
12 | AddEventHandler("ArenaAPI:PlayerJoinedFivem", function()
13 | TriggerClientEvent("ArenaAPI:sendStatus", source, "updateData", ArenaList)
14 | PlayerInfo[source] = "none"
15 | CooldownPlayers[source] = { }
16 | end)
17 |
18 | -- When some resource will stop it will delete all related events to the resource so it doesnt get
19 | -- duplicated if the resource was only reseted due to testing
20 | AddEventHandler('onResourceStop', function(resourceName)
21 | RemoveEventsWithNameResource(resourceName)
22 | end)
--------------------------------------------------------------------------------
/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Derby #01
15 |
Waiting for people
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/server/system/cooldown.lua:
--------------------------------------------------------------------------------
1 | -- Will set a cooldown to player so he cannot join the lobby defined in args
2 | --- @param source int
3 | --- @param arena string
4 | --- @param time int
5 | function CooldownPlayer(source, arena, time)
6 | CooldownPlayers[source][arena] = os.time(os.date("!*t")) + time
7 | end
8 |
9 | -- Will return true/false if player has cooldown to join the defined lobby
10 | --- @param source int
11 | --- @param arena string
12 | function IsPlayerInCooldown(source, arena)
13 | if CooldownPlayers[source][arena] == nil then return false end
14 | return CooldownPlayers[source][arena] > os.time(os.date("!*t"))
15 | end
16 |
17 | -- Will convert time into hh:mm:ss
18 | --- @param time int
19 | function TimestampToString(time)
20 | return os.date( "%H:%M:%S", time + Config.TimeZone * 60 * 60 )
21 | end
22 |
23 | -- Will return timestamp
24 | --- @param source int
25 | --- @param arena string
26 | function GetcooldownForPlayer(source, arena)
27 | if CooldownPlayers[source][arena] == nil then return os.time(os.date("!*t")) end
28 | return CooldownPlayers[source][arena]
29 | end
--------------------------------------------------------------------------------
/config.lua:
--------------------------------------------------------------------------------
1 | Config = {}
2 |
3 | -- Message list
4 | Config.MessageList = {
5 | ["arena_doesnt_exists"] = "The arena doesnt exists",
6 | ["player_isnt_in_arena"] = "You cant leave any arena because you are not in any arena",
7 | ["player_in_arena"] = "You cant join any arena, first you need to leave the current arena",
8 | ["arena_joined"] = "You joined arena, wait till the game will be ready",
9 | ["arena_left"] = "You left arena, you dont need to wait anymore for anything.",
10 | ["maximum_people"] = "This arena is at it maximum capacity!",
11 | ["cant_acces_this_arena"] = "You cant acces this arena, this arena is privte.",
12 | ["arena_busy"] = "This arena is busy, you have to wait until the arena is finished playing.",
13 | ["cooldown_to_join"] = "You need to wait before joining to this arena! Wait till %s to join!",
14 | }
15 |
16 | -- your current time zone
17 | Config.TimeZone = 1
18 |
19 | -- How many seconds player will have to wait before trying to join same lobby after leaving ?
20 | -- This will prevent trollers from trying to stop the lobby start.
21 | Config.TimeCooldown = 25
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 MrXogos
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/html/css/reset.css:
--------------------------------------------------------------------------------
1 | /* http://meyerweb.com/eric/tools/css/reset/
2 | v2.0 | 20110126
3 | License: none (public domain)
4 | */
5 |
6 | html, body, div, span, applet, object, iframe,
7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
8 | a, abbr, acronym, address, big, cite, code,
9 | del, dfn, em, img, ins, kbd, q, s, samp,
10 | small, strike, strong, sub, sup, tt, var,
11 | b, u, i, center,
12 | dl, dt, dd, ol, ul, li,
13 | fieldset, form, label, legend,
14 | table, caption, tbody, tfoot, thead, tr, th, td,
15 | article, aside, canvas, details, embed,
16 | figure, figcaption, footer, header, hgroup,
17 | menu, nav, output, ruby, section, summary,
18 | time, mark, audio, video {
19 | margin: 0;
20 | padding: 0;
21 | border: 0;
22 | font-size: 100%;
23 | font: inherit;
24 | vertical-align: baseline;
25 | }
26 | /* HTML5 display-role reset for older browsers */
27 | article, aside, details, figcaption, figure,
28 | footer, header, hgroup, menu, nav, section {
29 | display: block;
30 | }
31 | body {
32 | line-height: 1;
33 | }
34 | ol, ul {
35 | list-style: none;
36 | }
37 | blockquote, q {
38 | quotes: none;
39 | }
40 | blockquote:before, blockquote:after,
41 | q:before, q:after {
42 | content: '';
43 | content: none;
44 | }
45 | table {
46 | border-collapse: collapse;
47 | border-spacing: 0;
48 | }
--------------------------------------------------------------------------------
/client/events.lua:
--------------------------------------------------------------------------------
1 | -- When some resource will stop it will delete all related events to the resource so it doesnt get
2 | -- duplicated if the resource was only reseted due to testing
3 | AddEventHandler('onResourceStop', function(resourceName)
4 | RemoveEventsWithNameResource(resourceName)
5 | end)
6 |
7 | -- will fetch info from server and save it into client variable
8 | RegisterNetEvent("ArenaAPI:sendStatus")
9 | AddEventHandler("ArenaAPI:sendStatus", function(type, data)
10 | local arena = data.ArenaIdentifier
11 | if type == "updateData" then
12 | ArenaData = data
13 | UpdatePlayerNameList()
14 | end
15 |
16 | if type == "roundEnd" then
17 | if ArenaData[arena].MaximumArenaTime then
18 | ArenaData[arena].MaximumArenaTime = data.MaximumLobbyTime + 1
19 | end
20 | CallOn(arena, "roundend", data)
21 | end
22 |
23 | if type == "start" then
24 | CallOn(arena, "start", data)
25 | if PlayerData.CurrentArena == arena then
26 | IsArenaBusy = true
27 | end
28 | end
29 |
30 | if type == "end" then
31 | CallOn(arena, "end", data)
32 | if ArenaData[arena].MaximumArenaTime then
33 | ArenaData[arena].MaximumArenaTime = data.MaximumLobbyTime + 1
34 | end
35 | if PlayerData.CurrentArena == arena then
36 | IsArenaBusy = false
37 | end
38 | PlayerData.CurrentArena = "none"
39 | end
40 |
41 | if type == "join" then
42 | PlayerData.CurrentArena = data.ArenaIdentifier
43 | CallOn(arena, "join", data)
44 |
45 | SendNUIMessage({ type = "ui", status = true, })
46 | SendNUIMessage({ type = "arenaName", arenaName = data.ArenaLabel })
47 | UpdatePlayerNameList()
48 | end
49 |
50 | if type == "leave" then
51 | CallOn(arena, "leave", data)
52 |
53 | if PlayerData.CurrentArena == arena then
54 | IsArenaBusy = false
55 | end
56 |
57 | PlayerData.CurrentArena = "none"
58 | SendNUIMessage({ type = "ui", status = false, })
59 | end
60 | end)
--------------------------------------------------------------------------------
/server/exports/info.lua:
--------------------------------------------------------------------------------
1 | -- Will return array with arenas list
2 | function GetArenaList()
3 | return ArenaList
4 | end
5 |
6 | exports("GetArenaList", GetArenaList)
7 |
8 | -- Return true/false if the key exists in variable "ArenaList"
9 | --- @param identifier string
10 | function DoesArenaExists(identifier)
11 | return ArenaList[identifier] ~= nil
12 | end
13 |
14 | exports("DoesArenaExists", DoesArenaExists)
15 |
16 | -- Return true/false if player is in any lobby/Arena
17 | --- @param identifier string
18 | function IsPlayerInAnyArena(source)
19 | return PlayerInfo[source] ~= "none"
20 | end
21 |
22 | exports("IsPlayerInAnyArena", IsPlayerInAnyArena)
23 |
24 | -- will return true/false if player is in the arena defined in arguments
25 | --- @param identifier string
26 | function IsPlayerInArena(source, arena)
27 | return PlayerInfo[source] == arena
28 | end
29 |
30 | exports("IsPlayerInArena", IsPlayerInArena)
31 |
32 | -- Will return player arena name
33 | --- @param identifier string
34 | function GetPlayerArena(source)
35 | return PlayerInfo[source]
36 | end
37 |
38 | exports("GetPlayerArena", GetPlayerArena)
39 |
40 | -- Will return true/false if arena is busy
41 | --- @param identifier string
42 | function IsArenaBusy(identifier)
43 | return ArenaList[identifier].ArenaState == "ArenaBusy"
44 | end
45 |
46 | exports("IsArenaBusy", IsArenaBusy)
47 |
48 | -- Will return player count in the arena/lobby
49 | --- @param identifier string
50 | function GetPlayerCount(identifier)
51 | return ArenaList[identifier].CurrentCapacity
52 | end
53 |
54 | exports("GetPlayerCount", GetPlayerCount)
55 |
56 | -- Will return true/false if arena is active
57 | --- @param identifier string
58 | function IsArenaActive(identifier)
59 | return ArenaList[identifier].ArenaState == "ArenaActive"
60 | end
61 |
62 | exports("IsArenaActive", IsArenaActive)
63 |
64 | -- Will return true/false if arena is inactive
65 | --- @param identifier string
66 | function IsArenaInactive (identifier)
67 | return ArenaList[identifier].ArenaState == "ArenaInactive"
68 | end
69 |
70 | exports("IsArenaInactive", IsArenaInactive)
71 |
72 | -- Will return string in what state is the arena
73 | --- @param identifier string
74 | function GetArenaState (identifier)
75 | return ArenaList[identifier].ArenaState
76 | end
77 |
78 | exports("GetArenaState", GetArenaState)
--------------------------------------------------------------------------------
/client/exports/info.lua:
--------------------------------------------------------------------------------
1 | -- Will return array of the arena name
2 | --- @param identifier string
3 | function GetArena(identifier)
4 | return ArenaData[identifier]
5 | end
6 |
7 | exports("GetArena", GetArena)
8 |
9 | -- Will return true/false if player is in any arena
10 | function IsPlayerInAnyArena()
11 | return PlayerData.CurrentArena ~= "none"
12 | end
13 |
14 | exports("IsPlayerInAnyArena", IsPlayerInAnyArena)
15 |
16 | -- will return player arena name
17 | function GetPlayerArena()
18 | return PlayerData.CurrentArena
19 | end
20 |
21 | exports("GetPlayerArena", GetPlayerArena)
22 |
23 | -- Will return true/false if the player is in specific arena
24 | --- @param arena string
25 | function IsPlayerInArena(arena)
26 | return PlayerData.CurrentArena == arena
27 | end
28 |
29 | exports("IsPlayerInArena", IsPlayerInArena)
30 |
31 | -- will return label of the arena
32 | --- @param identifier string
33 | function GetArenaLabel(identifier)
34 | return GetCurrentArenaData(identifier).ArenaLabel
35 | end
36 |
37 | exports("GetArenaLabel", GetArenaLabel)
38 |
39 | -- Will return how many players can be in the specific arena
40 | --- @param identifier string
41 | function GetArenaMaximumSize(identifier)
42 | return GetCurrentArenaData(identifier).MaximumCapacity
43 | end
44 |
45 | exports("GetArenaMaximumSize", GetArenaMaximumSize)
46 |
47 | -- Will return minimum required people to start arena
48 | --- @param identifier string
49 | function GetArenaMinimumSize(identifier)
50 | return GetCurrentArenaData(identifier).MinimumCapacity
51 | end
52 |
53 | exports("GetArenaMinimumSize", GetArenaMinimumSize)
54 |
55 | -- Will return how many people is in this specific arena
56 | --- @param identifier string
57 | function GetArenaCurrentSize(identifier)
58 | return GetCurrentArenaData(identifier).CurrentCapacity
59 | end
60 |
61 | exports("GetArenaCurrentSize", GetArenaCurrentSize)
62 |
63 | -- will return data for the arena
64 | --- @param identifier string
65 | function GetCurrentArenaData(identifier)
66 | return {
67 | ArenaIdentifier = ArenaData[identifier].ArenaIdentifier,
68 | ArenaLabel = ArenaData[identifier].ArenaLabel,
69 | MaximumCapacity = ArenaData[identifier].MaximumCapacity,
70 | MinimumCapacity = ArenaData[identifier].MinimumCapacity,
71 | CurrentCapacity = ArenaData[identifier].CurrentCapacity,
72 | }
73 | end
74 |
75 | exports("GetCurrentArenaData", GetCurrentArenaData)
--------------------------------------------------------------------------------
/client/client.lua:
--------------------------------------------------------------------------------
1 | ----------------------------------------
2 | --- Variables
3 | ----------------------------------------
4 | IsArenaBusy = false
5 |
6 | ArenaData = {}
7 | PlayerData = {
8 | CurrentArena = "none",
9 | }
10 | ----------------------------------------
11 | --- Functions
12 | ----------------------------------------
13 | -- stolen from https://scriptinghelpers.org/questions/43622/how-do-i-turn-seconds-to-minutes-and-seconds
14 | function DecimalsToMinutes(dec)
15 | local ms = tonumber(dec)
16 | return math.floor(ms / 60) .. ":" .. (ms % 60)
17 | end
18 |
19 | function UpdatePlayerNameList()
20 | if IsPlayerInAnyArena() then
21 | local arena = GetPlayerArena()
22 | local data = GetArena(arena)
23 | local names = {}
24 | for k, v in pairs(data.PlayerNameList) do
25 | table.insert(names, v)
26 | end
27 | SendNUIMessage({ type = "playerNameList", Names = names, })
28 | end
29 | end
30 | ----------------------------------------
31 | --- threads
32 | ----------------------------------------
33 | CreateThread(function()
34 | TriggerServerEvent("ArenaAPI:PlayerJoinedFivem")
35 | end)
36 |
37 | CreateThread(function()
38 | while true do
39 | Wait(1000)
40 | if IsArenaBusy then
41 | local arena = GetPlayerArena()
42 | local data = GetArena(arena)
43 | if data.MaximumArenaTime ~= nil and data.MaximumArenaTime > 1 then
44 | data.MaximumArenaTime = data.MaximumArenaTime - 1
45 | BeginTextCommandPrint('STRING')
46 | AddTextComponentSubstringPlayerName(DecimalsToMinutes(data.MaximumArenaTime) .. " time left")
47 | EndTextCommandPrint(1000, 1)
48 | end
49 | end
50 |
51 | if IsPlayerInAnyArena() then
52 | local arena = GetPlayerArena()
53 | local data = GetArena(arena)
54 |
55 | if data.MinimumCapacity - 1 < data.CurrentCapacity then
56 | if data.MaximumLobbyTime == 1 then
57 | SendNUIMessage({ type = "ui", status = false, })
58 | else
59 | data.MaximumLobbyTime = data.MaximumLobbyTime - 1
60 |
61 | SendNUIMessage({
62 | type = "updateTime",
63 | time = data.MaximumLobbyTime,
64 | })
65 | end
66 | end
67 | end
68 | end
69 | end)
--------------------------------------------------------------------------------
/client/system/events.lua:
--------------------------------------------------------------------------------
1 | Events = {}
2 | ValidEvents = {
3 | ["join"] = true,
4 | ["leave"] = true,
5 | ["end"] = true,
6 | ["start"] = true,
7 | ["roundend"] = true,
8 | }
9 |
10 | -- Will check and return true/false if the event with identifier exists
11 | --- @param eventName string
12 | function ValidateEvents(eventName)
13 | return type(eventName) == "string" and ValidEvents[string.lower(eventName)] ~= nil
14 | end
15 |
16 | -- Will check and return true/false if the event with identifier exists
17 | --- @param identifier string
18 | --- @param eventName string
19 | function ValidateInvokingEvent(identifier, eventName)
20 | return Events[identifier] ~= nil and Events[identifier][eventName]
21 | end
22 |
23 | -- Will find and remove all events with the
24 | -- name of the resource
25 | --- @param nameResource string
26 | function RemoveEventsWithNameResource(nameResource)
27 | for identifier, v in pairs(Events) do
28 | for event, value in pairs(v) do
29 | for resource, val in pairs(value) do
30 | if resource == nameResource then
31 | Events[identifier][event][resource] = nil
32 | break
33 | end
34 | end
35 | end
36 | end
37 | end
38 |
39 | --Register event
40 | --Return true if event is registered, false if is not
41 | function On(identifier, eventName, cb)
42 | local invokingName = GetInvokingResource()
43 | eventName = string.lower(eventName)
44 | if not ValidateEvents(eventName) then
45 | return false
46 | end
47 |
48 | if Events[identifier] == nil then
49 | Events[identifier] = {}
50 | end
51 |
52 | if Events[identifier][eventName] == nil then
53 | Events[identifier][eventName] = {}
54 | end
55 |
56 | if Events[identifier][eventName][invokingName] == nil then
57 | Events[identifier][eventName][invokingName] = {}
58 | end
59 | table.insert(Events[identifier][eventName][invokingName], cb)
60 | return true
61 | end
62 |
63 | --Call event
64 | --- @param identifier string
65 | --- @param eventName string
66 | --- @param ... object
67 | function CallOn(identifier, eventName, ...)
68 | if ValidateInvokingEvent(identifier, eventName) then
69 | for key, value in pairs(Events[identifier][eventName]) do
70 | for k, cb in pairs(value) do
71 | if type(cb) == "table" or type(cb) == "function" then
72 | cb(...)
73 | end
74 | end
75 | end
76 | end
77 | end
78 |
--------------------------------------------------------------------------------
/server/system/events.lua:
--------------------------------------------------------------------------------
1 | Events = {}
2 | ValidEvents = {
3 | ["join"] = true,
4 | ["leave"] = true,
5 | ["end"] = true,
6 | ["start"] = true,
7 | ["roundend"] = true,
8 | }
9 |
10 | -- Will check and return true/false if the event with identifier exists
11 | --- @param eventName string
12 | function ValidateEvents(eventName)
13 | return type(eventName) == "string" and ValidEvents[string.lower(eventName)] ~= nil
14 | end
15 |
16 | -- Will check and return true/false if the event with identifier exists
17 | --- @param identifier string
18 | --- @param eventName string
19 | function ValidateInvokingEvent(identifier, eventName)
20 | return Events[identifier] ~= nil and Events[identifier][eventName]
21 | end
22 |
23 | -- Will find and remove all events with the
24 | -- name of the resource
25 | --- @param nameResource string
26 | function RemoveEventsWithNameResource(nameResource)
27 | for identifier, v in pairs(Events) do
28 | for event, value in pairs(v) do
29 | for resource, val in pairs(value) do
30 | if resource == nameResource then
31 | Events[identifier][event][resource] = nil
32 | break
33 | end
34 | end
35 | end
36 | end
37 | end
38 |
39 | --Register event
40 | --Return true if event is registered, false if is not
41 | function On(identifier, eventName, cb)
42 | local invokingName = GetInvokingResource()
43 | eventName = string.lower(eventName)
44 | if not ValidateEvents(eventName) then
45 | return false
46 | end
47 |
48 | if Events[identifier] == nil then
49 | Events[identifier] = {}
50 | end
51 |
52 | if Events[identifier][eventName] == nil then
53 | Events[identifier][eventName] = {}
54 | end
55 |
56 | if Events[identifier][eventName][invokingName] == nil then
57 | Events[identifier][eventName][invokingName] = {}
58 | end
59 | table.insert(Events[identifier][eventName][invokingName], cb)
60 | return true
61 | end
62 |
63 | --Call event
64 | --- @param identifier string
65 | --- @param eventName string
66 | --- @param ... object
67 | function CallOn(identifier, eventName, ...)
68 | if ValidateInvokingEvent(identifier, eventName) then
69 | for key, value in pairs(Events[identifier][eventName]) do
70 | for k, cb in pairs(value) do
71 | if type(cb) == "table" or type(cb) == "function" then
72 | cb(...)
73 | end
74 | end
75 | end
76 | end
77 | end
78 |
--------------------------------------------------------------------------------
/server/system/lobby.lua:
--------------------------------------------------------------------------------
1 | -- Checking every lobby if they're ready if so we will set each player into
2 | -- arena virtual world + calling the event "OnStart"
3 | function UpdateLobbies()
4 | SetTimeout(1000, UpdateLobbies)
5 |
6 | for k, v in pairs(ArenaList) do
7 | if IsArenaActive(k) then
8 | if v.MinimumCapacity - 1 < v.CurrentCapacity then
9 | v.MaximumLobbyTime = v.MaximumLobbyTime - 1
10 | if v.MaximumLobbyTime == 0 then
11 | v.MaximumLobbyTime = v.MaximumLobbyTimeSaved
12 |
13 | v.ArenaState = "ArenaBusy"
14 | CallOn(k, "start", v)
15 |
16 | if v.OwnWorld then
17 | for id, _ in pairs(v.PlayerList) do
18 | SetPlayerRoutingBucket(id, v.OwnWorldID)
19 | end
20 | end
21 |
22 | TriggerClientEvent("ArenaAPI:sendStatus", -1, "start", GetDefaultDataFromArena(k))
23 | end
24 | end
25 | end
26 | if IsArenaBusy(k) then
27 | if v.CurrentCapacity == 0 then
28 | GetArenaInstance(k).Reset()
29 | end
30 | end
31 | end
32 | end
33 |
34 | SetTimeout(1000, UpdateLobbies)
35 |
36 | -- This timer will and recount times left in the arena
37 | -- if the timer run to 0 and doesnt have any rounds left it
38 | -- will call event "onEnd" if there is round it will call
39 | -- "onRoundEnd"
40 | function UpdateArenaGame()
41 | SetTimeout(1000, UpdateArenaGame)
42 |
43 | for k, v in pairs(ArenaList) do
44 | if IsArenaBusy(k) then
45 | if v.MaximumArenaTime then
46 | v.MaximumArenaTime = v.MaximumArenaTime - 1
47 | if v.MaximumArenaTime == 0 then
48 | v.MaximumArenaTime = v.MaximumArenaTimeSaved
49 | if v.CurrentRound then
50 | v.CurrentRound = v.CurrentRound - 1
51 | if v.CurrentRound == -1 then
52 | GetArenaInstance(k).Reset()
53 | TriggerClientEvent("ArenaAPI:sendStatus", -1, "end", GetDefaultDataFromArena(k))
54 | else
55 | CallOn(k, "roundEnd", v)
56 | TriggerClientEvent("ArenaAPI:sendStatus", -1, "roundEnd", GetDefaultDataFromArena(k))
57 | end
58 | else
59 | GetArenaInstance(k).Reset()
60 | TriggerClientEvent("ArenaAPI:sendStatus", -1, "end", GetDefaultDataFromArena(k))
61 | end
62 | end
63 | end
64 | end
65 | end
66 | end
67 |
68 | SetTimeout(1000, UpdateArenaGame)
--------------------------------------------------------------------------------
/server/main.lua:
--------------------------------------------------------------------------------
1 | ----------------------------------------
2 | --- Variables
3 | ----------------------------------------
4 | ArenaList = {}
5 | PlayerInfo = {}
6 | CooldownPlayers = {}
7 | WorldCount = 0
8 | ----------------------------------------
9 | --- Functions
10 | ----------------------------------------
11 | -- Arena creator helper, will set all default variables.
12 | --- @param identifier string
13 | --- @param identifier bool
14 | function ArenaCreatorHelper(identifier, ignore)
15 | if ArenaList[identifier] ~= nil then return ArenaList[identifier] end
16 | if not ignore then
17 | ArenaList[identifier] = {
18 | MaximumCapacity = 0,
19 | MinimumCapacity = 0,
20 | CurrentCapacity = 0,
21 | -----
22 | MaximumRoundSaved = nil,
23 | CurrentRound = nil,
24 | -----
25 | DeleteWorldAfterWin = true,
26 | OwnWorld = false,
27 | OwnWorldID = 0,
28 | -----
29 | ArenaLabel = "",
30 | ArenaIdentifier = identifier,
31 | -----
32 | MaximumArenaTime = nil,
33 | MaximumArenaTimeSaved = nil,
34 | MaximumLobbyTimeSaved = 30,
35 | MaximumLobbyTime = 30,
36 | -----
37 | ArenaIsPublic = true,
38 | -----
39 | PlayerList = {},
40 | PlayerScoreList = {},
41 | PlayerNameList = {},
42 | -----
43 | ArenaState = "ArenaInactive",
44 | -----
45 | }
46 | TriggerClientEvent("ArenaAPI:sendStatus", -1, "updateData", ArenaList)
47 | end
48 | return ArenaList[identifier]
49 | end
50 |
51 | -- Will return data from "ArenaCreatorHelper" if arena does not exists
52 | -- it will return nil value
53 | --- @param identifier string
54 | function GetDefaultDataFromArena(identifier)
55 | return ArenaCreatorHelper(identifier, true)
56 | end
57 |
58 | -- Well this will just send chat message to... player :D
59 | --- @param source int
60 | --- @param string string
61 | function SendMessage(source, string)
62 | TriggerClientEvent('chat:addMessage', source, {
63 | color = { 255, 255, 255 },
64 | multiline = true,
65 | args = { "[ArenaAPI]", string }
66 | })
67 | end
68 |
69 | -- This is command to handle logic for joining/leaving + blocking joining arena lobby
70 | RegisterCommand("minigame", function(source, args, rawCommand)
71 | if args[1] == "join" then
72 | local arenaName = args[2]
73 | if not IsPlayerInAnyArena(source) then
74 | if DoesArenaExists(arenaName) then
75 | local arenaInfo = GetDefaultDataFromArena(arenaName)
76 | local arena = GetArenaInstance(arenaName)
77 | if arena.IsArenaPublic() then
78 | if not IsArenaBusy(arenaName) then
79 | if arenaInfo.MaximumCapacity > arenaInfo.CurrentCapacity then
80 | if not IsPlayerInCooldown(source, arenaName) then
81 | arena.MaximumLobbyTime = arena.MaximumLobbyTimeSaved
82 | GetArenaInstance(args[2]).AddPlayer(source)
83 | SendMessage(source, Config.MessageList["arena_joined"])
84 | else
85 | SendMessage(source, string.format(Config.MessageList["cooldown_to_join"], TimestampToString(GetcooldownForPlayer(source, arenaName))))
86 | end
87 | else
88 | SendMessage(source, Config.MessageList["maximum_people"])
89 | end
90 | else
91 | SendMessage(source, Config.MessageList["arena_busy"])
92 | end
93 | else
94 | SendMessage(source, Config.MessageList["cant_acces_this_arena"])
95 | end
96 | else
97 | SendMessage(source, Config.MessageList["arena_doesnt_exists"])
98 | end
99 | else
100 | SendMessage(source, Config.MessageList["player_in_arena"])
101 | end
102 | end
103 | if args[1] == "leave" then
104 | if IsPlayerInAnyArena(source) then
105 | local arenaName = GetPlayerArena(source)
106 | if DoesArenaExists(arenaName) then
107 | local arena = GetArenaInstance(arenaName)
108 | CooldownPlayer(source, arenaName, Config.TimeCooldown)
109 | arena.MaximumLobbyTime = arena.MaximumLobbyTimeSaved
110 |
111 | GetArenaInstance(arenaName).RemovePlayer(source)
112 | SendMessage(source, Config.MessageList["arena_left"])
113 | end
114 | else
115 | SendMessage(source, Config.MessageList["player_isnt_in_arena"])
116 | end
117 | end
118 | end, false)
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | #Arena library for Fivem
2 |
3 |
4 | ### ArenaAPI functions
5 |
6 | ------------
7 |
8 | #####Once a new arena is created, it can be acces with command: /minigame join [identifier]
9 |
10 | ------------
11 |
12 | ###**Functions (server side)**
13 |
14 | ------------
15 |
16 | ### About creating arena and others
17 |
18 | ------------
19 |
20 | - CreateArena(string identifier) returns module of the arena
21 |
22 | - GetArenaInstance(string identifier) will return an instance of arena
23 |
24 | - GetArenaList() will return an array of arenas
25 |
26 | - DoesArenaExists(string identifier) true/false
27 |
28 | ------------
29 |
30 | - IsArenaBusy(string identifier) return true / false
31 |
32 | - IsArenaActive(string identifier) return true / false
33 |
34 | - IsArenaInactive(string identifier) return true / false
35 |
36 | - GetArenaState(string identifier) return state of arena
37 | ```
38 | ArenaInactive -- no one is in a lobby or arena
39 | ArenaActive -- people are in lobby
40 | ArenaBusy -- people playing already
41 | ```
42 |
43 | ------------
44 |
45 | - IsPlayerInArena(int source, string name)
46 |
47 | - IsPlayerInAnyArena(int source)
48 |
49 | - GetPlayerArena(int source) returns name of the arena, if he isnt anywhere it will return "none"
50 |
51 | ------------
52 |
53 | ### Events
54 |
55 | ------------
56 |
57 | - OnPlayerJoinLobby(cb)
58 | Will be called whenever someone join arena
59 |
60 | - OnPlayerExitLobby(cb)
61 | Will be called whenever player leave arena
62 | The array data returns
63 |
64 | - OnArenaStart(cb)
65 |
66 | - OnArenaEnd(cb)
67 |
68 | - OnArenaRoundEnd(cb)
69 |
70 | - On(cb)
71 | if the event is join/leave there is first argument source, second is arena instance
72 | for others such a like end,start etc, there is only one argument, and thats the arena instance.
73 | ```
74 | {
75 | MaximumRoundSaved,
76 | CurrentRound,
77 | ArenaIdentifier,
78 | ArenaLabel,
79 | MaximumCapacity,
80 | MinimumCapacity,
81 | CurrentCapacity,
82 | }
83 | ```
84 |
85 | Usage of these events
86 | ```LUA
87 | local arenaBuilder = exports.ArenaAPI
88 |
89 | local arena = arenaBuilder:GetArenaInstance("MyArena")
90 |
91 | arena.PlayerJoinArena(function(data)
92 | TriggerClientEvent("showNotification", data.source, "Welcome to the arena: " .. data.ArenaLabel)
93 | end)
94 | ```
95 |
96 | Second example of events
97 | ```LUA
98 | local arenaBuilder = exports.ArenaAPI
99 |
100 | local arena = arenaBuilder:GetArenaInstance("MyArena")
101 |
102 | arena.On("join",function(source, data)
103 | TriggerClientEvent("showNotification", source, "Welcome to the arena: " .. data.ArenaLabel)
104 | end)
105 | ```
106 |
107 | ------------
108 |
109 | #All functions bellow are from module, so use it like this
110 |
111 | ```LUA
112 | local arenaBuilder = exports.ArenaAPI
113 | local arena = arenaBuilder:CreateArena("gungame_1")
114 |
115 | arena.SetMaximumCapacity(10) -- maximum player
116 | arena.SetMinimumCapacity(2) -- minimum to start
117 | arena.SetArenaLabel("Gungame arena #1")
118 | ```
119 | ------------
120 |
121 | ### Setting info about arena
122 |
123 | ------------
124 | - SetMaximumCapacity(int number) Will set how many people can join to the arena
125 |
126 | - SetMinimumCapacity(int number) Will set how many players need to join to start game
127 |
128 | - SetArenaMaxRounds(int number) How many rounds this arena will have ?
129 |
130 | - SetArenaLabel(string name)
131 |
132 | - SetOwnWorld(boolean result) when players join to the arena it will create their own world with other players
133 |
134 | - SetMaximumArenaTime(int second) This will set for how long the arena can go,
135 | if the value isnt set the arena will be there forever
136 |
137 | - SetMaximumLobbyTime(int second)
138 | How long player have to wait in lobby before letting him into the game,
139 | if player leave the lobby the timer will reset to this value.
140 |
141 | - SetArenaPublic(boolean value)
142 | if true player will be able to acces arena from command /arena join [name]
143 | if false that means you will have to use somewhere else this function "AddPlayer(int source)"
144 |
145 | - RemoveWorldAfterWin(boolean result) if you have something like winner cutscene, set this on false, but you have to send player into world 0 by your code.
146 |
147 | ------------
148 |
149 | ### Getting info about arena
150 |
151 | ------------
152 |
153 | - GetMaximumCapacity()
154 |
155 | - GetMinimumCapacity()
156 |
157 | - GetMaximumRounds()
158 |
159 | - GetCurrentRound()
160 |
161 | - GetPlayerCount()
162 |
163 | - GetArenaIdentifier()
164 |
165 | - GetArenaLabel()
166 |
167 | - GetPlayerList()
168 |
169 | - GetOwnWorld() return boolean, id of world
170 |
171 | - IsArenaPublic() true/false (means if you can acces the arena with command /minigame)
172 |
173 | ------------
174 |
175 | **Player manipulation**
176 |
177 | ------------
178 |
179 | - AddPlayer(int source)
180 |
181 | - RemovePlayer(int source)
182 |
183 | ------------
184 |
185 | - Reset()
186 |
187 | - Destroy() will destroy arena and new one has to be created
188 |
189 | ------------
190 |
191 | - SetPlayerScore(int source, string key, object value)
192 |
193 | - GetPlayerScore(int source, string key)
194 |
195 | - GivePlayerScore(int source, string key, object value)
196 |
197 | - RemovePlayerScore(int source, string key, object value)
198 |
199 | - PlayerScoreExists(int source, string key)
200 |
201 | - DeleteScore(int source, string key)
202 |
203 | ------------
204 |
205 | ###**Functions (client side)**
206 |
207 | ------------
208 |
209 | - IsPlayerInAnyArena() true/false
210 |
211 | - IsPlayerInArena(string arena)
212 |
213 | - GetArenaIdentifier()
214 |
215 | - GetArenaLabel()
216 |
217 | - GetArenaMaximumSize()
218 |
219 | - GetArenaMinimumSize()
220 |
221 | - GetArenaCurrentSize()
222 |
223 | - GetCurrentArenaData() returns array
224 | - GetCurrentArenaData() returns array
225 | ```
226 | {
227 | MaximumRoundSaved,
228 | CurrentRound,
229 | ArenaIdentifier,
230 | ArenaLabel,
231 | MaximumCapacity,
232 | MinimumCapacity,
233 | CurrentCapacity,
234 | }
235 | ```
236 | ------------
237 |
238 | ### Events
239 |
240 | ------------
241 |
242 | - OnPlayerJoinLobby(string arena, cb)
243 | Will be called whenever someone join arena
244 |
245 | - OnPlayerExitLobby(string arena, cb)
246 | Will be called whenever player leave arena
247 |
248 | - OnArenaStart(string arena, cb)
249 | Will be called whenever arena started game
250 |
251 | - OnArenaEnd(string arena, cb)
252 | Will be called after arena runs out of time or player achieve enough points
253 |
254 | - OnArenaRoundEnd(string arena, cb)
255 |
256 | - On(string arena, string eventName, cb)
257 |
258 | The array data returns
259 | ```
260 | {
261 | MaximumRoundSaved,
262 | CurrentRound,
263 | ArenaIdentifier,
264 | ArenaLabel,
265 | MaximumCapacity,
266 | MinimumCapacity,
267 | CurrentCapacity,
268 | }
269 | ```
270 |
271 | ------------
--------------------------------------------------------------------------------
/server/module/arena.lua:
--------------------------------------------------------------------------------
1 | -- Just holder for arena virtual world ID
2 | ClaimedVirtualWorld = {}
3 |
4 | -- Will return + create Arena lobby
5 | --- @param identifier string
6 | function CreateArena(identifier)
7 | ArenaCreatorHelper(identifier)
8 | local arena = ArenaList[identifier]
9 | --------------------------------------------
10 | local self = {}
11 | --------------------------------------------
12 | -- Basic information about arena --
13 | --------------------------------------------
14 | self.SetOwnWorld = function(result)
15 | arena.OwnWorld = result
16 | if result then
17 | if ArenaList[identifier].OwnWorldID == 0 then
18 | local newID = 0
19 | for i = 1, 64 do
20 | if not ClaimedVirtualWorld[i] then
21 | newID = i
22 | ClaimedVirtualWorld[i] = i
23 | break
24 | end
25 | end
26 | if newID == 0 then
27 | print("WARNING the poolsize of virtual worlds have run out! Delete some Arena lobbies to make space!")
28 | else
29 | ArenaList[identifier].OwnWorldID = newID
30 | end
31 | end
32 | end
33 | end
34 |
35 | self.GetOwnWorld = function()
36 | return arena.OwnWorld, arena.OwnWorldID
37 | end
38 | --------
39 | self.RemoveWorldAfterWin = function(result)
40 | arena.DeleteWorldAfterWin = result
41 | end
42 | --------
43 | self.SetMaximumCapacity = function(number)
44 | arena.MaximumCapacity = number
45 | end
46 |
47 | self.GetMaximumCapacity = function()
48 | return arena.MaximumCapacity
49 | end
50 | --------
51 | self.SetMinimumCapacity = function(number)
52 | arena.MinimumCapacity = number
53 | end
54 |
55 | self.GetMinimumCapacity = function()
56 | return arena.MinimumCapacity
57 | end
58 | --------
59 | self.GetArenaIdentifier = function()
60 | return arena.ArenaIdentifier
61 | end
62 | --------
63 | self.SetArenaLabel = function(name)
64 | arena.ArenaLabel = name
65 | end
66 |
67 | self.GetArenaLabel = function()
68 | return arena.ArenaLabel
69 | end
70 | --------
71 | self.SetArenaMaxRounds = function(rounds)
72 | if arena.MaximumRoundSaved == nil then
73 | arena.MaximumRoundSaved = rounds
74 | end
75 | arena.CurrentRound = rounds
76 | end
77 |
78 | self.GetMaximumRounds = function()
79 | return arena.MaximumRoundSaved
80 | end
81 |
82 | self.GetCurrentRound = function()
83 | return arena.CurrentRound
84 | end
85 | --------
86 | self.SetMaximumArenaTime = function(second)
87 | arena.MaximumArenaTime = second
88 | arena.MaximumArenaTimeSaved = second
89 | end
90 |
91 | self.GetMaximumArenaTime = function()
92 | return arena.MaximumArenaTimeSaved
93 | end
94 | --------
95 | self.SetMaximumLobbyTime = function(second)
96 | arena.MaximumLobbyTime = second
97 | arena.MaximumLobbyTimeSaved = second
98 | end
99 |
100 | self.GetMaximumLobbyTime = function()
101 | return arena.MaximumLobbyTimeSaved
102 | end
103 | --------
104 | self.SetArenaPublic = function(value)
105 | arena.ArenaIsPublic = value
106 | end
107 |
108 | self.IsArenaPublic = function()
109 | return arena.ArenaIsPublic
110 | end
111 | --------------------------------------------
112 | -- Adding player into arena logic --
113 | --------------------------------------------
114 | self.AddPlayer = function(source)
115 | if arena.PlayerList[source] == nil then
116 | PlayerInfo[source] = arena.ArenaIdentifier
117 | arena.PlayerList[source] = true
118 | arena.PlayerScoreList[source] = {}
119 | arena.PlayerNameList[source] = GetPlayerName(source):gsub("<[^>]+>", " ")
120 |
121 | arena.CurrentCapacity = arena.CurrentCapacity + 1
122 |
123 | local data = GetDefaultDataFromArena(arena.ArenaIdentifier)
124 |
125 | CallOn(identifier, "join", source, data)
126 |
127 | arena.MaximumLobbyTime = arena.MaximumLobbyTimeSaved
128 |
129 | arena.ArenaState = "ArenaActive"
130 |
131 | TriggerClientEvent("ArenaAPI:sendStatus", -1, "updateData", ArenaList)
132 | TriggerClientEvent("ArenaAPI:sendStatus", source, "join", data)
133 | end
134 | end
135 | --------
136 | self.RemovePlayer = function(source, skipEvent)
137 | if arena.PlayerList[source] ~= nil then
138 | if arena.DeleteWorldAfterWin then
139 | SetPlayerRoutingBucket(source, 0)
140 | end
141 |
142 | PlayerInfo[source] = "none"
143 | arena.PlayerList[source] = nil
144 | arena.PlayerScoreList[source] = nil
145 | arena.PlayerNameList[source] = nil
146 |
147 | arena.CurrentCapacity = arena.CurrentCapacity - 1
148 | if arena.CurrentCapacity == 0 then
149 | arena.ArenaState = "ArenaInactive"
150 | end
151 |
152 | local data = GetDefaultDataFromArena(arena.ArenaIdentifier)
153 |
154 | CallOn(identifier, "leave", source, data)
155 |
156 | arena.MaximumLobbyTime = arena.MaximumLobbyTimeSaved
157 |
158 | TriggerClientEvent("ArenaAPI:sendStatus", -1, "updateData", ArenaList)
159 | if skipEvent == nil then TriggerClientEvent("ArenaAPI:sendStatus", source, "leave", data) end
160 | end
161 | end
162 | --------
163 | self.GetPlayerList = function()
164 | return arena.PlayerList
165 | end
166 | --------
167 | self.IsPlayerInArena = function(source)
168 | return arena.PlayerList[source] ~= nil
169 | end
170 | --------------------------------------------
171 | -- Setting player score logic --
172 | --------------------------------------------
173 | self.SetPlayerScore = function(source, key, value)
174 | arena.PlayerScoreList[source][key] = value
175 | end
176 | --------
177 | self.GetPlayerScore = function(source, key)
178 | return arena.PlayerScoreList[source][key]
179 | end
180 | --------
181 | self.GivePlayerScore = function(source, key, value)
182 | arena.PlayerScoreList[source][key] = arena.PlayerScoreList[source][key] + value
183 | end
184 | --------
185 | self.RemovePlayerScore = function(source, key, value)
186 | arena.PlayerScoreList[source][key] = arena.PlayerScoreList[source][key] - value
187 | end
188 | --------
189 | self.PlayerScoreExists = function(source, key)
190 | return arena.PlayerScoreList[source][key] ~= nil
191 | end
192 | --------
193 | self.DeleteScore = function(source, key)
194 | arena.PlayerScoreList[source][key] = nil
195 | end
196 | --------------------------------------------
197 | -- Basic manipulation arena --
198 | --------------------------------------------
199 | self.Destroy = function()
200 | CallOn(identifier, "end", arena)
201 |
202 | for k, v in pairs(arena.PlayerList) do
203 | self.RemovePlayer(k)
204 | end
205 |
206 | ClaimedVirtualWorld[ArenaList[identifier].OwnWorldID] = nil
207 | TriggerClientEvent("ArenaAPI:sendStatus", -1, "end", GetDefaultDataFromArena(arena.ArenaIdentifier))
208 | ArenaList[identifier] = nil
209 | end
210 | --------
211 | self.Reset = function()
212 | CallOn(identifier, "end", arena)
213 |
214 | for k, v in pairs(arena.PlayerList) do
215 | self.RemovePlayer(k, true)
216 | end
217 |
218 | ClaimedVirtualWorld[ArenaList[identifier].OwnWorldID] = nil
219 |
220 | arena.PlayerList = {}
221 | arena.PlayerScoreList = {}
222 | arena.ArenaState = "ArenaInactive"
223 |
224 | arena.MaximumArenaTime = arena.MaximumArenaTimeSaved
225 | arena.CurrentRound = arena.MaximumRoundSaved
226 | end
227 | --------------------------------------------
228 | -- Basic events for arena --
229 | --------------------------------------------
230 | self.OnPlayerJoinLobby = function(cb, test)
231 | return On(identifier, "join", cb)
232 | end
233 |
234 | self.OnPlayerExitLobby = function(cb)
235 | return On(identifier, "leave", cb)
236 | end
237 |
238 | self.OnArenaStart = function(cb)
239 | return On(identifier, "start", cb)
240 | end
241 |
242 | self.OnArenaEnd = function(cb)
243 | return On(identifier, "end", cb)
244 | end
245 |
246 | self.OnArenaRoundEnd = function(cb)
247 | return On(identifier, "roundEnd", cb)
248 | end
249 |
250 | self.On = function(eventName, cb)
251 | return On(identifier, eventName, cb)
252 | end
253 | --------------------------------------------
254 | return self
255 | end
256 |
257 | exports("CreateArena", CreateArena)
258 |
259 | function GetArenaInstance(identifier)
260 | return CreateArena(identifier)
261 | end
262 |
263 | exports("GetArenaInstance", GetArenaInstance)
--------------------------------------------------------------------------------