You are viewing a potentially older version of this package. View all versions.
Ralsei-RepoBots-0.7.2 icon

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
Date uploaded 2 days ago
Version 0.7.2
Download link Ralsei-RepoBots-0.7.2.zip
Downloads 381
Dependency string Ralsei-RepoBots-0.7.2

This mod requires the following mods to function

BepInEx-BepInExPack-5.4.2305 icon
BepInEx-BepInExPack

BepInEx pack for Mono Unity games. Preconfigured and ready to use.

Preferred version: 5.4.2305

README

RepoBots

Bot teammates for R.E.P.O. that play like real players.

A bot is a real PlayerAvatar — same robot body, name tag, colour, health bar, death head and grab beam as a human. The game treats it like a remote player who's on a laggy connection: monsters see, chase and hurt it, it shows up in spectate, it has to be in the truck before the level can end, and when it dies its head drops so you can carry it to extraction to revive it.

The host runs every bot's brain and streams its movement to everyone else.

Status: v0.3.2, loads and hosts in-game; bot behaviour still being tested. It compiles and every Harmony patch applies cleanly against a decompiled (older, April 2025) Assembly-CSharp.dll, but it hasn't been run inside the game yet. Expect a round or two of fixes — see Reporting problems.


What bots do

Situation Bot behaviour
Level starts Joins ~3 s after load next to the host, says hi, looks around the truck
Exploring Builds its own map room by room (it starts knowing only the truck area), heads for the edge of what it knows, glances around as it walks. It can only route through rooms it has explored, so it can get lost
Sees loot Only loot in front of it with nothing in the way (or right next to it). Calls it out, pings it on the map, walks over, faces it, grabs it with the normal grab beam
C.A.R.T. One bot takes a cart, pushes it while exploring, parks it to fetch nearby loot, loads it, and pushes it into extraction at CartLoadTarget items
Hauling Carries it at a slower pace into its cart or to an extraction point it has found (searches for one if it doesn't know any), waits if the loot snags, presses the extraction button itself if none is active
Extraction running Steps off the platform (the tube hurts) and waits with any loot until the next point opens
Monster seen / heard / hunting it Shouts, drops loot (keeps heads), sprints away to somewhere it knows, then crouches for a bit once it's lost it
Hit by a cart, thrown object or tumbling player Gets knocked over (the game's tumble) and gets back up when it settles; walking into it shoves it
Teammate dies Picks up their head and carries it to extraction so they get revived
Hurt Takes real damage from monsters and traps, gets knocked down by big hits, "Ow!", flees from whatever hit it
Dies Normal death: head drops, it can be revived by extracting its head
All extractions done Heads into the truck and waits. Once everyone alive is aboard a bot uses the truck screen; if people don't come back within TruckWaitTime it warns, then leaves without them (the game's own rule for anyone outside)
Player walks up and stares at it Double-crouch greeting
Everyone else is dead Keeps going (and can revive you), but gives up after BotsGiveUpAfter seconds so the run can end

Chat commands

Type in the normal in-game chat. Address one bot by name (clanker follow), all of them (bots follow, everyone stay), or the nearest one (bot follow).

Say Effect
follow, with me, on me Follows you, sprints to catch up, crouches when you crouch
come, come here, over here Walks to where you are and waits
stay, wait, hold, stop Holds its current position
loot, explore, go, resume Back to playing on its own
truck, go back, return Goes to the truck
drop, let go Drops what it's holding
status, report, how much Says the haul, what it's doing and its HP

Bots talk like players

Each bot gets its own voice object (the same one every player has, with the microphone part switched off) and talks through the game's normal chat, so lines are spoken by TTS from where the bot is standing, with the floating chat text above its head, mouth movement, and a whisper when it's crouching. Monsters can hear it too.

What they say: "I found something!" (or "I found something worth about three grand!"), "There's a Huntsman! Run!", "Oh no, Sam is down!", "Hang on Sam, grabbing your head!", "Taking this to extraction.", "That's everything, back to the truck!", replies to your commands, and the odd bit of idle chatter. All the lines are in src/BotLines.cs if you want to rewrite them.

The voice takes ~3 seconds to set up after a bot joins; anything it says before that shows as a speech bubble instead. Turn TTS off with Chat.UseGameChat = false.

Keys (host)

Key Action
F6 Add a bot (it stays for the whole session, max 6)
F7 Remove the newest bot for good
F5 Debug overlay: each bot's mode, task, target, path progress, HP

Install (try it now)

  1. In r2modman / Thunderstore Mod Manager: Settings → Import local mod → pick RepoBots-0.3.2-prebuilt.zip.
  2. Everyone in the lobby needs the mod. Players without it see the bot frozen at the spawn.
  3. Host a lobby (a private lobby on your own works — singleplayer mode isn't supported) and start a level.

The prebuilt DLL was compiled against an older game version. At startup RepoBots checks that everything it uses still exists in your game. If not, it switches itself off (the game is unaffected), shows a red notice in the corner, and lists what changed in LogOutput.log under RepoBots ... doesn't match this version of R.E.P.O.. Send that list, or build from source against your own game files (below), and the compiler will point at the same things.

Build from source

Needs the .NET SDK (6 or newer) and R.E.P.O. installed.

# default GameDir is C:\Program Files (x86)\Steam\steamapps\common\REPO
dotnet build -c Release -p:GameDir="D:\SteamLibrary\steamapps\common\REPO"

Or copy GameDir.props.user.example to GameDir.props.user and set GameDir (and optionally ProfileDir to your r2modman profile so every build is copied straight into BepInEx/plugins/RepoBots).

package.ps1 builds and zips a Thunderstore package into dist/.

The game assembly is publicized at build time (BepInEx.AssemblyPublicizer.MSBuild), so the code reads the game's internal fields directly.


How it works

Host                                             Every client (incl. host)
────                                             ─────────────────────────
PhotonNetwork.Instantiate(PlayerAvatar,          PUN builds the avatar → our PhotonView patch
  data: ["RepoBots.v1", name, id, colour])  ───► sees the marker and forces IsMine = false
                                                 before any Awake runs → game code takes the
BotBrain (host only)                              "remote player" path for it everywhere
  think 5 Hz: threats → truck → mode → loot
  act every frame: navmesh path, look, grab     BotPuppet writes position / look / stance /
  publishes BotState ───────────────────────►     velocity / grab puller into the same fields
                       RaiseEvent @ 20 Hz         PlayerAvatar.OnPhotonSerializeView fills

Patches (each one separately, so a game update only breaks the feature it touches):

Target Why
PhotonView.ControllerActorNr setter Keep bot views "not mine", even on the host who owns them
PlayerAvatar.Awake Register the bot, set its name / steam id, add the puppet
PlayerAvatar.Start + LevelGenerator.PlayerSpawn A late-joining avatar makes the host re-run PlayerSpawn, which teleports everyone back to the truck. Skipped for bots; their death head + tumble body are created separately
PlayerAvatar.OutroStartRPC The level only ends when every avatar reports outroDone
PlayerHealth.HurtOtherRPC / HealOtherRPC Damage/heal normally applies on the avatar owner's machine. The host applies it for bots
PlayerAvatar.ReviveRPC / PlayerDeathRPC / SpawnRPC Keep the brain in sync with deaths, revives and teleports
SemiFunc.PlayerGetName Names come from the Photon owner, which for a bot is the host
StatsManager.SaveGame Keep bots out of your save file's player list
PlayerAvatar.ChatMessageSendRPC Chat commands
PlayerVoiceChat.Start Bot voice objects: microphone off, never block chat

Grabbing goes through the game's own grab system (GrabLink → GrabStartedRPC → beam RPCs, then the master's physics pulls the object to the bot's puller point), so the beam and "who's holding what" look normal to everyone.


Config

BepInEx/config/Jillybob.RepoBots.cfg (also editable in r2modman's config editor).

Section Key Default
General BotCount 1 Bots per level (1–4)
General AutoSpawn true Join automatically each level
General SpawnInLobby true Also join in the lobby menu, truck and shop
General DefaultMode Loot Loot / Follow / Stay / Truck
General BotNames Clanker,Rusty,…
Behaviour FleeEnemies true
Behaviour DangerRadius / SafeRadius 8 / 16 When to run, when it's safe
Behaviour RescueHeads true Carry dead teammates' heads to extraction
Behaviour ActivateExtraction true Press the extraction button
Behaviour MaxCarryMass 3.5 Skip heavier loot
Behaviour CheatKnowAllLoot false Know where all valuables are
Behaviour UseCart / CartLoadTarget true / 3 Push the C.A.R.T., items before taking it to extraction
Behaviour TruckWaitTime 120 Seconds to wait at the truck before leaving (0 = forever)
Behaviour HideFromMonsters true Hide from monsters that aren't after them instead of always running
Behaviour BotsShop / BotsPressShopButton true / true Buy an upgrade each in the shop, press the buy button
Behaviour OpenContainers true Open cabinets / lids they pass
Behaviour PlayMinigames true Fight in the arena after a failed run
Behaviour Trolling / TrollChance true / 0.15 Pranks, chance per minute near a human
General LobbyComeAndGo / LobbyLeaveChance true / 0.2 Bots leave and new ones join in the lobby menu
Chat Conversations / ReplyToChat true / true Bot-to-bot chats, answering what you say
Chat UseExpressions true Use the game's face expressions
Behaviour GiveUp / GiveUpSelfDestruct true / true Give up when they think the quota can't be made, and self-destruct (say "no" / "stop" to cancel)
Behaviour AskForHelp true Go for heavy loot, ask for help and help each other carry it
Behaviour HealTeammates true Share health with hurt teammates ("heal me" in chat)
Behaviour Stamina true Sprinting uses energy like a player's
Behaviour SelfDestructWhenHumansDeadAfter 0 Self-destruct this long after every human dies (0 = never)
Behaviour SplitUp / SplitChance true / 0.5 Sometimes split up and take a side of the level each, then regroup
Behaviour FooledByFellowDroid true With Fellow Droid installed, bots don't run from a disguised droid until it comes for them
Movement WalkSpeed / SprintSpeed / CarrySpeed 2.6 / 4.4 / 2.1 m/s
Movement FootOffset 0 Fix floating / sinking
Chat Chatty / ChatCommands true / true
Chat UseGameChat true Talk through game chat + TTS (false = speech bubbles)
Chat ChatCooldown 7 Seconds between unprompted lines
Advanced EventCodeBase 180 Photon event codes 180–183
Advanced VerboseLogging false Log every decision
Advanced SkipCompatCheck false Load even if the startup check finds game changes (testing only)

Known limitations

  • Singleplayer isn't supported — host a private lobby instead.
  • Everyone needs the mod, or they see a frozen bot.
  • Bots move along the navmesh, so they don't jump or climb. They push doors and props but can't vault over things. Enemy grabs that pull a player around on their own client don't move bots.
  • Bots buy and use upgrades and use weapons in the arena, but don't use other items (flashlights, drones, grenades) during levels.
  • Bots play both after-failure minigames (arena fight and scooter race), but they drive fairly simply: no boost pads or deliberate drifting.
  • Big two-person valuables are skipped (MaxCarryMass).
  • Enemies that hook into a player's voice chat may misbehave around bots.

Reporting problems

Turn on VerboseLogging, play until it goes wrong, then send:

Don't copy the log out of the black BepInEx console window: it only keeps the last ~9,000 lines, so the startup part (where the useful errors are) is gone. Attach the file instead: r2modman → Settings → Browse profile folder → BepInEx\LogOutput.log.

  1. The whole BepInEx/LogOutput.log from the host's r2modman profile — the important part is the top (load + patch lines) and the RepoBots diagnostics block it writes ~3 s after bots join
  2. A screenshot with the F5 overlay open
  3. Your game version, and whether it was the prebuilt DLL or your own build (and any build errors)

License

MIT — see LICENSE. Not affiliated with semiwork. No game code or assets are included.

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 setting SelfDestructWhenHumansDeadAfter (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!". GiveUpSelfDestruct off = 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 frame warning 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.Awake patch).
  • 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 expressions log 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 Enemy component, 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. CheatKnowAllLoot still 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 CartLoadTarget items (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) and RepoBots 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, SetupColorsRPC for 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.Awake now removes "duplicate" player bodies, and on the network a bot looks like a second body of the host. RepoBots now also hides the host's AmOwner flag on bot views (not just IsMine), 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 map lines listing what PlayerAvatar.Awake and Start check, 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 to GameDirector.PlayerList itself if the game didn't.
  • Bot colour on newer game versions via PlayerCosmetics.SetupColorsAllRPC.
  • Diagnostics: a RepoBots status line 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-time RepoBots player-list writers line 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 inaccessible when a bot spawns. RepoBots reads private game fields; Unity's Mono blocks that unless the DLL opts out of verification. The prebuilt DLL now carries SecurityPermission(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 map line (the fields the game syncs for every remote player, read from PlayerAvatar.OnPhotonSerializeView) and a RepoBots cosmetics API line, 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.PlayerAvatarSetColor and AssetManager.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 candidates line 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.Awake referenced 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.log and shows a notice on screen. Advanced.SkipCompatCheck forces 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. UpdateHealthRPC gained 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.instance or PlayerController'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.