Bots: Now following some basic objectives - don't look too deep into it

Weapons: We now have added weapon weights and isempty() functions to the
weapon structs
Spectator: Now integrated into the gamemodes proper. NEEDS MORE TESTING!
Radio: Fixed a bug in which the wrong player name would be displayed.
This commit is contained in:
Marco Cawthorne 2021-05-12 15:47:34 +02:00
parent 9b620da3fb
commit 6a24b29e3d
49 changed files with 956 additions and 314 deletions

View File

@ -31,4 +31,6 @@ ClientGame_EntityUpdate(float id, float new)
void
ClientGame_EntityRemove(void)
{
if (self.classname == "player")
Player_DestroyWeaponModel((base_player) self);
}

2
src/server/ammo.h Normal file
View File

@ -0,0 +1,2 @@
void Ammo_BuyPrimary(base_player pl, int free);
void Ammo_BuySecondary(base_player pl, int free);

View File

@ -169,19 +169,13 @@ Ammo_BuyCaliber(player pl, int cal, int free)
return rv;
}
/* We want to loop through all the possible weapons in case the server
* enabled the ability to pick up more than one primary/secondary weapon */
void
CSEv_AmmoBuySecondary(void)
Ammo_BuySecondary(base_player pp, int free)
{
int cal = 0;
int ps = 0;
player pl = (player)self;
CSGameRules rules = (CSGameRules)g_grMode;
if (rules.BuyingPossible(pl) == FALSE) {
return;
}
player pl = (player)pp;
for (int i = 1; i < g_weapons.length; i++) {
if ((pl.g_items & g_weapons[i].id) && (g_weapons[i].slot == 1)) {
@ -212,24 +206,34 @@ CSEv_AmmoBuySecondary(void)
}
}
if (ps) {
if (ps && !free) {
Sound_Play(pl, CHAN_ITEM, "buy.ammo");
}
Weapons_RefreshAmmo(pl);
}
/* We want to loop through all the possible weapons in case the server
* enabled the ability to pick up more than one primary/secondary weapon */
void
CSEv_AmmoBuyPrimary(void)
CSEv_AmmoBuySecondary(void)
{
int ps = 0;
int cal = 0;
player pl = (player)self;
CSGameRules rules = (CSGameRules)g_grMode;
CSGameRules rules = (CSGameRules)g_grMode;
if (rules.BuyingPossible(pl) == FALSE) {
return;
}
Ammo_BuySecondary(pl, FALSE);
}
void
Ammo_BuyPrimary(base_player pp, int free)
{
int ps = 0;
int cal = 0;
player pl = (player)pp;
for (int i = 1; i < g_weapons.length; i++) {
if ((pl.g_items & g_weapons[i].id) && (g_weapons[i].slot == 0)) {
switch (i) {
@ -283,18 +287,32 @@ CSEv_AmmoBuyPrimary(void)
break;
}
if (Ammo_BuyCaliber(pl, cal, FALSE) == 1) {
if (Ammo_BuyCaliber(pl, cal, free) == 1) {
ps = 1;
}
}
}
if (ps) {
if (ps && !free) {
Sound_Play(pl, CHAN_ITEM, "buy.ammo");
}
Weapons_RefreshAmmo(pl);
}
void
CSEv_AmmoBuyPrimary(void)
{
player pl = (player)self;
CSGameRules rules = (CSGameRules)g_grMode;
if (rules.BuyingPossible(pl) == FALSE) {
return;
}
Ammo_BuyPrimary(pl, FALSE);
}
void
Ammo_AutoFill(player pl)
{

19
src/server/bot.h Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2016-2021 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 CSBot_BombPlantedNotify(void);
void CSBot_HostageRescueNotify(void);
void CSBot_RoundStart(void);

268
src/server/bot.qc Normal file
View File

@ -0,0 +1,268 @@
/*
* Copyright (c) 2016-2021 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 csbot:bot
{
void(void) csbot;
/* some objectives */
virtual void(void) RunToConfront;
virtual void(void) RunToBomb;
virtual void(void) RunToBombsite;
virtual void(void) RunToHostages;
virtual void(void) CreateObjective;
virtual void(void) PostFrame;
virtual void(void) WeaponThink;
};
void
csbot::RunToConfront(void)
{
entity t;
if (team == TEAM_T) {
t = Route_SelectRandom("info_player_start");
} else {
t = Route_SelectRandom("info_player_deathmatch");
}
ChatSayTeam("Going to run to the enemy spawn!");
if (t)
route_calculate(this, t.origin, 0, Bot_RouteCB);
}
/* go to the planted bomb */
void
csbot::RunToBomb(void)
{
entity e = world;
e = find(e, ::model, "models/w_c4bomb.mdl");
route_calculate(this, e.origin, 0, Bot_RouteCB);
ChatSayTeam("Going to run to the bomb!");
}
/* go to a random bombsite */
void
csbot::RunToBombsite(void)
{
entity e = world;
vector vecTarget;
/* FIXME: make this random and error checked */
while (e == world)
e = find(e, ::classname, "func_bomb_target");
vecTarget[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0]));
vecTarget[1] = e.absmin[1] + (0.5 * (e.absmax[1] - e.absmin[1]));
vecTarget[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2]));
route_calculate(this, vecTarget, 0, Bot_RouteCB);
ChatSayTeam("Going to run to a bomb site!");
}
void
csbot::RunToHostages(void)
{
entity e = world;
e = find(e, ::classname, "hostage_entity");
route_calculate(this, e.origin, 0, Bot_RouteCB);
ChatSayTeam("Going to run to the hostages!");
}
void
csbot::CreateObjective(void)
{
if (g_cs_bombzones > 0 && g_cs_bombplanted)
RunToBombsite();
if (random() < 0.5) {
if (g_cs_hostagestotal > 0)
RunToHostages();
if (g_cs_bombzones > 0)
RunToBombsite();
} else {
RunToConfront();
}
}
void
csbot::PostFrame(void)
{
team = infokeyf(this, "*team");
};
void
csbot::WeaponThink(void)
{
if (activeweapon == WEAPON_KNIFE)
return;
/* clip empty */
if (a_ammo1 == 0) {
/* still got ammo left, reload! */
if (a_ammo2 != 0) {
input_buttons &= ~INPUT_BUTTON0;
input_buttons |= INPUT_BUTTON4;
} else {
Weapons_SwitchBest(this);
}
}
};
void
csbot::csbot(void)
{
bot::bot();
targetname = "_csbot_";
team = infokeyf(this, "*team");
}
void
CSBot_BombPlantedNotify(void)
{
for (entity a = world; (a = find(a, classname, "player"));) {
if (clienttype(a) != CLIENTTYPE_REAL) {
csbot targ;
targ = (csbot)a;
if (targ.team == TEAM_T)
continue;
if (targ.health <= 0)
continue;
targ.RunToBombsite();
}
}
}
void
CSBot_HostageRescueNotify(void)
{
for (entity a = world; (a = find(a, classname, "player"));) {
if (clienttype(a) != CLIENTTYPE_REAL) {
csbot targ;
targ = (csbot)a;
if (targ.team == TEAM_T)
continue;
if (targ.health <= 0)
continue;
targ.RunToHostages();
}
}
}
void
CSBot_BuyStart_Shop(void)
{
int done = 0;
int count = 0;
player pl = (player)self;
pl.team = infokeyf(pl, "*team");
count = 0;
while (done != 1) {
int r = floor(random(1,17));
if (pl.team == TEAM_T) {
if (r == WEAPON_M4A1) { continue; }
if (r == WEAPON_AUG) { continue; }
if (r == WEAPON_SG550) { continue; }
if (r == WEAPON_FIVESEVEN) { continue; }
if (r == WEAPON_TMP) { continue; }
} else if (pl.team == TEAM_CT) {
if (r == WEAPON_AK47) { continue; }
if (r == WEAPON_SG552) { continue; }
if (r == WEAPON_G3SG1) { continue; }
if (r == WEAPON_ELITES) { continue; }
if (r == WEAPON_MAC10) { continue; }
}
if (g_cstrikeWeaponPrice[r] <= pl.money) {
CSEv_BuyWeapon_f((float)r);
done = 1;
}
count++;
/* give it enough attempts */
if (count > 17)
done = 1;
}
/* need armor */
if (pl.armor < 100) {
if (pl.money >= g_cstrikeUtilPrice[1]) /* kevlar and helmet */
CSEv_BuyEquipment_f(1);
else if (pl.money >= g_cstrikeUtilPrice[0]) /* just kevlar */
CSEv_BuyEquipment_f(0);
} else if (!(pl.g_items & ITEM_HELMET)) { /* we need helmet */
if (pl.money >= 350) /* kevlar and helmet */
CSEv_BuyEquipment_f(1);
}
/* make SURE we switch to it */
for (int i = 0; i < g_weapons.length; i++)
if (pl.g_items & g_weapons[i].id) {
pl.activeweapon = i;
Weapons_Draw();
return;
}
/* force buy right now */
CSEv_AmmoBuyPrimary();
CSEv_AmmoBuySecondary();
}
void
CSBot_BuyStart(void)
{
for (entity a = world; (a = find(a, classname, "player"));) {
if (clienttype(a) != CLIENTTYPE_REAL) {
if (a.health <= 0)
continue;
a.think = CSBot_BuyStart_Shop;
a.nextthink = time + random(0, autocvar_mp_freezetime);
}
}
}
void
CSBot_RoundStart(void)
{
/* if (g_cs_bombzones <= 0) {
return;
}
for (entity a = world; (a = find(a, classname, "player"));) {
if (clienttype(a) != CLIENTTYPE_REAL) {
csbot targ;
targ = (csbot)a;
if (targ.team == TEAM_T)
continue;
if (targ.health <= 0)
continue;
targ.RunToBombsite();
}
}
} */
}

