From 89cf6fc80972e8ecd287ac8df007f9bf7603fe19 Mon Sep 17 00:00:00 2001 From: icedream Date: Sun, 19 Apr 2015 01:32:39 +0200 Subject: [PATCH] Initial commit. --- .gitignore | 9 + LICENSE | 22 +++ README.md | 18 ++ addon.json | 20 +++ lua/autorun/client/prophunt_tauntmenu.lua | 109 ++++++++++++ lua/autorun/server/prophunt_tauntmenu.lua | 192 ++++++++++++++++++++++ 6 files changed, 370 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 addon.json create mode 100644 lua/autorun/client/prophunt_tauntmenu.lua create mode 100644 lua/autorun/server/prophunt_tauntmenu.lua diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..97b7e1e --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.bat +*.cmd +*.sh +*.gma +*.exe +*.exe.config +*.pdb +*.dll +*.dll.config \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..45e9be9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 DreamNetwork + +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. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..fefb7ae --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +PropHunt Taunt Menu +------------------- + +Implements a very minimal but flexible menu for playing taunts while playing Prop Hunt. + +## Installation via Workshop + +This addon will be available via the Steam Workshop. +If you want to install it on your client, subscribe to it with the green Subscribe button. It will be automatically updated appropriately. +If you want to install it on your server, you can add the addon to a collection and use the collection with your server. More info regarding this can be looked up [here](http://wiki.garrysmod.com/page/Workshop_for_Dedicated_Servers). + +## How to use? + +Press the key you selected as "Spare 2" in your Garry's Mod "Options" menu while you're playing as Prop or Hunter. Usually that is F4. + +## License + +This tauntpack has been published under the MIT license. For license information see the [LICENSE](LICENSE) file. \ No newline at end of file diff --git a/addon.json b/addon.json new file mode 100644 index 0000000..5297f70 --- /dev/null +++ b/addon.json @@ -0,0 +1,20 @@ +{ + "title" : "PropHunt Taunt Menu", + "type" : "gamemode", + "tags" : [ "fun", "roleplay" ], + "ignore" : + [ + "*.md", + "*.exe", + "*.exe.config", + "*.dll", + "*.dll.config", + "*.pdb", + "*.bat", + "*.cmd", + "*.sh", + "*.txt", + "*.gma", + ".git*" + ] +} diff --git a/lua/autorun/client/prophunt_tauntmenu.lua b/lua/autorun/client/prophunt_tauntmenu.lua new file mode 100644 index 0000000..e552185 --- /dev/null +++ b/lua/autorun/client/prophunt_tauntmenu.lua @@ -0,0 +1,109 @@ +-- Sent by the server to let us know about available taunts +local sortedTaunts = {} + +net.Receive("TauntList_Update", function() + + local tauntsTable = net.ReadTable() + + --[[ + print("Got tauntlist update:") + PrintTable(tauntsTable) + --]] + + -- Syntax of the table is just the same as for tauntpacks. + -- We categorize the taunts by splitting the names up and making use of the parts. + sortedTaunts = {} + for team, taunts in pairs(tauntsTable) do + sortedTaunts[team] = { sounds={}, categories={} } + + for _, value in pairs(taunts) do + local path = value[1] + local description = value[2] + local name = nil + local parent = sortedTaunts[team] + + -- split the name for categorization + for _, i in pairs(string.Split(description, " - ")) do + if name ~= nil then + if parent.categories[name] == nil then + parent.categories[name] = { sounds={}, categories={} } + end + parent = parent.categories[name] + end + + name = i + end + + parent.sounds[name] = path + end + end +end) + +local windowColor = Color(128, 128, 128, 192) +local textColor = Color(255, 255, 255) + +local function PlayTaunt(sound) + net.Start("TauntMenu_Play") + net.WriteString(sound) + net.SendToServer() +end + +local function Apply(menu, taunts) + -- sort sounds + local sounds = {} + for key,value in pairs(taunts.sounds) do + table.insert(sounds, { key=key, value=value }) + end + table.sort(sounds, function(a, b) + return string.lower(a.key) < string.lower(b.key) + end) + + -- sort categories + local categories = {} + for key,value in pairs(taunts.categories) do + table.insert(categories, { key=key, value=value }) + end + table.sort(categories, function(a, b) + return string.lower(a.key) < string.lower(b.key) + end) + + -- add categories to the menu + for _, item in pairs(categories) do + Apply(menu:AddSubMenu(item.key), item.value) + end + + -- add sounds to the menu + for _, item in pairs(sounds) do + menu:AddOption(item.key, function() + PlayTaunt(item.value) + end) + end + + menu:AddSpacer() +end + +local function CreateMenu() + -- does the team even have taunts? (spectators don't, so no menu for them!) + local team = LocalPlayer():Team() + local teamTaunts = sortedTaunts[team] + if teamTaunts == nil then + return nil + end + + -- menu bar + local menu = vgui.Create("DMenu") + + -- build submenus + Apply(menu, teamTaunts) + + return menu +end + +hook.Add( "PlayerBindPress", "PlayerBindPressFKeyMenus", function(pl, bind, pressed) + if string.find(bind, "gm_showspare2") then + local menu = CreateMenu() + if menu ~= nil then + menu:Open() + end + end +end); \ No newline at end of file diff --git a/lua/autorun/server/prophunt_tauntmenu.lua b/lua/autorun/server/prophunt_tauntmenu.lua new file mode 100644 index 0000000..f580a6a --- /dev/null +++ b/lua/autorun/server/prophunt_tauntmenu.lua @@ -0,0 +1,192 @@ +-- For reference see Prop Hunt, sh_init.lua:58 and sh_init.lua:63 + +local tauntsTable = {} +local tauntsFixedTable = {} +local tauntPathsTable = {} + +local fixedNames = { + --[[ Hunter taunts ]]-- + -- shipped with Prop Hunt + ["taunts/hunters/come_to_papa.wav"] = "Come to papa", + ["taunts/hunters/father.wav"] = "Father", + ["taunts/hunters/fireassis.wav"] = "Fire Assist", + ["taunts/hunters/hitassist.wav"] = "Hit Assist", + ["taunts/hunters/now_what.wav"] = "Now what", + ["taunts/hunters/you_dont_know_the_power.wav"] = "Star Wars - Darth Vader - You don't know the power of the dark side", + ["taunts/hunters/you_underestimate_the_power.wav"] = "Star Wars - Darth Vader - You underestimate the power of the dark side", + ["taunts/hunters/glados-president.wav"] = "Portal - GLaDOS - Past president of the being-alive club", + ["taunts/hunters/rude.mp3"] = "Rude", + ["taunts/hunters/illfindyou.mp3"] = "I will find you and I will kill you", + + -- Half-Life 2 + ["vo/k_lab/ba_guh.wav"] = "Half-Life 2 - Barney - Guh", + ["vo/npc/male01/vanswer13.wav"] = "Half-Life 2 - Stop, you're killing me", + ["vo/npc/male01/thehacks01.wav"] = "Half-Life 2 - The hacks!", + ["vo/npc/male01/runforyourlife02.wav"] = "Half-Life 2 - Run for your life!", + ["vo/npc/male01/overhere01.wav"] = "Half-Life 2 - Hey, over here!", + ["vo/npc/male01/overthere01.wav"] = "Half-Life 2 - Over there! - 1", + ["vo/npc/male01/overthere02.wav"] = "Half-Life 2 - Over there! - 2", + + --[[ Prop taunts ]]-- + -- shipped with Prop Hunt + ["taunts/boom_headshot.wav"] = "Boom, Headshot!", + ["taunts/go_away_or_i_shall.wav"] = "Go away or I shall taunt you", + ["taunts/ill_be_back.wav"] = "I'll be back", + ["taunts/negative.wav"] = "Negative", + ["taunts/doh.wav"] = "Simpsons - D'oh!", + ["taunts/oh_yea_he_will_pay.wav"] = "Yeah, you'll pay, you will definitely pay", + ["taunts/ok_i_will_tell_you.wav"] = "I'll tell you, do you know the muffin man?", + ["taunts/please_come_again.wav"] = "Please come again", + ["taunts/threat_neutralized.wav"] = "Thread neutralized!", + ["taunts/what_is_wrong_with_you.wav"] = "What is wrong with you!?", + ["taunts/woohoo.wav"] = "Woohoo!", + ["taunts/props/1.wav"] = "Boom, Headshot!", + ["taunts/props/2.wav"] = "Simpsons - D'oh!", + ["taunts/props/3.wav"] = "Go away or I shall taunt you", + ["taunts/props/4.wav"] = "Vince with ShamWow!", + ["taunts/props/5.wav"] = "Negative", + ["taunts/props/6.wav"] = "Over 9000", + ["taunts/props/7.wav"] = "LEEROY JENKINS", + ["taunts/props/8.wav"] = "Please come again", + ["taunts/props/9.wav"] = "This is SPARTA!", + ["taunts/props/10.wav"] = "What is wrong with you!?", + ["taunts/props/11.wav"] = "Woohoo!", + ["taunts/props/12.wav"] = "What do you like to play? Pokemon!", + ["taunts/props/13.mp3"] = "I need chippie for my bonga hole", + ["taunts/props/14.wav"] = "Wheeee!", + ["taunts/props/15.wav"] = "Snooping as usual, I see", + ["taunts/props/16.wav"] = "AAAAAAAAAAATATATATATATATA", + ["taunts/props/17.mp3"] = "Aaaaaahahahaha", + ["taunts/props/18.wav"] = "Billy Maze - Get on the ball!", + ["taunts/props/19.wav"] = "Car horns", + ["taunts/props/20.wav"] = "Billy Maze - Are you on the ball?", + ["taunts/props/21.wav"] = "Billy Maze - For only 19.99!", + ["taunts/props/22.wav"] = "Billy Maze - And you'll never have to pour...", + ["taunts/props/23.wav"] = "Billy Maze - I guarantee it", + ["taunts/props/24.wav"] = "Billy Maze - It's new Oxiclean Detergent", + ["taunts/props/25.wav"] = "Billy Maze - It's so easy, even your kids can do laundry", + ["taunts/props/26.wav"] = "Billy Maze - So get on the ball!", + ["taunts/props/27.wav"] = "Billy Maze - The Oxiclean Detergent ball", + ["taunts/props/28.wav"] = "Billy Maze - Laundries just got easier", + ["taunts/props/29.wav"] = "Music - Running in the 90's", + ["taunts/props/30.wav"] = "All military forces...", + ["taunts/props/31.mp3"] = "Bad boys, what you gonna do when they come for you?", + ["taunts/props/32.mp3"] = "Music - TEKKNO", + ["taunts/props/33.mp3"] = "Music - Call on me", + ["taunts/props/34.mp3"] = "Music - I am the one and only", + ["taunts/props/35.mp3"] = "Wololo", + ["taunts/hunters/laugh.wav"] = "Laugh", -- look in the Prop Hunt source if you don't believe this being a prop taunt (despite the fact the sound file is missing there) + + -- Half-life 2 taunts -- + ["vo/citadel/br_ohshit.wav"] = "Half-Life 2 - Dr. Breen - Oh, shit", + ["vo/citadel/br_youfool.wav"] = "Half-Life 2 - Dr. Breen - You fool", + ["vo/citadel/br_youneedme.wav"] = "Half-Life 2 - Dr. Breen - You need me", + ["vo/coast/odessa/male01/nlo_cheer01.wav"] = "Half-Life 2 - Cheer - Male - 1", + ["vo/coast/odessa/male01/nlo_cheer02.wav"] = "Half-Life 2 - Cheer - Male - 2", + ["vo/coast/odessa/male01/nlo_cheer03.wav"] = "Half-Life 2 - Cheer - Male - 3", + ["vo/coast/odessa/male01/nlo_cheer04.wav"] = "Half-Life 2 - Cheer - Male - 4", + ["vo/coast/odessa/female01/nlo_cheer01.wav"] = "Half-Life 2 - Cheer - Female - 1", + ["vo/coast/odessa/female01/nlo_cheer02.wav"] = "Half-Life 2 - Cheer - Female - 2", + ["vo/coast/odessa/female01/nlo_cheer03.wav"] = "Half-Life 2 - Cheer - Female - 3", + ["vo/gman_misc/gman_riseshine.wav"] = "Half-Life 2 - G-Man - Rise and shine", + ["vo/npc/barney/ba_damnit.wav"] = "Half-Life 2 - Barney - Damn it", + ["vo/npc/barney/ba_laugh01.wav"] = "Half-Life 2 - Barney - Laugh - 1", + ["vo/npc/barney/ba_laugh02.wav"] = "Half-Life 2 - Barney - Laugh - 2", + ["vo/npc/barney/ba_laugh03.wav"] = "Half-Life 2 - Barney - Laugh - 3", + ["vo/npc/barney/ba_laugh04.wav"] = "Half-Life 2 - Barney - Laugh - 4", + ["vo/npc/male01/hacks01.wav"] = "Half-Life 2 - Hacks - 1", + ["vo/npc/male01/hacks02.wav"] = "Half-Life 2 - Hacks - 2", + ["vo/npc/male01/vanswer01.wav"] = "Half-Life 2 - Enough of your mumbo-jumbo", + ["vo/npc/male01/question05.wav"] = "Half-Life 2 - Oh! Deja-vu!", + ["vo/npc/male01/question06.wav"] = "Half-Life 2 - Sometimes I dream about cheese", + ["vo/npc/male01/answer34.wav"] = "Half-Life 2 - Don't forget Hawaii", + ["vo/npc/male01/question30.wav"] = "Half-Life 2 - I'm glad there's no kids around to see this", + ["vo/npc/male01/question26.wav"] = "Half-Life 2 - This is bullshit", + ["vo/npc/male01/incoming02.wav"] = "Half-Life 2 - Incoming!", + ["vo/npc/male01/gethellout.wav"] = "Half-Life 2 - Get the hell outta here", + ["vo/ravenholm/madlaugh04.wav"] = "Father Gregori - Mad laugh", + ["taunts/fixed/13_fix.wav"] = "I need chippie for my bonga hole", + ["taunts/fixed/bees_fix.wav"] = "Not the bees!" +} + +util.AddNetworkString("TauntList_Update") +util.AddNetworkString("TauntMenu_Play") + +local function FixName(name) + if fixedNames[name] ~= nil then return fixedNames[name] end + return name +end + +local function PlayTaunt(pl, sound) + local team = pl:Team() + local tauntPaths = tauntPathsTable[team] + + -- TAUNT_DELAY from Prop Hunt, sh_config.lua:172 + -- The code tries to match up with Prop Hunt, init.lua:163-178 + if GAMEMODE:InRound() && IsValid(pl) && pl:IsPlayer() && pl:Alive() && pl.last_taunt_time + TAUNT_DELAY <= CurTime() + && tauntPaths ~= nil && table.HasValue(tauntPaths, sound) then + pl.last_taunt_time = CurTime() + pl.last_taunt = sound + + pl:EmitSound(sound, 100) + end +end + +local function BroadcastUpdate() + net.Start("TauntList_Update") + net.WriteTable(tauntsFixedTable) + net.Broadcast() +end + +local function SendUpdate(pl) + net.Start("TauntList_Update") + net.WriteTable(tauntsFixedTable) + net.Send(pl) +end + +-- Detect changes in the taunt list +hook.Add("Think", "TauntList_DetectUpdate", function() + -- Tauntpack loader replaces the old table with a new instance whenever it reloads the taunts. + -- This means we can use reference equality to detect changes quickly here. + -- For reference see sv_ph_tauntpack_loader.lua:55-56 + if (GAMEMODE.Hunter_Taunts == nil) or (GAMEMODE.Prop_Taunts == nil) then return end + if (tauntsTable[TEAM_HUNTERS] ~= GAMEMODE.Hunter_Taunts) + or (tauntsTable[TEAM_PROPS] ~= GAMEMODE.Prop_Taunts) then + + tauntsTable= {} + tauntsFixedTable= {} + + -- Replace some of the names with fixed names since Tauntpack Loader + -- just uses the file path for them which will look ugly on the UI + tauntsTable[TEAM_HUNTERS] = GAMEMODE.Hunter_Taunts + tauntsFixedTable[TEAM_HUNTERS] = {} + for index, item in pairs(GAMEMODE.Hunter_Taunts) do + tauntsFixedTable[TEAM_HUNTERS][index] = { item[1], FixName(item[2]) } + end + + tauntsTable[TEAM_PROPS] = GAMEMODE.Prop_Taunts + tauntsFixedTable[TEAM_PROPS] = {} + for index, item in pairs(GAMEMODE.Prop_Taunts) do + tauntsFixedTable[TEAM_PROPS][index] = { item[1], FixName(item[2]) } + end + + -- Tables that hold sound paths, see Prop Hunt, sh_config.lua:70-168 + tauntPathsTable[TEAM_HUNTERS] = HUNTER_TAUNTS + tauntPathsTable[TEAM_PROPS] = PROP_TAUNTS + + BroadcastUpdate() + end +end) + +-- PlayerInitialSpawn gets called when the player gets to "Sending Client Info". +-- We let the player know all the taunts for the menu here. +hook.Add("PlayerInitialSpawn", "TauntList_UpdateFirst", function(pl) + SendUpdate(pl) +end) + +-- Sent by the client to play a custom taunt +net.Receive("TauntMenu_Play", function(len, pl) + local path = net.ReadString() + + PlayTaunt(pl, path) +end) \ No newline at end of file