fix: Make game time/date have a single source of truth - #1408
Conversation
There was a problem hiding this comment.
24 issues found across 33 files
Confidence score: 2/5
objects/obj_ini/Create_0.gmlinitializes 2D arrays with shared row references (array_create(11, [])) and also leavesrace[1]as a scalar, which can corrupt cross-company writes and break new chapter creation during company setup — initialize each row as an independent array before anyrace[c][i]/roster writes.scripts/scr_company_view/scr_company_view.gmlcan write a transferred unit past the destination company’s appended slot by reusing a source index, creating out-of-bounds/undefined roster state that will cascade into later turn logic — compute and use the index returned fromtarget_companyinsertion.objects/obj_p_assra/Alarm_0.gml,scripts/scr_dialogue/scr_dialogue.gml, andobjects/obj_controller/Alarm_5.gmleach contain direct undefined dereferences (unit/age, unseto, and_unit.god_statusbefore guard), so normal gameplay paths (death recovery, meeting dialogue, turn end) can hard-error — fix variable references and move undefined checks before field access.scripts/scr_world_time/scr_world_time.gmlandscripts/scr_random_event/scr_random_event.gmlinclude call-site/schema mismatches (game_yearused as a property,_unit.specialvsspecials, and bareTTRPG), which can silently break progression timing and event eligibility or throw identifier errors — align callers togame_year(), correct field names, and consistently referenceobj_ini.TTRPG.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/scr_company_view/scr_company_view.gml">
<violation number="1" location="scripts/scr_company_view/scr_company_view.gml:52">
P2: Custom agent: **Code Quality Review**
The `find_company_open_slot` function mutates persistent `obj_ini` arrays when no open slot exists, but its name implies a simple read-only lookup. Hiding array-expansion side effects inside a finder makes it easy for callers to accidentally alter game state. Consider renaming this function to something like `find_or_create_company_open_slot`, or move the expansion logic out to the caller so the side effect is explicit.</violation>
<violation number="2" location="scripts/scr_company_view/scr_company_view.gml:63">
P1: Transfers into a full destination company can use an index from the source company's `TTRPG` array, then write the unit beyond the newly appended destination slot. Derive the returned index from `target_company` so `scr_move_unit_info` targets the initialized destination slot.</violation>
</file>
<file name="objects/obj_p_assra/Alarm_0.gml">
<violation number="1" location="objects/obj_p_assra/Alarm_0.gml:21">
P1: Recovering gene-seed now errors whenever an Astartes dies with an Apothecary available: `recoverable_geneseed()` reads undefined `unit`, and its time calculation reads undefined `age`. Fix the helper to use its receiver's `gene_seed_mutations` and pass/use `marine_ascension` in `get_time_from_current_year` before invoking it here.</violation>
</file>
<file name="scripts/scr_world_time/scr_world_time.gml">
<violation number="1" location="scripts/scr_world_time/scr_world_time.gml:26">
P1: Chapter initialization and marine ascension now consume the `game_year` function itself instead of a numeric year because existing callers use property access. Update those callers to invoke `game_year()` (or preserve a numeric property API) before this handler is used.</violation>
<violation number="2" location="scripts/scr_world_time/scr_world_time.gml:26">
P2: Custom agent: **Code Quality Review**
The raw constant `1000` (years per millennium) is repeated three times in two functions without a `#macro` or `enum`. Because this is newly added code and the project already uses `#macro` extensively for numeric constants, this should be named (e.g., `#macro YEARS_PER_MILLENNIUM 1000`) to ensure a single source of truth and easier maintenance.</violation>
<violation number="3" location="scripts/scr_world_time/scr_world_time.gml:34">
P2: Crossing a year boundary drops the 8-unit overflow from the twelfth turn, making the world clock lose time every year. Preserve the remainder when rolling the year.</violation>
</file>
<file name="scripts/scr_random_event/scr_random_event.gml">
<violation number="1" location="scripts/scr_random_event/scr_random_event.gml:710">
P1: This loop reads the bare identifier `TTRPG`, but the player roster is stored on the game object as `obj_ini.TTRPG` (declared as `obj_ini.TTRPG = array_create(11, [])` in obj_ini/Create_0.gml) and there is no `globalvar`/global `TTRPG` and no local `TTRPG` in this script. When the CHAOS_INVASION event fires, `TTRPG[0]` will throw an 'undefined variable' runtime error (breaking the event). The sibling changes in scr_enemy_ai_d and scr_dialogue correctly use `obj_ini.TTRPG[0]`; this one should match.</violation>
<violation number="2" location="scripts/scr_random_event/scr_random_event.gml:712">
P1: The psyker check in the Chaos Invasion event reads `_unit.special`, but the marine struct's field is `specials` (`scr_marine_struct.gml:1052`); the removed code read the parallel `obj_ini.spe[0][i]` copy. As written, `_unit.special` is undefined, so `string_count("0", _unit.special)` won't detect a psychic chaptermaster, and this event branch's special version of "The Maw of the Warp Yawns Wide" popup can't trigger (and may throw). Replace `_unit.special` with `_unit.specials`.</violation>
</file>
<file name="scripts/scr_dialogue/scr_dialogue.gml">
<violation number="1" location="scripts/scr_dialogue/scr_dialogue.gml:182">
P1: Selecting any response that enters `cs_meeting_m1` reads an unset `o` and fails before dialogue options are built. Use the HQ company index used by this loop.</violation>
</file>
<file name="objects/obj_controller/Alarm_5.gml">
<violation number="1" location="objects/obj_controller/Alarm_5.gml:293">
P1: Turn-end processing can error after a unit is removed: `_unit.god_status` dereferences the `undefined` slot before the intended struct guard runs. Validate `_unit` before reading its fields.</violation>
</file>
<file name="scripts/scr_chapter_managent_events/scr_chapter_managent_events.gml">
<violation number="1" location="scripts/scr_chapter_managent_events/scr_chapter_managent_events.gml:276">
P1: The new empty-slot scan dereferences obj_ini.TTRPG[0][i].name() on every slot, but scr_wipe_unit stores undefined in a dead/replaced unit's TTRPG slot (e.g. the previous Forge Master whose death opens this popup). Calling .name() on undefined crashes the popup, whereas the old obj_ini.name[0][i] == "" check was safe since the name array always holds a string. Guard the access with is_struct (or keep scanning the name array) before calling .name().</violation>
</file>
<file name="scripts/scr_after_combat/scr_after_combat.gml">
<violation number="1" location="scripts/scr_after_combat/scr_after_combat.gml:306">
P2: Gene-seed recovery now uses one 80% roll for the entire unit, reducing the prior 90%-per-seed recovery rate and eliminating partial recovery for two seeds. Roll once per seed with the previous threshold to preserve recovery behavior.</violation>
</file>
<file name="scripts/scr_count_forces/scr_count_forces.gml">
<violation number="1" location="scripts/scr_count_forces/scr_count_forces.gml:16">
P2: The loop bound now equals the company's marine-array length, but the same loop also counts vehicles, and vehicle slots can extend beyond that length (veh_* arrays hold up to 205 slots per company and aren't resized with the marine count). When a company has vehicles occupying indexes >= its TTRPG array length, those vehicles silently drop out of the count, misreporting forces to the AI (scr_enemy_ai_e.gml:519) and the turn-end UI. Restore scanning up to the max of marine and vehicle lengths, guarding each sub-check by its own array length.</violation>
</file>
<file name="objects/obj_ini/Create_0.gml">
<violation number="1" location="objects/obj_ini/Create_0.gml:121">
P2: Custom agent: **Code Quality Review**
The marine array initializations repeat the raw dimension constant `11` across eight consecutive added lines instead of using the already-defined `_max_companies` constant. Using a named constant prevents drift between the array sizes and the intended capacity (e.g., vehicle arrays right above already use `_max_companies`). Consider replacing the raw `11` with `_max_companies`.</violation>
<violation number="2" location="objects/obj_ini/Create_0.gml:121">
P1: Creating a new chapter fails while initializing company 1 because `race[1]` is `501`, not an array. Initialize independent empty rows so the later `race[c][i]` assignments can grow them.</violation>
<violation number="3" location="objects/obj_ini/Create_0.gml:123">
P0: Custom agent: **Code Quality Review**
Using `array_create(11, [])` for a grid introduces shared-row references: every slot points to the same empty array. That makes two-dimensional indexing fragile and can cause writes to one company to leak into others. It also leaves each row at length 0, which breaks downstream code that indexes up to 500. Keep the explicit `array_create_2d(11, 501, "")` helper (or initialize each row independently) so each company gets its own 501-length array.</violation>
</file>
<file name="scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml">
<violation number="1" location="scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml:170">
P2: This reads `_unit.special` (singular), but the psyker-powers field on the unit struct is `specials` (plural). Since `special` is undefined, `string_count("0", undefined)` returns 0, so the 'Shadow in the Warp' popup/event-log for a psyker Chapter Master will never trigger even when the master has psyker powers. Should be `_unit.specials`.</violation>
</file>
<file name="scripts/scr_civil_roster/scr_civil_roster.gml">
<violation number="1" location="scripts/scr_civil_roster/scr_civil_roster.gml:703">
P1: `deploying_unit` is `obj_ini` (assigned at the top of this function), and `obj_ini` has its own `specials = 0` field (obj_ini/Create_0.gml:4), not a per-unit powers string. So `string_count("0", 0)` converts 0 to "0" and returns 1, meaning `chapter_master_psyker` is always set to 1 for every Chapter Master regardless of actual psyker powers. The per-unit specials now live on the fetched unit struct, so this should read `unit.specials` (as the dudes_powers line at 369 in the same change already does).</violation>
<violation number="2" location="scripts/scr_civil_roster/scr_civil_roster.gml:750">
P1: `deploying_unit` is `obj_ini`, whose `specials` field is `0` (obj_ini/Create_0.gml:4), not the unit's powers. This writes `0` to `marine_powers` for the deployed Chapter Master instead of the actual specials string. Since the per-unit powers now live on the fetched unit struct, this should read `unit.specials` to match the dudes_powers line (369) changed in the same PR.</violation>
</file>
<file name="objects/obj_controller/Mouse_50.gml">
<violation number="1" location="objects/obj_controller/Mouse_50.gml:48">
P1: The jail-detection loop can crash on dead or unassigned marines. The previous code scanned a numeric array (obj_ini.god[c]) where every index held an int, so reading god[c][e] was always safe. This version iterates obj_ini.TTRPG[c] and dereferences each entry directly (obj_ini.TTRPG[c][e].god_status) without checking that the entry is a struct. Other code paths set TTRPG slots to undefined when a marine is killed (scr_kill_unit array_set ... undefined) and when new slots are appended (scr_company_view array_push ... undefined for open slots), so the loop will hit undefined entries and raise a runtime error instead of simply skipping them. Add an is_struct guard before reading god_status, matching how scr_role_count already guards its equivalent loop.</violation>
</file>
<file name="scripts/scr_marine_struct/scr_marine_struct.gml">
<violation number="1" location="scripts/scr_marine_struct/scr_marine_struct.gml:105">
P1: Loading an existing save resets every marine's age to zero because those saves contain legacy `obj_ini.age` data, not `born`. Seed `born` from that legacy age when present before treating the new field as authoritative.</violation>
<violation number="2" location="scripts/scr_marine_struct/scr_marine_struct.gml:1052">
P2: Existing saves lose all encoded psychic-power specials after load because the replacement source is initialized to an empty string rather than migrated from legacy `obj_ini.spe`. Initialize from `spe` when it exists, then retain this per-marine field going forward.</violation>
<violation number="3" location="scripts/scr_marine_struct/scr_marine_struct.gml:2009">
P2: Existing saves clear every jailed marine's status on load because legacy `obj_ini.god` values are never copied into `god_status`. Migrate that value when the legacy array is present.</violation>
</file>
<file name="scripts/scr_controller_helpers/scr_controller_helpers.gml">
<violation number="1" location="scripts/scr_controller_helpers/scr_controller_helpers.gml:240">
P1: This jail-detection loop dereferences obj_ini.TTRPG[c][e].god_status directly and can hit undefined entries (dead marines and unassigned slots are stored as undefined in obj_ini.TTRPG), producing a runtime error instead of skipping them. The previous code read a numeric god[c][e] array where every index existed. Guard the dereference with an is_struct check, as scr_role_count does for its equivalent loop.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| race = array_create(11, 501); | ||
| /// @type {Array<Array<String>>} | ||
| name = array_create_2d(11, 501, ""); | ||
| name = array_create(11, []); |
There was a problem hiding this comment.
P0: Custom agent: Code Quality Review
Using array_create(11, []) for a grid introduces shared-row references: every slot points to the same empty array. That makes two-dimensional indexing fragile and can cause writes to one company to leak into others. It also leaves each row at length 0, which breaks downstream code that indexes up to 500. Keep the explicit array_create_2d(11, 501, "") helper (or initialize each row independently) so each company gets its own 501-length array.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At objects/obj_ini/Create_0.gml, line 123:
<comment>Using `array_create(11, [])` for a grid introduces shared-row references: every slot points to the same empty array. That makes two-dimensional indexing fragile and can cause writes to one company to leak into others. It also leaves each row at length 0, which breaks downstream code that indexes up to 500. Keep the explicit `array_create_2d(11, 501, "")` helper (or initialize each row independently) so each company gets its own 501-length array.</comment>
<file context>
@@ -118,29 +118,23 @@ veh_acc = array_create_2d(_max_companies, _max_vehicles, "");
+race = array_create(11, 501);
/// @type {Array<Array<String>>}
-name = array_create_2d(11, 501, "");
+name = array_create(11, []);
/// @type {Array<Array<String>>}
-role = array_create_2d(11, 501, "");
</file context>
| name = array_create(11, []); | |
| name = array_create_2d(11, 501, ""); |
| static specials = function() { | ||
| return obj_ini.spe[company][marine_number]; | ||
| }; | ||
| specials = ""; |
There was a problem hiding this comment.
P2: Existing saves lose all encoded psychic-power specials after load because the replacement source is initialized to an empty string rather than migrated from legacy obj_ini.spe. Initialize from spe when it exists, then retain this per-marine field going forward.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_marine_struct/scr_marine_struct.gml, line 1052:
<comment>Existing saves lose all encoded psychic-power specials after load because the replacement source is initialized to an empty string rather than migrated from legacy `obj_ini.spe`. Initialize from `spe` when it exists, then retain this per-marine field going forward.</comment>
<file context>
@@ -1048,12 +1049,10 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {}
- static specials = function() {
- return obj_ini.spe[company][marine_number];
- };
+ specials = "";
static specials_array = function() {
</file context>
| specials = ""; | |
| specials = variable_instance_exists(obj_ini, "spe") ? obj_ini.spe[company][marine_number] : ""; |
| for (var q = 0; q < array_length(obj_ini.TTRPG[0]); q++) { | ||
| var _unit = fetch_unit([0, q]); | ||
| if (_unit.role() == obj_ini.role[100][eROLE.CHAPTERMASTER]) { | ||
| if (string_count("0", _unit.special) > 0) { |
There was a problem hiding this comment.
P2: This reads _unit.special (singular), but the psyker-powers field on the unit struct is specials (plural). Since special is undefined, string_count("0", undefined) returns 0, so the 'Shadow in the Warp' popup/event-log for a psyker Chapter Master will never trigger even when the master has psyker powers. Should be _unit.specials.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml, line 170:
<comment>This reads `_unit.special` (singular), but the psyker-powers field on the unit struct is `specials` (plural). Since `special` is undefined, `string_count("0", undefined)` returns 0, so the 'Shadow in the Warp' popup/event-log for a psyker Chapter Master will never trigger even when the master has psyker powers. Should be `_unit.specials`.</comment>
<file context>
@@ -164,9 +164,10 @@ function scr_enemy_ai_d() {
+ for (var q = 0; q < array_length(obj_ini.TTRPG[0]); q++) {
+ var _unit = fetch_unit([0, q]);
+ if (_unit.role() == obj_ini.role[100][eROLE.CHAPTERMASTER]) {
+ if (string_count("0", _unit.special) > 0) {
scr_popup("Shadow in the Warp", "You are distracted and bothered by a nagging sensation in the warp. It feels as though a shadow descends upon your sector.", "shadow", "");
scr_event_log("red", "You sense a disturbance in the warp. It feels something like a massive shadow.");
</file context>
| break; | ||
| } | ||
| } | ||
| if (good == -1) { |
There was a problem hiding this comment.
P2: Custom agent: Code Quality Review
The find_company_open_slot function mutates persistent obj_ini arrays when no open slot exists, but its name implies a simple read-only lookup. Hiding array-expansion side effects inside a finder makes it easy for callers to accidentally alter game state. Consider renaming this function to something like find_or_create_company_open_slot, or move the expansion logic out to the caller so the side effect is explicit.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_company_view/scr_company_view.gml, line 52:
<comment>The `find_company_open_slot` function mutates persistent `obj_ini` arrays when no open slot exists, but its name implies a simple read-only lookup. Hiding array-expansion side effects inside a finder makes it easy for callers to accidentally alter game state. Consider renaming this function to something like `find_or_create_company_open_slot`, or move the expansion logic out to the caller so the side effect is explicit.</comment>
<file context>
@@ -49,6 +49,19 @@ function find_company_open_slot(target_company) {
break;
}
}
+ if (good == -1) {
+ good = array_length(obj_ini.name[target_company]);
+ array_push(obj_ini.race[target_company], 0);
</file context>
| return $"{check_number} {yf} {year}.M{millenium}"; | ||
| } | ||
|
|
||
| static game_year = function(){ |
There was a problem hiding this comment.
P2: Custom agent: Code Quality Review
The raw constant 1000 (years per millennium) is repeated three times in two functions without a #macro or enum. Because this is newly added code and the project already uses #macro extensively for numeric constants, this should be named (e.g., #macro YEARS_PER_MILLENNIUM 1000) to ensure a single source of truth and easier maintenance.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_world_time/scr_world_time.gml, line 26:
<comment>The raw constant `1000` (years per millennium) is repeated three times in two functions without a `#macro` or `enum`. Because this is newly added code and the project already uses `#macro` extensively for numeric constants, this should be named (e.g., `#macro YEARS_PER_MILLENNIUM 1000`) to ensure a single source of truth and easier maintenance.</comment>
<file context>
@@ -0,0 +1,45 @@
+ return $"{check_number} {yf} {year}.M{millenium}";
+ }
+
+ static game_year = function(){
+ return (millenium * 1000) + year;
+ }
</file context>
|
|
||
| /// @type {Array<Array<Real>>} | ||
| race = array_create_2d(11, 501, 0); | ||
| race = array_create(11, 501); |
There was a problem hiding this comment.
P2: Custom agent: Code Quality Review
The marine array initializations repeat the raw dimension constant 11 across eight consecutive added lines instead of using the already-defined _max_companies constant. Using a named constant prevents drift between the array sizes and the intended capacity (e.g., vehicle arrays right above already use _max_companies). Consider replacing the raw 11 with _max_companies.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At objects/obj_ini/Create_0.gml, line 121:
<comment>The marine array initializations repeat the raw dimension constant `11` across eight consecutive added lines instead of using the already-defined `_max_companies` constant. Using a named constant prevents drift between the array sizes and the intended capacity (e.g., vehicle arrays right above already use `_max_companies`). Consider replacing the raw `11` with `_max_companies`.</comment>
<file context>
@@ -118,29 +118,23 @@ veh_acc = array_create_2d(_max_companies, _max_vehicles, "");
/// @type {Array<Array<Real>>}
-race = array_create_2d(11, 501, 0);
+race = array_create(11, 501);
/// @type {Array<Array<String>>}
-name = array_create_2d(11, 501, "");
</file context>
631cba7 to
e873e26
Compare
|
/review |
|
Reviewed the actual diff ( Blockers
High
Minor
The centralization idea is sound, but the handler is wired to |
There was a problem hiding this comment.
1 issue found across 6 files (changes from recent commits).
Confidence score: 4/5
- In
scripts/scr_marine_struct/scr_marine_struct.gml, the fallbackborn = 4000introduces a conflicting timeline baseline, so units created before init can get incorrect age/year data and downstream logic drift despite the “single source of truth” intent—replace the magic number with the canonical timeline source (or defer until init is available) and document the fallback behavior.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="scripts/scr_marine_struct/scr_marine_struct.gml">
<violation number="1" location="scripts/scr_marine_struct/scr_marine_struct.gml:110">
P2: The fallback `born = 4000` is an unexplained magic number that contradicts the game's real timeline (obj_ini.millenium = 41 → game_year() ≈ 41000) and the PR's "single source of truth" goal. Any unit constructed before obj_controller exists that doesn't get born overridden (e.g. the blank + load path in obj_ini/Create_0) would carry a birth year ~37,000 years in the past, so age() (get_time_from_current_year(born)) returns an implausible value. Consider deriving the fallback from a named start-of-game constant (M41.000 = 41000) or documenting 4000, so it can't silently drift from the sector_handler's canonical time.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| if (instance_exists(obj_controller)){ | ||
| born = obj_controller.sector_handler.game_year(); | ||
| } else { | ||
| born = 4000; |
There was a problem hiding this comment.
P2: The fallback born = 4000 is an unexplained magic number that contradicts the game's real timeline (obj_ini.millenium = 41 → game_year() ≈ 41000) and the PR's "single source of truth" goal. Any unit constructed before obj_controller exists that doesn't get born overridden (e.g. the blank + load path in obj_ini/Create_0) would carry a birth year ~37,000 years in the past, so age() (get_time_from_current_year(born)) returns an implausible value. Consider deriving the fallback from a named start-of-game constant (M41.000 = 41000) or documenting 4000, so it can't silently drift from the sector_handler's canonical time.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_marine_struct/scr_marine_struct.gml, line 110:
<comment>The fallback `born = 4000` is an unexplained magic number that contradicts the game's real timeline (obj_ini.millenium = 41 → game_year() ≈ 41000) and the PR's "single source of truth" goal. Any unit constructed before obj_controller exists that doesn't get born overridden (e.g. the blank + load path in obj_ini/Create_0) would carry a birth year ~37,000 years in the past, so age() (get_time_from_current_year(born)) returns an implausible value. Consider deriving the fallback from a named start-of-game constant (M41.000 = 41000) or documenting 4000, so it can't silently drift from the sector_handler's canonical time.</comment>
<file context>
@@ -102,7 +102,13 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {}
+ if (instance_exists(obj_controller)){
+ born = obj_controller.sector_handler.game_year();
+ } else {
+ born = 4000;
+ }
</file context>
|
/review |
|
Reviewed the PR diff ( Blockers
High
Minor
Recommendation: rebase/cherry-pick the lost fixes (missing Notably, several of cubic's findings target files not in this PR ( |
There was a problem hiding this comment.
All reported issues were addressed across 17 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 5 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 3 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
0 issues found across 1 file (changes from recent commits).
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Requires human review: Auto-approval blocked by 25 unresolved issues from previous reviews.
Re-trigger cubic
Summary by cubic
Made the game time/date a single source of truth via
SectorHandler, and wired it into UI, saves, turn progression, and unit systems. Reintroduced the Doomed rule; gene‑seed recovery and ages now follow a consistent timeline.New Features
ValueShifters for Millennium/Year (locked for premade); the chosensector_handleris reused during init; intro/banner and event logs readsector_handler.date(), and end turn advances time viaincrement_date().born/marine_ascensionon spawn and for starting forces; newage()andrecoverable_geneseed()power post‑combat harvest, kill flow, armour rolls, sorting, and unit details, and respectdoomedand zygote mutations.Bug Fixes
ValueShifternow has a safe default and step-aware clamping.obj_ini.sector_handler.sector_handler.game_year()for consistent expiry.Written for commit f58fb74. Summary will update on new commits.