Compare commits

...

7 commits

52 changed files with 1700 additions and 661 deletions

1
PROJECT Normal file
View file

@ -0,0 +1 @@
ScientistHunt

View file

@ -3,3 +3,4 @@ CC=fteqcc
all: all:
cd client && $(MAKE) cd client && $(MAKE)
cd server && $(MAKE) cd server && $(MAKE)
cd rules && $(MAKE)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org> * Copyright (c) 2016-2024 Marco Cawthorne <marco@icculus.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -19,7 +19,6 @@ void VGUI_ChooseTeam(void);
int int
ClientGame_ConsoleCommand(void) ClientGame_ConsoleCommand(void)
{ {
switch(argv(0)) { switch(argv(0)) {
case "+sciscore": case "+sciscore":
if (cvar("sh_announcescinum") == 1) if (cvar("sh_announcescinum") == 1)
@ -36,15 +35,18 @@ ClientGame_ConsoleCommand(void)
default: default:
return (0); return (0);
} }
return (1); return (1);
} }
void void
CMD_ChooseTeam(void) CMD_ChooseTeam(void)
{ {
if (serverkeyfloat("sv_playerslots") <= 1) if (serverkeyfloat("sv_playerslots") <= 1) {
return; return;
}
if (serverkeyfloat("teams") > 1) if (serverkeyfloat("teams") > 1) {
VGUI_ChooseTeam(); VGUI_ChooseTeam();
} }
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org> * Copyright (c) 2016-2024 Marco Cawthorne <marco@icculus.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -14,9 +14,11 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "../../../valve/src/shared/defs.h"
#include "../../../valve/src/client/obituary.h" #include "../../../valve/src/client/obituary.h"
#include "../../../valve/src/client/particles.h" #include "../../../valve/src/client/particles.h"
#include "../../../valve/src/client/hud_sprite.h" #include "../../../valve/src/client/hud_sprite.h"
#include "../../../valve/src/client/HLWeaponSelect.h"
var int autocvar_cl_autoweaponswitch = TRUE; var int autocvar_cl_autoweaponswitch = TRUE;
@ -61,6 +63,7 @@ struct
int m_iItemsOld; int m_iItemsOld;
float m_flDamageIndicator; float m_flDamageIndicator;
HLWeaponSelect weaponSelectionHUD;
} g_seatslocal[4], *pSeatLocal; } g_seatslocal[4], *pSeatLocal;
void HUD_DrawAmmo1(void); void HUD_DrawAmmo1(void);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2022 Vera Visions LLC. * Copyright (c) 2016-2024 Marco Cawthorne <marco@icculus.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -29,28 +29,28 @@ SH_DrawSciScore(void)
vector pos; vector pos;
line = "^xFA0Scientist round score info:"; line = "^xFA0Scientist round score info:";
pos = (video_res / 2); pos = (g_vidsize / 2);
pos[0] -= (Font_StringWidth(line, FALSE, FONT_CON) / 2); pos[0] -= (Font_StringWidth(line, FALSE, FONT_CON) / 2);
pos[1] -= 64; pos[1] -= 64;
Font_DrawText(pos, line, FONT_CON); Font_DrawText(pos, line, FONT_CON);
line = sprintf("^xFA0Team Red: %d kills", serverkeyfloat("teamkills_1")); line = sprintf("^xFA0Team Red: %d kills", serverkeyfloat("teamkills_1"));
pos = (video_res / 2); pos = (g_vidsize / 2);
pos[0] -= (Font_StringWidth(line, FALSE, FONT_CON) / 2); pos[0] -= (Font_StringWidth(line, FALSE, FONT_CON) / 2);
pos[1] -= 36; pos[1] -= 36;
Font_DrawText(pos, line, FONT_CON); Font_DrawText(pos, line, FONT_CON);
line = sprintf("^xFA0Team Blue: %d kills", serverkeyfloat("teamkills_2")); line = sprintf("^xFA0Team Blue: %d kills", serverkeyfloat("teamkills_2"));
pos = (video_res / 2); pos = (g_vidsize / 2);
pos[0] -= (Font_StringWidth(line, FALSE, FONT_CON) / 2); pos[0] -= (Font_StringWidth(line, FALSE, FONT_CON) / 2);
pos[1] -= 24; pos[1] -= 24;
Font_DrawText(pos, line, FONT_CON); Font_DrawText(pos, line, FONT_CON);
line = sprintf("^xFA0Scientists left: %d", serverkeyfloat("sci_count")); line = sprintf("^xFA0Scientists left: %d", serverkeyfloat("sci_count"));
pos = (video_res / 2); pos = (g_vidsize / 2);
pos[0] -= (Font_StringWidth(line, FALSE, FONT_CON) / 2); pos[0] -= (Font_StringWidth(line, FALSE, FONT_CON) / 2);
Font_DrawText(pos, line, FONT_CON); Font_DrawText(pos, line, FONT_CON);
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org> * Copyright (c) 2016-2024 Marco Cawthorne <marco@icculus.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above

View file

