Initial commit.
This commit is contained in:
commit
6074c787b5
33 changed files with 4882 additions and 0 deletions
5
src/Makefile
Normal file
5
src/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
CC=fteqcc
|
||||
|
||||
all:
|
||||
cd client && $(MAKE)
|
||||
cd server && $(MAKE)
|
4
src/client/Makefile
Normal file
4
src/client/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
CC=fteqcc
|
||||
|
||||
all:
|
||||
$(CC) progs.src
|
83
src/client/defs.h
Normal file
83
src/client/defs.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2021 Marco Cawthorne <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.
|
||||
*/
|
||||
|
||||
#include "../../../valve/src/client/obituary.h"
|
||||
#include "../../../valve/src/client/particles.h"
|
||||
|
||||
var int autocvar_cl_autoweaponswitch = TRUE;
|
||||
|
||||
vector g_hud_color;
|
||||
vector g_hudmins;
|
||||
vector g_hudres;
|
||||
|
||||
var string g_hud1_spr;
|
||||
var string g_hud2_spr;
|
||||
var string g_hud3_spr;
|
||||
var string g_hud4_spr;
|
||||
var string g_hud5_spr;
|
||||
var string g_hud6_spr;
|
||||
var string g_hud7_spr;
|
||||
var string g_hudcb_spr;
|
||||
var string g_hudsg_spr;
|
||||
var string g_hudssg_spr;
|
||||
var string g_hudng_spr;
|
||||
var string g_hudsng_spr;
|
||||
var string g_hudgl_spr;
|
||||
var string g_hudrl_spr;
|
||||
var string g_hudlg_spr;
|
||||
var string g_cross_spr;
|
||||
var string g_laser_spr;
|
||||
|
||||
var string g_hudglammo;
|
||||
var string g_hudlgammo;
|
||||
var string g_hudngammo;
|
||||
var string g_hudrlammo;
|
||||
var string g_hudsgammo;
|
||||
var string g_hudsngammo;
|
||||
var string g_hudssgammo;
|
||||
|
||||
/* muzzleflash indices */
|
||||
var int MUZZLE_SMALL;
|
||||
var int MUZZLE_RIFLE;
|
||||
var int MUZZLE_WEIRD;
|
||||
|
||||
struct
|
||||
{
|
||||
/* hud.c */
|
||||
int m_iHealthOld;
|
||||
float m_flHealthAlpha;
|
||||
int m_iArmorOld;
|
||||
float m_flArmorAlpha;
|
||||
int m_iAmmo1Old;
|
||||
float m_flAmmo1Alpha;
|
||||
int m_iAmmo2Old;
|
||||
float m_flAmmo2Alpha;
|
||||
int m_iAmmo3Old;
|
||||
float m_flAmmo3Alpha;
|
||||
int m_iPickupWeapon;
|
||||
float m_flPickupAlpha;
|
||||
int m_iHUDWeaponSelected;
|
||||
float m_flHUDWeaponSelectTime;
|
||||
int m_iItemsOld;
|
||||
|
||||
float m_flDamageIndicator;
|
||||
} g_seatslocal[4], *pSeatLocal;
|
||||
|
||||
void HUD_DrawAmmo1(void);
|
||||
void HUD_DrawAmmo2(void);
|
||||
void HUD_DrawAmmo3(void);
|
||||
void HUD_DrawAmmoBar(vector pos, float val, float max, float a);
|
||||
void HUD_WeaponPickupNotify(int);
|
26
src/client/entities.qc
Normal file
26
src/client/entities.qc
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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 (0);
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
523
src/client/hud.qc
Normal file
523
src/client/hud.qc
Normal file
|
@ -0,0 +1,523 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2021 Marco Cawthorne <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 HUD_DrawWeaponSelect(void);
|
||||
|
||||
/* Use first frame for drawing (needs precache) */
|
||||
#define NUMSIZE_X 24/256
|
||||
#define NUMSIZE_Y 24/128
|
||||
#define HUD_ALPHA 0.5
|
||||
|
||||
float spr_hudnum[10] = {
|
||||
0 / 256,
|
||||
24 / 256,
|
||||
(24*2) / 256,
|
||||
(24*3) / 256,
|
||||
(24*4) / 256,
|
||||
(24*5) / 256,
|
||||
(24*6) / 256,
|
||||
(24*7) / 256,
|
||||
(24*8) / 256,
|
||||
(24*9) / 256
|
||||
};
|
||||
|
||||
/* pre-calculated sprite definitions */
|
||||
float spr_health[4] = {
|
||||
80 / 256, // pos x
|
||||
24 / 128, // pos u
|
||||
32 / 256, // size x
|
||||
32 / 128 // size y
|
||||
};
|
||||
|
||||
float spr_suit1[4] = {
|
||||
0 / 256, // pos x
|
||||
24 / 128, // pos u
|
||||
40 / 256, // size x
|
||||
40 / 128 // size y
|
||||
};
|
||||
|
||||
float spr_suit2[4] = {
|
||||
40 / 256, // pos x
|
||||
24 / 128, // pos u
|
||||
40 / 256, // size x
|
||||
40 / 128 // size y
|
||||
};
|
||||
|
||||
float spr_flash1[4] = {
|
||||
160 / 256, // pos x
|
||||
24 / 128, // pos u
|
||||
32 / 256, // size x
|
||||
32 / 128 // size y
|
||||
};
|
||||
|
||||
float spr_flash2[4] = {
|
||||
112 / 256, // pos x
|
||||
24 / 128, // pos u
|
||||
48 / 256, // size x
|
||||
32 / 128 // size y
|
||||
};
|
||||
|
||||
/* precaches */
|
||||
void
|
||||
HUD_Init(void)
|
||||
{
|
||||
g_cross_spr = spriteframe("sprites/crosshairs.spr", 0, 0.0f);
|
||||
g_laser_spr = spriteframe("sprites/laserdot.spr", 0, 0.0f);
|
||||
g_hud1_spr = spriteframe("sprites/640hud1.spr", 0, 0.0f);
|
||||
g_hud2_spr = spriteframe("sprites/640hud2.spr", 0, 0.0f);
|
||||
g_hud3_spr = spriteframe("sprites/640hud3.spr", 0, 0.0f);
|
||||
g_hud4_spr = spriteframe("sprites/640hud4.spr", 0, 0.0f);
|
||||
g_hud5_spr = spriteframe("sprites/640hud5.spr", 0, 0.0f);
|
||||
g_hud6_spr = spriteframe("sprites/640hud6.spr", 0, 0.0f);
|
||||
g_hud7_spr = spriteframe("sprites/640hud7.spr", 0, 0.0f);
|
||||
|
||||
g_hudcb_spr = spriteframe("sprites/hudcb.spr", 0, 0.0f);
|
||||
g_hudsg_spr = spriteframe("sprites/hudsg.spr", 0, 0.0f);
|
||||
g_hudssg_spr = spriteframe("sprites/hudssg.spr", 0, 0.0f);
|
||||
g_hudng_spr = spriteframe("sprites/hudng.spr", 0, 0.0f);
|
||||
g_hudsng_spr = spriteframe("sprites/hudsng.spr", 0, 0.0f);
|
||||
g_hudgl_spr = spriteframe("sprites/hudgl.spr", 0, 0.0f);
|
||||
g_hudrl_spr = spriteframe("sprites/hudrl.spr", 0, 0.0f);
|
||||
g_hudlg_spr = spriteframe("sprites/hudlg.spr", 0, 0.0f);
|
||||
|
||||
g_hudglammo = spriteframe("sprites/hudglammo.spr", 0, 0.0f);
|
||||
g_hudlgammo = spriteframe("sprites/hudlgammo.spr", 0, 0.0f);
|
||||
g_hudngammo = spriteframe("sprites/hudngammo.spr", 0, 0.0f);
|
||||
g_hudrlammo = spriteframe("sprites/hudrlammo.spr", 0, 0.0f);
|
||||
g_hudsgammo = spriteframe("sprites/hudsgammo.spr", 0, 0.0f);
|
||||
g_hudsngammo = spriteframe("sprites/hudsngammo.spr", 0, 0.0f);
|
||||
g_hudssgammo = spriteframe("sprites/hudssgammo.spr", 0, 0.0f);
|
||||
|
||||
HUD_AmmoNotify_Init();
|
||||
HUD_DamageNotify_Init();
|
||||
HUD_ItemNotify_Init();
|
||||
}
|
||||
|
||||
/* seperator for mainly ammo */
|
||||
void
|
||||
HUD_DrawSeperator(vector pos)
|
||||
{
|
||||
drawsubpic(pos,
|
||||
[2,24],
|
||||
g_hud7_spr,
|
||||
[240/256, 0],
|
||||
[2/256, 24/128],
|
||||
g_hud_color,
|
||||
HUD_ALPHA,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
|
||||
/* handle single/multiple digits */
|
||||
void
|
||||
HUD_DrawNumber(int iNumber, vector vecPos, float fAlpha, vector vColor)
|
||||
{
|
||||
drawsubpic(vecPos,
|
||||
[24,24],
|
||||
g_hud7_spr,
|
||||
[spr_hudnum[iNumber], 0],
|
||||
[NUMSIZE_X, NUMSIZE_Y],
|
||||
vColor,
|
||||
fAlpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
HUD_DrawNums(float fNumber, vector vecPos, float fAlpha, vector vColor)
|
||||
{
|
||||
int i = fNumber;
|
||||
if (i > 0) {
|
||||
while (i > 0) {
|
||||
HUD_DrawNumber((float)i % 10.0f, vecPos, fAlpha, vColor);
|
||||
i = i / 10;
|
||||
vecPos[0] -= 20;
|
||||
}
|
||||
} else {
|
||||
HUD_DrawNumber(0, vecPos, fAlpha, vColor);
|
||||
}
|
||||
}
|
||||
|
||||
/* health */
|
||||
void
|
||||
HUD_DrawHealth(void)
|
||||
{
|
||||
vector pos;
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
if (pl.health != pSeatLocal->m_iHealthOld) {
|
||||
pSeatLocal->m_flHealthAlpha = 1.0;
|
||||
}
|
||||
|
||||
if (pSeatLocal->m_flHealthAlpha >= HUD_ALPHA) {
|
||||
pSeatLocal->m_flHealthAlpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeatLocal->m_flHealthAlpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
pos = g_hudmins + [88, g_hudres[1] - 42];
|
||||
if (pl.health > 25) {
|
||||
drawsubpic(
|
||||
pos + [-72,-4],
|
||||
[32,32],
|
||||
g_hud7_spr,
|
||||
[spr_health[0], spr_health[1]],
|
||||
[spr_health[2], spr_health[3]],
|
||||
g_hud_color,
|
||||
pSeatLocal->m_flHealthAlpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
HUD_DrawNums(pl.health, pos, pSeatLocal->m_flHealthAlpha, g_hud_color);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos + [-72,-4],
|
||||
[32,32],
|
||||
g_hud7_spr,
|
||||
[spr_health[0], spr_health[1]],
|
||||
[spr_health[2], spr_health[3]],
|
||||
[1,0,0],
|
||||
pSeatLocal->m_flHealthAlpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
HUD_DrawNums(pl.health, pos, pSeatLocal->m_flHealthAlpha, [1,0,0]);
|
||||
}
|
||||
|
||||
pSeatLocal->m_iHealthOld = pl.health;
|
||||
}
|
||||
|
||||
/* armor/suit charge */
|
||||
void
|
||||
HUD_DrawArmor(void)
|
||||
{
|
||||
vector pos;
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
pos = g_hudmins + [198, g_hudres[1] - 42];
|
||||
|
||||
if (pl.armor != pSeatLocal->m_iArmorOld) {
|
||||
pSeatLocal->m_flArmorAlpha = 1.0;
|
||||
}
|
||||
|
||||
if (pSeatLocal->m_flArmorAlpha >= HUD_ALPHA) {
|
||||
pSeatLocal->m_flArmorAlpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeatLocal->m_flArmorAlpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
drawsubpic(
|
||||
pos + [-80,-9],
|
||||
[40,40],
|
||||
g_hud7_spr,
|
||||
[spr_suit2[0], spr_suit2[1]],
|
||||
[spr_suit2[2], spr_suit2[3]],
|
||||
g_hud_color,
|
||||
pSeatLocal->m_flArmorAlpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
|
||||
if (pl.armor > 0) {
|
||||
float perc = bound(0, (pl.armor / 100), 1.0);
|
||||
drawsubpic(
|
||||
pos + [-80,-9] + [0, 40 * (1.0-perc)],
|
||||
[40, 40 * perc],
|
||||
g_hud7_spr,
|
||||
[spr_suit1[0],spr_suit1[1] + spr_suit1[3] * (1.0-perc)],
|
||||
[spr_suit1[2], spr_suit1[3] * perc],
|
||||
g_hud_color,
|
||||
pSeatLocal->m_flArmorAlpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
|
||||
HUD_DrawNums(pl.armor, pos, pSeatLocal->m_flArmorAlpha, g_hud_color);
|
||||
pSeatLocal->m_iArmorOld = pl.armor;
|
||||
}
|
||||
|
||||
/* magazine/clip ammo */
|
||||
void
|
||||
HUD_DrawAmmo1(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
vector pos;
|
||||
|
||||
if (pl.a_ammo1 != pSeatLocal->m_iAmmo1Old) {
|
||||
pSeatLocal->m_flAmmo1Alpha = 1.0;
|
||||
pSeatLocal->m_iAmmo1Old = pl.a_ammo1;
|
||||
}
|
||||
|
||||
if (pSeatLocal->m_flAmmo1Alpha >= HUD_ALPHA) {
|
||||
pSeatLocal->m_flAmmo1Alpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeatLocal->m_flAmmo1Alpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
pos = g_hudmins + [g_hudres[0] - 152, g_hudres[1] - 42];
|
||||
HUD_DrawNums(pl.a_ammo1, pos, pSeatLocal->m_flAmmo1Alpha, g_hud_color);
|
||||
HUD_DrawSeperator(pos + [30,0]);
|
||||
}
|
||||
|
||||
/* leftover type ammo */
|
||||
void
|
||||
HUD_DrawAmmo2(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
vector pos;
|
||||
|
||||
if (pl.a_ammo2 != pSeatLocal->m_iAmmo2Old) {
|
||||
pSeatLocal->m_flAmmo2Alpha = 1.0;
|
||||
pSeatLocal->m_iAmmo2Old = pl.a_ammo2;
|
||||
}
|
||||
|
||||
if (pSeatLocal->m_flAmmo2Alpha >= HUD_ALPHA) {
|
||||
pSeatLocal->m_flAmmo2Alpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeatLocal->m_flAmmo2Alpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 42];
|
||||
HUD_DrawNums(pl.a_ammo2, pos, pSeatLocal->m_flAmmo2Alpha, g_hud_color);
|
||||
}
|
||||
|
||||
/* special ammo */
|
||||
void
|
||||
HUD_DrawAmmo3(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
vector pos;
|
||||
|
||||
if (pl.a_ammo3 != pSeatLocal->m_iAmmo3Old) {
|
||||
pSeatLocal->m_flAmmo3Alpha = 1.0;
|
||||
pSeatLocal->m_iAmmo3Old = pl.a_ammo3;
|
||||
}
|
||||
|
||||
if (pSeatLocal->m_flAmmo3Alpha >= HUD_ALPHA) {
|
||||
pSeatLocal->m_flAmmo3Alpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeatLocal->m_flAmmo3Alpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 74];
|
||||
HUD_DrawNums(pl.a_ammo3, pos, pSeatLocal->m_flAmmo3Alpha, g_hud_color);
|
||||
}
|
||||
|
||||
/* ammo bar */
|
||||
void
|
||||
HUD_DrawAmmoBar(vector pos, float val, float max, float a)
|
||||
{
|
||||
if (val <= 0)
|
||||
return;
|
||||
|
||||
float perc;
|
||||
perc = val / max;
|
||||
drawfill(pos + [10,0], [20,4], g_hud_color, a, DRAWFLAG_NORMAL);
|
||||
drawfill(pos + [10,0], [20 * perc,4], [0,1,0], a, DRAWFLAG_NORMAL);
|
||||
}
|
||||
|
||||
/* flashlight/torch indicator */
|
||||
void
|
||||
HUD_DrawFlashlight(void)
|
||||
{
|
||||
vector pos;
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
pos = g_hudmins + [g_hudres[0] - 48, 16];
|
||||
|
||||
/* both on, draw both sprites at full intensity */
|
||||
if (pl.gflags & GF_FLASHLIGHT) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[32,32],
|
||||
g_hud7_spr,
|
||||
[spr_flash1[0], spr_flash1[1]],
|
||||
[spr_flash1[2], spr_flash1[3]],
|
||||
g_hud_color,
|
||||
1.0f,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
|
||||
drawsubpic(
|
||||
pos,
|
||||
[48,32],
|
||||
g_hud7_spr,
|
||||
[spr_flash2[0], spr_flash2[1]],
|
||||
[spr_flash2[2], spr_flash2[3]],
|
||||
g_hud_color,
|
||||
1.0f,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[32,32],
|
||||
g_hud7_spr,
|
||||
[spr_flash1[0], spr_flash1[1]],
|
||||
[spr_flash1[2], spr_flash1[3]],
|
||||
g_hud_color,
|
||||
HUD_ALPHA,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* logo animation used during e3 1998 */
|
||||
void
|
||||
HUD_DrawLogo(void)
|
||||
{
|
||||
vector pos;
|
||||
static int f;
|
||||
static float frame_timer;
|
||||
|
||||
frame_timer -= clframetime;
|
||||
pos = [g_hudres[0] - 262, 48];
|
||||
|
||||
drawpic(
|
||||
pos,
|
||||
sprintf("sprites/640_logo.spr_%i.tga", f),
|
||||
[256,48],
|
||||
[1,1,1],
|
||||
1.0f,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
|
||||
if (frame_timer > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
frame_timer = 0.1f;
|
||||
|
||||
f++;
|
||||
if (f == 31) {
|
||||
f = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* weapon/ammo pickup notifications */
|
||||
void
|
||||
HUD_DrawNotify(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
vector pos;
|
||||
float a;
|
||||
|
||||
pos = g_hudmins + [g_hudres[0] - 192, g_hudres[1] - 128];
|
||||
|
||||
if (pSeatLocal->m_flPickupAlpha <= 0.0f) {
|
||||
pos[1] += 48;
|
||||
HUD_ItemNotify_Draw(pos);
|
||||
HUD_AmmoNotify_Draw(pos);
|
||||
return;
|
||||
}
|
||||
|
||||
a = bound(0.0, pSeatLocal->m_flPickupAlpha, 1.0);
|
||||
pos[1] += 48 * (1.0 - a);
|
||||
Weapons_HUDPic(pl, pSeatLocal->m_iPickupWeapon, 1, pos, a);
|
||||
HUD_ItemNotify_Draw(pos);
|
||||
HUD_AmmoNotify_Draw(pos);
|
||||
pSeatLocal->m_flPickupAlpha -= (clframetime * 0.5);
|
||||
}
|
||||
|
||||
void
|
||||
HUD_WeaponPickupNotify(int w)
|
||||
{
|
||||
pSeatLocal->m_iPickupWeapon = w;
|
||||
pSeatLocal->m_flPickupAlpha = 2.5f;
|
||||
}
|
||||
|
||||
void
|
||||
HUD_DrawDamageIndicator(void)
|
||||
{
|
||||
vector cross_pos;
|
||||
|
||||
if (pSeatLocal->m_flDamageIndicator <= 0.0)
|
||||
return;
|
||||
|
||||
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
|
||||
|
||||
/*drawsubpic(
|
||||
cross_pos,
|
||||
[24,24],
|
||||
g_cross_spr,
|
||||
[0.0, 72/128],
|
||||
[0.1875, 0.1875],
|
||||
[1,1,1] * pSeatLocal->m_flDamageIndicator,
|
||||
1.0f,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);*/
|
||||
|
||||
pSeatLocal->m_flDamageIndicator -= clframetime;
|
||||
}
|
||||
|
||||
/* main entry */
|
||||
void
|
||||
HUD_Draw(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
#ifndef TFC
|
||||
g_hud_color = autocvar_con_color * (1 / 255);
|
||||
#endif
|
||||
|
||||
/* little point in not drawing these, even if you don't have a suit */
|
||||
Weapons_DrawCrosshair(pl);
|
||||
HUD_DrawDamageIndicator();
|
||||
HUD_DrawWeaponSelect();
|
||||
Obituary_Draw();
|
||||
Textmenu_Draw();
|
||||
|
||||
if (!(pl.g_items & ITEM_SUIT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
HUD_DamageNotify_Draw();
|
||||
HUD_DrawHealth();
|
||||
HUD_DrawArmor();
|
||||
HUD_DrawFlashlight();
|
||||
HUD_DrawNotify();
|
||||
Damage_Draw();
|
||||
}
|
||||
|
||||
string g_specmodes[] = {
|
||||
"Free Camera",
|
||||
"Third Person",
|
||||
"First Person"
|
||||
};
|
||||
|
||||
/* specatator main entry */
|
||||
void
|
||||
HUD_DrawSpectator(void)
|
||||
{
|
||||
Textmenu_Draw();
|
||||
|
||||
NSClientSpectator spec = (NSClientSpectator)pSeat->m_ePlayer;
|
||||
|
||||
drawfont = Font_GetID(FONT_20);
|
||||
vector vecPos = [0.0f, 0.0f, 0.0f];
|
||||
string strText = __NULL__;
|
||||
float palpha = 1.0f;
|
||||
|
||||
if (spec.spec_mode == SPECMODE_FREE) {
|
||||
palpha = 0.5f;
|
||||
}
|
||||
|
||||
strText = sprintf("Tracking: %s", getplayerkeyvalue(spec.spec_ent - 1, "name"));
|
||||
vecPos[0] = g_hudmins[0] + (g_hudres[0] / 2) - (stringwidth(strText, TRUE, [20,20]) / 2);
|
||||
vecPos[1] = g_hudmins[1] + g_hudres[1] - 60;
|
||||
drawstring(vecPos, strText, [20,20], [1,1,1], palpha, DRAWFLAG_ADDITIVE);
|
||||
|
||||
strText = sprintf("Mode: %s", g_specmodes[spec.spec_mode]);
|
||||
vecPos[0] = g_hudmins[0] + (g_hudres[0] / 2) - (stringwidth(strText, TRUE, [20,20]) / 2);
|
||||
vecPos[1] = g_hudmins[1] + g_hudres[1] - 40;
|
||||
drawstring(vecPos, strText, [20,20], [1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
|
||||
}
|
92
src/client/hud_ammonotify.qc
Normal file
92
src/client/hud_ammonotify.qc
Normal file
|
@ -0,0 +1,92 @@
|
|||
|
||||
#ifndef GEARBOX
|
||||
#define AMMO_COUNT 12
|
||||
#else
|
||||
#define AMMO_COUNT 17
|
||||
#endif
|
||||
|
||||
string g_ammo_spr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float alpha;
|
||||
int count;
|
||||
} ammonote_t;
|
||||
ammonote_t g_ammonotify[AMMO_COUNT];
|
||||
|
||||
vector g_ammotype[AMMO_COUNT] = {
|
||||
[0/256, 72/128], // pistol
|
||||
[72/256, 72/128], // shell
|
||||
[120/256, 72/128], // rocket
|
||||
[0/256, 96/128], // uranium
|
||||
};
|
||||
|
||||
void
|
||||
HUD_AmmoNotify_Init(void)
|
||||
{
|
||||
g_ammo_spr = spriteframe("sprites/640hud7.spr", 0, 0.0f);
|
||||
}
|
||||
|
||||
void
|
||||
HUD_AmmoNotify_Draw(__inout vector pos)
|
||||
{
|
||||
pos[0] = g_hudmins[0] + g_hudres[0] - 40;
|
||||
|
||||
for (int i = 0; i < AMMO_COUNT; i++) {
|
||||
vector srcpos;
|
||||
float a;
|
||||
|
||||
/* make sure we skip any faded entries, and also null them */
|
||||
if (g_ammonotify[i].alpha <= 0.0f) {
|
||||
g_ammonotify[i].count = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* let's get the src img pos for our type */
|
||||
srcpos = g_ammotype[i];
|
||||
a = bound(0, g_ammonotify[i].alpha, 1.0);
|
||||
|
||||
/* we'll use the alpha to control the offset so it gently glides down when fading out */
|
||||
pos -= [0, 32 * a]; /* go up a notch */
|
||||
drawsubpic(pos,
|
||||
[24,24],
|
||||
g_ammo_spr,
|
||||
srcpos,
|
||||
[24/256, 24/128],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
|
||||
drawfont = Font_GetID(FONT_20);
|
||||
string txt = sprintf("%i", g_ammonotify[i].count);
|
||||
float offs = stringwidth(txt, FALSE, [20,20]);
|
||||
drawstring(pos + [-offs - 8,4], sprintf("%i", g_ammonotify[i].count), [20,20], g_hud_color, a, DRAWFLAG_ADDITIVE);
|
||||
|
||||
g_ammonotify[i].alpha -= (clframetime * 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HUD_AmmoNotify_Insert(int type, int count)
|
||||
{
|
||||
if (count <= 0)
|
||||
return;
|
||||
|
||||
if (type == 7 && count < 8) // hornet hack!
|
||||
return;
|
||||
|
||||
g_ammonotify[type].count += count;
|
||||
g_ammonotify[type].alpha = 2.5f;
|
||||
|
||||
}
|
||||
|
||||
/* called whenever we should check for pickup updates */
|
||||
void
|
||||
HUD_AmmoNotify_Check(player pl)
|
||||
{
|
||||
HUD_AmmoNotify_Insert(0, pl.ammo_shells - pl.ammo_shells_net);
|
||||
HUD_AmmoNotify_Insert(1, pl.ammo_nails - pl.ammo_nails_net);
|
||||
HUD_AmmoNotify_Insert(2, pl.ammo_rockets - pl.ammo_rockets_net);
|
||||
HUD_AmmoNotify_Insert(3, pl.ammo_cells - pl.ammo_cells_net);
|
||||
}
|
258
src/client/hud_weaponselect.qc
Normal file
258
src/client/hud_weaponselect.qc
Normal file
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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.
|
||||
*/
|
||||
|
||||
vector g_vecHUDNums[8] =
|
||||
{
|
||||
[168 / 256, 72 / 128],
|
||||
[188 / 256, 72 / 128],
|
||||
[208 / 256, 72 / 128],
|
||||
[168 / 256, 92 / 128],
|
||||
[188 / 256, 92 / 128],
|
||||
[208 / 256, 92 / 128],
|
||||
|
||||
[188 / 256, 92 / 128],
|
||||
[208 / 256, 92 / 128]
|
||||
};
|
||||
|
||||
bool
|
||||
HUD_DrawWeaponSelect_CanSwitch(player pl)
|
||||
{
|
||||
if (!pl.activeweapon)
|
||||
return false;
|
||||
|
||||
for (int i = 1; i < g_weapons.length; i++) {
|
||||
if (pl.g_items & g_weapons[i].id && g_weapons[i].isempty(pl) == false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
HUD_DrawWeaponSelect_Forward(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
if (HUD_DrawWeaponSelect_CanSwitch(pl) == false) {
|
||||
pSeat->m_flHUDWeaponSelectTime = time + 3;
|
||||
pSeat->m_iHUDWeaponSelected = pl.activeweapon;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pSeat->m_flHUDWeaponSelectTime < time) {
|
||||
pSeat->m_iHUDWeaponSelected = pl.activeweapon;
|
||||
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
|
||||
} else {
|
||||
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
|
||||
pSeat->m_iHUDWeaponSelected--;
|
||||
if (pSeat->m_iHUDWeaponSelected <= 0) {
|
||||
pSeat->m_iHUDWeaponSelected = g_weapons.length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
pSeat->m_flHUDWeaponSelectTime = time + 3;
|
||||
|
||||
if not (pl.g_items & g_weapons[pSeat->m_iHUDWeaponSelected].id)
|
||||
HUD_DrawWeaponSelect_Forward();
|
||||
else if (g_weapons[pSeat->m_iHUDWeaponSelected].isempty)
|
||||
if (g_weapons[pSeat->m_iHUDWeaponSelected].isempty(pl))
|
||||
HUD_DrawWeaponSelect_Forward();
|
||||
}
|
||||
|
||||
void
|
||||
HUD_DrawWeaponSelect_Back(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
if (HUD_DrawWeaponSelect_CanSwitch(pl) == false) {
|
||||
pSeat->m_flHUDWeaponSelectTime = time + 3;
|
||||
pSeat->m_iHUDWeaponSelected = pl.activeweapon;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pSeat->m_flHUDWeaponSelectTime < time) {
|
||||
pSeat->m_iHUDWeaponSelected = pl.activeweapon;
|
||||
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
|
||||
} else {
|
||||
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
|
||||
pSeat->m_iHUDWeaponSelected++;
|
||||
if (pSeat->m_iHUDWeaponSelected >= g_weapons.length) {
|
||||
pSeat->m_iHUDWeaponSelected = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pSeat->m_flHUDWeaponSelectTime = time + 3;
|
||||
|
||||
if not (pl.g_items & g_weapons[pSeat->m_iHUDWeaponSelected].id)
|
||||
HUD_DrawWeaponSelect_Back();
|
||||
else if (g_weapons[pSeat->m_iHUDWeaponSelected].isempty)
|
||||
if (g_weapons[pSeat->m_iHUDWeaponSelected].isempty(pl))
|
||||
HUD_DrawWeaponSelect_Back();
|
||||
}
|
||||
|
||||
void
|
||||
HUD_DrawWeaponSelect_Trigger(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
if (pl.activeweapon != pSeat->m_iHUDWeaponSelected)
|
||||
sendevent("PlayerSwitchWeapon", "i", pSeat->m_iHUDWeaponSelected);
|
||||
|
||||
pl.activeweapon = pSeat->m_iHUDWeaponSelected;
|
||||
|
||||
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_select.wav", 0.5f, ATTN_NONE);
|
||||
pSeat->m_iHUDWeaponSelected = pSeat->m_flHUDWeaponSelectTime = 0;
|
||||
}
|
||||
|
||||
void
|
||||
HUD_DrawWeaponSelect_Last(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
if (pl.g_items & g_weapons[pSeat->m_iOldWeapon].id) {
|
||||
pl.activeweapon = pSeat->m_iOldWeapon;
|
||||
sendevent("PlayerSwitchWeapon", "i", pSeat->m_iOldWeapon);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HUD_DrawWeaponSelect_Num(vector vecPos, float fValue)
|
||||
{
|
||||
drawsubpic(vecPos, [20,20], g_hud7_spr, g_vecHUDNums[fValue], [20/256, 20/128], g_hud_color, 1, DRAWFLAG_ADDITIVE);
|
||||
}
|
||||
|
||||
int
|
||||
HUD_InSlotPos(int slot, int pos)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
for (int i = 1; i < g_weapons.length; i++) {
|
||||
if (g_weapons[i].slot == slot && g_weapons[i].slot_pos == pos) {
|
||||
if (pl.g_items & g_weapons[i].id) {
|
||||
return i;
|
||||
} else {
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
void
|
||||
HUD_SlotSelect(int slot)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
int curslot = g_weapons[pSeat->m_iHUDWeaponSelected].slot;
|
||||
int i;
|
||||
|
||||
if (g_textmenu != "") {
|
||||
Textmenu_Input(slot);
|
||||
return;
|
||||
}
|
||||
|
||||
/* hack to see if we have ANY weapons at all. */
|
||||
if (!pl.activeweapon) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pSeat->m_flHUDWeaponSelectTime < time) {
|
||||
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
|
||||
} else {
|
||||
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
|
||||
}
|
||||
|
||||
/* weren't in that slot? select the first one then */
|
||||
if (curslot != slot) {
|
||||
for (i = 1; i < g_weapons.length; i++) {
|
||||
if (g_weapons[i].slot == slot && pl.g_items & g_weapons[i].id) {
|
||||
pSeat->m_iHUDWeaponSelected = i;
|
||||
pSeat->m_flHUDWeaponSelectTime = time + 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int first = -1;
|
||||
for (i = 1; i < g_weapons.length; i++) {
|
||||
if (g_weapons[i].slot == slot && pl.g_items & g_weapons[i].id) {
|
||||
if (i < pSeat->m_iHUDWeaponSelected && first == -1) {
|
||||
first = i;
|
||||
} else if (i > pSeat->m_iHUDWeaponSelected) {
|
||||
first = -1;
|
||||
pSeat->m_iHUDWeaponSelected = i;
|
||||
pSeat->m_flHUDWeaponSelectTime = time + 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (first > 0) {
|
||||
pSeat->m_iHUDWeaponSelected = first;
|
||||
pSeat->m_flHUDWeaponSelectTime = time + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HUD_DrawWeaponSelect(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
if (!pl.activeweapon) {
|
||||
return;
|
||||
}
|
||||
if (pSeat->m_flHUDWeaponSelectTime < time) {
|
||||
if (pSeat->m_iHUDWeaponSelected) {
|
||||
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudoff.wav", 0.5, ATTN_NONE);
|
||||
pSeat->m_iHUDWeaponSelected = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
vector vecPos = g_hudmins + [16,16];
|
||||
|
||||
int b;
|
||||
int wantslot = g_weapons[pSeat->m_iHUDWeaponSelected].slot;
|
||||
int wantpos = g_weapons[pSeat->m_iHUDWeaponSelected].slot_pos;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int slot_selected = 0;
|
||||
vecPos[1] = g_hudmins[1] + 16;
|
||||
HUD_DrawWeaponSelect_Num(vecPos, i);
|
||||
vecPos[1] += 20;
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (i == wantslot) {
|
||||
slot_selected = TRUE;
|
||||
if (x == wantpos) {
|
||||
// Selected Sprite
|
||||
Weapons_HUDPic(pl, pSeat->m_iHUDWeaponSelected, 1, vecPos, 1.0f);
|
||||
drawsubpic(vecPos, [170,45], g_hud3_spr,
|
||||
[0,180/256], [170/256,45/256], g_hud_color, 1, DRAWFLAG_ADDITIVE);
|
||||
vecPos[1] += 50;
|
||||
} else if ((b=HUD_InSlotPos(i, x)) != -1) {
|
||||
// Unselected Sprite
|
||||
Weapons_HUDPic(pl, b, 0, vecPos, 1.0f);
|
||||
vecPos[1] += 50;
|
||||
}
|
||||
} else if (HUD_InSlotPos(i, x) != -1) {
|
||||
HUD_DrawWeaponSelect_Num(vecPos, 5);
|
||||
vecPos[1] += 25;
|
||||
}
|
||||
}
|
||||
|
||||
if (slot_selected == TRUE) {
|
||||
vecPos[0] += 175;
|
||||
} else {
|
||||
vecPos[0] += 25;
|
||||
}
|
||||
}
|
||||
}
|
45
src/client/progs.src
Normal file
45
src/client/progs.src
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma target fte_5768
|
||||
//#pragma flag enable assumeint
|
||||
#pragma progs_dat "../../csprogs.dat"
|
||||
|
||||
#define CSQC
|
||||
#define CLIENT
|
||||
#define VALVE
|
||||
#define CLASSIC_VGUI
|
||||
|
||||
#includelist
|
||||
../../../src/shared/fteextensions.qc
|
||||
../../../src/shared/defs.h
|
||||
defs.h
|
||||
../../../src/client/defs.h
|
||||
|
||||
../../../src/vgui/include.src
|
||||
|
||||
../../../src/gs-entbase/client.src
|
||||
../../../src/gs-entbase/shared.src
|
||||
../shared/include.src
|
||||
|
||||
../../../valve/src/client/draw.qc
|
||||
|
||||
../../../valve/src/client/damage.qc
|
||||
../../../valve/src/client/init.qc
|
||||
../../../valve/src/client/flashlight.qc
|
||||
entities.qc
|
||||
../../../valve/src/client/cmds.qc
|
||||
../../../valve/src/client/game_event.qc
|
||||
../../../valve/src/client/camera.qc
|
||||
../../../valve/src/client/viewmodel.qc
|
||||
../../../valve/src/client/view.qc
|
||||
../../../valve/src/client/obituary.qc
|
||||
../../../valve/src/client/hud_itemnotify.qc
|
||||
../../../valve/src/client/hud_dmgnotify.qc
|
||||
hud_ammonotify.qc
|
||||
hud.qc
|
||||
hud_weaponselect.qc
|
||||
../../../valve/src/client/scoreboard.qc
|
||||
../../../valve/src/client/modelevent.qc
|
||||
|
||||
../../../src/client/include.src
|
||||
../../../valve/src/client/vgui_motd.qc
|
||||
../../../src/shared/include.src
|
||||
#endlist
|
2
src/progs.src
Normal file
2
src/progs.src
Normal file
|
@ -0,0 +1,2 @@
|
|||
#pragma sourcefile client/progs.src
|
||||
#pragma sourcefile server/progs.src
|
4
src/server/Makefile
Normal file
4
src/server/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
CC=fteqcc
|
||||
|
||||
all:
|
||||
$(CC) progs.src
|
238
src/server/ammo.qc
Normal file
238
src/server/ammo.qc
Normal file
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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:NSRenderableEntity
|
||||
{
|
||||
void(void) item_ammo;
|
||||
|
||||
virtual void(void) Spawned;
|
||||
virtual void(void) Respawn;
|
||||
virtual void(entity) Touch;
|
||||
};
|
||||
|
||||
void
|
||||
item_ammo::Touch(entity eToucher)
|
||||
{
|
||||
if not (eToucher.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
player pl = (player)eToucher;
|
||||
Sound_Play(eToucher, CHAN_ITEM, "ammo.pickup");
|
||||
Weapons_RefreshAmmo(pl);
|
||||
Logging_Pickup(eToucher, this, __NULL__);
|
||||
|
||||
if (real_owner || cvar("sv_playerslots") == 1) {
|
||||
Destroy();
|
||||
} else {
|
||||
Disappear();
|
||||
ScheduleThink(Respawn, 30.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
item_ammo::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_TOSS);
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
SetModel(GetSpawnModel());
|
||||
SetSize([-16,-16,0],[16,16,16]);
|
||||
|
||||
ReleaseThink();
|
||||
|
||||
if (real_owner && time > 30.0f)
|
||||
Sound_Play(this, CHAN_ITEM, "ammo.respawn");
|
||||
|
||||
droptofloor();
|
||||
}
|
||||
|
||||
void
|
||||
item_ammo::Spawned(void)
|
||||
{
|
||||
super::Spawned();
|
||||
|
||||
Sound_Precache("ammo.pickup");
|
||||
Sound_Precache("ammo.respawn");
|
||||
precache_model(model);
|
||||
}
|
||||
|
||||
void
|
||||
item_ammo::item_ammo(void)
|
||||
{
|
||||
m_oldModel = model;
|
||||
}
|
||||
|
||||
/*QUAKED item_shells (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Ammo for the .357 Magnum Revolver.
|
||||
A single ammo_shells will provide 6 bullets.
|
||||
|
||||
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
|
||||
model="models/w_357ammobox.mdl"
|
||||
*/
|
||||
|
||||
class
|
||||
item_shells:item_ammo
|
||||
{
|
||||
void(void) item_shells;
|
||||
virtual void(entity) Touch;
|
||||
};
|
||||
|
||||
void
|
||||
item_shells::item_shells(void)
|
||||
{
|
||||
model = "models/w_shotbox_big.mdl";
|
||||
}
|
||||
|
||||
void
|
||||
item_shells::Touch(entity eToucher)
|
||||
{
|
||||
if not (eToucher.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (eToucher.classname == "player") {
|
||||
player pl = (player)eToucher;
|
||||
if (pl.ammo_shells < MAX_A_SHELLS) {
|
||||
pl.ammo_shells = bound(0, pl.ammo_shells + 6, MAX_A_SHELLS);
|
||||
item_ammo::Touch(eToucher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED item_spikes (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Ammo for the .357 Magnum Revolver.
|
||||
A single ammo_nails will provide 6 bullets.
|
||||
|
||||
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
|
||||
model="models/w_357ammobox.mdl"
|
||||
*/
|
||||
|
||||
class
|
||||
item_spikes:item_ammo
|
||||
{
|
||||
void(void) item_spikes;
|
||||
virtual void(entity) Touch;
|
||||
};
|
||||
|
||||
void
|
||||
item_spikes::item_spikes(void)
|
||||
{
|
||||
model = "models/b_nail1.mdl";
|
||||
}
|
||||
|
||||
void
|
||||
item_spikes::Touch(entity eToucher)
|
||||
{
|
||||
if not (eToucher.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (eToucher.classname == "player") {
|
||||
player pl = (player)eToucher;
|
||||
if (pl.ammo_nails < MAX_A_NAILS) {
|
||||
pl.ammo_nails = bound(0, pl.ammo_nails + 6, MAX_A_NAILS);
|
||||
item_ammo::Touch(eToucher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*QUAKED item_rockets (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Ammo for the .357 Magnum Revolver.
|
||||
A single ammo_rockets will provide 6 bullets.
|
||||
|
||||
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
|
||||
model="models/w_357ammobox.mdl"
|
||||
*/
|
||||
|
||||
class item_rockets:item_ammo
|
||||
{
|
||||
void(void) item_rockets;
|
||||
virtual void(entity) Touch;
|
||||
};
|
||||
|
||||
void
|
||||
item_rockets::item_rockets(void)
|
||||
{
|
||||
model = "models/w_rpgammo.mdl";
|
||||
}
|
||||
|
||||
void
|
||||
item_rockets::Touch(entity eToucher)
|
||||
{
|
||||
if not (eToucher.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (eToucher.classname == "player") {
|
||||
player pl = (player)eToucher;
|
||||
if (pl.ammo_rockets < MAX_A_ROCKETS) {
|
||||
pl.ammo_rockets = bound(0, pl.ammo_rockets + 6, MAX_A_ROCKETS);
|
||||
item_ammo::Touch(eToucher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*QUAKED item_cells (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Ammo for the .357 Magnum Revolver.
|
||||
A single ammo_cells will provide 6 bullets.
|
||||
|
||||
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
|
||||
model="models/w_357ammobox.mdl"
|
||||
*/
|
||||
|
||||
class item_cells:item_ammo
|
||||
{
|
||||
void(void) item_cells;
|
||||
virtual void(entity) Touch;
|
||||
};
|
||||
|
||||
void
|
||||
item_cells::item_cells(void)
|
||||
{
|
||||
model = "models/w_battery.mdl";
|
||||
}
|
||||
|
||||
void
|
||||
item_cells::Touch(entity eToucher)
|
||||
{
|
||||
if not (eToucher.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (eToucher.classname == "player") {
|
||||
player pl = (player)eToucher;
|
||||
if (pl.ammo_cells < MAX_A_CELLS) {
|
||||
pl.ammo_cells = bound(0, pl.ammo_cells + 6, MAX_A_CELLS);
|
||||
item_ammo::Touch(eToucher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
133
src/server/gamerules.qc
Normal file
133
src/server/gamerules.qc
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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.
|
||||
*/
|
||||
|
||||
bool
|
||||
HLGameRules::IsMultiplayer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
HLGameRules::LevelDecodeParms(NSClientPlayer pp)
|
||||
{
|
||||
player pl = (player)pp;
|
||||
g_landmarkpos[0] = parm1;
|
||||
g_landmarkpos[1] = parm2;
|
||||
g_landmarkpos[2] = parm3;
|
||||
|
||||
pl.SetAngles([parm4, parm5, parm6]);
|
||||
pl.SetVelocity([parm7, parm8, parm9]);
|
||||
|
||||
/* game specific stuff */
|
||||
pl.g_items = parm10;
|
||||
pl.activeweapon = parm11;
|
||||
pl.flags = parm64;
|
||||
|
||||
pl.ammo_shells = parm12;
|
||||
pl.ammo_nails = parm13;
|
||||
pl.ammo_rockets = parm14;
|
||||
pl.ammo_cells = parm15;
|
||||
|
||||
/* reset bounds */
|
||||
if (pl.HasFlags(FL_CROUCHING)) {
|
||||
pl.SetSize(VEC_CHULL_MIN, VEC_CHULL_MAX);
|
||||
} else {
|
||||
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HLGameRules::LevelChangeParms(NSClientPlayer 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.GetFlags();
|
||||
parm10 = pl.g_items;
|
||||
parm11 = pl.activeweapon;
|
||||
parm12 = pl.ammo_shells;
|
||||
parm13 = pl.ammo_nails;
|
||||
parm14 = pl.ammo_rockets;
|
||||
parm15 = pl.ammo_cells;
|
||||
}
|
||||
|
||||
void
|
||||
HLGameRules::LevelNewParms(void)
|
||||
{
|
||||
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
|
||||
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
|
||||
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
|
||||
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
|
||||
parm29 = parm30 = 0;
|
||||
parm64 = FL_CLIENT;
|
||||
}
|
||||
|
||||
/* we check what fields have changed over the course of the frame and network
|
||||
* only the ones that have actually changed */
|
||||
void
|
||||
HLGameRules::PlayerPostFrame(NSClientPlayer pl)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
HLGameRules::PlayerConnect(NSClientPlayer pl)
|
||||
{
|
||||
if (Plugin_PlayerConnect(pl) == FALSE)
|
||||
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname));
|
||||
}
|
||||
|
||||
void
|
||||
HLGameRules::PlayerDisconnect(NSClientPlayer pl)
|
||||
{
|
||||
if (Plugin_PlayerDisconnect(pl) == FALSE)
|
||||
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
|
||||
}
|
||||
|
||||
void
|
||||
HLGameRules::PlayerKill(NSClientPlayer pl)
|
||||
{
|
||||
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
|
||||
}
|
||||
|
||||
void
|
||||
TriggerFlashlight(NSClient target)
|
||||
{
|
||||
entity oldself = self;
|
||||
self = target;
|
||||
Flashlight_Toggle();
|
||||
self = oldself;
|
||||
}
|
||||
|
||||
bool
|
||||
HLGameRules::ImpulseCommand(NSClient bp, float num)
|
||||
{
|
||||
switch (num) {
|
||||
case 100:
|
||||
TriggerFlashlight(bp);
|
||||
break;
|
||||
default:
|
||||
return super::ImpulseCommand(bp, num);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
283
src/server/gamerules_multiplayer.qc
Normal file
283
src/server/gamerules_multiplayer.qc
Normal file
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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.
|
||||
*/
|
||||
|
||||
const string mp_teamlist_fallback = "robo;hgrunt";
|
||||
var string autocvar_mp_teamlist = mp_teamlist_fallback;
|
||||
|
||||
bool
|
||||
HLMultiplayerRules::IsMultiplayer(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
HLMultiplayerRules::PlayerRequestRespawn(NSClientPlayer bp)
|
||||
{
|
||||
if (bp.TimeSinceDeath() > 0.5f) {
|
||||
bp.ScheduleThink(PutClientInServer, 0.0f);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
HLMultiplayerRules::IsTeamplay(void)
|
||||
{
|
||||
return cvar("mp_teamplay") == 1 ? true : false;
|
||||
}
|
||||
|
||||
void
|
||||
HLMultiplayerRules::InitPostEnts(void)
|
||||
{
|
||||
MOTD_LoadDefault();
|
||||
|
||||
if (IsTeamplay() == true) {
|
||||
int c;
|
||||
|
||||
/* get the segments from our cvar */
|
||||
m_strTeamList = autocvar_mp_teamlist;
|
||||
c = tokenizebyseparator(m_strTeamList, ";");
|
||||
|
||||
/* if we've got less than 2 teams, use the fallback... */
|
||||
if (c < 2) {
|
||||
m_strTeamList = mp_teamlist_fallback;
|
||||
c = tokenizebyseparator(m_strTeamList, ";");
|
||||
}
|
||||
|
||||
forceinfokey(world, "teams", itos(c));
|
||||
|
||||
/* initialize all dem teams */
|
||||
for (int i = 0; i < c; i++) {
|
||||
forceinfokey(world, sprintf("team_%i", i+1i), argv(i));
|
||||
forceinfokey(world, sprintf("teamscore_%i", i+1i), "0");
|
||||
}
|
||||
} else {
|
||||
forceinfokey(world, "teams", "0");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HLMultiplayerRules::FrameStart(void)
|
||||
{
|
||||
if (cvar("timelimit"))
|
||||
if (time >= (cvar("timelimit") * 60)) {
|
||||
IntermissionStart();
|
||||
}
|
||||
|
||||
IntermissionCycle();
|
||||
}
|
||||
|
||||
void
|
||||
HLMultiplayerRules::CheckRules(void)
|
||||
{
|
||||
/* last person who killed somebody has hit the limit */
|
||||
if (cvar("fraglimit"))
|
||||
if (g_dmg_eAttacker.frags >= cvar("fraglimit"))
|
||||
IntermissionStart();
|
||||
}
|
||||
|
||||
void
|
||||
HLMultiplayerRules::PlayerDeath(NSClientPlayer pl)
|
||||
{
|
||||
/* obituary networking */
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EV_OBITUARY);
|
||||
WriteString(MSG_MULTICAST, (g_dmg_eAttacker.netname) ? g_dmg_eAttacker.netname : g_dmg_eAttacker.classname);
|
||||
WriteString(MSG_MULTICAST, pl.netname);
|
||||
WriteByte(MSG_MULTICAST, g_dmg_iWeapon);
|
||||
WriteByte(MSG_MULTICAST, 0);
|
||||
msg_entity = world;
|
||||
multicast([0,0,0], MULTICAST_ALL);
|
||||
|
||||
Plugin_PlayerObituary(g_dmg_eAttacker, g_dmg_eTarget, g_dmg_iWeapon, g_dmg_iHitBody, g_dmg_iDamage);
|
||||
|
||||
/* death-counter */
|
||||
pl.deaths++;
|
||||
pl.SetInfoKey("*deaths", ftos(pl.deaths));
|
||||
|
||||
/* update score-counter */
|
||||
if (pl.flags & FL_CLIENT || pl.flags & FL_MONSTER)
|
||||
if (g_dmg_eAttacker.flags & FL_CLIENT) {
|
||||
if (pl == g_dmg_eAttacker)
|
||||
g_dmg_eAttacker.frags--;
|
||||
else
|
||||
g_dmg_eAttacker.frags++;
|
||||
}
|
||||
|
||||
/* either gib, or make a corpse */
|
||||
if (pl.health < -50) {
|
||||
FX_GibHuman(pl.origin, vectoangles(pl.origin - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
|
||||
} else {
|
||||
FX_Corpse_Spawn((player)pl, ANIM_DIESIMPLE);
|
||||
}
|
||||
|
||||
/* now let's make the real client invisible */
|
||||
pl.Death();
|
||||
pl.SetTakedamage(DAMAGE_NO);
|
||||
pl.gflags &= ~GF_FLASHLIGHT;
|
||||
pl.gflags &= ~GF_EGONBEAM;
|
||||
|
||||
Sound_Play(pl, CHAN_AUTO, "player.die");
|
||||
|
||||
/* force respawn */
|
||||
pl.ScheduleThink(PutClientInServer, 4.0f);
|
||||
|
||||
/* have we gone over the fraglimit? */
|
||||
CheckRules();
|
||||
}
|
||||
|
||||
void
|
||||
HLMultiplayerRules::PlayerSpawn(NSClientPlayer pp)
|
||||
{
|
||||
player pl = (player)pp;
|
||||
string playerModel;
|
||||
/* this is where the mods want to deviate */
|
||||
entity spot;
|
||||
|
||||
pl.classname = "player";
|
||||
pl.SetMaxHealth(100);
|
||||
pl.SetHealth(100);
|
||||
pl.SetTakedamage(DAMAGE_YES);
|
||||
pl.SetSolid(SOLID_SLIDEBOX);
|
||||
pl.SetMovetype(MOVETYPE_WALK);
|
||||
pl.AddFlags(FL_CLIENT);
|
||||
pl.viewzoom = 1.0;
|
||||
|
||||
/* player model selection */
|
||||
if (IsTeamplay() == true) {
|
||||
int teamCount = tokenizebyseparator(m_strTeamList, ";");
|
||||
int playerTeam = (int)pl.GetTeam();
|
||||
|
||||
/* not part of a team? pick one of the ones we have */
|
||||
/* TODO: this should sort us into the lowest team */
|
||||
if (playerTeam == 0) {
|
||||
playerTeam = 1i + (int)floor(random(0, (float)teamCount)); /* teams start at 1 after all */
|
||||
pl.SetTeam(playerTeam);
|
||||
}
|
||||
|
||||
/* assign our player model */
|
||||
playerModel = sprintf("models/player/%s/%s.mdl", argv(playerTeam - 1i), argv(playerTeam - 1i));
|
||||
} else {
|
||||
/* interpret the 'model' InfoKey */
|
||||
playerModel = pl.GetInfoKey("model");
|
||||
|
||||
if (playerModel) {
|
||||
playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
|
||||
}
|
||||
}
|
||||
|
||||
/* fallback is always models/player.mdl for Half-Life */
|
||||
if not (whichpack(playerModel)) {
|
||||
playerModel = "models/player.mdl";
|
||||
}
|
||||
|
||||
pl.SetModel(playerModel);
|
||||
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
pl.ClearVelocity();
|
||||
pl.gravity = __NULL__;
|
||||
pl.SetFrame(1);
|
||||
pl.SendFlags = UPDATE_ALL;
|
||||
pl.iBleeds = TRUE;
|
||||
pl.SetInfoKey("*spec", "0");
|
||||
pl.SetInfoKey("*dead", "0");
|
||||
pl.SetInfoKey("*deaths", ftos(pl.deaths));
|
||||
|
||||
LevelNewParms();
|
||||
LevelDecodeParms(pl);
|
||||
|
||||
#if defined (VALVE) || defined (GEARBOX)
|
||||
pl.g_items = ITEM_CROWBAR | ITEM_SHOTGUN | ITEM_SUIT;
|
||||
pl.activeweapon = WEAPON_SHOTGUN;
|
||||
pl.ammo_shells = 25;
|
||||
#endif
|
||||
|
||||
spot = Spawn_SelectRandom("info_player_deathmatch");
|
||||
pl.SetOrigin(spot.origin);
|
||||
pl.SetAngles(spot.angles);
|
||||
Weapons_RefreshAmmo(pl);
|
||||
|
||||
Client_FixAngle(pl, pl.angles);
|
||||
}
|
||||
|
||||
bool
|
||||
HLMultiplayerRules::ConsoleCommand(NSClientPlayer pp, string cmd)
|
||||
{
|
||||
tokenize(cmd);
|
||||
|
||||
switch (argv(0)) {
|
||||
case "bot_add":
|
||||
bot pete = (bot)Bot_AddQuick();
|
||||
Bot_RandomColormap(pete);
|
||||
searchhandle pm = search_begin("models/player/*/*.mdl", TRUE, TRUE);
|
||||
int r = floor(random(0, search_getsize(pm)));
|
||||
string mdl = substring(search_getfilename(pm, r), 0, -5);
|
||||
tokenizebyseparator(mdl, "/");
|
||||
forceinfokey(pete, "model", argv(2));
|
||||
search_end(pm);
|
||||
break;
|
||||
case "jumptest":
|
||||
makevectors(pp.v_angle);
|
||||
traceline(pp.origin + pp.view_ofs, pp.origin + pp.view_ofs + v_forward * 1024, FALSE, pp);
|
||||
pp.velocity = Route_GetJumpVelocity(pp.origin, trace_endpos, pp.gravity);
|
||||
break;
|
||||
default:
|
||||
return (false);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
bool
|
||||
HLMultiplayerRules::MonstersSpawn(void)
|
||||
{
|
||||
return (autocvar(mp_allowmonsters, 0)) ? true : false;
|
||||
}
|
||||
|
||||
void
|
||||
HLMultiplayerRules::HLMultiplayerRules(void)
|
||||
{
|
||||
/* these lines do nothing but tell the server to register those cvars */
|
||||
autocvar(timelimit, 15, "Timelimit for multiplayer rounds");
|
||||
autocvar(fraglimit, 15, "Points limit for multiplayer rounds");
|
||||
}
|
||||
|
||||
void
|
||||
CSEv_HLDM_Chooseteam_s(string teamName)
|
||||
{
|
||||
HLGameRules rules = (HLGameRules)g_grMode;
|
||||
player pl = (player)self;
|
||||
|
||||
if (!teamName)
|
||||
return;
|
||||
if (rules.IsMultiplayer() == false)
|
||||
return;
|
||||
if (rules.IsTeamplay() == false)
|
||||
return;
|
||||
if (pl.IsDead() == true)
|
||||
return;
|
||||
|
||||
HLMultiplayerRules mprules = (HLMultiplayerRules)rules;
|
||||
int c = tokenizebyseparator(mprules.m_strTeamList, ";");
|
||||
|
||||
for (int i = 0; i < c; i++) {
|
||||
if (argv(i) == teamName) {
|
||||
pl.SetTeam((float)i + 1);
|
||||
Damage_Apply(pl, pl, 100, 0, DMG_SKIP_ARMOR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
133
src/server/gamerules_singleplayer.qc
Normal file
133
src/server/gamerules_singleplayer.qc
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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.
|
||||
*/
|
||||
|
||||
bool
|
||||
HLSingleplayerRules::IsMultiplayer(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
HLSingleplayerRules::PlayerDeath(NSClientPlayer pl)
|
||||
{
|
||||
pl.movetype = MOVETYPE_NONE;
|
||||
pl.solid = SOLID_NOT;
|
||||
pl.takedamage = DAMAGE_NO;
|
||||
pl.gflags &= ~GF_FLASHLIGHT;
|
||||
pl.armor = pl.activeweapon = pl.g_items = pl.weapon = 0;
|
||||
pl.health = 0;
|
||||
Sound_Play(pl, CHAN_AUTO, "player.die");
|
||||
|
||||
if (cvar("coop") == 1) {
|
||||
pl.think = PutClientInServer;
|
||||
pl.nextthink = time + 4.0f;
|
||||
}
|
||||
|
||||
if (pl.health < -50) {
|
||||
FX_GibHuman(pl.origin, vectoangles(pl.origin - g_dmg_eAttacker.origin), g_dmg_iDamage * 2.0f);
|
||||
}
|
||||
|
||||
/* Let's handle corpses on the clientside */
|
||||
entity corpse = spawn();
|
||||
setorigin(corpse, pl.origin + [0,0,32]);
|
||||
setmodel(corpse, pl.model);
|
||||
setsize(corpse, VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
corpse.movetype = MOVETYPE_TOSS;
|
||||
corpse.solid = SOLID_TRIGGER;
|
||||
corpse.modelindex = pl.modelindex;
|
||||
corpse.frame = ANIM_DIESIMPLE;
|
||||
corpse.angles = pl.angles;
|
||||
corpse.velocity = pl.velocity;
|
||||
}
|
||||
|
||||
void
|
||||
HLSingleplayerRules::PlayerSpawn(NSClientPlayer pl)
|
||||
{
|
||||
pl.classname = "player";
|
||||
pl.health = pl.max_health = 100;
|
||||
pl.takedamage = DAMAGE_YES;
|
||||
pl.SetSolid(SOLID_SLIDEBOX);
|
||||
pl.SetMovetype(MOVETYPE_WALK);
|
||||
pl.flags = FL_CLIENT;
|
||||
pl.viewzoom = 1.0;
|
||||
pl.model = "models/player.mdl";
|
||||
|
||||
|
||||
if (cvar("coop") == 1) {
|
||||
string mymodel = infokey(pl, "model");
|
||||
if (mymodel) {
|
||||
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
|
||||
if (whichpack(mymodel)) {
|
||||
pl.model = mymodel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setmodel(pl, pl.model);
|
||||
|
||||
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
pl.velocity = [0,0,0];
|
||||
pl.gravity = __NULL__;
|
||||
pl.frame = 1;
|
||||
//pl.SendEntity = Player_SendEntity;
|
||||
pl.SendFlags = UPDATE_ALL;
|
||||
pl.customphysics = Empty;
|
||||
pl.iBleeds = TRUE;
|
||||
forceinfokey(pl, "*spec", "0");
|
||||
forceinfokey(pl, "*deaths", ftos(pl.deaths));
|
||||
|
||||
/* this is where the mods want to deviate */
|
||||
entity spot;
|
||||
|
||||
if (startspot != "") {
|
||||
dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", startspot));
|
||||
LevelDecodeParms(pl);
|
||||
setorigin(pl, Landmark_GetSpot());
|
||||
} else {
|
||||
LevelNewParms();
|
||||
spot = find(world, ::classname, "info_player_start");
|
||||
setorigin(pl, spot.origin);
|
||||
pl.angles = spot.angles;
|
||||
}
|
||||
|
||||
Weapons_RefreshAmmo(pl);
|
||||
Client_FixAngle(pl, pl.angles);
|
||||
}
|
||||
|
||||
bool
|
||||
HLSingleplayerRules::ImpulseCommand(NSClient bp, float num)
|
||||
{
|
||||
switch (num) {
|
||||
case 101:
|
||||
player pl = (player)bp;
|
||||
pl.health = 100;
|
||||
pl.armor = 100;
|
||||
pl.g_items |= ITEM_SUIT;
|
||||
Weapons_AddItem(pl, WEAPON_CROWBAR, -1);
|
||||
Weapons_AddItem(pl, WEAPON_SHOTGUN, -1);
|
||||
Weapons_AddItem(pl, WEAPON_SUPERSHOTGUN, -1);
|
||||
Weapons_AddItem(pl, WEAPON_NAILGUN, -1);
|
||||
Weapons_AddItem(pl, WEAPON_SUPERNAILGUN, -1);
|
||||
Weapons_AddItem(pl, WEAPON_GRENADELAUNCHER, -1);
|
||||
Weapons_AddItem(pl, WEAPON_ROCKETLAUNCHER, -1);
|
||||
Weapons_AddItem(pl, WEAPON_LIGHTNING, -1);
|
||||
break;
|
||||
default:
|
||||
return super::ImpulseCommand(bp, num);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
196
src/server/item_armor.qc
Normal file
196
src/server/item_armor.qc
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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_armor:NSRenderableEntity
|
||||
{
|
||||
void(void) item_armor;
|
||||
|
||||
virtual void(void) Spawned;
|
||||
virtual void(void) Respawn;
|
||||
virtual void(entity) Touch;
|
||||
};
|
||||
|
||||
void
|
||||
item_armor::Touch(entity eToucher)
|
||||
{
|
||||
if not (eToucher.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
player pl = (player)eToucher;
|
||||
Sound_Play(eToucher, CHAN_ITEM, "armor.pickup");
|
||||
Weapons_RefreshAmmo(pl);
|
||||
Logging_Pickup(eToucher, this, __NULL__);
|
||||
|
||||
if (real_owner || cvar("sv_playerslots") == 1) {
|
||||
Destroy();
|
||||
} else {
|
||||
Disappear();
|
||||
ScheduleThink(Respawn, 30.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
item_armor::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_TOSS);
|
||||
SetOrigin(GetSpawnOrigin());
|
||||
SetModel(GetSpawnModel());
|
||||
SetSize([-16,-16,0],[16,16,16]);
|
||||
|
||||
ReleaseThink();
|
||||
|
||||
if (real_owner && time > 30.0f)
|
||||
Sound_Play(this, CHAN_ITEM, "armor.respawn");
|
||||
|
||||
droptofloor();
|
||||
}
|
||||
|
||||
void
|
||||
item_armor::Spawned(void)
|
||||
{
|
||||
super::Spawned();
|
||||
|
||||
Sound_Precache("armor.pickup");
|
||||
Sound_Precache("armor.respawn");
|
||||
precache_model(model);
|
||||
}
|
||||
|
||||
void
|
||||
item_armor::item_armor(void)
|
||||
{
|
||||
m_oldModel = model;
|
||||
}
|
||||
|
||||
/*QUAKED item_armor1 (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
DEATHMATCH CLASSIC (1999) ENTITY
|
||||
|
||||
Armor item that gives you 100 armor points.
|
||||
It is the green armor.
|
||||
|
||||
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
|
||||
model="models/armour_g.mdl"
|
||||
*/
|
||||
|
||||
class
|
||||
item_armor1:item_armor
|
||||
{
|
||||
void(void) item_armor1;
|
||||
virtual void(entity) Touch;
|
||||
};
|
||||
|
||||
void
|
||||
item_armor1::item_armor1(void)
|
||||
{
|
||||
model = "models/armour_g.mdl";
|
||||
}
|
||||
|
||||
void
|
||||
item_armor1::Touch(entity eToucher)
|
||||
{
|
||||
if not (eToucher.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (eToucher.classname == "player") {
|
||||
player pl = (player)eToucher;
|
||||
if (pl.armor < 100) {
|
||||
pl.armor = 100;
|
||||
item_armor::Touch(eToucher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*QUAKED item_armor2 (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
DEATHMATCH CLASSIC (1999) ENTITY
|
||||
|
||||
Armor item that gives you 150 armor points.
|
||||
It is the yellow armor.
|
||||
|
||||
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
|
||||
model="models/armour_y.mdl"
|
||||
*/
|
||||
|
||||
class
|
||||
item_armor2:item_armor
|
||||
{
|
||||
void(void) item_armor2;
|
||||
virtual void(entity) Touch;
|
||||
};
|
||||
|
||||
void
|
||||
item_armor2::item_armor2(void)
|
||||
{
|
||||
model = "models/armour_y.mdl";
|
||||
}
|
||||
|
||||
void
|
||||
item_armor2::Touch(entity eToucher)
|
||||
{
|
||||
if not (eToucher.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (eToucher.classname == "player") {
|
||||
player pl = (player)eToucher;
|
||||
if (pl.armor < 150) {
|
||||
pl.armor = 150;
|
||||
item_armor::Touch(eToucher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*QUAKED item_armor3 (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
DEATHMATCH CLASSIC (1999) ENTITY
|
||||
|
||||
Armor item that gives you 200 armor points.
|
||||
It is the green armor.
|
||||
|
||||
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
|
||||
model="models/armour_r.mdl"
|
||||
*/
|
||||
|
||||
class item_armor3:item_armor
|
||||
{
|
||||
void(void) item_armor3;
|
||||
virtual void(entity) Touch;
|
||||
};
|
||||
|
||||
void
|
||||
item_armor3::item_armor3(void)
|
||||
{
|
||||
model = "models/armour_r.mdl";
|
||||
}
|
||||
|
||||
void
|
||||
item_armor3::Touch(entity eToucher)
|
||||
{
|
||||
if not (eToucher.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (eToucher.classname == "player") {
|
||||
player pl = (player)eToucher;
|
||||
if (pl.armor < 200) {
|
||||
pl.armor = 200;
|
||||
item_armor::Touch(eToucher);
|
||||
}
|
||||
}
|
||||
}
|
92
src/server/item_weaponbox.qc
Normal file
92
src/server/item_weaponbox.qc
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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_weaponbox:NSRenderableEntity
|
||||
{
|
||||
|
||||
int weapon_items;
|
||||
|
||||
void(void) item_weaponbox;
|
||||
|
||||
virtual void(void) Spawned;
|
||||
virtual void(entity) Touch;
|
||||
virtual void(player) setup;
|
||||
};
|
||||
|
||||
void
|
||||
item_weaponbox::Touch(entity eToucher)
|
||||
{
|
||||
if (eToucher.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
player pl = (player)eToucher;
|
||||
Logging_Pickup(eToucher, this, __NULL__);
|
||||
sound(pl, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM);
|
||||
|
||||
pl.ammo_shells += ammo_shells;
|
||||
pl.ammo_nails += ammo_nails;
|
||||
pl.ammo_rockets += ammo_rockets;
|
||||
pl.ammo_cells += ammo_cells;
|
||||
|
||||
/* cull */
|
||||
pl.ammo_shells = min(pl.ammo_shells, MAX_A_SHELLS);
|
||||
pl.ammo_nails = min(pl.ammo_nails, MAX_A_NAILS);
|
||||
pl.ammo_rockets = min(pl.ammo_rockets, MAX_A_ROCKETS);
|
||||
pl.ammo_cells = min(pl.ammo_cells, MAX_A_CELLS);
|
||||
|
||||
pl.g_items |= weapon_items;
|
||||
Weapons_RefreshAmmo(pl);
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void
|
||||
item_weaponbox::setup(player pl)
|
||||
{
|
||||
/* TODO: Should the magazine bits be transferred too? */
|
||||
ammo_shells = pl. ammo_shells;
|
||||
ammo_nails = pl. ammo_nails;
|
||||
ammo_rockets = pl.ammo_rockets;
|
||||
ammo_cells = pl.ammo_cells;
|
||||
weapon_items = pl.g_items;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
item_weaponbox::Spawned(void)
|
||||
{
|
||||
super::Spawned();
|
||||
|
||||
SetModel("models/w_weaponbox.mdl");
|
||||
SetSize([-16,-16,0], [16,16,16]);
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_TOSS);
|
||||
}
|
||||
|
||||
void
|
||||
item_weaponbox::item_weaponbox(void)
|
||||
{
|
||||
botinfo = BOTINFO_AMMO;
|
||||
}
|
||||
|
||||
void
|
||||
weaponbox_spawn(player spawner)
|
||||
{
|
||||
item_weaponbox weaponbox = spawn(item_weaponbox);
|
||||
weaponbox.SetOrigin(spawner.origin);
|
||||
weaponbox.setup(spawner);
|
||||
}
|
87
src/server/progs.src
Normal file
87
src/server/progs.src
Normal file
|
@ -0,0 +1,87 @@
|
|||
#pragma target fte_5768
|
||||
//#pragma flag enable assumeint
|
||||
#pragma progs_dat "../../progs.dat"
|
||||
|
||||
#define QWSSQC
|
||||
#define SERVER
|
||||
#define VALVE
|
||||
|
||||
#includelist
|
||||
../../../src/shared/fteextensions.qc
|
||||
../../../src/shared/defs.h
|
||||
../../../src/server/defs.h
|
||||
../../../src/botlib/botinfo.h
|
||||
|
||||
../../../src/gs-entbase/server.src
|
||||
../../../src/gs-entbase/shared.src
|
||||
|
||||
../../../valve/src/server/defs.h
|
||||
|
||||
../shared/include.src
|
||||
|
||||
../../../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/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
|
||||
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
|
||||
ammo.qc
|
||||
item_armor.qc
|
||||
|
||||
../../../src/botlib/include.src
|
||||
|
||||
gamerules.qc
|
||||
gamerules_singleplayer.qc
|
||||
gamerules_multiplayer.qc
|
||||
../../../valve/src/server/server.qc
|
||||
../../../valve/src/server/damage.qc
|
||||
../../../valve/src/server/flashlight.qc
|
||||
../../../valve/src/server/modelevent.qc
|
||||
|
||||
../../../valve/src/server/spawn.qc
|
||||
|
||||
../../../src/server/include.src
|
||||
../../../src/shared/include.src
|
||||
#endlist
|
61
src/server/weaponbox.qc
Normal file
61
src/server/weaponbox.qc
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2022 Marco Cawthorne <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 weaponbox (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Ammo container. Used to delvier more than 1 singular ammo type, as well as
|
||||
more precise control.
|
||||
|
||||
-------- KEYS --------
|
||||
"targetname" : Name
|
||||
"uranium" : Amount of Uranium (Egon, Gauss) ammo to give
|
||||
"357" : Amount of 357 Python ammo to give
|
||||
"9mm" : Amount of 9mm Handgun/MP5 ammo to give
|
||||
"ARgrenades" : Amount of MP5 grenades to give
|
||||
"bolts" : Amount of Crossbow bolts
|
||||
"buckshot" : Amount of Shotgun ammo to give
|
||||
"rockets" : Amount of RPG ammo to give
|
||||
"556" : (Oppossing Force only) Amount for the SAW Machine Gun
|
||||
"762" : (Oppossing Force only) Amount for the Sniper Rifle
|
||||
"spore" : (Oppossing Force only) Amount for the Spore Launcher
|
||||
|
||||
|
||||
-------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
|
||||
model="models/models/w_weaponbox.mdl"
|
||||
*/
|
||||
|
||||
class
|
||||
weaponbox:item_weaponbox
|
||||
{
|
||||
void(void) weaponbox;
|
||||
|
||||
virtual void(string, string) SpawnKey;
|
||||
};
|
||||
|
||||
void
|
||||
weaponbox::SpawnKey(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
weaponbox::weaponbox(void)
|
||||
{
|
||||
// do nothing
|
||||
}
|
32
src/shared/include.src
Normal file
32
src/shared/include.src
Normal file
|
@ -0,0 +1,32 @@
|
|||
#includelist
|
||||
../../../valve/src/shared/entities.h
|
||||
../../../valve/src/shared/events.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/fx_blood.qc
|
||||
../../../valve/src/shared/fx_gaussbeam.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_corpse.qc
|
||||
../../../valve/src/shared/fx_impact.qc
|
||||
|
||||
items.h
|
||||
weapons.h
|
||||
w_crowbar.qc
|
||||
w_shotgun.qc
|
||||
w_supershotgun.qc
|
||||
w_nailgun.qc
|
||||
w_supernailgun.qc
|
||||
w_grenadelauncher.qc
|
||||
w_rocketlauncher.qc
|
||||
w_lightning.qc
|
||||
weapons.qc
|
||||
../../../valve/src/shared/weapon_common.qc
|
||||
#endlist
|
51
src/shared/items.h
Normal file
51
src/shared/items.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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 0x00000001i
|
||||
#define ITEM_SHOTGUN 0x00000002i
|
||||
#define ITEM_SUPERSHOTGUN 0x00000004i
|
||||
#define ITEM_NAILGUN 0x00000008i
|
||||
#define ITEM_SUPERNAILGUN 0x00000010i
|
||||
#define ITEM_GRENADELAUNCHER 0x00000020i
|
||||
#define ITEM_ROCKETLAUNCHER 0x00000040i
|
||||
#define ITEM_LIGHTNING 0x00000080i
|
||||
|
||||
#define ITEM_UNUSED10 0x00000100i
|
||||
#define ITEM_UNUSED11 0x00000200i
|
||||
#define ITEM_UNUSED12 0x00000400i
|
||||
#define ITEM_UNUSED13 0x00000800i
|
||||
#define ITEM_UNUSED14 0x00001000i
|
||||
#define ITEM_UNUSED15 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
|
503
src/shared/player.qc
Normal file
503
src/shared/player.qc
Normal file
|
@ -0,0 +1,503 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2021 Marco Cawthorne <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.
|
||||
*/
|
||||
|
||||
#ifdef CLIENT
|
||||
/* Here's a list of bone names that we are aware of on HL player models.
|
||||
Usually we'd use skeletalobjects to share the same skeleton/anim with
|
||||
another model - but because FTEQW does not support that for HLMDL we
|
||||
are forced to manually position the bones of our attachnment
|
||||
by iterating over them and manually setting their position in 3D-space.
|
||||
*/
|
||||
string g_pbones[] =
|
||||
{
|
||||
"Bip01",
|
||||
"Bip01 Footsteps",
|
||||
"Bip01 Pelvis",
|
||||
"Bip01 L Leg",
|
||||
"Bip01 L Leg1",
|
||||
"Bip01 L Foot",
|
||||
"Bip01 L Toe0",
|
||||
"Bip01 L Toe01",
|
||||
"Bip01 L Toe02",
|
||||
"Dummy16",
|
||||
"Bip01 R Leg",
|
||||
"Bip01 R Leg1",
|
||||
"Bip01 R Foot",
|
||||
"Bip01 R Toe0",
|
||||
"Bip01 R Toe01",
|
||||
"Bip01 R Toe02",
|
||||
"Dummy11",
|
||||
"Bip01 Spine",
|
||||
"Bip01 Spine1",
|
||||
"Bip01 Spine2",
|
||||
"Bip01 Spine3",
|
||||
"Bip01 Neck",
|
||||
"Bip01 Head",
|
||||
"Dummy21",
|
||||
"Dummy08",
|
||||
"Bone02",
|
||||
"Bone03",
|
||||
"Bone04",
|
||||
"Dummy05",
|
||||
"Bone09",
|
||||
"Bone10",
|
||||
"Dummy04",
|
||||
"Bone05",
|
||||
"Bone06",
|
||||
"Dummy03",
|
||||
"Bone07",
|
||||
"Bone08",
|
||||
"Dummy09",
|
||||
"Bone11",
|
||||
"Bone12",
|
||||
"Dummy10",
|
||||
"Bone13",
|
||||
"Bone14",
|
||||
"Bone15",
|
||||
"Bip01 L Arm",
|
||||
"Bip01 L Arm1",
|
||||
"Bip01 L Arm2",
|
||||
"Bip01 L Hand",
|
||||
"Bip01 L Finger0",
|
||||
"Bip01 L Finger01",
|
||||
"Bip01 L Finger02",
|
||||
"Dummy06",
|
||||
"Bip01 L Finger1",
|
||||
"Bip01 L Finger11",
|
||||
"Bip01 L Finger12",
|
||||
"Dummy07",
|
||||
"Bip01 R Arm",
|
||||
"Bip01 R Arm1",
|
||||
"Bip01 R Arm2",
|
||||
"Bip01 R Hand",
|
||||
"Bip01 R Finger0",
|
||||
"Bip01 R Finger01",
|
||||
"Bip01 R Finger02",
|
||||
"Dummy01",
|
||||
"Bip01 R Finger1",
|
||||
"Bip01 R Finger11",
|
||||
"Bip01 R Finger12",
|
||||
"Dummy02",
|
||||
"Box02",
|
||||
"Bone08",
|
||||
"Bone15"
|
||||
};
|
||||
#endif
|
||||
|
||||
/* all custom SendFlags bits we can possibly send */
|
||||
enumflags
|
||||
{
|
||||
PLAYER_TOPFRAME = PLAYER_CUSTOMFIELDSTART,
|
||||
PLAYER_BOTTOMFRAME,
|
||||
PLAYER_AMMO1,
|
||||
PLAYER_AMMO2,
|
||||
PLAYER_AMMO3,
|
||||
PLAYER_UNUSED5,
|
||||
PLAYER_UNUSED6,
|
||||
PLAYER_UNUSED7
|
||||
};
|
||||
|
||||
noref .float ammo_shells;
|
||||
noref .float ammo_nails;
|
||||
noref .float ammo_rockets;
|
||||
noref .float ammo_cells;
|
||||
|
||||
class player:NSClientPlayer
|
||||
{
|
||||
void(void) player;
|
||||
|
||||
/* animation */
|
||||
PREDICTED_INT(anim_top)
|
||||
PREDICTED_FLOAT(anim_top_time)
|
||||
PREDICTED_FLOAT(anim_top_delay)
|
||||
PREDICTED_INT(anim_bottom)
|
||||
PREDICTED_FLOAT(anim_bottom_time)
|
||||
|
||||
/* ammo 1 */
|
||||
PREDICTED_FLOAT_N(ammo_shells)
|
||||
PREDICTED_FLOAT_N(ammo_nails)
|
||||
PREDICTED_FLOAT_N(ammo_rockets)
|
||||
PREDICTED_FLOAT_N(ammo_cells)
|
||||
|
||||
virtual void Physics_Jump(void);
|
||||
virtual void UpdatePlayerAnimation(float);
|
||||
|
||||
#ifdef CLIENT
|
||||
////virtual void(void) draw;
|
||||
//virtual float() predraw;
|
||||
//virtual void(void) postdraw;
|
||||
virtual void UpdatePlayerAttachments(bool);
|
||||
virtual void ReceiveEntity(float,float);
|
||||
virtual void PredictPreFrame(void);
|
||||
virtual void PredictPostFrame(void);
|
||||
virtual void UpdateAliveCam(void);
|
||||
#else
|
||||
virtual void EvaluateEntity(void);
|
||||
virtual float SendEntity(entity, float);
|
||||
virtual void Save(float);
|
||||
virtual void Restore(string,string);
|
||||
#endif
|
||||
};
|
||||
|
||||
void Animation_PlayerUpdate(player);
|
||||
void Animation_TimerUpdate(player, float);
|
||||
|
||||
void
|
||||
player::UpdatePlayerAnimation(float timelength)
|
||||
{
|
||||
/* calculate our skeletal progression */
|
||||
Animation_PlayerUpdate(this);
|
||||
/* advance animation timers */
|
||||
Animation_TimerUpdate(this, timelength);
|
||||
}
|
||||
|
||||
#ifdef CLIENT
|
||||
void Camera_RunPosBob(vector angles, __inout vector camera_pos);
|
||||
void Camera_StrafeRoll(__inout vector camera_angle);
|
||||
void Shake_Update(NSClientPlayer);
|
||||
|
||||
void
|
||||
player::UpdateAliveCam(void)
|
||||
{
|
||||
vector cam_pos = GetEyePos();
|
||||
Camera_RunPosBob(view_angles, cam_pos);
|
||||
|
||||
g_view.SetCameraOrigin(cam_pos);
|
||||
Camera_StrafeRoll(view_angles);
|
||||
g_view.SetCameraAngle(view_angles);
|
||||
|
||||
if (vehicle) {
|
||||
NSVehicle veh = (NSVehicle)vehicle;
|
||||
|
||||
if (veh.UpdateView)
|
||||
veh.UpdateView();
|
||||
} else if (health) {
|
||||
if (autocvar_pm_thirdPerson == TRUE) {
|
||||
makevectors(view_angles);
|
||||
vector vStart = [pSeat->m_vecPredictedOrigin[0], pSeat->m_vecPredictedOrigin[1], pSeat->m_vecPredictedOrigin[2] + 16] + (v_right * 4);
|
||||
vector vEnd = vStart + (v_forward * -48) + [0,0,16] + (v_right * 4);
|
||||
traceline(vStart, vEnd, FALSE, this);
|
||||
g_view.SetCameraOrigin(trace_endpos + (v_forward * 5));
|
||||
}
|
||||
}
|
||||
|
||||
Shake_Update(this);
|
||||
g_view.AddPunchAngle(punchangle);
|
||||
}
|
||||
|
||||
.string oldmodel;
|
||||
string Weapons_GetPlayermodel(player, int);
|
||||
|
||||
void
|
||||
player::UpdatePlayerAttachments(bool visible)
|
||||
{
|
||||
/* draw the flashlight */
|
||||
if (gflags & GF_FLASHLIGHT) {
|
||||
vector src;
|
||||
vector ang;
|
||||
|
||||
if (entnum != player_localentnum) {
|
||||
src = origin + view_ofs;
|
||||
ang = v_angle;
|
||||
} else {
|
||||
src = pSeat->m_vecPredictedOrigin + [0,0,-8];
|
||||
ang = view_angles;
|
||||
}
|
||||
|
||||
makevectors(ang);
|
||||
traceline(src, src + (v_forward * 8096), MOVE_NORMAL, this);
|
||||
|
||||
if (serverkeyfloat("*bspversion") == BSPVER_HL) {
|
||||
dynamiclight_add(trace_endpos + (v_forward * -2), 128, [1,1,1]);
|
||||
} else {
|
||||
float p = dynamiclight_add(src, 512, [1,1,1], 0, "textures/flashlight");
|
||||
dynamiclight_set(p, LFIELD_ANGLES, ang);
|
||||
dynamiclight_set(p, LFIELD_FLAGS, 3);
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: this needs to be incorporated and simplified, now that we can handle it all in-class */
|
||||
if (!visible)
|
||||
return;
|
||||
|
||||
/* what's the current weapon model supposed to be anyway? */
|
||||
p_model.oldmodel = Weapons_GetPlayermodel(this, activeweapon);
|
||||
|
||||
/* we changed weapons, update skeletonindex */
|
||||
if (p_model.model != p_model.oldmodel) {
|
||||
/* free memory */
|
||||
if (p_model.skeletonindex)
|
||||
skel_delete(p_model.skeletonindex);
|
||||
|
||||
/* set the new model and mark us updated */
|
||||
setmodel(p_model, p_model.oldmodel);
|
||||
p_model.model = p_model.oldmodel;
|
||||
|
||||
/* set the new skeletonindex */
|
||||
p_model.skeletonindex = skel_create(p_model.modelindex);
|
||||
|
||||
/* hack this thing in here FIXME: this should be done when popping in/out of a pvs */
|
||||
if (autocvar(cl_himodels, 1, "Use high-quality thisayer models over lower-definition ones"))
|
||||
setcustomskin(this, "", "geomset 0 2\n");
|
||||
else
|
||||
setcustomskin(this, "", "geomset 0 1\n");
|
||||
}
|
||||
|
||||
/* follow thisayer at all times */
|
||||
setorigin(p_model, origin);
|
||||
p_model.angles = angles;
|
||||
skel_build(p_model.skeletonindex, p_model, p_model.modelindex,0, 0, -1);
|
||||
|
||||
/* we have to loop through all valid bones of the weapon model and match them
|
||||
* to the thisayer one */
|
||||
for (float i = 0; i < g_pbones.length; i++) {
|
||||
vector bpos;
|
||||
float pbone = gettagindex(this, g_pbones[i]);
|
||||
float wbone = gettagindex(p_model, g_pbones[i]);
|
||||
|
||||
/* if the bone doesn't ignore in either skeletal mesh, ignore */
|
||||
if (wbone <= 0 || pbone <= 0)
|
||||
continue;
|
||||
|
||||
bpos = gettaginfo(this, pbone);
|
||||
|
||||
/* the most expensive bit */
|
||||
skel_set_bone_world(p_model, wbone, bpos, v_forward, v_right, v_up);
|
||||
}
|
||||
}
|
||||
|
||||
void Weapons_AmmoUpdate(entity);
|
||||
void HUD_AmmoNotify_Check(player pl);
|
||||
void HUD_ItemNotify_Check(player pl);
|
||||
/*
|
||||
=================
|
||||
player::ReceiveEntity
|
||||
=================
|
||||
*/
|
||||
void
|
||||
player::ReceiveEntity(float new, float flChanged)
|
||||
{
|
||||
/* the generic client attributes */
|
||||
NSClientPlayer::ReceiveEntity(new, flChanged);
|
||||
|
||||
/* animation */
|
||||
READENTITY_BYTE(anim_top, PLAYER_TOPFRAME)
|
||||
READENTITY_FLOAT(anim_top_time, PLAYER_TOPFRAME)
|
||||
READENTITY_FLOAT(anim_top_delay, PLAYER_TOPFRAME)
|
||||
READENTITY_BYTE(anim_bottom, PLAYER_BOTTOMFRAME)
|
||||
READENTITY_FLOAT(anim_bottom_time, PLAYER_BOTTOMFRAME)
|
||||
|
||||
READENTITY_BYTE(ammo_shells, PLAYER_AMMO1)
|
||||
READENTITY_BYTE(ammo_nails, PLAYER_AMMO1)
|
||||
READENTITY_BYTE(ammo_rockets, PLAYER_AMMO1)
|
||||
READENTITY_BYTE(ammo_cells, PLAYER_AMMO1)
|
||||
|
||||
setorigin(this, origin);
|
||||
|
||||
/* these only concern the current player */
|
||||
CSQC_UpdateSeat();
|
||||
if (this != pSeat->m_ePlayer)
|
||||
return;
|
||||
|
||||
/* do not notify us of updates when spawning initially */
|
||||
if (flChanged == UPDATE_ALL)
|
||||
PredictPreFrame();
|
||||
|
||||
if (flChanged & PLAYER_AMMO1 || flChanged & PLAYER_AMMO2 || flChanged & PLAYER_AMMO3) {
|
||||
Weapons_AmmoUpdate(this);
|
||||
HUD_AmmoNotify_Check(this);
|
||||
}
|
||||
|
||||
if (flChanged & PLAYER_ITEMS || flChanged & PLAYER_HEALTH)
|
||||
HUD_ItemNotify_Check(this);
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
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)
|
||||
{
|
||||
/* the generic client attributes */
|
||||
NSClientPlayer::PredictPreFrame();
|
||||
|
||||
SAVE_STATE(anim_top)
|
||||
SAVE_STATE(anim_top_delay)
|
||||
SAVE_STATE(anim_top_time)
|
||||
SAVE_STATE(anim_bottom)
|
||||
SAVE_STATE(anim_bottom_time)
|
||||
|
||||
SAVE_STATE(ammo_shells)
|
||||
SAVE_STATE(ammo_nails)
|
||||
SAVE_STATE(ammo_rockets)
|
||||
SAVE_STATE(ammo_cells)
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
player::PredictPostFrame
|
||||
|
||||
Where we roll back our values to the ones last sent/verified by the server.
|
||||
=================
|
||||
*/
|
||||
void
|
||||
player::PredictPostFrame(void)
|
||||
{
|
||||
/* the generic client attributes */
|
||||
NSClientPlayer::PredictPostFrame();
|
||||
|
||||
ROLL_BACK(anim_top)
|
||||
ROLL_BACK(anim_top_delay)
|
||||
ROLL_BACK(anim_top_time)
|
||||
ROLL_BACK(anim_bottom)
|
||||
ROLL_BACK(anim_bottom_time)
|
||||
|
||||
ROLL_BACK(ammo_shells)
|
||||
ROLL_BACK(ammo_nails)
|
||||
ROLL_BACK(ammo_rockets)
|
||||
ROLL_BACK(ammo_cells)
|
||||
}
|
||||
|
||||
#else
|
||||
void
|
||||
player::Save(float handle)
|
||||
{
|
||||
super::Save(handle);
|
||||
|
||||
SaveInt(handle, "anim_top", anim_top);
|
||||
SaveFloat(handle, "anim_top_time", anim_top_time);
|
||||
SaveFloat(handle, "anim_top_delay", anim_top_delay);
|
||||
SaveInt(handle, "anim_bottom", anim_bottom);
|
||||
SaveFloat(handle, "anim_bottom_time", anim_bottom_time);
|
||||
|
||||
/* ammo 1 */
|
||||
SaveInt(handle, "ammo_shells", ammo_shells);
|
||||
SaveInt(handle, "ammo_nails", ammo_nails);
|
||||
SaveInt(handle, "ammo_rockets", ammo_rockets);
|
||||
SaveInt(handle, "ammo_cells", ammo_cells);
|
||||
}
|
||||
|
||||
void
|
||||
player::Restore(string strKey, string strValue)
|
||||
{
|
||||
switch (strKey) {
|
||||
case "anim_top":
|
||||
anim_top = ReadInt(strValue);
|
||||
break;
|
||||
case "anim_top_time":
|
||||
anim_top_time = ReadFloat(strValue);
|
||||
break;
|
||||
case "anim_top_delay":
|
||||
anim_top_delay = ReadFloat(strValue);
|
||||
break;
|
||||
case "anim_bottom":
|
||||
anim_bottom = ReadInt(strValue);
|
||||
break;
|
||||
case "anim_bottom_time":
|
||||
anim_bottom_time = ReadFloat(strValue);
|
||||
break;
|
||||
|
||||
/* AMMO 1 */
|
||||
case "ammo_shells":
|
||||
ammo_shells = ReadInt(strValue);
|
||||
break;
|
||||
case "ammo_nails":
|
||||
ammo_nails = ReadInt(strValue);
|
||||
break;
|
||||
case "ammo_rockets":
|
||||
ammo_rockets = ReadInt(strValue);
|
||||
break;
|
||||
case "ammo_cells":
|
||||
ammo_cells = ReadInt(strValue);
|
||||
break;
|
||||
default:
|
||||
super::Restore(strKey, strValue);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
player::EvaluateEntity(void)
|
||||
{
|
||||
/* the generic client attributes */
|
||||
NSClientPlayer::EvaluateEntity();
|
||||
|
||||
EVALUATE_FIELD(anim_top, PLAYER_TOPFRAME)
|
||||
EVALUATE_FIELD(anim_top_time, PLAYER_TOPFRAME)
|
||||
EVALUATE_FIELD(anim_top_delay, PLAYER_TOPFRAME)
|
||||
EVALUATE_FIELD(anim_bottom, PLAYER_BOTTOMFRAME)
|
||||
EVALUATE_FIELD(anim_bottom_time, PLAYER_BOTTOMFRAME)
|
||||
|
||||
EVALUATE_FIELD(ammo_shells, PLAYER_AMMO1)
|
||||
EVALUATE_FIELD(ammo_nails, PLAYER_AMMO1)
|
||||
EVALUATE_FIELD(ammo_rockets, PLAYER_AMMO1)
|
||||
EVALUATE_FIELD(ammo_cells, PLAYER_AMMO1)
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
player::SendEntity
|
||||
=================
|
||||
*/
|
||||
float
|
||||
player::SendEntity(entity ePEnt, float flChanged)
|
||||
{
|
||||
/* don't broadcast invisible players */
|
||||
if (IsFakeSpectator() && ePEnt != this)
|
||||
return (0);
|
||||
if (!GetModelindex() && ePEnt != this)
|
||||
return (0);
|
||||
|
||||
flChanged = OptimiseChangedFlags(ePEnt, flChanged);
|
||||
|
||||
WriteByte(MSG_ENTITY, ENT_PLAYER);
|
||||
WriteFloat(MSG_ENTITY, flChanged);
|
||||
|
||||
/* the generic client attributes */
|
||||
NSClientPlayer::SendEntity(ePEnt, flChanged);
|
||||
|
||||
SENDENTITY_BYTE(anim_top, PLAYER_TOPFRAME)
|
||||
SENDENTITY_FLOAT(anim_top_time, PLAYER_TOPFRAME)
|
||||
SENDENTITY_FLOAT(anim_top_delay, PLAYER_TOPFRAME)
|
||||
SENDENTITY_BYTE(anim_bottom, PLAYER_BOTTOMFRAME)
|
||||
SENDENTITY_FLOAT(anim_bottom_time, PLAYER_BOTTOMFRAME)
|
||||
|
||||
SENDENTITY_BYTE(ammo_shells, PLAYER_AMMO1)
|
||||
SENDENTITY_BYTE(ammo_nails, PLAYER_AMMO1)
|
||||
SENDENTITY_BYTE(ammo_rockets, PLAYER_AMMO1)
|
||||
SENDENTITY_BYTE(ammo_cells, PLAYER_AMMO1)
|
||||
|
||||
return (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
player::player(void)
|
||||
{
|
||||
anim_top = 0;
|
||||
anim_top_time = 0;
|
||||
anim_top_delay = 0;
|
||||
anim_bottom = 0;
|
||||
anim_bottom_time = 0;
|
||||
ammo_shells = 0;
|
||||
ammo_nails = 0;
|
||||
ammo_rockets = 0;
|
||||
ammo_cells = 0;
|
||||
}
|
206
src/shared/w_crowbar.qc
Normal file
206
src/shared/w_crowbar.qc
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Marco Cawthorne <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_crowbar (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/w_crowbar.mdl"
|
||||
|
||||
DEATHMATCH CLASSIC (1999) ENTITY
|
||||
|
||||
Crowbar Weapon
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
CBAR_IDLE,
|
||||
CBAR_ATTACK,
|
||||
};
|
||||
|
||||
void
|
||||
w_crowbar_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_crowbar.swing");
|
||||
Sound_Precache("weapon_crowbar.hit");
|
||||
Sound_Precache("weapon_crowbar.hitbody");
|
||||
precache_model("models/w_crowbar.mdl");
|
||||
#else
|
||||
precache_model("models/v_crowbar.mdl");
|
||||
precache_model("models/p_crowbar.mdl");
|
||||
#endif
|
||||
}
|
||||
|
||||
string
|
||||
w_crowbar_wmodel(void)
|
||||
{
|
||||
return "models/w_crowbar.mdl";
|
||||
}
|
||||
string
|
||||
w_crowbar_pmodel(player pl)
|
||||
{
|
||||
return "models/p_crowbar.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_crowbar_deathmsg(void)
|
||||
{
|
||||
return "%s was assaulted by %s's Crowbar.";
|
||||
}
|
||||
|
||||
void
|
||||
w_crowbar_draw(player pl)
|
||||
{
|
||||
Weapons_SetModel("models/v_crowbar.mdl");
|
||||
Weapons_ViewAnimation(pl, CBAR_IDLE);
|
||||
}
|
||||
|
||||
void
|
||||
w_crowbar_primary(player pl)
|
||||
{
|
||||
int anim = 0;
|
||||
vector src;
|
||||
|
||||
if (pl.w_attack_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors(pl);
|
||||
src = pl.origin + pl.view_ofs;
|
||||
|
||||
/* make sure we can gib corpses */
|
||||
int oldhitcontents = pl.hitcontentsmaski;
|
||||
pl.hitcontentsmaski = CONTENTBITS_POINTSOLID | CONTENTBIT_CORPSE;
|
||||
traceline(src, src + (v_forward * 64), FALSE, pl);
|
||||
pl.hitcontentsmaski = oldhitcontents;
|
||||
|
||||
pl.w_attack_next = 0.5f;
|
||||
pl.w_idle_next = 2.5f;
|
||||
|
||||
Weapons_ViewAnimation(pl, CBAR_ATTACK);
|
||||
Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTCROWBAR : ANIM_SHOOTCROWBAR, 0.41f);
|
||||
|
||||
#ifdef SERVER
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_crowbar.swing");
|
||||
|
||||
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", 20), WEAPON_CROWBAR, DMG_BLUNT);
|
||||
if (trace_ent.iBleeds) {
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_crowbar.hitbody");
|
||||
}
|
||||
} else {
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_crowbar.hit");
|
||||
DecalGroups_Place("Impact.Shot", trace_endpos + (v_forward * -2));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_crowbar_aimanim(player pl)
|
||||
{
|
||||
return pl.flags & FL_CROUCHING ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR;
|
||||
}
|
||||
|
||||
void
|
||||
w_crowbar_hudpic(player pl, int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
g_hudcb_spr,
|
||||
[0,0],
|
||||
[1,0.625],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
g_hudcb_spr,
|
||||
[0,0],
|
||||
[1,0.625],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
w_crowbar_isempty(player pl)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
weapontype_t w_crowbar_type(player pl)
|
||||
{
|
||||
return WPNTYPE_CLOSE;
|
||||
}
|
||||
|
||||
weapon_t w_crowbar =
|
||||
{
|
||||
.name = "axe",
|
||||
.id = ITEM_CROWBAR,
|
||||
.slot = 0,
|
||||
.slot_pos = 0,
|
||||
.weight = 0,
|
||||
.draw = w_crowbar_draw,
|
||||
.holster = __NULL__,
|
||||
.primary = w_crowbar_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = __NULL__,
|
||||
.postdraw = __NULL__,
|
||||
.precache = w_crowbar_precache,
|
||||
.pickup = __NULL__,
|
||||
.updateammo = __NULL__,
|
||||
.wmodel = w_crowbar_wmodel,
|
||||
.pmodel = w_crowbar_pmodel,
|
||||
.deathmsg = w_crowbar_deathmsg,
|
||||
.aimanim = w_crowbar_aimanim,
|
||||
.isempty = w_crowbar_isempty,
|
||||
.type = w_crowbar_type,
|
||||
.hudpic = w_crowbar_hudpic
|
||||
};
|
||||
|
||||
/* entity definitions for pickups */
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_crowbar(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_CROWBAR);
|
||||
}
|
||||
void
|
||||
weapon_axe(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_CROWBAR);
|
||||
}
|
||||
#endif
|
262
src/shared/w_grenadelauncher.qc
Normal file
262
src/shared/w_grenadelauncher.qc
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Marco Cawthorne <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_hornetgun (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/g_rock.mdl"
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Hornetgun Weapon
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
GRENLAUNCHER_IDLE,
|
||||
GRENLAUNCHER_SHOOT,
|
||||
};
|
||||
|
||||
void
|
||||
w_grenadelauncher_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_grenadelauncher.shoot");
|
||||
Sound_Precache("weapon_grenadelauncher.bounce");
|
||||
precache_model("models/g_rock.mdl");
|
||||
precache_model("models/grenade.mdl");
|
||||
#else
|
||||
precache_model("models/v_rock.mdl");
|
||||
precache_model("models/p_rock.mdl");
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
w_grenadelauncher_pickup(player pl, int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
if (pl.ammo_rockets < MAX_A_ROCKETS) {
|
||||
pl.ammo_rockets = bound(0, pl.ammo_rockets + 5, MAX_A_ROCKETS);
|
||||
} else {
|
||||
if (!new)
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
w_grenadelauncher_updateammo(player pl)
|
||||
{
|
||||
Weapons_UpdateAmmo(pl, -1, pl.ammo_rockets, -1);
|
||||
}
|
||||
|
||||
string
|
||||
w_grenadelauncher_wmodel(void)
|
||||
{
|
||||
return "models/g_rock.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_grenadelauncher_pmodel(player pl)
|
||||
{
|
||||
return "models/p_rock.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_grenadelauncher_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
w_grenadelauncher_draw(player pl)
|
||||
{
|
||||
Weapons_SetModel("models/v_rock.mdl");
|
||||
Weapons_ViewAnimation(pl, GRENLAUNCHER_IDLE);
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
w_grenadelauncher_shootnade(player pl)
|
||||
{
|
||||
static void Grenade_Explode(void) {
|
||||
float dmg = Skill_GetValue("plr_grenadelauncher_dmg", 100);
|
||||
FX_Explosion(self.origin);
|
||||
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_GRENADELAUNCHER);
|
||||
sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
|
||||
remove(self);
|
||||
}
|
||||
static void Grenade_Bounce(void) {
|
||||
/* if what we are touching can be damaged, explode */
|
||||
if (other.takedamage) {
|
||||
Grenade_Explode();
|
||||
return;
|
||||
}
|
||||
|
||||
Sound_Play(self, CHAN_VOICE, "weapon_grenadelauncher.bounce");
|
||||
}
|
||||
|
||||
Weapons_MakeVectors(pl);
|
||||
|
||||
/* spawn the 'pineapple' */
|
||||
entity grenade = spawn();
|
||||
setmodel(grenade, "models/grenade.mdl");
|
||||
setorigin(grenade, pl.origin);
|
||||
grenade.owner = pl;
|
||||
|
||||
if (pl.v_angle[0]) {
|
||||
grenade.velocity = v_forward * 600;
|
||||
grenade.velocity += v_up * 200;
|
||||
grenade.velocity += ((random() - 0.5) * v_right) * 10;
|
||||
grenade.velocity += ((random() - 0.5) * v_up) * 10;
|
||||
} else {
|
||||
grenade.velocity = v_forward * 600;
|
||||
grenade.velocity[2] = 200;
|
||||
}
|
||||
|
||||
grenade.avelocity = [300, 300, 300];
|
||||
grenade.movetype = MOVETYPE_BOUNCE;
|
||||
grenade.solid = SOLID_BBOX;
|
||||
//grenade.flags |= FL_LAGGEDMOVE;
|
||||
grenade.angles = vectoangles(grenade.velocity);
|
||||
grenade.touch = Grenade_Bounce;
|
||||
grenade.think = Grenade_Explode;
|
||||
grenade.nextthink = time + 2.5f;
|
||||
grenade.traileffectnum = particleeffectnum("weapon_rpg.trail");
|
||||
setsize(grenade, [0,0,0], [0,0,0]);
|
||||
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_grenadelauncher.shoot");
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
w_grenadelauncher_primary(player pl)
|
||||
{
|
||||
if (pl.w_attack_next > 0.0)
|
||||
return;
|
||||
if (pl.ammo_rockets <= 0)
|
||||
return;
|
||||
|
||||
/* fire the actual projectile (on the server) */
|
||||
#ifdef SERVER
|
||||
w_grenadelauncher_shootnade(pl);
|
||||
#endif
|
||||
|
||||
/* remove ammo and play the animation on view + player model */
|
||||
pl.ammo_rockets--;
|
||||
Weapons_ViewAnimation(pl, GRENLAUNCHER_SHOOT);
|
||||
Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTGAUSS : ANIM_SHOOTGAUSS, 0.43f);
|
||||
|
||||
pl.w_attack_next = 0.6;
|
||||
}
|
||||
|
||||
void
|
||||
w_grenadelauncher_crosshair(player pl)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector aicon_pos;
|
||||
|
||||
Cross_DrawSub(g_cross_spr, [24,24], [72/128,24/128], [0.1875, 0.1875]);
|
||||
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
drawsubpic(
|
||||
aicon_pos,
|
||||
[24,24],
|
||||
g_hudglammo,
|
||||
[0, 0],
|
||||
[24/24, 24/24],
|
||||
g_hud_color,
|
||||
pSeatLocal->m_flAmmo2Alpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_grenadelauncher_aimanim(player pl)
|
||||
{
|
||||
return pl.flags & FL_CROUCHING ? ANIM_CR_AIMGAUSS : ANIM_AIMGAUSS;
|
||||
}
|
||||
|
||||
int
|
||||
w_grenadelauncher_isempty(player pl)
|
||||
{
|
||||
return (pl.ammo_rockets == 0) ? true : false;
|
||||
}
|
||||
|
||||
void
|
||||
w_grenadelauncher_hudpic(player pl, int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector hud_col;
|
||||
|
||||
if (w_grenadelauncher_isempty(pl))
|
||||
hud_col = [1,0,0];
|
||||
else
|
||||
hud_col = g_hud_color;
|
||||
|
||||
if (selected) {
|
||||
drawsubpic(pos, [170,45], g_hudgl_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
} else {
|
||||
drawsubpic(pos, [170,45], g_hudgl_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
}
|
||||
|
||||
HUD_DrawAmmoBar(pos, pl.ammo_rockets, MAX_A_ROCKETS, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
weapontype_t
|
||||
w_grenadelauncher_type(player pl)
|
||||
{
|
||||
return WPNTYPE_RANGED;
|
||||
}
|
||||
|
||||
weapon_t
|
||||
w_grenadelauncher =
|
||||
{
|
||||
.name = "grenadel",
|
||||
.id = ITEM_GRENADELAUNCHER,
|
||||
.slot = 5,
|
||||
.slot_pos = 0,
|
||||
.weight = 4,
|
||||
.draw = w_grenadelauncher_draw,
|
||||
.holster = __NULL__,
|
||||
.primary = w_grenadelauncher_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = __NULL__,
|
||||
.postdraw = w_grenadelauncher_crosshair,
|
||||
.precache = w_grenadelauncher_precache,
|
||||
.pickup = w_grenadelauncher_pickup,
|
||||
.updateammo = w_grenadelauncher_updateammo,
|
||||
.wmodel = w_grenadelauncher_wmodel,
|
||||
.pmodel = w_grenadelauncher_pmodel,
|
||||
.deathmsg = w_grenadelauncher_deathmsg,
|
||||
.aimanim = w_grenadelauncher_aimanim,
|
||||
.isempty = w_grenadelauncher_isempty,
|
||||
.type = w_grenadelauncher_type,
|
||||
.hudpic = w_grenadelauncher_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_grenadelauncher(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_GRENADELAUNCHER);
|
||||
}
|
||||
#endif
|
241
src/shared/w_lightning.qc
Normal file
241
src/shared/w_lightning.qc
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Marco Cawthorne <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_crossbow (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/g_light.mdl"
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Crossbow Weapon
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
LIGHTNING_IDLE,
|
||||
LIGHTNING_SHOOT,
|
||||
};
|
||||
|
||||
void
|
||||
w_lightning_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_lightning.start");
|
||||
precache_model("models/g_light.mdl");
|
||||
#else
|
||||
precache_model("models/v_light.mdl");
|
||||
precache_model("models/p_light.mdl");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_lightning_updateammo(player pl)
|
||||
{
|
||||
Weapons_UpdateAmmo(pl, -1, pl.ammo_cells, -1);
|
||||
}
|
||||
|
||||
string
|
||||
w_lightning_wmodel(void)
|
||||
{
|
||||
return "models/g_light.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_lightning_pmodel(player pl)
|
||||
{
|
||||
return "models/p_light.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_lightning_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
w_lightning_pickup(player pl, int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
if (pl.ammo_cells < MAX_A_CELLS) {
|
||||
pl.ammo_cells = bound(0, pl.ammo_cells + 15, MAX_A_CELLS);
|
||||
} else {
|
||||
if (!new)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
w_lightning_draw(player pl)
|
||||
{
|
||||
Weapons_SetModel("models/v_light.mdl");
|
||||
Weapons_ViewAnimation(pl, LIGHTNING_IDLE);
|
||||
}
|
||||
|
||||
void
|
||||
w_lightning_primary(player pl)
|
||||
{
|
||||
if (pl.w_attack_next > 0.0)
|
||||
return;
|
||||
if (pl.ammo_cells <= 0)
|
||||
return;
|
||||
|
||||
pl.ammo_cells--;
|
||||
|
||||
#ifdef SERVER
|
||||
{
|
||||
if (pl.WaterLevel() > 1) {
|
||||
// we're underwater... fry everyone */
|
||||
} else {
|
||||
vector startPos = Weapons_GetCameraPos(pl);
|
||||
Weapons_MakeVectors(pl);
|
||||
traceline(startPos, startPos + v_forward * 600, MOVE_NORMAL, pl);
|
||||
|
||||
WriteByte(MSG_MULTICAST, SVC_TEMPENTITY);
|
||||
WriteByte(MSG_MULTICAST, TE_LIGHTNING2);
|
||||
WriteEntity(MSG_MULTICAST, pl);
|
||||
WriteCoord(MSG_MULTICAST, startPos[0]);
|
||||
WriteCoord(MSG_MULTICAST, startPos[1]);
|
||||
WriteCoord(MSG_MULTICAST, startPos[2]);
|
||||
WriteCoord(MSG_MULTICAST, trace_endpos[0]);
|
||||
WriteCoord(MSG_MULTICAST, trace_endpos[1]);
|
||||
WriteCoord(MSG_MULTICAST, trace_endpos[2]);
|
||||
multicast(startPos, MULTICAST_PHS);
|
||||
|
||||
if (trace_ent.takedamage) {
|
||||
Damage_Apply(trace_ent, pl, Skill_GetValue("plr_crowbar", 10), WEAPON_CROWBAR, DMG_BLUNT);
|
||||
|
||||
/* throw players into the air */
|
||||
if (trace_ent.classname == "player") {
|
||||
NSClientPlayer tp = (NSClientPlayer)trace_ent;
|
||||
tp.SetVelocity(tp.GetVelocity() + [0, 0, 400]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_lightning.start");
|
||||
#endif
|
||||
|
||||
Weapons_ViewAnimation(pl, LIGHTNING_SHOOT);
|
||||
Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTGAUSS : ANIM_SHOOTGAUSS, 0.43f);
|
||||
|
||||
Weapons_ViewPunchAngle(pl, [-2,0,0]);
|
||||
|
||||
pl.w_attack_next = 0.1f;
|
||||
}
|
||||
|
||||
void
|
||||
w_lightning_crosshair(player pl)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector aicon_pos;
|
||||
|
||||
Cross_DrawSub(g_cross_spr, [24,24], [72/128,0], [0.1875, 0.1875]);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
|
||||
drawsubpic(
|
||||
aicon_pos,
|
||||
[24,24],
|
||||
g_hudlgammo,
|
||||
[0, 0],
|
||||
[24/24, 24/24],
|
||||
g_hud_color,
|
||||
pSeatLocal->m_flAmmo2Alpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_lightning_aimanim(player pl)
|
||||
{
|
||||
return pl.flags & FL_CROUCHING ? ANIM_CR_AIMGAUSS : ANIM_AIMGAUSS;
|
||||
}
|
||||
|
||||
int
|
||||
w_lightning_isempty(player pl)
|
||||
{
|
||||
if (pl.ammo_cells <= 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
w_lightning_hudpic(player pl, int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector hud_col;
|
||||
|
||||
if (w_lightning_isempty(pl))
|
||||
hud_col = [1,0,0];
|
||||
else
|
||||
hud_col = g_hud_color;
|
||||
|
||||
if (selected) {
|
||||
drawsubpic(pos, [170,45], g_hudlg_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
} else {
|
||||
drawsubpic(pos, [170,45], g_hudlg_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
}
|
||||
|
||||
HUD_DrawAmmoBar(pos, pl.ammo_cells, MAX_A_CELLS, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
weapontype_t
|
||||
w_lightning_type(player pl)
|
||||
{
|
||||
return WPNTYPE_RANGED;
|
||||
}
|
||||
|
||||
weapon_t w_lightning =
|
||||
{
|
||||
.name = "lightning",
|
||||
.id = ITEM_LIGHTNING,
|
||||
.slot = 7,
|
||||
.slot_pos = 0,
|
||||
.weight = 1,
|
||||
.draw = w_lightning_draw,
|
||||
.holster = __NULL__,
|
||||
.primary = w_lightning_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = __NULL__,
|
||||
.postdraw = w_lightning_crosshair,
|
||||
.precache = w_lightning_precache,
|
||||
.pickup = w_lightning_pickup,
|
||||
.updateammo = w_lightning_updateammo,
|
||||
.wmodel = w_lightning_wmodel,
|
||||
.pmodel = w_lightning_pmodel,
|
||||
.deathmsg = w_lightning_deathmsg,
|
||||
.aimanim = w_lightning_aimanim,
|
||||
.isempty = w_lightning_isempty,
|
||||
.type = w_lightning_type,
|
||||
.hudpic = w_lightning_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_lightning(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_LIGHTNING);
|
||||
}
|
||||
#endif
|
235
src/shared/w_nailgun.qc
Normal file
235
src/shared/w_nailgun.qc
Normal file
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Marco Cawthorne <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_nailgun (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/g_nail.mdl"
|
||||
|
||||
DEATHMATCH CLASSIC (1999) ENTITY
|
||||
|
||||
Nailgun
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
NAILGUN_IDLE,
|
||||
NAILGUN_SHOOT,
|
||||
};
|
||||
|
||||
void
|
||||
w_nailgun_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_nailgun.shoot");
|
||||
precache_model("models/g_nail.mdl");
|
||||
#else
|
||||
precache_model("models/v_nail.mdl");
|
||||
precache_model("models/p_nail.mdl");
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
w_nailgun_pickup(player pl, int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
if (pl.ammo_nails < MAX_A_NAILS) {
|
||||
pl.ammo_nails = bound(0, pl.ammo_nails + 30, MAX_A_NAILS);
|
||||
} else {
|
||||
if (!new)
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
w_nailgun_updateammo(player pl)
|
||||
{
|
||||
Weapons_UpdateAmmo(pl, -1, pl.ammo_nails, -1);
|
||||
}
|
||||
|
||||
string
|
||||
w_nailgun_wmodel(void)
|
||||
{
|
||||
return "models/g_nail.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_nailgun_pmodel(player pl)
|
||||
{
|
||||
return "models/p_nail.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_nailgun_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
w_nailgun_draw(player pl)
|
||||
{
|
||||
Weapons_SetModel("models/v_nail.mdl");
|
||||
Weapons_ViewAnimation(pl, NAILGUN_IDLE);
|
||||
}
|
||||
|
||||
void
|
||||
w_nailgun_primary(player pl)
|
||||
{
|
||||
if (pl.w_attack_next > 0.0)
|
||||
return;
|
||||
if (pl.ammo_nails <= 0)
|
||||
return;
|
||||
|
||||
pl.ammo_nails--;
|
||||
|
||||
/* Actual firing */
|
||||
#ifdef CLIENT
|
||||
#else
|
||||
{
|
||||
static void nail_touch(void) {
|
||||
remove(self);
|
||||
}
|
||||
|
||||
entity nail = spawn();
|
||||
setmodel(nail, "models/spike.mdl");
|
||||
setsize(nail, g_vec_null, g_vec_null);
|
||||
nail.movetype = MOVETYPE_FLYMISSILE;
|
||||
nail.solid = SOLID_BBOX;
|
||||
nail.touch = nail_touch;
|
||||
nail.owner = pl;
|
||||
Weapons_MakeVectors(pl);
|
||||
|
||||
if (pl.ammo_nails & 1) {
|
||||
setorigin(nail, Weapons_GetCameraPos(pl) + (v_right * -2) + (v_up * -5));
|
||||
nail.velocity = v_forward * 1000 + (v_right * -2) + (v_up * -5);
|
||||
} else {
|
||||
setorigin(nail, Weapons_GetCameraPos(pl) + (v_right * 2) + (v_up * -5));
|
||||
nail.velocity = v_forward * 1000 + (v_right * 2) + (v_up * -5);
|
||||
}
|
||||
nail.angles = vectoangles(nail.velocity);
|
||||
}
|
||||
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_nailgun.shoot");
|
||||
#endif
|
||||
|
||||
Weapons_ViewPunchAngle(pl, [-2,0,0]);
|
||||
Weapons_ViewAnimation(pl, NAILGUN_SHOOT);
|
||||
Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTMP5 : ANIM_SHOOTMP5, 0.45f);
|
||||
|
||||
pl.w_attack_next = 0.1f;
|
||||
}
|
||||
|
||||
void
|
||||
w_nailgun_crosshair(player pl)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector aicon_pos;
|
||||
|
||||
Cross_DrawSub(g_cross_spr, [24,24], [48/128,0], [0.1875, 0.1875]);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
|
||||
drawsubpic(
|
||||
aicon_pos,
|
||||
[24,24],
|
||||
g_hudngammo,
|
||||
[0, 0],
|
||||
[24/24, 24/24],
|
||||
g_hud_color,
|
||||
pSeatLocal->m_flAmmo2Alpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_nailgun_aimanim(player pl)
|
||||
{
|
||||
return pl.flags & FL_CROUCHING ? ANIM_CR_AIMMP5 : ANIM_AIMMP5;
|
||||
}
|
||||
|
||||
int
|
||||
w_nailgun_isempty(player pl)
|
||||
{
|
||||
if (pl.ammo_nails <= 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
w_nailgun_hudpic(player pl, int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector hud_col;
|
||||
|
||||
if (w_nailgun_isempty(pl))
|
||||
hud_col = [1,0,0];
|
||||
else
|
||||
hud_col = g_hud_color;
|
||||
|
||||
if (selected) {
|
||||
drawsubpic(pos, [170,45], g_hudng_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
} else {
|
||||
drawsubpic(pos, [170,45], g_hudng_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
}
|
||||
|
||||
HUD_DrawAmmoBar(pos, pl.ammo_nails, MAX_A_NAILS, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
weapontype_t
|
||||
w_nailgun_type(player pl)
|
||||
{
|
||||
return WPNTYPE_RANGED;
|
||||
}
|
||||
|
||||
weapon_t w_nailgun =
|
||||
{
|
||||
.name = "nailgun",
|
||||
.id = ITEM_NAILGUN,
|
||||
.slot = 3,
|
||||
.slot_pos = 0,
|
||||
.weight = 6,
|
||||
.draw = w_nailgun_draw,
|
||||
.holster = __NULL__,
|
||||
.primary = w_nailgun_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = __NULL__,
|
||||
.postdraw = w_nailgun_crosshair,
|
||||
.precache = w_nailgun_precache,
|
||||
.pickup = w_nailgun_pickup,
|
||||
.updateammo = w_nailgun_updateammo,
|
||||
.wmodel = w_nailgun_wmodel,
|
||||
.pmodel = w_nailgun_pmodel,
|
||||
.deathmsg = w_nailgun_deathmsg,
|
||||
.aimanim = w_nailgun_aimanim,
|
||||
.isempty = w_nailgun_isempty,
|
||||
.type = w_nailgun_type,
|
||||
.hudpic = w_nailgun_hudpic
|
||||
};
|
||||
|
||||
/* pickups */
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_nailgun(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_NAILGUN);
|
||||
}
|
||||
#endif
|
236
src/shared/w_rocketlauncher.qc
Normal file
236
src/shared/w_rocketlauncher.qc
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Marco Cawthorne <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_rocketlauncher (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/g_rock2.mdl"
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
RPG Weapon
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
RPG_IDLE,
|
||||
RPG_SHOOT
|
||||
};
|
||||
|
||||
void
|
||||
w_rocketlauncher_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_rocketlauncher.shoot");
|
||||
precache_model("models/g_rock2.mdl");
|
||||
precache_model("models/rocket.mdl");
|
||||
#else
|
||||
precache_model("models/v_rock2.mdl");
|
||||
precache_model("models/p_rock2.mdl");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_rocketlauncher_updateammo(player pl)
|
||||
{
|
||||
Weapons_UpdateAmmo(pl, -1, pl.ammo_rockets, -1);
|
||||
}
|
||||
|
||||
string
|
||||
w_rocketlauncher_wmodel(void)
|
||||
{
|
||||
return "models/g_rock2.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_rocketlauncher_pmodel(player pl)
|
||||
{
|
||||
return "models/p_rock2.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_rocketlauncher_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
w_rocketlauncher_pickup(player pl, int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
if (pl.ammo_rockets < MAX_A_ROCKETS) {
|
||||
pl.ammo_rockets = bound(0, pl.ammo_rockets + 5, MAX_A_ROCKETS);
|
||||
} else {
|
||||
if (!new)
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
w_rocketlauncher_draw(player pl)
|
||||
{
|
||||
Weapons_SetModel("models/v_rock2.mdl");
|
||||
Weapons_ViewAnimation(pl, RPG_IDLE);
|
||||
}
|
||||
|
||||
void
|
||||
w_rocketlauncher_primary(player pl)
|
||||
{
|
||||
if (pl.w_attack_next > 0.0)
|
||||
return;
|
||||
if (pl.ammo_rockets <= 0)
|
||||
return;
|
||||
|
||||
/* visual fluff */
|
||||
Weapons_ViewAnimation(pl, RPG_SHOOT);
|
||||
Weapons_ViewPunchAngle(pl, [-10,0,0]);
|
||||
Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTGAUSS : ANIM_SHOOTGAUSS, 0.43f);
|
||||
|
||||
pl.w_attack_next = 0.8f;
|
||||
pl.ammo_rockets--;
|
||||
|
||||
#ifdef SERVER
|
||||
static void Rocket_Touch(void) {
|
||||
float dmg = Skill_GetValue("plr_rocketlauncher_dmg", 100);
|
||||
FX_Explosion(self.origin);
|
||||
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_ROCKETLAUNCHER);
|
||||
sound(self, CHAN_WEAPON, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
|
||||
remove(self);
|
||||
}
|
||||
|
||||
|
||||
Weapons_MakeVectors(pl);
|
||||
entity rocket = spawn();
|
||||
setmodel(rocket, "models/rocket.mdl");
|
||||
setorigin(rocket, Weapons_GetCameraPos(pl) + (v_forward * 16));
|
||||
rocket.owner = pl;
|
||||
rocket.movetype = MOVETYPE_FLYMISSILE;
|
||||
rocket.solid = SOLID_BBOX;
|
||||
rocket.velocity = (pl.WaterLevel() >= WATERLEVEL_SUBMERGED) ? (v_forward * 100): (v_forward * 1000);
|
||||
rocket.angles = vectoangles(rocket.velocity);
|
||||
rocket.avelocity[2] = 10;
|
||||
rocket.touch = Rocket_Touch;
|
||||
rocket.traileffectnum = particleeffectnum("weapon_rpg.trail");
|
||||
|
||||
setsize(rocket, [0,0,0], [0,0,0]);
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_rocketlauncher.shoot");
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_rocketlauncher_aimanim(player pl)
|
||||
{
|
||||
return pl.flags & FL_CROUCHING ? ANIM_CR_AIMGAUSS : ANIM_AIMGAUSS;
|
||||
}
|
||||
|
||||
int
|
||||
w_rocketlauncher_isempty(player pl)
|
||||
{
|
||||
if (pl.ammo_rockets <= 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
w_rocketlauncher_hudpic(player pl, int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector hud_col;
|
||||
|
||||
if (w_rocketlauncher_isempty(pl))
|
||||
hud_col = [1,0,0];
|
||||
else
|
||||
hud_col = g_hud_color;
|
||||
|
||||
if (selected) {
|
||||
drawsubpic(pos, [170,45], g_hudrl_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
} else {
|
||||
drawsubpic(pos, [170,45], g_hudrl_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
}
|
||||
|
||||
HUD_DrawAmmoBar(pos, pl.ammo_rockets, MAX_A_ROCKETS, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_rocketlauncher_hud(player pl)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector laser_pos;
|
||||
vector aicon_pos;
|
||||
|
||||
Cross_DrawSub(g_cross_spr, [24,24], [24/128,48/128], [0.1875, 0.1875]);
|
||||
|
||||
/* ammo counters */
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
/* ammo icon */
|
||||
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
|
||||
drawsubpic(
|
||||
aicon_pos,
|
||||
[24,24],
|
||||
g_hudrlammo,
|
||||
[0, 0],
|
||||
[24/24, 24/24],
|
||||
g_hud_color,
|
||||
pSeatLocal->m_flAmmo2Alpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
weapontype_t
|
||||
w_rocketlauncher_type(player pl)
|
||||
{
|
||||
return WPNTYPE_RANGED;
|
||||
}
|
||||
|
||||
weapon_t
|
||||
w_rocketlauncher =
|
||||
{
|
||||
.name = "rocketl",
|
||||
.id = ITEM_ROCKETLAUNCHER,
|
||||
.slot = 6,
|
||||
.slot_pos = 0,
|
||||
.weight = 2,
|
||||
.draw = w_rocketlauncher_draw,
|
||||
.holster = __NULL__,
|
||||
.primary = w_rocketlauncher_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = __NULL__,
|
||||
.postdraw = w_rocketlauncher_hud,
|
||||
.precache = w_rocketlauncher_precache,
|
||||
.pickup = w_rocketlauncher_pickup,
|
||||
.updateammo = w_rocketlauncher_updateammo,
|
||||
.wmodel = w_rocketlauncher_wmodel,
|
||||
.pmodel = w_rocketlauncher_pmodel,
|
||||
.deathmsg = w_rocketlauncher_deathmsg,
|
||||
.aimanim = w_rocketlauncher_aimanim,
|
||||
.isempty = w_rocketlauncher_isempty,
|
||||
.type = w_rocketlauncher_type,
|
||||
.hudpic = w_rocketlauncher_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_rocketlauncher(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_ROCKETLAUNCHER);
|
||||
}
|
||||
#endif
|
234
src/shared/w_shotgun.qc
Normal file
234
src/shared/w_shotgun.qc
Normal file
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Marco Cawthorne <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_shotgun (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/g_shotgun.mdl"
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Shotgun Weapon
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
SHOTGUN_IDLE1,
|
||||
SHOTGUN_FIRE1
|
||||
};
|
||||
|
||||
#ifdef CLIENT
|
||||
void w_shotgun_ejectshell(void)
|
||||
{
|
||||
static void w_shotgun_ejectshell_death(void) {
|
||||
remove(self);
|
||||
}
|
||||
static void w_shotgun_ejectshell_touch(void) {
|
||||
if (other == world)
|
||||
Sound_Play(self, CHAN_BODY, "modelevent_shotgunshell.land");
|
||||
}
|
||||
entity eShell = spawn();
|
||||
setmodel(eShell, "models/shotgunshell.mdl");
|
||||
eShell.solid = SOLID_BBOX;
|
||||
eShell.movetype = MOVETYPE_BOUNCE;
|
||||
eShell.drawmask = MASK_ENGINE;
|
||||
eShell.angles = [pSeat->m_eViewModel.angles[0], pSeat->m_eViewModel.angles[1], 0];
|
||||
eShell.velocity = pSeat->m_vecPredictedVelocity;
|
||||
|
||||
makevectors(pSeat->m_eViewModel.angles);
|
||||
eShell.velocity += (v_forward * 0);
|
||||
eShell.velocity += (v_right * 80);
|
||||
eShell.velocity += (v_up * 100);
|
||||
eShell.touch = w_shotgun_ejectshell_touch;
|
||||
|
||||
eShell.avelocity = [0,45,900];
|
||||
eShell.think = w_shotgun_ejectshell_death;
|
||||
eShell.nextthink = time + 2.5f;
|
||||
setsize(eShell, [0,0,0], [0,0,0]);
|
||||
setorigin(eShell, pSeat->m_eViewModel.origin + (v_forward * 20) + (v_up * -16));
|
||||
}
|
||||
#endif
|
||||
|
||||
void w_shotgun_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_shotgun.shoot");
|
||||
precache_model("models/g_shot.mdl");
|
||||
precache_model("models/shotgunshell.mdl");
|
||||
#else
|
||||
precache_model("models/v_shot.mdl");
|
||||
precache_model("models/p_shot.mdl");
|
||||
precache_model("models/shotgunshell.mdl");
|
||||
Sound_Precache("modelevent_shotgunshell.land");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_shotgun_updateammo(player pl)
|
||||
{
|
||||
Weapons_UpdateAmmo(pl, -1, pl.ammo_shells, -1);
|
||||
}
|
||||
|
||||
string
|
||||
w_shotgun_wmodel(void)
|
||||
{
|
||||
return "models/g_shot.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_shotgun_pmodel(player pl)
|
||||
{
|
||||
return "models/p_shot.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_shotgun_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
w_shotgun_pickup(player pl, int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
if (pl.ammo_shells < MAX_A_SHELLS) {
|
||||
pl.ammo_shells = bound(0, pl.ammo_shells + 5, MAX_A_SHELLS);
|
||||
} else {
|
||||
if (!new)
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
w_shotgun_draw(player pl)
|
||||
{
|
||||
Weapons_SetModel("models/v_shot.mdl");
|
||||
}
|
||||
|
||||
void
|
||||
w_shotgun_primary(player pl)
|
||||
{
|
||||
if (pl.w_attack_next > 0.0)
|
||||
return;
|
||||
if (pl.ammo_shells <= 0)
|
||||
return;
|
||||
|
||||
#ifdef SERVER
|
||||
/* Singleplayer is more accurate */
|
||||
TraceAttack_FireBulletsWithDecal(6, pl.origin + pl.view_ofs, Skill_GetValue("plr_shotgun_dmg", 4), [0.1,0.1], WEAPON_SHOTGUN, "Impact.BigShot");
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.shoot");
|
||||
#else
|
||||
//View_AddEvent(w_shotgun_ejectshell, 0.25f);
|
||||
#endif
|
||||
|
||||
Weapons_ViewAnimation(pl, SHOTGUN_FIRE1);
|
||||
Weapons_ViewPunchAngle(pl, [-5,0,0]);
|
||||
Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTSHOTGUN : ANIM_SHOOTSHOTGUN, 0.5f);
|
||||
|
||||
pl.ammo_shells--;
|
||||
|
||||
pl.w_idle_next = 0.5f;
|
||||
pl.w_attack_next = 0.5;
|
||||
}
|
||||
|
||||
void
|
||||
w_shotgun_crosshair(player pl)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
Cross_DrawSub(g_cross_spr, [24,24], [48/128,24/128], [0.1875, 0.1875]);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
|
||||
drawsubpic(aicon_pos, [24,24], g_hudsgammo, [0, 0], [1,1], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_shotgun_aimanim(player pl)
|
||||
{
|
||||
return pl.flags & FL_CROUCHING ? ANIM_CR_AIMSHOTGUN : ANIM_AIMSHOTGUN;
|
||||
}
|
||||
|
||||
int
|
||||
w_shotgun_isempty(player pl)
|
||||
{
|
||||
if (pl.ammo_shells <= 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
w_shotgun_hudpic(player pl, int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector hud_col;
|
||||
|
||||
if (w_shotgun_isempty(pl))
|
||||
hud_col = [1,0,0];
|
||||
else
|
||||
hud_col = g_hud_color;
|
||||
|
||||
if (selected) {
|
||||
drawsubpic(pos, [170,45], g_hudsg_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
} else {
|
||||
drawsubpic(pos, [170,45], g_hudsg_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
}
|
||||
|
||||
HUD_DrawAmmoBar(pos, pl.ammo_shells, MAX_A_SHELLS, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
weapontype_t
|
||||
w_shotgun_type(player pl)
|
||||
{
|
||||
return WPNTYPE_RANGED;
|
||||
}
|
||||
|
||||
weapon_t w_shotgun =
|
||||
{
|
||||
.name = "shotgun",
|
||||
.id = ITEM_SHOTGUN,
|
||||
.slot = 1,
|
||||
.slot_pos = 0,
|
||||
.weight = 15,
|
||||
.draw = w_shotgun_draw,
|
||||
.holster = __NULL__,
|
||||
.primary = w_shotgun_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = __NULL__,
|
||||
.postdraw = w_shotgun_crosshair,
|
||||
.precache = w_shotgun_precache,
|
||||
.pickup = w_shotgun_pickup,
|
||||
.updateammo = w_shotgun_updateammo,
|
||||
.wmodel = w_shotgun_wmodel,
|
||||
.pmodel = w_shotgun_pmodel,
|
||||
.deathmsg = w_shotgun_deathmsg,
|
||||
.aimanim = w_shotgun_aimanim,
|
||||
.isempty = w_shotgun_isempty,
|
||||
.type = w_shotgun_type,
|
||||
.hudpic = w_shotgun_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_shotgun(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_SHOTGUN);
|
||||
}
|
||||
#endif
|
219
src/shared/w_supernailgun.qc
Normal file
219
src/shared/w_supernailgun.qc
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Marco Cawthorne <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_supernailgun (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/g_nail2.mdl"
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
MP5/9mmAR Weapon
|
||||
Same as weapon_9mmAR
|
||||
|
||||
*/
|
||||
|
||||
/* Animations */
|
||||
enum
|
||||
{
|
||||
SUPERNAIL_IDLE,
|
||||
SUPERNAIL_SHOOT
|
||||
};
|
||||
|
||||
void
|
||||
w_supernailgun_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_supernailgun.shoot");
|
||||
precache_model("models/g_nail2.mdl");
|
||||
precache_model("models/spike.mdl");
|
||||
#else
|
||||
precache_model("models/v_nail2.mdl");
|
||||
precache_model("models/p_nail2.mdl");
|
||||
Sound_Precache("modelevent_shell.land");
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
w_supernailgun_pickup(player pl, int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
if (pl.ammo_nails < MAX_A_NAILS) {
|
||||
pl.ammo_nails = bound(0, pl.ammo_nails + 30, MAX_A_NAILS);
|
||||
} else {
|
||||
if (!new)
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
w_supernailgun_updateammo(player pl)
|
||||
{
|
||||
Weapons_UpdateAmmo(pl, -1, pl.ammo_nails, -1);
|
||||
}
|
||||
|
||||
string
|
||||
w_supernailgun_wmodel(void)
|
||||
{
|
||||
return "models/g_nail2.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_supernailgun_pmodel(player pl)
|
||||
{
|
||||
return "models/p_nail2.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_supernailgun_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
w_supernailgun_draw(player pl)
|
||||
{
|
||||
Weapons_SetModel("models/v_nail2.mdl");
|
||||
Weapons_ViewAnimation(pl, SUPERNAIL_IDLE);
|
||||
}
|
||||
|
||||
void
|
||||
w_supernailgun_primary(player pl)
|
||||
{
|
||||
if (pl.w_attack_next > 0.0f)
|
||||
return;
|
||||
|
||||
pl.ammo_nails--;
|
||||
Weapons_ViewAnimation(pl, SUPERNAIL_SHOOT);
|
||||
Weapons_ViewPunchAngle(pl, [-2,0,0]);
|
||||
Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTMP5 : ANIM_SHOOTMP5, 0.1f);
|
||||
|
||||
#ifdef CLIENT
|
||||
#else
|
||||
{
|
||||
static void nail_touch(void) {
|
||||
remove(self);
|
||||
}
|
||||
|
||||
entity nail = spawn();
|
||||
setmodel(nail, "models/spike.mdl");
|
||||
setorigin(nail, Weapons_GetCameraPos(pl) + (v_up * -5));
|
||||
setsize(nail, g_vec_null, g_vec_null);
|
||||
nail.movetype = MOVETYPE_FLYMISSILE;
|
||||
nail.solid = SOLID_BBOX;
|
||||
nail.touch = nail_touch;
|
||||
nail.owner = pl;
|
||||
Weapons_MakeVectors(pl);
|
||||
nail.velocity = v_forward * 1000 + (v_up * -5);
|
||||
nail.angles = vectoangles(nail.velocity);
|
||||
}
|
||||
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_supernailgun.shoot");
|
||||
#endif
|
||||
|
||||
pl.w_attack_next = 0.085f;
|
||||
pl.w_idle_next = 10.0f;
|
||||
}
|
||||
|
||||
void
|
||||
w_supernailgun_crosshair(player pl)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
|
||||
|
||||
Cross_DrawSub(g_cross_spr, [24,24], [0,48/128], [0.1875, 0.1875]);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
drawsubpic(aicon_pos, [24,24], g_hudsngammo, [0, 0], [1,1], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_supernailgun_aimanim(player pl)
|
||||
{
|
||||
return pl.flags & ANIM_CR_AIMMP5 ? ANIM_CR_AIMCROWBAR : ANIM_AIMMP5;
|
||||
}
|
||||
|
||||
int
|
||||
w_supernailgun_isempty(player pl)
|
||||
{
|
||||
if (pl.ammo_nails <= 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
w_supernailgun_hudpic(player pl, int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector hud_col;
|
||||
|
||||
if (w_supernailgun_isempty(pl))
|
||||
hud_col = [1,0,0];
|
||||
else
|
||||
hud_col = g_hud_color;
|
||||
|
||||
if (selected) {
|
||||
drawsubpic(pos, [170,45], g_hudsng_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
} else {
|
||||
drawsubpic(pos, [170,45], g_hudsng_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
}
|
||||
|
||||
HUD_DrawAmmoBar(pos, pl.ammo_nails, MAX_A_NAILS, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
weapontype_t
|
||||
w_supernailgun_type(player pl)
|
||||
{
|
||||
return WPNTYPE_RANGED;
|
||||
}
|
||||
|
||||
weapon_t w_supernailgun =
|
||||
{
|
||||
.name = "supernail",
|
||||
.id = ITEM_SUPERNAILGUN,
|
||||
.slot = 4,
|
||||
.slot_pos = 0,
|
||||
.weight = 3,
|
||||
.draw = w_supernailgun_draw,
|
||||
.holster = __NULL__,
|
||||
.primary = w_supernailgun_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = __NULL__,
|
||||
.postdraw = w_supernailgun_crosshair,
|
||||
.precache = w_supernailgun_precache,
|
||||
.pickup = w_supernailgun_pickup,
|
||||
.updateammo = w_supernailgun_updateammo,
|
||||
.wmodel = w_supernailgun_wmodel,
|
||||
.pmodel = w_supernailgun_pmodel,
|
||||
.deathmsg = w_supernailgun_deathmsg,
|
||||
.aimanim = w_supernailgun_aimanim,
|
||||
.isempty = w_supernailgun_isempty,
|
||||
.type = w_supernailgun_type,
|
||||
.hudpic = w_supernailgun_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_supernailgun(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_SUPERNAILGUN);
|
||||
}
|
||||
#endif
|
252
src/shared/w_supershotgun.qc
Normal file
252
src/shared/w_supershotgun.qc
Normal file
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Marco Cawthorne <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_9mmhandgun (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/g_shot2.mdl"
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
9mm Handgun/Glock Weapon
|
||||
Same as weapon_glock
|
||||
|
||||
*/
|
||||
|
||||
/*QUAKED weapon_glock (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/g_shot2.mdl"
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
9mm Handgun/Glock Weapon
|
||||
Same as weapon_9mmhandgun
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
SUPERSHOT_IDLE,
|
||||
SUPERSHOT_SHOOT,
|
||||
};
|
||||
|
||||
#ifdef CLIENT
|
||||
void w_supershotgun_ejectshell(void)
|
||||
{
|
||||
static void w_supershotgun_ejectshell_death(void) {
|
||||
remove(self);
|
||||
}
|
||||
static void w_supershotgun_ejectshell_touch(void) {
|
||||
if (other == world)
|
||||
Sound_Play(self, CHAN_BODY, "modelevent_shell.land");
|
||||
}
|
||||
entity eShell = spawn();
|
||||
setmodel(eShell, "models/shell.mdl");
|
||||
eShell.solid = SOLID_BBOX;
|
||||
eShell.movetype = MOVETYPE_BOUNCE;
|
||||
eShell.drawmask = MASK_ENGINE;
|
||||
eShell.angles = [pSeat->m_eViewModel.angles[0], pSeat->m_eViewModel.angles[1], 0];
|
||||
eShell.velocity = pSeat->m_vecPredictedVelocity;
|
||||
|
||||
makevectors(pSeat->m_eViewModel.angles);
|
||||
eShell.velocity += (v_forward * 0);
|
||||
eShell.velocity += (v_right * 80);
|
||||
eShell.velocity += (v_up * 100);
|
||||
eShell.touch = w_supershotgun_ejectshell_touch;
|
||||
|
||||
eShell.avelocity = [0,45,900];
|
||||
eShell.think = w_supershotgun_ejectshell_death;
|
||||
eShell.nextthink = time + 2.5f;
|
||||
setsize(eShell, [0,0,0], [0,0,0]);
|
||||
setorigin(eShell, pSeat->m_eViewModel.origin + (v_forward * 26) + (v_right * 8) + (v_up * -4));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
w_supershotgun_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_supershotgun.shoot");
|
||||
precache_model("models/g_shot2.mdl");
|
||||
precache_model("models/shell.mdl");
|
||||
#else
|
||||
precache_model("models/v_shot2.mdl");
|
||||
precache_model("models/p_shot2.mdl");
|
||||
precache_model("models/shell.mdl");
|
||||
Sound_Precache("modelevent_shell.land");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_supershotgun_updateammo(player pl)
|
||||
{
|
||||
Weapons_UpdateAmmo(pl, -1, pl.ammo_shells, -1);
|
||||
}
|
||||
|
||||
string
|
||||
w_supershotgun_wmodel(void)
|
||||
{
|
||||
return "models/g_shot2.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_supershotgun_pmodel(player pl)
|
||||
{
|
||||
return "models/p_shot2.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_supershotgun_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
w_supershotgun_pickup(player pl, int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
if (pl.ammo_shells < MAX_A_SHELLS) {
|
||||
pl.ammo_shells = bound(0, pl.ammo_shells + 5, MAX_A_SHELLS);
|
||||
} else {
|
||||
if (!new)
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
w_supershotgun_draw(player pl)
|
||||
{
|
||||
Weapons_SetModel("models/v_shot2.mdl");
|
||||
Weapons_ViewAnimation(pl, SUPERSHOT_IDLE);
|
||||
}
|
||||
|
||||
void
|
||||
w_supershotgun_primary(player pl)
|
||||
{
|
||||
if (pl.w_attack_next > 0.0)
|
||||
return;
|
||||
|
||||
if (pl.ammo_shells < 2)
|
||||
return;
|
||||
|
||||
/* actual firing */
|
||||
pl.ammo_shells -= 2;
|
||||
|
||||
#ifdef CLIENT
|
||||
View_AddEvent(w_supershotgun_ejectshell, 0.0f);
|
||||
#else
|
||||
TraceAttack_FireBulletsWithDecal(14, pl.origin + pl.view_ofs, Skill_GetValue("plr_supershotgun_dmg", 4), [0.14,0.08], WEAPON_SUPERSHOTGUN, "Impact.BigShot");
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_supershotgun.shoot");
|
||||
#endif
|
||||
|
||||
Weapons_ViewPunchAngle(pl, [-2,0,0]);
|
||||
Weapons_ViewAnimation(pl, SUPERSHOT_SHOOT);
|
||||
Animation_PlayerTop(pl, (pl.flags & FL_CROUCHING) ? ANIM_CR_SHOOTSHOTGUN : ANIM_SHOOTSHOTGUN, 0.5f);
|
||||
|
||||
pl.w_attack_next = 0.7f;
|
||||
}
|
||||
|
||||
float
|
||||
w_supershotgun_aimanim(player pl)
|
||||
{
|
||||
return pl.flags & FL_CROUCHING ? ANIM_CR_AIMSHOTGUN : ANIM_AIMSHOTGUN;
|
||||
}
|
||||
|
||||
void
|
||||
w_supershotgun_hud(player pl)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector aicon_pos;
|
||||
|
||||
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
|
||||
|
||||
Cross_DrawSub(g_cross_spr, [24,24], [0.1875,0], [0.1875, 0.1875]);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
drawsubpic(aicon_pos, [24,24], g_hudssgammo, [0, 0], [1,1], g_hud_color, pSeatLocal->m_flAmmo2Alpha, DRAWFLAG_ADDITIVE);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
w_supershotgun_isempty(player pl)
|
||||
{
|
||||
if (pl.ammo_shells <= 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
w_supershotgun_hudpic(player pl, int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector hud_col;
|
||||
|
||||
if (w_supershotgun_isempty(pl))
|
||||
hud_col = [1,0,0];
|
||||
else
|
||||
hud_col = g_hud_color;
|
||||
|
||||
if (selected) {
|
||||
drawsubpic(pos, [170,45], g_hudssg_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
} else {
|
||||
drawsubpic(pos, [170,45], g_hudssg_spr, [0,0], [1,0.625], hud_col, a, DRAWFLAG_ADDITIVE);
|
||||
}
|
||||
|
||||
HUD_DrawAmmoBar(pos, pl.ammo_shells, MAX_A_SHELLS, a);
|
||||
#endif
|
||||
}
|
||||
|
||||
weapontype_t
|
||||
w_supershotgun_type(player pl)
|
||||
{
|
||||
return WPNTYPE_RANGED;
|
||||
}
|
||||
|
||||
weapon_t w_supershotgun =
|
||||
{
|
||||
.name = "doubleshotgun",
|
||||
.id = ITEM_SUPERSHOTGUN,
|
||||
.slot = 2,
|
||||
.slot_pos = 0,
|
||||
.weight = 5,
|
||||
.draw = w_supershotgun_draw,
|
||||
.holster = __NULL__,
|
||||
.primary = w_supershotgun_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = __NULL__,
|
||||
.postdraw = w_supershotgun_hud,
|
||||
.precache = w_supershotgun_precache,
|
||||
.pickup = w_supershotgun_pickup,
|
||||
.updateammo = w_supershotgun_updateammo,
|
||||
.wmodel = w_supershotgun_wmodel,
|
||||
.pmodel = w_supershotgun_pmodel,
|
||||
.deathmsg = w_supershotgun_deathmsg,
|
||||
.aimanim = w_supershotgun_aimanim,
|
||||
.isempty = w_supershotgun_isempty,
|
||||
.type = w_supershotgun_type,
|
||||
.hudpic = w_supershotgun_hudpic
|
||||
};
|
||||
|
||||
/* pickups */
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_supershotgun(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_SUPERSHOTGUN);
|
||||
}
|
||||
#endif
|
34
src/shared/weapons.h
Normal file
34
src/shared/weapons.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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_SHOTGUN,
|
||||
WEAPON_SUPERSHOTGUN,
|
||||
WEAPON_NAILGUN,
|
||||
WEAPON_SUPERNAILGUN,
|
||||
WEAPON_GRENADELAUNCHER,
|
||||
WEAPON_ROCKETLAUNCHER,
|
||||
WEAPON_LIGHTNING,
|
||||
};
|
||||
|
||||
#define MAX_A_SHELLS 100
|
||||
#define MAX_A_NAILS 200
|
||||
#define MAX_A_ROCKETS 100
|
||||
#define MAX_A_CELLS 100
|
28
src/shared/weapons.qc
Normal file
28
src/shared/weapons.qc
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Cawthorne <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_shotgun,
|
||||
w_supershotgun,
|
||||
w_nailgun,
|
||||
w_supernailgun,
|
||||
w_grenadelauncher,
|
||||
w_rocketlauncher,
|
||||
w_lightning
|
||||
};
|
19
zpak001.pk3dir/sound/items_dmc.sndshd
Normal file
19
zpak001.pk3dir/sound/items_dmc.sndshd
Normal file
|
@ -0,0 +1,19 @@
|
|||
armor.pickup
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
armor.respawn
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ammo.pickup
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ammo.respawn
|
||||
{
|
||||
|
||||
}
|
65
zpak001.pk3dir/sound/weapons_dmc.sndshd
Normal file
65
zpak001.pk3dir/sound/weapons_dmc.sndshd
Normal file
|
@ -0,0 +1,65 @@
|
|||
weapon_crowbar.swing
|
||||
{
|
||||
alerts
|
||||
sample weapons/ax1.wav
|
||||
}
|
||||
|
||||
weapon_crowbar.hitbody
|
||||
{
|
||||
alerts
|
||||
sample player/axhit1.wav
|
||||
}
|
||||
|
||||
weapon_crowbar.hit
|
||||
{
|
||||
alerts
|
||||
sample player/axhit2.wav
|
||||
}
|
||||
|
||||
weapon_shotgun.shoot
|
||||
{
|
||||
alerts
|
||||
sample weapons/guncock.wav
|
||||
}
|
||||
|
||||
weapon_supershotgun.shoot
|
||||
{
|
||||
alerts
|
||||
sample weapons/shotgn2.wav
|
||||
}
|
||||
|
||||
weapon_nailgun.shoot
|
||||
{
|
||||
alerts
|
||||
sample weapons/rocket1i.wav
|
||||
}
|
||||
|
||||
weapon_supernailgun.shoot
|
||||
{
|
||||
alerts
|
||||
sample weapons/spike2.wav
|
||||
}
|
||||
|
||||
weapon_grenadelauncher.shoot
|
||||
{
|
||||
alerts
|
||||
sample weapons/grenade.wav
|
||||
}
|
||||
|
||||
weapon_grenadelauncher.bounce
|
||||
{
|
||||
alerts
|
||||
sample weapons/bounce.wav
|
||||
}
|
||||
|
||||
weapon_rocketlauncher.shoot
|
||||
{
|
||||
alerts
|
||||
sample weapons/sgun1.wav
|
||||
}
|
||||
|
||||
weapon_lightning.start
|
||||
{
|
||||
alerts
|
||||
sample weapons/lstart.wav
|
||||
}
|
Loading…
Reference in a new issue