Files
2025-05-31 10:13:27 +02:00

197 lines
5.3 KiB
Lua

resource.AddWorkshop( "3207278246" )
SquadMenu.blockDamage = SquadMenu.blockDamage or {}
SquadMenu.squads = SquadMenu.squads or {}
SquadMenu.lastSquadId = SquadMenu.lastSquadId or 0
--- Find a squad by it's ID.
function SquadMenu:GetSquad( id )
return self.squads[id]
end
--- Find and remove a squad by it's ID.
function SquadMenu:DeleteSquad( id )
local squad = self.squads[id]
if squad then
squad:Delete()
end
end
--- Remove a player id from join requests on all squads.
function SquadMenu:CleanupRequests( id, dontSync )
for _, squad in pairs( self.squads ) do
if squad.requestsById[id] then
squad.requestsById[id] = nil
if not dontSync then
squad:SyncRequests()
end
end
end
end
-- Updates the player name everywhere it appears.
function SquadMenu:UpdatePlayerName( ply )
if not IsValid( ply ) then return end
local id = self.GetPlayerId( ply )
local name = ply:Nick()
for _, squad in pairs( self.squads ) do
-- Update leader name
if squad.leaderId == id then
squad.leaderName = name
end
-- Update join request
if squad.requestsById[id] then
squad.requestsById[id] = name
squad:SyncRequests()
end
-- Update member name
if squad.membersById[id] then
squad.membersById[id] = name
squad:SyncWithMembers()
end
end
end
--- Create a new squad.
function SquadMenu:CreateSquad()
local id = self.lastSquadId + 1
self.lastSquadId = id
self.squads[id] = setmetatable( {
id = id,
name = "",
icon = "",
enableRings = false,
friendlyFire = false,
isPublic = false,
r = 255,
g = 255,
b = 255,
-- Members key-value table. Do not modify directly,
-- instead use squad:AddMember/squad:RemoveMember.
--
-- Each key is a player id from SquadMenu.GetPlayerId,
-- and each value is the player name.
membersById = {},
-- Join Requests key-value table.
--
-- Each key is a player id from SquadMenu.GetPlayerId,
-- and each value is the player name.
requestsById = {}
}, self.Squad )
self.PrintF( "Created squad #%d", id )
return self.squads[id]
end
-- Callbacks on FCVAR_REPLICATED cvars don't work clientside so we need this
cvars.AddChangeCallback( "squad_members_position", function()
SquadMenu.StartEvent( "squad_position_changed" )
net.Broadcast()
end, "changed_squad_members_position" )
--- Update player names on change
gameevent.Listen( "player_changename" )
hook.Add( "player_changename", "SquadMenu.UpdatePlayerName", function( data )
SquadMenu:UpdatePlayerName( Player( data.userid ) )
end )
--- Update player names on first spawn
hook.Add( "PlayerInitialSpawn", "SquadMenu.UpdatePlayerName", function( ply )
SquadMenu:UpdatePlayerName( ply )
end )
-- On disconnect, remove join requests and this player from their squad, if they have one
hook.Add( "PlayerDisconnected", "SquadMenu.PlayerCleanup", function( ply )
SquadMenu:CleanupRequests( SquadMenu.GetPlayerId( ply ) )
local squad = SquadMenu:GetSquad( ply:GetSquadID() )
if squad then
squad:RemoveMember( ply )
end
end )
--- Block damage between squad members
local blockDamage = SquadMenu.blockDamage
hook.Add( "PlayerShouldTakeDamage", "SquadMenu.BlockFriendlyFire", function( ply, attacker )
if not attacker.GetSquadID then return end
local id = ply:GetSquadID()
if id ~= -1 and ply ~= attacker and blockDamage[id] and id == attacker:GetSquadID() then
return false
end
end )
--- Chat commands and squad-only chat messages
local prefixes = {}
for _, prefix in ipairs( SquadMenu.CHAT_PREFIXES ) do
prefixes[prefix] = true
end
hook.Add( "PlayerSay", "SquadMenu.RemovePrefix", function( sender, text, _, channel )
-- Check for commands to open the menu
if text[1] == "!" then
text = string.lower( string.Trim( text ) )
if text == "!squad" or text == "!party" then
SquadMenu.StartEvent( "open_menu" )
net.Send( sender )
return ""
end
end
-- Check if this is supposed to be a members-only message
local isCustomChatSquadChannel = channel == "squad"
local parts = string.Explode( " ", text, false )
if not isCustomChatSquadChannel and ( not parts[1] or not prefixes[parts[1]] ) then return end
local id = sender:GetSquadID()
if id == -1 then
sender:ChatPrint( "You're not in a squad." )
return ""
end
if not isCustomChatSquadChannel then
table.remove( parts, 1 )
end
text = table.concat( parts, " " )
if text:len() == 0 then
sender:ChatPrint( "Please type a message to send to your squad members." )
return ""
end
local override = hook.Run( "SquadPlayerSay", sender, text )
if override ~= nil and ( not override or override == "" ) then return "" end
if type( override ) == "string" then text = override end
local members = SquadMenu:GetSquad( id ):GetActiveMembers()
SquadMenu.StartEvent( "members_chat", {
senderName = sender:Nick(),
text = text
} )
net.Send( members )
return ""
end, HOOK_HIGH )