Started moving gamerule logic into classes, so we can manage seperate

modes of play better. This will be much appreciated too by anyone modding
CS to add additional gamemodes later for example.
This commit is contained in:
Marco Cawthorne 2020-04-14 03:12:09 +02:00
parent 142e6c9cf3
commit 594ba56f02
51 changed files with 2359 additions and 991 deletions

View File

@ -14,15 +14,15 @@ games:
mkdir -p ../valve/data.pk3dir
$(CC) client/valve/progs.src
$(CC) server/valve/progs.src
mkdir -p ../tfc/data.pk3dir
$(CC) client/tfc/progs.src
$(CC) server/tfc/progs.src
mkdir -p ../rewolf/data.pk3dir
$(CC) client/rewolf/progs.src
$(CC) server/rewolf/progs.src
mkdir -p ../gearbox/data.pk3dir
$(CC) client/gearbox/progs.src
$(CC) server/gearbox/progs.src
mkdir -p ../tfc/data.pk3dir
$(CC) client/tfc/progs.src
$(CC) server/tfc/progs.src
mods:
mkdir -p ../cstrike/data.pk3dir

View File

@ -51,70 +51,70 @@ Game_ConsoleCommand(void)
sendevent("WeaponDrop", "");
break;
case "glock":
sendevent("PlayerBuyWeapon", "f", WEAPON_GLOCK18);
sendevent("BuyWeapon", "f", WEAPON_GLOCK18);
break;
case "usp":
sendevent("PlayerBuyWeapon", "f", WEAPON_USP45);
sendevent("BuyWeapon", "f", WEAPON_USP45);
break;
case "p228":
sendevent("PlayerBuyWeapon", "f", WEAPON_P228);
sendevent("BuyWeapon", "f", WEAPON_P228);
break;
case "deagle":
sendevent("PlayerBuyWeapon", "f", WEAPON_DEAGLE);
sendevent("BuyWeapon", "f", WEAPON_DEAGLE);
break;
case "fn57":
sendevent("PlayerBuyWeapon", "f", WEAPON_FIVESEVEN);
sendevent("BuyWeapon", "f", WEAPON_FIVESEVEN);
break;
case "elites":
sendevent("PlayerBuyWeapon", "f", WEAPON_ELITES);
sendevent("BuyWeapon", "f", WEAPON_ELITES);
break;
case "m3":
sendevent("PlayerBuyWeapon", "f", WEAPON_M3);
sendevent("BuyWeapon", "f", WEAPON_M3);
break;
case "xm1014":
sendevent("PlayerBuyWeapon", "f", WEAPON_XM1014);
sendevent("BuyWeapon", "f", WEAPON_XM1014);
break;
case "tmp":
sendevent("PlayerBuyWeapon", "f", WEAPON_TMP);
sendevent("BuyWeapon", "f", WEAPON_TMP);
break;
case "mac10":
sendevent("PlayerBuyWeapon", "f", WEAPON_MAC10);
sendevent("BuyWeapon", "f", WEAPON_MAC10);
break;
case "mp5":
sendevent("PlayerBuyWeapon", "f", WEAPON_MP5);
sendevent("BuyWeapon", "f", WEAPON_MP5);
break;
case "ump45":
sendevent("PlayerBuyWeapon", "f", WEAPON_UMP45);
sendevent("BuyWeapon", "f", WEAPON_UMP45);
break;
case "p90":
sendevent("PlayerBuyWeapon", "f", WEAPON_P90);
sendevent("BuyWeapon", "f", WEAPON_P90);
break;
case "ak47":
sendevent("PlayerBuyWeapon", "f", WEAPON_AK47);
sendevent("BuyWeapon", "f", WEAPON_AK47);
break;
case "m4a1":
sendevent("PlayerBuyWeapon", "f", WEAPON_M4A1);
sendevent("BuyWeapon", "f", WEAPON_M4A1);
break;
case "sg552":
sendevent("PlayerBuyWeapon", "f", WEAPON_SG552);
sendevent("BuyWeapon", "f", WEAPON_SG552);
break;
case "aug":
sendevent("PlayerBuyWeapon", "f", WEAPON_AUG);
sendevent("BuyWeapon", "f", WEAPON_AUG);
break;
case "scout":
sendevent("PlayerBuyWeapon", "f", WEAPON_SCOUT);
sendevent("BuyWeapon", "f", WEAPON_SCOUT);
break;
case "sg550":
sendevent("PlayerBuyWeapon", "f", WEAPON_SG550);
sendevent("BuyWeapon", "f", WEAPON_SG550);
break;
case "awp":
sendevent("PlayerBuyWeapon", "f", WEAPON_AWP);
sendevent("BuyWeapon", "f", WEAPON_AWP);
break;
case "g3sg1":
sendevent("PlayerBuyWeapon", "f", WEAPON_G3SG1);
sendevent("BuyWeapon", "f", WEAPON_G3SG1);
break;
case "m249":
sendevent("PlayerBuyWeapon", "f", WEAPON_PARA);
sendevent("BuyWeapon", "f", WEAPON_PARA);
break;
case "buyammo1":
case "primammo":

View File

