Code fixups against latest Nuclide. Move gamerules into their own module.

This commit is contained in:
Marco Cawthorne 2024-09-03 12:21:03 -07:00
parent 4dba3af403
commit 35bbae956b
Signed by: eukara
GPG key ID: CE2032F0A2882A22
25 changed files with 475 additions and 289 deletions

View file

@ -29,7 +29,7 @@
/* disable quake specific hacks and overrides */
#define QUAKETC
#define NOBUILTINMENUS
//#define NOBUILTINMENUS
#define NOLEGACY
/* engine behaviour */
@ -43,8 +43,11 @@
#define USEAREAGRID /* leave it on, improves performance */
#define AVAIL_DINPUT /* input for Windows */
#define AVAIL_FREETYPE /* for truetype font rendering */
#define AVAIL_STBI /* avoid libpng/libjpeg dependancies */
//#define AVAIL_STBI /* avoid libpng/libjpeg dependancies */
#define ENGINE_ROUTING /* engine-side, fast routing */
#define HAVE_MEDIA_DECODER /* can play cin/roq, more with plugins */
#define HAVE_MEDIA_ENCODER /* capture/capturedemo work */
#define PACKAGEMANAGER /* enable/disable/download packages and plugins */
#ifndef LEGACY_GPU
#define RTLIGHTS
@ -59,7 +62,7 @@
/* uncompressed textures */
#define IMAGEFMT_BMP /* sprays */
#define IMAGEFMT_TGA
#define IMAGEFMT_JPG
#define IMAGEFMT_JPG
/* compressed textures */
#define IMAGEFMT_KTX
@ -95,14 +98,14 @@
#define TERRAIN
/* audio */
#undef AVAIL_DSOUND
#undef AVAIL_DSOUND
#define AVAIL_OPENAL
#define AVAIL_OGGVORBIS
#define HAVE_OPUS
#define VOICECHAT
/* todo: make OpenAL only */
#define HAVE_MIXER
/* todo: make OpenAL only */
#define HAVE_MIXER
/* Model formats, IQM/VVM and HLMDL for legacy maps */
#define INTERQUAKEMODELS
@ -141,8 +144,8 @@
#undef HAVE_SPEEX /* .xz decompression */
#undef AVAIL_GZDEC /* .gz decompression */
#undef PACKAGE_DZIP /* .dzip special-case archive support */
#undef AVAIL_PNGLIB /* .png image format support (read+screenshots) */
#undef AVAIL_JPEGLIB /* .jpeg image format support (read+screenshots) */
#define AVAIL_PNGLIB /* .png image format support (read+screenshots) */
#define AVAIL_JPEGLIB /* .jpeg image format support (read+screenshots) */
#undef AVAIL_MP3_ACM /* .mp3 support (in windows). */
#undef IMAGEFMT_DDS
#undef IMAGEFMT_PKM
@ -179,11 +182,8 @@
#undef HLSERVER /* regressed, unfinished */
#undef FTPSERVER
#undef HAVE_JUKEBO /* includes built-in jukebox */
#define HAVE_MEDIA_DECODER /* can play cin/roq, more with plugins */
#undef HAVE_MEDIA_ENCODER /* capture/capturedemo work */
#undef HAVE_SPEECHTOTEXT /* Windows speech-to-text thing */
#undef SAVEDGAMES
#undef PACKAGEMANAGER /* enable/disable/download packages and plugins */
#undef HEADLESSQUAKE
#undef WAYLANDQUAKE
#undef SERVER_DEMO_PLAYBACK /* deprecated */

View file

@ -3,4 +3,6 @@ QCC=fteqcc
all:
cd client && $(MAKE)
cd server && $(MAKE)
cd menu && $(MAKE)
cd menu && $(MAKE)
cd ../zpak001.pk3dir/maps/mp/gametypes/ && $(QCC) dm.qc
cd ../zpak001.pk3dir/maps/ && $(QCC) singleplayer.qc

View file

