1 Commits

Author SHA1 Message Date
Michael Fabian 'Xaymar' Dirks 194b2c6553 Update build tools 2017-11-07 16:43:28 +01:00
93 changed files with 2078 additions and 7745 deletions
-7
View File
@@ -1,7 +0,0 @@
*.jpg merge=binary -diff
*.png merge=bianry -diff
*.gif merge=binary -diff
*.tiff merge=bianry -diff
*.tga merge=binary -diff
*.psd merge=binary -diff
*.psb merge=binary -diff
-3
View File
@@ -1,3 +0,0 @@
issuehunt: xaymar
patreon: xaymar
custom: https://www.paypal.me/xaymar
-20
View File
@@ -1,20 +0,0 @@
---
name: Feature request
about: Want a new feature implemented?
---
<!--- Please fill out the following template, which will help other contributors review your Issue. -->
<!--- Make sure youve read the contribution guidelines -->
### Description
<!-- Describe the feature (and behavior) in as much detail as possible (yes, that means write an essay if you have to) -->
<!-- Include images of what you expect from the feature -->
### Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] I have read the contribution guidelines.
- [ ] This feature is necessary and can't be done through other means.
- [ ] This feature does not break existing functionality.
- [ ] I am willing to hire/pay someone to implement this.
-27
View File
@@ -1,27 +0,0 @@
---
name: Question/Feedback
about: Submit a question or some feedback! (Not for bugs, issues or crashes!)
---
<!--- Please fill out the following template, which will help other contributors review your Issue. -->
<!--- Make sure youve read the contribution guidelines -->
### Description
<!-- Describe the feature (and behavior) in as much detail as possible (yes, that means write an essay if you have to) -->
<!-- Include images of what you expect from the feature -->
### System Information
<!-- Include as much information about the system you're using as possible. -->
- Software Version: [e. g. 1.0.0, 1.2.1, ... - NEVER LATEST]
- Operating System: [e. g. Windows, Debian, Ubuntu, RedHat, FreeBSD, ...]
- Kernel Version: [e. g. 1903/1809 (Windows), 4.12 (Linux), ...]
- CPU: [e. g. Intel i7, AMD Zen2, Qualcomm, ...]
- GPU: [e. g. Nvidia RTX 2xxx Series, AMD Radeone 5xxx Series, ...]
- RAM: [e. g. 16GB, 32GB, 64GB, ...]
### Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] I have read the contribution guidelines.
- [ ] This is not a bug, crash or generic issue.
-38
View File
@@ -1,38 +0,0 @@
---
name: Issue/Bug report
about: Encountered a problem, a bug or a crash?
---
<!--- Please fill out the following template, which will help other contributors review your Issue. -->
<!--- Make sure youve read the contribution guidelines -->
### Description
<!-- Describe the bug (and behavior) in as much detail as necessary -->
<!-- Include screenshots and attach (crash) logs if possible -->
### Expected Behavior
<!-- What is the expected behavior in this case? -->
### Reproduction Steps
<!-- Describe the steps required to get this to happen from a cleanly installed obs-studio -->
<!-- Leave out detail that is not relevant to -->
1. Open a portal to the Infinite Void
2. Summon an ancient God
3. Realize your mistake
### System Information
<!-- Include as much information about the system you're using as possible. -->
- Software Version: [e. g. 1.0.0, 1.2.1, ... - NEVER LATEST]
- Operating System: [e. g. Windows, Debian, Ubuntu, RedHat, FreeBSD, ...]
- Kernel Version: [e. g. 1903/1809 (Windows), 4.12 (Linux), ...]
- CPU: [e. g. Intel i7, AMD Zen2, Qualcomm, ...]
- GPU: [e. g. Nvidia RTX 2xxx Series, AMD Radeone 5xxx Series, ...]
- RAM: [e. g. 16GB, 32GB, 64GB, ...]
### Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] I have read the contribution guidelines.
- [ ] I can reproduce the issue with the exact reproduction steps I have provided.
- [ ] The issue appears on all of my systems that can run this software.
-35
View File
@@ -1,35 +0,0 @@
<!--- Please fill out the following template, which will help other contributors review your Pull Request. -->
<!--- Make sure youve read the contribution guidelines -->
### Description
<!--- Describe your changes in detail. -->
<!--- If this change includes UI elements, please include screenshots. -->
### Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open Mantis issue, or implements feature request -->
<!--- from the Ideas page, please link to the issue here. -->
### How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment (hardware, OS version, etc.),-->
<!--- and the tests you ran, including how it may affect other areas of code. -->
### Types of changes
<!--- What types of changes does your PR introduce? Uncomment all that apply -->
<!--- - Bug fix (non-breaking change which fixes an issue) -->
<!--- - New feature (non-breaking change which adds functionality) -->
<!--- - Performance enhancement (non-breaking change which improves efficiency) -->
<!--- - Code cleanup (non-breaking change which makes code smaller or more readable) -->
<!--- - Breaking change (fix or feature that would cause existing functionality to change) -->
<!--- - Documentation (a change to documentation pages) -->
### Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
- [ ] My code has been run through [clang-format](https://github.com/obsproject/obs-studio/blob/master/.clang-format).
- [ ] I have read the [**contributing** document](https://github.com/obsproject/obs-studio/blob/master/CONTRIBUTING.rst).
- [ ] My code is not on the master branch.
- [ ] The code has been tested.
- [ ] All commit messages are properly formatted and commits squashed where appropriate.
+1 -3
View File
@@ -1,3 +1 @@
/media/rendered/*
*.gma
desktop.ini
Pack.gma
+15
View File
@@ -0,0 +1,15 @@
Changelist
-
ToDo:
- Replace all createconvar with getconvar?
- Other game modes
- UI stuff
- Scoreboard
- Custom Collisions for Hiders? Allows to copy the prop geometry/align with rotation
- Spectator: Spectate players(team only), first & third person
- UI: Proper Scoreboard replacement
- UI: Proper Team Selection replacement
- PostMatch: Implement Round Limit & Map Time Limit checking.
- PostMatch: Implement MapVoting? Or add support for MapVote addon?
- Seekers, Hiders: Taunts! And custom Taunts. And everything that belongs to that.
+17 -6
View File
@@ -1,11 +1,22 @@
Copyright 2015-2020 Michael Fabian 'Xaymar' Dirks <info@xaymar.com>
The MIT License (MIT)
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Copyright (c) 2016 Michael Fabian Dirks
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

-58
View File
@@ -1,58 +0,0 @@
# Prop Hunt Extended
Hide n Seek with a twist - Hiders can turn into anything on the map! From bottles, to vending machines and all the way to huge cars - what you become depends on how you want to play. Do you want to blend in with your surroundings, or do you want to make a fool of the Seekers? And how will you deal with finding (and killing) all hiders as a Seeker?
## Features and Improvements
* **Prop Rotation**: Rotate your prop into the correct orientation to fool Seekers even more.
* **Correct Hitboxes**: All hitboxes now compensate for lag, making shots that should have hit actually hit.
* **Better Camera**: First- & Third-Person modes, world collision, proper world origin to support small hiding spaces without making the world disappear.
* **Custom Player Models**: Customize yourself to the best of your abilities.
* **Taunt Packs**: All taunt packs compatible with Tsukasas Taunt Pack Loader will work and load.
* **Name Plates and Selection Halo**: Know who is what, and what you're going to select!
* **Proper Scoreboard**: The gamemode comes with a proper Scoreboard instead of the default one.
* **Better Configuration**: Everything can be configured during gameplay using CVars.
* **Improved Networking Performance**: Only necessary information is shared.
## Compatibility with other Addons
* **[MapVote](https://steamcommunity.com/sharedfiles/filedetails/?id=151583504)**: Full support
* **Tsukasas Taunt Pack Loader**: Compatibility layer included, not compatible due to this.
* **LiteGibs**: Breaks literally everything somehow.
# How To Play
## Seekers
Your primary goal is to find hiders by any means possible. But watch out, you might lose health if you shoot an object that isn't actually a hider! Pick things up before shooting them, or simply remember the layout of the maps you are playing on. And remember: You lose if only a single hider is still alive at the end of the round.
## Hiders
Stay alive as long as possible and make Seekers look like a fool. Dance around their feet, hide in plain sight or be that huge car that nobody though you could become! What you do is entirely up to you.
## Spectators
You get to watch the whole thing go down live! Sit back, grab some popcorn or any other snack and relax.
## Controls
* ShowHelp (Default F1): Show Help and client Settings menu.
* ShowTeam (Default F2): Show Team Selection menu.
* ShowSpare1 (Default F3): Taunt everything and everyone.
* ShowContextMenu (Default C): Toggle between First- and Thirdperson camera.
* ShowSpawnMenu (Default Q): (Hider only) Hold to enable prop rotation, let go to disable prop rotation.
* Prop Hunt SMG Reload (Default R): If ammo is full switches between single and burst fire.
# Other Stuff
## Help and Community
All help is provided through [Discord (preferred, channel #gmod-prop-hunt-extended)](https://discord.gg/tbqhAxr) and [Steam Workshop Discussions](https://steamcommunity.com/sharedfiles/filedetails/discussions/468149739). Please read the [FAQ](https://steamcommunity.com/workshop/filedetails/discussion/468149739/358415206095321277/) as it can often answer your question.
## Spread the Word
It is always appreciated to see the word about this Gamemode being spread, especially to content creators that are still uploading Prop Hunt content. If you want to tag me, my Twitter username is [@Xaymar](https://twitter.com/Xaymar), my Twitch username is [Xaymar](https://twitch.tv/Xaymar), my YouTube custom url is [Xaymar](https://youtube.com/c/Xaymar) and my Patreon is also [Xaymar](https://patreon.com/Xaymar).
## Donations to help the cause
The development of this and other projects is funded through [Patreon](https://www.patreon.com/Xaymar). My dream is to eventually be able to do this full time without requiring a full-time job, perhaps even streaming this to YouTube and Twitch.
## Official Servers
### Central Europe
* Primary: steam://connect/xaymar.com:27015
* Secondary: steam://connect/xaymar.com:27016
## Links
* [Workshop page](https://steamcommunity.com/sharedfiles/filedetails/?id=468149739)
* [Facepunch Thread](https://forum.facepunch.com/f/gmodgames/osvi/Prop-Hunt-Extended/1/)
# License
For the license, see the file `LICENSE`. This file overrides any headers written in files.
-1
View File
@@ -3,6 +3,5 @@
"type" : "gamemode",
"tags" : [ "fun" ],
"ignore" : [
"addon.txt"
]
}
@@ -0,0 +1,8 @@
"TableToKeyValues"
{
"1" "models/props/cs_assault/dollar.mdl"
"2" "models/props/cs_assault/money.mdl"
"3" "models/props/cs_office/snowman_arm.mdl"
"4" "models/props_junk/garbage_plasticbottle001a.mdl"
"5" "models/props/cs_office/projector_remote.mdl"
}
@@ -0,0 +1,8 @@
"TableToKeyValues"
{
"TAUNT_DELAY" "0.1"
"ROUNDS_PER_MAP" "20"
"ROUND_TIME" "240"
"SWAP_TEAM_EVERY_ROUND" "1"
"GAME_TIME" "20"
}
@@ -0,0 +1,26 @@
"TableToKeyValues"
{
"1" "bot/aw_hell.wav"
"2" "bot/aww_man.wav"
"3" "bot/anyone_see_anything.wav"
"4" "bot/anyone_see_them.wav"
"5" "bot/come_out_and_fight_like_a_man.wav"
"6" "bot/come_out_wherever_you_are.wav"
"7" "bot/he_got_away.wav"
"8" "bot/he_got_away2.wav"
"9" "bot/i_dont_know_where_he_went.wav"
"10" "bot/i_got_nothing.wav"
"11" "bot/nothing_happening_over_here.wav"
"12" "bot/nothing_here.wav"
"13" "bot/nothing_moving_over_here.wav"
"14" "bot/thats_not_good.wav"
"15" "bot/theres_too_many.wav"
"16" "bot/theres_too_many_of_them.wav"
"17" "bot/theyre_all_over_the_place2.wav"
"18" "bot/theyre_everywhere2.wav"
"19" "bot/too_many2.wav"
"20" "bot/what_happened.wav"
"21" "bot/what_have_you_done.wav"
"22" "bot/where_are_they.wav"
"23" "bot/where_are_you_hiding.wav"
}
@@ -0,0 +1,20 @@
"TableToKeyValues"
{
"1" "bot/a_bunch_of_them.wav"
"2" "bot/come_out_and_fight_like_a_man.wav"
"3" "bot/come_out_wherever_you_are.wav"
"4" "bot/come_to_papa.wav"
"5" "bot/dont_worry_hell_get_it.wav"
"6" "bot/hang_on_i_heard_something.wav"
"7" "bot/hang_on_im_coming.wav"
"8" "bot/i_dont_think_so.wav"
"9" "bot/i_have_the_hostages.wav"
"10" "bot/i_see_our_target.wav"
"11" "bot/im_waiting_here.wav"
"12" "bot/keeping_an_eye_on_the_hostages.wav"
"13" "bot/nnno_sir.wav"
"14" "bot/spotted_the_delivery_boy.wav"
"15" "bot/target_acquired.wav"
"16" "bot/target_spotted.wav"
"17" "bot/you_heard_the_man_lets_go.wav"
}
@@ -0,0 +1,131 @@
"TableToKeyValues"
{
"1" "ambient/alarms/apc_alarm_pass1.wav"
"2" "ambient/alarms/manhack_alert_pass1.wav"
"3" "ambient/alarms/razortrain_horn1.wav"
"4" "ambient/alarms/scanner_alert_pass1.wav"
"5" "ambient/alarms/train_horn2.wav"
"6" "ambient/alarms/train_horn_distant1.wav"
"7" "ambient/alarms/warningbell1.wav"
"8" "ambient/energy/whiteflash.wav"
"9" "ambient/intro/alyxremove.wav"
"10" "ambient/intro/logosfx.wav"
"11" "ambient/levels/launch/1stfiringwarning.wav"
"12" "ambient/levels/launch/rockettakeoffblast.wav"
"13" "ambient/misc/ambulance1.wav"
"14" "ambient/misc/carhonk1.wav"
"15" "ambient/misc/carhonk2.wav"
"16" "ambient/misc/carhonk3.wav"
"17" "ambient/outro/gunshipcrash.wav"
"18" "ambient/3dmeagle.wav"
"19" "beams/beamstart5.wav"
"20" "buttons/bell1.wav"
"21" "buttons/weapon_cant_buy.wav"
"22" "common/bass.wav"
"23" "common/bugreporter_failed.wav"
"24" "common/warning.wav"
"25" "doors/door_squeek1.wav"
"26" "friends/friend_join.wav"
"27" "friends/friend_online.wav"
"28" "friends/message.wav"
"29" "hostage/hunuse/comeback.wav"
"30" "hostage/hunuse/dontleaveme.wav"
"31" "hostage/hunuse/yeahillstay.wav"
"32" "items/gift_drop.wav"
"33" "music/radio1.mp3"
"34" "phx/eggcrack.wav"
"35" "plats/elevbell1.wav"
"36" "player/headshot1.wav"
"37" "player/headshot2.wav"
"38" "player/sprayer.wav"
"39" "radio/enemydown.wav"
"40" "radio/go.wav"
"41" "radio/locknload.wav"
"42" "radio/negative.wav"
"43" "radio/rounddraw.wav"
"44" "radio/takepoint.wav"
"45" "resource/warning.wav"
"46" "ui/achievement_earned.wav"
"47" "ui/freeze_cam.wav"
"48" "vehicles/junker/radar_ping_friendly1.wav"
"49" "weapons/c4/c4_beep1.wav"
"50" "weapons/c4/c4_click.wav"
"51" "weapons/awp/awp1.wav"
"52" "vo/canals/female01/gunboat_giveemhell.wav"
"53" "vo/canals/female01/gunboat_justintime.wav"
"54" "vo/canals/female01/stn6_incoming.wav"
"55" "vo/canals/male01/gunboat_giveemhell.wav"
"56" "vo/canals/male01/gunboat_justintime.wav"
"57" "vo/canals/male01/stn6_incoming.wav"
"58" "vo/canals/al_radio_stn6.wav"
"59" "vo/canals/arrest_getgoing.wav"
"60" "vo/canals/arrest_helpme.wav"
"61" "vo/canals/arrest_lookingforyou.wav"
"62" "vo/canals/boxcar_lethimhelp.wav"
"63" "vo/canals/matt_closecall.wav"
"64" "vo/canals/premassacre.wav"
"65" "vo/ravenholm/aimforhead.wav"
"66" "vo/ravenholm/bucket_patience.wav"
"67" "vo/ravenholm/madlaugh01.wav"
"68" "vo/ravenholm/madlaugh02.wav"
"69" "vo/ravenholm/madlaugh03.wav"
"70" "vo/ravenholm/madlaugh04.wav"
"71" "weapons/strider_buster/ol12_stickybombcreator.wav"
"72" "weapons/c4/c4_explode1.wav"
"73" "weapons/357/357_fire2.wav"
"74" "weapons/357/357_fire3.wav"
"75" "weapons/scout/scout_fire-1.wav"
"76" "weapons/smokegrenade/sg_explode.wav"
"77" "weapons/grenade_launcher1.wav"
"78" "weapons/explode3.wav"
"79" "weapons/underwater_explode3.wav"
"80" "items/nvg_on.wav"
"81" "hostage/huse/letsdoit.wav"
"82" "hostage/huse/illfollow.wav"
"83" "hostage/huse/getouttahere.wav"
"84" "doors/door_screen_move1.wav"
"85" "doors/heavy_metal_stop1.wav"
"86" "doors/default_move.wav"
"87" "common/stuck2.wav"
"88" "ambient/water_splash1.wav"
"89" "ambient/water_splash2.wav"
"90" "ambient/water_splash3.wav"
"91" "ambient/weather/thunder1.wav"
"92" "ambient/weather/thunder2.wav"
"93" "ambient/weather/thunder3.wav"
"94" "ambient/weather/thunder4.wav"
"95" "ambient/weather/thunder5.wav"
"96" "ambient/weather/thunder6.wav"
"97" "ambient/outro/thunder7.wav"
"98" "ambient/voices/crying_loop1.wav"
"99" "ambient/voices/playground_memory.wav"
"100" "ambient/voices/f_scream1.wav"
"101" "ambient/voices/m_scream1.wav"
"102" "ambient/voices/cough1.wav"
"103" "ambient/voices/cough2.wav"
"104" "ambient/voices/cough3.wav"
"105" "ambient/voices/cough4.wav"
"106" "ambient/overhead/plane1.wav"
"107" "ambient/overhead/plane2.wav"
"108" "ambient/overhead/plane3.wav"
"109" "ambient/overhead/hel1.wav"
"110" "ambient/overhead/hel2.wav"
"111" "ambient/misc/truck_backup1.wav"
"112" "ambient/misc/truck_drive1.wav"
"113" "ambient/misc/truck_drive2.wav"
"114" "ambient/machines/pneumatic_drill_1.wav"
"115" "ambient/machines/pneumatic_drill_2.wav"
"116" "ambient/machines/pneumatic_drill_3.wav"
"117" "ambient/machines/pneumatic_drill_4.wav"
"118" "ambient/machines/station_train_squeel.wav"
"119" "ambient/machines/ticktock.wav"
"120" "ambient/creatures/teddy.wav"
"121" "ambient/creatures/town_child_scream1.wav"
"122" "ambient/creatures/town_moan1.wav"
"123" "ambient/creatures/town_muffled_cry1.wav"
"124" "ambient/creatures/town_scared_breathing1.wav"
"125" "ambient/creatures/town_scared_breathing2.wav"
"126" "ambient/creatures/town_scared_sob1.wav"
"127" "ambient/creatures/town_scared_sob2.wav"
"128" "ambient/creatures/town_zombie_call1.wav"
}
@@ -0,0 +1,52 @@
"TableToKeyValues"
{
"1" "bot/and_thats_how_its_done.wav"
"2" "bot/come_to_papa.wav"
"3" "bot/do_not_mess_with_me.wav"
"4" "bot/dropped_him.wav"
"5" "bot/enemy_down.wav"
"6" "bot/enemy_down2.wav"
"7" "bot/good_job_team.wav"
"8" "bot/got_him.wav"
"9" "bot/hes_broken.wav"
"10" "bot/hes_dead.wav"
"11" "bot/hes_done.wav"
"12" "bot/hes_down.wav"
"13" "bot/its_a_party.wav"
"14" "bot/i_am_dangerous.wav"
"15" "bot/i_am_on_fire.wav"
"16" "bot/i_got_more_where_that_came_from.wav"
"17" "bot/i_wasnt_worried_for_a_minute.wav"
"18" "bot/killed_him.wav"
"19" "bot/look_out_brag.wav"
"20" "bot/made_him_cry.wav"
"21" "bot/oh_yea.wav"
"22" "bot/oh_yea2.wav"
"23" "bot/owned.wav"
"24" "bot/ruined_his_day.wav"
"25" "bot/tag_them_and_bag_them.wav"
"26" "bot/thats_the_way_this_is_done.wav"
"27" "bot/that_was_a_close_one.wav"
"28" "bot/that_was_it.wav"
"29" "bot/that_was_the_last_guy.wav"
"30" "bot/that_was_the_last_one.wav"
"31" "bot/they_never_knew_what_hit_them.wav"
"32" "bot/they_will_not_escape.wav"
"33" "bot/they_wont_get_away.wav"
"34" "bot/they_wont_get_away2.wav"
"35" "bot/this_is_my_house.wav"
"36" "bot/took_him_down.wav"
"37" "bot/took_him_out.wav"
"38" "bot/took_him_out2.wav"
"39" "bot/wasted_him.wav"
"40" "bot/way_to_be_team.wav"
"41" "bot/well_done.wav"
"42" "bot/we_owned_them.wav"
"43" "bot/whew_that_was_close.wav"
"44" "bot/whoo.wav"
"45" "bot/whoo2.wav"
"46" "bot/whos_the_man.wav"
"47" "bot/who_wants_some_more.wav"
"48" "bot/yesss.wav"
"49" "bot/yesss2.wav"
}
@@ -23,15 +23,7 @@ function ENT:Think()
-- Angles
if (self.Owner:GetNWBool("PropRotation")) then
self:ApplyRotation(self.Owner:EyeAngles())
self:SetAngles(self.Owner:EyeAngles())
end
end
function ENT:ApplyRotation(ang)
if !(GAMEMODE.Config.Hider:AllowFullRotation()) then
ang.p = 0
ang.r = 0
end
self:SetAngles(ang)
end
@@ -1,6 +1,6 @@
-- SWEP Information
SWEP.Author = "Michael 'Xaymar' Dirks"
SWEP.Contact = "info@xaymar.com"
SWEP.Contact = "info@project-kube.de"
SWEP.PrintName = "PH Submachine Gun"
SWEP.Purpose = "More accurate SMG for Prop Hunt."
SWEP.Instructions = "Fire away! Alternative fire to fire a grenade."
@@ -30,8 +30,8 @@ SWEP.Primary.ClipSize = 45
SWEP.Primary.DefaultClip = 45
SWEP.Primary.Automatic = true
SWEP.Primary.Ammo = "SMG1"
SWEP.Primary.Damage = 4
SWEP.Primary.RefireTime = 0.075
SWEP.Primary.Damage = 5
SWEP.Primary.RefireTime = 0.1
-- Secondary Ammunition: SMG Grenades
SWEP.Secondary.ClipSize = 1
@@ -25,21 +25,11 @@
-- ------------------------------------------------------------------------- --
--! Includes
-- ------------------------------------------------------------------------- --
-- Early Init
include("sh_init.lua")
include("vgui/dlabeldpi.lua")
include("vgui/dframedpi.lua")
include("vgui/fontmanager.lua")
include("vgui/uimanager.lua")
include("client/roundmanager.lua")
-- Late Init
GM.UI = {}
include("client/cl_ui_help.lua")
include("client/cl_ui_teamselection.lua")
include("client/hud/gamestatedisplay.lua")
include("client/ui/scoreboard.lua")
include("client/ui/help.lua")
include("client/ui/settings.lua")
-- ------------------------------------------------------------------------- --
--! Code
@@ -48,27 +38,20 @@ function GM:Initialize()
print("-------------------------------------------------------------------------")
print("Prop Hunt CL: Initializing...")
print("Prop Hunt CL: Preparing data...")
print("Prop Hunt CL: Initializing Gamemode Data...")
self.Data = {}
print("Prop Hunt CL: Creating User Interface...")
FontManager:Request("RobotoBoldCondensed160", {font="Roboto Bold Condensed", extended=true, size=160, weight=800, antialias=true})
self.UI = {}
self.UI.Help = vgui.Create("PHE_HelpUI")
self.UI.Scoreboard = vgui.Create("DScoreBoard")
self.UI.GameStateDisplay = vgui.Create("PHE_GameState")
self.UI.GameStateDisplay:Show()
print("Prop Hunt CL: Creating Huge Ass Font...")
surface.CreateFont("PHHugeAssFont", {font="Roboto Bold Condensed", extended=true, size=160, weight=800, antialias=true})
print("Prop Hunt CL: Complete.")
print("-------------------------------------------------------------------------")
end
function GM:Think()
UIManager:Tick()
end
function GM:Think() end
function GM:InitialPlayerSpawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: InitialPlayerSpawn") end
print("Prop Hunt CL: InitialPlayerSpawn")
-- Delay execution until LocalPlayer() is valid.
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
@@ -76,13 +59,13 @@ function GM:InitialPlayerSpawn()
return
end
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: InitialPlayerSpawn Valid") end
print("Prop Hunt CL: InitialPlayerSpawn Valid")
player_manager.RunClass(LocalPlayer(), "InitialClientSpawn")
end
function GM:PlayerSpawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: PlayerSpawn") end
print("Prop Hunt CL: PlayerSpawn")
-- Delay execution until LocalPlayer() is valid.
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
@@ -90,7 +73,7 @@ function GM:PlayerSpawn()
return
end
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: PlayerSpawn Valid") end
print("Prop Hunt CL: PlayerSpawn Valid")
if !(LocalPlayer().Data) then
LocalPlayer().Data = {}
@@ -123,9 +106,8 @@ function GM:PlayerSetViewOffset(vo, voduck)
if !(GAMEMODE.TempData) then GAMEMODE.TempData = {} end
GAMEMODE.TempData.ViewOffset = vo
GAMEMODE.TempData.ViewOffsetDuck = voduck
timer.Simple(.1, function()
GAMEMODE:PlayerSetViewOffset(GAMEMODE.TempData.ViewOffset, GAMEMODE.TempData.ViewOffsetDuck)
end)
timer.Simple(.1, function() GAMEMODE:PlayerSetViewOffset(GAMEMODE.TempData.ViewOffset, GAMEMODE.TempData.ViewOffsetDuck) end)
return
end
@@ -144,8 +126,8 @@ function GM:PlayerSetHull(hullMin, hullMax)
if !(GAMEMODE.TempData) then GAMEMODE.TempData = {} end
GAMEMODE.TempData.HullMin = hullMin
GAMEMODE.TempData.HullMax = hullMax
timer.Simple(.1, function()
GAMEMODE:PlayerSetHull(GAMEMODE.TempData.HullMin, GAMEMODE.TempData.HullMax) end)
timer.Simple(.1, function() GAMEMODE:PlayerSetHull(GAMEMODE.TempData.HullMin, GAMEMODE.TempData.HullMax) end)
return
end
@@ -164,32 +146,20 @@ function GM:OnContextMenuOpen()
end
function GM:OnContextMenuClose()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Toggled View Mode") end
print("Prop Hunt CL: Toggled View Mode")
LocalPlayer().Data.ThirdPerson = !LocalPlayer().Data.ThirdPerson
end
function GM:OnSpawnMenuOpen()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Enabling Prop Rotation") end
print("Prop Hunt CL: Enabling Prop Rotation")
LocalPlayer():SetNWBool("PropRotation", true)
net.Start("PlayerEnablePropRotation")
net.WriteAngle(LocalPlayer():EyeAngles())
net.SendToServer()
net.Start("PlayerEnablePropRotation");net.SendToServer()
end
function GM:OnSpawnMenuClose()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Disabling Prop Rotation") end
print("Prop Hunt CL: Disabling Prop Rotation")
LocalPlayer():SetNWBool("PropRotation", false)
net.Start("PlayerDisablePropRotation")
net.WriteAngle(LocalPlayer():EyeAngles())
net.SendToServer()
end
function GM:ScoreboardShow()
self.UI.Scoreboard:Show()
end
function GM:ScoreboardHide()
self.UI.Scoreboard:Hide()
net.Start("PlayerDisablePropRotation");net.SendToServer()
end
function GM:ShowHelpUI()
@@ -217,95 +187,45 @@ net.Receive( "PlayerViewOffset", function(len, pl)
GAMEMODE:PlayerSetViewOffset(vo, voduck)
end)
-- ------------------------------------------------------------------------- --
--! Special Drawing
-- ------------------------------------------------------------------------- --
function DrawNamePlates(bDrawingDepth, bDrawingSkybox)
if (!GAMEMODE.Config.NamePlates:Show()) then
return
end
local scale = GAMEMODE.Config.NamePlates:Scale()
local pls = team.GetPlayers(GAMEMODE.Teams.Seekers)
if (LocalPlayer():Team() == GAMEMODE.Teams.Hiders) then
pls = table.Add(pls, team.GetPlayers(GAMEMODE.Teams.Hiders))
end
for i,v in ipairs(pls) do
if (v:Alive() && v != LocalPlayer()) then
if (player_manager.GetPlayerClass(v) != "Spectator") then
local color = HSVToColor(GAMEMODE.Config.NamePlates:TintHue(),
GAMEMODE.Config.NamePlates:TintSaturation(),
GAMEMODE.Config.NamePlates:TintValue())
if GAMEMODE.Config.NamePlates:TintHealth() then
local healthPrc = v:Health() / v:GetMaxHealth()
color = HSVToColor(120 * healthPrc, 1.0, 1.0)
elseif GAMEMODE.Config.NamePlates:TintTeam() then
color = team.GetColor(v:Team())
end
local pos = v:GetPos() + v:GetViewOffset() + Vector(0, 0, GAMEMODE.Config.NamePlates:Height())
local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x)
cam.Start3D2D(pos, ang, scale)
draw.DrawText(v:GetName(), "RobotoBoldCondensed160", 0, -draw.GetFontHeight("RobotoBoldCondensed160") / 2, color, TEXT_ALIGN_CENTER)
cam.End3D2D()
end
end
end
end
hook.Add("PostDrawTranslucentRenderables", "PHDrawNamePlates", DrawNamePlates)
function DrawSelectionHalo(bDrawingDepth, bDrawingSkybox)
if (!GAMEMODE.Config.SelectionHalo:Enabled()) then return end
if ((LocalPlayer():Team() == GAMEMODE.Teams.Hiders)
&& (player_manager.GetPlayerClass(LocalPlayer()) == "Hider")) then
local ent = nil
if (GAMEMODE.Config.SelectionHalo:Approximate()) then
local trace = {
start = LocalPlayer():EyePos(),
endpos = LocalPlayer():EyePos() + LocalPlayer():EyeAngles():Forward() * 80,
mins = Vector(-16, -16, -16),
maxs = Vector( 16, 16, 16),
mask = MASK_SOLID + CONTENTS_DEBRIS + CONTENTS_PLAYERCLIP,
filter = function(ent)
-- Ensure that we don't actually hit ourselves by accident, or our "hands" model.
if (!IsValid(ent)
|| (ent == LocalPlayer())
|| (ent == LocalPlayer():GetHands())) then
return false
end
if table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass()) then return true end
return false
end,
output = {}
}
util.TraceLine(trace)
if !IsValid(trace.output.Entity) then util.TraceHull(trace) end
if IsValid(trace.output.Entity) then
if (!table.HasValue(GAMEMODE.Config.Lists:ModelBlacklist(), trace.output.Entity:GetModel())) then
ent = trace.output.Entity
end
end
else
ent = LocalPlayer():GetNWEntity("SelectionHalo")
end
if IsValid(ent) then
local color = HSVToColor(
GAMEMODE.Config.SelectionHalo:TintHue(),
GAMEMODE.Config.SelectionHalo:TintSaturation(),
GAMEMODE.Config.SelectionHalo:TintValue()
)
halo.Add({ ent }, color,
GAMEMODE.Config.SelectionHalo:BlurX(), GAMEMODE.Config.SelectionHalo:BlurY(), GAMEMODE.Config.SelectionHalo:Passes(),
GAMEMODE.Config.SelectionHalo:Additive(), GAMEMODE.Config.SelectionHalo:IgnoreZ())
end
end
end
hook.Add("PostDrawEffects", "PHDrawSelectionHalo", DrawSelectionHalo)
-- ------------------------------------------------------------------------- --
--! Old Code
-- ------------------------------------------------------------------------- --
--[[
-- Render halos and player names.
function DrawPlayerNames(bDrawingDepth, bDrawingSkybox)
for i,v in ipairs(player.GetAll()) do
if v:Alive() && v != LocalPlayer() then
local pos = v:GetPos() + v:GetViewOffset() + Vector(0, 0, 5)
local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x)
local healthPrc = v:Health() / v:GetMaxHealth()
local healthCol = HSVToColor(120 * healthPrc, 1.0, 1.0)
if v:Team() == TEAM_HUNTERS || LocalPlayer():Team() == TEAM_PROPS then
cam.Start3D2D(pos, ang, 0.15)
draw.DrawText(v:GetName(), "Trebuchet24", 0, -draw.GetFontHeight("Trebuchet24"), healthCol, TEXT_ALIGN_CENTER)
cam.End3D2D()
end
end
end
end
hook.Add("PostDrawTranslucentRenderables", "PH_DrawPlayerNames", DrawPlayerNames)
function DrawPlayerHalos(bDrawingDepth, bDrawingSkybox)
for i,v in ipairs(player.GetAll()) do
if v:Alive() then
local pos = v:GetPos() + Vector(0, 0, 1) * (v:OBBMaxs().z - v:OBBMins().z + 5)
local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x)
local healthPrc = v:Health() / v:GetMaxHealth()
local healthCol = HSVToColor(120 * healthPrc, 1.0, 1.0)
if v:Team() == TEAM_HUNTERS || LocalPlayer():Team() == TEAM_PROPS then
local ent = v
if v.ph_prop && v.ph_prop:IsValid() then ent = v.ph_prop end
halo.Add({ent}, healthCol, 2, 2, 1)
end
end
end
end
--hook.Add("PostDrawEffects", "PH_DrawPlayerHalos", DrawPlayerHalos)
]]
@@ -1,25 +1,61 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
include("sh_init.lua")
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local PANEL = vgui.Create("DFrame")
PANEL:SetSize(400, 300)
PANEL:SetTitle("Help")
PANEL:SetDraggable(true)
PANEL:SetVisible(false)
PANEL:SetDraggable(true)
PANEL:SetSizable(true)
PANEL:ShowCloseButton(true)
PANEL:SetDeleteOnClose(false)
function PANEL:Init()
DFrame.Init(self)
-- Sheets
self.Sheets = vgui.Create("DPropertySheet", self)
self.Sheets:Dock(FILL)
-- Basic Info
self.BasicInfoSheet = vgui.Create("DPanel", self.Sheets)
function self.BasicInfoSheet:Paint(w, h)
draw.RoundedBox(4, 0, 0, 100, 100, Color(0,128,255))
end
self.Sheets:AddSheet("The Gamemode", self.BasicInfoSheet)
end
function PANEL:Show()
self:SetSize(ScrW(), ScrH())
self:Center()
self:SetVisible(true)
self:SetFocusTopLevel(true)
self:SlideDown(.5)
self:MakePopup()
end
GAMEMODE.UI.Help = PANEL
@@ -22,19 +22,6 @@
SOFTWARE.
--]]
local PANEL = vgui.Create("DFrame")
PANEL:SetSize(400, 300)
PANEL:SetTitle("Select a Team")
PANEL:SetDraggable(true)
PANEL:SetVisible(false)
PANEL:SetDraggable(true)
PANEL:SetSizable(true)
PANEL:ShowCloseButton(true)
PANEL:SetDeleteOnClose(false)
TeamSelectionUI = {}
TeamSelectionUI.Frame = vgui.Create("DFrame")
TeamSelectionUI.Frame:SetPos(0, 0)
@@ -33,30 +33,17 @@ function CompatTauntPackLoader()
-- Run the old hook name.
hook.Run("ph_AddTaunts", nil)
-- Insert the taunts into the new structure (cvar).
Taunts = {}
for i,t in ipairs(GAMEMODE.Prop_Taunts) do
ty = type(t)
if (ty == "string") then
Taunts[#Taunts+1] = t
elseif (ty == "table") then
Taunts[#Taunts+1] = t[1]
end
-- Insert the taunts into the new structure.
for k,v in ipairs(GAMEMODE.Hunter_Taunts) do
-- ToDo: string.GetFileFromFilename is broken!
--pcall(GAMEMODE.Config.Taunts.Add("TauntPackLoader."..string.GetFileFromFilename(v), v, TEAM_SEEKERES, nil))
end
GAMEMODE.Config.Taunt.HidersCacheStatic = Taunts
Taunts = {}
for i,t in ipairs(GAMEMODE.Hunter_Taunts) do
ty = type(t)
if (ty == "string") then
Taunts[#Taunts+1] = t
elseif (ty == "table") then
Taunts[#Taunts+1] = t[1]
end
for k,v in ipairs(GAMEMODE.Prop_Taunts) do
--pcall(GAMEMODE.Config.Taunts.Add("TauntPackLoader."..string.GetFileFromFilename(v), v, TEAM_HIDERS, nil))
end
GAMEMODE.Config.Taunt.SeekersCacheStatic = Taunts
-- Clean up after ourselves
GAMEMODE.Prop_Taunts = nil
GAMEMODE.Hunter_Taunts = nil
end
hook.Add("Initialize", "CompatTauntPackLoader", CompatTauntPackLoader)
hook.Add("OnPropHuntInitialized", "CompatTauntPackLoader", CompatTauntPackLoader)
@@ -27,30 +27,18 @@
-- ------------------------------------------------------------------------- --
-- Shared
AddCSLuaFile("sh_init.lua")
AddCSLuaFile("sh_defines.lua")
AddCSLuaFile("sh_config.lua")
AddCSLuaFile("meta/player.lua")
AddCSLuaFile("sh_player.lua")
AddCSLuaFile("player_class/class_default.lua")
AddCSLuaFile("player_class/class_spectator.lua")
AddCSLuaFile("player_class/class_seeker.lua")
AddCSLuaFile("player_class/class_hider.lua")
-- Client-Only
AddCSLuaFile("vgui/fontmanager.lua")
AddCSLuaFile("vgui/uimanager.lua")
AddCSLuaFile("vgui/dlabeldpi.lua")
AddCSLuaFile("vgui/dframedpi.lua")
AddCSLuaFile("client/ui/help.lua")
AddCSLuaFile("client/ui/settings.lua")
AddCSLuaFile("client/ui/scoreboard.lua")
AddCSLuaFile("client/hud/gamestatedisplay.lua")
AddCSLuaFile("client/roundmanager.lua")
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("client/cl_ui_help.lua")
AddCSLuaFile("client/cl_ui_teamselection.lua")
-- Client Init
AddCSLuaFile("cl_init.lua") -- Immediately executed when downloaded, weird behavior.
-- ------------------------------------------------------------------------- --
--! Code
-- ------------------------------------------------------------------------- --
@@ -58,6 +46,7 @@ AddCSLuaFile("cl_init.lua") -- Immediately executed when downloaded, weird behav
include "sh_init.lua"
-- Server Only
include "server/config.lua"
include "compat/compat_tauntpackloader.lua"
include "server/roundmanager.lua"
include "server/states/state_prematch.lua"
@@ -74,6 +63,7 @@ function GM:Initialize()
print("Prop Hunt: Registering Networked Messages...")
util.AddNetworkString("PlayerManagerInitialClientSpawn")
util.AddNetworkString("PlayerManagerClientSpawn")
util.AddNetworkString("PlayerSetHull")
util.AddNetworkString("PlayerResetHull")
util.AddNetworkString("PlayerViewOffset")
@@ -83,46 +73,42 @@ function GM:Initialize()
print("Prop Hunt: Initializing Gamemode Data...")
self.Data = {}
self.Data.RoundTime = 0
self.Data.RoundStartTime = 0
self.Data.StateTime = 0
print("Prop Hunt: Initializing Round Manager")
RoundManager:SetState(StatePreRound)
print("Prop Hunt: Precaching...")
GAMEMODE.Config.Taunt:Seekers()
GAMEMODE.Config.Taunt:Hiders()
print("Prop Hunt: Setting initial RoundManager State...")
self.RoundManager:SetState(StatePreMatch)
print("Prop Hunt: Complete.")
print("-------------------------------------------------------------------------")
end
function GM:Think()
self.RoundManager:Tick()
end
-- Player Connected
function GM:PlayerConnect(name, ip)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..name.."' connecting from IP '"..ip.."'.") end
print("Prop Hunt: Player '"..name.."' connecting from IP '"..ip.."'.")
end
-- Player Authenticated
function GM:PlayerAuthed(ply, steamid, uniqueid)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") authenticated.") end
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") authenticated.")
end
-- Player Disconnected
function GM:PlayerDisconnected(ply)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") disconnected.") end
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") disconnected.")
end
-- Player Spawn (Initial)
function GM:PlayerInitialSpawn(ply)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned for the first time, applying defaults...") end
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned for the first time, applying defaults...")
if (!ply.Data) then
-- Initialize Data Structure
ply.Data = {}
ply.Data.Alive = false
ply.Data.AliveTime = 0
ply.Data.RandomWeight = 0 -- Higher means higher chance of becoming Seeker instead of Hider.
end
-- Kill Silently
@@ -135,10 +121,10 @@ function GM:PlayerInitialSpawn(ply)
-- Bot: Auto Assign to Team
if (ply:IsBot()) then
if team.NumPlayers(self.Teams.Hiders) > team.NumPlayers(self.Teams.Seekers) then
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Seekers.") end
print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Seekers.")
ply:SetTeam(self.Teams.Seekers)
else
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Hiders.") end
print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Hiders.")
ply:SetTeam(self.Teams.Hiders)
end
end
@@ -152,7 +138,7 @@ end
-- Player Spawn
function GM:PlayerSpawn(ply)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned in.") end
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned in.")
-- Player Manager: Assign Player Class
local class = team.GetClass(ply:Team())
@@ -181,7 +167,7 @@ end
-- Player requests Team Change
function GM:PlayerRequestTeam(ply, teamId)
if self:PlayerCanJoinTeam(ply, teamId) then
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") requested to join Team "..team.GetName(teamId)..".") end
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") requested to join Team "..team.GetName(teamId)..".")
if (ply:Team() != teamId) then
ply:KillSilent()
@@ -192,7 +178,7 @@ function GM:PlayerRequestTeam(ply, teamId)
ply.AliveTime = CurTime()
end
else
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") attempted to rejoin the Team it is already in.") end
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") attempted to rejoin the Team it is already in.")
end
end
end
@@ -201,38 +187,7 @@ end
--! Player Manager Binding
-- ------------------------------------------------------------------------- --
function GM:PlayerLoadout(ply) player_manager.RunClass(ply, "Loadout") end
function GM:PlayerDeath(ply, inflictor, attacker)
player_manager.RunClass(ply, "Death", inflictor, attacker)
-- Signal Client Stuff
if IsValid(attacker) then
if attacker:IsPlayer() then
if (attacker == ply) then
net.Start("PlayerKilledSelf")
net.WriteEntity(ply)
net.Broadcast()
else
net.Start("PlayerKilledByPlayer")
net.WriteEntity(ply)
net.WriteString(inflictor:GetName())
net.WriteEntity(attacker)
net.Broadcast()
end
else
net.Start("PlayerKilled")
net.WriteEntity(ply)
net.WriteString(inflictor:GetName())
net.WriteString(attacker:GetClass())
net.Broadcast()
end
else
net.Start("PlayerKilled")
net.WriteEntity(ply)
net.WriteString(inflictor:GetName())
net.WriteString("World")
net.Broadcast()
end
end
function GM:PlayerDeath(ply, inflictor, attacker) player_manager.RunClass(ply, "Death", inflictor, attacker) end
function GM:PlayerSilentDeath(ply) player_manager.RunClass(ply, "SilentDeath") end
function GM:PostPlayerDeath(ply)
player_manager.RunClass(ply, "PostDeath")
@@ -240,10 +195,10 @@ function GM:PostPlayerDeath(ply)
-- Debug Mode: Respawn after Death
if (GAMEMODE.Config:Debug()) then
ply.Data.Alive = true
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Debug Mode active, Player "..ply:GetName().." was respawned.") end
print("Prop Hunt: Debug Mode active, Player "..ply:GetName().." was respawned.")
end
end
function GM:DoPlayerDeath(ply, attacker, dmg) player_manager.RunClass(ply, "DoDeath", attacker, dmg) end
--function GM:DoPlayerDeath(ply, attacker, dmg) player_manager.RunClass(ply, "DoDeath", attacker, dmg) end
function GM:PlayerDeathThink(ply) return player_manager.RunClass(ply, "DeathThink") end
function GM:CanPlayerSuicide(ply) return player_manager.RunClass(ply, "CanSuicide") end
function GM:PlayerCanPickupWeapon(ply, weapon) return player_manager.RunClass(ply, "CanPickupWeapon", weapon) end
@@ -252,19 +207,7 @@ function GM:PlayerUse(ply, ent) return player_manager.RunClass(ply, "Use", ent)
function GM:AllowPlayerPickup(ply, ent) return player_manager.RunClass(ply, "AllowPickup", ent) end
function GM:PlayerSetModel(ply) return player_manager.RunClass(ply, "SetModel") end
-- Damage
function GM:PlayerShouldTakeDamage(victim, attacker)
return player_manager.RunClass(victim, "ShouldTakeDamage", attacker)
end
function GM:PlayerHurt(victim, attacker, healthRemaining, damageTaken)
player_manager.RunClass(victim, "Hurt", victim, attacker, healthRemaining, damageTaken)
if (IsValid(attacker) && attacker:IsPlayer()) then
player_manager.RunClass(attacker, "Damage", victim, attacker, healthRemaining, damageTaken)
end
end
-- Called when an entity takes damage
function GM:EntityTakeDamage(ent, dmg)
local att = dmg:GetAttacker()
@@ -276,20 +219,12 @@ end
-- ------------------------------------------------------------------------- --
--! Gamemode Functionality
-- ------------------------------------------------------------------------- --
function GM:SetRound(Round)
SetGlobalInt("Round", Round)
end
function GM:SetRoundTime(Time)
SetGlobalInt("RoundTime", Time)
end
function GM:SetRoundState(State)
SetGlobalInt("RoundState", State)
end
function GM:SetRoundStateTime(Time)
SetGlobalInt("RoundStateTime", Time)
function GM:SetRoundTime(Time)
SetGlobalInt("RoundTime", Time)
end
function GM:SetRoundWinner(Winner)
@@ -306,7 +241,6 @@ function GM:PlayerHullFromEntity(ply, ent)
hull.x = hull.y
end
hull:Mul(0.5)
hull:Mul(0.95) -- Reduce size slightly
local hullmin = Vector(-hull.x, -hull.y, 0)
local hullmax = Vector(hull.x, hull.y, hull.z * 2)
@@ -355,73 +289,153 @@ function GM:ShowTeam(ply)
ply:ConCommand("ph_select_team")
end
function GM:ShowSpare1(ply) player_manager.RunClass(ply, "ShowSpare1") end -- F3/ShowSpare1
function GM:ShowSpare2(ply) player_manager.RunClass(ply, "ShowSpare2") end -- F4/ShowSpare2
-- F3/ShowSpare1
function GM:ShowSpare1(ply) end
-- F4/ShowSpare2
function GM:ShowSpare2(ply) end
-- Debug Command: Print All Players
concommand.Add("ph_debug_printplayers", function(ply, cmd, args, argStr)
if GAMEMODE.Config:DebugLog() then
print ("All Players:")
for i,ply in ipairs(player.GetAll()) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..") - Team "..team.GetName(ply:Team()).. " - Alive "..tostring(ply.Data.Alive))
end
print ("Spectators:")
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Spectators)) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
end
print ("Seekers:")
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
end
print ("Hiders:")
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Hiders)) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
end
print ("All Players:")
for i,ply in ipairs(player.GetAll()) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..") - Team "..team.GetName(ply:Team()).. " - Alive "..tostring(ply.Data.Alive))
end
end, nil, nil, FCVAR_CLIENTCMD_CAN_EXECUTE + FCVAR_CHEAT)
-- Debug Command: Print All Players
concommand.Add("ph_debug_stats", function(ply, cmd, args, argStr)
if GAMEMODE.Config:DebugLog() then
for i,ply in ipairs(player.GetAll()) do
print(ply:GetName().." (SteamID: "..ply:SteamID()..")")
print(" Team: "..team.GetName(ply:Team()))
print(" Alive: "..tostring(ply.Data.Alive))
print(" AliveTime: "..tostring(ply.Data.AliveTime))
print(" Score: "..tostring(ply.Data.RandomWeight))
end
print ("Spectators:")
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Spectators)) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
end
print ("Seekers:")
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
end
print ("Hiders:")
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Hiders)) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
end
end, nil, nil, FCVAR_CLIENTCMD_CAN_EXECUTE + FCVAR_CHEAT)
-- ------------------------------------------------------------------------- --
--! Network Messages
-- ------------------------------------------------------------------------- --
net.Receive("PlayerEnablePropRotation", function(len, ply)
if (ply:Team() != GAMEMODE.Teams.Hiders) then
return
end
angle = net.ReadAngle()
print("Prop Hunt: Enabling Prop Rotation")
ply:SetNWBool("PropRotation", true)
ply.Data.Prop:ApplyRotation(angle)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") enabled prop rotation with angle ["..tostring(angle).."].") end
end)
net.Receive("PlayerDisablePropRotation", function(len, ply)
if (ply:Team() != GAMEMODE.Teams.Hiders) then
print("Prop Hunt: Disabling Prop Rotation")
ply:SetNWBool("PropRotation", false)
end)
-- ------------------------------------------------------------------------- --
--! LEGACY CODE - TO BE REPLACED SOON
-- ------------------------------------------------------------------------- --
--[[
function AnnounceVictory(players, force)
for i,pl in ipairs(players) do
if pl:Alive() || force || pl:Team() == TEAM_SPECTATOR then
announcer = table.Random(VICTORY_SOUNDS);
print("Prop Hunt: '"..pl:GetName().."' announcing victory with '"..announcer.."'.")
pl:EmitSound(announcer, 200, 100, 0.5, CHAN_VOICE2)
end
end
end
function AnnounceLoss(players, force)
for i,pl in ipairs(players) do
if pl:Alive() || force || pl:Team() == TEAM_SPECTATOR then
announcer = table.Random(LOSS_SOUNDS);
print("Prop Hunt: '"..pl:GetName().."' announcing loss with '"..announcer.."'.")
pl:EmitSound(announcer, 100, 100, 0.5, CHAN_VOICE2)
end
end
end
-- If there is a mapfile send it to the client (sometimes servers want to change settings for certain maps)
if file.Exists("maps/"..game.GetMap()..".lua", "LUA") then
AddCSLuaFile("maps/"..game.GetMap()..".lua")
end
-- Send the required resources to the client
for _, announcer in pairs(LOSS_SOUNDS) do resource.AddFile("sound/"..announcer) end
for _, announcer in pairs(VICTORY_SOUNDS) do resource.AddFile("source/"..announcer) end
for _, taunt in pairs(HUNTER_TAUNTS) do resource.AddFile("sound/"..taunt) end
for _, taunt in pairs(PROP_TAUNTS) do resource.AddFile("sound/"..taunt) 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!")
AnnounceLoss(player.GetAll(), true)
return
end
if table.Count(Teams) == 1 then
-- Play victory and loss sounds.
if Teams[0] == TEAM_HUNTERS then
AnnounceVictory(team.GetPlayers(TEAM_HUNTERS))
AnnounceLoss(team.GetPlayers(TEAM_PROPS))
elseif Teams[0] == TEAM_PROPS then
AnnounceLoss(team.GetPlayers(TEAM_HUNTERS))
AnnounceVictory(team.GetPlayers(TEAM_PROPS))
end
local TeamID = table.GetFirstKey(Teams)
GAMEMODE:RoundEndWithResult(TeamID, team.GetName(TeamID).." win!")
return
end
end
-- Called when player presses [F3]. Plays a taunt for their team
function GM:ShowSpare1(pl)
if GAMEMODE:InRound() && pl:Alive() && (pl:Team() == TEAM_HUNTERS || pl:Team() == TEAM_PROPS) && pl.last_taunt_time + TAUNT_DELAY <= CurTime() && #PROP_TAUNTS > 1 && #HUNTER_TAUNTS > 1 then
-- repeat
if pl:Team() == TEAM_HUNTERS then
rand_taunt = table.Random(HUNTER_TAUNTS)
else
rand_taunt = table.Random(PROP_TAUNTS)
end
-- until rand_taunt != pl.last_taunt
pl.last_taunt_time = CurTime()
pl.last_taunt = rand_taunt
print("Prop Hunt: '"..pl:GetName().."' taunting with '"..rand_taunt.."'.")
local vol = 1.0
if pl:Team() == TEAM_HUNTERS then vol = vol * 0.5 end
pl:EmitSound(rand_taunt, 100, 100, vol, CHAN_VOICE2)
end
end
-- Allow player to rotate the prop. (Either F4 or ducking)
function GM:ShowSpare2(pl)
if pl:Alive() && (pl:Team() == TEAM_PROPS) then
pl.ph_prop:SetApplyNewAngles(!pl.ph_prop:GetApplyNewAngles())
-- pl.ph_prop:SetNewAngles(pl:GetAngles())
end
end
-- Removes all weapons on a map
function RemoveWeaponsAndItems()
for _, wep in pairs(ents.FindByClass("weapon_*")) do
wep:Remove()
end
angle = net.ReadAngle()
ply:SetNWBool("PropRotation", false)
ply.Data.Prop:ApplyRotation(angle)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") enabled prop rotation with angle ["..tostring(angle).."].") end
end)
for _, item in pairs(ents.FindByClass("item_*")) do
item:Remove()
end
end
hook.Add("InitPostEntity", "PH_RemoveWeaponsAndItems", RemoveWeaponsAndItems)
]]
@@ -44,15 +44,11 @@ CLASS.UseVMHands = true -- Uses viewmodel hands
--! Server-Side
-- ------------------------------------------------------------------------- --
-- Spawn
function CLASS:InitialSpawn()
self.Player.Data = {}
self.Player.Data.SelectionHaloTime = CurTime()
end
function CLASS:InitialSpawn() end
function CLASS:Spawn() end
function CLASS:Loadout() end
-- Damage
function CLASS:ShouldTakeDamage(attacker) return true end -- Should take damage from attacker?
function CLASS:Hurt(victim, attacker, healthRemaining, damageTaken) end -- Damage Taken
function CLASS:Damage(victim, attacker, healthRemaining, damageDealt) end -- Damage Dealt
function CLASS:DamageEntity(ent, attacker, dmginfo) end -- Damage Dealt To Entity
@@ -61,21 +57,15 @@ function CLASS:DamageEntity(ent, attacker, dmginfo) end -- Damage Dealt To Entit
function CLASS:Death(inflictor, attacker)
self.Player.Data.Alive = false
self.Player.Data.AliveTime = CurTime()
-- Score support
self.Player:AddDeaths(1)
if IsValid(attacker) && attacker:IsPlayer() then
if ((attacker == self.Player)
|| (attacker:Team() == self.Player:Team())) then
self.Player:AddFrags(-1)
end
end
end
function CLASS:SilentDeath()
self.Player.Data.Alive = false
self.Player.Data.AliveTime = CurTime()
end
function CLASS:PostDeath() end
function CLASS:DoDeath() end
function CLASS:DeathThink()
if (CurTime() - self.Player.Data.AliveTime) > 5 then
self.Player:Spawn()
@@ -83,6 +73,7 @@ function CLASS:DeathThink()
end
return false
end
function CLASS:CanSuicide() return true end
-- Visible Stuff
@@ -91,14 +82,14 @@ function CLASS:SetModel() BaseClass.SetModel( self ) end
-- Interaction
function CLASS:Use(ent)
-- Entity must be valid and not a player.
if (!ent || !ent:IsValid()) then
if (!ent) || (!ent:IsValid()) || (ent:IsPlayer()) then
return false
end
-- Cool Down
if (self.Player.Data.UseTime) then
local timeSinceUse = (CurTime() - self.Player.Data.UseTime)
if (0.5 > timeSinceUse) then
if (0.2 > timeSinceUse) then
return false
end
@@ -118,23 +109,11 @@ function CLASS:AllowPickup(ent) return false end
function CLASS:CanPickupWeapon(ent) return false end
function CLASS:CanPickupItem(ent) return false end
-- Menu (Always Server)
function CLASS:ShowSpare1()
local lastTaunt = (self.Player.Data.LastTaunt or 0)
if ((CurTime() - lastTaunt) <= GAMEMODE.Config.Taunt:Cooldown()) then
return true
end
self.Player.Data.LastTaunt = CurTime()
end
function CLASS:ShowSpare2() end
-- ------------------------------------------------------------------------- --
--! Shared
-- ------------------------------------------------------------------------- --
function CLASS:PostThink() end
function CLASS:Tick(mv) end
function CLASS:FindUseEntity(defEnt) return defEnt end
function CLASS:Alive() return false end
-- ------------------------------------------------------------------------- --
--! Client-Side
@@ -150,60 +129,91 @@ function CLASS:ClientSpawn() end
function CLASS:GetHandsModel() return BaseClass.GetHandsModel(self) end
function CLASS:ShouldDrawLocal() return false end
function CLASS:HUDPaint()
-- Death Notices
GAMEMODE:DrawDeathNotice((ScrW() - 192) / ScrW() , 24 / ScrH())
end
function CLASS:CalcView(camdata)
-- Config
local cameraCollision = GAMEMODE.Config.Camera:Collisions()
local cameraDistance = GAMEMODE.Config.Camera:Distance()
local cameraDistanceRight = GAMEMODE.Config.Camera:DistanceRight()
local cameraDistanceUp = GAMEMODE.Config.Camera:DistanceUp()
local cameraLag = GAMEMODE.Config.Camera:Lag()
local cameraLagInv = 1 - cameraLag
local State = GetGlobalInt("RoundState", GAMEMODE.States.PreMatch)
-- First/Third Person Target Distance
local targetDistance = 0
if (self.Player.Data.ThirdPerson) then -- Incremental Distance instead of instant.
targetDistance = cameraDistance
-- Show Status at the top center
local statusX, statusY, statusW, statusH
statusW = 192
statusH = 64
statusX = ScrW() / 2 - statusW / 2
statusY = 16
-- Status
if (State == GAMEMODE.States.PreMatch) then -- Pre Match
draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204))
surface.SetFont( "Trebuchet24" )
surface.SetTextColor( 255, 255, 255, 255 )
local w,h = surface.GetTextSize("Waiting for Players")
surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/2 - h / 2)
surface.DrawText("Waiting for Players")
elseif (State == GAMEMODE.States.PreRound) then -- Pre Round
draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204))
surface.SetFont( "Trebuchet24" )
surface.SetTextColor( 255, 255, 255, 255 )
local w,h = surface.GetTextSize("Preparing...")
surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/2 - h / 2)
surface.DrawText( "Preparing..." )
elseif (State == GAMEMODE.States.Hide) then -- Hide
local strTime = tostring(math.ceil(GetGlobalInt("RoundTime")))
if (cameraCollision == true) then
-- Trace from Player to would-be camera position
local trace = {
start = camdata.origin,
endpos = camdata.origin - (camdata.angles:Forward() * cameraDistance),
--filter = { "worldspawn", "ph_prop", "player" },
--[-[
filter = function(ent)
local filter = { "worldspawn", "ph_prop", "player" }
if (ent:IsPlayer())
|| (table.HasValue(filter, ent:GetClass()))
|| (ent == LocalPlayer()) || (ent == LocalPlayer():GetHands()) then
return false
end
return true
end,
--]]
}
local result = util.TraceLine(trace)
-- The Camera has a Sphere radius of 10.
if (result.Hit) then -- Configurable?
targetDistance = math.Clamp(result.HitPos:Distance(camdata.origin), 0, cameraDistance)
end
-- Show Status at the top center
draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204))
surface.SetTextColor(255,255,255,255)
surface.SetFont("Trebuchet18")
local w,h = surface.GetTextSize("Seekers unblinded in:")
surface.SetTextPos(statusX + statusW/2 - w / 2, statusY + statusH/4 - h / 2)
surface.DrawText("Seekers unblinded in:")
surface.SetFont( "Trebuchet24" )
local w,h = surface.GetTextSize(strTime.." Seconds!")
surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/1.5 - h / 2)
surface.DrawText(strTime.." Seconds!")
elseif (State == GAMEMODE.States.Seek) then -- Seek
local intTime = math.ceil(GetGlobalInt("RoundTime"))
local strTime = string.format("%d:%02d", math.floor(intTime / 60), math.ceil(intTime % 60))
-- Show Status at the top center
draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204))
surface.SetTextColor(255,255,255,255)
surface.SetFont("Trebuchet18")
local w,h = surface.GetTextSize("Hunting Time!")
surface.SetTextPos(statusX + statusW/2 - w / 2, statusY + statusH/4 - h / 2)
surface.DrawText("Hunting Time!")
surface.SetFont( "Trebuchet24" )
local w,h = surface.GetTextSize(strTime)
surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/1.5 - h / 2)
surface.DrawText(strTime)
elseif (State == GAMEMODE.States.PostRound) then -- Post Round
-- Show Status at the top center
draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204))
surface.SetTextColor(255,255,255,255)
surface.SetFont("Trebuchet18")
local w,h = surface.GetTextSize("Match Result")
surface.SetTextPos(statusX + statusW/2 - w / 2, statusY + statusH/4 - h / 2)
surface.DrawText("Match Result")
local victor = GAMEMODE:GetRoundWinner()
local victorName = "Unknown"
if (victor == GAMEMODE.Teams.Spectator) then
victorName = "Draw"
elseif (victor == GAMEMODE.Teams.Hiders) then
victorName = "Hiders Win"
elseif (victor == GAMEMODE.Teams.Seekers) then
victorName = "Seekers Win"
end
else
targetDistance = 0
surface.SetTextColor(team.GetColor(victor))
surface.SetFont( "Trebuchet24" )
local w,h = surface.GetTextSize(victorName)
surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/1.5 - h / 2)
surface.DrawText(victorName)
elseif (State == GAMEMODE.States.PostMatch) then -- Post Match
end
-- Fade between Target and Current Distance
self.Player.Data.ViewDistance = math.Clamp(((self.Player.Data.ViewDistance or targetDistance) * cameraLag) + (targetDistance * cameraLagInv), 0, GAMEMODE.Config.Camera:DistanceMax())
-- Adjust CamData and return
camdata.origin = camdata.origin - (camdata.angles:Forward() * math.Clamp(self.Player.Data.ViewDistance - 10, 0, self.Player.Data.ViewDistance)) + (camdata.angles:Right() * cameraDistanceRight) + (camdata.angles:Up() * cameraDistanceUp)
return camdata
end
function CLASS:CalcView(camdata) return camdata end
-- ------------------------------------------------------------------------- --
--! Register
@@ -35,38 +35,32 @@ CLASS.UseVMHands = false -- Uses viewmodel hands
-- ------------------------------------------------------------------------- --
-- Spawn
function CLASS:Spawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
BaseClass.Spawn(self, self.Player)
-- Sprinting
if (!GAMEMODE.Config:Sprinting()) then
self.Player:SetRunSpeed(self.WalkSpeed)
end
-- Settings
self.Player:SetMaxHealth(GAMEMODE.Config.Hider:HealthMax())
self.Player:SetHealth(GAMEMODE.Config.Hider:Health())
self.Player:SetRenderMode(RENDERMODE_TRANSALPHA)
self.Player:SetColor(Color(0,0,0,0))
-- Speed and Jump Power
self.Player:SetWalkSpeed(GAMEMODE.Config.Hider:WalkSpeed())
if (GAMEMODE.Config.Hider:Sprint()) then
self.Player:SetRunSpeed(GAMEMODE.Config.Hider:SprintSpeed())
else
self.Player:SetRunSpeed(GAMEMODE.Config.Hider:WalkSpeed())
end
self.Player:SetJumpPower(GAMEMODE.Config.Hider:JumpPower())
-- Hull & View Offset
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,72), Vector(0,0,72))
-- Collision Group
self.Player:SetCollisionGroup(COLLISION_GROUP_PLAYER)
self.Player:SetSolid(SOLID_VPHYSICS)
-- Prop Stuff
self.Player.Data.Prop = ents.Create("ph_prop")
self.Player.Data.Prop:SetOwner(self.Player)
self.Player.Data.Prop:Spawn()
self.Player:DeleteOnRemove(self.Player.Data.Prop)
self.Player.Data.PropContraint = constraint.NoCollide(self.Player, self.Player.Data.Prop, 0, 0)
-- Assign Hands (Auto Networked Sync!)
local oldhands = self.Player:GetHands()
@@ -75,35 +69,11 @@ function CLASS:Spawn()
end
-- Death
function CLASS:DoDeath(attacker, dmginfo)
BaseClass.DoDeath(self, attacker, dmginfo)
if GAMEMODE.Config:DebugLog() then
if (IsValid(attacker) && attacker:IsPlayer() && attacker != self.Player) then
print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") killed by '"..attacker:GetName().."' (SteamID: "..attacker:SteamID()..").")
end
end
if (!IsValid(attacker)) then return end
if (!attacker:IsPlayer()) then return end
if (attacker:Team() == self.Player:Team()) then return end
if (attacker:Team() == GAMEMODE.Teams.Seekers) then
if GAMEMODE.Config:DebugLog() then
print("Prop Hunt: Seeker '"..attacker:GetName().."' (SteamID: "..attacker:SteamID()..") gained "..GAMEMODE.Config.Seeker:HealthBonus().." health for killing Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..").")
end
local newhealth = attacker:Health() + GAMEMODE.Config.Seeker:HealthBonus()
if (newhealth > attacker:GetMaxHealth()) then newhealth = attacker:GetMaxHealth() end
attacker:SetHealth(newhealth)
end
end
function CLASS:PostDeath()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") end
function CLASS:PostDeath(attacker, dmginfo)
print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.")
BaseClass.PostDeath(self, inflictor, attacker)
-- Delete Hands Model
if IsValid(self.Player.Data.PropConstraint) then
self.Player.Data.PropConstraint:Remove()
end
if IsValid(self.Player:GetHands()) then
self.Player:GetHands():Remove()
end
@@ -136,9 +106,7 @@ function CLASS:DeathThink()
end
-- Visible Stuff
function CLASS:SetModel()
self.Player:SetModel("models/Gibs/Antlion_gib_small_3.mdl")
end
function CLASS:SetModel() self.Player:SetModel("models/Gibs/Antlion_gib_small_3.mdl") end -- does "" even work?
-- Interaction
function CLASS:Use(ent)
@@ -147,17 +115,16 @@ function CLASS:Use(ent)
end
-- Allow interacting while crouched instead of turning into the prop.
if (self.Player:Crouching()) then
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") interacted with "..ent:GetClass().." ("..ent:GetModel()..").") end
if (self.Player:Crouching()) then
return true
end
-- Check Lists and other Parameters
if (!table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass())) -- Class is not Whitelisted
|| (table.HasValue(GAMEMODE.Config.Lists:ModelBlacklist(), ent:GetModel())) -- Model is Blacklisted
|| !((ent:GetPhysicsObject()) && (ent:GetPhysicsObject():IsValid())) -- Entity doesn't have Physics
if (!table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass()))-- Class is not Whitelisted
|| (GAMEMODE.Config.Lists.ModelBlacklist[ent:GetModel()]) -- Model is Blacklisted
|| !((ent:GetPhysicsObject()) && (ent:GetPhysicsObject():IsValid())) -- Entity doesn't have Physics
then
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") attempted to turn into "..ent:GetClass().." ("..ent:GetModel()..").") end
print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") attempted to turn into "..ent:GetClass().." ("..ent:GetModel()..").")
return true -- Use instead of erroring.
end
@@ -188,77 +155,84 @@ function CLASS:Use(ent)
self.Player:SetMaxHealth(maxhealth)
end
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") turned into "..ent:GetClass().." ("..ent:GetModel()..").") end
print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") turned into "..ent:GetClass().." ("..ent:GetModel()..").")
end
function CLASS:AllowPickup(ent) return true end
-- Menu Buttons
function CLASS:ShowSpare1()
if BaseClass.ShowSpare1(self) then return end
-- Play a taunt
local tauntList = GAMEMODE.Config.Taunt:Hiders()
local index = math.random(#tauntList)
self.Player:EmitSound(tauntList[index], SNDLVL_NORM, 100, 1, CHAN_VOICE)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") taunted with sound '"..tauntList[index].."'.") end
end
-- ------------------------------------------------------------------------- --
--! Shared
-- ------------------------------------------------------------------------- --
if SERVER then
function CLASS:FindUseEntity(defEnt)
return self.Player:FindUseEntity()
end
function CLASS:Tick(mv)
if (self.Player.Data == nil) then return end
-- Selection Halo
if (GAMEMODE.Config.SelectionHalo:Allow()) && (!GAMEMODE.Config.SelectionHalo:Approximate()) then
if (self.Player.Data.SelectionHaloTime == nil) then
self.Player.Data.SelectionHaloTime = CurTime()
elseif ((CurTime() - self.Player.Data.SelectionHaloTime) > GAMEMODE.Config.SelectionHalo:Interval()) then
self.Player.Data.SelectionHaloTime = CurTime()
local ent = self.Player:FindUseEntity()
if (IsValid(ent)
&& table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass())
&& !table.HasValue(GAMEMODE.Config.Lists:ModelBlacklist(), ent:GetModel())) then
self.Player:SetNWEntity("SelectionHalo", ent)
else
self.Player:SetNWBool("SelectionHalo", false)
end
end
end
end
end
function CLASS:Alive() return true end
-- ------------------------------------------------------------------------- --
--! Client-Side
-- ------------------------------------------------------------------------- --
function CLASS:ClientSpawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
print("Prop Hunt CL: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
BaseClass.ClientSpawn(self, self.Player)
self.Player:SetRenderMode(RENDERMODE_TRANSALPHA)
end
function CLASS:ShouldDrawLocal()
if (self.Player.Data.ViewDistance or 0) >= 10 then
return false
end
function CLASS:CalcView(camdata)
-- ThirdPerson Settings (ToDo: client config maybe?)
local maxViewDist = 100
local viewDist = self.Player.Data.ViewDistance or 0
-- First/Third
if (self.Player.Data.ThirdPerson) then
if (IsValid(self.Player:GetHands())) then
self.Player:GetHands():SetRenderMode(RENDERMODE_TRANSALPHA)
self.Player:GetHands():SetColor(Color(255, 255, 255, 127))
end
-- Incremental Distance instead of instant.
viewDist = math.Clamp(viewDist * 0.95 + maxViewDist * 0.05, 0, maxViewDist) -- Zoom Out
else
if (IsValid(self.Player:GetHands())) then
self.Player:GetHands():SetRenderMode(RENDERMODE_TRANSALPHA)
self.Player:GetHands():SetColor(Color(255, 255, 255, 0))
end
viewDist = math.Clamp(viewDist * 0.95, 0, maxViewDist) -- Zoom In
end
return (self.Player.Data.ViewDistance or 0) >= 10
-- Trace from Player to would-be camera position
local trace = {
start = camdata.origin,
endpos = camdata.origin - (camdata.angles:Forward() * viewDist),
--filter = { "worldspawn", "ph_prop" },
filter = function(ent)
local filter = { "worldspawn", "ph_prop" }
if (ent:IsPlayer())
|| (table.HasValue(filter, ent:GetClass()))
|| (ent == LocalPlayer()) || (ent == LocalPlayer():GetHands()) then
return false
end
return true
end
}
local result = util.TraceLine(trace)
-- The Camera has a Sphere radius of 10.
if (result.Hit) then -- Configurable?
viewDist = math.Clamp(result.HitPos:Distance(camdata.origin), 0, maxViewDist)
end
-- Store ViewDistance
self.Player.Data.ViewDistance = viewDist
-- Adjust CamData
camdata.origin = camdata.origin - (camdata.angles:Forward() * math.Clamp(viewDist - 10, 0, maxViewDist))
camdata.drawviewer = false
-- Return
return camdata
end
-- Register
@@ -44,24 +44,20 @@ CLASS.DropWeaponOnDie = true
-- ------------------------------------------------------------------------- --
-- Spawn
function CLASS:Spawn()
if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
BaseClass.Spawn(self)
-- Sprinting
if (GAMEMODE.Config:Sprinting()) then
self.Player:SetRunSpeed(self.WalkSpeed)
end
-- Settings
self.Player:SetMaxHealth(GAMEMODE.Config.Seeker:HealthMax())
self.Player:SetHealth(GAMEMODE.Config.Seeker:Health())
self.Player:SetRenderMode(RENDERMODE_NORMAL)
self.Player:SetColor(Color(255,255,255,255))
-- Speed and Jump Power
self.Player:SetWalkSpeed(GAMEMODE.Config.Seeker:WalkSpeed())
if (GAMEMODE.Config.Seeker:Sprint()) then
self.Player:SetRunSpeed(GAMEMODE.Config.Seeker:SprintSpeed())
else
self.Player:SetRunSpeed(GAMEMODE.Config.Seeker:WalkSpeed())
end
self.Player:SetJumpPower(GAMEMODE.Config.Seeker:JumpPower())
-- Hull & View Offset
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,64), Vector(0,0,32))
@@ -89,79 +85,32 @@ function CLASS:Loadout()
end
-- Damage
function CLASS:ShouldTakeDamage(attacker)
if (IsValid(attacker)) then
if (attacker:IsPlayer()) then
if (attacker:Team() == self.Player:Team()) then
local ffmode = GetConVarNumber("mp_friendlyfire")
if (ffmode == 0) then -- Not Allowed
return false
end
end
end
end
return true
end
function CLASS:Damage(victim, attacker, healthRemaining, damageDealt)
if ((victim != attacker) && victim:IsPlayer() && attacker:IsPlayer() && (attacker:Team() == victim:Team())) then
if (GAMEMODE.Config:DebugLog()) then
print("Prop Hunt: Seeker '"..attacker:GetName().."' (SteamID: "..attacker:SteamID()..") damaged seeker '"..victim:GetName().."' (SteamID: "..victim:SteamID()..") with "..damageDealt.." damage.")
end
end
end
function CLASS:Hurt(victim, attacker, healthRemaining, damageTaken)
if ((victim != attacker) && victim:IsPlayer() && attacker:IsPlayer() && (attacker:Team() == victim:Team())) then
if (GAMEMODE.Config:DebugLog()) then
print("Prop Hunt: Seeker '"..victim:GetName().."' (SteamID: "..victim:SteamID()..") was hurt by seeker '"..attacker:GetName().."' (SteamID: "..attacker:SteamID()..") with "..damageTaken.." damage.")
end
if (GetConVarNumber("mp_friendlyfire") == 2) then
victim:SetHealth(healthRemaining + damageTaken)
attacker:TakeDamage(damageTaken, attacker, attacker)
print("Prop Hunt: Seeker '"..victim:GetName().."' (SteamID: "..victim:SteamID()..") reflected "..damageTaken.." to seeker '"..attacker:GetName().."' (SteamID: "..attacker:SteamID()..").")
end
end
end
function CLASS:Damage(victim, attacker, healthRemaining, damageDealt) end
function CLASS:DamageEntity(ent, att, dmg)
if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") damaged entity "..ent:GetClass()..".") end
if (GAMEMODE:GetRoundState() != GAMEMODE.States.Seek) then return end
if (!IsValid(ent) || !IsValid(att)) then return end
if (att == ent) then return end
print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") damaged entity "..ent:GetClass()..".")
-- Only take damage during this phase.
if IsValid(ent) && (!(ent:IsPlayer())) then
if (ent:GetClass() == "ph_prop") then
ent:GetOwner():TakeDamageInfo(dmg)
self.Player.Data.RandomWeight = self.Player.Data.RandomWeight - 1
elseif (ent:GetClass() == "func_breakable") then
elseif (ent:GetClass() == "prop_ragdoll") then
else
att:TakeDamage(GAMEMODE.Config.Seeker:HealthPenalty(), ent, ent)
if (GAMEMODE:GetRoundState() == GAMEMODE.States.Seek) then
if IsValid(ent) && (!(ent:IsPlayer())) then
if (ent:GetClass() == "ph_prop") then
ent:GetOwner():TakeDamageInfo(dmg)
elseif (ent:GetClass() == "func_breakable") then -- ToDo: Make Configurable which entities don't hurt?
else
att:TakeDamage(GAMEMODE.Config.Seeker:HealthPenalty(), ent, ent)
end
end
end
end
-- Death
function CLASS:DoDeath(attacker, dmginfo)
BaseClass.DoDeath(self, attacker, dmginfo)
if GAMEMODE.Config:DebugLog() then
if (IsValid(attacker) && attacker:IsPlayer() && attacker != self.Player) then
print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") killed by '"..attacker:GetName().."' (SteamID: "..attacker:SteamID()..").")
end
end
function CLASS:Death(inflictor, attacker)
BaseClass.Death(self, inflictor, attacker)
if SERVER then
self.Player:SetShouldServerRagdoll(true)
--self.Player:CreateRagdoll()
end
self.Player:CreateRagdoll()
end
function CLASS:PostDeath()
if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") end
print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.")
BaseClass.PostDeath(self, inflictor, attacker)
self.Player:UnLock()
@@ -199,27 +148,11 @@ function CLASS:AllowPickup(ent) return true end
function CLASS:CanPickupItem(ent) return true end
function CLASS:CanPickupWeapon(ent) return true end
-- Menu Buttons
function CLASS:ShowSpare1()
if BaseClass.ShowSpare1(self) then return end
-- Play a taunt
local tauntList = GAMEMODE.Config.Taunt:Seekers()
local index = math.random(#tauntList)
self.Player:EmitSound(tauntList[index], SNDLVL_NORM, 100, 1, CHAN_VOICE)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") taunted with sound '"..tauntList[index].."'.") end
end
-- ------------------------------------------------------------------------- --
--! Shared
-- ------------------------------------------------------------------------- --
function CLASS:Alive() return true end
-- ------------------------------------------------------------------------- --
--! Client-Side
-- ------------------------------------------------------------------------- --
function CLASS:ClientSpawn()
if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt CL: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
print("Prop Hunt CL: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
BaseClass.ClientSpawn(self)
end
@@ -248,7 +181,53 @@ function CLASS:HUDPaint()
end
function CLASS:ShouldDrawLocal()
return (self.Player.Data.ViewDistance or 0) >= 10
return self.Player.Data.ThirdPerson
end
function CLASS:CalcView(camdata)
-- ThirdPerson Settings (ToDo: client config maybe?)
local maxViewDist = 100
local viewDist = self.Player.Data.ViewDistance or 0
-- First/Third
if (self.Player.Data.ThirdPerson) then
viewDist = math.Clamp(viewDist * 0.95 + maxViewDist * 0.05, 0, maxViewDist) -- Zoom Out
else
viewDist = math.Clamp(viewDist * 0.95, 0, maxViewDist) -- Zoom In
end
-- Trace from Player to would-be camera position
local trace = {
start = camdata.origin,
endpos = camdata.origin - (camdata.angles:Forward() * viewDist),
--filter = { "worldspawn", "ph_prop" },
filter = function(ent)
local filter = { "worldspawn", "ph_prop" }
if (ent:IsPlayer())
|| (table.HasValue(filter, ent:GetClass()))
|| (ent == LocalPlayer()) || (ent == LocalPlayer():GetHands()) then
return false
end
return true
end
}
local result = util.TraceLine(trace)
-- The Camera has a Sphere radius of 10.
if (result.Hit) then -- Configurable?
viewDist = math.Clamp(result.HitPos:Distance(camdata.origin), 0, maxViewDist)
end
-- Store ViewDistance
self.Player.Data.ViewDistance = viewDist
-- Adjust CamData
camdata.origin = camdata.origin - (camdata.angles:Forward() * math.Clamp(viewDist - 10, 0, maxViewDist))
--camdata.drawviewer = false
-- Return
return camdata
end
-- Register
@@ -35,7 +35,7 @@ CLASS.UseVMHands = false -- Uses viewmodel hands
-- ------------------------------------------------------------------------- --
-- Spawn
function CLASS:Spawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
BaseClass.Spawn(self)
self.Player:Spectate(OBS_MODE_ROAMING)
@@ -48,7 +48,7 @@ end
-- Death
function CLASS:PostDeath(inflictor, attacker)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") end
print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.")
BaseClass.PostDeath(self, inflictor, attacker)
self.Player:Spectate(OBS_MODE_NONE)
@@ -77,10 +77,9 @@ function CLASS:CanPickupItem(ent) return false end
--! Client-Side
-- ------------------------------------------------------------------------- --
function CLASS:ClientSpawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
print("Prop Hunt CL: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
end
function CLASS:ShouldDrawLocal() return false end
function CLASS:CalcView(camdata) return camdata end
player_manager.RegisterClass( "Spectator", CLASS, "Default")
@@ -0,0 +1,549 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
--! Initialize configuration table.
GM.Config = { }
GM.Config.ConVars = {}
-- ------------------------------------------------------------------------- --
--! Basic Settings
-- ------------------------------------------------------------------------- --
-- Debug Mode
GM.Config.ConVars.Debug = CreateConVar("ph_debug", 0, FCVAR_CHEAT + FCVAR_REPLICATED)
function GM.Config:Debug()
return self.ConVars.Debug:GetBool()
end
-- Game Mode (See sh_init.lua)
GM.Config.ConVars.GameMode = CreateConVar("ph_gamemode", GM.Modes.Original, FCVAR_REPLICATED)
function GM.Config:GameMode()
return self.ConVars.GameMode:GetInt()
end
-- Timelimit in minutes
GM.Config.ConVars.TimeLimit = GetConVar("mp_timelimit")
function GM.Config:TimeLimit()
return self.ConVars.TimeLimit:GetFloat()
end
-- Enable Sprinting?
GM.Config.ConVars.Sprinting = CreateConVar("ph_sprinting", 0, FCVAR_REPLICATED)
function GM.Config:Sprinting()
return self.ConVars.Sprinting:GetBool()
end
-- Taunt Cooldown (Seconds)
GM.Config.ConVars.TauntCoolDown = CreateConVar("ph_tauntcooldown", 5, FCVAR_REPLICATED)
function GM.Config:TauntCoolDown()
return self.ConVars.TauntCoolDown:GetFloat()
end
-- ------------------------------------------------------------------------- --
--! Round Settings
-- ------------------------------------------------------------------------- --
GM.Config.Round = {}
GM.Config.Round.ConVars = {}
-- How many rounds should the gamemode attempt to fit into the map timelimit, if there is any?
GM.Config.Round.ConVars.Amount = CreateConVar("ph_round_limit", 10, FCVAR_REPLICATED)
function GM.Config.Round:Amount()
return self.ConVars.Amount:GetInt()
end
-- Round Time Limit (Seconds, Default 3 minutes)
GM.Config.Round.ConVars.Time = CreateConVar("ph_round_timelimit", 180, FCVAR_REPLICATED)
function GM.Config.Round:Time()
return self.ConVars.Time:GetInt() - GAMEMODE.Config.Round:BlindTime()
end
-- For how many seconds are the Seekers blinded? (Seconds)
GM.Config.Round.ConVars.BlindTime = CreateConVar("ph_round_blindtime", 30, FCVAR_REPLICATED, "How long are hunters blinded? (positive values will be inside the round time limit, negative will add to the round time limit)")
function GM.Config.Round:BlindTime()
return self.ConVars.BlindTime:GetInt()
end
-- ------------------------------------------------------------------------- --
--! Seeker Settings
-- ------------------------------------------------------------------------- --
GM.Config.Seeker = {}
GM.Config.Seeker.ConVars = {}
GM.Config.Seeker.ConVars.Health = CreateConVar("ph_seeker_health", 100, FCVAR_REPLICATED)
function GM.Config.Seeker:Health()
return self.ConVars.Health:GetInt()
end
GM.Config.Seeker.ConVars.HealthMax = CreateConVar("ph_seeker_health_max", 100, FCVAR_REPLICATED)
function GM.Config.Seeker:HealthMax()
return self.ConVars.HealthMax:GetInt()
end
GM.Config.Seeker.ConVars.HealthBonus = CreateConVar("ph_seeker_health_bonus", 20, FCVAR_REPLICATED)
function GM.Config.Seeker:HealthBonus()
return self.ConVars.HealthBonus:GetInt()
end
GM.Config.Seeker.ConVars.HealthPenalty = CreateConVar("ph_seeker_health_penalty", 5, FCVAR_REPLICATED)
function GM.Config.Seeker:HealthPenalty()
return self.ConVars.HealthPenalty:GetInt()
end
GM.Config.Seeker.ConVars.Weapons = CreateConVar("ph_seeker_weapons", "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun", FCVAR_REPLICATED)
function GM.Config.Seeker:Weapons()
return string.Split(self.ConVars.Weapons:GetString(), ",")
end
GM.Config.Seeker.ConVars.Ammo = CreateConVar("ph_seeker_ammo", "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64", FCVAR_REPLICATED)
function GM.Config.Seeker:Ammo()
return string.Split(self.ConVars.Ammo:GetString(), ",")
end
-- ------------------------------------------------------------------------- --
--! Hider Settings
-- ------------------------------------------------------------------------- --
GM.Config.Hider = {}
GM.Config.Hider.ConVars = {}
GM.Config.Hider.ConVars.Health = CreateConVar("ph_hider_health", 100, FCVAR_REPLICATED)
function GM.Config.Hider:Health()
return self.ConVars.Health:GetInt()
end
GM.Config.Hider.ConVars.HealthMax = CreateConVar("ph_hider_health_max", 100, FCVAR_REPLICATED)
function GM.Config.Hider:HealthMax()
return self.ConVars.HealthMax:GetInt()
end
GM.Config.Hider.ConVars.HealthScaling = CreateConVar("ph_hider_health_scaling", 100, FCVAR_REPLICATED)
function GM.Config.Hider:HealthScaling()
return self.ConVars.HealthScaling:GetBool()
end
GM.Config.Hider.ConVars.HealthScalingMax = CreateConVar("ph_hider_health_scaling_max", 200, FCVAR_REPLICATED)
function GM.Config.Hider:HealthScalingMax()
return self.ConVars.HealthScalingMax:GetInt()
end
-- ------------------------------------------------------------------------- --
--! Whitelist & Blacklist
-- ------------------------------------------------------------------------- --
GM.Config.Lists = {}
GM.Config.Lists.ConVars = {}
GM.Config.Lists.ConCmds = {}
GM.Config.Lists.ConVars.ClassWhitelist = CreateConVar("ph_list_class_whitelist", "prop_physics,prop_physics_multiplayer,prop_physics_respawnable", FCVAR_REPLICATED)
function GM.Config.Lists:ClassWhitelist()
return string.Split(self.ConVars.ClassWhitelist:GetString(), ",")
end
-- Use Abuse Blacklist
GM.Config.Lists.ConVars.AbuseBlacklist = CreateConVar("ph_list_abuse_blacklist", "func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable", FCVAR_REPLICATED)
function GM.Config.Lists:AbuseBlacklist()
return string.Split(self.ConVars.AbuseBlacklist:GetString(), ",")
end
-- Model Blacklist
GM.Config.Lists.ModelBlacklist = {}
GM.Config.Lists.ModelBlacklist["models/props/cs_assault/dollar.mdl"] = true
GM.Config.Lists.ModelBlacklist["models/props/cs_assault/money.mdl"] = true
GM.Config.Lists.ModelBlacklist["models/props/cs_office/snowman_arm.mdl"] = true
GM.Config.Lists.ModelBlacklist["models/props/cs_office/projector_remote.mdl"] = true
--GM.Config.Lists.ModelBlacklist["models/props_junk/garbage_plasticbottle001a.mdl"] = true
GM.Config.Lists.ConCmds.ModelBlacklistList = concommand.Add("ph_list_model_blacklist_list", function(ply, cmd, args, argStr)
print("Model Blacklist:")
for k,v in pairs(GAMEMODE.Config.Lists.ModelBlacklist) do
print(" "..k)
end
end, "List all blacklisted models.")
GM.Config.Lists.ConCmds.ModelBlacklistClear = concommand.Add("ph_list_model_blacklist_list", function(ply, cmd, args, argStr)
GM.Config.Lists.ModelBlacklist = {}
end, "Clear blacklisted models.")
GM.Config.Lists.ConCmds.ModelBlacklistAdd = concommand.Add("ph_list_model_blacklist_add", function(ply, cmd, args, argStr)
if (table.count(args) > 0) then
GAMEMODE.Config.Lists.ModelBlacklist[args[1]] = true
else
print("Missing model name")
end
end, "Add a new blacklisted model.")
GM.Config.Lists.ConCmds.ModelBlacklistRemove = concommand.Add("ph_list_model_blacklist_remove", function(ply, cmd, args, argStr)
if (table.count(args) > 0) then
GAMEMODE.Config.Lists.ModelBlacklist[args[1]] = nil
else
print("Missing model name")
end
end, "Removes a blacklisted model.")
-- ------------------------------------------------------------------------- --
--! Taunts
-- ------------------------------------------------------------------------- --
-- GM.Config.Taunts = {
-- Seeker = { },
-- Hider = { },
-- }
-- -- Taunts.Clear()
-- --@desc: Clears the current taunt list.
-- GM.Config.Taunts.Clear = function()
-- this.Seeker = {}
-- this.Hider = {}
-- end
-- -- Taunts.Load(sTauntListFile)
-- --@desc: Loads the taunt list from disk.
-- --@param:
-- -- sTauntListFile - A string containing the path to the taunt list to load.
-- --@return: true or false depending on success.
-- GM.Config.Taunts.Load = function(sTauntListFile)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Loading taunt list from file '"..sTauntListFile.."'...") end
-- -- Safeguard against idiots.
-- if type(sTauntListFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: <sTauntListFile> is not a string.") end
-- return false
-- end
-- -- Given file must exist for us to continue.
-- if ! file.Exists(sTauntListFile, "GAME") then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: File not found.") end
-- return false
-- end
-- -- Read the file and check if it's empty.
-- sTauntListData = file.Read(sTauntListFile, "GAME")
-- if sTauntListData == "" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: File is empty.") end
-- return false
-- end
-- -- Convert JSON to a table for us to use.
-- sTauntList = util.JSONToTable(sTauntListData)
-- -- Is it nil? Then it's not valid JSON
-- if sTauntList == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: File contains invalid JSON.") end
-- return false
-- end
-- -- Finally, append the taunt lists.
-- if sTauntList.Seeker != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Adding Seeker taunts...") end
-- for k,v in pairs(sTauntList.Seeker) do
-- GAMEMODE.Taunts.Seeker[k] = v
-- end
-- end
-- if sTauntList.Hider != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Adding Hider taunts...") end
-- for k,v in pairs(sTauntList.Hider) do
-- GAMEMODE.Taunts.Hider[k] = v
-- end
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Complete.") end
-- return true
-- end
-- -- Taunts.Save(sTauntListFile)
-- --@desc: Saves the current taunt list to disk.
-- --@param:
-- -- sTauntListFile - A string containing the path to the file to save to.
-- --@return: true or false depending on success.
-- GM.Config.Taunts.Save = function(sTauntListFile)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Saving taunt list to file '"..sTauntListFile.."'...") end
-- -- Safeguard against idiots.
-- if type(sTauntListFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: <sTauntListFile> is not a string.") end
-- return false
-- end
-- -- File must not be nil, otherwise we can't write to it.
-- if sTauntListFile == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: No file given.") end
-- return false
-- end
-- -- Convert our taunt table to JSON.
-- sTauntListData = util.TableToJSON(GAMEMODE.Taunts);
-- if sTauntListData == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Corrupted GAMEMODE table.") end
-- return false
-- end
-- -- Write out JSON out to file
-- if ! file.Write(sTauntListFile, sTauntListData) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Failed to write to file.") end
-- return false
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Complete.") end
-- return true
-- end
-- -- Taunts.Add(sTauntName, sSoundFile, iTeamID, mPropFilter)
-- --@desc: Registers a new taunt with the given name, file, team and filter.
-- --@param:
-- -- sTauntName - The unique name of the taunt.
-- -- sSoundFile - A sound file to play when this taunt is selected.
-- -- iTeamID - The team that should receive the taunt or nil for all teams.
-- -- mPropFilter - A string or a table containing strings for props that should be able to use this taunt.
-- --@return: true or false depending on success.
-- GM.Config.Taunts.Add = function(sTauntName, sSoundFile, iTeamID, mPropFilter)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Adding new taunt '"..sTauntName.."'...") end
-- -- Safeguard against idiots.
-- if type(sTauntName) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <sTauntName> is not a string.") end
-- return false
-- end
-- if type(sSoundFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <sSoundFile> is not a string.") end
-- return false
-- end
-- if (type(iTeamID) != "number" && iTeamID != nil) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <iTeamID> is not a number or nil.") end
-- return false
-- end
-- if (type(mPropFilter) != "string" && type(mPropFilter) != "table" && mPropFilter != nil) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <mPropFilter> is not a string, table or nil.") end
-- return false
-- end
-- -- Check if the sound file actually exists
-- if !file.Exists("sound/"..sSoundFile, "GAME") then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: File '"..sSoundFile.."' does not exist.") end
-- return false
-- end
-- -- Make sure that our prop filter is a table listing the props it's supposed to work for.
-- if (mPropFilter == nil) then
-- mPropFilter = { }
-- elseif type(mPropFilter) == "string" then
-- mPropFilter = { mPropFilter }
-- end
-- -- Prepare Taunt table
-- Taunt = {
-- File = sSoundFile,
-- Filter = mPropFilter
-- }
-- -- If iTeamID is nil, both teams will receive the taunt.
-- if iTeamID == nil then
-- GAMEMODE.Taunts.Seeker[sTauntName] = Taunt
-- GAMEMODE.Taunts.Hider[sTauntName] = Taunt
-- else
-- -- Make sure that the team is valid.
-- if ! team.Valid(iTeamID) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Team "..iTeamID.."' does not exist.") end
-- return false
-- end
-- if (iTeamID == TEAM_SEEKERS) then
-- GAMEMODE.Taunts.Seeker[sTauntName] = Taunt
-- elseif (iTeamID == TEAM_HIDERS) then
-- GAMEMODE.Taunts.Hider[sTauntName] = Taunt
-- else
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Team "..iTeamID.."' can't have taunts.") end
-- return false
-- end
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Complete.") end
-- return true
-- end
-- -- Taunts.Remove(sTauntName, iTeamID)
-- --@desc: Removes a registered taunt with the given name and team.
-- --@param:
-- -- sTauntName - The unique name of the taunt.
-- -- iTeamID - The team that the taunt should be removed from or nil for all teams.
-- --@return: true or false depending on success.
-- GM.Config.Taunts.Remove = function(sTauntName, iTeamID)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Removing taunt '"..sTauntName.."'...") end
-- -- Safeguard against idiots.
-- if type(sTauntName) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: <sTauntName> is not a string.") end
-- return false
-- end
-- if (type(iTeamID) != "number" && iTeamID != nil) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: <iTeamID> is not a number or nil.") end
-- return false
-- end
-- -- if iTeamID is nil, both teams will have the taunt removed.
-- if (iTeamID == nil) then
-- GAMEMODE.Taunts.Seeker[sTauntName] = nil
-- GAMEMODE.Taunts.Hider[sTauntName] = nil
-- else
-- -- Make sure we have a valid Team.
-- if ! team.Valid(iTeamID) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Team "..iTeamID.."' does not exist.") end
-- return false
-- end
-- if iTeamID == TEAM_SEEKERS then
-- GAMEMODE.Taunts.Seeker[sTauntName] = nil
-- elseif iTeamID == TEAM_HIDERS then
-- GAMEMODE.Taunts.Hider[sTauntName] = nil
-- else
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Team "..iTeamID.."' can't have taunts.") end
-- return false
-- end
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Complete.") end
-- return true
-- end
-- -- ToDo: Taunts.Get(iTeamID, sPropName)
-- --! Announcers (Round Start, Unblind, Win, Loss)
-- GM.Config.Announcers = {
-- Start = { },
-- Unblind = { },
-- Win = { },
-- Loss = { }
-- }
-- -- Announcers.Clear()
-- --@desc: Clears the current announcer list.
-- GM.Config.Announcers.Clear = function()
-- Announcers.Start = { }
-- Announcers.Unblind = { }
-- Announcers.Win = { }
-- Announcers.Loss = { }
-- end
-- -- Announcers.Load(sAnnouncerListFile)
-- --@desc: Tries to load the given announcer list.
-- --@param:
-- -- sAnnouncerListFile - A string containing the path to the announcer list to load.
-- --@return: true or false depending on success.
-- GM.Config.Announcers.Load = function(sAnnouncerListFile)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Loading announcer list from file '"..sAnnouncerListFile.."'...") end
-- -- Safeguard against idiots.
-- if type(sAnnouncerListFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: <sAnnouncerListFile> is not a string.") end
-- return false
-- end
-- -- Given file must exist for us to continue.
-- if ! file.Exists(sAnnouncerListFile, "GAME") then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: File not found.") end
-- return false
-- end
-- -- Read the file and check if it's empty.
-- sAnnouncerListData = file.Read(sAnnouncerListFile, "GAME")
-- if sAnnouncerListData == "" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: File is empty.") end
-- return false
-- end
-- -- Convert JSON to a table for us to use.
-- sAnnouncerList = util.JSONToTable(sAnnouncerListData)
-- -- Is it nil? Then it's not valid JSON
-- if sAnnouncerList == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: File contains invalid JSON.") end
-- return false
-- end
-- -- Finally, insert the announcer lists.
-- if sAnnouncerList.Start != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Start announcers...") end
-- for k,v in pairs(sAnnouncerList.Start) do
-- GAMEMODE.Announcers.Start[k] = v
-- end
-- end
-- if sAnnouncerList.Unblind != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Unblind announcers...") end
-- for k,v in pairs(sAnnouncerList.Unblind) do
-- GAMEMODE.Announcers.Unblind[k] = v
-- end
-- end
-- if sAnnouncerList.Win != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Win announcers...") end
-- for k,v in pairs(sAnnouncerList.Win) do
-- GAMEMODE.Announcers.Win[k] = v
-- end
-- end
-- if sAnnouncerList.Loss != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Loss announcers...") end
-- for k,v in pairs(sAnnouncerList.Loss) do
-- GAMEMODE.Announcers.Loss[k] = v
-- end
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Complete.") end
-- return true
-- end
-- -- Announcers.Save(sAnnouncerListFile)
-- --@desc: Saves the current taunt list to disk.
-- --@param:
-- -- sAnnouncerListFile - A string containing the path to the file to save to.
-- --@return: true or false depending on success.
-- GM.Config.Announcers.Save = function(sAnnouncerListFile)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Saving announcer list to file '"..sAnnouncerListFile.."'...") end
-- -- Safeguard against idiots.
-- if type(sAnnouncerListFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: <sAnnouncerListFile> is not a string.") end
-- return false
-- end
-- -- File must not be nil, otherwise we can't write to it.
-- if sAnnouncerListFile == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: No file given.") end
-- return false
-- end
-- -- Convert our taunt table to JSON.
-- sAnnouncerListData = util.TableToJSON(GAMEMODE.Announcers);
-- if sAnnouncerListData == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Corrupted GAMEMODE table.") end
-- return false
-- end
-- -- Write out JSON out to file
-- if ! file.Write(sAnnouncerListFile, sAnnouncerListData) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Failed to write to file.") end
-- return false
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Complete.") end
-- return true
-- end
-- -- ToDo: Announcers.Add
-- -- ToDo: Announcers.Remove
-- -- ToDo: Announcers.Get(iType)
@@ -22,6 +22,42 @@
SOFTWARE.
--]]
AddCSLuaFile("sh_init.lua")
AddCSLuaFile("cl_init.lua")
include "sh_init.lua"
GM.RoundManager = {}
GM.RoundManager.State = nil;
GM.RoundManager.NextState = nil;
function GM.RoundManager:Tick(...)
if (self.State != nil) then
if (self.State.Tick != nil) then
self.State:Tick(...)
end
end
-- Advance States
if (self.NextState != self.State) then
-- Call OnLeave(NewState)
if (self.State != nil) then
if (self.State.OnLeave != nil) then
self.State:OnLeave(self.NextState)
end
end
-- Call OnEnter(OldState)
if (self.NextState != nil) then
if (self.NextState.OnEnter != nil) then
self.NextState:OnEnter(self.State)
end
end
-- Set State
self.State = self.NextState
end
end
function GM.RoundManager:GetState()
return self.State
end
function GM.RoundManager:SetState(State)
self.NextState = State
end
@@ -1,7 +1,7 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -22,28 +22,29 @@
SOFTWARE.
--]]
include "base.lua"
StateHide = {}
local CLASS = state("Hide", GM.States.Hide)
function CLASS:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StateHide: OnEnter") end
function StateHide:OnEnter(OldState)
if GAMEMODE.Config:Debug() then print("StateHide: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.Hide)
-- Round Data
GAMEMODE.Data.RoundTime = math.abs(GAMEMODE.Config.Round:BlindTime())
GAMEMODE.Data.RoundStartTime = CurTime()
GAMEMODE:SetRoundTime(GAMEMODE.Data.RoundTime)
end
function CLASS:Tick()
function StateHide:Tick()
-- Update Game Time
local deltaTime = (CurTime() - GAMEMODE.Data.RoundStartTime)
GAMEMODE.Data.RoundTime = GAMEMODE.Config.Round:Time() - deltaTime
GAMEMODE.Data.StateTime = math.abs(GAMEMODE.Config.Round:BlindTime()) - deltaTime
GAMEMODE.Data.RoundTime = math.abs(GAMEMODE.Config.Round:BlindTime()) - (CurTime() - GAMEMODE.Data.RoundStartTime)
GAMEMODE:SetRoundTime(GAMEMODE.Data.RoundTime)
GAMEMODE:SetRoundStateTime(GAMEMODE.Data.StateTime)
-- Advance to Seeking State
if (GAMEMODE.Data.StateTime <= 0) then
if (GAMEMODE.Data.RoundTime <= 0) then
if GAMEMODE.Config:Debug() then print("StateHide: Advancing to Seek stage.") end
RoundManager:SetState(StateSeek)
GAMEMODE.RoundManager:SetState(StateSeek)
end
-- Freeze Seekers
@@ -56,11 +57,6 @@ function CLASS:Tick()
-- ToDo: Logic for more game modes here?
end
function CLASS:OnLeave(NewState)
function StateHide:OnLeave(NewState)
if GAMEMODE.Config:Debug() then print("StateHide: OnLeave") end
-- Fretta Hooks
hook.Run("PropHuntUnblind")
end
_G["StateHide"] = CLASS
end
@@ -1,37 +1,39 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- ------------------------------------------------------------------------- --
--! Gamemode Information
-- ------------------------------------------------------------------------- --
GM.Name = "Prop Hunt Extended"
GM.Author = "Michael Fabian 'Xaymar' Dirks"
GM.Email = "info@xaymar.com"
GM.Website = "http://xaymar.com/"
GM.TeamBased = true
GM.AllowAutoTeam = true
GM.SecondsBetweenTeamSwitches = 10
DeriveGamemode("prophuntextended")
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
StatePostMatch = {}
function StatePostMatch:OnEnter(OldState)
if GAMEMODE.Config:Debug() then print("StatePostMatch: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PostMatch)
end
function StatePostMatch:Tick()
-- Advance State
GAMEMODE.RoundManager:SetState(StatePreMatch)
end
function StatePostMatch:OnLeave(NewState)
if GAMEMODE.Config:Debug() then print("StatePostMatch: OnLeave") end
end
@@ -1,7 +1,7 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -22,37 +22,38 @@
SOFTWARE.
--]]
include "base.lua"
StatePostRound = {}
local CLASS = state("PostMatch", GM.States.PostMatch)
function StatePostRound:OnEnter(OldState)
if GAMEMODE.Config:Debug() then print("StatePostRound: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PostRound)
GAMEMODE.Data.RoundStartTime = CurTime()
end
function CLASS:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StatePostMatch: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PostMatch)
self.NextState = StatePreMatch
-- Check Change map conditions.
if ((GAMEMODE.Config:TimeLimit() > 0) && ((CurTime() - GAMEMODE.Data.StartTime) >= (GAMEMODE.Config:TimeLimit() * 60))) -- Over Time
|| ((GAMEMODE.Config.Round:Limit() > 0) && (GAMEMODE:GetRound() >= GAMEMODE.Config.Round:Limit())) -- Over Round Limit
then
-- Advance to nothing
GAMEMODE:SetRoundState(-1)
self.NextState = nil
-- MapVote
if (MapVote != nil) then MapVote.Start(30, true, 30, "ph_") return end
function StatePostRound:Tick()
-- Advance State
if (CurTime() - GAMEMODE.Data.RoundStartTime) >= 5 then -- ToDo: configureable time?
GAMEMODE.RoundManager:SetState(StatePostMatch)
end
end
function CLASS:Tick()
-- Advance State
RoundManager:SetState(self.NextState)
end
function CLASS:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StatePostMatch: OnLeave") end
end
_G["StatePostMatch"] = CLASS
function StatePostRound:OnLeave(NewState)
if GAMEMODE.Config:Debug() then print("StatePostRound: OnLeave") end
-- Game Mode: Basic
if (GAMEMODE.Config:GameMode() == GAMEMODE.Modes.Original) then
-- Swap Teams
local hiders, seekers = team.GetPlayers(GAMEMODE.Teams.Hiders), team.GetPlayers(GAMEMODE.Teams.Seekers)
for i, ply in ipairs(hiders) do
ply:KillSilent()
ply:SetTeam(GAMEMODE.Teams.Seekers)
end
for i, ply in ipairs(seekers) do
ply:KillSilent()
ply:SetTeam(GAMEMODE.Teams.Hiders)
end
-- TODO: Other Gamemodes
end
end
@@ -1,7 +1,7 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -22,33 +22,33 @@
SOFTWARE.
--]]
include "base.lua"
-- Precache Network Message
StatePreMatch = {}
local CLASS = state("PreMatch", GM.States.PreMatch)
function CLASS:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StatePreMatch: OnEnter") end
function StatePreMatch:OnEnter(OldState)
if GAMEMODE.Config:Debug() then print("StatePreMatch: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PreMatch)
math.randomseed(CurTime())
SetGlobalInt("Round", GetGlobalInt("Round", 0) + 1)
end
function CLASS:Tick()
function StatePreMatch:Tick()
-- Debug: Auto Advance to PreRound State
if (GAMEMODE.Config:Debug()) then
if GAMEMODE.Config:DebugLog() then print("StatePreMatch: Advancing to StatePreRound") end
RoundManager:SetState(StatePreRound)
print("StatePreMatch: Advancing to StatePreRound")
GAMEMODE.RoundManager:SetState(StatePreRound)
end
-- Both Teams must have at least 1 player.
if ((team.NumPlayers(GAMEMODE.Teams.Seekers) >= 1) && (team.NumPlayers(GAMEMODE.Teams.Hiders) >= 1)) then
RoundManager:SetState(StatePreRound)
if GAMEMODE.Config:DebugLog() then print("StatePreMatch: <Original> Have enough players to start match.") end
-- Game Mode: Basic
if (GAMEMODE.Config:GameMode() == GAMEMODE.Modes.Original) then
-- Both Teams must have at least 1 player.
if ((team.NumPlayers(GAMEMODE.Teams.Seekers) >= 1) && (team.NumPlayers(GAMEMODE.Teams.Hiders) >= 1)) then
GAMEMODE.RoundManager:SetState(StatePreRound)
end
-- TODO: Other Gamemodes
end
end
function CLASS:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StatePreMatch: OnLeave") end
end
_G["StatePreMatch"] = CLASS
function StatePreMatch:OnLeave(NewState)
if GAMEMODE.Config:Debug() then print("StatePreMatch: OnLeave") end
end
@@ -1,7 +1,7 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -22,30 +22,22 @@
SOFTWARE.
--]]
include "base.lua"
StatePreRound = {}
local CLASS = state("PreRound", GM.States.PreRound)
function CLASS:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StatePreRound: OnEnter") end
function StatePreRound:OnEnter(OldState)
if GAMEMODE.Config:Debug() then print("StatePreRound: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PreRound)
GAMEMODE:SetRound(GAMEMODE:GetRound() + 1)
-- Clean Up the Map
game.CleanUpMap()
-- Set Round Start Time
GAMEMODE.Data.RoundStartTime = CurTime()
end
function CLASS:Tick()
function StatePreRound:Tick()
-- Advance State
RoundManager:SetState(StateHide)
GAMEMODE.RoundManager:SetState(StateHide)
end
function CLASS:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StatePreRound: OnLeave") end
function StatePreRound:OnLeave(NewState)
if GAMEMODE.Config:Debug() then print("StatePreRound: OnLeave") end
-- Respawn Everyone
for i, ply in ipairs(player.GetAll()) do
@@ -54,17 +46,5 @@ function CLASS:OnLeave(NewState)
ply:Spawn()
ply:ScreenFade(SCREENFADE.PURGE, color_black, 0, 0)
ply:ScreenFade(SCREENFADE.IN, color_black, 1, 0)
-- Weighted Score: Adjust towards other Team.
if (ply:Team() == GAMEMODE.Teams.Hiders) then
ply.Data.RandomWeight = ply.Data.RandomWeight + 1
elseif (ply:Team() == GAMEMODE.Teams.Seekers) then
ply.Data.RandomWeight = ply.Data.RandomWeight - 1
end
end
-- Fretta Hooks
hook.Run("RoundStart")
end
_G["StatePreRound"] = CLASS
end
@@ -1,7 +1,7 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -22,14 +22,15 @@
SOFTWARE.
--]]
include "base.lua"
StateSeek = {}
local CLASS = state("Seek", GM.States.Seek)
function CLASS:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StateSeek: OnEnter") end
function StateSeek:OnEnter(OldState)
if GAMEMODE.Config:Debug() then print("StateSeek: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.Seek)
-- Round Data
GAMEMODE.Data.RoundTime = GAMEMODE.Config.Round:Time()
-- Unfreeze Seekers
for i, ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do
ply:Freeze(false)
@@ -39,13 +40,10 @@ function CLASS:OnEnter(OldState)
end
end
function CLASS:Tick()
function StateSeek:Tick()
-- Update Game Time
local deltaTime = (CurTime() - GAMEMODE.Data.RoundStartTime)
GAMEMODE.Data.RoundTime = GAMEMODE.Config.Round:Time() - deltaTime
GAMEMODE.Data.StateTime = GAMEMODE.Config.Round:Time() - deltaTime
GAMEMODE.Data.RoundTime = GAMEMODE.Config.Round:Time() - (CurTime() - GAMEMODE.Data.RoundStartTime)
GAMEMODE:SetRoundTime(GAMEMODE.Data.RoundTime)
GAMEMODE:SetRoundStateTime(GAMEMODE.Data.StateTime)
-- Victory Conditions
local hiders, seekers = team.GetPlayers(GAMEMODE.Teams.Hiders), team.GetPlayers(GAMEMODE.Teams.Seekers)
@@ -60,49 +58,30 @@ function CLASS:Tick()
end
for i,ply in ipairs(seekers) do
if (ply.Data.Alive) then
seekerAlive = truew
seekerAlive = true
end
end
if (hiderAlive == false) then
if (seekerAlive == false) then -- Draw, both teams dead.
GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Spectators)
RoundManager:SetState(StatePostRound)
GAMEMODE.RoundManager:SetState(StatePostRound)
else -- Seeker victory, Hiders dead
GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Seekers)
RoundManager:SetState(StatePostRound)
GAMEMODE.RoundManager:SetState(StatePostRound)
end
else
if (seekerAlive == false) then -- Hider Victory, Seeker dead.
GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Hiders)
RoundManager:SetState(StatePostRound)
GAMEMODE.RoundManager:SetState(StatePostRound)
else
if (GAMEMODE.Data.StateTime <= 0) then -- No Time remaining
GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Hiders)
RoundManager:SetState(StatePostRound)
if (GAMEMODE.Data.RoundTime <= 0) then -- No Time remaining
GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Hiders)
GAMEMODE.RoundManager:SetState(StatePostRound)
end
end
end
end
function CLASS:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StateSeek: OnLeave") end
if GAMEMODE:GetRoundWinner() == GAMEMODE.Teams.Seekers then
-- Run external Hooks
hook.Run("RoundVictorySeeker")
-- Assign Team Points
team.SetScore(GAMEMODE.Teams.Seekers, team.GetScore(GAMEMODE.Teams.Seekers) + 1)
elseif GAMEMODE:GetRoundWinner() == GAMEMODE.Teams.Hiders then
-- Run external Hooks
hook.Run("RoundVictoryHider")
-- Assign Team Points
team.SetScore(GAMEMODE.Teams.Hiders, team.GetScore(GAMEMODE.Teams.Hiders) + 1)
else
-- Run external Hooks
hook.Run("RoundVictoryDraw")
end
end
_G["StateSeek"] = CLASS
function StateSeek:OnLeave(NewState)
if GAMEMODE.Config:Debug() then print("StateSeek: OnLeave") end
end
@@ -0,0 +1,294 @@
-- Sounds played by members of the losing team at the end of the round.
LOSS_SOUNDS = {
"bot/aw_hell.wav",
"bot/aww_man.wav",
"bot/anyone_see_anything.wav",
"bot/anyone_see_them.wav",
"bot/come_out_and_fight_like_a_man.wav",
"bot/come_out_wherever_you_are.wav",
"bot/he_got_away.wav",
"bot/he_got_away2.wav",
"bot/i_dont_know_where_he_went.wav",
"bot/i_got_nothing.wav",
"bot/nothing_happening_over_here.wav",
"bot/nothing_here.wav",
"bot/nothing_moving_over_here.wav",
"bot/thats_not_good.wav",
"bot/theres_too_many.wav",
"bot/theres_too_many_of_them.wav",
"bot/theyre_all_over_the_place2.wav",
"bot/theyre_everywhere2.wav",
"bot/too_many2.wav",
"bot/what_happened.wav",
"bot/what_have_you_done.wav",
"bot/where_are_they.wav",
"bot/where_are_you_hiding.wav"
}
if (! file.Exists("prop_hunt/sounds_loss.txt", "DATA")) then
file.Write("prop_hunt/sounds_loss.txt", util.TableToKeyValues(LOSS_SOUNDS))
end
local fileContent = file.Read("prop_hunt/sounds_loss.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then LOSS_SOUNDS = fileTable end
end
-- Sounds played by members of the winning team at the end of the round.
VICTORY_SOUNDS = {
"bot/and_thats_how_its_done.wav",
"bot/come_to_papa.wav",
"bot/do_not_mess_with_me.wav",
"bot/dropped_him.wav",
"bot/enemy_down.wav",
"bot/enemy_down2.wav",
"bot/good_job_team.wav",
"bot/got_him.wav",
"bot/hes_broken.wav",
"bot/hes_dead.wav",
"bot/hes_done.wav",
"bot/hes_down.wav",
"bot/its_a_party.wav",
"bot/i_am_dangerous.wav",
"bot/i_am_on_fire.wav",
"bot/i_got_more_where_that_came_from.wav",
"bot/i_wasnt_worried_for_a_minute.wav",
"bot/killed_him.wav",
"bot/look_out_brag.wav",
"bot/made_him_cry.wav",
"bot/oh_yea.wav",
"bot/oh_yea2.wav",
"bot/owned.wav",
"bot/ruined_his_day.wav",
"bot/tag_them_and_bag_them.wav",
"bot/thats_the_way_this_is_done.wav",
"bot/that_was_a_close_one.wav",
"bot/that_was_it.wav",
"bot/that_was_the_last_guy.wav",
"bot/that_was_the_last_one.wav",
"bot/they_never_knew_what_hit_them.wav",
"bot/they_will_not_escape.wav",
"bot/they_wont_get_away.wav",
"bot/they_wont_get_away2.wav",
"bot/this_is_my_house.wav",
"bot/took_him_down.wav",
"bot/took_him_out.wav",
"bot/took_him_out2.wav",
"bot/wasted_him.wav",
"bot/way_to_be_team.wav",
"bot/well_done.wav",
"bot/we_owned_them.wav",
"bot/whew_that_was_close.wav",
"bot/whoo.wav",
"bot/whoo2.wav",
"bot/whos_the_man.wav",
"bot/who_wants_some_more.wav",
"bot/yesss.wav",
"bot/yesss2.wav"
}
if (! file.Exists("prop_hunt/sounds_victory.txt", "DATA")) then
file.Write("prop_hunt/sounds_victory.txt", util.TableToKeyValues(VICTORY_SOUNDS))
end
local fileContent = file.Read("prop_hunt/sounds_victory.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then VICTORY_SOUNDS = fileTable end
end
-- Taunts played when Hunters hit their Spare1 binding.
HUNTER_TAUNTS = {
"bot/a_bunch_of_them.wav",
"bot/come_out_and_fight_like_a_man.wav",
"bot/come_out_wherever_you_are.wav",
"bot/come_to_papa.wav",
"bot/dont_worry_hell_get_it.wav",
"bot/hang_on_i_heard_something.wav",
"bot/hang_on_im_coming.wav",
"bot/i_dont_think_so.wav",
"bot/i_have_the_hostages.wav",
"bot/i_see_our_target.wav",
"bot/im_waiting_here.wav",
"bot/keeping_an_eye_on_the_hostages.wav",
"bot/nnno_sir.wav",
"bot/spotted_the_delivery_boy.wav",
"bot/target_acquired.wav",
"bot/target_spotted.wav",
"bot/you_heard_the_man_lets_go.wav"
}
if (! file.Exists("prop_hunt/sounds_taunt_hunter.txt", "DATA")) then
file.Write("prop_hunt/sounds_taunt_hunter.txt", util.TableToKeyValues(HUNTER_TAUNTS))
end
local fileContent = file.Read("prop_hunt/sounds_taunt_hunter.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then HUNTER_TAUNTS = fileTable end
end
-- Taunts played when Props hit their Spare1 binding.
PROP_TAUNTS = {
-- "ambient/alarms/apc_alarm_loop1.wav",
"ambient/alarms/apc_alarm_pass1.wav",
-- "ambient/alarms/citadel_alert_loop2.wav",
-- "ambient/alarms/city_firebell_loop1.wav",
-- "ambient/alarms/city_siren_loop2.wav",
-- "ambient/alarms/combine_bank_alarm_loop1.wav",
-- "ambient/alarms/combine_bank_alarm_loop4.wav",
-- "ambient/alarms/klaxon1.wav",
"ambient/alarms/manhack_alert_pass1.wav",
"ambient/alarms/razortrain_horn1.wav",
"ambient/alarms/scanner_alert_pass1.wav",
-- "ambient/alarms/siren.wav",
-- "ambient/alarms/train_crossing_bell_loop1.wav",
"ambient/alarms/train_horn2.wav",
"ambient/alarms/train_horn_distant1.wav",
"ambient/alarms/warningbell1.wav",
-- "ambient/chatter/cb_radio_chatter_1.wav",
-- "ambient/chatter/cb_radio_chatter_2.wav",
-- "ambient/chatter/cb_radio_chatter_3.wav",
"ambient/energy/whiteflash.wav",
"ambient/intro/alyxremove.wav",
"ambient/intro/logosfx.wav",
-- "ambient/levels/labs/teleport_alarm_loop1.wav",
"ambient/levels/launch/1stfiringwarning.wav",
"ambient/levels/launch/rockettakeoffblast.wav",
-- "ambient/levels/outland/basealarmloop.wav",
-- "ambient/machines/60hzhum.wav",
"ambient/misc/ambulance1.wav",
"ambient/misc/carhonk1.wav",
"ambient/misc/carhonk2.wav",
"ambient/misc/carhonk3.wav",
-- "ambient/music/bongo.wav",
-- "ambient/music/country_rock_am_radio_loop.wav",
-- "ambient/music/cubanmusic1.wav",
-- "ambient/music/dustmusic1.wav",
-- "ambient/music/dustmusic2.wav",
-- "ambient/music/dustmusic3.wav",
-- "ambient/music/flamenco.wav",
-- "ambient/music/latin.wav",
-- "ambient/music/mirame_radio_thru_wall.wav",
-- "ambient/music/piano1.wav",
-- "ambient/music/piano2.wav",
"ambient/outro/gunshipcrash.wav",
"ambient/3dmeagle.wav",
-- "ambient/guit1.wav",
-- "ambient/opera.wav",
-- "ambient/sheep.wav",
"beams/beamstart5.wav",
"buttons/bell1.wav",
"buttons/weapon_cant_buy.wav",
"common/bass.wav",
"common/bugreporter_failed.wav",
"common/warning.wav",
"doors/door_squeek1.wav",
"friends/friend_join.wav",
"friends/friend_online.wav",
"friends/message.wav",
"hostage/hunuse/comeback.wav",
"hostage/hunuse/dontleaveme.wav",
"hostage/hunuse/yeahillstay.wav",
"items/gift_drop.wav",
"music/radio1.mp3",
"phx/eggcrack.wav",
"plats/elevbell1.wav",
"player/headshot1.wav",
"player/headshot2.wav",
"player/sprayer.wav",
"radio/enemydown.wav",
"radio/go.wav",
"radio/locknload.wav",
"radio/negative.wav",
"radio/rounddraw.wav",
"radio/takepoint.wav",
"resource/warning.wav",
-- "test/temp/soundscape_test/tv_music.wav",
"ui/achievement_earned.wav",
"ui/freeze_cam.wav",
"vehicles/junker/radar_ping_friendly1.wav",
"weapons/c4/c4_beep1.wav",
"weapons/c4/c4_click.wav",
"weapons/awp/awp1.wav",
"vo/canals/female01/gunboat_giveemhell.wav",
"vo/canals/female01/gunboat_justintime.wav",
"vo/canals/female01/stn6_incoming.wav",
"vo/canals/male01/gunboat_giveemhell.wav",
"vo/canals/male01/gunboat_justintime.wav",
"vo/canals/male01/stn6_incoming.wav",
"vo/canals/al_radio_stn6.wav",
"vo/canals/arrest_getgoing.wav",
"vo/canals/arrest_helpme.wav",
"vo/canals/arrest_lookingforyou.wav",
"vo/canals/boxcar_lethimhelp.wav",
"vo/canals/matt_closecall.wav",
"vo/canals/premassacre.wav",
"vo/ravenholm/aimforhead.wav",
"vo/ravenholm/bucket_patience.wav",
"vo/ravenholm/madlaugh01.wav",
"vo/ravenholm/madlaugh02.wav",
"vo/ravenholm/madlaugh03.wav",
"vo/ravenholm/madlaugh04.wav",
"weapons/strider_buster/ol12_stickybombcreator.wav",
"weapons/c4/c4_explode1.wav",
"weapons/357/357_fire2.wav",
"weapons/357/357_fire3.wav",
"weapons/scout/scout_fire-1.wav",
"weapons/smokegrenade/sg_explode.wav",
"weapons/grenade_launcher1.wav",
"weapons/explode3.wav",
"weapons/underwater_explode3.wav",
"items/nvg_on.wav",
"hostage/huse/letsdoit.wav",
"hostage/huse/illfollow.wav",
"hostage/huse/getouttahere.wav",
"doors/door_screen_move1.wav",
"doors/heavy_metal_stop1.wav",
"doors/default_move.wav",
"common/stuck2.wav",
"ambient/water_splash1.wav",
"ambient/water_splash2.wav",
"ambient/water_splash3.wav",
"ambient/weather/thunder1.wav",
"ambient/weather/thunder2.wav",
"ambient/weather/thunder3.wav",
"ambient/weather/thunder4.wav",
"ambient/weather/thunder5.wav",
"ambient/weather/thunder6.wav",
"ambient/outro/thunder7.wav",
"ambient/voices/crying_loop1.wav",
"ambient/voices/playground_memory.wav",
"ambient/voices/f_scream1.wav",
"ambient/voices/m_scream1.wav",
"ambient/voices/cough1.wav",
"ambient/voices/cough2.wav",
"ambient/voices/cough3.wav",
"ambient/voices/cough4.wav",
"ambient/overhead/plane1.wav",
"ambient/overhead/plane2.wav",
"ambient/overhead/plane3.wav",
"ambient/overhead/hel1.wav",
"ambient/overhead/hel2.wav",
"ambient/misc/truck_backup1.wav",
"ambient/misc/truck_drive1.wav",
"ambient/misc/truck_drive2.wav",
"ambient/machines/pneumatic_drill_1.wav",
"ambient/machines/pneumatic_drill_2.wav",
"ambient/machines/pneumatic_drill_3.wav",
"ambient/machines/pneumatic_drill_4.wav",
"ambient/machines/station_train_squeel.wav",
"ambient/machines/ticktock.wav",
"ambient/creatures/teddy.wav",
"ambient/creatures/town_child_scream1.wav",
"ambient/creatures/town_moan1.wav",
"ambient/creatures/town_muffled_cry1.wav",
"ambient/creatures/town_scared_breathing1.wav",
"ambient/creatures/town_scared_breathing2.wav",
"ambient/creatures/town_scared_sob1.wav",
"ambient/creatures/town_scared_sob2.wav",
"ambient/creatures/town_zombie_call1.wav"
}
if (! file.Exists("prop_hunt/sounds_taunt_prop.txt", "DATA")) then
file.Write("prop_hunt/sounds_taunt_prop.txt", util.TableToKeyValues(PROP_TAUNTS))
end
local fileContent = file.Read("prop_hunt/sounds_taunt_prop.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then PROP_TAUNTS = fileTable end
end
@@ -26,14 +26,23 @@
--! Gamemode Information
-- ------------------------------------------------------------------------- --
GM.Name = "Prop Hunt Extended"
GM.Author = "Michael Fabian 'Xaymar' Dirks"
GM.Email = "info@xaymar.com"
GM.Author = "Michael 'Xaymar' Dirks (Based on Kow@lskis Version, Original by AMT)"
GM.Email = "michael.fabian.dirks@gmail.com"
GM.Website = "http://xaymar.com/"
GM.TeamBased = true
GM.AllowAutoTeam = true
GM.SecondsBetweenTeamSwitches = 10
-- ------------------------------------------------------------------------- --
--! Includes
-- ------------------------------------------------------------------------- --
-- Player Classes
include "player_class/class_default.lua"
include "player_class/class_spectator.lua"
include "player_class/class_seeker.lua"
include "player_class/class_hider.lua"
-- ------------------------------------------------------------------------- --
--! Code
-- ------------------------------------------------------------------------- --
@@ -46,6 +55,12 @@ GM.States.Seek = 3
GM.States.PostRound = 4
GM.States.PostMatch = 5
-- Game Modes
GM.Modes = {}
GM.Modes.Original = 0
GM.Modes.SwizzleEffect = 1 -- Randomizes Teams each Round
GM.Modes.TheDeadHunt = 2 -- One Hunter, Dead Prop become Hunter, Props can't see each other.
-- Teams
GM.Teams = {}
GM.Teams.Spectators = 0
@@ -56,8 +71,6 @@ function GM:CreateTeams()
-- Specators
team.SetUp(self.Teams.Spectators, "Spectators", Color(127, 127, 127, 255))
team.SetSpawnPoint(self.Teams.Spectators, {
"info_player_start",
"info_player_spawn",
"info_player_deathmatch",
"info_player_combine",
"info_player_counterterrorist",
@@ -69,7 +82,6 @@ function GM:CreateTeams()
-- Seekers: "Hunters"
team.SetUp(self.Teams.Seekers, "Seekers", Color(0, 128, 255, 255))
team.SetSpawnPoint(self.Teams.Seekers, {
"info_player_start",
"info_player_spawn",
"info_player_deathmatch",
"info_player_combine",
@@ -80,7 +92,6 @@ function GM:CreateTeams()
-- Hiders: "Props"
team.SetUp(self.Teams.Hiders, "Hiders", Color(255, 128, 0, 255))
team.SetSpawnPoint(self.Teams.Hiders, {
"info_player_start",
"info_player_spawn",
"info_player_deathmatch",
"info_player_allies",
@@ -100,47 +111,26 @@ function GM:PlayerTick(ply, mv)
return player_manager.RunClass(ply, "Tick", mv)
end
function GM:FindUseEntity(ply, defaultEnt)
return player_manager.RunClass(ply, "FindUseEntity", defaultEnt)
function GM:PlayerHurt(victim, attacker, healthRemaining, damageTaken)
if (victim != nil && victim:IsPlayer()) then
player_manager.RunClass(victim, "Hurt", victim, attacker, healthRemaining, damageTaken)
end
if (attacker != nil && attacker:IsPlayer()) then
player_manager.RunClass(attacker, "Damage", victim, attacker, healthRemaining, damageTaken)
end
end
-- ------------------------------------------------------------------------- --
--! Gamemode Functionality
-- ------------------------------------------------------------------------- --
function GM:GetRound()
return GetGlobalInt("Round", 0)
function GM:GetRoundState()
return GetGlobalInt("RoundState", self.States.PreMatch)
end
function GM:GetRoundTime()
return GetGlobalInt("RoundTime", 0)
end
function GM:GetRoundState()
return GetGlobalInt("RoundState", self.States.PreMatch)
end
function GM:GetRoundStateTime()
return GetGlobalInt("RoundStateTime", 0)
end
function GM:GetRoundWinner()
return GetGlobalInt("RoundWinner", GAMEMODE.Teams.Spectator)
end
-- ------------------------------------------------------------------------- --
--! Includes
-- ------------------------------------------------------------------------- --
-- Defines
include "sh_defines.lua"
-- Meta
include "meta/player.lua"
-- Configuration
include "sh_config.lua"
-- Player Classes
include "player_class/class_default.lua"
include "player_class/class_spectator.lua"
include "player_class/class_seeker.lua"
include "player_class/class_hider.lua"
end
@@ -0,0 +1,49 @@
-- Finds the player meta table or terminates
local meta = FindMetaTable("Player")
if !meta then return end
-- Blinds the player by setting view out into the void
function meta:Blind(bool)
if !self:IsValid() then return end
if SERVER then
umsg.Start("SetBlind", self)
if bool then
umsg.Bool(true)
else
umsg.Bool(false)
end
umsg.End()
elseif CLIENT then
blind = bool
end
end
-- Blinds the player by setting view out into the void
function meta: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
-- Sets a new Hull for a player.
function meta:NewHull(hullOBBMin, hullOBBMax)
if !self:IsValid() then return end
if hullOBBMax == nil then return end
if hullOBBMin == nil then return end
local hullOBB = hullOBBMax - hullOBBMin
local hullOBBXY = math.max(hullOBB.x, hullOBB.y)
local xyMul = 0.5
local hullMin = Vector(-hullOBBXY * xyMul, -hullOBBXY * xyMul, 0)
local hullMax = Vector( hullOBBXY * xyMul, hullOBBXY * xyMul, hullOBB.z)
self:SetHull(hullMin, hullMax)
self:SetHullDuck(hullMin, hullMax)
self:SetViewOffset(Vector(0, 0, hullOBB.z))
self:SetViewOffsetDucked(Vector(0, 0, hullOBB.z / 2.0))
end
Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

@@ -0,0 +1,182 @@
"prophuntextended"
{
"base" "base"
"title" "Prop Hunt Extended"
"maps" "^ph_|^cs_|^de_|^ttt_"
"menusystem" "1"
"workshopid" "468149739"
"settings"
{
// Game Settings
1
{
"name" "ph_gamemode"
"text" "G: Game Mode"
"help" "0: Basic, 1: Swizzle Effect (Random Teams), 2: The Dead Hunt (One Hunter, Dead Props become Hunters)"
"type" "Numeric"
"default" "0"
}
2
{
"name" "mp_timelimit"
"text" "G: Time Limit"
"help" "Time Limit in Minutes for how long should we stay on one map. (0 to disable)"
"type" "Numeric"
"default" "20"
}
3
{
"name" "ph_sprinting"
"text" "G: Enable Sprinting"
"help" "Should sprinting be possible?"
"type" "CheckBox"
"default" "0"
}
4
{
"name" "ph_tauntcooldown"
"text" "G: Taunt Cooldown"
"help" "How much time must pass before another taunt may be played."
"type" "Numeric"
"default" "5"
}
// Round Settings
10
{
"name" "ph_round_limit"
"text" "R: Rounds per Map"
"help" "How many rounds are played per map."
"type" "Numeric"
"default" "10"
}
11
{
"name" "ph_round_timelimit"
"text" "R: Round Duration (Seconds)"
"help" "How long is each round going to last?"
"type" "Numeric"
"default" "300"
}
12
{
"name" "ph_round_blindtime"
"text" "R: Hiding Time (Seconds)"
"help" "How long are hunters blinded? (positive values will be inside the round time limit, negative will add to the round time limit)"
"type" "Numeric"
"default" "30"
}
// Seeker Settings
20
{
"name" "ph_seeker_health"
"text" "S: Health"
"type" "Numeric"
"default" "100"
}
21
{
"name" "ph_seeker_health_max"
"text" "S: Max Health"
"type" "Numeric"
"default" "100"
}
22
{
"name" "ph_seeker_health_bonus"
"text" "S: Health Kill-Bonus"
"help" "Health gained on kill."
"type" "Numeric"
"default" "20"
}
23
{
"name" "ph_seeker_health_penalty"
"text" "S: Health Penalty"
"help" "Health lost on wrong shot."
"type" "Numeric"
"default" "5"
}
24
{
"name" "ph_seeker_weapons"
"text" "S: Weapons to be given to Seekers"
"help" "Format: Weapon,Weapon,..."
"type" "Text"
"default" "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun,weapon_physcannon"
}
25
{
"name" "ph_seeker_ammo"
"text" "S: Ammo to give to Seekers"
"help" "Format: Name:Amount,Name:Amount,..."
"type" "Text"
"default" "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64"
}
// Hider Settings
30
{
"name" "ph_hider_health"
"text" "H: Health"
"type" "Numeric"
"default" "100"
}
31
{
"name" "ph_hider_health_max"
"text" "H: Max Health"
"type" "Numeric"
"default" "100"
}
32
{
"name" "ph_hider_health_scaling"
"text" "H: Enable Health Scaling"
"help" "Larger & heavier objects have more health, smaller less."
"type" "CheckBox"
"default" "1"
}
33
{
"name" "ph_hider_health_scaling_max"
"text" "H: Scaled Max Health"
"type" "Numeric"
"default" "200"
}
// Whitelist & Blacklist
40
{
"name" "ph_list_class_whitelist"
"text" "L: Allowed Entity Classes"
"help" "Hiders can only use these for changing model and skin."
"type" "Text"
"default" "ph_prop,prop_physics,prop_physics_multiplayer,prop_physics_respawnable"
}
41
{
"name" "ph_list_abuse_blacklist"
"text" "L: Abuse Blacklist"
"help" "Fix interact spam with certain entities so that all areas stay accessible."
"type" "Text"
"default" ""func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable""
}
}
}
+7
View File
@@ -0,0 +1,7 @@
@ECHO OFF
:: Retrieve Garry's Mod path from Regristry
:: FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
SET "GARRYSMODPATH=C:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
SET "PATH=%CD%;%GARRYSMODPATH%\bin;%PATH%"
CMD
+6
View File
@@ -0,0 +1,6 @@
@ECHO OFF
SET "PWD=%~dp0"
CALL build-env.bat
"%TOOLPATH%\bin\gmad.exe" create -folder "%PWD%\Source" -out "%PWD%\Pack.gma"
PAUSE
+6
View File
@@ -0,0 +1,6 @@
@ECHO OFF
SET "PWD=%~dp0"
CALL build-env.bat
"%GARRYSMODPATH%\bin\gmpublish.exe" update -id %WORKSHOPID% -icon "Logo.jpg" -addon "Pack.gma" -changes ""
PAUSE
+2
View File
@@ -0,0 +1,2 @@
SET "WORKSHOPID=468149739"
FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "TOOLPATH=%%B"
-11
View File
@@ -1,11 +0,0 @@
[h1]Version: 1.4.0[/h1]
The round manager has been rewritten to improve code quality and reusability and is now using meta-classes, which slightly improves overall performance. For addons that hook into the gamemode, this means that GAMEMODE.RoundManager is only valid after GM:Initialize() has been run.
Additionally the Prop Hunt SMG has been slightly changed and now fires at a rate of 0.075 (from 0.1), but deals only 4 damage (from 5), which makes it near identical to the standard Half Life 2 SMG. It will now deal 53.33 DPS instead of 50 DPS like before, while keeping the accuracy and extra features as is.
[b]Changelog:[/b]
[list][*]Changed Prop Hunt SMD Refire Time from 0.1 to 0.075.
[*]Fixed Seekers not gaining health back after killing a Hider.
[*]Fixed some debug log messages by Prop Rotation appearing without debug log being enabled.
[*]Rewrote the round manager to use a class based system.
[list]
-102
View File
@@ -1,102 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
height="32"
viewBox="0 0 8.4666667 8.4666667"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="icon.svg"
inkscape:export-filename="D:\Projects\GarrysMod\PropHuntExtended\media\rendered\icon.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="22.42927"
inkscape:cy="16.716875"
inkscape:document-units="mm"
inkscape:current-layer="layer3"
showgrid="false"
units="px"
inkscape:window-width="2880"
inkscape:window-height="1620"
inkscape:window-x="4068"
inkscape:window-y="228"
inkscape:window-maximized="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-288.53332)">
<rect
style="display:inline;fill:#433a35;fill-opacity:1;stroke-width:0.0073266"
id="rect4532"
width="8.4666662"
height="8.4666662"
x="0"
y="288.53333" />
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Layer 2"
style="display:inline">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:9.64581013px;line-height:1.25;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:0px;word-spacing:0px;fill:#f2722b;fill-opacity:1;stroke:none;stroke-width:1.80858934"
x="-0.39562893"
y="267.48511"
id="text817"
transform="matrix(0.90062328,0,0,1.1103422,0,-288.53331)"><tspan
sodipodi:role="line"
id="tspan815"
x="-0.39562893"
y="267.48511"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Impact;-inkscape-font-specification:Impact;fill:#f2722b;fill-opacity:1;stroke-width:1.80858934">PH</tspan></text>
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Layer 3">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:6.02445936px;line-height:1.25;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:0px;word-spacing:0px;fill:#fffff7;fill-opacity:1;stroke:none;stroke-width:1.12958598"
x="1.3681852"
y="8.4666901"
id="text821"><tspan
sodipodi:role="line"
id="tspan819"
x="1.3681852"
y="8.4666901"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Impact;-inkscape-font-specification:Impact;fill:#fffff7;fill-opacity:1;stroke-width:1.12958598">EX</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

-213
View File
@@ -1,213 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8192"
height="1024"
viewBox="0 0 2167.4666 270.93334"
version="1.1"
id="svg4530"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="logo-wide-transparent.svg"
style="enable-background:new"
inkscape:export-filename="D:\Projects\GarrysMod\PropHuntExtended\source\gamemodes\prophuntextended\logo.png"
inkscape:export-xdpi="24"
inkscape:export-ydpi="24">
<defs
id="defs4524">
<marker
inkscape:stockid="Arrow1Sstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Sstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6765"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
transform="matrix(0.2,0,0,0.2,1.2,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6753"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
transform="matrix(0.8,0,0,0.8,10,0)"
inkscape:connector-curvature="0" />
</marker>
<linearGradient
id="linearGradient6153"
osb:paint="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop6151" />
</linearGradient>
<filter
style="color-interpolation-filters:sRGB"
id="filter7370"
inkscape:label="text-extended-filter"
x="-0.02"
width="1.04">
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur7374"
result="result4" />
<feGaussianBlur
stdDeviation="2"
id="feGaussianBlur7376"
in="SourceGraphic"
result="result2" />
<feGaussianBlur
stdDeviation="4"
id="feGaussianBlur7378"
in="SourceGraphic"
result="result1" />
<feBlend
mode="screen"
in2="result2"
id="feBlend7380"
result="result3"
in="result1" />
<feBlend
mode="screen"
in2="result4"
id="feBlend7382"
result="result5" />
<feBlend
mode="screen"
in2="SourceGraphic"
id="feBlend7384"
result="result7" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.27854414"
inkscape:cx="4871.459"
inkscape:cy="1967.7857"
inkscape:document-units="mm"
inkscape:current-layer="layer3"
showgrid="false"
showborder="true"
inkscape:pagecheckerboard="true"
units="px"
inkscape:window-width="3840"
inkscape:window-height="2080"
inkscape:window-x="3829"
inkscape:window-y="-11"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
position="541.86667,270.93333"
orientation="0,1"
id="guide4543"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="541.86667,270.93334"
orientation="1,0"
id="guide4545"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="541.86667,406.4"
orientation="0,1"
id="guide4547"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
</sodipodi:namedview>
<metadata
id="metadata4527">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Text EXTENDED"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-26.066643)"
style="display:inline">
<g
style="display:inline;stroke:#f2722b;stroke-width:14.74307919;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;filter:url(#filter7370)"
transform="matrix(0.82040111,0,0,0.82040111,1119.0696,23.456852)"
inkscape:label="Layer 1"
id="g7255">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:316.34109497px;line-height:1.25;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:0px;word-spacing:0px;fill:none;fill-opacity:1;stroke:#f2722b;stroke-width:14.57606602;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
x="-10.334827"
y="293.34174"
id="text7253"><tspan
dx="0"
sodipodi:role="line"
id="tspan7251"
x="-10.334827"
y="293.34174"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:273.42272949px;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:4.85868835px;fill:none;fill-opacity:1;stroke:#f2722b;stroke-width:14.57606602;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal">EXTENDED</tspan></text>
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Text PROP HUNT"
style="display:inline"
transform="translate(0,-270.93333)">
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Background"
style="display:inline" />
<g
transform="matrix(0.95541658,0,0,0.99515462,383.45565,251.14939)"
id="layer1-9"
inkscape:label="Ebene 1"
style="fill:#f2722b;fill-opacity:1;fill-rule:nonzero">
<text
id="text3715"
y="255.2442"
x="-387.08383"
style="font-style:normal;font-weight:normal;font-size:251.06704712px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#f2722b;fill-opacity:1;fill-rule:nonzero"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Impact;-inkscape-font-specification:Impact;fill:#f2722b;fill-opacity:1;fill-rule:nonzero"
y="255.2442"
x="-387.08383"
id="tspan3713"
sodipodi:role="line">PROP HUNT</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.2 KiB

-221
View File
@@ -1,221 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8192"
height="1024"
viewBox="0 0 2167.4666 270.93334"
version="1.1"
id="svg4530"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="logo-wide.svg"
style="enable-background:new"
inkscape:export-filename="D:\Projects\GarrysMod\PropHuntExtended\media\rendered\logo-wide.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs4524">
<marker
inkscape:stockid="Arrow1Sstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Sstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6765"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
transform="matrix(0.2,0,0,0.2,1.2,0)"
inkscape:connector-curvature="0" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6753"
d="M 0,0 5,-5 -12.5,0 5,5 Z"
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt"
transform="matrix(0.8,0,0,0.8,10,0)"
inkscape:connector-curvature="0" />
</marker>
<linearGradient
id="linearGradient6153"
osb:paint="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop6151" />
</linearGradient>
<filter
style="color-interpolation-filters:sRGB"
id="filter7370"
inkscape:label="text-extended-filter"
x="-0.02"
width="1.04">
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur7374"
result="result4" />
<feGaussianBlur
stdDeviation="2"
id="feGaussianBlur7376"
in="SourceGraphic"
result="result2" />
<feGaussianBlur
stdDeviation="4"
id="feGaussianBlur7378"
in="SourceGraphic"
result="result1" />
<feBlend
mode="screen"
in2="result2"
id="feBlend7380"
result="result3"
in="result1" />
<feBlend
mode="screen"
in2="result4"
id="feBlend7382"
result="result5" />
<feBlend
mode="screen"
in2="SourceGraphic"
id="feBlend7384"
result="result7" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.27854414"
inkscape:cx="5596.6582"
inkscape:cy="1967.7857"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
showborder="true"
inkscape:pagecheckerboard="true"
units="px"
inkscape:window-width="3840"
inkscape:window-height="2080"
inkscape:window-x="3829"
inkscape:window-y="-11"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
position="541.86667,270.93333"
orientation="0,1"
id="guide4543"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="541.86667,270.93334"
orientation="1,0"
id="guide4545"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="541.86667,406.4"
orientation="0,1"
id="guide4547"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
</sodipodi:namedview>
<metadata
id="metadata4527">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Text EXTENDED"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-26.066643)"
style="display:inline">
<g
style="display:inline;stroke:#f2722b;stroke-width:14.74307919;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;filter:url(#filter7370)"
transform="matrix(0.82040111,0,0,0.82040111,1119.0696,23.456852)"
inkscape:label="Layer 1"
id="g7255">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:316.34109497px;line-height:1.25;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:0px;word-spacing:0px;fill:none;fill-opacity:1;stroke:#f2722b;stroke-width:14.57606602;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
x="-10.334827"
y="293.34174"
id="text7253"><tspan
dx="0"
sodipodi:role="line"
id="tspan7251"
x="-10.334827"
y="293.34174"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:273.42272949px;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:4.85868835px;fill:none;fill-opacity:1;stroke:#f2722b;stroke-width:14.57606602;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal">EXTENDED</tspan></text>
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Text PROP HUNT"
style="display:inline"
transform="translate(0,-270.93333)">
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Background"
style="display:inline">
<rect
style="display:inline;fill:#433a35;fill-opacity:1;stroke-width:0.46890202"
id="rect4532"
width="1083.7333"
height="270.93332"
x="1.110223e-016"
y="270.93335" />
</g>
<g
transform="matrix(0.95541658,0,0,0.99515462,383.45565,251.14939)"
id="layer1-9"
inkscape:label="Ebene 1"
style="fill:#f2722b;fill-opacity:1;fill-rule:nonzero">
<text
id="text3715"
y="255.2442"
x="-387.08383"
style="font-style:normal;font-weight:normal;font-size:251.06704712px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#f2722b;fill-opacity:1;fill-rule:nonzero"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Impact;-inkscape-font-specification:Impact;fill:#f2722b;fill-opacity:1;fill-rule:nonzero"
y="255.2442"
x="-387.08383"
id="tspan3713"
sodipodi:role="line">PROP HUNT</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.4 KiB

-219
View File
@@ -1,219 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="4096"
height="2048"
viewBox="0 0 1083.7333 541.86668"
version="1.1"
id="svg4530"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="logo.svg"
enable-background="new"
inkscape:export-filename="D:\Projects\GarrysMod\PropHuntExtended\media\rendered\logo.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs4524">
<marker
inkscape:stockid="Arrow1Sstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Sstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6765"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.2) translate(6,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lstart"
style="overflow:visible"
inkscape:isstock="true">
<path
id="path6753"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt"
transform="scale(0.8) translate(12.5,0)" />
</marker>
<linearGradient
id="linearGradient6153"
osb:paint="solid">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop6151" />
</linearGradient>
<filter
style="color-interpolation-filters:sRGB"
id="filter7370"
inkscape:label="text-extended-filter"
x="-0.02"
width="1.04">
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur7374"
result="result4" />
<feGaussianBlur
stdDeviation="2"
id="feGaussianBlur7376"
in="SourceGraphic"
result="result2" />
<feGaussianBlur
stdDeviation="4"
id="feGaussianBlur7378"
in="SourceGraphic"
result="result1" />
<feBlend
mode="screen"
in2="result2"
id="feBlend7380"
result="result3"
in="result1" />
<feBlend
mode="screen"
in2="result4"
id="feBlend7382"
result="result5" />
<feBlend
mode="screen"
in2="SourceGraphic"
id="feBlend7384"
result="result7" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.7878418"
inkscape:cx="1533.9593"
inkscape:cy="1030.2533"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
showborder="true"
inkscape:pagecheckerboard="true"
units="px"
inkscape:window-width="3840"
inkscape:window-height="2080"
inkscape:window-x="3829"
inkscape:window-y="-11"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true">
<sodipodi:guide
position="541.86667,270.93333"
orientation="0,1"
id="guide4543"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="541.86667,270.93334"
orientation="1,0"
id="guide4545"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="541.86667,406.4"
orientation="0,1"
id="guide4547"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
</sodipodi:namedview>
<metadata
id="metadata4527">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Text EXTENDED"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,244.86669)"
style="display:inline;">
<g
style="display:inline;stroke:#f2722b;stroke-width:14.74307919;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;filter:url(#filter7370)"
transform="matrix(0.82040111,0,0,0.82040111,37.679834,22.343453)"
inkscape:label="Layer 1"
id="g7255">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:316.34109497px;line-height:1.25;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:0px;word-spacing:0px;fill:none;fill-opacity:1;stroke:#f2722b;stroke-width:14.57606602;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
x="-10.334827"
y="293.34174"
id="text7253"><tspan
dx="0"
sodipodi:role="line"
id="tspan7251"
x="-10.334827"
y="293.34174"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:273.42272949px;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:4.85868835px;fill:none;fill-opacity:1;stroke:#f2722b;stroke-width:14.57606602;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal">EXTENDED</tspan></text>
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Text PROP HUNT"
style="display:inline">
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Background"
style="display:inline">
<rect
transform="translate(0,244.86669)"
style="display:inline;fill:#433a35;fill-opacity:1;stroke-width:0.46890202"
id="rect4532"
width="1083.7333"
height="270.93332"
x="1.110223e-016"
y="-244.86668" />
</g>
<g
transform="matrix(0.95541658,0,0,0.99515462,383.45565,-19.78395)"
id="layer1-9"
inkscape:label="Ebene 1"
style="fill:#f2722b;fill-opacity:1;fill-rule:nonzero">
<text
id="text3715"
y="255.2442"
x="-387.08383"
style="font-style:normal;font-weight:normal;font-size:251.06704712px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#f2722b;fill-opacity:1;fill-rule:nonzero"
xml:space="preserve"><tspan
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Impact;-inkscape-font-specification:Impact;fill:#f2722b;fill-opacity:1;fill-rule:nonzero"
y="255.2442"
x="-387.08383"
id="tspan3713"
sodipodi:role="line">PROP HUNT</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.4 KiB

-110
View File
@@ -1,110 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg6163"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="title-extended.svg">
<defs
id="defs6157">
<filter
style="color-interpolation-filters:sRGB"
id="filter7370"
inkscape:label="text-extended-filter">
<feGaussianBlur
stdDeviation="1"
id="feGaussianBlur7374"
result="result4" />
<feGaussianBlur
stdDeviation="2"
id="feGaussianBlur7376"
in="SourceGraphic"
result="result2" />
<feGaussianBlur
stdDeviation="4"
id="feGaussianBlur7378"
in="SourceGraphic"
result="result1" />
<feBlend
mode="screen"
in2="result2"
id="feBlend7380"
result="result3"
in="result1" />
<feBlend
mode="screen"
in2="result4"
id="feBlend7382"
result="result5" />
<feBlend
mode="screen"
in2="SourceGraphic"
id="feBlend7384"
result="result7" />
</filter>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="-77.142857"
inkscape:cy="560"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="3840"
inkscape:window-height="2080"
inkscape:window-x="3829"
inkscape:window-y="-11"
inkscape:window-maximized="1" />
<metadata
id="metadata6160">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
style="display:inline;stroke:#f2722b;stroke-width:14.74307919;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;filter:url(#filter7370)"
transform="matrix(0.82040111,0,0,0.82040111,98.238237,35.82582)"
inkscape:label="Layer 1"
id="g7255">
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:316.34109497px;line-height:1.25;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:0px;word-spacing:0px;fill:none;fill-opacity:1;stroke:#f2722b;stroke-width:14.57606602;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
x="-10.334827"
y="293.34174"
id="text7253"><tspan
dx="0"
sodipodi:role="line"
id="tspan7251"
x="-10.334827"
y="293.34174"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:273.42272949px;font-family:Impact;-inkscape-font-specification:Impact;letter-spacing:4.85868835px;fill:none;fill-opacity:1;stroke:#f2722b;stroke-width:14.57606602;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal">EXTENDED</tspan></text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

-88
View File
@@ -1,88 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="4101.4619"
height="781.65002"
viewBox="0 0 1085.1785 206.81157"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="title-text.svg">
<title
id="title3717">Prop Hunt Title Text</title>
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="1186.9308"
inkscape:cy="417.93638"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:pagecheckerboard="true"
showborder="false"
units="px"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="3840"
inkscape:window-height="2080"
inkscape:window-x="3829"
inkscape:window-y="-11"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>Prop Hunt Title Text</dc:title>
<dc:creator>
<cc:Agent>
<dc:title>Michael Fabian Dirks &lt;info@xaymar.com&gt;</dc:title>
</cc:Agent>
</dc:creator>
<dc:rights>
<cc:Agent>
<dc:title></dc:title>
</cc:Agent>
</dc:rights>
<dc:language>English</dc:language>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(376.78616,-52.600731)">
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:251.06704712px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#f2722b;fill-opacity:1;stroke:none;stroke-width:6.27667618;"
x="-387.08383"
y="255.2442"
id="text3715"><tspan
sodipodi:role="line"
id="tspan3713"
x="-387.08383"
y="255.2442"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Impact;-inkscape-font-specification:Impact;stroke-width:6.27667618;fill:#f2722b;fill-opacity:1;">PROP HUNT</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 177 KiB

-31
View File
@@ -1,31 +0,0 @@
Hide n Seek with a twist - Hiders can turn into anything on the map! From bottles, to vending machines and all the way to huge cars - what you become depends on how you want to play. Do you want to blend in with your surroundings, or do you want to make a fool of the Seekers? And how will you deal with finding (and killing) all hiders as a Seeker?
The Gamemode comes with out of the box support for console configuration (ph_*), custom taunt support, prop rotation, an improved code base for modders and better integration and some other fixes. Support for [url=https://steamcommunity.com/sharedfiles/filedetails/?id=151583504]MapVote[/url] is also built in, so as long as you have a compatible addon installed you will get a map voting menu at the end of a match.
[h1]How To Play[/h1]
[b]Seekers[/b]
Your primary goal is to find hiders by any means possible. But watch out, you might lose health if you shoot an object that isn't actually a hider! Pick things up before shooting them, or simply remember the layout of the maps you are playing on. And remember: You lose if only a single hider is still alive at the end of the round.
[b]Hiders[/b]
Stay alive as long as possible and make Seekers look like a fool. Dance around their feet, hide in plain sight or be that huge car that nobody though you could become! What you do is entirely up to you.
[b]Spectators[/b]
You get to watch the whole thing go down live! Sit back, grab some popcorn or any other snack and relax.
[h1]Controls[/h1]
[list][*]F2 (ShowTeam): Select A Team or Change Current Team.
[*]F3 (ShowSpare1): Play a Taunt.
[*]C (ShowContextMenu): Toggle between first and third person camera.
[*]Q (ShowSpawnMenu): Hold to rotate your object (Hider only).
[*]Ctrl (Duck, Crouch): Interact with objects instead of turning into them, allowing you to pick things up (Hiders only, Seekers always interact with things).
[*]R with the Prop Hunt SMG (Reload): On full magazine, switch between auto and burst fire.
[/list]
[h1]Support the Gamemode[/h1]
Spreading the word that Prop Hunt Extended exists, work together with others on the gamemode or just play it on your favourite server. Every single thing helps! You can also join our [url=https://discord.gg/tbqhAxr]Discord[/url] and perhaps find additional people to play with that way.
[h1]Need support?[/h1]
Please consider reading the [url=http://steamcommunity.com/workshop/filedetails/discussion/468149739/358415206095321277/]Frequently Asked Questions[/url] first. If nothing of that helped, either write a comment below or try asking your question in #gmod-prop-hunt-extended on [url=https://discord.gg/tbqhAxr]Discord[/url].
[h1]Want to join development?[/h1]
The entire source code is available under the MIT License [url=https://github.com/Xaymar/PropHuntExtended]on GitHub[/url].
-8
View File
@@ -1,8 +0,0 @@
{
"title" : "Prop Hunt Extended (Proxy Gamemode)",
"type" : "gamemode",
"tags" : [ ],
"ignore" : [
"addon.txt"
]
}
-9
View File
@@ -1,9 +0,0 @@
"AddonInfo"
{
"name" "Prop Hunt"
"version" "1.0.0"
"up_date" "00/00/00"
"author_name" "Xaymar"
"author_email" "info@xaymar.com"
"author_url" "https://xaymar.com/"
}
-401
View File
@@ -1,401 +0,0 @@
"prop_hunt"
{
"base" "prophuntextended"
"title" "Prop Hunt Extended"
"maps" "^ph_"
"menusystem" "1"
"workshopid" "468149739"
"settings"
{
// Debug Settings
1
{
"name" "ph_debug"
"text" "Enable Debug Mode"
"type" "CheckBox"
"default" "0"
"help" "Prop Hunt: Enable Debug Mode"
}
2
{
"name" "ph_debug_log"
"text" "Enable Debug Logging"
"type" "CheckBox"
"default" "1"
"help" "Prop Hunt: Enable Debug Logging"
}
// Basic Settings
100
{
"name" "ph_gametype"
"text" "Game Type to use"
"type" "Numeric"
"default" "0"
"help" "Prop Hunt: Which Game Type should be played?"
}
101
{
"name" "mp_timelimit"
"text" "Map Time Limit"
"type" "Numeric"
"default" "0"
"help" "Map Time Limit (in Minutes)"
}
102
{
"name" "mp_friendlyfire"
"text" "Friendly fire"
"type" "Numeric"
"default" "0"
"help" "Allow friendly fire? (0 = No, 1 = Yes, 2 = Reflect)"
}
// Round Settings
200
{
"name" "ph_round_limit"
"text" "Maximum Rounds Played"
"type" "Numeric"
"default" "10"
"help" "Round Manager: Maximum Rounds to Play on a single Map"
}
201
{
"name" "ph_round_timelimit"
"text" "Time Limit per Round"
"type" "Numeric"
"default" "180"
"help" "Round Manager: Time Limit per Round (in Seconds)"
}
202
{
"name" "ph_round_blindtime"
"text" "Seeker Blind time per Round"
"type" "Numeric"
"default" "-30"
"help" "Round Manager: Blind Time for Seekers (in Seconds, positive takes away from ph_round_timelimit, negative adds extra time to ph_round_timelimit)"
}
// Team Settings
300
{
"name" "ph_teams_randomize"
"text" "Randomize Teams"
"type" "CheckBox"
"default" "1"
"help" "Teams: Randomize Teams instead of swapping each round"
}
301
{
"name" "ph_teams_weighted"
"text" "Randomize with weighted Score"
"type" "CheckBox"
"default" "1"
"help" "Teams: Use Weighted Randomization"
}
302
{
"name" "ph_teams_seekerpct"
"text" "Pct of Pl. becoming Seeker"
"type" "Numeric"
"default" "25"
"help" "Teams: Initial percentage of Seekers in Dead Hunt Game Type"
}
// Seeker Settings
400
{
"name" "ph_seeker_health"
"text" "Seeker Health"
"type" "Numeric"
"default" "100"
"help" "Seekers: Initial Health"
}
401
{
"name" "ph_seeker_health_max"
"text" "Seeker Max Health"
"type" "Numeric"
"default" "100"
"help" "Seekers: Maximum Health"
}
402
{
"name" "ph_seeker_health_bonus"
"text" "Seeker Health Kill-Bonus"
"type" "Numeric"
"default" "20"
"help" "Seekers: Health Bonus per Kill"
}
403
{
"name" "ph_seeker_health_penalty"
"text" "Seeker Health Penalty"
"type" "Numeric"
"default" "5"
"help" "Seekers: Health Penalty per wrong Shot"
}
404
{
"name" "ph_seeker_weapons"
"text" "Seeker Weapons"
"type" "Text"
"default" "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun"
"help" "Seekers: Initial Weapons (Weapon,Weapon,...)"
}
405
{
"name" "ph_seeker_ammo"
"text" "Seeker Ammo"
"type" "Text"
"default" "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64"
"help" "Seekers: Initial Ammo (Ammo:Amount,Ammo:Amount,...)"
}
406
{
"name" "ph_seeker_walk_speed"
"text" "Seeker Walk Speed"
"type" "Numeric"
"default" "250"
"help" "Seekers: Walk Speed"
}
407
{
"name" "ph_seeker_sprint"
"text" "Seeker Sprint Allowed"
"type" "CheckBox"
"default" "1"
"help" "Seekers: Allow Sprinting"
}
408
{
"name" "ph_seeker_sprint_speed"
"text" "Seeker Sprint Speed"
"type" "Numeric"
"default" "500"
"help" "Seekers: Sprint Speed"
}
409
{
"name" "ph_seeker_jump_power"
"text" "Seeker Jump Power"
"type" "Numeric"
"default" "200"
"help" "Seekers: Jump Power"
}
// Hider Settings
500
{
"name" "ph_hider_health"
"text" "Hider Health"
"type" "Numeric"
"default" "100"
"help" "Hiders: Initial Health"
}
501
{
"name" "ph_hider_health_max"
"text" "Hider Max Health"
"type" "Numeric"
"default" "100"
"help" "Hiders: Maximum Health"
}
502
{
"name" "ph_hider_health_scaling"
"text" "Hider Enable Health Scaling"
"type" "CheckBox"
"default" "1"
"help" "Hiders: Enable Health Scaling"
}
503
{
"name" "ph_hider_health_scaling_max"
"text" "Hider Scaled Max Health"
"type" "Numeric"
"default" "200"
"help" "Hiders: Maximum scaled Health"
}
504
{
"name" "ph_hider_allow_full_rotation"
"text" "Hider 3-Dimensional Rotation"
"type" "CheckBox"
"default" "0"
"help" "Hiders: Enable full 3D Rotation"
}
505
{
"name" "ph_hider_walk_speed"
"text" "Hider Walk Speed"
"type" "Numeric"
"default" "250"
"help" "Hiders: Walk Speed"
}
506
{
"name" "ph_hider_sprint"
"text" "Hider Sprint Allowed"
"type" "CheckBox"
"default" "0"
"help" "Hiders: Allow Sprinting"
}
507
{
"name" "ph_hider_sprint_speed"
"text" "Hider Sprint Speed"
"type" "Numeric"
"default" "500"
"help" "Hiders: Sprint Speed"
}
507
{
"name" "ph_hider_jump_power"
"text" "Hider Jump Power"
"type" "Numeric"
"default" "200"
"help" "Hiders: Jump Power"
}
// Whitelist & Blacklist
600
{
"name" "ph_list_class_whitelist"
"text" "Allowed Entity Classes"
"type" "Text"
"default" "ph_prop,prop_physics,prop_physics_multiplayer,prop_physics_respawnable"
"help" "Anti-Cheat: Whitelisted Hider Classes"
}
601
{
"name" "ph_list_abuse_blacklist"
"text" "Abuse Blacklist"
"type" "Text"
"default" "func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable"
"help" "Anti-Cheat: Entity Abuse Blacklist"
}
602
{
"name" "ph_list_model_blacklist"
"text" "Model Blacklist"
"type" "Text"
"default" "models/props/cs_assault/dollar.mdl,models/props/cs_assault/money.mdl,models/props/cs_office/snowman_arm.mdl,models/props/cs_office/projector_remote.mdl"
"help" "Anti-Cheat: Model Abuse Blacklist"
}
// Taunts
700
{
"name" "ph_taunt_cooldown"
"text" "Cooldown for Taunts"
"type" "Numeric"
"default" "5"
"help" "Prop Hunt: Cooldown between Taunts"
}
701
{
"name" "ph_taunt_seekers"
"text" "Seeker Taunts"
"type" "Text"
"default" "bot/a_bunch_of_them.wav,bot/come_out_and_fight_like_a_man.wav,bot/come_out_wherever_you_are.wav,bot/come_to_papa.wav,bot/dont_worry_hell_get_it.wav,bot/hang_on_i_heard_something.wav,bot/hang_on_im_coming.wav,bot/i_dont_think_so.wav,bot/i_have_the_hostages.wav,bot/i_see_our_target.wav,bot/im_waiting_here.wav,bot/keeping_an_eye_on_the_hostages.wav,bot/nnno_sir.wav,bot/spotted_the_delivery_boy.wav,bot/target_acquired.wav,bot/target_spotted.wav,bot/you_heard_the_man_lets_go.wav"
"help" "Prop Hunt: Seeker Taunts"
}
702
{
"name" "ph_taunt_hiders"
"text" "Hider Taunts"
"type" "Text"
"default" "ambient/alarms/apc_alarm_pass1.wav,ambient/alarms/manhack_alert_pass1.wav,ambient/alarms/razortrain_horn1.wav,ambient/alarms/scanner_alert_pass1.wav,ambient/alarms/train_horn2.wav,ambient/alarms/train_horn_distant1.wav,ambient/alarms/warningbell1.wav,ambient/energy/whiteflash.wav,ambient/intro/alyxremove.wav,ambient/intro/logosfx.wav,ambient/levels/launch/1stfiringwarning.wav,ambient/levels/launch/rockettakeoffblast.wav,ambient/misc/ambulance1.wav,ambient/misc/carhonk1.wav,ambient/misc/carhonk2.wav,ambient/misc/carhonk3.wav,ambient/outro/gunshipcrash.wav,ambient/3dmeagle.wav,beams/beamstart5.wav,buttons/bell1.wav,buttons/weapon_cant_buy.wav,common/bass.wav,common/bugreporter_failed.wav,common/warning.wav,doors/door_squeek1.wav,friends/friend_join.wav,friends/friend_online.wav,friends/message.wav,hostage/hunuse/comeback.wav,hostage/hunuse/dontleaveme.wav,hostage/hunuse/yeahillstay.wav,items/gift_drop.wav,music/radio1.mp3,phx/eggcrack.wav,plats/elevbell1.wav,player/headshot1.wav,player/headshot2.wav,player/sprayer.wav,radio/enemydown.wav,radio/go.wav,radio/locknload.wav,radio/negative.wav,radio/rounddraw.wav,radio/takepoint.wav,resource/warning.wav,ui/achievement_earned.wav,ui/freeze_cam.wav,vehicles/junker/radar_ping_friendly1.wav,weapons/c4/c4_beep1.wav,weapons/c4/c4_click.wav,weapons/awp/awp1.wav,vo/canals/female01/gunboat_giveemhell.wav,vo/canals/female01/gunboat_justintime.wav,vo/canals/female01/stn6_incoming.wav,vo/canals/male01/gunboat_giveemhell.wav,vo/canals/male01/gunboat_justintime.wav,vo/canals/male01/stn6_incoming.wav,vo/canals/al_radio_stn6.wav,vo/canals/arrest_getgoing.wav,vo/canals/arrest_helpme.wav,vo/canals/arrest_lookingforyou.wav,vo/canals/boxcar_lethimhelp.wav,vo/canals/matt_closecall.wav,vo/canals/premassacre.wav,vo/ravenholm/aimforhead.wav,vo/ravenholm/bucket_patience.wav,vo/ravenholm/madlaugh01.wav,vo/ravenholm/madlaugh02.wav,vo/ravenholm/madlaugh03.wav,vo/ravenholm/madlaugh04.wav,weapons/strider_buster/ol12_stickybombcreator.wav,weapons/c4/c4_explode1.wav,weapons/357/357_fire2.wav,weapons/357/357_fire3.wav,weapons/scout/scout_fire-1.wav,weapons/smokegrenade/sg_explode.wav,weapons/grenade_launcher1.wav,weapons/explode3.wav,weapons/underwater_explode3.wav,items/nvg_on.wav,hostage/huse/letsdoit.wav,hostage/huse/illfollow.wav,hostage/huse/getouttahere.wav,doors/door_screen_move1.wav,doors/heavy_metal_stop1.wav,doors/default_move.wav,common/stuck2.wav,ambient/water_splash1.wav,ambient/water_splash2.wav,ambient/water_splash3.wav,ambient/weather/thunder1.wav,ambient/weather/thunder2.wav,ambient/weather/thunder3.wav,ambient/weather/thunder4.wav,ambient/weather/thunder5.wav,ambient/weather/thunder6.wav,ambient/outro/thunder7.wav,ambient/voices/crying_loop1.wav,ambient/voices/playground_memory.wav,ambient/voices/f_scream1.wav,ambient/voices/m_scream1.wav,ambient/voices/cough1.wav,ambient/voices/cough2.wav,ambient/voices/cough3.wav,ambient/voices/cough4.wav,ambient/overhead/plane1.wav,ambient/overhead/plane2.wav,ambient/overhead/plane3.wav,ambient/overhead/hel1.wav,ambient/overhead/hel2.wav,ambient/misc/truck_backup1.wav,ambient/misc/truck_drive1.wav,ambient/misc/truck_drive2.wav,ambient/machines/pneumatic_drill_1.wav,ambient/machines/pneumatic_drill_2.wav,ambient/machines/pneumatic_drill_3.wav,ambient/machines/pneumatic_drill_4.wav,ambient/machines/station_train_squeel.wav,ambient/machines/ticktock.wav,ambient/creatures/teddy.wav,ambient/creatures/town_child_scream1.wav,ambient/creatures/town_moan1.wav,ambient/creatures/town_muffled_cry1.wav,ambient/creatures/town_scared_breathing1.wav,ambient/creatures/town_scared_breathing2.wav,ambient/creatures/town_scared_sob1.wav,ambient/creatures/town_scared_sob2.wav,ambient/creatures/town_zombie_call1.wav"
"help" "Prop Hunt: Hider Taunts"
}
// Camera
800
{
"name" "ph_camera_allow_noclip"
"text" "Camera Noclip Allowed"
"type" "CheckBox"
"default" "0"
"help" "Camera: Allow clients to disable camera collision"
}
801
{
"name" "ph_camera_distance_max"
"text" "Camera Distance Max."
"type" "Numeric"
"default" "150"
"help" "Camera: Maximum allowed distance to player."
}
802
{
"name" "ph_camera_distance_min"
"text" "Camera Distance Min."
"type" "Numeric"
"default" "30"
"help" "Camera: Minimum allowed distance to player."
}
803
{
"name" "ph_camera_distance_right_range"
"text" "Camera Horizontal Offset Range"
"type" "Numeric"
"default" "20"
"help" "Camera: Horizontal allowed camera distance range."
}
804
{
"name" "ph_camera_distance_up_range"
"text" "Camera Vertical Offset Range"
"type" "Numeric"
"default" "20"
"help" "Camera: Vertical allowed camera distance range."
}
805
{
"name" "ph_camera_lag_min"
"text" "Camera Lag Min."
"type" "Numeric"
"default" "0"
"help" "Camera: Minimum Camera Lag."
}
806
{
"name" "ph_camera_lag_max"
"text" "Camera Lag Max."
"type" "Numeric"
"default" "0.95"
"help" "Camera: Maximum Camera Lag."
}
// Selection Halo
900
{
"name" "ph_selectionhalo_allow"
"text" "Selection Halo Allowed"
"type" "CheckBox"
"default" "1"
"help" "Selection Halo: Allow clients to enable halo around the currently looked at prop?"
}
901
{
"name" "ph_selectionhalo_approximate"
"text" "Selection Approximate Mode"
"type" "CheckBox"
"default" "1"
"help" "Selection Halo: Enable approximate selection halo, which only checks the forward vector on the client."
}
902
{
"name" "ph_selectionhalo_interval"
"text" "Selection Halo Allowed"
"type" "Numeric"
"default" "0.05"
"help" "Selection Halo: Interval for updates of the accuracte selection halo in seconds."
}
}
}
-9
View File
@@ -1,9 +0,0 @@
"AddonInfo"
{
"name" "Prop Hunt Extended"
"version" "1.4.0"
"up_date" "00/00/00"
"author_name" "Xaymar"
"author_email" "info@xaymar.com"
"author_url" "https://xaymar.com/"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1003 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

@@ -1,79 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local UI = {}
function UI:Init()
-- Initialize
self:SetVisible(false)
self:SetSize(1280, 720)
self:SetScreenLock(true)
self:SetTitle("Help & Settings")
self:SetDraggable(true)
self:SetSizable(true)
self:ShowCloseButton(true)
self:SetDeleteOnClose(false)
self.scale = 1.0
self.psh = vgui.Create("DPropertySheet", self)
self.psh:Dock(FILL)
self.psh:AddSheet("Help", vgui.Create("PHE_HelpUI_Help", self.psh))
self.psh:AddSheet("Settings", vgui.Create("PHE_HelpUI_Settings", self.psh))
-- Listen to DPI Updates
UIManager:Listen("UpdateDPI", self, function(dpi) self:UpdateDPI(dpi) end)
self:UpdateDPI(UIManager:GetDPIScale())
end
function UI:OnRemove()
UIManager:Silence("UpdateDPI", self)
self.psh:Remove()
end
function UI:Show()
self:Center()
self:SetVisible(true)
self:SetFocusTopLevel(true)
self:MakePopup()
end
function UI:Paint(w, h)
draw.RoundedBox(0, 0, 0, w, h, Color(0,0,0,240))
end
function UI:UpdateDPI(dpi)
local mult = dpi / self.scale
self.scale = dpi
local x, y = self:GetPos()
local w, h = self:GetSize()
local nw, nh = w * mult, h * mult
local ox, oy = (nw - w) / 2, (nh - h) / 2
self:SetSize(w * mult, h * mult)
self:SetPos(x - ox, y - oy)
end
derma.DefineControl("PHE_HelpUI", "Show Help UI Element", UI, "DFrameDPI");
@@ -1,235 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local UI = {}
function UI:Init()
self.time = CurTime() - 0.5
self.padding = 3
self.size = Vector(320, 30 + self.padding * 2)
self.size2 = Vector(60, self.size.y)
self.colors = {}
self.colors.background = Color(0, 0, 0, 204)
self.colors.title = Color(204, 204, 204, 255)
self.colors.text = Color(255, 255, 255, 255)
self.state = {}
self.state.name = ""
self.ui = {}
self:DockPadding(self.padding, self.padding, self.padding, self.padding)
self.ui.bar = vgui.Create("DShape", self)
self.ui.bar:SetType("Rect")
self.ui.bar:SetSize(0, 5)
self.ui.bar:Dock(BOTTOM)
self.ui.round = vgui.Create("Panel", self)
self.ui.round:Dock(LEFT)
self.ui.round:SetSize(100, self.size.y)
self.ui.round_title = vgui.Create("DLabelDPI", self.ui.round)
self.ui.round_title:SetFontEx({ size = 10 })
self.ui.round_title:SetText("Round")
self.ui.round_title:SetColor(self.colors.title)
self.ui.round_title:SetContentAlignment(2)
self.ui.round_title:SizeToContents()
self.ui.round_title:Dock(TOP)
self.ui.round_text = vgui.Create("DLabelDPI", self.ui.round)
self.ui.round_text:SetFontEx({ size = 14 })
self.ui.round_text:SetText("0 / 10")
self.ui.round_text:SetColor(self.colors.text)
self.ui.round_text:SetContentAlignment(8)
self.ui.round_text:Dock(FILL)
self.ui.time = vgui.Create("Panel", self)
self.ui.time:Dock(RIGHT)
self.ui.time:SetSize(100, self.size.y)
self.ui.time_title = vgui.Create("DLabelDPI", self.ui.time)
self.ui.time_title:SetFontEx({ size = 10 })
self.ui.time_title:SetText("Time")
self.ui.time_title:SetColor(self.colors.title)
self.ui.time_title:SetContentAlignment(2)
self.ui.time_title:SizeToContents()
self.ui.time_title:Dock(TOP)
self.ui.time_text = vgui.Create("DLabelDPI", self.ui.time)
self.ui.time_text:SetFontEx({ size = 14 })
self.ui.time_text:SetText("00:00")
self.ui.time_text:SetColor(self.colors.text)
self.ui.time_text:SetContentAlignment(8)
self.ui.time_text:Dock(FILL)
self.ui.state = vgui.Create("Panel", self)
self.ui.state:Dock(FILL)
self.ui.state_title = vgui.Create("DLabelDPI", self.ui.state)
self.ui.state_title:SetFontEx({ size = 14 })
self.ui.state_title:SetText("Waiting for Server...")
self.ui.state_title:SetColor(self.colors.title)
self.ui.state_title:SetContentAlignment(2)
self.ui.state_title:SizeToContents()
self.ui.state_title:Dock(TOP)
self.ui.state_text = vgui.Create("DLabelDPI", self.ui.state)
self.ui.state_text:SetFontEx({ size = 10 })
self.ui.state_text:SetText("Waiting for Server...")
self.ui.state_text:SetColor(self.colors.text)
self.ui.state_text:SetContentAlignment(8)
self.ui.state_text:Dock(FILL)
hook.Add("RoundManagerEnterState", self, self.HandleEnterState);
UIManager:Listen("UpdateDPI", self, function(dpi) self:UpdateDPI(dpi) end)
self:UpdateDPI(UIManager:GetDPIScale())
end
function UI:OnRemove()
UIManager:Silence("UpdateDPI", self)
end
function UI:Think()
-- Only update once every 1/20th of a second.
if ((CurTime() - self.time) < 0.05) then
return
end
self.time = CurTime()
-- Update Time
self.ui.time_text:SetText(string.format("%02d:%02d",
math.floor(GAMEMODE:GetRoundTime() / 60),
math.floor(GAMEMODE:GetRoundTime() % 60)))
-- Update State Text
local round_time = GAMEMODE:GetRoundStateTime()
local team_id = GAMEMODE.Teams.Spectator
if (LocalPlayer() && LocalPlayer():IsPlayer()) then
team_id = LocalPlayer():Team()
end
if (self.state.name == "Hide") then
if (team_id == GAMEMODE.Teams.Seekers) then
self.ui.state_text:SetText(string.format("You will be unblinded in %02d:%02d",
math.floor(round_time / 60), math.floor(round_time % 60)))
else
self.ui.state_text:SetText(string.format("Seekers unblinded in %02d:%02d...",
math.floor(round_time / 60), math.floor(round_time % 60)))
end
elseif (self.state.name == "Seek") then
if (team_id == GAMEMODE.Teams.Seekers) then
self.ui.state_text:SetText(string.format("You have %02d:%02d left to kill all Hiders.",
math.floor(round_time / 60), math.floor(round_time % 60)))
else
self.ui.state_text:SetText(string.format("You have %02d:%02d left to annoy all Seekers.",
math.floor(round_time / 60), math.floor(round_time % 60)))
end
end
end
function UI:Paint()
local w,h = self:GetSize()
draw.RoundedBox(0, 0, 0, w, h, self.colors.background)
end
function UI:PerformLayout(w, h)
end
function UI:UpdateDPI(dpi)
local w, h = self.size.x * dpi, self.size.y * dpi
local w2, h2 = self.size2.x * dpi, self.size2.y * dpi
self.ui.round:SetSize(w2, h2)
self.ui.time:SetSize(w2, h2)
self:DockPadding(self.padding * dpi, self.padding * dpi, self.padding * dpi, self.padding * dpi)
self:SetSize(w, h)
self:CenterHorizontal()
self:AlignTop(20 * dpi)
self.ui.round:InvalidateLayout()
self.ui.time:InvalidateLayout()
self:InvalidateLayout()
end
function UI:UpdateStateDisplay()
local team_id = GAMEMODE.Teams.Spectator
if (LocalPlayer() && LocalPlayer():IsPlayer()) then
team_id = LocalPlayer():Team()
end
-- Update Team Color
self.ui.bar:SetColor(team.GetColor(team_id))
-- Update State itself
if (self.state.name == "PreMatch") then
self.ui.state_title:SetText(team.GetName(team_id))
self.ui.state_text:SetText(string.format("Waiting for players..."))
elseif (self.state.name == "PreRound") then
self.ui.state_title:SetText(team.GetName(team_id))
self.ui.state_text:SetText(string.format("Round starts soon..."))
elseif (self.state.name == "Hide") then
local round_time = GAMEMODE:GetRoundStateTime()
if (team_id == GAMEMODE.Teams.Seekers) then
self.ui.state_title:SetText("Blinded! Get ready to seek.")
else
self.ui.state_title:SetText("Hiding Time!")
end
elseif (self.state.name == "Seek") then
local round_time = GAMEMODE:GetRoundStateTime()
if (team_id == GAMEMODE.Teams.Seekers) then
self.ui.state_title:SetText("Seek & Destroy!")
else
self.ui.state_title:SetText("Hide & Avoid!")
end
elseif (self.state.name == "PostRound") then
self.ui.state_text:SetText("Next Round starting soon...")
local winner = GAMEMODE:GetRoundWinner()
if (winner == GAMEMODE.Teams.Spectators) then
self.ui.state_title:SetText("Draw! Everybody lost.")
elseif (winner == GAMEMODE.Teams.Seekers) then
self.ui.state_title:SetText("Seekers Win!")
elseif (winner == GAMEMODE.Teams.Hiders) then
self.ui.state_title:SetText("Hiders Win!")
end
elseif (self.state.name == "PostMatch") then
self.ui.state_title:SetText(team.GetName(team_id))
end
end
function UI:HandleEnterState(id, name)
self.state.name = name
-- Update Round
if (GAMEMODE.Config.Round:Limit() > 0) then
self.ui.round_text:SetText(string.format("%d / %d", GAMEMODE:GetRound(), GAMEMODE.Config.Round:Limit()))
else
self.ui.round_text:SetText(string.format("%d / ∞", GAMEMODE:GetRound()))
end
self:UpdateStateDisplay()
end
vgui.Register("PHE_GameState", UI, "Panel")
@@ -1,75 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2019 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local CLASS = {}
CLASS.__index = CLASS
local netmsg = { -- Keep in sync with server table.
refresh = "RoundManagerUpdate",
winner = "RoundManagerWinner"
}
function CLASS:__construct()
self.state = nil
self.state_name = ""
net.Receive(netmsg.refresh, function(len, pl) self:__netRefresh(len, pl) end)
net.Receive(netmsg.winner, function(len, pl) self:__netWinner(len, pl) end)
end
function CLASS:GetStateId()
return self.state
end
function CLASS:GetStateName()
return self.state_name
end
function CLASS:CanJoinTeam(team)
if (LocalPlayer():Team() == team) then
return false
end
end
function CLASS:__netRefresh(len, pl)
local data = net.ReadTable()
if (self.state != data.state) then
hook.Run("RoundManagerLeaveState", self.state, self.state_name)
self.state = data.state
self.state_name = data.state_name
hook.Run("RoundManagerEnterState", self.state, self.state_name)
end
end
function CreateRoundManager()
local obj = {}
obj.__index = obj
setmetatable(obj, CLASS)
obj:__construct()
return obj
end
_G["RoundManager"] = CreateRoundManager()
@@ -1,107 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local FontManagerMeta = {}
FontManagerMeta.__index = FontManagerMeta
-- Global Constructor
function FontManager()
local obj = {}
obj.__index = obj
setmetatable(obj, FontManagerMeta)
obj:__construct()
return obj
end
-- Constructor
function FontManagerMeta:__construct()
self.fonts = {}
end
function FontManagerMeta:Exists(name)
if (self.fonts[name] != nil) then
return true
end
return false
end
function FontManagerMeta:CreateFontData(settings)
local base = {}
base.font = "Roboto"
base.extended = true
base.size = 13
base.weight = 500
base.blursize = 0
base.scanlines = 0
base.antialias = true
base.underline = false
base.italic = false
base.strikeout = false
base.symbol = false
base.rotary = false
base.shadow = false
base.additive = false
base.outline = false
local final = table.Merge(base, settings)
return final
end
function FontManagerMeta:CreateFont(settings)
local final = self:CreateFontData(settings)
local name = self:ToName(final)
return self:Request(name, final)
end
function FontManagerMeta:ToName(settings)
local name = settings.font
name = name .. "[S" .. settings.size
name = name .. "W" .. settings.weight
if (settings.blursize > 0) then name = name .. "B" .. settings.blursize end
if (settings.scanlines > 0) then name = name .. "L" .. settings.scanlines end
if (settings.antialias) then name = name .. "A" end
if (settings.extended) then name = name .. "E" end
if (settings.underline) then name = name .. "U" end
if (settings.italic) then name = name .. "I" end
if (settings.strikeout) then name = name .. "-" end
if (settings.shadow) then name = name .. "S" end
if (settings.outline) then name = name .. "O" end
if (settings.additive) then name = name .. "+" end
if (settings.rotary) then name = name .. "R" end
if (settings.symbol) then name = name .. "#" end
name = name .. "]"
return name
end
function FontManagerMeta:Request(name, settings)
if (self.fonts[name] != nil) then
--print("[Prop Hunt Font Manager] Request for font '"..name.."' received and cached.")
return name
end
print("[Font Manager] Creating new Font '"..name.."'...")
self.fonts[name] = surface.CreateFont(name, settings)
return name
end
_G["FontManager"] = FontManager()
@@ -1,148 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2019 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- Help Panel
local UI = {}
local HTML = [[
<!DOCTYPE html>
<html>
<head>
<style>
body {
font-family: Roboto;
font-size: 18pt;
color: rgba(255, 255, 255, 1.0);
background: rgba(51, 51, 51, 1.0);
}
div, p {
margin: 0;
padding: 0;
}
p + p {
margin-top: 10pt;
}
</style>
</head>
<body>
<div id="about">
<h1>About Prop Hunt Extended</h1>
<p>
Hide n Seek with a twist: Hiders can turn into anything on the map! From bottles, to vending machines and all the way to huge cars, what you become depends on how you want to play. Do you want to blend in with your surroundings, or do you want to make a fool of the Seekers? And how will you deal with finding (and killing) all hiders as a Seeker?
</p>
<p>
The Gamemode comes with out of the box support for console configuration (ph_*), custom taunt support, prop rotation, an improved code base for modders and better integration and some other fixes. Support for MapVote is also built in, so as long as you have a compatible addon installed you will get a map voting menu at the end of a match.
</p>
<p>
<h2>Help Develop:</h2>
The Gamemode is Open Source under the MIT License <a href="https://github.com/xaymar/prophuntextended" target="_blank">on Github</a>.
</p>
</div>
<div id="howto">
<h2>How To Play</h2>
<p>
<h3>Seekers</h3>
Your primary goal is to find hiders by any means possible. But watch out, you might lose health if you shoot an object that isn't actually a hider! Pick things up before shooting them, or simply remember the layout of the maps you are playing on. And remember: You lose if only a single hider is still alive at the end of the round.
</p>
<p>
<h3>Hiders</h3>
Stay alive as long as possible and make Seekers look like a fool. Dance around their feet, hide in plain sight or be that huge car that nobody though you could become! What you do is entirely up to you.
</p>
<p>
<h3>Spectators</h3>
You get to watch the whole thing go down live! Sit back, grab some popcorn or any other snack and relax.
</p>
</div>
<div id="controls">
<h2>Controls</h2>
<table>
<tr>
<th>Key/Button</th>
<th>Control Name</th>
<th>Description</th>
</tr>
<tr>
<td>F1</td>
<td>ShowHelp</td>
<td>Opens the Help and Settings window for this gamemode.</td>
</tr>
<tr>
<td>F2</td>
<td>ShowTeam</td>
<td>Change the team.</td>
</tr>
<tr>
<td>F3</td>
<td>ShowSpare1</td>
<td>Play a random Taunt, if it is not currently on cooldown.</td>
</tr>
<tr>
<td>C</td>
<td>ShowContextMenu</td>
<td>Toggle between 1st and 3rd Person Camera.</td>
</tr>
<tr>
<td>Q</td>
<td>ShowSpawnMenu</td>
<td>Tap to rotate the prop towards your current view angle, hold to continue rotating.</td>
</tr>
<tr>
<td>Ctrl + E</td>
<td>Duck + Use</td>
<td>Interact with objects, such as picking them up, opening doors, or pushing buttons, instead of turning into the object you are targeting.</td>
</tr>
</table>
</div>
</body>
</html>
]]
function UI:Init()
self.content = vgui.Create("DHTML", self)
self.content:Dock(FILL)
self.content:SetHTML(HTML)
self.content.OnChildViewCreated = function(source, target, isPopup)
gui.OpenURL(target)
print(source)
print(target)
print(isPopup)
end
self.content.OnChangeTargetURL = function(url)
print(url)
end
-- GAMEMODE.UIManager:Listen("UpdateDPI", self, function(dpi) self:UpdateDPI(dpi) end)
-- self:UpdateDPI(GAMEMODE.UIManager:GetDPIScale())
end
function UI:OnRemove()
self.content:Remove()
-- GAMEMODE.UIManager:Silence("UpdateDPI", self)
end
derma.DefineControl("PHE_HelpUI_Help", "Help Page for Prop Hunt Extended", UI, "DPanel");
@@ -1,340 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local DPlayerEntry = {}
function DPlayerEntry:Init()
self.Data = {}
self.Data.Margin = {
left = 0,
top = 0,
right = 0,
bottom = 0
}
self.Data.LastUpdate = CurTime() - 10
self.Data.Player = nil
self:SetMinimumSize(100, 40)
self.Container = vgui.Create("DPanel", self)
self.Container:SetBackgroundColor(Color(127,127,127,255))
self.Container:SetPaintBackground(true)
self.Container:Dock(FILL)
self.Container:DockMargin(0, 0, 0, 0)
self.Avatar = vgui.Create("AvatarImage", self.Container)
self.Avatar:Dock(LEFT)
self.Name = vgui.Create("DLabel", self.Container)
self.Name:SetText("Unknown")
self.Name:SetFont("Roboto24")
self.Name:SetContentAlignment(4)
self.Name:Dock(FILL)
self.Name:DockMargin(10, 5, 10, 5)
self.Deaths = vgui.Create("DLabel", self.Container)
self.Deaths:SetSize(80, 30)
self.Deaths:SetText("N/A")
self.Deaths:SetFont("Roboto24")
self.Deaths:SetContentAlignment(6)
self.Deaths:Dock(RIGHT)
self.Deaths:DockMargin(10, 5, 10, 5)
self.Kills = vgui.Create("DLabel", self.Container)
self.Kills:SetSize(80, 30)
self.Kills:SetText("N/A")
self.Kills:SetFont("Roboto24")
self.Kills:SetContentAlignment(6)
self.Kills:Dock(RIGHT)
self.Kills:DockMargin(10, 5, 10, 5)
end
function DPlayerEntry:PerformLayout(w, h)
self:SetMinimumSize(
100 + self.Data.Margin.left + self.Data.Margin.right,
40 + self.Data.Margin.top + self.Data.Margin.bottom
)
-- Docked Content
local containerX, containerY, containerW, containerH = self.Container:GetBounds()
self.Avatar:SetSize(containerH, containerH)
self.Kills:SetSize(80, containerH - 10)
self.Deaths:SetSize(80, containerH - 10)
end
function DPlayerEntry:Think()
if (CurTime() - self.Data.LastUpdate) < 0.25 then return end
if IsValid(self.Data.Player) then
self.Avatar:SetPlayer(self.Data.Player, 184)
self.Name:SetText(self.Data.Player:GetName())
self.Kills:SetText(self.Data.Player:Frags())
self.Deaths:SetText(self.Data.Player:Deaths())
end
end
function DPlayerEntry:SetMargin(left, top, right, bottom)
local uleft = left or 0
local utop = top or uleft
local uright = right or uleft
local ubottom = bottom or utop
self.Container:DockMargin(uleft, utop, uright, ubottom)
self:InvalidateLayout()
end
function DPlayerEntry:SetBackgroundColor(clr)
self.Container:SetBackgroundColor(clr)
end
function DPlayerEntry:SetForegroundColor(clr)
self.Name:SetColor(clr)
self.Kills:SetColor(clr)
self.Deaths:SetColor(clr)
end
function DPlayerEntry:SetPlayer(ply)
self.Data.Player = ply
end
function DPlayerEntry:ShowFlags(kills, deaths)
self.Kills:SetVisible(kills)
self.Deaths:SetVisible(deaths)
self.Container:InvalidateLayout()
end
vgui.Register("DPlayerEntry", DPlayerEntry, "Panel")
local DPlayerList = {}
function DPlayerList:Init()
self.Data = {}
self.Data.Time = CurTime() - 1
self.Data.Team = nil
self.Data.Players = {}
self.Data.ShowKills = true
self.Data.ShowDeaths = true
self.Container = vgui.Create("DPanel", self)
self.Container:SetPaintBackground(true)
self.Container:SetBackgroundColor(Color(51, 51, 51, 102))
self.Container:Dock(FILL)
self.Title = vgui.Create("DPanel", self.Container)
self.Title:SetSize(1, 40)
self.Title:Dock(TOP)
self.Title:DockMargin(0, 0, 0, 5)
self.Title.Name = vgui.Create("DLabel", self.Title)
self.Title.Name:SetText("Unknown")
self.Title.Name:SetFont("Roboto32Bold")
self.Title.Name:SetContentAlignment(5)
self.Title.Name:Dock(FILL)
self.Title.Name:DockMargin(10, 5, 10, 5)
self.Title.Deaths = vgui.Create("DLabel", self.Title)
self.Title.Deaths:SetText("Deaths")
self.Title.Deaths:SetFont("Roboto24")
self.Title.Deaths:SetContentAlignment(6)
self.Title.Deaths:SetSize(80, 40)
self.Title.Deaths:Dock(RIGHT)
self.Title.Deaths:DockMargin(10, 5, 10, 5)
self.Title.Kills = vgui.Create("DLabel", self.Title)
self.Title.Kills:SetText("Kills")
self.Title.Kills:SetFont("Roboto24")
self.Title.Kills:SetContentAlignment(6)
self.Title.Kills:SetSize(80, 40)
self.Title.Kills:Dock(RIGHT)
self.Title.Kills:DockMargin(10, 5, 10, 5)
self.Scroll = vgui.Create("DScrollPanel", self.Container)
self.Scroll:Dock(FILL)
self.Layout = vgui.Create("DListLayout", self.Scroll)
self.Layout:Dock(FILL)
end
function DPlayerList:PerformLayout(w, h)
--self.Container:SetSize(w, h)
end
function DPlayerList:Think()
if (self.Data.Team == -1) then return end
if ((CurTime() - self.Data.Time) < 0.1) then return end
self.Data.Time = CurTime()
-- Update Team Information
if (self.Data.Team != nil) then
self.Title:SetBackgroundColor(team.GetColor(self.Data.Team))
-- Name
self.Title.Name:SetText(team.GetName(self.Data.Team))
-- Text Color
local hue,sat,val = ColorToHSV(team.GetColor(self.Data.Team))
sat = sat * 0.1
val = val * 0.1
local col = HSVToColor(hue,sat,val)
self.Title.Name:SetColor(col)
self.Title.Kills:SetColor(col)
self.Title.Deaths:SetColor(col)
end
-- Update living players
local pls = team.GetPlayers(self.Data.Team)
for i,v in ipairs(pls) do
local alive = player_manager.RunClass(v, "Alive")
local gui = self.Data.Players[v]
if (gui == nil) then
gui = vgui.Create("DPlayerEntry")
gui:SetPlayer(v)
gui:SetMargin(0, 0, 0, 5)
gui:Stop()
gui:SetAlpha(0)
gui:AlphaTo(255, 1)
self.Data.Players[v] = gui
self.Layout:Add(gui)
end
if (alive) then
local hue,sat,val = ColorToHSV(team.GetColor(self.Data.Team))
local sat2,val2 = sat * 0.8, val * 0.8
gui:SetBackgroundColor(HSVToColor(hue, sat2, val2))
local sat3,val3 = sat * 0.1, val
gui:SetForegroundColor(HSVToColor(hue, sat3, val3))
else
local hue,sat,val = ColorToHSV(team.GetColor(self.Data.Team))
local sat2,val2 = sat * 0.8, val * 0.1
gui:SetBackgroundColor(HSVToColor(hue, sat2, val2))
local sat3,val3 = sat * 0.1, val
gui:SetForegroundColor(HSVToColor(hue, sat3, val3))
end
gui:ShowFlags(self.Data.ShowKills, self.Data.ShowDeaths)
end
-- Find dead players
for ply,gui in pairs(self.Data.Players) do
if (!table.HasValue(pls, ply)) then
self.Data.Players[ply] = nil
gui:Stop()
gui:AlphaTo(0, 1)
gui:SetTerm(1)
end
end
self.Layout:InvalidateLayout()
self.Scroll:InvalidateLayout()
end
function DPlayerList:SetTeam(team)
self.Data.Team = team
end
function DPlayerList:ShowFlags(kills, deaths)
self.Data.ShowKills = kills
self.Data.ShowDeaths = deaths
self.Title.Kills:SetVisible(self.Data.ShowKills)
self.Title.Deaths:SetVisible(self.Data.ShowDeaths)
self.Title:InvalidateLayout()
end
vgui.Register("DPlayerList", DPlayerList, "Panel")
local DScoreBoard = {}
function DScoreBoard:Init()
self.Container = vgui.Create("DPanel", self)
self.Container:SetPaintBackground(true)
self.Container:SetBackgroundColor(Color(0, 0, 0, 240))
self.Container:Dock(FILL)
self.Container:DockMargin(0, 35, 0, 0)
self.Logo = vgui.Create("DImage", self)
self.Logo:SetImage("prophuntextended/scoreboard_logo.png")
self.Logo:SetKeepAspect(true)
self.Logo:SetSize(580, 70)
self.Logo:SetPos(10, 0)
self.Frame = vgui.Create("DPanel", self.Container)
self.Frame:SetPaintBackground(false)
self.Frame:Dock(FILL)
self.Frame:DockMargin(5, 40, 5, 5)
self.Teams = {}
self.Teams.Seekers = vgui.Create("DPlayerList", self.Frame)
self.Teams.Seekers:SetTeam(GAMEMODE.Teams.Seekers)
self.Teams.Seekers:Dock(LEFT)
self.Teams.Seekers:DockMargin(5, 5, 5, 5)
self.Teams.Hiders = vgui.Create("DPlayerList", self.Frame)
self.Teams.Hiders:SetTeam(GAMEMODE.Teams.Hiders)
self.Teams.Hiders:Dock(RIGHT)
self.Teams.Hiders:DockMargin(5, 5, 5, 5)
self.Teams.Spectators = vgui.Create("DPlayerList", self.Container)
self.Teams.Spectators:SetSize(100, 100)
self.Teams.Spectators:SetTeam(GAMEMODE.Teams.Spectators)
self.Teams.Spectators:ShowFlags(false, false)
self.Teams.Spectators:Dock(BOTTOM)
self.Teams.Spectators:DockMargin(10, 0, 10, 10)
self:SetVisible(false)
self:SetAlpha(0)
end
function DScoreBoard:PerformLayout(w, h)
local frameW, frameH = self.Frame:GetSize()
local contW, contH = self.Container:GetSize()
-- Update Team Lists
self.Teams.Seekers:SetSize(frameW / 2 - 10, 0)
self.Teams.Hiders:SetSize(frameW / 2 - 10, 0)
self.Teams.Spectators:SetSize(100, contH / 5)
self.Frame:InvalidateLayout()
self.Container:InvalidateLayout()
end
function DScoreBoard:Show()
-- Size and Position
local w, h = ScrW() / 2, ScrH() / 4 * 3
if (w < 600) then w = 600 end
if (h < 400) then h = 400 end
self:SetSize(w, h)
self:Center()
-- Visibility
self:Stop()
self:AlphaTo(255, 0.1)
self:SetVisible(true)
-- Focus
self:SetPopupStayAtBack(true)
self:SetFocusTopLevel(true)
self:RequestFocus()
end
function DScoreBoard:Hide()
-- Visibility
self:Stop()
self:AlphaTo(0, 0.1, 0, function(animData, pnl)
pnl:SetVisible(false)
end)
end
vgui.Register("DScoreBoard", DScoreBoard, "EditablePanel")
@@ -1,43 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2019 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local UI = {}
function UI:Init()
self.text = vgui.Create("DLabelDPI", self)
self.text:SetText("Hello World")
UIManager:Listen("UpdateDPI", self, function(dpi) self:UpdateDPI(dpi) end)
self:UpdateDPI(UIManager:GetDPIScale())
end
function UI:OnRemove()
UIManager:Silence("UpdateDPI", self)
end
function UI:UpdateDPI(dpi)
end
derma.DefineControl("PHE_HelpUI_Settings", "Settings Page for Prop Hunt Extended", UI, "DPanel");
@@ -1,182 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
--[[
# Class UIManager
UIManager is used to simplify the logic required to keep the GameMode's UI looking
good by simply moving all the logic into a single class and then handing off
the UI control to the windows themselves.
# Events
Events must be explicitly listened to by the client object. A client must first call
UIManager:Listen(string event, any uniqueId, function callback)
to listen to an event and call
UIManager:Silence(string event, any uniqueId)
to stop listening to an event.
## UpdateDPI(float DPIPercent)
Called whenever a change is made to the DPI, such as a change in the screen resolution,
or an update from the user of this class. Only parameter is DPI, which is a float.
1.0 designates 100%, 2.0 designates 200% and so on.
--]]
local UIManagerMeta = {}
UIManagerMeta.__index = UIManagerMeta
-- Global Constructor
function UIManager()
local obj = {}
obj.__index = obj
setmetatable(obj, UIManagerMeta)
obj:__construct()
return obj
end
-- Constructor
function UIManagerMeta:__construct()
self:InitializeEvents()
self:UpdateScreen()
self:InitializeDPI()
end
-- Events
function UIManagerMeta:InitializeEvents()
self.events = {}
end
function UIManagerMeta:Listen(event, uniqueName, callback)
assert(type(event) == "string", "UIManager:Listen(event<string>, uniqueName<any>, callback<function>): event must be a string")
assert(type(callback) == "function", "UIManager:Listen(event<string>, uniqueName<any>, callback<function>): callback must be a function")
if (self.events[event] == nil) then
self.events[event] = {}
end
self.events[event][uniqueName] = callback
return true
end
function UIManagerMeta:Silence(event, uniqueName)
assert(type(event) == "string", "UIManager:Silence(event<string>, uniqueName<any>): event must be a string")
if (self.events[event] == nil) then
return false
end
if (self.events[event][uniqueName] == nil) then
return false
end
self.events[event][uniqueName] = nil
return true
end
function UIManagerMeta:Call(event, ...)
if (self.events[event] == nil) then
return
end
for k,v in pairs(self.events[event]) do
v(...)
end
end
-- Screen
function UIManagerMeta:UpdateScreen()
if (self.screen == nil) then
self.screen = {}
end
if ((self.screen.width != ScrW()) || (self.screen.height != ScrH())) then
self.screen.width = ScrW()
self.screen.height = ScrH()
return true
end
return false
end
-- Tick
function UIManagerMeta:Tick()
if (self:UpdateScreen() == true) then
self.dpi.calculated = self:CalculateDPI()
self:SetDPIScale(self.dpi.override)
end
end
-- DPI Scaling
function UIManagerMeta:InitializeDPI()
self.dpi = {}
-- Calculate DPI using these base sizes.
self.dpi.base = {}
self.dpi.base.width = 1280
self.dpi.base.height = 720
-- Limits
self.dpi.limits = {}
self.dpi.limits.min = 0.25
self.dpi.limits.max = 10.00
-- Final Value
self.dpi.override = nil
self.dpi.calculated = self:CalculateDPI()
end
function UIManagerMeta:CalculateDPI()
--[[
DPI Scaling is linear in respect to the base resolution.
That means that at 50% of the Base resolution, the output is 0.5,
and at 200% of the Base resolution, the output is 2.0.
--]]
-- Shortest Edge scaling
local wScale, hScale = self.screen.width / self.dpi.base.width, self.screen.height / self.dpi.base.height
if (wScale < hScale) then
return wScale
end
return hScale
end
function UIManagerMeta:GetDPIScale()
if (self.dpi.override != nil) then
return self.dpi.override
end
return self.dpi.calculated
end
function UIManagerMeta:SetDPIScale(newDPIScale)
self.dpi.override = newDPIScale
if (self.dpi.override == nil) then
self:Call("UpdateDPI", self.dpi.calculated)
else
if (self.dpi.override < self.dpi.limits.min) then
self.dpi.override = self.dpi.limits.min
end
if (self.dpi.override > self.dpi.limits.max) then
self.dpi.override = self.dpi.limits.max
end
self:Call("UpdateDPI", self.dpi.override)
end
end
_G["UIManager"] = UIManager()
@@ -1,64 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2019 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- DPI Aware Frame
local UI = {}
function UI:Init()
self.scale = 1.0
self.fontdata = FontManager:CreateFontData({})
UIManager:Listen("UpdateDPI", self, function(dpi) self:UpdateDPI(dpi) end)
self:UpdateDPI(UIManager:GetDPIScale())
end
function UI:OnRemove()
UIManager:Silence("UpdateDPI", self)
end
function UI:SetFontEx(fontData)
self.fontdata = FontManager:CreateFontData(fontData)
local scaled = table.Merge({}, self.fontdata)
scaled.size = math.Round(self.fontdata.size * self.scale)
scaled.blursize = math.Round(self.fontdata.blursize * self.scale)
self.font = FontManager:Request(FontManager:ToName(scaled), scaled)
self.lblTitle:SetFont(self.font)
self.lblTitle:InvalidateLayout()
self.lblTitle:InvalidateParent()
--self.btnClose:SetFont(self.font)
--self.btnMinim:SetFont(self.font)
--self.btnMaxim:SetFont(self.font)
end
function UI:UpdateDPI(dpi)
self.scale = dpi
self:SetFontEx(self.fontdata)
--self:InvalidateLayout()
--self:InvalidateParent()
end
derma.DefineControl("DFrameDPI", "DPI Aware DFrame (requires UIManager)", UI, "DFrame");
@@ -1,58 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2019 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- DPI Aware Label
local UI = {}
function UI:Init()
self.scale = 1.0
self.fontdata = FontManager:CreateFontData({})
UIManager:Listen("UpdateDPI", self, function(dpi) self:UpdateDPI(dpi) end)
self:UpdateDPI(UIManager:GetDPIScale())
end
function UI:OnRemove()
UIManager:Silence("UpdateDPI", self)
end
function UI:SetFontEx(fontData)
self.fontdata = FontManager:CreateFontData(fontData)
local scaled = table.Merge({}, self.fontdata)
scaled.size = math.Round(self.fontdata.size * self.scale)
scaled.blursize = math.Round(self.fontdata.blursize * self.scale)
self:SetFont(FontManager:Request(FontManager:ToName(scaled), scaled))
end
function UI:UpdateDPI(dpi)
self.scale = dpi
self:SetFontEx(self.fontdata)
self:InvalidateLayout()
self:InvalidateParent()
end
derma.DefineControl("DLabelDPI", "DPI Aware DLabel (requires UIManager)", UI, "DLabel");
@@ -1,259 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2017 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- Finds the player meta table or terminates
local meta = FindMetaTable("Player")
if !meta then print("FAILED TO FIND PLAYER META") return end
-- Blinds the player by setting view out into the void
function meta:Blind(bool)
if !self:IsValid() then return end
if SERVER then
umsg.Start("SetBlind", self)
if bool then
umsg.Bool(true)
else
umsg.Bool(false)
end
umsg.End()
elseif CLIENT then
blind = bool
end
end
-- Blinds the player by setting view out into the void
function meta: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
-- Sets a new Hull for a player.
function meta:NewHull(hullOBBMin, hullOBBMax)
if !self:IsValid() then return end
if hullOBBMax == nil then return end
if hullOBBMin == nil then return end
local hullOBB = hullOBBMax - hullOBBMin
local hullOBBXY = math.max(hullOBB.x, hullOBB.y)
local xyMul = 0.5
local hullMin = Vector(-hullOBBXY * xyMul, -hullOBBXY * xyMul, 0)
local hullMax = Vector( hullOBBXY * xyMul, hullOBBXY * xyMul, hullOBB.z)
self:SetHull(hullMin, hullMax)
self:SetHullDuck(hullMin, hullMax)
self:SetViewOffset(Vector(0, 0, hullOBB.z))
self:SetViewOffsetDucked(Vector(0, 0, hullOBB.z / 2.0))
end
-- Can the passed entity be used by the player?
function testflag(set, flag)
if (flag == 0) then return true end -- Mod(%) by 0 is nan.
return (set % (2 * flag)) >= flag
end
function meta:IsUseableEntity(ent, requiredCaps)
if ((ent != nil) && (ent:IsValid())) then
local caps = ent:ObjectCaps()
local capsmask = 16 + 32 + 64 + 128
if (testflag(caps, 16)
|| testflag(caps, 32)
|| testflag(caps, 64)
|| testflag(caps, 128)
) && testflag(caps, requiredCaps) then
return true
end
end
return false
end
function IntervalDistance(x, x0, x1)
-- swap so x0 < x1
if ( x0 > x1 ) then
local tmp = x0
x0 = x1
x1 = tmp
end
if ( x < x0 ) then
return x0-x
elseif ( x > x1 ) then
return x - x1
end
return 0
end
-- Find useable entity (Lua version of CBasePlayer:FindUseEntity)
function meta:FindUseEntity()
-- https://raw.githubusercontent.com/ValveSoftware/source-sdk-2013/0d8dceea4310fde5706b3ce1c70609d72a38efdf/mp/src/game/shared/baseplayer_shared.cpp
local PLAYER_USE_RADIUS = 80
-- Vectors
local forward = self:EyeAngles():Forward()
local up = self:EyeAngles():Up()
local center = self:EyePos()
local trace = {
start = center,
endpos = center,
mins = Vector(-16, -16, -16),
maxs = Vector( 16, 16, 16),
mask = MASK_SOLID + CONTENTS_DEBRIS + CONTENTS_PLAYERCLIP,
filter = function(ent)
if (ent == self) then return false end
if (!ent:IsValid()) then return false end
if (ent:IsPlayer()) then return false end
if (ent == self:GetHands()) then return false end
return true
end,
output = {}
}
local foundEnt = nil
local nearestDist = 16777216
local nearestEnt = nil
local tangents_num = 8
local tangents = {}
tangents[1] = 0
tangents[2] = 1
tangents[3] = 0.57735026919
tangents[4] = 0.3639702342
tangents[5] = 0.267949192431
tangents[6] = 0.1763269807
tangents[7] = -0.1763269807
tangents[8] = -0.267949192431
for idx=1,tangents_num,1 do
if (idx == 1) then
trace.endpos = center + forward * 1024
util.TraceLine(trace)
else
local down = forward - (Vector(tangents[idx], tangents[idx], tangents[idx]) * up)
down:Normalize()
trace.endpos = center + down * 72
util.TraceHull(trace)
end
foundEnt = trace.output.Entity
local useable = self:IsUseableEntity(foundEnt, 0)
while ((foundEnt:IsValid()) && !useable && (foundEnt:GetMoveParent():IsValid())) do
foundEnt = foundEnt:GetMoveParent()
useable = self:IsUseableEntity(foundEnt, 0)
end
if (useable) then
local delta = trace.output.HitPos - trace.output.StartPos
local centerZ = foundEnt:WorldSpaceCenter().z
delta.z = IntervalDistance(trace.output.HitPos.z, centerZ + foundEnt:OBBMins().z, centerZ + foundEnt:OBBMaxs().z)
local dist = delta:Length()
if (dist < PLAYER_USE_RADIUS) then
if (foundEnt:IsNPC() && (foundEnt:Team() == self:Team())) then
foundEnt = self:DoubleCheckUseNPC(foundEnt, center, forward)
end
--if (dist < nearestDist) then -- Not identical to CBasePlayer
--nearestDist = dist
nearestEnt = foundEnt
--end
if (idx == 1) then return foundEnt end
end
end
end
-- check ground entity first
-- if you've got a useable ground entity, then shrink the cone of this search to 45 degrees
-- otherwise, search out in a 90 degree cone (hemisphere)
if (self:GetGroundEntity():IsValid() && self:IsUseableEntity(self:GetGroundEntity(), 256)) then
nearestEnt = self:GetGroundEntity()
end
if (nearestEnt) then
local point = self:NearestPoint(center)
nearestDist = util.DistanceToLine(point, center, forward)
end
local search = ents.FindInSphere(center, PLAYER_USE_RADIUS)
for k,v in ipairs(search) do
if (v) && (v:IsValid()) && (self:IsUseableEntity(v, 512)) then
local point = v:NearestPoint(center)
local dir = (point - center):GetNormalized()
local dot = dir:Dot(forward)
if (dot >= 0.8) then
local dist = util.DistanceToLine(point, center, forward)
if (dist < nearestDist) then
trace.endpos = point
util.TraceLine(trace)
if ((trace.output.Fraction == 1.0) || (trace.output.Entity == v)) then
nearestEnt = v
nearestDist = dist
end
end
end
end
end
if (!nearestEnt) then
trace.endpos = center + forward * PLAYER_USE_RADIUS
trace.mask = MASK_OPAQUE_AND_NPCS
util.TraceLine(trace)
if (trace.output.Entity
&& trace.output.Entity:IsValid()
&& self:IsUseableEntity(trace.output.Entity, 0)
&& trace.output.Entity:IsNPC()
&& (trace.output.Entity:Team() == self:Team())) then
nearestEnt = trace.output.Entity
end
end
if (foundEnt:IsNPC() && (foundEnt:Team() == self:Team())) then
foundEnt = self:DoubleCheckUseNPC(foundEnt, center, forward)
end
return nearestEnt
end
-- Double Check NPC
-- Perhaps a poorly-named function. This function traces against the supplied
-- NPC's hitboxes (instead of hull). If the trace hits a different NPC, the
-- new NPC is selected. Otherwise, the supplied NPC is determined to be the
-- one the citizen wants. This function allows the selection of a citizen over
-- another citizen's shoulder, which is impossible without tracing against
-- hitboxes instead of the hull (sjb)
function meta:DoubleCheckUseNPC(npc, src, dir)
local trace = {
start = src,
endpos = src + dir * 1024,
mask = MASK_SHOT,
result = {}
}
util.TraceLine(trace)
if ((trace.result.Entity != nil) && (trace.result.Entity:IsValid()) && (trace.result.Entity:IsNPC()) && (trace.result.Entity != npc)) then
-- Player is selecting a different NPC through some negative space
-- in the first NPC's hitboxes (between legs, over shoulder, etc).
return trace.result.Entity
end
return npc
end
@@ -1,152 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local CLASS = {}
CLASS.__index = CLASS
local netmsg = {
refresh = "RoundManagerUpdate",
winner = "RoundManagerWinner"
}
function CLASS:__construct()
self.state = nil
self.next_state = nil
-- Custom Timer Stuff
self.timers = {}
self.timers.funcs = {}
self.timers.times = {}
self.timers.delay = {}
-- Register all network string
for k, v in pairs(netmsg) do
util.AddNetworkString(v)
end
-- And some more Timers based functionality.
self:_RegisterTimer("refresh", 2.0, function() self:RefreshAll() end)
-- We need a Think hook.
hook.Add("Think", "RoundManagerThink", function(...) self:Tick(...) end)
end
function CLASS:_RegisterTimer(name, delay, func)
self.timers.funcs[name] = func
self.timers.delay[name] = delay
self.timers.times[name] = CurTime()
end
function CLASS:GetState()
return self.state
end
function CLASS:GetNextState()
return self.next_state
end
function CLASS:SetState(state)
self.next_state = state
end
function CLASS:Tick(...)
-- Tick State
if (self.state != nil) then
if (self.state.Tick != nil) then
self.state:Tick(...)
end
end
-- Advance States
if (self.next_state != self.state) then
local to_id = -1
local to_name = ""
-- Call OnLeave
if (self.state != nil) then
if (self.state.OnLeave != nil) then
self.state:OnLeave(self.next_state)
end
-- Run Hook
hook.Run("RoundManagerLeaveState", self.state:GetId(), self.state:GetName())
end
-- Call OnEnter
if (self.next_state != nil) then
if (self.next_state.OnEnter != nil) then
self.next_state:OnEnter(self.state)
end
to_id = self.next_state:GetId()
to_name = self.next_state:GetName()
-- Run Hook
hook.Run("RoundManagerEnterState", self.next_state:GetId(), self.next_state:GetName())
end
-- Send Network Message
self:RefreshAll()
-- Set State
self.state = self.next_state
end
-- Run all timers.
for k, v in pairs(self.timers.times) do
if ((CurTime() - self.timers.times[k]) >= self.timers.delay[k]) then
self.timers.funcs[k]()
self.timers.times[k] = CurTime()
end
end
end
function CLASS:RefreshAll()
local data = {}
if (self.state != nil) then
data.state = self.state:GetId()
data.state_name = self.state:GetName()
else
data.state = -1
data.state_name = "Unknown"
end
net.Start(netmsg.refresh)
net.WriteTable(data)
net.Broadcast()
end
function CLASS:AnnounceWinner(team)
end
function CreateRoundManager()
local obj = {}
obj.__index = obj
setmetatable(obj, CLASS)
obj:__construct()
return obj
end
_G["RoundManager"] = CreateRoundManager()
@@ -1,59 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2018 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local CLASS = {}
CLASS.__index = CLASS
function CLASS:__construct()
self.name = "Unnamed"
self.id = 0
end
function CLASS:GetName()
return self.name
end
function CLASS:GetId()
return self.id
end
function CLASS:OnEnter() end
function CLASS:Tick() end
function CLASS:OnLeave() end
function state(name, id)
local obj = {}
obj.__index = obj
setmetatable(obj, CLASS)
obj:__construct()
if (name != nil) then
obj.name = name
end
if (id != nil) then
obj.id = id
end
return obj;
end
@@ -1,136 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015-2018 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
include "base.lua"
local CLASS = state("PostRound", GM.States.PostRound)
function CLASS:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StatePostRound: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PostRound)
GAMEMODE.Data.RoundStartTime = CurTime()
-- Fretta Hooks
hook.Run("RoundEnd")
end
function CLASS:Tick()
-- Advance State
if (CurTime() - GAMEMODE.Data.RoundStartTime) >= 5 then -- ToDo: configureable time?
RoundManager:SetState(StatePostMatch)
local players = team.GetPlayers(GAMEMODE.Teams.Seekers)
table.Add(players, team.GetPlayers(GAMEMODE.Teams.Hiders))
-- Assign end of round weighted points.
local aliveSeekers = 0
local aliveHiders = 0
for i,ply in ipairs(players) do
if ply:Alive() then
if (ply:Team() == GAMEMODE.Teams.Hiders) then
aliveHiders = aliveHiders + 1
elseif (ply:Team() == GAMEMODE.Teams.Seekers) then
aliveSeekers = aliveSeekers + 1
end
end
end
for i,ply in ipairs(players) do
local score = 0
if (ply:Team() == GAMEMODE:GetRoundWinner()) then
if (ply:Alive()) then
score = 2
else
score = 1
end
if (ply:Team() == GAMEMODE.Teams.Hiders) then
score = score * aliveHiders
elseif (ply:Team() == GAMEMODE.Teams.Seekers) then
score = -1 * score * aliveSeekers
end
end
ply.Data.RandomWeight = ply.Data.RandomWeight + score
end
-- Team Distribution
if (GAMEMODE.Config.Teams:Weighted() == true) then
-- Weighted Teams
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Randomizing Teams using weighted Score.") end
-- table.sort function returns true if it should a should be before b.
table.sort(players, function(a, b)
if (a.Data.RandomWeight == b.Data.RandomWeight) then
return math.random(100) > 50
else
return a.Data.RandomWeight > b.Data.RandomWeight
end
end)
elseif (GAMEMODE.Config.Teams:Randomize() == true) then
-- Randomize Teams
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Randomizing Teams.") end
table.sort(players, function(a,b)
return math.random(100) > 50
end)
else
-- Swap Teams
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Swapping Teams.") end
table.sort(players, function(a,b)
return (math.random(100) > 50)
end)
table.sort(players, function(a,b)
if (b:Team() == GAMEMODE.Teams.Seekers) then
return (a:Team() == GAMEMODE.Teams.Hiders)
end
return false
end)
end
-- Team Distribution Logic
local hiders, seekers = {}, {}
local plyCount, finalPlyCount = #players, math.max(math.ceil(#players / 2), 1)
for c = 1,finalPlyCount do
seekers[c] = table.remove(players, 1)
end
hiders = players
-- Kill & Assign Teams
for i, ply in ipairs(hiders) do
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Assigned '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") to Team Hiders.") end
ply:KillSilent()
ply:SetTeam(GAMEMODE.Teams.Hiders)
end
for i, ply in ipairs(seekers) do
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Assigned '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") to Team Seekers.") end
ply:KillSilent()
ply:SetTeam(GAMEMODE.Teams.Seekers)
end
end
end
function CLASS:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StatePostRound: OnLeave") end
end
_G["StatePostRound"] = CLASS
@@ -1,556 +0,0 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
--! Initialize configuration table.
GM.Config = { }
GM.Config.ConVars = {}
function CreateConVarIfNotExists(name, value, flags, helptext)
cv = GetConVar(name)
if (cv == nil) then
cv = CreateConVar(name, value, flags, helptext)
-- else
-- ncv = CreateConVar(name, value, flags, helptext)
end
return cv
end
-- ------------------------------------------------------------------------- --
--! Options
-- ------------------------------------------------------------------------- --
GM.Options = { }
-- Friendly Fire
GM.Options.FriendlyFire = { }
GM.Options.FriendlyFire.Off = 0
GM.Options.FriendlyFire.On = 1
GM.Options.FriendlyFire.Reflect = 2
-- ------------------------------------------------------------------------- --
--! Debug Settings
-- ------------------------------------------------------------------------- --
-- Debug Mode
GM.Config.ConVars.Debug = CreateConVarIfNotExists("ph_debug", "0", FCVAR_CHEAT + FCVAR_REPLICATED, "Prop Hunt: Enable Debug Mode")
function GM.Config:Debug()
return self.ConVars.Debug:GetBool()
end
-- Debug Log
GM.Config.ConVars.DebugLog = CreateConVarIfNotExists("ph_debug_log", "0", FCVAR_REPLICATED, "Prop Hunt: Enable Debug Logging")
function GM.Config:DebugLog()
return self.ConVars.DebugLog:GetBool()
end
-- ------------------------------------------------------------------------- --
--! Basic Settings
-- ------------------------------------------------------------------------- --
-- Timelimit in minutes
GM.Config.ConVars.TimeLimit = CreateConVarIfNotExists("mp_timelimit", "20", FCVAR_REPLICATED, "Map Time Limit (in Minutes)")
function GM.Config:TimeLimit()
return self.ConVars.TimeLimit:GetFloat()
end
-- Friendly Fire
GM.Config.ConVars.FriendlyFire = CreateConVarIfNotExists(
"mp_friendlyfire",
GM.Options.FriendlyFire.Off,
FCVAR_REPLICATED,
"Enable Friendly Fire? (0 = Off, 1 = On, 2 = Reflect)"
)
function GM.Config:FriendlyFire()
return self.ConVars.FriendlyFire:GetInt()
end
-- ------------------------------------------------------------------------- --
--! Round Settings
-- ------------------------------------------------------------------------- --
GM.Config.Round = {}
GM.Config.Round.ConVars = {}
-- How many rounds should the GM attempt to fit into the map timelimit, if there is any?
GM.Config.Round.ConVars.Limit = CreateConVarIfNotExists("ph_round_limit", "10", FCVAR_REPLICATED, "Round Manager: Maximum Rounds to Play on a single Map")
function GM.Config.Round:Limit()
return self.ConVars.Limit:GetInt()
end
-- Round Time Limit (Seconds, Default 3 minutes)
GM.Config.Round.ConVars.Time = CreateConVarIfNotExists("ph_round_timelimit", "180", FCVAR_REPLICATED, "Round Manager: Time Limit per Round (in Seconds)")
function GM.Config.Round:Time()
return math.max(self.ConVars.Time:GetFloat() - math.min(self:BlindTime(),0),0)
end
-- For how many seconds are the Seekers blinded? (Seconds)
GM.Config.Round.ConVars.BlindTime = CreateConVarIfNotExists("ph_round_blindtime", "-30", FCVAR_REPLICATED, "Round Manager: Blind Time for Seekers (in Seconds, positive takes away from ph_round_timelimit, negative adds extra time to ph_round_timelimit)")
function GM.Config.Round:BlindTime()
return self.ConVars.BlindTime:GetFloat()
end
-- ------------------------------------------------------------------------- --
--! Team Settings
-- ------------------------------------------------------------------------- --
GM.Config.Teams = {}
GM.Config.Teams.ConVars = {}
-- Should teams be ranomized each round?
GM.Config.Teams.ConVars.Randomize = CreateConVarIfNotExists("ph_teams_randomize", "0", FCVAR_REPLICATED, "Teams: Randomize Teams instead of swapping each round")
function GM.Config.Teams:Randomize()
return self.ConVars.Randomize:GetBool()
end
-- Should teams be using weighted randomization?
-- Weighted randomization works by using a score calculated over the entire session.
-- * Round Start: Adjust Score towards the other Team by 1 (Positive = Seeker, Negative = Hider)
-- * Round Win: Adjust score by how many players are still alive on the winning team towards the other team.
-- * Alive players get double the score.
GM.Config.Teams.ConVars.Weighted = CreateConVarIfNotExists("ph_teams_weighted", "1", FCVAR_REPLICATED, "Teams: Use Weighted Randomization")
function GM.Config.Teams:Weighted()
return self.ConVars.Weighted:GetBool()
end
-- The Dead Hunt: Percent of players to assign to seeker.
GM.Config.Teams.ConVars.SeekerPercentage = CreateConVarIfNotExists("ph_teams_seekerpct", "25", FCVAR_REPLICATED, "Teams: Initial percentage of Seekers in Dead Hunt Game Type")
function GM.Config.Teams:SeekerPercentage()
return self.ConVars.SeekerPercentage:GetFloat() / 100
end
-- ------------------------------------------------------------------------- --
--! Seeker Settings
-- ------------------------------------------------------------------------- --
GM.Config.Seeker = {}
GM.Config.Seeker.ConVars = {}
GM.Config.Seeker.ConVars.Health = CreateConVarIfNotExists("ph_seeker_health", "100", FCVAR_REPLICATED, "Seekers: Initial Health")
function GM.Config.Seeker:Health()
return self.ConVars.Health:GetInt()
end
GM.Config.Seeker.ConVars.HealthMax = CreateConVarIfNotExists("ph_seeker_health_max", "100", FCVAR_REPLICATED, "Seekers: Maximum Health")
function GM.Config.Seeker:HealthMax()
return self.ConVars.HealthMax:GetInt()
end
GM.Config.Seeker.ConVars.HealthBonus = CreateConVarIfNotExists("ph_seeker_health_bonus", "20", FCVAR_REPLICATED, "Seekers: Health Bonus per Kill")
function GM.Config.Seeker:HealthBonus()
return self.ConVars.HealthBonus:GetInt()
end
GM.Config.Seeker.ConVars.HealthPenalty = CreateConVarIfNotExists("ph_seeker_health_penalty", "5", FCVAR_REPLICATED, "Seekers: Health Penalty per wrong Shot")
function GM.Config.Seeker:HealthPenalty()
return self.ConVars.HealthPenalty:GetInt()
end
GM.Config.Seeker.ConVars.Weapons = CreateConVarIfNotExists("ph_seeker_weapons", "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun", FCVAR_REPLICATED, "Seekers: Initial Weapons (Weapon,Weapon,...)")
function GM.Config.Seeker:Weapons()
return string.Split(self.ConVars.Weapons:GetString(), ",")
end
GM.Config.Seeker.ConVars.Ammo = CreateConVarIfNotExists("ph_seeker_ammo", "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64", FCVAR_REPLICATED, "Seekers: Initial Ammo (Ammo:Amount,Ammo:Amount,...)")
function GM.Config.Seeker:Ammo()
return string.Split(self.ConVars.Ammo:GetString(), ",")
end
GM.Config.Seeker.ConVars.WalkSpeed = CreateConVarIfNotExists("ph_seeker_walk_speed", "250", 0, "Seekers: Walk Speed")
function GM.Config.Seeker:WalkSpeed()
return self.ConVars.WalkSpeed:GetFloat()
end
GM.Config.Seeker.ConVars.Sprint = CreateConVarIfNotExists("ph_seeker_sprint", "1", FCVAR_REPLICATED, "Seekers: Allow Sprinting")
function GM.Config.Seeker:Sprint()
return self.ConVars.Sprint:GetBool()
end
GM.Config.Seeker.ConVars.SprintSpeed = CreateConVarIfNotExists("ph_seeker_sprint_speed", "500", 0, "Seekers: Sprint Speed")
function GM.Config.Seeker:SprintSpeed()
return self.ConVars.SprintSpeed:GetFloat()
end
GM.Config.Seeker.ConVars.JumpPower = CreateConVarIfNotExists("ph_seeker_jump_power", "200", 0, "Seekers: Jump Power")
function GM.Config.Seeker:JumpPower()
return self.ConVars.JumpPower:GetFloat()
end
-- ------------------------------------------------------------------------- --
--! Hider Settings
-- ------------------------------------------------------------------------- --
GM.Config.Hider = {}
GM.Config.Hider.ConVars = {}
GM.Config.Hider.ConVars.Health = CreateConVarIfNotExists("ph_hider_health", "100", FCVAR_REPLICATED, "Hiders: Initial Health")
function GM.Config.Hider:Health()
return self.ConVars.Health:GetInt()
end
GM.Config.Hider.ConVars.HealthMax = CreateConVarIfNotExists("ph_hider_health_max", "100", FCVAR_REPLICATED, "Hiders: Maximum Health")
function GM.Config.Hider:HealthMax()
return self.ConVars.HealthMax:GetInt()
end
GM.Config.Hider.ConVars.HealthScaling = CreateConVarIfNotExists("ph_hider_health_scaling", "1", FCVAR_REPLICATED, "Hiders: Enable Health Scaling")
function GM.Config.Hider:HealthScaling()
return self.ConVars.HealthScaling:GetBool()
end
GM.Config.Hider.ConVars.HealthScalingMax = CreateConVarIfNotExists("ph_hider_health_scaling_max", "200", FCVAR_REPLICATED, "Hiders: Maximum scaled Health")
function GM.Config.Hider:HealthScalingMax()
return self.ConVars.HealthScalingMax:GetInt()
end
GM.Config.Hider.ConVars.AllowFullRotation = CreateConVarIfNotExists("ph_hider_allow_full_rotation", "0", FCVAR_REPLICATED, "Hiders: Enable full 3D Rotation")
function GM.Config.Hider:AllowFullRotation()
return self.ConVars.AllowFullRotation:GetBool()
end
GM.Config.Hider.ConVars.WalkSpeed = CreateConVarIfNotExists("ph_hider_walk_speed", "250", 0, "Hiders: Walk Speed")
function GM.Config.Hider:WalkSpeed()
return self.ConVars.WalkSpeed:GetFloat()
end
GM.Config.Hider.ConVars.Sprint = CreateConVarIfNotExists("ph_hider_sprint", "0", FCVAR_REPLICATED, "Hiders: Allow Sprinting")
function GM.Config.Hider:Sprint()
return self.ConVars.Sprint:GetBool()
end
GM.Config.Hider.ConVars.SprintSpeed = CreateConVarIfNotExists("ph_hider_sprint_speed", "500", 0, "Hiders: Sprint Speed")
function GM.Config.Hider:SprintSpeed()
return self.ConVars.SprintSpeed:GetFloat()
end
GM.Config.Hider.ConVars.JumpPower = CreateConVarIfNotExists("ph_hider_jump_power", "200", 0, "Hiders: Jump Power")
function GM.Config.Hider:JumpPower()
return self.ConVars.JumpPower:GetFloat()
end
-- ------------------------------------------------------------------------- --
--! Whitelist & Blacklist
-- ------------------------------------------------------------------------- --
GM.Config.Lists = {}
GM.Config.Lists.ConVars = {}
-- Class Whitelist
GM.Config.Lists.ConVars.ClassWhitelist = CreateConVarIfNotExists("ph_list_class_whitelist", "prop_physics,prop_physics_multiplayer,prop_physics_respawnable", FCVAR_REPLICATED, "Anti-Cheat: Whitelisted Hider Classes")
function GM.Config.Lists:ClassWhitelist()
local str = self.ConVars.ClassWhitelist:GetString()
if (self.ClassWhitelistCache != str) then
self.ClassWhitelistCache = str
self.ClassWhitelistCacheTbl = string.Split(self.ClassWhitelistCache, ",")
end
return self.ClassWhitelistCacheTbl
end
-- Abuse Blacklist
GM.Config.Lists.ConVars.AbuseBlacklist = CreateConVarIfNotExists("ph_list_abuse_blacklist", "func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable", FCVAR_REPLICATED, "Anti-Cheat: Entity Abuse Blacklist")
function GM.Config.Lists:AbuseBlacklist()
local str = self.ConVars.AbuseBlacklist:GetString()
if (self.AbuseBlacklistCache != str) then
self.AbuseBlacklistCache = str
self.AbuseBlacklistCacheTbl = string.Split(self.AbuseBlacklistCache, ",")
end
return self.AbuseBlacklistCacheTbl
end
-- Model Blacklist
GM.Config.Lists.ConVars.ModelBlacklist = CreateConVarIfNotExists("ph_list_model_blacklist", "models/props/cs_assault/dollar.mdl,models/props/cs_assault/money.mdl,models/props/cs_office/snowman_arm.mdl,models/props/cs_office/projector_remote.mdl", FCVAR_REPLICATED, "Anti-Cheat: Model Abuse Blacklist")
function GM.Config.Lists:ModelBlacklist()
local str = self.ConVars.ModelBlacklist:GetString()
if (self.ModelBlacklistCache != str) then
self.ModelBlacklistCache = str
self.ModelBlacklistCacheTbl = string.Split(self.ModelBlacklistCache, ",")
end
return self.ModelBlacklistCacheTbl
end
-- ------------------------------------------------------------------------- --
--! Taunts
-- ------------------------------------------------------------------------- --
GM.Config.Taunt = {}
GM.Config.Taunt.ConVars = {}
-- Cooldown (Seconds)
GM.Config.Taunt.ConVars.Cooldown = CreateConVarIfNotExists("ph_taunt_cooldown", 5, FCVAR_REPLICATED, "Prop Hunt: Cooldown between Taunts")
function GM.Config.Taunt:Cooldown()
return self.ConVars.Cooldown:GetFloat()
end
-- Seeker
GM.Config.Taunt.SeekersCache = ""
GM.Config.Taunt.SeekersCacheDynamic = nil
GM.Config.Taunt.SeekersCacheStatic = nil
GM.Config.Taunt.SeekersCacheFull = nil
GM.Config.Taunt.ConVars.Seekers = CreateConVarIfNotExists("ph_taunt_seekers", "bot/a_bunch_of_them.wav,bot/come_out_and_fight_like_a_man.wav,bot/come_out_wherever_you_are.wav,bot/come_to_papa.wav,bot/dont_worry_hell_get_it.wav,bot/hang_on_i_heard_something.wav,bot/hang_on_im_coming.wav,bot/i_dont_think_so.wav,bot/i_have_the_hostages.wav,bot/i_see_our_target.wav,bot/im_waiting_here.wav,bot/keeping_an_eye_on_the_hostages.wav,bot/nnno_sir.wav,bot/spotted_the_delivery_boy.wav,bot/target_acquired.wav,bot/target_spotted.wav,bot/you_heard_the_man_lets_go.wav", 0, "Prop Hunt: Seeker Taunts")
function GM.Config.Taunt:Seekers()
local str = self.ConVars.Seekers:GetString()
if (self.SeekersCache != str) then
self.SeekersCache = str
self.SeekersCacheDynamic = string.Split(self.SeekersCache, ",")
self.SeekersCacheFull = table.Add(self.SeekersCacheDynamic, self.SeekersCacheStatic)
for i,snd in ipairs(self.SeekersCacheFull) do
util.PrecacheSound(snd)
end
end
return self.SeekersCacheFull
end
-- Hider
GM.Config.Taunt.HidersCache = ""
GM.Config.Taunt.HidersCacheDynamic = nil
GM.Config.Taunt.HidersCacheStatic = nil
GM.Config.Taunt.HidersCacheFull = nil
GM.Config.Taunt.ConVars.Hiders = CreateConVarIfNotExists("ph_taunt_hiders", "ambient/alarms/apc_alarm_pass1.wav,ambient/alarms/manhack_alert_pass1.wav,ambient/alarms/razortrain_horn1.wav,ambient/alarms/scanner_alert_pass1.wav,ambient/alarms/train_horn2.wav,ambient/alarms/train_horn_distant1.wav,ambient/alarms/warningbell1.wav,ambient/energy/whiteflash.wav,ambient/intro/alyxremove.wav,ambient/intro/logosfx.wav,ambient/levels/launch/1stfiringwarning.wav,ambient/levels/launch/rockettakeoffblast.wav,ambient/misc/ambulance1.wav,ambient/misc/carhonk1.wav,ambient/misc/carhonk2.wav,ambient/misc/carhonk3.wav,ambient/outro/gunshipcrash.wav,ambient/3dmeagle.wav,beams/beamstart5.wav,buttons/bell1.wav,buttons/weapon_cant_buy.wav,common/bass.wav,common/bugreporter_failed.wav,common/warning.wav,doors/door_squeek1.wav,friends/friend_join.wav,friends/friend_online.wav,friends/message.wav,hostage/hunuse/comeback.wav,hostage/hunuse/dontleaveme.wav,hostage/hunuse/yeahillstay.wav,items/gift_drop.wav,music/radio1.mp3,phx/eggcrack.wav,plats/elevbell1.wav,player/headshot1.wav,player/headshot2.wav,player/sprayer.wav,radio/enemydown.wav,radio/go.wav,radio/locknload.wav,radio/negative.wav,radio/rounddraw.wav,radio/takepoint.wav,resource/warning.wav,ui/achievement_earned.wav,ui/freeze_cam.wav,vehicles/junker/radar_ping_friendly1.wav,weapons/c4/c4_beep1.wav,weapons/c4/c4_click.wav,weapons/awp/awp1.wav,vo/canals/female01/gunboat_giveemhell.wav,vo/canals/female01/gunboat_justintime.wav,vo/canals/female01/stn6_incoming.wav,vo/canals/male01/gunboat_giveemhell.wav,vo/canals/male01/gunboat_justintime.wav,vo/canals/male01/stn6_incoming.wav,vo/canals/al_radio_stn6.wav,vo/canals/arrest_getgoing.wav,vo/canals/arrest_helpme.wav,vo/canals/arrest_lookingforyou.wav,vo/canals/boxcar_lethimhelp.wav,vo/canals/matt_closecall.wav,vo/canals/premassacre.wav,vo/ravenholm/aimforhead.wav,vo/ravenholm/bucket_patience.wav,vo/ravenholm/madlaugh01.wav,vo/ravenholm/madlaugh02.wav,vo/ravenholm/madlaugh03.wav,vo/ravenholm/madlaugh04.wav,weapons/strider_buster/ol12_stickybombcreator.wav,weapons/c4/c4_explode1.wav,weapons/357/357_fire2.wav,weapons/357/357_fire3.wav,weapons/scout/scout_fire-1.wav,weapons/smokegrenade/sg_explode.wav,weapons/grenade_launcher1.wav,weapons/explode3.wav,weapons/underwater_explode3.wav,items/nvg_on.wav,hostage/huse/letsdoit.wav,hostage/huse/illfollow.wav,hostage/huse/getouttahere.wav,doors/door_screen_move1.wav,doors/heavy_metal_stop1.wav,doors/default_move.wav,common/stuck2.wav,ambient/water_splash1.wav,ambient/water_splash2.wav,ambient/water_splash3.wav,ambient/weather/thunder1.wav,ambient/weather/thunder2.wav,ambient/weather/thunder3.wav,ambient/weather/thunder4.wav,ambient/weather/thunder5.wav,ambient/weather/thunder6.wav,ambient/outro/thunder7.wav,ambient/voices/crying_loop1.wav,ambient/voices/playground_memory.wav,ambient/voices/f_scream1.wav,ambient/voices/m_scream1.wav,ambient/voices/cough1.wav,ambient/voices/cough2.wav,ambient/voices/cough3.wav,ambient/voices/cough4.wav,ambient/overhead/plane1.wav,ambient/overhead/plane2.wav,ambient/overhead/plane3.wav,ambient/overhead/hel1.wav,ambient/overhead/hel2.wav,ambient/misc/truck_backup1.wav,ambient/misc/truck_drive1.wav,ambient/misc/truck_drive2.wav,ambient/machines/pneumatic_drill_1.wav,ambient/machines/pneumatic_drill_2.wav,ambient/machines/pneumatic_drill_3.wav,ambient/machines/pneumatic_drill_4.wav,ambient/machines/station_train_squeel.wav,ambient/machines/ticktock.wav,ambient/creatures/teddy.wav,ambient/creatures/town_child_scream1.wav,ambient/creatures/town_moan1.wav,ambient/creatures/town_muffled_cry1.wav,ambient/creatures/town_scared_breathing1.wav,ambient/creatures/town_scared_breathing2.wav,ambient/creatures/town_scared_sob1.wav,ambient/creatures/town_scared_sob2.wav,ambient/creatures/town_zombie_call1.wav", 0, "Prop Hunt: Hider Taunts")
function GM.Config.Taunt:Hiders()
local str = self.ConVars.Hiders:GetString()
if (self.HidersCacheDynamic == nil)
|| (self.HidersCache != str) then
self.HidersCache = str
self.HidersCacheDynamic = string.Split(self.HidersCache, ",")
self.HidersCacheFull = table.Add(self.HidersCacheDynamic, self.HidersCacheStatic)
for i,snd in ipairs(self.HidersCacheFull) do
util.PrecacheSound(snd)
end
end
return self.HidersCacheFull
end
-- ------------------------------------------------------------------------- --
--! Announcers
-- ------------------------------------------------------------------------- --
-- --! Announcers (Round Start, Unblind, Win, Loss)
-- GM.Config.Announcers = {
-- Start = { },
-- Unblind = { },
-- Win = { },
-- Loss = { }
-- }
-- ------------------------------------------------------------------------- --
--! Camera
-- ------------------------------------------------------------------------- --
GM.Config.Camera = {}
GM.Config.Camera.ConVars = {}
-- Allow Camera No Clip
GM.Config.Camera.ConVars.AllowNoClip = CreateConVarIfNotExists("ph_camera_allow_noclip", "0", FCVAR_REPLICATED, "Camera: Allow clients to disable camera collision.")
function GM.Config.Camera:AllowNoClip()
return self.ConVars.AllowNoClip:GetBool()
end
-- Camera Distance Maximum
GM.Config.Camera.ConVars.DistanceMax = CreateConVarIfNotExists("ph_camera_distance_max", "150", FCVAR_REPLICATED, "Camera: Maximum allowed distance to player.")
function GM.Config.Camera:DistanceMax()
return self.ConVars.DistanceMax:GetFloat()
end
-- Camera Distance Minimum
GM.Config.Camera.ConVars.DistanceMin = CreateConVarIfNotExists("ph_camera_distance_min", "30", FCVAR_REPLICATED, "Camera: Minimum allowed distance to player.")
function GM.Config.Camera:DistanceMin()
return self.ConVars.DistanceMin:GetFloat()
end
-- Camera Distance Right Maximum
GM.Config.Camera.ConVars.DistanceRightRange = CreateConVarIfNotExists("ph_camera_distance_right_range", "20", FCVAR_REPLICATED, "Camera: Horizontal allowed camera distance range.")
function GM.Config.Camera:DistanceRightRange()
return self.ConVars.DistanceRightRange:GetFloat()
end
-- Camera Distance Up Maximum
GM.Config.Camera.ConVars.DistanceUpRange = CreateConVarIfNotExists("ph_camera_distance_up_range", "20", FCVAR_REPLICATED, "Camera: Vertical allowed camera distance range.")
function GM.Config.Camera:DistanceUpRange()
return self.ConVars.DistanceUpRange:GetFloat()
end
-- Lag Minimum
GM.Config.Camera.ConVars.LagMinimum = CreateConVarIfNotExists("ph_camera_lag_min", "0.01", FCVAR_REPLICATED, "Camera: Minimum Camera Lag.")
function GM.Config.Camera:LagMinimum()
return self.ConVars.LagMinimum:GetFloat()
end
-- Lag Maximum
GM.Config.Camera.ConVars.LagMaximum = CreateConVarIfNotExists("ph_camera_lag_max", "0.95", FCVAR_REPLICATED, "Camera: Maximum Camera Lag.")
function GM.Config.Camera:LagMaximum()
return self.ConVars.LagMaximum:GetFloat()
end
if CLIENT then
-- Collisions
GM.Config.Camera.ConVars.Collisions = CreateConVarIfNotExists("ph_camera_collisions", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Enable collisions with the world and objects in it.")
function GM.Config.Camera:Collisions()
if self:AllowNoClip() then
return self.ConVars.Collisions:GetBool()
else
return true
end
end
-- Distance
GM.Config.Camera.ConVars.Distance = CreateConVarIfNotExists("ph_camera_distance", "100", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Ideal Distance to player.")
function GM.Config.Camera:Distance()
return math.Clamp(self.ConVars.Distance:GetFloat(), self:DistanceMin(), self:DistanceMax())
end
-- Distance Right
GM.Config.Camera.ConVars.DistanceRight = CreateConVarIfNotExists("ph_camera_distance_right", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Ideal Distance to player horizontally.")
function GM.Config.Camera:DistanceRight()
return math.Clamp(self.ConVars.DistanceRight:GetFloat(), -self:DistanceRightRange(), self:DistanceRightRange())
end
-- Distance Up
GM.Config.Camera.ConVars.DistanceUp = CreateConVarIfNotExists("ph_camera_distance_up", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Ideal Distance to player vertically.")
function GM.Config.Camera:DistanceUp()
return math.Clamp(self.ConVars.DistanceUp:GetFloat(), -self:DistanceUpRange(), self:DistanceUpRange())
end
-- Lag
GM.Config.Camera.ConVars.Lag = CreateConVarIfNotExists("ph_camera_lag", "0.95", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Percentage of camera lag (higher = slower, lower = faster).")
function GM.Config.Camera:Lag()
return math.Clamp(self.ConVars.Lag:GetFloat(), self:LagMinimum(), self:LagMaximum())
end
end
-- ------------------------------------------------------------------------- --
--! Name Plates
-- ------------------------------------------------------------------------- --
GM.Config.NamePlates = {}
GM.Config.NamePlates.ConVars = {}
if CLIENT then
-- Show
GM.Config.NamePlates.ConVars.Show = CreateConVarIfNotExists("ph_nameplates_show", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Show a name plate above each player in your team (or all players if spectating).")
function GM.Config.NamePlates:Show()
return self.ConVars.Show:GetBool()
end
-- Scale
GM.Config.NamePlates.ConVars.Scale = CreateConVarIfNotExists("ph_nameplates_scale", "0.05", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: World scale of name plate, a setting of 1 means 1px = 1unit.")
function GM.Config.NamePlates:Scale()
return self.ConVars.Scale:GetFloat()
end
-- Height
GM.Config.NamePlates.ConVars.Height = CreateConVarIfNotExists("ph_nameplates_height", "10", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Height above player.")
function GM.Config.NamePlates:Height()
return self.ConVars.Height:GetFloat()
end
-- Tint Color
GM.Config.NamePlates.ConVars.TintHue = CreateConVarIfNotExists("ph_nameplates_tint_hue", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint hue.")
function GM.Config.NamePlates:TintHue()
return self.ConVars.TintHue:GetFloat()
end
GM.Config.NamePlates.ConVars.TintSaturation = CreateConVarIfNotExists("ph_nameplates_tint_saturation", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint saturation.")
function GM.Config.NamePlates:TintSaturation()
return self.ConVars.TintSaturation:GetFloat()
end
GM.Config.NamePlates.ConVars.TintValue = CreateConVarIfNotExists("ph_nameplates_tint_value", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint value.")
function GM.Config.NamePlates:TintValue()
return self.ConVars.TintValue:GetFloat()
end
-- Tint By Health
GM.Config.NamePlates.ConVars.TintHealth = CreateConVarIfNotExists("ph_nameplates_tint_health", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint the nameplate using their health percent.")
function GM.Config.NamePlates:TintHealth()
return self.ConVars.TintHealth:GetBool()
end
-- Tint By Team
GM.Config.NamePlates.ConVars.TintTeam = CreateConVarIfNotExists("ph_nameplates_tint_team", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint the nameplate with the team colors.")
function GM.Config.NamePlates:TintTeam()
return self.ConVars.TintTeam:GetBool()
end
end
-- ------------------------------------------------------------------------- --
--! Selection Halo
-- ------------------------------------------------------------------------- --
GM.Config.SelectionHalo = {}
GM.Config.SelectionHalo.ConVars = {}
-- Allow
GM.Config.SelectionHalo.ConVars.Allow = CreateConVarIfNotExists("ph_selectionhalo_allow", "1", FCVAR_REPLICATED, "Selection Halo: Allow clients to enable halo around the currently looked at prop?")
function GM.Config.SelectionHalo:Allow()
return self.ConVars.Allow:GetBool()
end
-- Approximate
GM.Config.SelectionHalo.ConVars.Approximate = CreateConVarIfNotExists("ph_selectionhalo_approximate", "1", FCVAR_REPLICATED, "Selection Halo: Enable approximate selection halo, which only checks the forward vector on the client.")
function GM.Config.SelectionHalo:Approximate()
return self.ConVars.Approximate:GetBool()
end
if SERVER then
-- Update Interval
GM.Config.SelectionHalo.ConVars.Interval = CreateConVarIfNotExists("ph_selectionhalo_interval", "0.05", FCVAR_ARCHIVE, "Selection Halo: Interval for updates of the accuracte selection halo in seconds.")
function GM.Config.SelectionHalo:Interval()
return self.ConVars.Interval:GetFloat()
end
end
if CLIENT then
-- Enabled
GM.Config.SelectionHalo.ConVars.Enabled = CreateConVarIfNotExists("ph_selectionhalo_enabled", "1", FCVAR_ARCHIVE, "Selection Halo: Enable halo around prop you might become.")
function GM.Config.SelectionHalo:Enabled()
if (self:Allow()) then
return self.ConVars.Enabled:GetBool()
else
return false
end
end
-- Settings
GM.Config.SelectionHalo.ConVars.Passes = CreateConVarIfNotExists("ph_selectionhalo_passes", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Passes")
function GM.Config.SelectionHalo:Passes()
return self.ConVars.Passes:GetInt()
end
GM.Config.SelectionHalo.ConVars.Additive = CreateConVarIfNotExists("ph_selectionhalo_additive", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Additive")
function GM.Config.SelectionHalo:Additive()
return self.ConVars.Additive:GetBool()
end
GM.Config.SelectionHalo.ConVars.IgnoreZ = CreateConVarIfNotExists("ph_selectionhalo_ignorez", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Ignore Z")
function GM.Config.SelectionHalo:IgnoreZ()
return self.ConVars.IgnoreZ:GetBool()
end
-- Blur
GM.Config.SelectionHalo.ConVars.BlurX = CreateConVarIfNotExists("ph_selectionhalo_blur_x", "2", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Blur X")
function GM.Config.SelectionHalo:BlurX()
return self.ConVars.BlurX:GetFloat()
end
GM.Config.SelectionHalo.ConVars.BlurY = CreateConVarIfNotExists("ph_selectionhalo_blur_y", "2", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Blur Y")
function GM.Config.SelectionHalo:BlurY()
return self.ConVars.BlurY:GetFloat()
end
-- Tint Color
GM.Config.SelectionHalo.ConVars.TintHue = CreateConVarIfNotExists("ph_selectionhalo_tint_hue", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Tint Hue")
function GM.Config.SelectionHalo:TintHue()
return self.ConVars.TintHue:GetFloat()
end
GM.Config.SelectionHalo.ConVars.TintSaturation = CreateConVarIfNotExists("ph_selectionhalo_tint_saturation", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Tint Saturation")
function GM.Config.SelectionHalo:TintSaturation()
return self.ConVars.TintSaturation:GetFloat()
end
GM.Config.SelectionHalo.ConVars.TintValue = CreateConVarIfNotExists("ph_selectionhalo_tint_value", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Selection Halo: Tint Value")
function GM.Config.SelectionHalo:TintValue()
return self.ConVars.TintValue:GetFloat()
end
end
Binary file not shown.

Before

Width:  |  Height:  |  Size: 920 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

@@ -1,84 +0,0 @@
"prophuntextended"
{
"base" "base"
"title" "Prop Hunt Extended"
"maps" "^ph_"
"menusystem" "1"
"workshopid" "468149739"
"settings"
{
// Basic Settings
100
{
"name" "mp_timelimit"
"text" "Core: Time Limit for the entire Map"
"type" "Numeric"
"default" "0"
"help" "Map Time Limit (in Minutes)"
}
101
{
"name" "mp_friendlyfire"
"text" "Core: Friendly fire"
"type" "Numeric"
"default" "0"
"help" "Allow friendly fire? (0 = No, 1 = Yes, 2 = Reflect)"
}
// Round Settings
200
{
"name" "ph_round_limit"
"text" "Rounds: Limit"
"type" "Numeric"
"default" "10"
"help" "Round Manager: Maximum Rounds to Play on a single Map"
}
201
{
"name" "ph_round_timelimit"
"text" "Rounds: Time Limit per Round"
"type" "Numeric"
"default" "180"
"help" "Round Manager: Time Limit per Round (in Seconds)"
}
202
{
"name" "ph_round_blindtime"
"text" "Rounds: Blind Time per Round"
"type" "Numeric"
"default" "-30"
"help" "Round Manager: Blind Time for Seekers (in Seconds, positive takes away from ph_round_timelimit, negative adds extra time to ph_round_timelimit)"
}
// Team Settings
300
{
"name" "ph_teams_randomize"
"text" "Teams: Randomize instead of Swap"
"type" "CheckBox"
"default" "0"
"help" "Teams: Randomize Teams instead of swapping each round"
}
301
{
"name" "ph_teams_weighted"
"text" "Teams: Weighted Randomization"
"type" "CheckBox"
"default" "0"
"help" "Teams: Use Weighted Randomization, which may seem more fair towards players."
}
// Taunts
700
{
"name" "ph_taunt_cooldown"
"text" "Cooldown for Taunts"
"type" "Numeric"
"default" "5"
"help" "Prop Hunt: Cooldown between Taunts"
}
}
}
-17
View File
@@ -1,17 +0,0 @@
@ECHO OFF
ECHO This script must be run as administrator, or will fail with unknown results.
ECHO I've been run from "%CD%", and am in "%~dp0", switching directory to set up environment.
PUSHD "%~dp0"
CALL "%~dp0\env.win.bat"
SET "PATH_GMOD=%GARRYSMODPATH%"
SET "PATH_REPO=%ROOT%\.."
PUSHD "%PATH_GMOD%\garrysmod\addons"
MKLINK /J prophuntextended "%PATH_REPO%\source"
MKLINK /J prophunt "%PATH_REPO%\proxy"
POPD
POPD
PAUSE
-14
View File
@@ -1,14 +0,0 @@
@ECHO OFF
:: Root and repo
SET "ROOT=%~dp0"
:: Garry's Mod
SET "GARRYSMODPATH="
FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
IF "%GARRYSMODPATH%" == "" (
FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
)
IF "%GARRYSMODPATH%" == "" (
ECHO Failed to figure out where Garry's Mod is installed.
)
-10
View File
@@ -1,10 +0,0 @@
@ECHO OFF
CALL "env.win.bat"
SET "GMANAME=%TMP%\prophuntextended-%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%.gma"
PUSHD "%REPO%"
"%GARRYSMODPATH%\bin\gmad.exe" create -folder "%REPO%source" -out "%GMANAME%"
"%GARRYSMODPATH%\bin\gmpublish.exe" update -id 468149739 -icon "media\workshop-gamemode.jpg" -addon "%GMANAME%" -changes "To be added (see Github in the mean time)"
POPD
PAUSE
-10
View File
@@ -1,10 +0,0 @@
@ECHO OFF
CALL "env.win.bat"
SET "GMANAME=%TMP%\prophuntproxy-%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%.gma"
PUSHD "%REPO%"
"%GARRYSMODPATH%\bin\gmad.exe" create -folder "%REPO%source" -out "%GMANAME%"
"%GARRYSMODPATH%\bin\gmpublish.exe" update -id 1327985306 -icon "media\workshop-gamemode.jpg" -addon "%GMANAME%" -changes "To be added (see Github in the mean time)"
POPD
PAUSE
-4
View File
@@ -1,4 +0,0 @@
@ECHO OFF
call env.win.bat
SET "PATH=%CD%;%GARRYSMODPATH%\bin;%PATH%"
CMD
-8
View File
@@ -1,8 +0,0 @@
{
"folders": [
{
"path": "."
}
],
"settings": {}
}