├── gamemodes └── fretta13 │ ├── creditsandcontact.txt │ ├── fretta13.txt │ └── gamemode │ ├── player_colours.lua │ ├── cl_notify.lua │ ├── player_class.lua │ ├── vgui │ ├── vgui_hudbase.lua │ ├── vgui_hudelement.lua │ ├── vgui_scoreboard_small.lua │ ├── vgui_hudcommon.lua │ ├── vgui_gamenotice.lua │ ├── vgui_hudlayout.lua │ ├── vgui_scoreboard.lua │ ├── vgui_scoreboard_team.lua │ └── vgui_vote.lua │ ├── class_default.lua │ ├── utility.lua │ ├── cl_gmchanger.lua │ ├── cl_splashscreen.lua │ ├── cl_deathnotice.lua │ ├── cl_scores.lua │ ├── cl_help.lua │ ├── player_extension.lua │ ├── cl_init.lua │ ├── cl_hud.lua │ ├── sv_spectator.lua │ ├── round_controller.lua │ ├── cl_selectscreen.lua │ ├── sv_gmchanger.lua │ ├── shared.lua │ ├── skin.lua │ └── init.lua ├── README.md └── LICENSE /gamemodes/fretta13/creditsandcontact.txt: -------------------------------------------------------------------------------- 1 | Original gamemode by garry. Conversion and updates by JetBoom. 2 | 3 | Any problems, e-mail me at williammoodhe@gmail.com -------------------------------------------------------------------------------- /gamemodes/fretta13/fretta13.txt: -------------------------------------------------------------------------------- 1 | "fretta13" 2 | { 3 | "base" "base" 4 | "title" "Fretta Gamemode Base" 5 | "category" "pvp" 6 | "menusystem" "0" 7 | 8 | "author_name" "TEAM GARRY" 9 | "author_email" "" 10 | "author_url" "http://www.garrysmod.com/" 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # About 2 | When fretta stopped being supported by Facepunch, gmod updates eventually broke many original and fun games still using it as a base. 3 | fretta13 is an update of the abandoned fretta gamemode base for Garry's Mod. It's meant as a direct replacement for fretta. 4 | If anyone would like to update older, broken gamemodes still stuck using "fretta" as a base, the first step should be to point to fretta13 as the new base. 5 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/player_colours.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | list.Set( "PlayerColours", "red", Color( 255, 0, 0 ) ) 4 | list.Set( "PlayerColours", "yellow", Color( 255, 255, 0 ) ) 5 | list.Set( "PlayerColours", "green", Color( 43, 235, 79 ) ) 6 | list.Set( "PlayerColours", "blue", Color( 43, 158, 255 ) ) 7 | list.Set( "PlayerColours", "orange", Color( 255, 148, 39 ) ) 8 | list.Set( "PlayerColours", "pink", Color( 255, 148, 255 ) ) 9 | list.Set( "PlayerColours", "lilac", Color( 120, 133, 255 ) ) 10 | list.Set( "PlayerColours", "army", Color( 120, 158, 18 ) ) 11 | list.Set( "PlayerColours", "grey", Color( 200, 200, 200 ) ) 12 | 13 | if ( CLIENT ) then 14 | CreateClientConVar( "cl_playercolor", "", true, true ) 15 | end 16 | 17 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/cl_notify.lua: -------------------------------------------------------------------------------- 1 | 2 | local function CreateLeftNotify() 3 | 4 | local x, y = chat.GetChatBoxPos() 5 | 6 | g_LeftNotify = vgui.Create( "DNotify" ) 7 | 8 | g_LeftNotify:SetPos( 32, 0 ) 9 | g_LeftNotify:SetSize( ScrW(), y - 8 ) 10 | g_LeftNotify:SetAlignment( 1 ) 11 | g_LeftNotify:ParentToHUD() 12 | 13 | end 14 | 15 | hook.Add( "InitPostEntity", "CreateLeftNotify", CreateLeftNotify ) 16 | 17 | function GM:NotifyGMVote( name, gamemode, votesneeded ) 18 | 19 | local dl = vgui.Create( "DLabel" ) 20 | dl:SetFont( "FRETTA_MEDIUM_SHADOW" ) 21 | dl:SetTextColor( Color( 255, 255, 255, 255 ) ) 22 | dl:SetText( Format( "%s voted for %s (need %i more)", name, gamemode, votesneeded ) ) 23 | dl:SizeToContents() 24 | g_LeftNotify:AddItem( dl, 5 ) 25 | 26 | end 27 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/player_class.lua: -------------------------------------------------------------------------------- 1 | 2 | module( "player_class", package.seeall ) 3 | 4 | local ClassTables = {} 5 | 6 | 7 | 8 | function Register( name, classtable ) 9 | ClassTables[ name ] = classtable 10 | ClassTables[ name ].m_HasBeenSetup = false 11 | end 12 | 13 | function Get( name ) 14 | 15 | if ( !ClassTables[ name ] ) then return {} end 16 | 17 | // Derive class here. 18 | // I have favoured using table.Inherit over using a meta table 19 | // This is to the performance hit is once, now, rather than on every usage 20 | if ( !ClassTables[ name ].m_HasBeenSetup ) then 21 | 22 | ClassTables[ name ].m_HasBeenSetup = true 23 | 24 | local Base = ClassTables[ name ].Base 25 | if ( ClassTables[ name ].Base && Get( Base ) ) then 26 | ClassTables[ name ] = table.Inherit( ClassTables[ name ], Get( Base ) ) 27 | ClassTables[ name ].BaseClass = Get( Base ) 28 | end 29 | 30 | end 31 | 32 | return ClassTables[ name ] 33 | end 34 | 35 | 36 | function GetClassName( name ) 37 | 38 | local class = Get( name ) 39 | if (!class) then return name end 40 | 41 | return class.DisplayName 42 | 43 | end 44 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/vgui/vgui_hudbase.lua: -------------------------------------------------------------------------------- 1 | local PANEL = {} 2 | 3 | surface.CreateLegacyFont( "Trebuchet MS", 32, 800, true, false, "FHUDElement" ) 4 | 5 | AccessorFunc( PANEL, "m_bPartOfBar", "PartOfBar" ) 6 | 7 | function PANEL:Init() 8 | 9 | self:SetText( "-" ) 10 | self:SetTextColor( self:GetDefaultTextColor() ) 11 | self:SetFont( "FHUDElement" ) 12 | 13 | self:ChooseParent() 14 | 15 | end 16 | 17 | // This makes it so that it's behind chat & hides when you're in the menu 18 | // But it also removes the ability to click on it. So override it if you want to. 19 | function PANEL:ChooseParent() 20 | self:ParentToHUD() 21 | end 22 | 23 | function PANEL:GetPadding() 24 | return 16 25 | end 26 | 27 | function PANEL:GetDefaultTextColor() 28 | return Color( 255, 255, 255, 255 ) 29 | end 30 | 31 | function PANEL:GetTextLabelColor() 32 | return Color( 255, 255, 0 ) 33 | end 34 | 35 | function PANEL:GetTextLabelFont() 36 | return "HudSelectionText" 37 | end 38 | 39 | function PANEL:Paint() 40 | 41 | if ( !self.m_bPartOfBar ) then 42 | draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 100 ) ) 43 | end 44 | 45 | end 46 | 47 | derma.DefineControl( "HudBase", "A HUD Base Element (override to change the style)", PANEL, "DLabel" ) 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/vgui/vgui_hudelement.lua: -------------------------------------------------------------------------------- 1 | local PANEL = {} 2 | 3 | /*--------------------------------------------------------- 4 | Name: Init 5 | ---------------------------------------------------------*/ 6 | function PANEL:Init() 7 | 8 | end 9 | 10 | function PANEL:SetLabel( text ) 11 | 12 | self.LabelPanel = vgui.Create( "DLabel", self ) 13 | self.LabelPanel:SetText( text ) 14 | self.LabelPanel:SetTextColor( self:GetTextLabelColor() ) 15 | self.LabelPanel:SetFont( self:GetTextLabelFont() ) 16 | 17 | end 18 | 19 | /*--------------------------------------------------------- 20 | Name: PerformLayout 21 | ---------------------------------------------------------*/ 22 | function PANEL:PerformLayout() 23 | 24 | self:SetContentAlignment( 5 ) 25 | 26 | if ( self.LabelPanel ) then 27 | self.LabelPanel:SetPos( self:GetPadding(), self:GetPadding() ) 28 | self.LabelPanel:SizeToContents() 29 | self.LabelPanel:SetSize( self.LabelPanel:GetWide() + self:GetPadding() * 0.5, self.LabelPanel:GetTall() + self:GetPadding() * 0.5 ) 30 | self:SetTextInset( self.LabelPanel:GetWide() + self:GetPadding(), 0 ) 31 | self:SetContentAlignment( 4 ) 32 | end 33 | 34 | self:SizeToContents( ) 35 | self:SetSize( self:GetWide() + self:GetPadding(), self:GetTall() + self:GetPadding() ) 36 | 37 | end 38 | 39 | derma.DefineControl( "DHudElement", "A HUD Element", PANEL, "HudBase" ) 40 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/vgui/vgui_scoreboard_small.lua: -------------------------------------------------------------------------------- 1 | local PANEL = {} 2 | 3 | Derma_Hook( PANEL, "Paint", "Paint", "SpectatorInfo" ) 4 | Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "SpectatorInfo" ) 5 | Derma_Hook( PANEL, "PerformLayout", "Layout", "SpectatorInfo" ) 6 | 7 | function PANEL:Init() 8 | 9 | self.LastThink = 0 10 | 11 | end 12 | 13 | function PANEL:Setup( iTeam, pMainScoreboard ) 14 | self.iTeam = iTeam 15 | end 16 | 17 | function PANEL:GetPlayers() 18 | return team.GetPlayers( self.iTeam ) 19 | end 20 | 21 | function PANEL:ShouldShow() 22 | 23 | local players = team.GetPlayers( self.iTeam ) 24 | if ( !players || #players == 0 ) then 25 | return false 26 | end 27 | 28 | return true 29 | 30 | end 31 | 32 | function PANEL:UpdateText( NewText ) 33 | 34 | local OldText = self:GetValue() 35 | if ( OldText == NewText ) then return end 36 | 37 | self:SetText( NewText ) 38 | self:SizeToContents() 39 | self:InvalidateLayout() 40 | self:GetParent():InvalidateLayout() 41 | 42 | end 43 | 44 | function PANEL:Think() 45 | 46 | if ( self.LastThink > RealTime() ) then return end 47 | self.LastThink = RealTime() + 1 48 | 49 | local players = team.GetPlayers( self.iTeam ) 50 | if ( !players || #players == 0 ) then 51 | self:UpdateText( "" ) 52 | return 53 | end 54 | 55 | local Str = team.GetName( self.iTeam ) .. ": " 56 | 57 | for k, v in pairs( players ) do 58 | Str = Str .. v:Name() .. ", " 59 | end 60 | 61 | Str = Str:sub( 0, -3 ) 62 | self:UpdateText( Str ) 63 | 64 | end 65 | 66 | derma.DefineControl( "TeamBoardSmall", "", PANEL, "DLabel" ) -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/class_default.lua: -------------------------------------------------------------------------------- 1 | 2 | local CLASS = {} 3 | 4 | CLASS.DisplayName = "Default Class" 5 | CLASS.WalkSpeed = 400 6 | CLASS.CrouchedWalkSpeed = 0.2 7 | CLASS.RunSpeed = 600 8 | CLASS.DuckSpeed = 0.2 9 | CLASS.JumpPower = 200 10 | CLASS.PlayerModel = "models/player.mdl" 11 | CLASS.DrawTeamRing = false 12 | CLASS.DrawViewModel = true 13 | CLASS.CanUseFlashlight = true 14 | CLASS.MaxHealth = 100 15 | CLASS.StartHealth = 100 16 | CLASS.StartArmor = 0 17 | CLASS.RespawnTime = 0 // 0 means use the default spawn time chosen by gamemode 18 | CLASS.DropWeaponOnDie = false 19 | CLASS.TeammateNoCollide = true 20 | CLASS.AvoidPlayers = true // Automatically avoid players that we're no colliding 21 | CLASS.Selectable = true // When false, this disables all the team checking 22 | CLASS.FullRotation = false // Allow the player's model to rotate upwards, etc etc 23 | 24 | function CLASS:Loadout( pl ) 25 | 26 | pl:GiveAmmo( 255, "Pistol", true ) 27 | 28 | pl:Give( "weapon_pistol" ) 29 | 30 | end 31 | 32 | function CLASS:OnSpawn( pl ) 33 | end 34 | 35 | function CLASS:OnDeath( pl, attacker, dmginfo ) 36 | end 37 | 38 | function CLASS:Think( pl ) 39 | end 40 | 41 | function CLASS:Move( pl, mv ) 42 | end 43 | 44 | function CLASS:OnKeyPress( pl, key ) 45 | end 46 | 47 | function CLASS:OnKeyRelease( pl, key ) 48 | end 49 | 50 | function CLASS:ShouldDrawLocalPlayer( pl ) 51 | return false 52 | end 53 | 54 | function CLASS:CalcView( ply, origin, angles, fov ) 55 | end 56 | 57 | player_class.Register( "Default", CLASS ) 58 | 59 | local CLASS = {} 60 | CLASS.DisplayName = "Spectator Class" 61 | CLASS.DrawTeamRing = false 62 | CLASS.PlayerModel = "models/player.mdl" 63 | 64 | player_class.Register( "Spectator", CLASS ) -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/utility.lua: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------- 2 | Name: UTIL_SpawnAllPlayers 3 | Desc: Respawn all non-spectators, providing they are allowed to spawn. 4 | ---------------------------------------------------------*/ 5 | function UTIL_SpawnAllPlayers() 6 | 7 | for k,v in pairs( player.GetAll() ) do 8 | if ( v:CanRespawn() && v:Team() != TEAM_SPECTATOR && v:Team() != TEAM_CONNECTING ) then 9 | v:Spawn() 10 | end 11 | end 12 | 13 | end 14 | 15 | /*--------------------------------------------------------- 16 | Name: UTIL_StripAllPlayers 17 | Desc: Clears all weapons and ammo from all players. 18 | ---------------------------------------------------------*/ 19 | function UTIL_StripAllPlayers() 20 | 21 | for k,v in pairs( player.GetAll() ) do 22 | if ( v:Team() != TEAM_SPECTATOR && v:Team() != TEAM_CONNECTING ) then 23 | v:StripWeapons() 24 | v:StripAmmo() 25 | end 26 | end 27 | 28 | end 29 | 30 | /*--------------------------------------------------------- 31 | Name: UTIL_FreezeAllPlayers 32 | Desc: Freeze all non-spectators. 33 | ---------------------------------------------------------*/ 34 | function UTIL_FreezeAllPlayers() 35 | 36 | for k,v in pairs( player.GetAll() ) do 37 | if ( v:Team() != TEAM_SPECTATOR && v:Team() != TEAM_CONNECTING ) then 38 | v:Freeze( true ) 39 | end 40 | end 41 | 42 | end 43 | 44 | /*--------------------------------------------------------- 45 | Name: UTIL_UnFreezeAllPlayers 46 | Desc: Removes frozen flag from all players. 47 | ---------------------------------------------------------*/ 48 | function UTIL_UnFreezeAllPlayers() 49 | 50 | for k,v in pairs( player.GetAll() ) do 51 | if ( v:Team() != TEAM_SPECTATOR && v:Team() != TEAM_CONNECTING ) then 52 | v:Freeze( false ) 53 | end 54 | end 55 | 56 | end 57 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/cl_gmchanger.lua: -------------------------------------------------------------------------------- 1 | include( "vgui/vgui_vote.lua" ) 2 | 3 | 4 | g_PlayableGamemodes = {} 5 | g_bGotGamemodesTable = false 6 | 7 | function RcvPlayableGamemodes( length ) 8 | 9 | g_PlayableGamemodes = net.ReadTable() 10 | g_bGotGamemodesTable = true 11 | 12 | end 13 | 14 | net.Receive( "PlayableGamemodes", function() pcall(RcvPlayableGamemodes) end ) 15 | 16 | local GMChooser = nil 17 | local function GetVoteScreen() 18 | LocalPlayer():ConCommand("-score") 19 | if ( IsValid( GMChooser ) ) then return GMChooser end 20 | 21 | GMChooser = vgui.Create( "VoteScreen" ) 22 | return GMChooser 23 | 24 | end 25 | 26 | function GM:ShowGamemodeChooser() 27 | 28 | local votescreen = GetVoteScreen() 29 | votescreen:ChooseGamemode() 30 | 31 | end 32 | 33 | function GM:GamemodeWon( mode ) 34 | 35 | local votescreen = GetVoteScreen() 36 | votescreen:FlashItem( mode ) 37 | 38 | end 39 | 40 | function GM:ChangingGamemode( mode, map ) 41 | 42 | local votescreen = GetVoteScreen() 43 | votescreen:FlashItem( map ) 44 | 45 | end 46 | 47 | function GM:ShowMapChooserForGamemode( gmname ) 48 | 49 | local votescreen = GetVoteScreen() 50 | votescreen:ChooseMap( gmname ) 51 | 52 | end 53 | 54 | 55 | local ClassChooser = nil 56 | cl_classsuicide = CreateConVar( "cl_classsuicide", "0", { FCVAR_ARCHIVE } ) 57 | 58 | function GM:ShowClassChooser( TEAMID ) 59 | 60 | if ( !GAMEMODE.SelectClass ) then return end 61 | if ( ClassChooser ) then ClassChooser:Remove() end 62 | 63 | ClassChooser = vgui.CreateFromTable( vgui_Splash ) 64 | ClassChooser:SetHeaderText( "Choose Class" ) 65 | ClassChooser:SetHoverText( "What class do you want to be?" ); 66 | 67 | Classes = team.GetClass( TEAMID ) 68 | for k, v in SortedPairs( Classes ) do 69 | 70 | local displayname = v 71 | local Class = player_class.Get( v ) 72 | if ( Class && Class.DisplayName ) then 73 | displayname = Class.DisplayName 74 | end 75 | 76 | local description = "Click to spawn as " .. displayname 77 | 78 | if( Class and Class.Description ) then 79 | description = Class.Description 80 | end 81 | 82 | local func = function() if( cl_classsuicide:GetBool() ) then RunConsoleCommand( "kill" ) end RunConsoleCommand( "changeclass", k ) end 83 | local btn = ClassChooser:AddSelectButton( displayname, func, description ) 84 | btn.m_colBackground = team.GetColor( TEAMID ) 85 | 86 | end 87 | 88 | ClassChooser:AddCancelButton() 89 | ClassChooser:MakePopup() 90 | ClassChooser:NoFadeIn() 91 | 92 | end 93 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/vgui/vgui_hudcommon.lua: -------------------------------------------------------------------------------- 1 | local PANEL = {} 2 | AccessorFunc( PANEL, "m_Items", "Items" ) 3 | AccessorFunc( PANEL, "m_Horizontal", "Horizontal" ) 4 | AccessorFunc( PANEL, "m_Spacing", "Spacing" ) 5 | 6 | AccessorFunc( PANEL, "m_AlignBottom", "AlignBottom" ) 7 | AccessorFunc( PANEL, "m_AlignCenter", "AlignCenter" ) 8 | 9 | function PANEL:Init() 10 | self.m_Items = {} 11 | self:SetHorizontal( true ) 12 | self:SetText( "" ) 13 | self:SetAlignCenter( true ) 14 | self:SetSpacing( 8 ) 15 | end 16 | 17 | function PANEL:AddItem( item ) 18 | item:SetParent( self ) 19 | table.insert( self.m_Items, item ) 20 | self:InvalidateLayout() 21 | item:SetPaintBackgroundEnabled( false ) 22 | item.m_bPartOfBar = true 23 | end 24 | 25 | function PANEL:PerformLayout() 26 | 27 | if ( self.m_Horizontal ) then 28 | local x = self.m_Spacing 29 | local tallest = 0 30 | for k, v in pairs( self.m_Items ) do 31 | 32 | v:SetPos( x, 0 ) 33 | x = x + v:GetWide() + self.m_Spacing 34 | tallest = math.max( tallest, v:GetTall() ) 35 | 36 | if ( self.m_AlignBottom ) then v:AlignBottom() end 37 | if ( self.m_AlignCenter ) then v:CenterVertical() end 38 | 39 | end 40 | self:SetSize( x, tallest ) 41 | else 42 | // todo. 43 | end 44 | 45 | end 46 | 47 | derma.DefineControl( "DHudBar", "", PANEL, "HudBase" ) 48 | 49 | local PANEL = {} 50 | AccessorFunc( PANEL, "m_ValueFunction", "ValueFunction" ) 51 | AccessorFunc( PANEL, "m_ColorFunction", "ColorFunction" ) 52 | 53 | /*--------------------------------------------------------- 54 | Name: Init 55 | ---------------------------------------------------------*/ 56 | function PANEL:Init() 57 | 58 | end 59 | 60 | function PANEL:GetTextValueFromFunction() 61 | if (!self.m_ValueFunction) then return "-" end 62 | return tostring( self:m_ValueFunction() ) 63 | end 64 | 65 | function PANEL:GetColorFromFunction() 66 | if (!self.m_ColorFunction) then return self:GetDefaultTextColor() end 67 | return self:m_ColorFunction() 68 | end 69 | 70 | function PANEL:Think() 71 | self:SetTextColor( self:GetColorFromFunction() ) 72 | self:SetText( self:GetTextValueFromFunction() ) 73 | end 74 | 75 | derma.DefineControl( "DHudUpdater", "A HUD Element", PANEL, "DHudElement" ) 76 | 77 | 78 | local PANEL = {} 79 | AccessorFunc( PANEL, "m_Function", "Function" ) 80 | 81 | /*--------------------------------------------------------- 82 | Name: Init 83 | ---------------------------------------------------------*/ 84 | function PANEL:Init() 85 | HudBase.Init( self ) 86 | end 87 | 88 | function PANEL:Think() 89 | 90 | if ( !self.m_ValueFunction ) then return end 91 | 92 | self:SetTextColor( self:GetColorFromFunction() ) 93 | 94 | local EndTime = self:m_ValueFunction() 95 | if ( EndTime == -1 ) then return end 96 | 97 | if ( !EndTime || EndTime < CurTime() ) then 98 | self:SetText( "00:00" ) 99 | return 100 | end 101 | 102 | local Time = util.ToMinutesSeconds( EndTime - CurTime() ) 103 | self:SetText( Time ) 104 | 105 | end 106 | 107 | derma.DefineControl( "DHudCountdown", "A HUD Element", PANEL, "DHudUpdater" ) -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/vgui/vgui_gamenotice.lua: -------------------------------------------------------------------------------- 1 | -- client cvars to control deathmsgs 2 | local hud_deathnotice_time = CreateClientConVar( "hud_deathnotice_time", "6", true, false ) 3 | local hud_deathnotice_limit = CreateClientConVar( "hud_deathnotice_limit", "5", true, false ) 4 | 5 | --[[ 6 | This is the player death panel. This should be parented to a DeathMessage_Panel. The DeathMessage_Panel that 7 | it's parented to controls aspects such as the position on screen. All this panel's job is to print the 8 | specific death it's been given and fade out before its RetireTime. 9 | ]] 10 | 11 | local PANEL = {} 12 | 13 | Derma_Hook( PANEL, "Paint", "Paint", "GameNotice" ) 14 | Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "GameNotice" ) 15 | Derma_Hook( PANEL, "PerformLayout", "Layout", "GameNotice" ) 16 | 17 | function PANEL:Init() 18 | self.m_bHighlight = false 19 | self.Padding = 8 20 | self.Spacing = 8 21 | self.Items = {} 22 | end 23 | 24 | function PANEL:AddEntityText( txt ) 25 | 26 | if ( type( txt ) == "string" ) then return false end 27 | 28 | if ( type( txt ) == "Player" ) then 29 | 30 | self:AddText( txt:Nick(), GAMEMODE:GetTeamColor( txt ) ) 31 | if ( txt == LocalPlayer() ) then self.m_bHighlight = true end 32 | 33 | return true 34 | 35 | end 36 | 37 | if( txt:IsValid() ) then 38 | self:AddText( txt:GetClass(), GAMEMODE.DeathNoticeDefaultColor ) 39 | else 40 | self:AddText( tostring( txt ) ) 41 | end 42 | 43 | end 44 | 45 | function PANEL:AddItem( item ) 46 | 47 | table.insert( self.Items, item ) 48 | self:InvalidateLayout( true ) 49 | 50 | end 51 | 52 | function PANEL:AddText( txt, color ) 53 | 54 | if ( self:AddEntityText( txt ) ) then return end 55 | 56 | local txt = tostring( txt ) 57 | 58 | local lbl = vgui.Create( "DLabel", self ) 59 | 60 | Derma_Hook( lbl, "ApplySchemeSettings", "Scheme", "GameNoticeLabel" ) 61 | lbl:ApplySchemeSettings() 62 | lbl:SetText( txt ) 63 | 64 | if( string.Left( txt , 1 ) == "#" && !color ) then color = GAMEMODE.DeathNoticeDefaultColor end // localised ent death 65 | if( GAMEMODE.DeathNoticeTextColor && !color ) then color = GAMEMODE.DeathNoticeTextColor end // something else 66 | if ( !color ) then color = color_white end 67 | 68 | lbl:SetTextColor( color ) 69 | 70 | self:AddItem( lbl ) 71 | 72 | end 73 | 74 | function PANEL:AddIcon( txt ) 75 | 76 | if ( killicon.Exists( txt ) ) then 77 | 78 | local icon = vgui.Create( "DKillIcon", self ) 79 | icon:SetName( txt ) 80 | icon:SizeToContents() 81 | 82 | self:AddItem( icon ) 83 | 84 | else 85 | 86 | self:AddText( "killed" ) 87 | 88 | end 89 | 90 | end 91 | 92 | function PANEL:PerformLayout() 93 | 94 | local x = self.Padding 95 | local height = self.Padding * 0.5 96 | 97 | for k, v in pairs( self.Items ) do 98 | 99 | v:SetPos( x, self.Padding * 0.5 ) 100 | v:SizeToContents() 101 | 102 | x = x + v:GetWide() + self.Spacing 103 | height = math.max( height, v:GetTall() + self.Padding ) 104 | 105 | end 106 | 107 | self:SetSize( x + self.Padding, height ) 108 | 109 | end 110 | 111 | derma.DefineControl( "GameNotice", "", PANEL, "DPanel" ) -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/cl_splashscreen.lua: -------------------------------------------------------------------------------- 1 | 2 | local PANEL = {} 3 | 4 | /*--------------------------------------------------------- 5 | Init 6 | ---------------------------------------------------------*/ 7 | function PANEL:Init() 8 | 9 | self:SetText( "" ) 10 | self.DoClick = function() RunConsoleCommand( "seensplash" ) self:Remove() end 11 | self:SetSkin( GAMEMODE.HudSkin ) 12 | 13 | self.lblGamemodeName = vgui.Create( "DLabel", self ) 14 | self.lblGamemodeName:SetText( GAMEMODE.Name ) 15 | self.lblGamemodeName:SetFont( "FRETTA_LARGE" ) 16 | self.lblGamemodeName:SetColor( color_white ) 17 | 18 | self.lblGamemodeAuthor = vgui.Create( "DLabel", self ) 19 | self.lblGamemodeAuthor:SetText( "by " .. GAMEMODE.Author ) 20 | self.lblGamemodeAuthor:SetFont( "FRETTA_MEDIUM" ) 21 | self.lblGamemodeAuthor:SetColor( color_white ) 22 | 23 | self.lblServerName = vgui.Create( "DLabel", self ) 24 | self.lblServerName:SetText( GetHostName() ) 25 | self.lblServerName:SetFont( "FRETTA_MEDIUM" ) 26 | self.lblServerName:SetColor( color_white ) 27 | 28 | self.lblIP = vgui.Create( "DLabel", self ) 29 | self.lblIP:SetText( "0.0.0.0" ) 30 | self.lblIP:SetFont( "FRETTA_MEDIUM" ) 31 | self.lblIP:SetColor( color_white ) 32 | 33 | 34 | self:PerformLayout() 35 | 36 | self.FadeInTime = RealTime() 37 | 38 | end 39 | 40 | /*--------------------------------------------------------- 41 | PerformLayout 42 | ---------------------------------------------------------*/ 43 | function PANEL:PerformLayout() 44 | 45 | self:SetSize( ScrW(), ScrH() ) 46 | 47 | local CenterY = ScrH() / 2.0 48 | 49 | self.lblGamemodeName:SizeToContents() 50 | self.lblGamemodeName:SetPos( ScrW()/2 - self.lblGamemodeName:GetWide()/2, CenterY - 200 - self.lblGamemodeName:GetTall() - self.lblGamemodeAuthor:GetTall() ) 51 | 52 | self.lblGamemodeAuthor:SizeToContents() 53 | self.lblGamemodeAuthor:SetPos( ScrW()/2 - self.lblGamemodeAuthor:GetWide()/2, CenterY - 200 - self.lblGamemodeAuthor:GetTall() ) 54 | 55 | self.lblServerName:SizeToContents() 56 | self.lblServerName:SetPos( 100, CenterY + 200 ) 57 | 58 | self.lblIP:SetText( GetConVarString( "ip" ) ) 59 | self.lblIP:SizeToContents() 60 | self.lblIP:SetPos( self:GetWide() - 100 - self.lblIP:GetWide(), CenterY + 200 ) 61 | 62 | end 63 | 64 | /*--------------------------------------------------------- 65 | Paint 66 | ---------------------------------------------------------*/ 67 | function PANEL:Paint() 68 | 69 | Derma_DrawBackgroundBlur( self ) 70 | 71 | local Fade = RealTime() - self.FadeInTime 72 | if ( Fade < 3 ) then 73 | 74 | Fade = 1- (Fade / 3); 75 | surface.SetDrawColor( 0,0, 0, Fade * 255 ); 76 | surface.DrawRect( 0, 0, self:GetWide(), self:GetTall() ); 77 | 78 | end 79 | 80 | 81 | local CenterY = ScrH() / 2.0 82 | 83 | surface.SetDrawColor( 0, 0, 0, 200 ); 84 | surface.DrawRect( 0, 0, self:GetWide(), CenterY - 180 ); 85 | 86 | surface.DrawRect( 0, CenterY + 180, self:GetWide(), self:GetTall() - ( CenterY+ 180 ) ); 87 | 88 | GAMEMODE:PaintSplashScreen( self:GetWide(), self:GetTall() ) 89 | 90 | end 91 | 92 | local vgui_Splash = vgui.RegisterTable( PANEL, "DButton" ) 93 | 94 | function GM:ShowSplash() 95 | 96 | local pnl = vgui.CreateFromTable( vgui_Splash ) 97 | pnl:MakePopup() 98 | 99 | end 100 | 101 | 102 | function GM:PaintSplashScreen( w, h ) 103 | 104 | // Customised splashscreen render here ( The center bit! ) 105 | 106 | end 107 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/cl_deathnotice.lua: -------------------------------------------------------------------------------- 1 | /* 2 | Start of the death message stuff. 3 | */ 4 | 5 | include( 'vgui/vgui_gamenotice.lua' ) 6 | 7 | local function CreateDeathNotify() 8 | 9 | local x, y = ScrW(), ScrH() 10 | 11 | g_DeathNotify = vgui.Create( "DNotify" ) 12 | 13 | g_DeathNotify:SetPos( 0, 25 ) 14 | g_DeathNotify:SetSize( x - ( 25 ), y ) 15 | g_DeathNotify:SetAlignment( 9 ) 16 | g_DeathNotify:SetSkin( GAMEMODE.HudSkin ) 17 | g_DeathNotify:SetLife( 4 ) 18 | g_DeathNotify:ParentToHUD() 19 | 20 | end 21 | 22 | hook.Add( "InitPostEntity", "CreateDeathNotify", CreateDeathNotify ) 23 | 24 | local function RecvPlayerKilledByPlayer( length ) 25 | 26 | local victim = net.ReadEntity() 27 | local inflictor = net.ReadString() 28 | local attacker = net.ReadEntity() 29 | 30 | if ( !IsValid( attacker ) ) then return end 31 | if ( !IsValid( victim ) ) then return end 32 | 33 | GAMEMODE:AddDeathNotice( victim, inflictor, attacker ) 34 | end 35 | 36 | net.Receive( "PlayerKilledByPlayer", RecvPlayerKilledByPlayer ) 37 | 38 | 39 | local function RecvPlayerKilledSelf( length ) 40 | 41 | local victim = net.ReadEntity() 42 | 43 | if ( !IsValid( victim ) ) then return end 44 | 45 | GAMEMODE:AddPlayerAction( victim, GAMEMODE.SuicideString ) 46 | 47 | end 48 | 49 | net.Receive( "PlayerKilledSelf", RecvPlayerKilledSelf ) 50 | 51 | 52 | local function RecvPlayerKilled( length ) 53 | 54 | local victim = net.ReadEntity() 55 | local inflictor = net.ReadString() 56 | local attacker = "#" .. net.ReadString() 57 | 58 | if ( !IsValid( victim ) ) then return end 59 | 60 | GAMEMODE:AddDeathNotice( victim, inflictor, attacker ) 61 | 62 | end 63 | 64 | net.Receive( "PlayerKilled", RecvPlayerKilled ) 65 | 66 | local function RecvPlayerKilledNPC( length ) 67 | 68 | local victim = "#" .. net.ReadString() 69 | local inflictor = net.ReadString() 70 | local attacker = net.ReadEntity() 71 | 72 | if ( !IsValid( attacker ) ) then return end 73 | 74 | GAMEMODE:AddDeathNotice( victim, inflictor, attacker ) 75 | 76 | end 77 | 78 | net.Receive( "PlayerKilledNPC", RecvPlayerKilledNPC ) 79 | 80 | 81 | local function RecvNPCKilledNPC( length ) 82 | 83 | local victim = "#" .. net.ReadString() 84 | local inflictor = net.ReadString() 85 | local attacker = "#" .. net.ReadString() 86 | 87 | GAMEMODE:AddDeathNotice( victim, inflictor, attacker ) 88 | 89 | end 90 | 91 | net.Receive( "NPCKilledNPC", RecvNPCKilledNPC ) 92 | 93 | 94 | /*--------------------------------------------------------- 95 | Name: gamemode:AddDeathNotice( Victim, Weapon, Attacker ) 96 | Desc: Adds an death notice entry 97 | ---------------------------------------------------------*/ 98 | function GM:AddDeathNotice( victim, inflictor, attacker ) 99 | 100 | if ( !IsValid( g_DeathNotify ) ) then return end 101 | 102 | local pnl = vgui.Create( "GameNotice", g_DeathNotify ) 103 | 104 | pnl:AddText( attacker ) 105 | pnl:AddIcon( inflictor ) 106 | pnl:AddText( victim ) 107 | 108 | g_DeathNotify:AddItem( pnl ) 109 | 110 | end 111 | 112 | function GM:AddPlayerAction( ... ) 113 | 114 | if ( !IsValid( g_DeathNotify ) ) then return end 115 | 116 | local pnl = vgui.Create( "GameNotice", g_DeathNotify ) 117 | 118 | for k, v in ipairs({...}) do 119 | pnl:AddText( v ) 120 | end 121 | 122 | // The rest of the arguments should be re-thought. 123 | // Just create the notify and add them instead of trying to fit everything into this function!??? 124 | 125 | g_DeathNotify:AddItem( pnl ) 126 | 127 | end 128 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/cl_scores.lua: -------------------------------------------------------------------------------- 1 | 2 | include( "vgui/vgui_scoreboard.lua" ) 3 | 4 | function GM:GetScoreboard() 5 | 6 | if ( IsValid( g_ScoreBoard ) ) then 7 | g_ScoreBoard:Remove() 8 | end 9 | 10 | g_ScoreBoard = vgui.Create( "FrettaScoreboard" ) 11 | self:CreateScoreboard( g_ScoreBoard ) 12 | 13 | return g_ScoreBoard 14 | 15 | end 16 | 17 | function GM:ScoreboardShow() 18 | 19 | GAMEMODE:GetScoreboard():SetVisible( true ) 20 | GAMEMODE:PositionScoreboard( GAMEMODE:GetScoreboard() ) 21 | 22 | end 23 | 24 | function GM:ScoreboardHide() 25 | 26 | GAMEMODE:GetScoreboard():SetVisible( false ) 27 | 28 | end 29 | 30 | function GM:ScoreboardPlayerPressed(pl) 31 | end 32 | 33 | function GM:AddScoreboardAvatar( ScoreBoard ) 34 | 35 | local f = function( ply ) 36 | local av = vgui.Create( "AvatarImage", ScoreBoard ) 37 | av:SetSize( 32, 32 ) 38 | av:SetPlayer( ply ) 39 | return av 40 | end 41 | 42 | ScoreBoard:AddColumn( "", 32, f, 360 ) // Avatar 43 | 44 | end 45 | 46 | function GM:AddScoreboardSpacer( ScoreBoard, iSize ) 47 | ScoreBoard:AddColumn( "", 16 ) // Gap 48 | end 49 | 50 | function GM:AddScoreboardName( ScoreBoard ) 51 | 52 | local f = function( ply ) return ply:Name() end 53 | ScoreBoard:AddColumn( "Name", nil, f, 10, nil, 4, 4 ) 54 | 55 | end 56 | 57 | function GM:AddScoreboardKills( ScoreBoard ) 58 | 59 | local f = function( ply ) return ply:Frags() end 60 | ScoreBoard:AddColumn( "Kills", 80, f, 0.5, nil, 6, 6 ) 61 | 62 | end 63 | 64 | function GM:AddScoreboardDeaths( ScoreBoard ) 65 | 66 | local f = function( ply ) return ply:Deaths() end 67 | ScoreBoard:AddColumn( "Deaths", 80, f, 0.5, nil, 6, 6 ) 68 | 69 | end 70 | 71 | function GM:AddScoreboardPing( ScoreBoard ) 72 | 73 | local f = function( ply ) return ply:Ping() end 74 | ScoreBoard:AddColumn( "Ping", 80, f, 0.1, nil, 6, 6 ) 75 | 76 | end 77 | 78 | // THESE SHOULD BE THE ONLY FUNCTION YOU NEED TO OVERRIDE 79 | 80 | function GM:PositionScoreboard( ScoreBoard ) 81 | 82 | if ( GAMEMODE.TeamBased ) then 83 | ScoreBoard:SetSize( math.min( 1024, ScrW() ), ScrH() - 50 ) 84 | ScoreBoard:SetPos( (ScrW() - ScoreBoard:GetWide()) * 0.5, 25 ) 85 | else 86 | ScoreBoard:SetSize( 512, ScrH() - 64 ) 87 | ScoreBoard:SetPos( (ScrW() - ScoreBoard:GetWide()) / 2, 32 ) 88 | end 89 | 90 | end 91 | 92 | function GM:AddScoreboardWantsChange( ScoreBoard ) 93 | 94 | local f = function( ply ) 95 | if ( ply:GetNWBool( "WantsVote", false ) ) then 96 | local lbl = vgui.Create( "DLabel" ) 97 | lbl:SetFont( "Marlett" ) 98 | lbl:SetText( "a" ) 99 | lbl:SetTextColor( Color( 100, 255, 0 ) ) 100 | lbl:SetContentAlignment( 5 ) 101 | return lbl 102 | end 103 | end 104 | 105 | ScoreBoard:AddColumn( "", 16, f, 2, nil, 6, 6 ) 106 | 107 | end 108 | 109 | function GM:CreateScoreboard( ScoreBoard ) 110 | 111 | // This makes it so that it's behind chat & hides when you're in the menu 112 | // Disable this if you want to be able to click on stuff on your scoreboard 113 | ScoreBoard:ParentToHUD() 114 | 115 | ScoreBoard:SetRowHeight( 32 ) 116 | 117 | ScoreBoard:SetAsBullshitTeam( TEAM_SPECTATOR ) 118 | ScoreBoard:SetAsBullshitTeam( TEAM_CONNECTING ) 119 | ScoreBoard:SetShowScoreboardHeaders( GAMEMODE.TeamBased ) 120 | 121 | if ( GAMEMODE.TeamBased ) then 122 | ScoreBoard:SetAsBullshitTeam( TEAM_UNASSIGNED ) 123 | ScoreBoard:SetHorizontal( true ) 124 | end 125 | 126 | ScoreBoard:SetSkin( GAMEMODE.HudSkin ) 127 | 128 | self:AddScoreboardAvatar( ScoreBoard ) // 1 129 | self:AddScoreboardWantsChange( ScoreBoard ) // 2 130 | self:AddScoreboardName( ScoreBoard ) // 3 131 | self:AddScoreboardKills( ScoreBoard ) // 4 132 | self:AddScoreboardDeaths( ScoreBoard ) // 5 133 | self:AddScoreboardPing( ScoreBoard ) // 6 134 | 135 | // Here we sort by these columns (and descending), in this order. You can define up to 4 136 | ScoreBoard:SetSortColumns( { 4, true, 5, false, 3, false } ) 137 | 138 | end 139 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/vgui/vgui_hudlayout.lua: -------------------------------------------------------------------------------- 1 | local PANEL = {} 2 | 3 | AccessorFunc( PANEL, "Spacing", "Spacing" ) 4 | 5 | /*--------------------------------------------------------- 6 | Name: Init 7 | ---------------------------------------------------------*/ 8 | function PANEL:Init() 9 | 10 | self.Items = {} 11 | 12 | self:SetSpacing( 8 ) 13 | 14 | self:SetPaintBackgroundEnabled( false ) 15 | self:SetPaintBorderEnabled( false ) 16 | 17 | self:ParentToHUD() 18 | 19 | end 20 | 21 | // This makes it so that it's behind chat & hides when you're in the menu 22 | // But it also removes the ability to click on it. So override it if you want to. 23 | function PANEL:ChooseParent() 24 | self:ParentToHUD() 25 | end 26 | 27 | /*--------------------------------------------------------- 28 | Name: GetCanvas 29 | ---------------------------------------------------------*/ 30 | function PANEL:Clear( bDelete ) 31 | 32 | for k, panel in pairs( self.Items ) do 33 | 34 | if ( panel && panel:IsValid() ) then 35 | 36 | panel:SetParent( panel ) 37 | panel:SetVisible( false ) 38 | 39 | if ( bDelete ) then 40 | panel:Remove() 41 | end 42 | 43 | end 44 | 45 | end 46 | 47 | self.Items = {} 48 | 49 | end 50 | 51 | /*--------------------------------------------------------- 52 | Name: AddItem 53 | ---------------------------------------------------------*/ 54 | function PANEL:AddItem( item, relative, pos ) 55 | 56 | if (!item || !item:IsValid()) then return end 57 | 58 | item.HUDPos = pos 59 | item.HUDrelative = relative 60 | 61 | item:SetVisible( true ) 62 | item:SetParent( self ) 63 | table.insert( self.Items, item ) 64 | 65 | self:InvalidateLayout() 66 | 67 | end 68 | 69 | function PANEL:PositionItem( item ) 70 | 71 | if ( item.Positioned ) then return end 72 | if ( IsValid( item.HUDrelative ) && item != item.HUDrelative ) then self:PositionItem( item.HUDrelative ) end 73 | 74 | local SPACING = self:GetSpacing() 75 | 76 | item:InvalidateLayout( true ) 77 | 78 | if ( item.HUDPos == 7 || item.HUDPos == 8 || item.HUDPos == 9 ) then 79 | if ( IsValid( item.HUDrelative ) ) then 80 | item:MoveAbove( item.HUDrelative, SPACING ) 81 | else 82 | item:AlignTop() 83 | end 84 | end 85 | 86 | if ( item.HUDPos == 4 || item.HUDPos == 5 || item.HUDPos == 6 ) then 87 | if ( IsValid( item.HUDrelative ) ) then 88 | item.y = item.HUDrelative.y 89 | else 90 | item:CenterVertical() 91 | end 92 | end 93 | 94 | if ( item.HUDPos == 1 || item.HUDPos == 2 || item.HUDPos == 3 ) then 95 | if ( IsValid( item.HUDrelative ) ) then 96 | item:MoveBelow( item.HUDrelative, SPACING ) 97 | else 98 | item:AlignBottom() 99 | end 100 | end 101 | 102 | if ( item.HUDPos == 7 || item.HUDPos == 4 || item.HUDPos == 1 ) then 103 | if ( IsValid( item.HUDrelative ) ) then 104 | item.x = item.HUDrelative.x 105 | else 106 | item:AlignLeft() 107 | end 108 | end 109 | 110 | if ( item.HUDPos == 8 || item.HUDPos == 5 || item.HUDPos == 2 ) then 111 | if ( IsValid( item.HUDrelative ) ) then 112 | item.x = item.HUDrelative.x + ( item.HUDrelative:GetWide() - item:GetWide() ) / 2 113 | else 114 | item:CenterHorizontal() 115 | end 116 | end 117 | 118 | if ( item.HUDPos == 9 || item.HUDPos == 6 || item.HUDPos == 3 ) then 119 | if ( IsValid( item.HUDrelative ) ) then 120 | item.x = item.HUDrelative.x + item.HUDrelative:GetWide() - item:GetWide() 121 | else 122 | item:AlignRight() 123 | end 124 | end 125 | 126 | if ( item.HUDPos == 4 && IsValid( item.HUDrelative ) ) then 127 | item:MoveLeftOf( item.HUDrelative, SPACING ) 128 | end 129 | 130 | if ( item.HUDPos == 6 && IsValid( item.HUDrelative ) ) then 131 | item:MoveRightOf( item.HUDrelative, SPACING ) 132 | end 133 | 134 | item.Positioned = true 135 | 136 | end 137 | 138 | function PANEL:Think() 139 | self:InvalidateLayout() 140 | end 141 | 142 | /*--------------------------------------------------------- 143 | Name: PerformLayout 144 | ---------------------------------------------------------*/ 145 | function PANEL:PerformLayout() 146 | 147 | self:SetPos( 32, 32 ) 148 | self:SetWide( ScrW() - 64 ) 149 | self:SetTall( ScrH() - 64 ) 150 | 151 | for k, item in pairs( self.Items ) do 152 | item.Positioned = false 153 | end 154 | 155 | for k, item in pairs( self.Items ) do 156 | self:PositionItem( item ) 157 | end 158 | 159 | end 160 | 161 | derma.DefineControl( "DHudLayout", "A HUD Layout Base", PANEL, "Panel" ) 162 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/cl_help.lua: -------------------------------------------------------------------------------- 1 | 2 | local Help = nil 3 | function GM:ShowHelp() 4 | 5 | if ( !IsValid( Help ) ) then 6 | 7 | Help = vgui.CreateFromTable( vgui_Splash ) 8 | Help:SetHeaderText( GAMEMODE.Name or "Untitled Gamemode" ) 9 | Help:SetHoverText( GAMEMODE.Help or "No Help Avaliable" ); 10 | 11 | Help.lblFooterText.Think = function( panel ) 12 | local tl = GAMEMODE:GetGameTimeLeft() 13 | if ( tl == -1 ) then return end 14 | if( GetGlobalBool( "IsEndOfGame", false ) ) then panel:SetText( "Game has ended..." ) return end 15 | if( GAMEMODE.RoundBased && CurTime() > GAMEMODE:GetTimeLimit() ) then panel:SetText( "Game will end after this round" ) return end 16 | 17 | panel:SetText( "Time Left: " .. util.ToMinutesSeconds( tl ) ) 18 | end 19 | 20 | if ( GetConVarNumber( "fretta_voting" ) != 0 ) then 21 | local btn = Help:AddSelectButton( "Vote For Change", function() RunConsoleCommand( "voteforchange" ) end ) 22 | btn.m_colBackground = Color( 255, 200, 100 ) 23 | btn:SetDisabled( LocalPlayer():GetNWBool( "WantsVote" ) ) 24 | end 25 | 26 | if ( GAMEMODE.TeamBased ) then 27 | local btn = Help:AddSelectButton( "Change Team", function() GAMEMODE:ShowTeam() end ) 28 | btn.m_colBackground = Color( 120, 255, 100 ) 29 | end 30 | 31 | if ( !GAMEMODE.TeamBased && GAMEMODE.AllowSpectating ) then 32 | 33 | if ( LocalPlayer():Team() == TEAM_SPECTATOR ) then 34 | 35 | local btn = Help:AddSelectButton( "Join Game", function() RunConsoleCommand( "changeteam", TEAM_UNASSIGNED ) end ) 36 | btn.m_colBackground = Color( 120, 255, 100 ) 37 | 38 | else 39 | 40 | local btn = Help:AddSelectButton( "Spectate", function() RunConsoleCommand( "changeteam", TEAM_SPECTATOR ) end ) 41 | btn.m_colBackground = Color( 200, 200, 200 ) 42 | 43 | end 44 | end 45 | 46 | if ( IsValid( LocalPlayer() ) ) then 47 | 48 | local TeamID = LocalPlayer():Team() 49 | local Classes = team.GetClass( TeamID ) 50 | if ( Classes && #Classes > 1 ) then 51 | local btn = Help:AddSelectButton( "Change Class", function() GAMEMODE:ShowClassChooser( LocalPlayer():Team() ) end ) 52 | btn.m_colBackground = Color( 120, 255, 100 ) 53 | end 54 | 55 | end 56 | 57 | Help:AddCancelButton() 58 | 59 | if ( GAMEMODE.SelectModel ) then 60 | 61 | local function CreateModelPanel() 62 | 63 | local pnl = vgui.Create( "DGrid" ) 64 | 65 | pnl:SetCols( 6 ) 66 | pnl:SetColWide( 66 ) 67 | pnl:SetRowHeight( 66 ) 68 | 69 | for name, model in SortedPairs( player_manager.AllValidModels() ) do 70 | 71 | local icon = vgui.Create( "SpawnIcon" ) 72 | icon.DoClick = function() surface.PlaySound( "ui/buttonclickrelease.wav" ) RunConsoleCommand( "cl_playermodel", name ) end 73 | icon.PaintOver = function() if ( GetConVarString( "cl_playermodel" ) == name ) then surface.SetDrawColor( Color( 255, 210 + math.sin(RealTime()*10)*40, 0 ) ) surface.DrawOutlinedRect( 4, 4, icon:GetWide()-8, icon:GetTall()-8 ) surface.DrawOutlinedRect( 3, 3, icon:GetWide()-6, icon:GetTall()-6 ) end end 74 | icon:SetModel( model ) 75 | icon:SetSize( 64, 64 ) 76 | icon:SetTooltip( name ) 77 | 78 | pnl:AddItem( icon ) 79 | 80 | end 81 | 82 | return pnl 83 | 84 | end 85 | 86 | Help:AddPanelButton( "icon16/user.png", "Choose Player Model", CreateModelPanel ) 87 | 88 | end 89 | 90 | if ( GAMEMODE.SelectColor ) then 91 | 92 | local function CreateColorPanel() 93 | 94 | local pnl = vgui.Create( "DGrid" ) 95 | 96 | pnl:SetCols( 10 ) 97 | pnl:SetColWide( 36 ) 98 | pnl:SetRowHeight( 128 ) 99 | 100 | for name, colr in pairs( list.Get( "PlayerColours" ) ) do 101 | 102 | local icon = vgui.Create( "DButton" ) 103 | icon:SetText( "" ) 104 | icon.DoClick = function() surface.PlaySound( "ui/buttonclickrelease.wav" ) RunConsoleCommand( "cl_playercolor", name ) end 105 | icon.Paint = function() surface.SetDrawColor( colr ) icon:DrawFilledRect() end 106 | icon.PaintOver = function() if ( GetConVarString( "cl_playercolor" ) == name ) then surface.SetDrawColor( Color( 255, 210 + math.sin(RealTime()*10)*40, 0 ) ) surface.DrawOutlinedRect( 4, 4, icon:GetWide()-8, icon:GetTall()-8 ) surface.DrawOutlinedRect( 3, 3, icon:GetWide()-6, icon:GetTall()-6 ) end end 107 | icon:SetSize( 32, 128 ) 108 | icon:SetTooltip( name ) 109 | 110 | pnl:AddItem( icon ) 111 | 112 | end 113 | 114 | return pnl 115 | 116 | end 117 | 118 | Help:AddPanelButton( "icon16/application_view_tile.png", "Choose Player Color", CreateColorPanel ) 119 | 120 | end 121 | 122 | end 123 | 124 | Help:MakePopup() 125 | Help:NoFadeIn() 126 | 127 | end 128 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/vgui/vgui_scoreboard.lua: -------------------------------------------------------------------------------- 1 | include( "vgui_scoreboard_team.lua" ) 2 | include( "vgui_scoreboard_small.lua" ) 3 | 4 | local PANEL = {} 5 | 6 | Derma_Hook( PANEL, "Paint", "Paint", "ScoreHeader" ) 7 | Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "ScoreHeader" ) 8 | Derma_Hook( PANEL, "PerformLayout", "Layout", "ScoreHeader" ) 9 | 10 | 11 | function PANEL:Init() 12 | 13 | self.Columns = {} 14 | self.iTeamID = 0 15 | 16 | self.HostName = vgui.Create( "DLabel", self ) 17 | self.HostName:SetText( GetHostName() ) 18 | 19 | self.GamemodeName = vgui.Create( "DLabel", self ) 20 | self.GamemodeName:SetText( GAMEMODE.Name ) 21 | 22 | self:SetHeight( 64 ) 23 | 24 | end 25 | 26 | derma.DefineControl( "ScoreboardHeader", "", PANEL, "Panel" ) 27 | 28 | 29 | local PANEL = {} 30 | 31 | 32 | AccessorFunc( PANEL, "m_bHorizontal", "Horizontal" ) 33 | AccessorFunc( PANEL, "m_iPadding", "Padding" ) 34 | AccessorFunc( PANEL, "m_iRowHeight", "RowHeight" ) 35 | AccessorFunc( PANEL, "m_bShowScoreHeaders", "ShowScoreboardHeaders" ) 36 | 37 | Derma_Hook( PANEL, "Paint", "Paint", "ScorePanel" ) 38 | Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "ScorePanel" ) 39 | Derma_Hook( PANEL, "PerformLayout", "Layout", "ScorePanel" ) 40 | 41 | function PANEL:Init() 42 | 43 | self.SortDesc = true 44 | 45 | self.Boards = {} 46 | self.SmallBoards = {} 47 | self.Columns = {} 48 | 49 | self:SetRowHeight( 32 ) 50 | self:SetHorizontal( false ) 51 | self:SetPadding( 10 ) 52 | self:SetShowScoreboardHeaders( true ) 53 | 54 | self.Header = vgui.Create( "ScoreboardHeader", self ) 55 | 56 | local teams = team.GetAllTeams() 57 | for k, v in pairs( teams ) do 58 | 59 | local ScoreBoard = vgui.Create( "TeamScoreboard", self ) 60 | ScoreBoard:Setup( k, self ) 61 | self.Boards[ k ] = ScoreBoard 62 | 63 | end 64 | 65 | self:MakePopup() 66 | 67 | end 68 | 69 | function PANEL:SetAsBullshitTeam( iTeamID ) 70 | 71 | if ( IsValid( self.Boards[ iTeamID ] ) ) then 72 | self.Boards[ iTeamID ]:Remove() 73 | self.Boards[ iTeamID ] = nil 74 | end 75 | 76 | self.SmallBoards[ iTeamID ] = vgui.Create( "TeamBoardSmall", self ) 77 | self.SmallBoards[ iTeamID ]:Setup( iTeamID, self ) 78 | 79 | end 80 | 81 | function PANEL:SetSortColumns( ... ) 82 | 83 | for k, v in pairs( self.Boards ) do 84 | v:SetSortColumns( ... ) 85 | end 86 | 87 | end 88 | 89 | function PANEL:AddColumn( Name, iFixedSize, fncValue, UpdateRate, TeamID, HeaderAlign, ValueAlign, Font ) 90 | 91 | local Col = {} 92 | 93 | Col.Name = Name 94 | Col.iFixedSize = iFixedSize 95 | Col.fncValue = fncValue 96 | Col.TeamID = TeamID 97 | Col.UpdateRate = UpdateRate 98 | Col.ValueAlign = ValueAlign 99 | Col.HeaderAlign = HeaderAlign 100 | Col.Font = Font 101 | 102 | for k, v in pairs( self.Boards ) do 103 | v:AddColumn( Col ) 104 | end 105 | 106 | return Col 107 | 108 | end 109 | 110 | function PANEL:Layout4By4( y ) 111 | 112 | local a = self.Boards[1] 113 | local b = self.Boards[2] 114 | local c = self.Boards[3] 115 | local d = self.Boards[4] 116 | 117 | local widtheach = (self:GetWide() - ( self.m_iPadding * 3 )) / 2 118 | 119 | for k, v in pairs( self.Boards ) do 120 | 121 | v:SizeToContents() 122 | v:SetWide( widtheach ) 123 | 124 | end 125 | 126 | a:SetPos( self.m_iPadding, y + self.m_iPadding ) 127 | b:SetPos( a:GetPos() + a:GetWide() + self.m_iPadding, y + self.m_iPadding ) 128 | 129 | local height = a:GetTall() + a.y 130 | height = math.max( b:GetTall() + b.y, height ) 131 | height = height + self.m_iPadding * 2 132 | 133 | c:SetPos( self.m_iPadding, height ) 134 | d:SetPos( c:GetPos() + c:GetWide() + self.m_iPadding, height ) 135 | 136 | local height = d:GetTall() + d.y 137 | height = math.max( c:GetTall() + c.y, height ) 138 | height = height + self.m_iPadding * 2 139 | 140 | return height 141 | 142 | end 143 | 144 | function PANEL:LayoutHorizontal( y ) 145 | 146 | local cols = table.Count( self.Boards ) 147 | 148 | if ( cols == 4 ) then 149 | return self:Layout4By4( y ) 150 | end 151 | 152 | local widtheach = (self:GetWide() - ( self.m_iPadding * (cols+1) )) / cols 153 | 154 | local x = self.m_iPadding 155 | local tallest = 0 156 | for k, v in pairs( self.Boards ) do 157 | 158 | v:SizeToContents() 159 | v:SetPos( x, y ) 160 | v:SetWide( widtheach ) 161 | 162 | x = x + widtheach + self.m_iPadding 163 | tallest = math.max( tallest, y + v:GetTall() + self.m_iPadding ) 164 | 165 | end 166 | 167 | return tallest 168 | 169 | end 170 | 171 | function PANEL:LayoutVertical( y ) 172 | 173 | for k, v in pairs( self.Boards ) do 174 | 175 | v:SizeToContents() 176 | v:SetPos( self.m_iPadding, y ) 177 | v:SetWide( self:GetWide() - self.m_iPadding * 2 ) 178 | y = y + v:GetTall() + self.m_iPadding 179 | 180 | end 181 | 182 | return y 183 | 184 | end 185 | 186 | function PANEL:PerformLayout() 187 | 188 | local y = 0 189 | 190 | if ( IsValid( self.Header ) ) then 191 | 192 | self.Header:SetPos( 0, 0 ) 193 | self.Header:SetWidth( self:GetWide() ) 194 | 195 | y = y + self.Header:GetTall() + self.m_iPadding 196 | 197 | end 198 | 199 | if ( self.m_bHorizontal ) then 200 | y = self:LayoutHorizontal( y ) 201 | else 202 | y = self:LayoutVertical( y ) 203 | end 204 | 205 | for k, v in pairs( self.SmallBoards ) do 206 | 207 | if ( v:ShouldShow() ) then 208 | 209 | v:SizeToContents() 210 | 211 | v:SetPos( self.m_iPadding, y ) 212 | v:CenterHorizontal() 213 | 214 | y = y + v:GetTall() + self.m_iPadding 215 | end 216 | 217 | end 218 | 219 | end 220 | 221 | derma.DefineControl( "FrettaScoreboard", "", PANEL, "DPanel" ) 222 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/vgui/vgui_scoreboard_team.lua: -------------------------------------------------------------------------------- 1 | local PANEL = {} 2 | 3 | Derma_Hook( PANEL, "Paint", "Paint", "TeamScoreboardHeader" ) 4 | Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "TeamScoreboardHeader" ) 5 | Derma_Hook( PANEL, "PerformLayout", "Layout", "TeamScoreboardHeader" ) 6 | 7 | function PANEL:Init() 8 | 9 | self.Columns = {} 10 | self.iTeamID = 0 11 | self.PlayerCount = 0 12 | 13 | self.TeamName = vgui.Create( "DLabel", self ) 14 | self.TeamScore = vgui.Create( "DLabel", self ) 15 | 16 | end 17 | 18 | function PANEL:Setup( iTeam, pMainScoreboard ) 19 | 20 | self.TeamName:SetText( team.GetName( iTeam ) ) 21 | self.iTeamID = iTeam 22 | 23 | end 24 | 25 | function PANEL:Think() 26 | 27 | local Count = #team.GetPlayers( self.iTeamID ) 28 | if ( self.PlayerCount != Count ) then 29 | self.PlayerCount = Count 30 | self.TeamName:SetText( team.GetName( self.iTeamID ) .. " (" .. self.PlayerCount .. " Players)" ) 31 | end 32 | 33 | self.TeamScore:SetText( team.GetScore( self.iTeamID ) ) 34 | 35 | end 36 | 37 | derma.DefineControl( "TeamScoreboardHeader", "", PANEL, "Panel" ) 38 | 39 | 40 | 41 | 42 | local PANEL = {} 43 | 44 | function PANEL:Init() 45 | 46 | self.Columns = {} 47 | 48 | self.List = vgui.Create( "DListView", self ) 49 | self.List:SetSortable( false ) 50 | self.List:DisableScrollbar() 51 | self.List:SetMultiSelect( false ) 52 | 53 | self.Header = vgui.Create( "TeamScoreboardHeader", self ) 54 | 55 | end 56 | 57 | function PANEL:Setup( iTeam, pMainScoreboard ) 58 | 59 | self.iTeam = iTeam 60 | self.pMain = pMainScoreboard 61 | 62 | self.Header:Setup( iTeam, pMainScoreboard ) 63 | 64 | end 65 | 66 | function PANEL:SizeToContents() 67 | 68 | self.List:SizeToContents() 69 | local tall = self.List:GetTall() 70 | 71 | self:SetTall( tall + self.Header:GetTall() ) 72 | 73 | end 74 | 75 | function PANEL:PerformLayout() 76 | 77 | if ( self.pMain:GetShowScoreboardHeaders() ) then 78 | 79 | self.Header:SetPos( 0, 0 ) 80 | self.Header:CopyWidth( self ) 81 | 82 | else 83 | 84 | self.Header:SetTall( 0 ) 85 | self.Header:SetVisible( false ) 86 | 87 | end 88 | 89 | self:SizeToContents() 90 | self.List:StretchToParent( 0, self.Header:GetTall(), 0, 0 ) 91 | self.List:SetDataHeight( self.pMain:GetRowHeight() ) 92 | self.List:SetHeaderHeight( 16 ) 93 | 94 | end 95 | 96 | function PANEL:AddColumn( col ) 97 | 98 | table.insert( self.Columns, col ) 99 | 100 | local pnlCol = self.List:AddColumn( col.Name ) 101 | 102 | if (col.iFixedSize) then pnlCol:SetMinWidth( col.iFixedSize ) pnlCol:SetMaxWidth( col.iFixedSize ) end 103 | if (col.HeaderAlign) then 104 | pnlCol.Header:SetContentAlignment( col.HeaderAlign ) 105 | end 106 | 107 | Derma_Hook( pnlCol, "Paint", "Paint", "ScorePanelHeader" ) 108 | 109 | pnlCol.cTeamColor = team.GetColor( self.iTeam ) 110 | 111 | Derma_Hook( pnlCol.Header, "Paint", "Paint", "ScorePanelHeaderLabel" ) 112 | Derma_Hook( pnlCol.Header, "ApplySchemeSettings", "Scheme", "ScorePanelHeaderLabel" ) 113 | Derma_Hook( pnlCol.Header, "PerformLayout", "Layout", "ScorePanelHeaderLabel" ) 114 | 115 | pnlCol.Header:ApplySchemeSettings() 116 | 117 | end 118 | 119 | function PANEL:SetSortColumns( ... ) 120 | 121 | self.SortArgs = ... 122 | 123 | end 124 | 125 | local function LinePressed(self, mcode) 126 | if mcode == MOUSE_LEFT and IsValid(self.pPlayer) then 127 | gamemode.Call("ScoreboardPlayerPressed", self.pPlayer) 128 | end 129 | end 130 | function PANEL:FindPlayerLine( ply ) 131 | 132 | for _, line in pairs( self.List.Lines ) do 133 | if ( line.pPlayer == ply ) then return line end 134 | end 135 | 136 | local line = self.List:AddLine() 137 | line.pPlayer = ply 138 | line.UpdateTime = {} 139 | 140 | line.OnMousePressed = LinePressed 141 | 142 | Derma_Hook( line, "Paint", "Paint", "ScorePanelLine" ) 143 | Derma_Hook( line, "ApplySchemeSettings", "Scheme", "ScorePanelLine" ) 144 | Derma_Hook( line, "PerformLayout", "Layout", "ScorePanelLine" ) 145 | 146 | self.pMain:InvalidateLayout() 147 | 148 | return line 149 | 150 | end 151 | 152 | function PANEL:UpdateColumn( i, col, pLine ) 153 | 154 | if ( !col.fncValue ) then return end 155 | 156 | pLine.UpdateTime[i] = pLine.UpdateTime[i] or 0 157 | if ( col.UpdateRate == 0 && pLine.UpdateTime[i] != 0 ) then return end // 0 = only update once 158 | if ( pLine.UpdateTime[i] > RealTime() ) then return end 159 | 160 | pLine.UpdateTime[i] = RealTime() + col.UpdateRate 161 | 162 | local Value = col.fncValue( pLine.pPlayer ) 163 | if ( Value == nil ) then return end 164 | 165 | local lbl = pLine:SetColumnText( i, Value ) 166 | if ( IsValid( lbl ) && !lbl.bScorePanelHooks ) then 167 | 168 | lbl.bScorePanelHooks = true 169 | 170 | if ( col.ValueAlign ) then lbl:SetContentAlignment( col.ValueAlign ) end 171 | if ( col.Font ) then lbl:SetFont( col.Font ) end 172 | 173 | lbl.pPlayer = pLine.pPlayer 174 | 175 | Derma_Hook( lbl, "Paint", "Paint", "ScorePanelLabel" ) 176 | Derma_Hook( lbl, "ApplySchemeSettings", "Scheme", "ScorePanelLabel" ) 177 | Derma_Hook( lbl, "PerformLayout", "Layout", "ScorePanelLabel" ) 178 | 179 | end 180 | 181 | 182 | end 183 | 184 | function PANEL:UpdateLine( pLine ) 185 | 186 | for i, col in pairs( self.Columns ) do 187 | self:UpdateColumn( i, col, pLine ) 188 | end 189 | 190 | end 191 | 192 | function PANEL:CleanLines( pLine ) 193 | 194 | for k, line in pairs( self.List.Lines ) do 195 | 196 | if ( !IsValid( line.pPlayer ) || line.pPlayer:Team() != self.iTeam ) then 197 | self.List:RemoveLine( k ) 198 | end 199 | 200 | end 201 | 202 | end 203 | 204 | function PANEL:Think() 205 | 206 | self:CleanLines() 207 | 208 | local players = team.GetPlayers( self.iTeam ) 209 | for _, player in pairs( players ) do 210 | 211 | local line = self:FindPlayerLine( player ) 212 | self:UpdateLine( line ) 213 | 214 | end 215 | 216 | if ( self.SortArgs ) then 217 | self.List:SortByColumns( unpack(self.SortArgs) ) 218 | end 219 | 220 | end 221 | 222 | derma.DefineControl( "TeamScoreboard", "", PANEL, "Panel" ) 223 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/player_extension.lua: -------------------------------------------------------------------------------- 1 | 2 | local meta = FindMetaTable( "Player" ) 3 | if (!meta) then return end 4 | 5 | function meta:SetPlayerClass( strName ) 6 | 7 | self:SetNWString( "Class", strName ) 8 | 9 | local c = player_class.Get( strName ) 10 | if ( !c ) then 11 | MsgN( "Warning: Player joined undefined class (", strName, ")" ) 12 | end 13 | 14 | end 15 | 16 | function meta:GetPlayerClassName() 17 | 18 | return self:GetNWString( "Class", "Default" ) 19 | 20 | end 21 | 22 | 23 | function meta:GetPlayerClass() 24 | 25 | // Class that has been set using SetClass 26 | local ClassName = self:GetPlayerClassName() 27 | local c = player_class.Get( ClassName ) 28 | if ( c ) then return c end 29 | 30 | // Class based on their Team 31 | local c = player_class.Get( self:Team() ) 32 | if ( c ) then return c end 33 | 34 | // If all else fails, use the default 35 | local c = player_class.Get( "Default" ) 36 | if ( c ) then return c end 37 | 38 | end 39 | 40 | function meta:SetRandomClass() 41 | 42 | local Classes = team.GetClass( self:Team() ) 43 | if ( Classes ) then 44 | local Class = table.Random( Classes ) 45 | self:SetPlayerClass( Class ) 46 | return 47 | end 48 | 49 | end 50 | 51 | function meta:CheckPlayerClassOnSpawn() 52 | 53 | local Classes = team.GetClass( self:Team() ) 54 | 55 | // The player has requested to spawn as a new class 56 | 57 | if ( self.m_SpawnAsClass ) then 58 | 59 | self:SetPlayerClass( self.m_SpawnAsClass ) 60 | self.m_SpawnAsClass = nil 61 | 62 | end 63 | 64 | // Make sure the player isn't using the wrong class 65 | 66 | if ( Classes && #Classes > 0 && !table.HasValue( Classes, self:GetPlayerClassName() ) ) then 67 | self:SetRandomClass() 68 | end 69 | 70 | // If the player is on a team with only one class, 71 | // make sure we're that one when we spawn. 72 | 73 | if ( Classes && #Classes == 1 ) then 74 | self:SetPlayerClass( Classes[1] ) 75 | end 76 | 77 | // No defined classes, use default class 78 | 79 | if ( !Classes || #Classes == 0 ) then 80 | self:SetPlayerClass( "Default" ) 81 | end 82 | 83 | end 84 | 85 | function meta:OnSpawn() 86 | 87 | local Class = self:GetPlayerClass() 88 | if ( !Class ) then return end 89 | 90 | if ( Class.DuckSpeed ) then self:SetDuckSpeed( Class.DuckSpeed ) end 91 | if ( Class.WalkSpeed ) then self:SetWalkSpeed( Class.WalkSpeed ) end 92 | if ( Class.RunSpeed ) then self:SetRunSpeed( Class.RunSpeed ) end 93 | if ( Class.CrouchedWalkSpeed ) then self:SetCrouchedWalkSpeed( Class.CrouchedWalkSpeed ) end 94 | if ( Class.JumpPower ) then self:SetJumpPower( Class.JumpPower ) end 95 | if ( Class.DrawTeamRing ) then self:SetNWBool( "DrawRing", true ) else self:SetNWBool( "DrawRing", false ) end 96 | if ( Class.DrawViewModel == false ) then self:DrawViewModel( false ) else self:DrawViewModel( true ) end 97 | if ( Class.CanUseFlashlight != nil ) then self:AllowFlashlight( Class.CanUseFlashlight ) end 98 | if ( Class.StartHealth ) then self:SetHealth( Class.StartHealth ) end 99 | if ( Class.MaxHealth ) then self:SetMaxHealth( Class.MaxHealth ) end 100 | if ( Class.StartArmor ) then self:SetArmor( Class.StartArmor ) end 101 | if ( Class.RespawnTime ) then self:SetRespawnTime( Class.RespawnTime ) end 102 | if ( Class.DropWeaponOnDie != nil ) then self:ShouldDropWeapon( Class.DropWeaponOnDie ) end 103 | if ( Class.TeammateNoCollide != nil ) then self:SetNoCollideWithTeammates( Class.TeammateNoCollide ) end 104 | if ( Class.AvoidPlayers != nil ) then self:SetAvoidPlayers( Class.AvoidPlayers ) end 105 | if ( Class.FullRotation != nil ) then self:SetAllowFullRotation( Class.FullRotation ) end 106 | 107 | self:CallClassFunction( "OnSpawn" ) 108 | 109 | end 110 | 111 | function meta:CallClassFunction( name, ... ) 112 | 113 | local Class = self:GetPlayerClass() 114 | if ( !Class ) then return end 115 | if ( !Class[name] ) then return end 116 | 117 | //print( "Class Function: ", self:GetPlayerClassName(), name ) 118 | 119 | return Class[name]( Class, self, ... ) 120 | 121 | end 122 | 123 | function meta:OnLoadout() 124 | 125 | self:CallClassFunction( "Loadout" ) 126 | 127 | end 128 | 129 | function meta:OnDeath() 130 | 131 | end 132 | 133 | function meta:OnPlayerModel() 134 | 135 | // If the class forces a player model, use that.. 136 | // If not, use our preferred model.. 137 | 138 | local Class = self:GetPlayerClass() 139 | if ( Class && Class.PlayerModel ) then 140 | 141 | local mdl = Class.PlayerModel 142 | if( type( mdl ) == "table" ) then // table of models, set random 143 | mdl = table.Random( Class.PlayerModel ); 144 | end 145 | 146 | util.PrecacheModel( mdl ); 147 | self:SetModel( mdl ); 148 | return 149 | 150 | end 151 | 152 | local cl_playermodel = self:GetInfo( "cl_playermodel" ) 153 | local modelname = player_manager.TranslatePlayerModel( cl_playermodel ) 154 | util.PrecacheModel( modelname ) 155 | self:SetModel( modelname ) 156 | 157 | end 158 | 159 | function meta:AllowFlashlight( bAble ) 160 | 161 | self.m_bFlashlight = bAble 162 | 163 | end 164 | 165 | function meta:CanUseFlashlight() 166 | 167 | if self.m_bFlashlight == nil then 168 | return true // Default to true unless modified by the player class 169 | end 170 | 171 | return self.m_bFlashlight 172 | 173 | end 174 | 175 | function meta:SetRespawnTime( num ) 176 | 177 | self.m_iSpawnTime = num 178 | 179 | end 180 | 181 | function meta:GetRespawnTime( num ) 182 | 183 | if ( self.m_iSpawnTime == 0 || !self.m_iSpawnTime ) then 184 | return GAMEMODE.MinimumDeathLength 185 | end 186 | return self.m_iSpawnTime 187 | 188 | end 189 | 190 | function meta:DisableRespawn( strReason ) 191 | 192 | self.m_bCanRespawn = false 193 | 194 | end 195 | 196 | function meta:EnableRespawn() 197 | 198 | self.m_bCanRespawn = true 199 | 200 | end 201 | 202 | function meta:CanRespawn() 203 | 204 | return self.m_bCanRespawn == nil || self.m_bCanRespawn == true 205 | 206 | end 207 | 208 | function meta:IsObserver() 209 | return ( self:GetObserverMode() > OBS_MODE_NONE ); 210 | end 211 | 212 | function meta:UpdateNameColor() 213 | 214 | if ( GAMEMODE.SelectColor ) then 215 | self:SetNWString( "NameColor", self:GetInfo( "cl_playercolor" ) ) 216 | end 217 | 218 | end 219 | 220 | function meta:Frags() 221 | return self:GetDTInt(14) 222 | end 223 | 224 | local OldSetFrags = meta.SetFrags 225 | function meta:SetFrags(frags) 226 | OldSetFrags(self, frags) 227 | self:SetDTInt(14, frags) 228 | end 229 | 230 | function meta:AddFrags(frags) 231 | self:SetFrags(self:Frags() + frags) 232 | end 233 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/cl_init.lua: -------------------------------------------------------------------------------- 1 | 2 | function surface.CreateLegacyFont(font, size, weight, antialias, additive, name, shadow, outline, blursize) 3 | surface.CreateFont(name, {font = font, size = size, weight = weight, antialias = antialias, additive = additive, shadow = shadow, outline = outline, blursize = blursize}) 4 | end 5 | 6 | include( 'shared.lua' ) 7 | include( 'cl_splashscreen.lua' ) 8 | include( 'cl_selectscreen.lua' ) 9 | include( 'cl_gmchanger.lua' ) 10 | include( 'cl_help.lua' ) 11 | include( 'skin.lua' ) 12 | include( 'vgui/vgui_hudlayout.lua' ) 13 | include( 'vgui/vgui_hudelement.lua' ) 14 | include( 'vgui/vgui_hudbase.lua' ) 15 | include( 'vgui/vgui_hudcommon.lua' ) 16 | include( 'cl_hud.lua' ) 17 | include( 'cl_deathnotice.lua' ) 18 | include( 'cl_scores.lua' ) 19 | include( 'cl_notify.lua' ) 20 | 21 | language.Add( "env_laser", "Laser" ) 22 | language.Add( "env_explosion", "Explosion" ) 23 | language.Add( "func_door", "Door" ) 24 | language.Add( "func_door_rotating", "Door" ) 25 | language.Add( "trigger_hurt", "Hazard" ) 26 | language.Add( "func_rotating", "Hazard" ) 27 | language.Add( "worldspawn", "Gravity" ) 28 | language.Add( "prop_physics", "Prop" ) 29 | language.Add( "prop_physics_respawnable", "Prop" ) 30 | language.Add( "prop_physics_multiplayer", "Prop" ) 31 | language.Add( "entityflame", "Fire" ) 32 | 33 | surface.CreateLegacyFont( "Trebuchet MS", 69, 700, true, false, "FRETTA_HUGE" ) 34 | surface.CreateLegacyFont( "Trebuchet MS", 69, 700, true, false, "FRETTA_HUGE_SHADOW", true ) 35 | surface.CreateLegacyFont( "Trebuchet MS", 40, 700, true, false, "FRETTA_LARGE" ) 36 | surface.CreateLegacyFont( "Trebuchet MS", 40, 700, true, false, "FRETTA_LARGE_SHADOW", true ) 37 | surface.CreateLegacyFont( "Trebuchet MS", 19, 700, true, false, "FRETTA_MEDIUM" ) 38 | surface.CreateLegacyFont( "Trebuchet MS", 19, 700, true, false, "FRETTA_MEDIUM_SHADOW", true ) 39 | surface.CreateLegacyFont( "Trebuchet MS", 16, 700, true, false, "FRETTA_SMALL" ) 40 | 41 | surface.CreateLegacyFont( "Trebuchet MS", ScreenScale( 10 ), 700, true, false, "FRETTA_NOTIFY", true ) 42 | 43 | surface.CreateLegacyFont( "csd", ScreenScale(30), 500, true, true, "CSKillIcons" ) 44 | surface.CreateLegacyFont( "csd", ScreenScale(60), 500, true, true, "CSSelectIcons" ) 45 | 46 | CreateClientConVar( "cl_spec_mode", "5", true, true ) 47 | 48 | function GM:Initialize() 49 | 50 | self.BaseClass:Initialize() 51 | 52 | end 53 | 54 | function GM:InitPostEntity() 55 | 56 | if ( GAMEMODE.TeamBased ) then 57 | GAMEMODE:ShowTeam(); 58 | end 59 | 60 | GAMEMODE:ShowSplash(); 61 | 62 | end 63 | 64 | local CircleMat = Material( "SGM/playercircle" ); 65 | 66 | function GM:DrawPlayerRing( pPlayer ) 67 | 68 | if ( !IsValid( pPlayer ) ) then return end 69 | if ( !pPlayer:GetNWBool( "DrawRing", false ) ) then return end 70 | if ( !pPlayer:Alive() ) then return end 71 | 72 | local trace = {} 73 | trace.start = pPlayer:GetPos() + Vector(0,0,50) 74 | trace.endpos = trace.start + Vector(0,0,-300) 75 | trace.filter = pPlayer 76 | 77 | local tr = util.TraceLine( trace ) 78 | 79 | if not tr.HitWorld then 80 | tr.HitPos = pPlayer:GetPos() 81 | end 82 | 83 | local color = table.Copy( team.GetColor( pPlayer:Team() ) ) 84 | color.a = 40; 85 | 86 | render.SetMaterial( CircleMat ) 87 | render.DrawQuadEasy( tr.HitPos + tr.HitNormal, tr.HitNormal, GAMEMODE.PlayerRingSize, GAMEMODE.PlayerRingSize, color ) 88 | 89 | end 90 | 91 | hook.Add( "PrePlayerDraw", "DrawPlayerRing", function( ply ) GAMEMODE:DrawPlayerRing( ply ) end ) 92 | 93 | function GM:HUDShouldDraw( name ) 94 | 95 | if GAMEMODE.ScoreboardVisible then return false end 96 | 97 | // commented out until HUD elements are made 98 | //for k, v in pairs{"CHudHealth", "CHudBattery", "CHudAmmo", "CHudSecondaryAmmo"} do 99 | // if name == v then return false end 100 | //end 101 | 102 | if name == "CHudDamageIndicator" and not LocalPlayer():Alive() then 103 | return false 104 | end 105 | 106 | return true 107 | 108 | end 109 | 110 | function GM:OnSpawnMenuOpen() 111 | RunConsoleCommand( "lastinv" ); // Fretta is derived from base and has no spawn menu, so give it a use, make it lastinv. 112 | end 113 | 114 | 115 | function GM:PlayerBindPress( pl, bind, down ) 116 | 117 | // Redirect binds to the spectate system 118 | if ( pl:IsObserver() && down ) then 119 | 120 | if ( bind == "+jump" ) then RunConsoleCommand( "spec_mode" ) end 121 | if ( bind == "+attack" ) then RunConsoleCommand( "spec_next" ) end 122 | if ( bind == "+attack2" ) then RunConsoleCommand( "spec_prev" ) end 123 | 124 | end 125 | 126 | return false 127 | 128 | end 129 | 130 | /*--------------------------------------------------------- 131 | Name: gamemode:GetTeamColor( ent ) 132 | ---------------------------------------------------------*/ 133 | function GM:GetTeamColor( ent ) 134 | 135 | if ( GAMEMODE.SelectColor && IsValid( ent ) ) then 136 | 137 | local clr = ent:GetNWString( "NameColor", -1 ) 138 | if ( clr && clr != -1 && clr != "" ) then 139 | clr = list.Get( "PlayerColours" )[ clr ] 140 | if ( clr ) then return clr end 141 | end 142 | 143 | end 144 | 145 | local team = TEAM_UNASSIGNED 146 | if ( ent.Team and IsValid(ent) ) then team = ent:Team() end 147 | return GAMEMODE:GetTeamNumColor( team ) 148 | 149 | end 150 | 151 | 152 | /*--------------------------------------------------------- 153 | Name: ShouldDrawLocalPlayer 154 | ---------------------------------------------------------*/ 155 | function GM:ShouldDrawLocalPlayer( ply ) 156 | return ply:CallClassFunction( "ShouldDrawLocalPlayer" ) 157 | end 158 | 159 | 160 | /*--------------------------------------------------------- 161 | Name: InputMouseApply 162 | ---------------------------------------------------------*/ 163 | function GM:InputMouseApply( cmd, x, y, angle ) 164 | 165 | return LocalPlayer():CallClassFunction( "InputMouseApply", cmd, x, y, angle ) 166 | 167 | end 168 | 169 | function GM:TeamChangeNotification( ply, oldteam, newteam ) 170 | if( ply && ply:IsValid() ) then 171 | local nick = ply:Nick(); 172 | local oldTeamColor = team.GetColor( oldteam ); 173 | local newTeamName = team.GetName( newteam ); 174 | local newTeamColor = team.GetColor( newteam ); 175 | 176 | if( newteam == TEAM_SPECTATOR ) then 177 | chat.AddText( oldTeamColor, nick, color_white, " is now spectating" ); 178 | else 179 | chat.AddText( oldTeamColor, nick, color_white, " joined ", newTeamColor, newTeamName ); 180 | end 181 | 182 | chat.PlaySound( "buttons/button15.wav" ); 183 | end 184 | end 185 | net.Receive( "fretta_teamchange", function( um ) if ( GAMEMODE ) then GAMEMODE:TeamChangeNotification( net.ReadEntity(), net.ReadUInt(16), net.ReadUInt(16) ) end end ) 186 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/vgui/vgui_vote.lua: -------------------------------------------------------------------------------- 1 | local PANEL = {} 2 | 3 | function PANEL:Init() 4 | 5 | self:SetSkin( GAMEMODE.HudSkin ) 6 | self:ParentToHUD() 7 | 8 | self.ControlCanvas = vgui.Create( "Panel", self ) 9 | self.ControlCanvas:MakePopup() 10 | self.ControlCanvas:SetKeyboardInputEnabled( false ) 11 | 12 | self.lblCountDown = vgui.Create( "DLabel", self.ControlCanvas ) 13 | self.lblCountDown:SetText( "60" ) 14 | 15 | self.lblActionName = vgui.Create( "DLabel", self.ControlCanvas ) 16 | 17 | self.ctrlList = vgui.Create( "DPanelList", self.ControlCanvas ) 18 | self.ctrlList:SetDrawBackground( false ) 19 | self.ctrlList:SetSpacing( 2 ) 20 | self.ctrlList:SetPadding( 2 ) 21 | self.ctrlList:EnableHorizontal( true ) 22 | self.ctrlList:EnableVerticalScrollbar() 23 | 24 | self.Peeps = {} 25 | 26 | for i =1, game.MaxPlayers() do 27 | 28 | self.Peeps[i] = vgui.Create( "DImage", self.ctrlList:GetCanvas() ) 29 | self.Peeps[i]:SetSize( 16, 16 ) 30 | self.Peeps[i]:SetZPos( 1000 ) 31 | self.Peeps[i]:SetVisible( false ) 32 | self.Peeps[i]:SetImage( "icon16/emoticon_smile.png" ) 33 | 34 | end 35 | 36 | end 37 | 38 | function PANEL:PerformLayout() 39 | 40 | local cx, cy = chat.GetChatBoxPos() 41 | 42 | self:SetPos( 0, 0 ) 43 | self:SetSize( ScrW(), ScrH() ) 44 | 45 | self.ControlCanvas:StretchToParent( 0, 0, 0, 0 ) 46 | self.ControlCanvas:SetWide( 550 ) 47 | self.ControlCanvas:SetTall( cy - 30 ) 48 | self.ControlCanvas:SetPos( 0, 30 ) 49 | self.ControlCanvas:CenterHorizontal(); 50 | self.ControlCanvas:SetZPos( 0 ) 51 | 52 | self.lblCountDown:SetFont( "FRETTA_MEDIUM_SHADOW" ) 53 | self.lblCountDown:AlignRight() 54 | self.lblCountDown:SetTextColor( color_white ) 55 | self.lblCountDown:SetContentAlignment( 6 ) 56 | self.lblCountDown:SetWidth( 500 ) 57 | 58 | self.lblActionName:SetFont( "FRETTA_LARGE_SHADOW" ) 59 | self.lblActionName:AlignLeft() 60 | self.lblActionName:SetTextColor( color_white ) 61 | self.lblActionName:SizeToContents() 62 | self.lblActionName:SetWidth( 500 ) 63 | 64 | self.ctrlList:StretchToParent( 0, 60, 0, 0 ) 65 | 66 | end 67 | 68 | function PANEL:ChooseGamemode() 69 | 70 | self.lblActionName:SetText( "Which Gamemode Next?" ) 71 | self.ctrlList:Clear() 72 | 73 | for name, gamemode in RandomPairs( g_PlayableGamemodes ) do 74 | 75 | local lbl = vgui.Create( "DButton", self.ctrlList ) 76 | lbl:SetText( gamemode.label or name ) 77 | 78 | Derma_Hook( lbl, "Paint", "Paint", "GamemodeButton" ) 79 | Derma_Hook( lbl, "ApplySchemeSettings", "Scheme", "GamemodeButton" ) 80 | Derma_Hook( lbl, "PerformLayout", "Layout", "GamemodeButton" ) 81 | 82 | lbl:SetTall( 24 ) 83 | lbl:SetWide( 240 ) 84 | 85 | local desc = tostring( gamemode.description ); 86 | if ( gamemode.author ) then desc = desc .. "\n\nBy: " .. tostring( gamemode.author ) end 87 | if ( gamemode.authorurl ) then desc = desc .. "\n" .. tostring( gamemode.authorurl ) end 88 | 89 | lbl:SetTooltip( desc ) 90 | 91 | lbl.WantName = name 92 | lbl.NumVotes = 0 93 | lbl.DoClick = function() if GetGlobalFloat( "VoteEndTime", 0 ) - CurTime() <= 0 then return end RunConsoleCommand( "votegamemode", name ) end 94 | 95 | self.ctrlList:AddItem( lbl ) 96 | 97 | end 98 | 99 | end 100 | 101 | function PANEL:ChooseMap( gamemode ) 102 | 103 | self.lblActionName:SetText( "Which Map?" ) 104 | self:ResetPeeps() 105 | self.ctrlList:Clear() 106 | 107 | local gm = g_PlayableGamemodes[ gamemode ] 108 | if ( !gm ) then MsgN( "GAMEMODE MISSING, COULDN'T VOTE FOR MAP ", gamemode ) return end 109 | 110 | for id, mapname in RandomPairs( gm.maps ) do 111 | local lbl = vgui.Create( "DButton", self.ctrlList ) 112 | lbl:SetText( mapname ) 113 | 114 | Derma_Hook( lbl, "Paint", "Paint", "GamemodeButton" ) 115 | Derma_Hook( lbl, "ApplySchemeSettings", "Scheme", "GamemodeButton" ) 116 | Derma_Hook( lbl, "PerformLayout", "Layout", "GamemodeButton" ) 117 | 118 | lbl:SetTall( 24 ) 119 | lbl:SetWide( 240 ) 120 | 121 | lbl.WantName = mapname 122 | lbl.NumVotes = 0 123 | lbl.DoClick = function() if GetGlobalFloat( "VoteEndTime", 0 ) - CurTime() <= 0 then return end RunConsoleCommand( "votemap", mapname ) end 124 | 125 | --[[if file.Exists("maps/"..mapname..".png", "MOD") then 126 | lbl:SetTall(72) 127 | 128 | local Image = vgui.Create("DImage", lbl) 129 | Image:SetImage("../maps/"..mapname..".png") 130 | Image:SizeToContents() 131 | Image:SetSize(math.min(Image:GetWide(), 64), math.min(Image:GetTall(), 64)) 132 | Image:AlignRight(4) 133 | Image:CenterVertical() 134 | end]] 135 | 136 | self.ctrlList:AddItem( lbl ) 137 | 138 | end 139 | 140 | end 141 | 142 | function PANEL:ResetPeeps() 143 | 144 | for i=1, game.MaxPlayers() do 145 | self.Peeps[i]:SetPos( math.random( 0, 600 ), -16 ) 146 | self.Peeps[i]:SetVisible( false ) 147 | self.Peeps[i].strVote = nil 148 | end 149 | 150 | end 151 | 152 | function PANEL:FindWantBar( name ) 153 | 154 | for k, v in pairs( self.ctrlList:GetItems() ) do 155 | if ( v.WantName == name ) then return v end 156 | end 157 | 158 | end 159 | 160 | function PANEL:PeepThink( peep, ent ) 161 | 162 | if ( !IsValid( ent ) ) then 163 | peep:SetVisible( false ) 164 | return 165 | end 166 | 167 | peep:SetTooltip( ent:Nick() ) 168 | peep:SetMouseInputEnabled( true ) 169 | 170 | if ( !peep.strVote ) then 171 | peep:SetVisible( true ) 172 | peep:SetPos( math.random( 0, 600 ), -16 ) 173 | if ( ent == LocalPlayer() ) then 174 | peep:SetImage( "icon16/star.png" ) 175 | end 176 | end 177 | 178 | peep.strVote = ent:GetNWString( "Wants", "" ) 179 | local bar = self:FindWantBar( peep.strVote ) 180 | if ( IsValid( bar ) ) then 181 | 182 | bar.NumVotes = bar.NumVotes + 1 183 | local vCurrentPos = Vector( peep.x, peep.y, 0 ) 184 | local vNewPos = Vector( (bar.x + bar:GetWide()) - 15 * bar.NumVotes - 4, bar.y + ( bar:GetTall() * 0.5 - 8 ), 0 ) 185 | 186 | if ( !peep.CurPos || peep.CurPos != vNewPos ) then 187 | 188 | peep:MoveTo( vNewPos.x, vNewPos.y, 0.2 ) 189 | peep.CurPos = vNewPos 190 | 191 | end 192 | 193 | end 194 | 195 | end 196 | 197 | function PANEL:Think() 198 | 199 | local Seconds = GetGlobalFloat( "VoteEndTime", 0 ) - CurTime() 200 | if ( Seconds < 0 ) then Seconds = 0 end 201 | 202 | self.lblCountDown:SetText( Format( "%i", Seconds ) ) 203 | 204 | for k, v in pairs( self.ctrlList:GetItems() ) do 205 | v.NumVotes = 0 206 | end 207 | 208 | for i=1, game.MaxPlayers() do 209 | self:PeepThink( self.Peeps[i], Entity(i) ) 210 | end 211 | 212 | end 213 | 214 | function PANEL:Paint() 215 | 216 | Derma_DrawBackgroundBlur( self ) 217 | 218 | local CenterY = ScrH() / 2.0 219 | local CenterX = ScrW() / 2.0 220 | 221 | surface.SetDrawColor( 0, 0, 0, 200 ); 222 | surface.DrawRect( 0, 0, ScrW(), ScrH() ); 223 | 224 | end 225 | 226 | function PANEL:FlashItem( itemname ) 227 | 228 | local bar = self:FindWantBar( itemname ) 229 | if ( !IsValid( bar ) ) then return end 230 | 231 | timer.Simple( 0.0, function() bar.bgColor = Color( 0, 255, 255 ) surface.PlaySound( "hl1/fvox/blip.wav" ) end ) 232 | timer.Simple( 0.2, function() bar.bgColor = nil end ) 233 | timer.Simple( 0.4, function() bar.bgColor = Color( 0, 255, 255 ) surface.PlaySound( "hl1/fvox/blip.wav" ) end ) 234 | timer.Simple( 0.6, function() bar.bgColor = nil end ) 235 | timer.Simple( 0.8, function() bar.bgColor = Color( 0, 255, 255 ) surface.PlaySound( "hl1/fvox/blip.wav" ) end ) 236 | timer.Simple( 1.0, function() bar.bgColor = Color( 100, 100, 100 ) end ) 237 | 238 | end 239 | 240 | derma.DefineControl( "VoteScreen", "", PANEL, "DPanel" ) 241 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/cl_hud.lua: -------------------------------------------------------------------------------- 1 | 2 | local hudScreen = nil 3 | local Alive = false 4 | local Class = nil 5 | local Team = 0 6 | local WaitingToRespawn = false 7 | local InRound = false 8 | local RoundResult = 0 9 | local RoundWinner = nil 10 | local IsObserver = false 11 | local ObserveMode = 0 12 | local ObserveTarget = NULL 13 | local InVote = false 14 | 15 | function GM:AddHUDItem( item, pos, parent ) 16 | hudScreen:AddItem( item, parent, pos ) 17 | end 18 | 19 | function GM:HUDNeedsUpdate() 20 | 21 | if ( !IsValid( LocalPlayer() ) ) then return false end 22 | 23 | if ( Class != LocalPlayer():GetNWString( "Class", "Default" ) ) then return true end 24 | if ( Alive != LocalPlayer():Alive() ) then return true end 25 | if ( Team != LocalPlayer():Team() ) then return true end 26 | if ( WaitingToRespawn != ( (LocalPlayer():GetNWFloat( "RespawnTime", 0 ) > CurTime()) && LocalPlayer():Team() != TEAM_SPECTATOR && !LocalPlayer():Alive()) ) then return true end 27 | if ( InRound != GetGlobalBool( "InRound", false ) ) then return true end 28 | if ( RoundResult != GetGlobalInt( "RoundResult", 0 ) ) then return true end 29 | if ( RoundWinner != GetGlobalEntity( "RoundWinner", nil ) ) then return true end 30 | if ( IsObserver != LocalPlayer():IsObserver() ) then return true end 31 | if ( ObserveMode != LocalPlayer():GetObserverMode() ) then return true end 32 | if ( ObserveTarget != LocalPlayer():GetObserverTarget() ) then return true end 33 | if ( InVote != GAMEMODE:InGamemodeVote() ) then return true end 34 | 35 | return false 36 | end 37 | 38 | function GM:OnHUDUpdated() 39 | Class = LocalPlayer():GetNWString( "Class", "Default" ) 40 | Alive = LocalPlayer():Alive() 41 | Team = LocalPlayer():Team() 42 | WaitingToRespawn = (LocalPlayer():GetNWFloat( "RespawnTime", 0 ) > CurTime()) && LocalPlayer():Team() != TEAM_SPECTATOR && !Alive 43 | InRound = GetGlobalBool( "InRound", false ) 44 | RoundResult = GetGlobalInt( "RoundResult", 0 ) 45 | RoundWinner = GetGlobalEntity( "RoundWinner", nil ) 46 | IsObserver = LocalPlayer():IsObserver() 47 | ObserveMode = LocalPlayer():GetObserverMode() 48 | ObserveTarget = LocalPlayer():GetObserverTarget() 49 | InVote = GAMEMODE:InGamemodeVote() 50 | end 51 | 52 | function GM:OnHUDPaint() 53 | 54 | end 55 | 56 | function GM:RefreshHUD() 57 | 58 | if ( !GAMEMODE:HUDNeedsUpdate() ) then return end 59 | GAMEMODE:OnHUDUpdated() 60 | 61 | if ( IsValid( hudScreen ) ) then hudScreen:Remove() end 62 | hudScreen = vgui.Create( "DHudLayout" ) 63 | 64 | if ( InVote ) then return end 65 | 66 | if ( RoundWinner and RoundWinner != NULL ) then 67 | GAMEMODE:UpdateHUD_RoundResult( RoundWinner, Alive ) 68 | elseif ( RoundResult != 0 ) then 69 | GAMEMODE:UpdateHUD_RoundResult( RoundResult, Alive ) 70 | elseif ( IsObserver ) then 71 | GAMEMODE:UpdateHUD_Observer( WaitingToRespawn, InRound, ObserveMode, ObserveTarget ) 72 | elseif ( !Alive ) then 73 | GAMEMODE:UpdateHUD_Dead( WaitingToRespawn, InRound ) 74 | else 75 | GAMEMODE:UpdateHUD_Alive( InRound ) 76 | end 77 | 78 | end 79 | 80 | function GM:HUDPaint() 81 | 82 | self.BaseClass:HUDPaint() 83 | 84 | GAMEMODE:OnHUDPaint() 85 | GAMEMODE:RefreshHUD() 86 | 87 | end 88 | 89 | function GM:UpdateHUD_RoundResult( RoundResult, Alive ) 90 | 91 | local txt = GetGlobalString( "RRText" ) 92 | 93 | if ( type( RoundResult ) == "number" ) && ( team.GetAllTeams()[ RoundResult ] && txt == "" ) then 94 | local TeamName = team.GetName( RoundResult ) 95 | if ( TeamName ) then txt = TeamName .. " Wins!" end 96 | elseif ( type( RoundResult ) == "Player" && IsValid( RoundResult ) && txt == "" ) then 97 | txt = RoundResult:Name() .. " Wins!" 98 | end 99 | 100 | local RespawnText = vgui.Create( "DHudElement" ); 101 | RespawnText:SizeToContents() 102 | RespawnText:SetText( txt ) 103 | GAMEMODE:AddHUDItem( RespawnText, 8 ) 104 | 105 | end 106 | 107 | function GM:UpdateHUD_Observer( bWaitingToSpawn, InRound, ObserveMode, ObserveTarget ) 108 | 109 | local lbl = nil 110 | local txt = nil 111 | local col = Color( 255, 255, 255 ); 112 | 113 | if ( IsValid( ObserveTarget ) && ObserveTarget:IsPlayer() && ObserveTarget != LocalPlayer() && ObserveMode != OBS_MODE_ROAMING ) then 114 | lbl = "SPECTATING" 115 | txt = ObserveTarget:Nick() 116 | col = team.GetColor( ObserveTarget:Team() ); 117 | end 118 | 119 | if ( ObserveMode == OBS_MODE_DEATHCAM || ObserveMode == OBS_MODE_FREEZECAM ) then 120 | txt = "You Died!" // were killed by? 121 | end 122 | 123 | if ( txt ) then 124 | local txtLabel = vgui.Create( "DHudElement" ); 125 | txtLabel:SetText( txt ) 126 | if ( lbl ) then txtLabel:SetLabel( lbl ) end 127 | txtLabel:SetTextColor( col ) 128 | 129 | GAMEMODE:AddHUDItem( txtLabel, 2 ) 130 | end 131 | 132 | 133 | GAMEMODE:UpdateHUD_Dead( bWaitingToSpawn, InRound ) 134 | 135 | end 136 | 137 | function GM:UpdateHUD_Dead( bWaitingToSpawn, InRound ) 138 | 139 | if ( !InRound && GAMEMODE.RoundBased ) then 140 | 141 | local RespawnText = vgui.Create( "DHudElement" ); 142 | RespawnText:SizeToContents() 143 | RespawnText:SetText( "Waiting for round start" ) 144 | GAMEMODE:AddHUDItem( RespawnText, 8 ) 145 | return 146 | 147 | end 148 | 149 | if ( bWaitingToSpawn ) then 150 | 151 | local RespawnTimer = vgui.Create( "DHudCountdown" ); 152 | RespawnTimer:SizeToContents() 153 | RespawnTimer:SetValueFunction( function() return LocalPlayer():GetNWFloat( "RespawnTime", 0 ) end ) 154 | RespawnTimer:SetLabel( "SPAWN IN" ) 155 | GAMEMODE:AddHUDItem( RespawnTimer, 8 ) 156 | return 157 | 158 | end 159 | 160 | if ( InRound ) then 161 | 162 | local RoundTimer = vgui.Create( "DHudCountdown" ); 163 | RoundTimer:SizeToContents() 164 | RoundTimer:SetValueFunction( function() 165 | if ( GetGlobalFloat( "RoundStartTime", 0 ) > CurTime() ) then return GetGlobalFloat( "RoundStartTime", 0 ) end 166 | return GetGlobalFloat( "RoundEndTime" ) end ) 167 | RoundTimer:SetLabel( "TIME" ) 168 | GAMEMODE:AddHUDItem( RoundTimer, 8 ) 169 | return 170 | 171 | end 172 | 173 | if ( Team != TEAM_SPECTATOR && !Alive ) then 174 | 175 | local RespawnText = vgui.Create( "DHudElement" ); 176 | RespawnText:SizeToContents() 177 | RespawnText:SetText( "Press Fire to Spawn" ) 178 | GAMEMODE:AddHUDItem( RespawnText, 8 ) 179 | 180 | end 181 | 182 | end 183 | 184 | function GM:UpdateHUD_Alive( InRound ) 185 | 186 | if ( GAMEMODE.RoundBased || GAMEMODE.TeamBased ) then 187 | 188 | local Bar = vgui.Create( "DHudBar" ) 189 | GAMEMODE:AddHUDItem( Bar, 2 ) 190 | 191 | if ( GAMEMODE.TeamBased && GAMEMODE.ShowTeamName ) then 192 | 193 | local TeamIndicator = vgui.Create( "DHudUpdater" ); 194 | TeamIndicator:SizeToContents() 195 | TeamIndicator:SetValueFunction( function() 196 | return team.GetName( LocalPlayer():Team() ) 197 | end ) 198 | TeamIndicator:SetColorFunction( function() 199 | return team.GetColor( LocalPlayer():Team() ) 200 | end ) 201 | TeamIndicator:SetFont( "HudSelectionText" ) 202 | Bar:AddItem( TeamIndicator ) 203 | 204 | end 205 | 206 | if ( GAMEMODE.RoundBased ) then 207 | 208 | local RoundNumber = vgui.Create( "DHudUpdater" ); 209 | RoundNumber:SizeToContents() 210 | RoundNumber:SetValueFunction( function() return GetGlobalInt( "RoundNumber", 0 ) end ) 211 | RoundNumber:SetLabel( "ROUND" ) 212 | Bar:AddItem( RoundNumber ) 213 | 214 | local RoundTimer = vgui.Create( "DHudCountdown" ); 215 | RoundTimer:SizeToContents() 216 | RoundTimer:SetValueFunction( function() 217 | if ( GetGlobalFloat( "RoundStartTime", 0 ) > CurTime() ) then return GetGlobalFloat( "RoundStartTime", 0 ) end 218 | return GetGlobalFloat( "RoundEndTime" ) end ) 219 | RoundTimer:SetLabel( "TIME" ) 220 | Bar:AddItem( RoundTimer ) 221 | 222 | end 223 | 224 | end 225 | 226 | end 227 | 228 | function GM:UpdateHUD_AddedTime( iTimeAdded ) 229 | // to do or to override, your choice 230 | end 231 | net.Receive( "RoundAddedTime", function( length ) if ( GAMEMODE ) then GAMEMODE:UpdateHUD_AddedTime( net.ReadFloat() ) end end ) 232 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/sv_spectator.lua: -------------------------------------------------------------------------------- 1 | 2 | /*--------------------------------------------------------- 3 | Name: gamemode:GetValidSpectatorModes( Player ply ) 4 | Desc: Gets a table of the allowed spectator modes (OBS_MODE_INEYE, etc) 5 | Player is the player object of the spectator 6 | ---------------------------------------------------------*/ 7 | function GM:GetValidSpectatorModes( ply ) 8 | 9 | // Note: Override this and return valid modes per player/team 10 | 11 | return GAMEMODE.ValidSpectatorModes 12 | 13 | end 14 | 15 | /*--------------------------------------------------------- 16 | Name: gamemode:GetValidSpectatorEntityNames( Player ply ) 17 | Desc: Returns a table of entities that can be spectated (player etc) 18 | ---------------------------------------------------------*/ 19 | function GM:GetValidSpectatorEntityNames( ply ) 20 | 21 | // Note: Override this and return valid entity names per player/team 22 | 23 | return GAMEMODE.ValidSpectatorEntities 24 | 25 | end 26 | 27 | /*--------------------------------------------------------- 28 | Name: gamemode:IsValidSpectator( Player ply ) 29 | Desc: Is our player spectating - and valid? 30 | ---------------------------------------------------------*/ 31 | function GM:IsValidSpectator( pl ) 32 | 33 | if ( !IsValid( pl ) ) then return false end 34 | if ( pl:Team() != TEAM_SPECTATOR && !pl:IsObserver() ) then return false end 35 | 36 | return true 37 | 38 | end 39 | 40 | /*--------------------------------------------------------- 41 | Name: gamemode:IsValidSpectatorTarget( Player pl, Entity ent ) 42 | Desc: Checks to make sure a spectated entity is valid. 43 | By default, you can change GM.CanOnlySpectate own team if you want to 44 | prevent players from spectating the other team. 45 | ---------------------------------------------------------*/ 46 | function GM:IsValidSpectatorTarget( pl, ent ) 47 | 48 | if ( !IsValid( ent ) ) then return false end 49 | if ( ent == pl ) then return false end 50 | if ( !table.HasValue( GAMEMODE:GetValidSpectatorEntityNames( pl ), ent:GetClass() ) ) then return false end 51 | if ( ent:IsPlayer() && !ent:Alive() ) then return false end 52 | if ( ent:IsPlayer() && ent:IsObserver() ) then return false end 53 | if ( pl:Team() != TEAM_SPECTATOR && ent:IsPlayer() && GAMEMODE.CanOnlySpectateOwnTeam && pl:Team() != ent:Team() ) then return false end 54 | 55 | return true 56 | 57 | end 58 | 59 | /*--------------------------------------------------------- 60 | Name: gamemode:GetSpectatorTargets( Player pl ) 61 | Desc: Returns a table of entities the player can spectate. 62 | ---------------------------------------------------------*/ 63 | function GM:GetSpectatorTargets( pl ) 64 | 65 | local t = {} 66 | for k, v in pairs( GAMEMODE:GetValidSpectatorEntityNames( pl ) ) do 67 | t = table.Merge( t, ents.FindByClass( v ) ) 68 | end 69 | 70 | return t 71 | 72 | end 73 | 74 | /*--------------------------------------------------------- 75 | Name: gamemode:FindRandomSpectatorTarget( Player pl ) 76 | Desc: Finds a random player/ent we can spectate. 77 | This is called when a player is first put in spectate. 78 | ---------------------------------------------------------*/ 79 | function GM:FindRandomSpectatorTarget( pl ) 80 | 81 | local Targets = GAMEMODE:GetSpectatorTargets( pl ) 82 | return table.Random( Targets ) 83 | 84 | end 85 | 86 | /*--------------------------------------------------------- 87 | Name: gamemode:FindNextSpectatorTarget( Player pl, Entity ent ) 88 | Desc: Finds the next entity we can spectate. 89 | ent param is the current entity we are viewing. 90 | ---------------------------------------------------------*/ 91 | function GM:FindNextSpectatorTarget( pl, ent ) 92 | 93 | local Targets = GAMEMODE:GetSpectatorTargets( pl ) 94 | return table.FindNext( Targets, ent ) 95 | 96 | end 97 | 98 | /*--------------------------------------------------------- 99 | Name: gamemode:FindPrevSpectatorTarget( Player pl, Entity ent ) 100 | Desc: Finds the previous entity we can spectate. 101 | ent param is the current entity we are viewing. 102 | ---------------------------------------------------------*/ 103 | function GM:FindPrevSpectatorTarget( pl, ent ) 104 | 105 | local Targets = GAMEMODE:GetSpectatorTargets( pl ) 106 | return table.FindPrev( Targets, ent ) 107 | 108 | end 109 | 110 | /*--------------------------------------------------------- 111 | Name: gamemode:StartEntitySpectate( Player pl ) 112 | Desc: Called when we start spectating. 113 | ---------------------------------------------------------*/ 114 | function GM:StartEntitySpectate( pl ) 115 | 116 | local CurrentSpectateEntity = pl:GetObserverTarget() 117 | 118 | for i=1, 32 do 119 | 120 | if ( GAMEMODE:IsValidSpectatorTarget( pl, CurrentSpectateEntity ) ) then 121 | pl:SpectateEntity( CurrentSpectateEntity ) 122 | return 123 | end 124 | 125 | CurrentSpectateEntity = GAMEMODE:FindRandomSpectatorTarget( pl ) 126 | 127 | end 128 | 129 | end 130 | 131 | /*--------------------------------------------------------- 132 | Name: gamemode:NextEntitySpectate( Player pl ) 133 | Desc: Called when we want to spec the next entity. 134 | ---------------------------------------------------------*/ 135 | function GM:NextEntitySpectate( pl ) 136 | 137 | local Target = pl:GetObserverTarget() 138 | 139 | for i=1, 32 do 140 | 141 | Target = GAMEMODE:FindNextSpectatorTarget( pl, Target ) 142 | 143 | if ( GAMEMODE:IsValidSpectatorTarget( pl, Target ) ) then 144 | pl:SpectateEntity( Target ) 145 | return 146 | end 147 | 148 | end 149 | 150 | end 151 | 152 | /*--------------------------------------------------------- 153 | Name: gamemode:PrevEntitySpectate( Player pl ) 154 | Desc: Called when we want to spec the previous entity. 155 | ---------------------------------------------------------*/ 156 | function GM:PrevEntitySpectate( pl ) 157 | 158 | local Target = pl:GetObserverTarget() 159 | 160 | for i=1, 32 do 161 | 162 | Target = GAMEMODE:FindPrevSpectatorTarget( pl, Target ) 163 | 164 | if ( GAMEMODE:IsValidSpectatorTarget( pl, Target ) ) then 165 | pl:SpectateEntity( Target ) 166 | return 167 | end 168 | 169 | end 170 | 171 | end 172 | 173 | /*--------------------------------------------------------- 174 | Name: gamemode:ChangeObserverMode( Player pl, Number mode ) 175 | Desc: Change the observer mode of a player. 176 | ---------------------------------------------------------*/ 177 | function GM:ChangeObserverMode( pl, mode ) 178 | 179 | if ( pl:GetInfoNum( "cl_spec_mode", 0) != mode ) then 180 | pl:ConCommand( "cl_spec_mode "..mode ) 181 | end 182 | 183 | if ( mode == OBS_MODE_IN_EYE || mode == OBS_MODE_CHASE ) then 184 | GAMEMODE:StartEntitySpectate( pl, mode ) 185 | end 186 | 187 | pl:SpectateEntity( NULL ) 188 | pl:Spectate( mode ) 189 | 190 | end 191 | 192 | /*--------------------------------------------------------- 193 | Name: gamemode:BecomeObserver( Player pl ) 194 | Desc: Called when we first become a spectator. 195 | ---------------------------------------------------------*/ 196 | function GM:BecomeObserver( pl ) 197 | 198 | local mode = pl:GetInfoNum( "cl_spec_mode", OBS_MODE_CHASE ) 199 | 200 | if ( !table.HasValue( GAMEMODE:GetValidSpectatorModes( pl ), mode ) ) then 201 | mode = table.FindNext( GAMEMODE:GetValidSpectatorModes( pl ), mode ) 202 | end 203 | 204 | GAMEMODE:ChangeObserverMode( pl, mode ) 205 | 206 | end 207 | 208 | local function spec_mode( pl, cmd, args ) 209 | 210 | if ( !GAMEMODE:IsValidSpectator( pl ) ) then return end 211 | 212 | local mode = pl:GetObserverMode() 213 | local nextmode = table.FindNext( GAMEMODE:GetValidSpectatorModes( pl ), mode ) 214 | 215 | GAMEMODE:ChangeObserverMode( pl, nextmode ) 216 | 217 | end 218 | 219 | concommand.Add( "spec_mode", spec_mode ) 220 | 221 | local function spec_next( pl, cmd, args ) 222 | 223 | if ( !GAMEMODE:IsValidSpectator( pl ) ) then return end 224 | if ( !table.HasValue( GAMEMODE:GetValidSpectatorModes( pl ), pl:GetObserverMode() ) ) then return end 225 | 226 | GAMEMODE:NextEntitySpectate( pl ) 227 | 228 | end 229 | 230 | concommand.Add( "spec_next", spec_next ) 231 | 232 | local function spec_prev( pl, cmd, args ) 233 | 234 | if ( !GAMEMODE:IsValidSpectator( pl ) ) then return end 235 | if ( !table.HasValue( GAMEMODE:GetValidSpectatorModes( pl ), pl:GetObserverMode() ) ) then return end 236 | 237 | GAMEMODE:PrevEntitySpectate( pl ) 238 | 239 | end 240 | 241 | concommand.Add( "spec_prev", spec_prev ) -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/round_controller.lua: -------------------------------------------------------------------------------- 1 | 2 | function GM:SetRoundWinner( ply, resulttext ) SetGlobalEntity( "RoundWinner", ply ) SetGlobalString( "RRText", tostring(resulttext) ) end 3 | function GM:SetRoundResult( i, resulttext ) SetGlobalInt( "RoundResult", i ) SetGlobalString( "RRText", tostring(resulttext) ) end 4 | function GM:ClearRoundResult() SetGlobalEntity( "RoundWinner", NULL ) SetGlobalInt( "RoundResult", 0 ) SetGlobalString( "RRText", "" ) end 5 | function GM:SetInRound( b ) SetGlobalBool( "InRound", b ) end 6 | function GM:InRound() return GetGlobalBool( "InRound", false ) end 7 | 8 | function GM:OnRoundStart( num ) 9 | 10 | UTIL_UnFreezeAllPlayers() 11 | 12 | end 13 | 14 | function GM:OnRoundEnd( num ) 15 | end 16 | 17 | function GM:OnRoundResult( result, resulttext ) 18 | 19 | // The fact that result might not be a team 20 | // shouldn't matter when calling this.. 21 | team.AddScore( result, 1 ) 22 | 23 | end 24 | 25 | function GM:OnRoundWinner( ply, resulttext ) 26 | 27 | // Do whatever you want to do with the winner here (this is only called in Free For All gamemodes)... 28 | ply:AddFrags( 1 ) 29 | 30 | end 31 | 32 | function GM:OnPreRoundStart( num ) 33 | 34 | game.CleanUpMap() 35 | 36 | UTIL_StripAllPlayers() 37 | UTIL_SpawnAllPlayers() 38 | UTIL_FreezeAllPlayers() 39 | 40 | end 41 | 42 | function GM:CanStartRound( iNum ) 43 | return true 44 | end 45 | 46 | function GM:StartRoundBasedGame() 47 | 48 | GAMEMODE:PreRoundStart( 1 ) 49 | 50 | end 51 | 52 | // Number of rounds 53 | function GM:GetRoundLimit() 54 | return GAMEMODE.RoundLimit; 55 | end 56 | 57 | // Has the round limit been reached? 58 | function GM:HasReachedRoundLimit( iNum ) 59 | 60 | local iRoundLimit = GAMEMODE:GetRoundLimit(); 61 | 62 | if( iRoundLimit > 0 && iNum > iRoundLimit ) then 63 | return true 64 | end 65 | 66 | return false 67 | 68 | end 69 | 70 | // This is for the timer-based game end. set this to return true if you want it to end mid-round 71 | function GM:CanEndRoundBasedGame() 72 | return false 73 | end 74 | 75 | // You can add round time by calling this (takes time in seconds) 76 | function GM:AddRoundTime( fAddedTime ) 77 | 78 | if( !GAMEMODE:InRound() ) then // don't add time if round is not in progress 79 | return 80 | end 81 | 82 | SetGlobalFloat( "RoundEndTime", GetGlobalFloat( "RoundEndTime", CurTime() ) + fAddedTime ); 83 | timer.Adjust( "RoundEndTimer", GetGlobalFloat( "RoundEndTime" ) - GetGlobalFloat( "RoundStartTime" ), 0, function() GAMEMODE:RoundTimerEnd() end ); 84 | 85 | net.Start( "RoundAddedTime" ) 86 | net.WriteFloat( fAddedTime ) 87 | net.Broadcast() 88 | 89 | end 90 | 91 | // This gets the timer for a round (you can make round number dependant round lengths, or make it cvar controlled) 92 | function GM:GetRoundTime( iRoundNumber ) 93 | return GAMEMODE.RoundLength; 94 | end 95 | 96 | // 97 | // Internal, override OnPreRoundStart if you want to do stuff here 98 | // 99 | function GM:PreRoundStart( iNum ) 100 | 101 | // Should the game end? 102 | if( CurTime() >= GAMEMODE.GetTimeLimit() || GAMEMODE:HasReachedRoundLimit( iNum ) ) then 103 | GAMEMODE:EndOfGame( true ); 104 | return; 105 | end 106 | 107 | if ( !GAMEMODE:CanStartRound( iNum ) ) then 108 | 109 | timer.Simple( 1, function() GAMEMODE:PreRoundStart( iNum ) end ) // In a second, check to see if we can start 110 | return; 111 | 112 | end 113 | 114 | timer.Simple( GAMEMODE.RoundPreStartTime, function() GAMEMODE:RoundStart() end ) 115 | SetGlobalInt( "RoundNumber", iNum ) 116 | SetGlobalFloat( "RoundStartTime", CurTime() + GAMEMODE.RoundPreStartTime ) 117 | 118 | GAMEMODE:ClearRoundResult() 119 | GAMEMODE:OnPreRoundStart( GetGlobalInt( "RoundNumber" ) ) 120 | GAMEMODE:SetInRound( true ) 121 | 122 | end 123 | 124 | // 125 | // Internal, override OnRoundStart if you want to do stuff here 126 | // 127 | function GM:RoundStart() 128 | 129 | local roundNum = GetGlobalInt( "RoundNumber" ); 130 | local roundDuration = GAMEMODE:GetRoundTime( roundNum ) 131 | 132 | GAMEMODE:OnRoundStart( roundNum ) 133 | 134 | timer.Create( "RoundEndTimer", roundDuration, 0, function() GAMEMODE:RoundTimerEnd() end ) 135 | timer.Create( "CheckRoundEnd", 1, 0, function() GAMEMODE:CheckRoundEnd() end ) 136 | 137 | SetGlobalFloat( "RoundEndTime", CurTime() + roundDuration ); 138 | 139 | end 140 | 141 | // 142 | // Decide what text should show when a team/player wins 143 | // 144 | function GM:ProcessResultText( result, resulttext ) 145 | 146 | if ( resulttext == nil ) then resulttext = "" end 147 | 148 | //the result could either be a number or a player! 149 | // for a free for all you could do... if type(result) == "Player" and IsValid( result ) then return result:Name().." is the winner" or whatever 150 | 151 | return resulttext 152 | 153 | end 154 | 155 | // 156 | // Round Ended with Result 157 | // 158 | function GM:RoundEndWithResult( result, resulttext ) 159 | 160 | resulttext = GAMEMODE:ProcessResultText( result, resulttext ) 161 | 162 | if type( result ) == "number" then // the result is a team ID 163 | 164 | GAMEMODE:SetRoundResult( result, resulttext ) 165 | GAMEMODE:RoundEnd() 166 | GAMEMODE:OnRoundResult( result, resulttext ) 167 | 168 | else // the result is a player 169 | 170 | GAMEMODE:SetRoundWinner( result, resulttext ) 171 | GAMEMODE:RoundEnd() 172 | GAMEMODE:OnRoundWinner( result, resulttext ) 173 | 174 | end 175 | 176 | end 177 | 178 | // 179 | // Internal, override OnRoundEnd if you want to do stuff here 180 | // 181 | function GM:RoundEnd() 182 | 183 | if ( !GAMEMODE:InRound() ) then 184 | // if someone uses RoundEnd incorrectly then do a trace. 185 | MsgN("WARNING: RoundEnd being called while gamemode not in round...") 186 | debug.Trace() 187 | return 188 | end 189 | 190 | GAMEMODE:OnRoundEnd( GetGlobalInt( "RoundNumber" ) ) 191 | 192 | self:SetInRound( false ) 193 | 194 | timer.Destroy( "RoundEndTimer" ) 195 | timer.Destroy( "CheckRoundEnd" ) 196 | SetGlobalFloat( "RoundEndTime", -1 ) 197 | 198 | timer.Simple( GAMEMODE.RoundPostLength, function() GAMEMODE:PreRoundStart( GetGlobalInt( "RoundNumber" )+1 ) end ) 199 | 200 | end 201 | 202 | function GM:GetTeamAliveCounts() 203 | 204 | local TeamCounter = {} 205 | 206 | for k,v in pairs( player.GetAll() ) do 207 | if ( v:Alive() && v:Team() > 0 && v:Team() < 1000 ) then 208 | TeamCounter[ v:Team() ] = TeamCounter[ v:Team() ] or 0 209 | TeamCounter[ v:Team() ] = TeamCounter[ v:Team() ] + 1 210 | end 211 | end 212 | 213 | return TeamCounter 214 | 215 | end 216 | 217 | // 218 | // For round based games that end when a team is dead 219 | // 220 | function GM:CheckPlayerDeathRoundEnd() 221 | 222 | if ( !GAMEMODE.RoundBased ) then return end 223 | if ( !GAMEMODE:InRound() ) then return end 224 | 225 | if ( GAMEMODE.RoundEndsWhenOneTeamAlive ) then 226 | 227 | local Teams = GAMEMODE:GetTeamAliveCounts() 228 | 229 | if ( table.Count( Teams ) == 0 ) then 230 | 231 | GAMEMODE:RoundEndWithResult( 1001, "Draw, everyone loses!" ) 232 | return 233 | 234 | end 235 | 236 | if ( table.Count( Teams ) == 1 ) then 237 | 238 | local TeamID = table.GetFirstKey( Teams ) 239 | GAMEMODE:RoundEndWithResult( TeamID ) 240 | return 241 | 242 | end 243 | 244 | end 245 | 246 | 247 | end 248 | 249 | hook.Add( "PlayerDisconnected", "RoundCheck_PlayerDisconnect", function() timer.Simple( 0.2, function() GAMEMODE:CheckPlayerDeathRoundEnd() end ) end ) 250 | hook.Add( "PostPlayerDeath", "RoundCheck_PostPlayerDeath", function() timer.Simple( 0.2, function() GAMEMODE:CheckPlayerDeathRoundEnd() end ) end ) 251 | 252 | // 253 | // You should use this to check any round end conditions 254 | // 255 | function GM:CheckRoundEnd() 256 | 257 | // Do checks.. 258 | 259 | // if something then call GAMEMODE:RoundEndWithResult( TEAM_BLUE, "Team Blue Ate All The Mushrooms!" ) 260 | // OR for a free for all you could do something like... GAMEMODE:RoundEndWithResult( SomePlayer ) 261 | 262 | end 263 | 264 | function GM:CheckRoundEndInternal() 265 | 266 | if ( !GAMEMODE:InRound() ) then return end 267 | 268 | GAMEMODE:CheckRoundEnd() 269 | 270 | timer.Create( "CheckRoundEnd", 1, 0, function() GAMEMODE:CheckRoundEndInternal() end ) 271 | 272 | end 273 | 274 | // 275 | // This is called when the round time ends. 276 | // 277 | function GM:RoundTimerEnd() 278 | 279 | if ( !GAMEMODE:InRound() ) then return end 280 | 281 | if ( !GAMEMODE.TeamBased ) then 282 | 283 | local ply = GAMEMODE:SelectCurrentlyWinningPlayer() 284 | 285 | if ply then 286 | GAMEMODE:RoundEndWithResult( ply, "Time Up" ) 287 | else 288 | GAMEMODE:RoundEndWithResult( -1, "Time Up" ) 289 | end 290 | 291 | else 292 | 293 | GAMEMODE:RoundEndWithResult( -1, "Time Up" ) 294 | 295 | end 296 | 297 | end 298 | 299 | // 300 | // This is called when time runs out and there is no winner chosen yet (free for all gamemodes only) 301 | // By default it chooses the player with the most frags but you can edit this to do what you need.. 302 | // 303 | function GM:SelectCurrentlyWinningPlayer() 304 | 305 | local winner 306 | local topscore = 0 307 | 308 | for k,v in pairs( player.GetAll() ) do 309 | 310 | if v:Frags() > topscore and v:Team() != TEAM_CONNECTING and v:Team() != TEAM_UNASSIGNED and v:Team() != TEAM_SPECTATOR then 311 | 312 | winner = v 313 | topscore = v:Frags() 314 | 315 | end 316 | 317 | end 318 | 319 | return winner 320 | 321 | end 322 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/cl_selectscreen.lua: -------------------------------------------------------------------------------- 1 | 2 | local CENTER_HEIGHT = 250 3 | local PANEL = {} 4 | 5 | /*--------------------------------------------------------- 6 | Init 7 | ---------------------------------------------------------*/ 8 | function PANEL:Init() 9 | 10 | self:SetText( "" ) 11 | self.Buttons = {} 12 | self.BottomButtons = {} 13 | self:SetSkin( GAMEMODE.HudSkin ) 14 | 15 | self.pnlButtons = vgui.Create( "DPanelList", self ) 16 | self.pnlButtons:SetPadding( 10 ) 17 | self.pnlButtons:SetSpacing( 10 ) 18 | self.pnlButtons:SetDrawBackground( false ) 19 | self.pnlButtons:EnableVerticalScrollbar() 20 | 21 | self.lblMain = vgui.Create( "DLabel", self ) 22 | self.lblMain:SetText( GAMEMODE.Name ) 23 | self.lblMain:SetFont( "FRETTA_HUGE" ) 24 | self.lblMain:SetColor( color_white ) 25 | 26 | self.pnlMain = vgui.Create( "DPanelList", self ) 27 | self.pnlMain:SetNoSizing( true ) 28 | self.pnlMain:SetDrawBackground( false ) 29 | self.pnlMain:EnableVerticalScrollbar() 30 | 31 | self.btnCancel = vgui.Create( "DButton", self ) 32 | self.btnCancel:SetText( "#Close" ) 33 | self.btnCancel:SetSize( 100, 30 ) 34 | self.btnCancel:SetFGColor( Color( 0, 0, 0, 200 ) ) 35 | self.btnCancel:SetFont( "FRETTA_SMALL" ) 36 | self.btnCancel.DoClick = function() self:Remove() end 37 | self.btnCancel:SetVisible( false ) 38 | 39 | Derma_Hook( self.btnCancel, "Paint", "Paint", "CancelButton" ) 40 | Derma_Hook( self.btnCancel, "PaintOver", "PaintOver", "CancelButton" ) 41 | Derma_Hook( self.btnCancel, "ApplySchemeSettings", "Scheme", "CancelButton" ) 42 | Derma_Hook( self.btnCancel, "PerformLayout", "Layout", "CancelButton" ) 43 | 44 | self.lblHoverText = vgui.Create( "DLabel", self ) 45 | self.lblHoverText:SetText( "" ) 46 | self.lblHoverText:SetFont( "FRETTA_MEDIUM" ) 47 | self.lblHoverText:SetColor( color_white ) 48 | self.lblHoverText:SetContentAlignment( 8 ) 49 | self.lblHoverText:SetWrap( true ) 50 | 51 | self.lblFooterText = vgui.Create( "DLabel", self ) 52 | self.lblFooterText:SetText( "" ) 53 | self.lblFooterText:SetFont( "FRETTA_MEDIUM" ) 54 | self.lblFooterText:SetColor( color_white ) 55 | self.lblFooterText:SetContentAlignment( 8 ) 56 | self.lblFooterText:SetWrap( false ) 57 | 58 | self.pnlMain:AddItem( self.lblHoverText ) 59 | 60 | self:PerformLayout() 61 | 62 | self.OpenTime = SysTime() 63 | 64 | end 65 | 66 | function PANEL:NoFadeIn() 67 | self.OpenTime = 0 68 | end 69 | 70 | /*--------------------------------------------------------- 71 | AddPanelButton 72 | ---------------------------------------------------------*/ 73 | function PANEL:AddPanelButton( icon, title, pnlfnc ) 74 | 75 | local btn = vgui.Create( "DImageButton", self ) 76 | btn:SetImage( icon ) 77 | btn:SetTooltip( title ) 78 | btn:SetSize( 30, 30 ) 79 | btn:SetVisible( true ) 80 | btn.pPanelFnc = pnlfnc 81 | btn.pPanel = nil 82 | btn:SetStretchToFit( false ) 83 | 84 | Derma_Hook( btn, "Paint", "Paint", "PanelButton" ) 85 | Derma_Hook( btn, "PaintOver", "PaintOver", "PanelButton" ) 86 | //Derma_Hook( btn, "ApplySchemeSettings", "Scheme", "PanelButton" ) 87 | //Derma_Hook( btn, "PerformLayout", "Layout", "PanelButton" ) 88 | 89 | local fnClick = function() 90 | 91 | if ( !btn.pPanel ) then 92 | btn.pPanel = btn.pPanelFnc() 93 | btn.pPanel:SetParent( self.pnlMain ) 94 | btn.pPanel:SetVisible( false ) 95 | btn.pPanelFnc = nil 96 | end 97 | 98 | // Toggle off 99 | if ( btn.m_bSelected ) then self:ClearSelectedPanel() return end 100 | 101 | self:ClearSelectedPanel() 102 | 103 | btn.m_bSelected = true 104 | 105 | self.pnlMain:Clear() 106 | btn.pPanel:SetVisible( true ) 107 | self.pnlMain:AddItem( btn.pPanel ) 108 | 109 | end 110 | btn.DoClick = fnClick 111 | 112 | table.insert( self.BottomButtons, btn ) 113 | 114 | return btn 115 | 116 | end 117 | 118 | function PANEL:ClearSelectedPanel() 119 | 120 | self.pnlMain:Clear() 121 | self.pnlMain:AddItem( self.lblHoverText ) 122 | 123 | for k, btn in pairs( self.BottomButtons ) do 124 | 125 | btn.m_bSelected = false 126 | if ( IsValid( btn.pPanel ) ) then 127 | btn.pPanel:SetVisible( false ) 128 | end 129 | 130 | end 131 | 132 | end 133 | 134 | /*--------------------------------------------------------- 135 | SetHeaderText 136 | ---------------------------------------------------------*/ 137 | function PANEL:SetHeaderText( strName ) 138 | 139 | self.lblMain:SetText( strName ) 140 | 141 | end 142 | 143 | /*--------------------------------------------------------- 144 | SetHeaderText 145 | ---------------------------------------------------------*/ 146 | function PANEL:SetHoverText( strName ) 147 | 148 | self.lblHoverText:SetText( strName or "" ) 149 | 150 | end 151 | 152 | /*--------------------------------------------------------- 153 | SetHeaderText 154 | ---------------------------------------------------------*/ 155 | function PANEL:GetHoverText( strName ) 156 | 157 | return self.lblHoverText:GetValue() 158 | 159 | end 160 | 161 | /*--------------------------------------------------------- 162 | AddSelectButton 163 | ---------------------------------------------------------*/ 164 | function PANEL:AddSelectButton( strName, fnFunction, txt ) 165 | 166 | local btn = vgui.Create( "DButton", self.pnlButtons ) 167 | btn:SetText( strName ) 168 | btn:SetSize( 200, 30 ) 169 | btn.DoClick = function() fnFunction() surface.PlaySound( Sound("buttons/lightswitch2.wav") ) self:Remove() end 170 | 171 | Derma_Hook( btn, "Paint", "Paint", "SelectButton" ) 172 | Derma_Hook( btn, "PaintOver", "PaintOver", "SelectButton" ) 173 | Derma_Hook( btn, "ApplySchemeSettings", "Scheme", "SelectButton" ) 174 | Derma_Hook( btn, "PerformLayout", "Layout", "SelectButton" ) 175 | 176 | if ( txt ) then 177 | btn.OnCursorEntered = function() self.OldHoverText = self:GetHoverText() self:SetHoverText( txt ) end 178 | btn.OnCursorExited = function() self:SetHoverText( self.OldHoverText ) self.OldHoverText = nil end 179 | end 180 | 181 | self.pnlButtons:AddItem( btn ) 182 | 183 | table.insert( self.Buttons, btn ) 184 | return btn 185 | 186 | end 187 | 188 | /*--------------------------------------------------------- 189 | SetHeaderText 190 | ---------------------------------------------------------*/ 191 | function PANEL:AddSpacer( h ) 192 | 193 | local btn = vgui.Create( "Panel", self ) 194 | btn:SetSize( 200, h ) 195 | table.insert( self.Buttons, btn ) 196 | return btn 197 | 198 | end 199 | 200 | /*--------------------------------------------------------- 201 | SetHeaderText 202 | ---------------------------------------------------------*/ 203 | function PANEL:AddCancelButton() 204 | 205 | self.btnCancel:SetVisible( true ) 206 | 207 | end 208 | 209 | /*--------------------------------------------------------- 210 | PerformLayout 211 | ---------------------------------------------------------*/ 212 | function PANEL:PerformLayout() 213 | 214 | self:SetSize( ScrW(), ScrH() ) 215 | 216 | local CenterY = ScrH() / 2.0 217 | local CenterX = ScrW() / 2.0 218 | local InnerWidth = 640 219 | 220 | self.lblMain:SizeToContents() 221 | self.lblMain:SetPos( ScrW() * 0.5 - self.lblMain:GetWide() * 0.5, CenterY - CENTER_HEIGHT - self.lblMain:GetTall() * 1.2 ) 222 | 223 | self.pnlButtons:SetPos( ScrW() * 0.5 - InnerWidth * 0.5, (CenterY - CENTER_HEIGHT) + 20 ) 224 | self.pnlButtons:SetSize( 210, (CENTER_HEIGHT * 2) - self.btnCancel:GetTall() - 20 - 20 - 20 ) 225 | 226 | self.btnCancel:SetPos( ScrW() * 0.5 + InnerWidth * 0.5 - self.btnCancel:GetWide(), CenterY + CENTER_HEIGHT - self.btnCancel:GetTall() - 20 ) 227 | 228 | self.lblHoverText:SetPos( ScrW() * 0.5 - InnerWidth * 0.5 + 50, (CenterY - 150) ) 229 | self.lblHoverText:SetSize( 300, 300 ) 230 | 231 | self.pnlMain:SetPos( self.pnlButtons.x + self.pnlButtons:GetWide() + 10, self.pnlButtons.y ) 232 | self.pnlMain:SetSize( InnerWidth - self.pnlButtons:GetWide() - 10, 400 ) 233 | 234 | self.lblFooterText:SetSize( ScrW(), 30 ) 235 | self.lblFooterText:SetPos( 0, CenterY + CENTER_HEIGHT + 10 ) 236 | 237 | local x = self.pnlButtons.x 238 | for k, btn in pairs( self.BottomButtons ) do 239 | 240 | btn:SetPos( x, CenterY + CENTER_HEIGHT - btn:GetTall() - 20 ) 241 | x = x + btn:GetWide() + 8 242 | 243 | end 244 | 245 | end 246 | 247 | /*--------------------------------------------------------- 248 | Paint 249 | ---------------------------------------------------------*/ 250 | function PANEL:Paint() 251 | 252 | Derma_DrawBackgroundBlur( self, self.OpenTime ) 253 | 254 | local CenterY = ScrH() / 2.0 255 | local CenterX = ScrW() / 2.0 256 | 257 | surface.SetDrawColor( 0, 0, 0, 200 ); 258 | surface.DrawRect( 0, CenterY - CENTER_HEIGHT, ScrW(), CENTER_HEIGHT * 2 ); 259 | surface.DrawRect( 0, CenterY - CENTER_HEIGHT - 4, ScrW(), 2 ); 260 | surface.DrawRect( 0, CenterY + CENTER_HEIGHT + 2, ScrW(), 2 ); 261 | 262 | GAMEMODE:PaintSplashScreen( self:GetWide(), self:GetTall() ) 263 | 264 | end 265 | 266 | vgui_Splash = vgui.RegisterTable( PANEL, "DPanel" ) 267 | local TeamPanel = nil 268 | 269 | function GM:ShowTeam() 270 | 271 | if ( !IsValid( TeamPanel ) ) then 272 | 273 | TeamPanel = vgui.CreateFromTable( vgui_Splash ) 274 | TeamPanel:SetHeaderText( "Choose Team" ) 275 | 276 | local AllTeams = team.GetAllTeams() 277 | for ID, TeamInfo in SortedPairs ( AllTeams ) do 278 | 279 | if ( ID != TEAM_CONNECTING && ID != TEAM_UNASSIGNED && ( ID != TEAM_SPECTATOR || GAMEMODE.AllowSpectating ) && team.Joinable(ID) ) then 280 | 281 | if ( ID == TEAM_SPECTATOR ) then 282 | TeamPanel:AddSpacer( 10 ) 283 | end 284 | 285 | local strName = TeamInfo.Name 286 | local func = function() RunConsoleCommand( "changeteam", ID ) end 287 | 288 | local btn = TeamPanel:AddSelectButton( strName, func ) 289 | btn.m_colBackground = TeamInfo.Color 290 | btn.Think = function( self ) 291 | self:SetText( Format( "%s (%i)", strName, team.NumPlayers( ID ) )) 292 | self:SetDisabled( GAMEMODE:TeamHasEnoughPlayers( ID ) ) 293 | end 294 | 295 | if ( IsValid( LocalPlayer() ) && LocalPlayer():Team() == ID ) then 296 | btn:SetDisabled( true ) 297 | end 298 | 299 | end 300 | 301 | end 302 | 303 | TeamPanel:AddCancelButton() 304 | 305 | end 306 | 307 | TeamPanel:MakePopup() 308 | 309 | end 310 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/sv_gmchanger.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | sv_gmchanger.lua - Gamemode Changer (server side) 3 | ----------------------------------------------------- 4 | Most of the internal stuff for the votes is here and contains stuff you really don't 5 | want to override. 6 | ]] 7 | 8 | local g_PlayableGamemodes = {} 9 | 10 | fretta_votesneeded = CreateConVar( "fretta_votesneeded", "0.75", { FCVAR_ARCHIVE } ) 11 | fretta_votetime = CreateConVar( "fretta_votetime", "20", { FCVAR_ARCHIVE } ) 12 | fretta_votegraceperiod = CreateConVar( "fretta_votegraceperiod", "30", { FCVAR_ARCHIVE } ) 13 | 14 | 15 | local function SendAvailableGamemodes( ply ) 16 | 17 | net.Start("PlayableGamemodes") 18 | net.WriteTable(g_PlayableGamemodes) 19 | net.Send(ply) 20 | 21 | end 22 | 23 | function GetRandomGamemodeName() 24 | local choose = table.Random( g_PlayableGamemodes ) 25 | if choose then return choose.key end 26 | 27 | return GAMEMODE.FolderName 28 | end 29 | 30 | function GetRandomGamemodeMap( gm ) 31 | local gmtab = g_PlayableGamemodes[ gm or GAMEMODE.FolderName ] 32 | if gmtab then 33 | return table.Random( gmtab.maps ) 34 | end 35 | 36 | return game.GetMap() 37 | end 38 | 39 | function GetNumberOfGamemodeMaps( gm ) 40 | local gmtab = g_PlayableGamemodes[ gm or GAMEMODE.FolderName ] 41 | if gmtab then 42 | return table.Count( gmtab.maps ) 43 | end 44 | 45 | return 0 46 | end 47 | 48 | hook.Add( "PlayerInitialSpawn", "SendAvailableGamemodes", SendAvailableGamemodes ) 49 | 50 | 51 | local AllMaps = file.Find( "maps/*.bsp", "GAME" ) 52 | for key, map in pairs( AllMaps ) do 53 | AllMaps[ key ] = string.gsub( map, ".bsp", "" ) 54 | end 55 | 56 | local GameModes = engine.GetGamemodes() 57 | 58 | for _, gm in pairs( engine.GetGamemodes() ) do 59 | 60 | local info = file.Read( "gamemodes/"..gm.name.."/"..gm.name..".txt", "GAME" ) 61 | if ( info ) then 62 | 63 | local info = util.KeyValuesToTable( info ) 64 | 65 | if ( info.selectable == 1 ) then 66 | 67 | g_PlayableGamemodes[ gm.name ] = {} 68 | g_PlayableGamemodes[ gm.name ].key = gm.name 69 | g_PlayableGamemodes[ gm.name ].name = gm.title 70 | g_PlayableGamemodes[ gm.name ].label = info.title 71 | g_PlayableGamemodes[ gm.name ].description = info.description 72 | g_PlayableGamemodes[ gm.name ].author = info.author_name 73 | g_PlayableGamemodes[ gm.name ].authorurl = info.author_url 74 | 75 | g_PlayableGamemodes[ gm.name ].maps = {} 76 | 77 | if ( info.fretta_maps ) then 78 | for _, mapname in pairs( AllMaps ) do 79 | mapname = string.lower(mapname) 80 | for _, p in pairs( info.fretta_maps ) do 81 | if ( string.sub( mapname, 1, #p ) == p ) then 82 | table.insert( g_PlayableGamemodes[ gm.name ].maps, mapname ) 83 | end 84 | end 85 | end 86 | else 87 | g_PlayableGamemodes[ gm.name ].maps = AllMaps 88 | end 89 | 90 | if ( info.fretta_maps_disallow ) then 91 | for key, mapname in pairs( g_PlayableGamemodes[ gm.name ].maps ) do 92 | mapname = string.lower(mapname) 93 | for _, p in pairs( info.fretta_maps_disallow ) do 94 | if ( string.sub( mapname, 1, #p ) == p ) then 95 | g_PlayableGamemodes[ gm.name ].maps[ key ] = nil 96 | end 97 | end 98 | end 99 | end 100 | 101 | end 102 | 103 | end 104 | 105 | end 106 | 107 | GameModes = nil 108 | 109 | function GM:IsValidGamemode( gamemode, map ) 110 | 111 | if ( g_PlayableGamemodes[ gamemode ] == nil ) then return false end 112 | 113 | if ( map == nil ) then return true end 114 | 115 | for _, mapname in pairs( g_PlayableGamemodes[ gamemode ].maps ) do 116 | if ( mapname == map ) then return true end 117 | end 118 | 119 | return false 120 | 121 | end 122 | 123 | local gVotes = {} 124 | 125 | function GM:VotePlayGamemode( ply, gamemode ) 126 | 127 | if ( !gamemode ) then return end 128 | if ( GAMEMODE.WinningGamemode ) then return end 129 | if ( !GAMEMODE:InGamemodeVote() ) then return end 130 | if ( !GAMEMODE:IsValidGamemode( gamemode ) ) then return end 131 | 132 | ply:SetNWString( "Wants", gamemode ) 133 | 134 | end 135 | 136 | concommand.Add( "votegamemode", function( pl, cmd, args ) GAMEMODE:VotePlayGamemode( pl, args[1] ) end ) 137 | 138 | function GM:VotePlayMap( ply, map ) 139 | 140 | if ( !map ) then return end 141 | if ( !GAMEMODE.WinningGamemode ) then return end 142 | if ( !GAMEMODE:InGamemodeVote() ) then return end 143 | if ( !GAMEMODE:IsValidGamemode( GAMEMODE.WinningGamemode, map ) ) then return end 144 | 145 | ply:SetNWString( "Wants", map ) 146 | 147 | end 148 | 149 | concommand.Add( "votemap", function( pl, cmd, args ) GAMEMODE:VotePlayMap( pl, args[1] ) end ) 150 | 151 | function GM:GetFractionOfPlayersThatWantChange() 152 | 153 | local Humans = player.GetHumans() 154 | local NumHumans = #Humans 155 | local WantsChange = 0 156 | 157 | for k, player in pairs( Humans ) do 158 | 159 | if ( player:GetNWBool( "WantsVote" ) ) then 160 | WantsChange = WantsChange + 1 161 | end 162 | 163 | -- Don't count players that aren't connected yet 164 | if ( !player:IsConnected() ) then 165 | NumHumans = NumHumans - 1 166 | end 167 | 168 | end 169 | 170 | local fraction = WantsChange / NumHumans 171 | 172 | return fraction, NumHumans, WantsChange 173 | 174 | end 175 | 176 | function GM:GetVotesNeededForChange() 177 | 178 | local Fraction, NumHumans, WantsChange = GAMEMODE:GetFractionOfPlayersThatWantChange() 179 | local FractionNeeded = fretta_votesneeded:GetFloat() 180 | 181 | local VotesNeeded = math.ceil( FractionNeeded * NumHumans ) 182 | 183 | return VotesNeeded - WantsChange 184 | 185 | end 186 | 187 | function GM:CountVotesForChange() 188 | 189 | if ( CurTime() >= GetConVarNumber( "fretta_votegraceperiod" ) ) then -- can't vote too early on 190 | 191 | if ( GAMEMODE:InGamemodeVote() ) then return end 192 | 193 | fraction = GAMEMODE:GetFractionOfPlayersThatWantChange() 194 | 195 | if ( fraction > fretta_votesneeded:GetFloat() ) then 196 | GAMEMODE:StartGamemodeVote() 197 | return false 198 | end 199 | 200 | end 201 | 202 | return true 203 | end 204 | 205 | function GM:VoteForChange( ply ) 206 | 207 | if ( GetConVarNumber( "fretta_voting" ) == 0 ) then return end 208 | if ( ply:GetNWBool( "WantsVote" ) ) then return end 209 | 210 | ply:SetNWBool( "WantsVote", true ) 211 | 212 | local VotesNeeded = GAMEMODE:GetVotesNeededForChange() 213 | local NeedTxt = "" 214 | if ( VotesNeeded > 0 ) then NeedTxt = ", Color( 80, 255, 50 ), [[ (need "..VotesNeeded.." more) ]] " end 215 | 216 | if ( CurTime() < GetConVarNumber( "fretta_votegraceperiod" ) ) then -- can't vote too early on 217 | local timediff = math.Round( GetConVarNumber( "fretta_votegraceperiod" ) - CurTime() ); 218 | BroadcastLua( "chat.AddText( Entity("..ply:EntIndex().."), Color( 255, 255, 255 ), [[ voted to change the gamemode]] )" ) 219 | else 220 | BroadcastLua( "chat.AddText( Entity("..ply:EntIndex().."), Color( 255, 255, 255 ), [[ voted to change the gamemode]] "..NeedTxt.." )" ) 221 | end 222 | 223 | Msg( ply:Nick() .. " voted to change the gamemode\n" ) 224 | 225 | timer.Simple( 5, function() GAMEMODE:CountVotesForChange() end ) 226 | 227 | end 228 | 229 | concommand.Add( "VoteForChange", function( pl, cmd, args ) GAMEMODE:VoteForChange( pl ) end ) 230 | timer.Create( "VoteForChangeThink", 10, 0, function() if ( GAMEMODE ) then GAMEMODE.CountVotesForChange( GAMEMODE ) end end ) 231 | 232 | 233 | function GM:ClearPlayerWants() 234 | 235 | for k, ply in pairs( player.GetAll() ) do 236 | ply:SetNWString( "Wants", "" ) 237 | end 238 | 239 | end 240 | 241 | 242 | function GM:StartGamemodeVote() 243 | 244 | if( !GAMEMODE.m_bVotingStarted ) then 245 | SetGlobalBool( "InGamemodeVote", true ) 246 | 247 | if ( fretta_voting:GetBool() ) then 248 | if table.Count( g_PlayableGamemodes ) >= 2 then 249 | GAMEMODE:ClearPlayerWants() 250 | BroadcastLua( "GAMEMODE:ShowGamemodeChooser()" ) 251 | timer.Simple( fretta_votetime:GetFloat(), function() GAMEMODE:FinishGamemodeVote() end ) 252 | SetGlobalFloat( "VoteEndTime", CurTime() + fretta_votetime:GetFloat() ) 253 | else 254 | GAMEMODE.WinningGamemode = GAMEMODE:WorkOutWinningGamemode() 255 | GAMEMODE:StartMapVote() 256 | end 257 | else 258 | GAMEMODE.WinningGamemode = GAMEMODE.FolderName 259 | GAMEMODE:StartMapVote() 260 | end 261 | 262 | GAMEMODE.m_bVotingStarted = true; 263 | end 264 | end 265 | 266 | function GM:StartMapVote() 267 | 268 | -- If there's only one map, let the 'random map' thing choose it 269 | if ( GetNumberOfGamemodeMaps( GAMEMODE.WinningGamemode ) == 1 ) then 270 | return GAMEMODE:FinishMapVote( true ) 271 | end 272 | 273 | BroadcastLua( "GAMEMODE:ShowMapChooserForGamemode( \""..GAMEMODE.WinningGamemode.."\" )" ); 274 | timer.Simple( fretta_votetime:GetFloat(), function() GAMEMODE:FinishMapVote() end ) 275 | SetGlobalFloat( "VoteEndTime", CurTime() + fretta_votetime:GetFloat() ) 276 | 277 | end 278 | 279 | function GM:GetWinningWant() 280 | 281 | local Votes = {} 282 | 283 | for k, ply in pairs( player.GetAll() ) do 284 | 285 | local want = ply:GetNWString( "Wants", nil ) 286 | if ( want && want != "" ) then 287 | Votes[ want ] = Votes[ want ] or 0 288 | Votes[ want ] = Votes[ want ] + 1 289 | end 290 | 291 | end 292 | 293 | return table.GetWinningKey( Votes ) 294 | 295 | end 296 | 297 | function GM:WorkOutWinningGamemode() 298 | 299 | if ( GAMEMODE.WinningGamemode ) then return GAMEMODE.WinningGamemode end 300 | 301 | -- Gamemode Voting disabled, return current gamemode 302 | if ( !fretta_voting:GetBool() ) then 303 | return GAMEMODE.FolderName 304 | end 305 | 306 | local winner = GAMEMODE:GetWinningWant() 307 | if ( !winner ) then return GetRandomGamemodeName() end 308 | 309 | return winner 310 | 311 | end 312 | 313 | function GM:GetWinningMap( WinningGamemode ) 314 | 315 | if ( GAMEMODE.WinningMap ) then return GAMEMODE.WinningMap end 316 | 317 | local winner = GAMEMODE:GetWinningWant() 318 | if ( !winner ) then return GetRandomGamemodeMap( GAMEMODE.WinningGamemode ) end 319 | 320 | return winner 321 | 322 | end 323 | 324 | function GM:FinishGamemodeVote() 325 | 326 | GAMEMODE.WinningGamemode = GAMEMODE:WorkOutWinningGamemode() 327 | GAMEMODE:ClearPlayerWants() 328 | 329 | -- Send bink bink notification 330 | BroadcastLua( "GAMEMODE:GamemodeWon( '"..GAMEMODE.WinningGamemode.."' )" ); 331 | 332 | -- Start map vote.. 333 | timer.Simple( 2, function() GAMEMODE:StartMapVote() end ) 334 | 335 | end 336 | 337 | function GM:FinishMapVote() 338 | 339 | GAMEMODE.WinningMap = GAMEMODE:GetWinningMap() 340 | GAMEMODE:ClearPlayerWants() 341 | 342 | if self.WinningMap then 343 | -- Send bink bink notification 344 | BroadcastLua( "GAMEMODE:ChangingGamemode( '"..GAMEMODE.WinningGamemode.."', '"..GAMEMODE.WinningMap.."' )" ); 345 | 346 | -- Start map vote? 347 | timer.Simple( 3, function() GAMEMODE:ChangeGamemode() end ) 348 | else 349 | -- Notifies the server owner of the issue 350 | ErrorNoHalt("No maps for this gamemode, forcing map to gm_construct\nPlease change this as soon as you can!\n") 351 | 352 | --Picks gm_construct to prevent the server from halting 353 | GAMEMODE.WinningMap = "gm_construct" 354 | timer.Simple( 3, function() 355 | RunConsoleCommand( "gamemode", GAMEMODE.WorkOutWinningGamemode()) 356 | RunConsoleCommand( "changelevel", GAMEMODE.WinningMap ) 357 | end) 358 | end 359 | end 360 | 361 | function GM:ChangeGamemode() 362 | 363 | local gm = GAMEMODE:WorkOutWinningGamemode() 364 | local mp = GAMEMODE:GetWinningMap() 365 | 366 | RunConsoleCommand( "gamemode", gm ) 367 | RunConsoleCommand( "changelevel", mp ) 368 | 369 | end -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/shared.lua: -------------------------------------------------------------------------------- 1 | /* 2 | shared.lua - Shared Component 3 | ----------------------------------------------------- 4 | This is the shared component of your gamemode, a lot of the game variables 5 | can be changed from here. 6 | */ 7 | 8 | include( "player_class.lua" ) 9 | include( "player_extension.lua" ) 10 | include( "class_default.lua" ) 11 | include( "player_colours.lua" ) 12 | 13 | fretta_voting = CreateConVar( "fretta_voting", "1", { FCVAR_REPLICATED, FCVAR_NOTIFY, FCVAR_ARCHIVE }, "Allow/Dissallow voting" ) 14 | 15 | GM.Name = "Simple Game Base" 16 | GM.Author = "Anonymous" 17 | GM.Email = "" 18 | GM.Website = "www.garry.tv" 19 | GM.Help = "No Help Available" 20 | 21 | GM.TeamBased = true // Team based game or a Free For All game? 22 | GM.AllowAutoTeam = true // Allow auto-assign? 23 | GM.AllowSpectating = true // Allow people to spectate during the game? 24 | GM.SecondsBetweenTeamSwitches = 10 // The minimum time between each team change? 25 | GM.GameLength = 15 // The overall length of the game 26 | GM.RoundLimit = -1 // Maximum amount of rounds to be played in round based games 27 | GM.VotingDelay = 5 // Delay between end of game, and vote. if you want to display any extra screens before the vote pops up 28 | GM.ShowTeamName = true // Show the team name on the HUD 29 | 30 | GM.NoPlayerSuicide = false // Set to true if players should not be allowed to commit suicide. 31 | GM.NoPlayerDamage = false // Set to true if players should not be able to damage each other. 32 | GM.NoPlayerSelfDamage = false // Allow players to hurt themselves? 33 | GM.NoPlayerTeamDamage = true // Allow team-members to hurt each other? 34 | GM.NoPlayerPlayerDamage = false // Allow players to hurt each other? 35 | GM.NoNonPlayerPlayerDamage = false // Allow damage from non players (physics, fire etc) 36 | GM.NoPlayerFootsteps = false // When true, all players have silent footsteps 37 | GM.PlayerCanNoClip = false // When true, players can use noclip without sv_cheats 38 | GM.TakeFragOnSuicide = true // -1 frag on suicide 39 | 40 | GM.MaximumDeathLength = 0 // Player will repspawn if death length > this (can be 0 to disable) 41 | GM.MinimumDeathLength = 2 // Player has to be dead for at least this long 42 | GM.AutomaticTeamBalance = false // Teams will be periodically balanced 43 | GM.ForceJoinBalancedTeams = true // Players won't be allowed to join a team if it has more players than another team 44 | GM.RealisticFallDamage = false // Set to true if you want realistic fall damage instead of the fix 10 damage. 45 | GM.AddFragsToTeamScore = false // Adds player's individual kills to team score (must be team based) 46 | 47 | GM.NoAutomaticSpawning = false // Players don't spawn automatically when they die, some other system spawns them 48 | GM.RoundBased = false // Round based, like CS 49 | GM.RoundLength = 30 // Round length, in seconds 50 | GM.RoundPreStartTime = 5 // Preperation time before a round starts 51 | GM.RoundPostLength = 8 // Seconds to show the 'x team won!' screen at the end of a round 52 | GM.RoundEndsWhenOneTeamAlive = true // CS Style rules 53 | 54 | GM.EnableFreezeCam = false // TF2 Style Freezecam 55 | GM.DeathLingerTime = 4 // The time between you dying and it going into spectator mode, 0 disables 56 | 57 | GM.SelectModel = true // Can players use the playermodel picker in the F1 menu? 58 | GM.SelectColor = false // Can players modify the colour of their name? (ie.. no teams) 59 | 60 | GM.PlayerRingSize = 48 // How big are the colored rings under the player's feet (if they are enabled) ? 61 | GM.HudSkin = "SimpleSkin" // The Derma skin to use for the HUD components 62 | GM.SuicideString = "died" // The string to append to the player's name when they commit suicide. 63 | GM.DeathNoticeDefaultColor = Color( 255, 128, 0 ); // Default colour for entity kills 64 | GM.DeathNoticeTextColor = color_white; // colour for text ie. "died", "killed" 65 | 66 | GM.ValidSpectatorModes = { OBS_MODE_CHASE, OBS_MODE_IN_EYE, OBS_MODE_ROAMING } // The spectator modes that are allowed 67 | GM.ValidSpectatorEntities = { "player" } // Entities we can spectate, players being the obvious default choice. 68 | GM.CanOnlySpectateOwnTeam = true; // you can only spectate players on your own team 69 | 70 | DeriveGamemode( "base" ) 71 | 72 | TEAM_GREEN = 1 73 | TEAM_ORANGE = 2 74 | TEAM_BLUE = 3 75 | TEAM_RED = 4 76 | 77 | /*--------------------------------------------------------- 78 | Name: gamemode:CreateTeams() 79 | Desc: Set up all your teams here. Note - HAS to be shared. 80 | ---------------------------------------------------------*/ 81 | function GM:CreateTeams() 82 | 83 | if ( !GAMEMODE.TeamBased ) then return end 84 | 85 | team.SetUp( TEAM_GREEN, "Green Team", Color( 70, 230, 70 ), true ) 86 | team.SetSpawnPoint( TEAM_GREEN, "info_player_start" ) // The list of entities can be a table 87 | 88 | team.SetUp( TEAM_ORANGE, "Orange Team", Color( 255, 200, 50 ) ) 89 | team.SetSpawnPoint( TEAM_ORANGE, "info_player_start", true ) 90 | 91 | team.SetUp( TEAM_BLUE, "Blue Team", Color( 80, 150, 255 ) ) 92 | team.SetSpawnPoint( TEAM_BLUE, "info_player_start", true ) 93 | 94 | team.SetUp( TEAM_RED, "Red Team", Color( 255, 80, 80 ) ) 95 | team.SetSpawnPoint( TEAM_RED, "info_player_start", true ) 96 | 97 | team.SetUp( TEAM_SPECTATOR, "Spectators", Color( 200, 200, 200 ), true ) 98 | team.SetSpawnPoint( TEAM_SPECTATOR, "info_player_start" ) 99 | team.SetClass( TEAM_SPECTATOR, { "Spectator" } ) 100 | 101 | end 102 | 103 | function GM:InGamemodeVote() 104 | return GetGlobalBool( "InGamemodeVote", false ) 105 | end 106 | 107 | /*--------------------------------------------------------- 108 | Name: gamemode:TeamHasEnoughPlayers( Number teamid ) 109 | Desc: Return true if the team has too many players. 110 | Useful for when forced auto-assign is on. 111 | ---------------------------------------------------------*/ 112 | function GM:TeamHasEnoughPlayers( teamid ) 113 | 114 | if teamid == TEAM_SPECTATOR then return false end 115 | 116 | local PlayerCount = team.NumPlayers( teamid ) 117 | 118 | // Don't let them join a team if it has more players than another team 119 | if ( GAMEMODE.ForceJoinBalancedTeams ) then 120 | 121 | for id, tm in pairs( team.GetAllTeams() ) do 122 | if ( id > 0 && id < 1000 && team.NumPlayers( id ) < PlayerCount && team.Joinable(id) ) then return true end 123 | end 124 | 125 | end 126 | 127 | return false 128 | 129 | end 130 | 131 | /*--------------------------------------------------------- 132 | Name: gamemode:PlayerCanJoinTeam( Player ply, Number teamid ) 133 | Desc: Are we allowed to join a team? Return true if so. 134 | ---------------------------------------------------------*/ 135 | function GM:PlayerCanJoinTeam( ply, teamid ) 136 | 137 | if ( SERVER && !self.BaseClass:PlayerCanJoinTeam( ply, teamid ) ) then 138 | return false 139 | end 140 | 141 | if ( GAMEMODE:TeamHasEnoughPlayers( teamid ) ) then 142 | ply:ChatPrint( "That team is full!" ) 143 | ply:SendLua("GAMEMODE:ShowTeam()") 144 | return false 145 | end 146 | 147 | return true 148 | 149 | end 150 | 151 | /*--------------------------------------------------------- 152 | Name: gamemode:Move( Player ply, CMoveData mv ) 153 | Desc: Setup Move, this also calls the player's class move 154 | function. 155 | ---------------------------------------------------------*/ 156 | function GM:Move( ply, mv ) 157 | 158 | if ( ply:CallClassFunction( "Move", mv ) ) then return true end 159 | 160 | end 161 | 162 | /*--------------------------------------------------------- 163 | Name: gamemode:KeyPress( Player ply, Number key ) 164 | Desc: Player presses a key, this also calls the player's class 165 | OnKeyPress function. 166 | ---------------------------------------------------------*/ 167 | function GM:KeyPress( ply, key ) 168 | 169 | if ( ply:CallClassFunction( "OnKeyPress", key ) ) then return true end 170 | 171 | end 172 | 173 | /*--------------------------------------------------------- 174 | Name: gamemode:KeyRelease( Player ply, Number key ) 175 | Desc: Player releases a key, this also calls the player's class 176 | OnKeyRelease function. 177 | ---------------------------------------------------------*/ 178 | function GM:KeyRelease( ply, key ) 179 | 180 | if ( ply:CallClassFunction( "OnKeyRelease", key ) ) then return true end 181 | 182 | end 183 | 184 | /*--------------------------------------------------------- 185 | Name: gamemode:PlayerFootstep( Player ply, Vector pos, Number foot, String sound, Float volume, CReceipientFilter rf ) 186 | Desc: Player's feet makes a sound, this also calls the player's class Footstep function. 187 | If you want to disable all footsteps set GM.NoPlayerFootsteps to true. 188 | If you want to disable footsteps on a class, set Class.DisableFootsteps to true. 189 | ---------------------------------------------------------*/ 190 | function GM:PlayerFootstep( ply, pos, foot, sound, volume, rf ) 191 | 192 | if( GAMEMODE.NoPlayerFootsteps || !ply:Alive() || ply:Team() == TEAM_SPECTATOR || ply:IsObserver() ) then 193 | return true; 194 | end 195 | 196 | local Class = ply:GetPlayerClass(); 197 | if( !Class ) then return end 198 | 199 | if( Class.DisableFootsteps ) then // rather than using a hook, we can just do this to override the function instead. 200 | return true; 201 | end 202 | 203 | if( Class.Footstep ) then 204 | return Class:Footstep( ply, pos, foot, sound, volume, rf ); // Call footstep function in class, you can use this to make custom footstep sounds 205 | end 206 | 207 | end 208 | 209 | /*--------------------------------------------------------- 210 | Name: gamemode:CalcView( Player ply, Vector origin, Angles angles, Number fov ) 211 | Desc: Calculates the players view. Also calls the players class 212 | CalcView function, as well as GetViewModelPosition and CalcView 213 | on the current weapon. Returns a table. 214 | ---------------------------------------------------------*/ 215 | function GM:CalcView( ply, origin, angles, fov ) 216 | 217 | local view = ply:CallClassFunction( "CalcView", origin, angles, fov ) or { ["origin"] = origin, ["angles"] = angles, ["fov"] = fov }; 218 | 219 | origin = view.origin or origin 220 | angles = view.angles or angles 221 | fov = view.fov or fov 222 | 223 | local wep = ply:GetActiveWeapon() 224 | if ( IsValid( wep ) ) then 225 | 226 | local func = wep.GetViewModelPosition 227 | if ( func ) then view.vm_origin, view.vm_angles = func( wep, origin*1, angles*1 ) end 228 | 229 | local func = wep.CalcView 230 | if ( func ) then view.origin, view.angles, view.fov = func( wep, ply, origin*1, angles*1, fov ) end 231 | 232 | end 233 | 234 | return view 235 | 236 | end 237 | 238 | /*--------------------------------------------------------- 239 | Name: gamemode:GetTimeLimit() 240 | Desc: Returns the time limit of a game in seconds, so you could 241 | make it use a cvar instead. Return -1 for unlimited. 242 | Unlimited length games can be changed using vote for 243 | change. 244 | ---------------------------------------------------------*/ 245 | function GM:GetTimeLimit() 246 | 247 | if( GAMEMODE.GameLength > 0 ) then 248 | return GAMEMODE.GameLength * 60; 249 | end 250 | 251 | return -1; 252 | 253 | end 254 | 255 | /*--------------------------------------------------------- 256 | Name: gamemode:GetGameTimeLeft() 257 | Desc: Get the remaining time in seconds. 258 | ---------------------------------------------------------*/ 259 | function GM:GetGameTimeLeft() 260 | 261 | local EndTime = GAMEMODE:GetTimeLimit(); 262 | if ( EndTime == -1 ) then return -1 end 263 | 264 | return EndTime - CurTime() 265 | 266 | end 267 | 268 | /*--------------------------------------------------------- 269 | Name: gamemode:PlayerNoClip( player, bool ) 270 | Desc: Player pressed the noclip key, return true if 271 | the player is allowed to noclip, false to block 272 | ---------------------------------------------------------*/ 273 | function GM:PlayerNoClip( pl, on ) 274 | 275 | // Allow noclip if we're in single player or have cheats enabled 276 | if ( GAMEMODE.PlayerCanNoClip || game.SinglePlayer() || GetConVar( "sv_cheats" ):GetBool() ) then return true end 277 | 278 | // Don't if it's not. 279 | return false 280 | 281 | end 282 | 283 | // This function includes /yourgamemode/player_class/*.lua 284 | // And AddCSLuaFile's each of those files. 285 | // You need to call it in your derived shared.lua IF you have files in that folder 286 | // and want to include them! 287 | 288 | function IncludePlayerClasses() 289 | 290 | local Folder = string.Replace( GM.Folder, "gamemodes/", "" ); 291 | 292 | for c,d in pairs(file.Find(Folder.."/gamemode/player_class/*.lua", "LUA")) do 293 | include( Folder.."/gamemode/player_class/"..d ) 294 | AddCSLuaFile( Folder.."/gamemode/player_class/"..d ) 295 | end 296 | 297 | end 298 | 299 | IncludePlayerClasses() 300 | 301 | function util.ToMinutesSeconds(seconds) 302 | local minutes = math.floor(seconds / 60) 303 | seconds = seconds - minutes * 60 304 | 305 | return string.format("%02d:%02d", minutes, math.floor(seconds)) 306 | end 307 | 308 | function util.ToMinutesSecondsMilliseconds(seconds) 309 | local minutes = math.floor(seconds / 60) 310 | seconds = seconds - minutes * 60 311 | 312 | local milliseconds = math.floor(seconds % 1 * 100) 313 | 314 | return string.format("%02d:%02d.%02d", minutes, math.floor(seconds), milliseconds) 315 | end 316 | 317 | function timer.SimpleEx(delay, action, ...) 318 | if ... == nil then 319 | timer.Simple(delay, action) 320 | else 321 | local a, b, c, d, e, f, g, h, i, j, k = ... 322 | timer.Simple(delay, function() action(a, b, c, d, e, f, g, h, i, j, k) end) 323 | end 324 | end 325 | 326 | function timer.CreateEx(timername, delay, repeats, action, ...) 327 | if ... == nil then 328 | timer.Create(timername, delay, repeats, action) 329 | else 330 | local a, b, c, d, e, f, g, h, i, j, k = ... 331 | timer.Create(timername, delay, repeats, function() action(a, b, c, d, e, f, g, h, i, j, k) end) 332 | end 333 | end 334 | -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/skin.lua: -------------------------------------------------------------------------------- 1 | /* 2 | skin.lua - Fretta Derma Skin 3 | ----------------------------------------------------- 4 | This is the default Fretta skin for Derma. If you want to override the look of Fretta, 5 | base a skin of this and change GM.HudSkin. 6 | */ 7 | 8 | local surface = surface 9 | local draw = draw 10 | local Color = Color 11 | 12 | local SKIN = {} 13 | 14 | SKIN.PrintName = "" 15 | SKIN.Author = "" 16 | SKIN.DermaVersion = 1 17 | 18 | SKIN.bg_color = Color( 100, 100, 100, 255 ) 19 | SKIN.bg_color_sleep = Color( 70, 70, 70, 255 ) 20 | SKIN.bg_color_dark = Color( 50, 50, 50, 255 ) 21 | SKIN.bg_color_bright = Color( 220, 220, 220, 255 ) 22 | 23 | SKIN.fontFrame = "Default" 24 | 25 | SKIN.control_color = Color( 180, 180, 180, 255 ) 26 | SKIN.control_color_highlight = Color( 220, 220, 220, 255 ) 27 | SKIN.control_color_active = Color( 110, 150, 255, 255 ) 28 | SKIN.control_color_bright = Color( 255, 200, 100, 255 ) 29 | SKIN.control_color_dark = Color( 100, 100, 100, 255 ) 30 | 31 | SKIN.bg_alt1 = Color( 50, 50, 50, 255 ) 32 | SKIN.bg_alt2 = Color( 55, 55, 55, 255 ) 33 | 34 | SKIN.listview_hover = Color( 70, 70, 70, 255 ) 35 | SKIN.listview_selected = Color( 100, 170, 220, 255 ) 36 | 37 | SKIN.text_bright = Color( 255, 255, 255, 255 ) 38 | SKIN.text_normal = Color( 180, 180, 180, 255 ) 39 | SKIN.text_dark = Color( 20, 20, 20, 255 ) 40 | SKIN.text_highlight = Color( 255, 20, 20, 255 ) 41 | 42 | SKIN.texGradientUp = Material( "gui/gradient_up" ) 43 | SKIN.texGradientDown = Material( "gui/gradient_down" ) 44 | 45 | SKIN.combobox_selected = SKIN.listview_selected 46 | 47 | SKIN.panel_transback = Color( 255, 255, 255, 50 ) 48 | SKIN.tooltip = Color( 255, 245, 175, 255 ) 49 | 50 | SKIN.colPropertySheet = Color( 170, 170, 170, 255 ) 51 | SKIN.colTab = SKIN.colPropertySheet 52 | SKIN.colTabInactive = Color( 170, 170, 170, 155 ) 53 | SKIN.colTabShadow = Color( 60, 60, 60, 255 ) 54 | SKIN.colTabText = Color( 255, 255, 255, 255 ) 55 | SKIN.colTabTextInactive = Color( 0, 0, 0, 155 ) 56 | SKIN.fontTab = "Default" 57 | 58 | SKIN.colCollapsibleCategory = Color( 255, 255, 255, 20 ) 59 | 60 | SKIN.colCategoryText = Color( 255, 255, 255, 255 ) 61 | SKIN.colCategoryTextInactive = Color( 200, 200, 200, 255 ) 62 | SKIN.fontCategoryHeader = "TabLarge" 63 | 64 | SKIN.colNumberWangBG = Color( 255, 240, 150, 255 ) 65 | SKIN.colTextEntryBG = Color( 240, 240, 240, 255 ) 66 | SKIN.colTextEntryBorder = Color( 20, 20, 20, 255 ) 67 | SKIN.colTextEntryText = Color( 20, 20, 20, 255 ) 68 | SKIN.colTextEntryTextHighlight = Color( 20, 200, 250, 255 ) 69 | SKIN.colTextEntryTextHighlight = Color( 20, 200, 250, 255 ) 70 | 71 | SKIN.colMenuBG = Color( 255, 255, 255, 200 ) 72 | SKIN.colMenuBorder = Color( 0, 0, 0, 200 ) 73 | 74 | SKIN.colButtonText = Color( 0, 0, 0, 250 ) 75 | SKIN.colButtonTextDisabled = Color( 0, 0, 0, 100 ) 76 | SKIN.colButtonBorder = Color( 20, 20, 20, 255 ) 77 | SKIN.colButtonBorderHighlight = Color( 255, 255, 255, 50 ) 78 | SKIN.colButtonBorderShadow = Color( 0, 0, 0, 100 ) 79 | SKIN.fontButton = "Default" 80 | 81 | -- enum for draw order 82 | DM_ORDER_LATESTATTOP = 1; 83 | DM_ORDER_LATESTATBOTTOM = 2; 84 | 85 | -- basic deathmsg appearance settings 86 | SKIN.deathMessageBackgroundCol = Color( 46, 43, 42, 220 ); 87 | SKIN.deathMessageBackgroundLocal = Color( 75, 75, 75, 200 ); -- this is the colour that the background is when the local player is involved in the deathmsg, so it stands out. 88 | SKIN.deathMessageActionColor = Color( 200, 200, 200 ); 89 | 90 | local matBlurScreen = Material( "pp/blurscreen" ) 91 | 92 | 93 | /*--------------------------------------------------------- 94 | DrawGenericBackground 95 | ---------------------------------------------------------*/ 96 | function SKIN:DrawGenericBackground( x, y, w, h, color ) 97 | 98 | draw.RoundedBox( 4, x, y, w, h, color ) 99 | 100 | end 101 | 102 | /*--------------------------------------------------------- 103 | DrawLinedButtonBorder 104 | ---------------------------------------------------------*/ 105 | function SKIN:DrawLinedButtonBorder( x, y, w, h, depressed ) 106 | 107 | surface.SetDrawColor( Color( 0, 0, 0, 200 ) ) 108 | surface.DrawOutlinedRect( x+1, y+1, w-2, h-2 ) 109 | 110 | end 111 | 112 | /*--------------------------------------------------------- 113 | Button 114 | ---------------------------------------------------------*/ 115 | function SKIN:PaintCancelButton( panel ) 116 | 117 | local w, h = panel:GetSize() 118 | 119 | if ( panel.m_bBackground ) then 120 | 121 | local col = self.control_color 122 | 123 | if ( panel:GetDisabled() ) then 124 | col = self.control_color_dark 125 | elseif ( panel.Depressed ) then 126 | col = self.control_color_active 127 | elseif ( panel.Hovered ) then 128 | col = self.control_color_highlight 129 | end 130 | 131 | if ( panel.m_colBackground ) then 132 | 133 | col = table.Copy( panel.m_colBackground ) 134 | 135 | if ( panel:GetDisabled() ) then 136 | col.r = math.Clamp( col.r * 0.7, 0, 255 ) 137 | col.g = math.Clamp( col.g * 0.7, 0, 255 ) 138 | col.b = math.Clamp( col.b * 0.7, 0, 255 ) 139 | col.a = 20 140 | elseif ( panel.Depressed ) then 141 | col.r = math.Clamp( col.r + 100, 0, 255 ) 142 | col.g = math.Clamp( col.g + 100, 0, 255 ) 143 | col.b = math.Clamp( col.b + 100, 0, 255 ) 144 | elseif ( panel.Hovered ) then 145 | col.r = math.Clamp( col.r + 30, 0, 255 ) 146 | col.g = math.Clamp( col.g + 30, 0, 255 ) 147 | col.b = math.Clamp( col.b + 30, 0, 255 ) 148 | end 149 | end 150 | 151 | surface.SetDrawColor( col.r, col.g, col.b, col.a ) 152 | panel:DrawFilledRect() 153 | 154 | end 155 | 156 | end 157 | 158 | SKIN.PaintSelectButton = SKIN.PaintCancelButton 159 | 160 | function SKIN:PaintOverCancelButton( panel ) 161 | 162 | local w, h = panel:GetSize() 163 | 164 | if ( panel.m_bBorder ) then 165 | self:DrawLinedButtonBorder( 0, 0, w, h, panel.Depressed ) 166 | end 167 | 168 | end 169 | 170 | SKIN.PaintOverSelectButton = SKIN.PaintOverCancelButton 171 | 172 | function SKIN:SchemeCancelButton( panel ) 173 | 174 | panel:SetFontInternal( "FRETTA_SMALL" ) 175 | 176 | if ( panel:GetDisabled() ) then 177 | panel:SetTextColor( self.colButtonTextDisabled ) 178 | else 179 | panel:SetTextColor( self.colButtonText ) 180 | end 181 | 182 | DLabel.ApplySchemeSettings( panel ) 183 | 184 | end 185 | 186 | function SKIN:SchemeSelectButton( panel ) 187 | 188 | panel:SetFontInternal( "FRETTA_SMALL" ) 189 | 190 | if ( panel:GetDisabled() ) then 191 | panel:SetTextColor( self.colButtonTextDisabled ) 192 | else 193 | panel:SetTextColor( self.colButtonText ) 194 | end 195 | 196 | DLabel.ApplySchemeSettings( panel ) 197 | 198 | end 199 | 200 | /*--------------------------------------------------------- 201 | ListViewLine 202 | ---------------------------------------------------------*/ 203 | function SKIN:PaintListViewLine( panel ) 204 | 205 | 206 | end 207 | 208 | /*--------------------------------------------------------- 209 | ListViewLine 210 | ---------------------------------------------------------*/ 211 | function SKIN:PaintListView( panel ) 212 | 213 | 214 | end 215 | 216 | /*--------------------------------------------------------- 217 | ListViewLabel 218 | ---------------------------------------------------------*/ 219 | function SKIN:PaintScorePanelHeader( panel ) 220 | 221 | //surface.SetDrawColor( panel.cTeamColor ) 222 | //panel:DrawFilledRect() 223 | 224 | end 225 | 226 | /*--------------------------------------------------------- 227 | ListViewLabel 228 | ---------------------------------------------------------*/ 229 | function SKIN:PaintScorePanelLine( panel ) 230 | 231 | local Tall = panel:GetTall() 232 | local BoxHeight = 21 233 | 234 | if ( !IsValid( panel.pPlayer ) || !panel.pPlayer:Alive() ) then 235 | draw.RoundedBox( 4, 0, Tall*0.5 - BoxHeight*0.5, panel:GetWide(), BoxHeight, Color( 60, 60, 60, 255 ) ) 236 | return 237 | end 238 | 239 | if ( panel.pPlayer == LocalPlayer() ) then 240 | draw.RoundedBox( 4, 0, Tall*0.5 - BoxHeight*0.5, panel:GetWide(), BoxHeight, Color( 90, 90, 90, 255 ) ) 241 | return 242 | end 243 | 244 | draw.RoundedBox( 4, 0, Tall*0.5 - BoxHeight*0.5, panel:GetWide(), BoxHeight, Color( 70, 70, 70, 255 ) ) 245 | 246 | end 247 | 248 | /*--------------------------------------------------------- 249 | PaintScorePanel 250 | ---------------------------------------------------------*/ 251 | function SKIN:PaintScorePanel( panel ) 252 | 253 | surface.SetMaterial( matBlurScreen ) 254 | surface.SetDrawColor( 255, 255, 255, 255 ) 255 | 256 | local x, y = panel:LocalToScreen( 0, 0 ) 257 | 258 | matBlurScreen:SetFloat( "$blur", 5 ) 259 | render.UpdateScreenEffectTexture() 260 | surface.DrawTexturedRect( x*-1, y*-1, ScrW(), ScrH() ) 261 | 262 | //matBlurScreen:SetFloat( "$blur", 3 ) 263 | //render.UpdateScreenEffectTexture() 264 | //surface.DrawTexturedRect( x*-1, y*-1, ScrW(), ScrH() ) 265 | 266 | draw.RoundedBox( 8, 0, 8, panel:GetWide(), panel:GetTall()-8, Color( 200, 200, 200, 150 ) ) 267 | 268 | end 269 | 270 | 271 | /*--------------------------------------------------------- 272 | LayoutTeamScoreboardHeader 273 | ---------------------------------------------------------*/ 274 | function SKIN:LayoutTeamScoreboardHeader( panel ) 275 | 276 | panel.TeamName:StretchToParent( 0, 0, 0, 0 ) 277 | panel.TeamName:SetTextInset( 8, 0 ) 278 | panel.TeamName:SetColor( color_white ) 279 | panel.TeamName:SetFontInternal( "FRETTA_MEDIUM" ) 280 | 281 | panel.TeamScore:StretchToParent( 0, 0, 0, 0 ) 282 | panel.TeamScore:SetContentAlignment( 6 ) 283 | panel.TeamScore:SetTextInset( 8, 0 ) 284 | panel.TeamScore:SetColor( color_white ) 285 | panel.TeamScore:SetFontInternal( "FRETTA_MEDIUM" ) 286 | 287 | end 288 | 289 | function SKIN:PaintTeamScoreboardHeader( panel ) 290 | 291 | local Color = team.GetColor( panel.iTeamID ) 292 | draw.RoundedBox( 4, 0, 0, panel:GetWide(), panel:GetTall()*2, Color ) 293 | 294 | end 295 | 296 | function SKIN:SchemeScorePanelLabel( panel ) 297 | 298 | --panel:SetTextColor( GAMEMODE:GetTeamColor( panel.pPlayer ) ) 299 | panel:SetTextColor( color_white ) 300 | panel:SetFontInternal( "FRETTA_MEDIUM_SHADOW" ) 301 | 302 | end 303 | 304 | function SKIN:PaintScorePanelLabel( panel ) 305 | 306 | if ( !IsValid( panel.pPlayer ) || !panel.pPlayer:Alive() ) then 307 | panel:SetAlpha( 125 ) 308 | else 309 | panel:SetAlpha( 255 ) 310 | end 311 | 312 | end 313 | 314 | function SKIN:SchemeScorePanelHeaderLabel( panel ) 315 | 316 | panel:SetTextColor( Color( 70, 70, 70, 255 ) ) 317 | panel:SetFontInternal( "HudSelectionText" ) 318 | 319 | end 320 | 321 | function SKIN:SchemeSpectatorInfo( panel ) 322 | 323 | panel:SetTextColor( Color( 255, 255, 255, 255 ) ) 324 | panel:SetFontInternal( "FRETTA_SMALL" ) 325 | 326 | end 327 | 328 | /*--------------------------------------------------------- 329 | ScoreHeader 330 | ---------------------------------------------------------*/ 331 | function SKIN:PaintScoreHeader( panel ) 332 | 333 | draw.RoundedBox( 8, 0, 0, panel:GetWide(), panel:GetTall()*2, Color( 50, 90, 160 ) ) 334 | 335 | end 336 | 337 | function SKIN:LayoutScoreHeader( panel ) 338 | 339 | panel.HostName:SizeToContents() 340 | panel.HostName:SetPos( 0, 0 ) 341 | panel.HostName:CenterHorizontal() 342 | 343 | panel.GamemodeName:SizeToContents() 344 | panel.GamemodeName:MoveBelow( panel.HostName, 0 ) 345 | panel.GamemodeName:CenterHorizontal() 346 | 347 | panel:SetTall( panel.GamemodeName.y + panel.GamemodeName:GetTall() + 4 ) 348 | 349 | end 350 | 351 | function SKIN:SchemeScoreHeader( panel ) 352 | 353 | panel.HostName:SetTextColor( Color( 255, 255, 255, 255 ) ) 354 | panel.HostName:SetFontInternal( "FRETTA_LARGE_SHADOW" ) 355 | 356 | panel.GamemodeName:SetTextColor( Color( 255, 255, 255, 255 ) ) 357 | panel.GamemodeName:SetFontInternal( "FRETTA_MEDIUM_SHADOW" ) 358 | 359 | end 360 | 361 | /*--------------------------------------------------------- 362 | DeathMessages 363 | ---------------------------------------------------------*/ 364 | function SKIN:PaintGameNotice( panel ) 365 | 366 | if ( panel.m_bHighlight ) then 367 | draw.RoundedBox( 4, 0, 0, panel:GetWide(), panel:GetTall(), Color( 90, 90, 90, 200 ) ) 368 | return 369 | end 370 | 371 | draw.RoundedBox( 4, 0, 0, panel:GetWide(), panel:GetTall(), Color( 20, 20, 20, 190 ) ) 372 | 373 | end 374 | 375 | function SKIN:SchemeGameNoticeLabel( panel ) 376 | 377 | panel:SetFontInternal( "FRETTA_NOTIFY" ); 378 | DLabel.ApplySchemeSettings( panel ) 379 | 380 | end 381 | 382 | /*--------------------------------------------------------- 383 | GamemodeButton 384 | ---------------------------------------------------------*/ 385 | function SKIN:PaintGamemodeButton( panel ) 386 | 387 | local w, h = panel:GetSize() 388 | 389 | local col = Color( 255, 255, 255, 10 ) 390 | 391 | if ( panel:GetDisabled() ) then 392 | col = Color( 0, 0, 0, 10 ) 393 | elseif ( panel.Depressed ) then 394 | col = Color( 255, 255, 255, 50 ) 395 | elseif ( panel.Hovered ) then 396 | col = Color( 255, 255, 255, 20 ) 397 | end 398 | 399 | if ( panel.bgColor != nil ) then col = panel.bgColor end 400 | 401 | draw.RoundedBox( 4, 0, 0, w, h, col ) 402 | 403 | end 404 | 405 | function SKIN:SchemeGamemodeButton( panel ) 406 | 407 | panel:SetTextColor( color_white ) 408 | panel:SetFontInternal( "FRETTA_MEDIUM_SHADOW" ) 409 | panel:SetContentAlignment( 4 ) 410 | panel:SetTextInset( 8, 0 ) 411 | 412 | end 413 | 414 | 415 | /*--------------------------------------------------------- 416 | PanelButton 417 | ---------------------------------------------------------*/ 418 | function SKIN:PaintPanelButton( panel ) 419 | 420 | local w, h = panel:GetSize() 421 | 422 | local col = Color( 160, 160, 160, 255 ) 423 | 424 | if ( panel:GetDisabled() ) then 425 | col = Color( 100, 100, 100, 255 ) 426 | elseif ( panel.Depressed ) then 427 | col = Color( 150, 210, 255, 255 ) 428 | elseif ( panel.Hovered ) then 429 | col = Color( 200, 200, 200, 255 ) 430 | end 431 | 432 | if ( panel.bgColor != nil ) then col = panel.bgColor end 433 | 434 | surface.SetDrawColor( col ) 435 | panel:DrawFilledRect() 436 | 437 | end 438 | 439 | function SKIN:PaintOverPanelButton( panel ) 440 | 441 | local w, h = panel:GetSize() 442 | self:DrawLinedButtonBorder( 0, 0, w, h, panel.Depressed ) 443 | 444 | end 445 | 446 | derma.DefineSkin( "SimpleSkin", "", SKIN ) -------------------------------------------------------------------------------- /gamemodes/fretta13/gamemode/init.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | init.lua - Server Component 3 | ----------------------------------------------------- 4 | The entire server side bit of Fretta starts here. 5 | ]] 6 | 7 | AddCSLuaFile( "cl_init.lua" ) 8 | AddCSLuaFile( "shared.lua" ) 9 | AddCSLuaFile( "skin.lua" ) 10 | AddCSLuaFile( "player_class.lua" ) 11 | AddCSLuaFile( "class_default.lua" ) 12 | AddCSLuaFile( "cl_splashscreen.lua" ) 13 | AddCSLuaFile( "cl_selectscreen.lua" ) 14 | AddCSLuaFile( "cl_gmchanger.lua" ) 15 | AddCSLuaFile( "cl_help.lua" ) 16 | AddCSLuaFile( "player_extension.lua" ) 17 | AddCSLuaFile( "vgui/vgui_hudlayout.lua" ) 18 | AddCSLuaFile( "vgui/vgui_hudelement.lua" ) 19 | AddCSLuaFile( "vgui/vgui_hudbase.lua" ) 20 | AddCSLuaFile( "vgui/vgui_hudcommon.lua" ) 21 | AddCSLuaFile( "vgui/vgui_gamenotice.lua" ) 22 | AddCSLuaFile( "vgui/vgui_scoreboard.lua" ) 23 | AddCSLuaFile( "vgui/vgui_scoreboard_team.lua" ) 24 | AddCSLuaFile( "vgui/vgui_scoreboard_small.lua" ) 25 | AddCSLuaFile( "vgui/vgui_vote.lua" ) 26 | AddCSLuaFile( "cl_hud.lua" ) 27 | AddCSLuaFile( "cl_deathnotice.lua" ) 28 | AddCSLuaFile( "cl_scores.lua" ) 29 | AddCSLuaFile( "cl_notify.lua" ) 30 | AddCSLuaFile( "player_colours.lua" ) 31 | 32 | include( "shared.lua" ) 33 | include( "sv_gmchanger.lua" ) 34 | include( "sv_spectator.lua" ) 35 | include( "round_controller.lua" ) 36 | include( "utility.lua" ) 37 | 38 | GM.ReconnectedPlayers = {} 39 | 40 | function GM:Initialize() 41 | 42 | util.AddNetworkString("PlayableGamemodes") 43 | util.AddNetworkString("RoundAddedTime") 44 | util.AddNetworkString("PlayableGamemodes") 45 | util.AddNetworkString("fretta_teamchange") 46 | 47 | -- If we're round based, wait 3 seconds before the first round starts 48 | if ( GAMEMODE.RoundBased ) then 49 | timer.Simple( 3, function() GAMEMODE:StartRoundBasedGame() end ) 50 | end 51 | 52 | if ( GAMEMODE.AutomaticTeamBalance ) then 53 | timer.Create( "CheckTeamBalance", 30, 0, function() GAMEMODE:CheckTeamBalance() end ) 54 | end 55 | end 56 | 57 | function GM:Think() 58 | 59 | self.BaseClass:Think() 60 | 61 | for k,v in pairs( player.GetAll() ) do 62 | 63 | local Class = v:GetPlayerClass() 64 | if ( !Class ) then return end 65 | 66 | v:CallClassFunction( "Think" ) 67 | 68 | end 69 | 70 | -- Game time related 71 | if( !GAMEMODE.IsEndOfGame && ( !GAMEMODE.RoundBased || ( GAMEMODE.RoundBased && GAMEMODE:CanEndRoundBasedGame() ) ) && CurTime() >= GAMEMODE.GetTimeLimit() ) then 72 | GAMEMODE:EndOfGame( true ) 73 | end 74 | 75 | end 76 | 77 | /*--------------------------------------------------------- 78 | Name: gamemode:CanPlayerSuicide( Player ply ) 79 | Desc: Is the player allowed to commit suicide? 80 | ---------------------------------------------------------*/ 81 | function GM:CanPlayerSuicide( ply ) 82 | 83 | if( ply:Team() == TEAM_UNASSIGNED || ply:Team() == TEAM_SPECTATOR ) then 84 | return false -- no suicide in spectator mode 85 | end 86 | 87 | return !GAMEMODE.NoPlayerSuicide 88 | 89 | end 90 | 91 | /*--------------------------------------------------------- 92 | Name: gamemode:PlayerSwitchFlashlight( Player ply, Bool on ) 93 | Desc: Can we turn our flashlight on or off? 94 | ---------------------------------------------------------*/ 95 | function GM:PlayerSwitchFlashlight( ply, on ) 96 | 97 | if ( ply:Team() == TEAM_SPECTATOR || ply:Team() == TEAM_UNASSIGNED || ply:Team() == TEAM_CONNECTING ) then 98 | return not on 99 | end 100 | 101 | return ply:CanUseFlashlight() 102 | 103 | end 104 | 105 | /*--------------------------------------------------------- 106 | Name: gamemode:PlayerInitialSpawn( Player ply ) 107 | Desc: Our very first spawn in the game. 108 | ---------------------------------------------------------*/ 109 | function GM:PlayerInitialSpawn( pl ) 110 | 111 | pl:SetTeam( TEAM_UNASSIGNED ) 112 | pl:SetPlayerClass( "Spectator" ) 113 | pl.m_bFirstSpawn = true 114 | pl:UpdateNameColor() 115 | 116 | GAMEMODE:CheckPlayerReconnected( pl ) 117 | 118 | end 119 | 120 | function GM:CheckPlayerReconnected( pl ) 121 | 122 | if table.HasValue( GAMEMODE.ReconnectedPlayers, pl:UniqueID() ) then 123 | GAMEMODE:PlayerReconnected( pl ) 124 | end 125 | 126 | end 127 | 128 | /*--------------------------------------------------------- 129 | Name: gamemode:PlayerReconnected( Player ply ) 130 | Desc: Called if the player has appeared to have reconnected. 131 | ---------------------------------------------------------*/ 132 | function GM:PlayerReconnected( pl ) 133 | 134 | -- Use this hook to do stuff when a player rejoins and has been in the server previously 135 | 136 | end 137 | 138 | function GM:PlayerDisconnected( pl ) 139 | 140 | table.insert( GAMEMODE.ReconnectedPlayers, pl:UniqueID() ) 141 | 142 | self.BaseClass:PlayerDisconnected( pl ) 143 | 144 | end 145 | 146 | function GM:ShowHelp( pl ) 147 | 148 | pl:SendLua( "GAMEMODE:ShowHelp()" ) 149 | 150 | end 151 | 152 | 153 | function GM:PlayerSpawn( pl ) 154 | 155 | pl:UpdateNameColor() 156 | 157 | -- The player never spawns straight into the game in Fretta 158 | -- They spawn as a spectator first (during the splash screen and team picking screens) 159 | if ( pl.m_bFirstSpawn ) then 160 | 161 | pl.m_bFirstSpawn = nil 162 | 163 | if ( pl:IsBot() ) then 164 | 165 | GAMEMODE:AutoTeam( pl ) 166 | 167 | -- The bot doesn't send back the 'seen splash' command, so fake it. 168 | if ( !GAMEMODE.TeamBased && !GAMEMODE.NoAutomaticSpawning ) then 169 | pl:Spawn() 170 | end 171 | 172 | else 173 | 174 | pl:StripWeapons() 175 | GAMEMODE:PlayerSpawnAsSpectator( pl ) 176 | 177 | -- Follow a random player until we join a team 178 | if ( #player.GetAll() > 1 ) then 179 | pl:Spectate( OBS_MODE_CHASE ) 180 | pl:SpectateEntity( table.Random( player.GetAll() ) ) 181 | end 182 | 183 | end 184 | 185 | return 186 | 187 | end 188 | 189 | pl:CheckPlayerClassOnSpawn() 190 | 191 | if ( GAMEMODE.TeamBased && ( pl:Team() == TEAM_SPECTATOR || pl:Team() == TEAM_UNASSIGNED ) ) then 192 | 193 | GAMEMODE:PlayerSpawnAsSpectator( pl ) 194 | return 195 | 196 | end 197 | 198 | -- Stop observer mode 199 | pl:UnSpectate() 200 | 201 | -- Call item loadout function 202 | hook.Call( "PlayerLoadout", GAMEMODE, pl ) 203 | 204 | -- Set player model 205 | hook.Call( "PlayerSetModel", GAMEMODE, pl ) 206 | 207 | pl:SetupHands() 208 | 209 | -- Call class function 210 | pl:OnSpawn() 211 | 212 | end 213 | 214 | 215 | function GM:PlayerLoadout( pl ) 216 | 217 | pl:CheckPlayerClassOnSpawn() 218 | 219 | pl:OnLoadout() 220 | 221 | -- Switch to prefered weapon if they have it 222 | local cl_defaultweapon = pl:GetInfo( "cl_defaultweapon" ) 223 | 224 | if ( pl:HasWeapon( cl_defaultweapon ) ) then 225 | pl:SelectWeapon( cl_defaultweapon ) 226 | end 227 | 228 | end 229 | 230 | 231 | function GM:PlayerSetModel( pl ) 232 | 233 | pl:OnPlayerModel() 234 | 235 | end 236 | 237 | 238 | function GM:AutoTeam( pl ) 239 | 240 | if ( !GAMEMODE.AllowAutoTeam ) then return end 241 | if ( !GAMEMODE.TeamBased ) then return end 242 | 243 | GAMEMODE:PlayerRequestTeam( pl, team.BestAutoJoinTeam() ) 244 | 245 | end 246 | 247 | concommand.Add( "autoteam", function( pl, cmd, args ) hook.Call( "AutoTeam", GAMEMODE, pl ) end ) 248 | 249 | 250 | function GM:PlayerRequestClass( ply, class, disablemessage ) 251 | 252 | local Classes = team.GetClass( ply:Team() ) 253 | if (!Classes) then return end 254 | 255 | local RequestedClass = Classes[ class ] 256 | if (!RequestedClass) then return end 257 | 258 | if ( ply:Alive() && SERVER ) then 259 | 260 | if ( ply.m_SpawnAsClass && ply.m_SpawnAsClass == RequestedClass ) then return end 261 | 262 | ply.m_SpawnAsClass = RequestedClass 263 | 264 | if ( !disablemessage ) then 265 | ply:ChatPrint( "Your class will change to '".. player_class.GetClassName( RequestedClass ) .. "' when you respawn" ) 266 | end 267 | 268 | else 269 | self:PlayerJoinClass( ply, RequestedClass ) 270 | ply.m_SpawnAsClass = nil 271 | end 272 | 273 | end 274 | 275 | concommand.Add( "changeclass", function( pl, cmd, args ) hook.Call( "PlayerRequestClass", GAMEMODE, pl, tonumber(args[1]) ) end ) 276 | 277 | 278 | local function SeenSplash( ply ) 279 | 280 | if ( ply.m_bSeenSplashScreen ) then return end 281 | ply.m_bSeenSplashScreen = true 282 | 283 | if ( !GAMEMODE.TeamBased && !GAMEMODE.NoAutomaticSpawning ) then 284 | ply:KillSilent() 285 | end 286 | 287 | end 288 | 289 | concommand.Add( "seensplash", SeenSplash ) 290 | 291 | 292 | function GM:PlayerJoinTeam( ply, teamid ) 293 | 294 | local iOldTeam = ply:Team() 295 | 296 | if ( ply:Alive() ) then 297 | if ( iOldTeam == TEAM_SPECTATOR || (iOldTeam == TEAM_UNASSIGNED && GAMEMODE.TeamBased) ) then 298 | ply:KillSilent() 299 | else 300 | ply:Kill() 301 | end 302 | end 303 | 304 | ply:SetTeam( teamid ) 305 | ply.LastTeamSwitch = RealTime() 306 | 307 | local Classes = team.GetClass( teamid ) 308 | 309 | 310 | -- Needs to choose class 311 | if ( Classes && #Classes > 1 ) then 312 | 313 | if ( ply:IsBot() || !GAMEMODE.SelectClass ) then 314 | 315 | GAMEMODE:PlayerRequestClass( ply, math.random( 1, #Classes ) ) 316 | 317 | else 318 | 319 | ply.m_fnCallAfterClassChoose = function() 320 | ply.DeathTime = CurTime() 321 | GAMEMODE:OnPlayerChangedTeam( ply, iOldTeam, teamid ) 322 | ply:EnableRespawn() 323 | end 324 | 325 | ply:SendLua( "GAMEMODE:ShowClassChooser( ".. teamid .." )" ) 326 | ply:DisableRespawn() 327 | ply:SetRandomClass() -- put the player in a VALID class in case they don't choose and get spawned 328 | return 329 | 330 | end 331 | 332 | end 333 | 334 | -- No class, use default 335 | if ( !Classes || #Classes == 0 ) then 336 | ply:SetPlayerClass( "Default" ) 337 | end 338 | 339 | -- Only one class, use that 340 | if ( Classes && #Classes == 1 ) then 341 | GAMEMODE:PlayerRequestClass( ply, 1 ) 342 | end 343 | 344 | gamemode.Call("OnPlayerChangedTeam", ply, iOldTeam, teamid ) 345 | 346 | end 347 | 348 | function GM:PlayerJoinClass( ply, classname ) 349 | 350 | ply.m_SpawnAsClass = nil 351 | ply:SetPlayerClass( classname ) 352 | 353 | if ( ply.m_fnCallAfterClassChoose ) then 354 | 355 | ply.m_fnCallAfterClassChoose() 356 | ply.m_fnCallAfterClassChoose = nil 357 | 358 | end 359 | 360 | end 361 | 362 | function GM:OnPlayerChangedTeam( ply, oldteam, newteam ) 363 | 364 | -- Here's an immediate respawn thing by default. If you want to 365 | -- re-create something more like CS or some shit you could probably 366 | -- change to a spectator or something while dead. 367 | if ( newteam == TEAM_SPECTATOR ) then 368 | 369 | -- If we changed to spectator mode, respawn where we are 370 | local Pos = ply:EyePos() 371 | ply:Spawn() 372 | ply:SetPos( Pos ) 373 | 374 | elseif ( oldteam == TEAM_SPECTATOR ) then 375 | 376 | -- If we're changing from spectator, join the game 377 | if ( !GAMEMODE.NoAutomaticSpawning ) then 378 | ply:Spawn() 379 | end 380 | 381 | elseif ( oldteam ~= TEAM_SPECTATOR ) then 382 | 383 | ply.LastTeamChange = CurTime() 384 | 385 | else 386 | 387 | -- If we're straight up changing teams just hang 388 | -- around until we're ready to respawn onto the 389 | -- team that we chose 390 | 391 | end 392 | 393 | --PrintMessage( HUD_PRINTTALK, Format( "%s joined '%s'", ply:Nick(), team.GetName( newteam ) ) ) 394 | 395 | -- Send net msg for team change 396 | 397 | net.Start( "fretta_teamchange" ) 398 | net.WriteEntity( ply ) 399 | net.WriteUInt( oldteam, 16 ) 400 | net.WriteUInt( newteam, 16 ) 401 | net.Broadcast() 402 | 403 | end 404 | 405 | function GM:CheckTeamBalance() 406 | 407 | local highest 408 | 409 | for id, tm in pairs( team.GetAllTeams() ) do 410 | if ( id > 0 && id < 1000 && team.Joinable( id ) ) then 411 | if ( !highest || team.NumPlayers( id ) > team.NumPlayers( highest ) ) then 412 | 413 | highest = id 414 | 415 | end 416 | end 417 | end 418 | 419 | if not highest then return end 420 | 421 | for id, tm in pairs( team.GetAllTeams() ) do 422 | if ( id ~= highest and id > 0 && id < 1000 && team.Joinable( id ) ) then 423 | if team.NumPlayers( id ) < team.NumPlayers( highest ) then 424 | while team.NumPlayers( id ) < team.NumPlayers( highest ) - 1 do 425 | 426 | local ply, reason = GAMEMODE:FindLeastCommittedPlayerOnTeam( highest ) 427 | 428 | ply:Kill() 429 | ply:SetTeam( id ) 430 | 431 | -- Todo: Notify player 'you have been swapped' 432 | -- This is a placeholder 433 | PrintMessage(HUD_PRINTTALK, ply:Name().." has been changed to "..team.GetName( id ).." for team balance. ("..reason..")" ) 434 | 435 | end 436 | end 437 | end 438 | end 439 | 440 | end 441 | 442 | function GM:FindLeastCommittedPlayerOnTeam( teamid ) 443 | 444 | local worst 445 | local worstteamswapper 446 | 447 | for k,v in pairs( team.GetPlayers( teamid ) ) do 448 | 449 | if ( v.LastTeamChange && CurTime() < v.LastTeamChange + 180 && (!worstteamswapper || worstteamswapper.LastTeamChange < v.LastTeamChange) ) then 450 | worstteamswapper = v 451 | end 452 | 453 | if ( !worst || v:Frags() < worst:Frags() ) then 454 | worst = v 455 | end 456 | 457 | end 458 | 459 | if worstteamswapper then 460 | return worstteamswapper, "They changed teams recently" 461 | end 462 | 463 | return worst, "Least points on their team" 464 | 465 | end 466 | 467 | function GM:OnEndOfGame(bGamemodeVote) 468 | 469 | for k,v in pairs( player.GetAll() ) do 470 | 471 | v:Freeze(true) 472 | v:ConCommand( "+showscores" ) 473 | 474 | end 475 | 476 | end 477 | 478 | -- Override OnEndOfGame to do any other stuff. like winning music. 479 | function GM:EndOfGame( bGamemodeVote ) 480 | 481 | if GAMEMODE.IsEndOfGame then return end 482 | 483 | GAMEMODE.IsEndOfGame = true 484 | SetGlobalBool( "IsEndOfGame", true ); 485 | 486 | gamemode.Call("OnEndOfGame", bGamemodeVote); 487 | 488 | if ( bGamemodeVote ) then 489 | 490 | MsgN( "Starting gamemode voting..." ) 491 | PrintMessage( HUD_PRINTTALK, "Starting gamemode voting..." ); 492 | timer.Simple( GAMEMODE.VotingDelay, function() GAMEMODE:StartGamemodeVote() end ) 493 | 494 | end 495 | 496 | end 497 | 498 | function GM:GetWinningFraction() 499 | if ( !GAMEMODE.GMVoteResults ) then return end 500 | return GAMEMODE.GMVoteResults.Fraction 501 | end 502 | 503 | function GM:PlayerShouldTakeDamage( ply, attacker ) 504 | 505 | if ( GAMEMODE.NoPlayerSelfDamage && IsValid( attacker ) && ply == attacker ) then return false end 506 | if ( GAMEMODE.NoPlayerDamage ) then return false end 507 | 508 | if ( GAMEMODE.NoPlayerTeamDamage && IsValid( attacker ) ) then 509 | if ( attacker.Team && ply:Team() == attacker:Team() && ply != attacker ) then return false end 510 | end 511 | 512 | if ( IsValid( attacker ) && attacker:IsPlayer() && GAMEMODE.NoPlayerPlayerDamage ) then return false end 513 | if ( IsValid( attacker ) && !attacker:IsPlayer() && GAMEMODE.NoNonPlayerPlayerDamage ) then return false end 514 | 515 | return true 516 | 517 | end 518 | 519 | 520 | function GM:PlayerDeathThink( pl ) 521 | 522 | pl.DeathTime = pl.DeathTime or CurTime() 523 | local timeDead = CurTime() - pl.DeathTime 524 | 525 | -- If we're in deathcam mode, promote to a generic spectator mode 526 | if ( GAMEMODE.DeathLingerTime > 0 && timeDead > GAMEMODE.DeathLingerTime && ( pl:GetObserverMode() == OBS_MODE_FREEZECAM || pl:GetObserverMode() == OBS_MODE_DEATHCAM ) ) then 527 | GAMEMODE:BecomeObserver( pl ) 528 | end 529 | 530 | -- If we're in a round based game, player NEVER spawns in death think 531 | if ( GAMEMODE.NoAutomaticSpawning ) then return end 532 | 533 | -- The gamemode is holding the player from respawning. 534 | -- Probably because they have to choose a class.. 535 | if ( !pl:CanRespawn() ) then return end 536 | 537 | -- Don't respawn yet - wait for minimum time... 538 | if ( GAMEMODE.MinimumDeathLength ) then 539 | 540 | pl:SetNWFloat( "RespawnTime", pl.DeathTime + GAMEMODE.MinimumDeathLength ) 541 | 542 | if ( timeDead < pl:GetRespawnTime() ) then 543 | return 544 | end 545 | 546 | end 547 | 548 | -- Force respawn 549 | if ( pl:GetRespawnTime() != 0 && GAMEMODE.MaximumDeathLength != 0 && timeDead > GAMEMODE.MaximumDeathLength ) then 550 | pl:Spawn() 551 | return 552 | end 553 | 554 | -- We're between min and max death length, player can press a key to spawn. 555 | if ( pl:KeyPressed( IN_ATTACK ) || pl:KeyPressed( IN_ATTACK2 ) || pl:KeyPressed( IN_JUMP ) ) then 556 | pl:Spawn() 557 | end 558 | 559 | end 560 | 561 | function GM:GetFallDamage( ply, flFallSpeed ) 562 | 563 | if ( GAMEMODE.RealisticFallDamage ) then 564 | return flFallSpeed / 8 565 | end 566 | 567 | return 10 568 | 569 | end 570 | 571 | function GM:PostPlayerDeath( ply ) 572 | 573 | -- Note, this gets called AFTER DoPlayerDeath.. AND it gets called 574 | -- for KillSilent too. So if Freezecam isn't set by DoPlayerDeath, we 575 | -- pick up the slack by setting DEATHCAM here. 576 | 577 | if ( ply:GetObserverMode() == OBS_MODE_NONE ) then 578 | ply:Spectate( OBS_MODE_DEATHCAM ) 579 | end 580 | 581 | ply:OnDeath() 582 | 583 | end 584 | 585 | function GM:DoPlayerDeath( ply, attacker, dmginfo ) 586 | 587 | ply:CallClassFunction( "OnDeath", attacker, dmginfo ) 588 | ply:CreateRagdoll() 589 | ply:AddDeaths( 1 ) 590 | 591 | if ( attacker:IsValid() && attacker:IsPlayer() ) then 592 | 593 | if ( attacker == ply ) then 594 | 595 | if ( GAMEMODE.TakeFragOnSuicide ) then 596 | 597 | attacker:AddFrags( -1 ) 598 | 599 | if ( GAMEMODE.TeamBased && GAMEMODE.AddFragsToTeamScore ) then 600 | team.AddScore( attacker:Team(), -1 ) 601 | end 602 | 603 | end 604 | 605 | else 606 | 607 | attacker:AddFrags( 1 ) 608 | 609 | if ( GAMEMODE.TeamBased && GAMEMODE.AddFragsToTeamScore ) then 610 | team.AddScore( attacker:Team(), 1 ) 611 | end 612 | 613 | end 614 | 615 | end 616 | 617 | if ( GAMEMODE.EnableFreezeCam && IsValid( attacker ) && attacker != ply ) then 618 | 619 | ply:SpectateEntity( attacker ) 620 | ply:Spectate( OBS_MODE_FREEZECAM ) 621 | 622 | end 623 | 624 | end 625 | 626 | function GM:StartSpectating( ply ) 627 | 628 | if ( !GAMEMODE:PlayerCanJoinTeam( ply ) ) then return end 629 | 630 | ply:StripWeapons(); 631 | GAMEMODE:PlayerJoinTeam( ply, TEAM_SPECTATOR ) 632 | GAMEMODE:BecomeObserver( ply ) 633 | 634 | end 635 | 636 | 637 | function GM:EndSpectating( ply ) 638 | 639 | if ( !GAMEMODE:PlayerCanJoinTeam( ply ) ) then return end 640 | 641 | GAMEMODE:PlayerJoinTeam( ply, TEAM_UNASSIGNED ) 642 | 643 | ply:KillSilent() 644 | 645 | end 646 | 647 | /*--------------------------------------------------------- 648 | Name: gamemode:PlayerRequestTeam() 649 | Player wants to change team 650 | ---------------------------------------------------------*/ 651 | function GM:PlayerRequestTeam( ply, teamid ) 652 | 653 | if ( !GAMEMODE.TeamBased && GAMEMODE.AllowSpectating ) then 654 | 655 | if ( teamid == TEAM_SPECTATOR ) then 656 | GAMEMODE:StartSpectating( ply ) 657 | else 658 | GAMEMODE:EndSpectating( ply ) 659 | end 660 | 661 | return 662 | 663 | end 664 | 665 | return self.BaseClass:PlayerRequestTeam( ply, teamid ) 666 | 667 | end 668 | 669 | local function TimeLeft( ply ) 670 | 671 | local tl = GAMEMODE:GetGameTimeLeft() 672 | if ( tl == -1 ) then return end 673 | 674 | local Time = util.ToMinutesSeconds( tl ) 675 | 676 | if ( IsValid( ply ) ) then 677 | ply:PrintMessage( HUD_PRINTCONSOLE, Time ) 678 | else 679 | MsgN( Time ) 680 | end 681 | 682 | end 683 | 684 | concommand.Add( "timeleft", TimeLeft ) --------------------------------------------------------------------------------