@ -24,7 +24,7 @@ ClientGame_ConsoleCommand(void)
{
switch(argv(0)) {
case "chooseteam":
sendevent("HLDM_Chooseteam", "s", argv(1));
localcmd(sprintf("cmd %s %s\n", argv(0), argv(1)));
break;
case "invnext":
pSeatLocal->weaponSelectionHUD.SelectNext(false);

View file

@ -144,12 +144,6 @@ HUD_DrawHealth(void)
pSeatLocal->m_flHealthAlpha = 1.0;
}
if (pSeatLocal->m_flHealthAlpha >= HUD_ALPHA) {
pSeatLocal->m_flHealthAlpha -= clframetime * 0.5;
} else {
pSeatLocal->m_flHealthAlpha = HUD_ALPHA;
}
pos = g_hudmins + [88, g_hudres[1] - 42];
if (pl.health > 25) {
drawsubpic(
@ -178,6 +172,12 @@ HUD_DrawHealth(void)
}
pSeatLocal->m_iHealthOld = pl.health;
if (pSeatLocal->m_flHealthAlpha >= HUD_ALPHA) {
pSeatLocal->m_flHealthAlpha = bound(HUD_ALPHA, pSeatLocal->m_flHealthAlpha - (clframetime * 0.5), 1.0);
} else {
pSeatLocal->m_flHealthAlpha = HUD_ALPHA;
}
}
/* armor/suit charge */
@ -193,12 +193,6 @@ HUD_DrawArmor(void)
pSeatLocal->m_flArmorAlpha = 1.0;
}
if (pSeatLocal->m_flArmorAlpha >= HUD_ALPHA) {
pSeatLocal->m_flArmorAlpha -= clframetime * 0.5;
} else {
pSeatLocal->m_flArmorAlpha = HUD_ALPHA;
}
drawsubpic(
pos + [-80,-9],
[40,40],
@ -226,6 +220,12 @@ HUD_DrawArmor(void)
HUD_DrawNums(pl.armor, pos, pSeatLocal->m_flArmorAlpha, g_hud_color);
pSeatLocal->m_iArmorOld = pl.armor;
if (pSeatLocal->m_flArmorAlpha >= HUD_ALPHA) {
pSeatLocal->m_flArmorAlpha = bound(HUD_ALPHA, pSeatLocal->m_flArmorAlpha - (clframetime * 0.5), 1.0);
} else {
pSeatLocal->m_flArmorAlpha = HUD_ALPHA;
}
}
/* magazine/clip ammo */
@ -240,15 +240,15 @@ HUD_DrawAmmo1(void)
pSeatLocal->m_iAmmo1Old = pl.a_ammo1;
}
if (pSeatLocal->m_flAmmo1Alpha >= HUD_ALPHA) {
pSeatLocal->m_flAmmo1Alpha -= clframetime * 0.5;
} else {
pSeatLocal->m_flAmmo1Alpha = HUD_ALPHA;
}
pos = g_hudmins + [g_hudres[0] - 152, g_hudres[1] - 42];
HUD_DrawNums(pl.a_ammo1, pos, pSeatLocal->m_flAmmo1Alpha, g_hud_color);
HUD_DrawSeperator(pos + [30,0]);
if (pSeatLocal->m_flAmmo1Alpha >= HUD_ALPHA) {
pSeatLocal->m_flAmmo1Alpha = bound(HUD_ALPHA, pSeatLocal->m_flAmmo1Alpha - (clframetime * 0.5), 1.0);
} else {
pSeatLocal->m_flAmmo1Alpha = HUD_ALPHA;
}
}
/* leftover type ammo */
@ -263,14 +263,14 @@ HUD_DrawAmmo2(void)
pSeatLocal->m_iAmmo2Old = pl.a_ammo2;
}
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 42];
HUD_DrawNums(pl.a_ammo2, pos, pSeatLocal->m_flAmmo2Alpha, g_hud_color);
if (pSeatLocal->m_flAmmo2Alpha >= HUD_ALPHA) {
pSeatLocal->m_flAmmo2Alpha -= clframetime * 0.5;
pSeatLocal->m_flAmmo2Alpha = bound(HUD_ALPHA, pSeatLocal->m_flAmmo2Alpha - (clframetime * 0.5), 1.0);
} else {
pSeatLocal->m_flAmmo2Alpha = HUD_ALPHA;
}
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 42];
HUD_DrawNums(pl.a_ammo2, pos, pSeatLocal->m_flAmmo2Alpha, g_hud_color);
}
/* special ammo */
@ -285,14 +285,15 @@ HUD_DrawAmmo3(void)
pSeatLocal->m_iAmmo3Old = pl.a_ammo3;
}
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 74];
HUD_DrawNums(pl.a_ammo3, pos, pSeatLocal->m_flAmmo3Alpha, g_hud_color);
if (pSeatLocal->m_flAmmo3Alpha >= HUD_ALPHA) {
pSeatLocal->m_flAmmo3Alpha -= clframetime * 0.5;
pSeatLocal->m_flAmmo3Alpha = bound(HUD_ALPHA, pSeatLocal->m_flAmmo3Alpha - (clframetime * 0.5), 1.0);
} else {
pSeatLocal->m_flAmmo3Alpha = HUD_ALPHA;
}
pos = g_hudmins + [g_hudres[0] - 72, g_hudres[1] - 74];
HUD_DrawNums(pl.a_ammo3, pos, pSeatLocal->m_flAmmo3Alpha, g_hud_color);
}
/* ammo bar */

View file