@ -148,7 +148,7 @@ void
HUD_DrawHealth(void) HUD_DrawHealth(void)
{ {
vector pos; vector pos;
NSClientPlayer pl = (NSClientPlayer)pSeat->m_ePlayer; ncPlayer pl = (ncPlayer)pSeat->m_ePlayer;
if (pl.health != pSeatLocal->m_iHealthOld) { if (pl.health != pSeatLocal->m_iHealthOld) {
pSeatLocal->m_flHealthAlpha = 1.0; pSeatLocal->m_flHealthAlpha = 1.0;
@ -309,8 +309,9 @@ HUD_DrawAmmo3(void)
void void
HUD_DrawAmmoBar(vector pos, float val, float max, float a) HUD_DrawAmmoBar(vector pos, float val, float max, float a)
{ {
if (val <= 0) if (val <= 0) {
return; return;
}
float perc; float perc;
perc = val / max; perc = val / max;
@ -390,6 +391,7 @@ HUD_DrawLogo(void)
frame_timer = 0.1f; frame_timer = 0.1f;
f++; f++;
if (f == 31) { if (f == 31) {
f = 0; f = 0;
} }
@ -447,8 +449,9 @@ HUD_DrawDamageIndicator(void)
{ {
vector cross_pos; vector cross_pos;
if (pSeatLocal->m_flDamageIndicator <= 0.0) if (pSeatLocal->m_flDamageIndicator <= 0.0) {
return; return;
}
cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12]; cross_pos = g_hudmins + (g_hudres / 2) + [-12,-12];
@ -478,7 +481,7 @@ HUD_DrawInsanityIcon(void)
insanityalpha = bound(0,pl.sh_insaneactive * 0.05f,0.4); insanityalpha = bound(0,pl.sh_insaneactive * 0.05f,0.4);
drawfill( drawfill(
video_mins, video_mins,
video_res, g_vidsize,
[1,0,0], [1,0,0],
insanityalpha, insanityalpha,
DRAWFLAG_ADDITIVE DRAWFLAG_ADDITIVE
@ -568,8 +571,9 @@ HUD_Draw(void)
#endif #endif
/* little point in not drawing these, even if you don't have a suit */ /* little point in not drawing these, even if you don't have a suit */
if (pl.m_activeWeapon) if (pl.m_activeWeapon) {
pl.m_activeWeapon.UpdateGUI(); pl.m_activeWeapon.UpdateGUI();
}
HUD_DrawDamageIndicator(); HUD_DrawDamageIndicator();
HUD_DrawWeaponSelect(); HUD_DrawWeaponSelect();
@ -596,7 +600,7 @@ HUD_DrawSpectator(void)
{ {
Textmenu_Draw(); Textmenu_Draw();
NSClientSpectator spec = (NSClientSpectator)pSeat->m_ePlayer; ncSpectator spec = (ncSpectator)pSeat->m_ePlayer;
drawfont = Font_GetID(FONT_20); drawfont = Font_GetID(FONT_20);
vector vecPos = [0.0f, 0.0f, 0.0f]; vector vecPos = [0.0f, 0.0f, 0.0f];

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2021 Marco Cawthorne <marco@icculus.org> * Copyright (c) 2016-2024 Marco Cawthorne <marco@icculus.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -28,6 +28,8 @@ ClientGame_Init(float apilevel, string enginename, float engineversion)
registercommand("+sciscore"); registercommand("+sciscore");
registercommand("-sciscore"); registercommand("-sciscore");
registercommand("chooseteam"); registercommand("chooseteam");
pSeatLocal->weaponSelectionHUD = spawn(HLWeaponSelect);
} }
void VGUI_ShowMOTD(void); void VGUI_ShowMOTD(void);

View file

@ -1,6 +1,7 @@
#pragma target fte_5768 #pragma target fte_5768
//#pragma flag enable assumeint //#pragma flag enable assumeint
#pragma progs_dat "../../csprogs.dat" #pragma progs_dat "../../csprogs.dat"
#pragma forcecrc 54730
#define CSQC #define CSQC
#define CLIENT #define CLIENT
@ -26,6 +27,7 @@ init.qc
../../../valve/src/client/flashlight.qc ../../../valve/src/client/flashlight.qc
entities.qc entities.qc
cmds.qc cmds.qc
../../../valve/src/client/HLWeaponSelect.qc
../../../valve/src/client/game_event.qc ../../../valve/src/client/game_event.qc
../../../valve/src/client/camera.qc ../../../valve/src/client/camera.qc
../../../valve/src/client/viewmodel.qc ../../../valve/src/client/viewmodel.qc

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org> * Copyright (c) 2016-2024 Marco Cawthorne <marco@icculus.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -14,9 +14,9 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
static VGUIWindow winChooseTeam; static vguiWindow winChooseTeam;
class TeamButton:VGUIButton class TeamButton:vguiButton
{ {
void TeamButton(void); void TeamButton(void);
@ -32,7 +32,6 @@ void
TeamButton::OnMouseUp(void) TeamButton::OnMouseUp(void)
{ {
int tag = GetTag(); int tag = GetTag();
localcmd("changeclass\n"); localcmd("changeclass\n");
sendevent("TeamJoin", "f", (float)tag); sendevent("TeamJoin", "f", (float)tag);
winChooseTeam.Hide(); winChooseTeam.Hide();
@ -44,8 +43,9 @@ VGUI_ChooseTeam_MapInfo(void)
{ {
static string mapinfo = __NULL__; static string mapinfo = __NULL__;
if (mapinfo != __NULL__) if (mapinfo != __NULL__) {
return mapinfo; return mapinfo;
}
filestream fileMap = fopen(strcat("maps/", mapname, ".txt"), FILE_READ); filestream fileMap = fopen(strcat("maps/", mapname, ".txt"), FILE_READ);
string temp; string temp;
@ -65,14 +65,14 @@ void
VGUI_ChooseTeam(void) VGUI_ChooseTeam(void)
{ {
static int initialized; static int initialized;
static VGUIButton btnTeamBlue; static vguiButton btnTeamBlue;
static VGUIButton btnTeamRed; static vguiButton btnTeamRed;
static VGUIButton btnAutoAssign; static vguiButton btnAutoAssign;
static VGUIButton btnGoSpectator; static vguiButton btnGoSpectator;
static VGUIFrame frmMapInfo; static vguiFrame frmMapInfo;
static VGUILabel lblSelectTeam; static vguiLabel lblSelectTeam;
static VGUILabel lblMapName; static vguiLabel lblMapName;
static VGUILabel lblMapInfo; static vguiLabel lblMapInfo;
static void VGUI_AutoAssign(void) { static void VGUI_AutoAssign(void) {
sendevent("JoinAuto", ""); sendevent("JoinAuto", "");
@ -99,32 +99,32 @@ VGUI_ChooseTeam(void)
vector btnpos = [40,80]; vector btnpos = [40,80];
initialized = TRUE; initialized = TRUE;
winChooseTeam = spawn(VGUIWindow); winChooseTeam = spawn(vguiWindow);
winChooseTeam.SetSize('640 480'); winChooseTeam.SetSize('640 480');
winChooseTeam.SetStyleMask(VGUIWindowBorderless | VGUIWindowFullscreen); winChooseTeam.SetStyleMask(vguiWindowBorderless | vguiWindowFullscreen);
lblSelectTeam = spawn(VGUILabel); lblSelectTeam = spawn(vguiLabel);
lblSelectTeam.SetTitle("SELECT YOUR TEAM"); lblSelectTeam.SetTitle("SELECT YOUR TEAM");
lblSelectTeam.SetTextSize(19); lblSelectTeam.SetTextSize(19);
lblSelectTeam.SetPos([40, 38]); lblSelectTeam.SetPos([40, 38]);
lblSelectTeam.SetSize('400 24'); lblSelectTeam.SetSize('400 24');
frmMapInfo = spawn(VGUIFrame); frmMapInfo = spawn(vguiFrame);
frmMapInfo.SetPos('176 80'); frmMapInfo.SetPos('176 80');
frmMapInfo.SetSize('424 312'); frmMapInfo.SetSize('424 312');
lblMapName = spawn(VGUILabel); lblMapName = spawn(vguiLabel);
lblMapName.SetTitle(mapname); lblMapName.SetTitle(mapname);
lblMapName.SetTextSize(19); lblMapName.SetTextSize(19);
lblMapName.SetPos('194 105'); lblMapName.SetPos('194 105');
lblMapName.SetSize('250 312'); lblMapName.SetSize('250 312');
lblMapInfo = spawn(VGUILabel); lblMapInfo = spawn(vguiLabel);
lblMapInfo.SetTitle(VGUI_ChooseTeam_MapInfo()); lblMapInfo.SetTitle(VGUI_ChooseTeam_MapInfo());
lblMapInfo.SetPos('194 129'); lblMapInfo.SetPos('194 129');
lblMapInfo.SetSize('375 250'); lblMapInfo.SetSize('375 250');
btnTeamBlue = spawn(VGUIButton); btnTeamBlue = spawn(vguiButton);
btnTeamBlue.SetTitle("BLUE"); btnTeamBlue.SetTitle("BLUE");
btnTeamBlue.SetPos(btnpos); btnTeamBlue.SetPos(btnpos);
btnTeamBlue.SetSize('124 24'); btnTeamBlue.SetSize('124 24');
@ -132,7 +132,7 @@ VGUI_ChooseTeam(void)
btnTeamBlue.SetFunc(VGUI_JoinBlue); btnTeamBlue.SetFunc(VGUI_JoinBlue);
btnpos[1] += 32; btnpos[1] += 32;
btnTeamRed = spawn(VGUIButton); btnTeamRed = spawn(vguiButton);
btnTeamRed.SetTitle("RED"); btnTeamRed.SetTitle("RED");
btnTeamRed.SetPos(btnpos); btnTeamRed.SetPos(btnpos);
btnTeamRed.SetSize('124 24'); btnTeamRed.SetSize('124 24');
@ -140,7 +140,7 @@ VGUI_ChooseTeam(void)
btnTeamRed.SetFunc(VGUI_JoinRed); btnTeamRed.SetFunc(VGUI_JoinRed);
btnpos[1] += 32; btnpos[1] += 32;
btnAutoAssign = spawn(VGUIButton); btnAutoAssign = spawn(vguiButton);
btnAutoAssign.SetTitle("AUTO ASSIGN"); btnAutoAssign.SetTitle("AUTO ASSIGN");
btnAutoAssign.SetPos(btnpos); btnAutoAssign.SetPos(btnpos);
btnAutoAssign.SetSize('124 24'); btnAutoAssign.SetSize('124 24');
@ -148,7 +148,7 @@ VGUI_ChooseTeam(void)
btnAutoAssign.SetFunc(VGUI_AutoAssign); btnAutoAssign.SetFunc(VGUI_AutoAssign);
btnpos[1] += 32; btnpos[1] += 32;
btnGoSpectator = spawn(VGUIButton); btnGoSpectator = spawn(vguiButton);
btnGoSpectator.SetTitle("SPECTATE"); btnGoSpectator.SetTitle("SPECTATE");
btnGoSpectator.SetPos(btnpos); btnGoSpectator.SetPos(btnpos);
btnGoSpectator.SetSize('124 24'); btnGoSpectator.SetSize('124 24');
@ -167,5 +167,5 @@ VGUI_ChooseTeam(void)
} }
winChooseTeam.Show(); winChooseTeam.Show();
winChooseTeam.SetPos((video_res / 2) - (winChooseTeam.GetSize() / 2)); winChooseTeam.SetPos((g_vidsize / 2) - (winChooseTeam.GetSize() / 2));
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org> * Copyright (c) 2023-2024 Marco Cawthorne <marco@icculus.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -18,11 +18,11 @@ void
VGUI_ShowMOTD(void) VGUI_ShowMOTD(void)
{ {
static int initialized; static int initialized;
static VGUIButton winMotdClose; static vguiButton winMotdClose;
// static VGUIButton winMotdMapInfo; // static vguiButton winMotdMapInfo;
static VGUIWindow winMotd; static vguiWindow winMotd;
static VGUILabel winMotdHostname; static vguiLabel winMotdHostname;
static VGUILabel winMotdBody; static vguiLabel winMotdBody;
static void VGUI_ShowMOTD_Close(void) static void VGUI_ShowMOTD_Close(void)
{ {
@ -30,17 +30,18 @@ VGUI_ShowMOTD(void)
winMotd.Hide(); winMotd.Hide();
} }
if (MOTD_GetLineCount() < 1i) if (MOTD_GetLineCount() < 1i) {
return; return;
}
if (!initialized) { if (!initialized) {
initialized = TRUE; initialized = TRUE;
winMotd = spawn(VGUIWindow); winMotd = spawn(vguiWindow);
winMotd.SetTitle("Message Of The Day"); winMotd.SetTitle("Message Of The Day");
winMotd.SetSize('424 312'); winMotd.SetSize('424 312');
winMotd.SetStyleMask(0); winMotd.SetStyleMask(0);
winMotdClose = spawn(VGUIButton); winMotdClose = spawn(vguiButton);
winMotdClose.SetTitle("OK"); winMotdClose.SetTitle("OK");
winMotdClose.SetPos([16, 266]); winMotdClose.SetPos([16, 266]);
winMotdClose.SetSize([160, 30]); winMotdClose.SetSize([160, 30]);
@ -49,7 +50,7 @@ VGUI_ShowMOTD(void)
/* TODO An experiment with how to display map readme /* TODO An experiment with how to display map readme
* files for non team games * files for non team games
if (serverkeyfloat("teams") < 1) { if (serverkeyfloat("teams") < 1) {
winMotdMapInfo = spawn(VGUIButton); winMotdMapInfo = spawn(vguiButton);
winMotdMapInfo.SetTitle("Map Info"); winMotdMapInfo.SetTitle("Map Info");
winMotdMapInfo.SetPos([196, 266]); winMotdMapInfo.SetPos([196, 266]);
winMotdMapInfo.SetSize([160, 30]); winMotdMapInfo.SetSize([160, 30]);
@ -57,12 +58,12 @@ VGUI_ShowMOTD(void)
} }
*/ */
winMotdHostname = spawn(VGUILabel); winMotdHostname = spawn(vguiLabel);
winMotdHostname.SetTitle(serverkey("hostname")); winMotdHostname.SetTitle(serverkey("hostname"));
winMotdHostname.SetTextSize(19); winMotdHostname.SetTextSize(19);
winMotdHostname.SetPos([16, 20]); winMotdHostname.SetPos([16, 20]);
winMotdBody = spawn(VGUILabel); winMotdBody = spawn(vguiLabel);
winMotdBody.SetTitle(MOTD_GetTextBody()); winMotdBody.SetTitle(MOTD_GetTextBody());
winMotdBody.SetPos([16, 48]); winMotdBody.SetPos([16, 48]);
winMotdBody.SetSize([392, 210]); winMotdBody.SetSize([392, 210]);
@ -75,5 +76,5 @@ VGUI_ShowMOTD(void)
} }
winMotd.Show(); winMotd.Show();
winMotd.SetPos((video_res / 2) - (winMotd.GetSize() / 2)); winMotd.SetPos((g_vidsize / 2) - (winMotd.GetSize() / 2));
} }

10
src/rules/Makefile Normal file
View file

@ -0,0 +1,10 @@
QCC=fteqcc
all:
mkdir -pv ../../zpak001.pk3dir/progs/
$(QCC) fear.qc
$(QCC) hunt.qc
$(QCC) invasion.qc
$(QCC) madness.qc
$(QCC) slaughter.qc
$(QCC) stealth.qc

80
src/rules/arsenal.h Normal file
View file

@ -0,0 +1,80 @@
/*
* Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var string g_defaultArsenal = "";
var string g_mapArsenal = "";
void
SHArsenal_Init(void)
{
int c = 0i;
string line;
string lineFeed;
filestream arsHandle;
string standardArsenal = "arsenals/starteqp.txt";
string mapArsenal = cvars.GetString("sh_weapfileloc"); //strcat("arsenal/", game.GetMap(), ".txt");
g_defaultArsenal = "";
g_mapArsenal = "";
if (exists.InVFS(standardArsenal) == true) {
arsHandle = fopen(standardArsenal, FILE_READ);
if (arsHandle >= 0) {
while ((lineFeed = fgets(arsHandle))) {
c = (int)tokenize_console(lineFeed);
line = argv(0);
if (STRING_SET(line)) {
g_defaultArsenal = strcat(g_defaultArsenal, line, " ");
}
}
fclose(arsHandle);
}
}
if (exists.InVFS(mapArsenal) == true) {
arsHandle = fopen(mapArsenal, FILE_READ);
if (arsHandle >= 0) {
while ((lineFeed = fgets(arsHandle))) {
c = (int)tokenize_console(lineFeed);
line = argv(0);
if (STRING_SET(line)) {
g_mapArsenal = strcat(g_mapArsenal, line, " ");
}
}
fclose(arsHandle);
}
}
// NSWarning("Default equipment: %s\nMap equipment: %s", g_defaultArsenal, g_mapArsenal);
}
void
SHArsenal_GiveItemsToPlayer(entity targetPlayer)
{
for (int i = 0; i < (int)tokenize_console(g_defaultArsenal); i++) {
ents.Input(targetPlayer, "GiveItem", argv(i), targetPlayer);
}
for (int i = 0; i < (int)tokenize_console(g_mapArsenal); i++) {
ents.Input(targetPlayer, "GiveItem", argv(i), targetPlayer);
}
}

213
src/rules/fear.qc Normal file
View file

@ -0,0 +1,213 @@
/*
* Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma PROGS_DAT "../../zpak001.pk3dir/progs/fear.dat"
#include "../../../src/server/api.h"
string g_strTeamList;
const string mp_teamlist_fallback = "scientist;hgrunt";
var string autocvar_mp_teamlist = mp_teamlist_fallback;
bool
IsTeamplay(void)
{
return cvars.GetBool("mp_teamplay");
}
bool
AllowFlashlight(void)
{
return cvars.GetBool("mp_flashlight");
}
void
CodeCallback_StartGameType(void)
{
motd.LoadDefault();
if (IsTeamplay() == true) {
int c;
/* get the segments from our cvar */
g_strTeamList = autocvar_mp_teamlist;
c = tokenizebyseparator(g_strTeamList, ";");
/* if we've got less than 2 teams, use the fallback... */
if (c < 2) {
g_strTeamList = mp_teamlist_fallback;
c = tokenizebyseparator(g_strTeamList, ";");
}
/* initialize all dem teams */
for (int i = 0; i < c; i++) {
teams.SetUp(i+1, argv(i), [255,255,255], true);
teams.SetSpawnPoint(i+1, "info_player_deathmatch");
}
} else {
game.SetSpawnPoint("info_player_deathmatch");
}
}
void
HLDM_PlayerSpawn(entity playerEntity)
{
string playerModel;
ents.ChangeToClass(playerEntity, "player_mp");
if (IsTeamplay() == true) {
float teamCount = tokenizebyseparator(g_strTeamList, ";");
float playerTeam = playerEntity.team;
string teamModel;
/* not part of a team? pick one of the ones we have */
/* TODO: this should sort us into the lowest team */
if (playerTeam == 0) {
playerTeam = 1 + floor(random(0, teamCount)); /* teams start at 1 after all */
ents.Input(playerEntity, "SetTeam", ftos(playerTeam), playerEntity);
}
teamModel = argv(playerTeam - 1);
playerModel = sprintf("models/player/%s/%s.mdl", teamModel, teamModel);
} else {
/* interpret the 'model' InfoKey */
playerModel = userinfo.GetString(playerEntity, "model");
if (playerModel != "") {
playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
}
}
/* fallback is always models/player.mdl for Half-Life */
if (playerModel == "" || exists.InVFS(playerModel) == false) {
playerModel = "models/player.mdl";
}
playerEntity.modelindex = getmodelindex(playerModel); /* keep OG size */
game.TeleportToSpawn(playerEntity);
}
void
CodeCallback_PlayerSpawn(entity playerEntity)
{
if (IsTeamplay() == false) {
HLDM_PlayerSpawn(playerEntity);
} else {
ents.ChangeToClass(playerEntity, "spectator");
game.TeleportToSpawn(playerEntity);
}
}
void
CodeCallback_PlayerDisconnect(entity playerEntity)
{
}
bool
CodeCallback_PlayerRequestRespawn(entity playerEntity)
{
CodeCallback_PlayerSpawn(playerEntity);
return (true);
}
void
CodeCallback_PlayerDamage(entity playerEntity, entity inflictor, entity attacker)
{
}
bool
CodeCallback_CallRequestTeam(entity playerEntity, int teamNum)
{
ents.Input(playerEntity, "SetTeam", itos(teamNum), playerEntity);
ents.Input(playerEntity, "Damage", "1000", playerEntity);
return (true);
}
void
CodeCallback_PlayerKilled(entity playerEntity, entity inflictor, entity attacker, string weapon)
{
combat.Obituary(playerEntity.netname, attacker.netname, weapon, "");
/* death-counter */
playerEntity.deaths++;
/* update score-counter */
if (ents.isPlayer(attacker)) {
if (playerEntity == attacker) {
attacker.frags--;
} else {
attacker.frags++;
}
}
}
bool
CodeCallback_ClientCommand(entity playerEntity, string command)
{
float commandArgs = tokenize(command);
switch (argv(0)) {
case "chooseteam":
string teamName = argv(1);
/* wrong mode */
if (IsTeamplay() == false) {
break;
}
/* no team defined */
if (!teamName) {
break;
}
float c = tokenizebyseparator(g_strTeamList, ";");
for (float i = 0; i < c; i++) {
if (argv(i) == teamName) {
string newTeam = ftos(i + 1);
ents.Input(playerEntity, "SetTeam", newTeam, playerEntity);
ents.Input(playerEntity, "Damage", "1000", playerEntity);
break;
}
}
break;
default:
return (false);
}
return (true);
}
bool
CodeCallback_ImpulseCommand(entity playerEntity, float impulseNum)
{
switch (impulseNum) {
case 100:
if (AllowFlashlight() == true) {
ents.Input(playerEntity, "UseItem", "item_suit", playerEntity);
}
break;
default:
return (false);
}
return (true);
}

139
src/rules/hunt.qc Normal file
View file

@ -0,0 +1,139 @@
/*
* Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// SCIENTISTS DO NOT RESPAWN IN THIS MODE!
#pragma PROGS_DAT "../../zpak001.pk3dir/progs/hunt.dat"
#include "../../../src/server/api.h"
bool
AllowFlashlight(void)
{
return cvars.GetBool("mp_flashlight");
}
void
CodeCallback_StartGameType(void)
{
motd.LoadDefault();
game.SetSpawnPoint("info_player_team1");
}
void
HLDM_PlayerSpawn(entity playerEntity)
{
string playerModel;
ents.ChangeToClass(playerEntity, "player");
/* interpret the 'model' InfoKey */
playerModel = userinfo.GetString(playerEntity, "model");
if (playerModel != "") {
playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
}
/* fallback is always models/player.mdl for Half-Life */
if (playerModel == "" || exists.InVFS(playerModel) == false) {
playerModel = "models/player.mdl";
}
playerEntity.modelindex = getmodelindex(playerModel); /* keep OG size */
game.TeleportToSpawn(playerEntity);
}
void
CodeCallback_PlayerSpawn(entity playerEntity)
{
ents.ChangeToClass(playerEntity, "spectator");
game.TeleportToSpawn(playerEntity);
}
void
CodeCallback_PlayerDisconnect(entity playerEntity)
{
}
bool
CodeCallback_PlayerRequestRespawn(entity playerEntity)
{
CodeCallback_PlayerSpawn(playerEntity);
return (true);
}
void
CodeCallback_PlayerDamage(entity playerEntity, entity inflictor, entity attacker)
{
}
bool
CodeCallback_CallRequestTeam(entity playerEntity, int teamNum)
{
return (false);
}
void
CodeCallback_PlayerKilled(entity playerEntity, entity inflictor, entity attacker, string weapon)
{
combat.Obituary(playerEntity.netname, attacker.netname, weapon, "");
/* death-counter */
playerEntity.deaths++;
/* update score-counter */
if (ents.isPlayer(attacker)) {
if (playerEntity == attacker) {
attacker.frags--;
} else {
attacker.frags++;
}
}
}
bool
CodeCallback_ClientCommand(entity playerEntity, string command)
{
float commandArgs = tokenize(command);
switch (argv(0)) {
default:
return (false);
}
return (true);
}
bool
CodeCallback_ImpulseCommand(entity playerEntity, float impulseNum)
{
switch (impulseNum) {
case 100:
if (AllowFlashlight() == true) {
ents.Input(playerEntity, "UseItem", "item_suit", playerEntity);
}
break;
default:
return (false);
}
return (true);
}

215
src/rules/invasion.qc Normal file
View file

@ -0,0 +1,215 @@
/*
* Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// SCIENTISTS DO NOT RESPAWN IN THIS MODE!
#pragma PROGS_DAT "../../zpak001.pk3dir/progs/invasion.dat"
#include "../../../src/server/api.h"
string g_strTeamList;
const string mp_teamlist_fallback = "scientist;hgrunt";
var string autocvar_mp_teamlist = mp_teamlist_fallback;
bool
IsTeamplay(void)
{
return cvars.GetBool("mp_teamplay");
}
bool
AllowFlashlight(void)
{
return cvars.GetBool("mp_flashlight");
}
void
CodeCallback_StartGameType(void)
{
motd.LoadDefault();
if (IsTeamplay() == true) {
int c;
/* get the segments from our cvar */
g_strTeamList = autocvar_mp_teamlist;
c = tokenizebyseparator(g_strTeamList, ";");
/* if we've got less than 2 teams, use the fallback... */
if (c < 2) {
g_strTeamList = mp_teamlist_fallback;
c = tokenizebyseparator(g_strTeamList, ";");
}
/* initialize all dem teams */
for (int i = 0; i < c; i++) {
teams.SetUp(i+1, argv(i), [255,255,255], true);
teams.SetSpawnPoint(i+1, "info_player_deathmatch");
}
} else {
game.SetSpawnPoint("info_player_deathmatch");
}
}
void
HLDM_PlayerSpawn(entity playerEntity)
{
string playerModel;
ents.ChangeToClass(playerEntity, "player_mp");
if (IsTeamplay() == true) {
float teamCount = tokenizebyseparator(g_strTeamList, ";");
float playerTeam = playerEntity.team;
string teamModel;
/* not part of a team? pick one of the ones we have */
/* TODO: this should sort us into the lowest team */
if (playerTeam == 0) {
playerTeam = 1 + floor(random(0, teamCount)); /* teams start at 1 after all */
ents.Input(playerEntity, "SetTeam", ftos(playerTeam), playerEntity);
}
teamModel = argv(playerTeam - 1);
playerModel = sprintf("models/player/%s/%s.mdl", teamModel, teamModel);
} else {
/* interpret the 'model' InfoKey */
playerModel = userinfo.GetString(playerEntity, "model");
if (playerModel != "") {
playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
}
}
/* fallback is always models/player.mdl for Half-Life */
if (playerModel == "" || exists.InVFS(playerModel) == false) {
playerModel = "models/player.mdl";
}
playerEntity.modelindex = getmodelindex(playerModel); /* keep OG size */
game.TeleportToSpawn(playerEntity);
}
void
CodeCallback_PlayerSpawn(entity playerEntity)
{
if (IsTeamplay() == false) {
HLDM_PlayerSpawn(playerEntity);
} else {
ents.ChangeToClass(playerEntity, "spectator");
game.TeleportToSpawn(playerEntity);
}
}
void
CodeCallback_PlayerDisconnect(entity playerEntity)
{
}
bool
CodeCallback_PlayerRequestRespawn(entity playerEntity)
{
CodeCallback_PlayerSpawn(playerEntity);
return (true);
}
void
CodeCallback_PlayerDamage(entity playerEntity, entity inflictor, entity attacker)
{
}
bool
CodeCallback_CallRequestTeam(entity playerEntity, int teamNum)
{
ents.Input(playerEntity, "SetTeam", itos(teamNum), playerEntity);
ents.Input(playerEntity, "Damage", "1000", playerEntity);
return (true);
}
void
CodeCallback_PlayerKilled(entity playerEntity, entity inflictor, entity attacker, string weapon)
{
combat.Obituary(playerEntity.netname, attacker.netname, weapon, "");
/* death-counter */
playerEntity.deaths++;
/* update score-counter */
if (ents.isPlayer(attacker)) {
if (playerEntity == attacker) {
attacker.frags--;
} else {
attacker.frags++;
}
}
}
bool
CodeCallback_ClientCommand(entity playerEntity, string command)
{
float commandArgs = tokenize(command);
switch (argv(0)) {
case "chooseteam":
string teamName = argv(1);
/* wrong mode */
if (IsTeamplay() == false) {
break;
}
/* no team defined */
if (!teamName) {
break;
}
float c = tokenizebyseparator(g_strTeamList, ";");
for (float i = 0; i < c; i++) {
if (argv(i) == teamName) {
string newTeam = ftos(i + 1);
ents.Input(playerEntity, "SetTeam", newTeam, playerEntity);
ents.Input(playerEntity, "Damage", "1000", playerEntity);
break;
}
}
break;
default:
return (false);
}
return (true);
}
bool
CodeCallback_ImpulseCommand(entity playerEntity, float impulseNum)
{
switch (impulseNum) {
case 100:
if (AllowFlashlight() == true) {
ents.Input(playerEntity, "UseItem", "item_suit", playerEntity);
}
break;
default:
return (false);
}
return (true);
}

174
src/rules/madness.qc Normal file
View file

@ -0,0 +1,174 @@
/*
* Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
// SCIENTISTS WILL ATTACK EACH OTHER AS WELL AS
// PLAYERS. THEY ARE BASICALLY ALL ROGUE.
//
// IF A SCIENTIST KILLS NPCS OR PLAYERS
// IT WILL PLAY SH/HIDE_LAUGH.WAV
//
// THEY CAN ALSO RESPAWN
#pragma PROGS_DAT "../../zpak001.pk3dir/progs/madness.dat"
#include "../../../src/server/api.h"
#include "arsenal.h"
#include "scimanager.h"
#include "shared.h"
/* Slaughter is the default game mode. */
void
CodeCallback_Input(entity activator, string inputName, string dataString)
{
switch (inputName) {
#if 0
case "CountScientists":
int livingScientists = 0i;
for (entity s = world; (s = find(s, ::classname, "monster_scientist"));) {
if (s.solid == SOLID_BBOX || s.solid == SOLID_SLIDEBOX) {
livingScientists++;
}
}
serverinfo.SetInteger("sci_count", livingScientists);
break;
#endif
case "ScientistKilled":
activator.frags += 1;
break;
case "ScientistDied":
ScientistManager::RespawnSingle(activator, 10.0f);
break;
}
}
void
CodeCallback_StartGameType(void)
{
SHArsenal_Init();
motd.LoadDefault();
teams.SetUp(1, "Players", [153, 204, 255], true);
teams.SetSpawnPoint(1, "info_player_team1");
teams.SetUp(4, "Scientists", [153, 204, 255], true);
teams.SetSpawnPoint(2, "monster_scientist");
precache_sound("sh/hide_laugh.wav");
// game.SetSpawnPoint("info_player_team1");
ScientistManager::PopulateLevel(cvars.GetInteger("sh_scimax"), "sh_scientist_madness");
}
void
CodeCallback_PlayerSpawn(entity playerEntity)
{
string playerModel;
ents.ChangeToClass(playerEntity, "player_slaughter");
ents.Input(playerEntity, "SetTeam", "1", playerEntity);
/* interpret the 'model' InfoKey */
playerModel = userinfo.GetString(playerEntity, "model");
if (playerModel != "") {
playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
}
/* fallback is always models/player.mdl for Half-Life */
if (playerModel == "" || exists.InVFS(playerModel) == false) {
playerModel = "models/player.mdl";
}
playerEntity.modelindex = getmodelindex(playerModel); /* keep OG size */
game.TeleportToSpawn(playerEntity);
SHArsenal_GiveItemsToPlayer(playerEntity);
}
void
CodeCallback_PlayerDisconnect(entity playerEntity)
{
}
bool
CodeCallback_PlayerRequestRespawn(entity playerEntity)
{
CodeCallback_PlayerSpawn(playerEntity);
return (true);
}
void
CodeCallback_PlayerDamage(entity playerEntity, entity inflictor, entity attacker)
{
}
.bool WASPOISONED;
void
CodeCallback_PlayerKilled(entity playerEntity, entity inflictor, entity attacker, string weapon)
{
/* Only laugh when the target wasn't poisoned, TODO */
if (attacker.classname == "sh_scientist_madness" && playerEntity.WASPOISONED == false) {
sound(attacker, CHAN_AUTO, "sh/hide_laugh.wav", 1.0, ATTN_NORM);
}
combat.Obituary(playerEntity.netname, attacker.netname, weapon, "");
/* death-counter */
playerEntity.deaths++;
/* update score-counter */
if (ents.isPlayer(attacker)) {
if (playerEntity == attacker) {
attacker.frags--;
} else {
attacker.frags++;
}
}
}
bool
CodeCallback_ClientCommand(entity playerEntity, string command)
{
float commandArgs = tokenize(command);
switch (argv(0)) {
default:
return (false);
}
return (true);
}
bool
CodeCallback_ImpulseCommand(entity playerEntity, float impulseNum)
{
switch (impulseNum) {
case 100:
if (AllowFlashlight() == true) {
ents.Input(playerEntity, "UseItem", "item_suit", playerEntity);
}
break;
default:
return (false);
}
return (true);
}

78
src/rules/scimanager.h Normal file
View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* Utility class that handles sh_scientist entities across all game modes */
class
ScientistManager
{
const void PopulateLevel(int sciNum, string decl);
const void ClearScientists(string decl);
const void RespawnSingle(entity scientistEntity, float waitTime);
const void TeleportToSpot(entity scientistEntity);
};
static void
_RespawnTimerFinished(void)
{
ents.Input(self.owner, "Respawn", "", self.owner);
ScientistManager::TeleportToSpot(self.owner);
remove(self);
}
void
ScientistManager::RespawnSingle(entity scientistEntity, float waitTime)
{
entity timer = spawn();
timer.owner = scientistEntity;
timer.think = _RespawnTimerFinished;
timer.nextthink = time + waitTime;
}
void
ScientistManager::TeleportToSpot(entity scientistEntity)
{
entity spawnPoint = game.FindRandomClassObject("monster_scientist");
setorigin(scientistEntity, spawnPoint.origin);
scientistEntity.angles = spawnPoint.angles;
}
void
ScientistManager::PopulateLevel(int sciNum, string decl)
{
int newMax = 0i;
for (entity s = world; (s = find(s, ::classname, "monster_scientist"));) {
newMax += 1i;
}
if (sciNum > newMax) {
NSWarning("Scientists spawns for %i desired, can only deliver %i", sciNum, newMax);
sciNum = newMax;
}
for (int i = 0; i < sciNum; i++) {
entity scientistEntity = ents.Create(decl, g_vec_null);
TeleportToSpot(scientistEntity);
}
}
void
ScientistManager::ClearScientists(string decl)
{
for (entity s = world; (s = find(s, ::classname, decl));) {
remove(s);
}
}

7
src/rules/shared.h Normal file
View file

@ -0,0 +1,7 @@
bool
AllowFlashlight(void)
{
return cvars.GetBool("mp_flashlight");
}

151
src/rules/slaughter.qc Normal file
View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma PROGS_DAT "../../zpak001.pk3dir/progs/slaughter.dat"
#include "../../../src/server/api.h"
#include "arsenal.h"
#include "scimanager.h"
#include "shared.h"
/* Slaughter is the default game mode. */
void
CodeCallback_Input(entity activator, string inputName, string dataString)
{
switch (inputName) {
#if 0
case "CountScientists":
int livingScientists = 0i;
for (entity s = world; (s = find(s, ::classname, "monster_scientist"));) {
if (s.solid == SOLID_BBOX || s.solid == SOLID_SLIDEBOX) {
livingScientists++;
}
}
serverinfo.SetInteger("sci_count", livingScientists);
break;
#endif
case "ScientistKilled":
activator.frags += 1;
break;
case "ScientistDied":
ScientistManager::RespawnSingle(activator, 10.0f);
break;
}
}
void
CodeCallback_StartGameType(void)
{
SHArsenal_Init();
motd.LoadDefault();
game.SetSpawnPoint("info_player_team1");
ScientistManager::PopulateLevel(cvars.GetInteger("sh_scimax"), "sh_scientist");
}
void
CodeCallback_PlayerSpawn(entity playerEntity)
{
string playerModel;
ents.ChangeToClass(playerEntity, "player_slaughter");
/* interpret the 'model' InfoKey */
playerModel = userinfo.GetString(playerEntity, "model");
if (playerModel != "") {
playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
}
/* fallback is always models/player.mdl for Half-Life */
if (playerModel == "" || exists.InVFS(playerModel) == false) {
playerModel = "models/player.mdl";
}
playerEntity.modelindex = getmodelindex(playerModel); /* keep OG size */
game.TeleportToSpawn(playerEntity);
SHArsenal_GiveItemsToPlayer(playerEntity);
}
void
CodeCallback_PlayerDisconnect(entity playerEntity)
{
}
bool
CodeCallback_PlayerRequestRespawn(entity playerEntity)
{
CodeCallback_PlayerSpawn(playerEntity);
return (true);
}
void
CodeCallback_PlayerDamage(entity playerEntity, entity inflictor, entity attacker)
{
}
void
CodeCallback_PlayerKilled(entity playerEntity, entity inflictor, entity attacker, string weapon)
{
combat.Obituary(playerEntity.netname, attacker.netname, weapon, "");
/* death-counter */
playerEntity.deaths++;
/* update score-counter */
if (ents.isPlayer(attacker)) {
if (playerEntity == attacker) {
attacker.frags--;
} else {
attacker.frags++;
}
}
}
bool
CodeCallback_ClientCommand(entity playerEntity, string command)
{
float commandArgs = tokenize(command);
switch (argv(0)) {
default:
return (false);
}
return (true);
}
bool
CodeCallback_ImpulseCommand(entity playerEntity, float impulseNum)
{
switch (impulseNum) {
case 100:
if (AllowFlashlight() == true) {
ents.Input(playerEntity, "UseItem", "item_suit", playerEntity);
}
break;
default:
return (false);
}
return (true);
}

213
src/rules/stealth.qc Normal file
View file

@ -0,0 +1,213 @@
/*
* Copyright (c) 2024 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma PROGS_DAT "../../zpak001.pk3dir/progs/stealth.dat"
#include "../../../src/server/api.h"
string g_strTeamList;
const string mp_teamlist_fallback = "scientist;hgrunt";
var string autocvar_mp_teamlist = mp_teamlist_fallback;
bool
IsTeamplay(void)
{
return cvars.GetBool("mp_teamplay");
}
bool
AllowFlashlight(void)
{
return cvars.GetBool("mp_flashlight");
}
void
CodeCallback_StartGameType(void)
{
motd.LoadDefault();
if (IsTeamplay() == true) {
int c;
/* get the segments from our cvar */
g_strTeamList = autocvar_mp_teamlist;
c = tokenizebyseparator(g_strTeamList, ";");
/* if we've got less than 2 teams, use the fallback... */
if (c < 2) {
g_strTeamList = mp_teamlist_fallback;
c = tokenizebyseparator(g_strTeamList, ";");
}
/* initialize all dem teams */
for (int i = 0; i < c; i++) {
teams.SetUp(i+1, argv(i), [255,255,255], true);
teams.SetSpawnPoint(i+1, "info_player_deathmatch");
}
} else {
game.SetSpawnPoint("info_player_deathmatch");
}
}
void
HLDM_PlayerSpawn(entity playerEntity)
{
string playerModel;
ents.ChangeToClass(playerEntity, "player_mp");
if (IsTeamplay() == true) {
float teamCount = tokenizebyseparator(g_strTeamList, ";");
float playerTeam = playerEntity.team;
string teamModel;
/* not part of a team? pick one of the ones we have */
/* TODO: this should sort us into the lowest team */
if (playerTeam == 0) {
playerTeam = 1 + floor(random(0, teamCount)); /* teams start at 1 after all */
ents.Input(playerEntity, "SetTeam", ftos(playerTeam), playerEntity);
}
teamModel = argv(playerTeam - 1);
playerModel = sprintf("models/player/%s/%s.mdl", teamModel, teamModel);
} else {
/* interpret the 'model' InfoKey */
playerModel = userinfo.GetString(playerEntity, "model");
if (playerModel != "") {
playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
}
}
/* fallback is always models/player.mdl for Half-Life */
if (playerModel == "" || exists.InVFS(playerModel) == false) {
playerModel = "models/player.mdl";
}
playerEntity.modelindex = getmodelindex(playerModel); /* keep OG size */
game.TeleportToSpawn(playerEntity);
}
void
CodeCallback_PlayerSpawn(entity playerEntity)
{
if (IsTeamplay() == false) {
HLDM_PlayerSpawn(playerEntity);
} else {
ents.ChangeToClass(playerEntity, "spectator");
game.TeleportToSpawn(playerEntity);
}
}
void
CodeCallback_PlayerDisconnect(entity playerEntity)
{
}
bool
CodeCallback_PlayerRequestRespawn(entity playerEntity)
{
CodeCallback_PlayerSpawn(playerEntity);
return (true);
}
void
CodeCallback_PlayerDamage(entity playerEntity, entity inflictor, entity attacker)
{
}
bool
CodeCallback_CallRequestTeam(entity playerEntity, int teamNum)
{
ents.Input(playerEntity, "SetTeam", itos(teamNum), playerEntity);
ents.Input(playerEntity, "Damage", "1000", playerEntity);
return (true);
}
void
CodeCallback_PlayerKilled(entity playerEntity, entity inflictor, entity attacker, string weapon)
{
combat.Obituary(playerEntity.netname, attacker.netname, weapon, "");
/* death-counter */
playerEntity.deaths++;
/* update score-counter */
if (ents.isPlayer(attacker)) {
if (playerEntity == attacker) {
attacker.frags--;
} else {
attacker.frags++;
}
}
}
bool
CodeCallback_ClientCommand(entity playerEntity, string command)
{
float commandArgs = tokenize(command);
switch (argv(0)) {
case "chooseteam":
string teamName = argv(1);
/* wrong mode */
if (IsTeamplay() == false) {
break;
}
/* no team defined */
if (!teamName) {
break;
}
float c = tokenizebyseparator(g_strTeamList, ";");
for (float i = 0; i < c; i++) {
if (argv(i) == teamName) {
string newTeam = ftos(i + 1);
ents.Input(playerEntity, "SetTeam", newTeam, playerEntity);
ents.Input(playerEntity, "Damage", "1000", playerEntity);
break;
}
}
break;
default:
return (false);
}
return (true);
}
bool
CodeCallback_ImpulseCommand(entity playerEntity, float impulseNum)
{
switch (impulseNum) {
case 100:
if (AllowFlashlight() == true) {
ents.Input(playerEntity, "UseItem", "item_suit", playerEntity);
}
break;
default:
return (false);
}
return (true);
}

View file

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

View file

@ -14,126 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
class HLGameRules:CGameRules
{
int m_iScientistsAlive;
float m_flRestockTimer;
float m_flBreakRespawnTimer;
/* client */
virtual void(NSClientPlayer) PlayerSpawn;
virtual void(NSClientPlayer) PlayerDeath;
virtual bool PlayerRequestRespawn(NSClientPlayer);
virtual bool ImpulseCommand(NSClient, float);
virtual void(NSClientPlayer) PlayerPostFrame;
virtual void(NSClientPlayer, entity) ScientistKill;
virtual void(void) RegisterSciDeath;
virtual bool(NSClientPlayer, string) ConsoleCommand;
virtual void(NSClientPlayer) LevelDecodeParms;
virtual void(NSClientPlayer) LevelChangeParms;
virtual void(void) LevelNewParms;
virtual void(void) FrameStart;
virtual void(void) CheckRules;
virtual bool(void) IsMultiplayer;
virtual void(void) RestartRound;
virtual void(void) CountScientists;
void(void) HLGameRules;
virtual void(void) InitPostEnts;
};
class SHTeamRules:HLGameRules
{
int m_iKillsTeam1;
int m_iKillsTeam2;
int m_iScoreTeam1;
int m_iScoreTeam2;
void(void) SHTeamRules;
virtual void(void) RestartRound;
virtual void(NSClientPlayer) PlayerSpawn;
virtual bool(void) IsTeamplay;
virtual void(void) AddTeam1Kill;
virtual void(void) AddTeam2Kill;
virtual void(void) RegisterSciDeath;
virtual void(NSClientPlayer, entity) ScientistKill;
virtual void(void) InitPostEnts;
};
class SHInvasionRules:HLGameRules
{
void(void) SHInvasionRules;
virtual void(void) RegisterSciDeath;
virtual string Title(void);
};
/* Standard Hunting (0):
Round-based competitive killing where scientists are always running around. Scientists don't respawn.
*/
class SHGameHunt:SHTeamRules
{
void(void) SHGameHunt;
virtual string Title(void);
};
/* Stealth Hunting (1):
Round-based competitive killing where scientists stand or walk around, but will run in fear if they see the player. Similar to deer hunting. Scientists don't respawn.
*/
class SHGameStealth:SHTeamRules
{
void(void) SHGameStealth;
virtual string Title(void);
};
/* Traditional Slaughter (2):
Casual killing where scientists behave the same as they were in Half-Life. Scientists respawn.
*/
class SHGameSlaughter:HLGameRules
{
void(void) SHGameSlaughter;
virtual string Title(void);
};
/* Live in Fear (3):
Unique round-based gamemode where players have to only kill an evil randomly selected player controlled scientist causing chaos. Those who kill good scientists are punished with lost points. The evil scientist gains one point from every kill (NPC or Players). Scientists respawn.
*/
class SHGameFear:SHTeamRules
{
void(void) SHGameFear;
virtual void(NSClientPlayer, entity) ScientistKill;
virtual string Title(void);
};
/* Madness (4):
Unique gamemode where scientists attack themselves and the players. Scientists inject players and NPCs only once with a poison that slowly drains their health to 0. The scientists also play a sound (sh/hide_laugh.wav) when they get a sucessful kill and are still alive. Scientists respawn.
*/
class SHGameMadness:HLGameRules
{
void(void) SHGameMadness;
virtual string Title(void);
};
/* Invasion (5):
Unique new round-based gamemode where scientists attack similar to madness but work together to kill everyone else. If players eleminate all scientists, then they win the round and have to do it all over again. Heavy WIP. Scientists and players don't respawn.
*/
class SHGameInvasion:SHInvasionRules
{
void(void) SHGameInvasion;
virtual string Title(void);
};
typedef enum typedef enum
{ {
SHMODE_STANDARD = 0, SHMODE_STANDARD = 0,
@ -171,6 +51,3 @@ var int autocvar_sh_announcescinum = 1;
/* default kills required for insanity */ /* default kills required for insanity */
var int autocvar_sh_insanity = 5; var int autocvar_sh_insanity = 5;
/* an override for sh_scimax */
var int autocvarsh_scimax_override = 0;

View file

@ -20,10 +20,10 @@ HLGameRules::RestartRound(void)
{ {
/* respawn all players and scientists */ /* respawn all players and scientists */
for (entity e = world; (e = find( e, ::classname, "player"));) { for (entity e = world; (e = find( e, ::classname, "player"));) {
PlayerSpawn((NSClientPlayer)e); PlayerSpawn((ncPlayer)e);
} }
for (entity e = world; (e = find( e, ::classname, "monster_scientist"));) { for (entity e = world; (e = find( e, ::classname, "monster_scientist"));) {
NSEntity sci = (NSEntity)e; ncEntity sci = (ncEntity)e;
sci.Respawn(); sci.Respawn();
} }
env_message_broadcast("New round, let's go!"); env_message_broadcast("New round, let's go!");
@ -42,7 +42,7 @@ HLGameRules::IsMultiplayer(void)
} }
void void
HLGameRules::LevelDecodeParms(NSClientPlayer pp) HLGameRules::LevelDecodeParms(ncPlayer pp)
{ {
SHPlayer pl = (SHPlayer)pp; SHPlayer pl = (SHPlayer)pp;
g_landmarkpos[0] = parm1; g_landmarkpos[0] = parm1;
@ -61,7 +61,7 @@ HLGameRules::LevelDecodeParms(NSClientPlayer pp)
} }
void void
HLGameRules::LevelChangeParms(NSClientPlayer pp) HLGameRules::LevelChangeParms(ncPlayer pp)
{ {
SHPlayer pl = (SHPlayer)pp; SHPlayer pl = (SHPlayer)pp;
parm1 = g_landmarkpos[0]; parm1 = g_landmarkpos[0];
@ -91,7 +91,7 @@ HLGameRules::LevelNewParms(void)
/* we check what fields have changed over the course of the frame and network /* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */ * only the ones that have actually changed */
void void
HLGameRules::PlayerPostFrame(NSClientPlayer pp) HLGameRules::PlayerPostFrame(ncPlayer pp)
{ {
SHPlayer pl = (SHPlayer)pp; SHPlayer pl = (SHPlayer)pp;
@ -126,7 +126,7 @@ HLGameRules::CountScientists(void)
} }
void void
HLGameRules::ScientistKill(NSClientPlayer pp, entity sci) HLGameRules::ScientistKill(ncPlayer pp, entity sci)
{ {
SHPlayer pl = (SHPlayer)pp; SHPlayer pl = (SHPlayer)pp;
@ -233,7 +233,7 @@ HLGameRules::CheckRules(void)
} }
void void
HLGameRules::PlayerDeath(NSClientPlayer pl) HLGameRules::PlayerDeath(ncPlayer pl)
{ {
SHPlayer sh_pl = (SHPlayer)pl; SHPlayer sh_pl = (SHPlayer)pl;
@ -300,7 +300,7 @@ HLGameRules::PlayerDeath(NSClientPlayer pl)
} }
bool bool
HLGameRules::PlayerRequestRespawn(NSClientPlayer bp) HLGameRules::PlayerRequestRespawn(ncPlayer bp)
{ {
if (bp.TimeSinceDeath() > 0.5f) { if (bp.TimeSinceDeath() > 0.5f) {
bp.ScheduleThink(PutClientInServer, 0.0f); bp.ScheduleThink(PutClientInServer, 0.0f);
@ -311,7 +311,7 @@ HLGameRules::PlayerRequestRespawn(NSClientPlayer bp)
} }
void void
HLGameRules::PlayerSpawn(NSClientPlayer pp) HLGameRules::PlayerSpawn(ncPlayer pp)
{ {
SHPlayer pl = (SHPlayer)pp; SHPlayer pl = (SHPlayer)pp;
/* this is where the mods want to deviate */ /* this is where the mods want to deviate */
@ -399,8 +399,6 @@ HLGameRules::PlayerSpawn(NSClientPlayer pp)
pl.SetOrigin(spot.origin); pl.SetOrigin(spot.origin);
pl.SetAngles(spot.angles); pl.SetAngles(spot.angles);
Client_FixAngle(pl, pl.angles);
pl.GiveItem("item_suit"); pl.GiveItem("item_suit");
SHData_GetItems(pl); SHData_GetItems(pl);
} }
@ -459,7 +457,7 @@ HLGameRules::HLGameRules(void)
} }
bool bool
HLGameRules::ConsoleCommand(NSClientPlayer pp, string cmd) HLGameRules::ConsoleCommand(ncPlayer pp, string cmd)
{ {
tokenize(cmd); tokenize(cmd);
@ -484,7 +482,7 @@ SHTeamRules::IsTeamplay(void)
} }
void void
SHTeamRules::PlayerSpawn(NSClientPlayer pp) SHTeamRules::PlayerSpawn(ncPlayer pp)
{ {
SHPlayer pl = (SHPlayer)pp; SHPlayer pl = (SHPlayer)pp;
@ -498,7 +496,7 @@ SHTeamRules::PlayerSpawn(NSClientPlayer pp)
} }
void void
SHTeamRules::ScientistKill(NSClientPlayer cl, entity sci) SHTeamRules::ScientistKill(ncPlayer cl, entity sci)
{ {
super::ScientistKill(cl, sci); super::ScientistKill(cl, sci);
@ -601,7 +599,7 @@ SHInvasionRules::RegisterSciDeath(void)
} }
void void
SHInvasionRules::PlayerDeath(NSClientPlayer pl) SHInvasionRules::PlayerDeath(ncPlayer pl)
{ {
pl = (SHPlayer)pl; pl = (SHPlayer)pl;
super::PlayerDeath(pl); super::PlayerDeath(pl);
@ -624,7 +622,7 @@ SHInvasionRules::SHInvasionRules(void)
void void
TriggerFlashlight(NSClient target) TriggerFlashlight(ncClient target)
{ {
entity oldself = self; entity oldself = self;
self = target; self = target;
@ -633,7 +631,7 @@ TriggerFlashlight(NSClient target)
} }
bool bool
HLGameRules::ImpulseCommand(NSClient bp, float num) HLGameRules::ImpulseCommand(ncClient bp, float num)
{ {
switch (num) { switch (num) {
case 100: case 100:

View file

@ -6,7 +6,7 @@ SHGameFear::SHGameFear(void)
void void
SHGameFear::ScientistKill(NSClientPlayer pp, entity sci) SHGameFear::ScientistKill(ncPlayer pp, entity sci)
{ {
SHPlayer pl = (SHPlayer)pp; SHPlayer pl = (SHPlayer)pp;

View file

@ -69,20 +69,16 @@ enum
SCIA_DEADTABLE3 SCIA_DEADTABLE3
}; };
class SHScientist:NSTalkMonster class SHScientist:ncTalkMonster
{ {
void SHScientist(void); void SHScientist(void);
/* override */ /* override */
virtual void SeeThink(void); virtual void SeeThink(void);
virtual float GetWalkSpeed(void);
virtual float GetChaseSpeed(void);
virtual float GetRunSpeed(void);
virtual void PanicFrame(void); virtual void PanicFrame(void);
virtual void Respawn(void); virtual void Respawn(void);
virtual void Pain(entity, entity, int, vector, int); virtual void Death(entity, entity, int, vector, vector, int);
virtual void Death(entity, entity, int, vector, int);
virtual void PlayerUse(void); virtual void PlayerUse(void);
virtual void TalkPanic(void); virtual void TalkPanic(void);
@ -93,6 +89,12 @@ class SHScientist:NSTalkMonster
}; };
void
SHScientist::SHScientist(void)
{
}
/* Players scare scientists if they see them in Stealth Hunting */ /* Players scare scientists if they see them in Stealth Hunting */
void void
SHScientist::SeeThink(void) SHScientist::SeeThink(void)
@ -126,27 +128,6 @@ SHScientist::PanicFrame(void)
input_movevalues = [6 * cvar("sh_scispeed"), 0, 0]; input_movevalues = [6 * cvar("sh_scispeed"), 0, 0];
} }
float
SHScientist::GetWalkSpeed(void)
{
super::GetWalkSpeed();
return 1.6 * cvar("sh_scispeed");
}
float
SHScientist::GetChaseSpeed(void)
{
super:: GetChaseSpeed();
return 6 * cvar("sh_scispeed");
}
float
SHScientist::GetRunSpeed(void)
{
super::GetRunSpeed();
return 3.5 * cvar("sh_scispeed");
}
void void
SHScientist::FallNoise(void) SHScientist::FallNoise(void)
@ -180,7 +161,7 @@ SHScientist::AttackMelee(void)
/* set these globals for scientist's poison /* set these globals for scientist's poison
* a little messy but it works */ * a little messy but it works */
.NSTimer poisonTimer; .ncTimer poisonTimer;
.entity poisonSource; .entity poisonSource;
.float OldTargetHealth; .float OldTargetHealth;
@ -337,28 +318,9 @@ SHScientist::PlayerUse(void)
} }
void void
SHScientist::Pain(entity inflictor, entity attacker, int damage, vector dir, int location) SHScientist::Death(entity inflictor, entity attacker, int damage, vector dir, vector absImpactPos, int location)
{
/* make everyone on edge */
WarnAllies();
if (m_flAnimTime > time) {
return;
}
if (IsAlive() == true) {
Sound_Speak(this, "monster_scientist.pain");
SetFrame(SCIA_FLINCH + floor(random(0, 6)));
m_iFlags |= MONSTER_FEAR;
m_flAnimTime = time + 0.25f;
}
}
void
SHScientist::Death(entity inflictor, entity attacker, int damage, vector dir, int location)
{ {
bool deathcheck = false; bool deathcheck = false;
HLGameRules rules = (HLGameRules)g_grMode;
/* upset everyone */ /* upset everyone */
if not (g_chosen_mode == SHMODE_MADNESS || g_chosen_mode == SHMODE_INVASION) if not (g_chosen_mode == SHMODE_MADNESS || g_chosen_mode == SHMODE_INVASION)
@ -366,61 +328,32 @@ SHScientist::Death(entity inflictor, entity attacker, int damage, vector dir, in
if (IsAlive() == true) { if (IsAlive() == true) {
SetFrame(SCIA_DIE_SIMPLE + floor(random(0, 6))); SetFrame(SCIA_DIE_SIMPLE + floor(random(0, 6)));
rules.ScientistKill((SHPlayer)attacker, (entity)this); g_grMode.Input(attacker, "ScientistKilled", "");
Plugin_PlayerObituary(attacker, this, g_dmg_iWeapon, g_dmg_iHitBody, g_dmg_iDamage);
Sound_Speak(this, "SHScientist.die");
deathcheck = true; deathcheck = true;
} }
/* now mark our state as 'dead' */ /* now mark our state as 'dead' */
super::Death(inflictor, attacker, damage, dir, location); super::Death(inflictor, attacker, damage, dir, absImpactPos, location);
/* now we'll tell our kill function about it, since we're now legally dead */ /* now we'll tell our kill function about it, since we're now legally dead */
if (deathcheck == true) { if (deathcheck == true) {
rules.RegisterSciDeath(); g_grMode.Input(this, "ScientistDied", "");
} }
/* will not respawn by themselves in these modes */
if (g_chosen_mode == SHMODE_STANDARD || g_chosen_mode == SHMODE_STEALTH || g_chosen_mode == SHMODE_INVASION)
return;
ScheduleThink(Respawn, 10.0f);
} }
void void
SHScientist::Respawn(void) SHScientist::Respawn(void)
{ {
HLGameRules rules = (HLGameRules)g_grMode;
/* don't spawn if we're hitting scimax */
if (serverkeyfloat("sci_count") >= serverkeyfloat("sv_scimax"))
return;
super::Respawn(); super::Respawn();
/* unset notarget for attacking scientists
* TODO in the future we shouldn't have to mess with flags this way */
flags &= ~FL_NOTARGET;
if not (g_chosen_mode == SHMODE_MADNESS || g_chosen_mode == SHMODE_INVASION)
m_iFlags |= MONSTER_CANFOLLOW;
/* attack EVERYONE */
if (g_chosen_mode == SHMODE_MADNESS)
m_iAlliance = MAL_ROGUE;
/* attack anyone but aliens */
if (g_chosen_mode == SHMODE_INVASION)
m_iAlliance = MAL_ALIEN;
/* scientists are always afraid in these modes */ /* scientists are always afraid in these modes */
if (g_chosen_mode == SHMODE_STANDARD || g_chosen_mode == SHMODE_MADNESS || g_chosen_mode == SHMODE_INVASION) { if (g_chosen_mode == SHMODE_STANDARD || g_chosen_mode == SHMODE_MADNESS || g_chosen_mode == SHMODE_INVASION) {
m_iFlags |= MONSTER_FEAR; m_iFlags |= MONSTER_FEAR;
} }
if (m_iBody <= 0i) if (m_iBody <= 0i) {
m_iBody = 0i; m_iBody = 0i;
}
if ((cvar("sh_scirand") == 1) || (m_iBody == 0i)) { if ((cvar("sh_scirand") == 1) || (m_iBody == 0i)) {
m_iBody = floor(random(1,5)); m_iBody = floor(random(1,5));
@ -450,13 +383,4 @@ SHScientist::Respawn(void)
SetBodyInGroup(1, 4); SetBodyInGroup(1, 4);
} }
} }
/* recount to update sciscore and so on */
rules.CountScientists();
}
void
SHScientist::SHScientist(void)
{
} }

View file

@ -1,6 +1,7 @@
#pragma target fte_5768 #pragma target fte_5768
//#pragma flag enable assumeint //#pragma flag enable assumeint
#pragma progs_dat "../../progs.dat" #pragma progs_dat "../../progs.dat"
#pragma forcecrc 54730
#define QWSSQC #define QWSSQC
#define SERVER #define SERVER
@ -14,22 +15,14 @@
../../../src/botlib/botinfo.h ../../../src/botlib/botinfo.h
../../../src/gs-entbase/server.src ../../../src/gs-entbase/server.src
../../../src/gs-entbase/shared.src ../../../src/gs-entbase/shared.src
defs.h ../../../valve/src/server/defs.h
../shared/include.src ../shared/include.src
gamerules.h
monster_scientist.qc monster_scientist.qc
../../../valve/src/server/player.qc
../../../src/botlib/include.src ../../../src/botlib/include.src
shdata_parse.qc shdata_parse.qc
gamerules.qc
gamerules_fear.qc
gamerules_hunt.qc
gamerules_invasion.qc
gamerules_madness.qc
gamerules_slaughter.qc
gamerules_stealth.qc
server.qc server.qc
../../../valve/src/server/flashlight.qc ../../../valve/src/server/HLSuit.qc
../../../valve/src/server/spawn.qc
../../../src/server/include.src ../../../src/server/include.src
../../../src/shared/include.src ../../../src/shared/include.src
#endlist #endlist

View file

@ -14,34 +14,34 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#if 0
void void
Game_InitRules(void) Game_InitRules(void)
{ {
g_chosen_mode = autocvar_sh_realistic; g_chosen_mode = autocvar_sh_realistic;
switch (autocvar_sh_realistic) { switch (autocvar_sh_realistic) {
case SHMODE_STANDARD:
g_grMode = spawn(SHGameHunt);
break;
case SHMODE_STEALTH: case SHMODE_STEALTH:
g_grMode = spawn(SHGameStealth); g_grMode = ncGameRules::InitFromProgs("progs/stealth.dat");
break; break;
case SHMODE_SLAUGHTER: case SHMODE_SLAUGHTER:
g_grMode = spawn(SHGameSlaughter); g_grMode = ncGameRules::InitFromProgs("progs/slaughter.dat");
break; break;
case SHMODE_LIVEINFEAR: case SHMODE_LIVEINFEAR:
g_grMode = spawn(SHGameFear); g_grMode = ncGameRules::InitFromProgs("progs/fear.dat");
break; break;
case SHMODE_MADNESS: case SHMODE_MADNESS:
g_grMode = spawn(SHGameMadness); g_grMode = ncGameRules::InitFromProgs("progs/madness.dat");
break; break;
case SHMODE_INVASION: case SHMODE_INVASION:
g_grMode = spawn(SHGameInvasion); g_grMode = ncGameRules::InitFromProgs("progs/invasion.dat");
break; break;
case SHMODE_STANDARD:
default: default:
g_grMode = spawn(HLGameRules); g_grMode = ncGameRules::InitFromProgs("progs/hunt.dat");
} }
} }
#endif
void void
Game_Worldspawn(void) Game_Worldspawn(void)
@ -51,6 +51,7 @@ Game_Worldspawn(void)
Sound_Precache("Player.FlashLightOff"); Sound_Precache("Player.FlashLightOff");
Sound_Precache("Player.FlashLightOn"); Sound_Precache("Player.FlashLightOn");
EntityDef_Precache("monster_scientist");
EntityDef_Precache("weapon_crowbar"); EntityDef_Precache("weapon_crowbar");
EntityDef_Precache("weapon_9mmhandgun"); EntityDef_Precache("weapon_9mmhandgun");
EntityDef_Precache("weapon_357"); EntityDef_Precache("weapon_357");
@ -69,7 +70,5 @@ Game_Worldspawn(void)
EntityDef_Precache("weapon_chainsaw"); EntityDef_Precache("weapon_chainsaw");
EntityDef_Precache("weapon_hammer"); EntityDef_Precache("weapon_hammer");
Player_Precache();
SHData_Parse(mapname); SHData_Parse(mapname);
FX_Corpse_Init();
} }

View file

@ -2,16 +2,15 @@
../../../valve/src/shared/entities.h ../../../valve/src/shared/entities.h
../../../valve/src/shared/events.h ../../../valve/src/shared/events.h
../../../valve/src/shared/flags.h ../../../valve/src/shared/flags.h
../../../valve/src/shared/skeleton.h
../../../valve/src/shared/player.qc ../../../valve/src/shared/player.qc
player.qc player.qc
../../../valve/src/shared/pmove.qc
pmove.qc pmove.qc
../../../valve/src/shared/animations.h ../../../valve/src/shared/animations.h
../../../valve/src/shared/animations.qc ../../../valve/src/shared/animations.qc
../../../valve/src/shared/fx_blood.qc ../../../valve/src/shared/fx_blood.qc
../../../valve/src/shared/fx_gaussbeam.qc ../../../valve/src/shared/fx_gaussbeam.qc
../../../valve/src/shared/fx_corpse.qc
../../../valve/src/shared/HLGaussBeam.qc ../../../valve/src/shared/HLGaussBeam.qc
../../../valve/src/shared/HLWeapon.qc ../../../valve/src/shared/HLWeapon.qc
../../../valve/src/shared/w_tripmine.qc ../../../valve/src/shared/w_tripmine.qc

View file

@ -1,54 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define ITEM_CROWBAR 0x00000001
#define ITEM_GLOCK 0x00000002
#define ITEM_PYTHON 0x00000004
#define ITEM_MP5 0x00000008
#define ITEM_CROSSBOW 0x00000010
#define ITEM_SHOTGUN 0x00000020
#define ITEM_RPG 0x00000040
#define ITEM_GAUSS 0x00000080
#define ITEM_EGON 0x00000100
#define ITEM_HORNETGUN 0x00000200
#define ITEM_HANDGRENADE 0x00000400
#define ITEM_TRIPMINE 0x00000800
#define ITEM_SATCHEL 0x00001000
#define ITEM_SNARK 0x00002000
#define ITEM_SUIT 0x00004000
#define ITEM_LONGJUMP 0x00008000
#define ITEM_HEALTHKIT 0x00010000
#define ITEM_BATTERY 0x00020000
#define ITEM_CANNON 0x00040000
#define ITEM_CHAINSAW 0x00080000
#define ITEM_HAMMER 0x00100000
#define ITEM_NEEDLE 0x00200000
#define ITEM_UNUSED23 0x00400000
#define ITEM_UNUSED24 0x00800000
#define ITEM_UNUSED25 0x01000000
#define ITEM_UNUSED26 0x02000000
#define ITEM_UNUSED27 0x04000000
#define ITEM_UNUSED28 0x08000000
#define ITEM_UNUSED29 0x10000000
#define ITEM_UNUSED30 0x20000000
#define ITEM_UNUSED31 0x40000000
#define ITEM_UNUSED32 0x80000000
/* part of .gflags */
#define GF_MADNESS (1<<23)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2021 Marco Cawthorne <marco@icculus.org> * Copyright (c) 2016-2024 Marco Cawthorne <marco@icculus.org>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -68,7 +68,7 @@ SHPlayer::SHPlayer(void)
} }
void void
SHSciAnim_PlayerUpdate(NSClientPlayer playerTarget) SHSciAnim_PlayerUpdate(ncPlayer playerTarget)
{ {
bool useTopAnim; bool useTopAnim;
SHPlayer pl = (SHPlayer)playerTarget; SHPlayer pl = (SHPlayer)playerTarget;
@ -199,7 +199,7 @@ void
SHPlayer::ReceiveEntity(float new, float flChanged) SHPlayer::ReceiveEntity(float new, float flChanged)
{ {
/* the generic client attributes */ /* the generic client attributes */
NSClientPlayer::ReceiveEntity(new, flChanged); ncPlayer::ReceiveEntity(new, flChanged);
/* animation */ /* animation */
READENTITY_BYTE(anim_top, PLAYER_TOPFRAME) READENTITY_BYTE(anim_top, PLAYER_TOPFRAME)
@ -318,7 +318,7 @@ SHPlayer::SendEntity(entity ePEnt, float flChanged)
flChanged = OptimiseChangedFlags(ePEnt, flChanged); flChanged = OptimiseChangedFlags(ePEnt, flChanged);
/* the generic client attributes */ /* the generic client attributes */
NSClientPlayer::SendEntity(ePEnt, flChanged); ncPlayer::SendEntity(ePEnt, flChanged);
SENDENTITY_BYTE(anim_top, PLAYER_TOPFRAME) SENDENTITY_BYTE(anim_top, PLAYER_TOPFRAME)
SENDENTITY_FLOAT(anim_top_time, PLAYER_TOPFRAME) SENDENTITY_FLOAT(anim_top_time, PLAYER_TOPFRAME)

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016-2023 Marco Cawthorne <marco@icculus.org> * Copyright (c) 2016-2024 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-2023 Gethyn ThomasQuail <gethyn@vera-visions.com> * Copyright (c) 2016-2023 Gethyn ThomasQuail <gethyn@vera-visions.com>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
@ -15,21 +15,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#define PMOVE_AIRSTEPHEIGHT 0 #define GF_MADNESS (1<<23)
#define PMOVE_STEPHEIGHT 18
#define PMOVE_FRICTION 4
#define PMOVE_EDGEFRICTION 1
#define PMOVE_STOPSPEED 100
#define PMOVE_GRAVITY 800
#define PMOVE_AIRACCELERATE 10
#define PMOVE_WATERACCELERATE 10
#define PMOVE_ACCELERATE 10
#define PMOVE_MAXSPEED 270
#define PMOVE_STEP_WALKSPEED 135
#define PMOVE_STEP_RUNSPEED 220
#define PHY_VIEWPOS [0,0,28]
#define PHY_VIEWPOS_CROUCHED [0,0,12]
#include "items.h"
/* insanity changes player move and attack speed /* insanity changes player move and attack speed
* so lets override some base player functions */ * so lets override some base player functions */

View file

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

View file

@ -1,17 +1,21 @@
exec skill_valve.cfg exec skill_valve.cfg
set sk_plr_hammer1 "50"
set sk_plr_hammer2 "50"
set sk_plr_hammer3 "50"
set sk_plr_hammeralt1 "200"
set sk_plr_hammeralt2 "200"
set sk_plr_hammeralt3 "200"
set sk_plr_chainsaw1 "10" set sk_plr_chainsaw1 "10"
set sk_plr_chainsaw2 "10" set sk_plr_chainsaw2 "10"
set sk_plr_chainsaw3 "10" set sk_plr_chainsaw3 "10"
set sk_plr_hammer1 "50"
set sk_plr_hammer2 "50"
set sk_plr_hammer3 "50"
set sk_plr_hammer_alt1 "200"
set sk_plr_hammer_alt2 "200"
set sk_plr_hammer_alt3 "200"
set sk_plr_handcannon1 "5" set sk_plr_handcannon1 "5"
set sk_plr_handcannon2 "5" set sk_plr_handcannon2 "5"
set sk_plr_handcannon3 "5" set sk_plr_handcannon3 "5"
set sk_plr_needle1 "5"
set sk_plr_needle2 "5"
set sk_plr_needle3 "5"

View file

@ -1,4 +1,13 @@
entityDef monster_scientist entityDef monster_scientist
{
"editor_mins" "-16 -16 -36"
"editor_maxs" "16 16 36"
"editor_description" "Scientist Spawn Point"
"editor_color" "1 0 0"
"spawnclass" "ncSpawnPoint"
}
entityDef sh_scientist
{ {
"spawnclass" "SHScientist" "spawnclass" "SHScientist"
"model" "models/scientist.mdl" "model" "models/scientist.mdl"
@ -14,9 +23,8 @@ entityDef monster_scientist
"speed_walk" "64" "speed_walk" "64"
"speed_run" "364" "speed_run" "364"
"snd_pain" "monster_scientist.pain" "snd_pain" "Scientist.Pain"
"snd_death" "monster_scientist.die" "snd_death" "Scientist.Die"
"snd_thud" "monster_scientist.thud"
"talk_answer" "!SC_ANSWER" "talk_answer" "!SC_ANSWER"
"talk_ask" "!SC_QUESTION" "talk_ask" "!SC_QUESTION"
@ -37,38 +45,23 @@ entityDef monster_scientist
"talk_follow" "!SC_OK" "talk_follow" "!SC_OK"
"talk_stop_follow" "!SC_STOP" "talk_stop_follow" "!SC_STOP"
"talk_deny_follow" "!SC_POK" "talk_deny_follow" "!SC_POK"
when "body" equals "1" {
"pitch" "105"
"netname" "Walter"
"body1" "1"
} }
when "body" equals "2" {
"pitch" "100" entityDef sh_scientist_madness
"netname" "Einstein" {
"body1" "2" "inherit" "sh_scientist"
"def_attack_melee" "scientist_syringe_poison"
"melee_range" "96"
"act_meleeAttack1" "61"
"act_meleeAttack2" "61"
"team" "4"
} }
when "body" equals "3" { entityDef scientist_syringe_poison
"pitch" "95" {
"netname" "Luther" "damage" "15"
"skin" "1" "delay" "0.5"
"body1" "3" "wait" "0.5"
} "attempts" "2"
when "body" equals "4" {
"pitch" "105"
"netname" "Slick"
"body1" "4"
}
// pre-disaster
when "spawnflags" equals "256" {
"talk_ask" ""
"talk_player_ask" "!SC_PQUEST"
"talk_player_greet" "!SC_PHELLO"
"talk_player_idle" "!SC_PIDLE"
"follow_on_use" "0"
}
} }

View file

@ -0,0 +1,14 @@
entityDef player
{
"spawnclass" "SHPlayer"
}
entityDef player_slaughter
{
"inherit" "player"
"ammo_9mm" "44"
"item" "item_suit"
"weapon" "weapon_crowbar,weapon_9mmhandgun"
"current_weapon" "1"
}

View file

@ -4,7 +4,7 @@ entityDef info_player_start
"editor_maxs" "16 16 36" "editor_maxs" "16 16 36"
"editor_description" "Singleplayer Spawn Point" "editor_description" "Singleplayer Spawn Point"
"editor_color" "1 0 0" "editor_color" "1 0 0"
"spawnclass" "NSSpawnPoint" "spawnclass" "ncSpawnPoint"
} }
entityDef info_player_deathmatch entityDef info_player_deathmatch
@ -13,7 +13,7 @@ entityDef info_player_deathmatch
"editor_maxs" "16 16 36" "editor_maxs" "16 16 36"
"editor_description" "Deathmatch Spawn Point" "editor_description" "Deathmatch Spawn Point"
"editor_color" "1 0 0" "editor_color" "1 0 0"
"spawnclass" "NSSpawnPoint" "spawnclass" "ncSpawnPoint"
} }
entityDef info_player_coop entityDef info_player_coop
@ -22,7 +22,7 @@ entityDef info_player_coop
"editor_maxs" "16 16 36" "editor_maxs" "16 16 36"
"editor_description" "Cooperative Spawn Point" "editor_description" "Cooperative Spawn Point"
"editor_color" "1 0 0" "editor_color" "1 0 0"
"spawnclass" "NSSpawnPoint" "spawnclass" "ncSpawnPoint"
} }
entityDef info_player_team1 entityDef info_player_team1
@ -31,7 +31,7 @@ entityDef info_player_team1
"editor_maxs" "16 16 36" "editor_maxs" "16 16 36"
"editor_description" "Red Team Spawn Point" "editor_description" "Red Team Spawn Point"
"editor_color" "1 0 0" "editor_color" "1 0 0"
"spawnclass" "NSSpawnPoint" "spawnclass" "ncSpawnPoint"
} }
entityDef info_player_team2 entityDef info_player_team2
@ -40,5 +40,5 @@ entityDef info_player_team2
"editor_maxs" "16 16 36" "editor_maxs" "16 16 36"
"editor_description" "Blue Team Spawn Point" "editor_description" "Blue Team Spawn Point"
"editor_color" "0 0 1" "editor_color" "0 0 1"
"spawnclass" "NSSpawnPoint" "spawnclass" "ncSpawnPoint"
} }

View file

@ -1,3 +1,4 @@
#include "weapons/base.def"
#include "weapons/357.def" #include "weapons/357.def"
#include "weapons/9mmAR.def" #include "weapons/9mmAR.def"
#include "weapons/9mmhandgun.def" #include "weapons/9mmhandgun.def"

View file

@ -0,0 +1,8 @@
entityDef weapon_base
{
"spawnclass" "ncWeapon"
"mins" "-16 -16 0"
"maxs" "16 16 16"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
}

View file

@ -0,0 +1,59 @@
#define CHAINSAW_IDLE_OFF 0
#define CHAINSAW_IDLE_ON 1
entityDef weapon_chainsaw
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Chainsaw"
"editor_rotatable" "1"
"inherit" "weapon_base"
"model" "models/p_saw.mdl"
"model_view" "models/v_chainsaw.mdl"
"snd_idle" "weapon_chainsaw.idle"
"snd_start" "weapon_chainsaw.start"
"snd_stop" "weapon_chainsaw.stop"
// weapon specific
"def_melee" "damage_chainsaw"
"melee_distance" "32"
"inv_name" "Chainsaw"
"ammoType" ""
"silent_fire" "0"
"act_idle" "5,6"
"act_draw" "3"
"act_holster" "4"
"act_fireStart" "0"
"act_fireFailed" "1"
"act_fire" "1"
"actMeleeStop" "2"
// HLWeapon specific
"hudSlot" "0"
"hudSlotPos" "2"
"weight" "1"
"crosshair" "none"
"ammoIcon" "none"
}
// TODO sh_chainspark and fx_spark.main
entityDef projectile_chainsaw
{
"spawnclass" "ncProjectile"
"damage" "skill:plr_chainsaw"
"is_bullet" "1"
"range" "32"
"decal_impact" "Impact.Spark"
"detonate_on_world" "1"
"gib" "1"
"failRate" "0.5"
"fireRate" "0.25"
"knockback" "-32"
"snd_fireFailed" "Weapon_Machete.miss"
"snd_hitBody" "weapon_chainsaw.hit"
"snd_hitWorld" "weapon_chainsaw.hit"
}

View file

@ -0,0 +1,76 @@
entityDef weapon_hammer
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Hammer"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_hammer.mdl"
"model_view" "models/v_hammer.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
"snd_hit" "weapon_hammer.hit"
"snd_failed" "weapon_hammer.miss"
// weapon specific
"def_fireInfo" "fireInfo_hammer"
"def_altFireInfo" "fireInfo_hammerCharged"
"inv_name" "Hammer"
"ammoRequired" "0"
"silent_fire" "1"
"testDistance" "-32"
"act_idle" "0,5,6"
"act_draw" "1"
"act_holster" "2,7,8"
// HLWeapon specific
"hudSlot" "0"
"hudSlotPos" "1"
"weight" "1"
"crosshair" "none"
"ammoIcon" "none"
}
entityDef damage_hammerCharged
{
"damage" "skill: plr_hammer_alt"
}
entityDef projectile_hammer
{
"spawnclass" "ncProjectile"
"damage" "skill:plr_hammer"
"is_bullet" "1"
"decal_impact" "Impact.Shot"
"detonate_on_world" "1"
"push" "3500"
}
entityDef projectile_hammerCharged
{
"spawnclass" "ncProjectile"
"def_damage" "damage_hammerCharged"
"is_bullet" "1"
"decal_impact" "Impact.Shot"
"detonate_on_world" "1"
}
entityDef fireInfo_hammer
{
"def_onFire" "projectile_hammer"
"failRate" "1.0"
"fireRate" "1.0"
"act_fireFailed" "3"
"act_fire" "3"
}
entityDef fireInfo_hammerCharged
{
"def_onRelease" "projectile_hammerCharged"
"act_fireFailed" "4"
"act_fire" "4"
}

View file

@ -21,10 +21,10 @@ entityDef weapon_handcannon
"ammoRequired" "1" "ammoRequired" "1"
"model_flash" "sprites/muzzleflash2.spr" "model_flash" "sprites/muzzleflash2.spr"
"actHolster" "5" "act_holster" "5"
"actReload" "3" "act_reload" "3"
"actDraw" "4" "act_draw" "4"
"actIdle" "6,7" "act_idle" "6,7"
"snd_fire" "weapon_handcannon.shoot" "snd_fire" "weapon_handcannon.shoot"
"snd_empty" "weapon_shotgun.empty" "snd_empty" "weapon_shotgun.empty"
@ -56,7 +56,7 @@ entityDef fireInfo_handcannon
"def_onFire" "projectile_handcannon" "def_onFire" "projectile_handcannon"
"ammoPerShot" "2" "ammoPerShot" "2"
"fireRate" "1.5" "fireRate" "1.5"
"actFire" "0" "act_fire" "0"
} }
entityDef fireInfo_altCannon entityDef fireInfo_altCannon
@ -64,7 +64,7 @@ entityDef fireInfo_altCannon
"def_onFire" "projectile_handcannon_single" "def_onFire" "projectile_handcannon_single"
"ammoPerShot" "1" "ammoPerShot" "1"
"fireRate" "1.5" "fireRate" "1.5"
"actFire" "1,2" "act_fire" "1,2"
} }
// TODO respect sh_hchorror = 1 // TODO respect sh_hchorror = 1
@ -72,6 +72,6 @@ entityDef fireInfo_handcannonHorror
{ {
"def_onFire" "projectile_handcannon" "def_onFire" "projectile_handcannon"
"fireRate" "0.5" "fireRate" "0.5"
"actFire" "0" "act_fire" "0"
"ammoRequired" "0" "ammoRequired" "0"
} }

