PutClientInServer(bot);
}
+void bot_remove(entity bot)
+{
+ currentbots = currentbots - 1;
+ dropclient(bot);
+}
+
void bot_think(entity this)
{
if (this.bot_nextthink > time)
});
if(!bcount)
return; // no bots to remove
- currentbots = currentbots - 1;
- dropclient(best);
+ bot_remove(best);
}
void bot_removenewest()
{
+ entity best = NULL;
+ MUTATOR_CALLHOOK(Bot_SelectRemove, best);
+ best = M_ARGV(0, entity);
+ if ( best )
+ {
+ if ( !IS_BOT_CLIENT(best) )
+ {
+ LOG_WARN("Mutator selected a non-bot as a bot to remove\n");
+ best = NULL;
+ }
+ else
+ {
+ bot_remove(best);
+ return;
+ }
+ }
+
if(teamplay)
{
bot_removefromlargestteam();
}
float besttime = 0;
- entity best = NULL;
int bcount = 0;
FOREACH_CLIENT(it.isbot,
if(!bcount)
return; // no bots to remove
- currentbots = currentbots - 1;
- dropclient(best);
+ bot_remove(best);
}
void autoskill(float factor)
.string weapon_name;
.int sp_spawn_team;
.entity sp_spawn_spot;
+.bool can_respawn;
+
+int sp_bot_number;
/*QUAKED spawnfunc_tdm_team (0 .5 .8) (-16 -16 -24) (16 16 32)
Team declaration for TDM gameplay, this allows you to decide what team names and control point models are used in your map.
void sp_spawn_bot(entity spawn_point)
{
+ sp_bot_number++;
entity bot = spawnclient();
if (bot)
{
void sp_enemy_spawn_think(entity this)
{
sp_spawn_bot(this);
- setthink(this, SUB_Remove);
+ setthink(this, func_null);
+}
+
+
+void sp_enemy_spawn_use(entity this, entity actor, entity trigger)
+{
+ sp_spawn_bot(this);
}
spawnfunc(info_player_singleplayer_enemy)
this.team = SP_TEAM_ENEMY;
this.sp_spawn_team = SP_TEAM_ENEMY;
spawnfunc_info_player_deathmatch(this);
- setthink(this, sp_enemy_spawn_think);
+ this.use = sp_enemy_spawn_use;
+ if ( this.targetname == "" )
+ setthink(this, sp_enemy_spawn_think);
}
void sp_delayed_init(entity this)
// if no teams are found, spawn defaults
if(find(NULL, classname, "sp_team") == NULL)
{
- LOG_TRACE("No \"sp_team\" entities found on this map, creating them anyway.");
-
sp_spawn_team_entity("Player", SP_TEAM_PLAYER);
sp_spawn_team_entity("Enemy", SP_TEAM_ENEMY);
}
+
+ sp_bot_number = 0;
+}
+
+void sp_remove_bot(entity bot)
+{
+ sp_bot_number--;
+ bot.sp_spawn_spot = NULL;
+ bot_clear(bot);
}
MUTATOR_HOOKFUNCTION(sp, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
vector spawn_score = M_ARGV(2, vector);
if ( IS_BOT_CLIENT(player) )
{
- if ( spawn_spot.sp_spawn_team != SP_TEAM_ENEMY ||
- (player.sp_spawn_spot && player.sp_spawn_spot !=spawn_spot) )
+ if ( spawn_spot.sp_spawn_team != SP_TEAM_ENEMY ||
+ (player.sp_spawn_spot && player.sp_spawn_spot != spawn_spot) )
spawn_score.x = -1;
}
else if ( spawn_spot.sp_spawn_team != SP_TEAM_PLAYER )
MUTATOR_HOOKFUNCTION(sp, Bot_FixCount)
{
- int count = 0;
- for ( entity e = NULL; (e = findfloat(e, sp_spawn_team, SP_TEAM_ENEMY)); )
- count++;
- M_ARGV(2, int) = count;
+ M_ARGV(2, int) = sp_bot_number;
return true;
}
+
+MUTATOR_HOOKFUNCTION(sp, PlayerDies)
+{
+ entity target = M_ARGV(2, entity);
+ if ( IS_BOT_CLIENT(target) )
+ {
+ if ( target.sp_spawn_spot && !target.sp_spawn_spot.can_respawn )
+ {
+ sp_remove_bot(target);
+ }
+ }
+}
+
+MUTATOR_HOOKFUNCTION(sp, Bot_SelectRemove)
+{
+ FOREACH_CLIENT(it.isbot,
+ {
+ if ( !it.sp_spawn_spot )
+ {
+ M_ARGV(0, entity) = it;
+ return;
+ }
+ });
+}
+
+MUTATOR_HOOKFUNCTION(sp, PlayerPreThink)
+{
+ entity player = M_ARGV(0, entity);
+ if ( IS_BOT_CLIENT(player) && !player.sp_spawn_spot )
+ bot_remove(player);
+}