64
src/server/buy.h Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2016-2021 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.
*/
/* values courtesy of https://wiki.alliedmods.net/Cs_weapons_information */
int g_cstrikeWeaponPrice[] =
{
0, /* WEAPON_NONE */
1700, /* WEAPON_M3 */
3000, /* WEAPON_XM1014 */
1500, /* WEAPON_MP5 */
2350, /* WEAPON_P90 */
1700, /* WEAPON_UMP45 */
1400, /* WEAPON_MAC10 */
1250, /* WEAPON_TMP */
2500, /* WEAPON_AK47 */
3500, /* WEAPON_SG552 */
3100, /* WEAPON_M4A1 */
3500, /* WEAPON_AUG */
2750, /* WEAPON_SCOUT */
4750, /* WEAPON_AWP */
5000, /* WEAPON_G3SG1 */
4200, /* WEAPON_SG550 */
5750, /* WEAPON_PARA */
500, /* WEAPON_USP45 */
400, /* WEAPON_GLOCK18 */
650, /* WEAPON_DEAGLE */
600, /* WEAPON_P228 */
800, /* WEAPON_ELITES */
750, /* WEAPON_FIVESEVEN */
0, /* WEAPON_KNIFE */
300, /* WEAPON_HEGRENADE */
200, /* WEAPON_FLASHBANG */
300, /* WEAPON_SMOKEGRENADE */
0 /* WEAPON_C4BOMB */
};
int g_cstrikeUtilPrice[] =
{
650, /* Kevlar Vest */
1000, /* Kevlar Vest & Helmet */
200, /* Flashbang */
300, /* HE Grenade */
300, /* Smoke Grenade */
200, /* Defuse Kit */
1250 /* NightVision Goggles */
};
void CSEv_BuyWeapon_f(float fWeapon);
void CSEv_BuyEquipment_f(float fWeapon);
void CSEv_AmmoBuyPrimary(void);
void CSEv_AmmoBuySecondary(void);

View File

@ -14,39 +14,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* values courtesy of https://wiki.alliedmods.net/Cs_weapons_information */
int g_cstrikeWeaponPrice[] =
{
0, /* WEAPON_NONE */
1700, /* WEAPON_M3 */
3000, /* WEAPON_XM1014 */
1500, /* WEAPON_MP5 */
2350, /* WEAPON_P90 */
1700, /* WEAPON_UMP45 */
1400, /* WEAPON_MAC10 */
1250, /* WEAPON_TMP */
2500, /* WEAPON_AK47 */
3500, /* WEAPON_SG552 */
3100, /* WEAPON_M4A1 */
3500, /* WEAPON_AUG */
2750, /* WEAPON_SCOUT */
4750, /* WEAPON_AWP */
5000, /* WEAPON_G3SG1 */
4200, /* WEAPON_SG550 */
5750, /* WEAPON_PARA */
500, /* WEAPON_USP45 */
400, /* WEAPON_GLOCK18 */
650, /* WEAPON_DEAGLE */
600, /* WEAPON_P228 */
800, /* WEAPON_ELITES */
750, /* WEAPON_FIVESEVEN */
0, /* WEAPON_KNIFE */
300, /* WEAPON_HEGRENADE */
200, /* WEAPON_FLASHBANG */
300, /* WEAPON_SMOKEGRENADE */
0 /* WEAPON_C4BOMB */
};
void
CSEv_BuyWeapon_f(float fWeapon)
{
@ -100,21 +67,17 @@ CSEv_BuyWeapon_f(float fWeapon)
Weapons_AddItem(pl, iWeapon, -1);
Money_AddMoney(pl, -g_cstrikeWeaponPrice[iWeapon]);
Sound_Play(pl, CHAN_ITEM, "buy.weapon");
if (autocvar_fcs_fillweapons) {
if (g_weapons[iWeapon].slot == 0)
Ammo_BuyPrimary(pl, TRUE);
else if (g_weapons[iWeapon].slot == 1)
Ammo_BuySecondary(pl, TRUE);
}
} else {
//centerprint(pl, "You have insufficient funds!");
}
}
int g_cstrikeUtilPrice[] =
{
650, /* Kevlar Vest */
1000, /* Kevlar Vest & Helmet */
200, /* Flashbang */
300, /* HE Grenade */
300, /* Smoke Grenade */
200, /* Defuse Kit */
1250 /* NightVision Goggles */
};
}
void
CSEv_BuyEquipment_f(float fUtil)
@ -147,6 +110,11 @@ CSEv_BuyEquipment_f(float fUtil)
if (pl.g_items & ITEM_HELMET && pl.armor >= 0) {
CSEv_BuyEquipment_f(0);
return;
} else if (!(pl.g_items & ITEM_HELMET) && pl.armor >= 100) { /* only need helmet, so add it */
pl.g_items |= ITEM_HELMET;
Money_AddMoney(pl, -350);
Sound_Play(pl, CHAN_ITEM, "buy.kevlar");
return;
}
pl.armor = 100;

View File

