Initial commit, carried over from Nuclide's Git on March 8th 2021

This commit is contained in:
Marco Cawthorne 2021-03-08 11:40:33 +01:00
commit 1ec97ee732
35 changed files with 4477 additions and 0 deletions

15
LICENSE Normal file
View File

@ -0,0 +1,15 @@
ISC License
Copyright (c) 2016-2021, Marco "eukara" Hladik <marco@icculus.org>
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.

38
README.md Normal file
View File

@ -0,0 +1,38 @@
# FreeSci
Clean-room reimplementation of They Hunger in QuakeC.
![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 hunger
then either run Nuclide's ./build_game.sh shell script, or issue 'make' inside
./hunger/src!
Obviously make sure that Nuclide has fteqw and fteqcc set-up for building.
## Community
Join us on #halflife or #hunger via irc.frag-net.com and chat.
## License
ISC License
Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
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.

BIN
img/preview1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
img/preview2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

BIN
img/preview3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

BIN
img/preview4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

5
src/Makefile Normal file
View File

@ -0,0 +1,5 @@
CC=fteqcc
all:
cd client && $(MAKE)
cd server && $(MAKE)

4
src/client/Makefile Normal file
View File

@ -0,0 +1,4 @@
CC=fteqcc
all:
$(CC) progs.src

65
src/client/init.qc Normal file
View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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(entity foo, float chanid) getchannellevel = #0;
/*
=================
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();
precache_model("sprites/640hud1.spr");
precache_model("sprites/640hud2.spr");
precache_model("sprites/640hud3.spr");
precache_model("sprites/640hud4.spr");
precache_model("sprites/640hud5.spr");
precache_model("sprites/640hud6.spr");
precache_model("sprites/tfchud01.spr");
precache_model("sprites/tfchud02.spr");
precache_model("sprites/tfchud03.spr");
precache_model("sprites/tfchud04.spr");
precache_model("sprites/tfchud05.spr");
precache_model("sprites/tfchud06.spr");
precache_model("sprites/tfc_dmsg.spr");
precache_model("sprites/nmxhair2.spr");
BEAM_TRIPMINE = particleeffectnum("weapon_tripmine.beam");
}

39
src/client/progs.src Normal file
View File

@ -0,0 +1,39 @@
#pragma target fte
#pragma progs_dat "../../csprogs.dat"
#define CSQC
#define CLIENT
#define VALVE
#define HUNGER
#define CLASSIC_VGUI
#define GS_RENDERFX
#includelist
../../../src/shared/fteextensions.qc
../../../src/shared/defs.h
../../../valve/src/client/defs.h
../../../src/client/defs.h
../../../src/vgui/include.src
../../../src/gs-entbase/client.src
../../../src/gs-entbase/shared.src
../shared/include.src
../../../valve/src/client/predict.qc
init.qc
../../../valve/src/client/player.qc
../../../valve/src/client/entities.qc
../../../valve/src/client/cmds.qc
../../../valve/src/client/game_event.qc
../../../valve/src/client/view.qc
../../../valve/src/client/obituary.qc
../../../valve/src/client/hud.qc
../../../valve/src/client/hud_weaponselect.qc
../../../valve/src/client/scoreboard.qc
../../../valve/src/client/input.qc
../../../base/src/client/modelevent.qc
../../../src/client/include.src
../../../src/shared/include.src
#endlist

2
src/progs.src Executable file
View File

@ -0,0 +1,2 @@
#pragma sourcefile client/progs.src
#pragma sourcefile server/progs.src

4
src/server/Makefile Normal file
View File

@ -0,0 +1,4 @@
CC=fteqcc
all:
$(CC) progs.src

132
src/server/ammo_th.qc Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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 ammo_th_ap9 (0 0 0.8) (-16 -16 0) (16 16 32)
THEY HUNGER (1999) ENTITY
Ammo for the Flamethrower.
A single ammo_egonclip will provide 25, er, gas.
*/
class ammo_egonclip:item_ammo
{
void(void) ammo_egonclip;
virtual void(void) touch;
};
void ammo_egonclip::ammo_egonclip(void)
{
model = "models/w_gas.mdl";
item_ammo::item_ammo();
}
void ammo_egonclip::touch(void)
{
if not (other.flags & FL_CLIENT) {
return;
}
if (other.classname == "player") {
player pl = (player)other;
if (pl.ammo_gas < MAX_A_GAS) {
pl.ammo_gas = bound(0, pl.ammo_gas + 25, MAX_A_GAS);
Sound_Play(other, CHAN_ITEM, "ammo_gas.pickup");
item_ammo::touch();
}
}
}
/*QUAKED ammo_th_ap9 (0 0 0.8) (-16 -16 0) (16 16 32)
THEY HUNGER (1999) ENTITY
Ammo for the AP9.
A single ammo_th_ap9 will provide 40 bullets.
*/
class ammo_th_ap9:item_ammo
{
void(void) ammo_th_ap9;
virtual void(void) touch;
};
void ammo_th_ap9::ammo_th_ap9(void)
{
model = "models/w_ap9clip.mdl";
item_ammo::item_ammo();
}
void ammo_th_ap9::touch(void)
{
if not (other.flags & FL_CLIENT) {
return;
}
if (other.classname == "player") {
player pl = (player)other;
if (pl.ammo_ap9 < MAX_A_AP9) {
pl.ammo_ap9 = bound(0, pl.ammo_ap9 + 40, MAX_A_AP9);
item_ammo::touch();
}
}
}
/*QUAKED ammo_einar1 (0 0 0.8) (-16 -16 0) (16 16 32)
THEY HUNGER (1999) ENTITY
Ammo for the Snipers.
A single ammo_th_sniper will provide 5 bullets.
Same as ammo_th_sniper
*/
/*QUAKED ammo_th_sniper (0 0 0.8) (-16 -16 0) (16 16 32)
THEY HUNGER (1999) ENTITY
Ammo for the Snipers.
A single ammo_th_sniper will provide 5 bullets.
Same as ammo_einar1
*/
class ammo_th_sniper:item_ammo
{
void(void) ammo_th_sniper;
virtual void(void) touch;
};
void ammo_th_sniper::ammo_th_sniper(void)
{
model = "models/w_antidote.mdl";
item_ammo::item_ammo();
}
void ammo_th_sniper::touch(void)
{
if not (other.flags & FL_CLIENT) {
return;
}
if (other.classname == "player") {
player pl = (player)other;
if (pl.ammo_sniper < MAX_A_SNIPER) {
pl.ammo_sniper = bound(0, pl.ammo_sniper + 5, MAX_A_SNIPER);
item_ammo::touch();
}
}
}
CLASSEXPORT(ammo_einar1, ammo_th_sniper)

86
src/server/input.qc Normal file
View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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)
{
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_SHOVEL, -1);
Weapons_AddItem(pl, WEAPON_SPANNER, -1);
Weapons_AddItem(pl, WEAPON_GLOCK, -1);
Weapons_AddItem(pl, WEAPON_PYTHON, -1);
Weapons_AddItem(pl, WEAPON_AP9, -1);
Weapons_AddItem(pl, WEAPON_TAURUS, -1);
Weapons_AddItem(pl, WEAPON_MP5, -1);
Weapons_AddItem(pl, WEAPON_SHOTGUN, -1);
Weapons_AddItem(pl, WEAPON_CROSSBOW, -1);
Weapons_AddItem(pl, WEAPON_SNIPER, -1);
Weapons_AddItem(pl, WEAPON_SNIPER2, -1);
Weapons_AddItem(pl, WEAPON_RPG, -1);
Weapons_AddItem(pl, WEAPON_GAUSS, -1);
Weapons_AddItem(pl, WEAPON_EGON, -1);
Weapons_AddItem(pl, WEAPON_CHAINGUN, -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);
Weapons_AddItem(pl, WEAPON_MEDKIT, -1);
}
if (self.impulse == 102) {
// Respawn all the entities
for (entity a = world; (a = findfloat(a, ::identity, 1));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
bprint(PRINT_HIGH, "Respawning all map entities...\n");
}
}
self.impulse = 0;
}

91
src/server/progs.src Executable file
View File