View file

@ -17,8 +17,7 @@ entityDef weapon_needle
"clipSize" "0" "clipSize" "0"
"meleeRateMiss" "0.5" "meleeRateMiss" "0.5"
"meleeRateHit" "0.25" "meleeRateHit" "0.5"
// HLWeapon specific // HLWeapon specific
"hudSlot" "0" "hudSlot" "0"
@ -26,16 +25,13 @@ entityDef weapon_needle
"weight" "0" "weight" "0"
"crosshair" "none" "crosshair" "none"
"ammoIcon" "none" "ammoIcon" "none"
"icon" "none"
"iconSelected" "none"
} }
// TODO needs infection
entityDef damage_needle entityDef damage_needle
{ {
"damage" "skill:plr_needle" "damage" "skill:plr_needle"
// "kickDir" "-1 0 0"
// "knockback" "20"
// "push" "20000"
"gib" "0" "gib" "0"
"snd_hit" "weapon_needle.hit"
"snd_miss" "weapon_needle.miss"
} }

View file

@ -3,11 +3,6 @@ weapon_handcannon.shoot
sample cannon/fire.wav sample cannon/fire.wav
} }
weapon_chainsaw.attack
{
sample sh/chainsaw_idle2.wav
}
weapon_chainsaw.draw weapon_chainsaw.draw
{ {
sample sh/chainsaw_pullout.wav sample sh/chainsaw_pullout.wav
@ -30,7 +25,12 @@ weapon_chainsaw.idle
sample sh/chainsaw_idle.wav sample sh/chainsaw_idle.wav
} }
weapon_chainsaw.startup weapon_chainsaw.miss
{
sample sh/chainsaw_idle2.wav
}
weapon_chainsaw.start
{ {
sample sh/chainsaw_startup.wav sample sh/chainsaw_startup.wav
} }

