197 lines
5.3 KiB
Lua
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 )
|