@ -14,6 +14,9 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "ammo.h"
#include "bot.h"
#include "buy.h"
#include "gamerules.h"
#include "money.h"
#include "radio.h"
@ -32,8 +35,13 @@ var int g_cs_bombplanted;
var int g_cs_roundswon_ct;
var int g_cs_roundswon_t;
var int g_cs_roundsplayed;
var int g_cs_alive_t;
var int g_cs_alive_ct;
var int g_cs_total_t;
var int g_cs_total_ct;
var int g_cs_hostagesrescued;
var int g_cs_hostagestotal;
var int g_cs_roundslost_ct;

View File

@ -62,6 +62,7 @@ func_hostage_rescue::touch(void)
g_cs_hostagesrescued++;
Money_AddMoney((player)hosty.m_eFollowing, 1000);
CSBot_HostageRescueNotify();
/* In Hostage Rescue, all Counter-Terrorists receive an $850
* bonus for every hostage that was rescued, even if they lose the round. */

View File

@ -95,7 +95,11 @@ CSMultiplayerRules::PlayerDeath(base_player pl)
corpse.classname = "remove_me";
/* gamerule stuff */
PlayerMakeSpectator(pl);
static void GoSpec(void) {
spawnfunc_spectator();
}
pl.think = GoSpec;
pl.nextthink = time;
pl.classname = "player";
forceinfokey(pl, "*dead", "1");
forceinfokey(pl, "*team", ftos(pl.team));
@ -126,25 +130,20 @@ CSMultiplayerRules::PlayerPreFrame(base_player pl)
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)) {
TimerBegin(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 {
TimerUpdate(); // Timer that happens once players have started joining
}
int iInGamePlayers;
iInGamePlayers = g_cs_total_t + g_cs_total_ct;
if ((iInGamePlayers > 0) && (g_cs_gamestate == GAME_INACTIVE)) {
TimerBegin(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 {
TimerUpdate(); // Normal gameplay timer
TimerUpdate(); // Timer that happens once players have started joining
}
}
@ -339,6 +338,7 @@ CSMultiplayerRules::TimerUpdate(void)
} else {
TimerBegin(autocvar_mp_roundtime * 60, GAME_ACTIVE); // Unfreeze
Radio_StartMessage();
CSBot_RoundStart();
}
}
}
@ -419,8 +419,30 @@ Loop through all ents and handle them
void
CSMultiplayerRules::RestartRound(int iWipe)
{
// Spawn/Respawn everyone at their team position and give them $$$
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
for (entity eFind = world; (eFind = findfloat(eFind, ::team, TEAM_T));) {
if (!(eFind.flags & FL_CLIENT))
continue;
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(pl);
} else {
pl.money = 0;
Money_AddMoney(pl, autocvar_mp_startmoney);
}
}
for (entity eFind = world; (eFind = findfloat(eFind, ::team, TEAM_CT));) {
if (!(eFind.flags & FL_CLIENT))
continue;
player pl = (player)eFind;
if (pl.health > 0 && iWipe == FALSE) {
@ -481,6 +503,7 @@ CSMultiplayerRules::RestartRound(int iWipe)
caw.Respawn();
}
CSBot_BuyStart();
TimerBegin(autocvar_mp_freezetime, GAME_FREEZE);
Money_ResetTeamReward();
}
@ -602,17 +625,26 @@ CSMultiplayerRules::CountPlayers(void)
{
g_cs_alive_t = 0;
g_cs_alive_ct = 0;
g_cs_total_t = 0;
g_cs_total_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++;
}
}
for (entity eFind = world; (eFind = findfloat(eFind, ::team, TEAM_T));) {
if (!(eFind.flags & FL_CLIENT))
continue;
g_cs_total_t++;
if (eFind.health > 0)
g_cs_alive_t++;
}
for (entity eFind = world; (eFind = findfloat(eFind, ::team, TEAM_CT));) {
if (!(eFind.flags & FL_CLIENT))
continue;
g_cs_total_ct++;
if (eFind.health > 0)
g_cs_alive_ct++;
}
}
@ -751,13 +783,14 @@ CSMultiplayerRules::PlayerRespawn(base_player pp, int fTeam)
pl.SetModel(pl.model);
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.velocity = [0,0,0];
pl.progress = 0.0f;
Weapons_SwitchBest(pl);
/*Ammo_AutoFill(pl.fSlotPrimary);
Ammo_AutoFill(pl.fSlotSecondary);*/
if (autocvar_fcs_fillweapons) {
Ammo_BuyPrimary(pl, TRUE);
Ammo_BuySecondary(pl, TRUE);
}
}
void
@ -814,6 +847,28 @@ 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.
=================
*/
static void
MakePlayable(entity targ)
{
entity oself = self;
self = targ;
if (clienttype(targ) != CLIENTTYPE_REAL)
spawnfunc_csbot();
else
spawnfunc_player();
self = oself;
}
static void
MakeSpectator(entity targ)
{
entity oself = self;
self = targ;
spawnfunc_spectator();
self = oself;
}
void
CSMultiplayerRules::PlayerMakePlayable(base_player pp, int chara)
{
@ -824,6 +879,7 @@ CSMultiplayerRules::PlayerMakePlayable(base_player pp, int chara)
return;
}
MakePlayable(pp);
pl.g_items |= ITEM_SUIT;
Weapons_AddItem(pl, WEAPON_KNIFE, -1);
@ -858,23 +914,8 @@ Force the player to become an observer.
void
CSMultiplayerRules::PlayerMakeSpectator(base_player pl)
{
pl.classname = "dead";
pl.health = 0;
pl.armor = 0;
pl.takedamage = DAMAGE_NO;
pl.solid = SOLID_NOT;
pl.movetype = MOVETYPE_NOCLIP;
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");
/* clear the inventory */
pl.items = 0x0;
pl.activeweapon = 0;
PlayerClearWeaponry(pl);
MakeSpectator(pl);
}
/*
@ -895,10 +936,17 @@ CSMultiplayerRules::PlayerSpawn(base_player pl)
Money_AddMoney(pl, autocvar_mp_startmoney);
/* we don't belong to any team */
pl.team = 0;
pl.team = TEAM_SPECTATOR;
forceinfokey(pl, "*team", "0");
}
void
CSMultiplayerRules_BotJoin(void)
{
spawnfunc_csbot();
CSEv_JoinAuto();
}
float
CSMultiplayerRules::ConsoleCommand(base_player pp, string cmd)
{
@ -908,7 +956,7 @@ CSMultiplayerRules::ConsoleCommand(base_player pp, string cmd)
case "bot_add":
entity bot_ent = Bot_AddQuick();
if (bot_ent) {
bot_ent.think = CSEv_JoinAuto;
bot_ent.think = CSMultiplayerRules_BotJoin;
bot_ent.nextthink = time;
}
break;
@ -976,21 +1024,19 @@ CSEv_JoinTeam_f(float flChar)
return;
}
if (flChar < 5) {
pl.team = TEAM_T;
} else {
pl.team = TEAM_CT;
}
rules.PlayerMakeSpectator(pl);
pl.classname = "player";
//PlayerMakeSpectator(pl);
pl.charmodel = (int)flChar;
pl.health = 0;
forceinfokey(pl, "*dead", "1");
forceinfokey(pl, "*team", ftos(pl.team));
break;
}
if (flChar < 5)
pl.team = TEAM_T;
else
pl.team = TEAM_CT;
forceinfokey(pl, "*team", ftos(pl.team));
pl.frags = 0;
pl.deaths = 0;
forceinfokey(pl, "*deaths", ftos(pl.deaths));
@ -1008,20 +1054,10 @@ CSEv_JoinTeam_f(float flChar)
void
CSEv_JoinAuto(void)
{
int ct_count = 0;
int t_count = 1;
CSMultiplayerRules rules = (CSMultiplayerRules)g_grMode;
rules.CountPlayers();
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
player pl = (player)eFind;
if (pl.team == TEAM_T) {
t_count++;
}
if (pl.team == TEAM_CT) {
ct_count++;
}
}
if (ct_count >= t_count) {
if (g_cs_total_ct >= g_cs_total_t) {
CSEv_JoinTeam_f(floor(random(1,5)));
} else {
CSEv_JoinTeam_f(floor(random(5,9)));

View File

@ -46,7 +46,7 @@ CSSingleplayerRules::PlayerSpawn(base_player pl)
setmodel(pl, pl.model);
setsize(pl, VEC_HULL_MIN, VEC_HULL_MAX);
pl.view_ofs = VEC_PLAYER_VIEWPOS;
pl.view_ofs = PHY_VIEWPOS;
pl.velocity = [0,0,0];
pl.gravity = __NULL__;
pl.frame = 1;

View File

@ -165,9 +165,23 @@ hostage_entity::Death(void)
WarnAllies();
if (style != MONSTER_DEAD) {
SetFrame(HOSA_DIE_SIMPLE + floor(random(0, 6)));
switch (g_dmg_iHitBody) {
case BODY_HEAD:
SetFrame(HOSA_DIE_HEADSHOT);
break;
case BODY_STOMACH:
SetFrame(HOSA_DIE_GUTSHOT);
break;
default:
SetFrame(HOSA_DIE_SIMPLE + floor(random(0,4)));
break;
}
}
/* HACK: don't let them gib */
health = 0;
solid = SOLID_NOT;
/* now mark our state as 'dead' */
CBaseNPC::Death();

View File

@ -59,6 +59,7 @@ info_hostage_rescue::touch(void)
return;
Radio_BroadcastMessage(RADIO_RESCUED);
CSBot_HostageRescueNotify();
g_cs_hostagesrescued++;
Money_AddMoney((player)hosty.m_eFollowing, 1000);

View File

@ -38,6 +38,7 @@ item_suit.qc
../../../valve/src/server/items.qc
../../../src/botlib/include.src
bot.qc
game_money.qc
gamerules.qc
@ -50,7 +51,7 @@ ammo.qc
buy.qc
server.qc
../../../base/src/server/damage.qc
../../../valve/src/server/rules.qc
rules.qc
../../../valve/src/server/flashlight.qc
../../../base/src/server/modelevent.qc

View File

@ -94,12 +94,12 @@ Triggered by clients, plays a message to members of the same team
void
CSEv_Radio_f(float fMessage)
{
static void CSEv_Radio_Send(float fMessage, entity eEnt) {
static void CSEv_Radio_Send(float fMessage, entity eEnt, entity eTarg) {
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_RADIOMSG2);
WriteByte(MSG_MULTICAST, num_for_edict(eEnt) - 1);
WriteByte(MSG_MULTICAST, fMessage);
msg_entity = eEnt;
msg_entity = eTarg;
multicast([0,0,0], MULTICAST_ONE);
}
@ -121,9 +121,9 @@ CSEv_Radio_f(float fMessage)
for (entity eFind = world; (eFind = find(eFind, classname, "player"));) {
if (eFind.team == fTargetTeam) {
CSEv_Radio_Send(fMessage, eFind);
CSEv_Radio_Send(fMessage, self, eFind);
} else if (eFind.team == TEAM_VIP && fTargetTeam == TEAM_CT) {
CSEv_Radio_Send(fMessage, eFind);
CSEv_Radio_Send(fMessage, self, eFind);
}
}

5
src/server/rules.qc Normal file
View File

@ -0,0 +1,5 @@
int
Rules_IsTeamPlay(void)
{
return 1;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -122,9 +122,11 @@ Animation_PlayerUpdate(player pl)
void
Animation_PlayerTop(player pl, float topanim, float timer)
{
#if 0
pl.anim_top = topanim;
pl.anim_top_time = 0.0f;
pl.anim_top_delay = timer;
#endif
}
void

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2019 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -21,6 +21,7 @@
#include "entities.h"
#include "events.h"
#define TEAM_SPECTATOR 0
#define TEAM_T 1
#define TEAM_CT 2
#define TEAM_VIP 3

View File

@ -1,115 +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.
*/
#ifdef SERVER
void
CSEv_PlayerBuyEquipment_f(float fID) {
/* if (Rules_BuyingPossible() == FALSE) {
return;
}
if ((self.fMoney - eqptTable[fID].iPrice) >= 0) {
if (eqptTable[fID].iID == EQUIPMENT_DEFUSALKIT) {
if (self.team == TEAM_T) { return; }
if (!(self.iEquipment & EQUIPMENT_DEFUSALKIT)) {
self.iEquipment |= EQUIPMENT_DEFUSALKIT;
Money_AddMoney(self, -200);
sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE);
} else {
centerprint(self, "You already have a defusal kit!");
}
} else if (eqptTable[fID].iID == EQUIPMENT_NIGHTVISION) {
if (!(self.iEquipment & EQUIPMENT_NIGHTVISION)) {
self.iEquipment |= EQUIPMENT_NIGHTVISION;
Money_AddMoney(self, -1250);
sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE);
} else {
centerprint(self, "You already have nightvision goggles!");
}
} else if (eqptTable[fID].iID == WEAPON_HEGRENADE) {
if (self.iAmmo_HEGRENADE < 2) {
self.iAmmo_HEGRENADE++;
Money_AddMoney(self, -300);
sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE);
} else {
centerprint(self, "You can't carry any more!");
}
} else if (eqptTable[fID].iID == WEAPON_FLASHBANG) {
if (self.iAmmo_FLASHBANG < 2) {
self.iAmmo_FLASHBANG++;
Money_AddMoney(self, -300);
sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE);
} else {
centerprint(self, "You can't carry any more!");
}
} else if (eqptTable[fID].iID == WEAPON_SMOKEGRENADE) {
if (self.iAmmo_SMOKEGRENADE < 2) {
self.iAmmo_SMOKEGRENADE++;
Money_AddMoney(self, -300);
sound(self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE);
} else {
centerprint(self, "You can't carry any more!");
}
} else if (eqptTable[fID].iID == EQUIPMENT_KEVLAR) {
if (self.armor == 100) {
// You already own kevlar etc.
centerprint(self, "You already have kevlar!");
} else {
self.armor = 100;
Money_AddMoney(self, -650);
}
sound(self, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_IDLE);
self.fAttackFinished = time + 1.0;
return;
} else if (eqptTable[fID].iID == EQUIPMENT_HELMET) {
if (self.armor == 100) {
if (self.iEquipment & EQUIPMENT_HELMET) {
// You already have full kevlar and a helmet
centerprint(self, "You already have kevlar and a helmet!");
} else {
// You have full kevlar, but no helmet
Money_AddMoney(self, -350);
sound(self, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_IDLE);
centerprint(self, "You already have some kevlar,\nand now you've bought a helmet!");
self.iEquipment = self.iEquipment | EQUIPMENT_HELMET;
}
} else {
if (self.iEquipment & EQUIPMENT_HELMET) {
// Only get kevlar
self.armor = 100;
Money_AddMoney(self, -650);
sound(self, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_IDLE);
centerprint(self, "You already have a helmet,\nand now you've bought some kevlar!");
} else {
// Get both
self.armor = 100;
self.iEquipment = self.iEquipment | EQUIPMENT_HELMET;
Money_AddMoney(self, -1000);
sound(self, CHAN_ITEM, "items/tr_kevlar.wav", 1, ATTN_IDLE);
}
}
self.fAttackFinished = time + 1.0;
return;
}
} else {
centerprint(self, "You have insufficient funds!");
}
self.fAttackFinished = time + 1.0;*/
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -198,6 +198,7 @@ C4Bomb_Plant(base_player planter)
bomb.SendFlags = -1;
Radio_BroadcastMessage(RADIO_BOMBPL);
CSBot_BombPlantedNotify();
g_cs_bombplanted = TRUE;
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
* Copyright (c) 2016-2021 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
@ -25,6 +25,10 @@
#define PMOVE_ACCELERATE 4
#define PMOVE_MAXSPEED 250
/* Counter-Strike players are hunched over a little bit */
#define PHY_VIEWPOS [0,0,18]
#define PHY_VIEWPOS_CROUCHED [0,0,12]
.float waterlevel;
.float watertype;
@ -130,9 +134,10 @@ GamePMove_Maxspeed(player target)
void
GamePMove_Fall(player target, float impactspeed)
{
impactspeed *= 1.25f;
if (impactspeed > 580) {
#ifdef SERVER
float fFallDamage = (impactspeed - 580) * (100 / (1024 - 580)) * 1.75f;
float fFallDamage = (impactspeed - 580) * (100 / (1024 - 580)) * 0.75f;
Damage_Apply(target, world, fFallDamage, 0, DMG_FALL);
if (random() < 0.5)
@ -157,6 +162,6 @@ GamePMove_Jump(player target)
} else {
/* slow the player down a bit to prevent bhopping like crazy */
target.velocity *= 0.80f;
target.velocity[2] += 220;
target.velocity[2] += 200;
}
}

View File

@ -247,6 +247,17 @@ w_ak47_hud(void)
#endif
}
int
w_ak47_isempty(void)
{
player pl = (player)self;
if (pl.ak47_mag <= 0 && pl.ammo_762mm <= 0)
return 1;
return 0;
}
void
w_ak47_hudpic(int selected, vector pos, float a)
{
@ -254,7 +265,7 @@ w_ak47_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.ak47_mag == 0 && pl.ammo_762mm == 0)
if (w_ak47_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -293,6 +304,7 @@ weapon_t w_ak47 =
.id = ITEM_AK47,
.slot = 0,
.slot_pos = 7,
.weight = 25,
.allow_drop = TRUE,
.draw = w_ak47_draw,
.holster = __NULL__,
@ -308,7 +320,8 @@ weapon_t w_ak47 =
.pmodel = w_ak47_pmodel,
.deathmsg = w_ak47_deathmsg,
.aimanim = w_ak47_aimanim,
.hudpic = w_ak47_hudpic
.hudpic = w_ak47_hudpic,
.isempty = w_ak47_isempty
};
#ifdef SERVER

View File

@ -237,6 +237,17 @@ w_aug_hud(void)
#endif
}
int
w_aug_isempty(void)
{
player pl = (player)self;
if (pl.aug_mag <= 0 && pl.ammo_762mm <= 0)
return 1;
return 0;
}
void
w_aug_hudpic(int selected, vector pos, float a)
{
@ -244,7 +255,7 @@ w_aug_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.aug_mag == 0 && pl.ammo_762mm == 0)
if (w_aug_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -283,6 +294,7 @@ weapon_t w_aug =
.id = ITEM_AUG,
.slot = 0,
.slot_pos = 10,
.weight = 25,
.allow_drop = TRUE,
.draw = w_aug_draw,
.holster = __NULL__,
@ -298,7 +310,8 @@ weapon_t w_aug =
.pmodel = w_aug_pmodel,
.deathmsg = w_aug_deathmsg,
.aimanim = w_aug_aimanim,
.hudpic = w_aug_hudpic
.hudpic = w_aug_hudpic,
.isempty = w_aug_isempty
};
#ifdef SERVER

View File

@ -288,6 +288,17 @@ w_awp_hud(void)
#endif
}
int
w_awp_isempty(void)
{
player pl = (player)self;
if (pl.awp_mag <= 0 && pl.ammo_338mag <= 0)
return 1;
return 0;
}
void
w_awp_hudpic(int selected, vector pos, float a)
{
@ -295,7 +306,7 @@ w_awp_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.awp_mag == 0 && pl.ammo_338mag == 0)
if (w_awp_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -334,6 +345,7 @@ weapon_t w_awp =
.id = ITEM_AWP,
.slot = 0,
.slot_pos = 12,
.weight = 30,
.allow_drop = TRUE,
.draw = w_awp_draw,
.holster = __NULL__,
@ -349,7 +361,8 @@ weapon_t w_awp =
.pmodel = w_awp_pmodel,
.deathmsg = w_awp_deathmsg,
.aimanim = w_awp_aimanim,
.hudpic = w_awp_hudpic
.hudpic = w_awp_hudpic,
.isempty = w_awp_isempty
};
#ifdef SERVER

View File

@ -246,6 +246,17 @@ w_deagle_hud(void)
#endif
}
int
w_deagle_isempty(void)
{
player pl = (player)self;
if (pl.deagle_mag <= 0 && pl.ammo_50ae <= 0)
return 1;
return 0;
}
void
w_deagle_hudpic(int selected, vector pos, float a)
{
@ -253,7 +264,7 @@ w_deagle_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.deagle_mag == 0 && pl.ammo_50ae == 0)
if (w_deagle_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -292,6 +303,7 @@ weapon_t w_deagle =
.id = ITEM_DEAGLE,
.slot = 1,
.slot_pos = 2,
.weight = 7,
.allow_drop = TRUE,
.draw = w_deagle_draw,
.holster = __NULL__,
@ -307,7 +319,8 @@ weapon_t w_deagle =
.pmodel = w_deagle_pmodel,
.deathmsg = w_deagle_deathmsg,
.aimanim = w_deagle_aimanim,
.hudpic = w_deagle_hudpic
.hudpic = w_deagle_hudpic,
.isempty = w_deagle_isempty
};
#ifdef SERVER

View File

@ -316,6 +316,17 @@ w_elites_hud(void)
#endif
}
int
w_elites_isempty(void)
{
player pl = (player)self;
if (pl.elites_mag <= 0 && pl.ammo_9mm <= 0)
return 1;
return 0;
}
void
w_elites_hudpic(int selected, vector pos, float a)
{
@ -323,7 +334,7 @@ w_elites_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.elites_mag == 0 && pl.ammo_9mm == 0)
if (w_elites_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -362,6 +373,7 @@ weapon_t w_elites =
.id = ITEM_ELITES,
.slot = 1,
.slot_pos = 4,
.weight = 5,
.allow_drop = TRUE,
.draw = w_elites_draw,
.holster = __NULL__,
@ -377,7 +389,8 @@ weapon_t w_elites =
.pmodel = w_elites_pmodel,
.deathmsg = w_elites_deathmsg,
.aimanim = w_elites_aimanim,
.hudpic = w_elites_hudpic
.hudpic = w_elites_hudpic,
.isempty = w_elites_isempty
};
#ifdef SERVER