@ -83,10 +83,11 @@ Sentences_Init(void)
/* allocate memory and increase count */
#ifdef DYNAMIC_SENTENCES
g_sentences_count++;
g_sentences = memrealloc(g_sentences,
sizeof(sentences_t),
g_sentences_count,
++g_sentences_count);
x,
g_sentences_count);
#else
if (g_sentences_count + 1 >= SENTENCES_LIMIT) {
print("^1WARNING: ^7Reached limit of max sentences!\n");

View File

@ -14,7 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*QUAKED func_dustmotes (1 0 0) (-8 -8 -8) (8 8 8) ?
/*QUAKED func_dustmotes (0 .5 .8) ?
Dustmote emitting brush volume.
*/

View File

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

View File

@ -111,7 +111,7 @@ void Game_StartFrame(void)
if (!iRescueZones && iHostagesMax > 0) {
Game_CreateRescueZones();
}
if (iBuyZones == 0) {
Game_CreateBuyZones();
}

85
src/server/cstrike/buy.c Normal file
View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
int g_cstrikeWeaponPrice[] =
{
WEAPON_NONE,
WEAPON_M3,
WEAPON_XM1014,
WEAPON_MP5,
WEAPON_P90,
WEAPON_UMP45,
WEAPON_MAC10,
WEAPON_TMP,
WEAPON_AK47,
WEAPON_SG552,
WEAPON_M4A1,
WEAPON_AUG,
WEAPON_SCOUT,
WEAPON_AWP,
WEAPON_G3SG1,
WEAPON_SG550,
WEAPON_PARA,
WEAPON_USP45,
WEAPON_GLOCK18,
WEAPON_DEAGLE,
WEAPON_P228,
WEAPON_ELITES,
WEAPON_FIVESEVEN,
WEAPON_KNIFE,
WEAPON_HEGRENADE,
WEAPON_FLASHBANG,
WEAPON_SMOKEGRENADE,
WEAPON_C4BOMB
};
void
CSEv_BuyWeapon_f(float fWeapon)
{
int iWeapon;
player pl = (player)self;
iWeapon = (int)fWeapon;
if (Rules_BuyingPossible() == FALSE) {
return;
}
if (pl.team == TEAM_T) {
if (iWeapon == WEAPON_M4A1) { return; }
if (iWeapon == WEAPON_AUG) { return; }
if (iWeapon == WEAPON_SG550) { return; }
if (iWeapon == WEAPON_FIVESEVEN) { return; }
if (iWeapon == WEAPON_TMP) { return; }
} else if (pl.team == TEAM_CT) {
if (iWeapon == WEAPON_AK47) { return; }
if (iWeapon == WEAPON_SG552) { return; }
if (iWeapon == WEAPON_G3SG1) { return; }
if (iWeapon == WEAPON_ELITES) { return; }
if (iWeapon == WEAPON_MAC10) { return; }
}
if ((pl.money - g_cstrikeWeaponPrice[iWeapon]) >= 0) {
Weapons_AddItem(pl, iWeapon);
//Ammo_AutoFill(iWeapon);
//Weapon_Draw(iWeapon);
Money_AddMoney(pl, -g_cstrikeWeaponPrice[iWeapon]);
sound(pl, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE);
} else {
//centerprint(pl, "You have insufficient funds!");
}
}

View File

@ -14,190 +14,16 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
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(player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}
void
Game_PlayerPreThink(player pl)
{
}
void
Game_PlayerPostThink(player pl)
{
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;
}
if (pl.old_cs_shotmultiplier != pl.cs_shotmultiplier) {
pl.SendFlags |= PLAYER_CSSHOT;
}
if (pl.old_cs_shottime != pl.cs_shottime) {
pl.SendFlags |= PLAYER_CSSHOTTIME;
}
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;
pl.old_cs_shotmultiplier = pl.cs_shotmultiplier;
pl.old_cs_shottime = pl.cs_shottime;
}
void
Game_RunClientCommand(void)
{
player pl = (player)self;
pl.buyzone = FALSE;
Footsteps_Update();
QPhysics_Run(self);
}
void
Game_PutClientInServer(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");
entity eTarget = world;
Spawn_MakeSpectator();
Spawn_ObserverCam();
// Because we don't want to reset these when we die
Money_AddMoney(pl, autocvar_mp_startmoney);
pl.team = 0;
forceinfokey(pl, "*team", "0");
}
void
SV_SendChat(entity sender, string msg, entity eEnt, float fType)
{

View File

@ -42,9 +42,21 @@ Choices for 'team' include:
class func_buyzone:CBaseTrigger
{
virtual void(void) touch;
virtual void(void) Respawn;
};
void
func_buyzone::touch(void)
{
player pl = (player)other;
if (!(other.flags & FL_CLIENT)) {
return;
}
pl.buyzone = TRUE;
}
void
func_buyzone::Respawn(void)
{

View File

@ -92,6 +92,7 @@ Rules_BuyingPossible(void)
}
if (pl.buyzone == FALSE) {
centerprint(pl, "Sorry, you aren't in a buyzone.\n");
return FALSE;
}

View File

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

View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_playerkeepalive = TRUE;
class HLGameRules:CGameRules
{
virtual void(entity) PlayerConnect;
virtual void(entity) PlayerDisconnect;
virtual void(player) PlayerKill;
virtual void(player) PlayerPostFrame;
virtual void(void) LevelNewParms;
};
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
HLGameRules::PlayerPostFrame(player pl)
{
Animation_PlayerUpdate();
if (autocvar_sv_playerkeepalive)
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
if (pl.old_angles[0] != pl.v_angle[0])
pl.SendFlags |= PLAYER_ANGLES_X;
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_angles[0] = pl.v_angle[0];
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
pl.old_cs_shotmultiplier = pl.cs_shotmultiplier;
pl.old_cs_shottime = pl.cs_shottime;
}
void
HLGameRules::LevelNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm64 = FL_CLIENT;
}
void
HLGameRules::PlayerConnect(entity pl)
{
entity a;
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.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();
}
Nodes_Init();
}
}
void
HLGameRules::PlayerDisconnect(entity pl)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = PLAYER_MODELINDEX;
}
void
HLGameRules::PlayerKill(player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class CSMultiplayerRules:HLGameRules
{
virtual void(void) FrameStart;
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelDecodeParms;
};
void
CSMultiplayerRules::FrameStart(void)
{
if ((g_cs_alive_t + g_cs_alive_ct) == 0) {
int iInGamePlayers = 0;
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
iInGamePlayers++;
}
if ((iInGamePlayers > 0) && (g_cs_gamestate != GAME_COMMENCING && g_cs_gamestate != GAME_END)) {
Timer_Begin(2, GAME_COMMENCING);
} else if (iInGamePlayers == 0) {
g_cs_gamestate = GAME_INACTIVE;
g_cs_gametime = 0;
g_cs_roundswon_t = 0;
g_cs_roundswon_ct = 0;
g_cs_roundsplayed = 0;
} else {
Timer_Update(); // Timer that happens once players have started joining
}
} else {
Timer_Update(); // Normal gameplay timer
}
}
void
CSMultiplayerRules::LevelDecodeParms(player pl)
{
}
void
CSMultiplayerRules::PlayerSpawn(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");
entity eTarget = world;
Spawn_MakeSpectator();
Spawn_ObserverCam();
// Because we don't want to reset these when we die
Money_AddMoney(pl, autocvar_mp_startmoney);
pl.team = 0;
forceinfokey(pl, "*team", "0");
}
void weaponbox_spawn(player pl)
{
}
void
CSEv_JoinT_f(float c)
{
player pl = (player)self;
pl.charmodel = c;
CSEv_GamePlayerSpawn_f(pl.charmodel);
};
void
CSEv_JoinCT_f(float c)
{
player pl = (player)self;
pl.charmodel = c + 4;
CSEv_GamePlayerSpawn_f(pl.charmodel);
}

