feat: Imperial Guard Auxilia#1271
Draft
KestasV wants to merge 163 commits into
Draft
Conversation
For now to recruit them you must be above your home system, press P and type "titheguard x" (x being the number of guardsmen you want (embark guard x). Then you can deploy the guard on the planet you choose via the menu option on the planet. Feel free to test them out. Guardsmen appear in the Fleet menu near the ship name to see if the embark worked.
This reverts commit e088871.
he Guard not moving on attack. move_unit_block("east") won't move a block if another block sits directly ahead of it, so Guard spawned at the rear were permanently pinned behind the Marines, who then advanced off without them. I changed the placement so the Guard are the front rank on attack as well as defense. Now they have open ground ahead, lead the charge, and reach the enemy. Lore-wise it makes them the screening first wave, which fits expendable infantry.
Updated to latest main version
Added imperial guard recruitment button option in the planet population screen under the Colonists. Guardsmen now take from the Planet PDF instead of population, cost 50 req for 1000 guardsmen.
Guardsmen are now hierlins you can take from your planet. To spawn them in type P and "guardsman X" with the number you want. Bigger numbers crash the game, but you can spawn 50 as many times as you like.
…ning in battle Basically fixed the Gaussian stat roll so the guardsmen ALWAYS spawn with positive health, making them a bit stronger, but definitely not too strong. They're still incredibly weak when compared to the original p_guardsman implementation
Added a new Guard squad mechanic. Instead of single entities - each guard squad represents 10 guardsmen. They take damage and "lose guardsmen" per each 40hp hit. cheat is "guardsquad X" for testing (x being the number.
Limits on HQ pool size removed. You can now huge numbers of guarrdsmen without either the game freezing or crashing. Still recommending to just spawn 1000 at a time. Use cheat "guardsman 1000" to spawn them, they will appear in your HQ company and should be on your home planet.
Basically you can now filter for guard units in your ships. to add guard to your planet press P and type in "guardsman 2000" or more. Or less. Not recommended going over 10k for now, as it can slow down post battle loading and takes a minute to load them in.
…irer force if you w ant
…me guardsmen logic For now the main way to recruit them is on your homeworld by pressing P for cheats and entering "guardsman 1000" for testing. You can get even morse guardsmen, i'll test how they work in combat.
Too long to describe what's implemented. Basically made working diplomacy (Buy 1000 guards for 50 req off of sector governor) added decimal unit counts (10 guard take up 1 space marine slot) and balanced their combat and survivability. Short version, lots of changes not mentioned. Needs testing and balance now.
Basically accidentally attached their damage and new cover mechanic values to old pnunit.guard instead of the current guard. Should work now as intended. Not overpowered, not incredibly weak, doing damage, also having melee. Also fixed some values with REQ and tried to set a limit on how many guardsmen you received from the Sector Governor via diplomacy. If that doesn't work then P "guardsman X" cheat is your other option
Now they should arrive lol the last patch biffed it
Also edited some other variables, but the base is that guardsmen didn't take splash damage from single weapons before as effectively. Also edited the cover system so it doesn't roll on melee.
Added the Steel legion guardsman portrait placeholder for now (i always loved their look) will replace them with a more popular variant based on a vote most likely.
obj_star_select Draw_64 replaced Raid with Purge whenever an imperial or unowned world had any population, so an enemy force that had landed but not yet taken the world could not be raided. The imperial-held branch now offers Raid while an enemy force is present (xenos_and_heretics > 0) and returns Purge only once the world is clear of enemies and still populated. Dead worlds never register as enemy-owned, so an enemy-occupied dead world always fell into this branch, which never set Bombard (it only appeared while a live world kept the system flagged). A dead world with an enemy force and a fleet in orbit now offers Bombard; the gate is limited to planet_type == "Dead" so populated worlds with invaders still show Raid only. Display logic only; the action economy is unchanged.
…ow reduce planet disposition (upstream fix) Finish the per-ship action economy the fork started for Attack. Raid is gated per ship like an assault: it deploys troops from ships, so it now spends a ship_assault use on each contributing ship (new can_ground_deploy helper, shared 2-use ground budget with Attack) instead of the fleet-wide fleet.acted <= 1 gate. Bombard is one per ship per turn: it picks a fresh ship (get_fresh_bombard_ship) and spends its whole allowance, replacing the fleet.acted > 0 gate. Purge intentionally kept on its .acted gate. All .acted writes preserved since .acted also drives fleet movement. Epoch-keyed counters, no save-format change. scr_purge_world only changed disposition on completing an Inquisition quest (raising it +1-3); a fire or selective purge of a world with no active quest changed disposition not at all, so razing a populated world cost no loyalty. Indiscriminate fire purges now drop disposition scaled by the share of population killed (PURGE_FIRE_DISPO_PENALTY, tunable). Selective purges and assassinations stay penalty-free. Bug is upstream; relayed to Mystic and Etty.
…e; Bombardment spends per selected ship; spent ships locked in selection grid obj_p_fleet Step_0 counted ii_check down to 0 and called set_player_fleet_image once, but never reset ii_check, so the map icon frame was calculated a single time about 10 steps after the fleet was created. Fleets loaded from a save (ship counts populated by the load pass) or changed in composition during play kept that stale frame, usually the smallest, regardless of actual size. Added ii_check = 10 reset inside the trigger, mirroring obj_en_fleet Step_0, so the player fleet recomputes its icon size every 10 steps and self-corrects after loads and composition changes. Upstream obj_p_fleet Step_0 shares this omission; relayed to Adeptus Dominus; The bombard ship-selection dialog listed every bombard-capable ship with no check for whether it had already acted this turn, and its red/green was only a selected/unselected toggle. On Confirm, scr_bomb_world spent a single ship (get_fresh_bombard_ship) no matter how many were selected, so the remaining selected ships stayed fresh and could be re-selected to bombard the same world again on the next Confirm. Each Confirm applied the full selected bombard score but retired one hull, letting one fleet bombard a world several times over. obj_bomb_select now records a per-ship spent flag (ship_assaults_used > 0) when populating the list. Spent ships render locked in c_red, reject clicks, and are skipped by Select All, matching the attack roster. scr_bomb_world now spends ship_bombard_spend on every selected ship, so each ship bombards at most once per turn and a fully committed fleet cannot reopen the dialog.
obj_p_fleet Step_0 fired set_player_fleet_image() when ii_check reached 0 but never rearmed the timer, so a player fleet recomputed its map sprite size only once and never again after ii_check went negative. Because ii_check is serialized, a fleet loaded with a negative ii_check never resized and rendered as a single tiny blip regardless of its real strength (fleets saved with a positive timer self-corrected, hence the intermittency). obj_en_fleet runs the same countdown but rearms ii_check = 10, which is why enemy and imperial fleets were unaffected. Rearm ii_check and use <= 0 so a loaded fleet with a negative timer heals on the next step, then refreshes periodically like enemy fleets. Bug is upstream-verbatim; relayed to the Adeptus Dominus maintainers.
…before firing The bombard dialog gave no indication of consequences, so bombarding a small-population world to shave a point off an entrenched enemy silently wiped out its entire population (the kill is a fixed slice of population that does not scale with ship count and dwarfs a small world). The dialog now shows a live, colour-coded effect preview above Confirm: population loss and enemy losses, each bracketed None/Negligible/Low/Medium/High/Massive, updating with the ships selected and the chosen target force. Estimates live in scr_bomb_world (bombard_effect_estimate and helpers) and mirror the kill and strength_reduction math there, ignoring the sub-1 random roll and Ork Stronghold / Daemon-world specials. Runtime UI only; no new game or save change.
…illing the world Replace the flat/capped population kill with a share of the world's population CAPACITY (max population) per bombard, so repeated bombardment grinds a world down to exactly zero in a handful of strikes regardless of size, rather than a fixed figure that wiped small worlds in one shot or a share of survivors that only asymptoted. Per-strike size scales with world type, entrenched enemy size, and enemy-to-population ratio (hive worlds fall fast, agri worlds slowly). A bombard never kills more people than are present and never turns a world Dead; a depopulated world keeps its type and regrows once its enemies are cleared. The dialog preview calls the same kill function so estimate and outcome agree. Removes the fleet-Exterminatus tier, its scr_destroy_planet method, and the firepower-gate macro; the item-based Cyclonic Torpedo is unchanged. Tunable macros BOMBARD_BASE_FRACTION and BOMBARD_MAX_FRACTION; runtime logic only.
…, enemy, and defenses Population casualties were computed without the bombard score, so damage was static regardless of how many ships were selected (and showed a value at zero ships). bombard_population_kill now takes the bombard score and drives casualties from committed firepower (Battle Barge 3, Strike Cruiser 1, escorts 0) as a share of world capacity, shaped by world type (Hive high, Agri/Feudal low), enemy presence tier (larger enemy, more collateral), enemy-to-population ratio, and fortification level (each level cuts casualties, bunkers shelter civilians). Zero ships now kill nobody; a lone ship chips away while a full fleet can depopulate a world in one strike. Enemy-loss scaling is unchanged, so more ships raise both enemy and population damage. The dialog preview calls the same function, so the estimate tracks the outcome. Tunable macros; runtime logic only, no save change.
obj_star_select's draw handler (Draw_64) already stands down while the bombard dialog is open, but its click handler (Mouse_50) only guarded against the attack dialog (obj_drop_select), not obj_bomb_select. So while bombarding, clicks that missed a dialog button fell through to the star panel underneath and could hit its Exit or fleet-combat hitboxes, which set obj_controller.cooldown = 8000 (decays 1/step, about two minutes of frozen input) and ran instance_destroy or instance_deactivate_all, closing the dialog and locking the mouse. Add obj_bomb_select to the Mouse_50 guard so the panel ignores clicks while the bombard dialog is open, matching Draw_64. Runtime input only; no save change.
The GUARD_COVER_SAVE macro only lived in the dead guard==1 branch, so nothing saved live units. Wire a per-shot cover save into damage_infantry (the live path): a saved shot counts as a spent hit but deals no damage. Rate is per unit by role (guard flag is dead) - Guard auxilia GUARD_COVER_SAVE 0.4, Astartes the weaker MARINE_COVER_SAVE 0.15. Scaled by shooter distance threaded from scr_shoot through scr_clean (COVER_SAVE_FULL_RANGE, COVER_SAVE_MIN_FACTOR) so closing the range strips cover. A save posts a light-blue combat-log line. Tunable macros.
Enemy no-kill fire (wounds and armour-piercing) used eMSG_COLOR.LIGHTGREEN, the same green the player's own wounding uses, so incoming damage read as friendly. Add eMSG_COLOR.BRIGHT_RED and point enemy wound/AP lines at it so incoming damage reads in the red family; enemy bounces stay grey (WHITE), enemy kills stay the muted RED. Establishes the paradigm: green/light green for player damage, red/bright red for enemy damage, grey for saves with no effect. Also adds a BRIGHT_BLUE palette entry for future continuous-log use.
…: earn XP from battles, gate promotion on it The Hellgun had no value field, so the catalog forced forgable=false and hid it from the forge (only the Hellrifle, which has a value, was visible). Add value 8 so the Hellgun is forgeable and appears in the Armamentarium. Stays equip-gated to Veteran Guard via its veteran_guard_only tag; Skitarii still receive it only as start gear. Guardsmen now earn GUARD_BATTLE_XP (25) each ground victory they fight at and survive (basic Guardsmen on the roster at the battle location), granted in obj_ncombat Alarm_7. promote_auxilia_to_veteran now requires GUARD_VETERAN_XP (90) experience, roughly GUARD_VETERAN_XP / GUARD_BATTLE_XP survived battles, so fresh recruits cannot be promoted until they have bled for it. Both amounts are tunable macros. Add a guardxp cheat (grants enough to promote, or a passed amount) to test the gate without fighting several battles; pair with the veteranguard cheat to promote the eligible. ALSO note: the roll AT PENETRATION ROLL was added along with the addition of COVER. Just forgot to copy and paste the info onto it.
As the description. Range damage falloff is basically making the back line not do as much damage as the closer lines, adding another layer into combat tactics.
…-block drift Player blocks advanced per-block inside Alarm_0 in arbitrary instance order, so a rear block (a Rhino behind the infantry) often ran its move before the block ahead had vacated its column, failed the occupied-slot check, and drifted out of the line. Extract the advance-to-contact decision into move_player_block and drive it from set_up_player_blocks_turn via move_player_blocks, a front-first sweep that drains a priority queue highest-x first (mirroring move_enemy_blocks, which uses lowest-x for the enemy front). The frontmost block clears its column before the one behind it moves, so rear blocks keep formation. Advance-to-contact latch and order_manual leapfrog behavior unchanged; movement now resolves once per turn before fire. Files: scr_punit_combat_heplers, scr_player_combat_weapon_stacks, obj_pnunit\Alarm_0.
…d Raider 5%) The AP-based penetration chance gave high-AP weapons a higher chance, so the toughest, most expensive vehicles were the easiest to kill: the Ork Rokkit (arp 4 in scr_en_weapon, so it ignores armour and one-shots a 100 HP hull) had a high pen chance and deleted Land Raider lines. Replace it with vehicle_penetration_chance, a per-vehicle cost-tiered weak-spot chance independent of weapon AP (Land Raider 5% at value 500, up to light APCs at 45-55%). A capable shot rolls that chance; a hit still one-shots, so it reads as a rare critical. 7 Rokkits now wipe a Land Raider line effectively never. Tunable per vehicle in vehicle_penetration_chance. Files: scr_clean, macros.
…ns keep their orders Manually ordered formations that hit a friendly block ahead used to teleport over the line to the next empty column (the old leapfrog), snapping the back line to the front and tangling formations together. Replace it with a lane side-step: the block steps into a free parallel lane (PLAYER_LANE_OFFSET off the home lane at COMBAT_HOME_LANE_Y), advances past keeping its own order, and re-forms onto the home lane once its column is clear (move_player_block). Scoped to manual orders via the leapfrog flag, so the auto-advancing body is unchanged and only deliberately maneuvered formations leave the line. Never steps onto an enemy-held position. Files: macros, scr_punit_combat_heplers. Tunable lane offset.
The parallel-lane pass moved blocks off the shared line, which overlapped their icons and double-drew the Row Composition panel (garbled text). Pull it: remove the lane side-step and re-form and the COMBAT_HOME_LANE_Y / PLAYER_LANE_OFFSET macros. A block blocked by a friendly now holds for the tick; the front-first advance sweep is unchanged. Movement-through will return with the per-unit-type formation rework. Files: macros, scr_punit_combat_heplers.
… tier 4 Two upstream-endorsed fixes. HK Missile was arp 1 despite reading as a top anti- armour weapon; set arp 4 (per Mystic). Dreadnoughts carried the heavy Mount/Sponson weapon variants (shared with vehicles) and brute-forced vehicle damage, which the penetration roll now makes unnecessary. Add dread_infantry_weapon mapping the Mount/Sponson variants to their infantry versions and apply it in get_weapon_one_data / get_weapon_two_data, so a dread resolves to the infantry stats everywhere (combat, upkeep, display) including existing dreads, without rewriting saved equipment. Twin Linked Assault Cannon Mount 800 -> Assault Cannon 400; Heavy Flamer Sponsons 600 -> Heavy Flamer 500; Lascannon/Heavy Bolter already matched. Kheres Assault Cannon and Inferno Cannon have no infantry counterpart and pass through unchanged. Files: weapons.json, scr_marine_struct.
…is held OURS) Merge of the 4 upstream commits fork main was behind. Adopted: docs CODE_STYLE (Adeptus-Dominus#1305), welcome-message fold in obj_controller Create (Adeptus-Dominus#1303, untouched here), and the formation-bar collapse + for_arr->bat_for rename (Adeptus-Dominus#1304) in obj_formation_bar Create and scr_ui_formation_bars (rename self-contained, fields preserved). Kept OURS: scr_shoot (Adeptus-Dominus#1306 removes the splash multiplier from the enemy armour soak - a balance change our cover/AT/range systems sit on, held for a deliberate call), and obj_formation_bar Draw_64 (upstream Adeptus-Dominus#1304 removed the same col_parent idle reset we already fixed, so our version already covers it plus the comment).
…combat + hangar OURS) Merge of the 6 new upstream commits. Adopted: dread-tag removal from Mount/Sponson weapons (#185dbd448, the flagged follow-up) and HK arp 4 (#20ddf64a5, already matched) in weapons.json; empty all-equip text fix (#6768d3923); item-name handling; CountingMap improvement (#9afee0dff); specialist-point handler. Kept OURS: scr_shoot (Adeptus-Dominus#1306 splash/armour, held for a deliberate balance call), obj_formation_bar Draw_64 (our col_parent fix), and scr_controller_helpers (our hangar-duping fix, which is the same bug upstream's #fa129fdb9 fixes).
…nters
All three ship actions shared one per-ship counter (ship_assault_uses), and
bombardment maxed it out, so bombarding with the fleet blocked ground assaults that
turn. Generalize the counter into ship_action_used/ship_action_spend keyed by kind
("assault"/"bombard"/"raid"), each with its own obj_ini.ship_<kind>_uses/_turn
arrays (still turn-keyed, no save change). Bombard spends only its bombard counter
(get_fresh_bombard_ship and the bomb dialog's spent check read it), attack spends
assault, raid spends raid; can_ground_deploy gates raids on the raid counter, the
attack gate stays on assault, and the roster lock reads the counter matching the
open drop type. Local planetside forces still shared between attack and raid
(documented follow-up). Files: scr_player_ship_functions, obj_bomb_select Alarm_1,
scr_drop_select_function, scr_roster.
Added a link to the new release for Chapter Master 1.5.
…to the slot) Companies already grow past 500 via find_company_open_slot, but scr_move_unit_info copies a marine across a dozen parallel per-company arrays (spe/race/name/wep1/role/ wep2/gear/armour/god/age/mobi/TTRPG), and if any lagged the marine's slot (e.g. name/ TTRPG grown past the legacy 501-length scalar arrays in an older save), the copy read out of range: "Variable Index [501] out of range [501]". Add ensure_marine_slot, which pads every parallel array for a company up to a given slot with the same blank defaults find_company_open_slot uses, and call it for both companies/slots before the move. Each array pads on its own length, so in-sync arrays are untouched. Promoting, transferring, or training a marine in an over-500 company no longer crashes.
…ster testing No quick way to build a large company to test over-500 roster handling; recruit only queues training. Add "spawnmarines [count] [company]" (defaults 500 into company 1) that calls scr_add_man directly with the same default recruit role the game grants on completion (obj_ini.role[100][12]), generated names, exp 20. One summary alert at the end instead of per marine. Bundled with the recruit-cheat alert batch fix in the same file. File: scr_cheatcode.
…lind increment) transfer_marines computed the destination slot once via find_company_open_slot then did mahreens++ per marine, so with any occupied slot after the first open one (a gap before the command squad) the destination walked into it and scr_move_unit_info overwrote and wiped that marine: transferring into a company could delete its command squad. Pre-existing; the over-500 crash fix un-masked it (transfers into large companies previously threw before reaching the loop). Re-find find_company_open_slot for each marine (individual and squad paths) so each lands on a real empty slot and never overwrites an occupant; squad member records track the actual slots. File: scr_transfer_marines.
obj_mass_equip matched marines by exact role, so a squad's Sergeant (Sergeant/ Veteran Sergeant role, slots 18/19) never matched the base role being equipped and was skipped while the rest of the squad got kitted. Factor the equip logic into an apply_gear method and, per bulk-swappable squad, equip its Sergeant once with the same requirement (armour/wep1/wep2/gear/mobi). Artifact/non-standard weapons are preserved via the existing is_string/can_assign_weapon guards, so a Sergeant keeps a weapon he can't swap. Files: obj_mass_equip Create_0, Step_0.
…ced Devastators, Assault jump Formations now fight as one block per formation-editor type (all four fill paths route via formation_block; blocks sharing a column draw as stacked, individually clickable segments; manually ordered formations may merge through friendly columns, never onto enemies). On top of that, formation orders: right-click cycles a formation's firing order (nearest / first / second / third enemy line, confirmed in the combat log; ranged only, melee stays adjacent), shift+left-click orders an irreversible retreat (no firing, 80% reduced damage via RETREAT_DAMAGE_MULT, withdraws west through friendly lines and leaves the field, yellow < marker), Devastator formations on hold gain DEVASTATOR_BRACED_MULT (1.25x) ranged damage, and a personally ordered Assault formation leaps to enemy contact from up to ASSAULT_JUMP_RANGE (30, once per battle). Files: macros, scr_punit_combat_heplers, scr_roster, scr_ship_battle, scr_civil_roster, scr_shoot, scr_clean, obj_pnunit Create/Step/Alarm_0/Draw_0, obj_ncombat Create_0.
Also defines the missing add_experience method on the unit struct: the Guardsman
veterancy call sites (obj_ncombat Alarm_7 battle XP, guardxp cheat) and Techmarine
mission rewards shipped without it ever being defined, so all three crashed at
runtime ("Variable <unknown_object>.add_experience not set before reading it").
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary by cubic
Adds Imperial Guard Auxilia as recruitable, embarkable ground forces with vehicles, loadouts, portraits, and collapsed squad views, and reactivates the Eldar craftworld hunt with visible, scaling incursions and clue‑gated reveals. Tightens assault/bombard/raid rules, adds per‑block orders (with manual‑order leapfrogging and retreat), and hardens fleet movement, saves, and the combat/log system.
New Features
Guardsman/Guard Sergeant/Veteran Guardand pooled‑HPHeavy Weapons Team(0.5 berth);Guard Squadtemplate reserved;Chimera/Leman Russ/Basiliskwith default loadouts (Multi‑Laser/Heavy Bolter,Battle Cannon/Heavy Bolter,Earthshaker Cannon);Flak Armour; guardsman/sergeant and vehicle portraits; Auxilia panel and collapsed squad views (Marines too); fleet advisor shows embarked IG; Recruit/Deploy Guard actions; Guardsmen gain battle XP towardVeteran Guard;Leman Russpurchasable from the Mechanicus.Bug Fixes
Melee1works; rightmost‑column targeting corrected; overkill spill stops at air gaps; partial‑volley damage scaled; player/enemy look‑behind corrected; vehicle‑only engagement stall removed; combat log tail overwrite and casualty attribution fixed with severity/aqua colouring.Omnissian Axebuyable/forgeable; trade values and levy costs adjusted (Guardsman/Leman Russ/Basilisk); raid/assault limits enforced and blocked actions explain themselves; bombard target initializes and locks spent ships; recruit/build screen hardened; fleets/load sanitize bad positions; Auxilia vehicles persist after battles and loads; Eldar clue grants gated to full clearance and first‑contact only.Written for commit c5593c4. Summary will update on new commits.