@ -27,15 +27,12 @@ typedef struct {
string src_sprite; /* precaching reasons */
} obituaryimg_t;
obituaryimg_t *g_obtypes;
int g_obtype_count;
/* actual obituary storage */
typedef struct
{
string attacker;
string victim;
int icon;
string icon;
} obituary_t;
obituary_t g_obituary[OBITUARY_LINES];

View file

@ -17,114 +17,38 @@
void
Obituary_Init(void)
{
#if 0
int c;
int i;
filestream fh;
string line;
vector tmp;
if (g_obtype_count > 0) {
return;
}
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 = spriteframe(sprintf("sprites/%s.spr", argv(2)), 0, 0.0f);
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);
#endif
}
void
Obituary_Precache(void)
{
for (int i = 0; i < g_obtype_count; i++)
precache_model(g_obtypes[i].src_sprite);
}
void
Obituary_KillIcon(int id, float w)
{
#if 0
if (w > 0)
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;
}
}
#endif
}
void
Obituary_Add(string attacker, string victim, float weapon, float flags)
Obituary_Add(string attacker, string victim, string weapon, float flags)
{
#if 0
int i;
int x, y;
x = OBITUARY_LINES;
string weaponIcon = "";
if (attacker == "worldspawn" || attacker == victim) {
attacker = "";
}
weaponIcon = EntityDef_GetKeyValue(weapon, "killIcon");
if (weaponIcon == "") {
weaponIcon = "d_skull";
}
/* 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[y].icon = weaponIcon;
g_obituary_count++;
} else {
for (i = 0; i < (x-1); i++) {
@ -135,11 +59,12 @@ Obituary_Add(string attacker, string victim, float weapon, float flags)
/* 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[x-1].icon = weaponIcon;
}
g_obituary_time = OBITUARY_TIME;
#if 0
if (g_weapons[weapon].deathmsg) {
string conprint = g_weapons[weapon].deathmsg();
@ -191,18 +116,13 @@ Obituary_Draw(void)
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]],
g_hud_color,
1.0f,
DRAWFLAG_ADDITIVE
);
//item[0] -= g_obtypes[g_obituary[i].icon].size[0];
HLSprite_Draw_RGBA(g_obituary[i].icon, item, g_hud_color, 1.0f, true);
// draw g_obituary[i].icon
a = g_obituary[i].attacker;
drawstring_r(item + [-4,2], a, [12,12], [1,1,1], 1.0f, 0);
@ -217,12 +137,12 @@ Obituary_Parse(void)
{
string attacker;
string victim;
float weapon;
string weapon;
float flags;
attacker = readstring();
victim = readstring();
weapon = readbyte();
weapon = readstring();
flags = readbyte();
if (!attacker) {

View file

@ -1,5 +1,5 @@
#pragma target fte_5768
#pragma progs_dat "../../zpak001.pk3dir/csprogs.dat"
#pragma progs_dat "../../csprogs.dat"
#define CSQC
#define CLIENT

View file

@ -33,7 +33,7 @@ class HLSingleplayerRules:HLGameRules
{
/* client */
virtual void(NSClientPlayer) PlayerSpawn;
virtual void(NSClientPlayer) PlayerDeath;
virtual void(NSClientPlayer, NSActor, NSDict) PlayerDeath;
virtual bool(void) IsMultiplayer;
virtual bool ImpulseCommand(NSClient, float);
};
@ -52,7 +52,7 @@ class HLMultiplayerRules:HLGameRules
/* client */
virtual void(NSClientPlayer) PlayerSpawn;
virtual void(NSClientPlayer) PlayerDeath;
virtual void(NSClientPlayer, NSActor, NSDict) PlayerDeath;
virtual bool(NSClientPlayer, string) ConsoleCommand;
virtual bool(void) IsMultiplayer;
virtual bool(void) IsTeamplay;

View file

@ -34,29 +34,6 @@ HLGameRules::LevelDecodeParms(NSClientPlayer pl)
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.flags = parm64;
#if 0
pl.ammo_9mm = parm12;
pl.ammo_357 = parm13;
pl.ammo_buckshot = parm14;
pl.ammo_m203_grenade = parm15;
pl.ammo_bolt = parm16;
pl.ammo_rocket = parm17;
pl.ammo_uranium = parm18;
pl.ammo_handgrenade = parm19;
pl.ammo_satchel = parm20;
pl.ammo_tripmine = parm21;
pl.ammo_snark = parm22;
pl.ammo_hornet = parm23;
pl.glock_mag = parm24;
pl.mp5_mag = parm25;
pl.python_mag = parm26;
pl.shotgun_mag = parm27;
pl.crossbow_mag = parm28;
pl.rpg_mag = parm29;
pl.satchel_chg = parm30;
#endif
}
void

View file