View File

@ -14,10 +14,18 @@
* 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. */
class CSSingleplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelChangeParms;
virtual void(player) LevelDecodeParms;
};
void
Gamerules_DecodeChangeParms(player pl)
CSSingleplayerRules::LevelDecodeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
@ -30,11 +38,17 @@ Gamerules_DecodeChangeParms(player pl)
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.flags = parm64;
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
}
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
CSSingleplayerRules::LevelChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
@ -45,46 +59,50 @@ Gamerules_SetChangeParms(player pl)
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm64 = pl.flags;
parm10 = pl.g_items;
parm11 = pl.activeweapon;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
CSSingleplayerRules::PlayerSpawn(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;
}
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
setmodel(pl, pl.model);
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* this is where the mods want to deviate */
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;
}
if (startspot != "") {
dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", startspot));
LevelDecodeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
spot = Spawn_SelectRandom("info_player_deathmatch");
LevelNewParms();
spot = find(world, ::classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.g_items |= ITEM_SUIT;
}
Client_FixAngle(pl, pl.angles);
}
void weaponbox_spawn(player pl)
{
}
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}

View File

@ -84,11 +84,18 @@
../spawn.c
../vox.c
../../shared/valve/animations.c
../gamerules.cpp
../cstrike/game_money.c
../cstrike/game_timer.c
../cstrike/game_rules.c
../cstrike/gamerules.c
../cstrike/gamerules.cpp
../cstrike/gamerules_singleplayer.cpp
../cstrike/gamerules_multiplayer.cpp
../cstrike/client.c
../cstrike/buy.c
../client.c
../cstrike/server.c
../server.c

View File

@ -14,33 +14,15 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void Game_StartFrame(void)
{
if ((g_cs_alive_t + g_cs_alive_ct) == 0) {
int iInGamePlayers = 0;
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
iInGamePlayers++;
}
if ((iInGamePlayers > 0) && (g_cs_gamestate != GAME_COMMENCING && g_cs_gamestate != GAME_END)) {
Timer_Begin(2, GAME_COMMENCING);
} else if (iInGamePlayers == 0) {
g_cs_gamestate = GAME_INACTIVE;
g_cs_gametime = 0;
g_cs_roundswon_t = 0;
g_cs_roundswon_ct = 0;
g_cs_roundsplayed = 0;
} else {
Timer_Update(); // Timer that happens once players have started joining
}
} else {
Timer_Update(); // Normal gameplay timer
}
}
float Game_ConsoleCmd(string cmd)
void
Game_InitRules(void)
{
return FALSE;
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
g_grMode = spawn(CSSingleplayerRules);
} else {
g_grMode = spawn(CSMultiplayerRules);
}
}
void Game_Worldspawn(void)

View File