View File

@ -215,6 +215,17 @@ w_fiveseven_hud(void)
#endif
}
int
w_fiveseven_isempty(void)
{
player pl = (player)self;
if (pl.fiveseven_mag <= 0 && pl.ammo_57mm <= 0)
return 1;
return 0;
}
void
w_fiveseven_hudpic(int selected, vector pos, float a)
{
@ -222,7 +233,7 @@ w_fiveseven_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.fiveseven_mag == 0 && pl.ammo_57mm == 0)
if (w_fiveseven_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -261,6 +272,7 @@ weapon_t w_fiveseven =
.id = ITEM_FIVESEVEN,
.slot = 1,
.slot_pos = 5,
.weight = 5,
.allow_drop = TRUE,
.draw = w_fiveseven_draw,
.holster = __NULL__,
@ -276,7 +288,8 @@ weapon_t w_fiveseven =
.pmodel = w_fiveseven_pmodel,
.deathmsg = w_fiveseven_deathmsg,
.aimanim = w_fiveseven_aimanim,
.hudpic = w_fiveseven_hudpic
.hudpic = w_fiveseven_hudpic,
.isempty = w_fiveseven_isempty
};
#ifdef SERVER

View File

@ -228,6 +228,17 @@ w_flashbang_hud(void)
#endif
}
int
w_flashbang_isempty(void)
{
player pl = (player)self;
if (pl.ammo_fbgrenade <= 0)
return 1;
return 0;
}
void
w_flashbang_hudpic(int selected, vector pos, float a)
{
@ -283,7 +294,8 @@ weapon_t w_flashbang =
.pmodel = w_flashbang_pmodel,
.deathmsg = w_flashbang_deathmsg,
.aimanim = w_flashbang_aimanim,
.hudpic = w_flashbang_hudpic
.hudpic = w_flashbang_hudpic,
.isempty = w_flashbang_isempty
};
#ifdef SERVER