@ -0,0 +1,91 @@
#pragma target fte
#pragma progs_dat "../../progs.dat"
#define QWSSQC
#define SERVER
#define VALVE
#define HUNGER
#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
../../../valve/src/server/defs.h
../../../valve/src/server/monster_apache.qc
../../../valve/src/server/monster_alien_controller.qc
../../../valve/src/server/monster_alien_grunt.qc
../../../valve/src/server/monster_alien_slave.qc
../../../valve/src/server/monster_barnacle.qc
../../../valve/src/server/monster_barney.qc
../../../valve/src/server/monster_barney_dead.qc
../../../valve/src/server/monster_bigmomma.qc
../../../valve/src/server/monster_bloater.qc
../../../valve/src/server/monster_bullchicken.qc
../../../valve/src/server/monster_cockroach.qc
../../../valve/src/server/monster_flyer_flock.qc
../../../valve/src/server/monster_gargantua.qc
../../../valve/src/server/monster_gman.qc
../../../valve/src/server/monster_headcrab.qc
../../../valve/src/server/monster_babycrab.qc
../../../valve/src/server/monster_hevsuit_dead.qc
../../../valve/src/server/monster_houndeye.qc
../../../valve/src/server/monster_human_grunt.qc
../../../valve/src/server/monster_hgrunt_dead.qc
../../../valve/src/server/monster_human_assassin.qc
../../../valve/src/server/monster_ichthyosaur.qc
../../../valve/src/server/monster_leech.qc
../../../valve/src/server/monster_miniturret.qc
../../../valve/src/server/monster_nihilanth.qc
../../../valve/src/server/monster_osprey.qc
../../../valve/src/server/monster_rat.qc
../../../valve/src/server/monster_scientist_dead.qc
../../../valve/src/server/monster_sitting_scientist.qc
../../../valve/src/server/monster_scientist.qc
../../../valve/src/server/monster_sentry.qc
../../../valve/src/server/monster_tentacle.qc
../../../valve/src/server/monster_turret.qc
../../../valve/src/server/monster_zombie.qc
../../../valve/src/server/player.qc
../../../valve/src/server/spectator.qc
../../../valve/src/server/items.qc
../../../valve/src/server/item_longjump.qc
../../../valve/src/server/item_suit.qc
../../../valve/src/server/item_healthkit.qc
../../../valve/src/server/item_battery.qc
../../../valve/src/server/item_weaponbox.qc
../../../valve/src/server/world_items.qc
../../../valve/src/server/xen_spore_small.qc
../../../valve/src/server/xen_spore_medium.qc
../../../valve/src/server/xen_spore_large.qc
../../../valve/src/server/xen_hair.qc
../../../valve/src/server/xen_plantlight.qc
../../../valve/src/server/ammo.qc
ammo_th.qc
../../../src/botlib/include.src
../../../valve/src/server/gamerules.qc
../../../valve/src/server/gamerules_singleplayer.qc
../../../valve/src/server/gamerules_multiplayer.qc
../../../valve/src/server/client.qc
../../../valve/src/server/server.qc
../../../valve/src/server/damage.qc
../../../valve/src/server/rules.qc
../../../valve/src/server/flashlight.qc
../../../base/src/server/modelevent.qc
input.qc
../../../valve/src/server/spawn.qc
../../../src/server/include.src
../../../src/shared/include.src
#endlist

46
src/shared/include.src Normal file
View File

@ -0,0 +1,46 @@
#includelist
../../../valve/src/shared/entities.h
../../../valve/src/shared/flags.h
player.qc
../../../valve/src/shared/weapon_common.h
../../../valve/src/shared/animations.h
../../../valve/src/shared/animations.qc
../../../valve/src/shared/pmove.qc
../../../valve/src/shared/pmove_water.qc
../../../valve/src/shared/fx_blood.qc
../../../valve/src/shared/fx_breakmodel.qc
../../../valve/src/shared/fx_explosion.qc
../../../valve/src/shared/fx_gibhuman.qc
../../../valve/src/shared/fx_spark.qc
../../../valve/src/shared/fx_impact.qc
items.h
weapons.h
../../../valve/src/shared/w_crossbow.qc
../../../valve/src/shared/w_crowbar.qc
../../../valve/src/shared/w_egon.qc
../../../valve/src/shared/w_gauss.qc
../../../valve/src/shared/w_glock.qc
../../../valve/src/shared/w_handgrenade.qc
../../../valve/src/shared/w_mp5.qc
../../../valve/src/shared/w_python.qc
../../../valve/src/shared/w_rpg.qc
../../../valve/src/shared/w_satchel.qc
../../../valve/src/shared/w_shotgun.qc
../../../valve/src/shared/w_snark.qc
../../../valve/src/shared/w_tripmine.qc
w_ap9.qc
w_chaingun.qc
w_flame.qc
w_silencer.qc
w_medkit.qc
w_shovel.qc
w_sniper.qc
w_sniper2.qc
w_spanner.qc
w_taurus.qc
w_tnt.qc
weapons.qc
../../../valve/src/shared/weapon_common.qc
#endlist

51
src/shared/items.h Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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 0x00000001
#define ITEM_GLOCK 0x00000002
#define ITEM_PYTHON 0x00000004
#define ITEM_MP5 0x00000008
#define ITEM_CROSSBOW 0x00000010
#define ITEM_SHOTGUN 0x00000020
#define ITEM_RPG 0x00000040
#define ITEM_GAUSS 0x00000080
#define ITEM_EGON 0x00000100
#define ITEM_CHAINGUN 0x00000200
#define ITEM_HANDGRENADE 0x00000400
#define ITEM_TRIPMINE 0x00000800
#define ITEM_SATCHEL 0x00001000
#define ITEM_SNARK 0x00002000
#define ITEM_SUIT 0x00004000
#define ITEM_LONGJUMP 0x00008000
#define ITEM_SHOVEL 0x00010000
#define ITEM_SPANNER 0x00020000
#define ITEM_AP9 0x00040000
#define ITEM_TAURUS 0x00080000
#define ITEM_SNIPER 0x00100000
#define ITEM_SNIPER2 0x00200000
#define ITEM_MEDKIT2 0x00400000
#define ITEM_UNUSED24 0x00800000
#define ITEM_UNUSED25 0x01000000
#define ITEM_UNUSED26 0x02000000
#define ITEM_UNUSED27 0x04000000
#define ITEM_UNUSED28 0x08000000
#define ITEM_UNUSED29 0x10000000
#define ITEM_UNUSED30 0x20000000
#define ITEM_UNUSED31 0x40000000
#define ITEM_UNUSED32 0x80000000

785
src/shared/player.qc Normal file
View File

@ -0,0 +1,785 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
*
* 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_shotgun_state;
int ammo_shotgun_state_net;
int ammo_gauss_state;
int ammo_gauss_state_net;
int ammo_gauss_volume;
int ammo_gauss_volume_net;
int ammo_egon_state;
int ammo_egon_state_net;
int ammo_rpg_state;
int ammo_rpg_state_net;
int mode_tempstate;
int mode_tempstate_net;
/* hunger */
int sniper_mag; int sniper_mag_net;
int chaingun_mag; int chaingun_mag_net;
int ap9_mag; int ap9_mag_net;
int taurus_mag; int taurus_mag_net;
int ammo_ap9; int ammo_ap9_net;
int ammo_taurus; int ammo_taurus_net;
int ammo_bolt; int ammo_bolt_net;
int ammo_sniper; int ammo_sniper_net;
int ammo_medkit; int ammo_medkit_net;
int ammo_gas; int ammo_gas_net;
int mode_silencer; int mode_silencer_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();
/* hunger */
sniper_mag = readbyte();
chaingun_mag = readbyte();
ap9_mag = readbyte();
taurus_mag = 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();
/* hunger */
ammo_ap9 = readbyte();
ammo_taurus = readbyte();
ammo_bolt = readbyte();
ammo_sniper = readbyte();
ammo_medkit = readbyte();
ammo_gas = readbyte();
}
if (fl & PLAYER_AMMO3) {
ammo_m203_grenade = readbyte();
ammo_shotgun_state = readbyte();
ammo_gauss_state = readbyte();
ammo_gauss_volume = readbyte();
ammo_egon_state = readbyte();
ammo_rpg_state = readbyte();
mode_tempstate = readbyte();
mode_silencer = 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_shotgun_state_net = ammo_shotgun_state;
ammo_gauss_state_net = ammo_gauss_state;
ammo_gauss_volume_net = ammo_gauss_volume;
ammo_egon_state_net = ammo_egon_state;
ammo_rpg_state_net = ammo_rpg_state;
mode_tempstate_net = mode_tempstate;
/* gearbox */
sniper_mag_net = sniper_mag;
chaingun_mag_net = chaingun_mag;
ap9_mag_net = ap9_mag;
taurus_mag_net = taurus_mag;
ammo_ap9_net = ammo_ap9;
ammo_taurus_net = ammo_taurus;
ammo_bolt_net = ammo_bolt;
ammo_sniper_net = ammo_sniper;
ammo_medkit_net = ammo_medkit;
ammo_gas_net = ammo_gas;
mode_silencer_net = mode_silencer;
}
/*
=================
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_shotgun_state = ammo_shotgun_state_net;
ammo_gauss_state = ammo_gauss_state_net;
ammo_gauss_volume = ammo_gauss_volume_net;
ammo_egon_state = ammo_egon_state_net;
ammo_rpg_state = ammo_rpg_state_net;
mode_tempstate = mode_tempstate_net;
/* hunger */
sniper_mag = sniper_mag_net;
chaingun_mag = chaingun_mag_net;
ap9_mag = ap9_mag_net;
taurus_mag = taurus_mag_net;
ammo_ap9 = ammo_ap9_net;
ammo_taurus = ammo_taurus_net;
ammo_bolt = ammo_bolt_net;
ammo_sniper = ammo_sniper_net;
ammo_medkit = ammo_medkit_net;
ammo_gas = ammo_gas_net;
mode_silencer = mode_silencer_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_shotgun_state != ammo_shotgun_state_net) {
SendFlags |= PLAYER_AMMO3;
}
if (ammo_gauss_state != ammo_gauss_state_net) {
SendFlags |= PLAYER_AMMO3;
}
if (ammo_gauss_volume != ammo_gauss_volume_net) {
SendFlags |= PLAYER_AMMO3;
}
if (ammo_egon_state != ammo_egon_state_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_shotgun_state_net = ammo_shotgun_state;
ammo_gauss_state_net = ammo_gauss_state;
ammo_gauss_volume_net = ammo_gauss_volume;
ammo_egon_state_net = ammo_egon_state;
ammo_rpg_state_net = ammo_rpg_state;
mode_tempstate_net = mode_tempstate;
/* hunger */
if (sniper_mag != sniper_mag_net)
SendFlags |= PLAYER_AMMO1;
if (chaingun_mag != chaingun_mag_net)
SendFlags |= PLAYER_AMMO1;
if (ap9_mag != ap9_mag_net)
SendFlags |= PLAYER_AMMO1;
if (taurus_mag != taurus_mag_net)
SendFlags |= PLAYER_AMMO1;
if (ammo_ap9 != ammo_ap9_net)
SendFlags |= PLAYER_AMMO2;
if (ammo_taurus != ammo_taurus_net)
SendFlags |= PLAYER_AMMO2;
if (ammo_bolt != ammo_bolt_net)
SendFlags |= PLAYER_AMMO2;
if (ammo_sniper != ammo_sniper_net)
SendFlags |= PLAYER_AMMO2;
if (ammo_medkit != ammo_medkit_net)
SendFlags |= PLAYER_AMMO2;
if (ammo_gas != ammo_gas_net)
SendFlags |= PLAYER_AMMO2;
if (mode_silencer != mode_silencer_net)
SendFlags |= PLAYER_AMMO3;
sniper_mag_net = sniper_mag;
chaingun_mag_net = chaingun_mag;
ap9_mag_net = ap9_mag;
taurus_mag_net = taurus_mag;
ammo_ap9_net = ammo_ap9;
ammo_taurus_net = ammo_taurus;
ammo_bolt_net = ammo_bolt;
ammo_sniper_net = ammo_sniper;
ammo_medkit_net = ammo_medkit;
ammo_gas_net = ammo_gas;
mode_silencer_net= mode_silencer;
}
/*
=================
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);
/* hunger */
WriteByte(MSG_ENTITY, sniper_mag);
WriteByte(MSG_ENTITY, chaingun_mag);
WriteByte(MSG_ENTITY, ap9_mag);
WriteByte(MSG_ENTITY, taurus_mag);
}
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);
/* hunger */
WriteByte(MSG_ENTITY, ammo_ap9);
WriteByte(MSG_ENTITY, ammo_taurus);
WriteByte(MSG_ENTITY, ammo_bolt);
WriteByte(MSG_ENTITY, ammo_sniper);
WriteByte(MSG_ENTITY, ammo_medkit);
WriteByte(MSG_ENTITY, ammo_gas);
}
if (fChanged & PLAYER_AMMO3) {
WriteByte(MSG_ENTITY, ammo_m203_grenade);
WriteByte(MSG_ENTITY, ammo_shotgun_state);
WriteByte(MSG_ENTITY, ammo_gauss_state);
WriteByte(MSG_ENTITY, ammo_gauss_volume);
WriteByte(MSG_ENTITY, ammo_egon_state);
WriteByte(MSG_ENTITY, ammo_rpg_state);
WriteByte(MSG_ENTITY, mode_tempstate);
WriteByte(MSG_ENTITY, mode_silencer);
}
return TRUE;
}
#endif