@ -21,29 +21,29 @@ void main(void)
void StartFrame(void)
{
for (entity a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) {
for (entity a = world; (a = findfloat(a, ::gflags, GF_CANRESPAWN));) {
CBaseEntity ent = (CBaseEntity)a;
ent.ParentUpdate();
}
Game_StartFrame();
g_grMode.FrameStart();
Vote_Frame();
}
void ClientConnect(float csqc_active)
{
Game_ClientConnect();
g_grMode.PlayerConnect(self);
}
void ClientDisconnect(void)
{
Game_ClientDisconnect();
g_grMode.PlayerDisconnect(self);
}
void ClientKill(void)
{
player pl = (player)self;
Game_ClientKill(pl);
g_grMode.PlayerKill(pl);
}
void SpectatorThink(void)
@ -69,30 +69,30 @@ void PutClientInServer(void)
}
pl = (player)self;
Game_PutClientInServer(pl);
g_grMode.PlayerSpawn(pl);
}
void PlayerPreThink(void)
{
player pl = (player)self;
Game_PlayerPreThink(pl);
g_grMode.PlayerPreFrame(pl);
}
void PlayerPostThink(void)
{
player pl = (player)self;
Game_PlayerPostThink(pl);
g_grMode.PlayerPostFrame(pl);
}
void SetNewParms(void)
{
Gamerules_SetNewParms();
g_grMode.LevelNewParms();
}
void SetChangeParms(void)
{
player pl = (player)self;
Gamerules_SetChangeParms(pl);
g_grMode.LevelChangeParms(pl);
}
void SV_RunClientCommand(void)
@ -110,6 +110,20 @@ void SV_ParseClientCommand(string cmd)
}
void init(float prevprogs)
{
Plugin_Init();
}
void init_respawn(void)
{
for (entity a = world; (a = findfloat(a, ::gflags, GF_CANRESPAWN));) {
CBaseEntity ent = (CBaseEntity)a;
ent.Respawn();
}
remove(self);
}
void initents(void)
{
string sTemp;
@ -117,10 +131,11 @@ void init(float prevprogs)
// Let's load materials.txt because someone thought this was the best idea
filestream fileMaterial = fopen("sound/materials.txt", FILE_READ);
hashMaterials = __NULL__;
hashMaterials = hash_createtab(2, HASH_ADD);
if (fileMaterial >= 0) {
while ((sTemp = fgets(fileMaterial))) {
while ((sTemp = fgets(fileMaterial))) {
// Tokenize and just parse this stuff in
if (tokenize_console(sTemp) == 2) {
hash_add(hashMaterials, strtolower(argv(1)), str2chr(argv(0), 0));
@ -134,20 +149,7 @@ void init(float prevprogs)
}
PMove_Init();
Plugin_Init();
}
void init_respawn(void)
{
for (entity a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) {
CBaseEntity ent = (CBaseEntity)a;
ent.Respawn();
}
remove(self);
}
void initents(void)
{
precache_sound("weapons/explode3.wav");
precache_sound("weapons/explode4.wav");
precache_sound("weapons/explode5.wav");
@ -214,6 +216,7 @@ void initents(void)
precache_sound("items/flashlight1.wav");
precache_sound("common/null.wav");
Game_InitRules();
Game_Worldspawn();
Decals_Init();
Sentences_Init();
@ -241,6 +244,6 @@ void worldspawn(void)
float ConsoleCmd(string cmd)
{
return Game_ConsoleCmd(cmd);
player pl = (player)self;
return g_grMode.ConsoleCommand(pl, cmd);
}

130
src/server/gamerules.cpp Normal file
View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class CGameRules
{
void() CGameRules;
/* logic */
virtual void() FrameStart;
virtual float(player,string) ConsoleCommand;
/* client */
virtual void(entity) PlayerConnect;
virtual void(entity) PlayerDisconnect;
virtual void(player) PlayerKill;
virtual void(player) PlayerSpawn;
virtual void(player) PlayerPreFrame;
virtual void(player) PlayerPostFrame;
/* level transitions */
virtual void(void) LevelNewParms;
virtual void(player) LevelChangeParms;
/* spectator */
/*virtual void(player) SpectatorConnect;
virtual void(player) SpectatorDisconnect;
virtual void(player) SpectatorThink;*/
};
/* init */
void
CGameRules::Init(void)
{
//print("Init!\n");
}
/* logic */
void
CGameRules::FrameStart(void)
{
//print("StartFrame!\n");
}
float
CGameRules::ConsoleCommand(player pl, string cmd)
{
return FALSE;
}
/* client */
void
CGameRules::PlayerConnect(entity pl)
{
//print("ClientConnect!\n");
}
void
CGameRules::PlayerDisconnect(entity pl)
{
//print("ClientDisconnect!\n");
}
void
CGameRules::PlayerKill(player pl)
{
//print("ClientKill!\n");
}
void
CGameRules::PlayerSpawn(player pl)
{
//print("PutClientInServer!\n");
}
void
CGameRules::PlayerPreFrame(player pl)
{
//print("PlayerPreThink!\n");
}
void
CGameRules::PlayerPostFrame(player pl)
{
//print("PlayerPostThink!\n");
}
/* level transitions */
void
CGameRules::LevelNewParms(void)
{
//print("LevelNewParms!\n");
}
void
CGameRules::LevelChangeParms(player pl)
{
//print("LevelChangeParms!\n");
}
/* spectator */
/*void
CGameRules::SpectatorConnect(player pl)
{
//print("SpectatorConnect!\n");
}
void
CGameRules::SpectatorDisconnect(player pl)
{
//print("SpectatorDisconnect!\n");
}
void
CGameRules::SpectatorThink(player pl)
{
//print("SpectatorThink!\n");
}*/
void
CGameRules::CGameRules(void)
{
//print("CGameRules!\n");
}
/* our currently running mode */
CGameRules g_grMode;

View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_playerkeepalive = TRUE;
class HLGameRules:CGameRules
{
virtual void(entity) PlayerConnect;
virtual void(entity) PlayerDisconnect;
virtual void(player) PlayerKill;
virtual void(player) PlayerPostFrame;
virtual void(void) LevelNewParms;
};
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
HLGameRules::PlayerPostFrame(player pl)
{
Animation_PlayerUpdate();
if (autocvar_sv_playerkeepalive)
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
if (pl.old_angles[0] != pl.v_angle[0])
pl.SendFlags |= PLAYER_ANGLES_X;
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_angles[0] = pl.v_angle[0];
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void
HLGameRules::LevelNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm64 = FL_CLIENT;
}
void
HLGameRules::PlayerConnect(entity pl)
{
entity a;
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.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();
}
Nodes_Init();
}
}
void
HLGameRules::PlayerDisconnect(entity pl)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = PLAYER_MODELINDEX;
}
void
HLGameRules::PlayerKill(player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class HLMultiplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelDecodeParms;
};
void
HLMultiplayerRules::LevelDecodeParms(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 = ITEM_CROWBAR | ITEM_GLOCK | ITEM_SUIT;
pl.activeweapon = WEAPON_GLOCK;
pl.flags = parm64;
pl.ammo_9mm = 44;
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 = 18;
pl.mp5_mag = parm25;
pl.python_mag = parm26;
pl.shotgun_mag = parm27;
pl.crossbow_mag = parm28;
pl.rpg_mag = parm29;
pl.satchel_chg = parm30;
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
}
}
void
HLMultiplayerRules::PlayerSpawn(player pl)
{
/* this is where the mods want to deviate */
entity spot;
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
LevelNewParms();
LevelDecodeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}

View File

@ -14,10 +14,18 @@
* 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. */
class HLSingleplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelChangeParms;
virtual void(player) LevelDecodeParms;
};
void
Gamerules_DecodeChangeParms(player pl)
HLSingleplayerRules::LevelDecodeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
@ -30,6 +38,7 @@ Gamerules_DecodeChangeParms(player pl)
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.flags = parm64;
pl.ammo_9mm = parm12;
pl.ammo_357 = parm13;
@ -62,11 +71,16 @@ Gamerules_DecodeChangeParms(player pl)
pl.sniper_mag = parm37;
pl.m249_mag = parm38;
pl.sporelauncher_mag = parm39;
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
}
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
HLSingleplayerRules::LevelChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
@ -77,6 +91,7 @@ Gamerules_SetChangeParms(player pl)
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm64 = pl.flags;
parm10 = pl.g_items;
parm11 = pl.activeweapon;
parm12 = pl.ammo_9mm;
@ -111,46 +126,45 @@ Gamerules_SetChangeParms(player pl)
parm39 = pl.sporelauncher_mag;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
HLSingleplayerRules::PlayerSpawn(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 = parm31 = parm32 = parm33 = parm34 = parm35 =
parm36 = parm37 = parm39 = parm39 = 0;
}
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
setmodel(pl, pl.model);
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* this is where the mods want to deviate */
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;
}
Weapons_RefreshAmmo(pl);
if (startspot != "") {
dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", startspot));
LevelDecodeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
Gamerules_SetNewParms();
Gamerules_DecodeChangeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
LevelNewParms();
spot = find(world, ::classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.ammo_9mm = 68;
Weapons_AddItem(pl, WEAPON_CROWBAR);
Weapons_AddItem(pl, WEAPON_GLOCK);
pl.g_items |= ITEM_SUIT;
}
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
}

