Initial Reupload

This commit is contained in:
Lucas Magnien 2019-05-28 09:16:53 +02:00
parent c7dea7beef
commit ded79721a1
368 changed files with 12298 additions and 2 deletions

38
.gitignore vendored Normal file
View File

@ -0,0 +1,38 @@
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

View File

@ -1,2 +1,67 @@
# ph-enhanced # Wolvin's - Prop Hunt: ENHANCED v.15 Rev. I
Prop Hunt: Enhanced - By Wolvindra [REUPLOAD]
![Prop Hunt: Enhanced Logo](https://i.ibb.co/7Yq3PhX/image.png "Prop Hunt: Enhanced v.15")
![Prop Hunt: Enhanced Cover](https://i.ibb.co/4PV3QSk/image.png "Prop Hunt: Enhanced v.15 New Main Menu")
## Base Information
**Version: 15, Revision: I, Release Type: Stopped/Hiatus**
Updates to address some exploits and other things. [See Changelog here](https://steamcommunity.com/sharedfiles/filedetails/changelog/417565863) for details.
## Upcoming "Version 16 Update" Notice
![Prop Hunt: Enhanced V16 Logo](https://i.ibb.co/gP5qzwc/phe.jpg "Prop Hunt: Enhanced v.16")
Version 16 will be the major update for the next version release of Prop Hunt: Enhanced. This also includes several changes and improvement for the gamemode which includes:
- Smoother Angle Rotation
- Prop Chooser UI*
- TauntURL*
- Minigame*
- New HUD, Help Menu, Scoreboard, and others
- Language Support
- Custom Taunt Additions (Workshop, from Data, etc)
- Pointshop Integration Support*
- and more...!
(* This is planned feature, which mean that this feature will be implemented or not based from user survey inputs)
[Support for V16 Release](https://ko-fi.com/post/Prop-Hunt-Enhanced-XVI---Teaser-T6T2OHNJ)
### Main gamemode Description
Prop Hunt: Enhanced is an enhanced version of Classic original **Prop Hunt** Gamemode. The gamemode is focused to be always maintained and fully customizable with many things.
The gamemode also includes several many major changes including the HUD, the code optimisation, Player skins, and other kind of additional features.
The gamemode was contributted to the old Classic Prop Hunt as for the fixes on march 2015 update (which completely broken) with the viewmodel fix additions. The classic version may no longer
maintained anymore.
### Available Links & Public Server Tests
#### Available Servers
- Soup Network: 103.193.80.135:28380
- GFL Clan Server: 208.103.169.70:27030
#### Links
[**Workshop Version**](https://steamcommunity.com/sharedfiles/filedetails/?id=417565863)
[**Main Website**](https://vinzuerio.bitbucket.io/phe)
[**Wiki (Helps, FAQ, Adding Custom Sound, etc)**](https://vinzuerio.bitbucket.io/phe/faq)
## Required Addons
* ULX Admin Mod. ( Workshop or Legacy Download: http://ulyssesmod.net/downloads.php )
* (Optional) M9K/TFA Base. You can optionally subscribe the M9K weapon base if you wish to use custom weapon base for bonus weapon, otherwise will use from default sandbox weapon base.
## Donate
Currently, The donation method can be done by using paypalme links: https://paypal.me/wolvindra or [use from this link](https://vinzuerio.bitbucket.io/phe/#donate).
Once the website is running active again, this will turn back to main official donation page instead.
## Reporting an Issue
### Reporting game issue (Bugs/Glitches)
Please provide information with detail so we know what's the actual problem that can occurs on your side. This issue page is not a place for asking help.
### Community Discussion Thread
If you wish to use help, please [open a discussion thread from workshop here](http://steamcommunity.com/sharedfiles/filedetails/discussions/417565863).

63
cfg/listenserver.cfg Normal file
View File

@ -0,0 +1,63 @@
hostname "My Prop Hunt Server"
sv_password ""
sv_lan 0
sv_region 255
// if these configs somehow won't load from your server, try remove any comments that marked as '//'.
// Fore more info about all configs:
// https://project.wolvindra.net/phe/new/faq/?dir=Config&gettopic=Common_Server_Config
// https://project.wolvindra.net/phe/new/faq/?dir=ConVars_and_ConCmds&gettopic=Serverside_ConVars
// https://project.wolvindra.net/phe/new/faq/?dir=ConVars_and_ConCmds&gettopic=MapVote_ConVars
p2p_enabled 0 // change this to 1 to enable P2P Mode.
p2p_friendsonly 0 // change this to 1 to only allow Friends Only P2P mode.
// PH: Enhanced - Gameplay settings
ph_hunter_fire_penalty 10
ph_hunter_kill_bonus 100
ph_swap_teams_every_round 1 //leave this as default.
ph_game_time 40 //minutes
ph_hunter_blindlock_time 30 //seconds
ph_round_time 300 //seconds
ph_rounds_per_map 10
ph_waitforplayers 1
ph_min_waitforplayers 1
//Verbosely prints any events of Prop Hunt: Enhanced.
ph_print_verbose 1
// PH: Enhanced - Props/Player settings
ph_use_custom_plmodel 1
ph_use_custom_plmodel_for_prop 1
ph_use_playermodeltype 0
ph_enable_plnames 0
ph_prop_camera_collisions 1
ph_prop_collision 1
ph_enable_custom_taunts 1
ph_autotaunt_enabled 1
ph_customtaunts_delay 4
ph_normal_taunt_delay 3
ph_autotaunt_delay 45
ph_prop_jumppower 1.4
ph_notice_prop_rotation 1
ph_enable_lucky_balls 1
// Freezecam Settings
ph_freezecam 1
ph_fc_use_single_sound 0
ph_fc_cue_path "misc/freeze_cam.wav"
// PH: Enhanced - MapVote
mv_allowcurmap 1 // 1/0, allow current map or not
mv_cooldown 1 // 1/0, enable cooldown
mv_mapbeforerevote 2 // number of each map should be cooldown
mv_maplimit 30 // allow 30 maps listed in mapvotes
mv_rtvcount 3 // Minimum players to allow MapVote
mv_timelimit 30 // Time in seconds to begin voting before changing the most choosen maps.
// Use map listing from ULX Mapvote? This convar will grab any whitelisted maps from your ULX Map List.
// 1 = use from ULX mapvote list (which you can whitelist them), 0 = use default maps/*.bsp directory listing.
mv_use_ulx_votemaps 0
// Map Prefixes to start with, for example: ph_ stands for Prop Hunt, de_ stands for CSS, etc...
mv_mapprefix "ph_,de_,fy_,"

68
cfg/server.cfg Normal file
View File

@ -0,0 +1,68 @@
hostname "My Prop Hunt Server"
sv_password ""
sv_lan 0
sv_region 255
// if these configs somehow won't load from your server, try remove any comments that marked as '//'.
// Fore more info about all configs:
// Read the Wiki:
// https://project.wolvindra.net/phe/new/faq/?dir=Config&gettopic=Common_Server_Config
// https://project.wolvindra.net/phe/new/faq/?dir=ConVars_and_ConCmds&gettopic=Serverside_ConVars
// https://project.wolvindra.net/phe/new/faq/?dir=ConVars_and_ConCmds&gettopic=MapVote_ConVars
// PH: Enhanced - Gameplay settings
ph_hunter_fire_penalty 10
ph_hunter_kill_bonus 100
ph_swap_teams_every_round 1 //leave this as default.
ph_game_time 40 //minutes
ph_hunter_blindlock_time 30 //seconds
ph_round_time 300 //seconds
ph_rounds_per_map 10
ph_waitforplayers 1
ph_min_waitforplayers 1
//Verbosely prints any events of Prop Hunt: Enhanced.
ph_print_verbose 1
// PH: Enhanced - Props/Player settings
ph_use_custom_plmodel 1
ph_use_custom_plmodel_for_prop 1
ph_use_playermodeltype 0
ph_enable_plnames 0
ph_prop_camera_collisions 1
ph_prop_collision 1
ph_enable_custom_taunts 1
ph_autotaunt_enabled 1
ph_customtaunts_delay 4
ph_normal_taunt_delay 3
ph_autotaunt_delay 45
ph_prop_jumppower 1.4
ph_notice_prop_rotation 1
ph_enable_lucky_balls 1
// Freezecam Settings
ph_freezecam 1
ph_fc_use_single_sound 0
ph_fc_cue_path "misc/freeze_cam.wav"
// PH: Enhanced - MapVote
mv_allowcurmap 1 // 1/0, allow current map or not
mv_cooldown 1 // 1/0, enable cooldown
mv_mapbeforerevote 2 // number of each map should be cooldown
mv_maplimit 30 // allow 30 maps listed in mapvotes
mv_rtvcount 3 // Minimum players to allow MapVote
mv_timelimit 30 // Time in seconds to begin voting before changing the most choosen maps.
// Use map listing from ULX Mapvote? This convar will grab any whitelisted maps from your ULX Map List.
// 1 = use from ULX mapvote list (which you can whitelist them), 0 = use default maps/*.bsp directory listing.
mv_use_ulx_votemaps 0
// Map Prefixes to start with, for example: ph_ stands for Prop Hunt, de_ stands for CSS, etc...
mv_mapprefix "ph_,de_,fy_,"
// Resource: Custom taunts downloads
sv_allowdownload 1
sv_allowupload 1
// Specify your fastdl address to make it available for downloads to the clients.
sv_downloadurl "http://yoursite/path_of_fastdl/"

View File

@ -0,0 +1,10 @@
"fretta"
{
"base" "base"
"title" "Fretta Gamemode Base"
"menusystem" "0"
"author_name" "TEAM GARRY"
"author_email" ""
"author_url" "http://www.garrysmod.com/"
}

View File

@ -0,0 +1,180 @@
-- di gamemodes\fretta\gamemode\cl_deathnotice.lua
-- Copy semuanya
/*
Start of the death message stuff.
*/
include( 'vgui/vgui_gamenotice.lua' )
local function CreateDeathNotify()
local x, y = ScrW(), ScrH()
g_DeathNotify = vgui.Create( "DNotify" )
g_DeathNotify:SetPos( 0, 25 )
g_DeathNotify:SetSize( x - ( 25 ), y )
g_DeathNotify:SetAlignment( 9 )
g_DeathNotify:SetSkin( GAMEMODE.HudSkin )
g_DeathNotify:SetLife( 4 )
g_DeathNotify:ParentToHUD()
end
hook.Add( "InitPostEntity", "CreateDeathNotify", CreateDeathNotify )
local function RecvPlayerKilledByPlayer()
local victim = net.ReadEntity();
local inflictor = net.ReadString();
local attacker = net.ReadEntity();
if ( !IsValid( attacker ) ) then return end
if ( !IsValid( victim ) ) then return end
GAMEMODE:AddDeathNotice( attacker:Name(), attacker:Team(), inflictor, victim:Name(), victim:Team() )
end
net.Receive( "PlayerKilledByPlayer", RecvPlayerKilledByPlayer )
local function RecvPlayerKilledSelf()
local victim = net.ReadEntity();
if ( !IsValid( victim ) ) then return end
GAMEMODE:AddDeathNotice( victim:Name(), victim:Team(), "suicide", victim:Name(), victim:Team() )
end
net.Receive( "PlayerKilledSelf", RecvPlayerKilledSelf )
local function RecvPlayerKilled()
local victim = net.ReadEntity();
if ( !IsValid( victim ) ) then return end
local inflictor = net.ReadString();
local attacker = "#" .. net.ReadString();
GAMEMODE:AddDeathNotice( attacker, -1, inflictor, victim:Name(), victim:Team() )
end
net.Receive( "PlayerKilled", RecvPlayerKilled )
local function RecvPlayerKilledNPC()
local victimtype = net.ReadString();
local victim = "#" .. victimtype;
local inflictor = net.ReadString();
local attacker = net.ReadEntity();
--
-- For some reason the killer isn't known to us, so don't proceed.
--
if ( !IsValid( attacker ) ) then return end
GAMEMODE:AddDeathNotice( attacker:Name(), attacker:Team(), inflictor, victim, -1 )
local bIsLocalPlayer = (IsValid(attacker) && attacker == LocalPlayer())
local bIsEnemy = IsEnemyEntityName( victimtype )
local bIsFriend = IsFriendEntityName( victimtype )
if ( bIsLocalPlayer && bIsEnemy ) then
achievements.IncBaddies();
end
if ( bIsLocalPlayer && bIsFriend ) then
achievements.IncGoodies();
end
if ( bIsLocalPlayer && (!bIsFriend && !bIsEnemy) ) then
achievements.IncBystander();
end
end
net.Receive( "PlayerKilledNPC", RecvPlayerKilledNPC )
local function RecvNPCKilledNPC()
local victim = "#" .. net.ReadString();
local inflictor = net.ReadString();
local attacker = "#" .. net.ReadString();
GAMEMODE:AddDeathNotice( attacker, -1, inflictor, victim, -1 )
end
net.Receive( "NPCKilledNPC", RecvNPCKilledNPC )
/*---------------------------------------------------------
Name: gamemode:AddDeathNotice( Victim, Weapon, Attacker )
Desc: Adds an death notice entry
---------------------------------------------------------*/
--function GM:AddDeathNotice( victim, inflictor, attacker )
function GM:AddDeathNotice( Attacker, team1, Inflictor, Victim , team2 )
local RdmDeathString = {
"suicided!",
"died mysteriously.",
"died from magic.",
"no-scoped themself.",
"has just ragequit.",
"is drunk.",
"died... better luck next time!",
"slapped themself.",
"tripped on a stick.",
"died by the force.",
"ragdolled."
}
local stringtext = table.Random( RdmDeathString )
if ( !IsValid( g_DeathNotify ) ) then return end
local pnl = vgui.Create( "GameNotice", g_DeathNotify )
local color1
local color2
if ( team1 == -1 ) then color1 = table.Copy( NPC_Color )
else color1 = table.Copy( team.GetColor( team1 ) ) end
if ( team2 == -1 ) then color2 = table.Copy( NPC_Color )
else color2 = table.Copy( team.GetColor( team2 ) ) end
if Victim == Attacker then
pnl:AddText( Attacker, color1)
pnl:AddText( stringtext )
else
pnl:AddText( Attacker, color1)
pnl:AddIcon( Inflictor )
pnl:AddText( Victim, color2 )
end
g_DeathNotify:AddItem( pnl )
end
function GM:AddPlayerAction( ... )
if ( !IsValid( g_DeathNotify ) ) then return end
local pnl = vgui.Create( "GameNotice", g_DeathNotify )
for k, v in ipairs({...}) do
pnl:AddText( v )
end
g_DeathNotify:AddItem( pnl )
end

View File

@ -0,0 +1,90 @@
g_PlayableGamemodes = {}
g_bGotGamemodesTable = false
function RcvPlayableGamemodes( length )
g_PlayableGamemodes = net.ReadTable()
g_bGotGamemodesTable = true
end
net.Receive( "PlayableGamemodes", RcvPlayableGamemodes );
local GMChooser = nil
local function GetVoteScreen()
if ( IsValid( GMChooser ) ) then return GMChooser end
GMChooser = vgui.Create( "VoteScreen" )
return GMChooser
end
function GM:ShowGamemodeChooser()
local votescreen = GetVoteScreen()
votescreen:ChooseGamemode()
end
function GM:GamemodeWon( mode )
local votescreen = GetVoteScreen()
votescreen:FlashItem( mode )
end
function GM:ChangingGamemode( mode, map )
local votescreen = GetVoteScreen()
votescreen:FlashItem( map )
end
function GM:ShowMapChooserForGamemode( gmname )
local votescreen = GetVoteScreen()
votescreen:ChooseMap( gmname )
end
local ClassChooser = nil
cl_classsuicide = CreateConVar( "cl_classsuicide", "0", { FCVAR_ARCHIVE } )
function GM:ShowClassChooser( TEAMID )
if ( !GAMEMODE.SelectClass ) then return end
if ( ClassChooser ) then ClassChooser:Remove() end
ClassChooser = vgui.CreateFromTable( vgui_Splash )
ClassChooser:SetHeaderText( "Choose Class" )
ClassChooser:SetHoverText( "What class do you want to be?" );
Classes = team.GetClass( TEAMID )
for k, v in SortedPairs( Classes ) do
local displayname = v
local Class = player_class.Get( v )
if ( Class && Class.DisplayName ) then
displayname = Class.DisplayName
end
local description = "Click to spawn as " .. displayname
if( Class and Class.Description ) then
description = Class.Description
end
local func = function() if( cl_classsuicide:GetBool() ) then RunConsoleCommand( "kill" ) end RunConsoleCommand( "changeclass", k ) end
local btn = ClassChooser:AddSelectButton( displayname, func, description )
btn.m_colBackground = team.GetColor( TEAMID )
end
ClassChooser:AddCancelButton()
ClassChooser:MakePopup()
ClassChooser:NoFadeIn()
end

View File

@ -0,0 +1,136 @@
local Help = nil
function GM:ShowHelp()
if ( !IsValid( Help ) ) then
Help = vgui.CreateFromTable( vgui_Splash )
Help:SetHeaderText( GAMEMODE.Name or "Untitled Gamemode" )
Help:SetHoverText( GAMEMODE.Help or "No Help Avaliable" );
Help.lblFooterText.Think = function( panel )
local tl = GAMEMODE:GetGameTimeLeft()
if ( tl == -1 ) then return end
if( GetGlobalBool( "IsEndOfGame", false ) ) then panel:SetText( "Game has ended..." ) return end
if( GAMEMODE.RoundBased && CurTime() > GAMEMODE:GetTimeLimit() ) then panel:SetText( "Game will end after this round" ) return end
panel:SetText( "Time Left: " .. util.ToMinutesSeconds( tl ) )
end
if ( GetConVarNumber( "fretta_voting" ) != 0 ) then
local btn = Help:AddSelectButton( "Vote For Change", function() RunConsoleCommand( "say", "rtv" ) end )
btn.m_colBackground = Color( 255, 200, 100 )
btn:SetDisabled( LocalPlayer():GetNWBool( "WantsVote" ) )
end
-- Internal Select buttons.
local btnadd = Help:AddSelectButton("Prop Hunt Menu", function()
LocalPlayer():ConCommand("ph_enhanced_show_help")
end)
btnadd.m_colBackground = Color(255,128,40)
-- Add a hook if you want to make another custom buttons by calling PH_AddSplashHelpButton.
hook.Call("PH_AddSplashHelpButton", nil, Help)
if ( GAMEMODE.TeamBased ) then
local btn = Help:AddSelectButton( "Change Team", function() GAMEMODE:ShowTeam() end )
btn.m_colBackground = Color( 120, 255, 100 )
end
if ( !GAMEMODE.TeamBased && GAMEMODE.AllowSpectating ) then
if ( LocalPlayer():Team() == TEAM_SPECTATOR ) then
local btn = Help:AddSelectButton( "Join Game", function() RunConsoleCommand( "changeteam", TEAM_UNASSIGNED ) end )
btn.m_colBackground = Color( 120, 255, 100 )
else
local btn = Help:AddSelectButton( "Spectate", function() RunConsoleCommand( "changeteam", TEAM_SPECTATOR ) end )
btn.m_colBackground = Color( 200, 200, 200 )
end
end
if ( IsValid( LocalPlayer() ) ) then
local TeamID = LocalPlayer():Team()
local Classes = team.GetClass( TeamID )
if ( Classes && #Classes > 1 ) then
local btn = Help:AddSelectButton( "Change Class", function() GAMEMODE:ShowClassChooser( LocalPlayer():Team() ) end )
btn.m_colBackground = Color( 120, 255, 100 )
end
end
Help:AddCancelButton()
if ( GAMEMODE.SelectModel ) then
local function CreateModelPanel()
local pnl = vgui.Create( "DGrid" )
pnl:SetCols( 6 )
pnl:SetColWide( 66 )
pnl:SetRowHeight( 66 )
for name, model in pairs( list.Get( "PlayerOptionsModel" ) ) do
local icon = vgui.Create( "SpawnIcon" )
icon.DoClick = function() surface.PlaySound( "ui/buttonclickrelease.wav" ) RunConsoleCommand( "cl_playermodel", name ) end
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
icon:SetModel( model )
icon:SetSize( 64, 64 )
icon:SetTooltip( name )
pnl:AddItem( icon )
end
return pnl
end
Help:AddPanelButton( "icon16/user.png", "Choose Player Model", CreateModelPanel )
end
if ( GAMEMODE.SelectColor ) then
local function CreateColorPanel()
local pnl = vgui.Create( "DGrid" )
pnl:SetCols( 10 )
pnl:SetColWide( 36 )
pnl:SetRowHeight( 128 )
for name, colr in pairs( list.Get( "PlayerColours" ) ) do
local icon = vgui.Create( "DButton" )
icon:SetText( "" )
icon.DoClick = function() surface.PlaySound( "ui/buttonclickrelease.wav" ) RunConsoleCommand( "cl_playercolor", name ) end
icon.Paint = function() surface.SetDrawColor( colr ) icon:DrawFilledRect() end
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
icon:SetSize( 32, 128 )
icon:SetTooltip( name )
pnl:AddItem( icon )
end
return pnl
end
Help:AddPanelButton( "icon16/application_view_tile.png", "Choose Player Color", CreateColorPanel )
end
end
Help:MakePopup()
Help:NoFadeIn()
end

View File

@ -0,0 +1,291 @@
local hudScreen = nil
local Alive = false
local Class = nil
local Team = 0
local WaitingToRespawn = false
local InRound = false
local RoundResult = 0
local RoundWinner = nil
local IsObserver = false
local ObserveMode = 0
local ObserveTarget = NULL
local InVote = false
function GM:AddHUDItem( item, pos, parent )
hudScreen:AddItem( item, parent, pos )
end
function GM:HUDNeedsUpdate()
if ( !IsValid( LocalPlayer() ) ) then return false end
if ( Class != LocalPlayer():GetNWString( "Class", "Default" ) ) then return true end
if ( Alive != LocalPlayer():Alive() ) then return true end
if ( Team != LocalPlayer():Team() ) then return true end
if ( WaitingToRespawn != ( (LocalPlayer():GetNWFloat( "RespawnTime", 0 ) > CurTime()) && LocalPlayer():Team() != TEAM_SPECTATOR && !LocalPlayer():Alive()) ) then return true end
if ( InRound != GetGlobalBool( "InRound", false ) ) then return true end
if ( RoundResult != GetGlobalInt( "RoundResult", 0 ) ) then return true end
if ( RoundWinner != GetGlobalEntity( "RoundWinner", nil ) ) then return true end
if ( IsObserver != LocalPlayer():IsObserver() ) then return true end
if ( ObserveMode != LocalPlayer():GetObserverMode() ) then return true end
if ( ObserveTarget != LocalPlayer():GetObserverTarget() ) then return true end
if ( InVote != GAMEMODE:InGamemodeVote() ) then return true end
return false
end
function GM:OnHUDUpdated()
Class = LocalPlayer():GetNWString( "Class", "Default" )
Alive = LocalPlayer():Alive()
Team = LocalPlayer():Team()
WaitingToRespawn = (LocalPlayer():GetNWFloat( "RespawnTime", 0 ) > CurTime()) && LocalPlayer():Team() != TEAM_SPECTATOR && !Alive
InRound = GetGlobalBool( "InRound", false )
RoundResult = GetGlobalInt( "RoundResult", 0 )
RoundWinner = GetGlobalEntity( "RoundWinner", nil )
IsObserver = LocalPlayer():IsObserver()
ObserveMode = LocalPlayer():GetObserverMode()
ObserveTarget = LocalPlayer():GetObserverTarget()
InVote = GAMEMODE:InGamemodeVote()
end
function GM:OnHUDPaint()
end
function GM:RefreshHUD()
if ( !GAMEMODE:HUDNeedsUpdate() ) then return end
GAMEMODE:OnHUDUpdated()
if ( IsValid( hudScreen ) ) then hudScreen:Remove() end
hudScreen = vgui.Create( "DHudLayout" )
if ( InVote ) then return end
if ( RoundWinner and RoundWinner != NULL ) then
GAMEMODE:UpdateHUD_RoundResult( RoundWinner, Alive )
elseif ( RoundResult != 0 ) then
GAMEMODE:UpdateHUD_RoundResult( RoundResult, Alive )
elseif ( IsObserver ) then
GAMEMODE:UpdateHUD_Observer( WaitingToRespawn, InRound, ObserveMode, ObserveTarget )
elseif ( !Alive ) then
GAMEMODE:UpdateHUD_Dead( WaitingToRespawn, InRound )
else
GAMEMODE:UpdateHUD_Alive( InRound )
if ( GetGlobalBool( "RoundWaitForPlayers" ) && ( ( team.NumPlayers( TEAM_HUNTERS ) < 1 ) || ( team.NumPlayers( TEAM_PROPS ) < 1 ) ) ) then
GAMEMODE:UpdateHUD_WaitForPlayers( InRound )
end
end
end
function GM:HUDPaint()
self.BaseClass:HUDPaint()
GAMEMODE:OnHUDPaint()
GAMEMODE:RefreshHUD()
end
function GM:UpdateHUD_WaitForPlayers( InRound )
if ( InRound && Alive ) then
local WaitText = vgui.Create( "DHudElement" );
WaitText:SizeToContents()
WaitText:SetText( "Waiting for players..." )
GAMEMODE:AddHUDItem( WaitText, 8 )
end
end
function GM:UpdateHUD_RoundResult( RoundResult, Alive )
local txt = GetGlobalString( "RRText" )
if ( type( RoundResult ) == "number" ) && ( team.GetAllTeams()[ RoundResult ] && txt == "" ) then
local TeamName = team.GetName( RoundResult )
if ( TeamName ) then txt = TeamName .. " Wins!" end
elseif ( type( RoundResult ) == "Player" && IsValid( RoundResult ) && txt == "" ) then
txt = RoundResult:Name() .. " Wins!"
end
local RespawnText = vgui.Create( "DHudElement" );
RespawnText:SizeToContents()
RespawnText:SetText( txt )
GAMEMODE:AddHUDItem( RespawnText, 8 )
end
function GM:UpdateHUD_Observer( bWaitingToSpawn, InRound, ObserveMode, ObserveTarget )
local lbl = nil
local txt = nil
local col = Color( 255, 255, 255 );
if ( IsValid( ObserveTarget ) && ObserveTarget:IsPlayer() && ObserveTarget != LocalPlayer() && ObserveMode != OBS_MODE_ROAMING ) then
lbl = "SPECTATING"
txt = ObserveTarget:Nick()
col = team.GetColor( ObserveTarget:Team() );
end
if ( ObserveMode == OBS_MODE_DEATHCAM || ObserveMode == OBS_MODE_FREEZECAM ) then
txt = "You Died!" // were killed by?
end
if ( txt ) then
local txtLabel = vgui.Create( "DHudElement" );
txtLabel:SetText( txt )
if ( lbl ) then txtLabel:SetLabel( lbl ) end
txtLabel:SetTextColor( col )
GAMEMODE:AddHUDItem( txtLabel, 2 )
end
GAMEMODE:UpdateHUD_Dead( bWaitingToSpawn, InRound )
end
function GM:UpdateHUD_Dead( bWaitingToSpawn, InRound )
if ( !InRound && GAMEMODE.RoundBased ) then
local RespawnText = vgui.Create( "DHudElement" );
RespawnText:SizeToContents()
RespawnText:SetText( "Waiting for round start" )
GAMEMODE:AddHUDItem( RespawnText, 8 )
return
end
if ( bWaitingToSpawn ) then
local RespawnTimer = vgui.Create( "DHudCountdown" );
RespawnTimer:SizeToContents()
RespawnTimer:SetValueFunction( function() return LocalPlayer():GetNWFloat( "RespawnTime", 0 ) end )
RespawnTimer:SetLabel( "SPAWN IN" )
GAMEMODE:AddHUDItem( RespawnTimer, 8 )
return
end
--[[
if ( InRound ) then
local RoundTimer = vgui.Create( "DHudCountdown" );
RoundTimer:SizeToContents()
RoundTimer:SetValueFunction( function()
if ( GetGlobalFloat( "RoundStartTime", 0 ) > CurTime() ) then return GetGlobalFloat( "RoundStartTime", 0 ) end
return GetGlobalFloat( "RoundEndTime" ) end )
RoundTimer:SetLabel( "TIME" )
GAMEMODE:AddHUDItem( RoundTimer, 8 )
return
end
]]--
local Bar = vgui.Create( "DHudBar" )
GAMEMODE:AddHUDItem( Bar, 8 )
-- This should show on dead players too
if ( InRound ) then
local TeamIndicator_Name_AddString = "(DEAD) "
if ( LocalPlayer():Team() == TEAM_SPECTATOR ) then TeamIndicator_Name_AddString = "" end
local TeamIndicator = vgui.Create( "DHudUpdater" );
TeamIndicator:SizeToContents()
TeamIndicator:SetValueFunction( function()
return TeamIndicator_Name_AddString..""..team.GetName( LocalPlayer():Team() )
end )
TeamIndicator:SetColorFunction( function()
return team.GetColor( LocalPlayer():Team() )
end )
TeamIndicator:SetFont( "HudSelectionText" )
Bar:AddItem( TeamIndicator )
local RoundNumber = vgui.Create( "DHudUpdater" );
RoundNumber:SizeToContents()
RoundNumber:SetValueFunction( function() return GetGlobalInt( "RoundNumber", 0 ) end )
RoundNumber:SetLabel( "ROUND" )
Bar:AddItem( RoundNumber )
local RoundTimer = vgui.Create( "DHudCountdown" );
RoundTimer:SizeToContents()
RoundTimer:SetValueFunction( function()
if ( GetGlobalFloat( "RoundStartTime", 0 ) > CurTime() ) then return GetGlobalFloat( "RoundStartTime", 0 ) end
return GetGlobalFloat( "RoundEndTime" ) end )
RoundTimer:SetLabel( "TIME" )
Bar:AddItem( RoundTimer )
end
if ( Team != TEAM_SPECTATOR && !Alive && !GAMEMODE.RoundBased ) then
local RespawnText = vgui.Create( "DHudElement" );
RespawnText:SizeToContents()
RespawnText:SetText( "Press Fire to Spawn" )
GAMEMODE:AddHUDItem( RespawnText, 8 )
end
end
function GM:UpdateHUD_Alive( InRound )
if ( GAMEMODE.RoundBased || GAMEMODE.TeamBased ) then
local Bar = vgui.Create( "DHudBar" )
GAMEMODE:AddHUDItem( Bar, 2 )
if ( GAMEMODE.TeamBased && GAMEMODE.ShowTeamName ) then
local TeamIndicator = vgui.Create( "DHudUpdater" );
TeamIndicator:SizeToContents()
TeamIndicator:SetValueFunction( function()
return team.GetName( LocalPlayer():Team() )
end )
TeamIndicator:SetColorFunction( function()
return team.GetColor( LocalPlayer():Team() )
end )
TeamIndicator:SetFont( "HudSelectionText" )
Bar:AddItem( TeamIndicator )
end
if ( GAMEMODE.RoundBased ) then
local RoundNumber = vgui.Create( "DHudUpdater" );
RoundNumber:SizeToContents()
RoundNumber:SetValueFunction( function() return GetGlobalInt( "RoundNumber", 0 ) end )
RoundNumber:SetLabel( "ROUND" )
Bar:AddItem( RoundNumber )
local RoundTimer = vgui.Create( "DHudCountdown" );
RoundTimer:SizeToContents()
RoundTimer:SetValueFunction( function()
if ( GetGlobalFloat( "RoundStartTime", 0 ) > CurTime() ) then return GetGlobalFloat( "RoundStartTime", 0 ) end
return GetGlobalFloat( "RoundEndTime" ) end )
RoundTimer:SetLabel( "TIME" )
Bar:AddItem( RoundTimer )
end
end
end
--[[
this thing is obsolete/depcretaed. Sorry!
function GM:UpdateHUD_AddedTime( iTimeAdded )
// to do or to override, your choice
end
usermessage.Hook( "RoundAddedTime", function( um ) if( GAMEMODE && um ) then GAMEMODE:UpdateHUD_AddedTime( um:ReadFloat() ) end end )
]]--

View File

@ -0,0 +1,198 @@
function surface.CreateLegacyFont(font, size, weight, antialias, additive, name, shadow, outline, blursize)
surface.CreateFont(name, {font = font, size = size, weight = weight, antialias = antialias, additive = additive, shadow = shadow, outline = outline, blursize = blursize})
end
include( 'shared.lua' )
include( 'cl_splashscreen.lua' )
include( 'cl_selectscreen.lua' )
include( 'cl_gmchanger.lua' )
include( 'cl_help.lua' )
include( 'skin.lua' )
include( 'vgui/vgui_hudlayout.lua' )
include( 'vgui/vgui_hudelement.lua' )
include( 'vgui/vgui_hudbase.lua' )
include( 'vgui/vgui_hudcommon.lua' )
include( 'cl_hud.lua' )
include( 'cl_deathnotice.lua' )
include( 'cl_scores.lua' )
include( 'cl_notify.lua' )
language.Add( "env_laser", "Laser" )
language.Add( "env_explosion", "Explosion" )
language.Add( "func_door", "Door" )
language.Add( "func_door_rotating", "Door" )
language.Add( "trigger_hurt", "Hazard" )
language.Add( "func_rotating", "Hazard" )
language.Add( "worldspawn", "Gravity" )
language.Add( "prop_physics", "Prop" )
language.Add( "prop_physics_respawnable", "Prop" )
language.Add( "prop_physics_multiplayer", "Prop" )
language.Add( "entityflame", "Fire" )
surface.CreateLegacyFont( "Roboto", 40, 700, true, false, "FRETTA_HUGE" )
surface.CreateLegacyFont( "Roboto", 40, 700, true, false, "FRETTA_HUGE_SHADOW", true )
surface.CreateLegacyFont( "Roboto", 24, 700, true, false, "FRETTA_LARGE" )
surface.CreateLegacyFont( "Roboto", 24, 700, true, false, "FRETTA_LARGE_SHADOW", true )
surface.CreateLegacyFont( "Roboto", 19, 700, true, false, "FRETTA_MEDIUM" )
surface.CreateLegacyFont( "Roboto", 19, 700, true, false, "FRETTA_MEDIUM_SHADOW", true )
surface.CreateLegacyFont( "Roboto", 16, 700, true, false, "FRETTA_SMALL" )
surface.CreateLegacyFont( "Roboto", ScreenScale( 10 ), 700, true, false, "FRETTA_NOTIFY", true )
CreateClientConVar( "cl_spec_mode", "5", true, true )
function GM:Initialize()
self.BaseClass:Initialize()
end
function GM:InitPostEntity()
if ( GAMEMODE.TeamBased ) then
GAMEMODE:ShowTeam();
end
GAMEMODE:ShowSplash();
end
local CircleMat = Material( "SGM/playercircle" );
function GM:DrawPlayerRing( pPlayer )
if ( !IsValid( pPlayer ) ) then return end
if ( !pPlayer:GetNWBool( "DrawRing", false ) ) then return end
if ( !pPlayer:Alive() ) then return end
local trace = {}
trace.start = pPlayer:GetPos() + Vector(0,0,50)
trace.endpos = trace.start + Vector(0,0,-300)
trace.filter = pPlayer
local tr = util.TraceLine( trace )
if not tr.HitWorld then
tr.HitPos = pPlayer:GetPos()
end
local color = table.Copy( team.GetColor( pPlayer:Team() ) )
color.a = 40;
render.SetMaterial( CircleMat )
render.DrawQuadEasy( tr.HitPos + tr.HitNormal, tr.HitNormal, GAMEMODE.PlayerRingSize, GAMEMODE.PlayerRingSize, color )
end
hook.Add( "PrePlayerDraw", "DrawPlayerRing", function( ply ) GAMEMODE:DrawPlayerRing( ply ) end )
function GM:HUDShouldDraw( name )
if GAMEMODE.ScoreboardVisible then return false end
// commented out until HUD elements are made
//for k, v in pairs{"CHudHealth", "CHudBattery", "CHudAmmo", "CHudSecondaryAmmo"} do
// if name == v then return false end
//end
if name == "CHudDamageIndicator" and not LocalPlayer():Alive() then
return false
end
return true
end
function GM:OnSpawnMenuOpen()
RunConsoleCommand( "lastinv" ); // Fretta is derived from base and has no spawn menu, so give it a use, make it lastinv.
end
function GM:PlayerBindPress( pl, bind, down )
// Redirect binds to the spectate system
if ( pl:IsObserver() && down ) then
if ( bind == "+jump" ) then RunConsoleCommand( "spec_mode" ) end
if ( bind == "+attack" ) then RunConsoleCommand( "spec_next" ) end
if ( bind == "+attack2" ) then RunConsoleCommand( "spec_prev" ) end
end
return false
end
/*---------------------------------------------------------
Name: gamemode:GetTeamColor( ent )
---------------------------------------------------------*/
function GM:GetTeamColor( ent )
if ( GAMEMODE.SelectColor && IsValid( ent ) ) then
local clr = ent:GetNWString( "NameColor", -1 )
if ( clr && clr != -1 && clr != "" ) then
clr = list.Get( "PlayerColours" )[ clr ]
if ( clr ) then return clr end
end
end
local team = TEAM_UNASSIGNED
if ( ent.Team and IsValid(ent) ) then team = ent:Team() end
return GAMEMODE:GetTeamNumColor( team )
end
/*---------------------------------------------------------
Name: ShouldDrawLocalPlayer
---------------------------------------------------------*/
function GM:ShouldDrawLocalPlayer( ply )
return ply:CallClassFunction( "ShouldDrawLocalPlayer" )
end
/*---------------------------------------------------------
Name: InputMouseApply
---------------------------------------------------------*/
function GM:InputMouseApply( cmd, x, y, angle )
return LocalPlayer():CallClassFunction( "InputMouseApply", cmd, x, y, angle )
end
function GM:TeamChangeNotification( ply, oldteam, newteam )
local random_spectator_text = {
"to watch and chill.",
"to see them hanging around.",
" ", -- you serious?
"to see the things."
}
if( ply && ply:IsValid() ) then
local nick = ply:Nick();
local oldTeamColor = team.GetColor( oldteam );
local newTeamName = team.GetName( newteam );
local newTeamColor = team.GetColor( newteam );
if( newteam == TEAM_SPECTATOR ) then
chat.AddText( oldTeamColor, nick, color_white, " joined the ", newTeamColor, newTeamName , color_white, " "..table.Random(random_spectator_text));
else
chat.AddText( oldTeamColor, nick, color_white, " joined ", newTeamColor, newTeamName );
end
surface.PlaySound("buttons/button17.wav")
end
end
net.Receive("fretta_teamchange", function()
local ply = net.ReadEntity()
local oldt = net.ReadInt(12)
local newt = net.ReadInt(12)
if (GAMEMODE) then
GAMEMODE:TeamChangeNotification(ply, oldt, newt)
end
end)

View File

@ -0,0 +1,26 @@
local function CreateLeftNotify()
local x, y = chat.GetChatBoxPos()
g_LeftNotify = vgui.Create( "DNotify" )
g_LeftNotify:SetPos( 32, 0 )
g_LeftNotify:SetSize( ScrW(), y - 8 )
g_LeftNotify:SetAlignment( 1 )
g_LeftNotify:ParentToHUD()
end
hook.Add( "InitPostEntity", "CreateLeftNotify", CreateLeftNotify )
function GM:NotifyGMVote( name, gamemode, votesneeded )
local dl = vgui.Create( "DLabel" )
dl:SetFont( "FRETTA_MEDIUM_SHADOW" )
dl:SetTextColor( Color( 255, 255, 255, 255 ) )
dl:SetText( Format( "%s voted for %s (need %i more)", name, gamemode, votesneeded ) )
dl:SizeToContents()
g_LeftNotify:AddItem( dl, 5 )
end

View File

@ -0,0 +1,138 @@
include( "vgui/vgui_scoreboard.lua" )
function GM:GetScoreboard()
if ( IsValid( g_ScoreBoard ) ) then
g_ScoreBoard:Remove()
end
g_ScoreBoard = vgui.Create( "FrettaScoreboard" )
self:CreateScoreboard( g_ScoreBoard )
return g_ScoreBoard
end
function GM:ScoreboardShow()
GAMEMODE:GetScoreboard():SetVisible( true )
GAMEMODE:PositionScoreboard( GAMEMODE:GetScoreboard() )
end
function GM:ScoreboardHide()
GAMEMODE:GetScoreboard():SetVisible( false )
end
function GM:AddScoreboardAvatar( ScoreBoard )
local f = function( ply )
local av = vgui.Create( "AvatarImage", ScoreBoard )
av:SetSize( 32, 32 )
av:SetPlayer( ply )
av.Click = function()
print( "LOL" )
end
return av
end
ScoreBoard:AddColumn( "", 32, f, 360 ) // Avatar
end
function GM:AddScoreboardSpacer( ScoreBoard, iSize )
ScoreBoard:AddColumn( "", 16 )
end
function GM:AddScoreboardName( ScoreBoard )
local f = function( ply ) return ply:Name() end
ScoreBoard:AddColumn( "Name", nil, f, 10, nil, 4, 4 )
end
function GM:AddScoreboardKills( ScoreBoard )
local f = function( ply ) return ply:Frags() end
ScoreBoard:AddColumn( "Kills", 40, f, 0.5, nil, 6, 6 )
end
function GM:AddScoreboardDeaths( ScoreBoard )
local f = function( ply ) return ply:Deaths() end
ScoreBoard:AddColumn( "Deaths", 60, f, 0.5, nil, 6, 6 )
end
function GM:AddScoreboardPing( ScoreBoard )
local f = function( ply ) return ply:ScoreboardPing() end
ScoreBoard:AddColumn( "Ping", 40, f, 0.1, nil, 6, 6 )
end
// THESE SHOULD BE THE ONLY FUNCTION YOU NEED TO OVERRIDE
function GM:PositionScoreboard( ScoreBoard )
if ( GAMEMODE.TeamBased ) then
ScoreBoard:SetSize( ScrW()/1.2, ScrH() - 50 )
ScoreBoard:SetPos( (ScrW() - ScoreBoard:GetWide()) * 0.5, 25 )
else
ScoreBoard:SetSize( 420, ScrH() - 64 )
ScoreBoard:SetPos( (ScrW() - ScoreBoard:GetWide()) / 2, 32 )
end
end
function GM:AddScoreboardWantsChange( ScoreBoard )
local f = function( ply )
if ( ply:GetNWBool( "WantsVote", false ) ) then
local lbl = vgui.Create( "DLabel" )
lbl:SetFont( "Marlett" )
lbl:SetText( "a" )
lbl:SetTextColor( Color( 100, 255, 0 ) )
lbl:SetContentAlignment( 5 )
return lbl
end
end
ScoreBoard:AddColumn( "", 16, f, 2, nil, 6, 6 )
end
function GM:CreateScoreboard( ScoreBoard )
// This makes it so that it's behind chat & hides when you're in the menu
// Disable this if you want to be able to click on stuff on your scoreboard
ScoreBoard:ParentToHUD()
ScoreBoard:SetRowHeight( 32 )
ScoreBoard:SetAsBullshitTeam( TEAM_SPECTATOR )
ScoreBoard:SetAsBullshitTeam( TEAM_CONNECTING )
ScoreBoard:SetShowScoreboardHeaders( GAMEMODE.TeamBased )
if ( GAMEMODE.TeamBased ) then
ScoreBoard:SetAsBullshitTeam( TEAM_UNASSIGNED )
ScoreBoard:SetHorizontal( true )
end
ScoreBoard:SetSkin( GAMEMODE.HudSkin )
self:AddScoreboardAvatar( ScoreBoard ) // 1
self:AddScoreboardWantsChange( ScoreBoard ) // 2
self:AddScoreboardName( ScoreBoard ) // 3
self:AddScoreboardKills( ScoreBoard ) // 4
self:AddScoreboardDeaths( ScoreBoard ) // 5
self:AddScoreboardPing( ScoreBoard ) // 6
// Here we sort by these columns (and descending), in this order. You can define up to 4
ScoreBoard:SetSortColumns( { 4, true, 5, false, 3, false } )
end

View File

@ -0,0 +1,317 @@
local CENTER_HEIGHT = 250
local PANEL = {}
/*---------------------------------------------------------
Init
---------------------------------------------------------*/
function PANEL:Init()
self:SetText( "" )
self.Buttons = {}
self.BottomButtons = {}
self:SetSkin( GAMEMODE.HudSkin )
self.pnlButtons = vgui.Create( "DPanelList", self )
self.pnlButtons:SetPadding( 10 )
self.pnlButtons:SetSpacing( 10 )
self.pnlButtons:SetDrawBackground( false )
self.pnlButtons:EnableVerticalScrollbar()
self.lblMain = vgui.Create( "DLabel", self )
self.lblMain:SetText( GAMEMODE.Name )
self.lblMain:SetFont( "FRETTA_HUGE" )
self.lblMain:SetColor( color_white )
self.pnlMain = vgui.Create( "DPanelList", self )
self.pnlMain:SetNoSizing( true )
self.pnlMain:SetDrawBackground( false )
self.pnlMain:EnableVerticalScrollbar()
self.btnCancel = vgui.Create( "DButton", self )
self.btnCancel:SetText( "#Close" )
self.btnCancel:SetSize( 100, 30 )
self.btnCancel:SetFGColor( Color( 0, 0, 0, 200 ) )
self.btnCancel:SetFont( "FRETTA_SMALL" )
self.btnCancel.DoClick = function() self:Remove() end
self.btnCancel:SetVisible( false )
Derma_Hook( self.btnCancel, "Paint", "Paint", "CancelButton" )
Derma_Hook( self.btnCancel, "PaintOver", "PaintOver", "CancelButton" )
Derma_Hook( self.btnCancel, "ApplySchemeSettings", "Scheme", "CancelButton" )
Derma_Hook( self.btnCancel, "PerformLayout", "Layout", "CancelButton" )
self.lblHoverText = vgui.Create( "DLabel", self )
self.lblHoverText:SetText( "" )
self.lblHoverText:SetFont( "FRETTA_MEDIUM" )
self.lblHoverText:SetColor( color_white )
self.lblHoverText:SetContentAlignment( 8 )
self.lblHoverText:SetWrap( true )
self.lblFooterText = vgui.Create( "DLabel", self )
self.lblFooterText:SetText( "" )
self.lblFooterText:SetFont( "FRETTA_MEDIUM" )
self.lblFooterText:SetColor( color_white )
self.lblFooterText:SetContentAlignment( 8 )
self.lblFooterText:SetWrap( false )
self.pnlMain:AddItem( self.lblHoverText )
self:PerformLayout()
self.OpenTime = SysTime()
end
function PANEL:NoFadeIn()
self.OpenTime = 0
end
/*---------------------------------------------------------
AddPanelButton
---------------------------------------------------------*/
function PANEL:AddPanelButton( icon, title, pnlfnc )
local btn = vgui.Create( "DImageButton", self )
btn:SetImage( icon )
btn:SetTooltip( title )
btn:SetSize( 30, 30 )
btn:SetVisible( true )
btn.pPanelFnc = pnlfnc
btn.pPanel = nil
btn:SetStretchToFit( false )
Derma_Hook( btn, "Paint", "Paint", "PanelButton" )
Derma_Hook( btn, "PaintOver", "PaintOver", "PanelButton" )
//Derma_Hook( btn, "ApplySchemeSettings", "Scheme", "PanelButton" )
//Derma_Hook( btn, "PerformLayout", "Layout", "PanelButton" )
local fnClick = function()
if ( !btn.pPanel ) then
btn.pPanel = btn.pPanelFnc()
btn.pPanel:SetParent( self.pnlMain )
btn.pPanel:SetVisible( false )
btn.pPanelFnc = nil
end
// Toggle off
if ( btn.m_bSelected ) then self:ClearSelectedPanel() return end
self:ClearSelectedPanel()
btn.m_bSelected = true
self.pnlMain:Clear()
btn.pPanel:SetVisible( true )
self.pnlMain:AddItem( btn.pPanel )
end
btn.DoClick = fnClick
table.insert( self.BottomButtons, btn )
return btn
end
function PANEL:ClearSelectedPanel()
self.pnlMain:Clear()
self.pnlMain:AddItem( self.lblHoverText )
for k, btn in pairs( self.BottomButtons ) do
btn.m_bSelected = false
if ( IsValid( btn.pPanel ) ) then
btn.pPanel:SetVisible( false )
end
end
end
/*---------------------------------------------------------
SetHeaderText
---------------------------------------------------------*/
function PANEL:SetHeaderText( strName )
self.lblMain:SetText( strName )
end
/*---------------------------------------------------------
SetHeaderText
---------------------------------------------------------*/
function PANEL:SetHoverText( strName )
self.lblHoverText:SetText( strName or "" )
end
/*---------------------------------------------------------
SetHeaderText
---------------------------------------------------------*/
function PANEL:GetHoverText( strName )
return self.lblHoverText:GetValue()
end
/*---------------------------------------------------------
AddSelectButton
---------------------------------------------------------*/
function PANEL:AddSelectButton( strName, fnFunction, txt )
local btn = vgui.Create( "DButton", self.pnlButtons )
btn:SetText( strName )
btn:SetSize( 200, 30 )
btn.DoClick = function() fnFunction() surface.PlaySound( Sound("buttons/lightswitch2.wav") ) self:Remove() end
Derma_Hook( btn, "Paint", "Paint", "SelectButton" )
Derma_Hook( btn, "PaintOver", "PaintOver", "SelectButton" )
Derma_Hook( btn, "ApplySchemeSettings", "Scheme", "SelectButton" )
Derma_Hook( btn, "PerformLayout", "Layout", "SelectButton" )
if ( txt ) then
btn.OnCursorEntered = function() self.OldHoverText = self:GetHoverText() self:SetHoverText( txt ) end
btn.OnCursorExited = function() self:SetHoverText( self.OldHoverText ) self.OldHoverText = nil end
end
self.pnlButtons:AddItem( btn )
table.insert( self.Buttons, btn )
return btn
end
/*---------------------------------------------------------
SetHeaderText
---------------------------------------------------------*/
function PANEL:AddSpacer( h )
local btn = vgui.Create( "Panel", self )
btn:SetSize( 200, h )
table.insert( self.Buttons, btn )
return btn
end
/*---------------------------------------------------------
SetHeaderText
---------------------------------------------------------*/
function PANEL:AddCancelButton()
self.btnCancel:SetVisible( true )
end
/*---------------------------------------------------------
PerformLayout
---------------------------------------------------------*/
function PANEL:PerformLayout()
self:SetSize( ScrW(), ScrH() )
local CenterY = ScrH() / 2.0
local CenterX = ScrW() / 2.0
local InnerWidth = 640
self.lblMain:SizeToContents()
self.lblMain:SetPos( ScrW() * 0.5 - self.lblMain:GetWide() * 0.5, CenterY - CENTER_HEIGHT - self.lblMain:GetTall() * 1.2 )
self.pnlButtons:SetPos( ScrW() * 0.5 - InnerWidth * 0.5, (CenterY - CENTER_HEIGHT) + 20 )
self.pnlButtons:SetSize( 210, (CENTER_HEIGHT * 2) - self.btnCancel:GetTall() - 20 - 20 - 20 )
self.btnCancel:SetPos( ScrW() * 0.5 + InnerWidth * 0.5 - self.btnCancel:GetWide(), CenterY + CENTER_HEIGHT - self.btnCancel:GetTall() - 20 )
self.lblHoverText:SetPos( ScrW() * 0.5 - InnerWidth * 0.5 + 50, (CenterY - 150) )
self.lblHoverText:SetSize( 300, 300 )
self.pnlMain:SetPos( self.pnlButtons.x + self.pnlButtons:GetWide() + 10, self.pnlButtons.y )
self.pnlMain:SetSize( InnerWidth - self.pnlButtons:GetWide() - 10, 400 )
self.lblFooterText:SetSize( ScrW(), 30 )
self.lblFooterText:SetPos( 0, CenterY + CENTER_HEIGHT + 10 )
local x = self.pnlButtons.x
for k, btn in pairs( self.BottomButtons ) do
btn:SetPos( x, CenterY + CENTER_HEIGHT - btn:GetTall() - 20 )
x = x + btn:GetWide() + 8
end
end
/*---------------------------------------------------------
Paint
---------------------------------------------------------*/
function PANEL:Paint()
Derma_DrawBackgroundBlur( self, self.OpenTime )
local CenterY = ScrH() / 2.0
local CenterX = ScrW() / 2.0
surface.SetDrawColor( 0, 0, 0, 200 );
surface.DrawRect( 0, CenterY - CENTER_HEIGHT, ScrW(), CENTER_HEIGHT * 2 );
surface.DrawRect( 0, CenterY - CENTER_HEIGHT - 4, ScrW(), 2 );
surface.DrawRect( 0, CenterY + CENTER_HEIGHT + 2, ScrW(), 2 );
GAMEMODE:PaintSplashScreen( self:GetWide(), self:GetTall() )
end
vgui_Splash = vgui.RegisterTable( PANEL, "DPanel" )
local TeamPanel = nil
function GM:ShowTeam()
if ( !IsValid( TeamPanel ) ) then
TeamPanel = vgui.CreateFromTable( vgui_Splash )
TeamPanel:SetHeaderText( "Choose Team" )
local AllTeams = team.GetAllTeams()
for ID, TeamInfo in SortedPairs ( AllTeams ) do
if ( ID != TEAM_CONNECTING && ID != TEAM_UNASSIGNED && ( ID != TEAM_SPECTATOR || GAMEMODE.AllowSpectating ) && team.Joinable(ID) ) then
if ( ID == TEAM_SPECTATOR ) then
TeamPanel:AddSpacer( 10 )
end
local strName = TeamInfo.Name
local func = function() RunConsoleCommand( "changeteam", ID ) end
local btn = TeamPanel:AddSelectButton( strName, func )
btn.m_colBackground = TeamInfo.Color
btn.Think = function( self )
self:SetText( Format( "%s (%i)", strName, team.NumPlayers( ID ) ))
self:SetDisabled( GAMEMODE:TeamHasEnoughPlayers( ID ) )
end
if ( IsValid( LocalPlayer() ) && LocalPlayer():Team() == ID ) then
btn:SetDisabled( true )
end
end
end
if ( IsValid( LocalPlayer() ) &&
( LocalPlayer():Team() == TEAM_UNASSIGNED or
LocalPlayer():Team() == TEAM_SPECTATOR or
LocalPlayer():Team() == TEAM_HUNTERS or
LocalPlayer():Team() == TEAM_PROPS ) ) then
TeamPanel:AddCancelButton()
end
end
TeamPanel:MakePopup()
end

View File

@ -0,0 +1,107 @@
local PANEL = {}
/*---------------------------------------------------------
Init
---------------------------------------------------------*/
function PANEL:Init()
self:SetText( "" )
self.DoClick = function() RunConsoleCommand( "seensplash" ) self:Remove() end
self:SetSkin( GAMEMODE.HudSkin )
self.lblGamemodeName = vgui.Create( "DLabel", self )
self.lblGamemodeName:SetText( GAMEMODE.Name )
self.lblGamemodeName:SetFont( "FRETTA_LARGE" )
self.lblGamemodeName:SetColor( color_white )
self.lblGamemodeAuthor = vgui.Create( "DLabel", self )
self.lblGamemodeAuthor:SetText( "by " .. GAMEMODE.Author )
self.lblGamemodeAuthor:SetFont( "FRETTA_MEDIUM" )
self.lblGamemodeAuthor:SetColor( color_white )
self.lblServerName = vgui.Create( "DLabel", self )
self.lblServerName:SetText( GetHostName() )
self.lblServerName:SetFont( "FRETTA_MEDIUM" )
self.lblServerName:SetColor( color_white )
self.lblIP = vgui.Create( "DLabel", self )
self.lblIP:SetText( "0.0.0.0" )
self.lblIP:SetFont( "FRETTA_MEDIUM" )
self.lblIP:SetColor( color_white )
self:PerformLayout()
self.FadeInTime = RealTime()
end
/*---------------------------------------------------------
PerformLayout
---------------------------------------------------------*/
function PANEL:PerformLayout()
self:SetSize( ScrW(), ScrH() )
local CenterY = ScrH() / 2.0
self.lblGamemodeName:SizeToContents()
self.lblGamemodeName:SetPos( ScrW()/2 - self.lblGamemodeName:GetWide()/2, CenterY - 200 - self.lblGamemodeName:GetTall() - self.lblGamemodeAuthor:GetTall() )
self.lblGamemodeAuthor:SizeToContents()
self.lblGamemodeAuthor:SetPos( ScrW()/2 - self.lblGamemodeAuthor:GetWide()/2, CenterY - 200 - self.lblGamemodeAuthor:GetTall() )
self.lblServerName:SizeToContents()
self.lblServerName:SetPos( 100, CenterY + 200 )
--self.lblIP:SetText( GetConVarString( "ip" ) )
self.lblIP:SetText( tostring(game.GetIPAddress()) )
self.lblIP:SizeToContents()
self.lblIP:SetPos( self:GetWide() - 100 - self.lblIP:GetWide(), CenterY + 200 )
end
/*---------------------------------------------------------
Paint
---------------------------------------------------------*/
function PANEL:Paint()
Derma_DrawBackgroundBlur( self )
local Fade = RealTime() - self.FadeInTime
if ( Fade < 3 ) then
Fade = 1- (Fade / 3);
surface.SetDrawColor( 0,0, 0, Fade * 255 );
surface.DrawRect( 0, 0, self:GetWide(), self:GetTall() );
end
local CenterY = ScrH() / 2.0
surface.SetDrawColor( 0, 0, 0, 200 );
surface.DrawRect( 0, 0, self:GetWide(), CenterY - 180 );
surface.DrawRect( 0, CenterY + 180, self:GetWide(), self:GetTall() - ( CenterY+ 180 ) );
GAMEMODE:PaintSplashScreen( self:GetWide(), self:GetTall() )
end
local vgui_Splash = vgui.RegisterTable( PANEL, "DButton" )
function GM:ShowSplash()
local pnl = vgui.CreateFromTable( vgui_Splash )
pnl:MakePopup()
end
function GM:PaintSplashScreen( w, h )
// Customised splashscreen render here ( The center bit! )
end

View File

@ -0,0 +1,65 @@
local CLASS = {}
CLASS.DisplayName = "Default Class"
CLASS.WalkSpeed = 400
CLASS.CrouchedWalkSpeed = 0.2
CLASS.RunSpeed = 600
CLASS.DuckSpeed = 0.2
CLASS.JumpPower = 200
--CLASS.PlayerModel = "models/player.mdl"
CLASS.PlayerModel = "models/player/combine_soldier.mdl"
CLASS.DrawTeamRing = false
CLASS.DrawViewModel = true
CLASS.CanUseFlashlight = true
CLASS.MaxHealth = 100
CLASS.StartHealth = 100
CLASS.StartArmor = 0
CLASS.RespawnTime = 0 // 0 means use the default spawn time chosen by gamemode
CLASS.DropWeaponOnDie = false
CLASS.TeammateNoCollide = true
CLASS.AvoidPlayers = true // Automatically avoid players that we're no colliding
CLASS.Selectable = true // When false, this disables all the team checking
CLASS.FullRotation = false // Allow the player's model to rotate upwards, etc etc
function CLASS:Loadout( pl )
pl:GiveAmmo( 255, "Pistol", true )
pl:Give( "weapon_pistol" )
end
function CLASS:OnSpawn( pl )
end
function CLASS:OnDeath( pl, attacker, dmginfo )
end
function CLASS:Think( pl )
end
function CLASS:Move( pl, mv )
end
function CLASS:OnKeyPress( pl, key )
end
function CLASS:OnKeyRelease( pl, key )
end
function CLASS:ShouldDrawLocalPlayer( pl )
return false
end
function CLASS:CalcView( ply, origin, angles, fov )
end
player_class.Register( "Default", CLASS )
local CLASS = {}
CLASS.DisplayName = "Spectator Class"
CLASS.DrawTeamRing = false
CLASS.PlayerModel = "models/player.mdl"
player_class.Register( "Spectator", CLASS )

View File

@ -0,0 +1,706 @@
/*
init.lua - Server Component
-----------------------------------------------------
The entire server side bit of Fretta starts here.
*/
util.AddNetworkString("PlayableGamemodes")
util.AddNetworkString("fretta_teamchange")
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
AddCSLuaFile( 'skin.lua' )
AddCSLuaFile( 'player_class.lua' )
AddCSLuaFile( 'class_default.lua' )
AddCSLuaFile( 'cl_splashscreen.lua' )
AddCSLuaFile( 'cl_selectscreen.lua' )
AddCSLuaFile( 'cl_gmchanger.lua' )
AddCSLuaFile( 'cl_help.lua' )
AddCSLuaFile( 'player_extension.lua' )
AddCSLuaFile( 'vgui/vgui_hudlayout.lua' )
AddCSLuaFile( 'vgui/vgui_hudelement.lua' )
AddCSLuaFile( 'vgui/vgui_hudbase.lua' )
AddCSLuaFile( 'vgui/vgui_hudcommon.lua' )
AddCSLuaFile( 'vgui/vgui_gamenotice.lua' )
AddCSLuaFile( 'vgui/vgui_scoreboard.lua' )
AddCSLuaFile( 'vgui/vgui_scoreboard_team.lua' )
AddCSLuaFile( 'vgui/vgui_scoreboard_small.lua' )
AddCSLuaFile( 'cl_hud.lua' )
AddCSLuaFile( 'cl_deathnotice.lua' )
AddCSLuaFile( 'cl_scores.lua' )
AddCSLuaFile( 'cl_notify.lua' )
AddCSLuaFile( 'player_colours.lua' )
include( "shared.lua" )
include( "sv_spectator.lua" )
include( "round_controller.lua" )
include( "utility.lua" )
GM.ReconnectedPlayers = {}
function GM:Initialize()
/*
// Disabled - causes games to end in the middle of a round - we don't want that to happen!
// ::Think takes care of this anyway.
if ( GAMEMODE.GameLength > 0 ) then
timer.Simple( GAMEMODE.GameLength * 60, function() GAMEMODE:EndOfGame( true ) end )
SetGlobalFloat( "GameEndTime", CurTime() + GAMEMODE.GameLength * 60 )
end
*/
// If we're round based, wait 3 seconds before the first round starts
--GAMEMODE:SetInRound( false ) --iguess?
if ( GAMEMODE.RoundBased ) then
timer.Simple( 3, function() GAMEMODE:StartRoundBasedGame() end )
end
if ( GAMEMODE.AutomaticTeamBalance ) then
timer.Create( "CheckTeamBalance", 30, 0, function() GAMEMODE:CheckTeamBalance() end )
end
end
function GM:Think()
self.BaseClass:Think()
for k,v in pairs( player.GetAll() ) do
local Class = v:GetPlayerClass()
if ( !Class ) then return end
v:CallClassFunction( "Think" )
end
// Game time related
if( !GAMEMODE.IsEndOfGame && ( !GAMEMODE.RoundBased || ( GAMEMODE.RoundBased && GAMEMODE:CanEndRoundBasedGame() ) ) && CurTime() >= GAMEMODE.GetTimeLimit() ) then
GAMEMODE:EndOfGame( true )
end
end
/*---------------------------------------------------------
Name: gamemode:CanPlayerSuicide( Player ply )
Desc: Is the player allowed to commit suicide?
---------------------------------------------------------*/
function GM:CanPlayerSuicide( ply )
if not GAMEMODE:InRound() then return false end
if( ply:Team() == TEAM_UNASSIGNED || ply:Team() == TEAM_SPECTATOR ) then
return false // no suicide in spectator mode
end
return !GAMEMODE.NoPlayerSuicide
end
/*---------------------------------------------------------
Name: gamemode:PlayerSwitchFlashlight( Player ply, Bool on )
Desc: Can we turn our flashlight on or off?
---------------------------------------------------------*/
function GM:PlayerSwitchFlashlight( ply, on )
if ( ply:Team() == TEAM_SPECTATOR || ply:Team() == TEAM_UNASSIGNED || ply:Team() == TEAM_CONNECTING ) then
return not on
end
return ply:CanUseFlashlight()
end
/*---------------------------------------------------------
Name: gamemode:PlayerInitialSpawn( Player ply )
Desc: Our very first spawn in the game.
---------------------------------------------------------*/
function GM:PlayerInitialSpawn( pl )
--pl:SetTeam( TEAM_UNASSIGNED )
pl:SetTeam( TEAM_SPECTATOR )
pl:SetPlayerClass( "Spectator" )
pl.m_bFirstSpawn = true
pl:UpdateNameColor()
GAMEMODE:CheckPlayerReconnected( pl )
end
function GM:CheckPlayerReconnected( pl )
if table.HasValue( GAMEMODE.ReconnectedPlayers, pl:UniqueID() ) then
GAMEMODE:PlayerReconnected( pl )
end
end
/*---------------------------------------------------------
Name: gamemode:PlayerReconnected( Player ply )
Desc: Called if the player has appeared to have reconnected.
---------------------------------------------------------*/
function GM:PlayerReconnected( pl )
// Use this hook to do stuff when a player rejoins and has been in the server previously
end
function GM:PlayerDisconnected( pl )
table.insert( GAMEMODE.ReconnectedPlayers, pl:UniqueID() )
self.BaseClass:PlayerDisconnected( pl )
end
function GM:ShowHelp( pl )
pl:SendLua( "GAMEMODE:ShowHelp()" )
end
function GM:PlayerSpawn( pl )
pl:UpdateNameColor()
// The player never spawns straight into the game in Fretta
// They spawn as a spectator first (during the splash screen and team picking screens)
if ( pl.m_bFirstSpawn ) then
pl.m_bFirstSpawn = nil
if ( pl:IsBot() ) then
GAMEMODE:AutoTeam( pl )
// The bot doesn't send back the 'seen splash' command, so fake it.
if ( !GAMEMODE.TeamBased && !GAMEMODE.NoAutomaticSpawning ) then
pl:Spawn()
end
else
pl:StripWeapons()
GAMEMODE:PlayerSpawnAsSpectator( pl )
// Follow a random player until we join a team
--[[
if ( #player.GetAll() > 1 ) then
pl:Spectate( OBS_MODE_CHASE )
pl:SpectateEntity( table.Random( player.GetAll() ) )
end
]]--
pl:Spectate( OBS_MODE_ROAMING )
end
return
end
pl:CheckPlayerClassOnSpawn()
if ( GAMEMODE.TeamBased && ( pl:Team() == TEAM_SPECTATOR || pl:Team() == TEAM_UNASSIGNED ) ) then
GAMEMODE:PlayerSpawnAsSpectator( pl )
return
end
// Stop observer mode
pl:UnSpectate()
// Call item loadout function
hook.Call( "PlayerLoadout", GAMEMODE, pl )
// Set player model
hook.Call( "PlayerSetModel", GAMEMODE, pl )
// Call class function
pl:OnSpawn()
end
function GM:PlayerLoadout( pl )
pl:CheckPlayerClassOnSpawn()
pl:OnLoadout()
// Switch to prefered weapon if they have it
local cl_defaultweapon = pl:GetInfo( "cl_defaultweapon" )
if ( pl:HasWeapon( cl_defaultweapon ) ) then
pl:SelectWeapon( cl_defaultweapon )
end
end
function GM:PlayerSetModel( pl )
pl:OnPlayerModel()
end
function GM:AutoTeam( pl )
if ( !GAMEMODE.AllowAutoTeam ) then return end
if ( !GAMEMODE.TeamBased ) then return end
GAMEMODE:PlayerRequestTeam( pl, team.BestAutoJoinTeam() )
end
concommand.Add( "autoteam", function( pl, cmd, args ) hook.Call( "AutoTeam", GAMEMODE, pl ) end )
function GM:PlayerRequestClass( ply, class, disablemessage )
local Classes = team.GetClass( ply:Team() )
if (!Classes) then return end
local RequestedClass = Classes[ class ]
if (!RequestedClass) then return end
if ( ply:Alive() && SERVER ) then
if ( ply.m_SpawnAsClass && ply.m_SpawnAsClass == RequestedClass ) then return end
ply.m_SpawnAsClass = RequestedClass
if ( !disablemessage ) then
ply:ChatPrint( "Your class will change to '".. player_class.GetClassName( RequestedClass ) .. "' when you respawn" )
end
else
self:PlayerJoinClass( ply, RequestedClass )
ply.m_SpawnAsClass = nil
end
end
concommand.Add( "changeclass", function( pl, cmd, args ) hook.Call( "PlayerRequestClass", GAMEMODE, pl, tonumber(args[1]) ) end )
local function SeenSplash( ply )
if ( ply.m_bSeenSplashScreen ) then return end
ply.m_bSeenSplashScreen = true
if ( !GAMEMODE.TeamBased && !GAMEMODE.NoAutomaticSpawning ) then
ply:KillSilent()
end
end
concommand.Add( "seensplash", SeenSplash )
function GM:PlayerJoinTeam( ply, teamid )
local iOldTeam = ply:Team()
if ( ply:Alive() ) then
if ( iOldTeam == TEAM_SPECTATOR || (iOldTeam == TEAM_UNASSIGNED && GAMEMODE.TeamBased) ) then
ply:KillSilent()
else
ply:Kill()
end
end
ply:SetTeam( teamid )
ply.LastTeamSwitch = RealTime()
local Classes = team.GetClass( teamid )
// Needs to choose class
if ( Classes && #Classes > 1 ) then
if ( ply:IsBot() || !GAMEMODE.SelectClass ) then
GAMEMODE:PlayerRequestClass( ply, math.random( 1, #Classes ) )
else
ply.m_fnCallAfterClassChoose = function()
ply.DeathTime = CurTime()
GAMEMODE:OnPlayerChangedTeam( ply, iOldTeam, teamid )
ply:EnableRespawn()
end
ply:SendLua( "GAMEMODE:ShowClassChooser( ".. teamid .." )" )
ply:DisableRespawn()
ply:SetRandomClass() // put the player in a VALID class in case they don't choose and get spawned
return
end
end
// No class, use default
if ( !Classes || #Classes == 0 ) then
ply:SetPlayerClass( "Default" )
end
// Only one class, use that
if ( Classes && #Classes == 1 ) then
GAMEMODE:PlayerRequestClass( ply, 1 )
end
gamemode.Call("OnPlayerChangedTeam", ply, iOldTeam, teamid )
end
function GM:PlayerJoinClass( ply, classname )
ply.m_SpawnAsClass = nil
ply:SetPlayerClass( classname )
if ( ply.m_fnCallAfterClassChoose ) then
ply.m_fnCallAfterClassChoose()
ply.m_fnCallAfterClassChoose = nil
end
end
function GM:OnPlayerChangedTeam( ply, oldteam, newteam )
// Here's an immediate respawn thing by default. If you want to
// re-create something more like CS or some shit you could probably
// change to a spectator or something while dead.
if ( newteam == TEAM_SPECTATOR ) then
// If we changed to spectator mode, respawn where we are
local Pos = ply:EyePos()
ply:Spawn()
ply:SetPos( Pos )
elseif ( oldteam == TEAM_SPECTATOR ) then
// If we're changing from spectator, join the game
if ( !GAMEMODE.NoAutomaticSpawning ) then
ply:Spawn()
end
elseif ( oldteam ~= TEAM_SPECTATOR ) then
ply.LastTeamChange = CurTime()
else
// If we're straight up changing teams just hang
// around until we're ready to respawn onto the
// team that we chose
end
//PrintMessage( HUD_PRINTTALK, Format( "%s joined '%s'", ply:Nick(), team.GetName( newteam ) ) )
// Send net for team change
net.Start("fretta_teamchange")
net.WriteEntity(ply)
net.WriteInt(oldteam, 12)
net.WriteInt(newteam, 12)
net.Broadcast()
end
function GM:CheckTeamBalance()
local highest
for id, tm in pairs( team.GetAllTeams() ) do
if ( id > 0 && id < 1000 && team.Joinable( id ) ) then
if ( !highest || team.NumPlayers( id ) > team.NumPlayers( highest ) ) then
highest = id
end
end
end
if not highest then return end
for id, tm in pairs( team.GetAllTeams() ) do
if ( id ~= highest and id > 0 && id < 1000 && team.Joinable( id ) ) then
if team.NumPlayers( id ) < team.NumPlayers( highest ) then
while team.NumPlayers( id ) < team.NumPlayers( highest ) - 1 do
local ply = GAMEMODE:FindLeastCommittedPlayerOnTeam( highest )
ply:Kill()
ply:SetTeam( id )
// Todo: Notify player 'you have been swapped'
// This is a placeholder
PrintMessage(HUD_PRINTTALK, ply:Name().." has been changed to "..team.GetName( id ).." for team balance." )
end
end
end
end
end
function GM:FindLeastCommittedPlayerOnTeam( teamid )
local worst
local worstteamswapper
for k,v in pairs( team.GetPlayers( teamid ) ) do
if ( v.LastTeamChange && CurTime() < v.LastTeamChange + 180 && (!worstteamswapper || worstteamswapper.LastTeamChange < v.LastTeamChange) ) then
worstteamswapper = v
end
if ( !worst || v:Frags() < worst:Frags() ) then
worst = v
end
end
if worstteamswapper then
return worstteamswapper
end
return worst
end
function GM:OnEndOfGame(bGamemodeVote)
for k,v in pairs( player.GetAll() ) do
v:Freeze(true)
v:ConCommand( "+showscores" )
timer.Simple(GAMEMODE.VotingDelay, function()
if (IsValid(v)) then
v:ConCommand("-showscores")
end
end)
end
end
// Override OnEndOfGame to do any other stuff. like winning music.
function GM:EndOfGame( bGamemodeVote )
if GAMEMODE.IsEndOfGame then return end
GAMEMODE.IsEndOfGame = true
SetGlobalBool( "IsEndOfGame", true );
gamemode.Call("OnEndOfGame", bGamemodeVote);
if ( bGamemodeVote ) then
MsgN( "Starting gamemode voting..." )
PrintMessage( HUD_PRINTTALK, "Starting gamemode voting..." );
timer.Simple( GAMEMODE.VotingDelay, function() MapVote.Start() end )
end
end
function GM:GetWinningFraction()
if ( !GAMEMODE.GMVoteResults ) then return end
return GAMEMODE.GMVoteResults.Fraction
end
function GM:PlayerShouldTakeDamage( ply, attacker )
if ( GAMEMODE.NoPlayerSelfDamage && IsValid( attacker ) && ply == attacker ) then return false end
if ( GAMEMODE.NoPlayerDamage ) then return false end
if ( GAMEMODE.NoPlayerTeamDamage && IsValid( attacker ) ) then
if ( attacker.Team && ply:Team() == attacker:Team() && ply != attacker ) then return false end
end
if ( IsValid( attacker ) && attacker:IsPlayer() && GAMEMODE.NoPlayerPlayerDamage ) then return false end
if ( IsValid( attacker ) && !attacker:IsPlayer() && GAMEMODE.NoNonPlayerPlayerDamage ) then return false end
return true
end
function GM:PlayerDeathThink( pl )
pl.DeathTime = pl.DeathTime or CurTime()
local timeDead = CurTime() - pl.DeathTime
// If we're in deathcam mode, promote to a generic spectator mode
if ( GAMEMODE.DeathLingerTime > 0 && timeDead > GAMEMODE.DeathLingerTime && ( pl:GetObserverMode() == OBS_MODE_FREEZECAM || pl:GetObserverMode() == OBS_MODE_DEATHCAM ) ) then
GAMEMODE:BecomeObserver( pl )
end
// If we're in a round based game, player NEVER spawns in death think
if ( GAMEMODE.NoAutomaticSpawning ) then return end
// The gamemode is holding the player from respawning.
// Probably because they have to choose a class..
if ( !pl:CanRespawn() ) then return end
// Don't respawn yet - wait for minimum time...
if ( GAMEMODE.MinimumDeathLength ) then
pl:SetNWFloat( "RespawnTime", pl.DeathTime + GAMEMODE.MinimumDeathLength )
if ( timeDead < pl:GetRespawnTime() ) then
return
end
end
// Force respawn
if ( pl:GetRespawnTime() != 0 && GAMEMODE.MaximumDeathLength != 0 && timeDead > GAMEMODE.MaximumDeathLength ) then
pl:Spawn()
return
end
// We're between min and max death length, player can press a key to spawn.
if ( pl:KeyPressed( IN_ATTACK ) || pl:KeyPressed( IN_ATTACK2 ) || pl:KeyPressed( IN_JUMP ) ) then
pl:Spawn()
end
end
function GM:GetFallDamage( ply, flFallSpeed )
if not GAMEMODE:InRound() then return 0 end
if ( GAMEMODE.RealisticFallDamage ) then
return flFallSpeed / 8
end
return 10
end
function GM:PostPlayerDeath( ply )
// Note, this gets called AFTER DoPlayerDeath.. AND it gets called
// for KillSilent too. So if Freezecam isn't set by DoPlayerDeath, we
// pick up the slack by setting DEATHCAM here.
if ( ply:GetObserverMode() == OBS_MODE_NONE ) then
ply:Spectate( OBS_MODE_DEATHCAM )
end
ply:OnDeath()
end
function GM:DoPlayerDeath( ply, attacker, dmginfo )
ply:CallClassFunction( "OnDeath", attacker, dmginfo )
ply:CreateRagdoll()
ply:AddDeaths( 1 )
if ( attacker:IsValid() && attacker:IsPlayer() ) then
if ( attacker == ply ) then
if ( GAMEMODE.TakeFragOnSuicide ) then
attacker:AddFrags( -1 )
if ( GAMEMODE.TeamBased && GAMEMODE.AddFragsToTeamScore ) then
team.AddScore( attacker:Team(), -1 )
end
end
else
attacker:AddFrags( 1 )
if ( GAMEMODE.TeamBased && GAMEMODE.AddFragsToTeamScore ) then
team.AddScore( attacker:Team(), 1 )
end
end
end
if ( GAMEMODE.EnableFreezeCam && IsValid( attacker ) && attacker != ply ) then
ply:SpectateEntity( attacker )
ply:Spectate( OBS_MODE_FREEZECAM )
end
end
function GM:StartSpectating( ply )
if ( !GAMEMODE:PlayerCanJoinTeam( ply ) ) then return end
ply:StripWeapons();
GAMEMODE:PlayerJoinTeam( ply, TEAM_SPECTATOR )
GAMEMODE:BecomeObserver( ply )
end
function GM:EndSpectating( ply )
if ( !GAMEMODE:PlayerCanJoinTeam( ply ) ) then return end
GAMEMODE:PlayerJoinTeam( ply, TEAM_UNASSIGNED )
ply:KillSilent()
end
/*---------------------------------------------------------
Name: gamemode:PlayerRequestTeam()
Player wants to change team
---------------------------------------------------------*/
function GM:PlayerRequestTeam( ply, teamid )
if ( !GAMEMODE.TeamBased && GAMEMODE.AllowSpectating ) then
if ( teamid == TEAM_SPECTATOR ) then
GAMEMODE:StartSpectating( ply )
else
GAMEMODE:EndSpectating( ply )
end
return
end
return self.BaseClass:PlayerRequestTeam( ply, teamid )
end
local function TimeLeft( ply )
local tl = GAMEMODE:GetGameTimeLeft()
if ( tl == -1 ) then return end
local Time = util.ToMinutesSeconds( tl )
if ( IsValid( ply ) ) then
ply:PrintMessage( HUD_PRINTCONSOLE, Time )
else
MsgN( Time )
end
end
concommand.Add( "timeleft", TimeLeft )

View File

@ -0,0 +1,43 @@
module( "player_class", package.seeall )
local ClassTables = {}
function Register( name, classtable )
ClassTables[ name ] = classtable
ClassTables[ name ].m_HasBeenSetup = false
end
function Get( name )
if ( !ClassTables[ name ] ) then return {} end
// Derive class here.
// I have favoured using table.Inherit over using a meta table
// This is to the performance hit is once, now, rather than on every usage
if ( !ClassTables[ name ].m_HasBeenSetup ) then
ClassTables[ name ].m_HasBeenSetup = true
local Base = ClassTables[ name ].Base
if ( ClassTables[ name ].Base && Get( Base ) ) then
ClassTables[ name ] = table.Inherit( ClassTables[ name ], Get( Base ) )
ClassTables[ name ].BaseClass = Get( Base )
end
end
return ClassTables[ name ]
end
function GetClassName( name )
local class = Get( name )
if (!class) then return name end
return class.DisplayName
end

View File

@ -0,0 +1,16 @@
list.Set( "PlayerColours", "red", Color( 255, 0, 0 ) )
list.Set( "PlayerColours", "yellow", Color( 255, 255, 0 ) )
list.Set( "PlayerColours", "green", Color( 43, 235, 79 ) )
list.Set( "PlayerColours", "blue", Color( 43, 158, 255 ) )
list.Set( "PlayerColours", "orange", Color( 255, 148, 39 ) )
list.Set( "PlayerColours", "pink", Color( 255, 148, 255 ) )
list.Set( "PlayerColours", "lilac", Color( 120, 133, 255 ) )
list.Set( "PlayerColours", "army", Color( 120, 158, 18 ) )
list.Set( "PlayerColours", "grey", Color( 200, 200, 200 ) )
if ( CLIENT ) then
CreateClientConVar( "cl_playercolor", "", true, true )
end

View File

@ -0,0 +1,218 @@
local meta = FindMetaTable( "Player" )
if (!meta) then return end
function meta:SetPlayerClass( strName )
self:SetNWString( "Class", strName )
local c = player_class.Get( strName )
if ( !c ) then
MsgN( "Warning: Player joined undefined class (", strName, ")" )
end
end
function meta:GetPlayerClassName()
return self:GetNWString( "Class", "Default" )
end
function meta:GetPlayerClass()
// Class that has been set using SetClass
local ClassName = self:GetPlayerClassName()
local c = player_class.Get( ClassName )
if ( c ) then return c end
// Class based on their Team
local c = player_class.Get( self:Team() )
if ( c ) then return c end
// If all else fails, use the default
local c = player_class.Get( "Default" )
if ( c ) then return c end
end
function meta:SetRandomClass()
local Classes = team.GetClass( self:Team() )
if ( Classes ) then
local Class = table.Random( Classes )
self:SetPlayerClass( Class )
return
end
end
function meta:CheckPlayerClassOnSpawn()
local Classes = team.GetClass( self:Team() )
// The player has requested to spawn as a new class
if ( self.m_SpawnAsClass ) then
self:SetPlayerClass( self.m_SpawnAsClass )
self.m_SpawnAsClass = nil
end
// Make sure the player isn't using the wrong class
if ( Classes && #Classes > 0 && !table.HasValue( Classes, self:GetPlayerClassName() ) ) then
self:SetRandomClass()
end
// If the player is on a team with only one class,
// make sure we're that one when we spawn.
if ( Classes && #Classes == 1 ) then
self:SetPlayerClass( Classes[1] )
end
// No defined classes, use default class
if ( !Classes || #Classes == 0 ) then
self:SetPlayerClass( "Default" )
end
end
function meta:OnSpawn()
local Class = self:GetPlayerClass()
if ( !Class ) then return end
if ( Class.DuckSpeed ) then self:SetDuckSpeed( Class.DuckSpeed ) end
if ( Class.WalkSpeed ) then self:SetWalkSpeed( Class.WalkSpeed ) end
if ( Class.RunSpeed ) then self:SetRunSpeed( Class.RunSpeed ) end
if ( Class.CrouchedWalkSpeed ) then self:SetCrouchedWalkSpeed( Class.CrouchedWalkSpeed ) end
if ( Class.JumpPower ) then self:SetJumpPower( Class.JumpPower ) end
if ( Class.DrawTeamRing ) then self:SetNWBool( "DrawRing", true ) else self:SetNWBool( "DrawRing", false ) end
if ( Class.DrawViewModel == false ) then self:DrawViewModel( false ) else self:DrawViewModel( true ) end
if ( Class.CanUseFlashlight != nil ) then self:AllowFlashlight( Class.CanUseFlashlight ) end
if ( Class.StartHealth ) then self:SetHealth( Class.StartHealth ) end
if ( Class.MaxHealth ) then self:SetMaxHealth( Class.MaxHealth ) end
if ( Class.StartArmor ) then self:SetArmor( Class.StartArmor ) end
if ( Class.RespawnTime ) then self:SetRespawnTime( Class.RespawnTime ) end
if ( Class.DropWeaponOnDie != nil ) then self:ShouldDropWeapon( Class.DropWeaponOnDie ) end
if ( Class.TeammateNoCollide != nil ) then self:SetNoCollideWithTeammates( Class.TeammateNoCollide ) end
if ( Class.AvoidPlayers != nil ) then self:SetAvoidPlayers( Class.AvoidPlayers ) end
if ( Class.FullRotation != nil ) then self:SetAllowFullRotation( Class.FullRotation ) end
self:CallClassFunction( "OnSpawn" )
end
function meta:CallClassFunction( name, ... )
local Class = self:GetPlayerClass()
if ( !Class ) then return end
if ( !Class[name] ) then return end
//print( "Class Function: ", self:GetPlayerClassName(), name )
return Class[name]( Class, self, ... )
end
function meta:OnLoadout()
self:CallClassFunction( "Loadout" )
end
function meta:OnDeath()
end
function meta:OnPlayerModel()
// If the class forces a player model, use that..
// If not, use our preferred model..
local Class = self:GetPlayerClass()
if ( Class && Class.PlayerModel ) then
local mdl = Class.PlayerModel
if( type( mdl ) == "table" ) then // table of models, set random
mdl = table.Random( Class.PlayerModel );
end
util.PrecacheModel( mdl );
self:SetModel( mdl );
return
end
local cl_playermodel = self:GetInfo( "cl_playermodel" )
local modelname = player_manager.TranslatePlayerModel( cl_playermodel )
util.PrecacheModel( modelname )
self:SetModel( modelname )
end
function meta:AllowFlashlight( bAble )
self.m_bFlashlight = bAble
end
function meta:CanUseFlashlight()
if self.m_bFlashlight == nil then
return true // Default to true unless modified by the player class
end
return self.m_bFlashlight
end
function meta:SetRespawnTime( num )
self.m_iSpawnTime = num
end
function meta:GetRespawnTime( num )
if ( self.m_iSpawnTime == 0 || !self.m_iSpawnTime ) then
return GAMEMODE.MinimumDeathLength
end
return self.m_iSpawnTime
end
function meta:DisableRespawn( strReason )
self.m_bCanRespawn = false
end
function meta:EnableRespawn()
self.m_bCanRespawn = true
end
function meta:CanRespawn()
return self.m_bCanRespawn == nil || self.m_bCanRespawn == true
end
function meta:IsObserver()
return ( self:GetObserverMode() > OBS_MODE_NONE );
end
function meta:UpdateNameColor()
if ( GAMEMODE.SelectColor ) then
self:SetNWString( "NameColor", self:GetInfo( "cl_playercolor" ) )
end
end

View File

@ -0,0 +1,408 @@
function GM:SetRoundWinner( ply, resulttext ) SetGlobalEntity( "RoundWinner", ply ) SetGlobalString( "RRText", tostring(resulttext) ) end
function GM:SetRoundResult( i, resulttext ) SetGlobalInt( "RoundResult", i ) SetGlobalString( "RRText", tostring(resulttext) ) end
function GM:ClearRoundResult() SetGlobalEntity( "RoundWinner", NULL ) SetGlobalInt( "RoundResult", 0 ) SetGlobalString( "RRText", "" ) end
function GM:SetInRound( b ) SetGlobalBool( "InRound", b ) end
function GM:InRound() return GetGlobalBool( "InRound", false ) end
--//moved to prop hunt's init.lua
-- fretta_waitforplayers = CreateConVar( "fretta_waitforplayers", "1", { FCVAR_ARCHIVE } )
function GM:OnRoundStart( num )
UTIL_UnFreezeAllPlayers()
hook.Call("PH_OnRoundStart", nil, num)
end
--local bAlreadyStarted = false
--[[moved to prop hunt's init.lua
function GM:OnRoundEnd( num )
// Check if fretta_waitforplayers is true
// This is a fast implementation for a waiting system
// Make optimisations if needed
if ( fretta_waitforplayers:GetBool() ) then
// Take away a round number quickly before it adds another when there are not enough players
// Set to false
if ( ( team.NumPlayers( TEAM_HUNTERS ) < 1 ) || ( team.NumPlayers( TEAM_PROPS ) < 1 ) ) then
bAlreadyStarted = false
end
// Check if the round was already started before so we count it as a fully played round
if ( !bAlreadyStarted ) then
SetGlobalInt( "RoundNumber", GetGlobalInt( "RoundNumber" )-1 )
end
// Set to true
if ( ( team.NumPlayers( TEAM_HUNTERS ) >= 1 ) && ( team.NumPlayers( TEAM_PROPS ) >= 1 ) ) then
bAlreadyStarted = true
end
end
end
]]--
function GM:OnRoundEnd(num)
end
function GM:OnRoundResult( result, resulttext )
// The fact that result might not be a team
// shouldn't matter when calling this..
team.AddScore( result, 1 )
end
function GM:OnRoundWinner( ply, resulttext )
// Do whatever you want to do with the winner here (this is only called in Free For All gamemodes)...
ply:AddFrags( 1 )
end
function GM:OnPreRoundStart( num )
game.CleanUpMap()
UTIL_StripAllPlayers()
UTIL_SpawnAllPlayers()
UTIL_FreezeAllPlayers()
end
function GM:CanStartRound( iNum )
return true
end
function GM:StartRoundBasedGame()
GAMEMODE:PreRoundStart( 1 )
end
// Number of rounds
function GM:GetRoundLimit()
return GAMEMODE.RoundLimit;
end
// Has the round limit been reached?
function GM:HasReachedRoundLimit( iNum )
local iRoundLimit = GAMEMODE:GetRoundLimit();
if( iRoundLimit > 0 && iNum > iRoundLimit ) then
--MapVote.Start()
return true
end
return false
end
// This is for the timer-based game end. set this to return true if you want it to end mid-round
function GM:CanEndRoundBasedGame()
return false
end
// You can add round time by calling this (takes time in seconds)
function GM:AddRoundTime( iAddedTime )
if( !GAMEMODE:InRound() ) then // don't add time if round is not in progress
return
end
SetGlobalFloat( "RoundEndTime", GetGlobalFloat( "RoundEndTime", CurTime() ) + iAddedTime );
timer.Adjust( "RoundEndTimer", GetGlobalFloat( "RoundEndTime" ) - GetGlobalFloat( "RoundStartTime" ), 0, function() GAMEMODE:RoundTimerEnd() end );
local rf = RecipientFilter()
rf:AddAllPlayers()
umsg.Start( "RoundAddedTime", rf ); // send a umsg so you can do something with the HUD
umsg.Float( iAddedTime ); // time added
umsg.End();
end
// This gets the timer for a round (you can make round number dependant round lengths, or make it cvar controlled)
function GM:GetRoundTime( iRoundNumber )
return GAMEMODE.RoundLength;
end
//
// Internal, override OnPreRoundStart if you want to do stuff here
//
function GM:PreRoundStart( iNum )
// Should the game end?
if( CurTime() >= GAMEMODE.GetTimeLimit() || GAMEMODE:HasReachedRoundLimit( iNum ) ) then
GAMEMODE:EndOfGame( true );
return;
end
if ( !GAMEMODE:CanStartRound( iNum ) ) then
timer.Simple( 1, function() GAMEMODE:PreRoundStart( iNum ) end ) // In a second, check to see if we can start
return;
end
timer.Create( "RoundStartTimer", GAMEMODE.RoundPreStartTime, 1, function() GAMEMODE:RoundStart() end )
SetGlobalInt( "RoundNumber", iNum )
SetGlobalFloat( "RoundStartTime", CurTime() + GAMEMODE.RoundPreStartTime )
GAMEMODE:ClearRoundResult()
GAMEMODE:OnPreRoundStart( GetGlobalInt( "RoundNumber" ) )
GAMEMODE:SetInRound( true )
end
//
// Internal, override OnRoundStart if you want to do stuff here
//
--[[ moved to prop hunt's init.lua
function GM:RoundStart()
local roundNum = GetGlobalInt( "RoundNumber" );
local roundDuration = GAMEMODE:GetRoundTime( roundNum )
GAMEMODE:OnRoundStart( roundNum )
timer.Create( "RoundEndTimer", roundDuration, 0, function() GAMEMODE:RoundTimerEnd() end )
timer.Create( "CheckRoundEnd", 1, 0, function() GAMEMODE:CheckRoundEnd() end )
SetGlobalFloat( "RoundEndTime", CurTime() + roundDuration );
// Check if fretta_waitforplayers is true
// This is a fast implementation for a waiting system
// Make optimisations if needed
if ( fretta_waitforplayers:GetBool() ) then
// Pause these timers if there are not enough players on the teams in the server
if ( ( team.NumPlayers( TEAM_HUNTERS ) < 1 ) || ( team.NumPlayers( TEAM_PROPS ) < 1 ) ) then
if ( timer.Exists( "RoundEndTimer" ) && timer.Exists( "CheckRoundEnd" ) ) then
timer.Pause( "RoundEndTimer" )
timer.Pause( "CheckRoundEnd" )
SetGlobalFloat( "RoundEndTime", -1 );
PrintMessage( HUD_PRINTTALK, "There's not enough players to start the game." )
end
end
end
// Send this as a global boolean
SetGlobalBool( "RoundWaitForPlayers", fretta_waitforplayers:GetBool() )
end
]]--
-- default fretta on round start.
function GM:RoundStart()
local roundNum = GetGlobalInt( "RoundNumber" );
local roundDuration = GAMEMODE:GetRoundTime( roundNum )
GAMEMODE:OnRoundStart( roundNum )
timer.Create( "RoundEndTimer", roundDuration, 0, function() GAMEMODE:RoundTimerEnd() end )
timer.Create( "CheckRoundEnd", 1, 0, function() GAMEMODE:CheckRoundEnd() end )
SetGlobalFloat( "RoundEndTime", CurTime() + roundDuration );
end
//
// Decide what text should show when a team/player wins
//
function GM:ProcessResultText( result, resulttext )
if ( resulttext == nil ) then resulttext = "" end
//the result could either be a number or a player!
// for a free for all you could do... if type(result) == "Player" and IsValid( result ) then return result:Name().." is the winner" or whatever
return resulttext
end
//
// Round Ended with Result
//
function GM:RoundEndWithResult( result, resulttext )
resulttext = GAMEMODE:ProcessResultText( result, resulttext )
if type( result ) == "number" then // the result is a team ID
GAMEMODE:SetRoundResult( result, resulttext )
GAMEMODE:RoundEnd()
GAMEMODE:OnRoundResult( result, resulttext )
else // the result is a player
GAMEMODE:SetRoundWinner( result, resulttext )
GAMEMODE:RoundEnd()
GAMEMODE:OnRoundWinner( result, resulttext )
end
end
//
// Internal, override OnRoundEnd if you want to do stuff here
//
function GM:RoundEnd()
if ( !GAMEMODE:InRound() ) then
// if someone uses RoundEnd incorrectly then do a trace.
MsgN("WARNING: RoundEnd being called while gamemode not in round...")
debug.Trace()
return
end
GAMEMODE:OnRoundEnd( GetGlobalInt( "RoundNumber" ) )
self:SetInRound( false )
timer.Destroy( "RoundEndTimer" )
timer.Destroy( "CheckRoundEnd" )
SetGlobalFloat( "RoundEndTime", -1 )
timer.Simple( GAMEMODE.RoundPostLength, function() GAMEMODE:PreRoundStart( GetGlobalInt( "RoundNumber" )+1 ) end )
hook.Call("PH_RoundEnd", nil)
end
function GM:GetTeamAliveCounts()
local TeamCounter = {}
for k,v in pairs( player.GetAll() ) do
if ( v:Alive() && v:Team() > 0 && v:Team() < 1000 ) then
TeamCounter[ v:Team() ] = TeamCounter[ v:Team() ] or 0
TeamCounter[ v:Team() ] = TeamCounter[ v:Team() ] + 1
end
end
return TeamCounter
end
//
// For round based games that end when a team is dead
//
function GM:CheckPlayerDeathRoundEnd()
if ( !GAMEMODE.RoundBased ) then return end
if ( !GAMEMODE:InRound() ) then return end
if ( GAMEMODE.RoundEndsWhenOneTeamAlive ) then
local Teams = GAMEMODE:GetTeamAliveCounts()
if ( table.Count( Teams ) == 0 ) then
GAMEMODE:RoundEndWithResult( 1001, "Draw, everyone loses!" )
return
end
if ( table.Count( Teams ) == 1 ) then
local TeamID = table.GetFirstKey( Teams )
GAMEMODE:RoundEndWithResult( TeamID )
return
end
end
end
hook.Add( "PlayerDisconnected", "RoundCheck_PlayerDisconnect", function() timer.Simple( 0.2, function() GAMEMODE:CheckPlayerDeathRoundEnd() end ) end )
hook.Add( "PostPlayerDeath", "RoundCheck_PostPlayerDeath", function() timer.Simple( 0.2, function() GAMEMODE:CheckPlayerDeathRoundEnd() end ) end )
//
// You should use this to check any round end conditions
//
function GM:CheckRoundEnd()
// Do checks..
// if something then call GAMEMODE:RoundEndWithResult( TEAM_BLUE, "Team Blue Ate All The Mushrooms!" )
// OR for a free for all you could do something like... GAMEMODE:RoundEndWithResult( SomePlayer )
end
function GM:CheckRoundEndInternal()
if ( !GAMEMODE:InRound() ) then return end
GAMEMODE:CheckRoundEnd()
timer.Create( "CheckRoundEnd", 1, 0, function() GAMEMODE:CheckRoundEndInternal() end )
end
//
// This is called when the round time ends.
//
function GM:RoundTimerEnd()
if ( !GAMEMODE:InRound() ) then return end
if ( !GAMEMODE.TeamBased ) then
local ply = GAMEMODE:SelectCurrentlyWinningPlayer()
if ply then
GAMEMODE:RoundEndWithResult( ply, "Time Up" )
else
GAMEMODE:RoundEndWithResult( -1, "Time Up" )
end
else
GAMEMODE:RoundEndWithResult( -1, "Time Up" )
end
end
//
// This is called when time runs out and there is no winner chosen yet (free for all gamemodes only)
// By default it chooses the player with the most frags but you can edit this to do what you need..
//
function GM:SelectCurrentlyWinningPlayer()
local winner
local topscore = 0
for k,v in pairs( player.GetAll() ) do
if v:Frags() > topscore and v:Team() != TEAM_CONNECTING and v:Team() != TEAM_UNASSIGNED and v:Team() != TEAM_SPECTATOR then
winner = v
topscore = v:Frags()
end
end
return winner
end

View File

@ -0,0 +1,331 @@
/*
shared.lua - Shared Component
-----------------------------------------------------
This is the shared component of your gamemode, a lot of the game variables
can be changed from here.
*/
include( "player_class.lua" )
include( "player_extension.lua" )
include( "class_default.lua" )
include( "player_colours.lua" )
fretta_voting = CreateConVar( "fretta_voting", "1", { FCVAR_REPLICATED, FCVAR_NOTIFY, FCVAR_ARCHIVE }, "Allow/Dissallow voting" )
GM.Name = "Simple Game Base"
GM.Author = "Anonymous"
GM.Email = ""
GM.Website = "www.garry.tv"
GM.Help = "No Help Available"
GM.TeamBased = true // Team based game or a Free For All game?
GM.AllowAutoTeam = true // Allow auto-assign?
GM.AllowSpectating = true // Allow people to spectate during the game?
GM.SecondsBetweenTeamSwitches = 10 // The minimum time between each team change?
GM.GameLength = 15 // The overall length of the game
GM.RoundLimit = -1 // Maximum amount of rounds to be played in round based games
GM.VotingDelay = 5 // Delay between end of game, and vote. if you want to display any extra screens before the vote pops up
GM.ShowTeamName = true // Show the team name on the HUD
GM.NoPlayerSuicide = false // Set to true if players should not be allowed to commit suicide.
GM.NoPlayerDamage = false // Set to true if players should not be able to damage each other.
GM.NoPlayerSelfDamage = false // Allow players to hurt themselves?
GM.NoPlayerTeamDamage = true // Allow team-members to hurt each other?
GM.NoPlayerPlayerDamage = false // Allow players to hurt each other?
GM.NoNonPlayerPlayerDamage = false // Allow damage from non players (physics, fire etc)
GM.NoPlayerFootsteps = false // When true, all players have silent footsteps
GM.PlayerCanNoClip = false // When true, players can use noclip without sv_cheats
GM.TakeFragOnSuicide = false // -1 frag on suicide
GM.MaximumDeathLength = 0 // Player will repspawn if death length > this (can be 0 to disable)
GM.MinimumDeathLength = 2 // Player has to be dead for at least this long
GM.AutomaticTeamBalance = false // Teams will be periodically balanced
GM.ForceJoinBalancedTeams = true // Players won't be allowed to join a team if it has more players than another team
GM.RealisticFallDamage = false // Set to true if you want realistic fall damage instead of the fix 10 damage.
GM.AddFragsToTeamScore = false // Adds player's individual kills to team score (must be team based)
GM.NoAutomaticSpawning = false // Players don't spawn automatically when they die, some other system spawns them
GM.RoundBased = false // Round based, like CS
GM.RoundLength = 30 // Round length, in seconds
GM.RoundPreStartTime = 5 // Preperation time before a round starts
GM.RoundPostLength = 8 // Seconds to show the 'x team won!' screen at the end of a round
GM.RoundEndsWhenOneTeamAlive = true // CS Style rules
GM.EnableFreezeCam = true // TF2 Style Freezecam
GM.DeathLingerTime = 7 // The time between you dying and it going into spectator mode, 0 disables
GM.SelectModel = false // Can players use the playermodel picker in the F1 menu?
GM.SelectColor = false // Can players modify the colour of their name? (ie.. no teams)
GM.PlayerRingSize = 48 // How big are the colored rings under the player's feet (if they are enabled) ?
GM.HudSkin = "SimpleSkin" // The Derma skin to use for the HUD components
GM.SuicideString = "died" // The string to append to the player's name when they commit suicide.
GM.DeathNoticeDefaultColor = Color( 255, 128, 0 ); // Default colour for entity kills
GM.DeathNoticeTextColor = color_white; // colour for text ie. "died", "killed"
GM.ValidSpectatorModes = { OBS_MODE_CHASE, OBS_MODE_IN_EYE, OBS_MODE_ROAMING } // The spectator modes that are allowed
GM.ValidSpectatorEntities = { "player" } // Entities we can spectate, players being the obvious default choice.
GM.CanOnlySpectateOwnTeam = true; // you can only spectate players on your own team
DeriveGamemode( "base" )
TEAM_GREEN = 1
TEAM_ORANGE = 2
TEAM_BLUE = 3
TEAM_RED = 4
/*---------------------------------------------------------
Name: gamemode:CreateTeams()
Desc: Set up all your teams here. Note - HAS to be shared.
---------------------------------------------------------*/
function GM:CreateTeams()
if ( !GAMEMODE.TeamBased ) then return end
team.SetUp( TEAM_GREEN, "Green Team", Color( 70, 230, 70 ), true )
team.SetSpawnPoint( TEAM_GREEN, "info_player_start" ) // The list of entities can be a table
team.SetUp( TEAM_ORANGE, "Orange Team", Color( 255, 200, 50 ) )
team.SetSpawnPoint( TEAM_ORANGE, "info_player_start", true )
team.SetUp( TEAM_BLUE, "Blue Team", Color( 80, 150, 255 ) )
team.SetSpawnPoint( TEAM_BLUE, "info_player_start", true )
team.SetUp( TEAM_RED, "Red Team", Color( 255, 80, 80 ) )
team.SetSpawnPoint( TEAM_RED, "info_player_start", true )
team.SetUp( TEAM_SPECTATOR, "Spectators", Color( 200, 200, 200 ), true )
team.SetSpawnPoint( TEAM_SPECTATOR, "info_player_start" )
team.SetClass( TEAM_SPECTATOR, { "Spectator" } )
end
function GM:InGamemodeVote()
return GetGlobalBool( "InGamemodeVote", false )
end
/*---------------------------------------------------------
Name: gamemode:TeamHasEnoughPlayers( Number teamid )
Desc: Return true if the team has too many players.
Useful for when forced auto-assign is on.
---------------------------------------------------------*/
function GM:TeamHasEnoughPlayers( teamid )
local PlayerCount = team.NumPlayers( teamid )
// Don't let them join a team if it has more players than another team
if ( GAMEMODE.ForceJoinBalancedTeams ) then
for id, tm in pairs( team.GetAllTeams() ) do
if ( id > 0 && id < 1000 && team.NumPlayers( id ) < PlayerCount && team.Joinable(id) ) then return true end
end
end
return false
end
/*---------------------------------------------------------
Name: gamemode:PlayerCanJoinTeam( Player ply, Number teamid )
Desc: Are we allowed to join a team? Return true if so.
---------------------------------------------------------*/
function GM:PlayerCanJoinTeam( ply, teamid )
if ( SERVER && !self.BaseClass:PlayerCanJoinTeam( ply, teamid ) ) then
return false
end
if ( GAMEMODE:TeamHasEnoughPlayers( teamid ) ) then
ply:ChatPrint( "That team is full!" )
ply:SendLua("GAMEMODE:ShowTeam()")
return false
end
return true
end
/*---------------------------------------------------------
Name: gamemode:Move( Player ply, CMoveData mv )
Desc: Setup Move, this also calls the player's class move
function.
---------------------------------------------------------*/
function GM:Move( ply, mv )
if ( ply:CallClassFunction( "Move", mv ) ) then return true end
end
/*---------------------------------------------------------
Name: gamemode:KeyPress( Player ply, Number key )
Desc: Player presses a key, this also calls the player's class
OnKeyPress function.
---------------------------------------------------------*/
function GM:KeyPress( ply, key )
if ( ply:CallClassFunction( "OnKeyPress", key ) ) then return true end
end
/*---------------------------------------------------------
Name: gamemode:KeyRelease( Player ply, Number key )
Desc: Player releases a key, this also calls the player's class
OnKeyRelease function.
---------------------------------------------------------*/
function GM:KeyRelease( ply, key )
if ( ply:CallClassFunction( "OnKeyRelease", key ) ) then return true end
end
/*---------------------------------------------------------
Name: gamemode:PlayerFootstep( Player ply, Vector pos, Number foot, String sound, Float volume, CReceipientFilter rf )
Desc: Player's feet makes a sound, this also calls the player's class Footstep function.
If you want to disable all footsteps set GM.NoPlayerFootsteps to true.
If you want to disable footsteps on a class, set Class.DisableFootsteps to true.
---------------------------------------------------------*/
function GM:PlayerFootstep( ply, pos, foot, sound, volume, rf )
if( GAMEMODE.NoPlayerFootsteps || !ply:Alive() || ply:Team() == TEAM_SPECTATOR || ply:IsObserver() ) then
return true;
end
local Class = ply:GetPlayerClass();
if( !Class ) then return end
if( Class.DisableFootsteps ) then // rather than using a hook, we can just do this to override the function instead.
return true;
end
if( Class.Footstep ) then
return Class:Footstep( ply, pos, foot, sound, volume, rf ); // Call footstep function in class, you can use this to make custom footstep sounds
end
end
/*---------------------------------------------------------
Name: gamemode:CalcView( Player ply, Vector origin, Angles angles, Number fov )
Desc: Calculates the players view. Also calls the players class
CalcView function, as well as GetViewModelPosition and CalcView
on the current weapon. Returns a table.
---------------------------------------------------------*/
function GM:CalcView( ply, origin, angles, fov )
local view = ply:CallClassFunction( "CalcView", origin, angles, fov ) or { ["origin"] = origin, ["angles"] = angles, ["fov"] = fov };
origin = view.origin or origin
angles = view.angles or angles
fov = view.fov or fov
local wep = ply:GetActiveWeapon()
if ( IsValid( wep ) ) then
local func = wep.GetViewModelPosition
if ( func ) then view.vm_origin, view.vm_angles = func( wep, origin*1, angles*1 ) end
local func = wep.CalcView
if ( func ) then view.origin, view.angles, view.fov = func( wep, ply, origin*1, angles*1, fov ) end
end
return view
end
/*---------------------------------------------------------
Name: gamemode:GetTimeLimit()
Desc: Returns the time limit of a game in seconds, so you could
make it use a cvar instead. Return -1 for unlimited.
Unlimited length games can be changed using vote for
change.
---------------------------------------------------------*/
function GM:GetTimeLimit()
if( GAMEMODE.GameLength > 0 ) then
return GAMEMODE.GameLength * 60;
end
return -1;
end
/*---------------------------------------------------------
Name: gamemode:GetGameTimeLeft()
Desc: Get the remaining time in seconds.
---------------------------------------------------------*/
function GM:GetGameTimeLeft()
local EndTime = GAMEMODE:GetTimeLimit();
if ( EndTime == -1 ) then return -1 end
return EndTime - CurTime()
end
/*---------------------------------------------------------
Name: gamemode:PlayerNoClip( player, bool )
Desc: Player pressed the noclip key, return true if
the player is allowed to noclip, false to block
---------------------------------------------------------*/
function GM:PlayerNoClip( pl, on )
// Allow noclip if we're in single player or have cheats enabled
if ( GAMEMODE.PlayerCanNoClip || game.SinglePlayer() || GetConVar( "sv_cheats" ):GetBool() ) then return true end
// Don't if it's not.
return false
end
// This function includes /yourgamemode/player_class/*.lua
// And AddCSLuaFile's each of those files.
// You need to call it in your derived shared.lua IF you have files in that folder
// and want to include them!
function IncludePlayerClasses()
local Folder = string.Replace( GM.Folder, "gamemodes/", "" );
for c,d in pairs(file.Find(Folder.."/gamemode/player_class/*.lua", "LUA")) do
include( Folder.."/gamemode/player_class/"..d )
AddCSLuaFile( Folder.."/gamemode/player_class/"..d )
end
end
IncludePlayerClasses()
function util.ToMinutesSeconds(seconds)
local minutes = math.floor(seconds / 60)
seconds = seconds - minutes * 60
return string.format("%02d:%02d", minutes, math.floor(seconds))
end
function util.ToMinutesSecondsMilliseconds(seconds)
local minutes = math.floor(seconds / 60)
seconds = seconds - minutes * 60
local milliseconds = math.floor(seconds % 1 * 100)
return string.format("%02d:%02d.%02d", minutes, math.floor(seconds), milliseconds)
end
function timer.SimpleEx(delay, action, ...)
if ... == nil then
timer.Simple(delay, action)
else
local a, b, c, d, e, f, g, h, i, j, k = ...
timer.Simple(delay, function() action(a, b, c, d, e, f, g, h, i, j, k) end)
end
end
function timer.CreateEx(timername, delay, repeats, action, ...)
if ... == nil then
timer.Create(timername, delay, repeats, action)
else
local a, b, c, d, e, f, g, h, i, j, k = ...
timer.Create(timername, delay, repeats, function() action(a, b, c, d, e, f, g, h, i, j, k) end)
end
end

View File

@ -0,0 +1,443 @@
/*
skin.lua - Fretta Derma Skin
-----------------------------------------------------
This is the default Fretta skin for Derma. If you want to override the look of Fretta,
base a skin of this and change GM.HudSkin.
*/
local surface = surface
local draw = draw
local Color = Color
local SKIN = {}
SKIN.PrintName = ""
SKIN.Author = ""
SKIN.DermaVersion = 1
SKIN.bg_color = Color( 100, 100, 100, 255 )
SKIN.bg_color_sleep = Color( 70, 70, 70, 255 )
SKIN.bg_color_dark = Color( 50, 50, 50, 255 )
SKIN.bg_color_bright = Color( 220, 220, 220, 255 )
SKIN.fontFrame = "Default"
SKIN.control_color = Color( 180, 180, 180, 255 )
SKIN.control_color_highlight = Color( 220, 220, 220, 255 )
SKIN.control_color_active = Color( 110, 150, 255, 255 )
SKIN.control_color_bright = Color( 255, 200, 100, 255 )
SKIN.control_color_dark = Color( 100, 100, 100, 255 )
SKIN.bg_alt1 = Color( 50, 50, 50, 255 )
SKIN.bg_alt2 = Color( 55, 55, 55, 255 )
SKIN.listview_hover = Color( 70, 70, 70, 255 )
SKIN.listview_selected = Color( 100, 170, 220, 255 )
SKIN.text_bright = Color( 255, 255, 255, 255 )
SKIN.text_normal = Color( 180, 180, 180, 255 )
SKIN.text_dark = Color( 20, 20, 20, 255 )
SKIN.text_highlight = Color( 255, 20, 20, 255 )
SKIN.texGradientUp = Material( "gui/gradient_up" )
SKIN.texGradientDown = Material( "gui/gradient_down" )
SKIN.combobox_selected = SKIN.listview_selected
SKIN.panel_transback = Color( 255, 255, 255, 50 )
SKIN.tooltip = Color( 255, 245, 175, 255 )
SKIN.colPropertySheet = Color( 170, 170, 170, 255 )
SKIN.colTab = SKIN.colPropertySheet
SKIN.colTabInactive = Color( 170, 170, 170, 155 )
SKIN.colTabShadow = Color( 60, 60, 60, 255 )
SKIN.colTabText = Color( 255, 255, 255, 255 )
SKIN.colTabTextInactive = Color( 0, 0, 0, 155 )
SKIN.fontTab = "Default"
SKIN.colCollapsibleCategory = Color( 255, 255, 255, 20 )
SKIN.colCategoryText = Color( 255, 255, 255, 255 )
SKIN.colCategoryTextInactive = Color( 200, 200, 200, 255 )
SKIN.fontCategoryHeader = "TabLarge"
SKIN.colNumberWangBG = Color( 255, 240, 150, 255 )
SKIN.colTextEntryBG = Color( 240, 240, 240, 255 )
SKIN.colTextEntryBorder = Color( 20, 20, 20, 255 )
SKIN.colTextEntryText = Color( 20, 20, 20, 255 )
SKIN.colTextEntryTextHighlight = Color( 20, 200, 250, 255 )
SKIN.colTextEntryTextHighlight = Color( 20, 200, 250, 255 )
SKIN.colMenuBG = Color( 255, 255, 255, 200 )
SKIN.colMenuBorder = Color( 0, 0, 0, 200 )
SKIN.colButtonText = Color( 0, 0, 0, 250 )
SKIN.colButtonTextDisabled = Color( 0, 0, 0, 100 )
SKIN.colButtonBorder = Color( 20, 20, 20, 255 )
SKIN.colButtonBorderHighlight = Color( 255, 255, 255, 50 )
SKIN.colButtonBorderShadow = Color( 0, 0, 0, 100 )
SKIN.fontButton = "Default"
-- enum for draw order
DM_ORDER_LATESTATTOP = 1;
DM_ORDER_LATESTATBOTTOM = 2;
-- basic deathmsg appearance settings
SKIN.deathMessageBackgroundCol = Color( 46, 43, 42, 220 );
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.
SKIN.deathMessageActionColor = Color( 200, 200, 200 );
local matBlurScreen = Material( "pp/blurscreen" )
/*---------------------------------------------------------
DrawGenericBackground
---------------------------------------------------------*/
function SKIN:DrawGenericBackground( x, y, w, h, color )
draw.RoundedBox( 4, x, y, w, h, color )
end
/*---------------------------------------------------------
DrawLinedButtonBorder
---------------------------------------------------------*/
function SKIN:DrawLinedButtonBorder( x, y, w, h, depressed )
surface.SetDrawColor( Color( 0, 0, 0, 200 ) )
surface.DrawOutlinedRect( x+1, y+1, w-2, h-2 )
end
/*---------------------------------------------------------
Button
---------------------------------------------------------*/
function SKIN:PaintCancelButton( panel )
local w, h = panel:GetSize()
if ( panel.m_bBackground ) then
local col = self.control_color
if ( panel:GetDisabled() ) then
col = self.control_color_dark
elseif ( panel.Depressed ) then
col = self.control_color_active
elseif ( panel.Hovered ) then
col = self.control_color_highlight
end
if ( panel.m_colBackground ) then
col = table.Copy( panel.m_colBackground )
if ( panel:GetDisabled() ) then
col.r = math.Clamp( col.r * 0.7, 0, 255 )
col.g = math.Clamp( col.g * 0.7, 0, 255 )
col.b = math.Clamp( col.b * 0.7, 0, 255 )
col.a = 20
elseif ( panel.Depressed ) then
col.r = math.Clamp( col.r + 100, 0, 255 )
col.g = math.Clamp( col.g + 100, 0, 255 )
col.b = math.Clamp( col.b + 100, 0, 255 )
elseif ( panel.Hovered ) then
col.r = math.Clamp( col.r + 30, 0, 255 )
col.g = math.Clamp( col.g + 30, 0, 255 )
col.b = math.Clamp( col.b + 30, 0, 255 )
end
end
surface.SetDrawColor( col.r, col.g, col.b, col.a )
panel:DrawFilledRect()
end
end
SKIN.PaintSelectButton = SKIN.PaintCancelButton
function SKIN:PaintOverCancelButton( panel )
local w, h = panel:GetSize()
if ( panel.m_bBorder ) then
self:DrawLinedButtonBorder( 0, 0, w, h, panel.Depressed )
end
end
SKIN.PaintOverSelectButton = SKIN.PaintOverCancelButton
function SKIN:SchemeCancelButton( panel )
panel:SetFontInternal( "FRETTA_SMALL" )
if ( panel:GetDisabled() ) then
panel:SetTextColor( self.colButtonTextDisabled )
else
panel:SetTextColor( self.colButtonText )
end
DLabel.ApplySchemeSettings( panel )
end
function SKIN:SchemeSelectButton( panel )
panel:SetFontInternal( "FRETTA_SMALL" )
if ( panel:GetDisabled() ) then
panel:SetTextColor( self.colButtonTextDisabled )
else
panel:SetTextColor( self.colButtonText )
end
DLabel.ApplySchemeSettings( panel )
end
/*---------------------------------------------------------
ListViewLine
---------------------------------------------------------*/
function SKIN:PaintListViewLine( panel )
end
/*---------------------------------------------------------
ListViewLine
---------------------------------------------------------*/
function SKIN:PaintListView( panel )
end
/*---------------------------------------------------------
ListViewLabel
---------------------------------------------------------*/
function SKIN:PaintScorePanelHeader( panel )
//surface.SetDrawColor( panel.cTeamColor )
//panel:DrawFilledRect()
end
/*---------------------------------------------------------
ListViewLabel
---------------------------------------------------------*/
function SKIN:PaintScorePanelLine( panel )
local Tall = panel:GetTall()
local BoxHeight = 21
if ( !IsValid( panel.pPlayer ) || !panel.pPlayer:Alive() ) then
draw.RoundedBox( 4, 0, Tall*0.5 - BoxHeight*0.5, panel:GetWide(), BoxHeight, Color( 60, 60, 60, 255 ) )
return
end
if ( panel.pPlayer == LocalPlayer() ) then
draw.RoundedBox( 4, 0, Tall*0.5 - BoxHeight*0.5, panel:GetWide(), BoxHeight, Color( 90, 90, 90, 255 ) )
return
end
draw.RoundedBox( 4, 0, Tall*0.5 - BoxHeight*0.5, panel:GetWide(), BoxHeight, Color( 70, 70, 70, 255 ) )
end
/*---------------------------------------------------------
PaintScorePanel
---------------------------------------------------------*/
function SKIN:PaintScorePanel( panel )
surface.SetMaterial( matBlurScreen )
surface.SetDrawColor( 255, 255, 255, 255 )
local x, y = panel:LocalToScreen( 0, 0 )
matBlurScreen:SetFloat( "$blur", 5 )
render.UpdateScreenEffectTexture()
surface.DrawTexturedRect( x*-1, y*-1, ScrW(), ScrH() )
//matBlurScreen:SetFloat( "$blur", 3 )
//render.UpdateScreenEffectTexture()
//surface.DrawTexturedRect( x*-1, y*-1, ScrW(), ScrH() )
draw.RoundedBox( 8, 0, 8, panel:GetWide(), panel:GetTall()-8, Color( 40, 40, 40, 150 ) )
end
/*---------------------------------------------------------
LayoutTeamScoreboardHeader
---------------------------------------------------------*/
function SKIN:LayoutTeamScoreboardHeader( panel )
panel.TeamName:StretchToParent( 0, 0, 0, 0 )
panel.TeamName:SetTextInset( 8, 0 )
panel.TeamName:SetColor( Color( 0,0,0 ) )
panel.TeamName:SetFontInternal( "FRETTA_SMALL" )
panel.TeamScore:StretchToParent( 0, 0, 0, 0 )
panel.TeamScore:SetContentAlignment( 6 )
panel.TeamScore:SetTextInset( 8, 0 )
panel.TeamScore:SetColor( Color( 0, 0, 0, 250 ) )
panel.TeamScore:SetFontInternal( "FRETTA_MEDIUM" )
end
function SKIN:PaintTeamScoreboardHeader( panel )
local Color = team.GetColor( panel.iTeamID )
draw.RoundedBox( 4, 0, 0, panel:GetWide(), panel:GetTall()*2, Color )
end
function SKIN:SchemeScorePanelLabel( panel )
panel:SetTextColor( GAMEMODE:GetTeamColor( panel.pPlayer ) )
panel:SetFontInternal( "FRETTA_MEDIUM_SHADOW" )
end
function SKIN:PaintScorePanelLabel( panel )
if ( !IsValid( panel.pPlayer ) || !panel.pPlayer:Alive() ) then
panel:SetAlpha( 125 )
else
panel:SetAlpha( 255 )
end
end
function SKIN:SchemeScorePanelHeaderLabel( panel )
panel:SetTextColor( Color( 180, 180, 180, 255 ) )
panel:SetFontInternal( "Default" ) -- HudSelectionText
end
function SKIN:SchemeSpectatorInfo( panel )
panel:SetTextColor( Color( 255, 255, 255, 255 ) )
panel:SetFontInternal( "FRETTA_SMALL" )
end
/*---------------------------------------------------------
ScoreHeader
---------------------------------------------------------*/
function SKIN:PaintScoreHeader( panel )
draw.RoundedBox( 8, 0, 0, panel:GetWide(), panel:GetTall()*2, Color( 60,60,60,255 ) )
end
function SKIN:LayoutScoreHeader( panel )
panel.HostName:SizeToContents()
panel.HostName:SetPos( 0, 0 )
panel.HostName:CenterHorizontal()
panel.GamemodeName:SizeToContents()
panel.GamemodeName:MoveBelow( panel.HostName, 0 )
panel.GamemodeName:CenterHorizontal()
panel:SetTall( panel.GamemodeName.y + panel.GamemodeName:GetTall() + 4 )
end
function SKIN:SchemeScoreHeader( panel )
panel.HostName:SetTextColor( Color( 255, 255, 255, 255 ) )
panel.HostName:SetFontInternal( "FRETTA_LARGE_SHADOW" )
panel.GamemodeName:SetTextColor( Color( 255, 255, 255, 255 ) )
panel.GamemodeName:SetFontInternal( "FRETTA_MEDIUM_SHADOW" )
end
/*---------------------------------------------------------
DeathMessages
---------------------------------------------------------*/
function SKIN:PaintGameNotice( panel )
if ( panel.m_bHighlight ) then
draw.RoundedBox( 4, 0, 0, panel:GetWide(), panel:GetTall(), Color( 90, 90, 90, 200 ) )
return
end
draw.RoundedBox( 4, 0, 0, panel:GetWide(), panel:GetTall(), Color( 20, 20, 20, 190 ) )
end
function SKIN:SchemeGameNoticeLabel( panel )
panel:SetFontInternal( "FRETTA_NOTIFY" );
DLabel.ApplySchemeSettings( panel )
end
/*---------------------------------------------------------
GamemodeButton
---------------------------------------------------------*/
function SKIN:PaintGamemodeButton( panel )
local w, h = panel:GetSize()
local col = Color( 255, 255, 255, 10 )
if ( panel:GetDisabled() ) then
col = Color( 0, 0, 0, 10 )
elseif ( panel.Depressed ) then
col = Color( 255, 255, 255, 50 )
elseif ( panel.Hovered ) then
col = Color( 255, 255, 255, 20 )
end
if ( panel.bgColor != nil ) then col = panel.bgColor end
draw.RoundedBox( 4, 0, 0, w, h, col )
end
function SKIN:SchemeGamemodeButton( panel )
panel:SetTextColor( color_white )
panel:SetFontInternal( "FRETTA_MEDIUM_SHADOW" )
panel:SetContentAlignment( 4 )
panel:SetTextInset( 8, 0 )
end
/*---------------------------------------------------------
PanelButton
---------------------------------------------------------*/
function SKIN:PaintPanelButton( panel )
local w, h = panel:GetSize()
local col = Color( 160, 160, 160, 255 )
if ( panel:GetDisabled() ) then
col = Color( 100, 100, 100, 255 )
elseif ( panel.Depressed ) then
col = Color( 150, 210, 255, 255 )
elseif ( panel.Hovered ) then
col = Color( 200, 200, 200, 255 )
end
if ( panel.bgColor != nil ) then col = panel.bgColor end
surface.SetDrawColor( col )
panel:DrawFilledRect()
end
function SKIN:PaintOverPanelButton( panel )
local w, h = panel:GetSize()
self:DrawLinedButtonBorder( 0, 0, w, h, panel.Depressed )
end
derma.DefineSkin( "SimpleSkin", "", SKIN )

View File

@ -0,0 +1,358 @@
--[[
sv_gmchanger.lua - Gamemode Changer (server side)
-----------------------------------------------------
Most of the internal stuff for the votes is here and contains stuff you really don't
want to override.
]]
local g_PlayableGamemodes = {}
fretta_votesneeded = CreateConVar( "fretta_votesneeded", "0.75", { FCVAR_ARCHIVE } )
fretta_votetime = CreateConVar( "fretta_votetime", "20", { FCVAR_ARCHIVE } )
fretta_votegraceperiod = CreateConVar( "fretta_votegraceperiod", "30", { FCVAR_ARCHIVE } )
local function SendAvailableGamemodes( ply )
net.Start("PlayableGamemodes")
net.WriteTable(g_PlayableGamemodes)
net.Send(ply)
end
function GetRandomGamemodeName()
local choose = table.Random( g_PlayableGamemodes )
if choose then return choose.key end
return GAMEMODE.FolderName
end
function GetRandomGamemodeMap( gm )
local gmtab = g_PlayableGamemodes[ gm or GAMEMODE.FolderName ]
if gmtab then
return table.Random( gmtab.maps )
end
return game.GetMap()
end
function GetNumberOfGamemodeMaps( gm )
local gmtab = g_PlayableGamemodes[ gm or GAMEMODE.FolderName ]
if gmtab then
return table.Count( gmtab.maps )
end
return 0
end
hook.Add( "PlayerInitialSpawn", "SendAvailableGamemodes", SendAvailableGamemodes )
local AllMaps = file.Find( "maps/*.bsp", "GAME" )
for key, map in pairs( AllMaps ) do
AllMaps[ key ] = string.gsub( map, ".bsp", "" )
end
local GameModes = engine.GetGamemodes()
for _, gm in pairs( engine.GetGamemodes() ) do
local info = file.Read( "gamemodes/"..gm.name.."/"..gm.name..".txt", "GAME" )
if ( info ) then
local info = util.KeyValuesToTable( info )
if ( info.selectable == 1 ) then
g_PlayableGamemodes[ gm.name ] = {}
g_PlayableGamemodes[ gm.name ].key = gm.name
g_PlayableGamemodes[ gm.name ].name = gm.title
g_PlayableGamemodes[ gm.name ].label = info.title
g_PlayableGamemodes[ gm.name ].description = info.description
g_PlayableGamemodes[ gm.name ].author = info.author_name
g_PlayableGamemodes[ gm.name ].authorurl = info.author_url
g_PlayableGamemodes[ gm.name ].maps = {}
if ( info.fretta_maps ) then
for _, mapname in pairs( AllMaps ) do
mapname = string.lower(mapname)
for _, p in pairs( info.fretta_maps ) do
if ( string.sub( mapname, 1, #p ) == p ) then
table.insert( g_PlayableGamemodes[ gm.name ].maps, mapname )
end
end
end
else
g_PlayableGamemodes[ gm.name ].maps = AllMaps
end
if ( info.fretta_maps_disallow ) then
for key, mapname in pairs( g_PlayableGamemodes[ gm.name ].maps ) do
mapname = string.lower(mapname)
for _, p in pairs( info.fretta_maps_disallow ) do
if ( string.sub( mapname, 1, #p ) == p ) then
g_PlayableGamemodes[ gm.name ].maps[ key ] = nil
end
end
end
end
end
end
end
GameModes = nil
function GM:IsValidGamemode( gamemode, map )
if ( g_PlayableGamemodes[ gamemode ] == nil ) then return false end
if ( map == nil ) then return true end
for _, mapname in pairs( g_PlayableGamemodes[ gamemode ].maps ) do
if ( mapname == map ) then return true end
end
return false
end
local gVotes = {}
function GM:VotePlayGamemode( ply, gamemode )
if ( !gamemode ) then return end
if ( GAMEMODE.WinningGamemode ) then return end
if ( !GAMEMODE:InGamemodeVote() ) then return end
if ( !GAMEMODE:IsValidGamemode( gamemode ) ) then return end
ply:SetNWString( "Wants", gamemode )
end
concommand.Add( "votegamemode", function( pl, cmd, args ) GAMEMODE:VotePlayGamemode( pl, args[1] ) end )
function GM:VotePlayMap( ply, map )
if ( !map ) then return end
if ( !GAMEMODE.WinningGamemode ) then return end
if ( !GAMEMODE:InGamemodeVote() ) then return end
if ( !GAMEMODE:IsValidGamemode( GAMEMODE.WinningGamemode, map ) ) then return end
ply:SetNWString( "Wants", map )
end
concommand.Add( "votemap", function( pl, cmd, args ) GAMEMODE:VotePlayMap( pl, args[1] ) end )
function GM:GetFractionOfPlayersThatWantChange()
local Humans = player.GetHumans()
local NumHumans = #Humans
local WantsChange = 0
for k, player in pairs( Humans ) do
if ( player:GetNWBool( "WantsVote" ) ) then
WantsChange = WantsChange + 1
end
-- Don't count players that aren't connected yet
if ( !player:IsConnected() ) then
NumHumans = NumHumans - 1
end
end
local fraction = WantsChange / NumHumans
return fraction, NumHumans, WantsChange
end
function GM:GetVotesNeededForChange()
local Fraction, NumHumans, WantsChange = GAMEMODE:GetFractionOfPlayersThatWantChange()
local FractionNeeded = fretta_votesneeded:GetFloat()
local VotesNeeded = math.ceil( FractionNeeded * NumHumans )
return VotesNeeded - WantsChange
end
function GM:CountVotesForChange()
if ( CurTime() >= GetConVarNumber( "fretta_votegraceperiod" ) ) then -- can't vote too early on
if ( GAMEMODE:InGamemodeVote() ) then return end
fraction = GAMEMODE:GetFractionOfPlayersThatWantChange()
if ( fraction > fretta_votesneeded:GetFloat() ) then
GAMEMODE:StartGamemodeVote()
return false
end
end
return true
end
function GM:VoteForChange( ply )
if ( GetConVarNumber( "fretta_voting" ) == 0 ) then return end
if ( ply:GetNWBool( "WantsVote" ) ) then return end
ply:SetNWBool( "WantsVote", true )
local VotesNeeded = GAMEMODE:GetVotesNeededForChange()
local NeedTxt = ""
if ( VotesNeeded > 0 ) then NeedTxt = ", Color( 80, 255, 50 ), [[ (need "..VotesNeeded.." more) ]] " end
if ( CurTime() < GetConVarNumber( "fretta_votegraceperiod" ) ) then -- can't vote too early on
local timediff = math.Round( GetConVarNumber( "fretta_votegraceperiod" ) - CurTime() );
BroadcastLua( "chat.AddText( Entity("..ply:EntIndex().."), Color( 255, 255, 255 ), [[ voted to change the gamemode]] )" )
else
BroadcastLua( "chat.AddText( Entity("..ply:EntIndex().."), Color( 255, 255, 255 ), [[ voted to change the gamemode]] "..NeedTxt.." )" )
end
Msg( ply:Nick() .. " voted to change the gamemode\n" )
timer.Simple( 5, function() GAMEMODE:CountVotesForChange() end )
end
concommand.Add( "VoteForChange", function( pl, cmd, args ) GAMEMODE:VoteForChange( pl ) end )
timer.Create( "VoteForChangeThink", 10, 0, function() if ( GAMEMODE ) then GAMEMODE.CountVotesForChange( GAMEMODE ) end end )
function GM:ClearPlayerWants()
for k, ply in pairs( player.GetAll() ) do
ply:SetNWString( "Wants", "" )
end
end
function GM:StartGamemodeVote()
if( !GAMEMODE.m_bVotingStarted ) then
SetGlobalBool( "InGamemodeVote", true )
if ( fretta_voting:GetBool() ) then
if #g_PlayableGamemodes >= 2 then
GAMEMODE:ClearPlayerWants()
BroadcastLua( "GAMEMODE:ShowGamemodeChooser()" )
timer.Simple( fretta_votetime:GetFloat(), function() GAMEMODE:FinishGamemodeVote() end )
SetGlobalFloat( "VoteEndTime", CurTime() + fretta_votetime:GetFloat() )
else
GAMEMODE.WinningGamemode = GAMEMODE:WorkOutWinningGamemode()
GAMEMODE:StartMapVote()
end
else
GAMEMODE.WinningGamemode = GAMEMODE.FolderName
GAMEMODE:StartMapVote()
end
GAMEMODE.m_bVotingStarted = true;
end
end
function GM:StartMapVote()
-- If there's only one map, let the 'random map' thing choose it
if ( GetNumberOfGamemodeMaps( GAMEMODE.WinningGamemode ) == 1 ) then
return GAMEMODE:FinishMapVote( true )
end
BroadcastLua( "GAMEMODE:ShowMapChooserForGamemode( \""..GAMEMODE.WinningGamemode.."\" )" );
timer.Simple( fretta_votetime:GetFloat(), function() GAMEMODE:FinishMapVote() end )
SetGlobalFloat( "VoteEndTime", CurTime() + fretta_votetime:GetFloat() )
end
function GM:GetWinningWant()
local Votes = {}
for k, ply in pairs( player.GetAll() ) do
local want = ply:GetNWString( "Wants", nil )
if ( want && want != "" ) then
Votes[ want ] = Votes[ want ] or 0
Votes[ want ] = Votes[ want ] + 1
end
end
return table.GetWinningKey( Votes )
end
function GM:WorkOutWinningGamemode()
if ( GAMEMODE.WinningGamemode ) then return GAMEMODE.WinningGamemode end
-- Gamemode Voting disabled, return current gamemode
if ( !fretta_voting:GetBool() ) then
return GAMEMODE.FolderName
end
local winner = GAMEMODE:GetWinningWant()
if ( !winner ) then return GetRandomGamemodeName() end
return winner
end
function GM:GetWinningMap( WinningGamemode )
if ( GAMEMODE.WinningMap ) then return GAMEMODE.WinningMap end
local winner = GAMEMODE:GetWinningWant()
if ( !winner ) then return GetRandomGamemodeMap( GAMEMODE.WinningGamemode ) end
return winner
end
function GM:FinishGamemodeVote()
GAMEMODE.WinningGamemode = GAMEMODE:WorkOutWinningGamemode()
GAMEMODE:ClearPlayerWants()
-- Send bink bink notification
BroadcastLua( "GAMEMODE:GamemodeWon( '"..GAMEMODE.WinningGamemode.."' )" );
-- Start map vote..
timer.Simple( 2, function() GAMEMODE:StartMapVote() end )
end
function GM:FinishMapVote()
GAMEMODE.WinningMap = GAMEMODE:GetWinningMap()
GAMEMODE:ClearPlayerWants()
-- Send bink bink notification
BroadcastLua( "GAMEMODE:ChangingGamemode( '"..GAMEMODE.WinningGamemode.."', '"..GAMEMODE.WinningMap.."' )" );
-- Start map vote?
timer.Simple( 3, function() GAMEMODE:ChangeGamemode() end )
end
function GM:ChangeGamemode()
local gm = GAMEMODE:WorkOutWinningGamemode()
local mp = GAMEMODE:GetWinningMap()
RunConsoleCommand( "gamemode", gm )
RunConsoleCommand( "changelevel", mp )
end

View File

@ -0,0 +1,245 @@
/*---------------------------------------------------------
Name: gamemode:GetValidSpectatorModes( Player ply )
Desc: Gets a table of the allowed spectator modes (OBS_MODE_INEYE, etc)
Player is the player object of the spectator
---------------------------------------------------------*/
function GM:GetValidSpectatorModes( ply )
// Note: Override this and return valid modes per player/team
return GAMEMODE.ValidSpectatorModes
end
/*---------------------------------------------------------
Name: gamemode:GetValidSpectatorEntityNames( Player ply )
Desc: Returns a table of entities that can be spectated (player etc)
---------------------------------------------------------*/
function GM:GetValidSpectatorEntityNames( ply )
// Note: Override this and return valid entity names per player/team
return GAMEMODE.ValidSpectatorEntities
end
/*---------------------------------------------------------
Name: gamemode:IsValidSpectator( Player ply )
Desc: Is our player spectating - and valid?
---------------------------------------------------------*/
function GM:IsValidSpectator( pl )
if ( !IsValid( pl ) ) then return false end
if ( pl:Team() != TEAM_SPECTATOR && !pl:IsObserver() ) then return false end
return true
end
/*---------------------------------------------------------
Name: gamemode:IsValidSpectatorTarget( Player pl, Entity ent )
Desc: Checks to make sure a spectated entity is valid.
By default, you can change GM.CanOnlySpectate own team if you want to
prevent players from spectating the other team.
---------------------------------------------------------*/
function GM:IsValidSpectatorTarget( pl, ent )
if ( !IsValid( ent ) ) then return false end
if ( ent == pl ) then return false end
if ( !table.HasValue( GAMEMODE:GetValidSpectatorEntityNames( pl ), ent:GetClass() ) ) then return false end
if ( ent:IsPlayer() && !ent:Alive() ) then return false end
if ( ent:IsPlayer() && ent:IsObserver() ) then return false end
if ( pl:Team() != TEAM_SPECTATOR && ent:IsPlayer() && GAMEMODE.CanOnlySpectateOwnTeam && pl:Team() != ent:Team() ) then return false end
return true
end
/*---------------------------------------------------------
Name: gamemode:GetSpectatorTargets( Player pl )
Desc: Returns a table of entities the player can spectate.
---------------------------------------------------------*/
function GM:GetSpectatorTargets( pl )
local t = {}
for k, v in pairs( GAMEMODE:GetValidSpectatorEntityNames( pl ) ) do
t = table.Merge( t, ents.FindByClass( v ) )
end
return t
end
/*---------------------------------------------------------
Name: gamemode:FindRandomSpectatorTarget( Player pl )
Desc: Finds a random player/ent we can spectate.
This is called when a player is first put in spectate.
---------------------------------------------------------*/
function GM:FindRandomSpectatorTarget( pl )
local Targets = GAMEMODE:GetSpectatorTargets( pl )
return table.Random( Targets )
end
/*---------------------------------------------------------
Name: gamemode:FindNextSpectatorTarget( Player pl, Entity ent )
Desc: Finds the next entity we can spectate.
ent param is the current entity we are viewing.
---------------------------------------------------------*/
function GM:FindNextSpectatorTarget( pl, ent )
local Targets = GAMEMODE:GetSpectatorTargets( pl )
return table.FindNext( Targets, ent )
end
/*---------------------------------------------------------
Name: gamemode:FindPrevSpectatorTarget( Player pl, Entity ent )
Desc: Finds the previous entity we can spectate.
ent param is the current entity we are viewing.
---------------------------------------------------------*/
function GM:FindPrevSpectatorTarget( pl, ent )
local Targets = GAMEMODE:GetSpectatorTargets( pl )
return table.FindPrev( Targets, ent )
end
/*---------------------------------------------------------
Name: gamemode:StartEntitySpectate( Player pl )
Desc: Called when we start spectating.
---------------------------------------------------------*/
function GM:StartEntitySpectate( pl )
local CurrentSpectateEntity = pl:GetObserverTarget()
for i=1, 32 do
if ( GAMEMODE:IsValidSpectatorTarget( pl, CurrentSpectateEntity ) ) then
pl:SpectateEntity( CurrentSpectateEntity )
pl:SetupHands( CurrentSpectateEntity )
return
end
CurrentSpectateEntity = GAMEMODE:FindRandomSpectatorTarget( pl )
end
end
/*---------------------------------------------------------
Name: gamemode:NextEntitySpectate( Player pl )
Desc: Called when we want to spec the next entity.
---------------------------------------------------------*/
function GM:NextEntitySpectate( pl )
local Target = pl:GetObserverTarget()
for i=1, 32 do
Target = GAMEMODE:FindNextSpectatorTarget( pl, Target )
if ( GAMEMODE:IsValidSpectatorTarget( pl, Target ) ) then
pl:SpectateEntity( Target )
pl:SetupHands( Target )
return
end
end
end
/*---------------------------------------------------------
Name: gamemode:PrevEntitySpectate( Player pl )
Desc: Called when we want to spec the previous entity.
---------------------------------------------------------*/
function GM:PrevEntitySpectate( pl )
local Target = pl:GetObserverTarget()
for i=1, 32 do
Target = GAMEMODE:FindPrevSpectatorTarget( pl, Target )
if ( GAMEMODE:IsValidSpectatorTarget( pl, Target ) ) then
pl:SpectateEntity( Target )
pl:SetupHands( Target )
return
end
end
end
/*---------------------------------------------------------
Name: gamemode:ChangeObserverMode( Player pl, Number mode )
Desc: Change the observer mode of a player.
---------------------------------------------------------*/
function GM:ChangeObserverMode( pl, mode )
if ( pl:GetInfoNum( "cl_spec_mode", 0) != mode ) then
pl:ConCommand( "cl_spec_mode "..mode )
end
if ( mode == OBS_MODE_IN_EYE || mode == OBS_MODE_CHASE ) then
GAMEMODE:StartEntitySpectate( pl, mode )
end
pl:SpectateEntity( NULL )
pl:Spectate( mode )
end
/*---------------------------------------------------------
Name: gamemode:BecomeObserver( Player pl )
Desc: Called when we first become a spectator.
---------------------------------------------------------*/
function GM:BecomeObserver( pl )
local mode = pl:GetInfoNum( "cl_spec_mode", OBS_MODE_CHASE )
if ( !table.HasValue( GAMEMODE:GetValidSpectatorModes( pl ), mode ) ) then
mode = table.FindNext( GAMEMODE:GetValidSpectatorModes( pl ), mode )
end
GAMEMODE:ChangeObserverMode( pl, mode )
end
local function spec_mode( pl, cmd, args )
if ( !GAMEMODE:IsValidSpectator( pl ) ) then return end
local mode = pl:GetObserverMode()
local nextmode = table.FindNext( GAMEMODE:GetValidSpectatorModes( pl ), mode )
GAMEMODE:ChangeObserverMode( pl, nextmode )
end
concommand.Add( "spec_mode", spec_mode )
local function spec_next( pl, cmd, args )
if ( !GAMEMODE:IsValidSpectator( pl ) ) then return end
if ( !table.HasValue( GAMEMODE:GetValidSpectatorModes( pl ), pl:GetObserverMode() ) ) then return end
GAMEMODE:NextEntitySpectate( pl )
end
concommand.Add( "spec_next", spec_next )
local function spec_prev( pl, cmd, args )
if ( !GAMEMODE:IsValidSpectator( pl ) ) then return end
if ( !table.HasValue( GAMEMODE:GetValidSpectatorModes( pl ), pl:GetObserverMode() ) ) then return end
GAMEMODE:PrevEntitySpectate( pl )
end
concommand.Add( "spec_prev", spec_prev )

View File

@ -0,0 +1,56 @@
/*---------------------------------------------------------
Name: UTIL_SpawnAllPlayers
Desc: Respawn all non-spectators, providing they are allowed to spawn.
---------------------------------------------------------*/
function UTIL_SpawnAllPlayers()
for k,v in pairs( player.GetAll() ) do
if ( v:CanRespawn() && v:Team() != TEAM_SPECTATOR && v:Team() != TEAM_CONNECTING ) then
v:Spawn()
end
end
end
/*---------------------------------------------------------
Name: UTIL_StripAllPlayers
Desc: Clears all weapons and ammo from all players.
---------------------------------------------------------*/
function UTIL_StripAllPlayers()
for k,v in pairs( player.GetAll() ) do
if ( v:Team() != TEAM_SPECTATOR && v:Team() != TEAM_CONNECTING ) then
v:StripWeapons()
v:StripAmmo()
end
end
end
/*---------------------------------------------------------
Name: UTIL_FreezeAllPlayers
Desc: Freeze all non-spectators.
---------------------------------------------------------*/
function UTIL_FreezeAllPlayers()
for k,v in pairs( player.GetAll() ) do
if ( v:Team() != TEAM_SPECTATOR && v:Team() != TEAM_CONNECTING ) then
v:Freeze( true )
end
end
end
/*---------------------------------------------------------
Name: UTIL_UnFreezeAllPlayers
Desc: Removes frozen flag from all players.
---------------------------------------------------------*/
function UTIL_UnFreezeAllPlayers()
for k,v in pairs( player.GetAll() ) do
if ( v:Team() != TEAM_SPECTATOR && v:Team() != TEAM_CONNECTING ) then
v:Freeze( false )
end
end
end

View File

@ -0,0 +1,111 @@
-- client cvars to control deathmsgs
local hud_deathnotice_time = CreateClientConVar( "hud_deathnotice_time", "6", true, false )
local hud_deathnotice_limit = CreateClientConVar( "hud_deathnotice_limit", "5", true, false )
/*
This is the player death panel. This should be parented to a DeathMessage_Panel. The DeathMessage_Panel that
it's parented to controls aspects such as the position on screen. All this panel's job is to print the
specific death it's been given and fade out before its RetireTime.
*/
local PANEL = {}
Derma_Hook( PANEL, "Paint", "Paint", "GameNotice" )
Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "GameNotice" )
Derma_Hook( PANEL, "PerformLayout", "Layout", "GameNotice" )
function PANEL:Init()
self.m_bHighlight = false
self.Padding = 8
self.Spacing = 8
self.Items = {}
end
function PANEL:AddEntityText( txt )
if ( type( txt ) == "string" ) then return false end
if ( type( txt ) == "Player" ) then
self:AddText( txt:Nick(), GAMEMODE:GetTeamColor( txt ) )
if ( txt == LocalPlayer() ) then self.m_bHighlight = true end
return true
end
if( txt:IsValid() ) then
self:AddText( txt:GetClass(), GAMEMODE.DeathNoticeDefaultColor )
else
self:AddText( tostring( txt ) )
end
end
function PANEL:AddItem( item )
table.insert( self.Items, item )
self:InvalidateLayout( true )
end
function PANEL:AddText( txt, color )
if ( self:AddEntityText( txt ) ) then return end
local txt = tostring( txt )
local lbl = vgui.Create( "DLabel", self )
Derma_Hook( lbl, "ApplySchemeSettings", "Scheme", "GameNoticeLabel" )
lbl:ApplySchemeSettings()
lbl:SetText( txt )
if( string.Left( txt , 1 ) == "#" && !color ) then color = GAMEMODE.DeathNoticeDefaultColor end // localised ent death
if( GAMEMODE.DeathNoticeTextColor && !color ) then color = GAMEMODE.DeathNoticeTextColor end // something else
if ( !color ) then color = color_white end
lbl:SetTextColor( color )
self:AddItem( lbl )
end
function PANEL:AddIcon( txt )
if ( killicon.Exists( txt ) ) then
local icon = vgui.Create( "DKillIcon", self )
icon:SetName( txt )
icon:SizeToContents()
self:AddItem( icon )
else
self:AddText( "killed" )
end
end
function PANEL:PerformLayout()
local x = self.Padding
local height = self.Padding * 0.5
for k, v in pairs( self.Items ) do
v:SetPos( x, self.Padding * 0.5 )
v:SizeToContents()
x = x + v:GetWide() + self.Spacing
height = math.max( height, v:GetTall() + self.Padding )
end
self:SetSize( x + self.Padding, height )
end
derma.DefineControl( "GameNotice", "", PANEL, "DPanel" )

View File

@ -0,0 +1,47 @@
local PANEL = {}
surface.CreateLegacyFont( "Roboto", 32, 800, true, false, "FHUDElement" )
AccessorFunc( PANEL, "m_bPartOfBar", "PartOfBar" )
function PANEL:Init()
self:SetText( "-" )
self:SetTextColor( self:GetDefaultTextColor() )
self:SetFont( "FHUDElement" )
self:ChooseParent()
end
// This makes it so that it's behind chat & hides when you're in the menu
// But it also removes the ability to click on it. So override it if you want to.
function PANEL:ChooseParent()
self:ParentToHUD()
end
function PANEL:GetPadding()
return 16
end
function PANEL:GetDefaultTextColor()
return Color( 255, 255, 255, 255 )
end
function PANEL:GetTextLabelColor()
return Color( 255, 255, 0 )
end
function PANEL:GetTextLabelFont()
return "HudSelectionText"
end
function PANEL:Paint()
if ( !self.m_bPartOfBar ) then
draw.RoundedBox( 4, 0, 0, self:GetWide(), self:GetTall(), Color( 0, 0, 0, 100 ) )
end
end
derma.DefineControl( "HudBase", "A HUD Base Element (override to change the style)", PANEL, "DLabel" )

View File

@ -0,0 +1,107 @@
local PANEL = {}
AccessorFunc( PANEL, "m_Items", "Items" )
AccessorFunc( PANEL, "m_Horizontal", "Horizontal" )
AccessorFunc( PANEL, "m_Spacing", "Spacing" )
AccessorFunc( PANEL, "m_AlignBottom", "AlignBottom" )
AccessorFunc( PANEL, "m_AlignCenter", "AlignCenter" )
function PANEL:Init()
self.m_Items = {}
self:SetHorizontal( true )
self:SetText( "" )
self:SetAlignCenter( true )
self:SetSpacing( 8 )
end
function PANEL:AddItem( item )
item:SetParent( self )
table.insert( self.m_Items, item )
self:InvalidateLayout()
item:SetPaintBackgroundEnabled( false )
item.m_bPartOfBar = true
end
function PANEL:PerformLayout()
if ( self.m_Horizontal ) then
local x = self.m_Spacing
local tallest = 0
for k, v in pairs( self.m_Items ) do
v:SetPos( x, 0 )
x = x + v:GetWide() + self.m_Spacing
tallest = math.max( tallest, v:GetTall() )
if ( self.m_AlignBottom ) then v:AlignBottom() end
if ( self.m_AlignCenter ) then v:CenterVertical() end
end
self:SetSize( x, tallest )
else
// todo.
end
end
derma.DefineControl( "DHudBar", "", PANEL, "HudBase" )
local PANEL = {}
AccessorFunc( PANEL, "m_ValueFunction", "ValueFunction" )
AccessorFunc( PANEL, "m_ColorFunction", "ColorFunction" )
/*---------------------------------------------------------
Name: Init
---------------------------------------------------------*/
function PANEL:Init()
end
function PANEL:GetTextValueFromFunction()
if (!self.m_ValueFunction) then return "-" end
return tostring( self:m_ValueFunction() )
end
function PANEL:GetColorFromFunction()
if (!self.m_ColorFunction) then return self:GetDefaultTextColor() end
return self:m_ColorFunction()
end
function PANEL:Think()
self:SetTextColor( self:GetColorFromFunction() )
self:SetText( self:GetTextValueFromFunction() )
end
derma.DefineControl( "DHudUpdater", "A HUD Element", PANEL, "DHudElement" )
local PANEL = {}
AccessorFunc( PANEL, "m_Function", "Function" )
/*---------------------------------------------------------
Name: Init
---------------------------------------------------------*/
function PANEL:Init()
HudBase.Init( self )
end
function PANEL:Think()
if ( !self.m_ValueFunction ) then return end
self:SetTextColor( self:GetColorFromFunction() )
local EndTime = self:m_ValueFunction()
if ( EndTime == -1 ) then return end
if ( !EndTime || EndTime < CurTime() ) then
self:SetText( "00:00" )
return
end
local Time = util.ToMinutesSeconds( EndTime - CurTime() )
self:SetText( Time )
end
derma.DefineControl( "DHudCountdown", "A HUD Element", PANEL, "DHudUpdater" )

View File

@ -0,0 +1,39 @@
local PANEL = {}
/*---------------------------------------------------------
Name: Init
---------------------------------------------------------*/
function PANEL:Init()
end
function PANEL:SetLabel( text )
self.LabelPanel = vgui.Create( "DLabel", self )
self.LabelPanel:SetText( text )
self.LabelPanel:SetTextColor( self:GetTextLabelColor() )
self.LabelPanel:SetFont( self:GetTextLabelFont() )
end
/*---------------------------------------------------------
Name: PerformLayout
---------------------------------------------------------*/
function PANEL:PerformLayout()
self:SetContentAlignment( 5 )
if ( self.LabelPanel ) then
self.LabelPanel:SetPos( self:GetPadding(), self:GetPadding() )
self.LabelPanel:SizeToContents()
self.LabelPanel:SetSize( self.LabelPanel:GetWide() + self:GetPadding() * 0.5, self.LabelPanel:GetTall() + self:GetPadding() * 0.5 )
self:SetTextInset( self.LabelPanel:GetWide() + self:GetPadding(), 0 )
self:SetContentAlignment( 4 )
end
self:SizeToContents( )
self:SetSize( self:GetWide() + self:GetPadding(), self:GetTall() + self:GetPadding() )
end
derma.DefineControl( "DHudElement", "A HUD Element", PANEL, "HudBase" )

View File

@ -0,0 +1,161 @@
local PANEL = {}
AccessorFunc( PANEL, "Spacing", "Spacing" )
/*---------------------------------------------------------
Name: Init
---------------------------------------------------------*/
function PANEL:Init()
self.Items = {}
self:SetSpacing( 8 )
self:SetPaintBackgroundEnabled( false )
self:SetPaintBorderEnabled( false )
self:ParentToHUD()
end
// This makes it so that it's behind chat & hides when you're in the menu
// But it also removes the ability to click on it. So override it if you want to.
function PANEL:ChooseParent()
self:ParentToHUD()
end
/*---------------------------------------------------------
Name: GetCanvas
---------------------------------------------------------*/
function PANEL:Clear( bDelete )
for k, panel in pairs( self.Items ) do
if ( panel && panel:IsValid() ) then
panel:SetParent( panel )
panel:SetVisible( false )
if ( bDelete ) then
panel:Remove()
end
end
end
self.Items = {}
end
/*---------------------------------------------------------
Name: AddItem
---------------------------------------------------------*/
function PANEL:AddItem( item, relative, pos )
if (!item || !item:IsValid()) then return end
item.HUDPos = pos
item.HUDrelative = relative
item:SetVisible( true )
item:SetParent( self )
table.insert( self.Items, item )
self:InvalidateLayout()
end
function PANEL:PositionItem( item )
if ( item.Positioned ) then return end
if ( IsValid( item.HUDrelative ) && item != item.HUDrelative ) then self:PositionItem( item.HUDrelative ) end
local SPACING = self:GetSpacing()
item:InvalidateLayout( true )
if ( item.HUDPos == 7 || item.HUDPos == 8 || item.HUDPos == 9 ) then
if ( IsValid( item.HUDrelative ) ) then
item:MoveAbove( item.HUDrelative, SPACING )
else
item:AlignTop()
end
end
if ( item.HUDPos == 4 || item.HUDPos == 5 || item.HUDPos == 6 ) then
if ( IsValid( item.HUDrelative ) ) then
item.y = item.HUDrelative.y
else
item:CenterVertical()
end
end
if ( item.HUDPos == 1 || item.HUDPos == 2 || item.HUDPos == 3 ) then
if ( IsValid( item.HUDrelative ) ) then
item:MoveBelow( item.HUDrelative, SPACING )
else
item:AlignBottom()
end
end
if ( item.HUDPos == 7 || item.HUDPos == 4 || item.HUDPos == 1 ) then
if ( IsValid( item.HUDrelative ) ) then
item.x = item.HUDrelative.x
else
item:AlignLeft()
end
end
if ( item.HUDPos == 8 || item.HUDPos == 5 || item.HUDPos == 2 ) then
if ( IsValid( item.HUDrelative ) ) then
item.x = item.HUDrelative.x + ( item.HUDrelative:GetWide() - item:GetWide() ) / 2
else
item:CenterHorizontal()
end
end
if ( item.HUDPos == 9 || item.HUDPos == 6 || item.HUDPos == 3 ) then
if ( IsValid( item.HUDrelative ) ) then
item.x = item.HUDrelative.x + item.HUDrelative:GetWide() - item:GetWide()
else
item:AlignRight()
end
end
if ( item.HUDPos == 4 && IsValid( item.HUDrelative ) ) then
item:MoveLeftOf( item.HUDrelative, SPACING )
end
if ( item.HUDPos == 6 && IsValid( item.HUDrelative ) ) then
item:MoveRightOf( item.HUDrelative, SPACING )
end
item.Positioned = true
end
function PANEL:Think()
self:InvalidateLayout()
end
/*---------------------------------------------------------
Name: PerformLayout
---------------------------------------------------------*/
function PANEL:PerformLayout()
self:SetPos( 32, 32 )
self:SetWide( ScrW() - 64 )
self:SetTall( ScrH() - 64 )
for k, item in pairs( self.Items ) do
item.Positioned = false
end
for k, item in pairs( self.Items ) do
self:PositionItem( item )
end
end
derma.DefineControl( "DHudLayout", "A HUD Layout Base", PANEL, "Panel" )

View File

@ -0,0 +1,219 @@
include( "vgui_scoreboard_team.lua" )
include( "vgui_scoreboard_small.lua" )
local PANEL = {}
Derma_Hook( PANEL, "Paint", "Paint", "ScoreHeader" )
Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "ScoreHeader" )
Derma_Hook( PANEL, "PerformLayout", "Layout", "ScoreHeader" )
function PANEL:Init()
self.Columns = {}
self.iTeamID = 0
self.HostName = vgui.Create( "DLabel", self )
self.HostName:SetText( GetHostName() )
self.GamemodeName = vgui.Create( "DLabel", self )
self.GamemodeName:SetText( GAMEMODE.Name .. " | Version: ".. GAMEMODE._VERSION .. " - Rev. ".. GAMEMODE.REVISION )
self:SetHeight( 64 )
end
derma.DefineControl( "ScoreboardHeader", "", PANEL, "Panel" )
local PANEL = {}
AccessorFunc( PANEL, "m_bHorizontal", "Horizontal" )
AccessorFunc( PANEL, "m_iPadding", "Padding" )
AccessorFunc( PANEL, "m_iRowHeight", "RowHeight" )
AccessorFunc( PANEL, "m_bShowScoreHeaders", "ShowScoreboardHeaders" )
Derma_Hook( PANEL, "Paint", "Paint", "ScorePanel" )
Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "ScorePanel" )
Derma_Hook( PANEL, "PerformLayout", "Layout", "ScorePanel" )
function PANEL:Init()
self.SortDesc = true
self.Boards = {}
self.SmallBoards = {}
self.Columns = {}
self:SetRowHeight( 32 )
self:SetHorizontal( false )
self:SetPadding( 10 )
self:SetShowScoreboardHeaders( true )
self.Header = vgui.Create( "ScoreboardHeader", self )
local teams = team.GetAllTeams()
for k, v in pairs( teams ) do
local ScoreBoard = vgui.Create( "TeamScoreboard", self )
ScoreBoard:Setup( k, self )
self.Boards[ k ] = ScoreBoard
end
end
function PANEL:SetAsBullshitTeam( iTeamID )
if ( IsValid( self.Boards[ iTeamID ] ) ) then
self.Boards[ iTeamID ]:Remove()
self.Boards[ iTeamID ] = nil
end
self.SmallBoards[ iTeamID ] = vgui.Create( "TeamBoardSmall", self )
self.SmallBoards[ iTeamID ]:Setup( iTeamID, self )
end
function PANEL:SetSortColumns( ... )
for k, v in pairs( self.Boards ) do
v:SetSortColumns( ... )
end
end
function PANEL:AddColumn( Name, iFixedSize, fncValue, UpdateRate, TeamID, HeaderAlign, ValueAlign, Font )
local Col = {}
Col.Name = Name
Col.iFixedSize = iFixedSize
Col.fncValue = fncValue
Col.TeamID = TeamID
Col.UpdateRate = UpdateRate
Col.ValueAlign = ValueAlign
Col.HeaderAlign = HeaderAlign
Col.Font = Font
for k, v in pairs( self.Boards ) do
v:AddColumn( Col )
end
return Col
end
function PANEL:Layout4By4( y )
local a = self.Boards[1]
local b = self.Boards[2]
local c = self.Boards[3]
local d = self.Boards[4]
local widtheach = (self:GetWide() - ( self.m_iPadding * 3 )) / 2
for k, v in pairs( self.Boards ) do
v:SizeToContents()
v:SetWide( widtheach )
end
a:SetPos( self.m_iPadding, y + self.m_iPadding )
b:SetPos( a:GetPos() + a:GetWide() + self.m_iPadding, y + self.m_iPadding )
local height = a:GetTall() + a.y
height = math.max( b:GetTall() + b.y, height )
height = height + self.m_iPadding * 2
c:SetPos( self.m_iPadding, height )
d:SetPos( c:GetPos() + c:GetWide() + self.m_iPadding, height )
local height = d:GetTall() + d.y
height = math.max( c:GetTall() + c.y, height )
height = height + self.m_iPadding * 2
return height
end
function PANEL:LayoutHorizontal( y )
local cols = table.Count( self.Boards )
if ( cols == 4 ) then
return self:Layout4By4( y )
end
local widtheach = (self:GetWide() - ( self.m_iPadding * (cols+1) )) / cols
local x = self.m_iPadding
local tallest = 0
for k, v in pairs( self.Boards ) do
v:SizeToContents()
v:SetPos( x, y )
v:SetWide( widtheach )
x = x + widtheach + self.m_iPadding
tallest = math.max( tallest, y + v:GetTall() + self.m_iPadding )
end
return tallest
end
function PANEL:LayoutVertical( y )
for k, v in pairs( self.Boards ) do
v:SizeToContents()
v:SetPos( self.m_iPadding, y )
v:SetWide( self:GetWide() - self.m_iPadding * 2 )
y = y + v:GetTall() + self.m_iPadding
end
return y
end
function PANEL:PerformLayout()
local y = 0
if ( IsValid( self.Header ) ) then
self.Header:SetPos( 0, 0 )
self.Header:SetWidth( self:GetWide() )
y = y + self.Header:GetTall() + self.m_iPadding
end
if ( self.m_bHorizontal ) then
y = self:LayoutHorizontal( y )
else
y = self:LayoutVertical( y )
end
for k, v in pairs( self.SmallBoards ) do
if ( v:ShouldShow() ) then
v:SizeToContents()
v:SetPos( self.m_iPadding, y )
v:CenterHorizontal()
y = y + v:GetTall() + self.m_iPadding
end
end
end
derma.DefineControl( "FrettaScoreboard", "", PANEL, "DPanel" )

View File

@ -0,0 +1,67 @@
local PANEL = {}
Derma_Hook( PANEL, "Paint", "Paint", "SpectatorInfo" )
Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "SpectatorInfo" )
Derma_Hook( PANEL, "PerformLayout", "Layout", "SpectatorInfo" )
function PANEL:Init()
self.LastThink = 0
end
function PANEL:Setup( iTeam, pMainScoreboard )
self.iTeam = iTeam
end
function PANEL:GetPlayers()
return team.GetPlayers( self.iTeam )
end
function PANEL:ShouldShow()
local players = team.GetPlayers( self.iTeam )
if ( !players || #players == 0 ) then
return false
end
return true
end
function PANEL:UpdateText( NewText )
local OldText = self:GetValue()
if ( OldText == NewText ) then return end
self:SetText( NewText )
self:SizeToContents()
self:InvalidateLayout()
self:GetParent():InvalidateLayout()
end
function PANEL:Think()
if ( self.LastThink > RealTime() ) then return end
self.LastThink = RealTime() + 1
local players = team.GetPlayers( self.iTeam )
if ( !players || #players == 0 ) then
local OldText = self:GetValue()
self:UpdateText( "" )
return
end
local Str = team.GetName( self.iTeam ) .. ": "
for k, v in pairs( players ) do
Str = Str .. v:Name() .. ", "
end
Str = Str:sub( 0, -3 )
self:UpdateText( Str )
end
derma.DefineControl( "TeamBoardSmall", "", PANEL, "DLabel" )

View File

@ -0,0 +1,218 @@
local PANEL = {}
Derma_Hook( PANEL, "Paint", "Paint", "TeamScoreboardHeader" )
Derma_Hook( PANEL, "ApplySchemeSettings", "Scheme", "TeamScoreboardHeader" )
Derma_Hook( PANEL, "PerformLayout", "Layout", "TeamScoreboardHeader" )
function PANEL:Init()
self.Columns = {}
self.iTeamID = 0
self.PlayerCount = 0
self.TeamName = vgui.Create( "DLabel", self )
self.TeamScore = vgui.Create( "DLabel", self )
end
function PANEL:Setup( iTeam, pMainScoreboard )
self.TeamName:SetText( team.GetName( iTeam ) )
self.iTeamID = iTeam
end
function PANEL:Think()
local Count = #team.GetPlayers( self.iTeamID )
if ( self.PlayerCount != Count ) then
self.PlayerCount = Count
self.TeamName:SetText( team.GetName( self.iTeamID ) .. " (" .. self.PlayerCount .. " Players)" )
end
self.TeamScore:SetText( team.GetScore( self.iTeamID ) )
end
derma.DefineControl( "TeamScoreboardHeader", "", PANEL, "Panel" )
local PANEL = {}
function PANEL:Init()
self.Columns = {}
self.List = vgui.Create( "DListView", self )
self.List:SetSortable( false )
self.List:DisableScrollbar()
self.Header = vgui.Create( "TeamScoreboardHeader", self )
end
function PANEL:Setup( iTeam, pMainScoreboard )
self.iTeam = iTeam
self.pMain = pMainScoreboard
self.Header:Setup( iTeam, pMainScoreboard )
end
function PANEL:SizeToContents()
self.List:SizeToContents()
local tall = self.List:GetTall()
self:SetTall( tall + self.Header:GetTall() )
end
function PANEL:PerformLayout()
if ( self.pMain:GetShowScoreboardHeaders() ) then
self.Header:SetPos( 0, 0 )
self.Header:CopyWidth( self )
else
self.Header:SetTall( 0 )
self.Header:SetVisible( false )
end
self:SizeToContents()
self.List:StretchToParent( 0, self.Header:GetTall(), 0, 0 )
self.List:SetDataHeight( self.pMain:GetRowHeight() )
self.List:SetHeaderHeight( 16 )
end
function PANEL:AddColumn( col )
table.insert( self.Columns, col )
local pnlCol = self.List:AddColumn( col.Name )
if (col.iFixedSize) then pnlCol:SetMinWidth( col.iFixedSize ) pnlCol:SetMaxWidth( col.iFixedSize ) end
if (col.HeaderAlign) then
pnlCol.Header:SetContentAlignment( col.HeaderAlign )
end
-- Credits to dhantasmic on GitHub for this fix
pnlCol:GetChildren()[1]:SetVisible( false )
pnlCol:GetChildren()[2]:SetVisible( false )
Derma_Hook( pnlCol, "Paint", "Paint", "ScorePanelHeader" )
pnlCol.cTeamColor = team.GetColor( self.iTeam )
Derma_Hook( pnlCol.Header, "Paint", "Paint", "ScorePanelHeaderLabel" )
Derma_Hook( pnlCol.Header, "ApplySchemeSettings", "Scheme", "ScorePanelHeaderLabel" )
Derma_Hook( pnlCol.Header, "PerformLayout", "Layout", "ScorePanelHeaderLabel" )
pnlCol.Header:ApplySchemeSettings()
end
function PANEL:SetSortColumns( ... )
self.SortArgs = ...
end
function PANEL:FindPlayerLine( ply )
for _, line in pairs( self.List.Lines ) do
if ( line.pPlayer == ply ) then return line end
end
local line = self.List:AddLine()
line.pPlayer = ply
line.UpdateTime = {}
Derma_Hook( line, "Paint", "Paint", "ScorePanelLine" )
Derma_Hook( line, "ApplySchemeSettings", "Scheme", "ScorePanelLine" )
Derma_Hook( line, "PerformLayout", "Layout", "ScorePanelLine" )
self.pMain:InvalidateLayout()
return line
end
function PANEL:UpdateColumn( i, col, pLine )
if ( !col.fncValue ) then return end
pLine.UpdateTime[i] = pLine.UpdateTime[i] or 0
if ( col.UpdateRate == 0 && pLine.UpdateTime[i] != 0 ) then return end // 0 = only update once
if ( pLine.UpdateTime[i] > RealTime() ) then return end
pLine.UpdateTime[i] = RealTime() + col.UpdateRate
local Value = col.fncValue( pLine.pPlayer )
if ( Value == nil ) then return end
local lbl = pLine:SetColumnText( i, Value )
if ( IsValid( lbl ) && !lbl.bScorePanelHooks ) then
lbl.bScorePanelHooks = true
if ( col.ValueAlign ) then lbl:SetContentAlignment( col.ValueAlign ) end
if ( col.Font ) then lbl:SetFont( col.Font ) end
lbl.pPlayer = pLine.pPlayer
Derma_Hook( lbl, "Paint", "Paint", "ScorePanelLabel" )
Derma_Hook( lbl, "ApplySchemeSettings", "Scheme", "ScorePanelLabel" )
Derma_Hook( lbl, "PerformLayout", "Layout", "ScorePanelLabel" )
end
end
function PANEL:UpdateLine( pLine )
for i, col in pairs( self.Columns ) do
self:UpdateColumn( i, col, pLine )
end
end
function PANEL:CleanLines( pLine )
for k, line in pairs( self.List.Lines ) do
if ( !IsValid( line.pPlayer ) || line.pPlayer:Team() != self.iTeam ) then
self.List:RemoveLine( k )
end
end
end
function PANEL:Think()
self:CleanLines()
local players = team.GetPlayers( self.iTeam )
for _, player in pairs( players ) do
local line = self:FindPlayerLine( player )
self:UpdateLine( line )
end
if ( self.SortArgs ) then
self.List:SortByColumns( unpack(self.SortArgs) )
end
end
derma.DefineControl( "TeamScoreboard", "", PANEL, "Panel" )

View File

@ -0,0 +1,240 @@
local PANEL = {}
function PANEL:Init()
self:SetSkin( GAMEMODE.HudSkin )
self:ParentToHUD()
self.ControlCanvas = vgui.Create( "Panel", self )
self.ControlCanvas:MakePopup()
self.ControlCanvas:SetKeyboardInputEnabled( false )
self.lblCountDown = vgui.Create( "DLabel", self.ControlCanvas )
self.lblCountDown:SetText( "60" )
self.lblActionName = vgui.Create( "DLabel", self.ControlCanvas )
self.ctrlList = vgui.Create( "DPanelList", self.ControlCanvas )
self.ctrlList:SetDrawBackground( false )
self.ctrlList:SetSpacing( 2 )
self.ctrlList:SetPadding( 2 )
self.ctrlList:EnableHorizontal( true )
self.ctrlList:EnableVerticalScrollbar()
self.Peeps = {}
for i =1, game.MaxPlayers() do
self.Peeps[i] = vgui.Create( "DImage", self.ctrlList:GetCanvas() )
self.Peeps[i]:SetSize( 16, 16 )
self.Peeps[i]:SetZPos( 1000 )
self.Peeps[i]:SetVisible( false )
self.Peeps[i]:SetImage( "icon16/emoticon_smile.png" )
end
end
function PANEL:PerformLayout()
local cx, cy = chat.GetChatBoxPos()
self:SetPos( 0, 0 )
self:SetSize( ScrW(), ScrH() )
self.ControlCanvas:StretchToParent( 0, 0, 0, 0 )
self.ControlCanvas:SetWide( 550 )
self.ControlCanvas:SetTall( cy - 30 )
self.ControlCanvas:SetPos( 0, 30 )
self.ControlCanvas:CenterHorizontal();
self.ControlCanvas:SetZPos( 0 )
self.lblCountDown:SetFont( "FRETTA_MEDIUM_SHADOW" )
self.lblCountDown:AlignRight()
self.lblCountDown:SetTextColor( color_white )
self.lblCountDown:SetContentAlignment( 6 )
self.lblCountDown:SetWidth( 500 )
self.lblActionName:SetFont( "FRETTA_LARGE_SHADOW" )
self.lblActionName:AlignLeft()
self.lblActionName:SetTextColor( color_white )
self.lblActionName:SizeToContents()
self.lblActionName:SetWidth( 500 )
self.ctrlList:StretchToParent( 0, 60, 0, 0 )
end
function PANEL:ChooseGamemode()
self.lblActionName:SetText( "Which Gamemode Next?" )
self.ctrlList:Clear()
for name, gamemode in RandomPairs( g_PlayableGamemodes ) do
local lbl = vgui.Create( "DButton", self.ctrlList )
lbl:SetText( gamemode.label )
Derma_Hook( lbl, "Paint", "Paint", "GamemodeButton" )
Derma_Hook( lbl, "ApplySchemeSettings", "Scheme", "GamemodeButton" )
Derma_Hook( lbl, "PerformLayout", "Layout", "GamemodeButton" )
lbl:SetTall( 24 )
lbl:SetWide( 240 )
local desc = tostring( gamemode.description );
if ( gamemode.author ) then desc = desc .. "\n\nBy: " .. tostring( gamemode.author ) end
if ( gamemode.authorurl ) then desc = desc .. "\n" .. tostring( gamemode.authorurl ) end
lbl:SetTooltip( desc )
lbl.WantName = name
lbl.NumVotes = 0
lbl.DoClick = function() if GetGlobalFloat( "VoteEndTime", 0 ) - CurTime() <= 0 then return end RunConsoleCommand( "votegamemode", name ) end
self.ctrlList:AddItem( lbl )
end
end
function PANEL:ChooseMap( gamemode )
self.lblActionName:SetText( "Which Map?" )
self:ResetPeeps()
self.ctrlList:Clear()
local gm = g_PlayableGamemodes[ gamemode ]
if ( !gm ) then MsgN( "GAMEMODE MISSING, COULDN'T VOTE FOR MAP ", gamemode ) return end
for id, mapname in RandomPairs( gm.maps ) do
local lbl = vgui.Create( "DButton", self.ctrlList )
lbl:SetText( mapname )
Derma_Hook( lbl, "Paint", "Paint", "GamemodeButton" )
Derma_Hook( lbl, "ApplySchemeSettings", "Scheme", "GamemodeButton" )
Derma_Hook( lbl, "PerformLayout", "Layout", "GamemodeButton" )
lbl:SetTall( 24 )
lbl:SetWide( 240 )
lbl.WantName = mapname
lbl.NumVotes = 0
lbl.DoClick = function() if GetGlobalFloat( "VoteEndTime", 0 ) - CurTime() <= 0 then return end RunConsoleCommand( "votemap", mapname ) end
--[[if file.Exists("maps/"..mapname..".png", "MOD") then
lbl:SetTall(72)
local Image = vgui.Create("DImage", lbl)
Image:SetImage("../maps/"..mapname..".png")
Image:SizeToContents()
Image:SetSize(math.min(Image:GetWide(), 64), math.min(Image:GetTall(), 64))
Image:AlignRight(4)
Image:CenterVertical()
end]]
self.ctrlList:AddItem( lbl )
end
end
function PANEL:ResetPeeps()
for i=1, game.MaxPlayers() do
self.Peeps[i]:SetPos( math.random( 0, 600 ), -16 )
self.Peeps[i]:SetVisible( false )
self.Peeps[i].strVote = nil
end
end
function PANEL:FindWantBar( name )
for k, v in pairs( self.ctrlList:GetItems() ) do
if ( v.WantName == name ) then return v end
end
end
function PANEL:PeepThink( peep, ent )
if ( !IsValid( ent ) ) then
peep:SetVisible( false )
return
end
peep:SetTooltip( ent:Nick() )
peep:SetMouseInputEnabled( true )
if ( !peep.strVote ) then
peep:SetVisible( true )
peep:SetPos( math.random( 0, 600 ), -16 )
if ( ent == LocalPlayer() ) then
peep:SetImage( "icon16/star.png" )
end
end
peep.strVote = ent:GetNWString( "Wants", "" )
local bar = self:FindWantBar( peep.strVote )
if ( IsValid( bar ) ) then
bar.NumVotes = bar.NumVotes + 1
local vCurrentPos = Vector( peep.x, peep.y, 0 )
local vNewPos = Vector( (bar.x + bar:GetWide()) - 15 * bar.NumVotes - 4, bar.y + ( bar:GetTall() * 0.5 - 8 ), 0 )
if ( !peep.CurPos || peep.CurPos != vNewPos ) then
peep:MoveTo( vNewPos.x, vNewPos.y, 0.2 )
peep.CurPos = vNewPos
end
end
end
function PANEL:Think()
local Seconds = GetGlobalFloat( "VoteEndTime", 0 ) - CurTime()
if ( Seconds < 0 ) then Seconds = 0 end
self.lblCountDown:SetText( Format( "%i", Seconds ) )
for k, v in pairs( self.ctrlList:GetItems() ) do
v.NumVotes = 0
end
for i=1, game.MaxPlayers() do
self:PeepThink( self.Peeps[i], Entity(i) )
end
end
function PANEL:Paint()
Derma_DrawBackgroundBlur( self )
local CenterY = ScrH() / 2.0
local CenterX = ScrW() / 2.0
surface.SetDrawColor( 0, 0, 0, 200 );
surface.DrawRect( 0, 0, ScrW(), ScrH() );
end
function PANEL:FlashItem( itemname )
local bar = self:FindWantBar( itemname )
if ( !IsValid( bar ) ) then return end
timer.Simple( 0.0, function() bar.bgColor = Color( 0, 255, 255 ) surface.PlaySound( "hl1/fvox/blip.wav" ) end )
timer.Simple( 0.2, function() bar.bgColor = nil end )
timer.Simple( 0.4, function() bar.bgColor = Color( 0, 255, 255 ) surface.PlaySound( "hl1/fvox/blip.wav" ) end )
timer.Simple( 0.6, function() bar.bgColor = nil end )
timer.Simple( 0.8, function() bar.bgColor = Color( 0, 255, 255 ) surface.PlaySound( "hl1/fvox/blip.wav" ) end )
timer.Simple( 1.0, function() bar.bgColor = Color( 100, 100, 100 ) end )
end
derma.DefineControl( "VoteScreen", "", PANEL, "DPanel" )

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

View File

@ -0,0 +1,17 @@
"VertexLitGeneric"
{
"$basetexture" "models/weapons/v_models/blast_brenmk3/bren_d"
"$bumpmap" "models/weapons/v_models/blast_brenmk3/bren_n"
"$phongexponenttexture" "models/weapons/v_models/blast_brenmk3/bren_m"
"$phong" "1"
"$phongboost" ".5"
"$phongalbedoboost" "25"
"$phongfresnelranges" "[.83 .83 0]"
"$phongalbedotint" "1"
"$phongdisablehalflambert" "1"
"$envmap" "env_cubemap"
"$envmapfresnel" "1"
"$envmaptint" "[.0025 .0025 .0025]"
}

View File

@ -0,0 +1,15 @@
"VertexLitGeneric"
{
"$baseTexture" "models\weapons\V_models\bren\tex_bren_diff"
"$bumpmap" "models\weapons\V_models\bren\tex_bren_nrm"
"$halflambert" 1
"$nocull" 1
"$phong" "1"
"$phongexponent" "20"
"$phongboost" "0.75"
"$phongfresnelranges" "[.3 1 7]"
"$rimlight" "1"
"$rimlightexponent" "300"
}

View File

@ -0,0 +1,4 @@
"VertexLitGeneric"
{
"$baseTexture" "models\weapons\v_models\hands\sleeve_diffuse"
}

View File

@ -0,0 +1,18 @@
VertexLitGeneric
{
$basetexture "models\weapons\v_models\blast_brenmk3\bren_d"
$bumpmap "models\weapons\v_models\blast_brenmk3\bren_n"
$ambientocculusion "models\weapons\v_models\blast_brenmk3\bren_s"
$phongexponenttexture "models\weapons\v_models\blast_brenmk3\bren_m"
$phong 1
$phongboost ".5"
$phongalbedoboost 25
$phongfresnelranges "[.83 .83 0]"
$phongalbedotint 1
$phongdisablehalflambert 1
$envmap env_cubemap
$envmapfresnel 1
$envmaptint "[.0025 .0025 .0025]"
}

View File

@ -0,0 +1,9 @@
"UnlitGeneric"
{
"$basetexture" "prophunt_enhanced/box/box"
"$translucent" "1"
"$alphatest" "1"
"$nodraw" "1"
"$no_draw" "1"
}

View File

@ -0,0 +1,10 @@
"VertexLitGeneric"
{
"$basetexture" "prophunt_enhanced/devil"
"$surfaceprop" "Glass"
"$envmap" "env_cubemap"
"$envmapsaturation" "[.75 .75 .75]"
// Don't this may get confused?
"$translucent" "1"
"$nocull" "1"
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "prophunt_enhanced/sprites/devilball"
"$translucent" 1
"$vertexcolor" 1
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "prophunt_enhanced/sprites/devilball_pointer"
"$translucent" 1
"$vertexcolor" 1
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "prophunt_enhanced/sprites/luckyball"
"$translucent" 1
"$vertexcolor" 1
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "prophunt_enhanced/sprites/luckyball_pointer"
"$translucent" 1
"$vertexcolor" 1
}

View File

@ -0,0 +1,7 @@
"UnlitGeneric"
{
"$basetexture" "vgui/hud/wlv_bren"
"$additive" 1
"$vertexalpha" 1
"$vertexcolor" 1
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "vgui/hud_crosshair"
"$additive" "1"
"$vertexcolor" "1"
}

View File

@ -0,0 +1,5 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\btn_close"
"$translucent" "1"
}

View File

@ -0,0 +1,5 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\btn_play"
"$translucent" "1"
}

View File

@ -0,0 +1,5 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\btn_playpub"
"$translucent" "1"
}

View File

@ -0,0 +1,5 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\btn_playx"
"$translucent" "1"
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\hud_topbar"
"$vertexcolor" "1"
"$translucent" "1"
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\i_halo"
"$translucent" "1"
"$vertexcolor" "1"
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\i_light"
"$translucent" "1"
"$vertexcolor" "1"
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\i_rotate"
"$translucent" "1"
"$vertexcolor" "1"
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\i_shield"
"$translucent" "1"
"$vertexcolor" "1"
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\res_hp_1"
"$vertexcolor" "1"
"$translucent" "1"
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\res_hp_2"
"$vertexcolor" "1"
"$translucent" "1"
}

View File

@ -0,0 +1,6 @@
"UnlitGeneric"
{
"$basetexture" "vgui\phehud\res_wep"
"$vertexcolor" "1"
"$translucent" "1"
}

Some files were not shown because too many files have changed in this diff Show More