320
src/shared/w_ap9.qc Normal file
View File

@ -0,0 +1,320 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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
{
AP9_IDLE,
AP9_RELOAD,
AP9_DRAW,
AP9_SHOOT1,
AP9_SHOOT2,
AP9_SHOOT3
};
void
w_ap9_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_ap9.fire");
#endif
precache_model("models/v_ap9.mdl");
precache_model("models/w_ap9.mdl");
precache_model("models/p_ap9.mdl");
precache_sound("weapons/ap9_bolt.wav");
precache_sound("weapons/ap9_clipin.wav");
precache_sound("weapons/ap9_clipout.wav");
}
void
w_ap9_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.ap9_mag, pl.ammo_ap9, -1);
}
string
w_ap9_wmodel(void)
{
return "models/w_ap9.mdl";
}
string
w_ap9_pmodel(void)
{
return "models/p_ap9.mdl";
}
string
w_ap9_deathmsg(void)
{
return "%s was unloaded into from %s's AP9.";
}
int
w_ap9_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (new) {
pl.ap9_mag = 40;
} else {
if (pl.ammo_ap9 < MAX_A_AP9) {
pl.ammo_ap9 = bound(0, pl.ammo_ap9 + 40, MAX_A_AP9);
} else {
return FALSE;
}
}
#endif
return TRUE;
}
void
w_ap9_draw(void)
{
#ifdef CLIENT
Weapons_SetModel("models/v_ap9.mdl");
Weapons_ViewAnimation(AP9_DRAW);
#endif
}
void
w_ap9_holster(void)
{
}
void
w_ap9_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
/* ammo check */
if (!pl.ap9_mag) {
return;
}
pl.ap9_mag--;
/* actual firing */
#ifdef CLIENT
pl.ap9_mag--;
View_SetMuzzleflash(MUZZLE_SMALL);
Weapons_ViewPunchAngle([-2,0,0]);
int r = (float)input_sequence % 3;
switch (r) {
case 0:
Weapons_ViewAnimation(AP9_SHOOT1);
break;
case 1:
Weapons_ViewAnimation(AP9_SHOOT2);
break;
case 2:
Weapons_ViewAnimation(AP9_SHOOT3);
break;
}
#else
TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 8, [0.1,0.1], WEAPON_AP9);
Sound_Play(pl, CHAN_WEAPON, "weapon_ap9.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.15f;
pl.w_idle_next = 5.0f;
}
void
w_ap9_secondary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0) {
return;
}
/* ammo check */
if ((pl.ap9_mag - 3) < 0) {
return;
}
pl.ap9_mag -= 3;
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_SMALL);
Weapons_ViewPunchAngle([-2,0,0]);
int r = floor(random(0,2));
switch (r) {
case 0:
Weapons_ViewAnimation(AP9_SHOOT1);
break;
case 1:
Weapons_ViewAnimation(AP9_SHOOT2);
break;
case 2:
Weapons_ViewAnimation(AP9_SHOOT3);
break;
}
#else
TraceAttack_FireBullets(3, pl.origin + pl.view_ofs, 8, [0.02,0.02], WEAPON_AP9);
Sound_Play(pl, CHAN_WEAPON, "weapon_ap9.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 = 1.0f;
pl.w_idle_next = 5.0f;
}
void
w_ap9_reload(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
if (pl.ap9_mag >= 40) {
return;
}
if (pl.a_ammo2 <= 0) {
return;
}
#ifdef CLIENT
Weapons_ViewAnimation(AP9_RELOAD);
#else
Weapons_ReloadWeapon(pl, player::ap9_mag, player::ammo_ap9, 40);
#endif
pl.w_attack_next = 2.0f;
pl.w_idle_next = 10.0f;
}
void
w_ap9_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.ap9_mag == 0 && pl.ammo_ap9 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}
Weapons_ViewAnimation(AP9_IDLE);
}
float
w_ap9_aimanim(void)
{
return w_glock_aimanim();
}
void
w_ap9_hud(void)
{
w_glock_hud();
}
void
w_ap9_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
player pl = (player)self;
vector hud_col;
if (pl.ap9_mag == 0 && pl.ammo_ap9 == 0)
hud_col = [1,0,0];
else
hud_col = g_hud_color;
HUD_DrawAmmoBar(pos, pl.ammo_ap9, MAX_A_AP9, a);
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/tfchud05.spr_0.tga",
[0,0],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/tfchud05.spr_0.tga",
[0,0],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_ap9 =
{
.name = "ap9",
.id = ITEM_AP9,
.slot = 1,
.slot_pos = 2,
.draw = w_ap9_draw,
.holster = w_ap9_holster,
.primary = w_ap9_primary,
.secondary = w_ap9_secondary,
.reload = w_ap9_reload,
.release = w_ap9_release,
.crosshair = w_ap9_hud,
.precache = w_ap9_precache,
.pickup = w_ap9_pickup,
.updateammo = w_ap9_updateammo,
.wmodel = w_ap9_wmodel,
.pmodel = w_ap9_pmodel,
.deathmsg = w_ap9_deathmsg,
.aimanim = w_ap9_aimanim,
.hudpic = w_ap9_hudpic
};
/* pickups */
#ifdef SERVER
void
weapon_th_ap9(void)
{
Weapons_InitItem(WEAPON_AP9);
}
#endif

310
src/shared/w_chaingun.qc Normal file
View File

