From 1a25ccc3341ed6e01b75d66f9f4fd2fb3273ac2f Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Mon, 8 Mar 2021 10:53:48 +0100 Subject: [PATCH] Initial commit, carried over from Nuclide's Git on March 8th 2021 --- LICENSE | 15 + README.md | 46 ++ img/preview1.jpg | Bin 0 -> 91410 bytes img/preview2.jpg | Bin 0 -> 71890 bytes img/preview3.jpg | Bin 0 -> 94432 bytes img/preview4.jpg | Bin 0 -> 122773 bytes src/Makefile | 5 + src/client/Makefile | 4 + src/client/cmds.qc | 25 + src/client/defs.h | 131 ++++ src/client/entities.qc | 29 + src/client/game_event.qc | 124 ++++ src/client/hud.qc | 438 +++++++++++++ src/client/hud_weaponselect.qc | 228 +++++++ src/client/init.qc | 48 ++ src/client/input.qc | 29 + src/client/obituary.h | 48 ++ src/client/obituary.qc | 221 +++++++ src/client/particles.h | 17 + src/client/player.qc | 44 ++ src/client/predict.qc | 25 + src/client/progs.src | 38 ++ src/client/scoreboard.qc | 181 ++++++ src/client/view.qc | 51 ++ src/progs.src | 2 + src/server/Makefile | 4 + src/server/ammo.qc | 364 +++++++++++ src/server/client.qc | 77 +++ src/server/damage.qc | 166 +++++ src/server/defs.h | 18 + src/server/flashlight.qc | 42 ++ src/server/gamerules.h | 47 ++ src/server/gamerules.qc | 143 +++++ src/server/gamerules_multiplayer.qc | 166 +++++ src/server/gamerules_singleplayer.qc | 103 +++ src/server/input.qc | 108 ++++ src/server/item_battery.qc | 91 +++ src/server/item_healthkit.qc | 80 +++ src/server/item_longjump.qc | 108 ++++ src/server/item_suit.qc | 113 ++++ src/server/item_weaponbox.qc | 112 ++++ src/server/items.h | 30 + src/server/items.qc | 88 +++ src/server/monster_alien_controller.qc | 128 ++++ src/server/monster_alien_grunt.qc | 153 +++++ src/server/monster_alien_slave.qc | 254 ++++++++ src/server/monster_apache.qc | 48 ++ src/server/monster_babycrab.qc | 34 + src/server/monster_barnacle.qc | 83 +++ src/server/monster_barney.qc | 209 ++++++ src/server/monster_barney_dead.qc | 89 +++ src/server/monster_bigmomma.qc | 132 ++++ src/server/monster_bloater.qc | 37 ++ src/server/monster_bullchicken.qc | 155 +++++ src/server/monster_cockroach.qc | 54 ++ src/server/monster_flyer_flock.qc | 37 ++ src/server/monster_gargantua.qc | 138 ++++ src/server/monster_gman.qc | 87 +++ src/server/monster_headcrab.qc | 181 ++++++ src/server/monster_hevsuit_dead.qc | 97 +++ src/server/monster_hgrunt_dead.qc | 96 +++ src/server/monster_houndeye.qc | 202 ++++++ src/server/monster_human_assassin.qc | 94 +++ src/server/monster_human_grunt.qc | 319 +++++++++ src/server/monster_ichthyosaur.qc | 137 ++++ src/server/monster_leech.qc | 84 +++ src/server/monster_miniturret.qc | 47 ++ src/server/monster_nihilanth.qc | 134 ++++ src/server/monster_osprey.qc | 45 ++ src/server/monster_rat.qc | 37 ++ src/server/monster_scientist.qc | 236 +++++++ src/server/monster_scientist_dead.qc | 131 ++++ src/server/monster_sentry.qc | 78 +++ src/server/monster_sitting_scientist.qc | 142 ++++ src/server/monster_tentacle.qc | 132 ++++ src/server/monster_turret.qc | 47 ++ src/server/monster_zombie.qc | 222 +++++++ src/server/player.qc | 96 +++ src/server/progs.src | 89 +++ src/server/rules.qc | 20 + src/server/server.qc | 40 ++ src/server/spawn.qc | 41 ++ src/server/spectator.qc | 28 + src/server/world_items.qc | 43 ++ src/server/xen_hair.qc | 37 ++ src/server/xen_plantlight.qc | 37 ++ src/server/xen_spore_large.qc | 37 ++ src/server/xen_spore_medium.qc | 37 ++ src/server/xen_spore_small.qc | 37 ++ src/shared/animations.h | 95 +++ src/shared/animations.qc | 178 +++++ src/shared/entities.h | 20 + src/shared/flags.h | 40 ++ src/shared/fx_blood.qc | 105 +++ src/shared/fx_breakmodel.qc | 164 +++++ src/shared/fx_explosion.qc | 62 ++ src/shared/fx_gibhuman.qc | 88 +++ src/shared/fx_impact.qc | 208 ++++++ src/shared/fx_spark.qc | 51 ++ src/shared/include.src | 36 ++ src/shared/items.h | 51 ++ src/shared/player.qc | 642 +++++++++++++++++++ src/shared/pmove.qc | 74 +++ src/shared/pmove_water.qc | 78 +++ src/shared/w_crossbow.qc | 396 ++++++++++++ src/shared/w_crowbar.qc | 238 +++++++ src/shared/w_egon.qc | 332 ++++++++++ src/shared/w_gauss.qc | 506 +++++++++++++++ src/shared/w_glock.qc | 384 +++++++++++ src/shared/w_handgrenade.qc | 274 ++++++++ src/shared/w_hornetgun.qc | 323 ++++++++++ src/shared/w_mp5.qc | 405 ++++++++++++ src/shared/w_python.qc | 368 +++++++++++ src/shared/w_rpg.qc | 359 +++++++++++ src/shared/w_satchel.qc | 334 ++++++++++ src/shared/w_shotgun.qc | 345 ++++++++++ src/shared/w_snark.qc | 324 ++++++++++ src/shared/w_tripmine.qc | 400 ++++++++++++ src/shared/weapon_common.h | 60 ++ src/shared/weapon_common.qc | 321 ++++++++++ src/shared/weapons.h | 48 ++ src/shared/weapons.qc | 34 + zpak001.pk3dir/default.cfg | 45 ++ zpak001.pk3dir/particles/fx_explosion.cfg | 69 ++ zpak001.pk3dir/particles/fx_impact.cfg | 72 +++ zpak001.pk3dir/particles/fx_spark.cfg | 19 + zpak001.pk3dir/particles/weapon_egon.cfg | 43 ++ zpak001.pk3dir/particles/weapon_hornet.cfg | 14 + zpak001.pk3dir/particles/weapon_rpg.cfg | 14 + zpak001.pk3dir/particles/weapon_tripmine.cfg | 14 + zpak001.pk3dir/scripts/map_blacklist | 106 +++ zpak001.pk3dir/skill_valve.cfg | 255 ++++++++ zpak001.pk3dir/sound/fx_valve.sndshd | 7 + zpak001.pk3dir/sound/items_valve.sndshd | 29 + zpak001.pk3dir/sound/monsters_valve.sndshd | 630 ++++++++++++++++++ zpak001.pk3dir/sound/player_valve.sndshd | 12 + zpak001.pk3dir/sound/weapons_valve.sndshd | 166 +++++ 137 files changed, 17088 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/defs.h create mode 100644 src/client/entities.qc create mode 100644 src/client/game_event.qc 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/input.qc create mode 100644 src/client/obituary.h create mode 100644 src/client/obituary.qc create mode 100644 src/client/particles.h create mode 100644 src/client/player.qc create mode 100644 src/client/predict.qc create mode 100755 src/client/progs.src create mode 100644 src/client/scoreboard.qc create mode 100644 src/client/view.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/client.qc create mode 100644 src/server/damage.qc create mode 100644 src/server/defs.h create mode 100644 src/server/flashlight.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/input.qc create mode 100644 src/server/item_battery.qc create mode 100644 src/server/item_healthkit.qc create mode 100644 src/server/item_longjump.qc create mode 100644 src/server/item_suit.qc create mode 100644 src/server/item_weaponbox.qc create mode 100644 src/server/items.h create mode 100644 src/server/items.qc create mode 100644 src/server/monster_alien_controller.qc create mode 100644 src/server/monster_alien_grunt.qc create mode 100644 src/server/monster_alien_slave.qc create mode 100644 src/server/monster_apache.qc create mode 100644 src/server/monster_babycrab.qc create mode 100644 src/server/monster_barnacle.qc create mode 100644 src/server/monster_barney.qc create mode 100644 src/server/monster_barney_dead.qc create mode 100644 src/server/monster_bigmomma.qc create mode 100644 src/server/monster_bloater.qc create mode 100644 src/server/monster_bullchicken.qc create mode 100644 src/server/monster_cockroach.qc create mode 100644 src/server/monster_flyer_flock.qc create mode 100644 src/server/monster_gargantua.qc create mode 100644 src/server/monster_gman.qc create mode 100644 src/server/monster_headcrab.qc create mode 100644 src/server/monster_hevsuit_dead.qc create mode 100644 src/server/monster_hgrunt_dead.qc create mode 100644 src/server/monster_houndeye.qc create mode 100644 src/server/monster_human_assassin.qc create mode 100644 src/server/monster_human_grunt.qc create mode 100644 src/server/monster_ichthyosaur.qc create mode 100644 src/server/monster_leech.qc create mode 100644 src/server/monster_miniturret.qc create mode 100644 src/server/monster_nihilanth.qc create mode 100644 src/server/monster_osprey.qc create mode 100644 src/server/monster_rat.qc create mode 100644 src/server/monster_scientist.qc create mode 100644 src/server/monster_scientist_dead.qc create mode 100644 src/server/monster_sentry.qc create mode 100644 src/server/monster_sitting_scientist.qc create mode 100644 src/server/monster_tentacle.qc create mode 100644 src/server/monster_turret.qc create mode 100644 src/server/monster_zombie.qc create mode 100644 src/server/player.qc create mode 100755 src/server/progs.src create mode 100644 src/server/rules.qc create mode 100644 src/server/server.qc create mode 100644 src/server/spawn.qc create mode 100644 src/server/spectator.qc create mode 100644 src/server/world_items.qc create mode 100644 src/server/xen_hair.qc create mode 100644 src/server/xen_plantlight.qc create mode 100644 src/server/xen_spore_large.qc create mode 100644 src/server/xen_spore_medium.qc create mode 100644 src/server/xen_spore_small.qc create mode 100644 src/shared/animations.h create mode 100755 src/shared/animations.qc create mode 100644 src/shared/entities.h create mode 100644 src/shared/flags.h create mode 100644 src/shared/fx_blood.qc create mode 100644 src/shared/fx_breakmodel.qc create mode 100755 src/shared/fx_explosion.qc create mode 100644 src/shared/fx_gibhuman.qc create mode 100644 src/shared/fx_impact.qc create mode 100644 src/shared/fx_spark.qc create mode 100644 src/shared/include.src create mode 100644 src/shared/items.h create mode 100644 src/shared/player.qc create mode 100644 src/shared/pmove.qc create mode 100644 src/shared/pmove_water.qc create mode 100644 src/shared/w_crossbow.qc create mode 100644 src/shared/w_crowbar.qc create mode 100644 src/shared/w_egon.qc create mode 100644 src/shared/w_gauss.qc create mode 100644 src/shared/w_glock.qc create mode 100644 src/shared/w_handgrenade.qc create mode 100644 src/shared/w_hornetgun.qc create mode 100644 src/shared/w_mp5.qc create mode 100644 src/shared/w_python.qc create mode 100644 src/shared/w_rpg.qc create mode 100644 src/shared/w_satchel.qc create mode 100644 src/shared/w_shotgun.qc create mode 100644 src/shared/w_snark.qc create mode 100644 src/shared/w_tripmine.qc create mode 100644 src/shared/weapon_common.h create mode 100644 src/shared/weapon_common.qc create mode 100644 src/shared/weapons.h create mode 100644 src/shared/weapons.qc create mode 100755 zpak001.pk3dir/default.cfg create mode 100644 zpak001.pk3dir/particles/fx_explosion.cfg create mode 100644 zpak001.pk3dir/particles/fx_impact.cfg create mode 100644 zpak001.pk3dir/particles/fx_spark.cfg create mode 100644 zpak001.pk3dir/particles/weapon_egon.cfg create mode 100644 zpak001.pk3dir/particles/weapon_hornet.cfg create mode 100644 zpak001.pk3dir/particles/weapon_rpg.cfg create mode 100644 zpak001.pk3dir/particles/weapon_tripmine.cfg create mode 100644 zpak001.pk3dir/scripts/map_blacklist create mode 100644 zpak001.pk3dir/skill_valve.cfg create mode 100644 zpak001.pk3dir/sound/fx_valve.sndshd create mode 100644 zpak001.pk3dir/sound/items_valve.sndshd create mode 100644 zpak001.pk3dir/sound/monsters_valve.sndshd create mode 100644 zpak001.pk3dir/sound/player_valve.sndshd create mode 100644 zpak001.pk3dir/sound/weapons_valve.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..9864ee1 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# FreeHL +Clean-room reimplementation of Half-Life: Deathmatch and Half-Life (Experimental). + +Similar to FreeCS, this aims to recreate the feeling of the original game. +It's designed to work with the content from the CD version of the game. + +Netplay improvements, such as prediction of both player physics and weapon-logic +are present. + +This is 100% original code, feel free to audit however you wish. +No proprietary SDKs have been looked at or taken apart, unlike similar projects. + +![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 valve + +then either run Nuclide's ./build_game.sh shell script, or issue 'make' inside +./valve/src! + +Obviously make sure that Nuclide has fteqw and fteqcc set-up for building. + +## Community +Join us on #halflife via irc.frag-net.com 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..898f71df95ffff872c8ae8388488cb3e73e714d5 GIT binary patch literal 91410 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

~vsSn7hWa^W{~L~z1Kg%?`di)hFGA1y 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 z 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

xQt1d+T^ft2PSQLdb9Z#! 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%0DUjp}|C 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 QMgP1Zjn?Uh;qUl=07lFMRR910 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..7109de1 --- /dev/null +++ b/src/client/cmds.qc @@ -0,0 +1,25 @@ +/* + * 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)) { + default: + return FALSE; + } + return TRUE; +} diff --git a/src/client/defs.h b/src/client/defs.h new file mode 100644 index 0000000..60dd330 --- /dev/null +++ b/src/client/defs.h @@ -0,0 +1,131 @@ +/* + * 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. + */ + +#include "obituary.h" +#include "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; + +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; + + /* shake */ + float m_flShakeFreq; + float m_flShakeDuration; + float m_flShakeTime; + float m_flShakeAmp; + + entity m_pWeaponFX; +} g_seats[4], *pSeat; + +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/entities.qc b/src/client/entities.qc new file mode 100644 index 0000000..d0ccf21 --- /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_TRIPMINE: + w_tripmine_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..233d752 --- /dev/null +++ b/src/client/game_event.qc @@ -0,0 +1,124 @@ +/* + * 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_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); + } + + HUD_WeaponPickupNotify(w); + break; + } +} diff --git a/src/client/hud.qc b/src/client/hud.qc new file mode 100644 index 0000000..06b59e5 --- /dev/null +++ b/src/client/hud.qc @@ -0,0 +1,438 @@ +/* + * 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 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 +}; + +/* 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); +} + +/* 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, 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 != 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,-4], + [32,32], + 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,-4], + [32,32], + 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; + } + + drawsubpic( + pos + [-80,-9], + [40,40], + 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) { + drawsubpic( + pos + [-80,-9], + [40, 40 * (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,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) +{ + 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(); + + if (!(pl.g_items & ITEM_SUIT)) { + return; + } + + HUD_DrawHealth(); + HUD_DrawArmor(); + HUD_DrawFlashlight(); + HUD_DrawNotify(); + Damage_Draw(); +} + +/* specatator main entry */ +void +HUD_DrawSpectator(void) +{ + // FIXME + Textmenu_Draw(); +} diff --git a/src/client/hud_weaponselect.qc b/src/client/hud_weaponselect.qc new file mode 100644 index 0000000..9b5b81f --- /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 / 128], + [188 / 256, 72 / 128], + [208 / 256, 72 / 128], + [168 / 256, 92 / 128], + [188 / 256, 92 / 128], + [208 / 256, 92 / 128] +}; + +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, float fValue) +{ + drawsubpic(vecPos, [20,20], g_hud7_spr, g_vecHUDNums[fValue], [20/256, 20/128], 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..4ad56cd --- /dev/null +++ b/src/client/init.qc @@ -0,0 +1,48 @@ +/* + * 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) +{ + Obituary_Init(); +} + +void +ClientGame_InitDone(void) +{ +} + +void +ClientGame_RendererRestart(string rstr) +{ + Obituary_Precache(); + + FX_Blood_Init(); + FX_BreakModel_Init(); + FX_Explosion_Init(); + FX_GibHuman_Init(); + FX_Spark_Init(); + FX_Impact_Init(); + + BEAM_TRIPMINE = particleeffectnum("weapon_tripmine.beam"); +} diff --git a/src/client/input.qc b/src/client/input.qc new file mode 100644 index 0000000..63e1d2d --- /dev/null +++ b/src/client/input.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. + */ + +void +Game_Input(void) +{ + 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(); + } +} diff --git a/src/client/obituary.h b/src/client/obituary.h new file mode 100644 index 0000000..e6b80c1 --- /dev/null +++ b/src/client/obituary.h @@ -0,0 +1,48 @@ +/* + * 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 OBITUARY_LINES 4 +#define OBITUARY_TIME 5 + +/* imagery */ +typedef struct { + string name; /* name of the weapon/type, e.g. d_crowbar */ + string sprite; /* name of the spritesheet it's from */ + float size[2]; /* on-screen size in pixels */ + float src_pos[2]; /* normalized position in the sprite sheet */ + float src_size[2]; /* normalized size in the sprite sheet */ + string src_sprite; /* precaching reasons */ +} obituaryimg_t; + +obituaryimg_t *g_obtypes; +int g_obtype_count; + +/* actual obituary storage */ +typedef struct +{ + string attacker; + string victim; + int icon; +} obituary_t; + +obituary_t g_obituary[OBITUARY_LINES]; +int g_obituary_count; +float g_obituary_time; + +void Obituary_Init(void); +void Obituary_Precache(void); +void Obituary_Draw(void); +void Obituary_Parse(void); diff --git a/src/client/obituary.qc b/src/client/obituary.qc new file mode 100644 index 0000000..ea61f79 --- /dev/null +++ b/src/client/obituary.qc @@ -0,0 +1,221 @@ +/* + * 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 +Obituary_Init(void) +{ + int c; + int i; + filestream fh; + string line; + vector tmp; + + if (g_obtype_count > 0) { + return; + } + + g_obtype_count = 0; + i = 0; + + fh = fopen("sprites/hud.txt", FILE_READ); + if (fh < 0) { + return; + } + + /* count valid entries */ + while ((line = fgets(fh))) { + if (substring(line, 0, 2) == "d_") { + c = tokenize(line); + if (c == 7 && argv(1) == "640") { + g_obtype_count++; + } + } + } + + g_obtypes = memalloc(sizeof(obituaryimg_t) * g_obtype_count); + + fseek(fh, 0); + + /* read them in */ + while ((line = fgets(fh))) { + if (substring(line, 0, 2) == "d_") { + c = tokenize(line); + + /* we only care about the high-res (640) variants. the 320 + * HUD is useless to us. Just use the builtin scaler */ + if (c == 7 && argv(1) == "640") { + g_obtypes[i].name = substring(argv(0), 2, -1); + g_obtypes[i].src_sprite = sprintf("sprites/%s.spr", argv(2)); + precache_model(g_obtypes[i].src_sprite); + g_obtypes[i].sprite = spriteframe(sprintf("sprites/%s.spr", argv(2)), 0, 0.0f); + g_obtypes[i].size[0] = stof(argv(5)); + g_obtypes[i].size[1] = stof(argv(6)); + tmp = drawgetimagesize(g_obtypes[i].sprite); + g_obtypes[i].src_pos[0] = stof(argv(3)) / tmp[0]; + g_obtypes[i].src_pos[1] = stof(argv(4)) / tmp[1]; + g_obtypes[i].src_size[0] = g_obtypes[i].size[0] / tmp[0]; + g_obtypes[i].src_size[1] = g_obtypes[i].size[1] / tmp[1]; + i++; + } + } + } + + fclose(fh); +} + +void +Obituary_Precache(void) +{ + for (int i = 0; i < g_obtype_count; i++) + precache_model(g_obtypes[i].src_sprite); +} + +void +Obituary_KillIcon(int id, float w) +{ + if (w > 0) + for (int i = 0; i < g_obtype_count; i++) { + if (g_weapons[w].name == g_obtypes[i].name) { + g_obituary[id].icon = i; + return; + } + } + + /* look for skull instead */ + for (int i = 0; i < g_obtype_count; i++) { + if (g_obtypes[i].name == "skull") { + g_obituary[id].icon = i; + return; + } + } +} + +void +Obituary_Add(string attacker, string victim, float weapon, float flags) +{ + int i; + int x, y; + x = OBITUARY_LINES; + + /* we're not full yet, so fill up the buffer */ + if (g_obituary_count < x) { + y = g_obituary_count; + g_obituary[y].attacker = attacker; + g_obituary[y].victim = victim; + Obituary_KillIcon(y, weapon); + g_obituary_count++; + } else { + for (i = 0; i < (x-1); i++) { + g_obituary[i].attacker = g_obituary[i+1].attacker; + g_obituary[i].victim = g_obituary[i+1].victim; + g_obituary[i].icon = g_obituary[i+1].icon; + } + /* after rearranging, add the newest to the bottom. */ + g_obituary[x-1].attacker = attacker; + g_obituary[x-1].victim = victim; + Obituary_KillIcon(x-1, weapon); + } + + g_obituary_time = OBITUARY_TIME; + + if (g_weapons[weapon].deathmsg) { + string conprint = g_weapons[weapon].deathmsg(); + + if (conprint != "") { + print(sprintf(conprint, attacker, victim)); + print("\n"); + } + } +} + +void +Obituary_Draw(void) +{ + int i; + vector pos; + vector item; + drawfont = FONT_CON; + pos = g_hudmins + [g_hudres[0] - 18, 56]; + + if (g_obituary_time <= 0 && g_obituary_count > 0) { + for (i = 0; i < (OBITUARY_LINES-1); i++) { + g_obituary[i].attacker = g_obituary[i+1].attacker; + g_obituary[i].victim = g_obituary[i+1].victim; + g_obituary[i].icon = g_obituary[i+1].icon; + } + g_obituary[OBITUARY_LINES-1].attacker = ""; + + g_obituary_time = OBITUARY_TIME; + g_obituary_count--; + } + + if (g_obituary_count <= 0) { + return; + } + + item = pos; + for (i = 0; i < OBITUARY_LINES; i++) { + string a, v; + + if (!g_obituary[i].attacker) { + break; + } + + item[0] = pos[0]; + + v = g_obituary[i].victim; + drawstring_r(item + [0,2], v, [12,12], [1,1,1], 1.0f, 0); + item[0] -= stringwidth(v, TRUE, [12,12]) + 4; + item[0] -= g_obtypes[g_obituary[i].icon].size[0]; + + drawsubpic( + item, + [g_obtypes[g_obituary[i].icon].size[0], g_obtypes[g_obituary[i].icon].size[1]], + g_obtypes[g_obituary[i].icon].sprite, + [g_obtypes[g_obituary[i].icon].src_pos[0],g_obtypes[g_obituary[i].icon].src_pos[1]], + [g_obtypes[g_obituary[i].icon].src_size[0],g_obtypes[g_obituary[i].icon].src_size[1]], + g_hud_color, + 1.0f, + DRAWFLAG_ADDITIVE + ); + + a = g_obituary[i].attacker; + drawstring_r(item + [-4,2], a, [12,12], [1,1,1], 1.0f, 0); + item[1] += 18; + } + + g_obituary_time = max(0, g_obituary_time - clframetime); +} + +void +Obituary_Parse(void) +{ + string attacker; + string victim; + float weapon; + float flags; + + attacker = readstring(); + victim = readstring(); + weapon = readbyte(); + flags = readbyte(); + + if (!attacker) { + return; + } + + Obituary_Add(attacker, victim, weapon, flags); +} diff --git a/src/client/particles.h b/src/client/particles.h new file mode 100644 index 0000000..37140d1 --- /dev/null +++ b/src/client/particles.h @@ -0,0 +1,17 @@ +/* + * 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. + */ + +var float BEAM_TRIPMINE; diff --git a/src/client/player.qc b/src/client/player.qc new file mode 100644 index 0000000..62453d1 --- /dev/null +++ b/src/client/player.qc @@ -0,0 +1,44 @@ +/* + * 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); + } + } +} diff --git a/src/client/predict.qc b/src/client/predict.qc new file mode 100644 index 0000000..5aea138 --- /dev/null +++ b/src/client/predict.qc @@ -0,0 +1,25 @@ +/* + * 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 +GamePredict_PreFrame(player pl) +{ +} + +void +GamePredict_PostFrame(player pl) +{ +} diff --git a/src/client/progs.src b/src/client/progs.src new file mode 100755 index 0000000..bd015f9 --- /dev/null +++ b/src/client/progs.src @@ -0,0 +1,38 @@ +#pragma target fte +#pragma progs_dat "../../csprogs.dat" + +#define CSQC +#define CLIENT +#define VALVE +#define CLASSIC_VGUI +#define GS_RENDERFX + +#includelist +../../../src/shared/fteextensions.qc +../../../src/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 +init.qc +player.qc +entities.qc +cmds.qc +game_event.qc +view.qc +obituary.qc +hud.qc +hud_weaponselect.qc +scoreboard.qc +input.qc +../../../base/src/client/modelevent.qc + +../../../src/client/include.src +../../../src/shared/include.src +#endlist diff --git a/src/client/scoreboard.qc b/src/client/scoreboard.qc new file mode 100644 index 0000000..2e9c14a --- /dev/null +++ b/src/client/scoreboard.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. + */ + +#define SCORE_HEADER_C [255/255,156/255,0] +#define SCORE_LINE_C [255/255,200/255,0] + +var int autocvar_cl_centerscores = FALSE; +var int g_scores_teamplay = 0; + +void +Scores_Init(void) +{ + g_scores_teamplay = (int)serverkeyfloat("teamplay"); +} + +void +Scores_DrawTeam(player pl, vector pos) +{ + drawfill(pos, [290, 1], SCORE_LINE_C, 1.0f, DRAWFLAG_ADDITIVE); + + drawfont = FONT_20; + drawstring(pos + [0,-18], "Teams", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [124,-18], "kills / deaths", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [240,-18], "latency", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + + pos[1] += 12; + + for (int t = 1; t <= serverkeyfloat("teams"); t++) { + float l; + string temp; + drawstring(pos, serverkey(sprintf("team_%i", t)), [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + temp = serverkey(sprintf("teamscore_%i", t)); + l = stringwidth(temp, FALSE, [20,20]); + drawstring(pos + [150-l, 0], temp, [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [158, 0], "wins", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + pos[1] += 16; + + for (int i = -1; i > -32; i--) { + if (getplayerkeyfloat(i, "*team") != t) { + continue; + } + + temp = getplayerkeyvalue(i, "name"); + + /* Out of players */ + if (!temp) { + break; + } else if (temp == getplayerkeyvalue(pl.entnum-1, "name")) { + drawfill(pos, [290, 13], [0,0,1], 0.5f, DRAWFLAG_ADDITIVE); + } + + drawstring(pos + [24,0], getplayerkeyvalue(i, "name"), [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [154,0], "/", [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Get the kills and align them left to right */ + temp = getplayerkeyvalue(i, "frags"); + l = stringwidth(temp, FALSE, [20,20]); + drawstring(pos + [150 - l,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Deaths are right to left aligned */ + temp = getplayerkeyvalue(i, "*deaths"); + drawstring(pos + [165,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Get the latency and align it left to right */ + temp = getplayerkeyvalue(i, "ping"); + l = stringwidth(temp, FALSE, [20,20]); + + if (getplayerkeyfloat(i, "*dead") == 1) { + drawsubpic( + pos - [8,0], + [32,16], + g_hud1_spr, + [224/256, 240/256], + [32/256, 16/256], + [1,0,0], + 1.0f, + DRAWFLAG_ADDITIVE + ); + } + + drawstring(pos + [290 - l,0], temp, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + pos[1] += 20; + } + pos[1] += 12; + } + + drawfont = FONT_CON; +} + +void +Scores_DrawNormal(player pl, vector pos) +{ + drawfill(pos, [290, 1], SCORE_LINE_C, 1.0f, DRAWFLAG_ADDITIVE); + + drawfont = FONT_20; + drawstring(pos + [0,-18], "Player", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [124,-18], "kills / deaths", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [240,-18], "latency", [20,20], SCORE_HEADER_C, 1.0f, DRAWFLAG_ADDITIVE); + + pos[1] += 12; + for (int i = -1; i > -32; i--) { + float l; + string ping; + string kills; + string deaths; + string name; + + name = getplayerkeyvalue(i, "name"); + + /* Out of players */ + if (!name) { + break; + } else if (name == getplayerkeyvalue(pl.entnum-1, "name")) { + drawfill(pos, [290, 13], [0,0,1], 0.5f, DRAWFLAG_ADDITIVE); + } + + drawstring(pos, getplayerkeyvalue(i, "name"), [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + drawstring(pos + [154,0], "/", [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Get the kills and align them left to right */ + kills = getplayerkeyvalue(i, "frags"); + l = stringwidth(kills, FALSE, [20,20]); + drawstring(pos + [150 - l,0], kills, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Deaths are right to left aligned */ + deaths = getplayerkeyvalue(i, "*deaths"); + drawstring(pos + [165,0], deaths, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + + /* Get the latency and align it left to right */ + ping = getplayerkeyvalue(i, "ping"); + l = stringwidth(ping, FALSE, [20,20]); + + drawstring(pos + [290 - l,0], ping, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE); + pos[1] += 20; + } + + drawfont = FONT_CON; +} + +void +Scores_Draw(void) +{ + vector pos; + player pl; + + pl = (player)pSeat->m_ePlayer; + + if (autocvar_cl_centerscores) { + int c = 10; + + /* calculate all valid entries */ + for (int i = -1; i > -32; i--) { + if (getplayerkeyvalue(i, "name")) { + break; + } + c += 10; + } + pos = video_mins + [(video_res[0] / 2) - 145, (video_res[1] / 2) - c]; + } else { + pos = video_mins + [(video_res[0] / 2) - 145, 30]; + } + + if (serverkeyfloat("teams") > 0) { + Scores_DrawTeam(pl, pos); + } else { + Scores_DrawNormal(pl, pos); + } +} diff --git a/src/client/view.qc b/src/client/view.qc new file mode 100644 index 0000000..5592181 --- /dev/null +++ b/src/client/view.qc @@ -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. + */ + +void +View_UpdateWeapon(entity vm, entity mflash) +{ + player pl = (player)pSeat->m_ePlayer; + + /* only bother upon change */ + if (pSeat->m_iLastWeapon == pl.activeweapon) { + return; + } + pSeat->m_iOldWeapon = pSeat->m_iLastWeapon; + pSeat->m_iLastWeapon = pl.activeweapon; + + if (!pl.activeweapon) { + return; + } + + /* hack, we changed the wep, move this into Game_Input/PMove */ + Weapons_Draw(); + + /* we forced a weapon call outside the prediction, + * thus we need to update all the net variables to + * make sure these updates are recognized. this is + * vile but it'll have to do for now */ + pl.net_w_attack_next = pl.w_attack_next; + pl.net_w_idle_next = pl.w_idle_next; + pl.net_viewzoom = pl.viewzoom; + pl.net_weapontime = pl.weapontime; + + /* figure out when the attachments start. in FTE attachments for + * HLMDL are treated as bones. they start at numbones + 1 */ + skel_delete(mflash.skeletonindex); + mflash.skeletonindex = skel_create(vm.modelindex); + pSeat->m_iVMBones = skel_get_numbones(mflash.skeletonindex) + 1; + pSeat->m_iVMEjectBone = pSeat->m_iVMBones + 1; +} 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..f47920c --- /dev/null +++ b/src/server/ammo.qc @@ -0,0 +1,364 @@ +/* + * 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_ammo:CBaseEntity +{ + void(void) item_ammo; + virtual void(void) Respawn; + virtual void(void) touch; +}; + +void item_ammo::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + + player pl = (player)other; + Sound_Play(other, CHAN_ITEM, "ammo.pickup"); + Weapons_RefreshAmmo(pl); + Logging_Pickup(other, this, __NULL__); + + if (real_owner || cvar("sv_playerslots") == 1) { + remove(self); + } else { + Hide(); + think = Respawn; + nextthink = time + 20.0f; + } +} + +void item_ammo::Respawn(void) +{ + SetSolid(SOLID_TRIGGER); + SetMovetype(MOVETYPE_TOSS); + SetSize([-16,-16,0],[16,16,16]); + SetOrigin(m_oldOrigin); + SetModel(m_oldModel); + + think = __NULL__; + nextthink = -1; + + if (real_owner) + Sound_Play(this, CHAN_ITEM, "ammo.respawn"); + + droptofloor(); +} + +void item_ammo::item_ammo(void) +{ + precache_model(model); + m_oldModel = model; + SetModel(m_oldModel); + CBaseEntity::CBaseEntity(); +} + +/*QUAKED ammo_357 (0 0 0.8) (-16 -16 0) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Ammo for the .357 Magnum Revolver. +A single ammo_357 will provide 6 bullets. + +*/ +class ammo_357:item_ammo +{ + void(void) ammo_357; + virtual void(void) touch; +}; + +void ammo_357::ammo_357(void) +{ + model = "models/w_357ammobox.mdl"; + item_ammo::item_ammo(); +} +void ammo_357::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + if (other.classname == "player") { + player pl = (player)other; + if (pl.ammo_357 < MAX_A_357) { + pl.ammo_357 = bound(0, pl.ammo_357 + 6, MAX_A_357); + item_ammo::touch(); + } + } +} + +/*QUAKED ammo_9mmAR (0 0 0.8) (-16 -16 0) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Ammo for the 9mm Handgun and the 9mm AR. +A single ammo_9mmAR will provide 50 bullets. + +*/ +class ammo_9mmAR:item_ammo +{ + void(void) ammo_9mmAR; + virtual void(void) touch; +}; + +void ammo_9mmAR::ammo_9mmAR(void) +{ + model = "models/w_9mmarclip.mdl"; + item_ammo::item_ammo(); +} +void ammo_9mmAR::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + if (other.classname == "player") { + player pl = (player)other; + if (pl.ammo_9mm < MAX_A_9MM) { + pl.ammo_9mm = bound(0, pl.ammo_9mm + 50, MAX_A_9MM); + item_ammo::touch(); + } + } +} +CLASSEXPORT(ammo_mp5clip, ammo_9mmAR) + +/*QUAKED ammo_9mmbox (0 0 0.8) (-16 -16 0) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Ammo for the 9mm Handgun and the 9mm AR. +A single ammo_9mmbox will provide 200 bullets. + +*/ +class ammo_9mmbox:item_ammo +{ + void(void) ammo_9mmbox; + virtual void(void) touch; +}; + +void ammo_9mmbox::ammo_9mmbox(void) +{ + model = "models/w_chainammo.mdl"; + item_ammo::item_ammo(); +} +void ammo_9mmbox::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + if (other.classname == "player") { + player pl = (player)other; + if (pl.ammo_9mm < MAX_A_9MM) { + pl.ammo_9mm = bound(0, pl.ammo_9mm + 200, MAX_A_9MM); + item_ammo::touch(); + } + } +} + +/*QUAKED ammo_9mmclip (0 0 0.8) (-16 -16 0) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Ammo for the 9mm Handgun and the 9mm AR. +A single ammo_9mmclip will provide 17 bullets. + +*/ +class ammo_9mmclip:item_ammo +{ + void(void) ammo_9mmclip; + virtual void(void) touch; +}; + +void ammo_9mmclip::ammo_9mmclip(void) +{ + model = "models/w_9mmclip.mdl"; + item_ammo::item_ammo(); +} +void ammo_9mmclip::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + if (other.classname == "player") { + player pl = (player)other; + if (pl.ammo_9mm < MAX_A_9MM) { + pl.ammo_9mm = bound(0, pl.ammo_9mm + 17, MAX_A_9MM); + item_ammo::touch(); + } + } +} + +/*QUAKED ammo_ARgrenades (0 0 0.8) (-16 -16 0) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Ammo for the 9mm AR's secondary fire. +A single ammo_ARgrenades will provide 2 AR grenades. + +*/ +class ammo_ARgrenades:item_ammo +{ + void(void) ammo_ARgrenades; + virtual void(void) touch; +}; + +void ammo_ARgrenades::ammo_ARgrenades(void) +{ + model = "models/w_argrenade.mdl"; + item_ammo::item_ammo(); +} +void ammo_ARgrenades::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + if (other.classname == "player") { + player pl = (player)other; + if (pl.ammo_m203_grenade < MAX_A_M203_GRENADE) { + pl.ammo_m203_grenade = bound(0, pl.ammo_m203_grenade + 2, MAX_A_M203_GRENADE); + item_ammo::touch(); + } + } +} +CLASSEXPORT(ammo_mp5grenades, ammo_ARgrenades) + +/*QUAKED ammo_buckshot (0 0 0.8) (-16 -16 0) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Ammo for the Shotgun. +A single ammo_buckshot will provide 12 shells. + +*/ +class ammo_buckshot:item_ammo +{ + void(void) ammo_buckshot; + virtual void(void) touch; +}; + +void ammo_buckshot::ammo_buckshot(void) +{ + model = "models/w_shotbox.mdl"; + item_ammo::item_ammo(); +} +void ammo_buckshot::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + if (other.classname == "player") { + player pl = (player)other; + if (pl.ammo_buckshot < MAX_A_BUCKSHOT) { + pl.ammo_buckshot = bound(0, pl.ammo_buckshot + 12, MAX_A_BUCKSHOT); + item_ammo::touch(); + } + } +} + +/*QUAKED ammo_crossbow (0 0 0.8) (-16 -16 0) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Ammo for the Crossbow. +A single ammo_crossbow will provide 5 bolts. + +*/ +class ammo_crossbow:item_ammo +{ + void(void) ammo_crossbow; + virtual void(void) touch; +}; + +void ammo_crossbow::ammo_crossbow(void) +{ + model = "models/w_crossbow_clip.mdl"; + item_ammo::item_ammo(); +} +void ammo_crossbow::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + if (other.classname == "player") { + player pl = (player)other; + if (pl.ammo_bolt < MAX_A_BOLT) { + pl.ammo_bolt = bound(0, pl.ammo_bolt + 5, MAX_A_BOLT); + item_ammo::touch(); + } + } +} + +/*QUAKED ammo_gaussclip (0 0 0.8) (-16 -16 0) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Ammo for the Tau Cannon and the Gluon Gun. +A single ammo_gaussclip will provide 20 cells. + +*/ +class ammo_gaussclip:item_ammo +{ + void(void) ammo_gaussclip; + virtual void(void) touch; +}; + +void ammo_gaussclip::ammo_gaussclip(void) +{ + model = "models/w_gaussammo.mdl"; + item_ammo::item_ammo(); +} +void ammo_gaussclip::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + + player pl = (player)other; + if (pl.ammo_uranium < MAX_A_URANIUM) { + pl.ammo_uranium = bound(0, pl.ammo_uranium + 20, MAX_A_URANIUM); + item_ammo::touch(); + } +} + +/*QUAKED ammo_rpgclip (0 0 0.8) (-16 -16 0) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Ammo for the RPG. +A single ammo_rpgclip will provide 1 rocket. + +*/ +class ammo_rpgclip:item_ammo +{ + void(void) ammo_rpgclip; + virtual void(void) touch; +}; + +void ammo_rpgclip::ammo_rpgclip(void) +{ + model = "models/w_rpgammo.mdl"; + item_ammo::item_ammo(); +} +void ammo_rpgclip::touch(void) +{ + if not (other.flags & FL_CLIENT) { + return; + } + + player pl = (player)other; + if (pl.ammo_rocket < MAX_A_ROCKET) { + pl.ammo_rocket = bound(0, pl.ammo_rocket + 1, MAX_A_ROCKET); + item_ammo::touch(); + } +} diff --git a/src/server/client.qc b/src/server/client.qc new file mode 100644 index 0000000..107c58e --- /dev/null +++ b/src/server/client.qc @@ -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. + */ + +/* called every input frame */ +void +Game_RunClientCommand(void) +{ + Footsteps_Update(); + Animation_PlayerUpdate(); + PMove_Run(); +} + +/* custom chat packet */ +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)); +} + +/* client cmd overrides happen here */ +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); +} diff --git a/src/server/damage.qc b/src/server/damage.qc new file mode 100644 index 0000000..73cd380 --- /dev/null +++ b/src/server/damage.qc @@ -0,0 +1,166 @@ +/* + * 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. + */ + +/* generic function that applies damage, pain and suffering */ +void +Damage_Apply(entity t, entity c, float dmg, int w, int type) +{ + base_player tp = (base_player)t; + + CGameRules rules = (CGameRules)g_grMode; + if (t.flags & FL_GODMODE) { + return; + } + + /* already dead, please avoid recursion */ + if (t.health <= 0) { + return; + } + + /* skip armor */ + if not (type & DMG_SKIP_ARMOR) + if (tp.armor && dmg > 0) { + float flArmor; + float flNewDamage; + + flNewDamage = dmg * 0.2; + flArmor = (dmg - flNewDamage) * 0.5; + + if (flArmor > tp.armor) { + flArmor = tp.armor; + flArmor *= (1/0.5); + flNewDamage = dmg - flArmor; + tp.armor = 0; + } else { + tp.armor -= flArmor; + } + dmg = flNewDamage; + } + + dmg = rint(dmg); + t.health -= dmg; + + /* the globals... */ + g_dmg_eAttacker = c; + g_dmg_eTarget = t; + g_dmg_iDamage = dmg; + g_dmg_iHitBody = trace_surface_id; + g_dmg_iFlags = type; + g_dmg_iWeapon = w; + + if (dmg > 0) { + t.dmg_take = dmg; + t.dmg_inflictor = c; + } else if (t.max_health && t.health > t.max_health) { + t.health = t.max_health; + } + + /* set this global in case we need it later */ + g_eAttacker = c; + + CBaseEntity s = (CBaseEntity)t; + + if (s.health <= 0) { + if (s.flags & FL_CLIENT) { + rules.PlayerDeath((player)s); + } else { + s.Death(); + } + } else { + if (s.flags & FL_CLIENT) { + rules.PlayerPain((player)s); + } else { + s.Pain(); + } + } +} + +/* physical check of whether or not we can trace important parts of an ent */ +float +Damage_CheckTrace(entity t, vector vecHitPos) +{ + /* We're lazy. Who cares */ + if (t.solid == SOLID_BSP) { + return TRUE; + } + + traceline(vecHitPos, t.origin, 1, self); + if (trace_fraction == 1) { + return TRUE; + } + traceline(vecHitPos, t.origin + [15,15,0], 1, self); + if (trace_fraction == 1) { + return TRUE; + } + traceline(vecHitPos, t.origin + [-15,-15,0], 1, self); + if (trace_fraction == 1) { + return TRUE; + } + traceline(vecHitPos, t.origin + [-15,15,0], 1, self); + if (trace_fraction == 1) { + return TRUE; + } + traceline(vecHitPos, t.origin + [15,-15,0], 1, self); + if (trace_fraction == 1) { + return TRUE; + } + + return FALSE; +} + +/* even more pain and suffering, mostly used for explosives */ +void +Damage_Radius(vector org, entity attacker, float dmg, float r, int check, int w) +{ + float new_dmg; + float dist; + float diff; + vector pos; + + for (entity e = world; (e = findfloat(e, ::takedamage, DAMAGE_YES));) { + pos[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0])); + pos[1] = e.absmin[1] + (0.5 * (e.absmax[1] - e.absmin[1])); + pos[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2])); + + /* don't bother if it's not anywhere near us */ + dist = vlen(org - pos); + if (dist > r) { + continue; + } + + /* can we physically hit this thing? */ + if (Damage_CheckTrace(e, org) == FALSE) { + if (check == TRUE) { + continue; + } + } + + /* calculate new damage values */ + diff = vlen(org - pos); + diff = (r - diff) / r; + new_dmg = rint(dmg * diff); + + if (diff > 0) { + Damage_Apply(e, attacker, new_dmg, w, DMG_EXPLODE); + + /* approximate, feel free to tweak */ + if (e.movetype == MOVETYPE_WALK) { + makevectors(vectoangles(e.origin - org)); + e.velocity += v_forward * (new_dmg * 5); + } + } + } +} diff --git a/src/server/defs.h b/src/server/defs.h new file mode 100644 index 0000000..88c3448 --- /dev/null +++ b/src/server/defs.h @@ -0,0 +1,18 @@ +/* + * 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 "items.h" diff --git a/src/server/flashlight.qc b/src/server/flashlight.qc new file mode 100644 index 0000000..fbdf827 --- /dev/null +++ b/src/server/flashlight.qc @@ -0,0 +1,42 @@ +/* + * 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 Flashlight_Toggle(void) +{ + if (cvar("sv_playerslots") != 1) { + if (cvar("mp_flashlight") != 1) { + return; + } + } + +#ifdef VALVE + player pl = (player)self; + if (!(pl.g_items & ITEM_SUIT)) { + return; + } +#endif + + if (self.health <= 0) { + return; + } + + if (self.gflags & GF_FLASHLIGHT) { + self.gflags &= ~GF_FLASHLIGHT; + } else { + self.gflags |= GF_FLASHLIGHT; + } + sound(self, CHAN_ITEM, "items/flashlight1.wav", 1, ATTN_IDLE); +} diff --git a/src/server/gamerules.h b/src/server/gamerules.h new file mode 100644 index 0000000..b25b994 --- /dev/null +++ b/src/server/gamerules.h @@ -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. + */ + +class HLGameRules: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) LevelDecodeParms; + virtual void(base_player) LevelChangeParms; + virtual void(void) LevelNewParms; +}; + +class HLSingleplayerRules:HLGameRules +{ + /* client */ + virtual void(base_player) PlayerSpawn; + virtual void(base_player) PlayerDeath; +}; + +class HLMultiplayerRules:HLGameRules +{ + int m_iIntermission; + int m_iIntermissionTime; + + virtual void(void) FrameStart; + + /* client */ + virtual void(base_player) PlayerSpawn; + virtual void(base_player) PlayerDeath; + virtual float(base_player, string) ConsoleCommand; +}; diff --git a/src/server/gamerules.qc b/src/server/gamerules.qc new file mode 100644 index 0000000..146d74c --- /dev/null +++ b/src/server/gamerules.qc @@ -0,0 +1,143 @@ +/* + * 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 +HLGameRules::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_9mm = parm12; + pl.ammo_357 = parm13; + pl.ammo_buckshot = parm14; + pl.ammo_m203_grenade = parm15; + pl.ammo_bolt = parm16; + pl.ammo_rocket = parm17; + pl.ammo_uranium = parm18; + pl.ammo_handgrenade = parm19; + pl.ammo_satchel = parm20; + pl.ammo_tripmine = parm21; + pl.ammo_snark = parm22; + pl.ammo_hornet = parm23; + + pl.glock_mag = parm24; + pl.mp5_mag = parm25; + pl.python_mag = parm26; + pl.shotgun_mag = parm27; + pl.crossbow_mag = parm28; + pl.rpg_mag = parm29; + pl.satchel_chg = parm30; + + if (pl.flags & FL_CROUCHING) { + setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX); + } else { + setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX); + } +} + +void +HLGameRules::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]; + parm64 = pl.flags; + parm10 = pl.g_items; + parm11 = pl.activeweapon; + parm12 = pl.ammo_9mm; + parm13 = pl.ammo_357; + parm14 = pl.ammo_buckshot; + parm15 = pl.ammo_m203_grenade; + parm16 = pl.ammo_bolt; + parm17 = pl.ammo_rocket; + parm18 = pl.ammo_uranium; + parm19 = pl.ammo_handgrenade; + parm20 = pl.ammo_satchel; + parm21 = pl.ammo_tripmine; + parm22 = pl.ammo_snark; + parm23 = pl.ammo_hornet; + parm24 = pl.glock_mag; + parm25 = pl.mp5_mag; + parm26 = pl.python_mag; + parm27 = pl.shotgun_mag; + parm28 = pl.crossbow_mag; + parm29 = pl.rpg_mag; + parm30 = pl.satchel_chg; +} + +void +HLGameRules::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 = 0; + parm64 = FL_CLIENT; +} + +/* we check what fields have changed over the course of the frame and network + * only the ones that have actually changed */ +void +HLGameRules::PlayerPostFrame(base_player pl) +{ +} + +void +HLGameRules::PlayerConnect(base_player pl) +{ + if (Plugin_PlayerConnect(pl) == FALSE) + bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname)); +} + +void +HLGameRules::PlayerDisconnect(base_player pl) +{ + if (Plugin_PlayerDisconnect(pl) == FALSE) + 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 = -1; +} + +void +HLGameRules::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..1ff921a --- /dev/null +++ b/src/server/gamerules_multiplayer.qc @@ -0,0 +1,166 @@ +/* + * 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 +HLMultiplayerRules::FrameStart(void) +{ + if (cvar("mp_timelimit")) + if (time >= (cvar("mp_timelimit") * 60)) { + IntermissionStart(); + } + + IntermissionCycle(); +} + +void +HLMultiplayerRules::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); + + Plugin_PlayerObituary(g_dmg_eAttacker, g_dmg_eTarget, g_dmg_iWeapon, g_dmg_iHitBody, g_dmg_iDamage); + + /* death-counter */ + pl.deaths++; + forceinfokey(pl, "*deaths", ftos(pl.deaths)); + + /* update score-counter */ + if (pl.flags & FL_CLIENT || pl.flags & FL_MONSTER) + if (g_dmg_eAttacker.flags & FL_CLIENT) { + if (pl == g_dmg_eAttacker) + g_dmg_eAttacker.frags--; + else + g_dmg_eAttacker.frags++; + } + + /* in DM we only care about the frags */ + if (cvar("mp_fraglimit")) + if (g_dmg_eAttacker.frags >= cvar("mp_fraglimit")) { + IntermissionStart(); + } + + weaponbox_spawn((player)pl); + + /* either gib, or make a corpse */ + if (pl.health < -50) { + FX_GibHuman(pl.origin); + } else { + /* Let's handle corpses on the clientside */ + 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_DIESIMPLE; + corpse.angles = pl.angles; + corpse.velocity = pl.velocity; + } + + /* now let's make the real client invisible */ + pl.SetModelindex(0); + pl.SetMovetype(MOVETYPE_NONE); + pl.SetSolid(SOLID_NOT); + pl.takedamage = DAMAGE_NO; + pl.gflags &= ~GF_FLASHLIGHT; + pl.armor = pl.activeweapon = pl.g_items = 0; + pl.health = 0; + + Sound_Play(pl, CHAN_AUTO, "player.die"); + + /* force respawn */ + pl.think = PutClientInServer; + pl.nextthink = time + 4.0f; +} + +void +HLMultiplayerRules::PlayerSpawn(base_player pp) +{ + player pl = (player)pp; + /* this is where the mods want to deviate */ + entity spot; + + 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"; + string mymodel = infokey(pl, "model"); + + if (mymodel) { + mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel); + if (whichpack(mymodel)) { + pl.model = mymodel; + } + } + 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.SendEntity = Player_SendEntity; + pl.SendFlags = UPDATE_ALL; + pl.customphysics = Empty; + pl.iBleeds = TRUE; + forceinfokey(pl, "*spec", "0"); + forceinfokey(pl, "*deaths", ftos(pl.deaths)); + + LevelNewParms(); + LevelDecodeParms(pl); + pl.g_items = ITEM_CROWBAR | ITEM_GLOCK | ITEM_SUIT; + pl.activeweapon = WEAPON_GLOCK; + pl.glock_mag = 18; + pl.ammo_9mm = 44; + + spot = Spawn_SelectRandom("info_player_deathmatch"); + setorigin(pl, spot.origin); + pl.angles = spot.angles; + Weapons_RefreshAmmo(pl); + + Client_FixAngle(pl, pl.angles); +} + +float +HLMultiplayerRules::ConsoleCommand(base_player pp, string cmd) +{ + tokenize(cmd); + + switch (argv(0)) { + case "bot_add": + Bot_AddQuick(); + break; + default: + return FALSE; + } + + return TRUE; +} diff --git a/src/server/gamerules_singleplayer.qc b/src/server/gamerules_singleplayer.qc new file mode 100644 index 0000000..7c967e6 --- /dev/null +++ b/src/server/gamerules_singleplayer.qc @@ -0,0 +1,103 @@ +/* + * 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 +HLSingleplayerRules::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 = pl.weapon = 0; + pl.health = 0; + Sound_Play(pl, CHAN_AUTO, "player.die"); + + if (cvar("coop") == 1) { + pl.think = PutClientInServer; + pl.nextthink = time + 4.0f; + } + + if (pl.health < -50) { + FX_GibHuman(pl.origin); + } + + /* Let's handle corpses on the clientside */ + 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_DIESIMPLE; + corpse.angles = pl.angles; + corpse.velocity = pl.velocity; +} + +void +HLSingleplayerRules::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"; + + + if (cvar("coop") == 1) { + string mymodel = infokey(pl, "model"); + if (mymodel) { + mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel); + if (whichpack(mymodel)) { + pl.model = mymodel; + } + } + } + + 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.SendEntity = Player_SendEntity; + pl.SendFlags = UPDATE_ALL; + pl.customphysics = Empty; + pl.iBleeds = TRUE; + forceinfokey(pl, "*spec", "0"); + forceinfokey(pl, "*deaths", ftos(pl.deaths)); + + /* this is where the mods want to deviate */ + 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/input.qc b/src/server/input.qc new file mode 100644 index 0000000..9f802f7 --- /dev/null +++ b/src/server/input.qc @@ -0,0 +1,108 @@ +/* + * 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. + */ + +/* +================= +Input_Handle + +Handles impulse and whatnot +================= +*/ +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; + pl.g_items |= ITEM_SUIT; + Weapons_AddItem(pl, WEAPON_CROWBAR, -1); + Weapons_AddItem(pl, WEAPON_GLOCK, -1); + Weapons_AddItem(pl, WEAPON_PYTHON, -1); + Weapons_AddItem(pl, WEAPON_MP5, -1); + Weapons_AddItem(pl, WEAPON_SHOTGUN, -1); + Weapons_AddItem(pl, WEAPON_CROSSBOW, -1); + Weapons_AddItem(pl, WEAPON_RPG, -1); + Weapons_AddItem(pl, WEAPON_GAUSS, -1); + Weapons_AddItem(pl, WEAPON_EGON, -1); + Weapons_AddItem(pl, WEAPON_HORNETGUN, -1); + Weapons_AddItem(pl, WEAPON_HANDGRENADE, -1); + Weapons_AddItem(pl, WEAPON_SATCHEL, -1); + Weapons_AddItem(pl, WEAPON_TRIPMINE, -1); + Weapons_AddItem(pl, WEAPON_SNARK, -1); +#ifdef GEARBOX + Weapons_AddItem(pl, WEAPON_PIPEWRENCH, -1); + Weapons_AddItem(pl, WEAPON_KNIFE, -1); + Weapons_AddItem(pl, WEAPON_GRAPPLE, -1); + Weapons_AddItem(pl, WEAPON_EAGLE, -1); + Weapons_AddItem(pl, WEAPON_PENGUIN, -1); + Weapons_AddItem(pl, WEAPON_M249, -1); + Weapons_AddItem(pl, WEAPON_DISPLACER, -1); + Weapons_AddItem(pl, WEAPON_SNIPERRIFLE, -1); + Weapons_AddItem(pl, WEAPON_SPORELAUNCHER, -1); + Weapons_AddItem(pl, WEAPON_SHOCKRIFLE, -1); +#endif + } + + if (self.impulse == 102) { + // Respawn all the entities + for (entity a = world; (a = findfloat(a, ::identity, 1));) { + CBaseEntity caw = (CBaseEntity)a; + caw.Respawn(); + caw.SendFlags |= + BASEFL_CHANGED_ORIGIN | + BASEFL_CHANGED_ANGLES | + BASEFL_CHANGED_MODELINDEX | + BASEFL_CHANGED_SIZE | + BASEFL_CHANGED_SOLID | + BASEFL_CHANGED_FRAME | + BASEFL_CHANGED_SKIN | + BASEFL_CHANGED_MOVETYPE | + BASEFL_CHANGED_EFFECTS; + } + bprint(PRINT_HIGH, "Respawning all map entities...\n"); + } + } + + self.impulse = 0; +} diff --git a/src/server/item_battery.qc b/src/server/item_battery.qc new file mode 100644 index 0000000..bb19d99 --- /dev/null +++ b/src/server/item_battery.qc @@ -0,0 +1,91 @@ +/* + * 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 item_battery (0 0 0.8) (-16 -16 0) (16 16 36) + +HALF-LIFE (1998) ENTITY + +HEV Suit energy battery. +It adds the following energy values to the HEV Suit by default: +Skill 1 (Easy): 15 +Skill 2 (Medium): 15 +Skill 3 (Hard): 10 + +The values can be tweaked in the skill.cfg file. + +*/ +class item_battery:CBaseEntity +{ + void(void) item_battery; + virtual void(void) Respawn; + virtual void(void) touch; +}; + +void item_battery::touch(void) +{ + if (other.classname != "player") { + return; + } + + base_player pl = (base_player)other; + + if (pl.armor >= 100) { + return; + } + /* Move this somewhere else? */ + pl.armor += Skill_GetValue("battery", 15); + if (pl.armor > 100) { + pl.armor = 100; + } + + Logging_Pickup(other, this, __NULL__); + Sound_Play(other, CHAN_ITEM, "item.battery"); + + if (real_owner || cvar("sv_playerslots") == 1) { + remove(self); + } else { + Hide(); + think = Respawn; + nextthink = time + 20.0f; + } +} + +void item_battery::Respawn(void) +{ + SetSolid(SOLID_TRIGGER); + SetMovetype(MOVETYPE_TOSS); + SetSize([-16,-16,0],[16,16,16]); + SetOrigin(m_oldOrigin); + SetModel(m_oldModel); +// botinfo = BOTINFO_ARMOR; + + think = __NULL__; + nextthink = -1; + + if (!real_owner) + Sound_Play(this, CHAN_ITEM, "item.respawn"); + + droptofloor(); +} + +void item_battery::item_battery(void) +{ + Sound_Precache("item.battery"); + Sound_Precache("item.respawn"); + model = "models/w_battery.mdl"; + CBaseEntity::CBaseEntity(); + item_healthkit::Respawn(); +} diff --git a/src/server/item_healthkit.qc b/src/server/item_healthkit.qc new file mode 100644 index 0000000..a345bc9 --- /dev/null +++ b/src/server/item_healthkit.qc @@ -0,0 +1,80 @@ +/* + * 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 item_healthkit (0 0 0.8) (-16 -16 0) (16 16 36) + +HALF-LIFE (1998) ENTITY + +Healthkit item. +Adds 20 of health to the player. + +*/ +class item_healthkit:CBaseEntity +{ + void(void) item_healthkit; + virtual void(void) Respawn; + virtual void(void) touch; +}; + +void item_healthkit::touch(void) +{ + if (other.classname != "player") { + return; + } + + if (other.health >= other.max_health) { + return; + } + + Damage_Apply(other, this, -20, 0, DMG_GENERIC); + Sound_Play(this, CHAN_ITEM, "item.healthkit"); + Logging_Pickup(other, this, __NULL__); + + if (real_owner || cvar("sv_playerslots") == 1) { + remove(self); + } else { + Hide(); + think = Respawn; + nextthink = time + 20.0f; + } +} + +void item_healthkit::Respawn(void) +{ + SetSolid(SOLID_TRIGGER); + SetMovetype(MOVETYPE_TOSS); + SetSize([-16,-16,0],[16,16,16]); + SetOrigin(m_oldOrigin); + SetModel(m_oldModel); + //botinfo = BOTINFO_HEALTH; + + think = __NULL__; + nextthink = -1; + + if (!real_owner) + Sound_Play(this, CHAN_ITEM, "item.respawn"); + + droptofloor(); +} + +void item_healthkit::item_healthkit(void) +{ + Sound_Precache("item.healthkit"); + Sound_Precache("item.respawn"); + model = "models/w_medkit.mdl"; + CBaseEntity::CBaseEntity(); + item_healthkit::Respawn(); +} diff --git a/src/server/item_longjump.qc b/src/server/item_longjump.qc new file mode 100644 index 0000000..38a729e --- /dev/null +++ b/src/server/item_longjump.qc @@ -0,0 +1,108 @@ +/* + * 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 item_longjump (0 0 0.8) (-16 -16 0) (16 16 36) + +HALF-LIFE (1998) ENTITY + +Longjump module. +Allows the player to jump longer distance by holding crouch +and pressing jump. + +*/ +class item_longjump:CBaseTrigger +{ + string m_strOnPlayerTouch; + + void(void) item_longjump; + + virtual void(void) touch; + virtual void(void) Respawn; + virtual void(string, string) SpawnKey; +}; + +void +item_longjump::touch(void) +{ + if (other.classname != "player") { + return; + } + + player pl = (player)other; + if (pl.g_items & ITEM_LONGJUMP) { + return; + } + + Logging_Pickup(other, this, __NULL__); + sound(other, CHAN_ITEM, "fvox/blip.wav", 1, ATTN_NORM); + sound(other, CHAN_VOICE, "fvox/powermove_on.wav", 1, ATTN_NORM); + pl.g_items |= ITEM_LONGJUMP; + + if (!target) { + UseOutput(other, m_strOnPlayerTouch); + } else { + UseTargets(other, TRIG_TOGGLE, m_flDelay); + } + + if (real_owner || cvar("sv_playerslots") == 1) { + remove(self); + } else { + Hide(); + think = Respawn; + nextthink = time + 30.0f; + } +} + +void +item_longjump::Respawn(void) +{ + SetSolid(SOLID_TRIGGER); + SetMovetype(MOVETYPE_TOSS); + SetSize([-16,-16,0],[16,16,16]); + SetOrigin(m_oldOrigin); + SetModel(m_oldModel); + + think = __NULL__; + nextthink = -1; + + if (!real_owner) + Sound_Play(this, CHAN_ITEM, "item.respawn"); +} + +void +item_longjump::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "OnPlayerTouch": + strValue = strreplace(",", ",_", strValue); + m_strOnPlayerTouch = strcat(m_strOnPlayerTouch, ",_", strValue); + break; + default: + CBaseTrigger::SpawnKey(strKey, strValue); + break; + } +} + +void +item_longjump::item_longjump(void) +{ + model = "models/w_longjump.mdl"; + precache_sound("items/suitchargeok1.wav"); + precache_sound("fvox/powermove_on.wav"); + precache_sound("fvox/blip.wav"); + CBaseTrigger::CBaseTrigger(); + Respawn(); +} diff --git a/src/server/item_suit.qc b/src/server/item_suit.qc new file mode 100644 index 0000000..5283317 --- /dev/null +++ b/src/server/item_suit.qc @@ -0,0 +1,113 @@ +/* + * 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 item_suit (0 0 0.8) (-16 -16 0) (16 16 36) SUIT_LONGINTRO + +HALF-LIFE (1998) ENTITY + +HEV Suit +Provides the player with armor, a flashlight and a Heads-Up-Display. + +When SUIT_LONGINTRO is set, the intro dialog will be longer. + +*/ + +class item_suit:CBaseTrigger +{ + string m_strOnPlayerTouch; + + void(void) item_suit; + + virtual void(void) touch; + virtual void(void) Respawn; + virtual void(string, string) SpawnKey; +}; + +void +item_suit::touch(void) +{ + if (other.classname != "player") { + return; + } + + player pl = (player)other; + if (pl.g_items & ITEM_SUIT) { + return; + } + + Logging_Pickup(other, this, __NULL__); + sound(other, CHAN_ITEM, "fvox/bell.wav", 1, ATTN_NORM); + sound(other, CHAN_VOICE, "fvox/hev_logon.wav", 1, ATTN_NORM); + pl.g_items |= ITEM_SUIT; + m_iValue = TRUE; + + if (!target) { + UseOutput(other, m_strOnPlayerTouch); + } else { + UseTargets(other, TRIG_TOGGLE, m_flDelay); + } + + if (real_owner || 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); + m_iValue = FALSE; + + think = __NULL__; + nextthink = -1; + + if (!real_owner) + Sound_Play(this, CHAN_ITEM, "item.respawn"); +} + +void +item_suit::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "OnPlayerTouch": + strValue = strreplace(",", ",_", strValue); + m_strOnPlayerTouch = strcat(m_strOnPlayerTouch, ",_", strValue); + break; + default: + CBaseTrigger::SpawnKey(strKey, strValue); + break; + } +} + +void +item_suit::item_suit(void) +{ + model = "models/w_suit.mdl"; + precache_sound("items/suitchargeok1.wav"); + precache_sound("fvox/hev_logon.wav"); + precache_sound("fvox/bell.wav"); + CBaseTrigger::CBaseTrigger(); + + m_strOnPlayerTouch = CreateOutput(m_strOnPlayerTouch); +} diff --git a/src/server/item_weaponbox.qc b/src/server/item_weaponbox.qc new file mode 100644 index 0000000..60bec04 --- /dev/null +++ b/src/server/item_weaponbox.qc @@ -0,0 +1,112 @@ +/* + * 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_weaponbox:CBaseEntity +{ + int ammo_9mm; + int ammo_357; + int ammo_buckshot; + int ammo_m203_grenade; + int ammo_bolt; + int ammo_rocket; + int ammo_uranium; + int ammo_handgrenade; + int ammo_satchel; + int ammo_tripmine; + int ammo_snark; + int ammo_hornet; + int weapon_items; + + void(void) item_weaponbox; + virtual void(void) touch; + virtual void(player) setup; +}; + +void item_weaponbox::touch(void) +{ + if (other.classname != "player") { + return; + } + + player pl = (player)other; + Logging_Pickup(other, this, __NULL__); + sound(pl, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM); + + pl.ammo_9mm += ammo_9mm; + pl.ammo_357 += ammo_357; + pl.ammo_buckshot += ammo_buckshot; + pl.ammo_m203_grenade += ammo_m203_grenade; + pl.ammo_bolt += ammo_bolt; + pl.ammo_rocket += ammo_rocket; + pl.ammo_uranium += ammo_uranium; + pl.ammo_handgrenade += ammo_handgrenade; + pl.ammo_satchel += ammo_satchel; + pl.ammo_tripmine += ammo_tripmine; + pl.ammo_snark += ammo_snark; + pl.ammo_hornet += ammo_hornet; + + /* cull */ + pl.ammo_9mm = min(pl.ammo_9mm, MAX_A_9MM); + pl.ammo_357 = min(pl.ammo_357, MAX_A_357); + pl.ammo_buckshot = min(pl.ammo_buckshot, MAX_A_BUCKSHOT); + pl.ammo_m203_grenade = min(pl.ammo_m203_grenade, MAX_A_M203_GRENADE); + pl.ammo_bolt = min(pl.ammo_bolt, MAX_A_BOLT); + pl.ammo_rocket = min(pl.ammo_rocket, MAX_A_ROCKET); + pl.ammo_uranium = min(pl.ammo_uranium, MAX_A_URANIUM); + pl.ammo_handgrenade = min(pl.ammo_handgrenade, MAX_A_HANDGRENADE); + pl.ammo_satchel = min(pl.ammo_satchel, MAX_A_SATCHEL); + pl.ammo_tripmine = min(pl.ammo_tripmine, MAX_A_TRIPMINE); + pl.ammo_snark = min(pl.ammo_snark, MAX_A_SNARK); + pl.ammo_hornet = min(pl.ammo_hornet, MAX_A_HORNET); + + pl.g_items |= weapon_items; + Weapons_RefreshAmmo(pl); + + remove(this); +} + +void item_weaponbox::setup(player pl) +{ + /* TODO: Should the magazine bits be transferred too? */ + ammo_9mm = pl.ammo_9mm; + ammo_357 = pl.ammo_357; + ammo_buckshot = pl.ammo_buckshot; + ammo_m203_grenade = pl.ammo_m203_grenade; + ammo_bolt = pl.ammo_bolt; + ammo_rocket = pl.ammo_rocket; + ammo_uranium = pl.ammo_uranium; + ammo_handgrenade = pl.ammo_handgrenade; + ammo_satchel = pl.ammo_satchel; + ammo_tripmine = pl.ammo_tripmine; + ammo_snark = pl.ammo_snark; + ammo_hornet = pl.ammo_hornet; + weapon_items = pl.g_items; +} + +void item_weaponbox::item_weaponbox(void) +{ + SetModel("models/w_weaponbox.mdl"); + SetSize([-16,-16,0], [16,16,16]); + SetSolid(SOLID_TRIGGER); + SetMovetype(MOVETYPE_TOSS); +} + +void weaponbox_spawn(player spawner) +{ + item_weaponbox weaponbox = spawn(item_weaponbox); + weaponbox.SetOrigin(spawner.origin); + weaponbox.setup(spawner); +} diff --git a/src/server/items.h b/src/server/items.h new file mode 100644 index 0000000..dee59bd --- /dev/null +++ b/src/server/items.h @@ -0,0 +1,30 @@ +/* + * 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. + */ + +/* PICKUP ITEMS */ +class item_pickup:CBaseTrigger +{ + int m_bFloating; + int m_iClip; + int m_iWasDropped; + int id; + void(void) item_pickup; + + virtual void(void) touch; + virtual void(int i) SetItem; + virtual void(void) Respawn; + virtual void(int) SetFloating; +}; diff --git a/src/server/items.qc b/src/server/items.qc new file mode 100644 index 0000000..b635066 --- /dev/null +++ b/src/server/items.qc @@ -0,0 +1,88 @@ +/* + * 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 item_pickup::touch(void) +{ + if (other.classname != "player") { + return; + } + + /* don't remove if AddItem fails */ + if (Weapons_AddItem((player)other, id, m_iClip) == FALSE) { + return; + } + + Logging_Pickup(other, this, __NULL__); + Sound_Play(other, CHAN_ITEM, "weapon.pickup"); + + UseTargets(other, TRIG_TOGGLE, m_flDelay); + + if (real_owner || m_iWasDropped == 1 || cvar("sv_playerslots") == 1) { + remove(self); + } else { + Hide(); + think = Respawn; + nextthink = time + 30.0f; + } +} + +void item_pickup::SetItem(int i) +{ + id = i; + m_oldModel = Weapons_GetWorldmodel(id); + SetModel(m_oldModel); +} + +void item_pickup::SetFloating(int i) +{ + m_bFloating = rint(bound(0, m_bFloating, 1)); +} + +void item_pickup::Respawn(void) +{ + SetSolid(SOLID_TRIGGER); + SetOrigin(m_oldOrigin); + + /* At some points, the item id might not yet be set */ + if (m_oldModel) { + SetModel(m_oldModel); + } + + SetSize([-16,-16,0], [16,16,16]); + + think = __NULL__; + nextthink = -1; + + if (!m_iWasDropped && cvar("sv_playerslots") > 1) { + if (!real_owner) + Sound_Play(this, CHAN_ITEM, "item.respawn"); + + m_iClip = -1; + } + + if (!m_bFloating) { + droptofloor(); + SetMovetype(MOVETYPE_TOSS); + } +} + +void item_pickup::item_pickup(void) +{ + Sound_Precache("item.respawn"); + Sound_Precache("weapon.pickup"); + CBaseTrigger::CBaseTrigger(); + Respawn(); +} diff --git a/src/server/monster_alien_controller.qc b/src/server/monster_alien_controller.qc new file mode 100644 index 0000000..5ef43e7 --- /dev/null +++ b/src/server/monster_alien_controller.qc @@ -0,0 +1,128 @@ +/* + * 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 monster_alien_controller (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Alien Controller + +*/ + +enum +{ + CON_ATTACK, + CON_ATTACK2, + CON_THROW, + CON_IDLE2, + CON_BLOCK, + CON_SHOOT, + CON_FLINCH, + CON_FLINCH2, + CON_FALL, + CON_FORWARD, + CON_BACKWARD, + CON_UP, + CON_DOWN, + CON_RIGHT, + CON_LEFT, + CON_IDLE, + CON_UNUSED, + CON_UNUSED2, + CON_DIE +}; + +class monster_alien_controller:CBaseMonster +{ + float m_flIdleTime; + float m_flPainTime; + + void(void) monster_alien_controller; + + virtual void(void) Pain; + virtual void(void) Death; + virtual void(void) IdleNoise; + virtual void(void) Respawn; +}; + +void +monster_alien_controller::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flPainTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_alien_controller.die"); + SetFrame(CON_FLINCH + floor(random(0, 2))); + m_flPainTime = time + 0.25f; +} + +void +monster_alien_controller::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + SetFrame(CON_DIE); + Sound_Play(this, CHAN_VOICE, "monster_alien_controller.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_alien_controller::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_alien_controller.idle"); +} + +void +monster_alien_controller::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(CON_IDLE); +} + +void +monster_alien_controller::monster_alien_controller(void) +{ + Sound_Precache("monster_alien_controller.alert"); + Sound_Precache("monster_alien_controller.attack"); + Sound_Precache("monster_alien_controller.die"); + Sound_Precache("monster_alien_controller.idle"); + Sound_Precache("monster_alien_controller.pain"); + netname = "Alien Controller"; + model = "models/controller.mdl"; + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_alien_grunt.qc b/src/server/monster_alien_grunt.qc new file mode 100644 index 0000000..64f7e45 --- /dev/null +++ b/src/server/monster_alien_grunt.qc @@ -0,0 +1,153 @@ +/* + * 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 monster_alien_grunt (0 0.8 0.8) (-32 -32 0) (32 32 64) + +HALF-LIFE (1998) ENTITY + +Alien Grunt + +*/ + +enum +{ + AG_IDLE, + AG_THREAT, + AG_WALK, + AG_RUN, + AG_LEFT, + AG_RIGHT, + AG_FLINCH, + AG_FLINCHBIG, + AG_ATTACK, + AG_ATTACK2, + AG_VICTORYSQUAT, + AG_VICTORYEAT, + AG_VICTORYSTAND, + AG_FLINCHARML, + AG_FLINCHLEGL, + AG_FLINCHARMR, + AG_FLINCHLEGR, + AG_SHOOTUP, + AG_SHOOTDOWN, + AG_SHOOT, + AG_SHOOTQUICK, + AG_SHOOTLONG, + AG_DIEHS, + AG_DIEGUT, + AG_DIEFORWARD, + AG_DIE, + AG_DIEBACK, + AG_FLOAT, + AG_SCARE, + AG_OPEN, + AG_SMASHRAIL, + AG_LAND +}; + +class monster_alien_grunt:CBaseMonster +{ + float m_flIdleTime; + float m_flPainTime; + + void(void) monster_alien_grunt; + + virtual void(void) Pain; + virtual void(void) Death; + virtual void(void) IdleNoise; + virtual void(void) Respawn; +}; + +void +monster_alien_grunt::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flPainTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_alien_grunt.pain"); + SetFrame(AG_FLINCH + floor(random(0, 2))); + m_flPainTime = time + 0.25f; +} + +void +monster_alien_grunt::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + /* headshots == different animation */ + if (g_dmg_iHitBody == BODY_HEAD) { + if (random() < 0.5) { + SetFrame(AG_DIEHS); + } else { + SetFrame(AG_DIEFORWARD); + } + } else { + SetFrame(AG_DIE + floor(random(0, 2))); + } + + Sound_Play(this, CHAN_VOICE, "monster_alien_grunt.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_alien_grunt::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_alien_grunt.idle"); +} + +void +monster_alien_grunt::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(AG_IDLE); +} + +void +monster_alien_grunt::monster_alien_grunt(void) +{ + Sound_Precache("monster_alien_grunt.alert"); + Sound_Precache("monster_alien_grunt.attack"); + Sound_Precache("monster_alien_grunt.die"); + Sound_Precache("monster_alien_grunt.idle"); + Sound_Precache("monster_alien_grunt.pain"); + + netname = "Alien Grunt"; + model = "models/agrunt.mdl"; + base_mins = [-32,-32,0]; + base_maxs = [32,32,64]; + base_health = Skill_GetValue("agrunt_health", 90); + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_alien_slave.qc b/src/server/monster_alien_slave.qc new file mode 100644 index 0000000..7dea1a5 --- /dev/null +++ b/src/server/monster_alien_slave.qc @@ -0,0 +1,254 @@ +/* + * 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 monster_alien_slave (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Alien Slave + +*/ + +enum +{ + SLV_IDLE, + SLV_IDLE2, + SLV_IDLE3, + SLV_CROUCH, + SLV_WALK, + SLV_WALK2, + SLV_RUN, + SLV_RIGHT, + SLV_LEFT, + SLV_JUMP, + SLV_STAIRUP, + SLV_ATTACK, + SLV_ATTACKZAP, + SLV_FLINCH, + SLV_FLINCHLA, + SLV_FLINCHRA, + SLV_FLINCHL, + SLV_FLINCHR, + SLV_DIEHS, + SLV_DIE, + SLV_DIEBACK, + SLV_DIEFORWARD, + SLV_COLLAR, + SLV_COLLAR2, + SLV_PUSHUP, + SLV_GRAB, + SLV_UPDOWN, + SLV_DOWNUP, + SLV_JIBBER, + SLV_JABBER +}; + +class monster_alien_slave:CBaseNPC +{ + float m_flIdleTime; + float m_flPainTime; + + void(void) monster_alien_slave; + + virtual void(void) Death; + virtual void(void) Pain; + virtual void(void) IdleChat; + virtual void(void) Respawn; + + virtual int(void) AnimIdle; + virtual int(void) AnimWalk; + virtual int(void) AnimRun; + + virtual int(void) AttackMelee; + virtual void(void) AttackFlail; + + virtual int(void) AttackRanged; + virtual void(void) AttackBeam; +}; + +int +monster_alien_slave::AnimIdle(void) +{ + return SLV_IDLE; +} + +int +monster_alien_slave::AnimWalk(void) +{ + return SLV_WALK; +} + +int +monster_alien_slave::AnimRun(void) +{ + return SLV_RUN; +} + +int +monster_alien_slave::AttackMelee(void) +{ + /* visual */ + AnimPlay(SLV_ATTACK); + + m_flAttackThink = m_flAnimTime; + + /* functional */ + think = AttackFlail; + nextthink = 0.25f; + return TRUE; +} + +void +monster_alien_slave::AttackFlail(void) +{ + traceline(origin, m_eEnemy.origin, FALSE, this); + + if (trace_fraction >= 1.0 || trace_ent.takedamage != DAMAGE_YES) { + Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackmiss"); + return; + } + + Damage_Apply(trace_ent, this, 25, 0, 0); + Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackhit"); +} + +int +monster_alien_slave::AttackRanged(void) +{ + /* visual */ + AnimPlay(SLV_ATTACKZAP); + + m_flAttackThink = m_flAnimTime; + Sound_Play(this, CHAN_VOICE, "monster_alien_slave.attack_charge"); + + /* functional */ + think = AttackBeam; + nextthink = time + 1.5f; + return TRUE; +} + +void +monster_alien_slave::AttackBeam(void) +{ + traceline(origin, m_eEnemy.origin, FALSE, this); + Sound_Play(this, CHAN_WEAPON, "monster_alien_slave.attack_shoot"); + + if (trace_fraction >= 1.0 || trace_ent.takedamage != DAMAGE_YES) { + //Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackmiss"); + return; + } + + Damage_Apply(trace_ent, this, 100, 0, 0); +} + +void +monster_alien_slave::IdleChat(void) +{ + if (m_flIdleTime > time) { + return; + } + + Sentence(m_talkIdle); + + m_flIdleTime = time + 5.0f + random(0,20); +} + +void +monster_alien_slave::Pain(void) +{ + CBaseNPC::Pain(); + + if (m_flPainTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_alien_slave.pain"); + SetFrame(SLV_FLINCH + floor(random(0, 2))); + m_flPainTime = time + 0.25f; +} + +void +monster_alien_slave::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + /* headshots == different animation */ + if (g_dmg_iHitBody == BODY_HEAD) { + if (random() < 0.5) { + SetFrame(SLV_DIEHS); + } else { + SetFrame(SLV_DIEBACK); + } + } else { + SetFrame(SLV_DIE + floor(random(0, 3))); + } + + Sound_Play(this, CHAN_VOICE, "monster_alien_slave.die"); + } + + /* set the functional differences */ + CBaseNPC::Death(); +} + +void +monster_alien_slave::Respawn(void) +{ + CBaseNPC::Respawn(); + SetFrame(SLV_IDLE); +} + +void +monster_alien_slave::monster_alien_slave(void) +{ + Sound_Precache("monster_alien_slave.die"); + Sound_Precache("monster_alien_slave.pain"); + Sound_Precache("monster_alien_slave.attack_charge"); + Sound_Precache("monster_alien_slave.attack_shoot"); + Sound_Precache("monster_zombie.attackhit"); + Sound_Precache("monster_zombie.attackmiss"); + + m_talkAnswer = ""; + m_talkAsk = ""; + m_talkAllyShot = ""; + m_talkGreet = "SLV_ALERT"; + m_talkIdle = "!SLV_IDLE"; + m_talkSmelling = ""; + m_talkStare = ""; + m_talkSurvived = ""; + m_talkWounded = ""; + + m_talkPlayerAsk = ""; + m_talkPlayerGreet = "!SLV_ALERT"; + m_talkPlayerIdle = ""; + m_talkPlayerWounded1 = ""; + m_talkPlayerWounded2 = ""; + m_talkPlayerWounded3 = ""; + m_talkUnfollow = ""; + m_talkFollow = ""; + m_talkStopFollow = ""; + + netname = "Alien Slave"; + model = "models/islave.mdl"; + base_health = Skill_GetValue("islave_health", 30); + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + m_iAlliance = MAL_ALIEN; + CBaseNPC::CBaseNPC(); +} diff --git a/src/server/monster_apache.qc b/src/server/monster_apache.qc new file mode 100644 index 0000000..ff09a44 --- /dev/null +++ b/src/server/monster_apache.qc @@ -0,0 +1,48 @@ +/* + * 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 monster_apache (0 0.8 0.8) (-300 -300 -172) (300 300 8) + +HALF-LIFE (1998) ENTITY + +Boeing AH-64 Apache + +*/ + +class monster_apache:CBaseMonster +{ + void(void) monster_apache; + virtual void(void) Respawn; +}; + +void monster_apache::Respawn(void) +{ + CBaseMonster::Respawn(); + movetype = MOVETYPE_NONE; + takedamage = DAMAGE_NO; + iBleeds = FALSE; + setsize(this, [-300,-300,-172], [300, 300, 8]); +} + +void monster_apache::monster_apache(void) +{ + netname = "Apache"; + model = "models/apache.mdl"; + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + base_health = Skill_GetValue("apache_health", 250); + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_babycrab.qc b/src/server/monster_babycrab.qc new file mode 100644 index 0000000..299ccc3 --- /dev/null +++ b/src/server/monster_babycrab.qc @@ -0,0 +1,34 @@ +/* + * 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 monster_babycrab (0 0.8 0.8) (-16 -16 0) (16 16 36) + +HALF-LIFE (1998) ENTITY + +Baby Headcrab + +*/ + +class monster_babycrab:monster_headcrab +{ + void(void) monster_babycrab; +}; + +void +monster_babycrab::monster_babycrab(void) +{ + monster_headcrab::monster_headcrab(); +} diff --git a/src/server/monster_barnacle.qc b/src/server/monster_barnacle.qc new file mode 100644 index 0000000..5dbaab9 --- /dev/null +++ b/src/server/monster_barnacle.qc @@ -0,0 +1,83 @@ +/* + * 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 monster_barnacle (0 0.8 0.8) (-16 -16 -36) (16 16 0) + +HALF-LIFE (1998) ENTITY + +Barnacle + +*/ + +enum +{ + BCL_IDLE, + BCL_IDLE2, + BCL_IDLE3, + BCL_FLINCH, + BCL_ATTACK, + BCL_CHEW, + BCL_DIE +}; + +class monster_barnacle:CBaseMonster +{ + void(void) monster_barnacle; + + virtual void(void) Death; + virtual void(void) Respawn; + virtual void(void) Physics; +}; + +void +monster_barnacle::Physics(void) +{ + movetype = MOVETYPE_NONE; +} + +void +monster_barnacle::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + SetFrame(BCL_DIE); + Sound_Play(this, CHAN_VOICE, "monster_barnacle.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_barnacle::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(BCL_IDLE); +} + +void monster_barnacle::monster_barnacle(void) +{ + Sound_Precache("monster_barnacle.attackchew"); + Sound_Precache("monster_barnacle.attackpull"); + Sound_Precache("monster_barnacle.die"); + + netname = "Barnacle"; + model = "models/barnacle.mdl"; + base_mins = [-16,-16,-36]; + base_maxs = [16,16,0]; + base_health = Skill_GetValue("barnacle_health", 25); + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_barney.qc b/src/server/monster_barney.qc new file mode 100644 index 0000000..67e37c6 --- /dev/null +++ b/src/server/monster_barney.qc @@ -0,0 +1,209 @@ +/* + * 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 monster_barney (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Barney Calhoun + +*/ + +enum +{ + BA_IDLE1, + BA_IDLE2, + BA_IDLE3, + BA_IDLE4, + BA_WALK, + BA_RUN, + BA_SHOOT1, + BA_SHOOT2, + BA_DRAW, + BA_HOLSTER, + BA_RELOAD, + BA_TURNLEFT, + BA_TURNRIGHT, + BA_FLINCH_LA, + BA_FLINCH_RA, + BA_FLINCH_LL, + BA_FLINCH_RL, + BA_FLINCH_SML +}; + +class monster_barney:CBaseNPC +{ + void(void) monster_barney; + + 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; + + virtual void(void) AttackDraw; + virtual void(void) AttackHolster; + virtual int(void) AttackMelee; + virtual int(void) AttackRanged; +}; + +int +monster_barney::AnimIdle(void) +{ + return BA_IDLE1; +} + +int +monster_barney::AnimWalk(void) +{ + return BA_WALK; +} + +int +monster_barney::AnimRun(void) +{ + return BA_RUN; +} + +void +monster_barney::AttackDraw(void) +{ + AnimPlay(BA_DRAW); + m_flAttackThink = m_flAnimTime; +} + +void +monster_barney::AttackHolster(void) +{ + AnimPlay(BA_HOLSTER); + m_flAttackThink = m_flAnimTime; +} + +int +monster_barney::AttackMelee(void) +{ + return AttackRanged(); +} + +int +monster_barney::AttackRanged(void) +{ + /* visual */ + AnimPlay(BA_SHOOT1); + m_flAttackThink = time + 0.4f; + + /* functional */ + v_angle = vectoangles(m_eEnemy.origin - origin); + TraceAttack_FireBullets(1, origin + [0,0,16], 8, [0.01,0.01], 2); + Sound_Play(this, CHAN_WEAPON, "weapon_glock.fire"); + return TRUE; +} + +void +monster_barney::OnPlayerUse(void) +{ + if (spawnflags & MSF_PREDISASTER) { + Sentence("!BA_POK"); + return; + } + + CBaseNPC::OnPlayerUse(); +} + +void +monster_barney::Pain(void) +{ + CBaseNPC::Pain(); + + WarnAllies(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Speak(this, "monster_barney.pain"); + + AnimPlay(BA_FLINCH_LA + floor(random(0, 5))); + m_flAttackThink = m_flAnimTime; + m_iFlags |= MONSTER_FEAR; +} + +void +monster_barney::Death(void) +{ + WarnAllies(); + + if (style != MONSTER_DEAD) { + SetFrame(25 + floor(random(0, 6))); + Sound_Speak(this, "monster_barney.die"); + } + + /* now mark our state as 'dead' */ + CBaseNPC::Death(); +} + +void +monster_barney::Respawn(void) +{ + CBaseNPC::Respawn(); + m_iFlags |= MONSTER_CANFOLLOW; + PlayerUse = OnPlayerUse; +} + +void +monster_barney::monster_barney(void) +{ + Sound_Precache("monster_barney.die"); + Sound_Precache("monster_barney.pain"); + + /* TODO + * BA_MAD - When player gets too naughty + * */ + m_talkAnswer = "!BA_ANSWER"; + m_talkAsk = "!BA_QUESTION"; + m_talkAllyShot = "!BA_SHOOT"; + m_talkGreet = ""; + m_talkIdle = "!BA_IDLE"; + m_talkHearing = "!BA_HEAR"; + m_talkSmelling = "!BA_SMELL"; + m_talkStare = "!BA_STARE"; + m_talkSurvived = "!BA_WOUND"; + m_talkWounded = "!BA_WOUND"; + + m_talkPlayerAsk = "!BA_QUESTION"; + m_talkPlayerGreet = "!BA_HELLO"; + m_talkPlayerIdle = "!BA_IDLE"; + m_talkPlayerWounded1 = "!BA_CUREA"; + m_talkPlayerWounded2 = "!BA_CUREB"; + m_talkPlayerWounded3 = "!BA_CUREC"; + m_talkUnfollow = "!BA_WAIT"; + m_talkFollow = "!BA_OK"; + m_talkStopFollow = "!BA_STOP"; + + model = "models/barney.mdl"; + netname = "Barney"; + base_health = Skill_GetValue("barney_health", 35); + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + m_iAlliance = MAL_FRIEND; + CBaseNPC::CBaseNPC(); +} diff --git a/src/server/monster_barney_dead.qc b/src/server/monster_barney_dead.qc new file mode 100644 index 0000000..15acce9 --- /dev/null +++ b/src/server/monster_barney_dead.qc @@ -0,0 +1,89 @@ +/* + * 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 monster_barney_dead (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Barney's corpse + +*/ + +class monster_barney_dead:CBaseEntity +{ + int m_iPose; + void(void) monster_barney_dead; + + virtual void(void) Hide; + virtual void(void) Respawn; + virtual void(void) Gib; + virtual void(string, string) SpawnKey; +}; + +void +monster_barney_dead::Gib(void) +{ + takedamage = DAMAGE_NO; + FX_GibHuman(this.origin); + Hide(); +} + +void +monster_barney_dead::Hide(void) +{ + SetModel(""); + solid = SOLID_NOT; + movetype = MOVETYPE_NONE; +} + +void +monster_barney_dead::Respawn(void) +{ + v_angle[0] = Math_FixDelta(m_oldAngle[0]); + v_angle[1] = Math_FixDelta(m_oldAngle[1]); + v_angle[2] = Math_FixDelta(m_oldAngle[2]); + + SetOrigin(m_oldOrigin); + angles = v_angle; + solid = SOLID_CORPSE; + movetype = MOVETYPE_NONE; + SetModel(m_oldModel); + setsize(this, VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]); + takedamage = DAMAGE_YES; + health = 0; + velocity = [0,0,0]; + iBleeds = TRUE; + SetFrame(35 + m_iPose); +} + +void +monster_barney_dead::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "pose": + m_iPose = stoi(strValue); + break; + default: + CBaseMonster::SpawnKey(strKey, strValue); + } +} + +void +monster_barney_dead::monster_barney_dead(void) +{ + model = "models/barney.mdl"; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_bigmomma.qc b/src/server/monster_bigmomma.qc new file mode 100644 index 0000000..705f45d --- /dev/null +++ b/src/server/monster_bigmomma.qc @@ -0,0 +1,132 @@ +/* + * 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 monster_bigmomma (0 0.8 0.8) (-95 -95 0) (95 95 190) + +HALF-LIFE (1998) ENTITY + +Gonarch + +*/ + +enum +{ + GON_IDLE, + GON_IDLE2, + GON_WALK, + GON_RUN, + GON_DIE, + GON_CLAW, + GON_CLAW2, + GON_CLAW3, + GON_SPAWN, + GON_SHOOT, + GON_FLINCH, + GON_DEFEND, + GON_JUMP, + GON_ANGRY, + GON_ANGRY2, + GON_ANGRY3, + GON_BREAKWALL, + GON_FALL, + GON_FALL2, + GON_FALLDIE +}; + +class monster_bigmomma:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_bigmomma; + + virtual void(void) Death; + virtual void(void) Pain; + virtual void(void) IdleNoise; + virtual void(void) Respawn; +}; + +void +monster_bigmomma::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + /* timing needs to adjusted as sounds conflict */ + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_bigmomma.idle"); +} + +void +monster_bigmomma::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_bigmomma.pain"); + SetFrame(GON_FLINCH); + m_flAnimTime = time + 0.25f; +} + +void +monster_bigmomma::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + SetFrame(GON_DIE); + Sound_Play(this, CHAN_VOICE, "monster_bigmomma.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_bigmomma::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(GON_IDLE); +} + +void monster_bigmomma::monster_bigmomma(void) +{ + Sound_Precache("monster_bigmomma.alert"); + Sound_Precache("monster_bigmomma.attack"); + Sound_Precache("monster_bigmomma.child"); + Sound_Precache("monster_bigmomma.die"); + Sound_Precache("monster_bigmomma.idle"); + Sound_Precache("monster_bigmomma.pain"); + Sound_Precache("monster_bigmomma.step"); + netname = "Gonarch"; + model = "models/big_mom.mdl"; + /* health is based on factor, for it's not killable until last stage */ + base_health = Skill_GetValue("bigmomma_health_factor", 1.5) * 300; + base_mins = [-95,-95,0]; + base_maxs = [95,95,190]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_bloater.qc b/src/server/monster_bloater.qc new file mode 100644 index 0000000..9ed3b7b --- /dev/null +++ b/src/server/monster_bloater.qc @@ -0,0 +1,37 @@ +/* + * 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 monster_bloater (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Flocking Floater + +*/ + +class monster_bloater:CBaseMonster +{ + void(void) monster_bloater; +}; + +void monster_bloater::monster_bloater(void) +{ + netname = "Floater"; + model = "models/floater.mdl"; + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_bullchicken.qc b/src/server/monster_bullchicken.qc new file mode 100644 index 0000000..2ab5ae2 --- /dev/null +++ b/src/server/monster_bullchicken.qc @@ -0,0 +1,155 @@ +/* + * 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 monster_bullchicken (0 0.8 0.8) (-32 -32 0) (32 32 64) + +HALF-LIFE (1998) ENTITY + +Bullsquid + +*/ + +enum +{ + BULL_WALK, + BULL_RUN, + BULL_SURPIRSE, + BULL_FLINCH, + BULL_FLINCH2, + BULL_LEFT, + BULL_RIGHT, + BULL_IDLE, + BULL_WHIP, + BULL_BITE, + BULL_RANGE, + BULL_LOOK, + BULL_SEECRAB, + BULL_EAT, + BULL_INSPECT, + BULL_SNIFF, + BULL_DIE, + BULL_DIE2, + BULL_JUMP, + BULL_DRAGIDLE, + BULL_DRAG, + BULL_SCARE, + BULL_FALLIDLE, + BULL_FALL +}; + +/* the growls are used in combination with the bite sounds + * for close range attacks + */ + +class monster_bullchicken:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_bullchicken; + + virtual void(void) Death; + virtual void(void) Pain; + virtual void(void) IdleNoise; + virtual int(void) AnimIdle; + virtual int(void) AnimWalk; + virtual int(void) AnimRun; +}; + +int +monster_bullchicken::AnimIdle(void) +{ + return BULL_IDLE; +} + +int +monster_bullchicken::AnimWalk(void) +{ + return BULL_WALK; +} + +int +monster_bullchicken::AnimRun(void) +{ + return BULL_RUN; +} + +void +monster_bullchicken::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + /* timing needs to adjusted as sounds conflict */ + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_bullchicken.idle"); +} + +void +monster_bullchicken::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_bullchicken.pain"); + SetFrame((random() < 0.5) ? BULL_FLINCH : BULL_FLINCH2); + m_flAnimTime = time + 0.25f; +} + +void +monster_bullchicken::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + + /* two different animations */ + SetFrame((random() < 0.5) ? BULL_DIE : BULL_DIE2); + + Sound_Play(this, CHAN_VOICE, "monster_bullchicken.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void monster_bullchicken::monster_bullchicken(void) +{ + Sound_Precache("monster_bullchicken.alert"); + Sound_Precache("monster_bullchicken.attack"); + Sound_Precache("monster_bullchicken.attackbite"); + Sound_Precache("monster_bullchicken.attackshoot"); + Sound_Precache("monster_bullchicken.die"); + Sound_Precache("monster_bullchicken.idle"); + Sound_Precache("monster_bullchicken.pain"); + netname = "Bullsquid"; + model = "models/bullsquid.mdl"; + base_health = Skill_GetValue("bullsquid_health", 40); + base_mins = [-32,-32,0]; + base_maxs = [32,32,64]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_cockroach.qc b/src/server/monster_cockroach.qc new file mode 100644 index 0000000..333f8f6 --- /dev/null +++ b/src/server/monster_cockroach.qc @@ -0,0 +1,54 @@ +/* + * 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 monster_cockroach (0 0.8 0.8) (-4 -4 0) (4 4 4) + +HALF-LIFE (1998) ENTITY + +Cockroach + +*/ + +class monster_cockroach:CBaseMonster +{ + void(void) monster_cockroach; + virtual void(void) Death; +}; + +void +monster_cockroach::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + Sound_Play(this, CHAN_VOICE, "monster_cockroach.die"); + } + + /* make sure we gib this thing */ + health = -100; + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void monster_cockroach::monster_cockroach(void) +{ + Sound_Precache("monster_cockroach.die"); + netname = "Cockroach"; + model = "models/roach.mdl"; + base_mins = [-1,-1,0]; + base_maxs = [1,1,1]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_flyer_flock.qc b/src/server/monster_flyer_flock.qc new file mode 100644 index 0000000..9b4305e --- /dev/null +++ b/src/server/monster_flyer_flock.qc @@ -0,0 +1,37 @@ +/* + * 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 monster_flyer_flock (0 0.8 0.8) (-16 -16 0) (16 16 16) + +HALF-LIFE (1998) ENTITY + +Boid + +*/ + +class monster_flyer_flock:CBaseMonster +{ + void(void) monster_flyer_flock; +}; + +void monster_flyer_flock::monster_flyer_flock(void) +{ + netname = "Boid"; + model = "models/aflock.mdl"; + base_mins = [-16,-16,0]; + base_maxs = [16,16,16]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_gargantua.qc b/src/server/monster_gargantua.qc new file mode 100644 index 0000000..736d000 --- /dev/null +++ b/src/server/monster_gargantua.qc @@ -0,0 +1,138 @@ +/* + * 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 monster_gargantua (0 0.8 0.8) (-32 -32 0) (32 32 128) + +HALF-LIFE (1998) ENTITY + +Gargantua + +*/ + +enum +{ + GARG_IDLE, + GARG_IDLE2, + GARG_IDLE3, + GARG_IDLE4, + GARG_WALK, + GARG_RUN, + GARG_SHOOT, + GARG_SHOOT2, + GARG_ATTACK, + GARG_STOMP, + GARG_LEFT, + GARG_RIGHT, + GARG_FLINCH, + GARG_FLINCH2, + GARG_DIE, + GARG_BITEHEAD, + GARG_THROW, + GARG_SMASH, + GARG_ROLLCAR, + GARG_KICKCAR, + GARG_PUSHCAR, + GARG_BUST +}; + +class monster_gargantua:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_gargantua; + + virtual void(void) Death; + virtual void(void) Pain; + virtual void(void) IdleNoise; + virtual void(void) Respawn; +}; + +void +monster_gargantua::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + /* timing needs to adjusted as sounds conflict */ + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_gargantua.idle"); +} + +void +monster_gargantua::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_gargantua.pain"); + SetFrame((random() < 0.5) ? GARG_FLINCH : GARG_FLINCH2); + m_flAnimTime = time + 0.25f; +} + +void +monster_gargantua::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + SetFrame(GARG_DIE); + Sound_Play(this, CHAN_VOICE, "monster_gargantua.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_gargantua::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(GARG_IDLE); + /* takes damage from explosives only + * takedamage = DAMAGE_NO; */ + iBleeds = FALSE; +} + +void monster_gargantua::monster_gargantua(void) +{ + Sound_Precache("monster_gargantua.alert"); + Sound_Precache("monster_gargantua.attack"); + Sound_Precache("monster_gargantua.attackflame"); + Sound_Precache("monster_gargantua.attackflameon"); + Sound_Precache("monster_gargantua.attackflameoff"); + Sound_Precache("monster_gargantua.die"); + Sound_Precache("monster_gargantua.idle"); + Sound_Precache("monster_gargantua.pain"); + Sound_Precache("monster_gargantua.step"); + netname = "Gargantua"; + model = "models/garg.mdl"; + base_health = Skill_GetValue("gargantua_health", 800); + base_mins = [-32,-32,0]; + base_maxs = [32,32,128]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_gman.qc b/src/server/monster_gman.qc new file mode 100644 index 0000000..d1fff66 --- /dev/null +++ b/src/server/monster_gman.qc @@ -0,0 +1,87 @@ +/* + * 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 monster_gman (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +G-Man + +*/ + +enum +{ + GMAN_IDLE, + GMAN_IDLETIE, + GMAN_IDLELOOK, + GMAN_IDLE2, + GMAN_OPEN, + GMAN_STAND, + GMAN_WALK, + GMAN_YES, + GMAN_NO, + GMAN_NOBIG, + GMAN_YESBIG, + GMAN_LISTEN, + GMAN_LOOKDOWN, + GMAN_LOOKDOWN2 +}; + +class monster_gman:CBaseMonster +{ + void(void) monster_gman; + + virtual void(void) Respawn; + virtual int(void) AnimIdle; + virtual int(void) AnimWalk; + virtual int(void) AnimRun; +}; + +int +monster_gman::AnimIdle(void) +{ + return GMAN_IDLE; +} + +int +monster_gman::AnimWalk(void) +{ + return GMAN_WALK; +} + +int +monster_gman::AnimRun(void) +{ + return GMAN_WALK; +} + +void monster_gman::Respawn(void) +{ + /* he can't die, he's the G-Man! */ + CBaseMonster::Respawn(); + SetFrame(GMAN_IDLE); + takedamage = DAMAGE_NO; + iBleeds = FALSE; +} + +void monster_gman::monster_gman(void) +{ + netname = "G-Man"; + model = "models/gman.mdl"; + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_headcrab.qc b/src/server/monster_headcrab.qc new file mode 100644 index 0000000..00f0cd2 --- /dev/null +++ b/src/server/monster_headcrab.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 monster_headcrab (0 0.8 0.8) (-16 -16 0) (16 16 36) + +HALF-LIFE (1998) ENTITY + +Headcrab + +*/ + +enum +{ + HC_IDLE1, + HC_IDLE2, + HC_IDLE3, + HC_WALK, + HC_RUN, + HC_ANGRY, + HC_FLINCH, + HC_DIE, + HC_180_LEFT, + HC_180_RIGHT, + HC_JUMP, + HC_JUMP_VARIATION1, + HC_JUMP_VARIATION2, + HC_YAW_ADJUSTMENT, + HC_HEADCRABBED1, + HC_HEADCRABBED2, + HC_HEADIDLE, + HC_CRASHIDLE, + HC_CRASH, + HC_STRUGGLEIDLE, + HC_STRUGGLE +}; + +class monster_headcrab:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_headcrab; + + virtual void(void) Pain; + virtual void(void) Death; + virtual void(void) IdleNoise; + virtual int(void) AnimIdle; + virtual int(void) AnimWalk; + virtual int(void) AnimRun; + virtual int(void) AttackRanged; + virtual void(void) touch; +}; + +int +monster_headcrab::AnimIdle(void) +{ + return HC_IDLE1; +} + +int +monster_headcrab::AnimWalk(void) +{ + return HC_WALK; +} + +int +monster_headcrab::AnimRun(void) +{ + return HC_RUN; +} + +int +monster_headcrab::AttackRanged(void) +{ + /* visual */ + if (random() < 0.5) + AnimPlay(HC_JUMP); + else + AnimPlay(HC_JUMP_VARIATION1); + + m_flAttackThink = m_flAnimTime; + Sound_Play(this, CHAN_VOICE, "monster_headcrab.attack"); + + /* functional */ + makevectors(vectoangles(m_eEnemy.origin - origin)); + velocity = v_forward * 512 + [0,0,250]; + return TRUE; +} + +void +monster_headcrab::touch(void) +{ + if (other.takedamage == DAMAGE_YES) + if (frame == HC_JUMP || frame == HC_JUMP_VARIATION1) + Damage_Apply(other, this, 500, 0, 0); +} + +void +monster_headcrab::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_headcrab.pain"); + SetFrame(HC_FLINCH); + m_flAnimTime = time + 0.25f; +} + +void +monster_headcrab::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + SetFrame(HC_DIE); + Sound_Play(this, CHAN_VOICE, "monster_headcrab.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_headcrab::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_headcrab.idle"); +} + +void +monster_headcrab::monster_headcrab(void) +{ + Sound_Precache("monster_headcrab.alert"); + Sound_Precache("monster_headcrab.attack"); + Sound_Precache("monster_headcrab.attackhit"); + Sound_Precache("monster_headcrab.die"); + Sound_Precache("monster_headcrab.idle"); + Sound_Precache("monster_headcrab.pain"); + + if (classname == "monster_babycrab") { + netname = "Baby Headcrab"; + model = "models/baby_headcrab.mdl"; + base_health = Skill_GetValue ("headcrab_health", 10) /4; + } else { + netname = "Headcrab"; + model = "models/headcrab.mdl"; + base_health = Skill_GetValue("headcrab_health", 10); + } + + base_mins = [-16,-16,0]; + base_maxs = [16,16,36]; + m_iAlliance = MAL_ALIEN; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_hevsuit_dead.qc b/src/server/monster_hevsuit_dead.qc new file mode 100644 index 0000000..f99937a --- /dev/null +++ b/src/server/monster_hevsuit_dead.qc @@ -0,0 +1,97 @@ +/* + * 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 monster_hevsuit_dead (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +HEV-Suit/Player's corpse + +*/ + +class monster_hevsuit_dead:CBaseMonster +{ + int m_iPose; + void(void) monster_hevsuit_dead; + + virtual void(void) Hide; + virtual void(void) Respawn; + virtual void(void) Gib; + virtual void(string, string) SpawnKey; +}; + +void +monster_hevsuit_dead::Gib(void) +{ + takedamage = DAMAGE_NO; + FX_GibHuman(this.origin); + Hide(); +} + +void +monster_hevsuit_dead::Hide(void) +{ + SetModel(""); + solid = SOLID_NOT; + movetype = MOVETYPE_NONE; +} + +void +monster_hevsuit_dead::Respawn(void) +{ + v_angle[0] = Math_FixDelta(m_oldAngle[0]); + v_angle[1] = Math_FixDelta(m_oldAngle[1]); + v_angle[2] = Math_FixDelta(m_oldAngle[2]); + + SetOrigin(m_oldOrigin); + angles = v_angle; + solid = SOLID_CORPSE; + movetype = MOVETYPE_NONE; + SetModel(m_oldModel); + setsize(this, VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]); + takedamage = DAMAGE_YES; + health = 0; + velocity = [0,0,0]; + iBleeds = TRUE; + SetFrame(73 + m_iPose); + SendFlags |= NPC_BODY; +} + +void +monster_hevsuit_dead::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "pose": + m_iPose = stoi(strValue); + break; + case "body": + SetBody(stoi(strValue) + 1); + break; + case "skin": + SetSkin(stoi(strValue)); + break; + default: + CBaseMonster::SpawnKey(strKey, strValue); + } +} + +void +monster_hevsuit_dead::monster_hevsuit_dead(void) +{ + model = "models/player.mdl"; + m_iBody = 2; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_hgrunt_dead.qc b/src/server/monster_hgrunt_dead.qc new file mode 100644 index 0000000..77d6a1c --- /dev/null +++ b/src/server/monster_hgrunt_dead.qc @@ -0,0 +1,96 @@ +/* + * 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 monster_hgrunt_dead (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Human Grunt's corpse + +*/ + +class monster_hgrunt_dead:CBaseMonster +{ + int m_iPose; + void(void) monster_hgrunt_dead; + + virtual void(void) Hide; + virtual void(void) Respawn; + virtual void(void) Gib; + virtual void(string, string) SpawnKey; +}; + +void +monster_hgrunt_dead::Gib(void) +{ + takedamage = DAMAGE_NO; + FX_GibHuman(this.origin); + Hide(); +} + +void +monster_hgrunt_dead::Hide(void) +{ + SetModel(""); + solid = SOLID_NOT; + movetype = MOVETYPE_NONE; +} + +void +monster_hgrunt_dead::Respawn(void) +{ + v_angle[0] = Math_FixDelta(m_oldAngle[0]); + v_angle[1] = Math_FixDelta(m_oldAngle[1]); + v_angle[2] = Math_FixDelta(m_oldAngle[2]); + + SetOrigin(m_oldOrigin); + angles = v_angle; + solid = SOLID_CORPSE; + movetype = MOVETYPE_NONE; + SetModel(m_oldModel); + setsize(this, VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]); + takedamage = DAMAGE_YES; + health = 0; + velocity = [0,0,0]; + iBleeds = TRUE; + SetFrame(44 + m_iPose); + SendFlags |= NPC_BODY; +} + +void +monster_hgrunt_dead::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "pose": + m_iPose = stoi(strValue); + break; + case "body": + m_iBody = stoi(strValue) + 1; + break; + case "skin": + skin = stoi(strValue); + break; + default: + CBaseMonster::SpawnKey(strKey, strValue); + } +} + +void +monster_hgrunt_dead::monster_hgrunt_dead(void) +{ + model = "models/hgrunt.mdl"; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_houndeye.qc b/src/server/monster_houndeye.qc new file mode 100644 index 0000000..7a6cc0b --- /dev/null +++ b/src/server/monster_houndeye.qc @@ -0,0 +1,202 @@ +/* + * 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 monster_houndeye (0 0.8 0.8) (-16 -16 0) (16 16 36) + +HALF-LIFE (1998) ENTITY + +Houndeye + +*/ + +#define HE_BLAST_RADIUS 384 + +enum +{ + HE_IDLE, + HE_IDLE2, + HE_IDLE3, + HE_RUN, + HE_RUN2, + HE_RUN3, + HE_DIE, + HE_DIE2, + HE_DIE3, + HE_DIE4, + HE_ATTACK, + HE_FLINCH, + HE_FLINCH2, + HE_DIE5, + HE_WALKLIMP, + HE_WALK2, + HE_LEADERLOOK, + HE_SLEEP, + HE_GOTOSLEEP, + HE_WAKE, + HE_IDLEMAD, + HE_IDLEMAD2, + HE_IDLEMAD3, + HE_INSPECT, + HE_EAT, + HE_LEFT, + HE_RIGHT, + HE_JUMPBACK, + HE_WAKEFAST, + HE_WHIMPER, + HE_JUMPWINDOW +}; + +class monster_houndeye:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_houndeye; + + virtual void(void) Pain; + virtual void(void) Death; + virtual void(void) IdleNoise; + virtual void(void) Respawn; + + virtual int(void) AttackMelee; + virtual void(void) AttackBlast; +}; + +int +monster_houndeye::AttackMelee(void) +{ + AnimPlay(HE_ATTACK); + Sound_Play(this, CHAN_WEAPON, "monster_houndeye.attack"); + m_flAttackThink = m_flAnimTime + 0.5f; + + think = AttackBlast; + nextthink = m_flAnimTime; + return TRUE; +} + +void +monster_houndeye::AttackBlast(void) +{ + float new_dmg; + float dist; + float diff; + vector pos; + float dmg = 50; /* TODO: set proper damage */ + + for (entity e = world; (e = findfloat(e, ::takedamage, DAMAGE_YES));) { + pos[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0])); + pos[1] = e.absmin[1] + (0.5 * (e.absmax[1] - e.absmin[1])); + pos[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2])); + + if (e.classname == "monster_houndeye") + continue; + + /* don't bother if it's not anywhere near us */ + dist = vlen(origin - pos); + if (dist > HE_BLAST_RADIUS) { + continue; + } + + /* can we physically hit this thing? */ + other = world; + traceline(e.origin, origin, MOVE_OTHERONLY, this); + + if (trace_fraction < 1.0f) + dmg *= 0.5f; + + /* calculate new damage values */ + diff = vlen(origin - pos); + diff = (HE_BLAST_RADIUS - diff) / HE_BLAST_RADIUS; + new_dmg = rint(dmg * diff); + + if (diff > 0) { + Damage_Apply(e, this, new_dmg, 0, DMG_EXPLODE); + } + } + Sound_Play(this, CHAN_WEAPON, "monster_houndeye.blast"); +} + +void +monster_houndeye::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_houndeye.pain"); + SetFrame(HE_FLINCH + floor(random(0, 2))); + m_flAnimTime = time + 0.25f; +} + +void +monster_houndeye::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + SetFrame(HE_DIE + floor(random(0, 4))); + + Sound_Play(this, CHAN_VOICE, "monster_houndeye.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_houndeye::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_houndeye.idle"); +} + +void +monster_houndeye::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(HE_IDLE); +} + +void +monster_houndeye::monster_houndeye(void) +{ + Sound_Precache("monster_houndeye.alert"); + Sound_Precache("monster_houndeye.attack"); + Sound_Precache("monster_houndeye.blast"); + Sound_Precache("monster_houndeye.die"); + Sound_Precache("monster_houndeye.idle"); + Sound_Precache("monster_houndeye.pain"); + netname = "Houndeye"; + model = "models/houndeye.mdl"; + base_health = Skill_GetValue("houndeye_health", 20); + base_mins = [-16,-16,0]; + base_maxs = [16,16,36]; + m_iAlliance = MAL_ALIEN; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_human_assassin.qc b/src/server/monster_human_assassin.qc new file mode 100644 index 0000000..bda6378 --- /dev/null +++ b/src/server/monster_human_assassin.qc @@ -0,0 +1,94 @@ +/* + * 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 monster_human_assassin (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Black Ops - Assassin + +*/ + +enum +{ + HAS_IDLE, + HAS_IDLE3, + HAS_IDLE2, + HAS_RUN, + HAS_WALK, + HAS_SHOOT, + HAS_NADETHROW, + HAS_KICK, + HAS_KICK2, + HAS_DIERUN, + HAS_DIEBACK, + HAS_DIE, + HAS_JUMP, + HAS_UP, + HAS_UNUSED, + HAS_ATTACKDOWN, + HAS_LAND +}; + +class monster_human_assassin:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_human_assassin; + + virtual void(void) Death; + virtual void(void) Respawn; +}; + +void +monster_human_assassin::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + /* headshots == different animation */ + /* this animation may not have been used, but it looks cool */ + if (g_dmg_iHitBody == BODY_HEAD) { + if (random() < 0.5) { + SetFrame(HAS_DIERUN); + } else { + SetFrame(HAS_DIEBACK); + } + } else { + SetFrame(HAS_DIE); + } + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_human_assassin::Respawn(void) +{ + CBaseMonster::Respawn(); + frame = HAS_IDLE; +} + +void +monster_human_assassin::monster_human_assassin(void) +{ + netname = "Assassin"; + model = "models/hassassin.mdl"; + base_health = Skill_GetValue("hassassin_health", 50); + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_human_grunt.qc b/src/server/monster_human_grunt.qc new file mode 100644 index 0000000..dd6981b --- /dev/null +++ b/src/server/monster_human_grunt.qc @@ -0,0 +1,319 @@ +/* + * 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 monster_human_grunt (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +HECU - Human Grunt + +*/ + +enum +{ + GR_WALK, + GR_RUN, + GR_VICTORYDANCE, + GR_COWER, + GR_FLINCH, + GR_LEFTLEGFLINCH, + GR_RIGHTLEGFLINCH, + GR_RIGHTARMFLINCH, + GR_LEFTARMFLINCH, + GR_LAUNCHNADE, + GR_THROWNADE, + GR_IDLE, + GR_IDLE2, + GR_COMBATIDLE, + GR_FRONTKICK, + GR_CROUCHIDLE, + GR_CROUCHWAIT, + GR_CROUCHSHOOTMP5, + GR_STANDSHOOTMP5, + GR_RELOADMP5, + GR_CROUCHSHOOTSG, + GR_STANDSHOOTSG, + GR_RELOADSG, + GR_SIGNALADV, + GR_SIGNALFLANK, + GR_SIGNALRETREAT, + GR_DROPNADE, + GR_LIMPWALK, + GR_LIMPRUN, + GR_TURNLEFT, + GR_TURNRIGHT, + GR_STRAFELEFT, + GR_STRAFERIGHT, + GR_DIEBACK, + GR_DIEFORWARD, + GR_DIE, + GR_DIEBACK2, + GR_DIEHS, + GR_DIEGUT, + GR_BARNACLE1, + GR_BARNACLE2, + GR_BARNACLE3, + GR_BARNACLE4, + GR_DEADSTOMACH, + GR_DEADSTOMACH2, + GR_DEADSIDE, + GR_DEADSITTING, + GR_REPELJUMP, + GR_REPEL, + GR_REPELSHOOT, + GR_REPELLAND, + GR_REPELDIE, + GR_DRAGHOLEIDLE, + GR_DRAGHOLE, + GR_BUSTWALL, + GR_HOPRAIL, + GR_CONVERSE1, + GR_CONVERSE2, + GR_STARTLELEFT, + GR_STRRTLERIGHT, + GR_DIVE, + GR_DEFUSE, + GR_CORNER1, + GR_CORNER2, + GR_STONETOSS, + GR_CLIFFDIE, + GR_DIVESIDEIDLE, + GR_DIVESIDE, + GR_DIVEKNEELIDLE, + GR_DIVEKNEEL, + GR_WMBUTTON, + GR_WM, + GR_WMJUMP, + GR_BUSTWINDOW, + GR_DRAGLEFT, + GR_DRAGRIGHT, + GR_TRACKWAVE, + GR_TRACKDIVE, + GR_FLYBACK, + GR_IMPALED, + GR_JUMPTRACKS, + GR_THROWPIPE, + GR_PLUNGER +}; + +class monster_human_grunt:CBaseNPC +{ + float m_flIdleTime; + int m_iMP5Burst; + + void(void) monster_human_grunt; + + virtual void(void) Scream; + virtual void(void) IdleChat; + virtual void(void) Respawn; + virtual void(void) Pain; + virtual void(void) Death; + + virtual int(void) AnimIdle; + virtual int(void) AnimWalk; + virtual int(void) AnimRun; + + virtual int(void) AttackRanged; + virtual int(void) AttackMelee; + virtual void(void) AttackKick; + +}; + +int +monster_human_grunt::AnimIdle(void) +{ + return GR_IDLE; +} + +int +monster_human_grunt::AnimWalk(void) +{ + return GR_WALK; +} + +int +monster_human_grunt::AnimRun(void) +{ + return GR_RUN; +} + +int +monster_human_grunt::AttackMelee(void) +{ + /* visual */ + AnimPlay(GR_FRONTKICK); + + m_flAttackThink = m_flAnimTime; + Sound_Play(this, CHAN_VOICE, "monster_zombie.attack"); + + /* functional */ + think = AttackKick; + nextthink = 0.25f; + return TRUE; +} + +void +monster_human_grunt::AttackKick(void) +{ + traceline(origin, m_eEnemy.origin, FALSE, this); + + if (trace_fraction >= 1.0 || trace_ent.takedamage != DAMAGE_YES) { + //Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackmiss"); + return; + } + + Damage_Apply(trace_ent, this, 25, 0, 0); + //Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackhit"); +} + +int +monster_human_grunt::AttackRanged(void) +{ + /* visual */ + AnimPlay(GR_STANDSHOOTMP5); + Sound_Play(this, CHAN_WEAPON, "weapon_mp5.shoot"); + + if (m_iMP5Burst >= 2) { + m_iMP5Burst = 0; + m_flAttackThink = time + 0.4f; + } else { + m_iMP5Burst++; + m_flAttackThink = time + 0.1f; + } + + /* functional */ + v_angle = vectoangles(m_eEnemy.origin - origin); + TraceAttack_FireBullets(1, origin + [0,0,16], 8, [0.01,0.01], 2); + return TRUE; +} + +void monster_human_grunt::Scream(void) +{ + if (m_flIdleTime > time) { + return; + } + + Sentence(m_talkAllyShot); + m_flIdleTime = time + 5.0f; +} + +void monster_human_grunt::IdleChat(void) +{ + if (m_flIdleTime > time) { + return; + } + + Sentence(m_talkIdle); + + /* Sentence(m_talkPlayerIdle); */ + /* come up with logic to make them repsone to questions + * Sentence(m_talkAsk); + * Sentence(m_talkAnswer); + */ + m_flIdleTime = time + 5.0f + random(0,20); +} + +void +monster_human_grunt::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_human_grunt.pain"); + SetFrame(GR_FLINCH); + m_flAnimTime = time + 0.25f; +} + +void +monster_human_grunt::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + /* headshots == different animation */ + /* this animation may not have been used, but it looks cool */ + if (g_dmg_iHitBody == BODY_HEAD) { + if (random() < 0.5) { + SetFrame(GR_DIEHS); + } else { + SetFrame(GR_DIEBACK); + } + } else { + SetFrame(GR_DIE); + } + } + + Sound_Play(this, CHAN_VOICE, "monster_human_grunt.die"); + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_human_grunt::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(GR_IDLE); +} + + +void monster_human_grunt::monster_human_grunt(void) +{ + Sound_Precache("monster_human_grunt.die"); + Sound_Precache("monster_human_grunt.pain"); + + /* Adding some into other slots in hopes it feels right + * listed below are other setences that might need their own: + * !HG_MONST - Monster HG_ALERT + * !HG_GREN - Grenade toss + * !HG_CHECK - Sector check question + * !HG_CLEAR - Sector clear response */ + + m_talkAnswer = "!HG_ANSWER"; + m_talkAsk = "!HG_QUEST"; + m_talkAllyShot = "!HG_COVER"; + m_talkGreet = ""; + m_talkIdle = "!HG_IDLE"; + m_talkSmelling = ""; + m_talkStare = ""; + m_talkSurvived = "!HG_CLEAR"; + m_talkWounded = "!HG_CHECK"; + + m_talkPlayerAsk = ""; + m_talkPlayerGreet = "!HG_ALERT"; + m_talkPlayerIdle = "!HG_CHARGE"; + m_talkPlayerWounded1 = ""; + m_talkPlayerWounded2 = ""; + m_talkPlayerWounded3 = ""; + m_talkUnfollow = ""; + m_talkFollow = ""; + m_talkStopFollow = ""; + + + netname = "Grunt"; + model = "models/hgrunt.mdl"; + base_health = Skill_GetValue("hgrunt_health", 50); + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + m_iAlliance = MAL_ENEMY; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_ichthyosaur.qc b/src/server/monster_ichthyosaur.qc new file mode 100644 index 0000000..eb30588 --- /dev/null +++ b/src/server/monster_ichthyosaur.qc @@ -0,0 +1,137 @@ +/* + * 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 monster_ichthyosaur (0 0.8 0.8) (-32 -32 0) (32 32 64) + +HALF-LIFE (1998) ENTITY + +Ichthyosaur + +*/ + +enum +{ + ICHY_IDLE, + ICHY_SWIM, + ICHY_THRUST, + ICHY_DIE1, + ICHY_DIE2, + ICHY_FLINCH, + ICHY_FLINCH2, + ICHY_DIE3, + ICHY_BITER, + ICHY_BITEL, + ICHY_ATTACK, + ICHY_RIGHT, + ICHY_LEFT, + ICHY_180, + ICHY_HITCAGE, + ICHY_JUMP +}; + +class monster_ichthyosaur:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_ichthyosaur; + + virtual void(void) Pain; + virtual void(void) Death; + virtual void(void) IdleNoise; + virtual void(void) Respawn; +}; + +void +monster_ichthyosaur::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_ichthyosaur.pain"); + SetFrame(ICHY_FLINCH + floor(random(0, 2))); + m_flAnimTime = time + 0.25f; +} + +void +monster_ichthyosaur::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + int r = floor(random(0,3)); + + switch (r) { + case 1: + SetFrame(ICHY_DIE2); + break; + case 2: + SetFrame(ICHY_DIE3); + break; + default: + SetFrame(ICHY_DIE1); + break; + } + + Sound_Play(this, CHAN_VOICE, "monster_ichthyosaur.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_ichthyosaur::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_ichthyosaur.idle"); +} + +void +monster_ichthyosaur::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(ICHY_IDLE); +} + +void +monster_ichthyosaur::monster_ichthyosaur(void) +{ + Sound_Precache("monster_ichthyosaur.alert"); + Sound_Precache("monster_ichthyosaur.attack"); + Sound_Precache("monster_ichthyosaur.die"); + Sound_Precache("monster_ichthyosaur.idle"); + Sound_Precache("monster_ichthyosaur.pain"); + netname = "Ichthyosaur"; + model = "models/icky.mdl"; + base_mins = [-32,-32,0]; + base_maxs = [32,32,64]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_leech.qc b/src/server/monster_leech.qc new file mode 100644 index 0000000..a37e270 --- /dev/null +++ b/src/server/monster_leech.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. + */ + +/*QUAKED monster_leech (0 0.8 0.8) (-6 -6 0) (6 6 6) + +HALF-LIFE (1998) ENTITY + +Leech + +*/ + +enum +{ + LEECH_SWIM, + LEECH_SWIM2, + LEECH_ATTACK, + LEECH_HOVER, + LEECH_LEFT, + LEECH_RIGHT, + LEECH_DIE, + LEECH_DIEEND +}; + +class monster_leech:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_leech; + + virtual void(void) Death; + virtual void(void) DeathEnd; + virtual void(void) Respawn; +}; + +void +monster_leech::DeathEnd(void) +{ + SetFrame(LEECH_DIEEND); +} + +void +monster_leech::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + SetFrame(LEECH_DIE); + think = DeathEnd; + nextthink = time + 1.0f; + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_leech::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(LEECH_SWIM); +} + +void monster_leech::monster_leech(void) +{ + Sound_Precache("monster_leech.alert"); + Sound_Precache("monster_leech.attack"); + netname = "Leech"; + model = "models/leech.mdl"; + base_mins = [-6,-6,0]; + base_maxs = [6,6,6]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_miniturret.qc b/src/server/monster_miniturret.qc new file mode 100644 index 0000000..b952d73 --- /dev/null +++ b/src/server/monster_miniturret.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. + */ + +/*QUAKED monster_miniturret (0 0.8 0.8) (-16 -16 -32) (16 16 32) + +HALF-LIFE (1998) ENTITY + +Automatic Turret (small) + +*/ + +enum +{ + TUR_IDLE, + TUR_FIRE, + TUR_SPIN, + TUR_DEPLOY, + TUR_RETIRE, + TUR_DIE +}; + +class monster_miniturret:CBaseMonster +{ + void(void) monster_miniturret; +}; + +void monster_miniturret::monster_miniturret(void) +{ + netname = "Mini-Turret"; + model = "models/miniturret.mdl"; + base_mins = [-16,-16,-32]; + base_maxs = [16,16,32]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_nihilanth.qc b/src/server/monster_nihilanth.qc new file mode 100644 index 0000000..0e8c620 --- /dev/null +++ b/src/server/monster_nihilanth.qc @@ -0,0 +1,134 @@ +/* + * 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 monster_nihilanth (0 0.8 0.8) (-192 -192 0) (192 192 384) + +HALF-LIFE (1998) ENTITY + +Nihilanth + +*/ + +enum +{ + NIL_IDLE, + NIL_ATTACK, + NIL_ATTACK2, + NIL_THROW, + NIL_BLOCK, + NIL_RECHARGE, + NIL_IDLEOPEN, + NIL_ATTACKOPEN, + NIL_ATTACKOPEN2, + NIL_FLINCH, + NIL_FLINCH2, + NIL_FALL, + NIL_DIE, + NIL_FORWARD, + NIL_BACK, + NIL_UP, + NIL_DOWN, + NIL_RIGHT, + NIL_LEFT, + NIL_WALK2, + NIL_SHOOT +}; + +class monster_nihilanth:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_nihilanth; + + virtual void(void) Death; + virtual void(void) Pain; + virtual void(void) IdleNoise; + virtual void(void) Respawn; +}; + +void +monster_nihilanth::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + + /* timing needs to adjusted as sounds conflict */ + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_nihilanth.idle"); +} + +void +monster_nihilanth::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_nihilanth.pain"); + + SetFrame((random() < 0.5) ? NIL_FLINCH : NIL_FLINCH2); + m_flAnimTime = time + 0.25f; +} + +void +monster_nihilanth::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + SetFrame(NIL_DIE); + Sound_Play(this, CHAN_VOICE, "monster_nihilanth.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_nihilanth::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(NIL_IDLE); +} + +void monster_nihilanth::monster_nihilanth(void) +{ + Sound_Precache("monster_nihilanth.attack"); + Sound_Precache("monster_nihilanth.attackball"); + Sound_Precache("monster_nihilanth.attackballmove"); + Sound_Precache("monster_nihilanth.die"); + Sound_Precache("monster_nihilanth.idle"); + Sound_Precache("monster_nihilanth.pain"); + Sound_Precache("monster_nihilanth.recharge"); + netname = "Nihilanth"; + model = "models/nihilanth.mdl"; + base_health = Skill_GetValue("nihilanth_health", 800); + base_mins = [-192,-192,-32]; + base_maxs = [192,192,384]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_osprey.qc b/src/server/monster_osprey.qc new file mode 100644 index 0000000..cbc635a --- /dev/null +++ b/src/server/monster_osprey.qc @@ -0,0 +1,45 @@ +/* + * 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 monster_osprey (0 0.8 0.8) (-480 -480 -112) (480 480 24) + +HALF-LIFE (1998) ENTITY + +Bell Boeing VV-22 Osprey + +*/ + +class monster_osprey:CBaseMonster +{ + void(void) monster_osprey; + virtual void(void) Respawn; +}; + +void monster_osprey::Respawn(void) +{ + CBaseMonster::Respawn(); + takedamage = DAMAGE_NO; + iBleeds = FALSE; +} + +void monster_osprey::monster_osprey(void) +{ + netname = "Osprey"; + model = "models/osprey.mdl"; + base_mins = [-480,-480,-112]; + base_maxs = [480,480,24]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_rat.qc b/src/server/monster_rat.qc new file mode 100644 index 0000000..57cee12 --- /dev/null +++ b/src/server/monster_rat.qc @@ -0,0 +1,37 @@ +/* + * 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 monster_rat (0 0.8 0.8) (-6 -6 0) (6 6 6) + +HALF-LIFE (1998) ENTITY + +Rat + +*/ + +class monster_rat:CBaseMonster +{ + void(void) monster_rat; +}; + +void monster_rat::monster_rat(void) +{ + netname = "Rat"; + model = "models/bigrat.mdl"; + base_mins = [-6,-6,-0]; + base_maxs = [6,6,6]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_scientist.qc b/src/server/monster_scientist.qc new file mode 100644 index 0000000..25d9ae2 --- /dev/null +++ b/src/server/monster_scientist.qc @@ -0,0 +1,236 @@ +/* + * 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 monster_scientist (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Scientist + +*/ + +enum +{ + SCIA_WALK, + SCIA_WALKSCARED, + SCIA_RUN, + SCIA_RUNSCARED, + SCIA_RUNLOOK, + SCIA_180LEFT, + SCIA_180RIGHT, + SCIA_FLINCH, + SCIA_PAIN, + SCIA_PAINLEFT, + SCIA_PAINRIGHT, + SCIA_PAINLEGLEFT, + SCIA_PAINLEGRIGHT, + SCIA_IDLE1, + SCIA_IDLE2, + SCIA_IDLE3, + SCIA_IDLE4, + SCIA_IDLE5, + SCIA_IDLE6, + SCIA_SCARED_END, + SCIA_SCARED1, + SCIA_SCARED2, + SCIA_SCARED3, + SCIA_SCARED4, + SCIA_PANIC, + SCIA_FEAR1, + SCIA_FEAR2, + SCIA_CRY, + SCIA_SCI1, + SCIA_SCI2, + SCIA_SCI3, + SCIA_DIE_SIMPLE, + SCIA_DIE_FORWARD1, + SCIA_DIE_FORWARD2, + SCIA_DIE_BACKWARD, + SCIA_DIE_HEADSHOT, + SCIA_DIE_GUTSHOT, + SCIA_LYING1, + SCIA_LYING2, + SCIA_DEADSIT, + SCIA_DEADTABLE1, + SCIA_DEADTABLE2, + SCIA_DEADTABLE3 +}; + +class monster_scientist:CBaseNPC +{ + void(void) monster_scientist; + + 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; + virtual void(string, string) SpawnKey; +}; + +int +monster_scientist::AnimIdle(void) +{ + return SCIA_IDLE1; +} + +int +monster_scientist::AnimWalk(void) +{ + return SCIA_WALK; +} + +int +monster_scientist::AnimRun(void) +{ + return SCIA_RUN; +} + +void +monster_scientist::OnPlayerUse(void) +{ + if (spawnflags & MSF_PREDISASTER) { + Sentence("!SC_POK"); + return; + } + + CBaseNPC::OnPlayerUse(); +} + +void +monster_scientist::Pain(void) +{ + WarnAllies(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Speak(this, "monster_scientist.pain"); + + frame = SCIA_FLINCH + floor(random(0, 6)); + m_iFlags |= MONSTER_FEAR; + m_flAnimTime = time + 0.25f; +} + +void +monster_scientist::Death(void) +{ + WarnAllies(); + + if (style != MONSTER_DEAD) { + SetFrame(SCIA_DIE_SIMPLE + floor(random(0, 6))); + Sound_Speak(this, "monster_scientist.die"); + } + + /* now mark our state as 'dead' */ + CBaseNPC::Death(); +} + +void +monster_scientist::Respawn(void) +{ + CBaseNPC::Respawn(); + m_iFlags |= MONSTER_CANFOLLOW; + PlayerUse = OnPlayerUse; +} + +void +monster_scientist::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "body": + SetBody(stoi(strValue) + 1); + break; + default: + CBaseEntity::SpawnKey(strKey, strValue); + } +} + +void +monster_scientist::monster_scientist(void) +{ + Sound_Precache("monster_scientist.die"); + Sound_Precache("monster_scientist.pain"); + + if (spawnflags & MSF_PREDISASTER) { + m_talkAsk = ""; + m_talkPlayerAsk = "!SC_PQUEST"; + m_talkPlayerGreet = "!SC_PHELLO"; + m_talkPlayerIdle = "!SC_PIDLE"; + } else { + m_talkAsk = "!SC_QUESTION"; + m_talkPlayerAsk = "!SC_QUESTION"; + m_talkPlayerGreet = "!SC_HELLO"; + m_talkPlayerIdle = "!SC_PIDLE"; + } + + m_talkAnswer = "!SC_ANSWER"; + m_talkAllyShot = "!SC_PLFEAR"; + m_talkGreet = ""; + m_talkIdle = "!SC_IDLE"; + m_talkHearing = "!SC_HEAR"; + m_talkSmelling = "!SC_SMELL"; + m_talkStare = "!SC_STARE"; + m_talkSurvived = "!SC_WOUND"; + m_talkWounded = "!SC_MORTAL"; + + /* they seem to use predisaster lines regardless of disaster state */ + m_talkPlayerWounded1 = "!SC_CUREA"; + m_talkPlayerWounded2 = "!SC_CUREB"; + m_talkPlayerWounded3 = "!SC_CUREC"; + m_talkUnfollow = "!SC_WAIT"; + m_talkFollow = "!SC_OK"; + m_talkStopFollow = "!SC_STOP"; + m_iBody = -1; + + model = "models/scientist.mdl"; + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + base_health = Skill_GetValue("scientist_health", 20); + + CBaseNPC::CBaseNPC(); + + /* has the body not been overriden, etc. choose a character for us */ + if (m_iBody == -1) { + SetBody((int)floor(random(1,5))); + } + + switch (m_iBody) { + case 1: + m_flPitch = 105; + netname = "Walter"; + break; + case 2: + m_flPitch = 100; + netname = "Einstein"; + break; + case 3: + m_flPitch = 95; + netname = "Luther"; + SetSkin(1); + break; + default: + m_flPitch = 100; + netname = "Slick"; + } +} diff --git a/src/server/monster_scientist_dead.qc b/src/server/monster_scientist_dead.qc new file mode 100644 index 0000000..8e82379 --- /dev/null +++ b/src/server/monster_scientist_dead.qc @@ -0,0 +1,131 @@ +/* + * 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 monster_scientist_dead (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Scientists' corpse + +*/ + +enum +{ + DSCIA_LYING1 = 37, + DSCIA_LYING2, + DSCIA_DEADSIT, + DSCIA_DEADTABLE1, + DSCIA_DEADTABLE2, + DSCIA_DEADTABLE3, + DSCIA_DEADHANG +}; + +class monster_scientist_dead:CBaseMonster +{ + int m_iPose; + void(void) monster_scientist_dead; + + virtual void(void) Hide; + virtual void(void) Respawn; + virtual void(void) Gib; + virtual void(string, string) SpawnKey; +}; + +void +monster_scientist_dead::Gib(void) +{ + takedamage = DAMAGE_NO; + FX_GibHuman(this.origin); + Hide(); +} + +void +monster_scientist_dead::Hide(void) +{ + SetModel(""); + solid = SOLID_NOT; + movetype = MOVETYPE_NONE; +} + +void +monster_scientist_dead::Respawn(void) +{ + v_angle[0] = Math_FixDelta(m_oldAngle[0]); + v_angle[1] = Math_FixDelta(m_oldAngle[1]); + v_angle[2] = Math_FixDelta(m_oldAngle[2]); + + SetOrigin(m_oldOrigin); + angles = v_angle; + solid = SOLID_CORPSE; + movetype = MOVETYPE_NONE; + SetModel(m_oldModel); + setsize(this, VEC_HULL_MIN + [0,0,36], VEC_HULL_MAX + [0,0,36]); + takedamage = DAMAGE_YES; + health = 0; + velocity = [0,0,0]; + iBleeds = TRUE; + SendFlags |= NPC_BODY; + + switch (m_iPose) { + case 1: + SetFrame(DSCIA_LYING2); + break; + case 2: + SetFrame(DSCIA_DEADSIT); + break; + case 3: + SetFrame(DSCIA_DEADHANG); + break; + case 4: + SetFrame(DSCIA_DEADTABLE1); + break; + case 5: + SetFrame(DSCIA_DEADTABLE2); + break; + case 6: + SetFrame(DSCIA_DEADTABLE3); + break; + default: + SetFrame(DSCIA_LYING1); + } + + droptofloor(); +} + +void +monster_scientist_dead::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "pose": + m_iPose = stoi(strValue); + break; + case "body": + SetBody(stoi(strValue) + 1); + break; + case "skin": + SetSkin(stoi(strValue)); + break; + default: + CBaseMonster::SpawnKey(strKey, strValue); + } +} + +void +monster_scientist_dead::monster_scientist_dead(void) +{ + model = "models/scientist.mdl"; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_sentry.qc b/src/server/monster_sentry.qc new file mode 100644 index 0000000..8925386 --- /dev/null +++ b/src/server/monster_sentry.qc @@ -0,0 +1,78 @@ +/* + * 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 monster_sentry (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Sentry Gun + +*/ + +enum +{ + SENT_IDLE, + SENT_FIRE, + SENT_SPIN, + SENT_DEPLOY, + SENT_RETIRE, + SENT_DIE +}; + + +class monster_sentry:CBaseMonster +{ + void(void) monster_sentry; + + virtual void(void) Death; + virtual void(void) Respawn; + +}; + +void +monster_sentry::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + SetFrame(SENT_DIE); + Sound_Play(this, CHAN_VOICE, "monster_sentry.die"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_sentry::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(SENT_IDLE); + iBleeds = FALSE; +} + +void monster_sentry::monster_sentry(void) +{ + Sound_Precache("monster_sentry.alert"); + Sound_Precache("monster_sentry.die"); + Sound_Precache("monster_sentry.idle"); + Sound_Precache("monster_sentry.retract"); + netname = "Sentry"; + model = "models/sentry.mdl"; + base_health = Skill_GetValue("sentry_health", 40); + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_sitting_scientist.qc b/src/server/monster_sitting_scientist.qc new file mode 100644 index 0000000..b4aff43 --- /dev/null +++ b/src/server/monster_sitting_scientist.qc @@ -0,0 +1,142 @@ +/* + * 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 monster_sitting_scientist (0 0.8 0.8) (-14 -14 0) (14 14 36) + +HALF-LIFE (1998) ENTITY + +Sitting scientists + +*/ + +enum +{ + DSCIA_LYING1 = 37, + DSCIA_LYING2, + DSCIA_DEADSIT, + DSCIA_DEADTABLE1, + DSCIA_DEADTABLE2, + DSCIA_DEADTABLE3, + DSCIA_DEADHANG +}; + +class monster_sitting_scientist:CBaseMonster +{ + int m_iPose; + void(void) monster_sitting_scientist; + + virtual void(void) Hide; + virtual void(void) Respawn; + virtual void(void) Death; + virtual void(void) Gib; + virtual void(string, string) SpawnKey; +}; + +void +monster_sitting_scientist::Gib(void) +{ + takedamage = DAMAGE_NO; + FX_GibHuman(this.origin); + Hide(); +} + +void +monster_sitting_scientist::Death(void) +{ + if (health < -50) { + Gib(); + return; + } +} + +void +monster_sitting_scientist::Hide(void) +{ + SetModel(""); + solid = SOLID_NOT; + movetype = MOVETYPE_NONE; +} + +void +monster_sitting_scientist::Respawn(void) +{ + v_angle[0] = Math_FixDelta(m_oldAngle[0]); + v_angle[1] = Math_FixDelta(m_oldAngle[1]); + v_angle[2] = Math_FixDelta(m_oldAngle[2]); + + SetOrigin(m_oldOrigin); + angles = v_angle; + solid = SOLID_BBOX; + movetype = MOVETYPE_NONE; + SetModel(m_oldModel); + setsize(this, [-14,-14,0],[14,14,36]); + takedamage = DAMAGE_YES; + health = 0; + velocity = [0,0,0]; + iBleeds = TRUE; + SendFlags |= NPC_BODY; + frame = 74; + droptofloor(); +} + +void +monster_sitting_scientist::SpawnKey(string strKey, string strValue) +{ + switch (strKey) { + case "pose": + m_iPose = stoi(strValue); + break; + case "body": + SetBody(stoi(strValue) + 1); + break; + case "skin": + SetSkin(stoi(strValue)); + break; + default: + CBaseMonster::SpawnKey(strKey, strValue); + } +} + +void +monster_sitting_scientist::monster_sitting_scientist(void) +{ + model = "models/scientist.mdl"; + CBaseMonster::CBaseMonster(); + + /* has the body not been overriden, etc. choose a character for us */ + if (m_iBody == -1) { + SetBody((int)floor(random(1,5))); + } + + switch (m_iBody) { + case 1: + m_flPitch = 105; + netname = "Walter"; + break; + case 2: + m_flPitch = 100; + netname = "Einstein"; + break; + case 3: + m_flPitch = 95; + netname = "Luther"; + SetSkin(1); + break; + default: + m_flPitch = 100; + netname = "Slick"; + } +} diff --git a/src/server/monster_tentacle.qc b/src/server/monster_tentacle.qc new file mode 100644 index 0000000..0afe7db --- /dev/null +++ b/src/server/monster_tentacle.qc @@ -0,0 +1,132 @@ +/* + * 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 monster_tentacle (0 0.8 0.8) (-32 -32 0) (32 32 64) + +HALF-LIFE (1998) ENTITY + +Tentacle + +*/ + +enum +{ + TE_IDLEPIT, + TE_RISE, + TE_TOFLOOR1, + TE_IDLE, + TE_PISSED, + TE_SMALLRISE, + TE_WAVE, + TE_STRIKE, + TE_TAP, + TE_ROTATE, + TE_REAR, + TE_REARIDLE, + TE_TOLEV1, + TE_IDELLEV1, + TE_FIDGETLEV1, + TE_SNAPLEV1, + TE_STRIKELEV1, + TE_TAPLEV1, + TE_ROTATELEV1, + TE_REARLEV1, + TE_REARIDELLEV1, + TE_TOLEV2, + TE_IDLELEV2, + TE_FIDGETLEV2, + TE_SNAPLEV2, + TE_SWINGLEV2, + TE_TUTLEV2, + TE_STRIKELEV2, + TE_TAPLEV2, + TE_ROTATELEV2, + TE_REARLEV2, + TE_FREAKDIE, + TE_REARIDLE2, + TE_TOLEV3, + TE_IDLELEV3, + TE_FIDGETLEV3, + TE_SIDELEV3, + TE_SWIPELEV3, + TE_STRIKELEV3, + TE_TAPLEV3, + TE_ROTATELEV3, + TE_REARLEV3, + TE_REARIDLELEV3, + TE_DOORLEV1, + TE_ENGINELEV3, + TE_ENGINEIDLE, + TE_ENGINESWAY, + TE_ENGINESWAT, + TE_ENGINEBOB, + TE_ENGINEDEATH, + TE_ENGINEDEATH2, + TE_ENGINEDEATH3, + TE_GRABIDLE, + TE_GRAB +}; + +class monster_tentacle:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_tentacle; + + virtual void(void) IdleNoise; + virtual void(void) Respawn; +}; + +void +monster_tentacle::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + /* timing needs to adjusted as sounds conflict */ + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_tentacle.idle"); +} + +void +monster_tentacle::Respawn(void) +{ + CBaseMonster::Respawn(); + /* not entirely true, takes damage then retreats and reheals */ + takedamage = DAMAGE_NO; + iBleeds = FALSE; + SetFrame(TE_IDLE); +} + +void +monster_tentacle::monster_tentacle(void) +{ + Sound_Precache("monster_tentacle.alert"); + Sound_Precache("monster_tentacle.attack"); + Sound_Precache("monster_tentacle.die"); + Sound_Precache("monster_tentacle.idle"); + netname = "Tentacle"; + model = "models/tentacle2.mdl"; + base_mins = [-32,-32,0]; + base_maxs = [32,32,64]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_turret.qc b/src/server/monster_turret.qc new file mode 100644 index 0000000..026706a --- /dev/null +++ b/src/server/monster_turret.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. + */ + +/*QUAKED monster_turret (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Automatic Turret (large) + +*/ + +enum +{ + TUR_IDLE, + TUR_FIRE, + TUR_SPIN, + TUR_DEPLOY, + TUR_RETIRE, + TUR_DIE +}; + +class monster_turret:CBaseMonster +{ + void(void) monster_turret; +}; + +void monster_turret::monster_turret(void) +{ + netname = "Turret"; + model = "models/turret.mdl"; + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/monster_zombie.qc b/src/server/monster_zombie.qc new file mode 100644 index 0000000..9806531 --- /dev/null +++ b/src/server/monster_zombie.qc @@ -0,0 +1,222 @@ +/* + * 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 monster_zombie (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Zombie + +*/ + +enum +{ + ZO_IDLE, + ZO_TURNLEFT, + ZO_TURNRIGHT, + ZO_FLINCHSM, + ZO_FLINCH, + ZO_FLINCHBIG, + ZO_RISE, + ZO_FALLING, + ZO_ATTACK1, + ZO_ATTACK2, + ZO_WALK, + ZO_FLINCHLA, + ZO_FLINCHRA, + ZO_FLINCHLEFT, + ZO_FLINCHRIGHT, + ZO_DIEHS, + ZO_DIEHS2, + ZO_DIE, + ZO_DIE2, + ZO_DIE3, + ZO_PAUSE, + ZO_WALLBUST, + ZO_WALLKICK, + ZO_WINDOWBUST, + ZO_SODA, + ZO_SLIDEIDLE, + ZO_SLIDE, + ZO_VENTIDLE, + ZO_VENT, + ZO_DEADIDLE, + ZO_DEAD, + ZO_FREAKDIE, + ZO_FREAK, + ZO_EATTABLE, + ZO_EAT, + ZO_EATSTAND, + ZO_DOORIP, + ZO_PULLSCI, + ZO_EAT2, + ZO_EAT2STAND, + ZO_VENT2IDLE, + ZO_VENT2, + ZO_HAUL, + ZO_RISESNACK +}; + +class monster_zombie:CBaseMonster +{ + float m_flIdleTime; + + void(void) monster_zombie; + + virtual void(void) Pain; + virtual void(void) Death; + virtual void(void) IdleNoise; + virtual void(void) Respawn; + + virtual int(void) AnimIdle; + virtual int(void) AnimWalk; + virtual int(void) AnimRun; + + virtual int(void) AttackMelee; + virtual void(void) AttackFlail; +}; + +int +monster_zombie::AnimIdle(void) +{ + return ZO_IDLE; +} + +int +monster_zombie::AnimWalk(void) +{ + return ZO_WALK; +} + +int +monster_zombie::AnimRun(void) +{ + return ZO_WALK; +} + +int +monster_zombie::AttackMelee(void) +{ + /* visual */ + if (random() < 0.5) + AnimPlay(ZO_ATTACK1); + else + AnimPlay(ZO_ATTACK2); + + m_flAttackThink = m_flAnimTime; + Sound_Play(this, CHAN_VOICE, "monster_zombie.attack"); + + /* functional */ + think = AttackFlail; + nextthink = 0.25f; + return TRUE; +} + +void +monster_zombie::AttackFlail(void) +{ + traceline(origin, m_eEnemy.origin, FALSE, this); + + if (trace_fraction >= 1.0 || trace_ent.takedamage != DAMAGE_YES) { + Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackmiss"); + return; + } + + Damage_Apply(trace_ent, this, 25, 0, 0); + Sound_Play(this, CHAN_WEAPON, "monster_zombie.attackhit"); +} + +void +monster_zombie::Pain(void) +{ + CBaseMonster::Pain(); + + if (m_flAnimTime > time) { + return; + } + + if (random() < 0.25f) { + return; + } + + Sound_Play(this, CHAN_VOICE, "monster_zombie.pain"); + SetFrame(ZO_FLINCH + floor(random(0, 2))); + m_flAnimTime = time + 0.25f; +} + +void +monster_zombie::Death(void) +{ + /* if we're already dead (corpse) don't change animations */ + if (style != MONSTER_DEAD) { + /* headshots == different animation */ + if (g_dmg_iHitBody == BODY_HEAD) { + if (random() < 0.5) { + SetFrame(ZO_DIEHS); + } else { + SetFrame(ZO_DIEHS2); + } + } else { + SetFrame(ZO_DIE + floor(random(0, 3))); + } + + Sound_Play(this, CHAN_VOICE, "monster_zombie.pain"); + } + + /* set the functional differences */ + CBaseMonster::Death(); +} + +void +monster_zombie::IdleNoise(void) +{ + /* don't make noise if we're dead (corpse) */ + if (style == MONSTER_DEAD) { + return; + } + + if (m_flIdleTime > time) { + return; + } + m_flIdleTime = time + random(2,10); + + Sound_Play(this, CHAN_VOICE, "monster_zombie.idle"); +} + +void +monster_zombie::Respawn(void) +{ + CBaseMonster::Respawn(); + SetFrame(ZO_IDLE); +} + +void +monster_zombie::monster_zombie(void) +{ + Sound_Precache("monster_zombie.alert"); + Sound_Precache("monster_zombie.attack"); + Sound_Precache("monster_zombie.attackhit"); + Sound_Precache("monster_zombie.attackmiss"); + Sound_Precache("monster_zombie.idle"); + Sound_Precache("monster_zombie.pain"); + netname = "Zombie"; + model = "models/zombie.mdl"; + base_health = Skill_GetValue("zombie_health", 50); + base_mins = [-16,-16,0]; + base_maxs = [16,16,72]; + m_iAlliance = MAL_ALIEN; + CBaseMonster::CBaseMonster(); +} diff --git a/src/server/player.qc b/src/server/player.qc new file mode 100644 index 0000000..2b8b170 --- /dev/null +++ b/src/server/player.qc @@ -0,0 +1,96 @@ +/* + * 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. + */ + +/* +==================== +UseWorkaround +==================== +*/ +void UseWorkaround(entity eTarget) +{ + eActivator = self; + entity eOldSelf = self; + self = eTarget; + self.PlayerUse(); + self = eOldSelf; +} + +/* +==================== +Player_UseDown +==================== +*/ +void Player_UseDown(void) +{ + vector vecSrc; + + if (self.health <= 0) { + return; + } else if (!(self.flags & FL_USE_RELEASED)) { + return; + } + + makevectors(self.v_angle); + vecSrc = self.origin + self.view_ofs; + + self.hitcontentsmaski = CONTENTBITS_POINTSOLID; + traceline(vecSrc, vecSrc + (v_forward * 64), MOVE_HITMODEL, 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..a3d7cb8 --- /dev/null +++ b/src/server/progs.src @@ -0,0 +1,89 @@ +#pragma target fte +#pragma progs_dat "../../progs.dat" + +#define QWSSQC +#define SERVER +#define VALVE +#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 +../shared/include.src + +defs.h + +monster_apache.qc +monster_alien_controller.qc +monster_alien_grunt.qc +monster_alien_slave.qc +monster_barnacle.qc +monster_barney.qc +monster_barney_dead.qc +monster_bigmomma.qc +monster_bloater.qc +monster_bullchicken.qc +monster_cockroach.qc +monster_flyer_flock.qc +monster_gargantua.qc +monster_gman.qc +monster_headcrab.qc +monster_babycrab.qc +monster_hevsuit_dead.qc +monster_houndeye.qc +monster_human_grunt.qc +monster_hgrunt_dead.qc +monster_human_assassin.qc +monster_ichthyosaur.qc +monster_leech.qc +monster_miniturret.qc +monster_nihilanth.qc +monster_osprey.qc +monster_rat.qc +monster_scientist_dead.qc +monster_sitting_scientist.qc +monster_scientist.qc +monster_sentry.qc +monster_tentacle.qc +monster_turret.qc +monster_zombie.qc + +player.qc +spectator.qc +items.qc +item_longjump.qc +item_suit.qc +item_healthkit.qc +item_battery.qc +item_weaponbox.qc +world_items.qc +xen_spore_small.qc +xen_spore_medium.qc +xen_spore_large.qc +xen_hair.qc +xen_plantlight.qc +ammo.qc + +../../../src/botlib/include.src + +gamerules.qc +gamerules_singleplayer.qc +gamerules_multiplayer.qc +client.qc +server.qc +damage.qc +rules.qc +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/rules.qc b/src/server/rules.qc new file mode 100644 index 0000000..e6b76f0 --- /dev/null +++ b/src/server/rules.qc @@ -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. + */ + +int Rules_IsTeamPlay(void) +{ + return cvar("teamplay"); +} diff --git a/src/server/server.qc b/src/server/server.qc new file mode 100644 index 0000000..d923dc0 --- /dev/null +++ b/src/server/server.qc @@ -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. + */ + +void +Game_InitRules(void) +{ + if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) { + g_grMode = spawn(HLSingleplayerRules); + } else { + g_grMode = spawn(HLMultiplayerRules); + } +} + +void +Game_Worldspawn(void) +{ + Sound_Precache("ammo.pickup"); + Sound_Precache("ammo.respawn"); + Sound_Precache("player.die"); + Sound_Precache("player.fall"); + Sound_Precache("player.lightfall"); + + precache_model("models/player.mdl"); + precache_model("models/w_weaponbox.mdl"); + Weapons_Init(); + Player_Precache(); +} diff --git a/src/server/spawn.qc b/src/server/spawn.qc new file mode 100644 index 0000000..b60cc9e --- /dev/null +++ b/src/server/spawn.qc @@ -0,0 +1,41 @@ +/* + * 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 info_player_start(void) +{ + self.solid = SOLID_TRIGGER; + setsize(self, VEC_HULL_MIN, VEC_HULL_MAX); + self.botinfo = BOTINFO_SPAWNPOINT; +} + +void info_player_deathmatch(void) +{ + self.solid = SOLID_TRIGGER; + setsize(self, VEC_HULL_MIN, VEC_HULL_MAX); + self.botinfo = BOTINFO_SPAWNPOINT; +} + +void info_player_team1(void) +{ + self.classname = "info_player_deathmatch"; + self.botinfo = BOTINFO_SPAWNPOINT; +} + +void info_player_team2(void) +{ + self.classname = "info_player_deathmatch"; + self.botinfo = BOTINFO_SPAWNPOINT; +} diff --git a/src/server/spectator.qc b/src/server/spectator.qc new file mode 100644 index 0000000..01ce53f --- /dev/null +++ b/src/server/spectator.qc @@ -0,0 +1,28 @@ +/* + * 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_SpectatorThink(void) +{ + +} +void Game_SpectatorConnect(void) +{ + +} +void Game_SpectatorDisconnect(void) +{ + +} diff --git a/src/server/world_items.qc b/src/server/world_items.qc new file mode 100644 index 0000000..9efa058 --- /dev/null +++ b/src/server/world_items.qc @@ -0,0 +1,43 @@ +/* + * 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. + */ + +/* This is one of those leftovers from trying to get a game out in time */ +class world_items:CBaseTrigger +{ + void(void) world_items; +}; + +void world_items::world_items(void) +{ + int nfields = tokenize(__fullspawndata); + for (int i = 1; i < (nfields - 1); i += 2) { + switch (argv(i)) { + case "type": + float type = stof(argv(i+1)); + switch (type) { + case 44: + spawnfunc_item_battery(); + break; + case 45: + spawnfunc_item_suit(); + break; + default: + } + default: + break; + } + } +} diff --git a/src/server/xen_hair.qc b/src/server/xen_hair.qc new file mode 100644 index 0000000..eb1afe6 --- /dev/null +++ b/src/server/xen_hair.qc @@ -0,0 +1,37 @@ +/* + * 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 xen_hair (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Xen Hair + +*/ +class xen_hair:CBaseEntity +{ + void(void) xen_hair; +}; + +void xen_hair::xen_hair(void) +{ + CBaseEntity::CBaseEntity(); + precache_model("models/hair.mdl"); + solid = SOLID_SLIDEBOX; + movetype = MOVETYPE_WALK; + SetModel("models/hair.mdl"); + SetOrigin(origin); +} diff --git a/src/server/xen_plantlight.qc b/src/server/xen_plantlight.qc new file mode 100644 index 0000000..17a0118 --- /dev/null +++ b/src/server/xen_plantlight.qc @@ -0,0 +1,37 @@ +/* + * 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 xen_plantlight (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Xen Plant Light + +*/ +class xen_plantlight:CBaseEntity +{ + void(void) xen_plantlight; +}; + +void xen_plantlight::xen_plantlight(void) +{ + CBaseEntity::CBaseEntity(); + precache_model("models/light.mdl"); + solid = SOLID_SLIDEBOX; + movetype = MOVETYPE_WALK; + SetModel("models/light.mdl"); + SetOrigin(origin); +} diff --git a/src/server/xen_spore_large.qc b/src/server/xen_spore_large.qc new file mode 100644 index 0000000..be5bdec --- /dev/null +++ b/src/server/xen_spore_large.qc @@ -0,0 +1,37 @@ +/* + * 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 xen_spore_large (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Large Xen Spore + +*/ +class xen_spore_large:CBaseEntity +{ + void(void) xen_spore_large; +}; + +void xen_spore_large::xen_spore_large(void) +{ + CBaseEntity::CBaseEntity(); + precache_model("models/fungus(large).mdl"); + solid = SOLID_SLIDEBOX; + movetype = MOVETYPE_WALK; + SetModel("models/fungus(large).mdl"); + SetOrigin(origin); +} diff --git a/src/server/xen_spore_medium.qc b/src/server/xen_spore_medium.qc new file mode 100644 index 0000000..41ab34a --- /dev/null +++ b/src/server/xen_spore_medium.qc @@ -0,0 +1,37 @@ +/* + * 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 xen_spore_medium (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Medium Xen Spore + +*/ +class xen_spore_medium:CBaseEntity +{ + void(void) xen_spore_medium; +}; + +void xen_spore_medium::xen_spore_medium(void) +{ + CBaseEntity::CBaseEntity(); + precache_model("models/fungus.mdl"); + solid = SOLID_SLIDEBOX; + movetype = MOVETYPE_WALK; + SetModel("models/fungus.mdl"); + SetOrigin(origin); +} diff --git a/src/server/xen_spore_small.qc b/src/server/xen_spore_small.qc new file mode 100644 index 0000000..3698282 --- /dev/null +++ b/src/server/xen_spore_small.qc @@ -0,0 +1,37 @@ +/* + * 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 xen_spore_small (0 0.8 0.8) (-16 -16 0) (16 16 72) + +HALF-LIFE (1998) ENTITY + +Small Xen Spore + +*/ +class xen_spore_small:CBaseEntity +{ + void(void) xen_spore_small; +}; + +void xen_spore_small::xen_spore_small(void) +{ + CBaseEntity::CBaseEntity(); + precache_model("models/fungus(small).mdl"); + solid = SOLID_SLIDEBOX; + movetype = MOVETYPE_WALK; + SetModel("models/fungus(small).mdl"); + SetOrigin(origin); +} diff --git a/src/shared/animations.h b/src/shared/animations.h new file mode 100644 index 0000000..d7b9812 --- /dev/null +++ b/src/shared/animations.h @@ -0,0 +1,95 @@ +/* + * 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_LOOKIDLE, + ANIM_IDLE, + ANIM_DEEPIDLE, + ANIM_RUN2, + ANIM_WALK2HANDED, + ANIM_2HANDSHOT, + ANIM_CRAWL, + ANIM_CROUCHIDLE, + ANIM_JUMP, + ANIM_LONGJUMP, + ANIM_SWIM, + ANIM_TREADWATER, + ANIM_RUN, + ANIM_WALK, + ANIM_AIM2, + ANIM_SHOOT2, + ANIM_AIM1, + ANIM_SHOOT1, + ANIM_DIESIMPLE, + ANIM_DIEBACKWARDS1, + ANIM_DIEBACKWARDS2, + ANIM_DIEFORWARD, + ANIM_DIEHEADSHOT, + ANIM_DIESPIN, + ANIM_DIEGUTSHOT, + ANIM_AIMCROWBAR, + ANIM_SHOOTCROWBAR, + ANIM_CR_AIMCROWBAR, + ANIM_CR_SHOOTCROWBAR, + ANIM_AIMTRIPMINE, + ANIM_SHOOTTRIPMINE, + ANIM_CR_AIMTRIPMINE, + ANIM_CR_SHOOTTRIPMINE, + ANIM_AIM1HAND, + ANIM_SHOOT1HAND, + ANIM_CR_AIM1HAND, + ANIM_CR_SHOOT1HAND, + ANIM_AIMPYTHON, + ANIM_SHOOTPYTHON, + ANIM_CR_AIMPYTHON, + ANIM_CR_SHOOTPYTHON, + ANIM_AIMSHOTGUN, + ANIM_SHOOTSHOTGUN, + ANIM_CR_AIMSHOTGUN, + ANIM_CR_SHOOTSHOTGUN, + ANIM_AIMGAUSS, + ANIM_SHOOTGAUSS, + ANIM_CR_AIMGAUSS, + ANIM_CR_SHOOTGAUSS, + ANIM_AIMMP5, + ANIM_SHOOTMP5, + ANIM_CR_AIMMP5, + ANIM_CR_SHOOTMP5, + ANIM_AIMRPG, + ANIM_SHOOTRPG, + ANIM_CR_AIMRPG, + ANIM_CR_SHOOTRPG, + ANIM_AIMEGON, + ANIM_SHOOTEGON, + ANIM_CR_AIMEGON, + ANIM_CR_SHOOTEGON, + ANIM_AIMSQUEAK, + ANIM_SHOOTSQUEAK, + ANIM_CR_AIMSQUEAK, + ANIM_CR_SHOOTSQUEAK, + ANIM_AIMHIVE, + ANIM_SHOOTHIVE, + ANIM_CR_AIMHIVE, + ANIM_CR_SHOOTHIVE, + ANIM_AIMBOW, + ANIM_SHOOTBOW, + ANIM_CR_AIMBOW, + ANIM_CR_SHOOTBOW +}; + +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..59dd1c5 --- /dev/null +++ b/src/shared/animations.qc @@ -0,0 +1,178 @@ +/* + * 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 baselerpfrac; +.float lerpfrac; +.float frame_time; +.float frame_old; +.float fWasCrouching; +.float frame2time; +.float frame2; +.float baseframe2time; +.float baseframe1time; +.float baseframe2; + +// For lerping, sigh +.float frame_last; +.float baseframe_last; +.float subblendfrac; +.float subblend2frac; + +void Animation_Print(string sWow) { +#ifdef CLIENT + print(sprintf("[DEBUG] %s", sWow)); +#else + bprint(PRINT_HIGH, sprintf("SSQC: %s", sWow) ); +#endif +} + +var int autocvar_bone_spinebone = 0; +var int autocvar_bone_baseframe = 0; +var int autocvar_bone_frame = 0; +/* +================= +Animation_PlayerUpdate + +Called every frame to update the animation sequences +depending on what the player is doing +================= +*/ +void +Animation_PlayerUpdate(void) +{ + self.basebone = gettagindex(self, "Bip01 Spine1"); + + // TODO: Make this faster + if (self.frame_time < time) { + player pl = (player)self; + self.frame = Weapons_GetAim(pl.activeweapon); + self.frame_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.baseframe == ANIM_JUMP)) { + self.baseframe = ANIM_JUMP; + } else if (vlen(self.velocity) == 0) { + if (self.flags & FL_CROUCHING) { + self.baseframe = ANIM_CROUCHIDLE; + } else { + self.baseframe = ANIM_IDLE; + } + } else if (vlen(self.velocity) < 150) { + if (self.flags & FL_CROUCHING) { + self.baseframe = ANIM_CRAWL; + } else { + self.baseframe = ANIM_WALK; + } + } else if (vlen(self.velocity) > 150) { + if (self.flags & FL_CROUCHING) { + self.baseframe = ANIM_CRAWL; + } else { + self.baseframe = 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; + } + + self.subblend2frac = self.angles[0]; + + self.angles[0] = self.angles[2] = 0; + + if (!(self.flags & FL_ONGROUND)) { + /*self.frame = ANIM_JUMP;*/ + } + + // Force the code above to update if we switched positions + if (self.fWasCrouching != (self.flags & FL_CROUCHING)) { + self.frame_old = 0; + self.frame_time = 0; + self.fWasCrouching = (self.flags & FL_CROUCHING); + } + +#ifndef CLIENT + // On the CSQC it's done in Player.c + self.subblendfrac = + self.subblend2frac = self.v_angle[0] / 90; +#endif +} + +/* +================= +Animation_PlayerTop + +Changes the animation sequence for the upper body part +================= +*/ +void +Animation_PlayerTop(float fFrame) +{ +#ifndef CLIENT + self.frame = fFrame; + self.frame_old = fFrame; +#endif +} + +void +Animation_PlayerTopTemp(float fFrame, float fTime) +{ +#ifndef CLIENT + self.frame = fFrame; + self.frame_time = time + fTime; + self.SendFlags |= PLAYER_FRAME; +#endif +} diff --git a/src/shared/entities.h b/src/shared/entities.h new file mode 100644 index 0000000..9d2beb5 --- /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_TRIPMINE = ENT_SEPARATOR +}; diff --git a/src/shared/flags.h b/src/shared/flags.h new file mode 100644 index 0000000..87c3e9a --- /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_UNUSED3 (1<<2) +#define GF_UNUSED4 (1<<3) +#define GF_UNUSED5 (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_blood.qc b/src/shared/fx_blood.qc new file mode 100644 index 0000000..fe0a149 --- /dev/null +++ b/src/shared/fx_blood.qc @@ -0,0 +1,105 @@ +/* + * 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 float PARTICLE_BLOOD; +var int DECAL_BLOOD; + +void +FX_Blood_Init(void) +{ + precache_model("sprites/bloodspray.spr"); + precache_model("sprites/blood.spr"); + PARTICLE_BLOOD = particleeffectnum("part_blood"); + DECAL_BLOOD = particleeffectnum("decal_blood.effect"); +} +#endif + +void +FX_Blood(vector pos, vector color) +{ +#ifdef SERVER + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_BLOOD); + WriteCoord(MSG_MULTICAST, pos[0]); + WriteCoord(MSG_MULTICAST, pos[1]); + WriteCoord(MSG_MULTICAST, pos[2]); + WriteByte(MSG_MULTICAST, color[0] * 255); + WriteByte(MSG_MULTICAST, color[1] * 255); + WriteByte(MSG_MULTICAST, color[2] * 255); + msg_entity = self; + multicast(pos, MULTICAST_PVS); +#else + static void Blood_Touch(void) + { + if (serverkeyfloat("*bspversion") == BSPVER_HL) + Decals_Place(self.origin, sprintf("{blood%d", floor(random(1,9)))); + else { + decal_pickwall(self, self.origin); + pointparticles(DECAL_BLOOD, g_tracedDecal.endpos, g_tracedDecal.normal, 1); + } + } + + if (cvar("violence_hblood") <= 0) { + return; + } + + env_sprite eBlood = spawn(env_sprite); + setorigin(eBlood, pos); + setmodel(eBlood, "sprites/bloodspray.spr"); + + eBlood.drawmask = MASK_ENGINE; + eBlood.maxframe = modelframecount(eBlood.modelindex); + eBlood.loops = 0; + eBlood.scale = 1.0f; + +#ifdef GS_RENDERFX + eBlood.m_vecRenderColor = color; +#else + eBlood.colormod = color; +#endif + + eBlood.framerate = 20; + eBlood.nextthink = time + 0.05f; + + for (int i = 0; i < 3; i++) { + env_sprite ePart = spawn(env_sprite); + setorigin(ePart, pos); + setmodel(ePart, "sprites/blood.spr"); + ePart.movetype = MOVETYPE_BOUNCE; + ePart.gravity = 0.5f; + ePart.scale = 0.5f; + ePart.drawmask = MASK_ENGINE; + ePart.maxframe = modelframecount(ePart.modelindex); + ePart.loops = 0; + +#ifdef GS_RENDERFX + ePart.m_vecRenderColor = color; +#else + ePart.colormod = color; +#endif + ePart.framerate = 15; + ePart.nextthink = time + 0.1f; + ePart.velocity = randomvec() * 64; + ePart.touch = Blood_Touch; + ePart.solid = SOLID_BBOX; + /* ignore player physics */ + ePart.dimension_solid = 1; + ePart.dimension_hit = 1; + setsize(ePart, [0,0,0], [0,0,0]); + } +#endif +} diff --git a/src/shared/fx_breakmodel.qc b/src/shared/fx_breakmodel.qc new file mode 100644 index 0000000..4f80f19 --- /dev/null +++ b/src/shared/fx_breakmodel.qc @@ -0,0 +1,164 @@ +/* + * 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 +void +FX_BreakModel_Init(void) +{ + precache_model("models/glassgibs.mdl"); + precache_model("models/woodgibs.mdl"); + precache_model("models/metalplategibs.mdl"); + precache_model("models/fleshgibs.mdl"); + precache_model("models/ceilinggibs.mdl"); + precache_model("models/computergibs.mdl"); + precache_model("models/rockgibs.mdl"); + precache_model("models/cindergibs.mdl"); + precache_sound("debris/bustglass1.wav"); + precache_sound("debris/bustglass2.wav"); + precache_sound("debris/bustglass3.wav"); + precache_sound("debris/bustcrate1.wav"); + precache_sound("debris/bustcrate2.wav"); + precache_sound("debris/bustcrate3.wav"); + precache_sound("debris/bustmetal1.wav"); + precache_sound("debris/bustmetal2.wav"); + precache_sound("debris/bustflesh1.wav"); + precache_sound("debris/bustflesh2.wav"); + precache_sound("debris/bustconcrete1.wav"); + precache_sound("debris/bustconcrete2.wav"); + precache_sound("debris/bustceiling.wav"); +} +#endif + +void +FX_BreakModel(int count, vector vMins, vector vMaxs, vector vVel, float fStyle) +{ +#ifdef SERVER + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_MODELGIB); + WriteCoord(MSG_MULTICAST, vMins[0]); + WriteCoord(MSG_MULTICAST, vMins[1]); + WriteCoord(MSG_MULTICAST, vMins[2]); + WriteCoord(MSG_MULTICAST, vMaxs[0]); + WriteCoord(MSG_MULTICAST, vMaxs[1]); + WriteCoord(MSG_MULTICAST, vMaxs[2]); + WriteByte(MSG_MULTICAST, fStyle); + WriteByte(MSG_MULTICAST, count); + + msg_entity = self; + + vector vWorldPos; + vWorldPos[0] = vMins[0] + (0.5 * (vMaxs[0] - vMins[0])); + vWorldPos[1] = vMins[1] + (0.5 * (vMaxs[1] - vMins[1])); + vWorldPos[2] = vMins[2] + (0.5 * (vMaxs[2] - vMins[2])); + multicast(vWorldPos, MULTICAST_PVS); +#else + static void FX_BreakModel_Remove(void) { remove(self) ; } + + float fModelCount = 0; + vector vecPos; + string sModel = ""; + + switch (fStyle) { + case GSMATERIAL_GLASS: + case GSMATERIAL_GLASS_UNBREAKABLE: + sModel = "models/glassgibs.mdl"; + fModelCount = 8; + break; + case GSMATERIAL_WOOD: + sModel = "models/woodgibs.mdl"; + fModelCount = 3; + break; + case GSMATERIAL_METAL: + sModel = "models/metalplategibs.mdl"; + fModelCount = 13; + break; + case GSMATERIAL_FLESH: + sModel = "models/fleshgibs.mdl"; + fModelCount = 4; + break; + case GSMATERIAL_TILE: + sModel = "models/ceilinggibs.mdl"; + fModelCount = 4; + break; + case GSMATERIAL_COMPUTER: + sModel = "models/computergibs.mdl"; + fModelCount = 15; + break; + case GSMATERIAL_ROCK: + sModel = "models/rockgibs.mdl"; + fModelCount = 3; + break; + default: + case GSMATERIAL_CINDER: + sModel = "models/cindergibs.mdl"; + fModelCount = 9; + break; + } + + vector vWorldPos; + vWorldPos = vMins + (0.5 * (vMaxs - vMins)); + + switch (fStyle) { + case GSMATERIAL_GLASS: + pointsound(vWorldPos, sprintf("debris/bustglass%d.wav", random(1, 4)), 1.0f, ATTN_NORM); + break; + case GSMATERIAL_WOOD: + pointsound(vWorldPos, sprintf("debris/bustcrate%d.wav", random(1, 4)), 1.0f, ATTN_NORM); + break; + case GSMATERIAL_METAL: + case GSMATERIAL_COMPUTER: + pointsound(vWorldPos, sprintf("debris/bustmetal%d.wav", random(1, 3)), 1.0f, ATTN_NORM); + break; + case GSMATERIAL_FLESH: + pointsound(vWorldPos, sprintf("debris/bustflesh%d.wav", random(1, 3)), 1.0f, ATTN_NORM); + break; + case GSMATERIAL_CINDER: + case GSMATERIAL_ROCK: + pointsound(vWorldPos, sprintf("debris/bustconcrete%d.wav", random(1, 4)), 1.0f, ATTN_NORM); + break; + case GSMATERIAL_TILE: + pointsound(vWorldPos, "debris/bustceiling.wav", 1.0f, ATTN_NORM); + break; + } + + for (int i = 0; i < count; i++) { + entity eGib = spawn(); + eGib.classname = "gib"; + + vecPos[0] = vMins[0] + (random() * (vMaxs[0] - vMins[0])); + vecPos[1] = vMins[1] + (random() * (vMaxs[1] - vMins[1])); + vecPos[2] = vMins[2] + (random() * (vMaxs[2] - vMins[2])); + + setorigin(eGib, vecPos); + setmodel(eGib, sModel); + setcustomskin(eGib, "", sprintf("geomset 0 %f\n", random(1, fModelCount + 1))); + eGib.movetype = MOVETYPE_BOUNCE; + eGib.solid = SOLID_NOT; + + eGib.avelocity[0] = random()*600; + eGib.avelocity[1] = random()*600; + eGib.avelocity[2] = random()*600; + eGib.think = FX_BreakModel_Remove; + eGib.nextthink = time + 10; + + if ((fStyle == GSMATERIAL_GLASS) || (fStyle == GSMATERIAL_GLASS_UNBREAKABLE)) { + eGib.alpha = 0.5f; + } + + eGib.drawmask = MASK_ENGINE; + } +#endif +} diff --git a/src/shared/fx_explosion.qc b/src/shared/fx_explosion.qc new file mode 100755 index 0000000..17df90f --- /dev/null +++ b/src/shared/fx_explosion.qc @@ -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. + */ + +#ifdef CLIENT +var int FX_EXPLOSION_MAIN; +var int FX_EXPLOSION_BS; + +void +FX_Explosion_Init(void) +{ + Sound_Precache("fx.explosion"); + precache_model("sprites/fexplo.spr"); + FX_EXPLOSION_MAIN = particleeffectnum("fx_explosion.main"); + FX_EXPLOSION_BS = particleeffectnum("fx_explosion.blacksmoke"); +} +#endif + +void +FX_Explosion(vector vecPos) +{ +#ifdef SERVER + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_EXPLOSION); + WriteCoord(MSG_MULTICAST, vecPos[0]); + WriteCoord(MSG_MULTICAST, vecPos[1]); + WriteCoord(MSG_MULTICAST, vecPos[2]); + msg_entity = self; + multicast(vecPos, MULTICAST_PVS); +#else + Decals_Place(vecPos, sprintf("{scorch%d", floor(random(1,4)))); + vecPos[2] += 48; + env_sprite eExplosion = spawn(env_sprite); + setorigin(eExplosion, vecPos); + setmodel(eExplosion, "sprites/fexplo.spr"); + Sound_Play(eExplosion, CHAN_WEAPON, "fx.explosion"); + + //eExplosion.think = FX_Explosion_Animate; + eExplosion.effects = EF_ADDITIVE; + eExplosion.drawmask = MASK_ENGINE; + eExplosion.maxframe = modelframecount(eExplosion.modelindex); + eExplosion.loops = 0; + eExplosion.framerate = 20; + eExplosion.nextthink = time + 0.05f; + + pointparticles(FX_EXPLOSION_MAIN, vecPos, [0,0,0], 1); + pointparticles(FX_EXPLOSION_BS, vecPos, [0,0,0], 1); +#endif +} + diff --git a/src/shared/fx_gibhuman.qc b/src/shared/fx_gibhuman.qc new file mode 100644 index 0000000..25bd919 --- /dev/null +++ b/src/shared/fx_gibhuman.qc @@ -0,0 +1,88 @@ +/* + * 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 +string g_hgibs[] = { + "models/gib_b_bone.mdl", + "models/gib_legbone.mdl", + "models/gib_lung.mdl", + "models/gib_skull.mdl", + "models/gib_b_gib.mdl" +}; + +void +FX_GibHuman_Init(void) +{ + precache_model("models/gib_b_bone.mdl"); + precache_model("models/gib_legbone.mdl"); + precache_model("models/gib_lung.mdl"); + precache_model("models/gib_skull.mdl"); + precache_model("models/gib_b_gib.mdl"); + precache_sound("common/bodysplat.wav"); +} +#endif + +void +FX_GibHuman(vector pos) +{ +#ifdef SERVER + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_GIBHUMAN); + WriteCoord(MSG_MULTICAST, pos[0]); + WriteCoord(MSG_MULTICAST, pos[1]); + WriteCoord(MSG_MULTICAST, pos[2]); + msg_entity = __NULL__; + multicast(pos, MULTICAST_PVS); +#else + static void Gib_Remove(void) { + remove(self); + } + static void Gib_Touch(void) + { + if (serverkeyfloat("*bspversion") == BSPVER_HL) + Decals_Place(self.origin, sprintf("{blood%d", floor(random(1,9)))); + else { + decal_pickwall(self, self.origin); + pointparticles(DECAL_BLOOD, g_tracedDecal.endpos, g_tracedDecal.normal, 1); + } + } + + if (cvar("violence_hgibs") <= 0) { + return; + } + + for (int i = 0; i < 5; i++) { + vector vel; + vel[0] = random(-128,128); + vel[1] = random(-128,128); + vel[2] = (300 + random() * 64); + + entity gibb = spawn(); + setmodel(gibb, g_hgibs[i]); + setorigin(gibb, pos); + gibb.movetype = MOVETYPE_BOUNCE; + gibb.solid = SOLID_BBOX; + setsize(gibb, [0,0,0], [0,0,0]); + gibb.velocity = vel; + gibb.avelocity = vectoangles(gibb.velocity); + gibb.think = Gib_Remove; + gibb.touch = Gib_Touch; + gibb.nextthink = time + 5.0f; + gibb.drawmask = MASK_ENGINE; + } + pointsound(pos, "common/bodysplat.wav", 1, ATTN_NORM); +#endif +} diff --git a/src/shared/fx_impact.qc b/src/shared/fx_impact.qc new file mode 100644 index 0000000..7ff012b --- /dev/null +++ b/src/shared/fx_impact.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. + */ + +#ifdef CLIENT +var int FX_IMPACT_BLACKBITS; +var int FX_IMPACT_SMOKE_BROWN; +var int FX_IMPACT_SMOKE_GREY; +var int FX_IMPACT_SPARK; + +var int DECAL_IMPACT_DEFAULT; +var int DECAL_IMPACT_ALIEN; +var int DECAL_IMPACT_FLESH; +var int DECAL_IMPACT_FOLIAGE; +var int DECAL_IMPACT_COMPUTER; +var int DECAL_IMPACT_DIRT; +var int DECAL_IMPACT_VENT; +var int DECAL_IMPACT_GRATE; +var int DECAL_IMPACT_METAL; +var int DECAL_IMPACT_GLASS; +var int DECAL_IMPACT_SAND; +var int DECAL_IMPACT_SLOSH; +var int DECAL_IMPACT_SNOW; +var int DECAL_IMPACT_TILE; +var int DECAL_IMPACT_WOOD; +var int DECAL_IMPACT_CONCRETE; + +void +FX_Impact_Init(void) +{ + Sound_Precache("sfx_impact.default"); + Sound_Precache("sfx_impact.alien"); + Sound_Precache("sfx_impact.flesh"); + Sound_Precache("sfx_impact.foliage"); + Sound_Precache("sfx_impact.computer"); + Sound_Precache("sfx_impact.dirt"); + Sound_Precache("sfx_impact.vent"); + Sound_Precache("sfx_impact.grate"); + Sound_Precache("sfx_impact.metal"); + Sound_Precache("sfx_impact.glass"); + Sound_Precache("sfx_impact.sand"); + Sound_Precache("sfx_impact.slosh"); + Sound_Precache("sfx_impact.snow"); + Sound_Precache("sfx_impact.tile"); + Sound_Precache("sfx_impact.wood"); + Sound_Precache("sfx_impact.concrete"); + + 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"); + + /* engine-side particle system decals for non HL1 BSP */ + DECAL_IMPACT_DEFAULT = particleeffectnum("decal_impact.default"); + DECAL_IMPACT_ALIEN = particleeffectnum("decal_impact.alien"); + DECAL_IMPACT_FLESH = particleeffectnum("decal_impact.flesh"); + DECAL_IMPACT_FOLIAGE = particleeffectnum("decal_impact.foliage"); + DECAL_IMPACT_COMPUTER = particleeffectnum("decal_impact.computer"); + DECAL_IMPACT_DIRT = particleeffectnum("decal_impact.dirt"); + DECAL_IMPACT_VENT = particleeffectnum("decal_impact.vent"); + DECAL_IMPACT_GRATE = particleeffectnum("decal_impact.grate"); + DECAL_IMPACT_METAL = particleeffectnum("decal_impact.metal"); + DECAL_IMPACT_GLASS = particleeffectnum("decal_impact.glass"); + DECAL_IMPACT_SAND = particleeffectnum("decal_impact.sand"); + DECAL_IMPACT_SLOSH = particleeffectnum("decal_impact.slosh"); + DECAL_IMPACT_SNOW = particleeffectnum("decal_impact.snow"); + DECAL_IMPACT_TILE = particleeffectnum("decal_impact.tile"); + DECAL_IMPACT_WOOD = particleeffectnum("decal_impact.wood"); + DECAL_IMPACT_CONCRETE = particleeffectnum("decal_impact.concrete"); +} +#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 */ + if (serverkeyfloat("*bspversion") == BSPVER_HL) { + 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; + } + } else { + switch (iType) { + case IMPACT_GLASS: + pointparticles(DECAL_IMPACT_GLASS, vecPos, vNormal, 1); + break; + case IMPACT_WOOD: + pointparticles(DECAL_IMPACT_WOOD, vecPos, vNormal, 1); + break; + case IMPACT_METAL: + pointparticles(DECAL_IMPACT_METAL, vecPos, vNormal, 1); + break; + case IMPACT_FLESH: + pointparticles(DECAL_IMPACT_FLESH, vecPos, vNormal, 1); + break; + default: + pointparticles(DECAL_IMPACT_DEFAULT, vecPos, vNormal, 1); + break; + } + } + + switch (iType) { + case IMPACT_MELEE: + 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; + 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_ALIEN: + Sound_PlayAt(vecPos, "sfx_impact.alien"); + break; + case IMPACT_COMPUTER: + Sound_PlayAt(vecPos, "sfx_impact.computer"); + break; + case IMPACT_CONCRETE: + Sound_PlayAt(vecPos, "sfx_impact.concrete"); + break; + case IMPACT_DIRT: + Sound_PlayAt(vecPos, "sfx_impact.dirt"); + break; + case IMPACT_FLESH: + Sound_PlayAt(vecPos, "sfx_impact.flesh"); + break; + case IMPACT_FOLIAGE: + Sound_PlayAt(vecPos, "sfx_impact.foliage"); + break; + case IMPACT_GLASS: + Sound_PlayAt(vecPos, "sfx_impact.glass"); + break; + case IMPACT_GRATE: + Sound_PlayAt(vecPos, "sfx_impact.grate"); + break; + case IMPACT_METAL: + Sound_PlayAt(vecPos, "sfx_impact.metal"); + break; + case IMPACT_SLOSH: + Sound_PlayAt(vecPos, "sfx_impact.slosh"); + break; + case IMPACT_SNOW: + Sound_PlayAt(vecPos, "sfx_impact.snow"); + break; + case IMPACT_TILE: + Sound_PlayAt(vecPos, "sfx_impact.tile"); + break; + case IMPACT_VENT: + Sound_PlayAt(vecPos, "sfx_impact.vent"); + break; + case IMPACT_WOOD: + Sound_PlayAt(vecPos, "sfx_impact.wood"); + break; + default: + Sound_PlayAt(vecPos, "sfx_impact.default"); + break; + } +#endif +} diff --git a/src/shared/fx_spark.qc b/src/shared/fx_spark.qc new file mode 100644 index 0000000..b326fd8 --- /dev/null +++ b/src/shared/fx_spark.qc @@ -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. + */ + +#ifdef CLIENT +var float PARTICLE_SPARK; + +void +FX_Spark_Init(void) +{ + precache_sound("buttons/spark1.wav"); + precache_sound("buttons/spark2.wav"); + precache_sound("buttons/spark3.wav"); + precache_sound("buttons/spark4.wav"); + precache_sound("buttons/spark5.wav"); + precache_sound("buttons/spark6.wav"); + PARTICLE_SPARK = particleeffectnum("fx_spark.effect"); +} +#endif + +void +FX_Spark(vector pos, vector ang) +{ +#ifdef SERVER + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_SPARK); + WriteCoord(MSG_MULTICAST, pos[0]); + WriteCoord(MSG_MULTICAST, pos[1]); + WriteCoord(MSG_MULTICAST, pos[2]); + WriteCoord(MSG_MULTICAST, ang[0]); + WriteCoord(MSG_MULTICAST, ang[1]); + WriteCoord(MSG_MULTICAST, ang[2]); + msg_entity = self; + multicast(pos, MULTICAST_PVS); +#else + pointparticles(PARTICLE_SPARK, pos, ang, 1); + pointsound(pos, sprintf("buttons/spark%d.wav", floor(random() * 6) + 1), 1, ATTN_STATIC); +#endif +} diff --git a/src/shared/include.src b/src/shared/include.src new file mode 100644 index 0000000..b454be1 --- /dev/null +++ b/src/shared/include.src @@ -0,0 +1,36 @@ + #includelist +entities.h +flags.h +player.qc +weapon_common.h +animations.h +animations.qc +pmove.qc +pmove_water.qc + +fx_blood.qc +fx_breakmodel.qc +fx_explosion.qc +fx_gibhuman.qc +fx_spark.qc +fx_impact.qc + +items.h +weapons.h +w_crossbow.qc +w_crowbar.qc +w_egon.qc +w_gauss.qc +w_glock.qc +w_handgrenade.qc +w_hornetgun.qc +w_mp5.qc +w_python.qc +w_rpg.qc +w_satchel.qc +w_shotgun.qc +w_snark.qc +w_tripmine.qc +weapons.qc +weapon_common.qc +#endlist diff --git a/src/shared/items.h b/src/shared/items.h new file mode 100644 index 0000000..f6e6b37 --- /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_CROWBAR 0x00000001i +#define ITEM_GLOCK 0x00000002i +#define ITEM_PYTHON 0x00000004i +#define ITEM_MP5 0x00000008i +#define ITEM_CROSSBOW 0x00000010i +#define ITEM_SHOTGUN 0x00000020i +#define ITEM_RPG 0x00000040i +#define ITEM_GAUSS 0x00000080i + +#define ITEM_EGON 0x00000100i +#define ITEM_HORNETGUN 0x00000200i +#define ITEM_HANDGRENADE 0x00000400i +#define ITEM_TRIPMINE 0x00000800i +#define ITEM_SATCHEL 0x00001000i +#define ITEM_SNARK 0x00002000i +#define ITEM_SUIT 0x00004000i +#define ITEM_LONGJUMP 0x00008000i + +#define ITEM_UNUSED17 0x00010000i +#define ITEM_UNUSED18 0x00020000i +#define ITEM_UNUSED19 0x00040000i +#define ITEM_UNUSED20 0x00080000i +#define ITEM_UNUSED21 0x00100000i +#define ITEM_UNUSED22 0x00200000i +#define ITEM_UNUSED23 0x00400000i +#define ITEM_UNUSED24 0x00800000i + +#define ITEM_UNUSED25 0x01000000i +#define ITEM_UNUSED26 0x02000000i +#define ITEM_UNUSED27 0x04000000i +#define ITEM_UNUSED28 0x08000000i +#define ITEM_UNUSED29 0x10000000i +#define ITEM_UNUSED30 0x20000000i +#define ITEM_UNUSED31 0x40000000i +#define ITEM_UNUSED32 0x80000000i diff --git a/src/shared/player.qc b/src/shared/player.qc new file mode 100644 index 0000000..5b36c3f --- /dev/null +++ b/src/shared/player.qc @@ -0,0 +1,642 @@ +/* + * 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. + */ + +/* all potential SendFlags bits we can possibly send */ +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_UNUSED1, + PLAYER_UNUSED2 +}; + +/* ammo 1 type updates */ +enumflags +{ + AMMO1_GLOCK, + AMMO1_MP5, + AMMO1_PYTHON, + AMMO1_SHOTGUN, + AMMO1_CROSSBOW, + AMMO1_RPG, + AMMO1_SATCHEL +}; + +/* ammo 2 type updates */ +enumflags +{ + AMMO2_9MM, + AMMO2_357, + AMMO2_BUCKSHOT, + AMMO2_BOLT, + AMMO2_ROCKET, + AMMO2_URANIUM, + AMMO2_HANDGRENADE, + AMMO2_SATCHEL, + AMMO2_TRIPMINE, + AMMO2_SNARK, + AMMO2_HORNET, +}; + +enumflags +{ + AMMO3_M203_GRENADE, + AMMO3_SHOTGUN_STATE, + AMMO3_GAUSS_STATE, + AMMO3_GAUSS_VOLUME, + AMMO3_EGON_STATE, + AMMO3_RPG_STATE, + AMMO3_HANDGRENADE_STATE +}; + +noref int input_sequence; +class player:base_player +{ + /* Weapon specific */ + int glock_mag; + int glock_mag_net; + int mp5_mag; + int mp5_mag_net; + int python_mag; + int python_mag_net; + int shotgun_mag; + int shotgun_mag_net; + int crossbow_mag; + int crossbow_mag_net; + int rpg_mag; + int rpg_mag_net; + int satchel_chg; + int satchel_chg_net; + + int ammo_9mm; + int ammo_9mm_net; + int ammo_357; + int ammo_357_net; + int ammo_buckshot; + int ammo_buckshot_net; + int ammo_bolt; + int ammo_bolt_net; + int ammo_rocket; + int ammo_rocket_net; + int ammo_uranium; + int ammo_uranium_net; + int ammo_handgrenade; + int ammo_handgrenade_net; + int ammo_satchel; + int ammo_satchel_net; + int ammo_tripmine; + int ammo_tripmine_net; + int ammo_snark; + int ammo_snark_net; + int ammo_hornet; + int ammo_hornet_net; + + int ammo_m203_grenade; + int ammo_m203_grenade_net; + int ammo_gauss_volume; + int ammo_gauss_volume_net; + int ammo_rpg_state; + int ammo_rpg_state_net; + int mode_tempstate; + int mode_tempstate_net; + +#ifdef CLIENT + /* External model */ + entity p_model; + int p_hand_bone; + int p_model_bone; + float lastweapon; + + 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; +#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) { + glock_mag = readbyte(); + mp5_mag = readbyte(); + python_mag = readbyte(); + shotgun_mag = readbyte(); + crossbow_mag = readbyte(); + rpg_mag = readbyte(); + satchel_chg = readbyte(); + } + + if (fl & PLAYER_AMMO2) { + ammo_9mm = readbyte(); + ammo_357 = readbyte(); + ammo_buckshot = readbyte(); + ammo_bolt = readbyte(); + ammo_rocket = readbyte(); + ammo_uranium = readbyte(); + ammo_handgrenade = readbyte(); + ammo_satchel = readbyte(); + ammo_tripmine = readbyte(); + ammo_snark = readbyte(); + ammo_hornet = readbyte(); + } + + if (fl & PLAYER_AMMO3) { + ammo_m203_grenade = readbyte(); + ammo_gauss_volume = readbyte(); + ammo_rpg_state = readbyte(); + mode_tempstate = readbyte(); + } + + 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) +{ + glock_mag_net = glock_mag; + mp5_mag_net = mp5_mag; + python_mag_net = python_mag; + shotgun_mag_net = shotgun_mag; + crossbow_mag_net = crossbow_mag; + rpg_mag_net = rpg_mag; + satchel_chg_net = satchel_chg; + ammo_9mm_net = ammo_9mm; + ammo_357_net = ammo_357; + ammo_buckshot_net = ammo_buckshot; + ammo_bolt_net = ammo_bolt; + ammo_rocket_net = ammo_rocket; + ammo_uranium_net = ammo_uranium; + ammo_handgrenade_net = ammo_handgrenade; + ammo_satchel_net = ammo_satchel; + ammo_tripmine_net = ammo_tripmine; + ammo_snark_net = ammo_snark; + ammo_hornet_net = ammo_hornet; + + ammo_m203_grenade_net = ammo_m203_grenade; + ammo_gauss_volume_net = ammo_gauss_volume; + ammo_rpg_state_net = ammo_rpg_state; + mode_tempstate_net = mode_tempstate; +} + +/* +================= +player::PredictPostFrame + +Where we roll back our values to the ones last sent/verified by the server. +================= +*/ +void +player::PredictPostFrame(void) +{ + glock_mag = glock_mag_net; + mp5_mag = mp5_mag_net; + python_mag = python_mag_net; + shotgun_mag = shotgun_mag_net; + crossbow_mag = crossbow_mag_net; + rpg_mag = rpg_mag_net; + satchel_chg = satchel_chg_net; + ammo_9mm = ammo_9mm_net; + ammo_357 = ammo_357_net; + ammo_buckshot = ammo_buckshot_net; + ammo_m203_grenade = ammo_m203_grenade_net; + ammo_bolt = ammo_bolt_net; + ammo_rocket = ammo_rocket_net; + ammo_uranium = ammo_uranium_net; + ammo_handgrenade = ammo_handgrenade_net; + ammo_satchel = ammo_satchel_net; + ammo_tripmine = ammo_tripmine_net; + ammo_snark = ammo_snark_net; + ammo_hornet = ammo_hornet_net; + + ammo_m203_grenade = ammo_m203_grenade_net; + ammo_gauss_volume = ammo_gauss_volume_net; + ammo_rpg_state = ammo_rpg_state_net; + mode_tempstate = mode_tempstate_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 (glock_mag != glock_mag_net) { + SendFlags |= PLAYER_AMMO1; + } + if (mp5_mag != mp5_mag_net) { + SendFlags |= PLAYER_AMMO1; + } + if (python_mag != python_mag_net) { + SendFlags |= PLAYER_AMMO1; + } + if (shotgun_mag != shotgun_mag_net) { + SendFlags |= PLAYER_AMMO1; + } + if (crossbow_mag != crossbow_mag_net) { + SendFlags |= PLAYER_AMMO1; + } + if (rpg_mag != rpg_mag_net) { + SendFlags |= PLAYER_AMMO1; + } + if (satchel_chg != satchel_chg_net) { + SendFlags |= PLAYER_AMMO1; + } + + /* ammo 2 type updates */ + if (ammo_9mm != ammo_9mm_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_357 != ammo_357_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_buckshot != ammo_buckshot_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_bolt != ammo_bolt_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_rocket != ammo_rocket_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_uranium != ammo_uranium_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_handgrenade != ammo_handgrenade_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_satchel != ammo_satchel_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_tripmine != ammo_tripmine_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_snark != ammo_snark_net) { + SendFlags |= PLAYER_AMMO2; + } + if (ammo_hornet != ammo_hornet_net) { + SendFlags |= PLAYER_AMMO2; + } + + if (ammo_m203_grenade != ammo_m203_grenade_net) { + SendFlags |= PLAYER_AMMO3; + } + if (ammo_gauss_volume != ammo_gauss_volume_net) { + SendFlags |= PLAYER_AMMO3; + } + if (ammo_rpg_state != ammo_rpg_state_net) { + SendFlags |= PLAYER_AMMO3; + } + if (mode_tempstate != mode_tempstate_net) { + SendFlags |= PLAYER_AMMO3; + } + + 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; + + glock_mag_net = glock_mag; + mp5_mag_net = mp5_mag; + python_mag_net = python_mag; + shotgun_mag_net = shotgun_mag; + crossbow_mag_net = crossbow_mag; + rpg_mag_net = rpg_mag; + satchel_chg_net = satchel_chg; + + ammo_9mm_net = ammo_9mm; + ammo_357_net = ammo_357; + ammo_buckshot_net = ammo_buckshot; + ammo_m203_grenade_net = ammo_m203_grenade; + ammo_bolt_net = ammo_bolt; + ammo_rocket_net = ammo_rocket; + ammo_uranium_net = ammo_uranium; + ammo_handgrenade_net = ammo_handgrenade; + ammo_satchel_net = ammo_satchel; + ammo_tripmine_net = ammo_tripmine; + ammo_snark_net = ammo_snark; + ammo_hornet_net = ammo_hornet; + + ammo_m203_grenade_net = ammo_m203_grenade; + ammo_gauss_volume_net = ammo_gauss_volume; + ammo_rpg_state_net = ammo_rpg_state; + mode_tempstate_net = mode_tempstate; +} + +/* +================= +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, glock_mag); + WriteByte(MSG_ENTITY, mp5_mag); + WriteByte(MSG_ENTITY, python_mag); + WriteByte(MSG_ENTITY, shotgun_mag); + WriteByte(MSG_ENTITY, crossbow_mag); + WriteByte(MSG_ENTITY, rpg_mag); + WriteByte(MSG_ENTITY, satchel_chg); + } + + if (fChanged & PLAYER_AMMO2) { + WriteByte(MSG_ENTITY, ammo_9mm); + WriteByte(MSG_ENTITY, ammo_357); + WriteByte(MSG_ENTITY, ammo_buckshot); + WriteByte(MSG_ENTITY, ammo_bolt); + WriteByte(MSG_ENTITY, ammo_rocket); + WriteByte(MSG_ENTITY, ammo_uranium); + WriteByte(MSG_ENTITY, ammo_handgrenade); + WriteByte(MSG_ENTITY, ammo_satchel); + WriteByte(MSG_ENTITY, ammo_tripmine); + WriteByte(MSG_ENTITY, ammo_snark); + WriteByte(MSG_ENTITY, ammo_hornet); + } + + if (fChanged & PLAYER_AMMO3) { + WriteByte(MSG_ENTITY, ammo_m203_grenade); + WriteByte(MSG_ENTITY, ammo_gauss_volume); + WriteByte(MSG_ENTITY, ammo_rpg_state); + WriteByte(MSG_ENTITY, mode_tempstate); + } + + return TRUE; +} +#endif diff --git a/src/shared/pmove.qc b/src/shared/pmove.qc new file mode 100644 index 0000000..9656ee5 --- /dev/null +++ b/src/shared/pmove.qc @@ -0,0 +1,74 @@ +/* + * 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 PHY_JUMP_CHAINWINDOW 0.5 +#define PHY_JUMP_CHAIN 100 +#define PHY_JUMP_CHAINDECAY 50 + +.float waterlevel; +.float watertype; + +float GamePMove_Maxspeed(player target) +{ + return (target.flags & FL_CROUCHING) ? 135 : 270; +} + +void GamePMove_Fall(player target, float impactspeed) +{ + if (impactspeed > 580) { +#ifdef SERVER + float fFallDamage = (impactspeed - 580) * (100 / (1024 - 580)); + Damage_Apply(target, world, fFallDamage, 0, DMG_FALL); + Sound_Play(target, CHAN_VOICE, "player.fall"); +#endif + target.punchangle += [15,0,(input_sequence & 1) ? 15 : -15]; + } else if (impactspeed > 400) { + target.punchangle += [15,0,0]; +#ifdef SERVER + Sound_Play(target, CHAN_VOICE, "player.lightfall"); +#endif + } +} + +void GamePMove_Jump(player target) +{ + float flJumptimeDelta; + float flChainBonus; + + 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 { + /* Half-Life: Longjump module */ + if (target.flags & FL_CROUCHING && target.g_items & 0x00008000i) { + target.velocity = v_forward * 512; + target.velocity[2] += 100; + } + target.velocity[2] += 240; + } + + if (target.jumptime > 0) { + flJumptimeDelta = 0 - (target.jumptime - PHY_JUMP_CHAINWINDOW); + flChainBonus = PHY_JUMP_CHAIN - (((PHY_JUMP_CHAINWINDOW - (PHY_JUMP_CHAINWINDOW - flJumptimeDelta)) * 2) * PHY_JUMP_CHAINDECAY); + target.velocity[2] += flChainBonus; + } + target.jumptime = PHY_JUMP_CHAINWINDOW; +} diff --git a/src/shared/pmove_water.qc b/src/shared/pmove_water.qc new file mode 100644 index 0000000..cec6cab --- /dev/null +++ b/src/shared/pmove_water.qc @@ -0,0 +1,78 @@ +/* + * 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 +GamePMove_WaterMove(player target) +{ + if (target.movetype == MOVETYPE_NOCLIP) { + return; + } + +#ifdef SERVER + if (target.health < 0) { + return; + } + + /* we've just exited water */ + if (target.waterlevel != 3) { + if (target.underwater_time < time) { + Sound_Play(target, CHAN_BODY, "player.gasplight"); + } else if (target.underwater_time < time + 9) { + Sound_Play(target, CHAN_BODY, "player.gaspheavy"); + } + target.underwater_time = time + 12; + } else if (target.underwater_time < time) { + /* we've been underwater... for too long. */ + if (target.pain_time < time) { + Damage_Apply(target, world, 5, DMG_DROWN, 0); + target.pain_time = time + 1; + } + } +#endif + + if (!target.waterlevel){ + if (target.flags & FL_INWATER) { +#ifdef SERVER + Sound_Play(target, CHAN_BODY, "player.waterexit"); +#endif + target.flags &= ~FL_INWATER; + } + return; + } + +#ifdef SERVER + if (target.watertype == CONTENT_LAVA) { + if (target.pain_time < time) { + target.pain_time = time + 0.2; + Damage_Apply(target, world, 10*target.waterlevel, DMG_BURN, 0); + } + } else if (target.watertype == CONTENT_SLIME) { + if (target.pain_time < time) { + target.pain_time = time + 1; + Damage_Apply(target, world, 4*target.waterlevel, DMG_ACID, 0); + } + } +#endif + + if (!(target.flags & FL_INWATER)) { +#ifdef SERVER + Sound_Play(target, CHAN_BODY, "player.waterenter"); + target.pain_time = 0; +#endif + target.flags |= FL_INWATER; + } +} + diff --git a/src/shared/w_crossbow.qc b/src/shared/w_crossbow.qc new file mode 100644 index 0000000..d86ef62 --- /dev/null +++ b/src/shared/w_crossbow.qc @@ -0,0 +1,396 @@ +/* + * 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_crossbow (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_crossbow.mdl" + +HALF-LIFE (1998) ENTITY + +Crossbow Weapon + +*/ + +enum +{ + CROSSBOW_IDLE1, + CROSSBOW_IDLE2, + CROSSBOW_FIDGET1, + CROSSBOW_FIDGET2, + CROSSBOW_FIRE1, + CROSSBOW_FIRE2, + CROSSBOW_FIRE3, + CROSSBOW_RELOAD, + CROSSBOW_DRAW1, + CROSSBOW_DRAW2, + CROSSBOW_HOLSTER1, + CROSSBOW_HOLSTER2 +}; + +void +w_crossbow_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_crossbow.fire"); + Sound_Precache("weapon_crossbow.hit"); + Sound_Precache("weapon_crossbow.hitbody"); + Sound_Precache("weapon_crossbow.reload"); + precache_model("models/crossbow_bolt.mdl"); + precache_model("models/w_crossbow.mdl"); +#else + precache_model("models/v_crossbow.mdl"); + precache_model("models/p_crossbow.mdl"); +#endif +} + +void +w_crossbow_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.crossbow_mag, pl.ammo_bolt, -1); +} + +string +w_crossbow_wmodel(void) +{ + return "models/w_crossbow.mdl"; +} + +string +w_crossbow_pmodel(void) +{ + return "models/p_crossbow.mdl"; +} + +string +w_crossbow_deathmsg(void) +{ + return ""; +} + +int +w_crossbow_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + pl.crossbow_mag = 5; + } else { + if (pl.ammo_bolt < MAX_A_BOLT) { + pl.ammo_bolt = bound(0, pl.ammo_bolt + 5, MAX_A_BOLT); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_crossbow_draw(void) +{ + player pl = (player)self; + Weapons_SetModel("models/v_crossbow.mdl"); + + if (pl.crossbow_mag <= 0) + Weapons_ViewAnimation(CROSSBOW_DRAW2); + else + Weapons_ViewAnimation(CROSSBOW_DRAW1); +} + +void +w_crossbow_holster(void) +{ + Weapons_ViewAnimation(CROSSBOW_HOLSTER1); +} + +#ifdef SERVER +void Crossbolt_Touch(void) { + /* explode mode, multiplayer */ + if (self.weapon) { + float dmg = Skill_GetValue("plr_xbow_bolt_monster", 50); + FX_Explosion(self.origin); + Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_CROSSBOW); + if (random() < 0.5) { + sound(self, 1, "weapons/explode3.wav", 1.0f, ATTN_NORM); + } else { + sound(self, 1, "weapons/explode4.wav", 1.0f, ATTN_NORM); + } + remove(self); + return; + } + + /* walls, etc. */ + if (other.takedamage != DAMAGE_YES) { + FX_Spark(self.origin, trace_plane_normal); + Sound_Play(self, 1, "weapon_crossbow.hit"); + remove(self); + return; + } + + /* anything else that can take damage */ + Damage_Apply(other, self.owner, Skill_GetValue("plr_xbow_bolt_monster", 50), WEAPON_CROSSBOW, DMG_BLUNT); + Sound_Play(self, 1, "weapon_crossbow.hitbody"); + + if (other.iBleeds == FALSE) { + FX_Spark(self.origin, trace_plane_normal); + } else { + FX_Blood(self.origin, [1,0,0]); + } + remove(self); +} +#endif + +void +w_crossbow_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* ammo check */ + if (pl.crossbow_mag <= 0) { + return; + } + + pl.crossbow_mag--; + +#ifndef CLIENT + Weapons_MakeVectors(); + entity bolt = spawn(); + setmodel(bolt, "models/crossbow_bolt.mdl"); + setorigin(bolt, Weapons_GetCameraPos() + (v_forward * 16)); + bolt.owner = self; + bolt.velocity = v_forward * 2000; + bolt.movetype = MOVETYPE_FLYMISSILE; + bolt.solid = SOLID_BBOX; + //bolt.flags |= FL_LAGGEDMOVE; + bolt.gravity = 0.5f; + bolt.angles = vectoangles(bolt.velocity); + bolt.avelocity[2] = 10; + bolt.touch = Crossbolt_Touch; + bolt.weapon = pl.viewzoom == 1.0 ? 1 : 0; + setsize(bolt, [0,0,0], [0,0,0]); + + if (pl.crossbow_mag > 0) { + Sound_Play(pl, 8, "weapon_crossbow.hitbody"); + } + + Sound_Play(pl, CHAN_WEAPON, "weapon_crossbow.fire"); +#endif + + if (pl.crossbow_mag) { + Weapons_ViewAnimation(CROSSBOW_FIRE1); + } else { + Weapons_ViewAnimation(CROSSBOW_FIRE3); + } + + Weapons_ViewPunchAngle([-2,0,0]); + + pl.w_attack_next = 0.75f; + pl.w_idle_next = 10.0f; +} + +void +w_crossbow_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_crossbow_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + if (pl.ammo_bolt <= 0) { + return; + } + if (pl.crossbow_mag >= 5) { + return; + } + +#ifdef SERVER + Weapons_ReloadWeapon(pl, player::crossbow_mag, player::ammo_bolt, 5); + Sound_Play(pl, CHAN_ITEM, "weapon_crossbow.reload"); +#endif + + Weapons_ViewAnimation(CROSSBOW_RELOAD); + + pl.w_attack_next = 4.5f; + pl.w_idle_next = 10.0f; +} + +void +w_crossbow_release(void) +{ + player pl = (player)self; + + /* auto-reload if need be */ + if (pl.w_attack_next <= 0.0) + if (pl.crossbow_mag == 0 && pl.ammo_bolt > 0) { + Weapons_Reload(); + return; + } + + if (pl.w_idle_next > 0.0) { + return; + } + + int r = (float)input_sequence % 2; + if (r == 1) { + if (pl.ammo_bolt) { + Weapons_ViewAnimation(CROSSBOW_IDLE1); + } else { + Weapons_ViewAnimation(CROSSBOW_IDLE2); + } + } else { + if (pl.ammo_bolt) { + Weapons_ViewAnimation(CROSSBOW_FIDGET1); + } else { + Weapons_ViewAnimation(CROSSBOW_FIDGET2); + } + } + + pl.w_idle_next = 3.0f; +} + +void +w_crossbow_crosshair(void) +{ +#ifdef CLIENT + vector cross_pos; + vector aicon_pos; + + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + drawsubpic( + cross_pos, + [24,24], + g_cross_spr, + [72/128,0], + [0.1875, 0.1875], + [1,1,1], + 1, + DRAWFLAG_NORMAL + ); + + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + + aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic( + aicon_pos, + [24,24], + g_hud7_spr, + [96/256,72/128], + [24/256, 24/128], + g_hud_color, + pSeat->m_flAmmo2Alpha, + DRAWFLAG_ADDITIVE + ); +#endif +} + +float +w_crossbow_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMBOW : ANIM_AIMBOW; +} + +void +w_crossbow_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.crossbow_mag == 0 && pl.ammo_bolt == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud5_spr, + [0,0], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud2_spr, + [0,0], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } + + HUD_DrawAmmoBar(pos, pl.ammo_bolt, MAX_A_BOLT, a); +#endif +} + +weapon_t w_crossbow = +{ + .name = "crossbow", + .id = ITEM_CROSSBOW, + .slot = 2, + .slot_pos = 2, + .draw = w_crossbow_draw, + .holster = w_crossbow_holster, + .primary = w_crossbow_primary, + .secondary = w_crossbow_secondary, + .reload = w_crossbow_reload, + .release = w_crossbow_release, + .crosshair = w_crossbow_crosshair, + .precache = w_crossbow_precache, + .pickup = w_crossbow_pickup, + .updateammo = w_crossbow_updateammo, + .wmodel = w_crossbow_wmodel, + .pmodel = w_crossbow_pmodel, + .deathmsg = w_crossbow_deathmsg, + .aimanim = w_crossbow_aimanim, + .hudpic = w_crossbow_hudpic +}; + +#ifdef SERVER +void +weapon_crossbow(void) +{ + Weapons_InitItem(WEAPON_CROSSBOW); +} +#endif diff --git a/src/shared/w_crowbar.qc b/src/shared/w_crowbar.qc new file mode 100644 index 0000000..86dd56b --- /dev/null +++ b/src/shared/w_crowbar.qc @@ -0,0 +1,238 @@ +/* + * 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 weapon_crowbar (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_crowbar.mdl" + +HALF-LIFE (1998) ENTITY + +Crowbar Weapon + +*/ + +enum +{ + CBAR_IDLE, + CBAR_DRAW, + CBAR_HOLSTER, + CBAR_ATTACK1HIT, + CBAR_ATTACK1MISS, + CBAR_ATTACK2MISS, + CBAR_ATTACK2HIT, + CBAR_ATTACK3MISS, + CBAR_ATTACK3HIT +}; + +void +w_crowbar_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_crowbar.hit"); + Sound_Precache("weapon_crowbar.miss"); + Sound_Precache("weapon_crowbar.hitbody"); + precache_model("models/w_crowbar.mdl"); +#else + precache_model("models/v_crowbar.mdl"); + precache_model("models/p_crowbar.mdl"); +#endif +} + +void +w_crowbar_updateammo(player pl) +{ + +} + +string +w_crowbar_wmodel(void) +{ + return "models/w_crowbar.mdl"; +} +string +w_crowbar_pmodel(void) +{ + return "models/p_crowbar.mdl"; +} + +string +w_crowbar_deathmsg(void) +{ + return "%s was assaulted by %s's Crowbar."; +} + +void +w_crowbar_draw(void) +{ + Weapons_SetModel("models/v_crowbar.mdl"); + Weapons_ViewAnimation(CBAR_DRAW); +} + +void +w_crowbar_holster(void) +{ + Weapons_ViewAnimation(CBAR_HOLSTER); +} + +void +w_crowbar_primary(void) +{ + int anim = 0; + vector src; + player pl = (player)self; + + if (pl.w_attack_next) { + return; + } + + Weapons_MakeVectors(); + src = pl.origin + pl.view_ofs; + + /* make sure we can gib corpses */ + int oldhitcontents = self.hitcontentsmaski; + self.hitcontentsmaski = CONTENTBITS_POINTSOLID | CONTENTBIT_CORPSE; + traceline(src, src + (v_forward * 32), FALSE, pl); + self.hitcontentsmaski = oldhitcontents; + + if (trace_fraction >= 1.0) { + pl.w_attack_next = 0.5f; + } else { + pl.w_attack_next = 0.25f; + } + pl.w_idle_next = 2.5f; + + int r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(trace_fraction >= 1 ? CBAR_ATTACK1MISS:CBAR_ATTACK1HIT); + break; + case 1: + Weapons_ViewAnimation(trace_fraction >= 1 ? CBAR_ATTACK2MISS:CBAR_ATTACK2HIT); + break; + default: + Weapons_ViewAnimation(trace_fraction >= 1 ? CBAR_ATTACK3MISS:CBAR_ATTACK3HIT); + } + + if (pl.flags & FL_CROUCHING) { + Animation_PlayerTopTemp(ANIM_SHOOTCROWBAR, 0.5f); + } else { + Animation_PlayerTopTemp(ANIM_CR_SHOOTCROWBAR, 0.42f); + } + +#ifdef SERVER + Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.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]); + } else { + FX_Impact(IMPACT_MELEE, trace_endpos, trace_plane_normal); + } + + if (trace_ent.takedamage) { + Damage_Apply(trace_ent, pl, Skill_GetValue("plr_crowbar", 10), WEAPON_CROWBAR, DMG_BLUNT); + if (trace_ent.iBleeds) { + Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.hitbody"); + } + } else { + Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.hit"); + } +#endif +} + +void +w_crowbar_release(void) +{ + player pl = (player)self; + + if (pl.w_idle_next) { + return; + } + + Weapons_ViewAnimation(CBAR_IDLE); + pl.w_idle_next = 15.0f; +} + +float +w_crowbar_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR; +} + +void +w_crowbar_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, + a, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud1_spr, + [0,0], + [170/256,45/256], + g_hud_color, + a, + DRAWFLAG_ADDITIVE + ); + } +#endif +} + +weapon_t w_crowbar = +{ + .name = "crowbar", + .id = ITEM_CROWBAR, + .slot = 0, + .slot_pos = 0, + .draw = w_crowbar_draw, + .holster = w_crowbar_holster, + .primary = w_crowbar_primary, + .secondary = __NULL__, + .reload = __NULL__, + .release = w_crowbar_release, + .crosshair = __NULL__, + .precache = w_crowbar_precache, + .pickup = __NULL__, + .updateammo = w_crowbar_updateammo, + .wmodel = w_crowbar_wmodel, + .pmodel = w_crowbar_pmodel, + .deathmsg = w_crowbar_deathmsg, + .aimanim = w_crowbar_aimanim, + .hudpic = w_crowbar_hudpic +}; + +/* entity definitions for pickups */ +#ifdef SERVER +void +weapon_crowbar(void) +{ + Weapons_InitItem(WEAPON_CROWBAR); +} +#endif diff --git a/src/shared/w_egon.qc b/src/shared/w_egon.qc new file mode 100644 index 0000000..6adc26c --- /dev/null +++ b/src/shared/w_egon.qc @@ -0,0 +1,332 @@ +/* + * 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_egon (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_egon.mdl" + +HALF-LIFE (1998) ENTITY + +Egon/Gluon-Gun Weapon + +*/ + +#ifdef CLIENT +var float TRAIL_EGONBEAM; + +#define FXGAUSS_BEAMCOLOR [1,0.5,0] +class FXEgon:CBaseFX +{ + int m_iBeams; + vector m_vecStart; + vector m_vecAngle; + + void(void) FXEgon; + virtual void(void) Draw; +}; + +void +FXEgon::Animate_Next(void) +{ + frame++; + + if (frame == 11) + frame = 0; + + nextthink = time + 0.1f; +} + +void +FXEgon::Draw(void) +{ + player pl = (player)self; + int iLoop = 6; + vector src, endpos; + vector gunpos = gettaginfo(pSeat->m_eViewModel, 33); + + if (alpha <= 0.0f) { + modelindex = 0; + return; + } + + src = gettaginfo(pSeat->m_eViewModel, 0); + makevectors(input_angles); + endpos = src + v_forward * 1024; + traceline(src, endpos, FALSE, pl); + + dynamiclight_add(trace_endpos + v_forward * -16, 128, [0.5, 0.5, 1.0]); + trailparticles(TRAIL_EGONBEAM, pl, gunpos, trace_endpos); + setorigin(this, trace_endpos + v_forward * -16); + + setmodel(this, "sprites/xspark1.spr"); + effects = EF_ADDITIVE; +} + +void +FXEgon::FXEgon(void) +{ + CBaseFX::CBaseFX(); + think = Animate_Next; + nextthink = time + 0.1f; +} +#endif + +enum +{ + EGON_IDLE1, + EGON_FIDGET1, + EGON_ALTFIREON, + EGON_ALTFIRECYCLE, + EGON_ALTFIREOFF, + EGON_FIRE1, + EGON_FIRE2, + EGON_FIRE3, + EGON_FIRE4, + EGON_DRAW, + EGON_HOLSTER +}; + +void w_egon_precache(void) +{ +#ifdef SERVER + precache_sound("weapons/egon_windup2.wav"); + precache_sound("weapons/egon_run3.wav"); + precache_sound("weapons/egon_off1.wav"); + precache_model("models/w_egon.mdl"); +#else + TRAIL_EGONBEAM = particleeffectnum("weapon_egon.beam"); + precache_model("models/v_egon.mdl"); + precache_model("models/p_egon.mdl"); + precache_model("sprites/xspark1.spr"); +#endif +} +void w_egon_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, pl.ammo_uranium, -1); +} +string w_egon_wmodel(void) +{ + return "models/w_egon.mdl"; +} +string w_egon_pmodel(void) +{ + return "models/p_egon.mdl"; +} +string w_egon_deathmsg(void) +{ + return ""; +} + +int w_egon_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (pl.ammo_uranium < MAX_A_URANIUM) { + pl.ammo_uranium = bound(0, pl.ammo_uranium + 20, MAX_A_URANIUM); + } else { + return FALSE; + } +#endif + return TRUE; +} + +void w_egon_draw(void) +{ + player pl = (player)self; + pl.mode_tempstate = 0; + + /* link the FX class */ +#ifdef CLIENT + Weapons_SetModel("models/v_egon.mdl"); + Weapons_ViewAnimation(EGON_DRAW); + + entity eold = self; + self = pSeat->m_pWeaponFX; + spawnfunc_FXEgon(); + self = eold; +#endif +} + +void w_egon_holster(void) +{ + Weapons_ViewAnimation(EGON_HOLSTER); +} + +void w_egon_release(void); + +void w_egon_primary(void) +{ + player pl = (player)self; + if (pl.w_attack_next > 0.0) { + return; + } + + /* Ammo check */ + if (pl.ammo_uranium <= 0) { + w_egon_release(); + return; + } + +#ifdef CLIENT + if (Weapons_GetAnimation() == EGON_IDLE1) + Weapons_ViewAnimation(EGON_ALTFIREON); + else if (Weapons_GetAnimation() == EGON_ALTFIREON) + Weapons_ViewAnimation(EGON_ALTFIRECYCLE); + + FXEgon p = (FXEgon)pSeat->m_pWeaponFX; + p.m_vecAngle = input_angles; + p.m_vecStart = pl.origin + pl.view_ofs; + p.alpha = 1.0f; +#else + Weapons_MakeVectors(); + vector src = Weapons_GetCameraPos(); + vector endpos = src + v_forward * 1024; + traceline(src, endpos, FALSE, pl); + Damage_Radius(trace_endpos, pl, 14, 64, TRUE, DMG_ELECTRO); +#endif + + pl.ammo_uranium--; + + if (pl.mode_tempstate == 0) { +#ifdef SERVER + sound(pl, CHAN_WEAPON, "weapons/egon_windup2.wav", 1, ATTN_NORM, 100, 0); +#endif + pl.mode_tempstate = 1; + Weapons_ViewPunchAngle([-5,0,0]); + pl.w_idle_next = 3.0f; + } else if not (pl.w_idle_next > 0.0f) { + /* wait 3 seconds (idle next) */ + if (pl.mode_tempstate == 1) { +#ifdef SERVER + sound(pl, CHAN_WEAPON, "weapons/egon_run3.wav", 1, ATTN_NORM, 100); +#endif + pl.mode_tempstate = 2; + } + pl.w_idle_next = 3.0f; + } + + pl.w_attack_next = 0.2f; +} + +void w_egon_reload(void) +{ + +} + +void w_egon_release(void) +{ + player pl = (player)self; + +#ifdef CLIENT + FXEgon p = (FXEgon)pSeat->m_pWeaponFX; + p.m_vecAngle = input_angles; + p.m_vecStart = pl.origin + pl.view_ofs; + p.alpha = 0.0f; +#endif + + if (pl.mode_tempstate != 0) { +#ifdef SERVER + sound(pl, CHAN_WEAPON, "weapons/egon_off1.wav", 1, ATTN_NORM, 100, 0); +#endif + pl.mode_tempstate = 0; + Weapons_ViewPunchAngle([-2,0,0]); + } + +#ifndef SERVER + if (Weapons_GetAnimation() == EGON_ALTFIRECYCLE) { + Weapons_ViewAnimation(EGON_ALTFIREOFF); + pl.w_idle_next = 1.0f; + } else { + if (pl.w_idle_next > 0.0f) { + return; + } + int r = (float)input_sequence % 3; + if (r == 1) { + Weapons_ViewAnimation(EGON_FIDGET1); + pl.w_idle_next = 2.666667f; + } else { + Weapons_ViewAnimation(EGON_IDLE1); + pl.w_idle_next = 2.0f; + } + } +#endif +} +void w_egon_crosshair(void) +{ +#ifdef CLIENT + static vector cross_pos; + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + drawsubpic(cross_pos, [24,24], g_cross_spr, [72/128,48/128], [0.1875, 0.1875], [1,1,1], 1, DRAWFLAG_NORMAL); + 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/128], [24/256, 24/128], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +float w_egon_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMEGON : ANIM_AIMEGON; +} + +void w_egon_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.ammo_uranium == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + if (selected) { + drawsubpic(pos, [170,45], g_hud5_spr, [0,135/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE); + } else { + drawsubpic(pos, [170,45], g_hud2_spr, [0,135/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE); + } + + HUD_DrawAmmoBar(pos, pl.ammo_uranium, MAX_A_URANIUM, a); +#endif +} + +weapon_t w_egon = +{ + .name = "egon", + .id = ITEM_EGON, + .slot = 3, + .slot_pos = 2, + .draw = w_egon_draw, + .holster = w_egon_holster, + .primary = w_egon_primary, + .secondary = w_egon_release, + .reload = w_egon_reload, + .release = w_egon_release, + .crosshair = w_egon_crosshair, + .precache = w_egon_precache, + .pickup = w_egon_pickup, + .updateammo = w_egon_updateammo, + .wmodel = w_egon_wmodel, + .pmodel = w_egon_pmodel, + .deathmsg = w_egon_deathmsg, + .aimanim = w_egon_aimanim, + .hudpic = w_egon_hudpic +}; + +#ifdef SERVER +void weapon_egon(void) { + Weapons_InitItem(WEAPON_EGON); +} +#endif diff --git a/src/shared/w_gauss.qc b/src/shared/w_gauss.qc new file mode 100644 index 0000000..ec1c407 --- /dev/null +++ b/src/shared/w_gauss.qc @@ -0,0 +1,506 @@ +/* + * 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_gauss (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_gauss.mdl" + +HALF-LIFE (1998) ENTITY + +Gauss Weapon + +*/ + +#ifdef CLIENT +#define FXGAUSS_BEAMCOLOR [1,0.5,0] +class FXGauss:CBaseFX +{ + int m_iBeams; + vector m_vecStart; + vector m_vecAngle; + + void(void) FXGauss; + virtual void(void) Draw; +}; + +void +FXGauss::Draw(void) +{ + player pl = (player)self; + int iLoop = 6; + vector src, endpos; + vector gunpos = gettaginfo(pSeat->m_eViewModel, 33); + + if (alpha <= 0.0f) { + return; + } + + src = m_vecStart; + makevectors(input_angles); + endpos = src + v_forward * 1024; + traceline(src, endpos, FALSE, pl); + + /* drawing the first bit */ + vector fsize = [3,3]; + makevectors(view_angles); + R_BeginPolygon("sprites/xbeam1.spr_0.tga", 1, 0); + R_PolygonVertex(gunpos + v_right * fsize[0] - v_up * fsize[1], + [1,1], FXGAUSS_BEAMCOLOR, alpha); + R_PolygonVertex(gunpos - v_right * fsize[0] - v_up * fsize[1], + [0,1], FXGAUSS_BEAMCOLOR, alpha); + R_PolygonVertex(trace_endpos - v_right * fsize[0] + v_up * fsize[1], + [0,0], FXGAUSS_BEAMCOLOR, alpha); + R_PolygonVertex(trace_endpos + v_right * fsize[0] + v_up * fsize[1], + [1,0], FXGAUSS_BEAMCOLOR, alpha); + R_EndPolygon(); + + if (m_iBeams == 0) { + alpha -= clframetime * 3; + return; + } + + // reflection equation: + vector x = v_forward; + while (iLoop > 0) { + float n; + vector r; + n = -dotproduct(trace_plane_normal, x); + r = 2 * trace_plane_normal * n + x; + x = r; + src = trace_endpos + (x * 1); + endpos = trace_endpos + (x * 8192); + traceline(src, endpos, FALSE, pl); + + makevectors(view_angles); + R_BeginPolygon("sprites/xbeam1.spr_0.tga", 1, 0); + R_PolygonVertex(src + v_right * fsize[0] - v_up * fsize[1], + [1,1], FXGAUSS_BEAMCOLOR, alpha); + R_PolygonVertex(src - v_right * fsize[0] - v_up * fsize[1], + [0,1], FXGAUSS_BEAMCOLOR, alpha); + R_PolygonVertex(trace_endpos - v_right * fsize[0] + v_up * fsize[1], + [0,0], FXGAUSS_BEAMCOLOR, alpha); + R_PolygonVertex(trace_endpos + v_right * fsize[0] + v_up * fsize[1], + [1,0], FXGAUSS_BEAMCOLOR, alpha); + R_EndPolygon(); + + iLoop--; + } + alpha -= clframetime * 3; +} + +void +FXGauss::FXGauss(void) +{ + CBaseFX::CBaseFX(); +} +#endif + +enum +{ + GAUSS_IDLE1, + GAUSS_IDLE2, + GAUSS_FIDGET, + GAUSS_SPINUP, + GAUSS_SPIN, + GAUSS_FIRE1, + GAUSS_FIRE2, + GAUSS_HOLSTER, + GAUSS_DRAW +}; + +void w_gauss_release(void); + +void w_gauss_precache(void) +{ +#ifdef SERVER + precache_model("models/w_gauss.mdl"); + precache_model("sprites/yelflare1.spr"); + precache_model("sprites/xbeam1.spr"); + precache_sound("weapons/electro4.wav"); + precache_sound("weapons/electro5.wav"); + precache_sound("weapons/electro6.wav"); + precache_sound("weapons/gauss2.wav"); +#else + precache_sound("ambience/pulsemachine.wav"); + precache_model("models/v_gauss.mdl"); + precache_model("models/p_gauss.mdl"); +#endif +} +void w_gauss_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, pl.ammo_uranium, -1); +} +string w_gauss_wmodel(void) +{ + return "models/w_gauss.mdl"; +} +string w_gauss_pmodel(void) +{ + return "models/p_gauss.mdl"; +} +string w_gauss_deathmsg(void) +{ + return ""; +} + +int w_gauss_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (pl.ammo_uranium < MAX_A_URANIUM) { + pl.ammo_uranium = bound(0, pl.ammo_uranium + 20, MAX_A_URANIUM); + } else { + return FALSE; + } +#endif + return TRUE; +} + +void w_gauss_draw(void) +{ + player pl = (player)self; + pl.mode_tempstate = 0; + + /* link the FX class */ +#ifdef CLIENT + Weapons_SetModel("models/v_gauss.mdl"); + Weapons_ViewAnimation(GAUSS_DRAW); + + entity eold = self; + self = pSeat->m_pWeaponFX; + spawnfunc_FXGauss(); + self = eold; +#endif +} + +void w_gauss_holster(void) +{ + Weapons_ViewAnimation(GAUSS_HOLSTER); +} + +#ifdef SERVER +void w_gauss_fire(int one) +{ + player pl = (player)self; + int iLoop = 6; + + Weapons_MakeVectors(); + vector src = Weapons_GetCameraPos(); + vector endpos = src + v_forward * 1024; + traceline(src, endpos, FALSE, pl); + sound(pl, CHAN_WEAPON, "weapons/gauss2.wav", 1, ATTN_NORM); + int iDamage = one ? 20 : 200; + + if (getsurfacetexture(trace_ent, getsurfacenearpoint(trace_ent, trace_endpos)) == "sky") { + return; + } + + if (trace_ent.takedamage == DAMAGE_YES) { + Damage_Apply(trace_ent, self, iDamage, WEAPON_GAUSS, DMG_ELECTRO); + sound(trace_ent, CHAN_ITEM, sprintf("weapons/electro%d.wav", random(0,3)+4), 1, ATTN_NORM); + } + if (one) { + return; + } else { + /* Apply force */ + if (pl.flags & FL_ONGROUND) { + pl.velocity += v_forward * -400; + } else { + pl.velocity += v_forward * -800; + } + } + + // reflection equation: + vector dir = v_forward; + while (iLoop > 0) { + float n; + vector r; + n = -dotproduct(trace_plane_normal, dir); + r = 2 * trace_plane_normal * n + dir; + dir = r; + src = trace_endpos + (dir * 1); + endpos = trace_endpos + (dir * 8192); + traceline(src, endpos, FALSE, pl); + te_beam(world, src, trace_endpos); + iLoop--; + if (trace_ent.takedamage == DAMAGE_YES) { + Damage_Apply(trace_ent, self, iDamage, WEAPON_GAUSS, DMG_ELECTRO); + sound(trace_ent, CHAN_ITEM, sprintf("weapons/electro%d.wav", random(0,3)+4), 1, ATTN_NORM); + } + + if (getsurfacetexture(trace_ent, getsurfacenearpoint(trace_ent, trace_endpos)) != "sky") { + Decals_Place(trace_endpos, "{gaussshot1"); + } else { + break; + } + } +} +#endif + +void w_gauss_primary(void) +{ + player pl = (player)self; + if (pl.w_attack_next > 0.0) { + return; + } + + /* Ammo check */ +#ifdef CLIENT + if (pl.a_ammo2 < 2) { + return; + } +#else + if (pl.ammo_uranium < 2) { + return; + } +#endif + + Weapons_ViewAnimation(GAUSS_FIRE2); +#ifdef CLIENT + FXGauss p = (FXGauss)pSeat->m_pWeaponFX; + p.m_iBeams = 0; + p.m_vecAngle = input_angles; + p.m_vecStart = pl.origin + pl.view_ofs; + p.alpha = 1.0f; + pl.a_ammo2 -= 2; + Weapons_ViewPunchAngle([-2,0,0]); +#else + pl.ammo_uranium -= 2; + w_gauss_fire(1); +#endif + + pl.w_attack_next = 0.2f; + pl.w_idle_next = 2.5f; +} +void w_gauss_secondary(void) +{ + player pl = (player)self; + +#ifdef CLIENT + if (pl.mode_tempstate) + soundupdate(pl, CHAN_WEAPON, "", 2, ATTN_NORM, 100 + (200 * (pl.ammo_gauss_volume/255)), 0, 0); +#endif + + if (pl.w_attack_next) { + return; + } + pl.w_attack_next = 0.1f; + + /* Ammo check */ +#ifdef CLIENT + if (pl.a_ammo2 <= 0) { + if (pl.mode_tempstate > 0) { + w_gauss_release(); + } + return; + } +#else + if (pl.ammo_uranium <= 0) { + if (pl.mode_tempstate > 0) { + w_gauss_release(); + } + return; + } +#endif + +#ifdef CLIENT + if (pl.ammo_gauss_volume < 255) + pl.a_ammo2--; +#else + if (pl.ammo_gauss_volume < 255) + pl.ammo_uranium--; +#endif + + /* Set pitch sound shift */ + pl.ammo_gauss_volume += 16; + if (pl.ammo_gauss_volume > 255) { + pl.ammo_gauss_volume = 255; + } + + if (pl.mode_tempstate == 1) { + Weapons_ViewAnimation(GAUSS_SPIN); + pl.mode_tempstate = 2; + pl.w_idle_next = 0.0f; + } else if (!pl.mode_tempstate) { + Weapons_ViewAnimation(GAUSS_SPINUP); +#ifdef CLIENT + sound(pl, CHAN_WEAPON, "ambience/pulsemachine.wav", 2, ATTN_NORM); +#endif + pl.mode_tempstate = 1; + } +} + +void w_gauss_release(void) +{ + player pl = (player)self; + if (pl.w_idle_next > 0.0) { + return; + } + + /* Reset the pitch sound shift */ + pl.ammo_gauss_volume = 0; + + if (pl.mode_tempstate == 1) { + pl.w_attack_next = 0.0f; + pl.w_idle_next = 4.0f; + w_gauss_primary(); + pl.mode_tempstate = 0; + return; + } else if (pl.mode_tempstate == 2) { + Weapons_ViewAnimation(GAUSS_FIRE1); +#ifdef CLIENT + FXGauss p = (FXGauss)pSeat->m_pWeaponFX; + p.m_iBeams = 1; + p.m_vecAngle = input_angles; + p.m_vecStart = pl.origin + pl.view_ofs; + p.alpha = 1.0f; + soundupdate(pl, CHAN_WEAPON, "", -1, ATTN_NORM, 0, 0, 0); + Weapons_ViewPunchAngle([-5,0,0]); +#else + w_gauss_fire(0); +#endif + pl.w_attack_next = 1.5f; + pl.w_idle_next = 4.0f; + pl.mode_tempstate = 0; + return; + } + + int r = (float)input_sequence % 3; + switch (r) { + case 1: + Weapons_ViewAnimation(GAUSS_IDLE2); + pl.w_idle_next = 4.0f; + break; +#ifndef GEARBOX + case 2: + Weapons_ViewAnimation(GAUSS_FIDGET); + pl.w_idle_next = 3.0f; + break; +#endif + default: + Weapons_ViewAnimation(GAUSS_IDLE1); + pl.w_idle_next = 4.0f; + break; + } +} + +void w_gauss_crosshair(void) +{ +#ifdef CLIENT + vector cross_pos; + vector aicon_pos; + + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + + drawsubpic( + cross_pos, + [24,24], + g_cross_spr, + [48/128,48/128], + [0.1875, 0.1875], + [1,1,1], + 1, + DRAWFLAG_NORMAL + ); + + drawsubpic( + aicon_pos, + [24,24], + g_hud7_spr, + [0,96/128], + [24/256,24/128], + g_hud_color, + pSeat->m_flAmmo2Alpha, + DRAWFLAG_ADDITIVE + ); + + HUD_DrawAmmo2(); +#endif +} + +float w_gauss_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMGAUSS : ANIM_AIMGAUSS; +} + +void w_gauss_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.ammo_uranium == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud5_spr, + [0,90/256], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud2_spr, + [0,90/256], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } + + HUD_DrawAmmoBar(pos, pl.ammo_uranium, MAX_A_URANIUM, a); +#endif +} + +weapon_t w_gauss = +{ + .name = "gauss", + .id = ITEM_GAUSS, + .slot = 3, + .slot_pos = 1, + .draw = w_gauss_draw, + .holster = w_gauss_holster, + .primary = w_gauss_primary, + .secondary = w_gauss_secondary, + .reload = __NULL__, + .release = w_gauss_release, + .crosshair = w_gauss_crosshair, + .precache = w_gauss_precache, + .pickup = w_gauss_pickup, + .updateammo = w_gauss_updateammo, + .wmodel = w_gauss_wmodel, + .pmodel = w_gauss_pmodel, + .deathmsg = w_gauss_deathmsg, + .aimanim = w_gauss_aimanim, + .hudpic = w_gauss_hudpic +}; + +#ifdef SERVER +void weapon_gauss(void) { + Weapons_InitItem(WEAPON_GAUSS); +} +#endif diff --git a/src/shared/w_glock.qc b/src/shared/w_glock.qc new file mode 100644 index 0000000..d6918cf --- /dev/null +++ b/src/shared/w_glock.qc @@ -0,0 +1,384 @@ +/* + * 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_9mmhandgun (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_9mmhandgun.mdl" + +HALF-LIFE (1998) ENTITY + +9mm Handgun/Glock Weapon +Same as weapon_glock + +*/ + +/*QUAKED weapon_glock (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_9mmhandgun.mdl" + +HALF-LIFE (1998) ENTITY + +9mm Handgun/Glock Weapon +Same as weapon_9mmhandgun + +*/ + +enum +{ + GLOCK_IDLE1, + GLOCK_IDLE2, + GLOCK_IDLE3, + GLOCK_SHOOT, + GLOCK_SHOOT_EMPTY, + GLOCK_RELOAD_EMPTY, + GLOCK_RELOAD, + GLOCK_DRAW, + GLOCK_HOLSTER +}; + +void +w_glock_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_glock.fire"); + precache_model("models/w_9mmhandgun.mdl"); +#else + precache_model("models/v_9mmhandgun.mdl"); + precache_model("models/p_9mmhandgun.mdl"); +#endif +} + +void +w_glock_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.glock_mag, pl.ammo_9mm, -1); +} + +string +w_glock_wmodel(void) +{ + return "models/w_9mmhandgun.mdl"; +} + +string +w_glock_pmodel(void) +{ + return "models/p_9mmhandgun.mdl"; +} + +string +w_glock_deathmsg(void) +{ + return ""; +} + +int +w_glock_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + pl.glock_mag = 18; + } else { + if (pl.ammo_9mm < MAX_A_9MM) { + pl.ammo_9mm = bound(0, pl.ammo_9mm + 18, MAX_A_9MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_glock_draw(void) +{ +#ifdef CLIENT + Weapons_SetModel("models/v_9mmhandgun.mdl"); + Weapons_ViewAnimation(GLOCK_DRAW); +#endif +} + +void +w_glock_holster(void) +{ +#ifdef CLIENT + Weapons_ViewAnimation(GLOCK_HOLSTER); +#endif +} + +void +w_glock_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* ammo check */ + if (!pl.glock_mag) { + return; + } + + /* actual firing */ + pl.glock_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_SMALL); + Weapons_ViewPunchAngle([-2,0,0]); + + if (pl.glock_mag) { + Weapons_ViewAnimation(GLOCK_SHOOT); + } else { + Weapons_ViewAnimation(GLOCK_SHOOT_EMPTY); + } +#else + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, Skill_GetValue("plr_9mm_bullet", 8), [0.01,0.01], WEAPON_GLOCK); + Sound_Play(pl, CHAN_WEAPON, "weapon_glock.fire"); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT1HAND, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CR_SHOOT1HAND, 0.45f); +#endif + + pl.w_attack_next = 0.3f; + pl.w_idle_next = 5.0f; +} + +void +w_glock_secondary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0) { + return; + } + + /* ammo check */ + if (!pl.glock_mag) { + return; + } + + pl.glock_mag--; + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_SMALL); + Weapons_ViewPunchAngle([-2,0,0]); + + if (pl.glock_mag) { + Weapons_ViewAnimation(GLOCK_SHOOT); + } else { + Weapons_ViewAnimation(GLOCK_SHOOT_EMPTY); + } +#else + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, Skill_GetValue("plr_9mm_bullet", 8), [0.1,0.1], WEAPON_GLOCK); + Sound_Play(pl, CHAN_WEAPON, "weapon_glock.fire"); + + if (self.flags & FL_CROUCHING) + Animation_PlayerTopTemp(ANIM_SHOOT1HAND, 0.45f); + else + Animation_PlayerTopTemp(ANIM_CR_SHOOT1HAND, 0.45f); +#endif + + pl.w_attack_next = 0.2f; + pl.w_idle_next = 5.0f; +} + +void +w_glock_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + if (pl.glock_mag >= 18) { + return; + } + if (pl.ammo_9mm <= 0) { + return; + } + + if (pl.glock_mag) { + Weapons_ViewAnimation(GLOCK_RELOAD); + } else { + Weapons_ViewAnimation(GLOCK_RELOAD_EMPTY); + } + +#ifdef SERVER + Weapons_ReloadWeapon(pl, player::glock_mag, player::ammo_9mm, 18); +#endif + + pl.w_attack_next = 2.0f; + pl.w_idle_next = 10.0f; +} + +void +w_glock_release(void) +{ + player pl = (player)self; + int r; + + /* auto-reload if need be */ + if (pl.w_attack_next <= 0.0) + if (pl.glock_mag == 0 && pl.ammo_9mm > 0) { + Weapons_Reload(); + return; + } + + if (pl.w_idle_next > 0.0) { + return; + } + + r = (float)input_sequence % 3; + switch (r) { + case 1: + Weapons_ViewAnimation(GLOCK_IDLE2); + pl.w_idle_next = 2.5f; + break; + case 2: + Weapons_ViewAnimation(GLOCK_IDLE3); + pl.w_idle_next = 3.5f; + break; + default: + Weapons_ViewAnimation(GLOCK_IDLE1); + pl.w_idle_next = 3.75f; + break; + } +} + +float +w_glock_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIM1HAND : ANIM_AIM1HAND; +} + +void +w_glock_hud(void) +{ +#ifdef CLIENT + vector cross_pos; + vector aicon_pos; + + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + + drawsubpic( + cross_pos, + [24,24], + g_cross_spr, + [0.1875,0], + [0.1875, 0.1875], + [1,1,1], + 1.0f, + DRAWFLAG_NORMAL + ); + + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + + drawsubpic( + aicon_pos, + [24,24], + g_hud7_spr, + [0,72/128], + [24/256, 24/128], + g_hud_color, + pSeat->m_flAmmo2Alpha, + DRAWFLAG_ADDITIVE + ); +#endif +} + +void +w_glock_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.glock_mag == 0 && pl.ammo_9mm == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud4_spr, + [0,45/256], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud1_spr, + [0,45/256], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } + + HUD_DrawAmmoBar(pos, pl.ammo_9mm, MAX_A_9MM, a); +#endif +} + +weapon_t w_glock = +{ + .name = "9mmhandgun", + .id = ITEM_GLOCK, + .slot = 1, + .slot_pos = 0, + .draw = w_glock_draw, + .holster = w_glock_holster, + .primary = w_glock_primary, + .secondary = w_glock_secondary, + .reload = w_glock_reload, + .release = w_glock_release, + .crosshair = w_glock_hud, + .precache = w_glock_precache, + .pickup = w_glock_pickup, + .updateammo = w_glock_updateammo, + .wmodel = w_glock_wmodel, + .pmodel = w_glock_pmodel, + .deathmsg = w_glock_deathmsg, + .aimanim = w_glock_aimanim, + .hudpic = w_glock_hudpic +}; + +/* pickups */ +#ifdef SERVER +void +weapon_9mmhandgun(void) +{ + Weapons_InitItem(WEAPON_GLOCK); +} + +void +weapon_glock(void) +{ + Weapons_InitItem(WEAPON_GLOCK); +} +#endif diff --git a/src/shared/w_handgrenade.qc b/src/shared/w_handgrenade.qc new file mode 100644 index 0000000..93cedef --- /dev/null +++ b/src/shared/w_handgrenade.qc @@ -0,0 +1,274 @@ +/* + * 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_handgrenade (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_grenade.mdl" + +HALF-LIFE (1998) ENTITY + +Handgrenade Weapon + +*/ + +enum +{ + HANDGRENADE_IDLE, + HANDGRENADE_FIDGET, + HANDGRENADE_PULLPIN, + HANDGRENADE_THROW1, + HANDGRENADE_THROW2, + HANDGRENADE_THROW3, + HANDGRENADE_HOLSTER, + HANDGRENADE_DRAW +}; + +void w_handgrenade_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_handgrenade.bounce"); + precache_model("models/w_grenade.mdl"); +#else + precache_model("models/v_grenade.mdl"); + precache_model("models/p_grenade.mdl"); +#endif +} +void w_handgrenade_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, pl.ammo_handgrenade, -1); +} +string w_handgrenade_wmodel(void) +{ + return "models/w_grenade.mdl"; +} +string w_handgrenade_pmodel(void) +{ + return "models/p_grenade.mdl"; +} +string w_handgrenade_deathmsg(void) +{ + return ""; +} + +int w_handgrenade_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (pl.ammo_handgrenade < MAX_A_HANDGRENADE) { + pl.ammo_handgrenade = bound(0, pl.ammo_handgrenade + 1, MAX_A_HANDGRENADE); + } else { + return FALSE; + } +#endif + return TRUE; +} + +#ifdef SERVER +void w_handgrenade_throw(void) +{ + static void WeaponFrag_Throw_Explode(void) + { + float dmg = Skill_GetValue("plr_hand_grenade", 150); + FX_Explosion(self.origin); + Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_HANDGRENADE); + sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM); + remove(self); + } + + static void WeaponFrag_Throw_Touch(void) + { + if (other.takedamage == DAMAGE_YES) { + Damage_Apply(other, self.owner, 15, WEAPON_HANDGRENADE, DMG_BLUNT); + } else { + Sound_Play(self, CHAN_BODY, "weapon_handgrenade.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 = WeaponFrag_Throw_Explode; + eGrenade.touch = WeaponFrag_Throw_Touch; + eGrenade.nextthink = time + 4.0f; + setmodel(eGrenade, "models/w_grenade.mdl"); + setsize(eGrenade, [0,0,0], [0,0,0]); + setorigin(eGrenade, vecSrc); +} +#endif + +void w_handgrenade_draw(void) +{ + player pl = (player)self; + pl.mode_tempstate = 0; + +#ifdef CLIENT + Weapons_SetModel("models/v_grenade.mdl"); + Weapons_ViewAnimation(HANDGRENADE_DRAW); +#endif +} + +void w_handgrenade_holster(void) +{ + +} +void w_handgrenade_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_tempstate > 0) { + return; + } + + /* Ammo check */ + if (pl.ammo_handgrenade <= 0) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(HANDGRENADE_PULLPIN); +#endif + + pl.mode_tempstate = 1; + pl.w_attack_next = 0.5f; + pl.w_idle_next = 0.5f; +} + +void w_handgrenade_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/128], [24/256, 24/128], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void w_handgrenade_release(void) +{ + player pl = (player)self; + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.mode_tempstate == 1) { +#ifdef CLIENT + Weapons_ViewAnimation(HANDGRENADE_THROW1); +#else + w_handgrenade_throw(); +#endif + pl.ammo_handgrenade--; + pl.mode_tempstate = 2; + pl.w_attack_next = 1.0f; + pl.w_idle_next = 0.5f; + } else if (pl.mode_tempstate == 2) { +#ifdef CLIENT + Weapons_ViewAnimation(HANDGRENADE_DRAW); +#else + if (!pl.ammo_handgrenade) { + Weapons_RemoveItem(pl, WEAPON_HANDGRENADE); + } +#endif + pl.w_attack_next = 0.5f; + pl.w_idle_next = 0.5f; + pl.mode_tempstate = 0; + } else { + int r = (float)input_sequence % 8; + if (r == 1) { + Weapons_ViewAnimation(HANDGRENADE_FIDGET); + pl.w_idle_next = 2.5f; + } else { + Weapons_ViewAnimation(HANDGRENADE_IDLE); + pl.w_idle_next = 3.0f; + } + } +} + +float +w_handgrenade_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR; +} + +void +w_handgrenade_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + + if (selected) { + drawsubpic(pos, [170,45], g_hud6_spr, [0,0], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE); + } else { + drawsubpic(pos, [170,45], g_hud3_spr, [0,0], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE); + } + + HUD_DrawAmmoBar(pos, pl.ammo_handgrenade, MAX_A_HANDGRENADE, a); +#endif +} + +weapon_t w_handgrenade = +{ + .name = "grenade", + .id = ITEM_HANDGRENADE, + .slot = 4, + .slot_pos = 0, + .draw = w_handgrenade_draw, + .holster = w_handgrenade_holster, + .primary = w_handgrenade_primary, + .secondary = __NULL__, + .reload = __NULL__, + .release = w_handgrenade_release, + .crosshair = w_handgrenade_hud, + .precache = w_handgrenade_precache, + .pickup = w_handgrenade_pickup, + .updateammo = w_handgrenade_updateammo, + .wmodel = w_handgrenade_wmodel, + .pmodel = w_handgrenade_pmodel, + .deathmsg = w_handgrenade_deathmsg, + .aimanim = w_handgrenade_aimanim, + .hudpic = w_handgrenade_hudpic +}; + +#ifdef SERVER +void weapon_handgrenade(void) { + Weapons_InitItem(WEAPON_HANDGRENADE); +} +#endif diff --git a/src/shared/w_hornetgun.qc b/src/shared/w_hornetgun.qc new file mode 100644 index 0000000..1721447 --- /dev/null +++ b/src/shared/w_hornetgun.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_hornetgun (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_hgun.mdl" + +HALF-LIFE (1998) ENTITY + +Hornetgun Weapon + +*/ + +enum +{ + HORNETGUN_IDLE, + HORNETGUN_FIDGET1, + HORNETGUN_FIDGET2, + HORNETGUN_HOLSTER, + HORNETGUN_DRAW, + HORNETGUN_SHOOT +}; + +void +w_hornetgun_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_hornetgun.fire"); + Sound_Precache("weapon_hornetgun.buzz"); + Sound_Precache("weapon_hornetgun.hit"); + precache_model("models/w_hgun.mdl"); + precache_model("models/hornet.mdl"); +#else + precache_model("models/v_hgun.mdl"); + precache_model("models/p_hgun.mdl"); +#endif +} + +int +w_hornetgun_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + /* only pick it up once */ + if (new) { + pl.ammo_hornet = MAX_A_HORNET; + return TRUE; + } +#endif + return FALSE; +} + +void +w_hornetgun_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, pl.ammo_hornet, -1); +} +string w_hornetgun_wmodel(void) +{ + return "models/w_hgun.mdl"; +} +string w_hornetgun_pmodel(void) +{ + return "models/p_hgun.mdl"; +} +string w_hornetgun_deathmsg(void) +{ + return ""; +} + +void +w_hornetgun_draw(void) +{ + Weapons_SetModel("models/v_hgun.mdl"); + Weapons_ViewAnimation(HORNETGUN_DRAW); +} + +void +w_hornetgun_holster(void) +{ + +} + +#ifdef SERVER +void +w_hornetgun_shoothornet(void) +{ + static void Hornet_Touch(void) { + if (other.takedamage == DAMAGE_YES) { + Damage_Apply(other, self.owner, Skill_GetValue("plr_hornet", 10), WEAPON_HORNETGUN, DMG_GENERIC); + Sound_Play(other, CHAN_VOICE, "weapon_hornetgun.hit"); + } else { + Sound_Play(self, CHAN_VOICE, "weapon_hornetgun.buzz"); + } + remove(self); + } + + Weapons_MakeVectors(); + entity bolt = spawn(); + setmodel(bolt, "models/hornet.mdl"); + setorigin(bolt, Weapons_GetCameraPos() + (v_forward * 16) + (v_up * -8)); + bolt.owner = self; + bolt.velocity = v_forward * 1000; + bolt.movetype = MOVETYPE_FLY; + bolt.solid = SOLID_BBOX; + //bolt.flags |= FL_LAGGEDMOVE; + bolt.gravity = 0.5f; + bolt.angles = vectoangles(bolt.velocity); + bolt.touch = Hornet_Touch; + bolt.traileffectnum = particleeffectnum("weapon_hornet.trail"); + setsize(bolt, [0,0,0], [0,0,0]); +} +#endif + +void +w_hornetgun_release(void) +{ + player pl = (player)self; + + if (pl.w_idle_next > 0.0) { + return; + } + + /* slow regeneration of ammunition */ + if (pl.ammo_hornet < MAX_A_HORNET) { + pl.ammo_hornet = bound(0, pl.ammo_hornet + 1, MAX_A_HORNET); + Weapons_UpdateAmmo(pl, -1, pl.ammo_hornet, -1); + pl.w_idle_next = 0.35f; + return; + } + + if (pl.w_idle_next > 0.0) { + return; + } + + int r; + r = (float)input_sequence % 3; + switch (r) { + case 1: + Weapons_ViewAnimation(HORNETGUN_FIDGET1); + pl.w_idle_next = 2.5f; + break; + case 2: + Weapons_ViewAnimation(HORNETGUN_FIDGET2); + pl.w_idle_next = 2.1875f; + break; + default: + Weapons_ViewAnimation(HORNETGUN_IDLE); + pl.w_idle_next = 1.875f; + } +} + +void +w_hornetgun_primary(void) +{ + player pl = (player)self; + if (pl.w_attack_next > 0.0) { + return; + } + + /* Ammo check */ + if (pl.ammo_hornet <= 0) { + w_hornetgun_release(); + return; + } + +#ifdef SERVER + w_hornetgun_shoothornet(); + Sound_Play(pl, CHAN_WEAPON, "weapon_hornetgun.fire"); +#endif + + pl.ammo_hornet--; + Weapons_ViewAnimation(HORNETGUN_SHOOT); + + pl.w_attack_next = 0.25; + pl.w_idle_next = 1.0f; +} + +void +w_hornetgun_secondary(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + + /* Ammo check */ + if (pl.ammo_hornet <= 0) { + w_hornetgun_release(); + return; + } + +#ifdef SERVER + w_hornetgun_shoothornet(); + Weapons_PlaySound(pl, CHAN_WEAPON, sprintf("agrunt/ag_fire%d.wav", floor(random(1,4))), 1, ATTN_NORM); +#endif + + pl.ammo_hornet--; + Weapons_ViewAnimation(HORNETGUN_SHOOT); + + pl.w_attack_next = 0.1; + pl.w_idle_next = 1.0f; +} + +void +w_hornetgun_crosshair(void) +{ +#ifdef CLIENT + vector cross_pos; + vector aicon_pos; + + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + + drawsubpic( + cross_pos, + [24,24], + g_cross_spr, + [72/128,24/128], + [0.1875, 0.1875], + [1,1,1], + 1.0f, + DRAWFLAG_NORMAL + ); + + HUD_DrawAmmo2(); + + drawsubpic( + aicon_pos, + [24,24], + g_hud7_spr, + [24/256,96/128], + [24/256, 24/128], + g_hud_color, + pSeat->m_flAmmo2Alpha, + DRAWFLAG_ADDITIVE + ); +#endif +} + +float +w_hornetgun_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMHIVE : ANIM_AIMHIVE; +} + +void +w_hornetgun_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud5_spr, + [0,180/256], + [170/256,45/256], + g_hud_color, + a, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud2_spr, + [0,180/256], + [170/256,45/256], + g_hud_color, + a, + DRAWFLAG_ADDITIVE + ); + } + + HUD_DrawAmmoBar(pos, pl.ammo_hornet, MAX_A_HORNET, a); +#endif +} + +weapon_t w_hornetgun = +{ + .name = "hornet", + .id = ITEM_HORNETGUN, + .slot = 3, + .slot_pos = 3, + .draw = w_hornetgun_draw, + .holster = w_hornetgun_holster, + .primary = w_hornetgun_primary, + .secondary = w_hornetgun_secondary, + .reload = __NULL__, + .release = w_hornetgun_release, + .crosshair = w_hornetgun_crosshair, + .precache = w_hornetgun_precache, + .pickup = w_hornetgun_pickup, + .updateammo = w_hornetgun_updateammo, + .wmodel = w_hornetgun_wmodel, + .pmodel = w_hornetgun_pmodel, + .deathmsg = w_hornetgun_deathmsg, + .aimanim = w_hornetgun_aimanim, + .hudpic = w_hornetgun_hudpic +}; + +#ifdef SERVER +void +weapon_hornetgun(void) +{ + Weapons_InitItem(WEAPON_HORNETGUN); +} +#endif diff --git a/src/shared/w_mp5.qc b/src/shared/w_mp5.qc new file mode 100644 index 0000000..6f8a882 --- /dev/null +++ b/src/shared/w_mp5.qc @@ -0,0 +1,405 @@ +/* + * 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_9mmAR (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_9mmar.mdl" + +HALF-LIFE (1998) ENTITY + +MP5/9mmAR Weapon +Same as weapon_mp5 + +*/ + +/*QUAKED weapon_mp5 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_9mmar.mdl" + +HALF-LIFE (1998) ENTITY + +MP5/9mmAR Weapon +Same as weapon_9mmAR + +*/ + +/* Animations */ +enum +{ + MP5_IDLE1, + MP5_IDLE2, + MP5_GRENADE, + MP5_RELOAD, + MP5_DRAW, +#ifdef GEARBOX + MP5_DEPLOY, /* not sure what this is about */ +#endif + MP5_FIRE1, + MP5_FIRE2, + MP5_FIRE3 +}; + +void +w_mp5_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_mp5.shoot"); + Sound_Precache("weapon_mp5.gl"); + precache_model("models/w_9mmar.mdl"); + precache_model("models/grenade.mdl"); +#else + precache_model("models/v_9mmar.mdl"); + precache_model("models/p_9mmar.mdl"); +#endif +} + +int +w_mp5_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + pl.mp5_mag = 25; + } else { + if (pl.ammo_9mm < MAX_A_9MM) { + pl.ammo_9mm = bound(0, pl.ammo_9mm + 25, MAX_A_9MM); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_mp5_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.mp5_mag, pl.ammo_9mm, pl.ammo_m203_grenade); +} + +string +w_mp5_wmodel(void) +{ + return "models/w_9mmar.mdl"; +} + +string +w_mp5_pmodel(void) +{ + return "models/p_9mmar.mdl"; +} + +string +w_mp5_deathmsg(void) +{ + return ""; +} + +void +w_mp5_draw(void) +{ +#ifdef CLIENT + Weapons_SetModel("models/v_9mmar.mdl"); + Weapons_ViewAnimation(MP5_DRAW); +#endif +} + +void +w_mp5_holster(void) +{ + Weapons_ViewAnimation(MP5_DRAW); +} + +void +w_mp5_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* Ammo check */ + if (pl.mp5_mag <= 0) { + return; + } + +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_RIFLE); +#else + /* singleplayer is more accurate */ + if (cvar("sv_playerslots") == 1) { + TraceAttack_FireBullets(1, Weapons_GetCameraPos(), Skill_GetValue("plr_9mmAR_bullet", 5), [0.025,0.025], WEAPON_MP5); + } else { + TraceAttack_FireBullets(1, Weapons_GetCameraPos(), Skill_GetValue("plr_9mmAR_bullet", 5), [0.05,0.05], WEAPON_MP5); + } + + Sound_Play(pl, CHAN_WEAPON, "weapon_mp5.shoot"); +#endif + + pl.mp5_mag--; + + /* Actual firing */ + int r = (float)input_sequence % 2; + if (r) { + Weapons_ViewAnimation(MP5_FIRE1); + } else { + Weapons_ViewAnimation(MP5_FIRE2); + } + + Weapons_ViewPunchAngle([-2,0,0]); + + pl.w_attack_next = 0.1f; + pl.w_idle_next = 10.0f; +} + +void +w_mp5_secondary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + + if (pl.ammo_m203_grenade <= 0) { + return; + } + + pl.ammo_m203_grenade--; + +#ifdef CLIENT + Weapons_ViewPunchAngle([-10,0,0]); + Weapons_ViewAnimation(MP5_GRENADE); +#else + static void Grenade_ExplodeTouch(void) { + float dmg = Skill_GetValue("plr_9mmAR_grenade", 100); + FX_Explosion(self.origin); + Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_MP5); + + if (random() < 0.5) { + sound(self, 1, "weapons/explode3.wav", 1, ATTN_NORM); + } else { + sound(self, 1, "weapons/explode4.wav", 1, ATTN_NORM); + } + remove(self); + } + + Weapons_MakeVectors(); + entity gren = spawn(); + setmodel(gren, "models/grenade.mdl"); + setorigin(gren, Weapons_GetCameraPos() + (v_forward * 16)); + gren.owner = self; + gren.velocity = v_forward * 800; + gren.angles = vectoangles(gren.velocity); + gren.avelocity[0] = random(-100, -500); + gren.gravity = 0.5f; + gren.movetype = MOVETYPE_BOUNCE; + //gren.flags |= FL_LAGGEDMOVE; + gren.solid = SOLID_BBOX; + setsize(gren, [0,0,0], [0,0,0]); + gren.touch = Grenade_ExplodeTouch; + Sound_Play(pl, CHAN_WEAPON, "weapon_mp5.gl"); +#endif + + pl.w_attack_next = 1.0f; + pl.w_idle_next = 10.0f; +} + +void +w_mp5_reload(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + + /* Ammo check */ + if (pl.mp5_mag >= 50) { + return; + } + if (pl.ammo_9mm <= 0) { + return; + } + +#ifdef CLIENT + Weapons_ViewAnimation(MP5_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::mp5_mag, player::ammo_9mm, 50); +#endif + + pl.w_attack_next = 1.5f; + pl.w_idle_next = 10.0f; +} + +void +w_mp5_release(void) +{ + player pl = (player)self; + + /* auto-reload if need be */ + if (pl.w_attack_next <= 0.0) + if (pl.mp5_mag == 0 && pl.ammo_9mm > 0) { + Weapons_Reload(); + return; + } + if (pl.w_idle_next > 0.0) { + return; + } + + int r = (float)input_sequence % 3; + if (r == 1) { + Weapons_ViewAnimation(MP5_IDLE1); + } else { + Weapons_ViewAnimation(MP5_IDLE2); + } + + pl.w_idle_next = 15.0f; +} + +void +w_mp5_crosshair(void) +{ +#ifdef CLIENT + vector cross_pos; + vector aicon_pos; + + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + + drawsubpic( + cross_pos, + [24,24], + g_cross_spr, + [24/128,48/128], + [0.1875, 0.1875], + [1,1,1], + 1.0f, + DRAWFLAG_NORMAL + ); + + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + HUD_DrawAmmo3(); + + aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic( + aicon_pos, + [24,24], + g_hud7_spr, + [0,72/128], + [24/256, 24/128], + g_hud_color, + pSeat->m_flAmmo2Alpha, + DRAWFLAG_ADDITIVE + ); + + aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 74]; + drawsubpic( + aicon_pos, + [24,24], + g_hud7_spr, + [48/256,72/128], + [24/256, 24/128], + g_hud_color, + pSeat->m_flAmmo3Alpha, + DRAWFLAG_ADDITIVE + ); +#endif +} + +float +w_mp5_aimanim(void) +{ + return self.flags & ANIM_CR_AIMMP5 ? ANIM_CR_AIMCROWBAR : ANIM_AIMMP5; +} + +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 && pl.ammo_m203_grenade == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud4_spr, + [0,135/256], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud1_spr, + [0,135/256], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } + + HUD_DrawAmmoBar(pos, pl.ammo_9mm, MAX_A_9MM, a); + HUD_DrawAmmoBar(pos + [25, 0], pl.ammo_m203_grenade, MAX_A_M203_GRENADE, a); +#endif +} + +weapon_t w_mp5 = +{ + .name = "9mmAR", + .id = ITEM_MP5, + .slot = 2, + .slot_pos = 0, + .draw = w_mp5_draw, + .holster = w_mp5_holster, + .primary = w_mp5_primary, + .secondary = w_mp5_secondary, + .reload = w_mp5_reload, + .release = w_mp5_release, + .crosshair = w_mp5_crosshair, + .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_9mmAR(void) +{ + Weapons_InitItem(WEAPON_MP5); +} + +void +weapon_mp5(void) +{ + Weapons_InitItem(WEAPON_MP5); +} +#endif diff --git a/src/shared/w_python.qc b/src/shared/w_python.qc new file mode 100644 index 0000000..a475116 --- /dev/null +++ b/src/shared/w_python.qc @@ -0,0 +1,368 @@ +/* + * 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_357 (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_357.mdl" + +HALF-LIFE (1998) ENTITY + +357/Python Weapon +Same as weapon_python + +*/ + +/*QUAKED weapon_python (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_357.mdl" + +HALF-LIFE (1998) ENTITY + +357/Python Weapon +Same as weapon_357 + +*/ + +enum +{ + PYTHON_IDLE1, + PYTHON_FIDGET, + PYTHON_FIRE1, + PYTHON_RELOAD, + PYTHON_HOLSTER, + PYTHON_DRAW, + PYTHON_IDLE2, + PYTHON_IDLE3 +}; + +void +w_python_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_357.shoot"); + Sound_Precache("weapon_357.reload"); + precache_model("models/w_357.mdl"); +#else + precache_model("models/v_357.mdl"); + precache_model("models/p_357.mdl"); +#endif +} + +int +w_python_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + pl.python_mag = 6; + } else { + if (pl.ammo_357 < MAX_A_357) { + pl.ammo_357 = bound(0, pl.ammo_357 + 6, MAX_A_357); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_python_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.python_mag, pl.ammo_357, -1); +} + +string +w_python_wmodel(void) +{ + return "models/w_357.mdl"; +} + +string +w_python_pmodel(void) +{ + return "models/p_357.mdl"; +} + +string +w_python_deathmsg(void) +{ + return ""; +} + +void +w_python_draw(void) +{ +#ifdef CLIENT + Weapons_SetModel("models/v_357.mdl"); + + /* singleplayer doesn't do scope */ + if (cvar("sv_playerslots") == 1) { + Weapons_SetGeomset("geomset 4 1\n"); + } else { + Weapons_SetGeomset("geomset 4 2\n"); + } + Weapons_ViewAnimation(PYTHON_DRAW); +#endif +} + +void +w_python_holster(void) +{ +#ifdef CLIENT + Weapons_ViewAnimation(PYTHON_HOLSTER); +#endif +} + +void +w_python_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* Ammo check */ + if (pl.python_mag <= 0) { + return; + } + + pl.python_mag--; + + /* Actual firing */ +#ifdef CLIENT + View_SetMuzzleflash(MUZZLE_SMALL); + Weapons_ViewPunchAngle([-10,0,0]); + Weapons_ViewAnimation(PYTHON_FIRE1); +#else + TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, Skill_GetValue("plr_357_bullet", 40), [0.008, 0.008], WEAPON_PYTHON); + Sound_Play(pl, CHAN_WEAPON, "weapon_357.shoot"); +#endif + + pl.w_attack_next = 0.75f; + pl.w_idle_next = 10.0f; +} + +void +w_python_secondary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* singleplayer doesn't do scope */ + if (cvar("sv_playerslots") == 1) { + return; + } + + /* Simple toggle of fovs */ + if (pl.viewzoom == 1.0f) { + pl.viewzoom = 0.5f; + } else { + pl.viewzoom = 1.0f; + } + + pl.w_attack_next = 0.25f; +} + +void +w_python_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* Ammo check */ + if (pl.python_mag >= 6) { + return; + } + if (pl.ammo_357 <= 0) { + return; + } + + /* Audio-Visual bit */ +#ifdef CLIENT + Weapons_ViewAnimation(PYTHON_RELOAD); +#else + Sound_Play(pl, CHAN_WEAPON, "weapon_357.reload"); + Weapons_ReloadWeapon(pl, player::python_mag, player::ammo_357, 6); +#endif + + pl.w_attack_next = 3.25f; + pl.w_idle_next = 10.0f; +} + +void +w_python_release(void) +{ + player pl = (player)self; + + /* auto-reload if need be */ + if (pl.w_attack_next <= 0.0) + if (pl.python_mag == 0 && pl.ammo_357 > 0) { + Weapons_Reload(); + return; + } + + if (pl.w_idle_next > 0.0) { + return; + } + + int r = (float)input_sequence % 4; + + switch (r) { + case 1: + Weapons_ViewAnimation(PYTHON_IDLE1); + pl.w_idle_next = 2.33f; + break; + case 2: + Weapons_ViewAnimation(PYTHON_FIDGET); + pl.w_idle_next = 5.66f; + break; + case 3: + Weapons_ViewAnimation(PYTHON_IDLE2); + pl.w_idle_next = 2.0f; + break; + default: + Weapons_ViewAnimation(PYTHON_IDLE3); + pl.w_idle_next = 2.93f; + break; + } +} + +void +w_python_crosshair(void) +{ +#ifdef CLIENT + vector cross_pos; + vector aicon_pos; + + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + drawsubpic( + cross_pos, + [24,24], + g_cross_spr, + [48/128,0], + [0.1875, 0.1875], + [1,1,1], + 1, + DRAWFLAG_NORMAL + ); + + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + + aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic( + aicon_pos, + [24,24], + g_hud7_spr, + [24/256,72/128], + [24/256, 24/128], + g_hud_color, + pSeat->m_flAmmo2Alpha, + DRAWFLAG_ADDITIVE + ); +#endif +} + +float +w_python_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMPYTHON : ANIM_AIMPYTHON; +} + +void +w_python_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.python_mag == 0 && pl.ammo_357 == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + if (selected) { + drawsubpic( + pos, + [170,45], + g_hud4_spr, + [0,90/256], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } else { + drawsubpic( + pos, + [170,45], + g_hud1_spr, + [0,90/256], + [170/256,45/256], + hud_col, + a, + DRAWFLAG_ADDITIVE + ); + } + + HUD_DrawAmmoBar(pos, pl.ammo_357, MAX_A_357, a); +#endif +} + +weapon_t w_python = +{ + .name = "357", + .id = ITEM_PYTHON, + .slot = 1, + .slot_pos = 1, + .draw = w_python_draw, + .holster = w_python_holster, + .primary = w_python_primary, + .secondary = w_python_secondary, + .reload = w_python_reload, + .release = w_python_release, + .crosshair = w_python_crosshair, + .precache = w_python_precache, + .pickup = w_python_pickup, + .updateammo = w_python_updateammo, + .wmodel = w_python_wmodel, + .pmodel = w_python_pmodel, + .deathmsg = w_python_deathmsg, + .aimanim = w_python_aimanim, + .hudpic = w_python_hudpic +}; + +/* pickups */ +#ifdef SERVER +void +weapon_357(void) +{ + Weapons_InitItem(WEAPON_PYTHON); +} + +void +weapon_python(void) +{ + Weapons_InitItem(WEAPON_PYTHON); +} +#endif diff --git a/src/shared/w_rpg.qc b/src/shared/w_rpg.qc new file mode 100644 index 0000000..18904f4 --- /dev/null +++ b/src/shared/w_rpg.qc @@ -0,0 +1,359 @@ +/* + * 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_rpg (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_rpg.mdl" + +HALF-LIFE (1998) ENTITY + +RPG Weapon + +*/ + +enum +{ + RPG_IDLE, + RPG_FIDGET, + RPG_RELOAD, + RPG_FIRE2, + RPG_HOLSTER1, + RPG_DRAW1, + RPG_HOLSTER2, + RPG_DRAW_UL, + RPG_IDLE_UL, + RPG_FIDGET_UL, +}; + +void w_rpg_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_rpg.shoot"); + precache_model("models/w_rpg.mdl"); + precache_model("models/rpgrocket.mdl"); +#else + precache_model("models/v_rpg.mdl"); + precache_model("models/p_rpg.mdl"); + precache_model("sprites/laserdot.spr"); +#endif +} + +void w_rpg_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.rpg_mag, pl.ammo_rocket, -1); +} +string w_rpg_wmodel(void) +{ + return "models/w_rpg.mdl"; +} +string w_rpg_pmodel(void) +{ + return "models/p_rpg.mdl"; +} +string w_rpg_deathmsg(void) +{ + return ""; +} + +int w_rpg_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + pl.rpg_mag = 1; + } else { + if (pl.ammo_rocket < MAX_A_ROCKET) { + pl.ammo_rocket = bound(0, pl.ammo_rocket + 1, MAX_A_ROCKET); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void w_rpg_draw(void) +{ +#ifdef CLIENT + Weapons_SetModel("models/v_rpg.mdl"); + Weapons_ViewAnimation(RPG_DRAW1); +#endif +} + +void w_rpg_holster(void) +{ + +} + +void w_rpg_primary(void) +{ + player pl = (player)self; + if (pl.w_attack_next > 0.0) { + return; + } + + /* Ammo check */ + if (pl.rpg_mag <= 0) { + return; + } + + pl.rpg_mag--; + +#ifdef CLIENT + Weapons_ViewAnimation(RPG_FIRE2); + Weapons_ViewPunchAngle([-10,0,0]); +#else + static void Rocket_Touch(void) { + float dmg = Skill_GetValue("plr_rpg", 100); + FX_Explosion(self.origin); + Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_RPG); + sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM); + remove(self); + } + static void Rocket_BuildSpeed(void){ + /* Calculate new direction */ + if (self.weapon) { + makevectors(self.owner.v_angle); + traceline(self.owner.origin, self.owner.origin + v_forward * 8096, FALSE, self.owner); + self.angles = vectoangles(trace_endpos - self.origin); + } + + /* Increase speed towards it */ + makevectors(self.angles); + self.velocity += (v_forward * 2000) * frametime; + self.nextthink = time; + } + + Weapons_MakeVectors(); + entity rocket = spawn(); + setmodel(rocket, "models/rpgrocket.mdl"); + setorigin(rocket, Weapons_GetCameraPos() + (v_forward * 16)); + rocket.owner = self; + rocket.movetype = MOVETYPE_FLY; + rocket.solid = SOLID_BBOX; + //bolt.flags |= FL_LAGGEDMOVE; + rocket.gravity = 0.5f; + rocket.velocity = (v_forward * 250); + rocket.angles = vectoangles(rocket.velocity); + rocket.avelocity[2] = 10; + rocket.touch = Rocket_Touch; + rocket.think = Rocket_BuildSpeed; + rocket.nextthink = time + 0.15f; + rocket.traileffectnum = particleeffectnum("weapon_rpg.trail"); + + if (pl.ammo_rpg_state > 0) { + rocket.weapon = 1; + } + + setsize(rocket, [0,0,0], [0,0,0]); + Sound_Play(pl, CHAN_WEAPON, "weapon_rpg.shoot"); +#endif + + pl.w_attack_next = + pl.w_idle_next = 2.5f; +} + +void w_rpg_reload(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0) { + return; + } + + /* Ammo check */ + if (pl.rpg_mag >= 1) { + return; + } + if (pl.ammo_rocket <= 0) { + return; + } + + /* Audio-Visual Bit */ +#ifdef CLIENT + Weapons_ViewAnimation(RPG_RELOAD); +#else + Weapons_ReloadWeapon(pl, player::rpg_mag, player::ammo_rocket, 1); +#endif + + pl.w_attack_next = 2.25f; + pl.w_idle_next = 10.0f; +} + +void w_rpg_release(void) +{ + player pl = (player)self; + + /* auto-reload if need be */ + if (pl.w_attack_next <= 0.0) + if (pl.rpg_mag == 0 && pl.ammo_rocket > 0) { + Weapons_Reload(); + return; + } + + if (pl.w_idle_next > 0.0) { + return; + } + + int r = (float)input_sequence % 3; + + if (pl.a_ammo1 > 0) { + if (r == 1) { + Weapons_ViewAnimation(RPG_FIDGET); + } else { + Weapons_ViewAnimation(RPG_IDLE); + } + } else { + if (r == 1) { + Weapons_ViewAnimation(RPG_FIDGET_UL); + } else { + Weapons_ViewAnimation(RPG_IDLE_UL); + } + } + + pl.w_idle_next = 6.0f; +} + +void w_rpg_secondary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next > 0.0) { + return; + } + + /* toggle laser */ + pl.ammo_rpg_state = 1 - pl.ammo_rpg_state; + + pl.w_attack_next = 0.25f; + w_rpg_release(); +} + +float w_rpg_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMRPG : ANIM_AIMRPG; +} + +void w_rpg_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.rpg_mag == 0 && pl.ammo_rocket == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + if (selected) { + drawsubpic(pos, [170,45], g_hud5_spr, [0,45/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE); + } else { + drawsubpic(pos, [170,45], g_hud2_spr, [0,45/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE); + } + + HUD_DrawAmmoBar(pos, pl.ammo_rocket, MAX_A_ROCKET, a); +#endif +} + +void w_rpg_hud(void) +{ +#ifdef CLIENT + player pl = (player)self; + vector cross_pos; + vector aicon_pos; + + /* crosshair/laser */ + if (pl.ammo_rpg_state == 1) { + float lerp; + vector jitter; + Weapons_MakeVectors(); + vector src = pl.origin + pl.view_ofs; + traceline(src, src + (v_forward * 256), FALSE, pl); + lerp = Math_Lerp(18,6, trace_fraction); + jitter[0] = (random(0,2) - 2) * (1 - trace_fraction); + jitter[1] = (random(0,2) - 2) * (1 - trace_fraction); + cross_pos = g_hudmins + (g_hudres / 2) + ([-lerp,-lerp] / 2); + drawsubpic( + cross_pos + jitter, + [lerp,lerp], + g_laser_spr, + [0,0], + [1.0, 1.0], + [1,1,1], + 1.0f, + DRAWFLAG_ADDITIVE + ); + } else { + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + drawsubpic( + cross_pos, + [24,24], + g_cross_spr, + [0,0], + [0.1875, 0.1875], + [1,1,1], + 1, + DRAWFLAG_NORMAL + ); + } + + /* ammo counters */ + HUD_DrawAmmo1(); + HUD_DrawAmmo2(); + + /* ammo icon */ + aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42]; + drawsubpic( + aicon_pos, + [24,24], + "sprites/640hud7.spr_0.tga", + [120/256,72/128], + [24/256, 24/128], + g_hud_color, + pSeat->m_flAmmo2Alpha, + DRAWFLAG_ADDITIVE + ); +#endif +} + +weapon_t w_rpg = +{ + .name = "rpg_rocket", + .id = ITEM_RPG, + .slot = 3, + .slot_pos = 0, + .draw = w_rpg_draw, + .holster = w_rpg_holster, + .primary = w_rpg_primary, + .secondary = w_rpg_secondary, + .reload = w_rpg_reload, + .release = w_rpg_release, + .crosshair = w_rpg_hud, + .precache = w_rpg_precache, + .pickup = w_rpg_pickup, + .updateammo = w_rpg_updateammo, + .wmodel = w_rpg_wmodel, + .pmodel = w_rpg_pmodel, + .deathmsg = w_rpg_deathmsg, + .aimanim = w_rpg_aimanim, + .hudpic = w_rpg_hudpic +}; + +#ifdef SERVER +void weapon_rpg(void) { + Weapons_InitItem(WEAPON_RPG); +} +#endif diff --git a/src/shared/w_satchel.qc b/src/shared/w_satchel.qc new file mode 100644 index 0000000..348e80e --- /dev/null +++ b/src/shared/w_satchel.qc @@ -0,0 +1,334 @@ +/* + * 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_satchel (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_satchel.mdl" + +HALF-LIFE (1998) ENTITY + +Satchel Weapon + +*/ + +enum +{ + SATCHEL_IDLE, + SATCHEL_FIDGET, + SATCHEL_DRAW, + SATCHEL_THROW +}; + +enum +{ + RADIO_IDLE, + RADIO_FIDGET, + RADIO_DRAW, + RADIO_USE, + RADIO_HOLSTER +}; + + + +#ifdef SERVER +void +s_satchel_drop(entity master, vector src, vector vel) +{ + static void s_satchel_touch(void) + { + if (other != world) + return; + + Sound_Play(self, CHAN_BODY, "weapon_satchel.bounce"); + } + entity satch; + satch = spawn(); + satch.owner = master; + satch.classname = "satchel"; + satch.movetype = MOVETYPE_BOUNCE; + satch.solid = SOLID_BBOX; + satch.frame = 1; + satch.gravity = 0.5f; + satch.friction = 0.8f; + satch.velocity = vel; + satch.avelocity = [0,400,0]; + satch.touch = s_satchel_touch; + setmodel(satch, "models/w_satchel.mdl"); + setsize(satch, [-4,-4,-4], [4,4,4]); + setorigin(satch, src); +} + +void +s_satchel_detonate(entity master) +{ + for (entity b = world; (b = find(b, ::classname, "satchel"));) { + if (b.owner != master) + continue; + + float dmg = Skill_GetValue("plr_satchel", 150); + FX_Explosion(b.origin); + Damage_Radius(b.origin, master, dmg, dmg * 2.5f, TRUE, WEAPON_SATCHEL); + sound(b, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM); + remove(b); + } +} +#endif + +void +w_satchel_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.satchel_chg, pl.ammo_satchel, -1); +} + +string +w_satchel_wmodel(void) +{ + return "models/w_satchel.mdl"; +} + +string +w_satchel_pmodel(void) +{ + return "models/p_satchel.mdl"; +} + +string +w_satchel_deathmsg(void) +{ + return ""; +} + +void +w_satchel_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_satchel.bounce"); + precache_model("models/w_satchel.mdl"); +#else + precache_model("models/v_satchel.mdl"); + precache_model("models/v_satchel_radio.mdl"); + precache_model("models/p_satchel.mdl"); +#endif +} + +int +w_satchel_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (pl.ammo_satchel < MAX_A_SATCHEL) { + pl.ammo_satchel = bound(0, pl.ammo_satchel + 1, MAX_A_SATCHEL); + } else { + return FALSE; + } +#endif + return TRUE; +} + +void +w_satchel_draw(void) +{ +#ifdef CLIENT + player pl = (player)self; + if (pl.satchel_chg > 0) { + Weapons_SetModel("models/v_satchel_radio.mdl"); + Weapons_ViewAnimation(RADIO_DRAW); + + } else { + Weapons_SetModel("models/v_satchel.mdl"); + Weapons_ViewAnimation(SATCHEL_DRAW); + } +#endif +} + +void +w_satchel_holster(void) +{ + +} + +void +w_satchel_primary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next) { + return; + } + + /* Ammo check */ + if (pl.satchel_chg <= 0 && pl.ammo_satchel <= 0) { + return; + } + + if (pl.satchel_chg <= 0) { + Weapons_ViewAnimation(RADIO_DRAW); + } else { + Weapons_ViewAnimation(RADIO_USE); + } + +#ifdef SERVER + /* if we don't have any satchels placed yet, place one */ + if (!pl.satchel_chg) { + vector throw; + + Weapons_MakeVectors(); + throw = pl.velocity + (v_forward * 274); + s_satchel_drop(self, pl.origin, throw); + pl.satchel_chg++; + pl.ammo_satchel--; + } else { + /* detonate all we have */ + s_satchel_detonate(pl); + pl.satchel_chg = 0; + + /* no satchels left to place? just get rid of this thing */ + if (pl.ammo_satchel <= 0) { + Weapons_RemoveItem(pl, WEAPON_SATCHEL); + } + } +#else + Weapons_SetModel("models/v_satchel_radio.mdl"); + + /* same thing as the SERVER ifdef above... */ + if (!pl.satchel_chg) { + pl.satchel_chg++; + pl.ammo_satchel--; + } else { + pl.satchel_chg = 0; + } +#endif + + pl.w_attack_next = 1.0f; + pl.w_idle_next = 1.0f; +} + +void +w_satchel_secondary(void) +{ + player pl = (player)self; + + if (pl.w_attack_next) { + return; + } + + /* Ammo check */ + if (pl.ammo_satchel <= 0) { + return; + } + +#ifdef SERVER + vector throw; + Weapons_MakeVectors(); + throw = pl.velocity + (v_forward * 274); + s_satchel_drop(self, pl.origin, throw); +#else + Weapons_SetModel("models/v_satchel_radio.mdl"); + Weapons_ViewAnimation(RADIO_DRAW); +#endif + + pl.satchel_chg++; + pl.ammo_satchel--; + + pl.w_attack_next = 1.0f; + pl.w_idle_next = 2.5f; +} + +void +w_satchel_reload(void) +{ + +} + +void +w_satchel_release(void) +{ + player pl = (player)self; + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.satchel_chg <= 0) { + Weapons_ViewAnimation(SATCHEL_FIDGET); + } else { + Weapons_ViewAnimation(RADIO_FIDGET); + } + pl.w_idle_next = 15.0f; +} + +float +w_satchel_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMSQUEAK : ANIM_AIMSQUEAK; +} + +void +w_satchel_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/128], [24/256, 24/128], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_satchel_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + + if (selected) { + drawsubpic(pos, [170,45], g_hud6_spr, [0,45/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE); + } else { + drawsubpic(pos, [170,45], g_hud3_spr, [0,45/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE); + } + + HUD_DrawAmmoBar(pos, pl.ammo_satchel, MAX_A_SATCHEL, a); +#endif +} + +weapon_t w_satchel = +{ + .name = "satchel", + .id = ITEM_SATCHEL, + .slot = 4, + .slot_pos = 1, + .draw = w_satchel_draw, + .holster = w_satchel_holster, + .primary = w_satchel_primary, + .secondary = w_satchel_secondary, + .reload = w_satchel_reload, + .release = w_satchel_release, + .crosshair = w_satchel_hud, + .precache = w_satchel_precache, + .pickup = w_satchel_pickup, + .updateammo = w_satchel_updateammo, + .wmodel = w_satchel_wmodel, + .pmodel = w_satchel_pmodel, + .deathmsg = w_satchel_deathmsg, + .aimanim = w_satchel_aimanim, + .hudpic = w_satchel_hudpic +}; + +#ifdef SERVER +void +weapon_satchel(void) +{ + Weapons_InitItem(WEAPON_SATCHEL); +} +#endif diff --git a/src/shared/w_shotgun.qc b/src/shared/w_shotgun.qc new file mode 100644 index 0000000..4471991 --- /dev/null +++ b/src/shared/w_shotgun.qc @@ -0,0 +1,345 @@ +/* + * 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_shotgun (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_shotgun.mdl" + +HALF-LIFE (1998) ENTITY + +Shotgun Weapon + +*/ + +enum +{ + SHOTGUN_IDLE1, + SHOTGUN_FIRE1, + SHOTGUN_FIRE2, + SHOTGUN_RELOAD, + SHOTGUN_PUMP, + SHOTGUN_START_RELOAD, + SHOTGUN_DRAW, + SHOTGUN_HOLSTER, + SHOTGUN_IDLE2, + SHOTGUN_IDLE3 +}; + +enum +{ + SHOTTY_IDLE, + SHOTTY_RELOAD_START, + SHOTTY_RELOAD, + SHOTTY_RELOAD_END +}; + +void w_shotgun_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_shotgun.single"); + Sound_Precache("weapon_shotgun.double"); + Sound_Precache("weapon_shotgun.reload"); + Sound_Precache("weapon_shotgun.cock"); + precache_model("models/w_shotgun.mdl"); +#else + precache_model("models/v_shotgun.mdl"); + precache_model("models/p_shotgun.mdl"); +#endif +} + +void +w_shotgun_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, pl.shotgun_mag, pl.ammo_buckshot, -1); +} + +string +w_shotgun_wmodel(void) +{ + return "models/w_shotgun.mdl"; +} + +string +w_shotgun_pmodel(void) +{ + return "models/p_shotgun.mdl"; +} + +string +w_shotgun_deathmsg(void) +{ + return ""; +} + +int +w_shotgun_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (new) { + pl.shotgun_mag = 8; + } else { + if (pl.ammo_buckshot < MAX_A_BUCKSHOT) { + pl.ammo_buckshot = bound(0, pl.ammo_buckshot + 8, MAX_A_BUCKSHOT); + } else { + return FALSE; + } + } +#endif + return TRUE; +} + +void +w_shotgun_draw(void) +{ + player pl = (player)self; + pl.mode_tempstate = 0; + +#ifdef CLIENT + Weapons_SetModel("models/v_shotgun.mdl"); + Weapons_ViewAnimation(SHOTGUN_DRAW); +#endif +} + +void +w_shotgun_holster(void) +{ + Weapons_ViewAnimation(SHOTGUN_HOLSTER); +} + +void +w_shotgun_primary(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + + if (pl.mode_tempstate > SHOTTY_IDLE) { + return; + } + + /* Ammo check */ + if (pl.shotgun_mag <= 0) { + return; + } + +#ifdef SERVER + /* Singleplayer is more accurate */ + if (cvar("sv_playerslots") == 1) { + TraceAttack_FireBullets(6, pl.origin + pl.view_ofs, Skill_GetValue("plr_buckshot", 5), [0.08716,0.08716], WEAPON_SHOTGUN); + } else { + TraceAttack_FireBullets(4, pl.origin + pl.view_ofs, Skill_GetValue("plr_buckshot", 5), [0.08716,0.04362], WEAPON_SHOTGUN); + } + Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.single"); +#else + View_SetMuzzleflash(MUZZLE_WEIRD); + Weapons_ViewAnimation(SHOTGUN_FIRE1); + Weapons_ViewPunchAngle([-5,0,0]); +#endif + + pl.shotgun_mag--; + + pl.w_attack_next = 0.75; + pl.w_idle_next = 2.5f; +} + +void +w_shotgun_secondary(void) +{ + player pl = (player)self; + if (pl.w_attack_next) { + return; + } + + if (pl.mode_tempstate > SHOTTY_IDLE) { + return; + } + + /* Ammo check */ + if (pl.shotgun_mag <= 1) { + return; + } + +#ifdef SERVER + /* Singleplayer is more accurate */ + if (cvar("sv_playerslots") == 1) { + TraceAttack_FireBullets(12, pl.origin + pl.view_ofs, 5, [0.08716,0.08716], WEAPON_SHOTGUN); + } else { + TraceAttack_FireBullets(8, pl.origin + pl.view_ofs, 5, [0.17365,0.04362], WEAPON_SHOTGUN); + } + Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.double"); + Weapons_UpdateAmmo(pl, pl.shotgun_mag, pl.ammo_buckshot, __NULL__); +#else + Weapons_ViewAnimation(SHOTGUN_FIRE2); + Weapons_ViewPunchAngle([-10,0,0]); +#endif + + pl.shotgun_mag -= 2; + pl.w_attack_next = 1.5f; + pl.w_idle_next = 2.5f; +} + +void +w_shotgun_reload(void) +{ + player pl = (player)self; + + if (pl.shotgun_mag >= 8) { + return; + } + if (pl.ammo_buckshot <= 0) { + return; + } + + if (pl.mode_tempstate > SHOTTY_IDLE) { + return; + } + pl.mode_tempstate = SHOTTY_RELOAD_START; + pl.w_idle_next = 0.0f; +} + +void +w_shotgun_release(void) +{ + player pl = (player)self; + + /* auto-reload if need be */ + if (pl.w_attack_next <= 0.0) + if (pl.mode_tempstate == SHOTTY_IDLE && pl.shotgun_mag == 0 && pl.ammo_buckshot > 0) { + Weapons_Reload(); + return; + } + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.mode_tempstate == SHOTTY_IDLE) { + int r = (float)input_sequence % 3; + switch (r) { + case 1: + Weapons_ViewAnimation(SHOTGUN_IDLE2); + pl.w_idle_next = 2.222222f; + break; + case 2: + Weapons_ViewAnimation(SHOTGUN_IDLE3); + pl.w_idle_next = 5.0f; + break; + default: + Weapons_ViewAnimation(SHOTGUN_IDLE1); + pl.w_idle_next = 2.222222f; + break; + } + } else if (pl.mode_tempstate == SHOTTY_RELOAD_START) { + Weapons_ViewAnimation(SHOTGUN_START_RELOAD); + pl.mode_tempstate = SHOTTY_RELOAD; + pl.w_idle_next = 0.65f; + } else if (pl.mode_tempstate == SHOTTY_RELOAD) { + Weapons_ViewAnimation(SHOTGUN_RELOAD); + pl.shotgun_mag++; + pl.ammo_buckshot--; +#ifdef SERVER + Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.reload"); +#endif + if (pl.ammo_buckshot <= 0 || pl.shotgun_mag >= 8) { + pl.mode_tempstate = SHOTTY_RELOAD_END; + } + Weapons_UpdateAmmo(pl, pl.shotgun_mag, pl.ammo_buckshot, pl.mode_tempstate); + pl.w_idle_next = 0.5f; + } else if (pl.mode_tempstate == SHOTTY_RELOAD_END) { + Weapons_ViewAnimation(SHOTGUN_PUMP); +#ifdef SERVER + Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.cock"); +#endif + pl.mode_tempstate = SHOTTY_IDLE; + pl.w_idle_next = 10.0f; + pl.w_attack_next = 0.5f; + } +} + +void +w_shotgun_crosshair(void) +{ +#ifdef CLIENT + static vector cross_pos; + cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; + drawsubpic(cross_pos, [24,24], g_cross_spr, [48/128,24/128], [0.1875, 0.1875], [1,1,1], 1, DRAWFLAG_NORMAL); + 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/128], [24/256, 24/128], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +float +w_shotgun_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMSHOTGUN : ANIM_AIMSHOTGUN; +} + +void +w_shotgun_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + vector hud_col; + + if (pl.shotgun_mag == 0 && pl.ammo_buckshot == 0) + hud_col = [1,0,0]; + else + hud_col = g_hud_color; + + if (selected) { + drawsubpic(pos, [170,45], g_hud4_spr, [0,180/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE); + } else { + drawsubpic(pos, [170,45], g_hud1_spr, [0,180/256], [170/256,45/256], hud_col, a, DRAWFLAG_ADDITIVE); + } + + HUD_DrawAmmoBar(pos, pl.ammo_buckshot, MAX_A_BUCKSHOT, a); +#endif +} + +weapon_t w_shotgun = +{ + .name = "shotgun", + .id = ITEM_SHOTGUN, + .slot = 2, + .slot_pos = 1, + .draw = w_shotgun_draw, + .holster = w_shotgun_holster, + .primary = w_shotgun_primary, + .secondary = w_shotgun_secondary, + .reload = w_shotgun_reload, + .release = w_shotgun_release, + .crosshair = w_shotgun_crosshair, + .precache = w_shotgun_precache, + .pickup = w_shotgun_pickup, + .updateammo = w_shotgun_updateammo, + .wmodel = w_shotgun_wmodel, + .pmodel = w_shotgun_pmodel, + .deathmsg = w_shotgun_deathmsg, + .aimanim = w_shotgun_aimanim, + .hudpic = w_shotgun_hudpic +}; + +#ifdef SERVER +void +weapon_shotgun(void) +{ + Weapons_InitItem(WEAPON_SHOTGUN); +} +#endif diff --git a/src/shared/w_snark.qc b/src/shared/w_snark.qc new file mode 100644 index 0000000..4b7c15d --- /dev/null +++ b/src/shared/w_snark.qc @@ -0,0 +1,324 @@ +/* + * 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_snark (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/w_squeak.mdl" + +HALF-LIFE (1998) ENTITY + +Snark/Squeakgrenade Weapon + +*/ + +enum +{ + SNARK_IDLE, + SNARK_FIDGET1, + SNARK_FIDGET2, + SNARK_HOLSTER, + SNARK_DRAW, + SNARK_THROW +}; + +#ifdef SERVER +class monster_snark:CBaseMonster +{ + float m_flJump; + entity m_eTarget; + + void(void) monster_snark; + + virtual void(void) customphysics; + virtual void(void) Death; + virtual void(void) Respawn; +}; + +void +monster_snark::customphysics(void) +{ + input_movevalues = [250,0,0]; + input_buttons = 0; + input_impulse = 0; + input_angles = angles; + input_timelength = frametime; + + if (health <= 0) { + return; + } + + if (m_flJump <= 0.0 && m_eTarget == __NULL__) { + float shortest = 999999; + for (entity ef = world; (ef = findfloat(ef, ::movetype, MOVETYPE_WALK));) { + float len = vlen(ef.origin - origin); + if (ef.classname != "monster_snark" && len < shortest && ef.health > 0) { + owner = __NULL__; + m_eTarget = ef; + shortest = len; + } + } + } + + if (m_eTarget) { + angles = input_angles = vectoangles(m_eTarget.origin - origin); + } + + if (m_eTarget && m_flJump <= 0.0) { + m_flJump = 0.5f + random(); + Sound_Play(this, CHAN_VOICE, "weapon_snark.hunt"); + input_buttons = 2; + Damage_Apply(this, world, 1, 0, DMG_GENERIC); + + makevectors(angles); + traceline(origin, origin + (v_forward * 128), 0, this); + + if (trace_ent.takedamage == DAMAGE_YES) { + Sound_Play(this, CHAN_BODY, "weapon_snark.deploy"); + Damage_Apply(trace_ent, real_owner, Skill_GetValue("snark_dmg_bite", 10), WEAPON_SNARK, DMG_GENERIC); + FX_Blood(origin + [0,0,16], [1,0,0]); + } + + if (m_eTarget.health <= 0) { + m_eTarget = __NULL__; + } + } + + m_flJump -= frametime; + runstandardplayerphysics(this); +} + +void +monster_snark::Death(void) +{ + float dmg = Skill_GetValue("snark_dmg_pop", 5); + Damage_Radius(origin, goalentity, dmg, dmg * 2.5f, TRUE, WEAPON_SNARK); + FX_Blood(origin + [0,0,16], [203,183,15] / 255); + Sound_Play(this, CHAN_VOICE, "weapon_snark.die"); + Sound_Play(this, CHAN_BODY, "weapon_snark.blast"); + customphysics = __NULL__; + remove(this); +} + +void +monster_snark::Respawn(void) +{ + netname = "Snark"; + SetModel("models/w_squeak.mdl"); + flags |= FL_MONSTER; + SetSolid(SOLID_BBOX); + SetMovetype(MOVETYPE_WALK); + SetFrame(3); /* running like crazy. */ + angles = goalentity.angles; + health = 20; + takedamage = DAMAGE_YES; + m_eTarget = __NULL__; + m_flJump = 1.0f; +} + +void +monster_snark::monster_snark(void) +{ + Respawn(); +} +#endif + +int w_snark_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (pl.ammo_snark < MAX_A_SNARK) { + pl.ammo_snark = bound(0, pl.ammo_snark + 5, MAX_A_SNARK); + } else { + return FALSE; + } +#endif + return TRUE; +} + +void w_snark_draw(void) +{ + Weapons_SetModel("models/v_squeak.mdl"); + Weapons_ViewAnimation(SNARK_DRAW); +} + +void w_snark_holster(void) +{ + +} + +#ifdef SERVER +void w_snark_deploy(void) +{ + monster_snark snark = spawn(monster_snark, real_owner: self, goalentity: self, spawnflags: MSF_MULTIPLAYER); + makevectors(self.v_angle); + snark.SetOrigin(self.origin + v_forward * 32); +} +#endif + +void w_snark_primary(void) +{ + player pl = (player)self; + if (pl.w_attack_next > 0.0) { + return; + } + + /* Ammo check */ + if (pl.ammo_snark <= 0) { + return; + } + + pl.ammo_snark--; + + /* Audio-Visual Bit */ +#ifdef CLIENT + Weapons_ViewAnimation(SNARK_THROW); +#else + w_snark_deploy(); + + if (pl.ammo_snark <= 0) { + Weapons_RemoveItem(pl, WEAPON_SNARK); + } +#endif + + pl.w_idle_next = 1.0f; + pl.w_attack_next = 0.25f; + +} +void w_snark_secondary(void) +{ + +} +void w_snark_reload(void) +{ + +} +void w_snark_release(void) +{ + int r; + player pl = (player)self; + if (pl.w_idle_next > 0.0) { + return; + } + + r = (float)input_sequence % 3; + switch (r) { + case 0: + Weapons_ViewAnimation(SNARK_IDLE); + pl.w_idle_next = 1.875f; + break; + case 1: + Weapons_ViewAnimation(SNARK_FIDGET1); + pl.w_idle_next = 4.375f; + break; + default: + Weapons_ViewAnimation(SNARK_FIDGET2); + pl.w_idle_next = 5.0f; + break; + } +} +void w_snark_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_snark.deploy"); + Sound_Precache("weapon_snark.die"); + Sound_Precache("weapon_snark.blast"); + Sound_Precache("weapon_snark.hunt"); + precache_model("models/w_sqknest.mdl"); + precache_model("models/w_squeak.mdl"); +#else + precache_model("models/p_squeak.mdl"); + precache_model("models/v_squeak.mdl"); +#endif +} +void w_snark_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, pl.ammo_snark, -1); +} +string w_snark_wmodel(void) +{ + return "models/w_sqknest.mdl"; +} +string w_snark_pmodel(void) +{ + return "models/p_squeak.mdl"; +} +string w_snark_deathmsg(void) +{ + return ""; +} + + +float w_snark_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMSQUEAK : ANIM_AIMSQUEAK; +} + +void w_snark_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/128], [24/256, 24/128], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void w_snark_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + + if (selected) { + drawsubpic(pos, [170,45], g_hud6_spr, + [0,135/256], [170/256,45/256], + g_hud_color, a, DRAWFLAG_ADDITIVE); + } else { + drawsubpic(pos, [170,45], g_hud3_spr, + [0,135/256], [170/256,45/256], + g_hud_color, a, DRAWFLAG_ADDITIVE); + } + + HUD_DrawAmmoBar(pos, pl.ammo_snark, MAX_A_SNARK, a); +#endif +} + +weapon_t w_snark = +{ + .name = "snark", + .id = ITEM_SNARK, + .slot = 4, + .slot_pos = 3, + .draw = w_snark_draw, + .holster = w_snark_holster, + .primary = w_snark_primary, + .secondary = w_snark_secondary, + .reload = w_snark_reload, + .release = w_snark_release, + .crosshair = w_snark_hud, + .precache = w_snark_precache, + .pickup = w_snark_pickup, + .updateammo = w_snark_updateammo, + .wmodel = w_snark_wmodel, + .pmodel = w_snark_pmodel, + .deathmsg = w_snark_deathmsg, + .aimanim = w_snark_aimanim, + .hudpic = w_snark_hudpic +}; + +#ifdef SERVER +void weapon_snark(void) { + Weapons_InitItem(WEAPON_SNARK); +} +#endif diff --git a/src/shared/w_tripmine.qc b/src/shared/w_tripmine.qc new file mode 100644 index 0000000..170c8ed --- /dev/null +++ b/src/shared/w_tripmine.qc @@ -0,0 +1,400 @@ +/* + * 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_tripmine (0 0 1) (-16 -16 0) (16 16 32) +"model" "models/v_tripmine.mdl" + +HALF-LIFE (1998) ENTITY + +Tripmine Weapon + +*/ + +enum +{ + TRIPMINE_IDLE1, + TRIPMINE_IDLE2, + TRIPMINE_FIRE1, + TRIPMINE_FIRE2, + TRIPMINE_FIDGET, + TRIPMINE_HOLSTER, + TRIPMINE_DRAW, + TRIPMINE_WORLD, + TRIPMINE_GROUND, +}; + +/* MONSTER_TRIPMINE SEGMENT + * + * Because not being able to place it around levels would be boring. + * Some maps, such as subtransit and a few singleplayer chapters have this. */ + +#ifdef SERVER +class monster_tripmine:CBaseMonster +{ + int m_iDist; + void(void) monster_tripmine; + + virtual float(entity, float) SendEntity; + virtual void(int) Trip; + virtual void(void) Damaged; + virtual void(void) Ready; + virtual void(void) Respawn; +}; + +float +monster_tripmine::SendEntity(entity pvsent, float flags) +{ + WriteByte(MSG_ENTITY, ENT_TRIPMINE); + 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]); + WriteByte(MSG_ENTITY, health); + WriteShort(MSG_ENTITY, modelindex); + return TRUE; +} + +void +monster_tripmine::Trip(int walkthrough) +{ + float dmg; + if (!walkthrough) { + real_owner = g_eAttacker; + } + + /* This is to prevent infinite loops in Damage_Radius */ + Death = + Pain = __NULL__; + takedamage = DAMAGE_NO; + dmg = Skill_GetValue("plr_tripmine", 150); + FX_Explosion(origin); + Damage_Radius(origin, real_owner, dmg, dmg * 2.5f, TRUE, WEAPON_TRIPMINE); + sound(this, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM); + remove(this); +} + +void +monster_tripmine::Damaged(void) +{ + Trip(0); +} + +void +monster_tripmine::Ready(void) +{ + makevectors(angles); + traceline(origin, origin + v_forward * 2048, FALSE, this); + SetSolid(SOLID_BBOX); + + /* first time we're marked as ready, we play a sound and set the distance */ + if (!health) { + SendFlags = -1; + health = 1; + Death = + Pain = Damaged; + takedamage = DAMAGE_YES; + m_iDist = (int)trace_plane_dist; + Sound_Play(this, CHAN_WEAPON, "weapon_tripmine.activate"); + } + + if ((int)trace_plane_dist != m_iDist) { + Trip(1); + } + nextthink = time; +} + +void +monster_tripmine::Respawn(void) +{ + SetModel("models/v_tripmine.mdl"); + SetSolid(SOLID_NOT); + SetMovetype(MOVETYPE_NONE); + SetSize([-8,-8,-8], [8,8,8]); + SetOrigin(origin); + SendFlags = 1; /* force update */ + + /* ready in 4 seconds flat */ + think = Ready; + + /* fast beam */ + if (spawnflags & 1) { + nextthink = time; + } else { + nextthink = time + 4.0f; + } +} + +void +monster_tripmine::monster_tripmine(void) +{ + Respawn(); +} +#else +class csitem_tripmine +{ + int m_iActive; + + void(void) csitem_tripmine; + virtual float(void) predraw; +}; + +float csitem_tripmine::predraw(void) +{ + if (m_iActive) { + makevectors(angles); + traceline(origin, origin + v_forward * 8196, FALSE, this); + trailparticles(BEAM_TRIPMINE, this, origin, trace_endpos); + } + + addentity(this); + return PREDRAW_NEXT; +} + +void +csitem_tripmine::csitem_tripmine(void) +{ + solid = SOLID_BBOX; + movetype = MOVETYPE_NONE; + drawmask = MASK_ENGINE; + frame = TRIPMINE_WORLD; +} + +void w_tripmine_parse(void) +{ + csitem_tripmine tm = (csitem_tripmine)self; + spawnfunc_csitem_tripmine(); + + 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.m_iActive = readbyte(); + tm.modelindex = readshort(); + + setcustomskin(tm, "", "geomset 0 2\ngeomset 1 2\n"); + setorigin(tm, tm.origin); + setsize(tm, [-8,-8,-8], [8,8,8]); +} +#endif + +/* The WEAPON_TRIPMINE code + * + * Here is where the actual 'weapon' logic happens that the player itself + * runs. It obviously won't work without MONSTER_TRIPMINE */ + +void w_tripmine_precache(void) +{ +#ifdef SERVER + Sound_Precache("weapon_tripmine.deploy"); + Sound_Precache("weapon_tripmine.charge"); + Sound_Precache("weapon_tripmine.activate"); + precache_model("models/v_tripmine.mdl"); +#else + precache_model("models/p_tripmine.mdl"); +#endif +} + +void w_tripmine_updateammo(player pl) +{ + Weapons_UpdateAmmo(pl, -1, pl.ammo_tripmine, -1); +} + +string w_tripmine_wmodel(void) +{ + return "models/v_tripmine.mdl"; +} + +string w_tripmine_pmodel(void) +{ + return "models/p_tripmine.mdl"; +} + +string w_tripmine_deathmsg(void) +{ + return ""; +} + +int w_tripmine_pickup(int new, int startammo) +{ +#ifdef SERVER + player pl = (player)self; + + if (pl.ammo_tripmine < MAX_A_TRIPMINE) { + pl.ammo_tripmine = bound(0, pl.ammo_tripmine + 1, MAX_A_TRIPMINE); + } else { + return FALSE; + } +#endif + return TRUE; +} + +void w_tripmine_draw(void) +{ +#ifdef CLIENT + Weapons_SetModel("models/v_tripmine.mdl"); + Weapons_ViewAnimation(TRIPMINE_DRAW); +#endif +} + +void w_tripmine_holster(void) +{ + +} + +void +w_tripmine_primary(void) +{ + player pl = (player)self; + vector src; + + if (pl.w_attack_next > 0.0) { + return; + } + + if (pl.ammo_tripmine <= 0) { + return; + } + + src = Weapons_GetCameraPos(); + Weapons_MakeVectors(); + traceline(src, src + v_forward * 64, FALSE, pl); + + if (trace_fraction >= 1.0) { + return; + } + + pl.ammo_tripmine--; + +#ifdef CLIENT + Weapons_ViewAnimation(TRIPMINE_FIRE2); +#else + vector ang = vectoangles(trace_plane_normal); + monster_tripmine mine = spawn(monster_tripmine, real_owner: pl, angles: ang, spawnflags: MSF_MULTIPLAYER); + mine.SetOrigin(trace_endpos - (v_forward * 8)); + + Sound_Play(pl, CHAN_WEAPON, "weapon_tripmine.deploy"); + Sound_Play(mine, CHAN_WEAPON, "weapon_tripmine.charge"); +#endif + + pl.a_ammo3 = 1; + pl.w_attack_next = + pl.w_idle_next = 0.5f; +} + +void +w_tripmine_release(void) +{ + player pl = (player)self; + + if (pl.w_idle_next > 0.0) { + return; + } + + if (pl.a_ammo3 == 1) { + Weapons_ViewAnimation(TRIPMINE_DRAW); +#ifdef SERVER + if (pl.ammo_tripmine <= 0) { + Weapons_RemoveItem(pl, WEAPON_TRIPMINE); + } +#endif + pl.a_ammo3 = 0; + pl.w_attack_next = 0.5f; + pl.w_idle_next = 3.0f; + return; + } + + int r = (float)input_sequence % 3; + switch (r) { + case 1: + Weapons_ViewAnimation(TRIPMINE_IDLE1); + pl.w_idle_next = 3.0f; + break; + case 2: + Weapons_ViewAnimation(TRIPMINE_IDLE2); + pl.w_idle_next = 2.0f; + break; + default: + Weapons_ViewAnimation(TRIPMINE_FIDGET); + pl.w_idle_next = 3.34f; + break; + } +} + +float +w_tripmine_aimanim(void) +{ + return self.flags & FL_CROUCHING ? ANIM_CR_AIMTRIPMINE : ANIM_AIMTRIPMINE; +} + +void +w_tripmine_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, [120/256,96/128], [24/256, 24/128], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE); +#endif +} + +void +w_tripmine_hudpic(int selected, vector pos, float a) +{ +#ifdef CLIENT + player pl = (player)self; + + if (selected) { + drawsubpic(pos, [170,45], g_hud6_spr, [0,90/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE); + } else { + drawsubpic(pos, [170,45], g_hud3_spr, [0,90/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE); + } + + HUD_DrawAmmoBar(pos, pl.ammo_tripmine, MAX_A_TRIPMINE, a); +#endif +} + +weapon_t w_tripmine = +{ + .name = "tripmine", + .id = ITEM_TRIPMINE, + .slot = 4, + .slot_pos = 2, + .draw = w_tripmine_draw, + .holster = w_tripmine_holster, + .primary = w_tripmine_primary, + .secondary = __NULL__, + .reload = __NULL__, + .release = w_tripmine_release, + .crosshair = w_tripmine_hud, + .precache = w_tripmine_precache, + .pickup = w_tripmine_pickup, + .updateammo = w_tripmine_updateammo, + .wmodel = w_tripmine_wmodel, + .pmodel = w_tripmine_pmodel, + .deathmsg = w_tripmine_deathmsg, + .aimanim = w_tripmine_aimanim, + .hudpic = w_tripmine_hudpic +}; + +#ifdef SERVER +void +weapon_tripmine(void) { + Weapons_InitItem(WEAPON_TRIPMINE); +} +#endif diff --git a/src/shared/weapon_common.h b/src/shared/weapon_common.h new file mode 100644 index 0000000..9aafd65 --- /dev/null +++ b/src/shared/weapon_common.h @@ -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. + */ + +typedef struct +{ + string name; + int id; /* bitflag id */ + int slot; + int slot_pos; + int allow_drop; + + void(void) draw; + void(void) holster; + void(void) primary; + void(void) secondary; + void(void) reload; + void(void) release; + void(void) crosshair; + + void(void) precache; + int(int, int) pickup; + void(player) updateammo; + string() wmodel; + string() pmodel; + string() deathmsg; + float() aimanim; + void(int, vector, float) hudpic; +} weapon_t; + +float Weapons_GetAim(int); +void Weapons_Reload(void); +void Weapons_DrawCrosshair(void); +void Weapons_MakeVectors(void); +vector Weapons_GetCameraPos(void); +void Weapons_ViewAnimation(int); +void Weapons_ViewPunchAngle(vector); +void Weapons_PlaySound(entity, float, string, float, float); +int Weapons_IsPresent(player, int); +void Weapons_SetModel(string); +void Weapons_SetGeomset(string); +void Weapons_UpdateAmmo(base_player, int, int, int); + +#ifdef CLIENT +string Weapons_GetPlayermodel(int); +int Weapons_GetAnimation(void); +void Weapons_HUDPic(int, int, vector, float); +#endif diff --git a/src/shared/weapon_common.qc b/src/shared/weapon_common.qc new file mode 100644 index 0000000..8d0b9cd --- /dev/null +++ b/src/shared/weapon_common.qc @@ -0,0 +1,321 @@ +/* + * 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 Decals_Init(void); +#endif + +void Weapons_Init(void) +{ + /* in the future we'll have no internal weapon table, then this will fill + * one up... */ + /*searchhandle sh; + filestream fh; + string line; + sh = search_begin("scripts/weapon_*.txt", TRUE, TRUE); + for (int i = 0; i < search_getsize(sh); i++) { + fh = fopen(search_getfilename(sh, i), FILE_READ); + if (fh < 0) { + continue; + } + + while ((line = fgets(fh))) { + int w = tokenize(line); + switch (argv(0)) { + case "name": + break; + case "slot": + break; + case "slot_pos": + break; + } + } + fclose(fh); + }*/ + + for (int i = 0; i < g_weapons.length; i++) { + if (g_weapons[i].precache != __NULL__) { + g_weapons[i].precache(); + } + } +} + +void Weapons_SetModel(string mdl) +{ +#ifdef CLIENT + setmodel(pSeat->m_eViewModel, mdl); +#endif +} + +void Weapons_SetGeomset(string set) +{ +#ifdef CLIENT + setcustomskin(pSeat->m_eViewModel, "", set); +#endif +} + +void Weapons_Draw(void) +{ + player pl = (player)self; + int i = pl.activeweapon; + + pl.w_attack_next = 0.5f; + pl.w_idle_next = 2.5f; + pl.viewzoom = 1.0f; + +#ifdef CLIENT + entity eold = self; + self = pSeat->m_pWeaponFX; + spawnfunc_CBaseFX(); + self = eold; +#endif + + /* make sure this is all wiped */ + pl.a_ammo1 = pl.a_ammo2 = pl.a_ammo3 = 0; + + if (g_weapons[i].draw != __NULL__) { + g_weapons[i].draw(); + } + + if (g_weapons[i].updateammo != __NULL__) { + g_weapons[i].updateammo(pl); + } + +} + +void Weapons_Holster(void) +{ + player pl = (player)self; + int i = pl.activeweapon; + if (g_weapons[i].holster != __NULL__) { + g_weapons[i].holster(); + } +} + +void Weapons_Primary(void) +{ + player pl = (player)self; + int i = pl.activeweapon; + + if (pl.flags & FL_NOATTACK) + return; + + if (g_weapons[i].primary != __NULL__) { + g_weapons[i].primary(); + } + + if (g_weapons[i].updateammo != __NULL__) { + g_weapons[i].updateammo(pl); + } +} + +void Weapons_AmmoUpdate(entity target) +{ + player pl = (player)target; + int i = pl.activeweapon; + + if (g_weapons[i].updateammo != __NULL__) { + g_weapons[i].updateammo(pl); + } +} + +void Weapons_Secondary(void) +{ + player pl = (player)self; + int i = pl.activeweapon; + + if (pl.flags & FL_NOATTACK) + return; + + if (g_weapons[i].secondary != __NULL__) { + g_weapons[i].secondary(); + } + + if (g_weapons[i].updateammo != __NULL__) { + g_weapons[i].updateammo(pl); + } + +} + +void Weapons_Reload(void) +{ + player pl = (player)self; + int i = pl.activeweapon; + + if (pl.flags & FL_NOATTACK) + return; + + if (g_weapons[i].reload != __NULL__) { + g_weapons[i].reload(); + } + + if (g_weapons[i].updateammo != __NULL__) { + g_weapons[i].updateammo(pl); + } +} + +void Weapons_Release(void) +{ + player pl = (player)self; + int i = pl.activeweapon; + if (g_weapons[i].release != __NULL__) { + g_weapons[i].release(); + } + + pl.gflags &= ~GF_SEMI_TOGGLED; +} + +void Weapons_DrawCrosshair(void) +{ + player pl = (player)self; + int i = pl.activeweapon; + if (g_weapons[i].crosshair != __NULL__) { + g_weapons[i].crosshair(); + } +} + +string Weapons_GetWorldmodel(int id) +{ + if (g_weapons[id].wmodel != __NULL__) { + return g_weapons[id].wmodel(); + } + + return ""; +} + +string Weapons_GetPlayermodel(int id) +{ + if (g_weapons[id].pmodel != __NULL__) { + return g_weapons[id].pmodel(); + } + + return ""; +} + +string Weapons_GetDeathmessage(int id) +{ + if (g_weapons[id].deathmsg != __NULL__) { + return g_weapons[id].deathmsg(); + } + + return ""; +} + +float Weapons_GetAim(int id) +{ + if (g_weapons[id].aimanim != __NULL__) { + return g_weapons[id].aimanim(); + } + + return 0; +} + +#ifdef CLIENT +void Weapons_HUDPic(int id, int s, vector pos, float a) +{ + if (g_weapons[id].hudpic != __NULL__) { + g_weapons[id].hudpic(s, pos, a); + } +} +#endif + +void Weapons_MakeVectors(void) +{ +#ifdef SERVER + player pl = (player)self; + makevectors(pl.v_angle); +#else + makevectors(view_angles); +#endif +} + +vector Weapons_GetCameraPos(void) +{ +#ifdef SERVER + return self.origin + self.view_ofs; +#else + return getproperty(VF_ORIGIN); +#endif +} + +void Weapons_ViewAnimation(int i) +{ +#ifdef CLIENT + player pl = (player)pSeat->m_ePlayer; + View_PlayAnimation(i); +#else + player pl = (player)self; +#endif + pl.weapontime = 0.0f; +} + +#ifdef CLIENT +int View_GetAnimation(void); +int Weapons_GetAnimation(void) +{ + return View_GetAnimation(); +} +#endif + +void Weapons_ViewPunchAngle(vector add) +{ +#ifdef CLIENT + player pl = (player)self; + pl.punchangle += add; +#endif +} + +void Weapons_PlaySound(entity t, float ch, string s, float vol, float at) +{ +#ifdef SERVER + sound(t, ch, s, vol, at); +#endif +} + +int Weapons_IsPresent(player pl, int w) +{ + if (pl.g_items & g_weapons[w].id) { + return TRUE; + } else { + return FALSE; + } +} +/* +================= +Weapons_UpdateAmmo + +Sets .a_ammoX fields and clamps them so they can be networked as a single byte. +================= +*/ +void +Weapons_UpdateAmmo(base_player pl, int a1, int a2, int a3) +{ + /* no change */ + if (a1 == -1) { + a1 = pl.a_ammo1; + } + if (a2 == -1) { + a2 = pl.a_ammo2; + } + if (a3 == -1) { + a3 = pl.a_ammo3; + } + + /* networked as bytes, since we don't need more. Clamp to avoid errors */ + pl.a_ammo1 = bound(0, a1, 255); + pl.a_ammo2 = bound(0, a2, 255); + pl.a_ammo3 = bound(0, a3, 255); +} diff --git a/src/shared/weapons.h b/src/shared/weapons.h new file mode 100644 index 0000000..6163f2b --- /dev/null +++ b/src/shared/weapons.h @@ -0,0 +1,48 @@ +/* + * 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_CROWBAR, + WEAPON_GLOCK, + WEAPON_PYTHON, + WEAPON_MP5, + WEAPON_SHOTGUN, + WEAPON_CROSSBOW, + WEAPON_RPG, + WEAPON_GAUSS, + WEAPON_EGON, + WEAPON_HORNETGUN, + WEAPON_HANDGRENADE, + WEAPON_SATCHEL, + WEAPON_TRIPMINE, + WEAPON_SNARK +}; + +#define MAX_A_9MM 250 +#define MAX_A_357 36 +#define MAX_A_BUCKSHOT 125 +#define MAX_A_M203_GRENADE 10 +#define MAX_A_BOLT 50 +#define MAX_A_ROCKET 5 +#define MAX_A_URANIUM 100 +#define MAX_A_HANDGRENADE 10 +#define MAX_A_SATCHEL 5 +#define MAX_A_TRIPMINE 10 +#define MAX_A_SNARK 10 +#define MAX_A_HORNET 8 diff --git a/src/shared/weapons.qc b/src/shared/weapons.qc new file mode 100644 index 0000000..6d388ad --- /dev/null +++ b/src/shared/weapons.qc @@ -0,0 +1,34 @@ +/* + * 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_crowbar, + w_glock, + w_python, + w_mp5, + w_shotgun, + w_crossbow, + w_rpg, + w_gauss, + w_egon, + w_hornetgun, + w_handgrenade, + w_satchel, + w_tripmine, + w_snark +}; diff --git a/zpak001.pk3dir/default.cfg b/zpak001.pk3dir/default.cfg new file mode 100755 index 0000000..1aaebc3 --- /dev/null +++ b/zpak001.pk3dir/default.cfg @@ -0,0 +1,45 @@ +// 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" + +// Game Variables +seta "hostname" "FreeHL Server" +seta "maxplayers" "8" + +// 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/particles/fx_explosion.cfg b/zpak001.pk3dir/particles/fx_explosion.cfg new file mode 100644 index 0000000..33a6712 --- /dev/null +++ b/zpak001.pk3dir/particles/fx_explosion.cfg @@ -0,0 +1,69 @@ +r_part ember +{ + count 1 + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + rgb 255 128 76 + alpha 0 + scale 15 + scalefactor 1 + friction 8 + gravity 50 + die 1.5 + blend add + randomvel 5 + veladd 1 + rampmode delta + ramp 0 0 0 -0.5 0 + ramp 0 0 0 0.1 0 + ramp 0 0 0 0.1 0 + ramp 0 0 0 0.1 0 + ramp 0 0 0 0.1 0 + ramp 0 0 0 0.1 0 +} + +r_part expgib +{ + cliptype expgib + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + alpha 0 + count 16 + die 1 + randomvel 128 + gravity 50 + friction 2 + emit ember + emitinterval 0.01 + spawnmode circle +} + +r_part main +{ + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + count 1 + scale 200 + scalefactor 1 + die 1 + rgb 255 128 76 + rgbdelta 0 -32 -32 + friction 1 + blend add + assoc expgib +} + +r_part blacksmoke +{ + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + count 1 + scale 324 + scalefactor 1 + die 3 + alpha 1 + rgb 0 0 0 + spawnmode ball + gravity -25 + veladd -20 +} diff --git a/zpak001.pk3dir/particles/fx_impact.cfg b/zpak001.pk3dir/particles/fx_impact.cfg new file mode 100644 index 0000000..132c8b5 --- /dev/null +++ b/zpak001.pk3dir/particles/fx_impact.cfg @@ -0,0 +1,72 @@ +r_part spark +{ + type texturedspark + texture ball + tcoords 1 65 31 95 256 8 32 + scale 1 + count 8 + scalefactor 1 + alpha 0.5 + die 0.8 + rgb 255 115 0 + blend add + spawnmode ball + spawnorg 1 + spawnvel 100 + veladd 100 + friction 0.5 + gravity 800 +} + +r_part blackbits +{ + type ball + texture ball + tcoords 1 65 31 95 256 8 32 + scale 4 + count 18 + scalefactor 1 + alpha 1 + die 0.8 + rgb 25 25 25 + spawnmode ball + spawnorg 1 + spawnvel 100 + veladd 100 + friction 0.3 + gravity 800 +} + +r_part smoke_brown +{ + texture ball + tcoords 1 65 31 95 256 8 32 + count 3 + scale 25 + scalefactor 1 + die 1 + alpha 0.5 + rgb 155 90 0 + blend add + spawnmode ball + spawnorg 2 + spawnvel 20 + veladd 20 +} + +r_part smoke_grey +{ + texture ball + tcoords 1 65 31 95 256 8 32 + count 3 + scale 25 + scalefactor 1 + die 1 + alpha 0.5 + rgb 25 25 25 + blend add + spawnmode ball + spawnorg 2 + spawnvel 20 + veladd 20 +} diff --git a/zpak001.pk3dir/particles/fx_spark.cfg b/zpak001.pk3dir/particles/fx_spark.cfg new file mode 100644 index 0000000..62ee1a6 --- /dev/null +++ b/zpak001.pk3dir/particles/fx_spark.cfg @@ -0,0 +1,19 @@ +r_part effect +{ + type texturedspark + texture ball + tcoords 1 65 31 95 256 8 32 + scale 1 + count 8 + scalefactor 1 + alpha 0.5 + die 0.8 + rgb 255 115 0 + blend add + spawnmode ball + spawnorg 1 + spawnvel 100 + veladd 100 + friction 0.5 + gravity 800 +} diff --git a/zpak001.pk3dir/particles/weapon_egon.cfg b/zpak001.pk3dir/particles/weapon_egon.cfg new file mode 100644 index 0000000..9230c3e --- /dev/null +++ b/zpak001.pk3dir/particles/weapon_egon.cfg @@ -0,0 +1,43 @@ +r_part beam +{ + texture "classicparticle" + tcoords 0 0 16 16 32 + scale 1 + scalefactor 0.8 + step 1 + alpha 0.25 + spawnmode spiral 32 + spawnorg 3 + spawnvel 18 + blend adda + rgbf 0.5 0.5 1.0 +} +r_part +beam +{ + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + scale 2 + scaledelta 0.25 + rgbf 1 1 1 + alpha 0.25 + blend add + step 4 + randomvel 0 + type beam +} + +r_part trail +{ + texture "classicparticle" + tcoords 0 0 16 16 32 + scale 1 + scalefactor 0.8 + step 0.25 + alpha 0.1 + spawnmode spiral 32 + spawnorg 3 + spawnvel 6 + blend adda + rgbf 0.1 0.1 0.5 + die 0.1 +} diff --git a/zpak001.pk3dir/particles/weapon_hornet.cfg b/zpak001.pk3dir/particles/weapon_hornet.cfg new file mode 100644 index 0000000..dd8922d --- /dev/null +++ b/zpak001.pk3dir/particles/weapon_hornet.cfg @@ -0,0 +1,14 @@ +r_part trail +{ + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + scale 2 + scaledelta 0.25 + rgbf 1 0.5 0 + alpha 0.5 + blend add + step 4 + die 1 + randomvel 0 + type beam +} diff --git a/zpak001.pk3dir/particles/weapon_rpg.cfg b/zpak001.pk3dir/particles/weapon_rpg.cfg new file mode 100644 index 0000000..d655dbc --- /dev/null +++ b/zpak001.pk3dir/particles/weapon_rpg.cfg @@ -0,0 +1,14 @@ +r_part trail +{ + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + scale 2 + scaledelta 0.25 + rgbf 1 1 1 + alpha 0.5 + blend add + step 4 + die 2 + randomvel 0 + type beam +} diff --git a/zpak001.pk3dir/particles/weapon_tripmine.cfg b/zpak001.pk3dir/particles/weapon_tripmine.cfg new file mode 100644 index 0000000..d2dfc0d --- /dev/null +++ b/zpak001.pk3dir/particles/weapon_tripmine.cfg @@ -0,0 +1,14 @@ +r_part beam +{ + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + scale 1 + scaledelta 0.5 + alpha 0.4 + step 4 + randomvel 0 + rgb 0 255 200 + rgbdelta 0 -150 -150 + type beam + blend add +} diff --git a/zpak001.pk3dir/scripts/map_blacklist b/zpak001.pk3dir/scripts/map_blacklist new file mode 100644 index 0000000..50f09d7 --- /dev/null +++ b/zpak001.pk3dir/scripts/map_blacklist @@ -0,0 +1,106 @@ +c0a0.bsp +c0a0a.bsp +c0a0b.bsp +c0a0c.bsp +c0a0d.bsp +c0a0e.bsp +c1a0.bsp +c1a0a.bsp +c1a0b.bsp +c1a0c.bsp +c1a0d.bsp +c1a0e.bsp +c1a1.bsp +c1a1a.bsp +c1a1b.bsp +c1a1c.bsp +c1a1d.bsp +c1a1f.bsp +c1a2.bsp +c1a2a.bsp +c1a2b.bsp +c1a2c.bsp +c1a2d.bsp +c1a3.bsp +c1a3a.bsp +c1a3b.bsp +c1a3c.bsp +c1a3d.bsp +c1a4.bsp +c1a4b.bsp +c1a4d.bsp +c1a4e.bsp +c1a4f.bsp +c1a4g.bsp +c1a4i.bsp +c1a4j.bsp +c1a4k.bsp +c2a1.bsp +c2a1a.bsp +c2a1b.bsp +c2a2.bsp +c2a2a.bsp +c2a2b1.bsp +c2a2b2.bsp +c2a2c.bsp +c2a2d.bsp +c2a2e.bsp +c2a2f.bsp +c2a2g.bsp +c2a2h.bsp +c2a3.bsp +c2a3a.bsp +c2a3b.bsp +c2a3c.bsp +c2a3d.bsp +c2a3e.bsp +c2a4.bsp +c2a4a.bsp +c2a4b.bsp +c2a4c.bsp +c2a4d.bsp +c2a4e.bsp +c2a4f.bsp +c2a4g.bsp +c2a5.bsp +c2a5a.bsp +c2a5b.bsp +c2a5c.bsp +c2a5d.bsp +c2a5e.bsp +c2a5f.bsp +c2a5g.bsp +c2a5w.bsp +c2a5x.bsp +c3a1.bsp +c3a1a.bsp +c3a1b.bsp +c3a2.bsp +c3a2a.bsp +c3a2b.bsp +c3a2c.bsp +c3a2d.bsp +c3a2e.bsp +c3a2f.bsp +c4a1.bsp +c4a1a.bsp +c4a1b.bsp +c4a1c.bsp +c4a1d.bsp +c4a1e.bsp +c4a1f.bsp +c4a2.bsp +c4a2a.bsp +c4a2b.bsp +c4a3.bsp +c5a1.bsp +t0a0.bsp +t0a0a.bsp +t0a0b.bsp +t0a0b1.bsp +t0a0b2.bsp +t0a0c.bsp +t0a0d.bsp +hldemo1.bsp +hldemo2.bsp +hldemo3.bsp diff --git a/zpak001.pk3dir/skill_valve.cfg b/zpak001.pk3dir/skill_valve.cfg new file mode 100644 index 0000000..041d4ac --- /dev/null +++ b/zpak001.pk3dir/skill_valve.cfg @@ -0,0 +1,255 @@ +set sk_12mm_bullet1 "8" +set sk_12mm_bullet2 "10" +set sk_12mm_bullet3 "10" +set sk_9mmAR_bullet1 "3" +set sk_9mmAR_bullet2 "4" +set sk_9mmAR_bullet3 "5" +set sk_9mm_bullet1 "5" +set sk_9mm_bullet2 "5" +set sk_9mm_bullet3 "8" +set sk_agrunt_dmg_punch1 "10" +set sk_agrunt_dmg_punch2 "20" +set sk_agrunt_dmg_punch3 "20" +set sk_agrunt_health1 "60" +set sk_agrunt_health2 "90" +set sk_agrunt_health3 "120" +set sk_apache_health1 "150" +set sk_apache_health2 "250" +set sk_apache_health3 "400" +set sk_barnacle_health1 "25" +set sk_barnacle_health2 "25" +set sk_barnacle_health3 "25" +set sk_barney_health1 "35" +set sk_barney_health2 "35" +set sk_barney_health3 "35" +set sk_battery1 "15" +set sk_battery2 "15" +set sk_battery3 "10" +set sk_bigmomma_dmg_blast1 "100" +set sk_bigmomma_dmg_blast2 "120" +set sk_bigmomma_dmg_blast3 "160" +set sk_bigmomma_dmg_slash1 "50" +set sk_bigmomma_dmg_slash2 "60" +set sk_bigmomma_dmg_slash3 "70" +set sk_bigmomma_health_factor1 "1.0" +set sk_bigmomma_health_factor2 "1.5" +set sk_bigmomma_health_factor3 "2" +set sk_bigmomma_radius_blast1 "250" +set sk_bigmomma_radius_blast2 "250" +set sk_bigmomma_radius_blast3 "275" +set sk_bullsquid_dmg_bite1 "15" +set sk_bullsquid_dmg_bite2 "25" +set sk_bullsquid_dmg_bite3 "25" +set sk_bullsquid_dmg_spit1 "10" +set sk_bullsquid_dmg_spit2 "10" +set sk_bullsquid_dmg_spit3 "15" +set sk_bullsquid_dmg_whip1 "25" +set sk_bullsquid_dmg_whip2 "35" +set sk_bullsquid_dmg_whip3 "35" +set sk_bullsquid_health1 "40" +set sk_bullsquid_health2 "40" +set sk_bullsquid_health3 "120" +set sk_controller_dmgball1 "3" +set sk_controller_dmgball2 "4" +set sk_controller_dmgball3 "5" +set sk_controller_dmgzap1 "15" +set sk_controller_dmgzap2 "25" +set sk_controller_dmgzap3 "35" +set sk_controller_health1 "60" +set sk_controller_health2 "60" +set sk_controller_health3 "100" +set sk_controller_speedball1 "650" +set sk_controller_speedball2 "800" +set sk_controller_speedball3 "1000" +set sk_gargantua_dmg_fire1 "3" +set sk_gargantua_dmg_fire2 "5" +set sk_gargantua_dmg_fire3 "5" +set sk_gargantua_dmg_slash1 "10" +set sk_gargantua_dmg_slash2 "30" +set sk_gargantua_dmg_slash3 "30" +set sk_gargantua_dmg_stomp1 "50" +set sk_gargantua_dmg_stomp2 "100" +set sk_gargantua_dmg_stomp3 "100" +set sk_gargantua_health1 "800" +set sk_gargantua_health2 "800" +set sk_gargantua_health3 "1000" +set sk_hassassin_health1 "30" +set sk_hassassin_health2 "50" +set sk_hassassin_health3 "50" +set sk_headcrab_dmg_bite1 "5" +set sk_headcrab_dmg_bite2 "10" +set sk_headcrab_dmg_bite3 "10" +set sk_headcrab_health1 "10" +set sk_headcrab_health2 "10" +set sk_headcrab_health3 "20" +set sk_healthcharger1 "50" +set sk_healthcharger2 "40" +set sk_healthcharger3 "25" +set sk_healthkit1 "15" +set sk_healthkit2 "15" +set sk_healthkit3 "10" +set sk_hgrunt_gspeed1 "400" +set sk_hgrunt_gspeed2 "600" +set sk_hgrunt_gspeed3 "800" +set sk_hgrunt_health1 "50" +set sk_hgrunt_health2 "50" +set sk_hgrunt_health3 "80" +set sk_hgrunt_kick1 "5" +set sk_hgrunt_kick2 "10" +set sk_hgrunt_kick3 "10" +set sk_hgrunt_pellets1 "3" +set sk_hgrunt_pellets2 "5" +set sk_hgrunt_pellets3 "6" +set sk_hornet_dmg1 "4" +set sk_hornet_dmg2 "5" +set sk_hornet_dmg3 "8" +set sk_houndeye_dmg_blast1 "10" +set sk_houndeye_dmg_blast2 "15" +set sk_houndeye_dmg_blast3 "15" +set sk_houndeye_health1 "20" +set sk_houndeye_health2 "20" +set sk_houndeye_health3 "30" +set sk_ichthyosaur_health1 "200" +set sk_ichthyosaur_health2 "200" +set sk_ichthyosaur_health3 "400" +set sk_ichthyosaur_shake1 "20" +set sk_ichthyosaur_shake2 "35" +set sk_ichthyosaur_shake3 "50" +set sk_islave_dmg_claw1 "8" +set sk_islave_dmg_claw2 "10" +set sk_islave_dmg_claw3 "10" +set sk_islave_dmg_clawrake1 "25" +set sk_islave_dmg_clawrake2 "25" +set sk_islave_dmg_clawrake3 "25" +set sk_islave_dmg_zap1 "10" +set sk_islave_dmg_zap2 "10" +set sk_islave_dmg_zap3 "15" +set sk_islave_health1 "30" +set sk_islave_health2 "30" +set sk_islave_health3 "60" +set sk_leech_dmg_bite1 "2" +set sk_leech_dmg_bite2 "2" +set sk_leech_dmg_bite3 "2" +set sk_leech_health1 "2" +set sk_leech_health2 "2" +set sk_leech_health3 "2" +set sk_miniturret_health1 "40" +set sk_miniturret_health2 "40" +set sk_miniturret_health3 "50" +set sk_monster_arm1 "1" +set sk_monster_arm2 "1" +set sk_monster_arm3 "1" +set sk_monster_chest1 "1" +set sk_monster_chest2 "1" +set sk_monster_chest3 "1" +set sk_monster_head1 "3" +set sk_monster_head2 "3" +set sk_monster_head3 "3" +set sk_monster_leg1 "1" +set sk_monster_leg2 "1" +set sk_monster_leg3 "1" +set sk_monster_stomach1 "1" +set sk_monster_stomach2 "1" +set sk_monster_stomach3 "1" +set sk_nihilanth_health1 "800" +set sk_nihilanth_health2 "800" +set sk_nihilanth_health3 "1000" +set sk_nihilanth_zap1 "30" +set sk_nihilanth_zap2 "30" +set sk_nihilanth_zap3 "50" +set sk_player_arm1 "1" +set sk_player_arm2 "1" +set sk_player_arm3 "1" +set sk_player_chest1 "1" +set sk_player_chest2 "1" +set sk_player_chest3 "1" +set sk_player_head1 "3" +set sk_player_head2 "3" +set sk_player_head3 "3" +set sk_player_leg1 "1" +set sk_player_leg2 "1" +set sk_player_leg3 "1" +set sk_player_stomach1 "1" +set sk_player_stomach2 "1" +set sk_player_stomach3 "1" +set sk_plr_357_bullet1 "40" +set sk_plr_357_bullet2 "40" +set sk_plr_357_bullet3 "40" +set sk_plr_9mmAR_bullet1 "5" +set sk_plr_9mmAR_bullet2 "5" +set sk_plr_9mmAR_bullet3 "5" +set sk_plr_9mmAR_grenade1 "100" +set sk_plr_9mmAR_grenade2 "100" +set sk_plr_9mmAR_grenade3 "100" +set sk_plr_9mm_bullet1 "8" +set sk_plr_9mm_bullet2 "8" +set sk_plr_9mm_bullet3 "8" +set sk_plr_buckshot1 "5" +set sk_plr_buckshot2 "5" +set sk_plr_buckshot3 "5" +set sk_plr_crowbar1 "10" +set sk_plr_crowbar2 "10" +set sk_plr_crowbar3 "10" +set sk_plr_egon_narrow1 "6" +set sk_plr_egon_narrow2 "6" +set sk_plr_egon_narrow3 "6" +set sk_plr_egon_wide1 "14" +set sk_plr_egon_wide2 "14" +set sk_plr_egon_wide3 "14" +set sk_plr_gauss1 "20" +set sk_plr_gauss2 "20" +set sk_plr_gauss3 "20" +set sk_plr_hand_grenade1 "100" +set sk_plr_hand_grenade2 "100" +set sk_plr_hand_grenade3 "100" +set sk_plr_hornet1 "10" +set sk_plr_hornet2 "10" +set sk_plr_hornet3 "10" +set sk_plr_rpg1 "100" +set sk_plr_rpg2 "100" +set sk_plr_rpg3 "100" +set sk_plr_satchel1 "150" +set sk_plr_satchel2 "150" +set sk_plr_satchel3 "150" +set sk_plr_tripmine1 "150" +set sk_plr_tripmine2 "150" +set sk_plr_tripmine3 "150" +set sk_plr_xbow_bolt_client1 "10" +set sk_plr_xbow_bolt_client2 "10" +set sk_plr_xbow_bolt_client3 "10" +set sk_plr_xbow_bolt_monster1 "50" +set sk_plr_xbow_bolt_monster2 "50" +set sk_plr_xbow_bolt_monster3 "50" +set sk_scientist_heal1 "25" +set sk_scientist_heal2 "25" +set sk_scientist_heal3 "25" +set sk_scientist_health1 "20" +set sk_scientist_health2 "20" +set sk_scientist_health3 "20" +set sk_sentry_health1 "40" +set sk_sentry_health2 "40" +set sk_sentry_health3 "50" +set sk_snark_dmg_bite1 "10" +set sk_snark_dmg_bite2 "10" +set sk_snark_dmg_bite3 "10" +set sk_snark_dmg_pop1 "5" +set sk_snark_dmg_pop2 "5" +set sk_snark_dmg_pop3 "5" +set sk_snark_health1 "2" +set sk_snark_health2 "2" +set sk_snark_health3 "2" +set sk_suitcharger1 "75" +set sk_suitcharger2 "50" +set sk_suitcharger3 "35" +set sk_turret_health1 "50" +set sk_turret_health2 "50" +set sk_turret_health3 "60" +set sk_zombie_dmg_both_slash1 "25" +set sk_zombie_dmg_both_slash2 "40" +set sk_zombie_dmg_both_slash3 "40" +set sk_zombie_dmg_one_slash1 "10" +set sk_zombie_dmg_one_slash2 "20" +set sk_zombie_dmg_one_slash3 "20" +set sk_zombie_health1 "50" +set sk_zombie_health2 "50" +set sk_zombie_health3 "100" diff --git a/zpak001.pk3dir/sound/fx_valve.sndshd b/zpak001.pk3dir/sound/fx_valve.sndshd new file mode 100644 index 0000000..3e85fe7 --- /dev/null +++ b/zpak001.pk3dir/sound/fx_valve.sndshd @@ -0,0 +1,7 @@ +fx.explosion +{ + sample weapons/explode3.wav + sample weapons/explode4.wav + sample weapons/explode5.wav + shakes 1.5 +} diff --git a/zpak001.pk3dir/sound/items_valve.sndshd b/zpak001.pk3dir/sound/items_valve.sndshd new file mode 100644 index 0000000..b01e9df --- /dev/null +++ b/zpak001.pk3dir/sound/items_valve.sndshd @@ -0,0 +1,29 @@ +ammo.pickup +{ + sample items/9mmclip1.wav +} + +ammo.respawn +{ + sample items/suitchargeok1.wav +} + +item.battery +{ + sample items/gunpickup2.wav +} + +item.healthkit +{ + sample items/smallmedkit1.wav +} + +item.respawn +{ + sample items/suitchargeok1.wav +} + +weapon.pickup +{ + sample items/gunpickup2.wav +} diff --git a/zpak001.pk3dir/sound/monsters_valve.sndshd b/zpak001.pk3dir/sound/monsters_valve.sndshd new file mode 100644 index 0000000..ac95038 --- /dev/null +++ b/zpak001.pk3dir/sound/monsters_valve.sndshd @@ -0,0 +1,630 @@ +monster_alien_grunt.alert +{ + sample agrunt/ag_alert1.wav + sample agrunt/ag_alert2.wav + sample agrunt/ag_alert3.wav + sample agrunt/ag_alert4.wav + sample agrunt/ag_alert5.wav +} + +monster_alien_grunt.attack +{ + sample agrunt/ag_attack1.wav + sample agrunt/ag_attack2.wav + sample agrunt/ag_attack3.wav +} + +monster_alien_grunt.die +{ + sample agrunt/ag_die1.wav + sample agrunt/ag_die2.wav + sample agrunt/ag_die3.wav + sample agrunt/ag_die4.wav + sample agrunt/ag_die5.wav +} + +monster_alien_grunt.idle +{ + sample agrunt/ag_idle1.wav + sample agrunt/ag_idle2.wav + sample agrunt/ag_idle3.wav + sample agrunt/ag_idle4.wav + sample agrunt/ag_idle5.wav +} + +monster_alien_grunt.pain +{ + sample agrunt/ag_pain1.wav + sample agrunt/ag_pain2.wav + sample agrunt/ag_pain3.wav + sample agrunt/ag_pain4.wav + sample agrunt/ag_pain5.wav +} + +monster_alien_controller.alert +{ + sample controller/con_alert1.wav + sample controller/con_alert2.wav + sample controller/con_alert3.wav +} + +monster_alien_controller.attack +{ + sample controller/con_attack1.wav + sample controller/con_attack2.wav + sample controller/con_attack3.wav +} + +monster_alien_controller.die +{ + sample controller/con_die1.wav + sample controller/con_die2.wav +} + +monster_alien_controller.idle +{ + sample controller/con_idle1.wav + sample controller/con_idle2.wav + sample controller/con_idle3.wav + sample controller/con_idle4.wav + sample controller/con_idle5.wav +} + +monster_alien_controller.pain +{ + sample controller/con_pain1.wav + sample controller/con_pain2.wav + sample controller/con_pain3.wav +} + +monster_alien_slave.die +{ + sample aslave/slv_die1.wav + sample aslave/slv_die2.wav +} + +monster_alien_slave.pain +{ + sample aslave/slv_pain1.wav + sample aslave/slv_pain2.wav +} + +monster_alien_slave.attack_charge +{ + sample debris/zap4.wav +} + +monster_alien_slave.attack_shoot +{ + pitch_min 1.3 + pitch_max 1.6 + sample hassault/hw_shoot1.wav +} + +// bcl_bite3 is played when an entity is in it's mouth bcl_tongue1 unused? +monster_barnacle.attackchew +{ + sample barnacle/bcl_chew1.wav + sample barnacle/bcl_chew2.wav + sample barnacle/bcl_chew3.wav +} +monster_barnacle.attackpull +{ + sample barnacle/bcl_alert2.wav +} + +monster_barnacle.die +{ + sample barnacle/bcl_die1.wav + sample barnacle/bcl_die3.wav +} + +monster_barney.die +{ + sample barney/ba_die1.wav + sample barney/ba_die1.wav + sample barney/ba_die2.wav +} + +monster_barney.pain +{ + sample barney/ba_pain1.wav + sample barney/ba_pain1.wav + sample barney/ba_pain1.wav +} + +monster_bigmomma.alert +{ + sample gonarch/gon_alert1.wav + sample gonarch/gon_alert2.wav + sample gonarch/gon_alert3.wav +} + +// the groans for when she spits? +monster_bigmomma.attack +{ + sample gonarch/gon_attack1.wav + sample gonarch/gon_attack2.wav + sample gonarch/gon_attack3.wav +} + +/ mourns the death of her children +monster_bigmomma.child +{ + sample gonarch/gon_childdie1.wav + sample gonarch/gon_childdie2.wav + sample gonarch/gon_childdie3.wav +} + +monster_bigmomma.die +{ + sample gonarch/gon_die1.wav + sample gonarch/gon_die2.wav + sample gonarch/gon_die3.wav +} + +monster_bigmomma.idle +{ + sample gonarch/gon_sack1.wav + sample gonarch/gon_sack2.wav + sample gonarch/gon_sack3.wav +} + +monster_bigmomma.pain +{ + sample gonarch/gon_pain2.wav + sample gonarch/gon_pain3.wav + sample gonarch/gon_pain4.wav + sample gonarch/gon_pain5.wav +} + +// has unique foot step sounds +monster_bigmomma.step +{ + sample gonarch/gon_step1.wav + sample gonarch/gon_step2.wav + sample gonarch/gon_step3.wav +} + +monster_bullchicken.attack +{ + sample bullchicken/bc_attackgrowl1.wav + sample bullchicken/bc_attackgrowl2.wav + sample bullchicken/bc_attackgrowl3.wav +} + +monster_bullchicken.attackbite +{ + sample bullchicken/bc_bite1.wav + sample bullchicken/bc_bite2.wav + sample bullchicken/bc_bite3.wav +} + +monster_bullchicken.attackshoot +{ + sample bullchicken/bc_attack1.wav + sample bullchicken/bc_attack2.wav + sample bullchicken/bc_attack3.wav +} + +monster_bullchicken.die +{ + sample bullchicken/bc_die1.wav + sample bullchicken/bc_die2.wav + sample bullchicken/bc_die3.wav +} + +monster_bullchicken.idle +{ + sample bullchicken/bc_idle1.wav + sample bullchicken/bc_idle2.wav + sample bullchicken/bc_idle3.wav + sample bullchicken/bc_idle4.wav + sample bullchicken/bc_idle5.wav +} + +monster_bullchicken.pain +{ + sample bullchicken/bc_pain1.wav + sample bullchicken/bc_pain2.wav + sample bullchicken/bc_pain3.wav + sample bullchicken/bc_pain4.wav +} + +monster_cockroach.die +{ + sample roach/rch_die.wav + sample roach/rch_smash.wav +} + +monster_gargantua.alert +{ + sample garg/gar_alert1.wav + sample garg/gar_alert2.wav + sample garg/gar_alert3.wav +} + +// similar to bullsquid groans during and after attacks +monster_gargantua.attack +{ + sample garg/gar_attack1.wav + sample garg/gar_attack2.wav + sample garg/gar_attack3.wav +} + +monster_gargantua.attackflame +{ + sample garg/gar_flamerun1.wav +} + +monster_gargantua.attackflameoff +{ + sample garg/gar_flameoff1.wav +} + +monster_gargantua.attackflameon +{ + sample garg/gar_flameon1.wav +} + + +monster_gargantua.die +{ + sample garg/gar_die1.wav + sample garg/gar_die2.wav +} + +monster_gargantua.idle +{ + sample garg/gar_idle1.wav + sample garg/gar_idle2.wav + sample garg/gar_idle3.wav + sample garg/gar_idle4.wav + sample garg/gar_idle5.wav + sample garg/gar_breathe1.wav + sample garg/gar_breathe2.wav + sample garg/gar_breathe3.wav +} + +monster_gargantua.pain +{ + sample garg/gar_pain1.wav + sample garg/gar_pain2.wav + sample garg/gar_pain3.wav +} + +// has unique foot step sounds +monster_gargantua.step +{ + sample garg/gar_step1.wav + sample garg/gar_step2.wav +} + +monster_headcrab.alert +{ + sample headcrab/hc_alert1.wav + sample headcrab/hc_alert2.wav +} + +// these attack sounds are actually the cry when it jumps +monster_headcrab.attack +{ + sample headcrab/hc_attack1.wav + sample headcrab/hc_attack2.wav + sample headcrab/hc_attack3.wav +} + +monster_headcrab.attackhit +{ + sample headcrab/hc_headbite.wav +} + +monster_headcrab.die +{ + sample headcrab/hc_die1.wav + sample headcrab/hc_die2.wav +} + +monster_headcrab.idle +{ + sample headcrab/hc_idle1.wav + sample headcrab/hc_idle2.wav + sample headcrab/hc_idle3.wav + sample headcrab/hc_idle4.wav + sample headcrab/hc_idle5.wav +} + +monster_headcrab.pain +{ + sample headcrab/hc_pain1.wav + sample headcrab/hc_pain2.wav + sample headcrab/hc_pain3.wav +} + +monster_houndeye.alert +{ + sample houndeye/he_alert1.wav + sample houndeye/he_alert2.wav + sample houndeye/he_alert3.wav +} + +monster_houndeye.attack +{ + sample houndeye/he_attack1.wav + sample houndeye/he_attack2.wav + sample houndeye/he_attack3.wav +} + +monster_houndeye.blast +{ + sample houndeye/he_blast1.wav + sample houndeye/he_blast2.wav + sample houndeye/he_blast3.wav +} + + +monster_houndeye.die +{ + sample houndeye/he_die1.wav + sample houndeye/he_die2.wav + sample houndeye/he_die3.wav +} + +// Not sure where the hunt sounds are actually used +monster_houndeye.idle +{ + sample houndeye/he_hunt1.wav + sample houndeye/he_hunt2.wav + sample houndeye/he_hunt3.wav + sample houndeye/he_hunt4.wav + sample houndeye/he_idle1.wav + sample houndeye/he_idle2.wav + sample houndeye/he_idle3.wav + sample houndeye/he_idle4.wav +} + +monster_houndeye.pain +{ + sample houndeye/he_pain1.wav + sample houndeye/he_pain2.wav + sample houndeye/he_pain3.wav + sample houndeye/he_pain4.wav + sample houndeye/he_pain5.wav +} + +monster_human_grunt.die +{ + sample hgrunt/gr_die1.wav + sample hgrunt/gr_die2.wav + sample hgrunt/gr_die3.wav +} + +monster_human_grunt.pain +{ + sample hgrunt/gr_pain1.wav + sample hgrunt/gr_pain2.wav + sample hgrunt/gr_pain3.wav + sample hgrunt/gr_pain4.wav + sample hgrunt/gr_pain5.wav +} + +monster_ichthyosaur.alert +{ + sample ichy/ichy_alert1.wav + sample ichy/ichy_alert2.wav + sample ichy/ichy_alert3.wav +} + +monster_ichthyosaur.attack +{ + sample ichy/ichy_attack1.wav + sample ichy/ichy_attack2.wav +} + +monster_ichthyosaur.die +{ + sample ichy/ichy_die1.wav + sample ichy/ichy_die2.wav + sample ichy/ichy_die3.wav + sample ichy/ichy_die4.wav +} + +monster_ichthyosaur.idle +{ + sample ichy/ichy_idle1.wav + sample ichy/ichy_idle2.wav + sample ichy/ichy_idle3.wav + sample ichy/ichy_idle4.wav +} + +monster_ichthyosaur.pain +{ + sample ichy/ichy_pain1.wav + sample ichy/ichy_pain2.wav + sample ichy/ichy_pain3.wav + sample ichy/ichy_pain4.wav + sample ichy/ichy_pain5.wav +} + +monster_leech.alert +{ + sample leech/leech_alert1.wav + sample leech/leech_alert2.wav +} + +monster_leech.attack +{ + sample leech/leech_bite1.wav + sample leech/leech_bite2.wav + sample leech/leech_bite3.wav +} + +// other sounds +// * x_shoot1 - ? +// * nih_die2 - used in map not code? + +// these attack sounds are his growls +monster_nihilanth.attack +{ + sample x/x_attack1.wav + sample x/x_attack2.wav + sample x/x_attack3.wav +} + +monster_nihilanth.attackball +{ + sample x/x_ballattack1.wav +} + +monster_nihilanth.attackballmove +{ + sample x/x_teleattack1.wav +} + +monster_nihilanth.die +{ + sample x/x_die1.wav +} + +monster_nihilanth.idle +{ + sample x/x_laugh1.wav + sample x/x_laugh2.wav +} + +monster_nihilanth.pain +{ + sample x/x_pain1.wav + sample x/x_pain2.wav + sample x/x_pain3.wav +} + +monster_nihilanth.recharge +{ + sample x/x_recharge1.wav + sample x/x_recharge2.wav + sample x/x_recharge3.wav +} + +monster_scientist.die +{ + sample scientist/sci_die1.wav + sample scientist/sci_die2.wav + sample scientist/sci_die3.wav + sample scientist/sci_die4.wav +} + +monster_scientist.pain +{ + sample scientist/sci_pain1.wav + sample scientist/sci_pain2.wav + sample scientist/sci_pain3.wav + sample scientist/sci_pain4.wav + sample scientist/sci_pain5.wav + sample scientist/sci_pain6.wav + sample scientist/sci_pain7.wav + sample scientist/sci_pain8.wav + sample scientist/sci_pain9.wav + sample scientist/sci_pain10.wav +} + +monster_sentry.alert +{ + sample turret/tu_deploy.wav +} + +monster_sentry.die +{ + sample turret/tu_die.wav + sample turret/tu_die2.wav + sample turret/tu_die3.wav +} + +monster_sentry.idle +{ + sample turret/tu_ping.wav +} + +monster_sentry.retract +{ + sample turret/tu_retract.wav +} + +// cut sounds listing here because why not +monster_tentacle.alert +{ + sample tentacle/te_alert1.wav + sample tentacle/te_alert2.wav +} + +monster_tentacle.attack +{ + sample tentacle/te_strike1.wav + sample tentacle/te_strike2.wav +} + +monster_tentacle.die +{ + sample tentacle/te_death2.wav +} + +// includes some cut sounds might be interesting +monster_tentacle.idle +{ + sample tentacle/te_roar1.wav + sample tentacle/te_roar2.wav + sample tentacle/te_search1.wav + sample tentacle/te_search2.wav + sample tentacle/te_sing1.wav + sample tentacle/te_sing2.wav +} + +monster_turret.spindown +{ + sample turret/tu_spindown.wav +} + +monster_turret.spinup +{ + sample turret/tu_spinup.wav +} + +monster_zombie.alert +{ + sample zombie/zo_alert10.wav + sample zombie/zo_alert20.wav + sample zombie/zo_alert30.wav +} + +monster_zombie.attack +{ + sample zombie/zo_attack1.wav + sample zombie/zo_attack2.wav +} + +monster_zombie.attackhit +{ + sample zombie/claw_strike1.wav + sample zombie/claw_strike2.wav + sample zombie/claw_strike3.wav +} + +monster_zombie.attackmiss +{ + sample zombie/claw_miss1.wav + sample zombie/claw_miss2.wav +} + +monster_zombie.idle +{ + sample zombie/zo_idle1.wav + sample zombie/zo_idle2.wav + sample zombie/zo_idle3.wav + sample zombie/zo_idle4.wav +} + +monster_zombie.pain +{ + sample zombie/zo_pain1.wav + sample zombie/zo_pain2.wav +} diff --git a/zpak001.pk3dir/sound/player_valve.sndshd b/zpak001.pk3dir/sound/player_valve.sndshd new file mode 100644 index 0000000..3adbb07 --- /dev/null +++ b/zpak001.pk3dir/sound/player_valve.sndshd @@ -0,0 +1,12 @@ +player.fall +{ + sample player/pl_fallpain3.wav +} +player.lightfall +{ + sample player/pl_fallpain1.wav +} +player.die +{ + sample fvox/flatline.wav +} diff --git a/zpak001.pk3dir/sound/weapons_valve.sndshd b/zpak001.pk3dir/sound/weapons_valve.sndshd new file mode 100644 index 0000000..069f3ae --- /dev/null +++ b/zpak001.pk3dir/sound/weapons_valve.sndshd @@ -0,0 +1,166 @@ +weapon_357.shoot +{ + sample weapons/357_shot1.wav + sample weapons/357_shot2.wav +} + +weapon_357.reload +{ + sample weapons/357_reload1.wav +} + +weapon_crossbow.fire +{ + sample weapons/xbow_fire1.wav +} + +weapon_crossbow.hit +{ + sample weapons/xbow_hit1.wav +} + +weapon_crossbow.hitbody +{ + sample weapons/xbow_hitbod1.wav + sample weapons/xbow_hitbod2.wav +} + +weapon_crossbow.reload +{ + sample weapons/xbow_reload1.wav +} + +weapon_crowbar.hit +{ + sample weapons/cbar_hit1.wav + sample weapons/cbar_hit2.wav +} + +weapon_crowbar.hitbody +{ + sample weapons/cbar_hitbod1.wav + sample weapons/cbar_hitbod2.wav + sample weapons/cbar_hitbod3.wav +} + +weapon_crowbar.miss +{ + sample weapons/cbar_miss1.wav +} + +weapon_glock.fire +{ + sample weapons/pl_gun3.wav +} + +weapon_handgrenade.bounce +{ + sample weapons/grenade_hit1.wav + sample weapons/grenade_hit2.wav + sample weapons/grenade_hit3.wav +} + +weapon_hornetgun.fire +{ + sample agrunt/ag_fire1.wav + sample agrunt/ag_fire2.wav + sample agrunt/ag_fire3.wav +} + +weapon_hornetgun.buzz +{ + sample hornet/ag_buzz1.wav + sample hornet/ag_buzz2.wav + sample hornet/ag_buzz3.wav +} + +weapon_hornetgun.hit +{ + sample hornet/ag_hornethit1.wav + sample hornet/ag_hornethit2.wav + sample hornet/ag_hornethit3.wav +} + +weapon_mp5.shoot +{ + sample weapons/hks1.wav + sample weapons/hks2.wav +} + +weapon_mp5.gl +{ + sample weapons/glauncher.wav +} + +weapon_satchel.bounce +{ + sample weapons/g_bounce1.wav + sample weapons/g_bounce2.wav + sample weapons/g_bounce3.wav + sample weapons/g_bounce4.wav + sample weapons/g_bounce5.wav +} + +weapon_tripmine.deploy +{ + sample weapons/mine_deploy.wav +} + +weapon_tripmine.charge +{ + sample weapons/mine_charge.wav +} + +weapon_tripmine.activate +{ + sample weapons/mine_activate.wav +} + +weapon_rpg.shoot +{ + sample weapons/rocketfire1.wav +} + +weapon_shotgun.single +{ + sample weapons/sbarrel1.wav +} + +weapon_shotgun.double +{ + sample weapons/dbarrel1.wav +} + +weapon_shotgun.reload +{ + sample weapons/reload3.wav +} + +weapon_shotgun.cock +{ + sample weapons/scock1.wav +} + +weapon_snark.deploy +{ + pitch_min 1.0 + pitch_max 1.1 + sample squeek/sqk_deploy1.wav +} + +weapon_snark.die +{ + sample squeek/sqk_die1.wav +} + +weapon_snark.blast +{ + sample squeek/sqk_blast1.wav +} + +weapon_snark.hunt +{ + sample squeek/sqk_hunt1.wav + sample squeek/sqk_hunt2.wav + sample squeek/sqk_hunt3.wav +}

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 literal 0 HcmV?d00001 diff --git a/img/preview3.jpg b/img/preview3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ad0c591ad635c0fe50d29ebeb6f0749856494a1d GIT binary patch literal 94432 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 LzOX`4#76ZB#$RlRSNJP84p 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 literal 0 HcmV?d00001 diff --git a/img/preview4.jpg b/img/preview4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3bff75aba9cd86bf4ff8ab2aafc4e62443b1d177 GIT binary patch literal 122773 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 z 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