View File

@ -227,6 +227,17 @@ w_g3sg1_hud(void)
#endif
}
int
w_g3sg1_isempty(void)
{
player pl = (player)self;
if (pl.g3sg1_mag <= 0 && pl.ammo_762mm <= 0)
return 1;
return 0;
}
void
w_g3sg1_hudpic(int selected, vector pos, float a)
{
@ -234,7 +245,7 @@ w_g3sg1_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.g3sg1_mag == 0 && pl.ammo_762mm == 0)
if (w_g3sg1_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -273,6 +284,7 @@ weapon_t w_g3sg1 =
.id = ITEM_G3SG1,
.slot = 0,
.slot_pos = 13,
.weight = 25,
.allow_drop = TRUE,
.draw = w_g3sg1_draw,
.holster = __NULL__,
@ -288,7 +300,8 @@ weapon_t w_g3sg1 =
.pmodel = w_g3sg1_pmodel,
.deathmsg = w_g3sg1_deathmsg,
.aimanim = w_g3sg1_aimanim,
.hudpic = w_g3sg1_hudpic
.hudpic = w_g3sg1_hudpic,
.isempty = w_g3sg1_isempty
};
#ifdef SERVER

View File

@ -282,6 +282,17 @@ w_glock18_hud(void)
#endif
}
int
w_glock18_isempty(void)
{
player pl = (player)self;
if (pl.glock18_mag <= 0 && pl.ammo_9mm <= 0)
return 1;
return 0;
}
void
w_glock18_hudpic(int selected, vector pos, float a)
{
@ -289,7 +300,7 @@ w_glock18_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.glock18_mag == 0 && pl.ammo_9mm == 0)
if (w_glock18_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -328,6 +339,7 @@ weapon_t w_glock18 =
.id = ITEM_GLOCK18,
.slot = 1,
.slot_pos = 1,
.weight = 5,
.allow_drop = TRUE,
.draw = w_glock18_draw,
.holster = __NULL__,
@ -343,7 +355,8 @@ weapon_t w_glock18 =
.pmodel = w_glock18_pmodel,
.deathmsg = w_glock18_deathmsg,
.aimanim = w_glock18_aimanim,
.hudpic = w_glock18_hudpic
.hudpic = w_glock18_hudpic,
.isempty = w_glock18_isempty
};
#ifdef SERVER

