Skip to content

18/04

Choose a tag to compare

@Pannoniae Pannoniae released this 18 Apr 17:50
· 14 commits to master since this release
5e3bd10

REX / M2EX - 18/04

Second public release. Continues from 20/03. Tags: (RTW), (M2TW), or (RTW/M2TW).

Important: Old REX/M2EX saves still load. New saves are written in the upgraded
Extended Saves format and aren't backward-loadable in the 20/03 release.

Core Engine & Performance

  • Made RTW combat match vanilla much closer (RTW)
  • More assembly optimising on the RTW collision path. Noticeably faster, especially in large 4v4s (RTW)
  • Better non-AVX2 CPU detection on launch. You now get a messagebox instead of the game silently doing nothing (RTW/M2TW)
  • Increased the FPS a bit (RTW/M2TW)
  • Restored ~75% of game logging that was silently disabled. You've been missing out (RTW/M2TW)
  • Enabled more logging for events and sound loading to make diagnosis easier (RTW/M2TW)
  • Enabled more logging for campaign scripts (RTW)
  • Disabled mods redirecting the log file. That privilege has been revoked (M2TW)

Crashes & Stability

  • Fixed a crash when right-clicking armies (RTW/M2TW)
  • Fixed crashes with settlement religion distributions (RTW/M2TW)
  • Fixed three more crashes from broken map mods (RTW/M2TW)
  • Fixed a potential freeze with some graphics drivers (RTW/M2TW)
  • Fixed a crash exiting to menu with an active papal settlement mission referencing corrupt data (M2TW)
  • Fixed a crash in AI resource evaluation when a tracked army or character was destroyed mid-turn (RTW/M2TW)
  • Fixed a crash with maps having coordinates greater than 32768 (RTW/M2TW)
  • Fixed a sound-pack-related crash with mods (RTW/M2TW)
  • Fixed a save loading issue for new saves related to the random number generation (RTW/M2TW)
  • Fixed a crash from mods with invalid faction setups (RTW/M2TW)
  • Fixed a crash from invalid EDU entries (RTW/M2TW)
  • Fixed a crash in Invasio Barbarorum: Ruina Romae with invalid traits (RTW/M2TW)
  • Fixed a crash with the kill_army console command (RTW/M2TW)
  • Fixed a crash with mods (Hyrule: Total War, Warcraft: Total War, etc.) whose elephants/monsters lack bone_E_platform. Used to corrupt memory, now falls back to bone 0. Thanks @fynn (RTW/M2TW)
  • Fixed a crash from invalid setting values in preference files. Stop editing them into crashing, you know who you are (RTW/M2TW)
  • Tightened keyboard-shortcut logic so you're less likely to crash from a missing/empty shortcuts screen (RTW/M2TW)

Save System: Extended Saves

  • Extended Saves: complete overhaul of the save format. Old 32-bit pointer collision bug eliminated. Large mods could silently corrupt saves once RAM use crossed 2 GB. Now writes full 64-bit pointer references. Old saves still load normally; new saves use the upgraded format automatically (RTW/M2TW)
  • Added class-based collision protection to the legacy save pointers, so old saves that previously corrupted should now load correctly in most cases (RTW/M2TW)

Camera & Controls

Camera

  • Fixed the camera being stuck with scripted/cinematic cameras in historical battles (RTW/M2TW)
  • Added a descr_ex option to adjust the minimum/maximum camera zoom (RTW/M2TW)
  • Edge pan rotate option ported to M2TW (edge_pan_rotate = 1 in preferences.txt, also in the in-game UI options tab) (M2TW)
  • Moved the edge pan/rotate setting into the game options alongside the rest of the camera options (M2TW)
  • Made the stratmap movement radius display crisper (RTW/M2TW)
  • Fixed the stratmap movement radius randomly cutting off halfway through movement when distances are too large in modded games (RTW/M2TW)

