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

This commit is contained in:
Marco Cawthorne 2021-03-08 11:58:43 +01:00
commit e26c38718a
32 changed files with 2898 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.

37
README.md Normal file
View File

@ -0,0 +1,37 @@
# FreePoke646
Clean-room reimplementation of Poke646 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 poke646
then either run Nuclide's ./build_game.sh shell script, or issue 'make' inside
./poke646/src!
Obviously make sure that Nuclide has fteqw and fteqcc set-up for building.
## Community
Join us on #halflife or #poke646 via irc.frag-net.com and chat.
## License
ISC License
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.

41
data.pk3dir/default.cfg Executable file
View File

@ -0,0 +1,41 @@
// 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"
// 2D/HUD Variables
seta "con_color" "193 207 204"
seta "vgui_color" "0 255 0"
seta "cross_color" "0 255 0"

View File

@ -0,0 +1,10 @@
weapon_bradnailer.fire
{
sample weapons/bradnailer.wav
}
weapon_bradnailer.hitbody
{
sample weapons/brad_hit1.wav
sample weapons/brad_hit2.wav
}

BIN
img/preview1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
img/preview2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
img/preview3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
img/preview4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 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

26
src/client/entities.qc Normal file
View File

@ -0,0 +1,26 @@
/*
* 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.
*/
int
ClientGame_EntityUpdate(float id, float new)
{
switch (id) {
default:
return FALSE;
}
return TRUE;
}

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

@ -0,0 +1,61 @@
/*
* 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/hud640_01.spr");
precache_model("sprites/hud640_02.spr");
precache_model("sprites/hud640_04.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 POKE646
#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
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

184
src/server/ammo_p646.qc Normal file
View File

@ -0,0 +1,184 @@
/*
* 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.
*/
class item_ammo:CBaseEntity
{
void(void) item_ammo;
virtual void(void) Respawn;
virtual void(void) touch;
};
void item_ammo::touch(void)
{
if not (other.flags & FL_CLIENT) {
return;
}
player pl = (player)other;
Sound_Play(other, CHAN_ITEM, "ammo.pickup");
Weapons_RefreshAmmo(pl);
Logging_Pickup(other, this, __NULL__);
if (cvar("sv_playerslots") == 1) {
remove(self);
} else {
Hide();
think = Respawn;
nextthink = time + 20.0f;
}
}
void item_ammo::Respawn(void)
{
solid = SOLID_TRIGGER;
movetype = MOVETYPE_TOSS;
if (m_oldModel) {
SetModel(m_oldModel);
}
setsize(this, [-16,-16,0], [16,16,16]);
SetOrigin(origin);
think = __NULL__;
nextthink = -1;
Sound_Play(this, CHAN_ITEM, "ammo.respawn");
droptofloor();
}
void item_ammo::item_ammo(void)
{
m_oldModel = model;
SetModel(m_oldModel);
CBaseEntity::CBaseEntity();
}
/*
* Ammo for the Crossbow.
* A single ammo_bolts will provide 5 bolts.
*/
class
ammo_bolts:item_ammo
{
void(void) ammo_bolts;
};
void
ammo_bolts::ammo_bolts(void)
{
model = "models/w_crossbow_clip.mdl";
}
/*QUAKED ammo_nailclip (0 0 0.8) (-16 -16 0) (16 16 32)
Poke646 (2001) ENTITY
Ammo for the nailguns.
A single ammo_nailclip will provide 25 nails.
*/
class ammo_nailclip:item_ammo
{
void(void) ammo_nailclip;
virtual void(void) touch;
};
void ammo_nailclip::ammo_nailclip(void)
{
model = "models/w_nailclip.mdl";
item_ammo::item_ammo();
}
void ammo_nailclip::touch(void)
{
if not (other.flags & FL_CLIENT) {
return;
}
if (other.classname == "player") {
player pl = (player)other;
if (pl.ammo_nail < MAX_A_NAIL) {
pl.ammo_nail = bound(0, pl.ammo_nail + 25, MAX_A_NAIL);
item_ammo::touch();
}
}
}
/*QUAKED ammo_nailround (0 0 0.8) (-16 -16 0) (16 16 32)
Poke646 (2001) ENTITY
Ammo for the nailguns.
A single ammo_nailround will provide 50 nails.
*/
class ammo_nailround:item_ammo
{
void(void) ammo_nailround;
virtual void(void) touch;
};
void ammo_nailround::ammo_nailround(void)
{
model = "models/w_nailround.mdl";
item_ammo::item_ammo();
}
void ammo_nailround::touch(void)
{
if not (other.flags & FL_CLIENT) {
return;
}
if (other.classname == "player") {
player pl = (player)other;
if (pl.ammo_nail < MAX_A_NAIL) {
pl.ammo_nail = bound(0, pl.ammo_nail + 50, MAX_A_NAIL);
item_ammo::touch();
}
}
}
/*QUAKED ammo_xencandy (0 0 0.8) (-16 -16 0) (16 16 32)
Poke646 (2001) ENTITY
Ammo for the alien.
A single ammo_xencandy will provide 20 snacks.
*/
class ammo_xencandy:item_ammo
{
void(void) ammo_xencandy;
virtual void(void) touch;
};
void ammo_xencandy::ammo_xencandy(void)
{
model = "models/w_xencandy.mdl";
item_ammo::item_ammo();
}
void ammo_xencandy::touch(void)
{
if not (other.flags & FL_CLIENT) {
return;
}
if (other.classname == "player") {
player pl = (player)other;
if (pl.ammo_xencandy < MAX_A_XENCANDY) {
pl.ammo_xencandy = bound(0, pl.ammo_xencandy + 20, MAX_A_XENCANDY);
item_ammo::touch();
}
}
}

127
src/server/gamerules.qc Normal file
View File