View File

@ -115,7 +115,11 @@
../spawn.c
../vox.c
../../shared/valve/animations.c
../valve/gamerules.c
../gamerules.cpp
../gearbox/gamerules.cpp
../gearbox/gamerules_singleplayer.cpp
../gearbox/gamerules_multiplayer.cpp
../valve/client.c
../client.c
../valve/server.c

View File

@ -1,133 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* 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;
}
Weapons_RefreshAmmo(pl);
} else {
Gamerules_SetNewParms();
Gamerules_DecodeChangeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.ammo_9mm = 68;
Weapons_AddItem(pl, WEAPON_CROWBAR);
Weapons_AddItem(pl, WEAPON_GLOCK);
pl.g_items |= ITEM_SUIT;
}
Client_FixAngle(pl, pl.angles);
}

View File

@ -112,7 +112,11 @@
../spawn.c
../vox.c
../../shared/valve/animations.c
../valve/gamerules.c
../gamerules.cpp
../valve/gamerules.cpp
../valve/gamerules_singleplayer.cpp
../valve/gamerules_multiplayer.cpp
../valve/client.c
../client.c
../valve/server.c

View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_playerkeepalive = TRUE;
class HLGameRules:CGameRules
{
virtual void(entity) PlayerConnect;
virtual void(entity) PlayerDisconnect;
virtual void(player) PlayerKill;
virtual void(player) PlayerPostFrame;
virtual void(void) LevelNewParms;
};
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
HLGameRules::PlayerPostFrame(player pl)
{
Animation_PlayerUpdate();
if (autocvar_sv_playerkeepalive)
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
if (pl.old_angles[0] != pl.v_angle[0])
pl.SendFlags |= PLAYER_ANGLES_X;
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_angles[0] = pl.v_angle[0];
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void
HLGameRules::LevelNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm64 = FL_CLIENT;
}
void
HLGameRules::PlayerConnect(entity pl)
{
entity a;
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.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();
}
Nodes_Init();
}
}
void
HLGameRules::PlayerDisconnect(entity pl)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = PLAYER_MODELINDEX;
}
void
HLGameRules::PlayerKill(player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class HLMultiplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelDecodeParms;
};
void
HLMultiplayerRules::LevelDecodeParms(player pl)
{
}
void
HLMultiplayerRules::PlayerSpawn(player pl)
{
/* this is where the mods want to deviate */
entity spot;
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
LevelNewParms();
LevelDecodeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
void weaponbox_spawn(player pl)
{
}

View File

@ -14,10 +14,18 @@
* 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. */
class HLSingleplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelChangeParms;
virtual void(player) LevelDecodeParms;
};
void
Gamerules_DecodeChangeParms(player pl)
HLSingleplayerRules::LevelDecodeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
@ -30,6 +38,7 @@ Gamerules_DecodeChangeParms(player pl)
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.flags = parm64;
pl.ammo_nail = parm12;
pl.ammo_buckshot = parm13;
@ -43,11 +52,16 @@ Gamerules_DecodeChangeParms(player pl)
pl.cmlwbr_mag = parm20;
pl.xs_mag = parm21;
pl.satchel_chg = parm22;
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
}
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
HLSingleplayerRules::LevelChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
@ -58,6 +72,7 @@ Gamerules_SetChangeParms(player pl)
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm64 = pl.flags;
parm10 = pl.g_items;
parm11 = pl.activeweapon;
parm12 = pl.ammo_nail;
@ -73,44 +88,45 @@ Gamerules_SetChangeParms(player pl)
parm22 = pl.satchel_chg;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
HLSingleplayerRules::PlayerSpawn(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;
}
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
setmodel(pl, pl.model);
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* this is where the mods want to deviate */
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.fixangle = TRUE;
}
if (startspot != "") {
dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", startspot));
LevelDecodeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
Gamerules_SetNewParms();
spot = Spawn_SelectRandom("info_player_deathmatch");
LevelNewParms();
spot = find(world, ::classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.g_items |= ITEM_SUIT;
}
Client_FixAngle(pl, pl.angles);
}
void weaponbox_spawn(player pl)
{
}
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}

View File

@ -94,7 +94,11 @@
../spawn.c
../vox.c
../../shared/valve/animations.c
gamerules.c
../gamerules.cpp
../poke646/gamerules.cpp
../poke646/gamerules_singleplayer.cpp
../poke646/gamerules_multiplayer.cpp
../valve/client.c
../client.c
../valve/server.c

View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_playerkeepalive = TRUE;
class HLGameRules:CGameRules
{
virtual void(entity) PlayerConnect;
virtual void(entity) PlayerDisconnect;
virtual void(player) PlayerKill;
virtual void(player) PlayerPostFrame;
virtual void(void) LevelNewParms;
};
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
HLGameRules::PlayerPostFrame(player pl)
{
Animation_PlayerUpdate();
if (autocvar_sv_playerkeepalive)
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
if (pl.old_angles[0] != pl.v_angle[0])
pl.SendFlags |= PLAYER_ANGLES_X;
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_angles[0] = pl.v_angle[0];
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void
HLGameRules::LevelNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm64 = FL_CLIENT;
}
void
HLGameRules::PlayerConnect(entity pl)
{
entity a;
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.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();
}
Nodes_Init();
}
}
void
HLGameRules::PlayerDisconnect(entity pl)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = PLAYER_MODELINDEX;
}
void
HLGameRules::PlayerKill(player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class HLMultiplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelDecodeParms;
};
void
HLMultiplayerRules::LevelDecodeParms(player pl)
{
}
void
HLMultiplayerRules::PlayerSpawn(player pl)
{
/* this is where the mods want to deviate */
entity spot;
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
LevelNewParms();
LevelDecodeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
void weaponbox_spawn(player pl)
{
}

View File

@ -14,10 +14,18 @@
* 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. */
class HLSingleplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelChangeParms;
virtual void(player) LevelDecodeParms;
};
void
Gamerules_DecodeChangeParms(player pl)
HLSingleplayerRules::LevelDecodeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
@ -30,11 +38,17 @@ Gamerules_DecodeChangeParms(player pl)
pl.velocity[2] = parm9;
pl.g_items = parm10;
pl.activeweapon = parm11;
pl.flags = parm64;
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
}
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
HLSingleplayerRules::LevelChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
@ -45,45 +59,50 @@ Gamerules_SetChangeParms(player pl)
parm7 = pl.velocity[0];
parm8 = pl.velocity[1];
parm9 = pl.velocity[2];
parm64 = pl.flags;
parm10 = pl.g_items;
parm11 = pl.activeweapon;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
HLSingleplayerRules::PlayerSpawn(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;
}
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
setmodel(pl, pl.model);
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* this is where the mods want to deviate */
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;
}
if (startspot != "") {
dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", startspot));
LevelDecodeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
Gamerules_SetNewParms();
spot = Spawn_SelectRandom("info_player_deathmatch");
LevelNewParms();
spot = find(world, ::classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.g_items |= ITEM_SUIT;
SHData_GetItems();
}
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
}

View File

@ -63,7 +63,11 @@ monster_human_unarmed.cpp
../spawn.c
../vox.c
../../shared/valve/animations.c
../rewolf/gamerules.c
../gamerules.cpp
../valve/gamerules.cpp
../rewolf/gamerules_singleplayer.cpp
../rewolf/gamerules_multiplayer.cpp
../valve/client.c
../client.c
../valve/server.c

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class SHMultiplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelDecodeParms;
};
void
SHMultiplayerRules::LevelDecodeParms(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 = ITEM_CROWBAR | ITEM_GLOCK | ITEM_SUIT;
pl.activeweapon = WEAPON_GLOCK;
pl.flags = parm64;
pl.ammo_9mm = 44;
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 = 18;
pl.mp5_mag = parm25;
pl.python_mag = parm26;
pl.shotgun_mag = parm27;
pl.crossbow_mag = parm28;
pl.rpg_mag = parm29;
pl.satchel_chg = parm30;
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
}
}
void
SHMultiplayerRules::PlayerSpawn(player pl)
{
/* this is where the mods want to deviate */
entity spot;
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
LevelNewParms();
LevelDecodeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
Weapons_RefreshAmmo(pl);
SHData_GetItems();
Client_FixAngle(pl, pl.angles);
}

View File

@ -109,7 +109,10 @@ shdata_parse.c
../vox.c
../../shared/valve/animations.c
../scihunt/gamerules.c
../gamerules.cpp
../valve/gamerules.cpp
../scihunt/gamerules_multiplayer.cpp
../valve/client.c
../client.c

View File

@ -14,14 +14,10 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void Game_StartFrame(void)
void
Game_InitRules(void)
{
}
float Game_ConsoleCmd(string cmd)
{
return FALSE;
g_grMode = spawn(SHMultiplayerRules);
}
void Game_Worldspawn(void)

View File