@ -93,31 +93,37 @@ HLMultiplayerRules::CheckRules(void)
}
void
HLMultiplayerRules::PlayerDeath(NSClientPlayer pl)
HLMultiplayerRules::PlayerDeath(NSClientPlayer pl, NSActor attacker, NSDict damageDecl)
{
vector damageLocation = damageDecl.GetVector("location");
int hitBody = (int)damageDecl.GetFloat("hitbody");
int damagePoints = (int)damageDecl.GetFloat("damage");
/* obituary networking */
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_OBITUARY);
WriteString(MSG_MULTICAST, (g_dmg_eAttacker.netname) ? g_dmg_eAttacker.netname : g_dmg_eAttacker.classname);
WriteString(MSG_MULTICAST, (attacker.netname) ? attacker.netname : attacker.classname);
WriteString(MSG_MULTICAST, pl.netname);
WriteByte(MSG_MULTICAST, g_dmg_iWeapon);
WriteString(MSG_MULTICAST, damageDecl.GetString("weapon"));
WriteByte(MSG_MULTICAST, 0);
msg_entity = world;
multicast([0,0,0], MULTICAST_ALL);
Plugin_PlayerObituary(g_dmg_eAttacker, g_dmg_eTarget, g_dmg_iWeapon, g_dmg_iHitBody, g_dmg_iDamage);
//Plugin_PlayerObituary(g_dmg_eAttacker, g_dmg_eTarget, g_dmg_iWeapon, g_dmg_iHitBody, g_dmg_iDamage);
/* death-counter */
pl.deaths++;
pl.SetInfoKey("*deaths", ftos(pl.deaths));
/* update score-counter */
if (pl.flags & FL_CLIENT || pl.flags & FL_MONSTER)
if (g_dmg_eAttacker.flags & FL_CLIENT) {
if (pl == g_dmg_eAttacker)
g_dmg_eAttacker.frags--;
else
g_dmg_eAttacker.frags++;
if (isPlayer(pl) || isAI(pl)) {
if (isPlayer(attacker)) {
if (pl == attacker) {
attacker.frags--;
} else {
attacker.frags++;
}
}
}
#ifdef VALVE
@ -129,14 +135,13 @@ HLMultiplayerRules::PlayerDeath(NSClientPlayer pl)
/* either gib, or make a corpse */
if (pl.health < -50) {
vector gibDir = vectoangles(pl.origin - g_dmg_eAttacker.origin);
float gibStrength = g_dmg_iDamage * 2.0f;
vector gibDir = vectoangles(pl.origin - attacker.origin);
float gibStrength = damagePoints * 2.0f;
BreakModel_Entity(pl, gibDir, gibStrength);
} else {
#if 0
float deathAnimation = ANIM_DIESIMPLE;
switch (g_dmg_iHitBody) {
switch (hitBody) {
case BODY_HEAD:
deathAnimation = ANIM_DIEHEADSHOT;
break;
@ -147,7 +152,7 @@ HLMultiplayerRules::PlayerDeath(NSClientPlayer pl)
deathAnimation = ANIM_DIEGUTSHOT;
break;
default:
bool isFacing = pl.IsFacingPosition(g_dmg_vecLocation);
bool isFacing = pl.IsFacingPosition(damageLocation);
/* we still want a change to play ANIM_DIESIMPLE */
if (random() < 0.5)
@ -166,11 +171,10 @@ HLMultiplayerRules::PlayerDeath(NSClientPlayer pl)
if (pl.IsCrouching()) {
newCorpse.SetSize(VEC_HULL_MIN, [16, 16, -16]);
}
#endif
}
/* now let's make the real client invisible */
pl.SetTakedamage(DAMAGE_NO);
pl.MakeInvulnerable();
pl.gflags &= ~GF_FLASHLIGHT;
pl.gflags &= ~GF_EGONBEAM;
@ -192,14 +196,8 @@ HLMultiplayerRules::PlayerSpawn(NSClientPlayer pl)
/* this is where the mods want to deviate */
entity spot;
pl.classname = "player";
pl.SetMaxHealth(100);
pl.SetHealth(100);
pl.SetTakedamage(DAMAGE_YES);
pl.SetSolid(SOLID_SLIDEBOX);
pl.SetMovetype(MOVETYPE_WALK);
pl.AddFlags(FL_CLIENT);
pl.viewzoom = 1.0;
EntityDef_SwitchClass(pl, "player_mp");
pl.MakePlayer();
/* player model selection */
if (IsTeamplay() == true) {
@ -229,28 +227,7 @@ HLMultiplayerRules::PlayerSpawn(NSClientPlayer pl)
playerModel = "models/player.mdl";
}
pl.SetModel(playerModel);
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
pl.ClearVelocity();
pl.gravity = __NULL__;
pl.SetFrame(1);
pl.SendFlags = UPDATE_ALL;
pl.SetInfoKey("*spec", "0");
pl.SetInfoKey("*dead", "0");
pl.SetInfoKey("*deaths", ftos(pl.deaths));
pl.SetPropData("actor_human");
pl.EnableBleeding();
LevelNewParms();
LevelDecodeParms(pl);
#if defined (VALVE) || defined (GEARBOX)
pl.GiveItem("item_suit");
pl.GiveItem("weapon_9mmhandgun");
pl.GiveItem("weapon_crowbar");
//pl.ammo_9mm = 44;
#endif
pl.SetModelindex(getmodelindex(playerModel)); /* keep OG size */
spot = Spawn_SelectRandom("info_player_deathmatch");
pl.Transport(spot.origin, spot.angles);
Client_FixAngle(pl, pl.angles);
@ -287,32 +264,3 @@ HLMultiplayerRules::HLMultiplayerRules(void)
autocvar(timelimit, 15, "Timelimit for multiplayer rounds");
autocvar(fraglimit, 15, "Points limit for multiplayer rounds");
}
void
CSEv_HLDM_Chooseteam_s(string teamName)
{
HLGameRules rules = (HLGameRules)g_grMode;
NSClientPlayer pl = (NSClientPlayer)self;
if (!teamName)
return;
if (rules.IsMultiplayer() == false)
return;
if (rules.IsTeamplay() == false)
return;
if (pl.IsDead() == true)
return;
HLMultiplayerRules mprules = (HLMultiplayerRules)rules;
int c = tokenizebyseparator(mprules.m_strTeamList, ";");
for (int i = 0; i < c; i++) {
if (argv(i) == teamName) {
pl.SetTeam((float)i + 1);
pl.SetHealth(-100);
pl.Death(pl, pl, 100i, g_vec_null, 0i);
//Damage_Apply(pl, pl, 100, 0, DMG_SKIP_ARMOR);
return;
}
}
}

View file

@ -21,11 +21,11 @@ HLSingleplayerRules::IsMultiplayer(void)
}
void
HLSingleplayerRules::PlayerDeath(NSClientPlayer pl)
HLSingleplayerRules::PlayerDeath(NSClientPlayer pl, NSActor attacker, NSDict damageDecl)
{
pl.SetMovetype(MOVETYPE_NONE);
pl.SetSolid(SOLID_NOT);
pl.SetTakedamage(DAMAGE_NO);
pl.MakeInvulnerable();
pl.SetHealth(0);
pl.StartSoundDef("Player.Death", CHAN_AUTO, true);
@ -63,7 +63,7 @@ HLSingleplayerRules::PlayerSpawn(NSClientPlayer pl)
pl.classname = "player";
pl.SetHealth(100);
pl.SetMaxHealth(100);
pl.SetTakedamage(DAMAGE_YES);
pl.MakeVulnerable();
pl.SetSolid(SOLID_SLIDEBOX);
pl.SetMovetype(MOVETYPE_WALK);
pl.AddFlags(FL_CLIENT);

View file

@ -1,6 +1,6 @@
#pragma target fte_5768
//#pragma flag enable assumeint
#pragma progs_dat "../../zpak001.pk3dir/progs.dat"
#pragma progs_dat "../../progs.dat"
#define QWSSQC
#define SERVER

View file

@ -17,10 +17,13 @@
void
Game_InitRules(void)
{
Player_Precache();
FX_Corpse_Init();
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
g_grMode = spawn(HLSingleplayerRules);
g_grMode = NSGameRules::InitFromProgs("maps/singleplayer.dat");
} else {
g_grMode = spawn(HLMultiplayerRules);
g_grMode = NSGameRules::InitFromProgs("maps/mp/gametypes/dm.dat");
}
}
@ -30,9 +33,6 @@ Game_Worldspawn(void)
Sound_Precache("Player.FlashLightOff");
Sound_Precache("Player.FlashLightOn");
Sound_Precache("item_weaponbox.Pickup");
precache_model("models/player.mdl");
precache_model("models/w_weaponbox.mdl");
Player_Precache();
FX_Corpse_Init();
}

