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 )