@ -0,0 +1,310 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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.
*/
/* Animations */
enum
{
CHAINGUN_IDLE1,
CHAINGUN_IDLE2,
CHAINGUN_SPINUP,
CHAINGUN_SPINDOWN,
CHAINGUN_FIRE,
CHAINGUN_DRAW,
CHAINGUN_HOLSTER
};
void
w_chaingun_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_chaingun.fire");
Sound_Precache("weapon_chaingun.reload");
Sound_Precache("weapon_chaingun.spindown");
Sound_Precache("weapon_chaingun.spinup");
#endif
precache_model("models/v_tfac.mdl");
precache_model("models/w_tfac.mdl");
precache_model("models/p_tfac.mdl");
}
int
w_chaingun_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (new) {
pl.chaingun_mag = 100;
} else {
if (pl.ammo_9mm < MAX_A_9MM) {
pl.ammo_9mm = bound(0, pl.ammo_9mm + 100, MAX_A_9MM);
} else {
return FALSE;
}
}
#endif
return TRUE;
}
void
w_chaingun_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.chaingun_mag, pl.ammo_9mm, -1);
}
string
w_chaingun_wmodel(void)
{
return "models/w_tfac.mdl";
}
string
w_chaingun_pmodel(void)
{
return "models/p_tfac.mdl";
}
string
w_chaingun_deathmsg(void)
{
return "%s was rolled over by %s' Chaingun.";
}
void
w_chaingun_draw(void)
{
player pl = (player)self;
pl.mode_tempstate = 0;
#ifdef CLIENT
Weapons_SetModel("models/v_tfac.mdl");
Weapons_ViewAnimation(CHAINGUN_DRAW);
#endif
}
void
w_chaingun_holster(void)
{
Weapons_ViewAnimation(CHAINGUN_HOLSTER);
}
void
w_chaingun_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.chaingun_mag == 0 && pl.ammo_9mm > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}
/* end firing */
if (pl.mode_tempstate == 1) {
pl.mode_tempstate = 0;
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_chaingun.spindown");
#endif
Weapons_ViewAnimation(CHAINGUN_SPINDOWN);
pl.w_attack_next = 1.0f;
pl.w_idle_next = pl.w_attack_next;
return;
}
/* end reload */
if (pl.mode_tempstate == 2) {
pl.mode_tempstate = 0;
Weapons_ViewAnimation(CHAINGUN_DRAW);
pl.w_attack_next = 1.0f;
pl.w_idle_next = pl.w_attack_next;
return;
}
int r = (float)input_sequence % 2;
if (r) {
Weapons_ViewAnimation(CHAINGUN_IDLE1);
} else {
Weapons_ViewAnimation(CHAINGUN_IDLE2);
}
pl.w_idle_next = 15.0f;
}
void
w_chaingun_primary(void)
{
player pl = (player)self;
/* in case we're spamming primary while reloading */
if (pl.mode_tempstate == 2) {
w_chaingun_release();
return;
}
if (pl.w_attack_next > 0.0) {
return;
}
/* ammo check */
if (pl.chaingun_mag <= 0) {
return;
}
/* spin up first */
if (pl.mode_tempstate == 0) {
pl.mode_tempstate = 1;
Weapons_ViewAnimation(CHAINGUN_SPINUP);
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_chaingun.spinup");
#endif
pl.w_attack_next = 0.5f;
pl.w_idle_next = pl.w_attack_next;
return;
}
pl.chaingun_mag--;
/* actual firing */
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_RIFLE);
Weapons_ViewAnimation(CHAINGUN_FIRE);
Weapons_ViewPunchAngle([random(-2, 2),0,0]);
#else
TraceAttack_FireBullets(1, Weapons_GetCameraPos(), 8, [0.15,0.15], WEAPON_CHAINGUN);
Sound_Play(pl, CHAN_WEAPON, "weapon_chaingun.fire");
#endif
pl.w_attack_next = 0.1f;
pl.w_idle_next = 0.0f;
}
void
w_chaingun_reload(void)
{
player pl = (player)self;
if (pl.w_attack_next) {
w_chaingun_release();
return;
}
/* ammo check */
if (pl.chaingun_mag >= 100) {
return;
}
if (pl.ammo_9mm <= 0) {
return;
}
#ifdef CLIENT
Weapons_ViewAnimation(CHAINGUN_HOLSTER);
#else
Sound_Play(pl, CHAN_WEAPON, "weapon_chaingun.reload");
Weapons_ReloadWeapon(pl, player::chaingun_mag, player::ammo_9mm, 100);
#endif
pl.mode_tempstate = 2;
pl.w_attack_next = 10.0f;
pl.w_idle_next = 1.5f;
}
void
w_chaingun_hud(void)
{
w_glock_hud();
}
float
w_chaingun_aimanim(void)
{
return w_mp5_aimanim();
}
void
w_chaingun_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
player pl = (player)self;
vector hud_col;
if (pl.chaingun_mag == 0 && pl.ammo_9mm == 0)
hud_col = [1,0,0];
else
hud_col = g_hud_color;
HUD_DrawAmmoBar(pos, pl.ammo_9mm, MAX_A_9MM, a);
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/tfchud04.spr_0.tga",
[0,90/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/tfchud03.spr_0.tga",
[0,45/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_chaingun =
{
.name = "chaingun",
.id = ITEM_CHAINGUN,
.slot = 3,
.slot_pos = 3,
.draw = w_chaingun_draw,
.holster = w_chaingun_holster,
.primary = w_chaingun_primary,
.secondary = w_chaingun_release,
.reload = w_chaingun_reload,
.release = w_chaingun_release,
.crosshair = w_chaingun_hud,
.precache = w_chaingun_precache,
.pickup = w_chaingun_pickup,
.updateammo = w_chaingun_updateammo,
.wmodel = w_chaingun_wmodel,
.pmodel = w_chaingun_pmodel,
.deathmsg = w_chaingun_deathmsg,
.aimanim = w_chaingun_aimanim,
.hudpic = w_chaingun_hudpic
};
/* pickups */
#ifdef SERVER
void
weapon_th_chaingun(void)
{
Weapons_InitItem(WEAPON_CHAINGUN);
}
#endif

248
src/shared/w_flame.qc Normal file
View File

@ -0,0 +1,248 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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
{
EGON_IDLE1,
EGON_FIDGET1,
EGON_ALTFIREON,
EGON_ALTFIRECYCLE,
EGON_ALTFIREOFF,
EGON_FIRE1,
EGON_FIRE2,
EGON_FIRE3,
EGON_FIRE4,
EGON_DRAW,
EGON_HOLSTER
};
void
w_flame_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_flame.fire");
#endif
precache_model("sprites/fthrow.spr");
precache_model("models/v_egon.mdl");
precache_model("models/w_egon.mdl");
precache_model("models/p_egon.mdl");
}
void
w_flame_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, -1, pl.ammo_gas, -1);
}
string
w_flame_wmodel(void)
{
return w_egon_wmodel();
}
string
w_flame_pmodel(void)
{
return w_egon_pmodel();
}
string
w_flame_deathmsg(void)
{
return "%s burned to a crisp by %s's Flamethrower.";
}
int
w_flame_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (pl.ammo_gas < MAX_A_GAS) {
pl.ammo_gas = bound(0, pl.ammo_gas + 20, MAX_A_GAS);
} else {
return FALSE;
}
#endif
return TRUE;
}
void
w_flame_draw(void)
{
w_egon_draw();
}
void
w_flame_holster(void)
{
w_egon_holster();
}
#ifdef SERVER
void
Flame_Touch(void)
{
if (other.takedamage != DAMAGE_YES) {
remove(self);
return;
}
/* anything else that can take damage */
Damage_Apply(other, self.owner, 40, WEAPON_EGON, DMG_BURN);
remove(self);
}
#endif
void
w_flame_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
/* Ammo check */
if (pl.ammo_gas <= 0) {
return;
}
pl.ammo_gas--;
#ifdef CLIENT
if (Weapons_GetAnimation() == EGON_IDLE1)
Weapons_ViewAnimation(EGON_ALTFIREON);
else if (Weapons_GetAnimation() == EGON_ALTFIREON)
Weapons_ViewAnimation(EGON_ALTFIRECYCLE);
#else
Sound_Play(pl, CHAN_WEAPON, "weapon_flame.fire");
Weapons_MakeVectors();
entity flame = spawn();
setmodel(flame, "sprites/fthrow.spr");
setorigin(flame, Weapons_GetCameraPos() + (v_forward * 16));
flame.owner = self;
flame.velocity = v_forward * 300;
flame.movetype = MOVETYPE_FLYMISSILE;
flame.solid = SOLID_BBOX;
//flame.flags |= FL_LAGGEDMOVE;
flame.angles = vectoangles(flame.velocity);
flame.avelocity[2] = 10;
flame.touch = Flame_Touch;
/*frame.think = Flame_Touch;
flame.nextthink = time + 2.0f;*/
flame.effects |= EF_BRIGHTLIGHT;
setsize(flame, [0,0,0], [0,0,0]);
#endif
pl.w_attack_next = 0.2f;
pl.w_idle_next = 2.5f;
}
void
w_flame_reload(void)
{
}
void
w_flame_release(void)
{
w_egon_release();
}
void
w_flame_crosshair(void)
{
#ifdef CLIENT
static vector cross_pos;
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
drawsubpic(cross_pos, [24,24], "sprites/crosshairs.spr_0.tga", [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], "sprites/640hud7.spr_0.tga", [0,96/128], [24/256, 24/128], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
float
w_flame_aimanim(void)
{
return w_egon_aimanim();
}
void
w_flame_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
player pl = (player)self;
vector hud_col;
if (pl.ammo_gas == 0)
hud_col = [1,0,0];
else
hud_col = g_hud_color;
HUD_DrawAmmoBar(pos, pl.ammo_gas, MAX_A_GAS, a);
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/tfchud04.spr_0.tga",
[0,45/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/tfchud03.spr_0.tga",
[0,0/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_flame =
{
.name = "flame",
.id = ITEM_EGON,
.slot = 3,
.slot_pos = 2,
.draw = w_flame_draw,
.holster = w_egon_holster,
.primary = w_flame_primary,
.secondary = w_flame_release,
.reload = __NULL__,
.release = w_flame_release,
.crosshair = w_flame_crosshair,
.precache = w_flame_precache,
.pickup = w_flame_pickup,
.updateammo = w_flame_updateammo,
.wmodel = w_flame_wmodel,
.pmodel = w_flame_pmodel,
.deathmsg = w_flame_deathmsg,
.aimanim = w_flame_aimanim,
.hudpic = w_flame_hudpic
};

246
src/shared/w_medkit.qc Normal file
View File

@ -0,0 +1,246 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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
{
MEDKIT_IDLE1,
MEDKIT_IDLE2,
MEDKIT_USE,
MEDKIT_UNUSED,
MEDKIT_HOLSTER,
MEDKIT_DRAW
};
void
w_medkit_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_medkit.heal");
#endif
precache_model("models/v_tfc_medkit.mdl");
precache_model("models/w_tfc_medkit.mdl");
precache_model("models/p_tfc_medkit.mdl");
}
void
w_medkit_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, -1, pl.ammo_medkit, -1);
}
string
w_medkit_wmodel(void)
{
return "models/w_tfc_medkit.mdl";
}
string
w_medkit_pmodel(void)
{
return "models/p_tfc_medkit.mdl";
}
string
w_medkit_deathmsg(void)
{
return "%s was somehow healed to death by %s's Medkit.";
}
int
w_medkit_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (new) {
pl.ammo_medkit = 8;
} else {
if (pl.ammo_medkit < MAX_A_MEDKIT) {
pl.ammo_medkit = bound(0, pl.ammo_medkit + 8, MAX_A_MEDKIT);
} else {
return FALSE;
}
}
#endif
return TRUE;
}
void
w_medkit_draw(void)
{
Weapons_SetModel("models/v_tfc_medkit.mdl");
Weapons_ViewAnimation(MEDKIT_DRAW);
}
void
w_medkit_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
if (!pl.ammo_medkit) {
return;
}
/* Don't give the player more than 100 health */
if (pl.health >= 100) {
return;
} else {
Weapons_ViewAnimation(MEDKIT_USE);
}
pl.ammo_medkit--;
#ifdef SERVER
/* We want to only give health to the player & skip armor */
Damage_Apply(pl, pl, -15, WEAPON_MEDKIT, DMG_GENERIC);
if (self.flags & FL_CROUCHING)
Animation_PlayerTopTemp(ANIM_SHOOT1HAND, 0.45f);
else
Animation_PlayerTopTemp(ANIM_CR_SHOOT1HAND, 0.45f);
Sound_Play(pl, CHAN_WEAPON, "weapon_medkit.heal");
#endif
pl.w_attack_next = 2.4f;
pl.w_idle_next = 5.0f;
}
void
w_medkit_release(void)
{
player pl = (player)self;
if (pl.w_idle_next > 0.0) {
return;
}
int r = (float)input_sequence % 2;
switch (r) {
case 0:
Weapons_ViewAnimation(MEDKIT_IDLE1);
pl.w_idle_next = 1.16f;
break;
default:
Weapons_ViewAnimation(MEDKIT_IDLE2);
pl.w_idle_next = 2.36f;
break;
}
}
float
w_medkit_aimanim(void)
{
return w_snark_aimanim();
}
void
w_medkit_crosshair(void)
{
#ifdef CLIENT
vector aicon_pos;
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
HUD_DrawAmmo2();
drawsubpic(
aicon_pos,
[24,24],
"sprites/640hud7.spr_0.tga",
[24/256,96/128],
[24/256, 24/128],
g_hud_color,
pSeat->m_flAmmo2Alpha,
DRAWFLAG_ADDITIVE
);
#endif
}
void
w_medkit_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
player pl = (player)self;
vector hud_col;
if (pl.ammo_medkit == 0)
hud_col = [1,0,0];
else
hud_col = g_hud_color;
HUD_DrawAmmoBar(pos, pl.ammo_medkit, MAX_A_MEDKIT, a);
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/tfchud05.spr_0.tga",
[0,180/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/tfchud06.spr_0.tga",
[0,90/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_medkit =
{
.name = "medkit",
.id = ITEM_MEDKIT2,
.slot = 4,
.slot_pos = 4,
.draw = w_medkit_draw,
.holster = __NULL__,
.primary = w_medkit_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_medkit_release,
.crosshair = w_medkit_crosshair,
.precache = w_medkit_precache,
.pickup = w_medkit_pickup,
.updateammo = w_medkit_updateammo,
.wmodel = w_medkit_wmodel,
.pmodel = w_medkit_pmodel,
.deathmsg = w_medkit_deathmsg,
.aimanim = w_medkit_aimanim,
.hudpic = w_medkit_hudpic
};
#ifdef SERVER
void
weapon_th_medkit(void)
{
Weapons_InitItem(WEAPON_MEDKIT);
}
#endif

158
src/shared/w_shovel.qc Normal file
View File

@ -0,0 +1,158 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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
{
CBAR_IDLE,
CBAR_DRAW,
CBAR_HOLSTER,
CBAR_ATTACK1HIT,
CBAR_ATTACK1MISS,
CBAR_ATTACK2MISS,
CBAR_ATTACK2HIT,
CBAR_ATTACK3MISS,
CBAR_ATTACK3HIT
};
void
w_shovel_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_crowbar.hit");
Sound_Precache("weapon_crowbar.miss");
Sound_Precache("weapon_crowbar.hitbody");
#endif
precache_model("models/v_shovel.mdl");
precache_model("models/w_shovel.mdl");
precache_model("models/p_shovel.mdl");
}
void
w_shovel_updateammo(player pl)
{
w_crowbar_updateammo(pl);
}
string
w_shovel_wmodel(void)
{
return "models/w_shovel.mdl";
}
string
w_shovel_pmodel(void)
{
return "models/p_shovel.mdl";
}
string
w_shovel_deathmsg(void)
{
return "%s was buried by %s's Shovel.";
}
void
w_shovel_draw(void)
{
Weapons_SetModel("models/v_shovel.mdl");
Weapons_ViewAnimation(CBAR_DRAW);
}
void
w_shovel_holster(void)
{
w_crowbar_holster();
}
void
w_shovel_primary(void)
{
w_crowbar_primary();
}
void
w_shovel_release(void)
{
w_crowbar_release();
}
float
w_shovel_aimanim(void)
{
return w_crowbar_aimanim();
}
void
w_shovel_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/tfchud04.spr_0.tga",
[0,135/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/tfchud03.spr_0.tga",
[0,90/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_shovel =
{
.name = "shovel",
.id = ITEM_SHOVEL,
.slot = 0,
.slot_pos = 1,
.draw = w_shovel_draw,
.holster = w_shovel_holster,
.primary = w_shovel_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_shovel_release,
.crosshair = __NULL__,
.precache = w_shovel_precache,
.pickup = __NULL__,
.updateammo = w_shovel_updateammo,
.wmodel = w_shovel_wmodel,
.pmodel = w_shovel_pmodel,
.deathmsg = w_shovel_deathmsg,
.aimanim = w_shovel_aimanim,
.hudpic = w_shovel_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_th_shovel(void)
{
Weapons_InitItem(WEAPON_SHOVEL);
}
#endif

270
src/shared/w_silencer.qc Normal file
View File

@ -0,0 +1,270 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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
{
GLOCK_IDLE1,
GLOCK_IDLE2,
GLOCK_IDLE3,
GLOCK_SHOOT,
GLOCK_SHOOT_EMPTY,
GLOCK_RELOAD_EMPTY,
GLOCK_RELOAD,
GLOCK_DRAW,
GLOCK_HOLSTER,
GLOCK_SILENCER
};
void
w_silencer_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_glock.fire");
Sound_Precache("weapon_silencer.fire");
#endif
precache_model("models/v_9mmhandgun.mdl");
precache_model("models/w_9mmhandgun.mdl");
precache_model("models/p_9mmhandgun.mdl");
}
void
w_silencer_updateammo(player pl)
{
w_glock_updateammo(pl);
}
string
w_silencer_wmodel(void)
{
return "models/w_silencer.mdl";
}
string
w_silencer_pmodel(void)
{
return w_glock_pmodel();
}
string
w_silencer_deathmsg(void)
{
return "%s was silenced by %s's Beretta.";
}
int
w_silencer_pickup(int new, int startammo)
{
return w_glock_pickup(new, startammo);
}
void
w_silencer_draw(void)
{
w_glock_draw();
#ifdef CLIENT
player pl = (player)self;
if (pl.mode_silencer) {
Weapons_SetGeomset("geomset 2 2\n");
} else {
Weapons_SetGeomset("geomset 2 0\n");
}
#endif
}
void
w_silencer_holster(void)
{
w_glock_holster();
}
void
w_silencer_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
/* ammo check */
if (!pl.glock_mag) {
return;
}
pl.glock_mag--;
/* actual firing */
Weapons_ViewPunchAngle([-2,0,0]);
#ifdef CLIENT
if (pl.mode_silencer == 1) {
View_SetMuzzleflash(0);
} else {
View_SetMuzzleflash(MUZZLE_SMALL);
}
if (pl.glock_mag) {
Weapons_ViewAnimation(GLOCK_SHOOT);
} else {
Weapons_ViewAnimation(GLOCK_SHOOT_EMPTY);
}
#else
/* Different sound & accuracy without silencer */
if (pl.mode_silencer == 1) {
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_silencer.fire");
} 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
/* Fires faster without silencer */
if (pl.mode_silencer == 1) {
pl.w_attack_next = 0.3f;
} else {
pl.w_attack_next = 0.2f;
}
pl.w_idle_next = 5.0f;
}
void
w_silencer_secondary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0) {
return;
}
/* toggle silencer */
pl.mode_silencer = 1 - pl.mode_silencer;
/* the sub model isn't setting right, need the right values */
#ifdef CLIENT
if (pl.mode_silencer) {
Weapons_SetGeomset("geomset 2 2\n");
Weapons_ViewAnimation(GLOCK_SILENCER);
} else {
Weapons_SetGeomset("geomset 2 0\n");
Weapons_ViewAnimation(GLOCK_HOLSTER);
}
#endif
if (pl.mode_silencer) {
pl.w_attack_next = 3.3f;
pl.w_idle_next = pl.w_attack_next;
} else {
pl.w_attack_next = 0.94f;
pl.w_idle_next = pl.w_attack_next;
}
}
void
w_silencer_reload(void)
{
w_glock_reload();
}
void
w_silencer_release(void)
{
w_glock_release();
}
float
w_silencer_aimanim(void)
{
return w_glock_aimanim();
}
void
w_silencer_hud(void)
{
w_glock_hud();
}
void
w_silencer_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;
HUD_DrawAmmoBar(pos, pl.ammo_9mm, MAX_A_9MM, a);
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/tfchud05.spr_0.tga",
[0,135/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/tfchud06.spr_0.tga",
[0,45/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_silencer =
{
.name = "silencer",
.id = ITEM_GLOCK,
.slot = 1,
.slot_pos = 0,
.draw = w_silencer_draw,
.holster = w_silencer_holster,
.primary = w_silencer_primary,
.secondary = w_silencer_secondary,
.reload = w_silencer_reload,
.release = w_silencer_release,
.crosshair = w_silencer_hud,
.precache = w_silencer_precache,
.pickup = w_silencer_pickup,
.updateammo = w_silencer_updateammo,
.wmodel = w_silencer_wmodel,
.pmodel = w_silencer_pmodel,
.deathmsg = w_silencer_deathmsg,
.aimanim = w_silencer_aimanim,
.hudpic = w_silencer_hudpic
};

357
src/shared/w_sniper.qc Normal file
View File

@ -0,0 +1,357 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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
{
SNIPER_IDLE1,
SNIPER_UNUSED1,
SNIPER_FIRE1,
SNIPER_DRAW,
SNIPER_HOLSTER,
SNIPER_IDLE2
};
void
w_sniper_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_sniper.fire");
Sound_Precache("weapon_sniper.reload");
#endif
precache_model("models/v_tfc_sniper.mdl");
precache_model("models/w_isotopebox.mdl");
precache_model("models/p_sniper.mdl");
}
int
w_sniper_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (new) {
pl.sniper_mag = 5;
} else {
if (pl.ammo_sniper < MAX_A_SNIPER) {
pl.ammo_sniper = bound(0, pl.ammo_sniper + 5, MAX_A_SNIPER);
} else {
return FALSE;
}
}
#endif
return TRUE;
}
void
w_sniper_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.sniper_mag, pl.ammo_sniper, -1);
}
string
w_sniper_wmodel(void)
{
return "models/w_isotopebox.mdl";
}
string
w_sniper_pmodel(void)
{
return "models/p_sniper.mdl";
}
string
w_sniper_deathmsg(void)
{
return "%s was taken out by %s's Sniper.";
}
void
w_sniper_draw(void)
{
player pl = (player)self;
pl.mode_tempstate = 0;
#ifdef CLIENT
Weapons_SetModel("models/v_tfc_sniper.mdl");
Weapons_ViewAnimation(SNIPER_DRAW);
#endif
}
void
w_sniper_holster(void)
{
#ifdef CLIENT
Weapons_ViewAnimation(SNIPER_HOLSTER);
#endif
}
void
w_sniper_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.sniper_mag == 0 && pl.ammo_sniper > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}
if (pl.mode_tempstate == 1) {
Weapons_ViewAnimation(SNIPER_DRAW);
pl.mode_tempstate = 0;
pl.w_attack_next = 0.0f;
pl.w_idle_next = 15.0f;
return;
}
int r = floor(random(0,2));
switch (r) {
case 0:
Weapons_ViewAnimation(SNIPER_IDLE1);
pl.w_idle_next = 3.0f;
break;
case 1:
Weapons_ViewAnimation(SNIPER_IDLE2);
pl.w_idle_next = 2.0f;
break;
}
pl.w_idle_next = 15.0f;
}
void
w_sniper_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
/* Ammo check */
if (pl.sniper_mag <= 0) {
return;
}
pl.sniper_mag--;
/* Actual firing */
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_SMALL);
Weapons_ViewPunchAngle([-20,0,0]);
Weapons_ViewAnimation(SNIPER_FIRE1);
#else
TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 40, [0.008, 0.008], WEAPON_SNIPER);
Sound_Play(pl, CHAN_WEAPON, "weapon_sniper.fire");
#endif
/* Simple toggle of fovs */
if (pl.viewzoom == 1.0f) {
pl.w_attack_next = 0.1f;
} else {
pl.w_attack_next = 1.0f;
}
pl.w_idle_next = 10.0f;
}
void
w_sniper_secondary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
/* Simple toggle of fovs */
if (pl.viewzoom == 1.0f) {
pl.viewzoom = 0.25f;
} else {
pl.viewzoom = 1.0f;
}
pl.w_attack_next = 0.5f;
}
void
w_sniper_reload(void)
{
player pl = (player)self;
if (pl.w_attack_next) {
w_sniper_release();
return;
}
if (pl.sniper_mag >= 5) {
return;
}
if (pl.ammo_sniper <= 0) {
return;
}
#ifdef CLIENT
Weapons_ViewAnimation(SNIPER_HOLSTER);
#else
Sound_Play(pl, CHAN_WEAPON, "weapon_sniper.reload");
Weapons_ReloadWeapon(pl, player::sniper_mag, player::ammo_sniper, 5);
#endif
pl.mode_tempstate = 1;
pl.w_attack_next = 2.5f;
pl.w_idle_next = 2.0f;
}
void
w_sniper_crosshair(void)
{
#ifdef CLIENT
player pl = (player)self;
static vector cross_pos;
vector aicon_pos;
if (pl.viewzoom < 1.0f) {
drawfill(
g_hudmins,
g_hudres,
[0,0.2,0],
1.0f,
DRAWFLAG_ADDITIVE
);
cross_pos = g_hudmins + (g_hudres / 2) + [-128,-104];
drawpic(
cross_pos,
"sprites/nmxhair2.spr_0.tga",
[256,208],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
} else {
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
drawsubpic(
cross_pos,
[24,24],
"sprites/crosshairs.spr_0.tga",
[48/128,0],
[24/128,24/128],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
}
HUD_DrawAmmo1();
HUD_DrawAmmo2();
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(
aicon_pos,
[24,24],
"sprites/640hud7.spr_0.tga",
[24/256,72/128],
[24/256, 24/128],
g_hud_color,
pSeat->m_flAmmo2Alpha,
DRAWFLAG_ADDITIVE
);
#endif
}
float
w_sniper_aimanim(void)
{
return w_crossbow_aimanim();
}
void
w_sniper_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
player pl = (player)self;
vector hud_col;
if (pl.sniper_mag == 0 && pl.ammo_sniper == 0)
hud_col = [1,0,0];
else
hud_col = g_hud_color;
HUD_DrawAmmoBar(pos, pl.ammo_sniper, MAX_A_SNIPER, a);
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/tfchud02.spr_0.tga",
[0,45/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/tfchud01.spr_0.tga",
[0,45/256],
[170/256,45/256],
hud_col,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_sniper =
{
.name = "sniper",
.id = ITEM_SNIPER,
.slot = 2,
.slot_pos = 3,
.draw = w_sniper_draw,
.holster = w_sniper_holster,
.primary = w_sniper_primary,
.secondary = w_sniper_secondary,
.reload = w_sniper_reload,
.release = w_sniper_release,
.crosshair = w_sniper_crosshair,
.precache = w_sniper_precache,
.pickup = w_sniper_pickup,
.updateammo = w_sniper_updateammo,
.wmodel = w_sniper_wmodel,
.pmodel = w_sniper_pmodel,
.deathmsg = w_sniper_deathmsg,
.aimanim = w_sniper_aimanim,
.hudpic = w_sniper_hudpic
};
/* pickups */
#ifdef SERVER
void
weapon_einar1(void)
{
Weapons_InitItem(WEAPON_SNIPER);
}
#endif

242
src/shared/w_sniper2.qc Normal file
View File

@ -0,0 +1,242 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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
{
SNIPER_IDLE,
SNIPER_RELOAD,
SNIPER_DRAW,
SNIPER_FIRE
};
void
w_sniper2_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_sniper.fire");
#endif
precache_model("models/v_hkg36.mdl");
precache_model("models/w_hkg36.mdl");
precache_model("models/p_hkg36.mdl");
}
int
w_sniper2_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (new) {
pl.sniper_mag = 5;
} else {
if (pl.ammo_sniper < MAX_A_SNIPER) {
pl.ammo_sniper = bound(0, pl.ammo_sniper + 5, MAX_A_SNIPER);
} else {
return FALSE;
}
}
#endif
return TRUE;
}
void
w_sniper2_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.sniper_mag, pl.ammo_sniper, -1);
}
string
w_sniper2_wmodel(void)
{
return "models/w_hkg36.mdl";
}
string
w_sniper2_pmodel(void)
{
return "models/p_hkg36.mdl";
}
string
w_sniper2_deathmsg(void)
{
return "%s was taken out by %s's Sniper.";
}
void
w_sniper2_draw(void)
{
#ifdef CLIENT
Weapons_SetModel("models/v_hkg36.mdl");
Weapons_ViewAnimation(SNIPER_DRAW);
#endif
}
void
w_sniper2_holster(void)
{
}
void
w_sniper2_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.sniper_mag == 0 && pl.ammo_sniper > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}
int r = floor(random(0,2));
switch (r) {
case 0:
Weapons_ViewAnimation(SNIPER_IDLE1);
pl.w_idle_next = 3.0f;
break;
case 1:
Weapons_ViewAnimation(SNIPER_IDLE2);
pl.w_idle_next = 2.0f;
break;
}
pl.w_idle_next = 15.0f;
}
void
w_sniper2_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
/* Ammo check */
if (pl.sniper_mag <= 0) {
return;
}
pl.sniper_mag--;
/* Actual firing */
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_SMALL);
Weapons_ViewPunchAngle([-20,0,0]);
Weapons_ViewAnimation(SNIPER_FIRE);
#else
TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 40, [0.008, 0.008], WEAPON_SNIPER);
Sound_Play(pl, CHAN_WEAPON, "weapon_sniper.fire");
#endif
/* Simple toggle of fovs */
if (pl.viewzoom == 1.0f) {
pl.w_attack_next = 0.1f;
} else {
pl.w_attack_next = 1.0f;
}
pl.w_idle_next = 10.0f;
}
void
w_sniper2_secondary(void)
{
w_sniper_secondary();
}
void
w_sniper2_reload(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
if (pl.sniper_mag >= 5) {
return;
}
if (pl.ammo_sniper <= 0) {
return;
}
#ifdef CLIENT
Weapons_ViewAnimation(SNIPER_RELOAD);
#else
Weapons_ReloadWeapon(pl, player::sniper_mag, player::ammo_sniper, 5);
#endif
pl.w_attack_next = 3.82f;
pl.w_idle_next = 5.0f;
}
void
w_sniper2_crosshair(void)
{
#ifdef CLIENT
w_sniper_crosshair();
#endif
}
float
w_sniper2_aimanim(void)
{
return w_crossbow_aimanim();
}
void
w_sniper2_hudpic(int selected, vector pos, float a)
{
w_sniper_hudpic(selected, pos, a);
}
weapon_t w_sniper2 =
{
.name = "sniper2",
.id = ITEM_SNIPER2,
.slot = 2,
.slot_pos = 4,
.draw = w_sniper2_draw,
.holster = w_sniper2_holster,
.primary = w_sniper2_primary,
.secondary = w_sniper2_secondary,
.reload = w_sniper2_reload,
.release = w_sniper2_release,
.crosshair = w_sniper2_crosshair,
.precache = w_sniper2_precache,
.pickup = w_sniper2_pickup,
.updateammo = w_sniper2_updateammo,
.wmodel = w_sniper2_wmodel,
.pmodel = w_sniper2_pmodel,
.deathmsg = w_sniper2_deathmsg,
.aimanim = w_sniper2_aimanim,
.hudpic = w_sniper2_hudpic
};
/* pickups */
#ifdef SERVER
void
weapon_th_sniper(void)
{
Weapons_InitItem(WEAPON_SNIPER2);
}
#endif