Cursor & Input

  • Fixed the cursor flicker (RTW/M2TW)
  • Fixed up windowed mode on RTW: no cursor desync, doesn't trap the cursor in the window, doesn't clip the bottom of the screen, plus misc. fixes (RTW)
  • More cursor fixes: a weird double-cursor scenario, the titlebar lacking a Windows cursor, and the RTW windowed cursor still being trapped (RTW/M2TW)

Selection & Run Preferences

  • Holding Alt while selecting deselects units. Works for both drag-select and individual select (RTW)
  • Left-click can deselect units. Toggle in preferences.txt: MOUSE_DESELECT = TRUE (RTW)
  • Unit groups now respect RP_ALWAYS / RP_ON_DRAG and no longer use the weird queue order system (RTW)
  • Ctrl modifier on grouped units now makes everyone walk, with slower units running to match a set velocity (RTW)
  • Removed queued orders from groups (it was the worst feature ever) (RTW)
  • Ctrl modifier support added for RP_ALWAYS so units walk while held. Applies to grouped and non-grouped units (RTW)
  • Alt-rotate (order rotate) now respects RP_ALWAYS / always-run (RTW)
  • Unit cards can be repositioned without needing groups, while respecting unit-card ordering. Multi-card movement not yet (RTW)
  • Added shift-scrolling to the campaign map. Same behaviour as the battlemap (RTW/M2TW)
  • Fixed not being able to Ctrl+select units (RTW)

Battle

Combat & AI

  • Fixed the battle AI not knowing what a hill is (RTW/M2TW)
  • Another round of pike fixes. This time without the "snapping" down (RTW/M2TW, mostly Med)
  • Fixed spearmen/pikemen not being able to properly climb ladders (RTW/M2TW)
  • Fixed ~6 overlapping bugs with precursor javelins. EB and other ancient-themed mods should rest more easily now (M2TW)
  • Made the area attribute compatible with melee attacks (1.75 m radius, not yet configurable). Use as: stat_pri_attr ap, area (RTW/M2TW)
  • Added is_knockdown_immune attribute, preventing units from being knocked down in melee (RTW/M2TW)
  • Added Immune to Psychology attribute. Units no longer take morale penalties from nearby fear effects (RTW/M2TW)

Strat Map

  • Overhauled the radar map (RTW/M2TW)
  • Uncapped the tree vertex limit on the strat map. Thanks @Mylae (RTW/M2TW)
  • Fixed the last letter of the last region's name being cut off in the campaign-map label (RTW/M2TW)
  • Universal drag-and-drop: drag-and-drop your units anywhere between RTW and M2TW, on stratmap and battlemap. Truly everywhere (RTW/M2TW)
  • Fixed AI armies always teleporting during end-of-turn movements, causing the "teleporting" units and stutter (RTW)

Graphics & Rendering

  • Upgraded the game's HLSL shaders to Shader Model 3.0. First step in modernising the graphics (RTW/M2TW)
  • Increased the grass distance on extreme settings. Previously it only worked for trees (RTW/M2TW)
  • Fixed the white flash at the start of campaigns/battles (RTW/M2TW)
  • Fixed both vegetation generation and sprite generation so they require zero hacks (no more 16-bit/1024x768/no-AA/special preferences). Just run the game and it works (RTW/M2TW)
  • Verified proper two-faced texture support across both games (RTW/M2TW)
  • Made missing layout TGAs no longer crash the vegetation DB (RTW)
  • Fixed some effects not being displayed (RTW)

Sound

  • Fixed the "sound bug" (mods having no sound) (RTW/M2TW)
  • No more "writing the sound pack out" on startup. It was hilariously unsafe and caused random file corruption (whole-install-screwing kind). To regenerate sound packs, launch with --debug.snd_save_events (RTW/M2TW)
  • Animation packs are now also gated behind --debug.snd_save_events. Same flag for both, no more accidental install corruption (RTW/M2TW)
  • Fixed a sound loading problem (RTW/M2TW)
  • Fixed a bug with custom music / audio. Thanks @majestic Steerve (RTW/M2TW)