View file

@ -60,7 +60,7 @@ FX_Corpse_Spawn(NSClientPlayer pl, float anim)
NSRenderableEntity body_next = (NSRenderableEntity)FX_Corpse_Next();
body_next.SetMovetype(MOVETYPE_BOUNCE);
body_next.SetSolid(SOLID_CORPSE);
body_next.SetModel(pl.GetModel());
body_next.SetModelindex(pl.GetModelindex());
if (pl.IsCrouching()) {
body_next.SetOrigin(pl.GetOrigin() + [0,0,32]);
@ -75,6 +75,7 @@ FX_Corpse_Spawn(NSClientPlayer pl, float anim)
body_next.ScheduleThink(FX_Corpse_Update, 0.0f);
body_next.colormap = pl.colormap;
body_next.frame1time = 0.0f;
printf("CORPSE SPAWNED: modelindex %d; origin: %v\n", body_next.modelindex, body_next.origin);
return (entity)body_next;
}
#endif

View file

@ -3,11 +3,11 @@
../../../valve/src/shared/events.h
../../../valve/src/shared/flags.h
../../../valve/src/shared/skeleton.h
../../../valve/src/shared/fx_corpse.qc
../../../valve/src/shared/player.qc
../../../valve/src/shared/animations.qc
../../../valve/src/shared/fx_blood.qc
../../../valve/src/shared/fx_gaussbeam.qc
../../../valve/src/shared/fx_corpse.qc
../../../valve/src/shared/HLGaussBeam.qc
../../../valve/src/shared/HLWeapon.qc
../../../valve/src/shared/w_tripmine.qc