View file

@ -1,4 +0,0 @@
entityDef player
{
"spawnclass" "SHPlayer"
}

View file

@ -1,56 +0,0 @@
entityDef weapon_chainsaw
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Chainsaw"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_saw.mdl"
"model_view" "models/v_chainsaw.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
"snd_idle" "weapon_chainsaw.idle"
// weapon specific
"def_melee" "damage_chainsaw"
"melee_distance" "32"
// TODO need velocity push on player (32 units each hit)
"inv_name" "Chainsaw"
"ammoType" ""
"ammoRequired" "0"
"clipSize" "0"
"meleeRateMiss" "0.5"
"meleeRateHit" "0.25"
"actIdle" "5,6"
"actDraw" "3"
"actHolster" "4"
"actMeleeStart" "0"
"actMeleeMiss" "1"
"actMeleeHit" "1"
"actMeleeStop" "2"
// HLWeapon specific
"hudSlot" "0"
"hudSlotPos" "2"
"weight" "1"
"crosshair" "none"
"ammoIcon" "none"
}
// TODO sh_chainspark and fx_spark.main
entityDef damage_chainsaw
{
"damage" "skill:plr_chainsaw"
// "kickDir" "-1 0 0"
// "knockback" "20"
// "push" "20000"
"gib" "1"
"snd_hit" "weapon_chainsaw.hit"
"snd_miss" "weapon_chainsaw.miss"
}

