Initial commit of the fixed codebase
This commit is contained in:
commit
542bc73bef
48 changed files with 5979 additions and 0 deletions
5
src/Makefile
Normal file
5
src/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
CC=fteqcc
|
||||
|
||||
all:
|
||||
cd client && $(MAKE)
|
||||
cd server && $(MAKE)
|
4
src/client/Makefile
Normal file
4
src/client/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
CC=fteqcc
|
||||
|
||||
all:
|
||||
$(CC) progs.src
|
26
src/client/entities.qc
Normal file
26
src/client/entities.qc
Normal 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
|
||||
Game_Entity_Update(float id, float new)
|
||||
{
|
||||
switch (id) {
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
154
src/client/game_event.qc
Normal file
154
src/client/game_event.qc
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* 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_Parse_Event(float fHeader)
|
||||
{
|
||||
switch (fHeader) {
|
||||
case EV_OBITUARY:
|
||||
Obituary_Parse();
|
||||
break;
|
||||
case EV_SPARK:
|
||||
vector vSparkPos, vSparkAngle;
|
||||
vSparkPos[0] = readcoord();
|
||||
vSparkPos[1] = readcoord();
|
||||
vSparkPos[2] = readcoord();
|
||||
vSparkAngle[0] = readcoord();
|
||||
vSparkAngle[1] = readcoord();
|
||||
vSparkAngle[2] = readcoord();
|
||||
FX_Spark(vSparkPos, vSparkAngle);
|
||||
break;
|
||||
case EV_GIBHUMAN:
|
||||
vector vGibPos;
|
||||
vGibPos[0] = readcoord();
|
||||
vGibPos[1] = readcoord();
|
||||
vGibPos[2] = readcoord();
|
||||
FX_GibHuman(vGibPos);
|
||||
break;
|
||||
case EV_BLOOD:
|
||||
vector vBloodPos;
|
||||
vector vBloodColor;
|
||||
|
||||
vBloodPos[0] = readcoord();
|
||||
vBloodPos[1] = readcoord();
|
||||
vBloodPos[2] = readcoord();
|
||||
|
||||
vBloodColor[0] = readbyte() / 255;
|
||||
vBloodColor[1] = readbyte() / 255;
|
||||
vBloodColor[2] = readbyte() / 255;
|
||||
|
||||
FX_Blood(vBloodPos, vBloodColor);
|
||||
break;
|
||||
case EV_LEGO:
|
||||
vector vLegoPos;
|
||||
|
||||
vLegoPos[0] = readcoord();
|
||||
vLegoPos[1] = readcoord();
|
||||
vLegoPos[2] = readcoord();
|
||||
|
||||
FX_Lego(vLegoPos);
|
||||
break;
|
||||
case EV_LEGOPIECE:
|
||||
vector vLegoPiecePos;
|
||||
|
||||
vLegoPiecePos[0] = readcoord();
|
||||
vLegoPiecePos[1] = readcoord();
|
||||
vLegoPiecePos[2] = readcoord();
|
||||
|
||||
FX_LegoPiece(vLegoPiecePos);
|
||||
break;
|
||||
case EV_SODA:
|
||||
vector vSodaPos;
|
||||
int vSodaColor;
|
||||
|
||||
vSodaPos[0] = readcoord();
|
||||
vSodaPos[1] = readcoord();
|
||||
vSodaPos[2] = readcoord();
|
||||
|
||||
vSodaColor = readbyte();
|
||||
|
||||
FX_Soda(vSodaPos, vSodaColor);
|
||||
break;
|
||||
case EV_EXPLOSION:
|
||||
vector vExploPos;
|
||||
|
||||
vExploPos[0] = readcoord();
|
||||
vExploPos[1] = readcoord();
|
||||
vExploPos[2] = readcoord();
|
||||
|
||||
FX_Explosion(vExploPos);
|
||||
break;
|
||||
case EV_MODELGIB:
|
||||
vector vecPos;
|
||||
vecPos[0] = readcoord();
|
||||
vecPos[1] = readcoord();
|
||||
vecPos[2] = readcoord();
|
||||
|
||||
vector vSize;
|
||||
vSize[0] = readcoord();
|
||||
vSize[1] = readcoord();
|
||||
vSize[2] = readcoord();
|
||||
|
||||
float fStyle = readbyte();
|
||||
int count = readbyte();
|
||||
FX_BreakModel(count, vecPos, vSize, [0,0,0], fStyle);
|
||||
break;
|
||||
case EV_IMPACT:
|
||||
int iType;
|
||||
vector vOrigin, vNormal;
|
||||
|
||||
iType = (int)readbyte();
|
||||
vOrigin[0] = readcoord();
|
||||
vOrigin[1] = readcoord();
|
||||
vOrigin[2] = readcoord();
|
||||
|
||||
vNormal[0] = readcoord();
|
||||
vNormal[1] = readcoord();
|
||||
vNormal[2] = readcoord();
|
||||
|
||||
FX_Impact(iType, vOrigin, vNormal);
|
||||
break;
|
||||
case EV_CHAT:
|
||||
float fSender = readbyte();
|
||||
float fTeam = readbyte();
|
||||
string sMessage = readstring();
|
||||
|
||||
CSQC_Parse_Print(sprintf("%s: %s", getplayerkeyvalue(fSender, "name"), sMessage), PRINT_CHAT);
|
||||
break;
|
||||
case EV_CHAT_TEAM:
|
||||
float fSender2 = readbyte();
|
||||
float fTeam2 = readbyte();
|
||||
string sMessage2 = readstring();
|
||||
|
||||
CSQC_Parse_Print(sprintf("[TEAM] %s: %s", getplayerkeyvalue(fSender2, "name"), sMessage2), PRINT_CHAT);
|
||||
break;
|
||||
case EV_CHAT_VOX:
|
||||
Vox_Play(readstring());
|
||||
break;
|
||||
case EV_VIEWMODEL:
|
||||
View_PlayAnimation(readbyte());
|
||||
break;
|
||||
case EV_WEAPON_PICKUP:
|
||||
int w = readbyte();
|
||||
|
||||
if (autocvar_cl_autoweaponswitch == 1) {
|
||||
sendevent("PlayerSwitchWeapon", "i", w);
|
||||
}
|
||||
|
||||
HUD_WeaponPickupNotify(w);
|
||||
break;
|
||||
}
|
||||
}
|
395
src/client/hud.qc
Normal file
395
src/client/hud.qc
Normal file
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
* 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 HUD_DrawWeaponSelect(void);
|
||||
|
||||
/* Use first frame for drawing (needs precache) */
|
||||
#define HUD_NUMS "sprites/640_numbers.spr_0.tga"
|
||||
#define NUMSIZE_X 32/256
|
||||
#define NUMSIZE_Y 32/64
|
||||
#define HUD_ALPHA 1.0
|
||||
|
||||
vector spr_hudnum[10] = {
|
||||
[0 / 256, 0],
|
||||
[32 / 256, 0],
|
||||
[(32*2) / 256, 0],
|
||||
[(32*3) / 256, 0],
|
||||
[(32*4) / 256, 0],
|
||||
[(32*5) / 256, 0],
|
||||
[(32*6) / 256, 0],
|
||||
[(32*7) / 256, 0],
|
||||
[0 / 256, 32/64],
|
||||
[32 / 256, 32/64]
|
||||
};
|
||||
|
||||
/* pre-calculated sprite definitions */
|
||||
float spr_health[4] = {
|
||||
80 / 256, // pos x
|
||||
24 / 128, // pos y
|
||||
32 / 256, // size x
|
||||
32 / 128 // size y
|
||||
};
|
||||
|
||||
#define HUD_SUIT "sprites/640_suit.spr_0.tga"
|
||||
#define SUITSIZE_X 32/128
|
||||
#define SUITSIZE_Y 32/64
|
||||
|
||||
float spr_suit1[4] = {
|
||||
0 / 128, // pos x
|
||||
0 / 128, // pos y
|
||||
40 / 128, // size x
|
||||
40 / 64 // size y
|
||||
};
|
||||
|
||||
float spr_suit2[4] = {
|
||||
40 / 128, // pos x
|
||||
0 / 128, // pos y
|
||||
40 / 128, // size x
|
||||
40 / 64 // size y
|
||||
};
|
||||
|
||||
#define HUD_FLASH "sprites/640hud7.spr_0.tga"
|
||||
#define FLASHSIZE_X 24/256
|
||||
#define FLASHSIZE_Y 24/128
|
||||
|
||||
float spr_flash1[4] = {
|
||||
160 / 256, // pos x
|
||||
24 / 128, // pos y
|
||||
32 / 256, // size x
|
||||
32 / 128 // size y
|
||||
};
|
||||
|
||||
float spr_flash2[4] = {
|
||||
112 / 256, // pos x
|
||||
24 / 128, // pos u
|
||||
48 / 256, // size x
|
||||
32 / 128 // size y
|
||||
};
|
||||
|
||||
/* precaches */
|
||||
void
|
||||
HUD_Init(void)
|
||||
{
|
||||
precache_model("sprites/640_cross.spr");
|
||||
precache_model("sprites/640_numbers.spr");
|
||||
precache_model("sprites/640_logo.spr");
|
||||
precache_model("sprites/640_suit.spr");
|
||||
precache_model("sprites/640hud7.spr");
|
||||
}
|
||||
|
||||
/* handle single/multiple digits */
|
||||
void
|
||||
HUD_DrawNumber(int iNumber, vector vecPos, float fAlpha, vector vColor)
|
||||
{
|
||||
drawsubpic(vecPos,
|
||||
[32,32],
|
||||
"sprites/640_numbers.spr_0.tga",
|
||||
spr_hudnum[iNumber],
|
||||
[NUMSIZE_X, NUMSIZE_Y],
|
||||
vColor,
|
||||
fAlpha,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
HUD_DrawNums(float fNumber, vector vecPos, float fAlpha, vector vColor)
|
||||
{
|
||||
int i = fNumber;
|
||||
if (i > 0) {
|
||||
while (i > 0) {
|
||||
HUD_DrawNumber((float)i % 10, vecPos, fAlpha, vColor);
|
||||
i = i / 10;
|
||||
vecPos[0] -= 32;
|
||||
}
|
||||
} else {
|
||||
HUD_DrawNumber(0, vecPos, fAlpha, vColor);
|
||||
}
|
||||
}
|
||||
|
||||
/* health */
|
||||
/* We don't need the changing color if case
|
||||
* it's always red in Household DEATH! */
|
||||
void
|
||||
HUD_DrawHealth(void)
|
||||
{
|
||||
vector pos;
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
if (pl.health != pSeat->m_iHealthOld) {
|
||||
pSeat->m_flHealthAlpha = 1.0;
|
||||
}
|
||||
|
||||
if (pSeat->m_flHealthAlpha >= HUD_ALPHA) {
|
||||
pSeat->m_flHealthAlpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeat->m_flHealthAlpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
pos = g_hudmins + [14, g_hudres[1] - 42];
|
||||
drawpic(
|
||||
pos,
|
||||
"sprites/640_cross.spr_0.tga",
|
||||
[32,32],
|
||||
[1,1,1],
|
||||
pSeat->m_flHealthAlpha
|
||||
);
|
||||
HUD_DrawNums(pl.health, pos + [96], pSeat->m_flHealthAlpha, g_hud_color);
|
||||
|
||||
pSeat->m_iHealthOld = pl.health;
|
||||
}
|
||||
|
||||
/* armor/suit charge */
|
||||
void
|
||||
HUD_DrawArmor(void)
|
||||
{
|
||||
vector pos;
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
pos = g_hudmins + [198, g_hudres[1] - 42];
|
||||
|
||||
if (pl.armor != pSeat->m_iArmorOld) {
|
||||
pSeat->m_flArmorAlpha = 1.0;
|
||||
}
|
||||
|
||||
if (pSeat->m_flArmorAlpha >= HUD_ALPHA) {
|
||||
pSeat->m_flArmorAlpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeat->m_flArmorAlpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
drawsubpic(
|
||||
pos + [-48,-9],
|
||||
[40,40],
|
||||
HUD_SUIT,
|
||||
[spr_suit2[0], spr_suit2[1]],
|
||||
[spr_suit2[2], spr_suit2[3]],
|
||||
[1,1,1],
|
||||
1.0f
|
||||
);
|
||||
|
||||
if (pl.armor > 0) {
|
||||
drawsubpic(
|
||||
pos + [-48,-9],
|
||||
[40, 40 * (pl.armor / 100)],
|
||||
HUD_SUIT,
|
||||
[spr_suit1[0],
|
||||
spr_suit1[1]],
|
||||
[spr_suit1[2], spr_suit1[3] * (pl.armor / 100)],
|
||||
[1,1,1],
|
||||
1.0f
|
||||
);
|
||||
}
|
||||
|
||||
HUD_DrawNums(pl.armor, pos + [48] , pSeat->m_flArmorAlpha, g_hud_color);
|
||||
pSeat->m_iArmorOld = pl.armor;
|
||||
}
|
||||
|
||||
/* magazine/clip ammo */
|
||||
void
|
||||
HUD_DrawAmmo1(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
vector pos;
|
||||
|
||||
if (pl.a_ammo1 != pSeat->m_iAmmo1Old) {
|
||||
pSeat->m_flAmmo1Alpha = 1.0;
|
||||
pSeat->m_iAmmo1Old = pl.a_ammo1;
|
||||
}
|
||||
|
||||
if (pSeat->m_flAmmo1Alpha >= HUD_ALPHA) {
|
||||
pSeat->m_flAmmo1Alpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeat->m_flAmmo1Alpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
pos = g_hudmins + [g_hudres[0] - 152, g_hudres[1] - 42];
|
||||
HUD_DrawNums(pl.a_ammo1, pos, pSeat->m_flAmmo1Alpha, g_hud_color);
|
||||
}
|
||||
|
||||
/* leftover type ammo */
|
||||
void
|
||||
HUD_DrawAmmo2(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
vector pos;
|
||||
|
||||
if (pl.a_ammo2 != pSeat->m_iAmmo2Old) {
|
||||
pSeat->m_flAmmo2Alpha = 1.0;
|
||||
pSeat->m_iAmmo2Old = pl.a_ammo2;
|
||||
}
|
||||
|
||||
if (pSeat->m_flAmmo2Alpha >= HUD_ALPHA) {
|
||||
pSeat->m_flAmmo2Alpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeat->m_flAmmo2Alpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 42];
|
||||
HUD_DrawNums(pl.a_ammo2, pos, pSeat->m_flAmmo2Alpha, g_hud_color);
|
||||
}
|
||||
|
||||
/* special ammo */
|
||||
void
|
||||
HUD_DrawAmmo3(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
vector pos;
|
||||
|
||||
if (pl.a_ammo3 != pSeat->m_iAmmo3Old) {
|
||||
pSeat->m_flAmmo3Alpha = 1.0;
|
||||
pSeat->m_iAmmo3Old = pl.a_ammo3;
|
||||
}
|
||||
|
||||
if (pSeat->m_flAmmo3Alpha >= HUD_ALPHA) {
|
||||
pSeat->m_flAmmo3Alpha -= clframetime * 0.5;
|
||||
} else {
|
||||
pSeat->m_flAmmo3Alpha = HUD_ALPHA;
|
||||
}
|
||||
|
||||
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 74];
|
||||
HUD_DrawNums(pl.a_ammo3, pos, pSeat->m_flAmmo3Alpha, g_hud_color);
|
||||
}
|
||||
|
||||
/* flashlight/torch indicator */
|
||||
void
|
||||
HUD_DrawFlashlight(void)
|
||||
{
|
||||
vector pos;
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
pos = g_hudmins + [g_hudres[0] - 48, 16];
|
||||
|
||||
/* both on, draw both sprites at full intensity */
|
||||
if (pl.gflags & GF_FLASHLIGHT) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[32,32],
|
||||
HUD_FLASH,
|
||||
[spr_flash1[0], spr_flash1[1]],
|
||||
[spr_flash1[2], spr_flash1[3]],
|
||||
g_hud_color,
|
||||
1.0f,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
|
||||
drawsubpic(
|
||||
pos,
|
||||
[48,32],
|
||||
HUD_FLASH,
|
||||
[spr_flash2[0], spr_flash2[1]],
|
||||
[spr_flash2[2], spr_flash2[3]],
|
||||
g_hud_color,
|
||||
1.0f,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[32,32],
|
||||
HUD_FLASH,
|
||||
[spr_flash1[0], spr_flash1[1]],
|
||||
[spr_flash1[2], spr_flash1[3]],
|
||||
g_hud_color,
|
||||
HUD_ALPHA,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* logo animation used during e3 1998 */
|
||||
void
|
||||
HUD_DrawLogo(void)
|
||||
{
|
||||
vector pos;
|
||||
static int f;
|
||||
static float frame_timer;
|
||||
|
||||
frame_timer -= clframetime;
|
||||
pos = [g_hudres[0] - 262, 48];
|
||||
|
||||
drawpic(
|
||||
pos,
|
||||
sprintf("sprites/640_logo.spr_%i.tga", f),
|
||||
[256,48],
|
||||
[1,1,1],
|
||||
1.0f,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
|
||||
if (frame_timer > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
frame_timer = 0.1f;
|
||||
|
||||
f++;
|
||||
if (f == 31) {
|
||||
f = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* weapon/ammo pickup notifications */
|
||||
void
|
||||
HUD_DrawNotify(void)
|
||||
{
|
||||
vector pos;
|
||||
|
||||
if (pSeat->m_flPickupAlpha <= 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
pos = g_hudmins + [g_hudres[0] - 192, g_hudres[1] - 128];
|
||||
Weapons_HUDPic(pSeat->m_iPickupWeapon, 1, pos, pSeat->m_flPickupAlpha);
|
||||
pSeat->m_flPickupAlpha -= clframetime;
|
||||
}
|
||||
|
||||
void
|
||||
HUD_WeaponPickupNotify(int w)
|
||||
{
|
||||
pSeat->m_iPickupWeapon = w;
|
||||
pSeat->m_flPickupAlpha = 1.0f;
|
||||
}
|
||||
|
||||
/* main entry */
|
||||
void
|
||||
HUD_Draw(void)
|
||||
{
|
||||
player pl = (player)pSeat->m_ePlayer;
|
||||
|
||||
g_hud_color = autocvar_con_color * (1 / 255);
|
||||
|
||||
/* little point in not drawing these, even if you don't have a suit */
|
||||
Weapons_DrawCrosshair();
|
||||
HUD_DrawWeaponSelect();
|
||||
Obituary_Draw();
|
||||
|
||||
if (!(pl.g_items & ITEM_SUIT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
HUD_DrawHealth();
|
||||
HUD_DrawArmor();
|
||||
HUD_DrawFlashlight();
|
||||
HUD_DrawNotify();
|
||||
Damage_Draw();
|
||||
}
|
||||
|
||||
/* specatator main entry */
|
||||
void
|
||||
HUD_DrawSpectator(void)
|
||||
{
|
||||
// FIXME
|
||||
}
|
55
src/client/init.qc
Normal file
55
src/client/init.qc
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
float(entity foo, float chanid) getchannellevel = #0;
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Client_Init
|
||||
|
||||
Comparable to worldspawn in SSQC in that it's mostly used for precaches
|
||||
=================
|
||||
*/
|
||||
void
|
||||
Client_Init(float apilevel, string enginename, float engineversion)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Client_InitDone(void)
|
||||
{
|
||||
Obituary_Init();
|
||||
}
|
||||
|
||||
void
|
||||
Game_RendererRestarted(string rstr)
|
||||
{
|
||||
FX_Blood_Init();
|
||||
FX_BreakModel_Init();
|
||||
FX_Explosion_Init();
|
||||
FX_GibHuman_Init();
|
||||
FX_Spark_Init();
|
||||
FX_Impact_Init();
|
||||
FX_Lego_Init();
|
||||
FX_Soda_Init();
|
||||
|
||||
precache_model("sprites/640_death.spr");
|
||||
precache_model("sprites/640_cross.spr");
|
||||
precache_model("sprites/640_numbers.spr");
|
||||
precache_model("sprites/640_suit.spr");
|
||||
precache_model("sprites/640hud7.spr");
|
||||
}
|
215
src/client/obituary.qc
Normal file
215
src/client/obituary.qc
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* 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
|
||||
Obituary_Init(void)
|
||||
{
|
||||
int c;
|
||||
int i;
|
||||
filestream fh;
|
||||
string line;
|
||||
vector tmp;
|
||||
|
||||
if (g_obtype_count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
print("Init Obituaries\n");
|
||||
g_obtype_count = 0;
|
||||
i = 0;
|
||||
|
||||
fh = fopen("sprites/hud.txt", FILE_READ);
|
||||
if (fh < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* count valid entries */
|
||||
while ((line = fgets(fh))) {
|
||||
if (substring(line, 0, 2) == "d_") {
|
||||
c = tokenize(line);
|
||||
if (c == 7 && argv(1) == "640") {
|
||||
g_obtype_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_obtypes = memalloc(sizeof(obituaryimg_t) * g_obtype_count);
|
||||
|
||||
fseek(fh, 0);
|
||||
|
||||
/* read them in */
|
||||
while ((line = fgets(fh))) {
|
||||
if (substring(line, 0, 2) == "d_") {
|
||||
c = tokenize(line);
|
||||
|
||||
/* we only care about the high-res (640) variants. the 320
|
||||
* HUD is useless to us. Just use the builtin scaler */
|
||||
if (c == 7 && argv(1) == "640") {
|
||||
g_obtypes[i].name = substring(argv(0), 2, -1);
|
||||
g_obtypes[i].src_sprite = sprintf("sprites/%s.spr", argv(2));
|
||||
precache_model(g_obtypes[i].src_sprite);
|
||||
g_obtypes[i].sprite = sprintf("sprites/%s.spr_0.tga", argv(2));
|
||||
g_obtypes[i].size[0] = stof(argv(5));
|
||||
g_obtypes[i].size[1] = stof(argv(6));
|
||||
tmp = drawgetimagesize(g_obtypes[i].sprite);
|
||||
g_obtypes[i].src_pos[0] = stof(argv(3)) / tmp[0];
|
||||
g_obtypes[i].src_pos[1] = stof(argv(4)) / tmp[1];
|
||||
g_obtypes[i].src_size[0] = g_obtypes[i].size[0] / tmp[0];
|
||||
g_obtypes[i].src_size[1] = g_obtypes[i].size[1] / tmp[1];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fh);
|
||||
}
|
||||
|
||||
void
|
||||
Obituary_Precache(void)
|
||||
{
|
||||
print("Precache Obituaries\n");
|
||||
|
||||
for (int i = 0; i < g_obtype_count; i++)
|
||||
precache_model(g_obtypes[i].src_sprite);
|
||||
}
|
||||
|
||||
void
|
||||
Obituary_KillIcon(int id, float w)
|
||||
{
|
||||
for (int i = 0; i < g_obtype_count; i++) {
|
||||
if (g_weapons[w].name == g_obtypes[i].name) {
|
||||
g_obituary[id].icon = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* look for skull instead */
|
||||
for (int i = 0; i < g_obtype_count; i++) {
|
||||
if (g_obtypes[i].name == "skull") {
|
||||
g_obituary[id].icon = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Obituary_Add(string attacker, string victim, float weapon, float flags)
|
||||
{
|
||||
int i;
|
||||
int x, y;
|
||||
x = OBITUARY_LINES;
|
||||
|
||||
/* we're not full yet, so fill up the buffer */
|
||||
if (g_obituary_count < x) {
|
||||
y = g_obituary_count;
|
||||
g_obituary[y].attacker = attacker;
|
||||
g_obituary[y].victim = victim;
|
||||
Obituary_KillIcon(y, weapon);
|
||||
g_obituary_count++;
|
||||
} else {
|
||||
for (i = 0; i < (x-1); i++) {
|
||||
g_obituary[i].attacker = g_obituary[i+1].attacker;
|
||||
g_obituary[i].victim = g_obituary[i+1].victim;
|
||||
g_obituary[i].icon = g_obituary[i+1].icon;
|
||||
}
|
||||
/* after rearranging, add the newest to the bottom. */
|
||||
g_obituary[x-1].attacker = attacker;
|
||||
g_obituary[x-1].victim = victim;
|
||||
Obituary_KillIcon(x-1, weapon);
|
||||
}
|
||||
|
||||
g_obituary_time = OBITUARY_TIME;
|
||||
}
|
||||
|
||||
void
|
||||
Obituary_Draw(void)
|
||||
{
|
||||
int i;
|
||||
vector pos;
|
||||
vector item;
|
||||
drawfont = FONT_CON;
|
||||
pos = g_hudmins + [g_hudres[0] - 18, 56];
|
||||
|
||||
if (g_obituary_time <= 0 && g_obituary_count > 0) {
|
||||
for (i = 0; i < (OBITUARY_LINES-1); i++) {
|
||||
g_obituary[i].attacker = g_obituary[i+1].attacker;
|
||||
g_obituary[i].victim = g_obituary[i+1].victim;
|
||||
g_obituary[i].icon = g_obituary[i+1].icon;
|
||||
}
|
||||
g_obituary[OBITUARY_LINES-1].attacker = "";
|
||||
|
||||
g_obituary_time = OBITUARY_TIME;
|
||||
g_obituary_count--;
|
||||
}
|
||||
|
||||
if (g_obituary_count <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
item = pos;
|
||||
for (i = 0; i < OBITUARY_LINES; i++) {
|
||||
string a, v;
|
||||
|
||||
if (!g_obituary[i].attacker) {
|
||||
break;
|
||||
}
|
||||
|
||||
item[0] = pos[0];
|
||||
|
||||
|
||||
v = g_obituary[i].victim;
|
||||
drawstring_r(item + [0,2], v, [12,12], [1,1,1], 1.0f, 0);
|
||||
item[0] -= stringwidth(v, TRUE, [12,12]) + 4;
|
||||
item[0] -= g_obtypes[g_obituary[i].icon].size[0];
|
||||
|
||||
drawsubpic(
|
||||
item,
|
||||
[g_obtypes[g_obituary[i].icon].size[0], g_obtypes[g_obituary[i].icon].size[1]],
|
||||
g_obtypes[g_obituary[i].icon].sprite,
|
||||
[g_obtypes[g_obituary[i].icon].src_pos[0],g_obtypes[g_obituary[i].icon].src_pos[1]],
|
||||
[g_obtypes[g_obituary[i].icon].src_size[0],g_obtypes[g_obituary[i].icon].src_size[1]],
|
||||
[1,1,1],
|
||||
1.0f,
|
||||
0
|
||||
);
|
||||
|
||||
a = g_obituary[i].attacker;
|
||||
drawstring_r(item + [-4,2], a, [12,12], [1,1,1], 1.0f, 0);
|
||||
item[1] += 18;
|
||||
}
|
||||
|
||||
g_obituary_time = max(0, g_obituary_time - clframetime);
|
||||
}
|
||||
|
||||
void
|
||||
Obituary_Parse(void)
|
||||
{
|
||||
string attacker;
|
||||
string victim;
|
||||
float weapon;
|
||||
float flags;
|
||||
|
||||
attacker = readstring();
|
||||
victim = readstring();
|
||||
weapon = readbyte();
|
||||
flags = readbyte();
|
||||
|
||||
if (!attacker) {
|
||||
return;
|
||||
}
|
||||
|
||||
Obituary_Add(attacker, victim, weapon, flags);
|
||||
}
|
42
src/client/progs.src
Normal file
42
src/client/progs.src
Normal file
|
@ -0,0 +1,42 @@
|
|||
#pragma target fte
|
||||
#pragma progs_dat "../../csprogs.dat"
|
||||
|
||||
#define CSQC
|
||||
#define CLIENT
|
||||
#define VALVE
|
||||
#define HHDEATH
|
||||
#define CLASSIC_VGUI
|
||||
#define GS_RENDERFX
|
||||
|
||||
#includelist
|
||||
../../../src/shared/fteextensions.qc
|
||||
../../../src/shared/defs.h
|
||||
../../../valve/src/client/defs.h
|
||||
../../../src/client/defs.h
|
||||
|
||||
../../../src/vgui/include.src
|
||||
|
||||
../../../src/gs-entbase/client.src
|
||||
../../../src/gs-entbase/shared.src
|
||||
../shared/include.src
|
||||
|
||||
../../../valve/src/client/predict.qc
|
||||
init.qc
|
||||
../../../valve/src/client/player.qc
|
||||
entities.qc
|
||||
../../../valve/src/client/cmds.qc
|
||||
game_event.qc
|
||||
../../../valve/src/client/view.qc
|
||||
obituary.qc
|
||||
hud.qc
|
||||
../../../valve/src/client/hud_weaponselect.qc
|
||||
../../../valve/src/client/scoreboard.qc
|
||||
../../../valve/src/client/input.qc
|
||||
|
||||
../../../base/src/client/modelevent.qc
|
||||
../../../src/client/include.src
|
||||
../../../src/shared/include.src
|
||||
|
||||
#endlist
|
||||
|
||||
|
2
src/progs.src
Executable file
2
src/progs.src
Executable file
|
@ -0,0 +1,2 @@
|
|||
#pragma sourcefile client/progs.src
|
||||
#pragma sourcefile server/progs.src
|
4
src/server/Makefile
Normal file
4
src/server/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
|||
CC=fteqcc
|
||||
|
||||
all:
|
||||
$(CC) progs.src
|
171
src/server/ammo_hd.qc
Normal file
171
src/server/ammo_hd.qc
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
* Copyright (c) 2020 Gethyn ThomasQuail <xylemon@posteo.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
class item_ammo:CBaseEntity
|
||||
{
|
||||
void(void) item_ammo;
|
||||
virtual void(void) Respawn;
|
||||
virtual void(void) touch;
|
||||
};
|
||||
|
||||
void item_ammo::touch(void)
|
||||
{
|
||||
if not (other.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
|
||||
player pl = (player)other;
|
||||
Sound_Play(other, CHAN_ITEM, "ammo.pickup");
|
||||
Weapons_RefreshAmmo(pl);
|
||||
Logging_Pickup(other, this, __NULL__);
|
||||
|
||||
if (cvar("sv_playerslots") == 1) {
|
||||
remove(self);
|
||||
} else {
|
||||
Hide();
|
||||
think = Respawn;
|
||||
nextthink = time + 20.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void item_ammo::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_TOSS);
|
||||
SetSize([-16,-16,0],[16,16,16]);
|
||||
SetOrigin(m_oldOrigin);
|
||||
SetModel(m_oldModel);
|
||||
|
||||
think = __NULL__;
|
||||
nextthink = -1;
|
||||
Sound_Play(this, CHAN_ITEM, "ammo.respawn");
|
||||
droptofloor();
|
||||
}
|
||||
|
||||
void item_ammo::item_ammo(void)
|
||||
{
|
||||
m_oldModel = model;
|
||||
SetModel(m_oldModel);
|
||||
CBaseEntity::CBaseEntity();
|
||||
}
|
||||
|
||||
/*QUAKED ammo_forks (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Ammo for the throwable Forks.
|
||||
A single fork, despite name. It's just a fork man.
|
||||
|
||||
*/
|
||||
class ammo_forks:item_ammo
|
||||
{
|
||||
void(void) ammo_forks;
|
||||
virtual void(void) touch;
|
||||
};
|
||||
|
||||
void ammo_forks::ammo_forks(void)
|
||||
{
|
||||
model = "models/w_fork2.mdl";
|
||||
item_ammo::item_ammo();
|
||||
SetRenderMode(RM_FULLBRIGHT);
|
||||
SetRenderAmt(1.0f);
|
||||
}
|
||||
void ammo_forks::touch(void)
|
||||
{
|
||||
if not (other.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (other.classname == "player") {
|
||||
player pl = (player)other;
|
||||
if (pl.ammo_forks < MAX_A_FORKS) {
|
||||
pl.ammo_forks = bound(0, pl.ammo_forks + 1, MAX_A_FORKS);
|
||||
item_ammo::touch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*QUAKED ammo_legoblocks (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Ammo for the Lego Launcher.
|
||||
A single pack provides 12 legos.
|
||||
|
||||
*/
|
||||
|
||||
class ammo_legoblocks:item_ammo
|
||||
{
|
||||
void(void) ammo_legoblocks;
|
||||
virtual void(void) touch;
|
||||
};
|
||||
|
||||
void ammo_legoblocks::ammo_legoblocks(void)
|
||||
{
|
||||
model = "models/legoblocks.mdl";
|
||||
item_ammo::item_ammo();
|
||||
SetRenderMode(RM_FULLBRIGHT);
|
||||
SetRenderAmt(1.0f);
|
||||
}
|
||||
void ammo_legoblocks::touch(void)
|
||||
{
|
||||
if not (other.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (other.classname == "player") {
|
||||
player pl = (player)other;
|
||||
if (pl.ammo_legos < MAX_A_LEGOS) {
|
||||
pl.ammo_legos = bound(0, pl.ammo_legos + 12, MAX_A_LEGOS);
|
||||
item_ammo::touch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*QUAKED ammo_sodacans (0 0 0.8) (-16 -16 0) (16 16 32)
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Ammo for the Soda Launcher.
|
||||
A single pack provides 6 soda cans.
|
||||
|
||||
*/
|
||||
|
||||
class ammo_sodacans:item_ammo
|
||||
{
|
||||
void(void) ammo_sodacans;
|
||||
virtual void(void) touch;
|
||||
};
|
||||
|
||||
void ammo_sodacans::ammo_sodacans(void)
|
||||
{
|
||||
model = "models/nukacola.mdl";
|
||||
item_ammo::item_ammo();
|
||||
SetRenderMode(RM_FULLBRIGHT);
|
||||
SetRenderAmt(1.0f);
|
||||
}
|
||||
void ammo_sodacans::touch(void)
|
||||
{
|
||||
if not (other.flags & FL_CLIENT) {
|
||||
return;
|
||||
}
|
||||
if (other.classname == "player") {
|
||||
player pl = (player)other;
|
||||
if (pl.ammo_soda < MAX_A_SODA) {
|
||||
pl.ammo_soda = bound(0, pl.ammo_soda + 6, MAX_A_SODA);
|
||||
item_ammo::touch();
|
||||
}
|
||||
}
|
||||
}
|
18
src/server/defs.h
Normal file
18
src/server/defs.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "gamerules.h"
|
||||
#include "../../../valve/src/server/items.h"
|
33
src/server/gamerules.h
Normal file
33
src/server/gamerules.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "../../../src/server/gamerules.h"
|
||||
|
||||
class HHDMultiplayerRules:CGameRules
|
||||
{
|
||||
/* client */
|
||||
virtual void(base_player) PlayerSpawn;
|
||||
virtual void(base_player) PlayerConnect;
|
||||
virtual void(base_player) PlayerDisconnect;
|
||||
virtual void(base_player) PlayerKill;
|
||||
virtual void(base_player) PlayerDeath;
|
||||
virtual void(base_player) PlayerPain;
|
||||
virtual void(base_player) PlayerPostFrame;
|
||||
|
||||
virtual void(base_player) LevelDecodeParms;
|
||||
virtual void(base_player) LevelChangeParms;
|
||||
virtual void(void) LevelNewParms;
|
||||
};
|
347
src/server/gamerules.qc
Normal file
347
src/server/gamerules.qc
Normal file
|
@ -0,0 +1,347 @@
|
|||
/*
|
||||
* 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
|
||||
HHDMultiplayerRules::PlayerDeath(base_player pl)
|
||||
{
|
||||
/* obituary networking */
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EV_OBITUARY);
|
||||
if (g_dmg_eAttacker.netname)
|
||||
WriteString(MSG_MULTICAST, g_dmg_eAttacker.netname);
|
||||
else
|
||||
WriteString(MSG_MULTICAST, g_dmg_eAttacker.classname);
|
||||
WriteString(MSG_MULTICAST, pl.netname);
|
||||
WriteByte(MSG_MULTICAST, g_dmg_iWeapon);
|
||||
WriteByte(MSG_MULTICAST, 0);
|
||||
msg_entity = world;
|
||||
multicast([0,0,0], MULTICAST_ALL);
|
||||
|
||||
/* death-counter */
|
||||
pl.deaths++;
|
||||
forceinfokey(pl, "*deaths", ftos(pl.deaths));
|
||||
|
||||
/* update score-counter */
|
||||
if (pl.flags & FL_CLIENT || pl.flags & FL_MONSTER)
|
||||
if (g_dmg_eAttacker.flags & FL_CLIENT) {
|
||||
if (pl == g_dmg_eAttacker)
|
||||
g_dmg_eAttacker.frags--;
|
||||
else
|
||||
g_dmg_eAttacker.frags++;
|
||||
}
|
||||
|
||||
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;
|
||||
Sound_Play(pl, CHAN_AUTO, "player.die");
|
||||
|
||||
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
|
||||
HHDMultiplayerRules::PlayerPain(base_player pl)
|
||||
{
|
||||
/* Vampire Rune
|
||||
* steals health from enemies */
|
||||
|
||||
if (g_dmg_eAttacker.flags & RUNE_VAMPIRE)
|
||||
g_dmg_eAttacker.health += g_dmg_iDamage;
|
||||
|
||||
/* This probably doesn't go here?
|
||||
* damage checks for vampire rune */
|
||||
|
||||
if (g_dmg_eAttacker == (entity)pl)
|
||||
return;
|
||||
|
||||
if (!(g_dmg_eAttacker.flags & FL_CLIENT))
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
HHDMultiplayerRules::PlayerSpawn(base_player pp)
|
||||
{
|
||||
player pl = (player)pp;
|
||||
/* this is where the mods want to deviate */
|
||||
entity spot;
|
||||
|
||||
pl.classname = "player";
|
||||
pl.health = pl.max_health = 100;
|
||||
pl.takedamage = DAMAGE_YES;
|
||||
pl.solid = SOLID_SLIDEBOX;
|
||||
pl.movetype = MOVETYPE_WALK;
|
||||
pl.flags = FL_CLIENT;
|
||||
pl.viewzoom = 1.0;
|
||||
pl.model = "models/player.mdl";
|
||||
string mymodel = infokey(pl, "model");
|
||||
|
||||
if (mymodel) {
|
||||
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
|
||||
if (whichpack(mymodel)) {
|
||||
pl.model = mymodel;
|
||||
}
|
||||
}
|
||||
setmodel(pl, pl.model);
|
||||
|
||||
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
pl.view_ofs = VEC_PLAYER_VIEWPOS;
|
||||
pl.velocity = [0,0,0];
|
||||
pl.gravity = __NULL__;
|
||||
pl.frame = 1;
|
||||
pl.SendEntity = Player_SendEntity;
|
||||
pl.SendFlags = UPDATE_ALL;
|
||||
pl.customphysics = Empty;
|
||||
pl.iBleeds = TRUE;
|
||||
forceinfokey(pl, "*spec", "0");
|
||||
forceinfokey(pl, "*deaths", ftos(pl.deaths));
|
||||
|
||||
spot = Spawn_SelectRandom("info_player_deathmatch");
|
||||
setorigin(pl, spot.origin);
|
||||
pl.angles = spot.angles;
|
||||
|
||||
pl.g_items = ITEM_BROOM | ITEM_SUIT;
|
||||
pl.activeweapon = WEAPON_BROOM;
|
||||
Weapons_RefreshAmmo(pl);
|
||||
|
||||
Client_FixAngle(pl, pl.angles);
|
||||
}
|
||||
|
||||
void
|
||||
HHDMultiplayerRules::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 = parm18;
|
||||
|
||||
pl.ammo_forks = parm12;
|
||||
pl.ammo_knives = parm13;
|
||||
pl.ammo_legogrenade = parm14;
|
||||
pl.ammo_legos = parm15;
|
||||
pl.ammo_soda = parm16;
|
||||
pl.ammo_spray = parm17;
|
||||
|
||||
if (pl.flags & FL_CROUCHING) {
|
||||
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
|
||||
} else {
|
||||
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HHDMultiplayerRules::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_forks;
|
||||
parm13 = pl.ammo_knives;
|
||||
parm14 = pl.ammo_legogrenade;
|
||||
parm15 = pl.ammo_legos;
|
||||
parm16 = pl.ammo_soda;
|
||||
parm17 = pl.ammo_spray;
|
||||
}
|
||||
|
||||
void
|
||||
HHDMultiplayerRules::LevelNewParms(void)
|
||||
{
|
||||
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
|
||||
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
|
||||
parm15 = parm16 = parm17 = 0;
|
||||
parm18 = FL_CLIENT;
|
||||
}
|
||||
|
||||
/* we check what fields have changed over the course of the frame and network
|
||||
* only the ones that have actually changed */
|
||||
void
|
||||
HHDMultiplayerRules::PlayerPostFrame(base_player pp)
|
||||
{
|
||||
player pl = (player)pp;
|
||||
Animation_PlayerUpdate();
|
||||
|
||||
if (autocvar_sv_playerkeepalive)
|
||||
pl.SendFlags |= PLAYER_KEEPALIVE;
|
||||
|
||||
if (pl.old_modelindex != pl.modelindex)
|
||||
pl.SendFlags |= PLAYER_MODELINDEX;
|
||||
|
||||
if (pl.old_origin[0] != pl.origin[0])
|
||||
pl.SendFlags |= PLAYER_ORIGIN;
|
||||
|
||||
if (pl.old_origin[1] != pl.origin[1])
|
||||
pl.SendFlags |= PLAYER_ORIGIN;
|
||||
|
||||
if (pl.old_origin[2] != pl.origin[2])
|
||||
pl.SendFlags |= PLAYER_ORIGIN_Z;
|
||||
|
||||
if (pl.old_angles[0] != pl.v_angle[0])
|
||||
pl.SendFlags |= PLAYER_ANGLES_X;
|
||||
|
||||
if (pl.old_angles[1] != pl.angles[1])
|
||||
pl.SendFlags |= PLAYER_ANGLES_Y;
|
||||
|
||||
if (pl.old_angles[2] != pl.angles[2])
|
||||
pl.SendFlags |= PLAYER_ANGLES_Z;
|
||||
|
||||
if (pl.old_velocity[0] != pl.velocity[0])
|
||||
pl.SendFlags |= PLAYER_VELOCITY;
|
||||
|
||||
if (pl.old_velocity[1] != pl.velocity[1])
|
||||
pl.SendFlags |= PLAYER_VELOCITY;
|
||||
|
||||
if (pl.old_velocity[2] != pl.velocity[2])
|
||||
pl.SendFlags |= PLAYER_VELOCITY_Z;
|
||||
|
||||
if (pl.old_flags != pl.flags)
|
||||
pl.SendFlags |= PLAYER_FLAGS;
|
||||
|
||||
if (pl.old_activeweapon != pl.activeweapon)
|
||||
pl.SendFlags |= PLAYER_WEAPON;
|
||||
|
||||
if (pl.old_items != pl.g_items)
|
||||
pl.SendFlags |= PLAYER_ITEMS;
|
||||
|
||||
if (pl.old_health != pl.health)
|
||||
pl.SendFlags |= PLAYER_HEALTH;
|
||||
|
||||
if (pl.old_armor != pl.armor)
|
||||
pl.SendFlags |= PLAYER_ARMOR;
|
||||
|
||||
if (pl.old_movetype != pl.movetype)
|
||||
pl.SendFlags |= PLAYER_MOVETYPE;
|
||||
|
||||
if (pl.old_viewofs != pl.view_ofs[2])
|
||||
pl.SendFlags |= PLAYER_VIEWOFS;
|
||||
|
||||
if (pl.old_baseframe != pl.baseframe)
|
||||
pl.SendFlags |= PLAYER_BASEFRAME;
|
||||
|
||||
if (pl.old_frame != pl.frame)
|
||||
pl.SendFlags |= PLAYER_FRAME;
|
||||
|
||||
if (pl.old_a_ammo1 != pl.a_ammo1)
|
||||
pl.SendFlags |= PLAYER_AMMO1;
|
||||
|
||||
if (pl.old_a_ammo2 != pl.a_ammo2)
|
||||
pl.SendFlags |= PLAYER_AMMO2;
|
||||
|
||||
if (pl.old_a_ammo3 != pl.a_ammo3)
|
||||
pl.SendFlags |= PLAYER_AMMO3;
|
||||
|
||||
pl.old_modelindex = pl.modelindex;
|
||||
pl.old_origin = pl.origin;
|
||||
pl.old_angles = pl.angles;
|
||||
pl.old_angles[0] = pl.v_angle[0];
|
||||
pl.old_velocity = pl.velocity;
|
||||
pl.old_flags = pl.flags;
|
||||
pl.old_activeweapon = pl.activeweapon;
|
||||
pl.old_items = pl.g_items;
|
||||
pl.old_health = pl.health;
|
||||
pl.old_armor = pl.armor;
|
||||
pl.old_movetype = pl.movetype;
|
||||
pl.old_viewofs = pl.view_ofs[2];
|
||||
pl.old_baseframe = pl.baseframe;
|
||||
pl.old_frame = pl.frame;
|
||||
pl.old_a_ammo1 = pl.a_ammo1;
|
||||
pl.old_a_ammo2 = pl.a_ammo2;
|
||||
pl.old_a_ammo3 = pl.a_ammo3;
|
||||
|
||||
/* Almost all powerups are on a timer */
|
||||
|
||||
pl.powerup_time = bound(0.0f, pl.powerup_time - frametime, pl.powerup_time);
|
||||
|
||||
/* and remove when time runs out ;) */
|
||||
|
||||
if (pl.powerup_time <= 0.0f) {
|
||||
pl.g_items &= ~ITEM_RUNE_HASTE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HHDMultiplayerRules::PlayerConnect(base_player pl)
|
||||
{
|
||||
entity a;
|
||||
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.netname));
|
||||
|
||||
int playercount = 0;
|
||||
for (a = world; (a = find(a, ::classname, "player"));) {
|
||||
playercount++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HHDMultiplayerRules::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
|
||||
HHDMultiplayerRules::PlayerKill(base_player pp)
|
||||
{
|
||||
player pl = (player)pp;
|
||||
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
|
||||
}
|
84
src/server/info_runespawn.qc
Normal file
84
src/server/info_runespawn.qc
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*QUAKED info_runespawn (0 0 0.8) (-16 -16 0) (16 16 36)
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
HEV Suit energy battery.
|
||||
It adds the following energy values to the HEV Suit by default:
|
||||
Skill 1 (Easy): 15
|
||||
Skill 2 (Medium): 15
|
||||
Skill 3 (Hard): 10
|
||||
|
||||
The values can be tweaked in the skill.cfg file.
|
||||
|
||||
*/
|
||||
class info_runespawn:CBaseEntity
|
||||
{
|
||||
void(void) info_runespawn;
|
||||
virtual void(void) Respawn;
|
||||
virtual void(void) touch;
|
||||
};
|
||||
|
||||
void info_runespawn::touch(void)
|
||||
{
|
||||
if (other.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO runestuff
|
||||
*if (other.rune >= 1) {
|
||||
* return;
|
||||
* }
|
||||
*/
|
||||
|
||||
Logging_Pickup(other, this, __NULL__);
|
||||
Sound_Play(other, CHAN_ITEM, "item.armor");
|
||||
|
||||
think = Respawn;
|
||||
nextthink = time + 30.0f;
|
||||
}
|
||||
|
||||
void info_runespawn::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_NONE);
|
||||
/* One of the models is transparent, and we need to set additive
|
||||
SetRenderMode(RM_ADDITIVE);
|
||||
SetRenderAmt(255);
|
||||
SetSize([-16,-16,0],[16,16,16]);
|
||||
* Rotation
|
||||
* avelocity[1] = 420; */
|
||||
/* Always spawns a little above origin */
|
||||
SetOrigin(m_oldOrigin + [0,0,16]);
|
||||
SetModel(m_oldModel);
|
||||
|
||||
|
||||
think = __NULL__;
|
||||
nextthink = -1;
|
||||
Sound_Play(this, CHAN_ITEM, "item.respawn");
|
||||
}
|
||||
|
||||
void info_runespawn::info_runespawn(void)
|
||||
{
|
||||
Sound_Precache("item.armor");
|
||||
Sound_Precache("item.respawn");
|
||||
/* TODO actually uses two models... */
|
||||
model = "models/rune_stand.mdl";
|
||||
CBaseEntity::CBaseEntity();
|
||||
item_healthkit::Respawn();
|
||||
}
|
77
src/server/input.qc
Normal file
77
src/server/input.qc
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
=================
|
||||
Input_Handle
|
||||
|
||||
Handles impulse and whatnot
|
||||
=================
|
||||
*/
|
||||
void Game_Input(void)
|
||||
{
|
||||
CGameRules rules = (CGameRules)g_grMode;
|
||||
|
||||
if (rules.m_iIntermission) {
|
||||
rules.IntermissionEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
if (input_buttons & INPUT_BUTTON0) {
|
||||
Weapons_Primary();
|
||||
} else if (input_buttons & INPUT_BUTTON4) {
|
||||
Weapons_Reload();
|
||||
} else if (input_buttons & INPUT_BUTTON3) {
|
||||
Weapons_Secondary();
|
||||
} else {
|
||||
Weapons_Release();
|
||||
}
|
||||
|
||||
if (input_buttons & INPUT_BUTTON5) {
|
||||
Player_UseDown();
|
||||
} else {
|
||||
Player_UseUp();
|
||||
}
|
||||
|
||||
if (self.impulse == 100) {
|
||||
Flashlight_Toggle();
|
||||
}
|
||||
|
||||
if (self.impulse == 240)
|
||||
Bot_AddQuick();
|
||||
|
||||
/* Uncomment rune weapons if you desire */
|
||||
if (cvar("sv_cheats") == 1) {
|
||||
player pl = (player)self;
|
||||
if (self.impulse == 101) {
|
||||
pl.health = 100;
|
||||
pl.armor = 100;
|
||||
pl.g_items |= ITEM_SUIT;
|
||||
Weapons_AddItem(pl, WEAPON_BROOM, -1);
|
||||
Weapons_AddItem(pl, WEAPON_FORKS, -1);
|
||||
Weapons_AddItem(pl, WEAPON_FRYINGPAN, -1);
|
||||
/* Weapons_AddItem(pl, WEAPON_GLOVE, -1); */
|
||||
Weapons_AddItem(pl, WEAPON_HAIRSPRAY, -1);
|
||||
Weapons_AddItem(pl, WEAPON_KNIFE, -1);
|
||||
Weapons_AddItem(pl, WEAPON_LEGO, -1);
|
||||
Weapons_AddItem(pl, WEAPON_LEGOLAUNCHER, -1);
|
||||
Weapons_AddItem(pl, WEAPON_MACHETTE, -1);
|
||||
Weapons_AddItem(pl, WEAPON_SODALAUNCHER, -1);
|
||||
}
|
||||
}
|
||||
|
||||
self.impulse = 0;
|
||||
}
|
91
src/server/item_battery.qc
Normal file
91
src/server/item_battery.qc
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*QUAKED item_battery (0 0 0.8) (-16 -16 0) (16 16 36)
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
HEV Suit energy battery.
|
||||
It adds the following energy values to the HEV Suit by default:
|
||||
Skill 1 (Easy): 15
|
||||
Skill 2 (Medium): 15
|
||||
Skill 3 (Hard): 10
|
||||
|
||||
The values can be tweaked in the skill.cfg file.
|
||||
|
||||
*/
|
||||
class item_battery:CBaseEntity
|
||||
{
|
||||
void(void) item_battery;
|
||||
virtual void(void) Respawn;
|
||||
virtual void(void) touch;
|
||||
};
|
||||
|
||||
void item_battery::touch(void)
|
||||
{
|
||||
if (other.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
base_player pl = (base_player)other;
|
||||
|
||||
if (pl.armor >= 100) {
|
||||
return;
|
||||
}
|
||||
/* Move this somewhere else? */
|
||||
pl.armor += Skill_GetValue("battery", 10);
|
||||
if (pl.armor > 100) {
|
||||
pl.armor = 100;
|
||||
}
|
||||
|
||||
Logging_Pickup(other, this, __NULL__);
|
||||
Sound_Play(other, CHAN_ITEM, "item.battery");
|
||||
|
||||
if (cvar("sv_playerslots") == 1) {
|
||||
remove(self);
|
||||
} else {
|
||||
Hide();
|
||||
think = Respawn;
|
||||
nextthink = time + 20.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void item_battery::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_NONE);
|
||||
/* One of the models is transparent, and we need to set additive */
|
||||
SetRenderMode(RM_ADDITIVE);
|
||||
SetRenderAmt(255);
|
||||
SetSize([-16,-16,0],[16,16,16]);
|
||||
/* Always spawns a little above origin */
|
||||
SetOrigin(m_oldOrigin + [0,0,16]);
|
||||
SetModel(m_oldModel);
|
||||
|
||||
think = __NULL__;
|
||||
nextthink = -1;
|
||||
Sound_Play(this, CHAN_ITEM, "item.respawn");
|
||||
}
|
||||
|
||||
void item_battery::item_battery(void)
|
||||
{
|
||||
Sound_Precache("item.armor");
|
||||
Sound_Precache("item.respawn");
|
||||
/* TODO actually uses two models... */
|
||||
model = "models/armor.mdl";
|
||||
CBaseEntity::CBaseEntity();
|
||||
item_healthkit::Respawn();
|
||||
}
|
83
src/server/item_healthkit.qc
Normal file
83
src/server/item_healthkit.qc
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*QUAKED item_healthkit (0 0 0.8) (-16 -16 0) (16 16 36)
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Healthkit item.
|
||||
Adds 20 of health to the player.
|
||||
|
||||
*/
|
||||
class item_healthkit:CBaseEntity
|
||||
{
|
||||
void(void) item_healthkit;
|
||||
virtual void(void) Respawn;
|
||||
virtual void(void) touch;
|
||||
};
|
||||
|
||||
void item_healthkit::touch(void)
|
||||
{
|
||||
if (other.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (other.health >= other.max_health) {
|
||||
return;
|
||||
}
|
||||
Damage_Apply(other, this, -20, 0, DMG_GENERIC);
|
||||
Sound_Play(this, CHAN_ITEM, "item.healthkit");
|
||||
Logging_Pickup(other, this, __NULL__);
|
||||
|
||||
if (cvar("sv_playerslots") == 1) {
|
||||
remove(self);
|
||||
} else {
|
||||
Hide();
|
||||
think = Respawn;
|
||||
nextthink = time + 20.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void item_healthkit::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_NONE);
|
||||
/* One of the models is transparent, and we need to set additive */
|
||||
SetRenderMode(RM_ADDITIVE);
|
||||
SetRenderAmt(255);
|
||||
SetSize([-16,-16,0],[16,16,16]);
|
||||
/* Always spawns a little above origin */
|
||||
SetOrigin(m_oldOrigin + [0,0,16]);
|
||||
SetModel(m_oldModel);
|
||||
|
||||
think = __NULL__;
|
||||
nextthink = -1;
|
||||
Sound_Play(this, CHAN_ITEM, "item.respawn");
|
||||
}
|
||||
|
||||
void item_healthkit::item_healthkit(void)
|
||||
{
|
||||
Sound_Precache("item.health");
|
||||
Sound_Precache("item.respawn");
|
||||
|
||||
entity base = spawn();
|
||||
setorigin(base, this.origin);
|
||||
setmodel(base, "models/health2.mdl");
|
||||
|
||||
model = "models/health.mdl";
|
||||
CBaseEntity::CBaseEntity();
|
||||
item_healthkit::Respawn();
|
||||
}
|
95
src/server/item_rune_haste.qc
Normal file
95
src/server/item_rune_haste.qc
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
* Copyright (c) 2020 Gethyn ThomasQuail <xylemon@posteo.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*QUAKED item_rune_haste (0 0 0.8) (-16 -16 0) (16 16 36)
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Haste Rune
|
||||
Doubles the player's speed for 30 seconds.
|
||||
|
||||
*/
|
||||
class item_rune_haste:CBaseTrigger
|
||||
{
|
||||
void(void) item_rune_haste;
|
||||
|
||||
virtual void(void) touch;
|
||||
virtual void(void) Respawn;
|
||||
};
|
||||
|
||||
void item_rune_haste::touch(void)
|
||||
{
|
||||
if (other.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure we don't have more than one powerup */
|
||||
|
||||
player pl = (player)other;
|
||||
if (pl.g_items & ITEM_MACHETTE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pl.g_items & ITEM_RUNE_HASTE) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logging_Pickup(other, this, __NULL__);
|
||||
/* Replace with proper sounds
|
||||
* sound(other, CHAN_ITEM, "fvox/bell.wav", 1, ATTN_NORM);
|
||||
sound(other, CHAN_VOICE, "fvox/hev_logon.wav", 1, ATTN_NORM); */
|
||||
pl.g_items |= ITEM_RUNE_HASTE;
|
||||
pl.powerup_time = 30.0f;
|
||||
|
||||
CBaseTrigger::UseTargets(this, TRIG_TOGGLE, 0.0f);
|
||||
|
||||
if (cvar("sv_playerslots") == 1) {
|
||||
remove(self);
|
||||
} else {
|
||||
Hide();
|
||||
think = Respawn;
|
||||
nextthink = time + 30.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void item_rune_haste::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_NONE);
|
||||
SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
SetOrigin(m_oldOrigin);
|
||||
SetModel(m_oldModel);
|
||||
|
||||
think = __NULL__;
|
||||
nextthink = -1;
|
||||
sound(this, CHAN_ITEM, "items/suitchargeok1.wav", 1, ATTN_NORM, 150);
|
||||
}
|
||||
|
||||
void item_rune_haste::item_rune_haste(void)
|
||||
{
|
||||
/* Powerups have a base model always visable */
|
||||
entity base = spawn();
|
||||
setorigin(base, this.origin);
|
||||
setmodel(base, "models/rune_stand.mdl");
|
||||
|
||||
model = "models/rune_haste.mdl";
|
||||
|
||||
precache_sound("items/suitchargeok1.wav");
|
||||
precache_sound("fvox/hev_logon.wav");
|
||||
precache_sound("fvox/bell.wav");
|
||||
CBaseTrigger::CBaseTrigger();
|
||||
}
|
96
src/server/item_rune_stalker.qc
Normal file
96
src/server/item_rune_stalker.qc
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
* Copyright (c) 2020 Gethyn ThomasQuail <xylemon@posteo.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*QUAKED item_rune_stalker (0 0 0.8) (-16 -16 0) (16 16 36)
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Stalker Rune
|
||||
|
||||
Turns the player into a health and speed boosted killer...
|
||||
Includes a trademark throwable machette weapon!
|
||||
*/
|
||||
class item_rune_stalker:CBaseTrigger
|
||||
{
|
||||
void(void) item_rune_stalker;
|
||||
|
||||
virtual void(void) touch;
|
||||
virtual void(void) Respawn;
|
||||
};
|
||||
|
||||
void item_rune_stalker::touch(void)
|
||||
{
|
||||
if (other.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure we don't have more than one powerup */
|
||||
|
||||
player pl = (player)other;
|
||||
if (pl.g_items & ITEM_MACHETTE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pl.g_items & ITEM_RUNE_HASTE) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logging_Pickup(other, this, __NULL__);
|
||||
Sound_Play(other, CHAN_ITEM, "weapon_machette.pickup");
|
||||
env_message_single(other, "Activating Rune STALKER!");
|
||||
pl.g_items = ITEM_SUIT | ITEM_MACHETTE;
|
||||
pl.health = 300; /* Player gets more health */
|
||||
pl.activeweapon = WEAPON_MACHETTE;
|
||||
Weapons_RefreshAmmo(pl);
|
||||
|
||||
CBaseTrigger::UseTargets(this, TRIG_TOGGLE, 0.0f);
|
||||
|
||||
if (cvar("sv_playerslots") == 1) {
|
||||
remove(self);
|
||||
} else {
|
||||
Hide();
|
||||
think = Respawn;
|
||||
nextthink = time + 30.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void item_rune_stalker::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_TOSS);
|
||||
SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
|
||||
SetOrigin(m_oldOrigin);
|
||||
SetModel(m_oldModel);
|
||||
|
||||
think = __NULL__;
|
||||
nextthink = -1;
|
||||
sound(this, CHAN_ITEM, "items/suitchargeok1.wav", 1, ATTN_NORM, 150);
|
||||
}
|
||||
|
||||
void item_rune_stalker::item_rune_stalker(void)
|
||||
{
|
||||
/* Powerups have a base model always visable */
|
||||
|
||||
entity base = spawn();
|
||||
setorigin(base, this.origin);
|
||||
setmodel(base, "models/rune_stand.mdl");
|
||||
|
||||
model = "models/rune_stalker.mdl";
|
||||
|
||||
Sound_Precache("weapon_machette.pickup");
|
||||
CBaseTrigger::CBaseTrigger();
|
||||
}
|
88
src/server/item_weaponbox.qc
Normal file
88
src/server/item_weaponbox.qc
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
class item_weaponbox:CBaseEntity
|
||||
{
|
||||
int ammo_forks;
|
||||
int ammo_knives;
|
||||
int ammo_legogrenade;
|
||||
int ammo_legos;
|
||||
int ammo_soda;
|
||||
int ammo_spray;
|
||||
int weapon_items;
|
||||
|
||||
void(void) item_weaponbox;
|
||||
virtual void(void) touch;
|
||||
virtual void(player) setup;
|
||||
};
|
||||
|
||||
void item_weaponbox::touch(void)
|
||||
{
|
||||
if (other.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
player pl = (player)other;
|
||||
Logging_Pickup(other, this, __NULL__);
|
||||
sound(pl, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_NORM);
|
||||
|
||||
pl.ammo_forks += ammo_forks;
|
||||
pl.ammo_knives += ammo_knives;
|
||||
pl.ammo_legogrenade += ammo_legogrenade;
|
||||
pl.ammo_legos += ammo_legos;
|
||||
pl.ammo_soda += ammo_soda;
|
||||
pl.ammo_spray += ammo_spray;
|
||||
|
||||
/* cull */
|
||||
pl.ammo_forks = min(pl.ammo_forks, MAX_A_FORKS);
|
||||
pl.ammo_knives = min(pl.ammo_knives, MAX_A_KNIVES);
|
||||
pl.ammo_legogrenade = min(pl.ammo_legogrenade, MAX_A_LEGOGRENADE);
|
||||
pl.ammo_legos = min(pl.ammo_legos, MAX_A_LEGOS);
|
||||
pl.ammo_soda = min(pl.ammo_soda, MAX_A_SODA);
|
||||
pl.ammo_spray = min(pl.ammo_spray, MAX_A_SPRAY);
|
||||
|
||||
pl.g_items |= weapon_items;
|
||||
Weapons_RefreshAmmo(pl);
|
||||
|
||||
remove(this);
|
||||
}
|
||||
|
||||
void item_weaponbox::setup(player pl)
|
||||
{
|
||||
/* TODO: Should the magazine bits be transferred too? */
|
||||
ammo_forks = pl.ammo_forks;
|
||||
ammo_knives = pl.ammo_knives;
|
||||
ammo_legogrenade = pl.ammo_legogrenade;
|
||||
ammo_legos = pl.ammo_legos;
|
||||
ammo_soda = pl.ammo_soda;
|
||||
ammo_spray = pl.ammo_spray;
|
||||
weapon_items = pl.g_items;
|
||||
}
|
||||
|
||||
void item_weaponbox::item_weaponbox(void)
|
||||
{
|
||||
SetModel("models/basket.mdl");
|
||||
SetSize([-16,-16,0], [16,16,16]);
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetMovetype(MOVETYPE_TOSS);
|
||||
}
|
||||
|
||||
void weaponbox_spawn(player spawner)
|
||||
{
|
||||
item_weaponbox weaponbox = spawn(item_weaponbox);
|
||||
weaponbox.SetOrigin(spawner.origin);
|
||||
weaponbox.setup(spawner);
|
||||
}
|
93
src/server/items.qc
Normal file
93
src/server/items.qc
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 item_pickup::touch(void)
|
||||
{
|
||||
if (other.classname != "player") {
|
||||
return;
|
||||
}
|
||||
|
||||
player pl = (player)other;
|
||||
if (pl.g_items & ITEM_MACHETTE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't remove if AddItem fails */
|
||||
if (Weapons_AddItem((player)other, id, m_iClip) == FALSE) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logging_Pickup(other, this, __NULL__);
|
||||
Sound_Play(other, CHAN_ITEM, "weapon.pickup");
|
||||
|
||||
CBaseTrigger::UseTargets(this, TRIG_TOGGLE, 0.0f);
|
||||
|
||||
if (real_owner || m_iWasDropped == 1 || cvar("sv_playerslots") == 1) {
|
||||
remove(self);
|
||||
} else {
|
||||
Hide();
|
||||
think = Respawn;
|
||||
nextthink = time + 30.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void item_pickup::SetItem(int i)
|
||||
{
|
||||
id = i;
|
||||
m_oldModel = Weapons_GetWorldmodel(id);
|
||||
SetModel(m_oldModel);
|
||||
}
|
||||
|
||||
void item_pickup::SetFloating(int i)
|
||||
{
|
||||
m_bFloating = rint(bound(0, m_bFloating, 1));
|
||||
}
|
||||
|
||||
void item_pickup::Respawn(void)
|
||||
{
|
||||
SetSolid(SOLID_TRIGGER);
|
||||
SetOrigin(m_oldOrigin);
|
||||
|
||||
/* At some points, the item id might not yet be set */
|
||||
if (m_oldModel) {
|
||||
SetModel(m_oldModel);
|
||||
}
|
||||
|
||||
SetSize([-16,-16,0], [16,16,16]);
|
||||
|
||||
think = __NULL__;
|
||||
nextthink = -1;
|
||||
|
||||
if (!m_iWasDropped && cvar("sv_playerslots") > 1) {
|
||||
if (!real_owner)
|
||||
Sound_Play(this, CHAN_ITEM, "item.respawn");
|
||||
|
||||
m_iClip = -1;
|
||||
}
|
||||
|
||||
if (!m_bFloating) {
|
||||
droptofloor();
|
||||
SetMovetype(MOVETYPE_TOSS);
|
||||
}
|
||||
}
|
||||
|
||||
void item_pickup::item_pickup(void)
|
||||
{
|
||||
Sound_Precache("item.respawn");
|
||||
Sound_Precache("weapon.pickup");
|
||||
CBaseTrigger::CBaseTrigger();
|
||||
Respawn();
|
||||
}
|
52
src/server/progs.src
Executable file
52
src/server/progs.src
Executable file
|
@ -0,0 +1,52 @@
|
|||
#pragma target fte
|
||||
#pragma progs_dat "../../progs.dat"
|
||||
|
||||
#define QWSSQC
|
||||
#define SERVER
|
||||
#define VALVE
|
||||
#define HHDEATH
|
||||
#define GS_RENDERFX
|
||||
|
||||
#includelist
|
||||
../../../src/shared/fteextensions.qc
|
||||
../../../src/gs-entbase/server/defs.h
|
||||
../../../src/shared/defs.h
|
||||
../../../src/server/defs.h
|
||||
|
||||
../../../src/gs-entbase/server.src
|
||||
../../../src/gs-entbase/shared.src
|
||||
../shared/include.src
|
||||
|
||||
defs.h
|
||||
|
||||
../../../valve/src/server/monster_scientist_dead.qc
|
||||
|
||||
../../../valve/src/server/player.qc
|
||||
../../../valve/src/server/spectator.qc
|
||||
items.qc
|
||||
../../../valve/src/server/item_suit.qc
|
||||
item_healthkit.qc
|
||||
item_battery.qc
|
||||
item_rune_haste.qc
|
||||
item_rune_stalker.qc
|
||||
item_weaponbox.qc
|
||||
../../../valve/src/server/world_items.qc
|
||||
ammo_hd.qc
|
||||
|
||||
gamerules.qc
|
||||
../../../valve/src/server/client.qc
|
||||
server.qc
|
||||
../../../valve/src/server/damage.qc
|
||||
../../../valve/src/server/rules.qc
|
||||
|
||||
../../../src/botlib/include.src
|
||||
|
||||
../../../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
|
32
src/server/server.qc
Normal file
32
src/server/server.qc
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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_InitRules(void)
|
||||
{
|
||||
g_grMode = spawn(HHDMultiplayerRules);
|
||||
}
|
||||
|
||||
void Game_Worldspawn(void)
|
||||
{
|
||||
precache_model("models/player.mdl");
|
||||
precache_model("models/w_weaponbox.mdl");
|
||||
Sound_Precache("player.die");
|
||||
Sound_Precache("player.fall");
|
||||
|
||||
Player_Precache();
|
||||
Weapons_Init();
|
||||
}
|
22
src/shared/events.h
Normal file
22
src/shared/events.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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
|
||||
{
|
||||
EV_LEGO = EV_SEPARATOR,
|
||||
EV_LEGOPIECE,
|
||||
EV_SODA
|
||||
};
|
42
src/shared/flags.h
Normal file
42
src/shared/flags.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "../../../valve/src/shared/flags.h"
|
||||
|
||||
/* game flags */
|
||||
#define GF_UNUSED1 (1<<0)
|
||||
#define GF_UNUSED2 (1<<1)
|
||||
#define GF_UNUSED3 (1<<2)
|
||||
#define GF_UNUSED4 (1<<3)
|
||||
#define GF_UNUSED5 (1<<4)
|
||||
#define GF_UNUSED6 (1<<5)
|
||||
#define GF_UNUSED7 (1<<6)
|
||||
#define GF_UNUSED8 (1<<7)
|
||||
#define GF_UNUSED9 (1<<8)
|
||||
#define GF_UNUSED10 (1<<9)
|
||||
#define GF_UNUSED11 (1<<10)
|
||||
#define GF_UNUSED12 (1<<11)
|
||||
#define GF_UNUSED13 (1<<12)
|
||||
#define GF_UNUSED14 (1<<14)
|
||||
#define GF_UNUSED15 (1<<16)
|
||||
#define GF_UNUSED16 (1<<13)
|
||||
#define GF_UNUSED17 (1<<17)
|
||||
#define GF_UNUSED18 (1<<18)
|
||||
#define GF_UNUSED19 (1<<19)
|
||||
#define GF_UNUSED20 (1<<20)
|
||||
#define GF_UNUSED21 (1<<21)
|
||||
#define GF_UNUSED22 (1<<22)
|
||||
#define RUNE_VAMPIRE (1<<23)
|
95
src/shared/fx_lego.qc
Normal file
95
src/shared/fx_lego.qc
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef CLIENT
|
||||
var float PARTICLE_LEGO;
|
||||
|
||||
void
|
||||
FX_Lego_Init(void)
|
||||
{
|
||||
Sound_Precache("weapon_lego.explode");
|
||||
precache_model("models/lego.mdl");
|
||||
PARTICLE_LEGO = particleeffectnum("part_lego");
|
||||
}
|
||||
|
||||
string g_fxlego_sets[12] = {
|
||||
"geomset 0 1",
|
||||
"geomset 0 2",
|
||||
"geomset 0 3",
|
||||
"geomset 0 4",
|
||||
"geomset 0 5",
|
||||
"geomset 0 6",
|
||||
"geomset 0 7",
|
||||
"geomset 0 8",
|
||||
"geomset 0 9",
|
||||
"geomset 0 10",
|
||||
"geomset 0 11",
|
||||
"geomset 0 12",
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
FX_Lego(vector pos)
|
||||
{
|
||||
#ifdef SERVER
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EV_LEGO);
|
||||
WriteCoord(MSG_MULTICAST, pos[0]);
|
||||
WriteCoord(MSG_MULTICAST, pos[1]);
|
||||
WriteCoord(MSG_MULTICAST, pos[2]);
|
||||
msg_entity = self;
|
||||
multicast(pos, MULTICAST_PVS);
|
||||
#else
|
||||
static void Lego_Remove(void) {
|
||||
remove(self);
|
||||
}
|
||||
|
||||
/* cast an explosive effect minus the fire */
|
||||
/* wrong decal atm, decal.wad loading is messy in HL */
|
||||
Decals_Place(pos, "{spraypaint");
|
||||
|
||||
/* has a different smoke sprite */
|
||||
env_sprite eSmoke = spawn(env_sprite);
|
||||
setorigin(eSmoke, pos);
|
||||
setmodel(eSmoke, "sprites/stmbal1.spr");
|
||||
Sound_Play(eSmoke, CHAN_WEAPON, "weapon_lego.explode");
|
||||
|
||||
eSmoke.effects = EF_ADDITIVE;
|
||||
eSmoke.drawmask = MASK_ENGINE;
|
||||
eSmoke.maxframe = modelframecount(eSmoke.modelindex);
|
||||
eSmoke.loops = 0;
|
||||
eSmoke.framerate = 15;
|
||||
eSmoke.nextthink = time + 0.05f;
|
||||
|
||||
/* there are many different lego submodels */
|
||||
for (int i = 0; i < 12; i++) {
|
||||
entity eLego = spawn();
|
||||
setorigin(eLego, pos);
|
||||
setmodel(eLego, "models/lego.mdl");
|
||||
eLego.movetype = MOVETYPE_BOUNCE;
|
||||
eLego.gravity = 0.5f;
|
||||
eLego.scale = 1.0f;
|
||||
eLego.drawmask = MASK_ENGINE;
|
||||
eLego.velocity = randomvec() * 192;
|
||||
eLego.think = Lego_Remove;
|
||||
eLego.nextthink = time + 5.0f;
|
||||
eLego.solid = SOLID_BBOX;
|
||||
setcustomskin(eLego, "", g_fxlego_sets[floor(random(0,12))]);
|
||||
setsize(eLego, [0,0,0], [0,0,0]);
|
||||
}
|
||||
#endif
|
||||
}
|
58
src/shared/fx_legopiece.qc
Normal file
58
src/shared/fx_legopiece.qc
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef CLIENT
|
||||
var float PARTICLE_LEGOPIECE;
|
||||
|
||||
void
|
||||
FX_LegoPiece_Init(void)
|
||||
{
|
||||
precache_model("models/lego.mdl");
|
||||
PARTICLE_LEGOPIECE = particleeffectnum("part_legopiece");
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
FX_LegoPiece(vector pos)
|
||||
{
|
||||
#ifdef SERVER
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EV_LEGOPIECE);
|
||||
WriteCoord(MSG_MULTICAST, pos[0]);
|
||||
WriteCoord(MSG_MULTICAST, pos[1]);
|
||||
WriteCoord(MSG_MULTICAST, pos[2]);
|
||||
msg_entity = self;
|
||||
multicast(pos, MULTICAST_PVS);
|
||||
#else
|
||||
static void LegoPiece_Remove(void) {
|
||||
remove(self);
|
||||
}
|
||||
entity eLegoPiece = spawn();
|
||||
setorigin(eLegoPiece, pos);
|
||||
setmodel(eLegoPiece, "models/lego.mdl");
|
||||
eLegoPiece.movetype = MOVETYPE_BOUNCE;
|
||||
eLegoPiece.gravity = 0.5f;
|
||||
eLegoPiece.scale = 1.0f;
|
||||
eLegoPiece.drawmask = MASK_ENGINE;
|
||||
eLegoPiece.velocity = randomvec() * 128;
|
||||
eLegoPiece.think = LegoPiece_Remove;
|
||||
eLegoPiece.nextthink = time + 5.0f;
|
||||
eLegoPiece.solid = SOLID_BBOX;
|
||||
setcustomskin(eLegoPiece, "", g_fxlego_sets[floor(random(0,12))]);
|
||||
setsize(eLegoPiece, [0,0,0], [0,0,0]);
|
||||
|
||||
#endif
|
||||
}
|
114
src/shared/fx_soda.qc
Normal file
114
src/shared/fx_soda.qc
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef CLIENT
|
||||
var float PARTICLE_SODA;
|
||||
|
||||
void
|
||||
FX_Soda_Init(void)
|
||||
{
|
||||
precache_model("sprites/blooddrop.spr");
|
||||
precache_model("sprites/soda2.spr");
|
||||
PARTICLE_SODA = particleeffectnum("part_soda");
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
FX_Soda(vector pos, int col)
|
||||
{
|
||||
#ifdef SERVER
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EV_SODA);
|
||||
WriteCoord(MSG_MULTICAST, pos[0]);
|
||||
WriteCoord(MSG_MULTICAST, pos[1]);
|
||||
WriteCoord(MSG_MULTICAST, pos[2]);
|
||||
WriteByte(MSG_MULTICAST, col);
|
||||
msg_entity = self;
|
||||
multicast(pos, MULTICAST_PVS);
|
||||
#else
|
||||
|
||||
vector color;
|
||||
/* Decals use a palette to set color, we need to set sprite colors by hand.
|
||||
* The order is important, we need to keep the clients and server in sync
|
||||
* for the view model, soda projectile, and soda spill effect */
|
||||
switch (col) {
|
||||
case 1:
|
||||
Decals_Place(pos, "{sodared");
|
||||
color = [1,0,0];
|
||||
break;
|
||||
case 2:
|
||||
Decals_Place(pos, "{sodapurple");
|
||||
color = [1,0,1];
|
||||
break;
|
||||
case 3:
|
||||
Decals_Place(pos, "{sodayellow");
|
||||
color = [1,1,0];
|
||||
break;
|
||||
case 4:
|
||||
Decals_Place(pos, "{sodablue");
|
||||
color = [0,0,1];
|
||||
break;
|
||||
case 5:
|
||||
Decals_Place(pos, "{sodabrown");
|
||||
color = [1,0.5,0];
|
||||
break;
|
||||
default:
|
||||
Decals_Place(pos, "{sodagreen");
|
||||
color = [0,1,0];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* enchancement from mod */
|
||||
env_sprite eSoda = spawn(env_sprite);
|
||||
setorigin(eSoda, pos);
|
||||
setmodel(eSoda, "sprites/soda1.spr");
|
||||
|
||||
eSoda.effects = EF_ADDITIVE;
|
||||
eSoda.drawmask = MASK_ENGINE;
|
||||
eSoda.maxframe = modelframecount(eSoda.modelindex);
|
||||
eSoda.loops = 0;
|
||||
eSoda.scale = 1.0f;
|
||||
eSoda.m_vecRenderColor = color;
|
||||
eSoda.framerate = 20;
|
||||
eSoda.nextthink = time + 0.05f;
|
||||
|
||||
static void Soda_Remove(void) {
|
||||
remove(self);
|
||||
}
|
||||
|
||||
/* Has a dripping effect from spill */
|
||||
for (int i = 0; i < 10; i++) {
|
||||
env_sprite eSodaPart = spawn(env_sprite);
|
||||
setorigin(eSodaPart, pos);
|
||||
setmodel(eSodaPart, "sprites/soda2.spr");
|
||||
eSodaPart.movetype = MOVETYPE_TOSS;
|
||||
eSodaPart.gravity = 0.3f;
|
||||
eSodaPart.scale = 0.5f;
|
||||
eSodaPart.effects = EF_ADDITIVE;
|
||||
eSodaPart.drawmask = MASK_ENGINE;
|
||||
eSodaPart.maxframe = modelframecount(eSodaPart.modelindex);
|
||||
eSodaPart.loops = 1;
|
||||
eSodaPart.m_vecRenderColor = color;
|
||||
eSodaPart.framerate = 10;
|
||||
eSodaPart.touch = Soda_Remove;
|
||||
eSodaPart.nextthink = time + 0.1f;
|
||||
eSodaPart.velocity = randomvec() * 128;
|
||||
eSodaPart.solid = SOLID_BBOX;
|
||||
setsize(eSodaPart, [0,0,0], [0,0,0]);
|
||||
}
|
||||
#endif
|
||||
}
|
36
src/shared/include.src
Normal file
36
src/shared/include.src
Normal file
|
@ -0,0 +1,36 @@
|
|||
#includelist
|
||||
../../../valve/src/shared/entities.h
|
||||
flags.h
|
||||
events.h
|
||||
player.qc
|
||||
../../../valve/src/shared/weapon_common.h
|
||||
../../../valve/src/shared/animations.h
|
||||
../../../valve/src/shared/animations.qc
|
||||
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
|
||||
fx_lego.qc
|
||||
fx_legopiece.qc
|
||||
fx_soda.qc
|
||||
|
||||
items.h
|
||||
weapons.h
|
||||
w_broom.qc
|
||||
w_forks.qc
|
||||
w_fryingpan.qc
|
||||
w_glove.qc
|
||||
w_hairspray.qc
|
||||
w_knife.qc
|
||||
w_lego.qc
|
||||
w_legolauncher.qc
|
||||
w_machette.qc
|
||||
w_sodalauncher.qc
|
||||
weapons.qc
|
||||
../../../valve/src/shared/weapon_common.qc
|
||||
#endlist
|
51
src/shared/items.h
Normal file
51
src/shared/items.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco 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_BROOM 0x00000001i
|
||||
#define ITEM_FORKS 0x00000002i
|
||||
#define ITEM_FRYINGPAN 0x00000004i
|
||||
#define ITEM_GLOVE 0x00000008i
|
||||
#define ITEM_HAIRSPRAY 0x00000010i
|
||||
#define ITEM_KNIFE 0x00000020i
|
||||
#define ITEM_LEGO 0x00000040i
|
||||
#define ITEM_LEGOLAUNCHER 0x00000080i
|
||||
|
||||
#define ITEM_MACHETTE 0x00000100i
|
||||
#define ITEM_SODALAUNCHER 0x00000200i
|
||||
#define ITEM_SUIT 0x00000400i
|
||||
#define ITEM_LONGJUMP 0x00000800i
|
||||
#define ITEM_RUNE_HASTE 0x00001000i
|
||||
#define ITEM_UNUSED14 0x00002000i
|
||||
#define ITEM_UNUSED15 0x00004000i
|
||||
#define ITEM_UNUSED16 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
|
42
src/shared/player.qc
Normal file
42
src/shared/player.qc
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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 input_sequence;
|
||||
|
||||
class player:base_player
|
||||
{
|
||||
#ifdef CLIENT
|
||||
/* External model */
|
||||
entity p_model;
|
||||
int p_hand_bone;
|
||||
int p_model_bone;
|
||||
float pitch;
|
||||
float lastweapon;
|
||||
|
||||
virtual void(void) gun_offset;
|
||||
virtual void(void) draw;
|
||||
virtual float() predraw;
|
||||
virtual void(void) postdraw;
|
||||
#else
|
||||
int ammo_forks;
|
||||
int ammo_knives;
|
||||
int ammo_legogrenade;
|
||||
int ammo_legos;
|
||||
int ammo_soda;
|
||||
int ammo_spray;
|
||||
float powerup_time;
|
||||
#endif
|
||||
};
|
69
src/shared/pmove.qc
Normal file
69
src/shared/pmove.qc
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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 PHY_JUMP_CHAINWINDOW 0.5
|
||||
#define PHY_JUMP_CHAIN 100
|
||||
#define PHY_JUMP_CHAINDECAY 50
|
||||
|
||||
.float waterlevel;
|
||||
.float watertype;
|
||||
|
||||
float GamePMove_Maxspeed(player target)
|
||||
{
|
||||
/* The Haste Rune doubles player speed */
|
||||
if (target.g_items & 0x00001000i) {
|
||||
return (target.flags & FL_CROUCHING) ? 200 : 420;
|
||||
} else {
|
||||
return (target.flags & FL_CROUCHING) ? 100 : 220;
|
||||
}
|
||||
}
|
||||
|
||||
void GamePMove_Fall(player target, float impactspeed)
|
||||
{
|
||||
if (impactspeed > 580) {
|
||||
#ifdef SERVER
|
||||
float fFallDamage = (impactspeed - 580) * (100 / (1024 - 580));
|
||||
Damage_Apply(self, world, fFallDamage, 0, DMG_FALL);
|
||||
/* TODO add armor specific fall damage */
|
||||
Sound_Play(self, CHAN_AUTO, "player.fall");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void GamePMove_Jump(player target)
|
||||
{
|
||||
float flJumptimeDelta;
|
||||
float flChainBonus;
|
||||
|
||||
if (target.waterlevel >= 2) {
|
||||
if (target.watertype == CONTENT_WATER) {
|
||||
target.velocity[2] = 100;
|
||||
} else if (target.watertype == CONTENT_SLIME) {
|
||||
target.velocity[2] = 80;
|
||||
} else {
|
||||
target.velocity[2] = 50;
|
||||
}
|
||||
} else {
|
||||
target.velocity[2] += 240;
|
||||
}
|
||||
|
||||
if (target.jumptime > 0) {
|
||||
flJumptimeDelta = 0 - (target.jumptime - PHY_JUMP_CHAINWINDOW);
|
||||
flChainBonus = PHY_JUMP_CHAIN - (((PHY_JUMP_CHAINWINDOW - (PHY_JUMP_CHAINWINDOW - flJumptimeDelta)) * 2) * PHY_JUMP_CHAINDECAY);
|
||||
target.velocity[2] += flChainBonus;
|
||||
}
|
||||
target.jumptime = PHY_JUMP_CHAINWINDOW;
|
||||
}
|
236
src/shared/w_broom.qc
Normal file
236
src/shared/w_broom.qc
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
BROOM_IDLE,
|
||||
BROOM_DRAW,
|
||||
BROOM_HOLSTER,
|
||||
BROOM_ATTACK1HIT,
|
||||
BROOM_ATTACK1MISS,
|
||||
BROOM_ATTACK2MISS,
|
||||
BROOM_ATTACK2HIT,
|
||||
BROOM_ATTACK3MISS,
|
||||
BROOM_ATTACK3HIT
|
||||
};
|
||||
|
||||
void
|
||||
w_broom_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_broom.hit");
|
||||
Sound_Precache("weapon_broom.miss");
|
||||
Sound_Precache("weapon_broom.hitbody");
|
||||
#endif
|
||||
precache_model("models/v_broom.mdl");
|
||||
precache_model("models/w_broom.mdl");
|
||||
precache_model("models/p_broom.mdl");
|
||||
}
|
||||
|
||||
void
|
||||
w_broom_updateammo(player pl)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Weapons_UpdateAmmo(pl, -1, -1, -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
string
|
||||
w_broom_wmodel(void)
|
||||
{
|
||||
return "models/w_broom.mdl";
|
||||
/* model = "models/w_broom.mdl";
|
||||
SetRenderMode(RM_FULLBRIGHT);
|
||||
SetRenderAmt(255); */
|
||||
}
|
||||
string
|
||||
w_broom_pmodel(void)
|
||||
{
|
||||
return "models/p_broom.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_broom_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
w_broom_draw(void)
|
||||
{
|
||||
Weapons_SetModel("models/v_broom.mdl");
|
||||
Weapons_ViewAnimation(BROOM_DRAW);
|
||||
}
|
||||
|
||||
void
|
||||
w_broom_holster(void)
|
||||
{
|
||||
Weapons_ViewAnimation(BROOM_HOLSTER);
|
||||
}
|
||||
|
||||
void
|
||||
w_broom_primary(void)
|
||||
{
|
||||
int anim = 0;
|
||||
vector src;
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
src = pl.origin + pl.view_ofs;
|
||||
|
||||
/* make sure we can gib corpses */
|
||||
int oldhitcontents = self.hitcontentsmaski;
|
||||
self.hitcontentsmaski = CONTENTBITS_POINTSOLID | CONTENTBIT_CORPSE;
|
||||
traceline(src, src + (v_forward * 32), FALSE, pl);
|
||||
self.hitcontentsmaski = oldhitcontents;
|
||||
|
||||
if (trace_fraction >= 1.0) {
|
||||
pl.w_attack_next = 0.5f;
|
||||
} else {
|
||||
pl.w_attack_next = 0.25f;
|
||||
}
|
||||
pl.w_idle_next = 2.5f;
|
||||
|
||||
int r = (float)input_sequence % 3;
|
||||
switch (r) {
|
||||
case 0:
|
||||
Weapons_ViewAnimation(trace_fraction >= 1 ? BROOM_ATTACK1MISS:BROOM_ATTACK1HIT);
|
||||
break;
|
||||
case 1:
|
||||
Weapons_ViewAnimation(trace_fraction >= 1 ? BROOM_ATTACK2MISS:BROOM_ATTACK2HIT);
|
||||
break;
|
||||
default:
|
||||
Weapons_ViewAnimation(trace_fraction >= 1 ? BROOM_ATTACK3MISS:BROOM_ATTACK3HIT);
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
if (pl.flags & FL_CROUCHING) {
|
||||
Animation_PlayerTopTemp(ANIM_SHOOTCROWBAR, 0.5f);
|
||||
} else {
|
||||
Animation_PlayerTopTemp(ANIM_CR_SHOOTCROWBAR, 0.42f);
|
||||
}
|
||||
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_broom.miss");
|
||||
|
||||
if (trace_fraction >= 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't bother with decals, we got squibs */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
}
|
||||
|
||||
if (trace_ent.takedamage) {
|
||||
Damage_Apply(trace_ent, pl, Skill_GetValue("plr_crowbar", 10), WEAPON_BROOM, DMG_BLUNT);
|
||||
if (trace_ent.iBleeds) {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_broom.hitbody");
|
||||
}
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_broom.hit");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_broom_release(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_idle_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_ViewAnimation(BROOM_IDLE);
|
||||
pl.w_idle_next = 15.0f;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
w_broom_aimanim(void)
|
||||
{
|
||||
return self.flags & FL_CROUCHING ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR;
|
||||
}
|
||||
|
||||
void
|
||||
w_broom_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/640hud4.spr_0.tga",
|
||||
[0,0],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/640hud1.spr_0.tga",
|
||||
[0,0],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_broom =
|
||||
{
|
||||
.name = "broom",
|
||||
.id = ITEM_BROOM,
|
||||
.slot = 0,
|
||||
.slot_pos = 0,
|
||||
.draw = w_broom_draw,
|
||||
.holster = w_broom_holster,
|
||||
.primary = w_broom_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = w_broom_release,
|
||||
.crosshair = __NULL__,
|
||||
.precache = w_broom_precache,
|
||||
.pickup = __NULL__,
|
||||
.updateammo = w_broom_updateammo,
|
||||
.wmodel = w_broom_wmodel,
|
||||
.pmodel = w_broom_pmodel,
|
||||
.deathmsg = w_broom_deathmsg,
|
||||
.aimanim = w_broom_aimanim,
|
||||
.hudpic = w_broom_hudpic
|
||||
};
|
||||
|
||||
/* entity definitions for pickups */
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_broom(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_BROOM);
|
||||
/*item_pickup item = (item_pickup)self;
|
||||
item.SetRenderMode(RM_FULLBRIGHT);
|
||||
item.SetRenderAmt(1.0f);*/
|
||||
}
|
||||
#endif
|
348
src/shared/w_forks.qc
Normal file
348
src/shared/w_forks.qc
Normal file
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*QUAKED weapon_forks (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/w_fork.mdl"
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Throwable Forks Weapon
|
||||
|
||||
Pile of 6 forks.
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
FORKS_IDLE1,
|
||||
FORKS_IDLE2,
|
||||
FORKS_IDLE3,
|
||||
FORKS_STAB,
|
||||
FORKS_THROW,
|
||||
FORKS_DRAW,
|
||||
FORKS_HOLSTER
|
||||
};
|
||||
|
||||
void
|
||||
w_forks_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_forks.hit");
|
||||
Sound_Precache("weapon_forks.hitbody");
|
||||
Sound_Precache("weapon_forks.stick");
|
||||
Sound_Precache("weapon_forks.throw");
|
||||
#endif
|
||||
precache_model("sprites/hud_fork.spr");
|
||||
precache_model("models/v_fork.mdl");
|
||||
precache_model("models/w_fork.mdl");
|
||||
precache_model("models/p_fork.mdl");
|
||||
}
|
||||
|
||||
void
|
||||
w_forks_updateammo(player pl)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Weapons_UpdateAmmo(pl, __NULL__, pl.ammo_forks, __NULL__);
|
||||
#endif
|
||||
}
|
||||
|
||||
string
|
||||
w_forks_wmodel(void)
|
||||
{
|
||||
return "models/w_forks.mdl";
|
||||
}
|
||||
string
|
||||
w_forks_pmodel(void)
|
||||
{
|
||||
return "models/p_fork.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_forks_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
w_forks_pickup(int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
player pl = (player)self;
|
||||
if (pl.ammo_forks < MAX_A_FORKS) {
|
||||
pl.ammo_forks = bound(0, pl.ammo_forks + 6, MAX_A_FORKS);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
void
|
||||
w_forks_draw(void)
|
||||
{
|
||||
Weapons_SetModel("models/v_fork.mdl");
|
||||
Weapons_ViewAnimation(FORKS_DRAW);
|
||||
}
|
||||
|
||||
void
|
||||
w_forks_holster(void)
|
||||
{
|
||||
Weapons_ViewAnimation(FORKS_HOLSTER);
|
||||
}
|
||||
|
||||
void
|
||||
w_forks_primary(void)
|
||||
{
|
||||
int anim = 0;
|
||||
vector src;
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
src = pl.origin + pl.view_ofs;
|
||||
traceline(src, src + (v_forward * 32), FALSE, pl);
|
||||
|
||||
|
||||
pl.w_attack_next = 0.4f;
|
||||
pl.w_idle_next = 2.5f;
|
||||
|
||||
Weapons_ViewAnimation(FORKS_STAB);
|
||||
|
||||
#ifdef SERVER
|
||||
if (pl.flags & FL_CROUCHING) {
|
||||
Animation_PlayerTopTemp(ANIM_SHOOTCROWBAR, 0.5f);
|
||||
} else {
|
||||
Animation_PlayerTopTemp(ANIM_CR_SHOOTCROWBAR, 0.42f);
|
||||
}
|
||||
|
||||
if (trace_fraction >= 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't bother with decals, we got squibs */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
} else {
|
||||
FX_Impact(IMPACT_MELEE, trace_endpos, trace_plane_normal);
|
||||
}
|
||||
|
||||
if (trace_ent.takedamage) {
|
||||
Damage_Apply(trace_ent, pl, 5, WEAPON_FORKS, DMG_BLUNT);
|
||||
if (trace_ent.iBleeds) {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_forks.hitbody");
|
||||
}
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_forks.hit");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_forks_secondary(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ammo check */
|
||||
#ifdef CLIENT
|
||||
if (pl.a_ammo2 <= 0) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (pl.ammo_forks <= 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Secondary has an ammo based throw function */
|
||||
#ifdef SERVER
|
||||
static void Fork_Touch(void) {
|
||||
setmodel(self, "models/fork.mdl");
|
||||
|
||||
/* don't bother with decals, we got squibs */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
remove(self);
|
||||
} else {
|
||||
FX_Impact(IMPACT_DEFAULT, trace_endpos, trace_plane_normal);
|
||||
}
|
||||
|
||||
if (other.takedamage == DAMAGE_YES) {
|
||||
Damage_Apply(other, self.owner, 15, WEAPON_FORKS, DMG_GENERIC);
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_forks.hitbody");
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_forks.stick");
|
||||
}
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
entity fork = spawn();
|
||||
setmodel(fork, "models/fork.mdl");
|
||||
setorigin(fork, Weapons_GetCameraPos() + (v_forward * 16));
|
||||
fork.owner = self;
|
||||
fork.velocity = v_forward * 2000;
|
||||
fork.movetype = MOVETYPE_FLY;
|
||||
fork.solid = SOLID_BBOX;
|
||||
fork.angles = vectoangles(fork.velocity);
|
||||
fork.avelocity[2] = 10;
|
||||
fork.touch = Fork_Touch;
|
||||
setsize(fork, [0,0,0], [0,0,0]);
|
||||
|
||||
pl.ammo_forks--;
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_forks.throw");
|
||||
#else
|
||||
Weapons_ViewPunchAngle([-2,0,0]);
|
||||
Weapons_ViewAnimation(FORKS_THROW);
|
||||
#endif
|
||||
|
||||
pl.w_attack_next = 0.5f;
|
||||
pl.w_idle_next = 5.0f;
|
||||
}
|
||||
|
||||
void
|
||||
w_forks_release(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_idle_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int r;
|
||||
r = (float)input_sequence % 3;
|
||||
switch (r) {
|
||||
case 1:
|
||||
Weapons_ViewAnimation(FORKS_IDLE1);
|
||||
pl.w_idle_next = 1.3f;
|
||||
break;
|
||||
case 2:
|
||||
Weapons_ViewAnimation(FORKS_IDLE2);
|
||||
pl.w_idle_next = 3.0f;
|
||||
break;
|
||||
default:
|
||||
Weapons_ViewAnimation(FORKS_IDLE3);
|
||||
pl.w_idle_next = 1.285f;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
w_forks_crosshair(void)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
static vector cross_pos;
|
||||
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
|
||||
drawsubpic(
|
||||
cross_pos,
|
||||
[24,24],
|
||||
"sprites/crosshairs.spr_0.tga",
|
||||
[72/128,48/128],
|
||||
[0.1875, 0.1875],
|
||||
[1,1,1],
|
||||
1,
|
||||
DRAWFLAG_NORMAL
|
||||
);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
vector aicon_pos = g_hudmins + [g_hudres[0] - 42, g_hudres[1] - 64];
|
||||
drawpic(
|
||||
aicon_pos,
|
||||
"sprites/hud_fork.spr_0.tga",
|
||||
[32,64],
|
||||
[1,1,1],
|
||||
pSeat->m_flAmmo2Alpha,
|
||||
0
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_forks_aimanim(void)
|
||||
{
|
||||
return w_broom_aimanim();
|
||||
}
|
||||
|
||||
void
|
||||
w_forks_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud04.spr_0.tga",
|
||||
[0,135/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud03.spr_0.tga",
|
||||
[0,90/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_forks =
|
||||
{
|
||||
.name = "fork",
|
||||
.id = ITEM_FORKS,
|
||||
.slot = 0,
|
||||
.slot_pos = 2,
|
||||
.draw = w_forks_draw,
|
||||
.holster = w_forks_holster,
|
||||
.primary = w_forks_primary,
|
||||
.secondary = w_forks_secondary,
|
||||
.reload = __NULL__,
|
||||
.release = w_forks_release,
|
||||
.crosshair = w_forks_crosshair,
|
||||
.precache = w_forks_precache,
|
||||
.pickup = w_forks_pickup,
|
||||
.updateammo = w_forks_updateammo,
|
||||
.wmodel = w_forks_wmodel,
|
||||
.pmodel = w_forks_pmodel,
|
||||
.deathmsg = w_forks_deathmsg,
|
||||
.aimanim = w_forks_aimanim,
|
||||
.hudpic = w_forks_hudpic
|
||||
};
|
||||
|
||||
/* entity definitions for pickups */
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_forks(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_FORKS);
|
||||
/*item_pickup item = (item_pickup)self;
|
||||
item.SetRenderMode(RM_FULLBRIGHT);
|
||||
item.SetRenderAmt(1.0f);*/
|
||||
}
|
||||
#endif
|
256
src/shared/w_fryingpan.qc
Normal file
256
src/shared/w_fryingpan.qc
Normal file
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
FRYINGPAN_IDLE1,
|
||||
FRYINGPAN_IDLE2,
|
||||
FRYINGPAN_HIT1,
|
||||
FRYINGPAN_HIT2,
|
||||
FRYINGPAN_DRAW,
|
||||
FRYINGPAN_HOLSTER
|
||||
};
|
||||
|
||||
void
|
||||
w_fryingpan_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_fryingpan.hit");
|
||||
Sound_Precache("weapon_fryingpan.miss");
|
||||
Sound_Precache("weapon_fryingpan.hitbody");
|
||||
#endif
|
||||
precache_model("models/v_pan.mdl");
|
||||
precache_model("models/w_pan.mdl");
|
||||
precache_model("models/p_pan.mdl");
|
||||
}
|
||||
|
||||
void
|
||||
w_fryingpan_updateammo(player pl)
|
||||
{
|
||||
w_broom_updateammo(pl);
|
||||
}
|
||||
|
||||
string
|
||||
w_fryingpan_wmodel(void)
|
||||
{
|
||||
return "models/w_pan.mdl";
|
||||
}
|
||||
string
|
||||
w_fryingpan_pmodel(void)
|
||||
{
|
||||
return "models/p_pan.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_fryingpan_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
w_fryingpan_draw(void)
|
||||
{
|
||||
Weapons_SetModel("models/v_pan.mdl");
|
||||
Weapons_ViewAnimation(FRYINGPAN_DRAW);
|
||||
}
|
||||
|
||||
void
|
||||
w_fryingpan_holster(void)
|
||||
{
|
||||
w_broom_holster();
|
||||
}
|
||||
|
||||
void
|
||||
w_fryingpan_primary(void)
|
||||
{
|
||||
int anim = 0;
|
||||
vector src;
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
src = pl.origin + pl.view_ofs;
|
||||
traceline(src, src + (v_forward * 32), FALSE, pl);
|
||||
|
||||
|
||||
pl.w_attack_next = 1.0f;
|
||||
pl.w_idle_next = 2.5f;
|
||||
|
||||
Weapons_ViewAnimation(FRYINGPAN_HIT1);
|
||||
|
||||
#ifdef SERVER
|
||||
if (pl.flags & FL_CROUCHING) {
|
||||
Animation_PlayerTopTemp(ANIM_SHOOTCROWBAR, 0.5f);
|
||||
} else {
|
||||
Animation_PlayerTopTemp(ANIM_CR_SHOOTCROWBAR, 0.42f);
|
||||
}
|
||||
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_fryingpan.miss");
|
||||
|
||||
if (trace_fraction >= 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't bother with decals, we got squibs */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
} else {
|
||||
FX_Impact(IMPACT_MELEE, trace_endpos, trace_plane_normal);
|
||||
}
|
||||
|
||||
if (trace_ent.takedamage) {
|
||||
Damage_Apply(trace_ent, pl, 5, WEAPON_FRYINGPAN, DMG_BLUNT);
|
||||
if (trace_ent.iBleeds) {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_fryingpan.hitbody");
|
||||
}
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_fryingpan.hit");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_fryingpan_secondary(void)
|
||||
{
|
||||
int anim = 0;
|
||||
vector src;
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
src = pl.origin + pl.view_ofs;
|
||||
traceline(src, src + (v_forward * 32), FALSE, pl);
|
||||
|
||||
|
||||
pl.w_attack_next = 1.0f;
|
||||
pl.w_idle_next = 2.5f;
|
||||
|
||||
Weapons_ViewAnimation(FRYINGPAN_HIT2);
|
||||
|
||||
#ifdef SERVER
|
||||
if (pl.flags & FL_CROUCHING) {
|
||||
Animation_PlayerTopTemp(ANIM_SHOOTCROWBAR, 0.5f);
|
||||
} else {
|
||||
Animation_PlayerTopTemp(ANIM_CR_SHOOTCROWBAR, 0.42f);
|
||||
}
|
||||
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_fryingpan.miss");
|
||||
|
||||
if (trace_fraction >= 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't bother with decals, we got squibs */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
} else {
|
||||
FX_Impact(IMPACT_MELEE, trace_endpos, trace_plane_normal);
|
||||
}
|
||||
|
||||
if (trace_ent.takedamage) {
|
||||
Damage_Apply(trace_ent, pl, 5, WEAPON_FRYINGPAN, DMG_BLUNT);
|
||||
if (trace_ent.iBleeds) {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_fryingpan.hitbody");
|
||||
}
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_fryingpan.hit");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_fryingpan_release(void)
|
||||
{
|
||||
w_broom_release();
|
||||
}
|
||||
|
||||
float
|
||||
w_fryingpan_aimanim(void)
|
||||
{
|
||||
return w_broom_aimanim();
|
||||
}
|
||||
|
||||
void
|
||||
w_fryingpan_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud04.spr_0.tga",
|
||||
[0,135/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud03.spr_0.tga",
|
||||
[0,90/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_fryingpan =
|
||||
{
|
||||
.name = "fryingpan",
|
||||
.id = ITEM_FRYINGPAN,
|
||||
.slot = 0,
|
||||
.slot_pos = 1,
|
||||
.draw = w_fryingpan_draw,
|
||||
.holster = w_fryingpan_holster,
|
||||
.primary = w_fryingpan_primary,
|
||||
.secondary = w_fryingpan_secondary,
|
||||
.reload = __NULL__,
|
||||
.release = w_fryingpan_release,
|
||||
.crosshair = __NULL__,
|
||||
.precache = w_fryingpan_precache,
|
||||
.pickup = __NULL__,
|
||||
.updateammo = w_fryingpan_updateammo,
|
||||
.wmodel = w_fryingpan_wmodel,
|
||||
.pmodel = w_fryingpan_pmodel,
|
||||
.deathmsg = w_fryingpan_deathmsg,
|
||||
.aimanim = w_fryingpan_aimanim,
|
||||
.hudpic = w_fryingpan_hudpic
|
||||
};
|
||||
|
||||
/* entity definitions for pickups */
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_fryingpan(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_FRYINGPAN);
|
||||
/*item_pickup item = (item_pickup)self;
|
||||
item.SetRenderMode(RM_FULLBRIGHT);
|
||||
item.SetRenderAmt(1.0f);*/
|
||||
}
|
||||
#endif
|
266
src/shared/w_glove.qc
Normal file
266
src/shared/w_glove.qc
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*QUAKED item_rune_slasher (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/rune_slasher.mdl"
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Powerup/Weapon that turns players into a similar looking legally
|
||||
copyrighted character.
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
GLOVE_IDLE,
|
||||
GLOVE_DRAW,
|
||||
GLOVE_HOLSTER,
|
||||
GLOVE_SLICE,
|
||||
GLOVE_DICE
|
||||
|
||||
};
|
||||
|
||||
void
|
||||
w_glove_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_glove.hit");
|
||||
Sound_Precache("weapon_glove.miss");
|
||||
Sound_Precache("weapon_glove.hitbody");
|
||||
Sound_Precache("weapon_glove.pickup");
|
||||
#endif
|
||||
precache_model("models/v_glove.mdl");
|
||||
precache_model("models/rune_slasher.mdl");
|
||||
precache_model("models/p_glove.mdl");
|
||||
}
|
||||
|
||||
void
|
||||
w_glove_updateammo(player pl)
|
||||
{
|
||||
w_broom_updateammo(pl);
|
||||
}
|
||||
|
||||
string
|
||||
w_glove_wmodel(void)
|
||||
{
|
||||
return "models/rune_slasher.mdl";
|
||||
}
|
||||
string
|
||||
w_glove_pmodel(void)
|
||||
{
|
||||
return "models/p_glove.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_glove_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
w_glove_pickup(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
/* Broadcast a message and sound upon picking up Rune */
|
||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||
WriteByte(MSG_MULTICAST, EV_TEXT);
|
||||
WriteByte(MSG_MULTICAST, 0);
|
||||
WriteString(MSG_MULTICAST, sprintf("One... Two... %s's coming for you...", self.netname));
|
||||
WriteFloat(MSG_MULTICAST, -1);
|
||||
WriteFloat(MSG_MULTICAST, -1);
|
||||
WriteByte(MSG_MULTICAST, 0);
|
||||
WriteByte(MSG_MULTICAST, 255);
|
||||
WriteByte(MSG_MULTICAST, 0);
|
||||
WriteByte(MSG_MULTICAST, 0);
|
||||
WriteByte(MSG_MULTICAST, 255);
|
||||
WriteByte(MSG_MULTICAST, 0);
|
||||
WriteByte(MSG_MULTICAST, 0);
|
||||
WriteFloat(MSG_MULTICAST, 0.2);
|
||||
WriteFloat(MSG_MULTICAST, 0.5);
|
||||
WriteFloat(MSG_MULTICAST, 5.0);
|
||||
WriteFloat(MSG_MULTICAST, 0);
|
||||
|
||||
msg_entity = world;
|
||||
multicast([0,0,0], MULTICAST_ALL);
|
||||
|
||||
Sound_Play(self, CHAN_ITEM, "weapon_glove.pickup");
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
w_glove_draw(void)
|
||||
{
|
||||
Weapons_SetModel("models/v_glove.mdl");
|
||||
Weapons_ViewAnimation(GLOVE_DRAW);
|
||||
}
|
||||
|
||||
void
|
||||
w_glove_holster(void)
|
||||
{
|
||||
Weapons_ViewAnimation(GLOVE_HOLSTER);
|
||||
}
|
||||
|
||||
void
|
||||
w_glove_primary(void)
|
||||
{
|
||||
int anim = 0;
|
||||
vector src;
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
src = pl.origin + pl.view_ofs;
|
||||
traceline(src, src + (v_forward * 32), FALSE, pl);
|
||||
|
||||
if (trace_fraction >= 1.0) {
|
||||
pl.w_attack_next = 0.5f;
|
||||
} else {
|
||||
pl.w_attack_next = 0.25f;
|
||||
}
|
||||
pl.w_idle_next = 2.5f;
|
||||
|
||||
int r = (float)input_sequence % 2;
|
||||
switch (r) {
|
||||
case 1:
|
||||
Weapons_ViewAnimation(GLOVE_SLICE);
|
||||
pl.w_idle_next = 3.6f;
|
||||
break;
|
||||
default:
|
||||
Weapons_ViewAnimation(GLOVE_DICE);
|
||||
pl.w_idle_next = 3.6f;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
if (pl.flags & FL_CROUCHING) {
|
||||
Animation_PlayerTopTemp(ANIM_SHOOTCROWBAR, 0.5f);
|
||||
} else {
|
||||
Animation_PlayerTopTemp(ANIM_CR_SHOOTCROWBAR, 0.42f);
|
||||
}
|
||||
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_glove.miss");
|
||||
|
||||
if (trace_fraction >= 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Since it has custom decals we do both FX and decal placement */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
} else {
|
||||
FX_Spark(trace_endpos, trace_plane_normal);
|
||||
int r = (float)input_sequence % 2;
|
||||
Decals_Place(trace_endpos, r == 1 ? "{slash1" : "{slash2");
|
||||
|
||||
}
|
||||
|
||||
if (trace_ent.takedamage) {
|
||||
Damage_Apply(trace_ent, pl, Skill_GetValue("plr_crowbar", 10), WEAPON_GLOVE, DMG_BLUNT);
|
||||
if (trace_ent.iBleeds) {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_glove.hitbody");
|
||||
}
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_glove.hit");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_glove_release(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_idle_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_ViewAnimation(GLOVE_IDLE);
|
||||
pl.w_idle_next = 2.0f;
|
||||
}
|
||||
|
||||
float
|
||||
w_glove_aimanim(void)
|
||||
{
|
||||
return w_broom_aimanim();
|
||||
}
|
||||
|
||||
void
|
||||
w_glove_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud04.spr_0.tga",
|
||||
[0,135/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud03.spr_0.tga",
|
||||
[0,90/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_glove =
|
||||
{
|
||||
.name = "glove",
|
||||
.id = ITEM_GLOVE,
|
||||
.slot = 1,
|
||||
.slot_pos = 0,
|
||||
.draw = w_glove_draw,
|
||||
.holster = w_glove_holster,
|
||||
.primary = w_glove_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = w_glove_release,
|
||||
.crosshair = __NULL__,
|
||||
.precache = w_glove_precache,
|
||||
.pickup = w_glove_pickup,
|
||||
.updateammo = w_glove_updateammo,
|
||||
.wmodel = w_glove_wmodel,
|
||||
.pmodel = w_glove_pmodel,
|
||||
.deathmsg = w_glove_deathmsg,
|
||||
.aimanim = w_glove_aimanim,
|
||||
.hudpic = w_glove_hudpic
|
||||
};
|
||||
|
||||
/* entity definitions for pickups */
|
||||
#ifdef SERVER
|
||||
void
|
||||
item_rune_slasher(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_GLOVE);
|
||||
}
|
||||
#endif
|
285
src/shared/w_hairspray.qc
Normal file
285
src/shared/w_hairspray.qc
Normal file
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*QUAKED weapon_hairspray (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/w_knife.mdl"
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Flamethrower Hairspray Weapon
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
HAIRSPRAY_IDLE,
|
||||
HAIRSPRAY_FIRE,
|
||||
HAIRSPRAY_DRAW,
|
||||
HAIRSPRAY_HOLSTER
|
||||
};
|
||||
|
||||
void
|
||||
w_hairspray_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_hairspray.fire");
|
||||
#endif
|
||||
precache_model("sprites/flame.spr");
|
||||
precache_model("sprites/hud_haircan.spr");
|
||||
precache_model("models/v_hairspray.mdl");
|
||||
precache_model("models/w_hairspray.mdl");
|
||||
precache_model("models/p_hairspray.mdl");
|
||||
}
|
||||
|
||||
void
|
||||
w_hairspray_updateammo(player pl)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Weapons_UpdateAmmo(pl, __NULL__, pl.ammo_spray, __NULL__);
|
||||
#endif
|
||||
}
|
||||
|
||||
string
|
||||
w_hairspray_wmodel(void)
|
||||
{
|
||||
return "models/w_hairspray.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_hairspray_pmodel(void)
|
||||
{
|
||||
return "models/p_hairspray.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_hairspray_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
w_hairspray_pickup(int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
player pl = (player)self;
|
||||
if (pl.ammo_spray < MAX_A_SPRAY) {
|
||||
pl.ammo_spray = bound(0, pl.ammo_spray + 20, MAX_A_SPRAY);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
w_hairspray_draw(void)
|
||||
{
|
||||
Weapons_SetModel("models/v_hairspray.mdl");
|
||||
Weapons_ViewAnimation(HAIRSPRAY_DRAW);
|
||||
}
|
||||
|
||||
void
|
||||
w_hairspray_holster(void)
|
||||
{
|
||||
Weapons_ViewAnimation(HAIRSPRAY_HOLSTER);
|
||||
}
|
||||
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
Flame_Touch(void)
|
||||
{
|
||||
if (other.takedamage != DAMAGE_YES) {
|
||||
remove(self);
|
||||
return;
|
||||
}
|
||||
|
||||
/* anything else that can take damage */
|
||||
Damage_Apply(other, self.owner, 40, WEAPON_HAIRSPRAY, DMG_BURN);
|
||||
remove(self);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
w_hairspray_primary(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
if (pl.w_attack_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ammo check */
|
||||
#ifdef CLIENT
|
||||
if (pl.a_ammo2 <= 0) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (pl.ammo_spray <= 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Actual firing */
|
||||
#ifdef CLIENT
|
||||
Weapons_ViewAnimation(HAIRSPRAY_FIRE);
|
||||
pl.a_ammo2--;
|
||||
#else
|
||||
Weapons_MakeVectors();
|
||||
entity flame = spawn();
|
||||
setmodel(flame, "sprites/flame.spr");
|
||||
setorigin(flame, Weapons_GetCameraPos() + (v_forward * 16));
|
||||
flame.owner = self;
|
||||
flame.velocity = v_forward * 300;
|
||||
flame.movetype = MOVETYPE_FLYMISSILE;
|
||||
flame.solid = SOLID_BBOX;
|
||||
//flame.flags |= FL_LAGGEDMOVE;
|
||||
flame.angles = vectoangles(flame.velocity);
|
||||
flame.avelocity[2] = 10;
|
||||
flame.touch = Flame_Touch;
|
||||
flame.think = Flame_Touch;
|
||||
flame.nextthink = time + 1.0f;
|
||||
flame.effects |= EF_BRIGHTLIGHT;
|
||||
setsize(flame, [0,0,0], [0,0,0]);
|
||||
|
||||
pl.ammo_spray--;
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_hairspray.fire");
|
||||
|
||||
/* Remove weapon if we run out of ammo */
|
||||
if (pl.ammo_spray <= 0) {
|
||||
Weapons_RemoveItem(pl, WEAPON_HAIRSPRAY);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
pl.w_attack_next = 0.2f;
|
||||
pl.w_idle_next = 2.5f;
|
||||
}
|
||||
|
||||
void
|
||||
w_hairspray_release(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_idle_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
sound(pl, CHAN_WEAPON, "", 1.0, ATTN_NORM);
|
||||
Weapons_ViewAnimation(HAIRSPRAY_IDLE);
|
||||
pl.w_idle_next = 2.0f;
|
||||
}
|
||||
void
|
||||
w_hairspray_crosshair(void)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
static vector cross_pos;
|
||||
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
|
||||
drawsubpic(
|
||||
cross_pos,
|
||||
[24,24],
|
||||
"sprites/crosshairs.spr_0.tga",
|
||||
[72/128,48/128],
|
||||
[0.1875, 0.1875],
|
||||
[1,1,1],
|
||||
1,
|
||||
DRAWFLAG_NORMAL
|
||||
);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
vector aicon_pos = g_hudmins + [g_hudres[0] - 42, g_hudres[1] - 64];
|
||||
drawpic(
|
||||
aicon_pos,
|
||||
"sprites/hud_haircan.spr_0.tga",
|
||||
[32,64],
|
||||
[1,1,1],
|
||||
pSeat->m_flAmmo2Alpha,
|
||||
0
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_hairspray_aimanim(void)
|
||||
{
|
||||
return self.flags & FL_CROUCHING ? ANIM_CR_AIMBOW : ANIM_AIMBOW;
|
||||
}
|
||||
|
||||
void
|
||||
w_hairspray_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud04.spr_0.tga",
|
||||
[0,45/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud03.spr_0.tga",
|
||||
[0,0/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_hairspray =
|
||||
{
|
||||
.name = "flame",
|
||||
.id = ITEM_HAIRSPRAY,
|
||||
.slot = 0,
|
||||
.slot_pos = 6,
|
||||
.draw = w_hairspray_draw,
|
||||
.holster = w_hairspray_holster,
|
||||
.primary = w_hairspray_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = w_hairspray_release,
|
||||
.crosshair = w_hairspray_crosshair,
|
||||
.precache = w_hairspray_precache,
|
||||
.pickup = w_hairspray_pickup,
|
||||
.updateammo = w_hairspray_updateammo,
|
||||
.wmodel = w_hairspray_wmodel,
|
||||
.pmodel = w_hairspray_pmodel,
|
||||
.deathmsg = w_hairspray_deathmsg,
|
||||
.aimanim = w_hairspray_aimanim,
|
||||
.hudpic = w_hairspray_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_hairspray(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_HAIRSPRAY);
|
||||
/*item_pickup item = (item_pickup)self;
|
||||
item.SetRenderMode(RM_FULLBRIGHT);
|
||||
item.SetRenderAmt(1.0f);*/
|
||||
}
|
||||
#endif
|
315
src/shared/w_knife.qc
Normal file
315
src/shared/w_knife.qc
Normal file
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*QUAKED weapon_knife (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/w_knife.mdl"
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Throwable Butcher/Cleaver Knife Weapon
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
KNIFE_IDLE1,
|
||||
KNIFE_IDLE2,
|
||||
KNIFE_IDLE3,
|
||||
KNIFE_THROW,
|
||||
KNIFE_DRAW,
|
||||
KNIFE_HOLSTER
|
||||
};
|
||||
|
||||
void
|
||||
w_knife_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_knife.hitbody");
|
||||
Sound_Precache("weapon_knife.move");
|
||||
Sound_Precache("weapon_knife.stick");
|
||||
Sound_Precache("weapon_knife.throw");
|
||||
#endif
|
||||
precache_model("sprites/hud_knife.spr");
|
||||
precache_model("models/knife.mdl");
|
||||
precache_model("models/v_knife.mdl");
|
||||
precache_model("models/w_knife.mdl");
|
||||
precache_model("models/p_knife.mdl");
|
||||
}
|
||||
|
||||
void
|
||||
w_knife_updateammo(player pl)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Weapons_UpdateAmmo(pl, __NULL__, pl.ammo_knives, __NULL__);
|
||||
#endif
|
||||
}
|
||||
|
||||
string
|
||||
w_knife_wmodel(void)
|
||||
{
|
||||
return "models/w_knife.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_knife_pmodel(void)
|
||||
{
|
||||
return "models/p_knife.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_knife_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
w_knife_pickup(int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.ammo_knives < MAX_A_KNIVES) {
|
||||
pl.ammo_knives = bound(0, pl.ammo_knives + 1, MAX_A_KNIVES);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
w_knife_draw(void)
|
||||
{
|
||||
Weapons_SetModel("models/v_knife.mdl");
|
||||
Weapons_ViewAnimation(KNIFE_DRAW);
|
||||
}
|
||||
|
||||
void
|
||||
w_knife_holster(void)
|
||||
{
|
||||
Weapons_ViewAnimation(KNIFE_HOLSTER);
|
||||
}
|
||||
|
||||
void
|
||||
w_knife_primary(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ammo check */
|
||||
#ifdef CLIENT
|
||||
if (pl.a_ammo2 <= 0) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (pl.ammo_knives <= 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Actual firing */
|
||||
#ifdef SERVER
|
||||
static void Knife_Touch(void) {
|
||||
/* Has two submodels, changes random in view and world model */
|
||||
setmodel(self, "models/knife.mdl");
|
||||
|
||||
/* Bleed and remove model if player, stick and spark if wall */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
remove(self);
|
||||
} else {
|
||||
FX_Spark(trace_endpos, trace_plane_normal);
|
||||
}
|
||||
|
||||
if (other.takedamage == DAMAGE_YES) {
|
||||
Damage_Apply(other, self.owner, 15, WEAPON_KNIFE, DMG_GENERIC);
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_knife.hitbody");
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_knife.stick");
|
||||
}
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
entity knife = spawn();
|
||||
setmodel(knife, "models/w_knife.mdl");
|
||||
setorigin(knife, Weapons_GetCameraPos());
|
||||
knife.owner = self;
|
||||
knife.velocity = v_forward * 1200;
|
||||
knife.movetype = MOVETYPE_FLY;
|
||||
knife.solid = SOLID_BBOX;
|
||||
knife.angles = vectoangles(knife.velocity);
|
||||
knife.avelocity[2] = 10;
|
||||
knife.touch = Knife_Touch;
|
||||
/* TODO Knife randomly changes submodel upon firing, no API support yet
|
||||
* int r = (float)input_sequence % 2;
|
||||
* setcustomskin(knife, "", r == 1 ? "geomset 1 0\n" : "geomset 1 1\n"); */
|
||||
setsize(knife, [0,0,0], [0,0,0]);
|
||||
|
||||
/* The thrown knife has it's own movement sound */
|
||||
Sound_Play(knife, CHAN_WEAPON, "weapon_knife.move");
|
||||
|
||||
pl.ammo_knives--;
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_knife.throw");
|
||||
|
||||
/* Remove weapon if we run out of knives */
|
||||
if (pl.ammo_knives <= 0) {
|
||||
Weapons_RemoveItem(pl, WEAPON_KNIFE);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
Weapons_ViewPunchAngle([-2,0,0]);
|
||||
Weapons_ViewAnimation(KNIFE_THROW);
|
||||
/* Knife randomly changes submodel upon firing */
|
||||
int r = (float)input_sequence % 2;
|
||||
Weapons_SetGeomset(r == 1 ? "geomset 0 0\n" : "geomset 0 1\n");
|
||||
#endif
|
||||
|
||||
pl.w_attack_next = 0.8f;
|
||||
pl.w_idle_next = 5.0f;
|
||||
}
|
||||
|
||||
void
|
||||
w_knife_release(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_idle_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int r;
|
||||
r = (float)input_sequence % 3;
|
||||
switch (r) {
|
||||
case 1:
|
||||
Weapons_ViewAnimation(KNIFE_IDLE1);
|
||||
pl.w_idle_next = 2.0f;
|
||||
break;
|
||||
case 2:
|
||||
Weapons_ViewAnimation(KNIFE_IDLE2);
|
||||
pl.w_idle_next = 3.0f;
|
||||
break;
|
||||
default:
|
||||
Weapons_ViewAnimation(KNIFE_IDLE3);
|
||||
pl.w_idle_next = 1.285f;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
w_knife_crosshair(void)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
static vector cross_pos;
|
||||
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
|
||||
drawsubpic(
|
||||
cross_pos,
|
||||
[24,24],
|
||||
"sprites/crosshairs.spr_0.tga",
|
||||
[72/128,48/128],
|
||||
[0.1875, 0.1875],
|
||||
[1,1,1],
|
||||
1,
|
||||
DRAWFLAG_NORMAL
|
||||
);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
vector aicon_pos = g_hudmins + [g_hudres[0] - 42, g_hudres[1] - 64];
|
||||
drawpic(
|
||||
aicon_pos,
|
||||
"sprites/hud_knife.spr_0.tga",
|
||||
[32,64],
|
||||
[1,1,1],
|
||||
pSeat->m_flAmmo2Alpha,
|
||||
0
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_knife_aimanim(void)
|
||||
{
|
||||
return self.flags & FL_CROUCHING ? ANIM_CR_AIMBOW : ANIM_AIMBOW;
|
||||
}
|
||||
|
||||
void
|
||||
w_knife_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/640hud5.spr_0.tga",
|
||||
[0,0],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/640hud2.spr_0.tga",
|
||||
[0,0],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_knife =
|
||||
{
|
||||
.name = "knife",
|
||||
.id = ITEM_KNIFE,
|
||||
.slot = 0,
|
||||
.slot_pos = 3,
|
||||
.draw = w_knife_draw,
|
||||
.holster = w_knife_holster,
|
||||
.primary = w_knife_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = w_knife_release,
|
||||
.crosshair = w_knife_crosshair,
|
||||
.precache = w_knife_precache,
|
||||
.pickup = w_knife_pickup,
|
||||
.updateammo = w_knife_updateammo,
|
||||
.wmodel = w_knife_wmodel,
|
||||
.pmodel = w_knife_pmodel,
|
||||
.deathmsg = w_knife_deathmsg,
|
||||
.aimanim = w_knife_aimanim,
|
||||
.hudpic = w_knife_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_knife(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_KNIFE);
|
||||
/*item_pickup item = (item_pickup)self;
|
||||
item.SetRenderMode(RM_FULLBRIGHT);
|
||||
item.SetRenderAmt(1.0f);
|
||||
item.SetFloating(TRUE);*/
|
||||
}
|
||||
#endif
|
||||
|
276
src/shared/w_lego.qc
Normal file
276
src/shared/w_lego.qc
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*QUAKED weapon_handgrenade (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/w_lego.mdl"
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
Handgrenade Weapon
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
LEGO_IDLE,
|
||||
LEGO_DRAW,
|
||||
LEGO_PULLPIN,
|
||||
LEGO_THROW,
|
||||
LEGO_HOLSTER
|
||||
};
|
||||
|
||||
void w_lego_precache(void)
|
||||
{
|
||||
precache_model("sprites/hud_lego.spr");
|
||||
precache_model("models/v_lego.mdl");
|
||||
precache_model("models/w_lego.mdl");
|
||||
precache_model("models/p_lego.mdl");
|
||||
}
|
||||
void w_lego_updateammo(player pl)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Weapons_UpdateAmmo(pl, -1, pl.ammo_legogrenade, -1);
|
||||
#endif
|
||||
}
|
||||
string w_lego_wmodel(void)
|
||||
{
|
||||
return "models/w_lego.mdl";
|
||||
}
|
||||
string w_lego_pmodel(void)
|
||||
{
|
||||
return "models/p_lego.mdl";
|
||||
}
|
||||
string w_lego_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int w_lego_pickup(int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.ammo_legogrenade < MAX_A_LEGOGRENADE) {
|
||||
pl.ammo_legogrenade = bound(0, pl.ammo_legogrenade + 1, MAX_A_LEGOGRENADE);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void w_lego_throw(void)
|
||||
{
|
||||
static void WeaponLego_Throw_Touch(void) {
|
||||
float dmg = Skill_GetValue("plr_hand_grenade", 150);
|
||||
FX_Lego(trace_endpos);
|
||||
Damage_Radius(self.origin, self.owner, dmg, dmg * 1.5f, TRUE, WEAPON_LEGO);
|
||||
remove(self);
|
||||
}
|
||||
|
||||
player pl = (player)self;
|
||||
vector vPLAngle = pl.v_angle;
|
||||
if (vPLAngle[0] < 0) {
|
||||
vPLAngle[0] = -10 + vPLAngle[0] * ((90 - 10) / 90.0);
|
||||
} else {
|
||||
vPLAngle[0] = -10 + vPLAngle[0] * ((90 + 10) / 90.0);
|
||||
}
|
||||
|
||||
float flVel = (90 - vPLAngle[0]) * 5;
|
||||
if (flVel > 1000) {
|
||||
flVel = 1000;
|
||||
}
|
||||
|
||||
makevectors(vPLAngle);
|
||||
vector vecSrc = pl.origin + pl.view_ofs + v_forward * 16;
|
||||
vector vecThrow = v_forward * flVel + pl.velocity;
|
||||
|
||||
entity eGrenade = spawn();
|
||||
eGrenade.owner = pl;
|
||||
eGrenade.classname = "remove_me";
|
||||
eGrenade.solid = SOLID_BBOX;
|
||||
eGrenade.frame = 1;
|
||||
eGrenade.velocity = vecThrow;
|
||||
eGrenade.movetype = MOVETYPE_BOUNCE;
|
||||
eGrenade.touch = WeaponLego_Throw_Touch;
|
||||
eGrenade.nextthink = time + 4.0f;
|
||||
setmodel(eGrenade, "models/lego2.mdl");
|
||||
setsize(eGrenade, [0,0,0], [0,0,0]);
|
||||
setorigin(eGrenade, vecSrc);
|
||||
}
|
||||
#endif
|
||||
|
||||
void w_lego_draw(void)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
Weapons_SetModel("models/v_lego.mdl");
|
||||
Weapons_ViewAnimation(LEGO_DRAW);
|
||||
#endif
|
||||
}
|
||||
|
||||
void w_lego_holster(void)
|
||||
{
|
||||
|
||||
}
|
||||
void w_lego_primary(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
if (pl.w_attack_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We're abusing this network variable for the holding check */
|
||||
if (pl.a_ammo3 > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ammo check */
|
||||
#ifdef CLIENT
|
||||
if (pl.a_ammo2 <= 0) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (pl.ammo_legogrenade <= 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CLIENT
|
||||
Weapons_ViewAnimation(LEGO_PULLPIN);
|
||||
#endif
|
||||
|
||||
pl.a_ammo3 = 1;
|
||||
pl.w_attack_next = 0.5f;
|
||||
pl.w_idle_next = 0.5f;
|
||||
}
|
||||
|
||||
void w_lego_hud(void)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
static vector cross_pos;
|
||||
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
|
||||
drawsubpic(
|
||||
cross_pos,
|
||||
[24,24],
|
||||
"sprites/crosshairs.spr_0.tga",
|
||||
[72/128,48/128],
|
||||
[0.1875, 0.1875],
|
||||
[1,1,1],
|
||||
1,
|
||||
DRAWFLAG_NORMAL
|
||||
);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
vector aicon_pos = g_hudmins + [g_hudres[0] - 42, g_hudres[1] - 64];
|
||||
drawpic(
|
||||
aicon_pos,
|
||||
"sprites/hud_lego.spr_0.tga",
|
||||
[32,64],
|
||||
[1,1,1],
|
||||
pSeat->m_flAmmo2Alpha,
|
||||
0
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
void w_lego_release(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_idle_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (pl.a_ammo3 == 1) {
|
||||
#ifdef CLIENT
|
||||
pl.a_ammo2--;
|
||||
Weapons_ViewAnimation(LEGO_THROW);
|
||||
#else
|
||||
pl.ammo_legogrenade--;
|
||||
w_lego_throw();
|
||||
#endif
|
||||
pl.a_ammo3 = 2;
|
||||
pl.w_attack_next = 1.0f;
|
||||
pl.w_idle_next = 0.5f;
|
||||
} else if (pl.a_ammo3 == 2) {
|
||||
#ifdef CLIENT
|
||||
Weapons_ViewAnimation(LEGO_DRAW);
|
||||
#else
|
||||
if (!pl.ammo_legogrenade) {
|
||||
Weapons_RemoveItem(pl, WEAPON_LEGO);
|
||||
}
|
||||
#endif
|
||||
pl.w_attack_next = 0.5f;
|
||||
pl.w_idle_next = 0.5f;
|
||||
pl.a_ammo3 = 0;
|
||||
} else {
|
||||
Weapons_ViewAnimation(LEGO_IDLE);
|
||||
pl.w_idle_next = 3.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
w_lego_aimanim(void)
|
||||
{
|
||||
return self.flags & FL_CROUCHING ? ANIM_CR_AIMCROWBAR : ANIM_AIMCROWBAR;
|
||||
}
|
||||
|
||||
void
|
||||
w_lego_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(pos, [170,45], "sprites/640hud6.spr_0.tga", [0,0], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
|
||||
} else {
|
||||
drawsubpic(pos, [170,45], "sprites/640hud3.spr_0.tga", [0,0], [170/256,45/256], g_hud_color, a, DRAWFLAG_ADDITIVE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_lego =
|
||||
{
|
||||
.name = "lego",
|
||||
.id = ITEM_LEGO,
|
||||
.slot = 0,
|
||||
.slot_pos = 5,
|
||||
.draw = w_lego_draw,
|
||||
.holster = w_lego_holster,
|
||||
.primary = w_lego_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = w_lego_release,
|
||||
.crosshair = w_lego_hud,
|
||||
.precache = w_lego_precache,
|
||||
.pickup = w_lego_pickup,
|
||||
.updateammo = w_lego_updateammo,
|
||||
.wmodel = w_lego_wmodel,
|
||||
.pmodel = w_lego_pmodel,
|
||||
.deathmsg = w_lego_deathmsg,
|
||||
.aimanim = w_lego_aimanim,
|
||||
.hudpic = w_lego_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void weapon_lego(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_LEGO);
|
||||
/*item_pickup item = (item_pickup)self;
|
||||
item.SetRenderMode(RM_FULLBRIGHT);
|
||||
item.SetRenderAmt(1.0f);*/
|
||||
}
|
||||
#endif
|
299
src/shared/w_legolauncher.qc
Normal file
299
src/shared/w_legolauncher.qc
Normal file
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*QUAKED weapon_legolauncher (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/w_legolauncher.mdl"
|
||||
|
||||
Household DEATH! (2003) ENTITY
|
||||
|
||||
Lego Launcher Weapon
|
||||
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
LEGOLAUNCHER_IDLE,
|
||||
LEGOLAUNCHER_SHOOT,
|
||||
LEGOLAUNCHER_DRAW,
|
||||
LEGOLAUNCHER_HOLSTER
|
||||
};
|
||||
|
||||
void
|
||||
w_legolauncher_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_legolauncher.fire");
|
||||
Sound_Precache("weapon_legolauncher.hit");
|
||||
Sound_Precache("weapon_legolauncher.hitbody");
|
||||
#endif
|
||||
precache_model("models/lego.mdl");
|
||||
precache_model("models/v_legolauncher.mdl");
|
||||
precache_model("models/w_legolauncher.mdl");
|
||||
precache_model("models/p_legolauncher.mdl");
|
||||
}
|
||||
|
||||
void
|
||||
w_legolauncher_updateammo(player pl)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Weapons_UpdateAmmo(pl, __NULL__, pl.ammo_legos, __NULL__);
|
||||
#endif
|
||||
}
|
||||
|
||||
string
|
||||
w_legolauncher_wmodel(void)
|
||||
{
|
||||
return "models/w_legolauncher.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_legolauncher_pmodel(void)
|
||||
{
|
||||
return "models/p_legolauncher.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_legolauncher_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int
|
||||
w_legolauncher_pickup(int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.ammo_legos < MAX_A_LEGOS) {
|
||||
pl.ammo_legos = bound(0, pl.ammo_legos + 40, MAX_A_LEGOS);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
w_legolauncher_draw(void)
|
||||
{
|
||||
Weapons_SetModel("models/v_legolauncher.mdl");
|
||||
Weapons_ViewAnimation(LEGOLAUNCHER_DRAW);
|
||||
}
|
||||
|
||||
void
|
||||
w_legolauncher_holster(void)
|
||||
{
|
||||
Weapons_ViewAnimation(LEGOLAUNCHER_HOLSTER);
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
w_legolauncher_shootlego(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
static void Lego_Touch(void) {
|
||||
FX_LegoPiece(trace_endpos);
|
||||
|
||||
/* different effects/sounds for players and walls */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
} else {
|
||||
FX_Impact(IMPACT_DEFAULT, self.origin, trace_plane_normal);
|
||||
}
|
||||
|
||||
if (other.takedamage == DAMAGE_YES) {
|
||||
Damage_Apply(other, self.owner, 15, WEAPON_LEGOLAUNCHER, DMG_GENERIC);
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_legolauncher.hitbody");
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_legolauncher.hit");
|
||||
}
|
||||
remove(self);
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
entity lego = spawn();
|
||||
setmodel(lego, "models/lego.mdl");
|
||||
/* TODO needs to spawn more to the right */
|
||||
setorigin(lego, Weapons_GetCameraPos() + (v_forward * 16) + (v_right * 4) + (v_up * -8));
|
||||
lego.owner = self;
|
||||
lego.velocity = v_forward * 2000;
|
||||
lego.movetype = MOVETYPE_FLY;
|
||||
lego.solid = SOLID_BBOX;
|
||||
lego.angles = vectoangles(lego.velocity);
|
||||
lego.avelocity[2] = 10;
|
||||
lego.touch = Lego_Touch;
|
||||
setsize(lego, [0,0,0], [0,0,0]);
|
||||
|
||||
if (self.flags & FL_CROUCHING)
|
||||
Animation_PlayerTopTemp(ANIM_SHOOT1HAND, 0.45f);
|
||||
else
|
||||
Animation_PlayerTopTemp(ANIM_CR_SHOOT1HAND, 0.45f);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
w_legolauncher_primary(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ammo check */
|
||||
#ifdef CLIENT
|
||||
if (pl.a_ammo2 <= 0) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (pl.ammo_legos <= 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Actual firing */
|
||||
#ifdef SERVER
|
||||
w_legolauncher_shootlego();
|
||||
pl.ammo_legos--;
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_legolauncher.fire");
|
||||
#else
|
||||
Weapons_ViewPunchAngle([-2,0,0]);
|
||||
Weapons_ViewAnimation(LEGOLAUNCHER_SHOOT);
|
||||
#endif
|
||||
|
||||
pl.w_attack_next = 0.15f;
|
||||
pl.w_idle_next = 5.0f;
|
||||
}
|
||||
|
||||
void
|
||||
w_legolauncher_release(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_idle_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_ViewAnimation(LEGOLAUNCHER_IDLE);
|
||||
|
||||
pl.w_idle_next = 3.0f;
|
||||
}
|
||||
|
||||
void
|
||||
w_legolauncher_crosshair(void)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
vector aicon_pos;
|
||||
|
||||
static vector cross_pos;
|
||||
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
|
||||
drawsubpic(
|
||||
cross_pos,
|
||||
[24,24],
|
||||
"sprites/crosshairs.spr_0.tga",
|
||||
[72/128,48/128],
|
||||
[0.1875, 0.1875],
|
||||
[1,1,1],
|
||||
1,
|
||||
DRAWFLAG_NORMAL
|
||||
);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
aicon_pos = g_hudmins + [g_hudres[0] - 48, g_hudres[1] - 42];
|
||||
drawsubpic(
|
||||
aicon_pos,
|
||||
[52,20],
|
||||
"sprites/640_death.spr_0.tga",
|
||||
[0/128,100/128],
|
||||
[60/128,20/128],
|
||||
[1,1,1],
|
||||
pSeat->m_flAmmo2Alpha,
|
||||
0
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_legolauncher_aimanim(void)
|
||||
{
|
||||
return self.flags & FL_CROUCHING ? ANIM_CR_AIMBOW : ANIM_AIMBOW;
|
||||
}
|
||||
|
||||
void
|
||||
w_legolauncher_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/640hud5.spr_0.tga",
|
||||
[0,0],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/640hud2.spr_0.tga",
|
||||
[0,0],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_legolauncher =
|
||||
{
|
||||
.name = "legoblock",
|
||||
.id = ITEM_LEGOLAUNCHER,
|
||||
.slot = 0,
|
||||
.slot_pos = 7,
|
||||
.draw = w_legolauncher_draw,
|
||||
.holster = w_legolauncher_holster,
|
||||
.primary = w_legolauncher_primary,
|
||||
.secondary = __NULL__,
|
||||
.reload = __NULL__,
|
||||
.release = w_legolauncher_release,
|
||||
.crosshair = w_legolauncher_crosshair,
|
||||
.precache = w_legolauncher_precache,
|
||||
.pickup = w_legolauncher_pickup,
|
||||
.updateammo = w_legolauncher_updateammo,
|
||||
.wmodel = w_legolauncher_wmodel,
|
||||
.pmodel = w_legolauncher_pmodel,
|
||||
.deathmsg = w_legolauncher_deathmsg,
|
||||
.aimanim = w_legolauncher_aimanim,
|
||||
.hudpic = w_legolauncher_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_legolauncher(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_LEGOLAUNCHER);
|
||||
/*item_pickup item = (item_pickup)self;
|
||||
item.SetRenderMode(RM_FULLBRIGHT);
|
||||
item.SetRenderAmt(1.0f);*/
|
||||
}
|
||||
#endif
|
||||
|
298
src/shared/w_machette.qc
Normal file
298
src/shared/w_machette.qc
Normal file
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
|
||||
* Copyright (c) 2019-2020 Gethyn ThomasQuail <xylemon@posteo.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
MACHETTE_IDLE1,
|
||||
MACHETTE_IDLE2,
|
||||
MACHETTE_IDLE3,
|
||||
MACHETTE_THROW,
|
||||
MACHETTE_DRAW,
|
||||
MACHETTE_HOLSTER
|
||||
};
|
||||
|
||||
void
|
||||
w_machette_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_crowbar.hit");
|
||||
Sound_Precache("weapon_crowbar.miss");
|
||||
Sound_Precache("weapon_crowbar.hitbody");
|
||||
#endif
|
||||
precache_model("models/v_machette.mdl");
|
||||
precache_model("models/rune_stalker.mdl");
|
||||
precache_model("models/p_machette.mdl");
|
||||
}
|
||||
|
||||
void
|
||||
w_machette_updateammo(player pl)
|
||||
{
|
||||
w_broom_updateammo(pl);
|
||||
}
|
||||
|
||||
string
|
||||
w_machette_wmodel(void)
|
||||
{
|
||||
return "models/w_machette.mdl";
|
||||
}
|
||||
string
|
||||
w_machette_pmodel(void)
|
||||
{
|
||||
return "models/p_machette.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_machette_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
w_machette_pickup(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
/* Broadcast a message and sound upon picking up Rune */
|
||||
Sound_Play(self, CHAN_ITEM, "weapon_machette.pickup");
|
||||
env_message_single(self, "Activating Rune STALKER!");
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
w_machette_draw(void)
|
||||
{
|
||||
Weapons_SetModel("models/v_machette.mdl");
|
||||
Weapons_ViewAnimation(MACHETTE_DRAW);
|
||||
}
|
||||
|
||||
void
|
||||
w_machette_holster(void)
|
||||
{
|
||||
Weapons_ViewAnimation(MACHETTE_HOLSTER);
|
||||
}
|
||||
|
||||
void
|
||||
w_machette_primary(void)
|
||||
{
|
||||
int anim = 0;
|
||||
vector src;
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
src = pl.origin + pl.view_ofs;
|
||||
traceline(src, src + (v_forward * 32), FALSE, pl);
|
||||
|
||||
|
||||
pl.w_attack_next = 0.4f;
|
||||
pl.w_idle_next = 2.5f;
|
||||
|
||||
Weapons_ViewAnimation(MACHETTE_THROW);
|
||||
|
||||
#ifdef SERVER
|
||||
if (pl.flags & FL_CROUCHING) {
|
||||
Animation_PlayerTopTemp(ANIM_SHOOTCROWBAR, 0.5f);
|
||||
} else {
|
||||
Animation_PlayerTopTemp(ANIM_CR_SHOOTCROWBAR, 0.42f);
|
||||
}
|
||||
|
||||
if (trace_fraction >= 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* don't bother with decals, we got squibs */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
} else {
|
||||
FX_Impact(IMPACT_MELEE, trace_endpos, trace_plane_normal);
|
||||
}
|
||||
|
||||
if (trace_ent.takedamage) {
|
||||
Damage_Apply(trace_ent, pl, 5, WEAPON_MACHETTE, DMG_BLUNT);
|
||||
if (trace_ent.iBleeds) {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_machette.hitbody");
|
||||
}
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_machette.hit");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
w_machette_throw(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
static void Machette_Touch(void) {
|
||||
setmodel(self, "models/machette.mdl");
|
||||
|
||||
/* squibs */
|
||||
if (trace_ent.iBleeds) {
|
||||
FX_Blood(trace_endpos, [1,0,0]);
|
||||
remove(self);
|
||||
} else {
|
||||
FX_Impact(IMPACT_DEFAULT, trace_endpos, trace_plane_normal);
|
||||
}
|
||||
|
||||
if (other.takedamage == DAMAGE_YES) {
|
||||
Damage_Apply(other, self.owner, 15, WEAPON_MACHETTE, DMG_GENERIC);
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_machette.hitbody");
|
||||
} else {
|
||||
Sound_Play(self, CHAN_WEAPON, "weapon_machette.stick");
|
||||
}
|
||||
self.movetype = MOVETYPE_NONE;
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
entity machette = spawn();
|
||||
setmodel(machette, "models/machette.mdl");
|
||||
setorigin(machette, Weapons_GetCameraPos() + (v_forward * 16));
|
||||
machette.owner = self;
|
||||
machette.velocity = v_forward * 2000;
|
||||
machette.movetype = MOVETYPE_FLY;
|
||||
machette.solid = SOLID_BBOX;
|
||||
machette.angles = vectoangles(machette.velocity);
|
||||
machette.avelocity[2] = 10;
|
||||
machette.touch = Machette_Touch;
|
||||
setsize(machette, [0,0,0], [0,0,0]);
|
||||
|
||||
if (self.flags & FL_CROUCHING)
|
||||
Animation_PlayerTopTemp(ANIM_SHOOT1HAND, 0.45f);
|
||||
else
|
||||
Animation_PlayerTopTemp(ANIM_CR_SHOOT1HAND, 0.45f);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
w_machette_secondary(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Actual firing */
|
||||
#ifdef SERVER
|
||||
w_machette_throw();
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_machette.throw");
|
||||
#else
|
||||
Weapons_ViewPunchAngle([-2,0,0]);
|
||||
Weapons_ViewAnimation(MACHETTE_THROW);
|
||||
#endif
|
||||
|
||||
pl.w_attack_next = 0.5f;
|
||||
pl.w_idle_next = 5.0f;
|
||||
}
|
||||
|
||||
void
|
||||
w_machette_release(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_idle_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int r;
|
||||
r = (float)input_sequence % 3;
|
||||
switch (r) {
|
||||
case 1:
|
||||
Weapons_ViewAnimation(MACHETTE_IDLE1);
|
||||
pl.w_idle_next = 1.3f;
|
||||
break;
|
||||
case 2:
|
||||
Weapons_ViewAnimation(MACHETTE_IDLE2);
|
||||
pl.w_idle_next = 3.0f;
|
||||
break;
|
||||
default:
|
||||
Weapons_ViewAnimation(MACHETTE_IDLE3);
|
||||
pl.w_idle_next = 1.285f;
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
w_machette_aimanim(void)
|
||||
{
|
||||
return w_broom_aimanim();
|
||||
}
|
||||
|
||||
void
|
||||
w_machette_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud04.spr_0.tga",
|
||||
[0,135/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/tfchud03.spr_0.tga",
|
||||
[0,90/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_machette =
|
||||
{
|
||||
.name = "machette",
|
||||
.id = ITEM_MACHETTE,
|
||||
.slot = 1,
|
||||
.slot_pos = 1,
|
||||
.draw = w_machette_draw,
|
||||
.holster = w_machette_holster,
|
||||
.primary = w_machette_primary,
|
||||
.secondary = w_machette_secondary,
|
||||
.reload = __NULL__,
|
||||
.release = w_machette_release,
|
||||
.crosshair = __NULL__,
|
||||
.precache = w_machette_precache,
|
||||
.pickup = w_machette_pickup,
|
||||
.updateammo = w_machette_updateammo,
|
||||
.wmodel = w_machette_wmodel,
|
||||
.pmodel = w_machette_pmodel,
|
||||
.deathmsg = w_machette_deathmsg,
|
||||
.aimanim = w_machette_aimanim,
|
||||
.hudpic = w_machette_hudpic
|
||||
};
|
||||
|
||||
/* entity definitions for pickups */
|
||||
#ifdef SERVER
|
||||
void
|
||||
rune_stalker(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_MACHETTE);
|
||||
}
|
||||
#endif
|
357
src/shared/w_sodalauncher.qc
Normal file
357
src/shared/w_sodalauncher.qc
Normal file
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*QUAKED weapon_sodalauncher (0 0 1) (-16 -16 0) (16 16 32)
|
||||
"model" "models/w_soda.mdl"
|
||||
|
||||
HALF-LIFE (1998) ENTITY
|
||||
|
||||
MP5/9mmAR Weapon
|
||||
Same as weapon_9mmAR
|
||||
|
||||
*/
|
||||
|
||||
/* Animations */
|
||||
enum
|
||||
{
|
||||
SODA_IDLE,
|
||||
SODA_IDLE_NOSODA,
|
||||
SODA_SHOOT_RELOAD,
|
||||
SODA_SHOOT,
|
||||
SODA_DRAW,
|
||||
SODA_DRAW_NOSODA,
|
||||
SODA_HOLSTER,
|
||||
SODA_HOLSTER_NOSODA
|
||||
};
|
||||
|
||||
void
|
||||
w_sodalauncher_precache(void)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Sound_Precache("weapon_sodalauncher.fire");
|
||||
Sound_Precache("weapon_sodalauncher.explode");
|
||||
#endif
|
||||
precache_model("sprites/hud_sodacan.spr");
|
||||
precache_model("models/v_soda.mdl");
|
||||
precache_model("models/w_soda.mdl");
|
||||
precache_model("models/p_soda.mdl");
|
||||
precache_model("models/sodacan.mdl");
|
||||
}
|
||||
|
||||
int
|
||||
w_sodalauncher_pickup(int new, int startammo)
|
||||
{
|
||||
#ifdef SERVER
|
||||
player pl = (player)self;
|
||||
if (pl.ammo_soda < MAX_A_SODA) {
|
||||
pl.ammo_soda = bound(0, pl.ammo_soda + 3, MAX_A_SODA);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
w_sodalauncher_updateammo(player pl)
|
||||
{
|
||||
#ifdef SERVER
|
||||
Weapons_UpdateAmmo(pl, __NULL__, pl.ammo_soda, __NULL__);
|
||||
#endif
|
||||
}
|
||||
|
||||
string
|
||||
w_sodalauncher_wmodel(void)
|
||||
{
|
||||
return "models/w_soda.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_sodalauncher_pmodel(void)
|
||||
{
|
||||
return "models/p_soda.mdl";
|
||||
}
|
||||
|
||||
string
|
||||
w_sodalauncher_deathmsg(void)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void
|
||||
w_sodalauncher_draw(void)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
Weapons_SetModel("models/v_soda.mdl");
|
||||
Weapons_ViewAnimation(SODA_DRAW);
|
||||
/* needs the skin value to be set, no API yet
|
||||
* the soda cans in the viewmodel sync up with
|
||||
* the projectile and spill decals */
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
w_sodalauncher_holster(void)
|
||||
{
|
||||
Weapons_ViewAnimation(SODA_HOLSTER);
|
||||
}
|
||||
|
||||
/* TODO now just need parameters */
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
w_sodalauncher_shoot(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
/* Apply force */
|
||||
if (pl.flags & FL_ONGROUND) {
|
||||
pl.velocity += v_forward * -100;
|
||||
} else {
|
||||
pl.velocity += v_forward * -300;
|
||||
}
|
||||
|
||||
static void Soda_ExplodeTouch(void) {
|
||||
float dmg = Skill_GetValue("plr_9mmAR_grenade", 150);
|
||||
FX_Soda(trace_endpos, self.skin);
|
||||
Damage_Radius(self.origin, self.owner, dmg, dmg * 2.5f, TRUE, WEAPON_SODALAUNCHER);
|
||||
Sound_Play(self, 1, "weapon_sodalauncher.explode");
|
||||
remove(self);
|
||||
}
|
||||
|
||||
Weapons_MakeVectors();
|
||||
entity soda = spawn();
|
||||
setmodel(soda, "models/sodacan.mdl");
|
||||
setorigin(soda, Weapons_GetCameraPos() + (v_forward * 16));
|
||||
soda.skin = floor(random(0,6));
|
||||
soda.owner = self;
|
||||
soda.velocity = v_forward * 800;
|
||||
soda.angles = vectoangles(soda.velocity);
|
||||
soda.avelocity[0] = random(-100, -500);
|
||||
soda.gravity = 0.5f;
|
||||
soda.movetype = MOVETYPE_BOUNCE;
|
||||
//soda.flags |= FL_LAGGEDMOVE;
|
||||
soda.solid = SOLID_BBOX;
|
||||
setsize(soda, [0,0,0], [0,0,0]);
|
||||
soda.touch = Soda_ExplodeTouch;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* TODO make server side
|
||||
* Sprite code in Nuclide is still WIP
|
||||
* so this is client-only for now */
|
||||
void
|
||||
w_sodalauncher_exhaust(void) {
|
||||
env_sprite eExhaust = spawn(env_sprite);
|
||||
setorigin(eExhaust, Weapons_GetCameraPos() + (v_forward * 16));
|
||||
setmodel(eExhaust, "sprites/co2_puff.spr");
|
||||
|
||||
eExhaust.effects = EF_ADDITIVE;
|
||||
eExhaust.drawmask = MASK_ENGINE;
|
||||
eExhaust.maxframe = modelframecount(eExhaust.modelindex);
|
||||
eExhaust.loops = 0;
|
||||
eExhaust.scale = 0.5f;
|
||||
eExhaust.framerate = 20;
|
||||
eExhaust.nextthink = time + 0.05f;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
w_sodalauncher_primary(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ammo check */
|
||||
#ifdef CLIENT
|
||||
if (pl.a_ammo2 <= 0) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (pl.ammo_soda <= 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Actual firing
|
||||
* TODO make this one fast straight */
|
||||
#ifdef CLIENT
|
||||
Weapons_ViewPunchAngle([-10,0,0]);
|
||||
Weapons_ViewAnimation(SODA_SHOOT_RELOAD);
|
||||
w_sodalauncher_exhaust();
|
||||
#else
|
||||
w_sodalauncher_shoot();
|
||||
pl.ammo_soda--;
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_sodalauncher.fire");
|
||||
#endif
|
||||
|
||||
pl.w_attack_next = 1.0f;
|
||||
pl.w_idle_next = 10.0f;
|
||||
}
|
||||
/* TODO Actual secondary fire is the current primary fire code, just WIP */
|
||||
void
|
||||
w_sodalauncher_secondary(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_attack_next > 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ammo check */
|
||||
#ifdef CLIENT
|
||||
if (pl.a_ammo2 <= 0) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (pl.ammo_soda <= 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TODO make this one sag and slower */
|
||||
#ifdef CLIENT
|
||||
Weapons_ViewPunchAngle([-10,0,0]);
|
||||
Weapons_ViewAnimation(SODA_SHOOT_RELOAD);
|
||||
w_sodalauncher_exhaust();
|
||||
#else
|
||||
w_sodalauncher_shoot();
|
||||
pl.ammo_soda--;
|
||||
Sound_Play(pl, CHAN_WEAPON, "weapon_sodalauncher.fire");
|
||||
#endif
|
||||
|
||||
pl.w_attack_next = 1.0f;
|
||||
pl.w_idle_next = 10.0f;
|
||||
}
|
||||
|
||||
void
|
||||
w_sodalauncher_release(void)
|
||||
{
|
||||
player pl = (player)self;
|
||||
|
||||
if (pl.w_idle_next) {
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons_ViewAnimation(SODA_IDLE);
|
||||
pl.w_idle_next = 3.0f;
|
||||
}
|
||||
|
||||
void
|
||||
w_sodalauncher_crosshair(void)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
static vector cross_pos;
|
||||
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
|
||||
drawsubpic(
|
||||
cross_pos,
|
||||
[24,24],
|
||||
"sprites/crosshairs.spr_0.tga",
|
||||
[72/128,48/128],
|
||||
[0.1875, 0.1875],
|
||||
[1,1,1],
|
||||
1,
|
||||
DRAWFLAG_NORMAL
|
||||
);
|
||||
|
||||
HUD_DrawAmmo2();
|
||||
|
||||
vector aicon_pos = g_hudmins + [g_hudres[0] - 42, g_hudres[1] - 64];
|
||||
drawpic(
|
||||
aicon_pos,
|
||||
"sprites/hud_sodacan.spr_0.tga",
|
||||
[32,64],
|
||||
[1,1,1],
|
||||
pSeat->m_flAmmo2Alpha,
|
||||
0
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
float
|
||||
w_sodalauncher_aimanim(void)
|
||||
{
|
||||
return self.flags & FL_CROUCHING ? ANIM_CR_AIMBOW : ANIM_AIMBOW;
|
||||
}
|
||||
|
||||
void
|
||||
w_sodalauncher_hudpic(int selected, vector pos, float a)
|
||||
{
|
||||
#ifdef CLIENT
|
||||
if (selected) {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/640hud4.spr_0.tga",
|
||||
[0,135/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
} else {
|
||||
drawsubpic(
|
||||
pos,
|
||||
[170,45],
|
||||
"sprites/640hud1.spr_0.tga",
|
||||
[0,135/256],
|
||||
[170/256,45/256],
|
||||
g_hud_color,
|
||||
a,
|
||||
DRAWFLAG_ADDITIVE
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
weapon_t w_sodalauncher = {
|
||||
.name = "sodacan",
|
||||
.id = ITEM_SODALAUNCHER,
|
||||
.slot = 0,
|
||||
.slot_pos = 4,
|
||||
.draw = w_sodalauncher_draw,
|
||||
.holster = w_sodalauncher_holster,
|
||||
.primary = w_sodalauncher_primary,
|
||||
.secondary = w_sodalauncher_secondary,
|
||||
.reload = __NULL__,
|
||||
.release = w_sodalauncher_release,
|
||||
.crosshair = w_sodalauncher_crosshair,
|
||||
.precache = w_sodalauncher_precache,
|
||||
.pickup = w_sodalauncher_pickup,
|
||||
.updateammo = w_sodalauncher_updateammo,
|
||||
.wmodel = w_sodalauncher_wmodel,
|
||||
.pmodel = w_sodalauncher_pmodel,
|
||||
.deathmsg = w_sodalauncher_deathmsg,
|
||||
.aimanim = w_sodalauncher_aimanim,
|
||||
.hudpic = w_sodalauncher_hudpic
|
||||
};
|
||||
|
||||
#ifdef SERVER
|
||||
void
|
||||
weapon_sodalauncher(void)
|
||||
{
|
||||
Weapons_InitItem(WEAPON_SODALAUNCHER);
|
||||
/*item_pickup item = (item_pickup)self;
|
||||
item.SetRenderMode(RM_FULLBRIGHT);
|
||||
item.SetRenderAmt(1.0f);
|
||||
item.SetFloating(TRUE);*/
|
||||
}
|
||||
#endif
|
39
src/shared/weapons.h
Normal file
39
src/shared/weapons.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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_BROOM,
|
||||
WEAPON_FRYINGPAN,
|
||||
WEAPON_FORKS,
|
||||
WEAPON_KNIFE,
|
||||
WEAPON_SODALAUNCHER,
|
||||
WEAPON_LEGO,
|
||||
WEAPON_HAIRSPRAY,
|
||||
WEAPON_LEGOLAUNCHER,
|
||||
WEAPON_GLOVE,
|
||||
WEAPON_MACHETTE
|
||||
};
|
||||
|
||||
|
||||
#define MAX_A_FORKS 25
|
||||
#define MAX_A_KNIVES 15
|
||||
#define MAX_A_LEGOGRENADE 3
|
||||
#define MAX_A_LEGOS 200
|
||||
#define MAX_A_SODA 24
|
||||
#define MAX_A_SPRAY 100
|
30
src/shared/weapons.qc
Normal file
30
src/shared/weapons.qc
Normal 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_t w_null = {};
|
||||
weapon_t g_weapons[] = {
|
||||
w_null,
|
||||
w_broom,
|
||||
w_fryingpan,
|
||||
w_forks,
|
||||
w_knife,
|
||||
w_sodalauncher,
|
||||
w_lego,
|
||||
w_hairspray,
|
||||
w_legolauncher,
|
||||
w_glove,
|
||||
w_machette
|
||||
};
|
29
zpak_sound.pk3dir/sound/items_hhdeath.sndshd
Normal file
29
zpak_sound.pk3dir/sound/items_hhdeath.sndshd
Normal file
|
@ -0,0 +1,29 @@
|
|||
ammo.pickup
|
||||
{
|
||||
sample items/pickup.wav
|
||||
}
|
||||
|
||||
ammo.respawn
|
||||
{
|
||||
sample items/respawn.wav
|
||||
}
|
||||
|
||||
item.armor
|
||||
{
|
||||
sample items/pickup_armor.wav
|
||||
}
|
||||
|
||||
item.health
|
||||
{
|
||||
sample items/takehealth.wav
|
||||
}
|
||||
|
||||
item.respawn
|
||||
{
|
||||
sample items/respawn.wav
|
||||
}
|
||||
|
||||
weapon.pickup
|
||||
{
|
||||
sample items/pickup.wav
|
||||
}
|
9
zpak_sound.pk3dir/sound/players_hhdeath.sndshd
Normal file
9
zpak_sound.pk3dir/sound/players_hhdeath.sndshd
Normal file
|
@ -0,0 +1,9 @@
|
|||
player.die
|
||||
{
|
||||
sample player/killed.wav
|
||||
}
|
||||
|
||||
player.fallarmor
|
||||
{
|
||||
sample player/fall_armor.wav
|
||||
}
|
145
zpak_sound.pk3dir/sound/weapons_hhdeath.sndshd
Normal file
145
zpak_sound.pk3dir/sound/weapons_hhdeath.sndshd
Normal file
|
@ -0,0 +1,145 @@
|
|||
weapon_broom.hit
|
||||
{
|
||||
sample weapons/broom_hit1.wav
|
||||
sample weapons/broom_hit2.wav
|
||||
}
|
||||
|
||||
weapon_broom.hitbody
|
||||
{
|
||||
sample weapons/broom_hitbod1.wav
|
||||
sample weapons/broom_hitbod2.wav
|
||||
sample weapons/broom_hitbod3.wav
|
||||
}
|
||||
|
||||
weapon_broom.miss
|
||||
{
|
||||
sample weapons/broom_swing1.wav
|
||||
sample weapons/broom_swing2.wav
|
||||
}
|
||||
|
||||
weapon_forks.hitbody
|
||||
{
|
||||
sample weapons/fork_stick_body.wav
|
||||
}
|
||||
|
||||
weapon_forks.hit
|
||||
{
|
||||
sample weapons/fork_hit_wall.wav
|
||||
}
|
||||
|
||||
weapon_forks.stick
|
||||
{
|
||||
sample weapons/fork_stick.wav
|
||||
}
|
||||
|
||||
weapon_forks.throw
|
||||
{
|
||||
sample weapons/fork_throw.wav
|
||||
}
|
||||
|
||||
weapon_fryingpan.hit
|
||||
{
|
||||
sample weapons/pan_hitwall1.wav
|
||||
}
|
||||
|
||||
weapon_fryingpan.hitbody
|
||||
{
|
||||
sample weapons/pan_hitbody1.wav
|
||||
sample weapons/pan_hitbody2.wav
|
||||
}
|
||||
|
||||
weapon_fryingpan.miss
|
||||
{
|
||||
sample weapons/pan_swing1.wav
|
||||
sample weapons/pan_swing2.wav
|
||||
}
|
||||
|
||||
|
||||
weapon_glove.hitbody
|
||||
{
|
||||
sample weapon/glove_hitbod1.wav
|
||||
sample weapon/glove_hitbod2.wav
|
||||
sample weapon/glove_hitbod3.wav
|
||||
}
|
||||
|
||||
weapon_glove.hit
|
||||
{
|
||||
sample weapon/glove_hit1.wav
|
||||
sample weapon/glove_hit2.wav
|
||||
}
|
||||
|
||||
weapon_glove.miss
|
||||
{
|
||||
sample weapons/glove_swing1.wav
|
||||
sample weapons/glove_swing2.wav
|
||||
}
|
||||
|
||||
weapon_glove.pickup
|
||||
{
|
||||
sample runes/on_slasher.wav
|
||||
}
|
||||
|
||||
|
||||
weapon_hairspray.fire
|
||||
{
|
||||
sample weapons/hspray_loop.wav
|
||||
}
|
||||
|
||||
weapon_knife.hitbody
|
||||
{
|
||||
sample weapons/knife_stick_wall.wav
|
||||
}
|
||||
|
||||
/* should have looping flag but can't due to engine bug */
|
||||
weapon_knife.move
|
||||
{
|
||||
follow
|
||||
sample weapons/knife_move.wav
|
||||
}
|
||||
|
||||
weapon_knife.stick
|
||||
{
|
||||
sample weapons/knife_stick_wall.wav
|
||||
}
|
||||
|
||||
weapon_knife.throw
|
||||
{
|
||||
sample weapons/knife_throw1.wav
|
||||
sample weapons/knife_throw2.wav
|
||||
}
|
||||
|
||||
weapon_lego.explode
|
||||
{
|
||||
sample gibs/lego_explode1.wav
|
||||
sample gibs/lego_explode2.wav
|
||||
}
|
||||
|
||||
weapon_legolauncher.fire
|
||||
{
|
||||
sample weapons/launch_lego.wav
|
||||
}
|
||||
|
||||
weapon_legolauncher.hitbody
|
||||
{
|
||||
sample weapons/launch_lego.wav
|
||||
}
|
||||
|
||||
weapon_legolauncher.hit
|
||||
{
|
||||
sample gibs/lego_bounce1.wav
|
||||
sample gibs/lego_bounce2.wav
|
||||
sample gibs/lego_bounce3.wav
|
||||
sample gibs/lego_bounce4.wav
|
||||
sample gibs/lego_bounce5.wav
|
||||
sample gibs/lego_bounce6.wav
|
||||
}
|
||||
|
||||
weapon_sodalauncher.explode
|
||||
{
|
||||
sample weapons/soda_spill.wav
|
||||
}
|
||||
|
||||
weapon_sodalauncher.fire
|
||||
{
|
||||
sample weapons/launch_soda.wav
|
||||
}
|
Loading…
Reference in a new issue