Localisation, Fonts & Text

  • Completely overhauled the localisation system. The game now ships localisation for all languages simultaneously and switches natively. Drop files into data/text/english/.txt, data/text/russian/.txt, or any other Steam-supported language and the correct one loads automatically. Mods that don't do this still work (assumed English). Unknown keys fall back to English. Mods can also localise M2EX strings into their language. Future: in-game language switcher (RTW/M2TW)
  • Added UTF-8 support for stringtables. No more UTF-16 LE bullshit (RTW/M2TW)
  • More UTF-8 fixes for mods with Unicode city names and characters (RTW/M2TW)
  • Fixed fonts not rendering on other alphabets (Ukrainian, Russian, etc.) (RTW/M2TW)
  • Fixed an instance of missing text in the escape menu (RTW)
  • Fixed rebel unit details in the escape menu (M2TW)
  • Fixed the savegame list text overflowing the listbox in the Load Game menu (RTW/M2TW)

Launcher & Game Folder

  • Collapsed the three RTW exes into one. Added shortcuts for launching RTW/BI/ALX and the four Kingdoms expansions from the game folder (RTW/M2TW)
  • Modders: the exe takes -bi and -alx flags for expansion behaviour. Couldn't be folded into -mod because mods rely on being installed under BI/ALX

Modding: descr_ex (gameplay toggles)

  • hide_age: hides character age from the UI (name panels, faction scroll, family tree tooltips). Your elves no longer die of old age at 55. Thanks @majestic Steerve (RTW/M2TW)
  • hide_upgrade_pop: hides the "population required for next level" text in the settlement panel (RTW/M2TW)
  • disable_console: blocks the player from opening RomeShell/MedievalShell. Script console_command still works (RTW/M2TW)
  • population_on_disband: set false and disbanding units no longer adds population back to the settlement (RTW/M2TW)
  • bribe_armies: set false to prevent diplomats from bribing armies (RTW/M2TW)
  • bribe_settlements: set false to prevent diplomats from bribing settlements (RTW/M2TW)
  • bribe_cost_army : multiplier on army bribe costs (RTW/M2TW)
  • bribe_cost_settlement : multiplier on settlement bribe costs (RTW/M2TW)
  • horde_initial_xp: horde units can spawn with experience (0-9) (RTW/M2TW)
  • horde_initial_armor: horde units can spawn with armour upgrades (0-3) (RTW/M2TW)
  • horde_initial_weapon: horde units can spawn with weapon upgrades (0-3) (RTW/M2TW)
  • easy_nightfight: any general can attempt a night attack regardless of traits (RTW/M2TW)
  • Added a descr_ex option to adjust the minimum/maximum camera zoom (also listed under Camera) (RTW/M2TW)

Modding: descr_caps_ex (engine toggles)

  • New flag to load vegetation from descr_vegetation.txt instead of the binary .db (M2TW)
  • New flag to load descr_items.txt instead of the items DB (RTW/M2TW)
  • New flag to load text descr_model_battle.txt instead of the binary battle_models.modelDB (M2TW)
  • New flag to control whether your mod adds to or overwrites vanilla portraits. Default is overwrite, so mods adding a single portrait no longer have to duplicate the entire folder to keep vanilla intact (RTW/M2TW)