View file

@ -1,65 +0,0 @@
entityDef weapon_hammer
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Hammer"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/p_hammer.mdl"
"model_view" "models/v_hammer.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
"snd_idle" "weapon_hammer.idle"
"snd_hit" "weapon_hammer.hit"
"snd_miss" "weapon_hammer.miss"
// weapon specific
"def_melee" "damage_hammer"
"def_meleeAlt" "damage_hammerWindup"
"melee_distance" "32"
"inv_name" "Hammer"
"ammoType" ""
"ammoRequired" "0"
"clipSize" "0"
"meleeRateMiss" "1.0"
"meleeRateHit" "1.0"
"actIdle" "0,5,6"
"actDraw" "1"
"actHolster" "2,7,8"
"actMeleeMiss" "3"
"actMeleeHit" "3"
// HLWeapon specific
"hudSlot" "0"
"hudSlotPos" "1"
"weight" "1"
"crosshair" "none"
"ammoIcon" "none"
}
// TODO double check push/knockback works on victims
entityDef damage_hammer
{
"damage" "skill:plr_hammer"
// "kickDir" "-1 0 0"
// "knockback" "20"
"push" "20000"
"gib" "0"
}
// TODO
entityDef damage_hammerWindup
{
"damage" "skill:plr_hammeralt"
"gib" "1"
"meleeRateMiss" "0.75"
"meleeRateHit" "0.75"
"actMeleeMiss" "4"
"actMeleeHit" "4"
}

