mirror of
https://github.com/vladtrc/iw4L
synced 2026-10-26 10:19:50 -04:00
Keep bots inside the 18 player slots instead of colliding with corpses
A bot took the next unused client id with no upper bound, and the roster only capped bots at MAX_HOST_BOTS (20). The lobby's Enemy and Friendly Bots rules plus a `bot add`, or two `bot add` commands, could therefore make more than 17 bots beside the host. Client ids are also entity numbers, and the corpse ring starts at entity 18 (PLAYER_CORPSE_ENTITY_BASE), so bots 18 and up shared an entity number with a corpse: the net layer rejected the snapshot entity as a centity-number gap, and the end-of-match client data overran its 18 rows (setclientmatchdata IndexOutOfRange). Bots now claim ids 1..17 only, wrapping around to reuse freed ids, and adding stops when every slot is taken. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,8 @@ use crate::controller::HostController;
|
||||
|
||||
pub const MAX_HOST_BOTS: u32 = 20;
|
||||
|
||||
const MAX_CLIENT_SLOTS: u32 = playerstate_iw4::PLAYER_CORPSE_ENTITY_BASE as u32;
|
||||
|
||||
const BOT_NAMES: [&str; 52] = [
|
||||
"contextrot",
|
||||
"t.me/contextrot",
|
||||
@@ -250,16 +252,12 @@ impl BotRoster {
|
||||
}
|
||||
|
||||
fn claim_id(&mut self, taken: &[ClientId]) -> Option<ClientId> {
|
||||
// Only `bots + taken` ids are spoken for, so one candidate more than
|
||||
// that always turns up a free one.
|
||||
let candidates = self
|
||||
.bots
|
||||
.len()
|
||||
.saturating_add(taken.len())
|
||||
.saturating_add(1);
|
||||
for _ in 0..candidates {
|
||||
for _ in 1..MAX_CLIENT_SLOTS {
|
||||
if !(1..MAX_CLIENT_SLOTS).contains(&self.next_client) {
|
||||
self.next_client = 1;
|
||||
}
|
||||
let id = ClientId(self.next_client);
|
||||
self.next_client = self.next_client.wrapping_add(1).max(1);
|
||||
self.next_client += 1;
|
||||
if !taken.contains(&id) && !self.is_bot(id) {
|
||||
return Some(id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user