Counter-Strike: Hostage Rescue works, Buymenu for weapons works, cleaned

up some gamemode code.
This commit is contained in:
Marco Cawthorne 2020-04-14 16:19:25 +02:00
parent 992add7dfd
commit 3e4a67367b
31 changed files with 1100 additions and 842 deletions

View file

@ -48,7 +48,7 @@ Game_ConsoleCommand(void)
/*Nightvision_Toggle();*/
break;
case "drop":
sendevent("WeaponDrop", "");
sendevent("DropWeapon", "");
break;
case "glock":
sendevent("BuyWeapon", "f", WEAPON_GLOCK18);
@ -118,32 +118,32 @@ Game_ConsoleCommand(void)
break;
case "buyammo1":
case "primammo":
sendevent("GamePlayerBuyAmmo", "f", 0);
sendevent("BuyAmmo", "f", 0);
break;
case "buyammo2":
case "secammo":
sendevent("GamePlayerBuyAmmo", "f", 1);
sendevent("BuyAmmo", "f", 1);
break;
case "vest":
sendevent("PlayerBuyEquipment", "f", 0);
sendevent("BuyEquipment", "f", 0);
break;
case "vesthelm":
sendevent("PlayerBuyEquipment", "f", 1);
sendevent("BuyEquipment", "f", 1);
break;
case "flash":
sendevent("PlayerBuyEquipment", "f", 2);
sendevent("BuyEquipment", "f", 2);
break;
case "hegren":
sendevent("PlayerBuyEquipment", "f", 3);
sendevent("BuyEquipment", "f", 3);
break;
case "vsgren":
sendevent("PlayerBuyEquipment", "f", 4);
sendevent("BuyEquipment", "f", 4);
break;
case "defuser":
sendevent("PlayerBuyEquipment", "f", 5);
sendevent("BuyEquipment", "f", 5);
break;
case "nvg":
sendevent("PlayerBuyEquipment", "f", 6);
sendevent("BuyEquipment", "f", 6);
break;
case "coverme":
sendevent("Radio", "f", RADIO_CT_COVERME);

View file

@ -24,9 +24,10 @@ Comparable to worldspawn in SSQC in that it's mostly used for precaches
void
Client_Init(float apilevel, string enginename, float engineversion)
{
registercommand("callvote");
registercommand("chooseteam");
registercommand("buy");
/* radio */
registercommand("radio1");
registercommand("radio2");
registercommand("radio3");
@ -34,18 +35,26 @@ Client_Init(float apilevel, string enginename, float engineversion)
registercommand("motd");
registercommand("drop");
registercommand("nightvision");
/* pistols */
registercommand("glock");
registercommand("usp");
registercommand("p228");
registercommand("deagle");
registercommand("fn57");
registercommand("elites");
/* shotties */
registercommand("m3");
registercommand("xm1014");
/* smg */
registercommand("tmp");
registercommand("mac10");
registercommand("mp5");
registercommand("ump45");
/* rifles */
registercommand("p90");
registercommand("ak47");
registercommand("m4a1");
@ -55,11 +64,17 @@ Client_Init(float apilevel, string enginename, float engineversion)
registercommand("sg550");
registercommand("awp");
registercommand("g3sg1");
/* lonely */
registercommand("m249");
/* ammo */
registercommand("primammo");
registercommand("buyammo1");
registercommand("secammo");
registercommand("buyammo2");
/* equipment */
registercommand("vest");
registercommand("vesthelm");
registercommand("flash");
@ -67,6 +82,8 @@ Client_Init(float apilevel, string enginename, float engineversion)
registercommand("vsgren");
registercommand("defuser");
registercommand("nvg");
/* radio */
registercommand("coverme");
registercommand("takepoint");
registercommand("holdpos");

View file

@ -35,23 +35,23 @@ TERRORIST_SELECT(int n)
{
switch (n) {
case 1:
sendevent("JoinT", "f", 1);
sendevent("JoinTeam", "f", 1);
Textmenu_Call("");
break;
case 2:
sendevent("JoinT", "f", 2);
sendevent("JoinTeam", "f", 2);
Textmenu_Call("");
break;
case 3:
sendevent("JoinT", "f", 3);
sendevent("JoinTeam", "f", 3);
Textmenu_Call("");
break;
case 4:
sendevent("JoinT", "f", 4);
sendevent("JoinTeam", "f", 4);
Textmenu_Call("");
break;
case 5:
sendevent("JoinT", "f", floor(random(1,5)));
sendevent("JoinTeam", "f", floor(random(1,5)));
Textmenu_Call("");
break;
}
@ -61,23 +61,23 @@ CT_SELECT(int n)
{
switch (n) {
case 1:
sendevent("JoinCT", "f", 1);
sendevent("JoinTeam", "f", 5);
Textmenu_Call("");
break;
case 2:
sendevent("JoinCT", "f", 2);
sendevent("JoinTeam", "f", 6);
Textmenu_Call("");
break;
case 3:
sendevent("JoinCT", "f", 3);
sendevent("JoinTeam", "f", 7);
Textmenu_Call("");
break;
case 4:
sendevent("JoinCT", "f", 4);
sendevent("JoinTeam", "f", 8);
Textmenu_Call("");
break;
case 5:
sendevent("JoinCT", "f", floor(random(1,5)));
sendevent("JoinTeam", "f", floor(random(1,5)));
Textmenu_Call("");
break;
}
@ -127,19 +127,60 @@ void
DT_BUYITEM(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 1:
sendevent("BuyEquipment", "f", 0);
break;
case 2:
sendevent("BuyEquipment", "f", 1);
break;
case 3:
sendevent("BuyEquipment", "f", 2);
break;
case 4:
sendevent("BuyEquipment", "f", 3);
break;
case 5:
sendevent("BuyEquipment", "f", 4);
break;
case 7:
sendevent("BuyEquipment", "f", 6);
break;
default:
return;
}
Textmenu_Call("");
}
void
DCT_BUYITEM(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 1:
sendevent("BuyEquipment", "f", 0);
break;
case 2:
sendevent("BuyEquipment", "f", 1);
break;
case 3:
sendevent("BuyEquipment", "f", 2);
break;
case 4:
sendevent("BuyEquipment", "f", 3);
break;
case 5:
sendevent("BuyEquipment", "f", 4);
break;
case 6:
sendevent("BuyEquipment", "f", 5);
break;
case 7:
sendevent("BuyEquipment", "f", 6);
break;
default:
return;
}
Textmenu_Call("");
}
/* Handguns */
@ -147,19 +188,51 @@ void
T_BUYPISTOL(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 1:
sendevent("BuyWeapon", "f", WEAPON_USP45);
break;
case 2:
sendevent("BuyWeapon", "f", WEAPON_GLOCK18);
break;
case 3:
sendevent("BuyWeapon", "f", WEAPON_DEAGLE);
break;
case 4:
sendevent("BuyWeapon", "f", WEAPON_P228);
break;
case 5:
sendevent("BuyWeapon", "f", WEAPON_ELITES);
break;
default:
return;
}
Textmenu_Call("");
}
void
CT_BUYPISTOL(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 1:
sendevent("BuyWeapon", "f", WEAPON_USP45);
break;
case 2:
sendevent("BuyWeapon", "f", WEAPON_GLOCK18);
break;
case 3:
sendevent("BuyWeapon", "f", WEAPON_DEAGLE);
break;
case 4:
sendevent("BuyWeapon", "f", WEAPON_P228);
break;
case 6:
sendevent("BuyWeapon", "f", WEAPON_FIVESEVEN);
break;
default:
return;
}
Textmenu_Call("");
}
/* Shotguns */
@ -167,10 +240,17 @@ void
BUYSHOTGUN(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 1:
sendevent("BuyWeapon", "f", WEAPON_M3);
break;
case 2:
sendevent("BuyWeapon", "f", WEAPON_XM1014);
break;
default:
return;
}
Textmenu_Call("");
}
/* Rifles, Sniper */
@ -178,19 +258,54 @@ void
T_BUYRIFLE(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 1:
sendevent("BuyWeapon", "f", WEAPON_AK47);
break;
case 2:
sendevent("BuyWeapon", "f", WEAPON_SG552);
break;
case 5:
sendevent("BuyWeapon", "f", WEAPON_SCOUT);
break;
case 6:
sendevent("BuyWeapon", "f", WEAPON_AWP);
break;
case 7:
sendevent("BuyWeapon", "f", WEAPON_G3SG1);
break;
default:
return;
}
Textmenu_Call("");
}
void
CT_BUYRIFLE(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 3:
sendevent("BuyWeapon", "f", WEAPON_M4A1);
break;
case 4:
sendevent("BuyWeapon", "f", WEAPON_AUG);
break;
case 5:
sendevent("BuyWeapon", "f", WEAPON_SCOUT);
break;
case 6:
sendevent("BuyWeapon", "f", WEAPON_AWP);
break;
case 7:
sendevent("BuyWeapon", "f", WEAPON_G3SG1);
break;
case 8:
sendevent("BuyWeapon", "f", WEAPON_SG550);
break;
default:
return;
}
Textmenu_Call("");
}
/* SMGs */
@ -198,19 +313,45 @@ void
T_BUYSUBMACHINEGUN(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 1:
sendevent("BuyWeapon", "f", WEAPON_MP5);
break;
case 3:
sendevent("BuyWeapon", "f", WEAPON_P90);
break;
case 4:
sendevent("BuyWeapon", "f", WEAPON_MAC10);
break;
case 5:
sendevent("BuyWeapon", "f", WEAPON_UMP45);
break;
default:
return;
}
Textmenu_Call("");
}
void
CT_BUYSUBMACHINEGUN(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 1:
sendevent("BuyWeapon", "f", WEAPON_MP5);
break;
case 2:
sendevent("BuyWeapon", "f", WEAPON_TMP);
break;
case 3:
sendevent("BuyWeapon", "f", WEAPON_P90);
break;
case 5:
sendevent("BuyWeapon", "f", WEAPON_UMP45);
break;
default:
return;
}
Textmenu_Call("");
}
/* Big and heavy */
@ -218,10 +359,14 @@ void
BUYMACHINEGUN(int n)
{
switch (n) {
default:
Textmenu_Call("");
case 1:
sendevent("BuyWeapon", "f", WEAPON_PARA);
break;
default:
return;
}
Textmenu_Call("");
}
/* Radio */