@ -72,10 +72,11 @@ Sentences_Init(void)
/* allocate memory and increase count */
#ifdef DYNAMIC_SENTENCES
g_sentences_count++;
g_sentences = memrealloc(g_sentences,
sizeof(string),
g_sentences_count,
++g_sentences_count);
x,
g_sentences_count);
#else
if (g_sentences_count + 1 >= SENTENCES_LIMIT) {
print("^1WARNING: ^7Reached limit of max sentences!\n");

View File

@ -20,13 +20,13 @@ Spawn_ObserverCam(void)
entity eTarget;
// Go find a camera if we aren't dead
entity eCamera = find(world, classname, "trigger_camera");
entity eCamera = find(world, ::classname, "trigger_camera");
if (eCamera) {
self.origin = eCamera.origin;
if (eCamera.target) {
eTarget = find(world, targetname, eCamera.target);
eTarget = find(world, ::targetname, eCamera.target);
if (eTarget) {
self.angles = vectoangles(eTarget.origin - eCamera.origin);
self.angles[0] *= -1;
@ -34,13 +34,13 @@ Spawn_ObserverCam(void)
}
} else {
// Can't find a camera? Just do this lazy thing, CS seems to do the same
eCamera = find (world, classname, "info_player_start");
eCamera = find (world, ::classname, "info_player_start");
if (eCamera) {
self.origin = eCamera.origin;
if (eCamera.target) {
eTarget = find(world, targetname, eCamera.target);
eTarget = find(world, ::targetname, eCamera.target);
if (eTarget) {
self.angles = vectoangles(eTarget.origin - eCamera.origin);
self.angles[0] *= -1;

View File

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

@ -0,0 +1,195 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_playerkeepalive = TRUE;
class TFCGameRules:CGameRules
{
virtual void(entity) PlayerConnect;
virtual void(entity) PlayerDisconnect;
virtual void(player) PlayerPostFrame;
virtual void(player) PlayerSpawn;
virtual void(player) PlayerKill;
virtual void(void) LevelNewParms;
};
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
TFCGameRules::PlayerPostFrame(player pl)
{
Animation_PlayerUpdate();
if (autocvar_sv_playerkeepalive)
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
if (pl.old_angles[0] != pl.v_angle[0])
pl.SendFlags |= PLAYER_ANGLES_X;
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_angles[0] = pl.v_angle[0];
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void
TFCGameRules::LevelNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm64 = FL_CLIENT;
}
void
TFCGameRules::PlayerConnect(entity pl)
{
entity a;
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.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();
}
Nodes_Init();
}
}
void
TFCGameRules::PlayerDisconnect(entity pl)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = PLAYER_MODELINDEX;
}
void
TFCGameRules::PlayerKill(player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}
void
TFCGameRules::PlayerSpawn(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();
}

View File

@ -66,10 +66,12 @@ info_player_teamspawn.cpp
spawn.c
../vox.c
../../shared/valve/animations.c
../tfc/gamerules.c
../gamerules.cpp
../tfc/gamerules.cpp
../valve/client.c
../client.c
../valve/server.c
../tfc/server.c
../server.c
../valve/damage.c
../traceattack.c

37
src/server/tfc/server.c Normal file
View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void
Game_InitRules(void)
{
g_grMode = spawn(TFCGameRules);
}
void
Game_Worldspawn(void)
{
Sound_Precache("ammo.pickup");
Sound_Precache("ammo.respawn");
precache_model("models/player.mdl");
precache_model("models/w_weaponbox.mdl");
precache_sound("fvox/flatline.wav");
Weapons_Init();
Player_Precache();
}
void weaponbox_spawn(player pl)
{
}

View File

@ -13,149 +13,6 @@
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_playerkeepalive = TRUE;
void
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();
}
Nodes_Init();
}
}
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(player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}
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(player pl)
{
Animation_PlayerUpdate();
if (autocvar_sv_playerkeepalive)
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
if (pl.old_angles[0] != pl.v_angle[0])
pl.SendFlags |= PLAYER_ANGLES_X;
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_angles[0] = pl.v_angle[0];
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
/* called every input frame */
void
@ -165,44 +22,6 @@ Game_RunClientCommand(void)
QPhysics_Run(self);
}
/* called whenever we respawn, or connect */
void
Game_PutClientInServer(player pl)
{
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* 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)
@ -244,7 +63,7 @@ Game_ParseClientCommand(string cmd)
return;
} else if (argv(0) == "say_team") {
entity a;
for (a = world; (a = find(a, classname, "player"));) {
for (a = world; (a = find(a, ::classname, "player"));) {
if (a.team == self.team) {
SV_SendChat(self, argv(1), a, 1);
}

View File

@ -147,7 +147,7 @@ Damage_Radius(vector org, entity attacker, float dmg, float r, int check, int w)
float diff;
vector pos;
for (entity e = world; (e = findfloat(e, takedamage, DAMAGE_YES));) {
for (entity e = world; (e = findfloat(e, ::takedamage, DAMAGE_YES));) {
pos[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0]));
pos[1] = e.absmin[1] + (0.5 * (e.absmax[1] - e.absmin[1]));
pos[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2]));

View File

@ -0,0 +1,174 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
var int autocvar_sv_playerkeepalive = TRUE;
class HLGameRules:CGameRules
{
virtual void(entity) PlayerConnect;
virtual void(entity) PlayerDisconnect;
virtual void(player) PlayerKill;
virtual void(player) PlayerPostFrame;
virtual void(void) LevelNewParms;
};
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void
HLGameRules::PlayerPostFrame(player pl)
{
Animation_PlayerUpdate();
if (autocvar_sv_playerkeepalive)
pl.SendFlags |= PLAYER_KEEPALIVE;
if (pl.old_modelindex != pl.modelindex)
pl.SendFlags |= PLAYER_MODELINDEX;
if (pl.old_origin[0] != pl.origin[0])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[1] != pl.origin[1])
pl.SendFlags |= PLAYER_ORIGIN;
if (pl.old_origin[2] != pl.origin[2])
pl.SendFlags |= PLAYER_ORIGIN_Z;
if (pl.old_angles[0] != pl.v_angle[0])
pl.SendFlags |= PLAYER_ANGLES_X;
if (pl.old_angles[1] != pl.angles[1])
pl.SendFlags |= PLAYER_ANGLES_Y;
if (pl.old_angles[2] != pl.angles[2])
pl.SendFlags |= PLAYER_ANGLES_Z;
if (pl.old_velocity[0] != pl.velocity[0])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[1] != pl.velocity[1])
pl.SendFlags |= PLAYER_VELOCITY;
if (pl.old_velocity[2] != pl.velocity[2])
pl.SendFlags |= PLAYER_VELOCITY_Z;
if (pl.old_flags != pl.flags)
pl.SendFlags |= PLAYER_FLAGS;
if (pl.old_activeweapon != pl.activeweapon)
pl.SendFlags |= PLAYER_WEAPON;
if (pl.old_items != pl.g_items)
pl.SendFlags |= PLAYER_ITEMS;
if (pl.old_health != pl.health)
pl.SendFlags |= PLAYER_HEALTH;
if (pl.old_armor != pl.armor)
pl.SendFlags |= PLAYER_ARMOR;
if (pl.old_movetype != pl.movetype)
pl.SendFlags |= PLAYER_MOVETYPE;
if (pl.old_viewofs != pl.view_ofs[2])
pl.SendFlags |= PLAYER_VIEWOFS;
if (pl.old_baseframe != pl.baseframe)
pl.SendFlags |= PLAYER_BASEFRAME;
if (pl.old_frame != pl.frame)
pl.SendFlags |= PLAYER_FRAME;
if (pl.old_a_ammo1 != pl.a_ammo1)
pl.SendFlags |= PLAYER_AMMO1;
if (pl.old_a_ammo2 != pl.a_ammo2)
pl.SendFlags |= PLAYER_AMMO2;
if (pl.old_a_ammo3 != pl.a_ammo3)
pl.SendFlags |= PLAYER_AMMO3;
pl.old_modelindex = pl.modelindex;
pl.old_origin = pl.origin;
pl.old_angles = pl.angles;
pl.old_angles[0] = pl.v_angle[0];
pl.old_velocity = pl.velocity;
pl.old_flags = pl.flags;
pl.old_activeweapon = pl.activeweapon;
pl.old_items = pl.g_items;
pl.old_health = pl.health;
pl.old_armor = pl.armor;
pl.old_movetype = pl.movetype;
pl.old_viewofs = pl.view_ofs[2];
pl.old_baseframe = pl.baseframe;
pl.old_frame = pl.frame;
pl.old_a_ammo1 = pl.a_ammo1;
pl.old_a_ammo2 = pl.a_ammo2;
pl.old_a_ammo3 = pl.a_ammo3;
}
void
HLGameRules::LevelNewParms(void)
{
parm1 = parm2 = parm3 = parm4 = parm5 = parm6 = parm7 =
parm8 = parm9 = parm10 = parm11 = parm12 = parm13 = parm14 =
parm15 = parm16 = parm17 = parm18 = parm19 = parm20 = parm21 =
parm22 = parm23 = parm24 = parm25 = parm26 = parm27 = parm28 =
parm29 = parm30 = 0;
parm64 = FL_CLIENT;
}
void
HLGameRules::PlayerConnect(entity pl)
{
entity a;
bprint(PRINT_HIGH, sprintf("%s connected\n", pl.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();
}
Nodes_Init();
}
}
void
HLGameRules::PlayerDisconnect(entity pl)
{
bprint(PRINT_HIGH, sprintf("%s disconnected\n", pl.netname));
/* Make this unusable */
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NONE;
pl.modelindex = 0;
pl.health = 0;
pl.takedamage = 0;
pl.SendFlags = PLAYER_MODELINDEX;
}
void
HLGameRules::PlayerKill(player pl)
{
Damage_Apply(pl, pl, pl.health, WEAPON_NONE, DMG_SKIP_ARMOR);
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
class HLMultiplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelDecodeParms;
};
void
HLMultiplayerRules::LevelDecodeParms(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 = ITEM_CROWBAR | ITEM_GLOCK | ITEM_SUIT;
pl.activeweapon = WEAPON_GLOCK;
pl.flags = parm64;
pl.ammo_9mm = 44;
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 = 18;
pl.mp5_mag = parm25;
pl.python_mag = parm26;
pl.shotgun_mag = parm27;
pl.crossbow_mag = parm28;
pl.rpg_mag = parm29;
pl.satchel_chg = parm30;
if (pl.flags & FL_CROUCHING) {
setsize(pl, VEC_CHULL_MIN, VEC_CHULL_MAX);
} else {
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
}
}
void
HLMultiplayerRules::PlayerSpawn(player pl)
{
/* this is where the mods want to deviate */
entity spot;
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
string mymodel = infokey(pl, "model");
if (mymodel) {
mymodel = sprintf("models/player/%s/%s.mdl", mymodel, mymodel);
if (whichpack(mymodel)) {
pl.model = mymodel;
}
}
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
LevelNewParms();
LevelDecodeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}

