Skip to content

fix: squad saving and loading - #1435

Open
OH296 wants to merge 1 commit into
Adeptus-Dominus:mainfrom
OH296:squad_button_gone_After_save
Open

fix: squad saving and loading#1435
OH296 wants to merge 1 commit into
Adeptus-Dominus:mainfrom
OH296:squad_button_gone_After_save

Conversation

@OH296

@OH296 OH296 commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Summary by cubic

Fixes squad save/load so squads and their members persist after reloading. Previously, serialization wrote to the wrong member index and deserialization didn’t register squads or resolve member IDs, which made squads disappear or appear empty after load.

  • Serialize: use the correct index when replacing member structs with uids; save squad_structs from _squad_copies instead of live squads.
  • Deserialize: replace load_json_data with UnitSquad.load, which moves data into the instance, registers it in obj_ini.squads, resolves member IDs via fetch_unit_uid, and prunes invalid entries.
  • Lookup: fetch_unit_uid now uses company_length(i) for bounds rather than array_length(obj_ini.TTRPG[i]) to avoid out-of-range access.
  • Migration: no changes required in core code; if any external scripts call load_json_data, rename those calls to load.

Written for commit 84efc69. Summary will update on new commits.

Review in cubic

@github-actions github-actions Bot added Size: Tiny Type: Fix This is a fix for a bug labels Aug 12, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 3 files

Confidence score: 3/5

  • In objects/obj_ini/Create_0.gml, deserialization now calls _squad.load(_data) without the previous post-load member validation, so malformed or legacy save payloads can leave squads in invalid states or fail at runtime—add defensive error handling and restore/replace member integrity checks after load.
  • In objects/obj_ini/Create_0.gml serialize(), squad members are normalized to UIDs but squad_leader is still saved as a full struct clone, which can reload as a detached plain struct without expected methods and break leader-related behavior—store the leader as a UID and re-resolve it on load.
  • In scripts/scr_squads/scr_squads.gml, pruning unresolved member UIDs without recomputing life_members can leave stale counts and show phantom members in the squad UI—recalculate life_members during the cleanup pass.
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_squads/scr_squads.gml">

<violation number="1" location="scripts/scr_squads/scr_squads.gml:483">
P2: When a saved member UID no longer resolves, this cleanup removes the member but leaves `life_members` at its saved value. Recalculate `life_members` while pruning so the squad UI does not show phantom members.</violation>
</file>

<file name="objects/obj_ini/Create_0.gml">

<violation number="1" location="objects/obj_ini/Create_0.gml:163">
P2: In serialize(), squad members are normalized to uid strings, but `squad_leader` is left as a full marine-struct clone, so it is embedded in the save and reloaded as a detached plain struct without methods instead of the live marine. Convert `squad_leader` to its uid like members (and resolve it back in `load`).</violation>

<violation number="2" location="objects/obj_ini/Create_0.gml:317">
P2: Custom agent: **Code Quality Review**

The new `_squad.load(_data)` call during deserialization has no error handling, and the post-load member validation loops from the previous code were removed. Because this loads user-provided save data, a malformed squad struct will cause an unhandled runtime exception. Follow the project's established deserialization pattern—used for artifact loading a few lines below—and wrap the call in `try/catch` with `LOGGER.exception()`.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic


for (var s = array_length(members) - 1; s >= 0; s--) {
if (!is_struct(members[s])) {
array_delete(members, s, 1);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a saved member UID no longer resolves, this cleanup removes the member but leaves life_members at its saved value. Recalculate life_members while pruning so the squad UI does not show phantom members.

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 483:

<comment>When a saved member UID no longer resolves, this cleanup removes the member but leaves `life_members` at its saved value. Recalculate `life_members` while pruning so the squad UI does not show phantom members.</comment>

<file context>
@@ -471,10 +471,17 @@ function UnitSquad(squad_type = undefined, company = 0) constructor {
+
+        for (var s = array_length(members) - 1; s >= 0; s--) {
+            if (!is_struct(members[s])) {
+                array_delete(members, s, 1);
+            }
         }
</file context>
Suggested change
array_delete(members, s, 1);
array_delete(members, s, 1);
life_members = array_length(members);

for (var s = 0; s < array_length(_squad.members); s++) {
if (is_struct(_squad.members[s])) {
_squad.members[i] = _squad.members[s].uid;
_squad.members[s] = _squad.members[s].uid;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: In serialize(), squad members are normalized to uid strings, but squad_leader is left as a full marine-struct clone, so it is embedded in the save and reloaded as a detached plain struct without methods instead of the live marine. Convert squad_leader to its uid like members (and resolve it back in load).

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 163:

<comment>In serialize(), squad members are normalized to uid strings, but `squad_leader` is left as a full marine-struct clone, so it is embedded in the save and reloaded as a detached plain struct without methods instead of the live marine. Convert `squad_leader` to its uid like members (and resolve it back in `load`).</comment>

<file context>
@@ -160,7 +160,7 @@ serialize = function() {
         for (var s = 0; s < array_length(_squad.members); s++) {
             if (is_struct(_squad.members[s])) {
-                _squad.members[i] = _squad.members[s].uid;
+                _squad.members[s] = _squad.members[s].uid;
             }
         }
</file context>

Comment on lines +317 to +319
var _data = _squad_structs[$ _squad_uid];
var _squad = new UnitSquad();
_squad.load_json_data(_squad_structs[$ _squad_uid]);
squads[$ _squad_uid] = _squad;
for (var s = 0; s < array_length(_squad.members); s++) {
_squad.members[s] = fetch_unit_uid(_squad.members[s]);
}
_squad.load(_data);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: Code Quality Review

The new _squad.load(_data) call during deserialization has no error handling, and the post-load member validation loops from the previous code were removed. Because this loads user-provided save data, a malformed squad struct will cause an unhandled runtime exception. Follow the project's established deserialization pattern—used for artifact loading a few lines below—and wrap the call in try/catch with LOGGER.exception().

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 317:

<comment>The new `_squad.load(_data)` call during deserialization has no error handling, and the post-load member validation loops from the previous code were removed. Because this loads user-provided save data, a malformed squad struct will cause an unhandled runtime exception. Follow the project's established deserialization pattern—used for artifact loading a few lines below—and wrap the call in `try/catch` with `LOGGER.exception()`.</comment>

<file context>
@@ -314,18 +314,10 @@ deserialize = function(save_data) {
         var _squad_count = array_length(_squad_uids);
         for (var i = 0; i < _squad_count; i++) {
             var _squad_uid = _squad_uids[i];
+            var _data = _squad_structs[$ _squad_uid];
             var _squad = new UnitSquad();
-            _squad.load_json_data(_squad_structs[$ _squad_uid]);
</file context>
Suggested change
var _data = _squad_structs[$ _squad_uid];
var _squad = new UnitSquad();
_squad.load_json_data(_squad_structs[$ _squad_uid]);
squads[$ _squad_uid] = _squad;
for (var s = 0; s < array_length(_squad.members); s++) {
_squad.members[s] = fetch_unit_uid(_squad.members[s]);
}
_squad.load(_data);
var _data = _squad_structs[$ _squad_uid];
var _squad = new UnitSquad();
try {
_squad.load(_data);
} catch (e) {
LOGGER.exception("Failed to load squad " + _squad_uid, e);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Size: Tiny Type: Fix This is a fix for a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant