Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions include/fb_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@ void BotsBackpackTouchedNonPlayer(gedict_t *backpack, gedict_t *entity);
void BotsMatchStart(void);
void BotsAssignTeamFlags(void);
qbool HasWeapon(gedict_t *player, int weapon);
int FrogbotSkillLevel(void);
int FrogbotHealth(void);
int FrogbotWeapon(void);

// botthink.qc
void SetMarker(gedict_t *client, gedict_t *marker);
Expand All @@ -389,15 +392,18 @@ void RunRandomTrials(float min, float max, float mult);
// editor
qbool HasSavedMarker(void);

#define FB_CVAR_ENABLED "k_fb_enabled"
#define FB_CVAR_OPTIONS "k_fb_options"
#define FB_CVAR_AUTOADD_LIMIT "k_fb_autoadd_limit"
#define FB_CVAR_AUTOREMOVE_AT "k_fb_autoremove_at"
#define FB_CVAR_AUTO_DELAY "k_fb_auto_delay"
#define FB_CVAR_SKILL "k_fb_skill"
#define FB_CVAR_DEBUG "k_fb_debug"
#define FB_CVAR_ADMIN_ONLY "k_fb_admin_only"
#define FB_CVAR_FREEZE_PREWAR "k_fb_freeze_prewar"
#define FB_CVAR_ENABLED "k_fb_enabled"
#define FB_CVAR_OPTIONS "k_fb_options"
#define FB_CVAR_AUTOADD_LIMIT "k_fb_autoadd_limit"
#define FB_CVAR_AUTOREMOVE_AT "k_fb_autoremove_at"
#define FB_CVAR_AUTO_DELAY "k_fb_auto_delay"
#define FB_CVAR_SKILL "k_fb_skill"
#define FB_CVAR_DEBUG "k_fb_debug"
#define FB_CVAR_ADMIN_ONLY "k_fb_admin_only"
#define FB_CVAR_FREEZE_PREWAR "k_fb_freeze_prewar"
#define FB_CVAR_HEALTH "k_fb_health"
#define FB_CVAR_WEAPON "k_fb_weapon"
#define FB_CVAR_BREAK_ON_DEATH "k_fb_break_on_death"

void BotsFireLogic(void);

Expand Down
4 changes: 4 additions & 0 deletions include/g_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,10 @@ void lgc_register_kill(gedict_t *player);
void lgc_register_miss(vec3_t start, gedict_t *player);
void lgc_register_hit(vec3_t start, gedict_t *player, gedict_t *victim);

#define TOT_MODE_VARIABLE "k_tot_mode"

qbool tot_mode_enabled(void);

// private games
qbool is_private_game(void);
qbool is_logged_in(gedict_t *p);
Expand Down
2 changes: 1 addition & 1 deletion include/g_syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ intptr_t trap_Map_Extension(const char *ext_name, intptr_t mapto);
-2 cannot map
*/

intptr_t trap_AddBot(const char *name, intptr_t bottomcolor, intptr_t topcolor, const char *skin);
intptr_t trap_AddBot(const char *name, intptr_t bottomcolor, intptr_t topcolor, const char *skin, intptr_t skill);
intptr_t trap_RemoveBot(intptr_t edn);
intptr_t trap_SetBotUserInfo(intptr_t edn, const char *varname, const char *value, intptr_t flags);
intptr_t trap_SetBotCMD(intptr_t edn, intptr_t msec, float angles_x, float angles_y, float angles_z,
Expand Down
10 changes: 9 additions & 1 deletion src/bot_botimp.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,11 +328,19 @@ char* BotNameGeneric(int botNumber)
{ "/ bro", "/ goldenboy", "/ tincan", "/ grue", "/ dizzy", "/ daisy", "/ denzil", "/ dora",
"/ shortie", "/ machina", "/ gudgie", "/ scoosh", "/ frazzle", "/ pop", "/ junk",
"/ overflow" };
char *hf_names[] =
{
"mutilator", "drejfus", "griffin", "heddan", "legio", "wigorf", "madmax",
"mrlame", "aptiva", "nepra", "nikke", "parasite", "rushing",
"lipton", "xorcist" };

char *custom_name = cvar_string(va("k_fb_name_%d", botNumber));

if (strnull(custom_name))
{
return names[(int)bound(0, botNumber, sizeof(names) / sizeof(names[0]) - 1)];
return tot_mode_enabled()
? hf_names[(int)bound(0, botNumber, sizeof(hf_names) / sizeof(hf_names[0]) - 1)]
: names[(int)bound(0, botNumber, sizeof(names) / sizeof(names[0]) - 1)];
}

return custom_name;
Expand Down
2 changes: 2 additions & 0 deletions src/bot_botweap.c
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,8 @@ void SelectWeapon(void)
}

CheckNewWeapon(DesiredWeapon());

self->fb.desired_weapon_impulse = FrogbotWeapon();
}

#endif // BOT_SUPPORT
129 changes: 123 additions & 6 deletions src/bot_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,21 @@ bot_t bots[MAX_BOTS] =
{ 0 }
};

static int FrogbotSkillLevel(void)
int FrogbotSkillLevel(void)
{
return (int)cvar(FB_CVAR_SKILL);
}

int FrogbotHealth(void)
{
return (int)cvar(FB_CVAR_HEALTH);
}

int FrogbotWeapon(void)
{
return (int)cvar(FB_CVAR_WEAPON);
}

static team_t* AddTeamToList(int *teamsFound, char *team, int topColor, int bottomColor)
{
int i;
Expand Down Expand Up @@ -294,11 +304,11 @@ void FrogbotsAddbot(int skill_level, const char *specificteam, qbool error_messa
{
strlcpy(bots[i].name, BotNameGeneric(i), sizeof(bots[i].name));

topColor = i_rnd(0, 13);
bottomColor = i_rnd(0, 13);
topColor = tot_mode_enabled() ? 11 : i_rnd(0, 13);
bottomColor = tot_mode_enabled() ? 12 : i_rnd(0, 13);
}

entity = trap_AddBot(bots[i].name, bottomColor, topColor, "base");
entity = trap_AddBot(bots[i].name, bottomColor, topColor, "base", skill_level);

if (entity == 0)
{
Expand Down Expand Up @@ -1860,12 +1870,27 @@ static void FrogbotsFillServer(void)
{
int max_clients = cvar("maxclients");
int plr_count = CountPlayers();
int skill_level = FrogbotSkillLevel();
int i;

if (trap_CmdArgc() >= 3)
{
char temp[10];

trap_CmdArgv(2, temp, sizeof(temp));

if (isdigit(temp[0]))
{
skill_level = atoi(temp);
}
}

for (i = 0; i < min(max_clients - plr_count, 8); ++i)
{
FrogbotsAddbot(FrogbotSkillLevel(), "", true);
FrogbotsAddbot(skill_level, "", true);
}

cvar_fset(FB_CVAR_SKILL, skill_level);
}

static void FrogbotsRemoveAll(void)
Expand Down Expand Up @@ -2108,6 +2133,94 @@ static void FrogbotsDisable(void)
}
}

static void FrogbotsSetHealth(void)
{
if (!bots_enabled())
{
G_sprint(self, 2, "Bots are disabled by the server.\n");
return;
}

if (trap_CmdArgc() <= 2)
{
G_sprint(self, 2, "Usage: /botcmd health <health>\n");
G_sprint(self, 2, " <health> must be in range %d and %d\n", 1, 300);
G_sprint(self, 2, "health is currently \"%d\"\n", FrogbotHealth());
}
else
{
char argument[32];
int new_health = 0;
int old_health = FrogbotHealth();

trap_CmdArgv(2, argument, sizeof(argument));
new_health = bound(1, atoi(argument), 300);

if (new_health != old_health)
{
cvar_fset(FB_CVAR_HEALTH, new_health);
G_sprint(self, 2, "health changed to \"%d\"\n", new_health);
}
}
}

static void FrogbotsSetWeapon(void)
{
if (!bots_enabled())
{
G_sprint(self, 2, "Bots are disabled by the server.\n");
return;
}

if (trap_CmdArgc() <= 2)
{
G_sprint(self, 2, "Usage: /botcmd weapon <weapon>\n");
G_sprint(self, 2, " <weapon> must be in range %d and %d\n", 2, 8);
G_sprint(self, 2, "weapon is currently \"%d\"\n", FrogbotWeapon());
}
else
{
char argument[32];
int new_weapon = 0;
int old_weapon = FrogbotWeapon();

trap_CmdArgv(2, argument, sizeof(argument));
new_weapon = bound(2, atoi(argument), 8);

if (new_weapon != old_weapon)
{
cvar_fset(FB_CVAR_WEAPON, new_weapon);
G_sprint(self, 2, "weapon changed to \"%d\"\n", new_weapon);
}
}
}

static void FrogbotsSetBreakOnDeath(void)
{
if (!bots_enabled())
{
G_sprint(self, 2, "Bots are disabled by the server.\n");
return;
}

cvar_fset(FB_CVAR_BREAK_ON_DEATH, !cvar(FB_CVAR_BREAK_ON_DEATH));
G_sprint(self, 2, "break on death changed to \"%s\"\n", (int)cvar(FB_CVAR_BREAK_ON_DEATH) ? "on" : "off");

}

static void FrogbotsToggleQuad(void)
{
if ((int)self->s.v.items & IT_QUAD) {
self->s.v.items = (int)self->s.v.items & ~IT_QUAD;
self->super_time = 0;
self->super_damage_finished = 0;
} else {
self->s.v.items = (int)self->s.v.items | IT_QUAD;
self->super_time = 1;
self->super_damage_finished = g_globalvars.time + 3600 * 20;
}
}

typedef struct frogbot_cmd_s
{
char *name;
Expand All @@ -2123,7 +2236,11 @@ static frogbot_cmd_t std_commands[] =
{ "removebot", FrogbotsRemovebot_f, "Removes a single bot" },
{ "removeall", FrogbotsRemoveAll, "Removes all bots from server" },
{ "debug", FrogbotsDebug, "Debugging commands" },
{ "disable", FrogbotsDisable, "Disable frogbots" } };
{ "disable", FrogbotsDisable, "Disable frogbots" },
{ "health", FrogbotsSetHealth, "Set initial health for the bot" },
{ "weapon", FrogbotsSetWeapon, "Set which weapon the bot should use" },
{ "breakondeath", FrogbotsSetBreakOnDeath, "Automatically break when you die" },
{ "togglequad", FrogbotsToggleQuad, "Toggle quad damage" } };