View file

@ -45,6 +45,7 @@ class HLPlayer:NSClientPlayer
virtual void UpdateAliveCam(void);
virtual void ClientInputFrame(void);
#else
virtual void Death(entity, entity, int, vector, int);
virtual void EvaluateEntity(void);
virtual float SendEntity(entity, float);
virtual void Save(float);
@ -339,6 +340,52 @@ HLPlayer::EvaluateEntity(void)
}
void
HLPlayer::Death(entity inflictor, entity attacker, int damagePoints, vector dir, int location)
{
/* either gib, or make a corpse */
if (GetHealth()< -50) {
vector gibDir = vectoangles(GetOrigin() - attacker.origin);
float gibStrength = damagePoints * 2.0f;
BreakModel_Entity(this, gibDir, gibStrength);
} else {
float deathAnimation = ANIM_DIESIMPLE;
switch (location) {
case BODY_HEAD:
deathAnimation = ANIM_DIEHEADSHOT;
break;
case BODY_CHEST:
deathAnimation = ANIM_DIESPIN;
break;
case BODY_STOMACH:
deathAnimation = ANIM_DIEGUTSHOT;
break;
default:
bool isFacing = IsFacingPosition(GetOrigin() + (dir * 128));
/* we still want a change to play ANIM_DIESIMPLE */
if (random() < 0.5)
if (isFacing == false) {
deathAnimation = ANIM_DIEFORWARD;
} else {
deathAnimation = random() < 0.5 ? ANIM_DIEBACKWARDS1 : ANIM_DIEBACKWARDS1;
}
break;
}
NSEntity newCorpse = (NSEntity)FX_Corpse_Spawn(this, deathAnimation);
/* if we were crouching, adjust the bbox (thx 2 lack of crouch death animation) */
if (IsCrouching()) {
newCorpse.SetSize(VEC_HULL_MIN, [16, 16, -16]);
}
}
super::Death(inflictor, attacker, damagePoints, dir, location);
}
/*
=================
HLPlayer::SendEntity

View file

@ -84,7 +84,7 @@ HLTripmine::Spawned(void)
{
super::Spawned();
SetTakedamage(DAMAGE_NO);
MakeInvulnerable();
SetSolid(SOLID_NOT);
SetMovetype(MOVETYPE_NONE);
SetSize([-8,-8,-8], [8,8,8]);
@ -105,7 +105,7 @@ HLTripmine::Death(entity inflictor, entity attacker, int damage, vector dir, int
float explosionRadius = explosionDamage * 2.5f;
/* This is to prevent infinite loops in Damage_Radius */
SetTakedamage(DAMAGE_NO);
MakeInvulnerable();
pointparticles(particleeffectnum("fx_explosion.main"), GetOrigin(), [0,0,0], 1);
@ -130,7 +130,7 @@ HLTripmine::Ready(void)
/* Laser calibrated to N units! */
m_vecEndPos = trace_endpos;
SetHealth(1);
SetTakedamage(DAMAGE_YES);
MakeVulnerable();
StartSoundDef("weapon_tripmine.activate", CHAN_WEAPON, true);
SetSolid(SOLID_BBOX);
ForceNetworkUpdate();

View file

@ -9,7 +9,6 @@ set ai_enable "1" // Disable AI behaviour when set.
set bot_aimless "0" // Bots will not set goals for themselves when set.
set bot_backspeed "133" // Bots desired maximum backwards speed.
set bot_crouch "0" // Bots are all forced to move crouched.
set bot_debug "0" // TODO: needs to be logLevel?
set bot_developer "0" // TODO: remove?
set bot_dont_shoot "0" // Bots never actually shoot.
set bot_enable "1" // Bot support enabled when set.
@ -53,6 +52,7 @@ set dev_skyscale "" // Override for the sky_camera room scale.
set dsp_soundscapes "1" // Enable the use of sound scapes.
set g_damageScale "1" // final damage scale on objects
set g_logLevel "2" // Game console log levels. 0 = None, 1 = Errors, 2 = Warnings, 3 = Extra Messages
set g_logTimestamps "0" // When 1, will print time stamps before the log message
set g_gravity "800" // Global gravity setting.

View file

@ -2,5 +2,5 @@ entityDef ammo_rpgclip
{
"inherit" "ammo_base"
"model" "models/w_rpgammo.mdl"
"inv_ammo_uranium" "1"
"inv_ammo_rocket" "1"
}

View file

@ -1,4 +1,19 @@
entityDef player
{
"spawnclass" "HLPlayer"
"spawnclass" "HLPlayer"
"health" "100"
"maxarmor" "100"
"bleeds" "1"
"propdata" "actor_human"
"armorProtection" "0.2"
"armorBonus" "0.5"
}
entityDef player_mp
{
"inherit" "player"
"ammo_9mm" "44"
"item" "item_suit"
"weapon" "weapon_crowbar,weapon_9mmhandgun"
"current_weapon" "1"
}

View file

@ -31,6 +31,7 @@ entityDef weapon_357
"hudSlot" "1"
"hudSlotPos" "1"
"weight" "15"
"killIcon" "d_357"
}
entityDef weapon_python

View file

@ -1,22 +1,22 @@
entityDef weapon_handgrenade
{
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Hand Grenade"
"editor_rotatable" "1"
"editor_color" ".3 .3 1"
"editor_mins" "-16 -16 -16"
"editor_maxs" "16 16 16"
"editor_usage" "Hand Grenade"
"editor_rotatable" "1"
"spawnclass" "HLWeapon"
"model" "models/w_grenade.mdl"
"model_view" "models/v_grenade.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
"spawnclass" "HLWeapon"
"model" "models/w_grenade.mdl"
"model_view" "models/v_grenade.mdl"
"snd_acquire" "weapon.pickup"
"snd_respawn" "item.respawn"
"inv_name" "Hand Grenade"
"inv_weapon" "weapon_handgrenade"
"inv_ammo_handgrenade" "5"
"def_onRelease" "projectile_handgrenade"
"def_onRelease" "projectile_handgrenade"
"def_explode_inhand" "env_handgrenade_explodeinhand"
"def_damage_inhand" "damage_handgrenadeSplash"
"ammoType" "ammo_handgrenade"
@ -25,17 +25,17 @@ entityDef weapon_handgrenade
"primed_fuse" "4"
"removeOnEmpty" "1"
"actIdle" "0,1"
"actDraw" "7"
"actHolster" "6"
"actFire" "2"
"actRelease" "3,4,5"
"actIdle" "0,1"
"actDraw" "7"
"actHolster" "6"
"actFire" "2"
"actRelease" "3,4,5"
// HLWeapon specific
"hudSlot" "4"
"hudSlotPos" "0"
"weight" "5"
"crosshair" "none"
"hudSlot" "4"
"hudSlotPos" "0"
"weight" "5"
"crosshair" "none"
}
entityDef projectile_handgrenade
@ -52,7 +52,6 @@ entityDef projectile_handgrenade
"snd_explode" "fx.explosion"
"snd_bounce" "weapon_handgrenade.bounce"
"decal_detonate" "ExplosionScorch"
"def_damage" "damage_handgrenadeDirect"
"def_splash_damage" "damage_handgrenadeSplash"
}
@ -67,9 +66,3 @@ entityDef damage_handgrenadeSplash
"damage" "skill:plr_hand_grenade"
"radius" "250"
}
entityDef env_handgrenade_explodeinhand
{
"spawnclass" "idAnimatedEntity"
"model" "grenadeExplosion.prt"
}

View file

@ -36,7 +36,7 @@ bind u "messagemode2"
bind v "impulse 100"
bind w "+forward"
bind x "goprone"
bind y "vote yes"
bind y "vote yes"
bind z "toggle sv_gamespeed 0.5 1"
seta brightness "0"
seta cl_chatmode "2"

View file

@ -0,0 +1,198 @@
/*
* 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 "dm.dat"
#include "../../../../../src/server/mapC.h"
entity lastSpawn;
string g_strTeamList;
const string mp_teamlist_fallback = "scientist;hgrunt";
var string autocvar_mp_teamlist = mp_teamlist_fallback;
bool
IsTeamplay(void)
{
return getCvarInt("mp_teamplay") ? (true) : (false);
}
bool
AllowFlashlight(void)
{
return getCvarInt("mp_flashlight") ? (true) : (false);
}
void
CodeCallback_StartGameType(void)
{
//MOTD_LoadDefault();
setServerInfo("scorepoints", "0");
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, ";");
}
setServerInfo("teams", itos(c));
/* initialize all dem teams */
for (int i = 0; i < c; i++) {
setServerInfo(sprintf("team_%i", i+1i), argv(i));
setServerInfo(sprintf("teamscore_%i", i+1i), "0");
}
} else {
setServerInfo("teams", "0");
}
}
void
CodeCallback_PlayerSpawn(void)
{
string playerModel;
changeClass(self, "player_mp");
if (IsTeamplay() == true) {
float teamCount = tokenizebyseparator(g_strTeamList, ";");
float playerTeam = self.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 */
sendInput(self, "SetTeam", ftos(playerTeam), self);
}
teamModel = argv(playerTeam - 1);
playerModel = sprintf("models/player/%s/%s.mdl", teamModel, teamModel);
} else {
/* interpret the 'model' InfoKey */
playerModel = getUserInfo(self, "model");
if (playerModel != "") {
playerModel = sprintf("models/player/%s/%s.mdl", playerModel, playerModel);
}
}
/* fallback is always models/player.mdl for Half-Life */
if (playerModel == "" || fileExists(playerModel) == false) {
playerModel = "models/player.mdl";
}
self.modelindex = getmodelindex(playerModel); /* keep OG size */
lastSpawn = getSpawnpoint("info_player_deathmatch");
setorigin(self, lastSpawn.origin);
}
void
CodeCallback_PlayerDisconnect(void)
{
}
bool
CodeCallback_PlayerRequestRespawn(void)
{
CodeCallback_PlayerSpawn();
return (true);
}
void
CodeCallback_PlayerDamage(entity inflictor, entity attacker)
{
}
void
CodeCallback_PlayerKilled(entity inflictor, entity attacker, string weapon)
{
obituary(self.netname, attacker.netname, weapon, "");
/* death-counter */
self.deaths++;
/* update score-counter */
if (isPlayer(attacker)) {
if (self == attacker) {
attacker.frags--;
} else {
attacker.frags++;
}
}
}
bool
CodeCallback_ClientCommand(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);
sendInput(self, "SetTeam", newTeam, self);
sendInput(self, "Damage", "1000", self);
break;
}
}
break;
default:
return (false);
}
return (true);
}
bool
CodeCallback_ImpulseCommand(float impulseNum)
{
switch (impulseNum) {
case 100:
if (AllowFlashlight() == true) {
sendInput(self, "UseItem", "item_suit", self);
}
break;
default:
return (false);
}
return (true);
}

View file

@ -0,0 +1,86 @@
/*
* 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 "singleplayer.dat"
#include "../../../src/server/mapC.h"
void
CodeCallback_StartGameType(void)
{
}
void
CodeCallback_PlayerSpawn(void)
{
changeClass(self, "player");
entity lastSpawn = getSpawnpoint("info_player_start");
setorigin(self, lastSpawn.origin);
}
bool
CodeCallback_PlayerRequestRespawn(void)
{
localcmd("load quick\n");
return (true);
}
bool
CodeCallback_ImpulseCommand(float impulseNum)
{
switch (impulseNum) {
case 100:
sendInput(self, "UseItem", "item_suit", self);
break;
case 101:
sendInput(self, "SetHealth", "100", self);
sendInput(self, "SetArmor", "100", self);
sendInput(self, "GiveItem", "item_suit", self);
sendInput(self, "GiveItem", "weapon_357", self);
sendInput(self, "GiveItem", "weapon_9mmAR", self);
sendInput(self, "GiveItem", "weapon_9mmhandgun", self);
sendInput(self, "GiveItem", "weapon_crossbow", self);
sendInput(self, "GiveItem", "weapon_crowbar", self);
sendInput(self, "GiveItem", "weapon_egon", self);
sendInput(self, "GiveItem", "weapon_gauss", self);
sendInput(self, "GiveItem", "weapon_handgrenade", self);
sendInput(self, "GiveItem", "weapon_hornetgun", self);
sendInput(self, "GiveItem", "weapon_rpg", self);
sendInput(self, "GiveItem", "weapon_satchel", self);
sendInput(self, "GiveItem", "weapon_shotgun", self);
sendInput(self, "GiveItem", "weapon_snark", self);
sendInput(self, "GiveItem", "weapon_tripmine", self);
sendInput(self, "GiveAmmo", "ammo_9mm 255", self);
sendInput(self, "GiveAmmo", "ammo_357 255", self);
sendInput(self, "GiveAmmo", "ammo_buckshot 255", self);
sendInput(self, "GiveAmmo", "ammo_bolt 255", self);
sendInput(self, "GiveAmmo", "ammo_rocket 255", self);
sendInput(self, "GiveAmmo", "ammo_uranium 255", self);
sendInput(self, "GiveAmmo", "ammo_handgrenade 255", self);
sendInput(self, "GiveAmmo", "ammo_satchel 255", self);
sendInput(self, "GiveAmmo", "ammo_tripmine 255", self);
sendInput(self, "GiveAmmo", "ammo_snark 255", self);
sendInput(self, "GiveAmmo", "ammo_hornet 255", self);
sendInput(self, "GiveAmmo", "ammo_m203_grenade 255", self);
break;
default:
return (false);
}
return (true);
}