Implement basic team/skin selection and spawning player on team base

This commit is contained in:
ChronosX88 2020-01-06 22:33:35 +04:00
commit a284a69e98
9 changed files with 424 additions and 0 deletions

38
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,38 @@
{
"Lua.diagnostics.globals": [
"addEventHandler",
"getRootElement",
"outputChatBox",
"source",
"spawnPlayer",
"setCameraMatrix",
"fadeCamera",
"toggleAllControls",
"showCursor",
"setPlayerHudComponentVisible",
"guiGetScreenSize",
"root",
"dxDrawText",
"dxDrawRectangle",
"tocolor",
"guiCreateLabel",
"resourceRoot",
"guiGetText",
"guiSetAlpha",
"bitExtract",
"destroyElement",
"removeEventHandler",
"outputDebugString",
"addEvent",
"triggerClientEvent",
"aclGetGroup",
"aclGroupAddObject",
"setElementModel",
"localPlayer",
"bindKey",
"setCameraTarget"
],
"Lua.diagnostics.disable": [
"lowercase-global"
]
}

171
client.lua Normal file
View File

@ -0,0 +1,171 @@
local screenW, screenH = guiGetScreenSize()
SkinSelectionMenu = class(function(menu)
menu.isTeamFull = false
menu.policeSkins = {280, 281, 282, 283, 284, 285, 288, 265, 266, 267}
menu.secretServiceSkins = {163, 164, 165, 166, 194}
menu.terroristsSkins = {124, 125, 126, 127, 111, 112}
menu._selectSecretService = function()
menu.teamSelected = Teams.SECRET_SERVICE
setElementModel(localPlayer, menu.secretServiceSkins[1])
menu._currentSkinIndex = 1
menu._currentSkinArray = menu.secretServiceSkins
end
menu._selectPolice = function()
menu.teamSelected = Teams.POLICE
setElementModel(localPlayer, menu.policeSkins[1])
menu._currentSkinIndex = 1
menu._currentSkinArray = menu.policeSkins
end
menu._selectTerrorists = function()
menu.teamSelected = Teams.TERRORISTS
setElementModel(localPlayer, menu.terroristsSkins[1])
menu._currentSkinIndex = 1
menu._currentSkinArray = menu.terroristsSkins
end
end)
function SkinSelectionMenu:showSkinSelectionDxLabels()
dxDrawText("Protect The President", (screenW * 0.2870) - 1, (screenH * 0.0528) - 1, (screenW * 0.6734) - 1, (screenH * 0.1176) - 1, tocolor(0, 0, 0, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("Protect The President", (screenW * 0.2870) + 1, (screenH * 0.0528) - 1, (screenW * 0.6734) + 1, (screenH * 0.1176) - 1, tocolor(0, 0, 0, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("Protect The President", (screenW * 0.2870) - 1, (screenH * 0.0528) + 1, (screenW * 0.6734) - 1, (screenH * 0.1176) + 1, tocolor(0, 0, 0, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("Protect The President", (screenW * 0.2870) + 1, (screenH * 0.0528) + 1, (screenW * 0.6734) + 1, (screenH * 0.1176) + 1, tocolor(0, 0, 0, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("Protect The President", screenW * 0.2870, screenH * 0.0528, screenW * 0.6734, screenH * 0.1176, tocolor(255, 255, 255, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("Select the team:", (screenW * 0.0896) - 1, (screenH * 0.2685) - 1, (screenW * 0.3693) - 1, (screenH * 0.3250) - 1, tocolor(0, 0, 0, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("Select the team:", (screenW * 0.0896) + 1, (screenH * 0.2685) - 1, (screenW * 0.3693) + 1, (screenH * 0.3250) - 1, tocolor(0, 0, 0, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("Select the team:", (screenW * 0.0896) - 1, (screenH * 0.2685) + 1, (screenW * 0.3693) - 1, (screenH * 0.3250) + 1, tocolor(0, 0, 0, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("Select the team:", (screenW * 0.0896) + 1, (screenH * 0.2685) + 1, (screenW * 0.3693) + 1, (screenH * 0.3250) + 1, tocolor(0, 0, 0, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("Select the team:", screenW * 0.0896, screenH * 0.2685, screenW * 0.3693, screenH * 0.3250, tocolor(255, 255, 255, 255), 2.00, "bankgothic", "left", "top", false, false, false, false, false)
dxDrawText("You can change skin via left & right arrow buttons. When you are done - click Space", screenW * 0.3089, screenH * 0.8111, screenW * 0.6896, screenH * 0.9185, tocolor(255, 255, 255, 255), 3.00, "arial", "left", "top", false, true, false, false, false)
if self.isTeamFull then
dxDrawText("Team is full!", (screenW * 0.6896) + 1, (screenH * 0.5630) + 1, (screenW * 0.7984) + 1, (screenH * 0.6139) + 1, tocolor(0, 0, 0, 255), 3.00, "arial", "left", "top", false, false, false, false, false)
dxDrawText("Team is full!", screenW * 0.6896, screenH * 0.5630, screenW * 0.7984, screenH * 0.6139, tocolor(241, 6, 0, 254), 3.00, "arial", "left", "top", false, false, false, false, false)
end
end
function SkinSelectionMenu:showSkinSelectionButtons()
self.secretServiceTeamButton = DxButton(
"secret_service",
0.0896,
0.3574,
0.2786,
0.0481,
tocolor(29, 253, 0, 200),
"Secret Service",
"pricedown",
2.0,
tocolor(255, 255, 255, 255),
true,
self._selectSecretService
)
self.policeTeamButton = DxButton(
"police",
0.0891,
0.4278,
0.2792,
0.0454,
tocolor(0, 23, 252, 200),
"Police",
"pricedown",
2.0,
tocolor(255, 255, 255, 255),
true,
self._selectPolice
)
self.terroristsTeamButton = DxButton(
"terrorists",
0.0891,
0.4917,
0.2792,
0.0472,
tocolor(251, 0, 0, 200),
"Terrorists",
"pricedown",
2.0,
tocolor(255, 255, 255, 255),
true,
self._selectTerrorists
)
self.secretServiceTeamButton:show()
self.policeTeamButton:show()
self.terroristsTeamButton:show()
end
function SkinSelectionMenu:hideSkinSelectionButtons()
self.secretServiceTeamButton:hide()
self.policeTeamButton:hide()
self.terroristsTeamButton:hide()
end
function SkinSelectionMenu:switchSkin(key)
if not self.teamSelected then
outputChatBox("Please select the team!")
return
end
if key == "arrow_r" then
if self._currentSkinIndex + 1 > #self._currentSkinArray then
self._currentSkinIndex = 1
setElementModel(localPlayer, self._currentSkinArray[self._currentSkinIndex])
return
else
self._currentSkinIndex = self._currentSkinIndex + 1
setElementModel(localPlayer, self._currentSkinArray[self._currentSkinIndex])
return
end
elseif key == "arrow_l" then
if self._currentSkinIndex - 1 < 1 then
self._currentSkinIndex = #self._currentSkinArray
setElementModel(localPlayer, self._currentSkinArray[self._currentSkinIndex])
return
else
self._currentSkinIndex = self._currentSkinIndex - 1
setElementModel(localPlayer, self._currentSkinArray[self._currentSkinIndex])
return
end
end
end
local function selectTeamAndSpawn(team, skin)
triggerServerEvent("onPlayerTeamSelected", localPlayer, team, skin)
end
addEventHandler("onClientResourceStart", resourceRoot, function()
skinSelectionMenu = SkinSelectionMenu()
skinSelectionMenu:showSkinSelectionButtons()
skinSelectionMenu._showLabels = function()
skinSelectionMenu:showSkinSelectionDxLabels()
end
skinSelectionMenu._switchSkin = function(key)
skinSelectionMenu:switchSkin(key)
end
bindKey("arrow_l", "down", skinSelectionMenu._switchSkin)
bindKey("arrow_r", "down", skinSelectionMenu._switchSkin)
addEventHandler("onClientRender", root, skinSelectionMenu._showLabels)
function _selectTeamAndSpawn()
selectTeamAndSpawn(skinSelectionMenu.teamSelected, skinSelectionMenu._currentSkinArray[skinSelectionMenu._currentSkinIndex])
end
bindKey("space", "down", _selectTeamAndSpawn)
skinSelectionMenu._selectSecretService()
end)
addEvent("onPlayerTeamFull", true)
addEventHandler("onPlayerTeamFull", root, function()
skinSelectionMenu.isTeamFull = true
setTimer(function()
skinSelectionMenu.isTeamFull = false
end, 2000, 1)
end)
addEvent("onPlayerTeamSelectedSuccessful", true)
addEventHandler("onPlayerTeamSelectedSuccessful", root, function()
unbindKey("arrow_l", "down", skinSelectionMenu._switchSkin)
unbindKey("arrow_r", "down", skinSelectionMenu._switchSkin)
unbindKey("space", "down", _selectTeamAndSpawn)
removeEventHandler("onClientRender", root, skinSelectionMenu._showLabels)
skinSelectionMenu:hideSkinSelectionButtons()
end)

5
enums.lua Normal file
View File

@ -0,0 +1,5 @@
Teams = {
SECRET_SERVICE = "secret_service",
POLICE = "police",
TERRORISTS = "terrorists"
}

63
gui/dxbutton.lua Normal file
View File

@ -0,0 +1,63 @@
DxButton = class(function(button, button_id, startX, startY, width, height, bgColor, text, textFont, textScale, textColor, textShadowEnabled, onClickHandler)
local screenW, screenH = guiGetScreenSize()
button.button_id = button_id
button.startX = startX * screenW
button.startY = startY * screenH
button.width = width * screenW
button.height = height * screenH
button.bgColor = bgColor
button.text = text
button.textFont = textFont
button.textScale = textScale
button.textColor = textColor
button.textShadowEnabled = textShadowEnabled
button.onClickHandler = onClickHandler
end)
function DxButton:show()
--self._invisibleLabel = guiCreateLabel(0.09, 0.36, 0.28, 0.05, self.button_id, true)
self._invisibleLabel = guiCreateLabel(self.startX, self.startY, self.width, self.height, self.button_id, false)
guiSetAlpha(self._invisibleLabel, 0.0)
self._drawButton = function()
dxDrawRectangle(self.startX, self.startY, self.width, self.height, self.bgColor)
if self._currentButtonUnderCursor then
local red, green, blue, alpha = extractRgbFromColor(self.bgColor)
local lightRed, lightGreen, lightBlue = shadeColor(red, green, blue, 20)
dxDrawRectangle(self.startX, self.startY, self.width, self.height, tocolor(lightRed, lightGreen, lightBlue, alpha))
end
if self.textShadowEnabled then
dxDrawText(self.text, self.startX + 1, self.startY + 1, self.width + 1, self.height + 1, tocolor(0, 0, 0, 255), self.textScale, self.textFont, "left", "top", false, false, false, false, false)
end
dxDrawText(self.text, self.startX, self.startY, self.width, self.height, self.textColor, self.textScale, self.textFont, "left", "top", false, false, false, false, false)
end
self._handleMouseOverButton = function()
if guiGetText(source) == self.button_id then
self._currentButtonUnderCursor = true
end
end
self._handleMouseLeaveButtonRectangle = function()
self._currentButtonUnderCursor = false
end
self._handleClickOnLabel = function()
if guiGetText(source) == self.button_id then
self.onClickHandler()
end
end
addEventHandler("onClientRender", root, self._drawButton)
addEventHandler("onClientMouseEnter", root, self._handleMouseOverButton)
addEventHandler("onClientMouseLeave", root, self._handleMouseLeaveButtonRectangle)
addEventHandler("onClientGUIClick", root, self._handleClickOnLabel)
end
function DxButton:hide()
destroyElement(self._invisibleLabel)
removeEventHandler("onClientRender", root, self._drawButton)
removeEventHandler("onClientMouseEnter", root, self._handleMouseOverButton)
removeEventHandler("onClientMouseLeave", root, self._handleMouseLeaveButtonRectangle)
removeEventHandler("onClientGUIClick", root, self._handleClickOnLabel)
end

11
meta.xml Normal file
View File

@ -0,0 +1,11 @@
<meta>
<info author="ChronosX88" type="gamemode" name="PTP" description="Classic Protect The President Mode" />
<script src="util\class.lua" type="shared"/>
<script src="util\color.lua" type="shared"/>
<script src="enums.lua" type="shared"/>
<script src="team.lua" type="shared"/>
<script src="server.lua" type="server"/>
<script src="client.lua" type="client"/>
<script src="gui\dxbutton.lua" type="client"/>
<oop>true</oop>
</meta>

43
server.lua Normal file
View File

@ -0,0 +1,43 @@
local teams = {}
local function mainOnPlayerJoin()
setCameraMatrix(source, 1654.3691, -1643.5967, 85.176224, 1658.8364, -1545.6569, 65.482597)
spawnPlayer(source, 1654.524, -1637.7119, 85.157089, 180.0, 0)
toggleAllControls(source, false, true, false)
setPlayerHudComponentVisible(source, "all", false)
fadeCamera(source, true, 5)
showCursor(source, true)
outputChatBox("Please select the class and skin of your player", source, 255, 255, 0)
end
local function spawnPlayerOnTeamBase(player, x, y, z, rotation, skinID)
showCursor(player, false)
spawnPlayer(player, x, y, z, rotation, skinID)
setCameraTarget(player)
fadeCamera(source, true)
setPlayerHudComponentVisible(player, "all", true)
toggleAllControls(player, true, true, true)
end
local function mainOnPlayerTeamSelected(team, skinID)
if type(team) ~= "string" or type(skinID) ~= "number" then
outputDebugString("OnPlayerTeamSelected: Invalid argument type")
end
if team == Teams.SECRET_SERVICE then
spawnPlayerOnTeamBase(source, 2795.0, -1825.0, 9.9, 90, skinID)
elseif team == Teams.POLICE then
spawnPlayerOnTeamBase(source, 1532.6, -1677.3, 5.9, 90, skinID)
elseif team == Teams.TERRORISTS then
spawnPlayerOnTeamBase(source, 1774.0, -1926.5, 13.5, 90, skinID)
end
triggerClientEvent(source, "onPlayerTeamSelectedSuccessful", resourceRoot)
end
addEvent("onPlayerTeamSelected", true)
addEventHandler("onPlayerTeamSelected", root, mainOnPlayerTeamSelected)
addEventHandler("onPlayerJoin", root, mainOnPlayerJoin)
addEventHandler("onResourceStart", root, function()
teams[Teams.SECRET_SERVICE] = Team(Teams.SECRET_SERVICE, "Secret Service", tocolor(29, 253, 0, 255))
teams[Teams.POLICE] = Team(Teams.POLICE, "Police", tocolor(0, 23, 252, 55))
teams[Teams.TERRORISTS] = Team(Teams.TERRORISTS, "Terrorists", tocolor(251, 0, 0, 200))
end)

6
team.lua Normal file
View File

@ -0,0 +1,6 @@
Team = class(function(team, teamID, teamName, teamColor)
team.teamID = teamID
team.teamName = teamName
team.teamColor = teamColor
team.playersCount = 0
end)

43
util/class.lua Normal file
View File

@ -0,0 +1,43 @@
function class(base, init)
local c = {} -- a new class instance
if not init and type(base) == 'function' then
init = base
base = nil
elseif type(base) == 'table' then
-- our new class is a shallow copy of the base class!
for i,v in pairs(base) do
c[i] = v
end
c._base = base
end
-- the class will be the metatable for all its objects,
-- and they will look up their methods in it.
c.__index = c
-- expose a constructor which can be called by <classname>(<args>)
local mt = {}
mt.__call = function(class_tbl, ...)
local obj = {}
setmetatable(obj, c)
if init then
init(obj, ...)
else
-- make sure that any stuff from the base class is initialized!
if base and base.init then
base.init(obj, ...)
end
end
return obj
end
c.init = init
c.is_a = function(self, klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m._base
end
return false
end
setmetatable(c, mt)
return c
end

44
util/color.lua Normal file
View File

@ -0,0 +1,44 @@
function roundNumber(number)
local _, decimals = math.modf(number)
if decimals < 0.5 then return math.floor(number) end
return math.ceil(number)
end
function shadeColor(red, green, blue, percent)
--[[red = (red * (100 + percent) / 100)
green = (green * (100 + percent) / 100)
blue = (blue * (100 + percent) / 100)]]
--percent = percent / 100
-- //FIXME don't work properly
red = red + (255 - red) * percent
green = green + (255 - green) * percent
blue = blue + (255 - blue) * percent
if red > 255 then
red = 255
end
if green > 255 then
green = 255
end
if blue > 255 then
blue = 255
end
red = roundNumber(red)
blue = roundNumber(blue)
green = roundNumber(green)
return red, green, blue
end
function extractRgbFromColor(color)
local red = bitExtract(color, 0, 8)
local green = bitExtract(color, 8, 8)
local blue = bitExtract(color, 16, 8)
local alpha = bitExtract(color, 24, 8)
return red, green, blue, alpha
end