Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
RepoBots
Bot teammates that play like real players: explore, haul loot to extraction, run from monsters, carry dead teammates' heads, talk through in-game chat with TTS and take chat orders. Host a lobby; everyone needs the mod.
By Ralsei
CHANGELOG
Changelog
0.7.2
- Race: bots get the crown when they win. When the race is down to one racer, the game flies the crown to the end of the winner's current track piece and then chases the winner until it touches them, and that ends the race. A winning bot kept driving flat out, so the target kept jumping ahead and the crown never caught it. A winning bot now brakes and waits for the crown. If it still stalls, the host finishes the same steps with the game's own messages (send the crown, crown the winner), so the bot gets KING OF THE LOSERS, the win screen and the crown in the lobby.
0.7.1
- KING OF THE LOSERS works for bots. In the arena the last one standing has to grab the crown, and the crown only reacts to a fresh grab press, a timer that only ticks on a player's own computer. A bot that's last alive now walks to the crown and grabs it with that press set ("I am the king of the losers!"). If the game still doesn't react, or the crown is somewhere a bot can't reach, it sends the same "crown grabbed" message the game would. The crown, title and win screen all go to the bot.
- The race already crowns whoever is left last; bots are part of it since 0.7.0, so a bot can win that too.
0.7.0
- Fix: bots all dying when you die. RepoBots made every bot self-destruct 90 s after the last human died (
BotsGiveUpAfter). Real players don't do that, and living bots can still carry your head to extraction to revive you. Now off by default; bots only give up if they think the quota is lost. New settingSelfDestructWhenHumansDeadAfter(0 = never) if you want the old timer. - Fix: minigame softlock. The arena and the scooter race count their players and hand out scooters the instant the level starts, before bots have joined, so bots were never part of the game but stayed "alive" and it never ended. Now bots join arena levels within half a second, the race waits (up to ~12 s) for them, each bot gets its own scooter through the game's own assignment, and the arena counts them. A bot that still ends up outside the minigame is eliminated instead of blocking it.
- Bots fall in the arena. They used to hover wherever they spawned. In arena levels they now fall for real: through the floor hatch with everyone, and off the platforms when they drop into the kill zone.
- Slacker system: when the truck leaves, bots outside get the countdown and self-destruct unless the game itself counted them as in the truck (its own "spared" flag). Before, standing in the doorway for a moment was enough to cancel it, and then the truck waited forever.
- Deeper into the truck: bots wait at spots well inside the truck's room volume, spread out, instead of by the door, and walk back if they get shoved out.
- Shop: after buying, bots get in the truck and wait like players.
- Heavy loot: bots now go for loot too heavy for one (over
MaxCarryMass). They pick it up, say "This one's too heavy, can someone help me?" and wait. Another bot comes and grabs the other side, and they carry it together. You can help too. If nobody comes within ~35 s they leave it. Setting:AskForHelp. - Healing: bots with health to spare heal hurt teammates (players and each other) the game's way, by holding their health handle (10 HP a second moves over). Say "heal me" to ask. Setting:
HealTeammates. - Extraction points: when a bot finds one, all bots know about it (called out). With loot in hand and no usable extraction known, they say they need to find the next one and go searching.
- Stamina: sprinting uses energy like a player's (40 + their stamina upgrades); at zero they walk until it recharges. Setting:
Stamina.
0.6.4
- Giving up = self-destruct. When the bots decide the quota can't be made, the ones that agree self-destruct the way a player does from the Esc menu: one of the game's own farewell lines ("sayonara", "it's over for me", "I'm sorry"...) goes into chat (TTS) and onto the truck screen, then they die. Stubborn bots keep looting. You get about 10 s to talk them out of it: say "no", "stop", "don't" or "bot loot" and they answer "SELF DESTRUCT SEQUENCE CANCELLED!".
GiveUpSelfDestructoff = they go sit in the truck instead (0.6.2 behaviour). - When every human is dead and the bots give up, they self-destruct too (instead of just dropping dead).
- Left behind: when the truck leaves and the game starts its "I need to get to the truck in... 10..." countdown, bots outside the truck get it too: they drop everything and sprint for the truck, and self-destruct with one of the game's betrayal lines if they don't make it.
- Diagnostics: a
RepoBots slow framewarning if RepoBots ever takes more than 40 ms in a frame, to tell mod hitches apart from network drops.
0.6.3
- Carts (and players) now collide with bots. The game's body for a remote player (
PlayerAvatarCollision) takes its size from that player's computer over the network. Nobody sent one for bots, so their real body was scaled to zero and carts rolled straight through. Bots now set it to the normal standing / crouching size on every client, the same as a real player. - A cart or heavy object pushed into a bot shoves the bot out of the way instead of passing through it. A hard hit still knocks it over.
- Bots never "shove through" carts or heavy objects when they're stuck any more (that was meant for light props only).
- The bot's impact-sensing body uses the same layer as the game's own player body.
0.6.2
- Bots give up when they think the quota can't be made. Every few seconds they weigh up what a player would know: how much is still needed, how much loot the team has actually found (seen by a bot or discovered by anyone), how much of the level they've explored, and how many players are dead. If they've searched about 80% of the level and the loot they know of isn't enough, or most of the team is dead with a long way to go, and that stays true for about 25 s, one calls it ("We're not going to make the quota.") and they head back to the truck and goof around (more trolling). About one bot in five is stubborn and keeps looting ("I'm not giving up!"). They don't decide this in the first 2 minutes of a level.
- They cheer up if things improve (more loot found: "Wait, we might actually make it!"), or when you say "bot loot" ("Fine, one more try.").
- If every human is dead too and the bots have given up, the run ends after 20 s instead of
BotsGiveUpAfter(the truck can't leave before quota, so waiting longer just makes you spectate). - Setting:
GiveUp.
0.6.1
- Bots split up sometimes. Every few minutes the team may decide to spread out ("Let's split up, we'll cover more ground." / "Fine, but if I die it's your fault."): each bot takes its own side of the level for a couple of minutes, then they regroup. Even when not split, a bot avoids exploring right where another bot is or is heading. Settings:
SplitUp,SplitChance.
0.6.0
Built and checked against the real game DLL (v0.4.4): every game member RepoBots uses exists, all 18 patches apply, every method compiles.
- Bots' head, held items and grab beam: the current game keeps each player's camera pose in
PlayerLocalCamera(synced from its owner). Nobody sent one for bots, so it sat at the world origin. The head looked nowhere, held objects turned strangely (the game rotates held items relative to the holder's camera), and the beam pointed wrong. Bots now drive it from their eyes on every client. - Chat / TTS fix: the game deletes a voice object if another voice has the same network owner. Bot voices are owned by the host, so every client deleted them on sight. Bot voices now skip that check (
PlayerVoiceChat.Awakepatch). - Damage: bots now honour the game's "detection only" hurt colliders and per-collider ignore lists (they were taking damage from things that only detect), and they don't take damage outside gameplay or while god-moded (race vehicles).
- Racing minigame: the game seats every player in a scooter. Bots now drive theirs: steer toward the end of the track piece they're on (vehicles steer by the driver's camera), hold the throttle, add side input on sharp turns, and reverse out when wedged. The fight arena still works as before; which one it is gets picked automatically.
- Fellow Droid (Wesleys Enemies add-on): it already works with bots, and the droid can disguise itself as a bot. Bots are now fooled like players: a disguised droid that isn't coming for them isn't treated as a monster (
FooledByFellowDroid). - Vehicles read the driver's raw input (
InputDirectionRaw); bots now set it. - No more misleading "not found, using fallbacks" warning on the current game.
0.5.0
- Fix: monsters not attacking anyone. Monsters keep a per-player table for vision, filled once when they finish spawning. Bots join later, so they weren't in it, and the first time a monster's vision reached a bot it crashed and that monster stayed blind to everyone for the rest of the level. Bots are now registered with every monster before they enter the player list, and again every second (covers monsters that spawn later).
- Carts are pushed, not pulled. The game only switches a cart to handle-steering (cart rolls in front, turns with you) right after the grab button is pressed, which only happens on a real player's computer. Bots now trigger that, with a host-side fallback that holds the cart in front if the game's steering doesn't engage.
- Bots don't take carts that have loot in them or are parked in extraction.
- Getting stuck less: slimmer collision (door frames, the truck door), steps up to 0.45 m (truck lip), path corners kept off walls, steering around snags, pulling doors that open toward them, shoving through loose props, backing off and trying a different line before giving up.
- Snagged loot: a bot lifts the item and stops for a moment when it catches on something, and lets go and re-grabs it from a better angle (twice) before giving up on it.
- Shop: each bot picks an upgrade it can afford with its share of the money and puts it in the buy zone. It presses the buy button if the team can afford everything there (
BotsPressShopButton). It uses upgrades it bought when it finds them later (truck / next level). Health upgrades raise its max health. - Hiding: a bot that sees or hears a monster that isn't after it gets out of the monster's sight and crouches. It still runs from one that's hunting it or right on top of it (
HideFromMonsters). - Expressions: bots pull the game's faces (happy finding loot, scared running, angry when hit, sad when someone dies, silly when trolling), if the game has them. See the
RepoBots expressionslog line. - Conversations: bots near each other chat now and then, and answer simple things players say (hi, gg, lol, thanks, sorry, bye, "are you a bot?", questions).
- Trolling (
Trolling,TrollChance): now and then a bot crouch-spams you, stares and follows you, spins, sneaks up and says boo, shouts a fake monster warning, or lobs a bit of junk at your feet (never loot or items). - Cabinets and lids: bots open hinged things they walk past (
OpenContainers) and look inside. - Arena (after a failed run): bots join, grab a melee weapon or gun and go for the other players; the last one standing goes for the crown (
PlayMinigames). - Lobby comings and goings (
LobbyComeAndGo,LobbyLeaveChance): in the lobby menu a bot sometimes says bye and leaves, and someone new joins a bit later. - Way more names: half the bots now get gamer-tag style names (thousands of combinations, e.g. SneakyToaster, xXSoggyPickleXx, Turbo_Goose27) on top of the built-in list.
- Custom maps: on maps without the game's level points, bots treat the whole map as known and wander the navmesh instead of standing still. Custom monsters are found by the game's
Enemycomponent, so anything built on it counts.
0.4.0
- Bots only know what they've seen. Loot is noticed only when it's in front of the bot (110° view) with nothing in the way, or right next to it. Spotting something pings it on everyone's map, like a player looking at it.
CheatKnowAllLootstill exists if you want the old behaviour. - Bots build their own map. Each bot starts knowing only the truck area and learns rooms as it walks into them or sees into them. It can only route through rooms it has explored, so it has to search for extraction points and can get lost carrying loot ("I think I'm lost").
- C.A.R.T.: one bot takes a cart, pushes it while exploring, parks it to grab nearby loot, loads it, and pushes it into extraction once it holds
CartLoadTargetitems (default 3). The cart stays in the extraction zone until the extraction is done. Switch:UseCart. - Leaving: when the quota is done bots go to the truck and wait inside. If everyone alive is aboard, a bot uses the truck screen after a few seconds. Otherwise they wait
TruckWaitTime(default 120 s, 0 = forever), call out at half time and 15 s before, then leave. Anyone outside is left behind, the game's own rule. - Bots can die. Monster attacks and traps never reached bots (the game only applies them on the hit player's own computer). The host now applies damage, knock-downs and shoves to bots. Other damage to bots also goes through the host without shaking the host's camera.
- Bots are scared of monsters. They find monsters directly in the scene. They run from one they can see (DangerRadius, 150° view, line of sight), one close enough to hear (4 m), or one hunting them, and they crouch and hide for a moment afterwards.
- Solid bodies: bots have a player-sized body on the player layer. You bump into them; a cart, a thrown object or a tumbling player knocks them over with the game's own tumble, and they get back up once they settle. Running into one shoves it.
- Head and spectating: bots now drive their "eyes" (the game's
PlayerVisionTarget: head height and look direction) on every client. Before, these sat at the floor, which is why spectating showed their feet and probably why monsters ignored them. They also get their own spectate point at eye level. - Looking around: glance around while walking and idling, look at nearby players, face what they grab.
- Cosmetics: each bot gets random cosmetics (at most one per slot), kept for the session.
- Chat/TTS: bot voice objects are protected from the game's "duplicate" removal during setup (logged with a stack trace either way). New log lines:
RepoBots voice 'Name': ...(voice object / linked / TTS state) and a warning naming the reason if a bot falls back to a speech bubble. - Diagnostics:
RepoBots views 'Name'(what each network view on a bot syncs) andRepoBots sync map <Component>lines for every player component the game syncs.
0.3.2
- Bots no longer walk through doors and objects. Every step is swept with a player-sized capsule against the layers a real player collides with (read from the game's collision matrix). Doors and props get pushed (doors swing open), valuables only get a gentle nudge so they don't break, walls and heavy things are slid along. The old "stuck too long, hop to the next path point" fallback (which clipped through things) is gone: a blocked bot re-plans, then gives up on that target after 8 s.
- Bot colours on the new game version. Bots now send their own cosmetics and colour messages the way a player's game does (
SetupCosmeticsRPC,SetupColorsRPCfor every colour slot,SetupColorsAllRPC), 1.5 s after spawning and again at 4 s in case the game's "no colour received" fallback reset them. The colour list is found by element type as well as name, and colour 0 (usually the plain default) is skipped. Log:RepoBots colour 'Name': ....
0.3.1
- Fix: bots destroyed the moment they spawn. The game's own
PlayerAvatar.Awakenow removes "duplicate" player bodies, and on the network a bot looks like a second body of the host. RepoBots now also hides the host'sAmOwnerflag on bot views (not justIsMine), and if the game still tries to destroy a bot during its setup, that one destroy is blocked and RepoBots finishes the setup itself (wires the avatar's own components, adds it to the player list). Switch:Advanced.BlockSetupDestroy. - Diagnostics: one-time
RepoBots setup maplines listing whatPlayerAvatar.AwakeandStartcheck, in order. - The DLL now reports its real version (0.3.0 still said 0.2.4).
0.3.0
- Bots join in the lobby menu, the truck between levels and the shop, not just levels (
General.SpawnInLobby, on by default). There they hang around like players waiting. - Same bots all session: bots have a fixed identity (name, colour, steam id) from a roster, so the same bots follow you from the lobby through every level, keeping their health/upgrades in StatsManager. F6 adds a bot to the roster (max 6, key spam ignored), F7 removes the newest one for good. Greeting only once per session.
- Fix attempt: bots spawning but never appearing. The game never put them in its player list. The bot's identity RPC (
AddToStatsManagerRPC) now also reaches the host (newer game versions list players when it arrives), and RepoBots adds the bot toGameDirector.PlayerListitself if the game didn't. - Bot colour on newer game versions via
PlayerCosmetics.SetupColorsAllRPC. - Diagnostics: a
RepoBots statusline 2 s after each spawn (active, started, in player list, position, renderers shown, ownership, cosmetics state); a warning with a stack trace if anything destroys a bot; a one-timeRepoBots player-list writersline naming the game method(s) that add players to the player list. Bots whose object never activates are removed instead of lingering invisibly.
0.2.4
- Fix:
FieldAccessException ... is inaccessiblewhen a bot spawns. RepoBots reads private game fields; Unity's Mono blocks that unless the DLL opts out of verification. The prebuilt DLL now carriesSecurityPermission(SkipVerification = true). - Startup self-test: RepoBots runs a tiny method that reads a private game field. If the runtime still blocks it, RepoBots switches itself off with one clear log line instead of failing mid-level.
0.2.3
- Don't touch Photon until the game is in multiplayer. RepoBots registered its network listener the moment it loaded, which runs Photon's static setup during the splash screen, before the game configures Photon itself. That can slow down or stall hosting a lobby. Now nothing in RepoBots touches Photon until the game is actually in a multiplayer session (same approach REPOLib uses).
- No more HarmonyX "Could not find field" warnings at startup (lookups use plain reflection).
- When game members are missing, the log also gets a
RepoBots sync mapline (the fields the game syncs for every remote player, read fromPlayerAvatar.OnPhotonSerializeView) and aRepoBots cosmetics APIline, so look direction and colour can be wired to the new game version.
0.2.2
- Works with the newer game version that changed six things the startup check flagged: the player's look/camera fields (
localCameraTransform,localCameraPosition,localCameraRotation,clientRotationDelta),PlayerAvatar.PlayerAvatarSetColorandAssetManager.playerColors. These are now looked up by name at runtime with fallbacks (look direction falls back to the head transform; colour is skipped if the colour API moved), so they no longer switch the whole mod off. - If any of them aren't found, the log gets one
RepoBots field candidatesline listing the game's real field/method names, so the next build can use them directly.
0.2.1
- Fix: main menu never opening. On newer game versions a patch on
PlayerAvatar.Awakereferenced a game field that had changed. Mono refuses to run a whole method if any member in it is missing (even on lines only bots reach), so your own player failed to spawn and the menu waited forever. - Startup compatibility check: scans every game field/method/type RepoBots uses. If anything is missing it applies no patches (the game runs as if the mod wasn't installed), lists exactly what changed in
LogOutput.logand shows a notice on screen.Advanced.SkipCompatCheckforces loading anyway (testing only). - Every patch body is now guarded: game-specific code lives in separate non-inlined helpers inside try/catch, and patches always let the game's own code run if something goes wrong.
- RPCs are sent with whatever parameters the installed game declares (e.g.
UpdateHealthRPCgained a 4th value), instead of a hard-coded list that receivers silently dropped.
0.2.0
- Bots talk through the game's own chat: each bot gets a voice object like a player (mic disabled), so its lines are spoken with TTS, show the floating chat text, move its mouth and whisper when crouched. Speech bubble is now only a fallback (
Chat.UseGameChat). - New callouts: "I found something!" (with value for big finds), named monsters ("There's a Huntsman! Run!"), teammate down, hauling, idle chatter. All lines live in
src/BotLines.cs. - Fix: bot network views are now picked by their own instantiation + marker instead of
transform.root, so a bot can never flip a human player's avatar to "remote". - Self-check every second: if the local player's ownership,
PlayerAvatar.instanceorPlayerController's avatar ever point at a bot, it's repaired and logged. - Diagnostics dump of every avatar in the log once per level (and on any repair). Game version logged at startup.
0.1.0
- First version. Bots are real PlayerAvatars driven by the host: explore, spot and haul loot to extraction, activate extraction, flee monsters, carry dead teammates' heads, return to the truck, follow/stay/loot chat commands, speech bubbles, debug overlay.
- Untested in-game; built against an older game assembly.