@ -0,0 +1,127 @@
/*
* 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.
*/
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
HLGameRules::PlayerPostFrame(base_player pp)
{
Animation_PlayerUpdate();
}
void
HLGameRules::LevelNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm64 = FL_CLIENT;
}
void
HLGameRules::LevelDecodeParms(base_player pp)
{
player pl = (player)pp;
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.flags = parm64;
pl.ammo_nail = parm12;
pl.ammo_buckshot = parm13;
pl.ammo_bolts = parm14;
pl.ammo_xencandy = parm15;
pl.ammo_satchel = parm16;
pl.bradnailer_mag = parm17;
pl.nailgun_mag = parm18;
pl.shotgun_mag = parm19;
pl.cmlwbr_mag = parm20;
pl.xs_mag = parm21;
pl.satchel_chg = parm22;
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
}
}
void
HLGameRules::LevelChangeParms(base_player pp)
{
player pl = (player)pp;
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm64 = pl.flags;
parm10 = pl.g_items;
parm11 = pl.activeweapon;
parm12 = pl.ammo_nail;
parm13 = pl.ammo_buckshot;
parm14 = pl.ammo_bolts;
parm15 = pl.ammo_xencandy;
parm16 = pl.ammo_satchel;
parm17 = pl.bradnailer_mag;
parm18 = pl.nailgun_mag;
parm19 = pl.shotgun_mag;
parm20 = pl.cmlwbr_mag;
parm21 = pl.xs_mag;
parm22 = pl.satchel_chg;
}
void
HLGameRules::PlayerConnect(base_player pl)
{
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname));
}
void
HLGameRules::PlayerDisconnect(base_player pl)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = PLAYER_MODELINDEX;
}
void
HLGameRules::PlayerKill(base_player pp)
{
player pl = (player)pp;
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}

View File

