Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ChapterMaster.yyp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@
{"$GMFolder":"","%Name":"Tile Sets","folderPath":"folders/Tile Sets.yy","name":"Tile Sets","resourceType":"GMFolder","resourceVersion":"2.0",},
{"$GMFolder":"","%Name":"Timelines","folderPath":"folders/Timelines.yy","name":"Timelines","resourceType":"GMFolder","resourceVersion":"2.0",},
],
"ForcedPrefabProjectReferences":[],
"ForcedPrefabProjectReferences":[
{"link":"io.gamemaker.sdfshaders-1.0.0","name":"io.gamemaker.sdfshaders-1.0.0","path":"io.gamemaker.sdfshaders-1.0.0.yyp",},
],
Comment on lines +121 to +123
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Search for the referenced SDF shaders prefab
fd 'io.gamemaker.sdfshaders-1.0.0.yyp'

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 55


🏁 Script executed:

# Inspect the project file structure to understand dependencies
fd '\.yyp$' | head -20

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 90


🏁 Script executed:

# Search for CI/build configuration that may specify IDE versions
fd -e yaml -e yml -e json | xargs grep -l '2024\|IDE\|GameMaker' 2>/dev/null | head -10

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 55


🏁 Script executed:

# Examine the ChapterMaster.yyp file itself for context on other dependencies
grep -n 'ForcedPrefabProjectReferences\|IDEVersion' ChapterMaster.yyp

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 150


🏁 Script executed:

# Check for git submodules
cat .gitmodules 2>/dev/null || echo "No submodules configured"

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 97


🏁 Script executed:

# Examine the ChapterMaster.yyp file for context around the prefab reference
sed -n '115,130p' ChapterMaster.yyp

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 2169


🏁 Script executed:

# Search for any documentation or configuration about external libraries/prefabs
fd -e md -e txt | xargs grep -l 'sdfshaders\|prefab\|library' 2>/dev/null | head -5

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 91


🏁 Script executed:

# Check if there are any other ForcedPrefabProjectReferences that might provide a pattern
grep 'ForcedPrefabProjectReferences' -A 20 ChapterMaster.yyp

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 3438


🏁 Script executed:

# Review the CODE_STYLE.md for guidance on external dependencies
cat docs/CODE_STYLE.md | head -100

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 4037


The SDF shaders prefab is absent from the repository—the project-spirit shall not awaken.

The manifest declares an allegiance to io.gamemaker.sdfshaders-1.0.0.yyp within ForcedPrefabProjectReferences (line 121), yet the archival search reveals no trace of this artefact within the forge. Without it, the IDE will reject the project at load-time, and compilation shall be rendered impossible. No submodule, no external resolver, no rite of installation has been inscribed.

The project cannot proceed to merge in this corrupted state. The prefab must either be committed to the repository, installed via established ritual (documented in README or setup guide), or the ForcedPrefabProjectReferences entry removed entirely if its inclusion was erroneous.

Regarding IDEVersion 2024.14.2.213 at line 584: Ensure all build-forges and developer workstations possess this version or newer, else synchronisation shall falter.

🤖 Prompt for AI Agents
In ChapterMaster.yyp around lines 121-123 (and note IDEVersion at line 584), the
ForcedPrefabProjectReferences points to io.gamemaker.sdfshaders-1.0.0.yyp which
is missing from the repository; either add/commit the prefab file at the
declared path (io.gamemaker.sdfshaders-1.0.0.yyp), wire it as a submodule or
include installation steps in the README/setup script to fetch it, or remove the
ForcedPrefabProjectReferences entry if it was added in error; also verify and
document the required IDEVersion 2024.14.2.213 in the setup docs so developers
and CI use a compatible IDE.

