diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e362f00 --- /dev/null +++ b/.gitignore @@ -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 + diff --git a/README.md b/README.md index 6c6d6ff..12eab06 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,67 @@ -# ph-enhanced -Prop Hunt: Enhanced - By Wolvindra [REUPLOAD] +# Wolvin's - Prop Hunt: ENHANCED v.15 Rev. I + +![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). \ No newline at end of file diff --git a/cfg/listenserver.cfg b/cfg/listenserver.cfg new file mode 100644 index 0000000..fb1eb5c --- /dev/null +++ b/cfg/listenserver.cfg @@ -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_," \ No newline at end of file diff --git a/cfg/server.cfg b/cfg/server.cfg new file mode 100644 index 0000000..94adb01 --- /dev/null +++ b/cfg/server.cfg @@ -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/" \ No newline at end of file diff --git a/gamemodes/fretta/fretta.txt b/gamemodes/fretta/fretta.txt new file mode 100644 index 0000000..5f539ab --- /dev/null +++ b/gamemodes/fretta/fretta.txt @@ -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/" +} diff --git a/gamemodes/fretta/gamemode/cl_deathnotice.lua b/gamemodes/fretta/gamemode/cl_deathnotice.lua new file mode 100644 index 0000000..56130e0 --- /dev/null +++ b/gamemodes/fretta/gamemode/cl_deathnotice.lua @@ -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 \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/cl_gmchanger.lua b/gamemodes/fretta/gamemode/cl_gmchanger.lua new file mode 100644 index 0000000..77a9347 --- /dev/null +++ b/gamemodes/fretta/gamemode/cl_gmchanger.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/cl_help.lua b/gamemodes/fretta/gamemode/cl_help.lua new file mode 100644 index 0000000..c0f5ee1 --- /dev/null +++ b/gamemodes/fretta/gamemode/cl_help.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/cl_hud.lua b/gamemodes/fretta/gamemode/cl_hud.lua new file mode 100644 index 0000000..dfd770a --- /dev/null +++ b/gamemodes/fretta/gamemode/cl_hud.lua @@ -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 ) +]]-- \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/cl_init.lua b/gamemodes/fretta/gamemode/cl_init.lua new file mode 100644 index 0000000..068d405 --- /dev/null +++ b/gamemodes/fretta/gamemode/cl_init.lua @@ -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) \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/cl_notify.lua b/gamemodes/fretta/gamemode/cl_notify.lua new file mode 100644 index 0000000..aac88b5 --- /dev/null +++ b/gamemodes/fretta/gamemode/cl_notify.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/cl_scores.lua b/gamemodes/fretta/gamemode/cl_scores.lua new file mode 100644 index 0000000..e6f1f48 --- /dev/null +++ b/gamemodes/fretta/gamemode/cl_scores.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/cl_selectscreen.lua b/gamemodes/fretta/gamemode/cl_selectscreen.lua new file mode 100644 index 0000000..7e41fed --- /dev/null +++ b/gamemodes/fretta/gamemode/cl_selectscreen.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/cl_splashscreen.lua b/gamemodes/fretta/gamemode/cl_splashscreen.lua new file mode 100644 index 0000000..3210687 --- /dev/null +++ b/gamemodes/fretta/gamemode/cl_splashscreen.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/class_default.lua b/gamemodes/fretta/gamemode/class_default.lua new file mode 100644 index 0000000..c7c9902 --- /dev/null +++ b/gamemodes/fretta/gamemode/class_default.lua @@ -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 ) \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/init.lua b/gamemodes/fretta/gamemode/init.lua new file mode 100644 index 0000000..6e6d900 --- /dev/null +++ b/gamemodes/fretta/gamemode/init.lua @@ -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 ) diff --git a/gamemodes/fretta/gamemode/player_class.lua b/gamemodes/fretta/gamemode/player_class.lua new file mode 100644 index 0000000..743fd2c --- /dev/null +++ b/gamemodes/fretta/gamemode/player_class.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/player_colours.lua b/gamemodes/fretta/gamemode/player_colours.lua new file mode 100644 index 0000000..45f41e6 --- /dev/null +++ b/gamemodes/fretta/gamemode/player_colours.lua @@ -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 + diff --git a/gamemodes/fretta/gamemode/player_extension.lua b/gamemodes/fretta/gamemode/player_extension.lua new file mode 100644 index 0000000..6ddadc5 --- /dev/null +++ b/gamemodes/fretta/gamemode/player_extension.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/round_controller.lua b/gamemodes/fretta/gamemode/round_controller.lua new file mode 100644 index 0000000..629775b --- /dev/null +++ b/gamemodes/fretta/gamemode/round_controller.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/shared.lua b/gamemodes/fretta/gamemode/shared.lua new file mode 100644 index 0000000..40fd0d8 --- /dev/null +++ b/gamemodes/fretta/gamemode/shared.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/skin.lua b/gamemodes/fretta/gamemode/skin.lua new file mode 100644 index 0000000..68c7d54 --- /dev/null +++ b/gamemodes/fretta/gamemode/skin.lua @@ -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 ) \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/sv_gmchanger.lua b/gamemodes/fretta/gamemode/sv_gmchanger.lua new file mode 100644 index 0000000..eb77225 --- /dev/null +++ b/gamemodes/fretta/gamemode/sv_gmchanger.lua @@ -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 \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/sv_spectator.lua b/gamemodes/fretta/gamemode/sv_spectator.lua new file mode 100644 index 0000000..603aa3f --- /dev/null +++ b/gamemodes/fretta/gamemode/sv_spectator.lua @@ -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 ) \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/utility.lua b/gamemodes/fretta/gamemode/utility.lua new file mode 100644 index 0000000..e392d4b --- /dev/null +++ b/gamemodes/fretta/gamemode/utility.lua @@ -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 diff --git a/gamemodes/fretta/gamemode/vgui/vgui_gamenotice.lua b/gamemodes/fretta/gamemode/vgui/vgui_gamenotice.lua new file mode 100644 index 0000000..45d11d9 --- /dev/null +++ b/gamemodes/fretta/gamemode/vgui/vgui_gamenotice.lua @@ -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" ) \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/vgui/vgui_hudbase.lua b/gamemodes/fretta/gamemode/vgui/vgui_hudbase.lua new file mode 100644 index 0000000..340a9d3 --- /dev/null +++ b/gamemodes/fretta/gamemode/vgui/vgui_hudbase.lua @@ -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" ) diff --git a/gamemodes/fretta/gamemode/vgui/vgui_hudcommon.lua b/gamemodes/fretta/gamemode/vgui/vgui_hudcommon.lua new file mode 100644 index 0000000..f92da3c --- /dev/null +++ b/gamemodes/fretta/gamemode/vgui/vgui_hudcommon.lua @@ -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" ) \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/vgui/vgui_hudelement.lua b/gamemodes/fretta/gamemode/vgui/vgui_hudelement.lua new file mode 100644 index 0000000..bbc89d9 --- /dev/null +++ b/gamemodes/fretta/gamemode/vgui/vgui_hudelement.lua @@ -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" ) diff --git a/gamemodes/fretta/gamemode/vgui/vgui_hudlayout.lua b/gamemodes/fretta/gamemode/vgui/vgui_hudlayout.lua new file mode 100644 index 0000000..b83a5c3 --- /dev/null +++ b/gamemodes/fretta/gamemode/vgui/vgui_hudlayout.lua @@ -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" ) diff --git a/gamemodes/fretta/gamemode/vgui/vgui_scoreboard.lua b/gamemodes/fretta/gamemode/vgui/vgui_scoreboard.lua new file mode 100644 index 0000000..5254513 --- /dev/null +++ b/gamemodes/fretta/gamemode/vgui/vgui_scoreboard.lua @@ -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" ) diff --git a/gamemodes/fretta/gamemode/vgui/vgui_scoreboard_small.lua b/gamemodes/fretta/gamemode/vgui/vgui_scoreboard_small.lua new file mode 100644 index 0000000..a638482 --- /dev/null +++ b/gamemodes/fretta/gamemode/vgui/vgui_scoreboard_small.lua @@ -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" ) \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/vgui/vgui_scoreboard_team.lua b/gamemodes/fretta/gamemode/vgui/vgui_scoreboard_team.lua new file mode 100644 index 0000000..883f265 --- /dev/null +++ b/gamemodes/fretta/gamemode/vgui/vgui_scoreboard_team.lua @@ -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" ) \ No newline at end of file diff --git a/gamemodes/fretta/gamemode/vgui/vgui_vote.lua b/gamemodes/fretta/gamemode/vgui/vgui_vote.lua new file mode 100644 index 0000000..577de91 --- /dev/null +++ b/gamemodes/fretta/gamemode/vgui/vgui_vote.lua @@ -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" ) diff --git a/gamemodes/prop_hunt/backgrounds/bunkered.jpg b/gamemodes/prop_hunt/backgrounds/bunkered.jpg new file mode 100644 index 0000000..28d6b25 Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/bunkered.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/cs_office.jpg b/gamemodes/prop_hunt/backgrounds/cs_office.jpg new file mode 100644 index 0000000..942c76d Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/cs_office.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/cs_office_2.jpg b/gamemodes/prop_hunt/backgrounds/cs_office_2.jpg new file mode 100644 index 0000000..d8a4265 Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/cs_office_2.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/drunk.jpg b/gamemodes/prop_hunt/backgrounds/drunk.jpg new file mode 100644 index 0000000..54ee47e Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/drunk.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/elementary_school.jpg b/gamemodes/prop_hunt/backgrounds/elementary_school.jpg new file mode 100644 index 0000000..f4e7b0e Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/elementary_school.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/elementary_school_2.jpg b/gamemodes/prop_hunt/backgrounds/elementary_school_2.jpg new file mode 100644 index 0000000..5ef7ded Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/elementary_school_2.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/hunterchase.jpg b/gamemodes/prop_hunt/backgrounds/hunterchase.jpg new file mode 100644 index 0000000..3cb2bda Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/hunterchase.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/lossing_his_prop.jpg b/gamemodes/prop_hunt/backgrounds/lossing_his_prop.jpg new file mode 100644 index 0000000..b9f6769 Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/lossing_his_prop.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/office.jpg b/gamemodes/prop_hunt/backgrounds/office.jpg new file mode 100644 index 0000000..2a7d142 Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/office.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/ph_islandhouse0013.jpg b/gamemodes/prop_hunt/backgrounds/ph_islandhouse0013.jpg new file mode 100644 index 0000000..531956e Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/ph_islandhouse0013.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/restaurant.jpg b/gamemodes/prop_hunt/backgrounds/restaurant.jpg new file mode 100644 index 0000000..e56f553 Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/restaurant.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/starship.jpg b/gamemodes/prop_hunt/backgrounds/starship.jpg new file mode 100644 index 0000000..28a0a5b Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/starship.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/story.jpg b/gamemodes/prop_hunt/backgrounds/story.jpg new file mode 100644 index 0000000..ffd4228 Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/story.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/underwater.jpg b/gamemodes/prop_hunt/backgrounds/underwater.jpg new file mode 100644 index 0000000..14e0ed5 Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/underwater.jpg differ diff --git a/gamemodes/prop_hunt/backgrounds/zombiebunker.jpg b/gamemodes/prop_hunt/backgrounds/zombiebunker.jpg new file mode 100644 index 0000000..911d003 Binary files /dev/null and b/gamemodes/prop_hunt/backgrounds/zombiebunker.jpg differ diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_d.vmt b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_d.vmt new file mode 100644 index 0000000..ee4fc92 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_d.vmt @@ -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]" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_d.vtf b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_d.vtf new file mode 100644 index 0000000..2ddc3dc Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_d.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_m.vtf b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_m.vtf new file mode 100644 index 0000000..ae643bb Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_m.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_n.vtf b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_n.vtf new file mode 100644 index 0000000..d156139 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/blast_brenmk3/bren_n.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/v_models/bren/tex_bren_diff.vmt b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/bren/tex_bren_diff.vmt new file mode 100644 index 0000000..3eb725f --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/bren/tex_bren_diff.vmt @@ -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" + +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/v_models/bren/tex_bren_diff.vtf b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/bren/tex_bren_diff.vtf new file mode 100644 index 0000000..9c109ce Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/bren/tex_bren_diff.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/v_models/bren/tex_bren_nrm.vtf b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/bren/tex_bren_nrm.vtf new file mode 100644 index 0000000..f5bd8df Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/bren/tex_bren_nrm.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/v_models/hands/sleeve_diffuse.vmt b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/hands/sleeve_diffuse.vmt new file mode 100644 index 0000000..93b5129 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/hands/sleeve_diffuse.vmt @@ -0,0 +1,4 @@ +"VertexLitGeneric" +{ + "$baseTexture" "models\weapons\v_models\hands\sleeve_diffuse" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/v_models/hands/sleeve_diffuse.vtf b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/hands/sleeve_diffuse.vtf new file mode 100644 index 0000000..9ac3543 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/models/weapons/v_models/hands/sleeve_diffuse.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/models/weapons/w_models/blast_brenmk3/bren_d.vmt b/gamemodes/prop_hunt/content/materials/models/weapons/w_models/blast_brenmk3/bren_d.vmt new file mode 100644 index 0000000..210404d --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/models/weapons/w_models/blast_brenmk3/bren_d.vmt @@ -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]" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/box/box.vmt b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/box/box.vmt new file mode 100644 index 0000000..7ce6469 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/box/box.vmt @@ -0,0 +1,9 @@ +"UnlitGeneric" +{ + "$basetexture" "prophunt_enhanced/box/box" + "$translucent" "1" + "$alphatest" "1" + + "$nodraw" "1" + "$no_draw" "1" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/box/box.vtf b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/box/box.vtf new file mode 100644 index 0000000..ce39483 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/box/box.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/devil.vtf b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/devil.vtf new file mode 100644 index 0000000..d49772b Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/devil.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/devil_crystal_texture.vmt b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/devil_crystal_texture.vmt new file mode 100644 index 0000000..aea45c4 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/devil_crystal_texture.vmt @@ -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" +} diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball.vmt b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball.vmt new file mode 100644 index 0000000..397540f --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "prophunt_enhanced/sprites/devilball" + "$translucent" 1 + "$vertexcolor" 1 +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball.vtf b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball.vtf new file mode 100644 index 0000000..acef615 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball_pointer.vmt b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball_pointer.vmt new file mode 100644 index 0000000..3ef670b --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball_pointer.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "prophunt_enhanced/sprites/devilball_pointer" + "$translucent" 1 + "$vertexcolor" 1 +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball_pointer.vtf b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball_pointer.vtf new file mode 100644 index 0000000..344920c Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/devilball_pointer.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball.vmt b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball.vmt new file mode 100644 index 0000000..79690c1 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "prophunt_enhanced/sprites/luckyball" + "$translucent" 1 + "$vertexcolor" 1 +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball.vtf b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball.vtf new file mode 100644 index 0000000..779274e Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball_pointer.vmt b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball_pointer.vmt new file mode 100644 index 0000000..32125a6 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball_pointer.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "prophunt_enhanced/sprites/luckyball_pointer" + "$translucent" 1 + "$vertexcolor" 1 +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball_pointer.vtf b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball_pointer.vtf new file mode 100644 index 0000000..d9d6e99 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/prophunt_enhanced/sprites/luckyball_pointer.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/hud/wlv_bren.vmt b/gamemodes/prop_hunt/content/materials/vgui/hud/wlv_bren.vmt new file mode 100644 index 0000000..e749fec --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/hud/wlv_bren.vmt @@ -0,0 +1,7 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui/hud/wlv_bren" + "$additive" 1 + "$vertexalpha" 1 + "$vertexcolor" 1 +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/hud/wlv_bren.vtf b/gamemodes/prop_hunt/content/materials/vgui/hud/wlv_bren.vtf new file mode 100644 index 0000000..87a6da0 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/hud/wlv_bren.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/hud_control_help.png b/gamemodes/prop_hunt/content/materials/vgui/hud_control_help.png new file mode 100644 index 0000000..fe106fe Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/hud_control_help.png differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/hud_crosshair.vmt b/gamemodes/prop_hunt/content/materials/vgui/hud_crosshair.vmt new file mode 100644 index 0000000..cfc2a43 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/hud_crosshair.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui/hud_crosshair" + "$additive" "1" + "$vertexcolor" "1" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/vgui/hud_crosshair.vtf b/gamemodes/prop_hunt/content/materials/vgui/hud_crosshair.vtf new file mode 100644 index 0000000..845e6ea Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/hud_crosshair.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_close.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_close.vmt new file mode 100644 index 0000000..22126a1 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_close.vmt @@ -0,0 +1,5 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\btn_close" + "$translucent" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_close.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_close.vtf new file mode 100644 index 0000000..a64506e Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_close.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_play.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_play.vmt new file mode 100644 index 0000000..6a1b084 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_play.vmt @@ -0,0 +1,5 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\btn_play" + "$translucent" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_play.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_play.vtf new file mode 100644 index 0000000..70b76a8 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_play.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playpub.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playpub.vmt new file mode 100644 index 0000000..0204f3b --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playpub.vmt @@ -0,0 +1,5 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\btn_playpub" + "$translucent" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playpub.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playpub.vtf new file mode 100644 index 0000000..64aa084 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playpub.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playx.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playx.vmt new file mode 100644 index 0000000..761e6f4 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playx.vmt @@ -0,0 +1,5 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\btn_playx" + "$translucent" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playx.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playx.vtf new file mode 100644 index 0000000..b26ee15 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/btn_playx.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/hud_topbar.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/hud_topbar.vmt new file mode 100644 index 0000000..b7126a5 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/hud_topbar.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\hud_topbar" + "$vertexcolor" "1" + "$translucent" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/hud_topbar.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/hud_topbar.vtf new file mode 100644 index 0000000..6c720c4 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/hud_topbar.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/i_halo.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_halo.vmt new file mode 100644 index 0000000..8661ecb --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_halo.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\i_halo" + "$translucent" "1" + "$vertexcolor" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/i_halo.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_halo.vtf new file mode 100644 index 0000000..ed27080 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_halo.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/i_light.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_light.vmt new file mode 100644 index 0000000..8b12f78 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_light.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\i_light" + "$translucent" "1" + "$vertexcolor" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/i_light.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_light.vtf new file mode 100644 index 0000000..27bb682 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_light.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/i_rotate.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_rotate.vmt new file mode 100644 index 0000000..6a99c2e --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_rotate.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\i_rotate" + "$translucent" "1" + "$vertexcolor" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/i_rotate.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_rotate.vtf new file mode 100644 index 0000000..f3d50d5 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_rotate.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/i_shield.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_shield.vmt new file mode 100644 index 0000000..5f193f0 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_shield.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\i_shield" + "$translucent" "1" + "$vertexcolor" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/i_shield.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_shield.vtf new file mode 100644 index 0000000..b30478c Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/i_shield.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_1.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_1.vmt new file mode 100644 index 0000000..02d1571 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_1.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\res_hp_1" + "$vertexcolor" "1" + "$translucent" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_1.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_1.vtf new file mode 100644 index 0000000..78d743c Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_1.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_2.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_2.vmt new file mode 100644 index 0000000..f7a46c2 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_2.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\res_hp_2" + "$vertexcolor" "1" + "$translucent" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_2.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_2.vtf new file mode 100644 index 0000000..ed00709 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_hp_2.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/res_wep.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_wep.vmt new file mode 100644 index 0000000..d06ae6e --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_wep.vmt @@ -0,0 +1,6 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\res_wep" + "$vertexcolor" "1" + "$translucent" "1" +} diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/res_wep.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_wep.vtf new file mode 100644 index 0000000..877de07 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/res_wep.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_off.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_off.vmt new file mode 100644 index 0000000..e3345ef --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_off.vmt @@ -0,0 +1,5 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\voice_off" + "$translucent" "1" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_off.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_off.vtf new file mode 100644 index 0000000..c66f27b Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_off.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_on.vmt b/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_on.vmt new file mode 100644 index 0000000..4b007fa --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_on.vmt @@ -0,0 +1,5 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui\phehud\voice_on" + "$translucent" "1" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_on.vtf b/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_on.vtf new file mode 100644 index 0000000..b3615da Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phehud/voice_on.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp1.vmt b/gamemodes/prop_hunt/content/materials/vgui/phhelp1.vmt new file mode 100644 index 0000000..83dcc5c --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phhelp1.vmt @@ -0,0 +1,4 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui/phhelp1" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp1.vtf b/gamemodes/prop_hunt/content/materials/vgui/phhelp1.vtf new file mode 100644 index 0000000..e89099c Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phhelp1.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp2.vmt b/gamemodes/prop_hunt/content/materials/vgui/phhelp2.vmt new file mode 100644 index 0000000..b3a3996 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phhelp2.vmt @@ -0,0 +1,4 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui/phhelp2" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp2.vtf b/gamemodes/prop_hunt/content/materials/vgui/phhelp2.vtf new file mode 100644 index 0000000..1ed14d8 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phhelp2.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp3.vmt b/gamemodes/prop_hunt/content/materials/vgui/phhelp3.vmt new file mode 100644 index 0000000..63c7af4 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phhelp3.vmt @@ -0,0 +1,4 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui/phhelp3" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp3.vtf b/gamemodes/prop_hunt/content/materials/vgui/phhelp3.vtf new file mode 100644 index 0000000..7c2b74d Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phhelp3.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp4.vmt b/gamemodes/prop_hunt/content/materials/vgui/phhelp4.vmt new file mode 100644 index 0000000..addd261 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phhelp4.vmt @@ -0,0 +1,4 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui/phhelp4" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp4.vtf b/gamemodes/prop_hunt/content/materials/vgui/phhelp4.vtf new file mode 100644 index 0000000..6f107b0 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phhelp4.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp5.vmt b/gamemodes/prop_hunt/content/materials/vgui/phhelp5.vmt new file mode 100644 index 0000000..665f4ee --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phhelp5.vmt @@ -0,0 +1,4 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui/phhelp5" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp5.vtf b/gamemodes/prop_hunt/content/materials/vgui/phhelp5.vtf new file mode 100644 index 0000000..17c0131 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phhelp5.vtf differ diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp6.vmt b/gamemodes/prop_hunt/content/materials/vgui/phhelp6.vmt new file mode 100644 index 0000000..4d911a5 --- /dev/null +++ b/gamemodes/prop_hunt/content/materials/vgui/phhelp6.vmt @@ -0,0 +1,4 @@ +"UnlitGeneric" +{ + "$basetexture" "vgui/phhelp6" +} \ No newline at end of file diff --git a/gamemodes/prop_hunt/content/materials/vgui/phhelp6.vtf b/gamemodes/prop_hunt/content/materials/vgui/phhelp6.vtf new file mode 100644 index 0000000..7254695 Binary files /dev/null and b/gamemodes/prop_hunt/content/materials/vgui/phhelp6.vtf differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.dx80.vtx b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.dx80.vtx new file mode 100644 index 0000000..827e271 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.dx80.vtx differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.dx90.vtx b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.dx90.vtx new file mode 100644 index 0000000..2a1d594 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.dx90.vtx differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.mdl b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.mdl new file mode 100644 index 0000000..0090ea7 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.mdl differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.phy b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.phy new file mode 100644 index 0000000..72e1b7a Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.phy differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.sw.vtx b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.sw.vtx new file mode 100644 index 0000000..9e489e9 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.sw.vtx differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.vvd b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.vvd new file mode 100644 index 0000000..3f7a56f Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/box.vvd differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.dx80.vtx b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.dx80.vtx new file mode 100644 index 0000000..685d24f Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.dx80.vtx differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.dx90.vtx b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.dx90.vtx new file mode 100644 index 0000000..c96f4d8 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.dx90.vtx differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.mdl b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.mdl new file mode 100644 index 0000000..8ed64fc Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.mdl differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.phy b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.phy new file mode 100644 index 0000000..fc05e7d Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.phy differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.sw.vtx b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.sw.vtx new file mode 100644 index 0000000..36f31e5 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.sw.vtx differ diff --git a/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.vvd b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.vvd new file mode 100644 index 0000000..9c17e49 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/props_idbs/phenhanced/devil.vvd differ diff --git a/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.dx80.vtx b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.dx80.vtx new file mode 100644 index 0000000..c925eb3 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.dx80.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.dx90.vtx b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.dx90.vtx new file mode 100644 index 0000000..f83de05 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.dx90.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.mdl b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.mdl new file mode 100644 index 0000000..4df9c05 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.mdl differ diff --git a/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.sw.vtx b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.sw.vtx new file mode 100644 index 0000000..d401f61 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.sw.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.vvd b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.vvd new file mode 100644 index 0000000..6d434c4 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/c_mach_brenmk3.vvd differ diff --git a/gamemodes/prop_hunt/content/models/weapons/v_mkbren.dx80.vtx b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.dx80.vtx new file mode 100644 index 0000000..6f200ce Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.dx80.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/v_mkbren.dx90.vtx b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.dx90.vtx new file mode 100644 index 0000000..1203957 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.dx90.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/v_mkbren.mdl b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.mdl new file mode 100644 index 0000000..7a592b8 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.mdl differ diff --git a/gamemodes/prop_hunt/content/models/weapons/v_mkbren.sw.vtx b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.sw.vtx new file mode 100644 index 0000000..32e2d96 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.sw.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/v_mkbren.vvd b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.vvd new file mode 100644 index 0000000..a5b2f8b Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.vvd differ diff --git a/gamemodes/prop_hunt/content/models/weapons/v_mkbren.xbox.vtx b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.xbox.vtx new file mode 100644 index 0000000..be79027 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/v_mkbren.xbox.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.dx80.vtx b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.dx80.vtx new file mode 100644 index 0000000..3309e33 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.dx80.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.dx90.vtx b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.dx90.vtx new file mode 100644 index 0000000..527cd47 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.dx90.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.mdl b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.mdl new file mode 100644 index 0000000..04fb505 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.mdl differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.phy b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.phy new file mode 100644 index 0000000..606898c Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.phy differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.sw.vtx b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.sw.vtx new file mode 100644 index 0000000..9e3f9fc Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.sw.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.vvd b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.vvd new file mode 100644 index 0000000..76dbdf9 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mach_brenmk3.vvd differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mkbren.dx80.vtx b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.dx80.vtx new file mode 100644 index 0000000..f7a373c Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.dx80.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mkbren.dx90.vtx b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.dx90.vtx new file mode 100644 index 0000000..71e2ff5 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.dx90.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mkbren.mdl b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.mdl new file mode 100644 index 0000000..0631ab6 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.mdl differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mkbren.phy b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.phy new file mode 100644 index 0000000..04f1760 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.phy differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mkbren.sw.vtx b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.sw.vtx new file mode 100644 index 0000000..856b892 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.sw.vtx differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mkbren.vvd b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.vvd new file mode 100644 index 0000000..9815301 Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.vvd differ diff --git a/gamemodes/prop_hunt/content/models/weapons/w_mkbren.xbox.vtx b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.xbox.vtx new file mode 100644 index 0000000..698ac0a Binary files /dev/null and b/gamemodes/prop_hunt/content/models/weapons/w_mkbren.xbox.vtx differ diff --git a/gamemodes/prop_hunt/content/sound/misc/freeze_cam.wav b/gamemodes/prop_hunt/content/sound/misc/freeze_cam.wav new file mode 100644 index 0000000..a239f6c Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/misc/freeze_cam.wav differ diff --git a/gamemodes/prop_hunt/content/sound/misc/freeze_cam_sad1.wav b/gamemodes/prop_hunt/content/sound/misc/freeze_cam_sad1.wav new file mode 100644 index 0000000..56bf8fd Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/misc/freeze_cam_sad1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/misc/ph_hunterwin.mp3 b/gamemodes/prop_hunt/content/sound/misc/ph_hunterwin.mp3 new file mode 100644 index 0000000..7004902 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/misc/ph_hunterwin.mp3 differ diff --git a/gamemodes/prop_hunt/content/sound/misc/ph_propwin.mp3 b/gamemodes/prop_hunt/content/sound/misc/ph_propwin.mp3 new file mode 100644 index 0000000..f260dbd Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/misc/ph_propwin.mp3 differ diff --git a/gamemodes/prop_hunt/content/sound/misc/ph_rounddraw_1.mp3 b/gamemodes/prop_hunt/content/sound/misc/ph_rounddraw_1.mp3 new file mode 100644 index 0000000..cac096d Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/misc/ph_rounddraw_1.mp3 differ diff --git a/gamemodes/prop_hunt/content/sound/misc/ph_rounddraw_2.mp3 b/gamemodes/prop_hunt/content/sound/misc/ph_rounddraw_2.mp3 new file mode 100644 index 0000000..1e8d2e0 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/misc/ph_rounddraw_2.mp3 differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/bc_pickup.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/bc_pickup.wav new file mode 100644 index 0000000..363c457 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/bc_pickup.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/biva_pickup.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/biva_pickup.wav new file mode 100644 index 0000000..649cde2 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/biva_pickup.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/cloak.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/cloak.wav new file mode 100644 index 0000000..b2aeacb Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/cloak.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/froze_done.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/froze_done.wav new file mode 100644 index 0000000..cd6d92f Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/froze_done.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/generic_exhaust.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/generic_exhaust.wav new file mode 100644 index 0000000..b7a5d07 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/generic_exhaust.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/govarchz_pickup.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/govarchz_pickup.wav new file mode 100644 index 0000000..1771c88 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/govarchz_pickup.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/huntep4_bc44_pickup.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/huntep4_bc44_pickup.wav new file mode 100644 index 0000000..0e89e8a Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/huntep4_bc44_pickup.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/light_off1.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/light_off1.wav new file mode 100644 index 0000000..3f56a6b Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/light_off1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/light_on.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/light_on.wav new file mode 100644 index 0000000..7bf4f88 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/light_on.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/np_pickup.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/np_pickup.wav new file mode 100644 index 0000000..e746156 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/np_pickup.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/slowdown.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/slowdown.wav new file mode 100644 index 0000000..b7fd590 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/slowdown.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/speedup.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/speedup.wav new file mode 100644 index 0000000..1d8db04 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/speedup.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/surface_prop_froze_hunter.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/surface_prop_froze_hunter.wav new file mode 100644 index 0000000..18e25ad Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/surface_prop_froze_hunter.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/venta_pickup.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/venta_pickup.wav new file mode 100644 index 0000000..5532512 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/venta_pickup.wav differ diff --git a/gamemodes/prop_hunt/content/sound/prop_idbs/zavogant_pickup.wav b/gamemodes/prop_hunt/content/sound/prop_idbs/zavogant_pickup.wav new file mode 100644 index 0000000..e89c670 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/prop_idbs/zavogant_pickup.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/come_to_papa.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/come_to_papa.wav new file mode 100644 index 0000000..6388794 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/come_to_papa.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/father.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/father.wav new file mode 100644 index 0000000..d1b2703 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/father.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/fireassis.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/fireassis.wav new file mode 100644 index 0000000..835ef50 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/fireassis.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/glados-president.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/glados-president.wav new file mode 100644 index 0000000..d666e36 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/glados-president.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/hitassist.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/hitassist.wav new file mode 100644 index 0000000..53b6d41 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/hitassist.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/how_rude.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/how_rude.wav new file mode 100644 index 0000000..d75a530 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/how_rude.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/ill_find_you.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/ill_find_you.wav new file mode 100644 index 0000000..29761ba Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/ill_find_you.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/laugh.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/laugh.wav new file mode 100644 index 0000000..452bb9e Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/laugh.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/now_what.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/now_what.wav new file mode 100644 index 0000000..8b79230 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/now_what.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/threat_neutralized.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/threat_neutralized.wav new file mode 100644 index 0000000..41f064b Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/threat_neutralized.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/you_dont_have_the_soul.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/you_dont_have_the_soul.wav new file mode 100644 index 0000000..1a48f0e Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/you_dont_have_the_soul.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/you_dont_know_the_power.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/you_dont_know_the_power.wav new file mode 100644 index 0000000..6501e3e Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/you_dont_know_the_power.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/hunters/you_underestimate_the_power.wav b/gamemodes/prop_hunt/content/sound/taunts/hunters/you_underestimate_the_power.wav new file mode 100644 index 0000000..5332413 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/hunters/you_underestimate_the_power.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_augmented.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_augmented.wav new file mode 100644 index 0000000..a8d2b2a Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_augmented.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_dontworrywurcops.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_dontworrywurcops.wav new file mode 100644 index 0000000..54e811f Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_dontworrywurcops.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_easy_bruh.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_easy_bruh.wav new file mode 100644 index 0000000..d7527e8 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_easy_bruh.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_heh.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_heh.wav new file mode 100644 index 0000000..11dfc71 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_heh.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_hehe.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_hehe.wav new file mode 100644 index 0000000..b32c874 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_hehe.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_idonotmoveout.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_idonotmoveout.wav new file mode 100644 index 0000000..cf029b2 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_idonotmoveout.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_iloominarty.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_iloominarty.wav new file mode 100644 index 0000000..16eb939 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_iloominarty.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_imgonnawoopyourass.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_imgonnawoopyourass.wav new file mode 100644 index 0000000..80b876a Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_imgonnawoopyourass.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_leaveme.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_leaveme.wav new file mode 100644 index 0000000..2540305 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_leaveme.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_lookatme.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_lookatme.wav new file mode 100644 index 0000000..689e558 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_lookatme.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_molepeople.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_molepeople.wav new file mode 100644 index 0000000..b051ae7 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_molepeople.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_thebomb.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_thebomb.wav new file mode 100644 index 0000000..206ccc9 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_thebomb.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_thebomb2.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_thebomb2.wav new file mode 100644 index 0000000..e4b3532 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_thebomb2.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_whatashame.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_whatashame.wav new file mode 100644 index 0000000..d4aed0d Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_whatashame.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_whoawhoawhoa_1.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_whoawhoawhoa_1.wav new file mode 100644 index 0000000..3dcf08c Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_whoawhoawhoa_1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_whoawhoawhoa_2.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_whoawhoawhoa_2.wav new file mode 100644 index 0000000..ad42b3b Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/dx_whoawhoawhoa_2.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_and_iiiiiiiiiiiiiiiiiiii.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_and_iiiiiiiiiiiiiiiiiiii.wav new file mode 100644 index 0000000..7d09a2c Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_and_iiiiiiiiiiiiiiiiiiii.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_angry_german_kid.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_angry_german_kid.wav new file mode 100644 index 0000000..6fd0e56 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_angry_german_kid.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_bicycle_bell.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_bicycle_bell.wav new file mode 100644 index 0000000..293c541 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_bicycle_bell.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_blablaahah.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_blablaahah.wav new file mode 100644 index 0000000..d0dc546 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_blablaahah.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_cling.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_cling.wav new file mode 100644 index 0000000..fa35193 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_cling.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_crackmod_ihateyou.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_crackmod_ihateyou.wav new file mode 100644 index 0000000..e07beb4 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_crackmod_ihateyou.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_crackmod_watchyourrear.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_crackmod_watchyourrear.wav new file mode 100644 index 0000000..f33e57c Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_crackmod_watchyourrear.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_crackmod_youareugly.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_crackmod_youareugly.wav new file mode 100644 index 0000000..c76d91c Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_crackmod_youareugly.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dance_music.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dance_music.wav new file mode 100644 index 0000000..eb0e604 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dance_music.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_darude.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_darude.wav new file mode 100644 index 0000000..cfd0969 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_darude.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_deaugh.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_deaugh.wav new file mode 100644 index 0000000..b9eb2c6 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_deaugh.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_die.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_die.wav new file mode 100644 index 0000000..e53cea5 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_die.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_do_you_kno_de_wei.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_do_you_kno_de_wei.wav new file mode 100644 index 0000000..625eca3 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_do_you_kno_de_wei.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh1.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh1.wav new file mode 100644 index 0000000..930fbd4 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh2.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh2.wav new file mode 100644 index 0000000..465a062 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh2.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh3.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh3.wav new file mode 100644 index 0000000..999f810 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh3.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh4.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh4.wav new file mode 100644 index 0000000..bc66a5c Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh4.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh5.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh5.wav new file mode 100644 index 0000000..eb8c475 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dosh5.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dundundun.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dundundun.wav new file mode 100644 index 0000000..f9a6c00 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_dundundun.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_fart1.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_fart1.wav new file mode 100644 index 0000000..6eadfaa Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_fart1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_fart2.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_fart2.wav new file mode 100644 index 0000000..8efe3a7 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_fart2.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_fdsa.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_fdsa.wav new file mode 100644 index 0000000..b64261d Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_fdsa.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_gameover.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_gameover.wav new file mode 100644 index 0000000..e6388a0 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_gameover.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_gameover_mario.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_gameover_mario.wav new file mode 100644 index 0000000..580f7c1 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_gameover_mario.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_get_no_scope.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_get_no_scope.wav new file mode 100644 index 0000000..5dfdccf Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_get_no_scope.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_get_to_the_choppa.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_get_to_the_choppa.wav new file mode 100644 index 0000000..fc724d3 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_get_to_the_choppa.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_getcamera.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_getcamera.wav new file mode 100644 index 0000000..710c5ea Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_getcamera.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_getoutofhere_stalker.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_getoutofhere_stalker.wav new file mode 100644 index 0000000..07f693f Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_getoutofhere_stalker.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_huladance.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_huladance.wav new file mode 100644 index 0000000..bd67463 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_huladance.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_idiots_1.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_idiots_1.wav new file mode 100644 index 0000000..b74d46f Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_idiots_1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_idiots_2.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_idiots_2.wav new file mode 100644 index 0000000..e045727 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_idiots_2.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_illegal.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_illegal.wav new file mode 100644 index 0000000..9faf90c Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_illegal.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_illuminaty.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_illuminaty.wav new file mode 100644 index 0000000..595bf8e Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_illuminaty.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jason1.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jason1.wav new file mode 100644 index 0000000..7398a37 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jason1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jason2.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jason2.wav new file mode 100644 index 0000000..5ff3ddd Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jason2.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jason3.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jason3.wav new file mode 100644 index 0000000..c19dbfa Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jason3.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jim_carrey.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jim_carrey.wav new file mode 100644 index 0000000..b4dc882 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_jim_carrey.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_johncena.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_johncena.wav new file mode 100644 index 0000000..ed407c6 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_johncena.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_johncena_remix.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_johncena_remix.wav new file mode 100644 index 0000000..0c76ec1 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_johncena_remix.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_lovely_hehe_mp4.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_lovely_hehe_mp4.wav new file mode 100644 index 0000000..b9aa839 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_lovely_hehe_mp4.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_mlg_triple.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_mlg_triple.wav new file mode 100644 index 0000000..0bf47ce Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_mlg_triple.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_my_leg.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_my_leg.wav new file mode 100644 index 0000000..010ce6b Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_my_leg.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_nowai.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_nowai.wav new file mode 100644 index 0000000..aff9b42 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_nowai.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_oah.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_oah.wav new file mode 100644 index 0000000..0a932fe Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_oah.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_oof_minecraft.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_oof_minecraft.wav new file mode 100644 index 0000000..2c670d8 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_oof_minecraft.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_oof_roblox.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_oof_roblox.wav new file mode 100644 index 0000000..932244f Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_oof_roblox.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_pd2_cloaker.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_pd2_cloaker.wav new file mode 100644 index 0000000..5d1037c Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_pd2_cloaker.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_pyrocynical_woo.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_pyrocynical_woo.wav new file mode 100644 index 0000000..8ecaa0e Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_pyrocynical_woo.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_remove_kebab.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_remove_kebab.wav new file mode 100644 index 0000000..aa96463 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_remove_kebab.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_shutuuuuuuup.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_shutuuuuuuup.wav new file mode 100644 index 0000000..b51014a Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_shutuuuuuuup.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_spaghet.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_spaghet.wav new file mode 100644 index 0000000..f808b9f Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_spaghet.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_touch_ma_spaghet.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_touch_ma_spaghet.wav new file mode 100644 index 0000000..200788d Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_touch_ma_spaghet.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_uhaveebolatoknodewei.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_uhaveebolatoknodewei.wav new file mode 100644 index 0000000..2ad1e72 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_uhaveebolatoknodewei.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_wepon.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_wepon.wav new file mode 100644 index 0000000..e0dc0fa Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_wepon.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_woo.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_woo.wav new file mode 100644 index 0000000..c5dd6bf Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_woo.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_xp_off.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_xp_off.wav new file mode 100644 index 0000000..46f495b Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_xp_off.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_xp_start.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_xp_start.wav new file mode 100644 index 0000000..c9f9d89 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_xp_start.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_yeahboy_mp4.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_yeahboy_mp4.wav new file mode 100644 index 0000000..6c764aa Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/ext_yeahboy_mp4.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/jc2_nonono.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/jc2_nonono.wav new file mode 100644 index 0000000..b5da143 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/jc2_nonono.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/jc2_nowai.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/jc2_nowai.wav new file mode 100644 index 0000000..2c9cffd Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/jc2_nowai.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/jc2_usonova_bee.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/jc2_usonova_bee.wav new file mode 100644 index 0000000..4feca45 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/jc2_usonova_bee.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/just_doit1.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/just_doit1.wav new file mode 100644 index 0000000..913677a Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/just_doit1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/just_doit2.wav b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/just_doit2.wav new file mode 100644 index 0000000..9468d3e Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/ph_enhanced/just_doit2.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/bad_boys.wav b/gamemodes/prop_hunt/content/sound/taunts/props/bad_boys.wav new file mode 100644 index 0000000..691c660 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/bad_boys.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/bees_fix.wav b/gamemodes/prop_hunt/content/sound/taunts/props/bees_fix.wav new file mode 100644 index 0000000..68a18f7 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/bees_fix.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_areyouontheballs.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_areyouontheballs.wav new file mode 100644 index 0000000..46c99c4 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_areyouontheballs.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_getontheballs.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_getontheballs.wav new file mode 100644 index 0000000..c327cb2 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_getontheballs.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_iguaranteeit.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_iguaranteeit.wav new file mode 100644 index 0000000..949d67d Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_iguaranteeit.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_itsoeasy.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_itsoeasy.wav new file mode 100644 index 0000000..eaf98ef Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_itsoeasy.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_laundrymadeeasy.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_laundrymadeeasy.wav new file mode 100644 index 0000000..aec37f9 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_laundrymadeeasy.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_newoxyclean.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_newoxyclean.wav new file mode 100644 index 0000000..8065266 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_newoxyclean.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_nomoredetergent.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_nomoredetergent.wav new file mode 100644 index 0000000..e468c01 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_nomoredetergent.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_only9_99.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_only9_99.wav new file mode 100644 index 0000000..a144c52 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_only9_99.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_oxyclean.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_oxyclean.wav new file mode 100644 index 0000000..b5ddc57 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_oxyclean.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/billymays_sogetontheballs.wav b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_sogetontheballs.wav new file mode 100644 index 0000000..f63948d Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/billymays_sogetontheballs.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/boom_hs.wav b/gamemodes/prop_hunt/content/sound/taunts/props/boom_hs.wav new file mode 100644 index 0000000..960e151 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/boom_hs.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/car_horn.wav b/gamemodes/prop_hunt/content/sound/taunts/props/car_horn.wav new file mode 100644 index 0000000..cb0a56a Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/car_horn.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/chicken_hammer.wav b/gamemodes/prop_hunt/content/sound/taunts/props/chicken_hammer.wav new file mode 100644 index 0000000..94358fa Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/chicken_hammer.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/doh.wav b/gamemodes/prop_hunt/content/sound/taunts/props/doh.wav new file mode 100644 index 0000000..2865bd0 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/doh.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/forces_eliminated.wav b/gamemodes/prop_hunt/content/sound/taunts/props/forces_eliminated.wav new file mode 100644 index 0000000..71610ef Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/forces_eliminated.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/go_away_or_i_shall.wav b/gamemodes/prop_hunt/content/sound/taunts/props/go_away_or_i_shall.wav new file mode 100644 index 0000000..94358fa Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/go_away_or_i_shall.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/hardbass.wav b/gamemodes/prop_hunt/content/sound/taunts/props/hardbass.wav new file mode 100644 index 0000000..8b775d6 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/hardbass.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/i_am_cornholio.wav b/gamemodes/prop_hunt/content/sound/taunts/props/i_am_cornholio.wav new file mode 100644 index 0000000..3bd0940 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/i_am_cornholio.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/i_am_the_one_and_only.wav b/gamemodes/prop_hunt/content/sound/taunts/props/i_am_the_one_and_only.wav new file mode 100644 index 0000000..b7a8196 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/i_am_the_one_and_only.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/ill_be_back.wav b/gamemodes/prop_hunt/content/sound/taunts/props/ill_be_back.wav new file mode 100644 index 0000000..6676438 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/ill_be_back.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/leroy_jenkins.wav b/gamemodes/prop_hunt/content/sound/taunts/props/leroy_jenkins.wav new file mode 100644 index 0000000..a5a0a4c Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/leroy_jenkins.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/nein.wav b/gamemodes/prop_hunt/content/sound/taunts/props/nein.wav new file mode 100644 index 0000000..607f348 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/nein.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/oh_yea_he_will_pay.wav b/gamemodes/prop_hunt/content/sound/taunts/props/oh_yea_he_will_pay.wav new file mode 100644 index 0000000..ac5998d Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/oh_yea_he_will_pay.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/ok_i_will_tell_you.wav b/gamemodes/prop_hunt/content/sound/taunts/props/ok_i_will_tell_you.wav new file mode 100644 index 0000000..5afcb19 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/ok_i_will_tell_you.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/on_me.wav b/gamemodes/prop_hunt/content/sound/taunts/props/on_me.wav new file mode 100644 index 0000000..a0a4f3f Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/on_me.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/over9000.wav b/gamemodes/prop_hunt/content/sound/taunts/props/over9000.wav new file mode 100644 index 0000000..d85746e Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/over9000.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/pingas.wav b/gamemodes/prop_hunt/content/sound/taunts/props/pingas.wav new file mode 100644 index 0000000..414b0fa Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/pingas.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/pls_come_again.wav b/gamemodes/prop_hunt/content/sound/taunts/props/pls_come_again.wav new file mode 100644 index 0000000..5777ae7 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/pls_come_again.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/pokemon.wav b/gamemodes/prop_hunt/content/sound/taunts/props/pokemon.wav new file mode 100644 index 0000000..2fb6d24 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/pokemon.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/retarted_laugh.wav b/gamemodes/prop_hunt/content/sound/taunts/props/retarted_laugh.wav new file mode 100644 index 0000000..c34f09e Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/retarted_laugh.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/sham_wow.wav b/gamemodes/prop_hunt/content/sound/taunts/props/sham_wow.wav new file mode 100644 index 0000000..b084527 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/sham_wow.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/sparta.wav b/gamemodes/prop_hunt/content/sound/taunts/props/sparta.wav new file mode 100644 index 0000000..76f3605 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/sparta.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/tri_poloski1.wav b/gamemodes/prop_hunt/content/sound/taunts/props/tri_poloski1.wav new file mode 100644 index 0000000..9288dcc Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/tri_poloski1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/tri_poloski2.wav b/gamemodes/prop_hunt/content/sound/taunts/props/tri_poloski2.wav new file mode 100644 index 0000000..bb1e873 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/tri_poloski2.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/watatata.wav b/gamemodes/prop_hunt/content/sound/taunts/props/watatata.wav new file mode 100644 index 0000000..3e034bd Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/watatata.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/wololo.wav b/gamemodes/prop_hunt/content/sound/taunts/props/wololo.wav new file mode 100644 index 0000000..75429b0 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/wololo.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/woohoo.wav b/gamemodes/prop_hunt/content/sound/taunts/props/woohoo.wav new file mode 100644 index 0000000..abf5819 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/woohoo.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/wrong.wav b/gamemodes/prop_hunt/content/sound/taunts/props/wrong.wav new file mode 100644 index 0000000..5e75af9 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/wrong.wav differ diff --git a/gamemodes/prop_hunt/content/sound/taunts/props/wroooong.wav b/gamemodes/prop_hunt/content/sound/taunts/props/wroooong.wav new file mode 100644 index 0000000..2b7cb8a Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/taunts/props/wroooong.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/brenmk3/boltback.wav b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/boltback.wav new file mode 100644 index 0000000..c1b1fd3 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/boltback.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/brenmk3/boltforward.wav b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/boltforward.wav new file mode 100644 index 0000000..af64aaa Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/boltforward.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/brenmk3/cloth.wav b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/cloth.wav new file mode 100644 index 0000000..b0204b1 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/cloth.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/brenmk3/draw.wav b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/draw.wav new file mode 100644 index 0000000..bfe367d Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/draw.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/brenmk3/magin.wav b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/magin.wav new file mode 100644 index 0000000..ce364fb Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/magin.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/brenmk3/magout.wav b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/magout.wav new file mode 100644 index 0000000..24b7168 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/magout.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/brenmk3/magtap.wav b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/magtap.wav new file mode 100644 index 0000000..9f1fff4 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/magtap.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/brenmk3/shoot.wav b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/shoot.wav new file mode 100644 index 0000000..26f6f6b Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/brenmk3/shoot.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_1.wav b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_1.wav new file mode 100644 index 0000000..26f6f6b Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_1.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_boltpull.wav b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_boltpull.wav new file mode 100644 index 0000000..c8eafa3 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_boltpull.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_draw.wav b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_draw.wav new file mode 100644 index 0000000..15f9b60 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_draw.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_magin.wav b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_magin.wav new file mode 100644 index 0000000..b0dbf33 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_magin.wav differ diff --git a/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_magout.wav b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_magout.wav new file mode 100644 index 0000000..d8f7138 Binary files /dev/null and b/gamemodes/prop_hunt/content/sound/weapons/mkbren/bren_magout.wav differ diff --git a/gamemodes/prop_hunt/entities/entities/brush_playerclip/cl_init.lua b/gamemodes/prop_hunt/entities/entities/brush_playerclip/cl_init.lua new file mode 100644 index 0000000..49c5048 --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/brush_playerclip/cl_init.lua @@ -0,0 +1 @@ +include("shared.lua") \ No newline at end of file diff --git a/gamemodes/prop_hunt/entities/entities/brush_playerclip/init.lua b/gamemodes/prop_hunt/entities/entities/brush_playerclip/init.lua new file mode 100644 index 0000000..4e42220 --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/brush_playerclip/init.lua @@ -0,0 +1,24 @@ +-- Credit to Awesome guy: D4UNKN0WNMAN :D +-- Had to place this entity for ph_kleiner maps. for purpose: Anti Exploiting. + +AddCSLuaFile("cl_init.lua") +AddCSLuaFile("shared.lua") + +include("shared.lua") + +function ENT:Initialize() + local w = self.max.x - self.min.x + local l = self.max.y - self.min.y + local h = self.max.z - self.min.z + + local min = Vector(0 - (w / 2), 0 - (l / 2), 0 - (h / 2)) + local max = Vector(w / 2, l / 2, h / 2) + + self:DrawShadow(false) + self:SetCollisionBounds(min, max) + self:SetSolid(SOLID_BBOX) + self:SetNoDraw(true) + self:SetCollisionGroup(COLLISION_GROUP_NONE) + self:SetMoveType(0) + self:SetTrigger(false) +end \ No newline at end of file diff --git a/gamemodes/prop_hunt/entities/entities/brush_playerclip/shared.lua b/gamemodes/prop_hunt/entities/entities/brush_playerclip/shared.lua new file mode 100644 index 0000000..545737f --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/brush_playerclip/shared.lua @@ -0,0 +1,2 @@ +ENT.Base = "base_anim" +ENT.Type = "anim" \ No newline at end of file diff --git a/gamemodes/prop_hunt/entities/entities/ph_devilball/cl_init.lua b/gamemodes/prop_hunt/entities/entities/ph_devilball/cl_init.lua new file mode 100644 index 0000000..301e0ec --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/ph_devilball/cl_init.lua @@ -0,0 +1,2 @@ +-- Include needed files +include("shared.lua") \ No newline at end of file diff --git a/gamemodes/prop_hunt/entities/entities/ph_devilball/init.lua b/gamemodes/prop_hunt/entities/entities/ph_devilball/init.lua new file mode 100644 index 0000000..e66f2b4 --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/ph_devilball/init.lua @@ -0,0 +1,214 @@ +AddCSLuaFile("cl_init.lua") +AddCSLuaFile("shared.lua") +include("shared.lua") + +ENT.model = Model("models/props_idbs/phenhanced/devil.mdl") + +function ENT:StartTeslaSpark() + timer.Create("DoTeslaSpark-"..self.Entity:EntIndex(),math.random(3,6),0,function() + self:ShowEffects(self.Entity, "StunstickImpact", self.Entity:GetPos(), self.Entity:GetPos()) + end) +end + +function ENT:StopTeslaSpark() + if timer.Exists("DoTeslaSpark-"..self.Entity:EntIndex()) then + timer.Remove("DoTeslaSpark-"..self.Entity:EntIndex()) + end +end + +function ENT:Initialize() + self.Entity:SetModel(self.model) + self.Entity:PhysicsInit(SOLID_BBOX) + self.Entity:SetMoveType(MOVETYPE_NONE) + self.Entity:SetSolid(SOLID_BBOX) + self.Entity:SetUseType(SIMPLE_USE) + self.health = 50 + + -- Spawn a Sprite, for an Effect. + self.Entity.Sprite = ents.Create("env_sprite") + self.Entity.Sprite:SetPos(self.Entity:GetPos()) + self.Entity.Sprite:SetAngles(Angle(0,0,0)) + self.Entity.Sprite:SetKeyValue("spawnflags","1") + self.Entity.Sprite:SetKeyValue("framerate","1") + self.Entity.Sprite:SetKeyValue("rendermode","5") + self.Entity.Sprite:SetKeyValue("rendercolor","255 "..tostring(math.random(1,180)).." "..tostring(math.random(1,20))) + self.Entity.Sprite:SetKeyValue("model","sprites/light_glow01.vmt") + self.Entity.Sprite:SetKeyValue("scale","0.4") + + self.Entity.Sprite:Spawn() + self.Entity.Sprite:Activate() + + self.Entity.Sprite:SetParent(self.Entity) + + self:StartTeslaSpark() +end + +function ENT:OnRemove() + self:StopTeslaSpark() + if IsValid(self.Entity.Sprite) then + self.Entity.Sprite:Remove() + end +end + +ENT.sounds = { + "prop_idbs/huntep4_bc44_pickup.wav", + "prop_idbs/zavogant_pickup.wav" +} + +--[[ +Base Devil Balls Functions. +Please note that you might have to create a custom serverside lua with full of function list with list.Set into "DevilBallsAddition". + Example: + + list.Set("DevilBallsAddition", "UniqueName", function(pl,ball) + -- code... + end) + +Keep in note that UniqueName should be unique and different. Otherwise will cause some confusion with printVerbose! +]] +ENT.funclists = { + function(pl) + if !pl.ph_fastspeed then + if !pl._OriginalWSpeed then pl._OriginalWSpeed = pl:GetWalkSpeed() end + + pl:ChatPrint("[Devil Crystal] You have super speed Power up!") + pl:SendLua("surface.PlaySound('prop_idbs/speedup.wav')") + pl:SetWalkSpeed( pl:GetWalkSpeed() + 100 ) + pl.ph_fastspeed = true + pl.RevertWalk = timer.Simple(math.random(4,12), + function() + pl:ChatPrint("[Devil Crystal] super speed power up exhausted...") + pl:SendLua("surface.PlaySound('prop_idbs/generic_exhaust.wav')") + pl:SetWalkSpeed( pl._OriginalWSpeed ) + pl.ph_fastspeed = false + end) + end + end, + function(pl) + local rand = math.random(10,50) + pl:SetHealth(pl:Health() + rand) + pl.ph_prop.health = pl.ph_prop.health + rand + pl:ChatPrint("[Devil Crystal] You got free +"..tostring(rand).." HP for your current Prop!") + end, + function(pl) + local rand + rand = math.random(20,60) + pl:SetArmor(pl:Armor() + rand) + pl:ChatPrint("[Devil Crystal] You gained armor points bonus : "..tostring(rand).."!") + end, + function(pl) + if !pl.ph_slowspeed then + if !pl._OriginalWSpeed then pl._OriginalWSpeed = pl:GetWalkSpeed() end + + pl:ChatPrint("[Devil Crystal] Uh oh, you're slowing down!") + pl:SendLua("surface.PlaySound('prop_idbs/slowdown.wav')") + pl:SetWalkSpeed( pl:GetWalkSpeed() - 100 ) + pl.ph_slowspeed = true + pl.RevertWalk = timer.Simple(math.random(4,12), + function() + pl:ChatPrint("[Devil Crystal] slow down power up exhausted...") + pl:SendLua("surface.PlaySound('prop_idbs/generic_exhaust.wav')") + pl:SetWalkSpeed( pl._OriginalWSpeed ) + pl.ph_slowspeed = false + end) + end + end, + function(pl) + if table.Count(team.GetPlayers(TEAM_HUNTERS)) >= 3 then + pl:ChatPrint("[Devil Crystal] Hunters are frozen!") + pl:SendLua("surface.PlaySound('prop_idbs/surface_prop_froze_hunter.wav')") + for _,v in pairs(team.GetPlayers(TEAM_HUNTERS)) do + if v:Alive() then + v:Freeze(true) + v:EmitSound(Sound("prop_idbs/govarchz_pickup.wav")) + v:ChatPrint("[Devil Crystal] Oops, you are temporary frozen...!") + v.UnFrooze = timer.Simple(math.random(2,3), + function() + v:ChatPrint("[Devil Crystal] You are free now!") + v:EmitSound(Sound("prop_idbs/froze_done.wav")) + v:Freeze(false) + end) + end + end + else + pl:ChatPrint("[Devil Crystal] It seems there are no hunters available to Froze 'em. Let it Go~") + end + end, + function(pl) + if !pl.ph_cloacking then + pl:ChatPrint("[Devil Crystal] Cloaking...") + pl:SendLua("surface.PlaySound('prop_idbs/cloak.wav')") + pl.ph_prop:DrawShadow(false) + pl.ph_prop:SetMaterial("models/effects/vol_light001") + pl.ph_cloacking = true + pl.RevertMaterial = timer.Simple(math.random(5,15), + function() + pl:ChatPrint("[Devil Crystal] cloak power up exhausted...") + pl:SendLua("surface.PlaySound('prop_idbs/generic_exhaust.wav')") + pl.ph_prop:DrawShadow(true) + pl.ph_prop:SetMaterial("") + pl.ph_cloacking = false + end) + end + end +} +-- Don't Edit below unless you know what you're doing. + +local function ResetEverything() + for _,v in pairs(player.GetAll()) do + if IsValid(v) && v:Alive() then + v.ph_cloacking = false + v.ph_slowspeed = false + v.ph_fastspeed = false + + if v:Team() == TEAM_PROPS && v._OriginalWSpeed then v:SetWalkSpeed(v._OriginalWSpeed) end + if v:Team() == TEAM_PROPS && v.ph_prop:GetMaterial() then v.ph_prop:DrawShadow(true) v.ph_prop:SetMaterial("") end + if v:IsFrozen() then v:Freeze(false) end + end + end +end +hook.Add("PH_RoundEnd", "PHE.ForceResetDevilBall", ResetEverything) + +function ENT:AddMoreLuckyEvents() + local t = list.Get("DevilBallsAddition") + if table.Count(t) > 0 then + for name,tab in pairs(t) do + printVerbose("[ Devil Ball :: Add Event ] Adding new Devil Balls events : "..name) + table.insert(self.funclists, tab) + end + else + printVerbose("[ Devil Ball :: Add Event ] There is no additional Devil Balls events detected, ignoring...") + end +end + +ENT:AddMoreLuckyEvents() + +function ENT:The_DevilDrop(pl) + if pl:Team() == TEAM_PROPS && pl:Alive() then + self.getfunction = table.Random(self.funclists) + self.getfunction(pl) + + hook.Call("PH_OnDevilBallPickup", nil, pl) + end +end + +function ENT:Use(activator) + if GAMEMODE:InRound() && IsValid(activator) && activator:IsPlayer() && activator:Alive() && activator:Team() == TEAM_PROPS then + self:The_DevilDrop(activator) + self:ShowEffects(self.Entity, "GlassImpact", self.Entity:GetPos(), self.Entity:GetPos()) + self.Entity:EmitSound(Sound(table.Random(self.sounds)),60) + self.Entity:Remove() + end +end + +function ENT:OnTakeDamage(dmg) + local hit = dmg:GetDamage() + + self.health = self.health - hit + + if self.health < 0 then + self.Entity:EmitSound(Sound("physics/glass/glass_cup_break"..math.random(1,2)..".wav")) + self:ShowEffects(self.Entity, "GlassImpact", self.Entity:GetPos(), self.Entity:GetPos()) + self.Entity:Remove() + end +end \ No newline at end of file diff --git a/gamemodes/prop_hunt/entities/entities/ph_devilball/shared.lua b/gamemodes/prop_hunt/entities/entities/ph_devilball/shared.lua new file mode 100644 index 0000000..5fc610c --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/ph_devilball/shared.lua @@ -0,0 +1,24 @@ +-- Entity information +ENT.Type = "anim" +ENT.Base = "base_anim" + +function ENT:ShowEffects(ent, fx_name, v_start, v_origin) + + local eData = EffectData() + eData:SetEntity(ent) -- parent + eData:SetStart(v_start) + eData:SetOrigin(v_origin) -- hit + eData:SetAttachment(1) + eData:SetMagnitude(15) + eData:SetScale(15) + eData:SetRadius(20) + util.Effect(fx_name, eData, true, true) + +end + +function ENT:Think() + -- make it rotate from client only. + if CLIENT then + self.Entity:SetAngles(self.Entity:GetAngles() + Angle(0,1,0)) + end +end \ No newline at end of file diff --git a/gamemodes/prop_hunt/entities/entities/ph_luckyball/cl_init.lua b/gamemodes/prop_hunt/entities/entities/ph_luckyball/cl_init.lua new file mode 100644 index 0000000..301e0ec --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/ph_luckyball/cl_init.lua @@ -0,0 +1,2 @@ +-- Include needed files +include("shared.lua") \ No newline at end of file diff --git a/gamemodes/prop_hunt/entities/entities/ph_luckyball/init.lua b/gamemodes/prop_hunt/entities/entities/ph_luckyball/init.lua new file mode 100644 index 0000000..4d68858 --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/ph_luckyball/init.lua @@ -0,0 +1,249 @@ +local balls = {} +-- no. + +AddCSLuaFile("cl_init.lua") +AddCSLuaFile("shared.lua") +include("shared.lua") + +balls.model = { + "models/dav0r/hoverball.mdl", + "models/maxofs2d/hover_basic.mdl", + "models/maxofs2d/hover_classic.mdl", + "models/maxofs2d/hover_rings.mdl" +} + +balls.bombswitch = 0 + +function ENT:Initialize() + self.Entity:SetModel(table.Random(balls.model)) + self.Entity:PhysicsInit(SOLID_VPHYSICS) + self.Entity:SetMoveType(MOVETYPE_VPHYSICS) + self.Entity:SetSolid(SOLID_VPHYSICS) + self.Entity:SetUseType(SIMPLE_USE) + + self.Uses = 0 + + local phys = self.Entity:GetPhysicsObject() + + if IsValid(phys) then + phys:Wake() + phys:SetMass(24) --since barrel + end + + self.health = 100 +end + +balls.sounds = { + "prop_idbs/bc_pickup.wav", + "prop_idbs/np_pickup.wav", + "prop_idbs/venta_pickup.wav", + "prop_idbs/biva_pickup.wav" +} + +balls.randomtext = { + "Trolling is \'A\' Art", + "0 8 1 3 - 6 9 2 8", + "SHUT UP NURSE!!", + "A fish with a cone hat.", + "A blueberry wolfy hangs around. (if he was here)", + "He keep laughing whenever he saw a moving prop/hunter or found an excelent hiding spot.", + "\'He once used this gamemode, then never again. Or Perhaps someone broke it, lmao.\'", + "The blueberry wolfy tried to swim in lava while mining a diamond.", + "Uncharted: The Game within The Game.", + "Look, ma! I said look! I'm on top of the world... again!", + "He always, stays patiently over 400 years to make a changes.", + "John Freeman whose Gordon Freeman\'s Brother!", + "John Freeman looked underground and found WEPONS!", + "When you go to space, there is a hiding crystal inside a \'box\'.", + "It\'s so fancy! Even people in \'that\' house didn\'t notice that there are 5 buttons and some dorito!", + "WHERE\'S THE BLACKSMITH!?", + "What a shame.", + "I never asked for this.", + "Knowing these lucky balls will give you something good fills you with determination.", + "PILLS HERE!", + "The Power of Fluffy Boy shines within you!", + "Actually, this guy is \'wacky\'. He live in the castle and... he has a \'Spade-Liked\' head.", + "You go to the Field where you can find your Dreams and Hopes~", + "There are two games which has similar characters that can cause CHAOS.", + "She like eating chalks, A LOT.", + ":3", + "You know, that time when GMod was used to be made for good animation video, YTPs, fads, etc...", + "Here's some text to occupy you.", + "Have you seen the NannerMan?", + "Although there are alot of missing textures, Just remember: \'Mitchell\' is useless guy and it\'s game too.", -- Pfftt, ok I'm done with HDTF. + "I once saw a man with green septic eyes.", + "I once saw a man with a pink mustache.", + "There was Obsidian and it had a Conflict.", + "We all just need a bit of Synergy in our lives.", + "The Presense is Watching you", -- todo is this correct for Terraria Eye of Chtulu Boss? + "sudo apt-get moo", + "\"Have you mooed today?\"", + "Someone could do well on the stage, we just need to find him.", + "You can \"Unite\" a \"Tower\" of people if you do it right.", + "Klace is a pink husky. So Pinky~", + "Major reference. Minor details.", -- This is 100% a reference! Think! + "*Notices* What's this? OwO", + "Lucky Ball: I luv u~! <3", -- LOL + "So much to do, so little time.", -- That was the rest of those fallen text additions - Nice! + "You don't realise that (nearly) all those were actually easter eggs? :P" +} + +--[[ +Base Lucky Balls Functions. +Please note that you might have to create a custom serverside lua with full of function list with list.Set into "LuckyBallsAddition". + Example: + + list.Set("LuckyBallsAddition", "UniqueName", function(pl,ball) + -- code... + end) + +Keep in note that UniqueName should be unique and different. Otherwise will cause some confusion with printVerbose! +]] +balls.funclists = { + function(pl) + pl:ChatPrint(table.Random(balls.randomtext)) + end, + function(pl) + if not pl:HasWeapon("wlv_bren") then + pl:Give("wlv_bren") + pl:SelectWeapon("wlv_bren") + pl:ChatPrint("[Lucky Ball] You got a *special* weapon!") + else + pl:ChatPrint(table.Random(balls.randomtext)) + end + end, + function(pl) + local rand = math.random(10,75) + pl:SetHealth(pl:Health() + rand) + pl:ChatPrint("[Lucky Ball] You got free +"..rand.." HP!") + end, + function(pl) + local rand = math.random(1,20) + pl:SetHealth(pl:Health() - rand) + pl:ChatPrint("[Lucky Ball] Aww Snap! Your health reduced by -"..rand.." HP, better luck next time!") + end, + function(pl) + pl:Give("item_battery") + pl:ChatPrint("[Lucky Ball] You obtained a free battery suit!") + end, + function(pl) + local rand + rand = math.random(15,100) + pl:SetArmor(pl:Armor() + rand) + pl:ChatPrint("[Lucky Ball] You gained armor points bonus : "..tostring(rand).."!") + end, + function(pl) + local ammo = {'Pistol', 'SMG1', '357', 'Buckshot'} + local rand + rand = math.random(8,45) + pl:GiveAmmo(rand, table.Random(ammo)) + pl:ChatPrint("[Lucky Ball] You got a random ammo!") + end, + function(pl) + if not pl:HasWeapon("weapon_rpg") then + pl:Give("weapon_rpg") + pl:SelectWeapon("weapon_rpg") + pl:SetAmmo(2, "RPG_Round") + pl:ChatPrint("[Lucky Ball] You got a free RPG!") + else + pl:ChatPrint(table.Random(balls.randomtext)) + end + end, + function(pl) + if not pl:HasWeapon("weapon_frag") then + pl:Give("weapon_frag") + pl:SelectWeapon("weapon_frag") + pl:ChatPrint("[Lucky Ball] You got a Frag Grenade for free!") + end + end, + function(pl) + for _, plph in pairs(player.GetAll()) do + if plph:SteamID() == "STEAM_0:0:63261691" then + pl:ChatPrint("[Lucky Ball] The blueberry wolf is actually => "..plph:Nick()) + end + end + end, + function(pl) + if not pl:HasWeapon("weapon_bugbait") then + pl:Give("weapon_bugbait") + pl:ChatPrint("[Lucky Ball] You got Bugbait for free... which does nothing. (unless you have a pet antlion).") + else + pl:ChatPrint(table.Random(balls.randomtext)) + end + end, + function(pl) -- Change hunter model to player mdl as a joke + if not (pl:GetModel() == "models/player.mdl") then + pl:ChatPrint("[Lucky Ball] I saw it once. The player.mdl will get its revenge one day. -D4") + pl:SetModel("models/player.mdl") + pl:SendLua("CL_GLIMPCAM = CurTime() + 3") + else + pl:ChatPrint(table.Random(balls.randomtext)) + end + end, + function(pl) -- This is a fun little reference to staging + for _, plph in pairs(player.GetAll()) do + if plph:SteamID() == "STEAM_0:0:49332102" && plph:Alive() && plph:Team() == TEAM_HUNTERS then + pl:ChatPrint("[Lucky Ball] You put "..plph:Name().." on the stage.") + plph:SendLua("CL_GLIMPCAM = CurTime() + 10") + plph:SendLua("RunConsoleCommand(\"act\", \"dance\")") + plph:EmitSound("taunts/props/hardbass.wav", 100) + end + end + end, + function(pl) + local suicidebomb = ents.Create("combine_mine") + suicidebomb:SetPos(Vector(pl:GetPos())) + suicidebomb:SetAngles(Angle(0,0,0)) + suicidebomb:Spawn() + suicidebomb:Activate() + suicidebomb:SetOwner(pl) + pl:ChatPrint("[Lucky Ball] You got a SUICIDE BOMB!") + + if balls.bombswitch == 0 then + pl:EmitSound("taunts/ph_enhanced/dx_thebomb2.wav") + balls.bombswitch = 1 + elseif balls.bombswitch == 1 then + pl:EmitSound("taunts/ph_enhanced/dx_thebomb.wav") + balls.bombswitch = 0 + end + end +} +-- Don't Edit below unless you know what you're doing. + +function balls:AddMoreLuckyEvents() + local t = list.Get("LuckyBallsAddition") + if table.Count(t) > 0 then + for name,tab in pairs(t) do + printVerbose("[ Lucky Ball :: Add Event ] Adding new Lucky Balls events : "..name) + table.insert(balls.funclists, tab) + end + else + printVerbose("[ Lucky Ball :: Add Event ] There is no additional Lucky Balls events detected, ignoring...") + end +end + +balls:AddMoreLuckyEvents() + +function balls:The_LuckyDrop(pl) + -- For hunter only. + if pl:Team() == TEAM_HUNTERS && pl:Alive() then + balls.getfunction = table.Random(balls.funclists) + balls.getfunction(pl) + + hook.Call("PH_OnLuckyBallPickup", nil, pl) + end +end + +function ENT:Use(activator) + if GAMEMODE:InRound() && activator:IsPlayer() && activator:Alive() && activator:Team() == TEAM_HUNTERS then + if self.Uses == 0 then + balls:The_LuckyDrop(activator) + + self.Entity:EmitSound(Sound(table.Random(balls.sounds))) + self.Uses = 1 + self.Entity:Remove() + else + self.Entity:Remove() + end + end +end diff --git a/gamemodes/prop_hunt/entities/entities/ph_luckyball/shared.lua b/gamemodes/prop_hunt/entities/entities/ph_luckyball/shared.lua new file mode 100644 index 0000000..7ff7b98 --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/ph_luckyball/shared.lua @@ -0,0 +1,3 @@ +-- Entity information +ENT.Type = "anim" +ENT.Base = "base_anim" \ No newline at end of file diff --git a/gamemodes/prop_hunt/entities/entities/ph_prop.lua b/gamemodes/prop_hunt/entities/entities/ph_prop.lua new file mode 100644 index 0000000..e4b7747 --- /dev/null +++ b/gamemodes/prop_hunt/entities/entities/ph_prop.lua @@ -0,0 +1,133 @@ +AddCSLuaFile() + +DEFINE_BASECLASS( "base_anim" ) + +ENT.PrintName = "Prop Entity" +ENT.Author = "Wolvindra-Vinzuerio" +ENT.Information = "A prop entity for Prop Hunt: Enhanced" +ENT.Category = "" +ENT.Editable = true +ENT.Spawnable = true +ENT.AdminOnly = false +ENT.RenderGroup = RENDERGROUP_BOTH + +function ENT:SetupDataTables() end + +function ENT:Initialize() + if SERVER then + self:SetModel("models/player/kleiner.mdl") + self:SetLagCompensated(true) + self:SetMoveType(MOVETYPE_NONE) + self.health = 100 + else + + end +end + +if CLIENT then + function ENT:Draw() + self:DrawModel() + end +end + +-- Prop Movement and Rotation (CLIENT) +function ENT:Think() + if CLIENT then + local pl = self:GetOwner() + if IsValid(pl) && pl:Alive() && pl == LocalPlayer() then + local me = LocalPlayer() + local pos = me:GetPos() + local ang = me:GetAngles() + local lockstate = pl:GetPlayerLockedRot() + + if self:GetModel() == "models/player/kleiner.mdl" || self:GetModel() == player_manager.TranslatePlayerModel(GetConVar("cl_playermodel"):GetString()) then + self:SetPos(pos) + else + self:SetPos(pos - Vector(0, 0, self:OBBMins().z)) + end + if !lockstate then self:SetAngles(Angle(0,ang.y,0)) end + end + end +end + +if SERVER then + + -- Transmit update + function ENT:UpdateTransmitState() + return TRANSMIT_ALWAYS + end + + -- Main Function + function ENT:OnTakeDamage(dmg) + local pl = self:GetOwner() + local attacker = dmg:GetAttacker() + local inflictor = dmg:GetInflictor() + + -- Health + if GAMEMODE:InRound() && IsValid(pl) && pl:Alive() && pl:IsPlayer() && attacker:IsPlayer() && dmg:GetDamage() > 0 then + if pl:Armor() >= 10 then + self.health = self.health - (math.Round(dmg:GetDamage()/2)) + pl:SetArmor(pl:Armor() - 20) + else + self.health = self.health - dmg:GetDamage() + end + pl:SetHealth(self.health) + + if self.health <= 0 then + pl:KillSilent() + pl:SetArmor(0) + + if inflictor && inflictor == attacker && inflictor:IsPlayer() then + inflictor = inflictor:GetActiveWeapon() + if !inflictor || inflictor == NULL then inflictor = attacker end + end + + net.Start( "PlayerKilledByPlayer" ) + + net.WriteEntity( pl ) + net.WriteString( inflictor:GetClass() ) + net.WriteEntity( attacker ) + + net.Broadcast() + + + MsgAll(attacker:Name() .. " found and killed " .. pl:Name() .. "\n") + + if GetConVar("ph_freezecam"):GetBool() then + if pl:GetNWBool("InFreezeCam", false) then + pl:PrintMessage(HUD_PRINTCONSOLE, "!! WARNING: Something went wrong with the Freeze Camera, but it's still enabled!") + else + timer.Simple(0.5, function() + if !pl:GetNWBool("InFreezeCam", false) then + -- Play the good old Freeze Cam sound + net.Start("PlayFreezeCamSound") + net.Send(pl) + + pl:SetNWEntity("PlayerKilledByPlayerEntity", attacker) + pl:SetNWBool("InFreezeCam", true) + pl:SpectateEntity( attacker ) + pl:Spectate( OBS_MODE_FREEZECAM ) + end + end) + + timer.Simple(4.5, function() + if pl:GetNWBool("InFreezeCam", false) then + pl:SetNWBool("InFreezeCam", false) + pl:Spectate( OBS_MODE_CHASE ) + pl:SpectateEntity( nil ) + end + end) + end + end + + attacker:AddFrags(1) + pl:AddDeaths(1) + attacker:SetHealth(math.Clamp(attacker:Health() + GetConVarNumber("ph_hunter_kill_bonus"), 1, 100)) + + hook.Call("PH_OnPropKilled", nil, pl, attacker) + pl:RemoveProp() + end + end + end + +end \ No newline at end of file diff --git a/gamemodes/prop_hunt/entities/weapons/wlv_bren/shared.lua b/gamemodes/prop_hunt/entities/weapons/wlv_bren/shared.lua new file mode 100644 index 0000000..2099d3f --- /dev/null +++ b/gamemodes/prop_hunt/entities/weapons/wlv_bren/shared.lua @@ -0,0 +1,290 @@ +-- Code base: Credit to http://steamcommunity.com/id/INCONCEIVABLEINCONCEIVABLE . +-- Weapon base are now removed due of M9K's version differences. + +-- Alternate version - Credits to: Blast da' Lizard - https://steamcommunity.com/id/blastdalizard + +-- These code are now supports with 3 bases: +-- --> TFA +-- --> M9K +-- --> Sandbox/default + +local function CheckConVar(cvar) + if cvar == nil then return false end + if cvar != nil then return true end + if IsValid(cvar) then return true end + return false +end + +if CheckConVar(GetConVar("DebugM9K")) or (CheckConVar(GetConVar("sv_tfa_conv_m9konvert")) && GetConVar("sv_tfa_conv_m9konvert"):GetBool()) then -- check if M9K or TFA is Exists on server. otherwise will use from Default base instead. + + SWEP.Gun = ("wlv_bren") + if (GetConVar(SWEP.Gun.."_allowed")) != nil then + if not (GetConVar(SWEP.Gun.."_allowed"):GetBool()) then + SWEP.Base = "bobs_blacklisted" + SWEP.PrintName = SWEP.Gun + return + end + end + + local icol = Color( 255, 255, 255, 255 ) + if CLIENT then + killicon.Add( SWEP.Gun, "vgui/hud/"..SWEP.Gun, icol ) + end + + SWEP.Category = "Wolvin\'s PH Bonus Weapon" + SWEP.Author = "Wolvindra-Vinzuerio" + SWEP.Contact = "wolvindra.vinzuerio@gmail.com" + SWEP.Purpose = "Just aim and shot at those innocent props lol." + SWEP.Instructions = "Step 1: Acquire This Gun.\nStep 2: Shoot.\nStep 3: Profit." --> Brain 404: Not Found. + SWEP.MuzzleAttachment = "1" + SWEP.ShellEjectAttachment = "2" + SWEP.PrintName = "Bren MK II" + SWEP.Slot = 3 + SWEP.SlotPos = 1 + SWEP.DrawAmmo = true + SWEP.DrawWeaponInfoBox = true + SWEP.BounceWeaponIcon = false + SWEP.DrawCrosshair = true + SWEP.Weight = 10 + SWEP.AutoSwitchTo = true + SWEP.AutoSwitchFrom = true + SWEP.HoldType = "ar2" + + SWEP.ViewModelFOV = 60 + SWEP.ViewModelFlip = false + if GetConVar("ph_mkbren_use_new_mdl"):GetBool() then + SWEP.ViewModel = Model("models/weapons/c_mach_brenmk3.mdl") + SWEP.WorldModel = Model("models/weapons/w_mach_brenmk3.mdl") + -- this one is used for M9K. TFA may ignore this. + SWEP.ShowWorldModel = false + + SWEP.UseHands = true + else + SWEP.ViewModel = Model("models/weapons/v_mkbren.mdl") + SWEP.WorldModel = Model("models/weapons/w_mkbren.mdl") + -- this one is used for M9K. TFA may ignore this. + SWEP.ShowWorldModel = true + + SWEP.UseHands = false + end + + SWEP.ShowWorldModel = true + SWEP.Base = "bobs_gun_base" + SWEP.Spawnable = false + SWEP.AdminSpawnable = false + + SWEP.FiresUnderwater = false + + if GetConVar("ph_mkbren_use_new_mdl"):GetBool() then + SWEP.Primary.Sound = Sound("brenmk3.single") + else + SWEP.Primary.Sound = Sound("BREN.Fire") + end + SWEP.Primary.RPM = 500 + SWEP.Primary.ClipSize = 30 + SWEP.Primary.DefaultClip = 90 + SWEP.Primary.KickUp = 0.85 + SWEP.Primary.KickDown = 0.6 + SWEP.Primary.KickHorizontal = 0.5 + SWEP.Primary.Automatic = true + SWEP.Primary.Ammo = "ar2" + + SWEP.Secondary.IronFOV = 55 + + SWEP.data = {} + SWEP.data.ironsights = 1 + + SWEP.Primary.NumShots = 1 + SWEP.Primary.Damage = 10 -- 35 for PH is bit OP, but hopefully this already balance the game since this is a rare drop. + SWEP.Primary.Spread = .025 + SWEP.Primary.IronAccuracy = .01 + + if GetConVar("ph_mkbren_use_new_mdl"):GetBool() then + SWEP.IronSightsPos = Vector(-3.383, -5.856, 2.49) + SWEP.IronSightsAng = Vector(-0.005, 0.009, 0) + SWEP.SightsPos = Vector(-3.383, -5.856, 2.49) + SWEP.SightsAng = Vector(-0.005, 0.009, 0) + SWEP.RunSightsPos = Vector(3, -1.609, -6.97) + SWEP.RunSightsAng = Vector(-7.739, 40.804, -30.251) + -- for M9K + SWEP.WElements = { + ["W_MkBren1"] = { type = "Model", model = "models/weapons/w_mach_brenmk3.mdl", bone = "ValveBiped.Bip01_R_Hand", rel = "", pos = Vector(4.991, 0.171, -1.693), angle = Angle(0, -90.326, -6.628), size = Vector(0.899, 0.899, 0.899), color = Color(255, 255, 255, 255), surpresslightning = false, material = "", skin = 0, bodygroup = {} } + } + -- for TFA + SWEP.Offset = { + Pos = { + Up = -2.1, + Right = 0, + Forward = 5.5 + }, + Ang = { + Up = 90, + Right = 178, + Forward = 176 + }, + Scale = 0.9 + } + else + SWEP.IronSightsPos = Vector(-3.172, -7.12, 0.425) + SWEP.IronSightsAng = Vector(2.213, 0, 0) + SWEP.SightsPos = Vector(-3.172, -7.12, 0.425) + SWEP.SightsAng = Vector(2.213, 0, 0) + SWEP.RunSightsPos = Vector(6.369, -10.244, -3.689) + SWEP.RunSightsAng = Vector(6.446, 62.852, 0) + end + + -- M9K Weapon properties + if GetConVar("M9KDefaultClip") == nil then + print("M9KDefaultClip is missing! You may have hit the lua limit!") + else + if GetConVar("M9KDefaultClip"):GetInt() != -1 then + SWEP.Primary.DefaultClip = SWEP.Primary.ClipSize * GetConVar("M9KDefaultClip"):GetInt() + end + end + + if GetConVar("M9KUniqueSlots") != nil then + if not (GetConVar("M9KUniqueSlots"):GetBool()) then + SWEP.SlotPos = 3 + end + end + +else + -- Revert to default base, if server has no M9K. + + if CLIENT then + killicon.Add( "wlv_bren", "vgui/hud/wlv_bren", Color(255,255,255,255) ) + end + + if SERVER then + printVerbose("[ Lucky Ball :: Bren MK ] Server has no default M9K Base, Reverting to normal sandbox base!") + end + + SWEP.Category = "Wolvindra-Vinzuerio" + SWEP.PrintName = "BREN MK II" + SWEP.Author = "Wolvindra-Vinzuerio" + SWEP.Instructions = "Simply shoot at props." + SWEP.Spawnable = true + SWEP.AdminOnly = false + + SWEP.Primary.ClipSize = 30 + SWEP.Primary.DefaultClip = 90 + SWEP.Primary.Automatic = true + SWEP.Primary.Ammo = "AR2" + SWEP.Secondary.ClipSize = -1 + SWEP.Secondary.DefaultClip = -1 + SWEP.Secondary.Automatic = false + SWEP.Secondary.Ammo = "None" + + SWEP.AutoSwitchTo = false + SWEP.AutoSwitchFrom = false + SWEP.Slot = 3 + SWEP.SlotPos = 1 + SWEP.Weight = 3 + SWEP.DrawAmmo = true + SWEP.DrawCrosshair = true + + SWEP.ViewModelFOV = 60 + SWEP.ViewModelFlip = false + + if GetConVar("ph_mkbren_use_new_mdl"):GetBool() then + SWEP.ViewModel = Model("models/weapons/c_mach_brenmk3.mdl") + SWEP.WorldModel = Model("models/weapons/w_mkbren.mdl") + SWEP.UseHands = true + else + SWEP.ViewModel = Model("models/weapons/v_mkbren.mdl") + SWEP.WorldModel = Model("models/weapons/w_mkbren.mdl") + SWEP.UseHands = false + end + + function SWEP:Initialize() + self:SetWeaponHoldType("ar2") + end + + function SWEP:PrimaryAttack() + + if (!self:CanPrimaryAttack()) then + return + end + + local punch = {} + punch.x = math.random(-0.7,-0.2) + punch.y = math.random(0, 0.1) + punch.z = 0 + + if GetConVar("ph_mkbren_use_new_mdl"):GetBool() then + self.Weapon:EmitSound( Sound("brenmk3.single") ) + else + self.Weapon:EmitSound( Sound("BREN.Fire") ) + end + self:ShootBullet( 35, 1, 0.025) + self:TakePrimaryAmmo(1) + self.Owner:ViewPunch(Angle(punch.x, punch.y, punch.z)) + self.Weapon:SetNextPrimaryFire(CurTime() + 0.12) + + end + + function SWEP:Deploy() + self:SetDeploySpeed(1) + end + +end + +-- Sound Override Tables for BREN. + +-- BREN: Firing Sound +local FS = {} + if GetConVar("ph_mkbren_use_new_mdl"):GetBool() then + FS["brenmk3.single"] = "weapons/brenmk3/shoot.wav" + else + FS["BREN.Fire"] = "weapons/mkbren/bren_1.wav" + end + +-- BREN: Reloading Sound +local RS = {} + if GetConVar("ph_mkbren_use_new_mdl"):GetBool() then + RS["brenmk3.draw"] = "weapons/brenmk3/draw.wav" + RS["brenmk3.cloth"] = "weapons/brenmk3/cloth.wav" + RS["brenmk3.boltback"] = "weapons/brenmk3/boltback.wav" + RS["brenmk3.boltforward"] = "weapons/brenmk3/boltforward.wav" + RS["brenmk3.magout"] = "weapons/brenmk3/magout.wav" + RS["brenmk3.magin"] = "weapons/brenmk3/magin.wav" + RS["brenmk3.magtap"] = "weapons/brenmk3/magtap.wav" + else + RS["BREN.MagOut"] = "weapons/mkbren/bren_magout.wav" + RS["BREN.MagIn"] = "weapons/mkbren/bren_magin.wav" + RS["BREN.BoltPull"] = "weapons/mkbren/bren_boltpull.wav" + RS["BREN.Draw"] = "weapons/mkbren/bren_draw.wav" + end + +-- Assign to table. +local wepsnd = {} + +wepsnd.fire = { + channel = CHAN_WEAPON, + volume = 1, + soundlevel = 120, + pitchstart = 100, + pitchend = 100 +} + +for k, v in pairs(FS) do + wepsnd.fire.name = k + wepsnd.fire.sound = v + + sound.Add(wepsnd.fire) +end + +wepsnd.weps = { + channel = CHAN_STATIC, + volume = 1, + soundlevel = 70, + pitchstart = 100, + pitchend = 100 +} + +for k, v in pairs(RS) do + wepsnd.weps.name = k + wepsnd.weps.sound = v + + sound.Add(wepsnd.weps) +end \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/cl_autotaunt.lua b/gamemodes/prop_hunt/gamemode/cl_autotaunt.lua new file mode 100644 index 0000000..bd2f4e7 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/cl_autotaunt.lua @@ -0,0 +1,135 @@ +-- For the love of furry heck, THIS PLACE NEEDS A CLEAN! +-- Props will autotaunt at specified intervals +local isEnabled = false +local isProp = false +local delay = 45 +local started = false +local timerID = "ph_autotaunt_timer" +local teamCheckTimer = "ph_autotaunt_teamchecktimer" + +local xStart +local xEnd +local y +local w = 140 +local h = 30 +local previousTime +local tweenTime = 0 + +local function TimeLeft() + local ply = LocalPlayer() + local lastTauntTime = ply:GetNWFloat("LastTauntTime") + local nextTauntTime = lastTauntTime + delay + local currentTime = CurTime() + return nextTauntTime - currentTime +end + +-- a: amplitude +-- p: period +local function outElastic(t, b, c, d, a, p) + local pi = math.pi + if t == 0 then return b end + + t = t / d + + if t == 1 then return b + c end + + if not p then p = d * 0.3 end + + local s + + if not a or a < math.abs(c) then + a = c + s = p / 4 + else + s = p / (2 * pi) * math.asin(c / a) + end + + return a * math.pow(2, - 10 * t) * math.sin((t * d - s) * (2 * pi) / p) + c + b +end + +local function AutoTauntPaint() + if !isEnabled || !isProp || !started then return; end + + if tweenTime < 1 then + x = outElastic(tweenTime, xStart, xEnd - xStart, 1, 1, 0.5) + local cTime = CurTime() + tweenTime = tweenTime + (cTime - previousTime) + previousTime = cTime + end + + local timeLeft = math.ceil(TimeLeft()) + local percentage = timeLeft / delay + + local txt = "Auto taunting in " .. timeLeft + + draw.RoundedBox(5, x, y, w, h, Color(0, 0, 0, 200)) + draw.RoundedBox(5, x + 5, y + 5, (w - 10) * percentage, h - 10, Color(200, 0, 0, 200)) + draw.DrawText(txt, "HunterBlindLockFont", x + 70, ScrH() - 57, Color(255, 255, 255, 255), TEXT_ALIGN_CENTER) +end +hook.Add("HUDPaint", "PH_AutoTauntPaint", AutoTauntPaint) + +local function RemoveTimer() + if timer.Exists(timerID) then + timer.Destroy(timerID) + end +end + +local function CheckAutoTaunt() + local timeLeft = TimeLeft() + local ply = LocalPlayer() + + -- Stop everything under these conditions + if !ply:Alive() || ply:Team() != TEAM_PROPS then + started = false + RemoveTimer() + printVerbose("[PH:E AutoTaunt] Blocked!") + return + end +end + +local function Setup() + local ply = LocalPlayer() + + isEnabled = GetConVar("ph_autotaunt_enabled"):GetBool() + isProp = ply:Team() == TEAM_PROPS + started = true + previousTime = CurTime() + tweenTime = 0 + + if isEnabled && isProp then + delay = GetConVar("ph_autotaunt_delay"):GetInt() + timer.Create(timerID, 1, 0, CheckAutoTaunt) + end +end + +local function CheckPlayer() + local ply = LocalPlayer() + + if ply:Alive() && ply:Team() == TEAM_PROPS then + if timer.Exists(teamCheckTimer) then + timer.Destroy(teamCheckTimer) + end + + Setup() + return true + end + + return false +end + +local function AutoTauntSpawn() + xStart = ScrW() + 200 + xEnd = ScrW() - 195 + y = ScrH() - 65 + + if !CheckPlayer() then + timer.Create(teamCheckTimer, 0.1, 10, CheckPlayer) + end +end +net.Receive("AutoTauntSpawn", function() AutoTauntSpawn() end) + +local function AutoTauntRoundEnd() + started = false + RemoveTimer() +end +net.Receive("AutoTauntRoundEnd", function() AutoTauntRoundEnd() end) diff --git a/gamemodes/prop_hunt/gamemode/cl_credits.lua b/gamemodes/prop_hunt/gamemode/cl_credits.lua new file mode 100644 index 0000000..f7947e8 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/cl_credits.lua @@ -0,0 +1,66 @@ +hook.Add("PH_CustomTabMenu", "PHE.About", function(tab, pVgui) + + surface.CreateFont("PHE.TitleFont", + { + font = "Roboto", + size = 40, + weight = 700, + antialias = true, + shadow = true + }) + + local panel = vgui.Create("DPanel", tab) + panel:SetBackgroundColor(Color(40,40,40,120)) + + local scroll = vgui.Create( "DScrollPanel", panel ) + scroll:Dock(FILL) + + local grid = vgui.Create("DGrid", scroll) + grid:Dock(NODOCK) + grid:SetPos(10,10) + grid:SetCols(1) + grid:SetColWide(800) + grid:SetRowHeight(50) + + local label = { + title = "Prop Hunt: Enhanced", + author = "Enhanced by: Wolvindra-Vinzuerio & D4UNKN0WNM4N.", + version = GAMEMODE._VERSION, + rev = GAMEMODE.REVISION, + credits = "Yam, Godfather, adk, Lucas2107, Jonpopnycorn, Thundernerd", + lgit = "https://github.com/Vinzuerio/ph-enhanced/", + lhome = "https://prophunt.wolvindra.net/", + ldonate = GAMEMODE.DONATEURL, + lwiki = "https://prophunt.wolvindra.net/?go=phe_faq", + lklog = "https://prophunt.wolvindra.net/?go=changelog", + lplugins = "https://prophunt.wolvindra.net/?go=plugins" + } + + pVgui("","label","PHE.TitleFont",grid, label.title ) + pVgui("","label","Trebuchet24",grid, "Current Version: "..label.version.." | Current Revision: "..label.rev) + pVgui("","label","Trebuchet24",grid, "If you are enjoyed with the gamemode, Please support by Donating!" ) + pVgui("spacer0","spacer",nil,grid,"" ) + pVgui("","label",false,grid, "Changelog & Updates" ) + pVgui("","btn",{max = 2,textdata = { + [1] = {"See Changelog", function() gui.OpenURL(label.lklog); tab:GetParent():Close() end}, + [2] = {"Check for Updates", + function() + LocalPlayer():ConCommand("ph_check_update") + Derma_Message("Check on your console by pressing [~] or F10 key!","Checking Updates","OK, Got it!") + end}, + }},grid,"") + pVgui("spacer1","spacer",nil,grid,"" ) + pVgui("","label",false,grid, "Helpful External Links & Credits" ) + pVgui("","btn",{max = 4,textdata = { + [1] = {"DONATE to PH:E Project", function() gui.OpenURL(label.ldonate) end}, + [2] = {"PH:E Official Homepage", function() gui.OpenURL(label.lhome) end}, + [3] = {"GitHub Repository", function() gui.OpenURL(label.lgit) end}, + [4] = {"PH:E Manuals & Wiki", function() gui.OpenURL(label.lwiki) end}, + [4] = {"PH:E Addons/Plugins", function() gui.OpenURL(label.lplugins) end} + }},grid,"") + pVgui("spacer1","spacer",nil,grid,"" ) + pVgui("","label","Trebuchet24",grid, "Special Thanks for the support, suggestion & contributing:\n"..label.credits ) + + tab:AddSheet("About & Credits",panel,"icon16/information.png") + +end) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/cl_hud.lua b/gamemodes/prop_hunt/gamemode/cl_hud.lua new file mode 100644 index 0000000..e0ec11c --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/cl_hud.lua @@ -0,0 +1,265 @@ +surface.CreateFont("PHE.HealthFont", +{ + font = "Roboto", + size = 56, + weight = 650, + antialias = true, + shadow = true +}) + +surface.CreateFont("PHE.AmmoFont", +{ + font = "Roboto", + size = 86, + weight = 500, + antialias = true, + shadow = true +}) + +surface.CreateFont("PHE.ArmorFont", +{ + font = "Roboto", + size = 32, + weight = 500, + antialias = true, + shadow = true +}) + +surface.CreateFont("PHE.TopBarFont", +{ + font = "Roboto", + size = 20, + weight = 500, + antialias = true, + shadow = true +}) +surface.CreateFont("PHE.TopBarFontTeam", +{ + font = "Roboto", + size = 60, + weight = 650, + antialias = true, + shadow = true +}) + +-- Hides HUD +local hide = { + ["CHudHealth"] = true, + ["CHudBattery"] = true, + ["CHudAmmo"] = true, + ["CHudSecondaryAmmo"] = true +} +hook.Add("HUDShouldDraw", "PHE.ShouldHideHUD", function(hudname) + if GetConVar("ph_hud_use_new"):GetBool() then + if (hide[hudname]) then return false end + end +end) + +local curteam +local mat = { + [1] = Material("vgui/phehud/res_hp_1"), + [2] = Material("vgui/phehud/res_hp_2"), +} +local indic = { + rotate = { mat = Material("vgui/phehud/i_rotate"), [0] = Color(190,190,190,255), [1] = Color(255,255,0,255) }, + halo = { mat = Material("vgui/phehud/i_halo"), [0] = Color(190,190,190,255), [1] = Color(0,255,0,255) }, + light = { mat = Material("vgui/phehud/i_light"), [0] = Color(190,190,190,255), [1] = Color(255,255,0,255) }, + armor = { mat = Material("vgui/phehud/i_shield"), [0] = Color(190,190,190,255), [1] = Color(80,190,255,255) } +} +local hudtopbar = { + mat = Material("vgui/phehud/hud_topbar"), + x = 0, + y = 60 +} +local matw = Material("vgui/phehud/res_wep") + +local ava + if (IsValid(ava)) then ava:Remove() ava = nil end +local pos = { x = 0, y = ScrH()-130 } +local posw = { x = ScrW() - 480, y = ScrH()-130 } +local hp +local armor +local hpcolor + +local bar = { + hp = { h = 5, col = Color(250,40,10,240) }, + am = { h = 5, col = Color(80,190,255,220) } +} + +local Rstate = 0 +net.Receive("PHE.rotateState", function() Rstate = net.ReadInt(2) end) + +local function PopulateAliveTeam(tm) + local tim = team.GetPlayers(tm) + local liveply = liveply or 0 + + for _,pl in pairs(tim) do + if IsValid(pl) && pl:Alive() then liveply = liveply + 1 end + end + + return liveply +end + +local state = false +local disabledcolor = Color(100,100,100,255) + +hook.Add("HUDPaint", "PHE.MainHUD", function() + + if GetConVar("ph_hud_use_new"):GetBool() then state = true else state = false end; + + if IsValid(LocalPlayer()) && LocalPlayer():Alive() && state && (LocalPlayer():Team() == TEAM_HUNTERS or LocalPlayer():Team() == TEAM_PROPS) then + -- Begin Player Info + if not IsValid(ava) then + ava = vgui.Create("AvatarMask") + ava:SetPos(16, pos.y+18) + ava:SetSize(86,86) + ava:SetPlayer(LocalPlayer(),128) + ava:SetVisible(true) + end + + -- Player Info + curteam = LocalPlayer():Team() + hp = LocalPlayer():Health() + armor = LocalPlayer():Armor() + + surface.SetDrawColor( 255, 255, 255, 255 ) + surface.SetMaterial( mat[curteam] ) + surface.DrawTexturedRect( pos.x, pos.y, 480, 120 ) + + draw.DrawText( "HEALTH", "Trebuchet24", pos.x + 175, pos.y + 14, color_white, TEXT_ALIGN_LEFT ) + + if hp < 0 then hp = 0 end + if armor < 0 then armor = 0 end + + if hp < 30 then + hpcolor = Color( 255, 1 * (hp*8), 1 * (hp*8), 255 ) + else + hpcolor = Color( 255, 255, 255, 255 ) + end + + -- hp bar + if hp > 100 then hpx = 100 else hpx = hp end + if armor > 100 then armx = 100 else armx = armor end + + surface.SetDrawColor(bar.hp.col) + surface.DrawRect(pos.x + 175, pos.y + 57, 1*(hpx*2.9), bar.hp.h) + + surface.SetDrawColor(bar.am.col) + surface.DrawRect(pos.x + 175, pos.y + 62, 1*(armx*2.9), bar.am.h) + + draw.DrawText( hp, "PHE.HealthFont", pos.x + 350, pos.y - 4, hpcolor, TEXT_ALIGN_RIGHT ) + draw.DrawText( " / "..armor, "PHE.ArmorFont", pos.x + 350, pos.y + 14, Color( 255,255,255,255 ), TEXT_ALIGN_LEFT ) + + if LocalPlayer():Team() == TEAM_HUNTERS then + surface.SetDrawColor(disabledcolor) + else + surface.SetDrawColor( indic.rotate[Rstate] ) + end + surface.SetMaterial( indic.rotate.mat ) + surface.DrawTexturedRect( pos.x + (168), pos.y + 74, 32, 32 ) + + if LocalPlayer():Team() == TEAM_HUNTERS then + surface.SetDrawColor(disabledcolor) + else + surface.SetDrawColor( indic.light[CL_GLOBAL_LIGHT_STATE] ) + end + surface.SetMaterial( indic.light.mat ) + surface.DrawTexturedRect( pos.x + (216), pos.y + 74, 32, 32 ) + + if LocalPlayer():Team() == TEAM_HUNTERS then + surface.SetDrawColor(disabledcolor) + else + surface.SetDrawColor( indic.halo[tonumber(GetConVar("ph_cl_halos"):GetInt())]) + end + surface.SetMaterial( indic.halo.mat ) + surface.DrawTexturedRect( pos.x + (264), pos.y + 74, 32, 32 ) + + if LocalPlayer():Armor() < 10 then + surface.SetDrawColor( indic.armor[0] ) + else + surface.SetDrawColor( indic.armor[1] ) + end + surface.SetMaterial( indic.armor.mat ) + surface.DrawTexturedRect (pos.x + (312), pos.y + (2*37), 32, 32 ) + end + + -- Weapon HUD + if IsValid(LocalPlayer()) && LocalPlayer():Alive() && state && LocalPlayer():Team() == TEAM_HUNTERS then + surface.SetDrawColor( 255, 255, 255, 255 ) + surface.SetMaterial( matw ) + surface.DrawTexturedRect( posw.x, posw.y, 480, 120 ) + + local curWep = LocalPlayer():GetActiveWeapon() + + local clip + local maxclip + local mag + local mag2 + local name + local percent + + draw.DrawText( "AMMO", "Trebuchet24", posw.x + (256), posw.y + 14, color_white, TEXT_ALIGN_LEFT ) + + if IsValid(curWep) then + clip = curWep:Clip1() + maxclip = curWep:GetMaxClip1() + mag = LocalPlayer():GetAmmoCount(curWep:GetPrimaryAmmoType()) + mag2 = LocalPlayer():GetAmmoCount(curWep:GetSecondaryAmmoType()) + name = language.GetPhrase(curWep:GetPrintName()) + + if clip < 0 then clip = 0 end + if maxclip < 0 then maxclip = 0 end + + if (clip < 0 || maxclip < 0) then + percent = 0 + else + percent = math.Round(clip / maxclip * 300) + end + + surface.SetDrawColor(255,200,15,255) + surface.DrawRect(posw.x + 8, posw.y + 58, percent, 8) + + draw.DrawText( clip, "PHE.HealthFont", posw.x + 136, posw.y -4, color_white, TEXT_ALIGN_RIGHT ) + draw.DrawText( " / "..mag, "PHE.ArmorFont", posw.x + 136, posw.y + 14, color_white, TEXT_ALIGN_LEFT ) + draw.DrawText( mag2, "PHE.AmmoFont", ScrW()-58, posw.y + 14, color_white, TEXT_ALIGN_CENTER ) + draw.DrawText( name, "PHE.TopBarFont", posw.x + 136, posw.y + 80, color_white, TEXT_ALIGN_LEFT ) + + end + end + + if IsValid(LocalPlayer()) && !LocalPlayer():Alive() then + if IsValid(ava) then + ava:SetVisible(false) + ava:Remove() + end + end + if IsValid(LocalPlayer()) && !state then + if IsValid(ava) then + ava:SetVisible(false) + ava:Remove() + end + end + if IsValid(LocalPlayer()) && (LocalPlayer():Team() == TEAM_SPECTATOR or LocalPlayer():Team() == TEAM_UNASSIGNED) then + if IsValid(ava) then + ava:SetVisible(false) + ava:Remove() + end + end + + -- the Team Bar. This requires at least 4 players to get this displayed. + if GetConVar("ph_show_team_topbar"):GetBool() then + if ((player.GetCount() >= 4 && LocalPlayer():Alive()) && (LocalPlayer():Team() != TEAM_UNASSIGNED && LocalPlayer():Team() != TEAM_SPECTATOR)) then + surface.SetDrawColor( 255, 255, 255, 255 ) + surface.SetMaterial( hudtopbar.mat ) + surface.DrawTexturedRect( hudtopbar.x, hudtopbar.y, 400, 50 ) + + -- Draw Props + draw.DrawText( "Props", "PHE.TopBarFont", 4, hudtopbar.y + 2, Color(255,255,255,255), TEXT_ALIGN_LEFT ) + draw.DrawText( tostring(PopulateAliveTeam(TEAM_PROPS)), "PHE.TopBarFontTeam", 96, hudtopbar.y - 8, Color(255,255,255,255), TEXT_ALIGN_LEFT ) + + -- Draw Hunters + draw.DrawText( "Hunter", "PHE.TopBarFont", 300, hudtopbar.y + 22, Color(255,255,255,255), TEXT_ALIGN_LEFT ) + draw.DrawText( tostring(PopulateAliveTeam(TEAM_HUNTERS)), "PHE.TopBarFontTeam", 220, hudtopbar.y - 8, Color(255,255,255,255), TEXT_ALIGN_LEFT ) + end + end +end) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/cl_hud_mask.lua b/gamemodes/prop_hunt/gamemode/cl_hud_mask.lua new file mode 100644 index 0000000..d6e0d01 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/cl_hud_mask.lua @@ -0,0 +1,83 @@ +-- Credit goes to this topic: +-- https://gmod.facepunch.com/f/gmoddev/ngzz/Circle-avatars/1/ + +local function MakeCirclePoly( _x, _y, _r, _points ) + local _u = ( _x + _r * 320 ) - _x; + local _v = ( _y + _r * 320 ) - _y; + + local _slices = ( 2 * math.pi ) / _points; + local _poly = { }; + for i = 0, _points - 1 do + local _angle = ( _slices * i ) % _points; + local x = _x + _r * math.cos( _angle ); + local y = _y + _r * math.sin( _angle ); + table.insert( _poly, { x = x, y = y, u = _u, v = _v } ) + end + + return _poly; +end + +local PANEL = {} + +function PANEL:Init() + self.Avatar = vgui.Create("AvatarImage", self) + self.Avatar:SetPaintedManually(true) + self.material = Material( "effects/flashlight001" ) + self:OnSizeChanged(self:GetWide(), self:GetTall()) +end + +function PANEL:PerformLayout() + self:OnSizeChanged(self:GetWide(), self:GetTall()) +end + +function PANEL:SetSteamID(...) + self.Avatar:SetSteamID(...) +end + +function PANEL:SetPlayer(...) + self.Avatar:SetPlayer(...) +end + +function PANEL:OnSizeChanged(w, h) + self.Avatar:SetSize(self:GetWide(), self:GetTall()) + self.points = math.Max((self:GetWide()/4), 32) + self.poly = MakeCirclePoly(self:GetWide()/2, self:GetTall()/2, self:GetWide()/2, self.points) +end + +function PANEL:DrawMask(w, h) + draw.NoTexture(); + surface.SetMaterial(self.material); + surface.SetDrawColor(color_white); + surface.DrawPoly(self.poly); +end + +function PANEL:Paint(w, h) + render.ClearStencil() + render.SetStencilEnable(true) + + render.SetStencilWriteMask(1) + render.SetStencilTestMask(1) + + render.SetStencilFailOperation( STENCILOPERATION_REPLACE ) + render.SetStencilPassOperation( STENCILOPERATION_ZERO ) + render.SetStencilZFailOperation( STENCILOPERATION_ZERO ) + render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_NEVER ) + render.SetStencilReferenceValue( 1 ) + + self:DrawMask(w, h) + + render.SetStencilFailOperation(STENCILOPERATION_ZERO) + render.SetStencilPassOperation(STENCILOPERATION_REPLACE) + render.SetStencilZFailOperation(STENCILOPERATION_ZERO) + render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL) + render.SetStencilReferenceValue(1) + + self.Avatar:SetPaintedManually(false) + self.Avatar:PaintManual() + self.Avatar:SetPaintedManually(true) + + render.SetStencilEnable(false) + render.ClearStencil() +end + +vgui.Register("AvatarMask", PANEL) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/cl_init.lua b/gamemodes/prop_hunt/gamemode/cl_init.lua new file mode 100644 index 0000000..75ae90f --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/cl_init.lua @@ -0,0 +1,461 @@ +CreateClientConVar("ph_cl_halos", "1", true, true, "Toggle Enable/Disable Halo effects when choosing a prop.") +CreateClientConVar("ph_cl_pltext", "1", true, false, "Options for Text above players. 0 = Disable. 1 = Enable.") +CreateClientConVar("ph_cl_endround_sound", "1", true, false, "Play a sound when round ends? 0 to disable.") +CreateClientConVar("ph_cl_autoclose_taunt", "1", true, false, "Auto close the taunt window (When Double Clicking on them)?") +CreateClientConVar("ph_cl_spec_hunter_line", "1", true, false, "Draw a line on hunters so we can see their aim in spectator mode.") +CreateClientConVar("cl_enable_luckyballs_icon", "1", true,false, "Enable 'Lucky ball' icon to be displayed once they spawned") +CreateClientConVar("cl_enable_devilballs_icon", "1", true,false, "Enable 'Devil ball' icon to be displayed once they spawned") +CreateClientConVar("ph_hud_use_new", "1", true, false, "Use new PH: Enhanced HUD") +CreateClientConVar("ph_show_team_topbar", "1", true, false, "Show total alive team players bar on the top left (Experimental)") +CreateClientConVar("ph_show_custom_crosshair","1",true,false,"Show custom crosshair for props") +CreateClientConVar("ph_show_tutor_control","1",true,false,"Show 'Prop Gameplay Control' hud on each prop spawns. This only show twice and reset until map changes/user disconnect.") + +surface.CreateFont( "HunterBlindLockFont", + { + font = "Arial", + size = 14, + weight = 1200, + antialias = true, + underline = false + }) + + surface.CreateFont("TrebuchetBig", { + font = "Impact", + size = 40 + }) + +include("sh_init.lua") +include("sh_config.lua") +CL_GLOBAL_LIGHT_STATE = 0 +include("cl_hud_mask.lua") +include("cl_hud.lua") +include("cl_menu.lua") +include("cl_tauntwindow.lua") +include("cl_targetid.lua") +include("cl_autotaunt.lua") + +include("cl_credits.lua") + +-- Called immediately after starting the gamemode +function Initialize() + cHullz = 64 + client_prop_light = false + blind = false + + CL_GLIMPCAM = 0 + MAT_LASERDOT = Material("sprites/glow04_noz") +end +hook.Add("Initialize", "PH_Initialize", Initialize) + +-- Decides where the player view should be (forces third person for props) +function GM:CalcView(pl, origin, angles, fov) + local view = {} + + if blind then + view.origin = Vector(20000, 0, 0) + view.angles = Angle(0, 0, 0) + view.fov = fov + + return view + end + + view.origin = origin + view.angles = angles + view.fov = fov + + -- Give the active weapon a go at changing the viewmodel position + if pl:Team() == TEAM_PROPS && pl:Alive() then + if GetConVar("ph_prop_camera_collisions"):GetBool() then + local trace = {} + + local filterent = ents.FindByClass("ph_prop") + table.insert(filterent, pl) + + if cHullz < 24 then + trace.start = origin + Vector(0, 0, cHullz + (24-cHullz)) + trace.endpos = origin + Vector(0, 0, cHullz + (24-cHullz)) + (angles:Forward() * -80) + elseif cHullz > 84 then + trace.start = origin + Vector(0, 0, cHullz - 84) + trace.endpos = origin + Vector(0, 0, cHullz - 84) + (angles:Forward() * -80) + else + trace.start = origin + Vector(0, 0, 8) + trace.endpos = origin + Vector(0, 0, 8) + (angles:Forward() * -80) + end + + trace.filter = filterent + + local tr = util.TraceLine(trace) + view.origin = tr.HitPos + else + if cHullz < 24 then + view.origin = origin + Vector(0, 0, cHullz + (24-cHullz)) + (angles:Forward() * -80) + elseif cHullz > 84 then + view.origin = origin + Vector(0, 0, cHullz - 84) + (angles:Forward() * -80) + else + view.origin = origin + Vector(0, 0, 8) + (angles:Forward() * -80) + end + end + elseif pl:Team() == TEAM_HUNTERS && pl:Alive() then + local wep = pl:GetActiveWeapon() + if wep && wep != NULL 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, pl, origin*1, angles*1, fov) + end + end + -- hunter glimpse of thirdperson + if CL_GLIMPCAM > CurTime() then + local trace = {} + + trace.start = origin + trace.endpos = origin + (angles:Forward() * -80) + trace.filter = player.GetAll() + trace.maxs = Vector(4, 4, 4) + trace.mins = Vector(-4, -4, -4) + local tr = util.TraceHull(trace) + + view.drawviewer = true + view.origin = tr.HitPos + end + end + + return view +end + +local mat = "prophunt_enhanced/sprites/luckyball" +local pointer = "prophunt_enhanced/sprites/luckyball_pointer" + +local dmat = "prophunt_enhanced/sprites/devilball" +local dpointer = "prophunt_enhanced/sprites/devilball_pointer" +local crosshair = Material("vgui/hud_crosshair") +-- Draw round timeleft and hunter release timeleft +function HUDPaint() + -- Draw player texts + if GetConVar("ph_enable_plnames"):GetBool() && GetConVar("ph_cl_pltext"):GetBool() && LocalPlayer():Team() != TEAM_SPECTATOR then + for _, pl in pairs(player.GetAll()) do + if pl != LocalPlayer() && (pl && pl:IsValid() && pl:Alive() && pl:Team() == LocalPlayer():Team()) then + local addvector = Vector(0, 0, math.Clamp(pl:EyePos():Distance(LocalPlayer():EyePos())*0.04, 16, 64)) + -- todo: text will disappear in a specified distance. + draw.DrawText(pl:Name().." ("..pl:Health().."%)", "TargetIDSmall", (pl:EyePos() + addvector):ToScreen().x, (pl:EyePos() + addvector):ToScreen().y, team.GetColor(pl:Team()), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER) + end + end + end + + -- Hunter Blindlock Time + if GetGlobalBool("InRound", false) then + local blindlock_time_left = (GetConVarNumber("ph_hunter_blindlock_time") - (CurTime() - GetGlobalFloat("RoundStartTime", 0))) + 1 + + if blindlock_time_left < 1 && blindlock_time_left > -6 then + blindlock_time_left_msg = "Ready or not, here we come!" + elseif blindlock_time_left > 0 then + blindlock_time_left_msg = "Hunters will be unblinded and released in "..string.ToMinutesSeconds(blindlock_time_left) + else + blindlock_time_left_msg = nil + end + + if blindlock_time_left_msg then + surface.SetFont("HunterBlindLockFont") + local tw, th = surface.GetTextSize(blindlock_time_left_msg) + + draw.RoundedBox(8, 20, 20, tw + 20, 26, Color(0, 0, 0, 75)) + draw.DrawText(blindlock_time_left_msg, "HunterBlindLockFont", 31, 26, Color(255, 255, 0, 255), TEXT_ALIGN_LEFT) + end + end + + -- Draw Lucky Balls Icon + if GetConVar("cl_enable_luckyballs_icon"):GetBool() && LocalPlayer():Team() == TEAM_HUNTERS then + local offset = Vector( 0, 0, 45 ) + local ang = LocalPlayer():EyeAngles() + + local w = ScrW() + local h = ScrH() + local cX = w/2 + local cY = h/2 + + for _,ent in pairs(ents.FindByClass('ph_luckyball')) do + local pos = ent:GetPos() + offset + local poscr = pos:ToScreen() + + if LocalPlayer():IsLineOfSightClear(ent) then + + if ((poscr.x > 32 && poscr.x < (w-43)) && (poscr.y > 32 && poscr.y < (h-38))) then + surface.SetDrawColor(255,255,255,255) + surface.SetTexture(surface.GetTextureID(mat)) + surface.DrawTexturedRect( poscr.x-32, poscr.y, 64, 64 ) + else + local r = math.Round(cX/2) + local rad = math.atan2(poscr.y-cY, poscr.x-cX) + local deg = 0 - math.Round(math.deg(rad)) + surface.SetDrawColor(255,255,255,255) + surface.SetTexture(surface.GetTextureID(pointer)) + surface.DrawTexturedRectRotated(math.cos(rad)*r+cX, math.sin(rad)*r+cY,64,64,deg+90) + end + + end + end + + end + + -- Draw Devil Ball Icon + if GetConVar("cl_enable_devilballs_icon"):GetBool() && LocalPlayer():Team() == TEAM_PROPS then + local offset = Vector( 0, 0, 35 ) + local ang = LocalPlayer():EyeAngles() + + local w = ScrW() + local h = ScrH() + local cX = w/2 + local cY = h/2 + + for _,ent in pairs(ents.FindByClass('ph_devilball')) do + local pos = ent:GetPos() + offset + local poscr = pos:ToScreen() + + if LocalPlayer():IsLineOfSightClear(ent) then + + if ((poscr.x > 32 && poscr.x < (w-43)) && (poscr.y > 32 && poscr.y < (h-38))) then + surface.SetDrawColor(255,255,255,255) + surface.SetTexture(surface.GetTextureID(dmat)) + surface.DrawTexturedRect( poscr.x-32, poscr.y, 64, 64 ) + else + local r = math.Round(cX/2) + local rad = math.atan2(poscr.y-cY, poscr.x-cX) + local deg = 0 - math.Round(math.deg(rad)) + surface.SetDrawColor(255,255,255,255) + surface.SetTexture(surface.GetTextureID(dpointer)) + surface.DrawTexturedRectRotated(math.cos(rad)*r+cX, math.sin(rad)*r+cY,64,64,deg+90) + end + + end + end + + end + + -- Prop Crosshair + if GetConVar("ph_show_custom_crosshair"):GetBool() && LocalPlayer():Team() == TEAM_PROPS && LocalPlayer():Alive() then + local color + local trace = {} + if cHullz < 24 then + trace.start = LocalPlayer():EyePos() + Vector(0, 0, cHullz + (24-cHullz)) + trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, cHullz + (24-cHullz)) + LocalPlayer():EyeAngles():Forward() * 100 + elseif cHullz > 84 then + trace.start = LocalPlayer():EyePos() + Vector(0, 0, cHullz - 84) + trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, cHullz - 84) + LocalPlayer():EyeAngles():Forward() * 300 + else + trace.start = LocalPlayer():EyePos() + Vector(0, 0, 8) + trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, 8) + LocalPlayer():EyeAngles():Forward() * 100 + end + trace.filter = ents.FindByClass("ph_prop") + + local trace2 = util.TraceLine(trace) + if trace2.Entity && trace2.Entity:IsValid() && table.HasValue(PHE.USABLE_PROP_ENTITIES, trace2.Entity:GetClass()) then + color = Color(10,255,10,255) + else + color = Color(255,255,255,255) + end + surface.SetDrawColor( color ) + surface.SetMaterial( crosshair ) + surface.DrawTexturedRect( ScrW() / 2 - ( 64 / 2 ), ScrH() / 2 - ( 64 / 2 ), 64, 64 ) + end + + -- The 'You were Killed By' text, or the Freeze Cam text. + if LocalPlayer():GetNWBool("InFreezeCam", false) then + local w1, h1 = surface.GetTextSize("You were killed by "..LocalPlayer():GetNWEntity("PlayerKilledByPlayerEntity", nil):Name() ); + local textx = ScrW()/2 + local steamx = (ScrW()/2) - 32 + draw.SimpleTextOutlined("You were killed by "..LocalPlayer():GetNWEntity("PlayerKilledByPlayerEntity", nil):Name(), "TrebuchetBig", textx, ScrH()*0.75, Color(255, 10, 10, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 1.5, Color(0, 0, 0, 255)) + end +end +hook.Add("HUDPaint", "PH_HUDPaint", HUDPaint) + + +-- After the player has been drawn +function PH_PostPlayerDraw(pl) + -- Draw a line on hunters + if GetConVar("ph_cl_spec_hunter_line"):GetBool() && (!LocalPlayer():Alive() || LocalPlayer():Team() == TEAM_SPECTATOR) then + if IsValid(pl) && pl:Alive() && pl:Team() == TEAM_HUNTERS then + render.DrawLine(pl:GetShootPos(), pl:GetEyeTrace().HitPos, team.GetColor(pl:Team()), true) + render.SetMaterial(MAT_LASERDOT) + render.DrawSprite(pl:GetEyeTrace().HitPos, 8, 8, team.GetColor(pl:Team())) + end + end +end +hook.Add("PostPlayerDraw", "PH_PostPlayerDraw", PH_PostPlayerDraw) + +hook.Add("PrePlayerDraw", "PHE.HidePlayer", function(ply) + if ply:Team() == TEAM_PROPS then return true end +end) + +-- Draws halos on team members +function PHEDrawPropselectHalos() + + if GetConVar("ph_cl_halos"):GetBool() then + -- Something to tell if the prop is selectable + if LocalPlayer():Team() == TEAM_PROPS && LocalPlayer():Alive() then + local trace = {} + -- fix for smaller prop size. They should stay horizontal rather than looking straight down. + if cHullz < 24 then + trace.start = LocalPlayer():EyePos() + Vector(0, 0, cHullz + (24-cHullz)) + trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, cHullz + (24-cHullz)) + LocalPlayer():EyeAngles():Forward() * 100 + elseif cHullz > 84 then + trace.start = LocalPlayer():EyePos() + Vector(0, 0, cHullz - 84) + trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, cHullz - 84) + LocalPlayer():EyeAngles():Forward() * 300 + else + trace.start = LocalPlayer():EyePos() + Vector(0, 0, 8) + trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, 8) + LocalPlayer():EyeAngles():Forward() * 100 + end + trace.filter = ents.FindByClass("ph_prop") + + local trace2 = util.TraceLine(trace) + if trace2.Entity && trace2.Entity:IsValid() && table.HasValue(PHE.USABLE_PROP_ENTITIES, trace2.Entity:GetClass()) then + local ent_table = {} + table.insert(ent_table, trace2.Entity) + halo.Add(ent_table, Color(20, 250, 0), 1.2, 1.2, 1, true, true) + end + end + + end +end +hook.Add("PreDrawHalos", "PHEDrawPropselectHalos", PHEDrawPropselectHalos) + +-- Play random taunt +hook.Add("KeyPress", "tracetest.GetPropInfo", function(pl, key) + if ((pl:Team() == TEAM_PROPS && pl:Alive()) && key == IN_ATTACK2) then + LocalPlayer():ConCommand("gm_showspare1") + end +end) + +-- Called every client frame +function GM:Think() + -- Prop light + if client_prop_light && LocalPlayer() && LocalPlayer():IsValid() && LocalPlayer():Alive() && LocalPlayer():Team() == TEAM_PROPS then + local prop_light = DynamicLight(LocalPlayer():EntIndex()) + if prop_light then + prop_light.pos = LocalPlayer():GetPos() + prop_light.r = 255 + prop_light.g = 255 + prop_light.b = 255 + prop_light.brightness = 0.25 + prop_light.decay = 1 + prop_light.size = 180 + prop_light.dietime = CurTime() + 0.1 + end + end +end + +-- ///////////////////\\\\\\\\\\\\\\\\\ -- +-- Net Receives Hooks -- +-- ///////////////////\\\\\\\\\\\\\\\\\ -- + +local tutormat = "vgui/hud_control_help.png" +local curshow = 0 +net.Receive("PH_ShowTutor", function() + if GetConVar("ph_show_tutor_control"):GetBool() && LocalPlayer():Alive() then + + if curshow <= 2 then + + local xNotify = vgui.Create( "DNotify" ) + xNotify:SetPos( ScrW() - 300 , 60 ) + xNotify:SetSize( 256, 256 ) + xNotify:SetLife(12) + + local bg = vgui.Create( "DPanel", xNotify ) + bg:Dock( FILL ) + bg:SetBackgroundColor( Color( 16, 16, 16, 180 ) ) + + local image = vgui.Create( "DImage", bg ) + image:SetImage(tutormat) + image:Dock(FILL) + + xNotify:AddItem(bg) + + curshow = curshow + 1 + + end + end +end) + +-- Receive the Winning Notification +net.Receive("PH_RoundDraw_Snd", function(len) + if GetConVar("ph_cl_endround_sound"):GetBool() then + surface.PlaySound(table.Random(PHE.WINNINGSOUNDS["Draw"])) + end +end) +net.Receive("PH_TeamWinning_Snd", function(len) + local snd = net.ReadString() + if GetConVar("ph_cl_endround_sound"):GetBool() then + surface.PlaySound(snd) + end +end) + +-- Resets the player hull +net.Receive("ResetHull", function() + if LocalPlayer() && LocalPlayer():IsValid() then + LocalPlayer():ResetHull() + cHullz = 64 + end +end) + +-- Sets the local blind variable to be used in CalcView +net.Receive("SetBlind", function() + blind = net.ReadBool() +end) + +--[[ Here you can add more than 2 additional freeze cam sounds. +You can add more sounds by using table.insert(PHE.FreezeCamSnd, ) repeatedly outside of this code scope. +Example: + table.insert(PHE.FreezeCamSnd, "vo/k_lab/kl_fiddlesticks.wav") + table.insert(PHE.FreezeCamSnd, "vo/k_lab/kl_ohdear.wav") + ...more ]] + +-- If you wish to use a single sound instead, use ph_fc_use_single_sound 1 & ph_fc_cue_path "" convar to override. + +PHE.FreezeCamSnd = { + -- do not manually add sounds in here, which this may break the sound list. Use table.insert instead! + "misc/freeze_cam.wav", + "misc/freeze_cam_sad1.wav" +} +-- Plays the Freeze Cam sound +net.Receive("PlayFreezeCamSound", function() + if GetConVar("ph_fc_use_single_sound"):GetBool() then + surface.PlaySound(GetConVar("ph_fc_cue_path"):GetString()) + else + surface.PlaySound(table.Random(PHE.FreezeCamSnd)) + end +end) + +-- Sets the player hull +net.Receive("SetHull", function() + local hullxy = net.ReadInt(32) + local huz = net.ReadInt(32) + local hulldz = net.ReadInt(32) + local new_health = net.ReadInt(9) + cHullz = huz + LocalPlayer():SetHull(Vector(hullxy * -1, hullxy * -1, 0), Vector(hullxy, hullxy, huz)) + LocalPlayer():SetHullDuck(Vector(hullxy * -1, hullxy * -1, 0), Vector(hullxy, hullxy, hulldz)) + LocalPlayer():SetHealth(new_health) +end) + +-- Replaces the flashlight with a client-side dynamic light for props +net.Receive("PlayerSwitchDynamicLight", function() + if client_prop_light then + client_prop_light = false + surface.PlaySound("prop_idbs/light_off1.wav") + CL_GLOBAL_LIGHT_STATE = 0 + else + client_prop_light = true + surface.PlaySound("prop_idbs/light_on.wav") + CL_GLOBAL_LIGHT_STATE = 1 + end +end) + +-- Turns the dynamic light OFF +net.Receive("DisableDynamicLight", function() + if client_prop_light then + client_prop_light = false + end +end) diff --git a/gamemodes/prop_hunt/gamemode/cl_menu.lua b/gamemodes/prop_hunt/gamemode/cl_menu.lua new file mode 100644 index 0000000..5367a85 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/cl_menu.lua @@ -0,0 +1,646 @@ +local Ph = {} +function ph_BaseMainWindow(ply, cmd, args) + local mdlName = ply:GetInfo("cl_playermodel") + local mdlPath = player_manager.TranslatePlayerModel(mdlName) + + local frm = vgui.Create("DFrame") + frm:SetSize(ScrW()-96,ScrH()-64) + frm:SetTitle("Prop Hunt: Enhanced | Help & Settings menu") + frm.Paint = function(self,w,h) + surface.SetDrawColor(30,30,30,180) + surface.DrawRect(0,0,w,h) + end + frm:SetDraggable(false) + frm:Center() + frm:MakePopup() + + local tab = vgui.Create("DPropertySheet", frm) + tab:Dock(FILL) + tab:DockMargin(12,12,12,12) + tab.Paint = function(self) + surface.SetDrawColor(50,50,50,255) + surface.DrawRect(0,0,self:GetWide(),self:GetTall()) + end + + function Ph:GetMutedStateIcon(bool) + if bool then + return "vgui/phehud/voice_off" + end + + return "vgui/phehud/voice_on" + end + + function Ph:CreateBasicLayout(color,pTab) -- Warning: This one only can be used within this scope! todo: See 'cl_credits.lua' to see some details. + local panel = vgui.Create("DPanel", pTab) + panel:SetBackgroundColor(color) + + local scroll = vgui.Create( "DScrollPanel", panel ) + scroll:Dock(FILL) + + local grid = vgui.Create("DGrid", scroll) + grid:Dock(NODOCK) + grid:SetPos(10,10) + grid:SetCols(1) + grid:SetColWide(800) + grid:SetRowHeight(32) + + return panel,grid + end + + -- Base Function for Automated-VGUI Creation. I've Spent 8 Hours to do this with laptop keep autoshutdowns... Damn it + -- Usage of Ph:CreateVGUIType(cmd,typ,data,panel,text) + -- typ: check, label, btn, slider + function Ph:CreateVGUIType(cmd,typ,data,panel,text) + -- CheckBox + if typ == "check" then + if type(data) == "string" then + local chk = vgui.Create("DCheckBoxLabel") + chk:SetSize(panel:GetColWide(),panel:GetRowHeight()) + chk:SetText(text) + local num = GetConVar(cmd):GetBool() + if num then + chk:SetChecked(true); chk:SetValue(1); + else + chk:SetChecked(false); chk:SetValue(0); + end + function chk:OnChange(bool) + local v = 0 + if bool then + v = 1 + else + v = 0 + end + if data == "SERVER" then + net.Start("SvCommandReq") + net.WriteString(cmd) + net.WriteInt(v,2) + net.SendToServer() + elseif data == "CLIENT" then + RunConsoleCommand(cmd, v) + chat.AddText(Color(200,0,0),"[Settings]", color_white, " Cvar '"..cmd.."' has been changed to "..v) + if v == 1 then + surface.PlaySound("buttons/button9.wav") + else + surface.PlaySound("buttons/button19.wav") + end + end + end + panel:AddItem(chk) + else + print(cmd.." -> Ph:CreateVGUIType FAILED! - 'data' argument must containt string value, Got: "..type(data).." instead!!") + end + end + + -- Label + if typ == "label" then + local txt = vgui.Create("DLabel") + txt:SetSize(panel:GetColWide(),panel:GetRowHeight()) + txt:SetText(text) + if !data then + txt:SetFont("HudHintTextLarge") + else + txt:SetFont(data) + end + txt:SetTextColor(color_white) + panel:AddItem(txt) + end + + -- Spacer/Divider + if typ == "spacer" then + local pnl = vgui.Create("DPanel") + pnl:SetSize(panel:GetColWide(),panel:GetRowHeight()) + pnl:SetBackgroundColor(Color(0,0,0,0)) + + panel:AddItem(pnl) + end + + -- Button + if typ == "btn" then + if type(data) == "table" then + -- How many buttons that will be created. Note: maximum are 6 buttons in 1 segment. + local legal = data.max + if data.max < 1 then legal = 1 end + if data.max > 6 then legal = 6 end + + local pnl = vgui.Create("DPanel") + pnl:SetSize(panel:GetColWide(),panel:GetRowHeight()) + pnl:SetBackgroundColor(Color(0,0,0,0)) + + local function btncreation(pPanel,pText, f) + local btn = vgui.Create("DButton", pPanel) + btn:SetText(pText) + btn:Dock(LEFT) + btn:DockMargin(8,2,0,2) + -- If this looks stupid, but it working, it ain't stupid! + btn:SizeToContents() + btn:SetSize(btn:GetWide()+8,btn:GetTall()) + btn.DoClick = f + end + + for i=1,legal do + btncreation(pnl,data.textdata[i][1], data.textdata[i][2]) + end + panel:AddItem(pnl) + else + print(cmd.." -> Ph:CreateVGUIType FAILED! - 'data' argument must containt table value, Example:\n\n { max = max_num_button, textdata = {[1] = {text, function}, [2] = {text, function}, etc...}} \n --> Got "..type(data).." instead!!") + end + end + + -- Slider + if typ == "slider" then + if type(data) == "table" then + local min = data.min + local max = data.max + local dval = data.init + local dec = data.dec + local kind = data.kind + local float = data.float + + local pnl = vgui.Create("DPanel") + pnl:SetSize(panel:GetColWide(),panel:GetRowHeight()-6) + pnl:SetBackgroundColor(Color(120,120,120,200)) + + local slider = vgui.Create("DNumSlider",pnl) + slider:SetPos(10,0) + slider:SetSize(panel:GetColWide()-30,panel:GetRowHeight()-6) + slider:SetText(text) + slider:SetMin(min) + slider:SetMax(max) + slider:SetValue(dval) + slider:SetDecimals(dec) + slider.OnValueChanged = function(pnl,val) + slider:SetValue(val) + if kind == "SERVER" then + net.Start("SvCommandSliderReq") + net.WriteString(cmd) + net.WriteBool(float) + if float then + net.WriteFloat(val) + else + net.WriteInt(slider:GetValue(), 16) + end + net.SendToServer() + elseif kind == "CLIENT" then + if float then + RunConsoleCommand(cmd, val) + else + RunConsoleCommand(cmd, math.Round(val)) + end + end + end + panel:AddItem(pnl) + else + print(cmd.." -> Ph:CreateVGUIType FAILED! - 'data' argument must containt table value, Example:\n\n { min = min value, max = max value, init = initial value, dec = decimal count, kind = SERVER/CLIENT} } \n --> Got "..type(data).." instead!!") + end + end + + -- Mute Functions + if typ == "mute" then + if type(data) == "Player" && IsValid(data) then + local ply = data + + local pnl = vgui.Create("DPanel") + pnl:SetSize(panel:GetColWide(),panel:GetRowHeight()-6) + pnl:SetBackgroundColor(Color(20,20,20,150)) + + local ava = vgui.Create("AvatarImage", pnl) + ava:Dock(LEFT) + ava:SetSize(24,24) + ava:SetPlayer(ply,32) + + local name = vgui.Create("DLabel", pnl) + name:Dock(LEFT) + name:DockMargin(8,4,8,4) + name:SetSize(panel:GetColWide()/2,0) + name:SetText(ply:Nick()) + name:SetFont("HudHintTextLarge") + name:SetTextColor(color_white) + + local imagebtn + local button = vgui.Create("DButton", pnl) + button:Dock(RIGHT) + button:DockMargin(4,0,4,0) + button:SetSize(24,0) + button:SetText("") + button.Paint = function(btn) + surface.SetDrawColor(90,90,90,0) + surface.DrawRect(0,0,btn:GetWide(),btn:GetTall()) + end + + button.DoClick = function() + if not IsValid(ply) then return end + local mute = ply:IsMuted() + ply:SetMuted(not mute) + imagebtn:SetImage(Ph:GetMutedStateIcon(not mute)) + end + + if ply == LocalPlayer() then + button:SetVisible(false) + else + button:SetVisible(true) + end + + imagebtn = vgui.Create("DImage",button) + imagebtn:Dock(FILL) + imagebtn:SetImage(Ph:GetMutedStateIcon(ply:IsMuted())) + + panel:AddItem(pnl) + else + print(cmd.." -> Ph:CreateVGUIType FAILED! - 'data' argument must containt Entity userdata value \n --> Got "..type(data).." instead!!") + end + end + end + + function Ph:HelpSelections() + local panel = vgui.Create("DPanel", tab) + panel:SetBackgroundColor(Color(100,100,100,255)) + + local helpImage = vgui.Create("DImage", panel) + helpImage.Count = 1 + helpImage:Dock(FILL) + helpImage:SetImage("vgui/phhelp1.vmt") + + local pBottom = vgui.Create("DPanel", panel) + pBottom:Dock(BOTTOM) + pBottom:SetSize(0,40) + pBottom:SetBackgroundColor(Color(0,0,0,0)) + + local motd = vgui.Create("DButton", pBottom) + motd:Dock(FILL) + motd:SetSize(0,40) + motd:SetText("SERVER INFORMATION & RULES [MOTD]") + motd:SetFont("PHE.ArmorFont") + motd:SetTextColor(color_white) + motd.hover = {r=55,g=55,b=55} + motd.Paint = function(pnl) + if pnl:IsHovered() then + pnl.hover = {r=70,g=70,b=70} + else + pnl.hover = {r=55,g=55,b=55} + end + surface.SetDrawColor(pnl.hover.r,pnl.hover.g,pnl.hover.b,255) + surface.DrawRect(0,0,motd:GetWide(),motd:GetTall()) + end + motd.DoClick = function() ply:ConCommand("ulx motd"); frm:Close() end + + local bnext = vgui.Create("DButton", pBottom) + bnext:Dock(RIGHT) + bnext:SetSize(128,40) + bnext:SetText("NEXT >") + bnext:SetFont("HudHintTextLarge") + bnext:SetTextColor(color_white) + bnext.hover = {r=100,g=100,b=100} + bnext.Paint = function(pnl) + if pnl:IsHovered() then + pnl.hover = {r=130,g=130,b=130} + pnl:SetTextColor(color_white) + elseif pnl:GetDisabled() then + pnl.hover = {r=20,g=20,b=20} + pnl:SetTextColor(Color(40,40,40)) + else + pnl.hover = {r=100,g=100,b=100} + pnl:SetTextColor(color_white) + end + surface.SetDrawColor(pnl.hover.r,pnl.hover.g,pnl.hover.b,255) + surface.DrawRect(0,0,motd:GetWide(),motd:GetTall()) + end + bnext.DoClick = function(pnl) + helpImage.Count = helpImage.Count + 1 + if helpImage.Count >= 6 then + helpImage.Count = 6 + end + helpImage:SetImage("vgui/phhelp"..helpImage.Count..".vmt") + end + + local bprev = vgui.Create("DButton", pBottom) + bprev:Dock(LEFT) + bprev:SetSize(128,40) + bprev:SetText("< PREVIOUS") + bprev:SetFont("HudHintTextLarge") + bprev:SetTextColor(color_white) + bprev.hover = {r=100,g=100,b=100} + bprev.Paint = function(pnl) + if pnl:IsHovered() then + pnl.hover = {r=130,g=130,b=130} + pnl:SetTextColor(color_white) + elseif pnl:GetDisabled() then + pnl.hover = {r=20,g=20,b=20} + pnl:SetTextColor(Color(40,40,40)) + else + pnl.hover = {r=100,g=100,b=100} + pnl:SetTextColor(color_white) + end + surface.SetDrawColor(pnl.hover.r,pnl.hover.g,pnl.hover.b,255) + surface.DrawRect(0,0,motd:GetWide(),motd:GetTall()) + end + bprev.DoClick = function(pnl) + helpImage.Count = helpImage.Count - 1 + if helpImage.Count <= 1 then + helpImage.Count = 1 + end + helpImage:SetImage("vgui/phhelp"..helpImage.Count..".vmt") + end + + tab:AddSheet("Help", panel, "icon16/help.png") + end + + function Ph:PlayerModelSelections() + local panel = vgui.Create("DPanel", tab) + panel:SetBackgroundColor(Color(40,40,40,120)) + + -- Prefer had to do this instead doing all over and over. + function Ph:PlayerModelAdditions() + + -- the Model's DPanel preview. The Pos & Size must be similar as the ModelPreview. + local panelpreview = vgui.Create( "DPanel", panel ) + panelpreview:Dock(FILL) + panelpreview:SetBackgroundColor(Color(120,120,120,100)) + + -- Model Preview. + local modelPreview = vgui.Create( "DModelPanel", panelpreview ) + modelPreview:Dock(FILL) + modelPreview:SetFOV ( 50 ) + modelPreview:SetModel ( mdlPath ) + + local slider = vgui.Create("DNumSlider", panelpreview) + slider:Dock(BOTTOM) + slider:SetSize(0,32) + slider:SetText(" Set Model FOV") + slider:SetMin(50) + slider:SetMax(90) + slider:SetValue(40) + slider:SetDecimals(0) + slider.OnValueChanged = function(pnl,val) + slider:SetValue(val) + modelPreview:SetFOV(val) + end + + local scroll = vgui.Create( "DScrollPanel", panel ) + scroll:Dock(LEFT) + scroll:SetSize( 720, 0 ) + + -- ^dito, grid dimensions 66x66 w/ Coloumn 7. + local pnl = vgui.Create( "DGrid", scroll ) + pnl:Dock(FILL) + pnl:SetCols( 10 ) + pnl:SetColWide( 68 ) + pnl:SetRowHeight( 68 ) + + local plMode = GetConVar("ph_use_playermodeltype"):GetInt() + local plWhich = { + [0] = player_manager.AllValidModels(), + [1] = list.Get("PlayerOptionsModel") + } + if plMode == nil then plWhich = 0 end + + -- Get All Valid Paired Models and sort 'em out. + for name, model in SortedPairs( plWhich[plMode] ) do + + -- dont forget to cache. + util.PrecacheModel(model) + + local icon = vgui.Create( "SpawnIcon" ) + + -- Click functions + icon.DoClick = function() + surface.PlaySound( "buttons/combine_button3.wav" ) + RunConsoleCommand( "cl_playermodel", name ) + modelPreview:SetModel(model) + Derma_Query("Model " .. name.. " has been selected and it will be applied after respawn!", "Model Applied", + "OK", function() end) + end + + -- Right click functions + icon.DoRightClick = function() + -- Same as above, but they has custom menus once user tries to right click on the models. + local menu = DermaMenu() + -- if user caught it says 'ERROR' but the model present, refresh it (:RebuildSpawnIcon) + menu:AddOption( "Apply Model", function() + surface.PlaySound( "buttons/combine_button3.wav" ) + RunConsoleCommand( "cl_playermodel", name ) + modelPreview:SetModel(model) + Derma_Query("Model " .. name.. " has been selected and it will be applied after respawn!", "Model Applied", "OK", function() end) + end):SetIcon("icon16/tick.png") + menu:AddSpacer() + menu:AddOption( "Refresh Icon", function() icon:RebuildSpawnIcon() end):SetIcon("icon16/arrow_refresh.png") + menu:AddOption( "Preview", function() modelPreview:SetModel(model) end):SetIcon("icon16/magnifier.png") + menu:AddOption( "Model Information", function() + Derma_Message( "Model's name is: " .. name .. "\n \nUsable by: Everyone.", "Model Info", "Close" ) + end ):SetIcon("icon16/information.png") + menu:AddSpacer() + menu:AddOption( "Close" ):SetIcon("icon16/cross.png") + menu:Open() + end + + -- Make sure the user has noticed after choosing a model by indicating from "Borders". + 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 + + -- Set set etc... + icon:SetModel(model) + icon:SetSize(64,64) + icon:SetTooltip(name) + + pnl:AddItem(icon) + end + return pnl + end + + -- Self Explanationary. + if GetConVar("ph_use_custom_plmodel"):GetBool() then + -- Call the VGUI Properties of PlayerModelAdditions(). + Ph:PlayerModelAdditions() + tab:AddSheet("Player Model", panel, "icon16/brick.png") + else + -- Show small message instead + local scroll = vgui.Create( "DScrollPanel", panel ) + scroll:Dock(FILL) + + local gridmdl = vgui.Create("DGrid", scroll) + gridmdl:Dock(NODOCK) + gridmdl:SetPos(10,10) + gridmdl:SetCols(1) + gridmdl:SetColWide(800) + gridmdl:SetRowHeight(32) + + Ph:CreateVGUIType("", "label", false, gridmdl, "Sorry, Custom Player Model is disabled on this server!") + + -- this hook is intended to use for custom player model outside from PH:E Menu. (like Custom Donator Model window or something). + hook.Call("PH_CustomPlayermdlButton", nil, panel, gridmdl, function(cmd,typ,data,panel,text) Ph:CreateVGUIType(cmd,typ,data,panel,text) end) + + tab:AddSheet("Player Model", panel, "icon16/brick.png") + end + end + + function Ph:PlayerOption() + local panel,gridpl = Ph:CreateBasicLayout(Color(40,40,40,180),tab) + + Ph:CreateVGUIType("", "label", false, gridpl, "Player Options:") + Ph:CreateVGUIType("ph_cl_halos", "check", "CLIENT", gridpl, "Toggle Halo effect when choosing a prop" ) + Ph:CreateVGUIType("ph_cl_pltext", "check", "CLIENT", gridpl, "Show Team player names above their heads instead (and appear through wall too)") + Ph:CreateVGUIType("ph_cl_endround_sound", "check", "CLIENT", gridpl, "Play End round sound cue") + Ph:CreateVGUIType("ph_cl_autoclose_taunt", "check", "CLIENT", gridpl, "Option for Auto closing for Taunt window when double-clicking them") + Ph:CreateVGUIType("ph_cl_spec_hunter_line", "check", "CLIENT", gridpl, "Draw a line on hunters so we can see their aim in spectator mode.") + Ph:CreateVGUIType("cl_enable_luckyballs_icon", "check", "CLIENT", gridpl, "Enable 'Lucky ball' icon to be displayed once they are spawned") + Ph:CreateVGUIType("cl_enable_devilballs_icon", "check", "CLIENT", gridpl, "Enable 'Devil ball' icon to be displayed once they are spawned") + Ph:CreateVGUIType("hudspacer","spacer",nil,gridpl,"" ) + Ph:CreateVGUIType("", "label", false, gridpl, "HUD Settings") + Ph:CreateVGUIType("ph_hud_use_new", "check", "CLIENT", gridpl, "Use New PH: Enhanced HUD") + Ph:CreateVGUIType("ph_show_tutor_control", "check", "CLIENT", gridpl, "Show Tutorial Pop-up (Shown only 2x on each prop spawns)") + Ph:CreateVGUIType("ph_show_custom_crosshair", "check", "CLIENT", gridpl, "Enable Custom Crosshair") + Ph:CreateVGUIType("ph_show_team_topbar", "check", "CLIENT", gridpl, "Show total alive team players bar on the top left (At least 4 Players will be shown)") + + tab:AddSheet("Player", panel, "icon16/user_orange.png") + end + + function Ph:PlayerMute() + local panel,gridmute = Ph:CreateBasicLayout(Color(40,40,40,180),tab) + + Ph:CreateVGUIType("","label",false,gridmute,"Select one player that you wish to mute.") + for _,Plys in pairs(player.GetAll()) do + Ph:CreateVGUIType("","mute",Plys,gridmute,"") + end + + tab:AddSheet("Mute", panel, "icon16/sound_delete.png") + end + -- Call All Functions, but Admin (must check by serverside user rights from sv_admin.lua) + Ph:HelpSelections() + Ph:PlayerMute() + Ph:PlayerOption() + Ph:PlayerModelSelections() + + -- Custom Hook Menu here. Give 1 second for better safe-calling... + timer.Simple(1, function() + hook.Call("PH_CustomTabMenu", nil, tab, function(cmd,typ,data,panel,text) Ph:CreateVGUIType(cmd,typ,data,panel,text) end) + end) + + function Ph:ShowAdminMenu() + local panel,grid = Ph:CreateBasicLayout(Color(40,40,40,180),tab) + + Ph:CreateVGUIType("", "label", false, grid, "Serverside gamemode Options (Only visible for Admins/Owner)") + Ph:CreateVGUIType("ph_use_custom_plmodel", "check", "SERVER", grid, "Enable custom models for Hunters") + Ph:CreateVGUIType("ph_use_custom_plmodel_for_prop", "check", "SERVER", grid, "Enable custom models for Props - Make sure to enable for Hunter too.") + Ph:CreateVGUIType("ph_customtaunts_delay", "slider", {min = 2, max = 120, init = GetConVar("ph_customtaunts_delay"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Custom Taunts Delay (Seconds)") + Ph:CreateVGUIType("ph_normal_taunt_delay", "slider", {min = 2, max = 120, init = GetConVar("ph_normal_taunt_delay"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Normal Taunts Delay (Seconds)") + Ph:CreateVGUIType("ph_autotaunt_enabled", "check", "SERVER", grid, "Enable Auto Taunt Features") + Ph:CreateVGUIType("ph_autotaunt_delay", "slider", {min = 30, max = 180, init = GetConVar("ph_autotaunt_delay"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Auto Taunts Delay (Seconds)") + Ph:CreateVGUIType("devspacer","spacer",nil,grid,"" ) + Ph:CreateVGUIType("ph_notice_prop_rotation", "check", "SERVER", grid, "Display 'Prop Rotation' notification on every Prop Spawns") + Ph:CreateVGUIType("ph_prop_camera_collisions", "check", "SERVER", grid, "Enable Prop Camera collision to the wall") + Ph:CreateVGUIType("ph_freezecam", "check", "SERVER", grid, "Enable Freecam features for team props") + Ph:CreateVGUIType("ph_prop_collision", "check", "SERVER", grid, "Enable Prop collide on each other prop players") + Ph:CreateVGUIType("ph_swap_teams_every_round", "check", "SERVER", grid, "Swap team every round - Disabling means team will stay forever") + Ph:CreateVGUIType("ph_hunter_fire_penalty", "slider", {min = 2, max = 80, init = GetConVar("ph_hunter_fire_penalty"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Hunter points penalty") + Ph:CreateVGUIType("ph_hunter_kill_bonus", "slider", {min = 5, max = 100, init = GetConVar("ph_hunter_kill_bonus"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Hunter kill bonus") + Ph:CreateVGUIType("ph_game_time", "slider", {min = 20, max = 300, init = GetConVar("ph_game_time"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Total Game time (Minutes)") + Ph:CreateVGUIType("ph_hunter_blindlock_time", "slider", {min = 15, max = 60, init = GetConVar("ph_hunter_blindlock_time"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Hunter blindlock time (Seconds)") + Ph:CreateVGUIType("ph_round_time", "slider", {min = 120, max = 600, init = GetConVar("ph_round_time"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Game round time (Seconds)") + Ph:CreateVGUIType("ph_rounds_per_map", "slider", {min = 5, max = 30, init = GetConVar("ph_rounds_per_map"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Total game Rounds per Map") + Ph:CreateVGUIType("ph_enable_lucky_balls", "check", "SERVER", grid, "Allow Lucky Balls Features to be spawned on breakable props (Chance is 8%)") + Ph:CreateVGUIType("ph_enable_devil_balls", "check", "SERVER", grid, "Allow Devil Balls Features to be spawned when hunter dies (Chance is 70%)") + Ph:CreateVGUIType("ph_waitforplayers", "check", "SERVER", grid, "Wait for Players to begin the gameplay") + Ph:CreateVGUIType("ph_min_waitforplayers", "slider", { min = 1, max = game.MaxPlayers(), init = GetConVar("ph_min_waitforplayers"):GetInt(), dec = 0, kind = "SERVER" }, grid, "Mininum Players to Wait before the game starts (default: 1)") + Ph:CreateVGUIType("", "label", false, grid, "Enable Custom Taunt. Mode: 0 = Random, 1 = Custom, 2 Both mode)") + Ph:CreateVGUIType("", "btn", {max = 2, textdata = { + [1] = {"--[ Current Mode is Mode: "..GetConVar('ph_enable_custom_taunts'):GetInt().." ] --", + function(self) + local CusTauntConvar = { + [0] = "Mode [0/F3]: Random Taunt", + [1] = "Mode [1/C]: Custom Taunt", + [2] = "Mode [2]: Both Modes" + } + local function SendTauntCommandState(state) + net.Start("SendTauntStateCmd") + net.WriteString(tostring(state)) + net.SendToServer() + end + + self:SetText(CusTauntConvar[GetConVar("ph_enable_custom_taunts"):GetInt()]) + local state = 0 + if GetConVar("ph_enable_custom_taunts"):GetInt() == 0 then + state = 1 + SendTauntCommandState(1) + self:SetText(CusTauntConvar[state]) + elseif GetConVar("ph_enable_custom_taunts"):GetInt() == 1 then + state = 2 + SendTauntCommandState(2) + self:SetText(CusTauntConvar[state]) + elseif GetConVar("ph_enable_custom_taunts"):GetInt() == 2 then + state = 0 + SendTauntCommandState(0) + self:SetText(CusTauntConvar[state]) + end + end}, + [2] = {"Open Taunt Window", function(self) + if !LocalPlayer():Alive() then + print("You must do this action when you are alive!") + frm:Close() + else + LocalPlayer():ConCommand("ph_showtaunts") + end + end} + } + }, grid ,"") + Ph:CreateVGUIType("devspacer","spacer",nil,grid,"" ) + Ph:CreateVGUIType("", "label", false, grid, "Developer Options/Experimentals Features") + Ph:CreateVGUIType("phe_check_props_boundaries", "check", "SERVER", grid, "[WORK IN PROGRESS] Enable Boundaries Check? This prevents you to get stuck with objects/walls.") + Ph:CreateVGUIType("ph_mkbren_use_new_mdl","check","SERVER",grid, "Developer: Use new model for Bren MK II Bonus Weapon (Require Map Restart!)") + Ph:CreateVGUIType("ph_print_verbose", "check", "SERVER", grid, "Developer: Enable verbose information of PH:E events in the console") + Ph:CreateVGUIType("ph_enable_plnames", "check", "SERVER", grid, "Enable Player team names to be appear on their screen.") + Ph:CreateVGUIType("ph_fc_use_single_sound", "check", "SERVER", grid, "Use single Freezecam sound instead of sound list (Use 'ph_fc_cue_path' to determine Freezecam sound path)") + Ph:CreateVGUIType("ph_use_playermodeltype", "check", "SERVER", grid, "Use Legacy Model List : 0 = All Playermodels (AddValidModel), 1 = Use Legacy: list.Get('PlayerOptionsModel')") + Ph:CreateVGUIType("ph_prop_jumppower", "slider", {min = 1, max = 3, init = GetConVar("ph_prop_jumppower"):GetFloat(), dec = 2, float = true, kind = "SERVER"}, grid, "Additional Jump Power multiplier for Props") + Ph:CreateVGUIType("ph_sv_enable_obb_modifier","check","SERVER",grid, "Developer: Enable Customized Prop Entity OBB Model Data Modifier") + Ph:CreateVGUIType("ph_reload_obb_setting_everyround","check","SERVER",grid, "Developer: Reload Customized Prop Entity OBB Model Data Modifier every round restarts") + + tab:AddSheet("Admins", panel, "icon16/user_gray.png") + end + + function Ph:MapVoteMenu() + local panel,grid = Ph:CreateBasicLayout(Color(40,40,40,180),tab) + + Ph:CreateVGUIType("", "label", false, grid, "MapVote Settings") + Ph:CreateVGUIType("mv_allowcurmap","check","SERVER",grid,"Allow Current map to be Voted") + Ph:CreateVGUIType("mv_cooldown","check","SERVER",grid,"Enable map Cooldown for voting") + Ph:CreateVGUIType("mv_use_ulx_votemaps","check","SERVER",grid,"Use map listing from ULX Mapvote? 1 = use from ULX mapvote list (which you can whitelist them), 0 = use default maps/*.bsp directory listing.") + Ph:CreateVGUIType("mv_maplimit", "slider", {min = 2, max = 80, init = GetConVar("mv_maplimit"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Number of Maps to be shown in MapVote.") + Ph:CreateVGUIType("mv_timelimit", "slider", {min = 15, max = 90, init = GetConVar("mv_timelimit"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Time in Seconds for default mapvote when voting.") + Ph:CreateVGUIType("mv_mapbeforerevote", "slider", {min = 1, max = 10, init = GetConVar("mv_mapbeforerevote"):GetInt(), dec = 0, kind = "SERVER"}, grid, "How many times cooldown map to be appear again?") + Ph:CreateVGUIType("mv_rtvcount", "slider", {min = 2, max = game.MaxPlayers(), init = GetConVar("mv_rtvcount"):GetInt(), dec = 0, kind = "SERVER"}, grid, "How many players required to use RTV (Rock the Vote)") + Ph:CreateVGUIType("s1","spacer",nil,grid,"" ) + Ph:CreateVGUIType("", "label", false, grid, "To Setup which map should be listed, use (for example) [ mv_mapprefix 'ph_,cs_,de_' ] in the console.") + Ph:CreateVGUIType("", "label", false, grid, "If you are unable to do a MapVote, you NEED to install ULX Admin Mod!") + Ph:CreateVGUIType("s2","spacer",nil,grid,"" ) + Ph:CreateVGUIType("", "label", false, grid, "MapVote Action (To cancel, simply type !unmap_vote in the chat or type 'unmap_vote' in console)") + Ph:CreateVGUIType("", "btn", {max = 2, textdata = { + [1] = {"Start MapVote", function(self) + LocalPlayer():ConCommand("map_vote") + end + }, + [2] = {"Stop MapVote", function(self) + LocalPlayer():ConCommand("unmap_vote") + end} + } + },grid,"") + + tab:AddSheet("MapVote", panel, "icon16/map.png") + end + + -- if Current User is Admin then check their user as security measure in the server. + if ply:IsAdmin() then + net.Start("CheckAdminFirst") + net.SendToServer() + end + + -- if Current User Passes the admin check, shows the admin tab. + net.Receive("CheckAdminResult", function(len, pln) + Ph:ShowAdminMenu() + Ph:MapVoteMenu() + end) +end +concommand.Add("ph_enhanced_show_help", ph_BaseMainWindow, nil, "Show Prop Hunt: Enhanced Main and Help menus." ) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/cl_targetid.lua b/gamemodes/prop_hunt/gamemode/cl_targetid.lua new file mode 100644 index 0000000..6e07553 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/cl_targetid.lua @@ -0,0 +1,51 @@ +function GM:HUDDrawTargetID() + local tr = util.GetPlayerTrace(LocalPlayer()) + local trace = util.TraceLine(tr) + + -- Don't show if 'Player Names above their head' is enabled. + if GetConVar("ph_enable_plnames"):GetBool() && GetConVar("ph_cl_pltext"):GetBool() then return end + + if (!trace.Hit) then return end + if (!trace.HitNonWorld) then return end + + local text = "ERROR" + local font = "TargetID" + + if (trace.Entity:IsPlayer() && trace.Entity:Team() == LocalPlayer():Team()) then + text = trace.Entity:Nick() + else + return + end + + surface.SetFont(font) + local w, h = surface.GetTextSize(text) + local MouseX, MouseY = gui.MousePos() + + if (MouseX == 0 && MouseY == 0) then + MouseX = ScrW() / 2 + MouseY = ScrH() / 2 + end + + local x = MouseX + local y = MouseY + + x = x - w / 2 + y = y + 30 + + draw.SimpleText(text, font, x + 1, y + 1, Color(0, 0, 0, 120)) + draw.SimpleText(text, font, x + 2, y + 2, Color(0, 0, 0, 50)) + draw.SimpleText(text, font, x, y, self:GetTeamColor(trace.Entity)) + + y = y + h + 5 + + local text = trace.Entity:Health().."%" + local font = "TargetIDSmall" + + surface.SetFont(font) + local w, h = surface.GetTextSize(text) + local x = MouseX - w / 2 + + draw.SimpleText(text, font, x + 1, y + 1, Color(0, 0, 0, 120)) + draw.SimpleText(text, font, x + 2, y + 2, Color(0, 0, 0, 50)) + draw.SimpleText(text, font, x, y, self:GetTeamColor(trace.Entity)) +end diff --git a/gamemodes/prop_hunt/gamemode/cl_tauntwindow.lua b/gamemodes/prop_hunt/gamemode/cl_tauntwindow.lua new file mode 100644 index 0000000..1bf0d01 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/cl_tauntwindow.lua @@ -0,0 +1,278 @@ +surface.CreateFont("PHE.TauntFont", +{ + font = "Roboto", + size = 16, + weight = 500, + antialias = true, + shadow = false +}) + +local isplayed = false +local isopened = false +local isforcedclose = false +local hastaunt = false + +net.Receive("PH_ForceCloseTauntWindow", function() + isforcedclose = true +end) + +net.Receive("PH_AllowTauntWindow", function() + isforcedclose = false +end) + +local function MainFrame() + if GetConVar("ph_enable_custom_taunts"):GetInt() < 1 then + chat.AddText(Color(220,0,0),"[PH:E - Taunts] Warning: This server has custom taunts disabled.") + return + end + + isopened = true + + local frame = vgui.Create("DFrame") + frame:SetSize(400,600) + frame:SetTitle("Prop Hunt | Taunt Menu") + frame:Center() + frame:SetVisible(true) + frame:ShowCloseButton(true) + -- Make sure they have Mouse & Keyboard interactions. + frame:SetMouseInputEnabled(true) + frame:SetKeyboardInputEnabled(true) + + frame.Paint = function(self,w,h) + surface.SetDrawColor(Color(40,40,40,180)) + surface.DrawRect(0,0,w,h) + end + + frame.OnClose = function() + isopened = false + hastaunt = false + end + + local function frame_Think_Force() + if isforcedclose == true && isopened == true then + isopened = false + hastaunt = false + frame:Close() + end + end + hook.Add("Think", "CloseWindowFrame_Force", frame_Think_Force) + + local list = vgui.Create("DListView", frame) + + list:SetMultiSelect(false) + list:AddColumn("soundlist") -- because header is gone. + list.m_bHideHeaders = true + list:SetPos(10,52) + list:SetSize(0,450) + list:Dock(BOTTOM) + + local TEAM_TAUNTS = {} + local WHOLE_TEAM_TAUNTS = {} + + -- Determine if prop or hunter taunt list to be used + if (LocalPlayer():Team() == TEAM_HUNTERS) then + TEAM_TAUNTS = PHE:GetTeamTaunt(TEAM_HUNTERS,false) + WHOLE_TEAM_TAUNTS = PHE:GetAllTeamTaunt(TEAM_HUNTERS) + else + TEAM_TAUNTS = PHE:GetTeamTaunt(TEAM_PROPS,false) + WHOLE_TEAM_TAUNTS = PHE:GetAllTeamTaunt(TEAM_PROPS) + end + + for name,_ in pairs(TEAM_TAUNTS) do + list:AddLine(name) + end + + local comb = vgui.Create("DComboBox", frame) + + comb:Dock(TOP) + comb:SetSize(0, 20) + comb:SetValue("Original Taunts") + comb:AddChoice("Original Taunts") + comb:AddChoice("PH:E/Custom Taunts") + + function comb:SortAndStyle(pnl) + pnl:SortByColumn(1,false) + + pnl.Paint = function(self,w,h) + surface.SetDrawColor(Color(50,50,50,180)) + surface.DrawRect(0,0,w,h) + end + + local color = + { + hover = Color(80,80,80,200), + select = Color(120,120,120,255), + alt = Color(60,60,60,180), + normal = Color(50,50,50,180) + } + + for _,line in pairs( pnl:GetLines() ) do + function line:Paint( w, h ) + if ( self:IsHovered() ) then + surface.SetDrawColor(color.hover) + elseif ( self:IsSelected() ) then + surface.SetDrawColor(color.select) + elseif ( self:GetAltLine() ) then + surface.SetDrawColor(color.alt) + else + surface.SetDrawColor(color.normal) + end + surface.DrawRect(0,0,w,h) + end + for _,col in pairs(line["Columns"]) do + col:SetFont("PHE.TauntFont") + col:SetTextColor(color_white) + end + end + end + + comb.OnSelect = function(pnl, idx, val) + if val == "Original Taunts" then + list:Clear() + hastaunt = false + if TEAM_TAUNTS then + for name,val in pairs(TEAM_TAUNTS) do + list:AddLine(name) + end + end + pnl:SortAndStyle(list) + elseif val == "PH:E/Custom Taunts" then + list:Clear() + hastaunt = false + if LocalPlayer():Team() == TEAM_PROPS then + if PHE:GetTeamTaunt(TEAM_PROPS,true) != false then + for name,val in pairs(PHE:GetTeamTaunt(TEAM_PROPS,true)) do + list:AddLine(name) + end + else + list:AddLine("<< WARNING: NO TAUNTS DETECTED! >>") + end + else + if PHE:GetTeamTaunt(TEAM_HUNTERS,true) != false then + for name,val in pairs(PHE:GetTeamTaunt(TEAM_HUNTERS,true)) do + list:AddLine(name) + end + else + list:AddLine("<< WARNING: NO TAUNTS DETECTED! >>") + end + end + pnl:SortAndStyle(list) + end + end + + comb:SortAndStyle(list) + + -- I know, this one is fixed style. + local btnpanel = vgui.Create("DPanel", frame) + btnpanel:Dock(FILL) + btnpanel:SetBackgroundColor(Color(20,20,20,200)) + + local function CreateStyledButton(dock,size,ttip,margin,texture,imagedock, btnfunction) + local left,top,right,bottom = margin[1],margin[2],margin[3],margin[4] + + local button = vgui.Create("DButton", btnpanel) + button:Dock(dock) + button:SetSize(size,0) + button:DockMargin(left,top,right,bottom) + button:SetText("") + button:SetTooltip(ttip) + + button.Paint = function(self,w,h) + if self:IsHovered() then + surface.SetDrawColor(Color(90,90,90,200)) + else + surface.SetDrawColor(Color(0,0,0,0)) + end + surface.DrawRect(0,0,w,h) + end + + button.DoClick = btnfunction + + local image = vgui.Create("DImage", button) + image:SetImage(texture) + image:Dock(imagedock) + end + + local function TranslateTaunt(linename) + return WHOLE_TEAM_TAUNTS[linename] + end + + local function SendToServer(snd) + if !isplayed then + net.Start("CL2SV_PlayThisTaunt"); net.WriteString(tostring(snd)); net.SendToServer(); + isplayed = true + timer.Simple(GetConVar("ph_customtaunts_delay"):GetInt(), function() isplayed = false; end) + else + chat.AddText(Color(220,40,0),"[PH:E - Taunts] Warning: ",Color(220,220,220),"Please wait in " .. GetConVar("ph_customtaunts_delay"):GetInt() .. " seconds...!") + end + end + + CreateStyledButton(LEFT,86,"Play Taunt Locally",{5,5,5,5},"vgui/phehud/btn_play.vmt",FILL, function() + if hastaunt then + local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1)) + surface.PlaySound(getline) + end + end) + CreateStyledButton(LEFT,86,"Play Taunt Globally",{5,5,5,5}, "vgui/phehud/btn_playpub.vmt",FILL, function() + if hastaunt then + local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1)) + SendToServer(getline) + end + end) + CreateStyledButton(LEFT,86,"Play Taunt Globally and Close",{5,5,5,5},"vgui/phehud/btn_playx.vmt",FILL, function() + if hastaunt then + local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1)) + + SendToServer(getline) + frame:Close() + end + end) + CreateStyledButton(FILL,86,"Close the Window",{5,5,5,5},"vgui/phehud/btn_close.vmt",FILL, function() + frame:Close() + end) + + list.OnRowRightClick = function(panel,line) + hastaunt = true + local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1)) + + local menu = DermaMenu() + menu:AddOption("Play (Local)", function() surface.PlaySound(getline); print("Playing: "..getline); end):SetIcon("icon16/control_play.png") + menu:AddOption("Play (Global)", function() SendToServer(getline); end):SetIcon("icon16/sound.png") + menu:AddOption("Play and Close (Global)", function() SendToServer(getline); frame:Close(); end):SetIcon("icon16/sound_delete.png") + menu:AddSpacer() + menu:AddOption("Close Menu", function() frame:Close(); end):SetIcon("icon16/cross.png") + menu:Open() + end + + list.OnRowSelected = function() + hastaunt = true + end + + list.DoDoubleClick = function(id,line) + hastaunt = true + local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1)) + SendToServer(getline) + + if GetConVar("ph_cl_autoclose_taunt"):GetBool() then frame:Close(); end + end + + frame:MakePopup() + frame:SetKeyboardInputEnabled(false) +end + +concommand.Add("ph_showtaunts", function() +if LocalPlayer():Alive() && isforcedclose != true && LocalPlayer():GetObserverMode() == OBS_MODE_NONE then + if isopened != true then + MainFrame() + end +else + chat.AddText(Color(220,40,0),"[PH:E Taunts] Notice: ",Color(220,220,220), "You can only play custom taunts when you\'re alive as prop/hunter!") +end +end, nil, "Show Prop Hunt taunt list, so you can select and play for self or play as a taunt.") + +local function BindPress(ply, bind, pressed) + if string.find(bind, "+menu_context") and pressed then + RunConsoleCommand("ph_showtaunts") + end +end +hook.Add("PlayerBindPress", "PlayerBindPress_menuContext", BindPress) diff --git a/gamemodes/prop_hunt/gamemode/config/server/sv_devilball_additions.lua b/gamemodes/prop_hunt/gamemode/config/server/sv_devilball_additions.lua new file mode 100644 index 0000000..d75567e --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/config/server/sv_devilball_additions.lua @@ -0,0 +1,23 @@ +-- This is a template of Devil Balls Additions which will adds a new events for Devil balls entity. +-- Note: Key name (the "UniqueName") must be different and cannot be similar with other name's addition. This is purposely used for printVerbose and preventing +-- Duplicated addition and table reading errors. + +-- To add something, Remove "--[[" and "]]" to make them available again. + +--[[ +list.Set("DevilBallsAddition", "UniqueName", function(pl) + + -- give something to the player or modify something to pl.ph_prop. for example: + pl:ChatPrint("Hello! Let me change the prop color and revert in 5 seconds!") + + if IsValid(pl.ph_prop) then + pl.ph_prop:SetMaterials("models/shiny") + pl.ph_prop:SetColor(255,0,0) + + pl.RevertColor = timer.Simple(5, function() + pl.ph_prop:SetMaterials("") + pl.ph_prop:SetColor(255,255,255) + end) + end +end) +]] \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/config/server/sv_luckyball_additions.lua b/gamemodes/prop_hunt/gamemode/config/server/sv_luckyball_additions.lua new file mode 100644 index 0000000..551a931 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/config/server/sv_luckyball_additions.lua @@ -0,0 +1,16 @@ +-- This is a template of Lucky Balls Additions which will adds a new events for luck balls entity. +-- Note: Key name (the "UniqueName") must be different and cannot be similar with other name's addition. This is purposely used for printVerbose and preventing +-- Duplicated addition and table reading errors. + +-- To add something, Remove "--[[" and "]]" to make them available again. + +--[[ +list.Set("LuckyBallsAddition", "UniqueName", function(pl) + + -- give something to the player. for example: Stunstick + + pl:ChatPrint("Hello! Here is your free Stunstick! :D") + pl:Give("weapon_stunstick") + +end) +]] \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/config/server/sv_phkleiner_config.lua b/gamemodes/prop_hunt/gamemode/config/server/sv_phkleiner_config.lua new file mode 100644 index 0000000..fc121a6 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/config/server/sv_phkleiner_config.lua @@ -0,0 +1,50 @@ +-- ph_kleiner Configuration. +-- Add some Invisible Wall to prevent Exploit. Additionaly, Force all player props become Kleiner model after 0.5 seconds of respawn. + +function PH_Create_PlayerClip(min, max) + local pc = ents.Create("brush_playerclip") + + pc.min = min + pc.max = max + pc.pos = pc.max - ((pc.max - pc.min) / 2) + + pc:SetPos(pc.pos) + pc:Spawn() +end + + +local function RemoveClipBrush() + for _,pc in pairs(ents.FindByClass("brush_playerclip")) do + if !IsValid(pc) then return end + printVerbose("[PH_Kleiner_v2.Config] Removing Anti Exploit Brush -> #"..pc:EntIndex()) + pc:Remove() + end +end +hook.Add("PreCleanupMap", "PH_RemoveClip", RemoveClipBrush) + +local function PostCreatePlayerClip() + if game.GetMap() == "ph_kliener_v2" && engine.ActiveGamemode() == "prop_hunt" then + printVerbose("Creating Anti Exploit walls...") + PH_Create_PlayerClip(Vector(1040, -273, 1000), Vector(-1159, -156, 1500)) + PH_Create_PlayerClip(Vector(-1020, 639, -50), Vector(-1306, 669, 850)) + PH_Create_PlayerClip(Vector(-1299, 659, -50), Vector(-1312, -1440, 1510)) + PH_Create_PlayerClip(Vector(-1302, -1434, -371), Vector(1042, -3500, 1500)) + PH_Create_PlayerClip(Vector(1049, -1432, -50), Vector(1058, -217, 1400)) + + -- Force all players become Kleiner on respawn! + timer.Simple(5, function() + for k,v in pairs(ents.FindByClass("ph_prop")) do + v:SetModel("models/player/kleiner.mdl") + v:DrawShadow(false) + end + end) + + -- Disable all shadows + local ShadowControl = ents.Create( "shadow_control" ) + ShadowControl:SetPos( Vector( 0, 0, 0 ) ) + ShadowControl:SetKeyValue( "disableallshadows", "1" ) + ShadowControl:Spawn() + ShadowControl:Activate() + end +end +hook.Add("PostCleanupMap", "PH_AddClipBrush", PostCreatePlayerClip) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/config/sh_init.lua b/gamemodes/prop_hunt/gamemode/config/sh_init.lua new file mode 100644 index 0000000..a55e661 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/config/sh_init.lua @@ -0,0 +1,16 @@ +-- We will initialize the config stuff here + + +-- Shared includes +AddCSLuaFile("sh_phe_additional_taunts.lua") +include("sh_phe_additional_taunts.lua") + + +-- Server includes +if SERVER then + + include("server/sv_phkleiner_config.lua") + include("server/sv_devilball_additions.lua") + include("server/sv_luckyball_additions.lua") + +end diff --git a/gamemodes/prop_hunt/gamemode/config/sh_phe_additional_taunts.lua b/gamemodes/prop_hunt/gamemode/config/sh_phe_additional_taunts.lua new file mode 100644 index 0000000..82518ed --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/config/sh_phe_additional_taunts.lua @@ -0,0 +1,23 @@ +-- In here you can add two team taunts without seperating them. +local taunts = {} + +-- Begin Table: Hunters +taunts.Hunter = { + ["Guuuh!"] = "vo/k_lab/ba_guh.wav", + ["If you See Dr. Breen"] = "vo/streetwar/rubble/ba_tellbreen.wav" + -- Add more Hunters Taunt here... +} +-- Begin Table: Props +taunts.Props = { + ["Windows XP Shutdown"] = "taunts/ph_enhanced/ext_xp_off.wav", + ["Windows XP Startup"] = "taunts/ph_enhanced/ext_xp_start.wav" + -- Add more Props Taunt here... +} + +-- if everything's done with above, let's add them as the list. +-- They will be automatically added as soon as the game loads! +for propTaunt,propPath in pairs(taunts.Props) do list.Set("PHE.CustomPropTaunts", propTaunt, propPath) end +for hunterTaunt,hunterPath in pairs(taunts.Hunter) do list.Set("PHE.CustomHunterTaunts", hunterTaunt, hunterPath) end + + +-- You can also add your custom taunts outside from this scope with your own [ list.Set("PHE.CustomTaunts", "Taunt Name", "Your Taunt Path") ] \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/init.lua b/gamemodes/prop_hunt/gamemode/init.lua new file mode 100644 index 0000000..a63315c --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/init.lua @@ -0,0 +1,791 @@ +-- Ship +resource.AddWorkshop("417565863") + +-- Send required file to clients +AddCSLuaFile("sh_init.lua") +AddCSLuaFile("sh_player.lua") +AddCSLuaFile("cl_tauntwindow.lua") +AddCSLuaFile("cl_init.lua") +AddCSLuaFile("cl_hud_mask.lua") +AddCSLuaFile("cl_hud.lua") +AddCSLuaFile("cl_menu.lua") +AddCSLuaFile("cl_targetid.lua") +AddCSLuaFile("cl_autotaunt.lua") +AddCSLuaFile("cl_credits.lua") + +-- Include the required lua files +include("sv_networkfunctions.lua") +include("sh_init.lua") +include("sh_config.lua") +include("sv_admin.lua") +include("sv_autotaunt.lua") +include("sv_tauntwindow.lua") + +include("sv_bbox_addition.lua") + +-- Server only constants +PHE.EXPLOITABLE_DOORS = { + "func_door", + "prop_door_rotating", + "func_door_rotating" +} + +-- Voice Control Constant init +PHE.VOICE_IS_END_ROUND = 0 + +-- Update cvar to variables changes every so seconds +PHE.UPDATE_CVAR_TO_VARIABLE = 0 + +-- Spectator check +PHE.SPECTATOR_CHECK = 0 + +-- Player Join/Leave message +gameevent.Listen( "player_connect" ) +hook.Add( "player_connect", "AnnouncePLJoin", function( data ) + for k, v in pairs( player.GetAll() ) do + v:PrintMessage( HUD_PRINTTALK, data.name .. " has connected to the server." ) + end +end ) + +gameevent.Listen( "player_disconnect" ) +hook.Add( "player_disconnect", "AnnouncePLLeave", function( data ) + for k,v in pairs( player.GetAll() ) do + v:PrintMessage( HUD_PRINTTALK, data.name .. " has left the server (Reason: " .. data.reason ..")" ) + end +end ) + +-- Force Close taunt window function, determined whenever the round ends, or team winning. +local function ForceCloseTauntWindow(num) + if num == 1 then + net.Start("PH_ForceCloseTauntWindow") + net.Broadcast() + elseif num == 0 then + net.Start("PH_AllowTauntWindow") + net.Broadcast() + end +end + +-- Called alot +function GM:CheckPlayerDeathRoundEnd() + if !GAMEMODE.RoundBased || !GAMEMODE:InRound() then + return + end + + local Teams = GAMEMODE:GetTeamAliveCounts() + + if table.Count(Teams) == 0 then + GAMEMODE:RoundEndWithResult(1001, "Draw, everyone loses!") + PHE.VOICE_IS_END_ROUND = 1 + ForceCloseTauntWindow(1) + + net.Start("PH_RoundDraw_Snd") + net.Broadcast() + + hook.Call("PH_OnRoundDraw", nil) + return + end + + if table.Count(Teams) == 1 then + local TeamID = table.GetFirstKey(Teams) + -- debug + MsgAll("Round Result: "..team.GetName(TeamID).." ("..TeamID..") Wins!\n") + -- End Round + GAMEMODE:RoundEndWithResult(TeamID, team.GetName(TeamID).." win!") + PHE.VOICE_IS_END_ROUND = 1 + ForceCloseTauntWindow(1) + + -- send the win notification + if TeamID == TEAM_HUNTERS then + net.Start("PH_TeamWinning_Snd") + net.WriteString(PHE.WINNINGSOUNDS[TEAM_HUNTERS]) + net.Broadcast() + elseif TeamID == TEAM_PROPS then + net.Start("PH_TeamWinning_Snd") + net.WriteString(PHE.WINNINGSOUNDS[TEAM_PROPS]) + net.Broadcast() + end + + hook.Call("PH_OnRoundWinTeam", nil, TeamID) + return + end + +end + +-- Player Voice & Chat Control to prevent Metagaming. (As requested by some server owners/suggestors.) +-- You can disable this feature by typing 'sv_alltalk 1' in console to make everyone can hear. + +-- Control Player Voice +function GM:PlayerCanHearPlayersVoice(listen, speaker) + + local alltalk_cvar = GetConVar("sv_alltalk"):GetInt() + if (alltalk_cvar > 0) then return true, false end + + -- prevent Loopback check. + if (listen == speaker) then return false, false end + + -- Only alive players can listen other living players. + if listen:Alive() && speaker:Alive() then return true, false end + + -- Event: On Round Start. Living Players don't listen to dead players. + if PHE.VOICE_IS_END_ROUND == 0 && listen:Alive() && !speaker:Alive() then return false, false end + + -- Listen to all dead players while you dead. + if !listen:Alive() && !speaker:Alive() then return true, false end + + -- However, Living players can be heard from dead players. + if !listen:Alive() && speaker:Alive() then return true, false end + + -- Event: On Round End/Time End. Listen to everyone. + if PHE.VOICE_IS_END_ROUND == 1 && listen:Alive() && !speaker:Alive() then return true, false end + + -- Spectator can only read from themselves. + if listen:Team() == TEAM_SPECTATOR && listen:Alive() && speaker:Alive() then return false, false end + + -- This is for ULX "Permanent Gag". Uncomment this if you have some issues. + -- if speaker:GetPData( "permgagged" ) == "true" then return false, false end + + -- does return true, true required here? +end + +-- Control Players Chat +function GM:PlayerCanSeePlayersChat(txt, onteam, listen, speaker) + + if ( onteam ) then + -- Generic Specific OnTeam chats + if ( !IsValid( speaker ) || !IsValid( listen ) ) then return false end + if ( listen:Team() != speaker:Team() ) then return false end + + -- ditto, this is same as below. + if listen:Alive() && speaker:Alive() then return true end + if PHE.VOICE_IS_END_ROUND == 0 && listen:Alive() && !speaker:Alive() then return false end + if !listen:Alive() && !speaker:Alive() then return true end + if !listen:Alive() && speaker:Alive() then return true end + if PHE.VOICE_IS_END_ROUND == 1 && listen:Alive() && !speaker:Alive() then return true end + if listen:Team() == TEAM_SPECTATOR && listen:Alive() && speaker:Alive() then return false end + end + + local alltalk_cvar = GetConVar("sv_alltalk"):GetInt() + if (alltalk_cvar > 0) then return true end + + -- Generic Checks + if ( !IsValid( speaker ) || !IsValid( listen ) ) then return false end + + -- Only alive players can see other living players. + if listen:Alive() && speaker:Alive() then return true end + + -- Event: On Round Start. Living Players don't see dead players' chat. + if PHE.VOICE_IS_END_ROUND == 0 && listen:Alive() && !speaker:Alive() then return false end + + -- See Chat to all dead players while you dead. + if !listen:Alive() && !speaker:Alive() then return true end + + -- However, Living players' chat can be seen from dead players. + if !listen:Alive() && speaker:Alive() then return true end + + -- Event: On Round End/Time End. See Chat to everyone. + if PHE.VOICE_IS_END_ROUND == 1 && listen:Alive() && !speaker:Alive() then return true end + + -- Spectator can only read from themselves. + if listen:Team() == TEAM_SPECTATOR && listen:Alive() && speaker:Alive() then return false end + + return true +end + +-- Called when an entity takes damage +function EntityTakeDamage(ent, dmginfo) + local att = dmginfo:GetAttacker() + + -- Code from: https://facepunch.com/showthread.php?t=1500179 , Special thanks from AlcoholicoDrogadicto(http://steamcommunity.com/profiles/76561198082241865/) for suggesting this. + if GAMEMODE:InRound() && ent && ent:IsPlayer() && ent:Alive() && ent:Team() == TEAM_PROPS && ent.ph_prop then + -- Prevent Prop 'Friendly Fire' + if ( dmginfo:GetAttacker():IsPlayer() && dmginfo:GetAttacker():Team() == ent:Team() ) + then printVerbose("DMGINFO::ATTACKED!!-> "..tostring(dmginfo:GetAttacker())..", DMGTYPE: "..dmginfo:GetDamageType()) + return + end + --Debug purpose. + printVerbose("!! " .. ent:Name() .. "'s PLAYER entity appears to have taken damage, we can redirect it to the prop! (Model is: " .. ent.ph_prop:GetModel() .. ")") + ent.ph_prop:TakeDamageInfo(dmginfo) + return + end + + if GAMEMODE:InRound() && ent && (ent:GetClass() != "ph_prop" && ent:GetClass() != "func_breakable" && ent:GetClass() != "prop_door_rotating" && ent:GetClass() != "prop_dynamic*") && !ent:IsPlayer() && att && att:IsPlayer() && att:Team() == TEAM_HUNTERS && att:Alive() then + if att:Armor() >= 5 && GetConVar("ph_hunter_fire_penalty"):GetInt() >= 5 then + att:SetHealth(att:Health() - (math.Round(GetConVar("ph_hunter_fire_penalty"):GetInt()/2))) + att:SetArmor(att:Armor() - 15) + if att:Armor() < 0 then att:SetArmor(0) end + else + att:SetHealth(att:Health() - GetConVar("ph_hunter_fire_penalty"):GetInt()) + end + if att:Health() <= 0 then + MsgAll(att:Name() .. " felt guilty for hurting so many innocent props and committed suicide\n") + att:Kill() + + hook.Call("PH_HunterDeathPenalty", nil, att) + end + end +end +hook.Add("EntityTakeDamage", "PH_EntityTakeDamage", EntityTakeDamage) + +-- Called when player tries to pickup a weapon +function GM:PlayerCanPickupWeapon(pl, ent) + if pl:Team() != TEAM_HUNTERS then + return false + end + + return true +end + +function PH_ResetCustomTauntWindowState() + -- Force close any taunt menu windows + ForceCloseTauntWindow(0) + -- Extra additional + PHE.VOICE_IS_END_ROUND = 0 + -- Reset Player's Height +end +hook.Add("PostCleanupMap", "PH_ResetCustomTauntWindow", PH_ResetCustomTauntWindowState) + +-- Make a variable for 4 unique combines. +-- Clean up, sorry btw. +local playerModels = { + "combine", + "combineprison", + "combineelite", + "police" + -- you may add more here. +} + +function GM:PlayerSetModel(pl) + + -- player actual model to prevent multi-damage hitbox. + local player_model = "models/props_idbs/phenhanced/box.mdl" + + if GetConVar("ph_use_custom_plmodel"):GetBool() then + -- Use a delivered player model info from cl_playermodel ConVar. + -- This however will use a custom player selection. It'll immediately apply once it is selected. + local mdlinfo = pl:GetInfo("cl_playermodel") + local mdlname = player_manager.TranslatePlayerModel(mdlinfo) + + if pl:Team() == TEAM_HUNTERS then + player_model = mdlname + end + else + -- Otherwise, Use Random one based from a table above. + local customModel = table.Random(playerModels) + local customMdlName = player_manager.TranslatePlayerModel(customModel) + + if pl:Team() == TEAM_HUNTERS then + player_model = customMdlName + end + end + + -- precache and Set the model. + util.PrecacheModel(player_model) + pl:SetModel(player_model) +end + +-- The [E] & Mouse Click 1 behaviour is now moved in here! +function GM:PlayerExchangeProp(pl, ent) + + if !IsValid(pl) then return; end + if !IsValid(ent) then return; end + + if pl:Team() == TEAM_PROPS && pl:IsOnGround() && !pl:Crouching() && table.HasValue(PHE.USABLE_PROP_ENTITIES, ent:GetClass()) && ent:GetModel() then + if table.HasValue(PHE.BANNED_PROP_MODELS, ent:GetModel()) then + pl:ChatPrint("[PH: Enhanced] Notice: That prop has been banned from the server.") + elseif IsValid(ent:GetPhysicsObject()) && (pl.ph_prop:GetModel() != ent:GetModel() || pl.ph_prop:GetSkin() != ent:GetSkin()) then + local ent_health = math.Clamp(ent:GetPhysicsObject():GetVolume() / 250, 1, 200) + local new_health = math.Clamp((pl.ph_prop.health / pl.ph_prop.max_health) * ent_health, 1, 200) + pl.ph_prop.health = new_health + + pl.ph_prop.max_health = ent_health + pl.ph_prop:SetModel(ent:GetModel()) + pl.ph_prop:SetSkin(ent:GetSkin()) + pl.ph_prop:SetSolid(SOLID_VPHYSICS) + pl.ph_prop:SetPos(pl:GetPos() - Vector(0, 0, ent:OBBMins().z)) + pl.ph_prop:SetAngles(pl:GetAngles()) + + pl:SetHealth(new_health) + + if GetConVar("ph_sv_enable_obb_modifier"):GetBool() && ent:GetNWBool("hasCustomHull",false) then + local hmin = ent.m_Hull[1] + local hmax = ent.m_Hull[2] + local dmin = ent.m_dHull[1] + local dmax = ent.m_dHull[2] + + if hmax.z < 24 || dmax.z < 24 then + pl:SetViewOffset(Vector(0,0,24)) + pl:SetViewOffsetDucked(Vector(0,0,24)) + elseif hmax.z > 84 || dmax.z > 84 then --what the heck Duck Size is 84? BigMomma.mdl? + pl:SetViewOffset(Vector(0,0,84)) + pl:SetViewOffsetDucked(Vector(0,0,84)) + else + pl:SetViewOffset(Vector(0,0,hmax.z)) + pl:SetViewOffsetDucked(Vector(0,0,dmax.z)) + end + + pl:SetHull(hmin,hmax) + pl:SetHullDuck(dmin,dmax) + + net.Start("SetHull") + net.WriteInt(math.Round(math.Max(hmax.x,hmax.y)),32) + net.WriteInt(hmax.z,32) + net.WriteInt(dmax.z,32) + net.WriteInt(new_health,9) + net.Send(pl) + else + local hullxymax = math.Round(math.Max(ent:OBBMaxs().x, ent:OBBMaxs().y)) + local hullxymin = hullxymax * -1 + local hullz = math.Round(ent:OBBMaxs().z - ent:OBBMins().z) + + local dhullz = hullz + if hullz > 10 && hullz <= 30 then + dhullz = hullz-(hullz*0.5) + elseif hullz > 30 && hullz <= 40 then + dhullz = hullz-(hullz*0.2) + elseif hullz > 40 && hullz <= 50 then + dhullz = hullz-(hullz*0.1) + else + dhullz = hullz + end + + if hullz < 24 then + pl:SetViewOffset(Vector(0,0,24)) + pl:SetViewOffsetDucked(Vector(0,0,24)) + elseif hullz > 84 then + pl:SetViewOffset(Vector(0,0,84)) + pl:SetViewOffsetDucked(Vector(0,0,84)) + else + pl:SetViewOffset(Vector(0,0,hullz)) + pl:SetViewOffsetDucked(Vector(0,0,dhullz)) + end + + pl:SetHull(Vector(hullxymin, hullxymin, 0), Vector(hullxymax, hullxymax, hullz)) + pl:SetHullDuck(Vector(hullxymin, hullxymin, 0), Vector(hullxymax, hullxymax, dhullz)) + + net.Start("SetHull") + net.WriteInt(hullxymax, 32) + net.WriteInt(hullz, 32) + net.WriteInt(dhullz, 32) + net.WriteInt(new_health, 9) + net.Send(pl) + end + end + + hook.Call("PH_OnChangeProp", nil, pl, ent) + end + +end + +-- Called when a player tries to use an object. By default this pressed ['E'] button. MouseClick 1 will be mentioned below at line @351 +function GM:PlayerUse(pl, ent) + if !pl:Alive() || pl:Team() == TEAM_SPECTATOR || pl:Team() == TEAM_UNASSIGNED then return false; end + + -- Prevent Execution Spam by holding ['E'] button too long. + if pl.UseTime <= CurTime() then + + local hmx, hz = ent:GetPropSize() + if GetConVar("phe_check_props_boundaries"):GetBool() && !pl:CheckHull(hmx, hmx, hz) then + pl:SendLua("chat.AddText(Color(235, 10, 15), \"[PH: Enhanced]\", Color(220, 220, 220), \" There is no room to change that prop!\")") + else + self:PlayerExchangeProp(pl, ent) + end + + pl.UseTime = CurTime() + 1 + + end + + -- Prevent the door exploit + if table.HasValue(PHE.EXPLOITABLE_DOORS, ent:GetClass()) && pl.last_door_time && pl.last_door_time + 1 > CurTime() then + return false + end + + pl.last_door_time = CurTime() + return true +end + +net.Receive("CL2SV_ExchangeProp", function(len, ply) + local Prop = net.ReadEntity() + + ply:PrintMessage(HUD_PRINTCONSOLE, "-=* NOTICE *=-") + ply:PrintMessage(HUD_PRINTCONSOLE, "Hello! We've noticed you tried using the \"CL2SV_ExchangeProp\" net message.") + ply:PrintMessage(HUD_PRINTCONSOLE, "Sad news is that this net message is no longer used (due to exploits). Shame, isn't it?") + ply:PrintMessage(HUD_PRINTCONSOLE, "") + ply:PrintMessage(HUD_PRINTCONSOLE, "This net message will still respond, but you will receive this message instead.") + ply:PrintMessage(HUD_PRINTCONSOLE, "-=* NOTICE *=-") + + --[[ + if ply.UseTime <= CurTime() then + + if !ply:IsHoldingEntity() then + local hmx,hz = Prop:GetPropSize() + if (GetConVar("phe_check_props_boundaries"):GetBool() && !ply:CheckHull(hmx,hmx,hz)) then + ply:SendLua("chat.AddText(Color(235,10,15), \"[PH: Enhanced]\", Color(220,220,220), \" There is no room to change that prop!\")") + else + GAMEMODE:PlayerExchangeProp(ply, Prop) + end + end + + ply.UseTime = CurTime() + 1 + + end + ]] + + -- OBSOLETE : THIS IS COMMENTED OUT BECAUSE THIS METHOD IS SILLY AND SHOULD NOT BE USED. --yeah kind of my fault! >.< +end) + +-- Called when player presses [F3]. Plays a taunt for their team +function GM:ShowSpare1(pl) + if (GetConVar("ph_enable_custom_taunts"):GetInt() == 1) && GAMEMODE:InRound() then + pl:ConCommand("ph_showtaunts") + end + + if ((GetConVar("ph_enable_custom_taunts"):GetInt() == 0) or (GetConVar("ph_enable_custom_taunts"):GetInt() == 2)) && GAMEMODE:InRound() && pl:Alive() && (pl:Team() == TEAM_HUNTERS || pl:Team() == TEAM_PROPS) && pl.last_taunt_time + GetConVar("ph_normal_taunt_delay"):GetInt() <= CurTime() && (table.Count(PHE.PROP_TAUNTS) > 1 && table.Count(PHE.HUNTER_TAUNTS) > 1) then + local curTeamTaunt = { + hunter = PHE:GetAllTeamTaunt(TEAM_HUNTERS), + prop = PHE:GetAllTeamTaunt(TEAM_PROPS) + } + + -- play the taunts based on listed curCustTaunt available. + repeat + if pl:Team() == TEAM_HUNTERS then + rand_taunt = table.Random(curTeamTaunt.hunter) + else + rand_taunt = table.Random(curTeamTaunt.prop) + end + until rand_taunt != pl.last_taunt + + pl.last_taunt_time = CurTime() + GetConVar("ph_normal_taunt_delay"):GetInt() + pl.last_taunt = rand_taunt + + pl:EmitSound(rand_taunt, 100) + pl:SetNWFloat("LastTauntTime", CurTime()) + end +end + +-- Called when a player leaves +function PlayerDisconnected(pl) + pl:RemoveProp() +end +hook.Add("PlayerDisconnected", "PH_PlayerDisconnected", PlayerDisconnected) + +-- Set specific variable for checking in player initial spawn, then use Player:IsHoldingEntity() +hook.Add("PlayerInitialSpawn", "PHE.SetupInitData", function(ply) + ply.LastPickupEnt = NULL + ply.UseTime = 0 +end) +hook.Add("AllowPlayerPickup", "PHE.IsHoldingEntity", function(ply,ent) + ply.LastPickupEnt = ent + ent.LastPickupPly = ply +end) + +-- Spray Controls +hook.Add( "PlayerSpray", "PH.GeneralSprayFunc", function( ply ) + if ( ( !ply:Alive() ) || ( ply:Team() == TEAM_SPECTATOR ) ) then + return true + end +end ) + +-- Called when the players spawns +function PlayerSpawn(pl) + pl:SetNWBool("PlayerLockedRotation", false) + pl:SetNWBool("InFreezeCam", false) + pl:SetNWEntity("PlayerKilledByPlayerEntity", nil) + pl:Blind(false) + pl:RemoveProp() + pl:SetColor(Color(255,255,255,255)) + pl:SetRenderMode(RENDERMODE_TRANSALPHA) + pl:UnLock() + pl:ResetHull() + pl:SetNWFloat("LastTauntTime", CurTime()) + pl.last_taunt_time = 0 + + net.Start("ResetHull") + net.Send(pl) + + net.Start("DisableDynamicLight") + net.Send(pl) + + pl:SetCollisionGroup(COLLISION_GROUP_PASSABLE_DOOR) + pl:CollisionRulesChanged() + + if pl:Team() == TEAM_HUNTERS then + pl:SetJumpPower(160) + elseif pl:Team() == TEAM_PROPS then + pl:SetJumpPower(160 * GetConVar("ph_prop_jumppower"):GetFloat()) + end + + -- Listen server host + if !game.IsDedicated() then + pl:SetNWBool("ListenServerHost", pl:IsListenServerHost()) + end +end +hook.Add("PlayerSpawn", "PH_PlayerSpawn", PlayerSpawn) + + +-- Called when round ends +function RoundEnd() + -- Unblind the hunters + for _, pl in pairs(team.GetPlayers(TEAM_HUNTERS)) do + pl:Blind(false) + pl:UnLock() + end + + -- Stop autotaunting + net.Start("AutoTauntRoundEnd") + net.Broadcast() +end +hook.Add("PH_RoundEnd", "PH.ForceHuntersUnblind", RoundEnd) + + +-- This is called when the round time ends (props win) +function GM:RoundTimerEnd() + if !GAMEMODE:InRound() then + return + end + + GAMEMODE:RoundEndWithResult(TEAM_PROPS, "Props win!") + PHE.VOICE_IS_END_ROUND = 1 + ForceCloseTauntWindow(1) + + net.Start("PH_TeamWinning_Snd") + net.WriteString(PHE.WINNINGSOUNDS[TEAM_PROPS]) + net.Broadcast() + + hook.Call("PH_OnTimerEnd", nil) +end + + +-- Called before start of round +function GM:OnPreRoundStart(num) + game.CleanUpMap() + + if GetGlobalInt("RoundNumber") != 1 && (GetConVar("ph_swap_teams_every_round"):GetInt() == 1 || ((team.GetScore(TEAM_PROPS) + team.GetScore(TEAM_HUNTERS)) > 0)) then + for _, pl in pairs(player.GetAll()) do + if pl:Team() == TEAM_PROPS || pl:Team() == TEAM_HUNTERS then + if pl:Team() == TEAM_PROPS then + pl:SetTeam(TEAM_HUNTERS) + else + pl:SetTeam(TEAM_PROPS) + if GetConVar("ph_notice_prop_rotation"):GetBool() then + timer.Simple(0.5, function() pl:SendLua( [[notification.AddLegacy("You are in Prop Team with Rotate support! You can rotate the prop around by moving your mouse.", NOTIFY_UNDO, 20 )]] ) end) + pl:SendLua( [[notification.AddLegacy("Additionally you can toggle lock rotation by pressing R key!", NOTIFY_GENERIC, 18 )]] ) + pl:SendLua( [[surface.PlaySound("garrysmod/content_downloaded.wav")]] ) + end + end + + pl:ChatPrint("Teams have been swapped!") + end + end + + -- Props will gain a Bonus Armor points Hunter teams has more than 4 players in it. The more player, the more armor they get. + timer.Simple(1, function() + local NumHunter = table.Count(team.GetPlayers(TEAM_HUNTERS)) + if NumHunter >= 4 && NumHunter <= 8 then + for _,prop in pairs(team.GetPlayers(TEAM_PROPS)) do + if IsValid(prop) then prop:SetArmor(math.random(1,3) * 15) end + end + elseif NumHunter > 8 then + for _,prop in pairs(team.GetPlayers(TEAM_PROPS)) do + if IsValid(prop) then prop:SetArmor(math.random(3,7) * 15) end + end + end + end) + + hook.Call("PH_OnPreRoundStart", nil, GetConVar("ph_swap_teams_every_round"):GetInt()) + end + + UTIL_StripAllPlayers() + UTIL_SpawnAllPlayers() + UTIL_FreezeAllPlayers() +end + + +-- Called every server tick. +function GM:Think() + -- Prop spectating is a bit messy so let us clean it up a bit + if PHE.SPECTATOR_CHECK < CurTime() then + for _, pl in pairs(team.GetPlayers(TEAM_PROPS)) do + if IsValid(pl) && !pl:Alive() && pl:GetObserverMode() == OBS_MODE_IN_EYE then + hook.Call("ChangeObserverMode", GAMEMODE, pl, OBS_MODE_ROAMING) + end + end + PHE.SPECTATOR_CHECK = CurTime() + PHE.SPECTATOR_CHECK_ADD + end +end + +-- Bonus Drop :D +function PH_Props_OnBreak(ply, ent) + if GetConVar("ph_enable_lucky_balls"):GetBool() then + local pos = ent:GetPos() + if math.random() < 0.08 then -- 8% Chance of drops. + local dropent = ents.Create("ph_luckyball") + dropent:SetPos(Vector(pos.x, pos.y, pos.z + 32)) -- to make sure the Lucky Ball didn't fall underground. + dropent:SetAngles(Angle(0,0,0)) + dropent:SetColor(Color(math.Round(math.random(0,255)),math.Round(math.random(0,255)),math.Round(math.random(0,255)),255)) + dropent:Spawn() + end + end +end +hook.Add("PropBreak", "Props_OnBreak_WithDrops", PH_Props_OnBreak) + +-- Force Close the Taunt Menu whenever the prop is being killed. +function close_PlayerKilledSilently(ply) + if ply:Team() == TEAM_PROPS then + net.Start( "PH_ForceCloseTauntWindow" ) + net.Send(ply) + end +end +hook.Add("PlayerSilentDeath", "SilentDed_ForceClose", close_PlayerKilledSilently) + +-- Flashlight toggling +function GM:PlayerSwitchFlashlight(pl, on) + if pl:Alive() && pl:Team() == TEAM_HUNTERS then + return true + end + + if pl:Alive() && pl:Team() == TEAM_PROPS then + net.Start("PlayerSwitchDynamicLight") + net.Send(pl) + end + + return false +end + +-- Round Control +cvars.AddChangeCallback("ph_min_waitforplayers", function(cvar, old, new) + if tonumber(new) < 1 then + RunConsoleCommand("ph_min_waitforplayers", "1") + print("[PH:E] Warning: Value must not be 0! Use ph_waitforplayers 0 to disable.") + end +end) + +local bAlreadyStarted = false +function GM:OnRoundEnd( num ) + -- Check if GetConVar("ph_waitforplayers"):GetBool() is true + -- This is a fast implementation for a waiting system + -- Make optimisations if needed + if ( GetConVar("ph_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 ) < GetConVar("ph_min_waitforplayers"):GetInt() ) || ( team.NumPlayers( TEAM_PROPS ) < GetConVar("ph_min_waitforplayers"):GetInt() ) ) then + bAlreadyStarted = false + end + + -- Set to true + if ( ( team.NumPlayers( TEAM_HUNTERS ) >= GetConVar("ph_min_waitforplayers"):GetInt() ) && ( team.NumPlayers( TEAM_PROPS ) >= GetConVar("ph_min_waitforplayers"):GetInt() ) ) then + bAlreadyStarted = true + 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 + end + + hook.Call("PH_OnRoundEnd", nil, num) + +end + +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 GetConVar("ph_waitforplayers"):GetBool() is true + -- This is a fast implementation for a waiting system + -- Make optimisations if needed + if ( GetConVar("ph_waitforplayers"):GetBool() ) then + + -- Pause these timers if there are not enough players on the teams in the server + if ( ( team.NumPlayers( TEAM_HUNTERS ) < GetConVar("ph_min_waitforplayers"):GetInt() ) || ( team.NumPlayers( TEAM_PROPS ) < GetConVar("ph_min_waitforplayers"):GetInt() ) ) 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!" ) + -- Reset the team score + team.SetScore(TEAM_PROPS, 0) + team.SetScore(TEAM_HUNTERS, 0) + end + + end + + end + + -- Send this as a global boolean + SetGlobalBool( "RoundWaitForPlayers", GetConVar("ph_waitforplayers"):GetBool() ) + + hook.Call("PH_RoundStart", nil) + +end +-- End of Round Control Override + +-- Player pressed a key +function PlayerPressedKey(pl, key) + -- Use traces to select a prop + local min,max = pl:GetHull() + if pl && pl:IsValid() && pl:Alive() && pl:Team() == TEAM_PROPS then + plhullz = max.z + + if key == IN_ATTACK then + local trace = {} + if plhullz < 24 then + trace.start = pl:EyePos() + Vector(0, 0, plhullz + (24- plhullz)) + trace.endpos = pl:EyePos() + Vector(0, 0, plhullz + (24 - plhullz)) + pl:EyeAngles():Forward() * 100 + elseif plhullz > 84 then + trace.start = pl:EyePos() + Vector(0, 0, plhullz - 84) + trace.endpos = pl:EyePos() + Vector(0, 0, plhullz - 84) + pl:EyeAngles():Forward() * 300 + else + trace.start = pl:EyePos() + Vector(0, 0, 8) + trace.endpos = pl:EyePos() + Vector(0, 0, 8) + pl:EyeAngles():Forward() * 100 + end + trace.filter = ents.FindByClass("ph_prop") + + local trace2 = util.TraceLine(trace) + if trace2.Entity && trace2.Entity:IsValid() && table.HasValue(PHE.USABLE_PROP_ENTITIES, trace2.Entity:GetClass()) then + if pl.UseTime <= CurTime() then + if !pl:IsHoldingEntity() then + local hmx, hz = trace2.Entity:GetPropSize() + if GetConVar("phe_check_props_boundaries"):GetBool() && !pl:CheckHull(hmx, hmx, hz) then + pl:SendLua("chat.AddText(Color(235, 10, 15), \"[PH: Enhanced]\", Color(220, 220, 220), \" There is no room to change that prop!\")") + else + GAMEMODE:PlayerExchangeProp(pl, trace2.Entity) + end + end + pl.UseTime = CurTime() + 1 + end + end + end + end + + -- Prop rotation lock key + if pl && pl:IsValid() && pl:Alive() && pl:Team() == TEAM_PROPS then + if key == IN_RELOAD then + if pl:GetPlayerLockedRot() then + pl:SetNWBool("PlayerLockedRotation", false) + pl:PrintMessage(HUD_PRINTCENTER, "Prop Rotation Lock: Disabled") + net.Start("PHE.rotateState") + net.WriteInt(0, 2) + net.Send(pl) + else + pl:SetNWBool("PlayerLockedRotation", true) + pl:PrintMessage(HUD_PRINTCENTER, "Prop Rotation Lock: Enabled") + net.Start("PHE.rotateState") + net.WriteInt(1, 2) + net.Send(pl) + end + end + end +end +hook.Add("KeyPress", "PlayerPressedKey", PlayerPressedKey) diff --git a/gamemodes/prop_hunt/gamemode/mapvote/cl_mapvote.lua b/gamemodes/prop_hunt/gamemode/mapvote/cl_mapvote.lua new file mode 100644 index 0000000..b678d11 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/mapvote/cl_mapvote.lua @@ -0,0 +1,329 @@ +surface.CreateFont("RAM_VoteFont", { + font = "Trebuchet MS", + size = 19, + weight = 700, + antialias = true, + shadow = true +}) + +surface.CreateFont("RAM_VoteFontCountdown", { + font = "Tahoma", + size = 32, + weight = 700, + antialias = true, + shadow = true +}) + +surface.CreateFont("RAM_VoteSysButton", +{ font = "Marlett", + size = 13, + weight = 0, + symbol = true, +}) + +MapVote.EndTime = 0 +MapVote.Panel = false + +net.Receive("RAM_MapVoteStart", function() + MapVote.CurrentMaps = {} + MapVote.Allow = true + MapVote.Votes = {} + + local amt = net.ReadUInt(32) + + for i = 1, amt do + local map = net.ReadString() + + MapVote.CurrentMaps[#MapVote.CurrentMaps + 1] = map + end + + MapVote.EndTime = CurTime() + net.ReadUInt(32) + + if(IsValid(MapVote.Panel)) then + MapVote.Panel:Remove() + end + + MapVote.Panel = vgui.Create("VoteScreen") + MapVote.Panel:SetMaps(MapVote.CurrentMaps) +end) + +net.Receive("RAM_MapVoteUpdate", function() + local update_type = net.ReadUInt(3) + + if(update_type == MapVote.UPDATE_VOTE) then + local ply = net.ReadEntity() + + if(IsValid(ply)) then + local map_id = net.ReadUInt(32) + MapVote.Votes[ply:SteamID()] = map_id + + if(IsValid(MapVote.Panel)) then + MapVote.Panel:AddVoter(ply) + end + end + elseif(update_type == MapVote.UPDATE_WIN) then + if(IsValid(MapVote.Panel)) then + MapVote.Panel:Flash(net.ReadUInt(32)) + end + end +end) + +net.Receive("RAM_MapVoteCancel", function() + if IsValid(MapVote.Panel) then + MapVote.Panel:Remove() + end +end) + +net.Receive("RTV_Delay", function() + chat.AddText(Color( 102,255,51 ), "[RTV]", Color( 255,255,255 ), " The vote has been rocked, map vote will begin on round end") +end) + +local PANEL = {} + +function PANEL:Init() + self:ParentToHUD() + + self.Canvas = vgui.Create("Panel", self) + self.Canvas:MakePopup() + self.Canvas:SetKeyboardInputEnabled(false) + + self.countDown = vgui.Create("DLabel", self.Canvas) + self.countDown:SetTextColor(color_white) + self.countDown:SetFont("RAM_VoteFontCountdown") + self.countDown:SetText("") + self.countDown:SetPos(0, 14) + + self.mapList = vgui.Create("DPanelList", self.Canvas) + self.mapList:SetDrawBackground(false) + self.mapList:SetSpacing(4) + self.mapList:SetPadding(4) + self.mapList:EnableHorizontal(true) + self.mapList:EnableVerticalScrollbar() + + self.closeButton = vgui.Create("DButton", self.Canvas) + self.closeButton:SetText("") + + self.closeButton.Paint = function(panel, w, h) + derma.SkinHook("Paint", "WindowCloseButton", panel, w, h) + end + + self.closeButton.DoClick = function() + print("MapVote has started...") + self:SetVisible(false) + end + + self.maximButton = vgui.Create("DButton", self.Canvas) + self.maximButton:SetText("") + self.maximButton:SetDisabled(true) + + self.maximButton.Paint = function(panel, w, h) + derma.SkinHook("Paint", "WindowMaximizeButton", panel, w, h) + end + + self.minimButton = vgui.Create("DButton", self.Canvas) + self.minimButton:SetText("") + self.minimButton:SetDisabled(true) + + self.minimButton.Paint = function(panel, w, h) + derma.SkinHook("Paint", "WindowMinimizeButton", panel, w, h) + end + + self.Voters = {} +end + +function PANEL:PerformLayout() + local cx, cy = chat.GetChatBoxPos() + + self:SetPos(0, 0) + self:SetSize(ScrW(), ScrH()) + + local extra = math.Clamp(300, 0, ScrW() - 640) + self.Canvas:StretchToParent(0, 0, 0, 0) + self.Canvas:SetWide(640 + extra) + // self.Canvas:SetTall(cy -60) + self.Canvas:SetTall(640) + self.Canvas:SetPos(0, 0) + self.Canvas:CenterHorizontal() + self.Canvas:SetZPos(0) + + self.mapList:StretchToParent(0, 90, 0, 0) + + local buttonPos = 640 + extra - 31 * 3 + + self.closeButton:SetPos(buttonPos - 31 * 0, 4) + self.closeButton:SetSize(31, 31) + self.closeButton:SetVisible(true) + + self.maximButton:SetPos(buttonPos - 31 * 1, 4) + self.maximButton:SetSize(31, 31) + self.maximButton:SetVisible(true) + + self.minimButton:SetPos(buttonPos - 31 * 2, 4) + self.minimButton:SetSize(31, 31) + self.minimButton:SetVisible(true) + +end + +local heart_mat = Material("icon16/heart.png") +local star_mat = Material("icon16/star.png") +local shield_mat = Material("icon16/shield.png") + +function PANEL:AddVoter(voter) + for k, v in pairs(self.Voters) do + if(v.Player and v.Player == voter) then + return false + end + end + + + local icon_container = vgui.Create("Panel", self.mapList:GetCanvas()) + local icon = vgui.Create("AvatarImage", icon_container) + icon:SetSize(16, 16) + icon:SetZPos(1000) + icon:SetTooltip(voter:Name()) + icon_container.Player = voter + icon_container:SetTooltip(voter:Name()) + icon:SetPlayer(voter, 16) + + if MapVote.HasExtraVotePower(voter) then + icon_container:SetSize(40, 20) + icon:SetPos(21, 2) + icon_container.img = star_mat + else + icon_container:SetSize(20, 20) + icon:SetPos(2, 2) + end + + icon_container.Paint = function(s, w, h) + draw.RoundedBox(4, 0, 0, w, h, Color(255, 0, 0, 80)) + + if(icon_container.img) then + surface.SetMaterial(icon_container.img) + surface.SetDrawColor(Color(255, 255, 255)) + surface.DrawTexturedRect(2, 2, 16, 16) + end + end + + table.insert(self.Voters, icon_container) +end + +function PANEL:Think() + for k, v in pairs(self.mapList:GetItems()) do + v.NumVotes = 0 + end + + for k, v in pairs(self.Voters) do + if(not IsValid(v.Player)) then + v:Remove() + else + if(not MapVote.Votes[v.Player:SteamID()]) then + v:Remove() + else + local bar = self:GetMapButton(MapVote.Votes[v.Player:SteamID()]) + + if(MapVote.HasExtraVotePower(v.Player)) then + bar.NumVotes = bar.NumVotes + 2 + else + bar.NumVotes = bar.NumVotes + 1 + end + + if(IsValid(bar)) then + local CurrentPos = Vector(v.x, v.y, 0) + local NewPos = Vector((bar.x + bar:GetWide()) - 21 * bar.NumVotes - 2, bar.y + (bar:GetTall() * 0.5 - 10), 0) + + if(not v.CurPos or v.CurPos ~= NewPos) then + v:MoveTo(NewPos.x, NewPos.y, 0.3) + v.CurPos = NewPos + end + end + end + end + + end + + local timeLeft = math.Round(math.Clamp(MapVote.EndTime - CurTime(), 0, math.huge)) + + self.countDown:SetText(tostring(timeLeft or 0).." seconds") + self.countDown:SizeToContents() + self.countDown:CenterHorizontal() +end + +function PANEL:SetMaps(maps) + self.mapList:Clear() + + for k, v in RandomPairs(maps) do + local button = vgui.Create("DButton", self.mapList) + button.ID = k + button:SetText(v) + + button.DoClick = function() + net.Start("RAM_MapVoteUpdate") + net.WriteUInt(MapVote.UPDATE_VOTE, 3) + net.WriteUInt(button.ID, 32) + net.SendToServer() + end + + do + local Paint = button.Paint + button.Paint = function(s, w, h) + local col = Color(255, 255, 255, 10) + + if(button.bgColor) then + col = button.bgColor + end + + draw.RoundedBox(4, 0, 0, w, h, col) + Paint(s, w, h) + end + end + + button:SetTextColor(color_white) + button:SetContentAlignment(4) + button:SetTextInset(8, 0) + button:SetFont("RAM_VoteFont") + + local extra = math.Clamp(300, 0, ScrW() - 640) + + button:SetDrawBackground(false) + button:SetTall(24) + button:SetWide(285 + (extra / 2)) + button.NumVotes = 0 + + self.mapList:AddItem(button) + end +end + +function PANEL:GetMapButton(id) + for k, v in pairs(self.mapList:GetItems()) do + if(v.ID == id) then return v end + end + + return false +end + +function PANEL:Paint() + --Derma_DrawBackgroundBlur(self) + + local CenterY = ScrH() / 2 + local CenterX = ScrW() / 2 + + surface.SetDrawColor(0, 0, 0, 200) + surface.DrawRect(0, 0, ScrW(), ScrH()) +end + +function PANEL:Flash(id) + self:SetVisible(true) + + local bar = self:GetMapButton(id) + + if(IsValid(bar)) then + 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 +end + +derma.DefineControl("VoteScreen", "", PANEL, "DPanel") \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/mapvote/rtv.lua b/gamemodes/prop_hunt/gamemode/mapvote/rtv.lua new file mode 100644 index 0000000..db78bf3 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/mapvote/rtv.lua @@ -0,0 +1,114 @@ +RTV = RTV or {} + +RTV.ChatCommands = { + "!rtv", + "/rtv", + "rtv" +} + +RTV.TotalVotes = 0 + +RTV.Wait = 60 -- The wait time in seconds. This is how long a player has to wait before voting when the map changes. + +RTV._ActualWait = CurTime() + RTV.Wait + +RTV.PlayerCount = MapVote.Config.RTVPlayerCount or 3 + +function RTV.ShouldChange() + return RTV.TotalVotes >= math.Round(#player.GetAll()*0.66) +end + +function RTV.RemoveVote() + RTV.TotalVotes = math.Clamp( RTV.TotalVotes - 1, 0, math.huge ) +end + +function RTV.Start() + PrintMessage( HUD_PRINTTALK, "The vote has been rocked, map vote imminent") + timer.Simple(4, function() + MapVote.Start(nil, nil, nil, nil) + end) +end + + +function RTV.AddVote( ply ) + + if RTV.CanVote( ply ) then + RTV.TotalVotes = RTV.TotalVotes + 1 + ply.RTVoted = true + MsgN( ply:Nick().." has voted to Rock the Vote." ) + PrintMessage( HUD_PRINTTALK, ply:Nick().." has voted to Rock the Vote. ("..RTV.TotalVotes.."/"..math.Round(#player.GetAll()*0.66)..")" ) + + if RTV.ShouldChange() then + RTV.Start() + end + end + +end + +hook.Add( "PlayerDisconnected", "Remove RTV", function( ply ) + + if ply.RTVoted then + RTV.RemoveVote() + end + + timer.Simple( 0.1, function() + if (#player.GetAll() < 1 && !GetConVar("mv_change_when_no_player"):GetBool()) then + print("MapVote: There is no player to force change map...") + else + if RTV.ShouldChange() then + RTV.Start() + end + end + end ) + +end ) + +function RTV.CanVote( ply ) + local plyCount = table.Count(player.GetAll()) + + if RTV._ActualWait >= CurTime() then + return false, "You must wait a bit before voting!" + end + + if GetGlobalBool( "In_Voting" ) then + return false, "There is currently a vote in progress!" + end + + if ply.RTVoted then + return false, "You have already voted to Rock the Vote!" + end + + if RTV.ChangingMaps then + return false, "There has already been a vote, the map is going to change!" + end + if plyCount < RTV.PlayerCount then + return false, "You need more players before you can rock the vote!" + end + + return true + +end + +function RTV.StartVote( ply ) + + local can, err = RTV.CanVote(ply) + + if not can then + ply:PrintMessage( HUD_PRINTTALK, err ) + return + end + + RTV.AddVote( ply ) + +end + +concommand.Add( "rtv_start", RTV.StartVote ) + +hook.Add( "PlayerSay", "RTV Chat Commands", function( ply, text ) + + if table.HasValue( RTV.ChatCommands, string.lower(text) ) then + RTV.StartVote( ply ) + return "" + end + +end ) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/mapvote/sv_mapvote.lua b/gamemodes/prop_hunt/gamemode/mapvote/sv_mapvote.lua new file mode 100644 index 0000000..8ad5372 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/mapvote/sv_mapvote.lua @@ -0,0 +1,257 @@ +util.AddNetworkString("RAM_MapVoteStart") +util.AddNetworkString("RAM_MapVoteUpdate") +util.AddNetworkString("RAM_MapVoteCancel") +util.AddNetworkString("RTV_Delay") + +MapVote.Continued = false + +net.Receive("RAM_MapVoteUpdate", function(len, ply) + if(MapVote.Allow) then + if(IsValid(ply)) then + local update_type = net.ReadUInt(3) + + if(update_type == MapVote.UPDATE_VOTE) then + local map_id = net.ReadUInt(32) + + if(MapVote.CurrentMaps[map_id]) then + MapVote.Votes[ply:SteamID()] = map_id + + net.Start("RAM_MapVoteUpdate") + net.WriteUInt(MapVote.UPDATE_VOTE, 3) + net.WriteEntity(ply) + net.WriteUInt(map_id, 32) + net.Broadcast() + end + end + end + end +end) + +if file.Exists( "mapvote/recentmaps.txt", "DATA" ) then + recentmaps = util.JSONToTable(file.Read("mapvote/recentmaps.txt", "DATA")) +else + recentmaps = {} +end + +if ConVarExists("mv_maplimit") then + printVerbose("[MapVote] Loading ConVars...") + MapVote.Config = { + MapLimit = GetConVar("mv_maplimit"):GetInt(), + TimeLimit = GetConVar("mv_timelimit"):GetInt(), + AllowCurrentMap = GetConVar("mv_allowcurmap"):GetBool(), + EnableCooldown = GetConVar("mv_cooldown"):GetBool(), + MapsBeforeRevote = GetConVar("mv_mapbeforerevote"):GetBool(), + RTVPlayerCount = GetConVar("mv_rtvcount"):GetInt(), + MapPrefixes = string.Explode(",", GetConVar("mv_mapprefix"):GetString():lower()) + } +else + MapVote.Config = {} +end + +local conv = { + ["mv_maplimit"] = function(cvar,old,new) + if new && (new != nil || new != "") then + MapVote.Config.MapLimit = tonumber(new) + end + end, + ["mv_timelimit"] = function(cvar,old,new) + if new && (new != nil || new != "") then + MapVote.Config.TimeLimit = tonumber(new) + end + end, + ["mv_allowcurmap"] = function(cvar,old,new) + if new && (new != nil || new != "") then + MapVote.Config.AllowCurrentMap = tobool(new) + end + end, + ["mv_cooldown"] = function(cvar,old,new) + if new && (new != nil || new != "") then + MapVote.Config.EnableCooldown = tobool(new) + end + end, + ["mv_mapbeforerevote"] = function(cvar,old,new) + if new && (new != nil || new != "") then + MapVote.Config.MapsBeforeRevote = tobool(new) + end + end, + ["mv_rtvcount"] = function(cvar,old,new) + if new && (new != nil || new != "") then + MapVote.Config.RTVPlayerCount = tonumber(new) + end + end, + ["mv_mapprefix"] = function(cvar,old,new) + if new && (new != nil || new != "") then + MapVote.Config.MapPrefixes = string.Explode(",", new:lower()) + end + end +} + +-- Precheck when the convar is changed +for cvar,func in pairs(conv) do + printVerbose("[MapVote] Adding ConVar Callbacks for: "..cvar) + cvars.AddChangeCallback(cvar, func) +end + +function CoolDownDoStuff() + cooldownnum = MapVote.Config.MapsBeforeRevote or 3 + + if table.getn(recentmaps) == cooldownnum then + table.remove(recentmaps) + end + + local curmap = game.GetMap():lower()..".bsp" + + if not table.HasValue(recentmaps, curmap) then + table.insert(recentmaps, 1, curmap) + end + + file.Write("mapvote/recentmaps.txt", util.TableToJSON(recentmaps)) +end + +function MapVote.GetFromULX() + if (ulx == nil) then + print("[!PH: Enhanced] Warning: ULX is not installed!") + return false + end + + if (ulx.votemaps) then + return ulx.votemaps + end +end + +function MapVote.Start(length, current, limit, prefix) + current = current or MapVote.Config.AllowCurrentMap or false + length = length or MapVote.Config.TimeLimit or 28 + limit = limit or MapVote.Config.MapLimit or 24 + cooldown = MapVote.Config.EnableCooldown or true + prefix = prefix or MapVote.Config.MapPrefixes + + local is_expression = false + local ulxmap = MapVote.GetFromULX() + + if not prefix then + local info = file.Read(GAMEMODE.Folder.."/"..GAMEMODE.FolderName..".txt", "GAME") + + if(info) then + local info = util.KeyValuesToTable(info) + prefix = info.maps + else + error("MapVote Prefix can not be loaded from gamemode") + end + + is_expression = true + else + if prefix and type(prefix) ~= "table" then + prefix = {prefix} + end + end + + local maps = {} + + if GetConVar("mv_use_ulx_votemaps"):GetBool() && ulxmap ~= false then + for _,map in pairs(ulxmap) do + table.insert(maps, map..".bsp") + end + else + maps = file.Find("maps/*.bsp", "GAME") + end + + local vote_maps = {} + + local amt = 0 + + for k, map in RandomPairs(maps) do + local mapstr = map:sub(1, -5):lower() + if(not current and game.GetMap():lower()..".bsp" == map) then continue end + if(cooldown and table.HasValue(recentmaps, map)) then continue end + + if is_expression then + if(string.find(map, prefix)) then -- This might work (from gamemode.txt) + vote_maps[#vote_maps + 1] = map:sub(1, -5) + amt = amt + 1 + end + else + for k, v in pairs(prefix) do + if string.find(map, "^"..v) then + vote_maps[#vote_maps + 1] = map:sub(1, -5) + amt = amt + 1 + break + end + end + end + + if(limit and amt >= limit) then break end + end + + net.Start("RAM_MapVoteStart") + net.WriteUInt(#vote_maps, 32) + + for i = 1, #vote_maps do + net.WriteString(vote_maps[i]) + end + + net.WriteUInt(length, 32) + net.Broadcast() + + MapVote.Allow = true + MapVote.CurrentMaps = vote_maps + MapVote.Votes = {} + + timer.Create("RAM_MapVote", length, 1, function() + MapVote.Allow = false + local map_results = {} + + for k, v in pairs(MapVote.Votes) do + if(not map_results[v]) then + map_results[v] = 0 + end + + for k2, v2 in pairs(player.GetAll()) do + if(v2:SteamID() == k) then + if(MapVote.HasExtraVotePower(v2)) then + map_results[v] = map_results[v] + 2 + else + map_results[v] = map_results[v] + 1 + end + end + end + + end + + CoolDownDoStuff() + + local winner = table.GetWinningKey(map_results) or 1 + + net.Start("RAM_MapVoteUpdate") + net.WriteUInt(MapVote.UPDATE_WIN, 3) + + net.WriteUInt(winner, 32) + net.Broadcast() + + local map = MapVote.CurrentMaps[winner] + + + + timer.Simple(4, function() + hook.Run("MapVoteChange", map) + RunConsoleCommand("changelevel", map) + end) + end) +end + +hook.Add( "Shutdown", "RemoveRecentMaps", function() + if file.Exists( "mapvote/recentmaps.txt", "DATA" ) then + file.Delete( "mapvote/recentmaps.txt" ) + end +end ) + +function MapVote.Cancel() + if MapVote.Allow then + MapVote.Allow = false + + net.Start("RAM_MapVoteCancel") + net.Broadcast() + + timer.Destroy("RAM_MapVote") + end +end diff --git a/gamemodes/prop_hunt/gamemode/player_class/class_hunter.lua b/gamemodes/prop_hunt/gamemode/player_class/class_hunter.lua new file mode 100644 index 0000000..37f9068 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/player_class/class_hunter.lua @@ -0,0 +1,106 @@ +-- Create new class +local CLASS = {} + + +-- Some settings for the class +CLASS.DisplayName = "Hunter" +CLASS.WalkSpeed = 230 +CLASS.CrouchedWalkSpeed = 0.4 +CLASS.RunSpeed = 290 +CLASS.DuckSpeed = 0.2 +CLASS.DrawTeamRing = false + + +-- Called by spawn and sets loadout +function CLASS:Loadout(pl) + pl:GiveAmmo(32, "Buckshot") + pl:GiveAmmo(255, "SMG1") + pl:GiveAmmo(12, "357") + + pl:Give("weapon_crowbar") + pl:Give("weapon_shotgun") + pl:Give("weapon_smg1") + pl:Give("item_ar2_grenade") + pl:Give("weapon_357") + + local cl_defaultweapon = pl:GetInfo("cl_defaultweapon") + + if pl:HasWeapon(cl_defaultweapon) then + pl:SelectWeapon(cl_defaultweapon) + end +end + +-- Called when player spawns with this class +function CLASS:OnSpawn(pl) + if !pl:IsValid() then return end + + pl:SetupHands() + pl:SetCustomCollisionCheck(true) + pl:SetAvoidPlayers(false) + pl:CrosshairEnable() + + pl:SetViewOffset(Vector(0,0,64)) + pl:SetViewOffsetDucked(Vector(0,0,28)) + + local unlock_time = math.Clamp(GetConVar("ph_hunter_blindlock_time"):GetInt() - (CurTime() - GetGlobalFloat("RoundStartTime", 0)), 0, GetConVar("ph_hunter_blindlock_time"):GetInt()) + + local unblindfunc = function() + if pl:IsValid() then + pl:Blind(false) + end + end + local lockfunc = function() + if pl:IsValid() then + pl.Lock(pl) + end + end + local unlockfunc = function() + if pl:IsValid() then + pl.UnLock(pl) + end + end + + if unlock_time > 2 then + pl:Blind(true) + + timer.Simple(unlock_time, unblindfunc) + + timer.Simple(2, lockfunc) + timer.Simple(unlock_time, unlockfunc) + end + +end + + +-- Hands +function CLASS:GetHandsModel() + if !GetConVar("ph_use_custom_plmodel"):GetBool() then + return { model = "models/weapons/c_arms_combine.mdl", skin = 1, body = "0100000" } + end +end + + +-- Called when a player dies with this class +function CLASS:OnDeath(pl, attacker, dmginfo) + pl:CreateRagdoll() + pl:UnLock() + + -- Always Reset the ViewOffset + pl:SetViewOffset(Vector(0,0,64)) + pl:SetViewOffsetDucked(Vector(0,0,28)) + + -- Spawn Devil Ball + local pos = pl:GetPos() + if GetConVar("ph_enable_devil_balls"):GetBool() then + if math.random() < 0.7 then --70% chance. + local dropent = ents.Create("ph_devilball") + dropent:SetPos(Vector(pos.x, pos.y, pos.z + 16)) -- to make sure the Devil Ball didn't fall underground. + dropent:SetAngles(Angle(0,0,0)) + dropent:Spawn() + end + end +end + + +-- Register +player_class.Register("Hunter", CLASS) diff --git a/gamemodes/prop_hunt/gamemode/player_class/class_prop.lua b/gamemodes/prop_hunt/gamemode/player_class/class_prop.lua new file mode 100644 index 0000000..ecdf895 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/player_class/class_prop.lua @@ -0,0 +1,93 @@ +-- Create new class +local CLASS = {} + + +-- Some settings for the class +CLASS.DisplayName = "Prop" +CLASS.WalkSpeed = 250 +CLASS.CrouchedWalkSpeed = 0.2 +CLASS.RunSpeed = 275 +CLASS.DuckSpeed = 0.2 +CLASS.DrawTeamRing = false + +-- Prevent 'mod_studio: MOVETYPE_FOLLOW with No Models error.' +CLASS.DrawViewModel = false + + +-- Called by spawn and sets loadout +function CLASS:Loadout(pl) + -- Props don't get anything +end + + +-- Called when player spawns with this class +function CLASS:OnSpawn(pl) + pl:SetColor(Color(0,0,0,0)) + pl:SetCustomCollisionCheck(true) + pl:SetupHands() + pl:SetAvoidPlayers(true) + pl:CrosshairEnable() + + -- Initial Setup during Prop choosing a props. Jump-Duck may still required somehow. + pl:SetViewOffset(Vector(0,0,64)) + pl:SetViewOffsetDucked(Vector(0,0,28)) + + -- Prevent 'mod_studio: MOVETYPE_FOLLOW with No Models error.' + pl:DrawViewModel(false) + + pl.ph_prop = ents.Create("ph_prop") + pl.ph_prop:SetPos(pl:GetPos()) + pl.ph_prop:SetAngles(pl:GetAngles()) + pl.ph_prop:Spawn() + + if GetConVar("ph_use_custom_plmodel_for_prop"):GetBool() then + if table.HasValue(PHE.PROP_PLMODEL_BANS, string.lower(player_manager.TranslatePlayerModel(pl:GetInfo("cl_playermodel")))) then + pl.ph_prop:SetModel("models/player/kleiner.mdl") + pl:ChatPrint("Your custom playermodel was banned from Props.") + elseif table.HasValue(PHE.PROP_PLMODEL_BANS, string.lower(pl:GetInfo("cl_playermodel"))) then + pl.ph_prop:SetModel("models/player/kleiner.mdl") + pl:ChatPrint("Your custom playermodel was banned from Props.") + else + pl.ph_prop:SetModel(player_manager.TranslatePlayerModel(pl:GetInfo("cl_playermodel"))) + end + end + pl.ph_prop:SetSolid(SOLID_BBOX) + pl.ph_prop:SetOwner(pl) + pl:SetNWEntity("PlayerPropEntity", pl.ph_prop) + + -- Delay start the AutoTaunt stuff and Control Tutorial + timer.Simple(1, function() + if IsValid(pl) then + net.Start("AutoTauntSpawn") + net.Send(pl) + + net.Start("PH_ShowTutor") + net.Send(pl) + end + end) + + pl.ph_prop.max_health = 100 +end + + +-- Hands +function CLASS:GetHandsModel() + return +end + + +-- Called when a player dies with this class +function CLASS:OnDeath(pl, attacker, dmginfo) + pl:RemoveProp() + -- reset the Prop Rotating State. + net.Start("PHE.rotateState") + net.WriteInt(0, 2) + net.Send(pl) + + pl:SetViewOffset(Vector(0,0,64)) + pl:SetViewOffsetDucked(Vector(0,0,28)) +end + + +-- Register +player_class.Register("Prop", CLASS) diff --git a/gamemodes/prop_hunt/gamemode/sh_config.lua b/gamemodes/prop_hunt/gamemode/sh_config.lua new file mode 100644 index 0000000..3a9b9fd --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sh_config.lua @@ -0,0 +1,421 @@ +-- Global Var for custom taunt, delivering from taunts/prop -or- hunter_taunts.lua +PHE.PH_TAUNT_CUSTOM = {} +PHE.PH_TAUNT_CUSTOM.PROP = {} +PHE.PH_TAUNT_CUSTOM.HUNTER = {} + +-- Time (in seconds) for spectator check (Default: 0.1) +PHE.SPECTATOR_CHECK_ADD = 0.1 + +PHE.USABLE_PROP_ENTITIES = { + "prop_physics", + "prop_physics_multiplayer" +} + +-- Configure your staff admin/mod or donator rank (vip/donator) to the ignore mute list so they cannot be muted for a reason. +PHE.IgnoreMutedUserGroup = { + -- admin + "superadmin", + "admin", + "Owner", + "Co-owner", + -- Misc users + "Developer", + "Moderator", + "Donator", + "VIP" +} + +-- Admin Staffs table for sv_admin.lua, which enables to modify gamemode settings under F1 > Prop Hunt Menu > Admin menu. +PHE.SVAdmins = { + "admin", + "superadmin", + "owner" +} + +-- Banned Props models +PHE.BANNED_PROP_MODELS = {} + +--[[ // DO NOT MODIFY! use from taunts/prop_taunts.lua or hunter_taunts.lua instead! \\ ]]-- +PHE.HUNTER_TAUNTS = { + ["Come to Papa"] = "taunts/hunters/come_to_papa.wav", + ["I am your Father"] = "taunts/hunters/father.wav", + ["Need Fire Assistance!"] = "taunts/hunters/fireassis.wav", + ["(GlaDOS) President"] = "taunts/hunters/glados-president.wav", + ["I am Hit!"] = "taunts/hunters/hitassist.wav", + ["How Rude"] = "taunts/hunters/how_rude.wav", + ["I will Find You"] = "taunts/hunters/ill_find_you.wav", + ["Radio Laugh"] = "taunts/hunters/laugh.wav", + ["Now What?"] = "taunts/hunters/now_what.wav", + ["You dont have the Soul"] = "taunts/hunters/you_dont_have_the_soul.wav", + ["You dont know the Power"] = "taunts/hunters/you_dont_know_the_power.wav", + ["You are underestimating"] = "taunts/hunters/you_underestimate_the_power.wav", + ["Threat Neutralized"] = "taunts/hunters/threat_neutralized.wav", + ["DX: My Vision is Augmented"] = "taunts/ph_enhanced/dx_augmented.wav", + ["DX: Im gonna Whoop your Ass"] = "taunts/ph_enhanced/dx_imgonnawoopyourass.wav", + ["DX: Dont worry we are cops"] = "taunts/ph_enhanced/dx_dontworrywurcops.wav", + ["DX: Heheh"] = "taunts/ph_enhanced/dx_hehe.wav", + ["Enough of Mambo Jumbo"] = "vo/npc/male01/vanswer13.wav", + ["HACKS"] = "vo/npc/male01/thehacks01.wav", + ["Over Here"] = "vo/npc/male01/overhere01.wav", + ["Over There"] = "vo/npc/male01/overthere01.wav", + ["Over There!!"] = "vo/npc/male01/overthere02.wav" +} + +--[[ // DO NOT MODIFY! use from taunts/props_taunts.lua or hunters_taunts.lua instead! \\ ]]-- +PHE.PROP_TAUNTS = { + ["Run for your Life!"] = "vo/npc/male01/runforyourlife02.wav", + ["Bad Boys"] = "taunts/props/bad_boys.wav", + ["Not the Bees"] = "taunts/props/bees_fix.wav", + ["BillyMays - Are you on the Balls"] = "taunts/props/billymays_areyouontheballs.wav", + ["BillyMays - Get on the Balls"] = "taunts/props/billymays_getontheballs.wav", + ["BillyMays - I Guarantee It"] = "taunts/props/billymays_iguaranteeit.wav", + ["BillyMays - Its so Easy"] = "taunts/props/billymays_itsoeasy.wav", + ["BillyMays - Laundry made Easy"] = "taunts/props/billymays_laundrymadeeasy.wav", + ["BillyMays - New OxyClean"] = "taunts/props/billymays_newoxyclean.wav", + ["BillyMays - No more Detergent"] = "taunts/props/billymays_nomoredetergent.wav", + ["BillyMays - Only $9.99"] = "taunts/props/billymays_only9_99.wav", + ["BillyMays - OxyClean"] = "taunts/props/billymays_oxyclean.wav", + ["BillyMays - So Get on the Balls!"] = "taunts/props/billymays_sogetontheballs.wav", + ["Boom, Headshot!"] = "taunts/props/boom_hs.wav", + ["Car Horn"] = "taunts/props/car_horn.wav", + ["Chicken Hammer"] = "taunts/props/chicken_hammer.wav", + ["DOH"] = "taunts/props/doh.wav", + ["Force Eliminated"] = "taunts/props/forces_eliminated.wav", + ["Go Away or I Shall"] = "taunts/props/go_away_or_i_shall.wav", + ["H A R D B A S S"] = "taunts/props/hardbass.wav", + ["T R I P O L O S K I"] = "taunts/props/tri_poloski1.wav", + ["Poloski Beats"] = "taunts/props/tri_poloski2.wav", + ["Nein Nein Nein"] = "taunts/props/nein.wav", + ["Ill be back"] = "taunts/props/ill_be_back.wav", + ["I am Corn Holio"] = "taunts/props/i_am_cornholio.wav", + ["I Am the one and only"] = "taunts/props/i_am_the_one_and_only.wav", + ["LEROY JENKINS"] = "taunts/props/leroy_jenkins.wav", + ["Oh yeah he will pay"] = "taunts/props/oh_yea_he_will_pay.wav", + ["Muffin Man"] = "taunts/props/ok_i_will_tell_you.wav", + ["ON ME"] = "taunts/props/on_me.wav", + ["Its over 9000"] = "taunts/props/over9000.wav", + ["PINGAS"] = "taunts/props/pingas.wav", + ["Please Come Again"] = "taunts/props/pls_come_again.wav", + ["Pokemon"] = "taunts/props/pokemon.wav", + ["Very Retarded Laugh"] = "taunts/props/retarted_laugh.wav", + ["Shams Wow"] = "taunts/props/sham_wow.wav", + ["This is SPARTA"] = "taunts/props/sparta.wav", + ["WATATATATA"] = "taunts/props/watatata.wav", + ["What is wrong with you"] = "taunts/props/wrong.wav", + ["WROOOONG"] = "taunts/props/wroooong.wav", + ["wololo"] = "taunts/props/wololo.wav", + ["WooHoo"] = "taunts/props/woohoo.wav", + ["DX: Easy Bruh"] = "taunts/ph_enhanced/dx_easy_bruh.wav", + ["DX: Hehe"] = "taunts/ph_enhanced/dx_heh.wav", + ["DX: I dont Move Out"] = "taunts/ph_enhanced/dx_idonotmoveout.wav", + ["DX: You Killed my Friend"] = "taunts/ph_enhanced/dx_iloominarty.wav", + ["DX: Leave me alone"] = "taunts/ph_enhanced/dx_leaveme.wav", + ["DX: LOOK AT ME"] = "taunts/ph_enhanced/dx_lookatme.wav", + ["DX: AAAAAAARGGHHHHHH"] = "taunts/ph_enhanced/dx_molepeople.wav", + ["DX: A BOMB"] = "taunts/ph_enhanced/dx_thebomb.wav", + ["DX: THE BOMB JC"] = "taunts/ph_enhanced/dx_thebomb2.wav", + ["DX: What a Shame"] = "taunts/ph_enhanced/dx_whatashame.wav", + ["DX: Whoa #1"] = "taunts/ph_enhanced/dx_whoawhoawhoa_1.wav", + ["DX: Whoa #2"] = "taunts/ph_enhanced/dx_whoawhoawhoa_2.wav", + ["SPAGHET"] = "taunts/ph_enhanced/ext_spaghet.wav", + ["WHO TOUCHA MY SPAGHET"] = "taunts/ph_enhanced/ext_touch_ma_spaghet.wav", + ["Do you know the way"] = "taunts/ph_enhanced/ext_do_you_kno_de_wei.wav", + ["U have ebola to kno the wei"] = "taunts/ph_enhanced/ext_uhaveebolatoknodewei.wav", + ["Angry German Kid"] = "taunts/ph_enhanced/ext_angry_german_kid.wav", + ["Vitas: 7th Elements"] = "taunts/ph_enhanced/ext_blablaahah.wav", + ["I hate you"] = "taunts/ph_enhanced/ext_crackmod_ihateyou.wav", + ["I watch your rear"] = "taunts/ph_enhanced/ext_crackmod_watchyourrear.wav", + ["You damn Ugly"] = "taunts/ph_enhanced/ext_crackmod_youareugly.wav", + ["Dance Music"] = "taunts/ph_enhanced/ext_dance_music.wav", + ["MLG: GET NO SCOPE"] = "taunts/ph_enhanced/ext_get_no_scope.wav", + ["MLG: GET THE CAMERA"] = "taunts/ph_enhanced/ext_getcamera.wav", + ["MLG: OH ITS TRIPLE"] = "taunts/ph_enhanced/ext_mlg_triple.wav", + ["Bicycle Bell"] = "taunts/ph_enhanced/ext_bicycle_bell.wav", + ["Ding"] = "taunts/ph_enhanced/ext_cling.wav", + ["AND III ALWAYS LOVE YOU"] = "taunts/ph_enhanced/ext_and_iiiiiiiiiiiiiiiiiiii.wav", + ["The Rude of Storming Sand"] = "taunts/ph_enhanced/ext_darude.wav", + ["deaugh"] = "taunts/ph_enhanced/ext_deaugh.wav", + ["CDI Die"] = "taunts/ph_enhanced/ext_die.wav", + ["CDI Oah"] = "taunts/ph_enhanced/ext_oah.wav", + ["Heres some cash goys"] = "taunts/ph_enhanced/ext_dosh1.wav", + ["Loadsam money"] = "taunts/ph_enhanced/ext_dosh2.wav", + ["Who needed money"] = "taunts/ph_enhanced/ext_dosh3.wav", + ["Money money money"] = "taunts/ph_enhanced/ext_dosh4.wav", + ["Dosh grab it while you can"] = "taunts/ph_enhanced/ext_dosh5.wav", + ["Dun dun duuuun"] = "taunts/ph_enhanced/ext_dundundun.wav", + ["derpy fart"] = "taunts/ph_enhanced/ext_fart1.wav", + ["nice fart"] = "taunts/ph_enhanced/ext_fart2.wav", + ["auffwauffderp"] = "taunts/ph_enhanced/ext_fdsa.wav", + ["Game Over"] = "taunts/ph_enhanced/ext_gameover.wav", + ["Game Over mario"] = "taunts/ph_enhanced/ext_gameover_mario.wav", + ["Get out of Here stalker"] = "taunts/ph_enhanced/ext_getoutofhere_stalker.wav", + ["GET TO THE CHOPPA"] = "taunts/ph_enhanced/ext_get_to_the_choppa.wav", + ["Idiots #1"] = "taunts/ph_enhanced/ext_idiots_1.wav", + ["Idiots #2"] = "taunts/ph_enhanced/ext_idiots_2.wav", + ["This is Illegal"] = "taunts/ph_enhanced/ext_illegal.wav", + ["JASONNN"] = "taunts/ph_enhanced/ext_jason1.wav", + ["JASON!"] = "taunts/ph_enhanced/ext_jason2.wav", + ["JASON"] = "taunts/ph_enhanced/ext_jason3.wav", + ["Jim Carrey REMIX"] = "taunts/ph_enhanced/ext_jim_carrey.wav", + ["AND HIS NAME IS JOHN CENA"] = "taunts/ph_enhanced/ext_johncena.wav", + ["AND HIS NAME IS JOHN CENA REMIX"] = "taunts/ph_enhanced/ext_johncena_remix.wav", + ["no way"] = "taunts/ph_enhanced/ext_nowai.wav", + ["Remove Freeman"] = "taunts/ph_enhanced/ext_remove_kebab.wav", + ["SHUT UP"] = "taunts/ph_enhanced/ext_shutuuuuuuup.wav", + ["JC2: No no no"] = "taunts/ph_enhanced/jc2_nonono.wav", + ["JC2: no way"] = "taunts/ph_enhanced/jc2_nowai.wav", + ["JC2: You Son of a Bee"] = "taunts/ph_enhanced/jc2_usonova_bee.wav", + ["Shia Labeouf: JUST DO IT"] = "taunts/ph_enhanced/just_doit1.wav", + ["Shia Labeouf: DO IT"] = "taunts/ph_enhanced/just_doit2.wav", + ["Hula Dance"] = "taunts/ph_enhanced/ext_huladance.wav", + ["X Files"] = "taunts/ph_enhanced/ext_illuminaty.wav", + ["Lovely hehe"] = "taunts/ph_enhanced/ext_lovely_hehe_mp4.wav", + ["Yeah Boy"] = "taunts/ph_enhanced/ext_yeahboy_mp4.wav", + ["MY LEG"] = "taunts/ph_enhanced/ext_my_leg.wav", + ["JOHN FREEMANS WEPON"] = "taunts/ph_enhanced/ext_wepon.wav", + ["OOOOOOOOH"] = "taunts/ph_enhanced/ext_woo.wav", + ["Uuf"] = "taunts/ph_enhanced/ext_oof_minecraft.wav", + ["Oof"] = "taunts/ph_enhanced/ext_oof_roblox.wav", + ["Cloaker"] = "taunts/ph_enhanced/ext_pd2_cloaker.wav", + ["WOOOOH"] = "taunts/ph_enhanced/ext_pyrocynical_woo.wav" +} + +-- Custom Player Model bans for props +PHE.PROP_PLMODEL_BANS = { + "models/player.mdl" +} + +PHE.WINNINGSOUNDS = { + [1] = "misc/ph_hunterwin.mp3", -- hunter + [2] = "misc/ph_propwin.mp3", -- props + ["Draw"] = {"misc/ph_rounddraw_1.mp3", "misc/ph_rounddraw_2.mp3"} +} + +local function AddDemTaunt() + + printVerbose("[PH:E Taunts] Initializing Custom Taunts...") + for propName,propTaunt in pairs(list.Get("PHE.CustomPropTaunts")) do + printVerbose("[PH:E Taunts] Adding Custom PROP taunts -> "..propName) + PHE.PH_TAUNT_CUSTOM.PROP[propName] = propTaunt + if (SERVER) then + resource.AddSingleFile("sound/"..propTaunt) + end + end + for huntName,huntTaunt in pairs(list.Get("PHE.CustomHunterTaunts")) do + printVerbose("[PH:E Taunts] Adding Custom HUNTER taunts -> "..huntName) + PHE.PH_TAUNT_CUSTOM.HUNTER[huntName] = huntTaunt + if (SERVER) then + resource.AddSingleFile("sound/"..huntTaunt) + end + end + +end +hook.Add("Initialize", "PHE.AddTauntTables", AddDemTaunt) + +-- External Use only, such as Taunt Collection and stuff. +-- MAKE SURE TO CALL 'PHE:RefreshTauntList()' AFTER ADDING YOUR CUSTOM TAUNTS! +function PHE:AddCustomTaunt(idTeam,strName,strTaunt) + if idTeam == TEAM_PROPS then + PHE.PH_TAUNT_CUSTOM.PROP[strName] = strTaunt + end + if idTeam == TEAM_HUNTERS then + PHE.PH_TAUNT_CUSTOM.HUNTER[strName] = strTaunt + end +end + +-- External Use only, such as Taunt Collection or other. +-- MAKE SURE TO CALL 'PHE:RefreshTauntList()' AFTER REMOVING THE SPECIFIED TAUNTS! +function PHE:RemoveCustomTauntByPath(idTeam,strTaunt) + if idTeam == TEAM_PROPS then + if table.HasValue(PHE.PH_TAUNT_CUSTOM.PROP, strTaunt) then table.RemoveByValue(strTaunt) end + end + if idTeam == TEAM_HUNTERS then + if table.HasValue(PHE.PH_TAUNT_CUSTOM.HUNTER, strTaunt) then table.RemoveByValue(strTaunt) end + end +end + +function PHE:GetAllTeamTaunt(teamid) + if teamid == TEAM_PROPS then + local taunt = table.Copy(PHE.PROP_TAUNTS) + if table.Count(PHE.PH_TAUNT_CUSTOM.PROP) > 0 then + for name,tprop in pairs(PHE.PH_TAUNT_CUSTOM.PROP) do + taunt[name] = tprop + end + end + + return taunt + end + + if teamid == TEAM_HUNTERS then + local taunt = table.Copy(PHE.HUNTER_TAUNTS) + if table.Count(PHE.PH_TAUNT_CUSTOM.HUNTER) > 0 then + for name,thunter in pairs(PHE.PH_TAUNT_CUSTOM.HUNTER) do + taunt[name] = thunter + end + end + + return taunt + end + + return false +end + +function PHE:GetTeamTaunt(teamid,bCustom) + if teamid == TEAM_PROPS then + if bCustom then + if table.Count(PHE.PH_TAUNT_CUSTOM.PROP) > 0 then + return PHE.PH_TAUNT_CUSTOM.PROP + else + return false + end + else + return PHE.PROP_TAUNTS + end + end + + if teamid == TEAM_HUNTERS then + if bCustom then + if table.Count(PHE.PH_TAUNT_CUSTOM.HUNTER) > 0 then + return PHE.PH_TAUNT_CUSTOM.HUNTER + else + return false + end + else + return PHE.HUNTER_TAUNTS + end + end + + return false +end + +function PHE:RefreshTauntList() + local proptaunt = { + normal = table.Copy(PHE.PROP_TAUNTS), + custom = table.Copy(PHE.PH_TAUNT_CUSTOM.PROP) + } + table.Empty(PHE.PROP_TAUNTS) + table.Empty(PHE.PH_TAUNT_CUSTOM.PROP) + + local huntertaunt = { + normal = table.Copy(PHE.HUNTER_TAUNTS), + custom = table.Copy(PHE.PH_TAUNT_CUSTOM.HUNTER) + } + table.Empty(PHE.HUNTER_TAUNTS) + table.Empty(PHE.PH_TAUNT_CUSTOM.HUNTER) + + -- Sort Prop Taunts + for name,taunt in pairs(proptaunt.normal) do + PHE.PROP_TAUNTS[name] = taunt + end + for name,taunt in pairs(proptaunt.custom) do + PHE.PH_TAUNT_CUSTOM.PROP[name] = taunt + end + table.sort(PHE.PROP_TAUNTS) + table.sort(PHE.PH_TAUNT_CUSTOM.PROP) + + -- Sort Hunter Taunts + for name,taunt in pairs(huntertaunt.normal) do + PHE.HUNTER_TAUNTS[name] = taunt + end + for name,taunt in pairs(huntertaunt.custom) do + PHE.PH_TAUNT_CUSTOM.HUNTER[name] = taunt + end + table.sort(PHE.HUNTER_TAUNTS) + table.sort(PHE.PH_TAUNT_CUSTOM.HUNTER) +end + +hook.Add("InitPostEntity","PHE.RefreshTaunts",function() + PHE:RefreshTauntList() +end) + +concommand.Add("phe_refresh_taunt_list", function() PHE:RefreshTauntList() end, nil, "(EXPERIMENTAL) Force Refresh the Taunt List. This may cause some taunts are missing. Restart map is Required!") + +-- Add the custom player model bans for props AND prop banned models +if SERVER then + if ( !file.Exists( "phe_config", "DATA" ) ) then + printVerbose("[PH: Enhanced] Warning: ./data/phe_config/ does not exist. Creating New One...") + file.CreateDir( "phe_config" ) + end + + local function AddBadPLModels() + + local dir = "phe_config/prop_plymodel_bans" + + -- Create base config area + if ( !file.Exists( dir, "DATA" ) ) then + file.CreateDir( dir ) + end + + -- Create actual config + if ( !file.Exists( dir.."/bans.txt", "DATA" ) ) then + file.Write( dir.."/bans.txt", util.TableToJSON({"models/player.mdl"}, true) ) + end + + if ( file.Exists( dir.."/bans.txt", "DATA" ) ) then + + local PROP_PLMODEL_BANS_READ = util.JSONToTable( file.Read( dir.."/bans.txt", "DATA" ) ) + + -- empty the table instead + table.Empty(PHE.PROP_PLMODEL_BANS) + + for _, v in pairs(PROP_PLMODEL_BANS_READ) do + printVerbose("[PH:E PlayerModels] Adding custom prop player model ban --> "..string.lower(v)) + table.insert(PHE.PROP_PLMODEL_BANS, string.lower(v)) + end + else + + printVerbose("[PH: Enhanced] Cannot read "..dir.."/bans.txt: Error - did not exist. Did you just delete it or what?") + + end + + end + hook.Add("Initialize", "PHE.AddBadPlayerModels", AddBadPLModels) + + local function AddBannedPropModels() + local dir = "phe_config/prop_model_bans" + + local mdlpermabans = { + "models/props/cs_assault/dollar.mdl", + "models/props/cs_assault/money.mdl", + "models/props/cs_office/snowman_arm.mdl", + "models/props/cs_office/computer_mouse.mdl", + "models/props/cs_office/projector_remote.mdl", + "models/foodnhouseholditems/egg.mdl", + "models/props/cs_militia/reload_bullet_tray.mdl" + } + + if ( !file.Exists(dir, "DATA") ) then + file.CreateDir(dir) + end + + if ( !file.Exists(dir.."/model_bans.txt","DATA") ) then + file.Write( dir.."/model_bans.txt", util.TableToJSON( mdlpermabans, true )) + end + + if ( file.Exists ( dir.."/model_bans.txt","DATA" ) ) then + local PROP_MODEL_BANS_READ = util.JSONToTable(file.Read(dir.."/model_bans.txt")) + -- empty the tables anyway. + table.Empty(PHE.BANNED_PROP_MODELS) + for _,v in pairs(PROP_MODEL_BANS_READ) do + printVerbose("[PH:E Model Bans] Adding entry of restricted model to be used --> "..string.lower(v)) + table.insert(PHE.BANNED_PROP_MODELS, string.lower(v)) + end + else + printVerbose("[PH: Enhanced] Cannot read "..dir.."/model_bans.txt: Error - did not exist. Did you just delete it or what?") + end + end + hook.Add("Initialize", "PHE.AddBannedPropModels", AddBannedPropModels) + + -- Add ConCommands. + concommand.Add("phe_refresh_plmodel_ban", AddBadPLModels, nil, "Refresh Server Playermodel Ban Lists, read from prop_plymodel_bans/bans.txt data.", FCVAR_SERVER_CAN_EXECUTE) + concommand.Add("phe_refresh_propmodel_ban", AddBannedPropModels, nil, "Refresh Server Prop Models Ban Lists, read from prop_model_bans/model_bans.txt data.", FCVAR_SERVER_CAN_EXECUTE) +end + +-- AAAAAAARGGHHHHHH +function PHE:AAAAAAARGGHHHHHH() + print("oh no, it\'s the AAAAAAARGGHHHHHH AAAHHHHHHHHHHHHHHHH!") + if CLIENT then + surface.PlaySound(PHE.PROP_TAUNTS["DX: AAAAAAARGGHHHHHH"]) + end +end +concommand.Add("aaaaaaargghhhhhh", function() PHE:AAAAAAARGGHHHHHH() end, nil, "The classic AAAAAAARGGHHHHHH from Deus Ex.",0x10) diff --git a/gamemodes/prop_hunt/gamemode/sh_convars.lua b/gamemodes/prop_hunt/gamemode/sh_convars.lua new file mode 100644 index 0000000..4227eec --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sh_convars.lua @@ -0,0 +1,73 @@ +-- PROP HUNT: ENHANCED CONVARS +-- Playermodels controls convars +local mdlprop = CreateConVar("ph_use_custom_plmodel_for_prop", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should use a custom Player's Model for Props when the round begins?") +local mdlenable = CreateConVar("ph_use_custom_plmodel", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should use a custom player model available for Hunters?\nPlease note that you must have to activate \'ph_use_custom_plmodel_for_prop\' too!") +-- Tutorial for ph_use_playermodeltype can be found under FAQ. +local mdltype = CreateConVar("ph_use_playermodeltype", "0", {FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Which model list that should deliver from? 0 = All Playermodels availale, 1 = Use Legacy method: list.Get('PlayerOptionsModel') (Recommended if you want to custom your model list)") + +-- Enhanced Prop Hunt specify convars +local cmcoll = CreateConVar("ph_prop_camera_collisions", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Attempts to stop props from viewing inside walls.") +local fcam = CreateConVar("ph_freezecam", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Freeze Camera.") +local propcoll = CreateConVar("ph_prop_collision", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should Team Props collide with each other?") + +-- Custom Taunts ConVars +local ct_delay = CreateConVar("ph_customtaunts_delay", "6", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "How many in seconds delay for props to play custom taunt again? (Default is 6)") +local ct_enable = CreateConVar("ph_enable_custom_taunts", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Enable custom taunts for prop teams by pressing C? (Default 0)\n You must have a list of custom taunts to enable this.") +local nt_delay = CreateConVar("ph_normal_taunt_delay", "2", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "How many in seconds delay for props to play normal [F3] taunt again? (Default is 2)") + +-- The Prop Jump Multiplier (count by float) +local pjumpx = CreateConVar("ph_prop_jumppower", "1.4", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Multipliers for Prop Jump Power (Do not confused with Prop's Gravity!). Default is 1.4. Min. 1.") + +-- The 'Prop Rotation' Notification +local rotation_notify = CreateConVar("ph_notice_prop_rotation", "1", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Enable Prop Rotation notification on every time Prop Spawns.") + +-- Freezecam Sound Overrides & Cue Path checks (make sure they don't use '\' but instead '/') +local fc_sound = CreateConVar("ph_fc_use_single_sound", "0", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Use single Freezecam sound instead of sound list?") +local fc_cue = CreateConVar("ph_fc_cue_path", "misc/freeze_cam.wav", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Path for single Freezecam sound.") +if SERVER then + cvars.AddChangeCallback("ph_fc_cue_path", function(cvar,old,new) PHE.LegalCuePath = string.Replace(new, "\\", "/") end, "fc_path_modify") +end + +-- Lucky Ball ConVars +local lball = CreateConVar("ph_enable_lucky_balls", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_NOTIFY }, "Spawn Lucky balls on breakable props?") +local dball = CreateConVar("ph_enable_devil_balls", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_NOTIFY }, "Spawn Devil balls when hunter dies?") + +-- PlayerID on Team Specific +local plnames = CreateConVar("ph_enable_plnames", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Serverside control for if a clients see client\'s team player names through walls.") + +-- Generic Prop Hunt ConVars +local h_penalty = CreateConVar("ph_hunter_fire_penalty", "5", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Health points removed from hunters when they shoot.") +local h_killbns = CreateConVar("ph_hunter_kill_bonus", "100", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "How much health to give back to the Hunter after killing a prop.") +local h_swap = CreateConVar("ph_swap_teams_every_round", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should teams swapped on every round?") +local game_time = CreateConVar("ph_game_time", "30", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Maximum Time Left (in minutes) - Default is 30 minutes.") +local blind_time = CreateConVar("ph_hunter_blindlock_time", "30", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "How long hunters are blinded (in seconds)") +local round_time = CreateConVar("ph_round_time", "300", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Time (in seconds) for each rounds.") +local round_map = CreateConVar("ph_rounds_per_map", "10", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Numbers played on a map (Default: 10)") + +-- Round Control +local wait_pl = CreateConVar( "ph_waitforplayers", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should we wait for players for proper round?" ) +local wait_pl_min = CreateConVar( "ph_min_waitforplayers", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Numbers of mininum players that we should wait for round start. Value must not contain less than 1." ) + +-- Verbose mode & Function +local verbose = CreateConVar("ph_print_verbose", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Developer Verbose. Some printed messages will only appear if this is enabled.") +function printVerbose(text) + if GetConVar("ph_print_verbose"):GetBool() && text then + print(tostring(text)) + end +end + +-- Autotaunt delay (in seconds) +local at_delay = CreateConVar("ph_autotaunt_delay", "45", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "The delay for the auto taunt") + +-- Is autotaunt enabled +local at_enable = CreateConVar("ph_autotaunt_enabled", "1",{ FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Should auto taunting be enabled") + +-- Use newer model for Bren MK +local mkbren_new = CreateConVar("ph_mkbren_use_new_mdl", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Use new model for Bren MK II Bonus Weapon (Require Map Restart!!)") + +-- OBB Model Data Modifier, specified on map. +local obb_mod = CreateConVar("ph_sv_enable_obb_modifier", "1",{ FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Developer: Enable OBB Model Data Modifier") +local obb_every = CreateConVar("ph_reload_obb_setting_everyround", "1",{ FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Developer: Reload OBB Model Data Modifier Every round Restarts") + +-- This is for a temporary. +local check_boundaries = CreateConVar("phe_check_props_boundaries", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "[EXPERIMENTAL] This feature is under Work-in-Progress! Enable prop boundaries Check? This will prevent you to stuck with other objects/Wall.") \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/sh_drive_prop.lua b/gamemodes/prop_hunt/gamemode/sh_drive_prop.lua new file mode 100644 index 0000000..f14393f --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sh_drive_prop.lua @@ -0,0 +1,24 @@ +hook.Add("Move", "moveProp", function(ply,move) + if SERVER then + if ply:Alive() && ply:Team() == TEAM_PROPS then + -- Local variables + local ent = ply.ph_prop + -- Set position and angles + if IsValid(ent) && IsValid(ply) && ply:Alive() then + -- Set position + if (ent:GetModel() == "models/player/kleiner.mdl" || ent:GetModel() == player_manager.TranslatePlayerModel(ply:GetInfo("cl_playermodel"))) then + ent:SetPos(move:GetOrigin()) + else + ent:SetPos(move:GetOrigin() - Vector(0, 0, ent:OBBMins().z)) + end + -- Set angles + if !ply:GetPlayerLockedRot() then + local ang = move:GetAngles() + ent:SetAngles(Angle(0,ang.y,0)) + end + end + + end + + end +end) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/sh_httpupdates.lua b/gamemodes/prop_hunt/gamemode/sh_httpupdates.lua new file mode 100644 index 0000000..49a250b --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sh_httpupdates.lua @@ -0,0 +1,105 @@ +PHE.RESULT = false + +local function UPDATE_SET_RESULT(result) + PHE.RESULT = result +end + +local function UPDATE_GET_RESULT() + return PHE.RESULT +end + +local function UPDATE_DO_FETCH() + http.Fetch( + GAMEMODE.UPDATEURL, + function(body,len,head,code) + if tonumber(code) >= 300 then + return false + elseif body == "" then + return false + else + UPDATE_SET_RESULT(body) + return body + end + end, + function(err) print("[!PH: Enhanced Update] Error retreiving update. Reason: "..err) end + ) +end + +function PHE:CheckUpdate(bool) + local result = "" + local httpcode = 0 + + result = UPDATE_DO_FETCH() or UPDATE_GET_RESULT() or PHE.RESULT or false + + if (!result || result == "") then + print("[!PH: Enhanced Update] Unknown Error retreiving update.") + return false,false,false + end + + printVerbose("[*PH: Enhanced Update] Incoming update result data:\n ===\n"..tostring(result).."\n ===\n") + local data = util.JSONToTable(result) + + local ver = tonumber(data.version) + local rev = data.revision + local log = data.notice + + local text + if tonumber(GAMEMODE._VERSION) > ver then + text = "[!PH: Enhanced Update] New version of "..ver.." is available. To update, please procceed to this link: \n --> https://prophunt.wolvindra.net/?go=download \n --> Changelog: "..log + MsgC(Color(0,160,230), text.."\n") + elseif string.lower(GAMEMODE.REVISION) != rev then + text = "[!PH: Enhanced Update] New Revision of "..rev.." is available. To update, please procceed with this revision, visit this link: \n --> https://prophunt.wolvindra.net/?go=download&rev="..rev.." \n --> Changelog: "..log + MsgC(Color(0,160,230), text.."\n") + elseif tonumber(GAMEMODE._VERSION) == ver && string.lower(GAMEMODE.REVISION) == rev then + text = "[*PH: Enhanced Update] Your gamemode is up to date. (Version "..ver.." - Revision "..string.upper(rev)..")" + MsgC(Color(0,200,40), text.."\n") + end + + if bool then + return ver,rev,log + end +end + +local function CheckUpdate() + print("[PH: Enhanced] - Retreiving Update Info... Please Wait!") + UPDATE_DO_FETCH() + + timer.Simple(4, function() + print( "~[ Prop Hunt : Enhanced Update & Info ]~" ) + + local version,rev,changelog = PHE:CheckUpdate(true) + + if (!version || !rev || !changelog) then + MsgC(Color(230,20,20), "[!!] Error Retreiving updates info") + return + end + + MsgC(Color(181,230,30),"[+] Current Version : "..version.."\n") + MsgC(Color(175,245,15),"[+] Current Revision: "..rev.."\n") + MsgC(Color(247,211,13),"[!] See ChangeLog : "..changelog.."\n\n") + end) +end + +concommand.Add("ph_check_update", CheckUpdate ,nil, "Force Check Update Prop Hunt: Enhanced.") + +local cooldown = 86400 +hook.Add("Initialize", "PHE.CheckUpdateInit", function() + + local nextUpdate = cookie.GetNumber("nextUpdate",0) + local time = os.time() + + if time < nextUpdate then + print("[PH: Enhanced] - Update has been checked. Will Re-check the update on "..os.date("%Y/%m/%d - %H:%M:%S",nextUpdate)) + else + print("[PH: Enhanced] - Initialize for Checking Update...") + UPDATE_DO_FETCH() + print("[PH: Enhanced] - Retreiving Update Info...") + cookie.Set("nextUpdate", time + cooldown) + + timer.Simple(5, function() + PHE:CheckUpdate(false) + print("[PH: Enhanced] - Update has been checked. Your next update notice will be displayed on "..os.date("%Y/%m/%d - %H:%M:%S",nextUpdate)) + end) + end + +end) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/sh_init.lua b/gamemodes/prop_hunt/gamemode/sh_init.lua new file mode 100644 index 0000000..e76284e --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sh_init.lua @@ -0,0 +1,129 @@ +-- Initialize the shared variable +PHE = {} +PHE.__index = PHE + +-- Some config stuff +AddCSLuaFile("config/sh_init.lua") +include("config/sh_init.lua") + +AddCSLuaFile("sh_drive_prop.lua") +include("sh_drive_prop.lua") + +-- ULX Mapvote +AddCSLuaFile("ulx/modules/sh/sh_phe_mapvote.lua") +include("ulx/modules/sh/sh_phe_mapvote.lua") + +-- Initialize and Add ConVar Blocks. +AddCSLuaFile("sh_convars.lua") +include("sh_convars.lua") + +-- Include the required lua files +AddCSLuaFile("sh_config.lua") +include("sh_config.lua") +include("sh_player.lua") + +-- Add Sound Precaching Functions +AddCSLuaFile("sh_precache.lua") +include("sh_precache.lua") + +-- Plugins! :D +PHE.PLUGINS = {} +AddCSLuaFile("sh_plugins.lua") +include("sh_plugins.lua") + +-- MapVote +if SERVER then + AddCSLuaFile("sh_mapvote.lua") + AddCSLuaFile("mapvote/cl_mapvote.lua") + + include("sh_mapvote.lua") + include("mapvote/sv_mapvote.lua") + include("mapvote/rtv.lua") +else + include("sh_mapvote.lua") + include("mapvote/cl_mapvote.lua") +end + +-- Updates! +AddCSLuaFile("sh_httpupdates.lua") +include("sh_httpupdates.lua") + +-- Fretta! +DeriveGamemode("fretta") +IncludePlayerClasses() + +-- Information about the gamemode +GM.Name = "Prop Hunt: ENHANCED" +GM.Author = "Wolvindra-Vinzuerio & D4UNKN0WNM4N2010" + +GM._VERSION = "15" +GM.REVISION = "I" +GM.DONATEURL = "https://prophunt.wolvindra.net/go/donate_go.php?gamemodeonly=true" +GM.UPDATEURL = "https://raw.githubusercontent.com/Vinzuerio/ph-enhanced/master/updates/version.json" + +-- Help info +GM.Help = [[An Enhanced Classic Prop Hunt Gamemode. + +To See More Help, Click 'Prop Hunt Menu' for more! + +Version: ]].. GM._VERSION ..[[ Revision: ]].. GM.REVISION ..[[ + +What's New: +- Optimised gamemode and more reliable +- New Prop Hunt Enhanced HUD +- New Hunter 'Armor' Method +- New gamemode settings in PH Menu +- New gamemode Plugins +- New UI for Menu & Taunt Window +- Smoother prop movements +- and many more..!]] + +-- Fretta configuration +GM.GameLength = GetConVarNumber("ph_game_time") +GM.AddFragsToTeamScore = true +GM.CanOnlySpectateOwnTeam = true +GM.ValidSpectatorModes = { OBS_MODE_CHASE, OBS_MODE_IN_EYE, OBS_MODE_ROAMING } +GM.Data = {} +GM.EnableFreezeCam = true +GM.NoAutomaticSpawning = true +GM.NoNonPlayerPlayerDamage = true +GM.NoPlayerPlayerDamage = true +GM.RoundBased = true +GM.RoundLimit = GetConVar("ph_rounds_per_map"):GetInt() +GM.RoundLength = GetConVar("ph_round_time"):GetInt() +GM.RoundPreStartTime = 0 +GM.SuicideString = "was dead or died mysteriously." -- i think this one is pretty obsolete. +GM.TeamBased = true +GM.AutomaticTeamBalance = false +GM.ForceJoinBalancedTeams = true + +-- Called on gamemdoe initialization to create teams +function GM:CreateTeams() + if !GAMEMODE.TeamBased then + return + end + + TEAM_HUNTERS = 1 + team.SetUp(TEAM_HUNTERS, "Hunters", Color(150, 205, 255, 255)) + team.SetSpawnPoint(TEAM_HUNTERS, {"info_player_counterterrorist", "info_player_combine", "info_player_deathmatch", "info_player_axis"}) + team.SetClass(TEAM_HUNTERS, {"Hunter"}) + + TEAM_PROPS = 2 + team.SetUp(TEAM_PROPS, "Props", Color(255, 60, 60, 255)) + team.SetSpawnPoint(TEAM_PROPS, {"info_player_terrorist", "info_player_rebel", "info_player_deathmatch", "info_player_allies"}) + team.SetClass(TEAM_PROPS, {"Prop"}) +end + +-- Check collisions +function CheckPropCollision(entA, entB) + -- Disable prop on prop collisions + if !GetConVar("ph_prop_collision"):GetBool() && (entA && entB && ((entA:IsPlayer() && entA:Team() == TEAM_PROPS && entB:IsValid() && entB:GetClass() == "ph_prop") || (entB:IsPlayer() && entB:Team() == TEAM_PROPS && entA:IsValid() && entA:GetClass() == "ph_prop"))) then + return false + end + + -- Disable hunter on hunter collisions so we can allow bullets through them + if (IsValid(entA) && IsValid(entB) && (entA:IsPlayer() && entA:Team() == TEAM_HUNTERS && entB:IsPlayer() && entB:Team() == TEAM_HUNTERS)) then + return false + end +end +hook.Add("ShouldCollide", "CheckPropCollision", CheckPropCollision) diff --git a/gamemodes/prop_hunt/gamemode/sh_mapvote.lua b/gamemodes/prop_hunt/gamemode/sh_mapvote.lua new file mode 100644 index 0000000..386a9bb --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sh_mapvote.lua @@ -0,0 +1,48 @@ +-- Credits & Original code: https://github.com/tyrantelf/gmod-mapvote +-- This is modified as for ease use of MapVote in Prop Hunt Enhanced, to avoid users having difficulties to edit their mapvote config file instead through ConVars. + +MapVote = {} +MapVote.Config = {} + +--Default Config +MapVoteConfigDefault = { + MapLimit = 24, + TimeLimit = 28, + AllowCurrentMap = false, + EnableCooldown = true, + MapsBeforeRevote = 2, + RTVPlayerCount = 3, + MapPrefixes = {"ph_"} + } +--Default Config + +local convarlist = { + {"mv_maplimit", "24", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "numbers of map that shown on mapvote." }, + {"mv_timelimit", "28", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "time in second for default mapvotes time." }, + {"mv_change_when_no_player", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "change the map after no players in the server?" }, + {"mv_allowcurmap", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "allow current map to be voted (1/0)" }, + {"mv_use_ulx_votemaps", "0", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Use map listing from ULX Mapvote? 1 = use from ULX mapvote list (which you can whitelist them), 0 = use default maps/*.bsp directory listing."}, + {"mv_cooldown", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "enable cooldown for voting a map" }, + {"mv_mapbeforerevote", "2", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "how many times that the map which cooldown can be shown again?" }, + {"mv_rtvcount", "3", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "number of required players to use rtv mapvote." }, + {"mv_mapprefix", "ph_,cs_,de_", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Map Prefixes that will be shown under mapvote. Use the following example:\n \"ph_,cs_,de_\" (Dont forget to use quotation marks!)." } +} + +if !ConVarExists("mv_maplimit") then + printVerbose("[MapVote] ConVars initialized!") + for _,convars in pairs(convarlist) do + CreateConVar(convars[1], convars[2], convars[3], convars[4]) + end +end + +function MapVote.HasExtraVotePower(ply) + return false +end + +MapVote.CurrentMaps = {} +MapVote.Votes = {} + +MapVote.Allow = false + +MapVote.UPDATE_VOTE = 1 +MapVote.UPDATE_WIN = 3 \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/sh_player.lua b/gamemodes/prop_hunt/gamemode/sh_player.lua new file mode 100644 index 0000000..e6ac305 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sh_player.lua @@ -0,0 +1,96 @@ +-- Finds the player Player/Entities table +local Player = FindMetaTable("Player") +local Entity = FindMetaTable("Entity") +if !Player then return end +if !Entity then return end + +-- Checks player hull to make sure it does not even stuck with the world/other objects. +function Entity:GetPropSize() + local hullxymax = math.Round(math.Max(self:OBBMaxs().x-self:OBBMins().x, self:OBBMaxs().y-self:OBBMins().y)) + local hullz = math.Round(self:OBBMaxs().z - self:OBBMins().z) + + return hullxymax,hullz +end + +function Player:CheckHull(hx,hy,hz) + local tr = {} + tr.start = self:GetPos() + tr.endpos = self:GetPos() + tr.filter = {self, self.ph_prop} + tr.maxs = Vector(hx,hy,hz) + tr.mins = Vector(-hx,-hy,0) + + local trx = util.TraceHull(tr) + if trx.Hit then return false end + return true +end + +-- Blinds the player by setting view out into the void +function Player:Blind(bool) + if !self:IsValid() then return end + + if SERVER then + net.Start("SetBlind") + if bool then + net.WriteBool(true) + self:SetNWBool("isBlind", true) + else + net.WriteBool(false) + self:SetNWBool("isBlind", false) + end + net.Send(self) + elseif CLIENT then + blind = bool + end +end + +-- Player has locked prop rotation? +function Player:GetPlayerLockedRot() + return self:GetNWBool("PlayerLockedRotation", false) +end + +-- Player's prop entity +function Player:GetPlayerPropEntity() + return self:GetNWEntity("PlayerPropEntity", nil) +end + +-- Removes the prop given to the player +function Player:RemoveProp() + if CLIENT || !self:IsValid() then return end + + if self.ph_prop && self.ph_prop:IsValid() then + self.ph_prop:Remove() + self.ph_prop = nil + end +end + +-- Returns ping for the scoreboard +function Player:ScoreboardPing() + -- If this is not a dedicated server and player is the host + if self:GetNWBool("ListenServerHost") then + return "SV" + elseif self:IsBot() then + return "BOT" -- otherwise this will act very strange. + end + -- Return normal ping value otherwise + return self:Ping() +end + +if SERVER then + function Player:IsHoldingEntity() + if !self.LastPickupEnt then + return false + end + if !IsValid(self.LastPickupEnt) then + return false + end + + local ent = self.LastPickupEnt + + if ent.LastPickupPly != self then + return false + end + + return self.LastPickupEnt:IsPlayerHolding() + end +end \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/sh_plugins.lua b/gamemodes/prop_hunt/gamemode/sh_plugins.lua new file mode 100644 index 0000000..10114df --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sh_plugins.lua @@ -0,0 +1,102 @@ +function PHE:InitializePlugin() + + for name,plugin in pairs(list.Get("PHE.Plugins")) do + printVerbose("------------------------------------------\n[PHE Plugin] :: Adding Plugin: "..name) + PHE.PLUGINS[name] = plugin + end + + if table.Count(PHE.PLUGINS) > 0 then + for pName,pData in pairs(PHE.PLUGINS) do + printVerbose("[PHE Plugin] Loading Plugin "..pName) + printVerbose("--> Loaded Plugins: "..pData.name.."\n--> Version: "..pData.version.."\n--> Info: "..pData.info.."\n------------------------------------------") + end + end +end +hook.Add("Initialize", "PHE.InitPlugins", function() + PHE:InitializePlugin() +end) + +if CLIENT then + + hook.Add("PH_CustomTabMenu", "PHE.NewPlugins", function(tab, pVgui) + + local main = {} + + main.panel = vgui.Create("DPanel", tab) + main.panel:SetSize(tab:GetWide(),tab:GetTall()) + main.panel:SetBackgroundColor(Color(40,40,40,120)) + + main.scroll = vgui.Create( "DScrollPanel", main.panel ) + main.scroll:Dock(FILL) + + main.grid = vgui.Create("DGrid", main.scroll) + main.grid:SetPos(10,10) + main.grid:SetSize(tab:GetWide()-20,280) + main.grid:SetCols(1) + main.grid:SetColWide(tab:GetWide()-100) + main.grid:SetRowHeight(300) + + if table.Count(PHE.PLUGINS) < 1 then + if LocalPlayer():IsSuperAdmin() then + local lbl = vgui.Create("DLabel",main.panel) + lbl:SetPos(40,60) + lbl:SetText("No Plugins are available. Find more Prop Hunt: Enhanced Exclusive Plugins here!") + lbl:SetFont("Trebuchet24") + lbl:SetTextColor(color_white) + lbl:SizeToContents() + + local but = vgui.Create("DButton",main.panel) + but:SetPos(40,96) + but:SetSize(256,40) + but:SetText("Find PH:E Plugins") + but.DoClick = function() gui.OpenURL("https://project.wolvindra.net/phe/?go=plugins") end + but:SetIcon("icon16/bricks.png") + else + local lbl = vgui.Create("DLabel",main.panel) + lbl:SetPos(40,60) + lbl:SetText("This server has no custom addons/plugins installed.") + lbl:SetFont("Trebuchet24") + lbl:SetTextColor(color_white) + lbl:SizeToContents() + end + else + for plName,Data in pairs(PHE.PLUGINS) do + local section = {} + section.main = vgui.Create("DPanel",main.grid) + section.main:SetSize(main.grid:GetWide()-100,main.grid:GetTall()) + section.main:SetBackgroundColor(Color(20,20,20,150)) + + section.roll = vgui.Create("DScrollPanel",section.main) + section.roll:SetSize(section.main:GetWide(),section.main:GetTall()) + + section.grid = vgui.Create("DGrid",section.roll) + section.grid:SetPos(20,20) + section.grid:SetSize(section.roll:GetWide()-20,section.roll:GetTall()) + section.grid:SetCols(1) + section.grid:SetColWide(800) + section.grid:SetRowHeight(40) + + pVgui("","label","Trebuchet24",section.grid, Data.name.."| v."..Data.version ) + pVgui("","label",false,section.grid, "Description: "..Data.info ) + if (LocalPlayer():IsSuperAdmin() || table.HasValue(PHE.SVAdmins, LocalPlayer():GetUserGroup())) then + if table.Count(Data.settings) > 0 then + pVgui("","label",false,section.grid, "-- Server Settings --" ) + for _,val in pairs(Data.settings) do + pVgui(val[1],val[2],val[3],section.grid,val[4]) + end + end + end + if table.Count(Data.client) > 0 then + pVgui("","label",false,section.grid, "-- Client Settings --" ) + for _,val in pairs(Data.client) do + pVgui(val[1],val[2],val[3],section.grid,val[4]) + end + end + main.grid:AddItem(section.main) + end + end + + tab:AddSheet("Plugins [BETA]", main.panel, "icon16/bricks.png") + + end) +end \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/sh_precache.lua b/gamemodes/prop_hunt/gamemode/sh_precache.lua new file mode 100644 index 0000000..0c8ceff --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sh_precache.lua @@ -0,0 +1,41 @@ +-- Generic Sound Precache function +CreateConVar("ph_precache_phe_core", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Precache Prop Hunt: Enhanced core sounds during player initial spawn.") +CreateConVar("ph_precache_taunts", "0", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Precache Prop Hunt: Enhanced core taunts during player's initial spawn.") + +hook.Add("PlayerInitialSpawn", "PHE.PrecacheSoundCore", function() + -- WARNING: THESE ARE FIXED FOR OPTIMISATION PURPOSE. + -- If you want to modify the gamemode, remove this function as well as the ConVars above. + local path = { + misc = "misc/", + core = "prop_idbs/", + swep = "weapons/mkbren/", + swepb = "weapons/brenmk3/", + + generic = "gamemode/prop_hunt/content/sound/" + } + + local function PrecacheThis(path) + if file.Exists(path, "GAME") then + wav = file.Find(path.."*.wav", "GAME") + mp3 = file.Find(path.."*.mp3", "GAME") + + printVerbose("[PH:E] Precaching Sound Core...") + for _,snd in pairs(wav) do util.PrecacheSound(snd) end + for _,sndm in pairs(mp3) do util.PrecacheSound(sndm) end + end + end + + if GetConVar("ph_precache_phe_core"):GetBool() then + PrecacheThis(path.generic..path.misc) + PrecacheThis(path.generic..path.core) + PrecacheThis(path.generic..path.swep) + PrecacheThis(path.generic..path.swepb) + end + + if GetConVar("ph_precache_taunts"):GetBool() then + timer.Simple(3, function() + for _,ptaunts in pairs(PHE.PROP_TAUNTS) do util.PrecacheSound(ptaunts) end + for _,htaunts in pairs(PHE.HUNTER_TAUNTS) do util.PrecacheSound(htaunts) end + end) + end +end) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/sv_admin.lua b/gamemodes/prop_hunt/gamemode/sv_admin.lua new file mode 100644 index 0000000..4753cf8 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sv_admin.lua @@ -0,0 +1,48 @@ +net.Receive("CheckAdminFirst", function(len, ply) + if ply:IsAdmin() or table.HasValue(PHE.SVAdmins, ply:GetUserGroup()) then + net.Start("CheckAdminResult") + net.Send(ply) + end +end) + +net.Receive("SvCommandReq", function(len, ply) + local cmd = net.ReadString() + local valbool = net.ReadInt(2) + if ply:IsAdmin() or table.HasValue(PHE.SVAdmins, ply:GetUserGroup()) then + RunConsoleCommand(cmd, math.Round(valbool)) + printVerbose("[ADMIN CVAR NOTIFY] Commands: "..cmd.." has been changed (Player: "..ply:Nick().." ("..ply:SteamID()..")") + else + game.KickID(ply:SteamID(), "Illegal command access found by: "..ply:Nick()) + printVerbose("[ADMIN CVAR NOTIFY] An user "..ply:Nick().."(".. ply:SteamID() ..") is attempting to access "..cmd..", kicked!") + end +end) + +net.Receive("SvCommandSliderReq", function(len, ply) + local cmd = net.ReadString() + local bool = net.ReadBool() + local val + if bool then + val = net.ReadFloat() + else + val = net.ReadInt(16) + end + if ply:IsAdmin() or table.HasValue(PHE.SVAdmins, ply:GetUserGroup()) then + RunConsoleCommand(cmd, val) + printVerbose("[ADMIN CVAR SLIDER NOTIFY] Commands: "..cmd.." has been changed (Player: "..ply:Nick().." ("..ply:SteamID()..")") + else + game.KickID(ply:SteamID(), "Illegal command access found by: "..ply:Nick()) + printVerbose("[ADMIN CVAR NOTIFY] An user "..ply:Nick().."(".. ply:SteamID() ..") is attempting to access "..cmd..", kicked!") + end +end) + +net.Receive("SendTauntStateCmd", function(len, ply) + local cmdval = net.ReadString() + + if ply:IsAdmin() or table.HasValue(PHE.SVAdmins, ply:GetUserGroup()) then + RunConsoleCommand("ph_enable_custom_taunts", cmdval) + printVerbose("[ADMIN CVAR TAUNT NOTIFY] Commands: "..cmdval.." has been changed (Player: "..ply:Nick().." ("..ply:SteamID()..")") + else + game.KickID(ply:SteamID(), "Illegal command access found by: "..ply:Nick()) + printVerbose("[ADMIN CVAR NOTIFY] An user "..ply:Nick().."(".. ply:SteamID() ..") is attempting to access "..cmdval..", kicked!") + end +end) diff --git a/gamemodes/prop_hunt/gamemode/sv_autotaunt.lua b/gamemodes/prop_hunt/gamemode/sv_autotaunt.lua new file mode 100644 index 0000000..c6ca90e --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sv_autotaunt.lua @@ -0,0 +1,30 @@ +-- Props will autotaunt at specified intervals (put this crap on the server because the old way was all on the client and that's silly) +local function TauntTimeLeft(ply) + -- Always return 1 when the conditions are not met + if !IsValid(ply) || !ply:Alive() || ply:Team() != TEAM_PROPS then return 1; end + + local lastTauntTime = ply:GetNWFloat("LastTauntTime") + local nextTauntTime = lastTauntTime + GetConVar("ph_autotaunt_delay"):GetInt() + local currentTime = CurTime() + return nextTauntTime - currentTime +end + +local function AutoTauntThink() + + if GetConVar("ph_autotaunt_enabled"):GetBool() then + + local WHOLE_TAUNTS = PHE:GetAllTeamTaunt(TEAM_PROPS) + for _, ply in ipairs(team.GetPlayers(TEAM_PROPS)) do + local timeLeft = TauntTimeLeft(ply) + + if IsValid(ply) && ply:Alive() && ply:Team() == TEAM_PROPS && timeLeft <= 0 then + local rand_taunt = table.Random(WHOLE_TAUNTS) + if !isstring(rand_taunt) then rand_taunt = tostring(rand_taunt); end + ply:EmitSound(rand_taunt, 100) + ply:SetNWFloat("LastTauntTime", CurTime()) + end + end + + end +end +timer.Create("AutoTauntThinkTimer", 1, 0, AutoTauntThink) diff --git a/gamemodes/prop_hunt/gamemode/sv_bbox_addition.lua b/gamemodes/prop_hunt/gamemode/sv_bbox_addition.lua new file mode 100644 index 0000000..597bb37 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sv_bbox_addition.lua @@ -0,0 +1,100 @@ +local CUR_MAP_DATA = {} + +local function LoadOBBConfig() + local map = game.GetMap() + local GetData = "phe-config/obb/"..map..".txt" + + if !file.Exists(GetData, "DATA") then + printVerbose("[PH: Enhanced] No OBB Configuration found for map: "..map) + return false + end + + if file.Exists(GetData, "DATA") then + local data = file.Read(GetData,"DATA") + local ParsedData = util.JSONToTable(data) + + return ParsedData + end +end + +local function DoConfig() + local data = CUR_MAP_DATA + if !data then return end + + --[[ + JSON structure: + [ + [ + "model/path/b.mdl", + { + "min": [0, 0, 0], + "max": [16, 16, 72], + "dmin": [0, 0, 0], + "dmax": [16, 16, 28] + } + ] + ] + + LUA structure: + 1: + 1: "model/path/b.mdl" + 2: + min = {-0,-0,-0} + max = {16,16,72} + dmin = {-0,-0,-0} + dmax = {16,16,28} + ]] + + local function SetEntityData(ent, tab1, tab2) + ent:SetNWBool("hasCustomHull",true) + ent.m_Hull = tab1 + ent.m_dHull = tab2 + end + + for i=1,#data do + local tent = ents.FindByModel(data[i][1]) + local min = Vector(data[i][2]["min"][1],data[i][2]["min"][2],data[i][2]["min"][3]) + local max = Vector(data[i][2]["max"][1],data[i][2]["max"][2],data[i][2]["max"][3]) + local dmin = Vector(data[i][2]["dmin"][1],data[i][2]["dmin"][2],data[i][2]["dmin"][3]) + local dmax = Vector(data[i][2]["dmax"][1],data[i][2]["dmax"][2],data[i][2]["dmax"][3]) + + for _,found in pairs(tent) do + if IsValid(found) then + printVerbose("[PH: Enhanced] OBB MODIFIER: Setting up Vector Value for Entity ["..found:EntIndex().."]["..found:GetModel().."] =\n >Hull-Vector: min "..tostring(min).." max "..tostring(max).."\n >Duck-Hull Vector: dmin "..tostring(dmin).." dmax "..tostring(dmax)) + SetEntityData(found,{min,max},{dmin,dmax}) + end + end + end + +end + +hook.Add("Initialize", "PHE.InitOBBModelData", function() + + if !file.Exists("phe-config/obb","DATA") then + file.CreateDir("phe-config/obb") + end + + timer.Simple(1.5, function() + printVerbose("[PH: Enhanced] Initializing OBB ModelData Config...") + + CUR_MAP_DATA = LoadOBBConfig() + DoConfig() + end) +end) + +hook.Add("PostCleanupMap", "PHE.PostOBBModelData", function() + if GetConVar("ph_reload_obb_setting_everyround"):GetBool() then + printVerbose("[PH: Enhanced] PostCleanup OBB ModelData Config...") + + DoConfig() + end +end) + +concommand.Add("refresh_obb_map_setting", function(ply) + + printVerbose("[PH: Enhanced] Refreshing OBB Model Data Modifier...") + CUR_MAP_DATA = LoadOBBConfig() + + DoConfig() + +end, nil, "Reload PH: Enhanced OBB/Collission Bound Model Data Modifier on this map.", FCVAR_SERVER_CAN_EXECUTE) \ No newline at end of file diff --git a/gamemodes/prop_hunt/gamemode/sv_networkfunctions.lua b/gamemodes/prop_hunt/gamemode/sv_networkfunctions.lua new file mode 100644 index 0000000..882d9e0 --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sv_networkfunctions.lua @@ -0,0 +1,29 @@ +-- initial for props functions +util.AddNetworkString("ResetHull") +util.AddNetworkString("SetBlind") +util.AddNetworkString("SetHull") +util.AddNetworkString("PlayFreezeCamSound") +util.AddNetworkString("PlayerSwitchDynamicLight") +util.AddNetworkString("DisableDynamicLight") +util.AddNetworkString("PH_ShowTutor") + +util.AddNetworkString("CheckAdminFirst") +util.AddNetworkString("CheckAdminResult") +util.AddNetworkString("SvCommandReq") +util.AddNetworkString("SvCommandSliderReq") +util.AddNetworkString("SendTauntStateCmd") + +util.AddNetworkString("CL2SV_PlayThisTaunt") +util.AddNetworkString("CL2SV_ExchangeProp") +util.AddNetworkString("utilWLVShowMessage") + +util.AddNetworkString("ServerUsablePropsToClient") +util.AddNetworkString("PH_ForceCloseTauntWindow") +util.AddNetworkString("PH_AllowTauntWindow") +util.AddNetworkString("PH_RoundDraw_Snd") +util.AddNetworkString("PH_TeamWinning_Snd") +util.AddNetworkString("AutoTauntSpawn") +util.AddNetworkString("AutoTauntRoundEnd") + +-- some stupid checks +util.AddNetworkString("PHE.rotateState") diff --git a/gamemodes/prop_hunt/gamemode/sv_tauntwindow.lua b/gamemodes/prop_hunt/gamemode/sv_tauntwindow.lua new file mode 100644 index 0000000..f06859a --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/sv_tauntwindow.lua @@ -0,0 +1,22 @@ +-- Validity check to prevent some sort of spam +local function IsDelayed(ply) + local lastTauntTime = ply:GetNWFloat("LastTauntTime") + local delayedTauntTime = lastTauntTime + GetConVar("ph_customtaunts_delay"):GetInt() + local currentTime = CurTime() + return delayedTauntTime > currentTime +end + +net.Receive("CL2SV_PlayThisTaunt", function(len, ply) + local snd = net.ReadString() + + if IsValid(ply) && !IsDelayed(ply) then + if file.Exists("sound/"..snd, "GAME") then + ply:EmitSound(snd, 100) + ply:SetNWFloat("LastTauntTime", CurTime()) + else + ply:ChatPrint("[PH: Enhanced] - Warning: That taunt you selected does not exists on server!") + end + else + ply:ChatPrint("[PH: Enhanced] - Please wait in few seconds...!") + end +end) diff --git a/gamemodes/prop_hunt/gamemode/ulx/modules/sh/sh_phe_mapvote.lua b/gamemodes/prop_hunt/gamemode/ulx/modules/sh/sh_phe_mapvote.lua new file mode 100644 index 0000000..9023e4e --- /dev/null +++ b/gamemodes/prop_hunt/gamemode/ulx/modules/sh/sh_phe_mapvote.lua @@ -0,0 +1,32 @@ +local CATEGORY_NAME = "PH:E MapVote" +------------------------------ VoteMap ------------------------------ +function PHE_MapVote( calling_ply, votetime, should_cancel ) + if MapVote != nil then + if not should_cancel then + MapVote.Start(votetime, nil, nil, nil) + ulx.fancyLogAdmin( calling_ply, "#A called a votemap!" ) + else + MapVote.Cancel() + ulx.fancyLogAdmin( calling_ply, "#A canceled the votemap!" ) + end + else + if SERVER then + if game.IsDedicated() then + print("[ULX MapVote] WARNING: You need at least few players to get this work!") + else + print("[ULX MapVote] ERROR: MapVote is Unavailable.") + end + end + end +end + +if !ulx then + print("MapVote Error: ULX is not installed!") +else + local mapvotecmd = ulx.command( CATEGORY_NAME, "map_vote", PHE_MapVote, "!map_vote" ) + mapvotecmd:addParam{ type=ULib.cmds.NumArg, min=15, default=25, hint="time", ULib.cmds.optional, ULib.cmds.round } + mapvotecmd:addParam{ type=ULib.cmds.BoolArg, invisible=true } + mapvotecmd:defaultAccess( ULib.ACCESS_ADMIN ) + mapvotecmd:help( "Invokes the map vote logic" ) + mapvotecmd:setOpposite( "unmap_vote", {_, _, true}, "!unmap_vote" ) +end \ No newline at end of file diff --git a/gamemodes/prop_hunt/icon24.png b/gamemodes/prop_hunt/icon24.png new file mode 100644 index 0000000..5fd4615 Binary files /dev/null and b/gamemodes/prop_hunt/icon24.png differ diff --git a/gamemodes/prop_hunt/logo.png b/gamemodes/prop_hunt/logo.png new file mode 100644 index 0000000..54ea308 Binary files /dev/null and b/gamemodes/prop_hunt/logo.png differ diff --git a/gamemodes/prop_hunt/prop_hunt.txt b/gamemodes/prop_hunt/prop_hunt.txt new file mode 100644 index 0000000..9531a5b --- /dev/null +++ b/gamemodes/prop_hunt/prop_hunt.txt @@ -0,0 +1,207 @@ +"prop_hunt" +{ + "base" "base" + "title" "Prop Hunt" + "maps" "^ph_" + + "fretta_maps" + { + "1" "ph_" + } + "selectable" "1" + + "menusystem" "1" + "workshopid" "417565863" + "settings" + { + 1 + { + "name" "ph_hunter_fire_penalty" + "text" "Hunter Fire Penality" + "help" "Health points removed from hunters when they shoot" + "type" "Numeric" + "default" "5" + } + + 2 + { + "name" "ph_hunter_kill_bonus" + "text" "Hunter Kill Bonus" + "help" "How much health to give back to the Hunter after killing a prop" + "type" "Numeric" + "default" "100" + } + + 3 + { + "name" "ph_swap_teams_every_round" + "text" "Swap Teams Every Round" + "help" "Should teams swapped on every round?" + "type" "CheckBox" + "default" "1" + } + + 4 + { + "name" "ph_game_time" + "text" "Time Left (Mins.)" + "help" "Maxium Time Left (in minutes) - Default is 30 minutes." + "type" "Numeric" + "default" "30" + } + + 5 + { + "name" "ph_hunter_blindlock_time" + "text" "Hunter Blind Time (Sec.)" + "help" "How long hunters are blinded (in seconds)" + "type" "Numeric" + "default" "30" + } + + 6 + { + "name" "ph_round_time" + "text" "Round Time (Sec.)" + "help" "Time (in seconds) for each rounds." + "type" "Numeric" + "default" "300" + } + + 7 + { + "name" "ph_rounds_per_map" + "text" "Rounds per Map (Num.)" + "help" "Numbers played on a map (Default: 10)" + "type" "Numeric" + "default" "10" + } + + 8 + { + "name" "ph_prop_camera_collisions" + "text" "Prop View Collisions" + "help" "Props can/cannot see through walls." + "type" "CheckBox" + "default" "1" + } + + 9 + { + "name" "ph_freezecam" + "text" "Freeze Camera" + "help" "Enable freeze cam features? Available only for Prop that attacked by Hunter." + "type" "CheckBox" + "default" "1" + } + + 10 + { + "name" "ph_prop_collision" + "text" "Team Props Collision" + "help" "Should Team Props collide with each other?" + "type" "CheckBox" + "default" "1" + } + + 11 + { + "name" "ph_use_custom_plmodel" + "text" "Hunters Custom Models" + "help" "Should Team Hunters have Custom models?" + "type" "CheckBox" + "default" "0" + } + + 12 + { + "name" "ph_use_custom_plmodel_for_prop" + "text" "Props Custom Models" + "help" "Should Team Props have Custom models? (Enable for Hunter first!)" + "type" "CheckBox" + "default" "0" + } + + 13 + { + "name" "ph_enable_custom_taunts" + "text" "Custom Taunts" + "help" "Enable custom taunts Window?" + "type" "Numeric" + "default" "2" + } + + 14 + { + "name" "ph_customtaunts_delay" + "text" "Custom Taunts delay" + "help" "How many times Custom Taunt should be able to played again?" + "type" "Numeric" + "default" "6" + } + + 15 + { + "name" "ph_normal_taunt_delay" + "text" "Normal taunts delay" + "help" "How many in seconds delay for props to play normal [F3] taunt again? (Default is 2)" + "type" "Numeric" + "default" "6" + } + + 16 + { + "name" "ph_enable_lucky_balls" + "text" "Enable Lucky Balls" + "help" "If you hate lucky balls, we're sorry. :(" + "type" "CheckBox" + "default" "1" + } + + 17 + { + "name" "ph_enable_plnames" + "text" "Allow Player Names" + "help" "Serverside control for if a clients see client's team player names through walls." + "type" "CheckBox" + "default" "0" + } + + 18 + { + "name" "ph_waitforplayers" + "text" "Wait for Players" + "help" "Should we wait for players for proper round?" + "type" "CheckBox" + "default" "0" + } + + 19 + { + "name" "ph_min_waitforplayers" + "text" "Minimum Players to wait" + "help" "Numbers of mininum players that we should wait for round start. Value must not contain less than 1." + "type" "Numeric" + "default" "1" + } + + 20 + { + "name" "ph_autotaunt_enabled" + "text" "Enable Auto Taunting" + "help" "Should the players be forced to taunt ever X seconds" + "type" "CheckBox" + "default" "1" + } + + 21 + { + "name" "ph_autotaunt_delay" + "text" "Auto Taunt Timer" + "help" "Time before auto taunt is invoked" + "type" "Numeric" + "default" "45" + } + } + +} diff --git a/updates/version.json b/updates/version.json new file mode 100644 index 0000000..7866500 --- /dev/null +++ b/updates/version.json @@ -0,0 +1,5 @@ +{ + "version":15, + "revision":"i", + "notice":"https://steamcommunity.com/sharedfiles/filedetails/changelog/417565863" +} \ No newline at end of file