View File

@ -230,6 +230,17 @@ w_hegrenade_hud(void)
#endif
}
int
w_hegrenade_isempty(void)
{
player pl = (player)self;
if (pl.ammo_hegrenade <= 0)
return 1;
return 0;
}
void
w_hegrenade_hudpic(int selected, vector pos, float a)
{
@ -285,7 +296,8 @@ weapon_t w_hegrenade =
.pmodel = w_hegrenade_pmodel,
.deathmsg = w_hegrenade_deathmsg,
.aimanim = w_hegrenade_aimanim,
.hudpic = w_hegrenade_hudpic
.hudpic = w_hegrenade_hudpic,
.isempty = w_hegrenade_isempty
};
#ifdef SERVER

View File

@ -183,6 +183,12 @@ w_knife_aimanim(void)
return self.flags & FL_CROUCHING ? ANIM_CROUCH_AIM_KNIFE : ANIM_AIM_KNIFE;
}
int
w_knife_isempty(void)
{
return 0;
}
void
w_knife_hudpic(int selected, vector pos, float a)
{
@ -234,7 +240,8 @@ weapon_t w_knife =
.pmodel = w_knife_pmodel,
.deathmsg = w_knife_deathmsg,
.aimanim = w_knife_aimanim,
.hudpic = w_knife_hudpic
.hudpic = w_knife_hudpic,
.isempty = w_knife_isempty
};
#ifdef SERVER

View File

@ -294,6 +294,17 @@ w_m3_hud(void)
#endif
}
int
w_m3_isempty(void)
{
player pl = (player)self;
if (pl.m3_mag <= 0 && pl.ammo_buckshot <= 0)
return 1;
return 0;
}
void
w_m3_hudpic(int selected, vector pos, float a)
{
@ -301,7 +312,7 @@ w_m3_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.m3_mag == 0 && pl.ammo_buckshot == 0)
if (w_m3_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -340,6 +351,7 @@ weapon_t w_m3 =
.id = ITEM_M3,
.slot = 0,
.slot_pos = 0,
.weight = 20,
.allow_drop = TRUE,
.draw = w_m3_draw,
.holster = __NULL__,
@ -355,7 +367,8 @@ weapon_t w_m3 =
.pmodel = w_m3_pmodel,
.deathmsg = w_m3_deathmsg,
.aimanim = w_m3_aimanim,
.hudpic = w_m3_hudpic
.hudpic = w_m3_hudpic,
.isempty = w_m3_isempty
};
#ifdef SERVER

View File

@ -287,6 +287,17 @@ w_m4a1_release(void)
pl.w_idle_next = 5.0f;
}
int
w_m4a1_isempty(void)
{
player pl = (player)self;
if (pl.m4a1_mag <= 0 && pl.ammo_556mm <= 0)
return 1;
return 0;
}
void
w_m4a1_hudpic(int selected, vector pos, float a)
{
@ -294,7 +305,7 @@ w_m4a1_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.m4a1_mag == 0 && pl.ammo_556mm == 0)
if (w_m4a1_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -333,6 +344,7 @@ weapon_t w_m4a1 =
.id = ITEM_M4A1,
.slot = 0,
.slot_pos = 9,
.weight = 25,
.allow_drop = TRUE,
.draw = w_m4a1_draw,
.holster = __NULL__,
@ -348,7 +360,8 @@ weapon_t w_m4a1 =
.pmodel = w_m4a1_pmodel,
.deathmsg = w_m4a1_deathmsg,
.aimanim = w_m4a1_aimanim,
.hudpic = w_m4a1_hudpic
.hudpic = w_m4a1_hudpic,
.isempty = w_m4a1_isempty
};
#ifdef SERVER