View file

@ -20,6 +20,7 @@ CSQC_Init(float apilevel, string enginename, float engineversion)
Sound_Init();
pSeat = &g_seats[0];
registercommand("callvote");
registercommand("dev_sentence");
registercommand("titles_test");
registercommand("vox_test");
@ -31,7 +32,6 @@ CSQC_Init(float apilevel, string enginename, float engineversion)
registercommand("-use");
registercommand("+duck");
registercommand("-duck");
registercommand("callvote");
registercommand("vote");
/* Requested by Slacer */

View file

@ -56,7 +56,7 @@ Called when a spectator joins the game
*/
void Game_SpectatorConnect(void)
{
//Spawn_MakeSpectator();
//PlayerMakeSpectator();
//Spawn_ObserverCam();
ClientConnect();
PutClientInServer();
@ -160,7 +160,7 @@ void Game_PutClientInServer(void)
entity eTarget = world;
Spawn_MakeSpectator();
PlayerMakeSpectator();
Spawn_ObserverCam();
self.SendEntity = Player_SendEntity;

View file

@ -81,9 +81,9 @@ int iBombPlanted;
void Rules_RoundOver(int iTeamWon, int iMoneyReward, float fSilent);
float Rules_BuyingPossible(void);
void Timer_Begin(float fTime, float fMode);
void Spawn_RespawnClient(float fTeam);
void Spawn_CreateClient(float fTeam);
void Spawn_MakeSpectator(void);
void PlayerRoundRespawn(float fTeam);
void PlayerSpawnIngame(float fTeam);
void PlayerMakeSpectator(void);
void Client_SendEvent(entity eClient, float fEVType);
void Weapon_Draw(float fWeapon);

View file

@ -30,7 +30,7 @@ void Escape_Touch(entity targ)
{
entity eOld = self;
self = targ;
Spawn_MakeSpectator();
PlayerMakeSpectator();
self.classname = "player";
forceinfokey(self, "*dead", "0");
self.health = 0;

View file

@ -25,7 +25,7 @@ void VIP_Rescue(entity targ)
{
entity eOld = self;
self = other;
Spawn_MakeSpectator();
PlayerMakeSpectator();
self.classname = "player";
self.team = TEAM_CT;
forceinfokey(self, "*dead", "0");

View file

@ -160,7 +160,7 @@ void Player_Death(int iHitBody)
}
}
Spawn_MakeSpectator();
PlayerMakeSpectator();
self.classname = "player";
self.health = 0;
forceinfokey(self, "*dead", "1");

View file

@ -107,7 +107,7 @@ void Rules_MakeBomber(void) {
void Rules_MakeVIP(void) {
self.team = TEAM_VIP;
Spawn_RespawnClient(self.team);
PlayerRoundRespawn(self.team);
centerprint(self, "You are the VIP\nMake your way to the safety zones!");
forceinfokey(self, "*dead", "2");
}
@ -129,10 +129,10 @@ void Rules_Restart(int iWipe) {
self = eFind;
if (self.health > 0 && iWipe == FALSE) {
Spawn_RespawnClient(self.team);
PlayerRoundRespawn(self.team);
} else {
Spawn_MakeSpectator();
Spawn_CreateClient(self.fCharModel);
PlayerMakeSpectator();
PlayerSpawnIngame(self.fCharModel);
}
if (iWipe == FALSE) {

View file

@ -19,12 +19,12 @@ entity eLastCTSpawn;
/*
=================
Spawn_FindSpawnPoint
PlayerFindSpawn
Recursive function that gets the next spawnpoint
=================
*/
entity Spawn_FindSpawnPoint(float fTeam)
entity PlayerFindSpawn(float fTeam)
{
entity eSpot, eLastSpawn;
entity eThing;
@ -71,16 +71,16 @@ entity Spawn_FindSpawnPoint(float fTeam)
/*
=================
Spawn_RespawnClient
PlayerRoundRespawn
Called whenever a player just needs his basic properties to be reset
=================
*/
void Spawn_RespawnClient(float fTeam)
void PlayerRoundRespawn(float fTeam)
{
entity eSpawn;
forceinfokey(self, "*spec", "0");
eSpawn = Spawn_FindSpawnPoint(self.team);
eSpawn = PlayerFindSpawn(self.team);
self.classname = "player";
self.health = self.max_health = 100;
@ -121,12 +121,12 @@ void Spawn_RespawnClient(float fTeam)
/*
=================
Spawn_CreateClient
PlayerSpawnIngame
Called whenever a player becomes a completely new type of player
=================
*/
void Spawn_CreateClient(float fCharModel)
void PlayerSpawnIngame(float fCharModel)
{
// What team are we on - 0= Spectator, < 5 Terrorists, CT rest
if(fCharModel == 0) {
@ -163,18 +163,18 @@ void Spawn_CreateClient(float fCharModel)
}
forceinfokey(self, "*team", ftos(self.team));
Spawn_RespawnClient(self.team);
PlayerRoundRespawn(self.team);
self.fAttackFinished = time + 1;
}
/*
=================
Spawn_MakeSpectator
PlayerMakeSpectator
Called on connect and whenever a player dies
=================
*/
void Spawn_MakeSpectator(void)
void PlayerMakeSpectator(void)
{
self.classname = "spectator";
@ -228,7 +228,7 @@ void CSEv_GamePlayerSpawn_f(float fChar)
switch (fGameState) {
case GAME_FREEZE:
self.fCharModel = fChar;
Spawn_CreateClient(fChar);
PlayerSpawnIngame(fChar);
if ((self.team == TEAM_T) && (iAlivePlayers_T == 1)) {
if (iBombZones > 0) {
@ -251,7 +251,7 @@ void CSEv_GamePlayerSpawn_f(float fChar)
self.team = TEAM_CT;
}
Spawn_MakeSpectator();
PlayerMakeSpectator();
self.classname = "player";
self.fCharModel = fChar;
self.health = 0;

View file

@ -49,11 +49,13 @@ int g_cstrikeWeaponPrice[] =
void
CSEv_BuyWeapon_f(float fWeapon)
{
CSGameRules rules = (CSGameRules)g_grMode;
int iWeapon;
player pl = (player)self;
iWeapon = (int)fWeapon;
if (Rules_BuyingPossible() == FALSE) {
if (rules.RulesBuyingPossible(pl) == FALSE) {
return;
}

View file

@ -63,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

@ -72,14 +72,3 @@ enum
GAME_END,
GAME_OVER
};
void Rules_RoundOver(int, int, float);
void Rules_CountPlayers(void);
void Rules_Restart(int);
void Rules_SwitchTeams(void);
void Rules_DeathCheck(void);
void Rules_TimeOver(void);
void Spawn_CreateClient(int);
void Spawn_RespawnClient(int);
void Spawn_MakeSpectator(void);
void CSEv_GamePlayerSpawn_f(int);

View file

@ -40,10 +40,10 @@ Choices for 'team' include:
2 = Counter-Terrorist
*/
class func_buyzone:CBaseTrigger
class func_buyzone
{
void(void) func_buyzone;
virtual void(void) touch;
virtual void(void) Respawn;
};
void
@ -58,7 +58,17 @@ func_buyzone::touch(void)
}
void
func_buyzone::Respawn(void)
func_buyzone::func_buyzone(void)
{
InitBrushTrigger();
angles = [0,0,0];
movetype = MOVETYPE_NONE;
solid = SOLID_TRIGGER;
if (model) {
setmodel(this, model);
} else {
mins = [-128,-128,-36];
maxs = [128,128,36];
setsize(this, mins, maxs);
}
}

View file

@ -28,13 +28,50 @@ If neither a func_hostage_rescue or a info_hostage_rescue is placed,
zones will be placed in Counter-Terrorist player spawn nodes automatically.
*/
class func_hostage_rescue:CBaseTrigger
class func_hostage_rescue
{
virtual void(void) Respawn;
};
void(void) func_hostage_rescue;
virtual void(void) touch;
};
void
func_hostage_rescue::Respawn(void)
func_hostage_rescue::touch(void)
{
InitBrushTrigger();
if (other.classname != "hostage_entity") {
return;
}
CBaseNPC hosty = (CBaseNPC)other;
if (hosty.solid == SOLID_NOT) {
return;
}
Radio_BroadcastMessage(RADIO_RESCUED);
g_cs_hostagesrescued++;
//Money_AddMoney(hosty.m_eFollowing, 1000);
/* In Hostage Rescue, all Counter-Terrorists receive an $850
* bonus for every hostage they rescue, even if they lose the round. */
//Money_QueTeamReward(TEAM_CT, 850);
CBaseEntity targa = (CBaseEntity)other;
targa.Hide();
}
void
func_hostage_rescue::func_hostage_rescue(void)
{
angles = [0,0,0];
movetype = MOVETYPE_NONE;
solid = SOLID_TRIGGER;
if (model) {
setmodel(this, model);
} else {
mins = [-128,-128,-36];
maxs = [128,128,36];
setsize(this, mins, maxs);
}
}

View file

@ -14,14 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
enum
{
BUY_BOTH,
BUY_CT,
BUY_T,
BUY_NEITHER
};
/* Edit this for a custom gun-game order */
int gg_order[] = {
WEAPON_KNIFE,
@ -49,316 +41,4 @@ int gg_order[] = {
WEAPON_PARA
};
/*
=================
Rules_BuyingPossible
Checks if it is possible for players to buy anything
=================
*/
int
Rules_BuyingPossible(void)
{
player pl = (player)self;
if (pl.health <= 0) {
return FALSE;
}
if (g_cs_gamestate == GAME_ACTIVE) {
if (((autocvar_mp_roundtime * 60) - g_cs_gametime) > autocvar_mp_buytime) {
centerprint(pl, sprintf("%d seconds have passed...\nYou can't buy anything now!", autocvar_mp_buytime));
return FALSE;
}
}
if (pl.team == TEAM_VIP) {
centerprint(pl, "You are the VIP...\nYou can't buy anything!\n");
return FALSE;
}
if (g_cstrike_buying == BUY_NEITHER) {
centerprint(pl, "Sorry, you aren't meant\nto be buying anything.\n");
return FALSE;
}
if (g_cstrike_buying != BUY_BOTH) {
if (g_cstrike_buying == BUY_CT && pl.team == TEAM_T) {
centerprint(pl, "Terrorists aren't allowed to\nbuy anything on this map!\n");
return FALSE;
} else if (g_cstrike_buying == BUY_T && pl.team == TEAM_CT) {
centerprint(pl, "CTs aren't allowed to buy\nanything on this map!\n");
return FALSE;
}
}
if (pl.buyzone == FALSE) {
centerprint(pl, "Sorry, you aren't in a buyzone.\n");
return FALSE;
}
return TRUE;
}
void
Rules_MakeBomber(void)
{
player pl = (player)self;
Weapons_AddItem(pl, WEAPON_C4BOMB);
centerprint(self, "You have the bomb!\nFind the target zone or DROP\nthe bomb for another Terrorist.");
}
void
Rules_MakeVIP(void)
{
self.team = TEAM_VIP;
Spawn_RespawnClient(self.team);
centerprint(self, "You are the VIP\nMake your way to the safety zones!");
forceinfokey(self, "*dead", "2");
}
/*
=================
Rules_Restart
Loop through all ents and handle them
=================
*/
void
Rules_Restart(int iWipe)
{
g_cs_hostagesrescued = 0;
entity eOld = self;
// Spawn/Respawn everyone at their team position and give them $$$
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
player pl = (player)eFind;
self = eFind;
if (pl.health > 0 && iWipe == FALSE) {
Spawn_RespawnClient(pl.team);
} else {
Spawn_MakeSpectator();
Spawn_CreateClient(pl.charmodel);
}
if (iWipe == FALSE) {
Money_GiveTeamReward();
} else {
pl.money = 0;
Money_AddMoney(pl, autocvar_mp_startmoney);
}
}
// Clear the corpses/items
for (entity eFind = world; (eFind = find(eFind, classname, "remove_me"));) {
remove(eFind);
}
// Find the bombs. Destory them!
for (entity eFind = world; (eFind = find(eFind, classname, "c4bomb"));) {
remove(eFind);
}
// Select a random Terrorist for the bomb, if needed
if (g_cs_bombzones > 0) {
int iRandomT = floor(random(1, (float)g_cs_alive_t + 1));
int iPickT = 0;
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
if (eFind.team == TEAM_T) {
iPickT++;
if (iPickT == iRandomT) {
self = eFind;
Rules_MakeBomber();
}
}
}
}
// If there is a VIP, select a random CT to be it
if (g_cs_vipzones > 0) {
int iRandomCT = floor(random(1, (float)g_cs_alive_ct + 1));
int iPickCT = 0;
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
if (eFind.team == TEAM_CT) {
iPickCT++;
if (iPickCT == iRandomCT) {
self = eFind;
Rules_MakeVIP();
}
}
}
}
// Respawn all the entities
for (entity a = world; (a = findfloat(a, gflags, GF_CANRESPAWN));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
self = eOld;
Timer_Begin(autocvar_mp_freezetime, GAME_FREEZE);
Money_ResetTeamReward();
}
/*
=================
Rules_RoundOver
This happens whenever an objective is complete or time is up
=================
*/
void
Rules_RoundOver(int iTeamWon, int iMoneyReward, float fSilent)
{
if (g_cs_gamestate != GAME_ACTIVE) {
return;
}
if (iTeamWon == TEAM_T) {
if (fSilent == FALSE) {
Radio_BroadcastMessage(RADIO_TERWIN);
}
g_cs_roundswon_t++;
} else if (iTeamWon == TEAM_CT) {
if (fSilent == FALSE) {
Radio_BroadcastMessage(RADIO_CTWIN);
}
g_cs_roundswon_ct++;
/* In Bomb Defusal, if Terrorists were able to plant the bomb
* but lose the round, all Terrorists receive an $800 bonus. */
if (g_cs_bombplanted) {
Money_QueTeamReward(TEAM_T, 800);
}
} else {
if (fSilent == FALSE) {
Radio_BroadcastMessage(RADIO_ROUNDDRAW);
}
}
Money_HandleRoundReward(iTeamWon);
Money_QueTeamReward(iTeamWon, iMoneyReward);
Timer_Begin(5, GAME_END); // Round is over, 5 seconds til a new round starts
g_cs_bombplanted = 0;
g_cs_roundsplayed++;
}
/*
=================
Rules_TimeOver
Whenever mp_roundtime was being counted down to 0
=================
*/
void
Rules_TimeOver(void)
{
if (g_cs_vipzones > 0) {
Rules_RoundOver(TEAM_T, 3250, FALSE);
} else if (g_cs_bombzones > 0) {
/* In Bomb Defusal, all Counter-Terrorists receive $3250
* if they won running down the time. */
Rules_RoundOver(TEAM_CT, 3250, FALSE);
} else if (g_cs_hostagestotal > 0) {
// TODO: Broadcast_Print: Hostages have not been rescued!
Rules_RoundOver(TEAM_T, 3250, FALSE);
} else {
Rules_RoundOver(0, 0, FALSE);
}
}
/*
=================
Rules_SwitchTeams
Happens rarely
=================
*/
void
Rules_SwitchTeams(void)
{
int iCTW, iTW;
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
player pl = (player)eFind;
if (pl.team == TEAM_CT) {
pl.team = TEAM_T;
pl.charmodel -= 4;
} else if (pl.team == TEAM_T) {
pl.team = TEAM_CT;
pl.charmodel += 4;
}
forceinfokey(pl, "*team", ftos(pl.team));
}
iCTW = g_cs_roundswon_ct;
iTW = g_cs_roundswon_t;
g_cs_roundswon_t = iCTW;
g_cs_roundswon_ct = iTW;
iCTW = g_cs_alive_ct;
iTW = g_cs_alive_t;
g_cs_alive_ct = iTW;
g_cs_alive_t = iCTW;
}
void
Rules_CountPlayers(void)
{
g_cs_alive_t = 0;
g_cs_alive_ct = 0;
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
if (eFind.health > 0) {
if (eFind.team == TEAM_T) {
g_cs_alive_t++;
} else if (eFind.team == TEAM_CT) {
g_cs_alive_ct++;
} else if (eFind.team == TEAM_VIP) {
g_cs_alive_ct++;
}
}
}
}
void
Rules_DeathCheck(void)
{
if ((g_cs_alive_t == 0) && (g_cs_alive_ct == 0)) {
if (g_cs_bombplanted == TRUE) {
Rules_RoundOver(TEAM_T, 3600, FALSE);
} else {
Rules_RoundOver(FALSE, 0, FALSE);
}
} else {
int winner;
if ((self.team == TEAM_T) && (g_cs_alive_t == 0)) {
winner = TEAM_CT;
} else if ((self.team == TEAM_CT) && (g_cs_alive_ct == 0)) {
winner = TEAM_T;
} else {
return;
}
if (g_cs_bombzones > 0) {
/* In Bomb Defusal, the winning team receives $3250
* if they won by eliminating the enemy team. */
if (!g_cs_bombplanted || g_cs_alive_ct == 0) {
Rules_RoundOver(winner, 3250, FALSE);
}
} else {
/* In Hostage Rescue, the winning team receives $3600
* if they won by eliminating the enemy team. */
Rules_RoundOver(winner, 3600, FALSE);
}
}
}

View file

@ -1,127 +0,0 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void Timer_Begin(float tleft, int mode)
{
if (mode == GAME_FREEZE) {
g_cs_gamestate = GAME_FREEZE;
} else if (mode == GAME_ACTIVE) {
g_cs_gamestate = GAME_ACTIVE;
} else if (mode == GAME_END) {
g_cs_gamestate = GAME_END;
} else if (mode == GAME_COMMENCING) {
g_cs_gamestate = GAME_COMMENCING;
} else if (mode == GAME_OVER) {
g_cs_gamestate = GAME_OVER;
}
g_cs_gametime = tleft;
}
void
Timer_Update(void)
{
// static float fVoxTimer;
if (cvar("sv_playerslots") == 1) {
g_cs_gametime = -1;
return;
}
// This map has been played enough we think
if (g_cs_gamestate != GAME_OVER) {
if (cvar("mp_timelimit") > 0) {
/*if (autocvar_fcs_voxannounce == TRUE) {
if (fVoxTimer > time) {
return;
}
float fTimeLeft = (cvar("mp_timelimit") * 60) - time;
for (int i = 0; i <= 10; i++) {
if (rint(fTimeLeft) == (i * 60)) {
Vox_Broadcast(sprintf("%s minutes remaining", Vox_TimeToString(fTimeLeft / 60)));
fVoxTimer = time + 10.0f;
}
}
}*/
if (time >= (cvar("mp_timelimit") * 60)) {
Timer_Begin(5, GAME_OVER);
}
}
}
if ((g_cs_gamestate == GAME_OVER) && (g_cs_gametime < 0)) {
localcmd("nextmap\n");
}
// Okay, this means that timelimit is not the only deciding factor
if (autocvar_mp_winlimit > 0 && g_cs_gamestate != GAME_OVER) {
// It really doesn't matter who won. Do some logging perhaps?
if (g_cs_roundswon_ct == autocvar_mp_winlimit) {
Timer_Begin(5, GAME_OVER);
} else if (g_cs_roundswon_t == autocvar_mp_winlimit) {
Timer_Begin(5, GAME_OVER);
}
}
if (g_cs_gamestate == GAME_INACTIVE) {
return;
}
if (g_cs_gametime > 0) {
g_cs_gametime -= frametime;
} else {
g_cs_gametime = 0;
}
if (g_cs_gamestate == GAME_COMMENCING || g_cs_gamestate == GAME_END) {
if (g_cs_gametime <= 0) {
if (g_cs_roundswon_t == 0 && g_cs_roundswon_ct == 0) {
Money_ResetTeamReward();
Money_ResetRoundReward();
Rules_Restart(TRUE);
} else {
if (autocvar_mp_halftime == TRUE && (autocvar_mp_winlimit / 2 == g_cs_roundsplayed)) {
Money_ResetTeamReward();
Rules_SwitchTeams();
Rules_Restart(TRUE);
} else {
Rules_Restart(FALSE);
}
}
}
return;
}
if ((g_cs_gamestate == GAME_ACTIVE) || (g_cs_gamestate == GAME_FREEZE)) {
if (g_cs_gametime <= 0) {
if (g_cs_gamestate == GAME_ACTIVE) {
/* 1.5 will make the T's lose if time runs out no matter what */
if (autocvar_fcs_fix_bombtimer == TRUE) {
if (g_cs_bombzones > 0 && g_cs_bombplanted == TRUE) {
return;
}
}
Rules_TimeOver();
Timer_Begin(5, GAME_END); // Round is over, 5 seconds til a new round starts
} else {
Timer_Begin(autocvar_mp_roundtime * 60, GAME_ACTIVE); // Unfreeze
Radio_StartMessage();
}
}
}
}

View file

@ -27,8 +27,17 @@ class CSGameRules:CGameRules
virtual void(player) LevelChangeParms;
virtual void(player) LevelDecodeParms;
virtual void(void) LevelNewParms;
virtual int(player) RulesBuyingPossible;
};
int
CSGameRules::RulesBuyingPossible(player pl)
{
return FALSE;
}
/* we check what fields have changed over the course of the frame and network
* only the ones that have actually changed */
void

View file

@ -16,12 +16,34 @@
class CSMultiplayerRules:CSGameRules
{
entity m_eLastTSpawn;
entity m_eLastCTSpawn;
virtual void(void) InitPostEnts;
virtual void(void) FrameStart;
/* client */
virtual void(player) PlayerSpawn;
/* level transitions */
virtual void(player) LevelDecodeParms;
/* CS specific */
virtual void(void) CreateRescueZones;
virtual void(void) CreateCTBuyzones;
virtual void(void) CreateTBuyzones;
virtual void(float, int) TimerBegin;
virtual void(void) TimerUpdate;
virtual void(player) RulesDeathCheck;
virtual void(void) RulesCountPlayers;
virtual void(void) RulesSwitchTeams;
virtual void(void) RulesTimeOver;
virtual void(int, int, int) RulesRoundOver;
virtual void(int) RulesRestart;
virtual void(player) RulesMakeVIP;
virtual void(player) RulesMakeBomber;
virtual int(player) RulesBuyingPossible;
virtual void(player, int) PlayerMakePlayable;
virtual void(player) PlayerMakeSpectator;
virtual void(player, int) PlayerRespawn;
virtual entity(float) PlayerFindSpawn;
};
void
@ -34,7 +56,7 @@ CSMultiplayerRules::FrameStart(void)
}
if ((iInGamePlayers > 0) && (g_cs_gamestate != GAME_COMMENCING && g_cs_gamestate != GAME_END)) {
Timer_Begin(2, GAME_COMMENCING);
TimerBegin(2, GAME_COMMENCING);
} else if (iInGamePlayers == 0) {
g_cs_gamestate = GAME_INACTIVE;
g_cs_gametime = 0;
@ -42,21 +64,668 @@ CSMultiplayerRules::FrameStart(void)
g_cs_roundswon_ct = 0;
g_cs_roundsplayed = 0;
} else {
Timer_Update(); // Timer that happens once players have started joining
TimerUpdate(); // Timer that happens once players have started joining
}
} else {
Timer_Update(); // Normal gameplay timer
TimerUpdate(); // Normal gameplay timer
}
}
void
CSMultiplayerRules::LevelDecodeParms(player pl)
CSMultiplayerRules::CreateRescueZones(void)
{
int zones = 0;
/* not in hostage rescue mode */
if (g_cs_hostagestotal <= 0) {
return;
}
/* count the already existing rescue zones. */
for (entity e = world; (e = find(e, ::classname, "func_hostage_rescue"));) {
if (e.team == TEAM_CT) {
zones++;
}
}
/* we don't need to create any additional rescue zones. */
if (zones > 0)
return;
/* since no buyzones are available, let's create one around every CT spawn */
for (entity e = world; (e = find(e, ::classname, "info_player_start"));) {
func_hostage_rescue newzone = spawn(func_hostage_rescue);
setorigin(newzone, e.origin);
}
}
void
CSMultiplayerRules::PlayerSpawn(player pl)
CSMultiplayerRules::CreateCTBuyzones(void)
{
int zones = 0;
/* count the already existing CT zones. */
for (entity e = world; (e = find(e, ::classname, "func_buyzone"));) {
if (e.team == TEAM_CT) {
zones++;
}
}
/* we don't need to create any additional CT zones. */
if (zones > 0)
return;
/* since no buyzones are available, let's create one around every CT spawn */
for (entity e = world; (e = find(e, ::classname, "info_player_start"));) {
func_buyzone newzone = spawn(func_buyzone);
setorigin(newzone, e.origin);
newzone.team = TEAM_CT;
}
}
void
CSMultiplayerRules::CreateTBuyzones(void)
{
int zones = 0;
/* count the already existing T zones. */
for (entity e = world; (e = find(e, ::classname, "func_buyzone"));) {
if (e.team == TEAM_T) {
zones++;
}
}
/* we don't need to create any additional T zones. */
if (zones > 0)
return;
/* since no buyzones are available, let's create one around every T spawn */
for (entity e = world; (e = find(e, ::classname, "info_player_deathmatch"));) {
func_buyzone newzone = spawn(func_buyzone);
setorigin(newzone, e.origin);
newzone.team = TEAM_T;
}
}
void
CSMultiplayerRules::InitPostEnts(void)
{
/* let's check if we need to create buyzones */
switch (g_cstrike_buying) {
case BUY_CT:
CreateCTBuyzones();
break;
case BUY_T:
CreateTBuyzones();
break;
case BUY_NEITHER:
break;
default:
CreateCTBuyzones();
CreateTBuyzones();
}
CreateRescueZones();
}
void
CSMultiplayerRules::TimerBegin(float tleft, int mode)
{
if (mode == GAME_FREEZE) {
g_cs_gamestate = GAME_FREEZE;
} else if (mode == GAME_ACTIVE) {
g_cs_gamestate = GAME_ACTIVE;
} else if (mode == GAME_END) {
g_cs_gamestate = GAME_END;
} else if (mode == GAME_COMMENCING) {
g_cs_gamestate = GAME_COMMENCING;
} else if (mode == GAME_OVER) {
g_cs_gamestate = GAME_OVER;
}
g_cs_gametime = tleft;
}
void
CSMultiplayerRules::TimerUpdate(void)
{
if (cvar("sv_playerslots") == 1) {
g_cs_gametime = -1;
return;
}
if (g_cs_hostagestotal > 0) {
if (g_cs_hostagesrescued >= g_cs_hostagestotal) {
RulesRoundOver(TEAM_CT, 0, FALSE);
return;
}
}
// This map has been played enough we think
if (g_cs_gamestate != GAME_OVER) {
if (cvar("mp_timelimit") > 0) {
if (time >= (cvar("mp_timelimit") * 60)) {
TimerBegin(5, GAME_OVER);
}
}
}
if ((g_cs_gamestate == GAME_OVER) && (g_cs_gametime < 0)) {
localcmd("echo nextmap\n");
}
// Okay, this means that timelimit is not the only deciding factor
if (autocvar_mp_winlimit > 0 && g_cs_gamestate != GAME_OVER) {
// It really doesn't matter who won. Do some logging perhaps?
if (g_cs_roundswon_ct == autocvar_mp_winlimit) {
TimerBegin(5, GAME_OVER);
} else if (g_cs_roundswon_t == autocvar_mp_winlimit) {
TimerBegin(5, GAME_OVER);
}
}
if (g_cs_gamestate == GAME_INACTIVE) {
return;
}
if (g_cs_gametime > 0) {
g_cs_gametime -= frametime;
} else {
g_cs_gametime = 0;
}
if (g_cs_gamestate == GAME_COMMENCING || g_cs_gamestate == GAME_END) {
if (g_cs_gametime <= 0) {
if (g_cs_roundswon_t == 0 && g_cs_roundswon_ct == 0) {
Money_ResetTeamReward();
Money_ResetRoundReward();
RulesRestart(TRUE);
} else {
if (autocvar_mp_halftime == TRUE && (autocvar_mp_winlimit / 2 == g_cs_roundsplayed)) {
Money_ResetTeamReward();
RulesSwitchTeams();
RulesRestart(TRUE);
} else {
RulesRestart(FALSE);
}
}
}
return;
}
if ((g_cs_gamestate == GAME_ACTIVE) || (g_cs_gamestate == GAME_FREEZE)) {
if (g_cs_gametime <= 0) {
if (g_cs_gamestate == GAME_ACTIVE) {
/* 1.5 will make the T's lose if time runs out no matter what */
if (autocvar_fcs_fix_bombtimer == TRUE) {
if (g_cs_bombzones > 0 && g_cs_bombplanted == TRUE) {
return;
}
}
RulesTimeOver();
TimerBegin(5, GAME_END); // Round is over, 5 seconds til a new round starts
} else {
TimerBegin(autocvar_mp_roundtime * 60, GAME_ACTIVE); // Unfreeze
Radio_StartMessage();
}
}
}
}
/*
=================
RulesBuyingPossible
Checks if it is possible for players to buy anything
=================
*/
int
CSMultiplayerRules::RulesBuyingPossible(player pl)
{
if (pl.health <= 0) {
return FALSE;
}
if (g_cs_gamestate == GAME_ACTIVE) {
if (((autocvar_mp_roundtime * 60) - g_cs_gametime) > autocvar_mp_buytime) {
centerprint(pl, sprintf("%d seconds have passed...\nYou can't buy anything now!", autocvar_mp_buytime));
return FALSE;
}
}
if (pl.team == TEAM_VIP) {
centerprint(pl, "You are the VIP...\nYou can't buy anything!\n");
return FALSE;
}
if (g_cstrike_buying == BUY_NEITHER) {
centerprint(pl, "Sorry, you aren't meant\nto be buying anything.\n");
return FALSE;
}
if (g_cstrike_buying != BUY_BOTH) {
if (g_cstrike_buying == BUY_CT && pl.team == TEAM_T) {
centerprint(pl, "Terrorists aren't allowed to\nbuy anything on this map!\n");
return FALSE;
} else if (g_cstrike_buying == BUY_T && pl.team == TEAM_CT) {
centerprint(pl, "CTs aren't allowed to buy\nanything on this map!\n");
return FALSE;
}
}
if (pl.buyzone == FALSE) {
centerprint(pl, "Sorry, you aren't in a buyzone.\n");
return FALSE;
}
return TRUE;
}
void
CSMultiplayerRules::RulesMakeBomber(player pl)
{
Weapons_AddItem(pl, WEAPON_C4BOMB);
centerprint(pl, "You have the bomb!\nFind the target zone or DROP\nthe bomb for another Terrorist.");
}
void
CSMultiplayerRules::RulesMakeVIP(player pl)
{
pl.team = TEAM_VIP;
PlayerRespawn(pl, pl.team);
centerprint(pl, "You are the VIP\nMake your way to the safety zones!");
forceinfokey(pl, "*dead", "2");
}
/*
=================
RulesRestart
Loop through all ents and handle them
=================
*/
void
CSMultiplayerRules::RulesRestart(int iWipe)
{
g_cs_hostagesrescued = 0;
// Spawn/Respawn everyone at their team position and give them $$$
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
player pl = (player)eFind;
if (pl.health > 0 && iWipe == FALSE) {
PlayerRespawn(pl, pl.team);
} else {
PlayerMakeSpectator(pl);
PlayerMakePlayable(pl, pl.charmodel);
}
if (iWipe == FALSE) {
Money_GiveTeamReward();
} else {
pl.money = 0;
Money_AddMoney(pl, autocvar_mp_startmoney);
}
}
// Clear the corpses/items
for (entity eFind = world; (eFind = find(eFind, ::classname, "remove_me"));) {
remove(eFind);
}
// Find the bombs. Destory them!
for (entity eFind = world; (eFind = find(eFind, ::classname, "c4bomb"));) {
remove(eFind);
}
// Select a random Terrorist for the bomb, if needed
if (g_cs_bombzones > 0) {
int iRandomT = floor(random(1, (float)g_cs_alive_t + 1));
int iPickT = 0;
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
if (eFind.team == TEAM_T) {
iPickT++;
if (iPickT == iRandomT) {
RulesMakeBomber((player)eFind);
}
}
}
}
// If there is a VIP, select a random CT to be it
if (g_cs_vipzones > 0) {
int iRandomCT = floor(random(1, (float)g_cs_alive_ct + 1));
int iPickCT = 0;
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
if (eFind.team == TEAM_CT) {
iPickCT++;
if (iPickCT == iRandomCT) {
RulesMakeVIP((player)eFind);
}
}
}
}
// Respawn all the entities
for (entity a = world; (a = findfloat(a, ::gflags, GF_CANRESPAWN));) {
CBaseEntity caw = (CBaseEntity)a;
caw.Respawn();
}
TimerBegin(autocvar_mp_freezetime, GAME_FREEZE);
Money_ResetTeamReward();
}
/*
=================
RulesRoundOver
This happens whenever an objective is complete or time is up
=================
*/
void
CSMultiplayerRules::RulesRoundOver(int iTeamWon, int iMoneyReward, int fSilent)
{
if (g_cs_gamestate != GAME_ACTIVE) {
return;
}
if (iTeamWon == TEAM_T) {
if (fSilent == FALSE) {
Radio_BroadcastMessage(RADIO_TERWIN);
}
g_cs_roundswon_t++;
} else if (iTeamWon == TEAM_CT) {
if (fSilent == FALSE) {
Radio_BroadcastMessage(RADIO_CTWIN);
}
g_cs_roundswon_ct++;
/* In Bomb Defusal, if Terrorists were able to plant the bomb
* but lose the round, all Terrorists receive an $800 bonus. */
if (g_cs_bombplanted) {
Money_QueTeamReward(TEAM_T, 800);
}
} else {
if (fSilent == FALSE) {
Radio_BroadcastMessage(RADIO_ROUNDDRAW);
}
}
Money_HandleRoundReward(iTeamWon);
Money_QueTeamReward(iTeamWon, iMoneyReward);
TimerBegin(5, GAME_END); // Round is over, 5 seconds til a new round starts
g_cs_hostagesrescued = 0;
g_cs_bombplanted = 0;
g_cs_roundsplayed++;
}
/*
=================
RulesTimeOver
Whenever mp_roundtime was being counted down to 0
=================
*/
void
CSMultiplayerRules::RulesTimeOver(void)
{
if (g_cs_vipzones > 0) {
RulesRoundOver(TEAM_T, 3250, FALSE);
} else if (g_cs_bombzones > 0) {
/* In Bomb Defusal, all Counter-Terrorists receive $3250
* if they won running down the time. */
RulesRoundOver(TEAM_CT, 3250, FALSE);
} else if (g_cs_hostagestotal > 0) {
// TODO: Broadcast_Print: Hostages have not been rescued!
RulesRoundOver(TEAM_T, 3250, FALSE);
} else {
RulesRoundOver(0, 0, FALSE);
}
}
/*
=================
RulesSwitchTeams
Happens rarely
=================
*/
void
CSMultiplayerRules::RulesSwitchTeams(void)
{
int iCTW, iTW;
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
player pl = (player)eFind;
if (pl.team == TEAM_CT) {
pl.team = TEAM_T;
pl.charmodel -= 4;
} else if (pl.team == TEAM_T) {
pl.team = TEAM_CT;
pl.charmodel += 4;
}
forceinfokey(pl, "*team", ftos(pl.team));
}
iCTW = g_cs_roundswon_ct;
iTW = g_cs_roundswon_t;
g_cs_roundswon_t = iCTW;
g_cs_roundswon_ct = iTW;
iCTW = g_cs_alive_ct;
iTW = g_cs_alive_t;
g_cs_alive_ct = iTW;
g_cs_alive_t = iCTW;
}
void
CSMultiplayerRules::RulesCountPlayers(void)
{
g_cs_alive_t = 0;
g_cs_alive_ct = 0;
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
if (eFind.health > 0) {
if (eFind.team == TEAM_T) {
g_cs_alive_t++;
} else if (eFind.team == TEAM_CT) {
g_cs_alive_ct++;
} else if (eFind.team == TEAM_VIP) {
g_cs_alive_ct++;
}
}
}
}
void
CSMultiplayerRules::RulesDeathCheck(player pl)
{
if ((g_cs_alive_t == 0) && (g_cs_alive_ct == 0)) {
if (g_cs_bombplanted == TRUE) {
RulesRoundOver(TEAM_T, 3600, FALSE);
} else {
RulesRoundOver(FALSE, 0, FALSE);
}
} else {
int winner;
if ((pl.team == TEAM_T) && (g_cs_alive_t == 0)) {
winner = TEAM_CT;
} else if ((pl.team == TEAM_CT) && (g_cs_alive_ct == 0)) {
winner = TEAM_T;
} else {
return;
}
if (g_cs_bombzones > 0) {
/* In Bomb Defusal, the winning team receives $3250
* if they won by eliminating the enemy team. */
if (!g_cs_bombplanted || g_cs_alive_ct == 0) {
RulesRoundOver(winner, 3250, FALSE);
}
} else {
/* In Hostage Rescue, the winning team receives $3600
* if they won by eliminating the enemy team. */
RulesRoundOver(winner, 3600, FALSE);
}
}
}
/*
=================
PlayerFindSpawn
Recursive function that gets the next spawnpoint
=================
*/
entity
CSMultiplayerRules::PlayerFindSpawn(float fTeam)
{
entity eSpot, eLastSpawn;
entity eThing;
int iCount;
string sClassname;
if (fTeam == TEAM_T) {
sClassname = "info_player_deathmatch";
eSpot = eLastSpawn = m_eLastTSpawn;
} else if (fTeam == TEAM_CT) {
sClassname = "info_player_start";
eSpot = eLastSpawn = m_eLastCTSpawn;
} else if (fTeam == TEAM_VIP) {
return find(world, ::classname, "info_vip_start");
}
while (1) {
eSpot = find(eSpot, ::classname, sClassname);
if (eSpot == eLastSpawn)
{//fall back on lame cycling/spawnfragging
eLastSpawn = find(eLastSpawn, ::classname, sClassname);
if (!eLastSpawn)
eLastSpawn = find(eLastSpawn, ::classname, sClassname);
return eLastSpawn;
}
if (eSpot != world) {
iCount = 0;
eThing = findradius(eSpot.origin, 32);
while(eThing) {
if (eThing.classname == "player")
iCount++;
eThing = eThing.chain;
}
if (iCount == 0) {
eLastSpawn = eSpot;
return eSpot;
}
}
}
return eSpot;
}
/*
=================
PlayerRespawn
Called whenever a player survived a round and needs a basic respawn.
=================
*/
void
CSMultiplayerRules::PlayerRespawn(player pl, int fTeam)
{
entity eSpawn;
forceinfokey(pl, "*spec", "0");
eSpawn = PlayerFindSpawn(pl.team);
pl.classname = "player";
pl.health = pl.max_health = 100;
forceinfokey(pl, "*dead", "0");
RulesCountPlayers();
pl.takedamage = DAMAGE_YES;
pl.solid = SOLID_SLIDEBOX;
pl.movetype = MOVETYPE_WALK;
pl.flags = FL_CLIENT;
pl.iBleeds = TRUE;
pl.viewzoom = 1.0;
pl.origin = eSpawn.origin;
pl.angles = eSpawn.angles;
setmodel(pl, "models/player/vip/vip.mdl");
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
/*Ammo_AutoFill(pl.fSlotPrimary);
Ammo_AutoFill(pl.fSlotSecondary);*/
}
/*
=================
PlayerMakePlayable
Called whenever need a full-reinit of a player.
This may be after a player had died or when the game starts for the first time.
=================
*/
void
CSMultiplayerRules::PlayerMakePlayable(player pl, int chara)
{
/* spectator */
if (chara == 0) {
PlayerSpawn(pl);
return;
}
pl.g_items |= ITEM_SUIT;
Weapons_AddItem(pl, WEAPON_KNIFE);
if (chara < 5) {
/* terrorists */
pl.team = TEAM_T;
if (autocvar_fcs_knifeonly == FALSE) {
Weapons_AddItem(pl, WEAPON_GLOCK18);
/*Weapon_GiveAmmo(WEAPON_GLOCK18, 40);*/
/*Weapon_Draw(WEAPON_GLOCK18);*/
} else {
/*Weapon_Draw(WEAPON_KNIFE);*/
}
} else {
/* counter */
pl.team = TEAM_CT;
pl.g_items |= ITEM_SUIT;
Weapons_AddItem(pl, WEAPON_KNIFE);
if (autocvar_fcs_knifeonly == FALSE) {
Weapons_AddItem(pl, WEAPON_USP45);
/*Weapon_GiveAmmo(WEAPON_USP45, 24);*/
/*Weapon_Draw(WEAPON_USP45);*/
} else {
/*Weapon_Draw(WEAPON_KNIFE);*/
}
}
pl.ingame = TRUE;
forceinfokey(pl, "*team", ftos(pl.team));
PlayerRespawn(pl, pl.team);
}
/*
=================
PlayerMakeSpectator
Force the player to become an observer.
=================
*/
void
CSMultiplayerRules::PlayerMakeSpectator(player pl)
{
pl.classname = "spectator";
pl.health = 0;
@ -72,34 +741,105 @@ CSMultiplayerRules::PlayerSpawn(player pl)
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();
/* clear the inventory */
pl.items = 0x0;
pl.activeweapon = 0;
}
// Because we don't want to reset these when we die
/*
=================
PlayerSpawn
Called on the client first joining the server.
=================
*/
void
CSMultiplayerRules::PlayerSpawn(player pl)
{
/* immediately put us into spectating mode */
PlayerMakeSpectator(pl);
Spawn_ObserverCam(pl);
/* give the initial server-joining money */
Money_AddMoney(pl, autocvar_mp_startmoney);
/* we don't belong to any team */
pl.team = 0;
forceinfokey(pl, "*team", "0");
}
void weaponbox_spawn(player pl)
/*
=================
CSEv_JoinTeam_f
Event Handling, called by the Client codebase via 'sendevent'
=================
*/
void CSEv_JoinTeam_f(int fChar)
{
CSMultiplayerRules rules = (CSMultiplayerRules)g_grMode;
player pl = (player)self;
if (pl.team == TEAM_VIP) {
centerprint(pl, "You are the VIP!\nYou cannot switch roles now.\n");
return;
}
// alive and are trying to switch teams, so subtract us from the Alive_Team counter.
if (pl.health > 0) {
rules.PlayerKill(pl);
}
switch (g_cs_gamestate) {
/* spawn the players immediately when its in the freeze state */
case GAME_FREEZE:
pl.charmodel = fChar;
rules.PlayerMakePlayable(pl, fChar);
if ((pl.team == TEAM_T) && (g_cs_alive_t == 1)) {
if (g_cs_bombzones > 0) {
rules.RulesMakeBomber(pl);
}
} else if ((pl.team == TEAM_CT) && (g_cs_alive_ct == 1)) {
if (g_cs_vipzones > 0) {
rules.RulesMakeVIP(pl);
}
}
break;
/* otherwise, just prepare their fields for the next round */
default:
if (fChar == 0) {
rules.PlayerSpawn(pl);
return;
}
if (fChar < 5) {
pl.team = TEAM_T;
} else {
pl.team = TEAM_CT;
}
rules.PlayerMakeSpectator(pl);
pl.classname = "player";
pl.charmodel = fChar;
pl.health = 0;
forceinfokey(pl, "*dead", "1");
forceinfokey(pl, "*team", ftos(pl.team));
break;
}
pl.frags = 0;
pl.deaths = 0;
forceinfokey(pl, "*deaths", ftos(pl.deaths));
/* if no players are present in the chosen team, force restart round */
if ((pl.team == TEAM_T) && (g_cs_alive_t == 0)) {
rules.RulesRoundOver(FALSE, 0, FALSE);
} else if ((pl.team == TEAM_CT) && (g_cs_alive_ct == 0)) {
rules.RulesRoundOver(FALSE, 0, FALSE);
}
}
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);
}
void weaponbox_spawn(player pl) {}