Modding: Data & Tools

  • Added --util.decompile_vegetation to dump the vegetation DB to text (M2TW)
  • Added --util.modeldb_decompile. Got a battle_models.modelDB made by IWTE? You can convert it back to actual text now :P (M2TW)
  • Added .cas support for battlefield meshes. Single-variation only, but useful when you don't need variations (M2TW)
  • Added retrain_pool EDB keyword (M2TW) / retrain EDB keyword (RTW). Like recruit_pool / recruit but the unit can only be retrained, not freshly recruited. If both recruit_pool and retrain_pool exist for the same unit, recruitment is allowed
  • Removed all hardcoded limits on trigger effects. Previously a single trigger could only affect 10 traits, 5 advice threads, 20 guild scores, and 10 faction-standing modifiers. Now unlimited, e.g. a crown ancillary trigger can grant arbitrarily many traits (RTW/M2TW)
  • Removed hardcoded limits on trait levels (was 10) and anti-traits (was 20). Now unlimited (RTW/M2TW)
  • Fixed an anti-trait bug: overflow points were calculated before NoGoingBackLevel had a chance to clamp the trait, so even traits protected by NoGoingBackLevel got removed and replaced by the anti-trait (RTW/M2TW)
  • Fixed another anti-trait bug in RTW: NoGoingBackLevel fired on every anti-trait check even for traits that didn't use it, stripping all positive levels (RTW)
  • Fixed trait stat effects leaking when traits were removed. In RTW the leak hit every removal path; in M2TW only the anti-trait removal path. Both fixed, no more ghost stats accumulating across a campaign <3 (RTW/M2TW)
  • Fixed the faction-leader status not being recorded on character death, which could affect succession and related scripts (RTW/M2TW)
  • Fixed faction unlocking when you defeat a faction under specific circumstances (RTW/M2TW)
  • Fixed custom portraits using the portrait file in place of the card image. Cards now correctly load card_.tga, with fallback to portrait_.tga for mods that ship only one set (RTW)
  • Fixed custom vegetation not loading from mod folders. Vegetation distribution maps now correctly resolve from the mod folder (RTW/M2TW)
  • Fixed horde bodyguard units not receiving XP / armour / weapon upgrades from descr_ex. horde_initial_xp/armor/weapon now apply to the general's bodyguard too (RTW/M2TW)
  • Fixed retraining experienced units losing their chevrons. The retrain queue's frozen XP was silently overwritten to the settlement's training level, dropping any experience above it. LoTW doesn't have to juggle the queue anymore :D (RTW)
  • Fixed cancelling recruitment with population_on_disband = false not actually returning your soldiers to the city (RTW)
  • Fixed coordinates moving the character to the wrong place in move_character (RTW/M2TW)

Scripting: Engine

  • Replaced the script event-context system with a proper scope stack. if/while conditions inside monitor_event bodies now correctly see the triggering event's context on every tick, not just the first. Fixes a vanilla bug where multi-tick monitor bodies lost track of which faction/settlement/character triggered them (RTW/M2TW)
  • RTW's monitor_event now supports multi-tick body execution. Previously a while loop inside a monitor_event would freeze until the same event fired again (RTW)
  • while loops now execute instantly instead of yielding between iterations. A 100-iteration counter loop used to take ~100 game ticks; now it completes in one. Hard cap of 1,000,000 iterations per tick with a warning, to catch infinite loops without deadlocking the game. Every script-heavy mod just got faster for free (RTW/M2TW)
  • Added while_yield. The old while behaviour for scripts that intentionally want one iteration per game tick (RTW/M2TW)
  • Added the local keyword for script commands. Pass local instead of a settlement/faction/character name and it reads from the current event context (RTW/M2TW)

Scripting: Control Flow

  • Added for_each. What else would you use local for? Iterates over factions, settlements (in a faction), or characters (in a faction) (RTW/M2TW)

    Example:

    for_each faction
    ; local = current faction
    end_for

    for_each settlement in england
    ; local = current settlement
    end_for

    for_each character in local
    ; local = current character
    end_for

  • Added break. Exits the innermost while or for_each. Punches through nested if blocks (RTW/M2TW)

  • Added return. Exits the current monitor body. Monitor stays alive and keeps listening for future events. At top level (outside any monitor) it kills the script entirely, same as terminate_script. WARNING: that's permanent in that savegame, no more campaign scripting after that (RTW/M2TW)

  • Added goto and set_label. Best and worst commands ever. Jumps both forwards and backwards, exits nested scopes. For normal modders: an escape hatch. For the nerds: "can it run Doom" tier (RTW/M2TW)

  • Added include_script. Inlines an external script file at the include point, like a C++ #include. Useful for sharing logic across scripts and for splitting up THOSE 20K-LINE SCRIPTS AAAA (RTW/M2TW)