View File

@ -14,10 +14,18 @@
* 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. */
class HLSingleplayerRules:HLGameRules
{
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelChangeParms;
virtual void(player) LevelDecodeParms;
};
void
Gamerules_DecodeChangeParms(player pl)
HLSingleplayerRules::LevelDecodeParms(player pl)
{
g_landmarkpos[0] = parm1;
g_landmarkpos[1] = parm2;
@ -60,9 +68,8 @@ Gamerules_DecodeChangeParms(player pl)
}
}
/* prepare the client-info for level-transition */
void
Gamerules_SetChangeParms(player pl)
HLSingleplayerRules::LevelChangeParms(player pl)
{
parm1 = g_landmarkpos[0];
parm2 = g_landmarkpos[1];
@ -97,48 +104,45 @@ Gamerules_SetChangeParms(player pl)
parm30 = pl.satchel_chg;
}
/* yuck, whenever 'changelevel' does not happen. */
void
Gamerules_SetNewParms(void)
HLSingleplayerRules::PlayerSpawn(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;
pl.classname = "player";
pl.health = pl.max_health = 100;
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.viewzoom = 1.0;
pl.model = "models/player.mdl";
setmodel(pl, pl.model);
parm64 = FL_CLIENT;
}
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;
pl.SendEntity = Player_SendEntity;
pl.SendFlags = UPDATE_ALL;
pl.customphysics = Empty;
pl.iBleeds = TRUE;
forceinfokey(pl, "*spec", "0");
forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* called when the player first spawns/respawns */
void
Gamerules_Spawn(player pl)
{
/* this is where the mods want to deviate */
entity spot;
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
if (startspot != "") {
dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", 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;
}
Weapons_RefreshAmmo(pl);
if (startspot != "") {
dprint(sprintf("^3Gamerules_Spawn^7: Startspot is %s\n", startspot));
LevelDecodeParms(pl);
setorigin(pl, Landmark_GetSpot());
} else {
Gamerules_SetNewParms();
Gamerules_DecodeChangeParms(pl);
spot = Spawn_SelectRandom("info_player_deathmatch");
LevelNewParms();
spot = find(world, ::classname, "info_player_start");
setorigin(pl, spot.origin);
pl.angles = spot.angles;
pl.ammo_9mm = 68;
Weapons_AddItem(pl, WEAPON_CROWBAR);
Weapons_AddItem(pl, WEAPON_GLOCK);
pl.g_items |= ITEM_SUIT;
}
Weapons_RefreshAmmo(pl);
Client_FixAngle(pl, pl.angles);
}
}

View File

@ -67,7 +67,7 @@ void Game_Input(void)
if (self.impulse == 102) {
// Respawn all the entities
for (entity a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) {
for (entity a = world; (a = findfloat(a, ::gflags, GF_CANRESPAWN));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
caw.SendFlags |=

View File

@ -100,7 +100,11 @@ ammo.cpp
../spawn.c
../vox.c
../../shared/valve/animations.c
../valve/gamerules.c
../gamerules.cpp
../valve/gamerules.cpp
../valve/gamerules_singleplayer.cpp
../valve/gamerules_multiplayer.cpp
../valve/client.c
../client.c
server.c

View File

@ -14,17 +14,19 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void Game_StartFrame(void)
void
Game_InitRules(void)
{
print("Game_InitRules!\n");
if (cvar("sv_playerslots") == 1 || cvar("coop") == 1) {
g_grMode = spawn(HLSingleplayerRules);
} else {
g_grMode = spawn(HLMultiplayerRules);
}
}
float Game_ConsoleCmd(string cmd)
{
return FALSE;
}
void Game_Worldspawn(void)
void
Game_Worldspawn(void)
{
Sound_Precache("ammo.pickup");
Sound_Precache("ammo.respawn");

View File

@ -55,7 +55,7 @@ Vote_Reset(void)
forceinfokey(world, "votes_n", "0");
forceinfokey(world, "vote_cmd", "");
for (entity e = world; (e = find(e, classname, "player"));) {
for (entity e = world; (e = find(e, ::classname, "player"));) {
e.flags &= ~FL_VOTED;
}
}
@ -145,7 +145,7 @@ CSEv_VoteY(void)
/* HACK: Is there a better way to do this? */
float playernums = 0;
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
playernums++;
}
@ -188,7 +188,7 @@ CSEv_VoteN(void)
/* HACK: Is there a better way to do this? */
float playernums = 0;
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
playernums++;
}

View File

@ -1,3 +1,8 @@
weapon_dbs.fire
{
sample weapons/shotgn2.wav
}
weapon_sbs.cock
{
sample weapons/scock1.wav