211
src/shared/w_spanner.qc Normal file
View File

@ -0,0 +1,211 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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
{
CBAR_IDLE,
CBAR_ATTACK1,
CBAR_ATTACK2,
CBAR_UNUSED,
CBAR_DRAW,
CBAR_HOLSTER
};
void
w_spanner_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_crowbar.hit");
Sound_Precache("weapon_crowbar.miss");
Sound_Precache("weapon_crowbar.hitbody");
#endif
precache_model("models/v_tfc_spanner.mdl");
precache_model("models/backpack.mdl");
precache_model("models/p_spanner.mdl");
}
void
w_spanner_updateammo(player pl)
{
w_crowbar_updateammo(pl);
}
string
w_spanner_wmodel(void)
{
return "models/backpack.mdl";
}
string
w_spanner_pmodel(void)
{
return "models/p_spanner.mdl";
}
string
w_spanner_deathmsg(void)
{
return "%s was retooled by %'s Wrench.";
}
void
w_spanner_draw(void)
{
Weapons_SetModel("models/v_tfc_spanner.mdl");
Weapons_ViewAnimation(CBAR_DRAW);
}
void
w_spanner_holster(void)
{
w_crowbar_holster();
}
void
w_spanner_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;
traceline(src, src + (v_forward * 32), FALSE, pl);
if (trace_fraction >= 1.0) {
pl.w_attack_next = 0.375f;
} else {
pl.w_attack_next = 0.20f;
}
pl.w_idle_next = 2.5f;
#ifdef CLIENT
if (random() < 0.5) {
Weapons_ViewAnimation(CBAR_ATTACK1);
} else {
Weapons_ViewAnimation(CBAR_ATTACK2);
}
#else
if (pl.flags & FL_CROUCHING) {
Animation_PlayerTopTemp(ANIM_SHOOTCROWBAR, 0.5f);
} else {
Animation_PlayerTopTemp(ANIM_CR_SHOOTCROWBAR, 0.42f);
}
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) {
return;
}
Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.hitbody");
} else {
Sound_Play(self, CHAN_WEAPON, "weapon_crowbar.hit");
}
#endif
}
void
w_spanner_release(void)
{
w_crowbar_release();
}
float
w_spanner_aimanim(void)
{
return w_crowbar_aimanim();
}
void
w_spanner_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/tfchud04.spr_0.tga",
[0,180/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/tfchud03.spr_0.tga",
[0,135/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_spanner =
{
.name = "spanner",
.id = ITEM_SPANNER,
.slot = 0,
.slot_pos = 2,
.draw = w_spanner_draw,
.holster = w_spanner_holster,
.primary = w_spanner_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_spanner_release,
.crosshair = __NULL__,
.precache = w_spanner_precache,
.pickup = __NULL__,
.updateammo = w_spanner_updateammo,
.wmodel = w_spanner_wmodel,
.pmodel = w_spanner_pmodel,
.deathmsg = w_spanner_deathmsg,
.aimanim = w_spanner_aimanim,
.hudpic = w_spanner_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_th_spanner(void)
{
Weapons_InitItem(WEAPON_SPANNER);
}
#endif

262
src/shared/w_taurus.qc Normal file
View File

@ -0,0 +1,262 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
*
* 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
{
TAURUS_IDLE1,
TAURUS_IDLE2,
TAURUS_IDLE3,
TAURUS_SHOOT,
TAURUS_SHOOT2,
TAURUS_SHOOT3,
TAURUS_SHOOT_EMPTY,
TAURUS_RELOAD,
TAURUS_RELOAD2,
TAURUS_DRAW,
TAURUS_HOLSTER
};
void
w_taurus_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_taurus.fire");
#endif
precache_model("models/v_taurus.mdl");
precache_model("models/w_taurus.mdl");
precache_model("models/p_taurus.mdl");
}
void
w_taurus_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.taurus_mag, pl.ammo_taurus, -1);
}
string
w_taurus_wmodel(void)
{
return "models/w_taurus.mdl";
}
string
w_taurus_pmodel(void)
{
return "models/p_taurus.mdl";
}
string
w_taurus_deathmsg(void)
{
return "%s is seeing blue from %s's Taurus.";
}
int
w_taurus_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (new) {
pl.taurus_mag = 10;
} else {
if (pl.ammo_taurus < MAX_A_TAURUS) {
pl.ammo_taurus = bound(0, pl.ammo_taurus + 10, MAX_A_TAURUS);
} else {
return FALSE;
}
}
#endif
return TRUE;
}
void
w_taurus_draw(void)
{
#ifdef CLIENT
Weapons_SetModel("models/v_taurus.mdl");
Weapons_ViewAnimation(TAURUS_DRAW);
#endif
}
void
w_taurus_holster(void)
{
#ifdef CLIENT
Weapons_ViewAnimation(TAURUS_HOLSTER);
#endif
}
void
w_taurus_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
/* ammo check */
if (!pl.taurus_mag) {
return;
}
pl.taurus_mag--;
/* actual firing */
#ifdef CLIENT
View_SetMuzzleflash(MUZZLE_SMALL);
Weapons_ViewPunchAngle([-2,0,0]);
if (pl.taurus_mag) {
Weapons_ViewAnimation(TAURUS_SHOOT);
} else {
Weapons_ViewAnimation(TAURUS_SHOOT_EMPTY);
}
#else
TraceAttack_FireBullets(1, pl.origin + pl.view_ofs, 12, [0.01,0.01], WEAPON_TAURUS);
Sound_Play(pl, CHAN_WEAPON, "weapon_taurus.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.25f;
pl.w_idle_next = 5.0f;
}
void
w_taurus_secondary(void)
{
}
void
w_taurus_reload(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
if (pl.taurus_mag >= 10) {
return;
}
if (pl.ammo_taurus <= 0) {
return;
}
#ifdef CLIENT
if (pl.taurus_mag) {
Weapons_ViewAnimation(TAURUS_RELOAD);
} else {
Weapons_ViewAnimation(TAURUS_RELOAD2);
}
#else
Weapons_ReloadWeapon(pl, player::taurus_mag, player::ammo_taurus, 10);
#endif
pl.w_attack_next = 2.0f;
pl.w_idle_next = 10.0f;
}
void
w_taurus_release(void)
{
player pl = (player)self;
int r;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.taurus_mag == 0 && pl.ammo_taurus > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}
r = floor(random(0,3));
switch (r) {
case 1:
Weapons_ViewAnimation(TAURUS_IDLE2);
pl.w_idle_next = 2.25f;
break;
case 2:
Weapons_ViewAnimation(TAURUS_IDLE3);
pl.w_idle_next = 2.5f;
break;
default:
Weapons_ViewAnimation(TAURUS_IDLE1);
pl.w_idle_next = 2.81f;
break;
}
}
float
w_taurus_aimanim(void)
{
return w_glock_aimanim();
}
void
w_taurus_hud(void)
{
w_glock_hud();
}
void
w_taurus_hudpic(int selected, vector pos, float a)
{
w_glock_hudpic(selected, pos, a);
}
weapon_t w_taurus =
{
.name = "taurus",
.id = ITEM_TAURUS,
.slot = 1,
.slot_pos = 3,
.draw = w_taurus_draw,
.holster = w_taurus_holster,
.primary = w_taurus_primary,
.secondary = w_taurus_secondary,
.reload = w_taurus_reload,
.release = w_taurus_release,
.crosshair = w_taurus_hud,
.precache = w_taurus_precache,
.pickup = w_taurus_pickup,
.updateammo = w_taurus_updateammo,
.wmodel = w_taurus_wmodel,
.pmodel = w_taurus_pmodel,
.deathmsg = w_taurus_deathmsg,
.aimanim = w_taurus_aimanim,
.hudpic = w_taurus_hudpic
};
/* pickups */
#ifdef SERVER
void
weapon_th_taurus(void)
{
Weapons_InitItem(WEAPON_TAURUS);
}
#endif

