Bot improvements, some more work done on the grenades.

This commit is contained in:
Marco Cawthorne 2024-01-08 15:34:11 -08:00
parent 3f636e0a3d
commit 29281e8101
Signed by: eukara
GPG Key ID: CE2032F0A2882A22
14 changed files with 270 additions and 35 deletions

View File

@ -17,20 +17,22 @@ TFCHallucination_Insert(vector viewPosition, vector viewDirection)
traceline(viewPosition, halluPos, MOVE_NORMAL, pSeat->m_ePlayer);
halluPos = trace_endpos;
makevectors(viewDirection);
makevectors([0, viewDirection[1], 0]);
r = (int)(floor(random(0, 8)));
r = (int)(floor(random(0, 10)));
switch (r) {
case 1:
case 1: /* blood splats */
for (int i = 0; i < 3; i++) {
halluPos = viewPosition;
halluPos += v_forward * random(8, 64);
halluPos += v_up * random(-64, 64);
halluPos += v_right * random(-64, 64);
FX_Blood(halluPos, [1,0,0]);
halluPos += v_forward * random(8, 128);
halluPos += v_up * random(-64, 128);
halluPos += v_right * random(-256, 256);
}
pointsound(viewPosition, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM);
break;
case 2:
case 2: /* explosions */
pointparticles(particleeffectnum("fx_explosion.main"), halluPos, [0,0,0], 1);
pSeat->m_flShakeDuration = 2;
pSeat->m_flShakeAmp = 5.0;
@ -38,46 +40,105 @@ TFCHallucination_Insert(vector viewPosition, vector viewDirection)
pSeat->m_flShakeTime = 2;
pointsound(halluPos, sprintf("weapons/explode%d.wav", floor(random() * 2) + 3), 1, ATTN_NORM);
break;
case 3:
case 3: /* shotgun impact */
traceline(viewPosition, halluPos + (v_forward * 1024), MOVE_NORMAL, pSeat->m_ePlayer);
SurfData_Impact(world, trace_endpos, [0,0,0]);
DecalGroups_Place("Impact.Shot", trace_endpos);
pointsound(halluPos, "weapons/sbarrel1.wav", 1, ATTN_NORM);
break;
case 4:
case 4: /* being hit by a crowbar */
pSeat->m_flShakeDuration = 1;
pSeat->m_flShakeAmp = 1.0;
pSeat->m_flShakeFreq = 2;
pSeat->m_flShakeTime = 2;
pointsound(halluPos, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM);
break;
case 5:
case 5: /* sniper impact */
traceline(viewPosition, halluPos + (v_forward * 1024), MOVE_NORMAL, pSeat->m_ePlayer);
SurfData_Impact(world, trace_endpos, [0,0,0]);
DecalGroups_Place("Impact.Shot", trace_endpos);
pointsound(halluPos, "weapons/sniper.wav", 1, ATTN_NORM);
break;
case 6:
case 6: /* nailgun impact */
traceline(viewPosition, halluPos + (v_forward * 1024), MOVE_NORMAL, pSeat->m_ePlayer);
SurfData_Impact(world, trace_endpos, [0,0,0]);
DecalGroups_Place("Impact.Shot", trace_endpos);
pointsound(halluPos, "weapons/airgun_1.wav", 1, ATTN_NORM);
break;
case 7:
case 7: /* nade thrown about */
int nadeSelection = (int)floor(random(0, 8));
NSRenderableEntity eNade = spawn(NSRenderableEntity);
eNade.SetModel("models/w_grenade.mdl");
eNade.SetOrigin(halluPos);
switch (nadeSelection) {
case 1:
eNade.SetModel("models/emp_grenade.mdl");
break;
case 2:
eNade.SetModel("models/spy_grenade.mdl");
break;
case 3:
eNade.SetModel("models/napalm.mdl");
break;
case 4:
eNade.SetModel("models/mirv_grenade.mdl");
break;
case 5:
eNade.SetModel("models/ngrenade.mdl");
break;
case 6:
eNade.SetModel("models/conc_grenade.mdl");
break;
case 7:
eNade.SetModel("models/caltrop.mdl");
break;
default:
eNade.SetModel("models/w_grenade.mdl");
}
eNade.SetOrigin(viewPosition + (v_forward * -32) + (v_right * random(-64, 64)));
eNade.SetMovetype(MOVETYPE_BOUNCE);
eNade.SetSolid(SOLID_NOT);
eNade.SetGravity(1.0f);
eNade.SetVelocity(v_forward * random(-320,320) + v_right * random(-64, 64) + v_up * 200);
eNade.SetVelocity(v_forward * 300 + v_right * random(-64, 64) + v_up * 200);
eNade.SetAngularVelocity([300, 300, 300]);
eNade.SetAngles(vectoangles(eNade.GetVelocity()));
eNade.ScheduleThink(eNade.Destroy, 5.0f);
eNade.drawmask = MASK_ENGINE;
pointsound(halluPos, "weapons/grenade_hit3.wav", 1, ATTN_NORM);
break;
case 8: /* nail shot around */
halluPos = viewPosition + (v_forward * -32) + (v_right * random(-64, 64));
NSRenderableEntity eNail = spawn(NSRenderableEntity);
eNail.SetModel("models/nail.mdl");
eNail.SetOrigin(halluPos);
eNail.SetMovetype(MOVETYPE_NOCLIP);
eNail.SetSolid(SOLID_NOT);
eNail.SetGravity(1.0f);
eNail.SetVelocity(v_forward * 800 + v_right * random(-800, 800));
eNail.SetAngles(vectoangles(eNail.GetVelocity()));
eNail.ScheduleThink(eNail.Destroy, 5.0f);
eNail.drawmask = MASK_ENGINE;
pointsound(halluPos, "weapons/airgun_1.wav", 1, ATTN_NORM);
break;
case 9: /* fire eruption */
/* get it close to the player than usual */
halluPos = viewPosition;
halluPos += v_forward * random(8, 64);
halluPos += v_up * random(-16, 16);
halluPos += v_right * random(-64, 64);
env_sprite eFired = spawn(env_sprite);
eFired.SetOrigin(halluPos);
eFired.SetModel("sprites/fthrow.spr");
eFired.SetMaxFrame(modelframecount(eFired.modelindex));
eFired.SetFramerate(20);
eFired.SetLoopFlag(false);
eFired.SetRenderMode(RM_ADDITIVE);
eFired.SetRenderAmt(1.0f);
eFired.nextthink = time + 0.05f;
pointsound(halluPos, "weapons/flmfire2.wav", 1, ATTN_NORM);
break;
default:
/* rocket launcher firing */
pointsound(halluPos, "weapons/rocketfire1.wav", 1, ATTN_NORM);
break;
}

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

