From dc0c57397bb022b98d43749235abe7221d337446 Mon Sep 17 00:00:00 2001 From: Marco Cawthorne Date: Wed, 24 Jul 2024 18:51:27 -0700 Subject: [PATCH] Rip out more now-unused stuff. Start fixing up the buy system, make weapons fire again --- src/client/cmds.qc | 62 ++--- src/client/entities.qc | 3 + src/client/radio.qc | 0 src/client/textmenu.qc | 94 +++---- src/client/vgui_buypages.qc | 62 ++--- src/server/ammo.qc | 8 +- src/server/bot.qc | 48 ++-- src/server/buy.h | 20 +- src/server/buy.qc | 2 +- src/server/gamerules_deathmatch.qc | 6 +- src/server/item_suit.qc | 78 ------ src/server/progs.src | 11 - src/server/spawn.qc | 74 ------ src/shared/CSProjectile.h | 30 ++- src/shared/CSProjectile.qc | 229 +++++++++++++++++ src/shared/CSWeapon.qc | 30 ++- src/{server/player.qc => shared/buying.h} | 53 +++- src/shared/defs.h | 3 +- src/shared/include.src | 1 + src/shared/player.h | 1 - src/shared/pmove.qc | 95 ------- src/shared/weapons.h | 66 ----- zpak001.pk3dir/def/items.def | 6 + .../def/{item_c4.def => items/c4.def} | 0 zpak001.pk3dir/def/items/defuse.def | 10 + zpak001.pk3dir/def/items/kevlar.def | 11 + zpak001.pk3dir/def/items/kevlar_helmet.def | 11 + zpak001.pk3dir/def/items/nightvision.def | 10 + zpak001.pk3dir/def/items/suit.def | 11 + zpak001.pk3dir/def/projectiles.def | 15 ++ zpak001.pk3dir/def/weapons/famas.def | 56 +++++ zpak001.pk3dir/def/weapons/galil.def | 27 ++ zpak001.pk3dir/def/weapons/m3.def | 4 +- zpak001.pk3dir/def/weapons/xm1014.def | 2 +- zpak001.pk3dir/maps/eukara/test_weapons.bsp | Bin 0 -> 18992 bytes zpak001.pk3dir/maps/eukara/test_weapons.map | 235 ++++++++++++++++++ zpak001.pk3dir/sound/player.sndshd | 4 +- 37 files changed, 872 insertions(+), 506 deletions(-) mode change 100755 => 100644 src/client/radio.qc delete mode 100644 src/server/item_suit.qc delete mode 100644 src/server/spawn.qc rename src/{server/player.qc => shared/buying.h} (53%) delete mode 100644 src/shared/weapons.h create mode 100644 zpak001.pk3dir/def/items.def rename zpak001.pk3dir/def/{item_c4.def => items/c4.def} (100%) create mode 100644 zpak001.pk3dir/def/items/defuse.def create mode 100644 zpak001.pk3dir/def/items/kevlar.def create mode 100644 zpak001.pk3dir/def/items/kevlar_helmet.def create mode 100644 zpak001.pk3dir/def/items/nightvision.def create mode 100644 zpak001.pk3dir/def/items/suit.def create mode 100644 zpak001.pk3dir/def/projectiles.def create mode 100644 zpak001.pk3dir/def/weapons/famas.def create mode 100644 zpak001.pk3dir/def/weapons/galil.def create mode 100644 zpak001.pk3dir/maps/eukara/test_weapons.bsp create mode 100644 zpak001.pk3dir/maps/eukara/test_weapons.map diff --git a/src/client/cmds.qc b/src/client/cmds.qc index 76b3b01..7ae10cf 100644 --- a/src/client/cmds.qc +++ b/src/client/cmds.qc @@ -73,99 +73,99 @@ ClientGame_ConsoleCommand(void) sendevent("DropWeapon", ""); break; case "glock": - sendevent("BuyWeapon", "f", WEAPON_GLOCK18); + sendevent("CSBuy", "f", BUY_GLOCK18); break; case "usp": - sendevent("BuyWeapon", "f", WEAPON_USP45); + sendevent("CSBuy", "f", BUY_USP45); break; case "p228": - sendevent("BuyWeapon", "f", WEAPON_P228); + sendevent("CSBuy", "f", BUY_P228); break; case "deagle": - sendevent("BuyWeapon", "f", WEAPON_DEAGLE); + sendevent("CSBuy", "f", BUY_DEAGLE); break; case "fn57": - sendevent("BuyWeapon", "f", WEAPON_FIVESEVEN); + sendevent("CSBuy", "f", BUY_FIVESEVEN); break; case "elites": - sendevent("BuyWeapon", "f", WEAPON_ELITES); + sendevent("CSBuy", "f", BUY_ELITES); break; case "m3": - sendevent("BuyWeapon", "f", WEAPON_M3); + sendevent("CSBuy", "f", BUY_M3); break; case "xm1014": - sendevent("BuyWeapon", "f", WEAPON_XM1014); + sendevent("CSBuy", "f", BUY_XM1014); break; case "tmp": - sendevent("BuyWeapon", "f", WEAPON_TMP); + sendevent("CSBuy", "f", BUY_TMP); break; case "mac10": - sendevent("BuyWeapon", "f", WEAPON_MAC10); + sendevent("CSBuy", "f", BUY_MAC10); break; case "mp5": - sendevent("BuyWeapon", "f", WEAPON_MP5); + sendevent("CSBuy", "f", BUY_MP5); break; case "ump45": - sendevent("BuyWeapon", "f", WEAPON_UMP45); + sendevent("CSBuy", "f", BUY_UMP45); break; case "p90": - sendevent("BuyWeapon", "f", WEAPON_P90); + sendevent("CSBuy", "f", BUY_P90); break; case "ak47": - sendevent("BuyWeapon", "f", WEAPON_AK47); + sendevent("CSBuy", "f", BUY_AK47); break; case "m4a1": - sendevent("BuyWeapon", "f", WEAPON_M4A1); + sendevent("CSBuy", "f", BUY_M4A1); break; case "sg552": - sendevent("BuyWeapon", "f", WEAPON_SG552); + sendevent("CSBuy", "f", BUY_SG552); break; case "aug": - sendevent("BuyWeapon", "f", WEAPON_AUG); + sendevent("CSBuy", "f", BUY_AUG); break; case "scout": - sendevent("BuyWeapon", "f", WEAPON_SCOUT); + sendevent("CSBuy", "f", BUY_SCOUT); break; case "sg550": - sendevent("BuyWeapon", "f", WEAPON_SG550); + sendevent("CSBuy", "f", BUY_SG550); break; case "awp": - sendevent("BuyWeapon", "f", WEAPON_AWP); + sendevent("CSBuy", "f", BUY_AWP); break; case "g3sg1": - sendevent("BuyWeapon", "f", WEAPON_G3SG1); + sendevent("CSBuy", "f", BUY_G3SG1); break; case "m249": - sendevent("BuyWeapon", "f", WEAPON_PARA); + sendevent("CSBuy", "f", BUY_PARA); break; case "buyammo1": case "primammo": - sendevent("AmmoBuyPrimary", ""); + sendevent("CSBuy", "f", BUY_PRIMARYAMMO); break; case "buyammo2": case "secammo": - sendevent("AmmoBuySecondary", ""); + sendevent("CSBuy", "f", BUY_SECONDARYAMMO); break; case "vest": - sendevent("BuyEquipment", "f", 0); + sendevent("CSBuy", "f", BUY_VEST); break; case "vesthelm": - sendevent("BuyEquipment", "f", 1); + sendevent("CSBuy", "f", BUY_VESTHELMET); break; case "flash": - sendevent("BuyEquipment", "f", 2); + sendevent("CSBuy", "f", BUY_FLASHBANG); break; case "hegren": - sendevent("BuyEquipment", "f", 3); + sendevent("CSBuy", "f", BUY_HEGRENADE); break; case "vsgren": - sendevent("BuyEquipment", "f", 4); + sendevent("CSBuy", "f", BUY_SMOKEGRENADE); break; case "defuser": - sendevent("BuyEquipment", "f", 5); + sendevent("CSBuy", "f", BUY_DEFUSALKIT); break; case "nvg": - sendevent("BuyEquipment", "f", 6); + sendevent("CSBuy", "f", BUY_NIGHTVISION); break; case "coverme": sendevent("Radio", "f", RADIO_CT_COVERME); diff --git a/src/client/entities.qc b/src/client/entities.qc index 91f0140..5a584e1 100644 --- a/src/client/entities.qc +++ b/src/client/entities.qc @@ -24,6 +24,9 @@ ClientGame_EntityUpdate(float id, float new) case ENT_PLAYER: NSENTITY_READENTITY(CSPlayer, new) break; + case ENT_ENTITYPROJECTILE: + NSENTITY_READENTITY(CSProjectile, new) + break; case ENT_WEAPON: NSENTITY_READENTITY(CSWeapon, new) break; diff --git a/src/client/radio.qc b/src/client/radio.qc old mode 100755 new mode 100644 diff --git a/src/client/textmenu.qc b/src/client/textmenu.qc index 7bf41b0..9ca20a8 100644 --- a/src/client/textmenu.qc +++ b/src/client/textmenu.qc @@ -106,11 +106,11 @@ BUY(int n) Textmenu_Call(inteam == TEAM_T ? "BUYMACHINEGUN" : "BUYMACHINEGUN"); break; case 6: - sendevent("AmmoBuyPrimary", ""); + sendevent("CSBuy", "f", BUY_PRIMARYAMMO); Textmenu_Call(""); break; case 7: - sendevent("AmmoBuySecondary", ""); + sendevent("CSBuy", "f", BUY_SECONDARYAMMO); Textmenu_Call(""); break; case 8: @@ -128,22 +128,22 @@ DT_BUYITEM(int n) { switch (n) { case 1: - sendevent("BuyEquipment", "f", 0); + sendevent("CSBuy", "f", BUY_VEST); break; case 2: - sendevent("BuyEquipment", "f", 1); + sendevent("CSBuy", "f", BUY_VESTHELMET); break; case 3: - sendevent("BuyEquipment", "f", 2); + sendevent("CSBuy", "f", BUY_FLASHBANG); break; case 4: - sendevent("BuyEquipment", "f", 3); + sendevent("CSBuy", "f", BUY_HEGRENADE); break; case 5: - sendevent("BuyEquipment", "f", 4); + sendevent("CSBuy", "f", BUY_SMOKEGRENADE); break; case 7: - sendevent("BuyEquipment", "f", 6); + sendevent("CSBuy", "f", BUY_NIGHTVISION); break; case 10: Textmenu_Call(""); @@ -159,25 +159,25 @@ DCT_BUYITEM(int n) { switch (n) { case 1: - sendevent("BuyEquipment", "f", 0); + sendevent("CSBuy", "f", BUY_VEST); break; case 2: - sendevent("BuyEquipment", "f", 1); + sendevent("CSBuy", "f", BUY_VESTHELMET); break; case 3: - sendevent("BuyEquipment", "f", 2); + sendevent("CSBuy", "f", BUY_FLASHBANG); break; case 4: - sendevent("BuyEquipment", "f", 3); + sendevent("CSBuy", "f", BUY_HEGRENADE); break; case 5: - sendevent("BuyEquipment", "f", 4); + sendevent("CSBuy", "f", BUY_SMOKEGRENADE); break; case 6: - sendevent("BuyEquipment", "f", 5); + sendevent("CSBuy", "f", BUY_DEFUSALKIT); break; case 7: - sendevent("BuyEquipment", "f", 6); + sendevent("CSBuy", "f", BUY_NIGHTVISION); break; case 10: Textmenu_Call(""); @@ -195,19 +195,19 @@ T_BUYPISTOL(int n) { switch (n) { case 1: - sendevent("BuyWeapon", "f", WEAPON_USP45); + sendevent("CSBuy", "f", BUY_USP45); break; case 2: - sendevent("BuyWeapon", "f", WEAPON_GLOCK18); + sendevent("CSBuy", "f", BUY_GLOCK18); break; case 3: - sendevent("BuyWeapon", "f", WEAPON_DEAGLE); + sendevent("CSBuy", "f", BUY_DEAGLE); break; case 4: - sendevent("BuyWeapon", "f", WEAPON_P228); + sendevent("CSBuy", "f", BUY_P228); break; case 5: - sendevent("BuyWeapon", "f", WEAPON_ELITES); + sendevent("CSBuy", "f", BUY_ELITES); break; case 10: Textmenu_Call(""); @@ -223,19 +223,19 @@ CT_BUYPISTOL(int n) { switch (n) { case 1: - sendevent("BuyWeapon", "f", WEAPON_USP45); + sendevent("CSBuy", "f", BUY_USP45); break; case 2: - sendevent("BuyWeapon", "f", WEAPON_GLOCK18); + sendevent("CSBuy", "f", BUY_GLOCK18); break; case 3: - sendevent("BuyWeapon", "f", WEAPON_DEAGLE); + sendevent("CSBuy", "f", BUY_DEAGLE); break; case 4: - sendevent("BuyWeapon", "f", WEAPON_P228); + sendevent("CSBuy", "f", BUY_P228); break; case 6: - sendevent("BuyWeapon", "f", WEAPON_FIVESEVEN); + sendevent("CSBuy", "f", BUY_FIVESEVEN); break; case 10: Textmenu_Call(""); @@ -253,10 +253,10 @@ BUYSHOTGUN(int n) { switch (n) { case 1: - sendevent("BuyWeapon", "f", WEAPON_M3); + sendevent("CSBuy", "f", BUY_M3); break; case 2: - sendevent("BuyWeapon", "f", WEAPON_XM1014); + sendevent("CSBuy", "f", BUY_XM1014); break; case 10: Textmenu_Call(""); @@ -274,19 +274,19 @@ T_BUYRIFLE(int n) { switch (n) { case 1: - sendevent("BuyWeapon", "f", WEAPON_AK47); + sendevent("CSBuy", "f", BUY_AK47); break; case 2: - sendevent("BuyWeapon", "f", WEAPON_SG552); + sendevent("CSBuy", "f", BUY_SG552); break; case 5: - sendevent("BuyWeapon", "f", WEAPON_SCOUT); + sendevent("CSBuy", "f", BUY_SCOUT); break; case 6: - sendevent("BuyWeapon", "f", WEAPON_AWP); + sendevent("CSBuy", "f", BUY_AWP); break; case 7: - sendevent("BuyWeapon", "f", WEAPON_G3SG1); + sendevent("CSBuy", "f", BUY_G3SG1); break; case 10: Textmenu_Call(""); @@ -302,22 +302,22 @@ CT_BUYRIFLE(int n) { switch (n) { case 3: - sendevent("BuyWeapon", "f", WEAPON_M4A1); + sendevent("CSBuy", "f", BUY_M4A1); break; case 4: - sendevent("BuyWeapon", "f", WEAPON_AUG); + sendevent("CSBuy", "f", BUY_AUG); break; case 5: - sendevent("BuyWeapon", "f", WEAPON_SCOUT); + sendevent("CSBuy", "f", BUY_SCOUT); break; case 6: - sendevent("BuyWeapon", "f", WEAPON_AWP); + sendevent("CSBuy", "f", BUY_AWP); break; case 7: - sendevent("BuyWeapon", "f", WEAPON_G3SG1); + sendevent("CSBuy", "f", BUY_G3SG1); break; case 8: - sendevent("BuyWeapon", "f", WEAPON_SG550); + sendevent("CSBuy", "f", BUY_SG550); break; case 10: Textmenu_Call(""); @@ -335,16 +335,16 @@ T_BUYSUBMACHINEGUN(int n) { switch (n) { case 1: - sendevent("BuyWeapon", "f", WEAPON_MP5); + sendevent("CSBuy", "f", BUY_MP5); break; case 3: - sendevent("BuyWeapon", "f", WEAPON_P90); + sendevent("CSBuy", "f", BUY_P90); break; case 4: - sendevent("BuyWeapon", "f", WEAPON_MAC10); + sendevent("CSBuy", "f", BUY_MAC10); break; case 5: - sendevent("BuyWeapon", "f", WEAPON_UMP45); + sendevent("CSBuy", "f", BUY_UMP45); break; case 10: Textmenu_Call(""); @@ -360,16 +360,16 @@ CT_BUYSUBMACHINEGUN(int n) { switch (n) { case 1: - sendevent("BuyWeapon", "f", WEAPON_MP5); + sendevent("CSBuy", "f", BUY_MP5); break; case 2: - sendevent("BuyWeapon", "f", WEAPON_TMP); + sendevent("CSBuy", "f", BUY_TMP); break; case 3: - sendevent("BuyWeapon", "f", WEAPON_P90); + sendevent("CSBuy", "f", BUY_P90); break; case 5: - sendevent("BuyWeapon", "f", WEAPON_UMP45); + sendevent("CSBuy", "f", BUY_UMP45); break; case 10: Textmenu_Call(""); @@ -387,7 +387,7 @@ BUYMACHINEGUN(int n) { switch (n) { case 1: - sendevent("BuyWeapon", "f", WEAPON_PARA); + sendevent("CSBuy", "f", BUY_PARA); break; case 10: Textmenu_Call(""); diff --git a/src/client/vgui_buypages.qc b/src/client/vgui_buypages.qc index 74e9ace..d3a0dbd 100644 --- a/src/client/vgui_buypages.qc +++ b/src/client/vgui_buypages.qc @@ -67,39 +67,39 @@ typedef struct } buyItems_t; const buyItems_t g_buyItemList [] = { - { "BuyWeapon", WEAPON_USP45, "classes/usp.txt", "gfx/vgui/640_usp", "USP45" }, - { "BuyWeapon", WEAPON_GLOCK18, "classes/glock18.txt", "gfx/vgui/640_glock18", "Glock18" }, - { "BuyWeapon", WEAPON_DEAGLE, "classes/deagle.txt", "gfx/vgui/640_deagle", "DesertEagle" }, - { "BuyWeapon", WEAPON_P228, "classes/p228.txt", "gfx/vgui/640_p228", "P228" }, - { "BuyWeapon", WEAPON_ELITES, "classes/elite.txt", "gfx/vgui/640_elite", "Beretta96G" }, - { "BuyWeapon", WEAPON_FIVESEVEN, "classes/fiveseven.txt", "gfx/vgui/640_fiveseven", "FiveSeven" }, - { "BuyWeapon", WEAPON_M3, "classes/m3.txt", "gfx/vgui/640_m3", "Super90" }, - { "BuyWeapon", WEAPON_XM1014, "classes/xm1014.txt", "gfx/vgui/640_xm1014", "XM1014" }, + { "CSBuy", BUY_USP45, "classes/usp.txt", "gfx/vgui/640_usp", "USP45" }, + { "CSBuy", BUY_GLOCK18, "classes/glock18.txt", "gfx/vgui/640_glock18", "Glock18" }, + { "CSBuy", BUY_DEAGLE, "classes/deagle.txt", "gfx/vgui/640_deagle", "DesertEagle" }, + { "CSBuy", BUY_P228, "classes/p228.txt", "gfx/vgui/640_p228", "P228" }, + { "CSBuy", BUY_ELITES, "classes/elite.txt", "gfx/vgui/640_elite", "Beretta96G" }, + { "CSBuy", BUY_FIVESEVEN, "classes/fiveseven.txt", "gfx/vgui/640_fiveseven", "FiveSeven" }, + { "CSBuy", BUY_M3, "classes/m3.txt", "gfx/vgui/640_m3", "Super90" }, + { "CSBuy", BUY_XM1014, "classes/xm1014.txt", "gfx/vgui/640_xm1014", "XM1014" }, #if defined(CZERO) || defined(CSSOURCE) - { "BuyWeapon", WEAPON_FAMAS, "classes/famas.txt", "gfx/vgui/640_famas", "Famas" }, - { "BuyWeapon", WEAPON_GALIL, "classes/galil.txt", "gfx/vgui/640_galil", "Galil" }, + { "CSBuy", BUY_FAMAS, "classes/famas.txt", "gfx/vgui/640_famas", "Famas" }, + { "CSBuy", BUY_GALIL, "classes/galil.txt", "gfx/vgui/640_galil", "Galil" }, #endif - { "BuyWeapon", WEAPON_AK47, "classes/ak47.txt", "gfx/vgui/640_ak47", "AK47" }, - { "BuyWeapon", WEAPON_SG552, "classes/sg552.txt", "gfx/vgui/640_sg552", "SG552" }, - { "BuyWeapon", WEAPON_M4A1, "classes/m4a1.txt", "gfx/vgui/640_m4a1", "M4A1" }, - { "BuyWeapon", WEAPON_AUG, "classes/aug.txt", "gfx/vgui/640_aug", "Aug" }, - { "BuyWeapon", WEAPON_SCOUT, "classes/scout.txt", "gfx/vgui/640_scout", "Scout" }, - { "BuyWeapon", WEAPON_AWP, "classes/awp.txt", "gfx/vgui/640_awp", "ArcticWarfareMagnum" }, - { "BuyWeapon", WEAPON_G3SG1, "classes/g3sg1.txt", "gfx/vgui/640_g3sg1", "G3SG1" }, - { "BuyWeapon", WEAPON_SG550, "classes/sg550.txt", "gfx/vgui/640_sg550", "SG550" }, - { "BuyWeapon", WEAPON_MP5, "classes/mp5.txt", "gfx/vgui/640_mp5", "mp5navy" }, - { "BuyWeapon", WEAPON_TMP, "classes/tmp.txt", "gfx/vgui/640_tmp", "tmp" }, - { "BuyWeapon", WEAPON_P90, "classes/p90.txt", "gfx/vgui/640_p90", "FNP90" }, - { "BuyWeapon", WEAPON_MAC10, "classes/mac10.txt", "gfx/vgui/640_mac10", "Mac10" }, - { "BuyWeapon", WEAPON_UMP45, "classes/ump45.txt", "gfx/vgui/640_ump45", "UMP45" }, - { "BuyWeapon", WEAPON_PARA, "classes/m249.txt", "gfx/vgui/640_m249", "M249" }, - { "BuyEquipment", 0, "classes/kevlar.txt", "", "Kevlar_Vest" }, - { "BuyEquipment", 1, "classes/kevlar_helmet.txt", "", "Kevlar_Vest_Ballistic_Helmet" }, - { "BuyEquipment", 2, "classes/flashbang.txt", "gfx/vgui/640_flashbang", "Flashbang" }, - { "BuyEquipment", 3, "classes/hegrenade.txt", "gfx/vgui/640_hegrenade", "High_Explosive_Grenade" }, - { "BuyEquipment", 4, "classes/smokegrenade.txt", "gfx/vgui/640_smokegrenade", "Smoke_Grenade" }, - { "BuyEquipment", 5, "classes/defuse.txt", "", "Defusal_Kit" }, - { "BuyEquipment", 6, "classes/nightvision.txt", "", "Nightvision_Goggles" }, + { "CSBuy", BUY_AK47, "classes/ak47.txt", "gfx/vgui/640_ak47", "AK47" }, + { "CSBuy", BUY_SG552, "classes/sg552.txt", "gfx/vgui/640_sg552", "SG552" }, + { "CSBuy", BUY_M4A1, "classes/m4a1.txt", "gfx/vgui/640_m4a1", "M4A1" }, + { "CSBuy", BUY_AUG, "classes/aug.txt", "gfx/vgui/640_aug", "Aug" }, + { "CSBuy", BUY_SCOUT, "classes/scout.txt", "gfx/vgui/640_scout", "Scout" }, + { "CSBuy", BUY_AWP, "classes/awp.txt", "gfx/vgui/640_awp", "ArcticWarfareMagnum" }, + { "CSBuy", BUY_G3SG1, "classes/g3sg1.txt", "gfx/vgui/640_g3sg1", "G3SG1" }, + { "CSBuy", BUY_SG550, "classes/sg550.txt", "gfx/vgui/640_sg550", "SG550" }, + { "CSBuy", BUY_MP5, "classes/mp5.txt", "gfx/vgui/640_mp5", "mp5navy" }, + { "CSBuy", BUY_TMP, "classes/tmp.txt", "gfx/vgui/640_tmp", "tmp" }, + { "CSBuy", BUY_P90, "classes/p90.txt", "gfx/vgui/640_p90", "FNP90" }, + { "CSBuy", BUY_MAC10, "classes/mac10.txt", "gfx/vgui/640_mac10", "Mac10" }, + { "CSBuy", BUY_UMP45, "classes/ump45.txt", "gfx/vgui/640_ump45", "UMP45" }, + { "CSBuy", BUY_PARA, "classes/m249.txt", "gfx/vgui/640_m249", "M249" }, + { "CSBuy", BUY_VEST, "classes/kevlar.txt", "", "Kevlar_Vest" }, + { "CSBuy", BUY_VESTHELMET, "classes/kevlar_helmet.txt", "", "Kevlar_Vest_Ballistic_Helmet" }, + { "CSBuy", BUY_FLASHBANG, "classes/flashbang.txt", "gfx/vgui/640_flashbang", "Flashbang" }, + { "CSBuy", BUY_HEGRENADE, "classes/hegrenade.txt", "gfx/vgui/640_hegrenade", "High_Explosive_Grenade" }, + { "CSBuy", BUY_SMOKEGRENADE, "classes/smokegrenade.txt", "gfx/vgui/640_smokegrenade", "Smoke_Grenade" }, + { "CSBuy", BUY_DEFUSALKIT, "classes/defuse.txt", "", "Defusal_Kit" }, + { "CSBuy", BUY_NIGHTVISION, "classes/nightvision.txt", "", "Nightvision_Goggles" }, }; string g_butItemDescr[29]; diff --git a/src/server/ammo.qc b/src/server/ammo.qc index 3fa4ed6..be622f2 100644 --- a/src/server/ammo.qc +++ b/src/server/ammo.qc @@ -38,6 +38,7 @@ typedef struct int price; } ammoinfo_t; +#if 0 ammoinfo_t cs_ammoinfo[11] = { /* CALIBER_NONE */ { @@ -106,6 +107,7 @@ ammoinfo_t cs_ammoinfo[11] = { .price = 50 } }; +#endif int Ammo_BuyCaliber(CSPlayer pl, int cal, int free) @@ -324,7 +326,7 @@ CSEv_AmmoBuyPrimary(void) return; } - Ammo_BuyPrimary(pl, FALSE); + //Ammo_BuyPrimary(pl, FALSE); } void @@ -336,8 +338,8 @@ Ammo_AutoFill(NSClientPlayer pp) return; } - Ammo_BuyPrimary(pl, true); - Ammo_BuySecondary(pl, true); + //Ammo_BuyPrimary(pl, true); + //Ammo_BuySecondary(pl, true); } void diff --git a/src/server/bot.qc b/src/server/bot.qc index 360ea1b..227ebe8 100644 --- a/src/server/bot.qc +++ b/src/server/bot.qc @@ -243,9 +243,9 @@ csbot::CreateObjective(void) /* We carry the bomb */ if (m_gflagsBackup & GF_BOMBZONE) { /* We are at a bombsite and ready to plant the bomb */ - if (activeweapon != WEAPON_C4BOMB) { + if (GetCurrentWeapon() != "weapon_c4") { /* TODO: REPLACE THIS WITH NSNAVAI METHOD */ - activeweapon = WEAPON_C4BOMB; + SwitchToWeapon("weapon_c4"); //Weapons_Draw((CSPlayer)self); } @@ -351,7 +351,7 @@ csbot::PostFrame(void) void csbot::WeaponThink(void) { - if (activeweapon == WEAPON_KNIFE) + if (GetCurrentWeapon() == "weapon_knife") return; #if FIXME @@ -473,21 +473,21 @@ CSBot_BuyStart_Shop(void) int r = floor(random(1,17)); if (pl.team == TEAM_T) { - if (r == WEAPON_M4A1) { continue; } - if (r == WEAPON_AUG) { continue; } - if (r == WEAPON_SG550) { continue; } - if (r == WEAPON_FIVESEVEN) { continue; } - if (r == WEAPON_TMP) { continue; } + if (r == BUY_M4A1) { continue; } + if (r == BUY_AUG) { continue; } + if (r == BUY_SG550) { continue; } + if (r == BUY_FIVESEVEN) { continue; } + if (r == BUY_TMP) { continue; } } else if (pl.team == TEAM_CT) { - if (r == WEAPON_AK47) { continue; } - if (r == WEAPON_SG552) { continue; } - if (r == WEAPON_G3SG1) { continue; } - if (r == WEAPON_ELITES) { continue; } - if (r == WEAPON_MAC10) { continue; } + if (r == BUY_AK47) { continue; } + if (r == BUY_SG552) { continue; } + if (r == BUY_G3SG1) { continue; } + if (r == BUY_ELITES) { continue; } + if (r == BUY_MAC10) { continue; } } - if (g_cstrikeWeaponPrice[r] <= pl.money) { - CSEv_BuyWeapon_f((float)r); + if (cs_buyprices[r] <= pl.money) { + CSEv_CSBuy_f((float)r); done = 1; } count++; @@ -499,21 +499,21 @@ CSBot_BuyStart_Shop(void) /* CT: Random buy bomb defuse kit when enough money left */ if (pl.team == TEAM_CT && g_cs_bombzones > 0 && - g_cstrikeUtilPrice[(float)5] <= pl.money && + cs_buyprices[BUY_DEFUSALKIT] <= pl.money && random() < 0.5) { - CSEv_BuyEquipment_f((float)5); // ITEM_DEFUSAL + CSEv_CSBuy_f(BUY_DEFUSALKIT); // ITEM_DEFUSAL } /* need armor */ if (pl.armor < 100) { - if (pl.money >= g_cstrikeUtilPrice[1]) /* kevlar and helmet */ - CSEv_BuyEquipment_f(1); - else if (pl.money >= g_cstrikeUtilPrice[0]) /* just kevlar */ - CSEv_BuyEquipment_f(0); + if (pl.money >= cs_buyprices[1]) /* kevlar and helmet */ + CSEv_CSBuy_f(BUY_VESTHELMET); + else if (pl.money >= cs_buyprices[0]) /* just kevlar */ + CSEv_CSBuy_f(BUY_VEST); } else if (!(pl.g_items & ITEM_HELMET)) { /* we need helmet */ if (pl.money >= 350) /* kevlar and helmet */ - CSEv_BuyEquipment_f(1); + CSEv_CSBuy_f(BUY_VESTHELMET); } #if FIXME @@ -527,8 +527,8 @@ CSBot_BuyStart_Shop(void) #endif /* force buy right now */ - CSEv_AmmoBuyPrimary(); - CSEv_AmmoBuySecondary(); + CSEv_CSBuy_f(BUY_PRIMARYAMMO); + CSEv_CSBuy_f(BUY_SECONDARYAMMO); } void diff --git a/src/server/buy.h b/src/server/buy.h index b79ac61..15cae04 100644 --- a/src/server/buy.h +++ b/src/server/buy.h @@ -15,7 +15,7 @@ */ /* values courtesy of https://wiki.alliedmods.net/Cs_weapons_information */ -int g_cstrikeWeaponPrice[] = +int cs_buyprices[] = { 0, /* WEAPON_NONE */ 1700, /* WEAPON_M3 */ @@ -40,25 +40,17 @@ int g_cstrikeWeaponPrice[] = 600, /* WEAPON_P228 */ 800, /* WEAPON_ELITES */ 750, /* WEAPON_FIVESEVEN */ - 0, /* WEAPON_KNIFE */ + 0, /* WEAPON_KNIFE */ 300, /* WEAPON_HEGRENADE */ 200, /* WEAPON_FLASHBANG */ 300, /* WEAPON_SMOKEGRENADE */ - 0 /* WEAPON_C4BOMB */ -}; - -int g_cstrikeUtilPrice[] = -{ + 0, /* WEAPON_C4BOMB */ + 0, /* padding */ + 0, /* padding */ 650, /* Kevlar Vest */ 1000, /* Kevlar Vest & Helmet */ - 200, /* Flashbang */ - 300, /* HE Grenade */ - 300, /* Smoke Grenade */ 200, /* Defuse Kit */ 1250 /* NightVision Goggles */ }; -void CSEv_BuyWeapon_f(float fWeapon); -void CSEv_BuyEquipment_f(float fWeapon); -void CSEv_AmmoBuyPrimary(void); -void CSEv_AmmoBuySecondary(void); +void CSEv_CSBuy_f(float itemID); diff --git a/src/server/buy.qc b/src/server/buy.qc index 85fb9ac..7648733 100644 --- a/src/server/buy.qc +++ b/src/server/buy.qc @@ -15,7 +15,7 @@ */ void -CSEv_BuyWeapon_f(float fWeapon) +CSEv_CSBuy_f(float fWeapon) { #if 0 CSGameRules rules = (CSGameRules)g_grMode; diff --git a/src/server/gamerules_deathmatch.qc b/src/server/gamerules_deathmatch.qc index 1b9cdba..7e6043c 100644 --- a/src/server/gamerules_deathmatch.qc +++ b/src/server/gamerules_deathmatch.qc @@ -228,14 +228,16 @@ CSDeathmatchRules::PlayerSpawn(NSClientPlayer pp) LevelNewParms(); LevelDecodeParms(pl); - pl.g_items = ITEM_KNIFE | ITEM_SUIT; - pl.activeweapon = WEAPON_KNIFE; + pl.GiveItem("item_suit"); + pl.GiveItem("weapon_knife"); +#if 0 int randomGun = (int)rint(random(WEAPON_USP45, WEAPON_FIVESEVEN)); //Weapons_AddItem(pl, randomGun, -1); randomGun = (int)rint(random(WEAPON_M3, WEAPON_PARA)); //Weapons_AddItem(pl, randomGun, -1); pl.activeweapon = randomGun; +#endif Ammo_BuyPrimary(pl, TRUE); Ammo_BuySecondary(pl, TRUE); diff --git a/src/server/item_suit.qc b/src/server/item_suit.qc deleted file mode 100644 index 8d4e8eb..0000000 --- a/src/server/item_suit.qc +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2016-2020 Marco Cawthorne - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -class item_suit:NSRenderableEntity -{ - void(void) item_suit; - - virtual void(entity) Touch; - virtual void(void) Respawn; - virtual void(void) Spawned; -}; - -void -item_suit::item_suit(void) -{ - /* a custom map may choose to override this */ - model = "models/w_kevlar.mdl"; -} - -void -item_suit::Spawned(void) -{ - super::Spawned(); - - precache_model(model); - precache_sound("items/tr_kevlar.wav"); -} - -void -item_suit::Respawn(void) -{ - super::Respawn(); - SetSolid(SOLID_TRIGGER); - SetMovetype(MOVETYPE_TOSS); - SetSize(VEC_HULL_MIN, VEC_HULL_MAX); - ReleaseThink(); -} - -void -item_suit::Touch(entity eToucher) -{ - CSPlayer pl = (CSPlayer)eToucher; - - if (pl.classname != "player") { - return; - } - - if (pl.g_items & ITEM_SUIT) { - return; - } - - sound(eToucher, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_NORM); - pl.g_items |= ITEM_SUIT; - - UseTargets(eToucher, TRIG_TOGGLE, m_flDelay); - - if (cvar("sv_playerslots") == 1) { - Destroy(); - } else { - Disappear(); - ScheduleThink(Respawn, 30.0f); - } -} - -CLASSEXPORT(item_kevlar, item_suit) diff --git a/src/server/progs.src b/src/server/progs.src index 7bb0387..16df440 100644 --- a/src/server/progs.src +++ b/src/server/progs.src @@ -17,12 +17,8 @@ ../../../src/gs-entbase/server.src ../../../src/gs-entbase/shared.src ../shared/defs.h - defs.h ../shared/include.src - -player.qc - hostage_entity.qc armoury_entity.qc func_bomb_target.qc @@ -33,25 +29,18 @@ func_hostage_rescue.qc info_hostage_rescue.qc func_vip_safetyzone.qc info_map_parameters.qc -item_suit.qc - ../../../src/botlib/include.src bot.qc - game_money.qc gamerules.qc gamerules_singleplayer.qc gamerules_deathmatch.qc gamerules_multiplayer.qc - radio.qc ammo.qc buy.qc server.qc ../../../valve/src/server/flashlight.qc - -spawn.qc - ../../../src/server/include.src ../../../src/shared/include.src #endlist diff --git a/src/server/spawn.qc b/src/server/spawn.qc deleted file mode 100644 index 3ff6ddd..0000000 --- a/src/server/spawn.qc +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2016-2019 Marco Cawthorne - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* -================= -info_player_start - -Counter-Terrorist Spawnpoints -================= -*/ -void -info_player_start(void) -{ - if (autocvar_fcs_swapteams == TRUE) { - self.classname = "info_player_deathmatch"; - } - self.botinfo = BOTINFO_SPAWNPOINT; -} - -/* -================= -info_player_deathmatch - -Terrorist Spawnpoints -================= -*/ -void -info_player_deathmatch(void) -{ - if (autocvar_fcs_swapteams == TRUE) { - self.classname = "info_player_start"; - } - self.botinfo = BOTINFO_SPAWNPOINT; -} - -/* Counter-Strike: Source compat */ -void -info_player_counterterrorist(void) -{ - setorigin(self, self.origin + [0,0,32]); - self.classname = "info_player_start"; - info_player_start(); -} - -void -info_player_terrorist(void) -{ - setorigin(self, self.origin + [0,0,32]); - self.classname = "info_player_deathmatch"; - info_player_deathmatch(); -} - -/* -================= -info_vip_start -================= -*/ -void -info_vip_start(void) -{ -} diff --git a/src/shared/CSProjectile.h b/src/shared/CSProjectile.h index a00110d..bf56f8d 100644 --- a/src/shared/CSProjectile.h +++ b/src/shared/CSProjectile.h @@ -1,8 +1,34 @@ +/* + * Copyright (c) 2024 Vera Visions LLC. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + class CSProjectile:NSProjectile { + float m_flRangeModifier; + int m_iTotalPenetrations; + float m_flMaxThickness; + void CSProjectile(void); - -}; +#ifdef SERVER + nonvirtual void SetRangeModifier(float); + nonvirtual void SetPenetrationMaxThickness(float); + nonvirtual void SetPenetrationPower(int); + virtual void _FireSingle(vector,vector,float,float); + virtual void _LaunchHitscan(vector, vector, float); +#endif +}; diff --git a/src/shared/CSProjectile.qc b/src/shared/CSProjectile.qc index a62e885..a972432 100644 --- a/src/shared/CSProjectile.qc +++ b/src/shared/CSProjectile.qc @@ -1,5 +1,234 @@ +/* + * Copyright (c) 2024 Vera Visions LLC. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + void CSProjectile::CSProjectile(void) { } + +void +CSProjectile::SetRangeModifier(float rangeModifier) +{ + m_flRangeModifier = rangeModifier; +} + +void +CSProjectile::SetPenetrationMaxThickness(float maxThickness) +{ + m_flMaxThickness = maxThickness; +} + +void +CSProjectile::SetPenetrationPower(int powerLevel) +{ + m_iTotalPenetrations = powerLevel; +} + +#ifdef SERVER +void +CSProjectile::_LaunchHitscan(vector startPos, vector launchDir, float dmgMultiplier) +{ + vector vecDir; + vector ownerAngle; + vector ownerDir; + + m_eMultiTarget = __NULL__; + m_iMultiValue = 0; + + ownerAngle = anglesToForward(launchDir); + ownerDir = aim(owner, 100000); + + while (m_iShots > 0) { + /* use cached value */ + v_forward = ownerAngle; + + if (owner.flags & FL_CLIENT) { + vecDir = ownerDir; + } else { + vecDir = v_forward; + } + + /* FOR NOW Monsters will not be able to do spread like players if patterns are enabled */ + if (!(owner.flags & FL_CLIENT)) { + vecDir += random(-1,1) * m_vecSpread[0] * anglesToRight(launchDir); + vecDir += random(-1,1) * m_vecSpread[1] * anglesToUp(launchDir); + } else { + CSPlayer pl = (CSPlayer)owner; + + /* weapons have already applied their multiplier... so attempt this */ + int multiplier = pl.cs_shotmultiplier - m_iShots; + float frand = (multiplier / 6); + + /* shoddy attempt at spray patterns */ + if (frand < 1) + frand = frand; + else if (frand <= 2) + frand = 2 - (frand * 1.5); + + vecDir += frand * m_vecSpread[0] * anglesToRight(launchDir); + vecDir += (m_vecSpread[1] * anglesToUp(launchDir)) * 2; + } + + _FireSingle(startPos, vecDir, m_flDamage, m_flRange); + m_iShots--; + } + + if (m_eMultiTarget) { + _ApplyDamage(); + } +} + +void +CSProjectile::_FireSingle(vector vecPos, vector vecAngles, float flDamage, float flRange) +{ + vector range; + vector planeNormal; + vector endPos; + + if (flRange <= 0) + return; + + if (flDamage < 1) + return; + + range = (vecAngles * 8196); + + owner.dimension_solid = 255; + owner.dimension_hit = 255; + + /* make sure we can gib corpses */ + int oldhitcontents = owner.hitcontentsmaski; + owner.hitcontentsmaski = CONTENTBITS_POINTSOLID | CONTENTBIT_CORPSE | CONTENTBIT_WATER | CONTENTBIT_SLIME | CONTENTBIT_LAVA | CONTENTBIT_PROJECTILE; + traceline(vecPos, vecPos + range, MOVE_LAGGED | MOVE_HITMODEL, owner); + owner.hitcontentsmaski = oldhitcontents; + planeNormal = trace_plane_normal; + endPos = trace_endpos; + + flRange -= trace_plane_dist; + + owner.dimension_solid = 254; + owner.dimension_hit = 254; + + m_iMultiBody |= trace_surface_id; + + if (trace_fraction >= 1.0f) + return; + + /* water impact */ + if (trace_endcontentsi & CONTENTBIT_WATER) { + SurfData_ImpactOfNamedType("water", endPos, planeNormal); + _FireSingle(endPos + (v_forward * 2), vecAngles, flDamage / 2, flRange); + } else if (trace_endcontentsi & CONTENTBIT_SLIME) { + SurfData_ImpactOfNamedType("slime", endPos, planeNormal); + _FireSingle(endPos + (v_forward * 2), vecAngles, flDamage / 2, flRange); + } else if (trace_endcontentsi & CONTENTBIT_LAVA) { + SurfData_ImpactOfNamedType("lama", endPos, planeNormal); + _FireSingle(endPos + (v_forward * 2), vecAngles, flDamage / 2, flRange); + } + + if (trace_ent.takedamage != DAMAGE_NO && trace_ent.iBleeds) { + Sound_Play(trace_ent, CHAN_BODY, "damage_bullet.hit"); + + NSClientPlayer pl = (NSClientPlayer)trace_ent; + /* modify the damage based on the location */ + switch (trace_surface_id) { + case BODY_HEAD: + /* the helmet is one power house */ + if (pl.HasItem("item_kevlar_helmet") == true) { + flDamage = 0; + Sound_Play(trace_ent, CHAN_BODY, "player.headshotarmor"); + pl.RemoveItem("item_kevlar_helmet"); + return; + } else { + flDamage *= 4; + Sound_Play(trace_ent, CHAN_BODY, "player.headshot"); + } + break; + case BODY_STOMACH: + flDamage *= 0.9; + if (pl.armor > 0) + Sound_Play(trace_ent, CHAN_BODY, "player.hitarmor"); + break; + case BODY_LEGLEFT: + case BODY_LEGRIGHT: + flDamage *= 0.4; + break; + } + } + + /* impact per bullet */ + if (m_bDetonateOnWorld == true && trace_ent.iBleeds == 0) { + if (m_strDecalGroup) + DecalGroups_Place(m_strDecalGroup, endPos + (vecAngles * -2)); + + SurfData_Impact(trace_ent, endPos, planeNormal); + } + + /* combine them into one single Damage_Apply call later */ + if (trace_ent.takedamage != DAMAGE_NO) { + if (trace_ent != m_eMultiTarget) { + trace_endpos = endPos; + _ApplyDamage(); + m_eMultiTarget = (NSSurfacePropEntity)trace_ent; + m_iMultiValue = flDamage; + } else { + m_iMultiValue += flDamage; + } + } + + if (m_iTotalPenetrations > 0) { + float cont; + +#if 0 + if (!(trace_surfaceflagsi & SURF_PENETRATE)) + m_iTotalPenetrations -= 1; +#endif + + /* check if this wall is 6 units thick... */ + if (m_iTotalPenetrations > 0) { + cont = pointcontents(endPos + v_forward * 5); + + if (cont == CONTENT_SOLID) + m_iTotalPenetrations -= 1; /* deduct 1 penetration power */ + } + + cont = pointcontents(endPos + v_forward * m_flMaxThickness); + + if (cont == CONTENT_EMPTY) + _FireSingle(endPos + (v_forward * 2), vecAngles, flDamage / 2, flRange); + } +} + +CSProjectile +CSProjectile_SpawnDef(string entityDef, NSEntity theOwner, float rangeMod, int power, vector spread) +{ + entity oldself = self; + + CSProjectile rocket = spawn(CSProjectile); + rocket.owner = theOwner; + self = rocket; + EntityDef_SpawnClassname(entityDef); + self = oldself; + + rocket.m_vecSpread = spread; + rocket.SetRangeModifier(rangeMod); + rocket.SetPenetrationPower(power); + rocket.SetPenetrationMaxThickness((8 * power) * rangeMod); + rocket.Launch(theOwner.GetEyePos(), theOwner.GetViewAngle(), 0.0f, 0.0f, 0.0f); + return rocket; +} +#endif diff --git a/src/shared/CSWeapon.qc b/src/shared/CSWeapon.qc index 950d2b1..80aed9b 100644 --- a/src/shared/CSWeapon.qc +++ b/src/shared/CSWeapon.qc @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024 Marco Cawthorne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #ifdef CLIENT void Cstrike_DrawCrosshair(CSPlayer); @@ -23,7 +38,7 @@ CSWeapon:NSWeapon virtual void PrimaryAttack(void); virtual void SecondaryAttack(void); virtual void Release(void); - virtual void HitscanAttack(string); + virtual void FiredWeapon(string); virtual void SwitchedToWeapon(void); }; @@ -87,11 +102,11 @@ CSWeapon::SecondaryAttack(void) } void -CSWeapon::HitscanAttack(string defName) +CSWeapon::FiredWeapon(string defName) { CSPlayer ourOwner = (CSPlayer)owner; int numProjectiles = GetSubDefInt(defName, "numProjectiles"); - string traceInfo = GetSubDefString(defName, "def_projectile"); + string traceInfo = GetSubDefString(defName, "def_onFire"); float flAccuracyDivisor = GetSubDefFloat(defName,"accuracyDivisor"); float flAccuracyMovementPenalty = GetSubDefFloat(defName,"accuracyMovementPenalty"); float flAccuracyMultiplier = GetSubDefFloat(defName,"accuracyMultiplier"); @@ -119,15 +134,12 @@ CSWeapon::HitscanAttack(string defName) float traceDamage = GetSubDefFloat(traceInfo, "damage"); /* don't bother with shotguns */ - if (numProjectiles <= 3i) { - //TraceAttack_SetRangeModifier(flRangeModifier); - //TraceAttack_SetPenetrationPower(flPenetrationPower); - } else { + if (numProjectiles > 3i) { bulletSpread = [random(-1,1) * 0.1,random(-1,1) * 0.05]; } for (int i = 0i; i < numProjectiles; i++) { - // TraceAttack_FireBulletsWithDecal(1, ourOwner.GetEyePos(), traceDamage, bulletSpread, 0, "Impact.BigShot", ourOwner); + CSProjectile_SpawnDef(traceInfo, owner, flRangeModifier, flPenetrationPower, bulletSpread); } #endif @@ -137,7 +149,7 @@ CSWeapon::HitscanAttack(string defName) /* don't bother with shotguns */ if (numProjectiles <= 3i) { - Cstrike_ShotMultiplierAdd(ourOwner, flMultiplierShots, flMultiplierStrength,accuracy* flMultiplierInaccuracy); + Cstrike_ShotMultiplierAdd(ourOwner, flMultiplierShots, flMultiplierStrength, accuracy * flMultiplierInaccuracy); } } diff --git a/src/server/player.qc b/src/shared/buying.h similarity index 53% rename from src/server/player.qc rename to src/shared/buying.h index bfec853..c039799 100644 --- a/src/server/player.qc +++ b/src/shared/buying.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2021 Marco Cawthorne + * Copyright (c) 2016-2020 Marco Cawthorne * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,14 +14,45 @@ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - -void -Player_Precache(void) +/* Weapon Indices for the weapon table */ +typedef enum { - searchhandle pm; - pm = search_begin("models/player/*/*.mdl", TRUE, TRUE); - for (int i = 0; i < search_getsize(pm); i++) { - precache_model(search_getfilename(pm, i)); - } - search_end(pm); -} + BUY_NONE, + BUY_M3, + BUY_XM1014, + BUY_MP5, + BUY_P90, + BUY_UMP45, + BUY_MAC10, + BUY_TMP, +#if defined(CZERO) || defined(CSSOURCE) + BUY_FAMAS, + BUY_GALIL, +#endif + BUY_AK47, + BUY_SG552, + BUY_M4A1, + BUY_AUG, + BUY_SCOUT, + BUY_AWP, + BUY_G3SG1, + BUY_SG550, + BUY_PARA, + BUY_USP45, + BUY_GLOCK18, + BUY_DEAGLE, + BUY_P228, + BUY_ELITES, + BUY_FIVESEVEN, + BUY_KNIFE, + BUY_HEGRENADE, + BUY_FLASHBANG, + BUY_SMOKEGRENADE, + BUY_C4BOMB, + BUY_PRIMARYAMMO, + BUY_SECONDARYAMMO, + BUY_VEST, + BUY_VESTHELMET, + BUY_DEFUSALKIT, + BUY_NIGHTVISION +} cs_buyindex; diff --git a/src/shared/defs.h b/src/shared/defs.h index 9e9e14c..2c955e1 100644 --- a/src/shared/defs.h +++ b/src/shared/defs.h @@ -16,10 +16,11 @@ #include "animations.h" #include "radio.h" -#include "weapons.h" +#include "buying.h" #include "items.h" #include "entities.h" #include "events.h" +#include "CSProjectile.h" #define TEAM_SPECTATOR 0 #define TEAM_T 1 diff --git a/src/shared/include.src b/src/shared/include.src index b77e372..c9b7a40 100644 --- a/src/shared/include.src +++ b/src/shared/include.src @@ -12,6 +12,7 @@ fx_flashbang.qc fx_smokenade.qc item_c4bomb.qc weapons_cstrike.qc +CSProjectile.qc CSWeapon.qc pmove.qc #endlist diff --git a/src/shared/player.h b/src/shared/player.h index d7a595c..01ddcd3 100644 --- a/src/shared/player.h +++ b/src/shared/player.h @@ -121,7 +121,6 @@ class CSPlayer:NSClientPlayer PREDICTED_FLOAT(anim_bottom) PREDICTED_FLOAT(anim_bottom_time) - virtual float(void) Physics_MaxSpeed; virtual void(float) Physics_Fall; virtual void(void) Physics_Jump; diff --git a/src/shared/pmove.qc b/src/shared/pmove.qc index 420cfaa..9a67b0a 100644 --- a/src/shared/pmove.qc +++ b/src/shared/pmove.qc @@ -39,101 +39,6 @@ .float waterlevel; .float watertype; -/* values courtesy of https://wiki.alliedmods.net/Cs_weapons_information */ -float -CSPlayer::Physics_MaxSpeed(void) -{ - float spd = super::Physics_MaxSpeed(); - - switch (activeweapon) - { - case WEAPON_M3: - spd *= 230/250; - break; - case WEAPON_XM1014: - spd *= 240/250; - break; - case WEAPON_MP5: - spd *= 250/250; - break; - case WEAPON_P90: - spd *= 245/250; - break; - case WEAPON_UMP45: - spd *= 250/250; - break; - case WEAPON_MAC10: - spd *= 250/250; - break; - case WEAPON_TMP: - spd *= 250/250; - break; - case WEAPON_AK47: - spd *= 221/250; - break; - case WEAPON_SG552: - spd *= 235/250; - break; - case WEAPON_M4A1: - spd *= 230/250; - break; - case WEAPON_AUG: - spd *= 240/250; - break; - case WEAPON_SCOUT: - spd *= 260/250; - break; - case WEAPON_AWP: - spd *= 210/250; - break; - case WEAPON_G3SG1: - spd *= 210/250; - break; - case WEAPON_SG550: - spd *= 210/250; - break; - case WEAPON_PARA: - spd *= 220/250; - break; - case WEAPON_USP45: - spd *= 250/250; - break; - case WEAPON_GLOCK18: - spd *= 250/250; - break; - case WEAPON_DEAGLE: - spd *= 250/250; - break; - case WEAPON_P228: - spd *= 250/250; - break; - case WEAPON_ELITES: - spd *= 250/250; - break; - case WEAPON_FIVESEVEN: - spd *= 250/250; - break; - case WEAPON_KNIFE: - spd *= 250/250; - break; - case WEAPON_HEGRENADE: - spd *= 250/250; - break; - case WEAPON_FLASHBANG: - spd *= 250/250; - break; - case WEAPON_SMOKEGRENADE: - spd *= 250/250; - break; - case WEAPON_C4BOMB: - spd *= 250/250; - break; - default: - } - - return spd; -} - void CSPlayer::Physics_Fall(float impactspeed) { diff --git a/src/shared/weapons.h b/src/shared/weapons.h deleted file mode 100644 index facea3f..0000000 --- a/src/shared/weapons.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2016-2020 Marco Cawthorne - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER - * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* Weapon Indices for the weapon table */ -enum -{ - WEAPON_NONE, - WEAPON_M3, - WEAPON_XM1014, - WEAPON_MP5, - WEAPON_P90, - WEAPON_UMP45, - WEAPON_MAC10, - WEAPON_TMP, -#if defined(CZERO) || defined(CSSOURCE) - WEAPON_FAMAS, - WEAPON_GALIL, -#endif - WEAPON_AK47, - WEAPON_SG552, - WEAPON_M4A1, - WEAPON_AUG, - WEAPON_SCOUT, - WEAPON_AWP, - WEAPON_G3SG1, - WEAPON_SG550, - WEAPON_PARA, - WEAPON_USP45, - WEAPON_GLOCK18, - WEAPON_DEAGLE, - WEAPON_P228, - WEAPON_ELITES, - WEAPON_FIVESEVEN, - WEAPON_KNIFE, - WEAPON_HEGRENADE, - WEAPON_FLASHBANG, - WEAPON_SMOKEGRENADE, - WEAPON_C4BOMB -}; - -#define AMMO_MAX_50AE 35 -#define AMMO_MAX_762MM 90 -#define AMMO_MAX_556MM 90 -#define AMMO_MAX_556MMBOX 200 -#define AMMO_MAX_338MAG 30 -#define AMMO_MAX_9MM 120 -#define AMMO_MAX_BUCKSHOT 32 -#define AMMO_MAX_45ACP 100 -#define AMMO_MAX_357SIG 52 -#define AMMO_MAX_57MM 100 -#define AMMO_MAX_FLASHBANG 2 -#define AMMO_MAX_SMOKE 1 -#define AMMO_MAX_HENADE 1 diff --git a/zpak001.pk3dir/def/items.def b/zpak001.pk3dir/def/items.def new file mode 100644 index 0000000..30adb5d --- /dev/null +++ b/zpak001.pk3dir/def/items.def @@ -0,0 +1,6 @@ +#include "items/c4.def" +#include "items/suit.def" +#include "items/kevlar_helmet.def" +#include "items/nightvision.def" +#include "items/defuse.def" +#include "items/kevlar.def" diff --git a/zpak001.pk3dir/def/item_c4.def b/zpak001.pk3dir/def/items/c4.def similarity index 100% rename from zpak001.pk3dir/def/item_c4.def rename to zpak001.pk3dir/def/items/c4.def diff --git a/zpak001.pk3dir/def/items/defuse.def b/zpak001.pk3dir/def/items/defuse.def new file mode 100644 index 0000000..705eb4c --- /dev/null +++ b/zpak001.pk3dir/def/items/defuse.def @@ -0,0 +1,10 @@ +entityDef item_defuse +{ + "spawnclass" "NSItem" + "model" "models/w_thighpack.mdl" + "mins" "-16 -16 0" + "maxs" "16 16 16" + "snd_acquire" "buy.weapon" + "snd_respawn" "item.respawn" + "inv_carry" "1" +} diff --git a/zpak001.pk3dir/def/items/kevlar.def b/zpak001.pk3dir/def/items/kevlar.def new file mode 100644 index 0000000..dc7f513 --- /dev/null +++ b/zpak001.pk3dir/def/items/kevlar.def @@ -0,0 +1,11 @@ +// actually armor +entityDef item_kevlar +{ + "spawnclass" "NSItem" + "model" "models/w_kevlar.mdl" + "mins" "-16 -16 0" + "maxs" "16 16 16" + "snd_acquire" "buy.kevlar" + "snd_respawn" "item.respawn" + "inv_armor" "100" +} diff --git a/zpak001.pk3dir/def/items/kevlar_helmet.def b/zpak001.pk3dir/def/items/kevlar_helmet.def new file mode 100644 index 0000000..65b21ee --- /dev/null +++ b/zpak001.pk3dir/def/items/kevlar_helmet.def @@ -0,0 +1,11 @@ +// other equipment +entityDef item_kevlar_helmet +{ + "spawnclass" "NSItem" + "model" "models/w_kevlar.mdl" + "mins" "-16 -16 0" + "maxs" "16 16 16" + "snd_acquire" "buy.kevlar" + "snd_respawn" "item.respawn" + "inv_carry" "1" +} diff --git a/zpak001.pk3dir/def/items/nightvision.def b/zpak001.pk3dir/def/items/nightvision.def new file mode 100644 index 0000000..e1380dc --- /dev/null +++ b/zpak001.pk3dir/def/items/nightvision.def @@ -0,0 +1,10 @@ +entityDef item_nightvision +{ + "spawnclass" "NSItem" + "model" "models/w_backpack.mdl" + "mins" "-16 -16 0" + "maxs" "16 16 16" + "snd_acquire" "buy.weapon" + "snd_respawn" "item.respawn" + "inv_carry" "1" +} diff --git a/zpak001.pk3dir/def/items/suit.def b/zpak001.pk3dir/def/items/suit.def new file mode 100644 index 0000000..95854b9 --- /dev/null +++ b/zpak001.pk3dir/def/items/suit.def @@ -0,0 +1,11 @@ +// used in the training mission, HUD etc. +entityDef item_suit +{ + "spawnclass" "NSItem" + "model" "models/w_kevlar.mdl" + "mins" "-16 -16 0" + "maxs" "16 16 16" + "snd_acquire" "buy.kevlar" + "snd_respawn" "item.respawn" + "inv_carry" "1" +} diff --git a/zpak001.pk3dir/def/projectiles.def b/zpak001.pk3dir/def/projectiles.def new file mode 100644 index 0000000..6d8bc9c --- /dev/null +++ b/zpak001.pk3dir/def/projectiles.def @@ -0,0 +1,15 @@ +entityDef projectile_bullet_base +{ + "spawnclass" "CSProjectile" + "is_bullet" "1" + "decal_impact" "Impact.BigShot" + "detonate_on_world" "1" +} + +entityDef projectile_bullet_shotgun +{ + "spawnclass" "NSProjectile" + "is_bullet" "1" + "decal_impact" "Impact.BigShot" + "detonate_on_world" "1" +} diff --git a/zpak001.pk3dir/def/weapons/famas.def b/zpak001.pk3dir/def/weapons/famas.def new file mode 100644 index 0000000..2fd44b4 --- /dev/null +++ b/zpak001.pk3dir/def/weapons/famas.def @@ -0,0 +1,56 @@ +entityDef weapon_famas +{ + "inherit" "CSBaseRifle" + "editor_usage" "FAMAS Weapon - Uses ammo_762nato" + + "model" "models/w_famas.mdl" + "model_view" "models/v_famas.mdl" + + "inv_name" "FAMAS Weapon" + "def_fireInfo" "fireInfo_famas" + "clipSize" "" + + "actFire" "" + "actAltFire" "" + "actHolster" "" + "actReload" "" + "actDraw" "" + "actIdle" "" + + + "snd_fire" "Weapon_FAMAS.Single" + + "speed_mod" "" + "price" "" + "crossMinDist" "" + "crossDeltaDist" "" + "accuracyDivisor" "" + "accuracyMovementPenalty" "" + "accuracyMultiplier" "" + "rangeModifier" "" + "penetrationPower" "" + "bulletStrength" "" + "multiplierShots" "" + "multiplierStrength" "" + "multiplierInaccuracy" "" + + "hudSlot" "0" + "hudSlotPos" "7" + "weight" "25" +} + +entityDef projectile_famas +{ + "inherit" "projectile_bullet_base" + "damage" "skill:plr_famas_dmg" +} + +entityDef fireInfo_famas +{ + "def_onFire" "projectile_famas" + "ammoType" "ammo_762nato" + "ammoRequired" "1" + "ammoPerShot" "1" + "fireRate" "" + "model_flash" "sprites/muzzleflash2.spr" +} diff --git a/zpak001.pk3dir/def/weapons/galil.def b/zpak001.pk3dir/def/weapons/galil.def new file mode 100644 index 0000000..974a647 --- /dev/null +++ b/zpak001.pk3dir/def/weapons/galil.def @@ -0,0 +1,27 @@ +entityDef weapon_galil +{ + "inherit" "CSBaseRifle" + "editor_usage" "galil" + + "model" "models/w_galil.mdl" + "model_view" "models/v_galil.mdl" + + "def_onFire" "projectile_csbullet" + "inv_name" "galil" + "clipSize" "50" + "clipSizeDefault" "25" + "ammoType" "ammo_762nato" + + "actFire" "5,6,7" + "actAltFire" "2" + "actHolster" "4" + "actReload" "3" + "actDraw" "4" + "actIdle" "0,1" + + "snd_fire" "Weapon_Galil.Single" + + "hudSlot" "0" + "hudSlotPos" "7" + "weight" "25" +} diff --git a/zpak001.pk3dir/def/weapons/m3.def b/zpak001.pk3dir/def/weapons/m3.def index 5f2a50c..8ae2a41 100644 --- a/zpak001.pk3dir/def/weapons/m3.def +++ b/zpak001.pk3dir/def/weapons/m3.def @@ -40,13 +40,13 @@ entityDef weapon_m3 entityDef projectile_m3 { - "inherit" "projectile_bullet_base" + "inherit" "projectile_bullet_shotgun" "damage" "skill:plr_m3_dmg" } entityDef fireInfo_m3 { - "def_onFire" "projectile_m3" + "def_onFire" "projectile_m3" "ammoType" "ammo_buckshot" "ammoRequired" "1" "ammoPerShot" "1" diff --git a/zpak001.pk3dir/def/weapons/xm1014.def b/zpak001.pk3dir/def/weapons/xm1014.def index b1b570c..3dd9377 100644 --- a/zpak001.pk3dir/def/weapons/xm1014.def +++ b/zpak001.pk3dir/def/weapons/xm1014.def @@ -42,7 +42,7 @@ entityDef weapon_xm1014 entityDef projectile_xm1014 { - "inherit" "projectile_bullet_base" + "inherit" "projectile_bullet_shotgun" "damage" "skill:plr_xm1014_dmg" } diff --git a/zpak001.pk3dir/maps/eukara/test_weapons.bsp b/zpak001.pk3dir/maps/eukara/test_weapons.bsp new file mode 100644 index 0000000000000000000000000000000000000000..7919edddd071eca911603df2a787f1fa3d82cee3 GIT binary patch literal 18992 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