View file

@ -1,60 +0,0 @@
// Generic Binds
bind "ESC" "togglemenu"
bind "w" "+forward"
bind "s" "+back"
bind "a" "+moveleft"
bind "d" "+moveright"
bind "SPACE" "+jump"
bind "CTRL" "+duck"
bind "SHIFT" "+speed"
bind "0" "slot10"
bind "1" "slot1"
bind "2" "slot2"
bind "3" "slot3"
bind "4" "slot4"
bind "5" "slot5"
bind "6" "slot6"
bind "7" "slot7"
bind "8" "slot8"
bind "9" "slot9"
bind "UPARROW" "+forward"
bind "DOWNARROW" "+back"
bind "LEFTARROW" "+left"
bind "RIGHTARROW" "+right"
bind "MOUSE1" "+attack"
bind "MOUSE2" "+attack2"
bind "MWHEELDOWN" "invnext"
bind "MWHEELUP" "invprev"
bind "r" "+reload"
bind "e" "+use"
bind "TAB" "+showscores"
bind "y" "messagemode"
bind "u" "messagemode2"
bind "t" "impulse 201"
bind "f" "impulse 100"
bind "f1" "vote yes"
bind "f2" "vote no"
// Game Variables
seta "hostname" "FreeSH Server"
seta "maxplayers" "8"
// 2D/HUD Variables
seta "con_color" "255 255 215"
seta "vgui_color" "255 255 215"
seta "cross_color" "0 255 0"
// disable some nuclide niceties
seta v_muzzledlight 0
// config compat
alias mp_timelimit timelimit
alias mp_fraglimit fraglimit
alias sv_gamemode sh_realistic
// video settings
seta gl_overbright 0
seta gl_ldr 1
seta r_lightmap_format rgb8
exec skill_scihunt.cfg

