SimPassiveLevelingOverhaul
Overhauls Erenshor's Sim level progression with passive XP over time.
| Date uploaded | 2 weeks ago |
| Version | 1.4.0 |
| Download link | TeamSaltyBois-SimPassiveLevelingOverhaul-1.4.0.zip |
| Downloads | 21 |
| Dependency string | TeamSaltyBois-SimPassiveLevelingOverhaul-1.4.0 |
This mod requires the following mods to function
BepInEx-BepInExPack
BepInEx pack for Mono Unity games. Preconfigured and ready to use.
Preferred version: 5.4.2305README
Sim Passive Leveling Overhaul — v1.4
Erenshor game update (2026-07-16): Supported.
Description
This mod replaces the vanilla sim XP catchup system with a highly configurable passive XP drip that runs in the background while you play, and only while you play. No offline catch up.
The vanilla system grants simulated players most of their levels in abrupt bursts each time you log in, depending on which slot the sims are assigned to. I found this a bit immersion breaking with my playstyle: I log out frequently and only play a couple times a week.
Many values are exposed and configurable so you can tweak the leveling to your liking. The mod can be added or removed mid playthrough with no issues.
If you're starting fresh and want more of a "day one" MMO experience, I recommend pairing this with my companion mod, Sim Start At Level 1.
Features
Passive XP for All Eligible Sims
- Unassigned generic sims gain XP on the standard curve.
- Rival sims level roughly 25% faster.
- Your own character slot sims gain XP on the standard curve up to a cap of two levels above you, with a configurable catch up multiplier when behind.
- Active party members and sims tied to other character slots do not receive passive XP. They gain levels through combat or when you play those characters.
- Passive XP stacks with whatever sims earn from their own kills out in the world. Neither overwrites the other.
1–35 Leveling Curve (~110 Hours Total assuming no variance)
- Levels 2–5: 12 to 18 minutes per level
- Levels 6–10: 18 minutes to 1 hour per level
- Levels 11–15: 1 hour 6 minutes to 1 hour 36 minutes per level
- Levels 16–20: 1 hour 48 minutes to 3 hours per level
- Levels 21–25: 3 hours 30 minutes to 5 hours 6 minutes per level
- Levels 26–30: 5 hours 24 minutes to 6 hours 30 minutes per level
- Levels 31–35: 6 hours 42 minutes to 7 hours 30 minutes per level
Per-Sim Variance (Configurable, default 0.5× – 1.5×)
XP modifier from a random seed, which rerolls on zone changes. Produces organic variation across the roster.
Configuration
All settings are stored in BepInEx/config/erenshor.simxpovertime.cfg. Edit this file while the game is closed to adjust behavior.
-
TickIntervalSeconds— Default:120, minimum30, maximum3600
Interval in seconds between XP grants. The XP granted is scaled accordingly, so the leveling speed stays the same regardless of interval. Values outside the range are clamped. Below 30 seconds, rounding on each tick starts to inflate early level speed. -
MaxLevel— Default:35, range1–35
Maximum level cap for sims. Sims will not gain passive XP beyond this level. Values outside the range are clamped: 35 is the game's own maximum, and post 35 ascension progression is left entirely to the base game. -
VarianceMin— Default:0.5
Minimum speed variance per sim. A value of0.5means the slowest sim levels at half speed. -
VarianceMax— Default:1.5
Maximum speed variance per sim. A value of1.5means the fastest sim levels at 1.5× speed. -
UseFixedSeed— Default:false
If enabled, uses a fixed seed for variance per sim. All sims will level at the same pace every session instead of randomizing on each login. -
FixedSeedValue— Default:12345
The seed value used whenUseFixedSeedis enabled. -
SeedIncrementOnZoneChange— Default:true
If enabled, rerolls variance per sim when you change zones. Set tofalsefor stable variance throughout an entire session. -
RivalSpeedMultiplier— Default:1.25
XP speed multiplier for rival sims (Friends' Club). Set to1.0for no bonus. -
SlotCatchupPerLevel— Default:0.10
Catch up boost applied per level behind. For example, if a sim is 5 levels behind, they receive a0.5(50%) boost. -
SlotCatchupMax— Default:3.0
Upper limit for the catch up multiplier. Prevents extreme catch up boosts. -
SlotLevelCapOffset— Default:2
How many levels above the player a character tied sim can passively reach. Set to 35 to effectively disable this cap. -
[XPCurve]section:HoursForLevel2throughHoursForLevel35(bottom of the config file)
Hours of passive XP each level takes to reach, at 1.0× variance (rival and catch up multipliers still apply on top).HoursForLevel2is the climb from level 1 to 2, and so on up the ladder. The defaults produce the curve in the table above. -
DebugLogging— Default:false
Enables verbose logging for troubleshooting.
Requirements
- BepInEx 5.4.23.5
Installation
- Install BepInEx for Erenshor.
- Place
SimPassiveLevelingOverhaul.dllin yourBepInEx/plugins/folder. - Launch the game. The configuration file generates in
BepInEx/config/automatically on the first run.
Compatibility
Twelve small Harmony patches across eleven game methods to natural event boundaries, logging in, sims spawning, sims saving, zone changes, and does all of its ongoing work in its own coroutines. What that means in practice:
-
Other mods: A conflict is only possible if another mod patches one of the methods listed below and changes what it does (skipping the original or rewriting the same fields). Mods that read sim data or touch other parts of the game will coexist fine.
-
Game updates: If an update removes or renames a patched method, the mod fails to load and logs an error. The game itself keeps running vanilla. Updates that change how sims save or load can change behavior more quietly, which is why each game patch gets checked. Version 1.3 handles the July 16th update's new spawn time saves.
-
Adding or removing mid playthrough: Safe. The mod only writes the level and XP fields of the same save files the game already uses. Delete the DLL and vanilla leveling (including the login catchup) simply resumes.
Methods Patched
-
SimPlayerMngr.Start— Postfix
Launches the mod's three coroutines: the XP tick, the background writer, and the login restore. The game recreates this manager every login, so the coroutines relaunch with it. -
SimPlayerMngr.LoadSimPlayersIntoGame— Prefix
Wipes the mod's session state clean at the start of each login. -
SimPlayerDataManager.CheckLoadData— Postfix
The game already parses every sim's save file during login. This grabs a copy as each one goes by, providing the pre login snapshot and seeding the in memory record cache without a single extra file read. -
SimPlayerDataManager.LoadFromFile— Postfix
Same capture, for the generic sim loading path. -
SimPlayer.Start— Postfix
A spawning sim gets its stats from its save file, which can lag behind the mod's tracked values. This brings the fresh spawn up to date. -
SimPlayer.SaveSim— Prefix + Postfix
When the game saves a spawned sim, the Postfix copies the saved XP back into tracking (the game does this for Level, but never did for XP), drops the sim's cached record, and cancels any pending background write. The Prefix snapshots the tracked level so the spawn time save the game performs (added in the July 16th patch) can't push stale file values over it. -
SimPlayerDataManager.SaveSimData— Postfix
Whenever the game writes any sim's file after login, the mod drops its cached copy of that record so a later background write can't resurrect older data. This covers the save paths that skip SaveSim, like the social list's friend toggle. -
SimPlayerDataManager.DeleteSimSaveData— Postfix
When the game deletes a sim's file on purpose (renames, sim resets), the mod forgets its cached copy and cancels any pending write, so the file stays deleted. -
SimPlayerMngr.CollectActiveSimData— Prefix
Rerolls the variance seed per sim on zone changes, if enabled in config. -
SimPlayerDataManager.SaveAllSimData— Prefix
Fires at every save point: zone changes (including teleports), logout, quit, respawn. Writes out anything the background writer hasn't reached yet, so the files on disk always match the in-memory state before the game moves on. -
SimPlayerMngr.SimPlayerCatchupCode— Prefix (skips the original)
Turns off the vanilla random catchup leveling. Replacing it is the whole point of the mod.
Performance
During normal gameplay the mod does no work on each frame. Three coroutines sit parked in Unity's scheduler. A background writer wakes four times a second and persists at most one changed sim per wake, using buffered atomic writes. This uses the same temp file, replace, and backup pattern as the game's own saver.
XP ticks run roughly every 120 seconds by default. They are pure arithmetic, processed in batches of 25 per frame, well under 0.1 milliseconds per frame with debug logging off. No file is read or written on a tick frame.
Notes
-
This passive XP stops at level 35 by default. I recommend keeping this, so sims don't become overpowered by getting too many ascension levels.
-
If the game hard crashes, unspawned sims can lose up to one tick interval of passive XP (whatever the writer hadn't persisted yet). Normal quits, logouts, and zone changes always save everything.
-
The "player level + offset" cap only limits passive XP. A slot sim that banked combat XP from its own kills can level past the cap when that XP converts. This matches vanilla combat leveling behavior.
To-Do
- Scrubby specific multiplier of .2 to simulate his true leveling speed.
CHANGELOG
Changelog
1.4.2
Fixed
- The quarantine now blocks the game's own login time saves.
During login the game saves every sim record back to disk right after reading it. For a sim quarantined by an unreadable (locked) file, that record is the mod's in memory substitute. the save normally fails against the same lock, but a lock released at exactly that instant could write the substitute over the real file. A newSaveSimDataprefix skips those writes for quarantined sims until the login restore completes. Nothing legitimate is blocked. Every later save of a quarantined sim is derived from a successful read of the real file. Side benefit, a lock held through login now produces one clear mod log line instead of the game'sSave FAILEDerror.
1.4.1
Fixed
-
Damaged sim files now repair themselves at login.
The mod now validates sim files as the game reads them. damaged files are restored from their backup, and if both copies are unusable the sim is reset with the login guaranteed to survive. This is the same recovery ladder the game already uses for Reliquary and guild data. -
A briefly locked sim file can no longer cause a permanent reset.
If something (an antivirus scan, a sync tool) held a sim's file at the exact moment of login the game built placeholder data for that sim, and the mod's background writer, would later save that placeholder over the real file. Locked files are now retried, then served from backup in memory and quarantined. Nothing writes to that sim's file for the session, and the first successful read restores normal service automatically. -
One unreadable sim file can no longer hang the login at the auction house pass.
The auction house rereads every sim's save file while the game loads. With no error handling a single locked or unreadable file stranded the loading screen forever. The login now continues with partial auction data for that session and rebuilds it next time. -
XP is no longer lost for sims that die or revive near you.
The game stops saving a sim's body the moment it dies, and never resumes for sims that revive with their group. The mod now recognizes both cases and persists their XP through the background writer, so a death near the end of a session loses nothing.
Changed
TickIntervalSecondsminimum raised from 30 to 90 seconds.
At very low intervals the background writer could still be working through the previous tick's changes when the next tick landed.
1.4.0
Added
- The leveling curve is now configurable.
[XPCurve]config section added. It exposes hours per level for levels 2 through 35. Each entry is the time that level takes to reach:HoursForLevel2is the climb from 1 to 2, and so on.
Fixed
-
Login level bumps are reverted again.
The game reads every premade sim's file twice while loading: once directly, and once more during its full save folder scan, after it has already applied and saved its vanilla login level bumps. Since the v1.3 rework, the mod's prelogin snapshot kept the second, already bumped read, so rival and slot tied premades quietly kept their vanilla login levels. The snapshot now keeps the first read of each login, so the revert sees the bumps again. -
Login bump reverts are written to disk before you can disconnect.
The reverts used to trickle out through the background writer while the character select screen sat idle. Disconnecting there performs no save pass, so a rapid login and disconnect could discard pending reverts and let bumped levels stick permanently. The reverts are now flushed to disk in the same instant the login restore finishes. -
Total leveling time now matches the advertised ~110 hours.
The old curve consumed its 35 entries one level early: each level was paced by its own row instead of the next one, so the final 7.5 hour entry never ran and a sim actually reached max in about 102 hours. The curve is now keyed to the level being reached, and the default table has been retuned to total 109.8 hours exactly. The first eight levels are unchanged, the odd speed dips at 10-11 and 30-32 are smoothed out, and the jump at level 20 is gentler. -
Friending an offline sim no longer gets silently reverted.
The social list's friend toggle writes a sim's file directly, bypassing the save path the mod watches. The mod's cached copy of that sim went stale, and the next background write would quietly restore the oldFriendedByandTiedToSlotvalues — the friendship would vanish on your next login. The cache is now invalidated on every game side sim save, no matter which path it comes through. -
A login level bump into the level cap is now reverted like any other.
Sims already at the cap were skipped entirely during the login check, so a bump from 34 to 35 in previous versions slipped through and stuck permanently. -
Deleted sim files now stay deleted.
When the game deletes a sim's save file (sim renames, single sim resets), the mod now forgets its cached copy and cancels any pending write for that name. Previously a queued background write could quietly recreate the file from memory.
Changed
-
MaxLevelnow enforces a 1 to 35 range.
35 is the game's own maximum. Past it, the base game's ascension system takes over, which this mod deliberately leaves alone. -
Trimmed the startup log line.
1.3.0
Game Update Compatibility (2026-07-16 patch)
-
Adapted to the game's new spawn time save behavior.
The July 16th patch introduced a subtle change. Every sim now callsSaveSim()right as they spawn, before the mod has a chance to link its tracking data. This meant passive XP could be quietly reverted to older file values.
The mod'sSaveSimpatch now acts as both a Prefix and Postfix to recognize this early spawn save, keeping the tracked level authoritative throughout. It also ignores saves that the game's newVerifyLoadCompleteguard rejects. Without this, sims wandering into your zone mid session could lose pending passive XP. -
Everything else in the patch (guard AI rework, raid opinion bonus, input and options changes) doesn't touch anything this mod uses.
Fixed
-
Fixed an XP race condition on spawn.
If a passive tick landed at the exact moment a sim spawned, the mod could mistakenly pull old data from disk. Now a sim is only treated as spawned once its tracking object is fully linked. Sims that are still spawning are handled as unspawned and reconciled a frame later. -
Combat XP now triggers level ups properly.
Sims earning XP from their own kills (solo hunters or group members) would bank it without triggering a level up check. The vanilla game relied on login catchups to fix this, which this mod disables. The tick now reads a spawned sim's live XP and converts any banked surplus into the correct levels. -
Passive XP no longer overwrites combat earned XP.
Previously the passive tick would wipe out any XP a spawned sim earned from its own kills. It now adds to that total instead. A newSaveSimPostfix also copies XP back into tracking whenever the game saves. The game already did this for Level, but never for XP, which is what let the stale value creep in. -
Session resets properly on relog.
Logging out used to destroy the mod's background processes while leaving a stale flag active. When you logged back in, nothing ran until you restarted the game. Now everything resets cleanly on each login. -
Saves are flushed reliably at logout and quit.
In v1.2, queued writes only processed during loading screens. If you quit without a load screen, pending changes could vanish. Now every session exit (logout, quit, zone change, manual save, respawn) guarantees everything is written to disk first. -
Error handling for the XP tick is more robust.
If one sim had an issue, the whole tick would fail. Now it catches and logs that specific sim's error and keeps processing the rest. -
The slot 12 login bump is now handled.
The game applies a specific level bump to slot 12's sim without saving it. The mod's previous file based checks missed it. This update catches and corrects that bump just like the others.
Changed
-
Smoother, faster background saving.
Instead of a queue, the mod now tags dirty sims (those with Level or XP changes) and writes them out at a steady pace: one sim every 0.25 seconds, with level ups jumping the queue. It uses the game's native save pattern (temp file → replace → backup) but skips the hardware flush on each file, saving 10 to 30 milliseconds per save on slower drives. The tradeoff: a hard crash could lose up to one tick's worth of background XP. Quits and logouts lose nothing. -
Zero extra file reads on login.
The mod captures each sim's data directly as the game parses it during loading (CheckLoadDataandLoadFromFilePostfixes). Gone are the double reads, the directory scans, and the edge case where a leftover.tmpfile could poison the snapshot. -
Level ups save in the background.
In v1.2, leveling a sim triggered an immediate file write. Now it just marks the sim as dirty and lets the background writer handle it when ready. -
Faster XP ticks.
Since the math is lightweight, we've increased the batch size from 5 to 25 sims per frame. This makes the whole pass complete sooner without adding any noticeable overhead. -
SimPlayer.SaveSimpatch reworked.
Previously a Prefix only patch, it now reacts to what the game actually wrote instead of trying to predict it. See the game update compatibility notes for how it handles spawn time saves. -
TickIntervalSecondsnow enforces a 30 to 3600 second range.
Below 30 seconds, rounding on each tick starts inflating early level speed. There's no practical use for faster ticks anyway, since the background writer already refreshes files on its own cycle of roughly 60 seconds regardless.
Removed
DrainCoroutineand the save queue.
These have been replaced by dirty sets and the background writer._coroutinesStartedflag.
Now replaced by tracking the manager instance the coroutines run on.
1.2.0
Architecture Rewrite
-
No more IL manipulation.
The mod used to inject code directly into the game's update loop via a transpiler. That's now completely gone. No Update() hooks, no low level IL patching. This means better compatibility with other mods and less risk of breaking on game updates. -
Switched to coroutines.
Instead of running work every frame, the mod now launches three coroutines fromSimPlayerMngr.Start():XpTickCoroutine— processes XP in batches of 5 sims per frameDrainCoroutine— drains the save queue one file per frameRebuildCacheCoroutine— rebuilds the in memory state in batches of 10 sims
Fixed
-
Prevented save file corruption.
The old cache system took a snapshot of each sim at login and wrote that back later. This stripped out everything the sim gained during play: equipment, inventory, skills, guild membership, and appearance. Unspawned sims could lose all non XP progress on zone changes. The mod now uses a read-modify-write pattern. It reads the file from disk, updates only the level and XP fields, and writes it back, preserving everything else. -
Stopped the
SaveSimpatch from overwriting fresh data.
The Prefix patch used to enqueue a stale cached object after the game had already saved the correct version. This caused older data to win on a later frame. Now it only syncs the in memory state. The game's ownSaveSim()body handles the actual persistence for spawned sims. -
Swallowed errors are no longer silent.
Five emptycatch { }blocks were replaced with proper error logging. If something goes wrong, you'll see a warning in the log instead of the problem vanishing without a trace.
Added
-
SimPlayer.StartPostfix.
When an unspawned sim spawns into your zone, its stats are initially pulled from a potentially stale disk file. This patch overwrites those values with the mod's authoritative in memory Level and CurXp, then recalculates derived stats. You no longer need the disk file to be perfectly up to date for spawned sims to have the right levels. -
Null checks for scene transitions.
GameData.PlayerStatsandGameData.CurrentCharacterSlotcan be null during loading screens. The XP tick now checks for both before processing, avoiding errors when you're swapping zones. -
Safe handling for manual saves.
Unspawned sim XP now gets persisted on every zone change behind the loading screen, so you never notice. For manual saves with no loading screen, writes are deferred to the drain coroutine (one per frame) to avoid hitching the game.
Removed
-
The write only
_cachedictionary.
This cache was never actually read. It just held data that was written out. Everything that needed sim data now reads directly from tracking fields or from disk, so the dictionary is gone. -
Dead dictionary lookup in
ProcessXpForSim.
An oldTryGetValueplus field write that nothing downstream ever consumed has been removed. This saves about 200 dictionary lookups on each XP tick. -
The
CheckCache()method.
It used to poll every frame. It's now replaced by a one shot coroutine launch from theSimPlayerMngr.Start()Postfix.
Performance
-
Idle frames are now incredibly light.
On frames where no XP tick runs (over 99% of gameplay), the mod uses roughly 20 CPU instructions. That's just the coroutine scheduler and one queue count check. Down from about 4,500 instructions per frame in v1.1. -
XP ticks are faster and more even.
The old transpiler processed all 257 sims in a single frame, adding up to 24 milliseconds to the update budget. Now they're batched across about 52 frames (5 sims per frame). Each frame takes under 0.02 milliseconds with debug logging off, well below any perceivable threshold. -
Login reads cut in half.
The snapshot and cache rebuild used to read each sim file twice. Now the mod reads each file only once. The cache rebuild is spread across roughly 26 frames, so no single frame hitch. -
Zone changes stay smooth.
Unspawned sims (about 237 of them) are persisted via read-modify-write behind the loading screen. If no loading screen is active (for example, a manual save), the drain coroutine handles them one per frame to avoid stuttering.