@ -0,0 +1,120 @@
/*
* 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.
*/
void
HLMultiplayerRules::FrameStart(void)
{
if (cvar("mp_timelimit") != 0)
if (time >= (cvar("mp_timelimit") * 60)) {
IntermissionStart();
}
}
void
HLMultiplayerRules::PlayerDeath(base_player pp)
{
player pl = (player)pp;
pl.movetype = MOVETYPE_NONE;
pl.solid = SOLID_NOT;
pl.takedamage = DAMAGE_NO;
pl.gflags &= ~GF_FLASHLIGHT;
pl.armor = pl.activeweapon = pl.g_items = 0;
pl.think = PutClientInServer;
pl.nextthink = time + 4.0f;
if (pl.health < -50) {
pl.health = 0;
FX_GibHuman(pl.origin);
return;
}
pl.health = 0;
/* Let's handle corpses on the clientside */
entity corpse = spawn();
setorigin(corpse, pl.origin + [0,0,32]);
setmodel(corpse, pl.model);
setsize(corpse, VEC_HULL_MIN, VEC_HULL_MAX);
corpse.movetype = MOVETYPE_TOSS;
corpse.solid = SOLID_TRIGGER;
corpse.modelindex = pl.modelindex;
corpse.frame = ANIM_DIESIMPLE;
corpse.angles = pl.angles;
corpse.velocity = pl.velocity;
}
void
HLMultiplayerRules::PlayerSpawn(base_player pp)
{
player pl = (player)pp;
/* this is where the mods want to deviate */
entity spot;
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
LevelNewParms();
LevelDecodeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
float
HLMultiplayerRules::ConsoleCommand(base_player pp, string cmd)
{
tokenize(cmd);
switch (argv(0)) {
case "bot_add":
Bot_AddQuick();
break;
default:
return FALSE;
}
return TRUE;
}

65
src/server/input.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.
*/
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;
Weapons_AddItem(pl, WEAPON_HEATERPIPE, -1);
Weapons_AddItem(pl, WEAPON_BRADNAILER, -1);
Weapons_AddItem(pl, WEAPON_NAILGUN, -1);
Weapons_AddItem(pl, WEAPON_SHOTGUN, -1);
Weapons_AddItem(pl, WEAPON_CMLWBR, -1);
Weapons_AddItem(pl, WEAPON_XS, -1);
Weapons_AddItem(pl, WEAPON_SATCHEL, -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;
}

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

@ -0,0 +1,89 @@
#pragma target fte
#pragma progs_dat "../../progs.dat"
#define QWSSQC
#define SERVER
#define VALVE
#define POKE646
#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/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
ammo_p646.qc
../../../src/botlib/include.src
gamerules.qc
../../../valve/src/server/gamerules_singleplayer.qc
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

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

@ -0,0 +1,29 @@
#includelist
../../../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_satchel.qc
w_bradnailer.qc
w_cmlwbr.qc
w_heaterpipe.qc
w_nailgun.qc
w_pipebomb.qc
w_shotgun.qc
w_xs.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_HEATERPIPE 0x00000001i
#define ITEM_BRADNAILER 0x00000002i
#define ITEM_NAILGUN 0x00000004i
#define ITEM_SHOTGUN 0x00000008i
#define ITEM_CMLWBR 0x00000010i
#define ITEM_XS 0x00000020i
#define ITEM_SATCHEL 0x00000040i
#define ITEM_UNUSED8 0x00000080i
#define ITEM_UNUSED9 0x00000100i
#define ITEM_UNUSED10 0x00000200i
#define ITEM_UNUSED11 0x00000400i
#define ITEM_UNUSED12 0x00000800i
#define ITEM_UNUSED13 0x00001000i
#define ITEM_UNUSED14 0x00002000i
#define ITEM_SUIT 0x00004000i
#define ITEM_LONGJUMP 0x00008000i
#define ITEM_UNUSED17 0x00010000i
#define ITEM_UNUSED18 0x00020000i
#define ITEM_UNUSED19 0x00040000i
#define ITEM_UNUSED20 0x00080000i
#define ITEM_UNUSED21 0x00100000i
#define ITEM_UNUSED22 0x00200000i
#define ITEM_UNUSED23 0x00400000i
#define ITEM_UNUSED24 0x00800000i
#define ITEM_UNUSED25 0x01000000i
#define ITEM_UNUSED26 0x02000000i
#define ITEM_UNUSED27 0x04000000i
#define ITEM_UNUSED28 0x08000000i
#define ITEM_UNUSED29 0x10000000i
#define ITEM_UNUSED30 0x20000000i
#define ITEM_UNUSED31 0x40000000i
#define ITEM_UNUSED32 0x80000000i

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

@ -0,0 +1,464 @@
/*
* 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
};
noref int input_sequence;
class player:base_player
{
/* Weapon specific */
int bradnailer_mag; int bradnailer_mag_net;
int nailgun_mag; int nailgun_mag_net;
int shotgun_mag; int shotgun_mag_net;
int cmlwbr_mag; int cmlwbr_mag_net;
int xs_mag; int xs_mag_net;
int satchel_chg; int satchel_chg_net;
int ammo_nail; int ammo_nail_net;
int ammo_buckshot; int ammo_buckshot_net;
int ammo_bolts; int ammo_bolts_net;
int ammo_xencandy; int ammo_xencandy_net;
int ammo_satchel; int ammo_satchel_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) {
bradnailer_mag = readbyte();
nailgun_mag = readbyte();
shotgun_mag = readbyte();
cmlwbr_mag = readbyte();
xs_mag = readbyte();
satchel_chg = readbyte();
}
if (fl & PLAYER_AMMO2) {
ammo_nail = readbyte();
ammo_buckshot = readbyte();
ammo_bolts = readbyte();
ammo_xencandy = readbyte();
ammo_satchel = readbyte();
}
if (fl & PLAYER_AMMO3) {
}
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)
{
bradnailer_mag_net = bradnailer_mag;
nailgun_mag_net = nailgun_mag;
shotgun_mag_net = shotgun_mag;
cmlwbr_mag_net = cmlwbr_mag;
xs_mag_net = xs_mag;
satchel_chg_net = satchel_chg;
ammo_nail_net = ammo_nail;
ammo_buckshot_net = ammo_buckshot;
ammo_bolts_net = ammo_bolts;
ammo_xencandy_net = ammo_xencandy;
ammo_satchel_net = ammo_satchel;
}
/*
=================
player::PredictPostFrame
Where we roll back our values to the ones last sent/verified by the server.
=================
*/
void
player::PredictPostFrame(void)
{
bradnailer_mag = bradnailer_mag_net;
nailgun_mag = nailgun_mag_net;
shotgun_mag = shotgun_mag_net;
cmlwbr_mag = cmlwbr_mag_net;
xs_mag = xs_mag_net;
satchel_chg = satchel_chg_net;
ammo_nail = ammo_nail_net;
ammo_buckshot = ammo_buckshot_net;
ammo_bolts = ammo_bolts_net;
ammo_xencandy = ammo_xencandy_net;
ammo_satchel = ammo_satchel_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;
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;
if (bradnailer_mag_net != bradnailer_mag)
SendFlags |= PLAYER_AMMO1;
if (nailgun_mag_net != nailgun_mag)
SendFlags |= PLAYER_AMMO1;
if (shotgun_mag_net != shotgun_mag)
SendFlags |= PLAYER_AMMO1;
if (cmlwbr_mag_net != cmlwbr_mag)
SendFlags |= PLAYER_AMMO1;
if (xs_mag_net != xs_mag)
SendFlags |= PLAYER_AMMO1;
if (satchel_chg_net != satchel_chg)
SendFlags |= PLAYER_AMMO1;
if (ammo_nail_net != ammo_nail)
SendFlags |= PLAYER_AMMO2;
if (ammo_buckshot_net != ammo_buckshot)
SendFlags |= PLAYER_AMMO2;
if (ammo_bolts_net != ammo_bolts)
SendFlags |= PLAYER_AMMO2;
if (ammo_xencandy_net != ammo_xencandy)
SendFlags |= PLAYER_AMMO2;
if (ammo_satchel_net != ammo_satchel)
SendFlags |= PLAYER_AMMO2;
bradnailer_mag_net = bradnailer_mag;
nailgun_mag_net = nailgun_mag;
shotgun_mag_net = shotgun_mag;
cmlwbr_mag_net = cmlwbr_mag;
xs_mag_net = xs_mag;
satchel_chg_net = satchel_chg;
ammo_nail_net = ammo_nail;
ammo_buckshot_net = ammo_buckshot;
ammo_bolts_net = ammo_bolts;
ammo_xencandy_net = ammo_xencandy;
ammo_satchel_net = ammo_satchel;
}
/*
=================
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, bradnailer_mag);
WriteByte(MSG_ENTITY, nailgun_mag);
WriteByte(MSG_ENTITY, shotgun_mag);
WriteByte(MSG_ENTITY, cmlwbr_mag);
WriteByte(MSG_ENTITY, xs_mag);
WriteByte(MSG_ENTITY, satchel_chg);
}
if (fChanged & PLAYER_AMMO2) {
WriteByte(MSG_ENTITY, ammo_nail);
WriteByte(MSG_ENTITY, ammo_buckshot);
WriteByte(MSG_ENTITY, ammo_bolts);
WriteByte(MSG_ENTITY, ammo_xencandy);
WriteByte(MSG_ENTITY, ammo_satchel);
}
if (fChanged & PLAYER_AMMO3) {
}
return TRUE;
}
#endif

268
src/shared/w_bradnailer.qc Normal file
View File

@ -0,0 +1,268 @@
/*
* 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.
*/
/*QUAKED weapon_bradnailer (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_bradnailer.mdl"
Poke646 (2001) ENTITY
Handheld Nailgun that kills like a pistol
*/
enum
{
BNAIL_IDLE1,
BNAIL_IDLE2,
BNAIL_IDLE3,
BNAIL_SHOOT,
BNAIL_UNUSED1,
BNAIL_RELOAD,
BNAIL_UNUSED2,
BNAIL_DRAW,
BNAIL_HOLSTER,
BNAIL_UNUSED3,
BNAIL_TILT,
BNAIL_TILTBACK,
BNAIL_SHOOT2
};
void
w_bradnailer_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_bradnailer.fire");
Sound_Precache("weapon_bradnailer.hitbody");
#endif
precache_model("models/nail.mdl");
precache_model("models/v_bradnailer.mdl");
precache_model("models/w_bradnailer.mdl");
}
void
w_bradnailer_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, pl.bradnailer_mag, pl.ammo_nail, -1);
}
string
w_bradnailer_wmodel(void)
{
return "models/w_bradnailer.mdl";
}
int
w_bradnailer_pickup(int new, int startammo)
{
/* TODO */
return TRUE;
}
void
w_bradnailer_draw(void)
{
Weapons_SetModel("models/v_bradnailer.mdl");
Weapons_ViewAnimation(BNAIL_DRAW);
}
void
w_bradnailer_holster(void)
{
Weapons_ViewAnimation(BNAIL_HOLSTER);
}
#ifdef SERVER
void
w_bradnailer_shootnail(void)
{
player pl = (player)self;
static void Nail_Touch(void) {
FX_Spark(self.origin, trace_plane_normal);
if (other.takedamage == DAMAGE_YES) {
Damage_Apply(other, self.owner, 15, WEAPON_BRADNAILER, DMG_GENERIC);
Sound_Play(self, CHAN_WEAPON, "weapon_bradnailer.hitbody");
} else {
Sound_Play(self, CHAN_WEAPON, "weapon_crossbow.hit");
}
remove(self);
}
Weapons_MakeVectors();
entity nail = spawn();
setmodel(nail, "models/nail.mdl");
setorigin(nail, Weapons_GetCameraPos() + (v_forward * 16));
nail.owner = self;
nail.velocity = v_forward * 2000;
nail.movetype = MOVETYPE_FLY;
nail.solid = SOLID_BBOX;
nail.angles = vectoangles(nail.velocity);
nail.avelocity[2] = 10;
nail.touch = Nail_Touch;
setsize(nail, [0,0,0], [0,0,0]);
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_bradnailer.fire");
}
#endif
void
w_bradnailer_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
#ifdef SERVER
w_bradnailer_shootnail();
#else
Weapons_ViewPunchAngle([-2,0,0]);
Weapons_ViewAnimation(BNAIL_SHOOT);
#endif
pl.w_attack_next = 0.3f;
pl.w_idle_next = 5.0f;
}
void
w_bradnailer_secondary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
/* Hack */
if (pl.a_ammo3 == 0) {
pl.a_ammo3 = 1;
Weapons_ViewAnimation(BNAIL_TILT);
pl.w_attack_next = 0.4f;
pl.w_idle_next = pl.w_attack_next;
return;
}
#ifdef SERVER
w_bradnailer_shootnail();
#else
Weapons_ViewPunchAngle([-2,0,0]);
Weapons_ViewAnimation(BNAIL_SHOOT2);
#endif
pl.w_attack_next = 0.2f;
pl.w_idle_next = pl.w_attack_next;
}
void
w_bradnailer_release(void)
{
player pl = (player)self;
if (pl.w_idle_next > 0.0) {
return;
}
if (pl.a_ammo3 == 1) {
pl.a_ammo3 = 0;
Weapons_ViewAnimation(BNAIL_TILTBACK);
pl.w_attack_next = 0.4f;
pl.w_idle_next = pl.w_attack_next;
return;
}
int r = (float)input_sequence % 3;
switch (r) {
case 0:
Weapons_ViewAnimation(BNAIL_IDLE1);
break;
case 1:
Weapons_ViewAnimation(BNAIL_IDLE2);
break;
case 2:
Weapons_ViewAnimation(BNAIL_IDLE3);
break;
}
pl.w_idle_next = 10.0f;
}
void
w_bradnailer_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/hud640_01.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/hud640_01.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_bradnailer =
{
.name = "bradnailer",
.id = ITEM_BRADNAILER,
.slot = 1,
.slot_pos = 0,
.draw = w_bradnailer_draw,
.holster = w_bradnailer_holster,
.primary = w_bradnailer_primary,
.secondary = w_bradnailer_secondary,
.reload = __NULL__,
.release = w_bradnailer_release,
.crosshair = __NULL__,
.precache = w_bradnailer_precache,
.pickup = w_bradnailer_pickup,
.updateammo = w_bradnailer_updateammo,
.wmodel = w_bradnailer_wmodel,
.pmodel = __NULL__,
.deathmsg = __NULL__,
.aimanim = __NULL__,
.hudpic = w_bradnailer_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_bradnailer(void)
{
Weapons_InitItem(WEAPON_BRADNAILER);
}
#endif

151
src/shared/w_cmlwbr.qc Normal file
View File

@ -0,0 +1,151 @@
/*
* 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
{
CML_IDLE1,
CML_IDLE2,
CML_IDLE3,
CML_IDLE4,
CML_FIRE1,
CML_RELOAD,
CML_DRAWBACK,
CML_UNDRAW,
CML_DRAW,
CML_UNUSED,
CML_HOLSTER
};
void
w_cmlwbr_precache(void)
{
precache_sound("weapons/cmlwbr_drawback.wav");
precache_sound("weapons/cmlwbr_fire.wav");
precache_sound("weapons/cmlwbr_reload.wav");
precache_sound("weapons/cmlwbr_undraw.wav");
precache_sound("weapons/cmlwbr_zoom.wav");
precache_model("models/v_cmlwbr.mdl");
precache_model("models/w_crossbow.mdl");
}
void
w_cmlwbr_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__);
#endif
}
string
w_cmlwbr_wmodel(void)
{
return "models/w_crossbow.mdl";
}
void
w_cmlwbr_draw(void)
{
Weapons_SetModel("models/v_cmlwbr.mdl");
Weapons_ViewAnimation(CML_DRAW);
}
void
w_cmlwbr_holster(void)
{
Weapons_ViewAnimation(CML_HOLSTER);
}
void
w_cmlwbr_primary(void)
{
/* TODO, attack slows to crawl & player breathes */
}
void
w_cmlwbr_secondary(void)
{
}
void
w_cmlwbr_release(void)
{
}
void
w_cmlwbr_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/hud640_03.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/hud640_03.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_cmlwbr =
{
.name = "cmlwbr",
.id = ITEM_CMLWBR,
.slot = 2,
.slot_pos = 1,
.draw = w_cmlwbr_draw,
.holster = w_cmlwbr_holster,
.primary = w_cmlwbr_primary,
.secondary = w_cmlwbr_secondary,
.reload = __NULL__,
.release = w_cmlwbr_release,
.crosshair = __NULL__,
.precache = w_cmlwbr_precache,
.pickup = __NULL__,
.updateammo = w_cmlwbr_updateammo,
.wmodel = w_cmlwbr_wmodel,
.pmodel = __NULL__,
.deathmsg = __NULL__,
.aimanim = __NULL__,
.hudpic = w_cmlwbr_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_cmlwbr(void)
{
Weapons_InitItem(WEAPON_CMLWBR);
}
#endif

140
src/shared/w_heaterpipe.qc Normal file
View File

@ -0,0 +1,140 @@
/*
* 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
{
HPIPE_IDLE1,
HPIPE_DRAW,
HPIPE_HOLSTER,
HPIPE_ATTACK1,
HPIPE_ATTACK1MISS,
HPIPE_ATTACK2MISS,
HPIPE_ATTACK2,
HPIPE_ATTACK3MISS,
HPIPE_ATTACK3
};
void
w_heaterpipe_precache(void)
{
precache_sound("weapons/pipe_hit1.wav");
precache_sound("weapons/pipe_hit2.wav");
precache_sound("weapons/pipe_miss.wav");
precache_model("models/v_heaterpipe.mdl");
precache_model("models/w_heaterpipe.mdl");
}
void
w_heaterpipe_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__);
#endif
}
string
w_heaterpipe_wmodel(void)
{
return "models/w_heaterpipe.mdl";
}
void
w_heaterpipe_draw(void)
{
Weapons_SetModel("models/v_heaterpipe.mdl");
Weapons_ViewAnimation(HPIPE_DRAW);
}
void
w_heaterpipe_holster(void)
{
Weapons_ViewAnimation(HPIPE_HOLSTER);
}
void
w_heaterpipe_primary(void)
{
/* TODO, attack slows to crawl & player breathes */
}
void
w_heaterpipe_release(void)
{
}
void
w_heaterpipe_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/hud640_01.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/hud640_01.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_heaterpipe =
{
.name = "heaterpipe",
.id = ITEM_HEATERPIPE,
.slot = 0,
.slot_pos = 0,
.draw = w_heaterpipe_draw,
.holster = w_heaterpipe_holster,
.primary = w_heaterpipe_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_heaterpipe_release,
.crosshair = __NULL__,
.precache = w_heaterpipe_precache,
.pickup = __NULL__,
.updateammo = w_heaterpipe_updateammo,
.wmodel = w_heaterpipe_wmodel,
.pmodel = __NULL__,
.deathmsg = __NULL__,
.aimanim = __NULL__,
.hudpic = w_heaterpipe_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_heaterpipe(void)
{
Weapons_InitItem(WEAPON_HEATERPIPE);
}
#endif

196
src/shared/w_nailgun.qc Normal file
View File

@ -0,0 +1,196 @@
/*
* 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
{
NAIL_IDLE1,
NAIL_IDLE2,
NAIL_UNUSED1,
NAIL_RELOAD,
NAIL_DRAW,
NAIL_SHOOT
};
void
w_nailgun_precache(void)
{
precache_sound("weapons/brad_hit1.wav");
precache_sound("weapons/brad_hit2.wav");
precache_sound("weapons/nailgun.wav");
precache_model("models/nail.mdl");
precache_model("models/v_nailgun.mdl");
precache_model("models/w_nailgun.mdl");
}
void
w_nailgun_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__);
#endif
}
string
w_nailgun_wmodel(void)
{
return "models/w_nailgun.mdl";
}
void
w_nailgun_draw(void)
{
Weapons_SetModel("models/v_nailgun.mdl");
Weapons_ViewAnimation(NAIL_DRAW);
}
void
w_nailgun_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next > 0.0) {
return;
}
#ifdef SERVER
static void Nail_Touch(void) {
FX_Spark(self.origin, trace_plane_normal);
if (other.takedamage == DAMAGE_YES) {
Damage_Apply(other, self.owner, 15, WEAPON_NAILGUN, DMG_GENERIC);
if (random() < 0.5) {
Weapons_PlaySound(self, CHAN_WEAPON, "weapons/brad_hit1.wav", 1, ATTN_NORM);
} else {
Weapons_PlaySound(self, CHAN_WEAPON, "weapons/brad_hit2.wav", 1, ATTN_NORM);
}
} else {
Weapons_PlaySound(self, CHAN_WEAPON, "weapons/xbow_hit1.wav", 1, ATTN_NORM);
}
remove(self);
}
Weapons_MakeVectors();
entity nail = spawn();
setmodel(nail, "models/nail.mdl");
setorigin(nail, Weapons_GetCameraPos() + (v_forward * 16));
nail.owner = self;
nail.velocity = v_forward * 2000;
nail.movetype = MOVETYPE_FLY;
nail.solid = SOLID_BBOX;
nail.angles = vectoangles(nail.velocity);
nail.avelocity[2] = 10;
nail.touch = Nail_Touch;
setsize(nail, [0,0,0], [0,0,0]);
if (self.flags & FL_CROUCHING)
Animation_PlayerTopTemp(ANIM_SHOOT1HAND, 0.45f);
else
Animation_PlayerTopTemp(ANIM_CR_SHOOT1HAND, 0.45f);
Weapons_PlaySound(pl, CHAN_WEAPON, "weapons/nailgun.wav", 1, ATTN_NORM);
#else
Weapons_ViewPunchAngle([-2,0,0]);
Weapons_ViewAnimation(NAIL_SHOOT);
#endif
pl.w_attack_next = 0.1f;
pl.w_idle_next = 5.0f;
}
void
w_nailgun_release(void)
{
player pl = (player)self;
if (pl.w_idle_next > 0) {
return;
}
if (random() < 0.5) {
Weapons_ViewAnimation(NAIL_IDLE1);
} else {
Weapons_ViewAnimation(NAIL_IDLE2);
}
pl.w_idle_next = 10.0f;
}
void
w_nailgun_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/hud640_01.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/hud640_01.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_nailgun =
{
.name = "nailgun",
.id = ITEM_NAILGUN,
.slot = 1,
.slot_pos = 1,
.draw = w_nailgun_draw,
.holster = __NULL__,
.primary = w_nailgun_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_nailgun_release,
.crosshair = __NULL__,
.precache = w_nailgun_precache,
.pickup = __NULL__,
.updateammo = w_nailgun_updateammo,
.wmodel = w_nailgun_wmodel,
.pmodel = __NULL__,
.deathmsg = __NULL__,
.aimanim = __NULL__,
.hudpic = w_nailgun_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_nailgun(void)
{
Weapons_InitItem(WEAPON_NAILGUN);
}
#endif

276
src/shared/w_pipebomb.qc Normal file
View File

@ -0,0 +1,276 @@
/*
* 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.
*/
/*QUAKED weapon_pipebomb (0 0 1) (-16 -16 0) (16 16 32)
"model" "models/w_pipebomb.mdl"
Poke646 (2001) ENTITY
Pipebomb Weapon, literal copy of Half-Life's Satchel Weapon
*/
enum
{
SATCHEL_IDLE,
SATCHEL_FIDGET,
SATCHEL_DRAW,
SATCHEL_THROW
};
enum
{
RADIO_IDLE,
RADIO_FIDGET,
RADIO_DRAW,
RADIO_USE,
RADIO_HOLSTER
};
void w_pipebomb_updateammo(player pl)
{
w_satchel_updateammo(pl);
}
string w_pipebomb_wmodel(void)
{
return "models/w_pipebomb.mdl";
}
string w_pipebomb_pmodel(void)
{
return "models/p_pipebomb.mdl";
}
string w_pipebomb_deathmsg(void)
{
return "%s blew up %s with a pipebomb.";
}
void w_pipebomb_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_satchel.bounce");
#endif
precache_model("models/w_pipebomb.mdl");
precache_model("models/v_pipebomb.mdl");
precache_model("models/v_pipebomb_watch.mdl");
precache_model("models/p_pipebomb.mdl");
}
int w_pipebomb_pickup(int new, int startammo)
{
return w_satchel_pickup(new, startammo);
}
void w_pipebomb_draw(void)
{
Weapons_SetModel("models/v_pipebomb.mdl");
Weapons_ViewAnimation(SATCHEL_DRAW);
#ifdef SERVER
player pl = (player)self;
Weapons_UpdateAmmo(pl, pl.satchel_chg, pl.ammo_satchel, __NULL__);
#endif
}
void w_pipebomb_holster(void)
{
}
#ifdef SERVER
void s_pipebomb_drop(entity master, vector src, vector vel)
{
static void s_pipebomb_touch(void)
{
if (other == world)
Sound_Play(self, CHAN_BODY, "weapon_satchel.bounce");
}
entity satch;
satch = spawn();
satch.owner = master;
satch.classname = "satchel";
satch.movetype = MOVETYPE_BOUNCE;
satch.solid = SOLID_BBOX;
satch.frame = 1;
satch.gravity = 0.5f;
satch.friction = 0.8f;
satch.velocity = vel;
satch.avelocity = [0,400,0];
satch.touch = s_pipebomb_touch;
setmodel(satch, "models/w_satchel.mdl");
setsize(satch, [-4,-4,-4], [4,4,4]);
setorigin(satch, src);
}
void s_pipebomb_detonate(entity master)
{
for (entity b = world; (b = find(b, ::classname, "satchel"));) {
if (b.owner == master) {
float dmg = Skill_GetValue("plr_satchel", 150);
FX_Explosion(b.origin);
Damage_Radius(b.origin, master, dmg, dmg * 2.5f, TRUE, WEAPON_SATCHEL);
sound(b, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
remove(b);
}
}
}
#endif
void w_pipebomb_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next) {
return;
}
/* Ammo check */
#ifdef CLIENT
if (pl.satchel_chg <= 0 && pl.ammo_satchel <= 0) {
return;
}
#else
if (pl.satchel_chg <= 0 && pl.ammo_satchel <= 0) {
return;
}
#endif
if (pl.satchel_chg <= 0) {
Weapons_ViewAnimation(RADIO_DRAW);
} else {
Weapons_ViewAnimation(RADIO_USE);
}
#ifdef SERVER
if (!pl.satchel_chg) {
vector throw;
Weapons_MakeVectors();
throw = pl.velocity + (v_forward * 274);
s_pipebomb_drop(self, pl.origin, throw);
pl.satchel_chg++;
pl.ammo_satchel--;
} else {
s_pipebomb_detonate(pl);
pl.satchel_chg = 0;
if (pl.ammo_satchel <= 0) {
Weapons_RemoveItem(pl, WEAPON_SATCHEL);
}
}
Weapons_UpdateAmmo(pl, pl.satchel_chg, pl.ammo_satchel, __NULL__);
#else
setmodel(pSeat->m_eViewModel, "models/v_pipebomb_watch.mdl");
pl.satchel_chg++;
pl.ammo_satchel--;
#endif
pl.w_attack_next = 1.0f;
pl.w_idle_next = 1.0f;
}
void w_pipebomb_secondary(void)
{
player pl = (player)self;
if (pl.w_attack_next) {
return;
}
/* Ammo check */
#ifdef CLIENT
if (pl.ammo_satchel <= 0) {
return;
}
#else
if (pl.ammo_satchel <= 0) {
return;
}
#endif
#ifdef SERVER
vector throw;
Weapons_MakeVectors();
throw = pl.velocity + (v_forward * 274);
s_pipebomb_drop(self, pl.origin, throw);
pl.satchel_chg++;
pl.ammo_satchel--;
Weapons_UpdateAmmo(pl, pl.satchel_chg, pl.ammo_satchel, __NULL__);
#else
pl.satchel_chg++;
pl.ammo_satchel--;
setmodel(pSeat->m_eViewModel, "models/v_pipebomb_watch.mdl");
#endif
Weapons_ViewAnimation(RADIO_DRAW);
pl.w_attack_next = 1.0f;
pl.w_idle_next = 2.5f;
}
void w_pipebomb_reload(void)
{
}
void w_pipebomb_release(void)
{
w_satchel_release();
}
float w_pipebomb_aimanim(void)
{
return w_satchel_aimanim();
}
void w_pipebomb_hud(void)
{
w_satchel_holster();
}
void w_pipebomb_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(pos, [170,45], "sprites/640hud6.spr_0.tga", [0,45/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
} else {
drawsubpic(pos, [170,45], "sprites/640hud3.spr_0.tga", [0,45/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
}
#endif
}
weapon_t w_pipebomb =
{
.name = "pipebomb",
.id = ITEM_SATCHEL,
.slot = 4,
.slot_pos = 1,
.draw = w_pipebomb_draw,
.holster = w_pipebomb_holster,
.primary = w_pipebomb_primary,
.secondary = w_pipebomb_secondary,
.reload = __NULL__,
.release = w_pipebomb_release,
.crosshair = w_pipebomb_hud,
.precache = w_pipebomb_precache,
.pickup = w_pipebomb_pickup,
.updateammo = w_pipebomb_updateammo,
.wmodel = w_pipebomb_wmodel,
.pmodel = __NULL__,
.deathmsg = __NULL__,
.aimanim = w_pipebomb_aimanim,
.hudpic = w_pipebomb_hudpic
};
#ifdef SERVER
void weapon_pipebomb(void) {
Weapons_InitItem(WEAPON_SATCHEL);
}
#endif

280
src/shared/w_shotgun.qc Normal file
View File

@ -0,0 +1,280 @@
/*
* 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
{
SHOTGUN_IDLE1,
SHOTGUN_FIRE1,
SHOTGUN_RELOAD,
SHOTGUN_PUMP,
SHOTGUN_START_RELOAD,
SHOTGUN_DRAW,
SHOTGUN_HOLSTER,
SHOTGUN_IDLE2
};
enum
{
SHOTTY_IDLE,
SHOTTY_RELOAD_START,
SHOTTY_RELOAD,
SHOTTY_RELOAD_END
};
void w_shotgun_precache(void)
{
precache_model("models/v_shotgun.mdl");
precache_model("models/w_shotgun.mdl");
precache_model("models/p_shotgun.mdl");
precache_sound("weapons/sbarrel1.wav");
precache_sound("weapons/dbarrel1.wav");
precache_sound("weapons/reload3.wav");
precache_sound("weapons/scock1.wav");
}
void w_shotgun_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, pl.shotgun_mag, pl.ammo_buckshot, __NULL__);
#endif
}
string w_shotgun_wmodel(void)
{
return "models/w_shotgun.mdl";
}
string w_shotgun_pmodel(void)
{
return "models/p_shotgun.mdl";
}
string w_shotgun_deathmsg(void)
{
return "";
}
int w_shotgun_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (new) {
pl.shotgun_mag = 8;
} else {
if (pl.ammo_buckshot < 125) {
pl.ammo_buckshot = bound(0, pl.ammo_buckshot + 8, 125);
} else {
return FALSE;
}
}
#endif
return TRUE;
}
void w_shotgun_draw(void)
{
Weapons_SetModel("models/v_shotgun.mdl");
Weapons_ViewAnimation(SHOTGUN_DRAW);
#ifdef SERVER
player pl = (player)self;
Weapons_UpdateAmmo(pl, pl.shotgun_mag, pl.ammo_buckshot, __NULL__);
#endif
}
void w_shotgun_holster(void)
{
Weapons_ViewAnimation(SHOTGUN_HOLSTER);
}
void w_shotgun_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next) {
return;
}
if (pl.a_ammo3 > SHOTTY_IDLE) {
return;
}
/* Ammo check */
#ifdef SERVER
if (pl.shotgun_mag <= 0) {
return;
}
#else
if (pl.a_ammo1 <= 0) {
return;
}
#endif
#ifdef SERVER
/* Singleplayer is more accurate */
if (cvar("sv_playerslots") == 1) {
TraceAttack_FireBullets(6, pl.origin + pl.view_ofs, 5, [0.08716,0.08716], WEAPON_SHOTGUN);
} else {
TraceAttack_FireBullets(4, pl.origin + pl.view_ofs, 5, [0.08716,0.04362], WEAPON_SHOTGUN);
}
Weapons_PlaySound(pl, CHAN_WEAPON, "weapons/dbarrel1.wav", 1, ATTN_NORM);
pl.shotgun_mag--;
Weapons_UpdateAmmo(pl, pl.shotgun_mag, pl.ammo_buckshot, __NULL__);
#else
View_SetMuzzleflash(MUZZLE_WEIRD);
Weapons_ViewPunchAngle([-5,0,0]);
pl.a_ammo1--;
#endif
Weapons_ViewAnimation(SHOTGUN_FIRE1);
pl.w_attack_next = 1.1f;
pl.w_idle_next = 2.5f;
}
void w_shotgun_reload(void)
{
player pl = (player)self;
#ifdef CLIENT
if (pl.a_ammo1 >= 8) {
return;
}
if (pl.a_ammo2 <= 0) {
return;
}
#else
if (pl.shotgun_mag >= 8) {
return;
}
if (pl.ammo_buckshot <= 0) {
return;
}
#endif
if (pl.a_ammo3 > SHOTTY_IDLE) {
return;
}
pl.a_ammo3 = SHOTTY_RELOAD_START;
pl.w_idle_next = 0.0f;
}
void w_shotgun_release(void)
{
player pl = (player)self;
/* auto-reload if need be */
if (pl.w_attack_next <= 0.0)
if (pl.a_ammo3 == SHOTTY_IDLE && pl.a_ammo1 == 0 && pl.a_ammo2 > 0) {
Weapons_Reload();
return;
}
if (pl.w_idle_next > 0.0) {
return;
}
if (pl.a_ammo3 == SHOTTY_IDLE) {
int r = floor(random(0,2));
switch (r) {
case 0:
Weapons_ViewAnimation(SHOTGUN_IDLE1);
break;
case 1:
Weapons_ViewAnimation(SHOTGUN_IDLE2);
break;
}
pl.w_idle_next = 15.0f;
} else if (pl.a_ammo3 == SHOTTY_RELOAD_START) {
Weapons_ViewAnimation(SHOTGUN_START_RELOAD);
pl.a_ammo3 = SHOTTY_RELOAD;
pl.w_idle_next = 0.65f;
} else if (pl.a_ammo3 == SHOTTY_RELOAD) {
Weapons_ViewAnimation(SHOTGUN_RELOAD);
#ifdef CLIENT
pl.a_ammo1++;
pl.a_ammo2--;
if (pl.a_ammo2 <= 0 || pl.a_ammo1 >= 8) {
pl.a_ammo3 = SHOTTY_RELOAD_END;
}
#else
pl.shotgun_mag++;
pl.ammo_buckshot--;
Weapons_UpdateAmmo(pl, pl.shotgun_mag, pl.ammo_buckshot, pl.a_ammo3);
sound(pl, CHAN_WEAPON, "weapons/reload3.wav", 1.0, ATTN_NORM);
if (pl.ammo_buckshot <= 0 || pl.shotgun_mag >= 8) {
pl.a_ammo3 = SHOTTY_RELOAD_END;
}
#endif
pl.w_idle_next = 0.5f;
} else if (pl.a_ammo3 == SHOTTY_RELOAD_END) {
Weapons_ViewAnimation(SHOTGUN_PUMP);
#ifdef SERVER
sound(pl, CHAN_WEAPON, "weapons/scock1.wav", 1.0, ATTN_NORM);
#endif
pl.a_ammo3 = SHOTTY_IDLE;
pl.w_idle_next = 10.0f;
pl.w_attack_next = 0.5f;
}
}
void w_shotgun_crosshair(void)
{
#ifdef CLIENT
static vector cross_pos;
cross_pos = (g_hudres / 2) + [-12,-12];
drawsubpic(cross_pos, [24,24], "sprites/crosshairs.spr_0.tga", [48/128,24/128], [0.1875, 0.1875], [1,1,1], 1, DRAWFLAG_NORMAL);
HUD_DrawAmmo1();
HUD_DrawAmmo2();
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
drawsubpic(aicon_pos, [24,24], "sprites/640hud7.spr_0.tga", [72/256,72/128], [24/256, 24/128], g_hud_color, pSeat->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
#endif
}
float w_shotgun_aimanim(void)
{
return self.flags & FL_CROUCHING ? ANIM_CR_AIMSHOTGUN : ANIM_AIMSHOTGUN;
}
void w_shotgun_hudpic(int s, vector pos, float a)
{
#ifdef CLIENT
if (s) {
drawsubpic(pos, [170,45], "sprites/640hud4.spr_0.tga", [0,180/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
} else {
drawsubpic(pos, [170,45], "sprites/640hud1.spr_0.tga", [0,180/256], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
}
#endif
}
weapon_t w_shotgun =
{
.name = "shotgun",
.id = ITEM_SHOTGUN,
.slot = 2,
.slot_pos = 1,
.draw = w_shotgun_draw,
.holster = w_shotgun_holster,
.primary = w_shotgun_primary,
.secondary = __NULL__,
.reload = w_shotgun_reload,
.release = w_shotgun_release,
.crosshair = __NULL__,
.precache = w_shotgun_precache,
.pickup = w_shotgun_pickup,
.updateammo = w_shotgun_updateammo,
.wmodel = w_shotgun_wmodel,
.pmodel = __NULL__,
.deathmsg = __NULL__,
.aimanim = __NULL__,
.hudpic = w_shotgun_hudpic
};
#ifdef SERVER
void weapon_shotgun(void) {
Weapons_InitItem(WEAPON_SHOTGUN);
}
#endif

153
src/shared/w_xs.qc Normal file
View File

@ -0,0 +1,153 @@
/*
* 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
{
XS_IDLE1,
XS_IDLE2,
XS_IDLE3,
XS_SPINUP,
XS_SPIN,
XS_FIRE1,
XS_FIRE2,
XS_HOLSTER,
XS_DRAW,
XS_RELOAD
};
void
w_xs_precache(void)
{
precache_sound("weapons/xs_moan1.wav");
precache_sound("weapons/xs_moan2.wav");
precache_sound("weapons/xs_moan3.wav");
precache_sound("weapons/xs_reload.wav");
precache_sound("weapons/xs_shot.wav");
precache_sound("weapons/xs_windup.wav");
precache_model("models/v_xs.mdl");
precache_model("models/w_xs.mdl");
}
void
w_xs_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, __NULL__, __NULL__, __NULL__);
#endif
}
string
w_xs_wmodel(void)
{
return "models/w_xs.mdl";
}
void
w_xs_draw(void)
{
Weapons_SetModel("models/v_xs.mdl");
Weapons_ViewAnimation(XS_DRAW);
}
void
w_xs_holster(void)
{
Weapons_ViewAnimation(XS_HOLSTER);
}
void
w_xs_primary(void)
{
/* TODO */
}
void
w_xs_secondary(void)
{
/* TODO Charge up, uses ammo similar to gauss */
}
void
w_xs_release(void)
{
}
void
w_xs_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
if (selected) {
drawsubpic(
pos,
[170,45],
"sprites/hud640_01.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
} else {
drawsubpic(
pos,
[170,45],
"sprites/hud640_01.spr_0.tga",
[0,45/256],
[170/256,45/256],
g_hud_color,
a,
DRAWFLAG_ADDITIVE
);
}
#endif
}
weapon_t w_xs =
{
.name = "xs",
.id = ITEM_XS,
.slot = 3,
.slot_pos = 0,
.draw = w_xs_draw,
.holster = w_xs_holster,
.primary = w_xs_primary,
.secondary = w_xs_secondary,
.reload = __NULL__,
.release = w_xs_release,
.crosshair = __NULL__,
.precache = w_xs_precache,
.pickup = __NULL__,
.updateammo = w_xs_updateammo,
.wmodel = w_xs_wmodel,
.pmodel = __NULL__,
.deathmsg = __NULL__,
.aimanim = __NULL__,
.hudpic = w_xs_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_xs(void)
{
Weapons_InitItem(WEAPON_XS);
}
#endif

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

@ -0,0 +1,34 @@
/*
* 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_HEATERPIPE,
WEAPON_BRADNAILER,
WEAPON_NAILGUN,
WEAPON_SHOTGUN,
WEAPON_CMLWBR,
WEAPON_XS,
WEAPON_SATCHEL
};
#define MAX_A_NAIL 250
#define MAX_A_BUCKSHOT 125
#define MAX_A_BOLT 50
#define MAX_A_XENCANDY 15
#define MAX_A_SATCHEL 5

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

@ -0,0 +1,27 @@
/*
* 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_heaterpipe,
w_bradnailer,
w_nailgun,
w_shotgun,
w_cmlwbr,
w_xs,
w_pipebomb
};