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

This commit is contained in:
Marco Cawthorne 2021-03-08 11:27:31 +01:00
commit a791238321
45 changed files with 5665 additions and 0 deletions

15
LICENSE Normal file
View File

@ -0,0 +1,15 @@
ISC License
Copyright (c) 2016-2021, Marco "eukara" Hladik <marco@icculus.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

37
README.md Normal file
View File

@ -0,0 +1,37 @@
# FreeSci
Clean-room reimplementation of Gunman Chronicles in QuakeC.
![Preview 1](img/preview1.jpg)
![Preview 2](img/preview2.jpg)
![Preview 3](img/preview3.jpg)
![Preview 4](img/preview4.jpg)
## Building
Clone the repository into the Nuclide-SDK:
> git clone REPOURL rewolf
then either run Nuclide's ./build_game.sh shell script, or issue 'make' inside
./rewolf/src!
Obviously make sure that Nuclide has fteqw and fteqcc set-up for building.
## Community
Join us on #halflife or #gunman via irc.frag-net.com and chat.
## License
ISC License
Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

BIN
img/preview1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

BIN
img/preview2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
img/preview3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
img/preview4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

5
src/Makefile Normal file
View File

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

4
src/client/Makefile Normal file
View File

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

184
src/client/decore.qc Normal file
View File

@ -0,0 +1,184 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class CBaseDecor:CBaseEntity
{
int m_iBody;
virtual void(string, string) SpawnKey;
};
void CBaseDecor::Initialized(void)
{
setmodel(this, model);
setorigin(this, origin);
setcustomskin(this, "", sprintf("geomset 0 %i\n", m_iBody));
drawmask = MASK_ENGINE;
}
void CBaseDecor::SpawnKey(string strField, string strKey)
{
switch (strField) {
case "body":
m_iBody = stoi(strKey);
break;
default:
CBaseEntity::SpawnKey(strField, strKey);
break;
}
}
/* Let's begin */
class decore_asteroid:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/asteroid.mdl";
CBaseDecor::Initialized();
};
};
class decore_baboon:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/baboon.mdl";
CBaseDecor::Initialized();
};
};
class decore_bodygib:CBaseDecor
{
void(void) decore_bodygib = {
model = "models/bodygib.mdl";
CBaseDecor::Initialized();
};
};
class decore_butterflyflock:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/butterfly.mdl";
CBaseDecor::Initialized();
};
};
class decore_explodable:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/EXPLODABLE!!!!";
CBaseDecor::Initialized();
};
};
class decore_foot:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/FOOT!!!!";
CBaseDecor::Initialized();
};
};
class decore_goldskull:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/goldskull.mdl";
CBaseDecor::Initialized();
};
};
class decore_hatgib:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/hatgib.mdl";
CBaseDecor::Initialized();
};
};
class decore_nest:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/ornest.mdl";
CBaseDecor::Initialized();
};
};
class decore_pteradon:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/pteradon2.mdl";
CBaseDecor::Initialized();
};
};
class decore_torch:CBaseDecor
{
virtual void(void) Initialized = {
precache_model("sprites/torch.spr");
model = "models/torch.mdl";
CBaseDecor::Initialized();
this.effects |= EF_FULLBRIGHT;
env_sprite flame = spawn(env_sprite);
setorigin(flame, origin + [0,0,24]);
setmodel(flame, "sprites/torch.spr");
flame.effects = EF_ADDITIVE;
flame.drawmask = MASK_ENGINE;
flame.maxframe = modelframecount(flame.modelindex);
flame.loops = 1;
flame.framerate = 10;
flame.nextthink = time + 0.05f;
};
};
class decore_spacedebris:CBaseDecor
{
virtual void(void) Initialized = {
CBaseDecor::Initialized();
};
virtual void(string strField, string strKey) SpawnKey = {
switch (strField) {
case "modelname":
model = strKey;
break;
default:
CBaseEntity::SpawnKey(strField, strKey);
break;
}
};
};
class decore_swampplants:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/swampstuff.mdl";
CBaseDecor::Initialized();
};
};
class decore_mushroom:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/mushroom.mdl";
CBaseDecor::Initialized();
};
};
class decore_mushroom2:CBaseDecor
{
virtual void(void) Initialized = {
model = "models/mushroom2.mdl";
CBaseDecor::Initialized();
};
};

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

@ -0,0 +1,26 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
int
ClientGame_EntityUpdate(float id, float new)
{
switch (id) {
default:
return FALSE;
}
return TRUE;
}

296
src/client/hud.qc Normal file
View File