View file

@ -191,4 +191,5 @@ hostage_entity::hostage_entity(void)
base_mins = [-16,-16,0];
base_maxs = [16,16,72];
CBaseNPC::CBaseNPC();
g_cs_hostagestotal++;
}

View file

@ -32,6 +32,14 @@ Choices for 'buying':
3 = Neither Counter-Terrorists nor Terrorists can buy items
*/
enum
{
BUY_BOTH,
BUY_CT,
BUY_T,
BUY_NEITHER
};
class info_map_parameters
{
void(void) info_map_parameters;

View file

@ -74,7 +74,7 @@ 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();
}

View file

@ -53,22 +53,22 @@ void Player_Death(int hit)
corpse.velocity = pl.velocity;
/* gamerule stuff */
Spawn_MakeSpectator();
// PlayerMakeSpectator();
self.classname = "player";
self.health = 0;
forceinfokey(self, "*dead", "1");
forceinfokey(self, "*team", ftos(self.team));
Rules_CountPlayers();
//Rules_CountPlayers();
/* In Assassination, all Terrorists receive a $2500
* reward if they won by killing the VIP. */
if (self.team == TEAM_VIP) {
Rules_RoundOver(TEAM_T, 2500, FALSE);
// Rules_RoundOver(TEAM_T, 2500, FALSE);
return;
}
Rules_DeathCheck();
//
//Rules_DeathCheck();
}
/*

View file

@ -70,13 +70,13 @@
../valve/items.cpp
../../shared/valve/weapon_common.c
../cstrike/hostage_entity.cpp
../cstrike/armoury_entity.cpp
../cstrike/func_bomb_target.cpp
../cstrike/func_buyzone.cpp
../cstrike/func_escapezone.cpp
../cstrike/func_hostage_rescue.cpp
../cstrike/func_vip_safetyzone.cpp
../cstrike/hostage_entity.cpp
../cstrike/info_hostage_rescue.cpp
../cstrike/info_map_parameters.cpp
../cstrike/item_suit.cpp
@ -87,8 +87,6 @@
../gamerules.cpp
../cstrike/game_money.c
../cstrike/game_timer.c
../cstrike/game_rules.c
../cstrike/gamerules.cpp
../cstrike/gamerules_singleplayer.cpp

View file

@ -14,261 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
entity eLastTSpawn;
entity eLastCTSpawn;
/*
=================
Spawn_FindSpawnPoint
Recursive function that gets the next spawnpoint
=================
*/
entity Spawn_FindSpawnPoint(float fTeam)
{
entity eSpot, eLastSpawn;
entity eThing;
int iCount;
string sClassname;
if (fTeam == TEAM_T) {
sClassname = "info_player_deathmatch";
eSpot = eLastSpawn = eLastTSpawn;
} else if (fTeam == TEAM_CT) {
sClassname = "info_player_start";
eSpot = eLastSpawn = eLastCTSpawn;
} else if (fTeam == TEAM_VIP) {
return find(world, classname, "info_vip_start");
}
while (1) {
eSpot = find(eSpot, classname, sClassname);
if (eSpot == eLastSpawn)
{//fall back on lame cycling/spawnfragging
eLastSpawn = find(eLastSpawn, classname, sClassname);
if (!eLastSpawn)
eLastSpawn = find(eLastSpawn, classname, sClassname);
return eLastSpawn;
}
if (eSpot != world) {
iCount = 0;
eThing = findradius(eSpot.origin, 32);
while(eThing) {
if (eThing.classname == "player")
iCount++;
eThing = eThing.chain;
}
if (iCount == 0) {
eLastSpawn = eSpot;
return eSpot;
}
}
}
return eSpot;
}
/*
=================
Spawn_RespawnClient
Called whenever a player just needs his basic properties to be reset
=================
*/
void Spawn_RespawnClient(int fTeam)
{
entity eSpawn;
forceinfokey(self, "*spec", "0");
eSpawn = Spawn_FindSpawnPoint(self.team);
self.classname = "player";
self.health = self.max_health = 100;
forceinfokey(self, "*dead", "0");
Rules_CountPlayers();
self.takedamage = DAMAGE_YES;
self.solid = SOLID_SLIDEBOX;
self.movetype = MOVETYPE_WALK;
self.flags = FL_CLIENT;
//self.Pain = Player_Pain;
//self.Death = Player_Death;
self.iBleeds = TRUE;
self.viewzoom = 1.0; // Clear scopes
self.origin = eSpawn.origin;
self.angles = eSpawn.angles;
// Get the player-model from Defs.h's list
setmodel(self, "models/player/vip/vip.mdl");
setsize(self, VEC_HULL_MIN, VEC_HULL_MAX);
self.view_ofs = VEC_PLAYER_VIEWPOS;
self.velocity = '0 0 0';
self.frame = 1; // Idle frame
/*Ammo_AutoFill(self.fSlotPrimary);
Ammo_AutoFill(self.fSlotSecondary);*/
}
/*
=================
Spawn_CreateClient
Called whenever a player becomes a completely new type of player
=================
*/
void Spawn_CreateClient(int fCharModel)
{
player pl = (player)self;
// What team are we on - 0= Spectator, < 5 Terrorists, CT rest
if (fCharModel == 0) {
PutClientInServer();
Spawn_ObserverCam();
return;
} else if(fCharModel < 5) {
forceinfokey(self, "*team", "0");
pl.team = TEAM_T;
pl.g_items |= ITEM_SUIT;
Weapons_AddItem(pl, WEAPON_KNIFE);
if (autocvar_fcs_knifeonly == FALSE) {
Weapons_AddItem(pl, WEAPON_GLOCK18);
/*Weapon_GiveAmmo(WEAPON_GLOCK18, 40);*/
/*Weapon_Draw(WEAPON_GLOCK18);*/
} else {
/*Weapon_Draw(WEAPON_KNIFE);*/
}
} else {
pl.team = TEAM_CT;
pl.g_items |= ITEM_SUIT;
Weapons_AddItem(pl, WEAPON_KNIFE);
if (autocvar_fcs_knifeonly == FALSE) {
Weapons_AddItem(pl, WEAPON_USP45);
/*Weapon_GiveAmmo(WEAPON_USP45, 24);*/
/*Weapon_Draw(WEAPON_USP45);*/
} else {
/*Weapon_Draw(WEAPON_KNIFE);*/
}
}
if(pl.ingame == FALSE) {
pl.ingame = TRUE;
}
forceinfokey(self, "*team", ftos(pl.team));
Spawn_RespawnClient(pl.team);
}
/*
=================
Spawn_MakeSpectator
Called on connect and whenever a player dies
=================
*/
void Spawn_MakeSpectator(void)
{
self.classname = "spectator";
self.health = 0;
self.armor = 0;
self.takedamage = DAMAGE_NO;
self.solid = SOLID_NOT;
self.movetype = MOVETYPE_NOCLIP;
self.flags = FL_CLIENT;
self.weapon = 0;
self.viewzoom = 1.0f;
self.model = 0;
setsize (self, '-16 -16 -16', '16 16 16');
self.view_ofs = self.velocity = '0 0 0';
forceinfokey(self, "*spec", "2"); // Make sure we are known as a spectator
//Ammo_Clear();
// Clear the inventory
self.items = 0x0;
}
/*
=================
CSEv_GamePlayerSpawn_f
Event Handling, called by the Client codebase via 'sendevent'
=================
*/
void CSEv_GamePlayerSpawn_f(int fChar)
{
player pl = (player)self;
if (pl.team == TEAM_VIP) {
centerprint(self, "You are the VIP!\nYou cannot switch roles now.\n");
return;
}
// Hey, we are alive and are trying to switch teams, so subtract us from the Alive_Team counter.
if (pl.health > 0) {
pl.health = 0;
Rules_CountPlayers();
Rules_DeathCheck();
Player_Death(0);
}
/*Ammo_Clear();*/
// Spawn the players immediately when its in the freeze state
switch (g_cs_gamestate) {
case GAME_FREEZE:
pl.charmodel = fChar;
Spawn_CreateClient(fChar);
if ((pl.team == TEAM_T) && (g_cs_alive_t == 1)) {
if (g_cs_bombzones > 0) {
Rules_MakeBomber();
}
} else if ((pl.team == TEAM_CT) && (g_cs_alive_ct == 1)) {
if (g_cs_vipzones > 0) {
Rules_MakeVIP();
}
}
break;
default:
if (fChar == 0) {
PutClientInServer();
return;
} else if(fChar < 5) {
pl.team = TEAM_T;
} else {
pl.team = TEAM_CT;
}
Spawn_MakeSpectator();
pl.classname = "player";
pl.charmodel = fChar;
pl.health = 0;
forceinfokey(self, "*dead", "1");
forceinfokey(self, "*team", ftos(pl.team));
break;
}
pl.frags = 0;
pl.deaths = 0;
forceinfokey(pl, "*deaths", ftos(pl.deaths));
// Split up for readability and expandability?
if ((pl.team == TEAM_T) && (g_cs_alive_t == 0)) {
Rules_RoundOver(FALSE, 0, FALSE);
} else if ((pl.team == TEAM_CT) && (g_cs_alive_ct == 0)) {
Rules_RoundOver(FALSE, 0, FALSE);
}
}
/*
=================
info_player_start

View file

@ -116,6 +116,8 @@ void init(float prevprogs)
void init_respawn(void)
{
g_grMode.InitPostEnts();
for (entity a = world; (a = findfloat(a, ::gflags, GF_CANRESPAWN));) {
CBaseEntity ent = (CBaseEntity)a;
ent.Respawn();

View file

@ -18,8 +18,10 @@ class CGameRules
{
void() CGameRules;
virtual void(void) InitPostEnts;
/* logic */
virtual void() FrameStart;
virtual void(void) FrameStart;
virtual float(player,string) ConsoleCommand;
/* client */
@ -42,7 +44,7 @@ class CGameRules
/* init */
void
CGameRules::Init(void)
CGameRules::InitPostEnts(void)
{
//print("Init!\n");
}