"IncludedFiles":[
{"$GMIncludedFile":"","%Name":"sisters.json","CopyToMask":-1,"filePath":"datafiles/data/dialogue","name":"sisters.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",},
{"$GMIncludedFile":"","%Name":"psychic_disciplines.json","CopyToMask":-1,"filePath":"datafiles/data","name":"psychic_disciplines.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",},
Expand Down Expand Up @@ -579,7 +581,7 @@
"isEcma":false,
"LibraryEmitters":[],
"MetaData":{
"IDEVersion":"2024.1400.0.901",
"IDEVersion":"2024.14.2.213",
},
"name":"ChapterMaster",
"resources":[
Expand Down
55 changes: 29 additions & 26 deletions objects/obj_star/Alarm_1.gml
Original file line number Diff line number Diff line change
Expand Up @@ -74,32 +74,35 @@ for(var i=1; i<=4; i++){
p_max_population[i] = p_population[i];
break;
}
// Sets military on planet
if (p_population[i]>=10000000){
var military=p_population[i]/470;
p_guardsmen[i]=floor(military*0.25);
p_pdf[i]=floor(military*0.75);
}
if (p_population[i]>=5000000) and (p_population[i]<10000000){
var military=p_population[i]/200;
p_guardsmen[i]=floor(military*0.25);
p_pdf[i]=floor(military*0.75);
}
if (p_population[i]>=100000) and (p_population[i]<5000000){
var military=p_population[i]/50;
p_guardsmen[i]=floor(military*0.25);
p_pdf[i]=floor(military*0.75);
}
if (p_population[i]<100000) and (p_population[i]>5) and (p_large[i]==0){
p_pdf[i]=floor(p_population[i]/25);
}
if (p_population[i]<2000) and (p_population[i]>5) and (p_large[i]==0){
p_pdf[i]=floor(p_population[i]/10);
}
if (p_large[i]==1){
p_guardsmen[i]=floor(p_population[i]*1250000);
p_pdf[i]=p_guardsmen[i]*3;
}

if (p_population[i]>=10000000){
var military=p_population[i]/470;
p_guardsmen[i]=floor(military*0.25);
p_pdf[i]=floor(military*0.75);
}
if (p_population[i]>=5000000) and (p_population[i]<10000000){
var military=p_population[i]/200;
p_guardsmen[i]=floor(military*0.25);
p_pdf[i]=floor(military*0.75);
}
if (p_population[i]>=100000) and (p_population[i]<5000000){
var military=p_population[i]/50;
p_guardsmen[i]=floor(military*0.25);
p_pdf[i]=floor(military*0.75);
}
if (p_population[i]<100000) and (p_population[i]>5) and (p_large[i]==0){
p_pdf[i]=floor(p_population[i]/25);
}
if (p_population[i]<2000) and (p_population[i]>5) and (p_large[i]==0){
p_pdf[i]=floor(p_population[i]/10);
}
if (p_large[i]==1){
p_guardsmen[i]=floor(p_population[i]*1250000);
p_pdf[i]=p_guardsmen[i]*3;
}

//the pdf on planet gen is set as the target_pdf
p_target_pdf[i] = p_pdf[i];
Comment on lines +78 to +105
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

p_target_pdf is not reset for Craftworlds, risking unintended PDF regrowth.

Tech-Priest, the logic that forges p_pdf and mirrors it into p_target_pdf at generation is sound for Imperial worlds: the target becomes “PDF at game birth”, as desired.

Yet note the later Craftworld rite:

  • You purge p_guardsmen[i] and p_pdf[i] back to 0 for craftworld==1,
  • But you leave p_target_pdf[i] at the pre-purge value you just computed.

Any subsequent population/PDF growth that climbs towards p_target_pdf will then quietly conjure Imperial-pattern PDF on an Eldar Craftworld, which seems both mechanically and lore-incongruent.

Would it not better honour the design if Craftworld planets also had their p_target_pdf[i] annulled alongside p_pdf[i], so no Imperial PDF cap exists there at all?

Possible adjustment to keep Craftworlds PDF-free
     if (craftworld==1){
-        p_guardsmen[i]=0;
-        p_pdf[i]=0;
+        p_guardsmen[i]=0;
+        p_pdf[i]=0;
+        p_target_pdf[i]=0;
         p_eldar[i]=6;
         owner = eFACTION.Eldar;
         p_owner[1]=6;
         warp_lanes=[];
         x2=0;
     }

Secondary incantation: in the 5–2000 population band both the <100000 and <2000 branches fire, reassigning p_pdf[i] twice. If this is intentional, consider tightening the first condition to p_population[i] >= 2000 && p_population[i] < 100000 to make the intent explicit to future adepts.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In objects/obj_star/Alarm_1.gml around lines 78 to 105, p_target_pdf is being
set from the computed p_pdf for all worlds but later Craftworlds reset
p_guardsmen and p_pdf to 0 while leaving p_target_pdf unchanged (allowing
unintended PDF regrowth); also the population bands for <100000 and <2000
overlap causing p_pdf to be assigned twice. Fix by ensuring when a planet is a
Craftworld (craftworld==1) you also set p_target_pdf[i]=0 alongside
p_guardsmen[i]=0 and p_pdf[i]=0, and tighten the first small-population branch
to only apply for 2000 <= p_population[i] < 100000 (or change the second branch
to p_population[i] < 2000) so the two branches do not both execute.


if (p_population[i]<1000000) and (p_large[i]==0)then p_pop[i]=string(p_population[i]);
if (p_population[i]>999999) and (p_large[i]==0)and (p_population[i]<1000000000) then p_pop[i]=string(p_population[i]/1000000)+"M";
Expand Down
1 change: 1 addition & 0 deletions objects/obj_star/Create_0.gml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ p_large = array_create(_planet_array_size, 0);
p_pop = array_create(_planet_array_size, "");
p_guardsmen = array_create(_planet_array_size, 0);
p_pdf = array_create(_planet_array_size, 0);
p_target_pdf = array_create(_planet_array_size, 0);
p_fortified = array_create(_planet_array_size, 0);
p_station = array_create(_planet_array_size, 0);
p_player = array_create(_planet_array_size, 0);
Expand Down
253 changes: 161 additions & 92 deletions objects/obj_star_select/Draw_64.gml
Original file line number Diff line number Diff line change
Expand Up @@ -261,109 +261,178 @@ if (obj_controller.selecting_planet!=0){
exit;
}
}
}else if (garrison!="" && !population){
if (garrison.garrison_force ){
draw_set_font(fnt_40k_14);
if (!garrison.garrison_leader){
garrison.find_leader()
garrison.garrison_disposition_change(target, obj_controller.selecting_planet, true);
garrison_data_slate.sub_title = $"Garrison Leader {garrison.garrison_leader.name_role()}"
garrison_data_slate.body_text = garrison.garrison_report();
}
garrison_data_slate.inside_method=function(){
garrison_data_slate.title = "Garrison Report"
draw_set_color(c_gray);
var xx = garrison_data_slate.XX;
var yy = garrison_data_slate.YY;
var cur_planet = obj_controller.selecting_planet;
var half_way = yy+garrison_data_slate.height/2;
draw_set_halign(fa_left);
draw_line(xx+10, half_way, garrison_data_slate.width-10, half_way);
var defence_data = determine_pdf_defence(target.p_pdf[cur_planet], garrison,target.p_fortified[cur_planet]);
var defence_string = $"Planetary Defence : {defence_data[0]}";
draw_text(xx+20, half_way, defence_string);
if (scr_hit(xx+20, half_way+10, xx+20+string_width(defence_string), half_way+10+20)){
tooltip_draw(defence_data[1], 400);
}
if (garrison.dispo_change!="none"){
if (garrison.dispo_change>55){
draw_text(xx+20, half_way+30, $"Garrison Disposition Effect : Positive");
} else if (garrison.dispo_change>44){
draw_text(xx+20, half_way+30, $"Garrison Disposition Effect : Neutral");
} else{
draw_text(xx+20, half_way+30, $"Garrison Disposition Effect : Negative");
}
}
}
garrison_data_slate.draw(340+main_data_slate.width, 160, 0.6, 0.6);

}
} else if (population){
garrison_data_slate.title = "Population Report";
garrison_data_slate.inside_method = function(){
draw_set_color(c_gray);
var xx = garrison_data_slate.XX;
var yy = garrison_data_slate.YY;
var cur_planet = obj_controller.selecting_planet;
var half_way = garrison_data_slate.height/2;
var spacing_x = 100
var spacing_y = 65
draw_set_halign(fa_left);
if (!target.space_hulk) {
if (obj_controller.faction_status[eFACTION.Imperium] != "War" && p_data.current_owner <= 5) || (obj_controller.faction_status[eFACTION.Imperium] == "War") {
colonist_button.update({
x1:xx+35,
y1:half_way,
allow_click : array_length(potential_doners),
});
colonist_button.draw();
} else if (population){
garrison_data_slate.title = "Population Report";
garrison_data_slate.inside_method = function(){
draw_set_color(c_gray);
var xx = garrison_data_slate.XX;
var yy = garrison_data_slate.YY;
var cur_planet = obj_controller.selecting_planet;
var half_way = garrison_data_slate.height/2;
var spacing_x = 100;
var spacing_y = 65;
draw_set_halign(fa_left);

if (!target.space_hulk) {
if (obj_controller.faction_status[eFACTION.Imperium] != "War" && p_data.current_owner <= 5) || (obj_controller.faction_status[eFACTION.Imperium] == "War") {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Clarify boolean precedence with explicit parentheses, Tech-Priest.

The machine logic chains multiple conditions without sacred parentheses. While the cogitator may parse correctly through precedence runes, mortal comprehension falters.

Is your intent ((status != "War") && (owner <= 5)) || (status == "War")?

⚙️ Proposed clarification
-if (obj_controller.faction_status[eFACTION.Imperium] != "War" && p_data.current_owner <= 5) || (obj_controller.faction_status[eFACTION.Imperium] == "War") {
+if ((obj_controller.faction_status[eFACTION.Imperium] != "War" && p_data.current_owner <= 5) || (obj_controller.faction_status[eFACTION.Imperium] == "War")) {

As per coding guidelines: prioritise code that explicitly reveals intent over brevity.

🤖 Prompt for AI Agents
In objects/obj_star_select/Draw_64.gml around line 277, the complex conditional
lacks explicit parentheses which makes boolean precedence unclear; update the if
condition to explicitly group as
((obj_controller.faction_status[eFACTION.Imperium] != "War") &&
(p_data.current_owner <= 5)) ||
(obj_controller.faction_status[eFACTION.Imperium] == "War") so the intent — war
status overrides the owner check, otherwise require owner <= 5 — is unambiguous.

colonist_button.update({
x1:xx+35,
y1:half_way,
allow_click : array_length(potential_doners),
});
colonist_button.draw();

recruiting_button.update({
x1:xx+(spacing_x*2)+15,
recruiting_button.update({
x1:xx+(spacing_x*2)+15,
y1:half_way,
allow_click : true,
});
recruiting_button.draw();

if (p_data.has_feature(P_features.Recruiting_World)) {
var _recruit_world = p_data.get_features(P_features.Recruiting_World)[0];
if (_recruit_world.recruit_type == 0) && (obj_controller.faction_status[p_data.current_owner] != "War" && obj_controller.faction_status[p_data.current_owner] != "Antagonism" || p_data.player_disposition >= 50) {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Boolean labyrinth requires illumination, Tech-Priest.

This conditional pathway interweaves four logic gates without parenthetical guidance. The intent remains obscured in ambiguity.

Reforge with explicit parentheses to reveal the true logic path: (type == 0) AND ((not War AND not Antagonism) OR (disposition >= 50))?

⚙️ Proposed clarification
-if (_recruit_world.recruit_type == 0) && (obj_controller.faction_status[p_data.current_owner] != "War" && obj_controller.faction_status[p_data.current_owner] != "Antagonism" || p_data.player_disposition >= 50) {
+if ((_recruit_world.recruit_type == 0) && ((obj_controller.faction_status[p_data.current_owner] != "War" && obj_controller.faction_status[p_data.current_owner] != "Antagonism") || p_data.player_disposition >= 50)) {

As per coding guidelines: if a solution is hard to parse mentally, refactor to clarity.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (_recruit_world.recruit_type == 0) && (obj_controller.faction_status[p_data.current_owner] != "War" && obj_controller.faction_status[p_data.current_owner] != "Antagonism" || p_data.player_disposition >= 50) {
if ((_recruit_world.recruit_type == 0) && ((obj_controller.faction_status[p_data.current_owner] != "War" && obj_controller.faction_status[p_data.current_owner] != "Antagonism") || p_data.player_disposition >= 50)) {
🤖 Prompt for AI Agents
In objects/obj_star_select/Draw_64.gml around line 294, the if-statement mixes
&& and || without explicit grouping, making the intended logic ambiguous;
rewrite the condition with explicit parentheses to enforce:
(_recruit_world.recruit_type == 0) AND (
(obj_controller.faction_status[p_data.current_owner] != "War" AND
obj_controller.faction_status[p_data.current_owner] != "Antagonism") OR
(p_data.player_disposition >= 50) ). Update the line to use these parentheses so
the boolean precedence is clear and the intended short-circuiting is preserved.

draw_text(xx+(spacing_x*3)+35, half_way-20, "Open: Voluntery");
} else if (_recruit_world.recruit_type == 0 && p_data.player_disposition <= 50) {
draw_text(xx+(spacing_x*3)+35, half_way-20, "Covert: Voluntery");
} else {
draw_text(xx+(spacing_x*3)+35, half_way-20, "Abduct");
}
recruitment_type_button.update({
x1:xx+(spacing_x*3)+35,
y1:half_way,
allow_click : true,
});
recruiting_button.draw();
if (p_data.has_feature(P_features.Recruiting_World)) {
var _recruit_world = p_data.get_features(P_features.Recruiting_World)[0];
if (_recruit_world.recruit_type == 0) && (obj_controller.faction_status[p_data.current_owner] != "War" && obj_controller.faction_status[p_data.current_owner] != "Antagonism" || p_data.player_disposition >= 50) {
draw_text(xx+(spacing_x*3)+35, half_way-20, "Open: Voluntery");
} else if (_recruit_world.recruit_type == 0 && p_data.player_disposition <= 50) {
draw_text(xx+(spacing_x*3)+35, half_way-20, "Covert: Voluntery");
} else {
draw_text(xx+(spacing_x*3)+35, half_way-20, "Abduct");
}
recruitment_type_button.update({
recruitment_type_button.draw();

draw_text(xx+(spacing_x*3)-15, half_way+(spacing_y)-20, $"Req:{_recruit_world.recruit_cost * 2}");
if (_recruit_world.recruit_cost > 0) {
recruitment_costdown_button.update({
x1:xx+(spacing_x*2)+35,
y1:half_way+(spacing_y),
allow_click : true,
});
recruitment_costdown_button.draw();
}
if (_recruit_world.recruit_cost < 5) {
recruitment_costup_button.update({
x1:xx+(spacing_x*3)+35,
y1:half_way,
y1:half_way+(spacing_y),
allow_click : true,
});
recruitment_type_button.draw();

draw_text(xx+(spacing_x*3)-15, half_way+(spacing_y)-20, $"Req:{_recruit_world.recruit_cost * 2}");
if (_recruit_world.recruit_cost > 0) {
recruitment_costdown_button.update({
x1:xx+(spacing_x*2)+35,
y1:half_way+(spacing_y),
allow_click : true,
});
recruitment_costdown_button.draw();
}
if (_recruit_world.recruit_cost < 5) {
recruitment_costup_button.update({
x1:xx+(spacing_x*3)+35,
y1:half_way+(spacing_y),
allow_click : true,
});
recruitment_costup_button.draw();
}
recruitment_costup_button.draw();
}
}
}

}
garrison_data_slate.draw(344+main_data_slate.width-4, 160, 0.6, 0.6);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Extraneous whitespace mars the sacred text, Tech-Priest.

Line 328 contains only a tab character. While the cogitator ignores such trivia, clean scripture pleases the Machine God.

🤖 Prompt for AI Agents
In objects/obj_star_select/Draw_64.gml around line 328, there is an extraneous
tab character on a line by itself; remove that trailing blank line or replace
the tab with an empty line (no whitespace) so the file contains no lone
whitespace-only line at 328, and save with normalized line endings to prevent
reintroduction.

var p = cur_planet;

function fmt_compact(_n){
_n = abs(_n);
if (_n >= 1000000000) return string_format(_n / 1000000000, 0, 2) + "B";
if (_n >= 1000000) return string_format(_n / 1000000, 0, 2) + "M";
if (_n >= 1000) return string_format(_n / 1000, 0, 1) + "K";
return string(floor(_n));
}
Comment on lines +331 to +337
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Function ritual repeats with each render cycle, Tech-Priest.

The fmt_compact subroutine manifests anew every frame within the drawing rite. The Draw_64 event invokes sixty times per second—this function regenerates endlessly.

Hoist this logic to initialization or script scope to honour efficiency protocols.

⚙️ Proposed optimisation

Define the formatter once outside the draw method, perhaps as a script or at object creation:

// In a separate script file or Create event
function fmt_compact(_n){
    _n = abs(_n);
    if (_n >= 1000000000) return string_format(_n / 1000000000, 0, 2) + "B";
    if (_n >= 1000000)    return string_format(_n / 1000000,    0, 2) + "M";
    if (_n >= 1000)       return string_format(_n / 1000,       0, 1) + "K";
    return string(floor(_n));
}
🤖 Prompt for AI Agents
In objects/obj_star_select/Draw_64.gml around lines 331-337, the fmt_compact
function is being redefined every frame inside the Draw event which is wasteful;
move the function definition out of the Draw_64 event into an initialization
scope (either a dedicated script file or the object's Create event) so it is
defined once, remove the inline definition from the Draw_64 code, ensure the
Draw_64 code calls the now-global/script-scoped fmt_compact, and verify there
are no name collisions or ordering issues (define the function before any Draw
events that call it).


var LARGE_POP_CONVERSION = 1000000000;
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Sacred constants reborn each cycle waste the Machine God's blessing, Tech-Priest.

LARGE_POP_CONVERSION, POP_GROWTH_RATE, and PDF_GROWTH_RATE manifest anew with every render invocation. Constants require no regeneration.

Elevate these immutable values to object initialization or macro declarations. Growth rates govern game balance—consider centralising within configuration scripture.

⚙️ Proposed relocation

In a configuration script or at object creation:

#macro LARGE_POP_CONVERSION 1000000000
#macro POP_GROWTH_RATE 0.00025
#macro PDF_GROWTH_RATE 0.01

Note the coding guideline: constants of macro type MUST have a space between name and value.

Also applies to: 364-364, 409-409

🤖 Prompt for AI Agents
In objects/obj_star_select/Draw_64.gml around lines 339, 364 and 409 the values
LARGE_POP_CONVERSION, POP_GROWTH_RATE and PDF_GROWTH_RATE are being redefined
inside the draw routine each frame; move these immutable values out of the
render path by declaring them once (either as #macro definitions in a
config/constants script or assigned in the object's Create event) and then
reference those names in the draw code; if using macros follow the GML style
with a space between name and value (e.g. #macro NAME value) and remove the
per-frame var declarations so the draw code only reads the constants.


var _supported_pop_stored = target.p_max_population[p];
var _cur_pop_stored = target.p_population[p];
var _max_pop_stored = target.p_max_population[p];

var _is_large = (target.p_large[p] == 1);

var _supported_pop_abs = _is_large ? (_supported_pop_stored * LARGE_POP_CONVERSION) : _supported_pop_stored;
var _cur_pop_abs = _is_large ? (_cur_pop_stored * LARGE_POP_CONVERSION) : _cur_pop_stored;
var _max_pop_abs = _is_large ? (_max_pop_stored * LARGE_POP_CONVERSION) : _max_pop_stored;

draw_set_color(c_white);
draw_set_halign(fa_left);

var _base_x = xx + 35;
var _base_y = half_way + spacing_y + 60;
var _line_h = 18;

draw_text(
_base_x,
_base_y,
"Max supported population: " + fmt_compact(_supported_pop_abs)
);

var POP_GROWTH_RATE = 0.00025;
var _pop_growth_abs = 0;

if (_cur_pop_abs > 0 && _supported_pop_abs > 0 && _cur_pop_abs < _supported_pop_abs){
_pop_growth_abs = ceil(_cur_pop_abs * POP_GROWTH_RATE);
_pop_growth_abs = min(_pop_growth_abs, _supported_pop_abs - _cur_pop_abs);
} else if (_cur_pop_abs > 0 && _supported_pop_abs <= 0) {
_pop_growth_abs = ceil(_cur_pop_abs * POP_GROWTH_RATE);
}
Comment on lines +367 to +372
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the full context of lines 367-372
fd "Draw_64.gml" -t f | head -1 | xargs cat -n | sed -n '355,385p'

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 55


🏁 Script executed:

# Search for p_max_population assignments and usage
rg -n 'p_max_population' --type=gml -B2 -A2 | head -100

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 100


🏁 Script executed:

# Search for recolonization and colonization mechanics
rg -n -i 'recolon|coloniz' --type=gml -B2 -A2 | head -80

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 100


🏁 Script executed:

# Search for POP_GROWTH_RATE constant definition
rg -n 'POP_GROWTH_RATE' --type=gml -B1 -A1

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 100


🏁 Script executed:

# Find the Draw_64.gml file
fd "Draw_64.gml" -t f

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 419


🏁 Script executed:

# Read the context around lines 367-372
fd "Draw_64.gml" -t f -exec cat -n {} \; | sed -n '360,380p'

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 303


🏁 Script executed:

# Search for p_max_population across all files
rg -n 'p_max_population' -B2 -A2 | head -150

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 11866


🏁 Script executed:

# Search for recolonization and colonization logic
rg -n -i 'recolon|coloniz' -B2 -A2 | head -100

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 8199


🏁 Script executed:

# Search for POP_GROWTH_RATE definition
rg -n 'POP_GROWTH_RATE' -B1 -A1 | head -50

Repository: Adeptus-Dominus/ChapterMaster

Length of output: 837


The logic paradox remains unresolved, Tech-Priest.

The second conditional pathway (lines 370-372) permits population expansion even when _supported_pop_abs <= 0—a state that manifests upon planetary destruction or during initialisation when p_max_population is not yet assigned. This violates the stated doctrine: "Growth capped so it does not exceed a planet's maximum supported population."

Observe the asymmetry: line 369 applies a min() constraint to cap growth against capacity, yet line 371 applies no such restraint. Population multiplies in the void of support.

Either this conditional path serves a purpose beyond the archives' current knowledge, or it represents unintended logic that should be excised. Which is it?

🤖 Prompt for AI Agents
In objects/obj_star_select/Draw_64.gml around lines 367 to 372, the else-if
branch allows population growth when _supported_pop_abs <= 0, contradicting the
capacity cap logic; change the logic so growth is only computed when
_supported_pop_abs > 0 (use the existing ceil/min clamp), and otherwise set
_pop_growth_abs to 0 to prevent growth when there is no support.


draw_text(
_base_x,
_base_y + _line_h,
"Pop growth/turn (0.025%): +" + fmt_compact(_pop_growth_abs)
);

var _has_target_pdf = variable_instance_exists(target.id, "p_target_pdf");
var _target_pdf = _has_target_pdf ? target.p_target_pdf[p] : 0;

draw_text(
_base_x,
_base_y + (_line_h * 2),
"Target PDF: " + fmt_compact(_target_pdf)
);

var _pdf_cap = 0;
var _support_pct = 0;

if (_has_target_pdf && _target_pdf > 0 && _max_pop_abs > 0){
var _pop_ratio = clamp(_cur_pop_abs / _max_pop_abs, 0, 1);
_pdf_cap = floor(_target_pdf * _pop_ratio);

if (_pdf_cap > 0){
_support_pct = (target.p_pdf[p] / _pdf_cap) * 100;
} else if (target.p_pdf[p] > 0){
_support_pct = 999;
}
Comment on lines +398 to +400
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

The sentinel value 999 obscures its meaning, Tech-Priest.

When PDF exists but capacity equals zero, the display renders "999%" to the user. This arcane number lacks semantic clarity.

Consider displaying textual wisdom ("Over Capacity" or "N/A") when this paradoxical state manifests, or define a named constant CAPACITY_INVALID = 999 to document intent.

⚙️ Alternative rendering logic
 if (_pdf_cap > 0){
     _support_pct = (target.p_pdf[p] / _pdf_cap) * 100;
-} else if (target.p_pdf[p] > 0){
-    _support_pct = 999;
-}
+} else if (target.p_pdf[p] > 0){
+    _support_pct = -1; // Use -1 as sentinel
+}

+// Later in display logic:
+if (_support_pct >= 0){
+    draw_text(..., "PDF capacity usage: " + string_format(_support_pct, 0, 1) + "%...");
+} else {
+    draw_text(..., "PDF capacity usage: Over Capacity (" + fmt_compact(target.p_pdf[p]) + ")");
+}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In objects/obj_star_select/Draw_64.gml around lines 398-400, the code sets
_support_pct = 999 as a magic sentinel when target.p_pdf[p] > 0 but capacity is
zero; replace this unclear literal with a named constant (e.g., CAPACITY_INVALID
= 999) declared near the top of the file and use that constant here, and update
the rendering logic to check for CAPACITY_INVALID and display a human-readable
label ("Over Capacity" or "N/A") instead of "999%". Ensure the constant is
documented with a comment and the rendering branch prefers the textual message
when CAPACITY_INVALID is set.

}

draw_text(
_base_x,
_base_y + (_line_h * 3),
"Supported PDF (current pop): " + fmt_compact(_pdf_cap)
);

var PDF_GROWTH_RATE = 0.01;
var _pdf_growth = 0;

if (_has_target_pdf && _target_pdf > 0 && _pdf_cap > 0){
if (target.p_pdf[p] < _pdf_cap){
_pdf_growth = ceil(_target_pdf * PDF_GROWTH_RATE);
_pdf_growth = min(_pdf_growth, _pdf_cap - target.p_pdf[p]);
}
}

draw_text(
_base_x,
_base_y + (_line_h * 4),
"PDF growth per turn: +" + fmt_compact(_pdf_growth)
);

draw_text(
_base_x,
_base_y + (_line_h * 5),
"PDF capacity usage: " +
string_format(_support_pct, 0, 1) + "% (" +
fmt_compact(target.p_pdf[p]) + " of " + fmt_compact(_pdf_cap) + ")"
);

}
garrison_data_slate.draw(344+main_data_slate.width-4, 160, 0.6, 0.6);
}
if (obj_controller.selecting_planet>0){
main_data_slate.draw(344,160, slate_draw_scale, slate_draw_scale+0.1);
}
Expand Down
2 changes: 1 addition & 1 deletion scripts/scr_PlanetData/scr_PlanetData.gml
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ function PlanetData(planet, system) constructor{

// Check for industrial facilities
var fleet_buildable = ((planet_type!="Dead" && planet_type!="Lava") || _has_warboss || _has_stronghold);
if (fleet_buildable && planet_forces[eFACTION.Ork]>=4){// Used to not have Ice either
if (fleet_buildable && planet_forces[eFACTION.Ork]>=4 && pdf < 200000){// Used to not have Ice either

Comment on lines 345 to 348
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Ork shipbuilding gate matches intent, but the threshold is an opaque constant.

Tech-Priest, constraining the ship-forges with pdf < 200000 correctly prevents new Ork fleets once local PDF reaches 200,000 or higher, as the design-chant decrees.

However, the raw literal 200000 obfuscates the rite’s purpose. Would this cogitation be clearer – to future priests and to your own memory – if expressed as a named threshold (or at least commented) indicating “PDF level beyond which Orks cease building ships on this world”, and is it deliberate that only the current planet’s PDF, not system-wide PDF, governs this gate?

if (instance_exists(obj_p_fleet)){
var ppp=instance_nearest(x,y,obj_p_fleet);
Expand Down
2 changes: 0 additions & 2 deletions scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ function scr_enemy_ai_c() {

// Orks spread
orks_end_turn_growth();


// traitors below here
i=0;
if array_sum(p_traitors){
Expand Down
Loading