Added support for chaptertitle worldspawn key.

Valve: Added monster_snark and monster_tripmine. Although they don't work
as such fully yet.
Pain/Death are properly part of the player class.
Added own music track networking so we can skip the looping business,
which is currently broken in the engine.
Shoved some gamerule specific stuff around so there's more shared code
between the mods.
This commit is contained in:
Marco Cawthorne 2020-03-26 23:07:13 +01:00
parent ad713d2f7e
commit 82d9027873
49 changed files with 1351 additions and 1612 deletions

View file

@ -24,9 +24,9 @@ games:
$(CC) server/tfc/progs.src
mods:
#mkdir -p ../cstrike/data.pk3dir
#$(CC) client/cstrike/progs.src
#$(CC) server/cstrike/progs.src
mkdir -p ../cstrike/data.pk3dir
##$(CC) client/cstrike.new/progs.src
##$(CC) server/cstrike.new/progs.src
mkdir -p ../scihunt/data.pk3dir
$(CC) client/scihunt/progs.src
$(CC) server/scihunt/progs.src

View file

@ -372,6 +372,10 @@ void HUD_DrawWeaponSelect(void)
}
}
void HUD_SlotSelect(int i)
{
}
var float fHUDWeaponLast;
/*

View file

@ -19,8 +19,10 @@ defs.h
../voice.c
../sound.c
../music.c
../prints.c
../util.c
../../gs-entbase/client.src
../../shared/cstrike/weaponak47.c
../../shared/cstrike/weaponaug.c
@ -64,8 +66,6 @@ defs.h
../text.c
../sentences.c
../../gs-entbase/client.src
../../shared/decals.c
../../shared/effects.c
../../shared/spraylogo.cpp

View file

@ -449,6 +449,12 @@ CSQC_Parse_Event(void)
float fHeader = readbyte();
switch (fHeader) {
case EV_MUSICTRACK:
Music_ParseTrack();
break;
case EV_MUSICLOOP:
Music_ParseLoop();
break;
case EV_OBITUARY:
Obituary_Parse();
break;

View file

@ -26,6 +26,7 @@
../../gs-entbase/client.src
../sky.c
../sound.c
../music.c
../prints.c
../voice.c
../../shared/valve/animations.h

View file

@ -26,6 +26,7 @@
../../gs-entbase/client.src
../sky.c
../sound.c
../music.c
../prints.c
../voice.c
../../shared/valve/animations.h

144
src/client/music.c Normal file
View file

@ -0,0 +1,144 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* we're forced to support a few different paths */
enum
{
MUSIC_CDSTYLE,
MUSIC_STEAMHL
};
var int autocvar_cl_musicstyle = MUSIC_CDSTYLE;
/* some installs may have the music in media/, others may be in music/ */
string
Music_GetPath(int id)
{
if (autocvar_cl_musicstyle == MUSIC_CDSTYLE) {
return sprintf("%i", id);
} else if (autocvar_cl_musicstyle == MUSIC_STEAMHL) {
/* this doesn't happen often enough for it to be in RAM all the time */
switch (id) {
case 2:
return "media/Half-Life01.mp3";
break;
case 3:
return "media/Prospero01.mp3";
break;
case 4:
return "media/Half-Life12.mp3";
break;
case 5:
return "media/Half-Life07.mp3";
break;
case 6:
return "media/Half-Life10.mp3";
break;
case 7:
return "media/Suspense01.mp3";
break;
case 8:
return "media/Suspense03.mp3";
break;
case 9:
return "media/Half-Life09.mp3";
break;
case 10:
return "media/Half-Life02.mp3";
break;
case 11:
return "media/Half-Life13.mp3";
break;
case 12:
return "media/Half-Life04.mp3";
break;
case 13:
return "media/Half-Life15.mp3";
break;
case 14:
return "media/Half-Life14.mp3";
break;
case 15:
return "media/Half-Life16.mp3";
break;
case 16:
return "media/Suspense02.mp3";
break;
case 17:
return "media/Half-Life03.mp3";
break;
case 18:
return "media/Half-Life08.mp3";
break;
case 19:
return "media/Prospero02.mp3";
break;
case 20:
return "media/Half-Life05.mp3";
break;
case 21:
return "media/Prospero04.mp3";
break;
case 22:
return "media/Half-Life11.mp3";
break;
case 23:
return "media/Half-Life06.mp3";
break;
case 24:
return "media/Prospero03.mp3";
break;
case 25:
return "media/Half-Life17.mp3";
break;
case 26:
return "media/Prospero05.mp3";
break;
case 27:
return "media/Suspense05.mp3";
break;
case 28:
return "media/Suspense07.mp3w";
break;
}
}
}
/* EV_MUSICTRACK */
void
Music_ParseTrack(void)
{
int track;
string path;
track = readbyte();
path = Music_GetPath(track);
dprint(sprintf("^2Music_ParseTrack:^7 Single track %i from %s\n", track, path));
localcmd(sprintf("music %s -\n", path));
}
/* EV_MUSICLOOP */
void
Music_ParseLoop(void)
{
int track;
string path;
track = readbyte();
path = Music_GetPath(track);
dprint(sprintf("^2Music_ParseTrack:^7 Looping track %i from %s\n", track, path));
localcmd(sprintf("music %s\n", path));
}

View file

@ -27,6 +27,7 @@
../sky.c
../sound.c
../music.c
../prints.c
../voice.c
../../shared/valve/animations.h

View file

@ -32,6 +32,7 @@ init.c
decore.cpp
../sky.c
../music.c
../sound.c
../prints.c
../voice.c

View file

@ -28,6 +28,7 @@
../../gs-entbase/client.src
../sky.c
../music.c
../sound.c
../prints.c
../voice.c

View file

@ -111,17 +111,14 @@ Sentences_Init(void)
} else {
/* check whether or not our keyword contains a path */
Sentences_Path(argv(i));
//Sentencens_Pitch(argv(i));
g_sentences[x].m_strSamples =
sprintf(
"%s %s%s",
g_sentences[x].m_strSamples,
g_sentences_path,
argv(i)
);
if (i == 1) {
g_sentences[x].m_strSamples = sprintf("%s%s", g_sentences_path, argv(i));
} else {
g_sentences[x].m_strSamples = sprintf("%s %s%s", g_sentences[x].m_strSamples, g_sentences_path, argv(i));
}
}
}
print(sprintf("%s\n", g_sentences[x].m_strSamples));
}
}

View file

@ -31,6 +31,7 @@ init.c
../../gs-entbase/client.src
../sky.c
../music.c
../sound.c
../prints.c
../voice.c

View file

@ -28,6 +28,7 @@
../../gs-entbase/client.src
../sky.c
../music.c
../sound.c
../sentences.c
../prints.c

View file

@ -74,7 +74,7 @@ CBaseEntity::ProcessWordQue(void)
}
sound(this, CHAN_VOICE, m_pSentenceQue[m_iSentencePos].m_strSnd, 1.0, ATTN_NORM);
print(sprintf("^2CBaseNPC: Speaking %s\n", m_pSentenceQue[m_iSentencePos].m_strSnd));
dprint(sprintf("^2CBaseEntity::ProcessWordQue^7: Speaking %s\n", m_pSentenceQue[m_iSentencePos].m_strSnd));
m_iSentencePos++;
if (m_iSentenceCount == m_iSentenceCount) {
@ -262,6 +262,6 @@ CBaseEntity_ParseSentence(void)
targ = (CBaseEntity)ent;
targ.Sentence(sentence);
} else {
print(sprintf("^1CBaseNPC_ParseSentence: Entity %d not in PVS\n", e));
print(sprintf("^1CBaseNPC_ParseSentence^7: Entity %d not in PVS\n", e));
}
}

View file

@ -41,6 +41,9 @@ void worldspawn::Initialized(void)
void worldspawn::SpawnKey(string strField, string strKey)
{
switch (strField) {
case "chaptertitle":
GameMessage_Setup(strKey);
break;
case "lf_pos":
g_vecLensPos = stov(strKey);
break;

View file

@ -54,8 +54,6 @@ CBaseNPC::Sentence(string sentence)
{
string seq = Sentences_GetSamples(sentence);
print(sprintf("^2CBaseNPC::Sentence: Attempting %s\n", seq));
if (seq == "") {
return;
}

View file

@ -49,7 +49,7 @@ void scripted_sentence::Trigger(void)
return;
}
print(sprintf("Speaking on %s\n", m_strSpeaker));
dprint(sprintf("^2scripted_sentence::Trigger^7: %s on %s\n", m_strSentence, m_strSpeaker));
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_SENTENCE);

View file

@ -37,8 +37,13 @@ void trigger_cdaudio :: Trigger ( void )
print( sprintf( "%s::Trigger: CD Track %i requested\n",
this.classname, m_iCDTrack ) );
#endif
WriteByte( MSG_ALL, 32 ); // aka SVC_CDTRACK
WriteByte( MSG_ALL, m_iCDTrack );
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_MUSICTRACK);
WriteByte(MSG_MULTICAST, m_iCDTrack);
msg_entity = world;
multicast([0,0,0], MULTICAST_ALL_R);
remove( this );
}

View file

@ -42,7 +42,8 @@ void ClientDisconnect(void)
void ClientKill(void)
{
Game_ClientKill();
player pl = (player)self;
Game_ClientKill(pl);
}
void SpectatorThink(void)
@ -60,27 +61,38 @@ void SpectatorDisconnect(void)
void PutClientInServer(void)
{
Game_PutClientInServer();
player pl;
/* make sure you never change the classname. ever. */
if (self.classname != "player") {
spawnfunc_player();
}
pl = (player)self;
Game_PutClientInServer(pl);
}
void PlayerPreThink(void)
{
Game_PlayerPreThink();
player pl = (player)self;
Game_PlayerPreThink(pl);
}
void PlayerPostThink(void)
{
Game_PlayerPostThink();
player pl = (player)self;
Game_PlayerPostThink(pl);
}
void SetNewParms(void)
{
Game_SetNewParms();
Gamerules_SetNewParms();
}
void SetChangeParms(void)
{
Game_SetChangeParms();
player pl = (player)self;
Gamerules_SetChangeParms(pl);
}
void SV_RunClientCommand(void)

View file

@ -0,0 +1,134 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* after a level-change is done we need to pick up the scraps and fill the
* info back in. */
void
Gamerules_DecodeChangeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.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;
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
parm12 = pl.ammo_9mm;
parm13 = pl.ammo_357;
parm14 = pl.ammo_buckshot;
parm15 = pl.ammo_m203_grenade;
parm16 = pl.ammo_bolt;
parm17 = pl.ammo_rocket;
parm18 = pl.ammo_uranium;
parm19 = pl.ammo_handgrenade;
parm20 = pl.ammo_satchel;
parm21 = pl.ammo_tripmine;
parm22 = pl.ammo_snark;
parm23 = pl.ammo_hornet;
parm24 = pl.glock_mag;
parm25 = pl.mp5_mag;
parm26 = pl.python_mag;
parm27 = pl.shotgun_mag;
parm28 = pl.crossbow_mag;
parm29 = pl.rpg_mag;
parm30 = pl.satchel_chg;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
}
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
entity spot;
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
if (startspot != "") {
Gamerules_DecodeChangeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
Gamerules_SetNewParms();
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
Weapons_RefreshAmmo(pl);
} else {
Gamerules_SetNewParms();
Gamerules_DecodeChangeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.ammo_9mm = 68;
Weapons_AddItem(pl, WEAPON_CROWBAR);
Weapons_AddItem(pl, WEAPON_GLOCK);
pl.g_items |= ITEM_SUIT;
}
}

View file

@ -110,6 +110,7 @@
../spawn.c
../vox.c
../../shared/valve/animations.c
../valve/gamerules.c
../valve/client.c
../client.c
../valve/server.c

View file

@ -0,0 +1,134 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* after a level-change is done we need to pick up the scraps and fill the
* info back in. */
void
Gamerules_DecodeChangeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.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;
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
parm12 = pl.ammo_9mm;
parm13 = pl.ammo_357;
parm14 = pl.ammo_buckshot;
parm15 = pl.ammo_m203_grenade;
parm16 = pl.ammo_bolt;
parm17 = pl.ammo_rocket;
parm18 = pl.ammo_uranium;
parm19 = pl.ammo_handgrenade;
parm20 = pl.ammo_satchel;
parm21 = pl.ammo_tripmine;
parm22 = pl.ammo_snark;
parm23 = pl.ammo_hornet;
parm24 = pl.glock_mag;
parm25 = pl.mp5_mag;
parm26 = pl.python_mag;
parm27 = pl.shotgun_mag;
parm28 = pl.crossbow_mag;
parm29 = pl.rpg_mag;
parm30 = pl.satchel_chg;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
}
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
entity spot;
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
if (startspot != "") {
Gamerules_DecodeChangeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
Gamerules_SetNewParms();
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
Weapons_RefreshAmmo(pl);
} else {
Gamerules_SetNewParms();
Gamerules_DecodeChangeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.ammo_9mm = 68;
Weapons_AddItem(pl, WEAPON_CROWBAR);
Weapons_AddItem(pl, WEAPON_GLOCK);
pl.g_items |= ITEM_SUIT;
}
}

View file

@ -107,6 +107,7 @@
../spawn.c
../vox.c
../../shared/valve/animations.c
../valve/gamerules.c
../valve/client.c
../client.c
../valve/server.c

View file

@ -1,321 +0,0 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_networkeverything = FALSE;
void weaponbox_spawn(player temp)
{
}
void
Game_ClientConnect(void)
{
entity a;
bprint(PRINT_HIGH, sprintf("%s connected\n", self.netname));
int playercount = 0;
for (a = world; (a = find(a, classname, "player"));) {
playercount++;
}
/* we're the first. respawn all entities? */
if (playercount == 0) {
for (a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
}
}
void
Game_ClientDisconnect(void)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", self.netname));
/* Make this unusable */
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_NONE;
self.modelindex = 0;
self.health = 0;
self.takedamage = 0;
self.SendFlags = PLAYER_MODELINDEX;
}
void
Game_ClientKill(void)
{
Damage_Apply(self, self, self.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}
void
Game_PlayerPreThink(void)
{
}
void
Game_PlayerPostThink(void)
{
player pl = (player)self;
Animation_PlayerUpdate();
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex) {
pl.SendFlags |= PLAYER_MODELINDEX;
}
if (pl.old_origin[0] != pl.origin[0]) {
pl.SendFlags |= PLAYER_ORIGIN;
}
if (pl.old_origin[1] != pl.origin[1]) {
pl.SendFlags |= PLAYER_ORIGIN;
}
if (pl.old_origin[2] != pl.origin[2]) {
pl.SendFlags |= PLAYER_ORIGIN_Z;
}
if (pl.old_angles[0] != pl.angles[0]) {
pl.SendFlags |= PLAYER_ANGLES_X;
}
if (pl.old_angles[1] != pl.angles[1]) {
pl.SendFlags |= PLAYER_ANGLES_Y;
}
if (pl.old_angles[2] != pl.angles[2]) {
pl.SendFlags |= PLAYER_ANGLES_Z;
}
if (pl.old_velocity[0] != pl.velocity[0]) {
pl.SendFlags |= PLAYER_VELOCITY;
}
if (pl.old_velocity[1] != pl.velocity[1]) {
pl.SendFlags |= PLAYER_VELOCITY;
}
if (pl.old_velocity[2] != pl.velocity[2]) {
pl.SendFlags |= PLAYER_VELOCITY_Z;
}
if (pl.old_flags != pl.flags) {
pl.SendFlags |= PLAYER_FLAGS;
}
if (pl.old_activeweapon != pl.activeweapon) {
pl.SendFlags |= PLAYER_WEAPON;
}
if (pl.old_items != pl.g_items) {
pl.SendFlags |= PLAYER_ITEMS;
}
if (pl.old_health != pl.health) {
pl.SendFlags |= PLAYER_HEALTH;
}
if (pl.old_armor != pl.armor) {
pl.SendFlags |= PLAYER_ARMOR;
}
if (pl.old_movetype != pl.movetype) {
pl.SendFlags |= PLAYER_MOVETYPE;
}
if (pl.old_viewofs != pl.view_ofs[2]) {
pl.SendFlags |= PLAYER_VIEWOFS;
}
if (pl.old_baseframe != pl.baseframe) {
pl.SendFlags |= PLAYER_BASEFRAME;
}
if (pl.old_frame != pl.frame) {
pl.SendFlags |= PLAYER_FRAME;
}
if (pl.old_a_ammo1 != pl.a_ammo1) {
pl.SendFlags |= PLAYER_AMMO1;
}
if (pl.old_a_ammo2 != pl.a_ammo2) {
pl.SendFlags |= PLAYER_AMMO2;
}
if (pl.old_a_ammo3 != pl.a_ammo3) {
pl.SendFlags |= PLAYER_AMMO3;
}
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void
Game_RunClientCommand(void)
{
Footsteps_Update();
QPhysics_Run(self);
}
void
Game_DecodeChangeParms(void)
{
player pl = (player)self;
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
}
void
Game_SetChangeParms(void)
{
player pl = (player)self;
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
}
void
Game_PutClientInServer(void)
{
if (self.classname != "player") {
spawnfunc_player();
}
player pl = (player)self;
entity spot;
pl.classname = "player";
pl.health = self.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.Pain = Player_Pain;
pl.Death = Player_Death;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(self, "*deaths", ftos(self.deaths));
if (cvar("sv_playerslots") == 1) {
Game_DecodeChangeParms();
if (startspot != "") {
setorigin(pl, Landmark_GetSpot());
} else {
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
} else {
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.g_items |= ITEM_SUIT;
}
}
void
SV_SendChat(entity sender, string msg, entity eEnt, float fType)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, fType == 0 ? EV_CHAT:EV_CHAT_TEAM);
WriteByte(MSG_MULTICAST, num_for_edict(sender) - 1);
WriteByte(MSG_MULTICAST, sender.team);
WriteString(MSG_MULTICAST, msg);
if (eEnt) {
msg_entity = eEnt;
multicast([0,0,0], MULTICAST_ONE);
} else {
multicast([0,0,0], MULTICAST_ALL);
}
localcmd(sprintf("echo [SERVER] %s: %s\n", sender.netname, msg));
}
void
Game_ParseClientCommand(string cmd)
{
tokenize(cmd);
if (argv(1) == "timeleft") {
string msg;
string timestring;
float timeleft;
timeleft = cvar("mp_timelimit") - (time / 60);
timestring = Vox_TimeToString(timeleft);
msg = sprintf("we have %s minutes remaining", timestring);
Vox_Singlecast(self, msg);
return;
}
if (argv(0) == "say") {
SV_SendChat(self, argv(1), world, 0);
return;
} else if (argv(0) == "say_team") {
entity a;
for (a = world; (a = find(a, classname, "player"));) {
if (a.team == self.team) {
SV_SendChat(self, argv(1), a, 1);
}
}
return;
}
clientcommand(self, cmd);
}
void
Game_SetNewParms(void)
{
}

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* after a level-change is done we need to pick up the scraps and fill the
* info back in. */
void
Gamerules_DecodeChangeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
}
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
entity spot;
if (cvar("sv_playerslots") == 1) {
if (startspot != "") {
Gamerules_DecodeChangeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
Gamerules_SetNewParms();
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
} else {
Gamerules_SetNewParms();
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.g_items |= ITEM_SUIT;
}
}
void weaponbox_spawn(player pl)
{
}

View file

@ -59,7 +59,8 @@
../spawn.c
../vox.c
../../shared/valve/animations.c
client.c
../poke646/gamerules.c
../valve/client.c
../client.c
../valve/server.c
../server.c

View file

@ -1,321 +0,0 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void weaponbox_spawn(player temp)
{
}
var int autocvar_sv_networkeverything = FALSE;
void
Game_ClientConnect(void)
{
entity a;
bprint(PRINT_HIGH, sprintf("%s connected\n", self.netname));
int playercount = 0;
for (a = world; (a = find(a, classname, "player"));) {
playercount++;
}
/* we're the first. respawn all entities? */
if (playercount == 0) {
for (a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
}
}
void
Game_ClientDisconnect(void)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", self.netname));
/* Make this unusable */
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_NONE;
self.modelindex = 0;
self.health = 0;
self.takedamage = 0;
self.SendFlags = PLAYER_MODELINDEX;
}
void
Game_ClientKill(void)
{
Damage_Apply(self, self, self.health, 0, DMG_SKIP_ARMOR);
}
void
Game_PlayerPreThink(void)
{
}
void
Game_PlayerPostThink(void)
{
player pl = (player)self;
Animation_PlayerUpdate();
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex) {
pl.SendFlags |= PLAYER_MODELINDEX;
}
if (pl.old_origin[0] != pl.origin[0]) {
pl.SendFlags |= PLAYER_ORIGIN;
}
if (pl.old_origin[1] != pl.origin[1]) {
pl.SendFlags |= PLAYER_ORIGIN;
}
if (pl.old_origin[2] != pl.origin[2]) {
pl.SendFlags |= PLAYER_ORIGIN_Z;
}
if (pl.old_angles[0] != pl.angles[0]) {
pl.SendFlags |= PLAYER_ANGLES_X;
}
if (pl.old_angles[1] != pl.angles[1]) {
pl.SendFlags |= PLAYER_ANGLES_Y;
}
if (pl.old_angles[2] != pl.angles[2]) {
pl.SendFlags |= PLAYER_ANGLES_Z;
}
if (pl.old_velocity[0] != pl.velocity[0]) {
pl.SendFlags |= PLAYER_VELOCITY;
}
if (pl.old_velocity[1] != pl.velocity[1]) {
pl.SendFlags |= PLAYER_VELOCITY;
}
if (pl.old_velocity[2] != pl.velocity[2]) {
pl.SendFlags |= PLAYER_VELOCITY_Z;
}
if (pl.old_flags != pl.flags) {
pl.SendFlags |= PLAYER_FLAGS;
}
if (pl.old_activeweapon != pl.activeweapon) {
pl.SendFlags |= PLAYER_WEAPON;
}
if (pl.old_items != pl.g_items) {
pl.SendFlags |= PLAYER_ITEMS;
}
if (pl.old_health != pl.health) {
pl.SendFlags |= PLAYER_HEALTH;
}
if (pl.old_armor != pl.armor) {
pl.SendFlags |= PLAYER_ARMOR;
}
if (pl.old_movetype != pl.movetype) {
pl.SendFlags |= PLAYER_MOVETYPE;
}
if (pl.old_viewofs != pl.view_ofs[2]) {
pl.SendFlags |= PLAYER_VIEWOFS;
}
if (pl.old_baseframe != pl.baseframe) {
pl.SendFlags |= PLAYER_BASEFRAME;
}
if (pl.old_frame != pl.frame) {
pl.SendFlags |= PLAYER_FRAME;
}
if (pl.old_a_ammo1 != pl.a_ammo1) {
pl.SendFlags |= PLAYER_AMMO1;
}
if (pl.old_a_ammo2 != pl.a_ammo2) {
pl.SendFlags |= PLAYER_AMMO2;
}
if (pl.old_a_ammo3 != pl.a_ammo3) {
pl.SendFlags |= PLAYER_AMMO3;
}
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void
Game_RunClientCommand(void)
{
Footsteps_Update();
QPhysics_Run(self);
}
void
Game_DecodeChangeParms(void)
{
player pl = (player)self;
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
}
void
Game_SetChangeParms(void)
{
player pl = (player)self;
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
}
void
Game_PutClientInServer(void)
{
if (self.classname != "player") {
spawnfunc_player();
}
player pl = (player)self;
entity spot;
pl.classname = "player";
pl.health = self.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.Pain = Player_Pain;
pl.Death = Player_Death;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(self, "*deaths", ftos(self.deaths));
if (cvar("sv_playerslots") == 1) {
Game_DecodeChangeParms();
if (startspot != "") {
setorigin(pl, Landmark_GetSpot());
} else {
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
} else {
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.g_items |= ITEM_SUIT;
}
}
void
SV_SendChat(entity sender, string msg, entity eEnt, float fType)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, fType == 0 ? EV_CHAT:EV_CHAT_TEAM);
WriteByte(MSG_MULTICAST, num_for_edict(sender) - 1);
WriteByte(MSG_MULTICAST, sender.team);
WriteString(MSG_MULTICAST, msg);
if (eEnt) {
msg_entity = eEnt;
multicast([0,0,0], MULTICAST_ONE);
} else {
multicast([0,0,0], MULTICAST_ALL);
}
localcmd(sprintf("echo [SERVER] %s: %s\n", sender.netname, msg));
}
void
Game_ParseClientCommand(string cmd)
{
tokenize(cmd);
if (argv(1) == "timeleft") {
string msg;
string timestring;
float timeleft;
timeleft = cvar("mp_timelimit") - (time / 60);
timestring = Vox_TimeToString(timeleft);
msg = sprintf("we have %s minutes remaining", timestring);
Vox_Singlecast(self, msg);
return;
}
if (argv(0) == "say") {
SV_SendChat(self, argv(1), world, 0);
return;
} else if (argv(0) == "say_team") {
entity a;
for (a = world; (a = find(a, classname, "player"));) {
if (a.team == self.team) {
SV_SendChat(self, argv(1), a, 1);
}
}
return;
}
clientcommand(self, cmd);
}
void
Game_SetNewParms(void)
{
}

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* after a level-change is done we need to pick up the scraps and fill the
* info back in. */
void
Gamerules_DecodeChangeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
}
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
entity spot;
if (cvar("sv_playerslots") == 1) {
if (startspot != "") {
Gamerules_DecodeChangeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
} else {
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.g_items |= ITEM_SUIT;
}
}
void weaponbox_spawn(player pl)
{
}

View file

@ -60,7 +60,8 @@ monster_human_unarmed.cpp
../spawn.c
../vox.c
../../shared/valve/animations.c
client.c
../rewolf/gamerules.c
../valve/client.c
../client.c
../valve/server.c
../server.c

View file

@ -1,270 +0,0 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void Game_ClientConnect(void)
{
bprint(PRINT_HIGH, sprintf("%s connected\n", self.netname));
int playercount = 0;
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
playercount++;
}
/* We're the first. */
if (playercount == 0) {
for (entity a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
}
}
void Game_ClientDisconnect(void)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", self.netname));
/* Make this unusable */
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_NONE;
self.modelindex = 0;
self.health = 0;
self.takedamage = 0;
self.SendFlags = 1;
}
void Game_ClientKill(void)
{
Damage_Apply(self, self, self.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}
void Game_PlayerPreThink(void)
{
}
void Game_PlayerPostThink(void)
{
player pl = (player)self;
Animation_PlayerUpdate();
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
if (pl.old_angles[0] != pl.angles[0])
pl.SendFlags |= PLAYER_ANGLES_X;
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void Game_RunClientCommand(void)
{
Footsteps_Update();
QPhysics_Run(self);
}
void Game_DecodeChangeParms(void)
{
player pl = (player)self;
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
}
void Game_SetChangeParms(void)
{
player pl = (player)self;
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
}
void Game_PutClientInServer(void)
{
if (self.classname != "player") {
spawnfunc_player();
}
player pl = (player)self;
entity spot;
pl.classname = "player";
pl.health = self.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.Pain = Player_Pain;
pl.Death = Player_Death;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(self, "*deaths", ftos(self.deaths));
if (cvar("sv_playerslots") == 1) {
Game_DecodeChangeParms();
if (startspot != "") {
setorigin(pl, Landmark_GetSpot());
} else {
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
} else {
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.g_items |= ITEM_SUIT;
SHData_GetItems();
}
}
void SV_SendChat(entity eSender, string sMessage, entity eEnt, float fType)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, fType == 0 ? EV_CHAT:EV_CHAT_TEAM);
WriteByte(MSG_MULTICAST, num_for_edict(eSender) - 1);
WriteByte(MSG_MULTICAST, eSender.team);
WriteString(MSG_MULTICAST, sMessage);
if (eEnt) {
msg_entity = eEnt;
multicast([0,0,0], MULTICAST_ONE);
} else {
multicast([0,0,0], MULTICAST_ALL);
}
}
void Game_ParseClientCommand(string cmd)
{
tokenize(cmd);
if (argv(1) == "timeleft") {
float fTimeLeft = cvar("mp_timelimit") - (time / 60);
Vox_Singlecast(self, sprintf("we have %s minutes remaining", Vox_TimeToString(fTimeLeft)));
return;
}
if (argv(0) == "say") {
localcmd(sprintf("echo [SERVER] %s: %s\n", self.netname, argv(1)));
SV_SendChat(self, argv(1), world, 0);
return;
} else if (argv(0) == "say_team") {
localcmd(sprintf("echo [TEAM %d] %s: %s\n", self.team, self.netname, argv(1)));
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
if (eFind.team == self.team) {
SV_SendChat(self, argv(1), eFind, 1);
}
}
return;
}
clientcommand(self, cmd);
}
void Game_SetNewParms(void)
{
}

View file

@ -0,0 +1,90 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* after a level-change is done we need to pick up the scraps and fill the
* info back in. */
void
Gamerules_DecodeChangeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
}
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
entity spot;
if (cvar("sv_playerslots") == 1) {
if (startspot != "") {
Gamerules_DecodeChangeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
Gamerules_SetNewParms();
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
} else {
Gamerules_SetNewParms();
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.g_items |= ITEM_SUIT;
SHData_GetItems();
}
}

View file

@ -108,7 +108,8 @@ shdata_parse.c
../vox.c
../../shared/valve/animations.c
client.c
../scihunt/gamerules.c
../valve/client.c
../client.c
server.c

View file

@ -1,279 +0,0 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_networkeverything = FALSE;
void weaponbox_spawn(player temp)
{
}
void
Game_ClientConnect(void)
{
entity a;
bprint(PRINT_HIGH, sprintf("%s connected\n", self.netname));
int playercount = 0;
for (a = world; (a = find(a, classname, "player"));) {
playercount++;
}
/* we're the first. respawn all entities? */
if (playercount == 0) {
for (a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
}
}
void
Game_ClientDisconnect(void)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", self.netname));
/* Make this unusable */
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_NONE;
self.modelindex = 0;
self.health = 0;
self.takedamage = 0;
self.SendFlags = PLAYER_MODELINDEX;
}
void
Game_ClientKill(void)
{
Damage_Apply(self, self, self.health, 0, DMG_SKIP_ARMOR);
}
void
Game_PlayerPreThink(void)
{
}
void
Game_PlayerPostThink(void)
{
player pl = (player)self;
Animation_PlayerUpdate();
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex) {
pl.SendFlags |= PLAYER_MODELINDEX;
}
if (pl.old_origin[0] != pl.origin[0]) {
pl.SendFlags |= PLAYER_ORIGIN;
}
if (pl.old_origin[1] != pl.origin[1]) {
pl.SendFlags |= PLAYER_ORIGIN;
}
if (pl.old_origin[2] != pl.origin[2]) {
pl.SendFlags |= PLAYER_ORIGIN_Z;
}
if (pl.old_angles[0] != pl.angles[0]) {
pl.SendFlags |= PLAYER_ANGLES_X;
}
if (pl.old_angles[1] != pl.angles[1]) {
pl.SendFlags |= PLAYER_ANGLES_Y;
}
if (pl.old_angles[2] != pl.angles[2]) {
pl.SendFlags |= PLAYER_ANGLES_Z;
}
if (pl.old_velocity[0] != pl.velocity[0]) {
pl.SendFlags |= PLAYER_VELOCITY;
}
if (pl.old_velocity[1] != pl.velocity[1]) {
pl.SendFlags |= PLAYER_VELOCITY;
}
if (pl.old_velocity[2] != pl.velocity[2]) {
pl.SendFlags |= PLAYER_VELOCITY_Z;
}
if (pl.old_flags != pl.flags) {
pl.SendFlags |= PLAYER_FLAGS;
}
if (pl.old_activeweapon != pl.activeweapon) {
pl.SendFlags |= PLAYER_WEAPON;
}
if (pl.old_items != pl.g_items) {
pl.SendFlags |= PLAYER_ITEMS;
}
if (pl.old_health != pl.health) {
pl.SendFlags |= PLAYER_HEALTH;
}
if (pl.old_armor != pl.armor) {
pl.SendFlags |= PLAYER_ARMOR;
}
if (pl.old_movetype != pl.movetype) {
pl.SendFlags |= PLAYER_MOVETYPE;
}
if (pl.old_viewofs != pl.view_ofs[2]) {
pl.SendFlags |= PLAYER_VIEWOFS;
}
if (pl.old_baseframe != pl.baseframe) {
pl.SendFlags |= PLAYER_BASEFRAME;
}
if (pl.old_frame != pl.frame) {
pl.SendFlags |= PLAYER_FRAME;
}
if (pl.old_a_ammo1 != pl.a_ammo1) {
pl.SendFlags |= PLAYER_AMMO1;
}
if (pl.old_a_ammo2 != pl.a_ammo2) {
pl.SendFlags |= PLAYER_AMMO2;
}
if (pl.old_a_ammo3 != pl.a_ammo3) {
pl.SendFlags |= PLAYER_AMMO3;
}
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void
Game_RunClientCommand(void)
{
Footsteps_Update();
QPhysics_Run(self);
}
void
Game_DecodeChangeParms(void)
{
player pl = (player)self;
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
}
void
Game_SetChangeParms(void)
{
player pl = (player)self;
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
}
void
Game_PutClientInServer(void)
{
player pl = (player)self;
pl.classname = "spectator";
pl.health = 0;
pl.armor = 0;
pl.takedamage = DAMAGE_NO;
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NOCLIP;
pl.SendEntity = Player_SendEntity;
pl.flags = FL_CLIENT;
pl.weapon = 0;
pl.viewzoom = 1.0f;
pl.model = 0;
setsize (pl, '-16 -16 -16', '16 16 16');
pl.view_ofs = pl.velocity = '0 0 0';
forceinfokey(pl, "*spec", "2");
Spawn_ObserverCam();
}
void
SV_SendChat(entity sender, string msg, entity eEnt, float fType)
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, fType == 0 ? EV_CHAT:EV_CHAT_TEAM);
WriteByte(MSG_MULTICAST, num_for_edict(sender) - 1);
WriteByte(MSG_MULTICAST, sender.team);
WriteString(MSG_MULTICAST, msg);
if (eEnt) {
msg_entity = eEnt;
multicast([0,0,0], MULTICAST_ONE);
} else {
multicast([0,0,0], MULTICAST_ALL);
}
localcmd(sprintf("echo [SERVER] %s: %s\n", sender.netname, msg));
}
void
Game_ParseClientCommand(string cmd)
{
tokenize(cmd);
if (argv(1) == "timeleft") {
string msg;
string timestring;
float timeleft;
timeleft = cvar("mp_timelimit") - (time / 60);
timestring = Vox_TimeToString(timeleft);
msg = sprintf("we have %s minutes remaining", timestring);
Vox_Singlecast(self, msg);
return;
}
if (argv(0) == "say") {
SV_SendChat(self, argv(1), world, 0);
return;
} else if (argv(0) == "say_team") {
entity a;
for (a = world; (a = find(a, classname, "player"));) {
if (a.team == self.team) {
SV_SendChat(self, argv(1), a, 1);
}
}
return;
}
clientcommand(self, cmd);
}
void
Game_SetNewParms(void)
{
}

127
src/server/tfc/gamerules.c Normal file
View file

@ -0,0 +1,127 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* after a level-change is done we need to pick up the scraps and fill the
* info back in. */
void
Gamerules_DecodeChangeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.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;
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
parm12 = pl.ammo_9mm;
parm13 = pl.ammo_357;
parm14 = pl.ammo_buckshot;
parm15 = pl.ammo_m203_grenade;
parm16 = pl.ammo_bolt;
parm17 = pl.ammo_rocket;
parm18 = pl.ammo_uranium;
parm19 = pl.ammo_handgrenade;
parm20 = pl.ammo_satchel;
parm21 = pl.ammo_tripmine;
parm22 = pl.ammo_snark;
parm23 = pl.ammo_hornet;
parm24 = pl.glock_mag;
parm25 = pl.mp5_mag;
parm26 = pl.python_mag;
parm27 = pl.shotgun_mag;
parm28 = pl.crossbow_mag;
parm29 = pl.rpg_mag;
parm30 = pl.satchel_chg;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
}
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
pl.classname = "spectator";
pl.health = 0;
pl.armor = 0;
pl.takedamage = DAMAGE_NO;
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NOCLIP;
pl.SendEntity = Player_SendEntity;
pl.flags = FL_CLIENT;
pl.weapon = 0;
pl.viewzoom = 1.0f;
pl.model = 0;
setsize (pl, '-16 -16 -16', '16 16 16');
pl.view_ofs = pl.velocity = '0 0 0';
forceinfokey(pl, "*spec", "2");
Spawn_ObserverCam();
}
void weaponbox_spawn(player pl)
{
}

View file

@ -63,7 +63,8 @@ info_player_teamspawn.cpp
spawn.c
../vox.c
../../shared/valve/animations.c
client.c
../tfc/gamerules.c
../valve/client.c
../client.c
../valve/server.c
../server.c

View file

@ -83,8 +83,6 @@ CSEv_TeamJoin_f(float f)
pl.armor = pl.activeweapon = pl.g_items = 0;
pl.customphysics = Empty;
pl.Pain = Player_Pain;
pl.Death = Player_Death;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(self, "*deaths", ftos(self.deaths));

View file

@ -14,8 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_networkeverything = FALSE;
void
Game_ClientConnect(void)
{
@ -52,91 +50,89 @@ Game_ClientDisconnect(void)
}
void
Game_ClientKill(void)
Game_ClientKill(player pl)
{
Damage_Apply(self, self, self.health, WEAPON_NONE, DMG_SKIP_ARMOR);
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}
void
Game_PlayerPreThink(void)
Game_PlayerPreThink(player pl)
{
}
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
Game_PlayerPostThink(void)
Game_PlayerPostThink(player pl)
{
player pl = (player)self;
Animation_PlayerUpdate();
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex) {
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
}
if (pl.old_origin[0] != pl.origin[0]) {
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
}
if (pl.old_origin[1] != pl.origin[1]) {
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
}
if (pl.old_origin[2] != pl.origin[2]) {
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
}
if (pl.old_angles[0] != pl.angles[0]) {
if (pl.old_angles[0] != pl.angles[0])
pl.SendFlags |= PLAYER_ANGLES_X;
}
if (pl.old_angles[1] != pl.angles[1]) {
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
}
if (pl.old_angles[2] != pl.angles[2]) {
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
}
if (pl.old_velocity[0] != pl.velocity[0]) {
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
}
if (pl.old_velocity[1] != pl.velocity[1]) {
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
}
if (pl.old_velocity[2] != pl.velocity[2]) {
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
}
if (pl.old_flags != pl.flags) {
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
}
if (pl.old_activeweapon != pl.activeweapon) {
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
}
if (pl.old_items != pl.g_items) {
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
}
if (pl.old_health != pl.health) {
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
}
if (pl.old_armor != pl.armor) {
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
}
if (pl.old_movetype != pl.movetype) {
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
}
if (pl.old_viewofs != pl.view_ofs[2]) {
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
}
if (pl.old_baseframe != pl.baseframe) {
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
}
if (pl.old_frame != pl.frame) {
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
}
if (pl.old_a_ammo1 != pl.a_ammo1) {
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
}
if (pl.old_a_ammo2 != pl.a_ammo2) {
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
}
if (pl.old_a_ammo3 != pl.a_ammo3) {
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
}
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
@ -155,6 +151,8 @@ Game_PlayerPostThink(void)
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
/* called every input frame */
void
Game_RunClientCommand(void)
{
@ -162,136 +160,19 @@ Game_RunClientCommand(void)
QPhysics_Run(self);
}
/* called whenever we respawn, or connect */
void
Game_SetNewParms(void)
Game_PutClientInServer(player pl)
{
parm1 =
parm2 =
parm3 =
parm4 =
parm5 =
parm6 =
parm7 =
parm8 =
parm9 =
parm10 =
parm11 =
parm12 =
parm13 =
parm14 =
parm15 =
parm16 =
parm17 =
parm18 =
parm19 =
parm20 =
parm21 =
parm22 =
parm23 =
parm24 =
parm25 =
parm26 =
parm27 =
parm28 =
parm29 =
parm30 = 0;
}
void
Game_DecodeChangeParms(void)
{
player pl = (player)self;
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.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;
}
void
Game_SetChangeParms(void)
{
player pl = (player)self;
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
parm12 = pl.ammo_9mm;
parm13 = pl.ammo_357;
parm14 = pl.ammo_buckshot;
parm15 = pl.ammo_m203_grenade;
parm16 = pl.ammo_bolt;
parm17 = pl.ammo_rocket;
parm18 = pl.ammo_uranium;
parm19 = pl.ammo_handgrenade;
parm20 = pl.ammo_satchel;
parm21 = pl.ammo_tripmine;
parm22 = pl.ammo_snark;
parm23 = pl.ammo_hornet;
parm24 = pl.glock_mag;
parm25 = pl.mp5_mag;
parm26 = pl.python_mag;
parm27 = pl.shotgun_mag;
parm28 = pl.crossbow_mag;
parm29 = pl.rpg_mag;
parm30 = pl.satchel_chg;
}
void
Game_PutClientInServer(void)
{
if (self.classname != "player") {
spawnfunc_player();
}
player pl = (player)self;
entity spot;
pl.classname = "player";
pl.health = self.max_health = 100;
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
@ -309,41 +190,16 @@ Game_PutClientInServer(void)
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.Pain = Player_Pain;
pl.Death = Player_Death;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(self, "*deaths", ftos(self.deaths));
forceinfokey(pl, "*deaths", ftos(pl.deaths));
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
Game_DecodeChangeParms();
if (startspot != "") {
setorigin(pl, Landmark_GetSpot());
} else {
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
Weapons_RefreshAmmo(pl);
} else {
Game_SetNewParms();
Game_DecodeChangeParms();
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.ammo_9mm = 68;
Weapons_AddItem(pl, WEAPON_CROWBAR);
Weapons_AddItem(pl, WEAPON_GLOCK);
pl.g_items |= ITEM_SUIT;
}
/* this is where the mods want to deviate */
Gamerules_Spawn(pl);
}
/* custom chat packet */
void
SV_SendChat(entity sender, string msg, entity eEnt, float fType)
{
@ -362,6 +218,7 @@ SV_SendChat(entity sender, string msg, entity eEnt, float fType)
localcmd(sprintf("echo [SERVER] %s: %s\n", sender.netname, msg));
}
/* client cmd overrides happen here */
void
Game_ParseClientCommand(string cmd)
{

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
.string chaptertitle;
/* after a level-change is done we need to pick up the scraps and fill the
* info back in. */
void
Gamerules_DecodeChangeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
g_landmarkpos[2] = parm3;
pl.angles[0] = parm4;
pl.angles[1] = parm5;
pl.angles[2] = parm6;
pl.velocity[0] = parm7;
pl.velocity[1] = parm8;
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.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;
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
parm3 = g_landmarkpos[2];
parm4 = pl.angles[0];
parm5 = pl.angles[1];
parm6 = pl.angles[2];
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm10 = pl.g_items;
parm11 = pl.activeweapon;
parm12 = pl.ammo_9mm;
parm13 = pl.ammo_357;
parm14 = pl.ammo_buckshot;
parm15 = pl.ammo_m203_grenade;
parm16 = pl.ammo_bolt;
parm17 = pl.ammo_rocket;
parm18 = pl.ammo_uranium;
parm19 = pl.ammo_handgrenade;
parm20 = pl.ammo_satchel;
parm21 = pl.ammo_tripmine;
parm22 = pl.ammo_snark;
parm23 = pl.ammo_hornet;
parm24 = pl.glock_mag;
parm25 = pl.mp5_mag;
parm26 = pl.python_mag;
parm27 = pl.shotgun_mag;
parm28 = pl.crossbow_mag;
parm29 = pl.rpg_mag;
parm30 = pl.satchel_chg;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
}
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
entity spot;
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
if (startspot != "") {
Gamerules_DecodeChangeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
Gamerules_SetNewParms();
spot = find(world, classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
}
Weapons_RefreshAmmo(pl);
} else {
Gamerules_SetNewParms();
Gamerules_DecodeChangeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.fixangle = TRUE;
pl.ammo_9mm = 68;
Weapons_AddItem(pl, WEAPON_CROWBAR);
Weapons_AddItem(pl, WEAPON_GLOCK);
pl.g_items |= ITEM_SUIT;
}
}

View file

@ -21,30 +21,56 @@ Baby Headcrab
*/
enum {
BHCB_IDLE,
BHCB_IDLE2,
BHCB_IDLE3,
BHCB_WALK,
BHCB_RUN,
BHCB_ANGRY,
BHCB_FLINCH,
BHCB_DIEBACK,
BHCB_LEFT,
BHCB_RIGHT,
BHCB_JUMP,
BHCB_JUMP2,
BHCB_JUMP3
BHC_IDLE,
BHC_IDLE2,
BHC_IDLE3,
BHC_WALK,
BHC_RUN,
BHC_ANGRY,
BHC_FLINCH,
BHC_DIEBACK,
BHC_LEFT,
BHC_RIGHT,
BHC_JUMP,
BHC_JUMP2,
BHC_JUMP3
};
class monster_babycrab:CBaseMonster
class monster_babycrab:monster_headcrab
{
void() monster_babycrab;
virtual void(void) Respawn;
};
void monster_babycrab::monster_babycrab(void)
void
monster_babycrab::Respawn(void)
{
CBaseMonster::Respawn();
frame = BHC_IDLE;
}
void
monster_babycrab::monster_babycrab(void)
{
for (int i = 0; i < hc_sndattack.length; i++) {
precache_sound(hc_sndattack[i]);
}
for (int i = 0; i < hc_snddie.length; i++) {
precache_sound(hc_snddie[i]);
}
for (int i = 0; i < hc_sndidle.length; i++) {
precache_sound(hc_sndidle[i]);
}
for (int i = 0; i < hc_sndpain.length; i++) {
precache_sound(hc_sndpain[i]);
}
for (int i = 0; i < hc_sndsee.length; i++) {
precache_sound(hc_sndsee[i]);
}
netname = "Baby Headcrab";
model = "models/baby_headcrab.mdl";
base_health = Skill_GetValue ("headcrab_health") /4;
base_mins = [-16,-16,0];
base_maxs = [16,16,36];
CBaseMonster::CBaseMonster();

View file

@ -14,45 +14,45 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void Player_Pain(int hit)
void weaponbox_spawn(player);
void player::Pain(int hit)
{
}
void weaponbox_spawn(player);
void Player_Death(int hit)
void player::Death(int hit)
{
player pl = (player)self;
weaponbox_spawn(pl);
pl.movetype = MOVETYPE_NONE;
pl.solid = SOLID_NOT;
pl.takedamage = DAMAGE_NO;
pl.flags &= ~FL_FLASHLIGHT;
pl.armor = pl.activeweapon = pl.g_items = 0;
weaponbox_spawn(this);
movetype = MOVETYPE_NONE;
solid = SOLID_NOT;
takedamage = DAMAGE_NO;
flags &= ~FL_FLASHLIGHT;
armor = activeweapon = g_items = 0;
pl.think = PutClientInServer;
pl.nextthink = time + 4.0f;
sound(pl, CHAN_AUTO, "fvox/flatline.wav", 1.0, ATTN_NORM);
think = PutClientInServer;
nextthink = time + 4.0f;
sound(this, CHAN_AUTO, "fvox/flatline.wav", 1.0, ATTN_NORM);
if (pl.health < -50) {
pl.health = 0;
Effect_GibHuman(pl.origin);
if (health < -50) {
health = 0;
Effect_GibHuman(origin);
return;
}
pl.health = 0;
health = 0;
/* Let's handle corpses on the clientside */
entity corpse = spawn();
setorigin(corpse, pl.origin + [0,0,32]);
setmodel(corpse, pl.model);
setorigin(corpse, origin + [0,0,32]);
setmodel(corpse, model);
setsize(corpse, VEC_HULL_MIN, VEC_HULL_MAX);
corpse.movetype = MOVETYPE_TOSS;
corpse.solid = SOLID_TRIGGER;
corpse.modelindex = pl.modelindex;
corpse.modelindex = modelindex;
corpse.frame = ANIM_DIESIMPLE;
corpse.angles = pl.angles;
corpse.velocity = pl.velocity;
corpse.angles = angles;
corpse.velocity = velocity;
}
/*

View file

@ -98,7 +98,8 @@ ammo.cpp
../spawn.c
../vox.c
../../shared/valve/animations.c
client.c
../valve/gamerules.c
../valve/client.c
../client.c
server.c
../server.c

View file

@ -16,6 +16,8 @@
// Network Events
enum {
EV_MUSICTRACK,
EV_MUSICLOOP,
EV_WEAPON_DRAW,
EV_WEAPON_PRIMARYATTACK,
EV_WEAPON_SECONDARYATTACK,

View file

@ -124,6 +124,9 @@ class player:CBaseEntity
int old_a_ammo1;
int old_a_ammo2;
int old_a_ammo3;
virtual void(int) Pain;
virtual void(int) Death;
#endif
};

View file

@ -123,6 +123,9 @@ class player:CBaseEntity
int old_a_ammo1;
int old_a_ammo2;
int old_a_ammo3;
virtual void(int) Pain;
virtual void(int) Death;
#endif
};

View file

@ -121,6 +121,9 @@ class player:CBaseEntity
int old_a_ammo1;
int old_a_ammo2;
int old_a_ammo3;
virtual void(int) Pain;
virtual void(int) Death;
#endif
};

View file

@ -115,5 +115,8 @@ class player:CBaseEntity
int old_a_ammo1;
int old_a_ammo2;
int old_a_ammo3;
virtual void(int) Pain;
virtual void(int) Death;
#endif
};

View file

@ -114,6 +114,9 @@ class player:CBaseEntity
int old_a_ammo1;
int old_a_ammo2;
int old_a_ammo3;
virtual void(int) Pain;
virtual void(int) Death;
#endif
};

View file

@ -24,6 +24,102 @@ enum
SNARK_THROW
};
#ifdef SSQC
class monster_snark:CBaseMonster
{
void() monster_snark;
virtual void() customphysics;
virtual void(int) Death;
virtual void(int) Pain;
};
void
monster_snark::customphysics(void)
{
input_movevalues = [250,0,0];
input_buttons = 0;
input_impulse = 0;
input_angles = self.angles;
input_timelength = frametime;
if (self.health <= 0) {
return;
}
if (self.weapon <= 0.0 && self.aiment == __NULL__) {
float shortest = 999999;
for (entity ef = world; (ef = findfloat(ef, ::movetype, MOVETYPE_WALK));) {
float len = vlen(ef.origin - self.origin);
if (ef.classname != "snark" && len < shortest && ef.health > 0) {
self.owner = __NULL__;
self.aiment = ef;
shortest = len;
}
}
}
if (self.aiment) {
self.angles = input_angles = vectoangles(self.aiment.origin - self.origin);
}
if (self.aiment && self.weapon <= 0.0) {
self.weapon = 0.5f + random();
sound(self, CHAN_VOICE, sprintf("squeek/sqk_hunt%d.wav",floor(random(1,4))), 1.0, ATTN_NORM);
input_buttons = 2;
Damage_Apply(self, world, 1, 0, DMG_GENERIC);
makevectors(self.angles);
traceline(self.origin, self.origin + (v_forward * 128), 0, self);
if (trace_ent.takedamage == DAMAGE_YES) {
float pit = 100 + random(0,10);
sound(self, CHAN_BODY, "squeek/sqk_deploy1.wav", 1.0, ATTN_NORM, pit);
Damage_Apply(trace_ent, self.goalentity, 10, WEAPON_SNARK, DMG_GENERIC);
Effect_CreateBlood(self.origin + [0,0,16], [1,0,0]);
}
if (self.aiment.health <= 0) {
self.aiment = __NULL__;
}
}
self.weapon -= frametime;
runstandardplayerphysics(self);
}
void
monster_snark::Death(int i)
{
Effect_CreateBlood(self.origin + [0,0,16], [203,183,15] / 255);
sound(self, CHAN_VOICE, "squeek/sqk_die1.wav", 1.0, ATTN_NORM);
sound(self, CHAN_BODY, "squeek/sqk_blast1.wav", 1.0, ATTN_NORM);
self.customphysics = __NULL__;
remove(self);
}
void
monster_snark::Pain(int i)
{
}
void
monster_snark::monster_snark(void)
{
netname = "Snark";
classname = "snark";
setmodel(this, "models/w_squeak.mdl");
flags |= FL_MONSTER;
solid = SOLID_BBOX;
movetype = MOVETYPE_WALK;
frame = 3; /* running like crazy. */
angles = goalentity.angles;
health = 20;
takedamage = DAMAGE_YES;
aiment = __NULL__;
weapon = 1.0f;
}
#endif
int w_snark_pickup(int new)
{
#ifdef SSQC
@ -56,84 +152,9 @@ void w_snark_holster(void)
#ifdef SSQC
void w_snark_deploy(void)
{
static void snark_ai(void)
{
input_movevalues = [250,0,0];
input_buttons = 0;
input_impulse = 0;
input_angles = self.angles;
input_timelength = frametime;
if (self.health <= 0) {
return;
}
if (self.weapon <= 0.0 && self.aiment == __NULL__) {
float shortest = 999999;
for (entity ef = world; (ef = findfloat(ef, movetype, MOVETYPE_WALK));) {
float len = vlen(ef.origin - self.origin);
if (ef.classname != "snark" && len < shortest && ef.health > 0) {
self.owner = __NULL__;
self.aiment = ef;
shortest = len;
}
}
}
if (self.aiment) {
self.angles = input_angles = vectoangles(self.aiment.origin - self.origin);
}
if (self.aiment && self.weapon <= 0.0) {
self.weapon = 0.5f + random();
sound(self, CHAN_VOICE, sprintf("squeek/sqk_hunt%d.wav",floor(random(1,4))), 1.0, ATTN_NORM);
input_buttons = 2;
Damage_Apply(self, world, 1, 0, DMG_GENERIC);
makevectors(self.angles);
traceline(self.origin, self.origin + (v_forward * 128), 0, self);
if (trace_ent.takedamage == DAMAGE_YES) {
float pit = 100 + random(0,10);
sound(self, CHAN_BODY, "squeek/sqk_deploy1.wav", 1.0, ATTN_NORM, pit);
Damage_Apply(trace_ent, self.goalentity, 10, WEAPON_SNARK, DMG_GENERIC);
Effect_CreateBlood(self.origin + [0,0,16], [1,0,0]);
}
if (self.aiment.health <= 0) {
self.aiment = __NULL__;
}
}
self.weapon -= frametime;
runstandardplayerphysics(self);
}
static void snark_die(int i) {
Effect_CreateBlood(self.origin + [0,0,16], [203,183,15] / 255);
sound(self, CHAN_VOICE, "squeek/sqk_die1.wav", 1.0, ATTN_NORM);
sound(self, CHAN_BODY, "squeek/sqk_blast1.wav", 1.0, ATTN_NORM);
self.customphysics = __NULL__;
remove(self);
}
static void snark_pain(int i) { }
CBaseEntity snark = spawn(CBaseEntity);
snark.owner = self;
snark.goalentity = self;
snark.netname = "Snark";
snark.classname = "snark";
setmodel(snark, "models/w_squeak.mdl");
monster_snark snark = spawn(monster_snark, owner: self, goalentity: self);
makevectors(self.v_angle);
setorigin(snark, self.origin + v_forward * 32);
snark.solid = SOLID_BBOX;
snark.movetype = MOVETYPE_WALK;
snark.frame = 3; /* running like crazy. */
snark.customphysics = snark_ai;
snark.angles = self.angles;
snark.health = 20;
snark.Pain = snark_pain;
snark.takedamage = DAMAGE_YES;
snark.aiment = __NULL__;
snark.Death = snark_die;
snark.weapon = 1.0f;
}
#endif

View file

@ -14,6 +14,96 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* MONSTER_TRIPMINE SEGMENT
*
* Because not being able to place it around levels would be boring.
* Some maps, such as subtransit and a few singleplayer chapters have this. */
#ifdef SSQC
class monster_tripmine:CBaseMonster
{
void() monster_tripmine;
virtual float(entity, float) SendEntity;
virtual void(int) Trip;
virtual void() Ready;
};
float
monster_tripmine::SendEntity(entity pvsent, float flags)
{
WriteByte(MSG_ENTITY, ENT_TRIPMINE);
WriteCoord(MSG_ENTITY, self.origin[0]);
WriteCoord(MSG_ENTITY, self.origin[1]);
WriteCoord(MSG_ENTITY, self.origin[2]);
WriteCoord(MSG_ENTITY, self.angles[0]);
WriteCoord(MSG_ENTITY, self.angles[1]);
WriteCoord(MSG_ENTITY, self.angles[2]);
WriteFloat(MSG_ENTITY, self.armor);
WriteByte(MSG_ENTITY, self.health);
WriteShort(MSG_ENTITY, self.modelindex);
return TRUE;
}
void
monster_tripmine::Trip(int walkthrough)
{
if (!walkthrough) {
real_owner = g_eAttacker;
}
/* This is to prevent infinite loops in Damage_Radius */
Death =
Pain = __NULL__;
takedamage = DAMAGE_NO;
Effect_CreateExplosion(origin);
Damage_Radius(origin, real_owner, 150, 150 * 2.5f, TRUE, WEAPON_TRIPMINE);
sound(this, CHAN_WEAPON, sprintf( "weapons/explode%d.wav", floor( random() * 2 ) + 3 ), 1, ATTN_NORM);
remove(this);
}
void
monster_tripmine::Ready(void)
{
makevectors(angles);
traceline(origin, origin + v_forward * 2048, FALSE, this);
if (!health) {
SendFlags = 1;
health = 1;
Death =
Pain = Trip;
takedamage = DAMAGE_YES;
solid = SOLID_BBOX;
setsize(this, [-8,-8,-8], [8,8,8]);
armor = trace_plane_dist;
sound(this, CHAN_WEAPON, "weapons/mine_activate.wav", 1.0f, ATTN_NORM);
}
if (trace_plane_dist != armor) {
Trip(1);
}
nextthink = time;
}
void
monster_tripmine::monster_tripmine(void)
{
setmodel(this, "models/v_tripmine.mdl");
setorigin(this, origin);
SendFlags = 1; /* force update */
/* ready in 4 seconds flat */
think = Ready;
nextthink = time + 4.0f;
}
#endif
/* The WEAPON_TRIPMINE code
*
* Here is where the actual 'weapon' logic happens that the player itself
* runs. It obviously won't work without MONSTER_TRIPMINE */
enum
{
TRIPMINE_IDLE1,
@ -79,66 +169,7 @@ void w_tripmine_holster(void)
}
#ifdef SSQC
void w_tripmine_trip(int walkthrough)
{
CBaseEntity mine = (CBaseEntity)self;
if (!walkthrough) {
mine.real_owner = g_eAttacker;
}
/* This is to prevent infinite loops in Damage_Radius */
mine.Death =
mine.Pain = __NULL__;
mine.takedamage = DAMAGE_NO;
Effect_CreateExplosion(mine.origin);
Damage_Radius(mine.origin, mine.real_owner, 150, 150 * 2.5f, TRUE, WEAPON_TRIPMINE);
sound(mine, CHAN_WEAPON, sprintf( "weapons/explode%d.wav", floor( random() * 2 ) + 3 ), 1, ATTN_NORM);
remove(mine);
}
void w_tripmine_ready(void)
{
CBaseEntity mine = (CBaseEntity)self;
makevectors(mine.angles);
traceline(mine.origin, mine.origin + v_forward * 2048, FALSE, mine);
if (!mine.health) {
mine.SendFlags = 1;
mine.health = 1;
mine.Death =
mine.Pain = w_tripmine_trip;
mine.takedamage = DAMAGE_YES;
mine.solid = SOLID_BBOX;
setsize(mine, [-8,-8,-8], [8,8,8]);
mine.armor = trace_plane_dist;
sound(mine, CHAN_WEAPON, "weapons/mine_activate.wav", 1, ATTN_NORM);
}
if (trace_plane_dist != mine.armor) {
w_tripmine_trip(1);
}
mine.nextthink = time;
}
#endif
#ifdef SSQC
float w_tripmine_sendentity(entity pvsent, float flags)
{
WriteByte(MSG_ENTITY, ENT_TRIPMINE);
WriteCoord(MSG_ENTITY, self.origin[0]);
WriteCoord(MSG_ENTITY, self.origin[1]);
WriteCoord(MSG_ENTITY, self.origin[2]);
WriteCoord(MSG_ENTITY, self.angles[0]);
WriteCoord(MSG_ENTITY, self.angles[1]);
WriteCoord(MSG_ENTITY, self.angles[2]);
WriteFloat(MSG_ENTITY, self.armor);
WriteByte(MSG_ENTITY, self.health);
WriteShort(MSG_ENTITY, self.modelindex);
return TRUE;
}
#else
#ifdef CSQC
.float health;
.float armor;
float w_tripmine_predraw(void)
@ -204,19 +235,11 @@ void w_tripmine_primary(void)
Weapons_ViewAnimation(TRIPMINE_FIRE2);
#else
pl.ammo_tripmine--;
entity mine = spawn();
setmodel(mine, "models/v_tripmine.mdl");
setorigin(mine, trace_endpos);
mine.angles = vectoangles( trace_plane_normal );
mine.think = w_tripmine_ready;
mine.nextthink = time + 4.0f;
mine.SendEntity = w_tripmine_sendentity;
mine.SendFlags = 1;
mine.real_owner = self;
vector ang = vectoangles( trace_plane_normal );
monster_tripmine mine = spawn(monster_tripmine, real_owner: self, angles: ang);
setorigin(mine, trace_endpos - (v_forward * 8));
sound(mine, CHAN_WEAPON, "weapons/mine_charge.wav", 1, ATTN_NORM);
sound(self, CHAN_WEAPON, "weapons/mine_deploy.wav", 1, ATTN_NORM);
sound(self, CHAN_WEAPON, "weapons/mine_deploy.wav", 1.0f, ATTN_NORM);
sound(mine, CHAN_WEAPON, "weapons/mine_charge.wav", 1.0f, ATTN_NORM);
#endif
pl.a_ammo3 = 1;