View file

@ -15,7 +15,7 @@
*/
void
Spawn_ObserverCam(void)
Spawn_ObserverCam(player pl)
{
entity eTarget;
@ -23,13 +23,13 @@ Spawn_ObserverCam(void)
entity eCamera = find(world, ::classname, "trigger_camera");
if (eCamera) {
self.origin = eCamera.origin;
pl.origin = eCamera.origin;
if (eCamera.target) {
eTarget = find(world, ::targetname, eCamera.target);
if (eTarget) {
self.angles = vectoangles(eTarget.origin - eCamera.origin);
self.angles[0] *= -1;
pl.angles = vectoangles(eTarget.origin - eCamera.origin);
pl.angles[0] *= -1;
}
}
} else {
@ -37,19 +37,19 @@ Spawn_ObserverCam(void)
eCamera = find (world, ::classname, "info_player_start");
if (eCamera) {
self.origin = eCamera.origin;
pl.origin = eCamera.origin;
if (eCamera.target) {
eTarget = find(world, ::targetname, eCamera.target);
if (eTarget) {
self.angles = vectoangles(eTarget.origin - eCamera.origin);
self.angles[0] *= -1;
pl.angles = vectoangles(eTarget.origin - eCamera.origin);
pl.angles[0] *= -1;
}
}
}
}
Client_FixAngle(self, self.angles);
Client_FixAngle(pl, pl.angles);
}
float Spawn_PlayerRange(entity spot) {

View file

@ -188,8 +188,8 @@ TFCGameRules::PlayerSpawn(player pl)
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';
setsize (pl, [-16,-16,-16], [16,16,16]);
pl.view_ofs = pl.velocity = [0,0,0];
forceinfokey(pl, "*spec", "2");
Spawn_ObserverCam();
Spawn_ObserverCam(pl);
}

View file

@ -120,7 +120,7 @@ TraceAttack_FireBullets(int iShots, vector vecPos, int iDamage, vector vecSpread
while (iShots > 0) {
#ifdef PENETRATION
iTotalPenetrations = 4;
iTotalPenetrations = 2;
#endif
vDir = aim(self, 100000);
#ifndef CSTRIKE