View File

@ -210,6 +210,17 @@ w_mac10_hud(void)
#endif
}
int
w_mac10_isempty(void)
{
player pl = (player)self;
if (pl.mac10_mag <= 0 && pl.ammo_45acp <= 0)
return 1;
return 0;
}
void
w_mac10_hudpic(int selected, vector pos, float a)
{
@ -217,7 +228,7 @@ w_mac10_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.mac10_mag == 0 && pl.ammo_45acp == 0)
if (w_mac10_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -256,6 +267,7 @@ weapon_t w_mac10 =
.id = ITEM_MAC10,
.slot = 0,
.slot_pos = 5,
.weight = 25,
.allow_drop = TRUE,
.draw = w_mac10_draw,
.holster = __NULL__,
@ -271,7 +283,8 @@ weapon_t w_mac10 =
.pmodel = w_mac10_pmodel,
.deathmsg = w_mac10_deathmsg,
.aimanim = w_mac10_aimanim,
.hudpic = w_mac10_hudpic
.hudpic = w_mac10_hudpic,
.isempty = w_mac10_isempty
};
#ifdef SERVER

View File

@ -208,6 +208,17 @@ w_mp5_hud(void)
#endif
}
int
w_mp5_isempty(void)
{
player pl = (player)self;
if (pl.mp5_mag <= 0 && pl.ammo_9mm <= 0)
return 1;
return 0;
}
void
w_mp5_hudpic(int selected, vector pos, float a)
{
@ -215,7 +226,7 @@ w_mp5_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.mp5_mag == 0 && pl.ammo_9mm == 0)
if (w_mp5_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -254,6 +265,7 @@ weapon_t w_mp5 =
.id = ITEM_MP5,
.slot = 0,
.slot_pos = 2,
.weight = 25,
.allow_drop = TRUE,
.draw = w_mp5_draw,
.holster = __NULL__,
@ -269,7 +281,8 @@ weapon_t w_mp5 =
.pmodel = w_mp5_pmodel,
.deathmsg = w_mp5_deathmsg,
.aimanim = w_mp5_aimanim,
.hudpic = w_mp5_hudpic
.hudpic = w_mp5_hudpic,
.isempty = w_mp5_isempty
};
#ifdef SERVER

View File

@ -216,6 +216,17 @@ w_p228_hud(void)
#endif
}
int
w_p228_isempty(void)
{
player pl = (player)self;
if (pl.p228_mag <= 0 && pl.ammo_357sig <= 0)
return 1;
return 0;
}
void
w_p228_hudpic(int selected, vector pos, float a)
{
@ -223,7 +234,7 @@ w_p228_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.p228_mag == 0 && pl.ammo_357sig == 0)
if (w_p228_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -262,6 +273,7 @@ weapon_t w_p228 =
.id = ITEM_P228,
.slot = 1,
.slot_pos = 3,
.weight = 5,
.allow_drop = TRUE,
.draw = w_p228_draw,
.holster = __NULL__,
@ -277,7 +289,8 @@ weapon_t w_p228 =
.pmodel = w_p228_pmodel,
.deathmsg = w_p228_deathmsg,
.aimanim = w_p228_aimanim,
.hudpic = w_p228_hudpic
.hudpic = w_p228_hudpic,
.isempty = w_p228_isempty
};
#ifdef SERVER

View File

@ -208,6 +208,17 @@ w_p90_hud(void)
#endif
}
int
w_p90_isempty(void)
{
player pl = (player)self;
if (pl.p90_mag <= 0 && pl.ammo_57mm <= 0)
return 1;
return 0;
}
void
w_p90_hudpic(int selected, vector pos, float a)
{
@ -215,7 +226,7 @@ w_p90_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.p90_mag == 0 && pl.ammo_57mm == 0)
if (w_p90_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -254,6 +265,7 @@ weapon_t w_p90 =
.id = ITEM_P90,
.slot = 0,
.slot_pos = 3,
.weight = 26,
.allow_drop = TRUE,
.draw = w_p90_draw,
.holster = __NULL__,
@ -269,7 +281,8 @@ weapon_t w_p90 =
.pmodel = w_p90_pmodel,
.deathmsg = w_p90_deathmsg,
.aimanim = w_p90_aimanim,
.hudpic = w_p90_hudpic
.hudpic = w_p90_hudpic,
.isempty = w_p90_isempty
};
#ifdef SERVER

View File

@ -204,6 +204,17 @@ w_para_hud(void)
#endif
}
int
w_para_isempty(void)
{
player pl = (player)self;
if (pl.para_mag <= 0 && pl.ammo_556mmbox <= 0)
return 1;
return 0;
}
void
w_para_hudpic(int selected, vector pos, float a)
{
@ -211,7 +222,7 @@ w_para_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.para_mag == 0 && pl.ammo_556mmbox == 0)
if (w_para_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -250,6 +261,7 @@ weapon_t w_para =
.id = ITEM_PARA,
.slot = 0,
.slot_pos = 15,
.weight = 25,
.allow_drop = TRUE,
.draw = w_para_draw,
.holster = __NULL__,
@ -265,7 +277,8 @@ weapon_t w_para =
.pmodel = w_para_pmodel,
.deathmsg = w_para_deathmsg,
.aimanim = w_para_aimanim,
.hudpic = w_para_hudpic
.hudpic = w_para_hudpic,
.isempty = w_para_isempty
};
#ifdef SERVER

View File

@ -251,6 +251,17 @@ w_scout_hud(void)
#endif
}
int
w_scout_isempty(void)
{
player pl = (player)self;
if (pl.scout_mag <= 0 && pl.ammo_762mm <= 0)
return 1;
return 0;
}
void
w_scout_hudpic(int selected, vector pos, float a)
{
@ -258,7 +269,7 @@ w_scout_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.scout_mag == 0 && pl.ammo_762mm == 0)
if (w_scout_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -297,6 +308,7 @@ weapon_t w_scout =
.id = ITEM_SCOUT,
.slot = 0,
.slot_pos = 11,
.weight = 30,
.allow_drop = TRUE,
.draw = w_scout_draw,
.holster = __NULL__,
@ -312,7 +324,8 @@ weapon_t w_scout =
.pmodel = w_scout_pmodel,
.deathmsg = w_scout_deathmsg,
.aimanim = w_scout_aimanim,
.hudpic = w_scout_hudpic
.hudpic = w_scout_hudpic,
.isempty = w_scout_isempty
};
#ifdef SERVER

View File

@ -227,6 +227,17 @@ w_sg550_hud(void)
#endif
}
int
w_sg550_isempty(void)
{
player pl = (player)self;
if (pl.sg550_mag <= 0 && pl.ammo_556mm <= 0)
return 1;
return 0;
}
void
w_sg550_hudpic(int selected, vector pos, float a)
{
@ -234,7 +245,7 @@ w_sg550_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.sg550_mag == 0 && pl.ammo_556mm == 0)
if (w_sg550_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -273,6 +284,7 @@ weapon_t w_sg550 =
.id = ITEM_SG550,
.slot = 0,
.slot_pos = 14,
.weight = 20,
.allow_drop = TRUE,
.draw = w_sg550_draw,
.holster = __NULL__,
@ -288,7 +300,8 @@ weapon_t w_sg550 =
.pmodel = w_sg550_pmodel,
.deathmsg = w_sg550_deathmsg,
.aimanim = w_sg550_aimanim,
.hudpic = w_sg550_hudpic
.hudpic = w_sg550_hudpic,
.isempty = w_sg550_isempty
};
#ifdef SERVER

