Initial commit
This commit is contained in:
122
gamemodes/darkrp/gamemode/modules/hitmenu/cl_init.lua
Normal file
122
gamemodes/darkrp/gamemode/modules/hitmenu/cl_init.lua
Normal file
@@ -0,0 +1,122 @@
|
||||
local localplayer
|
||||
local hudText
|
||||
local textCol1, textCol2 = Color(0, 0, 0, 200), Color(128, 30, 30, 255)
|
||||
local plyMeta = FindMetaTable("Player")
|
||||
local activeHitmen = {}
|
||||
local postPlayerDraw
|
||||
local minHitDistanceSqr = GM.Config.minHitDistance * GM.Config.minHitDistance
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Interface functions
|
||||
---------------------------------------------------------------------------]]
|
||||
function plyMeta:drawHitInfo()
|
||||
activeHitmen[self] = true
|
||||
|
||||
hook.Add("PostPlayerDraw", "drawHitInfo", postPlayerDraw)
|
||||
end
|
||||
|
||||
function plyMeta:stopHitInfo()
|
||||
activeHitmen[self] = nil
|
||||
if table.IsEmpty(activeHitmen) then
|
||||
hook.Remove("PostPlayerDraw", "drawHitInfo")
|
||||
end
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Hooks
|
||||
---------------------------------------------------------------------------]]
|
||||
function DarkRP.hooks:onHitAccepted(hitman, target, customer)
|
||||
if not IsValid(hitman) then return end
|
||||
hitman:drawHitInfo()
|
||||
end
|
||||
|
||||
function DarkRP.hooks:onHitCompleted(hitman, target, customer)
|
||||
if not IsValid(hitman) then return end
|
||||
hitman:stopHitInfo()
|
||||
end
|
||||
|
||||
function DarkRP.hooks:onHitFailed(hitman, target, reason)
|
||||
if not IsValid(hitman) then return end
|
||||
hitman:stopHitInfo()
|
||||
end
|
||||
|
||||
hook.Add("EntityRemoved", "hitmenu", function(ent)
|
||||
activeHitmen[ent] = nil
|
||||
end)
|
||||
|
||||
hook.Add("HUDPaint", "DrawHitOption", function()
|
||||
localplayer = localplayer or LocalPlayer()
|
||||
hudText = hudText or GAMEMODE.Config.hudText
|
||||
local x, y
|
||||
local ply = localplayer:GetEyeTrace().Entity
|
||||
|
||||
if IsValid(ply) and ply:IsPlayer() and ply:isHitman() and not ply:hasHit() and localplayer:GetPos():DistToSqr(ply:GetPos()) < minHitDistanceSqr then
|
||||
x, y = ScrW() / 2, ScrH() / 2 + 30
|
||||
|
||||
draw.DrawNonParsedText(hudText, "Roboto20", x + 1, y + 1, textCol1, 1)
|
||||
draw.DrawNonParsedText(hudText, "Roboto20", x, y, textCol2, 1)
|
||||
end
|
||||
|
||||
if localplayer:isHitman() and localplayer:hasHit() and IsValid(localplayer:getHitTarget()) then
|
||||
x, y = chat.GetChatBoxPos()
|
||||
local text = DarkRP.getPhrase("current_hit", localplayer:getHitTarget():Nick())
|
||||
draw.DrawNonParsedText(text, "HUDNumber5", x + 1, y + 1, textCol1, 0)
|
||||
draw.DrawNonParsedText(text, "HUDNumber5", x, y, textCol2, 0)
|
||||
end
|
||||
end)
|
||||
|
||||
local lastKeyPress = 0
|
||||
hook.Add("KeyPress", "openHitMenu", function(ply, key)
|
||||
if key ~= IN_USE or lastKeyPress > CurTime() - 0.2 then return end
|
||||
lastKeyPress = CurTime()
|
||||
localplayer = localplayer or LocalPlayer()
|
||||
local hitman = localplayer:GetEyeTrace().Entity
|
||||
|
||||
if not IsValid(hitman) or not hitman:IsPlayer() or not hitman:isHitman() or localplayer:GetPos():DistToSqr(hitman:GetPos()) > minHitDistanceSqr then return end
|
||||
|
||||
local canRequest, message = hook.Call("canRequestHit", DarkRP.hooks, hitman, ply, nil, hitman:getHitPrice())
|
||||
|
||||
if not canRequest then
|
||||
GAMEMODE:AddNotify(DarkRP.getPhrase("cannot_request_hit", message or ""), 1, 4)
|
||||
surface.PlaySound("buttons/lightswitch2.wav")
|
||||
return
|
||||
end
|
||||
|
||||
DarkRP.openHitMenu(hitman)
|
||||
end)
|
||||
|
||||
hook.Add("InitPostEntity", "HitmanMenu", function()
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if IsValid(v) and v:isHitman() and v:hasHit() then
|
||||
v:drawHitInfo()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function postPlayerDraw(ply)
|
||||
if not activeHitmen[ply] then return end
|
||||
local pos, ang = ply:GetShootPos(), ply:EyeAngles()
|
||||
ang.p = 0
|
||||
ang:RotateAroundAxis(ang:Up(), 90)
|
||||
ang:RotateAroundAxis(ang:Forward(), 90)
|
||||
|
||||
cam.Start3D2D(pos, ang, 0.3)
|
||||
draw.DrawNonParsedText(GAMEMODE.Config.hitmanText, "Roboto20", 1, -100, textCol1, 1)
|
||||
draw.DrawNonParsedText(GAMEMODE.Config.hitmanText, "Roboto20", 0, -101, textCol2, 1)
|
||||
cam.End3D2D()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Networking
|
||||
---------------------------------------------------------------------------]]
|
||||
net.Receive("onHitAccepted", function(len)
|
||||
hook.Call("onHitAccepted", DarkRP.hooks, net.ReadEntity(), net.ReadEntity(), net.ReadEntity())
|
||||
end)
|
||||
|
||||
net.Receive("onHitCompleted", function(len)
|
||||
hook.Call("onHitCompleted", DarkRP.hooks, net.ReadEntity(), net.ReadEntity(), net.ReadEntity())
|
||||
end)
|
||||
|
||||
net.Receive("onHitFailed", function(len)
|
||||
hook.Call("onHitFailed", DarkRP.hooks, net.ReadEntity(), net.ReadEntity(), net.ReadString())
|
||||
end)
|
||||
35
gamemodes/darkrp/gamemode/modules/hitmenu/cl_interface.lua
Normal file
35
gamemodes/darkrp/gamemode/modules/hitmenu/cl_interface.lua
Normal file
@@ -0,0 +1,35 @@
|
||||
DarkRP.openHitMenu = DarkRP.stub{
|
||||
name = "openHitMenu",
|
||||
description = "Open the menu that requests a hit.",
|
||||
parameters = {
|
||||
{
|
||||
name = "hitman",
|
||||
description = "The hitman to request the hit to.",
|
||||
type = "Player",
|
||||
optional = false
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.drawHitInfo = DarkRP.stub{
|
||||
name = "drawHitInfo",
|
||||
description = "Start drawing the hit information above a hitman.",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.stopHitInfo = DarkRP.stub{
|
||||
name = "stopHitInfo",
|
||||
description = "Stop drawing the hit information above a hitman.",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
227
gamemodes/darkrp/gamemode/modules/hitmenu/cl_menu.lua
Normal file
227
gamemodes/darkrp/gamemode/modules/hitmenu/cl_menu.lua
Normal file
@@ -0,0 +1,227 @@
|
||||
local PANEL
|
||||
local minHitDistanceSqr = GM.Config.minHitDistance * GM.Config.minHitDistance
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Hitman menu
|
||||
---------------------------------------------------------------------------]]
|
||||
PANEL = {}
|
||||
|
||||
AccessorFunc(PANEL, "hitman", "Hitman")
|
||||
AccessorFunc(PANEL, "target", "Target")
|
||||
AccessorFunc(PANEL, "selected", "Selected")
|
||||
|
||||
function PANEL:Init()
|
||||
self.BaseClass.Init(self)
|
||||
|
||||
self.btnClose = vgui.Create("DButton", self)
|
||||
self.btnClose:SetText("")
|
||||
self.btnClose.DoClick = function() self:Remove() end
|
||||
self.btnClose.Paint = function(panel, w, h) derma.SkinHook("Paint", "WindowCloseButton", panel, w, h) end
|
||||
|
||||
self.icon = vgui.Create("SpawnIcon", self)
|
||||
self.icon:SetDisabled(true)
|
||||
self.icon.PaintOver = function(icon) icon:SetTooltip() end
|
||||
self.icon:SetTooltip()
|
||||
|
||||
self.title = vgui.Create("DLabel", self)
|
||||
self.title:SetText(DarkRP.getPhrase("hitman"))
|
||||
|
||||
self.name = vgui.Create("DLabel", self)
|
||||
self.price = vgui.Create("DLabel", self)
|
||||
|
||||
self.playerList = vgui.Create("DScrollPanel", self)
|
||||
|
||||
self.btnRequest = vgui.Create("HitmanMenuButton", self)
|
||||
self.btnRequest:SetText(DarkRP.getPhrase("hitmenu_request"))
|
||||
self.btnRequest.DoClick = function()
|
||||
if IsValid(self:GetTarget()) then
|
||||
RunConsoleCommand("darkrp", "requesthit", self:GetTarget():SteamID(), self:GetHitman():UserID())
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
self.btnCancel = vgui.Create("HitmanMenuButton", self)
|
||||
self.btnCancel:SetText(DarkRP.getPhrase("cancel"))
|
||||
self.btnCancel.DoClick = function() self:Remove() end
|
||||
|
||||
self:SetSkin(GAMEMODE.Config.DarkRPSkin)
|
||||
|
||||
self:InvalidateLayout()
|
||||
end
|
||||
|
||||
function PANEL:Think()
|
||||
if not IsValid(self:GetHitman()) or self:GetHitman():GetPos():DistToSqr(LocalPlayer():GetPos()) > minHitDistanceSqr then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
-- update the price (so the hitman can't scam)
|
||||
self.price:SetText(DarkRP.getPhrase("priceTag", DarkRP.formatMoney(self:GetHitman():getHitPrice()), ""))
|
||||
self.price:SizeToContents()
|
||||
end
|
||||
|
||||
function PANEL:PerformLayout()
|
||||
local w, h = self:GetSize()
|
||||
|
||||
self:SetSize(500, 700)
|
||||
self:Center()
|
||||
|
||||
self.btnClose:SetSize(24, 24)
|
||||
self.btnClose:SetPos(w - 24 - 5, 5)
|
||||
|
||||
self.icon:SetSize(128, 128)
|
||||
self.icon:SetModel(self:GetHitman():GetModel())
|
||||
self.icon:SetPos(20, 20)
|
||||
|
||||
self.title:SetFont("ScoreboardHeader")
|
||||
self.title:SetPos(20 + 128 + 20, 20)
|
||||
self.title:SizeToContents(true)
|
||||
|
||||
self.name:SizeToContents(true)
|
||||
self.name:SetText(DarkRP.getPhrase("name", self:GetHitman():Nick()))
|
||||
self.name:SetPos(20 + 128 + 20, 20 + self.title:GetTall())
|
||||
|
||||
self.price:SetFont("HUDNumber5")
|
||||
self.price:SetColor(Color(255, 0, 0, 255))
|
||||
self.price:SetText(DarkRP.getPhrase("priceTag", DarkRP.formatMoney(self:GetHitman():getHitPrice()), ""))
|
||||
self.price:SetPos(20 + 128 + 20, 20 + self.title:GetTall() + 20)
|
||||
self.price:SizeToContents(true)
|
||||
|
||||
self.playerList:SetPos(20, 20 + self.icon:GetTall() + 20)
|
||||
self.playerList:SetWide(self:GetWide() - 40)
|
||||
|
||||
self.btnRequest:SetPos(20, h - self.btnRequest:GetTall() - 20)
|
||||
self.btnRequest:SetButtonColor(Color(0, 120, 30, 255))
|
||||
|
||||
self.btnCancel:SetPos(w - self.btnCancel:GetWide() - 20, h - self.btnCancel:GetTall() - 20)
|
||||
self.btnCancel:SetButtonColor(Color(140, 0, 0, 255))
|
||||
|
||||
self.playerList:StretchBottomTo(self.btnRequest, 20)
|
||||
|
||||
self.BaseClass.PerformLayout(self)
|
||||
end
|
||||
|
||||
function PANEL:Paint()
|
||||
local w, h = self:GetSize()
|
||||
|
||||
surface.SetDrawColor(Color(0, 0, 0, 200))
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
function PANEL:AddPlayerRows()
|
||||
local players = table.Copy(player.GetAll())
|
||||
|
||||
table.sort(players, function(a, b)
|
||||
local aTeam, bTeam, aNick, bNick = team.GetName(a:Team()), team.GetName(b:Team()), string.lower(a:Nick()), string.lower(b:Nick())
|
||||
return aTeam == bTeam and aNick < bNick or aTeam < bTeam
|
||||
end)
|
||||
|
||||
for _, v in ipairs(players) do
|
||||
local canRequest = hook.Call("canRequestHit", DarkRP.hooks, self:GetHitman(), LocalPlayer(), v, self:GetHitman():getHitPrice())
|
||||
if not canRequest then continue end
|
||||
|
||||
local line = vgui.Create("HitmanMenuPlayerRow")
|
||||
line:SetPlayer(v)
|
||||
self.playerList:AddItem(line)
|
||||
line:SetWide(self.playerList:GetWide() - 100)
|
||||
line:Dock(TOP)
|
||||
|
||||
line.DoClick = function()
|
||||
self:SetTarget(line:GetPlayer())
|
||||
|
||||
if IsValid(self:GetSelected()) then
|
||||
self:GetSelected():SetSelected(false)
|
||||
end
|
||||
|
||||
line:SetSelected(true)
|
||||
self:SetSelected(line)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vgui.Register("HitmanMenu", PANEL, "DPanel")
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Hitmenu button
|
||||
---------------------------------------------------------------------------]]
|
||||
PANEL = {}
|
||||
|
||||
AccessorFunc(PANEL, "btnColor", "ButtonColor")
|
||||
|
||||
function PANEL:PerformLayout()
|
||||
self:SetSize(self:GetParent():GetWide() / 2 - 30, 100)
|
||||
self:SetFont("HUDNumber5")
|
||||
self:SetTextColor(color_white)
|
||||
|
||||
self.BaseClass.PerformLayout(self)
|
||||
end
|
||||
|
||||
function PANEL:Paint()
|
||||
local w, h = self:GetSize()
|
||||
local col = self:GetButtonColor() or Color(0, 120, 30, 255)
|
||||
surface.SetDrawColor(col.r, col.g, col.b, col.a)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
end
|
||||
|
||||
vgui.Register("HitmanMenuButton", PANEL, "DButton")
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Player row
|
||||
---------------------------------------------------------------------------]]
|
||||
PANEL = {}
|
||||
|
||||
AccessorFunc(PANEL, "player", "Player")
|
||||
AccessorFunc(PANEL, "selected", "Selected", FORCE_BOOL)
|
||||
|
||||
function PANEL:Init()
|
||||
self.lblName = vgui.Create("DLabel", self)
|
||||
self.lblName:SetMouseInputEnabled(false)
|
||||
self.lblName:SetColor(Color(255,255,255,200))
|
||||
|
||||
self.lblTeam = vgui.Create("DLabel", self)
|
||||
self.lblTeam:SetMouseInputEnabled(false)
|
||||
self.lblTeam:SetColor(Color(255,255,255,200))
|
||||
|
||||
self:SetText("")
|
||||
|
||||
self:SetCursor("hand")
|
||||
end
|
||||
|
||||
function PANEL:PerformLayout()
|
||||
local ply = self:GetPlayer()
|
||||
if not IsValid(ply) then self:Remove() return end
|
||||
|
||||
self.lblName:SetFont("UiBold")
|
||||
self.lblName:SetText(DarkRP.deLocalise(ply:Nick()))
|
||||
self.lblName:SizeToContents()
|
||||
self.lblName:SetPos(10, 1)
|
||||
|
||||
self.lblTeam:SetFont("UiBold")
|
||||
self.lblTeam:SetText((ply.DarkRPVars and DarkRP.deLocalise(ply:getDarkRPVar("job") or "")) or team.GetName(ply:Team()))
|
||||
self.lblTeam:SizeToContents()
|
||||
self.lblTeam:SetPos(self:GetWide() / 2, 1)
|
||||
end
|
||||
|
||||
function PANEL:Paint()
|
||||
if not IsValid(self:GetPlayer()) then self:Remove() return end
|
||||
|
||||
local color = team.GetColor(self:GetPlayer():Team())
|
||||
color.a = self:GetSelected() and 70 or 255
|
||||
|
||||
surface.SetDrawColor(color)
|
||||
surface.DrawRect(0, 0, self:GetWide(), 20)
|
||||
end
|
||||
|
||||
vgui.Register("HitmanMenuPlayerRow", PANEL, "Button")
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Open the hit menu
|
||||
---------------------------------------------------------------------------]]
|
||||
function DarkRP.openHitMenu(hitman)
|
||||
local frame = vgui.Create("HitmanMenu")
|
||||
frame:SetHitman(hitman)
|
||||
frame:AddPlayerRows()
|
||||
frame:SetVisible(true)
|
||||
frame:MakePopup()
|
||||
frame:ParentToHUD()
|
||||
end
|
||||
79
gamemodes/darkrp/gamemode/modules/hitmenu/sh_init.lua
Normal file
79
gamemodes/darkrp/gamemode/modules/hitmenu/sh_init.lua
Normal file
@@ -0,0 +1,79 @@
|
||||
local plyMeta = FindMetaTable("Player")
|
||||
local hitmanTeams = {}
|
||||
local minHitDistanceSqr = GM.Config.minHitDistance * GM.Config.minHitDistance
|
||||
|
||||
function plyMeta:isHitman()
|
||||
return hitmanTeams[self:Team()]
|
||||
end
|
||||
|
||||
function plyMeta:hasHit()
|
||||
return self:getDarkRPVar("hasHit") or false
|
||||
end
|
||||
|
||||
function plyMeta:getHitTarget()
|
||||
return self:getDarkRPVar("hitTarget")
|
||||
end
|
||||
|
||||
function plyMeta:getHitPrice()
|
||||
return self:getDarkRPVar("hitPrice") or GAMEMODE.Config.minHitPrice
|
||||
end
|
||||
|
||||
function DarkRP.addHitmanTeam(job)
|
||||
if not job or not RPExtraTeams[job] then return end
|
||||
if DarkRP.DARKRP_LOADING and DarkRP.disabledDefaults["hitmen"][RPExtraTeams[job].command] then return end
|
||||
|
||||
hitmanTeams[job] = true
|
||||
end
|
||||
|
||||
DarkRP.getHitmanTeams = fp{fn.Id, hitmanTeams}
|
||||
|
||||
function DarkRP.hooks:canRequestHit(hitman, customer, target, price)
|
||||
if not hitman:isHitman() then return false, DarkRP.getPhrase("player_not_hitman") end
|
||||
if customer:GetPos():DistToSqr(hitman:GetPos()) > minHitDistanceSqr then return false, DarkRP.getPhrase("distance_too_big") end
|
||||
if not customer:Alive() then return false, DarkRP.getPhrase("must_be_alive_to_do_x", DarkRP.getPhrase("place_a_hit")) end
|
||||
if hitman == target then return false, DarkRP.getPhrase("hitman_no_suicide") end
|
||||
if hitman == customer then return false, DarkRP.getPhrase("hitman_no_self_order") end
|
||||
if not customer:canAfford(price) then return false, DarkRP.getPhrase("cant_afford", DarkRP.getPhrase("hit")) end
|
||||
if price < GAMEMODE.Config.minHitPrice then return false, DarkRP.getPhrase("price_too_low") end
|
||||
if hitman:hasHit() then return false, DarkRP.getPhrase("hitman_already_has_hit") end
|
||||
if IsValid(target) and ((target:getDarkRPVar("lastHitTime") or -GAMEMODE.Config.hitTargetCooldown) > CurTime() - GAMEMODE.Config.hitTargetCooldown) then return false, DarkRP.getPhrase("hit_target_recently_killed_by_hit") end
|
||||
if IsValid(customer) and ((customer.lastHitAccepted or -GAMEMODE.Config.hitCustomerCooldown) > CurTime() - GAMEMODE.Config.hitCustomerCooldown) then return false, DarkRP.getPhrase("customer_recently_bought_hit") end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
hook.Add("onJobRemoved", "hitmenuUpdate", function(i, job)
|
||||
hitmanTeams[i] = nil
|
||||
end)
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
DarkRPVars
|
||||
---------------------------------------------------------------------------]]
|
||||
DarkRP.registerDarkRPVar("hasHit", net.WriteBit, fn.Compose{tobool, net.ReadBit})
|
||||
DarkRP.registerDarkRPVar("hitTarget", net.WriteEntity, net.ReadEntity)
|
||||
DarkRP.registerDarkRPVar("hitPrice", fn.Curry(fn.Flip(net.WriteInt), 2)(32), fn.Partial(net.ReadInt, 32))
|
||||
DarkRP.registerDarkRPVar("lastHitTime", fn.Curry(fn.Flip(net.WriteInt), 2)(32), fn.Partial(net.ReadInt, 32))
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Chat commands
|
||||
---------------------------------------------------------------------------]]
|
||||
DarkRP.declareChatCommand{
|
||||
command = "hitprice",
|
||||
description = "Set the price of your hits",
|
||||
condition = plyMeta.isHitman,
|
||||
delay = 10
|
||||
}
|
||||
|
||||
DarkRP.declareChatCommand{
|
||||
command = "requesthit",
|
||||
description = "Request a hit from the player you're looking at",
|
||||
delay = 5,
|
||||
condition = fn.Compose{fn.Not, fn.Null, fn.Curry(fn.Filter, 2)(plyMeta.isHitman), player.GetAll}
|
||||
}
|
||||
|
||||
DarkRP.declareChatCommand{
|
||||
command = "cancelhit",
|
||||
description = "Cancel your on active hit",
|
||||
delay = 5,
|
||||
condition = plyMeta.hasHit
|
||||
}
|
||||
209
gamemodes/darkrp/gamemode/modules/hitmenu/sh_interface.lua
Normal file
209
gamemodes/darkrp/gamemode/modules/hitmenu/sh_interface.lua
Normal file
@@ -0,0 +1,209 @@
|
||||
DarkRP.PLAYER.isHitman = DarkRP.stub{
|
||||
name = "isHitman",
|
||||
description = "Whether this player is a hitman.",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
{
|
||||
name = "answer",
|
||||
description = "Whether this player is a hitman.",
|
||||
type = "boolean"
|
||||
}
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.hasHit = DarkRP.stub{
|
||||
name = "hasHit",
|
||||
description = "Whether this hitman has a hit.",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
{
|
||||
name = "answer",
|
||||
description = "Whether this player has a hit.",
|
||||
type = "boolean"
|
||||
}
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.getHitTarget = DarkRP.stub{
|
||||
name = "getHitTarget",
|
||||
description = "Get the target of a hitman.",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
{
|
||||
name = "target",
|
||||
description = "The target of the hit.",
|
||||
type = "Player"
|
||||
}
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.getHitPrice = DarkRP.stub{
|
||||
name = "getHitPrice",
|
||||
description = "Get the price the hitman demands for his work.",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
{
|
||||
name = "price",
|
||||
description = "The price of the next hit.",
|
||||
type = "number"
|
||||
}
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.addHitmanTeam = DarkRP.stub{
|
||||
name = "addHitmanTeam",
|
||||
description = "Make this team a hitman.",
|
||||
parameters = {
|
||||
{
|
||||
name = "team number",
|
||||
description = "The number of the team (e.g. TEAM_MOB)",
|
||||
type = "number",
|
||||
optional = false
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP
|
||||
}
|
||||
|
||||
DarkRP.getHitmanTeams = DarkRP.stub{
|
||||
name = "getHitmanTeams",
|
||||
description = "Get all the hitman teams.",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
{
|
||||
name = "tbl",
|
||||
description = "A table in which the keys are TEAM_ numbers and the values are just true.",
|
||||
type = "table"
|
||||
}
|
||||
},
|
||||
metatable = DarkRP
|
||||
}
|
||||
|
||||
DarkRP.hookStub{
|
||||
name = "canRequestHit",
|
||||
description = "Whether someone can request a hit.",
|
||||
parameters = {
|
||||
{
|
||||
name = "hitman",
|
||||
description = "The hitman performing the hit",
|
||||
type = "Player"
|
||||
},
|
||||
{
|
||||
name = "customer",
|
||||
description = "The customer for the current hit.",
|
||||
type = "Player"
|
||||
},
|
||||
{
|
||||
name = "target",
|
||||
description = "The target of the current hit",
|
||||
type = "Player"
|
||||
},
|
||||
{
|
||||
name = "price",
|
||||
description = "The agreed upon price.",
|
||||
type = "number"
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
{
|
||||
name = "canRequest",
|
||||
description = "A yes or no as to whether the hit can be requested.",
|
||||
type = "boolean"
|
||||
},
|
||||
{
|
||||
name = "message",
|
||||
description = "The message that is shown when they can't request the hit.",
|
||||
type = "string"
|
||||
},
|
||||
{
|
||||
name = "price",
|
||||
description = "An override for the price of the hit.",
|
||||
type = "number"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DarkRP.hookStub{
|
||||
name = "onHitAccepted",
|
||||
description = "When a hitman accepts a hit.",
|
||||
parameters = {
|
||||
{
|
||||
name = "hitman",
|
||||
description = "The hitman performing the hit.",
|
||||
type = "Player"
|
||||
},
|
||||
{
|
||||
name = "target",
|
||||
description = "The target of the current hit.",
|
||||
type = "Player"
|
||||
},
|
||||
{
|
||||
name = "customer",
|
||||
description = "The customer of the current hit.",
|
||||
type = "Player"
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DarkRP.hookStub{
|
||||
name = "onHitCompleted",
|
||||
description = "When a hitman finishes a hit.",
|
||||
parameters = {
|
||||
{
|
||||
name = "hitman",
|
||||
description = "The hitman performing the hit.",
|
||||
type = "Player"
|
||||
},
|
||||
{
|
||||
name = "target",
|
||||
description = "The target of the current hit.",
|
||||
type = "Player"
|
||||
},
|
||||
{
|
||||
name = "customer",
|
||||
description = "The customer of the current hit.",
|
||||
type = "Player"
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DarkRP.hookStub{
|
||||
name = "onHitFailed",
|
||||
description = "When a hit fails for some reason.",
|
||||
parameters = {
|
||||
{
|
||||
name = "hitman",
|
||||
description = "The hitman performing the hit.",
|
||||
type = "Player"
|
||||
},
|
||||
{
|
||||
name = "target",
|
||||
description = "The target of the current hit.",
|
||||
type = "Player"
|
||||
},
|
||||
{
|
||||
name = "reason",
|
||||
description = "why the hit failed.",
|
||||
type = "string"
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
|
||||
}
|
||||
}
|
||||
271
gamemodes/darkrp/gamemode/modules/hitmenu/sv_init.lua
Normal file
271
gamemodes/darkrp/gamemode/modules/hitmenu/sv_init.lua
Normal file
@@ -0,0 +1,271 @@
|
||||
local plyMeta = FindMetaTable("Player")
|
||||
local hits = {}
|
||||
local questionCallback
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Net messages
|
||||
---------------------------------------------------------------------------]]
|
||||
util.AddNetworkString("onHitAccepted")
|
||||
util.AddNetworkString("onHitCompleted")
|
||||
util.AddNetworkString("onHitFailed")
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Interface functions
|
||||
---------------------------------------------------------------------------]]
|
||||
DarkRP.getHits = fp{fn.Id, hits}
|
||||
|
||||
function plyMeta:requestHit(customer, target, price)
|
||||
local canRequest, msg, cost = hook.Call("canRequestHit", DarkRP.hooks, self, customer, target, price)
|
||||
price = cost or price
|
||||
|
||||
if canRequest == false then
|
||||
DarkRP.notify(customer, 1, 4, msg)
|
||||
return false
|
||||
end
|
||||
|
||||
DarkRP.createQuestion(DarkRP.getPhrase("accept_hit_request", customer:Nick(), target:Nick(), DarkRP.formatMoney(price)),
|
||||
"hit" .. self:UserID() .. "|" .. customer:UserID() .. "|" .. target:UserID(),
|
||||
self,
|
||||
20,
|
||||
questionCallback,
|
||||
customer,
|
||||
target,
|
||||
price
|
||||
)
|
||||
|
||||
DarkRP.notify(customer, 1, 4, DarkRP.getPhrase("hit_requested"))
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function plyMeta:placeHit(customer, target, price)
|
||||
if hits[self] then DarkRP.error("This person has an active hit!", 2) end
|
||||
|
||||
if not customer:canAfford(price) then
|
||||
DarkRP.notify(customer, 1, 4, DarkRP.getPhrase("cant_afford", DarkRP.getPhrase("hit")))
|
||||
return
|
||||
end
|
||||
|
||||
hits[self] = {}
|
||||
hits[self].price = price -- the agreed upon price (as opposed to the price set by the hitman)
|
||||
|
||||
self:setHitCustomer(customer)
|
||||
self:setHitTarget(target)
|
||||
|
||||
DarkRP.payPlayer(customer, self, price)
|
||||
|
||||
hook.Call("onHitAccepted", DarkRP.hooks, self, target, customer)
|
||||
end
|
||||
|
||||
function plyMeta:setHitTarget(target)
|
||||
if not hits[self] then DarkRP.error("This person has no active hit!", 2) end
|
||||
|
||||
self:setSelfDarkRPVar("hitTarget", target)
|
||||
self:setDarkRPVar("hasHit", target and true or nil)
|
||||
end
|
||||
|
||||
function plyMeta:setHitPrice(price)
|
||||
self:setDarkRPVar("hitPrice", math.Min(GAMEMODE.Config.maxHitPrice or 50000, math.Max(GAMEMODE.Config.minHitPrice or 200, price)))
|
||||
end
|
||||
|
||||
function plyMeta:setHitCustomer(customer)
|
||||
if not hits[self] then DarkRP.error("This person has no active hit!", 2) end
|
||||
|
||||
hits[self].customer = customer
|
||||
end
|
||||
|
||||
function plyMeta:getHitCustomer()
|
||||
return hits[self] and hits[self].customer or nil
|
||||
end
|
||||
|
||||
function plyMeta:abortHit(message)
|
||||
if not hits[self] then DarkRP.error("This person has no active hit!", 2) end
|
||||
|
||||
message = message or ""
|
||||
|
||||
hook.Call("onHitFailed", DarkRP.hooks, self, self:getHitTarget(), message)
|
||||
DarkRP.notifyAll(0, 4, DarkRP.getPhrase("hit_aborted", message))
|
||||
|
||||
self:finishHit()
|
||||
end
|
||||
|
||||
function plyMeta:cancelHit()
|
||||
if not hits[self] then DarkRP.error("This person has no active hit!", 2) end
|
||||
if not self:canAfford(hits[self].price) then
|
||||
DarkRP.notify(self, 1, 4, DarkRP.getPhrase("cant_afford", DarkRP.getPhrase("hit_cancel")))
|
||||
return
|
||||
end
|
||||
|
||||
DarkRP.payPlayer(self, hits[self].customer, hits[self].price)
|
||||
|
||||
self:abortHit(DarkRP.getPhrase("hit_cancelled"))
|
||||
end
|
||||
|
||||
function plyMeta:finishHit()
|
||||
self:setHitCustomer(nil)
|
||||
self:setHitTarget(nil)
|
||||
hits[self] = nil
|
||||
end
|
||||
|
||||
function questionCallback(answer, hitman, customer, target, price)
|
||||
if not IsValid(customer) then return end
|
||||
if not IsValid(hitman) or not hitman:isHitman() then return end
|
||||
|
||||
if not IsValid(customer) then
|
||||
DarkRP.notify(hitman, 1, 4, DarkRP.getPhrase("customer_left_server"))
|
||||
return
|
||||
end
|
||||
|
||||
if not IsValid(target) then
|
||||
DarkRP.notify(hitman, 1, 4, DarkRP.getPhrase("target_left_server"))
|
||||
return
|
||||
end
|
||||
|
||||
if not tobool(answer) then
|
||||
DarkRP.notify(customer, 1, 4, DarkRP.getPhrase("hit_declined"))
|
||||
return
|
||||
end
|
||||
|
||||
if hits[hitman] then return end
|
||||
|
||||
DarkRP.notify(hitman, 1, 4, DarkRP.getPhrase("hit_accepted"))
|
||||
|
||||
hitman:placeHit(customer, target, price)
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Chat commands
|
||||
---------------------------------------------------------------------------]]
|
||||
DarkRP.defineChatCommand("hitprice", function(ply, args)
|
||||
if not ply:isHitman() then return "" end
|
||||
local price = DarkRP.toInt(args) or 0
|
||||
ply:setHitPrice(price)
|
||||
price = ply:getHitPrice()
|
||||
|
||||
DarkRP.notify(ply, 2, 4, DarkRP.getPhrase("hit_price_set", DarkRP.formatMoney(price)))
|
||||
|
||||
return ""
|
||||
end)
|
||||
|
||||
DarkRP.defineChatCommand("requesthit", function(ply, args)
|
||||
args = string.Explode(' ', args)
|
||||
local target = DarkRP.findPlayer(args[1])
|
||||
local traceEnt = ply:GetEyeTrace().Entity
|
||||
local hitman = IsValid(traceEnt) and traceEnt:IsPlayer() and traceEnt or Player(tonumber(args[2] or -1) or -1)
|
||||
|
||||
if not IsValid(hitman) or not IsValid(target) or not hitman:IsPlayer() then
|
||||
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), ""))
|
||||
return ""
|
||||
end
|
||||
|
||||
hitman:requestHit(ply, target, hitman:getHitPrice())
|
||||
|
||||
return ""
|
||||
end)
|
||||
|
||||
DarkRP.defineChatCommand("cancelhit", function(ply, args)
|
||||
if not hits[ply] then
|
||||
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("no_active_hit"))
|
||||
return ""
|
||||
end
|
||||
|
||||
ply:cancelHit()
|
||||
end)
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Hooks
|
||||
---------------------------------------------------------------------------]]
|
||||
function DarkRP.hooks:onHitAccepted(hitman, target, customer)
|
||||
net.Start("onHitAccepted")
|
||||
net.WriteEntity(hitman)
|
||||
net.WriteEntity(target)
|
||||
net.WriteEntity(customer)
|
||||
net.Broadcast()
|
||||
|
||||
DarkRP.notify(customer, 0, 8, DarkRP.getPhrase("hit_accepted"))
|
||||
customer.lastHitAccepted = CurTime()
|
||||
|
||||
DarkRP.log("Hitman " .. hitman:Nick() .. " accepted a hit on " .. target:Nick() .. ", ordered by " .. customer:Nick() .. " for " .. DarkRP.formatMoney(hits[hitman].price), Color(255, 0, 255))
|
||||
end
|
||||
|
||||
function DarkRP.hooks:onHitCompleted(hitman, target, customer)
|
||||
net.Start("onHitCompleted")
|
||||
net.WriteEntity(hitman)
|
||||
net.WriteEntity(target)
|
||||
net.WriteEntity(customer)
|
||||
net.Broadcast()
|
||||
|
||||
DarkRP.notifyAll(0, 6, DarkRP.getPhrase("hit_complete", hitman:Nick()))
|
||||
|
||||
local targetname = IsValid(target) and target:Nick() or "disconnected player"
|
||||
local customername = IsValid(customer) and customer:Nick() or "disconnected player"
|
||||
|
||||
DarkRP.log("Hitman " .. hitman:Nick() .. " finished a hit on " .. targetname .. ", ordered by " .. customername .. " for " .. DarkRP.formatMoney(hits[hitman].price), Color(255, 0, 255))
|
||||
|
||||
target:setDarkRPVar("lastHitTime", CurTime())
|
||||
|
||||
hitman:finishHit()
|
||||
end
|
||||
|
||||
function DarkRP.hooks:onHitFailed(hitman, target, reason)
|
||||
net.Start("onHitFailed")
|
||||
net.WriteEntity(hitman)
|
||||
net.WriteEntity(target)
|
||||
net.WriteString(reason)
|
||||
net.Broadcast()
|
||||
|
||||
local targetname = IsValid(target) and target:Nick() or "disconnected player"
|
||||
|
||||
DarkRP.log("Hit on " .. targetname .. " failed. Reason: " .. reason, Color(255, 0, 255))
|
||||
end
|
||||
|
||||
hook.Add("PlayerDeath", "DarkRP Hitman System", function(ply, inflictor, attacker)
|
||||
if hits[ply] then -- player was hitman
|
||||
ply:abortHit(DarkRP.getPhrase("hitman_died"))
|
||||
end
|
||||
|
||||
if IsValid(attacker) and attacker:IsPlayer() and hits[attacker] and attacker:getHitTarget() == ply then
|
||||
hook.Call("onHitCompleted", DarkRP.hooks, attacker, ply, hits[attacker].customer)
|
||||
end
|
||||
|
||||
for hitman in pairs(hits) do
|
||||
if not hitman or not IsValid(hitman) then hits[hitman] = nil continue end
|
||||
if hitman:getHitTarget() == ply then
|
||||
hitman:abortHit(DarkRP.getPhrase("target_died"))
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("PlayerDisconnected", "Hitman system", function(ply)
|
||||
if hits[ply] then
|
||||
ply:abortHit(DarkRP.getPhrase("hitman_left_server"))
|
||||
end
|
||||
|
||||
for hitman, hit in pairs(hits) do
|
||||
if hitman:getHitTarget() == ply then
|
||||
hitman:abortHit(DarkRP.getPhrase("target_left_server"))
|
||||
end
|
||||
|
||||
if hit.customer == ply then
|
||||
hitman:abortHit(DarkRP.getPhrase("customer_left_server"))
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("playerArrested", "Hitman system", function(ply)
|
||||
if not hits[ply] or not IsValid(hits[ply].customer) then return end
|
||||
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
if not v:isCP() then continue end
|
||||
|
||||
DarkRP.notify(v, 0, 8, DarkRP.getPhrase("x_had_hit_ordered_by_y", ply:Nick(), hits[ply].customer:Nick()))
|
||||
end
|
||||
|
||||
ply:abortHit(DarkRP.getPhrase("hitman_arrested"))
|
||||
end)
|
||||
|
||||
hook.Add("OnPlayerChangedTeam", "Hitman system", function(ply, prev, new)
|
||||
if hits[ply] then
|
||||
ply:abortHit(DarkRP.getPhrase("hitman_changed_team"))
|
||||
end
|
||||
end)
|
||||
164
gamemodes/darkrp/gamemode/modules/hitmenu/sv_interface.lua
Normal file
164
gamemodes/darkrp/gamemode/modules/hitmenu/sv_interface.lua
Normal file
@@ -0,0 +1,164 @@
|
||||
DarkRP.PLAYER.requestHit = DarkRP.stub{
|
||||
name = "requestHit",
|
||||
description = "Request a hit to a hitman.",
|
||||
parameters = {
|
||||
{
|
||||
name = "customer",
|
||||
description = "The customer who paid for the hit.",
|
||||
type = "Player",
|
||||
optional = false
|
||||
},
|
||||
{
|
||||
name = "target",
|
||||
description = "The target of the hit.",
|
||||
type = "Player",
|
||||
optional = false
|
||||
},
|
||||
{
|
||||
name = "price",
|
||||
description = "The price of the hit.",
|
||||
type = "number",
|
||||
optional = false
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
{
|
||||
name = "succeeded",
|
||||
description = "Whether the hit request could be made.",
|
||||
type = "boolean"
|
||||
}
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.placeHit = DarkRP.stub{
|
||||
name = "placeHit",
|
||||
description = "Place an actual hit.",
|
||||
parameters = {
|
||||
{
|
||||
name = "customer",
|
||||
description = "The customer who paid for the hit.",
|
||||
type = "Player",
|
||||
optional = false
|
||||
},
|
||||
{
|
||||
name = "target",
|
||||
description = "The target of the hit.",
|
||||
type = "Player",
|
||||
optional = false
|
||||
},
|
||||
{
|
||||
name = "price",
|
||||
description = "The price of the hit.",
|
||||
type = "number",
|
||||
optional = false
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.setHitTarget = DarkRP.stub{
|
||||
name = "setHitTarget",
|
||||
description = "Set the target of a hit",
|
||||
parameters = {
|
||||
{
|
||||
name = "target",
|
||||
description = "The target of the hit.",
|
||||
type = "Player",
|
||||
optional = false
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.setHitPrice = DarkRP.stub{
|
||||
name = "setHitPrice",
|
||||
description = "Set the price of a hit",
|
||||
parameters = {
|
||||
{
|
||||
name = "price",
|
||||
description = "The price of the hit.",
|
||||
type = "number",
|
||||
optional = false
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.setHitCustomer = DarkRP.stub{
|
||||
name = "setHitCustomer",
|
||||
description = "Set the customer who pays for the hit.",
|
||||
parameters = {
|
||||
{
|
||||
name = "customer",
|
||||
description = "The customer who paid for the hit.",
|
||||
type = "Player",
|
||||
optional = false
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.getHitCustomer = DarkRP.stub{
|
||||
name = "getHitCustomer",
|
||||
description = "Get the customer for the current hit",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
{
|
||||
name = "customer",
|
||||
description = "The customer for the current hit",
|
||||
type = "Player"
|
||||
}
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.abortHit = DarkRP.stub{
|
||||
name = "abortHit",
|
||||
description = "Abort a hit",
|
||||
parameters = {
|
||||
{
|
||||
name = "message",
|
||||
description = "The reason why the hit was aborted",
|
||||
type = "string",
|
||||
optional = true
|
||||
}
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.PLAYER.finishHit = DarkRP.stub{
|
||||
name = "finishHit",
|
||||
description = "End a hit without a message",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
},
|
||||
metatable = DarkRP.PLAYER
|
||||
}
|
||||
|
||||
DarkRP.getHits = DarkRP.stub{
|
||||
name = "getHits",
|
||||
description = "Get all the active hits",
|
||||
parameters = {
|
||||
},
|
||||
returns = {
|
||||
{
|
||||
name = "hits",
|
||||
description = "A table in which the keys are hitmen and the values are hit information, like the customer.",
|
||||
type = "table"
|
||||
}
|
||||
},
|
||||
metatable = DarkRP
|
||||
}
|
||||
Reference in New Issue
Block a user