@ -0,0 +1,21 @@
class
TFCBot:bot
{
void TFCBot(void);
//virtual void CreateObjective(void);
};
void
TFCBot::TFCBot(void)
{
}
#if 0
void
TFCBot::CreateObjective(void)
{
super:: CreateObjective();
}
#endif

View File

@ -19,6 +19,11 @@
#include "../../../valve/src/server/flashlight.h"
#include "sentry.h"
var bool g_tfcHasBlueTeam = false;
var bool g_tfcHasRedTeam = false;
var bool g_tfcHasYellowTeam = false;
var bool g_tfcHasGreenTeam = false;
/* returns if a player already has a teleporter/exit built */
bool
TFC_ExistsForPlayer(entity pl, string cname)

View File

@ -18,6 +18,7 @@ class TFCGameRules:CGameRules
{
void(void) TFCGameRules;
virtual bool ConsoleCommand(NSClientPlayer, string);
virtual bool IsTeamplay(void);
virtual void PlayerConnect(NSClientPlayer);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Marco Cawthorne <marco@icculus.org>
* Copyright (c) 2016-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
@ -14,6 +14,52 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
void CSEv_TeamJoin_f(float f);
void CSEv_ClassJoin_f(float f);
void
TFCGameRules_BotJoin(void)
{
spawnfunc_TFCBot();
CSEv_TeamJoin_f(0);
CSEv_ClassJoin_f(0);
}
void
TFCGameRules::TFCGameRules(void)
{
/* wipe the serverinfo clean */
forceinfokey(world, "teams", "0");
forceinfokey(world, "team_1", "");
forceinfokey(world, "team_2", "");
forceinfokey(world, "team_3", "");
forceinfokey(world, "team_4", "");
forceinfokey(world, "teamscore_1", "");
forceinfokey(world, "teamscore_2", "");
forceinfokey(world, "teamscore_3", "");
forceinfokey(world, "teamscore_4", "");
}
bool
TFCGameRules::ConsoleCommand(NSClientPlayer pp, string cmd)
{
tokenize(cmd);
switch (argv(0)) {
case "bot_add":
entity bot_ent = Bot_AddQuick();
if (bot_ent) {
bot_ent.think = TFCGameRules_BotJoin;
bot_ent.nextthink = time;
}
break;
default:
return (false);
}
return (true);
}
bool
TFCGameRules::IsTeamplay(void)
{
@ -182,6 +228,7 @@ TFCGameRules::InitPostEnts(void)
team_count += 1;
forceinfokey(world, sprintf("team_%i", team_count), "Blue");
forceinfokey(world, sprintf("teamscore_%i", team_count), "0");
g_tfcHasBlueTeam = true;
}
e = find(world, ::classname, "info_teamspawn_red");
@ -189,6 +236,7 @@ TFCGameRules::InitPostEnts(void)
team_count += 1;
forceinfokey(world, sprintf("team_%i", team_count), "Red");
forceinfokey(world, sprintf("teamscore_%i", team_count), "0");
g_tfcHasRedTeam = true;
}
e = find(world, ::classname, "info_teamspawn_green");
@ -196,6 +244,7 @@ TFCGameRules::InitPostEnts(void)
team_count += 1;
forceinfokey(world, sprintf("team_%i", team_count), "Green");
forceinfokey(world, sprintf("teamscore_%i", team_count), "0");
g_tfcHasGreenTeam = true;
}
e = find(world, ::classname, "info_teamspawn_yellow");
@ -203,22 +252,8 @@ TFCGameRules::InitPostEnts(void)
team_count += 1;
forceinfokey(world, sprintf("team_%i", team_count), "Yellow");
forceinfokey(world, sprintf("teamscore_%i", team_count), "0");
g_tfcHasYellowTeam = true;
}
forceinfokey(world, "teams", itos(team_count));
}
void
TFCGameRules::TFCGameRules(void)
{
/* wipe the serverinfo clean */
forceinfokey(world, "teams", "0");
forceinfokey(world, "team_1", "");
forceinfokey(world, "team_2", "");
forceinfokey(world, "team_3", "");
forceinfokey(world, "team_4", "");
forceinfokey(world, "teamscore_1", "");
forceinfokey(world, "teamscore_2", "");
forceinfokey(world, "teamscore_3", "");
forceinfokey(world, "teamscore_4", "");
}