View File

@ -234,6 +234,17 @@ w_sg552_hud(void)
#endif
}
int
w_sg552_isempty(void)
{
player pl = (player)self;
if (pl.sg552_mag <= 0 && pl.ammo_556mm <= 0)
return 1;
return 0;
}
void
w_sg552_hudpic(int selected, vector pos, float a)
{
@ -241,7 +252,7 @@ w_sg552_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.sg552_mag == 0 && pl.ammo_556mm == 0)
if (w_sg552_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -280,6 +291,7 @@ weapon_t w_sg552 =
.id = ITEM_SG552,
.slot = 0,
.slot_pos = 8,
.weight = 25,
.allow_drop = TRUE,
.draw = w_sg552_draw,
.holster = __NULL__,
@ -295,7 +307,8 @@ weapon_t w_sg552 =
.pmodel = w_sg552_pmodel,
.deathmsg = w_sg552_deathmsg,
.aimanim = w_sg552_aimanim,
.hudpic = w_sg552_hudpic
.hudpic = w_sg552_hudpic,
.isempty = w_sg552_isempty
};
#ifdef SERVER

View File

@ -226,6 +226,17 @@ w_smokegrenade_hud(void)
#endif
}
int
w_smokegrenade_isempty(void)
{
player pl = (player)self;
if (pl.ammo_smokegrenade <= 0)
return 1;
return 0;
}
void
w_smokegrenade_hudpic(int selected, vector pos, float a)
{
@ -281,7 +292,8 @@ weapon_t w_smokegrenade =
.pmodel = w_smokegrenade_pmodel,
.deathmsg = w_smokegrenade_deathmsg,
.aimanim = w_smokegrenade_aimanim,
.hudpic = w_smokegrenade_hudpic
.hudpic = w_smokegrenade_hudpic,
.isempty = w_smokegrenade_isempty
};
#ifdef SERVER

View File

@ -208,6 +208,17 @@ w_tmp_hud(void)
#endif
}
int
w_tmp_isempty(void)
{
player pl = (player)self;
if (pl.tmp_mag <= 0 && pl.ammo_9mm <= 0)
return 1;
return 0;
}
void
w_tmp_hudpic(int selected, vector pos, float a)
{
@ -215,7 +226,7 @@ w_tmp_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.tmp_mag == 0 && pl.ammo_9mm == 0)
if (w_tmp_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -254,6 +265,7 @@ weapon_t w_tmp =
.id = ITEM_TMP,
.slot = 0,
.slot_pos = 6,
.weight = 25,
.allow_drop = TRUE,
.draw = w_tmp_draw,
.holster = __NULL__,
@ -269,7 +281,8 @@ weapon_t w_tmp =
.pmodel = w_tmp_pmodel,
.deathmsg = w_tmp_deathmsg,
.aimanim = w_tmp_aimanim,
.hudpic = w_tmp_hudpic
.hudpic = w_tmp_hudpic,
.isempty = w_tmp_isempty
};
#ifdef SERVER

View File

@ -208,6 +208,17 @@ w_ump45_hud(void)
#endif
}
int
w_ump45_isempty(void)
{
player pl = (player)self;
if (pl.ump45_mag <= 0 && pl.ammo_45acp <= 0)
return 1;
return 0;
}
void
w_ump45_hudpic(int selected, vector pos, float a)
{
@ -215,7 +226,7 @@ w_ump45_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.ump45_mag == 0 && pl.ammo_45acp == 0)
if (w_ump45_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -254,6 +265,7 @@ weapon_t w_ump45 =
.id = ITEM_UMP45,
.slot = 0,
.slot_pos = 4,
.weight = 25,
.allow_drop = TRUE,
.draw = w_ump45_draw,
.holster = __NULL__,
@ -269,7 +281,8 @@ weapon_t w_ump45 =
.pmodel = w_ump45_pmodel,
.deathmsg = w_ump45_deathmsg,
.aimanim = w_ump45_aimanim,
.hudpic = w_ump45_hudpic
.hudpic = w_ump45_hudpic,
.isempty = w_ump45_isempty
};
#ifdef SERVER

View File

@ -286,6 +286,17 @@ w_usp45_hud(void)
#endif
}
int
w_usp45_isempty(void)
{
player pl = (player)self;
if (pl.usp45_mag <= 0 && pl.ammo_45acp <= 0)
return 1;
return 0;
}
void
w_usp45_hudpic(int selected, vector pos, float a)
{
@ -293,7 +304,7 @@ w_usp45_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.usp45_mag == 0 && pl.ammo_45acp == 0)
if (w_usp45_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -332,6 +343,7 @@ weapon_t w_usp45 =
.id = ITEM_USP45,
.slot = 1,
.slot_pos = 0,
.weight = 5,
.allow_drop = TRUE,
.draw = w_usp45_draw,
.holster = __NULL__,
@ -347,7 +359,8 @@ weapon_t w_usp45 =
.pmodel = w_usp45_pmodel,
.deathmsg = w_usp45_deathmsg,
.aimanim = w_usp45_aimanim,
.hudpic = w_usp45_hudpic
.hudpic = w_usp45_hudpic,
.isempty = w_usp45_isempty
};
#ifdef SERVER

View File

@ -296,6 +296,17 @@ w_xm1014_hud(void)
#endif
}
int
w_xm1014_isempty(void)
{
player pl = (player)self;
if (pl.xm1014_mag <= 0 && pl.ammo_buckshot <= 0)
return 1;
return 0;
}
void
w_xm1014_hudpic(int selected, vector pos, float a)
{
@ -303,7 +314,7 @@ w_xm1014_hudpic(int selected, vector pos, float a)
player pl = (player)self;
vector hud_col;
if (pl.xm1014_mag == 0 && pl.ammo_buckshot == 0)
if (w_xm1014_isempty())
hud_col = [1,0,0];
else
hud_col = g_hud_color;
@ -342,6 +353,7 @@ weapon_t w_xm1014 =
.id = ITEM_XM1014,
.slot = 0,
.slot_pos = 1,
.weight = 20,
.allow_drop = TRUE,
.draw = w_xm1014_draw,
.holster = __NULL__,
@ -357,7 +369,8 @@ weapon_t w_xm1014 =
.pmodel = w_xm1014_pmodel,
.deathmsg = w_xm1014_deathmsg,
.aimanim = w_xm1014_aimanim,
.hudpic = w_xm1014_hudpic
.hudpic = w_xm1014_hudpic,
.isempty = w_xm1014_isempty
};
#ifdef SERVER

View File

@ -63,3 +63,15 @@ seta "fcs_autoreload" "0"
seta "con_color" "255 150 0"
seta "vgui_color" "255 170 0"
seta "cross_color" "0 255 0"
// physics
seta sv_stepheight 18
seta sv_airstepheight 18
seta sv_friction 4
seta sv_edgefriction 1
seta sv_stopspeed 75
seta sv_gravity 800
seta sv_airaccelerate 10
seta sv_wateraccelerate 8
seta sv_accelerate 4
seta sv_maxspeed 250