Compare commits
2 Commits
d2e841d964
...
bc4bd883b4
Author | SHA1 | Date |
---|---|---|
Marco Cawthorne | bc4bd883b4 | |
Marco Cawthorne | 1c3fc2c32d |
|
@ -751,89 +751,17 @@ HUD_Draw(void)
|
||||||
HUD_PlayerNames();
|
HUD_PlayerNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* specatator main entry */
|
|
||||||
string g_specmodes[] = {
|
|
||||||
"Free Camera",
|
|
||||||
"Third Person",
|
|
||||||
"First Person"
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SPEC_SEP_COL [0.204,0.196,0.114]
|
|
||||||
#define SPEC_FG_COL [0.561,0.561,0.212]
|
|
||||||
void
|
void
|
||||||
HUD_DrawSpectator(void)
|
HUD_DrawSpectator(void)
|
||||||
{
|
{
|
||||||
vector vecPos = g_vec_null;
|
|
||||||
float flSep;
|
|
||||||
string strText;
|
|
||||||
int iMinutes, iSeconds;
|
|
||||||
|
|
||||||
Textmenu_Draw();
|
Textmenu_Draw();
|
||||||
Obituary_Draw();
|
Obituary_Draw();
|
||||||
|
|
||||||
Textmenu_Draw();
|
if (!g_specHUD)
|
||||||
|
g_specHUD = spawn(CSSpectateHUD);
|
||||||
|
|
||||||
/* parts on top and bottom */
|
g_specHUD.SetPos(video_mins);
|
||||||
drawfill(video_mins, [video_res[0], 32], [0,0,0], 0.75f, DRAWFLAG_NORMAL);
|
g_specHUD.SetSize(video_res);
|
||||||
drawfill(video_mins + [0, video_res[1]-32], [video_res[0], 32], [0,0,0], 0.75f, DRAWFLAG_NORMAL);
|
g_specHUD.Draw();
|
||||||
|
|
||||||
/* tracking player box */
|
|
||||||
drawrect(g_hudmins + [(g_hudres[0] / 2) - 111, g_hudres[1]-26], [222,20], 1.0f, SPEC_SEP_COL, 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
NSClientSpectator spec = (NSClientSpectator)pSeat->m_ePlayer;
|
|
||||||
strText = strcat(HUD_GetChatColorHEX(getplayerkeyfloat(spec.spec_ent - 1, "*team")), getplayerkeyvalue(spec.spec_ent - 1, "name"));
|
|
||||||
vecPos[0] = g_hudmins[0] + (g_hudres[0] / 2) - (stringwidth(strText, TRUE, [12,12]) / 2);
|
|
||||||
vecPos[1] = g_hudres[1]-21;
|
|
||||||
drawstring(vecPos, strText, [12,12], [1,1,1], 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
|
|
||||||
/* tracking mode box */
|
|
||||||
drawrect(g_hudmins + [(g_hudres[0] / 2) + 128, g_hudres[1]-26], [172,20], 1.0f, SPEC_SEP_COL, 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
strText = g_specmodes[spec.spec_mode];
|
|
||||||
vecPos[0] = (g_hudmins[0] + (g_hudres[0] / 2) + 214) - (stringwidth(strText, TRUE, [12,12]) / 2);
|
|
||||||
vecPos[1] = g_hudres[1]-21;
|
|
||||||
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
|
|
||||||
if (spec.spec_mode == SPECMODE_FIRSTPERSON) {
|
|
||||||
entity oself = self;
|
|
||||||
self = findfloat(world, ::entnum, spec.spec_ent);
|
|
||||||
if (self)
|
|
||||||
Cstrike_DrawCrosshair();
|
|
||||||
self = oself;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* money */
|
|
||||||
strText = sprintf("$ %i", getstati(STAT_MONEY));
|
|
||||||
flSep = stringwidth(strText, TRUE, [12,12]);
|
|
||||||
|
|
||||||
if (flSep < 42)
|
|
||||||
flSep = 42;
|
|
||||||
|
|
||||||
flSep = g_hudmins[0] + (g_hudres[0] - flSep) - 10;
|
|
||||||
|
|
||||||
vecPos[0] = flSep + 8;
|
|
||||||
vecPos[1] = g_hudmins[1] + 3;
|
|
||||||
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
|
|
||||||
/* score/money separator */
|
|
||||||
drawfill([flSep,1], [4,30], SPEC_SEP_COL, 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
|
|
||||||
/* team scores */
|
|
||||||
drawfont = Font_GetID(FONT_CON);
|
|
||||||
strText = sprintf("Terrorist Forces: %s", serverkey("teamscore_1"));
|
|
||||||
vecPos[0] = flSep - stringwidth(strText, TRUE, [12,12]) - 2;
|
|
||||||
vecPos[1] = g_hudmins[1] + 3;
|
|
||||||
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
|
|
||||||
strText = sprintf("CT Forces: %s", serverkey("teamscore_2"));
|
|
||||||
vecPos[0] = flSep - stringwidth(strText, TRUE, [12,12]) - 2;
|
|
||||||
vecPos[1] = g_hudmins[1] + 16;
|
|
||||||
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
|
|
||||||
/* time display */
|
|
||||||
drawpic([flSep + 8, 15], "gfx/vgui/640_timer", [14, 14], [1,1,1], 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
iMinutes = getstatf(STAT_GAMETIME) / 60;
|
|
||||||
iSeconds = getstatf(STAT_GAMETIME) - 60 * iMinutes;
|
|
||||||
strText = sprintf("%i:%02i", iMinutes, iSeconds);
|
|
||||||
vecPos[0] = flSep + 8 + 17;
|
|
||||||
vecPos[1] = g_hudmins[1] + 17;
|
|
||||||
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ crosshair.qc
|
||||||
../../../valve/src/client/obituary.qc
|
../../../valve/src/client/obituary.qc
|
||||||
../../../valve/src/client/hud_dmgnotify.qc
|
../../../valve/src/client/hud_dmgnotify.qc
|
||||||
hud_ammonotify.qc
|
hud_ammonotify.qc
|
||||||
|
vgui_spectator.qc
|
||||||
hud.qc
|
hud.qc
|
||||||
hud_weaponselect.qc
|
hud_weaponselect.qc
|
||||||
../../../valve/src/client/hud_sprite.qc
|
../../../valve/src/client/hud_sprite.qc
|
||||||
|
|
|
@ -90,7 +90,7 @@ VGUI_ChooseTeam(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void VGUI_ChooseTeam_Spec(void) {
|
static void VGUI_ChooseTeam_Spec(void) {
|
||||||
//sendevent("JoinAuto", "");
|
sendevent("JoinSpectator", "");
|
||||||
winChooseTeam.Hide();
|
winChooseTeam.Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Marco Cawthorne <marco@icculus.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SPEC_SEP_COL [0.204,0.196,0.114]
|
||||||
|
#define SPEC_FG_COL [0.561,0.561,0.212]
|
||||||
|
|
||||||
|
class
|
||||||
|
CSSpectateHUD:VGUIWidget
|
||||||
|
{
|
||||||
|
void CSSpectateHUD(void);
|
||||||
|
|
||||||
|
virtual void Draw(void);
|
||||||
|
};
|
||||||
|
CSSpectateHUD g_specHUD;
|
||||||
|
|
||||||
|
void
|
||||||
|
CSSpectateHUD::CSSpectateHUD(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CSSpectateHUD::Draw(void)
|
||||||
|
{
|
||||||
|
vector vecPos = g_vec_null;
|
||||||
|
float flSep;
|
||||||
|
string strText;
|
||||||
|
int iMinutes, iSeconds;
|
||||||
|
NSClientSpectator spec = (NSClientSpectator)pSeat->m_ePlayer;
|
||||||
|
|
||||||
|
/* parts on top and bottom */
|
||||||
|
drawfill(m_vecOrigin, [m_vecSize[0], 32], [0,0,0], 0.75f, DRAWFLAG_NORMAL);
|
||||||
|
drawfill(m_vecOrigin + [0, m_vecSize[1]-32], [m_vecSize[0], 32], [0,0,0], 0.75f, DRAWFLAG_NORMAL);
|
||||||
|
|
||||||
|
/* tracking player box */
|
||||||
|
drawrect(g_hudmins + [(g_hudres[0] / 2) - 111, g_hudres[1]-26], [222,20], 1.0f, SPEC_SEP_COL, 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
strText = strcat(HUD_GetChatColorHEX(getplayerkeyfloat(spec.spec_ent - 1, "*team")), getplayerkeyvalue(spec.spec_ent - 1, "name"));
|
||||||
|
vecPos[0] = g_hudmins[0] + (g_hudres[0] / 2) - (stringwidth(strText, TRUE, [12,12]) / 2);
|
||||||
|
vecPos[1] = g_hudres[1]-21;
|
||||||
|
drawstring(vecPos, strText, [12,12], [1,1,1], 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
|
||||||
|
/* tracking mode box */
|
||||||
|
drawrect(g_hudmins + [(g_hudres[0] / 2) + 128, g_hudres[1]-26], [172,20], 1.0f, SPEC_SEP_COL, 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
strText = g_specmodes[spec.spec_mode];
|
||||||
|
vecPos[0] = (g_hudmins[0] + (g_hudres[0] / 2) + 214) - (stringwidth(strText, TRUE, [12,12]) / 2);
|
||||||
|
vecPos[1] = g_hudres[1]-21;
|
||||||
|
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (spec.spec_mode == SPECMODE_FIRSTPERSON) {
|
||||||
|
entity oself = self;
|
||||||
|
self = findfloat(world, ::entnum, spec.spec_ent);
|
||||||
|
if (self)
|
||||||
|
Cstrike_DrawCrosshair();
|
||||||
|
self = oself;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* money */
|
||||||
|
strText = sprintf("$ %i", getstati(STAT_MONEY));
|
||||||
|
flSep = stringwidth(strText, TRUE, [12,12]);
|
||||||
|
|
||||||
|
if (flSep < 42)
|
||||||
|
flSep = 42;
|
||||||
|
|
||||||
|
flSep = g_hudmins[0] + (g_hudres[0] - flSep) - 10;
|
||||||
|
|
||||||
|
vecPos[0] = flSep + 8;
|
||||||
|
vecPos[1] = g_hudmins[1] + 3;
|
||||||
|
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
|
||||||
|
/* score/money separator */
|
||||||
|
drawfill([flSep,1], [4,30], SPEC_SEP_COL, 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
|
||||||
|
/* team scores */
|
||||||
|
drawfont = Font_GetID(FONT_CON);
|
||||||
|
strText = sprintf("Terrorist Forces: %s", serverkey("teamscore_1"));
|
||||||
|
vecPos[0] = flSep - stringwidth(strText, TRUE, [12,12]) - 2;
|
||||||
|
vecPos[1] = g_hudmins[1] + 3;
|
||||||
|
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
|
||||||
|
strText = sprintf("CT Forces: %s", serverkey("teamscore_2"));
|
||||||
|
vecPos[0] = flSep - stringwidth(strText, TRUE, [12,12]) - 2;
|
||||||
|
vecPos[1] = g_hudmins[1] + 16;
|
||||||
|
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
|
||||||
|
/* time display */
|
||||||
|
drawpic([flSep + 8, 15], "gfx/vgui/640_timer", [14, 14], [1,1,1], 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
iMinutes = getstatf(STAT_GAMETIME) / 60;
|
||||||
|
iSeconds = getstatf(STAT_GAMETIME) - 60 * iMinutes;
|
||||||
|
strText = sprintf("%i:%02i", iMinutes, iSeconds);
|
||||||
|
vecPos[0] = flSep + 8 + 17;
|
||||||
|
vecPos[1] = g_hudmins[1] + 17;
|
||||||
|
drawstring(vecPos, strText, [12,12], SPEC_FG_COL, 1.0f, DRAWFLAG_NORMAL);
|
||||||
|
}
|
|
@ -17,3 +17,4 @@
|
||||||
void CSBot_BombPlantedNotify(void);
|
void CSBot_BombPlantedNotify(void);
|
||||||
void CSBot_HostageRescueNotify(void);
|
void CSBot_HostageRescueNotify(void);
|
||||||
void CSBot_RoundStart(void);
|
void CSBot_RoundStart(void);
|
||||||
|
void CSBot_RestartRound(void);
|
||||||
|
|
|
@ -14,6 +14,15 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** @brief Get the absolute center pos of a entity */
|
||||||
|
vector getEntityCenterPos(entity e) {
|
||||||
|
vector newVec;
|
||||||
|
newVec[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0]));
|
||||||
|
newVec[1] = e.absmin[1] + (0.5 * (e.absmax[1] - e.absmin[1]));
|
||||||
|
newVec[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2]));
|
||||||
|
return newVec;
|
||||||
|
}
|
||||||
|
|
||||||
class csbot:bot
|
class csbot:bot
|
||||||
{
|
{
|
||||||
void(void) csbot;
|
void(void) csbot;
|
||||||
|
@ -21,15 +30,29 @@ class csbot:bot
|
||||||
/* some objectives */
|
/* some objectives */
|
||||||
virtual void(void) RunToConfront;
|
virtual void(void) RunToConfront;
|
||||||
virtual void(void) RunToBomb;
|
virtual void(void) RunToBomb;
|
||||||
virtual void(void) RunToBombsite;
|
virtual void(int) RunToBombsite;
|
||||||
virtual void(void) RunToEscapeZone;
|
virtual void(void) RunToRandomBombsite;
|
||||||
virtual void(void) RunToVIPSafetyZone;
|
virtual void(int) RunToEscapeZone;
|
||||||
|
virtual void(void) RunToRandomEscapeZone;
|
||||||
|
virtual void(int) RunToVIPSafetyZone;
|
||||||
|
virtual void(void) RunToRandomVIPSafetyZone;
|
||||||
virtual void(void) RunToHostages;
|
virtual void(void) RunToHostages;
|
||||||
|
virtual void(vector, int) Roam;
|
||||||
|
|
||||||
virtual void(void) CreateObjective;
|
virtual void(void) CreateObjective;
|
||||||
virtual void(void) PostFrame;
|
virtual void(void) PostFrame;
|
||||||
virtual void(void) WeaponThink;
|
virtual void(void) WeaponThink;
|
||||||
|
|
||||||
|
/* helpers */
|
||||||
|
virtual entity(string, int) GetEntityByNameAndIndex;
|
||||||
|
virtual entity(int) GetBombsiteByIndex;
|
||||||
|
virtual entity(int) GetEscapeZoneByIndex;
|
||||||
|
virtual entity(int) GetVIPSafetyZoneByIndex;
|
||||||
|
virtual void(vector, float) AimLerp;
|
||||||
|
|
||||||
|
int m_actionIsPlanting;
|
||||||
|
int m_actionIsDefusing;
|
||||||
|
|
||||||
/* Workaround:
|
/* Workaround:
|
||||||
* gflags is not yet set when CSBot_BuyStart_Shop() or CreateObjective()
|
* gflags is not yet set when CSBot_BuyStart_Shop() or CreateObjective()
|
||||||
* are called, so we back it up on PostFrame() and use that instead.
|
* are called, so we back it up on PostFrame() and use that instead.
|
||||||
|
@ -59,7 +82,7 @@ void
|
||||||
csbot::RunToBomb(void)
|
csbot::RunToBomb(void)
|
||||||
{
|
{
|
||||||
entity e = world;
|
entity e = world;
|
||||||
e = find(e, ::model, "models/w_c4bomb.mdl");
|
e = find(e, ::model, "models/w_c4.mdl");
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
RouteToPosition(e.origin);
|
RouteToPosition(e.origin);
|
||||||
|
@ -67,61 +90,52 @@ csbot::RunToBomb(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go to a random bombsite */
|
/* go to given bombsite */
|
||||||
void
|
void
|
||||||
csbot::RunToBombsite(void)
|
csbot::RunToBombsite(int bombsiteIndex)
|
||||||
{
|
{
|
||||||
entity e = world;
|
entity e = GetBombsiteByIndex(bombsiteIndex);
|
||||||
vector vecTarget;
|
RouteToPosition(getEntityCenterPos(e));
|
||||||
|
ChatSayTeam(strcat("Going to run to Bomb Site ", itos(bombsiteIndex), "!"));
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: make this random and error checked */
|
/* go to random bombsite */
|
||||||
while (e == world)
|
void
|
||||||
e = find(e, ::classname, "func_bomb_target");
|
csbot::RunToRandomBombsite(void)
|
||||||
|
{
|
||||||
|
RunToBombsite(random(0, g_cs_bombzones));
|
||||||
|
}
|
||||||
|
|
||||||
vecTarget[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0]));
|
/* go to given escape zone */
|
||||||
vecTarget[1] = e.absmin[1] + (0.5 * (e.absmax[1] - e.absmin[1]));
|
void
|
||||||
vecTarget[2] = e.absmin[2] + (0.5 * (e.absmax[2] - e.absmin[2]));
|
csbot::RunToEscapeZone(int index)
|
||||||
|
{
|
||||||
RouteToPosition(vecTarget);
|
entity e = GetEscapeZoneByIndex(index);
|
||||||
ChatSayTeam("Going to run to a Bomb Site!");
|
RouteToPosition(getEntityCenterPos(e));
|
||||||
|
ChatSayTeam(strcat("Going to run to Escape Zone ", itos(index), "!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go to a random escape zone */
|
/* go to a random escape zone */
|
||||||
void
|
void
|
||||||
csbot::RunToEscapeZone(void)
|
csbot::RunToRandomEscapeZone(void)
|
||||||
{
|
{
|
||||||
entity e = world;
|
RunToEscapeZone(random(0, g_cs_escapezones));
|
||||||
vector vecTarget;
|
|
||||||
|
|
||||||
/* FIXME: make this random and error checked */
|
|
||||||
while (e == world)
|
|
||||||
e = find(e, ::classname, "func_escapezone");
|
|
||||||
|
|
||||||
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]));
|
|
||||||
|
|
||||||
RouteToPosition(vecTarget);
|
|
||||||
ChatSayTeam("Going to run to an Escape Zone!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* go to a random escape zone */
|
/* go to given VIP Safety Zone */
|
||||||
void
|
void
|
||||||
csbot::RunToVIPSafetyZone(void)
|
csbot::RunToVIPSafetyZone(int index)
|
||||||
{
|
{
|
||||||
entity e = world;
|
entity e = GetVIPSafetyZoneByIndex(index);
|
||||||
vector vecTarget;
|
RouteToPosition(getEntityCenterPos(e));
|
||||||
|
ChatSayTeam(strcat("Going to run to VIP Safety Zone ", itos(index), "!"));
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: make this random and error checked */
|
/* go to a random VIP Safety Zone */
|
||||||
while (e == world)
|
void
|
||||||
e = find(e, ::classname, "func_vip_safetyzone");
|
csbot::RunToRandomVIPSafetyZone(void)
|
||||||
|
{
|
||||||
vecTarget[0] = e.absmin[0] + (0.5 * (e.absmax[0] - e.absmin[0]));
|
RunToVIPSafetyZone(random(0, g_cs_vipzones));
|
||||||
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]));
|
|
||||||
|
|
||||||
RouteToPosition(vecTarget);
|
|
||||||
ChatSayTeam("Going to run to a VIP Safety Zone!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -135,45 +149,226 @@ csbot::RunToHostages(void)
|
||||||
ChatSayTeam("Going to run to the hostages!");
|
ChatSayTeam("Going to run to the hostages!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Let the bot roam within a maximum distance from a given origin. */
|
||||||
|
void csbot::Roam(vector roamOrigin, int maxDistance) {
|
||||||
|
/* Get random point whitin a radius from the given origin */
|
||||||
|
int angle = random(0, 360); /* random angle. */
|
||||||
|
int distance = random(0, maxDistance); /* random distance */
|
||||||
|
float radian = angle * 3.145238095238 / 180;
|
||||||
|
vector randLoc = roamOrigin;
|
||||||
|
randLoc.x += sin(radian) * distance;
|
||||||
|
randLoc.y += cos(radian) * distance;
|
||||||
|
|
||||||
|
/* Find closest waypoint to our random location. */
|
||||||
|
float flBestDist = COST_INFINITE;
|
||||||
|
int iBestNodeIndex = -1;
|
||||||
|
for (int i = 0; i < g_iNodes; i++) {
|
||||||
|
float fDist = vlen(g_pNodes[i].origin - randLoc) - g_pNodes[i].radius;
|
||||||
|
|
||||||
|
if (fDist > (float)maxDistance) {
|
||||||
|
/* Distance is greater then our maxDistance */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fDist < flBestDist) {
|
||||||
|
flBestDist = fDist;
|
||||||
|
iBestNodeIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iBestNodeIndex == -1) {
|
||||||
|
/* TODO No waypoint in range found */
|
||||||
|
print("WARNING!: Roaming failed, could not find waypoint in range.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go to the random waypoint. */
|
||||||
|
RouteToPosition(g_pNodes[iBestNodeIndex].origin);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
csbot::CreateObjective(void)
|
csbot::CreateObjective(void)
|
||||||
{
|
{
|
||||||
|
/* Bomb defuse map */
|
||||||
|
if (g_cs_bombzones > 0) {
|
||||||
|
/* Bomb is planted */
|
||||||
|
if (g_cs_bombplanted) {
|
||||||
|
entity eBomb = find(world, ::model, "models/w_c4.mdl");
|
||||||
|
if (eBomb == world) {
|
||||||
|
/* No bomb model found, but it is/was planted */
|
||||||
|
|
||||||
if (g_cs_bombzones > 0 && g_cs_bombplanted)
|
/* RoundOver: Bomb is defused */
|
||||||
RunToBombsite();
|
if (g_cs_gamestate == GAME_END) {
|
||||||
|
RunToRandomBombsite();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error */
|
||||||
|
print("WARNING! g_cs_bombplanted == TRUE, but bomb model "
|
||||||
|
"cannot be found in the world.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (team == TEAM_CT) {
|
||||||
|
if (g_cs_bombbeingdefused && m_actionIsDefusing == FALSE) {
|
||||||
|
/* Bomb is being defused but not by this bot */
|
||||||
|
/* Go and roam the defuser */
|
||||||
|
Roam(eBomb.origin, 300);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_actionIsDefusing) {
|
||||||
|
if (!g_cs_bombbeingdefused) {
|
||||||
|
/* Defusing complete or somehow failed. */
|
||||||
|
m_actionIsDefusing = FALSE;
|
||||||
|
} else {
|
||||||
|
/* Continue defusing. */
|
||||||
|
input_buttons |= (INPUT_BUTTON5 | INPUT_BUTTON8);
|
||||||
|
input_movevalues = [0,0,0];
|
||||||
|
button5 = input_buttons & INPUT_BUTTON5; // don't release button5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int distToBomb = floor(vlen(eBomb.origin - origin));
|
||||||
|
if (distToBomb > 60) {
|
||||||
|
/* To far away from the bomb to defuse it, run to it! */
|
||||||
|
RunToBomb();
|
||||||
|
} else {
|
||||||
|
/* Aim at the bomb. */
|
||||||
|
input_buttons |= INPUT_BUTTON8; // duck
|
||||||
|
if ((flags & FL_ONUSABLE)) {
|
||||||
|
// Aimed at the bomb, ready to defuse!
|
||||||
|
ChatSayTeam("Defusing!");
|
||||||
|
input_buttons |= INPUT_BUTTON5;
|
||||||
|
input_movevalues = [0,0,0];
|
||||||
|
button5 = input_buttons & INPUT_BUTTON5; // don't release button5
|
||||||
|
m_actionIsDefusing = TRUE;
|
||||||
|
} else {
|
||||||
|
// Do the real aiming
|
||||||
|
float flLerp = bound(0.0f, frametime * 45, 1.0f); // aim speed
|
||||||
|
AimLerp(eBomb.origin + [0, 0, -6], flLerp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* team == TEAM_T */
|
||||||
|
else {
|
||||||
|
/* Let T bots roam around the planted bomb */
|
||||||
|
Roam(eBomb.origin, 500);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Bomb is NOT planted */
|
||||||
|
else {
|
||||||
|
if (team == TEAM_T) {
|
||||||
|
/* T-bot: plant bomb */
|
||||||
|
if ((g_items & ITEM_C4BOMB)) {
|
||||||
|
/* We carry the bomb */
|
||||||
|
if (m_gflagsBackup & GF_BOMBZONE) {
|
||||||
|
/* We are at a bombsite and ready to plant the bomb */
|
||||||
|
if (activeweapon != WEAPON_C4BOMB) {
|
||||||
|
activeweapon = WEAPON_C4BOMB;
|
||||||
|
Weapons_Draw((player)self);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_actionIsPlanting) {
|
||||||
|
ChatSayTeam("Going to plant the bomb!");
|
||||||
|
m_actionIsPlanting = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Workaround */
|
||||||
|
gflags = m_gflagsBackup;
|
||||||
|
|
||||||
|
/* Duck and plant bomb. */
|
||||||
|
input_buttons = (INPUT_BUTTON0 | INPUT_BUTTON8);
|
||||||
|
input_movevalues = [0,0,0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Go to a bombsite first */
|
||||||
|
RunToRandomBombsite();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* T-bot: check if the bomb has been dropped */
|
||||||
|
entity e = find(world, ::model, "models/w_backpack.mdl");
|
||||||
|
if (e != world) {
|
||||||
|
/* The bomb backpack has been dropped */
|
||||||
|
/* Go fetch dropped bomb! */
|
||||||
|
ChatSayTeam("Arrr! Bomb on the ground, going to fetch it!");
|
||||||
|
RouteToPosition(getEntityCenterPos(e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (g_cs_escapezones && team == TEAM_T) {
|
if (g_cs_escapezones && team == TEAM_T) {
|
||||||
RunToEscapeZone();
|
RunToRandomEscapeZone();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (random() < 0.5 && g_cs_escapezones > 0 && team == TEAM_CT) {
|
if (random() < 0.5 && g_cs_escapezones > 0 && team == TEAM_CT) {
|
||||||
RunToEscapeZone();
|
RunToRandomEscapeZone();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (g_cs_vipzones > 0 && team == TEAM_CT) {
|
if (g_cs_vipzones > 0 && team == TEAM_CT) {
|
||||||
RunToVIPSafetyZone();
|
RunToRandomVIPSafetyZone();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (random() < 0.5 && g_cs_vipzones > 0 && team == TEAM_T) {
|
if (random() < 0.5 && g_cs_vipzones > 0 && team == TEAM_T) {
|
||||||
RunToVIPSafetyZone();
|
RunToRandomVIPSafetyZone();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (random() < 0.5) {
|
if (random() < 0.5) {
|
||||||
if (g_cs_hostagestotal > 0)
|
if (g_cs_hostagestotal > 0)
|
||||||
RunToHostages();
|
RunToHostages();
|
||||||
if (g_cs_bombzones > 0)
|
if (g_cs_bombzones > 0)
|
||||||
RunToBombsite();
|
RunToRandomBombsite();
|
||||||
} else {
|
} else {
|
||||||
RunToConfront();
|
RunToConfront();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @brief Aim towards a given (vector)aimpos with a given (float)lerp speed.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
* Copied code from nuclide botlib (inside bot::RunAI), maybe make this a
|
||||||
|
* method there, could be usefull for other stuff?
|
||||||
|
**/
|
||||||
|
void csbot::AimLerp(vector aimpos, float flLerp) {
|
||||||
|
vector aimdir, vecNewAngles;
|
||||||
|
|
||||||
|
vector oldAngle = v_angle;
|
||||||
|
|
||||||
|
/* that's the old angle */
|
||||||
|
makevectors(v_angle);
|
||||||
|
vecNewAngles = v_forward;
|
||||||
|
|
||||||
|
/* aimdir = new final angle */
|
||||||
|
aimdir = vectoangles(aimpos - origin);
|
||||||
|
makevectors(aimdir);
|
||||||
|
|
||||||
|
/* slowly lerp towards the final angle */
|
||||||
|
vecNewAngles[0] = Math_Lerp(vecNewAngles[0], v_forward[0], flLerp);
|
||||||
|
vecNewAngles[1] = Math_Lerp(vecNewAngles[1], v_forward[1], flLerp);
|
||||||
|
vecNewAngles[2] = Math_Lerp(vecNewAngles[2], v_forward[2], flLerp);
|
||||||
|
|
||||||
|
/* make sure we're aiming tight */
|
||||||
|
v_angle = vectoangles(vecNewAngles);
|
||||||
|
v_angle[0] = Math_FixDelta(v_angle[0]);
|
||||||
|
v_angle[1] = Math_FixDelta(v_angle[1]);
|
||||||
|
v_angle[2] = Math_FixDelta(v_angle[2]);
|
||||||
|
angles[0] = Math_FixDelta(v_angle[0]);
|
||||||
|
angles[1] = Math_FixDelta(v_angle[1]);
|
||||||
|
angles[2] = Math_FixDelta(v_angle[2]);
|
||||||
|
input_angles = v_angle;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
csbot::PostFrame(void)
|
csbot::PostFrame(void)
|
||||||
{
|
{
|
||||||
|
@ -199,12 +394,56 @@ csbot::WeaponThink(void)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** @brief Get entity by class name and index **/
|
||||||
|
entity
|
||||||
|
csbot::GetEntityByNameAndIndex(const string name, int index)
|
||||||
|
{
|
||||||
|
int curIndex = 0;
|
||||||
|
for (entity a = world; (a = find(a, ::classname, name));) {
|
||||||
|
if (curIndex == index) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
++curIndex;
|
||||||
|
}
|
||||||
|
print("WARNING: cstrike/server/bot.qc GetEntityByNameAndIndex: no entity '",
|
||||||
|
name, "' with index ", itos(index), "!\n");
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Get bombsite entity by bombsite index
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
* When there are for example 2 bombsites (g_cs_bombzones == 2) then valid
|
||||||
|
* indexes would be 0 and 1.
|
||||||
|
* */
|
||||||
|
entity
|
||||||
|
csbot::GetBombsiteByIndex(int index)
|
||||||
|
{
|
||||||
|
return GetEntityByNameAndIndex("func_bomb_target", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Get Escape Zone entity by index **/
|
||||||
|
entity
|
||||||
|
csbot::GetEscapeZoneByIndex(int index)
|
||||||
|
{
|
||||||
|
return GetEntityByNameAndIndex("func_escapezone", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Get VIP Safety Zone entity by index **/
|
||||||
|
entity
|
||||||
|
csbot::GetVIPSafetyZoneByIndex(int index)
|
||||||
|
{
|
||||||
|
return GetEntityByNameAndIndex("func_vip_safetyzone", index);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
csbot::csbot(void)
|
csbot::csbot(void)
|
||||||
{
|
{
|
||||||
bot::bot();
|
bot::bot();
|
||||||
targetname = "_csbot_";
|
targetname = "_csbot_";
|
||||||
team = infokeyf(this, "*team");
|
team = infokeyf(this, "*team");
|
||||||
|
m_actionIsPlanting = FALSE;
|
||||||
|
m_actionIsDefusing = FALSE;
|
||||||
m_gflagsBackup = 0;
|
m_gflagsBackup = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,8 +459,8 @@ CSBot_BombPlantedNotify(void)
|
||||||
continue;
|
continue;
|
||||||
if (targ.health <= 0)
|
if (targ.health <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
targ.RunToBombsite();
|
targ.RunToRandomBombsite();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +477,7 @@ CSBot_HostageRescueNotify(void)
|
||||||
continue;
|
continue;
|
||||||
if (targ.health <= 0)
|
if (targ.health <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
targ.RunToHostages();
|
targ.RunToHostages();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,7 +512,7 @@ CSBot_BuyStart_Shop(void)
|
||||||
if (r == WEAPON_ELITES) { continue; }
|
if (r == WEAPON_ELITES) { continue; }
|
||||||
if (r == WEAPON_MAC10) { continue; }
|
if (r == WEAPON_MAC10) { continue; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_cstrikeWeaponPrice[r] <= pl.money) {
|
if (g_cstrikeWeaponPrice[r] <= pl.money) {
|
||||||
CSEv_BuyWeapon_f((float)r);
|
CSEv_BuyWeapon_f((float)r);
|
||||||
done = 1;
|
done = 1;
|
||||||
|
@ -285,6 +524,14 @@ CSBot_BuyStart_Shop(void)
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* CT: Random buy bomb defuse kit when enough money left */
|
||||||
|
if (pl.team == TEAM_CT && g_cs_bombzones > 0 &&
|
||||||
|
g_cstrikeUtilPrice[(float)5] <= pl.money &&
|
||||||
|
random() < 0.5)
|
||||||
|
{
|
||||||
|
CSEv_BuyEquipment_f((float)5); // ITEM_DEFUSAL
|
||||||
|
}
|
||||||
|
|
||||||
/* need armor */
|
/* need armor */
|
||||||
if (pl.armor < 100) {
|
if (pl.armor < 100) {
|
||||||
if (pl.money >= g_cstrikeUtilPrice[1]) /* kevlar and helmet */
|
if (pl.money >= g_cstrikeUtilPrice[1]) /* kevlar and helmet */
|
||||||
|
@ -339,8 +586,27 @@ CSBot_RoundStart(void)
|
||||||
if (targ.health <= 0)
|
if (targ.health <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
targ.RunToBombsite();
|
targ.RunToRandomBombsite();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} */
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CSBot_RestartRound(void)
|
||||||
|
{
|
||||||
|
// Reset some variables for all bots
|
||||||
|
for (entity a = world; (a = find(a, classname, "player"));) {
|
||||||
|
if (clienttype(a) != CLIENTTYPE_REAL) {
|
||||||
|
csbot targ;
|
||||||
|
targ = (csbot)a;
|
||||||
|
|
||||||
|
if (targ.team == TEAM_T) {
|
||||||
|
targ.m_actionIsPlanting = FALSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
targ.m_actionIsDefusing = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ var int g_cs_vipzones;
|
||||||
var int g_cs_escapezones;
|
var int g_cs_escapezones;
|
||||||
var int g_cs_bombzones;
|
var int g_cs_bombzones;
|
||||||
|
|
||||||
|
var int g_cs_bombbeingdefused;
|
||||||
var int g_cs_bombplanted;
|
var int g_cs_bombplanted;
|
||||||
var int g_cs_roundswon_ct;
|
var int g_cs_roundswon_ct;
|
||||||
var int g_cs_roundswon_t;
|
var int g_cs_roundswon_t;
|
||||||
|
|
|
@ -14,9 +14,6 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const string mp_teamlist_fallback = "robo;hgrunt";
|
|
||||||
var string autocvar_mp_teamlist = mp_teamlist_fallback;
|
|
||||||
|
|
||||||
string
|
string
|
||||||
CSDeathmatchRules::Title(void)
|
CSDeathmatchRules::Title(void)
|
||||||
{
|
{
|
||||||
|
@ -60,25 +57,11 @@ CSDeathmatchRules::InitPostEnts(void)
|
||||||
forceinfokey(world, "scorepoints", "0");
|
forceinfokey(world, "scorepoints", "0");
|
||||||
|
|
||||||
if (IsTeamplay() == true) {
|
if (IsTeamplay() == true) {
|
||||||
int c;
|
forceinfokey(world, "teams", "2");
|
||||||
|
forceinfokey(world, "team_1", "Counter-Terrorist");
|
||||||
/* get the segments from our cvar */
|
forceinfokey(world, "teamscore_1", "0");
|
||||||
m_strTeamList = autocvar_mp_teamlist;
|
forceinfokey(world, "team_2", "Terrorist");
|
||||||
c = tokenizebyseparator(m_strTeamList, ";");
|
forceinfokey(world, "teamscore_2", "0");
|
||||||
|
|
||||||
/* if we've got less than 2 teams, use the fallback... */
|
|
||||||
if (c < 2) {
|
|
||||||
m_strTeamList = mp_teamlist_fallback;
|
|
||||||
c = tokenizebyseparator(m_strTeamList, ";");
|
|
||||||
}
|
|
||||||
|
|
||||||
forceinfokey(world, "teams", itos(c));
|
|
||||||
|
|
||||||
/* initialize all dem teams */
|
|
||||||
for (int i = 0; i < c; i++) {
|
|
||||||
forceinfokey(world, sprintf("team_%i", i+1i), argv(i));
|
|
||||||
forceinfokey(world, sprintf("teamscore_%i", i+1i), "0");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
forceinfokey(world, "teams", "0");
|
forceinfokey(world, "teams", "0");
|
||||||
}
|
}
|
||||||
|
@ -167,7 +150,6 @@ void
|
||||||
CSDeathmatchRules::PlayerSpawn(NSClientPlayer pp)
|
CSDeathmatchRules::PlayerSpawn(NSClientPlayer pp)
|
||||||
{
|
{
|
||||||
player pl = (player)pp;
|
player pl = (player)pp;
|
||||||
string playerModel;
|
|
||||||
/* this is where the mods want to deviate */
|
/* this is where the mods want to deviate */
|
||||||
entity spot;
|
entity spot;
|
||||||
|
|
||||||
|
@ -190,11 +172,13 @@ CSDeathmatchRules::PlayerSpawn(NSClientPlayer pp)
|
||||||
/* TODO: this should sort us into the lowest team */
|
/* TODO: this should sort us into the lowest team */
|
||||||
if (playerTeam == 0) {
|
if (playerTeam == 0) {
|
||||||
playerTeam = 1i + (int)floor(random(0, (float)teamCount)); /* teams start at 1 after all */
|
playerTeam = 1i + (int)floor(random(0, (float)teamCount)); /* teams start at 1 after all */
|
||||||
pl.SetTeam(playerTeam);
|
pl.SetTeam(random() < 0.5 ? TEAM_CT : TEAM_T);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assign our player model */
|
if (playerTeam == TEAM_T)
|
||||||
playerModel = sprintf("models/player/%s/%s.mdl", argv(playerTeam - 1i), argv(playerTeam - 1i));
|
pl.charmodel = floor(random(1,5));
|
||||||
|
else
|
||||||
|
pl.charmodel = floor(random(5,9));
|
||||||
} else {
|
} else {
|
||||||
pl.charmodel = rint(random(1,9));
|
pl.charmodel = rint(random(1,9));
|
||||||
}
|
}
|
||||||
|
@ -228,12 +212,8 @@ CSDeathmatchRules::PlayerSpawn(NSClientPlayer pp)
|
||||||
pl.model = "models/player/vip/vip.mdl";
|
pl.model = "models/player/vip/vip.mdl";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fallback is always models/player.mdl for Half-Life */
|
|
||||||
if not (whichpack(playerModel)) {
|
|
||||||
playerModel = "models/player.mdl";
|
|
||||||
}
|
|
||||||
|
|
||||||
pl.SetModel(playerModel);
|
pl.SetModel(pl.model);
|
||||||
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
|
pl.SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
|
||||||
pl.ClearVelocity();
|
pl.ClearVelocity();
|
||||||
pl.gravity = __NULL__;
|
pl.gravity = __NULL__;
|
||||||
|
@ -306,31 +286,4 @@ CSDeathmatchRules::CSDeathmatchRules(void)
|
||||||
/* these lines do nothing but tell the server to register those cvars */
|
/* these lines do nothing but tell the server to register those cvars */
|
||||||
autocvar(timelimit, 15, "Timelimit for multiplayer rounds");
|
autocvar(timelimit, 15, "Timelimit for multiplayer rounds");
|
||||||
autocvar(fraglimit, 15, "Points limit for multiplayer rounds");
|
autocvar(fraglimit, 15, "Points limit for multiplayer rounds");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CSEv_HLDM_Chooseteam_s(string teamName)
|
|
||||||
{
|
|
||||||
CSGameRules rules = (CSGameRules)g_grMode;
|
|
||||||
player pl = (player)self;
|
|
||||||
|
|
||||||
if (!teamName)
|
|
||||||
return;
|
|
||||||
if (rules.IsMultiplayer() == false)
|
|
||||||
return;
|
|
||||||
if (rules.IsTeamplay() == false)
|
|
||||||
return;
|
|
||||||
if (pl.IsDead() == true)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CSDeathmatchRules mprules = (CSDeathmatchRules)rules;
|
|
||||||
int c = tokenizebyseparator(mprules.m_strTeamList, ";");
|
|
||||||
|
|
||||||
for (int i = 0; i < c; i++) {
|
|
||||||
if (argv(i) == teamName) {
|
|
||||||
pl.SetTeam((float)i + 1);
|
|
||||||
Damage_Apply(pl, pl, 100, 0, DMG_SKIP_ARMOR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -294,7 +294,7 @@ CSMultiplayerRules::TimerBegin(float tleft, int mode)
|
||||||
RoundOver(TEAM_T, 3600, FALSE);
|
RoundOver(TEAM_T, 3600, FALSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (mode == GAME_END) {
|
} else if (mode == GAME_END) {
|
||||||
g_cs_gamestate = GAME_END;
|
g_cs_gamestate = GAME_END;
|
||||||
} else if (mode == GAME_COMMENCING) {
|
} else if (mode == GAME_COMMENCING) {
|
||||||
|
@ -397,7 +397,7 @@ CSMultiplayerRules::BuyingPossible(NSClientPlayer pl)
|
||||||
if (pl.health <= 0) {
|
if (pl.health <= 0) {
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_cs_gamestate == GAME_ACTIVE) {
|
if (g_cs_gamestate == GAME_ACTIVE) {
|
||||||
if (((autocvar_mp_roundtime * 60) - g_cs_gametime) > autocvar_mp_buytime) {
|
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));
|
centerprint(pl, sprintf("%d seconds have passed...\nYou can't buy anything now!", autocvar_mp_buytime));
|
||||||
|
@ -409,12 +409,12 @@ CSMultiplayerRules::BuyingPossible(NSClientPlayer pl)
|
||||||
centerprint(pl, "You are the VIP...\nYou can't buy anything!\n");
|
centerprint(pl, "You are the VIP...\nYou can't buy anything!\n");
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_cstrike_buying == BUY_NEITHER) {
|
if (g_cstrike_buying == BUY_NEITHER) {
|
||||||
centerprint(pl, "Sorry, you aren't meant\nto be buying anything.\n");
|
centerprint(pl, "Sorry, you aren't meant\nto be buying anything.\n");
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_cstrike_buying != BUY_BOTH) {
|
if (g_cstrike_buying != BUY_BOTH) {
|
||||||
if (g_cstrike_buying == BUY_CT && pl.team == TEAM_T) {
|
if (g_cstrike_buying == BUY_CT && pl.team == TEAM_T) {
|
||||||
centerprint(pl, "Terrorists aren't allowed to\nbuy anything on this map!\n");
|
centerprint(pl, "Terrorists aren't allowed to\nbuy anything on this map!\n");
|
||||||
|
@ -424,12 +424,12 @@ CSMultiplayerRules::BuyingPossible(NSClientPlayer pl)
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pl.gflags & GF_BUYZONE)) {
|
if (!(pl.gflags & GF_BUYZONE)) {
|
||||||
centerprint(pl, "Sorry, you aren't in a buyzone.\n");
|
centerprint(pl, "Sorry, you aren't in a buyzone.\n");
|
||||||
return (false);
|
return (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +463,7 @@ CSMultiplayerRules::RestartRound(int iWipe)
|
||||||
if (autocvar_fcs_swaponround > 0)
|
if (autocvar_fcs_swaponround > 0)
|
||||||
if (m_iSwapTeamRoundCounter >= autocvar_fcs_swaponround) {
|
if (m_iSwapTeamRoundCounter >= autocvar_fcs_swaponround) {
|
||||||
m_iSwapTeamRoundCounter = 0;
|
m_iSwapTeamRoundCounter = 0;
|
||||||
|
|
||||||
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
|
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
|
||||||
player pl = (player)eFind;
|
player pl = (player)eFind;
|
||||||
|
|
||||||
|
@ -479,6 +479,9 @@ CSMultiplayerRules::RestartRound(int iWipe)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset CSBot vars
|
||||||
|
CSBot_RestartRound();
|
||||||
|
|
||||||
for (entity eFind = world; (eFind = findfloat(eFind, ::team, TEAM_T));) {
|
for (entity eFind = world; (eFind = findfloat(eFind, ::team, TEAM_T));) {
|
||||||
if (!(eFind.flags & FL_CLIENT))
|
if (!(eFind.flags & FL_CLIENT))
|
||||||
continue;
|
continue;
|
||||||
|
@ -558,6 +561,12 @@ CSMultiplayerRules::RestartRound(int iWipe)
|
||||||
NSEntity e = (NSEntity)eFind;
|
NSEntity e = (NSEntity)eFind;
|
||||||
e.Destroy();
|
e.Destroy();
|
||||||
}
|
}
|
||||||
|
// Remove potential bomb backpack model from the world, else bots will go
|
||||||
|
// chase a ghost.
|
||||||
|
entity e = find(world, ::model, "models/w_backpack.mdl");
|
||||||
|
if (e != world) {
|
||||||
|
remove(e);
|
||||||
|
}
|
||||||
|
|
||||||
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
||||||
WriteByte(MSG_MULTICAST, EV_CLEARDECALS);
|
WriteByte(MSG_MULTICAST, EV_CLEARDECALS);
|
||||||
|
@ -568,11 +577,11 @@ CSMultiplayerRules::RestartRound(int iWipe)
|
||||||
if (g_cs_bombzones > 0) {
|
if (g_cs_bombzones > 0) {
|
||||||
int iRandomT = floor(random(1, (float)g_cs_alive_t + 1));
|
int iRandomT = floor(random(1, (float)g_cs_alive_t + 1));
|
||||||
int iPickT = 0;
|
int iPickT = 0;
|
||||||
|
|
||||||
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
|
for (entity eFind = world; (eFind = find(eFind, ::classname, "player"));) {
|
||||||
if (eFind.team == TEAM_T) {
|
if (eFind.team == TEAM_T) {
|
||||||
iPickT++;
|
iPickT++;
|
||||||
|
|
||||||
if (iPickT == iRandomT) {
|
if (iPickT == iRandomT) {
|
||||||
MakeBomber((player)eFind);
|
MakeBomber((player)eFind);
|
||||||
}
|
}
|
||||||
|
@ -650,6 +659,7 @@ CSMultiplayerRules::RoundOver(int iTeamWon, int iMoneyReward, int fSilent)
|
||||||
TimerBegin(5, GAME_END); // Round is over, 5 seconds til a new round starts
|
TimerBegin(5, GAME_END); // Round is over, 5 seconds til a new round starts
|
||||||
|
|
||||||
g_cs_hostagesrescued = 0;
|
g_cs_hostagesrescued = 0;
|
||||||
|
g_cs_bombbeingdefused = 0;
|
||||||
g_cs_bombplanted = 0;
|
g_cs_bombplanted = 0;
|
||||||
g_cs_roundsplayed++;
|
g_cs_roundsplayed++;
|
||||||
|
|
||||||
|
@ -810,14 +820,14 @@ CSMultiplayerRules::PlayerFindSpawn(float t)
|
||||||
|
|
||||||
if (t == TEAM_T) {
|
if (t == TEAM_T) {
|
||||||
m_eLastTSpawn = find(m_eLastTSpawn, ::classname, "info_player_deathmatch");
|
m_eLastTSpawn = find(m_eLastTSpawn, ::classname, "info_player_deathmatch");
|
||||||
|
|
||||||
if (m_eLastTSpawn == world) {
|
if (m_eLastTSpawn == world) {
|
||||||
m_eLastTSpawn = find(m_eLastTSpawn, ::classname, "info_player_deathmatch");
|
m_eLastTSpawn = find(m_eLastTSpawn, ::classname, "info_player_deathmatch");
|
||||||
}
|
}
|
||||||
point = m_eLastTSpawn;
|
point = m_eLastTSpawn;
|
||||||
} else if (t == TEAM_CT) {
|
} else if (t == TEAM_CT) {
|
||||||
m_eLastCTSpawn = find(m_eLastCTSpawn, ::classname, "info_player_start");
|
m_eLastCTSpawn = find(m_eLastCTSpawn, ::classname, "info_player_start");
|
||||||
|
|
||||||
if (m_eLastCTSpawn == world) {
|
if (m_eLastCTSpawn == world) {
|
||||||
m_eLastCTSpawn = find(m_eLastCTSpawn, ::classname, "info_player_start");
|
m_eLastCTSpawn = find(m_eLastCTSpawn, ::classname, "info_player_start");
|
||||||
}
|
}
|
||||||
|
@ -1111,8 +1121,10 @@ CSMultiplayerRules::CSMultiplayerRules(void)
|
||||||
forceinfokey(world, "teams", "2");
|
forceinfokey(world, "teams", "2");
|
||||||
forceinfokey(world, "team_1", "Terrorist");
|
forceinfokey(world, "team_1", "Terrorist");
|
||||||
forceinfokey(world, "teamscore_1", "0");
|
forceinfokey(world, "teamscore_1", "0");
|
||||||
|
forceinfokey(world, "teamcolor_1", "1 0 0" );
|
||||||
forceinfokey(world, "team_2", "Counter-Terrorist");
|
forceinfokey(world, "team_2", "Counter-Terrorist");
|
||||||
forceinfokey(world, "teamscore_2", "0");
|
forceinfokey(world, "teamscore_2", "0");
|
||||||
|
forceinfokey(world, "teamcolor_2", "0.25 0.25 1" );
|
||||||
m_iEscapedTerrorists = 0;
|
m_iEscapedTerrorists = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1217,3 +1229,11 @@ CSEv_JoinAuto(void)
|
||||||
CSEv_JoinTeam_f(floor(random(5,9)));
|
CSEv_JoinTeam_f(floor(random(5,9)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CSEv_JoinSpectator(void)
|
||||||
|
{
|
||||||
|
NSClientPlayer pl = (NSClientPlayer)self;
|
||||||
|
ClientKill();
|
||||||
|
pl.MakeSpectator();
|
||||||
|
}
|
||||||
|
|
|
@ -106,10 +106,11 @@ item_c4::Logic(void)
|
||||||
/* we need to check if the user has changed every frame. */
|
/* we need to check if the user has changed every frame. */
|
||||||
if (!m_eUser.button5) {
|
if (!m_eUser.button5) {
|
||||||
ClearProgress();
|
ClearProgress();
|
||||||
|
|
||||||
/* clear user */
|
/* clear user */
|
||||||
m_eUser = world;
|
m_eUser = world;
|
||||||
m_flDefusalState = 0.0f;
|
m_flDefusalState = 0.0f;
|
||||||
|
g_cs_bombbeingdefused = FALSE;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* defusal kit always cuts the time in half */
|
/* defusal kit always cuts the time in half */
|
||||||
|
@ -121,6 +122,8 @@ item_c4::Logic(void)
|
||||||
/* tracked stat */
|
/* tracked stat */
|
||||||
pl.progress = m_flDefusalState;
|
pl.progress = m_flDefusalState;
|
||||||
pl.flags |= FL_FROZEN;
|
pl.flags |= FL_FROZEN;
|
||||||
|
|
||||||
|
g_cs_bombbeingdefused = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,6 +188,8 @@ item_c4::OnRemoveEntity(void)
|
||||||
ClearProgress();
|
ClearProgress();
|
||||||
m_flBeepTime = 0.0f;
|
m_flBeepTime = 0.0f;
|
||||||
m_flDefusalState = 0;
|
m_flDefusalState = 0;
|
||||||
|
g_cs_bombbeingdefused = FALSE;
|
||||||
|
g_cs_bombplanted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -115,18 +115,19 @@
|
||||||
129 404.310150 0
|
129 404.310150 0
|
||||||
-1236.87 2106.78 36.0312 8.000000 1
|
-1236.87 2106.78 36.0312 8.000000 1
|
||||||
31 129.404831 0
|
31 129.404831 0
|
||||||
-1112.67 2558.34 54.5411 8.000000 2
|
-1115.89 2556.04 54.2432 8.000000 2
|
||||||
35 46.630283 0
|
35 46.630283 6
|
||||||
34 148.579971 0
|
150 90.005127 0
|
||||||
-1066.34 2420.98 21.9286 32.000000 3
|
-1060.06 2414.18 18.9855 32.000000 3
|
||||||
33 148.579971 0
|
|
||||||
31 229.015961 0
|
31 229.015961 0
|
||||||
129 368.347656 0
|
129 368.347656 0
|
||||||
-1122.41 2561.52 100.031 8.000000 1
|
150 99.204529 0
|
||||||
|
-1153.41 2561.52 100.031 8.000000 2
|
||||||
36 46.012051 0
|
36 46.012051 0
|
||||||
|
33 53.782150 2
|
||||||
-1167.97 2555.04 100.031 8.000000 1
|
-1167.97 2555.04 100.031 8.000000 1
|
||||||
37 58.178169 6
|
37 58.178169 6
|
||||||
-1168.83 2550.57 158.031 8.000000 1
|
-1186.83 2550.57 158.031 8.000000 1
|
||||||
38 49.115257 0
|
38 49.115257 0
|
||||||
-1216.33 2543.05 148.031 8.000000 1
|
-1216.33 2543.05 148.031 8.000000 1
|
||||||
39 93.324020 0
|
39 93.324020 0
|
||||||
|
@ -522,3 +523,6 @@
|
||||||
22 431.499512 0
|
22 431.499512 0
|
||||||
24 322.543915 0
|
24 322.543915 0
|
||||||
25 444.441376 0
|
25 444.441376 0
|
||||||
|
-1043.02 2511.69 25.5536 8.000000 2
|
||||||
|
33 90.005127 0
|
||||||
|
34 99.204529 0
|
||||||
|
|
Loading…
Reference in New Issue