View File

@ -47,6 +47,8 @@ info_player_teamspawn::info_player_teamspawn(void)
classname = "info_teamspawn_green";
break;
}
botinfo = BOTINFO_SPAWNPOINT;
}
CLASSEXPORT(i_p_t, info_player_teamspawn)

View File

@ -179,6 +179,7 @@ info_tfgoal::Touch(entity eToucher)
/* mark as removed on the player end, too. */
pl.g_items &= ~ITEM_GOALITEM;
pl.flags &= ~FL_GOALITEM;
forceinfokey(pl, "*goalitem_t", "");
}
@ -286,6 +287,10 @@ info_tfgoal::Respawn(void)
SetModel(GetSpawnModel());
SetSize(VEC_HULL_MIN, VEC_HULL_MAX);
SetOrigin(GetSpawnOrigin());
team = m_iTeamUses;
if (frags > 0)
botinfo = BOTINFO_TEAM_GOALCAPTURE;
}
void
@ -446,6 +451,10 @@ i_t_g::Respawn(void)
SetModel(GetSpawnModel());
SetOrigin(GetSpawnOrigin());
Hide();
team = m_iTeamUses;
if (frags > 0)
botinfo = BOTINFO_TEAM_GOALCAPTURE;
}
void

View File

@ -167,6 +167,7 @@ item_armor::Respawn(void)
SetSolid(SOLID_TRIGGER);
SetOrigin(GetSpawnOrigin());
DropToFloor();
botinfo = BOTINFO_ARMOR;
}
void

View File

@ -90,6 +90,7 @@ item_healthkit::Respawn(void)
SetSolid(SOLID_TRIGGER);
SetOrigin(GetSpawnOrigin());
DropToFloor();
botinfo = BOTINFO_HEALTH;
}
void

View File

