From 6ff68fcc349a3b9747ef7bf8ebf726a0daabfbbb Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Mon, 8 Mar 2021 10:38:54 +0100 Subject: [PATCH] Initial commit, carried over from Nuclide's Git on March 8th 2021 --- LICENSE | 15 + README.md | 48 + img/preview1.jpg | Bin 0 -> 90799 bytes img/preview2.jpg | Bin 0 -> 100129 bytes img/preview3.jpg | Bin 0 -> 75212 bytes img/preview4.jpg | Bin 0 -> 69564 bytes src/Makefile | 5 + src/client/Makefile | 4 + src/client/cmds.qc | 204 ++++ src/client/crosshair.qc | 123 +++ src/client/defs.h | 160 +++ src/client/entities.qc | 29 + src/client/game_event.qc | 144 +++ src/client/hud.h | 77 ++ src/client/hud.qc | 691 +++++++++++++ src/client/hud_weaponselect.qc | 228 +++++ src/client/init.qc | 141 +++ src/client/player.qc | 149 +++ src/client/predict.qc | 43 + src/client/progs.src | 42 + src/client/radio.h | 3 + src/client/radio.qc | 147 +++ src/client/textmenu.qc | 506 +++++++++ src/client/vgui_chooseteam.qc | 208 ++++ src/progs.src | 2 + src/server/Makefile | 4 + src/server/ammo.qc | 312 ++++++ src/server/armoury_entity.qc | 181 ++++ src/server/buy.qc | 205 ++++ src/server/client.qc | 84 ++ src/server/defs.h | 79 ++ src/server/func_bomb_target.qc | 63 ++ src/server/func_buyzone.qc | 73 ++ src/server/func_escapezone.qc | 38 + src/server/func_hostage_rescue.qc | 85 ++ src/server/func_vip_safetyzone.qc | 38 + src/server/game_money.qc | 156 +++ src/server/game_rules.qc | 44 + src/server/gamerules.h | 81 ++ src/server/gamerules.qc | 197 ++++ src/server/gamerules_multiplayer.qc | 1022 +++++++++++++++++++ src/server/gamerules_singleplayer.qc | 74 ++ src/server/hostage_entity.qc | 229 +++++ src/server/info_buyzone.qc | 50 + src/server/info_hostage_rescue.qc | 79 ++ src/server/info_map_parameters.qc | 63 ++ src/server/input.qc | 93 ++ src/server/item_suit.qc | 69 ++ src/server/money.h | 27 + src/server/player.qc | 93 ++ src/server/progs.src | 61 ++ src/server/radio.h | 4 + src/server/radio.qc | 131 +++ src/server/server.qc | 58 ++ src/server/spawn.qc | 69 ++ src/shared/animations.h | 117 +++ src/shared/animations.qc | 158 +++ src/shared/defs.h | 34 + src/shared/entities.h | 20 + src/shared/equipment.qc | 114 +++ src/shared/events.h | 23 + src/shared/flags.h | 40 + src/shared/fx_flashbang.qc | 60 ++ src/shared/fx_impact.qc | 116 +++ src/shared/fx_smokenade.qc | 63 ++ src/shared/include.src | 53 + src/shared/item_c4bomb.h | 8 + src/shared/item_c4bomb.qc | 286 ++++++ src/shared/items.h | 51 + src/shared/player.h | 837 +++++++++++++++ src/shared/pmove.qc | 162 +++ src/shared/radio.h | 47 + src/shared/w_ak47.qc | 271 +++++ src/shared/w_aug.qc | 296 ++++++ src/shared/w_awp.qc | 323 ++++++ src/shared/w_c4bomb.qc | 241 +++++ src/shared/w_deagle.qc | 276 +++++ src/shared/w_elites.qc | 328 ++++++ src/shared/w_fiveseven.qc | 276 +++++ src/shared/w_flashbang.qc | 292 ++++++ src/shared/w_g3sg1.qc | 288 ++++++ src/shared/w_glock18.qc | 336 ++++++ src/shared/w_hegrenade.qc | 301 ++++++ src/shared/w_knife.qc | 243 +++++ src/shared/w_m3.qc | 328 ++++++ src/shared/w_m4a1.qc | 357 +++++++ src/shared/w_mac10.qc | 271 +++++ src/shared/w_mp5.qc | 271 +++++ src/shared/w_p228.qc | 280 +++++ src/shared/w_p90.qc | 271 +++++ src/shared/w_para.qc | 267 +++++ src/shared/w_scout.qc | 320 ++++++ src/shared/w_sg550.qc | 288 ++++++ src/shared/w_sg552.qc | 296 ++++++ src/shared/w_smokegrenade.qc | 297 ++++++ src/shared/w_tmp.qc | 273 +++++ src/shared/w_ump45.qc | 287 ++++++ src/shared/w_usp45.qc | 354 +++++++ src/shared/w_xm1014.qc | 331 ++++++ src/shared/weapons.h | 62 ++ src/shared/weapons.qc | 47 + src/shared/weapons_cstrike.qc | 81 ++ zpak001.pk3dir/default.cfg | 65 ++ zpak001.pk3dir/gfx/vgui/buymenu.tga | Bin 0 -> 574 bytes zpak001.pk3dir/particles/fx_smokenade.cfg | 15 + zpak001.pk3dir/sound/items_cstrike.sndshd | 14 + zpak001.pk3dir/sound/npcs_cstrike.sndshd | 8 + zpak001.pk3dir/sound/weapons_cstrike.sndshd | 231 +++++ 108 files changed, 17405 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 img/preview1.jpg create mode 100644 img/preview2.jpg create mode 100644 img/preview3.jpg create mode 100644 img/preview4.jpg create mode 100644 src/Makefile create mode 100644 src/client/Makefile create mode 100644 src/client/cmds.qc create mode 100644 src/client/crosshair.qc create mode 100644 src/client/defs.h create mode 100644 src/client/entities.qc create mode 100644 src/client/game_event.qc create mode 100644 src/client/hud.h create mode 100644 src/client/hud.qc create mode 100644 src/client/hud_weaponselect.qc create mode 100644 src/client/init.qc create mode 100644 src/client/player.qc create mode 100644 src/client/predict.qc create mode 100644 src/client/progs.src create mode 100644 src/client/radio.h create mode 100755 src/client/radio.qc create mode 100644 src/client/textmenu.qc create mode 100644 src/client/vgui_chooseteam.qc create mode 100755 src/progs.src create mode 100644 src/server/Makefile create mode 100644 src/server/ammo.qc create mode 100644 src/server/armoury_entity.qc create mode 100644 src/server/buy.qc create mode 100644 src/server/client.qc create mode 100644 src/server/defs.h create mode 100644 src/server/func_bomb_target.qc create mode 100644 src/server/func_buyzone.qc create mode 100644 src/server/func_escapezone.qc create mode 100644 src/server/func_hostage_rescue.qc create mode 100644 src/server/func_vip_safetyzone.qc create mode 100644 src/server/game_money.qc create mode 100755 src/server/game_rules.qc create mode 100644 src/server/gamerules.h create mode 100644 src/server/gamerules.qc create mode 100644 src/server/gamerules_multiplayer.qc create mode 100644 src/server/gamerules_singleplayer.qc create mode 100644 src/server/hostage_entity.qc create mode 100644 src/server/info_buyzone.qc create mode 100644 src/server/info_hostage_rescue.qc create mode 100644 src/server/info_map_parameters.qc create mode 100644 src/server/input.qc create mode 100644 src/server/item_suit.qc create mode 100644 src/server/money.h create mode 100644 src/server/player.qc create mode 100755 src/server/progs.src create mode 100644 src/server/radio.h create mode 100644 src/server/radio.qc create mode 100644 src/server/server.qc create mode 100644 src/server/spawn.qc create mode 100644 src/shared/animations.h create mode 100755 src/shared/animations.qc create mode 100644 src/shared/defs.h create mode 100644 src/shared/entities.h create mode 100755 src/shared/equipment.qc create mode 100644 src/shared/events.h create mode 100644 src/shared/flags.h create mode 100644 src/shared/fx_flashbang.qc create mode 100644 src/shared/fx_impact.qc create mode 100644 src/shared/fx_smokenade.qc create mode 100644 src/shared/include.src create mode 100644 src/shared/item_c4bomb.h create mode 100644 src/shared/item_c4bomb.qc create mode 100644 src/shared/items.h create mode 100644 src/shared/player.h create mode 100644 src/shared/pmove.qc create mode 100644 src/shared/radio.h create mode 100644 src/shared/w_ak47.qc create mode 100644 src/shared/w_aug.qc create mode 100644 src/shared/w_awp.qc create mode 100644 src/shared/w_c4bomb.qc create mode 100644 src/shared/w_deagle.qc create mode 100644 src/shared/w_elites.qc create mode 100644 src/shared/w_fiveseven.qc create mode 100644 src/shared/w_flashbang.qc create mode 100644 src/shared/w_g3sg1.qc create mode 100644 src/shared/w_glock18.qc create mode 100644 src/shared/w_hegrenade.qc create mode 100644 src/shared/w_knife.qc create mode 100644 src/shared/w_m3.qc create mode 100644 src/shared/w_m4a1.qc create mode 100644 src/shared/w_mac10.qc create mode 100644 src/shared/w_mp5.qc create mode 100644 src/shared/w_p228.qc create mode 100644 src/shared/w_p90.qc create mode 100644 src/shared/w_para.qc create mode 100644 src/shared/w_scout.qc create mode 100644 src/shared/w_sg550.qc create mode 100644 src/shared/w_sg552.qc create mode 100644 src/shared/w_smokegrenade.qc create mode 100644 src/shared/w_tmp.qc create mode 100644 src/shared/w_ump45.qc create mode 100644 src/shared/w_usp45.qc create mode 100644 src/shared/w_xm1014.qc create mode 100644 src/shared/weapons.h create mode 100644 src/shared/weapons.qc create mode 100644 src/shared/weapons_cstrike.qc create mode 100755 zpak001.pk3dir/default.cfg create mode 100644 zpak001.pk3dir/gfx/vgui/buymenu.tga create mode 100644 zpak001.pk3dir/particles/fx_smokenade.cfg create mode 100644 zpak001.pk3dir/sound/items_cstrike.sndshd create mode 100644 zpak001.pk3dir/sound/npcs_cstrike.sndshd create mode 100644 zpak001.pk3dir/sound/weapons_cstrike.sndshd diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..73679b8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2016-2021, Marco "eukara" Hladik + +Permission to use, copy, modify, and/or 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 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..3439c2a --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# FreeCS +Clean-room reimplementation of Counter-Strike 1.5 (mod-version). + +Aiming for a stable reimagining of the original mod in QuakeC. +Not aiming for accuracy, but for a smooth, exploit and bug-free +experience over the Internet. + +This is all 100% new, original code written by good old trial and error. +Differences exist and features are slowly being implemented one by one. +This allows the code to be fully free and unencumbered, unlike similar projects. + +Featuring proper weapon prediction to enable stress-free netplay. + +![Preview 1](img/preview1.jpg) +![Preview 2](img/preview2.jpg) +![Preview 3](img/preview3.jpg) +![Preview 4](img/preview4.jpg) + +## Building +Clone the repository into the Nuclide-SDK: + +> git clone REPOURL cstrike + +then either run Nuclide's ./build_game.sh shell script, or issue 'make' inside +./cstrike/src! + +Obviously make sure that Nuclide has fteqw and fteqcc set-up for building. + +## Community +Join us on #freecs via irc.freenode.net and chat. + +## License +ISC License + +Copyright (c) 2016-2021 Marco Hladik + +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. + diff --git a/img/preview1.jpg b/img/preview1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f0393d9f21330115b7e6c7269d92a17459305fd4 GIT binary patch literal 90799 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�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 DhxOiN literal 0 HcmV?d00001 diff --git a/img/preview4.jpg b/img/preview4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..676d86ab017a537ce597d70d92db692f2fb7fb16 GIT binary patch literal 69564 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 Q?q0rE4P>kQXkZ=x0x{|#-T(jq literal 0 HcmV?d00001 diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..cc3f82d --- /dev/null +++ b/src/Makefile @@ -0,0 +1,5 @@ +CC=fteqcc + +all: + cd client && $(MAKE) + cd server && $(MAKE) diff --git a/src/client/Makefile b/src/client/Makefile new file mode 100644 index 0000000..627019a --- /dev/null +++ b/src/client/Makefile @@ -0,0 +1,4 @@ +CC=fteqcc + +all: + $(CC) progs.src diff --git a/src/client/cmds.qc b/src/client/cmds.qc new file mode 100644 index 0000000..375a002 --- /dev/null +++ b/src/client/cmds.qc @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +int +ClientGame_ConsoleCommand(void) +{ + switch(argv(0)) { + case "chooseteam": + Textmenu_Toggle("TEAM_SELECT"); + break; + case "buy": + Textmenu_Toggle("BUY"); + break; + case "radio1": + Textmenu_Toggle("RADIOA"); + break; + case "radio2": + Textmenu_Toggle("RADIOB"); + break; + case "radio3": + Textmenu_Toggle("RADIOC"); + break; + case "nightvision": + /*Nightvision_Toggle();*/ + break; + case "drop": + sendevent("DropWeapon", ""); + break; + case "glock": + sendevent("BuyWeapon", "f", WEAPON_GLOCK18); + break; + case "usp": + sendevent("BuyWeapon", "f", WEAPON_USP45); + break; + case "p228": + sendevent("BuyWeapon", "f", WEAPON_P228); + break; + case "deagle": + sendevent("BuyWeapon", "f", WEAPON_DEAGLE); + break; + case "fn57": + sendevent("BuyWeapon", "f", WEAPON_FIVESEVEN); + break; + case "elites": + sendevent("BuyWeapon", "f", WEAPON_ELITES); + break; + case "m3": + sendevent("BuyWeapon", "f", WEAPON_M3); + break; + case "xm1014": + sendevent("BuyWeapon", "f", WEAPON_XM1014); + break; + case "tmp": + sendevent("BuyWeapon", "f", WEAPON_TMP); + break; + case "mac10": + sendevent("BuyWeapon", "f", WEAPON_MAC10); + break; + case "mp5": + sendevent("BuyWeapon", "f", WEAPON_MP5); + break; + case "ump45": + sendevent("BuyWeapon", "f", WEAPON_UMP45); + break; + case "p90": + sendevent("BuyWeapon", "f", WEAPON_P90); + break; + case "ak47": + sendevent("BuyWeapon", "f", WEAPON_AK47); + break; + case "m4a1": + sendevent("BuyWeapon", "f", WEAPON_M4A1); + break; + case "sg552": + sendevent("BuyWeapon", "f", WEAPON_SG552); + break; + case "aug": + sendevent("BuyWeapon", "f", WEAPON_AUG); + break; + case "scout": + sendevent("BuyWeapon", "f", WEAPON_SCOUT); + break; + case "sg550": + sendevent("BuyWeapon", "f", WEAPON_SG550); + break; + case "awp": + sendevent("BuyWeapon", "f", WEAPON_AWP); + break; + case "g3sg1": + sendevent("BuyWeapon", "f", WEAPON_G3SG1); + break; + case "m249": + sendevent("BuyWeapon", "f", WEAPON_PARA); + break; + case "buyammo1": + case "primammo": + sendevent("AmmoBuyPrimary", ""); + break; + case "buyammo2": + case "secammo": + sendevent("AmmoBuySecondary", ""); + break; + case "vest": + sendevent("BuyEquipment", "f", 0); + break; + case "vesthelm": + sendevent("BuyEquipment", "f", 1); + break; + case "flash": + sendevent("BuyEquipment", "f", 2); + break; + case "hegren": + sendevent("BuyEquipment", "f", 3); + break; + case "vsgren": + sendevent("BuyEquipment", "f", 4); + break; + case "defuser": + sendevent("BuyEquipment", "f", 5); + break; + case "nvg": + sendevent("BuyEquipment", "f", 6); + break; + case "coverme": + sendevent("Radio", "f", RADIO_CT_COVERME); + break; + case "takepoint": + sendevent("Radio", "f", RADIO_CT_POINT); + break; + case "takepoint": + sendevent("Radio", "f", RADIO_POSITION); + break; + case "regroup": + sendevent("Radio", "f", RADIO_REGROUP); + break; + case "followme": + sendevent("Radio", "f", RADIO_FOLLOWME); + break; + case "takingfire": + sendevent("Radio", "f", RADIO_FIREASSIS); + break; + case "go": + sendevent("Radio", "f", RADIO_GO); + break; + case "fallback": + sendevent("Radio", "f", RADIO_FALLBACK); + break; + case "sticktog": + sendevent("Radio", "f", RADIO_STICKTOG); + break; + case "getinpos": + sendevent("Radio", "f", RADIO_COM_GETINPOS); + break; + case "stormfront": + sendevent("Radio", "f", RADIO_STORMFRONT); + break; + case "report": + sendevent("Radio", "f", RADIO_COM_REPORTIN); + break; + case "roger": + sendevent("Radio", "f", RADIO_ROGER); + break; + case "enemyspot": + sendevent("Radio", "f", RADIO_CT_ENEMYS); + break; + case "needbackup": + sendevent("Radio", "f", RADIO_CT_BACKUP); + break; + case "sectorclear": + sendevent("Radio", "f", RADIO_CLEAR); + break; + case "inposition": + sendevent("Radio", "f", RADIO_CT_INPOS); + break; + case "reportingin": + sendevent("Radio", "f", RADIO_CT_REPORTINGIN); + break; + case "getout": + sendevent("Radio", "f", RADIO_GETOUT); + break; + case "negative": + sendevent("Radio", "f", RADIO_NEGATIVE); + break; + case "enemydown": + sendevent("Radio", "f", RADIO_ENEMYDOWN); + break; + default: + return FALSE; + } + return TRUE; +} diff --git a/src/client/crosshair.qc b/src/client/crosshair.qc new file mode 100644 index 0000000..b2e7fd0 --- /dev/null +++ b/src/client/crosshair.qc @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +#define CS_CROSS_COLOR [0,1,0] +#define CS_CROSS_ALPHA 1.0f + +void +Cstrike_DrawCrosshair(void) +{ + player pl = (player)self; + int cross_dist; + int line_length; + + /* these are defined in the weapon-code files */ + float distance = pl.cs_cross_mindist; + float delta = pl.cs_cross_deltadist; + + if (!(pl.flags & FL_ONGROUND)) { + distance = distance * 2.0f; + } else if (pl.flags & FL_CROUCHING) { /* crouching... */ + distance = distance * 0.5f; + } else if (vlen(pl.velocity) > 120) { /* running, not walking */ + distance = distance * 1.5f; + } + + /* amount of shots that we've shot does affect our accuracy */ + if (pl.cs_shotmultiplier > pl.cs_shotmultiplier_net) { + pl.cs_crosshairdistance = min(15, pl.cs_crosshairdistance + delta); + } else if (pl.cs_crosshairdistance > distance) { + pl.cs_crosshairdistance -= (pl.cs_crosshairdistance * clframetime); + } + + pl.cs_shotmultiplier_net = pl.cs_shotmultiplier; + + if (pl.cs_crosshairdistance < distance) { + pl.cs_crosshairdistance = distance; + } + + cross_dist = ceil(pl.cs_crosshairdistance); + line_length = max(1, ((cross_dist - distance) / 2) + 5); + + /* line setup */ + vector vert1, vert2, hori1, hori2; + vert1 = vert2 = hori1 = hori2 = g_hudmins + (g_hudres / 2); + + /* vertical Lines */ + vert1[1] -= (cross_dist + line_length); + vert2[1] += cross_dist + 1; + + /* horizontal Lines */ + hori1[0] -= (cross_dist + line_length); + hori2[0] += cross_dist + 1; + + drawfill(vert1, [1, line_length], CS_CROSS_COLOR, CS_CROSS_ALPHA, DRAWFLAG_ADDITIVE); + drawfill(vert2, [1, line_length], CS_CROSS_COLOR, CS_CROSS_ALPHA, DRAWFLAG_ADDITIVE); + drawfill(hori1, [line_length, 1], CS_CROSS_COLOR, CS_CROSS_ALPHA, DRAWFLAG_ADDITIVE); + drawfill(hori2, [line_length, 1], CS_CROSS_COLOR, CS_CROSS_ALPHA, DRAWFLAG_ADDITIVE); +} + +/* AUG zoom uses this. so does the spectator cam */ +void +Cstrike_DrawSimpleCrosshair(void) +{ + static vector cross_pos; + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + drawsubpic(cross_pos, [24,24], g_cs_cross, [0.1875,0], [0.1875, 0.1875], [1,1,1], 1, DRAWFLAG_NORMAL); +} + +/* +================= +HUD_DrawScope + +Tries to draw a scope whenever viewzoom < 1.0f +================= +*/ +void +Cstrike_DrawScope(void) +{ + vector scope_pos; + static float scope_offset; + static float scope_scale; + + static void Cstrike_ScopePic(vector pos, vector sz, string img) { + drawpic((pos * scope_scale) + [scope_offset, 0], img, sz * scope_scale, [1,1,1], 1.0f); + } + + // Draw the scope in the middle, seperately from the border + scope_pos = g_hudmins + (g_hudres / 2) + [-128,-128]; + drawpic(scope_pos, g_cs_scope0, [256,256], [1,1,1], 1.0f, DRAWFLAG_NORMAL); + + // Border scale to fit the screen + scope_scale = g_hudres[1] / 480; + scope_offset = g_hudmins[0] + (g_hudres[0] / 2) - ((640 * scope_scale) / 2); + + // Type 1 Border... more coming soon? + Cstrike_ScopePic([0,0], [192,112], g_cs_scope1); + Cstrike_ScopePic([192,0], [256,112], g_cs_scope2); + Cstrike_ScopePic([448,0], [192,112], g_cs_scope3); + Cstrike_ScopePic([0,112], [192,256], g_cs_scope4); + Cstrike_ScopePic([448,112], [192,256], g_cs_scope5); + Cstrike_ScopePic([0,368], [192,112], g_cs_scope6); + Cstrike_ScopePic([192,368], [256,112], g_cs_scope7); + Cstrike_ScopePic([448,368], [192,112], g_cs_scope8); + + // Rect borders left and right + if (scope_offset > 0) { + drawfill([0,0], [scope_offset, g_hudres[1]], [0,0,0], 1.0f); + drawfill([(640 * scope_scale) + scope_offset, 0], [scope_offset, g_hudres[1]], [0,0,0], 1.0f); + } +} diff --git a/src/client/defs.h b/src/client/defs.h new file mode 100644 index 0000000..c29e4d5 --- /dev/null +++ b/src/client/defs.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +#include "hud.h" +#include "radio.h" +#include "../../../valve/src/client/obituary.h" + +var int autocvar_cl_autoweaponswitch = TRUE; + +vector g_hud_color; +vector g_hudmins; +vector g_hudres; + +var string g_hud1_spr; +var string g_hud2_spr; +var string g_hud3_spr; +var string g_hud4_spr; +var string g_hud5_spr; +var string g_hud6_spr; +var string g_hud7_spr; +var string g_hud10_spr; +var string g_hud11_spr; +var string g_hud12_spr; +var string g_hud13_spr; +var string g_hud14_spr; +var string g_hud15_spr; +var string g_hud16_spr; + +var string g_cs_cross; +var string g_cs_scope0; +var string g_cs_scope1; +var string g_cs_scope2; +var string g_cs_scope3; +var string g_cs_scope4; +var string g_cs_scope5; +var string g_cs_scope6; +var string g_cs_scope7; +var string g_cs_scope8; + +struct +{ + /* viewmodel stuff */ + entity m_eViewModel; + entity m_eMuzzleflash; + int m_iVMBones; + int m_iVMEjectBone; + int m_iLastWeapon; + int m_iOldWeapon; + float m_flBobTime; + float m_flBob; + + /* damage overlay */ + float m_flDamageAlpha; + vector m_vecDamagePos; + + /* +zoomin cmd */ + int m_iZoomed; + float m_flZoomTime; + + /* player fields */ + entity m_ePlayer; + vector m_vecPredictedOrigin; + vector m_vecPredictedOriginOld; + vector m_vecPredictedVelocity; + float m_flPredictedFlags; + + /* camera fields */ + vector m_vecCameraOrigin; + vector m_vecCameraAngle; + float m_flCameraTime; + + /* hud.c */ + int m_iHealthOld; + float m_flHealthAlpha; + int m_iArmorOld; + float m_flArmorAlpha; + int m_iAmmo1Old; + float m_flAmmo1Alpha; + int m_iAmmo2Old; + float m_flAmmo2Alpha; + int m_iAmmo3Old; + float m_flAmmo3Alpha; + int m_iPickupWeapon; + float m_flPickupAlpha; + + /* This is seperated from the other VGUI stuff so we can check scores + * while buying and whatnot */ + int m_iScoresVisible; + int m_iHUDWeaponSelected; + float m_flHUDWeaponSelectTime; + + /* saturn controller */ + int m_iSaturnMenu; + + /* centerprint related */ + float m_flCenterprintAlpha; + float m_flCenterprintTime; + float m_iCenterprintLines; + string m_strCenterprintBuffer[18]; + + /* chat related */ + float m_flPrintTime; + string m_strPrintBuffer[5]; + int m_iPrintLines; + + int m_iInputAttack2; + int m_iInputReload; + int m_iInputUse; + int m_iInputDuck; + float m_flInputBlockTime; + + /* fading */ + float m_flFadeDuration; + float m_flFadeHold; + float m_flFadeMaxAlpha; + float m_flFadeStyle; + float m_flFadeAlpha; + float m_flFadeTime; + vector m_vecFadeColor; + int m_iFadeActive; + entity m_pWeaponFX; + + /* shake */ + float m_flShakeFreq; + float m_flShakeDuration; + float m_flShakeTime; + float m_flShakeAmp; + + /* cstrike additions */ + float m_iMoneyOld; + float m_flMoneyAlpha; + float m_iMoneyDelta; + int m_iTimeUnitsOld; + float m_flTimeAlpha; + vector m_vecMoneyColor; +} g_seats[4], *pSeat; + +void HUD_DrawAmmo1(void); +void HUD_DrawAmmo2(void); +void HUD_DrawAmmo3(void); +void HUD_WeaponPickupNotify(int); +void HUD_DrawAmmoBar(vector pos, float val, float max, float a); + +void Cstrike_DrawCrosshair(void); +void Cstrike_DrawSimpleCrosshair(void); +void Cstrike_DrawScope(void); +void Textmenu_Call(string); diff --git a/src/client/entities.qc b/src/client/entities.qc new file mode 100644 index 0000000..a56f667 --- /dev/null +++ b/src/client/entities.qc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +int +ClientGame_EntityUpdate(float id, float new) +{ + switch (id) { + case ENT_C4BOMB: + w_c4bomb_parse(); + break; + default: + return FALSE; + } + + return TRUE; +} diff --git a/src/client/game_event.qc b/src/client/game_event.qc new file mode 100644 index 0000000..1e01ed8 --- /dev/null +++ b/src/client/game_event.qc @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 +ClientGame_EventParse(float fHeader) +{ +switch (fHeader) { + case EV_OBITUARY: + Obituary_Parse(); + break; + case EV_SPARK: + vector vSparkPos, vSparkAngle; + vSparkPos[0] = readcoord(); + vSparkPos[1] = readcoord(); + vSparkPos[2] = readcoord(); + vSparkAngle[0] = readcoord(); + vSparkAngle[1] = readcoord(); + vSparkAngle[2] = readcoord(); + FX_Spark(vSparkPos, vSparkAngle); + break; + case EV_GIBHUMAN: + vector vGibPos; + vGibPos[0] = readcoord(); + vGibPos[1] = readcoord(); + vGibPos[2] = readcoord(); + FX_GibHuman(vGibPos); + break; + case EV_BLOOD: + vector vBloodPos; + vector vBloodColor; + + vBloodPos[0] = readcoord(); + vBloodPos[1] = readcoord(); + vBloodPos[2] = readcoord(); + + vBloodColor[0] = readbyte() / 255; + vBloodColor[1] = readbyte() / 255; + vBloodColor[2] = readbyte() / 255; + + FX_Blood(vBloodPos, vBloodColor); + break; + case EV_EXPLOSION: + vector vExploPos; + + vExploPos[0] = readcoord(); + vExploPos[1] = readcoord(); + vExploPos[2] = readcoord(); + + FX_Explosion(vExploPos); + break; + case EV_MODELGIB: + vector vecPos; + vecPos[0] = readcoord(); + vecPos[1] = readcoord(); + vecPos[2] = readcoord(); + + vector vSize; + vSize[0] = readcoord(); + vSize[1] = readcoord(); + vSize[2] = readcoord(); + + float fStyle = readbyte(); + int count = readbyte(); + FX_BreakModel(count, vecPos, vSize, [0,0,0], fStyle); + break; + case EV_IMPACT: + int iType; + vector vOrigin, vNormal; + + iType = (int)readbyte(); + vOrigin[0] = readcoord(); + vOrigin[1] = readcoord(); + vOrigin[2] = readcoord(); + + vNormal[0] = readcoord(); + vNormal[1] = readcoord(); + vNormal[2] = readcoord(); + + FX_Impact(iType, vOrigin, vNormal); + break; + case EV_SMOKE: + vector vSmokePos; + vSmokePos[0] = readcoord(); + vSmokePos[1] = readcoord(); + vSmokePos[2] = readcoord(); + FX_Smokenade(vSmokePos); + break; + case EV_CHAT: + float fSender = readbyte(); + float fTeam = readbyte(); + string sMessage = readstring(); + + CSQC_Parse_Print(sprintf("%s: %s", getplayerkeyvalue(fSender, "name"), sMessage), PRINT_CHAT); + break; + case EV_CHAT_TEAM: + float fSender2 = readbyte(); + float fTeam2 = readbyte(); + string sMessage2 = readstring(); + + CSQC_Parse_Print(sprintf("[TEAM] %s: %s", getplayerkeyvalue(fSender2, "name"), sMessage2), PRINT_CHAT); + break; + case EV_CHAT_VOX: + Vox_Play(readstring()); + break; + case EV_VIEWMODEL: + View_PlayAnimation(readbyte()); + break; + case EV_WEAPON_PICKUP: + int w = readbyte(); + + if (autocvar_cl_autoweaponswitch == 1) { + sendevent("PlayerSwitchWeapon", "i", w); + } + + player pl = (player)pSeat->m_ePlayer; + if (getplayerkeyfloat(pl.entnum-1, "*team") == TEAM_CT) { + setcustomskin(pSeat->m_eViewModel, "", "geomset 0 2\n"); + } else { + setcustomskin(pSeat->m_eViewModel, "", "geomset 0 1\n"); + } + + HUD_WeaponPickupNotify(w); + break; + case EV_RADIOMSG: + Radio_PlayMessage(readbyte()); + break; + case EV_RADIOMSG2: + Radio_PlayPlayerMessage(readbyte(), readbyte()); + break; + } +} diff --git a/src/client/hud.h b/src/client/hud.h new file mode 100644 index 0000000..f9b26f2 --- /dev/null +++ b/src/client/hud.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/* pre-calculated sprite definitions */ +float spr_health[4] = { + 48 / 256, // pos x + 25 / 256, // pos u + 24 / 256, // size x + 24 / 256 // size y +}; + +float spr_suit1[4] = { + 0 / 256, // pos x + 25 / 256, // pos u + 24 / 256, // size x + 24 / 256 // size y +}; + +float spr_suit2[4] = { + 24 / 256, // pos x + 25 / 256, // pos u + 24 / 256, // size x + 24 / 256 // size y +}; + +float spr_suit3[4] = { + 0 / 256, // pos x + 124 / 256, // pos u + 24 / 256, // size x + 24 / 256 // size y +}; + +float spr_suit4[4] = { + 24 / 256, // pos x + 124 / 256, // pos u + 24 / 256, // size x + 24 / 256 // size y +}; + +float spr_flash1[4] = { + 160 / 256, // pos x + 24 / 256, // pos u + 32 / 256, // size x + 32 / 256 // size y +}; + +float spr_flash2[4] = { + 112 / 256, // pos x + 24 / 256, // pos u + 48 / 256, // size x + 32 / 256 // size y +}; + +string +HUD_GetChatColorHEX(float fTeam) +{ + if (fTeam == TEAM_CT) { + return "^x7AC"; + } else if (fTeam == TEAM_T) { + return "^xC33"; + } else { + return "^xCCC"; + } +} diff --git a/src/client/hud.qc b/src/client/hud.qc new file mode 100644 index 0000000..6da96ac --- /dev/null +++ b/src/client/hud.qc @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 HUD_DrawWeaponSelect(void); + +/* Use first frame for drawing (needs precache) */ +#define NUMSIZE_X 24/256 +#define NUMSIZE_Y 24/256 +#define HUD_ALPHA 0.5 + +float spr_hudnum[10] = { + 0 / 256, + 23 / 256, + 47 / 256, + 70 / 256, + 95 / 256, + 119 / 256, + 144 / 256, + 169 / 256, + 192 / 256, + 216 / 256 +}; + +/* precaches */ +void +HUD_Init(void) +{ + precache_model("sprites/640_logo.spr"); + + g_hud1_spr = spriteframe("sprites/640hud1.spr", 0, 0.0f); + g_hud2_spr = spriteframe("sprites/640hud2.spr", 0, 0.0f); + g_hud3_spr = spriteframe("sprites/640hud3.spr", 0, 0.0f); + g_hud4_spr = spriteframe("sprites/640hud4.spr", 0, 0.0f); + g_hud5_spr = spriteframe("sprites/640hud5.spr", 0, 0.0f); + g_hud6_spr = spriteframe("sprites/640hud6.spr", 0, 0.0f); + g_hud7_spr = spriteframe("sprites/640hud7.spr", 0, 0.0f); + g_hud10_spr = spriteframe("sprites/640hud10.spr", 0, 0.0f); + g_hud11_spr = spriteframe("sprites/640hud11.spr", 0, 0.0f); + g_hud12_spr = spriteframe("sprites/640hud12.spr", 0, 0.0f); + g_hud13_spr = spriteframe("sprites/640hud13.spr", 0, 0.0f); + g_hud14_spr = spriteframe("sprites/640hud14.spr", 0, 0.0f); + g_hud15_spr = spriteframe("sprites/640hud15.spr", 0, 0.0f); + g_hud16_spr = spriteframe("sprites/640hud16.spr", 0, 0.0f); + + precache_model("sprites/bottom.spr"); + precache_model("sprites/bottom_left.spr"); + precache_model("sprites/bottom_right.spr"); + precache_model("sprites/left.spr"); + precache_model("sprites/radar640.spr"); + precache_model("sprites/right.spr"); + precache_model("sprites/sniper_scope.spr"); + precache_model("sprites/top.spr"); + precache_model("sprites/top_left.spr"); + precache_model("sprites/top_right.spr"); +} + +/* seperator for mainly ammo */ +void +HUD_DrawSeperator(vector pos) +{ + drawsubpic(pos, + [2,24], + g_hud7_spr, + [240/256, 0], + [2/256, 24/256], + g_hud_color, + HUD_ALPHA, + DRAWFLAG_ADDITIVE + ); +} + +/* handle single/multiple digits */ +void +HUD_DrawNumber(int iNumber, vector vecPos, float fAlpha, vector vColor) +{ + drawsubpic(vecPos, + [20,25], + g_hud7_spr, + [spr_hudnum[iNumber], 0], + [20/256, 25/256], + vColor, + fAlpha, + DRAWFLAG_ADDITIVE + ); +} + +void +HUD_DrawNums(float fNumber, vector vecPos, float fAlpha, vector vColor) +{ + int i = fNumber; + if (i > 0) { + while (i > 0) { + HUD_DrawNumber((float)i % 10, vecPos, fAlpha, vColor); + i = i / 10; + vecPos[0] -= 20; + } + } else { + HUD_DrawNumber(0, vecPos, fAlpha, vColor); + } +} + +/* timer */ +void +HUD_DrawTimer(int spectator) +{ + int iMinutes, iSeconds, iTens, iUnits; + vector time_pos; + + if (spectator) { + time_pos = g_hudmins + [(g_hudres[0] / 2) - 62, 16]; + } else { + time_pos = g_hudmins + [(g_hudres[0] / 2) - 62, g_hudres[1] - 42]; + } + + if (getstatf(STAT_GAMETIME) == -1) { + return; + } + + iMinutes = getstatf(STAT_GAMETIME) / 60; + iSeconds = getstatf(STAT_GAMETIME) - 60 * iMinutes; + iTens = iSeconds / 10; + iUnits = iSeconds - 10 * iTens; + + /* Flashing red numbers */ + if ((iMinutes == 0) && (iTens <= 1)) { + float fAlpha; + + /* 0:00 is fully red */ + if ((iTens == 0) && (iUnits == 0)) { + fAlpha = 1; + } else { + fAlpha = fabs(sin(time * 20)); + } + + HUD_DrawNumber(iMinutes, time_pos + [48,0], fAlpha, [1,0,0]); + HUD_DrawNumber(iTens, time_pos + [75,0], fAlpha, [1,0,0]); + HUD_DrawNumber(iUnits, time_pos + [99,0],fAlpha, [1,0,0]); + HUD_DrawNumber(iMinutes, time_pos + [48,0], 1 - fAlpha, g_hud_color); + HUD_DrawNumber(iTens, time_pos + [75,0], 1 - fAlpha, g_hud_color); + HUD_DrawNumber(iUnits, time_pos + [99,0],1 - fAlpha, g_hud_color); + + /* : symbol */ + drawsubpic(time_pos + [70,6], [3,3], g_hud7_spr, [0.9375, 0], [0.01171875, 0.01171875], [1,0,0], fAlpha, DRAWFLAG_ADDITIVE); + drawsubpic(time_pos + [70,16], [3,3], g_hud7_spr, [0.9375, 0], [0.01171875, 0.01171875], [1,0,0], fAlpha, DRAWFLAG_ADDITIVE); + drawsubpic(time_pos + [70,6], [3,3], g_hud7_spr, [0.9375, 0], [0.01171875, 0.01171875], g_hud_color, 1 - fAlpha, DRAWFLAG_ADDITIVE); + drawsubpic(time_pos + [70,16], [3,3], g_hud7_spr, [0.9375, 0], [0.01171875, 0.01171875], g_hud_color, 1 - fAlpha, DRAWFLAG_ADDITIVE); + + /* clock */ + drawsubpic(time_pos, [24,25], g_hud7_spr, [NUMSIZE_X * 6, NUMSIZE_Y * 3], [NUMSIZE_X, NUMSIZE_Y], [1,0,0], fAlpha, DRAWFLAG_ADDITIVE); + drawsubpic(time_pos, [24,25], g_hud7_spr, [NUMSIZE_X * 6, NUMSIZE_Y * 3], [NUMSIZE_X, NUMSIZE_Y], g_hud_color, 1 - fAlpha, DRAWFLAG_ADDITIVE); + } else { + if (iUnits != pSeat->m_iTimeUnitsOld) { + pSeat->m_flTimeAlpha = 1.0; + } + + if (pSeat->m_flTimeAlpha >= HUD_ALPHA) { + pSeat->m_flTimeAlpha -= clframetime * 0.5; + } else { + pSeat->m_flTimeAlpha = HUD_ALPHA; + } + HUD_DrawNumber(iMinutes, time_pos + [48,0], pSeat->m_flTimeAlpha, g_hud_color); + HUD_DrawNumber(iTens, time_pos + [75,0], pSeat->m_flTimeAlpha, g_hud_color); + HUD_DrawNumber(iUnits, time_pos + [95,0], pSeat->m_flTimeAlpha, g_hud_color); + + drawsubpic(time_pos + [70,6], [3,3], g_hud7_spr, [0.9375, 0], [0.01171875, 0.01171875], g_hud_color, pSeat->m_flTimeAlpha, DRAWFLAG_ADDITIVE); + drawsubpic(time_pos + [70,16], [3,3], g_hud7_spr, [0.9375, 0], [0.01171875, 0.01171875], g_hud_color, pSeat->m_flTimeAlpha, DRAWFLAG_ADDITIVE); + + drawsubpic(time_pos, [24,25], g_hud7_spr, [NUMSIZE_X * 6, NUMSIZE_Y * 3], [NUMSIZE_X, NUMSIZE_Y], g_hud_color, pSeat->m_flTimeAlpha, DRAWFLAG_ADDITIVE); + pSeat->m_iTimeUnitsOld = iUnits; + } +} + +void +HUD_DrawMoney(void) +{ + vector money_pos; + float endalpha; + + money_pos = g_hudmins + [g_hudres[0] - 160, g_hudres[1] - 72]; + + /* if the money differs from last frame, paint it appropriately */ + if (getstati(STAT_MONEY) > pSeat->m_iMoneyOld) { + /* effect already in progress from something else, go add on top of it! */ + if (pSeat->m_flMoneyAlpha > 0) { + pSeat->m_iMoneyDelta += (pSeat->m_iMoneyOld - getstati(STAT_MONEY)); + } else { + pSeat->m_iMoneyDelta = pSeat->m_iMoneyOld - getstati(STAT_MONEY); + } + /* make it green for a short time */ + pSeat->m_vecMoneyColor = [0,1,0]; + pSeat->m_flMoneyAlpha = 1.0; + } else if (getstati(STAT_MONEY) < pSeat->m_iMoneyOld) { + /* same one as above */ + if (pSeat->m_flMoneyAlpha > 0) { + pSeat->m_iMoneyDelta += (pSeat->m_iMoneyOld - getstati(STAT_MONEY)); + } else { + pSeat->m_iMoneyDelta = pSeat->m_iMoneyOld - getstati(STAT_MONEY); + } + /* make it red */ + pSeat->m_vecMoneyColor = [1,0,0]; + pSeat->m_flMoneyAlpha = 1.0; + pSeat->m_iMoneyDelta = pSeat->m_iMoneyOld - getstati(STAT_MONEY); + } + + /* maximum alpha is variable. */ + endalpha = pSeat->m_flMoneyAlpha * HUD_ALPHA; + + /* dollar sign */ + drawsubpic( + money_pos, + [18,26], + g_hud7_spr, + [192/256, 24/256], + [18/256, 26/256], + g_hud_color, + HUD_ALPHA - endalpha, + DRAWFLAG_ADDITIVE + ); + + /* if the alpha/color effect is active, draw the money twice in their + * varying alphas/colors */ + if (pSeat->m_flMoneyAlpha > 0) { + /* red/green dollar sign */ + drawsubpic( + money_pos, + [18,26], + g_hud7_spr, + [192/256, 24/256], + [18/256, 26/256], + pSeat->m_vecMoneyColor, + endalpha, + DRAWFLAG_ADDITIVE + ); + + /* draw the +/- symbols depending on whether + * or not we made or lost money */ + if (pSeat->m_iMoneyDelta < 0) { + drawsubpic(money_pos + [0,-32], [18,23], g_hud7_spr, [0.8671875, 0.09765625], [0.0703125, 0.08984375], pSeat->m_vecMoneyColor, endalpha, DRAWFLAG_ADDITIVE); + } else { + drawsubpic(money_pos + [0,-32], [13,23], g_hud7_spr, [0.8203125, 0.09765625], [0.05078125, 0.08984375], pSeat->m_vecMoneyColor, endalpha, DRAWFLAG_ADDITIVE); + } + + /* shift the numbers for reverse drawing */ + money_pos[0] += (24 * 5); + + /* draw the red/green overlay numbers on top of ours */ + HUD_DrawNums(getstati(STAT_MONEY), money_pos, endalpha, pSeat->m_vecMoneyColor); + + /* draw above how much money we've lost/gotten from all this */ + HUD_DrawNums(fabs(pSeat->m_iMoneyDelta), money_pos + [0,-32], endalpha, pSeat->m_vecMoneyColor); + } else { + money_pos[0] += (24 * 5); + } + + /* regular number */ + HUD_DrawNums( + getstati(STAT_MONEY), + money_pos, + HUD_ALPHA - endalpha, + g_hud_color + ); + + pSeat->m_iMoneyOld = getstati(STAT_MONEY); + pSeat->m_flMoneyAlpha = max(0, pSeat->m_flMoneyAlpha - (clframetime * 0.5)); +} + +/* health */ +void +HUD_DrawHealth(void) +{ + vector pos; + player pl = (player)pSeat->m_ePlayer; + + if (pl.health != pSeat->m_iHealthOld) { + pSeat->m_flHealthAlpha = 1.0; + } + + if (pSeat->m_flHealthAlpha >= HUD_ALPHA) { + pSeat->m_flHealthAlpha -= clframetime * 0.5; + } else { + pSeat->m_flHealthAlpha = HUD_ALPHA; + } + + pos = g_hudmins + [88, g_hudres[1] - 42]; + if (pl.health > 25) { + drawsubpic( + pos + [-72,1], + [24,24], + g_hud7_spr, + [spr_health[0], spr_health[1]], + [spr_health[2], spr_health[3]], + g_hud_color, + pSeat->m_flHealthAlpha, + DRAWFLAG_ADDITIVE + ); + HUD_DrawNums(pl.health, pos, pSeat->m_flHealthAlpha, g_hud_color); + } else { + drawsubpic( + pos + [-72,1], + [24,24], + g_hud7_spr, + [spr_health[0], spr_health[1]], + [spr_health[2], spr_health[3]], + [1,0,0], + pSeat->m_flHealthAlpha, + DRAWFLAG_ADDITIVE + ); + HUD_DrawNums(pl.health, pos, pSeat->m_flHealthAlpha, [1,0,0]); + } + + pSeat->m_iHealthOld = pl.health; +} + +/* armor/suit charge */ +void +HUD_DrawArmor(void) +{ + vector pos; + player pl = (player)pSeat->m_ePlayer; + + pos = g_hudmins + [198, g_hudres[1] - 42]; + + if (pl.armor != pSeat->m_iArmorOld) { + pSeat->m_flArmorAlpha = 1.0; + } + + if (pSeat->m_flArmorAlpha >= HUD_ALPHA) { + pSeat->m_flArmorAlpha -= clframetime * 0.5; + } else { + pSeat->m_flArmorAlpha = HUD_ALPHA; + } + + if (pl.g_items & ITEM_HELMET) { + drawsubpic( + pos + [-80,1], + [24,24], + g_hud7_spr, + [spr_suit4[0], spr_suit4[1]], + [spr_suit4[2], spr_suit4[3]], + g_hud_color, + pSeat->m_flArmorAlpha, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos + [-80,1], + [24,24], + g_hud7_spr, + [spr_suit2[0], spr_suit2[1]], + [spr_suit2[2], spr_suit2[3]], + g_hud_color, + pSeat->m_flArmorAlpha, + DRAWFLAG_ADDITIVE + ); + } + + if (pl.armor > 0) { + if (pl.g_items & ITEM_HELMET) { + drawsubpic( + pos + [-80,1], + [24, 24 * (pl.armor / 100)], + g_hud7_spr, + [spr_suit3[0], + spr_suit3[1]], + [spr_suit3[2], spr_suit3[3] * (pl.armor / 100)], + g_hud_color, + pSeat->m_flArmorAlpha, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos + [-80,1], + [24, 24 * (pl.armor / 100)], + g_hud7_spr, + [spr_suit1[0], + spr_suit1[1]], + [spr_suit1[2], spr_suit1[3] * (pl.armor / 100)], + g_hud_color, + pSeat->m_flArmorAlpha, + DRAWFLAG_ADDITIVE + ); + } + } + + HUD_DrawNums(pl.armor, pos, pSeat->m_flArmorAlpha, g_hud_color); + pSeat->m_iArmorOld = pl.armor; +} + +/* magazine/clip ammo */ +void +HUD_DrawAmmo1(void) +{ + player pl = (player)pSeat->m_ePlayer; + vector pos; + + if (pl.a_ammo1 != pSeat->m_iAmmo1Old) { + pSeat->m_flAmmo1Alpha = 1.0; + pSeat->m_iAmmo1Old = pl.a_ammo1; + } + + if (pSeat->m_flAmmo1Alpha >= HUD_ALPHA) { + pSeat->m_flAmmo1Alpha -= clframetime * 0.5; + } else { + pSeat->m_flAmmo1Alpha = HUD_ALPHA; + } + + pos = g_hudmins + [g_hudres[0] - 152, g_hudres[1] - 42]; + HUD_DrawNums(pl.a_ammo1, pos, pSeat->m_flAmmo1Alpha, g_hud_color); + HUD_DrawSeperator(pos + [30,0]); +} + +/* leftover type ammo */ +void +HUD_DrawAmmo2(void) +{ + player pl = (player)pSeat->m_ePlayer; + vector pos; + + if (pl.a_ammo2 != pSeat->m_iAmmo2Old) { + pSeat->m_flAmmo2Alpha = 1.0; + pSeat->m_iAmmo2Old = pl.a_ammo2; + } + + if (pSeat->m_flAmmo2Alpha >= HUD_ALPHA) { + pSeat->m_flAmmo2Alpha -= clframetime * 0.5; + } else { + pSeat->m_flAmmo2Alpha = HUD_ALPHA; + } + + pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 42]; + HUD_DrawNums(pl.a_ammo2, pos, pSeat->m_flAmmo2Alpha, g_hud_color); +} + +/* special ammo */ +void +HUD_DrawAmmo3(void) +{ + player pl = (player)pSeat->m_ePlayer; + vector pos; + + if (pl.a_ammo3 != pSeat->m_iAmmo3Old) { + pSeat->m_flAmmo3Alpha = 1.0; + pSeat->m_iAmmo3Old = pl.a_ammo3; + } + + if (pSeat->m_flAmmo3Alpha >= HUD_ALPHA) { + pSeat->m_flAmmo3Alpha -= clframetime * 0.5; + } else { + pSeat->m_flAmmo3Alpha = HUD_ALPHA; + } + + pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 74]; + HUD_DrawNums(pl.a_ammo3, pos, pSeat->m_flAmmo3Alpha, g_hud_color); +} + +/* ammo bar */ +void +HUD_DrawAmmoBar(vector pos, float val, float max, float a) +{ + if (val <= 0) + return; + + float perc; + perc = val / max; + drawfill(pos + [10,5], [20,4], g_hud_color, a, DRAWFLAG_NORMAL); + drawfill(pos + [10,5], [20 * perc,4], [0,1,0], a, DRAWFLAG_NORMAL); +} + +/* flashlight/torch indicator */ +void +HUD_DrawFlashlight(void) +{ + vector pos; + player pl = (player)pSeat->m_ePlayer; + pos = g_hudmins + [g_hudres[0] - 48, 16]; + + /* both on, draw both sprites at full intensity */ + if (pl.gflags & GF_FLASHLIGHT) { + drawsubpic( + pos, + [32,32], + g_hud7_spr, + [spr_flash1[0], spr_flash1[1]], + [spr_flash1[2], spr_flash1[3]], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + + drawsubpic( + pos, + [48,32], + g_hud7_spr, + [spr_flash2[0], spr_flash2[1]], + [spr_flash2[2], spr_flash2[3]], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [32,32], + g_hud7_spr, + [spr_flash1[0], spr_flash1[1]], + [spr_flash1[2], spr_flash1[3]], + g_hud_color, + HUD_ALPHA, + DRAWFLAG_ADDITIVE + ); + } +} + +void +HUD_DrawZones(void) +{ + int zc = 0; + vector pos = [0,0,0]; + player pl = (player)pSeat->m_ePlayer; + + if (pl.gflags & GF_BUYZONE) { + zc++; + } + if (pl.gflags & GF_BOMBZONE) { + zc++; + } + if (pl.gflags & GF_RESCUEZONE) { + zc++; + } + if (pl.g_items & ITEM_DEFUSAL) { + zc++; + } + + pos = g_hudmins + [16, (g_hudres[1] / 2) - (zc * 16)]; + + if (pl.gflags & GF_BUYZONE) { + drawsubpic( + pos, + [32,32], + g_hud7_spr, + [96/256,148/256], + [32/256,32/256], + [0,1,0], + 1.0f, + DRAWFLAG_ADDITIVE + ); + pos[1] += 32; + } + if (pl.gflags & GF_BOMBZONE) { + drawsubpic( + pos, + [32,32], + g_hud7_spr, + [0/256,148/256], + [32/256,32/256], + [0,1,0], + 1.0f, + DRAWFLAG_ADDITIVE + ); + pos[1] += 32; + } + if (pl.gflags & GF_RESCUEZONE) { + drawsubpic( + pos, + [32,32], + g_hud7_spr, + [64/256,148/256], + [32/256,32/256], + [0,1,0], + 1.0f, + DRAWFLAG_ADDITIVE + ); + pos[1] += 32; + } + if (pl.g_items & ITEM_DEFUSAL) { + drawsubpic( + pos, + [32,32], + g_hud7_spr, + [32/256,148/256], + [32/256,32/256], + [0,1,0], + 1.0f, + DRAWFLAG_ADDITIVE + ); + pos[1] += 32; + } +} + +/* defusal etc. progress bar */ +void +HUD_DrawProgress(void) +{ + vector vSize = [540,16]; + vector vMainPos; + float progress; + + progress = getstatf(STAT_PROGRESS) / 10.0f; + + if (progress > 0) { + vMainPos = g_hudmins; + vMainPos[0] += (g_hudres[0] / 2) - (vSize[0] / 2); + vMainPos[1] += (g_hudres[1] / 2) - (vSize[1] / 2); + + vector vBar = vSize; + vBar[0] = 538 * progress; + vBar[1] = 14; + drawfill(vMainPos + [1,1], vBar, g_hud_color, 1.0, DRAWFLAG_ADDITIVE); + drawfill(vMainPos, [vSize[0], 1], g_hud_color, 1.0f); // Top + drawfill([vMainPos[0], vMainPos[1] + vSize[1]], [vSize[0], 1], g_hud_color, 1.0f); // Bottom + drawfill(vMainPos, [1, vSize[1]], g_hud_color, 1.0f); // Left + drawfill([vMainPos[0] + vSize[0], vMainPos[1]], [1, vSize[1] + 1], g_hud_color, 1.0f); // Right + } +} + +/* weapon/ammo pickup notifications */ +void +HUD_DrawNotify(void) +{ + vector pos; + + if (pSeat->m_flPickupAlpha <= 0.0f) { + return; + } + + pos = g_hudmins + [g_hudres[0] - 192, g_hudres[1] - 128]; + Weapons_HUDPic(pSeat->m_iPickupWeapon, 1, pos, pSeat->m_flPickupAlpha); + pSeat->m_flPickupAlpha -= clframetime; +} + +void +HUD_WeaponPickupNotify(int w) +{ + pSeat->m_iPickupWeapon = w; + pSeat->m_flPickupAlpha = 1.0f; +} + +/* main entry */ +void +HUD_Draw(void) +{ + player pl = (player)pSeat->m_ePlayer; + + g_hud_color = autocvar_con_color * (1 / 255); + + /* little point in not drawing these, even if you don't have a suit */ + Weapons_DrawCrosshair(); + HUD_DrawWeaponSelect(); + Obituary_Draw(); + + Textmenu_Draw(); + + HUD_DrawMoney(); + HUD_DrawTimer(0); + + if (!(pl.g_items & ITEM_SUIT)) { + return; + } + + HUD_DrawNotify(); + HUD_DrawHealth(); + HUD_DrawArmor(); + HUD_DrawZones(); + HUD_DrawProgress(); + HUD_DrawFlashlight(); + Damage_Draw(); +} + +/* specatator main entry */ +void +HUD_DrawSpectator(void) +{ + // FIXME + Textmenu_Draw(); + Obituary_Draw(); + + HUD_DrawTimer(1); +} diff --git a/src/client/hud_weaponselect.qc b/src/client/hud_weaponselect.qc new file mode 100644 index 0000000..01bd0d4 --- /dev/null +++ b/src/client/hud_weaponselect.qc @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +vector g_vecHUDNums[6] = +{ + [168 / 256, 72 / 256], + [188 / 256, 72 / 256], + [208 / 256, 72 / 256], + [168 / 256, 92 / 256], + [188 / 256, 92 / 256], + [208 / 256, 92 / 256] +}; + +void +HUD_DrawWeaponSelect_Forward(void) +{ + player pl = (player)pSeat->m_ePlayer; + + if (!pl.activeweapon) { + return; + } + + if (pSeat->m_flHUDWeaponSelectTime < time) { + pSeat->m_iHUDWeaponSelected = pl.activeweapon; + sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE); + } else { + sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE); + pSeat->m_iHUDWeaponSelected--; + if (pSeat->m_iHUDWeaponSelected <= 0) { + pSeat->m_iHUDWeaponSelected = g_weapons.length - 1; + } + } + + pSeat->m_flHUDWeaponSelectTime = time + 3; + + if not (pl.g_items & g_weapons[pSeat->m_iHUDWeaponSelected].id) { + HUD_DrawWeaponSelect_Forward(); + } +} + +void +HUD_DrawWeaponSelect_Back(void) +{ + player pl = (player)pSeat->m_ePlayer; + + if (!pl.activeweapon) { + return; + } + + if (pSeat->m_flHUDWeaponSelectTime < time) { + pSeat->m_iHUDWeaponSelected = pl.activeweapon; + sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE); + } else { + sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE); + pSeat->m_iHUDWeaponSelected++; + if (pSeat->m_iHUDWeaponSelected >= g_weapons.length) { + pSeat->m_iHUDWeaponSelected = 1; + } + } + + pSeat->m_flHUDWeaponSelectTime = time + 3; + + if not (pl.g_items & g_weapons[pSeat->m_iHUDWeaponSelected].id) { + HUD_DrawWeaponSelect_Back(); + } +} + +void +HUD_DrawWeaponSelect_Trigger(void) +{ + player pl = (player)pSeat->m_ePlayer; + pl.activeweapon = pSeat->m_iHUDWeaponSelected; + sendevent("PlayerSwitchWeapon", "i", pSeat->m_iHUDWeaponSelected); + sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_select.wav", 0.5f, ATTN_NONE); + pSeat->m_iHUDWeaponSelected = pSeat->m_flHUDWeaponSelectTime = 0; +} + +void +HUD_DrawWeaponSelect_Last(void) +{ + player pl = (player)pSeat->m_ePlayer; + if (pl.g_items & g_weapons[pSeat->m_iOldWeapon].id) { + pl.activeweapon = pSeat->m_iOldWeapon; + sendevent("PlayerSwitchWeapon", "i", pSeat->m_iOldWeapon); + } +} + +void +HUD_DrawWeaponSelect_Num(vector vecPos, int val) +{ + drawsubpic(vecPos, [20,20], g_hud7_spr, g_vecHUDNums[val], [20/256, 20/256], g_hud_color, 1, DRAWFLAG_ADDITIVE); +} + +int +HUD_InSlotPos(int slot, int pos) +{ + player pl = (player)pSeat->m_ePlayer; + for (int i = 1; i < g_weapons.length; i++) { + if (g_weapons[i].slot == slot && g_weapons[i].slot_pos == pos) { + if (pl.g_items & g_weapons[i].id) { + return i; + } else { + return -1; + } + } + } + return -1; +} + +void +HUD_SlotSelect(int slot) +{ + player pl = (player)pSeat->m_ePlayer; + int curslot = g_weapons[pSeat->m_iHUDWeaponSelected].slot; + int i; + + if (g_textmenu != "") { + Textmenu_Input(slot); + return; + } + + /* hack to see if we have ANY weapons at all. */ + if (!pl.activeweapon) { + return; + } + + if (pSeat->m_flHUDWeaponSelectTime < time) { + sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE); + } else { + sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE); + } + + /* weren't in that slot? select the first one then */ + if (curslot != slot) { + for (i = 1; i < g_weapons.length; i++) { + if (g_weapons[i].slot == slot && pl.g_items & g_weapons[i].id) { + pSeat->m_iHUDWeaponSelected = i; + pSeat->m_flHUDWeaponSelectTime = time + 3; + break; + } + } + } else { + int first = -1; + for (i = 1; i < g_weapons.length; i++) { + if (g_weapons[i].slot == slot && pl.g_items & g_weapons[i].id) { + if (i < pSeat->m_iHUDWeaponSelected && first == -1) { + first = i; + } else if (i > pSeat->m_iHUDWeaponSelected) { + first = -1; + pSeat->m_iHUDWeaponSelected = i; + pSeat->m_flHUDWeaponSelectTime = time + 3; + break; + } + } + } + + if (first > 0) { + pSeat->m_iHUDWeaponSelected = first; + pSeat->m_flHUDWeaponSelectTime = time + 3; + } + } +} + +void +HUD_DrawWeaponSelect(void) +{ + player pl = (player)pSeat->m_ePlayer; + if (!pl.activeweapon) { + return; + } + if (pSeat->m_flHUDWeaponSelectTime < time) { + if (pSeat->m_iHUDWeaponSelected) { + sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudoff.wav", 0.5, ATTN_NONE); + pSeat->m_iHUDWeaponSelected = 0; + } + return; + } + + vector vecPos = g_hudmins + [16,16]; + + int b; + int wantslot = g_weapons[pSeat->m_iHUDWeaponSelected].slot; + int wantpos = g_weapons[pSeat->m_iHUDWeaponSelected].slot_pos; + for (int i = 0; i < 5; i++) { + int slot_selected = 0; + vecPos[1] = g_hudmins[1] + 16; + HUD_DrawWeaponSelect_Num(vecPos, i); + vecPos[1] += 20; + for (int x = 0; x < 32; x++) { + if (i == wantslot) { + slot_selected = TRUE; + if (x == wantpos) { + // Selected Sprite + Weapons_HUDPic(pSeat->m_iHUDWeaponSelected, 1, vecPos, 1.0f); + drawsubpic(vecPos, [170,45], g_hud3_spr, + [0,180/256], [170/256,45/256], g_hud_color, 1, DRAWFLAG_ADDITIVE); + vecPos[1] += 50; + } else if ((b=HUD_InSlotPos(i, x)) != -1) { + // Unselected Sprite + Weapons_HUDPic(b, 0, vecPos, 1.0f); + vecPos[1] += 50; + } + } else if (HUD_InSlotPos(i, x) != -1) { + HUD_DrawWeaponSelect_Num(vecPos, 5); + vecPos[1] += 25; + } + } + + if (slot_selected == TRUE) { + vecPos[0] += 175; + } else { + vecPos[0] += 25; + } + } +} diff --git a/src/client/init.qc b/src/client/init.qc new file mode 100644 index 0000000..9281776 --- /dev/null +++ b/src/client/init.qc @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/* +================= +ClientGame_Init + +Comparable to worldspawn in SSQC in that it's mostly used for precaches +================= +*/ +void +ClientGame_Init(float apilevel, string enginename, float engineversion) +{ + registercommand("chooseteam"); + registercommand("buy"); + + /* radio */ + registercommand("radio1"); + registercommand("radio2"); + registercommand("radio3"); + + registercommand("motd"); + registercommand("drop"); + registercommand("nightvision"); + + /* pistols */ + registercommand("glock"); + registercommand("usp"); + registercommand("p228"); + registercommand("deagle"); + registercommand("fn57"); + registercommand("elites"); + + /* shotties */ + registercommand("m3"); + registercommand("xm1014"); + + /* smg */ + registercommand("tmp"); + registercommand("mac10"); + registercommand("mp5"); + registercommand("ump45"); + + /* rifles */ + registercommand("p90"); + registercommand("ak47"); + registercommand("m4a1"); + registercommand("sg552"); + registercommand("aug"); + registercommand("scout"); + registercommand("sg550"); + registercommand("awp"); + registercommand("g3sg1"); + + /* lonely */ + registercommand("m249"); + + /* ammo */ + registercommand("primammo"); + registercommand("buyammo1"); + registercommand("secammo"); + registercommand("buyammo2"); + + /* equipment */ + registercommand("vest"); + registercommand("vesthelm"); + registercommand("flash"); + registercommand("hegren"); + registercommand("vsgren"); + registercommand("defuser"); + registercommand("nvg"); + + /* radio */ + registercommand("coverme"); + registercommand("takepoint"); + registercommand("holdpos"); + registercommand("regroup"); + registercommand("followme"); + registercommand("takingfire"); + registercommand("go"); + registercommand("fallback"); + registercommand("sticktog"); + registercommand("getinpos"); + registercommand("stormfront"); + registercommand("report"); + registercommand("roger"); + registercommand("enemyspot"); + registercommand("needbackup"); + registercommand("sectorclear"); + registercommand("inposition"); + registercommand("reportingin"); + registercommand("getout"); + registercommand("negative"); + registercommand("enemydown"); + + Obituary_Init(); +} + +void +ClientGame_InitDone(void) +{ + Textmenu_Call("TEAM_SELECT"); +} + +void +ClientGame_RendererRestart(string rstr) +{ + g_cs_cross = spriteframe("sprites/crosshairs.spr", 0, 0.0f); + g_cs_scope0 = spriteframe("sprites/sniper_scope.spr", 0, 0.0f); + g_cs_scope1 = spriteframe("sprites/top_left.spr", 0, 0.0f); + g_cs_scope2 = spriteframe("sprites/top.spr", 0, 0.0f); + g_cs_scope3 = spriteframe("sprites/top_right.spr", 0, 0.0f); + g_cs_scope4 = spriteframe("sprites/left.spr", 0, 0.0f); + g_cs_scope5 = spriteframe("sprites/right.spr", 0, 0.0f); + g_cs_scope6 = spriteframe("sprites/bottom_left.spr", 0, 0.0f); + g_cs_scope7 = spriteframe("sprites/bottom.spr", 0, 0.0f); + g_cs_scope8 = spriteframe("sprites/bottom_right.spr", 0, 0.0f); + + Obituary_Precache(); + + FX_Blood_Init(); + FX_BreakModel_Init(); + FX_Explosion_Init(); + FX_GibHuman_Init(); + FX_Spark_Init(); + FX_Impact_Init(); + FX_Smokenade_Init(); +} diff --git a/src/client/player.qc b/src/client/player.qc new file mode 100644 index 0000000..42bacf9 --- /dev/null +++ b/src/client/player.qc @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 +Player_PreDraw(base_player pl, int thirdperson) +{ + /* Handle the flashlights... */ + if (pl.gflags & GF_FLASHLIGHT) { + vector src; + vector ang; + + if (pl.entnum != player_localentnum) { + src = pl.origin + pl.view_ofs; + ang = [pl.pitch, pl.angles[1], pl.angles[2]]; + } else { + src = pSeat->m_vecPredictedOrigin + [0,0,-8]; + ang = view_angles; + } + + makevectors(ang); + traceline(src, src + (v_forward * 8096), MOVE_NORMAL, pl); + + if (serverkeyfloat("*bspversion") == BSPVER_HL) { + dynamiclight_add(trace_endpos + (v_forward * -2), 128, [1,1,1]); + } else { + float p = dynamiclight_add(src, 512, [1,1,1], 0, "textures/flashlight"); + dynamiclight_set(p, LFIELD_ANGLES, ang); + dynamiclight_set(p, LFIELD_FLAGS, 3); + } + } +} + +void +Player_ReceiveEntity(float new) +{ + float fl; + player pl = (player)self; + + if (new == TRUE) { + spawnfunc_player(); + pl.classname = "player"; + pl.solid = SOLID_SLIDEBOX; + pl.drawmask = MASK_ENGINE; + pl.customphysics = Empty; + setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); + } else { + int i; + //FIXME: splitscreen + if (pl.entnum == player_localentnum) { + //FIXME: splitscreen + pSeat = &g_seats[0]; + for (i = pl.sequence+1; i <= servercommandframe; i++) { + if (!getinputstate(i)) { + break; //erk?... too old? + } + input_sequence = i; + PMove_Run(); + } + + /* any differences in things that are read below are now + * officially from prediction misses. */ + } + } + + pl.sequence = servercommandframe; + + fl = readfloat(); + + /* HACK: we need to make this more reliable */ + if (fl == UPDATE_ALL) { + /* we respawned */ + pl.gravity = __NULL__; + } + + if (fl & PLAYER_MODELINDEX) + pl.modelindex = readshort(); + + if (fl & PLAYER_ORIGIN) { + pl.origin[0] = readcoord(); + pl.origin[1] = readcoord(); + } + + if (fl & PLAYER_ORIGIN_Z) + pl.origin[2] = readcoord(); + if (fl & PLAYER_ANGLES_X) + pl.pitch = readfloat(); + if (fl & PLAYER_ANGLES_Y) + pl.angles[1] = readfloat(); + if (fl & PLAYER_ANGLES_Z) + pl.angles[2] = readfloat(); + + if (fl & PLAYER_VELOCITY) { + pl.velocity[0] = readcoord(); + pl.velocity[1] = readcoord(); + } + + if (fl & PLAYER_VELOCITY_Z) + pl.velocity[2] = readcoord(); + if (fl & PLAYER_FLAGS) { + pl.flags = readfloat(); + pl.gflags = readfloat(); + } + if (fl & PLAYER_WEAPON) + pl.activeweapon = readbyte(); + if (fl & PLAYER_ITEMS) + pl.g_items = (__variant)readfloat(); + if (fl & PLAYER_HEALTH) + pl.health = readbyte(); + if (fl & PLAYER_ARMOR) + pl.armor = readbyte(); + if (fl & PLAYER_MOVETYPE) + pl.movetype = readbyte(); + if (fl & PLAYER_VIEWOFS) + pl.view_ofs[2] = readfloat(); + if (fl & PLAYER_BASEFRAME) { + pl.baseframe = readbyte(); + pl.baseframe1time = 0.0f; + pl.baseframe2time = 0.0f; + } + if (fl & PLAYER_FRAME) + pl.frame = readbyte(); + + if (fl & PLAYER_AMMO1) + pl.a_ammo1 = readbyte(); + if (fl & PLAYER_AMMO2) + pl.a_ammo2 = readbyte(); + if (fl & PLAYER_AMMO3) + pl.a_ammo3 = readbyte(); + + if (fl & PLAYER_CSSHOT) + pl.cs_shotmultiplier = readbyte(); + if (fl & PLAYER_CSSHOTTIME) + pl.cs_shottime = readfloat(); + + setorigin(pl, pl.origin); +} diff --git a/src/client/predict.qc b/src/client/predict.qc new file mode 100644 index 0000000..7dabe8f --- /dev/null +++ b/src/client/predict.qc @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/* +================= +Predict_PreFrame + +We're part way through parsing new player data. +Propagate our pmove state to whatever the current frame before its stomped on +(so any non-networked state updates locally). +================= +*/ +void +GamePredict_PreFrame(player pl) +{ +} + +/* +================= +Predict_PostFrame + +We're part way through parsing new player data. +Rewind our pmove state back to before we started predicting. +(to give consistent state instead of accumulating errors) +================= +*/ +void +GamePredict_PostFrame(player pl) +{ +} diff --git a/src/client/progs.src b/src/client/progs.src new file mode 100644 index 0000000..1b33b5d --- /dev/null +++ b/src/client/progs.src @@ -0,0 +1,42 @@ +#pragma target fte +#pragma progs_dat "../../csprogs.dat" +#pragma includedir "../../../valve/src" + +#define CSQC +#define CLIENT +#define VALVE +#define CSTRIKE +#define CLASSIC_VGUI +#define GS_RENDERFX + +#includelist +../../../src/shared/fteextensions.qc +../../../src/shared/defs.h +../shared/defs.h +defs.h +../../../src/client/defs.h +../../../src/vgui/include.src +../../../src/gs-entbase/client.src +../../../src/gs-entbase/shared.src +../shared/include.src + +predict.qc +textmenu.qc +init.qc +player.qc +entities.qc +cmds.qc +game_event.qc +../../../valve/src/client/view.qc +crosshair.qc +../../../valve/src/client/obituary.qc +hud.qc +hud_weaponselect.qc +../../../valve/src/client/scoreboard.qc +../../../valve/src/client/input.qc +radio.qc +../../../base/src/client/modelevent.qc + +../../../src/client/include.src +../../../src/shared/include.src +#endlist diff --git a/src/client/radio.h b/src/client/radio.h new file mode 100644 index 0000000..64cbe23 --- /dev/null +++ b/src/client/radio.h @@ -0,0 +1,3 @@ +void Radio_Init(void); +void Radio_PlayMessage(float); +void Radio_PlayPlayerMessage(float, float); diff --git a/src/client/radio.qc b/src/client/radio.qc new file mode 100755 index 0000000..5a44087 --- /dev/null +++ b/src/client/radio.qc @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +string g_cstrikeRadioWAVs[43] = { + "radio/blow.wav", + "radio/bombdef.wav", + "radio/bombpl.wav", + "radio/circleback.wav", + "radio/clear.wav", + "radio/com_followcom.wav", + "radio/com_getinpos.wav", + "radio/com_go.wav", + "radio/com_reportin.wav", + "radio/ct_affirm.wav", + "radio/ct_backup.wav", + "radio/ct_coverme.wav", + "radio/ct_enemys.wav", + "radio/ct_fireinhole.wav", + "radio/ct_imhit.wav", + "radio/ct_inpos.wav", + "radio/ct_point.wav", + "radio/ct_reportingin.wav", + "radio/ctwin.wav", + "radio/enemydown.wav", + "radio/fallback.wav", + "radio/fireassis.wav", + "radio/followme.wav", + "radio/getout.wav", + "radio/go.wav", + "radio/hitassist.wav", + "radio/hosdown.wav", + "radio/letsgo.wav", + "radio/locknload.wav", + "radio/matedown.wav", + "radio/meetme.wav", + "radio/moveout.wav", + "radio/negative.wav", + "radio/position.wav", + "radio/regroup.wav", + "radio/rescued.wav", + "radio/roger.wav", + "radio/rounddraw.wav", + "radio/sticktog.wav", + "radio/stormfront.wav", + "radio/takepoint.wav", + "radio/terwin.wav", + "radio/vip.wav" +}; + +string g_cstrikeRadioChat[43] = { + _("RADIO_BLOW"), + _("RADIO_BOMBDEF"), + _("RADIO_BOMBPL"), + _("RADIO_CIRCLEBACK"), + _("RADIO_CLEAR"), + _("RADIO_COM_FOLLOWCOM"), + _("RADIO_COM_GETINPOS"), + _("RADIO_COM_GO"), + _("RADIO_COM_REPORTIN"), + _("RADIO_CT_AFFIRM"), + _("RADIO_CT_BACKUP"), + _("RADIO_CT_COVERME"), + _("RADIO_CT_ENEMYS"), + _("RADIO_CT_FIREINHOLE"), + _("RADIO_CT_IMHIT"), + _("RADIO_CT_INPOS"), + _("RADIO_CT_POINT"), + _("RADIO_CT_REPORTINGIN"), + _("RADIO_CTWIN"), + _("RADIO_ENEMYDOWN"), + _("RADIO_FALLBACK"), + _("RADIO_FIREASSIS"), + _("RADIO_FOLLOWME"), + _("RADIO_GETOUT"), + _("RADIO_GO"), + _("RADIO_HITASSIST"), + _("RADIO_HOSDOWN"), + _("RADIO_LETSGO"), + _("RADIO_LOCKNLOAD"), + _("RADIO_MATEDOWN"), + _("RADIO_MEETME"), + _("RADIO_MOVEOUT"), + _("RADIO_NEGATIVE"), + _("RADIO_POSITION"), + _("RADIO_REGROUP"), + _("RADIO_RESCUED"), + _("RADIO_ROGER"), + _("RADIO_ROUNDDRAW"), + _("RADIO_STICKTOG"), + _("RADIO_STORMFRONT"), + _("RADIO_TAKEPOINT"), + _("RADIO_TERWIN"), + _("RADIO_VIP"), +}; + +void +Radio_Init(void) +{ + for (int i = 0; i < g_cstrikeRadioWAVs.length; i++) + precache_sound(g_cstrikeRadioWAVs[i]); +} + +/* +================= +Radio_PlayMessage + +Play a radio message that doesn't come from a player +================= +*/ +void +Radio_PlayMessage(float fMessage) +{ + sound(world, CHAN_VOICE, g_cstrikeRadioWAVs[fMessage], 1, ATTN_NONE, 0, SOUNDFLAG_NOSPACIALISE); + + if (fMessage == RADIO_CTWIN || fMessage == RADIO_TERWIN || fMessage == RADIO_ROUNDDRAW) { + CSQC_Parse_CenterPrint(sprintf("%s", g_cstrikeRadioChat[fMessage])); + } else { + CSQC_Parse_Print(sprintf("^2[RADIO]^xF80: %s", g_cstrikeRadioChat[fMessage]), PRINT_CHAT); + } +} + +/* +================= +Radio_PlayPlayerMessage + +This radio message does come from a player +================= +*/ +void +Radio_PlayPlayerMessage(float fPlayerNum, float fMessage) +{ + sound(world, CHAN_VOICE, g_cstrikeRadioWAVs[fMessage], 1, ATTN_NONE, 0, SOUNDFLAG_NOSPACIALISE); + CSQC_Parse_Print(sprintf("^2[RADIO] %s%s^xF80: %s", HUD_GetChatColorHEX(stof(getplayerkeyvalue(fPlayerNum, "*team"))), getplayerkeyvalue(fPlayerNum, "name"), g_cstrikeRadioChat[fMessage]), PRINT_CHAT); +} diff --git a/src/client/textmenu.qc b/src/client/textmenu.qc new file mode 100644 index 0000000..d368b34 --- /dev/null +++ b/src/client/textmenu.qc @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 +TEAM_SELECT(int n) +{ + switch (n) { + case 1: + Textmenu_Call("TERRORIST_SELECT"); + break; + case 2: + Textmenu_Call("CT_SELECT"); + break; + case 5: + sendevent("JoinAuto", ""); + Textmenu_Call(""); + break; + } +} +void +TERRORIST_SELECT(int n) +{ + switch (n) { + case 1: + sendevent("JoinTeam", "f", 1); + Textmenu_Call(""); + break; + case 2: + sendevent("JoinTeam", "f", 2); + Textmenu_Call(""); + break; + case 3: + sendevent("JoinTeam", "f", 3); + Textmenu_Call(""); + break; + case 4: + sendevent("JoinTeam", "f", 4); + Textmenu_Call(""); + break; + case 5: + sendevent("JoinTeam", "f", floor(random(1,5))); + Textmenu_Call(""); + break; + } +} +void +CT_SELECT(int n) +{ + switch (n) { + case 1: + sendevent("JoinTeam", "f", 5); + Textmenu_Call(""); + break; + case 2: + sendevent("JoinTeam", "f", 6); + Textmenu_Call(""); + break; + case 3: + sendevent("JoinTeam", "f", 7); + Textmenu_Call(""); + break; + case 4: + sendevent("JoinTeam", "f", 8); + Textmenu_Call(""); + break; + case 5: + sendevent("JoinTeam", "f", floor(random(1,5))); + Textmenu_Call(""); + break; + } +} +void +BUY(int n) +{ + player pl; + pl = (player)pSeat->m_ePlayer; + int inteam = getplayerkeyfloat(pl.entnum-1, "*team"); + + switch (n) { + case 1: + Textmenu_Call(inteam == TEAM_T ? "T_BUYPISTOL" : "CT_BUYPISTOL"); + break; + case 2: + Textmenu_Call("BUYSHOTGUN"); + break; + case 3: + Textmenu_Call(inteam == TEAM_T ? "T_BUYSUBMACHINEGUN" : "CT_BUYSUBMACHINEGUN"); + break; + case 4: + Textmenu_Call(inteam == TEAM_T ? "T_BUYRIFLE" : "CT_BUYRIFLE"); + break; + case 5: + Textmenu_Call(inteam == TEAM_T ? "BUYMACHINEGUN" : "BUYMACHINEGUN"); + break; + case 6: + sendevent("AmmoBuyPrimary", ""); + Textmenu_Call(""); + break; + case 7: + sendevent("AmmoBuySecondary", ""); + Textmenu_Call(""); + break; + case 8: + Textmenu_Call(inteam == TEAM_T ? "DT_BUYITEM" : "DCT_BUYITEM"); + break; + case 10: + Textmenu_Call(""); + break; + } +} + +/* Equipment */ +void +DT_BUYITEM(int n) +{ + switch (n) { + case 1: + sendevent("BuyEquipment", "f", 0); + break; + case 2: + sendevent("BuyEquipment", "f", 1); + break; + case 3: + sendevent("BuyEquipment", "f", 2); + break; + case 4: + sendevent("BuyEquipment", "f", 3); + break; + case 5: + sendevent("BuyEquipment", "f", 4); + break; + case 7: + sendevent("BuyEquipment", "f", 6); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} +void +DCT_BUYITEM(int n) +{ + switch (n) { + case 1: + sendevent("BuyEquipment", "f", 0); + break; + case 2: + sendevent("BuyEquipment", "f", 1); + break; + case 3: + sendevent("BuyEquipment", "f", 2); + break; + case 4: + sendevent("BuyEquipment", "f", 3); + break; + case 5: + sendevent("BuyEquipment", "f", 4); + break; + case 6: + sendevent("BuyEquipment", "f", 5); + break; + case 7: + sendevent("BuyEquipment", "f", 6); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} + +/* Handguns */ +void +T_BUYPISTOL(int n) +{ + switch (n) { + case 1: + sendevent("BuyWeapon", "f", WEAPON_USP45); + break; + case 2: + sendevent("BuyWeapon", "f", WEAPON_GLOCK18); + break; + case 3: + sendevent("BuyWeapon", "f", WEAPON_DEAGLE); + break; + case 4: + sendevent("BuyWeapon", "f", WEAPON_P228); + break; + case 5: + sendevent("BuyWeapon", "f", WEAPON_ELITES); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} +void +CT_BUYPISTOL(int n) +{ + switch (n) { + case 1: + sendevent("BuyWeapon", "f", WEAPON_USP45); + break; + case 2: + sendevent("BuyWeapon", "f", WEAPON_GLOCK18); + break; + case 3: + sendevent("BuyWeapon", "f", WEAPON_DEAGLE); + break; + case 4: + sendevent("BuyWeapon", "f", WEAPON_P228); + break; + case 6: + sendevent("BuyWeapon", "f", WEAPON_FIVESEVEN); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} + +/* Shotguns */ +void +BUYSHOTGUN(int n) +{ + switch (n) { + case 1: + sendevent("BuyWeapon", "f", WEAPON_M3); + break; + case 2: + sendevent("BuyWeapon", "f", WEAPON_XM1014); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} + +/* Rifles, Sniper */ +void +T_BUYRIFLE(int n) +{ + switch (n) { + case 1: + sendevent("BuyWeapon", "f", WEAPON_AK47); + break; + case 2: + sendevent("BuyWeapon", "f", WEAPON_SG552); + break; + case 5: + sendevent("BuyWeapon", "f", WEAPON_SCOUT); + break; + case 6: + sendevent("BuyWeapon", "f", WEAPON_AWP); + break; + case 7: + sendevent("BuyWeapon", "f", WEAPON_G3SG1); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} +void +CT_BUYRIFLE(int n) +{ + switch (n) { + case 3: + sendevent("BuyWeapon", "f", WEAPON_M4A1); + break; + case 4: + sendevent("BuyWeapon", "f", WEAPON_AUG); + break; + case 5: + sendevent("BuyWeapon", "f", WEAPON_SCOUT); + break; + case 6: + sendevent("BuyWeapon", "f", WEAPON_AWP); + break; + case 7: + sendevent("BuyWeapon", "f", WEAPON_G3SG1); + break; + case 8: + sendevent("BuyWeapon", "f", WEAPON_SG550); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} + +/* SMGs */ +void +T_BUYSUBMACHINEGUN(int n) +{ + switch (n) { + case 1: + sendevent("BuyWeapon", "f", WEAPON_MP5); + break; + case 3: + sendevent("BuyWeapon", "f", WEAPON_P90); + break; + case 4: + sendevent("BuyWeapon", "f", WEAPON_MAC10); + break; + case 5: + sendevent("BuyWeapon", "f", WEAPON_UMP45); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} +void +CT_BUYSUBMACHINEGUN(int n) +{ + switch (n) { + case 1: + sendevent("BuyWeapon", "f", WEAPON_MP5); + break; + case 2: + sendevent("BuyWeapon", "f", WEAPON_TMP); + break; + case 3: + sendevent("BuyWeapon", "f", WEAPON_P90); + break; + case 5: + sendevent("BuyWeapon", "f", WEAPON_UMP45); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} + +/* Big and heavy */ +void +BUYMACHINEGUN(int n) +{ + switch (n) { + case 1: + sendevent("BuyWeapon", "f", WEAPON_PARA); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} + +/* Radio */ +void +RADIOA(int n) +{ + switch (n) { + case 1: + sendevent("Radio", "f", RADIO_CT_COVERME); + break; + case 2: + sendevent("Radio", "f", RADIO_TAKEPOINT); + break; + case 3: + sendevent("Radio", "f", RADIO_POSITION); + break; + case 4: + sendevent("Radio", "f", RADIO_REGROUP); + break; + case 5: + sendevent("Radio", "f", RADIO_FOLLOWME); + break; + case 6: + sendevent("Radio", "f", RADIO_FIREASSIS); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} + +void +RADIOB(int n) +{ + switch (n) { + case 1: + sendevent("Radio", "f", RADIO_COM_GO); + break; + case 2: + sendevent("Radio", "f", RADIO_FALLBACK); + break; + case 3: + sendevent("Radio", "f", RADIO_STICKTOG); + break; + case 4: + sendevent("Radio", "f", RADIO_COM_GETINPOS); + break; + case 5: + sendevent("Radio", "f", RADIO_STORMFRONT); + break; + case 6: + sendevent("Radio", "f", RADIO_COM_REPORTIN); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} + +void +RADIOC(int n) +{ + switch (n) { + case 1: + sendevent("Radio", "f", RADIO_CT_AFFIRM); + break; + case 2: + sendevent("Radio", "f", RADIO_CT_ENEMYS); + break; + case 3: + sendevent("Radio", "f", RADIO_CT_BACKUP); + break; + case 4: + sendevent("Radio", "f", RADIO_CLEAR); + break; + case 5: + sendevent("Radio", "f", RADIO_CT_INPOS); + break; + case 6: + sendevent("Radio", "f", RADIO_COM_REPORTIN); + break; + case 7: + sendevent("Radio", "f", RADIO_BLOW); + break; + case 8: + sendevent("Radio", "f", RADIO_NEGATIVE); + break; + case 9: + sendevent("Radio", "f", RADIO_ENEMYDOWN); + break; + case 10: + Textmenu_Call(""); + break; + default: + return; + } + + Textmenu_Call(""); +} diff --git a/src/client/vgui_chooseteam.qc b/src/client/vgui_chooseteam.qc new file mode 100644 index 0000000..683d4f9 --- /dev/null +++ b/src/client/vgui_chooseteam.qc @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +static CUIWindow winChooseTeam; +static CUIWindow winCTTeam; +static CUIWindow winTTeam; + +void +T_Skin1(void) +{ + sendevent("GamePlayerSpawn", "f", 1); + winTTeam.Hide(); +} +void +T_Skin2(void) +{ + sendevent("GamePlayerSpawn", "f", 2); + winTTeam.Hide(); +} +void +T_Skin3(void) +{ + sendevent("GamePlayerSpawn", "f", 3); + winTTeam.Hide(); +} +void +T_Skin4(void) +{ + sendevent("GamePlayerSpawn", "f", 4); + winTTeam.Hide(); +} + +void +CT_Skin1(void) +{ + sendevent("GamePlayerSpawn", "f", 5); + winCTTeam.Hide(); +} +void +CT_Skin2(void) +{ + sendevent("GamePlayerSpawn", "f", 6); + winCTTeam.Hide(); +} +void +CT_Skin3(void) +{ + sendevent("GamePlayerSpawn", "f", 7); + winCTTeam.Hide(); +} +void +CT_Skin4(void) +{ + sendevent("GamePlayerSpawn", "f", 8); + winCTTeam.Hide(); +} +void +VGUI_GoSpectator(void) +{ + sendevent("GamePlayerSpawn", "f", 0); + winChooseTeam.Hide(); +} + +void +VGUI_ChooseTeam_CT(void) +{ + static int initialized; + static CUIButton btnSkin1; + static CUIButton btnSkin2; + static CUIButton btnSkin3; + static CUIButton btnSkin4; + + if (!initialized) { + initialized = TRUE; + winCTTeam = spawn(CUIWindow); + winCTTeam.SetTitle("Choose Skin"); + winCTTeam.SetSize([420,320]); + + btnSkin1 = spawn(CUIButton); + btnSkin1.SetTitle("Skin 1"); + btnSkin1.SetPos([8,132]); + btnSkin1.SetFunc(CT_Skin1); + + btnSkin2 = spawn(CUIButton); + btnSkin2.SetTitle("Skin 2"); + btnSkin2.SetPos([8,132+30]); + btnSkin2.SetFunc(CT_Skin2); + + btnSkin3 = spawn(CUIButton); + btnSkin3.SetTitle("Skin 3"); + btnSkin3.SetPos([8,132+30+30]); + btnSkin3.SetFunc(CT_Skin3); + + btnSkin4 = spawn(CUIButton); + btnSkin4.SetTitle("Skin 4"); + btnSkin4.SetPos([8,132+30+30+30]); + btnSkin4.SetFunc(CT_Skin4); + + g_uiDesktop.Add(winCTTeam); + winCTTeam.Add(btnSkin1); + winCTTeam.Add(btnSkin2); + winCTTeam.Add(btnSkin3); + winCTTeam.Add(btnSkin4); + } + + winChooseTeam.Hide(); + winCTTeam.Show(); + winCTTeam.SetPos((video_res / 2) - (winCTTeam.GetSize() / 2)); +} + +void +VGUI_ChooseTeam_T(void) +{ + static int initialized; + static CUIButton btnSkin1; + static CUIButton btnSkin2; + static CUIButton btnSkin3; + static CUIButton btnSkin4; + + if (!initialized) { + initialized = TRUE; + winTTeam = spawn(CUIWindow); + winTTeam.SetTitle("Choose Skin"); + winTTeam.SetSize([420,320]); + + btnSkin1 = spawn(CUIButton); + btnSkin1.SetTitle("Skin 1"); + btnSkin1.SetPos([8,132]); + btnSkin1.SetFunc(T_Skin1); + + btnSkin2 = spawn(CUIButton); + btnSkin2.SetTitle("Skin 2"); + btnSkin2.SetPos([8,132+30]); + btnSkin2.SetFunc(T_Skin2); + + btnSkin3 = spawn(CUIButton); + btnSkin3.SetTitle("Skin 3"); + btnSkin3.SetPos([8,132+30+30]); + btnSkin3.SetFunc(T_Skin3); + + btnSkin4 = spawn(CUIButton); + btnSkin4.SetTitle("Skin 4"); + btnSkin4.SetPos([8,132+30+30+30]); + btnSkin4.SetFunc(T_Skin4); + + g_uiDesktop.Add(winTTeam); + winTTeam.Add(btnSkin1); + winTTeam.Add(btnSkin2); + winTTeam.Add(btnSkin3); + winTTeam.Add(btnSkin4); + } + + winChooseTeam.Hide(); + winTTeam.Show(); + winTTeam.SetPos((video_res / 2) - (winTTeam.GetSize() / 2)); +} + +void +VGUI_ChooseTeam(void) +{ + static int initialized; + static CUIButton btnGoCT; + static CUIButton btnGoT; + static CUIButton btnGoSpectator; + + if (!initialized) { + initialized = TRUE; + winChooseTeam = spawn(CUIWindow); + winChooseTeam.SetTitle("Choose Team"); + winChooseTeam.SetSize('420 320'); + + btnGoCT = spawn(CUIButton); + btnGoCT.SetTitle("Counter-Terrorists"); + btnGoCT.SetPos('8 132'); + btnGoCT.SetFunc(VGUI_ChooseTeam_CT); + + btnGoT = spawn(CUIButton); + btnGoT.SetTitle("Terrorists"); + btnGoT.SetPos('8 162'); + btnGoT.SetFunc(VGUI_ChooseTeam_T); + + btnGoSpectator = spawn(CUIButton); + btnGoSpectator.SetTitle("Spectator"); + btnGoSpectator.SetPos('8 192'); + btnGoSpectator.SetFunc(VGUI_GoSpectator); + + g_uiDesktop.Add(winChooseTeam); + winChooseTeam.Add(btnGoCT); + winChooseTeam.Add(btnGoT); + winChooseTeam.Add(btnGoSpectator); + } + + winChooseTeam.Show(); + winChooseTeam.SetPos((video_res / 2) - (winChooseTeam.GetSize() / 2)); +} diff --git a/src/progs.src b/src/progs.src new file mode 100755 index 0000000..2c2a868 --- /dev/null +++ b/src/progs.src @@ -0,0 +1,2 @@ +#pragma sourcefile client/progs.src +#pragma sourcefile server/progs.src diff --git a/src/server/Makefile b/src/server/Makefile new file mode 100644 index 0000000..627019a --- /dev/null +++ b/src/server/Makefile @@ -0,0 +1,4 @@ +CC=fteqcc + +all: + $(CC) progs.src diff --git a/src/server/ammo.qc b/src/server/ammo.qc new file mode 100644 index 0000000..0e74cfc --- /dev/null +++ b/src/server/ammo.qc @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/* Ammo information courtesy of https://wiki.alliedmods.net/CS_weapons_information */ + +enum +{ + CALIBER_NONE, + CALIBER_50AE, + CALIBER_762MM, + CALIBER_556MM, + CALIBER_556MMBOX, + CALIBER_338MAG, + CALIBER_9MM, + CALIBER_BUCKSHOT, + CALIBER_45ACP, + CALIBER_357SIG, + CALIBER_57MM +}; + +typedef struct +{ + int a_size; + int a_max; + int price; +} ammoinfo_t; + +ammoinfo_t cs_ammoinfo[11] = { + /* CALIBER_NONE */ + { + .a_size = 0, + .a_max = 0, + .price = 0 + }, + /* CALIBER_50AE */ + { + .a_size = 7, + .a_max = 35, + .price = 40 + }, + /* CALIBER_762MM */ + { + .a_size = 30, + .a_max = 90, + .price = 80 + }, + /* CALIBER_556MM */ + { + .a_size = 30, + .a_max = 90, + .price = 60 + }, + /* CALIBER_556MMBOX */ + { + .a_size = 30, + .a_max = 200, + .price = 60 + }, + /* CALIBER_338MAG */ + { + .a_size = 10, + .a_max = 30, + .price = 125 + }, + /* CALIBER_9MM */ + { + .a_size = 30, + .a_max = 150, + .price = 20 + }, + /* CALIBER_BUCKSHOT */ + { + .a_size = 8, + .a_max = 32, + .price = 65 + }, + /* CALIBER_45ACP */ + { + .a_size = 12, + .a_max = 100, + .price = 25 + }, + /* CALIBER_357SIG */ + { + .a_size = 13, + .a_max = 52, + .price = 50 + }, + /* CALIBER_57MM */ + { + .a_size = 50, + .a_max = 100, + .price = 50 + } +}; + +int +Ammo_BuyCaliber(player pl, int cal, int free) +{ + int *ptr_ammo = __NULL__; + int rv = 0; + + while (pl.money - cs_ammoinfo[cal].price > 0) { + switch (cal) { + case CALIBER_50AE: + ptr_ammo = &pl.ammo_50ae; + break; + case CALIBER_762MM: + ptr_ammo = &pl.ammo_762mm; + break; + case CALIBER_556MM: + ptr_ammo = &pl.ammo_556mm; + break; + case CALIBER_556MMBOX: + ptr_ammo = &pl.ammo_556mmbox; + break; + case CALIBER_338MAG: + ptr_ammo = &pl.ammo_338mag; + break; + case CALIBER_9MM: + ptr_ammo = &pl.ammo_9mm; + break; + case CALIBER_BUCKSHOT: + ptr_ammo = &pl.ammo_buckshot; + break; + case CALIBER_45ACP: + ptr_ammo = &pl.ammo_45acp; + break; + case CALIBER_357SIG: + ptr_ammo = &pl.ammo_357sig; + break; + case CALIBER_57MM: + ptr_ammo = &pl.ammo_57mm; + break; + default: + error("Ammo_BuyCaliber: Impossible caliber definition."); + } + + if (*ptr_ammo >= cs_ammoinfo[cal].a_max) { + break; + } + + *ptr_ammo += cs_ammoinfo[cal].a_size; + + /* clamp */ + if (*ptr_ammo >= cs_ammoinfo[cal].a_max) { + *ptr_ammo = cs_ammoinfo[cal].a_max; + } + + if (!free) + Money_AddMoney(pl, -cs_ammoinfo[cal].price); + + rv = 1; + } + + return rv; +} + +/* We want to loop through all the possible weapons in case the server + * enabled the ability to pick up more than one primary/secondary weapon */ +void +CSEv_AmmoBuySecondary(void) +{ + int cal = 0; + int ps = 0; + player pl = (player)self; + CSGameRules rules = (CSGameRules)g_grMode; + + if (rules.BuyingPossible(pl) == FALSE) { + return; + } + + for (int i = 1; i < g_weapons.length; i++) { + if ((pl.g_items & g_weapons[i].id) && (g_weapons[i].slot == 1)) { + switch (i) { + case WEAPON_USP45: + cal = CALIBER_45ACP; + break; + case WEAPON_GLOCK18: + cal = CALIBER_9MM; + break; + case WEAPON_DEAGLE: + cal = CALIBER_50AE; + break; + case WEAPON_P228: + cal = CALIBER_357SIG; + break; + case WEAPON_ELITES: + cal = CALIBER_9MM; + break; + case WEAPON_FIVESEVEN: + cal = CALIBER_57MM; + break; + } + + if (Ammo_BuyCaliber(pl, cal, FALSE) == 1) { + ps = 1; + } + } + } + + if (ps) { + Sound_Play(pl, CHAN_ITEM, "buy.ammo"); + } + Weapons_RefreshAmmo(pl); +} + +void +CSEv_AmmoBuyPrimary(void) +{ + int ps = 0; + int cal = 0; + player pl = (player)self; + CSGameRules rules = (CSGameRules)g_grMode; + + if (rules.BuyingPossible(pl) == FALSE) { + return; + } + + for (int i = 1; i < g_weapons.length; i++) { + if ((pl.g_items & g_weapons[i].id) && (g_weapons[i].slot == 0)) { + switch (i) { + case WEAPON_M3: + cal = CALIBER_BUCKSHOT; + break; + case WEAPON_XM1014: + cal = CALIBER_BUCKSHOT; + break; + case WEAPON_MP5: + cal = CALIBER_9MM; + break; + case WEAPON_P90: + cal = CALIBER_57MM; + break; + case WEAPON_UMP45: + cal = CALIBER_45ACP; + break; + case WEAPON_MAC10: + cal = CALIBER_45ACP; + break; + case WEAPON_TMP: + cal = CALIBER_9MM; + break; + case WEAPON_AK47: + cal = CALIBER_762MM; + break; + case WEAPON_SG552: + cal = CALIBER_556MM; + break; + case WEAPON_M4A1: + cal = CALIBER_556MM; + break; + case WEAPON_AUG: + cal = CALIBER_762MM; + break; + case WEAPON_SCOUT: + cal = CALIBER_762MM; + break; + case WEAPON_AWP: + cal = CALIBER_338MAG; + break; + case WEAPON_G3SG1: + cal = CALIBER_762MM; + break; + case WEAPON_SG550: + cal = CALIBER_556MM; + break; + case WEAPON_PARA: + cal = CALIBER_556MMBOX; + break; + } + + if (Ammo_BuyCaliber(pl, cal, FALSE) == 1) { + ps = 1; + } + } + } + + if (ps) { + Sound_Play(pl, CHAN_ITEM, "buy.ammo"); + } + Weapons_RefreshAmmo(pl); +} + +void +Ammo_AutoFill(player pl) +{ + if (autocvar_fcs_fillweapons == FALSE) { + return; + } + + /* TODO: */ +} + +void +Ammo_Clear(void) +{ + +} diff --git a/src/server/armoury_entity.qc b/src/server/armoury_entity.qc new file mode 100644 index 0000000..bf39393 --- /dev/null +++ b/src/server/armoury_entity.qc @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED armoury_entity (0 0 0.8) (-16 -16 0) (16 16 16) +"targetname" Name +"target" Target when triggered. +"killtarget" Target to kill when triggered. +"item" Which weapon/equipment this item will contain +"count" How many of said item will players be able to pick up from this + +COUNTER-STRIKE (1999) ENTITY + +Items in the armoury. + +An item oriented entity that contains one or more weapon/equipment item +for players to pick up. It's limited to early Counter-Strike weapons, as +it was never updated in newer versions to add support for newly added ones. + +List of available items: + 0 = H&K MP5-Navy + 1 = Steyr Tactical (TMP) + 2 = FN P90 + 3 = Ingram MAC-10 + 4 = AK-47 + 5 = Sig SG-552 Commando + 6 = Colt M4A1 Carbine + 7 = Steyr AUG + 8 = Steyr Scout + 9 = H&K G3/SG-1 + 10 = AI Arctic Warfare/Magnum + 11 = Benneli M3 Super90 + 12 = Benneli XM1014 + 13 = FN M249 Para + 14 = Flashbang Grenade + 15 = HE Grenade + 16 = Kevlar + 17 = Kevlar + Helmet + 18 = Smoke Grenade +*/ + +var int autocvar_fcs_nopickups = FALSE; + +int g_cstrike_armouryitems[19] = { + WEAPON_MP5, + WEAPON_TMP, + WEAPON_P90, + WEAPON_MAC10, + WEAPON_AK47, + WEAPON_SG552, + WEAPON_M4A1, + WEAPON_AUG, + WEAPON_SCOUT, + WEAPON_G3SG1, + WEAPON_AWP, + WEAPON_M3, + WEAPON_XM1014, + WEAPON_PARA, + WEAPON_FLASHBANG, + WEAPON_HEGRENADE, + 0,/*EQUIPMENT_KEVLAR,*/ + 0,/*EQUIPMENT_HELMET,*/ + WEAPON_SMOKEGRENADE +}; + +string sArmouryModels[19] = { + "models/w_mp5.mdl", + "models/w_tmp.mdl", + "models/w_p90.mdl", + "models/w_mac10.mdl", + "models/w_ak47.mdl", + "models/w_sg552.mdl", + "models/w_m4a1.mdl", + "models/w_aug.mdl", + "models/w_scout.mdl", + "models/w_g3sg1.mdl", + "models/w_awp.mdl", + "models/w_m3.mdl", + "models/w_xm1014.mdl", + "models/w_m249.mdl", + "models/w_flashbang.mdl", + "models/w_hegrenade.mdl", + "models/w_kevlar.mdl", + "models/w_assault.mdl", + "models/w_smokegrenade.mdl" +}; + +class armoury_entity:CBaseEntity +{ + int m_iCount; + int m_iLeft; + int m_iItem; + + void(void) armoury_entity; + virtual void(void) touch; + virtual void(void) Respawn; + virtual void(string, string) SpawnKey; +}; + +void +armoury_entity::touch(void) +{ + if (other.classname != "player") { + return; + } + + /* temp */ + if (m_iItem == 17 || m_iItem == 16) + return; + + if (Weapons_AddItem((player)other, m_iItem, -1) == FALSE) { + return; + } + + Logging_Pickup(other, this, __NULL__); + sound(other, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM); + + m_iLeft--; + if (m_iLeft <= 0) { + Hide(); + } +} + +void +armoury_entity::Respawn(void) +{ + SetModel(m_oldModel); + setsize(this, [-16,-16,0], [16,16,16]); + solid = SOLID_TRIGGER; + m_iLeft = m_iCount; + droptofloor(); +} + +void +armoury_entity::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "count": + m_iCount = stoi(strValue); + break; + case "item": + int id = stoi(strValue); + + if (id < 0 || id >= 19) { + print(sprintf("^1armoury_entity with invalid item %i. ignoring\n", m_iItem)); + remove(this); + return; + } + + m_iItem = g_cstrike_armouryitems[id]; + model = sArmouryModels[id]; + break; + default: + CBaseEntity::SpawnKey(strKey, strValue); + break; + } +} + +void +armoury_entity::armoury_entity(void) +{ + if (autocvar_fcs_nopickups == TRUE) { + remove(this); + return; + } + + m_iCount = 1; + CBaseEntity::CBaseEntity(); +} diff --git a/src/server/buy.qc b/src/server/buy.qc new file mode 100644 index 0000000..c374770 --- /dev/null +++ b/src/server/buy.qc @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/* values courtesy of https://wiki.alliedmods.net/Cs_weapons_information */ +int g_cstrikeWeaponPrice[] = +{ + 0, /* WEAPON_NONE */ + 1700, /* WEAPON_M3 */ + 3000, /* WEAPON_XM1014 */ + 1500, /* WEAPON_MP5 */ + 2350, /* WEAPON_P90 */ + 1700, /* WEAPON_UMP45 */ + 1400, /* WEAPON_MAC10 */ + 1250, /* WEAPON_TMP */ + 2500, /* WEAPON_AK47 */ + 3500, /* WEAPON_SG552 */ + 3100, /* WEAPON_M4A1 */ + 3500, /* WEAPON_AUG */ + 2750, /* WEAPON_SCOUT */ + 4750, /* WEAPON_AWP */ + 5000, /* WEAPON_G3SG1 */ + 4200, /* WEAPON_SG550 */ + 5750, /* WEAPON_PARA */ + 500, /* WEAPON_USP45 */ + 400, /* WEAPON_GLOCK18 */ + 650, /* WEAPON_DEAGLE */ + 600, /* WEAPON_P228 */ + 800, /* WEAPON_ELITES */ + 750, /* WEAPON_FIVESEVEN */ + 0, /* WEAPON_KNIFE */ + 300, /* WEAPON_HEGRENADE */ + 200, /* WEAPON_FLASHBANG */ + 300, /* WEAPON_SMOKEGRENADE */ + 0 /* WEAPON_C4BOMB */ +}; + +void +CSEv_BuyWeapon_f(float fWeapon) +{ + CSGameRules rules = (CSGameRules)g_grMode; + + int iWeapon; + player pl = (player)self; + iWeapon = (int)fWeapon; + + if (rules.BuyingPossible(pl) == FALSE) { + return; + } + + if (pl.team == TEAM_T) { + if (iWeapon == WEAPON_M4A1) { return; } + if (iWeapon == WEAPON_AUG) { return; } + if (iWeapon == WEAPON_SG550) { return; } + if (iWeapon == WEAPON_FIVESEVEN) { return; } + if (iWeapon == WEAPON_TMP) { return; } + } else if (pl.team == TEAM_CT) { + if (iWeapon == WEAPON_AK47) { return; } + if (iWeapon == WEAPON_SG552) { return; } + if (iWeapon == WEAPON_G3SG1) { return; } + if (iWeapon == WEAPON_ELITES) { return; } + if (iWeapon == WEAPON_MAC10) { return; } + } + + if (Weapons_IsPresent(pl, iWeapon)) + return; + + if ((pl.money - g_cstrikeWeaponPrice[iWeapon]) >= 0) { + /* let's check if we've got a limit */ + int maxit; + maxit = rules.MaxItemPerSlot(g_weapons[iWeapon].slot); + if (maxit > 0) { + int wantslot = g_weapons[iWeapon].slot; + int c = 0; + for (int i = 0; i < g_weapons.length; i++) { + if (pl.g_items & g_weapons[i].id && g_weapons[i].slot == wantslot) { + c++; + + /* we're over the slot limit. */ + if (c >= maxit) { + pl.activeweapon = i; + Weapon_DropCurrentWeapon(pl); + } + } + } + } + + Weapons_AddItem(pl, iWeapon, -1); + Money_AddMoney(pl, -g_cstrikeWeaponPrice[iWeapon]); + Sound_Play(pl, CHAN_ITEM, "buy.weapon"); + } else { + //centerprint(pl, "You have insufficient funds!"); + } +} + +int g_cstrikeUtilPrice[] = +{ + 650, /* Kevlar Vest */ + 1000, /* Kevlar Vest & Helmet */ + 200, /* Flashbang */ + 300, /* HE Grenade */ + 300, /* Smoke Grenade */ + 200, /* Defuse Kit */ + 1250 /* NightVision Goggles */ +}; + +void +CSEv_BuyEquipment_f(float fUtil) +{ + CSGameRules rules = (CSGameRules)g_grMode; + + int iUtil; + player pl = (player)self; + iUtil = (int)fUtil; + + if (rules.BuyingPossible(pl) == FALSE) { + return; + } + + if (pl.team == TEAM_T) { + if (iUtil == 5) { return; } + } + + if ((pl.money - g_cstrikeUtilPrice[iUtil]) >= 0) { + switch (iUtil) { + case 0: + if (pl.armor >= 100) + return; + + pl.armor = 100; + Sound_Play(pl, CHAN_ITEM, "buy.kevlar"); + break; + case 1: + if (pl.g_items & ITEM_HELMET && pl.armor >= 0) + return; + + pl.armor = 100; + pl.g_items |= ITEM_HELMET; + Sound_Play(pl, CHAN_ITEM, "buy.kevlar"); + break; + case 2: + if (Weapons_IsPresent(pl, WEAPON_FLASHBANG)) { + if (pl.ammo_fbgrenade >= AMMO_MAX_FLASHBANG) + return; + else + pl.ammo_fbgrenade++; + } else + Weapons_AddItem(pl, WEAPON_FLASHBANG, -1); + + Sound_Play(pl, CHAN_ITEM, "buy.weapon"); + break; + case 3: + if (Weapons_IsPresent(pl, WEAPON_HEGRENADE)) { + if (pl.ammo_hegrenade >= AMMO_MAX_HENADE) + return; + else + pl.ammo_hegrenade++; + } else + Weapons_AddItem(pl, WEAPON_HEGRENADE, -1); + + Sound_Play(pl, CHAN_ITEM, "buy.weapon"); + break; + case 4: + if (Weapons_IsPresent(pl, WEAPON_SMOKEGRENADE)) { + if (pl.ammo_smokegrenade >= AMMO_MAX_SMOKE) + return; + else + pl.ammo_smokegrenade++; + } else + Weapons_AddItem(pl, WEAPON_SMOKEGRENADE, -1); + + Sound_Play(pl, CHAN_ITEM, "buy.weapon"); + break; + case 5: + if (pl.g_items & ITEM_DEFUSAL) + return; + + pl.g_items |= ITEM_DEFUSAL; + Sound_Play(pl, CHAN_ITEM, "buy.weapon"); + break; + case 6: + if (pl.g_items & ITEM_NIGHTVISION) + return; + + pl.g_items |= ITEM_NIGHTVISION; + Sound_Play(pl, CHAN_ITEM, "buy.weapon"); + break; + } + Money_AddMoney(pl, -g_cstrikeUtilPrice[iUtil]); + } else { + //centerprint(pl, "You have insufficient funds!"); + } +} diff --git a/src/server/client.qc b/src/server/client.qc new file mode 100644 index 0000000..8343ae6 --- /dev/null +++ b/src/server/client.qc @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 +Game_RunClientCommand(void) +{ + player pl = (player)self; + + pl.gflags &= ~GF_BUYZONE; + pl.gflags &= ~GF_RESCUEZONE; + pl.gflags &= ~GF_BOMBZONE; + + Footsteps_Update(); + PMove_Run(); +} + +void +SV_SendChat(entity sender, string msg, entity eEnt, float fType) +{ + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, fType == 0 ? EV_CHAT:EV_CHAT_TEAM); + WriteByte(MSG_MULTICAST, num_for_edict(sender) - 1); + WriteByte(MSG_MULTICAST, sender.team); + WriteString(MSG_MULTICAST, msg); + if (eEnt) { + msg_entity = eEnt; + multicast([0,0,0], MULTICAST_ONE); + } else { + multicast([0,0,0], MULTICAST_ALL); + } + + localcmd(sprintf("echo [SERVER] %s: %s\n", sender.netname, msg)); +} + +void +Game_ParseClientCommand(string cmd) +{ + tokenize(cmd); + + if (argv(1) == "timeleft") { + string msg; + string timestring; + float timeleft; + timeleft = cvar("mp_timelimit") - (time / 60); + timestring = Vox_TimeToString(timeleft); + msg = sprintf("we have %s minutes remaining", timestring); + Vox_Singlecast(self, msg); + return; + } + + if (argv(0) == "say") { + SV_SendChat(self, argv(1), world, 0); + return; + } else if (argv(0) == "say_team") { + entity a; + for (a = world; (a = find(a, ::classname, "player"));) { + if (a.team == self.team) { + SV_SendChat(self, argv(1), a, 1); + } + } + return; + } + + clientcommand(self, cmd); +} + +void +Game_SetNewParms(void) +{ + +} diff --git a/src/server/defs.h b/src/server/defs.h new file mode 100644 index 0000000..442a4dc --- /dev/null +++ b/src/server/defs.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +#include "gamerules.h" +#include "money.h" +#include "radio.h" +#include "../../../valve/src/server/items.h" + +var int g_cstrike_buying = 0; +var float g_cstrike_bombradius = 500; + +var int g_cs_vipzones; +var int g_cs_escapezones; +var int g_cs_bombzones; + +var int g_cs_bombplanted; +var int g_cs_roundswon_ct; +var int g_cs_roundswon_t; +var int g_cs_roundsplayed; +var int g_cs_alive_t; +var int g_cs_alive_ct; +var int g_cs_hostagesrescued; +var int g_cs_hostagestotal; +var int g_cs_roundslost_ct; +var int g_cs_roundslost_t; +var int g_cs_winstreak_ct; +var int g_cs_winstreak_t; +var int g_cs_bonus_ct; +var int g_cs_bonus_t; +var int g_cs_gamestate; +var float g_cs_gametime; + +/* Counter-Strike's own cvars */ +var int autocvar_mp_winlimit = 0; +var int autocvar_mp_halftime = 0; +var int autocvar_mp_startmoney = 800; +var float autocvar_mp_buytime = 90; +var float autocvar_mp_freezetime = 6; +var float autocvar_mp_c4timer = 45; +var float autocvar_mp_roundtime = 5; +var float autocvar_mp_timelimit = 60; +var string autocvar_motdfile = "motd.txt"; +var int autocvar_mp_friendlyfire = FALSE; + +/* new, FreeCS exclusive variables */ +var int autocvar_fcs_voxannounce = FALSE; +var int autocvar_fcs_knifeonly = FALSE; /* Disallows buying and spawning with weps */ +var int autocvar_fcs_swapteams = FALSE; /* Swaps spawnpoints */ +var int autocvar_fcs_nopickups = FALSE; /* Disable weapon items */ +var int autocvar_fcs_reward_kill = 300; +var int autocvar_fcs_penalty_pain = -150; +var int autocvar_fcs_penalty_kill = -1500; +var int autocvar_fcs_maxmoney = 16000; +var int autocvar_fcs_fillweapons = FALSE; /* This will automatically get ammo for the weapon you buy */ +var int autocvar_fcs_fix_bombtimer = TRUE; /* If true, the bomb-timer will dictate the round-end */ +var int autocvar_fcs_bombaltthrow = TRUE; /* Randomize the bomb-throw every time ever so slightly */ + +enum +{ + GAME_INACTIVE, + GAME_COMMENCING, + GAME_FREEZE, + GAME_ACTIVE, + GAME_END, + GAME_OVER +}; diff --git a/src/server/func_bomb_target.qc b/src/server/func_bomb_target.qc new file mode 100644 index 0000000..278ddf7 --- /dev/null +++ b/src/server/func_bomb_target.qc @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED func_bomb_target (0 .5 .8) ? +"targetname" Name +"target" Target when bomb blows up. +"killtarget" Target to kill when triggered. + +COUNTER-STRIKE (1999) ENTITY + +Bomb target zone. + +Used in the bomb defusal mode (de_* maps). +Once the bomb explodes inside this volume, it'll trigger its targets. +*/ + +class func_bomb_target:CBaseTrigger +{ + void(void) func_bomb_target; + + virtual void(void) Respawn; + virtual void(void) touch; +}; + +void +func_bomb_target::touch(void) +{ + player pl = (player)other; + if (!(other.flags & FL_CLIENT)) { + return; + } + + if (pl.team != TEAM_T) { + return; + } + + pl.gflags |= GF_BOMBZONE; +} + +void +func_bomb_target::Respawn(void) +{ + InitBrushTrigger(); +} + +void +func_bomb_target::func_bomb_target(void) +{ + g_cs_bombzones++; +} diff --git a/src/server/func_buyzone.qc b/src/server/func_buyzone.qc new file mode 100644 index 0000000..17b6196 --- /dev/null +++ b/src/server/func_buyzone.qc @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED func_buyzone (0 .5 .8) ? +"targetname" Name +"target" Target when triggered. +"killtarget" Target to kill when triggered. +"team" Limits the buyzone to be used by set team. + +COUNTER-STRIKE (1999) ENTITY + +Buy zone. + +The buyzone is a brush volume that upon creation forces players of set team +to buy weapons in its designated area. +If this entity is not present, the game will automatically spawn buyzones +around each player spawn, unless prevented using a setting inside the +info_map_parameters entity. + +Info about automatically generated buyzones: +If no func_buyzone exists, the game will create one buyzone volume with a total +width of 256 units (radius thus being 128 units) on every player spawn point. + +Choices for 'team' include: + 0 = All teams + 1 = Terrorist + 2 = Counter-Terrorist +*/ + +class func_buyzone:CBaseTrigger +{ + void(void) func_buyzone; + + virtual void(void) touch; + virtual void(void) Respawn; +}; + +void +func_buyzone::touch(void) +{ + player pl = (player)other; + if (!(other.flags & FL_CLIENT)) + return; + + if (team == 0 || team == pl.team) + pl.gflags |= GF_BUYZONE; +} + +void +func_buyzone::Respawn(void) +{ + InitBrushTrigger(); +} + +void +func_buyzone::func_buyzone(void) +{ + CBaseTrigger::CBaseTrigger(); + InitBrushTrigger(); +} diff --git a/src/server/func_escapezone.qc b/src/server/func_escapezone.qc new file mode 100644 index 0000000..53a7d92 --- /dev/null +++ b/src/server/func_escapezone.qc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED func_escapezone (0 .5 .8) ? +"targetname" Name +"target" Target when triggered. +"killtarget" Target to kill when triggered. + +COUNTER-STRIKE (1999) ENTITY + +Terrorist escape zone. + +Used in the Escape mode (es_* maps). +*/ + +class func_escapezone:CBaseTrigger +{ + virtual void(void) Respawn; +}; + +void +func_escapezone::Respawn(void) +{ + InitBrushTrigger(); +} diff --git a/src/server/func_hostage_rescue.qc b/src/server/func_hostage_rescue.qc new file mode 100644 index 0000000..fce9237 --- /dev/null +++ b/src/server/func_hostage_rescue.qc @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED func_hostage_rescue (0 .5 .8) ? +"targetname" Name +"target" Target when triggered. +"killtarget" Target to kill when triggered. + +COUNTER-STRIKE (1999) ENTITY + +Hostage rescue zone. + +Used in the Hostage Rescue mode (cs_* maps). +If neither a func_hostage_rescue or a info_hostage_rescue is placed, +zones will be placed in Counter-Terrorist player spawn nodes automatically. +*/ + +class func_hostage_rescue:CBaseTrigger +{ + void(void) func_hostage_rescue; + + virtual void(void) touch; + virtual void(void) Respawn; +}; + +void +func_hostage_rescue::touch(void) +{ + if (other.flags & FL_CLIENT) { + player pl = (player)other; + pl.gflags |= GF_RESCUEZONE; + return; + } + + if (other.classname != "hostage_entity") { + return; + } + + CBaseNPC hosty = (CBaseNPC)other; + + if (hosty.solid == SOLID_NOT) { + return; + } + + if (!((player)hosty.m_eFollowing)) + return; + + Radio_BroadcastMessage(RADIO_RESCUED); + g_cs_hostagesrescued++; + + Money_AddMoney((player)hosty.m_eFollowing, 1000); + + /* In Hostage Rescue, all Counter-Terrorists receive an $850 + * bonus for every hostage that was rescued, even if they lose the round. */ + Money_QueTeamReward(TEAM_CT, 850); + + CBaseEntity targa = (CBaseEntity)other; + targa.Hide(); +} + +void +func_hostage_rescue::Respawn(void) +{ + InitBrushTrigger(); +} + +void +func_hostage_rescue::func_hostage_rescue(void) +{ + CBaseTrigger::CBaseTrigger(); + InitBrushTrigger(); +} diff --git a/src/server/func_vip_safetyzone.qc b/src/server/func_vip_safetyzone.qc new file mode 100644 index 0000000..a50b644 --- /dev/null +++ b/src/server/func_vip_safetyzone.qc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED func_vip_safetyzone (0 .5 .8) ? +"targetname" Name +"target" Target when triggered. +"killtarget" Target to kill when triggered. + +COUNTER-STRIKE (1999) ENTITY + +VIP safety zone. + +Used in the assassination mode (as_* maps). +*/ + +class func_vip_safetyzone:CBaseTrigger +{ + virtual void(void) Respawn; +}; + +void +func_vip_safetyzone::Respawn(void) +{ + InitBrushTrigger(); +} diff --git a/src/server/game_money.qc b/src/server/game_money.qc new file mode 100644 index 0000000..4a0a695 --- /dev/null +++ b/src/server/game_money.qc @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * 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 +Money_AddMoney(base_player pp, int iMoneyValue) +{ + player pl = (player)pp; + dprint(sprintf("^2Money_AddMoney^7: giving %s $%i\n", pl.netname, iMoneyValue)); + pl.money += (float)iMoneyValue; + + if (pl.money > autocvar_fcs_maxmoney) { + pl.money = autocvar_fcs_maxmoney; + } + + /* Because people do tend to kill hostages... */ + if (pl.money < 0) { + pl.money = 0; + } +} + +void +Money_QueTeamReward(int t, int iMoneyValue) +{ + if (t == TEAM_T) { + g_cs_moneyreward_t += iMoneyValue; + } else { + g_cs_moneyreward_ct += iMoneyValue; + } +} + +void +Money_GiveTeamReward(base_player pl) +{ + if (pl.team == TEAM_T) { + Money_AddMoney(pl, g_cs_moneyreward_t); + } else { + Money_AddMoney(pl, g_cs_moneyreward_ct); + } +} + +void +Money_ResetTeamReward(void) +{ + g_cs_moneyreward_t = 0; + g_cs_moneyreward_ct = 0; +} + +int +Money_GetLosses(int team) +{ + if (team == TEAM_T) { + return g_cs_roundslost_t; + } else { + return g_cs_roundslost_ct; + } +} + +int +Money_HasBonus(int team) +{ + if (team == TEAM_T) { + return g_cs_bonus_t; + } else { + return g_cs_bonus_ct; + } +} + +void +Money_HandleRoundReward(int winner) +{ + int loser = -1; + + if (winner == TEAM_CT) { + g_cs_winstreak_ct++; + g_cs_winstreak_t = 0; + g_cs_roundslost_t++; + g_cs_roundslost_ct = 0; + loser = TEAM_T; + + if (g_cs_winstreak_ct >= 2) { + g_cs_bonus_ct = TRUE; + } + } else { + g_cs_winstreak_t++; + g_cs_winstreak_ct = 0; + g_cs_roundslost_ct++; + g_cs_roundslost_t = 0; + loser = TEAM_CT; + + if (g_cs_winstreak_t >= 2) { + g_cs_bonus_t = TRUE; + } + } + + /* After the condition of a team winning two consecutive rounds is + * satisfied then the loss bonus money changes to above where their + * first loss means they receive $1500 and not $1400. */ + if (Money_HasBonus(loser)) { + switch (Money_GetLosses(loser)) { + case 1: + Money_QueTeamReward(loser, 1500); + break; + case 2: + Money_QueTeamReward(loser, 2000); + break; + case 3: + Money_QueTeamReward(loser, 2500); + break; + default: + Money_QueTeamReward(loser, 3000); + break; + } + } else { + switch (Money_GetLosses(loser)) { + case 1: + Money_QueTeamReward(loser, 1400); + break; + case 2: + Money_QueTeamReward(loser, 1900); + break; + case 3: + Money_QueTeamReward(loser, 2400); + break; + case 4: + Money_QueTeamReward(loser, 2900); + break; + default: + Money_QueTeamReward(loser, 3400); + break; + } + } +} + +void +Money_ResetRoundReward(void) +{ + g_cs_roundslost_ct = + g_cs_roundslost_t = + g_cs_winstreak_ct = + g_cs_winstreak_t = + g_cs_bonus_ct = + g_cs_bonus_t = 0; +} diff --git a/src/server/game_rules.qc b/src/server/game_rules.qc new file mode 100755 index 0000000..d5ce10e --- /dev/null +++ b/src/server/game_rules.qc @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * 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. + */ + +/* Edit this for a custom gun-game order */ +int gg_order[] = { + WEAPON_KNIFE, + WEAPON_GLOCK18, + WEAPON_USP45, + WEAPON_P228, + WEAPON_FIVESEVEN, + WEAPON_ELITES, + WEAPON_DEAGLE, + WEAPON_M3, + WEAPON_XM1014, + WEAPON_TMP, + WEAPON_MAC10, + WEAPON_MP5, + WEAPON_UMP45, + WEAPON_P90, + WEAPON_AK47, + WEAPON_SCOUT, + WEAPON_M4A1, + WEAPON_SG552, + WEAPON_AUG, + WEAPON_G3SG1, + WEAPON_SG550, + WEAPON_AWP, + WEAPON_PARA +}; + + diff --git a/src/server/gamerules.h b/src/server/gamerules.h new file mode 100644 index 0000000..deebb81 --- /dev/null +++ b/src/server/gamerules.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 CSGameRules:CGameRules +{ + virtual void(base_player) PlayerConnect; + virtual void(base_player) PlayerDisconnect; + virtual void(base_player) PlayerKill; + virtual void(base_player) PlayerPostFrame; + virtual void(base_player) PlayerDeath; + virtual void(base_player) PlayerPain; + + /* level transitions */ + virtual void(base_player) LevelChangeParms; + virtual void(base_player) LevelDecodeParms; + virtual void(void) LevelNewParms; + + virtual int(base_player) BuyingPossible; +}; + +class CSSingleplayerRules:CSGameRules +{ + /* client */ + virtual void(base_player) PlayerSpawn; + virtual void(base_player) PlayerDeath; +}; + +class CSMultiplayerRules:CSGameRules +{ + entity m_eLastTSpawn; + entity m_eLastCTSpawn; + + void() CSMultiplayerRules; + + virtual void(void) InitPostEnts; + virtual void(void) FrameStart; + virtual void(base_player) PlayerDisconnect; + virtual void(base_player) PlayerSpawn; + virtual void(base_player) PlayerPreFrame; + virtual void(base_player) PlayerDeath; + virtual int(int) MaxItemPerSlot; + virtual float(base_player, string) ConsoleCommand; + + /* CS specific */ + virtual void(void) CreateRescueZones; + virtual void(void) CreateCTBuyzones; + virtual void(void) CreateTBuyzones; + virtual void(float, int) TimerBegin; + virtual void(void) TimerUpdate; + + virtual int(base_player) BuyingPossible; + virtual void(int, int, int) RoundOver; + virtual void(int) RestartRound; + virtual void(base_player) DeathCheck; + virtual void(base_player) MakeBomber; + virtual void(base_player) MakeVIP; + virtual void(void) CountPlayers; + virtual void(void) SwitchTeams; + virtual void(void) TimeOut; + + virtual void(base_player) PlayerClearWeaponry; + virtual void(base_player, int) PlayerMakePlayable; + virtual void(base_player) PlayerMakeSpectator; + virtual void(base_player, int) PlayerRespawn; + virtual entity(float) PlayerFindSpawn; +}; + +void CSEv_JoinAuto(void); diff --git a/src/server/gamerules.qc b/src/server/gamerules.qc new file mode 100644 index 0000000..cc0f4c3 --- /dev/null +++ b/src/server/gamerules.qc @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +var int autocvar_sv_playerkeepalive = TRUE; + +void +CSGameRules::PlayerDeath(base_player pl) +{ +} + +void +CSGameRules::PlayerPain(base_player pl) +{ +} + +int +CSGameRules::BuyingPossible(base_player pl) +{ + return FALSE; +} + +/* we check what fields have changed over the course of the frame and network + * only the ones that have actually changed */ +void +CSGameRules::PlayerPostFrame(base_player pp) +{ + Animation_PlayerUpdate(); +} + +void +CSGameRules::LevelDecodeParms(base_player pp) +{ + player pl = (player)pp; + g_landmarkpos[0] = parm1; + g_landmarkpos[1] = parm2; + g_landmarkpos[2] = parm3; + pl.angles[0] = parm4; + pl.angles[1] = parm5; + pl.angles[2] = parm6; + pl.velocity[0] = parm7; + pl.velocity[1] = parm8; + pl.velocity[2] = parm9; + pl.g_items = parm10; + pl.activeweapon = parm11; + pl.flags = parm64; + + pl.ammo_50ae = parm12; + pl.ammo_762mm = parm13; + pl.ammo_556mm = parm14; + pl.ammo_556mmbox = parm15; + pl.ammo_338mag = parm16; + pl.ammo_9mm = parm17; + pl.ammo_buckshot = parm18; + pl.ammo_45acp = parm19; + pl.ammo_357sig = parm20; + pl.ammo_57mm = parm21; + pl.ammo_hegrenade = parm22; + pl.ammo_fbgrenade = parm23; + pl.ammo_smokegrenade = parm24; + pl.usp45_mag = parm25; + pl.glock18_mag = parm26; + pl.deagle_mag = parm27; + pl.p228_mag = parm28; + pl.elites_mag = parm29; + pl.fiveseven_mag = parm30; + pl.m3_mag = parm31; + pl.xm1014_mag = parm32; + pl.mp5_mag = parm33; + pl.p90_mag = parm34; + pl.ump45_mag = parm35; + pl.mac10_mag = parm36; + pl.tmp_mag = parm37; + pl.ak47_mag = parm38; + pl.sg552_mag = parm39; + pl.m4a1_mag = parm40; + pl.aug_mag = parm41; + pl.scout_mag = parm42; + pl.awp_mag = parm43; + pl.g3sg1_mag = parm44; + pl.sg550_mag = parm45; + pl.para_mag = parm46; + pl.gflags = parm63; + + if (pl.flags & FL_CROUCHING) { + setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX); + } else { + setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); + } +} + +void +CSGameRules::LevelChangeParms(base_player pp) +{ + player pl = (player)pp; + parm1 = g_landmarkpos[0]; + parm2 = g_landmarkpos[1]; + parm3 = g_landmarkpos[2]; + parm4 = pl.angles[0]; + parm5 = pl.angles[1]; + parm6 = pl.angles[2]; + parm7 = pl.velocity[0]; + parm8 = pl.velocity[1]; + parm9 = pl.velocity[2]; + parm63 = pl.gflags; + parm64 = pl.flags; + parm10 = pl.g_items; + parm11 = pl.activeweapon; + + parm12 = pl.ammo_50ae; + parm13 = pl.ammo_762mm; + parm14 = pl.ammo_556mm; + parm15 = pl.ammo_556mmbox; + parm16 = pl.ammo_338mag; + parm17 = pl.ammo_9mm; + parm18 = pl.ammo_buckshot; + parm19 = pl.ammo_45acp; + parm20 = pl.ammo_357sig; + parm21 = pl.ammo_57mm; + parm22 = pl.ammo_hegrenade; + parm23 = pl.ammo_fbgrenade; + parm24 = pl.ammo_smokegrenade; + parm25 = pl.usp45_mag; + parm26 = pl.glock18_mag; + parm27 = pl.deagle_mag; + parm28 = pl.p228_mag; + parm29 = pl.elites_mag; + parm30 = pl.fiveseven_mag; + parm31 = pl.m3_mag; + parm32 = pl.xm1014_mag; + parm33 = pl.mp5_mag; + parm34 = pl.p90_mag; + parm35 = pl.ump45_mag; + parm36 = pl.mac10_mag; + parm37 = pl.tmp_mag; + parm38 = pl.ak47_mag; + parm39 = pl.sg552_mag; + parm40 = pl.m4a1_mag; + parm41 = pl.aug_mag; + parm42 = pl.scout_mag; + parm43 = pl.awp_mag; + parm44 = pl.g3sg1_mag; + parm45 = pl.sg550_mag; + parm46 = pl.para_mag; +} + +void +CSGameRules::LevelNewParms(void) +{ + parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 = + parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 = + parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 = + parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 = + parm29 = parm30 = parm31 = parm32 = parm33 = parm34 = parm35 = + parm36 = parm37 = parm38 = parm39 = parm40 = parm41 = parm42 = + parm43 = parm44 = parm45 = parm46 = parm63= 0; + parm64 = FL_CLIENT; +} + +void +CSGameRules::PlayerConnect(base_player pl) +{ + if (Plugin_PlayerConnect(pl) == FALSE) + bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname)); +} + +void +CSGameRules::PlayerDisconnect(base_player pl) +{ + bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname)); + + /* Make this unusable */ + pl.solid = SOLID_NOT; + pl.movetype = MOVETYPE_NONE; + pl.modelindex = 0; + pl.health = 0; + pl.takedamage = 0; + pl.SendFlags = PLAYER_MODELINDEX; +} + +void +CSGameRules::PlayerKill(base_player pl) +{ + Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR); +} diff --git a/src/server/gamerules_multiplayer.qc b/src/server/gamerules_multiplayer.qc new file mode 100644 index 0000000..a4a1549 --- /dev/null +++ b/src/server/gamerules_multiplayer.qc @@ -0,0 +1,1022 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +int +CSMultiplayerRules::MaxItemPerSlot(int slot) +{ + /* grenades */ + if (slot == 3) { + return 3; + } + return 1; +} + +void +CSMultiplayerRules::PlayerDisconnect(base_player pl) +{ + if (health > 0) + PlayerDeath(pl); +} + +void +CSMultiplayerRules::PlayerDeath(base_player pl) +{ + /* obituary networking */ + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_OBITUARY); + if (g_dmg_eAttacker.netname) + WriteString(MSG_MULTICAST, g_dmg_eAttacker.netname); + else + WriteString(MSG_MULTICAST, g_dmg_eAttacker.classname); + WriteString(MSG_MULTICAST, pl.netname); + WriteByte(MSG_MULTICAST, g_dmg_iWeapon); + WriteByte(MSG_MULTICAST, 0); + msg_entity = world; + multicast([0,0,0], MULTICAST_ALL); + + /* death-counter */ + pl.deaths++; + forceinfokey(pl, "*deaths", ftos(pl.deaths)); + + /* update score-counter */ + if (g_dmg_eTarget.flags & FL_CLIENT || g_dmg_eTarget.flags & FL_MONSTER) + if (g_dmg_eAttacker.flags & FL_CLIENT) { + if (g_dmg_eTarget == g_dmg_eAttacker || g_dmg_eTarget.team == g_dmg_eAttacker.team) + g_dmg_eAttacker.frags--; + else + g_dmg_eAttacker.frags++; + } + + Weapon_DropCurrentWeapon(pl); + + /* if we're the bomb carrier, make sure we drop the bomb. */ + if (pl.g_items & ITEM_C4BOMB) { + pl.activeweapon = WEAPON_C4BOMB; + Weapon_DropCurrentWeapon(pl); + } + + /* clear all ammo and inventory... */ + PlayerClearWeaponry(pl); + + pl.movetype = MOVETYPE_NONE; + pl.solid = SOLID_NOT; + pl.takedamage = DAMAGE_NO; + pl.gflags &= ~GF_FLASHLIGHT; + pl.armor = 0; + pl.health = 0; + + entity corpse = spawn(); + setorigin(corpse, pl.origin + [0,0,32]); + setmodel(corpse, pl.model); + setsize(corpse, VEC_HULL_MIN, VEC_HULL_MAX); + corpse.movetype = MOVETYPE_TOSS; + corpse.solid = SOLID_TRIGGER; + corpse.modelindex = pl.modelindex; + corpse.frame = ANIM_DEATH1; + corpse.angles = pl.angles; + corpse.velocity = pl.velocity; + corpse.classname = "remove_me"; + + /* gamerule stuff */ + PlayerMakeSpectator(pl); + pl.classname = "player"; + forceinfokey(pl, "*dead", "1"); + forceinfokey(pl, "*team", ftos(pl.team)); + CountPlayers(); + + /* In Assassination, all Terrorists receive a $2500 + * reward if they won by killing the VIP. */ + if (self.team == TEAM_VIP) { + RoundOver(TEAM_T, 2500, FALSE); + return; + } + DeathCheck(pl); +} + +void +CSMultiplayerRules::PlayerPreFrame(base_player pl) +{ + player pp = (player)pl; + + if (pl.health <= 0) + return; + + if (g_cs_gamestate == GAME_FREEZE || pp.progress > 0.0f) { + pl.flags |= FL_FROZEN; + } +} + +void +CSMultiplayerRules::FrameStart(void) +{ + if ((g_cs_alive_t + g_cs_alive_ct) == 0) { + int iInGamePlayers = 0; + for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) { + iInGamePlayers++; + } + + if ((iInGamePlayers > 0) && (g_cs_gamestate != GAME_COMMENCING && g_cs_gamestate != GAME_END)) { + TimerBegin(2, GAME_COMMENCING); + } else if (iInGamePlayers == 0) { + g_cs_gamestate = GAME_INACTIVE; + g_cs_gametime = 0; + g_cs_roundswon_t = 0; + g_cs_roundswon_ct = 0; + g_cs_roundsplayed = 0; + } else { + TimerUpdate(); // Timer that happens once players have started joining + } + } else { + TimerUpdate(); // Normal gameplay timer + } +} + +void +CSMultiplayerRules::CreateRescueZones(void) +{ + int zones = 0; + + /* not in hostage rescue mode */ + if (g_cs_hostagestotal <= 0) { + return; + } + + /* count the already existing rescue zones. */ + for (entity e = world; (e = find(e, ::classname, "func_hostage_rescue"));) { + zones++; + } + + /* we don't need to create any additional rescue zones. */ + if (zones > 0) + return; + + /* since no buyzones are available, let's create one around every CT spawn */ + for (entity e = world; (e = find(e, ::classname, "info_player_start"));) { + info_hostage_rescue newzone = spawn(info_hostage_rescue); + setorigin(newzone, e.origin); + } +} + +void +CSMultiplayerRules::CreateCTBuyzones(void) +{ + int zones = 0; + + /* count the already existing CT zones. */ + for (entity e = world; (e = find(e, ::classname, "func_buyzone"));) { + if (e.team == TEAM_CT) { + zones++; + } + } + + /* we don't need to create any additional CT zones. */ + if (zones > 0) + return; + + /* since no buyzones are available, let's create one around every CT spawn */ + for (entity e = world; (e = find(e, ::classname, "info_player_start"));) { + info_buyzone newzone = spawn(info_buyzone); + setorigin(newzone, e.origin); + newzone.team = TEAM_CT; + } +} + +void +CSMultiplayerRules::CreateTBuyzones(void) +{ + int zones = 0; + + /* count the already existing T zones. */ + for (entity e = world; (e = find(e, ::classname, "func_buyzone"));) { + if (e.team == TEAM_T) { + zones++; + } + } + + /* we don't need to create any additional T zones. */ + if (zones > 0) + return; + + /* since no buyzones are available, let's create one around every T spawn */ + for (entity e = world; (e = find(e, ::classname, "info_player_deathmatch"));) { + info_buyzone newzone = spawn(info_buyzone); + setorigin(newzone, e.origin); + newzone.team = TEAM_T; + } +} + +void +CSMultiplayerRules::InitPostEnts(void) +{ + /* let's check if we need to create buyzones */ + switch (g_cstrike_buying) { + case BUY_CT: + CreateCTBuyzones(); + break; + case BUY_T: + CreateTBuyzones(); + break; + case BUY_NEITHER: + break; + default: + CreateCTBuyzones(); + CreateTBuyzones(); + } + + CreateRescueZones(); +} + +void +CSMultiplayerRules::TimerBegin(float tleft, int mode) +{ + if (mode == GAME_FREEZE) { + g_cs_gamestate = GAME_FREEZE; + } else if (mode == GAME_ACTIVE) { + g_cs_gamestate = GAME_ACTIVE; + } else if (mode == GAME_END) { + g_cs_gamestate = GAME_END; + } else if (mode == GAME_COMMENCING) { + g_cs_gamestate = GAME_COMMENCING; + } else if (mode == GAME_OVER) { + g_cs_gamestate = GAME_OVER; + } + + g_cs_gametime = tleft; +} + +void +CSMultiplayerRules::TimerUpdate(void) +{ + if (cvar("sv_playerslots") == 1) { + g_cs_gametime = -1; + return; + } + + if (g_cs_hostagestotal > 0) { + if (g_cs_hostagesrescued >= g_cs_hostagestotal) { + RoundOver(TEAM_CT, 0, FALSE); + return; + } + } + + // This map has been played enough we think + if (g_cs_gamestate != GAME_OVER) { + if (cvar("mp_timelimit") > 0) { + if (time >= (cvar("mp_timelimit") * 60)) { + IntermissionStart(); + g_cs_gamestate = GAME_OVER; + } + } + } + + // Okay, this means that timelimit is not the only deciding factor + if (autocvar_mp_winlimit > 0 && g_cs_gamestate != GAME_OVER) { + // It really doesn't matter who won. Do some logging perhaps? + if (g_cs_roundswon_ct == autocvar_mp_winlimit) { + IntermissionStart(); + } else if (g_cs_roundswon_t == autocvar_mp_winlimit) { + IntermissionStart(); + } + } + + if (g_cs_gamestate == GAME_INACTIVE) { + return; + } + + if (g_cs_gametime > 0) { + g_cs_gametime -= frametime; + } else { + g_cs_gametime = 0; + } + + if (g_cs_gamestate == GAME_COMMENCING || g_cs_gamestate == GAME_END) { + if (g_cs_gametime <= 0) { + if (g_cs_roundswon_t == 0 && g_cs_roundswon_ct == 0) { + Money_ResetTeamReward(); + Money_ResetRoundReward(); + RestartRound(TRUE); + } else { + if (autocvar_mp_halftime == TRUE && (autocvar_mp_winlimit / 2 == g_cs_roundsplayed)) { + Money_ResetTeamReward(); + SwitchTeams(); + RestartRound(TRUE); + } else { + RestartRound(FALSE); + } + } + } + return; + } + + if ((g_cs_gamestate == GAME_ACTIVE) || (g_cs_gamestate == GAME_FREEZE)) { + if (g_cs_gametime <= 0) { + if (g_cs_gamestate == GAME_ACTIVE) { + /* 1.5 will make the T's lose if time runs out no matter what */ + if (autocvar_fcs_fix_bombtimer == TRUE) { + if (g_cs_bombzones > 0 && g_cs_bombplanted == TRUE) { + return; + } + } + TimeOut(); + TimerBegin(5, GAME_END); // Round is over, 5 seconds til a new round starts + } else { + TimerBegin(autocvar_mp_roundtime * 60, GAME_ACTIVE); // Unfreeze + Radio_StartMessage(); + } + } + } +} + +/* +================= +BuyingPossible + +Checks if it is possible for players to buy anything +================= +*/ +int +CSMultiplayerRules::BuyingPossible(base_player pl) +{ + if (pl.health <= 0) { + return FALSE; + } + + if (g_cs_gamestate == GAME_ACTIVE) { + if (((autocvar_mp_roundtime * 60) - g_cs_gametime) > autocvar_mp_buytime) { + centerprint(pl, sprintf("%d seconds have passed...\nYou can't buy anything now!", autocvar_mp_buytime)); + return FALSE; + } + } + + if (pl.team == TEAM_VIP) { + centerprint(pl, "You are the VIP...\nYou can't buy anything!\n"); + return FALSE; + } + + if (g_cstrike_buying == BUY_NEITHER) { + centerprint(pl, "Sorry, you aren't meant\nto be buying anything.\n"); + return FALSE; + } + + if (g_cstrike_buying != BUY_BOTH) { + if (g_cstrike_buying == BUY_CT && pl.team == TEAM_T) { + centerprint(pl, "Terrorists aren't allowed to\nbuy anything on this map!\n"); + return FALSE; + } else if (g_cstrike_buying == BUY_T && pl.team == TEAM_CT) { + centerprint(pl, "CTs aren't allowed to buy\nanything on this map!\n"); + return FALSE; + } + } + + if (!(pl.gflags & GF_BUYZONE)) { + centerprint(pl, "Sorry, you aren't in a buyzone.\n"); + return FALSE; + } + + return TRUE; +} + +void +CSMultiplayerRules::MakeBomber(base_player pl) +{ + Weapons_AddItem(pl, WEAPON_C4BOMB, -1); + centerprint(pl, "You have the bomb!\nFind the target zone or DROP\nthe bomb for another Terrorist."); +} + +void +CSMultiplayerRules::MakeVIP(base_player pl) +{ + pl.team = TEAM_VIP; + PlayerRespawn(pl, pl.team); + centerprint(pl, "You are the VIP\nMake your way to the safety zones!"); + forceinfokey(pl, "*dead", "2"); +} + +/* +================= +RestartRound + +Loop through all ents and handle them +================= +*/ +void +CSMultiplayerRules::RestartRound(int iWipe) +{ + // Spawn/Respawn everyone at their team position and give them $$$ + for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) { + player pl = (player)eFind; + + if (pl.health > 0 && iWipe == FALSE) { + PlayerRespawn(pl, pl.team); + } else { + PlayerMakeSpectator(pl); + PlayerMakePlayable(pl, pl.charmodel); + } + + if (iWipe == FALSE) { + Money_GiveTeamReward(pl); + } else { + pl.money = 0; + Money_AddMoney(pl, autocvar_mp_startmoney); + } + } + + /* clear the corpses/items/bombs */ + for (entity eFind = world; (eFind = find(eFind, ::classname, "remove_me"));) { + remove(eFind); + } + + // Select a random Terrorist for the bomb, if needed + if (g_cs_bombzones > 0) { + int iRandomT = floor(random(1, (float)g_cs_alive_t + 1)); + int iPickT = 0; + + for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) { + if (eFind.team == TEAM_T) { + iPickT++; + + if (iPickT == iRandomT) { + MakeBomber((player)eFind); + } + } + } + } + + // If there is a VIP, select a random CT to be it + if (g_cs_vipzones > 0) { + int iRandomCT = floor(random(1, (float)g_cs_alive_ct + 1)); + int iPickCT = 0; + + for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) { + if (eFind.team == TEAM_CT) { + iPickCT++; + if (iPickCT == iRandomCT) { + MakeVIP((player)eFind); + } + } + } + } + + // Respawn all the entities + for (entity a = world; (a = findfloat(a, ::identity, 1));) { + CBaseEntity caw = (CBaseEntity)a; + if (caw.classname != "player") + caw.Respawn(); + } + + TimerBegin(autocvar_mp_freezetime, GAME_FREEZE); + Money_ResetTeamReward(); +} + +/* +================= +RoundOver + +This happens whenever an objective is complete or time is up +================= +*/ +void +CSMultiplayerRules::RoundOver(int iTeamWon, int iMoneyReward, int fSilent) +{ + if (g_cs_gamestate != GAME_ACTIVE) { + return; + } + + if (iTeamWon == TEAM_T) { + if (fSilent == FALSE) { + Radio_BroadcastMessage(RADIO_TERWIN); + } + g_cs_roundswon_t++; + } else if (iTeamWon == TEAM_CT) { + if (fSilent == FALSE) { + Radio_BroadcastMessage(RADIO_CTWIN); + } + g_cs_roundswon_ct++; + + /* In Bomb Defusal, if Terrorists were able to plant the bomb + * but lose the round, all Terrorists receive an $800 bonus. */ + if (g_cs_bombplanted) { + Money_QueTeamReward(TEAM_T, 800); + } + } else { + if (fSilent == FALSE) { + Radio_BroadcastMessage(RADIO_ROUNDDRAW); + } + } + + Money_HandleRoundReward(iTeamWon); + Money_QueTeamReward(iTeamWon, iMoneyReward); + TimerBegin(5, GAME_END); // Round is over, 5 seconds til a new round starts + + g_cs_hostagesrescued = 0; + g_cs_bombplanted = 0; + g_cs_roundsplayed++; + + forceinfokey(world, "teamscore_1", sprintf("%i", g_cs_roundswon_t)); + forceinfokey(world, "teamscore_2", sprintf("%i", g_cs_roundswon_ct)); +} + +/* +================= +TimeOut + +Whenever mp_roundtime was being counted down to 0 +================= +*/ +void +CSMultiplayerRules::TimeOut(void) +{ + if (g_cs_vipzones > 0) { + RoundOver(TEAM_T, 3250, FALSE); + } else if (g_cs_bombzones > 0) { + /* In Bomb Defusal, all Counter-Terrorists receive $3250 + * if they won running down the time. */ + RoundOver(TEAM_CT, 3250, FALSE); + } else if (g_cs_hostagestotal > 0) { + // TODO: Broadcast_Print: Hostages have not been rescued! + RoundOver(TEAM_T, 3250, FALSE); + } else { + RoundOver(0, 0, FALSE); + } +} + +/* +================= +SwitchTeams + +Happens rarely +================= +*/ +void +CSMultiplayerRules::SwitchTeams(void) +{ + int iCTW, iTW; + + for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) { + player pl = (player)eFind; + if (pl.team == TEAM_CT) { + pl.team = TEAM_T; + pl.charmodel -= 4; + } else if (pl.team == TEAM_T) { + pl.team = TEAM_CT; + pl.charmodel += 4; + } + forceinfokey(pl, "*team", ftos(pl.team)); + } + + iCTW = g_cs_roundswon_ct; + iTW = g_cs_roundswon_t; + + g_cs_roundswon_t = iCTW; + g_cs_roundswon_ct = iTW; + + iCTW = g_cs_alive_ct; + iTW = g_cs_alive_t; + + g_cs_alive_ct = iTW; + g_cs_alive_t = iCTW; + + forceinfokey(world, "teamscore_1", sprintf("%i", g_cs_roundswon_t)); + forceinfokey(world, "teamscore_2", sprintf("%i", g_cs_roundswon_ct)); +} + +void +CSMultiplayerRules::CountPlayers(void) +{ + g_cs_alive_t = 0; + g_cs_alive_ct = 0; + + for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) { + if (eFind.health > 0) { + if (eFind.team == TEAM_T) { + g_cs_alive_t++; + } else if (eFind.team == TEAM_CT) { + g_cs_alive_ct++; + } else if (eFind.team == TEAM_VIP) { + g_cs_alive_ct++; + } + } + } +} + +void +CSMultiplayerRules::DeathCheck(base_player pl) +{ + if ((g_cs_alive_t == 0) && (g_cs_alive_ct == 0)) { + if (g_cs_bombplanted == TRUE) { + RoundOver(TEAM_T, 3600, FALSE); + } else { + RoundOver(FALSE, 0, FALSE); + } + } else { + int winner; + if ((pl.team == TEAM_T) && (g_cs_alive_t == 0)) { + winner = TEAM_CT; + } else if ((pl.team == TEAM_CT) && (g_cs_alive_ct == 0)) { + winner = TEAM_T; + } else { + return; + } + if (g_cs_bombzones > 0) { + /* In Bomb Defusal, the winning team receives $3250 + * if they won by eliminating the enemy team. */ + if (!g_cs_bombplanted || g_cs_alive_ct == 0) { + RoundOver(winner, 3250, FALSE); + } + } else { + /* In Hostage Rescue, the winning team receives $3600 + * if they won by eliminating the enemy team. */ + RoundOver(winner, 3600, FALSE); + } + } +} + +/* +================= +PlayerFindSpawn + +Recursive function that gets the next spawnpoint +================= +*/ +entity +CSMultiplayerRules::PlayerFindSpawn(float t) +{ + entity point = world; + + if (t == TEAM_T) { + m_eLastTSpawn = find(m_eLastTSpawn, ::classname, "info_player_deathmatch"); + + if (m_eLastTSpawn == world) { + m_eLastTSpawn = find(m_eLastTSpawn, ::classname, "info_player_deathmatch"); + } + point = m_eLastTSpawn; + } else if (t == TEAM_CT) { + m_eLastCTSpawn = find(m_eLastCTSpawn, ::classname, "info_player_start"); + + if (m_eLastCTSpawn == world) { + m_eLastCTSpawn = find(m_eLastCTSpawn, ::classname, "info_player_start"); + } + point = m_eLastCTSpawn; + } else if (t == TEAM_VIP) { + point = find(world, ::classname, "info_vip_start"); + } + + if (point == world) { + error("Error: No valid spawnpoints available."); + } + + return point; +} + +/* +================= +PlayerRespawn + +Called whenever a player survived a round and needs a basic respawn. +================= +*/ +void +CSMultiplayerRules::PlayerRespawn(base_player pp, int fTeam) +{ + player pl = (player)pp; + + entity eSpawn; + forceinfokey(pl, "*spec", "0"); + eSpawn = PlayerFindSpawn(pl.team); + + pl.classname = "player"; + pl.health = pl.max_health = 100; + forceinfokey(pl, "*dead", "0"); + CountPlayers(); + + pl.takedamage = DAMAGE_YES; + pl.solid = SOLID_SLIDEBOX; + pl.movetype = MOVETYPE_WALK; + pl.flags = FL_CLIENT; + pl.iBleeds = TRUE; + pl.viewzoom = 1.0; + pl.g_items &= ~ITEM_C4BOMB; + + pl.SetOrigin(eSpawn.origin); + pl.angles = eSpawn.angles; + pl.SendFlags = UPDATE_ALL; + Client_FixAngle(pl, pl.angles); + + switch (pl.charmodel) { + case 1: + pl.model = "models/player/terror/terror.mdl"; + break; + case 2: + pl.model = "models/player/leet/leet.mdl"; + break; + case 3: + pl.model = "models/player/arctic/arctic.mdl"; + break; + case 4: + pl.model = "models/player/guerilla/guerilla.mdl"; + break; + case 5: + pl.model = "models/player/urban/urban.mdl"; + break; + case 6: + pl.model = "models/player/gsg9/gsg9.mdl"; + break; + case 7: + pl.model = "models/player/sas/sas.mdl"; + break; + case 8: + pl.model = "models/player/gign/gign.mdl"; + break; + default: + pl.model = "models/player/vip/vip.mdl"; + } + + pl.SetModel(pl.model); + pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX); + + pl.view_ofs = VEC_PLAYER_VIEWPOS; + pl.velocity = [0,0,0]; + pl.progress = 0.0f; + Weapons_SwitchBest(pl); + + /*Ammo_AutoFill(pl.fSlotPrimary); + Ammo_AutoFill(pl.fSlotSecondary);*/ +} + +void +CSMultiplayerRules::PlayerClearWeaponry(base_player pp) +{ + player pl = (player)pp; + + pl.g_items = 0x0; + pl.activeweapon = 0; + pl.ammo_50ae = 0; + pl.ammo_762mm = 0; + pl.ammo_556mm = 0; + pl.ammo_556mmbox = 0; + pl.ammo_338mag = 0; + pl.ammo_9mm = 0; + pl.ammo_buckshot = 0; + pl.ammo_45acp = 0; + pl.ammo_357sig = 0; + pl.ammo_57mm = 0; + pl.ammo_hegrenade = 0; + pl.ammo_fbgrenade = 0; + pl.ammo_smokegrenade = 0; + pl.usp45_mag = 0; + pl.glock18_mag = 0; + pl.deagle_mag = 0; + pl.p228_mag = 0; + pl.elites_mag = 0; + pl.fiveseven_mag = 0; + pl.m3_mag = 0; + pl.xm1014_mag = 0; + pl.mp5_mag = 0; + pl.p90_mag = 0; + pl.ump45_mag = 0; + pl.mac10_mag = 0; + pl.tmp_mag = 0; + pl.ak47_mag = 0; + pl.sg552_mag = 0; + pl.m4a1_mag = 0; + pl.aug_mag = 0; + pl.scout_mag = 0; + pl.awp_mag = 0; + pl.g3sg1_mag = 0; + pl.sg550_mag = 0; + pl.para_mag = 0; + pl.viewzoom = 1.0f; +} + +/* +================= +PlayerMakePlayable + +Called whenever need a full-reinit of a player. +This may be after a player had died or when the game starts for the first time. +================= +*/ +void +CSMultiplayerRules::PlayerMakePlayable(base_player pp, int chara) +{ + player pl = (player)pp; + /* spectator */ + if (chara == 0) { + PlayerSpawn(pl); + return; + } + + pl.g_items |= ITEM_SUIT; + Weapons_AddItem(pl, WEAPON_KNIFE, -1); + + /* terrorists */ + if (chara < 5) { + pl.team = TEAM_T; + if (autocvar_fcs_knifeonly == FALSE) { + Weapons_AddItem(pl, WEAPON_GLOCK18, -1); + pl.ammo_9mm = 40; + } + } else { + pl.team = TEAM_CT; + + if (autocvar_fcs_knifeonly == FALSE) { + Weapons_AddItem(pl, WEAPON_USP45, -1); + pl.ammo_45acp = 24; + } + } + + pl.ingame = TRUE; + forceinfokey(pl, "*team", ftos(pl.team)); + PlayerRespawn(pl, pl.team); +} + +/* +================= +PlayerMakeSpectator + +Force the player to become an observer. +================= +*/ +void +CSMultiplayerRules::PlayerMakeSpectator(base_player pl) +{ + pl.classname = "spectator"; + pl.health = 0; + pl.armor = 0; + pl.takedamage = DAMAGE_NO; + pl.solid = SOLID_NOT; + pl.movetype = MOVETYPE_NOCLIP; + pl.flags = FL_CLIENT; + pl.weapon = 0; + pl.viewzoom = 1.0f; + pl.model = 0; + setsize (pl, [-16,-16,-16], [16,16,16]); + pl.view_ofs = pl.velocity = [0,0,0]; + forceinfokey(pl, "*spec", "2"); + + /* clear the inventory */ + pl.items = 0x0; + pl.activeweapon = 0; +} + +/* +================= +PlayerSpawn + +Called on the client first joining the server. +================= +*/ +void +CSMultiplayerRules::PlayerSpawn(base_player pl) +{ + /* immediately put us into spectating mode */ + PlayerMakeSpectator(pl); + Spawn_ObserverCam(pl); + + /* give the initial server-joining money */ + Money_AddMoney(pl, autocvar_mp_startmoney); + + /* we don't belong to any team */ + pl.team = 0; + forceinfokey(pl, "*team", "0"); +} + +float +CSMultiplayerRules::ConsoleCommand(base_player pp, string cmd) +{ + tokenize(cmd); + + switch (argv(0)) { + case "bot_add": + entity bot_ent = Bot_AddQuick(); + if (bot_ent) { + bot_ent.think = CSEv_JoinAuto; + bot_ent.nextthink = time; + } + break; + default: + return FALSE; + } + + return TRUE; +} + +void +CSMultiplayerRules::CSMultiplayerRules(void) +{ + forceinfokey(world, "teams", "2"); + forceinfokey(world, "team_1", "Terrorist"); + forceinfokey(world, "teamscore_1", "0"); + forceinfokey(world, "team_2", "Counter-Terrorist"); + forceinfokey(world, "teamscore_2", "0"); +} + +/* +================= +CSEv_JoinTeam_f + +Event Handling, called by the Client codebase via 'sendevent' +================= +*/ +void CSEv_JoinTeam_f(float flChar) +{ + CSMultiplayerRules rules = (CSMultiplayerRules)g_grMode; + player pl = (player)self; + + if (pl.team == TEAM_VIP) { + centerprint(pl, "You are the VIP!\nYou cannot switch roles now.\n"); + return; + } + + // alive and are trying to switch teams, so subtract us from the Alive_Team counter. + if (pl.health > 0) { + rules.PlayerKill(pl); + } + + switch (g_cs_gamestate) { + /* spawn the players immediately when its in the freeze state */ + case GAME_FREEZE: + pl.charmodel = (int)flChar; + rules.PlayerMakePlayable(pl, (int)flChar); + + if ((pl.team == TEAM_T) && (g_cs_alive_t == 1)) { + if (g_cs_bombzones > 0) { + rules.MakeBomber(pl); + } + } else if ((pl.team == TEAM_CT) && (g_cs_alive_ct == 1)) { + if (g_cs_vipzones > 0) { + rules.MakeVIP(pl); + } + } + + break; + /* otherwise, just prepare their fields for the next round */ + default: + if (flChar == 0) { + rules.PlayerSpawn(pl); + return; + } + + if (flChar < 5) { + pl.team = TEAM_T; + } else { + pl.team = TEAM_CT; + } + + rules.PlayerMakeSpectator(pl); + pl.classname = "player"; + pl.charmodel = (int)flChar; + pl.health = 0; + forceinfokey(pl, "*dead", "1"); + forceinfokey(pl, "*team", ftos(pl.team)); + break; + } + + pl.frags = 0; + pl.deaths = 0; + forceinfokey(pl, "*deaths", ftos(pl.deaths)); + + rules.CountPlayers(); + + /* if no players are present in the chosen team, force restart round */ + if ((pl.team == TEAM_T) && (g_cs_alive_t == 0)) { + rules.RoundOver(FALSE, 0, FALSE); + } else if ((pl.team == TEAM_CT) && (g_cs_alive_ct == 0)) { + rules.RoundOver(FALSE, 0, FALSE); + } +} + +void CSEv_JoinAuto(void) +{ + int ct_count = 0; + int t_count = 1; + + for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) { + player pl = (player)eFind; + if (pl.team == TEAM_T) { + t_count++; + } + if (pl.team == TEAM_CT) { + ct_count++; + } + } + + if (ct_count >= t_count) { + CSEv_JoinTeam_f(floor(random(1,5))); + } else { + CSEv_JoinTeam_f(floor(random(5,9))); + } +} diff --git a/src/server/gamerules_singleplayer.qc b/src/server/gamerules_singleplayer.qc new file mode 100644 index 0000000..b4ecae6 --- /dev/null +++ b/src/server/gamerules_singleplayer.qc @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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 +CSSingleplayerRules::PlayerDeath(base_player pl) +{ + pl.movetype = MOVETYPE_NONE; + pl.solid = SOLID_NOT; + pl.takedamage = DAMAGE_NO; + pl.gflags &= ~GF_FLASHLIGHT; + pl.armor = pl.activeweapon = pl.g_items = 0; + + if (pl.health < -50) { + pl.health = 0; + FX_GibHuman(pl.origin); + return; + } + + pl.health = 0; +} + +void +CSSingleplayerRules::PlayerSpawn(base_player pl) +{ + pl.classname = "player"; + pl.health = pl.max_health = 100; + pl.takedamage = DAMAGE_YES; + pl.solid = SOLID_SLIDEBOX; + pl.movetype = MOVETYPE_WALK; + pl.flags = FL_CLIENT; + pl.viewzoom = 1.0; + pl.model = "models/player.mdl"; + setmodel(pl, pl.model); + + setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); + pl.view_ofs = VEC_PLAYER_VIEWPOS; + pl.velocity = [0,0,0]; + pl.gravity = __NULL__; + pl.frame = 1; + pl.SendFlags = UPDATE_ALL; + pl.customphysics = Empty; + pl.iBleeds = TRUE; + forceinfokey(pl, "*spec", "0"); + forceinfokey(pl, "*deaths", ftos(pl.deaths)); + + entity spot; + + if (startspot != "") { + dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", startspot)); + LevelDecodeParms(pl); + setorigin(pl, Landmark_GetSpot()); + } else { + LevelNewParms(); + spot = find(world, ::classname, "info_player_start"); + setorigin(pl, spot.origin); + pl.angles = spot.angles; + } + + Weapons_RefreshAmmo(pl); + Client_FixAngle(pl, pl.angles); +} diff --git a/src/server/hostage_entity.qc b/src/server/hostage_entity.qc new file mode 100644 index 0000000..0184df6 --- /dev/null +++ b/src/server/hostage_entity.qc @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED hostage_entity (0 1 0) (-16 -16 0) (16 16 72) +"targetname" Name +"target" Target when triggered. +"killtarget" Target to kill when triggered. +"model" "models/hostage.mdl" +"skin" "0" + +COUNTER-STRIKE (1999) ENTITY + +Hostage NPC. + +Used in the Hostage Rescue mode (cs_* maps). + +*/ + +enum +{ + HOSA_WALK, + HOSA_WALKSCARED, + HOSA_RUN, + HOSA_RUNSCARED, + HOSA_RUNLOOK, + HOSA_180LEFT, + HOSA_180RIGHT, + HOSA_FLINCH, + HOSA_PAIN, + HOSA_PAINLEFT, + HOSA_PAINRIGHT, + HOSA_PAINLEGLEFT, + HOSA_PAINLEGRIGHT, + HOSA_IDLE1, + HOSA_IDLE2, + HOSA_IDLE3, + HOSA_IDLE4, + HOSA_IDLE5, + HOSA_IDLE6, + HOSA_SCARED_END, + HOSA_SCARED1, + HOSA_SCARED2, + HOSA_SCARED3, + HOSA_SCARED4, + HOSA_PANIC, + HOSA_FEAR1, + HOSA_FEAR2, + HOSA_CRY, + HOSA_SCI1, + HOSA_SCI2, + HOSA_SCI3, + HOSA_DIE_SIMPLE, + HOSA_DIE_FORWARD1, + HOSA_DIE_FORWARD2, + HOSA_DIE_BACKWARD, + HOSA_DIE_HEADSHOT, + HOSA_DIE_GUTSHOT, + HOSA_LYING1, + HOSA_LYING2, + HOSA_DEADSIT, + HOSA_DEADTABLE1, + HOSA_DEADTABLE2, + HOSA_DEADTABLE3 +}; + +class hostage_entity:CBaseNPC +{ + int m_iUsedOnce; + + void(void) hostage_entity; + + virtual void(void) Respawn; + virtual void(void) OnPlayerUse; + virtual void(void) Pain; + virtual void(void) Death; + virtual int(void) AnimIdle; + virtual int(void) AnimWalk; + virtual int(void) AnimRun; +}; + +int +hostage_entity::AnimIdle(void) +{ + return HOSA_IDLE1; +} + +int +hostage_entity::AnimWalk(void) +{ + return HOSA_WALK; +} + +int +hostage_entity::AnimRun(void) +{ + return HOSA_RUN; +} + +void +hostage_entity::OnPlayerUse(void) +{ + if (eActivator.team == TEAM_T) { + return; + } + + if (m_eFollowing == world) + Sound_Speak(this, "hostage_entity.follow"); + + /* CT reward, first time only */ + if (m_iUsedOnce == FALSE) { + Money_AddMoney((player)eActivator, 150); + m_iUsedOnce = TRUE; + } + + CBaseNPC::OnPlayerUse(); +} + +void +hostage_entity::Pain(void) +{ + switch (g_dmg_iHitBody) { + case BODY_HEAD: + case BODY_DEFAULT: + case BODY_CHEST: + case BODY_STOMACH: + AnimPlay(HOSA_PAIN); + break; + case BODY_ARMLEFT: + AnimPlay(HOSA_PAINLEFT); + break; + case BODY_ARMRIGHT: + AnimPlay(HOSA_PAINRIGHT); + break; + case BODY_LEGLEFT: + AnimPlay(HOSA_PAINLEGLEFT); + break; + case BODY_LEGRIGHT: + AnimPlay(HOSA_PAINLEGRIGHT); + break; + } + + /* penalties */ + if (g_dmg_eAttacker.classname != "player") + return; + + Money_AddMoney((base_player)g_dmg_eAttacker, -(g_dmg_iDamage * 25)); +} + +void +hostage_entity::Death(void) +{ + WarnAllies(); + + if (style != MONSTER_DEAD) { + SetFrame(HOSA_DIE_SIMPLE + floor(random(0, 6))); + } + + /* now mark our state as 'dead' */ + CBaseNPC::Death(); + + /* penalties */ + if (g_dmg_eAttacker.classname != "player") + return; + + if (g_dmg_iDamage >= 100) + Money_AddMoney((base_player)g_dmg_eAttacker, -2500); + else + Money_AddMoney((base_player)g_dmg_eAttacker, -500); + + Radio_BroadcastMessage(RADIO_HOSDOWN); +} + +void +hostage_entity::Respawn(void) +{ + CBaseNPC::Respawn(); + m_iFlags |= MONSTER_CANFOLLOW; + m_iUsedOnce = FALSE; + PlayerUse = OnPlayerUse; +} + +void +hostage_entity::hostage_entity(void) +{ + Sound_Precache("hostage_entity.follow"); + + m_talkAnswer = ""; + m_talkAsk = ""; + m_talkAllyShot = ""; + m_talkGreet = ""; + m_talkIdle = ""; + m_talkHearing = ""; + m_talkSmelling = ""; + m_talkStare = ""; + m_talkSurvived = ""; + m_talkWounded = ""; + + m_talkPlayerAsk = ""; + m_talkPlayerGreet = ""; + m_talkPlayerIdle = ""; + m_talkPlayerWounded1 = ""; + m_talkPlayerWounded2 = ""; + m_talkPlayerWounded3 = ""; + m_talkUnfollow = ""; + m_talkFollow = ""; + m_talkStopFollow = ""; + + spawnflags |= MSF_MULTIPLAYER; + model = "models/hostage.mdl"; + netname = "Hostage"; + base_health = 100; + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + CBaseNPC::CBaseNPC(); + g_cs_hostagestotal++; +} diff --git a/src/server/info_buyzone.qc b/src/server/info_buyzone.qc new file mode 100644 index 0000000..99203ac --- /dev/null +++ b/src/server/info_buyzone.qc @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED info_buyzone (0 0 0.8) (-16 -16 0) (16 16 16) +"targetname" Name +"target" Target when triggered. +"killtarget" Target to kill when triggered. + +COUNTER-STRIKE (1999) ENTITY + +Buy zone. +See func_buyzone for more information. +*/ + +class info_buyzone +{ + void(void) info_buyzone; + virtual void(void) touch; +}; + +void +info_buyzone::touch(void) +{ + player pl = (player)other; + if (!(other.flags & FL_CLIENT)) + return; + + if (team == 0 || team == pl.team) + pl.gflags |= GF_BUYZONE; +} + +void +info_buyzone::info_buyzone(void) +{ + solid = SOLID_TRIGGER; + setsize(this, [-128,-128,-128], [128,128,128]); +} diff --git a/src/server/info_hostage_rescue.qc b/src/server/info_hostage_rescue.qc new file mode 100644 index 0000000..865cb58 --- /dev/null +++ b/src/server/info_hostage_rescue.qc @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED info_hostage_rescue (0 0 0.8) (-16 -16 0) (16 16 16) +"targetname" Name +"target" Target when triggered. +"killtarget" Target to kill when triggered. + +COUNTER-STRIKE (1999) ENTITY + +Hostage rescue point. + +Used in the Hostage Rescue mode (cs_* maps). +Creates a volume around itself with a radius of 128 units. +If neither a info_hostage_rescue or a func_hostage_rescue is placed, +zones will be placed in Counter-Terrorist player spawn nodes automatically. +*/ + +class info_hostage_rescue +{ + void(void) info_hostage_rescue; + virtual void(void) touch; +}; + +void +info_hostage_rescue::touch(void) +{ + if (other.flags & FL_CLIENT) { + player pl = (player)other; + pl.gflags |= GF_RESCUEZONE; + return; + } + + if (other.classname != "hostage_entity") { + return; + } + + CBaseNPC hosty = (CBaseNPC)other; + + if (hosty.solid == SOLID_NOT) { + return; + } + + /* some custom maps are very smart... */ + if (!((player)hosty.m_eFollowing)) + return; + + Radio_BroadcastMessage(RADIO_RESCUED); + g_cs_hostagesrescued++; + + Money_AddMoney((player)hosty.m_eFollowing, 1000); + + /* In Hostage Rescue, all Counter-Terrorists receive an $850 + * bonus for every hostage they rescue, even if they lose the round. */ + Money_QueTeamReward(TEAM_CT, 850); + + CBaseEntity targa = (CBaseEntity)other; + targa.Hide(); +} + +void +info_hostage_rescue::info_hostage_rescue(void) +{ + solid = SOLID_TRIGGER; + setsize(this, [-128,-128,-128], [128,128,128]); +} diff --git a/src/server/info_map_parameters.qc b/src/server/info_map_parameters.qc new file mode 100644 index 0000000..bda90c6 --- /dev/null +++ b/src/server/info_map_parameters.qc @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/*QUAKED info_map_parameters (0 0 0.8) (-16 -16 0) (16 16 16) +"targetname" Name +"target" Target when triggered. +"killtarget" Target to kill when triggered. +"buying" Override for buy-behaviour. +"bombradius" Overrides the default bomb radius. + +COUNTER-STRIKE (1999) ENTITY + +Miscellaneous mapping parameters. + +Choices for 'buying': + 0 = Both teams can buy items + 1 = Only Counter-Terrorists can buy items + 2 = Only Terrorists can buy items + 3 = Neither Counter-Terrorists nor Terrorists can buy items +*/ + +enum +{ + BUY_BOTH, + BUY_CT, + BUY_T, + BUY_NEITHER +}; + +class info_map_parameters +{ + void(void) info_map_parameters; +}; + +void +info_map_parameters::info_map_parameters(void) +{ + for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) { + switch (argv(i)) { + case "buying": + g_cstrike_buying = stoi(argv(i+1)); + break; + case "bombradius": + g_cstrike_bombradius = stof(argv(i+1)); + break; + default: + break; + } + } +} diff --git a/src/server/input.qc b/src/server/input.qc new file mode 100644 index 0000000..39f9987 --- /dev/null +++ b/src/server/input.qc @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 +Game_Input(void) +{ + CGameRules rules = (CGameRules)g_grMode; + + if (rules.m_iIntermission) { + rules.IntermissionEnd(); + return; + } + + if (input_buttons & INPUT_BUTTON0) { + Weapons_Primary(); + } else if (input_buttons & INPUT_BUTTON4) { + Weapons_Reload(); + } else if (input_buttons & INPUT_BUTTON3) { + Weapons_Secondary(); + } else { + Weapons_Release(); + } + + if (input_buttons & INPUT_BUTTON5) { + Player_UseDown(); + } else { + Player_UseUp(); + } + + if (self.impulse == 100) { + Flashlight_Toggle(); + } + + if (cvar("sv_cheats") == 1) { + player pl = (player)self; + if (self.impulse == 101) { + pl.health = 100; + pl.armor = 100; + + Weapons_AddItem(pl, WEAPON_M3, -1); + Weapons_AddItem(pl, WEAPON_XM1014, -1); + Weapons_AddItem(pl, WEAPON_MP5, -1); + Weapons_AddItem(pl, WEAPON_P90, -1); + Weapons_AddItem(pl, WEAPON_UMP45, -1); + Weapons_AddItem(pl, WEAPON_MAC10, -1); + Weapons_AddItem(pl, WEAPON_TMP, -1); + Weapons_AddItem(pl, WEAPON_AK47, -1); + Weapons_AddItem(pl, WEAPON_SG552, -1); + Weapons_AddItem(pl, WEAPON_M4A1, -1); + Weapons_AddItem(pl, WEAPON_AUG, -1); + Weapons_AddItem(pl, WEAPON_SCOUT, -1); + Weapons_AddItem(pl, WEAPON_AWP, -1); + Weapons_AddItem(pl, WEAPON_G3SG1, -1); + Weapons_AddItem(pl, WEAPON_SG550, -1); + Weapons_AddItem(pl, WEAPON_PARA, -1); + Weapons_AddItem(pl, WEAPON_C4BOMB, -1); + Weapons_AddItem(pl, WEAPON_FLASHBANG, -1); + Weapons_AddItem(pl, WEAPON_HEGRENADE, -1); + Weapons_AddItem(pl, WEAPON_SMOKEGRENADE, -1); + Weapons_AddItem(pl, WEAPON_USP45, -1); + Weapons_AddItem(pl, WEAPON_GLOCK18, -1); + Weapons_AddItem(pl, WEAPON_DEAGLE, -1); + Weapons_AddItem(pl, WEAPON_P228, -1); + Weapons_AddItem(pl, WEAPON_ELITES, -1); + Weapons_AddItem(pl, WEAPON_FIVESEVEN, -1); + Weapons_AddItem(pl, WEAPON_KNIFE, -1); + } + + if (self.impulse == 102) { + // Respawn all the entities + for (entity a = world; (a = findfloat(a, ::identity, 1));) { + CBaseEntity caw = (CBaseEntity)a; + caw.Respawn(); + } + bprint(PRINT_HIGH, "Respawning all map entities...\n"); + } + } + + self.impulse = 0; +} diff --git a/src/server/item_suit.qc b/src/server/item_suit.qc new file mode 100644 index 0000000..6af786b --- /dev/null +++ b/src/server/item_suit.qc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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:CBaseTrigger +{ + void(void) item_suit; + + virtual void(void) touch; + virtual void(void) Respawn; +}; + +void item_suit::touch(void) +{ + player pl = (player)other; + + if (pl.classname != "player") { + return; + } + + if (pl.g_items & ITEM_SUIT) { + return; + } + + sound(other, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_NORM); + pl.g_items |= ITEM_SUIT; + + UseTargets(other, TRIG_TOGGLE, m_flDelay); + + if (cvar("sv_playerslots") == 1) { + remove(self); + } else { + Hide(); + think = Respawn; + nextthink = time + 30.0f; + } +} + +void item_suit::Respawn(void) +{ + SetSolid(SOLID_TRIGGER); + SetMovetype(MOVETYPE_TOSS); + SetSize(VEC_HULL_MIN, VEC_HULL_MAX); + SetOrigin(m_oldOrigin); + SetModel(m_oldModel); + + think = __NULL__; + nextthink = -1; +} + +void item_suit::item_suit(void) +{ + model = "models/w_kevlar.mdl"; + precache_sound("items/tr_kevlar.wav"); + CBaseTrigger::CBaseTrigger(); + Respawn(); +} diff --git a/src/server/money.h b/src/server/money.h new file mode 100644 index 0000000..c81bdb9 --- /dev/null +++ b/src/server/money.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * 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. + */ + +int g_cs_moneyreward_ct; +int g_cs_moneyreward_t; + +void Money_AddMoney(base_player, int); +void Money_QueTeamReward(int, int); +void Money_GiveTeamReward(base_player); +void Money_ResetTeamReward(void); +void Money_HandleRoundReward(int) +void Money_ResetRoundReward(void); +int Money_GetLosses(int); +int Money_HasBonus(int); diff --git a/src/server/player.qc b/src/server/player.qc new file mode 100644 index 0000000..6bd06f1 --- /dev/null +++ b/src/server/player.qc @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/* +==================== +UseWorkaround +==================== +*/ +void UseWorkaround(entity eTarget) +{ + eActivator = self; + entity eOldSelf = self; + self = eTarget; + self.PlayerUse(); + self = eOldSelf; +} + +/* +==================== +Player_UseDown +==================== +*/ +void Player_UseDown(void) +{ + if (self.health <= 0) { + return; + } else if (!(self.flags & FL_USE_RELEASED)) { + return; + } + + vector vSource; + + makevectors(self.v_angle); + vSource = self.origin + self.view_ofs; + traceline (vSource, vSource + (v_forward * 64), MOVE_EVERYTHING, self); + + if (trace_ent.PlayerUse) { + self.flags &= ~FL_USE_RELEASED; + + UseWorkaround(trace_ent); + + /* Some entities want to support Use spamming */ + if (!(self.flags & FL_USE_RELEASED)) { + sound(self, CHAN_ITEM, "common/wpn_select.wav", 0.25, ATTN_IDLE); + } + } else { + sound(self, CHAN_ITEM, "common/wpn_denyselect.wav", 0.25, ATTN_IDLE); + self.flags &= ~FL_USE_RELEASED; + } +} + +/* +==================== +Player_UseUp +==================== +*/ +void Player_UseUp(void) { + if (!(self.flags & FL_USE_RELEASED)) { + self.flags |= FL_USE_RELEASED; + } +} + +void Weapons_Draw(void); +void CSEv_PlayerSwitchWeapon_i(int w) +{ + player pl = (player)self; + pl.activeweapon = w; + Weapons_Draw(); +} + +void +Player_Precache(void) +{ + 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); +} diff --git a/src/server/progs.src b/src/server/progs.src new file mode 100755 index 0000000..518b412 --- /dev/null +++ b/src/server/progs.src @@ -0,0 +1,61 @@ +#pragma target fte +#pragma progs_dat "../../progs.dat" + +#define QWSSQC +#define SERVER +#define VALVE +#define CSTRIKE +#define BULLETPENETRATION +#define BULLETPATTERNS +#define GS_RENDERFX + +#includelist +../../../src/shared/fteextensions.qc +../../../src/gs-entbase/server/defs.h +../../../src/shared/defs.h +../../../src/server/defs.h +../../../src/gs-entbase/server.src +../../../src/gs-entbase/shared.src + +defs.h +../shared/include.src + +player.qc +../../../valve/src/server/spectator.qc + +hostage_entity.qc +armoury_entity.qc +func_bomb_target.qc +func_buyzone.qc +info_buyzone.qc +func_escapezone.qc +func_hostage_rescue.qc +info_hostage_rescue.qc +func_vip_safetyzone.qc +info_map_parameters.qc +item_suit.qc +../../../valve/src/server/items.qc + +../../../src/botlib/include.src + +game_money.qc +gamerules.qc +gamerules_singleplayer.qc +gamerules_multiplayer.qc + +radio.qc +client.qc +ammo.qc +buy.qc +server.qc +../../../valve/src/server/damage.qc +../../../valve/src/server/rules.qc +../../../valve/src/server/flashlight.qc +../../../base/src/server/modelevent.qc + +input.qc +spawn.qc + +../../../src/server/include.src +../../../src/shared/include.src +#endlist diff --git a/src/server/radio.h b/src/server/radio.h new file mode 100644 index 0000000..1a900c2 --- /dev/null +++ b/src/server/radio.h @@ -0,0 +1,4 @@ +void Radio_BroadcastMessage(float fMessage) +void Radio_TeamMessage(float fMessage, float fTeam) +float Radio_DefaultStart(void) +void Radio_StartMessage(void) diff --git a/src/server/radio.qc b/src/server/radio.qc new file mode 100644 index 0000000..a55cc8e --- /dev/null +++ b/src/server/radio.qc @@ -0,0 +1,131 @@ +/* +================= +Radio_BroadcastMessage + +A global radio message for all players +================= +*/ +void +Radio_BroadcastMessage(float fMessage) +{ + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_RADIOMSG); + WriteByte(MSG_MULTICAST, fMessage); + msg_entity = self; + multicast([0,0,0], MULTICAST_ALL); +} + +/* +================= +Radio_TeamMessage + +A radio message targetted at members of a specific team +================= +*/ +void +Radio_TeamMessage(float fMessage, float fTeam) +{ + static void Radio_TeamMessage_Send(float fMessage, entity eEnt) { + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_RADIOMSG); + WriteByte(MSG_MULTICAST, fMessage); + msg_entity = eEnt; + multicast([0,0,0], MULTICAST_ONE); + } + + for (entity eFind = world; (eFind = find(eFind, classname, "player"));) { + if (eFind.team == fTeam) { + Radio_TeamMessage_Send(fMessage, eFind); + } else if (eFind.team == TEAM_VIP && fTeam == TEAM_CT) { + Radio_TeamMessage_Send(fMessage, eFind); + } + } +} + +/* +================= +Radio_DefaultStart + +Pick a generic, random radio string for global start messages +================= +*/ +float +Radio_DefaultStart(void) +{ + float fRand = floor(random(1, 4)); + + if (fRand == 1) { + return RADIO_MOVEOUT; + } else if (fRand == 2) { + return RADIO_LOCKNLOAD; + } else { + return RADIO_LETSGO; + } +} + +/* +================= +Radio_StartMessage + +Decide which startmessage to play at the beginning of each round +================= +*/ +void +Radio_StartMessage(void) +{ + if (g_cs_vipzones > 0) { + Radio_TeamMessage(RADIO_VIP, TEAM_CT); + Radio_TeamMessage(Radio_DefaultStart(), TEAM_T); + } else if (g_cs_escapezones > 0) { + Radio_TeamMessage(RADIO_GETOUT, TEAM_T); + Radio_TeamMessage(Radio_DefaultStart(), TEAM_CT); + } else { + Radio_BroadcastMessage(Radio_DefaultStart()); + } +} + +/* +================= +CSEv_Radio_f + +Triggered by clients, plays a message to members of the same team +================= +*/ +void +CSEv_Radio_f(float fMessage) +{ + static void CSEv_Radio_Send(float fMessage, entity eEnt) { + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_RADIOMSG2); + WriteByte(MSG_MULTICAST, num_for_edict(eEnt) - 1); + WriteByte(MSG_MULTICAST, fMessage); + msg_entity = eEnt; + multicast([0,0,0], MULTICAST_ONE); + } + + // Don't allow spamming + /*if (self.fRadioFinished > time) { + return; + }*/ + + // When dead, don't talk + if (self.health <= 0) { + return; + } + + // Make sure that VIPs and CTs get eachother + float fTargetTeam = self.team; + if (fTargetTeam == TEAM_VIP) { + fTargetTeam = TEAM_CT; + } + + for (entity eFind = world; (eFind = find(eFind, classname, "player"));) { + if (eFind.team == fTargetTeam) { + CSEv_Radio_Send(fMessage, eFind); + } else if (eFind.team == TEAM_VIP && fTargetTeam == TEAM_CT) { + CSEv_Radio_Send(fMessage, eFind); + } + } + + /*self.fRadioFinished = time + 3.0f;*/ +} diff --git a/src/server/server.qc b/src/server/server.qc new file mode 100644 index 0000000..833f29a --- /dev/null +++ b/src/server/server.qc @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 +Game_InitRules(void) +{ + if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) { + g_grMode = spawn(CSSingleplayerRules); + } else { + g_grMode = spawn(CSMultiplayerRules); + } +} + +void Game_Worldspawn(void) +{ + precache_model("models/player/arctic/arctic.mdl"); + precache_model("models/player/gign/gign.mdl"); + precache_model("models/player/gsg9/gsg9.mdl"); + precache_model("models/player/guerilla/guerilla.mdl"); + precache_model("models/player/leet/leet.mdl"); + precache_model("models/player/sas/sas.mdl"); + precache_model("models/player/terror/terror.mdl"); + precache_model("models/player/urban/urban.mdl"); + precache_model("models/player/vip/vip.mdl"); + precache_sound("weapons/ric_metal-2.wav"); + precache_sound("player/pl_pain2.wav"); + precache_sound("player/pl_pain4.wav"); + Sound_Precache("buy.kevlar"); + Sound_Precache("buy.weapon"); + Sound_Precache("buy.ammo"); + + /* some Counter-Strike maps do not have weapon pickups, so we want to + * precache these regardless in case of someone dropping a weapon, + * which happens quite often (buying weapons, etc.) */ + Sound_Precache("item.respawn"); + Sound_Precache("weapon.pickup"); + + Weapons_Init(); + + clientstat(STAT_MONEY, EV_INTEGER, player::money); + clientstat(STAT_PROGRESS, EV_FLOAT, player::progress); + + pointerstat(STAT_GAMETIME, EV_FLOAT, &g_cs_gametime); + pointerstat(STAT_GAMESTATE, EV_INTEGER, &g_cs_gamestate); +} diff --git a/src/server/spawn.qc b/src/server/spawn.qc new file mode 100644 index 0000000..97bce39 --- /dev/null +++ b/src/server/spawn.qc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * 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/animations.h b/src/shared/animations.h new file mode 100644 index 0000000..920874d --- /dev/null +++ b/src/shared/animations.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +enum +{ + ANIM_DUMMY1, + ANIM_IDLE, + ANIM_IDLE_CROUCH, + ANIM_WALK, + ANIM_RUN, + ANIM_RUN_CROUCH, + ANIM_JUMP, + ANIM_LONGJUMP, + ANIM_SWIM, + ANIM_TREADWATER, + ANIM_CROUCH_AIM_CARBINE, + ANIM_CROUCH_SHOOT_CARBINE, + ANIM_CROUCH_RELOAD_CARBINE, + ANIM_AIM_CARBINE, + ANIM_SHOOT_CARBINE, + ANIM_RELOAD_CARBINE, + ANIM_CROUCH_AIM_ONEHAND, + ANIM_CROUCH_SHOOT_ONEHAND, + ANIM_CROUCH_RELOAD_ONEHAND, + ANIM_AIM_ONEHAND, + ANIM_SHOOT_ONEHAND, + ANIM_RELOAD_ONEHAND, + ANIM_CROUCH_AIM_DUALPISTOLS, + ANIM_CROUCH_SHOOT_DUALPISTOLS, + ANIM_CROUCH_SHOOT2_DUALPISTOLS, + ANIM_CROUCH_RELOAD_DUALPISTOLS, + ANIM_AIM_DUALPISTOLS, + ANIM_SHOOT_DUALPISTOLS, + ANIM_SHOOT2_DUALPISTOLS, + ANIM_RELOAD_DUALPISTOLS, + ANIM_CROUCH_AIM_RIFLE, + ANIM_CROUCH_SHOOT_RIFLE, + ANIM_CROUCH_RELOAD_RIFLE, + ANIM_AIM_RIFLE, + ANIM_SHOOT_RIFLE, + ANIM_RELOAD_RIFLE, + ANIM_CROUCH_AIM_MP5, + ANIM_CROUCH_SHOOT_MP5, + ANIM_CROUCH_RELOAD_MP5, + ANIM_AIM_MP5, + ANIM_SHOOT_MP5, + ANIM_RELOAD_MP5, + ANIM_CROUCH_AIM_SHOTGUN, + ANIM_CROUCH_SHOOT_SHOTGUN, + ANIM_CROUCH_RELOAD_SHOTGUN, + ANIM_AIM_SHOTGUN, + ANIM_SHOOT_SHOTGUN, + ANIM_RELOAD_SHOTGUN, + ANIM_CROUCH_AIM_PARA, + ANIM_CROUCH_SHOOT_PARA, + ANIM_CROUCH_RELOAD_PARA, + ANIM_AIM_PARA, + ANIM_SHOOT_PARA, + ANIM_RELOAD_PARA, + ANIM_DUMMY2, + ANIM_DUMMY3, + ANIM_AIM_GRENADE, + ANIM_SHOOT_GRENADE, + ANIM_CROUCH_AIM_GRENADE, + ANIM_CROUCH_SHOOT_GRENADE, + ANIM_CROUCH_AIM_C4, + ANIM_CROUCH_SHOOT_C4, + ANIM_AIM_C4, + ANIM_SHOOT_C4, + ANIM_RELOAD_C4, + ANIM_DUPLICATE1, + ANIM_DUPLICATE2, + ANIM_DUPLICATE3, + ANIM_DUPLICATE4, + ANIM_DUPLICATE5, + ANIM_DUPLICATE6, + ANIM_DUPLICATE7, + ANIM_DUPLICATE8, + ANIM_CROUCH_AIM_KNIFE, + ANIM_CROUCH_SHOOT_KNIFE, + ANIM_AIM_KNIFE, + ANIM_SHOOT_KNIFE, + ANIM_CROUCH_AIM_AK47, + ANIM_CROUCH_SHOOT_AK47, + ANIM_CROUCH_RELOAD_AK47, + ANIM_AIM_AK47, + ANIM_SHOOT_AK47, + ANIM_RELOAD_AK47, + ANIM_GUT_FLINCH, + ANIM_HEAD_FLINCH, + ANIM_DEATH1, + ANIM_DEATH2, + ANIM_DEATH3, + ANIM_DIE_HEAD, + ANIM_DIE_GUT, + ANIM_DIE_LEFT, + ANIM_DIE_BACK, + ANIM_DIE_RIGHT, + ANIM_DIE_FORWARD, + ANIM_CROUCH_DIE +}; + +void Animation_PlayerTop(float); +void Animation_PlayerTopTemp(float, float); diff --git a/src/shared/animations.qc b/src/shared/animations.qc new file mode 100755 index 0000000..83e7422 --- /dev/null +++ b/src/shared/animations.qc @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +.float baseframe1time; +.float baseframe2time; +.float baseframe2; +.float baseframe_last; +.float baseframe_old; +.float baseframe_time; +.float baselerpfrac; +.float frame2; +.float frame2time; +.float frame_last; +.float fWasCrouching; +.float lerpfrac; +.float subblend2frac; +.float subblendfrac; + +void Animation_Print(string sWow) { +#ifdef CLIENT + print(sprintf("[DEBUG] %s", sWow)); +#else + bprint(PRINT_HIGH, sprintf("SSQC: %s", sWow) ); +#endif +} + +/* +================= +Animation_PlayerUpdate + +Called every frame to update the animation sequences +depending on what the player is doing +================= +*/ +void Animation_PlayerUpdate(void) { + self.basebone = cvar("spinebone"); // gettagindex(self, "Bip01 Spine"); + + if (self.baseframe_time < time) { + base_player pl = (base_player)self; + self.baseframe = Weapons_GetAim(pl.activeweapon); + self.baseframe_old = self.frame; + } + + /* in order to appear jumping, we want to not be on ground, + * but also make sure we're not just going down a ramp */ + if (!(self.flags & FL_ONGROUND) && (self.velocity[2] > 0 || self.frame == ANIM_JUMP)) { + self.frame = ANIM_JUMP; + } else if (vlen(self.velocity) == 0) { + if (self.flags & FL_CROUCHING) { + self.frame = ANIM_IDLE_CROUCH; + } else { + self.frame = ANIM_IDLE; + } + } else if (vlen(self.velocity) < 150) { + if (self.flags & FL_CROUCHING) { + self.frame = ANIM_RUN_CROUCH; + } else { + self.frame = ANIM_WALK; + } + } else if (vlen(self.velocity) > 150) { + if (self.flags & FL_CROUCHING) { + self.frame = ANIM_RUN_CROUCH; + } else { + self.frame = ANIM_RUN; + } + } + + // Lerp it down! + if (self.lerpfrac > 0) { + self.lerpfrac -= frametime * 5; + if (self.lerpfrac < 0) { + self.lerpfrac = 0; + } + } + + if (self.baselerpfrac > 0) { + self.baselerpfrac -= frametime * 5; + if (self.baselerpfrac < 0) { + self.baselerpfrac = 0; + } + } + + if (self.frame != self.frame_last) { + //Animation_Print(sprintf("New Frame: %d, Last Frame: %d\n", self.frame, self.frame_last)); + + // Move everything over to frame 2 + self.frame2time = self.frame1time; + self.frame2 = self.frame_last; + + // Set frame_last to avoid this being called again + self.frame_last = self.frame; + + self.lerpfrac = 1.0f; + self.frame1time = 0.0f; + } + + if (self.baseframe != self.baseframe_last) { + //Animation_Print(sprintf("New Baseframe: %d, Last Baseframe: %d\n", self.baseframe, self.baseframe_last)); + + // Move everything over to frame 2 + self.baseframe2time = self.baseframe1time; + self.baseframe2 = self.baseframe_last; + + // Set frame_last to avoid this being called again + self.baseframe_last = self.baseframe; + + self.baselerpfrac = 1.0f; + self.baseframe1time = 0.0f; + } + + // Force the code above to update if we switched positions + if (self.fWasCrouching != (self.flags & FL_CROUCHING)) { + self.baseframe_old = 0; + self.baseframe_time = 0; + self.fWasCrouching = (self.flags & FL_CROUCHING); + } + +#ifdef SERVER + // On the CSQC it's done in Player.c + self.subblendfrac = + self.subblend2frac = self.v_angle[0] / 90; +#endif + + self.angles[0] = self.angles[2] = 0; +} + +/* +================= +Animation_PlayerTop + +Changes the animation sequence for the upper body part +================= +*/ +void Animation_PlayerTop(float fFrame) { + self.baseframe = fFrame; + self.baseframe_old = fFrame; +} + +void Animation_PlayerTopTemp(float fFrame, float fTime) { + self.baseframe = fFrame; + self.baseframe_time = time + fTime; +#ifdef SERVER + self.SendFlags |= PLAYER_FRAME; +#endif +} diff --git a/src/shared/defs.h b/src/shared/defs.h new file mode 100644 index 0000000..120ce2c --- /dev/null +++ b/src/shared/defs.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016-2019 Marco Hladik + * + * 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. + */ + +#include "animations.h" +#include "radio.h" +#include "weapons.h" +#include "items.h" +#include "entities.h" +#include "events.h" + +#define TEAM_T 1 +#define TEAM_CT 2 +#define TEAM_VIP 3 + +enum +{ + STAT_MONEY = 34, + STAT_PROGRESS, + STAT_GAMETIME, + STAT_GAMESTATE +}; diff --git a/src/shared/entities.h b/src/shared/entities.h new file mode 100644 index 0000000..49d7ee1 --- /dev/null +++ b/src/shared/entities.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +enum +{ + ENT_C4BOMB = ENT_SEPARATOR, +}; diff --git a/src/shared/equipment.qc b/src/shared/equipment.qc new file mode 100755 index 0000000..f87c377 --- /dev/null +++ b/src/shared/equipment.qc @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 SERVER +void CSEv_PlayerBuyEquipment_f(float fID) { +/* if (Rules_BuyingPossible() == FALSE) { + return; + } + + if ((self.fMoney - eqptTable[fID].iPrice) >= 0) { + if (eqptTable[fID].iID == EQUIPMENT_DEFUSALKIT) { + if (self.team == TEAM_T) { return; } + if (!(self.iEquipment & EQUIPMENT_DEFUSALKIT)) { + self.iEquipment |= EQUIPMENT_DEFUSALKIT; + Money_AddMoney(self, -200); + sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE); + } else { + centerprint(self, "You already have a defusal kit!"); + } + } else if (eqptTable[fID].iID == EQUIPMENT_NIGHTVISION) { + if (!(self.iEquipment & EQUIPMENT_NIGHTVISION)) { + self.iEquipment |= EQUIPMENT_NIGHTVISION; + Money_AddMoney(self, -1250); + sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE); + } else { + centerprint(self, "You already have nightvision goggles!"); + } + } else if (eqptTable[fID].iID == WEAPON_HEGRENADE) { + if (self.iAmmo_HEGRENADE < 2) { + self.iAmmo_HEGRENADE++; + Money_AddMoney(self, -300); + sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE); + } else { + centerprint(self, "You can't carry any more!"); + } + } else if (eqptTable[fID].iID == WEAPON_FLASHBANG) { + if (self.iAmmo_FLASHBANG < 2) { + self.iAmmo_FLASHBANG++; + Money_AddMoney(self, -300); + sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE); + } else { + centerprint(self, "You can't carry any more!"); + } + } else if (eqptTable[fID].iID == WEAPON_SMOKEGRENADE) { + if (self.iAmmo_SMOKEGRENADE < 2) { + self.iAmmo_SMOKEGRENADE++; + Money_AddMoney(self, -300); + sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE); + } else { + centerprint(self, "You can't carry any more!"); + } + } else if (eqptTable[fID].iID == EQUIPMENT_KEVLAR) { + if (self.armor == 100) { + // You already own kevlar etc. + centerprint(self, "You already have kevlar!"); + } else { + self.armor = 100; + Money_AddMoney(self, -650); + } + + sound(self, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_IDLE); + self.fAttackFinished = time + 1.0; + return; + } else if (eqptTable[fID].iID == EQUIPMENT_HELMET) { + if (self.armor == 100) { + if (self.iEquipment & EQUIPMENT_HELMET) { + // You already have full kevlar and a helmet + centerprint(self, "You already have kevlar and a helmet!"); + } else { + // You have full kevlar, but no helmet + Money_AddMoney(self, -350); + sound(self, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_IDLE); + centerprint(self, "You already have some kevlar,\nand now you've bought a helmet!"); + self.iEquipment = self.iEquipment | EQUIPMENT_HELMET; + } + } else { + if (self.iEquipment & EQUIPMENT_HELMET) { + // Only get kevlar + self.armor = 100; + Money_AddMoney(self, -650); + sound(self, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_IDLE); + centerprint(self, "You already have a helmet,\nand now you've bought some kevlar!"); + } else { + // Get both + self.armor = 100; + self.iEquipment = self.iEquipment | EQUIPMENT_HELMET; + Money_AddMoney(self, -1000); + sound(self, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_IDLE); + } + } + + self.fAttackFinished = time + 1.0; + return; + } + } else { + centerprint(self, "You have insufficient funds!"); + } + + self.fAttackFinished = time + 1.0;*/ +} +#endif diff --git a/src/shared/events.h b/src/shared/events.h new file mode 100644 index 0000000..1204c4d --- /dev/null +++ b/src/shared/events.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +enum +{ + EV_RADIOMSG = EV_SEPARATOR, + EV_RADIOMSG2, + EV_SMOKE, + EV_FLASH +}; diff --git a/src/shared/flags.h b/src/shared/flags.h new file mode 100644 index 0000000..53b1313 --- /dev/null +++ b/src/shared/flags.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/* game flags */ +#define GF_SEMI_TOGGLED (1<<0) +#define GF_FLASHLIGHT (1<<1) +#define GF_BUYZONE (1<<2) +#define GF_RESCUEZONE (1<<3) +#define GF_BOMBZONE (1<<4) +#define GF_UNUSED6 (1<<5) +#define GF_UNUSED7 (1<<6) +#define GF_UNUSED8 (1<<7) +#define GF_UNUSED9 (1<<8) +#define GF_UNUSED10 (1<<9) +#define GF_UNUSED11 (1<<10) +#define GF_UNUSED12 (1<<11) +#define GF_UNUSED13 (1<<12) +#define GF_UNUSED14 (1<<14) +#define GF_UNUSED15 (1<<16) +#define GF_UNUSED16 (1<<13) +#define GF_UNUSED17 (1<<17) +#define GF_UNUSED18 (1<<18) +#define GF_UNUSED19 (1<<19) +#define GF_UNUSED20 (1<<20) +#define GF_UNUSED21 (1<<21) +#define GF_UNUSED22 (1<<22) +#define GF_UNUSED23 (1<<23) diff --git a/src/shared/fx_flashbang.qc b/src/shared/fx_flashbang.qc new file mode 100644 index 0000000..c5445bc --- /dev/null +++ b/src/shared/fx_flashbang.qc @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 SERVER +void +FX_Flashbang(vector org) +{ + for (entity e = world; (e = find(e, ::classname, "player"));) { + float fov_dot; + vector val; + float blindness; + float fade; + + /* wall check */ + traceline(e.origin + e.view_ofs, org, FALSE, e); + if (trace_fraction < 1.0f) + continue; + + /* calculate the fov in dotproduct form */ + makevectors(e.v_angle); + val = normalize(org - (e.origin + e.view_ofs)); + fov_dot = val * v_forward; + + /* it's behind us */ + if (fov_dot < 0) { + blindness = 0.1; + fade = 1.0f; + } else { + blindness = 2 * fov_dot; + fade = 4 * fov_dot; + } + + /* send the blinding env_fade event */ + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_FADE); + WriteFloat(MSG_MULTICAST, 1.0f); + WriteFloat(MSG_MULTICAST, 1.0f); + WriteFloat(MSG_MULTICAST, 1.0f); + WriteFloat(MSG_MULTICAST, 1.0f); + WriteFloat(MSG_MULTICAST, blindness); + WriteFloat(MSG_MULTICAST, fade); + WriteByte(MSG_MULTICAST, EVF_FADEDROM); + msg_entity = e; + multicast([0,0,0], MULTICAST_ONE_R); + } +} +#endif diff --git a/src/shared/fx_impact.qc b/src/shared/fx_impact.qc new file mode 100644 index 0000000..cdefcbd --- /dev/null +++ b/src/shared/fx_impact.qc @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 +var int FX_IMPACT_BLACKBITS; +var int FX_IMPACT_SMOKE_BROWN; +var int FX_IMPACT_SMOKE_GREY; +var int FX_IMPACT_SPARK; + +void +FX_Impact_Init(void) +{ + precache_sound("weapons/ric_metal-1.wav"); + precache_sound("weapons/ric_metal-2.wav"); + precache_sound("weapons/ric_conc-1.wav"); + precache_sound("weapons/ric_conc-2.wav"); + precache_sound("weapons/knife_hitwall1.wav"); + precache_sound("weapons/ric1.wav"); + precache_sound("weapons/ric2.wav"); + precache_sound("weapons/ric3.wav"); + precache_sound("weapons/ric4.wav"); + precache_sound("weapons/ric5.wav"); + + FX_IMPACT_BLACKBITS = particleeffectnum("fx_impact.blackbits"); + FX_IMPACT_SMOKE_GREY = particleeffectnum("fx_impact.smoke_grey"); + FX_IMPACT_SMOKE_BROWN = particleeffectnum("fx_impact.smoke_brown"); + FX_IMPACT_SPARK = particleeffectnum("fx_impact.spark"); +} +#endif + +void +FX_Impact(int iType, vector vecPos, vector vNormal) +{ +#ifdef SERVER + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_IMPACT); + WriteByte(MSG_MULTICAST, (float)iType); + WriteCoord(MSG_MULTICAST, vecPos[0]); + WriteCoord(MSG_MULTICAST, vecPos[1]); + WriteCoord(MSG_MULTICAST, vecPos[2]); + WriteCoord(MSG_MULTICAST, vNormal[0]); + WriteCoord(MSG_MULTICAST, vNormal[1]); + WriteCoord(MSG_MULTICAST, vNormal[2]); + msg_entity = self; + multicast(vecPos, MULTICAST_PVS); +#else + /* decals */ + switch (iType) { + case IMPACT_GLASS: + Decals_Place(vecPos, sprintf("{break%d", floor(random(1,4)))); + break; + case IMPACT_MELEE: + Decals_Place(vecPos, sprintf("{shot%d", floor(random(1,6)))); + break; + default: + Decals_Place(vecPos, sprintf("{bigshot%d", floor(random(1,6)))); + break; + } + + switch (iType) { + case IMPACT_MELEE: + pointsound(vecPos, "weapons/knife_hitwall1.wav", 1, ATTN_STATIC); + break; + case IMPACT_EXPLOSION: + break; + case IMPACT_GLASS: + pointparticles(FX_IMPACT_BLACKBITS, vecPos, vNormal, 1); + break; + case IMPACT_WOOD: + pointparticles(FX_IMPACT_SPARK, vecPos, vNormal, 1); + pointparticles(FX_IMPACT_BLACKBITS, vecPos, vNormal, 1); + pointparticles(FX_IMPACT_SMOKE_BROWN, vecPos, vNormal, 1); + break; + case IMPACT_METAL: + pointparticles(FX_IMPACT_SPARK, vecPos, vNormal, 1); + pointparticles(FX_IMPACT_BLACKBITS, vecPos, vNormal, 1); + break; + case IMPACT_FLESH: + FX_Blood(vecPos, vNormal); + break; + case IMPACT_DEFAULT: + default: + pointparticles(FX_IMPACT_SPARK, vecPos, vNormal, 1); + pointparticles(FX_IMPACT_BLACKBITS, vecPos, vNormal, 1); + pointparticles(FX_IMPACT_SMOKE_GREY, vecPos, vNormal, 1); + break; + } + + switch (iType) { + case IMPACT_METAL: + pointsound(vecPos, sprintf("weapons/ric_metal-%d.wav", floor((random() * 2) + 1)), 1, ATTN_STATIC); + break; + case IMPACT_CONCRETE: + pointsound(vecPos, sprintf("weapons/ric_conc-%d.wav", floor((random() * 2) + 1)), 1, ATTN_STATIC); + break; + case IMPACT_FLESH: + break; + default: + pointsound(vecPos, sprintf("weapons/ric%d.wav", floor((random() * 5) + 1)), 1, ATTN_STATIC); + break; + } +#endif +} diff --git a/src/shared/fx_smokenade.qc b/src/shared/fx_smokenade.qc new file mode 100644 index 0000000..4636026 --- /dev/null +++ b/src/shared/fx_smokenade.qc @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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 +var int PARTICLE_SMOKEGRENADE; + +void +FX_Smokenade_Init(void) +{ + PARTICLE_SMOKEGRENADE = particleeffectnum("fx_smokenade.effect"); +} +#endif + +void +FX_Smokenade(vector vecPos) +{ +#ifdef SERVER + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_SMOKE); + WriteCoord(MSG_MULTICAST, vecPos[0]); + WriteCoord(MSG_MULTICAST, vecPos[1]); + WriteCoord(MSG_MULTICAST, vecPos[2]); + msg_entity = self; + multicast([0,0,0], MULTICAST_ALL); +#else + static void Effect_CreateSmoke_Think(void) { + // HACK: This should only ever happen when rounds restart! + // Any way this can go wrong? + if (self.skin < getstatf(STAT_GAMETIME)) { + remove(self); + } + if (self.frame <= 0) { + remove(self); + return; + } + + pointparticles(PARTICLE_SMOKEGRENADE, self.origin, [0,0,0], 1); + self.frame--; + self.nextthink = time + 0.2f; + self.skin = getstatf(STAT_GAMETIME); + } + + entity eSmoke = spawn(); + setorigin(eSmoke, vecPos); + eSmoke.think = Effect_CreateSmoke_Think; + eSmoke.nextthink = time; + eSmoke.frame = 200; + eSmoke.skin = getstatf(STAT_GAMETIME); +#endif +} diff --git a/src/shared/include.src b/src/shared/include.src new file mode 100644 index 0000000..cb65439 --- /dev/null +++ b/src/shared/include.src @@ -0,0 +1,53 @@ + #includelist +defs.h +flags.h +player.h +../../../valve/src/shared/weapon_common.h +animations.h +animations.qc + +item_c4bomb.h + +../../../valve/src/shared/fx_blood.qc +../../../valve/src/shared/fx_breakmodel.qc +../../../valve/src/shared/fx_explosion.qc +../../../valve/src/shared/fx_gibhuman.qc +../../../valve/src/shared/fx_spark.qc +fx_impact.qc +fx_flashbang.qc +fx_smokenade.qc + +weapons_cstrike.qc +w_ak47.qc +w_deagle.qc +w_knife.qc +w_usp45.qc +w_glock18.qc +w_p228.qc +w_elites.qc +w_fiveseven.qc +w_m3.qc +w_xm1014.qc +w_mp5.qc +w_p90.qc +w_ump45.qc +w_mac10.qc +w_tmp.qc +w_sg552.qc +w_m4a1.qc +w_aug.qc +w_scout.qc +w_awp.qc +w_g3sg1.qc +w_sg550.qc +w_para.qc +w_c4bomb.qc +w_flashbang.qc +w_hegrenade.qc +w_smokegrenade.qc +weapons.qc +../../../valve/src/shared/weapon_common.qc +pmove.qc +../../../valve/src/shared/pmove_water.qc +item_c4bomb.qc +#endlist diff --git a/src/shared/item_c4bomb.h b/src/shared/item_c4bomb.h new file mode 100644 index 0000000..4373dc8 --- /dev/null +++ b/src/shared/item_c4bomb.h @@ -0,0 +1,8 @@ +#ifdef SERVER +void C4Bomb_Plant(base_player); +#endif + +#ifdef CLIENT +string g_c4bombled_spr; +void w_c4bomb_parse(void); +#endif diff --git a/src/shared/item_c4bomb.qc b/src/shared/item_c4bomb.qc new file mode 100644 index 0000000..fd70f21 --- /dev/null +++ b/src/shared/item_c4bomb.qc @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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_c4:CBaseEntity +{ +#ifdef SERVER + entity m_eUser; + float m_flBeepTime; + float m_flExplodeTime; + float m_flDefusalState; +#endif + +#ifdef CLIENT + float m_flAlpha; +#endif + +#ifdef SERVER + void(void) item_c4; + virtual float(entity, float) SendEntity; + virtual void(void) ClearProgress; + virtual void(void) OnPlayerUse; + virtual void(void) Logic; +#endif + +#ifdef CLIENT + void(void) item_c4; + virtual void(void) DrawLED; + virtual float(void) predraw; +#endif +}; + +#ifdef SERVER +float +item_c4::SendEntity(entity pvsent, float flags) +{ + WriteByte(MSG_ENTITY, ENT_C4BOMB); + WriteCoord(MSG_ENTITY, origin[0]); + WriteCoord(MSG_ENTITY, origin[1]); + WriteCoord(MSG_ENTITY, origin[2]); + WriteCoord(MSG_ENTITY, angles[0]); + WriteCoord(MSG_ENTITY, angles[1]); + WriteCoord(MSG_ENTITY, angles[2]); + WriteShort(MSG_ENTITY, modelindex); + return TRUE; +} + +void +item_c4::ClearProgress(void) +{ + if (m_eUser != world) { + player pl = (player)m_eUser; + pl.progress = 0.0f; + pl.flags &= ~FL_FROZEN; + } +} + +void +item_c4::OnPlayerUse(void) +{ + player pl = (player)eActivator; + + /* obvious check */ + if (pl.team != TEAM_CT) { + return; + } + + /* don't allow anyone else to hijack. */ + if (m_eUser == world) { + m_eUser = eActivator; + sound(this, CHAN_ITEM, "weapons/c4_disarm.wav", 1.0, ATTN_NONE); + } +} + +void +item_c4::Logic(void) +{ + CSMultiplayerRules rules = (CSMultiplayerRules)g_grMode; + + /* check if we're being used */ + if (m_eUser != world) { + player pl = (player)m_eUser; + + /* we need to check if the user has changed every frame. */ + if (!m_eUser.button5) { + ClearProgress(); + + /* clear user */ + m_eUser = world; + m_flDefusalState = 0.0f; + } else { + + /* defusal kit always cuts the time in half */ + if (pl.g_items & ITEM_DEFUSAL) + m_flDefusalState += (frametime * 2); + else + m_flDefusalState += frametime; + + /* tracked stat */ + pl.progress = m_flDefusalState; + pl.flags |= FL_FROZEN; + } + } + + if (m_flDefusalState > 10.0f) { + ClearProgress(); + sound(this, CHAN_VOICE, "weapons/c4_disarmed.wav", 1.0, ATTN_NORM); + rules.RoundOver(TEAM_CT, 3600, TRUE); + Radio_BroadcastMessage(RADIO_BOMBDEF); + m_flBeepTime = 0.0f; + m_flDefusalState = 0; + remove(this); + return; + } + + /* if our time has passed, explode */ + if (m_flExplodeTime < time) { + ClearProgress(); + + /* In Bomb Defusal, all Terrorists receive $3500 + * if they won by detonating the bomb. */ + rules.RoundOver(TEAM_T, 3500, FALSE); + Damage_Radius(origin, this.owner, 500, g_cstrike_bombradius, FALSE, WEAPON_C4BOMB); + Sound_Play(this, CHAN_VOICE, "weapon_c4bomb.explode"); + + for (entity e = world; (e = find(e, ::classname, "func_bomb_target"));) { + CBaseTrigger trigger = (CBaseTrigger)e; + if (trigger.Trigger != __NULL__) { + trigger.Trigger(this, TRIG_TOGGLE); + } + } + + m_flBeepTime = 0.0f; + m_flDefusalState = 0; + remove(this); + return; + } + + if (m_flBeepTime > time) { + return; + } + m_flBeepTime = time + 1.5; + + if (m_flExplodeTime - time < 2) { + sound(this, CHAN_VOICE, "weapons/c4_beep5.wav", 1.0, ATTN_NONE); + } else if (m_flExplodeTime - time < 5) { + sound(this, CHAN_VOICE, "weapons/c4_beep5.wav", 1.0, ATTN_NORM); + } else if (m_flExplodeTime - time < 10) { + sound(this, CHAN_VOICE, "weapons/c4_beep4.wav", 1.0, ATTN_NORM); + } else if (m_flExplodeTime - time < 20) { + sound(this, CHAN_VOICE, "weapons/c4_beep3.wav", 1.0, ATTN_NORM); + } else if (m_flExplodeTime - time < 30) { + sound(this, CHAN_VOICE, "weapons/c4_beep2.wav", 1.0, ATTN_NORM); + } else { + sound(this, CHAN_VOICE, "weapons/c4_beep1.wav", 1.0, ATTN_NORM); + } +} + +void +item_c4::item_c4(void) +{ + /* throw this in with the other temporary round entities */ + classname = "remove_me"; + + SetMovetype(MOVETYPE_NONE); + SetSolid(SOLID_BBOX); + SetModel("models/w_c4.mdl"); + SetSize([-6,-6,0], [6,6,6]); + + customphysics = Logic; + PlayerUse = OnPlayerUse; + m_flExplodeTime = time + 45.0f; + + Sound_Play(this, CHAN_WEAPON, "weapon_c4bomb.plant"); +} + +void +C4Bomb_Plant(base_player planter) +{ + item_c4 bomb = spawn(item_c4); + bomb.owner = planter; + + /* place directly below */ + traceline(planter.origin, planter.origin + [0,0,-64], FALSE, planter); + setorigin(bomb, trace_endpos); + bomb.SendFlags = -1; + + Radio_BroadcastMessage(RADIO_BOMBPL); + g_cs_bombplanted = TRUE; +} +#endif + +#ifdef CLIENT +void +item_c4::DrawLED(void) +{ + vector vecPlayer; + + int s = (float)getproperty(VF_ACTIVESEAT); + pSeat = &g_seats[s]; + vecPlayer = pSeat->m_vecPredictedOrigin; + + m_flAlpha -= frametime; + + if (m_flAlpha <= 0.0f) + m_flAlpha = 1.0f; + + if (m_flAlpha > 0) { + vector forg; + vector fsize; + float falpha; + + /* Scale the glow somewhat with the players distance */ + fsize = [16,16]; + fsize *= bound(1, vlen(vecPlayer - origin) / 256, 4); + + /* Fade out when the player is starting to move away */ + falpha = 1 - bound(0, vlen(vecPlayer - origin) / 1024, 1); + falpha *= m_flAlpha; + + /* Nudge this slightly towards the camera */ + makevectors(vectoangles(origin - vecPlayer)); + forg = (origin + [0,0,8]) + (v_forward * -16); + + /* Project it, always facing the player */ + makevectors(view_angles); + R_BeginPolygon(g_c4bombled_spr, 1, 0); + R_PolygonVertex(forg + v_right * fsize[0] - v_up * fsize[1], + [1,1], [1,1,1], falpha); + R_PolygonVertex(forg - v_right * fsize[0] - v_up * fsize[1], + [0,1], [1,1,1], falpha); + R_PolygonVertex(forg - v_right * fsize[0] + v_up * fsize[1], + [0,0], [1,1,1], falpha); + R_PolygonVertex(forg + v_right * fsize[0] + v_up * fsize[1], + [1,0], [1,1,1], falpha); + R_EndPolygon(); + } +} + +float +item_c4::predraw(void) +{ + DrawLED(); + addentity(this); + return PREDRAW_NEXT; +} + +void +item_c4::item_c4(void) +{ + solid = SOLID_BBOX; + movetype = MOVETYPE_NONE; + drawmask = MASK_ENGINE; +} + +void +w_c4bomb_parse(void) +{ + item_c4 tm = (item_c4)self; + spawnfunc_item_c4(); + + g_c4bombled_spr = spriteframe("sprites/ledglow.spr", 0, 0.0f); + + tm.origin[0] = readcoord(); + tm.origin[1] = readcoord(); + tm.origin[2] = readcoord(); + tm.angles[0] = readcoord(); + tm.angles[1] = readcoord(); + tm.angles[2] = readcoord(); + tm.modelindex = readshort(); + setorigin(tm, tm.origin); + setsize(tm, [-6,-6,0], [6,6,6]); +} +#endif diff --git a/src/shared/items.h b/src/shared/items.h new file mode 100644 index 0000000..4ed3d50 --- /dev/null +++ b/src/shared/items.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +#define ITEM_KNIFE 0x00000001i +#define ITEM_USP45 0x00000002i +#define ITEM_GLOCK18 0x00000004i +#define ITEM_DEAGLE 0x00000008i +#define ITEM_P228 0x00000010i +#define ITEM_ELITES 0x00000020i +#define ITEM_FIVESEVEN 0x00000040i +#define ITEM_M3 0x00000080i + +#define ITEM_XM1014 0x00000100i +#define ITEM_MP5 0x00000200i +#define ITEM_P90 0x00000400i +#define ITEM_UMP45 0x00000800i +#define ITEM_MAC10 0x00001000i +#define ITEM_TMP 0x00002000i +#define ITEM_SUIT 0x00004000i +#define ITEM_LONGJUMP 0x00008000i + +#define ITEM_AK47 0x00010000i +#define ITEM_SG552 0x00020000i +#define ITEM_M4A1 0x00040000i +#define ITEM_AUG 0x00080000i +#define ITEM_SCOUT 0x00100000i +#define ITEM_AWP 0x00200000i +#define ITEM_G3SG1 0x00400000i +#define ITEM_SG550 0x00800000i + +#define ITEM_PARA 0x01000000i +#define ITEM_C4BOMB 0x02000000i +#define ITEM_FLASHBANG 0x04000000i +#define ITEM_HEGRENADE 0x08000000i +#define ITEM_SMOKEGRENADE 0x10000000i +#define ITEM_DEFUSAL 0x20000000i +#define ITEM_NIGHTVISION 0x40000000i +#define ITEM_HELMET 0x80000000i diff --git a/src/shared/player.h b/src/shared/player.h new file mode 100644 index 0000000..16c6d60 --- /dev/null +++ b/src/shared/player.h @@ -0,0 +1,837 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +enumflags +{ + PLAYER_KEEPALIVE, + PLAYER_MODELINDEX, + PLAYER_ORIGIN, + PLAYER_ORIGIN_Z, + PLAYER_ANGLES_X, + PLAYER_ANGLES_Y, + PLAYER_ANGLES_Z, + PLAYER_VELOCITY, + PLAYER_VELOCITY_Z, + PLAYER_FLAGS, + PLAYER_WEAPON, + PLAYER_ITEMS, + PLAYER_HEALTH, + PLAYER_ARMOR, + PLAYER_MOVETYPE, + PLAYER_VIEWOFS, + PLAYER_BASEFRAME, + PLAYER_FRAME, + PLAYER_AMMO1, + PLAYER_AMMO2, + PLAYER_AMMO3, + PLAYER_CSSHOT, + PLAYER_CSSHOTTIME +}; + +enumflags +{ + AMMO1_USP45, + AMMO1_GLOCK18, + AMMO1_DEAGLE, + AMMO1_P228, + AMMO1_ELITES, + AMMO1_FIVESEVEN, + AMMO1_M3, + AMMO1_XM1014, + AMMO1_MP5, + AMMO1_P90, + AMMO1_UMP45, + AMMO1_MAC10, + AMMO1_TMP, + AMMO1_AK47, + AMMO1_SG552, + AMMO1_M4A1, + AMMO1_AUG, + AMMO1_SCOUT, + AMMO1_AWP, + AMMO1_G3SG1, + AMMO1_SG550, + AMMO1_PARA, +}; + +enumflags +{ + AMMO2_50AE, + AMMO2_762MM, + AMMO2_556MM, + AMMO2_556MMBOX, + AMMO2_338MAG, + AMMO2_9MM, + AMMO2_BUCKSHOT, + AMMO2_45ACP, + AMMO2_357SIG, + AMMO2_57MM, + AMMO2_HEGRENADE, + AMMO2_FBGRENADE, + AMMO2_SMOKEGRENADE, +}; + +enumflags +{ + AMMO3_MODE_USP45, + AMMO3_MODE_M4A1, + AMMO3_MODE_GLOCK18, +}; + +noref int input_sequence; +class player:base_player +{ + int ingame; + + int ammo_50ae; + int ammo_50ae_net; + int ammo_762mm; + int ammo_762mm_net; + int ammo_556mm; + int ammo_556mm_net; + int ammo_556mmbox; + int ammo_556mmbox_net; + int ammo_338mag; + int ammo_338mag_net; + int ammo_9mm; + int ammo_9mm_net; + int ammo_buckshot; + int ammo_buckshot_net; + int ammo_45acp; + int ammo_45acp_net; + int ammo_357sig; + int ammo_357sig_net; + int ammo_57mm; + int ammo_57mm_net; + int ammo_hegrenade; + int ammo_hegrenade_net; + int ammo_fbgrenade; + int ammo_fbgrenade_net; + int ammo_smokegrenade; + int ammo_smokegrenade_net; + + /* Weapon specific */ + int usp45_mag; + int usp45_mag_net; + int glock18_mag; + int glock18_mag_net; + int deagle_mag; + int deagle_mag_net; + int p228_mag; + int p228_mag_net; + int elites_mag; + int elites_mag_net; + int fiveseven_mag; + int fiveseven_mag_net; + int m3_mag; + int m3_mag_net; + int xm1014_mag; + int xm1014_mag_net; + int mp5_mag; + int mp5_mag_net; + int p90_mag; + int p90_mag_net; + int ump45_mag; + int ump45_mag_net; + int mac10_mag; + int mac10_mag_net; + int tmp_mag; + int tmp_mag_net; + int ak47_mag; + int ak47_mag_net; + int sg552_mag; + int sg552_mag_net; + int m4a1_mag; + int m4a1_mag_net; + int aug_mag; + int aug_mag_net; + int scout_mag; + int scout_mag_net; + int awp_mag; + int awp_mag_net; + int g3sg1_mag; + int g3sg1_mag_net; + int sg550_mag; + int sg550_mag_net; + int para_mag; + int para_mag_net; + + int mode_usp45; + int mode_usp45_net; + int mode_m4a1; + int mode_m4a1_net; + int mode_glock18; + int mode_glock18_net; + + int mode_temp; + int mode_temp_net; + + int cs_shotmultiplier; + int cs_shotmultiplier_net; + float cs_shottime; + float cs_shottime_net; + +#ifdef CLIENT + /* External model */ + entity p_model; + int playertype; + int p_hand_bone; + int p_model_bone; + float lastweapon; + + int cs_cross_mindist; + int cs_cross_deltadist; + float cs_crosshairdistance; + + virtual void(void) gun_offset; + virtual void(void) draw; + virtual float() predraw; + virtual void(void) postdraw; + virtual void(float) ReceiveEntity; + virtual void(void) PredictPreFrame; + virtual void(void) PredictPostFrame; +#else + virtual void(void) EvaluateEntity; + virtual float(entity, float) SendEntity; + + int charmodel; + int money; + float progress; +#endif +}; + + +#ifdef CLIENT +void Weapons_AmmoUpdate(entity); +/* +================= +player::ReceiveEntity +================= +*/ +void +player::ReceiveEntity(float new) +{ + float fl; + if (new == FALSE) { + /* Go through all the physics code between the last received frame + * and the newest frame and keep the changes this time around instead + * of rolling back, because we'll apply the new server-verified values + * right after anyway. */ + /* FIXME: splitscreen */ + if (entnum == player_localentnum) { + /* FIXME: splitscreen */ + pSeat = &g_seats[0]; + + for (int i = sequence+1; i <= servercommandframe; i++) { + /* ...maybe the input state is too old? */ + if (!getinputstate(i)) { + break; + } + input_sequence = i; + PMove_Run(); + } + + /* any differences in things that are read below are now + * officially from prediction misses. */ + } + } + + /* seed for our prediction table */ + sequence = servercommandframe; + + fl = readfloat(); + + /* HACK: we need to make this more reliable */ + if (fl == UPDATE_ALL) { + /* we respawned */ + gravity = __NULL__; + } + + if (fl & PLAYER_MODELINDEX) + modelindex = readshort(); + + if (fl & PLAYER_ORIGIN) { + origin[0] = readcoord(); + origin[1] = readcoord(); + } + + if (fl & PLAYER_ORIGIN_Z) + origin[2] = readcoord(); + if (fl & PLAYER_ANGLES_X) + pitch = readfloat(); + if (fl & PLAYER_ANGLES_Y) + angles[1] = readfloat(); + if (fl & PLAYER_ANGLES_Z) + angles[2] = readfloat(); + + if (fl & PLAYER_VELOCITY) { + velocity[0] = readcoord(); + velocity[1] = readcoord(); + } + + if (fl & PLAYER_VELOCITY_Z) + velocity[2] = readcoord(); + if (fl & PLAYER_FLAGS) { + flags = readfloat(); + gflags = readfloat(); + } + if (fl & PLAYER_WEAPON) + activeweapon = readbyte(); + if (fl & PLAYER_ITEMS) + g_items = (__variant)readfloat(); + if (fl & PLAYER_HEALTH) + health = readbyte(); + if (fl & PLAYER_ARMOR) + armor = readbyte(); + if (fl & PLAYER_MOVETYPE) + movetype = readbyte(); + if (fl & PLAYER_VIEWOFS) + view_ofs[2] = readfloat(); + if (fl & PLAYER_BASEFRAME) + baseframe = readbyte(); + if (fl & PLAYER_FRAME) { + frame = readbyte(); + frame1time = 0.0f; + frame2time = 0.0f; + } + + if (fl & PLAYER_AMMO1) { + usp45_mag = readbyte(); + glock18_mag = readbyte(); + deagle_mag = readbyte(); + p228_mag = readbyte(); + elites_mag = readbyte(); + fiveseven_mag = readbyte(); + m3_mag = readbyte(); + xm1014_mag = readbyte(); + mp5_mag = readbyte(); + p90_mag = readbyte(); + ump45_mag = readbyte(); + mac10_mag = readbyte(); + tmp_mag = readbyte(); + ak47_mag = readbyte(); + sg552_mag = readbyte(); + m4a1_mag = readbyte(); + aug_mag = readbyte(); + scout_mag = readbyte(); + awp_mag = readbyte(); + g3sg1_mag = readbyte(); + sg550_mag = readbyte(); + para_mag = readbyte(); + } + + if (fl & PLAYER_AMMO2) { + ammo_50ae = readbyte(); + ammo_762mm = readbyte(); + ammo_556mm = readbyte(); + ammo_556mmbox = readbyte(); + ammo_338mag = readbyte(); + ammo_9mm = readbyte(); + ammo_buckshot = readbyte(); + ammo_45acp = readbyte(); + ammo_357sig = readbyte(); + ammo_57mm = readbyte(); + ammo_hegrenade = readbyte(); + ammo_fbgrenade = readbyte(); + ammo_smokegrenade = readbyte(); + } + + if (fl & PLAYER_AMMO3) { + mode_usp45 = readbyte(); + mode_m4a1 = readbyte(); + mode_glock18 = readbyte(); + mode_temp = readbyte(); + } + + if (fl & PLAYER_CSSHOT) { + cs_shotmultiplier = readbyte(); + } + if (fl & PLAYER_CSSHOTTIME) { + cs_shottime = readfloat(); + } + + if (fl & PLAYER_AMMO1 || fl & PLAYER_AMMO2 || fl & PLAYER_AMMO3) + Weapons_AmmoUpdate(this); + + setorigin(this, origin); +} + +/* +================= +player::PredictPostFrame + +Save the last valid server values away in the _net variants of each field +so we can roll them back later. +================= +*/ +void +player::PredictPreFrame(void) +{ + usp45_mag_net = usp45_mag; + glock18_mag_net = glock18_mag; + deagle_mag_net = deagle_mag; + p228_mag_net = p228_mag; + elites_mag_net = elites_mag; + fiveseven_mag_net = fiveseven_mag; + m3_mag_net = m3_mag; + xm1014_mag_net = xm1014_mag; + mp5_mag_net = mp5_mag; + p90_mag_net = p90_mag; + ump45_mag_net = ump45_mag; + mac10_mag_net = mac10_mag; + tmp_mag_net = tmp_mag; + ak47_mag_net = ak47_mag; + sg552_mag_net = sg552_mag; + m4a1_mag_net = m4a1_mag; + aug_mag_net = aug_mag; + scout_mag_net = scout_mag; + awp_mag_net = awp_mag; + g3sg1_mag_net = g3sg1_mag; + sg550_mag_net = sg550_mag; + para_mag_net = para_mag; + + ammo_50ae_net = ammo_50ae; + ammo_762mm_net = ammo_762mm; + ammo_556mm_net = ammo_556mm; + ammo_556mmbox_net = ammo_556mmbox; + ammo_338mag_net = ammo_338mag; + ammo_9mm_net = ammo_9mm; + ammo_buckshot_net = ammo_buckshot; + ammo_45acp_net = ammo_45acp; + ammo_357sig_net = ammo_357sig; + ammo_57mm_net = ammo_57mm; + ammo_hegrenade_net = ammo_hegrenade; + ammo_fbgrenade_net = ammo_fbgrenade; + ammo_smokegrenade_net = ammo_smokegrenade; + + mode_usp45_net = mode_usp45; + mode_m4a1_net = mode_m4a1; + mode_glock18_net = mode_glock18; + mode_temp_net = mode_temp; + + cs_shotmultiplier_net = cs_shotmultiplier; + cs_shottime_net = cs_shottime; +} + +/* +================= +player::PredictPostFrame + +Where we roll back our values to the ones last sent/verified by the server. +================= +*/ +void +player::PredictPostFrame(void) +{ + usp45_mag = usp45_mag_net; + glock18_mag = glock18_mag_net; + deagle_mag = deagle_mag_net; + p228_mag = p228_mag_net; + elites_mag = elites_mag_net; + fiveseven_mag = fiveseven_mag_net; + m3_mag = m3_mag_net; + xm1014_mag = xm1014_mag_net; + mp5_mag = mp5_mag_net; + p90_mag = p90_mag_net; + ump45_mag = ump45_mag_net; + mac10_mag = mac10_mag_net; + tmp_mag = tmp_mag_net; + ak47_mag = ak47_mag_net; + sg552_mag = sg552_mag_net; + m4a1_mag = m4a1_mag_net; + aug_mag = aug_mag_net; + scout_mag = scout_mag_net; + awp_mag = awp_mag_net; + g3sg1_mag = g3sg1_mag_net; + sg550_mag = sg550_mag_net; + para_mag = para_mag_net; + + ammo_50ae = ammo_50ae_net; + ammo_762mm = ammo_762mm_net; + ammo_556mm = ammo_556mm_net; + ammo_556mmbox = ammo_556mmbox_net; + ammo_338mag = ammo_338mag_net; + ammo_9mm = ammo_9mm_net; + ammo_buckshot = ammo_buckshot_net; + ammo_45acp = ammo_45acp_net; + ammo_357sig = ammo_357sig_net; + ammo_57mm = ammo_57mm_net; + ammo_hegrenade = ammo_hegrenade_net; + ammo_fbgrenade = ammo_fbgrenade_net; + ammo_smokegrenade = ammo_smokegrenade_net; + + mode_usp45 = mode_usp45_net; + mode_m4a1 = mode_m4a1_net; + mode_glock18 = mode_glock18_net; + mode_temp = mode_temp_net; + + cs_shotmultiplier = cs_shotmultiplier_net; + cs_shottime = cs_shottime_net; +} + +#else +void +player::EvaluateEntity(void) +{ + SendFlags |= PLAYER_KEEPALIVE; + + if (old_modelindex != modelindex) + SendFlags |= PLAYER_MODELINDEX; + + if (old_origin[0] != origin[0]) + SendFlags |= PLAYER_ORIGIN; + + if (old_origin[1] != origin[1]) + SendFlags |= PLAYER_ORIGIN; + + if (old_origin[2] != origin[2]) + SendFlags |= PLAYER_ORIGIN_Z; + + if (old_angles[0] != v_angle[0]) + SendFlags |= PLAYER_ANGLES_X; + + if (old_angles[1] != angles[1]) + SendFlags |= PLAYER_ANGLES_Y; + + if (old_angles[2] != angles[2]) + SendFlags |= PLAYER_ANGLES_Z; + + if (old_velocity[0] != velocity[0]) + SendFlags |= PLAYER_VELOCITY; + + if (old_velocity[1] != velocity[1]) + SendFlags |= PLAYER_VELOCITY; + + if (old_velocity[2] != velocity[2]) + SendFlags |= PLAYER_VELOCITY_Z; + + if (old_flags != flags) + SendFlags |= PLAYER_FLAGS; + + if (old_gflags != gflags) + SendFlags |= PLAYER_FLAGS; + + if (old_activeweapon != activeweapon) + SendFlags |= PLAYER_WEAPON; + + if (old_items != g_items) + SendFlags |= PLAYER_ITEMS; + + if (old_health != health) + SendFlags |= PLAYER_HEALTH; + + if (old_armor != armor) + SendFlags |= PLAYER_ARMOR; + + if (old_movetype != movetype) + SendFlags |= PLAYER_MOVETYPE; + + if (old_viewofs != view_ofs[2]) + SendFlags |= PLAYER_VIEWOFS; + + if (old_baseframe != baseframe) + SendFlags |= PLAYER_BASEFRAME; + + if (old_frame != frame) + SendFlags |= PLAYER_FRAME; + + /* ammo 1 type updates */ + if (glock18_mag_net != glock18_mag) + SendFlags |= PLAYER_AMMO1; + if (usp45_mag_net != usp45_mag) + SendFlags |= PLAYER_AMMO1; + if (glock18_mag_net != glock18_mag) + SendFlags |= PLAYER_AMMO1; + if (deagle_mag_net != deagle_mag) + SendFlags |= PLAYER_AMMO1; + if (p228_mag_net != p228_mag) + SendFlags |= PLAYER_AMMO1; + if (elites_mag_net != elites_mag) + SendFlags |= PLAYER_AMMO1; + if (fiveseven_mag_net != fiveseven_mag) + SendFlags |= PLAYER_AMMO1; + if (m3_mag_net != m3_mag) + SendFlags |= PLAYER_AMMO1; + if (xm1014_mag_net != xm1014_mag) + SendFlags |= PLAYER_AMMO1; + if (mp5_mag_net != mp5_mag) + SendFlags |= PLAYER_AMMO1; + if (p90_mag_net != p90_mag) + SendFlags |= PLAYER_AMMO1; + if (ump45_mag_net != ump45_mag) + SendFlags |= PLAYER_AMMO1; + if (mac10_mag_net != mac10_mag) + SendFlags |= PLAYER_AMMO1; + if (tmp_mag_net != tmp_mag) + SendFlags |= PLAYER_AMMO1; + if (ak47_mag_net != ak47_mag) + SendFlags |= PLAYER_AMMO1; + if (sg552_mag_net != sg552_mag) + SendFlags |= PLAYER_AMMO1; + if (m4a1_mag_net != m4a1_mag) + SendFlags |= PLAYER_AMMO1; + if (aug_mag_net != aug_mag) + SendFlags |= PLAYER_AMMO1; + if (scout_mag_net != scout_mag) + SendFlags |= PLAYER_AMMO1; + if (awp_mag_net != awp_mag) + SendFlags |= PLAYER_AMMO1; + if (g3sg1_mag_net != g3sg1_mag) + SendFlags |= PLAYER_AMMO1; + if (sg550_mag_net != sg550_mag) + SendFlags |= PLAYER_AMMO1; + if (para_mag_net != para_mag) + SendFlags |= PLAYER_AMMO1; + + if (ammo_50ae_net != ammo_50ae) + SendFlags |= PLAYER_AMMO2; + if (ammo_762mm_net != ammo_762mm) + SendFlags |= PLAYER_AMMO2; + if (ammo_556mm_net != ammo_556mm) + SendFlags |= PLAYER_AMMO2; + if (ammo_556mmbox_net != ammo_556mmbox) + SendFlags |= PLAYER_AMMO2; + if (ammo_338mag_net != ammo_338mag) + SendFlags |= PLAYER_AMMO2; + if (ammo_9mm_net != ammo_9mm) + SendFlags |= PLAYER_AMMO2; + if (ammo_buckshot_net != ammo_buckshot) + SendFlags |= PLAYER_AMMO2; + if (ammo_45acp_net != ammo_45acp) + SendFlags |= PLAYER_AMMO2; + if (ammo_357sig_net != ammo_357sig) + SendFlags |= PLAYER_AMMO2; + if (ammo_57mm_net != ammo_57mm) + SendFlags |= PLAYER_AMMO2; + if (ammo_hegrenade_net != ammo_hegrenade) + SendFlags |= PLAYER_AMMO2; + if (ammo_fbgrenade_net != ammo_fbgrenade) + SendFlags |= PLAYER_AMMO2; + if (ammo_smokegrenade_net != ammo_smokegrenade) + SendFlags |= PLAYER_AMMO2; + + if (mode_usp45_net != mode_usp45) + SendFlags |= PLAYER_AMMO3; + if (mode_m4a1_net != mode_m4a1) + SendFlags |= PLAYER_AMMO3; + if (mode_glock18_net != mode_glock18) + SendFlags |= PLAYER_AMMO3; + if (mode_temp_net != mode_temp) + SendFlags |= PLAYER_AMMO3; + if (cs_shotmultiplier != cs_shotmultiplier_net) + SendFlags |= PLAYER_CSSHOT; + if (cs_shottime != cs_shottime_net) + SendFlags |= PLAYER_CSSHOTTIME; + + old_modelindex = modelindex; + old_origin = origin; + old_angles = angles; + old_angles[0] = v_angle[0]; + old_velocity = velocity; + old_flags = flags; + old_gflags = gflags; + old_activeweapon = activeweapon; + old_items = g_items; + old_health = health; + old_armor = armor; + old_movetype = movetype; + old_viewofs = view_ofs[2]; + old_baseframe = baseframe; + old_frame = frame; + + glock18_mag_net = glock18_mag; + usp45_mag_net = usp45_mag; + glock18_mag_net = glock18_mag; + deagle_mag_net = deagle_mag; + p228_mag_net = p228_mag; + elites_mag_net = elites_mag; + fiveseven_mag_net = fiveseven_mag; + m3_mag_net = m3_mag; + xm1014_mag_net = xm1014_mag; + mp5_mag_net = mp5_mag; + p90_mag_net = p90_mag; + ump45_mag_net = ump45_mag; + mac10_mag_net = mac10_mag; + tmp_mag_net = tmp_mag; + ak47_mag_net = ak47_mag; + sg552_mag_net = sg552_mag; + m4a1_mag_net = m4a1_mag; + aug_mag_net = aug_mag; + scout_mag_net = scout_mag; + awp_mag_net = awp_mag; + g3sg1_mag_net = g3sg1_mag; + sg550_mag_net = sg550_mag; + para_mag_net = para_mag; + + ammo_50ae_net = ammo_50ae; + ammo_762mm_net = ammo_762mm; + ammo_556mm_net = ammo_556mm; + ammo_556mmbox_net = ammo_556mmbox; + ammo_338mag_net = ammo_338mag; + ammo_9mm_net = ammo_9mm; + ammo_buckshot_net = ammo_buckshot; + ammo_45acp_net = ammo_45acp; + ammo_357sig_net = ammo_357sig; + ammo_57mm_net = ammo_57mm; + ammo_hegrenade_net = ammo_hegrenade; + ammo_fbgrenade_net = ammo_fbgrenade; + ammo_smokegrenade_net = ammo_smokegrenade; + + mode_usp45_net = mode_usp45; + mode_m4a1_net = mode_m4a1; + mode_glock18_net = mode_glock18; + mode_temp_net = mode_temp; + + cs_shotmultiplier_net = cs_shotmultiplier; + cs_shottime_net = cs_shottime; + + if (g_cs_gamestate != GAME_FREEZE) { + if (progress <= 0.0f) { + flags &= ~FL_FROZEN; + SendFlags |= PLAYER_FLAGS; + } + } +} + +/* +================= +player::SendEntity +================= +*/ +float +player::SendEntity(entity ePEnt, float fChanged) +{ + if (health <= 0 && ePEnt != this) { + return FALSE; + } + + if (clienttype(ePEnt) != CLIENTTYPE_REAL) { + return FALSE; + } + + if (ePEnt != self) { + fChanged &= ~PLAYER_ITEMS; + fChanged &= ~PLAYER_HEALTH; + fChanged &= ~PLAYER_ARMOR; + fChanged &= ~PLAYER_VIEWOFS; + fChanged &= ~PLAYER_AMMO1; + fChanged &= ~PLAYER_AMMO2; + fChanged &= ~PLAYER_AMMO3; + } + + WriteByte(MSG_ENTITY, ENT_PLAYER); + WriteFloat(MSG_ENTITY, fChanged); + + /* really trying to get our moneys worth with 23 bits of mantissa */ + if (fChanged & PLAYER_MODELINDEX) + WriteShort(MSG_ENTITY, modelindex); + if (fChanged & PLAYER_ORIGIN) { + WriteCoord(MSG_ENTITY, origin[0]); + WriteCoord(MSG_ENTITY, origin[1]); + } + if (fChanged & PLAYER_ORIGIN_Z) + WriteCoord(MSG_ENTITY, origin[2]); + if (fChanged & PLAYER_ANGLES_X) + WriteFloat(MSG_ENTITY, v_angle[0]); + if (fChanged & PLAYER_ANGLES_Y) + WriteFloat(MSG_ENTITY, angles[1]); + if (fChanged & PLAYER_ANGLES_Z) + WriteFloat(MSG_ENTITY, angles[2]); + if (fChanged & PLAYER_VELOCITY) { + WriteCoord(MSG_ENTITY, velocity[0]); + WriteCoord(MSG_ENTITY, velocity[1]); + } + if (fChanged & PLAYER_VELOCITY_Z) + WriteCoord(MSG_ENTITY, velocity[2]); + if (fChanged & PLAYER_FLAGS) { + WriteFloat(MSG_ENTITY, flags); + WriteFloat(MSG_ENTITY, gflags); + } + if (fChanged & PLAYER_WEAPON) + WriteByte(MSG_ENTITY, activeweapon); + if (fChanged & PLAYER_ITEMS) + WriteFloat(MSG_ENTITY, (__variant)g_items); + if (fChanged & PLAYER_HEALTH) + WriteByte(MSG_ENTITY, bound(0, health, 255)); + if (fChanged & PLAYER_ARMOR) + WriteByte(MSG_ENTITY, armor); + if (fChanged & PLAYER_MOVETYPE) + WriteByte(MSG_ENTITY, movetype); + if (fChanged & PLAYER_VIEWOFS) + WriteFloat(MSG_ENTITY, view_ofs[2]); + if (fChanged & PLAYER_BASEFRAME) + WriteByte(MSG_ENTITY, baseframe); + if (fChanged & PLAYER_FRAME) + WriteByte(MSG_ENTITY, frame); + + if (fChanged & PLAYER_AMMO1) { + WriteByte(MSG_ENTITY, usp45_mag); + WriteByte(MSG_ENTITY, glock18_mag); + WriteByte(MSG_ENTITY, deagle_mag); + WriteByte(MSG_ENTITY, p228_mag); + WriteByte(MSG_ENTITY, elites_mag); + WriteByte(MSG_ENTITY, fiveseven_mag); + WriteByte(MSG_ENTITY, m3_mag); + WriteByte(MSG_ENTITY, xm1014_mag); + WriteByte(MSG_ENTITY, mp5_mag); + WriteByte(MSG_ENTITY, p90_mag); + WriteByte(MSG_ENTITY, ump45_mag); + WriteByte(MSG_ENTITY, mac10_mag); + WriteByte(MSG_ENTITY, tmp_mag); + WriteByte(MSG_ENTITY, ak47_mag); + WriteByte(MSG_ENTITY, sg552_mag); + WriteByte(MSG_ENTITY, m4a1_mag); + WriteByte(MSG_ENTITY, aug_mag); + WriteByte(MSG_ENTITY, scout_mag); + WriteByte(MSG_ENTITY, awp_mag); + WriteByte(MSG_ENTITY, g3sg1_mag); + WriteByte(MSG_ENTITY, sg550_mag); + WriteByte(MSG_ENTITY, para_mag); + } + + if (fChanged & PLAYER_AMMO2) { + WriteByte(MSG_ENTITY, ammo_50ae); + WriteByte(MSG_ENTITY, ammo_762mm); + WriteByte(MSG_ENTITY, ammo_556mm); + WriteByte(MSG_ENTITY, ammo_556mmbox); + WriteByte(MSG_ENTITY, ammo_338mag); + WriteByte(MSG_ENTITY, ammo_9mm); + WriteByte(MSG_ENTITY, ammo_buckshot); + WriteByte(MSG_ENTITY, ammo_45acp); + WriteByte(MSG_ENTITY, ammo_357sig); + WriteByte(MSG_ENTITY, ammo_57mm); + WriteByte(MSG_ENTITY, ammo_hegrenade); + WriteByte(MSG_ENTITY, ammo_fbgrenade); + WriteByte(MSG_ENTITY, ammo_smokegrenade); + } + + if (fChanged & PLAYER_AMMO3) { + WriteByte(MSG_ENTITY, mode_usp45); + WriteByte(MSG_ENTITY, mode_m4a1); + WriteByte(MSG_ENTITY, mode_glock18); + WriteByte(MSG_ENTITY, mode_temp); + } + + if (fChanged & PLAYER_CSSHOT) { + WriteByte(MSG_ENTITY, cs_shotmultiplier); + } + if (fChanged & PLAYER_CSSHOTTIME) { + WriteFloat(MSG_ENTITY, cs_shottime); + } + + return TRUE; +} +#endif diff --git a/src/shared/pmove.qc b/src/shared/pmove.qc new file mode 100644 index 0000000..8940541 --- /dev/null +++ b/src/shared/pmove.qc @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +#define PMOVE_STEPHEIGHT 18 +#define PMOVE_AIRSTEPHEIGHT 18 +#define PMOVE_FRICTION 4 +#define PMOVE_EDGEFRICTION 1 +#define PMOVE_STOPSPEED 75 +#define PMOVE_GRAVITY 800 +#define PMOVE_AIRACCELERATE 10 +#define PMOVE_WATERACCELERATE 8 +#define PMOVE_ACCELERATE 4 +#define PMOVE_MAXSPEED 250 + +.float waterlevel; +.float watertype; + +/* values courtesy of https://wiki.alliedmods.net/Cs_weapons_information */ +float +GamePMove_Maxspeed(player target) +{ + float spd = serverkeyfloat("phy_maxspeed"); + + switch (target.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: + } + + if (target.flags & FL_CROUCHING) { + spd *= 0.5f; + } + + return spd; +} + +void +GamePMove_Fall(player target, float impactspeed) +{ + if (impactspeed > 580) { +#ifdef SERVER + float fFallDamage = (impactspeed - 580) * (100 / (1024 - 580)) * 1.75f; + Damage_Apply(target, world, fFallDamage, 0, DMG_FALL); + + if (random() < 0.5) + sound(target, CHAN_AUTO, "player/pl_pain2.wav", 1.0, ATTN_NORM); + else + sound(target, CHAN_AUTO, "player/pl_pain4.wav", 1.0, ATTN_NORM); +#endif + } +} + +void +GamePMove_Jump(player target) +{ + if (target.waterlevel >= 2) { + if (target.watertype == CONTENT_WATER) { + target.velocity[2] = 100; + } else if (target.watertype == CONTENT_SLIME) { + target.velocity[2] = 80; + } else { + target.velocity[2] = 50; + } + } else { + /* slow the player down a bit to prevent bhopping like crazy */ + target.velocity *= 0.80f; + target.velocity[2] += 220; + } +} diff --git a/src/shared/radio.h b/src/shared/radio.h new file mode 100644 index 0000000..94eb79d --- /dev/null +++ b/src/shared/radio.h @@ -0,0 +1,47 @@ + +enum +{ + RADIO_BLOW, + RADIO_BOMBDEF, + RADIO_BOMBPL, + RADIO_CIRCLEBACK, + RADIO_CLEAR, + RADIO_COM_FOLLOWCOM, + RADIO_COM_GETINPOS, + RADIO_COM_GO, + RADIO_COM_REPORTIN, + RADIO_CT_AFFIRM, + RADIO_CT_BACKUP, + RADIO_CT_COVERME, + RADIO_CT_ENEMYS, + RADIO_CT_FIREINHOLE, + RADIO_CT_IMHIT, + RADIO_CT_INPOS, + RADIO_CT_POINT, + RADIO_CT_REPORTINGIN, + RADIO_CTWIN, + RADIO_ENEMYDOWN, + RADIO_FALLBACK, + RADIO_FIREASSIS, + RADIO_FOLLOWME, + RADIO_GETOUT, + RADIO_GO, + RADIO_HITASSIST, + RADIO_HOSDOWN, + RADIO_LETSGO, + RADIO_LOCKNLOAD, + RADIO_MATEDOWN, + RADIO_MEETME, + RADIO_MOVEOUT, + RADIO_NEGATIVE, + RADIO_POSITION, + RADIO_REGROUP, + RADIO_RESCUED, + RADIO_ROGER, + RADIO_ROUNDDRAW, + RADIO_STICKTOG, + RADIO_STORMFRONT, + RADIO_TAKEPOINT, + RADIO_TERWIN, + RADIO_VIP, +}; diff --git a/src/shared/w_ak47.qc b/src/shared/w_ak47.qc new file mode 100644 index 0000000..69a8582 --- /dev/null +++ b/src/shared/w_ak47.qc @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_ak47 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_ak47.mdl" + +COUNTER-STRIKE (1999) ENTITY + +AK-47 Weapon + +- Buy Menu - +Price: $2500 +Terrorists only weapon + +*/ + +enum +{ + AK47_IDLE, + AK47_RELOAD, + AK47_DRAW, + AK47_SHOOT1, + AK47_SHOOT2, + AK47_SHOOT3 +}; + +void +w_ak47_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_ak47.fire"); + precache_model("models/w_ak47.mdl"); +#else + precache_model("models/v_ak47.mdl"); + precache_model("models/p_ak47.mdl"); +#endif +} + +void +w_ak47_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.ak47_mag, pl.ammo_762mm, -1); +} + +string +w_ak47_wmodel(void) +{ + return "models/w_ak47.mdl"; +} + +string +w_ak47_pmodel(void) +{ + return "models/p_ak47.mdl"; +} + +string +w_ak47_deathmsg(void) +{ + return ""; +} + +int +w_ak47_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.ak47_mag = 30; + else + pl.ak47_mag = startammo; + } else { + if (pl.ammo_762mm < AMMO_MAX_762MM) { + pl.ammo_762mm = bound(0, pl.ammo_762mm + 30, AMMO_MAX_762MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_ak47_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_ak47.mdl"); + Weapons_ViewAnimation(AK47_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 4; + pl.cs_cross_deltadist = 4; +#endif +} + +void +w_ak47_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0) { + return; + } + if (!pl.ak47_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.ak47_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(AK47_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(AK47_SHOOT2); + break; + default: + Weapons_ViewAnimation(AK47_SHOOT3); + break; + } +#else + TraceAttack_SetPenetrationPower(1); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 36, [accuracy,accuracy], WEAPON_AK47); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_AK47, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_AK47, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_ak47.fire"); +#endif + + pl.w_attack_next = 0.0955f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_ak47_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.ak47_mag >= 30) { + return; + } + if (!pl.ammo_762mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(AK47_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::ak47_mag, player::ammo_762mm, 30); +#endif + + pl.w_attack_next = 2.4f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_ak47_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CROUCH_AIM_AK47 : ANIM_AIM_AK47; +} + +void +w_ak47_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [72/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_ak47_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.ak47_mag == 0 && pl.ammo_762mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_762mm, AMMO_MAX_762MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud11_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud11_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_ak47 = +{ + .name = "ak47", + .id = ITEM_AK47, + .slot = 0, + .slot_pos = 7, + .allow_drop = TRUE, + .draw = w_ak47_draw, + .holster = __NULL__, + .primary = w_ak47_primary, + .secondary = __NULL__, + .reload = w_ak47_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_ak47_hud, + .precache = w_ak47_precache, + .pickup = w_ak47_pickup, + .updateammo = w_ak47_updateammo, + .wmodel = w_ak47_wmodel, + .pmodel = w_ak47_pmodel, + .deathmsg = w_ak47_deathmsg, + .aimanim = w_ak47_aimanim, + .hudpic = w_ak47_hudpic +}; + +#ifdef SERVER +void +weapon_ak47(void) +{ + Weapons_InitItem(WEAPON_AK47); +} +#endif diff --git a/src/shared/w_aug.qc b/src/shared/w_aug.qc new file mode 100644 index 0000000..cc5ce23 --- /dev/null +++ b/src/shared/w_aug.qc @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_aug (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_aug.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Steyr AUG Weapon + +- Buy Menu - +Price: $3500 +Counter-Terrorists only weapon + +*/ + +enum +{ + AUG_IDLE, + AUG_RELOAD, + AUG_DRAW, + AUG_SHOOT1, + AUG_SHOOT2, + AUG_SHOOT3 +}; + +void +w_aug_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_aug.fire"); + precache_model("models/w_aug.mdl"); +#else + precache_model("models/v_aug.mdl"); + precache_model("models/p_aug.mdl"); +#endif +} + +void +w_aug_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.aug_mag, pl.ammo_762mm, -1); +} + +string +w_aug_wmodel(void) +{ + return "models/w_aug.mdl"; +} + +string +w_aug_pmodel(void) +{ + return "models/p_aug.mdl"; +} + +string +w_aug_deathmsg(void) +{ + return ""; +} + +int +w_aug_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.aug_mag = 30; + else + pl.aug_mag = startammo; + } else { + if (pl.ammo_762mm < AMMO_MAX_762MM) { + pl.ammo_762mm = bound(0, pl.ammo_762mm + 30, AMMO_MAX_762MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_aug_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_aug.mdl"); + Weapons_ViewAnimation(AUG_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 3; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_aug_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (!pl.aug_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 215); + pl.aug_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(AUG_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(AUG_SHOOT2); + break; + default: + Weapons_ViewAnimation(AUG_SHOOT3); + break; + } +#else + TraceAttack_SetPenetrationPower(1); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 32, [accuracy,accuracy], WEAPON_AUG); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_RIFLE, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_RIFLE, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_aug.fire"); +#endif + + if (pl.viewzoom == 1.0f) { + pl.w_attack_next = 0.0825f; + } else { + pl.w_attack_next = 0.15f; + } + pl.w_idle_next = pl.w_attack_next; +} + +void +w_aug_secondary(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + /* Simple toggle of fovs */ + if (pl.viewzoom == 1.0f) { + pl.viewzoom = 0.2f; + } else { + pl.viewzoom = 1.0f; + } + pl.w_attack_next = 0.5f; +} + +void +w_aug_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.aug_mag >= 30) { + return; + } + if (!pl.ammo_762mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(AUG_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::aug_mag, player::ammo_762mm, 30); +#endif + + pl.w_attack_next = 3.3f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_aug_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_aug_hud(void) +{ +#ifdef CLIENT + player pl = (player)self; + if (pl.viewzoom == 1.0f) { + Cstrike_DrawCrosshair(); + } else { + Cstrike_DrawSimpleCrosshair(); + } + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [72/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_aug_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.aug_mag == 0 && pl.ammo_762mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_762mm, AMMO_MAX_762MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud15_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud14_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_aug = +{ + .name = "aug", + .id = ITEM_AUG, + .slot = 0, + .slot_pos = 10, + .allow_drop = TRUE, + .draw = w_aug_draw, + .holster = __NULL__, + .primary = w_aug_primary, + .secondary = w_aug_secondary, + .reload = w_aug_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_aug_hud, + .precache = w_aug_precache, + .pickup = w_aug_pickup, + .updateammo = w_aug_updateammo, + .wmodel = w_aug_wmodel, + .pmodel = w_aug_pmodel, + .deathmsg = w_aug_deathmsg, + .aimanim = w_aug_aimanim, + .hudpic = w_aug_hudpic +}; + +#ifdef SERVER +void +weapon_aug(void) +{ + Weapons_InitItem(WEAPON_AUG); +} +#endif diff --git a/src/shared/w_awp.qc b/src/shared/w_awp.qc new file mode 100644 index 0000000..475b47a --- /dev/null +++ b/src/shared/w_awp.qc @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_awp (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_awp.mdl" + +COUNTER-STRIKE (1999) ENTITY + +AWP (AI Arctic Warfare/Magnum) Weapon + +- Buy Menu - +Price: $4750 + +*/ + +enum +{ + AWP_IDLE, + AWP_SHOOT1, + AWP_SHOOT2, + AWP_SHOOT3, + AWP_RELOAD, + AWP_DRAW +}; + +void +w_awp_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_awp.fire"); + Sound_Precache("weapon_awp.zoom"); + precache_model("models/w_awp.mdl"); +#else + precache_model("models/v_awp.mdl"); + precache_model("models/p_awp.mdl"); +#endif +} + +void +w_awp_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.awp_mag, pl.ammo_338mag, pl.mode_temp); +} + +string +w_awp_wmodel(void) +{ + return "models/w_awp.mdl"; +} + +string +w_awp_pmodel(void) +{ + return "models/p_awp.mdl"; +} + +string +w_awp_deathmsg(void) +{ + return ""; +} + +int +w_awp_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.awp_mag = 10; + else + pl.awp_mag = startammo; + } else { + if (pl.ammo_338mag < 20) { + pl.ammo_338mag = bound(0, pl.ammo_338mag + 10, 20); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_awp_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_awp.mdl"); + Weapons_ViewAnimation(AWP_DRAW); + pl.mode_temp = 0; + +#ifdef CLIENT + pl.cs_cross_mindist = 8; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_awp_release(void) +{ + player pl = (player)self; + + w_cstrike_weaponrelease(); + + if (pl.w_idle_next > 0.0f) { + pl.viewzoom = 1.0f; + return; + } + + if (pl.mode_temp == 1) { + pl.viewzoom = 0.45f; + } else if (pl.mode_temp == 2) { + pl.viewzoom = 0.1f; + } else { + pl.viewzoom = 1.0f; + } +} + +void +w_awp_secondary(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + +#ifdef SSQC + Sound_Play(pl, CHAN_WEAPON, "weapon_awp.zoom"); +#endif + + /* Simple toggle of fovs */ + if (pl.mode_temp == 1) { + pl.mode_temp = 2; + } else if (pl.mode_temp == 2) { + pl.mode_temp = 0; + } else { + pl.mode_temp = 1; + } + + pl.w_attack_next = 0.3f; + pl.w_idle_next = 0.0f; + w_awp_release(); +} + +void +w_awp_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + w_awp_release(); + return; + } + if (!pl.awp_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, -1); + pl.awp_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(AWP_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(AWP_SHOOT2); + break; + default: + Weapons_ViewAnimation(AWP_SHOOT3); + break; + } +#else + TraceAttack_SetPenetrationPower(2); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 115, [accuracy,accuracy], WEAPON_AWP); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_RIFLE, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_RIFLE, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_awp.fire"); +#endif + + pl.w_attack_next = 1.2f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_awp_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.awp_mag >= 10) { + return; + } + if (!pl.ammo_338mag) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(AWP_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::awp_mag, player::ammo_338mag, 10); +#endif + + pl.w_attack_next = 2.9f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_awp_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_awp_hud(void) +{ +#ifdef CLIENT + player pl = (player)self; + if (pl.viewzoom < 1.0f) { + Cstrike_DrawScope(); + } + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [24/256,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_awp_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.awp_mag == 0 && pl.ammo_338mag == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_338mag, AMMO_MAX_338MAG, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud5_spr, + [0,135/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud2_spr, + [0,135/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_awp = +{ + .name = "awp", + .id = ITEM_AWP, + .slot = 0, + .slot_pos = 12, + .allow_drop = TRUE, + .draw = w_awp_draw, + .holster = __NULL__, + .primary = w_awp_primary, + .secondary = w_awp_secondary, + .reload = w_awp_reload, + .release = w_awp_release, + .crosshair = w_awp_hud, + .precache = w_awp_precache, + .pickup = w_awp_pickup, + .updateammo = w_awp_updateammo, + .wmodel = w_awp_wmodel, + .pmodel = w_awp_pmodel, + .deathmsg = w_awp_deathmsg, + .aimanim = w_awp_aimanim, + .hudpic = w_awp_hudpic +}; + +#ifdef SERVER +void +weapon_awp(void) +{ + Weapons_InitItem(WEAPON_AWP); +} +#endif diff --git a/src/shared/w_c4bomb.qc b/src/shared/w_c4bomb.qc new file mode 100644 index 0000000..b1d9cda --- /dev/null +++ b/src/shared/w_c4bomb.qc @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_c4bomb (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_c4.mdl" + +COUNTER-STRIKE (1999) ENTITY + +C4 Bomb Weapon, Bomb Defusal Gamemode Entity + +Default arsenal for Terrorists + +Can only be picked up by Terrorists and planted in +func_bombtarget brush entities. + +*/ + +/* C4 weapon logic */ + +enum +{ + C4_IDLE, + C4_DRAW, + C4_DROP, + C4_ENTERCODE +}; + +enum +{ + C4S_NONE, + C4S_ENTERINGCODE, + C4S_DROPPING, + C4S_DONE +}; + +void +w_c4bomb_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_c4bomb.disarm"); + Sound_Precache("weapon_c4bomb.disarmed"); + Sound_Precache("weapon_c4bomb.explode"); + Sound_Precache("weapon_c4bomb.plant"); + precache_sound("weapons/c4_beep1.wav"); + precache_sound("weapons/c4_beep2.wav"); + precache_sound("weapons/c4_beep3.wav"); + precache_sound("weapons/c4_beep4.wav"); + precache_sound("weapons/c4_beep5.wav"); + precache_sound("weapons/c4_disarmed.wav"); + precache_sound("weapons/c4_disarm.wav"); + precache_model("models/w_c4.mdl"); + precache_model("models/w_backpack.mdl"); + precache_model("sprites/ledglow.spr"); +#else + precache_model("models/v_c4.mdl"); + precache_model("models/p_c4.mdl"); +#endif +} + +void +w_c4bomb_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, 1, -1); +} + +string +w_c4bomb_wmodel(void) +{ + return "models/w_backpack.mdl"; +} + +string +w_c4bomb_pmodel(void) +{ + return "models/p_c4.mdl"; +} + +string +w_c4bomb_deathmsg(void) +{ + return ""; +} + +void +w_c4bomb_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_c4.mdl"); + Weapons_ViewAnimation(C4_DRAW); + pl.mode_temp = 0; +} + +void +w_c4bomb_release(void) +{ + player pl = (player)self; + + if (pl.mode_temp == C4S_DROPPING) { + if (pl.w_idle_next <= 0.0f) { + pl.mode_temp = C4S_DONE; +#ifdef SERVER + C4Bomb_Plant(pl); + Weapons_RemoveItem(pl, WEAPON_C4BOMB); +#endif + } + return; + } + + /* reset animation */ + if (pl.mode_temp != C4S_NONE) { + Weapons_ViewAnimation(C4_IDLE); + } + pl.mode_temp = C4S_NONE; + pl.w_idle_next = 0.0f; +} + +void +w_c4bomb_primary(void) +{ + player pl = (player)self; + + if (!(pl.gflags & GF_BOMBZONE)) { + return; + } + + pl.flags |= FL_FROZEN; + + switch (pl.mode_temp) { + case C4S_NONE: + pl.mode_temp = C4S_ENTERINGCODE; + Weapons_ViewAnimation(C4_ENTERCODE); + pl.w_idle_next = 3.0f; + break; + case C4S_ENTERINGCODE: + if (pl.w_idle_next <= 0.0f) { + pl.mode_temp = C4S_DROPPING; + Weapons_ViewAnimation(C4_DROP); + pl.w_idle_next = 1.0f; + } + break; + case C4S_DROPPING: + w_c4bomb_release(); + return; + break; + default: + break; + } + + pl.w_attack_next = 0.0f; +} + +float +w_c4bomb_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CROUCH_AIM_C4 : ANIM_AIM_C4; +} + +void +w_c4bomb_hud(void) +{ +#ifdef CLIENT + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [96/256,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_c4bomb_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud4_spr, + [0,0], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud1_spr, + [0,0], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_c4bomb = +{ + .name = "c4", + .id = ITEM_C4BOMB, + .slot = 4, + .slot_pos = 0, + .allow_drop = TRUE, + .draw = w_c4bomb_draw, + .holster = __NULL__, + .primary = w_c4bomb_primary, + .secondary = __NULL__, + .reload = __NULL__, + .release = w_c4bomb_release, + .crosshair = w_c4bomb_hud, + .precache = w_c4bomb_precache, + .pickup = __NULL__, + .updateammo = w_c4bomb_updateammo, + .wmodel = w_c4bomb_wmodel, + .pmodel = w_c4bomb_pmodel, + .deathmsg = w_c4bomb_deathmsg, + .aimanim = w_c4bomb_aimanim, + .hudpic = w_c4bomb_hudpic +}; + +#ifdef SERVER +void +weapon_c4bomb(void) +{ + Weapons_InitItem(WEAPON_C4BOMB); +} +#endif diff --git a/src/shared/w_deagle.qc b/src/shared/w_deagle.qc new file mode 100644 index 0000000..d0b720f --- /dev/null +++ b/src/shared/w_deagle.qc @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_deagle (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_deagle.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Desert Eagle .50 AE Weapon + +- Buy Menu - +Price: $650 + +*/ + +enum +{ + DEAGLE_IDLE, + DEAGLE_SHOOT1, + DEAGLE_SHOOT2, + DEAGLE_SHOOT_EMPTY, + DEAGLE_RELOAD, + DEAGLE_DRAW +}; + +void +w_deagle_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_deagle.fire"); + precache_model("models/w_deagle.mdl"); +#else + precache_model("models/v_deagle.mdl"); + precache_model("models/p_deagle.mdl"); +#endif +} + +void +w_deagle_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.deagle_mag, pl.ammo_50ae, -1); +} + +string +w_deagle_wmodel(void) +{ + return "models/w_deagle.mdl"; +} + +string +w_deagle_pmodel(void) +{ + return "models/p_deagle.mdl"; +} + +string +w_deagle_deathmsg(void) +{ + return ""; +} + +int +w_deagle_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.deagle_mag = 7; + else + pl.deagle_mag = startammo; + } else { + if (pl.ammo_50ae < AMMO_MAX_50AE) { + pl.ammo_50ae = bound(0, pl.ammo_50ae + 7, AMMO_MAX_50AE); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_deagle_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_deagle.mdl"); + Weapons_ViewAnimation(DEAGLE_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 8; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_deagle_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + if (pl.gflags & GF_SEMI_TOGGLED) { + return; + } + if (!pl.deagle_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.deagle_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + if (pl.deagle_mag <= 0) { + Weapons_ViewAnimation(DEAGLE_SHOOT_EMPTY); + } else { + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(DEAGLE_SHOOT1); + break; + default: + Weapons_ViewAnimation(DEAGLE_SHOOT2); + break; + } + } +#else + TraceAttack_SetPenetrationPower(1); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 54, [accuracy,accuracy], WEAPON_DEAGLE); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_ONEHAND, 0.45f); + else + Animation_PlayerTopTemp(ANIM_SHOOT_ONEHAND, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_deagle.fire"); +#endif + + pl.gflags |= GF_SEMI_TOGGLED; + pl.w_attack_next = 0.15f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_deagle_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.deagle_mag >= 7) { + return; + } + if (!pl.ammo_50ae) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(DEAGLE_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::deagle_mag, player::ammo_50ae, 7); +#endif + + pl.w_attack_next = 2.1f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_deagle_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CROUCH_AIM_ONEHAND : ANIM_AIM_ONEHAND; +} + +void +w_deagle_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [24/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_deagle_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.deagle_mag == 0 && pl.ammo_50ae == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_50ae, AMMO_MAX_50AE, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud11_spr, + [0,90/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud10_spr, + [0,90/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_deagle = +{ + .name = "deagle", + .id = ITEM_DEAGLE, + .slot = 1, + .slot_pos = 2, + .allow_drop = TRUE, + .draw = w_deagle_draw, + .holster = __NULL__, + .primary = w_deagle_primary, + .secondary = __NULL__, + .reload = w_deagle_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_deagle_hud, + .precache = w_deagle_precache, + .pickup = w_deagle_pickup, + .updateammo = w_deagle_updateammo, + .wmodel = w_deagle_wmodel, + .pmodel = w_deagle_pmodel, + .deathmsg = w_deagle_deathmsg, + .aimanim = w_deagle_aimanim, + .hudpic = w_deagle_hudpic +}; + +#ifdef SERVER +void +weapon_deagle(void) +{ + Weapons_InitItem(WEAPON_DEAGLE); +} +#endif diff --git a/src/shared/w_elites.qc b/src/shared/w_elites.qc new file mode 100644 index 0000000..f4cadda --- /dev/null +++ b/src/shared/w_elites.qc @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_elites (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_elite.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Dual Beretta 96G (Elites) Weapon + +- Buy Menu - +Price: $1000 + +*/ + +enum +{ + ELITES_IDLE, + ELITES_IDLE_LEFTEMPTY, + ELITES_SHOOT_LEFT1, + ELITES_SHOOT_LEFT2, + ELITES_SHOOT_LEFT3, + ELITES_SHOOT_LEFT4, + ELITES_SHOOT_LEFT5, + ELITES_SHOOT_LEFTLAST, + ELITES_SHOOT_RIGHT1, + ELITES_SHOOT_RIGHT2, + ELITES_SHOOT_RIGHT3, + ELITES_SHOOT_RIGHT4, + ELITES_SHOOT_RIGHT5, + ELITES_SHOOT_RIGHTLAST, + ELITES_RELOAD, + ELITES_DRAW +}; + +void +w_elites_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_elites.fire"); + precache_model("models/w_elite.mdl"); +#else + precache_model("models/v_elite.mdl"); + precache_model("models/p_elite.mdl"); +#endif +} + +void +w_elites_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.elites_mag, pl.ammo_9mm, -1); +} + +string +w_elites_wmodel(void) +{ + return "models/w_elites.mdl"; +} + +string +w_elites_pmodel(void) +{ + return "models/p_elites.mdl"; +} + +string +w_elites_deathmsg(void) +{ + return ""; +} + +int +w_elites_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.elites_mag = 30; + else + pl.elites_mag = startammo; + } else { + if (pl.ammo_9mm < AMMO_MAX_9MM) { + pl.ammo_9mm = bound(0, pl.ammo_9mm + 30, AMMO_MAX_9MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_elites_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_elite.mdl"); + Weapons_ViewAnimation(ELITES_DRAW); + pl.mode_temp = 0; + +#ifdef CLIENT + pl.cs_cross_mindist = 4; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_elites_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.gflags & GF_SEMI_TOGGLED) { + return; + } + if (!pl.elites_mag) { + return; + } + + pl.mode_temp = 1 - pl.mode_temp; + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.elites_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 5; + if (pl.mode_temp) { + if (pl.elites_mag <= 0) { + Weapons_ViewAnimation(ELITES_SHOOT_LEFTLAST); + } else { + switch (r) { + case 0: + Weapons_ViewAnimation(ELITES_SHOOT_LEFT1); + break; + case 1: + Weapons_ViewAnimation(ELITES_SHOOT_LEFT2); + break; + case 2: + Weapons_ViewAnimation(ELITES_SHOOT_LEFT3); + break; + case 3: + Weapons_ViewAnimation(ELITES_SHOOT_LEFT4); + break; + default: + Weapons_ViewAnimation(ELITES_SHOOT_LEFT1); + break; + } + } + } else { + if (pl.elites_mag <= 0) { + Weapons_ViewAnimation(ELITES_SHOOT_RIGHTLAST); + } else { + switch (r) { + case 0: + Weapons_ViewAnimation(ELITES_SHOOT_RIGHT1); + break; + case 1: + Weapons_ViewAnimation(ELITES_SHOOT_RIGHT2); + break; + case 2: + Weapons_ViewAnimation(ELITES_SHOOT_RIGHT3); + break; + case 3: + Weapons_ViewAnimation(ELITES_SHOOT_RIGHT4); + break; + default: + Weapons_ViewAnimation(ELITES_SHOOT_RIGHT1); + break; + } + } + } +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 45, [accuracy,accuracy], WEAPON_ELITES); + + if (self.flags & FL_CROUCHING) { + if (pl.mode_temp) + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT2_DUALPISTOLS, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_DUALPISTOLS, 0.45f); + } else { + if (pl.mode_temp) + Animation_PlayerTopTemp(ANIM_SHOOT2_DUALPISTOLS, 0.45f); + else + Animation_PlayerTopTemp(ANIM_SHOOT_DUALPISTOLS, 0.45f); + } + + Sound_Play(pl, CHAN_WEAPON, "weapon_elites.fire"); +#endif + + pl.gflags |= GF_SEMI_TOGGLED; + pl.w_attack_next = 0.15f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_elites_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.elites_mag >= 30) { + return; + } + if (!pl.ammo_9mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(ELITES_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::elites_mag, player::ammo_9mm, 30); +#endif + + pl.w_attack_next = 4.6f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_elites_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CROUCH_AIM_DUALPISTOLS : ANIM_AIM_DUALPISTOLS; +} + +void +w_elites_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [48/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_elites_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.elites_mag == 0 && pl.ammo_9mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_9mm, AMMO_MAX_9MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud15_spr, + [0,90/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud14_spr, + [0,90/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_elites = +{ + .name = "elites", + .id = ITEM_ELITES, + .slot = 1, + .slot_pos = 4, + .allow_drop = TRUE, + .draw = w_elites_draw, + .holster = __NULL__, + .primary = w_elites_primary, + .secondary = __NULL__, + .reload = w_elites_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_elites_hud, + .precache = w_elites_precache, + .pickup = w_elites_pickup, + .updateammo = w_elites_updateammo, + .wmodel = w_elites_wmodel, + .pmodel = w_elites_pmodel, + .deathmsg = w_elites_deathmsg, + .aimanim = w_elites_aimanim, + .hudpic = w_elites_hudpic +}; + +#ifdef SERVER +void +weapon_elites(void) +{ + Weapons_InitItem(WEAPON_ELITES); +} +#endif diff --git a/src/shared/w_fiveseven.qc b/src/shared/w_fiveseven.qc new file mode 100644 index 0000000..a0cc0a1 --- /dev/null +++ b/src/shared/w_fiveseven.qc @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_fiveseven (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_fiveseven.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Five-SeveN Weapon + +- Buy Menu - +Price: $750 + +*/ + +enum +{ + FIVESEVEN_IDLE, + FIVESEVEN_SHOOT1, + FIVESEVEN_SHOOT2, + FIVESEVEN_SHOOT_EMPTY, + FIVESEVEN_RELOAD, + FIVESEVEN_DRAW +}; + +void +w_fiveseven_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_fiveseven.fire"); + precache_model("models/w_fiveseven.mdl"); +#else + precache_model("models/v_fiveseven.mdl"); + precache_model("models/p_fiveseven.mdl"); +#endif +} + +void +w_fiveseven_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.fiveseven_mag, pl.ammo_57mm, -1); +} + +string +w_fiveseven_wmodel(void) +{ + return "models/w_fiveseven.mdl"; +} + +string +w_fiveseven_pmodel(void) +{ + return "models/p_fiveseven.mdl"; +} + +string +w_fiveseven_deathmsg(void) +{ + return ""; +} + +int +w_fiveseven_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.fiveseven_mag = 20; + else + pl.fiveseven_mag = startammo; + } else { + if (pl.ammo_57mm < AMMO_MAX_57MM) { + pl.ammo_57mm = bound(0, pl.ammo_57mm + 20, AMMO_MAX_57MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_fiveseven_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_fiveseven.mdl"); + Weapons_ViewAnimation(FIVESEVEN_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 8; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_fiveseven_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + if (pl.gflags & GF_SEMI_TOGGLED) { + return; + } + if (!pl.fiveseven_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.fiveseven_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + if (pl.fiveseven_mag <= 0) { + Weapons_ViewAnimation(FIVESEVEN_SHOOT_EMPTY); + } else { + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(FIVESEVEN_SHOOT1); + break; + default: + Weapons_ViewAnimation(FIVESEVEN_SHOOT2); + break; + } + } +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 25, [accuracy,accuracy], WEAPON_FIVESEVEN); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_ONEHAND, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_ONEHAND, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_fiveseven.fire"); +#endif + + pl.gflags |= GF_SEMI_TOGGLED; + pl.w_attack_next = 0.15f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_fiveseven_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.fiveseven_mag >= 20) { + return; + } + if (!pl.ammo_57mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(FIVESEVEN_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::fiveseven_mag, player::ammo_57mm, 20); +#endif + + pl.w_attack_next = 3.1f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_fiveseven_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CROUCH_AIM_ONEHAND : ANIM_AIM_ONEHAND; +} + +void +w_fiveseven_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [120/256,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_fiveseven_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.fiveseven_mag == 0 && pl.ammo_57mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_57mm, AMMO_MAX_57MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud15_spr, + [0,135/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud14_spr, + [0,135/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_fiveseven = +{ + .name = "fiveseven", + .id = ITEM_FIVESEVEN, + .slot = 1, + .slot_pos = 5, + .allow_drop = TRUE, + .draw = w_fiveseven_draw, + .holster = __NULL__, + .primary = w_fiveseven_primary, + .secondary = __NULL__, + .reload = w_fiveseven_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_fiveseven_hud, + .precache = w_fiveseven_precache, + .pickup = w_fiveseven_pickup, + .updateammo = w_fiveseven_updateammo, + .wmodel = w_fiveseven_wmodel, + .pmodel = w_fiveseven_pmodel, + .deathmsg = w_fiveseven_deathmsg, + .aimanim = w_fiveseven_aimanim, + .hudpic = w_fiveseven_hudpic +}; + +#ifdef SERVER +void +weapon_fiveseven(void) +{ + Weapons_InitItem(WEAPON_FIVESEVEN); +} +#endif diff --git a/src/shared/w_flashbang.qc b/src/shared/w_flashbang.qc new file mode 100644 index 0000000..6734d1e --- /dev/null +++ b/src/shared/w_flashbang.qc @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_flashbang (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_flashbang.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Concussion (Flashbang) Grenade Weapon + +When thrown, nearby players become blinded temporarily from the blast. + +- Buy Menu - +Price: $200 + +*/ + +enum +{ + FLASHBANG_IDLE, + FLASHBANG_PULLPIN, + FLASHBANG_THROW, + FLASHBANG_DRAW, +}; + +void +w_flashbang_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_flashbang.bounce"); + Sound_Precache("weapon_flashbang.explode"); + precache_model("models/w_flashbang.mdl"); +#else + precache_model("models/v_flashbang.mdl"); + precache_model("models/p_flashbang.mdl"); +#endif +} + +void +w_flashbang_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, pl.ammo_fbgrenade, pl.mode_temp); +} + +int +w_flashbang_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (pl.ammo_fbgrenade < AMMO_MAX_FLASHBANG) { + pl.ammo_fbgrenade = bound(0, pl.ammo_fbgrenade + 1, AMMO_MAX_FLASHBANG); + } else { + return FALSE; + } +#endif + return TRUE; +} + +string +w_flashbang_wmodel(void) +{ + return "models/w_flashbang.mdl"; +} + +string +w_flashbang_pmodel(void) +{ + return "models/p_flashbang.mdl"; +} + +string +w_flashbang_deathmsg(void) +{ + return ""; +} + +void +w_flashbang_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_flashbang.mdl"); + Weapons_ViewAnimation(FLASHBANG_DRAW); + pl.mode_temp = 0; +} + +#ifdef SERVER +void w_flashbang_throw(void) +{ + static void flashbang_explode(void) + { + FX_Flashbang(self.origin); + Sound_Play(self, CHAN_BODY, "weapon_flashbang.explode"); + remove(self); + } + + static void flashbang_touch(void) + { + if (other.takedamage == DAMAGE_YES) { + Damage_Apply(other, self.owner, 15, WEAPON_FLASHBANG, DMG_BLUNT); + } else { + Sound_Play(self, CHAN_BODY, "weapon_flashbang.bounce"); + } + self.frame = 0; + } + + player pl = (player)self; + vector vPLAngle = pl.v_angle; + if (vPLAngle[0] < 0) { + vPLAngle[0] = -10 + vPLAngle[0] * ((90 - 10) / 90.0); + } else { + vPLAngle[0] = -10 + vPLAngle[0] * ((90 + 10) / 90.0); + } + + float flVel = (90 - vPLAngle[0]) * 5; + if (flVel > 1000) { + flVel = 1000; + } + + makevectors(vPLAngle); + vector vecSrc = pl.origin + pl.view_ofs + v_forward * 16; + vector vecThrow = v_forward * flVel + pl.velocity; + + entity eGrenade = spawn(); + eGrenade.owner = pl; + eGrenade.classname = "remove_me"; + eGrenade.solid = SOLID_BBOX; + eGrenade.frame = 1; + eGrenade.velocity = vecThrow; + eGrenade.movetype = MOVETYPE_BOUNCE; + eGrenade.think = flashbang_explode; + eGrenade.touch = flashbang_touch; + eGrenade.nextthink = time + 4.0f; + setmodel(eGrenade, "models/w_flashbang.mdl"); + setsize(eGrenade, [0,0,0], [0,0,0]); + setorigin(eGrenade, vecSrc); +} +#endif + +void +w_flashbang_primary(void) +{ + player pl = (player)self; + if (pl.w_attack_next > 0.0) { + return; + } + + /* We're abusing this network variable for the holding check */ + if (pl.mode_temp > 0) { + return; + } + + /* Ammo check */ + if (pl.ammo_fbgrenade <= 0) { + return; + } + + Weapons_ViewAnimation(FLASHBANG_PULLPIN); + + pl.mode_temp = 1; + pl.w_attack_next = 0.975f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_flashbang_release(void) +{ + player pl = (player)self; + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.mode_temp == 1) { + pl.ammo_fbgrenade--; +#ifdef CLIENT + Weapons_ViewAnimation(FLASHBANG_THROW); +#else + w_flashbang_throw(); +#endif + pl.mode_temp = 2; + pl.w_attack_next = 1.0f; + pl.w_idle_next = 0.5f; + } else if (pl.mode_temp == 2) { +#ifdef CLIENT + Weapons_ViewAnimation(FLASHBANG_DRAW); +#else + if (!pl.ammo_fbgrenade) { + Weapons_RemoveItem(pl, WEAPON_FLASHBANG); + } +#endif + pl.w_attack_next = 0.5f; + pl.w_idle_next = 0.5f; + pl.mode_temp = 0; + } +} + +float +w_flashbang_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CROUCH_AIM_GRENADE : ANIM_AIM_GRENADE; +} + +void +w_flashbang_hud(void) +{ +#ifdef CLIENT + + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [48/256,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_flashbang_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + + HUD_DrawAmmoBar(pos, pl.ammo_fbgrenade, AMMO_MAX_FLASHBANG, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud6_spr, + [0,90/256], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud3_spr, + [0,90/256], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_flashbang = +{ + .name = "flashbang", + .id = ITEM_FLASHBANG, + .slot = 3, + .slot_pos = 1, + .allow_drop = FALSE, + .draw = w_flashbang_draw, + .holster = __NULL__, + .primary = w_flashbang_primary, + .secondary = __NULL__, + .reload = __NULL__, + .release = w_flashbang_release, + .crosshair = w_flashbang_hud, + .precache = w_flashbang_precache, + .pickup = w_flashbang_pickup, + .updateammo = w_flashbang_updateammo, + .wmodel = w_flashbang_wmodel, + .pmodel = w_flashbang_pmodel, + .deathmsg = w_flashbang_deathmsg, + .aimanim = w_flashbang_aimanim, + .hudpic = w_flashbang_hudpic +}; + +#ifdef SERVER +void +weapon_flashbang(void) +{ + Weapons_InitItem(WEAPON_FLASHBANG); +} +#endif diff --git a/src/shared/w_g3sg1.qc b/src/shared/w_g3sg1.qc new file mode 100644 index 0000000..a0688bc --- /dev/null +++ b/src/shared/w_g3sg1.qc @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_g3sg1 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_g3sg1.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Heckler & Koch G3/SG-1 Weapon + +- Buy Menu - +Price: $5000 + +*/ + +enum +{ + G3SG1_IDLE, + G3SG1_SHOOT1, + G3SG1_SHOOT2, + G3SG1_RELOAD, + G3SG1_DRAW +}; + +void +w_g3sg1_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_g3sg1.fire"); + precache_model("models/w_g3sg1.mdl"); +#else + precache_model("models/v_g3sg1.mdl"); + precache_model("models/p_g3sg1.mdl"); +#endif +} + +void +w_g3sg1_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.g3sg1_mag, pl.ammo_762mm, -1); +} + +string +w_g3sg1_wmodel(void) +{ + return "models/w_g3sg1.mdl"; +} + +string +w_g3sg1_pmodel(void) +{ + return "models/p_g3sg1.mdl"; +} + +string +w_g3sg1_deathmsg(void) +{ + return ""; +} + +int +w_g3sg1_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.g3sg1_mag = 20; + else + pl.g3sg1_mag = startammo; + } else { + if (pl.ammo_762mm < AMMO_MAX_762MM) { + pl.ammo_762mm = bound(0, pl.ammo_762mm + 20, AMMO_MAX_762MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_g3sg1_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_g3sg1.mdl"); + Weapons_ViewAnimation(G3SG1_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 6; + pl.cs_cross_deltadist = 4; +#endif +} + +void +w_g3sg1_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (!pl.g3sg1_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.g3sg1_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(SCOUT_SHOOT1); + break; + default: + Weapons_ViewAnimation(SCOUT_SHOOT2); + break; + } +#else + TraceAttack_SetPenetrationPower(2); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 80, [accuracy,accuracy], WEAPON_G3SG1); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_RIFLE, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_RIFLE, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_g3sg1.fire"); +#endif + + pl.w_attack_next = 0.25f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_g3sg1_secondary(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + /* Simple toggle of fovs */ + if (pl.viewzoom == 1.0f) { + pl.viewzoom = 0.45f; + } else if (pl.viewzoom == 0.45f) { + pl.viewzoom = 0.1f; + } else { + pl.viewzoom = 1.0f; + } + pl.w_attack_next = 0.5f; +} + +void +w_g3sg1_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.g3sg1_mag >= 20) { + return; + } + if (!pl.ammo_762mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(G3SG1_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::g3sg1_mag, player::ammo_762mm, 20); + Weapons_UpdateAmmo(pl, pl.g3sg1_mag, pl.ammo_762mm, -1); +#endif + + pl.w_attack_next = 4.6f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_g3sg1_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_g3sg1_hud(void) +{ +#ifdef CLIENT + player pl = (player)self; + if (pl.viewzoom < 1.0f) { + Cstrike_DrawScope(); + } + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [72/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_g3sg1_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.g3sg1_mag == 0 && pl.ammo_762mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_762mm, AMMO_MAX_762MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud5_spr, + [0,180/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud2_spr, + [0,180/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_g3sg1 = +{ + .name = "g3sg1", + .id = ITEM_G3SG1, + .slot = 0, + .slot_pos = 13, + .allow_drop = TRUE, + .draw = w_g3sg1_draw, + .holster = __NULL__, + .primary = w_g3sg1_primary, + .secondary = w_g3sg1_secondary, + .reload = w_g3sg1_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_g3sg1_hud, + .precache = w_g3sg1_precache, + .pickup = w_g3sg1_pickup, + .updateammo = w_g3sg1_updateammo, + .wmodel = w_g3sg1_wmodel, + .pmodel = w_g3sg1_pmodel, + .deathmsg = w_g3sg1_deathmsg, + .aimanim = w_g3sg1_aimanim, + .hudpic = w_g3sg1_hudpic +}; + +#ifdef SERVER +void +weapon_g3sg1(void) +{ + Weapons_InitItem(WEAPON_G3SG1); +} +#endif diff --git a/src/shared/w_glock18.qc b/src/shared/w_glock18.qc new file mode 100644 index 0000000..07de738 --- /dev/null +++ b/src/shared/w_glock18.qc @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_glock18 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_glock18.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Glock 18 Select Fire Weapon + +Default arsenal for Terrorists + +- Buy Menu - +Price: $400 + +*/ + +enum +{ + GLOCK_IDLE1, + GLOCK_IDLE2, + GLOCK_IDLE3, + GLOCK_SHOOT_BURST1, + GLOCK_SHOOT_BURST2, + GLOCK_SHOOT, + GLOCK_SHOOT_EMPTY, + GLOCK_RELOAD1, + GLOCK_DRAW1, + GLOCK_UNUSED1, + GLOCK_UNUSED2, + GLOCK_DRAW2, + GLOCK_RELOAD2 +}; + +void +w_glock18_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_glock18.fire"); + Sound_Precache("weapon_glock18.burstfire"); + precache_model("models/w_glock18.mdl"); +#else + precache_model("models/v_glock18.mdl"); + precache_model("models/p_glock18.mdl"); +#endif +} + +void +w_glock18_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.glock18_mag, pl.ammo_9mm, -1); +} + +string +w_glock18_wmodel(void) +{ + return "models/w_glock18.mdl"; +} + +string +w_glock18_pmodel(void) +{ + return "models/p_glock18.mdl"; +} + +string +w_glock18_deathmsg(void) +{ + return ""; +} + +int +w_glock18_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.glock18_mag = 20; + else + pl.glock18_mag = startammo; + } else { + if (pl.ammo_9mm < AMMO_MAX_9MM) { + pl.ammo_9mm = bound(0, pl.ammo_9mm + 20, AMMO_MAX_9MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_glock18_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_glock18.mdl"); + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(GLOCK_DRAW1); + break; + default: + Weapons_ViewAnimation(GLOCK_DRAW2); + break; + } + +#ifdef CLIENT + pl.cs_cross_mindist = 8; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_glock18_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + if (pl.gflags & GF_SEMI_TOGGLED) { + return; + } + if (!pl.glock18_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.glock18_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 25, [accuracy,accuracy], WEAPON_GLOCK18); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_ONEHAND, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_ONEHAND, 0.45f); + + if (pl.mode_glock18) { + Sound_Play(pl, CHAN_WEAPON, "weapon_glock18.burstfire"); + } else { + Sound_Play(pl, CHAN_WEAPON, "weapon_glock18.fire"); + } +#endif + + if (pl.mode_glock18) { + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(GLOCK_SHOOT_BURST1); + break; + default: + Weapons_ViewAnimation(GLOCK_SHOOT_BURST2); + break; + } + pl.w_attack_next = 0.5f; + } else { + if (pl.glock18_mag <= 0) { + Weapons_ViewAnimation(GLOCK_SHOOT_EMPTY); + } else { + Weapons_ViewAnimation(GLOCK_SHOOT); + } + pl.w_attack_next = 0.15f; + } + pl.gflags |= GF_SEMI_TOGGLED; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_glock18_secondary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0) { + return; + } + + /* toggle burst-fire */ + pl.mode_glock18 = 1 - pl.mode_glock18; + +#ifdef CLIENT + if (pl.mode_glock18) { + CSQC_Parse_CenterPrint("Switched to Burst-Fire mode"); + } else { + CSQC_Parse_CenterPrint("Switched to Semi-Automatic mode"); + } +#endif + + pl.w_attack_next = 1.0f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_glock18_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.glock18_mag >= 20) { + return; + } + if (!pl.ammo_9mm) { + return; + } + +#ifdef CLIENT + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(GLOCK_RELOAD1); + break; + default: + Weapons_ViewAnimation(GLOCK_RELOAD2); + break; + } +#else + + Weapons_ReloadWeapon(pl, player::glock18_mag, player::ammo_9mm, 20); + Weapons_UpdateAmmo(pl, pl.glock18_mag, pl.ammo_9mm, -1); +#endif + + pl.w_attack_next = 2.1f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_glock18_aimanim(void) +{ + return w_deagle_aimanim(); +} + +void +w_glock18_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [48/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_glock18_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.glock18_mag == 0 && pl.ammo_9mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_9mm, AMMO_MAX_9MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud4_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud1_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_glock18 = +{ + .name = "glock18", + .id = ITEM_GLOCK18, + .slot = 1, + .slot_pos = 1, + .allow_drop = TRUE, + .draw = w_glock18_draw, + .holster = __NULL__, + .primary = w_glock18_primary, + .secondary = w_glock18_secondary, + .reload = w_glock18_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_glock18_hud, + .precache = w_glock18_precache, + .pickup = w_glock18_pickup, + .updateammo = w_glock18_updateammo, + .wmodel = w_glock18_wmodel, + .pmodel = w_glock18_pmodel, + .deathmsg = w_glock18_deathmsg, + .aimanim = w_glock18_aimanim, + .hudpic = w_glock18_hudpic +}; + +#ifdef SERVER +void +weapon_glock18(void) +{ + Weapons_InitItem(WEAPON_GLOCK18); +} +#endif diff --git a/src/shared/w_hegrenade.qc b/src/shared/w_hegrenade.qc new file mode 100644 index 0000000..3340a30 --- /dev/null +++ b/src/shared/w_hegrenade.qc @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_hegrenade (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_hegrenade.mdl" + +COUNTER-STRIKE (1999) ENTITY + +HE (High Explosive) Grenade Weapon + +When thrown, explodes with a fairly deadly blast radius to players. + +- Buy Menu - +Price: $300 + +*/ + +enum +{ + HEGRENADE_IDLE, + HEGRENADE_PULLPIN, + HEGRENADE_THROW, + HEGRENADE_DRAW, +}; + +void +w_hegrenade_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_hegrenade.bounce"); + Sound_Precache("weapon_hegrenade.explode"); + precache_model("models/w_hegrenade.mdl"); +#else + precache_model("models/v_hegrenade.mdl"); + precache_model("models/p_hegrenade.mdl"); +#endif +} + +void +w_hegrenade_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, pl.ammo_hegrenade, pl.mode_temp); +} + +int +w_hegrenade_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (pl.ammo_hegrenade < AMMO_MAX_HENADE) { + pl.ammo_hegrenade = bound(0, pl.ammo_hegrenade + 1, AMMO_MAX_HENADE); + } else { + return FALSE; + } +#endif + return TRUE; +} + +string +w_hegrenade_wmodel(void) +{ + return "models/w_hegrenade.mdl"; +} + +string +w_hegrenade_pmodel(void) +{ + return "models/p_hegrenade.mdl"; +} + +string +w_hegrenade_deathmsg(void) +{ + return ""; +} + +void +w_hegrenade_draw(void) +{ + Weapons_SetModel("models/v_hegrenade.mdl"); + Weapons_ViewAnimation(HEGRENADE_DRAW); + player pl = (player)self; + pl.mode_temp = 0; +} + +#ifdef SERVER +void w_hegrenade_throw(void) +{ + static void hegrenade_explode(void) + { + float dmg = 100; + FX_Explosion(self.origin); + Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_HEGRENADE); + Sound_Play(self, CHAN_BODY, "weapon_hegrenade.explode"); + remove(self); + } + + static void hegrenade_touch(void) + { + if (other.takedamage == DAMAGE_YES) { + Damage_Apply(other, self.owner, 15, WEAPON_HEGRENADE, DMG_BLUNT); + } else { + Sound_Play(self, CHAN_BODY, "weapon_hegrenade.bounce"); + } + self.frame = 0; + } + + player pl = (player)self; + vector vPLAngle = pl.v_angle; + if (vPLAngle[0] < 0) { + vPLAngle[0] = -10 + vPLAngle[0] * ((90 - 10) / 90.0); + } else { + vPLAngle[0] = -10 + vPLAngle[0] * ((90 + 10) / 90.0); + } + + float flVel = (90 - vPLAngle[0]) * 5; + if (flVel > 1000) { + flVel = 1000; + } + + makevectors(vPLAngle); + vector vecSrc = pl.origin + pl.view_ofs + v_forward * 16; + vector vecThrow = v_forward * flVel + pl.velocity; + + entity eGrenade = spawn(); + eGrenade.owner = pl; + eGrenade.classname = "remove_me"; + eGrenade.solid = SOLID_BBOX; + eGrenade.frame = 1; + eGrenade.velocity = vecThrow; + eGrenade.movetype = MOVETYPE_BOUNCE; + eGrenade.think = hegrenade_explode; + eGrenade.touch = hegrenade_touch; + eGrenade.nextthink = time + 4.0f; + setmodel(eGrenade, "models/w_hegrenade.mdl"); + setsize(eGrenade, [0,0,0], [0,0,0]); + setorigin(eGrenade, vecSrc); +} +#endif + +void +w_hegrenade_primary(void) +{ + player pl = (player)self; + if (pl.w_attack_next > 0.0) { + return; + } + + /* We're abusing this network variable for the holding check */ + if (pl.mode_temp > 0) { + return; + } + + /* Ammo check */ +#ifdef CLIENT + if (pl.ammo_hegrenade <= 0) { + return; + } +#else + if (pl.ammo_hegrenade <= 0) { + return; + } +#endif + + Weapons_ViewAnimation(HEGRENADE_PULLPIN); + + pl.mode_temp = 1; + pl.w_attack_next = 0.975f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_hegrenade_release(void) +{ + player pl = (player)self; + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.mode_temp == 1) { +#ifdef CLIENT + pl.ammo_hegrenade--; + Weapons_ViewAnimation(HEGRENADE_THROW); +#else + pl.ammo_hegrenade--; + w_hegrenade_throw(); +#endif + pl.mode_temp = 2; + pl.w_attack_next = 1.0f; + pl.w_idle_next = 0.5f; + } else if (pl.mode_temp == 2) { +#ifdef CLIENT + Weapons_ViewAnimation(HEGRENADE_DRAW); +#else + if (!pl.ammo_hegrenade) { + Weapons_RemoveItem(pl, WEAPON_HEGRENADE); + } +#endif + pl.w_attack_next = 0.5f; + pl.w_idle_next = 0.5f; + pl.mode_temp = 0; + } +} + +float +w_hegrenade_aimanim(void) +{ + return w_flashbang_aimanim(); +} + +void +w_hegrenade_hud(void) +{ +#ifdef CLIENT + + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [72/256,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_hegrenade_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + + HUD_DrawAmmoBar(pos, pl.ammo_hegrenade, AMMO_MAX_HENADE, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud6_spr, + [0,45/256], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud3_spr, + [0,45/256], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_hegrenade = +{ + .name = "hegrenade", + .id = ITEM_HEGRENADE, + .slot = 3, + .slot_pos = 0, + .allow_drop = FALSE, + .draw = w_hegrenade_draw, + .holster = __NULL__, + .primary = w_hegrenade_primary, + .secondary = __NULL__, + .reload = __NULL__, + .release = w_hegrenade_release, + .crosshair = w_hegrenade_hud, + .precache = w_hegrenade_precache, + .pickup = w_hegrenade_pickup, + .updateammo = w_hegrenade_updateammo, + .wmodel = w_hegrenade_wmodel, + .pmodel = w_hegrenade_pmodel, + .deathmsg = w_hegrenade_deathmsg, + .aimanim = w_hegrenade_aimanim, + .hudpic = w_hegrenade_hudpic +}; + +#ifdef SERVER +void +weapon_hegrenade(void) +{ + Weapons_InitItem(WEAPON_HEGRENADE); +} +#endif diff --git a/src/shared/w_knife.qc b/src/shared/w_knife.qc new file mode 100644 index 0000000..ad8547c --- /dev/null +++ b/src/shared/w_knife.qc @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_knife (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_knife.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Knife Weapon + +Default arsenal on both teams + +*/ + +enum +{ + KNIFE_IDLE1, + KNIFE_SLASH1, + KNIFE_SLASH2, + KNIFE_DRAW, + KNIFE_STAB, + KNIFE_STAB_MISS, + KNIFE_MIDSLASH1, + KNIFE_MIDSLASH2 +}; + +void +w_knife_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_knife.hit"); + Sound_Precache("weapon_knife.hitbody"); + Sound_Precache("weapon_knife.hithard"); + Sound_Precache("weapon_knife.miss"); + precache_model("models/w_knife.mdl"); +#else + precache_model("models/v_knife.mdl"); + precache_model("models/p_knife.mdl"); +#endif +} + +void +w_knife_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, -1, -1); +} + +string +w_knife_wmodel(void) +{ + return "models/w_knife.mdl"; +} + +string +w_knife_pmodel(void) +{ + return "models/p_knife.mdl"; +} + +string +w_knife_deathmsg(void) +{ + return ""; +} + +void +w_knife_draw(void) +{ +#ifdef CLIENT + Weapons_SetModel("models/v_knife.mdl"); + Weapons_ViewAnimation(KNIFE_DRAW); +#endif +} + +void +w_knife_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + pl.w_attack_next = 0.7f; + +#ifdef CLIENT + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(KNIFE_SLASH1); + break; + default: + Weapons_ViewAnimation(KNIFE_SLASH2); + break; + } +#else + vector src; + Weapons_MakeVectors(); + src = pl.origin + pl.view_ofs; + traceline(src, src + (v_forward * 32), FALSE, pl); + + Sound_Play(pl, CHAN_WEAPON, "weapon_knife.miss"); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_KNIFE, 0.45f); + else + Animation_PlayerTopTemp(ANIM_SHOOT_KNIFE, 0.45f); + + if (trace_fraction >= 1.0) { + return; + } + + if (trace_ent.iBleeds) { + FX_Blood(trace_endpos, [1,0,0]); + Sound_Play(pl, CHAN_WEAPON, "weapon_knife.hitbody"); + } else { + Sound_Play(pl, CHAN_WEAPON, "weapon_knife.hit"); + } + + if (trace_ent.takedamage) { + Damage_Apply(trace_ent, pl, 15, WEAPON_KNIFE, DMG_SLASH); + } +#endif +} + +void +w_knife_secondary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + pl.w_attack_next = 1.2f; + +#ifdef CLIENT + Weapons_ViewAnimation(KNIFE_STAB); +#else + + vector src; + Weapons_MakeVectors(); + src = pl.origin + pl.view_ofs; + traceline(src, src + (v_forward * 32), FALSE, pl); + + Sound_Play(pl, CHAN_WEAPON, "weapon_knife.miss"); + + if (trace_fraction >= 1.0) { + return; + } + + /* don't bother with decals, we got squibs */ + if (trace_ent.iBleeds) { + FX_Blood(trace_endpos, [1,0,0]); + Sound_Play(pl, CHAN_WEAPON, "weapon_knife.hitbody"); + } else { + Sound_Play(pl, CHAN_WEAPON, "weapon_knife.hit"); + } + + if (trace_ent.takedamage) { + Damage_Apply(trace_ent, pl, 65, WEAPON_KNIFE, DMG_SLASH); + } +#endif +} + +float +w_knife_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CROUCH_AIM_KNIFE : ANIM_AIM_KNIFE; +} + +void +w_knife_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud11_spr, + [0,135/256], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud10_spr, + [0,135/256], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_knife = +{ + .name = "knife", + .id = ITEM_KNIFE, + .slot = 2, + .slot_pos = 0, + .allow_drop = FALSE, + .draw = w_knife_draw, + .holster = __NULL__, + .primary = w_knife_primary, + .secondary = w_knife_secondary, + .reload = __NULL__, + .release = __NULL__, + .crosshair = __NULL__, + .precache = w_knife_precache, + .pickup = __NULL__, + .updateammo = w_knife_updateammo, + .wmodel = w_knife_wmodel, + .pmodel = w_knife_pmodel, + .deathmsg = w_knife_deathmsg, + .aimanim = w_knife_aimanim, + .hudpic = w_knife_hudpic +}; + +#ifdef SERVER +void +weapon_knife(void) +{ + Weapons_InitItem(WEAPON_KNIFE); +} +#endif diff --git a/src/shared/w_m3.qc b/src/shared/w_m3.qc new file mode 100644 index 0000000..f728555 --- /dev/null +++ b/src/shared/w_m3.qc @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_m3 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_m3.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Benneli M3 Super90 Weapon + +- Buy Menu - +Price: $1700 + +*/ + +enum +{ + M3_IDLE, + M3_SHOOT1, + M3_SHOOT2, + M3_INSERT, + M3_RELOAD_END, + M3_RELOAD_START, + M3_DRAW +}; + +enum +{ + M3S_IDLE, + M3S_RELOAD_START, + M3S_RELOAD, + M3S_RELOAD_END +}; + +void +w_m3_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_m3.fire"); + precache_model("models/w_m3.mdl"); +#else + precache_model("models/v_m3.mdl"); + precache_model("models/p_m3.mdl"); +#endif +} + +void +w_m3_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.m3_mag, pl.ammo_buckshot, -1); +} + +string +w_m3_wmodel(void) +{ + return "models/w_m3.mdl"; +} + +string +w_m3_pmodel(void) +{ + return "models/p_m3.mdl"; +} + +string +w_m3_deathmsg(void) +{ + return ""; +} + +int +w_m3_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.m3_mag = 8; + else + pl.m3_mag = startammo; + } else { + if (pl.ammo_buckshot < AMMO_MAX_BUCKSHOT) { + pl.ammo_buckshot = bound(0, pl.ammo_buckshot + 8, AMMO_MAX_BUCKSHOT); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_m3_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_m3.mdl"); + Weapons_ViewAnimation(M3_DRAW); + pl.mode_temp = 0; + +#ifdef CLIENT + pl.cs_cross_mindist = 8; + pl.cs_cross_deltadist = 6; +#endif +} + +void +w_m3_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + +#ifdef CLIENT + if (!pl.m3_mag) { + return; + } +#else + if (!pl.m3_mag) { + return; + } +#endif + + Cstrike_ShotMultiplierAdd(pl, 9); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + +#ifdef CLIENT + pl.m3_mag--; + View_SetMuzzleflash(MUZZLE_RIFLE); +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(9, pl.origin + pl.view_ofs, 26, [accuracy,accuracy], WEAPON_M3); + pl.m3_mag--; + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_SHOTGUN, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_SHOTGUN, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_m3.fire"); +#endif + + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(M3_SHOOT1); + break; + default: + Weapons_ViewAnimation(M3_SHOOT2); + break; + } + + pl.w_attack_next = 1.0f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_m3_reload(void) +{ + player pl = (player)self; +#ifdef CLIENT + if (pl.m3_mag >= 8) { + return; + } + if (pl.ammo_buckshot <= 0) { + return; + } +#else + if (pl.m3_mag >= 8) { + return; + } + if (pl.ammo_buckshot <= 0) { + return; + } +#endif + + if (pl.mode_temp > M3S_IDLE) { + return; + } + pl.mode_temp = M3S_RELOAD_START; + pl.w_idle_next = 0.0f; +} + +void +w_m3_release(void) +{ + player pl = (player)self; + + w_cstrike_weaponrelease(); + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.mode_temp == M3S_RELOAD_START) { + Weapons_ViewAnimation(M3_RELOAD_START); + pl.mode_temp = M3S_RELOAD; + pl.w_idle_next = 0.65f; + } else if (pl.mode_temp == M3S_RELOAD) { + Weapons_ViewAnimation(M3_INSERT); +#ifdef CLIENT + pl.m3_mag++; + pl.ammo_buckshot--; + + if (pl.ammo_buckshot <= 0 || pl.m3_mag >= 8) { + pl.mode_temp = M3S_RELOAD_END; + } +#else + pl.m3_mag++; + pl.ammo_buckshot--; + w_m3_updateammo(pl); + if (pl.ammo_buckshot <= 0 || pl.m3_mag >= 8) { + pl.mode_temp = M3S_RELOAD_END; + } +#endif + pl.w_idle_next = 0.5f; + } else if (pl.mode_temp == M3S_RELOAD_END) { + Weapons_ViewAnimation(M3_RELOAD_END); + pl.mode_temp = M3S_IDLE; + pl.w_idle_next = 10.0f; + pl.w_attack_next = 0.5f; + } +} + +float +w_m3_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_m3_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_m3_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.m3_mag == 0 && pl.ammo_buckshot == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_buckshot, AMMO_MAX_BUCKSHOT, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud4_spr, + [0,135/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud1_spr, + [0,135/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_m3 = +{ + .name = "m3", + .id = ITEM_M3, + .slot = 0, + .slot_pos = 0, + .allow_drop = TRUE, + .draw = w_m3_draw, + .holster = __NULL__, + .primary = w_m3_primary, + .secondary = __NULL__, + .reload = w_m3_reload, + .release = w_m3_release, + .crosshair = w_m3_hud, + .precache = w_m3_precache, + .pickup = w_m3_pickup, + .updateammo = w_m3_updateammo, + .wmodel = w_m3_wmodel, + .pmodel = w_m3_pmodel, + .deathmsg = w_m3_deathmsg, + .aimanim = w_m3_aimanim, + .hudpic = w_m3_hudpic +}; + +#ifdef SERVER +void +weapon_m3(void) +{ + Weapons_InitItem(WEAPON_M3); +} +#endif diff --git a/src/shared/w_m4a1.qc b/src/shared/w_m4a1.qc new file mode 100644 index 0000000..eba8354 --- /dev/null +++ b/src/shared/w_m4a1.qc @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_m4a1 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_m4a1.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Colt M4A1 Carbine Weapon + +- Buy Menu - +Price: $3100 +Counter-Terrorists only weapon + +*/ + +enum +{ + M4A1_IDLE, + M4A1_SHOOT1, + M4A1_SHOOT2, + M4A1_SHOOT3, + M4A1_RELOAD, + M4A1_DRAW, + M4A1_ADDSIL, + M4A1_IDLEUNSIL, + M4A1_SHOOT1UNSIL, + M4A1_SHOOT2UNSIL, + M4A1_SHOOT3UNSIL, + M4A1_RELOADUNSIL, + M4A1_DRAWUNSIL, + M4A1_DETACHSIL +}; + +void +w_m4a1_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_m4a1.fire"); + Sound_Precache("weapon_m4a1.silenced"); + precache_model("models/w_m4a1.mdl"); +#else + precache_model("models/v_m4a1.mdl"); + precache_model("models/p_m4a1.mdl"); +#endif +} + +void +w_m4a1_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.m4a1_mag, pl.ammo_556mm, -1); +} + +string +w_m4a1_wmodel(void) +{ + return "models/w_m4a1.mdl"; +} + +string +w_m4a1_pmodel(void) +{ + return "models/p_m4a1.mdl"; +} + +string +w_m4a1_deathmsg(void) +{ + return ""; +} + +int +w_m4a1_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.m4a1_mag = 30; + else + pl.m4a1_mag = startammo; + } else { + if (pl.ammo_556mm < AMMO_MAX_556MM) { + pl.ammo_556mm = bound(0, pl.ammo_556mm + 30, AMMO_MAX_556MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_m4a1_draw(void) +{ + player pl = (player)self; + + Weapons_SetModel("models/v_m4a1.mdl"); + + if (pl.mode_m4a1 == 1) { + Weapons_ViewAnimation(M4A1_DRAW); + } else { + Weapons_ViewAnimation(M4A1_DRAWUNSIL); + } + +#ifdef CLIENT + pl.cs_cross_mindist = 4; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_m4a1_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (!pl.m4a1_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 220); + pl.m4a1_mag--; + + /* actual firing */ +#ifdef CLIENT + if (pl.mode_m4a1 == 1) { + View_SetMuzzleflash(0); + } else { + View_SetMuzzleflash(MUZZLE_RIFLE); + } + + /* this stuff is predicted */ + int r = (float)input_sequence % 3; + if (pl.mode_m4a1 == 1) { + switch (r) { + case 0: + Weapons_ViewAnimation(M4A1_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(M4A1_SHOOT2); + break; + default: + Weapons_ViewAnimation(M4A1_SHOOT3); + break; + } + } else { + switch (r) { + case 0: + Weapons_ViewAnimation(M4A1_SHOOT1UNSIL); + break; + case 1: + Weapons_ViewAnimation(M4A1_SHOOT2UNSIL); + break; + default: + Weapons_ViewAnimation(M4A1_SHOOT3UNSIL); + break; + } + } +#else + /* Different sounds without silencer */ + if (pl.mode_m4a1 == 1) { + Sound_Play(pl, CHAN_WEAPON, "weapon_m4a1.silenced"); + } else { + Sound_Play(pl, CHAN_WEAPON, "weapon_m4a1.fire"); + } + + TraceAttack_SetPenetrationPower(1); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 33, [accuracy,accuracy], WEAPON_M4A1); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_RIFLE, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_RIFLE, 0.45f); +#endif + + pl.w_attack_next = 0.0875f; + pl.w_idle_next = 2.0f; +} + +void +w_m4a1_secondary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0) { + return; + } + + /* toggle silencer */ + pl.mode_m4a1 = 1 - pl.mode_m4a1; + + /* play the animation */ + if (pl.mode_m4a1) { + Weapons_ViewAnimation(M4A1_ADDSIL); + } else { + Weapons_ViewAnimation(M4A1_DETACHSIL); + } + + pl.w_attack_next = 2.0f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_m4a1_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.m4a1_mag >= 30) { + return; + } + if (!pl.ammo_556mm) { + return; + } + +#ifdef CLIENT + if (pl.mode_m4a1 == 1) { + Weapons_ViewAnimation(M4A1_RELOAD); + } else { + Weapons_ViewAnimation(M4A1_RELOADUNSIL); + } +#else + Weapons_ReloadWeapon(pl, player::m4a1_mag, player::ammo_556mm, 30); +#endif + + pl.w_attack_next = 3.1f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_m4a1_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_m4a1_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_m4a1_release(void) +{ + player pl = (player)self; + + w_cstrike_weaponrelease(); + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.mode_m4a1) { + Weapons_ViewAnimation(M4A1_IDLE); + } else { + Weapons_ViewAnimation(M4A1_IDLEUNSIL); + } + pl.w_idle_next = 5.0f; +} + +void +w_m4a1_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.m4a1_mag == 0 && pl.ammo_556mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_556mm, AMMO_MAX_556MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud5_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud2_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_m4a1 = +{ + .name = "m4a1", + .id = ITEM_M4A1, + .slot = 0, + .slot_pos = 9, + .allow_drop = TRUE, + .draw = w_m4a1_draw, + .holster = __NULL__, + .primary = w_m4a1_primary, + .secondary = w_m4a1_secondary, + .reload = w_m4a1_reload, + .release = w_m4a1_release, + .crosshair = w_m4a1_hud, + .precache = w_m4a1_precache, + .pickup = w_m4a1_pickup, + .updateammo = w_m4a1_updateammo, + .wmodel = w_m4a1_wmodel, + .pmodel = w_m4a1_pmodel, + .deathmsg = w_m4a1_deathmsg, + .aimanim = w_m4a1_aimanim, + .hudpic = w_m4a1_hudpic +}; + +#ifdef SERVER +void +weapon_m4a1(void) +{ + Weapons_InitItem(WEAPON_M4A1); +} +#endif diff --git a/src/shared/w_mac10.qc b/src/shared/w_mac10.qc new file mode 100644 index 0000000..6c75472 --- /dev/null +++ b/src/shared/w_mac10.qc @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_mac10 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_mac10.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Ingram MAC-10 Weapon + +- Buy Menu - +Price: $1400 + +*/ + +enum +{ + MAC10_IDLE, + MAC10_RELOAD, + MAC10_DRAW, + MAC10_SHOOT1, + MAC10_SHOOT2, + MAC10_SHOOT3 +}; + +void +w_mac10_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_mac10.fire"); + precache_model("models/w_mac10.mdl"); +#else + precache_model("models/v_mac10.mdl"); + precache_model("models/p_mac10.mdl"); +#endif +} + +void +w_mac10_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.mac10_mag, pl.ammo_45acp, -1); +} + +string +w_mac10_wmodel(void) +{ + return "models/w_mac10.mdl"; +} + +string +w_mac10_pmodel(void) +{ + return "models/p_mac10.mdl"; +} + +string +w_mac10_deathmsg(void) +{ + return ""; +} + +int +w_mac10_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.mac10_mag = 30; + else + pl.mac10_mag = startammo; + } else { + if (pl.ammo_45acp < AMMO_MAX_45ACP) { + pl.ammo_45acp = bound(0, pl.ammo_45acp + 30, AMMO_MAX_45ACP); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_mac10_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_mac10.mdl"); + Weapons_ViewAnimation(MAC10_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 9; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_mac10_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (!pl.mac10_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.mac10_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(MAC10_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(MAC10_SHOOT2); + break; + default: + Weapons_ViewAnimation(MAC10_SHOOT3); + break; + } +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 29, [accuracy,accuracy], WEAPON_MAC10); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_MP5, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_MP5, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_mac10.fire"); +#endif + + pl.w_attack_next = 0.07f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_mac10_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.mac10_mag >= 30) { + return; + } + if (!pl.ammo_45acp) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(MAC10_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::mac10_mag, player::ammo_45acp, 30); + Weapons_UpdateAmmo(pl, pl.mac10_mag, pl.ammo_45acp, -1); +#endif + + pl.w_attack_next = 3.2f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_mac10_aimanim(void) +{ + return w_deagle_aimanim(); +} + +void +w_mac10_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [96/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_mac10_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.mac10_mag == 0 && pl.ammo_45acp == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_45acp, AMMO_MAX_45ACP, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud15_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud14_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_mac10 = +{ + .name = "mac10", + .id = ITEM_MAC10, + .slot = 0, + .slot_pos = 5, + .allow_drop = TRUE, + .draw = w_mac10_draw, + .holster = __NULL__, + .primary = w_mac10_primary, + .secondary = __NULL__, + .reload = w_mac10_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_mac10_hud, + .precache = w_mac10_precache, + .pickup = w_mac10_pickup, + .updateammo = w_mac10_updateammo, + .wmodel = w_mac10_wmodel, + .pmodel = w_mac10_pmodel, + .deathmsg = w_mac10_deathmsg, + .aimanim = w_mac10_aimanim, + .hudpic = w_mac10_hudpic +}; + +#ifdef SERVER +void +weapon_mac10(void) +{ + Weapons_InitItem(WEAPON_MAC10); +} +#endif diff --git a/src/shared/w_mp5.qc b/src/shared/w_mp5.qc new file mode 100644 index 0000000..c585234 --- /dev/null +++ b/src/shared/w_mp5.qc @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_mp5navy (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_mp5.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Heckler & Koch MP5-Navy Weapon + +- Buy Menu - +Price: $1500 + +*/ + +enum +{ + MP5_IDLE, + MP5_RELOAD, + MP5_DRAW, + MP5_SHOOT1, + MP5_SHOOT2, + MP5_SHOOT3 +}; + +void +w_mp5_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_mp5.fire"); + precache_model("models/w_mp5.mdl"); +#else + precache_model("models/v_mp5.mdl"); + precache_model("models/p_mp5.mdl"); +#endif +} + +void +w_mp5_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.mp5_mag, pl.ammo_9mm, -1); +} + +string +w_mp5_wmodel(void) +{ + return "models/w_mp5.mdl"; +} + +string +w_mp5_pmodel(void) +{ + return "models/p_mp5.mdl"; +} + +string +w_mp5_deathmsg(void) +{ + return ""; +} + +int +w_mp5_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.mp5_mag = 30; + else + pl.mp5_mag = startammo; + } else { + if (pl.ammo_9mm < AMMO_MAX_9MM) { + pl.ammo_9mm = bound(0, pl.ammo_9mm + 30, AMMO_MAX_9MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_mp5_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_mp5.mdl"); + Weapons_ViewAnimation(MP5_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 5; + pl.cs_cross_deltadist = 2; +#endif +} + +void +w_mp5_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (!pl.mp5_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 220); + pl.mp5_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(MP5_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(MP5_SHOOT2); + break; + default: + Weapons_ViewAnimation(MP5_SHOOT3); + break; + } +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 26, [accuracy,accuracy], WEAPON_MP5); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_MP5, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_MP5, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_mp5.fire"); +#endif + + pl.w_attack_next = 0.08f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_mp5_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.mp5_mag >= 30) { + return; + } + if (!pl.ammo_9mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(MP5_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::mp5_mag, player::ammo_9mm, 30); + Weapons_UpdateAmmo(pl, pl.mp5_mag, pl.ammo_9mm, -1); +#endif + + pl.w_attack_next = 2.6f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_mp5_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_mp5_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [48/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_mp5_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.mp5_mag == 0 && pl.ammo_9mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_9mm, AMMO_MAX_9MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud4_spr, + [0,180/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud1_spr, + [0,180/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_mp5 = +{ + .name = "mp5navy", + .id = ITEM_MP5, + .slot = 0, + .slot_pos = 2, + .allow_drop = TRUE, + .draw = w_mp5_draw, + .holster = __NULL__, + .primary = w_mp5_primary, + .secondary = __NULL__, + .reload = w_mp5_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_mp5_hud, + .precache = w_mp5_precache, + .pickup = w_mp5_pickup, + .updateammo = w_mp5_updateammo, + .wmodel = w_mp5_wmodel, + .pmodel = w_mp5_pmodel, + .deathmsg = w_mp5_deathmsg, + .aimanim = w_mp5_aimanim, + .hudpic = w_mp5_hudpic +}; + +#ifdef SERVER +void +weapon_mp5navy(void) +{ + Weapons_InitItem(WEAPON_MP5); +} +#endif diff --git a/src/shared/w_p228.qc b/src/shared/w_p228.qc new file mode 100644 index 0000000..50ca274 --- /dev/null +++ b/src/shared/w_p228.qc @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_ (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_p228.mdl" + +COUNTER-STRIKE (1999) ENTITY + +SIG P228 Weapon + +- Buy Menu - +Price: $600 + +*/ + +enum +{ + P228_IDLE, + P228_SHOOT1, + P228_SHOOT2, + P228_SHOOT3, + P228_SHOOT_EMPTY, + P228_RELOAD, + P228_DRAW +}; + +void +w_p228_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_p228.fire"); + precache_model("models/w_p228.mdl"); +#else + precache_model("models/v_p228.mdl"); + precache_model("models/p_p228.mdl"); +#endif +} + +void +w_p228_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.p228_mag, pl.ammo_357sig, -1); +} + +string +w_p228_wmodel(void) +{ + return "models/w_p228.mdl"; +} + +string +w_p228_pmodel(void) +{ + return "models/p_p228.mdl"; +} + +string +w_p228_deathmsg(void) +{ + return ""; +} + +int +w_p228_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.p228_mag = 13; + else + pl.p228_mag = startammo; + } else { + if (pl.ammo_357sig < AMMO_MAX_357SIG) { + pl.ammo_357sig = bound(0, pl.ammo_357sig + 13, AMMO_MAX_357SIG); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_p228_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_p228.mdl"); + Weapons_ViewAnimation(P228_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 8; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_p228_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.gflags & GF_SEMI_TOGGLED) { + return; + } + if (!pl.p228_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.p228_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + if (pl.p228_mag <= 0) { + Weapons_ViewAnimation(P228_SHOOT_EMPTY); + } else { + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(P228_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(P228_SHOOT2); + break; + default: + Weapons_ViewAnimation(P228_SHOOT3); + break; + } + } +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 40, [accuracy,accuracy], WEAPON_P228); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_ONEHAND, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_ONEHAND, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_p228.fire"); +#endif + + pl.gflags |= GF_SEMI_TOGGLED; + pl.w_attack_next = 0.15f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_p228_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.p228_mag >= 30) { + return; + } + if (!pl.ammo_357sig) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(P228_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::p228_mag, player::ammo_357sig, 13); + Weapons_UpdateAmmo(pl, pl.p228_mag, pl.ammo_357sig, -1); +#endif + + pl.w_attack_next = 2.7f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_p228_aimanim(void) +{ + return w_deagle_aimanim(); +} + +void +w_p228_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [120/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_p228_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.p228_mag == 0 && pl.ammo_357sig == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_357sig, AMMO_MAX_357SIG, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud13_spr, + [0,90/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud12_spr, + [0,90/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_p228 = +{ + .name = "p228", + .id = ITEM_P228, + .slot = 1, + .slot_pos = 3, + .allow_drop = TRUE, + .draw = w_p228_draw, + .holster = __NULL__, + .primary = w_p228_primary, + .secondary = __NULL__, + .reload = w_p228_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_p228_hud, + .precache = w_p228_precache, + .pickup = w_p228_pickup, + .updateammo = w_p228_updateammo, + .wmodel = w_p228_wmodel, + .pmodel = w_p228_pmodel, + .deathmsg = w_p228_deathmsg, + .aimanim = w_p228_aimanim, + .hudpic = w_p228_hudpic +}; + +#ifdef SERVER +void +weapon_p228(void) +{ + Weapons_InitItem(WEAPON_P228); +} +#endif diff --git a/src/shared/w_p90.qc b/src/shared/w_p90.qc new file mode 100644 index 0000000..99bd687 --- /dev/null +++ b/src/shared/w_p90.qc @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_p90 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_p90.mdl" + +COUNTER-STRIKE (1999) ENTITY + +FN P90 Weapon + +- Buy Menu - +Price: $2350 + +*/ + +enum +{ + P90_IDLE, + P90_RELOAD, + P90_DRAW, + P90_SHOOT1, + P90_SHOOT2, + P90_SHOOT3 +}; + +void +w_p90_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_p90.fire"); + precache_model("models/w_p90.mdl"); +#else + precache_model("models/v_p90.mdl"); + precache_model("models/p_p90.mdl"); +#endif +} + +void +w_p90_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.p90_mag, pl.ammo_57mm, -1); +} + +string +w_p90_wmodel(void) +{ + return "models/w_p90.mdl"; +} + +string +w_p90_pmodel(void) +{ + return "models/p_p90.mdl"; +} + +string +w_p90_deathmsg(void) +{ + return ""; +} + +int +w_p90_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.p90_mag = 50; + else + pl.p90_mag = startammo; + } else { + if (pl.ammo_57mm < AMMO_MAX_57MM) { + pl.ammo_57mm = bound(0, pl.ammo_57mm + 50, AMMO_MAX_57MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_p90_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_p90.mdl"); + Weapons_ViewAnimation(P90_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 7; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_p90_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (!pl.p90_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 175); + pl.p90_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(P90_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(P90_SHOOT2); + break; + default: + Weapons_ViewAnimation(P90_SHOOT3); + break; + } +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 26, [accuracy,accuracy], WEAPON_P90); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_MP5, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_MP5, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_p90.fire"); +#endif + + pl.w_attack_next = 0.07f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_p90_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.p90_mag >= 50) { + return; + } + if (!pl.ammo_57mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(P90_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::p90_mag, player::ammo_57mm, 50); + Weapons_UpdateAmmo(pl, pl.p90_mag, pl.ammo_57mm, -1); +#endif + + pl.w_attack_next = 3.3f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_p90_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_p90_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [120/256,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_p90_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.p90_mag == 0 && pl.ammo_57mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_57mm, AMMO_MAX_57MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud13_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud12_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_p90 = +{ + .name = "p90", + .id = ITEM_P90, + .slot = 0, + .slot_pos = 3, + .allow_drop = TRUE, + .draw = w_p90_draw, + .holster = __NULL__, + .primary = w_p90_primary, + .secondary = __NULL__, + .reload = w_p90_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_p90_hud, + .precache = w_p90_precache, + .pickup = w_p90_pickup, + .updateammo = w_p90_updateammo, + .wmodel = w_p90_wmodel, + .pmodel = w_p90_pmodel, + .deathmsg = w_p90_deathmsg, + .aimanim = w_p90_aimanim, + .hudpic = w_p90_hudpic +}; + +#ifdef SERVER +void +weapon_p90(void) +{ + Weapons_InitItem(WEAPON_P90); +} +#endif diff --git a/src/shared/w_para.qc b/src/shared/w_para.qc new file mode 100644 index 0000000..b943594 --- /dev/null +++ b/src/shared/w_para.qc @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_m249 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_m249.mdl" + +COUNTER-STRIKE (1999) ENTITY + +FN M249 Para Weapon + +- Buy Menu - +Price: $5750 + +*/ + +enum +{ + PARA_IDLE, + PARA_SHOOT1, + PARA_SHOOT2, + PARA_RELOAD, + PARA_DRAW +}; + +void +w_para_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_para.fire"); + precache_model("models/w_m249.mdl"); +#else + precache_model("models/v_m249.mdl"); + precache_model("models/p_m249.mdl"); +#endif +} + +void +w_para_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.para_mag, pl.ammo_556mmbox, -1); +} + +string +w_para_wmodel(void) +{ + return "models/w_m249.mdl"; +} + +string +w_para_pmodel(void) +{ + return "models/p_m249.mdl"; +} + +string +w_para_deathmsg(void) +{ + return ""; +} + +int +w_para_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.para_mag = 100; + else + pl.para_mag = startammo; + } else { + if (pl.ammo_556mmbox < AMMO_MAX_556MMBOX) { + pl.ammo_556mmbox = bound(0, pl.ammo_556mmbox + 100, AMMO_MAX_556MMBOX); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_para_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_m249.mdl"); + Weapons_ViewAnimation(PARA_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 6; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_para_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (!pl.para_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 175); + pl.para_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(SCOUT_SHOOT1); + break; + default: + Weapons_ViewAnimation(SCOUT_SHOOT2); + break; + } +#else + TraceAttack_SetPenetrationPower(1); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 35, [accuracy,accuracy], WEAPON_PARA); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_PARA, 0.45f); + else + Animation_PlayerTopTemp(ANIM_SHOOT_PARA, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_para.fire"); +#endif + + pl.w_attack_next = 0.1f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_para_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.para_mag >= 100) { + return; + } + if (!pl.ammo_556mmbox) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(PARA_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::para_mag, player::ammo_556mmbox, 100); + Weapons_UpdateAmmo(pl, pl.para_mag, pl.ammo_556mmbox, -1); +#endif + + pl.w_attack_next = 3.0f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_para_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_para_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_para_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.para_mag == 0 && pl.ammo_556mmbox == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_556mmbox, AMMO_MAX_556MMBOX, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud6_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud3_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_para = +{ + .name = "m249", + .id = ITEM_PARA, + .slot = 0, + .slot_pos = 15, + .allow_drop = TRUE, + .draw = w_para_draw, + .holster = __NULL__, + .primary = w_para_primary, + .secondary = __NULL__, + .reload = w_para_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_para_hud, + .precache = w_para_precache, + .pickup = w_para_pickup, + .updateammo = w_para_updateammo, + .wmodel = w_para_wmodel, + .pmodel = w_para_pmodel, + .deathmsg = w_para_deathmsg, + .aimanim = w_para_aimanim, + .hudpic = w_para_hudpic +}; + +#ifdef SERVER +void +weapon_m249(void) +{ + Weapons_InitItem(WEAPON_PARA); +} +#endif diff --git a/src/shared/w_scout.qc b/src/shared/w_scout.qc new file mode 100644 index 0000000..e98e69d --- /dev/null +++ b/src/shared/w_scout.qc @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_scout (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_scout.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Steyr Scout Weapon + +- Buy Menu - +Price: $1250 + +*/ + +enum +{ + SCOUT_IDLE, + SCOUT_SHOOT1, + SCOUT_SHOOT2, + SCOUT_RELOAD, + SCOUT_DRAW +}; + +void +w_scout_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_scout.fire"); + precache_model("models/w_scout.mdl"); +#else + precache_model("models/v_scout.mdl"); + precache_model("models/p_scout.mdl"); +#endif +} + +void +w_scout_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.scout_mag, pl.ammo_762mm, -1); +} + +string +w_scout_wmodel(void) +{ + return "models/w_scout.mdl"; +} + +string +w_scout_pmodel(void) +{ + return "models/p_scout.mdl"; +} + +string +w_scout_deathmsg(void) +{ + return ""; +} + +int +w_scout_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.scout_mag = 10; + else + pl.scout_mag = startammo; + } else { + if (pl.ammo_762mm < AMMO_MAX_762MM) { + pl.ammo_762mm = bound(0, pl.ammo_762mm + 10, AMMO_MAX_762MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_scout_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_scout.mdl"); + Weapons_ViewAnimation(SCOUT_DRAW); + pl.mode_temp = 0; + +#ifdef CLIENT + pl.cs_cross_mindist = 5; + pl.cs_cross_deltadist = 3; +#endif +} + + +void +w_scout_release(void) +{ + player pl = (player)self; + + w_cstrike_weaponrelease(); + + if (pl.w_idle_next > 0.0f) { + pl.viewzoom = 1.0f; + return; + } + + if (pl.mode_temp == 1) { + pl.viewzoom = 0.45f; + } else if (pl.mode_temp == 2) { + pl.viewzoom = 0.1f; + } else { + pl.viewzoom = 1.0f; + } +} + +void +w_scout_secondary(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + +#ifdef SSQC + Sound_Play(pl, CHAN_WEAPON, "weapon_awp.zoom"); +#endif + + /* Simple toggle of fovs */ + if (pl.mode_temp == 1) { + pl.mode_temp = 2; + } else if (pl.mode_temp == 2) { + pl.mode_temp = 0; + } else { + pl.mode_temp = 1; + } + + pl.w_attack_next = 0.3f; + pl.w_idle_next = 0.0f; + w_scout_release(); +} + +void +w_scout_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + w_scout_release(); + return; + } + if (!pl.scout_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.scout_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(SCOUT_SHOOT1); + break; + default: + Weapons_ViewAnimation(SCOUT_SHOOT2); + break; + } +#else + TraceAttack_SetPenetrationPower(2); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 75, [accuracy,accuracy], WEAPON_SCOUT); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_RIFLE, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_RIFLE, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_scout.fire"); +#endif + + pl.w_attack_next = 1.25f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_scout_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.scout_mag >= 10) { + return; + } + if (!pl.ammo_762mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(SCOUT_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::scout_mag, player::ammo_762mm, 10); + Weapons_UpdateAmmo(pl, pl.scout_mag, pl.ammo_762mm, -1); +#endif + + pl.w_attack_next = 2.0f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_scout_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_scout_hud(void) +{ +#ifdef CLIENT + player pl = (player)self; + if (pl.viewzoom < 1.0f) { + Cstrike_DrawScope(); + } + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [72/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_scout_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.scout_mag == 0 && pl.ammo_762mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_762mm, AMMO_MAX_762MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud13_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud12_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_scout = +{ + .name = "scout", + .id = ITEM_SCOUT, + .slot = 0, + .slot_pos = 11, + .allow_drop = TRUE, + .draw = w_scout_draw, + .holster = __NULL__, + .primary = w_scout_primary, + .secondary = w_scout_secondary, + .reload = w_scout_reload, + .release = w_scout_release, + .crosshair = w_scout_hud, + .precache = w_scout_precache, + .pickup = w_scout_pickup, + .updateammo = w_scout_updateammo, + .wmodel = w_scout_wmodel, + .pmodel = w_scout_pmodel, + .deathmsg = w_scout_deathmsg, + .aimanim = w_scout_aimanim, + .hudpic = w_scout_hudpic +}; + +#ifdef SERVER +void +weapon_scout(void) +{ + Weapons_InitItem(WEAPON_SCOUT); +} +#endif diff --git a/src/shared/w_sg550.qc b/src/shared/w_sg550.qc new file mode 100644 index 0000000..ffd912b --- /dev/null +++ b/src/shared/w_sg550.qc @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_sg550 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_sg550.mdl" + +COUNTER-STRIKE (1999) ENTITY + +SIG SG 550 Weapon + +- Buy Menu - +Price: $4200 + +*/ + +enum +{ + SG550_IDLE, + SG550_SHOOT1, + SG550_SHOOT2, + SG550_RELOAD, + SG550_DRAW, +}; + +void +w_sg550_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_sg550.fire"); + precache_model("models/w_sg550.mdl"); +#else + precache_model("models/v_sg550.mdl"); + precache_model("models/p_sg550.mdl"); +#endif +} + +void +w_sg550_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.sg550_mag, pl.ammo_556mm, -1); +} + +string +w_sg550_wmodel(void) +{ + return "models/w_sg550.mdl"; +} + +string +w_sg550_pmodel(void) +{ + return "models/p_sg550.mdl"; +} + +string +w_sg550_deathmsg(void) +{ + return ""; +} + +int +w_sg550_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.sg550_mag = 30; + else + pl.sg550_mag = startammo; + } else { + if (pl.ammo_556mm < AMMO_MAX_556MM) { + pl.ammo_556mm = bound(0, pl.ammo_556mm + 30, AMMO_MAX_556MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_sg550_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_sg550.mdl"); + Weapons_ViewAnimation(SG550_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 5; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_sg550_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (!pl.sg550_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.sg550_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 2; + switch (r) { + case 0: + Weapons_ViewAnimation(SCOUT_SHOOT1); + break; + default: + Weapons_ViewAnimation(SCOUT_SHOOT2); + break; + } +#else + TraceAttack_SetPenetrationPower(1); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 70, [accuracy,accuracy], WEAPON_SG550); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_RIFLE, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_RIFLE, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_sg550.fire"); +#endif + + pl.w_attack_next = 0.25f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_sg550_secondary(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + /* Simple toggle of fovs */ + if (pl.viewzoom == 1.0f) { + pl.viewzoom = 0.45f; + } else if (pl.viewzoom == 0.45f) { + pl.viewzoom = 0.1f; + } else { + pl.viewzoom = 1.0f; + } + pl.w_attack_next = 0.5f; +} + +void +w_sg550_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.sg550_mag >= 30) { + return; + } + if (!pl.ammo_556mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(SG550_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::sg550_mag, player::ammo_556mm, 30); + Weapons_UpdateAmmo(pl, pl.sg550_mag, pl.ammo_556mm, -1); +#endif + + pl.w_attack_next = 3.8f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_sg550_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_sg550_hud(void) +{ +#ifdef CLIENT + player pl = (player)self; + if (pl.viewzoom < 1.0f) { + Cstrike_DrawScope(); + } + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_sg550_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.sg550_mag == 0 && pl.ammo_556mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_556mm, AMMO_MAX_556MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud15_spr, + [0,180/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud14_spr, + [0,180/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_sg550 = +{ + .name = "sg550", + .id = ITEM_SG550, + .slot = 0, + .slot_pos = 14, + .allow_drop = TRUE, + .draw = w_sg550_draw, + .holster = __NULL__, + .primary = w_sg550_primary, + .secondary = w_sg550_secondary, + .reload = w_sg550_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_sg550_hud, + .precache = w_sg550_precache, + .pickup = w_sg550_pickup, + .updateammo = w_sg550_updateammo, + .wmodel = w_sg550_wmodel, + .pmodel = w_sg550_pmodel, + .deathmsg = w_sg550_deathmsg, + .aimanim = w_sg550_aimanim, + .hudpic = w_sg550_hudpic +}; + +#ifdef SERVER +void +weapon_sg550(void) +{ + Weapons_InitItem(WEAPON_SG550); +} +#endif diff --git a/src/shared/w_sg552.qc b/src/shared/w_sg552.qc new file mode 100644 index 0000000..34d29eb --- /dev/null +++ b/src/shared/w_sg552.qc @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_sg552 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_sg552.mdl" + +COUNTER-STRIKE (1999) ENTITY + +SIG SG 552 Commando Weapon + +- Buy Menu - +Price: $3500 + +*/ + +enum +{ + SG552_IDLE, + SG552_RELOAD, + SG552_DRAW, + SG552_SHOOT1, + SG552_SHOOT2, + SG552_SHOOT3 +}; + +void +w_sg552_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_sg552.fire"); + precache_model("models/w_sg552.mdl"); +#else + precache_model("models/v_sg552.mdl"); + precache_model("models/p_sg552.mdl"); +#endif +} + +void +w_sg552_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.sg552_mag, pl.ammo_556mm, -1); +} + +string +w_sg552_wmodel(void) +{ + return "models/w_sg552.mdl"; +} + +string +w_sg552_pmodel(void) +{ + return "models/p_sg552.mdl"; +} + +string +w_sg552_deathmsg(void) +{ + return ""; +} + +int +w_sg552_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.sg552_mag = 30; + else + pl.sg552_mag = startammo; + } else { + if (pl.ammo_556mm < AMMO_MAX_556MM) { + pl.ammo_556mm = bound(0, pl.ammo_556mm + 30, AMMO_MAX_556MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_sg552_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_sg552.mdl"); + Weapons_ViewAnimation(SG552_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 5; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_sg552_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (!pl.sg552_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 220); + pl.sg552_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(SG552_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(SG552_SHOOT2); + break; + default: + Weapons_ViewAnimation(SG552_SHOOT3); + break; + } +#else + TraceAttack_SetPenetrationPower(1); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 33, [accuracy,accuracy], WEAPON_SG552); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_RIFLE, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_RIFLE, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_sg552.fire"); +#endif + + if (pl.viewzoom == 1.0f) { + pl.w_attack_next = 0.0825f; + } else { + pl.w_attack_next = 0.15f; + } + pl.w_idle_next = pl.w_attack_next; +} + +void +w_sg552_secondary(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + /* Simple toggle of fovs */ + if (pl.viewzoom == 1.0f) { + pl.viewzoom = 0.2f; + } else { + pl.viewzoom = 1.0f; + } + pl.w_attack_next = 0.5f; +} + +void +w_sg552_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.sg552_mag >= 30) { + return; + } + if (!pl.ammo_556mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(SG552_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::sg552_mag, player::ammo_556mm, 30); + Weapons_UpdateAmmo(pl, pl.sg552_mag, pl.ammo_556mm, -1); +#endif + + pl.w_attack_next = 3.2f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_sg552_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_sg552_hud(void) +{ +#ifdef CLIENT + player pl = (player)self; + if (pl.viewzoom == 1.0f) { + Cstrike_DrawCrosshair(); + } else { + Cstrike_DrawSimpleCrosshair(); + } + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_sg552_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.sg552_mag == 0 && pl.ammo_556mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_556mm, AMMO_MAX_556MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud11_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud10_spr, + [0,45/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_sg552 = +{ + .name = "sg552", + .id = ITEM_SG552, + .slot = 0, + .slot_pos = 8, + .allow_drop = TRUE, + .draw = w_sg552_draw, + .holster = __NULL__, + .primary = w_sg552_primary, + .secondary = w_sg552_secondary, + .reload = w_sg552_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_sg552_hud, + .precache = w_sg552_precache, + .pickup = w_sg552_pickup, + .updateammo = w_sg552_updateammo, + .wmodel = w_sg552_wmodel, + .pmodel = w_sg552_pmodel, + .deathmsg = w_sg552_deathmsg, + .aimanim = w_sg552_aimanim, + .hudpic = w_sg552_hudpic +}; + +#ifdef SERVER +void +weapon_sg552(void) +{ + Weapons_InitItem(WEAPON_SG552); +} +#endif diff --git a/src/shared/w_smokegrenade.qc b/src/shared/w_smokegrenade.qc new file mode 100644 index 0000000..1adfef8 --- /dev/null +++ b/src/shared/w_smokegrenade.qc @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_smokegrenade (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_smokegrenade.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Smoke Grenade Weapon + +When thrown, the explosion casts view-blocking smoke in that radius. + +- Buy Menu - +Price: $300 + +*/ + +enum +{ + SMOKEGRENADE_IDLE, + SMOKEGRENADE_PULLPIN, + SMOKEGRENADE_THROW, + SMOKEGRENADE_DRAW, +}; + +void +w_smokegrenade_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_smokegrenade.bounce"); + Sound_Precache("weapon_smokegrenade.explode"); + precache_model("models/w_smokegrenade.mdl"); +#else + precache_model("models/v_smokegrenade.mdl"); + precache_model("models/p_smokegrenade.mdl"); +#endif +} + +void +w_smokegrenade_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, pl.ammo_smokegrenade, pl.mode_temp); +} + +int +w_smokegrenade_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (pl.ammo_smokegrenade < AMMO_MAX_SMOKE) { + pl.ammo_smokegrenade = bound(0, pl.ammo_smokegrenade + 1, AMMO_MAX_SMOKE); + } else { + return FALSE; + } +#endif + return TRUE; +} + +string +w_smokegrenade_wmodel(void) +{ + return "models/w_smokegrenade.mdl"; +} + +string +w_smokegrenade_pmodel(void) +{ + return "models/p_smokegrenade.mdl"; +} + +string +w_smokegrenade_deathmsg(void) +{ + return ""; +} + +void +w_smokegrenade_draw(void) +{ + Weapons_SetModel("models/v_smokegrenade.mdl"); + Weapons_ViewAnimation(SMOKEGRENADE_DRAW); + player pl = (player)self; + pl.mode_temp = 0; +} + +#ifdef SERVER +void w_smokegrenade_throw(void) +{ + static void smokegrenade_explode(void) + { + FX_Smokenade(self.origin); + Sound_Play(self, CHAN_BODY, "weapon_smokegrenade.explode"); + remove(self); + } + + static void smokegrenade_touch(void) + { + if (other.takedamage == DAMAGE_YES) { + Damage_Apply(other, self.owner, 15, WEAPON_SMOKEGRENADE, DMG_BLUNT); + } else { + Sound_Play(self, CHAN_BODY, "weapon_smokegrenade.bounce"); + } + self.frame = 0; + } + + player pl = (player)self; + vector vPLAngle = pl.v_angle; + if (vPLAngle[0] < 0) { + vPLAngle[0] = -10 + vPLAngle[0] * ((90 - 10) / 90.0); + } else { + vPLAngle[0] = -10 + vPLAngle[0] * ((90 + 10) / 90.0); + } + + float flVel = (90 - vPLAngle[0]) * 5; + if (flVel > 1000) { + flVel = 1000; + } + + makevectors(vPLAngle); + vector vecSrc = pl.origin + pl.view_ofs + v_forward * 16; + vector vecThrow = v_forward * flVel + pl.velocity; + + entity eGrenade = spawn(); + eGrenade.owner = pl; + eGrenade.classname = "remove_me"; + eGrenade.solid = SOLID_BBOX; + eGrenade.frame = 1; + eGrenade.velocity = vecThrow; + eGrenade.movetype = MOVETYPE_BOUNCE; + eGrenade.think = smokegrenade_explode; + eGrenade.touch = smokegrenade_touch; + eGrenade.nextthink = time + 4.0f; + setmodel(eGrenade, "models/w_smokegrenade.mdl"); + setsize(eGrenade, [0,0,0], [0,0,0]); + setorigin(eGrenade, vecSrc); +} +#endif + +void +w_smokegrenade_primary(void) +{ + player pl = (player)self; + if (pl.w_attack_next > 0.0) { + return; + } + + /* We're abusing this network variable for the holding check */ + if (pl.mode_temp > 0) { + return; + } + + /* Ammo check */ +#ifdef CLIENT + if (pl.ammo_smokegrenade <= 0) { + return; + } +#else + if (pl.ammo_smokegrenade <= 0) { + return; + } +#endif + + Weapons_ViewAnimation(SMOKEGRENADE_PULLPIN); + pl.mode_temp = 1; + pl.w_attack_next = 0.975f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_smokegrenade_release(void) +{ + player pl = (player)self; + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.mode_temp == 1) { +#ifdef CLIENT + pl.ammo_smokegrenade--; + Weapons_ViewAnimation(SMOKEGRENADE_THROW); +#else + pl.ammo_smokegrenade--; + w_smokegrenade_throw(); +#endif + pl.mode_temp = 2; + pl.w_attack_next = 1.0f; + pl.w_idle_next = 0.5f; + } else if (pl.mode_temp == 2) { +#ifdef CLIENT + Weapons_ViewAnimation(SMOKEGRENADE_DRAW); +#else + if (!pl.ammo_smokegrenade) { + Weapons_RemoveItem(pl, WEAPON_SMOKEGRENADE); + } +#endif + pl.w_attack_next = 0.5f; + pl.w_idle_next = 0.5f; + pl.mode_temp = 0; + } +} + +float +w_smokegrenade_aimanim(void) +{ + return w_flashbang_aimanim(); +} + +void +w_smokegrenade_hud(void) +{ +#ifdef CLIENT + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [144/256,96/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_smokegrenade_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + + HUD_DrawAmmoBar(pos, pl.ammo_smokegrenade, AMMO_MAX_SMOKE, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud6_spr, + [0,135/256], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud3_spr, + [0,135/256], + [170/256,45/256], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_smokegrenade = +{ + .name = "smokegrenade", + .id = ITEM_SMOKEGRENADE, + .slot = 3, + .slot_pos = 2, + .allow_drop = FALSE, + .draw = w_smokegrenade_draw, + .holster = __NULL__, + .primary = w_smokegrenade_primary, + .secondary = __NULL__, + .reload = __NULL__, + .release = w_smokegrenade_release, + .crosshair = w_smokegrenade_hud, + .precache = w_smokegrenade_precache, + .pickup = w_smokegrenade_pickup, + .updateammo = w_smokegrenade_updateammo, + .wmodel = w_smokegrenade_wmodel, + .pmodel = w_smokegrenade_pmodel, + .deathmsg = w_smokegrenade_deathmsg, + .aimanim = w_smokegrenade_aimanim, + .hudpic = w_smokegrenade_hudpic +}; + +#ifdef SERVER +void +weapon_smokegrenade(void) +{ + Weapons_InitItem(WEAPON_SMOKEGRENADE); +} +#endif diff --git a/src/shared/w_tmp.qc b/src/shared/w_tmp.qc new file mode 100644 index 0000000..dafd11b --- /dev/null +++ b/src/shared/w_tmp.qc @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_tmp (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_tmp.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Steyr Tactical Weapon + +- Buy Menu - +Price: $1250 + +*/ + +enum +{ + TMP_IDLE, + TMP_RELOAD, + TMP_DRAW, + TMP_SHOOT1, + TMP_SHOOT2, + TMP_SHOOT3 +}; + +void +w_tmp_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_tmp.fire"); + precache_model("models/w_tmp.mdl"); +#else + precache_model("models/v_tmp.mdl"); + precache_model("models/p_tmp.mdl"); +#endif +} + +void +w_tmp_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.tmp_mag, pl.ammo_9mm, -1); +} + +string +w_tmp_wmodel(void) +{ + return "models/w_tmp.mdl"; +} + +string +w_tmp_pmodel(void) +{ + return "models/p_tmp.mdl"; +} + +string +w_tmp_deathmsg(void) +{ + return ""; +} + +int +w_tmp_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.tmp_mag = 30; + else + pl.tmp_mag = startammo; + } else { + if (pl.ammo_9mm < AMMO_MAX_9MM) { + pl.ammo_9mm = bound(0, pl.ammo_9mm + 30, AMMO_MAX_9MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_tmp_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_tmp.mdl"); + Weapons_ViewAnimation(TMP_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 7; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_tmp_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* ammo check */ + if (!pl.tmp_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.tmp_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(TMP_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(TMP_SHOOT2); + break; + default: + Weapons_ViewAnimation(TMP_SHOOT3); + break; + } +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 26, [accuracy,accuracy], WEAPON_TMP); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_MP5, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_MP5, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_tmp.fire"); +#endif + + pl.w_attack_next = 0.07f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_tmp_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.tmp_mag >= 30) { + return; + } + if (!pl.ammo_9mm) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(TMP_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::tmp_mag, player::ammo_9mm, 30); + Weapons_UpdateAmmo(pl, pl.tmp_mag, pl.ammo_9mm, -1); +#endif + + pl.w_attack_next = 2.1f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_tmp_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_tmp_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [48/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_tmp_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.tmp_mag == 0 && pl.ammo_9mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_9mm, AMMO_MAX_9MM, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud5_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud2_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_tmp = +{ + .name = "tmp", + .id = ITEM_TMP, + .slot = 0, + .slot_pos = 6, + .allow_drop = TRUE, + .draw = w_tmp_draw, + .holster = __NULL__, + .primary = w_tmp_primary, + .secondary = __NULL__, + .reload = w_tmp_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_tmp_hud, + .precache = w_tmp_precache, + .pickup = w_tmp_pickup, + .updateammo = w_tmp_updateammo, + .wmodel = w_tmp_wmodel, + .pmodel = w_tmp_pmodel, + .deathmsg = w_tmp_deathmsg, + .aimanim = w_tmp_aimanim, + .hudpic = w_tmp_hudpic +}; + +#ifdef SERVER +void +weapon_tmp(void) +{ + Weapons_InitItem(WEAPON_TMP); +} +#endif diff --git a/src/shared/w_ump45.qc b/src/shared/w_ump45.qc new file mode 100644 index 0000000..faf3060 --- /dev/null +++ b/src/shared/w_ump45.qc @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_ump45 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_ump45.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Heckler & Koch UMP .45 ACP Weapon + +- Buy Menu - +Price: $1700 + +*/ + +enum +{ + UMP45_IDLE, + UMP45_RELOAD, + UMP45_DRAW, + UMP45_SHOOT1, + UMP45_SHOOT2, + UMP45_SHOOT3 +}; + +void +w_ump45_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_ump45.fire"); + precache_model("models/w_ump45.mdl"); +#else + precache_model("models/v_ump45.mdl"); + precache_model("models/p_ump45.mdl"); +#endif +} + +void +w_ump45_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.ump45_mag, pl.ammo_45acp, -1); +} + +string +w_ump45_wmodel(void) +{ + return "models/w_ump45.mdl"; +} + +string +w_ump45_pmodel(void) +{ + return "models/p_ump45.mdl"; +} + +string +w_ump45_deathmsg(void) +{ + return ""; +} + +int +w_ump45_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.ump45_mag = 25; + else + pl.ump45_mag = startammo; + } else { + if (pl.ammo_45acp < AMMO_MAX_45ACP) { + pl.ammo_45acp = bound(0, pl.ammo_45acp + 25, AMMO_MAX_45ACP); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_ump45_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_ump45.mdl"); + Weapons_ViewAnimation(UMP45_DRAW); + +#ifdef CLIENT + pl.cs_cross_mindist = 6; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_ump45_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* ammo check */ +#ifdef CLIENT + if (!pl.ump45_mag) { + return; + } +#else + if (!pl.ump45_mag) { + return; + } +#endif + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 210); + +#ifdef CLIENT + pl.ump45_mag--; + View_SetMuzzleflash(MUZZLE_RIFLE); +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 30, [accuracy,accuracy], WEAPON_UMP45); + pl.ump45_mag--; + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_MP5, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_MP5, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_ump45.fire"); +#endif + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(UMP45_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(UMP45_SHOOT2); + break; + default: + Weapons_ViewAnimation(UMP45_SHOOT3); + break; + } + + pl.w_attack_next = 0.105f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_ump45_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + +#ifdef CLIENT + if (pl.ump45_mag >= 25) { + return; + } + if (!pl.ammo_45acp) { + return; + } +#else + if (pl.ump45_mag >= 25) { + return; + } + if (!pl.ammo_45acp) { + return; + } + + Weapons_ReloadWeapon(pl, player::ump45_mag, player::ammo_45acp, 25); + Weapons_UpdateAmmo(pl, pl.ump45_mag, pl.ammo_45acp, -1); +#endif + + Weapons_ViewAnimation(UMP45_RELOAD); + pl.w_attack_next = 3.5f; + pl.w_idle_next = pl.w_attack_next; +} + +float +w_ump45_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_ump45_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [96/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_ump45_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.ump45_mag == 0 && pl.ammo_45acp == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_45acp, AMMO_MAX_45ACP, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud16_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud16_spr, + [0,0], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_ump45 = +{ + .name = "ump45", + .id = ITEM_UMP45, + .slot = 0, + .slot_pos = 4, + .allow_drop = TRUE, + .draw = w_ump45_draw, + .holster = __NULL__, + .primary = w_ump45_primary, + .secondary = __NULL__, + .reload = w_ump45_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_ump45_hud, + .precache = w_ump45_precache, + .pickup = w_ump45_pickup, + .updateammo = w_ump45_updateammo, + .wmodel = w_ump45_wmodel, + .pmodel = w_ump45_pmodel, + .deathmsg = w_ump45_deathmsg, + .aimanim = w_ump45_aimanim, + .hudpic = w_ump45_hudpic +}; + +#ifdef SERVER +void +weapon_ump45(void) +{ + Weapons_InitItem(WEAPON_UMP45); +} +#endif diff --git a/src/shared/w_usp45.qc b/src/shared/w_usp45.qc new file mode 100644 index 0000000..3f98c30 --- /dev/null +++ b/src/shared/w_usp45.qc @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_usp45 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_usp45.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Heckler & Koch USP .45 Tactical Weapon + +Default arsenal for Counter-Terrorists + +- Buy Menu - +Price: $500 + +*/ + +enum +{ + USP45_IDLE, + USP45_SHOOT1, + USP45_SHOOT2, + USP45_SHOOT3, + USP45_SHOOTLAST, + USP45_RELOAD, + USP45_DRAW, + USP45_ADDSIL, + USP45_IDLEUNSIL, + USP45_SHOOT1UNSIL, + USP45_SHOOT2UNSIL, + USP45_SHOOT3UNSIL, + USP45_SHOOTLASTUNSIL, + USP45_RELOADUNSIL, + USP45_DRAWUNSIL, + USP45_DETACHSIL +}; + +void +w_usp45_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_usp45.fire"); + Sound_Precache("weapon_usp45.silenced"); + precache_model("models/w_usp.mdl"); +#else + precache_model("models/v_usp.mdl"); + precache_model("models/p_usp.mdl"); +#endif +} + +void +w_usp45_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.usp45_mag, pl.ammo_45acp, -1); +} + +string +w_usp45_wmodel(void) +{ + return "models/w_usp.mdl"; +} + +string +w_usp45_pmodel(void) +{ + return "models/p_usp.mdl"; +} + +string +w_usp45_deathmsg(void) +{ + return ""; +} + +int +w_usp45_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.usp45_mag = 12; + else + pl.usp45_mag = startammo; + } else { + if (pl.ammo_45acp < AMMO_MAX_45ACP) { + pl.ammo_45acp = bound(0, pl.ammo_45acp + 12, AMMO_MAX_45ACP); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_usp45_draw(void) +{ + player pl = (player)self; + + Weapons_SetModel("models/v_usp.mdl"); + if (pl.mode_usp45 == 1) { + Weapons_ViewAnimation(USP45_DRAW); + } else { + Weapons_ViewAnimation(USP45_DRAWUNSIL); + } + +#ifdef CLIENT + pl.cs_cross_mindist = 8; + pl.cs_cross_deltadist = 3; +#endif +} + +void +w_usp45_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + if (pl.gflags & GF_SEMI_TOGGLED) { + return; + } + + /* ammo check */ + if (!pl.usp45_mag) { + return; + } + + Cstrike_ShotMultiplierAdd(pl, 1); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + pl.usp45_mag--; + + /* actual firing */ +#ifdef CLIENT + if (pl.mode_usp45 == 1) { + View_SetMuzzleflash(0); + } else { + View_SetMuzzleflash(MUZZLE_SMALL); + } +#else + /* Different sounds without silencer */ + if (pl.mode_usp45 == 1) { + Sound_Play(pl, CHAN_WEAPON, "weapon_usp45.silenced"); + } else { + Sound_Play(pl, CHAN_WEAPON, "weapon_usp45.fire"); + } + + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 33, [accuracy,accuracy], WEAPON_USP45); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_ONEHAND, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_ONEHAND, 0.45f); +#endif + + /* this stuff is predicted */ + int r = (float)input_sequence % 3; + if (pl.mode_usp45 == 1) { + if (pl.usp45_mag <= 0) { + Weapons_ViewAnimation(USP45_SHOOTLAST); + } else { + switch (r) { + case 0: + Weapons_ViewAnimation(USP45_SHOOT1); + break; + case 1: + Weapons_ViewAnimation(USP45_SHOOT2); + break; + default: + Weapons_ViewAnimation(USP45_SHOOT3); + break; + } + } + } else { + if (pl.usp45_mag <= 0) { + Weapons_ViewAnimation(USP45_SHOOTLASTUNSIL); + } else { + switch (r) { + case 0: + Weapons_ViewAnimation(USP45_SHOOT1UNSIL); + break; + case 1: + Weapons_ViewAnimation(USP45_SHOOT2UNSIL); + break; + default: + Weapons_ViewAnimation(USP45_SHOOT3UNSIL); + break; + } + } + } + + pl.gflags |= GF_SEMI_TOGGLED; + pl.w_attack_next = 0.15f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_usp45_secondary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0) { + return; + } + + /* toggle silencer */ + pl.mode_usp45 = 1 - pl.mode_usp45; + + /* play the animation */ + if (pl.mode_usp45) { + Weapons_ViewAnimation(USP45_ADDSIL); + } else { + Weapons_ViewAnimation(USP45_DETACHSIL); + } + + pl.w_attack_next = 3.1f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_usp45_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + if (pl.usp45_mag >= 12) { + return; + } + if (!pl.ammo_45acp) { + return; + } + +#ifdef CLIENT + if (pl.mode_usp45 == 1) { + Weapons_ViewAnimation(USP45_RELOAD); + } else { + Weapons_ViewAnimation(USP45_RELOADUNSIL); + } +#else + Weapons_ReloadWeapon(pl, player::usp45_mag, player::ammo_45acp, 12); +#endif + + pl.w_attack_next = 2.5f; +} + +float +w_usp45_aimanim(void) +{ + return w_deagle_aimanim(); +} + +void +w_usp45_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [96/256,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_usp45_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.usp45_mag == 0 && pl.ammo_45acp == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_45acp, AMMO_MAX_45ACP, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud4_spr, + [0,90/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud1_spr, + [0,90/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_usp45 = +{ + .name = "usp", + .id = ITEM_USP45, + .slot = 1, + .slot_pos = 0, + .allow_drop = TRUE, + .draw = w_usp45_draw, + .holster = __NULL__, + .primary = w_usp45_primary, + .secondary = w_usp45_secondary, + .reload = w_usp45_reload, + .release = w_cstrike_weaponrelease, + .crosshair = w_usp45_hud, + .precache = w_usp45_precache, + .pickup = w_usp45_pickup, + .updateammo = w_usp45_updateammo, + .wmodel = w_usp45_wmodel, + .pmodel = w_usp45_pmodel, + .deathmsg = w_usp45_deathmsg, + .aimanim = w_usp45_aimanim, + .hudpic = w_usp45_hudpic +}; + +#ifdef SERVER +void +weapon_usp45(void) +{ + Weapons_InitItem(WEAPON_USP45); +} +#endif diff --git a/src/shared/w_xm1014.qc b/src/shared/w_xm1014.qc new file mode 100644 index 0000000..7f19f18 --- /dev/null +++ b/src/shared/w_xm1014.qc @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2016-2021 Marco Hladik + * + * 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. + */ + +/*QUAKED weapon_xm1014 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_xm1014.mdl" + +COUNTER-STRIKE (1999) ENTITY + +Benneli XM1014 Weapon + +- Buy Menu - +Price: $3000 + +*/ + +enum +{ + XM1014_IDLE, + XM1014_SHOOT1, + XM1014_SHOOT2, + XM1014_INSERT, + XM1014_RELOAD_END, + XM1014_RELOAD_START, + XM1014_DRAW +}; + +enum +{ + XM1014S_IDLE, + XM1014S_RELOAD_START, + XM1014S_RELOAD, + XM1014S_RELOAD_END +}; + +void +w_xm1014_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_xm1014.fire"); + Sound_Precache("weapon_xm1014.insertshell"); + precache_model("models/w_xm1014.mdl"); +#else + precache_model("models/v_xm1014.mdl"); + precache_model("models/p_xm1014.mdl"); +#endif +} + +void +w_xm1014_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.xm1014_mag, pl.ammo_buckshot, -1); +} + +string +w_xm1014_wmodel(void) +{ + return "models/w_xm1014.mdl"; +} + +string +w_xm1014_pmodel(void) +{ + return "models/p_xm1014.mdl"; +} + +string +w_xm1014_deathmsg(void) +{ + return ""; +} + +int +w_xm1014_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + if (startammo == -1) + pl.xm1014_mag = 7; + else + pl.xm1014_mag = startammo; + } else { + if (pl.ammo_buckshot < AMMO_MAX_BUCKSHOT) { + pl.ammo_buckshot = bound(0, pl.ammo_buckshot + 7, AMMO_MAX_BUCKSHOT); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_xm1014_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_xm1014.mdl"); + Weapons_ViewAnimation(XM1014_DRAW); + pl.mode_temp = 0; + +#ifdef CLIENT + pl.cs_cross_mindist = 9; + pl.cs_cross_deltadist = 4; +#endif +} + +void +w_xm1014_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* ammo check */ +#ifdef CLIENT + if (!pl.xm1014_mag) { + return; + } +#else + if (!pl.xm1014_mag) { + return; + } +#endif + + Cstrike_ShotMultiplierAdd(pl, 6); + float accuracy = Cstrike_CalculateAccuracy(pl, 200); + +#ifdef CLIENT + pl.xm1014_mag--; + View_SetMuzzleflash(MUZZLE_RIFLE); +#else + TraceAttack_SetPenetrationPower(0); + TraceAttack_FireBullets(6, pl.origin + pl.view_ofs, 22, [accuracy,accuracy], WEAPON_XM1014); + pl.xm1014_mag--; + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT_SHOTGUN, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CROUCH_SHOOT_SHOTGUN, 0.45f); + + Sound_Play(pl, CHAN_WEAPON, "weapon_xm1014.fire"); +#endif + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(XM1014_SHOOT1); + break; + default: + Weapons_ViewAnimation(XM1014_SHOOT2); + break; + } + + pl.w_attack_next = 0.25f; + pl.w_idle_next = pl.w_attack_next; +} + +void +w_xm1014_reload(void) +{ + player pl = (player)self; +#ifdef CLIENT + if (pl.xm1014_mag >= 7) { + return; + } + if (pl.ammo_buckshot <= 0) { + return; + } +#else + if (pl.xm1014_mag >= 7) { + return; + } + if (pl.ammo_buckshot <= 0) { + return; + } +#endif + + if (pl.mode_temp > XM1014S_IDLE) { + return; + } + pl.mode_temp = XM1014S_RELOAD_START; + pl.w_idle_next = 0.0f; +} + +void +w_xm1014_release(void) +{ + player pl = (player)self; + + w_cstrike_weaponrelease(); + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.mode_temp == XM1014S_RELOAD_START) { + Weapons_ViewAnimation(XM1014_RELOAD_START); + pl.mode_temp = XM1014S_RELOAD; + pl.w_idle_next = 0.65f; + } else if (pl.mode_temp == XM1014S_RELOAD) { + Weapons_ViewAnimation(XM1014_INSERT); +#ifdef CLIENT + pl.xm1014_mag++; + pl.ammo_buckshot--; + + if (pl.ammo_buckshot <= 0 || pl.xm1014_mag >= 7) { + pl.mode_temp = XM1014S_RELOAD_END; + } +#else + pl.xm1014_mag++; + pl.ammo_buckshot--; + w_xm1014_updateammo(pl); + Sound_Play(pl, CHAN_WEAPON, "weapon_xm1014.insertshell"); + if (pl.ammo_buckshot <= 0 || pl.xm1014_mag >= 7) { + pl.mode_temp = XM1014S_RELOAD_END; + } +#endif + pl.w_idle_next = 0.5f; + } else if (pl.mode_temp == XM1014S_RELOAD_END) { + Weapons_ViewAnimation(XM1014_RELOAD_END); + pl.mode_temp = XM1014S_IDLE; + pl.w_idle_next = 10.0f; + pl.w_attack_next = 0.5f; + } +} + +float +w_xm1014_aimanim(void) +{ + return w_ak47_aimanim(); +} + +void +w_xm1014_hud(void) +{ +#ifdef CLIENT + Cstrike_DrawCrosshair(); + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic(aicon_pos, [24,24], g_hud7_spr, [0,72/256], [24/256, 24/256], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_xm1014_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.xm1014_mag == 0 && pl.ammo_buckshot == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + HUD_DrawAmmoBar(pos, pl.ammo_buckshot, AMMO_MAX_BUCKSHOT, a); + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud13_spr, + [0,135/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud12_spr, + [0,135/256], + [170/256,45/256], + hud_col, + 1.0f, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_xm1014 = +{ + .name = "xm1014", + .id = ITEM_XM1014, + .slot = 0, + .slot_pos = 1, + .allow_drop = TRUE, + .draw = w_xm1014_draw, + .holster = __NULL__, + .primary = w_xm1014_primary, + .secondary = __NULL__, + .reload = w_xm1014_reload, + .release = w_xm1014_release, + .crosshair = w_xm1014_hud, + .precache = w_xm1014_precache, + .pickup = w_xm1014_pickup, + .updateammo = w_xm1014_updateammo, + .wmodel = w_xm1014_wmodel, + .pmodel = w_xm1014_pmodel, + .deathmsg = w_xm1014_deathmsg, + .aimanim = w_xm1014_aimanim, + .hudpic = w_xm1014_hudpic +}; + +#ifdef SERVER +void +weapon_xm1014(void) +{ + Weapons_InitItem(WEAPON_XM1014); +} +#endif diff --git a/src/shared/weapons.h b/src/shared/weapons.h new file mode 100644 index 0000000..7084503 --- /dev/null +++ b/src/shared/weapons.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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, + 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/src/shared/weapons.qc b/src/shared/weapons.qc new file mode 100644 index 0000000..9600136 --- /dev/null +++ b/src/shared/weapons.qc @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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_t w_null = {}; +weapon_t g_weapons[] = { + w_null, + w_m3, + w_xm1014, + w_mp5, + w_p90, + w_ump45, + w_mac10, + w_tmp, + w_ak47, + w_sg552, + w_m4a1, + w_aug, + w_scout, + w_awp, + w_g3sg1, + w_sg550, + w_para, + w_usp45, + w_glock18, + w_deagle, + w_p228, + w_elites, + w_fiveseven, + w_knife, + w_hegrenade, + w_flashbang, + w_smokegrenade, + w_c4bomb +}; diff --git a/src/shared/weapons_cstrike.qc b/src/shared/weapons_cstrike.qc new file mode 100644 index 0000000..dd7ec34 --- /dev/null +++ b/src/shared/weapons_cstrike.qc @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * 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. + */ + +/* + * How Counter-Strike's accuracy works (from my understanding) + * this was deducted from the decrypted CS:S script files: + * https://gamebanana.com/gamefiles/2293 + * + * Each and every bullet fired contributes to the shotmultiplier value, + * which decreases back to 0 slowly over time. + * + * Meanwhile, accuracy gets calculated by taking said value and dividing it + * by the weapon-specific divider. Each gun has a different one. + * The higher the divider value, the more accurate the weapon is in contrast + * to other weapons. +*/ + +/* called whenever a cstrike gun fires a successful shot */ +void +Cstrike_ShotMultiplierAdd(player pl, int shots) +{ + /* more than 12 is enough, you can barely hit the barn */ + pl.cs_shotmultiplier = bound(0, pl.cs_shotmultiplier + shots, 12); + + pl.cs_shottime = 0.2f; + pl.punchangle[0] = -4 * (pl.cs_shotmultiplier / 6); + pl.punchangle[1] = random(-1, 1); +} + +/* generate an accuracy value that we'll pass onto TraceAttack */ +float +Cstrike_CalculateAccuracy(player pl, float divisor) +{ + float m = 1.0f; + + if (!(pl.flags & FL_ONGROUND)) { + m = 2.0f; + } else if (pl.flags & FL_CROUCHING) { + m = 0.5f; + } else if (vlen(pl.velocity) > 120) { + m = 1.5f; + } + + if (divisor == -1) { + /* snipers shoot way less accurate overall. */ + return (pl.viewzoom < 1.0f) ? (0.0f) : (0.05 * m); + } else { + return (pl.cs_shotmultiplier / divisor) * m; + } +} + +/* called whenever cstrike guns aren't firing */ +void +Cstrike_ShotMultiplierUpdate(player pl) +{ + if ((pl.cs_shotmultiplier > 0) && (pl.cs_shottime <= 0.0f)) { + pl.cs_shottime = pl.w_attack_next + 0.01; + pl.cs_shotmultiplier--; + } + + pl.cs_shottime = max(0, pl.cs_shottime - input_timelength); +} +void +w_cstrike_weaponrelease(void) +{ + player pl = (player)self; + Cstrike_ShotMultiplierUpdate(pl); +} diff --git a/zpak001.pk3dir/default.cfg b/zpak001.pk3dir/default.cfg new file mode 100755 index 0000000..23dd12e --- /dev/null +++ b/zpak001.pk3dir/default.cfg @@ -0,0 +1,65 @@ +// Generic Binds +bind "ESC" "togglemenu" +bind "w" "+forward" +bind "s" "+back" +bind "a" "+moveleft" +bind "d" "+moveright" +bind "SPACE" "+jump" +bind "CTRL" "+duck" +bind "SHIFT" "+speed" +bind "0" "slot10" +bind "1" "slot1" +bind "2" "slot2" +bind "3" "slot3" +bind "4" "slot4" +bind "5" "slot5" +bind "6" "slot6" +bind "7" "slot7" +bind "8" "slot8" +bind "9" "slot9" +bind "UPARROW" "+forward" +bind "DOWNARROW" "+back" +bind "LEFTARROW" "+left" +bind "RIGHTARROW" "+right" +bind "MOUSE1" "+attack" +bind "MOUSE2" "+attack2" +bind "MWHEELDOWN" "invnext" +bind "MWHEELUP" "invprev" +bind "r" "+reload" +bind "e" "+use" +bind "TAB" "+showscores" +bind "y" "messagemode" +bind "u" "messagemode2" +bind "t" "impulse 201" +bind "f" "impulse 100" +bind "f1" "vote yes" +bind "f2" "vote no" + +// Counter-Strike Binds +bind "b" "buy" +bind "m" "chooseteam" +bind "g" "drop" +bind "q" "lastinv" + +// Game Variables +seta "hostname" "FreeCS Server" +seta "maxplayers" "8" +seta "mp_startmoney" "800" +seta "mp_buytime" "90" +seta "mp_freezetime" "6" +seta "mp_c4timer" "45" +seta "mp_roundtime" "5" +seta "fcs_knifeonly" "0" +seta "fcs_swapteams" "0" +seta "fcs_nopickups" "0" +seta "fcs_reward_kill" "300" +seta "fcs_penalty_pain" "-150" +seta "fcs_penalty_kill" "-1500" +seta "fcs_maxmoney" "16000" +seta "fcs_fillweapons" "0" +seta "fcs_autoreload" "0" + +// 2D/HUD Variables +seta "con_color" "255 150 0" +seta "vgui_color" "255 170 0" +seta "cross_color" "0 255 0" diff --git a/zpak001.pk3dir/gfx/vgui/buymenu.tga b/zpak001.pk3dir/gfx/vgui/buymenu.tga new file mode 100644 index 0000000000000000000000000000000000000000..9afcaab3818464362b2cb73c24e3be85068f8757 GIT binary patch literal 574 zcmZvZy-UMT6va=#+9D1eIyj1hsHlrLI!T3qRPdvSe}JPPt`4!uM`ja~)U4ZLrBF|Z}7cElyAaX9U7#oK3Ga(oH>W$JzrFSMPsPZ~gklI~BdJClv*$L}N_nrMZS zyez89E5;|+SFBahjTJQgu>-Ri YN8*;l=K5B-YHpZomAUN|bG1B=U!{oHL;wH) literal 0 HcmV?d00001 diff --git a/zpak001.pk3dir/particles/fx_smokenade.cfg b/zpak001.pk3dir/particles/fx_smokenade.cfg new file mode 100644 index 0000000..1df4014 --- /dev/null +++ b/zpak001.pk3dir/particles/fx_smokenade.cfg @@ -0,0 +1,15 @@ +r_part effect +{ + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + count 1 + scale 512 + scalefactor 1 + die 3 + alpha 0.7 + rgb 128 128 128 + spawnmode ball + gravity -25 + veladd -20 + randomvel 64 -64 +} diff --git a/zpak001.pk3dir/sound/items_cstrike.sndshd b/zpak001.pk3dir/sound/items_cstrike.sndshd new file mode 100644 index 0000000..cf7d022 --- /dev/null +++ b/zpak001.pk3dir/sound/items_cstrike.sndshd @@ -0,0 +1,14 @@ +buy.kevlar +{ + sample items/tr_kevlar.wav +} + +buy.weapon +{ + sample items/gunpickup2.wav +} + +buy.ammo +{ + sample items/9mmclip1.wav +} diff --git a/zpak001.pk3dir/sound/npcs_cstrike.sndshd b/zpak001.pk3dir/sound/npcs_cstrike.sndshd new file mode 100644 index 0000000..048524d --- /dev/null +++ b/zpak001.pk3dir/sound/npcs_cstrike.sndshd @@ -0,0 +1,8 @@ +hostage_entity.follow +{ + sample hostage/hos1.wav + sample hostage/hos2.wav + sample hostage/hos3.wav + sample hostage/hos4.wav + sample hostage/hos5.wav +} diff --git a/zpak001.pk3dir/sound/weapons_cstrike.sndshd b/zpak001.pk3dir/sound/weapons_cstrike.sndshd new file mode 100644 index 0000000..901a514 --- /dev/null +++ b/zpak001.pk3dir/sound/weapons_cstrike.sndshd @@ -0,0 +1,231 @@ +weapon_ak47.fire +{ + sample weapons/ak47-1.wav + sample weapons/ak47-2.wav +} + +weapon_aug.fire +{ + sample weapons/aug-1.wav +} + +weapon_awp.fire +{ + sample weapons/awp1.wav +} + +weapon_awp.zoom +{ + sample weapons/zoom.wav +} + +weapon_c4bomb.disarm +{ + sample weapons/c4_disarm.wav +} + +weapon_c4bomb.disarmed +{ + sample weapons/c4_disarmed.wav +} + +weapon_c4bomb.explode +{ + sample weapons/c4_explode1.wav +} + +weapon_c4bomb.plant +{ + sample weapons/c4_plant.wav +} + +weapon_deagle.fire +{ + sample weapons/deagle-1.wav + sample weapons/deagle-2.wav +} + +weapon_elites.fire +{ + sample weapons/elite_fire.wav + sample weapons/elite_fire.wav +} + +weapon_fiveseven.fire +{ + sample weapons/fiveseven-1.wav +} + +weapon_flashbang.explode +{ + sample weapons/flashbang-1.wav +} + +weapon_g3sg1.fire +{ + sample weapons/g3sg1-1.wav +} + +weapon_glock18.fire +{ + sample weapons/glock18-2.wav +} + +weapon_glock18.burstfire +{ + sample weapons/glock18-1.wav +} + +weapon_hegrenade.bounce +{ + sample weapons/he_bounce-1.wav +} + +weapon_hegrenade.explode +{ + sample weapons/explode3.wav + sample weapons/explode4.wav +} + +weapon_smokegrenade.bounce +{ + sample weapons/grenade_hit1.wav + sample weapons/grenade_hit2.wav + sample weapons/grenade_hit3.wav +} + +weapon_smokegrenade.explode +{ + sample weapons/sg_explode.wav +} + +weapon_flashbang.bounce +{ + sample weapons/grenade_hit1.wav + sample weapons/grenade_hit2.wav + sample weapons/grenade_hit3.wav +} + +weapon_flashbang.explode +{ + sample weapons/flashbang-1.wav + sample weapons/flashbang-2.wav +} + +weapon_knife.hit +{ + sample weapons/knife_hitwall1.wav +} + +weapon_knife.hitbody +{ + sample weapons/knife_hit1.wav + sample weapons/knife_hit2.wav + sample weapons/knife_hit3.wav + sample weapons/knife_hit4.wav +} + +weapon_knife.hithard +{ + sample weapons/knife_stab.wav +} + +weapon_knife.miss +{ + sample weapons/knife_slash1.wav +} + +weapon_m3.fire +{ + sample weapons/m3-1.wav +} + +weapon_m4a1.fire +{ + sample weapons/m4a1_unsil-1.wav + sample weapons/m4a1_unsil-2.wav +} + +weapon_m4a1.silenced +{ + sample weapons/m4a1-1.wav +} + +weapon_mac10.fire +{ + sample weapons/mac10-1.wav +} + +weapon_mp5.fire +{ + sample weapons/mp5-1.wav +} + +weapon_p228.fire +{ + sample weapons/p228-1.wav +} + +weapon_p90.fire +{ + sample weapons/p90-1.wav +} + + +weapon_para.fire +{ + sample weapons/m249-1.wav + sample weapons/m249-2.wav +} + +weapon_scout.fire +{ + sample weapons/scout_fire-1.wav +} + +weapon_sg550.fire +{ + sample weapons/sg550-1.wav +} + +weapon_sg552.fire +{ + sample weapons/sg552-1.wav +} + +weapon_smokegrenade.explode +{ + sample weapons/sg_explode.wav +} + +weapon_tmp.fire +{ + sample weapons/tmp-1.wav + sample weapons/tmp-2.wav +} + +weapon_ump45.fire +{ + sample weapons/ump45-1.wav +} + +weapon_usp45.fire +{ + sample weapons/usp_unsil-1.wav +} + +weapon_usp45.silenced +{ + sample weapons/usp1.wav + sample weapons/usp2.wav +} + +weapon_xm1014.fire +{ + sample weapons/xm1014-1.wav +} + +weapon_xm1014.insertshell +{ + sample weapons/m3_insertshell.wav +}