Scripting: Counters & Math

  • Added add_counter. Totally not just inc_counter renamed (RTW/M2TW)
  • Added sub_counter (RTW/M2TW)
  • Added mul_counter (RTW/M2TW)
  • Added div_counter. Division by zero warns and returns 0 (RTW/M2TW)
  • Added mod_counter (RTW/M2TW)
  • Added min_counter and max_counter (RTW/M2TW)
  • Added abs_counter (RTW/M2TW)
  • Added clamp_counter (RTW/M2TW)
  • set_counter and inc_counter now accept counter names as well as literal values. set_counter gold income copies income into gold (RTW/M2TW)
  • I_CompareCounter now accepts counter names on the right side. I_CompareCounter gold > expenses finally works (RTW/M2TW)

Scripting: get_counter

Added get_counter <counter_name> [optional_arg]. Pulls live game state into a counter so scripts can read it directly. Works with scope context (monitor_event, for_each, etc.) or with an explicit entity name. Unknown keys log an error, no silent zero from typos (RTW/M2TW)

Example:

get_counter my_pop population ; from scope context
get_counter my_gold treasury england ; from a specific faction
get_counter my_cmd trait GoodCommander ; parameterised

Settlement keys (pass settlement name as optional arg, or rely on scope):

  • population: raw population count (RTW/M2TW)
  • population_pct: population as % of max (RTW/M2TW)
  • tax_level: current tax level as integer (RTW/M2TW)
  • loyalty: settlement loyalty level (RTW/M2TW)
  • riot_risk: chance of riots, 0-40 (RTW/M2TW)
  • health: public health level (RTW/M2TW)
  • besieged: 1 if under siege, else 0 (RTW/M2TW)
  • rioting: 1 if currently rioting, else 0 (RTW/M2TW)
  • plague: 1 if plague-stricken, else 0 (RTW/M2TW)
  • castle: 1 if castle, 0 if city (M2TW only, RTW has no castles)
  • garrisoned: 1 if a garrison is present, else 0 (RTW/M2TW)
  • garrison_units: number of units in the garrison (RTW/M2TW)
  • garrison_soldiers: total soldiers across garrison units (RTW/M2TW)

Faction keys (pass faction name, or rely on scope):

  • treasury: denarii in treasury (RTW/M2TW)
  • income: net income last turn (RTW/M2TW)
  • num_settlements: settlements owned (RTW/M2TW)
  • num_characters: characters on the map (RTW/M2TW)
  • settlements_taken: total settlements conquered this campaign (RTW/M2TW)
  • battles_fought (RTW/M2TW)
  • battles_won (RTW/M2TW)
  • battles_lost (RTW/M2TW)
  • def_sieges_fought (RTW/M2TW)
  • def_sieges_won (RTW/M2TW)
  • off_sieges_fought (RTW/M2TW)
  • off_sieges_won (RTW/M2TW)
  • score: overall faction score (RTW/M2TW)
  • score_rank: rank among all factions (M2TW)
  • median_tax: median tax level across all settlements (RTW/M2TW)
  • mode_tax: most common tax level across all settlements (RTW/M2TW)

Character keys:

  • age (RTW/M2TW)
  • command (RTW/M2TW)
  • influence (RTW/M2TW)
  • management: including hidden modifiers (RTW/M2TW)
  • subterfuge (RTW/M2TW)
  • turns_idle: turns the character has been doing nothing (M2TW)
  • movement_pct: movement points remaining this turn, 0-100 (RTW/M2TW)
  • num_traits (RTW/M2TW)
  • num_ancillaries (RTW/M2TW)
  • army_size: total soldiers in the character's army (RTW/M2TW)
  • army_units: number of units in the character's army (RTW/M2TW)

Parameterised keys:

  • trait : raw point value for a specific trait, 0 if not held (RTW/M2TW)
  • attribute : any attribute by name, including hidden ones like Management or Piety (RTW/M2TW)
  • score_type : faction score by category: military, production, or regions (M2TW)

Global keys (no context needed):

  • turn: current turn number (RTW/M2TW)
  • year: current campaign year (RTW/M2TW)
  • num_factions: factions still alive (RTW/M2TW)
  • random: random number 0-100, stored in the counter so the same roll can drive multiple comparisons (RTW/M2TW)

Scripting: Conditions

  • CityPopulation, e.g. CityPopulation > 2000 (RTW/M2TW)
  • HasAncillary , e.g. HasAncillary gladiator (RTW/M2TW)
  • AncillaryObtained : tests whether the ancillary just acquired matches. Use with AcquiredAncillary (RTW/M2TW)
  • IsAlly (RTW/M2TW)
  • IsAtWar (RTW/M2TW)
  • IsProtectorate : trigger faction is a protectorate/vassal of the named faction (RTW/M2TW)
  • IsProtector : reverse of IsProtectorate (RTW/M2TW)
  • I_SettlementLevel: comparison operator on a settlement's level. Supports village, town, large_town, city, large_city, huge_city, plus the castle tiers (M2TW) (RTW/M2TW)
  • I_SettlementOwnerCulture: culture of the settlement's owning faction (RTW/M2TW)
  • LangIs : current runtime language. Mods can branch on the player's language. Supports english, french, german, italian, spanish, polish, russian, czech, hungarian, etc. (RTW/M2TW)
  • I_BattleFinished: battle has fully finished (post-results screen) (RTW/M2TW)
  • I_BattleEnd: battle is in its end phase (routing/cleanup) (RTW/M2TW)
  • I_BattleEndPending: battle is about to end (one side breaking but not fully routed) (RTW/M2TW)
  • I_CharacterNameNearTile : checks if a named character is within a tile distance. Searches all factions. e.g. I_CharacterNameNearTile Henry 10 48 30 (RTW/M2TW)
  • HasResource : trade resource present in a region (RTW/M2TW)
  • HasHiddenResource : hidden resource present in a region (RTW/M2TW)

Scripting: Commands

  • adjust_treasury opt:faction_type : sets a faction's treasury to a percentage of itself (1.05 = 105%). Defaults to player faction (RTW/M2TW)
  • add_soldiers <character|settlement_name> <unit_type> (RTW/M2TW)
  • downgrade_building <settlement_name> <building_level_id>: drops a building one level, destroys it if at level 0 (RTW/M2TW)
  • remove_ancillary (RTW/M2TW)
  • change_character_faction : transfers a character to another faction. Brings their army with them (RTW/M2TW)
  • set_heir (RTW/M2TW)
  • set_leader (RTW/M2TW)
  • kill_army : kills an army and its commanding character in one go. No more kill_character then wait three business days for the leaderless army to sort itself out (RTW/M2TW)
  • go_to_capital : moves the strat-map camera to a faction's capital (RTW/M2TW)
  • go_to_sett : moves the strat-map camera to any settlement by name (RTW/M2TW)
  • go_to_char : moves the strat-map camera to any character by name (RTW/M2TW)
  • go_to_pos : moves the strat-map camera to specific coordinates (RTW/M2TW)
  • vulnerable_general: reverse of invulnerable_general. Battle-only (RTW/M2TW)
  • add_hidden_resource : adds a hidden resource to a region at runtime, e.g. add_hidden_resource London gold (RTW/M2TW)
  • remove_hidden_resource (RTW/M2TW)

Scripting: Monitors

  • NewTurnStart: fires once per campaign turn, globally. Unlike FactionTurnStart which fires per faction, this fires exactly once when the turn counter increments. Useful for once-per-round logic (RTW/M2TW)
  • FactionDestroyed: fires when a faction is eliminated. Exports the dying faction (RTW/M2TW)

Console Commands

  • create_assassin : spawns an assassin at a settlement of the targeted faction (RTW/M2TW)
  • create_spy (RTW/M2TW)
  • create_diplomat (RTW/M2TW)
  • create_merchant (M2TW)
  • show_counter : prints a counter's value in-game (RTW/M2TW)
  • show_counters: dumps every counter for debugging (RTW/M2TW)