@ -158,6 +158,7 @@ item_tfgoal::Touch(entity eToucher)
Disappear();
pl.g_items |= ITEM_GOALITEM;
pl.flags |= FL_GOALITEM;
forceinfokey(pl, "*goalitem_t", itos(m_iTeamOwner));
m_eActivator = pl;
@ -221,6 +222,16 @@ item_tfgoal::Respawn(void)
ReleaseThink();
m_status = GISTATUS_HOME;
/* helps with bots */
team = m_iTeamOwner;
/* it's either a goal item... or some other pickup */
if (m_dItemID) {
botinfo = BOTINFO_TEAM_GOALITEM;
} else {
botinfo = BOTINFO_AMMO;
}
if (m_iTeamOwner) {
SetRenderAmt(1.0f);
SetRenderFX(RFX_GLOWSHELL);

View File

@ -103,6 +103,28 @@ TFCNade_ThrowConcussion(player pl)
}
}
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EV_BEAMCYLINDER);
WriteCoord(MSG_MULTICAST, self.origin[0]);
WriteCoord(MSG_MULTICAST, self.origin[1]);
WriteCoord(MSG_MULTICAST, self.origin[2]);
WriteCoord(MSG_MULTICAST, 0);
WriteCoord(MSG_MULTICAST, 128);
WriteCoord(MSG_MULTICAST, 0);
WriteShort(MSG_MULTICAST, getmodelindex("sprites/shockwave.spr"));
WriteByte(MSG_MULTICAST, 0);
WriteByte(MSG_MULTICAST, 10);
WriteByte(MSG_MULTICAST, 2);
WriteByte(MSG_MULTICAST, 16);
WriteByte(MSG_MULTICAST, 0);
WriteByte(MSG_MULTICAST, 255);
WriteByte(MSG_MULTICAST, 255);
WriteByte(MSG_MULTICAST, 255);
WriteByte(MSG_MULTICAST, 255);
WriteByte(MSG_MULTICAST, 0);
msg_entity = self;
multicast(self.origin, MULTICAST_PVS);
NSEntity::Destroy();
}

View File

@ -31,6 +31,9 @@ func_nogrenades.qc
vox.qc
../../../valve/src/server/items.qc
../../../src/botlib/include.src
bot.qc
info_player_teamspawn.qc
item_tfgoal.qc
info_tfgoal.qc
@ -46,8 +49,6 @@ server.qc
../../../valve/src/server/flashlight.qc
../../../valve/src/server/modelevent.qc
../../../src/botlib/include.src
spawn.qc
../../../src/server/include.src

View File

@ -14,11 +14,77 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
float
TFCTeamJoin_SmallestTeam(int blue, int red, int yellow, int green)
{
while (blue > 0i || red > 0i || yellow > 0i || green > 0i) {
/* the first team that goes to 0, gets picked. */
if (blue <= 0i)
return 1;
else if (red <= 0i)
return 2;
else if (yellow <= 0i)
return 3;
else if (green <= 0i)
return 4;
blue--;
red--;
yellow--;
green--;
}
/* the first team that goes to 0, gets picked. */
if (blue == 0i)
return 1;
else if (red == 0i)
return 2;
else if (yellow == 0i)
return 3;
else if (green == 0i)
return 4;
return 0;
}
void
CSEv_TeamJoin_f(float f)
{
player pl = (player)self;
/* random... */
if (f == 0) {
int bluePlayers = 0i;
int redPlayers = 0i;
int yellowPlayers = 0i;
int greenPlayers = 0i;
/* hack to get it to never pick this team */
if (g_tfcHasBlueTeam == false)
bluePlayers = (int)cvar("sv_playerslots");
if (g_tfcHasRedTeam == false)
redPlayers = (int)cvar("sv_playerslots");
if (g_tfcHasYellowTeam == false)
yellowPlayers = (int)cvar("sv_playerslots");
if (g_tfcHasGreenTeam == false)
greenPlayers = (int)cvar("sv_playerslots");
/* count all valid players within each team */
for (entity e = world; (e = find(e, ::classname, "player"));) {
if (e.team == 1)
bluePlayers++;
else if (e.team == 2)
redPlayers++;
else if (e.team == 3)
yellowPlayers++;
else if (e.team == 4)
greenPlayers++;
}
/* assign us to the team with the lowest amount of players */
f = TFCTeamJoin_SmallestTeam(bluePlayers, redPlayers, yellowPlayers, greenPlayers);
}
/* mess, do it better */
if (f == 1) {
pl.team = 1; /* Blue */
@ -40,7 +106,6 @@ CSEv_TeamJoin_f(float f)
forceinfokey(pl, "topcolor", "0x3bff00");
forceinfokey(pl, "bottomcolor", "0x3bff00");
} else {
/* invalid */
return;
}

View File

@ -420,7 +420,7 @@ player::ReceiveEntity(float new, float flChanged)
return;
TFCHallucination_Insert(origin, v_angle);
m_flNextHallucination = time + 0.5f + random();
m_flNextHallucination = time + 0.25f + random(0.25,0.75);
}
}