225
src/shared/w_tnt.qc Normal file
View File

@ -0,0 +1,225 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
*
* 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
{
HANDGRENADE_IDLE,
HANDGRENADE_FIDGET,
HANDGRENADE_PULLPIN,
HANDGRENADE_THROW1,
HANDGRENADE_THROW2,
HANDGRENADE_THROW3,
HANDGRENADE_HOLSTER,
HANDGRENADE_DRAW
};
void w_tnt_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_handgrenade.bounce");
#endif
precache_model("models/v_tnt.mdl");
precache_model("models/w_tnt.mdl");
precache_model("models/p_tnt.mdl");
}
void w_tnt_updateammo(player pl)
{
w_handgrenade_updateammo(pl);
}
string w_tnt_wmodel(void)
{
return "models/w_tnt.mdl";
}
string w_tnt_pmodel(void)
{
return "models/p_tnt.mdl";
}
string w_tnt_deathmsg(void)
{
return w_handgrenade_deathmsg();
}
int w_tnt_pickup(int new, int startammo)
{
return w_handgrenade_pickup(new, startammo);
}
#ifdef SERVER
void w_tnt_throw(void)
{
static void WeaponFrag_Throw_Explode(void)
{
float dmg = Skill_GetValue("plr_hand_grenade", 100);
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_tnt.mdl");
setsize(eGrenade, [0,0,0], [0,0,0]);
setorigin(eGrenade, vecSrc);
}
#endif
void w_tnt_draw(void)
{
player pl = (player)self;
pl.mode_tempstate = 0;
#ifdef CLIENT
Weapons_SetModel("models/v_tnt.mdl");
Weapons_ViewAnimation(HANDGRENADE_DRAW);
#endif
}
void w_tnt_holster(void)
{
}
void w_tnt_primary(void)
{
w_handgrenade_primary();
}
void w_tnt_hud(void)
{
#ifdef CLIENT
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [16,24], "sprites/640hud7.spr_0.tga", [48/256,96/128], [24/256, 24/128], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
void w_tnt_release(void)
{
player pl = (player)self;
if (pl.w_idle_next > 0.0) {
return;
}
if (pl.mode_tempstate == 1) {
#ifdef CLIENT
pl.ammo_handgrenade--;
Weapons_ViewAnimation(HANDGRENADE_THROW1);
#else
pl.ammo_handgrenade--;
w_tnt_throw();
#endif
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_tnt_aimanim(void)
{
return w_handgrenade_aimanim();
}
void
w_tnt_hudpic(int selected, vector pos, float a)
{
w_handgrenade_hudpic(selected, pos, a);
}
weapon_t w_tnt =
{
.name = "tnt",
.id = ITEM_HANDGRENADE,
.slot = 4,
.slot_pos = 0,
.draw = w_tnt_draw,
.holster = w_tnt_holster,
.primary = w_tnt_primary,
.secondary = w_tnt_release,
.reload = w_tnt_release,
.release = w_tnt_release,
.crosshair = w_tnt_hud,
.precache = w_tnt_precache,
.pickup = w_tnt_pickup,
.updateammo = w_tnt_updateammo,
.wmodel = w_tnt_wmodel,
.pmodel = w_tnt_pmodel,
.deathmsg = w_tnt_deathmsg,
.aimanim = w_tnt_aimanim,
.hudpic = w_tnt_hudpic
};

60
src/shared/weapons.h Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_SHOVEL,
WEAPON_SPANNER,
WEAPON_GLOCK,
WEAPON_PYTHON,
WEAPON_AP9,
WEAPON_TAURUS,
WEAPON_MP5,
WEAPON_SHOTGUN,
WEAPON_CROSSBOW,
WEAPON_SNIPER,
WEAPON_SNIPER2,
WEAPON_RPG,
WEAPON_GAUSS,
WEAPON_EGON,
WEAPON_CHAINGUN,
WEAPON_HANDGRENADE,
WEAPON_SATCHEL,
WEAPON_TRIPMINE,
WEAPON_SNARK,
WEAPON_MEDKIT
};
#define MAX_A_9MM 250
#define MAX_A_357 36
#define MAX_A_AP9 200
#define MAX_A_TAURUS 80
#define MAX_A_BUCKSHOT 125
#define MAX_A_M203_GRENADE 10
#define MAX_A_BOLT 50
#define MAX_A_SNIPER 50
#define MAX_A_ROCKET 5
#define MAX_A_URANIUM 100
#define MAX_A_GAS 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
#define MAX_A_MEDKIT 12

41
src/shared/weapons.qc Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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_shovel,
w_spanner,
w_silencer,
w_python,
w_ap9,
w_taurus,
w_mp5,
w_shotgun,
w_crossbow,
w_sniper,
w_sniper2,
w_rpg,
w_gauss,
w_flame,
w_chaingun,
w_tnt,
w_satchel,
w_tripmine,
w_snark,
w_medkit
};

47
zpak001.pk3dir/default.cfg Executable file
View File

@ -0,0 +1,47 @@
// 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" "They Hunger Server"
name "Einar"
model nypdcop
seta "maxplayers" "8"
// 2D/HUD Variables
seta "con_color" "255 0 0"
seta "vgui_color" "255 0 0"
seta "cross_color" "255 0 0"

View File

@ -0,0 +1,58 @@
thintro.bsp
they1.bsp
they2.bsp
they3.bsp
they4.bsp
they5.bsp
they6.bsp
they7.bsp
they8.bsp
they9.bsp
they10.bsp
they11.bsp
they12.bsp
they13.bsp
they14.bsp
they15.bsp
they16.bsp
they17.bsp
they18.bsp
they19.bsp
they20.bsp
they21.bsp
they22.bsp
they23.bsp
they24.bsp
they25.bsp
they26.bsp
they27.bsp
they28.bsp
they29.bsp
they30.bsp
they30a.bsp
they31.bsp
they32.bsp
they33.bsp
they34.bsp
they35.bsp
they36.bsp
they37.bsp
they38.bsp
they39.bsp
they40.bsp
they41.bsp
they42.bsp
they43.bsp
they44.bsp
they45.bsp
they46.bsp
they47.bsp
they48.bsp
they49.bsp
they50.bsp
they51.bsp
they52.bsp
they53.bsp
they54.bsp
they55.bsp
they56.bsp

View File

@ -0,0 +1,4 @@
ammo_gas.pickup
{
sample player/pl_slosh1.wav
}

View File

@ -0,0 +1,55 @@
weapon_ap9.fire
{
sample weapons/ap9_fire.wav
}
weapon_chaingun.fire
{
sample weapons/asscan2.wav
}
weapon_chaingun.reload
{
sample weapons/reload3.wav
}
weapon_chaingun.spindown
{
sample weapons/asscan3.wav
}
weapon_chaingun.spinup
{
sample weapons/asscan1.wav
}
weapon_medkit.heal
{
sample items/smallmedkit1.wav
}
weapon_flame.fire
{
sample weapons/flmfire2.wav
}
weapon_silencer.fire
{
sample weapons/pl_gun1.wav
sample weapons/pl_gun2.wav
}
weapon_sniper.fire
{
sample weapons/sniper.wav
}
weapon_sniper.reload
{
sample weapons/reload3.wav
}
weapon_taurus.fire
{
sample weapons/tau_fire.wav
}