From 181090b7019751de854fb80cd1bf21ddeb350267 Mon Sep 17 00:00:00 2001 From: Xylemon Date: Sun, 23 Apr 2023 04:05:45 -0700 Subject: [PATCH] Insanity is now fully reimplemented --- src/client/defs.h | 69 +++++ src/client/hud.qc | 612 ++++++++++++++++++++++++++++++++++++++++ src/client/progs.src | 9 +- src/server/gamerules.h | 9 +- src/server/gamerules.qc | 96 ++++++- src/server/server.qc | 3 +- src/shared/include.src | 1 + src/shared/player.qc | 17 +- src/shared/pmove.qc | 90 ++++++ 9 files changed, 882 insertions(+), 24 deletions(-) create mode 100644 src/client/defs.h create mode 100644 src/client/hud.qc create mode 100644 src/shared/pmove.qc diff --git a/src/client/defs.h b/src/client/defs.h new file mode 100644 index 0000000..f89fe9b --- /dev/null +++ b/src/client/defs.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016-2023 Marco Cawthorne + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "../../../valve/src/client/obituary.h" +#include "../../../valve/src/client/particles.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_cross_spr; +var string g_laser_spr; + +/* muzzleflash indices */ +var int MUZZLE_SMALL; +var int MUZZLE_RIFLE; +var int MUZZLE_WEIRD; + +struct +{ + /* 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_iAmmoInsaneOld; + float m_flAmmoInsaneAlpha; + int m_iPickupWeapon; + float m_flPickupAlpha; + int m_iHUDWeaponSelected; + float m_flHUDWeaponSelectTime; + int m_iItemsOld; + + float m_flDamageIndicator; +} g_seatslocal[4], *pSeatLocal; + +void HUD_DrawAmmo1(void); +void HUD_DrawAmmo2(void); +void HUD_DrawAmmo3(void); +void HUD_DrawAmmoBar(vector pos, float val, float max, float a); +void HUD_WeaponPickupNotify(int); diff --git a/src/client/hud.qc b/src/client/hud.qc new file mode 100644 index 0000000..692f491 --- /dev/null +++ b/src/client/hud.qc @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2016-2023 Marco Cawthorne + * Copyright (c) 2016-2023 Gethyn ThomasQuail + * + * 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/128 +#define HUD_ALPHA 0.5 + +float spr_hudnum[10] = { + 0 / 256, + 24 / 256, + (24*2) / 256, + (24*3) / 256, + (24*4) / 256, + (24*5) / 256, + (24*6) / 256, + (24*7) / 256, + (24*8) / 256, + (24*9) / 256 +}; + +/* pre-calculated sprite definitions */ +float spr_health[4] = { + 80 / 256, // pos x + 24 / 128, // pos u + 32 / 256, // size x + 32 / 128 // size y +}; + +float spr_suit1[4] = { + 0 / 256, // pos x + 24 / 128, // pos u + 40 / 256, // size x + 40 / 128 // size y +}; + +float spr_suit2[4] = { + 40 / 256, // pos x + 24 / 128, // pos u + 40 / 256, // size x + 40 / 128 // size y +}; + +float spr_flash1[4] = { + 160 / 256, // pos x + 24 / 128, // pos u + 32 / 256, // size x + 32 / 128 // size y +}; + +float spr_flash2[4] = { + 112 / 256, // pos x + 24 / 128, // pos u + 48 / 256, // size x + 32 / 128 // size y +}; + +string g_hud_insanity01; +string g_hud_insanity02; +string g_hud_insanity03; + +/* precaches */ +void +HUD_Init(void) +{ + g_cross_spr = spriteframe("sprites/crosshairs.spr", 0, 0.0f); + g_laser_spr = spriteframe("sprites/laserdot.spr", 0, 0.0f); + 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_hud_insanity01 = spriteframe("sprites/insanity.spr", 0, 0.0f); + g_hud_insanity02 = spriteframe("sprites/insanity2.spr", 0, 0.0f); + g_hud_insanity03 = spriteframe("sprites/insanity3.spr", 0, 0.0f); + + HUD_AmmoNotify_Init(); + HUD_DamageNotify_Init(); + HUD_ItemNotify_Init(); +} + +/* seperator for mainly ammo */ +void +HUD_DrawSeperator(vector pos) +{ + drawsubpic(pos, + [2,24], + g_hud7_spr, + [240/256, 0], + [2/256, 24/128], + g_hud_color, + HUD_ALPHA, + DRAWFLAG_ADDITIVE + ); +} + +/* handle single/multiple digits */ +void +HUD_DrawNumber(int iNumber, vector vecPos, float fAlpha, vector vColor) +{ + drawsubpic(vecPos, + [24,24], + g_hud7_spr, + [spr_hudnum[iNumber], 0], + [NUMSIZE_X, NUMSIZE_Y], + 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.0f, vecPos, fAlpha, vColor); + i = i / 10; + vecPos[0] -= 20; + } + } else { + HUD_DrawNumber(0, vecPos, fAlpha, vColor); + } +} + +/* health */ +void +HUD_DrawHealth(void) +{ + vector pos; + player pl = (player)pSeat->m_ePlayer; + + if (pl.health != pSeatLocal->m_iHealthOld) { + pSeatLocal->m_flHealthAlpha = 1.0; + } + + if (pSeatLocal->m_flHealthAlpha >= HUD_ALPHA) { + pSeatLocal->m_flHealthAlpha -= clframetime * 0.5; + } else { + pSeatLocal->m_flHealthAlpha = HUD_ALPHA; + } + + pos = g_hudmins + [88, g_hudres[1] - 42]; + if (pl.health > 25) { + drawsubpic( + pos + [-72,-4], + [32,32], + g_hud7_spr, + [spr_health[0], spr_health[1]], + [spr_health[2], spr_health[3]], + g_hud_color, + pSeatLocal->m_flHealthAlpha, + DRAWFLAG_ADDITIVE + ); + HUD_DrawNums(pl.health, pos, pSeatLocal->m_flHealthAlpha, g_hud_color); + } else { + drawsubpic( + pos + [-72,-4], + [32,32], + g_hud7_spr, + [spr_health[0], spr_health[1]], + [spr_health[2], spr_health[3]], + [1,0,0], + pSeatLocal->m_flHealthAlpha, + DRAWFLAG_ADDITIVE + ); + HUD_DrawNums(pl.health, pos, pSeatLocal->m_flHealthAlpha, [1,0,0]); + } + + pSeatLocal->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 != pSeatLocal->m_iArmorOld) { + pSeatLocal->m_flArmorAlpha = 1.0; + } + + if (pSeatLocal->m_flArmorAlpha >= HUD_ALPHA) { + pSeatLocal->m_flArmorAlpha -= clframetime * 0.5; + } else { + pSeatLocal->m_flArmorAlpha = HUD_ALPHA; + } + + drawsubpic( + pos + [-80,-9], + [40,40], + g_hud7_spr, + [spr_suit2[0], spr_suit2[1]], + [spr_suit2[2], spr_suit2[3]], + g_hud_color, + pSeatLocal->m_flArmorAlpha, + DRAWFLAG_ADDITIVE + ); + + if (pl.armor > 0) { + float perc = bound(0, (pl.armor / 100), 1.0); + drawsubpic( + pos + [-80,-9] + [0, 40 * (1.0-perc)], + [40, 40 * perc], + g_hud7_spr, + [spr_suit1[0],spr_suit1[1] + spr_suit1[3] * (1.0-perc)], + [spr_suit1[2], spr_suit1[3] * perc], + g_hud_color, + pSeatLocal->m_flArmorAlpha, + DRAWFLAG_ADDITIVE + ); + } + + HUD_DrawNums(pl.armor, pos, pSeatLocal->m_flArmorAlpha, g_hud_color); + pSeatLocal->m_iArmorOld = pl.armor; +} + +/* magazine/clip ammo */ +void +HUD_DrawAmmo1(void) +{ + player pl = (player)pSeat->m_ePlayer; + vector pos; + + if (pl.a_ammo1 != pSeatLocal->m_iAmmo1Old) { + pSeatLocal->m_flAmmo1Alpha = 1.0; + pSeatLocal->m_iAmmo1Old = pl.a_ammo1; + } + + if (pSeatLocal->m_flAmmo1Alpha >= HUD_ALPHA) { + pSeatLocal->m_flAmmo1Alpha -= clframetime * 0.5; + } else { + pSeatLocal->m_flAmmo1Alpha = HUD_ALPHA; + } + + pos = g_hudmins + [g_hudres[0] - 152, g_hudres[1] - 42]; + HUD_DrawNums(pl.a_ammo1, pos, pSeatLocal->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 != pSeatLocal->m_iAmmo2Old) { + pSeatLocal->m_flAmmo2Alpha = 1.0; + pSeatLocal->m_iAmmo2Old = pl.a_ammo2; + } + + if (pSeatLocal->m_flAmmo2Alpha >= HUD_ALPHA) { + pSeatLocal->m_flAmmo2Alpha -= clframetime * 0.5; + } else { + pSeatLocal->m_flAmmo2Alpha = HUD_ALPHA; + } + + pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 42]; + HUD_DrawNums(pl.a_ammo2, pos, pSeatLocal->m_flAmmo2Alpha, g_hud_color); +} + +/* special ammo */ +void +HUD_DrawAmmo3(void) +{ + player pl = (player)pSeat->m_ePlayer; + vector pos; + + if (pl.a_ammo3 != pSeatLocal->m_iAmmo3Old) { + pSeatLocal->m_flAmmo3Alpha = 1.0; + pSeatLocal->m_iAmmo3Old = pl.a_ammo3; + } + + if (pSeatLocal->m_flAmmo3Alpha >= HUD_ALPHA) { + pSeatLocal->m_flAmmo3Alpha -= clframetime * 0.5; + } else { + pSeatLocal->m_flAmmo3Alpha = HUD_ALPHA; + } + + pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 74]; + HUD_DrawNums(pl.a_ammo3, pos, pSeatLocal->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,0], [20,4], g_hud_color, a, DRAWFLAG_NORMAL); + drawfill(pos + [10,0], [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 + ); + } +} + +/* logo animation used during e3 1998 */ +void +HUD_DrawLogo(void) +{ + vector pos; + static int f; + static float frame_timer; + + frame_timer -= clframetime; + pos = [g_hudres[0] - 262, 48]; + + drawpic( + pos, + sprintf("sprites/640_logo.spr_%i.tga", f), + [256,48], + [1,1,1], + 1.0f, + DRAWFLAG_ADDITIVE + ); + + if (frame_timer > 0) { + return; + } + + frame_timer = 0.1f; + + f++; + if (f == 31) { + f = 0; + } +} + +/* weapon/ammo pickup notifications */ +void +HUD_DrawNotify(void) +{ + player pl = (player)self; + vector pos; + float a; + + pos = g_hudmins + [g_hudres[0] - 192, g_hudres[1] - 128]; + + if (pSeatLocal->m_flPickupAlpha <= 0.0f) { + pos[1] += 48; + HUD_ItemNotify_Draw(pos); + HUD_AmmoNotify_Draw(pos); + return; + } + + a = bound(0.0, pSeatLocal->m_flPickupAlpha, 1.0); + pos[1] += 48 * (1.0 - a); + Weapons_HUDPic(pl, pSeatLocal->m_iPickupWeapon, 1, pos, a); + HUD_ItemNotify_Draw(pos); + HUD_AmmoNotify_Draw(pos); + pSeatLocal->m_flPickupAlpha -= (clframetime * 0.5); +} + +void +HUD_WeaponPickupNotify(int w) +{ +#if defined (VALVE) || defined (GEARBOX) + switch (w) { + case WEAPON_SNARK: + case WEAPON_SATCHEL: + case WEAPON_HANDGRENADE: + case WEAPON_TRIPMINE: +#if defined(GEARBOX) + case WEAPON_PENGUIN: +#endif + return; + default: + } +#endif + + pSeatLocal->m_iPickupWeapon = w; + pSeatLocal->m_flPickupAlpha = 2.5f; +} + +void +HUD_DrawDamageIndicator(void) +{ + vector cross_pos; + + if (pSeatLocal->m_flDamageIndicator <= 0.0) + return; + + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + + /*drawsubpic( + cross_pos, + [24,24], + g_cross_spr, + [0.0, 72/128], + [0.1875, 0.1875], + [1,1,1] * pSeatLocal->m_flDamageIndicator, + 1.0f, + DRAWFLAG_ADDITIVE + );*/ + + pSeatLocal->m_flDamageIndicator -= clframetime; +} + +void +HUD_DrawInsanityIcon(void) +{ + player pl = (player)pSeat->m_ePlayer; + vector pos; + float insanityalpha; + pos = g_hudmins + [13, g_hudres[1] - 92]; + + if (pl.gflags & GF_MADNESS) { + insanityalpha = bound(0,pl.sh_insaneactive * 0.05f,0.4); + drawfill( + video_mins, + video_res, + [1,0,0], + insanityalpha, + DRAWFLAG_ADDITIVE + ); + } + + if (pl.gflags & GF_MADNESS) { + drawsubpic(pos, + [40, 40], + g_hud_insanity01, + [0, 0], + [1.0, 1.0], + [1,1,1], + 1.0f, + 0 + ); + } + if (pl.sh_insaneactive > 40) { + drawsubpic(pos, + [40, 40], + g_hud_insanity02, + [0, 0], + [1.0, 1.0], + [1,1,1], + 1.0f, + 0 + ); + } + if (pl.sh_insaneactive > 50) { + drawsubpic(pos, + [40, 40], + g_hud_insanity03, + [0, 0], + [1.0, 1.0], + [1,1,1], + 1.0f, + 0 + ); + } +} + + +void +HUD_DrawInsanityTime(void) +{ + player pl = (player)pSeat->m_ePlayer; + vector pos; + float insanecount = floor(pl.sh_insaneactive); + + if (pl.gflags & GF_MADNESS) { + if (insanecount != pSeatLocal->m_iAmmoInsaneOld) { + pSeatLocal->m_flAmmoInsaneAlpha = 1.0; + pSeatLocal->m_iAmmoInsaneOld = insanecount; + } + + if (pSeatLocal->m_flAmmoInsaneAlpha >= HUD_ALPHA) { + pSeatLocal->m_flAmmoInsaneAlpha -= clframetime * 0.5; + } else { + pSeatLocal->m_flAmmoInsaneAlpha = HUD_ALPHA; + } + + pos = g_hudmins + [76, g_hudres[1] - 84]; + HUD_DrawNums(insanecount, pos, pSeatLocal->m_flAmmoInsaneAlpha, g_hud_color); + } +} + + +/* main entry */ +void +HUD_Draw(void) +{ + player pl = (player)pSeat->m_ePlayer; + +#ifndef TFC + g_hud_color = autocvar_con_color * (1 / 255); +#endif + + /* little point in not drawing these, even if you don't have a suit */ + Weapons_DrawCrosshair(pl); + HUD_DrawDamageIndicator(); + HUD_DrawWeaponSelect(); + Obituary_Draw(); + Textmenu_Draw(); + + if (!(pl.g_items & ITEM_SUIT)) { + return; + } + + HUD_DrawInsanityIcon(); + HUD_DrawInsanityTime(); + + HUD_DamageNotify_Draw(); + HUD_DrawHealth(); + HUD_DrawArmor(); + HUD_DrawFlashlight(); + HUD_DrawNotify(); + Damage_Draw(); +} + +string g_specmodes[] = { + "Free Camera", + "Third Person", + "First Person" +}; + +/* specatator main entry */ +void +HUD_DrawSpectator(void) +{ + Textmenu_Draw(); + + NSClientSpectator spec = (NSClientSpectator)pSeat->m_ePlayer; + + drawfont = Font_GetID(FONT_20); + vector vecPos = [0.0f, 0.0f, 0.0f]; + string strText = __NULL__; + float palpha = 1.0f; + + if (spec.spec_mode == SPECMODE_FREE) { + palpha = 0.5f; + } + + strText = sprintf("Tracking: %s", getplayerkeyvalue(spec.spec_ent - 1, "name")); + vecPos[0] = g_hudmins[0] + (g_hudres[0] / 2) - (stringwidth(strText, TRUE, [20,20]) / 2); + vecPos[1] = g_hudmins[1] + g_hudres[1] - 60; + drawstring(vecPos, strText, [20,20], [1,1,1], palpha, DRAWFLAG_ADDITIVE); + + strText = sprintf("Mode: %s", g_specmodes[spec.spec_mode]); + vecPos[0] = g_hudmins[0] + (g_hudres[0] / 2) - (stringwidth(strText, TRUE, [20,20]) / 2); + vecPos[1] = g_hudmins[1] + g_hudres[1] - 40; + drawstring(vecPos, strText, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); +} diff --git a/src/client/progs.src b/src/client/progs.src index f68dad7..f366f4d 100644 --- a/src/client/progs.src +++ b/src/client/progs.src @@ -10,7 +10,7 @@ #includelist ../../../src/shared/fteextensions.qc ../../../src/shared/defs.h -../../../valve/src/client/defs.h +defs.h ../../../src/client/defs.h ../../../src/vgui/include.src @@ -21,7 +21,7 @@ ../../../valve/src/client/damage.qc draw.qc -../../../valve/src/client/init.qc +init.qc ../../../valve/src/client/flashlight.qc ../../../valve/src/client/entities.qc cmds.qc @@ -33,12 +33,13 @@ cmds.qc ../../../valve/src/client/hud_ammonotify.qc ../../../valve/src/client/hud_dmgnotify.qc ../../../valve/src/client/hud_itemnotify.qc -../../../valve/src/client/hud.qc +hud.qc ../../../valve/src/client/hud_weaponselect.qc ../../../valve/src/client/scoreboard.qc ../../../valve/src/client/modelevent.qc ../../../src/client/include.src -../../../valve/src/client/vgui_motd.qc +vgui_motd.qc +vgui_chooseteam.qc ../../../src/shared/include.src #endlist diff --git a/src/server/gamerules.h b/src/server/gamerules.h index ead44b8..d938ff0 100644 --- a/src/server/gamerules.h +++ b/src/server/gamerules.h @@ -56,7 +56,11 @@ class SHTeamRules:HLGameRules virtual bool(void) IsTeamplay; virtual void(void) AddTeam1Kill; virtual void(void) AddTeam2Kill; + virtual void(void) RemoveTeam1Kill; + virtual void(void) RemoveTeam2Kill; + virtual void(void) RegisterSciDeathHuntTeam; virtual void(NSClientPlayer, entity) ScientistKill; + virtual void(NSClientPlayer, entity) ScientistKillFear; virtual void(void) InitPostEnts; }; @@ -66,8 +70,6 @@ class SHTeamRules:HLGameRules class SHGameHunt:SHTeamRules { void(void) SHGameHunt; - - virtual void(void) RegisterSciDeath; }; /* Stealth Hunting (1): @@ -75,7 +77,6 @@ class SHGameHunt:SHTeamRules */ class SHGameStealth:SHTeamRules { - void(void) SHGameStealth; }; @@ -84,7 +85,6 @@ class SHGameStealth:SHTeamRules */ class SHGameSlaughter:HLGameRules { - void(void) SHGameSlaughter; }; @@ -93,7 +93,6 @@ class SHGameSlaughter:HLGameRules */ class SHGameFear:HLGameRules { - void(void) SHGameFear; }; diff --git a/src/server/gamerules.qc b/src/server/gamerules.qc index 21433f6..52441c4 100644 --- a/src/server/gamerules.qc +++ b/src/server/gamerules.qc @@ -1,5 +1,6 @@ /* - * Copyright (c) 2016-2020 Marco Cawthorne + * Copyright (c) 2016-2023 Marco Cawthorne + * Copyright (c) 2016-2023 Gethyn ThomasQuail * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -45,6 +46,9 @@ HLGameRules::IsMultiplayer(void) void HLGameRules::PlayerDeath(NSClientPlayer pl) { + + player sh_pl = (player)pl; + /* obituary networking */ WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); WriteByte(MSG_MULTICAST, EV_OBITUARY); @@ -71,10 +75,14 @@ HLGameRules::PlayerDeath(NSClientPlayer pl) g_dmg_eAttacker.frags++; } + pl.Death(); pl.takedamage = DAMAGE_NO; pl.gflags &= ~GF_FLASHLIGHT; pl.gflags &= ~GF_EGONBEAM; + pl.gflags &= ~GF_MADNESS; + + sh_pl.sh_insaneactive = 0.0f; pl.think = PutClientInServer; pl.nextthink = time + 4.0f; @@ -239,14 +247,20 @@ HLGameRules::PlayerPostFrame(NSClientPlayer pp) pl.sh_insaneactive = bound(0.0f, pl.sh_insaneactive - frametime, pl.sh_insaneactive); - if (pl.sh_insaneactive > 0.0f) - pl.gflags |= GF_MADNESS; - else { + /* Apply insanity flag to players, and players only */ + if (pl.sh_insaneactive > 0.0f) { + if not (pl.gflags & GF_MADNESS) { + pl.gflags |= GF_MADNESS; + bprint(PRINT_HIGH, sprintf("%s is going insane!\n", pl.netname)); + Sound_Play(pl, CHAN_AUTO, "player.insane"); + } + } else { if (pl.gflags & GF_MADNESS) { - bprint(PRINT_CHAT, sprintf("%s is no longer insane!\n", pl.netname)); + bprint(PRINT_HIGH, sprintf("%s is no longer insane!\n", pl.netname)); } pl.gflags &= ~GF_MADNESS; } + } void @@ -275,10 +289,12 @@ HLGameRules::ScientistKill(NSClientPlayer pp, entity sci) msg_entity = world; multicast([0,0,0], MULTICAST_ALL); + /* give players a frag per scientist they kill */ pl.frags++; - /*if (g_weapons[g_dmg_iWeapon].slot != 0) - return;*/ + /* only reward melee frags for insanity, otherwise it's a bit OP */ + if (g_weapons[g_dmg_iWeapon].slot != 0) + return; /* if this is our first kill in a while, or in the timer... */ if (pl.sh_insanecount == 0 || pl.sh_insanetime > time) { @@ -288,11 +304,15 @@ HLGameRules::ScientistKill(NSClientPlayer pp, entity sci) } if (pl.sh_insanecount >= autocvar_sh_insanity) { - if (pl.sh_insaneactive <= 0.0f) - bprint(PRINT_CHAT, sprintf("%s is going insane!\n", pl.netname)); - - pl.sh_insaneactive += 3.0f; + /* always start with a 30 second cooldown + * otherwise give 3 seconds per frag */ + if (pl.gflags & GF_MADNESS) { + pl.sh_insaneactive += 3.0f; + } else { + pl.sh_insaneactive += 30.0f; + } + /* clamp our timer */ if (pl.sh_insaneactive > 60) pl.sh_insaneactive = 60; } @@ -402,6 +422,18 @@ SHTeamRules::ScientistKill(NSClientPlayer cl, entity sci) AddTeam1Kill(); } +void +SHTeamRules::ScientistKillFear(NSClientPlayer cl, entity sci) +{ + super::ScientistKill(cl, sci); + + if (cl.team == 2) + RemoveTeam2Kill(); + else if (cl.team == 1) + AddTeam1Kill(); +} + + void SHTeamRules::AddTeam1Kill(void) { @@ -416,6 +448,48 @@ SHTeamRules::AddTeam2Kill(void) forceinfokey(world, "teamkills_2", sprintf("%i", m_iKillsTeam2)); } +void +SHTeamRules::RemoveTeam1Kill(void) +{ + m_iKillsTeam1--; + forceinfokey(world, "teamkills_1", sprintf("%i", m_iKillsTeam1)); +} + +void +SHTeamRules::RemoveTeam2Kill(void) +{ + m_iKillsTeam2--; + forceinfokey(world, "teamkills_2", sprintf("%i", m_iKillsTeam2)); +} + +void +SHTeamRules::RegisterSciDeathHuntTeam(void) +{ + super::RegisterSciDeath(); + + if (m_iScientistsAlive > 0) + return; + + switch (g_chosen_mode) { + case SHMODE_STANDARD: + if (m_iKillsTeam1 > m_iKillsTeam2) { + m_iScoreTeam1++; + env_message_broadcast("Red team has won!"); + } else if (m_iKillsTeam1 > m_iKillsTeam2) { + m_iScoreTeam2++; + env_message_broadcast("Blue team has won!"); + } else { + env_message_broadcast("Both teams are tied!"); + } + + forceinfokey(world, "teamscore_1", sprintf("%i", m_iScoreTeam1)); + forceinfokey(world, "teamscore_2", sprintf("%i", m_iScoreTeam2)); + think = RestartRound; + nextthink = time + 5.0f; + break; + } +} + void SHTeamRules::InitPostEnts(void) { diff --git a/src/server/server.qc b/src/server/server.qc index dc3841e..ff189c6 100644 --- a/src/server/server.qc +++ b/src/server/server.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Marco Cawthorne + * Copyright (c) 2016-2023 Marco Cawthorne * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -46,6 +46,7 @@ Game_Worldspawn(void) precache_model("models/player.mdl"); precache_model("models/w_weaponbox.mdl"); Sound_Precache("player.die"); + Sound_Precache("player.insane"); Sound_Precache("player.fall"); Sound_Precache("player.lightfall"); diff --git a/src/shared/include.src b/src/shared/include.src index b745987..6e74bdf 100644 --- a/src/shared/include.src +++ b/src/shared/include.src @@ -3,6 +3,7 @@ ../../../valve/src/shared/events.h ../../../valve/src/shared/flags.h player.qc +pmove.qc ../../../valve/src/shared/weapon_common.h ../../../valve/src/shared/animations.h ../../../valve/src/shared/animations.qc diff --git a/src/shared/player.qc b/src/shared/player.qc index fe0225f..8d9ab0b 100644 --- a/src/shared/player.qc +++ b/src/shared/player.qc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2021 Marco Cawthorne + * Copyright (c) 2016-2023 Marco Cawthorne * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -144,6 +144,8 @@ class player:NSClientPlayer PREDICTED_INT(ammo_chainsaw_state) PREDICTED_INT(ammo_hammer_state) + PREDICTED_FLOAT(sh_insanetime) + PREDICTED_FLOAT(sh_insaneactive) PREDICTED_FLOAT(anim_top) PREDICTED_FLOAT(anim_top_time) PREDICTED_FLOAT(anim_top_delay) @@ -151,6 +153,9 @@ class player:NSClientPlayer PREDICTED_FLOAT(anim_bottom_time) virtual void UpdatePlayerAnimation(float); + virtual float Physics_MaxSpeed(void); + virtual void Physics_InputPreMove(void); + virtual void Physics_InputPostMove(void); #ifdef CLIENT virtual void UpdatePlayerAttachments(bool); @@ -162,8 +167,6 @@ class player:NSClientPlayer virtual float(entity, float) SendEntity; int sh_insanecount; - float sh_insanetime; - float sh_insaneactive; #endif }; @@ -322,6 +325,8 @@ player::ReceiveEntity(float new, float fl) mode_tempstate = readbyte(); ammo_chainsaw_state = readbyte(); ammo_hammer_state = readbyte(); + sh_insanetime = readfloat(); + sh_insaneactive = readfloat(); } setorigin(this, origin); @@ -518,6 +523,10 @@ player::EvaluateEntity(void) SendFlags |= PLAYER_AMMO3; else if (ATTR_CHANGED(ammo_hammer_state)) SendFlags |= PLAYER_AMMO3; + else if (ATTR_CHANGED(sh_insanetime)) + SendFlags |= PLAYER_AMMO3; + else if (ATTR_CHANGED(sh_insaneactive)) + SendFlags |= PLAYER_AMMO3; SAVE_STATE(glock_mag) SAVE_STATE(mp5_mag) @@ -623,6 +632,8 @@ player::SendEntity(entity ePEnt, float flChanged) WriteByte(MSG_ENTITY, mode_tempstate); WriteByte(MSG_ENTITY, ammo_chainsaw_state); WriteByte(MSG_ENTITY, ammo_hammer_state); + WriteFloat(MSG_ENTITY, sh_insanetime); + WriteFloat(MSG_ENTITY, sh_insaneactive); } return (1); diff --git a/src/shared/pmove.qc b/src/shared/pmove.qc new file mode 100644 index 0000000..027d075 --- /dev/null +++ b/src/shared/pmove.qc @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016-2023 Marco Cawthorne + * Copyright (c) 2016-2023 Gethyn ThomasQuail + * + * 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_AIRSTEPHEIGHT 0 +#define PMOVE_STEPHEIGHT 18 +#define PMOVE_FRICTION 4 +#define PMOVE_EDGEFRICTION 1 +#define PMOVE_STOPSPEED 100 +#define PMOVE_GRAVITY 800 +#define PMOVE_AIRACCELERATE 10 +#define PMOVE_WATERACCELERATE 10 +#define PMOVE_ACCELERATE 10 +#define PMOVE_MAXSPEED 270 +#define PMOVE_STEP_WALKSPEED 135 +#define PMOVE_STEP_RUNSPEED 220 +#define PHY_VIEWPOS [0,0,28] +#define PHY_VIEWPOS_CROUCHED [0,0,12] +#include "items.h" + + /* insanity changes player move and attack speed */ + +void +player::Physics_InputPreMove(void) +{ + float insanecooldown; + + super::Physics_InputPreMove(); + + if (gflags & GF_MADNESS) { + /* give us a nice transition from insanity */ + insanecooldown = bound(1,sh_insaneactive * 0.1f,3); + input_movevalues *= insanecooldown; + } +} + +void +player::Physics_InputPostMove(void) +{ + super::Physics_InputPostMove(); + if (gflags & GF_MADNESS) { + w_attack_next = max(0, w_attack_next - input_timelength); + } +} + +float +player::Physics_MaxSpeed(void) +{ + if (gflags & GF_MADNESS) { + return 1000.0f; + } else { + return super::Physics_MaxSpeed(); + } +} + +void +player::Physics_Jump(void) +{ + if (waterlevel >= 2) { + if (watertype == CONTENT_WATER) { + velocity[2] = 100; + } else if (watertype == CONTENT_SLIME) { + velocity[2] = 80; + } else { + velocity[2] = 50; + } + } else { + /* Half-Life: Longjump module */ + if (flags & FL_CROUCHING && g_items & 0x00008000i) { + makevectors([0, v_angle[1], 0]); + velocity = v_forward * 512; + velocity[2] += 100; + } + if (flags & FL_ONGROUND) + velocity[2] += 265; + } +}