View file

@ -0,0 +1,53 @@
unbindall
bind CTRL "+duck"
bind DOWNARROW "+back"
bind ESCAPE "togglemenu"
bind F1 "vote yes"
bind F2 "vote no"
bind LEFTARROW "+left"
bind MOUSE1 "+attack"
bind MOUSE2 "+attack2"
bind MWHEELDOWN "weapnext"
bind MWHEELUP "weapprev"
bind RIGHTARROW "+right"
bind SHIFT "+speed"
bind SPACE "+jump"
bind TAB "+showscores"
bind UPARROW "+forward"
bind 0 "slot10"
bind 1 "slot1"
bind 2 "slot2"
bind 3 "slot3"
bind 4 "slot4"
bind 5 "slot5"
bind 6 "slot6"
bind 7 "slot7"
bind 8 "slot8"
bind 9 "slot9"
bind ` "toggleconsole"
bind a "+moveleft"
bind d "+moveright"
bind e "+use"
bind f "impulse 100"
bind r "+reload"
bind s "+back"
bind t "impulse 201"
bind u "messagemode2"
bind w "+forward"
bind y "messagemode"
bind q "weaplast"
bind ~ "toggleconsole"
// load game defaults
exec cvar_defaults.cfg
// our mod overrides below
// Game Variables
seta "hostname" "FreeSH Server"
seta "maxplayers" "8"
// 2D/HUD Variables
seta "con_color" "255 255 215"
seta "vgui_color" "255 255 215"
seta "cross_color" "0 255 0"

5
zpak001.pk3dir/quake.rc Normal file
View file

@ -0,0 +1,5 @@
exec default_controls.cfg
exec default_cvar.cfg
exec default_video.cfg
exec default_valve.cfg
exec default_scihunt.cfg