@ -0,0 +1,296 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Use first frame for drawing (needs precache) */
#define HUD_NUMS "sprites/640hud7.spr_0.tga"
#define GM_NUMS "sprites/numbers.spr_0.tga"
#define HUD_ALPHA 0.5
/* New Gunman digits */
#define NUMSIZE_X 18/256
#define NUMSIZE_Y 32/32
float spr_hudnum[10] = {
0 / 256,
18 / 256,
(18*2) / 256,
(18*3) / 256,
(18*4) / 256,
(18*5) / 256,
(18*6) / 256,
(18*7) / 256,
(18*8) / 256,
(18*9) / 256
};
void HUD_DrawWeaponSelect(void);
void
HUD_Init(void)
{
precache_model("sprites/640hud1.spr");
precache_model("sprites/640hud2.spr");
precache_model("sprites/640hud3.spr");
precache_model("sprites/640hud4.spr");
precache_model("sprites/640hud5.spr");
precache_model("sprites/640hud6.spr");
precache_model("sprites/640hud7.spr");
precache_model("sprites/numbers.spr");
precache_model("sprites/armor.spr");
precache_model("sprites/hudpulse.spr");
precache_pic("gfx/vgui/640_metalhud_small.tga");
precache_pic("gfx/vgui/640_metalhud.tga");
}
/*
=================
HUD_DrawNumber
Draws a normal number
=================
*/
void
HUD_DrawNumber(int iNumber, vector vecPos, float fAlpha, vector vColor)
{
drawsubpic(vecPos, [18,32], GM_NUMS, [spr_hudnum[iNumber], 0],
[NUMSIZE_X, NUMSIZE_Y], vColor, fAlpha, DRAWFLAG_ADDITIVE);
}
void
HUD_DrawSeperator(vector pos)
{
drawsubpic(pos, [2,24], HUD_NUMS, [240/256, 0],
[2/256, 24/128], g_hud_color, HUD_ALPHA, DRAWFLAG_ADDITIVE);
}
/*
=================
HUD_DrawNums
Draws numerals quickly for health, armor etc.
=================
*/
void
HUD_DrawNums(float fNumber, vector vecPos, float fAlpha, vector vColor)
{
int iNumber = fNumber;
if (iNumber > 0) {
while (iNumber > 0) {
HUD_DrawNumber((float)iNumber % 10, vecPos, fAlpha, vColor);
iNumber = iNumber / 10;
vecPos[0] -= 20;
}
} else {
HUD_DrawNumber(0, vecPos, fAlpha, vColor);
}
}
/*
=================
HUD_DrawHealth
Draw the current amount of health
=================
*/
void
HUD_DrawHealth(void)
{
vector pos;
vector hcol;
player pl;
pl = (player)pSeat->m_ePlayer;
/* Shift digits by 128 units for the larger HUD */
if (g_hudres[0] <= 640) {
pos = g_hudmins + [0, g_hudres[1] - 128];
} else {
pos = g_hudmins + [128, g_hudres[1] - 128];
}
/* Obligatory low-health color tint */
if (pl.health <= 25) {
hcol = [1,0,0];
} else {
hcol = [0,1,1];
}
/* Because we've got little space, the number 100 is its own graphic */
if (pl.health >= 100) {
drawsubpic(pos+[34,30], [42,32], GM_NUMS, [192/256, 0],
[42/256, 32/32], hcol, 1.0f, DRAWFLAG_ADDITIVE);
} else {
HUD_DrawNums(pl.health, pos + [56,30], 1.0f, hcol);
}
if (pl.armor >= 100) {
drawsubpic(pos+[34,64], [42,32], GM_NUMS, [192/256, 0],
[42/256, 32/32], [0,1,0], 1.0f, DRAWFLAG_ADDITIVE);
} else {
HUD_DrawNums(pl.armor, pos + [56,64], 1.0f, [0,1,0]);
}
/* Minimal VS Larger HUD */
if (g_hudres[0] <= 640) {
drawpic(pos, "gfx/vgui/640_metalhud_small.tga", [128,128],
[1,1,1], 1.0f);
} else {
pos[0] -= 128;
/* Armor bar */
float ap = pl.armor / 100;
if (ap) {
drawsubpic(pos+[28,18], [95*ap,32], "sprites/armor.spr_0.tga",
[0, 0], [0.7421875*ap, 1], [1,1,1], 1.0f, DRAWFLAG_NORMAL);
}
/* Health, TODO: make it scroll */
if (pl.health <= 20) {
drawpic(pos + [35,53], "sprites/hudpulse.spr_4.tga", [128,32],
[1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
} else if (pl.health <= 40) {
drawpic(pos + [35,53], "sprites/hudpulse.spr_3.tga", [128,32],
[1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
} else if (pl.health <= 60) {
drawpic(pos + [35,53], "sprites/hudpulse.spr_2.tga", [128,32],
[1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
} else if (pl.health <= 80) {
drawpic(pos + [35,53], "sprites/hudpulse.spr_1.tga", [128,32],
[1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
} else {
drawpic(pos + [35,53], "sprites/hudpulse.spr_0.tga", [128,32],
[1,1,1], 1.0f, DRAWFLAG_ADDITIVE);
}
drawpic(pos, "gfx/vgui/640_metalhud.tga", [256,128], [1,1,1], 1.0f);
}
}
void
HUD_DrawAmmo1(void)
{
player pl = (player)pSeat->m_ePlayer;
vector pos;
static int old_ammo1;
static float m_flAmmo1Alpha;
if (pl.a_ammo1 != old_ammo1) {
m_flAmmo1Alpha = 1.0;
old_ammo1 = pl.a_ammo1;
}
if (m_flAmmo1Alpha >= HUD_ALPHA) {
m_flAmmo1Alpha -= clframetime * 0.5;
} else {
m_flAmmo1Alpha = HUD_ALPHA;
}
pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
/* Magazine/Clip */
if (pl.a_ammo1 != -1) {
HUD_DrawNums(pl.a_ammo1, pos + [-80,0], m_flAmmo1Alpha, g_hud_color);
}
HUD_DrawSeperator(pos + [-50,0]);
}
void
HUD_DrawAmmo2(void)
{
player pl = (player)pSeat->m_ePlayer;
vector pos;
static int old_ammo2;
static float m_flAmmo2Alpha;
if (pl.a_ammo2 != old_ammo2) {
m_flAmmo2Alpha = 1.0;
old_ammo2 = pl.a_ammo2;
}
if (m_flAmmo2Alpha >= HUD_ALPHA) {
m_flAmmo2Alpha -= clframetime * 0.5;
} else {
m_flAmmo2Alpha = HUD_ALPHA;
}
pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
/* Leftover Ammo */
HUD_DrawNums(pl.a_ammo2, pos, m_flAmmo2Alpha, g_hud_color);
}
void
HUD_DrawAmmo3(void)
{
player pl = (player)pSeat->m_ePlayer;
vector pos;
static int old_ammo3;
static float m_flAmmo3Alpha;
if (pl.a_ammo3 != old_ammo3) {
m_flAmmo3Alpha = 1.0;
old_ammo3 = pl.a_ammo3;
}
if (m_flAmmo3Alpha >= HUD_ALPHA) {
m_flAmmo3Alpha -= clframetime * 0.5;
} else {
m_flAmmo3Alpha = HUD_ALPHA;
}
pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
/* Special */
if (pl.a_ammo3) {
HUD_DrawNums(pl.a_ammo3, pos + [0, -32], m_flAmmo3Alpha, g_hud_color);
}
}
void
HUD_DrawAmmoBar(vector pos, float val, float max, float a)
{
}
void
HUD_WeaponPickupNotify(int w)
{
}
void
HUD_Draw(void)
{
g_hud_color = autocvar_con_color * (1 / 255);
Textmenu_Draw();
Obituary_Draw();
Damage_Draw();
HUD_DrawHealth();
Weapons_DrawCrosshair();
HUD_DrawWeaponSelect();
}
void
HUD_DrawSpectator(void)
{
// FIXME
Textmenu_Draw();
}

View File

@ -0,0 +1,236 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
vector g_vecHUDNums[6] =
{
[168 / 256, 72 / 128],
[188 / 256, 72 / 128],
[208 / 256, 72 / 128],
[168 / 256, 92 / 128],
[188 / 256, 92 / 128],
[208 / 256, 92 / 128]
};
void
HUD_DrawWeaponSelect_Forward(void)
{
player pl = (player)pSeat->m_ePlayer;
if (!pl.activeweapon) {
return;
}
if (Weapons_InputForward(pl) == FALSE) {
return;
}
if (pSeat->m_flHUDWeaponSelectTime < time) {
pSeat->m_iHUDWeaponSelected = pl.activeweapon;
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
} else {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
pSeat->m_iHUDWeaponSelected--;
if (pSeat->m_iHUDWeaponSelected <= 0) {
pSeat->m_iHUDWeaponSelected = g_weapons.length - 1;
}
}
pSeat->m_flHUDWeaponSelectTime = time + 3;
if not (pl.g_items & g_weapons[pSeat->m_iHUDWeaponSelected].id) {
HUD_DrawWeaponSelect_Forward();
}
}
void
HUD_DrawWeaponSelect_Back(void)
{
player pl = (player)pSeat->m_ePlayer;
if (!pl.activeweapon) {
return;
}
if (Weapons_InputBack(pl) == FALSE) {
return;
}
if (pSeat->m_flHUDWeaponSelectTime < time) {
pSeat->m_iHUDWeaponSelected = pl.activeweapon;
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
} else {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
pSeat->m_iHUDWeaponSelected++;
if (pSeat->m_iHUDWeaponSelected >= g_weapons.length) {
pSeat->m_iHUDWeaponSelected = 1;
}
}
pSeat->m_flHUDWeaponSelectTime = time + 3;
if not (pl.g_items & g_weapons[pSeat->m_iHUDWeaponSelected].id) {
HUD_DrawWeaponSelect_Back();
}
}
void
HUD_DrawWeaponSelect_Trigger(void)
{
player pl = (player)pSeat->m_ePlayer;
pl.activeweapon = pSeat->m_iHUDWeaponSelected;
sendevent("PlayerSwitchWeapon", "i", pSeat->m_iHUDWeaponSelected);
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_select.wav", 0.5f, ATTN_NONE);
pSeat->m_iHUDWeaponSelected = pSeat->m_flHUDWeaponSelectTime = 0;
}
void
HUD_DrawWeaponSelect_Last(void)
{
player pl = (player)pSeat->m_ePlayer;
if (pl.g_items & g_weapons[pSeat->m_iOldWeapon].id) {
pl.activeweapon = pSeat->m_iOldWeapon;
sendevent("PlayerSwitchWeapon", "i", pSeat->m_iOldWeapon);
}
}
void
HUD_DrawWeaponSelect_Num(vector vecPos, float fValue)
{
drawsubpic(vecPos, [20,20], "sprites/640hud7.spr_0.tga", g_vecHUDNums[fValue], [20/256, 20/128], g_hud_color, 1, DRAWFLAG_ADDITIVE);
}
int
HUD_InSlotPos(int slot, int pos)
{
player pl = (player)pSeat->m_ePlayer;
for (int i = 1; i < g_weapons.length; i++) {
if (g_weapons[i].slot == slot && g_weapons[i].slot_pos == pos) {
if (pl.g_items & g_weapons[i].id) {
return i;
} else {
return -1;
}
}
}
return -1;
}
void
HUD_SlotSelect(int slot)
{
player pl = (player)pSeat->m_ePlayer;
int curslot = g_weapons[pSeat->m_iHUDWeaponSelected].slot;
int i;
if (g_textmenu != "") {
Textmenu_Input(slot);
return;
}
/* hack to see if we have ANY weapons at all. */
if (!pl.activeweapon) {
return;
}
if (pSeat->m_flHUDWeaponSelectTime < time) {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudon.wav", 0.5, ATTN_NONE);
} else {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_moveselect.wav", 0.5, ATTN_NONE);
}
/* weren't in that slot? select the first one then */
if (curslot != slot) {
for (i = 1; i < g_weapons.length; i++) {
if (g_weapons[i].slot == slot && pl.g_items & g_weapons[i].id) {
pSeat->m_iHUDWeaponSelected = i;
pSeat->m_flHUDWeaponSelectTime = time + 3;
break;
}
}
} else {
int first = -1;
for (i = 1; i < g_weapons.length; i++) {
if (g_weapons[i].slot == slot && pl.g_items & g_weapons[i].id) {
if (i < pSeat->m_iHUDWeaponSelected && first == -1) {
first = i;
} else if (i > pSeat->m_iHUDWeaponSelected) {
first = -1;
pSeat->m_iHUDWeaponSelected = i;
pSeat->m_flHUDWeaponSelectTime = time + 3;
break;
}
}
}
if (first > 0) {
pSeat->m_iHUDWeaponSelected = first;
pSeat->m_flHUDWeaponSelectTime = time + 3;
}
}
}
void
HUD_DrawWeaponSelect(void)
{
player pl = (player)pSeat->m_ePlayer;
if (!pl.activeweapon) {
return;
}
if (pSeat->m_flHUDWeaponSelectTime < time) {
if (pSeat->m_iHUDWeaponSelected) {
sound(pSeat->m_ePlayer, CHAN_ITEM, "common/wpn_hudoff.wav", 0.5, ATTN_NONE);
pSeat->m_iHUDWeaponSelected = 0;
}
return;
}
vector vecPos = g_hudmins + [16,16];
int b;
int wantslot = g_weapons[pSeat->m_iHUDWeaponSelected].slot;
int wantpos = g_weapons[pSeat->m_iHUDWeaponSelected].slot_pos;
for (int i = 0; i < 5; i++) {
int slot_selected = 0;
vecPos[1] = g_hudmins[1] + 16;
HUD_DrawWeaponSelect_Num(vecPos, i);
vecPos[1] += 20;
for (int x = 0; x < 32; x++) {
if (i == wantslot) {
slot_selected = TRUE;
if (x == wantpos) {
// Selected Sprite
Weapons_HUDPic(pSeat->m_iHUDWeaponSelected, 1, vecPos, 1.0f);
drawsubpic(vecPos, [170,45], "sprites/640hud3.spr_0.tga",
[0,180/256], [170/256,45/256], g_hud_color, 1, DRAWFLAG_ADDITIVE);
vecPos[1] += 50;
} else if ((b=HUD_InSlotPos(i, x)) != -1) {
// Unselected Sprite
Weapons_HUDPic(b, 0, vecPos, 1.0f);
vecPos[1] += 50;
}
} else if (HUD_InSlotPos(i, x) != -1) {
HUD_DrawWeaponSelect_Num(vecPos, 5);
vecPos[1] += 25;
}
}
if (slot_selected == TRUE) {
vecPos[0] += 175;
} else {
vecPos[0] += 25;
}
}
}

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

@ -0,0 +1,48 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
=================
ClientGame_Init
Comparable to worldspawn in SSQC in that it's mostly used for precaches
=================
*/
void
ClientGame_Init(float apilevel, string enginename, float engineversion)
{
Obituary_Init();
}
void
ClientGame_InitDone(void)
{
}
void
ClientGame_RendererRestart(string rstr)
{
Obituary_Precache();
FX_Blood_Init();
FX_BreakModel_Init();
FX_Explosion_Init();
FX_GibHuman_Init();
FX_Spark_Init();
FX_Impact_Init();
BEAM_TRIPMINE = particleeffectnum("weapon_tripmine.beam");
}

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

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

2
src/progs.src Executable file
View File

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

4
src/server/Makefile Normal file
View File

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

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

@ -0,0 +1,146 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_playerkeepalive = TRUE;
void
HLGameRules::LevelDecodeParms(base_player pp)
{
player pl = (player)pp;
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.flags = parm64;
/*pl.ammo_9mm = parm12;
pl.ammo_357 = parm13;
pl.ammo_buckshot = parm14;
pl.ammo_m203_grenade = parm15;
pl.ammo_bolt = parm16;
pl.ammo_rocket = parm17;
pl.ammo_uranium = parm18;
pl.ammo_handgrenade = parm19;
pl.ammo_satchel = parm20;
pl.ammo_tripmine = parm21;
pl.ammo_snark = parm22;
pl.ammo_hornet = parm23;
pl.glock_mag = parm24;
pl.mp5_mag = parm25;
pl.python_mag = parm26;
pl.shotgun_mag = parm27;
pl.crossbow_mag = parm28;
pl.rpg_mag = parm29;
pl.satchel_chg = parm30;*/
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
}
}
void
HLGameRules::LevelChangeParms(base_player pp)
{
player pl = (player)pp;
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm64 = pl.flags;
parm10 = pl.g_items;
parm11 = pl.activeweapon;
/*parm12 = pl.ammo_9mm;
parm13 = pl.ammo_357;
parm14 = pl.ammo_buckshot;
parm15 = pl.ammo_m203_grenade;
parm16 = pl.ammo_bolt;
parm17 = pl.ammo_rocket;
parm18 = pl.ammo_uranium;
parm19 = pl.ammo_handgrenade;
parm20 = pl.ammo_satchel;
parm21 = pl.ammo_tripmine;
parm22 = pl.ammo_snark;
parm23 = pl.ammo_hornet;
parm24 = pl.glock_mag;
parm25 = pl.mp5_mag;
parm26 = pl.python_mag;
parm27 = pl.shotgun_mag;
parm28 = pl.crossbow_mag;
parm29 = pl.rpg_mag;
parm30 = pl.satchel_chg;*/
}
void
HLGameRules::LevelNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm64 = FL_CLIENT;
}
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
HLGameRules::PlayerPostFrame(base_player pp)
{
Animation_PlayerUpdate();
}
void
HLGameRules::PlayerConnect(base_player pl)
{
if (Plugin_PlayerConnect(pl) == FALSE)
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname));
}
void
HLGameRules::PlayerDisconnect(base_player pl)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = PLAYER_MODELINDEX;
}
void
HLGameRules::PlayerKill(base_player pp)
{
player pl = (player)pp;
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
HLMultiplayerRules::FrameStart(void)
{
if (cvar("mp_timelimit") != 0)
if (time >= (cvar("mp_timelimit") * 60)) {
IntermissionStart();
}
}
void
HLMultiplayerRules::PlayerDeath(base_player pp)
{
player pl = (player)pp;
pl.movetype = MOVETYPE_NONE;
pl.solid = SOLID_NOT;
pl.takedamage = DAMAGE_NO;
pl.gflags &= ~GF_FLASHLIGHT;
pl.armor = pl.activeweapon = pl.g_items = 0;
pl.think = PutClientInServer;
pl.nextthink = time + 4.0f;
if (pl.health < -50) {
pl.health = 0;
FX_GibHuman(pl.origin);
return;
}
pl.health = 0;
/* Let's handle corpses on the clientside */
entity corpse = spawn();
setorigin(corpse, pl.origin + [0,0,32]);
setmodel(corpse, pl.model);
setsize(corpse, VEC_HULL_MIN, VEC_HULL_MAX);
corpse.movetype = MOVETYPE_TOSS;
corpse.solid = SOLID_TRIGGER;
corpse.modelindex = pl.modelindex;
corpse.frame = ANIM_DIESIMPLE;
corpse.angles = pl.angles;
corpse.velocity = pl.velocity;
}
void
HLMultiplayerRules::PlayerSpawn(base_player pp)
{
player pl = (player)pp;
/* this is where the mods want to deviate */
entity spot;
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
LevelNewParms();
LevelDecodeParms(pl);
/*pl.g_items = ITEM_CROWBAR | ITEM_GLOCK | ITEM_SUIT;
pl.activeweapon = WEAPON_GLOCK;
pl.glock_mag = 18;
pl.ammo_9mm = 44;*/
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
float
HLMultiplayerRules::ConsoleCommand(base_player pp, string cmd)
{
tokenize(cmd);
switch (argv(0)) {
case "bot_add":
Bot_AddQuick();
break;
default:
return FALSE;
}
return TRUE;
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class gunman_cycler:cycler
{
};

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class hologram_damage:CBaseNPC
{
int m_iType;
void(void) hologram_damage;
virtual void(void) Respawn;
virtual void(string, string) SpawnKey;
};
void
hologram_damage::Respawn(void)
{
SetRenderMode(RM_ADDITIVE);
switch (m_iType) {
case 1:
model = "models/tube.mdl";
break;
case 2:
model = "models/raptor.mdl";
break;
default:
model = "models/beak.mdl";
}
SetModel(model);
}
void
hologram_damage::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
case "creaturetype":
m_iType = stoi(strValue);
break;
default:
CBaseNPC::SpawnKey(strKey, strValue);
}
}
void
hologram_damage::hologram_damage(void)
{
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
}

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

@ -0,0 +1,67 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
Game_Input(void)
{
if (input_buttons & INPUT_BUTTON0) {
Weapons_Primary();
} else if (input_buttons & INPUT_BUTTON4) {
Weapons_Reload();
} else if (input_buttons & INPUT_BUTTON3) {
Weapons_Secondary();
} else {
Weapons_Release();
}
if (input_buttons & INPUT_BUTTON5) {
Player_UseDown();
} else {
Player_UseUp();
}
if (self.impulse == 100) {
Flashlight_Toggle();
}
if (cvar("sv_cheats") == 1) {
player pl = (player)self;
if (self.impulse == 101) {
pl.health = 100;
pl.armor = 100;
Weapons_AddItem(pl, WEAPON_FISTS, -1);
Weapons_AddItem(pl, WEAPON_GAUSSPISTOL, -1);
Weapons_AddItem(pl, WEAPON_BEAMGUN, -1);
Weapons_AddItem(pl, WEAPON_CHEMICALGUN, -1);
Weapons_AddItem(pl, WEAPON_DML, -1);
Weapons_AddItem(pl, WEAPON_MINIGUN, -1);
Weapons_AddItem(pl, WEAPON_AICORE, -1);
Weapons_AddItem(pl, WEAPON_SHOTGUN, -1);
Weapons_AddItem(pl, WEAPON_GRENADE, -1);
}
if (self.impulse == 102) {
// Respawn all the entities
for (entity a = world; (a = findfloat(a, ::identity, 1));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
bprint(PRINT_HIGH, "Respawning all map entities...\n");
}
}
self.impulse = 0;
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class monster_human_bandit:CBaseNPC
{
void(void) monster_human_bandit;
};
void monster_human_bandit::monster_human_bandit(void)
{
model = "models/bandit.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class monster_human_chopper:CBaseNPC
{
void(void) monster_human_chopper;
};
void monster_human_chopper::monster_human_chopper(void)
{
model = "models/chopper.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class monster_human_demoman:CBaseNPC
{
void(void) monster_human_demoman;
};
void monster_human_demoman::monster_human_demoman(void)
{
model = "models/demolitionman.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class monster_human_gunman:CBaseNPC
{
void(void) monster_human_gunman;
};
void monster_human_gunman::monster_human_gunman(void)
{
model = "models/gunmantrooper.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class monster_human_unarmed:CBaseNPC
{
void(void) monster_human_unarmed;
};
void monster_human_unarmed::monster_human_unarmed(void)
{
model = "models/gunmantrooper.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
}

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class monster_trainingbot:CBaseNPC
{
void(void) monster_trainingbot;
};
void monster_trainingbot::monster_trainingbot(void)
{
model = "models/gunmantrooper.mdl";
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
}

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

@ -0,0 +1,54 @@
#pragma target fte
#pragma progs_dat "../../progs.dat"
#define QWSSQC
#define SERVER
#define VALVE
#define REWOLF
#define GS_RENDERFX
#includelist
../../../src/shared/fteextensions.qc
../../../src/gs-entbase/server/defs.h
../../../src/shared/defs.h
../../../src/server/defs.h
../../../src/gs-entbase/server.src
../../../src/gs-entbase/shared.src
../shared/include.src
../../../valve/src/server/defs.h
gunman_cycler.qc
hologram_damage.qc
monster_human_bandit.qc
monster_human_chopper.qc
monster_human_demoman.qc
monster_human_gunman.qc
monster_human_unarmed.qc
monster_trainingbot.qc
../../../valve/src/server/player.qc
../../../valve/src/server/spectator.qc
../../../valve/src/server/items.qc
../../../src/botlib/include.src
gamerules.qc
../../../valve/src/server/gamerules_singleplayer.qc
gamerules_multiplayer.qc
../../../valve/src/server/client.qc
../../../valve/src/server/server.qc
../../../valve/src/server/damage.qc
../../../valve/src/server/rules.qc
../../../valve/src/server/flashlight.qc
../../../base/src/server/modelevent.qc
input.qc
../../../valve/src/server/spawn.qc
../../../src/server/include.src
../../../src/shared/include.src
#endlist

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

@ -0,0 +1,30 @@
#includelist
../../../valve/src/shared/flags.h
player.qc
../../../valve/src/shared/weapon_common.h
../../../valve/src/shared/animations.h
../../../valve/src/shared/animations.qc
../../../valve/src/shared/pmove.qc
../../../valve/src/shared/pmove_water.qc
../../../valve/src/shared/fx_blood.qc
../../../valve/src/shared/fx_breakmodel.qc
../../../valve/src/shared/fx_explosion.qc
../../../valve/src/shared/fx_gibhuman.qc
../../../valve/src/shared/fx_spark.qc
../../../valve/src/shared/fx_impact.qc
items.h
weapons.h
w_fists.qc
w_gausspistol.qc
w_grenade.qc
w_shotgun.qc
w_beamgun.qc
w_chemicalgun.qc
w_dml.qc
w_minigun.qc
w_aicore.qc
weapons.qc
../../../valve/src/shared/weapon_common.qc
#endlist

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

@ -0,0 +1,51 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define ITEM_FISTS 0x00000001i
#define ITEM_GAUSSPISTOL 0x00000002i
#define ITEM_BEAMGUN 0x00000004i
#define ITEM_CHEMICALGUN 0x00000008i
#define ITEM_DML 0x00000010i
#define ITEM_MINIGUN 0x00000020i
#define ITEM_AICORE 0x00000040i
#define ITEM_GRENADE 0x00000080i
#define ITEM_SHOTGUN 0x00000100i
#define ITEM_GAUSSADDON 0x00000200i
#define ITEM_UNUSED11 0x00000400i
#define ITEM_UNUSED12 0x00000800i
#define ITEM_UNUSED13 0x00001000i
#define ITEM_UNUSED14 0x00002000i
#define ITEM_SUIT 0x00004000i
#define ITEM_LONGJUMP 0x00008000i
#define ITEM_UNUSED17 0x00010000i
#define ITEM_UNUSED18 0x00020000i
#define ITEM_UNUSED19 0x00040000i
#define ITEM_UNUSED20 0x00080000i
#define ITEM_UNUSED21 0x00100000i
#define ITEM_UNUSED22 0x00200000i
#define ITEM_UNUSED23 0x00400000i
#define ITEM_UNUSED24 0x00800000i
#define ITEM_UNUSED25 0x01000000i
#define ITEM_UNUSED26 0x02000000i
#define ITEM_UNUSED27 0x04000000i
#define ITEM_UNUSED28 0x08000000i
#define ITEM_UNUSED29 0x10000000i
#define ITEM_UNUSED30 0x20000000i
#define ITEM_UNUSED31 0x40000000i
#define ITEM_UNUSED32 0x80000000i

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

@ -0,0 +1,582 @@
/*
* Copyright (c) 2016-2021 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* all potential SendFlags bits we can possibly send */
enumflags
{
PLAYER_KEEPALIVE,
PLAYER_MODELINDEX,
PLAYER_ORIGIN,
PLAYER_ORIGIN_Z,
PLAYER_ANGLES_X,
PLAYER_ANGLES_Y,
PLAYER_ANGLES_Z,
PLAYER_VELOCITY,
PLAYER_VELOCITY_Z,
PLAYER_FLAGS,
PLAYER_WEAPON,
PLAYER_ITEMS,
PLAYER_HEALTH,
PLAYER_ARMOR,
PLAYER_MOVETYPE,
PLAYER_VIEWOFS,
PLAYER_BASEFRAME,
PLAYER_FRAME,
PLAYER_AMMO1,
PLAYER_AMMO2,
PLAYER_AMMO3,
PLAYER_UNUSED1,
PLAYER_UNUSED2
};
noref int input_sequence;
class player:base_player
{
/* Weapon specific */
int ammo_battery; int ammo_battery_net; // beamgun
int ammo_chem; int ammo_chem_net; // chemicalgun
int ammo_rocket; int ammo_rocket_net; // dml / grenades
int ammo_gauss; int ammo_gauss_net; // gauspistol
int ammo_minigun; int ammo_minigun_net; // minigun
int ammo_buckshot; int ammo_buckshot_net; // shotgun
int fist_mode; int fist_mode_net; // knife/fists
int gauss_mode; int gauss_mode_net;
int shotgun_shells; int shotgun_shells_net;
int shotgun_spread; int shotgun_spread_net;
int dml_launch; int dml_launch_net; /* when fired, when targeted */
int dml_flightpath; int dml_flightpath_net; /* guided, homing, spiral */
int dml_detonate; int dml_detonate_net; /* on impact, in proximity, timed, when tripped */
int dml_payload; int dml_payload_net; /* explosive, cluster */
int chem_acid; int chem_acid_net;
int chem_neutral; int chem_neutral_net;
int chem_base; int chem_base_net;
int chem_pressure; int chem_pressure_net;
int beam_range; int beam_range_net; /* TOUCH TAZER, SHORT TAZER, MEDIUM BEAM, LONG BEAM */
int beam_poweracc; int beam_poweracc_net; /* LOW HIGHEST, MEDIUM HIGH, HIGH MEDIUM, HIGHEST LOW */
int beam_lightning; int beam_lightning_net; /* BEAM, CHAIN, BALL */
int gren_detonate; int gren_detonate_net; /* when tripped (tripmine), timed, on impact */
int gren_payload; int gren_payload_net; /* cluster, explosive */
int menu_active; int menu_active_net;
int dml_state; int dml_state_net;
#ifdef CLIENT
/* External model */
entity p_model;
int p_hand_bone;
int p_model_bone;
float lastweapon;
virtual void(void) gun_offset;
virtual void(void) draw;
virtual float() predraw;
virtual void(void) postdraw;
virtual void(float) ReceiveEntity;
virtual void(void) PredictPreFrame;
virtual void(void) PredictPostFrame;
#else
virtual void(void) EvaluateEntity;
virtual float(entity, float) SendEntity;
#endif
};
#ifdef CLIENT
void Weapons_AmmoUpdate(entity);
/*
=================
player::ReceiveEntity
=================
*/
void
player::ReceiveEntity(float new)
{
float fl;
if (new == FALSE) {
/* Go through all the physics code between the last received frame
* and the newest frame and keep the changes this time around instead
* of rolling back, because we'll apply the new server-verified values
* right after anyway. */
/* FIXME: splitscreen */
if (entnum == player_localentnum) {
/* FIXME: splitscreen */
pSeat = &g_seats[0];
for (int i = sequence+1; i <= servercommandframe; i++) {
/* ...maybe the input state is too old? */
if (!getinputstate(i)) {
break;
}
input_sequence = i;
PMove_Run();
}
/* any differences in things that are read below are now
* officially from prediction misses. */
}
}
/* seed for our prediction table */
sequence = servercommandframe;
fl = readfloat();
/* HACK: we need to make this more reliable */
if (fl == UPDATE_ALL) {
/* we respawned */
gravity = __NULL__;
}
if (fl & PLAYER_MODELINDEX)
modelindex = readshort();
if (fl & PLAYER_ORIGIN) {
origin[0] = readcoord();
origin[1] = readcoord();
}
if (fl & PLAYER_ORIGIN_Z)
origin[2] = readcoord();
if (fl & PLAYER_ANGLES_X)
pitch = readfloat();
if (fl & PLAYER_ANGLES_Y)
angles[1] = readfloat();
if (fl & PLAYER_ANGLES_Z)
angles[2] = readfloat();
if (fl & PLAYER_VELOCITY) {
velocity[0] = readcoord();
velocity[1] = readcoord();
}
if (fl & PLAYER_VELOCITY_Z)
velocity[2] = readcoord();
if (fl & PLAYER_FLAGS) {
flags = readfloat();
gflags = readfloat();
}
if (fl & PLAYER_WEAPON)
activeweapon = readbyte();
if (fl & PLAYER_ITEMS)
g_items = (__variant)readfloat();
if (fl & PLAYER_HEALTH)
health = readbyte();
if (fl & PLAYER_ARMOR)
armor = readbyte();
if (fl & PLAYER_MOVETYPE)
movetype = readbyte();
if (fl & PLAYER_VIEWOFS)
view_ofs[2] = readfloat();
if (fl & PLAYER_BASEFRAME)
baseframe = readbyte();
if (fl & PLAYER_FRAME) {
frame = readbyte();
frame1time = 0.0f;
frame2time = 0.0f;
}
if (fl & PLAYER_AMMO1) {
ammo_battery = readbyte();
ammo_chem = readbyte();
ammo_rocket = readbyte();
ammo_gauss = readbyte();
ammo_minigun = readbyte();
ammo_buckshot = readbyte();
fist_mode = readbyte();
gauss_mode = readbyte();
shotgun_shells = readbyte();
shotgun_spread = readbyte();
}
if (fl & PLAYER_AMMO2) {
dml_launch = readbyte();
dml_flightpath = readbyte();
dml_detonate = readbyte();
dml_payload = readbyte();
chem_acid = readbyte();
chem_neutral = readbyte();
chem_base = readbyte();
chem_pressure = readbyte();
}
if (fl & PLAYER_AMMO3) {
beam_range = readbyte();
beam_poweracc = readbyte();
beam_lightning = readbyte();
gren_detonate = readbyte();
gren_payload = readbyte();
menu_active = readbyte();
dml_state = readbyte();
}
if (fl & PLAYER_AMMO1 || fl & PLAYER_AMMO2 || fl & PLAYER_AMMO3)
Weapons_AmmoUpdate(this);
setorigin(this, origin);
}
/*
=================
player::PredictPostFrame
Save the last valid server values away in the _net variants of each field
so we can roll them back later.
=================
*/
void
player::PredictPreFrame(void)
{
ammo_battery_net = ammo_battery; // beamgun
ammo_chem_net = ammo_chem; // chemicalgun
ammo_rocket_net = ammo_rocket; // dml / grenades
ammo_gauss_net = ammo_gauss; // gauspistol
ammo_minigun_net = ammo_minigun; // minigun
ammo_buckshot_net = ammo_buckshot; // shotgun
fist_mode_net = fist_mode; // knife/fists
gauss_mode_net = gauss_mode;
shotgun_shells_net = shotgun_shells;
shotgun_spread_net = shotgun_spread;
dml_launch_net = dml_launch; /* when fired, when targeted */
dml_flightpath_net = dml_flightpath; /* guided, homing, spiral */
dml_detonate_net = dml_detonate; /* on impact, in proximity, timed, when tripped */
dml_payload_net = dml_payload; /* explosive, cluster */
chem_acid_net = chem_acid;
chem_neutral_net = chem_neutral;
chem_base_net = chem_base;
chem_pressure_net = chem_pressure;
beam_range_net = beam_range; /* TOUCH TAZER, SHORT TAZER, MEDIUM BEAM, LONG BEAM */
beam_poweracc_net = beam_poweracc; /* LOW HIGHEST, MEDIUM HIGH, HIGH MEDIUM, HIGHEST LOW */
beam_lightning_net = beam_lightning; /* BEAM, CHAIN, BALL */
gren_detonate_net = gren_detonate; /* when tripped (tripmine), timed, on impact */
gren_payload_net = gren_payload; /* cluster, explosive */
menu_active_net = menu_active;
dml_state_net = dml_state;
}
/*
=================
player::PredictPostFrame
Where we roll back our values to the ones last sent/verified by the server.
=================
*/
void
player::PredictPostFrame(void)
{
ammo_battery = ammo_battery_net; // beamgun
ammo_chem = ammo_chem_net; // chemicalgun
ammo_rocket = ammo_rocket_net; // dml / grenades
ammo_gauss = ammo_gauss_net; // gauspistol
ammo_minigun = ammo_minigun_net; // minigun
ammo_buckshot = ammo_buckshot_net; // shotgun
fist_mode = fist_mode_net; // knife/fists
gauss_mode = gauss_mode_net;
shotgun_shells = shotgun_shells_net;
shotgun_spread = shotgun_spread_net;
dml_launch = dml_launch_net; /* when fired, when targeted */
dml_flightpath = dml_flightpath_net; /* guided, homing, spiral */
dml_detonate = dml_detonate_net; /* on impact, in proximity, timed, when tripped */
dml_payload = dml_payload_net; /* explosive, cluster */
chem_acid = chem_acid_net;
chem_neutral = chem_neutral_net;
chem_base = chem_base_net;
chem_pressure = chem_pressure_net;
beam_range = beam_range_net; /* TOUCH TAZER, SHORT TAZER, MEDIUM BEAM, LONG BEAM */
beam_poweracc = beam_poweracc_net; /* LOW HIGHEST, MEDIUM HIGH, HIGH MEDIUM, HIGHEST LOW */
beam_lightning = beam_lightning_net; /* BEAM, CHAIN, BALL */
gren_detonate = gren_detonate_net; /* when tripped (tripmine), timed, on impact */
gren_payload = gren_payload_net; /* cluster, explosive */
menu_active = menu_active_net;
}
#else
void
player::EvaluateEntity(void)
{
SendFlags |= PLAYER_KEEPALIVE;
if (old_modelindex != modelindex)
SendFlags |= PLAYER_MODELINDEX;
if (old_origin[0] != origin[0])
SendFlags |= PLAYER_ORIGIN;
if (old_origin[1] != origin[1])
SendFlags |= PLAYER_ORIGIN;
if (old_origin[2] != origin[2])
SendFlags |= PLAYER_ORIGIN_Z;
if (old_angles[0] != v_angle[0])
SendFlags |= PLAYER_ANGLES_X;
if (old_angles[1] != angles[1])
SendFlags |= PLAYER_ANGLES_Y;
if (old_angles[2] != angles[2])
SendFlags |= PLAYER_ANGLES_Z;
if (old_velocity[0] != velocity[0])
SendFlags |= PLAYER_VELOCITY;
if (old_velocity[1] != velocity[1])
SendFlags |= PLAYER_VELOCITY;
if (old_velocity[2] != velocity[2])
SendFlags |= PLAYER_VELOCITY_Z;
if (old_flags != flags)
SendFlags |= PLAYER_FLAGS;
if (old_gflags != gflags)
SendFlags |= PLAYER_FLAGS;
if (old_activeweapon != activeweapon)
SendFlags |= PLAYER_WEAPON;
if (old_items != g_items)
SendFlags |= PLAYER_ITEMS;
if (old_health != health)
SendFlags |= PLAYER_HEALTH;
if (old_armor != armor)
SendFlags |= PLAYER_ARMOR;
if (old_movetype != movetype)
SendFlags |= PLAYER_MOVETYPE;
if (old_viewofs != view_ofs[2])
SendFlags |= PLAYER_VIEWOFS;
if (old_baseframe != baseframe)
SendFlags |= PLAYER_BASEFRAME;
if (old_frame != frame)
SendFlags |= PLAYER_FRAME;
/* ammo 1 type updates */
if (ammo_battery_net == ammo_battery)
SendFlags |= PLAYER_AMMO1;
if (ammo_chem_net == ammo_chem)
SendFlags |= PLAYER_AMMO1;
if (ammo_rocket_net == ammo_rocket)
SendFlags |= PLAYER_AMMO1;
if (ammo_gauss_net == ammo_gauss)
SendFlags |= PLAYER_AMMO1;
if (ammo_minigun_net == ammo_minigun)
SendFlags |= PLAYER_AMMO1;
if (ammo_buckshot_net == ammo_buckshot)
SendFlags |= PLAYER_AMMO1;
if (fist_mode_net == fist_mode)
SendFlags |= PLAYER_AMMO1;
if (gauss_mode_net == gauss_mode)
SendFlags |= PLAYER_AMMO1;
if (shotgun_shells_net == shotgun_shells)
SendFlags |= PLAYER_AMMO1;
if (shotgun_spread_net == shotgun_spread)
SendFlags |= PLAYER_AMMO1;
if (dml_launch_net == dml_launch)
SendFlags |= PLAYER_AMMO2;
if (dml_flightpath_net == dml_flightpath)
SendFlags |= PLAYER_AMMO2;
if (dml_detonate_net == dml_detonate)
SendFlags |= PLAYER_AMMO2;
if (dml_payload_net == dml_payload)
SendFlags |= PLAYER_AMMO2;
if (chem_acid_net == chem_acid)
SendFlags |= PLAYER_AMMO2;
if (chem_neutral_net == chem_neutral)
SendFlags |= PLAYER_AMMO2;
if (chem_base_net == chem_base)
SendFlags |= PLAYER_AMMO2;
if (chem_pressure_net == chem_pressure)
SendFlags |= PLAYER_AMMO2;
if (beam_range_net == beam_range)
SendFlags |= PLAYER_AMMO3;
if (beam_poweracc_net == beam_poweracc)
SendFlags |= PLAYER_AMMO3;
if (beam_lightning_net == beam_lightning)
SendFlags |= PLAYER_AMMO3;
if (gren_detonate_net == gren_detonate)
SendFlags |= PLAYER_AMMO3;
if (gren_payload_net == gren_payload)
SendFlags |= PLAYER_AMMO3;
if (menu_active_net == menu_active)
SendFlags |= PLAYER_AMMO3;
if (dml_state_net == dml_state)
SendFlags |= PLAYER_AMMO3;
old_modelindex = modelindex;
old_origin = origin;
old_angles = angles;
old_angles[0] = v_angle[0];
old_velocity = velocity;
old_flags = flags;
old_gflags = gflags;
old_activeweapon = activeweapon;
old_items = g_items;
old_health = health;
old_armor = armor;
old_movetype = movetype;
old_viewofs = view_ofs[2];
old_baseframe = baseframe;
old_frame = frame;
ammo_battery_net = ammo_battery;
ammo_chem_net = ammo_chem;
ammo_rocket_net = ammo_rocket;
ammo_gauss_net = ammo_gauss;
ammo_minigun_net = ammo_minigun;
ammo_buckshot_net = ammo_buckshot;
fist_mode_net = fist_mode;
gauss_mode_net = gauss_mode;
shotgun_shells_net = shotgun_shells;
shotgun_spread_net = shotgun_spread;
dml_launch_net = dml_launch;
dml_flightpath_net = dml_flightpath;
dml_detonate_net = dml_detonate;
dml_payload_net = dml_payload;
chem_acid_net = chem_acid;
chem_neutral_net = chem_neutral;
chem_base_net = chem_base;
chem_pressure_net = chem_pressure;
beam_range_net = beam_range;
beam_poweracc_net = beam_poweracc;
beam_lightning_net = beam_lightning;
gren_detonate_net = gren_detonate;
gren_payload_net = gren_payload;
menu_active_net = menu_active;
dml_state_net = dml_state;
}
/*
=================
player::SendEntity
=================
*/
float
player::SendEntity(entity ePEnt, float fChanged)
{
if (health <= 0 && ePEnt != this) {
return FALSE;
}
if (clienttype(ePEnt) != CLIENTTYPE_REAL) {
return FALSE;
}
if (ePEnt != self) {
fChanged &= ~PLAYER_ITEMS;
fChanged &= ~PLAYER_HEALTH;
fChanged &= ~PLAYER_ARMOR;
fChanged &= ~PLAYER_VIEWOFS;
fChanged &= ~PLAYER_AMMO1;
fChanged &= ~PLAYER_AMMO2;
fChanged &= ~PLAYER_AMMO3;
}
WriteByte(MSG_ENTITY, ENT_PLAYER);
WriteFloat(MSG_ENTITY, fChanged);
/* really trying to get our moneys worth with 23 bits of mantissa */
if (fChanged & PLAYER_MODELINDEX)
WriteShort(MSG_ENTITY, modelindex);
if (fChanged & PLAYER_ORIGIN) {
WriteCoord(MSG_ENTITY, origin[0]);
WriteCoord(MSG_ENTITY, origin[1]);
}
if (fChanged & PLAYER_ORIGIN_Z)
WriteCoord(MSG_ENTITY, origin[2]);
if (fChanged & PLAYER_ANGLES_X)
WriteFloat(MSG_ENTITY, v_angle[0]);
if (fChanged & PLAYER_ANGLES_Y)
WriteFloat(MSG_ENTITY, angles[1]);
if (fChanged & PLAYER_ANGLES_Z)
WriteFloat(MSG_ENTITY, angles[2]);
if (fChanged & PLAYER_VELOCITY) {
WriteCoord(MSG_ENTITY, velocity[0]);
WriteCoord(MSG_ENTITY, velocity[1]);
}
if (fChanged & PLAYER_VELOCITY_Z)
WriteCoord(MSG_ENTITY, velocity[2]);
if (fChanged & PLAYER_FLAGS) {
WriteFloat(MSG_ENTITY, flags);
WriteFloat(MSG_ENTITY, gflags);
}
if (fChanged & PLAYER_WEAPON)
WriteByte(MSG_ENTITY, activeweapon);
if (fChanged & PLAYER_ITEMS)
WriteFloat(MSG_ENTITY, (__variant)g_items);
if (fChanged & PLAYER_HEALTH)
WriteByte(MSG_ENTITY, bound(0, health, 255));
if (fChanged & PLAYER_ARMOR)
WriteByte(MSG_ENTITY, armor);
if (fChanged & PLAYER_MOVETYPE)
WriteByte(MSG_ENTITY, movetype);
if (fChanged & PLAYER_VIEWOFS)
WriteFloat(MSG_ENTITY, view_ofs[2]);
if (fChanged & PLAYER_BASEFRAME)
WriteByte(MSG_ENTITY, baseframe);
if (fChanged & PLAYER_FRAME)
WriteByte(MSG_ENTITY, frame);
if (fChanged & PLAYER_AMMO1) {
WriteByte(MSG_ENTITY, ammo_battery);
WriteByte(MSG_ENTITY, ammo_chem);
WriteByte(MSG_ENTITY, ammo_rocket);
WriteByte(MSG_ENTITY, ammo_gauss);
WriteByte(MSG_ENTITY, ammo_minigun);
WriteByte(MSG_ENTITY, ammo_buckshot);
WriteByte(MSG_ENTITY, fist_mode);
WriteByte(MSG_ENTITY, gauss_mode);
WriteByte(MSG_ENTITY, shotgun_shells);
WriteByte(MSG_ENTITY, shotgun_spread);
}
if (fChanged & PLAYER_AMMO2) {
WriteByte(MSG_ENTITY, dml_launch);
WriteByte(MSG_ENTITY, dml_flightpath);
WriteByte(MSG_ENTITY, dml_detonate);
WriteByte(MSG_ENTITY, dml_payload);
WriteByte(MSG_ENTITY, chem_acid);
WriteByte(MSG_ENTITY, chem_neutral);
WriteByte(MSG_ENTITY, chem_base);
WriteByte(MSG_ENTITY, chem_pressure);
}
if (fChanged & PLAYER_AMMO3) {
WriteByte(MSG_ENTITY, beam_range);
WriteByte(MSG_ENTITY, beam_poweracc);
WriteByte(MSG_ENTITY, beam_lightning);
WriteByte(MSG_ENTITY, gren_detonate);
WriteByte(MSG_ENTITY, gren_payload);
WriteByte(MSG_ENTITY, menu_active);
WriteByte(MSG_ENTITY, dml_state);
}
return TRUE;
}
#endif

152
src/shared/w_aicore.qc Normal file
View File

@ -0,0 +1,152 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum
{
AIC_IDLE, // 1.777778f
AIC_PLUGIN, // 1.066667f
AIC_DRAW // 1.7f
};
void
w_aicore_draw(void)
{
Weapons_SetModel("models/v_aicore.mdl");
Weapons_SetGeomset("geomset 1 1\n");
Weapons_ViewAnimation(AIC_DRAW);
}
void
w_aicore_holster(void)
{
}
void
w_aicore_primary(void)
{
vector src;
player pl = (player)self;
if (pl.w_attack_next) {
return;
}
src = Weapons_GetCameraPos();
#ifdef CLIENT
//Weapons_ViewAnimation(GP_FIRESINGLE);
#endif
pl.w_attack_next = 0.15f;
pl.w_idle_next = 2.5f;
}
void
w_aicore_release(void)
{
player pl = (player)self;
pl.gflags |= GF_SEMI_TOGGLED;
if (pl.w_idle_next) {
return;
}
Weapons_ViewAnimation(AIC_IDLE);
pl.w_idle_next = 1.777778f;
}
void
w_aicore_updateammo(player pl)
{
}
string
w_aicore_wmodel(void)
{
return "";
}
string
w_aicore_pmodel(void)
{
return "models/w_aicore.mdl";
}
string
w_aicore_deathmsg(void)
{
return "";
}
float
w_aicore_aimanim(void)
{
return 0;
}
void
w_aicore_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
drawpic(
pos,
"gfx/vgui/640_weapon_aicore0.tga",
[170,43],
[1,1,1],
a,
DRAWFLAG_NORMAL
);
#endif
}
void
w_aicore_precache(void)
{
precache_model("models/v_aicore.mdl");
}
weapon_t w_aicore =
{
.name = "aicore",
.id = ITEM_AICORE,
.slot = 0,
.slot_pos = 1,
.draw = w_aicore_draw,
.holster = w_aicore_holster,
.primary = w_aicore_primary,
.secondary = __NULL__,
.reload = __NULL__,
.release = w_aicore_release,
.crosshair = __NULL__,
.precache = w_aicore_precache,
.pickup = __NULL__,
.updateammo = w_aicore_updateammo,
.wmodel = w_aicore_wmodel,
.pmodel = w_aicore_pmodel,
.deathmsg = w_aicore_deathmsg,
.aimanim = w_aicore_aimanim,
.hudpic = w_aicore_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_aicore(void)
{
Weapons_InitItem(WEAPON_AICORE);
}
#endif

350
src/shared/w_beamgun.qc Normal file
View File

@ -0,0 +1,350 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum
{
BEAMGUN_DRAW,
BEAMGUN_IDLE, // 2.6f
BEAMGUN_FIDGET1, // 2.4f
BEAMGUN_FIDGET2, // 2.08f
BEAMGUN_FIRE, // 0.333333f
BEAMGUN_FIRESINGLE, // 0.333333f
BEAMGUN_CONFIG, // 2.26087f
BEAMGUN_CHARGE // 1.3f
};
void
w_beamgun_draw(void)
{
Weapons_SetModel("models/v_beam.mdl");
Weapons_SetGeomset("geomset 1 1\n");
Weapons_ViewAnimation(BEAMGUN_DRAW);
}
void
w_beamgun_holster(void)
{
}
void
w_beamgun_release(void)
{
player pl = (player)self;
if (pl.w_idle_next) {
return;
}
Weapons_ViewAnimation(BEAMGUN_IDLE);
pl.w_idle_next = 2.6f;
}
void
w_beamgun_primary(void)
{
vector src;
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
if (pl.a_ammo1 > 0) {
pl.a_ammo1 = 0;
pl.gflags |= GF_SEMI_TOGGLED;
Weapons_ViewAnimation(BEAMGUN_CONFIG);
pl.w_attack_next = 2.26087f;
pl.w_idle_next = 2.26087f;
return;
}
if (pl.w_attack_next) {
return;
}
src = Weapons_GetCameraPos();
#ifdef CLIENT
//Weapons_ViewAnimation(GP_FIRESINGLE);
#endif
pl.w_attack_next = 0.15f;
pl.w_idle_next = 2.5f;
}
void
w_beamgun_secondary(void)
{
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
pl.gflags |= GF_SEMI_TOGGLED;
if (pl.w_attack_next) {
return;
}
/* activate menu */
if (pl.a_ammo1 <= 0 || pl.a_ammo1 == 3) {
pl.a_ammo1 = 1;
} else {
pl.a_ammo1 = bound(1, pl.a_ammo1 + 1, 3);
}
}
void
w_beamgun_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, -1, pl.ammo_battery, -1);
#endif
}
string
w_beamgun_wmodel(void)
{
return "models/w_beam.mdl";
}
string
w_beamgun_pmodel(void)
{
return "models/p_egon.mdl";
}
string
w_beamgun_deathmsg(void)
{
return "";
}
float
w_beamgun_aimanim(void)
{
return 0;
}
void
w_beamgun_hud(void)
{
#ifdef CLIENT
static string rmodes[] = {
"TOUCH TAZER",
"SHORT TAZER",
"MEDIUM BEAM",
"LONG BEAM"
};
static string pmodes[] = {
"LOW",
"MEDIUM",
"HIGH",
"HIGHEST"
};
static string amodes[] = {
"HIGHEST",
"HIGH",
"MEDIUM",
"LOW"
};
static string lmodes[] = {
"BEAM",
"CHAIN",
"BALL"
};
vector pos;
player pl = (player)self;
/* menu */
if (pl.a_ammo1 > 0) {
vector col1, col2, col3;
string txt1, txt2, txt3, txt4;
col1 = col2 = col3 = [1,1,1];
switch (pl.a_ammo1) {
case 1:
col1 = [0,1,0];
break;
case 2:
col2 = [0,1,0];
break;
case 3:
col3 = [0,1,0];
break;
}
txt1 = sprintf("RANGE: %s", rmodes[getstati(46)]);
txt2 = sprintf("POWER: %s", pmodes[getstati(47)]);
txt3 = sprintf("ACCURACY: %s", amodes[getstati(47)]);
txt4 = sprintf("LIGHTNING: %s", lmodes[getstati(48)]);
pos = g_hudmins + (g_hudres / 2) + [-80,-48];
drawfont = FONT_20;
drawstring(pos, txt1, [20,20], col1, 1.0f,
DRAWFLAG_ADDITIVE);
pos[1] += 24;
drawstring(pos, txt2, [20,20], col2, 1.0f,
DRAWFLAG_ADDITIVE);
pos[1] += 24;
drawstring(pos, txt3, [20,20], col2, 1.0f,
DRAWFLAG_ADDITIVE);
pos[1] += 24;
drawstring(pos, txt4, [20,20], col3, 1.0f,
DRAWFLAG_ADDITIVE);
return;
}
pos = g_hudmins + (g_hudres / 2) + [-15,-15];
drawsubpic(
pos,
[31,31],
"sprites/crosshairs.spr_0.tga",
[116/256,1/128],
[31/256, 31/128],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
HUD_DrawAmmo2();
#endif
}
void
w_beamgun_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
drawpic(
pos,
"gfx/vgui/640_weapon_beamgun0.tga",
[170,43],
[1,1,1],
a,
DRAWFLAG_NORMAL
);
#endif
}
void
w_beamgun_precache(void)
{
precache_model("models/v_beam.mdl");
#ifdef SERVER
clientstat(46, EV_INTEGER, player::beam_range);
clientstat(47, EV_INTEGER, player::beam_poweracc);
clientstat(48, EV_INTEGER, player::beam_lightning);
#endif
}
weapon_t w_beamgun =
{
.name = "beamgun",
.id = ITEM_BEAMGUN,
.slot = 3,
.slot_pos = 0,
.draw = w_beamgun_draw,
.holster = w_beamgun_holster,
.primary = w_beamgun_primary,
.secondary = w_beamgun_secondary,
.reload = __NULL__,
.release = w_beamgun_release,
.crosshair = w_beamgun_hud,
.precache = w_beamgun_precache,
.pickup = __NULL__,
.updateammo = w_beamgun_updateammo,
.wmodel = w_beamgun_wmodel,
.pmodel = w_beamgun_pmodel,
.deathmsg = w_beamgun_deathmsg,
.aimanim = w_beamgun_aimanim,
.hudpic = w_beamgun_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_beamgun(void)
{
Weapons_InitItem(WEAPON_BEAMGUN);
}
#endif
#ifdef CLIENT
int
w_beamgun_hudforward(player pl)
{
if (pl.a_ammo1 <= 0) {
return TRUE;
}
switch (pl.a_ammo1) {
case 1:
sendevent("w_beamgun_range", "i", 1i);
break;
case 2:
sendevent("w_beamgun_power", "i", 1i);
break;
case 3:
sendevent("w_beamgun_light", "i", 1i);
break;
}
return FALSE;
}
int
w_beamgun_hudback(player pl)
{
if (pl.a_ammo1 <= 0) {
return TRUE;
}
switch (pl.a_ammo1) {
case 1:
sendevent("w_beamgun_range", "i", -1i);
break;
case 2:
sendevent("w_beamgun_power", "i", -1i);
break;
case 3:
sendevent("w_beamgun_light", "i", -1i);
break;
}
return FALSE;
}
#else
void
CSEv_w_beamgun_range_i(int f)
{
player pl = (player)self;
pl.beam_range = bound(0, pl.beam_range + f, 3);
}
void
CSEv_w_beamgun_power_i(int f)
{
player pl = (player)self;
pl.beam_poweracc = bound(0, pl.beam_poweracc + f, 3);
}
void
CSEv_w_beamgun_light_i(int f)
{
player pl = (player)self;
pl.beam_lightning = bound(0, pl.beam_lightning + f, 2);
}
#endif

465
src/shared/w_chemicalgun.qc Normal file
View File

@ -0,0 +1,465 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum
{
CHEMGUN_DRAW, // 1.2f
CHEMGUN_HOLSTER, // 1.2f
CHEMGUN_IDLE, // 2.08f
CHEMGUN_FIDGET, // 2.08f
CHEMGUN_CONFIG, // 2.08f
CHEMGUN_SHOOT // 0.535714
};
void
w_chemicalgun_draw(void)
{
Weapons_SetModel("models/v_chemgun.mdl");
Weapons_SetGeomset("geomset 1 1\n");
Weapons_ViewAnimation(CHEMGUN_DRAW);
}
void
w_chemicalgun_holster(void)
{
}
void
w_chemicalgun_primary(void)
{
vector src;
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
if (pl.a_ammo1 > 0) {
pl.a_ammo1 = 0;
pl.gflags |= GF_SEMI_TOGGLED;
Weapons_ViewAnimation(CHEMGUN_CONFIG);
pl.w_attack_next = 2.08f;
pl.w_idle_next = pl.w_attack_next;
return;
}
if (pl.w_attack_next) {
return;
}
src = Weapons_GetCameraPos();
#ifdef CLIENT
//Weapons_ViewAnimation(GP_FIRESINGLE);
#endif
pl.w_attack_next = 0.15f;
pl.w_idle_next = 2.5f;
}
void
w_chemicalgun_secondary(void)
{
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
pl.gflags |= GF_SEMI_TOGGLED;
if (pl.w_attack_next) {
return;
}
/* activate menu */
if (pl.a_ammo1 <= 0 || pl.a_ammo1 == 4) {
pl.a_ammo1 = 1;
} else {
pl.a_ammo1 = bound(1, pl.a_ammo1 + 1, 4);
}
}
void
w_chemicalgun_release(void)
{
player pl = (player)self;
if (pl.w_idle_next) {
return;
}
Weapons_ViewAnimation(CHEMGUN_IDLE);
pl.w_idle_next = 2.08f;
}
void
w_chemicalgun_updateammo(player pl)
{
}
string
w_chemicalgun_wmodel(void)
{
return "models/w_chemgun.mdl";
}
string
w_chemicalgun_pmodel(void)
{
return "models/p_hgun.mdl";
}
string
w_chemicalgun_deathmsg(void)
{
return "";
}
float
w_chemicalgun_aimanim(void)
{
return 0;
}
int
w_chemicalgun_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (new) {
pl.chem_acid = 5;
pl.chem_neutral = 2;
pl.chem_base = 4;
pl.chem_pressure = 3;
}
if (pl.ammo_chem < 50) {
pl.ammo_chem = bound(0, pl.ammo_chem + 10, 50);
} else {
return FALSE;
}
#endif
return TRUE;
}
#ifdef CLIENT
void
w_chemgun_drawvial(vector pos, int length, vector col)
{
int i;
vector npos;
const string parts[] = {
"sprites/vial_el.spr_0.tga",
"sprites/vial_ec.spr_0.tga",
"sprites/vial_ec.spr_0.tga",
"sprites/vial_ec.spr_0.tga",
"sprites/vial_er.spr_0.tga"
};
pos[0] += 96;
npos = pos;
/* empty */
for (i = 0; i < 5; i++) {
if (i >= length) {
drawpic(
pos,
parts[i],
[32,32],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
}
pos[0] += 32;
}
/* full */
for (i = 0; i < length; i++) {
drawpic(
npos,
parts[i],
[32,32],
col,
1.0f,
DRAWFLAG_ADDITIVE
);
npos[0] += 32;
}
}
void
w_chemgun_drawpressure(vector pos, int length, vector col)
{
int i;
const string parts[] = {
"sprites/hud_pntr.spr_0.tga",
"sprites/vial_ec.spr_0.tga",
"sprites/vial_ec.spr_0.tga",
"sprites/vial_ec.spr_0.tga",
"sprites/vial_er.spr_0.tga"
};
pos[0] += 96;
/* full */
for (i = 0; i < 5; i++) {
if (i == length) {
drawpic(
pos,
"sprites/hud_pntr.spr_0.tga",
[32,32],
col,
1.0f,
DRAWFLAG_ADDITIVE
);
} else {
drawpic(
pos,
"sprites/hud_rule.spr_0.tga",
[32,32],
col,
1.0f,
DRAWFLAG_ADDITIVE
);
}
pos[0] += 32;
}
}
#endif
void
w_chemicalgun_hud(void)
{
#ifdef CLIENT
vector pos;
player pl = (player)self;
pos = g_hudmins + [g_hudres[0] - 125, g_hudres[1] - 42];
for (int i = 0; i < 3; i++) {
drawpic(
pos,
"gfx/vgui/640_ammo_chem.tga",
[32,16],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
pos[1] += 8;
}
HUD_DrawAmmo2();
/* menu */
if (pl.a_ammo1 > 0) {
vector col1, col2, col3, col4;
string txt1, txt2, txt3, txt4;
col1 = col2 = col3 = col4 = [1,1,1];
switch (pl.a_ammo1) {
case 1:
col1 = [0,1,0];
break;
case 2:
col2 = [0,1,0];
break;
case 3:
col3 = [0,1,0];
break;
case 4:
col4 = [0,1,0];
break;
}
txt1 = "ACID:";
txt2 = "NEUTRAL:";
txt3 = "BASE:";
txt4 = "PRESSURE:";
pos = g_hudmins + (g_hudres / 2) + [-128,-96];
drawfont = FONT_20;
drawstring(pos + [0,8], txt1, [20,20], col1, 1.0f,
DRAWFLAG_ADDITIVE);
w_chemgun_drawvial(pos, getstati(51), [0,1,0]);
pos[1] += 48;
drawstring(pos + [0,8], txt2, [20,20], col2, 1.0f,
DRAWFLAG_ADDITIVE);
w_chemgun_drawvial(pos, getstati(52), [0.25,0.25,1]);
pos[1] += 48;
drawstring(pos + [0,8], txt3, [20,20], col3, 1.0f,
DRAWFLAG_ADDITIVE);
w_chemgun_drawvial(pos, getstati(53), [1,0,0]);
pos[1] += 48;
drawstring(pos + [0,8], txt4, [20,20], col4, 1.0f,
DRAWFLAG_ADDITIVE);
w_chemgun_drawpressure(pos, getstati(54), [1,0.5,0.25]);
return;
}
#endif
}
void
w_chemicalgun_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
drawpic(
pos,
"gfx/vgui/640_weapon_SPchemicalgun0.tga",
[170,43],
[1,1,1],
a,
DRAWFLAG_NORMAL
);
#endif
}
void
w_chemicalgun_precache(void)
{
precache_model("models/v_chemgun.mdl");
/* empty */
precache_model("sprites/vial_el.spr"); /* 32x32 */
precache_model("sprites/vial_ec.spr");
precache_model("sprites/vial_er.spr");
/* full */
precache_model("sprites/vial_fl.spr");
precache_model("sprites/vial_fc.spr");
precache_model("sprites/vial_fr.spr");
precache_model("sprites/hud_pntr.spr");
precache_model("sprites/hud_rule.spr");
#ifdef SERVER
clientstat(51, EV_INTEGER, player::chem_acid);
clientstat(52, EV_INTEGER, player::chem_neutral);
clientstat(53, EV_INTEGER, player::chem_base);
clientstat(54, EV_INTEGER, player::chem_pressure);
#endif
}
weapon_t w_chemicalgun =
{
.name = "chemicalgun",
.id = ITEM_CHEMICALGUN,
.slot = 4,
.slot_pos = 1,
.draw = w_chemicalgun_draw,
.holster = w_chemicalgun_holster,
.primary = w_chemicalgun_primary,
.secondary = w_chemicalgun_secondary,
.reload = __NULL__,
.release = w_chemicalgun_release,
.crosshair = w_chemicalgun_hud,
.precache = w_chemicalgun_precache,
.pickup = w_chemicalgun_pickup,
.updateammo = w_chemicalgun_updateammo,
.wmodel = w_chemicalgun_wmodel,
.pmodel = w_chemicalgun_pmodel,
.deathmsg = w_chemicalgun_deathmsg,
.aimanim = w_chemicalgun_aimanim,
.hudpic = w_chemicalgun_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_SPchemicalgun(void)
{
Weapons_InitItem(WEAPON_CHEMICALGUN);
}
#endif
#ifdef CLIENT
int
w_chemgun_hudforward(player pl)
{
if (pl.a_ammo1 <= 0) {
return TRUE;
}
switch (pl.a_ammo1) {
case 1:
sendevent("w_chem_a", "i", 1i);
break;
case 2:
sendevent("w_chem_n", "i", 1i);
break;
case 3:
sendevent("w_chem_b", "i", 1i);
break;
case 4:
sendevent("w_chem_p", "i", 1i);
break;
}
return FALSE;
}
int
w_chemgun_hudback(player pl)
{
if (pl.a_ammo1 <= 0) {
return TRUE;
}
switch (pl.a_ammo1) {
case 1:
sendevent("w_chem_a", "i", -1i);
break;
case 2:
sendevent("w_chem_n", "i", -1i);
break;
case 3:
sendevent("w_chem_b", "i", -1i);
break;
case 4:
sendevent("w_chem_p", "i", -1i);
break;
}
return FALSE;
}
#else
void
CSEv_w_chem_a_i(int f)
{
player pl = (player)self;
pl.chem_acid = bound(0, pl.chem_acid + f, 5);
}
void
CSEv_w_chem_n_i(int f)
{
player pl = (player)self;
pl.chem_neutral = bound(0, pl.chem_neutral + f, 5);
}
void
CSEv_w_chem_b_i(int f)
{
player pl = (player)self;
pl.chem_base = bound(0, pl.chem_base + f, 5);
}
void
CSEv_w_chem_p_i(int f)
{
player pl = (player)self;
pl.chem_pressure = bound(0, pl.chem_pressure + f, 4);
}
#endif

483
src/shared/w_dml.qc Normal file
View File

@ -0,0 +1,483 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* the rocket launcher */
enum
{
DML_IDLE, // 2.5f
DML_FIDGET, // 2.0f
DML_RELOADBOTH, // 1.6f
DML_RELOADLEFT, // 1.6f
DML_RELOADRIGHT, // 1.6f
DML_FIRE, // 1.222222f
DML_CUSTOMIZE, // 4.0f
DML_DRAW // 1.222222f
};
enum
{
DS_FULL,
DS_RELOADING
};
enum
{
DMENU_NONE,
DMENU_LAUNCH,
DMENU_FLIGHTPATH,
DMENU_DETONATE,
DMENU_PAYLOAD
};
/* customizable states */
enum
{
LAUNCH_FIRED,
LAUNCH_TARGETED
};
enum
{
FLIGHTPATH_GUIDED,
FLIGHTPATH_HOMING,
FLIGHTPATH_SPIRAL
} ;
enum
{
DETONATE_IMPACT,
DETONATE_PROXIMITY,
DETONATE_TIMED,
DETONATE_TRIPPED
};
enum
{
PAYLOAD_EXPLOSIVE,
PAYLOAD_CLUSTER
};
/* functions */
void
w_dml_draw(void)
{
Weapons_SetModel("models/v_dml.mdl");
Weapons_SetGeomset("geomset 1 1\n");
Weapons_ViewAnimation(DML_DRAW);
}
void
w_dml_holster(void)
{
}
void
w_dml_release(void)
{
player pl = (player)self;
if (pl.w_idle_next) {
return;
}
if (pl.dml_state == DS_RELOADING) {
if (pl.menu_active == 1) {
Weapons_ViewAnimation(DML_RELOADRIGHT);
} else {
Weapons_ViewAnimation(DML_RELOADLEFT);
}
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_dml.reload");
#endif
pl.w_attack_next = 1.6f;
pl.w_idle_next = pl.w_attack_next;
pl.dml_state = DS_FULL;
return;
}
int r = (float)input_sequence % 5;
switch (r) {
case 0:
case 1:
case 2:
case 3:
Weapons_ViewAnimation(DML_IDLE);
pl.w_idle_next = 10.0f;
break;
default:
Weapons_ViewAnimation(DML_FIDGET);
pl.w_idle_next = 2.0f;
}
}
void
w_dml_primary(void)
{
vector src;
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
if (pl.menu_active > 0) {
pl.menu_active = 0;
pl.gflags |= GF_SEMI_TOGGLED;
Weapons_ViewAnimation(DML_CUSTOMIZE);
#ifdef SERVER
Sound_Play(pl, 8, "weapon_dml.customize");
#endif
pl.w_attack_next = 4.0f;
pl.w_idle_next = 5.0f;
return;
}
if (pl.w_attack_next) {
return;
}
if (pl.dml_state == DS_RELOADING) {
w_dml_release();
return;
}
src = Weapons_GetCameraPos();
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_dml.fire");
#endif
Weapons_ViewAnimation(DML_FIRE);
pl.w_attack_next = 1.222222f;
pl.w_idle_next = 1.222222f;
pl.dml_state = DS_RELOADING;
}
void
w_dml_secondary(void)
{
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
pl.gflags |= GF_SEMI_TOGGLED;
if (pl.w_attack_next) {
return;
}
/* activate menu */
if (pl.menu_active <= 0 || pl.menu_active == DMENU_PAYLOAD) {
pl.menu_active = 1;
} else {
pl.menu_active = bound(DMENU_LAUNCH, pl.menu_active + 1, DMENU_PAYLOAD);
}
}
void
w_dml_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, -1, pl.ammo_rocket, -1);
}
string
w_dml_wmodel(void)
{
return "models/w_dml.mdl";
}
string
w_dml_pmodel(void)
{
return "models/p_crossbow.mdl";
}
string
w_dml_deathmsg(void)
{
return "";
}
float
w_dml_aimanim(void)
{
return 0;
}
int
w_dml_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (pl.ammo_rocket < 100) {
pl.ammo_rocket = bound(0, pl.ammo_rocket + 2, 100);
} else {
return FALSE;
}
#endif
return TRUE;
}
void
w_dml_hud(void)
{
#ifdef CLIENT
static string lmodes[] = {
"WHEN FIRED",
"WHEN TARGETED"
};
static string fmodes[] = {
"GUIDED",
"HOMING",
"SPIRAL"
};
static string dmodes[] = {
"ON IMPACT",
"IN PROXIMITY",
"TIMED",
"WHEN TRIPPED"
};
static string pmodes[] = {
"EXPLOSIVE",
"CLUSTER"
};
vector pos;
vector jitter;
float lerp;
player pl = (player)self;
/* laser */
Weapons_MakeVectors();
vector src = Weapons_GetCameraPos();
traceline(src, src + (v_forward * 256), FALSE, pl);
lerp = Math_Lerp(18,6, trace_fraction);
jitter[0] = (random(0,2) - 2) * (1 - trace_fraction);
jitter[1] = (random(0,2) - 2) * (1 - trace_fraction);
pos = (g_hudres / 2) + ([-lerp,-lerp] / 2);
drawsubpic(
pos + jitter,
[lerp,lerp],
"sprites/laserdot.spr_0.tga",
[0,0],
[1.0, 1.0],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
/* menu */
if (pl.menu_active > 0) {
vector col1, col2, col3, col4;
string txt1, txt2, txt3, txt4;
col1 = col2 = col3 = col4 = [1,1,1];
switch (pl.menu_active) {
case DMENU_LAUNCH:
col1 = [0,1,0];
break;
case DMENU_FLIGHTPATH:
col2 = [0,1,0];
break;
case DMENU_DETONATE:
col3 = [0,1,0];
break;
case DMENU_PAYLOAD:
col4 = [0,1,0];
break;
}
txt1 = sprintf("LAUNCH: %s", lmodes[getstati(42)]);
txt2 = sprintf("FLIGHTPATH: %s", fmodes[getstati(43)]);
txt3 = sprintf("DETONATE: %s", dmodes[getstati(44)]);
txt4 = sprintf("PAYLOAD: %s", pmodes[getstati(45)]);
pos = g_hudmins + (g_hudres / 2) + [-80,-48];
drawfont = FONT_20;
drawstring(pos, txt1, [20,20], col1, 1.0f,
DRAWFLAG_ADDITIVE);
pos[1] += 24;
drawstring(pos, txt2, [20,20], col2, 1.0f,
DRAWFLAG_ADDITIVE);
pos[1] += 24;
drawstring(pos, txt3, [20,20], col3, 1.0f,
DRAWFLAG_ADDITIVE);
pos[1] += 24;
drawstring(pos, txt4, [20,20], col4, 1.0f,
DRAWFLAG_ADDITIVE);
return;
}
pos = g_hudmins + (g_hudres / 2) + [-32,-15];
drawsubpic(
pos,
[63,31],
"sprites/crosshairs.spr_0.tga",
[149/256,1/128],
[63/256, 31/128],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
HUD_DrawAmmo2();
#endif
}
void
w_dml_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
drawpic(
pos,
"gfx/vgui/640_weapon_dml0.tga",
[170,43],
[1,1,1],
a,
DRAWFLAG_NORMAL
);
#endif
}
void
w_dml_precache(void)
{
precache_model("models/v_dml.mdl");
precache_model("sprites/laserdot.spr");
#ifdef SERVER
Sound_Precache("weapon_dml.customize");
Sound_Precache("weapon_dml.fire");
Sound_Precache("weapon_dml.reload");
clientstat(42, EV_INTEGER, player::dml_launch);
clientstat(43, EV_INTEGER, player::dml_flightpath);
clientstat(44, EV_INTEGER, player::dml_detonate);
clientstat(45, EV_INTEGER, player::dml_payload);
#endif
}
weapon_t w_dml =
{
.name = "dml",
.id = ITEM_DML,
.slot = 3,
.slot_pos = 1,
.draw = w_dml_draw,
.holster = w_dml_holster,
.primary = w_dml_primary,
.secondary = w_dml_secondary,
.reload = __NULL__,
.release = w_dml_release,
.crosshair = w_dml_hud,
.precache = w_dml_precache,
.pickup = w_dml_pickup,
.updateammo = w_dml_updateammo,
.wmodel = w_dml_wmodel,
.pmodel = w_dml_pmodel,
.deathmsg = w_dml_deathmsg,
.aimanim = w_dml_aimanim,
.hudpic = w_dml_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_dml(void)
{
Weapons_InitItem(WEAPON_DML);
}
#endif
#ifdef CLIENT
int
w_dml_hudforward(player pl)
{
if (pl.menu_active <= 0) {
return TRUE;
}
switch (pl.menu_active) {
case DMENU_LAUNCH:
sendevent("w_dml_launch", "i", 1i);
break;
case DMENU_FLIGHTPATH:
sendevent("w_dml_path", "i", 1i);
break;
case DMENU_DETONATE:
sendevent("w_dml_det", "i", 1i);
break;
case DMENU_PAYLOAD:
sendevent("w_dml_pay", "i", 1i);
break;
}
return FALSE;
}
int
w_dml_hudback(player pl)
{
if (pl.menu_active <= 0) {
return TRUE;
}
switch (pl.menu_active) {
case DMENU_LAUNCH:
sendevent("w_dml_launch", "i", -1i);
break;
case DMENU_FLIGHTPATH:
sendevent("w_dml_path", "i", -1i);
break;
case DMENU_DETONATE:
sendevent("w_dml_det", "i", -1i);
break;
case DMENU_PAYLOAD:
sendevent("w_dml_pay", "i", -1i);
break;
}
return FALSE;
}
#else
void
CSEv_w_dml_launch_i(int f)
{
player pl = (player)self;
pl.dml_launch = bound(0, pl.dml_launch + f, 1);
}
void
CSEv_w_dml_path_i(int f)
{
player pl = (player)self;
pl.dml_flightpath = bound(0, pl.dml_flightpath + f, 2);
}
void
CSEv_w_dml_det_i(int f)
{
player pl = (player)self;
pl.dml_detonate = bound(0, pl.dml_detonate + f, 3);
}
void
CSEv_w_dml_pay_i(int f)
{
player pl = (player)self;
pl.dml_payload = bound(0, pl.dml_payload + f, 1);
}
#endif

287
src/shared/w_fists.qc Normal file
View File

@ -0,0 +1,287 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum
{
FISTS_IDLE, // 2.0f
FISTS_FIDGET1, // 3.0f
FISTS_FIDGET2, // 2.333333f
FISTS_RIGHT, // 0.419355f
FISTS_LEFT, // 0.419355f
FISTS_DOUBLE, // 0.739130f
FISTS_DRAW, // 1.4f
FISTS_HOLSTER, // 0.7f
KNIFE_DRAW, // 0.75f
KNIFE_HOLSTER, // 0.75f
KNIFE_IDLE, // 2.0f
KNIFE_FIDGET, // 2.0f
KNIFE_ATTACK1, // 0.789474f
KNIFE_ATTACK2, // 0.421053f
HANDS_PUSHBUTTON, // 8.0f
};
enum
{
HS_KNIFE,
HS_KNIFE_TO_FISTS,
HS_FISTS,
HS_FISTS_TO_KNIFE
};
void
w_fists_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, -1, -1, pl.fist_mode);
#endif
}
void
w_fists_draw(void)
{
player pl = (player)self;
Weapons_SetModel("models/v_hands.mdl");
Weapons_SetGeomset("geomset 1 2\n");
Weapons_ViewAnimation(KNIFE_DRAW);
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_fists.knifedraw");
#endif
}
void
w_fists_holster(void)
{
Weapons_ViewAnimation(KNIFE_HOLSTER);
}
void
w_fists_release(void)
{
int r;
player pl = (player)self;
if (pl.w_idle_next) {
return;
}
if (pl.a_ammo3 == HS_FISTS_TO_KNIFE) {
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_fists.knifedraw");
#endif
Weapons_ViewAnimation(KNIFE_DRAW);
Weapons_SetGeomset("geomset 1 2\n");
pl.a_ammo3 = HS_KNIFE;
pl.w_attack_next = 0.75f;
pl.w_idle_next = pl.w_attack_next;
return;
} else if (pl.a_ammo3 == HS_KNIFE_TO_FISTS) {
Weapons_ViewAnimation(FISTS_DRAW);
Weapons_SetGeomset("geomset 1 1\n");
pl.a_ammo3 = HS_FISTS;
pl.w_attack_next = 1.4f;
pl.w_idle_next = pl.w_attack_next;
return;
}
if (pl.a_ammo3 == HS_KNIFE) {
r = (float)input_sequence % 5;
switch (r) {
case 0:
case 1:
case 2:
case 3:
Weapons_ViewAnimation(KNIFE_IDLE);
pl.w_idle_next = 10.0f;
break;
default:
Weapons_ViewAnimation(KNIFE_FIDGET);
pl.w_idle_next = 2.0f;
}
} else {
r = (float)input_sequence % 5;
switch (r) {
case 0:
case 1:
case 2:
Weapons_ViewAnimation(FISTS_IDLE);
pl.w_idle_next = 10.0f;
break;
case 3:
Weapons_ViewAnimation(FISTS_FIDGET1);
pl.w_idle_next = 3.0f;
break;
default:
Weapons_ViewAnimation(FISTS_FIDGET2);
pl.w_idle_next = 2.333333f;
}
}
}
void
w_fists_primary(void)
{
player pl = (player)self;
if (pl.w_attack_next) {
return;
}
pl.a_ammo1 = 1 - pl.a_ammo1;
if (pl.a_ammo3 == HS_KNIFE) {
#ifdef SERVER
Sound_Play(pl, 8, "weapon_fists.missknife");
#endif
if (pl.a_ammo1 == 1) {
Weapons_ViewAnimation(KNIFE_ATTACK1);
} else {
Weapons_ViewAnimation(KNIFE_ATTACK2);
}
pl.w_attack_next = 0.5f;
pl.w_idle_next = pl.w_attack_next;
} else {
if (pl.a_ammo1 == 1) {
Weapons_ViewAnimation(FISTS_RIGHT);
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_fists.hitright");
#endif
} else {
Weapons_ViewAnimation(FISTS_LEFT);
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_fists.hitleft");
#endif
}
pl.w_attack_next = 0.25f;
pl.w_idle_next = pl.w_attack_next;
}
}
void
w_fists_secondary(void)
{
player pl = (player)self;
if (pl.w_attack_next) {
w_fists_release();
return;
}
if (pl.a_ammo3 == HS_KNIFE) {
Weapons_ViewAnimation(KNIFE_HOLSTER);
pl.a_ammo3 = HS_KNIFE_TO_FISTS;
pl.w_attack_next = 0.75f;
pl.w_idle_next = pl.w_attack_next;
} else if (pl.a_ammo3 == HS_FISTS) {
Weapons_ViewAnimation(FISTS_HOLSTER);
pl.a_ammo3 = HS_FISTS_TO_KNIFE;
pl.w_attack_next = 0.7f;
pl.w_idle_next = pl.w_attack_next;
}
}
string
w_fists_wmodel(void)
{
return "";
}
string
w_fists_pmodel(void)
{
/* if (pl.a_ammo3 == HS_KNIFE) {
return "";
} else {
return "";
}*/
return "";
}
string
w_fists_deathmsg(void)
{
return "%s killed %s with his knife.";
}
float
w_fists_aimanim(void)
{
return 0;
}
int
w_fists_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (pl.ammo_minigun < 100) {
pl.ammo_minigun = bound(0, pl.ammo_minigun + 30, 100);
} else {
return FALSE;
}
#endif
return TRUE;
}
void
w_fists_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
drawpic(
pos,
"gfx/vgui/640_weapon_fists0.tga",
[170,43],
[1,1,1],
a,
DRAWFLAG_NORMAL
);
#endif
}
void
w_fists_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_fists.knifedraw");
Sound_Precache("weapon_fists.hitleft");
Sound_Precache("weapon_fists.hitright");
Sound_Precache("weapon_fists.missknife");
#endif
precache_model("models/v_hands.mdl");
}
weapon_t w_fists =
{
.name = "fists",
.id = ITEM_FISTS,
.slot = 0,
.slot_pos = 0,
.draw = w_fists_draw,
.holster = w_fists_holster,
.primary = w_fists_primary,
.secondary = w_fists_secondary,
.reload = __NULL__,
.release = w_fists_release,
.crosshair = __NULL__,
.precache = w_fists_precache,
.pickup = __NULL__,
.updateammo = w_fists_updateammo,
.wmodel = __NULL__,
.pmodel = __NULL__,
.deathmsg = w_fists_deathmsg,
.aimanim = w_fists_aimanim,
.hudpic = w_fists_hudpic
};

428
src/shared/w_gausspistol.qc Normal file
View File

@ -0,0 +1,428 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum
{
GP_IDLE1, // 3.75f
GP_IDLE2, // 3.0f
GP_FIRESINGLE, // 0.727273f
GP_FIREFAST, // 0.2f
GP_FIRECHARGE, // 3.0f
GP_DRAW, // 1.071429f
GP_HOLSTER, // 0.9375f
SNIPER_IDLE1, // 3.0f
SNIPER_IDLE2, // 3.0f
SNIPER_FIDGET, // 3.0f
SNIPER_SHOOT, // 0.357143
SNIPER_DRAW, // 0.937500
SNIPER_HOLSTER // 1.666667f
};
enum
{
GM_SINGLE,
GM_CHARGE,
GM_FAST,
GM_SNIPER
};
void
w_gausspistol_draw(void)
{
Weapons_SetModel("models/v_guasspistol.mdl");
Weapons_SetGeomset("geomset 1 1\n");
Weapons_ViewAnimation(GP_DRAW);
}
void
w_gausspistol_holster(void)
{
Weapons_ViewAnimation(GP_HOLSTER);
}
void
w_gausspistol_release(void)
{
player pl = (player)self;
if (pl.w_idle_next) {
return;
}
int r = (float)input_sequence % 5;
switch (r) {
case 0:
case 1:
case 2:
case 3:
Weapons_ViewAnimation(GP_IDLE1);
pl.w_idle_next = 3.75f;
break;
default:
Weapons_ViewAnimation(GP_IDLE2);
pl.w_idle_next = 3.0f;
}
}
void
w_gausspistol_primary(void)
{
vector src;
int take = 1;
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
if (pl.a_ammo1 > 0) {
pl.a_ammo1 = 0;
pl.gflags |= GF_SEMI_TOGGLED;
return;
}
if (pl.w_attack_next > 0) {
return;
}
/* ammo check */
if (pl.a_ammo2 <= 0) {
return;
}
if (pl.a_ammo3 == GM_CHARGE && pl.a_ammo2 < 10) {
return;
}
switch (pl.a_ammo3) {
case GM_FAST:
Weapons_ViewAnimation(GP_FIREFAST);
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_gausspistol.firefast");
#endif
pl.w_attack_next = 0.15f;
pl.w_idle_next = 2.5f;
break;
case GM_CHARGE:
take = 10;
Weapons_ViewAnimation(GP_FIRECHARGE);
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_gausspistol.firecharge");
Sound_Play(pl, 8, "weapon_gausspistol.charge");
#endif
pl.w_attack_next = 2.0f;
pl.w_idle_next = 5.0f;
break;
default:
pl.gflags |= GF_SEMI_TOGGLED;
Weapons_ViewAnimation(GP_FIRESINGLE);
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_gausspistol.firesingle");
#endif
pl.w_attack_next = 0.15f;
pl.w_idle_next = 2.5f;
break;
}
src = Weapons_GetCameraPos();
#ifdef SERVER
pl.ammo_gauss -= take;
#else
pl.a_ammo2 -= take;
View_SetMuzzleflash(MUZZLE_SMALL);
Weapons_ViewPunchAngle([-5,0,0]);
#endif
}
void
w_gausspistol_secondary(void)
{
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
pl.gflags |= GF_SEMI_TOGGLED;
/* activate menu */
pl.a_ammo1 = 1;
w_gausspistol_release();
}
void
w_gausspistol_updateammo(player pl)
{
#ifdef SERVER
Weapons_UpdateAmmo(pl, -1, pl.ammo_gauss, pl.gauss_mode);
#endif
}
string
w_gausspistol_wmodel(void)
{
return "models/w_gauss.mdl";
}
string
w_gausspistol_pmodel(void)
{
return "models/p_357.mdl";
}
string
w_gausspistol_deathmsg(void)
{
return "%s kills %s with his Gauss-Pistol";
}
float
w_gausspistol_aimanim(void)
{
return 0;
}
int
w_gausspistol_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (pl.ammo_gauss < 150) {
pl.ammo_gauss = bound(0, pl.ammo_gauss + 35, 150);
} else {
return FALSE;
}
#endif
return TRUE;
}
void
w_gausspistol_hud(void)
{
#ifdef CLIENT
vector pos;
player pl = (player)self;
pos = g_hudmins + [g_hudres[0] - 125, g_hudres[1] - 42];
for (int i = 0; i < 3; i++) {
drawpic(
pos,
"gfx/vgui/640_ammo_gauss.tga",
[32,16],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
pos[1] += 8;
}
HUD_DrawAmmo2();
/* menu */
if (pl.a_ammo1 > 0) {
pos = g_hudmins + (g_hudres / 2) + [-96,-72];
/* far left */
if (pl.a_ammo3 == GM_SINGLE) {
drawsubpic(
pos,
[64,144],
"sprites/gausshud2.spr_0.tga",
[0/192,0/144],
[64/192, 144/144],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
drawsubpic(
pos + [64,0],
[128,144],
"sprites/gausshud1.spr_0.tga",
[64/192,0/144],
[128/192, 144/144],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
}
if (pl.a_ammo3 == GM_CHARGE) {
drawsubpic(
pos,
[64,144],
"sprites/gausshud1.spr_0.tga",
[0/192,0/144],
[64/192, 144/144],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
drawsubpic(
pos + [64,0],
[64,144],
"sprites/gausshud2.spr_0.tga",
[64/192,0/144],
[64/192, 144/144],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
drawsubpic(
pos + [128,0],
[64,144],
"sprites/gausshud1.spr_0.tga",
[128/192,0/144],
[64/192, 144/144],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
}
if (pl.a_ammo3 == GM_FAST) {
drawsubpic(
pos,
[128,144],
"sprites/gausshud1.spr_0.tga",
[0/192,0/144],
[128/192, 144/144],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
drawsubpic(
pos + [128,0],
[64,144],
"sprites/gausshud2.spr_0.tga",
[128/192,0/144],
[64/192, 144/144],
[1,1,1],
1.0f,
DRAWFLAG_ADDITIVE
);
}
return;
}
pos = g_hudmins + (g_hudres / 2) + [-15,-15];
drawsubpic(
pos,
[31,31],
"sprites/crosshairs.spr_0.tga",
[1/256,1/128],
[31/256, 31/128],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
#endif
}
void
w_gausspistol_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
drawpic(
pos,
"gfx/vgui/640_weapon_gaussPistol0.tga",
[170,43],
[1,1,1],
a,
DRAWFLAG_NORMAL
);
#endif
}
void
w_gausspistol_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_gausspistol.charge");
Sound_Precache("weapon_gausspistol.firecharge");
Sound_Precache("weapon_gausspistol.firefast");
Sound_Precache("weapon_gausspistol.firesingle");
#endif
precache_model("models/v_guasspistol.mdl");
precache_model("sprites/gausshud1.spr");
precache_model("sprites/gausshud2.spr");
}
weapon_t w_gausspistol =
{
.name = "gausspistol",
.id = ITEM_GAUSSPISTOL,
.slot = 1,
.slot_pos = 0,
.draw = w_gausspistol_draw,
.holster = w_gausspistol_holster,
.primary = w_gausspistol_primary,
.secondary = w_gausspistol_secondary,
.reload = __NULL__,
.release = w_gausspistol_release,
.crosshair = w_gausspistol_hud,
.precache = w_gausspistol_precache,
.pickup = w_gausspistol_pickup,
.updateammo = w_gausspistol_updateammo,
.wmodel = w_gausspistol_wmodel,
.pmodel = w_gausspistol_pmodel,
.deathmsg = w_gausspistol_deathmsg,
.aimanim = w_gausspistol_aimanim,
.hudpic = w_gausspistol_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_gausspistol(void)
{
Weapons_InitItem(WEAPON_GAUSSPISTOL);
}
#endif
#ifdef CLIENT
int
w_gausspistol_hudforward(player pl)
{
if (pl.a_ammo1 <= 0) {
return TRUE;
}
pl.a_ammo3 = bound(GM_SINGLE, pl.a_ammo3 - 1, GM_FAST);
sendevent("w_gp_setmode", "i", pl.a_ammo3);
return FALSE;
}
int
w_gausspistol_hudback(player pl)
{
if (pl.a_ammo1 <= 0) {
return TRUE;
}
pl.a_ammo3 = bound(GM_SINGLE, pl.a_ammo3 + 1, GM_FAST);
sendevent("w_gp_setmode", "i", pl.a_ammo3);
return FALSE;
}
#else
void CSEv_w_gp_setmode_i(int f)
{
player pl = (player)self;
pl.a_ammo3 = f;
pl.gauss_mode = f;
}
#endif

301
src/shared/w_grenade.qc Normal file
View File

@ -0,0 +1,301 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum
{
GREN_IDLE1, // 2.0f
GREN_IDLE2, // 2.0f
GREN_FIDGET, // 1.2f
GREN_RELOAD, // 1.6f
GREN_ARM, // 1.2f
GREN_THROW, // 0.5f
GREN_TRIPMINE, // 1.33333f
GREN_DRAW // 0.588235f
};
void
w_grenade_draw(void)
{
Weapons_SetModel("models/v_grenade.mdl");
Weapons_SetGeomset("geomset 1 1\n");
Weapons_ViewAnimation(GREN_DRAW);
}
void
w_grenade_holster(void)
{
}
void
w_grenade_primary(void)
{
vector src;
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
if (pl.a_ammo1 > 0) {
pl.a_ammo1 = 0;
pl.gflags |= GF_SEMI_TOGGLED;
Weapons_ViewAnimation(GREN_FIDGET);
pl.w_attack_next = 1.2f;
pl.w_idle_next = pl.w_attack_next;
return;
}
if (pl.w_attack_next) {
return;
}
src = Weapons_GetCameraPos();
#ifdef CLIENT
//Weapons_ViewAnimation(GP_FIRESINGLE);
#endif
pl.w_attack_next = 0.15f;
pl.w_idle_next = 2.5f;
}
void
w_grenade_secondary(void)
{
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
pl.gflags |= GF_SEMI_TOGGLED;
if (pl.w_attack_next) {
return;
}
/* activate menu */
if (pl.a_ammo1 <= 0) {
pl.a_ammo1 = 1;
} else {
if (pl.a_ammo1 == 1) {
pl.a_ammo1 = 2;
} else {
pl.a_ammo1 = 1;
}
}
}
void
w_grenade_release(void)
{
player pl = (player)self;
if (pl.w_idle_next) {
return;
}
Weapons_ViewAnimation(GREN_IDLE1);
pl.w_idle_next = 1.777778f;
}
void
w_grenade_updateammo(player pl)
{
}
string
w_grenade_wmodel(void)
{
return "models/w_grenade.mdl";
}
string
w_grenade_pmodel(void)
{
return "models/p_grenade.mdl";
}
string
w_grenade_deathmsg(void)
{
return "";
}
float
w_grenade_aimanim(void)
{
return 0;
}
void
w_grenade_hud(void)
{
#ifdef CLIENT
vector pos;
player pl = (player)self;
static string dmodes[] = {
"WHEN TRIPPED",
"TIMED",
"ON IMPACT"
};
static string pmodes[] = {
"CLUSTER",
"EXPLOSIVE"
};
HUD_DrawAmmo2();
/* menu */
if (pl.a_ammo1 > 0) {
vector col1, col2;
string txt1, txt2;
col1 = col2 = [1,1,1];
switch (pl.a_ammo1) {
case 1:
col1 = [0,1,0];
break;
case 2:
col2 = [0,1,0];
break;
}
txt1 = sprintf("DETONATE: %s", dmodes[getstati(49)]);
txt2 = sprintf("PAYLOAD: %s", pmodes[getstati(50)]);
pos = g_hudmins + (g_hudres / 2) + [-48,-16];
drawfont = FONT_20;
drawstring(pos, txt1, [20,20], col1, 1.0f,
DRAWFLAG_ADDITIVE);
drawstring(pos + [0,24], txt2, [20,20], col2, 1.0f,
DRAWFLAG_ADDITIVE);
return;
}
#endif
}
void
w_grenade_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
drawpic(
pos,
"gfx/vgui/640_weapon_dmlGrenade0.tga",
[170,43],
[1,1,1],
a,
DRAWFLAG_NORMAL
);
#endif
}
void
w_grenade_precache(void)
{
precache_model("models/v_grenade.mdl");
#ifdef SERVER
clientstat(49, EV_INTEGER, player::gren_detonate);
clientstat(50, EV_INTEGER, player::gren_payload);
#endif
}
weapon_t w_grenade =
{
.name = "grenade",
.id = ITEM_GRENADE,
.slot = 4,
.slot_pos = 0,
.draw = w_grenade_draw,
.holster = w_grenade_holster,
.primary = w_grenade_primary,
.secondary = w_grenade_secondary,
.reload = __NULL__,
.release = w_grenade_release,
.crosshair = w_grenade_hud,
.precache = w_grenade_precache,
.pickup = __NULL__,
.updateammo = w_grenade_updateammo,
.wmodel = w_grenade_wmodel,
.pmodel = w_grenade_pmodel,
.deathmsg = w_grenade_deathmsg,
.aimanim = w_grenade_aimanim,
.hudpic = w_grenade_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_grenade(void)
{
Weapons_InitItem(WEAPON_GRENADE);
}
#endif
#ifdef CLIENT
int
w_grenade_hudforward(player pl)
{
if (pl.a_ammo1 <= 0) {
return TRUE;
}
switch (pl.a_ammo1) {
case 1:
sendevent("w_gren_det", "i", 1i);
break;
case 2:
sendevent("w_gren_pay", "i", 1i);
break;
}
return FALSE;
}
int
w_grenade_hudback(player pl)
{
if (pl.a_ammo1 <= 0) {
return TRUE;
}
switch (pl.a_ammo1) {
case 1:
sendevent("w_gren_det", "i", -1i);
break;
case 2:
sendevent("w_gren_pay", "i", -1i);
break;
}
return FALSE;
}
#else
void
CSEv_w_gren_det_i(int f)
{
player pl = (player)self;
pl.gren_detonate = bound(0, pl.gren_detonate + f, 2);
}
void
CSEv_w_gren_pay_i(int f)
{
player pl = (player)self;
pl.gren_payload = bound(0, pl.gren_payload + f, 1);
}
#endif

281
src/shared/w_minigun.qc Normal file
View File

@ -0,0 +1,281 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum
{
MG_IDLE, // 2.0f
MG_FIDGET, // 2.6f
MG_FIRE, // 0.333333f
MG_SPINUP, // 2.0f
MG_FIRELOOP, // 0.666667f
MG_SPINDOWN, // 2.0f
MG_DRAW, // 1.5f
MG_IDLELOOP, // 0.666667f
MG_HOLSTER // 1.5f
};
void
w_minigun_draw(void)
{
Weapons_SetModel("models/v_mechagun.mdl");
Weapons_SetGeomset("geomset 1 1\n");
Weapons_ViewAnimation(MG_DRAW);
}
void
w_minigun_holster(void)
{
Weapons_ViewAnimation(MG_DRAW);
}
void
w_minigun_release(void)
{
player pl = (player)self;
if (pl.w_idle_next) {
return;
}
if (pl.menu_active == 1) {
Weapons_ViewAnimation(MG_IDLELOOP);
pl.w_idle_next = 0.666667f;
return;
}
int r = (float)input_sequence % 5;
switch (r) {
case 0:
case 1:
case 2:
case 3:
Weapons_ViewAnimation(MG_IDLE);
pl.w_idle_next = 10.0f;
break;
default:
Weapons_ViewAnimation(MG_FIDGET);
pl.w_idle_next = 2.0f;
}
}
void
w_minigun_primary(void)
{
vector src;
player pl = (player)self;
if (pl.w_attack_next) {
return;
}
if (pl.ammo_minigun <= 0) {
w_minigun_release();
return;
}
src = Weapons_GetCameraPos();
#ifdef SERVER
Sound_Play(pl, CHAN_WEAPON, "weapon_minigun.fire");
#else
View_SetMuzzleflash(MUZZLE_RIFLE);
Weapons_ViewPunchAngle([-2,0,0]);
#endif
pl.ammo_minigun--;
if (pl.menu_active == 1) {
#ifdef CLIENT
Weapons_ViewAnimation(MG_FIRELOOP);
#else
TraceAttack_FireBullets(1, src, 8, [0.1,0.1], WEAPON_MINIGUN);
#endif
pl.w_attack_next = 0.1f;
pl.w_idle_next = 0.1f;
} else {
#ifdef CLIENT
Weapons_ViewAnimation(MG_FIRE);
#else
TraceAttack_FireBullets(1, src, 8, [0.05,0.05], WEAPON_MINIGUN);
#endif
pl.w_attack_next = 0.25f;
pl.w_idle_next = 2.5f;
}
}
void
w_minigun_secondary(void)
{
player pl = (player)self;
if (pl.w_attack_next) {
return;
}
#ifdef SERVER
if (pl.menu_active == 0) {
Sound_Play(pl, 8, "weapon_minigun.spinup");
} else {
Sound_Play(pl, 8, "weapon_minigun.spindown");
}
#else
if (pl.menu_active == 0) {
Weapons_ViewAnimation(MG_SPINUP);
} else {
Weapons_ViewAnimation(MG_SPINDOWN);
}
#endif
pl.menu_active = 1 - pl.menu_active;
pl.w_attack_next = 2.0f;
pl.w_idle_next = 2.0f;
}
void
w_minigun_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, -1, pl.ammo_minigun, -1);
}
string
w_minigun_wmodel(void)
{
return "models/w_mechagun.mdl";
}
string
w_minigun_pmodel(void)
{
return "models/p_9mmar.mdl";
}
string
w_minigun_deathmsg(void)
{
return "";
}
float
w_minigun_aimanim(void)
{
return 0;
}
int
w_minigun_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (pl.ammo_minigun < 100) {
pl.ammo_minigun = bound(0, pl.ammo_minigun + 30, 100);
} else {
return FALSE;
}
#endif
return TRUE;
}
void
w_minigun_hud(void)
{
#ifdef CLIENT
vector pos;
pos = g_hudmins + (g_hudres / 2) + [-23,-15];
drawsubpic(
pos,
[47,31],
"sprites/crosshairs.spr_0.tga",
[67/256,1/128],
[47/256, 31/128],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
pos = g_hudmins + [g_hudres[0] - 125, g_hudres[1] - 42];
for (int i = 0; i < 3; i++) {
drawpic(
pos,
"gfx/vgui/640_ammo_minigun.tga",
[32,16],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
pos[1] += 8;
}
HUD_DrawAmmo2();
#endif
}
void
w_minigun_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
drawpic(
pos,
"gfx/vgui/640_weapon_minigun0.tga",
[170,43],
[1,1,1],
a,
DRAWFLAG_NORMAL
);
#endif
}
void
w_minigun_precache(void)
{
#ifdef SERVER
Sound_Precache("weapon_minigun.fire");
Sound_Precache("weapon_minigun.spindown");
Sound_Precache("weapon_minigun.spinup");
#endif
precache_model("models/v_mechagun.mdl");
precache_model("models/w_mechagun.mdl");
precache_model("models/p_9mmar.mdl");
}
weapon_t w_minigun =
{
.name = "minigun",
.id = ITEM_MINIGUN,
.slot = 2,
.slot_pos = 1,
.draw = w_minigun_draw,
.holster = w_minigun_holster,
.primary = w_minigun_primary,
.secondary = w_minigun_secondary,
.reload = __NULL__,
.release = w_minigun_release,
.crosshair = w_minigun_hud,
.precache = w_minigun_precache,
.pickup = w_minigun_pickup,
.updateammo = w_minigun_updateammo,
.wmodel = w_minigun_wmodel,
.pmodel = w_minigun_pmodel,
.deathmsg = w_minigun_deathmsg,
.aimanim = w_minigun_aimanim,
.hudpic = w_minigun_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_minigun(void)
{
Weapons_InitItem(WEAPON_MINIGUN);
}
#endif

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

@ -0,0 +1,409 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum
{
SHOTGUN_DRAW, // 0.909091f
SHOTGUN_IDLE, // 2.0f
SHOTGUN_FIDGET, // 2.0f
SHOTGUN_SHOOT1, // 0.846154f
SHOTGUN_SHOOT2, // 0.846154f
SHOTGUN_SHOOT3, // 0.846154f
SHOTGUN_SHOOT4, // 0.846154f
SHOTGUN_CUSTOMIZE // 2.25f
};
enum
{
SMENU_NONE,
SMENU_SHELLS,
SMENU_SPREAD
};
enum
{
SPREAD_RIOT,
SPREAD_SHOT,
SPREAD_RIFLE
};
#ifdef CLIENT
string gsmodes[] = {
"RIOTGUN",
"SHOTGUN",
"RIFLE"
};
#endif
void
w_shotgun_draw(void)
{
Weapons_SetModel("models/v_shotgun.mdl");
Weapons_SetGeomset("geomset 1 1\n");
Weapons_ViewAnimation(SHOTGUN_DRAW);
}
void
w_shotgun_holster(void)
{
Weapons_ViewAnimation(SHOTGUN_DRAW);
}
void
w_shotgun_primary(void)
{
vector src;
player pl = (player)self;
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
if (pl.menu_active > 0) {
pl.menu_active = 0;
pl.gflags |= GF_SEMI_TOGGLED;
Weapons_ViewAnimation(SHOTGUN_CUSTOMIZE);
pl.w_attack_next = 2.25f;
pl.w_idle_next = 2.25f;
return;
}
if (pl.w_attack_next) {
return;
}
src = Weapons_GetCameraPos();
pl.velocity += v_forward * -128;
#ifdef SERVER
vector spread = [0.1,0.05];
int pellets;
switch (pl.shotgun_spread) {
case SPREAD_RIOT:
spread = [0.1,0.1];
break;
case SPREAD_RIFLE:
spread = [0.05,0.05];
break;
default:
spread = [0.1,0.05];
}
pellets = pl.shotgun_shells * 4;
TraceAttack_FireBullets(pellets, src, 5, spread, WEAPON_SHOTGUN);
Sound_Play(pl, CHAN_WEAPON, "weapon_shotgun.fire");
#else
View_SetMuzzleflash(MUZZLE_SMALL);
Weapons_ViewPunchAngle([-5,0,0]);
int r = (float)input_sequence % 4;
switch (r) {
case 0:
Weapons_ViewAnimation(SHOTGUN_SHOOT1);
break;
case 1:
Weapons_ViewAnimation(SHOTGUN_SHOOT2);
break;
case 2:
Weapons_ViewAnimation(SHOTGUN_SHOOT3);
break;
default:
Weapons_ViewAnimation(SHOTGUN_SHOOT4);
}
#endif
pl.w_attack_next = 0.846154f;
pl.w_idle_next = 2.5f;
}
void
w_shotgun_secondary(void)
{
player pl = (player)self;
if (pl.w_attack_next) {
return;
}
if (pl.gflags & GF_SEMI_TOGGLED) {
return;
}
/* activate menu */
if (pl.menu_active <= 0) {
pl.menu_active = 1;
} else {
if (pl.menu_active == 1) {
pl.menu_active = 2;
} else {
pl.menu_active = 1;
}
}
pl.gflags |= GF_SEMI_TOGGLED;
}
void
w_shotgun_release(void)
{
player pl = (player)self;
if (pl.w_idle_next) {
return;
}
int r = (float)input_sequence % 5;
switch (r) {
case 0:
case 1:
case 2:
case 3:
Weapons_ViewAnimation(SHOTGUN_IDLE);
pl.w_idle_next = 10.0f;
break;
default:
Weapons_ViewAnimation(SHOTGUN_FIDGET);
pl.w_idle_next = 2.0f;
}
}
void
w_shotgun_updateammo(player pl)
{
Weapons_UpdateAmmo(pl, -1, pl.ammo_buckshot, -1);
}
string
w_shotgun_wmodel(void)
{
return "models/w_shotgun.mdl";
}
string
w_shotgun_pmodel(void)
{
return "models/p_shotgun.mdl";
}
string
w_shotgun_deathmsg(void)
{
return "";
}
float
w_shotgun_aimanim(void)
{
return 0;
}
int
w_shotgun_pickup(int new, int startammo)
{
#ifdef SERVER
player pl = (player)self;
if (new) {
pl.shotgun_shells = 2;
pl.shotgun_spread = SPREAD_SHOT;
}
if (pl.ammo_buckshot < 90) {
pl.ammo_buckshot = bound(0, pl.ammo_buckshot + 16, 90);
} else {
return FALSE;
}
#endif
return TRUE;
}
void
w_shotgun_hud(void)
{
#ifdef CLIENT
vector pos;
player pl = (player)self;
pos = g_hudmins + [g_hudres[0] - 125, g_hudres[1] - 42];
for (int i = 0; i < 3; i++) {
drawpic(
pos,
"gfx/vgui/640_ammo_buckshot.tga",
[32,16],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
pos[1] += 8;
}
HUD_DrawAmmo2();
/* menu */
if (pl.menu_active > 0) {
vector col1, col2;
string shellstr, spreadstr;
col1 = col2 = [1,1,1];
switch (pl.menu_active) {
case SMENU_SHELLS:
col1 = [0,1,0];
break;
case SMENU_SPREAD:
col2 = [0,1,0];
break;
}
shellstr = sprintf("SHELLS: %i", getstati(40));
spreadstr = sprintf("SPREAD: %s", gsmodes[getstati(41)]);
pos = g_hudmins + (g_hudres / 2) + [-48,-16];
drawfont = FONT_20;
drawstring(pos, shellstr, [20,20], col1, 1.0f,
DRAWFLAG_ADDITIVE);
drawstring(pos + [0,24], spreadstr, [20,20], col2, 1.0f,
DRAWFLAG_ADDITIVE);
return;
}
/* crosshair */
pos = g_hudmins + (g_hudres / 2) + [-15,-15];
drawsubpic(
pos,
[31,31],
"sprites/crosshairs.spr_0.tga",
[34/256,1/128],
[31/256, 31/128],
[1,1,1],
1.0f,
DRAWFLAG_NORMAL
);
#endif
}
void
w_shotgun_hudpic(int selected, vector pos, float a)
{
#ifdef CLIENT
drawpic(
pos,
"gfx/vgui/640_weapon_shotgun0.tga",
[170,43],
[1,1,1],
a,
DRAWFLAG_NORMAL
);
#endif
}
void
w_shotgun_precache(void)
{
precache_model("models/v_shotgun.mdl");
precache_model("models/w_shotgun.mdl");
precache_model("models/p_shotgun.mdl");
#ifdef SERVER
Sound_Precache("weapon_shotgun.fire");
#endif
}
weapon_t w_shotgun =
{
.name = "shotgun",
.id = ITEM_SHOTGUN,
.slot = 2,
.slot_pos = 0,
.draw = w_shotgun_draw,
.holster = w_shotgun_holster,
.primary = w_shotgun_primary,
.secondary = w_shotgun_secondary,
.reload = __NULL__,
.release = w_shotgun_release,
.crosshair = w_shotgun_hud,
.precache = w_shotgun_precache,
.pickup = w_shotgun_pickup,
.updateammo = w_shotgun_updateammo,
.wmodel = w_shotgun_wmodel,
.pmodel = w_shotgun_pmodel,
.deathmsg = w_shotgun_deathmsg,
.aimanim = w_shotgun_aimanim,
.hudpic = w_shotgun_hudpic
};
/* entity definitions for pickups */
#ifdef SERVER
void
weapon_shotgun(void)
{
Weapons_InitItem(WEAPON_SHOTGUN);
}
#endif
#ifdef CLIENT
int
w_shotgun_hudforward(player pl)
{
if (pl.menu_active <= 0) {
return TRUE;
}
switch (pl.menu_active) {
case SMENU_SHELLS:
sendevent("w_shot_shell", "i", 1i);
break;
case SMENU_SPREAD:
sendevent("w_shot_spread", "i", 1i);
break;
}
return FALSE;
}
int
w_shotgun_hudback(player pl)
{
if (pl.menu_active <= 0) {
return TRUE;
}
switch (pl.menu_active) {
case SMENU_SHELLS:
sendevent("w_shot_shell", "i", -1i);
break;
case SMENU_SPREAD:
sendevent("w_shot_spread", "i", -1i);
break;
}
return FALSE;
}
#else
void
CSEv_w_shot_shell_i(int f)
{
player pl = (player)self;
pl.shotgun_shells = bound(1, pl.shotgun_shells + f, 4);
}
void
CSEv_w_shot_spread_i(int f)
{
player pl = (player)self;
pl.shotgun_spread = bound(SPREAD_RIOT, pl.shotgun_spread + f, SPREAD_RIFLE);
}
#endif

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

@ -0,0 +1,30 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Weapon Indices for the weapon table */
enum
{
WEAPON_NONE,
WEAPON_FISTS, // 0
WEAPON_AICORE,
WEAPON_GAUSSPISTOL, // 1
WEAPON_SHOTGUN, // 2
WEAPON_MINIGUN, // 2
WEAPON_BEAMGUN, // 3
WEAPON_DML, // 3
WEAPON_GRENADE,
WEAPON_CHEMICALGUN
};

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

@ -0,0 +1,74 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
weapon_t w_null = {};
weapon_t g_weapons[] = {
w_null,
w_fists,
w_aicore,
w_gausspistol,
w_shotgun,
w_minigun,
w_beamgun,
w_dml,
w_grenade,
w_chemicalgun
};
#ifdef CLIENT
int(player) gp_inputforward[] = {
__NULL__,
__NULL__,
__NULL__,
w_gausspistol_hudforward,
w_shotgun_hudforward,
__NULL__,
w_beamgun_hudforward,
w_dml_hudforward,
w_grenade_hudforward,
w_chemgun_hudforward
}
int(player) gp_inputback[] = {
__NULL__,
__NULL__,
__NULL__,
w_gausspistol_hudback,
w_shotgun_hudback,
__NULL__,
w_beamgun_hudback,
w_dml_hudback,
w_grenade_hudback,
w_chemgun_hudback
}
int Weapons_InputForward(player pl)
{
if (gp_inputforward[pl.activeweapon] != __NULL__) {
return gp_inputforward[pl.activeweapon](pl);
}
return TRUE;
}
int Weapons_InputBack(player pl)
{
if (gp_inputback[pl.activeweapon] != __NULL__) {
return gp_inputback[pl.activeweapon](pl);
}
return TRUE;
}
#endif

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

@ -0,0 +1,45 @@
// Generic Binds
bind "ESC" "togglemenu"
bind "w" "+forward"
bind "s" "+back"
bind "a" "+moveleft"
bind "d" "+moveright"
bind "SPACE" "+jump"
bind "CTRL" "+duck"
bind "SHIFT" "+speed"
bind "0" "slot10"
bind "1" "slot1"
bind "2" "slot2"
bind "3" "slot3"
bind "4" "slot4"
bind "5" "slot5"
bind "6" "slot6"
bind "7" "slot7"
bind "8" "slot8"
bind "9" "slot9"
bind "UPARROW" "+forward"
bind "DOWNARROW" "+back"
bind "LEFTARROW" "+left"
bind "RIGHTARROW" "+right"
bind "MOUSE1" "+attack"
bind "MOUSE2" "+attack2"
bind "MWHEELDOWN" "invnext"
bind "MWHEELUP" "invprev"
bind "r" "+reload"
bind "e" "+use"
bind "TAB" "+showscores"
bind "y" "messagemode"
bind "u" "messagemode2"
bind "t" "impulse 201"
bind "f" "impulse 100"
bind "f1" "vote yes"
bind "f2" "vote no"
// Game Variables
seta "hostname" "FreeRewolf Server"
seta "maxplayers" "8"
// 2D/HUD Variables
seta "con_color" "255 150 0"
seta "vgui_color" "255 170 0"
seta "cross_color" "0 255 0"

View File

@ -0,0 +1,76 @@
cinematic1.bsp
cinematic2.bsp
cinematic3.bsp
cinematic4.bsp
city1a.bsp
city1b.bsp
city2a.bsp
city2b.bsp
city3a.bsp
city3b.bsp
demo1.bsp
demo2.bsp
demo3.bsp
demo4.bsp
demo5.bsp
demo6.bsp
demo6a.bsp
demo7.bsp
demo8.bsp
end1.bsp
end2.bsp
mayan0a.bsp
mayan0b.bsp
mayan1.bsp
mayan3a.bsp
mayan4.bsp
mayan6.bsp
mayan8.bsp
rebar0a.bsp
rebar0b.bsp
rebar2a.bsp
rebar2b.bsp
rebar2c.bsp
rebar2d.bsp
rebar2e.bsp
rebar2f.bsp
rebar2g.bsp
rebar2h.bsp
rebar2i.bsp
rebar2j.bsp
rebar2k.bsp
rebar2l.bsp
rebar3b.bsp
rebar3d.bsp
rebar3e.bsp
rust1.bsp
rust2a.bsp
rust2b.bsp
rust3a.bsp
rust4a.bsp
rust4b.bsp
rust4c.bsp
rust5a.bsp
rust6a.bsp
rust6b.bsp
rust6c.bsp
rust6d.bsp
rust7a.bsp
rust7b.bsp
rust7c.bsp
rust7d.bsp
rust7e.bsp
rust8a.bsp
rust9a.bsp
west1.bsp
west2.bsp
west3a.bsp
west3b.bsp
west4a.bsp
west4b.bsp
west5b.bsp
west6a.bsp
west6b.bsp
west6c.bsp
west6d.bsp
west6e.bsp

View File

@ -0,0 +1,81 @@
weapon_dml.customize
{
sample weapons/dml_customize.wav
}
weapon_dml.fire
{
sample weapons/dml_fire.wav
}
weapon_dml.reload
{
sample weapons/dml_reload.wav
}
weapon_fists.knifedraw
{
sample weapons/KnifeDraw.wav
}
weapon_fists.hitleft
{
sample weapons/LeftPunch.wav
sample weapons/LeftPunch2.wav
sample weapons/LeftPunch3.wav
}
weapon_fists.hitright
{
sample weapons/RightPunch.wav
sample weapons/RightPunch2.wav
sample weapons/RightPunch3.wav
}
weapon_fists.missknife
{
sample weapons/cbar_miss1.wav
sample weapons/cbar_miss2.wav
}
weapon_gausspistol.charge
{
sample weapons/gauss_charge.wav
}
weapon_gausspistol.firecharge
{
sample weapons/gauss_fire2.wav
}
weapon_gausspistol.firefast
{
sample weapons/gauss_fire4.wav
}
weapon_gausspistol.firesingle
{
sample weapons/gauss_fire1.wav
}
weapon_minigun.fire
{
sample weapons/hks1.wav
sample weapons/hks2.wav
sample weapons/hks3.wav
}
weapon_minigun.spindown
{
sample weapons/MechaSpinDown.wav
}
weapon_minigun.spinup
{
sample weapons/MechaSpinUp.wav
}
weapon_shotgun.fire
{
sample weapons/sbarrel1.wav
}