static frogbot_cmd_t editor_commands[] =
{
Expand Down
27 changes: 26 additions & 1 deletion src/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -2130,6 +2130,31 @@ void PutClientInServer(void)
// Red armor + LG
items = IT_LIGHTNING | IT_ARMOR3;
}
else if (tot_mode_enabled())
{
self->s.v.ammo_nails = 255;
self->s.v.ammo_shells = 255;
self->s.v.ammo_rockets = 255;
self->s.v.ammo_cells = 255;

self->s.v.armorvalue = self->isBot ? 0 : 200;
self->s.v.armortype = self->isBot ? 0 : 0.8;
self->s.v.health = self->isBot ? 100 : 250;

items = self->s.v.items;
items |= IT_NAILGUN;
items |= IT_SUPER_NAILGUN;
items |= IT_SUPER_SHOTGUN;
items |= IT_ROCKET_LAUNCHER;
items |= IT_GRENADE_LAUNCHER;

if (streq(mapname, "dm3") || streq(mapname, "dm4"))
items |= IT_LIGHTNING;

items &= ~( IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3);
if (!self->isBot)
items |= IT_ARMOR3;
}
else
{
self->s.v.ammo_nails = 255;
Expand Down Expand Up @@ -3878,7 +3903,7 @@ void CheckPowerups(void)
self->s.v.items -= IT_QUAD;
if (!k_practice) // #practice mode#
{
if (deathmatch == 4)
if (deathmatch == 4 && !tot_mode_enabled())
{
self->s.v.ammo_cells = 255;
self->s.v.armorvalue = 1;
Expand Down
Loading