381 lines
10 KiB
Lua
381 lines
10 KiB
Lua
function SquadMenu.GetLanguageText( id )
|
|
return language.GetPhrase( "squad_menu." .. id ):Trim()
|
|
end
|
|
|
|
function SquadMenu:PlayUISound( path )
|
|
if self.Config.enableSounds then
|
|
sound.Play( path, Vector(), 0, 120, 0.75 )
|
|
end
|
|
end
|
|
|
|
local L = SquadMenu.GetLanguageText
|
|
|
|
function SquadMenu.GlobalMessage( ... )
|
|
chat.AddText( SquadMenu.THEME_COLOR, "[" .. L( "title" ) .. "] ", Color( 255, 255, 255 ), ... )
|
|
end
|
|
|
|
function SquadMenu.SquadMessage( ... )
|
|
local squad = SquadMenu.mySquad
|
|
if not squad then return end
|
|
|
|
local contents = { color_white, "[", squad.color, squad.name, color_white, "] ", ... }
|
|
|
|
if CustomChat then
|
|
CustomChat:AddMessage( contents, "squad" )
|
|
else
|
|
chat.AddText( unpack( contents ) )
|
|
end
|
|
end
|
|
|
|
function SquadMenu.LeaveMySquad( buttonToBlank, leaveNow )
|
|
local squad = SquadMenu.mySquad
|
|
if not squad then return end
|
|
|
|
if not leaveNow and squad.leaderId == SquadMenu.GetPlayerId( LocalPlayer() ) then
|
|
Derma_Query( L"leave_leader", L"leave_squad", L"yes", function()
|
|
SquadMenu.LeaveMySquad( buttonToBlank, true )
|
|
end, L"no" )
|
|
|
|
return
|
|
end
|
|
|
|
if IsValid( buttonToBlank ) then
|
|
buttonToBlank:SetEnabled( false )
|
|
buttonToBlank:SetText( "..." )
|
|
end
|
|
|
|
SquadMenu.StartCommand( SquadMenu.LEAVE_SQUAD )
|
|
net.SendToServer()
|
|
end
|
|
|
|
--- If GMinimap is installed, update squad members' blips.
|
|
function SquadMenu:UpdatePlayerBlips( icon, color )
|
|
if not self.mySquad then return end
|
|
|
|
local me = LocalPlayer()
|
|
local byId = self.AllPlayersById()
|
|
|
|
for _, member in ipairs( self.mySquad.members ) do
|
|
local ply = byId[member.id]
|
|
|
|
if ply and ply ~= me then
|
|
ply:SetBlipIcon( icon )
|
|
ply:SetBlipColor( color )
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Set the current members of the local player's squad.
|
|
--- Updates the HUD and shows join/leave messages (if `printMessages` is `true`).
|
|
---
|
|
--- `newMembers` is an array where items are also arrays
|
|
--- with a number (player id) and a string (player name).
|
|
function SquadMenu:SetMembers( newMembers, printMessages )
|
|
local members = self.mySquad.members
|
|
local membersById = self.mySquad.membersById
|
|
local keep = {}
|
|
|
|
-- Add new members that we do not have on our end
|
|
for _, m in ipairs( newMembers ) do
|
|
local id = m[1]
|
|
local member = { id = id, name = m[2] }
|
|
|
|
keep[id] = true
|
|
|
|
if not membersById[id] then
|
|
membersById[id] = member
|
|
members[#members + 1] = member
|
|
|
|
self:AddMemberToHUD( member )
|
|
|
|
if printMessages then
|
|
self.SquadMessage( string.format( L"member_joined", member.name ) )
|
|
end
|
|
end
|
|
end
|
|
|
|
local byId = self.AllPlayersById()
|
|
|
|
-- Remove members that we have locally but do not exist on `newMembers`.
|
|
-- Backwards loop because we use `table.remove`
|
|
for i = #members, 1, -1 do
|
|
local member = members[i]
|
|
local id = member.id
|
|
|
|
if not keep[id] then
|
|
membersById[id] = nil
|
|
table.remove( members, i )
|
|
|
|
self:RemoveMemberFromHUD( member )
|
|
|
|
if printMessages then
|
|
self.SquadMessage( string.format( L"member_left", member.name ) )
|
|
end
|
|
|
|
local ply = byId[id]
|
|
|
|
if IsValid( ply ) and GMinimap then
|
|
ply:SetBlipIcon( nil )
|
|
ply:SetBlipColor( nil )
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Set the local player's squad.
|
|
--- `data` is a table that comes from `squad:GetBasicInfo`.
|
|
function SquadMenu:SetupSquad( data )
|
|
local squad = self.mySquad or { id = -1 }
|
|
local isUpdate = data.id == squad.id
|
|
|
|
self.mySquad = squad
|
|
|
|
squad.id = data.id
|
|
squad.name = data.name
|
|
squad.icon = data.icon
|
|
|
|
squad.leaderId = data.leaderId
|
|
squad.leaderName = data.leaderName or ""
|
|
|
|
squad.enableRings = data.enableRings
|
|
squad.friendlyFire = data.friendlyFire
|
|
squad.isPublic = data.isPublic
|
|
|
|
squad.color = Color( data.r, data.g, data.b )
|
|
|
|
if CustomChat and squad.name then
|
|
CustomChat:CreateCustomChannel( "squad", squad.name, squad.icon )
|
|
end
|
|
|
|
if not isUpdate then
|
|
squad.requests = {}
|
|
squad.members = {}
|
|
squad.membersById = {}
|
|
|
|
self:PlayUISound( "buttons/combine_button3.wav" )
|
|
self.SquadMessage( L"squad_welcome", squad.color, " " .. squad.name )
|
|
self.SquadMessage( L"chat_tip", " " .. table.concat( self.CHAT_PREFIXES, ", " ) )
|
|
end
|
|
|
|
self:UpdateMembersHUD()
|
|
self:SetMembers( data.members, isUpdate )
|
|
|
|
if IsValid( self.frame ) then
|
|
self:RequestSquadListUpdate()
|
|
self:UpdateSquadStatePanel()
|
|
self:UpdateRequestsPanel()
|
|
self:UpdateSquadMembersPanel()
|
|
self:UpdateSquadPropertiesPanel()
|
|
|
|
self.frame:SetActiveTabByIndex( 3 ) -- squad members
|
|
end
|
|
|
|
if GMinimap then
|
|
self:UpdatePlayerBlips( "gminimap/blips/npc_default.png", squad.color )
|
|
|
|
hook.Add( "CanSeePlayerBlip", "ShowSquadBlips", function( ply )
|
|
if ply:GetSquadID() == squad.id then return true, 50000 end
|
|
end )
|
|
end
|
|
end
|
|
|
|
function SquadMenu:OnLeaveSquad( reason )
|
|
if GMinimap then
|
|
self:UpdatePlayerBlips( nil, nil )
|
|
hook.Remove( "CanSeePlayerBlip", "ShowSquadBlips" )
|
|
end
|
|
|
|
local reasonText = {
|
|
[self.LEAVE_REASON_DELETED] = "deleted_squad",
|
|
[self.LEAVE_REASON_KICKED] = "kicked_from_squad"
|
|
}
|
|
|
|
if self.mySquad then
|
|
self.GlobalMessage( L( reasonText[reason] or "left_squad" ) )
|
|
self:PlayUISound( "buttons/combine_button2.wav" )
|
|
end
|
|
|
|
self.mySquad = nil
|
|
self:RemoveMembersHUD()
|
|
|
|
if IsValid( self.frame ) then
|
|
self:RequestSquadListUpdate()
|
|
self:UpdateSquadStatePanel()
|
|
self:UpdateRequestsPanel()
|
|
self:UpdateSquadMembersPanel()
|
|
self:UpdateSquadPropertiesPanel()
|
|
|
|
if self.frame.lastTabIndex ~= 5 then -- not in settings
|
|
self.frame:SetActiveTabByIndex( 1 ) -- squad list
|
|
end
|
|
end
|
|
|
|
if CustomChat then
|
|
CustomChat:RemoveCustomChannel( "squad" )
|
|
end
|
|
end
|
|
|
|
----------
|
|
|
|
local commands = {}
|
|
|
|
commands[SquadMenu.SQUAD_LIST] = function()
|
|
SquadMenu:UpdateSquadList( SquadMenu.ReadTable() )
|
|
end
|
|
|
|
commands[SquadMenu.SETUP_SQUAD] = function()
|
|
local data = SquadMenu.ReadTable()
|
|
SquadMenu:SetupSquad( data )
|
|
end
|
|
|
|
commands[SquadMenu.LEAVE_SQUAD] = function()
|
|
local reason = net.ReadUInt( 3 )
|
|
SquadMenu:OnLeaveSquad( reason )
|
|
end
|
|
|
|
commands[SquadMenu.REQUESTS_LIST] = function()
|
|
local squad = SquadMenu.mySquad
|
|
if not squad then return end
|
|
|
|
local requests = squad.requests
|
|
|
|
-- Remember which players have requested before
|
|
local alreadyRequested = {}
|
|
|
|
for _, member in ipairs( requests ) do
|
|
alreadyRequested[member.id] = true
|
|
end
|
|
|
|
-- Compare the new requests against what we already got
|
|
local requestsById = SquadMenu.ReadTable()
|
|
local newCount = 0
|
|
|
|
for id, name in pairs( requestsById ) do
|
|
if not alreadyRequested[id] then
|
|
-- This is a new request for us
|
|
requests[#requests + 1] = { id = id, name = name }
|
|
newCount = newCount + 1
|
|
|
|
SquadMenu.SquadMessage( string.format( L"request_message", name ) )
|
|
end
|
|
end
|
|
|
|
if newCount > 0 then
|
|
SquadMenu:PlayUISound( "buttons/combine_button1.wav" )
|
|
end
|
|
|
|
-- Remove requests we already got if they aren't on the new requests list
|
|
for i = #requests, 1, -1 do
|
|
local member = requests[i]
|
|
|
|
if not requestsById[member.id] then
|
|
table.remove( requests, i )
|
|
end
|
|
end
|
|
|
|
SquadMenu:UpdateRequestsPanel()
|
|
end
|
|
|
|
commands[SquadMenu.PING] = function()
|
|
local pos = net.ReadVector()
|
|
local label = net.ReadString()
|
|
local id = net.ReadString()
|
|
|
|
local ping = SquadMenu.pings[id]
|
|
|
|
if not ping then
|
|
ping = {}
|
|
end
|
|
|
|
ping.pos = pos
|
|
ping.label = label
|
|
ping.start = RealTime()
|
|
ping.lifetime = 5
|
|
|
|
SquadMenu.pings[id] = ping
|
|
|
|
if not SquadMenu.Config.enableSounds then return end
|
|
|
|
local eyePos = EyePos()
|
|
local soundDir = pos - eyePos
|
|
soundDir:Normalize()
|
|
|
|
sound.Play( "friends/friend_join.wav", eyePos + soundDir * 500, 100, 120, 1 )
|
|
end
|
|
|
|
commands[SquadMenu.BROADCAST_EVENT] = function()
|
|
local data = SquadMenu.ReadTable()
|
|
local event = data.event
|
|
|
|
SquadMenu.PrintF( "Event received: %s", event )
|
|
|
|
if event == "open_menu" then
|
|
SquadMenu:OpenFrame()
|
|
|
|
elseif event == "squad_position_changed" then
|
|
if SquadMenu.membersPanel then
|
|
SquadMenu.membersPanel:InvalidateLayout()
|
|
end
|
|
|
|
elseif event == "player_joined_squad" then
|
|
local squad = SquadMenu.mySquad
|
|
if not squad then return end
|
|
|
|
-- Remove this player from my requests list
|
|
local requests = squad.requests
|
|
|
|
for i, member in ipairs( requests ) do
|
|
if data.playerId == member.id then
|
|
table.remove( requests, i )
|
|
break
|
|
end
|
|
end
|
|
|
|
SquadMenu:UpdateRequestsPanel()
|
|
|
|
elseif event == "squad_created" or event == "squad_deleted" then
|
|
SquadMenu:RequestSquadListUpdate()
|
|
|
|
if event == "squad_created" and data.name and SquadMenu.GetShowCreationMessage() then
|
|
local color = Color( data.r, data.g, data.b )
|
|
SquadMenu.GlobalMessage( string.format( L"squad_created", data.leaderName ), color, " " .. data.name )
|
|
end
|
|
|
|
elseif event == "members_chat" then
|
|
local squad = SquadMenu.mySquad
|
|
if not squad then return end
|
|
|
|
SquadMenu.SquadMessage( squad.color, data.senderName, color_white, ": ", data.text )
|
|
end
|
|
end
|
|
|
|
net.Receive( "squad_menu.command", function()
|
|
local cmd = net.ReadUInt( SquadMenu.COMMAND_SIZE )
|
|
|
|
if not commands[cmd] then
|
|
SquadMenu.PrintF( "Received a unknown network command! (%d)", cmd )
|
|
return
|
|
end
|
|
|
|
commands[cmd]( ply, ent )
|
|
end )
|
|
|
|
concommand.Add(
|
|
"squad_menu",
|
|
function() SquadMenu:OpenFrame() end,
|
|
nil,
|
|
"Opens the squad menu."
|
|
)
|
|
|
|
if engine.ActiveGamemode() == "sandbox" then
|
|
list.Set(
|
|
"DesktopWindows",
|
|
"SquadMenuDesktopIcon",
|
|
{
|
|
title = SquadMenu.GetLanguageText( "title" ),
|
|
icon = "materials/squad_menu/squad_menu.png",
|
|
init = function() SquadMenu:OpenFrame() end
|
|
}
|
|
)
|
|
end
|