feat: Lightning Warriors and a boatload of stuff#1283
feat: Lightning Warriors and a boatload of stuff#1283CptMacTavish2224 wants to merge 50 commits into
Conversation
…mit-relate changes
There was a problem hiding this comment.
24 issues found across 47 files
Confidence score: 2/5
- The riskiest issue is data integrity in
datafiles/main/squads/base_squads.json,datafiles/main/chapters/template.JSON, anddatafiles/main/chapters/34.json: invalid JSON comments, malformed key names, and duplicate keys can break parsing or silently load wrong values at startup/content load — fix these files and run a full JSON/schema validation pass before merging. datafiles/main/squads/equal_spescout.jsonappears to regress 10th company composition from a unique scout+tactical setup to effectively command+single devastator, which can materially alter roster generation and campaign balance for users — restore intended company-10 squads and verify generated company totals in-game before merge.- In
scripts/scr_UnitGroup/scr_UnitGroup.gml, sergeant selection/promotion can happen before slot viability checks, so wrong-role marines may be promoted and state can drift even when squad creation fails — reorder the flow to validate squad/slot first, then mutate role/traits, and add a targeted regression test for failed creation paths. - There are multiple runtime edge-case risks in
objects/obj_ncombat/Alarm_3.gml,scripts/scr_initialize_custom/scr_initialize_custom.gml, andscripts/scr_shoot/scr_shoot.gml(combat log drain stall, scout bank overdraft/override check mismatch, and zero-HP division path), which together increase odds of hard-to-reproduce gameplay bugs — add guards for bounds/zero-HP, align instance-variable checks, and smoke-test long combats plus custom initialization before merging.
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
2 issues found across 18 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
7 issues found across 47 files
Confidence score: 2/5
scripts/scr_squads/scr_squads.gmldetects invalid squad types but still dereferences the bad key, which can hard-crash squad setup flows for players. Return early (or otherwise stop execution) as soon as a squad type is invalid before merging.scripts/scr_shoot/scr_shoot.gmlcan enter spill damage on ranks with nonpositive HP, creating divide-by-zero/negative-HP behavior and targeting ranks normal alive-rank logic would skip; it also spends Speed Force ammo before confirming there are valid targets. Skip zombie ranks before spill math and move ammo consumption after_total > 0is confirmed.- Formation/state consistency is at risk across
objects/obj_pnunit/Alarm_0.gml,scripts/scr_company_order/scr_company_order.gml, andobjects/obj_controller/Create_0.gml: the 30-rank empty-column scan can delete still-live formations, company 0 can be reorganized by 1-based defaults, and bike placements can stay stale after reset. Reusedestroy_empty_column, guard company 0 in default squad application, and includebat_bike_forin reset paths to keep combat layouts stable. scripts/scr_squads/scr_squads.gmlstores company override entries by reference, so editing a live arrangement can mutate the override template and cause hard-to-reproduce future layout drift. Store/copy overrides by value to isolate templates from runtime edits before merge.
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="objects/obj_controller/Create_0.gml">
<violation number="1" location="objects/obj_controller/Create_0.gml:830">
P2: Add bat_bike_for to the formation reset path. Otherwise resetting/customizing battle formations leaves bikes using stale placement while every other unit type returns to defaults.</violation>
</file>
<file name="objects/obj_pnunit/Alarm_0.gml">
<violation number="1" location="objects/obj_pnunit/Alarm_0.gml:291">
P2: Do not duplicate the empty-column scan with a 30-rank limit; it can destroy formations that still have live ranks beyond slot 30. Reuse `destroy_empty_column` so cleanup matches the rest of combat.</violation>
</file>
<file name="scripts/scr_shoot/scr_shoot.gml">
<violation number="1" location="scripts/scr_shoot/scr_shoot.gml:286">
P2: Also skip zombie ranks with nonpositive HP before entering the spill loop. Otherwise the new damage calculation can divide by zero/negative HP or keep firing at a rank that `find_next_alive_rank` would never consider alive.</violation>
<violation number="2" location="scripts/scr_shoot/scr_shoot.gml:473">
P2: Move Speed Force ammo consumption until after confirming `_total > 0`. Current ordering can consume ammo on an empty battlefield.</violation>
</file>
<file name="scripts/scr_company_order/scr_company_order.gml">
<violation number="1" location="scripts/scr_company_order/scr_company_order.gml:73">
P2: Guard company 0 before applying default_squads; otherwise the chapter/HQ company can be reorganized into normal bike/tactical templates even though arrangements are 1-based.</violation>
</file>
<file name="scripts/scr_squads/scr_squads.gml">
<violation number="1" location="scripts/scr_squads/scr_squads.gml:381">
P2: Invalid squad types are detected but not stopped; function still dereferences the invalid key and can crash.</violation>
<violation number="2" location="scripts/scr_squads/scr_squads.gml:925">
P2: Company override entries are stored by reference, so editing live arrangement can mutate override templates unexpectedly.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| bat_formation_type = array_create(_count, 0); | ||
| bat_deva_for = array_create(_count, 1); | ||
| bat_assa_for = array_create(_count, 4); | ||
| bat_bike_for = array_create(_count, 4); |
There was a problem hiding this comment.
P2: Add bat_bike_for to the formation reset path. Otherwise resetting/customizing battle formations leaves bikes using stale placement while every other unit type returns to defaults.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At objects/obj_controller/Create_0.gml, line 830:
<comment>Add bat_bike_for to the formation reset path. Otherwise resetting/customizing battle formations leaves bikes using stale placement while every other unit type returns to defaults.</comment>
<file context>
@@ -827,6 +827,7 @@ bat_formation = array_create(_count, "");
bat_formation_type = array_create(_count, 0);
bat_deva_for = array_create(_count, 1);
bat_assa_for = array_create(_count, 4);
+bat_bike_for = array_create(_count, 4);
bat_tact_for = array_create(_count, 2);
bat_vete_for = array_create(_count, 2);
</file context>
| with (obj_enunit) { | ||
| var _alive = 0; | ||
| for (var _rr = 1; _rr <= 30; _rr++) { | ||
| if (dudes_num[_rr] > 0 && dudes_hp[_rr] > 0) { | ||
| _alive += dudes_num[_rr]; | ||
| } | ||
| } | ||
| if ((_alive == 0) && (owner != 1)) { | ||
| instance_destroy(); | ||
| } | ||
| } |
There was a problem hiding this comment.
P2: Do not duplicate the empty-column scan with a 30-rank limit; it can destroy formations that still have live ranks beyond slot 30. Reuse destroy_empty_column so cleanup matches the rest of combat.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At objects/obj_pnunit/Alarm_0.gml, line 291:
<comment>Do not duplicate the empty-column scan with a 30-rank limit; it can destroy formations that still have live ranks beyond slot 30. Reuse `destroy_empty_column` so cleanup matches the rest of combat.</comment>
<file context>
@@ -244,17 +268,49 @@ try {
+ // Safety net: drop empty/zombie formations the firing loop never reached, so a lingering corpse
+ // can't keep the battle alive.
+ with (obj_enunit) {
+ var _alive = 0;
+ for (var _rr = 1; _rr <= 30; _rr++) {
</file context>
| with (obj_enunit) { | |
| var _alive = 0; | |
| for (var _rr = 1; _rr <= 30; _rr++) { | |
| if (dudes_num[_rr] > 0 && dudes_hp[_rr] > 0) { | |
| _alive += dudes_num[_rr]; | |
| } | |
| } | |
| if ((_alive == 0) && (owner != 1)) { | |
| instance_destroy(); | |
| } | |
| } | |
| with (obj_enunit) { | |
| destroy_empty_column(id); | |
| } |
| var _dpw = att[weapon_index_position] / _shots; // per-bike damage | ||
| var _mod = max(1, splash[weapon_index_position]); | ||
| if (ammo[weapon_index_position] > 0) { | ||
| ammo[weapon_index_position] -= 1; |
There was a problem hiding this comment.
P2: Move Speed Force ammo consumption until after confirming _total > 0. Current ordering can consume ammo on an empty battlefield.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_shoot/scr_shoot.gml, line 473:
<comment>Move Speed Force ammo consumption until after confirming `_total > 0`. Current ordering can consume ammo on an empty battlefield.</comment>
<file context>
@@ -254,258 +246,327 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat
+ var _dpw = att[weapon_index_position] / _shots; // per-bike damage
+ var _mod = max(1, splash[weapon_index_position]);
+ if (ammo[weapon_index_position] > 0) {
+ ammo[weapon_index_position] -= 1;
+ }
</file context>
| if (!instance_exists(target_object)) { | ||
| exit; | ||
| } | ||
| if (target_object.dudes_num[target_type] <= 0) { |
There was a problem hiding this comment.
P2: Also skip zombie ranks with nonpositive HP before entering the spill loop. Otherwise the new damage calculation can divide by zero/negative HP or keep firing at a rank that find_next_alive_rank would never consider alive.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_shoot/scr_shoot.gml, line 286:
<comment>Also skip zombie ranks with nonpositive HP before entering the spill loop. Otherwise the new damage calculation can divide by zero/negative HP or keep firing at a rank that `find_next_alive_rank` would never consider alive.</comment>
<file context>
@@ -254,258 +246,327 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat
+ if (!instance_exists(target_object)) {
+ exit;
+ }
+ if (target_object.dudes_num[target_type] <= 0) {
+ var _alive_rank = find_next_alive_rank(target_object, -1);
+ if (_alive_rank == -1) {
</file context>
| if (target_object.dudes_num[target_type] <= 0) { | |
| if (target_object.dudes_num[target_type] <= 0 || target_object.dudes_hp[target_type] <= 0) { |
| } | ||
| } | ||
| if (_data_match) { | ||
| var _data = resolve_company_arrangement(obj_ini.chapter_squad_arrangement, co); |
There was a problem hiding this comment.
P2: Guard company 0 before applying default_squads; otherwise the chapter/HQ company can be reorganized into normal bike/tactical templates even though arrangements are 1-based.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_company_order/scr_company_order.gml, line 73:
<comment>Guard company 0 before applying default_squads; otherwise the chapter/HQ company can be reorganized into normal bike/tactical templates even though arrangements are 1-based.</comment>
<file context>
@@ -70,18 +70,8 @@ function scr_company_order(company) {
- }
- }
- if (_data_match) {
+ var _data = resolve_company_arrangement(obj_ini.chapter_squad_arrangement, co);
+ if (_data != undefined) {
_squadless.organise_by_template(_data, _squad_index, _empty_index, false);
</file context>
| var _data = resolve_company_arrangement(obj_ini.chapter_squad_arrangement, co); | |
| var _data = (co > 0) ? resolve_company_arrangement(obj_ini.chapter_squad_arrangement, co) : undefined; |
| var _found = false; | ||
| for (var ai = 0; ai < array_length(arrangement.companies); ai++) { | ||
| if (arrangement.companies[ai].company == _ovr.company) { | ||
| arrangement.companies[ai] = _ovr; |
There was a problem hiding this comment.
P2: Company override entries are stored by reference, so editing live arrangement can mutate override templates unexpectedly.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_squads/scr_squads.gml, line 925:
<comment>Company override entries are stored by reference, so editing live arrangement can mutate override templates unexpectedly.</comment>
<file context>
@@ -705,17 +858,115 @@ function UnitSquad(squad_type = undefined, company = 0) constructor {
+ var _found = false;
+ for (var ai = 0; ai < array_length(arrangement.companies); ai++) {
+ if (arrangement.companies[ai].company == _ovr.company) {
+ arrangement.companies[ai] = _ovr;
+ _found = true;
+ break;
</file context>
| if (is_array(type)) { | ||
| show_debug_message($"[PROBE] change_type got ARRAY type (len {array_length(type)}): {type}"); | ||
| } else if (!struct_exists(obj_ini.squad_types, type)) { | ||
| show_debug_message($"[PROBE] change_type unknown squad type: \"{type}\""); | ||
| } |
There was a problem hiding this comment.
P2: Invalid squad types are detected but not stopped; function still dereferences the invalid key and can crash.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/scr_squads/scr_squads.gml, line 381:
<comment>Invalid squad types are detected but not stopped; function still dereferences the invalid key and can crash.</comment>
<file context>
@@ -279,6 +378,11 @@ function UnitSquad(squad_type = undefined, company = 0) constructor {
static change_type = function(new_type) {
type = new_type;
+ if (is_array(type)) {
+ show_debug_message($"[PROBE] change_type got ARRAY type (len {array_length(type)}): {type}");
+ } else if (!struct_exists(obj_ini.squad_types, type)) {
</file context>
| if (is_array(type)) { | |
| show_debug_message($"[PROBE] change_type got ARRAY type (len {array_length(type)}): {type}"); | |
| } else if (!struct_exists(obj_ini.squad_types, type)) { | |
| show_debug_message($"[PROBE] change_type unknown squad type: \"{type}\""); | |
| } | |
| if (is_array(type)) { | |
| show_debug_message($"[PROBE] change_type got ARRAY type (len {array_length(type)}): {type}"); | |
| return; | |
| } else if (!struct_exists(obj_ini.squad_types, type)) { | |
| show_debug_message($"[PROBE] change_type unknown squad type: \"{type}\""); | |
| return; | |
| } |
Dismissed because Cubic found issues in a newer review.
General LW_Beta Notes
more detailed info in the first Lightning Warriors Beta release
Testing
Checked everything I could, it seems this is on par with main in bugs
Summary by cubic
Adds the Lightning Warriors beta with bike-heavy squads and the “Speed Force” drive-by. Reworks the combat log with color, summaries, scrollback (wheel/drag), and stability fixes for long turns; cleans up company templates and shooting flow for clearer battles.
New Features
bike_squad/attack_bike_squadfocus, promotions, unique bike formation and icon.Refactors and Fixes
default_squads; generator supports multi-role sources and unique-role checks; equal Scouts/Specialists templates fixed; company view sorted and stable.id, “monastery” spelling, Librarian role label, Contemptor description; chapter template refreshed.Written for commit f6c5244. Summary will update on new commits.