From 7b5655e11b16e24701e8157424e2757cdc9b3e96 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 16 Jun 2026 23:13:33 +0300 Subject: [PATCH 001/140] "Add Imperial Guard auxilia and land-battle combatants --- objects/obj_ini/Create_0.gml | 2 + objects/obj_ncombat/Alarm_0.gml | 43 ++++++ scripts/scr_cheatcode/scr_cheatcode.gml | 19 +++ .../scr_ini_ship_cleanup.gml | 2 + .../scr_player_ship_functions.gml | 129 ++++++++++++++++++ 5 files changed, 195 insertions(+) diff --git a/objects/obj_ini/Create_0.gml b/objects/obj_ini/Create_0.gml index 1babe4f885..cda84a928b 100644 --- a/objects/obj_ini/Create_0.gml +++ b/objects/obj_ini/Create_0.gml @@ -94,6 +94,8 @@ ship_capacity = []; ship_carrying = []; ship_contents = []; ship_turrets = []; +ship_guardsmen = []; // Imperial Guard auxilia currently embarked on this ship +ship_guardsmen_max = []; // Max Guard auxilia this ship hull can carry ship_lost = []; // Vehicle Init diff --git a/objects/obj_ncombat/Alarm_0.gml b/objects/obj_ncombat/Alarm_0.gml index 7657a4bc4f..09e541de93 100644 --- a/objects/obj_ncombat/Alarm_0.gml +++ b/objects/obj_ncombat/Alarm_0.gml @@ -3154,6 +3154,49 @@ try { u.sprite_index = spr_weapon_blank; } + // ===== Friendly Imperial Guard / PDF on the player's side ===== + // Mirrors the enemy "Imperial Guard Force" spawn, but as obj_pnunit (player side). + // Fires only on an ordinary DEFENSIVE planetary battle where you are not at War + // with the Imperium and the attacker is not the Guard themselves. The model + // counts are read from the planet's p_guardsmen / p_pdf pools, which the deploy + // patch fills. "Imperial Guardsman" and "Leman Russ Battle Tank" are existing + // battlefield profiles, so no new unit content is needed. + if ((defending == true) && (enemy != 2) && (battle_special == "") && (battle_object != 0) + && (obj_controller.faction_status[eFACTION.IMPERIUM] != "War")) { + + var _gd = battle_object.p_guardsmen[battle_id]; + var _pdf = battle_object.p_pdf[battle_id]; + + // Friendly Guardsmen, plus armour if the garrison is large. + if (_gd > 0) { + var _guar = _gd / 10; + u = instance_create(-60, 240, obj_pnunit); + u.dudes[1] = "Imperial Guardsman"; + u.dudes_num[1] = max(1, round(_guar / 5)); + if (_gd > 20000) { + u.dudes[2] = "Leman Russ Battle Tank"; + u.dudes_num[2] = max(1, round(_gd / 20000)); + } + } + + // Friendly PDF: a lighter levy. Reuses the Guardsman profile in fewer numbers. + if (_pdf > 0) { + u = instance_create(-70, 240, obj_pnunit); + u.dudes[1] = "Imperial Guardsman"; + u.dudes_num[1] = max(1, round((_pdf / 10) / 8)); + } + + // Anti-farm: committing the garrison to a pitched battle costs lives, so a + // share is spent each fight. This drains the pool you would otherwise reuse + // for free. Tune the 0.2, or move to outcome-based attrition in Alarm_5. + if (_gd > 0) battle_object.p_guardsmen[battle_id] = max(0, _gd - round(_gd * 0.2)); + if (_pdf > 0) battle_object.p_pdf[battle_id] = max(0, _pdf - round(_pdf * 0.2)); + + // The real units now stand in for that force, so clear the abstract allies + // bonus to avoid counting the same Guard twice. + allies = 0; + } + instance_activate_object(obj_enunit); } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); diff --git a/scripts/scr_cheatcode/scr_cheatcode.gml b/scripts/scr_cheatcode/scr_cheatcode.gml index 1fa8da2127..439289bf45 100644 --- a/scripts/scr_cheatcode/scr_cheatcode.gml +++ b/scripts/scr_cheatcode/scr_cheatcode.gml @@ -41,6 +41,25 @@ function scr_cheatcode(argument0) { if (cheat_code != "") { switch (cheat_code) { + case "embarkguard": + with (obj_controller) { + var _n = embark_guardsmen(obj_ini.home_name, obj_ini.home_planet); + show_message("Embarked " + string(_n) + " Guard from your homeworld.#Total embarked: " + string(player_guardsmen_embarked())); + } + break; + case "deployguard": + with (obj_controller) { + var _n = deploy_guardsmen(obj_ini.home_name, obj_ini.home_planet); + show_message("Deployed " + string(_n) + " Guard onto your homeworld."); + } + break; + case "titheguard": + with (obj_controller) { + var _amt = real(cheat_arguments[0]); + var _n = tithe_guardsmen(obj_ini.home_name, obj_ini.home_planet, _amt); + show_message("Raised " + string(_n) + " Guard from your homeworld's population."); + } + break; case "finishforge": with (obj_controller) { specialist_point_handler.forge_points = 1000000; diff --git a/scripts/scr_ini_ship_cleanup/scr_ini_ship_cleanup.gml b/scripts/scr_ini_ship_cleanup/scr_ini_ship_cleanup.gml index b11957a0a6..e60b9dca76 100644 --- a/scripts/scr_ini_ship_cleanup/scr_ini_ship_cleanup.gml +++ b/scripts/scr_ini_ship_cleanup/scr_ini_ship_cleanup.gml @@ -99,6 +99,8 @@ function scr_kill_ship(index) { array_delete(ship_carrying, index, 1); array_delete(ship_contents, index, 1); array_delete(ship_turrets, index, 1); + array_delete(ship_guardsmen, index, 1); + array_delete(ship_guardsmen_max, index, 1); if (!in_warp) { if (_nearest_star != "none") { diff --git a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml index 7e34b63ed8..8964092127 100644 --- a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml +++ b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml @@ -143,6 +143,8 @@ function new_player_ship_defaults() { array_push(ship_carrying, 0); array_push(ship_contents, ""); array_push(ship_turrets, 0); + array_push(ship_guardsmen, 0); + array_push(ship_guardsmen_max, 0); } return array_length(obj_ini.ship) - 1; } @@ -286,6 +288,8 @@ function new_player_ship(type, start_loc = "home", new_name = "") { obj_ini.ship_wep_facing[index][5] = "most"; obj_ini.ship_wep_condition[index][5] = ""; obj_ini.ship_capacity[index] = 600; + obj_ini.ship_guardsmen_max[index] = 500000; // Battle Barge: Guard auxilia capacity + obj_ini.ship_guardsmen[index] = 0; obj_ini.ship_carrying[index] = 0; obj_ini.ship_contents[index] = ""; obj_ini.ship_turrets[index] = 3; @@ -315,6 +319,8 @@ function new_player_ship(type, start_loc = "home", new_name = "") { obj_ini.ship_wep_facing[index][4] = "most"; obj_ini.ship_wep_condition[index][4] = ""; obj_ini.ship_capacity[index] = 250; + obj_ini.ship_guardsmen_max[index] = 150000; // Strike Cruiser: Guard auxilia capacity + obj_ini.ship_guardsmen[index] = 0; obj_ini.ship_carrying[index] = 0; obj_ini.ship_contents[index] = ""; obj_ini.ship_turrets[index] = 1; @@ -334,6 +340,8 @@ function new_player_ship(type, start_loc = "home", new_name = "") { obj_ini.ship_wep_facing[index][1] = "most"; obj_ini.ship_wep_condition[index][1] = ""; obj_ini.ship_capacity[index] = 30; + obj_ini.ship_guardsmen_max[index] = 0; // Gladius escort: no Guard capacity + obj_ini.ship_guardsmen[index] = 0; obj_ini.ship_carrying[index] = 0; obj_ini.ship_contents[index] = ""; obj_ini.ship_turrets[index] = 1; @@ -356,6 +364,8 @@ function new_player_ship(type, start_loc = "home", new_name = "") { obj_ini.ship_wep_facing[index][2] = "most"; obj_ini.ship_wep_condition[index][2] = ""; obj_ini.ship_capacity[index] = 25; + obj_ini.ship_guardsmen_max[index] = 0; // Hunter escort: no Guard capacity + obj_ini.ship_guardsmen[index] = 0; obj_ini.ship_carrying[index] = 0; obj_ini.ship_contents[index] = ""; obj_ini.ship_turrets[index] = 1; @@ -391,6 +401,8 @@ function new_player_ship(type, start_loc = "home", new_name = "") { obj_ini.ship_wep_facing[index][5] = "most"; obj_ini.ship_wep_condition[index][5] = ""; obj_ini.ship_capacity[index] = 800; + obj_ini.ship_guardsmen_max[index] = 1000000; // Gloriana: Guard auxilia capacity + obj_ini.ship_guardsmen[index] = 0; obj_ini.ship_carrying[index] = 0; obj_ini.ship_contents[index] = ""; obj_ini.ship_turrets[index] = 8; @@ -455,3 +467,120 @@ function ship_bombard_score(ship_id) { return _bomb_score; } + +// ===================================================================== +// Imperial Guard Auxilia - player embark / deploy / raise +// Added by mod. Uses the same p_guardsmen planetary force the Imperial +// Navy uses, so deployed Guard plug straight into the ground-war AI. +// ===================================================================== + +/// @description Total Imperial Guard auxilia currently embarked across all player ships. +/// @returns {real} +function player_guardsmen_embarked() { + var _total = 0; + with (obj_ini) { + for (var i = 0; i < array_length(ship_guardsmen); i++) { + _total += ship_guardsmen[i]; + } + } + return _total; +} + +/// @description Embark Guard from a world you own onto your ships in that system. +/// Pulls from the planet garrison (p_guardsmen) and fills each ship up +/// to its ship_guardsmen_max. Returns the number actually loaded. +/// @param {string} system_name Star system name (e.g. obj_ini.home_name) +/// @param {real} planet Planet index in that system (e.g. obj_ini.home_planet) +/// @returns {real} +function embark_guardsmen(system_name, planet) { + var _star = find_star_by_name(system_name); + if (_star == "none") { + return 0; + } + if (_star.p_owner[planet] != eFACTION.PLAYER) { + return 0; // only from worlds you control + } + + var _pdata = new PlanetData(planet, _star); + var _available = _pdata.guardsmen; + if (_available <= 0) { + return 0; // nothing garrisoned to pick up + } + + var _loaded = 0; + with (obj_ini) { + for (var i = 0; i < array_length(ship); i++) { + if (ship[i] == "") continue; // empty roster slot + if (ship_location[i] != system_name) continue; // ship must be here + var _space = ship_guardsmen_max[i] - ship_guardsmen[i]; + if (_space <= 0) continue; // no hull room (escorts = 0) + var _take = min(_space, _available - _loaded); + if (_take <= 0) break; + ship_guardsmen[i] += _take; + _loaded += _take; + if (_loaded >= _available) break; + } + } + + _pdata.edit_guardsmen(-_loaded); // remove what we embarked from the planet + return _loaded; +} + +/// @description Deploy all embarked Guard from your ships in a system onto a planet. +/// Adds them to p_guardsmen so the ground-war AI fields them. +/// @param {string} system_name Star system the fleet is in +/// @param {real} planet Planet index to garrison +/// @returns {real} +function deploy_guardsmen(system_name, planet) { + var _star = find_star_by_name(system_name); + if (_star == "none") { + return 0; + } + + var _unloaded = 0; + with (obj_ini) { + for (var i = 0; i < array_length(ship); i++) { + if (ship[i] == "") continue; + if (ship_location[i] != system_name) continue; + if (ship_guardsmen[i] <= 0) continue; + _unloaded += ship_guardsmen[i]; + ship_guardsmen[i] = 0; + } + } + if (_unloaded <= 0) { + return 0; + } + + var _pdata = new PlanetData(planet, _star); + _pdata.edit_guardsmen(_unloaded); + return _unloaded; +} + +/// @description OPTIONAL: raise fresh Guard from a controlled world's population, +/// adding them to that world's garrison so you can then embark them. +/// Mirrors the Imperial Navy recruit idiom, so it is safe on both +/// "small" and "large" population worlds. +/// @param {string} system_name +/// @param {real} planet +/// @param {real} amount headcount of Guard to raise +/// @returns {real} +function tithe_guardsmen(system_name, planet, amount) { + var _star = find_star_by_name(system_name); + if (_star == "none") { + return 0; + } + if (_star.p_owner[planet] != eFACTION.PLAYER) { + return 0; + } + + var _pdata = new PlanetData(planet, _star); + var _headcount = _pdata.population_as_small(); + if (_headcount <= 0) { + return 0; + } + + amount = min(amount, _headcount); + _pdata.edit_population(-_pdata.population_large_conversion(amount)); + _pdata.edit_guardsmen(amount); + return amount; +} From 30f108f4ea84cde2b76fc7a4dc38efbf21b29f46 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 17 Jun 2026 19:48:54 +0300 Subject: [PATCH 002/140] Added imperial guardsmen 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. --- ChapterMaster.yyp | 6 - objects/obj_al_ship/Step_0.gml | 2 +- objects/obj_controller/Alarm_1.gml | 2 +- objects/obj_controller/Alarm_5.gml | 12 +- objects/obj_controller/Create_0.gml | 10 +- objects/obj_controller/Draw_64.gml | 2 +- objects/obj_controller/Mouse_50.gml | 10 +- objects/obj_controller/Step_0.gml | 27 +- objects/obj_creation/Create_0.gml | 2 - objects/obj_creation/Draw_0.gml | 36 +- objects/obj_en_ship/Step_0.gml | 2 +- objects/obj_enunit/Alarm_0.gml | 39 +- objects/obj_fleet/Alarm_5.gml | 2 +- objects/obj_fleet/Draw_64.gml | 2 +- objects/obj_fleet/KeyPress_13.gml | 2 +- objects/obj_fleet/Mouse_56.gml | 9 +- objects/obj_ncombat/Alarm_0.gml | 99 ++- objects/obj_ncombat/Create_0.gml | 2 + objects/obj_pnunit/Alarm_3.gml | 6 +- objects/obj_pnunit/Create_0.gml | 1 + objects/obj_star_select/Draw_64.gml | 7 + rooms/rm_testing_half/rm_testing_half.yy | 252 +----- rooms/rm_testing_new/rm_testing_new.yy | 746 +----------------- scripts/Armamentarium/Armamentarium.gml | 2 + scripts/ErrorHandler/ErrorHandler.gml | 3 + scripts/NameGenerator/NameGenerator.gml | 13 +- scripts/scr_cheatcode/scr_cheatcode.gml | 14 +- scripts/scr_clean/scr_clean.gml | 55 ++ .../scr_drop_select_function.gml | 18 + scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml | 4 +- .../scr_fleet_advisor/scr_fleet_advisor.gml | 6 +- scripts/scr_garrison/scr_garrison.gml | 81 +- .../scr_player_combat_weapon_stacks.gml | 51 ++ .../scr_player_ship_functions.gml | 15 + scripts/scr_ui_settings/scr_ui_settings.gml | 2 +- scripts/scr_unit_traits/scr_unit_traits.gml | 4 +- 36 files changed, 348 insertions(+), 1198 deletions(-) diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index 7452534f65..bdd1e3318e 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -22,7 +22,6 @@ {"$GMFolder":"","%Name":"Objects","folderPath":"folders/Objects.yy","name":"Objects","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Combat_Fleet","folderPath":"folders/Objects/Combat_Fleet.yy","name":"Combat_Fleet","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"New Combat","folderPath":"folders/Objects/New Combat.yy","name":"New Combat","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"New Ground","folderPath":"folders/Objects/New Ground.yy","name":"New Ground","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"New UI","folderPath":"folders/Objects/New UI.yy","name":"New UI","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Temp","folderPath":"folders/Objects/Temp.yy","name":"Temp","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Paths","folderPath":"folders/Paths.yy","name":"Paths","resourceType":"GMFolder","resourceVersion":"2.0",}, @@ -657,7 +656,6 @@ {"id":{"name":"obj_en_pulse","path":"objects/obj_en_pulse/obj_en_pulse.yy",},}, {"id":{"name":"obj_en_round","path":"objects/obj_en_round/obj_en_round.yy",},}, {"id":{"name":"obj_en_ship","path":"objects/obj_en_ship/obj_en_ship.yy",},}, - {"id":{"name":"obj_enemy_leftest","path":"objects/obj_enemy_leftest/obj_enemy_leftest.yy",},}, {"id":{"name":"obj_enunit","path":"objects/obj_enunit/obj_enunit.yy",},}, {"id":{"name":"obj_event_log","path":"objects/obj_event_log/obj_event_log.yy",},}, {"id":{"name":"obj_event","path":"objects/obj_event/obj_event.yy",},}, @@ -677,12 +675,10 @@ {"id":{"name":"obj_main_menu_buttons","path":"objects/obj_main_menu_buttons/obj_main_menu_buttons.yy",},}, {"id":{"name":"obj_main_menu","path":"objects/obj_main_menu/obj_main_menu.yy",},}, {"id":{"name":"obj_managment_panel","path":"objects/obj_managment_panel/obj_managment_panel.yy",},}, - {"id":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},}, {"id":{"name":"obj_mass_equip","path":"objects/obj_mass_equip/obj_mass_equip.yy",},}, {"id":{"name":"obj_ncombat","path":"objects/obj_ncombat/obj_ncombat.yy",},}, {"id":{"name":"obj_new_button","path":"objects/obj_new_button/obj_new_button.yy",},}, {"id":{"name":"obj_nfort","path":"objects/obj_nfort/obj_nfort.yy",},}, - {"id":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},}, {"id":{"name":"obj_p_assra","path":"objects/obj_p_assra/obj_p_assra.yy",},}, {"id":{"name":"obj_p_capital","path":"objects/obj_p_capital/obj_p_capital.yy",},}, {"id":{"name":"obj_p_cruiser","path":"objects/obj_p_cruiser/obj_p_cruiser.yy",},}, @@ -692,8 +688,6 @@ {"id":{"name":"obj_p_ship","path":"objects/obj_p_ship/obj_p_ship.yy",},}, {"id":{"name":"obj_p_small","path":"objects/obj_p_small/obj_p_small.yy",},}, {"id":{"name":"obj_p_th","path":"objects/obj_p_th/obj_p_th.yy",},}, - {"id":{"name":"obj_p1_bullet_miss","path":"objects/obj_p1_bullet_miss/obj_p1_bullet_miss.yy",},}, - {"id":{"name":"obj_p1_bullet","path":"objects/obj_p1_bullet/obj_p1_bullet.yy",},}, {"id":{"name":"obj_persistent","path":"objects/obj_persistent/obj_persistent.yy",},}, {"id":{"name":"obj_planet_map","path":"objects/obj_planet_map/obj_planet_map.yy",},}, {"id":{"name":"obj_pnunit","path":"objects/obj_pnunit/obj_pnunit.yy",},}, diff --git a/objects/obj_al_ship/Step_0.gml b/objects/obj_al_ship/Step_0.gml index 622e5d87f3..d175fa43de 100644 --- a/objects/obj_al_ship/Step_0.gml +++ b/objects/obj_al_ship/Step_0.gml @@ -75,7 +75,7 @@ if (owner != 6) { } } if (owner == eFACTION.TYRANIDS) { - effect_create_above(ef_firework, x, y, 1, c_purple); + effect_create_depth(depth - 1, ef_firework, x, y, 1, c_purple); } instance_destroy(); } diff --git a/objects/obj_controller/Alarm_1.gml b/objects/obj_controller/Alarm_1.gml index ff536028b9..0c5b7673d7 100644 --- a/objects/obj_controller/Alarm_1.gml +++ b/objects/obj_controller/Alarm_1.gml @@ -503,7 +503,7 @@ if (did != 0) { // Eldar craftworld here -var go = 0, xx = 0, yy = 0; +var go = 0; craftworld = 1; diff --git a/objects/obj_controller/Alarm_5.gml b/objects/obj_controller/Alarm_5.gml index 25717813e6..e68d7e6c36 100644 --- a/objects/obj_controller/Alarm_5.gml +++ b/objects/obj_controller/Alarm_5.gml @@ -8,13 +8,12 @@ try { var marine_company = 0; var warn = "", w5 = 0; var g1 = 0, g2 = 0; - var onceh = 0, stahp = 0; + var stahp = 0; var disc = 0, droll = 0; var rund = 0; var spikky = 0; var roll = 0; var novice_type = ""; - var unit; var times = max(1, round(turn / 150)); if ((known[eFACTION.CHAOS] == 2) && (faction_defeated[eFACTION.CHAOS] == 0)) { @@ -88,10 +87,8 @@ try { var recruits_finished = 0, recruit_first = ""; var total_recruits = 0; - var i = 0; - while (i < array_length(recruit_name)) { + for (var i = array_length(recruit_name) - 1; i >= 0; i--) { if (recruit_name[i] == "") { - i++; continue; } if (recruit_distance[i] <= 0) { @@ -113,7 +110,6 @@ try { } else { total_recruits++; } - i++; } with (obj_ini) { scr_company_order(10); @@ -299,11 +295,11 @@ try { } } } - var p = 0, penitorium = 0, unit; + var p = 0, penitorium = 0; for (var c = 0; c < 11; c++) { for (var e = 0; e < array_length(obj_ini.god[c]); e++) { if (obj_ini.god[c][e] == 10) { - unit = fetch_unit([c, e]); + var unit = fetch_unit([c, e]); p += 1; penit_co[p] = c; penit_id[p] = e; diff --git a/objects/obj_controller/Create_0.gml b/objects/obj_controller/Create_0.gml index 9be954c467..245f81806a 100644 --- a/objects/obj_controller/Create_0.gml +++ b/objects/obj_controller/Create_0.gml @@ -359,8 +359,6 @@ y_slide = 0; new_banner_x = 0; hide_banner = 0; // ui stuff -var xx = camera_get_view_x(view_camera[0]); -var yy = camera_get_view_y(view_camera[0]); menu_lock = false; menu_buttons = { "chapter_manage": new MainMenuButton(spr_ui_but_1, spr_ui_hov_1,,, ord("M"), scr_toggle_manage), @@ -1217,7 +1215,7 @@ if (global.load >= 0) { ///! ************************************************************ */ ///! ************************************************************ */ -var xx, yy, me, dist, go, planet; +var me, dist, go, planet; global.custom = eCHAPTER_TYPE.RANDOM; // ** Sets up base training level and trainees at game start ** @@ -1330,11 +1328,11 @@ if (is_test_map == true) { planet = 20; } -var xx, yy, nearest_star, repeats; +var nearest_star, repeats; mask_index = spr_star; while (instance_number(obj_star) < planet) { - xx = irandom_range(200, room_width - 150); // dictates how far away from the edge stars spawn - yy = irandom_range(130, room_height - 130); + var xx = irandom_range(200, room_width - 150); // dictates how far away from the edge stars spawn + var yy = irandom_range(130, room_height - 130); nearest_star = instance_nearest(xx, yy, obj_star); repeats = 0; while (point_distance(xx, yy, nearest_star.x, nearest_star.y) < 130 && repeats < 100) { diff --git a/objects/obj_controller/Draw_64.gml b/objects/obj_controller/Draw_64.gml index acc7320b48..96f77dc779 100644 --- a/objects/obj_controller/Draw_64.gml +++ b/objects/obj_controller/Draw_64.gml @@ -248,7 +248,7 @@ function draw_line(x1, y1, y_slide, variable) { l_why = min(variable - 96, 11); } - draw_line(view_xview[0] + variable + x1, view_yview[0] + 10 + 1 + l_why, view_xview[0] + variable + x1, view_yview[0] + 10 + 37 - l_why); + draw_line(view_xport[0] + variable + x1, view_yport[0] + 11 + l_why, view_xport[0] + variable + x1, view_yport[0] + 47 - l_why); } } diff --git a/objects/obj_controller/Mouse_50.gml b/objects/obj_controller/Mouse_50.gml index 3c2f274989..532aac4372 100644 --- a/objects/obj_controller/Mouse_50.gml +++ b/objects/obj_controller/Mouse_50.gml @@ -215,10 +215,9 @@ if ((zoomed == 0) && (cooldown <= 0) && (menu == eMENU.DIPLOMACY) && (diplomacy // End Turn scr_menu_clear_up(function() { + var xx = camera_get_view_x(view_camera[0]); + var yy = camera_get_view_y(view_camera[0]); if ((zoomed == 0) && (menu == 40) && (cooldown <= 0)) { - xx = xx + 0; - yy = yy + 0; - if ((mouse_x >= xx + 73) && (mouse_y >= yy + 69) && (mouse_x < xx + 305) && (mouse_y < yy + 415)) { menu = 41; cooldown = 8000; @@ -231,9 +230,6 @@ scr_menu_clear_up(function() { // This is the back button at LOADING TO SHIPS if ((zoomed == 0) && (menu == 30) && (managing > 0 || managing == -1) && (cooldown <= 0)) { - xx = xx + 0; - yy = yy + 0; - if ((mouse_x >= xx + 22) && (mouse_y >= yy + 84) && (mouse_x < xx + 98) && (mouse_y < yy + 126)) { menu = eMENU.MANAGE; cooldown = 8000; @@ -243,8 +239,6 @@ scr_menu_clear_up(function() { if ((menu == eMENU.MANAGE) && (managing > 0) || (managing < 0) && (!view_squad || !company_report)) { var unit; var eventing = false, bb = ""; - xx = camera_get_view_x(view_camera[0]); - yy = camera_get_view_y(view_camera[0]); var top = man_current, sel, temp1 = "", temp2 = "", temp3 = "", temp4 = "", temp5 = "", squad_sel = 0; var stop = 0; diff --git a/objects/obj_controller/Step_0.gml b/objects/obj_controller/Step_0.gml index 82a792b30e..79ee3aacd4 100644 --- a/objects/obj_controller/Step_0.gml +++ b/objects/obj_controller/Step_0.gml @@ -372,26 +372,6 @@ try { exit; } // Default view - if (menu == 1 && (managing > 0 || managing < 0)) { - if (!view_squad) { - var c = 0, fx = ""; - var bb = ""; - var xx = camera_get_view_x(view_camera[0]); - var yy = camera_get_view_y(view_camera[0]); - - if (managing <= 10) { - c = managing; - } - if (managing > 20) { - c = managing - 10; - } - - var top, sel, temp1 = "", temp2 = "", temp3 = "", temp4 = "", temp5 = "", force_tool = 0; - top = man_current; - sel = top; - yy += 77; - } - } if (global.load >= 0) { exit; @@ -476,21 +456,20 @@ try { cooldown = 8; var b = selecting_ship; - var unit, company, unit_id; for (var q = 0; q < array_length(display_unit); q++) { if ((man[q] == "man") && (ma_loc[q] == selecting_location) && (ma_wid[q] < 1) && (man_sel[q] != 0)) { if (b == -1) { b = ma_lid[q]; } - unit = display_unit[q]; + var unit = display_unit[q]; if (!is_struct(unit)) { continue; } if (unit.name() == "") { continue; } - unit_id = unit.marine_number; - company = unit.company; + var unit_id = unit.marine_number; + var company = unit.company; unit.location_string = obj_ini.ship_location[b]; unit.ship_location = -1; unit.planet_location = unload; diff --git a/objects/obj_creation/Create_0.gml b/objects/obj_creation/Create_0.gml index 1e1f99ebfe..fa45f5d93f 100644 --- a/objects/obj_creation/Create_0.gml +++ b/objects/obj_creation/Create_0.gml @@ -150,8 +150,6 @@ cooperation = 5; purity = 5; stability = 90; -var i = 9; - homeworld = "Temperate"; homeworld_name = global.name_generator.GenerateFromSet("star", false); recruiting = "Death"; diff --git a/objects/obj_creation/Draw_0.gml b/objects/obj_creation/Draw_0.gml index 373aff4b86..a8ecc0d4e8 100644 --- a/objects/obj_creation/Draw_0.gml +++ b/objects/obj_creation/Draw_0.gml @@ -4,9 +4,8 @@ try { //read // 850,860 - var xx, yy; - xx = 375; - yy = 10; + var xx = 375; + var yy = 10; tooltip = ""; tooltip2 = ""; @@ -17,7 +16,7 @@ try { // draw_sprite(spr_creation_slate,1,xx,yy); scr_image("creation/slate", 2, xx, yy, 850, 860); - draw_set_color(5998382); + draw_set_color(#5B872E); if (slate2 > 0) { if (slate2 <= 10) { draw_set_alpha(slate2 / 10); @@ -47,9 +46,6 @@ try { } } - var yar; - yar = 0; - if (slide >= 2) { tooltip = ""; tooltip2 = ""; @@ -66,7 +62,7 @@ try { draw_rectangle(0, 68, 374, 781, 1); } - draw_set_color(0); + draw_set_color(c_black); var sprx = 436, spry = 74, sprw = 128, sprh = 128; if (sprite_exists(global.chapter_icon.sprite)) { @@ -419,8 +415,6 @@ try { draw_set_font(fnt_40k_30b); draw_set_halign(fa_center); draw_set_alpha(1); - var yar; - yar = 0; tooltip = ""; tooltip2 = ""; @@ -515,13 +509,7 @@ try { if (melee_choice_order == 8) { melee_choice_weapon = "Force Staff"; } - - yar = 0; - if (chapter_master_melee == melee_choice_order) { - yar = 1; - } - draw_sprite(spr_creation_check, yar, x6, y6); - yar = 0; + draw_sprite(spr_creation_check, (chapter_master_melee == melee_choice_order), x6, y6); if (point_and_click([x6, y6, x6 + 32, y6 + 32]) && (custom != eCHAPTER_TYPE.PREMADE) && (restarted == 0) && (!instance_exists(obj_creation_popup))) { var onceh; onceh = 0; @@ -559,12 +547,7 @@ try { } repeat (7) { ranged_choice_order += 1; - yar = 0; - if (chapter_master_ranged == ranged_choice_order) { - yar = 1; - } - draw_sprite(spr_creation_check, yar, x6, y6); - yar = 0; + draw_sprite(spr_creation_check, (chapter_master_ranged == ranged_choice_order), x6, y6); if (point_and_click([x6, y6, x6 + 32, y6 + 32]) && (custom != eCHAPTER_TYPE.PREMADE) && (restarted == 0) && (!instance_exists(obj_creation_popup)) && (!array_contains([1, 2, 7], chapter_master_melee))) { var onceh = 0; if (chapter_master_ranged == ranged_choice_order) { @@ -682,7 +665,6 @@ try { // 850,860 - var xx, yy; xx = 375; yy = 10; @@ -707,7 +689,7 @@ try { draw_rectangle(518, 750, 1075, 820, 0); } - draw_set_color(5998382); + draw_set_color(#5B872E); if (slate5 > 0) { if (slate5 <= 30) { draw_set_alpha(slate5 / 30); @@ -729,7 +711,7 @@ try { if (fade_in > 0) { draw_set_alpha(fade_in / 50); - draw_set_color(0); + draw_set_color(c_black); draw_rectangle(0, 0, room_width, room_height, 0); } draw_set_alpha(1); @@ -842,7 +824,7 @@ try { if (tooltip != "" && tooltip2 != "" && change_slide <= 0) { draw_set_alpha(1); - draw_set_color(0); + draw_set_color(c_black); draw_set_halign(fa_left); draw_set_font(fnt_40k_14b); var _width1 = string_width_ext(string_hash_to_newline(tooltip), -1, 500); diff --git a/objects/obj_en_ship/Step_0.gml b/objects/obj_en_ship/Step_0.gml index 1740f86e27..b5987450da 100644 --- a/objects/obj_en_ship/Step_0.gml +++ b/objects/obj_en_ship/Step_0.gml @@ -83,7 +83,7 @@ if (owner != 6) { } } if (owner == eFACTION.TYRANIDS) { - effect_create_above(ef_firework, x, y, 1, c_purple); + effect_create_depth(depth - 1, ef_firework, x, y, 1, c_purple); } instance_destroy(); } diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index be08d7c742..96a4f17d48 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -94,22 +94,29 @@ if (!engaged) { scr_shoot(i, enemy, target_unit_index, "arp", "ranged"); // LOGGER.debug($"I'm shooting at a vehicle! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); continue; - } else if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != 7)) { - var x2 = enemy.x; - repeat (instance_number(obj_pnunit) - 1) { - x2 += flank == 0 ? -10 : 10; - var enemy2 = instance_nearest(x2, y, obj_pnunit); - if (!target_block_is_valid(enemy2, obj_pnunit)) { - continue; - } - if (range[i] < get_block_distance(enemy2)) { - break; - } - if (block_has_armour(enemy2)) { - scr_shoot(i, enemy2, target_unit_index, "arp", "ranged"); - // LOGGER.debug($"I'm shooting at a vehicle in another row! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); - _shot = true; - break; + } else { + // Front block has no armour. If there are other blocks behind, + // look for a vehicle to hit. If none is found anywhere (including + // a single men-only block, such as a lone Guard rank), fall back + // to shooting the men instead of idling. The original code gated + // this whole fallback behind a multi-block check, so a lone + // men-only block left every AP weapon firing zero shots. + if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != 7)) { + var x2 = enemy.x; + repeat (instance_number(obj_pnunit) - 1) { + x2 += flank == 0 ? -10 : 10; + var enemy2 = instance_nearest(x2, y, obj_pnunit); + if (!target_block_is_valid(enemy2, obj_pnunit)) { + continue; + } + if (range[i] < get_block_distance(enemy2)) { + break; + } + if (block_has_armour(enemy2)) { + scr_shoot(i, enemy2, target_unit_index, "arp", "ranged"); + _shot = true; + break; + } } } if (!_shot) { diff --git a/objects/obj_fleet/Alarm_5.gml b/objects/obj_fleet/Alarm_5.gml index aad308555b..afab278577 100644 --- a/objects/obj_fleet/Alarm_5.gml +++ b/objects/obj_fleet/Alarm_5.gml @@ -1,3 +1,3 @@ if (combat_end == 170) { - room_speed = 30; + game_set_speed(30, gamespeed_fps); } diff --git a/objects/obj_fleet/Draw_64.gml b/objects/obj_fleet/Draw_64.gml index 8b160d2e61..436410a156 100644 --- a/objects/obj_fleet/Draw_64.gml +++ b/objects/obj_fleet/Draw_64.gml @@ -50,7 +50,7 @@ if (start == 0) { } // fast forward icon -if (room_speed != 90 && start == 5) { +if (gamespeed_fps != 90 && start == 5) { draw_set_alpha(1); var _ff_h = sprite_get_height(spr_fast_forward); draw_sprite(spr_fast_forward, 0, 12, (_surface_h / 2) - (_ff_h / 2)); diff --git a/objects/obj_fleet/KeyPress_13.gml b/objects/obj_fleet/KeyPress_13.gml index a9a62a86db..81251612c9 100644 --- a/objects/obj_fleet/KeyPress_13.gml +++ b/objects/obj_fleet/KeyPress_13.gml @@ -6,7 +6,7 @@ if (obj_controller.cooldown <= 0) { if (start == 7) { // End battle crap here instance_activate_all(); - room_speed = 30; + game_set_speed(30, gamespeed_fps); alarm[7] = 1; } } diff --git a/objects/obj_fleet/Mouse_56.gml b/objects/obj_fleet/Mouse_56.gml index cb4d296f66..0765ef3893 100644 --- a/objects/obj_fleet/Mouse_56.gml +++ b/objects/obj_fleet/Mouse_56.gml @@ -40,13 +40,14 @@ if (instance_exists(obj_p_ship) && (control == 1)) { } } +//Why is this here? if ((start == 5) && (obj_controller.zoomed == 0)) { - if ((mouse_x >= camera_get_view_x(view_camera[0]) + 12) && (mouse_y >= camera_get_view_y(view_camera[0]) + 436) && (mouse_x < camera_get_view_x(view_camera[0]) + 48) && (mouse_y < camera_get_view_y(view_camera[0]) + 480) && (room_speed < 90)) { - room_speed += 30; + if ((mouse_x >= camera_get_view_x(view_camera[0]) + 12) && (mouse_y >= camera_get_view_y(view_camera[0]) + 436) && (mouse_x < camera_get_view_x(view_camera[0]) + 48) && (mouse_y < camera_get_view_y(view_camera[0]) + 480) && (gamespeed_fps < 90)) { + game_set_speed(game_get_speed(gamespeed_fps) + 30, gamespeed_fps); } } if ((start == 5) && (obj_controller.zoomed == 1)) { - if ((mouse_x > 24) && (mouse_y > 872) && (mouse_x < 90) && (mouse_y < 960) && (room_speed < 90)) { - room_speed += 30; + if ((mouse_x > 24) && (mouse_y > 872) && (mouse_x < 90) && (mouse_y < 960) && (gamespeed_fps < 90)) { + game_set_speed(game_get_speed(gamespeed_fps) + 30, gamespeed_fps); } } diff --git a/objects/obj_ncombat/Alarm_0.gml b/objects/obj_ncombat/Alarm_0.gml index 09e541de93..ce0fced4fe 100644 --- a/objects/obj_ncombat/Alarm_0.gml +++ b/objects/obj_ncombat/Alarm_0.gml @@ -3154,47 +3154,66 @@ try { u.sprite_index = spr_weapon_blank; } - // ===== Friendly Imperial Guard / PDF on the player's side ===== - // Mirrors the enemy "Imperial Guard Force" spawn, but as obj_pnunit (player side). - // Fires only on an ordinary DEFENSIVE planetary battle where you are not at War - // with the Imperium and the attacker is not the Guard themselves. The model - // counts are read from the planet's p_guardsmen / p_pdf pools, which the deploy - // patch fills. "Imperial Guardsman" and "Leman Russ Battle Tank" are existing - // battlefield profiles, so no new unit content is needed. - if ((defending == true) && (enemy != 2) && (battle_special == "") && (battle_object != 0) - && (obj_controller.faction_status[eFACTION.IMPERIUM] != "War")) { - - var _gd = battle_object.p_guardsmen[battle_id]; - var _pdf = battle_object.p_pdf[battle_id]; - - // Friendly Guardsmen, plus armour if the garrison is large. - if (_gd > 0) { - var _guar = _gd / 10; - u = instance_create(-60, 240, obj_pnunit); - u.dudes[1] = "Imperial Guardsman"; - u.dudes_num[1] = max(1, round(_guar / 5)); - if (_gd > 20000) { - u.dudes[2] = "Leman Russ Battle Tank"; - u.dudes_num[2] = max(1, round(_gd / 20000)); + // ** Set up friendly Imperial Guard auxilia ** + // Bulk player force modelled on the defenses above. Reads the world's deployed + // garrison (p_guardsmen). It renders and is durable via veh blocks; its firepower + // is injected in scr_player_combat_weapon_stacks, scaled to player_guard. No roster + // coupling, so no per-model casualty writes. + player_guard = 0; + if ((battle_object != 0) && (battle_special == "")) { + player_guard = battle_object.p_guardsmen[battle_id]; + } + if (player_guard > 0) { + // Place the Guard in the front column, matching the rightmost existing + // block. Stepping ahead of the line breaks the advance on an attack (they + // march out past the engagement), so they sit in the line and move with it. + var _frontx = -50; + with (obj_pnunit) { + if (x > _frontx) _frontx = x; + } + u = instance_create(_frontx, 240, obj_pnunit); + u.guard = 1; + + // The mass of Guardsmen are men, so they render and take losses per man, + // the same way the enemy Guard do. + u.men = player_guard; + u.dudes[1] = "Imperial Guardsman"; + u.dudes_num[1] = player_guard; + u.dudes_ac[1] = 40; // match the enemy Guardsman: flak armour value 40 + u.dudes_hp[1] = 5; + u.dudes_vehicle[1] = 0; + + // Leman Russ armour for a large garrison: real vehicles, like the enemy's. + var _tanks = min(30, round(player_guard / 5000)); + if (_tanks > 0) { + for (var i = 1; i <= _tanks; i++) { + u.veh_co[i] = 0; + u.veh_id[i] = 0; + u.veh_type[i] = "Leman Russ Battle Tank"; + u.veh_hp[i] = 250; + u.veh_ac[i] = 40; + u.veh_dead[i] = 0; + u.veh_hp_multiplier[i] = 1; + u.veh_wep1[i] = "Battle Cannon"; } - } - - // Friendly PDF: a lighter levy. Reuses the Guardsman profile in fewer numbers. - if (_pdf > 0) { - u = instance_create(-70, 240, obj_pnunit); - u.dudes[1] = "Imperial Guardsman"; - u.dudes_num[1] = max(1, round((_pdf / 10) / 8)); - } - - // Anti-farm: committing the garrison to a pitched battle costs lives, so a - // share is spent each fight. This drains the pool you would otherwise reuse - // for free. Tune the 0.2, or move to outcome-based attrition in Alarm_5. - if (_gd > 0) battle_object.p_guardsmen[battle_id] = max(0, _gd - round(_gd * 0.2)); - if (_pdf > 0) battle_object.p_pdf[battle_id] = max(0, _pdf - round(_pdf * 0.2)); - - // The real units now stand in for that force, so clear the abstract allies - // bonus to avoid counting the same Guard twice. - allies = 0; + u.veh = _tanks; + u.dudes[2] = "Leman Russ Battle Tank"; + u.dudes_num[2] = _tanks; + u.dudes_ac[2] = 40; + u.dudes_hp[2] = 250; + u.dudes_vehicle[2] = 1; + } + // Keep the default obj_pnunit sprite (do not blank it): the block needs its + // collision mask, or the enemy advance walks straight through the Guard + // without stopping to fight, which is what sent the enemy off the screen. + + // Count the Guard toward the battle's player forces. The normal accumulation + // only runs during setup and this block spawns too late for it, so the win/ + // loss check never saw them and the battle ended when the Marines died. Add + // them here; obj_pnunit's Alarm_3 skips its auto-add for guard blocks so this + // is not double counted. + player_forces += u.men + u.veh; + player_max += u.men + u.veh; } instance_activate_object(obj_enunit); diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index 5f685215a1..c96307ee20 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -86,6 +86,7 @@ leader = 0; thirsty = 0; really_thirsty = 0; allies = 0; +player_attack_guard = 0; // embarked Guard committed to an assault from the attacking fleet present_inquisitor = 0; sorcery_seen = 0; inquisitor_ship = 0; @@ -129,6 +130,7 @@ player_forces = 0; player_max = 0; player_defenses = 0; player_silos = 0; +player_guard = 0; enemy_forces = 0; enemy_max = 0; diff --git a/objects/obj_pnunit/Alarm_3.gml b/objects/obj_pnunit/Alarm_3.gml index 488913264b..c14485ab3b 100644 --- a/objects/obj_pnunit/Alarm_3.gml +++ b/objects/obj_pnunit/Alarm_3.gml @@ -5,8 +5,10 @@ try { instance_destroy(); } // if (veh+dreads>0) then instance_destroy(); - obj_ncombat.player_forces += self.men + self.veh + self.dreads; - obj_ncombat.player_max += self.men + self.veh + self.dreads; + if (guard == 0) { + obj_ncombat.player_forces += self.men + self.veh + self.dreads; + obj_ncombat.player_max += self.men + self.veh + self.dreads; + } //TODO centralise a method for moving units between columns /*if (men<=4) and (veh=0) and (dreads=0){// Squish leftt diff --git a/objects/obj_pnunit/Create_0.gml b/objects/obj_pnunit/Create_0.gml index af2c9fb260..92ad072a18 100644 --- a/objects/obj_pnunit/Create_0.gml +++ b/objects/obj_pnunit/Create_0.gml @@ -9,6 +9,7 @@ attacked_dudes = 0; dreads = 0; jetpack_destroy = 0; defenses = 0; +guard = 0; unit_count = 0; unit_count_old = 0; diff --git a/objects/obj_star_select/Draw_64.gml b/objects/obj_star_select/Draw_64.gml index 91208b743d..c7bdc3805e 100644 --- a/objects/obj_star_select/Draw_64.gml +++ b/objects/obj_star_select/Draw_64.gml @@ -306,6 +306,10 @@ try { if (obj_controller.selecting_planet > 0) { main_data_slate.draw(344, 160, slate_draw_scale, slate_draw_scale + 0.1); } + // Deploy Guard auxilia: offer the 4th slot when guard-carrying ships orbit this world. + if ((button4 == "") && (obj_controller.selecting_planet > 0) && (player_guardsmen_at(target.name) > 0)) { + button4 = "Deploy Guard"; + } var current_button = ""; var shutter_x = main_data_slate.XX - 165; var shutter_y = 296 + 165; @@ -376,6 +380,9 @@ try { } } } + } else if (current_button == "Deploy Guard") { + var _n = deploy_guardsmen(target.name, obj_controller.selecting_planet); + scr_popup("Imperial Guard", "Deployed " + string(_n) + " Guard onto " + planet_numeral_name(obj_controller.selecting_planet, target) + ".", ""); } else if (current_button == "+Recruiting") { if (obj_controller.recruiting_worlds_bought > 0 && p_data.current_owner <= 5 && !p_data.at_war()) { if (!p_data.has_feature(eP_FEATURES.RECRUITING_WORLD)) { diff --git a/rooms/rm_testing_half/rm_testing_half.yy b/rooms/rm_testing_half/rm_testing_half.yy index 9b4f3dbe49..92ff448b51 100644 --- a/rooms/rm_testing_half/rm_testing_half.yy +++ b/rooms/rm_testing_half/rm_testing_half.yy @@ -5,258 +5,10 @@ "inheritCode":false, "inheritCreationOrder":false, "inheritLayers":false, - "instanceCreationOrder":[ - {"name":"inst_388035F1","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_D5E41057","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_BB1D114A","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_09923952","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_DF446DDF","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_34FEE099","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_2C87EFF8","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_E02A4953","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_F8CF0E15","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_758D500A","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_5509A666","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_272EA924","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_688E87F2","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_FB07B8CC","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_E150D3CB","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_B6347843","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_055C23CA","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_3FF12B84","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_9C0C3419","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_7853AEB1","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_A8EDEDEF","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_9DE5021D","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_773884FA","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_6F23121B","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_8559002F","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_C6F1A0C2","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_257B03D5","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_95E7C107","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_EB544B1E","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_10852472","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_366D8B6F","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_80F6E1D8","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_BDE0ECC5","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_8224F4CC","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_20DF1E0B","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_F238AB87","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_6697D0EC","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_E223EB40","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_D91A343C","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_EE76140C","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_4D125B1C","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_78F308E8","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_5CDFA987","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_B9D13756","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_6A11A170","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_ECB34A19","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_1E3BD983","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_548EF074","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_09FA2609","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_6DA07E97","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_AB6FE04B","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_C3A5B2E4","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_FA0BA6CF","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_5105EE58","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_0EBA49F9","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_69D4CCEF","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_1576BC5E","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_D3700BC1","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_2A15F823","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_E1BDC14D","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_E3417EC1","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_454C3707","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_3A23E3C8","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_9A73FB61","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_C91C6FA0","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_BE4FE50E","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_1A3362DD","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_0875E5D6","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_E33204DA","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_357D736B","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_553EEFDD","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_63F741EE","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_0A63F7E8","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_80ED5D9F","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_55B41B69","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_B1C6E50D","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_A3C90E04","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_12C4B857","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_53DE12EB","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_AF92DE37","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_CEB29A8E","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_D30FA4FB","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_E0CCE0B8","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_6CE0B413","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_74157AE9","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_BECDE02E","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_16B3E5F0","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_80372912","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_1F53EF6B","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_F0034B9C","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_AF21A2C9","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_97E19425","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_CA7A3670","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_48ED570A","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_2FBE854A","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_EA0A23C0","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_27A10AB4","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_55533EF5","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_23D6570E","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_F5E4A9E2","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_3B7F594A","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_E18BAFD9","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_0FCAC0BE","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_1C7152BB","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_15ACEC8C","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_72BD1C47","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_9FB4C563","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_8B51DEA0","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_96F2BEA0","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_72612F45","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_074026D3","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_A94B0BD3","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_92AB3DF0","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_50511EB7","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_2442E6BE","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_00FF3F46","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_0D3D06EC","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_CE974969","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_09DD0B98","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_21204F1F","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_B6CFA351","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_3DC3B334","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - {"name":"inst_79E7CBAB","path":"rooms/rm_testing_half/rm_testing_half.yy",}, - ], + "instanceCreationOrder":[], "isDnd":false, "layers":[ - {"$GMRInstanceLayer":"","%Name":"Compatibility_Instances_Depth_0","depth":0,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"instances":[ - {"$GMRInstance":"v4","%Name":"inst_388035F1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_388035F1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":336.0,}, - {"$GMRInstance":"v4","%Name":"inst_D5E41057","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D5E41057","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_BB1D114A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BB1D114A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":496.0,}, - {"$GMRInstance":"v4","%Name":"inst_09923952","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_09923952","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":176.0,}, - {"$GMRInstance":"v4","%Name":"inst_DF446DDF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_DF446DDF","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_34FEE099","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_34FEE099","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":176.0,}, - {"$GMRInstance":"v4","%Name":"inst_2C87EFF8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2C87EFF8","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":240.0,}, - {"$GMRInstance":"v4","%Name":"inst_E02A4953","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E02A4953","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_F8CF0E15","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F8CF0E15","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":528.0,}, - {"$GMRInstance":"v4","%Name":"inst_758D500A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_758D500A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_5509A666","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5509A666","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_272EA924","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_272EA924","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":304.0,}, - {"$GMRInstance":"v4","%Name":"inst_688E87F2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_688E87F2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_FB07B8CC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_FB07B8CC","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":208.0,}, - {"$GMRInstance":"v4","%Name":"inst_E150D3CB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E150D3CB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_B6347843","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B6347843","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_055C23CA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_055C23CA","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_3FF12B84","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3FF12B84","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":400.0,}, - {"$GMRInstance":"v4","%Name":"inst_9C0C3419","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9C0C3419","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_7853AEB1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7853AEB1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_A8EDEDEF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A8EDEDEF","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_9DE5021D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9DE5021D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_773884FA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_773884FA","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_6F23121B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6F23121B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1056.0,"y":864.0,}, - {"$GMRInstance":"v4","%Name":"inst_8559002F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8559002F","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_C6F1A0C2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C6F1A0C2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_257B03D5","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_257B03D5","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_95E7C107","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_95E7C107","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_EB544B1E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EB544B1E","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_10852472","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_10852472","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_366D8B6F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_366D8B6F","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_80F6E1D8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_80F6E1D8","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1056.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_BDE0ECC5","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BDE0ECC5","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_8224F4CC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8224F4CC","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_20DF1E0B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_20DF1E0B","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_F238AB87","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F238AB87","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_6697D0EC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6697D0EC","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_E223EB40","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E223EB40","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_D91A343C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D91A343C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_EE76140C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EE76140C","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_4D125B1C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_4D125B1C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_78F308E8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_78F308E8","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_5CDFA987","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5CDFA987","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_B9D13756","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B9D13756","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1056.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_6A11A170","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6A11A170","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_ECB34A19","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_ECB34A19","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1152.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_1E3BD983","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1E3BD983","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_548EF074","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_548EF074","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_09FA2609","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_09FA2609","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_6DA07E97","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6DA07E97","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_AB6FE04B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AB6FE04B","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_C3A5B2E4","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C3A5B2E4","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_FA0BA6CF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_FA0BA6CF","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_5105EE58","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5105EE58","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_0EBA49F9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0EBA49F9","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_69D4CCEF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_69D4CCEF","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_1576BC5E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1576BC5E","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_D3700BC1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D3700BC1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_2A15F823","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2A15F823","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_E1BDC14D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E1BDC14D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":864.0,}, - {"$GMRInstance":"v4","%Name":"inst_E3417EC1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E3417EC1","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_454C3707","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_454C3707","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_3A23E3C8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3A23E3C8","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_9A73FB61","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9A73FB61","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_C91C6FA0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C91C6FA0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_BE4FE50E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BE4FE50E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_1A3362DD","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1A3362DD","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_0875E5D6","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0875E5D6","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_E33204DA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E33204DA","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_357D736B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_357D736B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_553EEFDD","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_553EEFDD","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_63F741EE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_63F741EE","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_0A63F7E8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0A63F7E8","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_80ED5D9F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_80ED5D9F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_55B41B69","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_55B41B69","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_B1C6E50D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B1C6E50D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_A3C90E04","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A3C90E04","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_12C4B857","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_12C4B857","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_53DE12EB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_53DE12EB","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_AF92DE37","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AF92DE37","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_CEB29A8E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CEB29A8E","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_D30FA4FB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D30FA4FB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_E0CCE0B8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E0CCE0B8","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_6CE0B413","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6CE0B413","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_74157AE9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_74157AE9","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_BECDE02E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BECDE02E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_16B3E5F0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_16B3E5F0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_80372912","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_80372912","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_1F53EF6B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1F53EF6B","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_F0034B9C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F0034B9C","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_AF21A2C9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AF21A2C9","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_97E19425","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_97E19425","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_CA7A3670","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CA7A3670","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_48ED570A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_48ED570A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_2FBE854A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2FBE854A","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_EA0A23C0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EA0A23C0","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_27A10AB4","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_27A10AB4","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_55533EF5","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_55533EF5","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_23D6570E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_23D6570E","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":96.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_F5E4A9E2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F5E4A9E2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1056.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_3B7F594A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3B7F594A","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_E18BAFD9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E18BAFD9","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_0FCAC0BE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0FCAC0BE","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_1C7152BB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1C7152BB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_15ACEC8C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_15ACEC8C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_72BD1C47","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_72BD1C47","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_9FB4C563","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9FB4C563","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_8B51DEA0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8B51DEA0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_96F2BEA0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_96F2BEA0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_72612F45","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_72612F45","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_074026D3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_074026D3","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_A94B0BD3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A94B0BD3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_92AB3DF0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_92AB3DF0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_50511EB7","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_50511EB7","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_2442E6BE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2442E6BE","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_00FF3F46","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_00FF3F46","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_0D3D06EC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0D3D06EC","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_CE974969","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CE974969","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_09DD0B98","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_09DD0B98","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_21204F1F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_21204F1F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_B6CFA351","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B6CFA351","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_3DC3B334","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3DC3B334","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_79E7CBAB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_79E7CBAB","objectId":{"name":"obj_enemy_leftest","path":"objects/obj_enemy_leftest/obj_enemy_leftest.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":64.0,}, - ],"layers":[],"name":"Compatibility_Instances_Depth_0","properties":[],"resourceType":"GMRInstanceLayer","resourceVersion":"2.0","userdefinedDepth":true,"visible":true,}, + {"$GMRInstanceLayer":"","%Name":"Compatibility_Instances_Depth_0","depth":0,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"instances":[],"layers":[],"name":"Compatibility_Instances_Depth_0","properties":[],"resourceType":"GMRInstanceLayer","resourceVersion":"2.0","userdefinedDepth":true,"visible":true,}, {"$GMRBackgroundLayer":"","%Name":"Compatibility_Colour","animationFPS":15.0,"animationSpeedType":0,"colour":4278222848,"depth":2147483600,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"hspeed":0.0,"htiled":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"layers":[],"name":"Compatibility_Colour","properties":[],"resourceType":"GMRBackgroundLayer","resourceVersion":"2.0","spriteId":null,"stretch":false,"userdefinedAnimFPS":false,"userdefinedDepth":true,"visible":true,"vspeed":0.0,"vtiled":false,"x":0,"y":0,}, ], "name":"rm_testing_half", diff --git a/rooms/rm_testing_new/rm_testing_new.yy b/rooms/rm_testing_new/rm_testing_new.yy index f9a173c932..b344f8e67b 100644 --- a/rooms/rm_testing_new/rm_testing_new.yy +++ b/rooms/rm_testing_new/rm_testing_new.yy @@ -5,752 +5,10 @@ "inheritCode":false, "inheritCreationOrder":false, "inheritLayers":false, - "instanceCreationOrder":[ - {"name":"inst_388035F1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D5E41057","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BB1D114A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_09923952","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_DF446DDF","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_34FEE099","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_2C87EFF8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E02A4953","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F8CF0E15","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_758D500A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5509A666","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_272EA924","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_688E87F2","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_FB07B8CC","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E150D3CB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B6347843","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_055C23CA","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3FF12B84","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9C0C3419","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_7853AEB1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A8EDEDEF","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6EBD3C1C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_773884FA","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_36A1F822","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8559002F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9F102D8B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_257B03D5","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BDFA2E0F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_EB544B1E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B42FF6B3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_366D8B6F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_47294749","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BDE0ECC5","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1DD400FB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_20DF1E0B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_38E46998","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6697D0EC","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_422015A7","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D91A343C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A2C31987","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_4D125B1C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CE4AA7DE","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5CDFA987","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_4D386697","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6A11A170","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E58708C6","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1E3BD983","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_059F747C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_09FA2609","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1B91E8FA","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_AB6FE04B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D598AD85","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_FA0BA6CF","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_AD3D1A06","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0EBA49F9","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3B94C5D4","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1576BC5E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_09E5CF4A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_2A15F823","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_876FFD18","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E3417EC1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_454C3707","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3A23E3C8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9A73FB61","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C91C6FA0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A1FE1A2D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D213BA1C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_55AF4196","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_7C8100DE","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_02D1525A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_553EEFDD","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8DF39DBA","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0A63F7E8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_387CDFBD","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_55B41B69","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_2A6DA71F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A3C90E04","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_69DB5D30","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_53DE12EB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E7A49E65","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CEB29A8E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8DDD2EA7","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E0CCE0B8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3B0C87A8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_74157AE9","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F8AF8DB6","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_16B3E5F0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C33643AE","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1F53EF6B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_46D965EA","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_AF21A2C9","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_47A36C68","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CA7A3670","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_258A0CBC","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_2FBE854A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D59943CF","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_27A10AB4","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6569A1F2","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_23D6570E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_20903E71","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3B7F594A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8953EFE0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0FCAC0BE","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D6166379","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_15ACEC8C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_AD03219D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9FB4C563","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_00AF5EF0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_96F2BEA0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BDEB7D5C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_074026D3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_EAE2CAF0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_92AB3DF0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_449E9A2B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_2442E6BE","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_99FC132E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0D3D06EC","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3E162286","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_09DD0B98","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5B65D7D8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B6CFA351","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1609728A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_72BD1C47","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_75DA04D0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_72612F45","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3A719755","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3DC3B334","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F2A3E647","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8B51DEA0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9E808E37","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1C7152BB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E18BAFD9","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A94B0BD3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_50511EB7","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_00FF3F46","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CE974969","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_21204F1F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_357D736B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E33204DA","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0875E5D6","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1A3362DD","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BE4FE50E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_63F741EE","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_80ED5D9F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B1C6E50D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_12C4B857","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_AF92DE37","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D30FA4FB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6CE0B413","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BECDE02E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_80372912","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F0034B9C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_97E19425","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_48ED570A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_EA0A23C0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_55533EF5","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F5E4A9E2","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9DE5021D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_294B9A40","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C6F1A0C2","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_95E7C107","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_10852472","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_80F6E1D8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8224F4CC","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F238AB87","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E223EB40","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_EE76140C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_78F308E8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B9D13756","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_ECB34A19","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_548EF074","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6DA07E97","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C3A5B2E4","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5105EE58","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_69D4CCEF","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D3700BC1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3673D84E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C7706CDF","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9AE2394D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0DB4551D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_93F8F9D1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F62CDA04","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BC1D4DD0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E8FB9DFB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F7F12BC3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_07A0A63F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_AE132D74","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_27CF4E5F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_81F7B93F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5E26086D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BAEAB96E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A126FBB2","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CD5F8840","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5A3D4E87","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_44C2FCE4","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BEEE1AAF","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_621FE1EA","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_262F9D6C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F16A14DB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_10ACBA49","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_FBD00D1E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_59474C1E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_18F2D01C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_AE939C59","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1B5CC0D8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_320DE7DE","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A1A947A7","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_62CB369D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6C4E2003","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_7E6E13B4","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_4380605B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_498365F0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_4AE5CF42","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1A21A3F0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_EBD07193","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_83510139","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_DE41F6CC","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D8E4D02A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F2F466F6","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_95BBF53D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A7A11173","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8EECC032","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1A5C1E88","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8BE37967","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_7832DC16","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_4A1DA0D0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_80E584A2","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_686C20E6","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8F68253E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_4E6920FB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C20E4C65","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B50A32A3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_10642C17","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A3FC4DB0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_495136A1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9DE3581A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D11BA48C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A161BBBB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_81B3C107","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BEDDD4C3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_4CD726A0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B2BEF198","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A37F6A79","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_60374050","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_167E625E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1B54F3C5","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_394A6756","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_93B6BABC","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3954542D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_347F206B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_FE311E3D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9AF09151","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_95B49484","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_FDCBC1D1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_DE472767","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_57FF5F83","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8309A915","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D5EA3E02","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5BAB987E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3DDFB15B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C76749B3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_05D7BA4A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_640BD834","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0ADF5D22","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_23E780B5","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BAA3A7CE","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_4342BBC3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9D8344B3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_2E6AFF62","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_347F4EB1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_18B3786A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1E558424","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_088F0628","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6A935031","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C5389FF3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_7ABDE645","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6CFF83E1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_250DA1E4","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_35BDDB56","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_808D0D05","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_49C7CF9A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_EB89405D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6615F3DA","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C6D8CE37","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6A54B063","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5C28250A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B6E07888","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_60AFBAA0","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_486C806D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_F472B89D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CAAF0390","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CFFA423D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_66114EEF","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6D716C3D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CBEAD4CF","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_273D6FF1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_573E9FB8","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6C0A2F06","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_EDFB0625","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_7709446B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_880DB048","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0CB3D0B6","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B6FFEF76","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_2E90CDC2","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_065A560D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_6E321360","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B0258217","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B93B6C1A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_82CBF21E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_41CF7EA7","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B19699B1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_AF0AF791","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_21715F1C","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E8DC446F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1AC4BC97","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BAD0240B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_398A2EE5","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5B5914C2","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9C8C1C19","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9FB4C666","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_31B6BFA2","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_99AEC12D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CE659175","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_28E908D9","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_73F6E1D3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_454D2360","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8B58BBCD","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5327609F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_555EADDB","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5D3AE2F7","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_7887F6C7","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9579B27E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_328C3604","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_471B0F57","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_610AA61E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_5705FF86","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E9B7FA95","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_BA6C786A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_7E6E61A3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D0FDB51F","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_CA6E259B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_79B66B59","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_06C49427","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_94641A7D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_8CCEBC61","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9969588E","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_FA2025A1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_55AEBA55","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_3EECDDD1","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0E6FA459","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_A3BF88B6","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_73F9FC32","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9113A661","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_FF9E47F9","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_990D1F3D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9CC8B76B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_74D4C1DC","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_195CA91B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_9BBC48C3","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D2C50DD9","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E9838623","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_E1F1977A","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_7C23CB80","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_C9C94E86","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_1213068B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_0E355180","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_B36BD9FA","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_32543C97","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_D59F519D","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - {"name":"inst_14FA416B","path":"rooms/rm_testing_new/rm_testing_new.yy",}, - ], + "instanceCreationOrder":[], "isDnd":false, "layers":[ - {"$GMRInstanceLayer":"","%Name":"Compatibility_Instances_Depth_0","depth":0,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"instances":[ - {"$GMRInstance":"v4","%Name":"inst_388035F1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_388035F1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":336.0,}, - {"$GMRInstance":"v4","%Name":"inst_D5E41057","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D5E41057","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_BB1D114A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BB1D114A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":496.0,}, - {"$GMRInstance":"v4","%Name":"inst_09923952","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_09923952","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":176.0,}, - {"$GMRInstance":"v4","%Name":"inst_DF446DDF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_DF446DDF","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_34FEE099","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_34FEE099","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":176.0,}, - {"$GMRInstance":"v4","%Name":"inst_2C87EFF8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2C87EFF8","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":240.0,}, - {"$GMRInstance":"v4","%Name":"inst_E02A4953","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E02A4953","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_F8CF0E15","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F8CF0E15","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":528.0,}, - {"$GMRInstance":"v4","%Name":"inst_758D500A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_758D500A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_5509A666","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5509A666","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_272EA924","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_272EA924","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":304.0,}, - {"$GMRInstance":"v4","%Name":"inst_688E87F2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_688E87F2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_FB07B8CC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_FB07B8CC","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":208.0,}, - {"$GMRInstance":"v4","%Name":"inst_E150D3CB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E150D3CB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_B6347843","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B6347843","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_055C23CA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_055C23CA","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_3FF12B84","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3FF12B84","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":400.0,}, - {"$GMRInstance":"v4","%Name":"inst_9C0C3419","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9C0C3419","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_7853AEB1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7853AEB1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_A8EDEDEF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A8EDEDEF","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_6EBD3C1C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6EBD3C1C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_773884FA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_773884FA","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_36A1F822","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_36A1F822","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_8559002F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8559002F","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_9F102D8B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9F102D8B","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_257B03D5","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_257B03D5","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_BDFA2E0F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BDFA2E0F","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_EB544B1E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EB544B1E","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_B42FF6B3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B42FF6B3","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_366D8B6F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_366D8B6F","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_47294749","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_47294749","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_BDE0ECC5","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BDE0ECC5","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_1DD400FB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1DD400FB","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_20DF1E0B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_20DF1E0B","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_38E46998","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_38E46998","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_6697D0EC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6697D0EC","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_422015A7","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_422015A7","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_D91A343C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D91A343C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_A2C31987","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A2C31987","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_4D125B1C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_4D125B1C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_CE4AA7DE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CE4AA7DE","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_5CDFA987","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5CDFA987","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_4D386697","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_4D386697","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_6A11A170","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6A11A170","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_E58708C6","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E58708C6","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_1E3BD983","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1E3BD983","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_059F747C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_059F747C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_09FA2609","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_09FA2609","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_1B91E8FA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1B91E8FA","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_AB6FE04B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AB6FE04B","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_D598AD85","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D598AD85","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_FA0BA6CF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_FA0BA6CF","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_AD3D1A06","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AD3D1A06","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_0EBA49F9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0EBA49F9","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_3B94C5D4","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3B94C5D4","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_1576BC5E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1576BC5E","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_09E5CF4A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_09E5CF4A","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_2A15F823","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2A15F823","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":32.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_876FFD18","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_876FFD18","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":64.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_E3417EC1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E3417EC1","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_454C3707","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_454C3707","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_3A23E3C8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3A23E3C8","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_9A73FB61","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9A73FB61","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_C91C6FA0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C91C6FA0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_A1FE1A2D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A1FE1A2D","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_D213BA1C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D213BA1C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_55AF4196","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_55AF4196","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_7C8100DE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7C8100DE","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_02D1525A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_02D1525A","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_553EEFDD","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_553EEFDD","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_8DF39DBA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8DF39DBA","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_0A63F7E8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0A63F7E8","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_387CDFBD","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_387CDFBD","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_55B41B69","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_55B41B69","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_2A6DA71F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2A6DA71F","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_A3C90E04","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A3C90E04","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_69DB5D30","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_69DB5D30","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_53DE12EB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_53DE12EB","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_E7A49E65","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E7A49E65","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_CEB29A8E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CEB29A8E","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_8DDD2EA7","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8DDD2EA7","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_E0CCE0B8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E0CCE0B8","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_3B0C87A8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3B0C87A8","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_74157AE9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_74157AE9","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_F8AF8DB6","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F8AF8DB6","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_16B3E5F0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_16B3E5F0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_C33643AE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C33643AE","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_1F53EF6B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1F53EF6B","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_46D965EA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_46D965EA","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_AF21A2C9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AF21A2C9","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_47A36C68","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_47A36C68","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_CA7A3670","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CA7A3670","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_258A0CBC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_258A0CBC","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_2FBE854A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2FBE854A","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_D59943CF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D59943CF","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_27A10AB4","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_27A10AB4","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_6569A1F2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6569A1F2","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_23D6570E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_23D6570E","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":128.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_20903E71","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_20903E71","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":160.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_3B7F594A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3B7F594A","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_8953EFE0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8953EFE0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_0FCAC0BE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0FCAC0BE","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_D6166379","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D6166379","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_15ACEC8C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_15ACEC8C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_AD03219D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AD03219D","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_9FB4C563","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9FB4C563","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_00AF5EF0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_00AF5EF0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_96F2BEA0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_96F2BEA0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_BDEB7D5C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BDEB7D5C","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_074026D3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_074026D3","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_EAE2CAF0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EAE2CAF0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_92AB3DF0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_92AB3DF0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_449E9A2B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_449E9A2B","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_2442E6BE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2442E6BE","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_99FC132E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_99FC132E","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_0D3D06EC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0D3D06EC","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_3E162286","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3E162286","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_09DD0B98","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_09DD0B98","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_5B65D7D8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5B65D7D8","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_B6CFA351","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B6CFA351","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_1609728A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1609728A","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_72BD1C47","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_72BD1C47","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_75DA04D0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_75DA04D0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_72612F45","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_72612F45","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_3A719755","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3A719755","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_3DC3B334","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3DC3B334","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_F2A3E647","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F2A3E647","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_8B51DEA0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8B51DEA0","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":224.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_9E808E37","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9E808E37","objectId":{"name":"obj_marine","path":"objects/obj_marine/obj_marine.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":256.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_1C7152BB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1C7152BB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_E18BAFD9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E18BAFD9","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_A94B0BD3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A94B0BD3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_50511EB7","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_50511EB7","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_00FF3F46","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_00FF3F46","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_CE974969","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CE974969","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_21204F1F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_21204F1F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_357D736B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_357D736B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_E33204DA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E33204DA","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_0875E5D6","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0875E5D6","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_1A3362DD","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1A3362DD","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":832.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_BE4FE50E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BE4FE50E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_63F741EE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_63F741EE","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_80ED5D9F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_80ED5D9F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_B1C6E50D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B1C6E50D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_12C4B857","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_12C4B857","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":896.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_AF92DE37","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AF92DE37","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_D30FA4FB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D30FA4FB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_6CE0B413","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6CE0B413","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_BECDE02E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BECDE02E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_80372912","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_80372912","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_F0034B9C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F0034B9C","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_97E19425","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_97E19425","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_48ED570A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_48ED570A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_EA0A23C0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EA0A23C0","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_55533EF5","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_55533EF5","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_F5E4A9E2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F5E4A9E2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1056.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_9DE5021D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9DE5021D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_294B9A40","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_294B9A40","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1568.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_C6F1A0C2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C6F1A0C2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_95E7C107","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_95E7C107","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_10852472","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_10852472","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_80F6E1D8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_80F6E1D8","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1056.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_8224F4CC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8224F4CC","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_F238AB87","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F238AB87","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_E223EB40","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E223EB40","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_EE76140C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EE76140C","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_78F308E8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_78F308E8","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_B9D13756","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B9D13756","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1056.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_ECB34A19","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_ECB34A19","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1152.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_548EF074","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_548EF074","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_6DA07E97","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6DA07E97","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":960.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_C3A5B2E4","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C3A5B2E4","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_5105EE58","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5105EE58","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_69D4CCEF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_69D4CCEF","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_D3700BC1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D3700BC1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":992.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_3673D84E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3673D84E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1568.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_C7706CDF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C7706CDF","objectId":{"name":"obj_enemy_leftest","path":"objects/obj_enemy_leftest/obj_enemy_leftest.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1504.0,"y":0.0,}, - {"$GMRInstance":"v4","%Name":"inst_9AE2394D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9AE2394D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1216.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_0DB4551D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0DB4551D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_93F8F9D1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_93F8F9D1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1248.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_F62CDA04","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F62CDA04","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_BC1D4DD0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BC1D4DD0","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1248.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_E8FB9DFB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E8FB9DFB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1184.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_F7F12BC3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F7F12BC3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1312.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_07A0A63F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_07A0A63F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1216.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_AE132D74","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AE132D74","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1312.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_27CF4E5F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_27CF4E5F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1152.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_81F7B93F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_81F7B93F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1312.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_5E26086D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5E26086D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1216.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_BAEAB96E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BAEAB96E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1248.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_A126FBB2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A126FBB2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1312.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_CD5F8840","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CD5F8840","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1184.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_5A3D4E87","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5A3D4E87","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1152.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_44C2FCE4","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_44C2FCE4","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1216.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_BEEE1AAF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BEEE1AAF","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1280.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_621FE1EA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_621FE1EA","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1184.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_262F9D6C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_262F9D6C","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1344.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_F16A14DB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F16A14DB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1216.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_10ACBA49","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_10ACBA49","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1312.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_FBD00D1E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_FBD00D1E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1216.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_59474C1E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_59474C1E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_18F2D01C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_18F2D01C","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1312.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_AE939C59","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AE939C59","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1568.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_1B5CC0D8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1B5CC0D8","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1280.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_320DE7DE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_320DE7DE","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1216.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_A1A947A7","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A1A947A7","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1312.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_62CB369D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_62CB369D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1216.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_6C4E2003","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6C4E2003","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1408.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_7E6E13B4","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7E6E13B4","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1184.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_4380605B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_4380605B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1248.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_498365F0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_498365F0","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1184.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_4AE5CF42","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_4AE5CF42","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1408.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_1A21A3F0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1A21A3F0","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1280.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_EBD07193","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EBD07193","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1344.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_83510139","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_83510139","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1376.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_DE41F6CC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_DE41F6CC","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1376.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_D8E4D02A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D8E4D02A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1440.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_F2F466F6","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F2F466F6","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1344.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_95BBF53D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_95BBF53D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1440.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_A7A11173","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A7A11173","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1376.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_8EECC032","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8EECC032","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1440.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_1A5C1E88","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1A5C1E88","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1440.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_8BE37967","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8BE37967","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1344.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_7832DC16","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7832DC16","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1056.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_4A1DA0D0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_4A1DA0D0","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_80E584A2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_80E584A2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1440.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_686C20E6","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_686C20E6","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1408.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_8F68253E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8F68253E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1472.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_4E6920FB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_4E6920FB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1408.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_C20E4C65","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C20E4C65","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1504.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_B50A32A3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B50A32A3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1568.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_10642C17","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_10642C17","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1440.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_A3FC4DB0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A3FC4DB0","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1536.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_495136A1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_495136A1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1472.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_9DE3581A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9DE3581A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1536.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_D11BA48C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D11BA48C","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1504.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_A161BBBB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A161BBBB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1568.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_81B3C107","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_81B3C107","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1504.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_BEDDD4C3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BEDDD4C3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1536.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_4CD726A0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_4CD726A0","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1440.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_B2BEF198","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B2BEF198","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1504.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_A37F6A79","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A37F6A79","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1536.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_60374050","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_60374050","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1568.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_167E625E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_167E625E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1504.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_1B54F3C5","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1B54F3C5","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1472.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_394A6756","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_394A6756","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1184.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_93B6BABC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_93B6BABC","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1344.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_3954542D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3954542D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1408.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_347F206B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_347F206B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1344.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_FE311E3D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_FE311E3D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1376.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_9AF09151","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9AF09151","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1248.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_95B49484","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_95B49484","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_FDCBC1D1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_FDCBC1D1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":864.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_DE472767","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_DE472767","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":928.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_57FF5F83","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_57FF5F83","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1024.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_8309A915","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8309A915","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1088.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_D5EA3E02","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D5EA3E02","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1056.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_5BAB987E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5BAB987E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1184.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_3DDFB15B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3DDFB15B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1120.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_C76749B3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C76749B3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1344.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_05D7BA4A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_05D7BA4A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1280.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_640BD834","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_640BD834","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1440.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_0ADF5D22","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0ADF5D22","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1504.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_23E780B5","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_23E780B5","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1568.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_BAA3A7CE","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BAA3A7CE","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1312.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_4342BBC3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_4342BBC3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1376.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_9D8344B3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9D8344B3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1248.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_2E6AFF62","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2E6AFF62","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1568.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_347F4EB1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_347F4EB1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_18B3786A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_18B3786A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_1E558424","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1E558424","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1728.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_088F0628","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_088F0628","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1664.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_6A935031","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6A935031","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1760.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_C5389FF3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C5389FF3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1728.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_7ABDE645","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7ABDE645","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1824.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_6CFF83E1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6CFF83E1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1760.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_250DA1E4","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_250DA1E4","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1856.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_35BDDB56","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_35BDDB56","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1824.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_808D0D05","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_808D0D05","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1920.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_49C7CF9A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_49C7CF9A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1888.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_EB89405D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EB89405D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1984.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_6615F3DA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6615F3DA","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1920.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_C6D8CE37","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C6D8CE37","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":2048.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_6A54B063","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6A54B063","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1984.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_5C28250A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5C28250A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1824.0,"y":512.0,}, - {"$GMRInstance":"v4","%Name":"inst_B6E07888","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B6E07888","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1952.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_60AFBAA0","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_60AFBAA0","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1664.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_486C806D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_486C806D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1856.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_F472B89D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_F472B89D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1696.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_CAAF0390","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CAAF0390","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1760.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_CFFA423D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CFFA423D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1760.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_66114EEF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_66114EEF","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1888.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_6D716C3D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6D716C3D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_CBEAD4CF","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CBEAD4CF","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1888.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_273D6FF1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_273D6FF1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1888.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_573E9FB8","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_573E9FB8","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1760.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_6C0A2F06","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6C0A2F06","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1696.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_EDFB0625","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_EDFB0625","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1856.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_7709446B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7709446B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1984.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_880DB048","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_880DB048","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1728.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_0CB3D0B6","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0CB3D0B6","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_B6FFEF76","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B6FFEF76","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1824.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_2E90CDC2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_2E90CDC2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_065A560D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_065A560D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1728.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_6E321360","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_6E321360","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_B0258217","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B0258217","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_B93B6C1A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B93B6C1A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1600.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_82CBF21E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_82CBF21E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1696.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_41CF7EA7","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_41CF7EA7","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1696.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_B19699B1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B19699B1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1760.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_AF0AF791","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_AF0AF791","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1696.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_21715F1C","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_21715F1C","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1760.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_E8DC446F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E8DC446F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1856.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_1AC4BC97","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1AC4BC97","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1920.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_BAD0240B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BAD0240B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_398A2EE5","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_398A2EE5","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1728.0,"y":544.0,}, - {"$GMRInstance":"v4","%Name":"inst_5B5914C2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5B5914C2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1600.0,"y":576.0,}, - {"$GMRInstance":"v4","%Name":"inst_9C8C1C19","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9C8C1C19","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_9FB4C666","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9FB4C666","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1664.0,"y":448.0,}, - {"$GMRInstance":"v4","%Name":"inst_31B6BFA2","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_31B6BFA2","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1600.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_99AEC12D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_99AEC12D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1600.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_CE659175","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CE659175","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1664.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_28E908D9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_28E908D9","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_73F6E1D3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_73F6E1D3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1728.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_454D2360","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_454D2360","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1664.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_8B58BBCD","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8B58BBCD","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":768.0,}, - {"$GMRInstance":"v4","%Name":"inst_5327609F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5327609F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_555EADDB","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_555EADDB","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1664.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_5D3AE2F7","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5D3AE2F7","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1760.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_7887F6C7","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7887F6C7","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_9579B27E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9579B27E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1888.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_328C3604","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_328C3604","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1952.0,"y":800.0,}, - {"$GMRInstance":"v4","%Name":"inst_471B0F57","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_471B0F57","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1920.0,"y":832.0,}, - {"$GMRInstance":"v4","%Name":"inst_610AA61E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_610AA61E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1952.0,"y":704.0,}, - {"$GMRInstance":"v4","%Name":"inst_5705FF86","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_5705FF86","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1952.0,"y":640.0,}, - {"$GMRInstance":"v4","%Name":"inst_E9B7FA95","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E9B7FA95","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1984.0,"y":736.0,}, - {"$GMRInstance":"v4","%Name":"inst_BA6C786A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_BA6C786A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_7E6E61A3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7E6E61A3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1824.0,"y":608.0,}, - {"$GMRInstance":"v4","%Name":"inst_D0FDB51F","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D0FDB51F","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1696.0,"y":672.0,}, - {"$GMRInstance":"v4","%Name":"inst_CA6E259B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_CA6E259B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1856.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_79B66B59","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_79B66B59","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_06C49427","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_06C49427","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1696.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_94641A7D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_94641A7D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_8CCEBC61","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_8CCEBC61","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1696.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_9969588E","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9969588E","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_FA2025A1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_FA2025A1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1856.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_55AEBA55","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_55AEBA55","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1504.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_3EECDDD1","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_3EECDDD1","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1888.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_0E6FA459","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0E6FA459","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1952.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_A3BF88B6","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_A3BF88B6","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1888.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_73F9FC32","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_73F9FC32","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1984.0,"y":224.0,}, - {"$GMRInstance":"v4","%Name":"inst_9113A661","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9113A661","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1920.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_FF9E47F9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_FF9E47F9","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1984.0,"y":288.0,}, - {"$GMRInstance":"v4","%Name":"inst_990D1F3D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_990D1F3D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1984.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_9CC8B76B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9CC8B76B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":2016.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_74D4C1DC","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_74D4C1DC","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":2016.0,"y":384.0,}, - {"$GMRInstance":"v4","%Name":"inst_195CA91B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_195CA91B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":2016.0,"y":256.0,}, - {"$GMRInstance":"v4","%Name":"inst_9BBC48C3","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_9BBC48C3","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":320.0,}, - {"$GMRInstance":"v4","%Name":"inst_D2C50DD9","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D2C50DD9","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1856.0,"y":352.0,}, - {"$GMRInstance":"v4","%Name":"inst_E9838623","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E9838623","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1952.0,"y":416.0,}, - {"$GMRInstance":"v4","%Name":"inst_E1F1977A","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_E1F1977A","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1984.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_7C23CB80","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_7C23CB80","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":2016.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_C9C94E86","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_C9C94E86","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1952.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_1213068B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_1213068B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":2016.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_0E355180","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_0E355180","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1888.0,"y":128.0,}, - {"$GMRInstance":"v4","%Name":"inst_B36BD9FA","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_B36BD9FA","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1792.0,"y":160.0,}, - {"$GMRInstance":"v4","%Name":"inst_32543C97","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_32543C97","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1824.0,"y":192.0,}, - {"$GMRInstance":"v4","%Name":"inst_D59F519D","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_D59F519D","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1696.0,"y":480.0,}, - {"$GMRInstance":"v4","%Name":"inst_14FA416B","colour":4294967295,"frozen":false,"hasCreationCode":false,"ignore":false,"imageIndex":0,"imageSpeed":1.0,"inheritCode":false,"inheritedItemId":null,"inheritItemSettings":false,"isDnd":false,"name":"inst_14FA416B","objectId":{"name":"obj_ork","path":"objects/obj_ork/obj_ork.yy",},"properties":[],"resourceType":"GMRInstance","resourceVersion":"2.0","rotation":0.0,"scaleX":1.0,"scaleY":1.0,"x":1632.0,"y":352.0,}, - ],"layers":[],"name":"Compatibility_Instances_Depth_0","properties":[],"resourceType":"GMRInstanceLayer","resourceVersion":"2.0","userdefinedDepth":true,"visible":true,}, + {"$GMRInstanceLayer":"","%Name":"Compatibility_Instances_Depth_0","depth":0,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"instances":[],"layers":[],"name":"Compatibility_Instances_Depth_0","properties":[],"resourceType":"GMRInstanceLayer","resourceVersion":"2.0","userdefinedDepth":true,"visible":true,}, {"$GMRBackgroundLayer":"","%Name":"Compatibility_Colour","animationFPS":15.0,"animationSpeedType":0,"colour":4278222848,"depth":2147483600,"effectEnabled":true,"effectType":null,"gridX":32,"gridY":32,"hierarchyFrozen":false,"hspeed":0.0,"htiled":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"inheritSubLayers":true,"inheritVisibility":true,"layers":[],"name":"Compatibility_Colour","properties":[],"resourceType":"GMRBackgroundLayer","resourceVersion":"2.0","spriteId":null,"stretch":false,"userdefinedAnimFPS":false,"userdefinedDepth":true,"visible":true,"vspeed":0.0,"vtiled":false,"x":0,"y":0,}, ], "name":"rm_testing_new", diff --git a/scripts/Armamentarium/Armamentarium.gml b/scripts/Armamentarium/Armamentarium.gml index 5935906ac6..241dd8215c 100644 --- a/scripts/Armamentarium/Armamentarium.gml +++ b/scripts/Armamentarium/Armamentarium.gml @@ -445,8 +445,10 @@ function Armamentarium(_controller) constructor { // --- Components --- slate_panel = new DataSlate(); + // feather ignore once GM2043 slate_panel.inside_method = method(self, _draw_slate_contents); + // feather ignore once GM2043 stc_panel = new STCResearchPanel(controller, method(self, refresh_catalog)); enter_forge_button = new ShutterButton(); diff --git a/scripts/ErrorHandler/ErrorHandler.gml b/scripts/ErrorHandler/ErrorHandler.gml index f44c9e0c1e..b211b22d70 100644 --- a/scripts/ErrorHandler/ErrorHandler.gml +++ b/scripts/ErrorHandler/ErrorHandler.gml @@ -22,8 +22,11 @@ function GameError(_header, _message, _stacktrace = "", _critical = false, _repo commit_hash = global.commit_hash; username = global.settings.username ?? ""; + // feather ignore once GM2043 full_log = build_full_log(); + // feather ignore once GM2043 error_file_text = build_error_file_text(); + // feather ignore once GM2043 player_message = build_player_message(); /// @description Builds the full log content diff --git a/scripts/NameGenerator/NameGenerator.gml b/scripts/NameGenerator/NameGenerator.gml index 4c994d856d..c1449e0873 100644 --- a/scripts/NameGenerator/NameGenerator.gml +++ b/scripts/NameGenerator/NameGenerator.gml @@ -189,7 +189,7 @@ function NameGenerator() constructor { var _simple_names = json_to_gamemaker(working_directory + $"main\\name_loader.json", json_parse); if (_simple_names == "") { - var _simple_names = [ + _simple_names = [ "sector", "star", { @@ -257,13 +257,14 @@ function NameGenerator() constructor { var _load_name = _name; var _load_as_composite = false; var _preffered = "simple"; + var _composites = {}; if (is_struct(_name)) { var _struc = _name; _name = _struc.load_as; _load_name = _struc.load_set; if (struct_exists(_struc, "composites")) { _load_as_composite = true; - var _composites = _struc.composites; + _composites = _struc.composites; } if (struct_exists(_struc, "preffered_method")) { _preffered = _struc.preffered_method; @@ -307,12 +308,10 @@ function NameGenerator() constructor { _styles = array_shuffle(_styles); - while (array_length(_styles)) { - var _style = array_pop(_styles); - var _set = get_name_set(_style); + for (var i = 0; i < array_length(_styles); i++) { + var _set = get_name_set(_styles[i]); if (is_struct(_set)) { - var _name = _set.UsePreffered(); - break; + _name = _set.UsePreffered(); } } diff --git a/scripts/scr_cheatcode/scr_cheatcode.gml b/scripts/scr_cheatcode/scr_cheatcode.gml index 439289bf45..ef2ab729be 100644 --- a/scripts/scr_cheatcode/scr_cheatcode.gml +++ b/scripts/scr_cheatcode/scr_cheatcode.gml @@ -44,20 +44,26 @@ function scr_cheatcode(argument0) { case "embarkguard": with (obj_controller) { var _n = embark_guardsmen(obj_ini.home_name, obj_ini.home_planet); - show_message("Embarked " + string(_n) + " Guard from your homeworld.#Total embarked: " + string(player_guardsmen_embarked())); + scr_popup("Imperial Guard", "Embarked " + string(_n) + " Guard from your homeworld. Total embarked: " + string(player_guardsmen_embarked()), ""); } break; case "deployguard": with (obj_controller) { - var _n = deploy_guardsmen(obj_ini.home_name, obj_ini.home_planet); - show_message("Deployed " + string(_n) + " Guard onto your homeworld."); + if (instance_exists(obj_star_select) && (selecting_planet > 0)) { + var _star = obj_star_select.target; + var _n = deploy_guardsmen(_star.name, selecting_planet); + scr_popup("Imperial Guard", "Deployed " + string(_n) + " Guard onto " + string(_star.name) + " " + string(selecting_planet) + ". (Unloads from your ships orbiting that world.)", ""); + } else { + var _n = deploy_guardsmen(obj_ini.home_name, obj_ini.home_planet); + scr_popup("Imperial Guard", "No world selected, so deployed " + string(_n) + " Guard at your homeworld. Open a system and click a planet first to target another world.", ""); + } } break; case "titheguard": with (obj_controller) { var _amt = real(cheat_arguments[0]); var _n = tithe_guardsmen(obj_ini.home_name, obj_ini.home_planet, _amt); - show_message("Raised " + string(_n) + " Guard from your homeworld's population."); + scr_popup("Imperial Guard", "Raised " + string(_n) + " Guard from your homeworld's population.", ""); } break; case "finishforge": diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index e1b6a2e10a..5996d5e392 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -211,6 +211,61 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index) { } } + // Bulk man-block with no individual model structs (Guard auxilia): take losses + // straight off the men count, the way the enemy's ranks do, since there are no + // marine structs for the normal path to kill. Scoped to guard blocks only. + if (guard == 1 && array_length(valid_marines) == 0 && men > 0) { + // Identical to the enemy Guardsman casualty math in scr_shoot. Reduce each + // shot by armour, pool the survivable damage across all shots, convert it to + // dead men at dudes_hp each, and cap the kills at the shot count. With + // dudes_ac 40 the rank shrugs off low-AP fire (basic Choppaz, Shootas) the + // same way the enemy Guardsmen you fight do, and only armour-piercing weapons + // cut them down in numbers. Armour is what gives them their staying power, so + // there is no separate cohesion cap here. + var _g_ac = (array_length(dudes_ac) > 1) ? dudes_ac[1] : 40; + var _g_hp = (array_length(dudes_hp) > 1) ? dudes_hp[1] : 5; + if (_g_hp <= 0) { + _g_hp = 5; + } + var _g_after = _damage - (_g_ac * _armour_mod); + if (_g_after < 0) { + _g_after = 0; + } + var _g_pool = _shots * _g_after; + var _g_total = min(floor(_g_pool / _g_hp), _shots); + _g_total = min(_g_total, men); + if (_g_total < 0) { + _g_total = 0; + } + _damage_data.hits += _shots; + // Always name the block, even on a zero-casualty hit, or the enemy attack + // flavor prints "fire at ." with a blank target whenever armour soaks the shot. + _damage_data.unit_type = "Imperial Guardsman"; + if (_g_total > 0) { + men -= _g_total; + if (array_length(dudes_num) > 1) { + dudes_num[1] = max(0, dudes_num[1] - _g_total); + } + // Report through the same lost/lost_num summary the marines use. + _damage_data.units_lost += _g_total; + _damage_data.unit_type = "Imperial Guardsman"; + var _g_idx = -1; + for (var gk = 0, gl = array_length(lost); gk < gl; gk++) { + if (lost[gk] == "Imperial Guardsman") { + _g_idx = gk; + break; + } + } + if (_g_idx >= 0) { + lost_num[_g_idx] += _g_total; + } else { + array_push(lost, "Imperial Guardsman"); + array_push(lost_num, _g_total); + } + } + return; + } + // Apply damage for each shot for (var shot = 0; shot < _shots; shot++) { if (array_length(valid_marines) == 0) { diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index 408a8b0032..5f03c9e2a8 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -238,6 +238,24 @@ function drop_select_unit_selection() { obj_ncombat.defending = false; obj_ncombat.local_forces = roster.local_button.active; + // Bring embarked Imperial Guard from the attacking fleet into the assault. + // They disembark for the battle, so they are spent from the ships here. + obj_ncombat.player_attack_guard = 0; + if (attack == 1) { + var _sysname = p_target.name; + var _ig = player_guardsmen_at(_sysname); + if (_ig > 0) { + obj_ncombat.player_attack_guard = _ig; + with (obj_ini) { + for (var _gi = 0; _gi < array_length(ship); _gi++) { + if (ship_location[_gi] == _sysname) { + ship_guardsmen[_gi] = 0; + } + } + } + } + } + var _planet = obj_ncombat.battle_object.p_feature[obj_ncombat.battle_id]; if (obj_ncombat.battle_object.space_hulk == 1) { obj_ncombat.battle_special = "space_hulk"; diff --git a/scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml b/scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml index 80c94f298a..817f2f20c6 100644 --- a/scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml +++ b/scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml @@ -538,7 +538,9 @@ function scr_enemy_ai_d() { for (var i = 1; i <= planets; i++) { if (i < array_length(system_garrison)) { var garrison = get_garrison(i); - garrison.garrison_disposition_change(); + if (garrison.garrison_force){ + garrison.garrison_disposition_change(); + } } } } diff --git a/scripts/scr_fleet_advisor/scr_fleet_advisor.gml b/scripts/scr_fleet_advisor/scr_fleet_advisor.gml index ead8f667f8..0696818b72 100644 --- a/scripts/scr_fleet_advisor/scr_fleet_advisor.gml +++ b/scripts/scr_fleet_advisor/scr_fleet_advisor.gml @@ -183,6 +183,9 @@ function scr_fleet_advisor() { location.contents = obj_ini.ship_location[i]; hp.contents = $"{round(obj_ini.ship_hp[i] / obj_ini.ship_maxhp[i] * 100)}%"; carrying.contents = $"{obj_ini.ship_carrying[i]}/{obj_ini.ship_capacity[i]}"; + if (obj_ini.ship_guardsmen[i] > 0) { + carrying.contents += $" +{scr_display_number(obj_ini.ship_guardsmen[i])} IG"; + } } for (var g = 0; g < array_length(_columns_array); g++) { @@ -234,7 +237,8 @@ function scr_fleet_advisor() { cn.temp[119] = scr_ship_occupants(i); } } - tooltip_draw($"Carrying ({cn.temp[118]}): {cn.temp[119]}"); + var _ig_line = (obj_ini.ship_guardsmen[i] > 0) ? $" | Imperial Guard embarked: {scr_display_number(obj_ini.ship_guardsmen[i])}" : ""; + tooltip_draw($"Carrying ({cn.temp[118]}): {cn.temp[119]}{_ig_line}"); if (_goto_button.click()) { with (obj_p_fleet) { var _fleet_ships = fleet_full_ship_array(); diff --git a/scripts/scr_garrison/scr_garrison.gml b/scripts/scr_garrison/scr_garrison.gml index 511cdcab88..a5b285cd9c 100644 --- a/scripts/scr_garrison/scr_garrison.gml +++ b/scripts/scr_garrison/scr_garrison.gml @@ -102,31 +102,31 @@ function GarrisonForce(system, planet, type = "garrison") constructor { } static garrison_sustain_damages = function(win_or_loss) { - var unit; + var _unit; var member_count = array_length(members); var members_lost = 0; for (var i = member_count - 1; i >= 0; i--) { - unit = members[i]; - if (unit.hp() <= 0) { + _unit = members[i]; + if (_unit.hp() <= 0) { continue; } if (win_or_loss == "win") { if (irandom(1) == 0) { - unit.add_or_sub_health(-40); + _unit.add_or_sub_health(-40); } - if (unit.hp() < 0) { - if (unit.calculate_death()) { - kill_and_recover(unit.company, unit.marine_number); + if (_unit.hp() < 0) { + if (_unit.calculate_death()) { + kill_and_recover(_unit.company, _unit.marine_number); members_lost++; array_delete(members, i, 1); } } } else if (win_or_loss == "loose") { - unit.add_or_sub_health(-50); - if (unit.hp() < 0) { - if (unit.calculate_death()) { - kill_and_recover(unit.company, unit.marine_number); + _unit.add_or_sub_health(-50); + if (_unit.hp() < 0) { + if (_unit.calculate_death()) { + kill_and_recover(_unit.company, _unit.marine_number); array_delete(members, i, 1); members_lost++; } @@ -142,27 +142,27 @@ function GarrisonForce(system, planet, type = "garrison") constructor { garrison_leader = false; var hierarchy = role_hierarchy(); var leader_hier_pos = array_length(hierarchy); - var unit; + var _unit; for (var _squad = 0; _squad < array_length(garrison_squads); _squad++) { var _leader = garrison_squads[_squad].determine_leader(); - unit = fetch_unit(_leader); + _unit = fetch_unit(_leader); if (garrison_leader == false) { - garrison_leader = unit; + garrison_leader = _unit; for (var r = 0; r < array_length(hierarchy); r++) { - if (hierarchy[r] == unit.role()) { + if (hierarchy[r] == _unit.role()) { leader_hier_pos = r; break; } } - } else if (hierarchy[leader_hier_pos] == unit.role()) { - if (garrison_leader.experience < unit.experience) { - garrison_leader = unit; + } else if (hierarchy[leader_hier_pos] == _unit.role()) { + if (garrison_leader.experience < _unit.experience) { + garrison_leader = _unit; } } else { for (var r = 0; r < leader_hier_pos; r++) { - if (hierarchy[r] == unit.role()) { + if (hierarchy[r] == _unit.role()) { leader_hier_pos = r; - garrison_leader = unit; + garrison_leader = _unit; break; } } @@ -172,11 +172,11 @@ function GarrisonForce(system, planet, type = "garrison") constructor { static exp_rewards = function() { var m; - var unit; + var _unit; for (var s = 0; s < array_length(garrison_squads); s++) { _squad = garrison_squads[s]; for (m = 0; m < array_length(_squad.members); m++) { - unit = fetch_unit(_squad.members[m]); + _unit = fetch_unit(_squad.members[m]); } } }; @@ -225,7 +225,7 @@ function GarrisonForce(system, planet, type = "garrison") constructor { var _time_modifier = max(time_on_planet / 2.5, 10); - if (!garrison_leader) { + if (!is_struct(garrison_leader)) { find_leader(); } var _diplomatic_leader = false; @@ -246,8 +246,14 @@ function GarrisonForce(system, planet, type = "garrison") constructor { dispo_change = 50; } } else { - var charisma_test = global.character_tester.standard_test(garrison_leader, "charisma", final_modifier); - if (!charisma_test[0]) { + var _charisma_test; + if (is_struct(garrison_leader)){ + _charisma_test = global.character_tester.standard_test(garrison_leader, "charisma", final_modifier); + } else { + _charisma_test = [bool(irandom(1)), irandom_range(0, 25)]; + } + var dispo_change = _charisma_test[1] / 10; + if (!_charisma_test[0]) { if (_diplomatic_leader) { dispo_change = "none"; } else { @@ -258,7 +264,6 @@ function GarrisonForce(system, planet, type = "garrison") constructor { } } } else { - dispo_change = charisma_test[1] / 10; _pdata.add_disposition(dispo_change); } } @@ -276,7 +281,7 @@ function GarrisonForce(system, planet, type = "garrison") constructor { //var squad_positions; var _leader; var m; - var unit; + var _unit; var effort = "failed"; switch (enemy) { case eFACTION.ORK: //trying to come up with how we might auto evaluate a squads fate in a battle @@ -295,30 +300,30 @@ function GarrisonForce(system, planet, type = "garrison") constructor { case 1: for (m = 0; m < array_length(_squad.members); m++) { //see how _squad members faired in their circumstances - unit = _squad.fetch_member(m); - if (irandom(unit.weapon_skill) > margin) { - //if unit "wins" in combat test against weapon skill as this is a cc enagement - if (irandom(4999) < sqr(unit.weapon_skill - 35) + unit.luck) { - //chance unit does something heroic + _unit = _squad.fetch_member(m); + if (irandom(_unit.weapon_skill) > margin) { + //if _unit "wins" in combat test against weapon skill as this is a cc enagement + if (irandom(4999) < sqr(_unit.weapon_skill - 35) + _unit.luck) { + //chance _unit does something heroic //wonder if luck should be renamed to fate ?? var alligience = "imperial"; switch (choose("still_standing", "slay_champion", "hold_breach")) { //feats and traits are stored seperatly but use very similar mechanics - //this is because i am not linking feats to indepth mecanics theyre just logs of unit deeps - //however a unit that collects a couple of slay_champion feats may earn the warlord_slayer trait with built in mechanics + //this is because i am not linking feats to indepth mecanics theyre just logs of _unit deeps + //however a _unit that collects a couple of slay_champion feats may earn the warlord_slayer trait with built in mechanics //think of it as a more story lead skill tree //equally a feat does not be stored anywhere you can just makeem up on the fly where as a trait has to be stored in teh global trait list //this may all be subject to change but in my head it's coming together case "hold_breach": - unit.add_feat({ident: "hold_breach", title: "Held breach", planet: planet, grade: 5, location: "location", text: $"Single Handedly held a breach in the {alligience} during the {effort} {attack_defend} of {location} {scr_roman_numeral[planet - 1]} from the Orks"}); + _unit.add_feat({ident: "hold_breach", title: "Held breach", planet: planet, grade: 5, location: "location", text: $"Single Handedly held a breach in the {alligience} during the {effort} {attack_defend} of {location} {scr_roman_numeral[planet - 1]} from the Orks"}); break; case "still_standing": - unit.add_feat({ident: "still_standing", planet: planet, location: "location", text: $"Was pullled from beneath the carcesses of his slain {alligience} during the {effort} {attack_defend} of {location} {scr_roman_numeral[planet - 1]} from the Orks"}); + _unit.add_feat({ident: "still_standing", planet: planet, location: "location", text: $"Was pullled from beneath the carcesses of his slain {alligience} during the {effort} {attack_defend} of {location} {scr_roman_numeral[planet - 1]} from the Orks"}); } } } else { - //unit "looses combat" - var toughness_check = irandom(99) - (floor(unit.constitution) / 8); //we can build some static test functions for these sorts of things + //_unit "looses combat" + var toughness_check = irandom(99) - (floor(_unit.constitution) / 8); //we can build some static test functions for these sorts of things //now we need some sort of toughness to chart to check against //then take a roll against a seperate injury chart or some such thing //roll against piett??? chance or a miracle ?? diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index 2c8e1cd5da..466be83725 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -130,6 +130,57 @@ function scr_player_combat_weapon_stacks() { exit; } + if (guard == 1) { + var _gi = 0; + var _pg = men; // current Guardsmen in this block + var _tk = veh; // current Leman Russ tanks in this block + + // Massed lasguns, identical to the enemy Guardsman profile in scr_en_weapon: + // one Lasgun per man, attack 60, armour pierce 1, range 6, 30 rounds. + _gi += 1; + wep[_gi] = "Lasgun"; + wep_num[_gi] = max(1, _pg); + range[_gi] = 6; + att[_gi] = 60 * wep_num[_gi]; + apa[_gi] = 1; + ammo[_gi] = 30; + splash[_gi] = 0; + + // Heavy weapons teams. Real Heavy Bolter profile: attack 120, range 16. + _gi += 1; + wep[_gi] = "Heavy Bolter"; + wep_num[_gi] = max(1, round(_pg / 200)); + range[_gi] = 16; + att[_gi] = 120 * wep_num[_gi]; + apa[_gi] = 0; + ammo[_gi] = -1; + splash[_gi] = 0; + + // Leman Russ guns, scaled to the tanks still alive: Battle Cannon 300 (AP) + // and Lascannon 200 (AP). + if (_tk > 0) { + _gi += 1; + wep[_gi] = "Battle Cannon"; + wep_num[_gi] = _tk; + range[_gi] = 12; + att[_gi] = 300 * wep_num[_gi]; + apa[_gi] = round(att[_gi] * 0.6); + ammo[_gi] = -1; + splash[_gi] = 0; + + _gi += 1; + wep[_gi] = "Lascannon"; + wep_num[_gi] = _tk; + range[_gi] = 20; + att[_gi] = 200 * wep_num[_gi]; + apa[_gi] = round(att[_gi] * 0.8); + ammo[_gi] = -1; + splash[_gi] = 0; + } + + exit; + } + var i, g = 0; veh = 0; men = 0; diff --git a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml index 8964092127..beee217c42 100644 --- a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml +++ b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml @@ -584,3 +584,18 @@ function tithe_guardsmen(system_name, planet, amount) { _pdata.edit_guardsmen(amount); return amount; } + +/// @description Total embarked Guard on player ships currently at a given system. +/// @param {string} system_name +/// @returns {real} +function player_guardsmen_at(system_name) { + var _total = 0; + with (obj_ini) { + for (var i = 0; i < array_length(ship); i++) { + if (ship[i] == "") continue; + if (ship_location[i] != system_name) continue; + _total += ship_guardsmen[i]; + } + } + return _total; +} diff --git a/scripts/scr_ui_settings/scr_ui_settings.gml b/scripts/scr_ui_settings/scr_ui_settings.gml index de7de8a8b4..3239d36915 100644 --- a/scripts/scr_ui_settings/scr_ui_settings.gml +++ b/scripts/scr_ui_settings/scr_ui_settings.gml @@ -694,7 +694,7 @@ function scr_draw_mass_equip_gui(){ if (mouse_button_clicked() && (good1 + good2 + good3 + good4 + good5 == 5)) { engage = true; refresh = true; - effect_create_above(ef_firework, 800, 400, 5, c_yellow); + effect_create_depth(depth - 1, ef_firework, 800, 400, 5, c_yellow); } } draw_set_alpha(1); diff --git a/scripts/scr_unit_traits/scr_unit_traits.gml b/scripts/scr_unit_traits/scr_unit_traits.gml index bebec11f65..f901bf4817 100644 --- a/scripts/scr_unit_traits/scr_unit_traits.gml +++ b/scripts/scr_unit_traits/scr_unit_traits.gml @@ -1098,8 +1098,8 @@ function scr_marine_trait_spawning(distribution_set) { } if (struct_exists(dist_modifiers, "trial_type")) { if (struct_exists(dist_modifiers, "recruit_trial")) { - trial_data = dist_modifiers.recruit_trial; - for (var t = 0; t < array_length(trial_data); t++) { + var type_data = dist_modifiers.recruit_trial; + for (var t = 0; t < array_length(type_data); t++) { if (type_data[t][0] == recruit_world_data.aspirant_trial) { dist_rate[1] += type_data[t][1]; } From e088871a4f547877dde2eac8c6f0a2348daab46e Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 17 Jun 2026 20:01:20 +0300 Subject: [PATCH 003/140] Delete Alarm_0.gml --- objects/obj_enunit/Alarm_0.gml | 413 --------------------------------- 1 file changed, 413 deletions(-) delete mode 100644 objects/obj_enunit/Alarm_0.gml diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml deleted file mode 100644 index 96a4f17d48..0000000000 --- a/objects/obj_enunit/Alarm_0.gml +++ /dev/null @@ -1,413 +0,0 @@ -//* This alarm is responsible for the enemy target column selection; - -if (!instance_exists(obj_pnunit)) { - exit; -} - -enemy = flank ? get_leftmost() : get_rightmost(); -if (enemy == "none") { - exit; -} - -var target_unit_index = 0; -var enemy2 = enemy; - -//In melee check -engaged = collision_point(x - 10, y, obj_pnunit, 0, 1) || collision_point(x + 10, y, obj_pnunit, 0, 1); - -if (!engaged) { - // Shooting - for (var i = 0; i < array_length(wep); i++) { - if (!instance_exists(obj_pnunit)) { - exit; - } - - if (wep[i] == "" || wep_num[i] == 0) { - continue; - } - - if ((range[i] == 1) || (ammo[i] == 0)) { - // LOGGER.debug($"A melee or no ammo weapon was found! Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}; Range: {range[i]}; Ammo: {ammo[i]}"); - continue; - } - - if (range[i] == 0) { - LOGGER.error($"{wep[i]} has broken range! This shouldn't happen! Range: {range[i]}; Ammo: {ammo[i]}; Owner: {wep_owner[i]}"); - // LOGGER.debug($"A broken weapon was found! i:{i}; Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}; Range: {range[i]}; Ammo: {ammo[i]}"); - continue; - } - - if (!target_block_is_valid(enemy, obj_pnunit)) { - enemy = flank == 0 ? get_rightmost() : get_leftmost(); - if (!target_block_is_valid(enemy, obj_pnunit)) { - exit; - } - } - - if (instance_exists(obj_nfort) && !flank) { - enemy = instance_nearest(x, y, obj_nfort); - dist = 2; - } else { - dist = get_block_distance(enemy); - } - - target_unit_index = 0; - - if (range[i] >= dist) { - // The weapon is in range; - var _target_vehicles = apa[i] > 0 ? true : false; // AP weapons target vehicles - - // if (string_count("Gauss",wep[i])>0) then _target_vehicles=true; - // if (wep[i]="Missile Launcher") or (wep[i]="Rokkit Launcha") or (wep[i]="Kannon") then _target_vehicles=true; - // if (wep[i]="Big Shoota") then _target_vehicles=false; - // if (wep[i]="Devourer") then _target_vehicles=false; - // if (wep[i]="Gauss Particle Cannon") or (wep[i]="Overcharged Gauss Cannon") or (wep[i]="Particle Whip") then _target_vehicles=true; - - // Weird alpha strike mechanic, that changes target unit index to CM; - if (((wep[i] == "Power Fist") || (wep[i] == "Bolter")) && (obj_ncombat.alpha_strike > 0) && (wep_num[i] > 5)) { - obj_ncombat.alpha_strike -= 0.5; - - var cm_present = false; - var cm_index = -1; - var cm_block = false; - with (obj_pnunit) { - for (var u = 0; u < array_length(unit_struct); u++) { - if (marine_type[u] == obj_ini.role[100][eROLE.CHAPTERMASTER]) { - cm_present = true; - cm_index = u; - cm_block = id; - } - } - } - if (cm_present) { - enemy = cm_block; - target_unit_index = cm_index; - } - } - - // AP weapons attacking vehicles and forts; - var _no_vehicles_present = false; - if (_target_vehicles) { - var _shot = false; - if ((!instance_exists(obj_nfort)) || flank) { - if (block_has_armour(enemy) || (enemy.veh_type[1] == "Defenses")) { - scr_shoot(i, enemy, target_unit_index, "arp", "ranged"); - // LOGGER.debug($"I'm shooting at a vehicle! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); - continue; - } else { - // Front block has no armour. If there are other blocks behind, - // look for a vehicle to hit. If none is found anywhere (including - // a single men-only block, such as a lone Guard rank), fall back - // to shooting the men instead of idling. The original code gated - // this whole fallback behind a multi-block check, so a lone - // men-only block left every AP weapon firing zero shots. - if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != 7)) { - var x2 = enemy.x; - repeat (instance_number(obj_pnunit) - 1) { - x2 += flank == 0 ? -10 : 10; - var enemy2 = instance_nearest(x2, y, obj_pnunit); - if (!target_block_is_valid(enemy2, obj_pnunit)) { - continue; - } - if (range[i] < get_block_distance(enemy2)) { - break; - } - if (block_has_armour(enemy2)) { - scr_shoot(i, enemy2, target_unit_index, "arp", "ranged"); - _shot = true; - break; - } - } - } - if (!_shot) { - _no_vehicles_present = true; - _target_vehicles = false; - } - } - } else { - enemy = instance_nearest(x, y, obj_nfort); - scr_shoot(i, enemy, 1, "arp", "wall"); - // LOGGER.debug($"I'm shooting at the fort! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); - continue; - } - } - - // Non-AP weapons attacking normal units; - if ((!_target_vehicles) && ((!instance_exists(obj_nfort)) || flank)) { - var _shot = false; - if (enemy.men > 0) { - // There are marines in the first column; - scr_shoot(i, enemy, target_unit_index, "att", "ranged"); - // LOGGER.debug($"I'm shooting at a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); - continue; - } else if (instance_number(obj_pnunit) > 1) { - // There were no marines in the first column, looking behind; - var _column_size_value = enemy.column_size; - var x2 = enemy.x; - - repeat (instance_number(obj_pnunit) - 1) { - x2 += !flank ? 10 : -10; - var enemy2 = instance_nearest(x2, y, obj_pnunit); - if (!target_block_is_valid(enemy2, obj_pnunit)) { - // LOGGER.debug($"The block is invalid!"); - continue; - } - - if (range[i] < get_block_distance(enemy2)) { - // LOGGER.debug($"The range is bad!"); - break; - } - - var _back_column_size_value = enemy2.column_size; - if (_back_column_size_value < _column_size_value) { - // LOGGER.debug($"Protection value is too big!"); - continue; - } else { - // Calculate chance of shots passing through to back row - // Higher ratio of back column size to front column size increases pass-through chance - // Maximum chance capped at 40% to ensure some protection remains - var _pass_chance = ((_back_column_size_value / _column_size_value) - 1) * 100; - if (irandom_range(1, 100) < min(_pass_chance, 80)) { - // LOGGER.debug($"I failed the protection check!"); - continue; - } - } - scr_shoot(i, enemy2, target_unit_index, "att", "ranged"); - // LOGGER.debug($"I'm shooting at a normal unit in another row! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); - _shot = true; - break; - } - } - - // We failed to find normal units to attack, attacking vehicles with a non-AP weapon; - //TODO: All of these code blocks should be functions instead; - if (!_shot && !_no_vehicles_present) { - if ((!instance_exists(obj_nfort)) || flank) { - if (block_has_armour(enemy) || (enemy.veh_type[1] == "Defenses")) { - scr_shoot(i, enemy, target_unit_index, "att", "ranged"); - // LOGGER.debug($"I'm shooting at a vehicle, because I can't find a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); - continue; - } else if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != 7)) { - var x2 = enemy.x; - repeat (instance_number(obj_pnunit) - 1) { - x2 += flank == 0 ? -10 : 10; - var enemy2 = instance_nearest(x2, y, obj_pnunit); - if (!target_block_is_valid(enemy2, obj_pnunit)) { - continue; - } - if (range[i] < get_block_distance(enemy2)) { - break; - } - if (block_has_armour(enemy2)) { - scr_shoot(i, enemy2, target_unit_index, "att", "ranged"); - // LOGGER.debug($"I'm shooting at a vehicle in another row, because I can't find a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); - break; - } - } - } - } else { - enemy = instance_nearest(x, y, obj_nfort); - scr_shoot(i, enemy, 1, "att", "wall"); - // LOGGER.debug($"I'm shooting at a fort, because I can't find a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); - continue; - } - } - } - } else { - // LOGGER.debug($"I can't shoot, my range is too small! Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}; Range: {range[i]}"); - continue; - } - LOGGER.error($"{wep[i]} didn't find a valid target! This shouldn't happen!"); - // LOGGER.debug($"We didn't find a valid target! Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); - } -} else if ((engaged || enemy.engaged) && target_block_is_valid(enemy, obj_pnunit)) { - //TODO: The melee code was not refactored; - // Melee - engaged = 1; - var i = 0, dist = 999, no_ap = 1; - // dist=point_distance(x,y,enemy.x,enemy.y)/10; - if (!instance_exists(obj_pnunit)) { - exit; - } - for (var i = 0; i < array_length(wep); i++) { - if (wep[i] == "" || wep_num[i] == 0) { - continue; - } - var _armour_piercing = 0; - if (!instance_exists(obj_pnunit)) { - exit; - } - if (!flank) { - enemy = get_rightmost(); - enemy2 = enemy; - if (enemy == "none") { - exit; - } - dist = get_block_distance(enemy); - } else if (flank) { - enemy = get_leftmost(); - enemy2 = enemy; - if (enemy == "none") { - exit; - } - dist = get_block_distance(enemy); - } - - if ((apa[i] == 0) || (apa[i] < att[i])) { - no_ap += 1; - } - //LOGGER.debug($"{range[i]},{att[i]},{apa[i]},{wep[i]},{enemy}") - if ((range[i] <= 2) || (floor(range[i]) != range[i])) { - // Weapon meets preliminary checks - if (apa[i] > 0) { - _armour_piercing = 1; - } // Determines if it is _armour_piercing or not - if (_armour_piercing && instance_exists(obj_nfort) && (!flank)) { - // Huff and puff and blow the wall down - enemy = instance_nearest(x, y, obj_nfort); - scr_shoot(i, enemy, 1, "arp", "wall"); - continue; - } - if (_armour_piercing) { - // Check for vehicles - var g = 0, good = 0, enemy2; - - if (block_has_armour(enemy)) { - // good=scr_target(enemy,"veh");// First target has vehicles, blow it to hell - scr_shoot(i, enemy, 1, "arp", "melee"); - good = true; - } - if (!good) { - _armour_piercing = 0; - } // Fuck it, shoot at infantry - } - - if ((!_armour_piercing) && target_block_is_valid(enemy, obj_pnunit)) { - // Check for men - // show_message(string(wep[i])); - var enemy2, g = 0, good = 0; - if (enemy.men) { - // good=scr_target(enemy,"men");// First target has vehicles, blow it to hell - scr_shoot(i, enemy, 1, "att", "melee"); - } else if (block_has_armour(enemy)) { - scr_shoot(i, enemy, 1, "arp", "melee"); // Swing anyways, maybe they'll get lucky - } - } - } - } - - // if (no_ap=30) and (enemy.men=0) and (flank=0){// Next turn? - - // } -} - -instance_activate_object(obj_pnunit); - -//TODO: Everything bellow has to be scrapped and reworked; -//! Commented out stuff bellow, until I understand why it exists; -/*if (image_index == -500) { - var leftest, charge = 0, - enemy2 = 0; - - with(obj_pnunit) { - if (x < -4000) { - instance_deactivate_object(id); - } - } - - if (flank == 0) { - move_unit_block("west"); - // instance_activate_object(obj_cursor); - } - if (flank == 1) { - enemy = instance_nearest(x, y, obj_pnunit); // Right most enemy - enemy2 = enemy; - // if (collision_point(x+10,y,obj_pnunit,0,1)) then engaged=1; - // if (!collision_point(x+10,y,obj_pnunit,0,1)) then engaged=0; - move_unit_block(); - - if (!position_empty(x + 10, y)) { - engaged = 1; - } // Quick smash - // instance_activate_object(obj_cursor); - } - -if (!collision_point(x+10,y,obj_pnunit,0,1)) and (!collision_point(x-10,y,obj_pnunit,0,1)) then engaged=0; -if (collision_point(x+10,y,obj_pnunit,0,1)) or (collision_point(x-10,y,obj_pnunit,0,1)) then engaged=1; - - - -var range_shooti; - - i=0; - - - repeat(30){i+=1; - - - - dist=floor(point_distance(enemy2.x,enemy2.y,x,y)/10); - - - - - - range_shoot=""; - - if (wep[i]!="") and (range[i]>=dist) and (ammo[i]!=0){ - if (range[i]!=1) and (engaged=0) then range_shoot="ranged"; - if ((range[i]!=floor(range[i])) or (range[i]=1)) and (engaged=1) then range_shoot="melee"; - } - - - - - - - - if (wep[i]!="") and (range_shoot="ranged") and (range[i]>=dist){// Weapon meets preliminary checks - var _armour_piercing;_armour_piercing=0;if (apa[i]>att[i]) then _armour_piercing=1;// Determines if it is _armour_piercing or not - - // if (wep[i]="Missile Launcher") then _armour_piercing=1; - - if (string_count("Gauss",wep[i])>0) then _armour_piercing=1; - - if (wep[i]="Missile Launcher") or (wep[i]="Rokkit Launcha") or (wep[i]="Kannon") then _armour_piercing=1; - if (wep[i]="Big Shoota") then _armour_piercing=0;if (wep[i]="Devourer") then _armour_piercing=0; - if (wep[i]="Gauss Particle Cannon") or (wep[i]="Overcharged Gauss Cannon") or (wep[i]="Particle Whip") then _armour_piercing=1; - - - if (instance_exists(enemy2)){ - if (enemy2.veh+enemy2.dreads>0) and (enemy2.men=0) and (apa[i]>10) then _armour_piercing=1; - - if (_armour_piercing=1) and (once_only=0){// Check for vehicles - var g,good;g=0;good=0; - - if (enemy.veh>0){ - // good=scr_target(enemy,"veh");// First target has vehicles, blow it to hell - scr_shoot(i,enemy2,good,"arp","ranged"); - } - if (good=0) and (instance_number(obj_pnunit)>1){// First target does not have vehicles, cycle through objects to find one that has vehicles - var x2;x2=enemy2.x; - repeat(instance_number(obj_enunit)-1){ - if (good=0){ - x2+=10;enemy2=instance_nearest(x2,y,obj_pnunit); - if (enemy2.veh+enemy2.dreads>0) and (good=0){ - good=scr_target(enemy2,"veh");// This target has vehicles, blow it to hell - scr_shoot(i,enemy2,good,"arp","ranged");once_only=1; - } - } - } - } - if (good=0) then _armour_piercing=0;// Fuck it, shoot at infantry - } - } - - } - - - -} - - instance_activate_object(obj_pnunit); -} */ From 503a7a99a854bf4b672870a6da2d668f008d3adb Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 17 Jun 2026 20:01:56 +0300 Subject: [PATCH 004/140] Revert "Delete Alarm_0.gml" This reverts commit e088871a4f547877dde2eac8c6f0a2348daab46e. --- objects/obj_enunit/Alarm_0.gml | 413 +++++++++++++++++++++++++++++++++ 1 file changed, 413 insertions(+) create mode 100644 objects/obj_enunit/Alarm_0.gml diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml new file mode 100644 index 0000000000..96a4f17d48 --- /dev/null +++ b/objects/obj_enunit/Alarm_0.gml @@ -0,0 +1,413 @@ +//* This alarm is responsible for the enemy target column selection; + +if (!instance_exists(obj_pnunit)) { + exit; +} + +enemy = flank ? get_leftmost() : get_rightmost(); +if (enemy == "none") { + exit; +} + +var target_unit_index = 0; +var enemy2 = enemy; + +//In melee check +engaged = collision_point(x - 10, y, obj_pnunit, 0, 1) || collision_point(x + 10, y, obj_pnunit, 0, 1); + +if (!engaged) { + // Shooting + for (var i = 0; i < array_length(wep); i++) { + if (!instance_exists(obj_pnunit)) { + exit; + } + + if (wep[i] == "" || wep_num[i] == 0) { + continue; + } + + if ((range[i] == 1) || (ammo[i] == 0)) { + // LOGGER.debug($"A melee or no ammo weapon was found! Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}; Range: {range[i]}; Ammo: {ammo[i]}"); + continue; + } + + if (range[i] == 0) { + LOGGER.error($"{wep[i]} has broken range! This shouldn't happen! Range: {range[i]}; Ammo: {ammo[i]}; Owner: {wep_owner[i]}"); + // LOGGER.debug($"A broken weapon was found! i:{i}; Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}; Range: {range[i]}; Ammo: {ammo[i]}"); + continue; + } + + if (!target_block_is_valid(enemy, obj_pnunit)) { + enemy = flank == 0 ? get_rightmost() : get_leftmost(); + if (!target_block_is_valid(enemy, obj_pnunit)) { + exit; + } + } + + if (instance_exists(obj_nfort) && !flank) { + enemy = instance_nearest(x, y, obj_nfort); + dist = 2; + } else { + dist = get_block_distance(enemy); + } + + target_unit_index = 0; + + if (range[i] >= dist) { + // The weapon is in range; + var _target_vehicles = apa[i] > 0 ? true : false; // AP weapons target vehicles + + // if (string_count("Gauss",wep[i])>0) then _target_vehicles=true; + // if (wep[i]="Missile Launcher") or (wep[i]="Rokkit Launcha") or (wep[i]="Kannon") then _target_vehicles=true; + // if (wep[i]="Big Shoota") then _target_vehicles=false; + // if (wep[i]="Devourer") then _target_vehicles=false; + // if (wep[i]="Gauss Particle Cannon") or (wep[i]="Overcharged Gauss Cannon") or (wep[i]="Particle Whip") then _target_vehicles=true; + + // Weird alpha strike mechanic, that changes target unit index to CM; + if (((wep[i] == "Power Fist") || (wep[i] == "Bolter")) && (obj_ncombat.alpha_strike > 0) && (wep_num[i] > 5)) { + obj_ncombat.alpha_strike -= 0.5; + + var cm_present = false; + var cm_index = -1; + var cm_block = false; + with (obj_pnunit) { + for (var u = 0; u < array_length(unit_struct); u++) { + if (marine_type[u] == obj_ini.role[100][eROLE.CHAPTERMASTER]) { + cm_present = true; + cm_index = u; + cm_block = id; + } + } + } + if (cm_present) { + enemy = cm_block; + target_unit_index = cm_index; + } + } + + // AP weapons attacking vehicles and forts; + var _no_vehicles_present = false; + if (_target_vehicles) { + var _shot = false; + if ((!instance_exists(obj_nfort)) || flank) { + if (block_has_armour(enemy) || (enemy.veh_type[1] == "Defenses")) { + scr_shoot(i, enemy, target_unit_index, "arp", "ranged"); + // LOGGER.debug($"I'm shooting at a vehicle! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); + continue; + } else { + // Front block has no armour. If there are other blocks behind, + // look for a vehicle to hit. If none is found anywhere (including + // a single men-only block, such as a lone Guard rank), fall back + // to shooting the men instead of idling. The original code gated + // this whole fallback behind a multi-block check, so a lone + // men-only block left every AP weapon firing zero shots. + if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != 7)) { + var x2 = enemy.x; + repeat (instance_number(obj_pnunit) - 1) { + x2 += flank == 0 ? -10 : 10; + var enemy2 = instance_nearest(x2, y, obj_pnunit); + if (!target_block_is_valid(enemy2, obj_pnunit)) { + continue; + } + if (range[i] < get_block_distance(enemy2)) { + break; + } + if (block_has_armour(enemy2)) { + scr_shoot(i, enemy2, target_unit_index, "arp", "ranged"); + _shot = true; + break; + } + } + } + if (!_shot) { + _no_vehicles_present = true; + _target_vehicles = false; + } + } + } else { + enemy = instance_nearest(x, y, obj_nfort); + scr_shoot(i, enemy, 1, "arp", "wall"); + // LOGGER.debug($"I'm shooting at the fort! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); + continue; + } + } + + // Non-AP weapons attacking normal units; + if ((!_target_vehicles) && ((!instance_exists(obj_nfort)) || flank)) { + var _shot = false; + if (enemy.men > 0) { + // There are marines in the first column; + scr_shoot(i, enemy, target_unit_index, "att", "ranged"); + // LOGGER.debug($"I'm shooting at a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); + continue; + } else if (instance_number(obj_pnunit) > 1) { + // There were no marines in the first column, looking behind; + var _column_size_value = enemy.column_size; + var x2 = enemy.x; + + repeat (instance_number(obj_pnunit) - 1) { + x2 += !flank ? 10 : -10; + var enemy2 = instance_nearest(x2, y, obj_pnunit); + if (!target_block_is_valid(enemy2, obj_pnunit)) { + // LOGGER.debug($"The block is invalid!"); + continue; + } + + if (range[i] < get_block_distance(enemy2)) { + // LOGGER.debug($"The range is bad!"); + break; + } + + var _back_column_size_value = enemy2.column_size; + if (_back_column_size_value < _column_size_value) { + // LOGGER.debug($"Protection value is too big!"); + continue; + } else { + // Calculate chance of shots passing through to back row + // Higher ratio of back column size to front column size increases pass-through chance + // Maximum chance capped at 40% to ensure some protection remains + var _pass_chance = ((_back_column_size_value / _column_size_value) - 1) * 100; + if (irandom_range(1, 100) < min(_pass_chance, 80)) { + // LOGGER.debug($"I failed the protection check!"); + continue; + } + } + scr_shoot(i, enemy2, target_unit_index, "att", "ranged"); + // LOGGER.debug($"I'm shooting at a normal unit in another row! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); + _shot = true; + break; + } + } + + // We failed to find normal units to attack, attacking vehicles with a non-AP weapon; + //TODO: All of these code blocks should be functions instead; + if (!_shot && !_no_vehicles_present) { + if ((!instance_exists(obj_nfort)) || flank) { + if (block_has_armour(enemy) || (enemy.veh_type[1] == "Defenses")) { + scr_shoot(i, enemy, target_unit_index, "att", "ranged"); + // LOGGER.debug($"I'm shooting at a vehicle, because I can't find a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); + continue; + } else if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != 7)) { + var x2 = enemy.x; + repeat (instance_number(obj_pnunit) - 1) { + x2 += flank == 0 ? -10 : 10; + var enemy2 = instance_nearest(x2, y, obj_pnunit); + if (!target_block_is_valid(enemy2, obj_pnunit)) { + continue; + } + if (range[i] < get_block_distance(enemy2)) { + break; + } + if (block_has_armour(enemy2)) { + scr_shoot(i, enemy2, target_unit_index, "att", "ranged"); + // LOGGER.debug($"I'm shooting at a vehicle in another row, because I can't find a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); + break; + } + } + } + } else { + enemy = instance_nearest(x, y, obj_nfort); + scr_shoot(i, enemy, 1, "att", "wall"); + // LOGGER.debug($"I'm shooting at a fort, because I can't find a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); + continue; + } + } + } + } else { + // LOGGER.debug($"I can't shoot, my range is too small! Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}; Range: {range[i]}"); + continue; + } + LOGGER.error($"{wep[i]} didn't find a valid target! This shouldn't happen!"); + // LOGGER.debug($"We didn't find a valid target! Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); + } +} else if ((engaged || enemy.engaged) && target_block_is_valid(enemy, obj_pnunit)) { + //TODO: The melee code was not refactored; + // Melee + engaged = 1; + var i = 0, dist = 999, no_ap = 1; + // dist=point_distance(x,y,enemy.x,enemy.y)/10; + if (!instance_exists(obj_pnunit)) { + exit; + } + for (var i = 0; i < array_length(wep); i++) { + if (wep[i] == "" || wep_num[i] == 0) { + continue; + } + var _armour_piercing = 0; + if (!instance_exists(obj_pnunit)) { + exit; + } + if (!flank) { + enemy = get_rightmost(); + enemy2 = enemy; + if (enemy == "none") { + exit; + } + dist = get_block_distance(enemy); + } else if (flank) { + enemy = get_leftmost(); + enemy2 = enemy; + if (enemy == "none") { + exit; + } + dist = get_block_distance(enemy); + } + + if ((apa[i] == 0) || (apa[i] < att[i])) { + no_ap += 1; + } + //LOGGER.debug($"{range[i]},{att[i]},{apa[i]},{wep[i]},{enemy}") + if ((range[i] <= 2) || (floor(range[i]) != range[i])) { + // Weapon meets preliminary checks + if (apa[i] > 0) { + _armour_piercing = 1; + } // Determines if it is _armour_piercing or not + if (_armour_piercing && instance_exists(obj_nfort) && (!flank)) { + // Huff and puff and blow the wall down + enemy = instance_nearest(x, y, obj_nfort); + scr_shoot(i, enemy, 1, "arp", "wall"); + continue; + } + if (_armour_piercing) { + // Check for vehicles + var g = 0, good = 0, enemy2; + + if (block_has_armour(enemy)) { + // good=scr_target(enemy,"veh");// First target has vehicles, blow it to hell + scr_shoot(i, enemy, 1, "arp", "melee"); + good = true; + } + if (!good) { + _armour_piercing = 0; + } // Fuck it, shoot at infantry + } + + if ((!_armour_piercing) && target_block_is_valid(enemy, obj_pnunit)) { + // Check for men + // show_message(string(wep[i])); + var enemy2, g = 0, good = 0; + if (enemy.men) { + // good=scr_target(enemy,"men");// First target has vehicles, blow it to hell + scr_shoot(i, enemy, 1, "att", "melee"); + } else if (block_has_armour(enemy)) { + scr_shoot(i, enemy, 1, "arp", "melee"); // Swing anyways, maybe they'll get lucky + } + } + } + } + + // if (no_ap=30) and (enemy.men=0) and (flank=0){// Next turn? + + // } +} + +instance_activate_object(obj_pnunit); + +//TODO: Everything bellow has to be scrapped and reworked; +//! Commented out stuff bellow, until I understand why it exists; +/*if (image_index == -500) { + var leftest, charge = 0, + enemy2 = 0; + + with(obj_pnunit) { + if (x < -4000) { + instance_deactivate_object(id); + } + } + + if (flank == 0) { + move_unit_block("west"); + // instance_activate_object(obj_cursor); + } + if (flank == 1) { + enemy = instance_nearest(x, y, obj_pnunit); // Right most enemy + enemy2 = enemy; + // if (collision_point(x+10,y,obj_pnunit,0,1)) then engaged=1; + // if (!collision_point(x+10,y,obj_pnunit,0,1)) then engaged=0; + move_unit_block(); + + if (!position_empty(x + 10, y)) { + engaged = 1; + } // Quick smash + // instance_activate_object(obj_cursor); + } + +if (!collision_point(x+10,y,obj_pnunit,0,1)) and (!collision_point(x-10,y,obj_pnunit,0,1)) then engaged=0; +if (collision_point(x+10,y,obj_pnunit,0,1)) or (collision_point(x-10,y,obj_pnunit,0,1)) then engaged=1; + + + +var range_shooti; + + i=0; + + + repeat(30){i+=1; + + + + dist=floor(point_distance(enemy2.x,enemy2.y,x,y)/10); + + + + + + range_shoot=""; + + if (wep[i]!="") and (range[i]>=dist) and (ammo[i]!=0){ + if (range[i]!=1) and (engaged=0) then range_shoot="ranged"; + if ((range[i]!=floor(range[i])) or (range[i]=1)) and (engaged=1) then range_shoot="melee"; + } + + + + + + + + if (wep[i]!="") and (range_shoot="ranged") and (range[i]>=dist){// Weapon meets preliminary checks + var _armour_piercing;_armour_piercing=0;if (apa[i]>att[i]) then _armour_piercing=1;// Determines if it is _armour_piercing or not + + // if (wep[i]="Missile Launcher") then _armour_piercing=1; + + if (string_count("Gauss",wep[i])>0) then _armour_piercing=1; + + if (wep[i]="Missile Launcher") or (wep[i]="Rokkit Launcha") or (wep[i]="Kannon") then _armour_piercing=1; + if (wep[i]="Big Shoota") then _armour_piercing=0;if (wep[i]="Devourer") then _armour_piercing=0; + if (wep[i]="Gauss Particle Cannon") or (wep[i]="Overcharged Gauss Cannon") or (wep[i]="Particle Whip") then _armour_piercing=1; + + + if (instance_exists(enemy2)){ + if (enemy2.veh+enemy2.dreads>0) and (enemy2.men=0) and (apa[i]>10) then _armour_piercing=1; + + if (_armour_piercing=1) and (once_only=0){// Check for vehicles + var g,good;g=0;good=0; + + if (enemy.veh>0){ + // good=scr_target(enemy,"veh");// First target has vehicles, blow it to hell + scr_shoot(i,enemy2,good,"arp","ranged"); + } + if (good=0) and (instance_number(obj_pnunit)>1){// First target does not have vehicles, cycle through objects to find one that has vehicles + var x2;x2=enemy2.x; + repeat(instance_number(obj_enunit)-1){ + if (good=0){ + x2+=10;enemy2=instance_nearest(x2,y,obj_pnunit); + if (enemy2.veh+enemy2.dreads>0) and (good=0){ + good=scr_target(enemy2,"veh");// This target has vehicles, blow it to hell + scr_shoot(i,enemy2,good,"arp","ranged");once_only=1; + } + } + } + } + if (good=0) then _armour_piercing=0;// Fuck it, shoot at infantry + } + } + + } + + + +} + + instance_activate_object(obj_pnunit); +} */ From 0e615765a83d99a4f0975c0e693c625709a08ec5 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 18 Jun 2026 00:40:01 +0300 Subject: [PATCH 005/140] Guardsmen moving fix 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. --- objects/obj_enunit/Alarm_0.gml | 27 +++++++ .../scr_player_combat_weapon_stacks.gml | 70 ++++++++++++------- 2 files changed, 72 insertions(+), 25 deletions(-) diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index 96a4f17d48..bb888ecba5 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -299,6 +299,33 @@ if (!engaged) { // if (no_ap=30) and (enemy.men=0) and (flank=0){// Next turn? // } +} else { + // Engaged in melee. The original code skipped every attack once an enemy was + // collision-locked against a player block, so a unit pinned against a line it + // could not shoot through (for example Meganobs against a Guard rank whose + // bayonets cannot pierce mega-armour) just stood there and the round stalled at a + // fixed enemy percentage. Run the melee weapons here so a fully engaged enemy + // still fights in close combat. engaged is computed once per turn, so this never + // double-attacks alongside the not-engaged branch above. + for (var i = 0; i < array_length(wep); i++) { + if (!instance_exists(obj_pnunit)) { + exit; + } + var melee_target = flank ? get_leftmost() : get_rightmost(); + if ((melee_target == "none") || (!target_block_is_valid(melee_target, obj_pnunit))) { + continue; + } + // Melee weapons only: range 1, 2, or fractional. + if ((range[i] <= 2) || (floor(range[i]) != range[i])) { + if ((apa[i] > 0) && block_has_armour(melee_target)) { + scr_shoot(i, melee_target, 1, "arp", "melee"); + } else if (melee_target.men > 0) { + scr_shoot(i, melee_target, 1, "att", "melee"); + } else if (block_has_armour(melee_target)) { + scr_shoot(i, melee_target, 1, "arp", "melee"); + } + } + } } instance_activate_object(obj_pnunit); diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index 466be83725..de330d2afd 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -133,10 +133,8 @@ function scr_player_combat_weapon_stacks() { if (guard == 1) { var _gi = 0; var _pg = men; // current Guardsmen in this block - var _tk = veh; // current Leman Russ tanks in this block - // Massed lasguns, identical to the enemy Guardsman profile in scr_en_weapon: - // one Lasgun per man, attack 60, armour pierce 1, range 6, 30 rounds. + // Massed lasguns: one per man, attack 60, armour pierce 1, range 6, 30 rounds. _gi += 1; wep[_gi] = "Lasgun"; wep_num[_gi] = max(1, _pg); @@ -146,7 +144,22 @@ function scr_player_combat_weapon_stacks() { ammo[_gi] = 30; splash[_gi] = 0; - // Heavy weapons teams. Real Heavy Bolter profile: attack 120, range 16. + // Bayonets (melee, range 1). Required or the block locks up in melee: once an + // enemy is adjacent the fire logic disables every ranged weapon, and with no + // melee weapon the Guard can neither shoot nor swing. Guardsmen are poor in + // melee, so this is a weak profile. + _gi += 1; + wep[_gi] = "Bayonet"; + wep_num[_gi] = max(1, _pg); + range[_gi] = 1; + att[_gi] = 12 * wep_num[_gi]; + apa[_gi] = 0; + ammo[_gi] = -1; + splash[_gi] = 0; + + // Heavy bolters: attack 120, range 16. Anti-infantry support only. The Guard + // carry no anti-tank weapon by design, so a pure-infantry force cannot crack + // armour; they bleed against vehicles unless a Leman Russ tank line is present. _gi += 1; wep[_gi] = "Heavy Bolter"; wep_num[_gi] = max(1, round(_pg / 200)); @@ -156,27 +169,34 @@ function scr_player_combat_weapon_stacks() { ammo[_gi] = -1; splash[_gi] = 0; - // Leman Russ guns, scaled to the tanks still alive: Battle Cannon 300 (AP) - // and Lascannon 200 (AP). - if (_tk > 0) { - _gi += 1; - wep[_gi] = "Battle Cannon"; - wep_num[_gi] = _tk; - range[_gi] = 12; - att[_gi] = 300 * wep_num[_gi]; - apa[_gi] = round(att[_gi] * 0.6); - ammo[_gi] = -1; - splash[_gi] = 0; - - _gi += 1; - wep[_gi] = "Lascannon"; - wep_num[_gi] = _tk; - range[_gi] = 20; - att[_gi] = 200 * wep_num[_gi]; - apa[_gi] = round(att[_gi] * 0.8); - ammo[_gi] = -1; - splash[_gi] = 0; - } + exit; + } + + if (guard == 2) { + // Leman Russ tank line, fielded as its own block separate from the infantry, + // the way the enemy Imperial Guard keep tanks out of their soldier lines. + // Battle Cannon 300 and Lascannon 200, both armour-piercing, scaled to the + // tanks still alive. This is the Guard's only anti-armour. + var _gi = 0; + var _tk = veh; + + _gi += 1; + wep[_gi] = "Battle Cannon"; + wep_num[_gi] = max(1, _tk); + range[_gi] = 12; + att[_gi] = 300 * wep_num[_gi]; + apa[_gi] = round(att[_gi] * 0.6); + ammo[_gi] = -1; + splash[_gi] = 0; + + _gi += 1; + wep[_gi] = "Lascannon"; + wep_num[_gi] = max(1, _tk); + range[_gi] = 20; + att[_gi] = 200 * wep_num[_gi]; + apa[_gi] = round(att[_gi] * 0.8); + ammo[_gi] = -1; + splash[_gi] = 0; exit; } From 13ba261cdc9ae8b97cda778dbeb4a0fdff7c15a2 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 18 Jun 2026 00:54:19 +0300 Subject: [PATCH 006/140] Update Alarm_0.gml --- objects/obj_pnunit/Alarm_0.gml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index 822996c62f..ae9ee205e3 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -75,7 +75,13 @@ try { } if ((range[i] >= dist) && (ammo[i] != 0 || range[i] == 1)) { - if ((range[i] != 1) && (engaged == 0)) { + // Guard blocks (guard > 0) keep firing their ranged weapons even when + // engaged: Guardsmen empty lasguns and heavy bolters into the enemy at + // point-blank, and the tank line keeps its main guns firing once a unit + // reaches it instead of standing mute. Marines keep the vanilla rule of + // ranged only while not engaged. The bayonet (range 1) still resolves on + // the melee line below, so engaged Guard both shoot and stab. + if ((range[i] != 1) && ((engaged == 0) || (guard > 0))) { range_shoot = "ranged"; } if ((range[i] != floor(range[i]) || floor(range[i]) == 1) && engaged == 1) { From 3aae05fba852abe4762e11067cd349122a93fcaa Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Thu, 18 Jun 2026 02:41:59 +0300 Subject: [PATCH 007/140] Update README.md --- docs/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index b885377a6d..19008739a0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,7 +2,8 @@ Chapter Master - Adeptus Dominus Logo

-# Chapter Master - Adeptus Dominus +# Chapter Master - Adeptus Dominus - Imperial Guard mod +**NOTE:**in this version, to get guard you need to press P then "titheguard X" (x being the number), "embarkguard" and then you can deploy them via the menu selection on the planet screen. That's it for now until further implementation arrives. Fixing basic stuff with the guardsmen first. [![Release-Development](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/release_dev.yml/badge.svg)](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/release_dev.yml) [![](https://dcbadge.limes.pink/api/server/https://discord.gg/zAGpqHzsXQ?style=flat)](https://discord.gg/zAGpqHzsXQ) From 061eee1738ac1cce2ef34e97b2288ed9c4a42ef0 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 18 Jun 2026 02:59:44 +0300 Subject: [PATCH 008/140] Updated to latest main version Updated to latest main version --- .gitignore | 9 +- docs/CONTRIBUTING.md | 51 + docs/README.md | 39 +- objects/obj_enunit/Alarm_0.gml | 99 +- objects/obj_enunit/Alarm_1.gml | 875 +++++++----------- objects/obj_enunit/Create_0.gml | 2 - objects/obj_enunit/Draw_0.gml | 13 +- objects/obj_event/Alarm_0.gml | 3 +- objects/obj_event/Create_0.gml | 25 +- objects/obj_event/Draw_0.gml | 23 +- objects/obj_event/Step_0.gml | 195 +--- objects/obj_event_log/Create_0.gml | 4 +- objects/obj_event_log/Draw_0.gml | 2 +- objects/obj_ini/Create_0.gml | 2 +- objects/obj_ncombat/Alarm_0.gml | 88 +- objects/obj_star/Alarm_3.gml | 3 +- objects/obj_star/Create_0.gml | 27 +- objects/obj_star_select/Draw_64.gml | 28 +- scripts/ErrorHandler/ErrorHandler.gml | 4 +- scripts/NameGenerator/NameGenerator.gml | 6 +- scripts/__init/__init.gml | 35 +- .../scr_ChapterTraits/scr_ChapterTraits.gml | 4 +- scripts/scr_PlanetData/scr_PlanetData.gml | 28 +- scripts/scr_chapter_new/scr_chapter_new.gml | 2 +- .../scr_culture_visuals.gml | 36 +- scripts/scr_dialogue/scr_dialogue.gml | 2 +- .../scr_drop_select_function.gml | 19 +- scripts/scr_garrison/scr_garrison.gml | 92 +- scripts/scr_image/scr_image.gml | 100 +- .../scr_initialize_custom.gml | 10 +- scripts/scr_powers/scr_powers.gml | 4 +- .../scr_punit_combat_heplers.gml | 47 +- scripts/scr_ruins_reward/scr_ruins_reward.gml | 2 +- scripts/scr_start_load/scr_start_load.gml | 58 +- scripts/scr_ui_manage/scr_ui_manage.gml | 12 +- scripts/scr_unit_traits/scr_unit_traits.gml | 2 +- 36 files changed, 820 insertions(+), 1131 deletions(-) create mode 100644 docs/CONTRIBUTING.md diff --git a/.gitignore b/.gitignore index ef827bf98b..2101b9e333 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,11 @@ sprites.import.json # This is a cache file for speeding up subsequent pipeline operations. It should not be tracked in git. sprites.info.json -Build/ \ No newline at end of file +# Gamemaker GMRT cache +Build/ + +# AI folders +.gemini/ +.claude/ +.cline/ +.kilo/ diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000000..ecc93a705f --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing + +WIP. + +## GameMaker vs VSCode+Stitch + +There are generally two main ways of working with a **GameMaker** project: through **Visual Studio Code** or through **GameMaker IDE**. + +- Working with the code through **GameMaker IDE** is not recommended for people used to normal IDEs. Use if you have to or like it. +- The preferred alternative is to use [Visual Studio Code](https://code.visualstudio.com/) with the [Stitch](https://github.com/bscotch/stitch) extension, that is available via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=bscotch.bscotch-stitch-vscode). +- You can also use any other IDE to work with the code, but you'll have to use one of the above apps to build, as no other building method is available at the moment. +- Other IDEs have no extended support for **GML** and as such typically are not recommended, unless you know what you're doing. + +Nonetheless, some things will have to be done through **GameMaker IDE**, even if you use other IDEs, including VSCode, such as: + +- Most of the sprite management. +- Debugging with breakpoints, function steps and real-time debugging. +- Profiling. +- Room management. + +Here we'll only look at the VSCode. If you're interested in using the GameMaker IDE instead, see [this](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Compiling) and just skip the 1st step in that instruction. + +## Preparations + +1. Learn what Git, source control, and GitHub are, how to use them. There is no way around it. + - If you are new to Git, then it's recommended to read the [Pro Git](https://git-scm.com/book/en/v2) book. You only need to read the first 3 chapters to comfortably work with Git, optionally chapter 6 to get more info on GitHub. + - If you prefer a more comfortable, graphical user interface based approach to Git, instead of command line, then it's recommended to use one of the options below, both are free and popular: + - [GitKraken](https://www.gitkraken.com/) + [Tutorials](https://www.gitkraken.com/learn/git/tutorials) + - [SourceTree](https://www.sourcetreeapp.com/) + [Tutorials](https://confluence.atlassian.com/get-started-with-sourcetree) +2. Fork the repository. +3. Clone your fork locally through Git CLI or any other GUI wrapper you've chosen. + +## Setting up the Visual Studio Code + +1. Get the Visual Studio Code (VSCode) installed, if not already. + - (Optional) It's recommended to get the Insider version, as it's the most frequently updated one and gets all new features first. + - (Optional) Get a hang of VSCode by reading some guides on the internet, installing some useful QoL extensions, configuring various settings, etc. +2. Add the project's folder that you've cloned to the workspace, wait for it to load. +3. Get the Stitch extension installed. + - (Optional) Watch [this guide video](https://youtu.be/N0wnHauUQjA?si=GPQ22a_LyZq3Y9LP) that covers basic features of **Stitch**, made by its creator. + - (Optional) Edit various **Stitch** specific settings, to improve your QoL. + - (Optional) It's recommended to disable "Run in Terminal" **Stitch** option. This allows you to goto error lines that come up in the output window and custom color output lines. The explanation is in the "Stitch Runner Panel" section on [this page](https://marketplace.visualstudio.com/items?itemName=bscotch.bscotch-stitch-vscode). +4. Run the game by pressing F5 or finding the run button on the **Stitch** panel, wait for it to download the **GameMaker** version and build the game. +5. Ensure that the game launches and works, exit. + +## Working with the code + +- Read the code, modify it, test, repeat. +- Check some general [GML hints](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/General-GML-hints-from-@sinthorion). +- Get accustomed to some [basic styling guidelines](https://github.com/Adeptus-Dominus/ChapterMaster/blob/main/docs/CODE_STYLE.md). +- Check the list of some [useful resources](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Useful-resources). diff --git a/docs/README.md b/docs/README.md index 4b17ddc55b..b885377a6d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,44 +3,57 @@

# Chapter Master - Adeptus Dominus + [![Release-Development](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/release_dev.yml/badge.svg)](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/release_dev.yml) [![](https://dcbadge.limes.pink/api/server/https://discord.gg/zAGpqHzsXQ?style=flat)](https://discord.gg/zAGpqHzsXQ) -[![CodeRabbit Pull Request Reviews](https://img.shields.io/coderabbit/prs/github/Adeptus-Dominus/ChapterMaster?logoColor=%23808080&label=CodeRabbit%20Reviews&labelColor=fd5608&color=545454)](https://coderabbit.ai/) [![GitHub repo size](https://img.shields.io/github/repo-size/Adeptus-Dominus/ChapterMaster?style=flat&label=Repo%20Size&labelColor=4493f8&color=545454)](https://github.com/Adeptus-Dominus/ChapterMaster) **Chapter Master** (aka CM) is a strategy/simulation game, written in **Game Maker Language**, originally designed and developed by Duke.\ This project aims to continue development on the game, fix any bugs, expand and add features. -**Adeptus Dominus** is just how the team of primordial collaborators decided to call themselves. +**Adeptus Dominus** is just how the team of primordial collaborators decided to call themselves and the new version of the game. + +## Links -- Our discord server: [Chapter Master Discord](https://discord.gg/zAGpqHzsXQ) +Our discord server: [Chapter Master Discord](https://discord.gg/zAGpqHzsXQ) - Where most of the development talk, feature suggestion and bug-reporting takes place. - GitHub issues are not used at the moment, as such we use #bug-report-forum in this server to handle bug reports. - If you can code, draw, design, help with the GitHub stuff or just want to help in any way possible - you'll be welcomed with open arms. - If you just love WH40K and want to chat - you'll have a great time in the server as well. -- 1d6Chan Wiki: [Chapter Master: Adeptus Dominus](https://1d6chan.miraheze.org/wiki/Chapter_Master:_Adeptus_Dominus) +1d6Chan Wiki: [Chapter Master: Adeptus Dominus](https://1d6chan.miraheze.org/wiki/Chapter_Master:_Adeptus_Dominus) - With some helpful pages that explain some of the new systems added in the Adeptus Dominus version. - Help with expanding it will be welcomed. -- Don't forget about the [GitHub Wiki (WIP)](https://github.com/Adeptus-Dominus/ChapterMaster/wiki) - - Help with expanding this one will be welcomed as well. - -- Main repository: [Adeptus-Dominus/ChapterMaster](https://github.com/Adeptus-Dominus/ChapterMaster) +Main repository: [Adeptus-Dominus/ChapterMaster](https://github.com/Adeptus-Dominus/ChapterMaster) ## Playing -Just download the [latest release](https://github.com/Adeptus-Dominus/ChapterMaster/releases/latest) or a [development pre-release](https://github.com/Adeptus-Dominus/ChapterMaster/releases), unzip it and launch the .exe. -## Compiling +### Windows + +Download the [latest release](https://github.com/Adeptus-Dominus/ChapterMaster/releases/latest) or a [development pre-release](https://github.com/Adeptus-Dominus/ChapterMaster/releases), unzip it and launch the .exe. + +### Linux -See [Compiling](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Compiling) wiki page or the [GameMaker tutorial](https://help.gamemaker.io/hc/en-us/articles/235186048-Setting-Up-For-Windows). +Pre-compiled Linux binaries are not currently supported. However, you can run the game on Linux by downloading the Windows release `.exe` and running it using **WINE** (or **Proton** / **Steam Play**). This has been reported to work well. Alternatively, you can compile from source. -Creating packages (i.e., creating an .exe with the game) and exporting them is allowed by YoYo Games for non-commercial use.\ -Everything else **must** be covered by [paid **GameMaker** subscriptions](https://gamemaker.io/en/get). +### macOS + +Same as with Linux. + +## Compiling from source + +1. Install the **GameMaker** IDE matching your system (available on the [GameMaker website](https://releases.gamemaker.io/release-notes/2026/0) or [Steam](https://store.steampowered.com/app/1670460/GameMaker/)). +2. Clone or download the repository (find the green **<>Code** button and select **Download ZIP**). +3. Find **ChapterMaster.yyp** in the downloaded folder and open it with **GameMaker**. +4. Select the target platform in the IDE: **Windows, macOS, Ubuntu**. +5. Select the output: **GMS2 VM** (no requirements; fast to compile; worse performance) or **GMS2 YYC** (requires a dedicated compiler; slow to compile; better performance). +6. Press **Run** (F5) to play the game or **Debug** (F6) to use debugger features. ## Contributing Best bet is to ask about everything in our Discord, because things bellow are probably not very helpful at the moment. + - [Working with GameMaker projects](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Working-with-GameMaker-projects) - [Useful Tools/Resources](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Useful-resources) - [Contributing](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Contributing) wiki page (not filled properly) diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index bb888ecba5..7155642f0c 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -1,39 +1,30 @@ -//* This alarm is responsible for the enemy target column selection; +/// @description This alarm is responsible for the enemy target column selection if (!instance_exists(obj_pnunit)) { exit; } enemy = flank ? get_leftmost() : get_rightmost(); -if (enemy == "none") { +if (enemy == noone) { exit; } -var target_unit_index = 0; -var enemy2 = enemy; - //In melee check engaged = collision_point(x - 10, y, obj_pnunit, 0, 1) || collision_point(x + 10, y, obj_pnunit, 0, 1); if (!engaged) { // Shooting for (var i = 0; i < array_length(wep); i++) { - if (!instance_exists(obj_pnunit)) { - exit; - } - if (wep[i] == "" || wep_num[i] == 0) { continue; } if ((range[i] == 1) || (ammo[i] == 0)) { - // LOGGER.debug($"A melee or no ammo weapon was found! Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}; Range: {range[i]}; Ammo: {ammo[i]}"); continue; } if (range[i] == 0) { LOGGER.error($"{wep[i]} has broken range! This shouldn't happen! Range: {range[i]}; Ammo: {ammo[i]}; Owner: {wep_owner[i]}"); - // LOGGER.debug($"A broken weapon was found! i:{i}; Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}; Range: {range[i]}; Ammo: {ammo[i]}"); continue; } @@ -44,6 +35,8 @@ if (!engaged) { } } + var dist = 0; + if (instance_exists(obj_nfort) && !flank) { enemy = instance_nearest(x, y, obj_nfort); dist = 2; @@ -51,18 +44,12 @@ if (!engaged) { dist = get_block_distance(enemy); } - target_unit_index = 0; + var target_unit_index = 0; if (range[i] >= dist) { // The weapon is in range; var _target_vehicles = apa[i] > 0 ? true : false; // AP weapons target vehicles - // if (string_count("Gauss",wep[i])>0) then _target_vehicles=true; - // if (wep[i]="Missile Launcher") or (wep[i]="Rokkit Launcha") or (wep[i]="Kannon") then _target_vehicles=true; - // if (wep[i]="Big Shoota") then _target_vehicles=false; - // if (wep[i]="Devourer") then _target_vehicles=false; - // if (wep[i]="Gauss Particle Cannon") or (wep[i]="Overcharged Gauss Cannon") or (wep[i]="Particle Whip") then _target_vehicles=true; - // Weird alpha strike mechanic, that changes target unit index to CM; if (((wep[i] == "Power Fist") || (wep[i] == "Bolter")) && (obj_ncombat.alpha_strike > 0) && (wep_num[i] > 5)) { obj_ncombat.alpha_strike -= 0.5; @@ -92,7 +79,6 @@ if (!engaged) { if ((!instance_exists(obj_nfort)) || flank) { if (block_has_armour(enemy) || (enemy.veh_type[1] == "Defenses")) { scr_shoot(i, enemy, target_unit_index, "arp", "ranged"); - // LOGGER.debug($"I'm shooting at a vehicle! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); continue; } else { // Front block has no armour. If there are other blocks behind, @@ -127,7 +113,6 @@ if (!engaged) { } else { enemy = instance_nearest(x, y, obj_nfort); scr_shoot(i, enemy, 1, "arp", "wall"); - // LOGGER.debug($"I'm shooting at the fort! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); continue; } } @@ -138,7 +123,6 @@ if (!engaged) { if (enemy.men > 0) { // There are marines in the first column; scr_shoot(i, enemy, target_unit_index, "att", "ranged"); - // LOGGER.debug($"I'm shooting at a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); continue; } else if (instance_number(obj_pnunit) > 1) { // There were no marines in the first column, looking behind; @@ -149,18 +133,15 @@ if (!engaged) { x2 += !flank ? 10 : -10; var enemy2 = instance_nearest(x2, y, obj_pnunit); if (!target_block_is_valid(enemy2, obj_pnunit)) { - // LOGGER.debug($"The block is invalid!"); continue; } if (range[i] < get_block_distance(enemy2)) { - // LOGGER.debug($"The range is bad!"); break; } var _back_column_size_value = enemy2.column_size; if (_back_column_size_value < _column_size_value) { - // LOGGER.debug($"Protection value is too big!"); continue; } else { // Calculate chance of shots passing through to back row @@ -168,12 +149,10 @@ if (!engaged) { // Maximum chance capped at 40% to ensure some protection remains var _pass_chance = ((_back_column_size_value / _column_size_value) - 1) * 100; if (irandom_range(1, 100) < min(_pass_chance, 80)) { - // LOGGER.debug($"I failed the protection check!"); continue; } } scr_shoot(i, enemy2, target_unit_index, "att", "ranged"); - // LOGGER.debug($"I'm shooting at a normal unit in another row! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); _shot = true; break; } @@ -185,7 +164,6 @@ if (!engaged) { if ((!instance_exists(obj_nfort)) || flank) { if (block_has_armour(enemy) || (enemy.veh_type[1] == "Defenses")) { scr_shoot(i, enemy, target_unit_index, "att", "ranged"); - // LOGGER.debug($"I'm shooting at a vehicle, because I can't find a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); continue; } else if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != 7)) { var x2 = enemy.x; @@ -200,7 +178,6 @@ if (!engaged) { } if (block_has_armour(enemy2)) { scr_shoot(i, enemy2, target_unit_index, "att", "ranged"); - // LOGGER.debug($"I'm shooting at a vehicle in another row, because I can't find a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); break; } } @@ -208,59 +185,40 @@ if (!engaged) { } else { enemy = instance_nearest(x, y, obj_nfort); scr_shoot(i, enemy, 1, "att", "wall"); - // LOGGER.debug($"I'm shooting at a fort, because I can't find a normal unit! {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); continue; } } } } else { - // LOGGER.debug($"I can't shoot, my range is too small! Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}; Range: {range[i]}"); continue; } LOGGER.error($"{wep[i]} didn't find a valid target! This shouldn't happen!"); - // LOGGER.debug($"We didn't find a valid target! Weapon: {wep[i]}; Column ID: {id}; Enemy Unit: {wep_owner[i]}"); } } else if ((engaged || enemy.engaged) && target_block_is_valid(enemy, obj_pnunit)) { //TODO: The melee code was not refactored; // Melee engaged = 1; - var i = 0, dist = 999, no_ap = 1; - // dist=point_distance(x,y,enemy.x,enemy.y)/10; - if (!instance_exists(obj_pnunit)) { - exit; - } for (var i = 0; i < array_length(wep); i++) { if (wep[i] == "" || wep_num[i] == 0) { continue; } - var _armour_piercing = 0; - if (!instance_exists(obj_pnunit)) { - exit; - } + var _armour_piercing = false; if (!flank) { enemy = get_rightmost(); - enemy2 = enemy; - if (enemy == "none") { + if (enemy == noone) { exit; } - dist = get_block_distance(enemy); } else if (flank) { enemy = get_leftmost(); - enemy2 = enemy; - if (enemy == "none") { + if (enemy == noone) { exit; } - dist = get_block_distance(enemy); } - if ((apa[i] == 0) || (apa[i] < att[i])) { - no_ap += 1; - } - //LOGGER.debug($"{range[i]},{att[i]},{apa[i]},{wep[i]},{enemy}") if ((range[i] <= 2) || (floor(range[i]) != range[i])) { // Weapon meets preliminary checks if (apa[i] > 0) { - _armour_piercing = 1; + _armour_piercing = true; } // Determines if it is _armour_piercing or not if (_armour_piercing && instance_exists(obj_nfort) && (!flank)) { // Huff and puff and blow the wall down @@ -270,24 +228,20 @@ if (!engaged) { } if (_armour_piercing) { // Check for vehicles - var g = 0, good = 0, enemy2; + var good = false; if (block_has_armour(enemy)) { - // good=scr_target(enemy,"veh");// First target has vehicles, blow it to hell scr_shoot(i, enemy, 1, "arp", "melee"); good = true; } if (!good) { - _armour_piercing = 0; + _armour_piercing = false; } // Fuck it, shoot at infantry } if ((!_armour_piercing) && target_block_is_valid(enemy, obj_pnunit)) { // Check for men - // show_message(string(wep[i])); - var enemy2, g = 0, good = 0; if (enemy.men) { - // good=scr_target(enemy,"men");// First target has vehicles, blow it to hell scr_shoot(i, enemy, 1, "att", "melee"); } else if (block_has_armour(enemy)) { scr_shoot(i, enemy, 1, "arp", "melee"); // Swing anyways, maybe they'll get lucky @@ -295,37 +249,6 @@ if (!engaged) { } } } - - // if (no_ap=30) and (enemy.men=0) and (flank=0){// Next turn? - - // } -} else { - // Engaged in melee. The original code skipped every attack once an enemy was - // collision-locked against a player block, so a unit pinned against a line it - // could not shoot through (for example Meganobs against a Guard rank whose - // bayonets cannot pierce mega-armour) just stood there and the round stalled at a - // fixed enemy percentage. Run the melee weapons here so a fully engaged enemy - // still fights in close combat. engaged is computed once per turn, so this never - // double-attacks alongside the not-engaged branch above. - for (var i = 0; i < array_length(wep); i++) { - if (!instance_exists(obj_pnunit)) { - exit; - } - var melee_target = flank ? get_leftmost() : get_rightmost(); - if ((melee_target == "none") || (!target_block_is_valid(melee_target, obj_pnunit))) { - continue; - } - // Melee weapons only: range 1, 2, or fractional. - if ((range[i] <= 2) || (floor(range[i]) != range[i])) { - if ((apa[i] > 0) && block_has_armour(melee_target)) { - scr_shoot(i, melee_target, 1, "arp", "melee"); - } else if (melee_target.men > 0) { - scr_shoot(i, melee_target, 1, "att", "melee"); - } else if (block_has_armour(melee_target)) { - scr_shoot(i, melee_target, 1, "arp", "melee"); - } - } - } } instance_activate_object(obj_pnunit); diff --git a/objects/obj_enunit/Alarm_1.gml b/objects/obj_enunit/Alarm_1.gml index d61a74bd60..ccd334b738 100644 --- a/objects/obj_enunit/Alarm_1.gml +++ b/objects/obj_enunit/Alarm_1.gml @@ -1,11 +1,7 @@ -var i, g; -i = 0; -g = 0; men = 0; veh = 0; medi = 0; -repeat (20) { - i += 1; +for (var i = 1; i <= 20; i++) { att[i] = 0; apa[i] = 0; wep_num[i] = 0; @@ -13,15 +9,8 @@ repeat (20) { // if (wep_owner[i]!="") and (wep_num[i]>1) then wep_owner[i]="";// What if they are using two ranged weapons? Hmmmmm? } -i = 0; -// men=0;veh=0; -j = 0; -good = 0; -open = 0; - -repeat (700) { - j += 1; +for (var j = 1; j <= 700; j++) { if (dudes_num[j] <= 0) { dudes[j] = ""; dudes_special[j] = ""; @@ -54,24 +43,12 @@ repeat (700) { dudes_vehicle[j + 1] = 0; dudes_damage[j + 1] = 0; dudes_ranged[j + 1] = 1; - dudges_defense[j + 1] = 1; + dudes_defense[j + 1] = 1; dudes_attack[j + 1] = 1; } } -j = 0; - -/*var no_ap;no_ap=0; - -repeat(18){j+=1; - if (apa[j]=0) then no_ap+=1; -} -if (no_ap=18){ - if (dudes_veh -}*/ - -repeat (20) { - j += 1; +for (var j = 1; j <= 20; j++) { if (obj_ncombat.started == 0) { if (dudes[j] == "Malcadon Spyrer") { dudes_ac[j] = 25; @@ -194,34 +171,22 @@ repeat (20) { dudes_dr[j] = 0.6; } } -j = 0; neww = 0; -if ((men + veh == 1) && (instance_number(obj_enunit) == 1)) { - if ((men == 1) && (veh == 0)) { - var i, h; - i = 0; - h = 0; - repeat (20) { - if (h == 0) { - i += 1; - if (dudes_num[i] == 1) { - h = dudes_hp[i]; - obj_ncombat.display_p2 = h; - obj_ncombat.display_p2n = string(dudes[i]); - } - } +if ((men == 1) && (veh == 0) && (instance_number(obj_enunit) == 1)) { + for (var i = 1; i <= 20; i++) { + if (dudes_num[i] == 1) { + obj_ncombat.display_p2 = dudes_hp[i]; + obj_ncombat.display_p2n = string(dudes[i]); + break; } } } if (obj_ncombat.enemy == 1) { - var j; - j = 0; men = 0; - repeat (100) { - j += 1; + for (var j = 1; j <= 100; j++) { veh = 0; dreads = 0; if ((dudes[j] != "") && (dudes_vehicle[j] == 0)) { @@ -229,43 +194,20 @@ if (obj_ncombat.enemy == 1) { } } - // show_message("dudes1:"+string(dudes[1])+", men:"+string(men)); - - var i, g; - i = 0; - g = 0; - repeat (100) { - i += 1; + for (var i = 1; i <= 100; i++) { att[i] = 0; apa[i] = 0; wep_num[i] = 0; wep_rnum[i] = 0; } - i = 0; - - var dreaded; - dreaded = false; - repeat (700) { - g += 1; + for (var g = 1; g <= 700; g++) { // Why was this here? And why was it later checked, if it always would be false?; // marine_casting[g] = false; if (((dudes[g] != "") && (dudes_num[g] > 0)) && (dudes_hp[g] > 0)) { - // if (marine_hp[g]>0) then men+=1; - - /* - scr_en_weapon - argument0: name - argument1: man? - argument2: number - argument3: owner - argument4: dudes number - */ - if ((dudes[g] == obj_ini.role[100][6]) || (dudes[g] == "Venerable " + obj_ini.role[100][6]) && (dudes_hp[g] > 0)) { dreads += 1; - dreaded = true; } if (dudes_mobi[g] == "Bike") { scr_en_weapon("Twin Linked Bolters", false, 1, dudes[g], g); @@ -285,12 +227,8 @@ if (obj_ncombat.enemy == 1) { scr_en_weapon("Plasma Cutter", false, 1, dudes[g], g); } - var j, good, open; - j = 0; - good = 0; - open = 0; // Counts the number and types of marines within this object - repeat (20) { - j += 1; + var open = 0; // Counts the number and types of marines within this object + for (var j = 1; j <= 20; j++) { if ((dudes[j] == "") && (open == 0)) { open = j; // Determine if vehicle here @@ -301,8 +239,6 @@ if (obj_ncombat.enemy == 1) { dudes_vehicle[j] = 1; } } - // if (dudes[g]=dudes[j]){good=1;dudes_num[j]+=1;} - // if (good=0) and (open!=0){dudes[open]=marine_type[g];dudes_num[open]=1;} } if ((dudes_wep1[g] != "") && (marine_casting[g] == false)) { @@ -341,23 +277,15 @@ if (obj_ncombat.enemy == 1) { // Right here should be retreat- if important units are exposed they should try to hop left - /*if (dudes_num[1]=0) and (obj_ncombat.started=0){ - instance_destroy(); - exit; - }*/ - if ((men > 0) && (alarm[5] > 0)) { alarm[5] = -1; } instance_activate_object(obj_enunit); exit; - - /* */ } -if (obj_ncombat.enemy == 2) { - repeat (20) { - j += 1; +if (obj_ncombat.enemy == eFACTION.IMPERIUM) { + for (var j = 1; j <= 20; j++) { if (dudes[j] == "Imperial Guardsman") { dudes_ac[j] = 40; dudes_hp[j] = 5; @@ -436,12 +364,9 @@ if (obj_ncombat.enemy == 2) { // Leman Russ Battle Tank = min.1, max = /40000 // Leman Russ Demolisher = min.1, max = /60000 // Chimera = min.1, max = /60000 - - /* */ } -if (obj_ncombat.enemy == 3) { - repeat (20) { - j += 1; +if (obj_ncombat.enemy == eFACTION.MECHANICUS) { + for (var j = 1; j <= 20; j++) { if (dudes[j] == "Thallax") { scr_en_weapon("Lightning Gun", true, dudes_num[j], dudes[j], j); scr_en_weapon("Thallax Melee", true, dudes_num[j], dudes[j], j); @@ -458,15 +383,9 @@ if (obj_ncombat.enemy == 3) { medi += dudes_num[j]; } } - - // - // - - /* */ } -if (obj_ncombat.enemy == 5) { - repeat (20) { - j += 1; +if (obj_ncombat.enemy == eFACTION.ECCLESIARCHY) { + for (var j = 1; j <= 20; j++) { if (dudes[j] == "Leader") { scr_en_weapon("Blessed Weapon", true, dudes_num[j], dudes[j], j); scr_en_weapon("Laser Mace", true, dudes_num[j], dudes[j], j); @@ -493,7 +412,6 @@ if (obj_ncombat.enemy == 5) { men += dudes_num[j]; dudes_dr[j] = 0.65; } - if (dudes[j] == "Arco-Flagellent") { scr_en_weapon("Electro-Flail", true, dudes_num[j], dudes[j], j); dudes_ac[j] = 5; @@ -501,7 +419,6 @@ if (obj_ncombat.enemy == 5) { men += dudes_num[j]; dudes_dr[j] = 0.7; } - if (dudes[j] == "Celestian") { scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); scr_en_weapon("Chainsword", true, dudes_num[j], dudes[j], j); @@ -524,7 +441,6 @@ if (obj_ncombat.enemy == 5) { men += dudes_num[j]; dudes_dr[j] = 0.75; } - if (dudes[j] == "Battle Sister") { if (dudes_num[j] <= 4) { scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); @@ -573,7 +489,6 @@ if (obj_ncombat.enemy == 5) { men += dudes_num[j]; dudes_dr[j] = 0.85; } - if (dudes[j] == "Follower") { //Frateris Militia scr_en_weapon("Laspistol", true, dudes_num[j], dudes[j], j); @@ -582,7 +497,6 @@ if (obj_ncombat.enemy == 5) { dudes_hp[j] = 30; men += dudes_num[j]; } - if (dudes[j] == "Rhino") { scr_en_weapon("Storm Bolter", false, dudes_num[j] * 2, dudes[j], j); dudes_ac[j] = 30; @@ -591,7 +505,6 @@ if (obj_ncombat.enemy == 5) { veh += dudes_num[j]; dudes_vehicle[j] = 1; } - if (dudes[j] == "Chimera") { scr_en_weapon("Heavy Flamer", false, dudes_num[j] * 2, dudes[j], j); dudes_ac[j] = 30; @@ -600,7 +513,6 @@ if (obj_ncombat.enemy == 5) { veh += dudes_num[j]; dudes_vehicle[j] = 1; } - if (dudes[j] == "Immolator") { scr_en_weapon("Twin Linked Heavy Flamers", false, dudes_num[j], dudes[j], j); dudes_ac[j] = 40; @@ -620,7 +532,6 @@ if (obj_ncombat.enemy == 5) { veh += dudes_num[j]; dudes_vehicle[j] = 1; } - if (dudes[j] == "Penitent Engine") { scr_en_weapon("Close Combat Weapon", false, dudes_num[j] * 2, dudes[j], j); scr_en_weapon("Heavy Flamer", false, dudes_num[j], dudes[j], j); @@ -630,11 +541,6 @@ if (obj_ncombat.enemy == 5) { veh += dudes_num[j]; dudes_vehicle[j] = 1; } - - // if (obj_ncombat.enemy=11) and (dudes_vehicle[j]=0) and (dudes[j]!="Cultist"){dudes_dr[j]=0.8;} - // if (obj_ncombat.enemy=11) and (dudes_vehicle[j]=1){dudes_dr[j]=0.75;} - - // if (dudes[j]!="") and (dudes_num[j]=0){dudes[j]="";dudes_num[j]=0;} if ((dudes[j] != "") && (dudes_hp[j] == 0)) { dudes[j] = ""; dudes_num[j] = 0; @@ -646,12 +552,9 @@ if (obj_ncombat.enemy == 5) { dudes_dr[j] = max(0.65, dudes_dr[j] + 0.15); } } - - /* */ } -if (obj_ncombat.enemy == 6) { - repeat (20) { - j += 1; +if (obj_ncombat.enemy == eFACTION.ELDAR) { + for (var j = 1; j <= 20; j++) { if (dudes[j] == "Leader") { scr_en_weapon("Singing Spear", true, dudes_num[j], dudes[j], j); scr_en_weapon("Singing Spear Throw", true, dudes_num[j], dudes[j], j); @@ -918,12 +821,9 @@ if (obj_ncombat.enemy == 6) { dudes_vehicle[j] = 1; } } - - /* */ } -if (obj_ncombat.enemy == 7) { - repeat (20) { - j += 1; +if (obj_ncombat.enemy == eFACTION.ORK) { + for (var j = 1; j <= 20; j++) { if (dudes[j] == "Leader") { scr_en_weapon("Power Klaw", true, dudes_num[j], dudes[j], j); scr_en_weapon("Rokkit Launcha", true, dudes_num[j], dudes[j], j); @@ -1083,12 +983,9 @@ if (obj_ncombat.enemy == 7) { dudes_vehicle[j] = 1; } } - - /* */ } -if (obj_ncombat.enemy == 8) { - repeat (20) { - j += 1; +if (obj_ncombat.enemy == eFACTION.TAU) { + for (var j = 1; j <= 20; j++) { if (dudes[j] == "XV8 Commander") { scr_en_weapon("Plasma Rifle", true, dudes_num[j], dudes[j], j); scr_en_weapon("Fusion Blaster", true, dudes_num[j], dudes[j], j); @@ -1188,12 +1085,9 @@ if (obj_ncombat.enemy == 8) { dudes_vehicle[j] = 1; } } - - /* */ } -if (obj_ncombat.enemy == 9) { - repeat (20) { - j += 1; +if (obj_ncombat.enemy == eFACTION.TYRANIDS || obj_ncombat.enemy == eFACTION.GENESTEALER) { + for (var j = 1; j <= 20; j++) { if (dudes[j] == "Hive Tyrant") { scr_en_weapon("Bonesword", true, dudes_num[j], dudes[j], j); scr_en_weapon("Lashwhip", true, dudes_num[j], dudes[j], j); @@ -1286,373 +1180,336 @@ if (obj_ncombat.enemy == 9) { men += dudes_num[j]; } } - - /* */ } -if (obj_ncombat.enemy >= 10) { -if (obj_ncombat.enemy < 12) { - repeat (20) { - j += 1; - if ((dudes[j] == "Leader") && (obj_controller.faction_gender[10] == 1)) { - // Terminator Chaos Lord - scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Power Fist", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 35; - if ((obj_ncombat.started == 0) || (dudes_num[j] > 1)) { - dudes_hp[j] = 300; - } - men += dudes_num[j]; - dudes_dr[j] = 0.5; - } - if ((dudes[j] == "Leader") && (obj_controller.faction_gender[10] == 2)) { - // World Eater Lord - scr_en_weapon("Khorne Demon Melee", true, dudes_num[j] * 2, dudes[j], j); - dudes_ac[j] = 25; - if ((obj_ncombat.started == 0) || (dudes_num[j] > 1)) { - dudes_hp[j] = 300; - } - men += dudes_num[j]; - dudes_dr[j] = 0.6; - } - - if (dudes[j] == "Fallen") { - scr_en_weapon("Bolt Pistol", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Power Weapon", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 25; - dudes_hp[j] = 150; - men += dudes_num[j]; - dudes_dr[j] = 0.5; - } - - if (dudes[j] == "Chaos Lord") { - scr_en_weapon("Plasma Pistol", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Power Weapon", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 25; - dudes_hp[j] = 150; - dudes_dr[j] = 0.5; - men += dudes_num[j]; - } - if (dudes[j] == "Chaos Sorcerer") { - scr_en_weapon("Plasma Pistol", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Force Staff", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 25; - dudes_hp[j] = 150; - dudes_dr[j] = 0.5; - men += dudes_num[j]; - } - if (dudes[j] == "Warpsmith") { - scr_en_weapon("Chainfist", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Flamer", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 25; - dudes_hp[j] = 150; - dudes_dr[j] = 0.5; - men += dudes_num[j]; - } - - if (dudes[j] == "Chaos Terminator") { - scr_en_weapon("Power Fist", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Combi-Flamer", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 35; - dudes_hp[j] = 125; - men += dudes_num[j]; - dudes_dr[j] = 0.5; - } - if (dudes[j] == "Venerable Chaos Terminator") { - scr_en_weapon("Power Fist", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Combi-Flamer", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 35; - dudes_hp[j] = 150; - men += dudes_num[j]; - dudes_dr[j] = 0.5; - } - if (dudes[j] == "World Eaters Terminator") { - scr_en_weapon("Power Fist", true, dudes_num[j] * 2, dudes[j], j); - scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 35; - dudes_hp[j] = 150; - men += dudes_num[j]; - dudes_dr[j] = 0.5; - } - if (dudes[j] == "Obliterator") { - scr_en_weapon("Power Fist", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Obliterator Weapon", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 25; - dudes_hp[j] = 300; - dudes_dr[j] = 0.5; - men += dudes_num[j]; - } - if (dudes[j] == "Chaos Chosen") { - scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Chainsword", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 125; - dudes_dr[j] = 0.85; - men += dudes_num[j]; - } - if (dudes[j] == "Venerable Chaos Chosen") { - scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Chainsword", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 150; - men += dudes_num[j]; - dudes_dr[j] = 0.75; - } - - if (dudes[j] == "Possessed") { - scr_en_weapon("Possessed Claws", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 150; - dudes_dr[j] = 0.6; - men += dudes_num[j]; - } - if (dudes[j] == "Chaos Space Marine") { - scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Chainsword", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 100; - dudes_dr[j] = 0.9; - men += dudes_num[j]; - } - if (dudes[j] == "Havoc") { - scr_en_weapon("Missile Launcher", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Melee1", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 100; - dudes_dr[j] = 0.9; - men += dudes_num[j]; - } - if (dudes[j] == "Raptor") { - scr_en_weapon("Chainsword", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Bolt Pistol", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 100; - dudes_dr[j] = 0.75; - dudes_special[j] = "Jump Pack"; - men += dudes_num[j]; - } - - if (dudes[j] == "World Eater") { - scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Chainaxe", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 100; - dudes_dr[j] = 0.75; - men += dudes_num[j]; - } - if (dudes[j] == "World Eaters Veteran") { - scr_en_weapon("Combi-Flamer", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Chainaxe", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 125; - dudes_dr[j] = 0.7; - men += dudes_num[j]; - } - - if (dudes[j] == "Khorne Berzerker") { - scr_en_weapon("Chainaxe", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Bolt Pistol", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 200; - dudes_dr[j] = 0.65; - men += dudes_num[j]; - } - if (dudes[j] == "Plague Marine") { - scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Poison Chainsword", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 180; - dudes_dr[j] = 0.65; - men += dudes_num[j]; - } - if (dudes[j] == "Noise Marine") { - scr_en_weapon("Sonic Blaster", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Melee1", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 125; - dudes_dr[j] = 0.75; - men += dudes_num[j]; - } - if (dudes[j] == "Rubric Marine") { - scr_en_weapon("Rubric Bolter", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Melee1", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 150; - dudes_dr[j] = 0.75; - men += dudes_num[j]; - } - if (dudes[j] == "Rubric Sorcerer") { - scr_en_weapon("Witchfire", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Force Staff", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 150; - dudes_dr[j] = 0.5; - men += dudes_num[j]; - } - if (dudes[j] == "Cultist") { - scr_en_weapon("Autogun", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Melee Weapon", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 5; - dudes_hp[j] = 35; - men += dudes_num[j]; - } - if (dudes[j] == "Hellbrute") { - scr_en_weapon("Power Fist", false, dudes_num[j], dudes[j], j); - scr_en_weapon("Meltagun", false, dudes_num[j], dudes[j], j); - dudes_ac[j] = 40; - dudes_hp[j] = 300; - dudes_dr[j] = 0.6; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; - } - if (dudes[j] == "Rhino") { - scr_en_weapon("Storm Bolter", false, dudes_num[j] * 2, dudes[j], j); - dudes_ac[j] = 30; - dudes_hp[j] = 200; - dudes_dr[j] = 0.75; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; - } - if (dudes[j] == "Predator") { - scr_en_weapon("Lascannon", false, dudes_num[j] * 2, dudes[j], j); - scr_en_weapon("Twin Linked Lascannon", false, dudes_num[j], dudes[j], j); - dudes_ac[j] = 40; - dudes_hp[j] = 350; - dudes_dr[j] = 0.65; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; - } - if (dudes[j] == "Vindicator") { - scr_en_weapon("Demolisher Cannon", false, dudes_num[j], dudes[j], j); - scr_en_weapon("Havoc Launcher", false, dudes_num[j], dudes[j], j); - dudes_ac[j] = 40; +if (obj_ncombat.enemy == eFACTION.CHAOS || obj_ncombat.enemy == eFACTION.HERETICS) { + for (var j = 1; j <= 20; j++) { + if ((dudes[j] == "Leader") && (obj_controller.faction_gender[10] == 1)) { + // Terminator Chaos Lord + scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Power Fist", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 35; + if ((obj_ncombat.started == 0) || (dudes_num[j] > 1)) { dudes_hp[j] = 300; - dudes_dr[j] = 0.65; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; - } - if (dudes[j] == "Land Raider") { - scr_en_weapon("Twin Linked Heavy Bolters", false, dudes_num[j], dudes[j], j); - scr_en_weapon("Twin Linked Lascannon", false, dudes_num[j] * 2, dudes[j], j); - dudes_ac[j] = 50; - dudes_hp[j] = 400; - dudes_dr[j] = 0.5; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; - } - if (dudes[j] == "Heldrake") { - scr_en_weapon("Baleflame", false, dudes_num[j] * 5, dudes[j], j); - dudes_ac[j] = 40; - dudes_hp[j] = 400; - dudes_dr[j] = 0.5; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; } - if (dudes[j] == "Defiler") { - scr_en_weapon("Defiler Claws", false, dudes_num[j], dudes[j], j); - scr_en_weapon("Battle Cannon", false, dudes_num[j], dudes[j], j); - scr_en_weapon("Reaper Autocannon", false, dudes_num[j], dudes[j], j); - scr_en_weapon("Flamer", false, dudes_num[j], dudes[j], j); - dudes_ac[j] = 40; + men += dudes_num[j]; + dudes_dr[j] = 0.5; + } + if ((dudes[j] == "Leader") && (obj_controller.faction_gender[10] == 2)) { + // World Eater Lord + scr_en_weapon("Khorne Demon Melee", true, dudes_num[j] * 2, dudes[j], j); + dudes_ac[j] = 25; + if ((obj_ncombat.started == 0) || (dudes_num[j] > 1)) { dudes_hp[j] = 300; - dudes_dr[j] = 0.65; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; - } - - if (dudes[j] == "Arch Heretic") { - scr_en_weapon("Power Weapon", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Plasma Pistol", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 40; - dudes_dr[j] = 0.85; - men += dudes_num[j]; - } - if (dudes[j] == "Cultist Elite") { - scr_en_weapon("Lasgun", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Chainaxe", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 10; - dudes_hp[j] = 40; - dudes_dr[j] = 0.9; - men += dudes_num[j]; - } - if (dudes[j] == "Mutant") { - scr_en_weapon("Flesh Hooks", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 5; - dudes_hp[j] = 50; - men += dudes_num[j]; - } - if (dudes[j] == "Daemonhost") { - scr_en_weapon("Daemonhost Claws", true, dudes_num[j], dudes[j], j); - scr_en_weapon("Daemonhost_Powers", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 15; - dudes_hp[j] = 200; - dudes_dr[j] = 0.7; - medi += dudes_num[j]; - } - if (dudes[j] == "Possessed") { - scr_en_weapon("Possessed Claws", true, dudes_num[j], dudes[j], j); - dudes_ac[j] = 10; - dudes_hp[j] = 100; - dudes_dr[j] = 0.75; - men += dudes_num[j]; - } - - /* - if (dudes[j]="Greater Daemon of Khorne"){scr_en_weapon("Khorne Demon Melee",true,dudes_num[j],dudes[j],j);dudes_ac[j]=10;dudes_hp[j]=300;dudes_dr[j]=0.25;medi+=dudes_num[j];} - if (dudes[j]="Greater Daemon of Slaanesh"){scr_en_weapon("Demon Melee",true,dudes_num[j],dudes[j],j);scr_en_weapon("Lash Whip",true,dudes_num[j],dudes[j],j);dudes_ac[j]=10;dudes_hp[j]=250;dudes_dr[j]=0.35;medi+=dudes_num[j];} - if (dudes[j]="Greater Daemon of Nurgle"){scr_en_weapon("Demon Melee",true,dudes_num[j],dudes[j],j);scr_en_weapon("Nurgle Vomit",true,dudes_num[j],dudes[j],j);dudes_ac[j]=15;dudes_hp[j]=400;dudes_dr[j]=0.25;medi+=dudes_num[j];} - if (dudes[j]="Greater Daemon of Tzeentch"){scr_en_weapon("Demon Melee",true,dudes_num[j],dudes[j],j);scr_en_weapon("Witchfire",true,dudes_num[j],dudes[j],j);dudes_ac[j]=10;dudes_hp[j]=250;dudes_dr[j]=0.35;medi+=dudes_num[j];} - */ - - if (dudes[j] == "Technical") { - scr_en_weapon("Autogun", false, dudes_num[j] * 2, dudes[j], j); - scr_en_weapon("Heavy Bolter", false, dudes_num[j], dudes[j], j); - dudes_ac[j] = 20; - dudes_hp[j] = 100; - dudes_dr[j] = 0.75; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; - } - - if (dudes[j] == "Chaos Leman Russ") { - scr_en_weapon("Battle Cannon", false, dudes_num[j], dudes[j], j); - scr_en_weapon("Heavy Bolter", false, dudes_num[j], dudes[j], j); - dudes_ac[j] = 40; - dudes_hp[j] = 250; - dudes_dr[j] = 0.5; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; - } - if (dudes[j] == "Chaos Basilisk") { - scr_en_weapon("Earthshaker Cannon", false, dudes_num[j], dudes[j], j); - scr_en_weapon("Heavy Bolter", false, dudes_num[j], dudes[j], j); - dudes_ac[j] = 30; - dudes_hp[j] = 150; - dudes_dr[j] = 0.75; - veh += dudes_num[j]; - dudes_vehicle[j] = 1; - } - - // if (obj_ncombat.enemy=11) and (dudes_vehicle[j]=0) and (dudes[j]!="Cultist"){dudes_dr[j]=0.8;} - // if (obj_ncombat.enemy=11) and (dudes_vehicle[j]=1){dudes_dr[j]=0.75;} - - // if (dudes[j]!="") and (dudes_num[j]=0){dudes[j]="";dudes_num[j]=0;} - if ((dudes[j] != "") && (dudes_hp[j] == 0)) { - dudes[j] = ""; - dudes_num[j] = 0; } + men += dudes_num[j]; + dudes_dr[j] = 0.6; + } + if (dudes[j] == "Fallen") { + scr_en_weapon("Bolt Pistol", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Power Weapon", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 25; + dudes_hp[j] = 150; + men += dudes_num[j]; + dudes_dr[j] = 0.5; + } + if (dudes[j] == "Chaos Lord") { + scr_en_weapon("Plasma Pistol", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Power Weapon", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 25; + dudes_hp[j] = 150; + dudes_dr[j] = 0.5; + men += dudes_num[j]; + } + if (dudes[j] == "Chaos Sorcerer") { + scr_en_weapon("Plasma Pistol", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Force Staff", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 25; + dudes_hp[j] = 150; + dudes_dr[j] = 0.5; + men += dudes_num[j]; + } + if (dudes[j] == "Warpsmith") { + scr_en_weapon("Chainfist", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Flamer", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 25; + dudes_hp[j] = 150; + dudes_dr[j] = 0.5; + men += dudes_num[j]; + } + if (dudes[j] == "Chaos Terminator") { + scr_en_weapon("Power Fist", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Combi-Flamer", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 35; + dudes_hp[j] = 125; + men += dudes_num[j]; + dudes_dr[j] = 0.5; + } + if (dudes[j] == "Venerable Chaos Terminator") { + scr_en_weapon("Power Fist", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Combi-Flamer", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 35; + dudes_hp[j] = 150; + men += dudes_num[j]; + dudes_dr[j] = 0.5; + } + if (dudes[j] == "World Eaters Terminator") { + scr_en_weapon("Power Fist", true, dudes_num[j] * 2, dudes[j], j); + scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 35; + dudes_hp[j] = 150; + men += dudes_num[j]; + dudes_dr[j] = 0.5; + } + if (dudes[j] == "Obliterator") { + scr_en_weapon("Power Fist", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Obliterator Weapon", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 25; + dudes_hp[j] = 300; + dudes_dr[j] = 0.5; + men += dudes_num[j]; + } + if (dudes[j] == "Chaos Chosen") { + scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Chainsword", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 125; + dudes_dr[j] = 0.85; + men += dudes_num[j]; + } + if (dudes[j] == "Venerable Chaos Chosen") { + scr_en_weapon("Meltagun", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Chainsword", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 150; + men += dudes_num[j]; + dudes_dr[j] = 0.75; + } + if (dudes[j] == "Chaos Space Marine") { + scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Chainsword", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 100; + dudes_dr[j] = 0.9; + men += dudes_num[j]; + } + if (dudes[j] == "Havoc") { + scr_en_weapon("Missile Launcher", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Melee1", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 100; + dudes_dr[j] = 0.9; + men += dudes_num[j]; + } + if (dudes[j] == "Raptor") { + scr_en_weapon("Chainsword", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Bolt Pistol", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 100; + dudes_dr[j] = 0.75; + dudes_special[j] = "Jump Pack"; + men += dudes_num[j]; + } + if (dudes[j] == "World Eater") { + scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Chainaxe", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 100; + dudes_dr[j] = 0.75; + men += dudes_num[j]; + } + if (dudes[j] == "World Eaters Veteran") { + scr_en_weapon("Combi-Flamer", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Chainaxe", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 125; + dudes_dr[j] = 0.7; + men += dudes_num[j]; + } + if (dudes[j] == "Khorne Berzerker") { + scr_en_weapon("Chainaxe", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Bolt Pistol", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 200; + dudes_dr[j] = 0.65; + men += dudes_num[j]; + } + if (dudes[j] == "Plague Marine") { + scr_en_weapon("Bolter", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Poison Chainsword", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 180; + dudes_dr[j] = 0.65; + men += dudes_num[j]; + } + if (dudes[j] == "Noise Marine") { + scr_en_weapon("Sonic Blaster", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Melee1", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 125; + dudes_dr[j] = 0.75; + men += dudes_num[j]; + } + if (dudes[j] == "Rubric Marine") { + scr_en_weapon("Rubric Bolter", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Melee1", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 150; + dudes_dr[j] = 0.75; + men += dudes_num[j]; + } + if (dudes[j] == "Rubric Sorcerer") { + scr_en_weapon("Witchfire", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Force Staff", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 150; + dudes_dr[j] = 0.5; + men += dudes_num[j]; + } + if (dudes[j] == "Cultist") { + scr_en_weapon("Autogun", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Melee Weapon", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 5; + dudes_hp[j] = 35; + men += dudes_num[j]; + } + if (dudes[j] == "Hellbrute") { + scr_en_weapon("Power Fist", false, dudes_num[j], dudes[j], j); + scr_en_weapon("Meltagun", false, dudes_num[j], dudes[j], j); + dudes_ac[j] = 40; + dudes_hp[j] = 300; + dudes_dr[j] = 0.6; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if (dudes[j] == "Rhino") { + scr_en_weapon("Storm Bolter", false, dudes_num[j] * 2, dudes[j], j); + dudes_ac[j] = 30; + dudes_hp[j] = 200; + dudes_dr[j] = 0.75; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if (dudes[j] == "Predator") { + scr_en_weapon("Lascannon", false, dudes_num[j] * 2, dudes[j], j); + scr_en_weapon("Twin Linked Lascannon", false, dudes_num[j], dudes[j], j); + dudes_ac[j] = 40; + dudes_hp[j] = 350; + dudes_dr[j] = 0.65; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if (dudes[j] == "Vindicator") { + scr_en_weapon("Demolisher Cannon", false, dudes_num[j], dudes[j], j); + scr_en_weapon("Havoc Launcher", false, dudes_num[j], dudes[j], j); + dudes_ac[j] = 40; + dudes_hp[j] = 300; + dudes_dr[j] = 0.65; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if (dudes[j] == "Land Raider") { + scr_en_weapon("Twin Linked Heavy Bolters", false, dudes_num[j], dudes[j], j); + scr_en_weapon("Twin Linked Lascannon", false, dudes_num[j] * 2, dudes[j], j); + dudes_ac[j] = 50; + dudes_hp[j] = 400; + dudes_dr[j] = 0.5; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if (dudes[j] == "Heldrake") { + scr_en_weapon("Baleflame", false, dudes_num[j] * 5, dudes[j], j); + dudes_ac[j] = 40; + dudes_hp[j] = 400; + dudes_dr[j] = 0.5; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if (dudes[j] == "Defiler") { + scr_en_weapon("Defiler Claws", false, dudes_num[j], dudes[j], j); + scr_en_weapon("Battle Cannon", false, dudes_num[j], dudes[j], j); + scr_en_weapon("Reaper Autocannon", false, dudes_num[j], dudes[j], j); + scr_en_weapon("Flamer", false, dudes_num[j], dudes[j], j); + dudes_ac[j] = 40; + dudes_hp[j] = 300; + dudes_dr[j] = 0.65; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if (dudes[j] == "Arch Heretic") { + scr_en_weapon("Power Weapon", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Plasma Pistol", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 40; + dudes_dr[j] = 0.85; + men += dudes_num[j]; + } + if (dudes[j] == "Cultist Elite") { + scr_en_weapon("Lasgun", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Chainaxe", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 10; + dudes_hp[j] = 40; + dudes_dr[j] = 0.9; + men += dudes_num[j]; + } + if (dudes[j] == "Mutant") { + scr_en_weapon("Flesh Hooks", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 5; + dudes_hp[j] = 50; + men += dudes_num[j]; + } + if (dudes[j] == "Daemonhost") { + scr_en_weapon("Daemonhost Claws", true, dudes_num[j], dudes[j], j); + scr_en_weapon("Daemonhost_Powers", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 15; + dudes_hp[j] = 200; + dudes_dr[j] = 0.7; + medi += dudes_num[j]; + } + if (dudes[j] == "Possessed") { + scr_en_weapon("Possessed Claws", true, dudes_num[j], dudes[j], j); + dudes_ac[j] = 10; + dudes_hp[j] = 100; + dudes_dr[j] = 0.75; + men += dudes_num[j]; + } + if (dudes[j] == "Technical") { + scr_en_weapon("Autogun", false, dudes_num[j] * 2, dudes[j], j); + scr_en_weapon("Heavy Bolter", false, dudes_num[j], dudes[j], j); + dudes_ac[j] = 20; + dudes_hp[j] = 100; + dudes_dr[j] = 0.75; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if (dudes[j] == "Chaos Leman Russ") { + scr_en_weapon("Battle Cannon", false, dudes_num[j], dudes[j], j); + scr_en_weapon("Heavy Bolter", false, dudes_num[j], dudes[j], j); + dudes_ac[j] = 40; + dudes_hp[j] = 250; + dudes_dr[j] = 0.5; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if (dudes[j] == "Chaos Basilisk") { + scr_en_weapon("Earthshaker Cannon", false, dudes_num[j], dudes[j], j); + scr_en_weapon("Heavy Bolter", false, dudes_num[j], dudes[j], j); + dudes_ac[j] = 30; + dudes_hp[j] = 150; + dudes_dr[j] = 0.75; + veh += dudes_num[j]; + dudes_vehicle[j] = 1; + } + if ((dudes[j] != "") && (dudes_hp[j] == 0)) { + dudes[j] = ""; + dudes_num[j] = 0; } - - /* */ } } -if (obj_ncombat.enemy == 13) { - repeat (20) { - j += 1; - +if (obj_ncombat.enemy == eFACTION.NECRONS) { + for (var j = 1; j <= 20; j++) { if (dudes[j] == "Necron Overlord") { scr_en_weapon("Staff of Light", true, dudes_num[j], dudes[j], j); scr_en_weapon("Staff of Light Shooting", true, dudes_num[j], dudes[j], j); @@ -1670,7 +1527,6 @@ if (obj_ncombat.enemy == 13) { dudes_dr[j] = 0.75; men += dudes_num[j]; } - if (dudes[j] == "Flayed One") { scr_en_weapon("Melee Weapon", true, dudes_num[j], dudes[j], j); dudes_ac[j] = 10; @@ -1694,7 +1550,6 @@ if (obj_ncombat.enemy == 13) { dudes_dr[j] = 0.85; men += dudes_num[j]; } - if (dudes[j] == "Necron Wraith") { scr_en_weapon("Wraith Claws", true, dudes_num[j], dudes[j], j); if ((obj_ncombat.started == 0) || (dudes_num[j] > 1)) { @@ -1712,7 +1567,6 @@ if (obj_ncombat.enemy == 13) { dudes_dr[j] = 0.75; men += dudes_num[j]; } - if (dudes[j] == "Tomb Stalker") { scr_en_weapon("Gauss Particle Cannon", false, dudes_num[j] * 1, dudes[j], j); scr_en_weapon("Overcharged Gauss Cannon", false, dudes_num[j] * 2, dudes[j], j); @@ -1761,32 +1615,8 @@ if (obj_ncombat.enemy == 13) { veh += dudes_num[j]; dudes_vehicle[j] = 1; } - - // if (dudes_dr[j]>0.8) then dudes_dr[j]=0.8; } - - /* */ -} -/* -if (obj_ncombat.battle_special = "ruins") or(obj_ncombat.battle_special = "ruins_eldar") { - var i; - i = 0; - repeat(20) { - i += 1; - if (dudes_vehicle[i] > 0) and(dudes_num[i] > 0) { - obj_ncombat.enemy_forces -= dudes_num[i]; - obj_ncombat.enemy_max -= dudes_num[i]; - dudes[i] = ""; - dudes_special[i] = ""; - dudes_num[i] = 0; - dudes_ac[i] = 0; - dudes_hp[i] = 0; - dudes_dr[i] = 1; - dudes_vehicle[i] = 0; - } - } } -*/ if (men + veh + medi <= 0) { instance_destroy(id); @@ -1801,6 +1631,3 @@ engaged = collision_point(x + 12, y, obj_pnunit, 0, 1) || collision_point(x - 12 if (neww == 1) { neww = 0; } - -/* */ -/* */ diff --git a/objects/obj_enunit/Create_0.gml b/objects/obj_enunit/Create_0.gml index e5b63b9c75..51a9373e1c 100644 --- a/objects/obj_enunit/Create_0.gml +++ b/objects/obj_enunit/Create_0.gml @@ -81,8 +81,6 @@ if (obj_ncombat.enemy == 1) { alarm[6] = 10; } -// if (obj_ncombat.enemy=1){alarm[1]=8;alarm[5]=10;} - hit = function() { return scr_hit(x1, y1, x2, y2) && obj_ncombat.fadein <= 0; }; diff --git a/objects/obj_enunit/Draw_0.gml b/objects/obj_enunit/Draw_0.gml index 8c1447084a..0006f1603e 100644 --- a/objects/obj_enunit/Draw_0.gml +++ b/objects/obj_enunit/Draw_0.gml @@ -25,11 +25,10 @@ if (draw_size > 0) { if (obj_ncombat.enemy != 1) { composition_string = block_composition_string(); } else { - var variety, variety_num, sofar, compl; - variety = []; - variety_num = []; - sofar = 0; - compl = ""; + var variety = []; + var variety_num = []; + var sofar = 0; + var compl = ""; var variety_len = array_length(variety); for (var q = 0; q < variety_len; q++) { @@ -47,10 +46,10 @@ if (draw_size > 0) { } } - var dudes_len = array_length(dudes); + dudes_len = array_length(dudes); for (var q = 0; q < dudes_len; q++) { if (dudes[q] != "") { - var variety_len = array_length(variety); + variety_len = array_length(variety); for (var i = 0; i < variety_len; i++) { if (dudes[q] == variety[i]) { variety_num[i] += dudes_num[q]; diff --git a/objects/obj_event/Alarm_0.gml b/objects/obj_event/Alarm_0.gml index 7d6d07e34d..aa4bf2ed4f 100644 --- a/objects/obj_event/Alarm_0.gml +++ b/objects/obj_event/Alarm_0.gml @@ -1,5 +1,4 @@ -var intro; -intro = ""; +var intro = ""; if (obj_controller.fest_type == "Great Feast") { if (obj_controller.fest_feasts == 0) { diff --git a/objects/obj_event/Create_0.gml b/objects/obj_event/Create_0.gml index 80cc3c704a..1c69075a04 100644 --- a/objects/obj_event/Create_0.gml +++ b/objects/obj_event/Create_0.gml @@ -14,10 +14,7 @@ closing = false; attendants = 0; avatars = 0; -var i; -i = -1; -repeat (2501) { - i += 1; +for (var i = 0; i <= 2500; i++) { attend_co[i] = 0; attend_id[i] = 0; attend_mood[i] = ""; @@ -64,23 +61,13 @@ scr_colors_initialize(); scr_shader_initialize(); if (obj_controller.fest_display > 0) { - var q, yep; - q = 0; - yep = 0; if (obj_ini.artifact_tags[obj_controller.fest_display] != obj_controller.fest_display_tags) { - repeat (20) { - q += 1; - if (yep == 0) { - if (obj_ini.artifact_tags[q] == obj_controller.fest_display_tags) { - yep = q; - } + obj_controller.fest_display = 0; + for (var q = 1; q <= 20; q++) { + if (obj_ini.artifact_tags[q] == obj_controller.fest_display_tags) { + obj_controller.fest_display = q; + break; } } - if (yep > 0) { - obj_controller.fest_display = q; - } - if (yep == 0) { - obj_controller.fest_display = 0; - } } } diff --git a/objects/obj_event/Draw_0.gml b/objects/obj_event/Draw_0.gml index 5c6e7f5820..5aad0920b6 100644 --- a/objects/obj_event/Draw_0.gml +++ b/objects/obj_event/Draw_0.gml @@ -1,6 +1,5 @@ var xx = camera_get_view_x(view_camera[0]) + 317; var yy = camera_get_view_y(view_camera[0]) + 144; -var ii = 0; draw_set_alpha(fade_alpha); @@ -41,14 +40,11 @@ if (avatars > 0) { draw_set_halign(fa_center); draw_set_color(c_black); - repeat (8) { - ii += 1; + for (var i = 1; i <= 8; i++) { x5 += 120; - if (avatar_name[ii] != "") { - // draw_sprite(spr_popup_event_avatar,avatar_image[ii],x5,y5); - scr_image("event", avatar_image[ii], x5, y5, 97, 95); - draw_text_transformed(x5 + 47, y5 + 99, string_hash_to_newline(string(avatar_name[ii])), 0.75, 1, 0); - // draw_text(x5+45,y5+100,string(avatar_name[ii])+"#"+string(avatar_rank[ii])); + if (avatar_name[i] != "") { + scr_image("event", avatar_image[i], x5, y5, 97, 95); + draw_text_transformed(x5 + 47, y5 + 99, string_hash_to_newline(string(avatar_name[i])), 0.75, 1, 0); } } @@ -64,8 +60,7 @@ draw_set_halign(fa_left); draw_set_font(fnt_40k_14); if (exit_fade >= 0) { - var ealpha; - ealpha = exit_fade / 30; + var ealpha = exit_fade / 30; draw_set_alpha(min(fade_alpha, ealpha)); if (exit_fade < 30) { @@ -89,11 +84,9 @@ if (exit_fade >= 0) { draw_set_color(c_gray); draw_set_alpha(fade_alpha); -ii = 0; -y5 = yy + 120 - 21; -repeat (17) { +y5 = yy + 99; +for (var i = 1; i <= 17; i++) { y5 += 21; - ii += 1; - draw_text_ext(xx + 25, y5, string_hash_to_newline(string(line[ii])), -1, 916); + draw_text_ext(xx + 25, y5, string_hash_to_newline(string(line[i])), -1, 916); } draw_set_alpha(1); diff --git a/objects/obj_event/Step_0.gml b/objects/obj_event/Step_0.gml index ee6992643f..702943e59f 100644 --- a/objects/obj_event/Step_0.gml +++ b/objects/obj_event/Step_0.gml @@ -25,10 +25,8 @@ if ((closing == true) && (fading == -1) && (fade_alpha <= 0)) { } } - var ide = 0, unit; - repeat (700) { - ide += 1; - unit = obj_ini.TTRPG[attend_co[ide]][attend_id[ide]]; + for (var ide = 1; ide <= 700; ide++) { + var unit = obj_ini.TTRPG[attend_co[ide]][attend_id[ide]]; if ((attend_corrupted[ide] == 0) && (attend_id[ide] > 0)) { if (array_contains(obj_ini.artifact_tags[obj_controller.fest_display], "chaos")) { unit.corruption += choose(1, 2, 3, 4); @@ -44,17 +42,9 @@ if ((closing == true) && (fading == -1) && (fade_alpha <= 0)) { if (obj_controller.fest_repeats <= 0) { obj_controller.fest_scheduled = 0; - var p1, p2, p3; - p1 = obj_controller.fest_type; - p3 = ""; - p2 = obj_controller.fest_planet; - - if (p2 > 0) { - p3 = string(obj_controller.fest_star) + " " + scr_roman(obj_controller.fest_wid); - } - if (p2 <= 0) { - p3 = +" the vessel '" + string(obj_ini.ship[obj_controller.fest_sid]) + "'"; - } + var p1 = obj_controller.fest_type; + var p2 = obj_controller.fest_planet; + var p3 = (p2 > 0) ? string(obj_controller.fest_star) + " " + scr_roman(obj_controller.fest_wid) : " the vessel '" + string(obj_ini.ship[obj_controller.fest_sid]) + "'"; scr_alert("green", "event", string(p1) + " on " + string(p3) + " ends.", 0, 0); scr_event_log("green", string(p1) + " on " + string(p3) + " ends.", p3); @@ -85,6 +75,7 @@ if (ticked == 1) { } if ((lines_acted == 18) && (part2 != "")) { + var textt = ""; if (part2 == "fish") { if (attendants <= 30) { textt = "Chapter Serfs ferry out several large, covered dishes, the scent of seafood filling the air. Once they are set front and center the silver cloches are removed, revealing a banquet of exotic fish. Raw rolls of meat with rice, pufferfish, and even a massive broadbill are contained within."; @@ -102,10 +93,10 @@ if (ticked == 1) { ticks = -120; ticked = 0; stage = 6; - textt = ""; exit; } if ((lines_acted == 36) && (part3 != "")) { + var textt = ""; if (part3 == "lobster") { textt = "A small army of Chapter Serfs and servitors enter the room, carrying with them a truly massive silver plate. Bore much like a palanquin, the massive dish is covered by an equally large and decorated cloche. As the main course inches across the room it gathers quite the number of looks. After struggling a bit the dish is set front and center in the room, the lid removed. Contained within is a giant, boiled Deathcoleri from Zeriah II. The once spikey carapace is now a healthily cooked red, the crustacean smelling absolutely delicious."; } @@ -115,81 +106,49 @@ if (ticked == 1) { ticks = -210; ticked = 0; stage = 7; - textt = ""; exit; } - var ide, good, dire, orig, dice1, dice2, dice3, dice4, txtt, rando, doso, activity; - good = false; - doso = false; - activity = ""; - dire = 0; - orig = 0; - rando = choose(1, 2); - dice1 = floor(random(100)) + 1; - dice2 = floor(random(100)) + 1; - dice3 = floor(random(100)) + 1; + var ide = floor(random(attendants)) + 1; var unit = obj_ini.TTRPG[attend_co[ide]][attend_id[ide]]; - - repeat (20) { - if (good == false) { - good = true; - ide = floor(random(attendants)) + 1; - if (unit.IsSpecialist(SPECIALISTS_HEADS)) { - good = false; - } - } - } - if (good == false) { - good = true; - } + var textt = ""; + var doso = false; + var activity = ""; + var dire = 0; + var orig = 0; + var rando = choose(1, 2); + var dice1 = floor(random(100)) + 1; + var dice2 = floor(random(100)) + 1; + var dice3 = floor(random(100)) + 1; + var dice4 = floor(random(100)) + 1; + var good = true; // If this marine has already acted then look for a nearby marine that has yet to act if (attend_displayed[ide] > 0) { - if (attend_displayed[ide] <= attendants / 2) { - dire = -1; - } - if (attend_displayed[ide] > attendants / 2) { - dire = 1; - } + dire = (attend_displayed[ide] <= attendants / 2) ? -1 : 1; orig = ide; } // Cycle downward if (dire == -1) { good = false; - var resp; - resp = ide; - - repeat (resp) { - if (good == false) { - ide -= 1; - if (attend_displayed[ide] == 0) { - good = true; - } + for (var resp = ide - 1; resp >= 0; resp--) { + if (attend_displayed[resp] == 0) { + good = true; + break; } } - if (good == false) { - dire = 1; - } - if (good == true) { - dire = 0; - } + dire = (good) ? 0 : 1; } // Cycle upward if (dire == 1) { good = false; - var resp; - resp = attendants; - - repeat (resp) { - if (good == false) { - ide += 1; - if (attend_displayed[ide] == 0) { - good = true; - } + for (var resp = 0; resp < attendants; resp++) { + if (attend_displayed[resp] == 0) { + good = true; + break; } } } @@ -213,7 +172,6 @@ if (ticked == 1) { if ((attend_confused[ide] <= 0) && (activity == "")) { doso = true; } - var unit = obj_ini.TTRPG[attend_co[ide]][attend_id[ide]]; if (doso == true) { dice1 = floor(random(100)) + 1; dice2 = floor(random(100)) + 1; @@ -222,21 +180,16 @@ if (ticked == 1) { if (obj_controller.fest_type == "Great Feast") { // Get chances of random crap when in a Great Feast - var mod1, mod2, mod3, rep1, rep2, rep3; - mod1 = 0; - mod2 = 0; - mod3 = 0; + var mod1 = 0; + var mod2 = unit.corruption / 5; + var mod3 = unit.corruption / 10; - rep1 = 1; // attend_feasted[ide]+1; - rep2 = attend_drunk[ide] + 1; - rep3 = attend_high[ide] + 1; - - mod2 = unit.corruption / 5; - mod3 = unit.corruption / 10; + var rep1 = 1; + var rep2 = attend_drunk[ide] + 1; + var rep3 = attend_high[ide] + 1; activity = "talk"; - // show_message("roll needed for eating: >="+string((((obj_controller.fest_feasts*30)-10)+mod1)/rep1)+", rolled:"+string(dice1)); if ((dice3 <= min(75, (((obj_controller.fest_drugses * 10) - 10) + mod3) / rep3)) && (obj_controller.fest_feature3 > 0)) { activity = "drugs"; } @@ -368,8 +321,7 @@ if (ticked == 1) { attend_feasted[ide] += 1; } if (activity == "drink") { - var eater_type; - eater_type = 1; + var eater_type = 1; if (global.chapter_name == "Space Wolves" || obj_ini.progenitor == ePROGENITOR.SPACE_WOLVES) { eater_type = 2; } @@ -386,8 +338,6 @@ if (ticked == 1) { } } if (eater_type == 2) { - // if (attend_drunk[ide]<=0) then textt=unit.name_role()+" hails a serf and has "+choose("him","her")+" bring him a tankard of Mjod."; - // if (attend_drunk[ide]>0){ rando = choose(1, 2, 3); if (rando == 1) { textt = unit.name_role() + " pounds down Mjod, the concoction already beginning to inebriate the astartes."; @@ -398,7 +348,6 @@ if (ticked == 1) { if (rando == 3) { textt = unit.name_role() + " begins to drink down Mjod, a large frothing glass of the substance in each hand. He alternates between the two."; } - // } } if (eater_type == 3) { if (attend_drunk[ide] <= 0) { @@ -422,8 +371,6 @@ if (ticked == 1) { } } - // show_message("activity:"+string(activity)+", text:"+string(textt)); - if (activity == "talk") { textt = scr_event_gossip(ide); } @@ -431,14 +378,7 @@ if (ticked == 1) { if (activity == "artifact") { var spesh = ""; var woa = string(obj_ini.artifact[obj_controller.fest_display]); - var nerves_spesh = [ - "GOAT", - "CHE", - "THI", - "TENTACLES", - "JUM", - "PRE" - ]; + var nerves_spesh = ["GOAT", "CHE", "THI", "TENTACLES", "JUM", "PRE"]; for (var sp = 0; sp < array_length(nerves_spesh); sp++) { if (array_contains(obj_ini.artifact_tags[obj_controller.fest_display], nerves_spesh[sp])) { spesh = "nerves"; @@ -453,8 +393,7 @@ if (ticked == 1) { if (array_contains(obj_ini.artifact_tags[obj_controller.fest_display], "MNR")) { spesh = "minor"; } - var unit = obj_ini.TTRPG[attend_co[ide]][attend_id[ide]]; - var textt = unit.name_role(); + textt = unit.name_role(); if (spesh == "") { rando = choose(1, 2, 3, 4, 5); @@ -508,54 +447,6 @@ if (ticked == 1) { } attend_corrupted[ide] = 1; } - - /* - - - - if (t1="Weapon"){ - // gold, glowing, underslung bolter, underslung flamer - t5=choose("GOLD","GLOW","UBOLT","UFL"); - // Runes, scope, adamantium, void - t4=choose("RUN","SCO","ADAMANTINE","VOI"); - if ((t2="Power Sword") or (t2="Power Axe") or (t2="Power Spear")) and (t4="SCO") then t4="CHB";// chainblade - if ((t2="Power Fist") or (t2="Power Claw")) and (t4="SCO") then t4="DUB";// doubled up - if (t2="Relic Blade") and (t4="SCO") then t4="UFL";// underslung flamer - } - if (t1="Armour"){ - // golden filigree, glowing optics, purity seals - t5=choose("GOLD","GLOW","PUR"); - // articulated plates, spikes, runes, drake scales - t4=choose("ART","SPIKES","RUN","DRA"); - } - if (t1="Gear"){ - // supreme construction, adamantium, gold - t4=choose("SUP","ADAMANTINE","GOLD");// bur = ever burning - if (t2="Rosarius") then t5=choose("GOLD","GLOW","BIG","BUR"); - if (t2="Bionics") then t5=choose("GOLD","GLOW","RUN","SOO");// Soothing appearance - if (t2="Psychic Hood") then t5=choose("FIN","GOLD","BUR","MASK");// fine cloth, gold, ever burning, mask - if (t2="Jump Pack") then t5=choose("SPIKES","SKRE","WHI","SILENT");// spikes, screaming, white flame, silent - if (t2="Servo-arm") then t5=choose("GOLD","TENTACLES","GOR","SOO");// gold, tentacles, gorilla build, soothing appearance - } - if (t1="Device") and (t2!="Robot"){ - t4=choose("GOLD","CRU","GLOW","ADAMANTINE");// skulls, falling angel, thin, tentacle, mindfuck - if (t2!="Statue") then t5=choose("SKU","FAL","THI","TENTACLES","MIN"); - // goat, speechless, dying angel, jumping into magma, cheshire grunx - if (t2="Statue") then t5=choose("GOAT","SPE","DYI","JUM","CHE"); - // Gold, glowing, preserved flesh, adamantium - if (t2="Tome") then t4=choose("GOLD","GLOW","PRE","ADAMANTINE","SAL","BUR"); - if (t4="PRE") and (t3="") then t3=choose("","Chaos","Daemonic"); - } - if (t1="Device") and (t2="Robot"){// human/robutt/shivarah - t4=choose("HU","RO","SHI"); - t5=choose("ADAMANTINE","JAD","BRO","RUNE"); - } - - - if (string_count("Chaos",obj_ini.artifact_tags[obj_controller.fest_display])>0) then spesh="chaos"; - if (string_count("Daem",obj_ini.artifact_tags[obj_controller.fest_display])>0) then spesh="daemonic"; - - */ } if (textt != "") { @@ -576,14 +467,6 @@ if (ticked == 1) { } if (liness > (attendants / 2)) { - var i; - i = -1; - repeat (1501) { - i += 1; - attend_displayed[i] = 0; - } + attend_displayed = array_create(1500, 0); liness = 0; } - -/* */ -/* */ diff --git a/objects/obj_event_log/Create_0.gml b/objects/obj_event_log/Create_0.gml index 6f51017e91..d9c01930f4 100644 --- a/objects/obj_event_log/Create_0.gml +++ b/objects/obj_event_log/Create_0.gml @@ -23,8 +23,8 @@ repeat (101) { e += 1; topics[e] = ""; } -if (file_exists("main\\help.ini")) { - ini_open("main\\help.ini"); +if (file_exists(PATH_HELP_INI)) { + ini_open(PATH_HELP_INI); var ch; ch = 0; repeat (100) { diff --git a/objects/obj_event_log/Draw_0.gml b/objects/obj_event_log/Draw_0.gml index 59b244d9e6..e3acdc8111 100644 --- a/objects/obj_event_log/Draw_0.gml +++ b/objects/obj_event_log/Draw_0.gml @@ -116,7 +116,7 @@ if (help == 1) { draw_set_alpha(1); if (mouse_button_clicked()) { topic = topics[t]; - ini_open("main\\help.ini"); + ini_open(PATH_HELP_INI); info = ini_read_string(string(t), "info", ""); strategy = ini_read_string(string(t), "strategy", ""); main_info = ini_read_string(string(t), "main_info", ""); diff --git a/objects/obj_ini/Create_0.gml b/objects/obj_ini/Create_0.gml index cda84a928b..c926a76407 100644 --- a/objects/obj_ini/Create_0.gml +++ b/objects/obj_ini/Create_0.gml @@ -273,7 +273,7 @@ deserialize = function(save_data) { var all_names = struct_get_names(save_data); if (!array_contains(all_names, "chapter_squad_arrangement")) { - obj_ini.chapter_squad_arrangement = json_to_gamemaker(working_directory + $"main\\squads\\company_squad_builds.json", json_parse); + obj_ini.chapter_squad_arrangement = json_to_gamemaker(working_directory + $"main/squads/company_squad_builds.json", json_parse); } var _len = array_length(all_names); diff --git a/objects/obj_ncombat/Alarm_0.gml b/objects/obj_ncombat/Alarm_0.gml index ce0fced4fe..f1bc5f961a 100644 --- a/objects/obj_ncombat/Alarm_0.gml +++ b/objects/obj_ncombat/Alarm_0.gml @@ -3164,18 +3164,34 @@ try { player_guard = battle_object.p_guardsmen[battle_id]; } if (player_guard > 0) { - // Place the Guard in the front column, matching the rightmost existing - // block. Stepping ahead of the line breaks the advance on an attack (they - // march out past the engagement), so they sit in the line and move with it. - var _frontx = -50; + // Place the Guard as the front rank in both attack and defence. They must be + // the leading block, never a rear one: the player advance (move_unit_block + // "east") refuses to move a block when another block sits directly ahead of it, + // so Guard placed behind the Marines on attack can never step forward, and the + // Marines simply advance off and leave them standing at the rear (the Marines + // "pass them by"). As the front rank the Guard have open ground ahead, so they + // lead the charge on attack and hold the line on defence, and either way they + // reach the enemy and fight. Front rank is just east of the Marines and still + // west of the enemy spawn (rightmost block + 10). + var _maxx = -50; + var _minx = 1000000; with (obj_pnunit) { - if (x > _frontx) _frontx = x; + if (x > _maxx) _maxx = x; + if (x < _minx) _minx = x; + } + var _frontx; + if (_maxx < 0) { + _frontx = 100; // no other player blocks: stand-alone Guard force + } else { + _frontx = _maxx + 5; // front rank, attack and defence alike } u = instance_create(_frontx, 240, obj_pnunit); u.guard = 1; - // The mass of Guardsmen are men, so they render and take losses per man, - // the same way the enemy Guard do. + // Guardsmen line: pure infantry, no tanks, the way the enemy Imperial Guard + // keep their soldier lines tank-free. They render and take losses per man like + // the enemy Guard. They have no anti-tank weapon, so against armour they can + // only bleed and die unless a Leman Russ line is present. u.men = player_guard; u.dudes[1] = "Imperial Guardsman"; u.dudes_num[1] = player_guard; @@ -3183,37 +3199,43 @@ try { u.dudes_hp[1] = 5; u.dudes_vehicle[1] = 0; - // Leman Russ armour for a large garrison: real vehicles, like the enemy's. + // Keep the default obj_pnunit sprite (do not blank it): the block needs its + // collision mask, or the enemy advance walks straight through the Guard. + + // Count the infantry toward player forces. The normal accumulation only runs + // during setup and this block spawns too late for it; obj_pnunit's Alarm_3 + // skips its auto-add for guard blocks so this is not double counted. + player_forces += u.men; + player_max += u.men; + + // Leman Russ tanks form their own separate block (guard == 2), placed just + // behind the infantry line so the Guardsmen screen them. Tanks are the only + // anti-armour the Guard field, kept out of the soldier line like the enemy's. var _tanks = min(30, round(player_guard / 5000)); if (_tanks > 0) { + var _tankx = max(5, _frontx - 10); + var t = instance_create(_tankx, 240, obj_pnunit); + t.guard = 2; + t.men = 0; for (var i = 1; i <= _tanks; i++) { - u.veh_co[i] = 0; - u.veh_id[i] = 0; - u.veh_type[i] = "Leman Russ Battle Tank"; - u.veh_hp[i] = 250; - u.veh_ac[i] = 40; - u.veh_dead[i] = 0; - u.veh_hp_multiplier[i] = 1; - u.veh_wep1[i] = "Battle Cannon"; + t.veh_co[i] = 0; + t.veh_id[i] = 0; + t.veh_type[i] = "Leman Russ Battle Tank"; + t.veh_hp[i] = 250; + t.veh_ac[i] = 40; + t.veh_dead[i] = 0; + t.veh_hp_multiplier[i] = 1; + t.veh_wep1[i] = "Battle Cannon"; } - u.veh = _tanks; - u.dudes[2] = "Leman Russ Battle Tank"; - u.dudes_num[2] = _tanks; - u.dudes_ac[2] = 40; - u.dudes_hp[2] = 250; - u.dudes_vehicle[2] = 1; + t.veh = _tanks; + t.dudes[1] = "Leman Russ Battle Tank"; + t.dudes_num[1] = _tanks; + t.dudes_ac[1] = 40; + t.dudes_hp[1] = 250; + t.dudes_vehicle[1] = 1; + player_forces += t.veh; + player_max += t.veh; } - // Keep the default obj_pnunit sprite (do not blank it): the block needs its - // collision mask, or the enemy advance walks straight through the Guard - // without stopping to fight, which is what sent the enemy off the screen. - - // Count the Guard toward the battle's player forces. The normal accumulation - // only runs during setup and this block spawns too late for it, so the win/ - // loss check never saw them and the battle ended when the Marines died. Add - // them here; obj_pnunit's Alarm_3 skips its auto-add for guard blocks so this - // is not double counted. - player_forces += u.men + u.veh; - player_max += u.men + u.veh; } instance_activate_object(obj_enunit); diff --git a/objects/obj_star/Alarm_3.gml b/objects/obj_star/Alarm_3.gml index 905bd864f5..b9e503f956 100644 --- a/objects/obj_star/Alarm_3.gml +++ b/objects/obj_star/Alarm_3.gml @@ -54,7 +54,8 @@ try { if (struct_exists(_data, "planet")) { obj_controller.selecting_planet = _data.planet; if (obj_controller.selecting_planet > 0 && obj_controller.selecting_planet < 5) { - obj_star_select.garrison = get_garrison(obj_controller.selecting_planet); + var _pdata = get_planet_data(obj_controller.selecting_planet); + _pdata.set_star_select_planet(); } } obj_controller.selection_data = false; diff --git a/objects/obj_star/Create_0.gml b/objects/obj_star/Create_0.gml index 854716dcdb..4d6d88dc95 100644 --- a/objects/obj_star/Create_0.gml +++ b/objects/obj_star/Create_0.gml @@ -85,7 +85,16 @@ get_garrison = function(planet){ _gar.star = self; _gar.planet = planet; } else { - _gar.update(); + try { + _gar.update(); + } catch (_garrison_reload_error) { + // A garrison restored from a save keeps its data but loses its struct + // methods, so rebuild it from the planet's operatives, which persist. + system_garrison[planet] = new GarrisonForce(self, planet); + _gar = system_garrison[planet]; + _gar.star = self; + _gar.planet = planet; + } } return _gar; } @@ -98,7 +107,14 @@ get_sabatours = function(planet){ _gar.star = self; _gar.planet = planet; } else { - _gar.update(); + try { + _gar.update(); + } catch (_sabotage_reload_error) { + system_sabatours[planet] = new GarrisonForce(self, planet, "sabotage"); + _gar = system_sabatours[planet]; + _gar.star = self; + _gar.planet = planet; + } } return _gar; } @@ -109,7 +125,12 @@ get_planet_data = function(planet){ system_datas[planet] = new PlanetData(planet, self); _gar = system_datas[planet]; } else { - _gar.refresh_data(); + try { + _gar.refresh_data(); + } catch (_planetdata_reload_error) { + system_datas[planet] = new PlanetData(planet, self); + _gar = system_datas[planet]; + } } return _gar; } diff --git a/objects/obj_star_select/Draw_64.gml b/objects/obj_star_select/Draw_64.gml index c7bdc3805e..54a834d72b 100644 --- a/objects/obj_star_select/Draw_64.gml +++ b/objects/obj_star_select/Draw_64.gml @@ -260,15 +260,13 @@ try { exit; } } - } else if (garrison != "" && !population) { + } else if (garrison != "" && !population && garrison.planet == obj_controller.selecting_planet) { if (garrison.garrison_force) { draw_set_font(fnt_40k_14); - if (!garrison.garrison_leader) { - garrison.find_leader(); - garrison.garrison_disposition_change(true); - garrison_data_slate.sub_title = $"Garrison Leader {garrison.garrison_leader.name_role()}"; - garrison_data_slate.body_text = garrison.garrison_report(); - } + + 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); @@ -284,15 +282,15 @@ try { 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"); - } + + if (garrison.dispo_change > 55) { + draw_text(xx + 20, half_way + 30, $"Garrison Disposition Effect : Positive"); + } else if (garrison.dispo_change > 44 || garrison.dispo_change == 0) { + 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); } diff --git a/scripts/ErrorHandler/ErrorHandler.gml b/scripts/ErrorHandler/ErrorHandler.gml index b211b22d70..c905e3ae83 100644 --- a/scripts/ErrorHandler/ErrorHandler.gml +++ b/scripts/ErrorHandler/ErrorHandler.gml @@ -73,10 +73,10 @@ function GameError(_header, _message, _stacktrace = "", _critical = false, _repo /// @description Builds player-facing error message static build_player_message = function() { - var _path_hint = string_replace_all(game_save_id, "/", "\\"); + var _path_hint = (os_type == os_windows) ? string_replace_all(game_save_id, "/", "\\") : game_save_id; var _msg = $"{header}\n\n{message}\n\n"; - _msg += $"The error log was saved at:\n{_path_hint}Logs\\\n\n"; + _msg += (os_type == os_windows) ? $"The error log was saved at:\n{_path_hint}Logs\\\n\n" : $"The error log was saved at:\n{_path_hint}Logs/\n\n"; if (UPDATE_CHECKER.compiled) { _msg += "You are using a debug build. Automated bug reports disabled.\n\n"; diff --git a/scripts/NameGenerator/NameGenerator.gml b/scripts/NameGenerator/NameGenerator.gml index c1449e0873..07ce8bf667 100644 --- a/scripts/NameGenerator/NameGenerator.gml +++ b/scripts/NameGenerator/NameGenerator.gml @@ -17,7 +17,7 @@ function NameTracker(set_name) constructor { var file_loader = new JsonFileListLoader(); - var load_result = file_loader.load_list_from_json_file($"main\\names\\{file_name}.json", [json_names_property_name]); + var load_result = file_loader.load_list_from_json_file($"main/names/{file_name}.json", [json_names_property_name]); if (load_result.is_success) { names = load_result.values[$ json_names_property_name]; @@ -48,7 +48,7 @@ function NameTracker(set_name) constructor { var file_loader = new JsonFileListLoader(); - var load_result = file_loader.load_list_from_json_file($"main\\names\\{file_name}.json", json_names_property_names); + var load_result = file_loader.load_list_from_json_file($"main/names/{file_name}.json", json_names_property_names); var result = {}; @@ -186,7 +186,7 @@ function NameTracker(set_name) constructor { function NameGenerator() constructor { // TODO after save rework is finished, check if these static can be converted to instance version - var _simple_names = json_to_gamemaker(working_directory + $"main\\name_loader.json", json_parse); + var _simple_names = json_to_gamemaker(working_directory + $"main/name_loader.json", json_parse); if (_simple_names == "") { _simple_names = [ diff --git a/scripts/__init/__init.gml b/scripts/__init/__init.gml index ba184e5459..ba0c460a8f 100644 --- a/scripts/__init/__init.gml +++ b/scripts/__init/__init.gml @@ -1,11 +1,12 @@ -#macro PATH_SAVE_FILES "Save Files\\save{0}.json" -#macro PATH_AUTOSAVE_FILE "Save Files\\save0.json" -#macro PATH_CUSTOM_ICONS "Custom Files\\Custom Icons\\" -#macro PATH_CHAPTER_ICONS working_directory + "\\images\\creation\\chapters\\icons\\" -#macro PATH_INCLUDED_ICONS working_directory + "\\images\\creation\\customicons\\" +#macro PATH_SAVE_FILES "Save Files/save{0}.json" +#macro PATH_AUTOSAVE_FILE "Save Files/save0.json" +#macro PATH_CUSTOM_ICONS "Custom Files/Custom Icons/" +#macro PATH_CHAPTER_ICONS working_directory + "/images/creation/chapters/icons/" +#macro PATH_INCLUDED_ICONS working_directory + "/images/creation/customicons/" #macro PATH_LOG_DIRECTORY "Logs/" #macro LAST_MESSAGES_LOG "last_messages.log" #macro PATH_LAST_MESSAGES PATH_LOG_DIRECTORY + LAST_MESSAGES_LOG +#macro PATH_HELP_INI "main/help.ini" /// @desc Called via gml_pragma("global") at startup, before any room. function __init() { @@ -33,8 +34,8 @@ function __init() { if (!directory_exists("Logs")) { directory_create("Logs"); } - if (!directory_exists("Custom Files\\Custom Icons")) { - directory_create("Custom Files\\Custom Icons"); + if (!directory_exists("Custom Files/Custom Icons")) { + directory_create("Custom Files/Custom Icons"); } if (!directory_exists("Save Files")) { directory_create("Save Files"); @@ -82,7 +83,7 @@ function __init() { global.game_version = "unknown version"; global.commit_hash = "unknown hash"; - var _version_file_path = working_directory + "\\main\\version.json"; + var _version_file_path = working_directory + "/main/version.json"; var _parsed_json = json_to_gamemaker(_version_file_path, json_parse); if (_parsed_json != undefined) { @@ -112,18 +113,18 @@ function __init() { global.update_checker.compiled = true; } - global.weapons = json_to_gamemaker(working_directory + "\\data\\weapons.json", json_parse); + global.weapons = json_to_gamemaker(working_directory + "/data/weapons.json", json_parse); global.gear = { - "armour": json_to_gamemaker(working_directory + "\\data\\armour.json", json_parse), - "gear": json_to_gamemaker(working_directory + "\\data\\gear.json", json_parse), - "mobility": json_to_gamemaker(working_directory + "\\data\\mobility.json", json_parse), + "armour": json_to_gamemaker(working_directory + "/data/armour.json", json_parse), + "gear": json_to_gamemaker(working_directory + "/data/gear.json", json_parse), + "mobility": json_to_gamemaker(working_directory + "/data/mobility.json", json_parse), }; - global.vehicles = json_to_gamemaker(working_directory + "\\data\\vehicles.json", json_parse); - global.vehicle_gear = json_to_gamemaker(working_directory + "\\data\\vehicle_gear.json", json_parse); - global.ships = json_to_gamemaker(working_directory + "\\data\\ships.json", json_parse); - global.technologies = json_to_gamemaker(working_directory + "\\data\\technologies.json", json_parse); + global.vehicles = json_to_gamemaker(working_directory + "/data/vehicles.json", json_parse); + global.vehicle_gear = json_to_gamemaker(working_directory + "/data/vehicle_gear.json", json_parse); + global.ships = json_to_gamemaker(working_directory + "/data/ships.json", json_parse); + global.technologies = json_to_gamemaker(working_directory + "/data/technologies.json", json_parse); - global.base_stats = json_to_gamemaker(working_directory + "\\data\\unit_stats.json", json_parse); + global.base_stats = json_to_gamemaker(working_directory + "/data/unit_stats.json", json_parse); layer_force_draw_depth(true, 0); // force all layers to draw at depth 0 draw_set_colour(c_black); diff --git a/scripts/scr_ChapterTraits/scr_ChapterTraits.gml b/scripts/scr_ChapterTraits/scr_ChapterTraits.gml index 60bee65601..ef930d94aa 100644 --- a/scripts/scr_ChapterTraits/scr_ChapterTraits.gml +++ b/scripts/scr_ChapterTraits/scr_ChapterTraits.gml @@ -275,11 +275,11 @@ function Disadvantage(trait) : ChapterTrait(trait) constructor { // TODO all the chapter start data should be ramed in here as well rather than being hardcoded function generate_disadvantages() { - return json_to_gamemaker(working_directory + $"main\\chapter_disadvantages.json", json_parse); + return json_to_gamemaker(working_directory + $"main/chapter_disadvantages.json", json_parse); } function generate_advantages() { - return json_to_gamemaker(working_directory + $"main\\chapter_advantages.json", json_parse); + return json_to_gamemaker(working_directory + $"main/chapter_advantages.json", json_parse); } function setup_chapter_traits() { diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index 48d026d24b..fa77bd094f 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -106,7 +106,13 @@ function PlanetData(planet, system) constructor { } garrisons = system.system_garrison[planet]; + if (garrisons == 0){ + garrisons = system.get_garrison(planet) + } sabatours = system.system_sabatours[planet]; + if (sabatours == 0){ + sabatours = system.get_sabatours(planet) + } system.system_datas[planet] = self; // current planet heresy @@ -253,6 +259,11 @@ function PlanetData(planet, system) constructor { guardsmen = system.p_guardsmen[planet]; }; + static edit_pdf = function(edit_val){ + system.p_pdf[planet] = max(0, system.p_pdf[planet] + edit_val); + pdf = system.p_pdf[planet] + } + pdf = system.p_pdf[planet]; fortification_level = system.p_fortified[planet]; @@ -1581,6 +1592,18 @@ function PlanetData(planet, system) constructor { instance_destroy(obj_star_select); }; + static set_star_select_planet = function(){ + obj_star_select.garrison = garrisons; + system.garrison = garrisons.garrison_force; + obj_star_select.feature = ""; + buttons_selected = false; + garrisons.update(); + if (garrisons.garrison_force){ + garrisons.find_leader(); + garrisons.garrison_disposition_change(true); + } + } + static planet_selection_logic = function() { var planet_is_allies = scr_is_planet_owned_by_allies(system, planet); var garrison_issue = !planet_is_allies || pdf <= 0; @@ -1602,10 +1625,7 @@ function PlanetData(planet, system) constructor { exit; } } else if (!_loading) { - obj_star_select.garrison = system.get_garrison(planet); - system.garrison = obj_star_select.garrison.garrison_force; - obj_star_select.feature = ""; - buttons_selected = false; + set_star_select_planet(); } else if (_loading && planet > 0) { obj_controller.unload = planet; obj_controller.return_object = system; diff --git a/scripts/scr_chapter_new/scr_chapter_new.gml b/scripts/scr_chapter_new/scr_chapter_new.gml index 78dffe1d46..320f32742d 100644 --- a/scripts/scr_chapter_new/scr_chapter_new.gml +++ b/scripts/scr_chapter_new/scr_chapter_new.gml @@ -156,7 +156,7 @@ function ChapterData() constructor { if (use_app_data) { load_result = file_loader.load_struct_from_json_file($"chaptersave#{chapter_id}.json", "chapter", true); } else { - load_result = file_loader.load_struct_from_json_file($"main\\chapters\\{chapter_id}.json", "chapter", false); + load_result = file_loader.load_struct_from_json_file($"main/chapters/{chapter_id}.json", "chapter", false); } if (!load_result.is_success) { // LOGGER.error($"No chapter json exits for chapter_id {chapter_id}"); diff --git a/scripts/scr_culture_visuals/scr_culture_visuals.gml b/scripts/scr_culture_visuals/scr_culture_visuals.gml index 78e8c2c658..d151b148dd 100644 --- a/scripts/scr_culture_visuals/scr_culture_visuals.gml +++ b/scripts/scr_culture_visuals/scr_culture_visuals.gml @@ -1,7 +1,7 @@ function load_visual_sets() { - var _vis_set_directory = working_directory + "\\main\\visual_sets"; + var _vis_set_directory = working_directory + "/main/visual_sets"; if (directory_exists(_vis_set_directory)) { - var _file_buffer = buffer_load($"{_vis_set_directory}\\use_sets.json"); + var _file_buffer = buffer_load($"{_vis_set_directory}/use_sets.json"); if (_file_buffer == -1) { throw "Could not open file"; } @@ -12,11 +12,11 @@ function load_visual_sets() { throw "use_sets.json File Wrong Format"; } for (var i = 0; i < array_length(_raw_data); i++) { - var _sepcific_vis_set = $"{_vis_set_directory}\\{_raw_data[i]}"; + var _sepcific_vis_set = $"{_vis_set_directory}/{_raw_data[i]}"; // LOGGER.debug(_raw_data[i]); if (directory_exists(_sepcific_vis_set)) { // LOGGER.debug(_raw_data[i]); - var _data_buffer = buffer_load($"{_sepcific_vis_set}\\data.json"); + var _data_buffer = buffer_load($"{_sepcific_vis_set}/data.json"); if (_data_buffer == -1) { buffer_delete(_data_buffer); continue; @@ -37,10 +37,10 @@ function load_visual_sets() { } function load_symbol_sets(global_area, main_key, sub_sets) { - var _cons_directory = working_directory + $"\\main\\{main_key}"; + var _cons_directory = working_directory + $"/main/{main_key}"; if (directory_exists(_cons_directory)) { // LOGGER.debug($"{_cons_directory}") - var _file_buffer = buffer_load($"{_cons_directory}\\load_sets.json"); + var _file_buffer = buffer_load($"{_cons_directory}/load_sets.json"); if (_file_buffer == -1) { throw false; } @@ -52,11 +52,11 @@ function load_symbol_sets(global_area, main_key, sub_sets) { } var _sprite_double_surface = surface_create(200, 200); for (var i = 0; i < array_length(_raw_data); i++) { - var _sepcific_vis_set = $"{_cons_directory}\\{_raw_data[i]}"; + var _sepcific_vis_set = $"{_cons_directory}/{_raw_data[i]}"; if (directory_exists(_sepcific_vis_set)) { for (var s = 0; s < array_length(sub_sets); s++) { var _sub = sub_sets[s]; - var sub_direct = $"{_sepcific_vis_set}\\{_sub}.png"; + var sub_direct = $"{_sepcific_vis_set}/{_sub}.png"; load_new_icon(_sprite_double_surface, sub_direct, global_area[$ _sub], _raw_data[i]); } } @@ -105,15 +105,15 @@ function load_vis_set_to_global(directory, data) { var _sprite_item = data[i]; // LOGGER.debug(_sprite_item); - if (directory_exists(directory + $"\\{_sprite_item.name}")) { - var _sprite_direct = directory + $"\\{_sprite_item.name}"; + if (directory_exists(directory + $"/{_sprite_item.name}")) { + var _sprite_direct = directory + $"/{_sprite_item.name}"; // --- MAIN SPRITE LOADING --- - if (file_exists($"{_sprite_direct}\\1.png")) { - var _new_sprite = sprite_add(_sprite_direct + "\\1.png", 1, 0, 0, 0, 0); + if (file_exists($"{_sprite_direct}/1.png")) { + var _new_sprite = sprite_add(_sprite_direct + "/1.png", 1, 0, 0, 0, 0); var s = 2; - while (file_exists(_sprite_direct + $"\\{s}.png")) { - var _merge_sprite = sprite_add(_sprite_direct + $"\\{s}.png", 1, 0, 0, 0, 0); + while (file_exists(_sprite_direct + $"/{s}.png")) { + var _merge_sprite = sprite_add(_sprite_direct + $"/{s}.png", 1, 0, 0, 0, 0); if (_merge_sprite == -1) { sprite_delete(_new_sprite); continue; @@ -126,11 +126,11 @@ function load_vis_set_to_global(directory, data) { // --- SHADOW SPRITE LOADING --- var _new_shadow = -1; - if (file_exists($"{_sprite_direct}\\shadow1.png")) { - _new_shadow = sprite_add(_sprite_direct + "\\shadow1.png", 1, 0, 0, 0, 0); + if (file_exists($"{_sprite_direct}/shadow1.png")) { + _new_shadow = sprite_add(_sprite_direct + "/shadow1.png", 1, 0, 0, 0, 0); var sh = 2; - while (file_exists(_sprite_direct + $"\\shadow{sh}.png")) { - var _merge_shadow = sprite_add(_sprite_direct + $"\\shadow{sh}.png", 1, 0, 0, 0, 0); + while (file_exists(_sprite_direct + $"/shadow{sh}.png")) { + var _merge_shadow = sprite_add(_sprite_direct + $"/shadow{sh}.png", 1, 0, 0, 0, 0); if (_merge_shadow == -1) { sprite_delete(_new_shadow); continue; diff --git a/scripts/scr_dialogue/scr_dialogue.gml b/scripts/scr_dialogue/scr_dialogue.gml index 5f9ef20221..fb971c6088 100644 --- a/scripts/scr_dialogue/scr_dialogue.gml +++ b/scripts/scr_dialogue/scr_dialogue.gml @@ -1,6 +1,6 @@ function initialize_dialogue() { global.dialogue = {}; - global.dialogue.sisters = json_to_gamemaker(working_directory + "\\data\\dialogue\\sisters.json", json_parse); + global.dialogue.sisters = json_to_gamemaker(working_directory + "/data/dialogue/sisters.json", json_parse); } function interpret_diag_string(string_data, data) { diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index 5f03c9e2a8..814f5b3266 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -238,23 +238,10 @@ function drop_select_unit_selection() { obj_ncombat.defending = false; obj_ncombat.local_forces = roster.local_button.active; - // Bring embarked Imperial Guard from the attacking fleet into the assault. - // They disembark for the battle, so they are spent from the ships here. + // (Imperial Guard assault bring-along disabled for now: the player-side + // battlefield unit needs real per-model data, so this is being rebuilt. + // Until then we do not touch the embarked Guard, so attacks cost nothing.) obj_ncombat.player_attack_guard = 0; - if (attack == 1) { - var _sysname = p_target.name; - var _ig = player_guardsmen_at(_sysname); - if (_ig > 0) { - obj_ncombat.player_attack_guard = _ig; - with (obj_ini) { - for (var _gi = 0; _gi < array_length(ship); _gi++) { - if (ship_location[_gi] == _sysname) { - ship_guardsmen[_gi] = 0; - } - } - } - } - } var _planet = obj_ncombat.battle_object.p_feature[obj_ncombat.battle_id]; if (obj_ncombat.battle_object.space_hulk == 1) { diff --git a/scripts/scr_garrison/scr_garrison.gml b/scripts/scr_garrison/scr_garrison.gml index a5b285cd9c..41e7e665e1 100644 --- a/scripts/scr_garrison/scr_garrison.gml +++ b/scripts/scr_garrison/scr_garrison.gml @@ -36,6 +36,7 @@ function GarrisonForce(system, planet, type = "garrison") constructor { members = []; time_on_planet = 0; viable_garrison = 0; + dispo_change = 0; self.type = type; self.system = system; self.planet = planet; @@ -213,63 +214,64 @@ function GarrisonForce(system, planet, type = "garrison") constructor { static garrison_disposition_change = function(up_or_down = false) { dispo_change = 0; var _pdata = system.get_planet_data(planet); - if (array_contains(obj_controller.imperial_factions, _pdata.current_owner)) { - var _planet_disposition = _pdata.player_disposition; + if (!array_contains(obj_controller.imperial_factions, _pdata.current_owner)) { + return dispo_change; + } + + var _planet_disposition = _pdata.player_disposition; - var _main_faction_disp = _pdata.owner_faction_disposition(); + var _main_faction_disp = _pdata.owner_faction_disposition(); - //basivally it is easier to increase dispositioon the nearer you are to 50 but becomminig greatly hated or greaty liked is much harder - var _disposition_modifier = _planet_disposition <= 50 ? (_planet_disposition / 10) : ((_planet_disposition - 50) / 10) % 5; + //basivally it is easier to increase dispositioon the nearer you are to 50 but becomminig greatly hated or greaty liked is much harder + var _disposition_modifier = _planet_disposition <= 50 ? (_planet_disposition / 10) : ((_planet_disposition - 50) / 10) % 5; - _disposition_modifier /= 10; + _disposition_modifier /= 10; - var _time_modifier = max(time_on_planet / 2.5, 10); + var _time_modifier = max(time_on_planet / 2.5, 10); - if (!is_struct(garrison_leader)) { - find_leader(); - } - var _diplomatic_leader = false; - if (is_struct(garrison_leader)) { - _diplomatic_leader = garrison_leader.has_trait("honorable"); - } else { - scr_alert("yellow", "DEBUG", $"DEBUG: Garrison _Leader on {_pdata.name()} couldn't be found!", 0, 0); - scr_event_log("yellow", $"DEBUG: Garrison _Leader on {_pdata.name()} couldn't be found!"); - LOGGER.error($"DEBUG: Garrison _Leader on {_pdata.name()} couldn't be found!"); - } - var _garrison_size_mod = total_garrison / 10; + if (!is_struct(garrison_leader)) { + find_leader(); + } + var _diplomatic_leader = false; + if (is_struct(garrison_leader)) { + _diplomatic_leader = garrison_leader.has_trait("honorable"); + } else { + scr_alert("yellow", "DEBUG", $"DEBUG: Garrison _Leader on {_pdata.name()} couldn't be found!", 0, 0); + scr_event_log("yellow", $"DEBUG: Garrison _Leader on {_pdata.name()} couldn't be found!"); + LOGGER.error($"DEBUG: Garrison _Leader on {_pdata.name()} couldn't be found!"); + } + var _garrison_size_mod = total_garrison / 10; - var final_modifier = 5 + _garrison_size_mod - _disposition_modifier + _time_modifier; + var final_modifier = 5 + _garrison_size_mod - _disposition_modifier + _time_modifier; - if (up_or_down) { - dispo_change = garrison_leader.charisma + final_modifier; - if (dispo_change < 50 && ((_planet_disposition < _main_faction_disp) || _diplomatic_leader)) { - dispo_change = 50; - } - } else { - var _charisma_test; - if (is_struct(garrison_leader)){ - _charisma_test = global.character_tester.standard_test(garrison_leader, "charisma", final_modifier); - } else { - _charisma_test = [bool(irandom(1)), irandom_range(0, 25)]; - } - var dispo_change = _charisma_test[1] / 10; - if (!_charisma_test[0]) { - if (_diplomatic_leader) { - dispo_change = "none"; + if (up_or_down) { + dispo_change = garrison_leader.charisma + final_modifier; + if (dispo_change < 50 && ((_planet_disposition < _main_faction_disp) || _diplomatic_leader)) { + dispo_change = 50; + } + } else { + var _charisma_test; + if (is_struct(garrison_leader)){ + _charisma_test = global.character_tester.standard_test(garrison_leader, "charisma", final_modifier); + } else { + _charisma_test = [bool(irandom(1)), irandom_range(0, 25)]; + } + var dispo_change = _charisma_test[1] / 10; + if (!_charisma_test[0]) { + if (_diplomatic_leader) { + dispo_change = 0; + } else { + if (_planet_disposition > _main_faction_disp) { + _pdata.add_disposition(dispo_change); } else { - if (_planet_disposition > _main_faction_disp) { - _pdata.add_disposition(dispo_change); - } else { - dispo_change = 0; - } + dispo_change = 0; } - } else { - _pdata.add_disposition(dispo_change); } + } else { + _pdata.add_disposition(dispo_change); } - } else { - dispo_change = "none"; } + return dispo_change; }; diff --git a/scripts/scr_image/scr_image.gml b/scripts/scr_image/scr_image.gml index 7143aa04e0..80842ab002 100644 --- a/scripts/scr_image/scr_image.gml +++ b/scripts/scr_image/scr_image.gml @@ -484,23 +484,23 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (single_image == true) { - if ((path == "creation") && file_exists(working_directory + "\\images\\creation\\creation_icons.png")) { - creation[1] = sprite_add(working_directory + "\\images\\creation\\creation_icons.png", 24, false, false, 0, 0); + if ((path == "creation") && file_exists(working_directory + "/images/creation/creation_icons.png")) { + creation[1] = sprite_add(working_directory + "/images/creation/creation_icons.png", 24, false, false, 0, 0); creation_exists[1] = true; creation_good = true; } - if ((path == "diplomacy_icon") && file_exists(working_directory + "\\images\\diplomacy\\diplomacy_icons.png")) { - diplomacy_icon[1] = sprite_add(working_directory + "\\images\\diplomacy\\diplomacy_icons.png", 28, false, false, 0, 0); + if ((path == "diplomacy_icon") && file_exists(working_directory + "/images/diplomacy/diplomacy_icons.png")) { + diplomacy_icon[1] = sprite_add(working_directory + "/images/diplomacy/diplomacy_icons.png", 28, false, false, 0, 0); diplomacy_icon_exists[1] = true; diplomacy_icon_good = true; } - if ((path == "menu") && file_exists(working_directory + "\\images\\ui\\ingame_menu.png")) { - menu[1] = sprite_add(working_directory + "\\images\\ui\\ingame_menu.png", 2, false, false, 0, 0); + if ((path == "menu") && file_exists(working_directory + "/images/ui/ingame_menu.png")) { + menu[1] = sprite_add(working_directory + "/images/ui/ingame_menu.png", 2, false, false, 0, 0); menu_exists[1] = true; menu_good = true; } - if ((path == "title_splash") && file_exists(working_directory + "\\images\\title_splash.png")) { - title_splash[1] = sprite_add(working_directory + "\\images\\title_splash.png", 1, false, false, 0, 0); + if ((path == "title_splash") && file_exists(working_directory + "/images/title_splash.png")) { + title_splash[1] = sprite_add(working_directory + "/images/title_splash.png", 1, false, false, 0, 0); title_splash_exists[1] = true; title_splash_good = true; } @@ -514,8 +514,8 @@ function scr_image(path, image_id, x1, y1, width, height) { repeat (40) { i += 1; if (path == "main_splash") { - if (file_exists(working_directory + "\\images\\creation\\main" + string(i) + ".png")) { - main[i - 1] = sprite_add(working_directory + "\\images\\creation\\main" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/creation/main" + string(i) + ".png")) { + main[i - 1] = sprite_add(working_directory + "/images/creation/main" + string(i) + ".png", 1, false, false, 0, 0); main_exists[i - 1] = 1; w += 1; } @@ -524,8 +524,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } } if (path == "existing_splash") { - if (file_exists(working_directory + "\\images\\creation\\existing" + string(i) + ".png")) { - existing[i - 1] = sprite_add(working_directory + "\\images\\creation\\existing" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/creation/existing" + string(i) + ".png")) { + existing[i - 1] = sprite_add(working_directory + "/images/creation/existing" + string(i) + ".png", 1, false, false, 0, 0); existing_exists[i - 1] = 1; w += 1; } @@ -534,8 +534,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } } if (path == "other_splash") { - if (file_exists(working_directory + "\\images\\creation\\other" + string(i) + ".png")) { - others[i - 1] = sprite_add(working_directory + "\\images\\creation\\other" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/creation/other" + string(i) + ".png")) { + others[i - 1] = sprite_add(working_directory + "/images/creation/other" + string(i) + ".png", 1, false, false, 0, 0); others_exists[i - 1] = 1; w += 1; } @@ -545,8 +545,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "advisor") { - if (file_exists(working_directory + "\\images\\diplomacy\\advisor" + string(i) + ".png")) { - advisor[i - 1] = sprite_add(working_directory + "\\images\\diplomacy\\advisor" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/diplomacy/advisor" + string(i) + ".png")) { + advisor[i - 1] = sprite_add(working_directory + "/images/diplomacy/advisor" + string(i) + ".png", 1, false, false, 0, 0); advisor_exists[i - 1] = 1; w += 1; } @@ -556,8 +556,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "diplomacy_splash") { - if (file_exists(working_directory + "\\images\\diplomacy\\diplomacy" + string(i) + ".png")) { - diplomacy_splash[i - 1] = sprite_add(working_directory + "\\images\\diplomacy\\diplomacy" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/diplomacy/diplomacy" + string(i) + ".png")) { + diplomacy_splash[i - 1] = sprite_add(working_directory + "/images/diplomacy/diplomacy" + string(i) + ".png", 1, false, false, 0, 0); diplomacy_splash_exists[i - 1] = 1; w += 1; } @@ -567,8 +567,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "diplomacy_daemon") { - if (file_exists(working_directory + "\\images\\diplomacy\\daemon" + string(i) + ".png")) { - diplomacy_daemon[i - 1] = sprite_add(working_directory + "\\images\\diplomacy\\daemon" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/diplomacy/daemon" + string(i) + ".png")) { + diplomacy_daemon[i - 1] = sprite_add(working_directory + "/images/diplomacy/daemon" + string(i) + ".png", 1, false, false, 0, 0); diplomacy_daemon_exists[i - 1] = 1; w += 1; } @@ -578,8 +578,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } // loading screen error arg if (path == "loading") { - if (file_exists(working_directory + "\\images\\loading\\loading" + string(i) + ".png")) { - loading[i - 1] = sprite_add(working_directory + "\\images\\loading\\loading" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/loading/loading" + string(i) + ".png")) { + loading[i - 1] = sprite_add(working_directory + "/images/loading/loading" + string(i) + ".png", 1, false, false, 0, 0); loading_exists[i - 1] = 1; w += 1; } @@ -589,8 +589,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "postbattle") { - if (file_exists(working_directory + "\\images\\ui\\postbattle" + string(i) + ".png")) { - postbattle[i - 1] = sprite_add(working_directory + "\\images\\ui\\postbattle" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/postbattle" + string(i) + ".png")) { + postbattle[i - 1] = sprite_add(working_directory + "/images/ui/postbattle" + string(i) + ".png", 1, false, false, 0, 0); postbattle_exists[i - 1] = 1; w += 1; } @@ -600,8 +600,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "postspace") { - if (file_exists(working_directory + "\\images\\ui\\postspace" + string(i) + ".png")) { - postspace[i - 1] = sprite_add(working_directory + "\\images\\ui\\postspace" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/postspace" + string(i) + ".png")) { + postspace[i - 1] = sprite_add(working_directory + "/images/ui/postspace" + string(i) + ".png", 1, false, false, 0, 0); postspace_exists[i - 1] = 1; w += 1; } @@ -611,8 +611,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "formation") { - if (file_exists(working_directory + "\\images\\ui\\formation" + string(i) + ".png")) { - formation[i - 1] = sprite_add(working_directory + "\\images\\ui\\formation" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/formation" + string(i) + ".png")) { + formation[i - 1] = sprite_add(working_directory + "/images/ui/formation" + string(i) + ".png", 1, false, false, 0, 0); formation_exists[i - 1] = 1; w += 1; } @@ -622,8 +622,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "popup") { - if (file_exists(working_directory + "\\images\\popup\\popup" + string(i) + ".png")) { - popup[i - 1] = sprite_add(working_directory + "\\images\\popup\\popup" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/popup/popup" + string(i) + ".png")) { + popup[i - 1] = sprite_add(working_directory + "/images/popup/popup" + string(i) + ".png", 1, false, false, 0, 0); popup_exists[i - 1] = 1; w += 1; } @@ -633,8 +633,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "commander") { - if (file_exists(working_directory + "\\images\\ui\\commander" + string(i) + ".png")) { - commander[i - 1] = sprite_add(working_directory + "\\images\\ui\\commander" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/commander" + string(i) + ".png")) { + commander[i - 1] = sprite_add(working_directory + "/images/ui/commander" + string(i) + ".png", 1, false, false, 0, 0); commander_exists[i - 1] = 1; w += 1; } @@ -644,8 +644,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "planet") { - if (file_exists(working_directory + "\\images\\ui\\planet" + string(i) + ".png")) { - planet[i - 1] = sprite_add(working_directory + "\\images\\ui\\planet" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/planet" + string(i) + ".png")) { + planet[i - 1] = sprite_add(working_directory + "/images/ui/planet" + string(i) + ".png", 1, false, false, 0, 0); planet_exists[i - 1] = 1; w += 1; } @@ -655,8 +655,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "attacked") { - if (file_exists(working_directory + "\\images\\ui\\attacked" + string(i) + ".png")) { - attacked[i - 1] = sprite_add(working_directory + "\\images\\ui\\attacked" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/attacked" + string(i) + ".png")) { + attacked[i - 1] = sprite_add(working_directory + "/images/ui/attacked" + string(i) + ".png", 1, false, false, 0, 0); attacked_exists[i - 1] = 1; w += 1; } @@ -666,8 +666,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "force") { - if (file_exists(working_directory + "\\images\\ui\\force" + string(i) + ".png")) { - force[i - 1] = sprite_add(working_directory + "\\images\\ui\\force" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/force" + string(i) + ".png")) { + force[i - 1] = sprite_add(working_directory + "/images/ui/force" + string(i) + ".png", 1, false, false, 0, 0); force_exists[i - 1] = 1; w += 1; } @@ -677,8 +677,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "purge") { - if (file_exists(working_directory + "\\images\\ui\\purge" + string(i) + ".png")) { - purge[i - 1] = sprite_add(working_directory + "\\images\\ui\\purge" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/purge" + string(i) + ".png")) { + purge[i - 1] = sprite_add(working_directory + "/images/ui/purge" + string(i) + ".png", 1, false, false, 0, 0); purge_exists[i - 1] = 1; w += 1; } @@ -688,8 +688,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "event") { - if (file_exists(working_directory + "\\images\\ui\\event" + string(i) + ".png")) { - event[i - 1] = sprite_add(working_directory + "\\images\\ui\\event" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/event" + string(i) + ".png")) { + event[i - 1] = sprite_add(working_directory + "/images/ui/event" + string(i) + ".png", 1, false, false, 0, 0); event_exists[i - 1] = 1; w += 1; } @@ -699,8 +699,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "symbol") { - if (file_exists(working_directory + "\\images\\diplomacy\\symbol" + string(i) + ".png")) { - symbol[i - 1] = sprite_add(working_directory + "\\images\\diplomacy\\symbol" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/diplomacy/symbol" + string(i) + ".png")) { + symbol[i - 1] = sprite_add(working_directory + "/images/diplomacy/symbol" + string(i) + ".png", 1, false, false, 0, 0); symbol_exists[i - 1] = 1; w += 1; } @@ -710,8 +710,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "defeat") { - if (file_exists(working_directory + "\\images\\ui\\defeat" + string(i) + ".png")) { - defeat[i - 1] = sprite_add(working_directory + "\\images\\ui\\defeat" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/ui/defeat" + string(i) + ".png")) { + defeat[i - 1] = sprite_add(working_directory + "/images/ui/defeat" + string(i) + ".png", 1, false, false, 0, 0); defeat_exists[i - 1] = 1; w += 1; } @@ -721,8 +721,8 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (path == "slate") { - if (file_exists(working_directory + "\\images\\creation\\slate" + string(i) + ".png")) { - slate[i - 1] = sprite_add(working_directory + "\\images\\creation\\slate" + string(i) + ".png", 1, false, false, 0, 0); + if (file_exists(working_directory + "/images/creation/slate" + string(i) + ".png")) { + slate[i - 1] = sprite_add(working_directory + "/images/creation/slate" + string(i) + ".png", 1, false, false, 0, 0); slate_exists[i - 1] = 1; w += 1; } @@ -953,12 +953,12 @@ function scr_image_cache(path, image_id, use_app_data = false) { if (sprite_exists(existing_sprite)) { drawing_sprite = existing_sprite; } else if (image_id > -1) { - var folders = string_replace_all(path, "/", "\\"); + var folders = string_replace_all(path, "\\", "/"); var dir; if (use_app_data) { dir = $"{folders}{string(image_id)}.png"; } else { - dir = $"{working_directory}\\images\\{folders}\\{string(image_id)}.png"; + dir = $"{working_directory}/images/{folders}/{string(image_id)}.png"; } if (file_exists(dir)) { drawing_sprite = sprite_add(dir, 1, false, false, 0, 0); diff --git a/scripts/scr_initialize_custom/scr_initialize_custom.gml b/scripts/scr_initialize_custom/scr_initialize_custom.gml index 628695f9c3..77e52c4c19 100644 --- a/scripts/scr_initialize_custom/scr_initialize_custom.gml +++ b/scripts/scr_initialize_custom/scr_initialize_custom.gml @@ -1662,19 +1662,19 @@ function scr_initialize_custom() { switch (obj_creation.squad_distribution) { case 1: // equal specialists only obj_ini.chapter_squad_arrangement = json_to_gamemaker( - working_directory + $"main\\squads\\equal_specialists.json", json_parse); + working_directory + $"main/squads/equal_specialists.json", json_parse); break; case 2: // equal scouts only obj_ini.chapter_squad_arrangement = json_to_gamemaker( - working_directory + $"main\\squads\\equal_scouts.json", json_parse); + working_directory + $"main/squads/equal_scouts.json", json_parse); break; case 3: // equal specialists and equal scouts obj_ini.chapter_squad_arrangement = json_to_gamemaker( - working_directory + $"main\\squads\\equal_spescout.json", json_parse); + working_directory + $"main/squads/equal_spescout.json", json_parse); break; default: // 0 = standard obj_ini.chapter_squad_arrangement = json_to_gamemaker( - working_directory + $"main\\squads\\company_squad_builds.json", json_parse); + working_directory + $"main/squads/company_squad_builds.json", json_parse); break; } @@ -1691,7 +1691,7 @@ function scr_initialize_custom() { _squad_name = obj_creation.squad_name; } - squad_types = json_to_gamemaker(working_directory + $"main\\squads\\base_squads.json", json_parse); + squad_types = json_to_gamemaker(working_directory + $"main/squads/base_squads.json", json_parse); var _swaps = [ // ── Heavy Ranged ────────────────────────────────────────────── { diff --git a/scripts/scr_powers/scr_powers.gml b/scripts/scr_powers/scr_powers.gml index 85a32c857e..3185b2f11b 100644 --- a/scripts/scr_powers/scr_powers.gml +++ b/scripts/scr_powers/scr_powers.gml @@ -20,8 +20,8 @@ global.psy_disciplines_starting = [ #macro PSY_CAST_DIFFICULTY_MIN 1 #macro PSY_CAST_DIFFICULTY_BASE 40 -global.disciplines_data = json_to_gamemaker(working_directory + "\\data\\psychic_disciplines.json", json_parse); -global.powers_data = json_to_gamemaker(working_directory + "\\data\\psychic_powers.json", json_parse); +global.disciplines_data = json_to_gamemaker(working_directory + "/data/psychic_disciplines.json", json_parse); +global.powers_data = json_to_gamemaker(working_directory + "/data/psychic_powers.json", json_parse); /// @param {Struct.TTRPG_stats} unit function generate_marine_powers_description_string(unit) { diff --git a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml index 012393f1c4..0364003fcc 100644 --- a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml +++ b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml @@ -1,39 +1,20 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information - function squeeze_map_forces() { try { var _player_front_row = get_rightmost(); var _enemy_front = get_leftmost(obj_enunit, false); - if (_player_front_row != "none" && _enemy_front != "none") { + if (_player_front_row != noone && _enemy_front != noone) { if (!collision_point(_player_front_row.x + 10, _player_front_row.y, obj_enunit, 0, 1)) { - var _enemy_front = get_leftmost(obj_enunit, false); - if (_enemy_front != "none") { - var _move_distance = calculate_block_distances(_player_front_row, _enemy_front) - 2; - with (obj_pnunit) { - move_unit_block("east", _move_distance, true); - } + var _move_distance = calculate_block_distances(_player_front_row, _enemy_front) - 2; + with (obj_pnunit) { + move_unit_block("east", _move_distance, true); } } } - /* var _enemy_front = get_leftmost(obj_enunit, false); - if (_enemy_front!="none"){ - var _player_front_row=get_rightmost(); - if (_player_front_row!="none"){ - var _move_distance = calculate_block_distances(_player_front_row, _enemy_front) -1; - with (obj_enunit){ - if (!flank && _player_front_row.x 0 && target.object_index == desired_type) { @@ -73,7 +54,7 @@ function target_block_is_valid(target, desired_type) { function get_rightmost(block_type = obj_pnunit, include_flanking = true, include_main_force = true) { try { - var rightmost = "none"; + var rightmost = noone; if (instance_exists(block_type)) { with (block_type) { if (!include_flanking && flank) { @@ -92,7 +73,7 @@ function get_rightmost(block_type = obj_pnunit, include_flanking = true, include continue; } } - if (rightmost == "none" && x > 0) { + if (rightmost == noone && x > 0) { rightmost = block_type.id; } else { if (x > rightmost.x) { @@ -117,7 +98,7 @@ function block_has_armour(target) { function get_leftmost(block_type = obj_pnunit, include_flanking = true) { try { - var left_most = "none"; + var left_most = noone; if (instance_exists(block_type)) { with (block_type) { if (!include_flanking && flank) { @@ -133,7 +114,7 @@ function get_leftmost(block_type = obj_pnunit, include_flanking = true) { continue; } } - if (left_most == "none" && x > 0) { + if (left_most == noone && x > 0) { left_most = block_type.id; } else { if (x < left_most.x && x > 0) { @@ -241,9 +222,7 @@ function move_enemy_blocks() { /// @self Asset.GMObject.obj_enunit|Asset.GMObject.obj_pnunit function block_composition_string() { - var _composition_string = ""; - - _composition_string = $"{unit_count}x Total; "; + var _composition_string = $"{unit_count}x Total; "; if (men > 0) { _composition_string += $"{string_plural_count("Normal Unit", men)}; "; } diff --git a/scripts/scr_ruins_reward/scr_ruins_reward.gml b/scripts/scr_ruins_reward/scr_ruins_reward.gml index c2969ef8e8..e0e8dd5461 100644 --- a/scripts/scr_ruins_reward/scr_ruins_reward.gml +++ b/scripts/scr_ruins_reward/scr_ruins_reward.gml @@ -54,7 +54,7 @@ function scr_ruins_reward(_star_system, _pid_idx, _ruins) { // Lazy-load JSON from disk once if (_loot_registry == undefined) { _loot_registry = {}; - var _path = working_directory + "\\data\\ruins_loot.json"; + var _path = working_directory + "/data/ruins_loot.json"; var _raw_json = json_to_gamemaker(_path, json_parse); var _keys = struct_get_names(_raw_json); diff --git a/scripts/scr_start_load/scr_start_load.gml b/scripts/scr_start_load/scr_start_load.gml index e6a8585bd5..3a0712144a 100644 --- a/scripts/scr_start_load/scr_start_load.gml +++ b/scripts/scr_start_load/scr_start_load.gml @@ -4,17 +4,7 @@ function scr_start_load(fleet, load_from_star, load_options) { // this distributes the marines and vehicles to the correct ships if the chapter is fleet-based or a home-based chapter - var _unit, _comp, _marine, total_vehic_size; - var total_distribute_squads = [ - [], - [], - [], - [], - [], - [], - [], - [] - ]; + var total_distribute_squads = [[], [], [], [], [], [], [], []]; var escort_load = load_options[0]; var split_scouts = load_options[1]; @@ -26,9 +16,9 @@ function scr_start_load(fleet, load_from_star, load_options) { escort_load = 1; } var comp_has_units = []; - for (_comp = 0; _comp < 10; _comp++) { + for (var _comp = 0; _comp < 10; _comp++) { comp_has_units[_comp] = false; - for (_unit = 0; _unit < 20; _unit++) { + for (var _unit = 0; _unit < 20; _unit++) { if (obj_ini.name[_comp][_unit] != "") { comp_has_units[_comp] = true; break; @@ -65,44 +55,31 @@ function scr_start_load(fleet, load_from_star, load_options) { } } // i feel like there definatly is or should be a generic function for this???? - var _vehicles = [ - "Rhino", - "Predator", - "Land Speeder", - "Land Raider", - "Whirlwind" - ]; + var _vehicles = ["Rhino", "Predator", "Land Speeder", "Land Raider", "Whirlwind"]; function load_vehicles(_companies, _equip, _ship, size) { obj_ini.veh_wid[_companies][_equip] = 0; obj_ini.veh_lid[_companies][_equip] = _ship; obj_ini.veh_loc[_companies][_equip] = obj_ini.ship_location[_ship]; obj_ini.ship_carrying[_ship] += size; } - var ship_size, _companies_loaded; - _company_size = 0; - var ship = 0; - //ship_size = obj_ini.ship_size[ship]; - _companies_loaded = 1; - var ship_return = 1; - var ship_has_space = true; //loop through companies. try and load whole company onto single ship else spread company across largest ships with remaining space var ship_loop_start = 0; - for (_comp = 0; _comp < 10; _comp++) { + for (var _comp = 0; _comp < 10; _comp++) { if ((split_vets == 1 && _comp == 1) || (!comp_has_units[_comp])) { continue; } if (ship_loop_start >= array_length(obj_ini.ship_carrying)) { ship_loop_start = array_length(obj_ini.ship_carrying); } - total_vehic_size = 0; + var total_vehic_size = 0; var _company_size = 0; var company_loader = []; //array of companies marines var company_vehicle = []; //array of companies vehicles var ship_fit = true; - for (_unit = 0; _unit < (array_length(obj_ini.role[_comp]) - 1); _unit++) { - _marine = fetch_unit([_comp, _unit]); + for (var _unit = 0; _unit < (array_length(obj_ini.role[_comp]) - 1); _unit++) { + var _marine = fetch_unit([_comp, _unit]); // check if marine exists if (_marine.name() != "") { //calculate marine space @@ -119,7 +96,7 @@ function scr_start_load(fleet, load_from_star, load_options) { var _members = _squad.members; for (var squad_member = 0; squad_member < array_length(_members); squad_member++) { squaddy = _members[squad_member]; - _marine = fetch_unit(squaddy); + var _marine = fetch_unit(squaddy); var marine_size = _marine.get_unit_size(); _company_size += marine_size; array_push(company_loader, _marine); @@ -128,7 +105,7 @@ function scr_start_load(fleet, load_from_star, load_options) { } //fetch company vehicles - for (_unit = 1; _unit < array_length(obj_ini.veh_role[_comp]); _unit++) { + for (var _unit = 1; _unit < array_length(obj_ini.veh_role[_comp]); _unit++) { if (array_contains(_vehicles, obj_ini.veh_role[_comp][_unit])) { var _vehic_size = scr_unit_size(false, obj_ini.veh_role[_comp][_unit], false, false); total_vehic_size += _vehic_size; @@ -142,7 +119,7 @@ function scr_start_load(fleet, load_from_star, load_options) { } //if entire company won't fit on ship test to see if there is any ship in the fleet the company will fit on; if (ship_fit == false) { - for (ship_loop = ship_loop_start; ship_loop < array_length(obj_ini.ship_carrying); ship_loop++) { + for (var ship_loop = ship_loop_start; ship_loop < array_length(obj_ini.ship_carrying); ship_loop++) { if ((escort_load == 2) && (obj_ini.ship_capacity[ship_loop] < 250)) { continue; } @@ -161,7 +138,7 @@ function scr_start_load(fleet, load_from_star, load_options) { } } if (!ship_fit) { - for (ship_loop = 1; ship_loop < ship_loop_start; ship_loop++) { + for (var ship_loop = 1; ship_loop < ship_loop_start; ship_loop++) { if ((escort_load == 2) && (obj_ini.ship_capacity[ship_loop] < 250)) { continue; } @@ -181,7 +158,7 @@ function scr_start_load(fleet, load_from_star, load_options) { } if (!ship_fit) { //see if all troops can be grouped together - for (ship_loop = ship_loop_start; ship_loop < array_length(obj_ini.ship_carrying); ship_loop++) { + for (var ship_loop = ship_loop_start; ship_loop < array_length(obj_ini.ship_carrying); ship_loop++) { if ((escort_load == 2) && (obj_ini.ship_capacity[ship_loop] < 250)) { continue; } @@ -196,7 +173,7 @@ function scr_start_load(fleet, load_from_star, load_options) { } } if (!ship_fit) { - for (ship_loop = 1; ship_loop < ship_loop_start; ship_loop++) { + for (var ship_loop = 1; ship_loop < ship_loop_start; ship_loop++) { if ((escort_load == 2) && (obj_ini.ship_capacity[ship_loop] < 250)) { continue; } @@ -218,7 +195,6 @@ function scr_start_load(fleet, load_from_star, load_options) { continue; } if (obj_ini.ship_carrying[ship_loop] < obj_ini.ship_capacity[ship_loop]) { - ship_has_space = true; // new arrays that will contain troops that didn't get loaded var comp_edit = []; var veh_edit = []; @@ -230,9 +206,6 @@ function scr_start_load(fleet, load_from_star, load_options) { } else { array_push(comp_edit, company_loader[m]); } - if (obj_ini.ship_carrying[ship_loop] == obj_ini.ship_capacity[ship_loop]) { - ship_has_space = false; - } } } for (var m = 0; m < array_length(company_vehicle); m++) { @@ -241,9 +214,6 @@ function scr_start_load(fleet, load_from_star, load_options) { } else { array_push(veh_edit, company_vehicle[m]); } - if (obj_ini.ship_carrying[ship_loop] == obj_ini.ship_capacity[ship_loop]) { - ship_has_space = false; - } } company_loader = comp_edit; company_vehicle = veh_edit; diff --git a/scripts/scr_ui_manage/scr_ui_manage.gml b/scripts/scr_ui_manage/scr_ui_manage.gml index c5a1d7d7ae..0502eb063a 100644 --- a/scripts/scr_ui_manage/scr_ui_manage.gml +++ b/scripts/scr_ui_manage/scr_ui_manage.gml @@ -574,7 +574,11 @@ function alternative_manage_views(x1, y1) { surface_reset_target(); // save to local game folder - var base_name = working_directory + $"\\main\\marine_capture_{_unit.name()}_{_unit.marine_number}{_unit.company}"; + var main_dir = working_directory + "/main"; + if (!directory_exists(main_dir)) { + directory_create(main_dir); + } + var base_name = main_dir + $"/marine_capture_{_unit.name()}_{_unit.marine_number}{_unit.company}"; var extension = ".png"; var index = 0; var path; @@ -592,7 +596,11 @@ function alternative_manage_views(x1, y1) { // cleanup surface_free(surf); - LOGGER.debug("Marine image saved to: " + path); + if (file_exists(path)) { + LOGGER.debug("Marine image saved to: " + path); + } else { + LOGGER.error("Failed to save marine image to: " + path); + } } } } diff --git a/scripts/scr_unit_traits/scr_unit_traits.gml b/scripts/scr_unit_traits/scr_unit_traits.gml index f901bf4817..ef52f1774c 100644 --- a/scripts/scr_unit_traits/scr_unit_traits.gml +++ b/scripts/scr_unit_traits/scr_unit_traits.gml @@ -1,5 +1,5 @@ function initialize_marine_traits() { - global.trait_list = json_to_gamemaker(working_directory + "\\data\\traits.json", json_parse); + global.trait_list = json_to_gamemaker(working_directory + "/data/traits.json", json_parse); } function marine_has_trait(wanted_trait) { From 4c9c92c2bf2afa25a4219c705f0cf611560702d6 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 18 Jun 2026 03:33:07 +0300 Subject: [PATCH 009/140] Update Alarm_3.gml --- objects/obj_pnunit/Alarm_3.gml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/objects/obj_pnunit/Alarm_3.gml b/objects/obj_pnunit/Alarm_3.gml index c14485ab3b..a1f7f38b1b 100644 --- a/objects/obj_pnunit/Alarm_3.gml +++ b/objects/obj_pnunit/Alarm_3.gml @@ -121,7 +121,15 @@ try { } } - if (norun == 0) { + // Guard blocks never retreat. The vanilla rule backs a block away from a + // pure-vehicle enemy it cannot hurt, but for the Guard that walks the + // whole rank out of the line and off to the rear, where the enemy ignores + // it (the Marines are now the front block) and turns on the Marines it was + // meant to screen. This is why the Guard only behaved when they were the + // last force left: alone there is nothing to fall back behind and no + // Marine front for the enemy to switch to. The Guard are meant to hold and + // die in place, so only non-guard blocks fall back here. + if (norun == 0 && guard == 0) { x -= 10; engaged = 0; } From e003911ef378534a89437c40ab48de78d58745c9 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 18 Jun 2026 14:14:57 +0300 Subject: [PATCH 010/140] Added Imperial Guard rercruitment button 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. --- objects/obj_controller/Alarm_8.gml | 22 ++++++---------------- objects/obj_star_select/Create_0.gml | 14 ++++++++++++++ scripts/scr_PlanetData/scr_PlanetData.gml | 11 +++++++++++ 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/objects/obj_controller/Alarm_8.gml b/objects/obj_controller/Alarm_8.gml index 53a8aa9f8c..446741deec 100644 --- a/objects/obj_controller/Alarm_8.gml +++ b/objects/obj_controller/Alarm_8.gml @@ -20,22 +20,12 @@ with (obj_star) { heh.show = false; heh.placing = false; heh.alarm[1] = -1; - if (p_owner[1] == 1) { - p_pdf[1] += p_guardsmen[1]; - p_guardsmen[1] = 0; - } - if (p_owner[2] == 1) { - p_pdf[2] += p_guardsmen[2]; - p_guardsmen[2] = 0; - } - if (p_owner[3] == 1) { - p_pdf[3] += p_guardsmen[3]; - p_guardsmen[3] = 0; - } - if (p_owner[4] == 1) { - p_pdf[4] += p_guardsmen[4]; - p_guardsmen[4] = 0; - } + // The Guard-into-PDF fold was removed here. It used to run, every turn, for + // each player world: p_pdf += p_guardsmen; p_guardsmen = 0. That quietly ate the + // Imperial Guard you raise and deploy, folding them back into the abstract PDF and + // zeroing the deployable pool. Recruited Guard now persist as their own pool until + // you embark them, and recruitment pulls bodies the other way (PDF into Guard), so + // folding them back would undo it. } } diff --git a/objects/obj_star_select/Create_0.gml b/objects/obj_star_select/Create_0.gml index 7464f52338..a9499ca01a 100644 --- a/objects/obj_star_select/Create_0.gml +++ b/objects/obj_star_select/Create_0.gml @@ -44,6 +44,20 @@ colonist_button.bind_method = function() { new_colony_fleet(doner[0], doner[1], target.id, obj_controller.selecting_planet, "bolster_population"); }; +// Recruit Guard: raise Imperial Guard from this world's Defense Force (PDF) in fixed +// elements of 1000, so it cannot be spammed off civilians and is bounded by the PDF on +// hand. Costs a small 50 requisition per 1000. Recruited Guard go into the deployable +// pool (p_guardsmen) to embark and deploy. +guard_recruit_button = new PurchaseButton(50); +guard_recruit_button.update({tooltip: "Raise 1000 Imperial Guard from this world's Defense Force (PDF). They join the deployable Guard pool, ready to embark and deploy. Drawn in fixed elements of 1000. /n Costs 50 requisition, requires at least 1000 PDF", label: "Recruit Guard", target: target}); +guard_recruit_button.bind_method = function() { + var _p = obj_controller.selecting_planet; + if (target.p_pdf[_p] >= 1000) { + target.p_pdf[_p] -= 1000; + target.p_guardsmen[_p] += 1000; + } +}; + recruiting_button = new PurchaseButton(0); recruiting_button.update({tooltip: "Enable recruiting", label: "Recruiting", target: target}); recruiting_button.bind_method = function() { diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index fa77bd094f..d3e7cdd75a 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -1685,6 +1685,17 @@ function PlanetData(planet, system) constructor { _col_button.draw(array_length(obj_star_select.potential_donors)); + // Recruit Guard sits directly below Request Colonists (same column, one + // row down). Player worlds only, since you can only mobilise your own PDF. + // Clicking is gated on the PDF holding at least 1000 (here) and on having + // the 50 requisition (the PurchaseButton's own check), so a click can never + // spend the 50 without actually raising the 1000. + if (current_owner == eFACTION.PLAYER) { + var _guard_button = obj_star_select.guard_recruit_button; + _guard_button.update({x1: xx + 35, y1: _half_way + spacing_y, allow_click: true}); + _guard_button.draw(pdf >= 1000); + } + var _recruit_button = obj_star_select.recruiting_button; _recruit_button.update({x1: xx + (spacing_x * 2) + 15, y1: _half_way, allow_click: true}); From 165cc1a663bf338fb73688162d7eeee25f1d8a0d Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 19 Jun 2026 01:25:59 +0300 Subject: [PATCH 011/140] Made a differnet pipeline for 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. --- datafiles/data/armour.json | 31 +++++++++++++++ datafiles/data/unit_stats.json | 53 +++++++++++++++++++++++++ datafiles/data/weapons.json | 19 +++++++++ scripts/scr_add_man/scr_add_man.gml | 12 +++++- scripts/scr_cheatcode/scr_cheatcode.gml | 30 +++----------- 5 files changed, 119 insertions(+), 26 deletions(-) diff --git a/datafiles/data/armour.json b/datafiles/data/armour.json index b591e3cbd4..6f1cea803f 100644 --- a/datafiles/data/armour.json +++ b/datafiles/data/armour.json @@ -172,6 +172,37 @@ }, "description": "This armour is used by T'au fire warriors." }, + "Flak Armour": { + "abbreviation": "FlkArm", + "armour_value": { + "artifact": 7, + "master_crafted": 6, + "standard": 5 + }, + "damage_resistance_mod": { + "artifact": 0, + "master_crafted": 0, + "standard": 0 + }, + "description": "A simple flak jacket of ablative plates and ballistic weave, the standard protection of the Astra Militarum rank and file. It turns aside shrapnel and glancing hits but offers little against a determined blow.", + "hp_mod": { + "artifact": 0, + "master_crafted": 0, + "standard": 0 + }, + "melee_mod": { + "artifact": 0, + "master_crafted": 0, + "standard": 0 + }, + "ranged_mod": { + "artifact": 10, + "master_crafted": 8, + "standard": 5 + }, + "renegade_buy": true, + "value": 2 + }, "Light Power Armour": { "abbreviation": "LPwrArm", "armour_value": { diff --git a/datafiles/data/unit_stats.json b/datafiles/data/unit_stats.json index a8ad115cf7..4773c6ca38 100644 --- a/datafiles/data/unit_stats.json +++ b/datafiles/data/unit_stats.json @@ -581,6 +581,59 @@ 1 ] }, + "guardsman": { + "ballistic_skill": [ + 25, + 1 + ], + "base_group": "human", + "charisma": [ + 15, + 1 + ], + "constitution": [ + 20, + 1 + ], + "dexterity": [ + 20, + 1 + ], + "intelligence": [ + 15, + 1 + ], + "luck": 5, + "piety": [ + 25, + 1 + ], + "religion": "imperial_cult", + "start_gear": { + "armour": "Flak Armour", + "gear": "", + "mobi": "", + "wep1": "Lasgun", + "wep2": "" + }, + "strength": [ + 20, + 1 + ], + "technology": [ + 10, + 1 + ], + "title": "Guardsman", + "weapon_skill": [ + 15, + 1 + ], + "wisdom": [ + 15, + 1 + ] + }, "skitarii": { "ballistic_skill": [ 20, diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index a570b6efeb..e779bbc2aa 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1610,6 +1610,25 @@ ], "value": 15 }, + "Lasgun": { + "abbreviation": "Lasgun", + "ammo": 40, + "arp": 1, + "attack": { + "artifact": 26, + "master_crafted": 22, + "standard": 18 + }, + "description": "The standard-issue weapon of the Astra Militarum. A rugged two-handed las weapon firing coherent energy beams, prized for its reliability and the ease of recharging its power packs in the field. Common, dependable, and unremarkable on its own.", + "melee_hands": 0, + "range": 12, + "ranged_hands": 1, + "spli": 2, + "tags": [ + "las" + ], + "value": 2 + }, "Laspistol": { "abbreviation": "Lpstl", "ammo": 30, diff --git a/scripts/scr_add_man/scr_add_man.gml b/scripts/scr_add_man/scr_add_man.gml index d8281e1c6f..a80b3b0371 100644 --- a/scripts/scr_add_man/scr_add_man.gml +++ b/scripts/scr_add_man/scr_add_man.gml @@ -10,7 +10,8 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption "Sister Hospitaler", "Ranger", "Ork Sniper", - "Flash Git" + "Flash Git", + "Guardsman" ]; var _gear = {}; var _company_slot = 0; @@ -26,6 +27,11 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption // TODO: Implement logic for Auxiliary Soldier (Race 2.5, Renegade stats) switch (man_role) { + case "Guardsman": + spawn_exp = 10; + obj_ini.race[target_company][_company_slot] = eFACTION.IMPERIUM; + _unit = new TTRPG_stats("imperial_guard", target_company, _company_slot, "guardsman"); + break; case "Skitarii": spawn_exp = 10; obj_ini.race[target_company][_company_slot] = 3; @@ -101,6 +107,10 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption case "Sister Hospitaler": obj_ini.name[target_company][_company_slot] = global.name_generator.GenerateFromSet("imperial_female"); break; + + case "Guardsman": + obj_ini.name[target_company][_company_slot] = global.name_generator.GenerateFromSet("imperial_male"); + break; } if (!array_contains(non_marine_roles, man_role)) { diff --git a/scripts/scr_cheatcode/scr_cheatcode.gml b/scripts/scr_cheatcode/scr_cheatcode.gml index ef2ab729be..1eb84817b5 100644 --- a/scripts/scr_cheatcode/scr_cheatcode.gml +++ b/scripts/scr_cheatcode/scr_cheatcode.gml @@ -41,31 +41,6 @@ function scr_cheatcode(argument0) { if (cheat_code != "") { switch (cheat_code) { - case "embarkguard": - with (obj_controller) { - var _n = embark_guardsmen(obj_ini.home_name, obj_ini.home_planet); - scr_popup("Imperial Guard", "Embarked " + string(_n) + " Guard from your homeworld. Total embarked: " + string(player_guardsmen_embarked()), ""); - } - break; - case "deployguard": - with (obj_controller) { - if (instance_exists(obj_star_select) && (selecting_planet > 0)) { - var _star = obj_star_select.target; - var _n = deploy_guardsmen(_star.name, selecting_planet); - scr_popup("Imperial Guard", "Deployed " + string(_n) + " Guard onto " + string(_star.name) + " " + string(selecting_planet) + ". (Unloads from your ships orbiting that world.)", ""); - } else { - var _n = deploy_guardsmen(obj_ini.home_name, obj_ini.home_planet); - scr_popup("Imperial Guard", "No world selected, so deployed " + string(_n) + " Guard at your homeworld. Open a system and click a planet first to target another world.", ""); - } - } - break; - case "titheguard": - with (obj_controller) { - var _amt = real(cheat_arguments[0]); - var _n = tithe_guardsmen(obj_ini.home_name, obj_ini.home_planet, _amt); - scr_popup("Imperial Guard", "Raised " + string(_n) + " Guard from your homeworld's population.", ""); - } - break; case "finishforge": with (obj_controller) { specialist_point_handler.forge_points = 1000000; @@ -128,6 +103,11 @@ function scr_cheatcode(argument0) { scr_add_man("Flash Git", 0, "", "", 0, true, "default"); } break; + case "guardsman": + repeat (real(cheat_arguments[0])) { + scr_add_man("Guardsman", 0, "", "", 0, true, "default"); + } + break; case "chaosfleetspawn": spawn_chaos_warlord(); break; From 1c1fb019468c4a73b4c6ada1dfd8895859f31870 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 19 Jun 2026 18:11:51 +0300 Subject: [PATCH 012/140] Fixed the health issue to guardsmen, added bolt on for guardsmen spawning 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 --- datafiles/data/unit_stats.json | 5 +- objects/obj_ncombat/Alarm_0.gml | 89 +++------------------------------ 2 files changed, 10 insertions(+), 84 deletions(-) diff --git a/datafiles/data/unit_stats.json b/datafiles/data/unit_stats.json index 4773c6ca38..f8fa2c7782 100644 --- a/datafiles/data/unit_stats.json +++ b/datafiles/data/unit_stats.json @@ -592,8 +592,9 @@ 1 ], "constitution": [ - 20, - 1 + 28, + 1, + "max" ], "dexterity": [ 20, diff --git a/objects/obj_ncombat/Alarm_0.gml b/objects/obj_ncombat/Alarm_0.gml index f1bc5f961a..b01e676c8c 100644 --- a/objects/obj_ncombat/Alarm_0.gml +++ b/objects/obj_ncombat/Alarm_0.gml @@ -3154,89 +3154,14 @@ try { u.sprite_index = spr_weapon_blank; } - // ** Set up friendly Imperial Guard auxilia ** - // Bulk player force modelled on the defenses above. Reads the world's deployed - // garrison (p_guardsmen). It renders and is durable via veh blocks; its firepower - // is injected in scr_player_combat_weapon_stacks, scaled to player_guard. No roster - // coupling, so no per-model casualty writes. + // ** Imperial Guard auxilia ** + // The old p_guardsmen bolt-on block was retired here. Guardsmen are now fielded + // through the standard roster: station them on a world (ship_location -1) and the + // Local Forces toggle deploys them into the Hirelings block like any other unit, + // so the engine handles placement, targeting and casualties. player_guard is kept + // at 0 so the dormant firepower-injection path in scr_player_combat_weapon_stacks + // stays inert. player_guard = 0; - if ((battle_object != 0) && (battle_special == "")) { - player_guard = battle_object.p_guardsmen[battle_id]; - } - if (player_guard > 0) { - // Place the Guard as the front rank in both attack and defence. They must be - // the leading block, never a rear one: the player advance (move_unit_block - // "east") refuses to move a block when another block sits directly ahead of it, - // so Guard placed behind the Marines on attack can never step forward, and the - // Marines simply advance off and leave them standing at the rear (the Marines - // "pass them by"). As the front rank the Guard have open ground ahead, so they - // lead the charge on attack and hold the line on defence, and either way they - // reach the enemy and fight. Front rank is just east of the Marines and still - // west of the enemy spawn (rightmost block + 10). - var _maxx = -50; - var _minx = 1000000; - with (obj_pnunit) { - if (x > _maxx) _maxx = x; - if (x < _minx) _minx = x; - } - var _frontx; - if (_maxx < 0) { - _frontx = 100; // no other player blocks: stand-alone Guard force - } else { - _frontx = _maxx + 5; // front rank, attack and defence alike - } - u = instance_create(_frontx, 240, obj_pnunit); - u.guard = 1; - - // Guardsmen line: pure infantry, no tanks, the way the enemy Imperial Guard - // keep their soldier lines tank-free. They render and take losses per man like - // the enemy Guard. They have no anti-tank weapon, so against armour they can - // only bleed and die unless a Leman Russ line is present. - u.men = player_guard; - u.dudes[1] = "Imperial Guardsman"; - u.dudes_num[1] = player_guard; - u.dudes_ac[1] = 40; // match the enemy Guardsman: flak armour value 40 - u.dudes_hp[1] = 5; - u.dudes_vehicle[1] = 0; - - // Keep the default obj_pnunit sprite (do not blank it): the block needs its - // collision mask, or the enemy advance walks straight through the Guard. - - // Count the infantry toward player forces. The normal accumulation only runs - // during setup and this block spawns too late for it; obj_pnunit's Alarm_3 - // skips its auto-add for guard blocks so this is not double counted. - player_forces += u.men; - player_max += u.men; - - // Leman Russ tanks form their own separate block (guard == 2), placed just - // behind the infantry line so the Guardsmen screen them. Tanks are the only - // anti-armour the Guard field, kept out of the soldier line like the enemy's. - var _tanks = min(30, round(player_guard / 5000)); - if (_tanks > 0) { - var _tankx = max(5, _frontx - 10); - var t = instance_create(_tankx, 240, obj_pnunit); - t.guard = 2; - t.men = 0; - for (var i = 1; i <= _tanks; i++) { - t.veh_co[i] = 0; - t.veh_id[i] = 0; - t.veh_type[i] = "Leman Russ Battle Tank"; - t.veh_hp[i] = 250; - t.veh_ac[i] = 40; - t.veh_dead[i] = 0; - t.veh_hp_multiplier[i] = 1; - t.veh_wep1[i] = "Battle Cannon"; - } - t.veh = _tanks; - t.dudes[1] = "Leman Russ Battle Tank"; - t.dudes_num[1] = _tanks; - t.dudes_ac[1] = 40; - t.dudes_hp[1] = 250; - t.dudes_vehicle[1] = 1; - player_forces += t.veh; - player_max += t.veh; - } - } instance_activate_object(obj_enunit); } catch (_exception) { From c9452d6cf3a79ba6ab3381f62ce321eb1cedfaf3 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sat, 20 Jun 2026 20:53:34 +0300 Subject: [PATCH 013/140] Added Guardsmen Squads 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. --- datafiles/data/unit_stats.json | 54 +++++++++++++++++++ scripts/macros/macros.gml | 3 ++ scripts/scr_add_man/scr_add_man.gml | 12 ++++- scripts/scr_cheatcode/scr_cheatcode.gml | 29 +++++----- .../scr_marine_struct/scr_marine_struct.gml | 3 ++ .../scr_player_combat_weapon_stacks.gml | 53 +++++++++++++++--- 6 files changed, 130 insertions(+), 24 deletions(-) diff --git a/datafiles/data/unit_stats.json b/datafiles/data/unit_stats.json index f8fa2c7782..249045efb9 100644 --- a/datafiles/data/unit_stats.json +++ b/datafiles/data/unit_stats.json @@ -581,6 +581,60 @@ 1 ] }, + "guard_squad": { + "ballistic_skill": [ + 25, + 1 + ], + "base_group": "human", + "charisma": [ + 15, + 1 + ], + "constitution": [ + 28, + 1, + "max" + ], + "dexterity": [ + 20, + 1 + ], + "intelligence": [ + 15, + 1 + ], + "luck": 5, + "piety": [ + 25, + 1 + ], + "religion": "imperial_cult", + "start_gear": { + "armour": "Flak Armour", + "gear": "", + "mobi": "", + "wep1": "Lasgun", + "wep2": "" + }, + "strength": [ + 20, + 1 + ], + "technology": [ + 10, + 1 + ], + "title": "Guard Squad", + "weapon_skill": [ + 15, + 1 + ], + "wisdom": [ + 15, + 1 + ] + }, "guardsman": { "ballistic_skill": [ 25, diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 7c16cd0d58..85a567a07d 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -1,3 +1,6 @@ +// Imperial Guard squad: how many guardsmen one Guard Squad unit represents. +#macro GUARD_SQUAD_SIZE 10 + #macro MAX_STC_PER_SUBCATEGORY 6 #macro DEFAULT_TOOLTIP_VIEW_OFFSET 32 #macro DEFAULT_LINE_GAP -1 diff --git a/scripts/scr_add_man/scr_add_man.gml b/scripts/scr_add_man/scr_add_man.gml index a80b3b0371..5737106699 100644 --- a/scripts/scr_add_man/scr_add_man.gml +++ b/scripts/scr_add_man/scr_add_man.gml @@ -11,7 +11,8 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption "Ranger", "Ork Sniper", "Flash Git", - "Guardsman" + "Guardsman", + "Guard Squad" ]; var _gear = {}; var _company_slot = 0; @@ -32,6 +33,11 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption obj_ini.race[target_company][_company_slot] = eFACTION.IMPERIUM; _unit = new TTRPG_stats("imperial_guard", target_company, _company_slot, "guardsman"); break; + case "Guard Squad": + spawn_exp = 10; + obj_ini.race[target_company][_company_slot] = eFACTION.IMPERIUM; + _unit = new TTRPG_stats("imperial_guard", target_company, _company_slot, "guard_squad"); + break; case "Skitarii": spawn_exp = 10; obj_ini.race[target_company][_company_slot] = 3; @@ -111,6 +117,10 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption case "Guardsman": obj_ini.name[target_company][_company_slot] = global.name_generator.GenerateFromSet("imperial_male"); break; + + case "Guard Squad": + obj_ini.name[target_company][_company_slot] = global.name_generator.GenerateFromSet("imperial_male"); + break; } if (!array_contains(non_marine_roles, man_role)) { diff --git a/scripts/scr_cheatcode/scr_cheatcode.gml b/scripts/scr_cheatcode/scr_cheatcode.gml index 61fd2b5ece..93089f05f2 100644 --- a/scripts/scr_cheatcode/scr_cheatcode.gml +++ b/scripts/scr_cheatcode/scr_cheatcode.gml @@ -108,6 +108,11 @@ function scr_cheatcode(argument0) { scr_add_man("Guardsman", 0, "", "", 0, true, "default"); } break; + case "guardsquad": + repeat (real(cheat_arguments[0])) { + scr_add_man("Guard Squad", 0, "", "", 0, true, "default"); + } + break; case "chaosfleetspawn": spawn_chaos_warlord(); break; @@ -411,16 +416,12 @@ function draw_planet_debug_options() { if (debug) { debug_slate.inside_method = function() { debug_options.draw(); - switch(debug_options.current_selection){ - case 0: - draw_planet_debug_forces(); - break; - case 1: - draw_planet_debug_problems(); - break; - case 2: - draw_planet_debug_features(); - break; + if (debug_options.current_selection == 0) { + draw_planet_debug_forces(); + } else if (debug_options.current_selection == 1) { + draw_planet_debug_problems(); + } else if (debug_options.current_selection == 2) { + draw_planet_debug_features(); } }; debug_slate.draw(); @@ -501,7 +502,6 @@ function draw_planet_debug_problems() { if (scr_hit(38, _y, 337, _y + 20)) { tooltip_draw(mission_name_key(_keys[i])); if (mouse_button_clicked()) { - var _p_data = obj_star_select.p_data; switch (_keys[i]) { case "inquisitor": mission_inquistion_hunt_inquisitor(target.id); @@ -518,12 +518,7 @@ function draw_planet_debug_problems() { case "mech_bionics": spawn_mechanicus_mission("mech_bionics"); break; - case "succession": - _p_data.init_war_of_succession(); - break; - case "fallen": - _p_data.init_fallen_marines(); - break + default: scr_popup("error", "no specific debug action created please consider helping to make one", ""); break; diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index 405aef0b6e..85735fc3bb 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -396,6 +396,9 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} max_h += gear_weapon_data("weapon", weapon_one(), "hp_mod"); max_h += gear_weapon_data("weapon", weapon_two(), "hp_mod"); } + if (role() == "Guard Squad") { + max_h *= GUARD_SQUAD_SIZE; // a squad shares one pooled health bar and dies as a whole + } return max_h; }; diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index de330d2afd..d8122c652a 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -60,6 +60,36 @@ function add_data_to_stack(stack_index, weapon, unit_damage = false, head_role = } } +/// @self Asset.GMObject.obj_pnunit +/// Adds a single named weapon to the stacks, firing "count" times. Used for Guard +/// Squads, where one unit struct stands for a whole squad: the default weapon (wep1) +/// fires once per man and the special weapon (wep2) fires once for the squad. Mirrors +/// the enemy horde firepower in scr_en_weapon (attack times the number firing) rather +/// than the normal single-primary-weapon path, which would only fire the higher-attack gun. +function add_squad_weapon(weapon_name, count, head_role = false, unit = "none") { + if (weapon_name == "") { + return; + } + var _w = gear_weapon_data("weapon", weapon_name, "all", false, "standard"); + if (!is_struct(_w) || _w.name == "") { + return; + } + var _idx = find_stack_index(_w.name, head_role, unit); + if (_idx < 0) { + return; + } + att[_idx] += _w.attack * count; + apa[_idx] = _w.arp; + range[_idx] = _w.range; + wep_num[_idx] += count; + splash[_idx] = _w.spli; + wep[_idx] = _w.name; + if (obj_ncombat.started == 0) { + ammo[_idx] = _w.ammo; + } + wep_owner[_idx] = "assorted"; +} + /// @self Asset.GMObject.obj_pnunit function find_stack_index(weapon_name, head_role = false, unit = "none") { final_index = -1; @@ -312,12 +342,23 @@ function scr_player_combat_weapon_stacks() { } if (marine_casting[g] == false) { var weapon_stack_index = 0; - var primary_ranged = unit.ranged_damage_data[3]; //collect unit ranged data - var weapon_stack_index = find_stack_index(primary_ranged.name, head_role, unit); - if (weapon_stack_index > -1) { - add_data_to_stack(weapon_stack_index, primary_ranged, unit.ranged_damage_data[0], head_role, unit); - if (head_role) { - player_head_role_stack(weapon_stack_index, unit); + if (unit.role() == "Guard Squad") { + // The squad thins as it takes losses: its surviving strength scales with + // remaining health, so a half-health squad fires half its lasguns and a + // squad on its last legs fires one. It fires wep1 once per surviving man + // and its special weapon (wep2) once while the squad still lives. + var _sq_max = unit.max_health(); + var _sq_men = (_sq_max > 0) ? max(1, ceil(GUARD_SQUAD_SIZE * unit.hp() / _sq_max)) : 1; + add_squad_weapon(unit.weapon_one(), _sq_men, head_role, unit); + add_squad_weapon(unit.weapon_two(), 1, head_role, unit); + } else { + var primary_ranged = unit.ranged_damage_data[3]; //collect unit ranged data + weapon_stack_index = find_stack_index(primary_ranged.name, head_role, unit); + if (weapon_stack_index > -1) { + add_data_to_stack(weapon_stack_index, primary_ranged, unit.ranged_damage_data[0], head_role, unit); + if (head_role) { + player_head_role_stack(weapon_stack_index, unit); + } } } From 448d2bc27fdb507da22c79cacec56c789d37d93a Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 21 Jun 2026 01:31:55 +0300 Subject: [PATCH 014/140] Fixed issues with single unit guardsmen and their spawning 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. --- datafiles/data/armour.json | 6 +++--- datafiles/data/weapons.json | 8 ++++---- scripts/scr_add_man/scr_add_man.gml | 10 ++++++++-- scripts/scr_after_combat/scr_after_combat.gml | 2 +- scripts/scr_cheatcode/scr_cheatcode.gml | 10 ++++++++-- scripts/scr_company_view/scr_company_view.gml | 19 +++++++++++++++++++ .../scr_marine_struct/scr_marine_struct.gml | 9 +++++++++ 7 files changed, 52 insertions(+), 12 deletions(-) diff --git a/datafiles/data/armour.json b/datafiles/data/armour.json index 6f1cea803f..0504ce9e46 100644 --- a/datafiles/data/armour.json +++ b/datafiles/data/armour.json @@ -175,9 +175,9 @@ "Flak Armour": { "abbreviation": "FlkArm", "armour_value": { - "artifact": 7, - "master_crafted": 6, - "standard": 5 + "artifact": 12, + "master_crafted": 11, + "standard": 10 }, "damage_resistance_mod": { "artifact": 0, diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index e779bbc2aa..e466bb0861 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1613,11 +1613,11 @@ "Lasgun": { "abbreviation": "Lasgun", "ammo": 40, - "arp": 1, + "arp": 2, "attack": { - "artifact": 26, - "master_crafted": 22, - "standard": 18 + "artifact": 36, + "master_crafted": 32, + "standard": 28 }, "description": "The standard-issue weapon of the Astra Militarum. A rugged two-handed las weapon firing coherent energy beams, prized for its reliability and the ease of recharging its power packs in the field. Common, dependable, and unremarkable on its own.", "melee_hands": 0, diff --git a/scripts/scr_add_man/scr_add_man.gml b/scripts/scr_add_man/scr_add_man.gml index 5737106699..3f68e2731d 100644 --- a/scripts/scr_add_man/scr_add_man.gml +++ b/scripts/scr_add_man/scr_add_man.gml @@ -145,8 +145,14 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption _unit.add_exp(spawn_exp); _unit.allocate_unit_to_fresh_spawn(home_spot); _unit.update_role(man_role); - with (obj_ini) { - scr_company_order(target_company); + // Re-sorting the whole company after every spawn is O(n) per call, which makes a + // bulk spawn O(n^2) and freezes at high counts. Callers doing a batch can pass + // other_data.skip_company_order and run scr_company_order once when finished. + var _skip_order = is_struct(other_data) && variable_struct_exists(other_data, "skip_company_order") && other_data.skip_company_order; + if (!_skip_order) { + with (obj_ini) { + scr_company_order(target_company); + } } _unit.update_health(_unit.max_health()); return _unit; diff --git a/scripts/scr_after_combat/scr_after_combat.gml b/scripts/scr_after_combat/scr_after_combat.gml index b4668a3b90..723cd11c9b 100644 --- a/scripts/scr_after_combat/scr_after_combat.gml +++ b/scripts/scr_after_combat/scr_after_combat.gml @@ -240,7 +240,7 @@ function after_battle_part1() { marine_dead[i] = 1; marine_hp[i] = -50; } - if ((veh_type[i] != "") && (obj_ncombat.defeat == 1)) { + if ((i < array_length(veh_type)) && (veh_type[i] != "") && (obj_ncombat.defeat == 1)) { veh_dead[i] = 1; veh_hp[i] = -200; } diff --git a/scripts/scr_cheatcode/scr_cheatcode.gml b/scripts/scr_cheatcode/scr_cheatcode.gml index 93089f05f2..8cdeb77b9e 100644 --- a/scripts/scr_cheatcode/scr_cheatcode.gml +++ b/scripts/scr_cheatcode/scr_cheatcode.gml @@ -105,12 +105,18 @@ function scr_cheatcode(argument0) { break; case "guardsman": repeat (real(cheat_arguments[0])) { - scr_add_man("Guardsman", 0, "", "", 0, true, "default"); + scr_add_man("Guardsman", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); + } + with (obj_ini) { + scr_company_order(0); } break; case "guardsquad": repeat (real(cheat_arguments[0])) { - scr_add_man("Guard Squad", 0, "", "", 0, true, "default"); + scr_add_man("Guard Squad", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); + } + with (obj_ini) { + scr_company_order(0); } break; case "chaosfleetspawn": diff --git a/scripts/scr_company_view/scr_company_view.gml b/scripts/scr_company_view/scr_company_view.gml index 0addd44874..273de529e9 100644 --- a/scripts/scr_company_view/scr_company_view.gml +++ b/scripts/scr_company_view/scr_company_view.gml @@ -49,6 +49,25 @@ function find_company_open_slot(target_company) { break; } } + if (good == -1) { + // No free slot left: grow the company by one fully-initialised blank slot so + // companies are effectively uncapped (HQ included). Only runs on overflow, so + // normal recruiting is unchanged. All parallel arrays are extended together to + // stay in sync, mirroring _init_marine_row for a single index. + good = array_length(obj_ini.name[target_company]); + obj_ini.race[target_company][good] = 1; + obj_ini.name[target_company][good] = ""; + obj_ini.role[target_company][good] = ""; + obj_ini.wep1[target_company][good] = ""; + obj_ini.spe[target_company][good] = ""; + obj_ini.wep2[target_company][good] = ""; + obj_ini.armour[target_company][good] = ""; + obj_ini.gear[target_company][good] = ""; + obj_ini.mobi[target_company][good] = ""; + obj_ini.age[target_company][good] = 0; + obj_ini.god[target_company][good] = 0; + obj_ini.TTRPG[target_company][good] = new TTRPG_stats("chapter", target_company, good, "blank"); + } return good; } diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index 85735fc3bb..98260be90d 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -1898,6 +1898,15 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} static allocate_unit_to_fresh_spawn = function(type = "default") { var homestar = "none"; var spawn_location_chosen = false; + if (type == "home_planet") { + // Place directly on the chapter home planet and keep the unit off-ship. Used by + // bulk spawns so large numbers of units are not distributed across the fleet's + // ships, which is slow and clutters ship cargo. + planet_location = obj_ini.home_planet; + ship_location = -1; + location_string = obj_ini.home_name; + return; + } if (((type == "home") || (type == "default")) && (obj_ini.fleet_type == ePLAYER_BASE.HOME_WORLD)) { var homestar = find_star_by_name(obj_ini.home_name); } else if (type != "ship") { From 70a5084b442d39ee671f98264c3a162504706724 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 21 Jun 2026 03:08:47 +0300 Subject: [PATCH 015/140] New update fixes guardsmen spawning and adds guard filter 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. --- datafiles/data/weapons.json | 8 ++++---- .../scr_marine_struct/scr_marine_struct.gml | 18 ++++++++++++++---- scripts/scr_roster/scr_roster.gml | 14 +++++++++++++- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index e466bb0861..2114b83c45 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1613,11 +1613,11 @@ "Lasgun": { "abbreviation": "Lasgun", "ammo": 40, - "arp": 2, + "arp": 1, "attack": { - "artifact": 36, - "master_crafted": 32, - "standard": 28 + "artifact": 30, + "master_crafted": 26, + "standard": 22 }, "description": "The standard-issue weapon of the Astra Militarum. A rugged two-handed las weapon firing coherent energy beams, prized for its reliability and the ease of recharging its power packs in the field. Common, dependable, and unremarkable on its own.", "melee_hands": 0, diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index 98260be90d..97b2f65824 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -1899,12 +1899,22 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} var homestar = "none"; var spawn_location_chosen = false; if (type == "home_planet") { - // Place directly on the chapter home planet and keep the unit off-ship. Used by - // bulk spawns so large numbers of units are not distributed across the fleet's - // ships, which is slow and clutters ship cargo. - planet_location = obj_ini.home_planet; + // Place on the chapter's actual owned planet in the home system and keep the unit + // off-ship, so bulk spawns are not scattered across the fleet's ships. Scan for a + // player-owned planet rather than trusting obj_ini.home_planet, which can be a + // stale index pointing at a planet that does not exist in this system. ship_location = -1; location_string = obj_ini.home_name; + planet_location = obj_ini.home_planet; + var homestar = find_star_by_name(obj_ini.home_name); + if (homestar != "none") { + for (var i = 1; i <= homestar.planets; i++) { + if (homestar.p_owner[i] == eFACTION.PLAYER) { + planet_location = i; + break; + } + } + } return; } if (((type == "home") || (type == "default")) && (obj_ini.fleet_type == ePLAYER_BASE.HOME_WORLD)) { diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 5caf8a0f44..0dc05d9132 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -111,6 +111,11 @@ function Roster() constructor { _valid_type = _allow_dreadnoughts; } } + // Guardsmen answer to their own filter button rather than always passing + var _grd_role = _unit.role(); + if (_grd_role == "Guardsman" || _grd_role == "Guard Squad") { + _valid_type = array_contains(_valid_squad_types, "guardsman"); + } } if (_unit.ship_location > -1) { @@ -158,7 +163,7 @@ function Roster() constructor { static new_squad_button = function(display, squad_id) { var _button = new ToggleButton(); display = string_replace(display, " Squad", ""); - if (display != "Command") { + if (display != "Command" && display != "Guardsmen") { display = string_plural(display); } _button.str1 = display; @@ -290,6 +295,13 @@ function Roster() constructor { new_squad_button("Dreadnought", "dreadnought"); } } + // Guardsmen and Guard Squads have no squad type, so give them their + // own filter button (added once) so they can be selected on their own. + var _grd_role = _unit.role(); + if ((_grd_role == "Guardsman" || _grd_role == "Guard Squad") && !array_contains(_squads, "guardsman")) { + array_push(_squads, "guardsman"); + new_squad_button("Guardsmen", "guardsman"); + } } } } From 065dcbdb574e21b9f1dceda6ac77c580f10f04aa Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 21 Jun 2026 03:53:31 +0300 Subject: [PATCH 016/140] Fixed filter for guardsmen. Now you can filter them out from your entirer force if you w ant --- objects/obj_star_select/Create_0.gml | 23 +++++++++ scripts/scr_PlanetData/scr_PlanetData.gml | 63 +++++------------------ 2 files changed, 37 insertions(+), 49 deletions(-) diff --git a/objects/obj_star_select/Create_0.gml b/objects/obj_star_select/Create_0.gml index a9499ca01a..df87d667a0 100644 --- a/objects/obj_star_select/Create_0.gml +++ b/objects/obj_star_select/Create_0.gml @@ -58,6 +58,29 @@ guard_recruit_button.bind_method = function() { } }; +// Levy Guardsmen: raise 100 deployable Guardsmen as actual units (not the abstract PDF +// pool). They muster on this world, stationed off-ship, so the deploy roster's Guardsmen +// filter can bring them into a battle here, or they can be embarked onto ships and taken +// on the offensive. Costs 10 requisition. Uses the batch spawn path (one sort at the end) +// so raising 100 at once stays fast. +guardsmen_levy_button = new PurchaseButton(10); +guardsmen_levy_button.update({tooltip: "Levy 100 Guardsmen from this world as deployable troops. They muster here, ready to be brought into battle or embarked onto your ships. /n Costs 10 requisition", label: "Levy Guardsmen", target: target}); +guardsmen_levy_button.bind_method = function() { + var _star = target.name; + var _planet = obj_controller.selecting_planet; + repeat (100) { + var _u = scr_add_man("Guardsman", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); + if (is_struct(_u)) { + _u.location_string = _star; + _u.planet_location = _planet; + _u.ship_location = -1; + } + } + with (obj_ini) { + scr_company_order(0); + } +}; + recruiting_button = new PurchaseButton(0); recruiting_button.update({tooltip: "Enable recruiting", label: "Recruiting", target: target}); recruiting_button.bind_method = function() { diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index a7490e7779..f938c9b05d 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -34,6 +34,7 @@ function PlanetData(planet, system) constructor { is_hulk = system.space_hulk; x = system.x; y = system.y; + player_disposition = system.dispo[planet]; planet_type = system.p_type[planet]; operatives = system.p_operatives[planet]; pdf = system.p_pdf[planet]; @@ -77,6 +78,10 @@ function PlanetData(planet, system) constructor { heretic_timer = system.p_hurssy_time[planet]; + secret_corruption = system.p_heresy_secret[planet]; + + corruption = system.p_heresy[planet]; + population_influences = system.p_influence[planet]; raided_this_turn = system.p_raided[planet]; @@ -100,7 +105,6 @@ function PlanetData(planet, system) constructor { system.dispo[planet] = 100; } - player_disposition = system.dispo[planet]; garrisons = system.system_garrison[planet]; if (garrisons == 0){ garrisons = system.get_garrison(planet) @@ -119,10 +123,6 @@ function PlanetData(planet, system) constructor { system.p_influence[planet][i] = 0; } } - - secret_corruption = system.p_heresy_secret[planet]; - - corruption = system.p_heresy[planet]; } refresh_data(); @@ -278,7 +278,8 @@ function PlanetData(planet, system) constructor { if (large_population) { new_pdf *= large_pop_conversion; } - edit_pdf(new_pdf) + pdf += new_pdf; + system.p_pdf[planet] = pdf; return new_pdf; }; @@ -467,7 +468,7 @@ function PlanetData(planet, system) constructor { var pip = instance_create(0,0,obj_popup); pip.title = "Planetary Governor Assassinated"; - pip._text = txt; + pip.text = txt; pip.planet = planet; pip.p_data = self; var options = [ @@ -1693,6 +1694,12 @@ function PlanetData(planet, system) constructor { var _guard_button = obj_star_select.guard_recruit_button; _guard_button.update({x1: xx + 35, y1: _half_way + spacing_y, allow_click: true}); _guard_button.draw(pdf >= 1000); + + // Levy Guardsmen sits one row below Recruit Guard. Enabled whenever the + // player can afford it (the PurchaseButton checks the 10 requisition). + var _levy_button = obj_star_select.guardsmen_levy_button; + _levy_button.update({x1: xx + 35, y1: _half_way + spacing_y * 2, allow_click: true}); + _levy_button.draw(true); } var _recruit_button = obj_star_select.recruiting_button; @@ -2123,46 +2130,4 @@ function PlanetData(planet, system) constructor { } } - - static create_alert = function(){ - return instance_create(system.x + 16, system.y - 24, obj_star_event); - } - - static init_war_of_succession = function(){ - add_feature(eP_FEATURES.SUCCESSION_WAR); - add_problem("succession", irandom(6) + 4); - set_player_disposition(-5000); - - scr_popup("War of Succession", $"The planetary governor of {name()} has died. Several subordinates and other parties each claim to be the true heir and successor- war has erupted across the planet as a result. Heresy thrives in chaos.", "succession", ""); - var _star_alert = create_alert(); - _star_alert.image_alpha = 1; - _star_alert.image_speed = 1; - _star_alert.col = "red"; - scr_event_log("red", $"War of Succession on {name()}"); - } - - - static init_fallen_marines = function(){ - - var _eta = scr_mission_eta(system.x, system.y, 1); - - LOGGER.info($"Fallen: found star {name()} as candidate"); - - var assigned_problem = add_problem("fallen", _eta); - LOGGER.info($"assigned_problem {assigned_problem}"); - - if (!assigned_problem) { - LOGGER.error("RE: Hunt the Fallen, coulnd't assign a problem to the planet"); - return; - } - - var _text = $"Sources indicate one of the Fallen may be upon {name()}. We have {_eta} months to send out a strike team and scour the planet. Any longer and any Fallen that might be there will have escaped."; - scr_popup("Hunt the Fallen", _text, "fallen", ""); - scr_event_log("", $"Sources indicate one of the Fallen may be upon {name()}. We have {_eta} months to investigate."); - var star_alert = create_alert(); - star_alert.image_alpha = 1; - star_alert.image_speed = 1; - star_alert.col = "purple"; - } - } \ No newline at end of file From 7dc1187863f067c53faeae47af545c26d788066d Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 21 Jun 2026 13:58:28 +0300 Subject: [PATCH 017/140] Added diplomacy with Sector Governor on behalf of guardsmen, fixed some 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. --- objects/obj_star_select/Create_0.gml | 23 --------------- scripts/scr_PlanetData/scr_PlanetData.gml | 6 ---- scripts/scr_trade/scr_trade.gml | 35 +++++++++++++++++++++++ scripts/scr_trade_dep/scr_trade_dep.gml | 11 ++++++- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/objects/obj_star_select/Create_0.gml b/objects/obj_star_select/Create_0.gml index df87d667a0..a9499ca01a 100644 --- a/objects/obj_star_select/Create_0.gml +++ b/objects/obj_star_select/Create_0.gml @@ -58,29 +58,6 @@ guard_recruit_button.bind_method = function() { } }; -// Levy Guardsmen: raise 100 deployable Guardsmen as actual units (not the abstract PDF -// pool). They muster on this world, stationed off-ship, so the deploy roster's Guardsmen -// filter can bring them into a battle here, or they can be embarked onto ships and taken -// on the offensive. Costs 10 requisition. Uses the batch spawn path (one sort at the end) -// so raising 100 at once stays fast. -guardsmen_levy_button = new PurchaseButton(10); -guardsmen_levy_button.update({tooltip: "Levy 100 Guardsmen from this world as deployable troops. They muster here, ready to be brought into battle or embarked onto your ships. /n Costs 10 requisition", label: "Levy Guardsmen", target: target}); -guardsmen_levy_button.bind_method = function() { - var _star = target.name; - var _planet = obj_controller.selecting_planet; - repeat (100) { - var _u = scr_add_man("Guardsman", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); - if (is_struct(_u)) { - _u.location_string = _star; - _u.planet_location = _planet; - _u.ship_location = -1; - } - } - with (obj_ini) { - scr_company_order(0); - } -}; - recruiting_button = new PurchaseButton(0); recruiting_button.update({tooltip: "Enable recruiting", label: "Recruiting", target: target}); recruiting_button.bind_method = function() { diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index f938c9b05d..d3e7cdd75a 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -1694,12 +1694,6 @@ function PlanetData(planet, system) constructor { var _guard_button = obj_star_select.guard_recruit_button; _guard_button.update({x1: xx + 35, y1: _half_way + spacing_y, allow_click: true}); _guard_button.draw(pdf >= 1000); - - // Levy Guardsmen sits one row below Recruit Guard. Enabled whenever the - // player can afford it (the PurchaseButton checks the 10 requisition). - var _levy_button = obj_star_select.guardsmen_levy_button; - _levy_button.update({x1: xx + 35, y1: _half_way + spacing_y * 2, allow_click: true}); - _levy_button.draw(true); } var _recruit_button = obj_star_select.recruiting_button; diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 76753d5db6..7d77bcda0a 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -17,6 +17,7 @@ function TradeAttempt(diplomacy) constructor { "Inferno Bolts": 5, "Sister of Battle": 40, "Sister Hospitaler": 75, + "Guardsman": 0.05, "Eldar Power Sword": 50, "Archeotech Laspistol": 150, "Ranger": 100, @@ -90,6 +91,12 @@ function TradeAttempt(diplomacy) constructor { quality: "standard", number: _opt.number, }; + // Space Marines commandeering Imperial Guard is frowned upon since the + // Heresy and the reign of Goge Vandire, so the Sector Governor's regard + // dips a little each time. The hit is small and one-off per levy. + if (_type == "Guardsman") { + alter_disposition(diplomacy_faction, -2); + } } else if (_opt.trade_type == "arti") { scr_add_artifact("random", "minor", true); } else if (_opt.trade_type == "vehic") { @@ -373,6 +380,7 @@ function TradeAttempt(diplomacy) constructor { switch (diplomacy_faction) { case 2: new_demand_buttons(0, "Requisition", "req"); + new_demand_buttons(0, "Guardsman", "merc", 5000); new_demand_buttons(0, "Recruiting Planet", "license", 1); new_demand_buttons(0, "License: Repair", "license", 1); new_demand_buttons(0, "License: Crusade", "license", 1); @@ -675,6 +683,33 @@ function TradeAttempt(diplomacy) constructor { deal_chance = (100 - penalty) - (their_worth - (my_worth * dif_penalty)); //LOGGER.debug($"{their_worth},{my_worth},{deal_chance}"); + + // Guardsmen are abundant Imperial line troops the Sector Governor hands over by the + // thousand, not a haggled rarity, so the base trade overhead does not apply to a + // pure Guard levy. They cost a flat 0.05 requisition each (50 per 1000). If the + // offered requisition covers the guardsmen demanded the Governor obliges outright, + // otherwise he declines. Only triggers when guardsmen are the sole demand, so it + // cannot be used to slip other goods through cheaply. + var _guard_num = 0; + var _other_demand = false; + for (var gi = 0; gi < array_length(demand_options); gi++) { + if (demand_options[gi].number > 0) { + if (demand_options[gi].label == "Guardsman") { + _guard_num += demand_options[gi].number; + } else { + _other_demand = true; + } + } + } + if ((_guard_num > 0) && !_other_demand) { + var _req_offered = 0; + for (var ri = 0; ri < array_length(offer_options); ri++) { + if (offer_options[ri].label == "Requisition") { + _req_offered += offer_options[ri].number; + } + } + deal_chance = _req_offered >= ceil(_guard_num * 0.05) ? 100 : 0; + } var _chance = clamp(floor((deal_chance / 20)), 0, 6); trade_likely = chance_chart[_chance]; diff --git a/scripts/scr_trade_dep/scr_trade_dep.gml b/scripts/scr_trade_dep/scr_trade_dep.gml index bd5bf465f5..f8343cd279 100644 --- a/scripts/scr_trade_dep/scr_trade_dep.gml +++ b/scripts/scr_trade_dep/scr_trade_dep.gml @@ -4,10 +4,19 @@ function scr_trade_dep() { //LOGGER.debug($"trade goods : {_goods}"); if (struct_exists(_goods, "mercenaries")) { var _mercs = struct_get_names(_goods.mercenaries); + var _spawned_any = false; for (var m = 0; m < array_length(_mercs); m++) { var _merc_type = _mercs[m]; repeat (_goods.mercenaries[$ _merc_type].number) { - scr_add_man(_merc_type, 0, "", "", 0, true, "default"); + // Skip the per-spawn company re-sort; one sort after the batch keeps a + // large levy (a thousand guardsmen) fast instead of O(n squared). + scr_add_man(_merc_type, 0, "", "", 0, true, "default", {skip_company_order: true}); + _spawned_any = true; + } + } + if (_spawned_any) { + with (obj_ini) { + scr_company_order(0); } } } From 26d1a809ec709f81eba911059e19cfd397996eb2 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 22 Jun 2026 00:58:56 +0300 Subject: [PATCH 018/140] Working Alpha of Guard mod 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. --- ChapterMaster.yyp | 2 +- datafiles/data/weapons.json | 2 +- scripts/macros/macros.gml | 6 ++++ scripts/scr_clean/scr_clean.gml | 7 ++++ scripts/scr_load_all/scr_load_all.gml | 15 +++++++++ .../scr_marine_struct/scr_marine_struct.gml | 7 ++++ scripts/scr_trade/scr_trade.gml | 31 ++++++++++++------ scripts/scr_ui_manage/scr_ui_manage.gml | 12 ++++++- .../scr_unit_quick_find_pane.gml | 32 +++++++++++++++++-- 9 files changed, 99 insertions(+), 15 deletions(-) diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index bdd1e3318e..0210c6f65a 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -604,7 +604,7 @@ "isEcma":false, "LibraryEmitters":[], "MetaData":{ - "IDEVersion":"2024.1400.5.1065", + "IDEVersion":"2026.0.0.16", }, "name":"ChapterMaster", "resources":[ diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index 2114b83c45..6bf705a23e 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1613,7 +1613,7 @@ "Lasgun": { "abbreviation": "Lasgun", "ammo": 40, - "arp": 1, + "arp": 2, "attack": { "artifact": 30, "master_crafted": 26, diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 85a567a07d..e978cea7aa 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -1,6 +1,12 @@ // Imperial Guard squad: how many guardsmen one Guard Squad unit represents. #macro GUARD_SQUAD_SIZE 10 +// Imperial Guard cover save: fraction of would-be ground-combat casualties treated as +// missed, standing in for spacing, terrain use and a low profile that the combat model +// does not simulate. Applied after armour, so it also blunts armour-piercing weapons +// (choppaz, power klawz) that ignore Flak entirely. 0 = no save, 0.4 = 40% fewer losses. +#macro GUARD_COVER_SAVE 0.4 + #macro MAX_STC_PER_SUBCATEGORY 6 #macro DEFAULT_TOOLTIP_VIEW_OFFSET 32 #macro DEFAULT_LINE_GAP -1 diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index 5996d5e392..033ccdefcc 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -237,6 +237,13 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index) { if (_g_total < 0) { _g_total = 0; } + // Cover / dispersion save (see GUARD_COVER_SAVE in macros.gml). A flat fraction + // of would-be casualties are treated as missed, standing in for spacing, terrain + // and a small profile. Applied after armour so it also blunts armour-piercing + // weapons (choppaz, power klawz) that ignore Flak entirely. + if (_g_total > 0 && GUARD_COVER_SAVE > 0) { + _g_total = floor(_g_total * (1 - GUARD_COVER_SAVE)); + } _damage_data.hits += _shots; // Always name the block, even on a zero-casualty hit, or the enemy attack // flavor prints "fire at ." with a blank target whenever armour soaks the shot. diff --git a/scripts/scr_load_all/scr_load_all.gml b/scripts/scr_load_all/scr_load_all.gml index 85f0fed57d..124c41efb9 100644 --- a/scripts/scr_load_all/scr_load_all.gml +++ b/scripts/scr_load_all/scr_load_all.gml @@ -4,6 +4,21 @@ function scr_load_all(select_units) { // Load / Select All if (select_units) { man_size = 0; + // If no location is anchored yet, anchor it to the first selectable unit so a + // straight Select All works even when nothing was individually clicked first + // (e.g. a body of guardsmen mustered on a planet). The vehicle branch below + // already self-anchors; this gives the man branch the same behaviour. + if (selecting_location == "") { + for (var j = 0; j < array_length(display_unit); j++) { + var anchor_unit = display_unit[j]; + if (is_struct(anchor_unit) && (man[j] == "man") && (ma_god[j] < 10) && (anchor_unit.assignment() == "none")) { + selecting_location = ma_loc[j]; + selecting_planet = ma_wid[j]; + selecting_ship = ma_lid[j]; + break; + } + } + } // This sets the maximum size of marines in a company to 200 size for (var i = 0; i < array_length(display_unit); i++) { unit = display_unit[i]; diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index 97b2f65824..35362a997d 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -361,6 +361,13 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} var arm = armour(); var sz = 0; sz = 1; + // Guardsmen are line infantry, racked aboard far denser than power-armoured + // Astartes, so a single trooper takes only a tenth of a marine's berth. A Guard + // Squad is left at a full slot, since one already stands in for a whole squad. + if (unit_role == "Guardsman") { + size = 0.1; + return size; + } if (string_count("Dread", arm) > 0) { sz += 5; } else if (array_contains(global.list_terminator_armour, arm)) { diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 7d77bcda0a..93257c9775 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -84,18 +84,29 @@ function TradeAttempt(diplomacy) constructor { } else if (_opt.trade_type == "req") { obj_controller.requisition += _opt.number; } else if (_opt.trade_type == "merc") { - if (!struct_exists(trading_object, "mercenaries")) { - trading_object.mercenaries = {}; - } - trading_object.mercenaries[$ _type] = { - quality: "standard", - number: _opt.number, - }; - // Space Marines commandeering Imperial Guard is frowned upon since the - // Heresy and the reign of Goge Vandire, so the Sector Governor's regard - // dips a little each time. The hit is small and one-off per levy. if (_type == "Guardsman") { + // Guardsmen are not shipped in like off-world mercenaries. At the + // Governor's word a regiment is raised on the spot from the homeworld's + // own PDF, so they muster immediately on your home world rather than + // travelling by trade convoy. Spawned off-ship via the home_planet path, + // batched with a single company sort so a thousand stays fast. + repeat (_opt.number) { + scr_add_man("Guardsman", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); + } + with (obj_ini) { + scr_company_order(0); + } + // Commandeering Imperial Guard is frowned upon since the Heresy and the + // reign of Goge Vandire, so the Sector Governor's regard dips a little. alter_disposition(diplomacy_faction, -2); + } else { + if (!struct_exists(trading_object, "mercenaries")) { + trading_object.mercenaries = {}; + } + trading_object.mercenaries[$ _type] = { + quality: "standard", + number: _opt.number, + }; } } else if (_opt.trade_type == "arti") { scr_add_artifact("random", "minor", true); diff --git a/scripts/scr_ui_manage/scr_ui_manage.gml b/scripts/scr_ui_manage/scr_ui_manage.gml index 0502eb063a..bd0aa97271 100644 --- a/scripts/scr_ui_manage/scr_ui_manage.gml +++ b/scripts/scr_ui_manage/scr_ui_manage.gml @@ -808,7 +808,17 @@ function scr_ui_manage() { squad_sel = -1; squad_sel_action = -1; } - if (man_size < 1) { + // Only clear the selection when nothing is actually picked. The old check reset + // on any total below 1.0, which wiped fractional-size selections (guardsmen at + // 0.1) before they could reach a full marine's worth of space. + var _has_selection = false; + for (var _ms = 0; _ms < array_length(man_sel); _ms++) { + if (man_sel[_ms] == 1) { + _has_selection = true; + break; + } + } + if (man_size < 1 && !_has_selection) { reset_manage_selections(); } var unit; diff --git a/scripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gml b/scripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gml index b52049e53a..329349f63e 100644 --- a/scripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gml +++ b/scripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gml @@ -684,9 +684,37 @@ function jail_selection() { alarm[6] = 7; } +/// @self Asset.GMObject.obj_controller +// Returns true if at least one unit is actually selected. Used so loading works for +// fractional-size units (guardsmen at 0.1) whose summed total can read as 0 even +// though units are picked. The real per-unit loader checks each unit's own size. +function selection_has_units() { + if (man_size > 0) { + return true; + } + for (var i = 0; i < array_length(man_sel); i++) { + if (man_sel[i] == 1) { + return true; + } + } + return false; +} + /// @self Asset.GMObject.obj_controller function load_selection() { - if (man_size > 0 && !location_out_of_player_control(selecting_location)) { + // Recover the location anchor from the actual selection if it was lost. This keeps + // Load working for fractional-size units whose summed total can read 0. + if (selecting_location == "") { + for (var i = 0; i < array_length(man_sel); i++) { + if (man_sel[i] == 1) { + selecting_location = ma_loc[i]; + selecting_planet = ma_wid[i]; + selecting_ship = ma_lid[i]; + break; + } + } + } + if (selection_has_units() && !location_out_of_player_control(selecting_location)) { scr_company_load(selecting_location); menu = 30; top = 1; @@ -695,7 +723,7 @@ function load_selection() { /// @self Asset.GMObject.obj_controller function unload_selection() { - if (man_size > 0 && obj_controller.selecting_ship >= 0 && !instance_exists(obj_star_select) && !location_out_of_player_control(selecting_location) && selecting_location != "Warp") { + if (selection_has_units() && obj_controller.selecting_ship >= 0 && !instance_exists(obj_star_select) && !location_out_of_player_control(selecting_location) && selecting_location != "Warp") { cooldown = 8000; var boba = 0; var unload_star = find_star_by_name(selecting_location); From 9461b7ed08578d482183e916e8e6ee22386dcfd0 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 22 Jun 2026 05:35:31 +0300 Subject: [PATCH 019/140] Fixed guardsmen doing no damage (woops) 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 --- datafiles/data/unit_stats.json | 4 ++-- datafiles/data/weapons.json | 25 +++++++++++++++++++--- scripts/scr_flavor2/scr_flavor2.gml | 7 ++++-- scripts/scr_trade/scr_trade.gml | 33 ++++++++++------------------- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/datafiles/data/unit_stats.json b/datafiles/data/unit_stats.json index 249045efb9..ad25d8e73a 100644 --- a/datafiles/data/unit_stats.json +++ b/datafiles/data/unit_stats.json @@ -615,7 +615,7 @@ "gear": "", "mobi": "", "wep1": "Lasgun", - "wep2": "" + "wep2": "Bayonet" }, "strength": [ 20, @@ -669,7 +669,7 @@ "gear": "", "mobi": "", "wep1": "Lasgun", - "wep2": "" + "wep2": "Bayonet" }, "strength": [ 20, diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index 6bf705a23e..b318ea4233 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -352,6 +352,25 @@ ], "value": 45 }, + "Bayonet": { + "abbreviation": "Bynt", + "ammo": 0, + "arp": 1, + "attack": { + "artifact": 22, + "master_crafted": 20, + "standard": 18 + }, + "description": "A short blade clamped to the muzzle of a lasgun. It gives a Guardsman something to thrust with when the foe closes, but against anything tougher than a grot it is little more than a desperate inconvenience.", + "melee_hands": 0, + "range": 1, + "ranged_hands": 0, + "spli": 0, + "tags": [ + "knife" + ], + "value": 1 + }, "Combat Knife": { "abbreviation": "CbKnf", "ammo": 0, @@ -1615,9 +1634,9 @@ "ammo": 40, "arp": 2, "attack": { - "artifact": 30, - "master_crafted": 26, - "standard": 22 + "artifact": 130, + "master_crafted": 110, + "standard": 90 }, "description": "The standard-issue weapon of the Astra Militarum. A rugged two-handed las weapon firing coherent energy beams, prized for its reliability and the ease of recharging its power packs in the field. Common, dependable, and unremarkable on its own.", "melee_hands": 0, diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index 5a84f0d153..52375f9c9d 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -439,8 +439,11 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo special = is_specialist(unit_role, SPECIALISTS_HEADS) || unit_role == obj_ini.role[100][eROLE.CHAPTERMASTER] || unit_role == "Venerable " + string(obj_ini.role[100][eROLE.DREADNOUGHT]) || unit_role == obj_ini.role[100][eROLE.CAPTAIN] || obj_ncombat.player_max <= 6; if (!special) { - plural = units_lost > 1 ? "s" : ""; - m2 += $"{units_lost} {unit_role}{plural}, "; + var _plural_name = unit_role; + if (units_lost > 1) { + _plural_name = (unit_role == "Guardsman") ? "Guardsmen" : (unit_role + "s"); + } + m2 += $"{units_lost} {_plural_name}, "; } else { him = -1; // Find which unit this is for (var marine = 0; marine < marine_length; marine++) { diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 93257c9775..5b730f97a2 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -84,29 +84,18 @@ function TradeAttempt(diplomacy) constructor { } else if (_opt.trade_type == "req") { obj_controller.requisition += _opt.number; } else if (_opt.trade_type == "merc") { + if (!struct_exists(trading_object, "mercenaries")) { + trading_object.mercenaries = {}; + } + trading_object.mercenaries[$ _type] = { + quality: "standard", + number: _opt.number, + }; + // Space Marines commandeering Imperial Guard is frowned upon since the + // Heresy and the reign of Goge Vandire, so the Sector Governor's regard + // dips a little each time. The hit is small and one-off per levy. if (_type == "Guardsman") { - // Guardsmen are not shipped in like off-world mercenaries. At the - // Governor's word a regiment is raised on the spot from the homeworld's - // own PDF, so they muster immediately on your home world rather than - // travelling by trade convoy. Spawned off-ship via the home_planet path, - // batched with a single company sort so a thousand stays fast. - repeat (_opt.number) { - scr_add_man("Guardsman", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); - } - with (obj_ini) { - scr_company_order(0); - } - // Commandeering Imperial Guard is frowned upon since the Heresy and the - // reign of Goge Vandire, so the Sector Governor's regard dips a little. alter_disposition(diplomacy_faction, -2); - } else { - if (!struct_exists(trading_object, "mercenaries")) { - trading_object.mercenaries = {}; - } - trading_object.mercenaries[$ _type] = { - quality: "standard", - number: _opt.number, - }; } } else if (_opt.trade_type == "arti") { scr_add_artifact("random", "minor", true); @@ -391,7 +380,7 @@ function TradeAttempt(diplomacy) constructor { switch (diplomacy_faction) { case 2: new_demand_buttons(0, "Requisition", "req"); - new_demand_buttons(0, "Guardsman", "merc", 5000); + new_demand_buttons(0, "Guardsman", "merc", 2000); new_demand_buttons(0, "Recruiting Planet", "license", 1); new_demand_buttons(0, "License: Repair", "license", 1); new_demand_buttons(0, "License: Crusade", "license", 1); From 956c5de489cd8f611295d5b82b0333bc4e0fb1b6 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 22 Jun 2026 05:47:19 +0300 Subject: [PATCH 020/140] Fixed the issue of your guardsmen not arriving via trade Now they should arrive lol the last patch biffed it --- scripts/scr_trade/scr_trade.gml | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 5b730f97a2..3372fde267 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -84,18 +84,30 @@ function TradeAttempt(diplomacy) constructor { } else if (_opt.trade_type == "req") { obj_controller.requisition += _opt.number; } else if (_opt.trade_type == "merc") { - if (!struct_exists(trading_object, "mercenaries")) { - trading_object.mercenaries = {}; - } - trading_object.mercenaries[$ _type] = { - quality: "standard", - number: _opt.number, - }; - // Space Marines commandeering Imperial Guard is frowned upon since the - // Heresy and the reign of Goge Vandire, so the Sector Governor's regard - // dips a little each time. The hit is small and one-off per levy. if (_type == "Guardsman") { + // The Sector Governor raises the regiment straight from his homeworld + // PDF, so they muster at the chapter's home planet at once with no + // convoy. An earlier patch dropped this and routed them onto the + // convoy stash instead, so they never arrived; this restores it. + repeat (_opt.number) { + scr_add_man("Guardsman", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); + } + with (obj_ini) { + scr_company_order(0); + } + // Space Marines commandeering Imperial Guard is frowned upon since the + // Heresy and the reign of Goge Vandire, so the Sector Governor's regard + // dips a little each time. The hit is small and one-off per levy. alter_disposition(diplomacy_faction, -2); + } else { + // Every other mercenary type arrives by trade convoy. + if (!struct_exists(trading_object, "mercenaries")) { + trading_object.mercenaries = {}; + } + trading_object.mercenaries[$ _type] = { + quality: "standard", + number: _opt.number, + }; } } else if (_opt.trade_type == "arti") { scr_add_artifact("random", "minor", true); From f8957ddb0e99409a1a0630b67c0542a2d2ab9ade Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 22 Jun 2026 10:49:23 +0300 Subject: [PATCH 021/140] Marked code as Obsolete, fixed guard splash damage, edited cover system 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. --- objects/obj_pnunit/Create_0.gml | 2 +- scripts/macros/macros.gml | 4 ++ scripts/scr_clean/scr_clean.gml | 44 +++++++++++++++++-- .../scr_player_combat_weapon_stacks.gml | 9 ++++ 4 files changed, 55 insertions(+), 4 deletions(-) diff --git a/objects/obj_pnunit/Create_0.gml b/objects/obj_pnunit/Create_0.gml index 92ad072a18..35b3bb9ace 100644 --- a/objects/obj_pnunit/Create_0.gml +++ b/objects/obj_pnunit/Create_0.gml @@ -9,7 +9,7 @@ attacked_dudes = 0; dreads = 0; jetpack_destroy = 0; defenses = 0; -guard = 0; +guard = 0; // OBSOLETE (iteration 1): flag for the dead planetary Guard men-block. Never set to 1 anywhere, so the guard==1 branches in scr_clean and scr_player_combat_weapon_stacks are dead. Live guardsmen are role "Guardsman" unit_struct units. unit_count = 0; unit_count_old = 0; diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index e978cea7aa..3e19426cfd 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -1,4 +1,8 @@ // Imperial Guard squad: how many guardsmen one Guard Squad unit represents. +// RESERVED (iteration 2): the Guard Squad system (this macro, the guard_squad template, +// scr_add_man, scr_marine_struct max_health(), scr_cheatcode, scr_roster, and the combat +// hook in scr_player_combat_weapon_stacks) is not used in normal play. Kept for planned +// reuse as heavy weapons teams. Do not delete. #macro GUARD_SQUAD_SIZE 10 // Imperial Guard cover save: fraction of would-be ground-combat casualties treated as diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index 033ccdefcc..c890d16111 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -151,7 +151,7 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam // ### Marine + Dreadnought Processing ### if (target_is_infantry && (men + dreads > 0)) { - damage_infantry(damage_data, hostile_shots, hostile_damage, weapon_index_position); + damage_infantry(damage_data, hostile_shots, hostile_damage, weapon_index_position, hostile_splash); } if (damage_data.hits < hostile_shots) { @@ -162,7 +162,7 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam // ### Marine + Dreadnought Processing ### if (!target_is_infantry && (men + dreads > 0)) { - damage_infantry(damage_data, hostile_shots, hostile_damage, weapon_index_position); + damage_infantry(damage_data, hostile_shots, hostile_damage, weapon_index_position, hostile_splash); } } @@ -181,7 +181,7 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam } /// @self Asset.GMObject.obj_pnunit -function damage_infantry(_damage_data, _shots, _damage, _weapon_index) { +function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash) { var _armour_pierce = apa[_weapon_index]; var _armour_mod = 0; switch (_armour_pierce) { @@ -214,6 +214,10 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index) { // Bulk man-block with no individual model structs (Guard auxilia): take losses // straight off the men count, the way the enemy's ranks do, since there are no // marine structs for the normal path to kill. Scoped to guard blocks only. + // ===== OBSOLETE: planetary Guard (iteration 1) ===== + // Casualty math for the dead first-iteration men-block. The `guard` flag is never set + // to 1, so this never runs, and the cover-save inside it never applies. Live guardsmen + // take casualties through the normal marine path below. Left for reference only. if (guard == 1 && array_length(valid_marines) == 0 && men > 0) { // Identical to the enemy Guardsman casualty math in scr_shoot. Reduce each // shot by armour, pool the survivable damage across all shots, convert it to @@ -332,6 +336,7 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index) { var chunk = max(10, 62 - (marine_ac[marine_index] * 2)); _modified_damage = (webr <= chunk) ? 5000 : 0; } */ + var _hp_before = marine.hp(); marine.add_or_sub_health(-_modified_damage); // Check if marine is dead @@ -339,6 +344,39 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index) { // Remove dead infantry from further hits valid_marines = array_delete_value(valid_marines, marine_index); _damage_data.units_lost++; + + // ===== Splash carry-over ===== + // Port of the enemy men-block math in scr_shoot onto the player's individual + // units. A blast weapon's lethal overkill spills onto adjacent units, capped at + // the weapon's splash, and every further kill is gated by that unit's own armour + // and HP. Low-HP ranks (guardsmen) get torn apart by a Kannon or Rokkit; Marines + // and bosses soak the leftover through armour and HP, so it cannot wipe them, and + // ordinary attrition does not rise because only overkill carries. + if (_splash > 1) { + var _carry = _modified_damage - _hp_before; // damage left after this kill + var _spread_left = _splash - 1; + while (_spread_left > 0 && _carry > 0 && array_length(valid_marines) > 0) { + var _next_index = array_random_element(valid_marines); + var _next = unit_struct[_next_index]; + var _next_net = _carry - (marine_ac[_next_index] * _armour_mod); + if (_next_net > 0) { + _next_net = round(_next_net * (1 - (_next.damage_resistance() / 100))); + } + if (_next_net <= 0) { + break; // armour soaked the leftover; the blast is spent + } + var _next_hp_before = _next.hp(); + _next.add_or_sub_health(-_next_net); + if (check_dead_marines(_next, _next_index)) { + valid_marines = array_delete_value(valid_marines, _next_index); + _damage_data.units_lost++; + _carry = _next_net - _next_hp_before; // remaining overkill rolls on + } else { + break; // wounded but alive; the blast is spent on this body + } + _spread_left--; + } + } } } diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index d8122c652a..25c8b45ba4 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -160,6 +160,11 @@ function scr_player_combat_weapon_stacks() { exit; } + // ===== OBSOLETE: planetary Guard (iteration 1) ===== + // First-iteration "planetary Guard" men-block (PDF / Imperial Navy). The obj_pnunit + // `guard` flag is never set to 1 anywhere in the project, so this branch is dead and + // never runs. Left for reference only. The live guardsmen are individual unit_struct + // units with role "Guardsman" and fire through the normal weapon path below, not here. if (guard == 1) { var _gi = 0; var _pg = men; // current Guardsmen in this block @@ -342,6 +347,10 @@ function scr_player_combat_weapon_stacks() { } if (marine_casting[g] == false) { var weapon_stack_index = 0; + // ===== RESERVED: Guard Squad (iteration 2) ===== + // Single pooled-HP squad entity (role "Guard Squad"). Not deployed in + // normal play; the live guardsmen are individuals. Kept deliberately for + // planned reuse as heavy weapons teams. Do not delete. if (unit.role() == "Guard Squad") { // The squad thins as it takes losses: its surviving strength scales with // remaining health, so a half-health squad fires half its lasguns and a From f7660a7bc7e6e01a830508c5b3d2c61e9b6bf538 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 22 Jun 2026 11:26:47 +0300 Subject: [PATCH 022/140] Added base guardsman portrait 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. --- datafiles/images/units/guardsman.png | Bin 0 -> 45359 bytes .../scr_draw_unit_image/scr_draw_unit_image.gml | 15 +++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 datafiles/images/units/guardsman.png diff --git a/datafiles/images/units/guardsman.png b/datafiles/images/units/guardsman.png new file mode 100644 index 0000000000000000000000000000000000000000..59ac96dbf596e122721186072d091c24b5e4b98f GIT binary patch literal 45359 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 }dCJ83Q}m`sXh1xoT#1B|hj(KQ@<_2l9`f1~$Pm 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 f{Qp1j Date: Mon, 22 Jun 2026 16:12:07 +0300 Subject: [PATCH 023/140] Fixed issue where the Guard fired weaponry all at once Tried mirroring the stack spawning of Orks and such (they are represented in the 1000's, but spawn 40 per stack) just so they don't fire all of their wepaons instantly and simulate the complex battlefield not being a napoleonic line battle. --- ChapterMaster.yyp | 1 + scripts/macros/macros.gml | 10 ++++++++++ scripts/scr_roster/scr_roster.gml | 14 ++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index 0210c6f65a..a835960638 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -522,6 +522,7 @@ {"$GMIncludedFile":"","%Name":"purge8.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"purge8.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"raid1.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"raid1.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"resources.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"resources.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, + {"$GMIncludedFile":"","%Name":"guardsman1.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"guardsman1.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_advantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_advantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_disadvantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_disadvantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"pauldron.png","CopyToMask":-1,"filePath":"datafiles/main/chapter_symbols/darkangels","name":"pauldron.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 3e19426cfd..5e4073fb07 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -11,6 +11,16 @@ // (choppaz, power klawz) that ignore Flak entirely. 0 = no save, 0.4 = 40% fewer losses. #macro GUARD_COVER_SAVE 0.4 +// Imperial Guard auxilia screen: the front-most battle columns guardsmen are dealt across. +// Ten obj_pnunit columns exist (1 back to 10 front, higher column = nearer the enemy); the +// Marine and vehicle roles only use columns 1-7, so 8-10 are free front-most positions. +// Guardsmen are spread across these as separate positional blocks so the screen sits ahead of +// the Marines and engages the enemy in waves, instead of merging the whole regiment into one +// lasgun volley in the hire column. FIRST is the rear-most screen column, COUNT how many +// front columns the screen occupies (FIRST + COUNT - 1 must stay within the 10 columns). +#macro GUARD_SCREEN_COLUMN_FIRST 8 +#macro GUARD_SCREEN_COLUMN_COUNT 3 + #macro MAX_STC_PER_SUBCATEGORY 6 #macro DEFAULT_TOOLTIP_VIEW_OFFSET 32 #macro DEFAULT_LINE_GAP -1 diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 0dc05d9132..46160f6204 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -723,6 +723,20 @@ function add_unit_to_battle(unit, meeting, is_local) { col = max(obj_controller.bat_assault_column, obj_controller.bat_command_column, obj_controller.bat_honor_column, obj_controller.bat_dreadnought_column, obj_controller.bat_veteran_column); } + // ===== Individual Guardsmen (iteration 3): positional screen ===== + // Deal guardsmen across the free front-most columns as separate positional blocks. Each + // column is its own obj_pnunit with its own distance and engagement, so the screen fires in + // waves and meets melee a block at a time ahead of the Marines, instead of merging the whole + // regiment into one lasgun volley in the hire column. Round-robin keeps the blocks even. + if (_unit_role == "Guardsman") { + if (variable_instance_exists(new_combat, "guard_screen_rotation")) { + new_combat.guard_screen_rotation += 1; + } else { + new_combat.guard_screen_rotation = 0; + } + col = GUARD_SCREEN_COLUMN_FIRST + (new_combat.guard_screen_rotation mod GUARD_SCREEN_COLUMN_COUNT); + } + targ = instance_nearest(col * 10, 240, obj_pnunit); with (targ) { From b1147c17c64319bc3276f6c84d5dfda485f7ff74 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 23 Jun 2026 03:22:40 +0300 Subject: [PATCH 024/140] Added Space Hulk fix, Guardsman DOOM acc mechanics and new Company screen Basically fixed guardsmen firing all of their weapons at once like in a line battle, now they only fire a 3rd of their weapons. Their balance seems a bit too strong r/n, but also right. They melt in melee but are better shots at ranged than orks. --- ChapterMaster.yyp | 2 +- objects/obj_managment_panel/Draw_64.gml | 2 +- objects/obj_ncombat/Alarm_5.gml | 17 +++- objects/obj_ncombat/Create_0.gml | 1 + scripts/macros/macros.gml | 9 ++ scripts/scr_company_view/scr_company_view.gml | 6 +- scripts/scr_management/scr_management.gml | 12 +++ .../scr_post_battle_events.gml | 85 +++++++++++++++++++ scripts/scr_roster/scr_roster.gml | 11 +++ scripts/scr_shoot/scr_shoot.gml | 9 ++ scripts/scr_special_view/scr_special_view.gml | 14 +++ scripts/scr_ui_manage/scr_ui_manage.gml | 6 ++ 12 files changed, 168 insertions(+), 6 deletions(-) diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index a835960638..a7f0909ebe 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -522,7 +522,7 @@ {"$GMIncludedFile":"","%Name":"purge8.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"purge8.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"raid1.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"raid1.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"resources.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"resources.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, - {"$GMIncludedFile":"","%Name":"guardsman1.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"guardsman1.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, + {"$GMIncludedFile":"","%Name":"guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_advantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_advantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_disadvantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_disadvantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"pauldron.png","CopyToMask":-1,"filePath":"datafiles/main/chapter_symbols/darkangels","name":"pauldron.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, diff --git a/objects/obj_managment_panel/Draw_64.gml b/objects/obj_managment_panel/Draw_64.gml index f49d172dc3..d2b9490c6e 100644 --- a/objects/obj_managment_panel/Draw_64.gml +++ b/objects/obj_managment_panel/Draw_64.gml @@ -60,7 +60,7 @@ slate_panel.inside_method = function() { } else if (title == "LIBRARIUM") { draw_sprite_ext(spr_lib_area_pad, 0, x + (panel_width / 2) - ((0.3 * 180) / 2), y - 30, 0.3, 0.3, 0, c_white, 1); } else { - sprx = x + (wid / 2) - 16; + sprx = x + (panel_width / 2) - 16; spry = y - 16; sprw = 141 * 0.23; sprh = 141 * 0.23; diff --git a/objects/obj_ncombat/Alarm_5.gml b/objects/obj_ncombat/Alarm_5.gml index 8e164ccf10..24b2f41e0b 100644 --- a/objects/obj_ncombat/Alarm_5.gml +++ b/objects/obj_ncombat/Alarm_5.gml @@ -354,8 +354,21 @@ if ((!defeat) && (battle_special == "space_hulk")) { var enemy_power = 0, loot = 0, dicey = roll_dice_chapter(1, 100, "low"); ex = 0; - if (enemy == eFACTION.ORK || enemy == eFACTION.TYRANIDS || enemy == eFACTION.HERETICS) { - enemy_power = p_data.add_forces(enemy, -1); + // Reduce the hulk garrison by one and read the strength left behind. A Chaos hulk keeps its + // strength in the traitor (p_traitors) slot, which edit_forces reaches through the HERETICS + // case, so it is reduced as HERETICS. This also lets Chaos hulks lose forces, clear, and roll + // loot at all, which they previously never could. + var _hulk_faction = enemy; + if (enemy == eFACTION.CHAOS) { + _hulk_faction = eFACTION.HERETICS; + } + if (enemy == eFACTION.ORK || enemy == eFACTION.TYRANIDS || enemy == eFACTION.HERETICS || enemy == eFACTION.CHAOS) { + enemy_power = p_data.add_forces(_hulk_faction, -1); + // Garrison wiped out: the hulk is cleared. The salvage choice is offered post-battle in + // space_hulk_explore_battle_aftermath (scr_post_battle_events). + if (enemy_power <= 0) { + hulk_cleared = 1; + } } part10 = "Space Hulk Exploration at "; diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index c96307ee20..213f7e1fd9 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -79,6 +79,7 @@ done = 0; captured_gaunt = 0; ethereal = 0; hulk_treasure = 0; +hulk_cleared = 0; four_show = 0; chaos_angry = 0; diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 5e4073fb07..c1ee78c49a 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -21,6 +21,15 @@ #macro GUARD_SCREEN_COLUMN_FIRST 8 #macro GUARD_SCREEN_COLUMN_COUNT 3 +// Imperial Guard accuracy ("doom"): mirrors the enemy's per-faction doom in scr_shoot (the +// owner == eFACTION.IMPERIUM branch, e.g. Orks 0.2, Tyranids 0.4). Massed lasgun fire from raw +// conscripts connects far less than disciplined Astartes fire, so the guard's ranged lasgun +// volleys have their effective shots scaled by this fraction before damage. The player branch +// divides damage_per_weapon by wep_num rather than the scaled count, so per-shot damage is +// untouched and the cut is linear: the volley still fires in full but only this share lands. +// 1 = no reduction (marine-grade), 0.35 = roughly a third of the lasguns connect. +#macro GUARD_DOOM 0.35 + #macro MAX_STC_PER_SUBCATEGORY 6 #macro DEFAULT_TOOLTIP_VIEW_OFFSET 32 #macro DEFAULT_LINE_GAP -1 diff --git a/scripts/scr_company_view/scr_company_view.gml b/scripts/scr_company_view/scr_company_view.gml index 273de529e9..61a6e41bda 100644 --- a/scripts/scr_company_view/scr_company_view.gml +++ b/scripts/scr_company_view/scr_company_view.gml @@ -524,13 +524,13 @@ function company_manage_actions() { } // Previous company if (point_and_click([xx + 424, yy + 80, xx + 496, yy + 128]) || (keyboard_check_pressed(ord(string("N"))) && allow_shortcuts)) { - var new_view = managing == 1 ? 15 : managing - 1; + var new_view = managing == 1 ? 16 : managing - 1; switch_view_company(new_view); } // Next company if (point_and_click([xx + 1105, yy + 80, xx + 1178, yy + 128]) || (keyboard_check_pressed(ord(string("M"))) && allow_shortcuts)) { - var new_view = managing == 15 ? 1 : managing + 1; + var new_view = managing == 16 ? 1 : managing + 1; switch_view_company(new_view); } } @@ -554,6 +554,8 @@ function ui_manage_hotkeys() { switch_view_company(14); } else if (press_exclusive(ord("Y"))) { switch_view_company(15); + } else if (press_exclusive(ord("U"))) { + switch_view_company(16); } } } diff --git a/scripts/scr_management/scr_management.gml b/scripts/scr_management/scr_management.gml index 816210c85b..fed4ba9abb 100644 --- a/scripts/scr_management/scr_management.gml +++ b/scripts/scr_management/scr_management.gml @@ -65,6 +65,18 @@ function scr_management(argument0) { pane.line = array_join(pane.line, _lib_units.create_plural_strings_array()); + pane = instance_create(1325, 180 - 48, obj_managment_panel); + pane.company = 0; + pane.manage = 16; + pane.header = 2; + pane.title = "AUXILIA"; + + var _auxilia_units = collect_role_group("all", "", false, {roles: auxilia_roles()}, true); + + var _auxilia_units = _auxilia_units.index_roles(); + + pane.line = array_join(pane.line, _auxilia_units.create_plural_strings_array()); + pane = instance_create(700, 180 - 48, obj_managment_panel); pane.company = 0; pane.manage = 11; diff --git a/scripts/scr_post_battle_events/scr_post_battle_events.gml b/scripts/scr_post_battle_events/scr_post_battle_events.gml index 323d35bb89..af2d78d688 100644 --- a/scripts/scr_post_battle_events/scr_post_battle_events.gml +++ b/scripts/scr_post_battle_events/scr_post_battle_events.gml @@ -150,4 +150,89 @@ function space_hulk_explore_battle_aftermath() { pop.text = "The fallen heretics wore several suits of Terminator Armour- a handful of them were found to be cleansible and worthy of use. " + string(termi) + " Terminator Armour has been added to the Armamentarium."; } } + + // Hulk fully cleared this battle: offer the salvage choice. The hulk is removed from the map + // by whichever option the player picks (space_hulk_strip / space_hulk_surrender). + if (!defeat && hulk_cleared) { + var _shi = 0, _loc = ""; + var _shiyp = instance_nearest(battle_object.x, battle_object.y, obj_p_fleet); + if (_shiyp.x == battle_object.x && _shiyp.y == battle_object.y) { + _shi = fleet_full_ship_array(_shiyp)[0]; + _loc = obj_ini.ship[_shi]; + } + + var pop = instance_create(0, 0, obj_popup); + pop.image = "space_hulk_done"; + pop.title = "Space Hulk Cleared"; + pop.text = "The last of the hulk's defenders are purged and the drifting wreck falls silent. It is yours to dispose of. Strip it for the Chapter, or tow it to the nearest Forge World for the Adeptus Mechanicus?"; + pop.hulk_star = battle_object; + pop.hulk_loot_ship = _shi; + pop.hulk_loot_loc = _loc; + with (pop) { + replace_options([ + { str1: "Strip it for the Chapter", choice_func: space_hulk_strip }, + { str1: "Tow it to the nearest Forge World", choice_func: space_hulk_surrender } + ]); + } + } +} + +/// @description Salvage choice: strip a cleared space hulk for the Chapter. Runs in obj_popup scope. +/// Raises Inquisitorial suspicion and angers the Mechanicus, but yields requisition and a relic +/// that carries the normal chance of chaos/daemonic taint. Removes the hulk from the map. +function space_hulk_strip() { + obj_ini.chapter_data.chapter_suspicion = clamp(obj_ini.chapter_data.chapter_suspicion + 1, -5, 5); + obj_controller.disposition[eFACTION.MECHANICUS] = clamp(obj_controller.disposition[eFACTION.MECHANICUS] - 12, 0, 100); + + var _reqi = irandom_range(20, 40) * 10; + obj_controller.requisition += _reqi; + scr_add_artifact("random", "random", 4, hulk_loot_loc, hulk_loot_ship + 500); + + if (instance_exists(hulk_star)) { + with (hulk_star) { + instance_destroy(); + } + } + if (instance_exists(obj_star_select)) { + with (obj_star_select) { + instance_destroy(); + } + } + obj_controller.sel_system_x = 0; + obj_controller.sel_system_y = 0; + + image = "space_hulk_done"; + title = "Space Hulk Stripped"; + text = $"Your Chapter strips the hulk for itself. Archeotech and a relic are hauled aboard and {_reqi} Requisition worth of materiel is salvaged. The unsanctioned claim will not go unnoticed: the Adeptus Mechanicus consider it theft from the Omnissiah, and the Inquisition's gaze lingers a little longer on your Chapter."; + reset_popup_options(); + cooldown = 20; +} + +/// @description Salvage choice: tow a cleared space hulk to the nearest Forge World. Runs in +/// obj_popup scope. The sanctioned, expected course: the Mechanicus are grateful and send a +/// token of thanks. Removes the hulk from the map. +function space_hulk_surrender() { + obj_controller.disposition[eFACTION.MECHANICUS] = clamp(obj_controller.disposition[eFACTION.MECHANICUS] + 12, 0, 100); + + var _reqi = irandom_range(5, 15) * 10; + obj_controller.requisition += _reqi; + + if (instance_exists(hulk_star)) { + with (hulk_star) { + instance_destroy(); + } + } + if (instance_exists(obj_star_select)) { + with (obj_star_select) { + instance_destroy(); + } + } + obj_controller.sel_system_x = 0; + obj_controller.sel_system_y = 0; + + image = "space_hulk_done"; + title = "Space Hulk Surrendered"; + text = $"The hulk is towed to the nearest Forge World for the Adeptus Mechanicus to pick apart at their leisure. They receive it gratefully and send a token of thanks worth {_reqi} Requisition."; + reset_popup_options(); + cooldown = 20; } diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 46160f6204..8a3fb959cf 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -827,3 +827,14 @@ function add_vehicle_to_battle(company, veh_index, is_local) { } } } + +/// @function auxilia_roles +/// @description Single source of truth for which unit roles belong to the Auxilia company +/// screen (managing 16). These are non-Astartes auxiliary mercenaries mustered into company 0 +/// alongside the Headquarters, but managed on their own screen. Add future merc roles here +/// (Ogryn, heavy weapons team, etc.) and they will automatically appear under Auxilia and be +/// excluded from the Headquarters detail view. +/// @returns {array} +function auxilia_roles() { + return ["Guardsman", "Guard Squad"]; +} diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index ad46100221..046f14c70e 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -203,6 +203,15 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat exit; } + // Guardsman accuracy: mirror the enemy's doom (the owner == eFACTION.IMPERIUM branch + // above) on the player side. Ranged, multi-shot lasgun stacks only, matching the enemy + // gating (shots_fired != 1 && not melee). Scaling shots_fired flows through total damage + // (c = shots_fired * final_hit_damage_value), the casualty cap, and the announced count, + // while damage_per_weapon stays divided by wep_num, so the cut is a clean linear share. + if ((weapon_index_position >= 0) && (shots_fired > 1) && (melee_or_ranged != "melee") && (wep[weapon_index_position] == "Lasgun")) { + shots_fired = max(1, floor(shots_fired * GUARD_DOOM)); + } + /*if (weapon_index_position<-40){ if (weapon_index_position=-53){ if (player_silos>30) then shots_fired=30; diff --git a/scripts/scr_special_view/scr_special_view.gml b/scripts/scr_special_view/scr_special_view.gml index e597e6387b..08ff2b466e 100644 --- a/scripts/scr_special_view/scr_special_view.gml +++ b/scripts/scr_special_view/scr_special_view.gml @@ -72,6 +72,18 @@ function scr_special_view(command_group) { } } + if ((command_group == 16) || (command_group == 0)) { + // Auxilia (Guardsmen and other auxiliary mercs). Gathered by role, not specialist + // group, since they are mustered into company 0 with race IMPERIUM but are not Astartes + // specialists. auxilia_roles() is the single source of truth shared with the HQ exclusion. + var auxilia = collect_role_group("all", "", false, {roles: auxilia_roles()}); + for (var i = 0; i < array_length(auxilia); i++) { + unit = auxilia[i]; + array_push(_already_used, unit.marine_number); + add_man_to_manage_arrays(auxilia[i]); + } + } + if ((command_group == 11) || (command_group == 0)) { //HQ units for (var v = 0; v < array_length(obj_ini.TTRPG[0]); v++) { @@ -88,6 +100,8 @@ function scr_special_view(command_group) { } yep = !(_unit.IsSpecialist(SPECIALISTS_TECHS) || _unit.IsSpecialist(SPECIALISTS_CHAPLAINS) || _unit.IsSpecialist(SPECIALISTS_LIBRARIANS) || _unit.IsSpecialist(SPECIALISTS_APOTHECARIES)); + // Auxilia mercs live in company 0 but belong to the Auxilia screen, not Headquarters. + yep = yep && !array_contains(auxilia_roles(), _unit.role()); if (yep) { add_man_to_manage_arrays(_unit); } diff --git a/scripts/scr_ui_manage/scr_ui_manage.gml b/scripts/scr_ui_manage/scr_ui_manage.gml index bd0aa97271..ec9c778e5d 100644 --- a/scripts/scr_ui_manage/scr_ui_manage.gml +++ b/scripts/scr_ui_manage/scr_ui_manage.gml @@ -488,6 +488,9 @@ function company_specific_management() { case 15: _company_name = "Armamentarium"; break; + case 16: + _company_name = "Auxilia"; + break; } } // Draw the company followed by chapters name @@ -1221,6 +1224,9 @@ function scr_ui_manage() { case 15: fx = "Armamentarium"; break; + case 16: + fx = "Auxilia"; + break; default: fx = "Unknown"; break; From 866e4eab93c3b5bba1183595b6f11273b129e91c Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 23 Jun 2026 05:01:10 +0300 Subject: [PATCH 025/140] Reduced the damage to the Lasguns to match that of the Elite Cultists From 90 dmg and 2 pen to 60 damage and 1 pen. --- datafiles/data/weapons.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index b318ea4233..27c29261a5 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1632,11 +1632,11 @@ "Lasgun": { "abbreviation": "Lasgun", "ammo": 40, - "arp": 2, + "arp": 1, "attack": { "artifact": 130, "master_crafted": 110, - "standard": 90 + "standard": 60 }, "description": "The standard-issue weapon of the Astra Militarum. A rugged two-handed las weapon firing coherent energy beams, prized for its reliability and the ease of recharging its power packs in the field. Common, dependable, and unremarkable on its own.", "melee_hands": 0, From 6a81d2f6eb39c2db0a0ae996a26b10a6e4fa1ffd Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 23 Jun 2026 23:46:21 +0300 Subject: [PATCH 026/140] Added loads of fixes. New combat log mechanics based on health damage, the guardsmen can now be placed anywhere in formation so much new stuff im too lazy to comment just check the game out and see if there are any bugs in combat --- datafiles/data/weapons.json | 2 +- objects/obj_drop_select/Create_0.gml | 9 ++ objects/obj_ini/Create_0.gml | 24 +++-- objects/obj_ncombat/Alarm_3.gml | 3 + scripts/macros/macros.gml | 6 +- scripts/scr_clean/scr_clean.gml | 12 ++- .../scr_drop_select_function.gml | 31 +++++-- scripts/scr_flavor/scr_flavor.gml | 87 +++++++++++++++---- scripts/scr_flavor2/scr_flavor2.gml | 60 ++++++++++--- scripts/scr_roster/scr_roster.gml | 18 ++-- scripts/scr_shoot/scr_shoot.gml | 2 +- 11 files changed, 195 insertions(+), 59 deletions(-) diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index 27c29261a5..0145511e6e 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1636,7 +1636,7 @@ "attack": { "artifact": 130, "master_crafted": 110, - "standard": 60 + "standard": 70 }, "description": "The standard-issue weapon of the Astra Militarum. A rugged two-handed las weapon firing coherent energy beams, prized for its reliability and the ease of recharging its power packs in the field. Common, dependable, and unremarkable on its own.", "melee_hands": 0, diff --git a/objects/obj_drop_select/Create_0.gml b/objects/obj_drop_select/Create_0.gml index f583a58a9d..f0d6bf76b9 100644 --- a/objects/obj_drop_select/Create_0.gml +++ b/objects/obj_drop_select/Create_0.gml @@ -134,6 +134,15 @@ if (!instance_exists(obj_saveload)) { if (formation_current == -1) { formation_current = 0; } + // Hardening: a stored last_raid_form / last_attack_form that is not among the formations + // valid for this drop type, or a value left over across a save/load, would otherwise leave + // formation_current as an out-of-range raw value. Clamp it so the selector can never index + // past the array, and pin it to 0 when there are no formations to choose from. + if (array_length(formation_possible) > 0) { + formation_current = clamp(formation_current, 0, array_length(formation_possible) - 1); + } else { + formation_current = 0; + } fighting = array_create(11, array_create(501)); veh_fighting = array_create(11, array_create(501)); diff --git a/objects/obj_ini/Create_0.gml b/objects/obj_ini/Create_0.gml index f9dd1f50a4..f66a3ef83e 100644 --- a/objects/obj_ini/Create_0.gml +++ b/objects/obj_ini/Create_0.gml @@ -198,13 +198,16 @@ serialize = function() { var _marines = array_create(0); for (var _coy = 0; _coy <= 10; _coy++) { - for (var _mar = 0; _mar <= 500; _mar++) { - var _marine_json; + // Iterate the company's full restored length, not a fixed 0..500, so guardsmen in overflow + // slots past 500 (HQ grows uncapped once it fills) are serialized too. The old early-break + // on consecutive empty slots is dropped because guardsmen can leave gaps, and the break + // would skip every unit after the first gap, which is what desynced TTRPG from name[] on + // reload. + var _coy_len = array_length(obj_ini.name[_coy]); + for (var _mar = 0; _mar < _coy_len; _mar++) { if (obj_ini.name[_coy][_mar] != "") { - _marine_json = jsonify_marine_struct(_coy, _mar, false); + var _marine_json = jsonify_marine_struct(_coy, _mar, false); array_push(_marines, _marine_json); - } else if (_mar > 0 && _mar <= 499 && obj_ini.name[_coy][_mar + 1] == "") { - break; } } } @@ -326,9 +329,16 @@ deserialize = function(save_data) { obj_ini.TTRPG[company][marine].load_json_data(struct); } - obj_ini.TTRPG = array_create(11, array_create(501, [])); + // Size each company's struct array to its restored roster length (minimum 501) so TTRPG can + // never be shorter than the flat name[] array. HQ can exceed 501 slots once guardsmen overflow + // it, and a fixed 501 here desynced from name[] after a load, sending fetch_unit out of range + // (Chapter Management crash). Building each company array separately also avoids the shared + // inner-array aliasing of the old array_create(11, array_create(501, [])) form. + obj_ini.TTRPG = array_create(11); for (var _coy = 0; _coy < 11; _coy++) { - for (var _mar = 0; _mar <= 500; _mar++) { + var _coy_len = max(501, array_length(obj_ini.name[_coy])); + obj_ini.TTRPG[_coy] = array_create(_coy_len); + for (var _mar = 0; _mar < _coy_len; _mar++) { obj_ini.TTRPG[_coy][_mar] = new TTRPG_stats("chapter", _coy, _mar, "blank"); } } diff --git a/objects/obj_ncombat/Alarm_3.gml b/objects/obj_ncombat/Alarm_3.gml index e50d0f7ac1..f6f97b5a76 100644 --- a/objects/obj_ncombat/Alarm_3.gml +++ b/objects/obj_ncombat/Alarm_3.gml @@ -116,6 +116,9 @@ if (((messages > 0) && (messages_shown < 24)) && (messages_shown <= 100)) { if (message_priority[that] == 137) { newline_color = "red"; } + if (message_priority[that] == 136) { + newline_color = "yellow"; + } scr_newtext(); messages_shown += 1; diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index c1ee78c49a..2a07cfac3f 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -27,8 +27,10 @@ // volleys have their effective shots scaled by this fraction before damage. The player branch // divides damage_per_weapon by wep_num rather than the scaled count, so per-shot damage is // untouched and the cut is linear: the volley still fires in full but only this share lands. -// 1 = no reduction (marine-grade), 0.35 = roughly a third of the lasguns connect. -#macro GUARD_DOOM 0.35 +// 1 = no reduction (marine-grade, also what Elite Cultists fire at), 0.35 = roughly a third of +// the lasguns connect. Kills scale about linearly with this value, so 0.7 is roughly double the +// effectiveness of 0.35 with no change to damage or penetration. +#macro GUARD_DOOM 0.7 #macro MAX_STC_PER_SUBCATEGORY 6 #macro DEFAULT_TOOLTIP_VIEW_OFFSET 32 diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index c890d16111..62cd9ad13d 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -142,6 +142,8 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam "units_lost": 0, "unit_type": "", "hits": 0, + "severity": 0, + "is_vehicle": false, }; // ### Vehicle Damage Processing ### @@ -166,7 +168,7 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam } } - scr_flavor2(damage_data.units_lost, damage_data.unit_type, hostile_range, hostile_weapon, damage_data.hits, hostile_splash); + scr_flavor2(damage_data.units_lost, damage_data.unit_type, hostile_range, hostile_weapon, damage_data.hits, hostile_splash, damage_data.severity, damage_data.is_vehicle); // ### Cleanup ### // If the target_object got wiped out, move it off-screen @@ -338,6 +340,9 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash) } */ var _hp_before = marine.hp(); marine.add_or_sub_health(-_modified_damage); + if ((_hp_before > 0) && (_modified_damage > 0)) { + _damage_data.severity = max(_damage_data.severity, clamp(_modified_damage / _hp_before, 0, 1)); + } // Check if marine is dead if (check_dead_marines(marine, marine_index)) { @@ -434,8 +439,13 @@ function damage_vehicles(_damage_data, _shots, _damage, _weapon_index) { if (enemy == 13 && _modified_damage < 1) { _modified_damage = 1; } + var _veh_hp_before = veh_hp[veh_index]; veh_hp[veh_index] -= _modified_damage; _damage_data.unit_type = veh_type[veh_index]; + _damage_data.is_vehicle = true; + if (_veh_hp_before > 0) { + _damage_data.severity = max(_damage_data.severity, clamp(_modified_damage / _veh_hp_before, 0, 1)); + } // Check if the vehicle is destroyed if (veh_hp[veh_index] <= 0 && veh_dead[veh_index] == 0) { diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index 6cbc1f4b60..2f513d4e65 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -49,15 +49,24 @@ function drop_select_unit_selection() { // draw_rectangle(xx+1084,yy+215,xx+1142,yy+273,0); // Formation - var _formation_str = $"Formation: {obj_controller.bat_formation[formation_possible[formation_current]]}"; + // Hardening: never index formation_possible without checking it is non-empty and the + // index is in range. A drifted or stale formation_current (e.g. across a load) would + // otherwise crash the whole drop screen on draw. + var _formation_str = "Formation: -"; + if (array_length(formation_possible) > 0) { + formation_current = clamp(formation_current, 0, array_length(formation_possible) - 1); + _formation_str = $"Formation: {obj_controller.bat_formation[formation_possible[formation_current]]}"; + } formation.x1 = x2 - 40 - (string_width(_formation_str) + 4); formation.y1 = y1 + 80; formation.update({str1: _formation_str}); formation.draw(); if (formation.clicked()) { - formation_current++; - if (formation_current >= array_length(formation_possible)) { - formation_current = 0; + if (array_length(formation_possible) > 0) { + formation_current++; + if (formation_current >= array_length(formation_possible)) { + formation_current = 0; + } } } @@ -205,11 +214,19 @@ function drop_select_unit_selection() { if (purge == 0) { combating = 1; // Start battle here + // Hardening: resolve the chosen formation through a single bounds-checked read so a + // bad formation_current cannot crash the drop launch. Falls back to formation 0 when + // no formations are available. + var _chosen_form = 0; + if (array_length(formation_possible) > 0) { + _chosen_form = formation_possible[clamp(formation_current, 0, array_length(formation_possible) - 1)]; + } + if (attack == 1) { - obj_controller.last_attack_form = formation_possible[formation_current]; + obj_controller.last_attack_form = _chosen_form; } if (attack == 0) { - obj_controller.last_raid_form = formation_possible[formation_current]; + obj_controller.last_raid_form = _chosen_form; } instance_deactivate_all(true); @@ -234,7 +251,7 @@ function drop_select_unit_selection() { obj_ncombat.dropping = 1 - attack; obj_ncombat.attacking = attack; obj_ncombat.enemy = attacking; - obj_ncombat.formation_set = formation_possible[formation_current]; + obj_ncombat.formation_set = _chosen_form; obj_ncombat.defending = false; obj_ncombat.local_forces = roster.local_button.active; diff --git a/scripts/scr_flavor/scr_flavor.gml b/scripts/scr_flavor/scr_flavor.gml index b26bd358e5..9fdaa6b746 100644 --- a/scripts/scr_flavor/scr_flavor.gml +++ b/scripts/scr_flavor/scr_flavor.gml @@ -22,7 +22,40 @@ function display_battle_log_message() { obj_ncombat.alarm[3] = 5; } -function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shots, casulties) { +/// @function combat_damage_flavor +/// @description Returns a combat-log fragment describing a NON-LETHAL hit, scaled by how close the +/// volley came to a kill (_severity = damage dealt as a fraction of one target's current health, +/// 0 = nothing got through, approaching 1 = almost a kill). Universal across weapons: infantry get +/// wound language, vehicles get structural-damage language. The fragments slot in after a comma, +/// e.g. "334 Lasguns strike at the Ork Boy ranks, {fragment}." Edit the wording freely; the tier +/// thresholds are the only thing the rest of the code depends on. +/// @param {real} _severity 0..1, damage this hit dealt over the target's current health +/// @param {bool} _is_vehicle target is a vehicle (hull/armour language instead of wounds) +/// @param {bool} _is_single target is a single model rather than a rank of many +/// @returns {string} +function combat_damage_flavor(_severity, _is_vehicle, _is_single) { + if (_is_vehicle) { + if (_severity < 0.10) return "but the hits spend themselves against its armour"; + if (_severity < 0.35) return "scorching its plating"; + if (_severity < 0.65) return "denting its hull"; + if (_severity < 0.90) return "tearing gashes into its hull"; + return "leaving it scorched and barely running"; + } + if (_is_single) { + if (_severity < 0.10) return "but its armour turns the blows aside"; + if (_severity < 0.35) return "but it is only grazed"; + if (_severity < 0.65) return "and it is wounded"; + if (_severity < 0.90) return "and it is gravely wounded"; + return "and it is left maimed, clinging to life"; + } + if (_severity < 0.10) return "but fail to penetrate their armour"; + if (_severity < 0.35) return "drawing little more than scratches"; + if (_severity < 0.65) return "wounding several"; + if (_severity < 0.90) return "leaving deep wounds among them"; + return "leaving the survivors maimed and reeling"; +} + +function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shots, casulties, damage_done = -1) { // Generates flavor based on the damage and casualties from scr_shoot, only for the player var attack_message, kill_message, leader_message, targeh; @@ -455,25 +488,35 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot if (flavoured == false) { flavoured = true; if (!character_shot) { + // Wound/damage severity for non-lethal hits: how close this volley came to a kill, + // measured as damage dealt over the target's current health. damage_done < 0 means the + // caller did not supply it, so keep the old flat "survives / no damage" wording. + var _flav_hp = target.dudes_hp[targeh]; + var _flav_veh = (target.dudes_vehicle[targeh] == 1); + var _flav_sev = ((damage_done >= 0) && (_flav_hp > 0)) ? clamp(damage_done / _flav_hp, 0, 1) : -1; + var _flav_shots = (number_of_shots == 1) ? weapon_name : $"{number_of_shots} {weapon_name}s"; + if (target.dudes_num[targeh] == 1) { - if (number_of_shots == 1 && casulties == 0) { - attack_message = $"A {target_name} is struck by {weapon_name} but survives."; - } else if (number_of_shots == 1 && casulties == 1) { - attack_message = $"A {target_name} is struck down by {weapon_name}."; - } else if (number_of_shots > 1 && casulties == 0) { - attack_message = $"A {target_name} is struck by {number_of_shots} {weapon_name}s but survives."; - } else if (number_of_shots > 1 && casulties == 1) { - attack_message = $"A {target_name} is struck down by {number_of_shots} {weapon_name}s."; + if (casulties >= 1) { + attack_message = $"A {target_name} is struck down by {_flav_shots}."; + } else if (_flav_sev < 0) { + attack_message = $"A {target_name} is struck by {_flav_shots} but survives."; + } else { + attack_message = $"A {target_name} is struck by {_flav_shots}, {combat_damage_flavor(_flav_sev, _flav_veh, true)}."; } } else { - if (number_of_shots == 1 && casulties == 0) { - attack_message = $"{weapon_name} strikes at {target_name} but they survive."; - } else if (number_of_shots == 1 && casulties > 0) { - attack_message = $"{weapon_name} strikes at {target_name} and kills {casulties}"; - } else if (number_of_shots > 1 && casulties == 0) { - attack_message = $"{number_of_shots} {weapon_name}s strike at the {target_name} ranks, but fail to inflict damage."; - } else if (number_of_shots > 1 && casulties > 0) { - attack_message = $"{number_of_shots} {weapon_name}s strike at the {target_name} ranks, killing {casulties}."; + if (casulties > 0) { + attack_message = (number_of_shots == 1) + ? $"{weapon_name} strikes at {target_name} and kills {casulties}." + : $"{number_of_shots} {weapon_name}s strike at the {target_name} ranks, killing {casulties}."; + } else if (_flav_sev < 0) { + attack_message = (number_of_shots == 1) + ? $"{weapon_name} strikes at {target_name} but they survive." + : $"{number_of_shots} {weapon_name}s strike at the {target_name} ranks, but fail to inflict damage."; + } else if (number_of_shots == 1) { + attack_message = $"{weapon_name} strikes at {target_name}, {combat_damage_flavor(_flav_sev, _flav_veh, false)}."; + } else { + attack_message = $"{number_of_shots} {weapon_name}s strike at the {target_name} ranks, {combat_damage_flavor(_flav_sev, _flav_veh, false)}."; } } } else { @@ -545,6 +588,16 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot } } + // Yellow when this volley wounded the target but killed nothing (damage, no destroy). Skips + // the "fail to penetrate" band (under 10% of a unit's health) so a shrugged-off volley stays + // the default colour, and skips leaders so their priority colour is preserved. + if ((message_priority == 0) && (casulties == 0) && (damage_done >= 0)) { + var _yhp = target.dudes_hp[targeh]; + if ((_yhp > 0) && ((damage_done / _yhp) >= 0.10)) { + message_priority = 136; + } + } + var message_size = 0; if (defenses == 1) { message_size = 999; diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index 52375f9c9d..f148e41b8f 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -1,4 +1,28 @@ -function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapon, hostile_shots, hostile_splash) { +/// @function incoming_damage_flavor +/// @description Combat-log sentence for an enemy hit that did NOT kill, scaled by how close it came +/// to a kill (_severity = damage over the target's health before the hit, 0..1). Vehicles get +/// armour/hull language, infantry get wound language. Appended after the attack verb, e.g. +/// "24 Big Shootaz roar and blast away at Rhino. Piercing the armour." Edit the wording freely; +/// only the tier thresholds matter to the rest of the code. +/// @param {real} _severity 0..1 +/// @param {bool} _is_vehicle target is a vehicle +/// @returns {string} +function incoming_damage_flavor(_severity, _is_vehicle) { + if (_is_vehicle) { + if (_severity < 0.10) return "Only peeling the paint."; + if (_severity < 0.35) return "Barely putting a dent in the armour."; + if (_severity < 0.65) return "Piercing the armour."; + if (_severity < 0.90) return "Punching a huge hole in the armour."; + return "Almost destroying it."; + } + if (_severity < 0.10) return "But the armour holds."; + if (_severity < 0.35) return "Drawing blood."; + if (_severity < 0.65) return "Wounding several."; + if (_severity < 0.90) return "Leaving deep wounds."; + return "Leaving the survivors maimed and reeling."; +} + +function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapon, hostile_shots, hostile_splash, damage_severity = 0, target_is_vehicle = false) { // Generates flavor based on the damage and casualties from scr_shoot, only for the opponent if (obj_ncombat.wall_destroyed == 1) { @@ -35,6 +59,13 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo _hostile_shots = max(1, round(_hostile_shots / 3)); } + // Suppress empty attacks: no hits landed or no resolved target means there is nothing worth + // reporting. This is what produced lines like "0 rokkitz shoot at ." and "blasting into ." + // Walls are exempt; their own branch handles display. + if ((target_type != "wall") && ((hostile_shots <= 0) || (string(target_type) == ""))) { + exit; + } + // show_message(string(hostile_weapon)+"|"+string(_hostile_weapon)+"#"+string(los)+"#"+string(los_num)); var flavor = 0; @@ -382,17 +413,9 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo if (flavor == 0) { flavor = true; if (_hostile_shots == 1) { - if (lost_units_count == 0) { - m1 += $"{_hostile_weapon} strikes at {target_type}, no casualties."; - } else { - m1 += $"{_hostile_weapon} strikes at {target_type}. "; - } + m1 += $"{_hostile_weapon} strikes at {target_type}. "; } else { - if (lost_units_count == 0) { - m1 += $"{_hostile_shots} {_hostile_weapon}s strike at {target_type}, no casualties."; - } else { - m1 += $"{_hostile_shots} {_hostile_weapon}s strike at {target_type}. "; - } + m1 += $"{_hostile_shots} {_hostile_weapon}s strike at {target_type}. "; } } @@ -520,14 +543,27 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } } + // No kills but the attack connected: report the damage instead of a bare attack verb, scaled by + // how close it came to a kill. Severity is 0 for targets that do not track it (e.g. guardsmen), + // which lands on the lowest tier. + if ((m2 == "") && (lost_units_count == 0) && (hostile_shots > 0) && (target_type != "wall")) { + m2 = incoming_damage_flavor(damage_severity, target_is_vehicle); + } + mes = m1 + m2 + m3; // show_message(mes); if (string_length(mes) > 3) { + // Yellow when the enemy hurt your forces but destroyed nothing (damage, no kill). Kills carry + // the word "lost" and are coloured red elsewhere, so they are left at priority 0 here. + var _enemy_priority = 0; + if ((lost_units_count == 0) && (hostile_shots > 0) && (damage_severity >= 0.10)) { + _enemy_priority = 136; + } obj_ncombat.messages += 1; obj_ncombat.message[obj_ncombat.messages] = mes; obj_ncombat.message_sz[obj_ncombat.messages] = lost_units_count + (0.5 - (obj_ncombat.messages / 100)); - obj_ncombat.message_priority[obj_ncombat.messages] = 0; + obj_ncombat.message_priority[obj_ncombat.messages] = _enemy_priority; obj_ncombat.alarm[3] = 2; } } diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 8a3fb959cf..3258b990d4 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -723,18 +723,14 @@ function add_unit_to_battle(unit, meeting, is_local) { col = max(obj_controller.bat_assault_column, obj_controller.bat_command_column, obj_controller.bat_honor_column, obj_controller.bat_dreadnought_column, obj_controller.bat_veteran_column); } - // ===== Individual Guardsmen (iteration 3): positional screen ===== - // Deal guardsmen across the free front-most columns as separate positional blocks. Each - // column is its own obj_pnunit with its own distance and engagement, so the screen fires in - // waves and meets melee a block at a time ahead of the Marines, instead of merging the whole - // regiment into one lasgun volley in the hire column. Round-robin keeps the blocks even. + // ===== Guardsmen: "Hirelings" formation ===== + // Guardsmen go into the movable Hirelings block (bat_hire_column), so the player can position + // them anywhere from the formation screen as a single line. This restores the behaviour from + // before the positional-screen experiment: every guardsman shares this one column instead of + // being pinned to fixed front columns. bat_hire_column was resolved for this formation at the + // top of this function and is driven by the Hirelings bar (bat_hire_for, unit_id 12). if (_unit_role == "Guardsman") { - if (variable_instance_exists(new_combat, "guard_screen_rotation")) { - new_combat.guard_screen_rotation += 1; - } else { - new_combat.guard_screen_rotation = 0; - } - col = GUARD_SCREEN_COLUMN_FIRST + (new_combat.guard_screen_rotation mod GUARD_SCREEN_COLUMN_COUNT); + col = obj_controller.bat_hire_column; } targ = instance_nearest(col * 10, 240, obj_pnunit); diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index 046f14c70e..df0eb0141b 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -533,7 +533,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat } } } // End repeat 10 - scr_flavor(weapon_index_position, target_object, target_type, shots_fired - wep_rnum[weapon_index_position], casualties); + scr_flavor(weapon_index_position, target_object, target_type, shots_fired - wep_rnum[weapon_index_position], casualties, c); if ((target_object.dudes_num[target_type] == 1) && (c > 0)) { target_object.dudes_hp[target_type] -= c; From d9e4885495417ca6bb308af21436d5fddbe7fa40 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 24 Jun 2026 01:13:49 +0300 Subject: [PATCH 027/140] Added Guard Sarge, more flavor txt and Removed undefined targ_planet crash to combat and So, for the fix for my colleagues in main: complete_garrison_mission threw "I32 argument is unset" on end turn whenever a provide_garrison problem reached completion, crashing obj_star's Step event through scr_enemy_ai_d -> problem_end_turn_checks. Stacktrace: scr_PlanetData:refresh_data:26 PlanetData:128 complete_garrison_mission:552 problem_end_turn_checks:266 scr_enemy_ai_d:96 obj_star_Step_0:84 Cause: complete_garrison_mission is dispatched from the problem_functions table via method(self, ...) then _problem_action(i), so it runs bound to a PlanetData as self and receives only the problem index. It never receives a targ_planet, and targ_planet is not a field on PlanetData, so the line var planet = new PlanetData(targ_planet, self); read targ_planet as undefined and passed it into the PlanetData constructor. refresh_data then ran system.p_feature[undefined], which throws "I32 argument is unset". That line was copy-paste leftover from complete_train_forces_mission and complete_beast_hunt_mission, which do take targ_planet as a parameter and fetch their planet. complete_garrison_mission already has the planet through self and uses self for everything (garrisons, current_owner, name(), add_disposition, alter_fortification). The local planet it built was never read. Fix: delete the unused line. The function loses nothing and the crash branch is gone. --- datafiles/data/unit_stats.json | 54 ++++++++++++++++ scripts/scr_add_man/scr_add_man.gml | 12 +++- scripts/scr_flavor/scr_flavor.gml | 64 ++++++++++++++----- scripts/scr_flavor2/scr_flavor2.gml | 20 +++--- .../scr_mission_functions.gml | 2 - scripts/scr_roster/scr_roster.gml | 8 +-- scripts/scr_trade/scr_trade.gml | 6 ++ 7 files changed, 134 insertions(+), 32 deletions(-) diff --git a/datafiles/data/unit_stats.json b/datafiles/data/unit_stats.json index ad25d8e73a..55df74adae 100644 --- a/datafiles/data/unit_stats.json +++ b/datafiles/data/unit_stats.json @@ -689,6 +689,60 @@ 1 ] }, + "guard_sergeant": { + "ballistic_skill": [ + 15, + 1 + ], + "base_group": "human", + "charisma": [ + 25, + 1 + ], + "constitution": [ + 45, + 1, + "max" + ], + "dexterity": [ + 22, + 1 + ], + "intelligence": [ + 18, + 1 + ], + "luck": 8, + "piety": [ + 28, + 1 + ], + "religion": "imperial_cult", + "start_gear": { + "armour": "Flak Armour", + "gear": "", + "mobi": "", + "wep1": "Chainsword", + "wep2": "Laspistol" + }, + "strength": [ + 30, + 1 + ], + "technology": [ + 10, + 1 + ], + "title": "Guard Sergeant", + "weapon_skill": [ + 35, + 1 + ], + "wisdom": [ + 20, + 1 + ] + }, "skitarii": { "ballistic_skill": [ 20, diff --git a/scripts/scr_add_man/scr_add_man.gml b/scripts/scr_add_man/scr_add_man.gml index 3f68e2731d..9bc9c5e125 100644 --- a/scripts/scr_add_man/scr_add_man.gml +++ b/scripts/scr_add_man/scr_add_man.gml @@ -12,7 +12,8 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption "Ork Sniper", "Flash Git", "Guardsman", - "Guard Squad" + "Guard Squad", + "Guard Sergeant" ]; var _gear = {}; var _company_slot = 0; @@ -38,6 +39,11 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption obj_ini.race[target_company][_company_slot] = eFACTION.IMPERIUM; _unit = new TTRPG_stats("imperial_guard", target_company, _company_slot, "guard_squad"); break; + case "Guard Sergeant": + spawn_exp = 10; + obj_ini.race[target_company][_company_slot] = eFACTION.IMPERIUM; + _unit = new TTRPG_stats("imperial_guard", target_company, _company_slot, "guard_sergeant"); + break; case "Skitarii": spawn_exp = 10; obj_ini.race[target_company][_company_slot] = 3; @@ -121,6 +127,10 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption case "Guard Squad": obj_ini.name[target_company][_company_slot] = global.name_generator.GenerateFromSet("imperial_male"); break; + + case "Guard Sergeant": + obj_ini.name[target_company][_company_slot] = global.name_generator.GenerateFromSet("imperial_male"); + break; } if (!array_contains(non_marine_roles, man_role)) { diff --git a/scripts/scr_flavor/scr_flavor.gml b/scripts/scr_flavor/scr_flavor.gml index 9fdaa6b746..383000e3ae 100644 --- a/scripts/scr_flavor/scr_flavor.gml +++ b/scripts/scr_flavor/scr_flavor.gml @@ -35,24 +35,24 @@ function display_battle_log_message() { /// @returns {string} function combat_damage_flavor(_severity, _is_vehicle, _is_single) { if (_is_vehicle) { - if (_severity < 0.10) return "but the hits spend themselves against its armour"; - if (_severity < 0.35) return "scorching its plating"; - if (_severity < 0.65) return "denting its hull"; - if (_severity < 0.90) return "tearing gashes into its hull"; - return "leaving it scorched and barely running"; + if (_severity < 0.10) return choose("but the hits spend themselves against its armour", "barely chipping its paint", "pinging off its armour", "bouncing off its plating", "only scratching its armour"); + if (_severity < 0.35) return choose("scorching its plating", "scuffing its armour", "leaving shallow dents in its hull"); + if (_severity < 0.65) return choose("denting its hull", "cracking its armour", "punching into its plating"); + if (_severity < 0.90) return choose("tearing gashes into its hull", "blowing holes in its plating", "ripping through its armour"); + return choose("leaving it scorched and barely running", "all but wrecking it", "leaving it a smoking hulk"); } if (_is_single) { - if (_severity < 0.10) return "but its armour turns the blows aside"; - if (_severity < 0.35) return "but it is only grazed"; - if (_severity < 0.65) return "and it is wounded"; - if (_severity < 0.90) return "and it is gravely wounded"; - return "and it is left maimed, clinging to life"; + if (_severity < 0.10) return choose("but its armour turns the blows aside", "but it shrugs them off"); + if (_severity < 0.35) return choose("but it is only grazed", "leaving only light wounds", "drawing a little blood"); + if (_severity < 0.65) return choose("and it is wounded", "leaving it bloodied", "and it is hurt"); + if (_severity < 0.90) return choose("and it is gravely wounded", "leaving it badly hurt", "and it is left reeling"); + return choose("and it is left maimed, clinging to life", "and it barely clings to life", "leaving it all but dead"); } - if (_severity < 0.10) return "but fail to penetrate their armour"; - if (_severity < 0.35) return "drawing little more than scratches"; - if (_severity < 0.65) return "wounding several"; - if (_severity < 0.90) return "leaving deep wounds among them"; - return "leaving the survivors maimed and reeling"; + if (_severity < 0.10) return choose("but fail to penetrate their armour", "but their armour holds"); + if (_severity < 0.35) return choose("drawing little more than scratches", "causing only light wounds", "leaving a few grazes"); + if (_severity < 0.65) return choose("wounding several", "bloodying their ranks", "leaving wounded in their wake"); + if (_severity < 0.90) return choose("leaving deep wounds among them", "savaging their ranks", "leaving many badly wounded"); + return choose("leaving the survivors maimed and reeling", "all but breaking them", "leaving them maimed and scattered"); } function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shots, casulties, damage_done = -1) { @@ -565,6 +565,40 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot // obj_ncombat.dead_enemies = 0; // } + // Unified outcome phrasing, applied after the per-weapon branches above so every weapon reads + // consistently. A volley that kills nothing reports wound/damage severity rather than generic + // "no casualties" wording, and a volley that destroys vehicles says "destroy" instead of "kill" + // so mechanical targets stand out at a glance. Infantry kills keep their bespoke per-weapon + // verbs untouched. + if ((damage_done >= 0) && (attack_message != "")) { + var _pp_hp = target.dudes_hp[targeh]; + var _pp_veh = (target.dudes_vehicle[targeh] == 1); + var _pp_single = (target.dudes_num[targeh] == 1); + var _pp_shots = (number_of_shots == 1) ? weapon_name : $"{number_of_shots} {weapon_name}s"; + if (casulties == 0) { + var _pp_sev = (_pp_hp > 0) ? clamp(damage_done / _pp_hp, 0, 1) : 0; + var _pp_flav = combat_damage_flavor(_pp_sev, _pp_veh, _pp_single); + if (character_shot && (unit_name != "")) { + attack_message = _pp_single + ? $"{unit_name} {weapon_name} strikes a {target_name}, {_pp_flav}." + : $"{unit_name} {weapon_name} strikes the {target_name} ranks, {_pp_flav}."; + } else if (_pp_single) { + attack_message = $"A {target_name} is struck by {_pp_shots}, {_pp_flav}."; + } else { + attack_message = $"{_pp_shots} strike at the {target_name} ranks, {_pp_flav}."; + } + } else if (_pp_veh) { + var _pp_obj = (casulties == 1) ? $"a {target_name}" : $"{casulties} {target_name}s"; + if (character_shot && (unit_name != "")) { + attack_message = $"{unit_name} {weapon_name} destroys {_pp_obj}."; + } else if (number_of_shots == 1) { + attack_message = $"{weapon_name} destroys {_pp_obj}."; + } else { + attack_message = $"{number_of_shots} {weapon_name}s destroy {_pp_obj}."; + } + } + } + var message_priority = 0; if (obj_ncombat.enemy <= 10) { if (target_name == obj_controller.faction_leader[obj_ncombat.enemy]) { diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index f148e41b8f..098bc1b875 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -9,17 +9,17 @@ /// @returns {string} function incoming_damage_flavor(_severity, _is_vehicle) { if (_is_vehicle) { - if (_severity < 0.10) return "Only peeling the paint."; - if (_severity < 0.35) return "Barely putting a dent in the armour."; - if (_severity < 0.65) return "Piercing the armour."; - if (_severity < 0.90) return "Punching a huge hole in the armour."; - return "Almost destroying it."; + if (_severity < 0.10) return choose("Only peeling the paint.", "Just chipping the paint.", "Pinging off the armour.", "Bouncing off the hull.", "Only scratching the armour."); + if (_severity < 0.35) return choose("Barely putting a dent in the armour.", "Leaving a few dents in the hull.", "Only scuffing the armour."); + if (_severity < 0.65) return choose("Piercing the armour.", "Punching through the plating.", "Cracking the armour open."); + if (_severity < 0.90) return choose("Punching a huge hole in the armour.", "Tearing a gash through the hull.", "Blowing a hole in the plating."); + return choose("Almost destroying it.", "Leaving it a smoking wreck.", "Nearly tearing it apart."); } - if (_severity < 0.10) return "But the armour holds."; - if (_severity < 0.35) return "Drawing blood."; - if (_severity < 0.65) return "Wounding several."; - if (_severity < 0.90) return "Leaving deep wounds."; - return "Leaving the survivors maimed and reeling."; + if (_severity < 0.10) return choose("But the armour holds.", "But it is shrugged off."); + if (_severity < 0.35) return choose("Drawing blood.", "Causing light wounds.", "Leaving a few grazes."); + if (_severity < 0.65) return choose("Wounding several.", "Bloodying the ranks.", "Leaving wounded behind."); + if (_severity < 0.90) return choose("Leaving deep wounds.", "Savaging the ranks.", "Leaving many badly wounded."); + return choose("Leaving the survivors maimed and reeling.", "All but breaking them.", "Leaving them maimed and scattered."); } function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapon, hostile_shots, hostile_splash, damage_severity = 0, target_is_vehicle = false) { diff --git a/scripts/scr_mission_functions/scr_mission_functions.gml b/scripts/scr_mission_functions/scr_mission_functions.gml index 556fddf967..ac536289df 100644 --- a/scripts/scr_mission_functions/scr_mission_functions.gml +++ b/scripts/scr_mission_functions/scr_mission_functions.gml @@ -549,8 +549,6 @@ function complete_garrison_mission(problem_index) { remove_problem("provide_garrison"); return; } - var planet = new PlanetData(targ_planet, self); - garrisons.update(); if (current_owner != eFACTION.IMPERIUM || !garrisons.garrison_force) { remove_problem("provide_garrison"); diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 3258b990d4..df4e64114f 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -113,7 +113,7 @@ function Roster() constructor { } // Guardsmen answer to their own filter button rather than always passing var _grd_role = _unit.role(); - if (_grd_role == "Guardsman" || _grd_role == "Guard Squad") { + if (_grd_role == "Guardsman" || _grd_role == "Guard Squad" || _grd_role == "Guard Sergeant") { _valid_type = array_contains(_valid_squad_types, "guardsman"); } } @@ -298,7 +298,7 @@ function Roster() constructor { // Guardsmen and Guard Squads have no squad type, so give them their // own filter button (added once) so they can be selected on their own. var _grd_role = _unit.role(); - if ((_grd_role == "Guardsman" || _grd_role == "Guard Squad") && !array_contains(_squads, "guardsman")) { + if ((_grd_role == "Guardsman" || _grd_role == "Guard Squad" || _grd_role == "Guard Sergeant") && !array_contains(_squads, "guardsman")) { array_push(_squads, "guardsman"); new_squad_button("Guardsmen", "guardsman"); } @@ -729,7 +729,7 @@ function add_unit_to_battle(unit, meeting, is_local) { // before the positional-screen experiment: every guardsman shares this one column instead of // being pinned to fixed front columns. bat_hire_column was resolved for this formation at the // top of this function and is driven by the Hirelings bar (bat_hire_for, unit_id 12). - if (_unit_role == "Guardsman") { + if (_unit_role == "Guardsman" || _unit_role == "Guard Sergeant") { col = obj_controller.bat_hire_column; } @@ -832,5 +832,5 @@ function add_vehicle_to_battle(company, veh_index, is_local) { /// excluded from the Headquarters detail view. /// @returns {array} function auxilia_roles() { - return ["Guardsman", "Guard Squad"]; + return ["Guardsman", "Guard Squad", "Guard Sergeant"]; } diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 3372fde267..c77228979c 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -92,6 +92,12 @@ function TradeAttempt(diplomacy) constructor { repeat (_opt.number) { scr_add_man("Guardsman", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); } + // One Guard Sergeant musters with every full squad of GUARD_SQUAD_SIZE + // guardsmen, raised from the same homeworld levy and attached to his men. He + // rides the same path as a guardsman, just a tougher melee-focused profile. + repeat (floor(_opt.number / GUARD_SQUAD_SIZE)) { + scr_add_man("Guard Sergeant", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); + } with (obj_ini) { scr_company_order(0); } From 1df4bbc93d673ec47a85b9f0cb32af47af816bb7 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 24 Jun 2026 02:42:14 +0300 Subject: [PATCH 028/140] Balanced Guard Sarge, added temp portrait As is was and will be. For now the portrait is base guard, just need to give him a chain axe. --- datafiles/data/unit_stats.json | 22 +++++++++--------- datafiles/data/weapons.json | 22 ++++++++++++++++++ datafiles/images/units/Sarge.png | Bin 0 -> 45359 bytes .../scr_draw_unit_image.gml | 11 +++++++++ .../scr_marine_struct/scr_marine_struct.gml | 5 ++-- 5 files changed, 47 insertions(+), 13 deletions(-) create mode 100644 datafiles/images/units/Sarge.png diff --git a/datafiles/data/unit_stats.json b/datafiles/data/unit_stats.json index 55df74adae..cc3775ee74 100644 --- a/datafiles/data/unit_stats.json +++ b/datafiles/data/unit_stats.json @@ -691,30 +691,30 @@ }, "guard_sergeant": { "ballistic_skill": [ - 15, + 20, 1 ], "base_group": "human", "charisma": [ - 25, + 18, 1 ], "constitution": [ - 45, + 34, 1, "max" ], "dexterity": [ - 22, + 24, 1 ], "intelligence": [ 18, 1 ], - "luck": 8, + "luck": 6, "piety": [ - 28, + 30, 1 ], "religion": "imperial_cult", @@ -722,24 +722,24 @@ "armour": "Flak Armour", "gear": "", "mobi": "", - "wep1": "Chainsword", + "wep1": "Guard Chainsword", "wep2": "Laspistol" }, "strength": [ - 30, + 24, 1 ], "technology": [ - 10, + 12, 1 ], "title": "Guard Sergeant", "weapon_skill": [ - 35, + 18, 1 ], "wisdom": [ - 20, + 18, 1 ] }, diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index 0145511e6e..d728b35066 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -314,6 +314,28 @@ ], "value": 4 }, + "Guard Chainsword": { + "abbreviation": "GdChSw", + "ammo": 0, + "arp": 1, + "attack": { + "artifact": 190, + "master_crafted": 150, + "standard": 120 + }, + "description": "A mass-produced chainsword issued to Astra Militarum officers and sergeants. Cruder and less potent than an Astartes blade, but a brutal close-quarters weapon in a guardsman's hands.", + "melee_hands": 1, + "range": 1, + "ranged_hands": 0, + "spli": 4, + "tags": [ + "chain", + "sword", + "savage", + "boarding 1" + ], + "value": 3 + }, "Choppa": { "abbreviation": "Chop", "attack": { diff --git a/datafiles/images/units/Sarge.png b/datafiles/images/units/Sarge.png new file mode 100644 index 0000000000000000000000000000000000000000..59ac96dbf596e122721186072d091c24b5e4b98f GIT binary patch literal 45359 zcmY(qbzD?k*ft6XN_Pz10ulpKLrY0_gLE@=mw+(RIUpb{DJ?B60z=6VLkLL6NP~2L z^StN%ednA%_RQL~;@)fBaoyL7)7DfXz@@=OLqj7_QC84J{a2ulzu3=Fzwv-`1Job7 zkFJs&S{+%;Ht|72Bkce0Kp*n>YKM9u##!Ik*H}Yc z+}6X5&)Uwz#-1kNQ{OfiY%6BRAtOzID;X$`s=>|P*P1EN&DGsUJWz_|e<~J7mH)d8WRaHi zwsR2IRe1ZqPoU1ESe$%)J;i~*fPetL06{(vZ%3ejn3x!l|26RSYhKh7ygothzSe=f z?mn#lTY-YTkFB?}r?0bzJJWv^THAQ|`AV_)`8nH(J6Jmi+t}F&^V(Po+VKhq*je*h z+X)Kr+6fBUi3$sVUONcbu>5cHzRnK+Z~N{(|0@QRK!E?<0SfT(|JUXJ%Hmqy&i1HY z{MV$kfaL$&|NmW+1pe2N|4+xH|DP+Uv7$=HkXC-W?^<0F>-_GP3c|(CP(L z6lC=SEe;-nzLoC>&&50xtmpUMnEBKfgiPH1DoIXGg|G>+MiLJbvuq6vl&Y7#A-3i4 zvZ0NA^7^4KSI+WVJNnIsB=l!;Kb2po6x}4=yIq%%#VG-C(iy{yuj{ZEcvRC!Mhv8&g~8M>=g8MjTa?9~$_?zijJ^VbwsSlZFn*R}=* z%f0uuPZmXw;VD;wsJS?{rH(@>~X-m{eE_+a9zq*J0*PG`7OC( zxQNP~3?)bRzB907m9aSEWjsqU=q2v6+Xv}xo|lBeFttc+GA#6NA!dA`KrOnVQWe#r zXLQMP&CA;cs*(IGiMGsT9oD8H70y+HYZpU>+ft|wqrIag9Qx=J{!(*VX6Bg4W6)WZ zd}zQcaW01+UuBxX8Ojeh$L^0UK7tl8VNZ!Ojgh_~cG3W9s6eyX;u_|3jfBy>@|epG zBK2PwgFS+erRy^8`M`&(=sg9_-7#0merR6;}nfmb}*(vPlMf(5tvXYI)HhqJQ{R`?y`cw<;iWGc@XfKZ9eL{&y3_Gg4_Z%R`p z3{cYmusvC^ToJ|!{5H4VC6E0f6T{JrrB>T?(;z~h2FyEWyw`}ytZk~ZlRIZ}$G&#o zjrNcgxEIw_wbg6e{R9ko@G38f<&Rf}LO4~XR5!aTTuk$vy+(XujY5W|eOFUh_+8 zHdPj&PmNY^tGo)d!TC=*Ao@yy<0AhtNU-eA|X{Mx~r ztERY0)(r9t)kHK0B2QMBAqvmY#j(>=zxYO6v6=2uF@%4wpgzXp0I{>l`O7-j_Thbl zqcb4LG5wP{8H)GGSbS7duqt_C75c-vwv>7gpC2zdH&iRd`j2bZjvP=IgJ89c)4z^% z#~G*QC{#!IzD1#xQOIGZl2$gWLbq-=iLQh;D+%Eq4|5)~@GoXy;_ES+4z@VC4029p zr%_VNUx80OYfA+<*Yv=F`!B~q$uj>+3Ss%ZqeS7ilut*D*Mwnf>GMJEi>V7_VXJL2 z6QZj#p@F?SW=EXTo}AhFD;3VPUBt`omE>~6^+s!D(BY%DWA@6dK$qh@V9)pE&XB8v zr+0?qDOftc6E?{qZ@`L_N^ClB0Iyy>b3BV|H1-6G%3eor#&D>=eP$8zfIeSduzf18 zsih^B>jsi4Xc8q53%`EpT#PeKB6Bs0pG!}C^&A^>B}5&3(j&2xkp4+2*R}8;? z*UWdFIt|{8}_^T4c)3AS=QjFkqsw=_D4|T>&64f9;@nLR)KR z3Wj0>b(@AD+9R_SWB5)5f!0NXJ1;~w){us4VA~v_Yapz+Je_@nJtzCdqhrDd{_GK^ z6_%E6KQ=Y^Jcfx5AG^^l_5~g9`e&p&F^50^68dz6JhquO-zZJFqU?IM%C2E4(Y3t2 zY^bUNfGvj9^#n8r1iD!M43uPOh26VC304^u1+2-TpIZdK4HqaA3B}4%SRIyal zsOB}1=L(PA927=ANf&{+r3M3o1KPwQk=uv^|LFV9NlmsP)1 z$wyYGirF?vExKWgk=(Q8dI^0t7H3OgG#}>1kpvT zjXbQWP?+f+j73oil$_qYpD#)v7h7lHVwM4Eb#@*l7>+1+^P1CcBLw5yoA_sF9#_Uk zo*_yK8ShT7%sm@|7TXK7>|5PyAHu-PmPDJbEM=v2uM(Yco@tN|p5NKNG&94L9d`Q7 zp;0h`Z?DR(=bbJkm|s}Kz^lO+>LIdqljGg=cKydp^W0Qxa-XL%z^QaE z%xz9Br{l+B^15BOJm>7h;U2=PMtZgNXzSE5Jm*CJD9?-TX$1s-v{b3r(%Isy{O)xo zUJ~|p!MLii=+(b5E3+vPzpLUNn17r3ryst7 zYqX%3fb$Sz#J6|I8Y8g!5?aBmjVAHQa*)N-OmFC31(BA$C(6#V>c)h#9$rx6N2|YO z%_-lyKZk6llVw1^^3jkqa_4w>c#wT$R!nO$t#e+a1Y)L-WU#DGw({y^XwS1-f1Ro- znY*}q{}RE4bgbaX#H%@NhLK{T!-Jwr1k!g!#IeOBB+A@g{kw?g$M0$5j4uqmUnqPj zS%#A)rz|_SPx2hyqxZ&OCHSE_ub^P^*j{}|{?flSPEG^h6s+bZ~uAvdITFT zPGp@(M`x1;P%XA3b;J$=jby_IT!frAWpf){-XtGiAC`J4kVfO*Qp*+rQihy(P59tq zVb>xRLqy6O$pq}BnEEHzdNOW-dyzik`ImlQ3*t625)gVvtM3y+TYls|FB3vduY)7{ z)KUSRuW=<2eMLj-edrI55umtOXebcp1EhdEBpeYIyiQ1VDzr_R1R+bj4!l?4b$sxV#(MO&0-o@dMdH@y@`W0|R} z$jwY7sLxYq=jw4~b?ov|WJ3B11K4{X<{!{{v*Yndo?C2}ZUjJ#6OB6{XZ+;B__@V$ zSOSiY$YwXSDy$bJ5CyfaD^yu;p2?ommsnSjW)7U3Jn?&B8EMOShgskCPf_}AzZYia(LH{8 z%F4$FzZq7Nfz4ftSU&7k2d*95N8Z?sobFPO`Sq>zF$24gA3}FO0lm)ul584#+tyFm zn5T&nQb4kN#Xp=sS}(PR?>ZAqR`7$i+px2p=JLu4aPqLuqy%|A@m7=k1D*U}5` z**Zh+{&ZiZ7S|ZpdWW3^JQAlLx`l0Lg~zp7-o0Y{-Y_`ie*9WPXsl~%Uiyi>wY4Jj ze6w)vu=7exI#(xyo$>Cv;=0x2&VK{6VT5{5OiJu6-ru1~Eun<2FaOYWpv)hODn|v6 zmw~3>r_KstP$5hg3e|m7DLXGrRSjXr##qG49V;NxHxqg=MP=fx|O-gGuoBmd|s zB39q~NMo-vxuw<`&6TSW*Ag98HEh;b*WZ$*SL^mL9;;vt)DnvJkwPH&;(noWAaFEzkfP^*OJWodo!FS|1!N|mfQcE}k42s3 zX&ibM^#0Ae^U3Pm4*8CL#C$%o5x`j(hcPqmoFoZ00yN{oI2fCY_t%ca5QXv=l==@6EquL5px9}VAy^|@e|k22;1kIl@4ah*sJIV`XSxo;Gy)D&O%G%f!)XvE-oWjAtq6AdE#1{XA& zWs4$_1w@y-^&+w_sUqeX!eJE@TGk|wqWz}aHGbmwtQoi`44RJMWVq;nNlHIB=3q56 zy71=Ddrcz>6*@gbVQeRj1j@)axEZ>j{aCq=XXaVTd$C4G<2R!v>=Tktqz{j1k+E&b zhIA8#8MV7#)l~njygjY|pE2n(m9p(S(lIbFMMX3=V6%@TKySPidu56~k<_mgGW)*S zq^rGXo+BMX7f*#)N4#0ft8nA>+Z+LpMKuu^5nTm6T!@~okVG>Fxfy3Af0wZfam)g# zq?$g19M_KY4j}HGKW&~~2LujS#v)eOl2{Ac{i4#-ZU0FsagX>)zTqCUk>&uZHK*d= zF$c{~8+*zL0tnM|3Y+{Cb=q82<#njz%gdbB$F3X!$Zv2`r;l^-eiqXJK;qj!?LG+z zgim6NuF9z!Mpw&a)+!=7JU$8)Llx|gBNKWh7Z-yBH1#k&4^Pl)*ZTTdOVM~`m50aT z8@~eV&~?6k=EdW~odAYDNc#E(8Z-zc-I+3ORtcZUqFKS0lWXJk>exZ`dBrjdn6E4ysGs(CwXCYX?^P;udybsxu_C6+USrS?V6(7b@i2hN6mx5_S4R2 zOLZthG#vMsr+V7+YD#QrQ`%myiHoL~pJ@Uw&u>6>GRX#$nelq<#dp64niU!bNpY5V zz0pv4M8>O$d4X&5^_!y9f7{^sd+^vcf`jMIObjHPiiS>nV7K6tBpmM6$@mmV8q27H zaU-v2paq$>>1Y}B6+)}bPE=BFy&4Ah?~ZVps@$3ke5WdA7lJkZnITWwwpz4>Did;$ zq)mtw0>9Q)td0#==gi3&7z}tppctEUimZW;Wm!Rw?Nm;Cq>eOmib+cR5)yrFey`(a zE26zlI&Yn?J56nS0y5Mey~xYEIW;OwGBslQi~qQW?Y9YsSNq56v)x2lj66l181rJP z3Wx(ZoXh(_^5oCEyu+i^hv@!%AGzR`z;BA>O#arPGz;pv9i<9<;I{lZLy=x!ld3qA zWZ&Z+_&7&7!9aN9R(Q`Zb1uI+E^~YQ#4K~gUGI72JI-BCpH7u2Gz9>Ev-rlxi#?v7 zwK9=JD;kH9)Jy>v>bm)hVawyudxaZ88{@Fl_*v5>Ls9oU%G$jT*U> z34FMi4_Ctj-Wx874IUjG!J8SMQdqVh|FET*^($P|yHz}NTNC5U%aY<^F#j$*2boYB ze|il_roJR&qlDPBJCBUTS5;yEOojQA3cKxd(kkUCoKL5|sG#jRxh0Xg@Uh(Bcv_$e z^6gl&avX3q`S!ax-=*O+BdJU#$Ma&xt@VnqW8t!#1xIo&sA_IA&$b)n$Z`7a^JSk| zGb!7L;w-1MK~<-?zZ?zNY=zR&x%En$r;VKPluiucB)t?TX6ztfOMTo}^NR@kypQVxc@a;2{9mO@prFo z$?X-vom)N4FQ3l zI-D!3BSG2&UrOESVR9C(zj^oq9Yh_nVa5okBDyMWp0K&t4BlJkHzspYew#hr?n{hq zb3M*q<`_(WKhKM2h8jnm zkt>eh6^Lymc;s*NL%59y@bb%Z^HVd<~^LzwI9gd6Lo{mMQnkHUY1oy=Ho< z{ek}QmO%51_A1U}3ec#UaYpvKJN>XbcXRhr--S1~!=VVj?J_32!yy}@@bfjCw3%G} zmP@7RdM}C^`H?+Va1W+E!@Hj#7xNzhdY@nJ+_SExvzppRtvD5c!~V4Q_^EnTdU@f=ig?hA_^nf|Q_`18weq+%D{|dT zikKzV=gtZSqRp^Io>wAC+ef=OCOC>FO(ENwgH0nt zUqbh*7Vf$uEZc}NJYZG%IvNjU^V_gwuM2~j3y+DSQ6E)pzBwX4-#qw%xngK&GE?0) z*018Hz^Z-?jr@u+&5P<{X4>=iVKYelU!s^&=ae(V3r;iLOyR=2Jyx2E_Mo%pmciR& z5U)gCbT~~jRN+hc>aow}&iGhgbM)*hjzrSN$5c+uQ@B8GzTju|uVeA!_n5PFHydVx z3^h!&?mpi4#7LeGwKspq1x5{?2^4B~f zyjKpq=}{7Y`8OWBJM){&%)CG>g3Y@+a$ zLI>da03!(AjjrfCUwiC&z?$U9I~*mX0E zIAxV(6B7^)2TNImA9AagOXNR7uUuV}rsQnt72TY8{`3yF2TbXPjPG_>gO;s9Gy=bD zP;PG`%Sum3Vd*^UNHA(*Xyy)JX7346$T6k9#lSp9`J zAv5u*o1Q`HyO#ORpAN4d>qnF^Axr1MT-cmrG)Vg6kX5{{`+sMcALL>+8J&d+Qp>oy zEk;q3f=A`%!txerr=tK=QI_kgf7}2Pb1G(*ajtrQr(mj#W5trwmeAUl(!@6O8*6mI z*?`n8zrXEH1mS+xgeBfm&xu8E;#iZjmdRn!9NRy44KEQf>q$$#AmXIBw+rXLe^W0r zZJkjRsj2BCAmJF`NcBY?f^R}a%a_d9@U8~?<6tWxk|#~y^}@E!{UUH@G$P8mu#w!= zbYlG?*VRqKm=Br1_qJhuB}xeugn1POt>R4-H<#9d=c);+wyDPgBoo<}khs8QJ z1KOC2$TPpe#i4iYVNu{tGN`h3H}YutMJ&@78Nkmnco!N(d*ajJZAiU&=cQ=Yn7t$Q z6#>MfG+*zd^>@LAmAL5|E#&vi$$g>){pigm_AklG8xcxG3_8Gxo8csZ)yogLp%Y5= zXXcC@qeI8|Hz(uh^A+)EDFY;2vU;EJLvZFV+rD@7jvHCru=HMn3z04J799A`r2nlG zdD@3(g;B0A(lEc{NIR6O)_~hdZfzqAty9?{rc?S@M91A41|q{uvWi@rwe-PJBv(hv zn~&XhzZ?WD!cM8{%$NIV<;`cw?V}!oKj^M?|6o0-<7Reqi6P73L0QQV*OU;24>mpT znp%VvomCJb5HE~ZY$^x^WidZ^cbm`S6SYzB!&HiSr=LXPCfr+Gg%m2ZzHyM)x_ELR z81U6}EVsV*gE8;TwIG>(XE~?pPHqmupntc+1_7W{R5WRWsQipdAkYDvJZ4#1i8G{L z+_LRPoX&}~xmzIHB}4%!w}D6;`El>|t?Mm(Fs};DX6^RD7DOxj7O@r7=g{=Ujpk^% zcgVY4&UxGl#2jnW+Ij`*^8ZBC`-IgP_STJUsKU_|p3>eU$}&K@2j{KkmKEEZ)1@6+ zPQcA447$8QF03+;xb)TEFFGz{@B+I}=$v!-|6Wa6Lppr1Kj#9mP{PD@NDxC(Rj_#ttXyW(&R_n$cpV)jtpi~C_-2iGh0OfbFB2d?tbt2) z66LYtJ<;)E0cD1Xr|!iJ6T z%{P(((Ghw`KiU-fhO!>y>0+N2s+TW4S?68+1gW3^h@5gv*$66(yv>dK#M8jxBi~VP z0p!M3qJ&We`AyE~kB76o2W~x!z@yZO_v?QCZ*g=0XD3}-P9}}7Tnd7AM2v_o0r=0A z%bdGyKy;15dt}j7g7$uyvmI+&HnPx*5mD}+{B}(X5oe+Q$QVoN)ZX@^uSlRY2V3%Y zki`1NJw)8nCoFitMtZaFq4U=SYOIa}QRrjSr=FQUSFZi82;EkGnsfdYK{L@B)4@Q; zl-gyfy{htGqFpz0QU&2hVlJE1gu(d1DoE`=fV{Tz5R*nzzA)lr>3N}XBtv++*6SXU zNHSs>{?A9DlCg5nO9Z^2q(cH;IT-oSw`s^Vp8nJ9s#Bgbf)q_8=a=FA%!EJu2ONnZ z0=*{-Z2|*b!Qn7hJytAKfCSGsQ&*BtroyT&woWZON5l%@oLs9dxeP71_TAWw&#f@~ z8R!{NsNzfutsgDl4LC=lq1K;bGo<#AOFZ>JqvBn6qn3=?!s;^fiSX*_dNua^+NMC^ z^?BRL2cq}cOz|VMV>eZ6kGs)|&dxPT3R1oqET7)KAhEpvNrkd?2lNNFT@@mfSVFbC zFW-D*#St3YmJ2+7v@oA9e1AVKJrXz_rAJ3cr!Jy+YA(?k!WailT(?utbiig$`|5t* zCr%uBmd;v7&tRi5<}IKk1RgElak9{B=2xbhHXw&Ja?#egIUeB4H-DS4m}Vqgkok>t zHPLBJ79#w;%&^gI)mk$t8{uXKcf`}=%XB?vuu>no5!Q%86A4-gYLw8j*n(Iq*UPMV zhBI94%RIl&;1n!O<}WX&DwbaztpI z(_rioTa1?RQuB3A$IfGSNa%G*AzJMMIYF)0wOXAEF~n(#{XLQjDW`IA_7L{u6I2l1 zpPEtlcP;dEkgESC^wB8fVd|JJnZp_|=<0D?)L&O?WI&&eHAh{ zBtM$qV9Cib-GcTWB^gquU4Az;otc`s+!UCXuSd5x4_wRwi_G=z?e&LF1uq!5|*S4v8ztb+PvvOP$06R(F|fnz)?lfAR4d*NXgUe~)KN zw_x=KEdK17qm;oi4k{*rc6|jEj(@GnnGNpuZn0@MwN7FtCXUXry#6C)O8tW!u^iGP zeb-}J_jN2XJzWq!;ecuV(=H@t;fA`d_Gb9bvZ#_flAnoCc&UT|5fWXNS0p<%o_V4POIqk<7-x<)Io!U=I3+P=PD3#U$SPowU2Cv zM8-9SHD`2{ay0wO&os2~{FMYcm&n|ge zgA!UMw0m=C&_!H_>YT2cIQj88J7rRp*A2`RSUP~$1@7sWu#BVWhnEv8Q$cu`4);xz< zXYH854<|Q!z$U;{Wlh6Wg|d5z(mpBFU-rgx+5vIX72}?aIl-Lg#LcXD0LN7B1~fxr)LOY*bEk1Tc6giUExy;(Bg(XzB$(&q8rxUC$sBkt5?j65UI1t1r0FzcsioOpj^J*_q4dz2@T&Ra zCuiGa6J3}2wi$HUXv{F9ibHi`BvrmP<;vJ@cJ!zCdBBr5_8mnI%__$^-;)ka}f zu47aEFMeqr`F#IG@`48VESWEpZX6G{gkSuNC_vDXYRe!&KN6(hT+0pw$2VGazr#p= zh^qb*e&^S7dt+!-;0HY0)H3cY4C9;dx{M|VrdY{dbuVV4#=AsW&l z=DCp3;?g?q(JJP8{OaPJjr;rdRyWZfq6%}517T3Me-e>QkB2&vMJ){bQgDf`6J;C| zIxqXh&C#RO@=6p=v1_NE!NxN$hAHqcC359J@iFB$0PA&8R;h6X$kgzDaS3_90j}us z>X7>zyJ+l?AYAJ=prhQIMS@9UfS48{@H5vj!dj8|mZ^aEa>?j>uVx^a+GqRnjLn3o zQutv#_0dzIUgl*Y8OqSD(A)}0hP;n4i!lp5S>SqFNqNsvnd|l5;|EjYpWlZ~={Udh zbb%9`hTJ0i29Ar{9gQYtMguyrKcd=DIVn9+r!r4XZG&jP*+w2(L;L<$^_~_?pLz)B zq#x@F^(7l5Du%*c_;W&IaOFlj>|fLH|7BNyX$$4=3sLJ?SgYB-4n>#a-z%$`=iWKP zdRPZkK1&A9b@@pm1E;*3YXW_B_?LuG*spxhn|x@($9T$B1tW84S~3|>pTS7u_<&^tN4 z|4k%7j<*te=$AYpB9z2TC>h{>^mquL}JxT<(!?k_Lm^A920~U4Qy*m__+5v9;r_XgYMtU#0AkGoJN{QnkXYo&mjA_A}n+xYl{CMtl^)|3TnLdqvyRtAOf zc!f5wsjW9@PW(?^KT^0TWo$ZV&u1M3%v>m&*Aa>)6+1q zACPi03g(z;arEe%xa4#IXZxbRRp>E^YC1SN`qtf&M22o}E@VeuhhxkoOtMCX~VmufkgEXkh{-<&gLP zii@hihG#zi#%buIC9gKd$bLKXoE@p!qR8ba_WE-s&_o18TLqsYmy=t4t#osBKP8U z{=g^Q9!5CHpDR*i|EwbrC=zGf^36;QHxRMu3~q5KA3O-gWLYH5^PhVP%>t2Tco zP)siao%L=dH5GFsPV1mcxSNQ*+9Kn67ZX0&3E{eF>E6+IMU*oO&(6KdNt9__Cz-vQpH< z^D6<0Xu|87(SNQ9&mvb;SrS>JS5=9AU`Wf%2>Rf68KpwHTDO1eA@jIWC?uJNqhq^} zDf^usGlwl1V27iNt51x$b^j%&@^PAmnXTz2(xqu*Z-r3j_viAQj-Nup9FE|`V}OF@ zE4XT3zQ?VFzk6@tPu!YgX!R}=7SPF5$>3A7U&7Vo47)+QEY1fXN-(b+b_Vf*ddz`) zQXIzk_d@<74*WYDH0vUO19N32Hu7}kO9o4vEh^-?t59ReL!Li>)+qFH-x1PH(%7p= zpBxl|F7xzJ@9{|H1~>dzu>KU$d-5vbk2T%0apNgZrr6jGeywossJFNoqLmWa;pjUz zttQyYAs=iamodO*B7;8F04?;COzWeDe9?j?f;2{^Gs0+66*0KzH1>_>-IU_eX>57V zw&RPx4hQ3;pQ3bjqA;($K_qTA;Vmbo1?Nw;ZH}k)RmXf_;KO?S8}8>(%p6S^rA1W) z&N*K)ioen%YXXPI@<7BOTPN2jAIiM`R^GcM);e|FI(0Jt7wG903Z#ST(eGPhaC8Ax zReGPR_i{?JplnG9BKT))ByKsF!mP7P4n>Ht75??*99fE0KNp>eSgFL z-mnE}*Shn5Li4XcI5k|2fiAzn7^!cs_?0g0c}>4*RB9u) zn^;VD*V3#;k^q4UXXRc_ea}TKqDgFjmIfgdNR&Q8nZh7t;~xee+~x8!_qsnJaYLlq zajDRiWE9H)_!kTQ5rrR7M4L&RbC78-(;IVrY{_gDp7Bef!rkX_)0>*1fVV1G4_p04 z?yM6!lYSH4^Z6#Vv-in-S}4epZs@6R6ZoXkpH7*FU{ZfXxbk0TPs?(sTJbnmLl+|k zqP`923>OQ{7*5e9JJnV=)7vi#MA^-ov*6pt>M_)b+>aWiT;DH&kMieg;vy9)QJ`<{x#9GiGwB(AlU(*oycVEc_BH{UePq6}_ zC#6_OA8T^y)qNtqkP(JTAwM_cEncOw__-f1k29jH%dHW{rZ12Q?73Y(#kBzbhEu9s zw-4z33XOs|)K}~}KN&ZgT7ayDIma$r%b# zaR)sEKVGckN!cH#QzQmDHnk`Q(MAn3t~@Fg({5Z;$}-Y1Wy_3dO)fx3Xi}f4%nlrr zk6!csCxnfW*92PHsAX5PA-rr|SXzLYMqNDTQdCMlWnjnpKze@HZPj8*FWG~pMOu)( z_N#I2{SP7*9XZ@mU4X6lslk$;(;ICebEf9nFJE6l4v)U5zA>1e(NF_KJJp`9*w%h= z$Lt2NWiSbZUgBA<;}t$(1cEHvX56yY5`zW2iug4?w$-tQ2P)b!d+=C8p=>0&DtmLU z&D^yyUeBKVJp#|v%5oE6Lo%?Bfqqg1<%bwmoMUwfGy8tathUM_QZ-&YRBFV_$(F9T z5aRO~DM&)O~@%ry}`D z4GbRY!g`-ZhUPa^`pC%gbY`9|_eDJ(?oj;duXWW&gbuuNzIfKA@+KKPlz1Xz!gFex zaLTP9&CHkQA-nSd*honYgjEhDk}j!5K}Uf`%|8Zxo-p9EI;s1gV05sxUvcDCU-kXpfE9;P*2jg3doq#1@-td!RcJXm=C~pC| zBuU>*T1qI}$x67dIL)`-CPkSfool$;y#E5%WDB{5{PGOBVxQ|LpN_9z6N`iinfW9@ z_Ce0<^dLqKzu}eyq1Ue@et%-{>U^GjoQvJjnl74#H zJ1Ay@RqMOcL8Ie;e|`I2)*EL=Pru4(U9x`BPjWW95tT(&r$x7Nu|`K2QvwV}Wq5B^ zF0b!eVebk3VO@cDG~LQ1is&l=dlcnvollqMnJ(%Hljzl>o{fJY^^j@v@p^YJcnONb zEvJyGEulz`xhD0cm5x!0DI>Z6kmM5{Xq?@$U1kW~dJ<E$mXuy~(@?JpUWp>Q1ctzFVnIf9MoboIsmPLQ!J>Ydk3uA1Co9O z<_vmk063F(#HjXjG)%l27CjqlKo+x-*+yHnLoWo{3WHGJF+v|5CSJ4uR`{~*?SaN! z=nc0edmM)Jg9f9$5M5({=kU=Z#q>I)_*8#88byYy?>%+kz+=Ty$=T>~Y&Rxm$64w3 z?s=oyceKKQtZ)R_qTGGTGb~f?R{vHf4Yh_!<;KMFSJ*#eh4wd3jlnok#EuejsulE$ zvoiSsLIxl8b2v4-T|#fg*iZ=q!nrtU`9598HCb=jYuU?L!UId2@qK7_bQSQ$`G!%I`u$TWjn zOCF>%EiMmCqQ1~0-OetJw5EwT#8@;{BYytw-8*ec6u(viQ&xGYmCm9Uc45}`#usPC z6I9BBm*_kkOf82Of6h)P^F#4roF{LHIzl)rQeBPY$zMzTAIZ6qMB?VlT zZLikDqau`>#2cjJ?JdFq1eZb~vTdC?HiPb3{K@pXfn71RVL$pn8&<^p<7`Gs=%NA9 zf0+gnj$GFAIi?G|Wb87q5}^^Tb;h-s_|K`8WlaoS=Vw)(AAaMd_2SzxfQ+aS~7@?BRY9g!G)7 z);Bpn_Yu4U(j#s829C3 z8HXDmV-R7ZbG|>l+pR<_zb(2BPshG-7Ev5L3#jw4^-y4w>bDS;K*X7g)iJ2=R*+zH zBsRNqih$qgdHT_$J zU&YYtZDinXyM$0unSVTLmyQE-2m*a6DnoQNIBMG^DP!4Hf4*db>r7)=WZd$(CWB>B z0GZZLxXP>$xjo9XaG?m_i^dH3KoH73U}O7obYS!^FO25(9{anc+(|8A6(*cdZ*WqG z*J`X=ESS6O#bZKsj=B$u%+3y+Nw-DocE^yQ-v@b9rYQIh8&K80%o{L34Ni!DQ4HHlCF&`Ji z$53BtG^sbK7bRDOAB08^Z00e~7FZXb_H5dRY3xkqL~G+Uf=a7!`7*gjVZ?(ZW}DKR z7Ljej703$n*Sml107eOQ0!2c))paE&kad;cV!bkn(3Jn+F?0Tfg)cR{mcbW%ew%SW zBdqI(244?>elIN_Nro0jc*(F6QZ#K>`TQIP|I>gU-2XB%INfi6N|=<|eHDiLDQwQ=tn-HOhQUTHwFYvp)=!Gnd(tK$z17qW-Di?t5#l0mnQaB1X&70KDVN1{4(f z=WfOd^im__JOs7N!BJ9NOz{OeqL#Om5LH)pRSk;My^Y#6A$laeac-kHYg#&EDayj{ zCf{QsLI2fqae4Xu63EgJHf3sT2t~+Q=>&3#eWs{6%j|H`(Phqa1WW!1nh5wc z1bMG8#~3zYCHYcA&_BQ*aQ+&VG&1Hhlnl9hC0a+{*wUg=fb4pIER8}~{46|!r5)3$ z07#Q<^S8&f>s!}O1p`w=GQsCgmCaQ-bMM=-tiSs+KkT}5Y#q~ozI>MpJ15nk^utk_ z0_+575|^6;7ZEoWl# zS6|$hC{s{u;NX@Y5?4k^0s;R!Pv8p>>p-q^;P>o$?8u1zd@koTkc5;&ld0$a9^vZw zRMz!%jOETHDghf1pbRCq30ZJ1wyr3-=RxkiUTsupLXq$1Ir$b-c+RqoQ~ zn_t`sVB-43-?HnkrB<)F;s*unP0|#Yqj>u91{Yk%JH8rc`3-&Pvb)Ld*qQ}Cic<|K zp>{4L3S^c1z%npt%pT{5>10ya>)2={WE5OU1^lqf^K9TV&SL*`QA0ZvwGcgRQRN2_ z5T{@3PxL!rOiR5C(9KM=@-%hsnlMuo ze{e7UPh`5#T`)ld7v=p4(Y;96KS9ei8^kwfdaCN2Aa~=5l!fJ$4Lcnj;pj#lFSz;9 zG)9O@T=jkqXxzBQJM2)6=zDcE|IPOTTh1$&|cE~Ph$u;iK6jtVvBXc8sX23jvv_-zpZpsz>AblsXbf6K8Z!_+auO~u}Q&xwF#K9S9?RWI zCK=d{Cbd2eV+8PEQ$(W$pJiHP@9)+_AbKI@rCe==A0o7>?$t?h?lP2MZ&JOKjYh`H$ zQOE}mnlb!=qRMKI_zgA@xJ^x2Ef|#qUx~V_nOD1Pdr5b2#9yF^Q<54+x~@L%-C)&F ziQSLwVMd(qXT2n31n1LK10MiodaRD0uhg!EhKCD1BD|m^%+xWtd=j5x&-Vu<9Tawgh_=1EgQT4_kk_@{B3hU)~Qwl*R+z4s0|u}>o_Ot<=+ zsUN;6FInx!8wZv;$Cf&hh@9*M25fG3Tq$LEIk(L^|TT*fm5XqstLmFx6 zZU*TFX{AF37-T2`Vd(CT=l-8}^J>;Qcdc{pIs3c!XG_C0yvP#z@wSDfFqg^F-&!Tr z;P&G9&kZ7G*edz)6<&8-LMFw!Npr%jG|BX*G}ZtOs4tl&bDgS?<49GC86WwFuZiVn zkSlW#69IEO`ip1{4=QOSb#~^e`Ev_>Z1e4j=jH0w$bQwNgm2^T$Fj?Z%l$o*IU3bw zoJM%HfUM@w1uB&7R%FjUHnNA34pdBv2}S`IzD}Im%WgAnuz*XEN&YG@nf-KIp)r0zzk zOGxxI@prPn{)!=B5vGgBfrX=B!BX=#i>Kz(l=NiqH%6^+h#qM~=Cz;9JPkuHanYPTkFu)O>>}_HkHd)XYJyhAzMAqLYg_`g50M z*Ix}iy4!XbhpJJ7K}~=z>w{ia;r&-W>yYxl2^3hWi&)Exrvy6oSO2QO7G||eo?ppG z(fK^7h0dU|IqkS;IVDOEwb^&-=p%wWujNicVVh$u^o*E%{fYDs zUFsy6ScmNm;|rejTDtrNjyTCITx|8+|86{j>*5AH+*-=*4af=P%&ZA0YlKWvKW6l0 z=jN=0_8E+qfB!L?{JG9%v;N=z4e|2-2MnjEJ+Qqh^-;vIM(M zSeow>YmMvDe5%cJe^<{QD#7c_1Yh7|^fJ7R@h#`dUQkWi8qF&Azdz>pV?B<;wqm$< z9B+IazX<<^Q_Px7xQ&mbL25WzWFFo9O0cTN|M4!)`$9R7ru{WSeX|mw4w3K~3Q>p$ zm1AoU3ZEbv!0qNm>?h;Q!~gVl>+gzglOR7mT@|2g!0=q*G`PGOFz2A;WagkYPsc2f zT2u;4`nq!c*8^Y3LW6*G)LTalFUw7~jZ)q&w3%My5N_|Q?kn4xm7T=H+h(HEyM3dF zgXLSR%9-aKA@0Vc*6C-j6D5(E;Zp1wRko=qjE-$9ogGa%?lB?oY6G2A2+A&sw2c1( znUHU1n%c5Cf0||k4ir`OZMV18fI!V4VnQ1SG>#g-_0GV}y3Ip;#Qj5H zvKLn-{HAE8B`M!Iae*t~%XB|alGFeY9;>hWxUl_X(cEg6LFsdk%C7BEae-x19Up=z zrPz*rKwtd$FDF`C6P0Ti;h!4KvKx!OrfI+93V0MWogs2oJ6^B(i=KDLTXc?BwQxr9 zj$t(Jt#SuFfvX}cy5I)m#OsNd%d{td1M;khZvHN*4apAswXXh}BegY}*|6s@c9Zc|q74dl zHw97m_P1GlXsT(B>ps4s?n?5a*nuXp6K?gB2Fa=5koS!=@J6<_EpDP7608VWKQ3k^ zydgx<5B=Q zmE!eYf$(&RQFc%_Z99}g{EksA4ND7`i6DtDKM#wJr`LC6o)kN?gZ+DKNvmjL3X1k1 z)bFgs=%DMIT8Y}sK6RQ*CwAu&Q?-B)HIa%m6D#-{Z(mqSUr#8++t_6 zd|eqwQhg83Bw>27&H)WQkH4(k~k9EVLzZM%- z8{Jl;Ol~E0p{P0a40s?w;HmGjD@)RjZ~|_r0k@qIlzu3gY=I>=t&@kd)D-o97%Y((N|h{H zN9TFNBI79L_1Gk#$5l3pyH&lo44o+V?IEL~&1KQely=uHpF<2Vi%8O|-SU;DmN>A0 z#U*DYu`T-fPa0dtXIeYumEU*5xwYO$fPq=ZM6kX}Wdkr{zkaJQ6nAd!Cn#KKK1ffV zb1E}~AI7qyo`y*#lst*>ed+@nT8!AF z&0+U;>R^n1Eq|X3!JUvM9dQV1P&Cc4ngY@x2latW#R|&mT>Ecc8=7S}*pnzq~v z7o0B;=RGN0Qq)jWGv6NS$p<0FV@YQ_^bsn<2Hefu!Nm+{u@zwvq(C^$UTpC=z6qxIS9AzkJzhS`_eX(9{7r8pL>Ch6gcnoN*% z=Ci_tjvbsycY8(jPZRdk!1cYev)J~dPC1>&Bvt#Y0q-( ze7CLVjsCGZTGJ7X$CMgtZZByq_Z=(P;lcU?jev!WZT@$gVluKU@`A*i!W{R|#Olly zc9eSwyxhJlrr&oE6pg%xbyL_JzwSByAZH&4uWb9H%19z9k(jKr06wBp(QH|aFmfXk zI^3eXxUfAmax+#)yEK>Z8zC)pU{)mt#cGj84@Rq*B~^0}ECGRI(ogtyBjJV3e_~mm zORv@@eRejUfF3Ogh6L1*z^~o5#O{sdO=+{_|LH`M7Ba&@8TZ6~ z>WH5zs$^JaNK8N0kN@Oa^r5!OMc=DF8Buk)d5&=fxDQA?tUvom7A1e4J|}MCV=K=_ zD`%_ZBU6mG#lon`FsV7T{dRCvt&uUB-*+lO)?gsy31O^MQKPhq9I@5!Xzb`u@7@E< zjcGUwK0n6br-X+sIA>s*LWY_we)8Vir^+78yPO$(m{5`(hsq!2w%NPYtc&hHKili+ zo=C5Xz8Q8;1HQ*z3eiVFtNn_@%e=#l#A#*}LCLZ~Oj^N`&!st(ivEjVb89s<0w!hY zRecwV z5DlC(HfA_FgV=4Jxkbsn>DWP^4Db$2Dn;HYlQxuN={f#gJ=&mqmCH^n_1kMRAt%H( z=FP%)hC;z?h8}z>^~hVpGx-;(4O9h!vO(r`)tb`vfTC@9;{kRUax+ST<3!x{_Z8_UOKGMEec7w2Un&IC!D^L z@_e>q>A=}eq9C#o(~T=r-~em8yZU(HI(D;Qd@?tKNJ?$a~OjJs?3e094D+G zirXwC&c&K|s~Qt37!Ds7tbA?f_ph`_2Ea-J45K&9a|uxi-li~3ZDS`WIL-w!&SIr9 zxad7f@yY=LrP&~;gi1;MF8cWG_B%T3WiYqW+`^*#?w6@kDil@dk;KMvjc~lZy`Ha} zBK0P&o9x_Gb+S&&pQ`PH5-1w8F<0f-Af6N>+G=`R?s_KgixyI(&DB!rN~>}`{{0Q( zq{Rj;NUE3_s*?OgqatqJf;L*!UC6`M+Fp^`JF5KPX8h%=k9-!3^Ag657t6|xZ6(Fn zGX&wdlSWsDtlZYk7lcX;;=(b`(jGZXB?dFO?)!CGb#FOJM>C`UIyXCjVh0PU_V--& zcXZ@Kk~Q#jM_JsBTx(m#Vtf4^UL6E!Bq%^LEa4%Y{|qplO+&}-Bbvfta2^yLGsl}y{Q49h_CqR6*g4w=5wfwvJ28|UOzW^ zEzoV~r4Vwu!z|8*KMl7IG?YkXA|P}AK2fgn5rYG_c<(@7@uct<-tcxI!&lPEGW|5{ z5C*}KWs&hmL$qwC$ol|Hs~*vsSt^zs(dhF<;>?sYR*~Y)CsJfU)VkHsOUM(1}+PFO` zIe4MP@uV)^FS(OVZ~I)h0h^Kkt%klCXq3R2IKdLUxk;f|Vo)j2h{E0c%Vn?L{IF+Z zj1Eoqc_=jBJPnrGRJ1&m^OCr>jDv_1 zZ$|%drpmRhfm5X?JvV$&YG&jGsm-pFbRm~&Q!vA)+0h?u5{xkzuX3|pA6H0%kfM)& zdEc}8_kccIS&jT!66iJVS-OZcCM9L-uU+o`?Is2Q0dw%VYFH-&3H&1^K;vV#MrlNx$ zd0DLM^}ENrBuRk)g^;9!>?5d$K}kaJfUphPS&^8ugvGe$4VRP$li>hFAd8j`)8uh} zW`|Z;*+dx7DvC4SB%~Vuh4s|1MQbo3+zBZ=*?(nZjt5-0ii!#;uu^e#+`S8#jI^Dp zE(rZMCnDJD{iAnfDV+_l8`AB$tdG1xKtr_};f%{<)+InB{tQWW$R5JJGJlYeqj|Xd zF-Q_CM&X4=GyJdc-<5SM$0OwFxYOwXqhK}tKe4}oUcXTYaahgZ#S(e>%Y!9})um3~ zMpZdlg{|7G7cRyLeYgmN^0pmJR%|NG;=s~ftc6#8`TQtop+8Nzw(|a7E#WDt3P#a#mSK~eEHnDy0;ct4{CM4HCVbtp8jp~ zNa4d15}hr0i|X*dbSTBp@_75J(>O{yhoNWNj?nFNYd|Qfo=K?z;jpfC=|4NFSd`$` zInc;Ks4|xfV)^0oLw(N8RUHLwZfTjF%g~tNNIJ%e?<)^ovW~Vg_R8oCk%<~LxcBSq z5s83t0PwRSFe0g#r$?reKZqzy1L`n>$0AqiS4oZ#dg&c27|u-GS0KqCr5yTavCctc z`WrW~V$jellX_3wLoX-1h^AM|H!1__dU`TSbMAgIC6&~{AWNgB?B6cou&BgO9r?|{ z(SNUy>CdsI{lvQ|ye_8~rTVy$jRSQcXcWqnq_LSz9PpMno!@X&e{4rwxJkbpG_S)p zoQmdS1$3pTC=fnLAuq-d5;JJaGI@lwm^sGR{9asVN{dQe6V-@vp9$A^8aM5;cs`%i zY-R*jqQus&GHref8X=_%&FLAo`Fdtl8}2Nf%#3L|WNw=k(rdeC(i%k=qE_0#4ukeu zLzqXkvQM>DLx{C>-E)-JqfsMTJH$W^dXd2z#5Rhup1|e82_gh=S1W6umFA2EM7M-p zrIByJ%hR%3wq6P^n7&Ank$X?y9Y~ccK)o^MSY*EiS4j=D)pvN;uS^zxn)c#M1!lh* zP5e5$-#gcS$+Z${-|g#Fn>ehrcdl zW{D&X=KeKFK2>%8!>1pCdMR-(afgrU**Ba~n!+)IVpL6P)y>(pZ8RYCb#tfTpX)xl zczLBnC@ACu8{*9$9T`nsGK*idWhK^^#iv$`g zG%-&($faSg#QlcOdn^8S-oDf^Na*8P%B*3_Oox})a}CqMO(zaD$*?Rm3oypsjE5aP z@jsQi?qRRt_5;h^<2@o}8P2l%4gy3BL*M19?}HZOf>R~7MuqkNIZ^mKB3?qQxBI(4R<(0T(d zgPJtJL`Az70}&NnTRQ^~Z>`>FYN-3p2;M}YEwvXTC@R>PdLo{@xeB(M7#&SD5ab>l zVTCmqo$0+@R%vO3Y9#Eymki6t*a+J`TQ8B{`T|j%U0yKr@ECzi`Q3$Zy#vC-)g@J~ zQGPNXDERC*4gb&+!eT9wHtkLl;r2s`>D)M-8s%-Sn`(SJ{aim#(K?gdh61!kc9iD+ zpUIDotvs$C)c>0MQkrIAe^k+F(bkbECc7Wv-I3#h{Zbe0@&G16lN%2?BEAb14eM5f z*f*_;A*aExm(KodaQfinoab_sVGR5V(ZTmhMCgCKCSJ0z_Lv6ik}SQk$42|bK$d?J zxo7A{`z@$^hP3Uk`w~;XBmCUBotF_gk}~$~YC|qUtQxuJE?-f2Q`Cvfs~_^NAU%eO zkiDB3X$?U@=uhWD4S7ZCMa`J_hbRy&ZOk{(L~;WLVkT`X-SwQ_CW5HcfErJ4bF0M; zf8$S;uT@_pLf{}LmGmr!}r482pqoYbDM<%yK6+|b&OiZ`0iu2Vu zd|;LWq_C$gs?edVB2)07#(ViRqHm<$hP`w*6JF!M6G->9~`ieOV{=oR$*L@OXMv$c%Mx5K$B%0pR;jQJwXL7tT zncZGW^U}N5mWWe7#l3WB7ZZEsr2Jm)@Y)-9**xb~HdWq~7<4kPNiCI4FsW>&I_lH( zi6@IkL;?-aW6o`UxwICxk|od)D12;n30ujZSqzj>O&rL{{%i}3Y*UWc>;+X@4QfD9 z*$gpr^K*yAzjAg(5zdu*D&=jaADSccT?4bY1RLQc0*ihDWY$M?N>688&W@hA>lB8X zH5fZN177+$Dmh~Yl0WWNZ8outfOi~#(G|FNVIFS^>fB#ep{ZasXfAjwsBJF?V{yz&(XM*zruBJz;aSkO z#`Xy2xLQ^Sf`5-aV#qn96nqs}_K|jqK9(}(4W^XdEq+geajMh$Cwdlg1I!T`>`pQk ztSTP9*p;yet3SGKm@#nE0OwzOtI6CkKb$v(PW)sj`{@iv3+yR*3ricX+(y`$Qb4u_o&x z5bLgW)RT?*PM>u9aZoM1t##@(p4LX#Q##U{;B}v{hFk~|2!WpGa{tk1K2;svu79Yh z++6Pblj);(9CwhN_QOFm@SUdJr8EwIDAeW0G&%$@(6^-3PZPB{6O>U|e6m+D!;1b} z584+izKP#Nbh=;PcU*QvX?On-zHP~-kjuP~NVcTXOq`_0r-~T>G-v?(H00y&Mq8w< zh#Uoe^+Z;fZy~@S~E~M~UnW{w+@@GZWs^LT+ZY&xPDfV_Mj~JW8m+Cvf|N zCyy$J*ECDFd6*~@-&RI;_wP#-HvYB=iarJC`GZIwBW@+EZ(kOkJ*_?@oTz_+)*-E| z(~d1|bl9d1B=DL6yB=CgyM0x9SyoZR_bEXZKPl3bG{5dWsn@nsUrr}UL{jp-v!sz- z`We%k45sG{xU&f9`)2^yJZbqzOue!x(AUc9(W;j_fb7yoR!N?+zfWo86NG8_UE_f; zhZasDGjNp!sd1}Kd`#7eDmVR>2BFewHkwn6I(Pt=?8$RqW%AYy8mMsX0zkPHq3QWAZ%_K`;dXB17F%UJ}9vrIB z_2~+|z;mssEkQ6z_hbKVNh1EUI$31vd`@1@)N|_Qa1#0-{2SN3j6se{jsKkH&4{1j z*C%XqKj9M3wKxkzU;4EiIqYTYwbXA7Ivl`FC5Ww`1Yv_k(R`nf(L%uL$7ee3y3!zG z!e)Qf0j!!SHIJJ61XP@Q^6uVX=?)%-+j|wS0K1_lPUo4u?ZH9EfDbUb>wj-c8OKU#3s|<< z{#t>*rsCI!^2JSP{^7~zY)x7c>S#&UQKb#TuP5f9lYR^M{J_swLFS&GEw1<^7>8IX z+Yf5l%xAavurA~7!!U~6$C~)KxPT90CwrgoeVcuD0t0MCNLoCx&wA8Ye+mWFaV+$P zGUG$Cs=nKoeqiDB-#0|J>bF$k-Q_t_M=f9ZFB5doh**73Nj50{mL@gH!njBVFHH&` zw(Y&2!lDQ>{eUWlx>|V-okp0w>HKo)eogprrY_04#YOBDGsEph>S5#{REY< z6$!%J6i)eMYiRdj)hNUh+m>3_TM12G6;W8uIVdL@+vLS+ZTK9R?qNJRy^aCxcr-JA z1u*#87JPd}+E!WydgSgpQ+x!{%Eh`LNgp#fW&kTVdOkJab)A~!XtR^#ua;kL{qXk%*S*Vdz&iO~G1#2p~H_ulymXQ;NK@WCca1;ky zbKwx2B_jkINv8A-Q!3c}X)N}{R$Y0;lHVY2Uc)7V{#LiZfW)GF(z;{kU%PJAPI>hu zqI2_MN&NP5VOfgAI&w9E0sm`ZWX?XgeZf%Hc~$QkBnuAHf;J9pwRBw)Eakn~A=-~O ztK*%BAq~^5)vuY&kTw5SY%AhprUCVxGTy`~K6-^=5>L36_oYU`nHpT2ltrXvuO0YJ zSG=t9(#kqk+wbPNCxlb7JfUhkeZ@K$iL1qyov`fc;c?Nu5P`24gqh%CR<}xDL|StG z22DD5i=lOOS@c-&wmQ?yUQy2;uX_fe4#bSf*GD}1CPkQ;@pn~}b6<_D! zTeT6!XaYP1M-B~=XTP3JN&0Vkl=tZ}&AnowWYbR->wMw1=zq~J$EN;()5PjyxXW*V zv$Fk};=e-=XXTPVKhHWVcT**$UV6LOO*b~?Sar8_mO86O;98hno%;$s?sL(f&_B#> zUeyE~kQ;lMDJ`89!glC0!&YddC_Ac~d^+tb9#v=T_wbvTf8Xel@{neEEuGNHmwp{1ODf{DIJx=X&C-_&-xqJD zaJMMwtj>NqiLxkR2L#%1DB}f#WbsBl{TE#Q76b!h1|2@Wjw*cSbJBHaz`g+-Hc^=& z_Z%K?o`x$ardqFpByrAHd@m2~Wh9?|Y;yyXNZ)BtD~c&g6E>IfHAzsF3y&7s>8J94 z)5TAsoN~A3m>j9lPdPza?Xtr%{l%JnA0@o>OhQpNXjtWgWBk6w%s`#&^I57AOsM7` zI_R}zd69+E9JHRfkRo_S&G3fdbA3ba`tD5Y#VmS{{^RP+`R+~Yruet_EiFhN?@a$A zlrHFf|C}hRT0}0vq0gJ%(46gr!Ro^XK{{gOlqZKNCEyS>I*i8)JCeEOQx(MhUkY){ z7u{>18sB>=$ikhKbGnuk|3WE(G!+O?N@@sj3_vpB$3ojEBx-EHpx3#UclE1n`+IC2 ztsk*gB;Pa3*xDoacJ4PzpKgZvb;7Nt#KWEsIJaN zv@ZT^BZ_;$)wy3Khokb{>!;KiTj`TBh>>pg7+cS5{0DeaXw{$br@Qc9814&4zXknY z=sAcX+=Mq;t+vhcdD?(n@_B1KGexOjhULBs+Rbg_rSu{W@(-3!9vJT2dwQt+S;%%uYD9=_)M^SuuGQaLs*z=^M#{}gjc zZ9qtcRt_`hO%!PxqCzSKuhuKBI5k+2s-Bpe?ptci;EU$wX79%j@y^~>_21T&i?wkW ze_exQnoJp}F!OHqM(;)_4o=v(Iz|8}wg1d@XN4=Ku&kE{_kXt!JfMLxLHq9_y_4nZ zh>lW}@5MS%DpgSQPUZF%yI08_>FI@1f^l#h7ye-si5vX8{uGi?pX}DKScWUMsG7gTh>s zPLeZxIE=5pi}gw-%94aY@S6jIRkzVg{R%0V=}#WHo@T zwA_3)Knz=1M`*q;lw5dO_qD}%jX>cvvG??R;1M=eiN$Esd*;}ViWo|5G7)RfMg1M$ zITJCC=wD1zb0F2Rt$-L!vsc7<&$*q%%sQ2BuW7N|0sy0JKGlkB=i$O+Kwh){TK5W))aZ=Qz*jeEWTqGl!o?;Tg;T0xUXR=Gl1FCYjt>9M)NJaF{cKWPnGCm>BbkQYKRg z(^tR3FqrLsZPi5%)b!E}!|HB{i5+C&woE=CjO;t!3I)So>Z~B z`?(Cj=;EV(7Xw7QWB~K&#@PR$dvgm5=;6{_%iVv}TuU6+e<(IPJU(jii)l$Z;t%|C zG1Ab96|~tB9^c{NfIH%@4X7e;i_hk1rdoht>H<}3#Ms|#*+cu9e6)9V%rBuC-BF~!64Zwzh?*ljOl!8SIZ~5(Q7LArZ>9W zuli!1krY^>p_>Ukg~hb?j*fv_JJS_vVE2z6XBDWrO1golb~r5WFU|L(y2TjVb~9l% zZ*<3J%`=<=h_L|s+g|URww=C6w8OiPvBOL zv;bo4Z`SmlDw9Vz*nPo8*Nv8wy4tu~P2jA4aoqobd_>Lp^y?s4MPg$Z$*8L13S`(L z#2>2eLh>Fg;t+VU#PyuQ$jO(^nT&wCCctUya(Z>Llq~($vLe`h+m)}q`PVs}&Wif+ zD)UMF6$lRV*=a5saRr|DKjagC!$g)PZ=tx?j*($S);`IpSwE;Aen$`03TOdLAcg*|W`V zAiBKUHCOO*pzdZO>GrGN%}8h=kQ?*_u&AV<{^@(%8hWmbl(;E(6|=wN5*`+}w+FQ3 z4H4qaHP4sMS4GA8DbcB&&fQSK`{e^V`daBjGW+rJcYqC%5KaZm>3*;q@W*wk=qVxp z2nskWFM2S;!WaA|(8rMrEzAG*_F|Gwc>@+$yEAk&c`_YbeS8ko147|;!ab5NYy#hx zhs3^If+i;xf18P-fAwnRz54PkwgO&|a{@lLHQj{!0}wDZZ~a)?*)VF;WN9mGnec{4 z?Msj3L=!;}p}yX|{996>Gp2yB!wxeDNnQNe$i1>69P|fMOKXN7Y8zg}2qbx@g`fHH zva-14FpfX}qAsX<`a)Cq?dkf-bMLu3x{~#AJ0i4%iZ5H$(EFmsS8kT!Fiyks!MsTX|cLe#5t8 zLgKfQ&mK5bwpDS9i9sdblnalBsdwGu_{HG%lOqxvzRxtXuXJ=HRkKaTY&y;PC?}|T z4-l_B>THh_QBukoeDkrwS=66>|Su z+lwiz+=`J>RGPUhb&$IxEajpg^@|rccLG-Mw@PtVcX$dasAi-4a^39TIt@ay8XsXXlA>}+VY{_ zjabto6)nv@J8$9alGf=gYamF82EBB3*kcBqE*A%!(d)s@4iiC^?=mz}Sb|XEguXdu zK@3r405#o3l`O1SQ=~`(&sl^aNT=tYU7;;=8h|=7^@;7WqABVNS zqI#oGqNU5Rki-bLO@J0O7H$)aA`K%e#=yxKq}#JJVShXLEb^sRo!%D8x#rINK21fe zrlcE1yKU2MIE`uqc-MzPnEm8ja@oyzzf(V z{0)Uh5zcoJ5mOg|-TG~Lps1R_r)S(<2mP(rO71`F1^taK4-CKARgI>i-3MU@8k$i{ zF#&H37qs1FsC}y3Yot9qF97niBIE4h^6Rm8YU&*&t**6DPV3CLVe{vVV%IW2|5=@E zkc8)@<%8Wt5FN@Zz-rn%O<>p0;Tvn1btYUIGI+gB67nnImseCmV)J3`%N_WeiA)9@ z{dE?{SGfQY$dr;PG#~U9wHv&2hUwMAj}a_sMts)UOR2D67}d52k|cmgsbIZX+x<1M1xmSQp~**moXEeMXnRXC63i3N6Zc z$4JCPYh)AsqxJOJU21W-8k!HS*QA=X9+l zToMah`%bQuS)V>GXvb7X#pwRN#ghb)hv_D-(G;ZJ2A# z+wBKOcpiM(NgNNnX!v6ky={ZAvLfP>>f`~~2!)`N#+KMipHzZ7X|$Y3dRJ+cZB${O zK`p8#Za^P6F74AU^g7sMEJc0FXp zvWkIP8y0eh9Da*>|7)<&Rla8duXq2;zBTh-egp~%VGI21X)3`#8^V#ya;9Dv^IseT z5AN@(Hysje28SydXy1P?k6Ll+LmY6XahgcKm7C&&Z0d99#mIjsWbPM|NiHr1C~D?E zc?G#vk}Uit@m6qu?Y6BSOoA;mz2I6K>PZKA{viN4+{NosHPP*-n{QV2zJ{_RpEM~g zpS{AO2fzTT6K_`pn|zFno!gavRsYs74nYxv4X#V=3zEi(*2tW+4%KE# z0Ps8eg}W08%XPovV+V@OScZSNCBdUwBWwmQm-q%A&H;c#z|kC$-#-*<*Ls$ty}hIA z|A=0Dhm#&+uuRkU>Zt@8J&ZfN9@yb}#{MDbhD3{^I^_==EJ?=+KhI+l6GX>>^Loup zrJj(XNc+Rq2RwLhj8q~wUCEy6vorq|st%Ftv!$a^o&LG&#ID^}KgdU8!M0P4eC_}j z`ETbbb`a{lrw1(SWmV&)x!#iB?=$S(d|R5|@*V{t6AjzPYvzp113@xK>OnVAd9YM5 zi^UX@(oxy6sz2jZHjrzg%_Yzw6SDsh`0A=I`j35JlUGaB2hrQThLyRwxkvIpfk5@i z3%%-(*Az9zoezUCb?9H#vNPv?*CiCd7slM#V-KyJYFh}AQkJ8%-f3GoP(o0ch^(9! zB??;c8>TrP0fjB*9v*695^EX$v(b3QcX!d*xiy+nikivqTi`Lzz-gYWqW7~b9s^** zBC<`tciCpI(Zrc1chg)>Z6Ieds0k|=rFM+^<%pS9hxDE zsdAwY^-siCVvVBFeVu-=C%*LHG8p60im`+IdU7sX#52CttyV=d8B|jHmiem;{HYvB zl;$D8(qiUP-wb=f&@iwF6cxSt=}HH^_!hA{x_&a4>wD1ZNUmiGkg9Lj)<@GUh%tBe z?y`ZE8*Rn}r!HT%i_1@Nc&~0)sOgDG(Y{XUF#yudz|5#x;#fR!Qh@3Gu)IupeQ^a_ zZl}=t?PJFBz_VA~vO3j345Y)G&#bL;3~kD*RQ!vC(K|c z;8@kc2k|6vkdQMror9Dg{XYFR0dY^O7kz@O4=16${s*Nm0*q~Z-!D(O6Ce%U8H#_} zU(_RfU{SL%jmTM|t!U%|s||nyVwk|=5Vo6ffaAqV5CR`_+X_(B12lJYG{W(rD9W>f zF>00j#wpd(5Hje~Y1ssI_VMZQ6TeiIo6%eoGVz-H@YlHAm4a@dE5w0j2mXZ7d+#eN zP7iSbIl|!L@_)eHzMxOZ*DrGU;=VS?D&e^Q!=+Qc0g;y)=y71s%SRC_mVpg>w}EA8 z7BzF{m}{*x^G&&=nhx}XY$gAW9~Or4s0sRD(`wtfm4 z(b%^)Wm!It?%gdTBUa!kIu7+-N=U=DB1nI^fLK+gIZtvSa>u(@dkuuQD^=8MhrC!W~Ujyq>)h2Qe|L^q$VVX|~i?md*K;DFP| z5JGLf@og|l{O~`(rn2@J!0qKbSEI`*aqywd4f=DDOC!w1F{&Gcti=t@S?4$LL&sRa zBz=rj8R!Z~1M*r|3}5APrgOPw!b^7jG2JP{tU12*6olp1C||HrE%bg_)Eq*9J_+Mc zT7Z3eLrJrKVjdAPNKv|MBU!3VmR3;bY?#OYk(V%#0ctaSaE3nzKAjIWL6;J4yYvPfw*9zEnPz;{&inH^*dh3~VilrMOv%V(o!(9~70~)a z^Eco$6n=4F1BvK!KHJzOyQZG<9ajdk3=Xm;UuP=4tQU*QAe3%{KUtx#8n|NgS@6YG zw4xPDEN`kT&xG?*vevzm#bShhA->c}G_Iz#>7H>LitSF6!&}c{DIvj8i&yUe%S=t2 z2V@cBC{Ww1N*2h)yCFPxuKYLs`7J3i0mYyBglbE<;#tIho#z`C(K>3HYwznP6x7+m zdVMl;@e+iQ3^hJe@t4?3DXaLs8vke;=CZl*VVMY`^aboPKTd=f-^RZa^6(;(-jzr@ z$cfB89A2%gZF2H-`JN>6b6i5)iqp{2(ko@#$~tQ-v_7x$=gew3hrKqEfb16$)QtD< z>#Gen+4set zN?#oQq9}xc6~fGn!wgIOoA+Ob)ke;tva|e8w>FkNxaQDlww{T9itlAy?SMmOSX@2G zdI#G~R0R~nW#{Fgv(touW*SANP*>WVDj^fW5OFeHawn_a zvV>(*R`D`?-(Zd3kv6von0KVtiXkWoKG%ch-~R`+q;7R;%^Isk zxu6FKa=lJ);ZtCvEA;bTNY4_8 z99iqId5m@Rz7DSj$Lot*4+Vug!itMwn!W4APGTy3c5x>Vb%3Wiqlhf=@kORJcKbUmOPVt-&~gJt6{3f{f%0JOjMhQS-nH z-VjZ4+b+`gtwqfZm1sS<#LS52-#`)eEe|{NSIE5s87oeSVgp$fGe-2bNTLSMtCIJn zQ!s=#_z-1?%qx`rlKNJiI#dwXRL7Dd+1{03}{CMgFy z-m$Cvx`3>msL3yLy~rPcbLAUb9cyE~ABdwE&JLWR%A_1P%%EfPoCM_3H=?`c98MJn z`mv6n5G|n9lUhMsFQ9?Sdvrh0{J6RU7regNgnDcyUR|DsKFa;$;!GRuCLTPFAS5Kr zZFO1Sxkd8%>%tzqs4MPH5MK;|PR)bjHM#z_11XR^n#7Yx{X0})+RI;c`F7Bq$n9-U zWICdjq}<V%cin}7#!sPx;|IMF#7@Yg3hOU_=YrzJB><~bDBo!5^T19j$X(Vtx9=`o)` zvBbT{gzEV$Mb8ErI~yLJL2 }dCJ83Q}m`sXh1xoT#1B|hj(KQ@<_2l9`f1~$Pm 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 f{Qp1j Date: Wed, 24 Jun 2026 03:40:23 +0300 Subject: [PATCH 029/140] Guard combat bug fix, added Chimera, balanced sarge, fixed bug and other stuff --- ChapterMaster.yyp | 2 + datafiles/data/weapons.json | 22 +++++++++ datafiles/images/units/Sarge.png | Bin 45359 -> 44235 bytes scripts/scr_add_vehicle/scr_add_vehicle.gml | 4 ++ scripts/scr_after_combat/scr_after_combat.gml | 1 + scripts/scr_clean/scr_clean.gml | 43 ++++++++++++++++++ .../scr_mission_functions.gml | 10 ++-- scripts/scr_roster/scr_roster.gml | 11 +++++ scripts/scr_trade/scr_trade.gml | 6 +++ scripts/scr_unit_size/scr_unit_size.gml | 1 + scripts/scr_zoom/scr_zoom.gml | 26 +++++++---- 11 files changed, 111 insertions(+), 15 deletions(-) diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index a7f0909ebe..c86b9984c9 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -523,6 +523,8 @@ {"$GMIncludedFile":"","%Name":"raid1.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"raid1.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"resources.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"resources.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, + {"$GMIncludedFile":"","%Name":"Guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, + {"$GMIncludedFile":"","%Name":"Sarge.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Sarge.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_advantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_advantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_disadvantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_disadvantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"pauldron.png","CopyToMask":-1,"filePath":"datafiles/main/chapter_symbols/darkangels","name":"pauldron.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index d728b35066..46cebb24fe 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1874,6 +1874,28 @@ ], "value": 70 }, + "Multi-Laser": { + "abbreviation": "MultiLas", + "ammo": 30, + "arp": 2, + "attack": { + "artifact": 220, + "master_crafted": 180, + "standard": 150 + }, + "description": "A rapid-firing laser array mounted on light Imperial vehicles such as the Chimera. Pours volley after volley of coherent energy into massed infantry and light targets.", + "melee_hands": 0, + "range": 10, + "ranged_hands": 0, + "spli": 6, + "tags": [ + "vehicle", + "heavy_ranged", + "las", + "turret" + ], + "value": 20 + }, "Multi-Melta": { "abbreviation": "MltMelt", "ammo": 8, diff --git a/datafiles/images/units/Sarge.png b/datafiles/images/units/Sarge.png index 59ac96dbf596e122721186072d091c24b5e4b98f..20ffb0db5540795e2488ce918927fcec8d32a702 100644 GIT binary patch literal 44235 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 literal 45359 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 }dCJ83Q}m`sXh1xoT#1B|hj(KQ@<_2l9`f1~$Pm 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 f{Qp1j 0) { + var _top = 0; + for (var _ti = 1; _ti < array_length(_killed_counts); _ti++) { + if (_killed_counts[_ti] > _killed_counts[_top]) { + _top = _ti; + } + } + _damage_data.unit_type = _killed_roles[_top]; + } + return; } diff --git a/scripts/scr_mission_functions/scr_mission_functions.gml b/scripts/scr_mission_functions/scr_mission_functions.gml index ac536289df..476f2b7e1b 100644 --- a/scripts/scr_mission_functions/scr_mission_functions.gml +++ b/scripts/scr_mission_functions/scr_mission_functions.gml @@ -141,7 +141,7 @@ function problem_end_turn_checks(){ return; } var _alert_text = "Inquisition Mission Failed: Investigate "; - var _disp_string = alter_dispostion(eFACTION.INQUISITION, -5); + var _disp_string = ""; alter_disposition(eFACTION.INQUISITION, -5); _alert_text += $"{name()}. {_disp_string}"; scr_alert("red", "mission_failed", _alert_text, 0, 0); scr_event_log("red", _alert_text); @@ -174,11 +174,11 @@ function problem_end_turn_checks(){ scr_event_log("", "Fleet embarks upon Crusade."); } else { // hit loyalty here - var _disp_hits = alter_dispostions([ + alter_dispositions([ [eFACTION.INQUISITION , -10], [eFACTION.IMPERIUM, -5], ]) - var _string = "No ships designated for Crusade. {_disp_hits}" + var _string = "No ships designated for Crusade." if (obj_controller.penitent == 1) { obj_controller.penitent_current = 0; _string += "Your penitence crusade has been lengthened for your failings"; @@ -196,7 +196,7 @@ function problem_end_turn_checks(){ } var _alert_text = "The Necron Tomb of planet "; - var _disp_string = alter_dispostion(eFACTION.INQUISITION, -8); + var _disp_string = ""; alter_disposition(eFACTION.INQUISITION, -8); _alert_text += $"{numeral_name} has not been deactivated in time. It has awakened, rank upon rank of Necrons pouring out to the planet's surface. The Inquisition is not pleased with your failure. {_disp_string}"; scr_popup("Inquisition Mission Failed", _alert_text, "necron_army", ""); scr_event_log("red", $"Inquisition Mission Failed: Bombing run failed; the Necron Tomb on {name()} has become active."); @@ -214,7 +214,7 @@ function problem_end_turn_checks(){ return; } var _planet_name = name(); - var _disp_string = alter_dispostion(eFACTION.INQUISITION, -3); + var _disp_string = ""; alter_disposition(eFACTION.INQUISITION, -3); var _alert_text = $"The Spyrer on {_planet_name} has been left unchecked. In the ensuing carnage some high-ranking officials have been killed, along with several Nobles. Panic is running amock in several parts of the hives and the Inquisition is less than pleased.{_disp_string}"; var _text = "Inquisition Mission Failed: The Spyrer on {_planet_name} was not removed."; scr_popup("Inquisition Mission Failed", _alert_text, "spyrer", ""); diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index df4e64114f..09bc1d0bda 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -751,6 +751,12 @@ function add_vehicle_to_battle(company, veh_index, is_local) { col = obj_controller.bat_rhino_column; new_combat.rhinos++; break; + // Chimera (guard transport) screens like a Rhino. This first drop parks it in the Rhino + // column; the dedicated Imperial Armor column arrives with the formation drop. + case "Chimera": + col = obj_controller.bat_rhino_column; + new_combat.rhinos++; + break; case "Predator": col = obj_controller.bat_predator_column; new_combat.predators++; @@ -798,6 +804,11 @@ function add_vehicle_to_battle(company, veh_index, is_local) { targ.veh_hp[targ.veh] = obj_ini.veh_hp[company][v] * 4; targ.veh_hp_multiplier[targ.veh] = 4; targ.veh_ac[targ.veh] = 40; + } else if (obj_ini.veh_role[company][v] == "Chimera") { + // Mirrors the enemy Chimera: HP 200 (base 100 x2), armour 30. + targ.veh_hp[targ.veh] = obj_ini.veh_hp[company][v] * 2; + targ.veh_hp_multiplier[targ.veh] = 2; + targ.veh_ac[targ.veh] = 30; } // STC Bonuses diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index c77228979c..23763fdf2b 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -98,6 +98,12 @@ function TradeAttempt(diplomacy) constructor { repeat (floor(_opt.number / GUARD_SQUAD_SIZE)) { scr_add_man("Guard Sergeant", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); } + // One Chimera transport is assigned per two squads (every 2 * GUARD_SQUAD_SIZE + // guardsmen) to carry and screen the levy. Vehicles live in the new_vehicles + // company; scr_add_vehicle berths them at the home planet or aboard a ship. + repeat (floor(_opt.number / (GUARD_SQUAD_SIZE * 2))) { + scr_add_vehicle("Chimera", obj_controller.new_vehicles); + } with (obj_ini) { scr_company_order(0); } diff --git a/scripts/scr_unit_size/scr_unit_size.gml b/scripts/scr_unit_size/scr_unit_size.gml index 4386d9a6c5..d943f560ac 100644 --- a/scripts/scr_unit_size/scr_unit_size.gml +++ b/scripts/scr_unit_size/scr_unit_size.gml @@ -6,6 +6,7 @@ function get_vehicle_size_map() { "Land Raider": 20, "Land Speeder": 5, "Whirlwind": 10, + "Chimera": 10, "Harlequin Troupe": 5, }; diff --git a/scripts/scr_zoom/scr_zoom.gml b/scripts/scr_zoom/scr_zoom.gml index 849e3bc075..b786239e9c 100644 --- a/scripts/scr_zoom/scr_zoom.gml +++ b/scripts/scr_zoom/scr_zoom.gml @@ -63,17 +63,23 @@ function scr_zoom_keys() { var old_y = camera_get_view_y(view_camera[0]); var old_w = camera_get_view_width(view_camera[0]); var old_h = camera_get_view_height(view_camera[0]); - var zoom_factor = 1 - zoom_speed * zoom_delta; - var new_w = old_w * zoom_factor; - var new_h = old_h * zoom_factor; - camera_set_view_size(view_camera[0], new_w, new_h); - var new_x = mouse_x_ - (mouse_x_ - old_x) * (new_w / old_w); - var new_y = mouse_y_ - (mouse_y_ - old_y) * (new_h / old_h); - camera_set_view_pos(view_camera[0], new_x, new_y) + // Guard against an uninitialised/zero-size camera (seen transiently just + // after a save load): old_w/old_h of 0 makes new_w/old_w a 0/0 NaN, which + // is written into obj_controller.x/y and hard-crashes later when obj_cursor + // flushes the collision grid with a NaN bounding box. + if (old_w > 0 && old_h > 0) { + var zoom_factor = 1 - zoom_speed * zoom_delta; + var new_w = old_w * zoom_factor; + var new_h = old_h * zoom_factor; + camera_set_view_size(view_camera[0], new_w, new_h); + var new_x = mouse_x_ - (mouse_x_ - old_x) * (new_w / old_w); + var new_y = mouse_y_ - (mouse_y_ - old_y) * (new_h / old_h); + camera_set_view_pos(view_camera[0], new_x, new_y) - // update obj_controller as the new center of the view - obj_controller.x = new_x + new_w / 2; - obj_controller.y = new_y + new_h / 2; + // update obj_controller as the new center of the view + obj_controller.x = new_x + new_w / 2; + obj_controller.y = new_y + new_h / 2; + } camera_set_view_target(view_camera[0], old_target); } From 2180f0de5caee86b1252b29d89fe60c8be2cfb93 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 24 Jun 2026 04:17:05 +0300 Subject: [PATCH 030/140] Changed Lasgun Spli 2 to Spli 1 Guardsmen failed to do chip damage against cultists, and the culprit was that for some reason i assigned splash damage to the lasgun (Every weapon has it) so now it doessn't and does damage not divided by 2 basically --- datafiles/data/weapons.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index 46cebb24fe..e37cb32a68 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1664,7 +1664,7 @@ "melee_hands": 0, "range": 12, "ranged_hands": 1, - "spli": 2, + "spli": 1, "tags": [ "las" ], From e4899b4a78b94dc919b87ea79bca605d66acb6e8 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 25 Jun 2026 10:57:15 +0300 Subject: [PATCH 031/140] Update scr_player_ship_functions.gml --- .../scr_player_ship_functions.gml | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml index beee217c42..7b39c1e4b6 100644 --- a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml +++ b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml @@ -474,6 +474,24 @@ function ship_bombard_score(ship_id) { // Navy uses, so deployed Guard plug straight into the ground-war AI. // ===================================================================== +/// @description Pad the parallel Guard arrays out to ship[] length so that indexing +/// ship_guardsmen[i] by a ship index is always safe. ship_guardsmen starts +/// empty and only grows as ships are added during play, so a loaded save +/// (especially one predating these arrays) can restore ship[] while leaving +/// ship_guardsmen shorter or empty. Without this, reading ship_guardsmen[i] +/// for a real ship throws "index out of range". +function ensure_ship_guardsmen_arrays() { + with (obj_ini) { + var _n = array_length(ship); + while (array_length(ship_guardsmen) < _n) { + array_push(ship_guardsmen, 0); + } + while (array_length(ship_guardsmen_max) < _n) { + array_push(ship_guardsmen_max, 0); + } + } +} + /// @description Total Imperial Guard auxilia currently embarked across all player ships. /// @returns {real} function player_guardsmen_embarked() { @@ -508,6 +526,7 @@ function embark_guardsmen(system_name, planet) { } var _loaded = 0; + ensure_ship_guardsmen_arrays(); with (obj_ini) { for (var i = 0; i < array_length(ship); i++) { if (ship[i] == "") continue; // empty roster slot @@ -538,6 +557,7 @@ function deploy_guardsmen(system_name, planet) { } var _unloaded = 0; + ensure_ship_guardsmen_arrays(); with (obj_ini) { for (var i = 0; i < array_length(ship); i++) { if (ship[i] == "") continue; @@ -589,6 +609,7 @@ function tithe_guardsmen(system_name, planet, amount) { /// @param {string} system_name /// @returns {real} function player_guardsmen_at(system_name) { + ensure_ship_guardsmen_arrays(); var _total = 0; with (obj_ini) { for (var i = 0; i < array_length(ship); i++) { From e87e7e6a641bf3ca681f6a4eeb5be61e5a9f30c3 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 25 Jun 2026 14:47:02 +0300 Subject: [PATCH 032/140] Rebalanced Space Hulk strip/tow rewards and updated Auxilia recruitment handling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Space Hulk changes: Rebalanced the Space Hulk strip/tow choice. Stripping a Hulk now gives stronger immediate rewards: around 1000 requisition, 1–3 mostly tainted artifacts, and a rare STC fragment chance. Added stronger consequences for stripping Hulks: Mechanicus disposition loss, Inquisition suspicion, and a -25 loyalty penalty. The loyalty penalty affects both visible and hidden loyalty values so the cost cannot be erased through normal inspection logic. Towing a Hulk now gives +12 Mechanicus disposition, around 100 requisition, and one minor untainted artifact. Towing is now the safer diplomatic option, while stripping is the greedy but risky option. STC fragments from stripped Hulks are rare, so the player cannot reliably offset the Mechanicus penalty by gifting the STC back. Even if an STC is gifted back, it only repairs Mechanicus disposition and does not undo the loyalty or suspicion penalties. Confirmed that Mechanicus disposition appears to work mainly through trade/access thresholds rather than a simple linear price-discount formula. Kept the changes focused inside the existing Space Hulk strip/tow logic without rewriting artifact, loyalty, trade, or Inquisition systems. Auxilia recruitment changes: Increased Guardsman recruitment cost to 200 requisition per 1000 Guardsmen. Made the recruitment disposition penalty scale with purchase size instead of using a flat penalty. Small purchases now cause a smaller disposition hit, with a minimum penalty of -1. Larger purchases now cause a larger hit, with 2000 Guardsmen intended to apply around -10 disposition. Fixed recruited Chimeras being assigned to 1st Company instead of the Auxilia company. Chimeras should now appear with the Auxilia force after recruitment instead of being misplaced. Autogun / Predator investigation: Investigated the reported autogun-vs-Predator issue. Confirmed that basic autoguns should not be able to penetrate Predator armor under the current damage formula. The reported “Autoguns killed Predators” result appears to be a combat log / casualty attribution issue rather than real autogun damage. Left the combat log attribution issue for a separate focused fix. Notes for reviewers: Space Hulk stripping is now more rewarding but carries meaningful political and loyalty consequences. Towing Hulks now rewards Mechanicus cooperation without giving excessive direct loot. Guardsman recruitment is more expensive and now scales its disposition penalty by amount purchased. Chimeras should now be assigned to the correct Auxilia company. No broad combat rewrite was included in this commit. --- .../scr_post_battle_events.gml | 41 ++++++++++++++++--- scripts/scr_trade/scr_trade.gml | 17 ++++---- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/scripts/scr_post_battle_events/scr_post_battle_events.gml b/scripts/scr_post_battle_events/scr_post_battle_events.gml index af2d78d688..be55ab8b40 100644 --- a/scripts/scr_post_battle_events/scr_post_battle_events.gml +++ b/scripts/scr_post_battle_events/scr_post_battle_events.gml @@ -181,12 +181,37 @@ function space_hulk_explore_battle_aftermath() { /// Raises Inquisitorial suspicion and angers the Mechanicus, but yields requisition and a relic /// that carries the normal chance of chaos/daemonic taint. Removes the hulk from the map. function space_hulk_strip() { + // --- Penalties (tunable) --- + // Inquisition takes note; the Mechanicus consider the claim theft from the Omnissiah. obj_ini.chapter_data.chapter_suspicion = clamp(obj_ini.chapter_data.chapter_suspicion + 1, -5, 5); obj_controller.disposition[eFACTION.MECHANICUS] = clamp(obj_controller.disposition[eFACTION.MECHANICUS] - 12, 0, 100); + // The uncancellable cost of hoarding forbidden discoveries: Chapter standing drops a tier + // (100 -> 75 leaves the >=85 "Loyal" band). Both visible and hidden loyalty fall, the same + // idiom the existing crime penalties use, so it persists through Inquisition inspections. + // Gifting any recovered STC to the Mechanicus can repair their disposition, never this. + var _loyalty_hit = 25; + obj_controller.loyalty = clamp(obj_controller.loyalty - _loyalty_hit, 0, 100); + obj_controller.loyalty_hidden = clamp(obj_controller.loyalty_hidden - _loyalty_hit, 0, 100); - var _reqi = irandom_range(20, 40) * 10; + // --- Rewards (tunable) --- + var _reqi = irandom_range(80, 120) * 10; // ~1000 Requisition obj_controller.requisition += _reqi; - scr_add_artifact("random", "random", 4, hulk_loot_loc, hulk_loot_ship + 500); + + // 1-3 relics, most carrying chaos/daemonic taint. ~65% are forced daemonic; the rest still + // roll the normal ~30% taint chance, so the overall haul is dangerous more often than not. + var _arts = irandom_range(1, 3); + for (var _a = 0; _a < _arts; _a++) { + var _art_tags = (random(1) < 0.65) ? "daemonic" : "random"; + scr_add_artifact("random", _art_tags, 4, hulk_loot_loc, hulk_loot_ship + 500); + } + + // Rare STC fragment in the haul. Kept low on purpose: a guaranteed STC would let the player + // gift it back to the Mechanicus and buy back the disposition they just lost (the loyalty + // hit above is what they can never undo). + var _found_stc = (random(1) < 0.20); + if (_found_stc) { + scr_add_stc_fragment(); + } if (instance_exists(hulk_star)) { with (hulk_star) { @@ -203,7 +228,8 @@ function space_hulk_strip() { image = "space_hulk_done"; title = "Space Hulk Stripped"; - text = $"Your Chapter strips the hulk for itself. Archeotech and a relic are hauled aboard and {_reqi} Requisition worth of materiel is salvaged. The unsanctioned claim will not go unnoticed: the Adeptus Mechanicus consider it theft from the Omnissiah, and the Inquisition's gaze lingers a little longer on your Chapter."; + var _stc_line = _found_stc ? " An intact STC fragment is prised from the wreck and spirited away." : ""; + text = $"Your Chapter strips the hulk for itself. {_arts} relic(s) and {_reqi} Requisition worth of archeotech are hauled aboard.{_stc_line} The unsanctioned claim will not go unnoticed: the Adeptus Mechanicus consider it theft from the Omnissiah, the Inquisition's gaze lingers, and the Chapter's standing suffers for hoarding forbidden discoveries."; reset_popup_options(); cooldown = 20; } @@ -212,11 +238,16 @@ function space_hulk_strip() { /// obj_popup scope. The sanctioned, expected course: the Mechanicus are grateful and send a /// token of thanks. Removes the hulk from the map. function space_hulk_surrender() { + // --- Rewards (tunable): the payoff here is Mechanicus favour, not loot. --- obj_controller.disposition[eFACTION.MECHANICUS] = clamp(obj_controller.disposition[eFACTION.MECHANICUS] + 12, 0, 100); - var _reqi = irandom_range(5, 15) * 10; + var _reqi = irandom_range(8, 12) * 10; // ~100 Requisition, a token of thanks obj_controller.requisition += _reqi; + // A single minor, untainted relic of the sort the Mechanicus part with in trade. No major + // relic wargear here: the Mechanicus are stingy and keep their best for themselves. + scr_add_artifact("random_nodemon", "minor", 4, hulk_loot_loc, hulk_loot_ship + 500); + if (instance_exists(hulk_star)) { with (hulk_star) { instance_destroy(); @@ -232,7 +263,7 @@ function space_hulk_surrender() { image = "space_hulk_done"; title = "Space Hulk Surrendered"; - text = $"The hulk is towed to the nearest Forge World for the Adeptus Mechanicus to pick apart at their leisure. They receive it gratefully and send a token of thanks worth {_reqi} Requisition."; + text = $"The hulk is towed to the nearest Forge World for the Adeptus Mechanicus to pick apart at their leisure. They receive it gratefully, their disposition toward your Chapter warms, and they send a token of thanks worth {_reqi} Requisition along with a minor relic from their archives."; reset_popup_options(); cooldown = 20; } diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 23763fdf2b..327d8ad3ab 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -17,7 +17,7 @@ function TradeAttempt(diplomacy) constructor { "Inferno Bolts": 5, "Sister of Battle": 40, "Sister Hospitaler": 75, - "Guardsman": 0.05, + "Guardsman": 0.2, "Eldar Power Sword": 50, "Archeotech Laspistol": 150, "Ranger": 100, @@ -99,18 +99,21 @@ function TradeAttempt(diplomacy) constructor { scr_add_man("Guard Sergeant", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); } // One Chimera transport is assigned per two squads (every 2 * GUARD_SQUAD_SIZE - // guardsmen) to carry and screen the levy. Vehicles live in the new_vehicles - // company; scr_add_vehicle berths them at the home planet or aboard a ship. + // guardsmen) to carry and screen the levy. They muster into the Auxilia company + // (company 0) alongside the guardsmen, not the transient new_vehicles staging + // company, so they stay grouped with the levy and persist after the battle + // instead of being reorganised out of the build-staging slot. repeat (floor(_opt.number / (GUARD_SQUAD_SIZE * 2))) { - scr_add_vehicle("Chimera", obj_controller.new_vehicles); + scr_add_vehicle("Chimera", 0); } with (obj_ini) { scr_company_order(0); } // Space Marines commandeering Imperial Guard is frowned upon since the - // Heresy and the reign of Goge Vandire, so the Sector Governor's regard - // dips a little each time. The hit is small and one-off per levy. - alter_disposition(diplomacy_faction, -2); + // Heresy and the reign of Goge Vandire, so the Sector Governor's regard dips + // with the size of the levy: about 1 per 200 raised (so a full 2000 costs 10), + // floored at 1 so even a token request costs a little standing. + alter_disposition(diplomacy_faction, -max(1, round(_opt.number / 200))); } else { // Every other mercenary type arrives by trade convoy. if (!struct_exists(trading_object, "mercenaries")) { From 00f6836869d0de1abdadc3a821a8592356f0dc5c Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 25 Jun 2026 15:02:50 +0300 Subject: [PATCH 033/140] Fixed enemy attacks reporting casualties they did not cause in the combat log Root cause: lost[]/lost_num[] on the player column are a per-attack scratch tally that scr_flavor2 reads to build its "X units lost" text. obj_pnunit Step_0 only clears that tally once per frame, while several enemy blocks attack the same column within a single frame. scr_flavor2 clears the tally at its end, but several early-exit paths (suppressed empty/zero-shot attacks, and the wall-destroyed guard) return before that reset runs. A block that did kill units (e.g. melee genestealers/lictors destroying Predators) could leave its casualties in the tally, and the next block to fire at that column would read and re-report them. This produced lines like "8 Autoguns strike at Predator. 4 Predators lost." even though autoguns (60 dmg, AP1) deal 0 damage to a Predator (AC 40): 60 - 40*6 = 0. The Predators were killed in melee; the autogun volley only inherited the count. Fix: Clear lost[]/lost_num[] at the start of scr_clean, before damage is applied, so each attack builds and reports only its own casualties. No damage math or balance was changed; this is a combat-log attribution fix only. Notes for reviewers: The lost_num tally and the wall-destroyed early-exit both exist upstream, so this mis-attribution can occur upstream as well (notably after a wall is destroyed mid-turn). The fix is on shared code and should port upstream cleanly." --- scripts/scr_clean/scr_clean.gml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index 97e8a2dc27..65eb8123b7 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -146,6 +146,17 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam "is_vehicle": false, }; + // Scope the casualty breakdown to THIS attack. lost[]/lost_num[] are the column's + // per-attack scratch tally that scr_flavor2 reads to build its "X Foo lost" text. + // scr_flavor2 clears them at its end, but fork-added early-exits (suppressed empty or + // zero-shot attacks, a destroyed wall) can return before that reset, leaving a previous + // attack's casualties in place. A later attack that inflicts nothing of its own (e.g. + // autoguns pinging off a Predator's AC40 armour for zero damage) would then read and + // mis-report those stale kills as "8 Autoguns strike at Predator. 4 Predators lost." + // Clearing here guarantees the breakdown reflects only what this attack actually kills. + lost = []; + lost_num = []; + // ### Vehicle Damage Processing ### if (!target_is_infantry && veh > 0) { damage_vehicles(damage_data, hostile_shots, hostile_damage, weapon_index_position); From 475f079a7ec62678e6423beb85d85715732e3ce0 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 25 Jun 2026 19:12:43 +0300 Subject: [PATCH 034/140] Preesync Alignment Aligning my stuff with main so i can merge without issue --- ChapterMaster.yyp | 1 + objects/obj_star_select/Draw_64.gml | 5 +++-- .../scr_mission_functions.gml | 17 +++++++++-------- scripts/scr_zoom/scr_zoom.gml | 4 ---- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index c86b9984c9..79fe03c2e5 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -524,6 +524,7 @@ {"$GMIncludedFile":"","%Name":"resources.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"resources.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, + {"$GMIncludedFile":"","%Name":"sarge.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"sarge.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Sarge.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Sarge.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_advantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_advantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_disadvantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_disadvantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, diff --git a/objects/obj_star_select/Draw_64.gml b/objects/obj_star_select/Draw_64.gml index 30409ed3a6..92b0e3f5de 100644 --- a/objects/obj_star_select/Draw_64.gml +++ b/objects/obj_star_select/Draw_64.gml @@ -283,9 +283,10 @@ try { tooltip_draw(defence_data[1], 400); } - if (garrison.dispo_change > 55) { + var _dispo_change = garrison.dispo_change; + if (_dispo_change > 55) { draw_text(xx + 20, half_way + 30, $"Garrison Disposition Effect : Positive"); - } else if (garrison.dispo_change > 44 || garrison.dispo_change == 0) { + } else if (_dispo_change > 44 || _dispo_change == 0) { draw_text(xx + 20, half_way + 30, $"Garrison Disposition Effect : Neutral"); } else { draw_text(xx + 20, half_way + 30, $"Garrison Disposition Effect : Negative"); diff --git a/scripts/scr_mission_functions/scr_mission_functions.gml b/scripts/scr_mission_functions/scr_mission_functions.gml index 476f2b7e1b..84a494ae52 100644 --- a/scripts/scr_mission_functions/scr_mission_functions.gml +++ b/scripts/scr_mission_functions/scr_mission_functions.gml @@ -141,8 +141,8 @@ function problem_end_turn_checks(){ return; } var _alert_text = "Inquisition Mission Failed: Investigate "; - var _disp_string = ""; alter_disposition(eFACTION.INQUISITION, -5); - _alert_text += $"{name()}. {_disp_string}"; + alter_disposition(eFACTION.INQUISITION, -5); + _alert_text += $"{name()}."; scr_alert("red", "mission_failed", _alert_text, 0, 0); scr_event_log("red", _alert_text); remove_problem("recon"); @@ -177,8 +177,8 @@ function problem_end_turn_checks(){ alter_dispositions([ [eFACTION.INQUISITION , -10], [eFACTION.IMPERIUM, -5], - ]) - var _string = "No ships designated for Crusade." + ]); + var _string = $"No ships designated for Crusade."; if (obj_controller.penitent == 1) { obj_controller.penitent_current = 0; _string += "Your penitence crusade has been lengthened for your failings"; @@ -196,8 +196,8 @@ function problem_end_turn_checks(){ } var _alert_text = "The Necron Tomb of planet "; - var _disp_string = ""; alter_disposition(eFACTION.INQUISITION, -8); - _alert_text += $"{numeral_name} has not been deactivated in time. It has awakened, rank upon rank of Necrons pouring out to the planet's surface. The Inquisition is not pleased with your failure. {_disp_string}"; + alter_disposition(eFACTION.INQUISITION, -8); + _alert_text += $"{numeral_name} has not been deactivated in time. It has awakened, rank upon rank of Necrons pouring out to the planet's surface. The Inquisition is not pleased with your failure."; scr_popup("Inquisition Mission Failed", _alert_text, "necron_army", ""); scr_event_log("red", $"Inquisition Mission Failed: Bombing run failed; the Necron Tomb on {name()} has become active."); @@ -214,8 +214,8 @@ function problem_end_turn_checks(){ return; } var _planet_name = name(); - var _disp_string = ""; alter_disposition(eFACTION.INQUISITION, -3); - var _alert_text = $"The Spyrer on {_planet_name} has been left unchecked. In the ensuing carnage some high-ranking officials have been killed, along with several Nobles. Panic is running amock in several parts of the hives and the Inquisition is less than pleased.{_disp_string}"; + alter_disposition(eFACTION.INQUISITION, -3); + var _alert_text = $"The Spyrer on {_planet_name} has been left unchecked. In the ensuing carnage some high-ranking officials have been killed, along with several Nobles. Panic is running amock in several parts of the hives and the Inquisition is less than pleased."; var _text = "Inquisition Mission Failed: The Spyrer on {_planet_name} was not removed."; scr_popup("Inquisition Mission Failed", _alert_text, "spyrer", ""); scr_event_log("red", _text); @@ -549,6 +549,7 @@ function complete_garrison_mission(problem_index) { remove_problem("provide_garrison"); return; } + garrisons.update(); if (current_owner != eFACTION.IMPERIUM || !garrisons.garrison_force) { remove_problem("provide_garrison"); diff --git a/scripts/scr_zoom/scr_zoom.gml b/scripts/scr_zoom/scr_zoom.gml index b786239e9c..a3a28e4d6d 100644 --- a/scripts/scr_zoom/scr_zoom.gml +++ b/scripts/scr_zoom/scr_zoom.gml @@ -63,10 +63,6 @@ function scr_zoom_keys() { var old_y = camera_get_view_y(view_camera[0]); var old_w = camera_get_view_width(view_camera[0]); var old_h = camera_get_view_height(view_camera[0]); - // Guard against an uninitialised/zero-size camera (seen transiently just - // after a save load): old_w/old_h of 0 makes new_w/old_w a 0/0 NaN, which - // is written into obj_controller.x/y and hard-crashes later when obj_cursor - // flushes the collision grid with a NaN bounding box. if (old_w > 0 && old_h > 0) { var zoom_factor = 1 - zoom_speed * zoom_delta; var new_w = old_w * zoom_factor; From 9c5740ac93cd4714c7cb22430d6ac7d20cfd4a8b Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 25 Jun 2026 20:25:00 +0300 Subject: [PATCH 035/140] Buyable Leman Russ from the Mechanicus; fix Guardsman levy cost Adds the Leman Russ battle tank as an Astra Militarum Auxilia asset and corrects guardsman levy pricing. Leman Russ: - Purchasable from the Adeptus Mechanicus trade screen (faction 3), gated at 40 disposition, since the Mechanicus forge it. Not sold by the Sector Governor. - Musters into the Auxilia company (company 0) with the guardsmen and Chimeras, so it stays grouped with the levy and persists after battle. - New "Battle Cannon" player vehicle weapon (AP4 anti-armour with splash 8 anti-infantry), modelled on the existing enemy Battle Cannon; default loadout is Battle Cannon turret + hull Heavy Bolter. - Deploys to the armour (Predator) column with HP 300 (base x3) and armour 40, mirroring the enemy Leman Russ Battle Tank. - Registered deploy size and a post-battle recovery priority of 3 (above Chimera, below Marine heavies). - Costs 800 requisition each; purchase reduces Mechanicus disposition by 1 per tank (floor of 1). Guardsman cost fix: - The pure-guardsman levy had a hardcoded flat cost of 0.05 req each (50 per 1000), separate from the trade value. Bumped to 0.1 each, so 1000 guardsmen now cost 100 req. - Aligned the Guardsman trade value to 0.1 for consistency in mixed trades. - Disposition penalty unchanged (already scales at ~1 per 200 raised, i.e. 5 for 1000). Balance values are a tunable first pass. --- datafiles/data/weapons.json | 24 ++++++++++++++++++- scripts/scr_add_vehicle/scr_add_vehicle.gml | 6 +++++ scripts/scr_after_combat/scr_after_combat.gml | 1 + scripts/scr_roster/scr_roster.gml | 11 +++++++++ scripts/scr_trade/scr_trade.gml | 22 ++++++++++++++--- scripts/scr_unit_size/scr_unit_size.gml | 1 + 6 files changed, 61 insertions(+), 4 deletions(-) diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index e37cb32a68..61fdf4dcb7 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -121,6 +121,28 @@ ], "value": 30 }, + "Battle Cannon": { + "abbreviation": "BtlCnn", + "ammo": 12, + "arp": 4, + "attack": { + "artifact": 1000, + "master_crafted": 800, + "standard": 650 + }, + "description": "The main armament of the Leman Russ battle tank. A high-calibre cannon firing massive shells that crack armour and scatter massed infantry alike, the versatile mainstay of Astra Militarum armoured companies.", + "melee_hands": 0, + "range": 18, + "ranged_hands": 0, + "spli": 8, + "tags": [ + "vehicle", + "heavy_ranged", + "explosive", + "turret" + ], + "value": 40 + }, "Boarding Shield": { "abbreviation": "BrdShld", "armour_value": { @@ -3377,4 +3399,4 @@ "xenos" ] } -} \ No newline at end of file +} diff --git a/scripts/scr_add_vehicle/scr_add_vehicle.gml b/scripts/scr_add_vehicle/scr_add_vehicle.gml index 07866dc678..84aa44a806 100644 --- a/scripts/scr_add_vehicle/scr_add_vehicle.gml +++ b/scripts/scr_add_vehicle/scr_add_vehicle.gml @@ -127,6 +127,12 @@ function scr_add_vehicle(vehicle_type, target_company, otherdata = {}, weapon1 = obj_ini.veh_wep1[target_company][good] = "Multi-Laser"; obj_ini.veh_wep2[target_company][good] = "Heavy Bolter"; } + if (vehicle_type == "Leman Russ") { + // Battle Cannon turret (anti-armour and anti-infantry blast) with a hull + // Heavy Bolter, the standard Astra Militarum main battle tank loadout. + obj_ini.veh_wep1[target_company][good] = "Battle Cannon"; + obj_ini.veh_wep2[target_company][good] = "Heavy Bolter"; + } } obj_ini.veh_hp[target_company][good] = 100; diff --git a/scripts/scr_after_combat/scr_after_combat.gml b/scripts/scr_after_combat/scr_after_combat.gml index 8229b6c61a..cf4b78b28b 100644 --- a/scripts/scr_after_combat/scr_after_combat.gml +++ b/scripts/scr_after_combat/scr_after_combat.gml @@ -70,6 +70,7 @@ function add_vehicles_to_recovery() { "Whirlwind": 4, "Rhino": 3, "Land Speeder": 3, + "Leman Russ": 3, "Chimera": 2, "Bike": 1, }; diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 09bc1d0bda..1b1c1c00cd 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -761,6 +761,11 @@ function add_vehicle_to_battle(company, veh_index, is_local) { col = obj_controller.bat_predator_column; new_combat.predators++; break; + // Leman Russ (guard battle tank) anchors the armour line alongside the Predators. + case "Leman Russ": + col = obj_controller.bat_predator_column; + new_combat.predators++; + break; case "Land Raider": col = obj_controller.bat_landraider_column; new_combat.land_raiders++; @@ -809,6 +814,12 @@ function add_vehicle_to_battle(company, veh_index, is_local) { targ.veh_hp[targ.veh] = obj_ini.veh_hp[company][v] * 2; targ.veh_hp_multiplier[targ.veh] = 2; targ.veh_ac[targ.veh] = 30; + } else if (obj_ini.veh_role[company][v] == "Leman Russ") { + // Mirrors the enemy Leman Russ Battle Tank: heavy armour 40, HP 300 (base 100 x3), + // so it shrugs off small arms and trades blows with other tanks like a Predator. + targ.veh_hp[targ.veh] = obj_ini.veh_hp[company][v] * 3; + targ.veh_hp_multiplier[targ.veh] = 3; + targ.veh_ac[targ.veh] = 40; } // STC Bonuses diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 327d8ad3ab..80eedf1db1 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -17,7 +17,8 @@ function TradeAttempt(diplomacy) constructor { "Inferno Bolts": 5, "Sister of Battle": 40, "Sister Hospitaler": 75, - "Guardsman": 0.2, + "Guardsman": 0.1, + "Leman Russ": 800, "Eldar Power Sword": 50, "Archeotech Laspistol": 150, "Ranger": 100, @@ -114,6 +115,20 @@ function TradeAttempt(diplomacy) constructor { // with the size of the levy: about 1 per 200 raised (so a full 2000 costs 10), // floored at 1 so even a token request costs a little standing. alter_disposition(diplomacy_faction, -max(1, round(_opt.number / 200))); + } else if (_type == "Leman Russ") { + // The Adeptus Mechanicus forge and part with their tanks reluctantly. Each + // Leman Russ musters into the Auxilia company (company 0) alongside the guard + // levy so the force can field its own armour line, then the company is reordered + // so the tanks settle into their slots. + repeat (_opt.number) { + scr_add_vehicle("Leman Russ", 0); + } + with (obj_ini) { + scr_company_order(0); + } + // Handing over sacred war materiel costs the forge world some regard, one point + // per tank with a floor of one, so a larger order stings their disposition more. + alter_disposition(diplomacy_faction, -max(1, _opt.number)); } else { // Every other mercenary type arrives by trade convoy. if (!struct_exists(trading_object, "mercenaries")) { @@ -416,6 +431,7 @@ function TradeAttempt(diplomacy) constructor { new_demand_buttons(40, "Minor Artifact", "arti", 1); new_demand_buttons(25, "Skitarii", "merc", 200); new_demand_buttons(55, "Techpriest", "merc", 3); + new_demand_buttons(40, "Leman Russ", "merc", 10); break; case 4: new_demand_buttons(25, "Crusader", "merc", 5); @@ -713,7 +729,7 @@ function TradeAttempt(diplomacy) constructor { // Guardsmen are abundant Imperial line troops the Sector Governor hands over by the // thousand, not a haggled rarity, so the base trade overhead does not apply to a - // pure Guard levy. They cost a flat 0.05 requisition each (50 per 1000). If the + // pure Guard levy. They cost a flat 0.1 requisition each (100 per 1000). If the // offered requisition covers the guardsmen demanded the Governor obliges outright, // otherwise he declines. Only triggers when guardsmen are the sole demand, so it // cannot be used to slip other goods through cheaply. @@ -735,7 +751,7 @@ function TradeAttempt(diplomacy) constructor { _req_offered += offer_options[ri].number; } } - deal_chance = _req_offered >= ceil(_guard_num * 0.05) ? 100 : 0; + deal_chance = _req_offered >= ceil(_guard_num * 0.1) ? 100 : 0; } var _chance = clamp(floor((deal_chance / 20)), 0, 6); diff --git a/scripts/scr_unit_size/scr_unit_size.gml b/scripts/scr_unit_size/scr_unit_size.gml index d943f560ac..8685d0600a 100644 --- a/scripts/scr_unit_size/scr_unit_size.gml +++ b/scripts/scr_unit_size/scr_unit_size.gml @@ -7,6 +7,7 @@ function get_vehicle_size_map() { "Land Speeder": 5, "Whirlwind": 10, "Chimera": 10, + "Leman Russ": 10, "Harlequin Troupe": 5, }; From dd2f370e0fa1b317d8a9b9b96880d31335256550 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 25 Jun 2026 20:38:53 +0300 Subject: [PATCH 036/140] Update scr_trade.gml --- scripts/scr_trade/scr_trade.gml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 80eedf1db1..3f729bd331 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -99,12 +99,12 @@ function TradeAttempt(diplomacy) constructor { repeat (floor(_opt.number / GUARD_SQUAD_SIZE)) { scr_add_man("Guard Sergeant", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); } - // One Chimera transport is assigned per two squads (every 2 * GUARD_SQUAD_SIZE - // guardsmen) to carry and screen the levy. They muster into the Auxilia company - // (company 0) alongside the guardsmen, not the transient new_vehicles staging - // company, so they stay grouped with the levy and persist after the battle - // instead of being reorganised out of the build-staging slot. - repeat (floor(_opt.number / (GUARD_SQUAD_SIZE * 2))) { + // One Chimera transport is assigned per 200 guardsmen to carry and screen the + // levy. They muster into the Auxilia company (company 0) alongside the guardsmen, + // not the transient new_vehicles staging company, so they stay grouped with the + // levy and persist after the battle instead of being reorganised out of the + // build-staging slot. + repeat (floor(_opt.number / 200)) { scr_add_vehicle("Chimera", 0); } with (obj_ini) { @@ -422,7 +422,7 @@ function TradeAttempt(diplomacy) constructor { switch (diplomacy_faction) { case 2: new_demand_buttons(0, "Requisition", "req"); - new_demand_buttons(0, "Guardsman", "merc", 2000); + new_demand_buttons(35, "Guardsman", "merc", 2000); new_demand_buttons(0, "Recruiting Planet", "license", 1); new_demand_buttons(0, "License: Repair", "license", 1); new_demand_buttons(0, "License: Crusade", "license", 1); From e146e2a8110f019d204442d1aab0a8480086049c Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 26 Jun 2026 00:50:47 +0300 Subject: [PATCH 037/140] fix: Chimeras and Leman Russ despawning after battle and on save load, ship STC discount values do not match the panel, STC discounts apply to forge cost only Fixed Auxilia vehicles vanishing after combat (and on save/load), not destroyed, just silently erased. Root cause: - scr_vehicle_order rebuilds each company's vehicle arrays from a hardcoded whitelist of roles, resets every slot, then writes back only whitelisted vehicles. Chimera and Leman Russ were absent, so they were wiped. obj_ncombat Alarm_7 calls this on all companies 0-10 after every battle, so they despawned each fight regardless of which company they were in. - scr_start_load uses the same hardcoded vehicle list to distribute vehicles onto ships on load; Chimera and Leman Russ were missing, so a fleet-based chapter would lose them on save/reload. Fix: - Added "Chimera" and "Leman Russ" to the role whitelist in scr_vehicle_order. - Added them to the vehicle list in scr_start_load. Note for reviewers: these hardcoded vehicle whitelists silently delete any unlisted vehicle role post-battle. Consider consolidating them to a single source (e.g. the scr_unit_size vehicle map) so new vehicles cannot regress this way. Also fixed the STC issues reported by the player, so now they should accurately represent discounts. --- scripts/Armamentarium/Armamentarium.gml | 8 +++++++- scripts/scr_start_load/scr_start_load.gml | 2 +- scripts/scr_vehicle_order/scr_vehicle_order.gml | 4 +++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/Armamentarium/Armamentarium.gml b/scripts/Armamentarium/Armamentarium.gml index 671e5e9f66..360c61c0f5 100644 --- a/scripts/Armamentarium/Armamentarium.gml +++ b/scripts/Armamentarium/Armamentarium.gml @@ -785,7 +785,13 @@ function Armamentarium(_controller) constructor { } break; case "ships": - discount_stc = controller.stc_ships * 5; + // Tiered discount matching the STC panel descriptions and the real + // per-level feature unlocks. 8% at L1, 16% at L3, 25% at L5, held + // across the feature levels (L2 Hull, L4 Armour, L6 Warp). The old + // stc_ships * 5 gave 5/10/15/20/25/30, which mismatched every label + // and overshot the 25% cap at L6. + var _ship_tiers = [0, 8, 8, 16, 16, 25, 25]; + discount_stc = _ship_tiers[clamp(controller.stc_ships, 0, STC_MAX_LEVEL)]; if (discount_stc > 0) { global_cost_tooltip += $"Ship STC: -{discount_stc}%\n"; } diff --git a/scripts/scr_start_load/scr_start_load.gml b/scripts/scr_start_load/scr_start_load.gml index f35b38b27d..b4e9658a27 100644 --- a/scripts/scr_start_load/scr_start_load.gml +++ b/scripts/scr_start_load/scr_start_load.gml @@ -55,7 +55,7 @@ function scr_start_load(fleet, load_from_star, load_options) { } } // i feel like there definatly is or should be a generic function for this???? - var _vehicles = ["Rhino", "Predator", "Land Speeder", "Land Raider", "Whirlwind"]; + var _vehicles = ["Rhino", "Predator", "Land Speeder", "Land Raider", "Whirlwind", "Chimera", "Leman Russ"]; function load_vehicles(_companies, _equip, _ship, size) { obj_ini.veh_wid[_companies][_equip] = 0; obj_ini.veh_lid[_companies][_equip] = _ship; diff --git a/scripts/scr_vehicle_order/scr_vehicle_order.gml b/scripts/scr_vehicle_order/scr_vehicle_order.gml index 8fa5e8c5e0..6272694c7a 100644 --- a/scripts/scr_vehicle_order/scr_vehicle_order.gml +++ b/scripts/scr_vehicle_order/scr_vehicle_order.gml @@ -48,7 +48,9 @@ function scr_vehicle_order(company_number) { || veh_role[company_number][i] == "Predator" || veh_role[company_number][i] == "Whirlwind" || veh_role[company_number][i] == "Land Speeder" - || veh_role[company_number][i] == "Land Raider"; + || veh_role[company_number][i] == "Land Raider" + || veh_role[company_number][i] == "Chimera" + || veh_role[company_number][i] == "Leman Russ"; if (_is_vehicle_role) { temp_race[company_number][vehicle_count] = veh_race[company_number][i]; From b22a685999a681660563f1614f6e73aecd63b8c5 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 26 Jun 2026 12:13:56 +0300 Subject: [PATCH 038/140] fix: NaN crash from fleet movement divide-by-zero at zero ETA Fixed a random crash (obj_cursor Create reporting invalid -nan bounds on obj_controller) caused by fleet positions going NaN. Root cause: - obj_p_fleet Alarm_1 computed spid = point_distance(...) / action_eta. With a fleet at its destination and action_eta == 0, this is 0/0 = NaN, so the fleet x/y became NaN. obj_p_fleet Alarm_3 copies the fleet position into obj_controller.x/y, so the controller's bounding box became NaN and the engine crashed on the next room entry when obj_cursor was created. - obj_en_fleet Alarm_1 had the same divide (orbiting = dos / action_eta) with no ETA guard, which could NaN an enemy fleet position and crash collision/nearest checks. Fix: - Both fleet movement steps now divide by max(1, action_eta). When the ETA is exhausted the fleet moves its full remaining distance and arrives, instead of dividing by zero. Normal in-transit movement is unchanged. Also changed Raptor gene seed mutation to better match founding chapter. --- datafiles/main/chapters/36.json | 4 ++-- objects/obj_en_fleet/Alarm_1.gml | 2 +- objects/obj_p_fleet/Alarm_1.gml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/datafiles/main/chapters/36.json b/datafiles/main/chapters/36.json index 8ab38f9e81..234df44b14 100644 --- a/datafiles/main/chapters/36.json +++ b/datafiles/main/chapters/36.json @@ -119,11 +119,11 @@ "ossmodula": 0, "membrane": 0, "zygote": 0, - "betchers": 0, + "betchers": 1, "catalepsean": 0, "secretions": 0, "occulobe": 0, - "mucranoid": 1 + "mucranoid": 0 }, "disposition": [ 0, // nothing diff --git a/objects/obj_en_fleet/Alarm_1.gml b/objects/obj_en_fleet/Alarm_1.gml index b29e6b9c6a..7dcc5e8375 100644 --- a/objects/obj_en_fleet/Alarm_1.gml +++ b/objects/obj_en_fleet/Alarm_1.gml @@ -444,7 +444,7 @@ try { var dos = 0; dos = point_distance(x, y, action_x, action_y); - orbiting = dos / action_eta; + orbiting = dos / max(1, action_eta); dir = point_direction(x, y, action_x, action_y); x = x + lengthdir_x(orbiting, dir); diff --git a/objects/obj_p_fleet/Alarm_1.gml b/objects/obj_p_fleet/Alarm_1.gml index 46203a0399..232a4a1c6e 100644 --- a/objects/obj_p_fleet/Alarm_1.gml +++ b/objects/obj_p_fleet/Alarm_1.gml @@ -40,7 +40,7 @@ try { } spid = point_distance(x, y, action_x, action_y); - spid = spid / action_eta; + spid = spid / max(1, action_eta); dir = point_direction(x, y, action_x, action_y); x = x + lengthdir_x(spid, dir); From ddcd776371350d9e2f6e083882549eefe19326a6 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 26 Jun 2026 22:15:03 +0300 Subject: [PATCH 039/140] Combat improvements New combat improvements, really glitchy. Still Alpha. --- objects/obj_ncombat/Draw_0.gml | 60 +++++++++++++++++++++++++---- objects/obj_pnunit/Mouse_0.gml | 13 ++++--- scripts/scr_newtext/scr_newtext.gml | 15 ++++++++ 3 files changed, 75 insertions(+), 13 deletions(-) diff --git a/objects/obj_ncombat/Draw_0.gml b/objects/obj_ncombat/Draw_0.gml index a406fb7925..545c40124b 100644 --- a/objects/obj_ncombat/Draw_0.gml +++ b/objects/obj_ncombat/Draw_0.gml @@ -51,31 +51,75 @@ if ((display_p2 > 0) && (enemy_forces > 0)) { draw_set_halign(fa_left); +// When pinned to the bottom (log_scroll == 0) the live 45-row window is drawn exactly as before; +// when scrolled up, page back through the retained log_history instead. +var _log_total = array_length(log_history); +var _log_start = (log_scroll <= 0) ? -1 : max(0, _log_total - log_view_lines - log_scroll); + repeat (45) { l += 1; - // draw_text(x+6,y-10+(l*14),"."+string(lines[31-l])); + + var _row_txt, _row_col; + if (_log_start < 0) { + _row_txt = lines[l]; + _row_col = lines_color[l]; + } else { + var _hi = _log_start + (l - 1); + if ((_hi >= 0) && (_hi < _log_total)) { + _row_txt = log_history[_hi].text; + _row_col = log_history[_hi].color; + } else { + _row_txt = ""; + _row_col = ""; + } + } + draw_set_color(CM_GREEN_COLOR); - if (lines_color[l] == "red") { + if (_row_col == "red") { draw_set_color(c_red); } - if (lines_color[l] == "yellow") { + if (_row_col == "yellow") { draw_set_color(3055825); } - if (lines_color[l] == "purple") { + if (_row_col == "purple") { draw_set_color(16646566); } - if (lines_color[l] == "bright") { + if (_row_col == "bright") { draw_set_color(65280); } - if (lines_color[l] == "white") { + if (_row_col == "white") { draw_set_color(c_silver); } - if (lines_color[l] == "blue") { + if (_row_col == "blue") { draw_set_color(c_aqua); } - draw_text(x + 6, y - 10 + (l * 18), string_hash_to_newline(string(lines[l]))); + if (_row_col == "lightgreen") { + draw_set_color(make_color_rgb(150, 255, 150)); + } + draw_text(x + 6, y - 10 + (l * 18), string_hash_to_newline(string(_row_txt))); } +// Combat-log scrollbar: a thin draggable thumb in the gutter between the frame and the text column. +// Only shown when there's more history than the visible window. Thumb height tracks visible/total; +// it sits at the bottom when live (log_scroll == 0) and rises as the player pages back. +if (_log_total > log_view_lines) { + var _sb_x1 = x + 2; + var _sb_x2 = x + 4; + var _sb_y1 = y + 8; + var _sb_h = log_view_lines * 18; + var _sb_max_scroll = _log_total - log_view_lines; + var _sb_thumb_h = max(20, _sb_h * (log_view_lines / _log_total)); + var _sb_frac = log_scroll / _sb_max_scroll; // 0 = live bottom, 1 = oldest + var _sb_thumb_y1 = _sb_y1 + (1 - _sb_frac) * (_sb_h - _sb_thumb_h); + + draw_set_color(CM_GREEN_COLOR); + draw_set_alpha(0.3); + draw_rectangle(_sb_x1, _sb_y1, _sb_x2, _sb_y1 + _sb_h, false); + draw_set_alpha(1); + draw_rectangle(_sb_x1, _sb_thumb_y1, _sb_x2, _sb_thumb_y1 + _sb_thumb_h, false); +} +draw_set_alpha(1); + draw_set_color(CM_GREEN_COLOR); if (click_stall_timer <= 0) { if ((fadein < 0) && (fadein > -100) && (started == 0)) { diff --git a/objects/obj_pnunit/Mouse_0.gml b/objects/obj_pnunit/Mouse_0.gml index f02d0756f4..590cdab285 100644 --- a/objects/obj_pnunit/Mouse_0.gml +++ b/objects/obj_pnunit/Mouse_0.gml @@ -46,10 +46,13 @@ show_message(blarg);*/ "+string(dudes_num[15])+"x "+string(dudes[15])+" "+string(dudes_num[16])+"x "+string(dudes[16]));*/ -var i = 0; -repeat (50) { - i += 1; - if (marine_type[i] != "") { - show_message(string(i) + ", " + string(marine_type[i]) + ", HP: " + string(marine_hp[i])); +// Debug-only roster dump. Guarded behind cheat_debug so a stray left-click during combat (e.g. on +// the log scrollbar, which overlaps the leftmost unit's sprite box) can't fire it in normal play, +// and bounded by the real array length so it can't index past marine_type. +if (global.cheat_debug == 1) { + for (var i = 0; i < array_length(marine_type); i++) { + if (marine_type[i] != "") { + show_message(string(i) + ", " + string(marine_type[i]) + ", HP: " + string(marine_hp[i])); + } } } diff --git a/scripts/scr_newtext/scr_newtext.gml b/scripts/scr_newtext/scr_newtext.gml index 67f7317824..065a56ec63 100644 --- a/scripts/scr_newtext/scr_newtext.gml +++ b/scripts/scr_newtext/scr_newtext.gml @@ -21,6 +21,21 @@ function scr_newtext() { } liness += string_count("@", newline); + // Mirror the freshly appended rows into the scrollback history (capped) so the log stays + // scrollable after lines[] rolls them off its 45-row live window. If the player is currently + // reading scrolled-up history, push their view down by the same amount to hold its position. + if (variable_instance_exists(id, "log_history")) { + for (var _h = first_open; _h <= first_open + breaks - 1; _h++) { + array_push(log_history, { text: lines[_h], color: newline_color }); + } + while (array_length(log_history) > log_history_max) { + array_delete(log_history, 0, 1); + } + if (log_scroll > 0) { + log_scroll = min(log_scroll + breaks, max(0, array_length(log_history) - log_view_lines)); + } + } + repeat (100) { // if (liness>30){scr_lines_increase(1);liness-=1;} if (liness > 45) { From 3c17e5a770fd91497878baf2565881c798d3d3b5 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 26 Jun 2026 22:29:54 +0300 Subject: [PATCH 040/140] Implemented Tavish's Scrollable log Impleneted the scrollable log made by Tavish in his LGW 1.2 Beta --- objects/obj_ncombat/Create_0.gml | 10 +++++++++ objects/obj_ncombat/Step_0.gml | 35 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index 213f7e1fd9..36fa70b838 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -194,6 +194,16 @@ dead_jims = 0; newline = ""; newline_color = ""; liness = 0; + +// Combat-log scrollback. lines[] is only a rolling 45-row live window (older rows are discarded by +// scr_lines_increase), so keep a separate capped history the player can scroll back through. +// log_scroll counts rows above the live bottom: 0 = pinned to the newest line (live). +log_history = []; +log_history_max = 300; +log_scroll = 0; +log_view_lines = 45; +log_dragging = false; + world_size = 0; timer = 0; diff --git a/objects/obj_ncombat/Step_0.gml b/objects/obj_ncombat/Step_0.gml index ecbd3e136a..a3de3e7d0e 100644 --- a/objects/obj_ncombat/Step_0.gml +++ b/objects/obj_ncombat/Step_0.gml @@ -1,3 +1,38 @@ +// --- Combat-log scroll input ------------------------------------------------- +// Mouse wheel over the left log panel pages through retained history; the thin scrollbar in the +// gutter can also be grabbed and dragged. log_scroll counts rows above the live bottom (0 = live). +var _log_total = array_length(log_history); +var _log_max_scroll = max(0, _log_total - log_view_lines); + +if ((mouse_x >= x) && (mouse_x <= x + 800) && (mouse_y >= y) && (mouse_y <= y + 900)) { + if (mouse_wheel_up()) { + log_scroll += 3; + } + if (mouse_wheel_down()) { + log_scroll -= 3; + } +} + +var _sb_y1 = y + 8; +var _sb_h = log_view_lines * 18; +if (mouse_check_button_pressed(mb_left) && (_log_max_scroll > 0) + && (mouse_x >= x + 1) && (mouse_x <= x + 5) + && (mouse_y >= _sb_y1) && (mouse_y <= _sb_y1 + _sb_h)) { + log_dragging = true; +} +if (!mouse_check_button(mb_left)) { + log_dragging = false; +} +if (log_dragging && (_log_max_scroll > 0)) { + var _sb_thumb_h = max(20, _sb_h * (log_view_lines / _log_total)); + var _sb_usable = max(1, _sb_h - _sb_thumb_h); + var _sb_rel = clamp((mouse_y - _sb_y1 - _sb_thumb_h * 0.5) / _sb_usable, 0, 1); + log_scroll = round((1 - _sb_rel) * _log_max_scroll); +} + +log_scroll = clamp(log_scroll, 0, _log_max_scroll); +// ----------------------------------------------------------------------------- + if (fadein > -30) { fadein -= 1; } From 6cc1173c23299d91298a4efc78ecdb5bb4fa5283 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 26 Jun 2026 23:02:55 +0300 Subject: [PATCH 041/140] Implement Tavish's Combat changes/experimental changes Implemented Tavish's combat changes, not as good as his because i had to do workarounds to make guardsmen work, but in essence still better than my older version. Not a permanent thing, just for testing how it works with guardsmen. --- objects/obj_ncombat/Alarm_3.gml | 80 +-- objects/obj_ncombat/Create_0.gml | 10 + objects/obj_ncombat/Step_0.gml | 20 +- objects/obj_pnunit/Alarm_0.gml | 54 +- scripts/macros/macros.gml | 10 + scripts/scr_clean/scr_clean.gml | 14 +- scripts/scr_flavor/scr_flavor.gml | 548 +++++++++++++----- .../scr_player_combat_weapon_stacks.gml | 10 + scripts/scr_powers/scr_powers.gml | 67 ++- scripts/scr_shoot/scr_shoot.gml | 494 ++++++++-------- 10 files changed, 847 insertions(+), 460 deletions(-) diff --git a/objects/obj_ncombat/Alarm_3.gml b/objects/obj_ncombat/Alarm_3.gml index f6f97b5a76..f0249ee4ad 100644 --- a/objects/obj_ncombat/Alarm_3.gml +++ b/objects/obj_ncombat/Alarm_3.gml @@ -27,7 +27,7 @@ repeat (100) { changed = 0; i = 0; - repeat (55) { + repeat (COMBAT_LOG_CAPACITY) { i += 1; // Collide the messages if needed @@ -42,37 +42,8 @@ repeat (100) { changed = 1; } - // Move larger messages up - if ((message[i] != "") && (message[i + 1] != "") && (message_sz[i] < message_sz[i + 1]) && ((message_priority[i] < message_priority[i + 1]) || (message_priority[i] == 0))) { - message[100] = message[i]; - message_sz[100] = message_sz[i]; - message_priority[100] = message_priority[i]; - - message[i] = message[i + 1]; - message_sz[i] = message_sz[i + 1]; - message_priority[i] = message_priority[i + 1]; - - message[i + 1] = message[100]; - message_sz[i + 1] = message_sz[100]; - message_priority[i + 1] = message_priority[100]; - changed = 1; - } - - // Move messages with higher priority up - if ((message[i] != "") && (message[i + 1] != "") && (message_priority[i] < message_priority[i + 1])) { - message[100] = message[i]; - message_sz[100] = message_sz[i]; - message_priority[100] = message_priority[i]; - - message[i] = message[i + 1]; - message_sz[i] = message_sz[i + 1]; - message_priority[i] = message_priority[i + 1]; - - message[i + 1] = message[100]; - message_sz[i + 1] = message_sz[100]; - message_priority[i + 1] = message_priority[100]; - changed = 1; - } + // Messages are shown in the order they happened, so we only compact gaps upward + // (above) and no longer reorder by size/priority. if (changed == 0) { good = 1; @@ -81,20 +52,20 @@ repeat (100) { } } -if (((messages > 0) && (messages_shown < 24)) && (messages_shown <= 100)) { - var that_sz, that; // show_message("Largest Message"); - that_sz = 0; - that = 0; +if (messages > 0) { + // Show messages in the order they happened (chronological), with no per-turn cap, so the + // whole exchange is visible right down to the closing "held fire" line. + var that = 0; i = 0; - repeat (60) { + repeat (COMBAT_LOG_CAPACITY) { i += 1; - if ((message[i] != "") && (message_sz[i] > that_sz)) { - that_sz = message_sz[i]; + if (message[i] != "") { that = i; + break; } } - if ((that != 0) && (that_sz > 0)) { + if (that != 0) { newline = message[that]; if (message_priority[that] > 0) { newline_color = "bright"; @@ -116,8 +87,11 @@ if (((messages > 0) && (messages_shown < 24)) && (messages_shown <= 100)) { if (message_priority[that] == 137) { newline_color = "red"; } - if (message_priority[that] == 136) { - newline_color = "yellow"; + if (message_priority[that] == MSG_COLOR_WHITE) { + newline_color = "white"; + } + if (message_priority[that] == MSG_COLOR_LIGHTGREEN) { + newline_color = "lightgreen"; } scr_newtext(); @@ -132,10 +106,6 @@ if (((messages > 0) && (messages_shown < 24)) && (messages_shown <= 100)) { alarm[3] = 2; } -if ((messages == 0) || (messages_shown >= 24)) { - messages_shown = 999; -} - if (messages == 0) { messages_shown = 999; } @@ -158,23 +128,7 @@ if (!instance_exists(obj_pnunit)) { if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { newline_color = "yellow"; if (obj_ncombat.enemy != 6) { - if ((enemy_forces > 0) && (obj_ncombat.enemy != 30)) { - newline = "Enemy Forces at " + string(max(1, round((enemy_forces / enemy_max) * 100))) + "%"; - } - if ((obj_ncombat.enemy == 30) && instance_exists(obj_enunit)) { - newline = "Enemy has "; - var yoo; - yoo = instance_nearest(0, 0, obj_enunit); - newline += string(round(yoo.dudes_hp[1])) + "HP remaining"; - } - if ((enemy_forces <= 0) || (!instance_exists(obj_enunit)) && (defeat_message == 0)) { - defeat_message = 1; - newline = "Enemy Forces Defeated"; - timer_maxspeed = 0; - timer_speed = 0; - started = 2; - instance_activate_object(obj_pnunit); - } + combat_emit_enemy_status(); } newline_color = "yellow"; if (obj_ncombat.enemy == 6) { diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index 36fa70b838..b4af9cda48 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -167,6 +167,16 @@ repeat (70) { } } +// The combat-log queue must hold at least COMBAT_LOG_CAPACITY entries so a long turn fully drains. +// The status line ("Enemy Forces at X%" / "Defeated") only renders once `messages` reaches 0, and +// Alarm_3 drains the queue through a COMBAT_LOG_CAPACITY-wide window - anything past it strands the +// tail, leaving messages > 0 forever so the status never shows. The +20 is headroom for compaction. +for (var _m = 1; _m <= COMBAT_LOG_CAPACITY + 20; _m++) { + message[_m] = ""; + message_sz[_m] = 0; + message_priority[_m] = 0; +} + post_equipment_lost = new EquipmentTracker(); post_equipment_recovered = new EquipmentTracker(); diff --git a/objects/obj_ncombat/Step_0.gml b/objects/obj_ncombat/Step_0.gml index a3de3e7d0e..5a71266b52 100644 --- a/objects/obj_ncombat/Step_0.gml +++ b/objects/obj_ncombat/Step_0.gml @@ -78,14 +78,7 @@ if (((fugg >= 60) || (fugg2 >= 60)) && (messages_shown == 0) && (messages_to_sho if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { newline_color = "yellow"; if (obj_ncombat.enemy != 6) { - if ((enemy_forces <= 0) || (!instance_exists(obj_enunit)) && (defeat_message == 0)) { - defeat_message = 1; - newline = "Enemy Forces Defeated"; - timer_maxspeed = 0; - timer_speed = 0; - started = 2; - instance_activate_object(obj_pnunit); - } + combat_emit_enemy_status(); } newline_color = "yellow"; if (obj_ncombat.enemy == 6) { @@ -144,8 +137,11 @@ if (((fugg >= 60) || (fugg2 >= 60)) && (messages_shown == 0) && (messages_to_sho if (timer_stage == 2) { fugg += 1; } -if ((timer_stage == 2) && (fugg > 60)) { - timer_stage = 3; // if (!instance_exists(obj_pnunit)) or (!instance_exists(obj_enunit)){alarm[5]=1;started=4;defeat_message=1;} +// Don't time out of stage 2 until the combat log has finished displaying - otherwise on a long turn +// the stage advances before `messages` drains and the "Enemy Forces at X%" status line is skipped. +// The large hard cap is anti-hang insurance in case the queue ever fails to drain. +if ((timer_stage == 2) && (((fugg > 60) && (messages == 0)) || (fugg > COMBAT_STAGE_TIMEOUT_FRAMES))) { + timer_stage = 3; } if (timer_stage != 2) { @@ -154,8 +150,8 @@ if (timer_stage != 2) { if (timer_stage == 4) { fugg2 += 1; } -if ((timer_stage == 4) && (fugg2 > 60)) { - timer_stage = 5; // if (!instance_exists(obj_pnunit)) or (!instance_exists(obj_enunit)){alarm[5]=1;started=4;defeat_message=1;} +if ((timer_stage == 4) && (((fugg2 > 60) && (messages == 0)) || (fugg2 > COMBAT_STAGE_TIMEOUT_FRAMES))) { + timer_stage = 5; } if (timer_stage != 4) { diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index ae9ee205e3..a50565a29d 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -57,7 +57,23 @@ try { } if (instance_exists(obj_enunit)) { + global.ctally_target = undefined; + global.ctally_bounce = []; + global.ctally_injure = []; for (var i = 0; i < array_length(wep); i++) { + // Enemies wiped before every weapon got to fire (e.g. spill-over cleared the line). + // Report who held fire and stop, rather than swinging at empty air. + if (!instance_exists(obj_enunit)) { + var _held_fire = []; + for (var hf = i; hf < array_length(wep); hf++) { + // Only ranged weapons "hold fire"; melee (range 1) never shoots, so skip it. + if (wep[hf] != "" && wep_num[hf] > 0 && range[hf] > 1) { + array_push(_held_fire, wep[hf]); + } + } + report_held_fire(_held_fire); + break; + } if (wep[i] == "") { continue; } @@ -74,6 +90,12 @@ try { enemy2 = enemy; } + // Speed Force sweeps the whole field - bypass normal targeting/range. + if (wep[i] == "Speed Force" || wep[i] == "Speed Force (Ranged)") { + scr_shoot_spread(i); + continue; + } + if ((range[i] >= dist) && (ammo[i] != 0 || range[i] == 1)) { // Guard blocks (guard > 0) keep firing their ranged weapons even when // engaged: Guardsmen empty lasguns and heavy bolters into the enemy at @@ -260,17 +282,47 @@ try { } } } + } else { + // The field was already clear when this block's turn came up - its whole arsenal holds fire. + var _skipped_fire = []; + for (var s = 0; s < array_length(wep); s++) { + // Only ranged weapons "hold fire"; melee (range 1) never shoots, so skip it. + if (wep[s] != "" && wep_num[s] > 0 && range[s] > 1) { + array_push(_skipped_fire, wep[s]); + } + } + report_held_fire(_skipped_fire); } + combat_tally_flush(); + instance_activate_object(obj_enunit); + // 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++) { + if (dudes_num[_rr] > 0 && dudes_hp[_rr] > 0) { + _alive += dudes_num[_rr]; + } + } + if ((_alive == 0) && (owner != 1)) { + instance_destroy(); + } + } + if (instance_exists(obj_enunit)) { + // Accumulate this formation's attack casts, then emit one summary line per power instead + // of one line per Librarian (see flush_psychic_summary in scr_powers). + var _psy_log = {}; for (var i = 0; i < array_length(unit_struct); i++) { if (marine_dead[i] == 0 && marine_casting[i] == true) { var caster_id = i; - scr_powers(caster_id); + scr_powers(caster_id, _psy_log); } } + flush_psychic_summary(_psy_log); } } // LOGGER.debug($"known_powers: {known_powers}"); diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 2a07cfac3f..5ede137fa3 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -49,6 +49,14 @@ #macro MANAGE_MAN_MAX array_length(obj_controller.display_unit) + 7 #macro LARGE_PLANET_MOD 1000000000 // Population threshold for large planet classification +// Ground combat message log: lines the display fully drains per turn (so the end-of-turn status +// line shows even on long battles), and the per-stage frame timeout before force-advancing. +#macro COMBAT_LOG_CAPACITY 500 +#macro COMBAT_STAGE_TIMEOUT_FRAMES 1200 +// Battle-log message_priority colour codes (extends the existing 134/135/137 set). +#macro MSG_COLOR_WHITE 140 +#macro MSG_COLOR_LIGHTGREEN 141 + #macro STR_ANY_POWER_ARMOUR "Any Power Armour" #macro STR_ANY_TERMINATOR_ARMOUR "Any Terminator Armour" @@ -104,12 +112,14 @@ enum eROLE { ASSAULT = 10, ANCIENT = 11, SCOUT = 12, + BIKER = 13, CHAPLAIN = 14, APOTHECARY = 15, TECHMARINE = 16, LIBRARIAN = 17, SERGEANT = 18, VETERANSERGEANT = 19, + ATTACK_BIKER = 20, LANDRAIDER = 50, RHINO = 51, PREDATOR = 52, diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index 65eb8123b7..44462b3c5e 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -75,9 +75,19 @@ function compress_enemy_array(_target_column) { /// @description Destroys the column if it's empty /// @param {id.Instance} _target_column - The column instance to clean up function destroy_empty_column(_target_column) { - // Destroy empty non-player columns to conserve memory and processing + // Destroy empty non-player columns to conserve memory and processing. with (_target_column) { - if ((men + veh + medi == 0) && (owner != 1)) { + // Count living models straight from dudes_num. men/veh/medi are only refreshed on the enemy's + // own alarm, so during the player's firing phase they're stale and would leave a wiped-out + // formation standing - which then keeps getting fired at and blocks "held fire" reporting. + var _alive = 0; + for (var r = 1; r < array_length(dudes_num); r++) { + // A rank chipped to 0 HP but still showing dudes_num is a dead "zombie" - don't count it. + if (dudes_num[r] > 0 && dudes_hp[r] > 0) { + _alive += dudes_num[r]; + } + } + if ((_alive == 0) && (owner != 1)) { instance_destroy(); } } diff --git a/scripts/scr_flavor/scr_flavor.gml b/scripts/scr_flavor/scr_flavor.gml index 383000e3ae..79500630d6 100644 --- a/scripts/scr_flavor/scr_flavor.gml +++ b/scripts/scr_flavor/scr_flavor.gml @@ -22,41 +22,59 @@ function display_battle_log_message() { obj_ncombat.alarm[3] = 5; } -/// @function combat_damage_flavor -/// @description Returns a combat-log fragment describing a NON-LETHAL hit, scaled by how close the -/// volley came to a kill (_severity = damage dealt as a fraction of one target's current health, -/// 0 = nothing got through, approaching 1 = almost a kill). Universal across weapons: infantry get -/// wound language, vehicles get structural-damage language. The fragments slot in after a comma, -/// e.g. "334 Lasguns strike at the Ork Boy ranks, {fragment}." Edit the wording freely; the tier -/// thresholds are the only thing the rest of the code depends on. -/// @param {real} _severity 0..1, damage this hit dealt over the target's current health -/// @param {bool} _is_vehicle target is a vehicle (hull/armour language instead of wounds) -/// @param {bool} _is_single target is a single model rather than a rank of many +/// @desc Plural form of a weapon name. Names that are already plural (end in "s", e.g. +/// "Twin Linked Bolters") are left as-is so we don't print "Bolterss". +/// @param {string} _name The weapon name. /// @returns {string} -function combat_damage_flavor(_severity, _is_vehicle, _is_single) { - if (_is_vehicle) { - if (_severity < 0.10) return choose("but the hits spend themselves against its armour", "barely chipping its paint", "pinging off its armour", "bouncing off its plating", "only scratching its armour"); - if (_severity < 0.35) return choose("scorching its plating", "scuffing its armour", "leaving shallow dents in its hull"); - if (_severity < 0.65) return choose("denting its hull", "cracking its armour", "punching into its plating"); - if (_severity < 0.90) return choose("tearing gashes into its hull", "blowing holes in its plating", "ripping through its armour"); - return choose("leaving it scorched and barely running", "all but wrecking it", "leaving it a smoking hulk"); - } - if (_is_single) { - if (_severity < 0.10) return choose("but its armour turns the blows aside", "but it shrugs them off"); - if (_severity < 0.35) return choose("but it is only grazed", "leaving only light wounds", "drawing a little blood"); - if (_severity < 0.65) return choose("and it is wounded", "leaving it bloodied", "and it is hurt"); - if (_severity < 0.90) return choose("and it is gravely wounded", "leaving it badly hurt", "and it is left reeling"); - return choose("and it is left maimed, clinging to life", "and it barely clings to life", "leaving it all but dead"); - } - if (_severity < 0.10) return choose("but fail to penetrate their armour", "but their armour holds"); - if (_severity < 0.35) return choose("drawing little more than scratches", "causing only light wounds", "leaving a few grazes"); - if (_severity < 0.65) return choose("wounding several", "bloodying their ranks", "leaving wounded in their wake"); - if (_severity < 0.90) return choose("leaving deep wounds among them", "savaging their ranks", "leaving many badly wounded"); - return choose("leaving the survivors maimed and reeling", "all but breaking them", "leaving them maimed and scattered"); +function weapon_name_plural(_name) { + return _name + ((string_char_at(_name, string_length(_name)) == "s") ? "" : "s"); } -function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shots, casulties, damage_done = -1) { +/// @desc Logs one "held fire" line for weapons that had no live target left to shoot at, e.g. +/// when an earlier volley wiped the enemy before the rest of the squad fired. +/// @param {Array} _weapon_names Raw weapon names (duplicates allowed) that never fired. +function report_held_fire(_weapon_names) { + // Dedupe and pluralise. + var _unique = []; + for (var i = 0; i < array_length(_weapon_names); i++) { + var _p = weapon_name_plural(_weapon_names[i]); + if (array_get_index(_unique, _p) == -1) { + array_push(_unique, _p); + } + } + + var _count = array_length(_unique); + if (_count == 0) { + return; + } + + // Build "A, B, and C" (or "A and B", or "A"). + var _list = _unique[0]; + for (var i = 1; i < _count; i++) { + if (i == _count - 1) { + _list += (_count > 2 ? ", and " : " and ") + _unique[i]; + } else { + _list += ", " + _unique[i]; + } + } + + add_battle_log_message($"{_list} held fire lacking live targets.", 0, 135); + display_battle_log_message(); +} + +function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shots, casulties, shots_bounced = false, _defer = false) { // Generates flavor based on the damage and casualties from scr_shoot, only for the player + // shots_bounced: true when armour stopped the shots outright (AP too low) and nothing died, + // so the log can explain *why* instead of a flat "no casualties". + // _defer: when true, build the message but DON'T post it; return it so the caller can append a + // spill-over kill list and post a single consolidated line (see emit_volley_flavour). + + // Clamp away any negative casualty count so it can never render as "-1". Every volley now earns + // a line: a kill, a wound (injured, no kill), or an armour-bounce. The latter two are consolidated + // per target by emit_volley_flavour / combat_tally_*. + if (casulties < 0) { + casulties = 0; + } var attack_message, kill_message, leader_message, targeh; targeh = target_type; @@ -64,10 +82,19 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot attack_message = $""; kill_message = ""; + // Guard/diagnostic: a non-killing volley against a rank with no living models means we fired at a + // dead target. Shouldn't happen now that emptied formations are destroyed - log it if it does and + // bail, so it can never feed the consolidated non-pen / wound feed. (Spill-over kills, if any, are + // still reported by emit_volley_flavour's undefined-primary path.) + if (casulties <= 0 && (!instance_exists(target) || target.dudes_num[targeh] <= 0)) { + LOGGER.warning($"scr_flavor: shot at a dead target (weapon stack {id_of_attacking_weapons}, rank {targeh})"); + exit; + } + var weapon_name = wep[id_of_attacking_weapons]; if (id_of_attacking_weapons == -51) { - weapon_name = "Heavy Bolter Emplacemelse ent"; + weapon_name = "Heavy Bolter Emplacement"; } if (id_of_attacking_weapons == -52) { weapon_name = "Missile Launcher Emplacement"; @@ -76,6 +103,9 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot weapon_name = "Missile Silo"; } + // Plural form for "{n} {weapon}s ..." lines (see weapon_name_plural). + var weapon_plural = weapon_name_plural(weapon_name); + var weapon_data = gear_weapon_data("weapon", weapon_name, "all"); if (!is_struct(weapon_data)) { weapon_data = new EquipmentStruct({}, ""); @@ -98,7 +128,7 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot if (array_length(full_names) == 1) { unit_name = wep_title[id_of_attacking_weapons] + " " + wep_solo[id_of_attacking_weapons][0]; } else { - unit_name = wep_title[id_of_attacking_weapons] + "'s"; + unit_name = wep_title[id_of_attacking_weapons]; } } if (wep_solo[id_of_attacking_weapons][0] == obj_ini.master_name) { @@ -126,6 +156,22 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot target_name = "flanking " + target_name; } + // Firing subject for consolidated lines: " " for a titled character, "The " + // for a lone shot, or " " for a volley (also used when a unit has no title, e.g. Dreadnoughts). + var firing_subject; + if (character_shot && unit_name != "") { + if (number_of_shots > 1) { + // Grouped titled units (e.g. several Dreadnoughts share one "Dreadnought" title) — show the count. + firing_subject = $"{number_of_shots} {string(unit_name)} {weapon_plural}"; + } else { + firing_subject = $"{string(unit_name)} {weapon_name}"; + } + } else if (number_of_shots == 1) { + firing_subject = $"The {weapon_name}"; + } else { + firing_subject = $"{number_of_shots} {weapon_plural}"; + } + var flavoured = false; if (weapon_data.has_tag("bolt")) { @@ -137,29 +183,29 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot if (number_of_shots < 200) { if (target.dudes_num[targeh] == 1) { if (casulties == 0) { - attack_message += $"{number_of_shots} {weapon_name}s fire. The {target_name} is hit but survives."; + attack_message += $"{number_of_shots} {weapon_plural} fire. The {target_name} is hit but survives."; } else { - attack_message += $"{number_of_shots} {weapon_name}s fire. The {target_name} is struck down."; + attack_message += $"{number_of_shots} {weapon_plural} fire. The {target_name} is struck down."; } } else { if (casulties == 0) { - attack_message += $"{number_of_shots} {weapon_name}s fire hits {target_name} ranks without causing casualties."; + attack_message += $"{number_of_shots} {weapon_plural} fire at {target_name} ranks without causing casualties."; } else { - attack_message += $"{number_of_shots} {weapon_name}s strike {target_name} ranks, taking down {casulties}."; + attack_message += $"{number_of_shots} {weapon_plural} strike {target_name} ranks, taking down {casulties}."; } } } else { if (target.dudes_num[targeh] == 1) { if (casulties == 0) { - attack_message += $"{number_of_shots} {weapon_name}s fire. Explosions rock the {target_name}'s armour but don't kill it."; + attack_message += $"{number_of_shots} {weapon_plural} fire. Explosions rock the {target_name}'s armour but don't kill it."; } else { - attack_message += $"{number_of_shots} {weapon_name}s fire. Explosions take down the {target_name}."; + attack_message += $"{number_of_shots} {weapon_plural} fire. Explosions take down the {target_name}."; } } else { if (casulties == 0) { - attack_message += $"{number_of_shots} {weapon_name}s hit {target_name} ranks, but no casualties are confirmed."; + attack_message += $"{number_of_shots} {weapon_plural} hit {target_name} ranks, but no casualties are confirmed."; } else { - attack_message += $"{number_of_shots} {weapon_name}s tear through {target_name} ranks, instantly killing {casulties}."; + attack_message += $"{number_of_shots} {weapon_plural} tear through {target_name} ranks, instantly killing {casulties}."; } } } @@ -214,7 +260,87 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot if (casulties == 0) { attack_message += $"but all survive the impact."; } else { - attack_message += $"killing {casulties} perish in the attack."; + attack_message += $"and {casulties} are crushed in the impact."; + } + } + } + } else if (weapon_name == "Speed Force" || weapon_name == "Speed Force(M)") { + flavoured = true; + if (!character_shot) { + if (number_of_shots < 20) { + attack_message += $"{number_of_shots} Astartes on Bikes speed ahead, their Bikes roaring like beasts of old- "; + } else if (number_of_shots >= 20 && number_of_shots < 100) { + attack_message += $"Squads of {number_of_shots} Astartes thunder ahead on their Bikes. They descend upon the enemy- "; + } else { + attack_message += $"A massive wave of {number_of_shots} Astartes rolls ahead on top of their mighty Bikes. They crash into enemy lines, smashing their foe- "; + } + if (target.dudes_num[targeh] == 1) { + if (casulties == 0) { + attack_message += $"but the {target_name} endures the onslaught."; + } else { + attack_message += $"the {target_name} falls to the charge."; + } + } else { + if (casulties == 0) { + attack_message += $"{target_name} ranks are hit, but no casualties are confirmed."; + } else { + attack_message += $"{target_name} ranks are hit, killing {casulties} in an instant."; + } + } + } else { + if (target.dudes_num[targeh] == 1) { + attack_message += string(unit_name) + $" speeds on his bike, roaring and crashing into the {target_name}- "; + if (casulties == 0) { + attack_message += $"but it endures the onslaught."; + } else { + attack_message += $"and it falls to the charge."; + } + } else { + attack_message += string(unit_name) + $" speeds on his bike, slamming into {target_name} ranks- "; + if (casulties == 0) { + attack_message += $"but all survive the impact."; + } else { + attack_message += $"crushing {casulties} beneath his wheels."; + } + } + } + } else if (weapon_name == "Speed Force (Ranged)") { + flavoured = true; + if (!character_shot) { + if (number_of_shots < 20) { + attack_message += $"{number_of_shots} Attack Bikes race across the field, sidecar gunners hosing down the enemy on the move- "; + } else if (number_of_shots >= 20 && number_of_shots < 100) { + attack_message += $"A column of {number_of_shots} Attack Bikes sweeps past, heavy weapons hammering away in a thunderous strafing run- "; + } else { + attack_message += $"A roaring tide of {number_of_shots} Attack Bikes tears along the line, sidecar guns blazing without pause- "; + } + if (target.dudes_num[targeh] == 1) { + if (casulties == 0) { + attack_message += $"but the {target_name} weathers the fusillade."; + } else { + attack_message += $"and the {target_name} is gunned down where it stands."; + } + } else { + if (casulties == 0) { + attack_message += $"{target_name} ranks are raked with fire, but none fall."; + } else { + attack_message += $"cutting down {casulties} {target_name} in the pass."; + } + } + } else { + if (target.dudes_num[targeh] == 1) { + attack_message += string(unit_name) + $" guns his Attack Bike past the {target_name}, sidecar weapon roaring- "; + if (casulties == 0) { + attack_message += $"but it endures the barrage."; + } else { + attack_message += $"and it is torn apart."; + } + } else { + attack_message += string(unit_name) + $" sweeps his Attack Bike along {target_name} ranks, raking them with fire- "; + if (casulties == 0) { + attack_message += $"but all survive the onslaught."; + } else { + attack_message += $"cutting down {casulties} in the pass."; } } } @@ -223,15 +349,15 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot if (!character_shot) { if (target.dudes_num[targeh] == 1) { if (casulties == 0) { - attack_message += $"{number_of_shots} {weapon_name}s roar, explosions clap across the armour of the {target_name} but it remains standing."; + attack_message += $"{number_of_shots} {weapon_plural} roar, explosions clap across the armour of the {target_name} but it remains standing."; } else { - attack_message += $"{number_of_shots} {weapon_name}s fire at the {target_name} and rip it apart."; + attack_message += $"{number_of_shots} {weapon_plural} fire at the {target_name} and rip it apart."; } } else { if (casulties == 0) { - attack_message += $"{number_of_shots} {weapon_name}s thunder, {target_name} are rocked but unharmed."; + attack_message += $"{number_of_shots} {weapon_plural} thunder, {target_name} are rocked but unharmed."; } else { - attack_message += $"{number_of_shots} {weapon_name}s mow down {casulties} {target_name}."; + attack_message += $"{number_of_shots} {weapon_plural} mow down {casulties} {target_name}."; } } } else { @@ -254,15 +380,15 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot if (!character_shot) { if (target.dudes_num[targeh] == 1) { if (casulties == 0) { - attack_message = $"{number_of_shots} {weapon_name}s fire upon the {target_name} but it remains standing."; + attack_message = $"{number_of_shots} {weapon_plural} fire upon the {target_name} but it remains standing."; } else { - attack_message = $"{number_of_shots} {weapon_name}s blast the {target_name} to oblivion."; + attack_message = $"{number_of_shots} {weapon_plural} blast the {target_name} to oblivion."; } } else { if (casulties == 0) { - attack_message = $"{number_of_shots} {weapon_name}s hit {target_name} ranks but they hold firm."; + attack_message = $"{number_of_shots} {weapon_plural} hit {target_name} ranks but they hold firm."; } else { - attack_message = $"{number_of_shots} {weapon_name}s pulverize {casulties} {target_name}."; + attack_message = $"{number_of_shots} {weapon_plural} pulverize {casulties} {target_name}."; } } } else { @@ -424,10 +550,10 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot attack_message = $"A {target_name} is struck down by a Battle Sister's {weapon_name}."; } if ((number_of_shots > 1) && (casulties == 0)) { - attack_message = $"Battle Sisters " + choose("howl out", "roar") + $" and hack at {target_name} ranks with their {weapon_name}s, but they survive."; + attack_message = $"Battle Sisters " + choose("howl out", "roar") + $" and hack at {target_name} ranks with their {weapon_plural}, but they survive."; } if ((number_of_shots > 1) && (casulties > 0)) { - attack_message = $"{number_of_shots} Battle Sisters " + choose("howl out", "roar") + $" as they hack away at the {target_name} ranks, killing {casulties} with their {weapon_name}s."; + attack_message = $"{number_of_shots} Battle Sisters " + choose("howl out", "roar") + $" as they hack away at the {target_name} ranks, killing {casulties} with their {weapon_plural}."; } } else if (weapon_name == "Eviscerator") { flavoured = true; @@ -468,18 +594,18 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot } if ((number_of_shots > 1) && (casulties == 0)) { - attack_message = $"A {target_name} is struck by {number_of_shots} {weapon_name}s but survives."; + attack_message = $"A {target_name} is struck by {number_of_shots} {weapon_plural} but survives."; } if ((number_of_shots > 1) && (casulties == 1)) { - attack_message = $"A {target_name} is struck down by {number_of_shots} {weapon_name}s."; + attack_message = $"A {target_name} is struck down by {number_of_shots} {weapon_plural}."; } } if (target.dudes_num[targeh] > 1) { if ((number_of_shots > 1) && (casulties == 0)) { - attack_message = $"{number_of_shots} {weapon_name}s crackle and spark, striking at the {target_name} ranks, inflicting no damage."; + attack_message = $"{number_of_shots} {weapon_plural} crackle and spark, striking at the {target_name} ranks, inflicting no damage."; } if ((number_of_shots > 1) && (casulties > 0)) { - attack_message = $"{number_of_shots} {weapon_name}s crackle and spark, hewing through the {target_name} ranks, {casulties} are cut down."; + attack_message = $"{number_of_shots} {weapon_plural} crackle and spark, hewing through the {target_name} ranks, {casulties} are cut down."; } } } @@ -488,54 +614,63 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot if (flavoured == false) { flavoured = true; if (!character_shot) { - // Wound/damage severity for non-lethal hits: how close this volley came to a kill, - // measured as damage dealt over the target's current health. damage_done < 0 means the - // caller did not supply it, so keep the old flat "survives / no damage" wording. - var _flav_hp = target.dudes_hp[targeh]; - var _flav_veh = (target.dudes_vehicle[targeh] == 1); - var _flav_sev = ((damage_done >= 0) && (_flav_hp > 0)) ? clamp(damage_done / _flav_hp, 0, 1) : -1; - var _flav_shots = (number_of_shots == 1) ? weapon_name : $"{number_of_shots} {weapon_name}s"; - if (target.dudes_num[targeh] == 1) { - if (casulties >= 1) { - attack_message = $"A {target_name} is struck down by {_flav_shots}."; - } else if (_flav_sev < 0) { - attack_message = $"A {target_name} is struck by {_flav_shots} but survives."; - } else { - attack_message = $"A {target_name} is struck by {_flav_shots}, {combat_damage_flavor(_flav_sev, _flav_veh, true)}."; + if (number_of_shots == 1 && casulties == 0) { + attack_message = $"A {target_name} is struck by {weapon_name} but survives."; + } else if (number_of_shots == 1 && casulties == 1) { + attack_message = $"A {target_name} is struck down by {weapon_name}."; + } else if (number_of_shots > 1 && casulties == 0) { + attack_message = $"A {target_name} is struck by {number_of_shots} {weapon_plural} but survives."; + } else if (number_of_shots > 1 && casulties == 1) { + attack_message = $"A {target_name} is struck down by {number_of_shots} {weapon_plural}."; } } else { - if (casulties > 0) { - attack_message = (number_of_shots == 1) - ? $"{weapon_name} strikes at {target_name} and kills {casulties}." - : $"{number_of_shots} {weapon_name}s strike at the {target_name} ranks, killing {casulties}."; - } else if (_flav_sev < 0) { - attack_message = (number_of_shots == 1) - ? $"{weapon_name} strikes at {target_name} but they survive." - : $"{number_of_shots} {weapon_name}s strike at the {target_name} ranks, but fail to inflict damage."; - } else if (number_of_shots == 1) { - attack_message = $"{weapon_name} strikes at {target_name}, {combat_damage_flavor(_flav_sev, _flav_veh, false)}."; - } else { - attack_message = $"{number_of_shots} {weapon_name}s strike at the {target_name} ranks, {combat_damage_flavor(_flav_sev, _flav_veh, false)}."; + if (number_of_shots == 1 && casulties == 0) { + attack_message = $"{weapon_name} strikes at {target_name} but they survive."; + } else if (number_of_shots == 1 && casulties > 0) { + attack_message = $"{weapon_name} strikes at {target_name} and kills {casulties}"; + } else if (number_of_shots > 1 && casulties == 0) { + attack_message = $"{number_of_shots} {weapon_plural} strike at the {target_name} ranks, but fail to inflict damage."; + } else if (number_of_shots > 1 && casulties > 0) { + attack_message = $"{number_of_shots} {weapon_plural} strike at the {target_name} ranks, killing {casulties}."; } } } else { if (target.dudes_num[targeh] == 1) { if (casulties == 0) { - attack_message = $"{string(unit_name)} {weapon_name} strikes at a {target_name} but fails to kill it."; + attack_message = $"{firing_subject} strikes at a {target_name} but fails to kill it."; } else { - attack_message = $"{string(unit_name)} {weapon_name} strikes at a {target_name}, killing it."; + attack_message = $"{firing_subject} strikes at a {target_name}, killing it."; } } else { if (casulties == 0) { - attack_message = $"{string(unit_name)} {weapon_name} strikes at the {target_name} ranks, failing to kill any."; + attack_message = $"{firing_subject} strikes at the {target_name} ranks, failing to kill any."; } else { - attack_message = $"{string(unit_name)} {weapon_name} strikes at the {target_name} ranks and kills {casulties}."; + attack_message = $"{firing_subject} strikes at the {target_name} ranks and kills {casulties}."; } } } } + // Reason-aware override: armour stopped the shots cold (AP too low). Replaces whatever + // generic "no casualties" text the branches produced with something that explains why. + if (shots_bounced && casulties == 0) { + flavoured = true; + if (character_shot) { + attack_message = $"{string(unit_name)} {weapon_name} strikes the {target_name} but fails to penetrate its armour."; + } else if (number_of_shots == 1) { + attack_message = $"The {weapon_name} strikes the {target_name} but fails to penetrate its armour."; + } else if (weapon_data.has_tag("bolt")) { + attack_message = $"{number_of_shots} {weapon_plural} hammer the {target_name} but spark harmlessly off its armour."; + } else if (weapon_data.has_tag("flame")) { + attack_message = $"{number_of_shots} {weapon_plural} wash over the {target_name} but its armour endures the flames."; + } else if (weapon_data.has_tag("power")) { + attack_message = $"{number_of_shots} {weapon_plural} strike the {target_name} but glance off its armour."; + } else { + attack_message = $"{number_of_shots} {weapon_plural} strike the {target_name} but fail to penetrate its armour."; + } + } + // if (string_length(attack_message+kill_message+p3)<8) then show_message(weapon_name+" is not displaying anything"); // I don't understand what this was supposed to do either. @@ -565,40 +700,6 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot // obj_ncombat.dead_enemies = 0; // } - // Unified outcome phrasing, applied after the per-weapon branches above so every weapon reads - // consistently. A volley that kills nothing reports wound/damage severity rather than generic - // "no casualties" wording, and a volley that destroys vehicles says "destroy" instead of "kill" - // so mechanical targets stand out at a glance. Infantry kills keep their bespoke per-weapon - // verbs untouched. - if ((damage_done >= 0) && (attack_message != "")) { - var _pp_hp = target.dudes_hp[targeh]; - var _pp_veh = (target.dudes_vehicle[targeh] == 1); - var _pp_single = (target.dudes_num[targeh] == 1); - var _pp_shots = (number_of_shots == 1) ? weapon_name : $"{number_of_shots} {weapon_name}s"; - if (casulties == 0) { - var _pp_sev = (_pp_hp > 0) ? clamp(damage_done / _pp_hp, 0, 1) : 0; - var _pp_flav = combat_damage_flavor(_pp_sev, _pp_veh, _pp_single); - if (character_shot && (unit_name != "")) { - attack_message = _pp_single - ? $"{unit_name} {weapon_name} strikes a {target_name}, {_pp_flav}." - : $"{unit_name} {weapon_name} strikes the {target_name} ranks, {_pp_flav}."; - } else if (_pp_single) { - attack_message = $"A {target_name} is struck by {_pp_shots}, {_pp_flav}."; - } else { - attack_message = $"{_pp_shots} strike at the {target_name} ranks, {_pp_flav}."; - } - } else if (_pp_veh) { - var _pp_obj = (casulties == 1) ? $"a {target_name}" : $"{casulties} {target_name}s"; - if (character_shot && (unit_name != "")) { - attack_message = $"{unit_name} {weapon_name} destroys {_pp_obj}."; - } else if (number_of_shots == 1) { - attack_message = $"{weapon_name} destroys {_pp_obj}."; - } else { - attack_message = $"{number_of_shots} {weapon_name}s destroy {_pp_obj}."; - } - } - } - var message_priority = 0; if (obj_ncombat.enemy <= 10) { if (target_name == obj_controller.faction_leader[obj_ncombat.enemy]) { @@ -622,36 +723,209 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot } } - // Yellow when this volley wounded the target but killed nothing (damage, no destroy). Skips - // the "fail to penetrate" band (under 10% of a unit's health) so a shrugged-off volley stays - // the default colour, and skips leaders so their priority colour is preserved. - if ((message_priority == 0) && (casulties == 0) && (damage_done >= 0)) { - var _yhp = target.dudes_hp[targeh]; - if ((_yhp > 0) && ((damage_done / _yhp) >= 0.10)) { - message_priority = 136; - } - } - + // Message size drives which lines survive the per-turn display cap (largest win). var message_size = 0; if (defenses == 1) { message_size = 999; } else if (casulties == 0) { - message_size = number_of_shots / 10; + // "Couldn't penetrate" lines must never outrank an actual kill (that's why a lone + // Warboss death used to get culled under its own bounce spam), so keep them tiny. + message_size = 0; } else { + // Weight kills by count *and* toughness so a single hard target (Warboss, Meganob) isn't + // buried under big trash-mob kills. Armour is the stable proxy: a lone survivor's HP gets + // chipped down before death, but its armour rating doesn't change. + message_size = casulties * (1 + target.dudes_ac[targeh]); if (target.dudes_vehicle[targeh] == 1) { - message_size = casulties * 10; + message_size *= 10; + } + } + + // When deferred, hand the parts back to the caller instead of posting them, so the spill-over + // kill list can be appended and the whole volley posted as one line. + if (!_defer) { + if (attack_message != "") { + add_battle_log_message(attack_message, message_size, message_priority); + display_battle_log_message(); + } + + if (leader_message != "") { + add_battle_log_message(leader_message, message_size, message_priority); + display_battle_log_message(); + } + } + + return { + attack: attack_message, + leader: leader_message, + size: message_size, + priority: message_priority, + bounced: (shots_bounced && casulties == 0), + injured: (!shots_bounced && casulties == 0), + target: target_name, + subject: firing_subject, + }; +} + +/// @desc Formats a list of kills into "the X" / "N X", joined as "A, B, and C". +/// @param {Array} _kills Array of { name, count } structs. +/// @returns {string} +function format_kill_list(_kills) { + // Merge entries that share a name so multiple ranks of one unit read as a single tally + // (e.g. "29 Slugga Boy and 223 Slugga Boy" -> "252 Slugga Boy"). + var _merged = []; + for (var m = 0; m < array_length(_kills); m++) { + var _hit = false; + for (var n = 0; n < array_length(_merged); n++) { + if (_merged[n].name == _kills[m].name) { + _merged[n].count += _kills[m].count; + _hit = true; + break; + } + } + if (!_hit) { + array_push(_merged, { name: _kills[m].name, count: _kills[m].count }); + } + } + _kills = _merged; + var _n = array_length(_kills); + if (_n == 0) { + return ""; + } + var _parts = []; + for (var i = 0; i < _n; i++) { + var _k = _kills[i]; + array_push(_parts, (_k.count == 1) ? ("the " + _k.name) : (string(_k.count) + " " + _k.name)); + } + var _list = _parts[0]; + for (var i = 1; i < _n; i++) { + if (i == _n - 1) { + _list += (_n > 2 ? ", and " : " and ") + _parts[i]; } else { - message_size = casulties; + _list += ", " + _parts[i]; } } + return _list; +} + +/// @desc Posts a single consolidated volley line: the deferred rich flavour for the first target, +/// plus a trailing list of everything the volley's overflow killed afterwards. +/// @param {Struct} _primary Result returned by scr_flavor(..., _defer=true) for the first target (or undefined). +/// @param {Array} _spill_kills Array of { name, count } for targets killed after the first. +function emit_volley_flavour(_primary, _spill_kills) { + var _list = format_kill_list(_spill_kills); + + // Non-killing volley (armour-bounce or a wound that dropped no-one, and nothing spilled): + // consolidate into one chronological line per target instead of one line per weapon. + if (is_struct(_primary) && (_primary.bounced || _primary.injured) && _list == "") { + combat_tally_add(_primary.target, _primary.subject, _primary.injured); + return; + } + + // A killing volley posts immediately; flush any pending bounce/injure tally first so the log + // stays in chronological order. + combat_tally_flush(); + + if (!is_struct(_primary)) { + // No primary line (scr_flavor bailed on a dead target - shouldn't happen now that emptied + // formations are destroyed). Spill-over only happens after a wipe, so this is just defensive. + if (_list != "") { + add_battle_log_message("Overflowing fire cuts down " + _list + ".", 0, 0); + display_battle_log_message(); + } + return; + } - if (attack_message != "") { - add_battle_log_message(attack_message, message_size, message_priority); + var _message = _primary.attack; + if (_list != "") { + _message += " In the torrent of fire that reaches beyond those they slaughter: " + _list + "."; + } + + if (_message != "") { + add_battle_log_message(_message, _primary.size, _primary.priority); display_battle_log_message(); } + if (_primary.leader != "") { + add_battle_log_message(_primary.leader, _primary.size, _primary.priority); + display_battle_log_message(); + } +} + +/// @desc Buffers a non-killing volley (wound or armour-bounce) against a target. Consecutive volleys +/// on the same target merge; switching target flushes the previous one, keeping the log +/// chronological. _injured true = penetrated but no kill; false = bounced off armour. +function combat_tally_add(_target, _subject, _injured) { + if (!variable_global_exists("ctally_target")) { + global.ctally_target = undefined; + global.ctally_bounce = []; + global.ctally_injure = []; + } + if (global.ctally_target != _target) { + combat_tally_flush(); + global.ctally_target = _target; + } + if (_injured) { + array_push(global.ctally_injure, _subject); + } else { + array_push(global.ctally_bounce, _subject); + } +} - if (leader_message != "") { - add_battle_log_message(leader_message, message_size, message_priority); +/// @desc Posts the buffered wound/bounce lines for the current target (one each), then clears them. +function combat_tally_flush() { + if (!variable_global_exists("ctally_target") || global.ctally_target == undefined) { + return; + } + var _t = global.ctally_target; + if (array_length(global.ctally_injure) > 0) { + add_battle_log_message($"Fire from {combat_subject_join(global.ctally_injure)} wounds the {_t} but cannot bring it down.", 0, MSG_COLOR_LIGHTGREEN); display_battle_log_message(); } + if (array_length(global.ctally_bounce) > 0) { + add_battle_log_message($"Fire from {combat_subject_join(global.ctally_bounce)} cannot penetrate the {_t}'s armour.", 0, MSG_COLOR_WHITE); + display_battle_log_message(); + } + global.ctally_target = undefined; + global.ctally_bounce = []; + global.ctally_injure = []; +} + +/// @desc Joins firing subjects into "A", "A and B", or "A, B, and C". +function combat_subject_join(_subjects) { + var _n = array_length(_subjects); + if (_n == 0) { + return ""; + } + var _list = _subjects[0]; + for (var i = 1; i < _n; i++) { + if (i == _n - 1) { + _list += (_n > 2 ? ", and " : " and ") + _subjects[i]; + } else { + _list += ", " + _subjects[i]; + } + } + return _list; +} + +/// @self Asset.GMObject.obj_ncombat +/// @desc Sets `newline` to the enemy strength readout (live %, boss HP, or "Defeated") and fires the +/// enemy-defeated side-effects. Shared by obj_ncombat's Alarm_3 and Step_0 so the line can't +/// drift between the two copies (that drift is what hid the % for so long). +function combat_emit_enemy_status() { + if ((enemy_forces > 0) && (enemy != 30)) { + newline = "Enemy Forces at " + string(max(1, round((enemy_forces / enemy_max) * 100))) + "%"; + } + if ((enemy == 30) && instance_exists(obj_enunit)) { + newline = "Enemy has "; + var yoo = instance_nearest(0, 0, obj_enunit); + newline += string(round(yoo.dudes_hp[1])) + "HP remaining"; + } + if ((enemy_forces <= 0) || (!instance_exists(obj_enunit)) && (defeat_message == 0)) { + defeat_message = 1; + newline = "Enemy Forces Defeated"; + timer_maxspeed = 0; + timer_speed = 0; + started = 2; + instance_activate_object(obj_pnunit); + } } diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index 25c8b45ba4..061fa8c6e2 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -295,6 +295,16 @@ function scr_player_combat_weapon_stacks() { } } } + if (is_struct(mobi_item) && mobi_item.has_tag("bike")) { + var _speed_force = unit.speed_force(mobi_item.has_tag("sf_ranged")); + var stack_index = find_stack_index(_speed_force.name, head_role, unit); + if (stack_index > -1) { + add_data_to_stack(stack_index, _speed_force, false, head_role, unit); + if (head_role) { + player_head_role_stack(stack_index, unit); + } + } + } if (is_struct(mobi_item)) { add_second_profiles_to_stack(mobi_item); diff --git a/scripts/scr_powers/scr_powers.gml b/scripts/scr_powers/scr_powers.gml index 3185b2f11b..cf72d96661 100644 --- a/scripts/scr_powers/scr_powers.gml +++ b/scripts/scr_powers/scr_powers.gml @@ -58,8 +58,11 @@ function generate_marine_powers_description_string(unit) { /// @desc Psychic powers execution mess. Called in the scope of obj_pnunit. /// @param {real} caster_id - ID of the caster in the player column from obj_pnunit. +/// @param {Struct} [_psy_log] - Per-formation accumulator for attack casts. When provided, ordinary +/// attack casts fold into a per-power summary (see flush_psychic_summary) instead of logging +/// one line each. Leader kills, failed casts and Perils still log individually. /// @self Asset.GMObject.obj_pnunit -function scr_powers(caster_id) { +function scr_powers(caster_id, _psy_log = undefined) { // Gather unit data /// @type {Struct.TTRPG_stats} var _unit = unit_struct[caster_id]; @@ -297,18 +300,19 @@ function scr_powers(caster_id) { compress_enemy_array(_target_data.column); destroy_empty_column(_target_data.column); - // Log battle message to combat feed - _battle_log_message = _cast_flavour_text + _power_flavour_text + _casualties_flavour_text; - if (_casualties == 0) { - _battle_log_priority = _final_damage / 50; // Just to have some priority here, as they don't have the usual "shots fired" + // Battle log: the enemy leader dying always earns its own callout; every other + // attack cast folds into a per-power summary emitted at the end of the casting + // phase (flush_psychic_summary), so a wall of Librarians becomes one line. + // (We're always inside the _casualties > 0 branch here.) + _battle_log_priority = _target_is_vehicle ? (_casualties * 12) : (_casualties * 3); + var _is_leader = (obj_ncombat.enemy <= 10) && (_target_unit_name == obj_controller.faction_leader[obj_ncombat.enemy]); + + if (is_struct(_psy_log) && !_is_leader) { + accumulate_psychic_cast(_psy_log, _power_name, _power_flavour_text, _target_unit_name, _destruction_verb, _target_is_vehicle, _casualties); } else { - if (_target_is_vehicle) { - _battle_log_priority = _casualties * 12; // Vehicles are more juicy - } else { - _battle_log_priority = _casualties * 3; // More casualties = higher priority messages - } + _battle_log_message = _cast_flavour_text + _power_flavour_text + _casualties_flavour_text; + add_battle_log_message(_battle_log_message, _battle_log_priority, 134); } - add_battle_log_message(_battle_log_message, _battle_log_priority, 134); } } } @@ -332,6 +336,47 @@ function scr_powers(caster_id) { display_battle_log_message(); } +/// @desc Folds one attack-power cast into the per-formation psychic summary, keyed by power + target, +/// so many identical Librarian casts collapse into a single battle-log line. +/// @param {Struct} _psy_log The accumulator struct (one per formation casting phase). +function accumulate_psychic_cast(_psy_log, _power_name, _power_flavour, _target_name, _verb, _is_vehicle, _kills) { + var _key = _power_name + "|" + _target_name; + if (!variable_struct_exists(_psy_log, _key)) { + _psy_log[$ _key] = { + power: _power_name, + flavour: _power_flavour, + target: _target_name, + verb: _verb, + vehicle: _is_vehicle, + casts: 0, + kills: 0, + }; + } + var _entry = _psy_log[$ _key]; + _entry.casts += 1; + _entry.kills += _kills; +} + +/// @desc Emits one battle-log line per power+target accumulated during a formation's casting phase. +/// Mirrors scr_powers' own concatenation so spacing matches the individual-cast lines. +/// @param {Struct} _psy_log The accumulator filled by accumulate_psychic_cast. +function flush_psychic_summary(_psy_log) { + if (!is_struct(_psy_log)) { + return; + } + var _keys = variable_struct_get_names(_psy_log); + for (var i = 0; i < array_length(_keys); i++) { + var _e = _psy_log[$ _keys[i]]; + var _cast_word = (_e.casts == 1) ? "casting" : "castings"; + var _message = $"{_e.casts} {_cast_word} of '{_e.power}'{_e.flavour} {_e.kills} {_e.target} are {_e.verb}."; + var _size = _e.vehicle ? (_e.kills * 12) : (_e.kills * 3); + add_battle_log_message(_message, _size, 134); + } + if (array_length(_keys) > 0) { + display_battle_log_message(); + } +} + /// @desc Function to get requested data from the disciplines_data structure. Returns The requested data, or undefined if not found. /// @param _discipline_name - The name of the discipline /// @param _data_name - The specific data attribute you want diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index df0eb0141b..267c0f784e 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -7,12 +7,6 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat // melee_or_ranged: melee or ranged // This massive clusterfuck of a script uses the newly determined weapon and target data to attack and assign damage - for (var j = 1; j <= 100; j++) { - obj_ncombat.dead_ene[j] = ""; - obj_ncombat.dead_ene_n[j] = 0; - } - obj_ncombat.dead_enemies = 0; - var hostile_type; var hostile_damage; var hostile_weapon; @@ -261,8 +255,6 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat if ((weapon_index_position >= 0) || (weapon_index_position < -40)) { // Normal shooting - var overkill = 0, damage_remaining = 0, shots_remaining = 0; - var that_works = false; if (weapon_index_position >= 0) { @@ -275,280 +267,314 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat } if (that_works == true) { - var damage_per_weapon = 0, c = 0, target_armour_value = 0, ap = 0, wii = ""; + var damage_per_weapon = 0; attack_count_mod = 0; if (weapon_index_position >= 0) { damage_per_weapon = aggregate_damage / wep_num[weapon_index_position]; - ap = armour_pierce; } // Average damage if (weapon_index_position < -40) { - wii = ""; attack_count_mod = 3; if (weapon_index_position == -51) { - wii = "Heavy Bolter Emplacement"; at = 160; armour_pierce = 0; } if (weapon_index_position == -52) { - wii = "Missile Launcher Emplacement"; at = 200; armour_pierce = -1; } if (weapon_index_position == -53) { - wii = "Missile Silo"; at = 250; armour_pierce = 0; } } - target_armour_value = target_object.dudes_ac[target_type]; + attack_count_mod = max(1, splash[weapon_index_position]); - // Calculate final armor value based on armor piercing (AP) rating against target type - if (target_object.dudes_vehicle[target_type]) { - if (armour_pierce == 4) { - target_armour_value = 0; + // Armour multiplier indexed by AP rating (1..4); any AP outside that range + // leaves armour untouched. Infantry and vehicles scale differently. + var _inf_ap = [1, 3, 2, 1.5, 0]; + var _veh_ap = [1, 6, 4, 2, 0]; + var _ap_valid = (armour_pierce >= 1) && (armour_pierce <= 4); + + // Never open fire on a dead rank/formation. Stale men/veh/medi (only refreshed on + // the enemy's own alarm) and scr_target's rank-1 fallback can aim us at corpses; + // snap to a living rank instead, or clean up the empty formation and bail. + 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) { + destroy_empty_column(target_object); + exit; } - if (armour_pierce == 3) { - target_armour_value = target_armour_value * 2; + target_type = _alive_rank; + } + + // Damage spills across ranks and, once a formation is spent, into the + // formation behind it. Every target actually fired upon gets its own flavour + // line with its own casualty count. The loop always terminates: shots_left + // strictly shrinks on every iteration that continues. + var spill_block = target_object; + var spill_rank = target_type; + var shots_left = shots_fired; + var touched_blocks = []; // Spill-over formations only; target_object is cleaned below. + + // The whole volley posts ONE battle-log line: the first target gets the rich + // weapon flavour (deferred), and every later target the overflow kills is + // gathered into a kill list appended to it (see emit_volley_flavour). + var _first_target = true; + var _primary_flavour = undefined; + var _spill_kills = []; // [{ name, count }] for targets killed after the first. + + while (shots_left > 0) { + // This target's armour against our AP rating. + var _armour = spill_block.dudes_ac[spill_rank]; + if (_ap_valid) { + var _ap_table = spill_block.dudes_vehicle[spill_rank] ? _veh_ap : _inf_ap; + _armour *= _ap_table[armour_pierce]; } - if (armour_pierce == 2) { - target_armour_value = target_armour_value * 4; + var final_hit = max(0, (damage_per_weapon - (_armour * attack_count_mod)) * spill_block.dudes_dr[spill_rank]); + + var rank_num = spill_block.dudes_num[spill_rank]; + var rank_hp = spill_block.dudes_hp[spill_rank]; + var total_damage = shots_left * final_hit; + var raw_kills = floor(total_damage / rank_hp); + var casualties = min(raw_kills, rank_num, shots_left * attack_count_mod); + + // Surplus damage only spills once this rank is actually wiped out. + var next_shots = 0; + if ((casualties >= rank_num) && (rank_num > 0) && (raw_kills > rank_num)) { + next_shots = max(0, shots_left - ceil((rank_num * rank_hp) / final_hit)); } - if (armour_pierce == 1) { - target_armour_value = target_armour_value * 6; + + // Gather flavour. The first target carries the rich phrasing (deferred, with + // the full weapon count); later targets just contribute to the kill list. + // final_hit <= 0 means armour stopped the shots cold (AP too low). + if (_first_target) { + _primary_flavour = scr_flavor(weapon_index_position, spill_block, spill_rank, shots_fired, casualties, final_hit <= 0, true); + _first_target = false; + } else if (casualties > 0) { + array_push(_spill_kills, { name: spill_block.dudes[spill_rank], count: casualties }); } - } else { - if (armour_pierce == 4) { - target_armour_value = 0; + + if ((rank_num == 1) && (casualties == 0) && (total_damage > 0)) { + spill_block.dudes_hp[spill_rank] -= total_damage; // Chip a lone survivor + if (spill_block.dudes_hp[spill_rank] <= 0) { + // Chipped to death: remove it now and drop the force count. Otherwise + // dudes_num stays 1 at dudes_hp <= 0 - a "zombie" that find_next_alive_rank + // skips, so it's never finished off and keeps inflating enemy_forces. + spill_block.dudes_num[spill_rank] = 0; + obj_ncombat.enemy_forces -= 1; + } } - if (armour_pierce == 3) { - target_armour_value = target_armour_value * 1.5; + if (casualties >= 1) { + spill_block.dudes_num[spill_rank] -= casualties; + obj_ncombat.enemy_forces -= casualties; } - if (armour_pierce == 2) { - target_armour_value = target_armour_value * 2; + + shots_left = next_shots; + if (shots_left <= 0) { + break; } - if (armour_pierce == 1) { - target_armour_value = target_armour_value * 3; + + // Next target: a living rank in this formation, else the formation behind. + var next_rank = find_next_alive_rank(spill_block, spill_block.dudes_vehicle[spill_rank]); + if (next_rank == -1) { + spill_block = get_next_enemy_formation(spill_block); + if (spill_block == noone) { + break; + } + array_push(touched_blocks, spill_block); + next_rank = find_next_alive_rank(spill_block, -1); + if (next_rank == -1) { + break; + } } + spill_rank = next_rank; } - attack_count_mod = max(1, splash[weapon_index_position]); - - final_hit_damage_value = damage_per_weapon - (target_armour_value * attack_count_mod); //damage armour reduction - - final_hit_damage_value *= target_object.dudes_dr[target_type]; //damage_resistance mod + // Post the single consolidated line for the whole volley. + emit_volley_flavour(_primary_flavour, _spill_kills); - if (final_hit_damage_value <= 0) { - final_hit_damage_value = 0; - } // Average after armour + // Clean up the spill-over formations (target_object is handled below). + for (var _tb = 0; _tb < array_length(touched_blocks); _tb++) { + if (instance_exists(touched_blocks[_tb])) { + compress_enemy_array(touched_blocks[_tb]); + destroy_empty_column(touched_blocks[_tb]); + } + } + } + } - c = shots_fired * final_hit_damage_value; // New damage + if (stop == 0) { + compress_enemy_array(target_object); + destroy_empty_column(target_object); + } + } + } catch (_exception) { + ERROR_HANDLER.handle_exception(_exception); + } +} - var casualties, onceh = 0, ponies = 0; +/// @function find_next_alive_rank +/// @description Returns the index of the next living rank (dudes_num > 0 and dudes_hp > 0) in a +/// formation, preferring ranks that match the requested vehicle flag. Returns -1 if +/// none. The dudes_hp > 0 check keeps callers safe from dividing by a rank's HP. +/// @param {Id.Instance} _block The obj_enunit formation to search. +/// @param {Real} _prefer_vehicle 0/1 to prefer that category, or -1 for any living rank. +/// @returns {Real} +function find_next_alive_rank(_block, _prefer_vehicle) { + if (!instance_exists(_block)) { + return -1; + } + var _fallback = -1; + for (var f = 1; f <= 30; f++) { + if (_block.dudes_num[f] <= 0 || _block.dudes_hp[f] <= 0) { + continue; + } + if (_prefer_vehicle == -1 || _block.dudes_vehicle[f] == _prefer_vehicle) { + return f; + } + if (_fallback == -1) { + _fallback = f; + } + } + return _fallback; +} - casualties = min(floor(c / target_object.dudes_hp[target_type]), shots_fired * attack_count_mod); +/// @function get_next_enemy_formation +/// @description Returns the nearest enemy formation (obj_enunit) sitting behind the given one +/// that still contains at least one living rank, or noone if there isn't one. +/// @param {Id.Instance} _block The formation we are spilling out of. +/// @returns {Id.Instance} +function get_next_enemy_formation(_block) { + if (!instance_exists(_block)) { + return noone; + } + var _bx = _block.x; + var _bid = _block.id; + var _best = noone; + var _best_x = 0; + with (obj_enunit) { + if (id == _bid) { + continue; + } + if (x <= _bx) { + continue; + } + if (find_next_alive_rank(id, -1) == -1) { + continue; + } + if (_best == noone || x < _best_x) { + _best = id; + _best_x = x; + } + } + return _best; +} - ponies = target_object.dudes_num[target_type]; - if ((target_object.dudes_num[target_type] == 1) && ((target_object.dudes_hp[target_type] - c) <= 0)) { - casualties = 1; - } +/// @self Asset.GMObject.obj_pnunit +/// @description Speed Force: sweep the whole enemy force, dividing damage proportionally to rank +/// size, and report it as ONE consolidated volley line (see emit_volley_flavour). +/// @param {Real} weapon_index_position The Speed Force weapon stack index. +function scr_shoot_spread(weapon_index_position) { + try { + if (wep_num[weapon_index_position] <= 0 || ammo[weapon_index_position] == 0) { + exit; + } - if (target_object.dudes_num[target_type] - casualties < 0) { - overkill = casualties - target_object.dudes_num[target_type]; - damage_remaining = c - (overkill * target_object.dudes_hp[target_type]); + var _shots = wep_num[weapon_index_position]; + var _ap = apa[weapon_index_position]; + 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; + } - shots_remaining = round(damage_remaining / damage_per_weapon); - } + // Armour multiplier indexed by AP rating (1..4), matching scr_shoot's normal path. + var _inf_ap = [1, 3, 2, 1.5, 0]; + var _veh_ap = [1, 6, 4, 2, 0]; + var _ap_valid = (_ap >= 1) && (_ap <= 4); + + // Total living models across every formation on the field. + var _formations = []; + var _total = 0; + with (obj_enunit) { + array_push(_formations, id); + for (var r = 1; r <= 30; r++) { + if (dudes[r] != "" && dudes_num[r] > 0) { + _total += dudes_num[r]; + } + } + } + if (_total <= 0) { + exit; + } - if (target_object.dudes_num[target_type] - casualties < 0) { - casualties = ponies; - } - if (casualties < 0) { - casualties = 0; - } + // Apply damage proportionally to each rank's share of the field; record every rank that lost models. + var _hits = []; // [{ name, kills, bounced }] + for (var fi = 0; fi < array_length(_formations); fi++) { + var _f = _formations[fi]; + if (!instance_exists(_f)) { + continue; + } + for (var r = 1; r <= 30; r++) { + if (_f.dudes[r] == "" || _f.dudes_num[r] <= 0) { + continue; + } - if (casualties >= 1) { - var iii = 0, found = 0, openz = 0; - for (iii = 0; iii <= 40; iii++) { - iii += 1; - if (found == 0) { - if ((obj_ncombat.dead_ene[iii] == "") && (openz == 0)) { - openz = iii; - } - if ((obj_ncombat.dead_ene[iii] == target_object.dudes[target_type]) && (found == 0)) { - found = iii; - obj_ncombat.dead_ene_n[obj_ncombat.dead_enemies] += casualties; - } - } - } - if (found == 0) { - obj_ncombat.dead_enemies += 1; - obj_ncombat.dead_ene[openz] = string(target_object.dudes[target_type]); - obj_ncombat.dead_ene_n[openz] = casualties; - } - } + var _armour = _f.dudes_ac[r]; + if (_ap_valid) { + var _ap_table = _f.dudes_vehicle[r] ? _veh_ap : _inf_ap; + _armour *= _ap_table[_ap]; + } - var k = 0; - if ((damage_remaining > 0) && (shots_remaining > 0)) { - repeat (10) { - if ((damage_remaining > 0) && (shots_remaining > 0)) { - var godd; - godd = 0; - k = target_type; - - // Find similar target in this same group - repeat (10) { - k += 1; - if (godd == 0) { - if ((target_object.dudes_num[k] > 0) && (target_object.dudes_vehicle[k] == target_object.dudes_vehicle[target_type])) { - godd = k; - } - } - } - k = target_type; - if (godd == 0) { - repeat (10) { - k -= 1; - if ((godd == 0) && (k >= 1)) { - if ((target_object.dudes_num[k] > 0) && (target_object.dudes_vehicle[k] == target_object.dudes_vehicle[target_type])) { - godd = k; - } - } - } - } - - // Found damage_per_weapon similar target to get the damage - if ((godd > 0) && (damage_remaining > 0) && (shots_remaining > 0)) { - var a2, b2, c2, target_armour_value2, ap2; - ap2 = damage_remaining; - a2 = damage_per_weapon; // Average damage - - target_armour_value2 = target_object.dudes_ac[godd]; - if (target_object.dudes_vehicle[godd] == 0) { - if (ap2 == 1) { - target_armour_value2 = target_armour_value2 * 3; - } - if (ap2 == 2) { - target_armour_value2 = target_armour_value2 * 2; - } - if (ap2 == 3) { - target_armour_value2 = target_armour_value2 * 1.5; - } - if (ap2 == 4) { - target_armour_value2 = 0; - } - } - if (target_object.dudes_vehicle[godd] == 1) { - if (ap2 == 1) { - target_armour_value2 = target_armour_value2 * 6; - } - if (ap2 == 2) { - target_armour_value2 = target_armour_value2 * 4; - } - if (ap2 == 3) { - target_armour_value2 = target_armour_value2 * 2; - } - } - b2 = a2 - target_armour_value2; - if (b2 <= 0) { - b2 = 0; - } // Average after armour - - c2 = b2 * shots_remaining; // New damage - - var casualties2, ponies2, onceh2; - onceh2 = 0; - ponies2 = 0; - if (attack_count_mod <= 1) { - casualties2 = min(floor(c2 / target_object.dudes_hp[godd]), shots_remaining); - } - - if (attack_count_mod > 1) { - casualties2 = floor(c2 / target_object.dudes_hp[godd]); - } - ponies2 = target_object.dudes_num[godd]; - if ((target_object.dudes_num[godd] == 1) && ((target_object.dudes_hp[godd] - c2) <= 0)) { - casualties2 = 1; - } - if (target_object.dudes_num[godd] < casualties2) { - casualties2 = target_object.dudes_num[godd]; - } - if (casualties2 < 1) { - casualties2 = 0; - damage_remaining = 0; - overkill = 0; - shots_remaining = 0; - } - - if ((casualties2 >= 1) && (shots_fired > 0)) { - var iii, found, openz; - iii = 0; - found = 0; - openz = 0; - repeat (40) { - iii += 1; - if (found == 0) { - if ((obj_ncombat.dead_ene[iii] == "") && (openz == 0)) { - openz = iii; - } - if ((obj_ncombat.dead_ene[iii] == target_object.dudes[godd]) && (found == 0)) { - found = iii; - obj_ncombat.dead_ene_n[obj_ncombat.dead_enemies] += casualties; - } - } - } - if (found == 0) { - obj_ncombat.dead_enemies += 1; - obj_ncombat.dead_ene[openz] = string(target_object.dudes[godd]); - obj_ncombat.dead_ene_n[openz] = casualties; - } - - /*obj_ncombat.dead_enemies+=1; - if (casualties2=1) then obj_ncombat.dead_ene[obj_ncombat.dead_enemies]="1 "+string(target_object.dudes[godd]); - if (casualties2>1) then obj_ncombat.dead_ene[obj_ncombat.dead_enemies]=string(casualties2)+" "+string(target_object.dudes[godd]); - obj_ncombat.dead_enemies+=1; - obj_ncombat.dead_ene[obj_ncombat.dead_enemies]=string(target_object.dudes[godd]); - obj_ncombat.dead_ene_n[obj_ncombat.dead_enemies]=casualties;*/ - - target_object.dudes_num[godd] -= casualties2; - obj_ncombat.enemy_forces -= casualties2; - } - - if (casualties2 >= 1) { - if (target_object.dudes_num[godd] <= 0) { - overkill = casualties2 - target_object.dudes_num[godd]; - damage_remaining -= casualties2 * target_object.dudes_hp[godd]; - - var proportional_shots; - proportional_shots = round(damage_remaining / a2); - shots_remaining = proportional_shots; - - // show_message("killed "+string(casualties2)+"x "+string(target_object.dudes[godd])); - // show_message("did "+string(c)+" damage with "+string(proportional_shots)+" shots fired, have "+string(damage_remaining)+" damage remaining"); - } - } - } - } - } - } // End repeat 10 - scr_flavor(weapon_index_position, target_object, target_type, shots_fired - wep_rnum[weapon_index_position], casualties, c); + var _rank_shots = _shots * (_f.dudes_num[r] / _total); + var _final_hit = max(0, (_dpw - (_armour * _mod)) * _f.dudes_dr[r]); + var _kills = min(floor((_rank_shots * _final_hit) / _f.dudes_hp[r]), _f.dudes_num[r]); + if (_kills < 0) { + _kills = 0; + } - if ((target_object.dudes_num[target_type] == 1) && (c > 0)) { - target_object.dudes_hp[target_type] -= c; - } // Need special flavor here for just damaging + if (_kills > 0) { + _f.dudes_num[r] -= _kills; + obj_ncombat.enemy_forces -= _kills; + array_push(_hits, { name: _f.dudes[r], kills: _kills, bounced: (_final_hit <= 0), block: _f, rank: r }); + } + } + } - if (casualties >= 1) { - target_object.dudes_num[target_type] -= casualties; - obj_ncombat.enemy_forces -= casualties; - } + // Primary = the rank with the most kills (rich deferred flavour); the rest form the kill list. + var _primary = undefined; + var _spill = []; + if (array_length(_hits) > 0) { + var _best = 0; + for (var i = 1; i < array_length(_hits); i++) { + if (_hits[i].kills > _hits[_best].kills) { + _best = i; } } + for (var i = 0; i < array_length(_hits); i++) { + if (i == _best) { + continue; + } + array_push(_spill, { name: _hits[i].name, count: _hits[i].kills }); + } + var _p = _hits[_best]; + if (instance_exists(_p.block)) { + _primary = scr_flavor(weapon_index_position, _p.block, _p.rank, _shots, _p.kills, _p.bounced, true); + } + } + emit_volley_flavour(_primary, _spill); - if (stop == 0) { - compress_enemy_array(target_object); - destroy_empty_column(target_object); + // Clean up spent ranks/formations (mirrors scr_shoot). + for (var fi = 0; fi < array_length(_formations); fi++) { + if (instance_exists(_formations[fi])) { + compress_enemy_array(_formations[fi]); + destroy_empty_column(_formations[fi]); } } } catch (_exception) { From 8d6b20779261bd131450b7a502099f44ac1216db Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 29 Jun 2026 07:30:45 +0300 Subject: [PATCH 042/140] Added... too much to describe.. Volley fire by guard, guard divided into 100 units, added enemies being capable of choosing targets based on penetration prefarance (no more enemies shooting at tanks IF they're capable to shoot at infantry) and more. --- datafiles/data/unit_stats.json | 58 ++++++++++++++++++- datafiles/data/weapons.json | 27 ++++++++- objects/obj_enunit/Alarm_0.gml | 11 +++- scripts/macros/macros.gml | 21 +++++++ scripts/scr_add_man/scr_add_man.gml | 12 +++- scripts/scr_add_vehicle/scr_add_vehicle.gml | 6 ++ .../scr_draw_unit_image.gml | 2 +- .../scr_marine_struct/scr_marine_struct.gml | 5 +- .../scr_player_combat_weapon_stacks.gml | 39 ++++++++++++- scripts/scr_roster/scr_roster.gml | 48 +++++++++++++-- scripts/scr_start_load/scr_start_load.gml | 2 +- scripts/scr_trade/scr_trade.gml | 27 +++++++++ .../scr_unit_equip_functions.gml | 11 ++++ .../scr_vehicle_order/scr_vehicle_order.gml | 3 +- 14 files changed, 257 insertions(+), 15 deletions(-) diff --git a/datafiles/data/unit_stats.json b/datafiles/data/unit_stats.json index cc3775ee74..b7d3d04977 100644 --- a/datafiles/data/unit_stats.json +++ b/datafiles/data/unit_stats.json @@ -638,7 +638,7 @@ "guardsman": { "ballistic_skill": [ 25, - 1 + 6 ], "base_group": "human", "charisma": [ @@ -689,11 +689,65 @@ 1 ] }, - "guard_sergeant": { + "heavy_weapons_team": { "ballistic_skill": [ + 28, + 4 + ], + "base_group": "human", + "charisma": [ + 15, + 1 + ], + "constitution": [ + 28, + 1, + "max" + ], + "dexterity": [ 20, 1 ], + "intelligence": [ + 15, + 1 + ], + "luck": 5, + "piety": [ + 25, + 1 + ], + "religion": "imperial_cult", + "start_gear": { + "armour": "Flak Armour", + "gear": "", + "mobi": "", + "wep1": "Heavy Bolter", + "wep2": "" + }, + "strength": [ + 22, + 1 + ], + "technology": [ + 10, + 1 + ], + "title": "Heavy Weapons Team", + "weapon_skill": [ + 15, + 1 + ], + "wisdom": [ + 15, + 1 + ] + }, + "guard_sergeant": { + "ballistic_skill": [ + 20, + 6 + ], "base_group": "human", "charisma": [ 18, diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index 61fdf4dcb7..f4a3054d91 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -121,6 +121,28 @@ ], "value": 30 }, + "Earthshaker Cannon": { + "abbreviation": "Erthshk", + "ammo": 8, + "arp": 3, + "attack": { + "artifact": 1050, + "master_crafted": 850, + "standard": 700 + }, + "description": "The Earthshaker is the thunderous main gun of the Basilisk self-propelled artillery. It lobs enormous high-explosive shells in a high arc onto distant formations, shattering massed infantry and light armour from well beyond the firing line.", + "melee_hands": 0, + "range": 24, + "ranged_hands": 0, + "spli": 12, + "tags": [ + "vehicle", + "heavy_ranged", + "explosive", + "turret" + ], + "value": 45 + }, "Battle Cannon": { "abbreviation": "BtlCnn", "ammo": 12, @@ -1322,7 +1344,8 @@ "ranged_hands": 1, "spli": 3, "tags": [ - "las" + "las", + "veteran_guard_only" ] }, "Hellrifle": { @@ -1680,7 +1703,7 @@ "attack": { "artifact": 130, "master_crafted": 110, - "standard": 70 + "standard": 60 }, "description": "The standard-issue weapon of the Astra Militarum. A rugged two-handed las weapon firing coherent energy beams, prized for its reliability and the ease of recharging its power packs in the field. Common, dependable, and unremarkable on its own.", "melee_hands": 0, diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index 74c3b96114..438018f8c4 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -48,7 +48,16 @@ if (!engaged) { if (range[i] >= dist) { // The weapon is in range; - var _target_vehicles = apa[i] > 0 ? true : false; // AP weapons target vehicles + // A weapon's armour pierce doubles as its role. Dedicated anti-tank guns + // (apa >= GUARD_ENEMY_ANTITANK_AP, the rokkit / lascannon / melta class) hunt + // vehicles. Everything lighter (general-purpose and pure anti-infantry) goes + // for the men first. This is preference by weapon role, not per-shot penetration + // knowledge: the enemy never checks whether a given shot would crack a specific + // target, it just sends tank-hunters at tanks and lighter guns at infantry. + // Either type still crosses over as a fallback through the paths below: an + // anti-tank gun with no vehicle in reach drops to the men path, and a lighter + // gun with no men in reach drops to the vehicle fallback inside the men path. + var _target_vehicles = apa[i] >= GUARD_ENEMY_ANTITANK_AP; // role-based target preference // Weird alpha strike mechanic, that changes target unit index to CM; if (((wep[i] == "Power Fist") || (wep[i] == "Bolter")) && (obj_ncombat.alpha_strike > 0) && (wep_num[i] > 5)) { diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 5ede137fa3..27b15dda2e 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -5,6 +5,11 @@ // reuse as heavy weapons teams. Do not delete. #macro GUARD_SQUAD_SIZE 10 +// Imperial Guard heavy weapons team: how many guardsmen one Heavy Weapons Team unit represents. +// The team is a single pooled-HP entity (role "Heavy Weapons Team") crewing one heavy weapon, with +// the health of this many guardsmen (see scr_marine_struct max_health()). 3 = a 3-man weapons team. +#macro GUARD_HEAVY_WEAPONS_TEAM_SIZE 3 + // Imperial Guard cover save: fraction of would-be ground-combat casualties treated as // missed, standing in for spacing, terrain use and a low profile that the combat model // does not simulate. Applied after armour, so it also blunts armour-piercing weapons @@ -21,6 +26,22 @@ #macro GUARD_SCREEN_COLUMN_FIRST 8 #macro GUARD_SCREEN_COLUMN_COUNT 3 +// Enemy target preference: the minimum weapon armour pierce (apa, scale 0-4) that counts as +// "anti-tank" and so hunts vehicles in obj_enunit\Alarm_0. Weapons below this prefer infantry +// and only turn to vehicles as a fallback. 3 splits dedicated anti-tank (rokkit / lascannon / +// melta tier) from general-purpose and anti-infantry guns. Raise toward 4 to make only the +// heaviest guns chase tanks; drop toward 1 for the old behaviour where almost everything did. +#macro GUARD_ENEMY_ANTITANK_AP 3 + +// Guard volley size: how many rank-and-file guardsmen share one firing stack in combat. The +// regiment splits into capped stacks of this size instead of merging into one giant lasgun +// volley, so each chunk fires and targets independently like an enemy obj_enunit block (those +// run ~32-40 strong). They still deploy as one movable hireling line; this only affects firing. +// Lower for more, smaller volleys; raise toward one big stack. Keep it from making too many +// stacks: a block has 71 stack slots shared with every other weapon. +#macro GUARD_VOLLEY_SIZE 100 + + // Imperial Guard accuracy ("doom"): mirrors the enemy's per-faction doom in scr_shoot (the // owner == eFACTION.IMPERIUM branch, e.g. Orks 0.2, Tyranids 0.4). Massed lasgun fire from raw // conscripts connects far less than disciplined Astartes fire, so the guard's ranged lasgun diff --git a/scripts/scr_add_man/scr_add_man.gml b/scripts/scr_add_man/scr_add_man.gml index 9bc9c5e125..a5e241b893 100644 --- a/scripts/scr_add_man/scr_add_man.gml +++ b/scripts/scr_add_man/scr_add_man.gml @@ -13,7 +13,8 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption "Flash Git", "Guardsman", "Guard Squad", - "Guard Sergeant" + "Guard Sergeant", + "Heavy Weapons Team" ]; var _gear = {}; var _company_slot = 0; @@ -44,6 +45,11 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption obj_ini.race[target_company][_company_slot] = eFACTION.IMPERIUM; _unit = new TTRPG_stats("imperial_guard", target_company, _company_slot, "guard_sergeant"); break; + case "Heavy Weapons Team": + spawn_exp = 10; + obj_ini.race[target_company][_company_slot] = eFACTION.IMPERIUM; + _unit = new TTRPG_stats("imperial_guard", target_company, _company_slot, "heavy_weapons_team"); + break; case "Skitarii": spawn_exp = 10; obj_ini.race[target_company][_company_slot] = 3; @@ -131,6 +137,10 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption case "Guard Sergeant": obj_ini.name[target_company][_company_slot] = global.name_generator.GenerateFromSet("imperial_male"); break; + + case "Heavy Weapons Team": + obj_ini.name[target_company][_company_slot] = global.name_generator.GenerateFromSet("imperial_male"); + break; } if (!array_contains(non_marine_roles, man_role)) { diff --git a/scripts/scr_add_vehicle/scr_add_vehicle.gml b/scripts/scr_add_vehicle/scr_add_vehicle.gml index 84aa44a806..8d91861855 100644 --- a/scripts/scr_add_vehicle/scr_add_vehicle.gml +++ b/scripts/scr_add_vehicle/scr_add_vehicle.gml @@ -133,6 +133,12 @@ function scr_add_vehicle(vehicle_type, target_company, otherdata = {}, weapon1 = obj_ini.veh_wep1[target_company][good] = "Battle Cannon"; obj_ini.veh_wep2[target_company][good] = "Heavy Bolter"; } + if (vehicle_type == "Basilisk") { + // Earthshaker Cannon (long-range artillery blast) with a Storm Bolter for + // close defence, mirroring the enemy Basilisk loadout. + obj_ini.veh_wep1[target_company][good] = "Earthshaker Cannon"; + obj_ini.veh_wep2[target_company][good] = "Storm Bolter"; + } } obj_ini.veh_hp[target_company][good] = 100; diff --git a/scripts/scr_draw_unit_image/scr_draw_unit_image.gml b/scripts/scr_draw_unit_image/scr_draw_unit_image.gml index a89b36be16..f51b01da91 100644 --- a/scripts/scr_draw_unit_image/scr_draw_unit_image.gml +++ b/scripts/scr_draw_unit_image/scr_draw_unit_image.gml @@ -531,7 +531,7 @@ function scr_draw_unit_image(_background = false) { // same way Skitarii and Sisters draw theirs, loaded once from a runtime PNG because the // mod cannot add compiled sprite assets. The image ships at images\units\guardsman.png. // If alignment needs nudging, offset the draw from x_surface_offset / y_surface_offset. - if (role() == "Guardsman") { + if (role() == "Guardsman" || role() == "Veteran Guard" || role() == "Heavy Weapons Team") { if (!variable_global_exists("guardsman_portrait")) { global.guardsman_portrait = sprite_add(working_directory + "/images/units/guardsman.png", 1, false, false, 0, 0); } diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index 30e815073b..cdc66f57c6 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -365,7 +365,7 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} // Astartes, so a single trooper takes only a tenth of a marine's berth. A Guard // Squad is left at a full slot, since one already stands in for a whole squad. A // Guard Sergeant bunks with his men, so he takes the same tenth-slot as a trooper. - if (unit_role == "Guardsman" || unit_role == "Guard Sergeant") { + if (unit_role == "Guardsman" || unit_role == "Guard Sergeant" || unit_role == "Veteran Guard" || unit_role == "Heavy Weapons Team") { size = 0.1; return size; } @@ -407,6 +407,9 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} if (role() == "Guard Squad") { max_h *= GUARD_SQUAD_SIZE; // a squad shares one pooled health bar and dies as a whole } + if (role() == "Heavy Weapons Team") { + max_h *= GUARD_HEAVY_WEAPONS_TEAM_SIZE; // a 3-man weapons team shares one pooled health bar + } return max_h; }; diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index 061fa8c6e2..2dcad296f9 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -111,6 +111,35 @@ function find_stack_index(weapon_name, head_role = false, unit = "none") { return final_index; } +/// @self Asset.GMObject.obj_pnunit +/// Like find_stack_index, but caps how many shooters share a stack so a large body of +/// identically-armed troops (a guard regiment of lasguns) splits into several smaller stacks +/// instead of one regiment-wide one. Each capped stack fires and targets independently in +/// combat, the way the enemy's obj_enunit blocks already do. Fills a partial chunk first, +/// opens a fresh stack when the current one is full, and only as a last resort (all 71 stack +/// slots used) merges over the cap so fire is never silently dropped. +function find_capped_stack_index(weapon_name, cap) { + // 1. a matching, un-led chunk that still has room + for (var si = 1; si < array_length(wep); si++) { + if (wep[si] == weapon_name && wep_title[si] == "" && wep_num[si] < cap) { + return si; + } + } + // 2. no room left in any existing chunk: start a fresh one + for (var si = 1; si < array_length(wep); si++) { + if (wep[si] == "" && wep_title[si] == "") { + return si; + } + } + // 3. stack slots exhausted: merge over the cap rather than drop the shots + for (var si = 1; si < array_length(wep); si++) { + if (wep[si] == weapon_name && wep_title[si] == "") { + return si; + } + } + return -1; +} + /// @self Asset.GMObject.obj_pnunit function player_head_role_stack(stack_index, unit) { wep_title[stack_index] = unit.role(); @@ -372,7 +401,15 @@ function scr_player_combat_weapon_stacks() { add_squad_weapon(unit.weapon_two(), 1, head_role, unit); } else { var primary_ranged = unit.ranged_damage_data[3]; //collect unit ranged data - weapon_stack_index = find_stack_index(primary_ranged.name, head_role, unit); + // Rank-and-file guardsmen split into enemy-block-sized volleys (capped + // stacks) instead of merging the whole regiment into one lasgun stack, so + // each volley fires and picks its target on its own. Everyone else (Marines, + // sergeants, specialists) stacks normally. + if (unit.role() == "Guardsman") { + weapon_stack_index = find_capped_stack_index(primary_ranged.name, GUARD_VOLLEY_SIZE); + } else { + weapon_stack_index = find_stack_index(primary_ranged.name, head_role, unit); + } if (weapon_stack_index > -1) { add_data_to_stack(weapon_stack_index, primary_ranged, unit.ranged_damage_data[0], head_role, unit); if (head_role) { diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 1b1c1c00cd..dc81c09e0e 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -113,7 +113,7 @@ function Roster() constructor { } // Guardsmen answer to their own filter button rather than always passing var _grd_role = _unit.role(); - if (_grd_role == "Guardsman" || _grd_role == "Guard Squad" || _grd_role == "Guard Sergeant") { + if (_grd_role == "Guardsman" || _grd_role == "Guard Squad" || _grd_role == "Guard Sergeant" || _grd_role == "Veteran Guard" || _grd_role == "Heavy Weapons Team") { _valid_type = array_contains(_valid_squad_types, "guardsman"); } } @@ -298,7 +298,7 @@ function Roster() constructor { // Guardsmen and Guard Squads have no squad type, so give them their // own filter button (added once) so they can be selected on their own. var _grd_role = _unit.role(); - if ((_grd_role == "Guardsman" || _grd_role == "Guard Squad" || _grd_role == "Guard Sergeant") && !array_contains(_squads, "guardsman")) { + if ((_grd_role == "Guardsman" || _grd_role == "Guard Squad" || _grd_role == "Guard Sergeant" || _grd_role == "Veteran Guard" || _grd_role == "Heavy Weapons Team") && !array_contains(_squads, "guardsman")) { array_push(_squads, "guardsman"); new_squad_button("Guardsmen", "guardsman"); } @@ -729,7 +729,12 @@ function add_unit_to_battle(unit, meeting, is_local) { // before the positional-screen experiment: every guardsman shares this one column instead of // being pinned to fixed front columns. bat_hire_column was resolved for this formation at the // top of this function and is driven by the Hirelings bar (bat_hire_for, unit_id 12). - if (_unit_role == "Guardsman" || _unit_role == "Guard Sergeant") { + if (_unit_role == "Heavy Weapons Team") { + // Heavy weapons teams fight from the Devastator formation, the chapter's own heavy-weapon + // line, instead of the Hirelings block, so the auxilia's heavy guns stand with the Marines'. + col = obj_controller.bat_devastator_column; + new_combat.devastators++; + } else if (_unit_role == "Guardsman" || _unit_role == "Guard Sergeant" || _unit_role == "Veteran Guard") { col = obj_controller.bat_hire_column; } @@ -820,6 +825,13 @@ function add_vehicle_to_battle(company, veh_index, is_local) { targ.veh_hp[targ.veh] = obj_ini.veh_hp[company][v] * 3; targ.veh_hp_multiplier[targ.veh] = 3; targ.veh_ac[targ.veh] = 40; + } else if (obj_ini.veh_role[company][v] == "Basilisk") { + // Mirrors the enemy Basilisk: armour 30, HP 150 (base 100 x1.5). A self-propelled + // artillery piece, tougher than a Chimera but lighter than a Leman Russ, built to + // shell from the rear of the line rather than trade blows at the front. + targ.veh_hp[targ.veh] = obj_ini.veh_hp[company][v] * 1.5; + targ.veh_hp_multiplier[targ.veh] = 1.5; + targ.veh_ac[targ.veh] = 30; } // STC Bonuses @@ -854,5 +866,33 @@ function add_vehicle_to_battle(company, veh_index, is_local) { /// excluded from the Headquarters detail view. /// @returns {array} function auxilia_roles() { - return ["Guardsman", "Guard Squad", "Guard Sergeant"]; + return ["Guardsman", "Guard Squad", "Guard Sergeant", "Veteran Guard", "Heavy Weapons Team"]; +} + +/// @description Promote every basic Guardsman to Veteran Guard, applying the veteran stat +/// buff. Veterans keep all Guard behaviour (Auxilia screen, hireling line, volley fire, +/// tenth-slot berth, guardsman portrait) through the role closure. They receive no free +/// weapon; Hellguns are forged separately and equip-gated to this role. Intended to be wired +/// to the Auxilia "Promote All" button. Pass a company index to limit promotion to one +/// company, or leave it undefined to promote every auxilia Guardsman. The stat_boosts numbers +/// are tunable. Additions are flat; stat_boosts rebalances constitution into current health. +/// @param {real} [_company] optional company index to limit promotion to +/// @returns {real} number of troopers promoted +function promote_auxilia_to_veteran(_company = undefined) { + var _troops = collect_role_group("all", "", false, { roles: ["Guardsman"] }); + var _count = 0; + for (var _i = 0; _i < array_length(_troops); _i++) { + var _unit = _troops[_i]; + if (_company != undefined && _unit.company != _company) { + continue; + } + _unit.update_role("Veteran Guard"); + _unit.stat_boosts({ + ballistic_skill: 8, + constitution: 6, + dexterity: 4 + }); + _count++; + } + return _count; } diff --git a/scripts/scr_start_load/scr_start_load.gml b/scripts/scr_start_load/scr_start_load.gml index b4e9658a27..700fcc16b8 100644 --- a/scripts/scr_start_load/scr_start_load.gml +++ b/scripts/scr_start_load/scr_start_load.gml @@ -55,7 +55,7 @@ function scr_start_load(fleet, load_from_star, load_options) { } } // i feel like there definatly is or should be a generic function for this???? - var _vehicles = ["Rhino", "Predator", "Land Speeder", "Land Raider", "Whirlwind", "Chimera", "Leman Russ"]; + var _vehicles = ["Rhino", "Predator", "Land Speeder", "Land Raider", "Whirlwind", "Chimera", "Leman Russ", "Basilisk"]; function load_vehicles(_companies, _equip, _ship, size) { obj_ini.veh_wid[_companies][_equip] = 0; obj_ini.veh_lid[_companies][_equip] = _ship; diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 3f729bd331..52c0e2cb83 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -107,6 +107,14 @@ function TradeAttempt(diplomacy) constructor { repeat (floor(_opt.number / 200)) { scr_add_vehicle("Chimera", 0); } + // One Heavy Weapons Team musters per 100 guardsmen, a Heavy Bolter crew + // drawn from the same homeworld levy to give the auxilia organic anti-heavy + // fire. This mirrors how the enemy Guard field Heavy Weapons Teams, scaled to + // the player at 1 per 100. They muster into the Auxilia company (company 0) + // alongside the guardsmen. The /100 ratio is tunable. + repeat (floor(_opt.number / 100)) { + scr_add_man("Heavy Weapons Team", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); + } with (obj_ini) { scr_company_order(0); } @@ -129,6 +137,24 @@ function TradeAttempt(diplomacy) constructor { // Handing over sacred war materiel costs the forge world some regard, one point // per tank with a floor of one, so a larger order stings their disposition more. alter_disposition(diplomacy_faction, -max(1, _opt.number)); + } else if (_type == "Basilisk") { + // The Adeptus Mechanicus part with a Basilisk only grudgingly. Each musters + // into the Auxilia company (company 0) alongside the guard armour line so the + // force can field its own artillery. The Basilisk serves the Imperial Guard + // auxilia, not the Chapter, so it is tagged eFACTION.IMPERIUM to match the + // guardsmen it supports rather than the player's own colours. + repeat (_opt.number) { + scr_add_vehicle("Basilisk", 0); + } + for (var _bv = 1; _bv < array_length(obj_ini.veh_role[0]); _bv++) { + if (obj_ini.veh_role[0][_bv] == "Basilisk") { + obj_ini.veh_race[0][_bv] = eFACTION.IMPERIUM; + } + } + with (obj_ini) { + scr_company_order(0); + } + alter_disposition(diplomacy_faction, -max(1, _opt.number)); } else { // Every other mercenary type arrives by trade convoy. if (!struct_exists(trading_object, "mercenaries")) { @@ -432,6 +458,7 @@ function TradeAttempt(diplomacy) constructor { new_demand_buttons(25, "Skitarii", "merc", 200); new_demand_buttons(55, "Techpriest", "merc", 3); new_demand_buttons(40, "Leman Russ", "merc", 10); + new_demand_buttons(50, "Basilisk", "merc", 5); break; case 4: new_demand_buttons(25, "Crusader", "merc", 5); diff --git a/scripts/scr_unit_equip_functions/scr_unit_equip_functions.gml b/scripts/scr_unit_equip_functions/scr_unit_equip_functions.gml index 46a1685743..c10a822a12 100644 --- a/scripts/scr_unit_equip_functions/scr_unit_equip_functions.gml +++ b/scripts/scr_unit_equip_functions/scr_unit_equip_functions.gml @@ -176,6 +176,17 @@ function scr_update_unit_weapon_one(new_weapon, from_armoury = true, to_armoury } } + // Veteran-only weapon gate: some weapons are role-restricted (the Hellgun is Veteran + // Guard only). Reject and log before any armoury or slot mutation if the unit lacks the + // role. Skips unequip and artifacts. Mirrors the mobility tag-gate, keyed on role. + if (!unequipping && !is_artifact) { + var _wep_restrict_data = gear_weapon_data("weapon", new_weapon); + if (is_struct(_wep_restrict_data) && _wep_restrict_data.has_tag("veteran_guard_only") && role() != "Veteran Guard") { + LOGGER.error($"Failed to equip {new_weapon} for {name()} - restricted to Veteran Guard."); + return "restricted"; + } + } + if (from_armoury && !unequipping && !is_artifact) { var viability = weapon_viable(new_weapon, quality); if (viability[0]) { diff --git a/scripts/scr_vehicle_order/scr_vehicle_order.gml b/scripts/scr_vehicle_order/scr_vehicle_order.gml index 6272694c7a..d46fe1c45e 100644 --- a/scripts/scr_vehicle_order/scr_vehicle_order.gml +++ b/scripts/scr_vehicle_order/scr_vehicle_order.gml @@ -50,7 +50,8 @@ function scr_vehicle_order(company_number) { || veh_role[company_number][i] == "Land Speeder" || veh_role[company_number][i] == "Land Raider" || veh_role[company_number][i] == "Chimera" - || veh_role[company_number][i] == "Leman Russ"; + || veh_role[company_number][i] == "Leman Russ" + || veh_role[company_number][i] == "Basilisk"; if (_is_vehicle_role) { temp_race[company_number][vehicle_count] = veh_race[company_number][i]; From 8a1fa4fac528d37ac3bdb07da58e0999d9bba8e7 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 29 Jun 2026 07:53:10 +0300 Subject: [PATCH 043/140] Kill consolidation fix For merging purposes --- objects/obj_pnunit/Alarm_0.gml | 5 ++ scripts/scr_flavor/scr_flavor.gml | 82 ++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index a50565a29d..d689667c56 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -60,6 +60,10 @@ try { global.ctally_target = undefined; global.ctally_bounce = []; global.ctally_injure = []; + global.ktally_target = undefined; + global.ktally_weapons = {}; + global.ktally_order = []; + global.ktally_leaders = []; for (var i = 0; i < array_length(wep); i++) { // Enemies wiped before every weapon got to fire (e.g. spill-over cleared the line). // Report who held fire and stop, rather than swinging at empty air. @@ -295,6 +299,7 @@ try { } combat_tally_flush(); + combat_kill_tally_flush(); instance_activate_object(obj_enunit); diff --git a/scripts/scr_flavor/scr_flavor.gml b/scripts/scr_flavor/scr_flavor.gml index 79500630d6..e41abd8ec7 100644 --- a/scripts/scr_flavor/scr_flavor.gml +++ b/scripts/scr_flavor/scr_flavor.gml @@ -172,6 +172,10 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot firing_subject = $"{number_of_shots} {weapon_plural}"; } + // A plain volley line (" ", no character title) can be summed with other volleys + // of the same weapon on the same target into one consolidated kill line (see emit_volley_flavour). + var _volley_line = (!(character_shot && unit_name != "")) && (number_of_shots > 1); + var flavoured = false; if (weapon_data.has_tag("bolt")) { @@ -764,6 +768,10 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot injured: (!shots_bounced && casulties == 0), target: target_name, subject: firing_subject, + weapon: weapon_plural, + shots: number_of_shots, + kills: casulties, + volley: _volley_line, }; } @@ -818,13 +826,25 @@ function emit_volley_flavour(_primary, _spill_kills) { // Non-killing volley (armour-bounce or a wound that dropped no-one, and nothing spilled): // consolidate into one chronological line per target instead of one line per weapon. if (is_struct(_primary) && (_primary.bounced || _primary.injured) && _list == "") { + combat_kill_tally_flush(); combat_tally_add(_primary.target, _primary.subject, _primary.injured); return; } - // A killing volley posts immediately; flush any pending bounce/injure tally first so the log - // stays in chronological order. + // Simple killing volley with no spill-over: buffer it so consecutive volleys of the same weapon + // on the same target (e.g. a split lasgun volley firing in sub-stacks) collapse into one summed + // line. A single unmerged volley keeps its original rich flavour on flush. Flush the wound/bounce + // tally first so the log stays chronological. + if (is_struct(_primary) && _list == "" && _primary.volley && _primary.kills > 0) { + combat_tally_flush(); + combat_kill_tally_add(_primary.target, _primary.weapon, _primary.shots, _primary.kills, _primary.attack, _primary.size, _primary.priority, _primary.leader); + return; + } + + // A killing volley with spill-over, or a titled/lone shot, posts immediately; flush both pending + // tallies first so the log stays in chronological order. combat_tally_flush(); + combat_kill_tally_flush(); if (!is_struct(_primary)) { // No primary line (scr_flavor bailed on a dead target - shouldn't happen now that emptied @@ -890,6 +910,64 @@ function combat_tally_flush() { global.ctally_injure = []; } +/// @desc Buffers killing volleys that share a weapon and target, summing shots and kills so a split +/// volley (many sub-stacks firing at one target) collapses into one line. The first volley's +/// rich flavour is kept and used verbatim if no second volley merges with it. Switching target +/// flushes the previous target first, keeping the log chronological. +function combat_kill_tally_add(_target, _weapon, _shots, _kills, _attack, _size, _priority, _leader) { + if (!variable_global_exists("ktally_target")) { + global.ktally_target = undefined; + global.ktally_weapons = {}; + global.ktally_order = []; + global.ktally_leaders = []; + } + if (global.ktally_target != _target) { + combat_kill_tally_flush(); + global.ktally_target = _target; + global.ktally_weapons = {}; + global.ktally_order = []; + global.ktally_leaders = []; + } + if (!variable_struct_exists(global.ktally_weapons, _weapon)) { + global.ktally_weapons[$ _weapon] = { shots: 0, kills: 0, count: 0, attack: _attack, size: _size, priority: _priority }; + array_push(global.ktally_order, _weapon); + } + var _acc = global.ktally_weapons[$ _weapon]; + _acc.shots += _shots; + _acc.kills += _kills; + _acc.count += 1; + if (_leader != "") { + array_push(global.ktally_leaders, _leader); + } +} + +/// @desc Posts the buffered kills for the current target: one line per weapon (the original rich +/// line when only a single volley landed, otherwise a summed " strike at the +/// ranks, killing "), then any deferred leader lines, and clears. +function combat_kill_tally_flush() { + if (!variable_global_exists("ktally_target") || global.ktally_target == undefined) { + return; + } + var _t = global.ktally_target; + for (var _i = 0; _i < array_length(global.ktally_order); _i++) { + var _acc = global.ktally_weapons[$ global.ktally_order[_i]]; + if (_acc.count == 1) { + add_battle_log_message(_acc.attack, _acc.size, _acc.priority); + } else { + add_battle_log_message($"{_acc.shots} {global.ktally_order[_i]} strike at the {_t} ranks, killing {_acc.kills}.", _acc.size, _acc.priority); + } + display_battle_log_message(); + } + for (var _i = 0; _i < array_length(global.ktally_leaders); _i++) { + add_battle_log_message(global.ktally_leaders[_i], 0, 0); + display_battle_log_message(); + } + global.ktally_target = undefined; + global.ktally_weapons = {}; + global.ktally_order = []; + global.ktally_leaders = []; +} + /// @desc Joins firing subjects into "A", "A and B", or "A, B, and C". function combat_subject_join(_subjects) { var _n = array_length(_subjects); From d93c60e67f7fa9b705c3a0c2403ae61dfed535e8 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 29 Jun 2026 08:59:11 +0300 Subject: [PATCH 044/140] Merging with upstream --- datafiles/data/gear.json | 1 + objects/obj_al_ship/Alarm_0.gml | 4 - objects/obj_al_ship/Create_0.gml | 9 +- objects/obj_al_ship/Step_0.gml | 61 +- objects/obj_bomb_select/Draw_0.gml | 12 +- objects/obj_controller/Alarm_1.gml | 64 +- objects/obj_controller/Alarm_5.gml | 2 +- objects/obj_controller/Create_0.gml | 4 +- objects/obj_controller/Draw_0.gml | 3 - objects/obj_controller/Draw_64.gml | 1 - objects/obj_controller/KeyPress_13.gml | 9 - objects/obj_controller/KeyPress_73.gml | 35 - objects/obj_controller/Mouse_50.gml | 27 - objects/obj_creation/Create_0.gml | 95 ++- objects/obj_creation/Draw_0.gml | 20 +- objects/obj_creation_popup/Create_0.gml | 4 + objects/obj_creation_popup/Step_0.gml | 43 +- objects/obj_credits/Draw_0.gml | 30 - objects/obj_drop_select/Alarm_2.gml | 44 +- objects/obj_drop_select/Alarm_3.gml | 54 +- objects/obj_drop_select/Alarm_4.gml | 45 +- objects/obj_drop_select/Create_0.gml | 32 +- objects/obj_drop_select/Draw_64.gml | 10 +- objects/obj_dropdown_sel/Create_0.gml | 22 +- objects/obj_dropdown_sel/Draw_0.gml | 84 +-- objects/obj_dropdown_sel/Step_0.gml | 144 +--- objects/obj_en_fleet/Alarm_1.gml | 124 +-- objects/obj_en_fleet/Alarm_3.gml | 4 - objects/obj_en_fleet/Alarm_4.gml | 121 ++- objects/obj_en_fleet/Alarm_5.gml | 3 - objects/obj_en_fleet/Alarm_8.gml | 3 +- objects/obj_en_fleet/Collision_obj_pnunit.gml | 14 - objects/obj_en_fleet/Create_0.gml | 15 +- objects/obj_en_fleet/Destroy_0.gml | 11 +- objects/obj_en_fleet/Draw_0.gml | 24 +- objects/obj_en_fleet/KeyPress_73.gml | 12 - objects/obj_en_fleet/Step_0.gml | 28 +- objects/obj_en_ship/Alarm_0.gml | 18 +- objects/obj_en_ship/Create_0.gml | 1 - objects/obj_en_ship/Draw_0.gml | 7 - objects/obj_en_ship/Step_0.gml | 367 +++------ objects/obj_enunit/Alarm_0.gml | 4 +- objects/obj_enunit/Create_0.gml | 8 +- objects/obj_event_log/Create_0.gml | 22 +- objects/obj_event_log/Draw_0.gml | 57 +- objects/obj_event_log/Mouse_60.gml | 6 - objects/obj_event_log/Mouse_61.gml | 11 - objects/obj_fleet/Alarm_1.gml | 119 +-- objects/obj_fleet/Alarm_2.gml | 81 +- objects/obj_fleet/Alarm_4.gml | 8 +- objects/obj_fleet/Alarm_6.gml | 100 +-- objects/obj_fleet/Alarm_7.gml | 69 +- objects/obj_fleet/Create_0.gml | 15 +- objects/obj_fleet/Draw_64.gml | 2 +- objects/obj_fleet/KeyPress_67.gml | 11 - objects/obj_fleet/Mouse_56.gml | 6 +- objects/obj_fleet/Step_0.gml | 7 +- objects/obj_fleet_select/Create_0.gml | 21 +- objects/obj_fleet_select/Draw_0.gml | 3 +- objects/obj_ingame_menu/Step_0.gml | 22 +- objects/obj_ini/Create_0.gml | 41 +- objects/obj_managment_panel/Create_0.gml | 5 +- objects/obj_ncombat/Alarm_0.gml | 48 +- objects/obj_ncombat/Alarm_1.gml | 57 +- objects/obj_ncombat/Alarm_2.gml | 16 +- objects/obj_ncombat/Alarm_3.gml | 44 +- objects/obj_ncombat/Alarm_4.gml | 6 +- objects/obj_ncombat/Alarm_5.gml | 13 +- objects/obj_ncombat/Alarm_7.gml | 72 +- objects/obj_ncombat/Create_0.gml | 48 +- objects/obj_ncombat/Draw_0.gml | 8 +- objects/obj_ncombat/KeyPress_13.gml | 12 - objects/obj_ncombat/Step_0.gml | 3 - objects/obj_p_assra/Step_0.gml | 15 +- objects/obj_p_fleet/Alarm_1.gml | 22 +- objects/obj_p_fleet/Alarm_11.gml | 2 +- objects/obj_p_fleet/Alarm_3.gml | 15 +- objects/obj_p_fleet/Alarm_4.gml | 12 +- objects/obj_p_fleet/Alarm_5.gml | 17 +- objects/obj_p_fleet/Alarm_6.gml | 3 - objects/obj_p_fleet/Alarm_7.gml | 3 +- objects/obj_p_fleet/Create_0.gml | 5 +- objects/obj_p_fleet/Destroy_0.gml | 4 +- objects/obj_p_fleet/Draw_0.gml | 15 +- objects/obj_p_fleet/Step_0.gml | 4 +- objects/obj_p_ship/Alarm_0.gml | 13 +- objects/obj_p_ship/Create_0.gml | 2 +- objects/obj_p_ship/Step_0.gml | 61 +- objects/obj_pnunit/Alarm_0.gml | 36 +- objects/obj_pnunit/Alarm_1.gml | 4 - objects/obj_pnunit/Alarm_3.gml | 28 +- objects/obj_pnunit/Alarm_6.gml | 23 +- objects/obj_pnunit/KeyPress_73.gml | 34 - objects/obj_pnunit/KeyPress_84.gml | 22 - objects/obj_pnunit/obj_pnunit.yy | 4 +- objects/obj_popup/Create_0.gml | 15 +- objects/obj_popup/Destroy_0.gml | 6 +- objects/obj_popup/Keyboard_13.gml | 2 +- objects/obj_popup/Step_0.gml | 10 +- objects/obj_saveload/Alarm_0.gml | 5 - objects/obj_saveload/Create_0.gml | 5 +- objects/obj_saveload/Draw_64.gml | 23 +- objects/obj_star/Alarm_1.gml | 98 +-- objects/obj_star/Alarm_3.gml | 4 +- objects/obj_star/Create_0.gml | 18 +- objects/obj_star_select/Alarm_0.gml | 33 +- objects/obj_star_select/Alarm_1.gml | 12 +- objects/obj_star_select/Create_0.gml | 10 +- objects/obj_star_select/Draw_64.gml | 47 +- objects/obj_star_select/Mouse_50.gml | 18 +- objects/obj_star_select/Step_0.gml | 3 - objects/obj_temp_build/Create_0.gml | 2 +- objects/obj_turn_end/Alarm_0.gml | 50 +- objects/obj_turn_end/Alarm_1.gml | 28 +- objects/obj_turn_end/Alarm_4.gml | 11 +- objects/obj_turn_end/Create_0.gml | 10 +- objects/obj_turn_end/Draw_0.gml | 107 +-- objects/obj_turn_end/Draw_64.gml | 11 +- objects/obj_turn_end/Mouse_56.gml | 24 +- objects/obj_turn_end/Step_0.gml | 11 +- scripts/Armamentarium/Armamentarium.gml | 5 +- scripts/ColourItem/ColourItem.gml | 11 +- scripts/DebugView/DebugView.gml | 8 +- scripts/NameGenerator/NameGenerator.gml | 24 +- scripts/instance_create/instance_create.gml | 10 +- scripts/is_specialist/is_specialist.gml | 20 +- scripts/macros/macros.gml | 3 +- .../scr_ChapterTraits/scr_ChapterTraits.gml | 18 +- scripts/scr_PlanetData/scr_PlanetData.gml | 707 +++++++++--------- scripts/scr_Table/scr_Table.gml | 3 +- scripts/scr_UnitGroup/scr_UnitGroup.gml | 3 +- scripts/scr_add_artifact/scr_add_artifact.gml | 22 +- .../scr_add_corruption/scr_add_corruption.gml | 10 +- scripts/scr_add_vehicle/scr_add_vehicle.gml | 18 +- .../scr_apothecary_ground.gml | 144 ++-- .../scr_array_functions.gml | 4 +- scripts/scr_battle_sort/scr_battle_sort.gml | 2 +- .../scr_boarding_actions.gml | 6 +- scripts/scr_buttons/scr_buttons.gml | 25 +- .../scr_chapter_managent_events.gml | 38 +- scripts/scr_chapter_new/scr_chapter_new.gml | 4 +- scripts/scr_clean/scr_clean.gml | 4 +- .../scr_company_order/scr_company_order.gml | 38 +- .../scr_company_struct/scr_company_struct.gml | 6 +- .../scr_complex_colour_kit.gml | 25 +- .../scr_creation_home_planet_create.gml | 15 +- scripts/scr_crusade/scr_crusade.gml | 19 +- .../scr_culture_visuals.gml | 9 +- .../scr_destroy_planet/scr_destroy_planet.gml | 13 +- scripts/scr_dialogue/scr_dialogue.gml | 37 +- .../scr_diplomacy_helpers.gml | 7 +- .../scr_draw_management_unit.gml | 22 +- .../scr_draw_unit_stat_data.gml | 259 +++---- .../scr_drop_select_function.gml | 14 +- scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml | 13 +- scripts/scr_enemy_ai_b/scr_enemy_ai_b.gml | 45 +- scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml | 118 +-- scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml | 76 +- .../scr_equipment_struct.gml | 2 - scripts/scr_event_code/scr_event_code.gml | 13 +- scripts/scr_event_log/scr_event_log.gml | 2 +- .../scr_event_newlines/scr_event_newlines.gml | 34 +- scripts/scr_flavor2/scr_flavor2.gml | 66 +- .../scr_fleet_functions.gml | 204 +++-- .../scr_forge_world_functions.gml | 4 +- scripts/scr_garrison/scr_garrison.gml | 5 +- .../scr_get_item_names/scr_get_item_names.gml | 2 +- scripts/scr_gift_items/scr_gift_items.gml | 19 +- .../scr_ground_ai_helpers.gml | 6 +- scripts/scr_has_adv/scr_has_adv.gml | 11 +- scripts/scr_has_disadv/scr_has_disadv.gml | 10 +- scripts/scr_hit/scr_hit.gml | 73 +- scripts/scr_image/scr_image.gml | 34 +- .../scr_imperial_manage_fleet_functions.gml | 8 +- .../scr_imperial_navy_functions.gml | 49 +- .../scr_ini_ship_cleanup.gml | 7 +- .../scr_initialize_custom.gml | 347 ++++----- .../scr_inquisition_fleet_functions.gml | 31 +- .../scr_inquisition_inspection.gml | 3 +- .../scr_inquisition_mission.gml | 54 +- .../scr_json_functions/scr_json_functions.gml | 3 - .../scr_khornate_fleet_functions.gml | 92 +-- scripts/scr_livery_setup/scr_livery_setup.gml | 5 - scripts/scr_load/scr_load.gml | 9 +- scripts/scr_manage_tags/scr_manage_tags.gml | 3 +- scripts/scr_management/scr_management.gml | 20 +- .../scr_map_and_warp_functions.gml | 66 +- .../scr_marine_struct/scr_marine_struct.gml | 129 ++-- .../scr_mechanicus_missions.gml | 12 +- scripts/scr_mission_eta/scr_mission_eta.gml | 2 +- .../scr_mission_functions.gml | 54 +- .../scr_mission_reward/scr_mission_reward.gml | 62 +- .../scr_move_unit_info/scr_move_unit_info.gml | 2 +- .../scr_ork_fleet_functions.gml | 21 +- .../scr_ork_planet_functions.gml | 4 +- scripts/scr_perils_table/scr_perils_table.gml | 91 +-- .../scr_planetary_feature.gml | 123 +-- .../scr_player_combat_weapon_stacks.gml | 41 +- .../scr_player_fleet_combat_functions.gml | 9 +- .../scr_player_fleet_functions.gml | 104 ++- .../scr_player_ship_functions.gml | 13 +- .../scr_population_influence.gml | 12 +- .../scr_popup_functions.gml | 22 +- .../scr_post_battle_events.gml | 2 +- scripts/scr_powers/scr_powers.gml | 12 +- scripts/scr_promote/scr_promote.gml | 11 +- scripts/scr_purge_world/scr_purge_world.gml | 614 ++++++++------- scripts/scr_quest/scr_quest.gml | 163 ++-- scripts/scr_random_event/scr_random_event.gml | 34 +- scripts/scr_random_find/scr_random_find.gml | 6 +- .../scr_random_marine/scr_random_marine.gml | 34 +- scripts/scr_recent/scr_recent.gml | 4 +- scripts/scr_recruit_data/scr_recruit_data.gml | 15 +- .../scr_reequip_units/scr_reequip_units.gml | 31 +- scripts/scr_return_ship/scr_return_ship.gml | 14 +- scripts/scr_role_count/scr_role_count.gml | 23 +- scripts/scr_roster/scr_roster.gml | 19 +- scripts/scr_ruins_reward/scr_ruins_reward.gml | 14 +- .../scr_serialization_functions.gml | 8 +- scripts/scr_ship_count/scr_ship_count.gml | 6 +- scripts/scr_shoot/scr_shoot.gml | 20 +- .../scr_specialist_point_handler.gml | 15 +- .../scr_specialist_points.gml | 4 +- .../scr_specialist_training.gml | 14 +- .../scr_sprite_helpers/scr_sprite_helpers.gml | 10 +- scripts/scr_squads/scr_squads.gml | 20 +- .../scr_system_search_helpers.gml | 51 +- .../scr_system_spawn_functions.gml | 21 +- scripts/scr_trade/scr_trade.gml | 6 +- scripts/scr_trade_dep/scr_trade_dep.gml | 1 + .../scr_transfer_marines.gml | 20 +- scripts/scr_turn_first/scr_turn_first.gml | 2 +- scripts/scr_ui_diplomacy/scr_ui_diplomacy.gml | 46 +- .../scr_ui_formation_bars.gml | 2 +- scripts/scr_ui_manage/scr_ui_manage.gml | 30 +- scripts/scr_ui_tooltip/scr_ui_tooltip.gml | 4 +- .../scr_unit_equip_functions.gml | 9 +- .../scr_unit_quick_find_pane.gml | 31 +- .../scr_unit_spawn_functions.gml | 6 +- .../scr_vehicle_helpers.gml | 11 +- 240 files changed, 2930 insertions(+), 5554 deletions(-) diff --git a/datafiles/data/gear.json b/datafiles/data/gear.json index cc769254d8..ee0c3bfdeb 100644 --- a/datafiles/data/gear.json +++ b/datafiles/data/gear.json @@ -41,6 +41,7 @@ "Gene Pod Incubator": { "abbreviation": "GenePod", "description": "Required to house gene slaves in order to generate new gene seed for the chapter.", + "tags":["no_equip"], "value": 20 }, "Iron Halo": { diff --git a/objects/obj_al_ship/Alarm_0.gml b/objects/obj_al_ship/Alarm_0.gml index e280bbb35b..78c3323c3a 100644 --- a/objects/obj_al_ship/Alarm_0.gml +++ b/objects/obj_al_ship/Alarm_0.gml @@ -876,8 +876,4 @@ if (owner != eFACTION.ELDAR) { shields = shields / 2; maxshields = shields; } -// if (obj_fleet.enemy=2){hp=hp*0.75;maxhp=hp;shields=shields*0.75;maxshields=shields;} -// hp=1;shields=1; -// if (obj_fleet.enemy="orks") then name=global.name_generator.GenerateFromSet("ork_ship"); name = "sdagdsagdasg"; -// show_message(string(class)); diff --git a/objects/obj_al_ship/Create_0.gml b/objects/obj_al_ship/Create_0.gml index 3b3ccd9bad..0b21ad38bb 100644 --- a/objects/obj_al_ship/Create_0.gml +++ b/objects/obj_al_ship/Create_0.gml @@ -3,8 +3,8 @@ ship_id = 0; action = ""; direction = 0; -/// @type {Asset.GMObject.obj_en_ship} -target = -50; +/// @type {Id.Instance.obj_en_ship} +target = noone; if (instance_exists(obj_en_ship)) { target = instance_nearest(x, y, obj_en_ship); } @@ -34,6 +34,11 @@ fighters = 0; bombers = 0; thunderhawks = 0; +capacity = 0; +carrying = 0; +leadership = 0; +ship_size = 0; + weapon = array_create(SHIP_WEAPON_SLOTS, ""); weapon_facing = array_create(SHIP_WEAPON_SLOTS, ""); weapon_cooldown = array_create(SHIP_WEAPON_SLOTS, 0); diff --git a/objects/obj_al_ship/Step_0.gml b/objects/obj_al_ship/Step_0.gml index d175fa43de..1155fe63a5 100644 --- a/objects/obj_al_ship/Step_0.gml +++ b/objects/obj_al_ship/Step_0.gml @@ -5,8 +5,6 @@ var front = 0, right = 0, left = 0, rear = 0; var f = 0, facing = "", ammo = 0, range = 0, wep = "", dam = 0; var o_dist = 0, spid = 0; var gud = 0; -var husk; -var explo; if (owner != 6) { image_angle = direction; @@ -60,14 +58,14 @@ if (owner != 6) { image_alpha = 0.5; if (owner != eFACTION.TYRANIDS) { - husk = instance_create(x, y, obj_en_husk); + var husk = instance_create(x, y, obj_en_husk); husk.sprite_index = sprite_index; husk.direction = direction; husk.image_angle = image_angle; husk.depth = depth; husk.image_speed = 0; for (var i = 0; i < choose(4, 5, 6); i++) { - explo = instance_create(x, y, obj_explosion); + var explo = instance_create(x, y, obj_explosion); explo.image_xscale = 0.5; explo.image_yscale = 0.5; explo.x += random_range(sprite_width * 0.25, sprite_width * -0.25); @@ -185,29 +183,6 @@ if (owner != 6) { } } } - /*if (target!=0) and (action="broadside") and (o_dist>=dist){ - direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - }*/ - /*if (target!=0) and (action="broadside") and (o_dist>=dist){ - var re_deh;re_deh=relative_direction(direction,target.direction); - // if (re_deh<45) or (re_deh>315) or ((re_deh>135) and (re_deh<225)) then direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - var wok; - wok=0; - if (!instance_exists(target_l)) then wok=2; - if (!instance_exists(target_r)) then wok=1; - if (instance_exists(target_l)) and (instance_exists(target_r)){ - if (point_distance(x,y,target_l.x,target_l.y))<(point_distance(x,y,target_r.x,target_r.y)) then wok=1; - else{wok=2;} - - } - if (wok=1){ - direction=turn_towards_point(direction,x,y,x+lengthdir_x(256,90),y+lengthdir_y(256,90),.2) - } - if (wok=2){ - direction=turn_towards_point(direction,x,y,x+lengthdir_x(256,270),y+lengthdir_y(256,270),.2) - } - // direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - }*/ // Controls speed based on action if (action == "attack") { if ((dist > o_dist) && (speed < (spid / 10))) { @@ -286,8 +261,6 @@ if (owner != 6) { targe = instance_nearest(xx, yy, obj_en_ship); rdir = point_direction(x, y, target.x, target.y); - // if (rdir>45) and (rdir<=135) and (targe!=target){target_r=targe;right=1;} - // if (rdir>225) and (rdir<=315) and (targe!=target) and (targe!=target_r){target_l=targe;left=1;} target_l = instance_nearest(x + lengthdir_x(64, direction + 90), y + lengthdir_y(64, direction + 90), obj_en_ship); target_r = instance_nearest(x + lengthdir_x(64, direction + 270), y + lengthdir_y(64, direction + 270), obj_en_ship); @@ -327,13 +300,6 @@ if (owner != 6) { if (facing == "most") { ok = 2; } - /* - if (facing="right") then targe=target_r; - if (facing="left") then targe=target_l; - if ((facing="front") or (facing="most")) and (front=1) then ok=2; - if (facing="right") or (facing="most") and (right=1) then ok=2; - if (facing="left") or (facing="most") and (left=1) then ok=2; - */ if (facing == "special") { ok = 2; } @@ -347,9 +313,6 @@ if (owner != 6) { if ((facing == "left") && (point_direction(x, y, target_r.x, target_r.y) > 22) && (point_direction(x, y, target_r.x, target_r.y) < 157)) { ok = 2; } - /*var re_deh;re_deh=relative_direction(direction,target.direction); - if (re_deh<45) or (re_deh>315) or ((re_deh>135) and (re_deh<225)) then direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - */ if ((ok == 2) && (dist < (range + max(sprite_get_width(sprite_index), sprite_get_height(sprite_index))))) { if ((ammo > 0) && (ammo < 900)) { ammo -= 1; @@ -358,7 +321,6 @@ if (owner != 6) { cooldown[gg] = weapon_cooldown[gg]; wep = weapon[gg]; dam = weapon_dam[gg]; - // if (f=3) and (ship_id=2) then show_message("ammo: "+string(ammo)+" | range: "+string(range)); if (ammo < 0) { ok = 0; } @@ -509,7 +471,7 @@ if (owner == 6) { image_alpha = 0.5; - husk = instance_create(x, y, obj_en_husk); + var husk = instance_create(x, y, obj_en_husk); husk.sprite_index = sprite_index; husk.direction = direction; husk.image_angle = image_angle; @@ -517,7 +479,7 @@ if (owner == 6) { husk.image_speed = 0; for (var i = 0; i < choose(4, 5, 6); i++) { - explo = instance_create(x, y, obj_explosion); + var explo = instance_create(x, y, obj_explosion); explo.image_xscale = 0.5; explo.image_yscale = 0.5; explo.x += random_range(sprite_width * 0.25, sprite_width * -0.25); @@ -624,8 +586,6 @@ if (owner == 6) { targe = instance_nearest(xx, yy, obj_en_ship); rdir = point_direction(x, y, target.x, target.y); - // if (rdir>45) and (rdir<=135) and (targe!=target){target_r=targe;right=1;} - // if (rdir>225) and (rdir<=315) and (targe!=target) and (targe!=target_r){target_l=targe;left=1;} target_l = instance_nearest(x + lengthdir_x(64, direction + 90), y + lengthdir_y(64, direction + 90), obj_en_ship); target_r = instance_nearest(x + lengthdir_x(64, direction + 270), y + lengthdir_y(64, direction + 270), obj_en_ship); @@ -639,7 +599,6 @@ if (owner == 6) { range = 0; wep = ""; dam = 0; - gg = 0; for (var gg = 1; gg <= weapons; gg++) { ok = 0; @@ -665,13 +624,6 @@ if (owner == 6) { if (facing == "most") { ok = 2; } - /* - if (facing="right") then targe=target_r; - if (facing="left") then targe=target_l; - if ((facing="front") or (facing="most")) and (front=1) then ok=2; - if (facing="right") or (facing="most") and (right=1) then ok=2; - if (facing="left") or (facing="most") and (left=1) then ok=2; - */ if (facing == "special") { ok = 2; } @@ -686,10 +638,6 @@ if (owner == 6) { if ((facing == "left") && (point_direction(x, y, target_r.x, target_r.y) > 22) && (point_direction(x, y, target_r.x, target_r.y) < 157)) { ok = 2; } - /* - var re_deh;re_deh=relative_direction(direction,target.direction); - if (re_deh<45) or (re_deh>315) or ((re_deh>135) and (re_deh<225)) then direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - */ if ((ok == 2) && (dist < (range + max(sprite_get_width(sprite_index), sprite_get_height(sprite_index))))) { if ((ammo > 0) && (ammo < 900)) { ammo -= 1; @@ -698,7 +646,6 @@ if (owner == 6) { cooldown[gg] = weapon_cooldown[gg]; wep = weapon[gg]; dam = weapon_dam[gg]; - // if (f=3) and (ship_id=2) then show_message("ammo: "+string(ammo)+" | range: "+string(range)); if (ammo < 0) { ok = 0; } diff --git a/objects/obj_bomb_select/Draw_0.gml b/objects/obj_bomb_select/Draw_0.gml index 0850d58e03..5ff3d97ced 100644 --- a/objects/obj_bomb_select/Draw_0.gml +++ b/objects/obj_bomb_select/Draw_0.gml @@ -37,13 +37,12 @@ if ((max_ships > 0) && instance_exists(obj_star_select)) { draw_text_transformed(bomb_window.x1 + 18, bomb_window.y1 + 30, "Initializing Bombardment...", 0.8, 0.8, 0); // Target info - var _total_hers, _influ; draw_set_font(fnt_info); draw_text_bold(bomb_window.x1 + 20, bomb_window.y1 + 70, $"Target planet: {p_data.name()}"); - _total_hers = p_data.corruption + p_data.secret_corruption; - - _influ = p_data.population_influences; + var _total_hers = p_data.corruption + p_data.secret_corruption; + var str = 0; + var _influ = p_data.population_influences; var population_string = $"Population: {p_data.display_population()} people"; draw_text_bold(bomb_window.x1 + 20, bomb_window.y1 + 90, population_string); @@ -91,7 +90,7 @@ if ((max_ships > 0) && instance_exists(obj_star_select)) { break; } - var str = 0, str_string = ""; + var str_string = ""; // TODO a centralised point to be able to fetch display names from factions identifying number str = floor(p_data.planet_forces[target]); if (target == 2.5) { @@ -150,8 +149,7 @@ if ((max_ships > 0) && instance_exists(obj_star_select)) { // Total selection number draw_set_halign(fa_left); draw_set_font(fnt_info); - var sel = ""; - sel = ships_selected; + var sel = ships_selected; var curr_sel_string = $"Current Selection: {sel} ships"; draw_text_bold(bomb_window.x1 + 20, bomb_window.y2 - 28, curr_sel_string); diff --git a/objects/obj_controller/Alarm_1.gml b/objects/obj_controller/Alarm_1.gml index 0c5b7673d7..ec35ac28aa 100644 --- a/objects/obj_controller/Alarm_1.gml +++ b/objects/obj_controller/Alarm_1.gml @@ -8,9 +8,7 @@ instance_activate_all(); // Lots of damn tyranids // Some damn orks and a few genestealer cults -var field = ""; - -field = "both"; //("orks","tyranids","both"); +var field = "both"; // "orks", "tyranids", "both" if (global.chapter_name == "Lamenters") { field = "both"; } @@ -20,7 +18,7 @@ if (is_test_map == true) { good_log = 1; -var xx, yy, ok = 0, did = 0, _current_system = 0, px = 0, py = 0, rando = 0; +var xx, yy, did = 0, _current_system = 0, px = 0, py = 0; // Set player set _current_system = find_player_spawn_star(); @@ -102,16 +100,6 @@ if (did) { _current_system.image_index = 4; _current_system.p_type[1] = "Forge"; _current_system.p_type[2] = "Ice"; - /* - _current_system.p_owner[1]=3; - _current_system.p_owner[2]=3; - _current_system.p_owner[3]=3; - _current_system.p_owner[4]=3; - _current_system.p_first[1]=3; - _current_system.p_first[2]=3; - _current_system.p_first[3]=3; - _current_system.p_first[4]=3; - */ _current_system.owner = eFACTION.MECHANICUS; _current_system.p_owner = array_create(5, _current_system.owner); _current_system.p_first = array_create(5, _current_system.owner); @@ -121,7 +109,6 @@ if (did) { } with (_current_system) { - // with _current_system var a = 99, b = 99, c = 99, d = 99, e = "", f = 0; for (var i = 0; i < 10; i++) { e = p_type[1]; @@ -280,8 +267,6 @@ if (did) { } } // end with _current_system - // _current_system.explored=1; - repeat (6) { instance_deactivate_object(instance_nearest(xx, yy, obj_star)); } @@ -326,7 +311,6 @@ if (did) { var tau_start_size = irandom(4) + 5; for (var i = 0; i <= tau_start_size; i++) { - rando = 1; _current_system = instance_nearest(xx, yy, obj_star); with (_current_system) { if ((planets > 0) && (_current_system.p_type[1] != "Dead") && (_current_system.owner == eFACTION.IMPERIUM)) { @@ -368,7 +352,7 @@ if (did) { ]; with (obj_star) { if (array_contains(hell_holes, name)) { - rando = choose(1, 1); // make 1's 0's if you want less chaos + var rando = choose(1, 1); // make 1's 0's if you want less chaos if (rando == 1) { owner = eFACTION.CHAOS; p_owner = array_create(5, owner); @@ -411,7 +395,6 @@ if (did) { if (field == "both") { orkz += 15; } - /*if (obj_ini.fleet_type==ePLAYER_BASE.PENITENT) then orkz+=2;*/ if (is_test_map == true) { orkz = 4; } @@ -514,7 +497,7 @@ for (var i = 0; i < 100; i++) { if (point_distance(room_width / 2, room_height / 2, xx, yy) >= 50) { go = 1; } - me = instance_nearest(xx, yy, obj_star); + var me = instance_nearest(xx, yy, obj_star); if ((go == 1) && (point_distance(me.x, me.y, xx, yy) >= 150)) { go = 2; } @@ -582,41 +565,6 @@ with (obj_creation) { create_complex_star_routes(_player_star.id); -/* //135 testing crusade object -instance_create(x,y,obj_crusade); -obj_crusade.placing=1;scr_zoom();*/ - -// 135 ; testing artifacts with combat -// argument0 : type -// argument1 : tags -// argument2 : identified -// argument3: location -// argument4: sid - -// scr_add_artifact("Weapon","",4,obj_ini.home_name,1); - -/*scr_add_artifact("good","daemonic",0,obj_ini.ship[0],501); -scr_add_artifact("good","daemonic",0,obj_ini.ship[0],501); -scr_add_artifact("good","daemonic",0,obj_ini.ship[0],501); -scr_add_artifact("good","daemonic",0,obj_ini.ship[0],501); -scr_add_artifact("good","daemonic",0,obj_ini.ship[0],501); -scr_add_artifact("good","daemonic",0,obj_ini.ship[0],501); -scr_add_artifact("good","daemonic",0,obj_ini.ship[0],501);*/ - -// scr_add_item("Cyclonic Torpedo",5); -// scr_add_item("Exterminatus",5); - -if (is_test_map == true) { - // scr_add_item("Exterminatus",5); - /*scr_add_artifact("good","",0,obj_ini.ship[0],501); - scr_add_artifact("good","",0,obj_ini.ship[0],501); - scr_add_artifact("good","",0,obj_ini.ship[0],501); - scr_add_artifact("good","",0,obj_ini.ship[0],501); - scr_add_artifact("good","",0,obj_ini.ship[0],501); - scr_add_artifact("good","",0,obj_ini.ship[0],501); - scr_add_artifact("good","",0,obj_ini.ship[0],501);*/ -} - with (obj_temp7) { instance_destroy(); } @@ -635,10 +583,6 @@ if (instance_exists(obj_temp7)) { } } -/*with(obj_star){ - scr_star_ownership(false); -}*/ - // Save immediately after world gen if (global.load == -1 && global.settings.autosave == true) { alarm[2] = 5; diff --git a/objects/obj_controller/Alarm_5.gml b/objects/obj_controller/Alarm_5.gml index e68d7e6c36..7444a45fc7 100644 --- a/objects/obj_controller/Alarm_5.gml +++ b/objects/obj_controller/Alarm_5.gml @@ -340,7 +340,7 @@ try { } with (_stars[i]) { if (owner == eFACTION.IMPERIUM && planets) { - if (scr_orbiting_fleet(eFACTION.IMPERIUM) != "none") { + if (scr_orbiting_fleet(eFACTION.IMPERIUM) != noone) { _star_found = true; _choice_star = self.id; break; diff --git a/objects/obj_controller/Create_0.gml b/objects/obj_controller/Create_0.gml index f1b8d3ccf4..42e9be7f2d 100644 --- a/objects/obj_controller/Create_0.gml +++ b/objects/obj_controller/Create_0.gml @@ -101,6 +101,7 @@ unit_manage_constants = {}; unit_manage_constants.current_data = ""; management_buttons = false; +diplo_buttons = {}; diplomacy_pathway = ""; option_selections = []; ready = false; @@ -804,9 +805,6 @@ trade_attempt = false; // ** Sets income ** income = 0; income_last = 0; -/*income-=obj_ini.battle_barges; -income-=obj_ini.strike_cruisers/2; -income-=(obj_ini.gladius+obj_ini.hunters)/10;*/ income_base = 0; income_home = 0; income_forge = 0; diff --git a/objects/obj_controller/Draw_0.gml b/objects/obj_controller/Draw_0.gml index 014492f1d9..d1f05f535d 100644 --- a/objects/obj_controller/Draw_0.gml +++ b/objects/obj_controller/Draw_0.gml @@ -4,9 +4,6 @@ try { scr_ui_advisors(); scr_ui_tooltip(); if (menu == eMENU.DIPLOMACY) { - /*if (audience > 0 && instance_exists(obj_turn_end)){ - menu = 20; - }*/ scr_ui_diplomacy(); } if (menu == eMENU.SECRET_LAIR) { diff --git a/objects/obj_controller/Draw_64.gml b/objects/obj_controller/Draw_64.gml index 96f77dc779..83f1318404 100644 --- a/objects/obj_controller/Draw_64.gml +++ b/objects/obj_controller/Draw_64.gml @@ -40,7 +40,6 @@ try { menu = eMENU.DEFAULT; } -// if (instance_exists(obj_turn_end)) then exit; draw_set_alpha(1); draw_set_valign(fa_top); draw_set_halign(fa_left); diff --git a/objects/obj_controller/KeyPress_13.gml b/objects/obj_controller/KeyPress_13.gml index f308c78a21..e69de29bb2 100644 --- a/objects/obj_controller/KeyPress_13.gml +++ b/objects/obj_controller/KeyPress_13.gml @@ -1,9 +0,0 @@ -/*var onceh;onceh=0; -if (new_buttons_hide=0) and (onceh=0){onceh=1;new_buttons_hide=1;} -if (new_buttons_hide=1) and (onceh=0){onceh=1;new_buttons_hide=0;} -*/ - -// scr_gov_disp("Ariana Prime",1,choose(1,2,3,4,5)); - -/* */ -/* */ diff --git a/objects/obj_controller/KeyPress_73.gml b/objects/obj_controller/KeyPress_73.gml index 876a6afc51..e69de29bb2 100644 --- a/objects/obj_controller/KeyPress_73.gml +++ b/objects/obj_controller/KeyPress_73.gml @@ -1,35 +0,0 @@ -/*var onceh;onceh=0; -if (audio_is_playing(snd_royal)=true) then scr_music("blood",2000); -if (audio_is_playing(snd_blood)=true) then scr_music("royal",2000); -*/ - -/*menu=20;diplomacy=10.1; -scr_dialogue("lol"); -*/ - -// alarm[7]=1; - -/*with(obj_star){ - var balh;balh=0; - if (string_count("WL10",p_feature[1])>0) then balh=1; - if (string_count("WL10",p_feature[2])>0) then balh=2; - if (string_count("WL10",p_feature[3])>0) then balh=3; - if (string_count("WL10",p_feature[4])>0) then balh=4; - if (balh>0) then show_message(string(name)+" "+scr_roman(balh)); -}*/ - -// loyalty=0;loyalty_hidden=0; - -// show_message(string(obj_ini.ship[0])+" location: "+string(obj_ini.ship_location[0])); - -// alarm[8]=1; - -// menu=20; -// diplomacy=-5.3; - -// show_message(cooldown); - -// instance_activate_object(obj_enunit); - -/* */ -/* */ diff --git a/objects/obj_controller/Mouse_50.gml b/objects/obj_controller/Mouse_50.gml index 532aac4372..d555496424 100644 --- a/objects/obj_controller/Mouse_50.gml +++ b/objects/obj_controller/Mouse_50.gml @@ -142,33 +142,6 @@ if ((menu == 12) && (cooldown <= 0) && (penitorium > 0)) { } } } -// ** Fleet count ** -// Moved to scr_fleet_advisor(); -/* if (menu==16) and (cooldown<=0){ - var i=ship_current; - for(var j=0; j<34; j++){ - i+=1; - if (obj_ini.ship[i]!="") and (mouse_x>=xx+953) and (mouse_x>=yy+84+(i*20)) and (mouse_x 0) || ((diplomacy < -5) && (diplomacy > -6)) && (cooldown <= 0) && (diplomacy < 10)) { diff --git a/objects/obj_creation/Create_0.gml b/objects/obj_creation/Create_0.gml index fa45f5d93f..0ecaca9b9d 100644 --- a/objects/obj_creation/Create_0.gml +++ b/objects/obj_creation/Create_0.gml @@ -7,27 +7,27 @@ keyboard_string = ""; #region Icon Grid settings for chapter selection icon_width = 48; icon_height = 48; -/// distance between 2 rows of icons in the grid +// distance between 2 rows of icons in the grid icon_row_gap = 60; -/// distance between section heading and icon grid row +// distance between section heading and icon grid row icon_gap_y = 34; -/// distance between columns in icon grid +// distance between columns in icon grid icon_gap_x = 53; -/// x coord of left edge of the icon grid +// x coord of left edge of the icon grid icon_grid_left_edge = 441; -/// Max number of columns of icons until a new row is made +// Max number of columns of icons until a new row is made max_cols = 10; -/// x coord of the right edge of the icon grid +// x coord of the right edge of the icon grid icon_grid_right_edge = function() { return icon_grid_left_edge + (icon_gap_x * max_cols - 1); }; // icon_gap_x * max number of desired columns - 1 -/// y coord of Founding section heading +// y coord of Founding section heading founding_y = 133; -/// y coord of Successor section heading +// y coord of Successor section heading successor_y = 250; -/// y coord of Custom section heading +// y coord of Custom section heading custom_y = 463; -/// y coord of Other section heading +// y coord of Other section heading other_y = 593; var view = new DebugView("Obj Creation Grid", self); @@ -60,6 +60,7 @@ company_liveries = ""; complex_livery = false; complex_selection = "sgt"; complex_depth_selection = 0; +allow_colour_click = false; //TODO probably make this array based at some point ot match other unit data complex_livery_data = complex_livery_default(); left_data_slate = new DataSlate(); @@ -131,8 +132,8 @@ temp = 0; target_gear = 0; tab = 0; role_names_all = ""; +custom_roles = {}; -// chapter_name = "Unnamed"; chapter_string = "Unnamed"; chapter_year = 0; @@ -303,37 +304,37 @@ function ChapterDataLite(_id, _origin, _progenitor, _name, _tooltip, _icon_name // For new additions, as long as the order in the array is the same as the enum order, //you will be able to index the array by using syntax like so: `var dark_angels = all_chapters[CHAPTERS.DARK_ANGELS]` all_chapters = [ - new ChapterDataLite(eCHAPTERS.UNKNOWN, eCHAPTER_ORIGINS.NONE, 0, "Unknown", "Error: The tooltip is missing", "unknown"), - new ChapterDataLite(eCHAPTERS.DARK_ANGELS, eCHAPTER_ORIGINS.FOUNDING, 0, "Dark Angels", "The Dark Angels claim complete allegiance and service to the Emperor of Mankind, though their actions and secret goals seem to run counter to this- above all other things they strive to atone for an ancient crime of betrayal.", "dark_angels"), - new ChapterDataLite(eCHAPTERS.WHITE_SCARS, eCHAPTER_ORIGINS.FOUNDING, 0, "White Scars", "Known and feared for their highly mobile way of war, the White Scars are the masters of lightning strikes and hit-and-run tactics. They are particularly adept in the use of Attack Bikes and field large numbers of them.", "white_scars"), - new ChapterDataLite(eCHAPTERS.SPACE_WOLVES, eCHAPTER_ORIGINS.FOUNDING, 0, "Space Wolves", "Brave sky warriors hailing from the icy deathworld of Fenris, the Space Wolves are a non-Codex compliant chapter, and deadly in close combat. They fight on their own terms and damn any who wish otherwise.", "space_wolves"), - new ChapterDataLite(eCHAPTERS.IMPERIAL_FISTS, eCHAPTER_ORIGINS.FOUNDING, 0, "Imperial Fists", "Siege-masters of utmost excellence, the Imperial Fists stoicism has lead them to great victories and horrifying defeats. To them, the idea of a tactical retreat is utterly inconsiderable. They hold ground on Inwit vigilantly, refusing to back down from any fight.", "imperial_fists"), - new ChapterDataLite(eCHAPTERS.BLOOD_ANGELS, eCHAPTER_ORIGINS.FOUNDING, 0, "Blood Angels", "One of the most noble and renowned chapters, their combat record belies a dark flaw in their gene-seed caused by the death of their primarch. Their primarch had wings and a propensity for close combat, and this shows in their extensive use of jump packs and close quarters weapons.", "blood_angels"), - new ChapterDataLite(eCHAPTERS.IRON_HANDS, eCHAPTER_ORIGINS.FOUNDING, 0, "Iron Hands", "The flesh is weak, and the weak shall perish. Such is the creed of these mercilessly efficient cyborg warriors. A chapter with strong ties to the Mechanicum, they crush the foes of the Emperor and Machine God alike with a plethora of exotic technology and ancient weaponry.", "iron_hands"), - new ChapterDataLite(eCHAPTERS.ULTRAMARINES, eCHAPTER_ORIGINS.FOUNDING, 0, "Ultramarines", "An honourable and venerated chapter, the Ultramarines are considered to be amongst the best of the best. Their Primarch was the author of the great tome of the “Codex Astartes”, and they are considered exemplars of what a perfect Space Marine Chapter should be like.", "ultramarines"), - new ChapterDataLite(eCHAPTERS.SALAMANDERS, eCHAPTER_ORIGINS.FOUNDING, 0, "Salamanders", "Followers of the Promethean Cult, the jet-black skinned Salamanders are forgemasters of legend. They are armed with the best wargear available and prefer flame based weaponry. Their only drawback is their low numbers and slow recruiting.", "salamanders"), - new ChapterDataLite(eCHAPTERS.RAVEN_GUARD, eCHAPTER_ORIGINS.FOUNDING, 0, "Raven Guard", "Clinging to the shadows and riding the edge of lightning the Raven Guard strike out at the hated enemy with stealth and speed. Using lightning strikes, hit and run tactics, and guerrilla warfare, they are known for being there one second and gone the next.", "raven_guard"), + new ChapterDataLite(eCHAPTERS.UNKNOWN, eCHAPTER_ORIGINS.NONE, eCHAPTERS.UNKNOWN, "Unknown", "Error: The tooltip is missing", "unknown"), + new ChapterDataLite(eCHAPTERS.DARK_ANGELS, eCHAPTER_ORIGINS.FOUNDING, eCHAPTERS.UNKNOWN, "Dark Angels", "The Dark Angels claim complete allegiance and service to the Emperor of Mankind, though their actions and secret goals seem to run counter to this- above all other things they strive to atone for an ancient crime of betrayal.", "dark_angels"), + new ChapterDataLite(eCHAPTERS.WHITE_SCARS, eCHAPTER_ORIGINS.FOUNDING, eCHAPTERS.UNKNOWN, "White Scars", "Known and feared for their highly mobile way of war, the White Scars are the masters of lightning strikes and hit-and-run tactics. They are particularly adept in the use of Attack Bikes and field large numbers of them.", "white_scars"), + new ChapterDataLite(eCHAPTERS.SPACE_WOLVES, eCHAPTER_ORIGINS.FOUNDING, eCHAPTERS.UNKNOWN, "Space Wolves", "Brave sky warriors hailing from the icy deathworld of Fenris, the Space Wolves are a non-Codex compliant chapter, and deadly in close combat. They fight on their own terms and damn any who wish otherwise.", "space_wolves"), + new ChapterDataLite(eCHAPTERS.IMPERIAL_FISTS, eCHAPTER_ORIGINS.FOUNDING, eCHAPTERS.UNKNOWN, "Imperial Fists", "Siege-masters of utmost excellence, the Imperial Fists stoicism has lead them to great victories and horrifying defeats. To them, the idea of a tactical retreat is utterly inconsiderable. They hold ground on Inwit vigilantly, refusing to back down from any fight.", "imperial_fists"), + new ChapterDataLite(eCHAPTERS.BLOOD_ANGELS, eCHAPTER_ORIGINS.FOUNDING, eCHAPTERS.UNKNOWN, "Blood Angels", "One of the most noble and renowned chapters, their combat record belies a dark flaw in their gene-seed caused by the death of their primarch. Their primarch had wings and a propensity for close combat, and this shows in their extensive use of jump packs and close quarters weapons.", "blood_angels"), + new ChapterDataLite(eCHAPTERS.IRON_HANDS, eCHAPTER_ORIGINS.FOUNDING, eCHAPTERS.UNKNOWN, "Iron Hands", "The flesh is weak, and the weak shall perish. Such is the creed of these mercilessly efficient cyborg warriors. A chapter with strong ties to the Mechanicum, they crush the foes of the Emperor and Machine God alike with a plethora of exotic technology and ancient weaponry.", "iron_hands"), + new ChapterDataLite(eCHAPTERS.ULTRAMARINES, eCHAPTER_ORIGINS.FOUNDING, eCHAPTERS.UNKNOWN, "Ultramarines", "An honourable and venerated chapter, the Ultramarines are considered to be amongst the best of the best. Their Primarch was the author of the great tome of the “Codex Astartes”, and they are considered exemplars of what a perfect Space Marine Chapter should be like.", "ultramarines"), + new ChapterDataLite(eCHAPTERS.SALAMANDERS, eCHAPTER_ORIGINS.FOUNDING, eCHAPTERS.UNKNOWN, "Salamanders", "Followers of the Promethean Cult, the jet-black skinned Salamanders are forgemasters of legend. They are armed with the best wargear available and prefer flame based weaponry. Their only drawback is their low numbers and slow recruiting.", "salamanders"), + new ChapterDataLite(eCHAPTERS.RAVEN_GUARD, eCHAPTER_ORIGINS.FOUNDING, eCHAPTERS.UNKNOWN, "Raven Guard", "Clinging to the shadows and riding the edge of lightning the Raven Guard strike out at the hated enemy with stealth and speed. Using lightning strikes, hit and run tactics, and guerrilla warfare, they are known for being there one second and gone the next.", "raven_guard"), new ChapterDataLite(eCHAPTERS.BLACK_TEMPLARS, eCHAPTER_ORIGINS.SUCCESSOR, eCHAPTERS.IMPERIAL_FISTS, "Black Templars", "Not adhering to the Codex Astartes, Black Templars are a Chapter on an Eternal Crusade with unique organization and high numbers. Masters of assault, they charge at the enemy with zeal unmatched. They hate psykers, and as such, have no Librarians.", "black_templars"), new ChapterDataLite(eCHAPTERS.MINOTAURS, eCHAPTER_ORIGINS.SUCCESSOR, eCHAPTERS.IMPERIAL_FISTS, "Minotaurs", "Bronze-clad Astartes of unknown Founding, the Minotaurs prefer to channel their righteous fury in a massive storm of fire, with tanks and artillery. They could be considered the Inquisition’s attack dog, since they often attack fellow chapters suspected of heresy.", "minotaurs"), - new ChapterDataLite(eCHAPTERS.BLOOD_RAVENS, eCHAPTER_ORIGINS.SUCCESSOR, 0, "Blood Ravens", "Of unknown origins and Founding, the origins of the Blood Ravens are shrouded in mystery and are believed to be tied to a dark truth. This elusive Chapter is drawn to the pursuit of knowledge and ancient lore and produces an unusually high number of Librarians.", "blood_ravens"), + new ChapterDataLite(eCHAPTERS.BLOOD_RAVENS, eCHAPTER_ORIGINS.SUCCESSOR, eCHAPTERS.UNKNOWN, "Blood Ravens", "Of unknown origins and Founding, the origins of the Blood Ravens are shrouded in mystery and are believed to be tied to a dark truth. This elusive Chapter is drawn to the pursuit of knowledge and ancient lore and produces an unusually high number of Librarians.", "blood_ravens"), new ChapterDataLite(eCHAPTERS.CRIMSON_FISTS, eCHAPTER_ORIGINS.SUCCESSOR, eCHAPTERS.IMPERIAL_FISTS, "Crimson Fists", "An Imperial Fists descendant, the Crimson Fists are more level-minded than their Progenitor and brother chapters. They suffer the same lacking zygotes as their ancestors, and more resemble the Ultramarines in their balanced approach to combat. After surviving a devastating Ork WAAAGH! the chapter clings dearly to its future.", "crimson_fists"), new ChapterDataLite(eCHAPTERS.LAMENTERS, eCHAPTER_ORIGINS.SUCCESSOR, eCHAPTERS.BLOOD_ANGELS, "Lamenters", "The Lamenter's accursed and haunted legacy seems to taint much of what they have achieved; their victories often become bitter ashes in their hands. Nearly extinct, they fight their last days on behalf of the common folk in a crusade of endless penitence.", "lamenters"), new ChapterDataLite(eCHAPTERS.CARCHARODONS, eCHAPTER_ORIGINS.SUCCESSOR, eCHAPTERS.RAVEN_GUARD, "Carcharodons", "Rumored to be Successors of the Raven Guard, these Astartes are known for their sudden attacks and shock assaults. Travelling through the Imperium via self-sufficient Nomad-Predation based fleets, no enemy is safe from the fury of these bloodthirsty Space Marines.", "carcharodons"), new ChapterDataLite(eCHAPTERS.SOUL_DRINKERS, eCHAPTER_ORIGINS.SUCCESSOR, eCHAPTERS.IMPERIAL_FISTS, "Soul Drinkers", "Sharing ancestry of the Black Templars or Crimson fists. As proud sons of Dorn they share the strong void combat traditions, fielding a large amount of Battle Barges. As well as being fearsome in close combat. Whispers of the Ruinous Powers are however quite enticing.", "soul_drinkers"), - new ChapterDataLite(eCHAPTERS.ANGRY_MARINES, eCHAPTER_ORIGINS.NON_CANON, 0, "Angry Marines", "Frothing with pathological rage since the day their Primarch emerged from his pod with naught but a dented copy of battletoads. Every last Angry Marine is a homicidal, suicidal berserker with a voice that projects, and are always angry, all the time. A /tg/ classic.", "angry_marines"), - new ChapterDataLite(eCHAPTERS.EMPERORS_NIGHTMARE, eCHAPTER_ORIGINS.NON_CANON, 0, "Emperor’s Nightmare", "The Emperor's Nightmare bear the curse of a bizarre mutation within their gene-seed. The Catalepsean Node is in a state of decay and thus do not sleep for months at a time until falling asleep suddenly. They prefer shock and awe tactics with stealth.", "emperors_nightmare"), - new ChapterDataLite(eCHAPTERS.STAR_KRAKENS, eCHAPTER_ORIGINS.NON_CANON, 0, "Star Krakens", "In darkness, they dwell in The Deep. The Star Krakens stand divided in individual companies but united in the form of the Ten-Flag Council. They utilize boarding tactics and are the sole guardians of the ancient sensor array called “The Lighthouse”.", "star_krakens"), - new ChapterDataLite(eCHAPTERS.CONSERVATORS, eCHAPTER_ORIGINS.NON_CANON, 0, "Conservators", "Hailing from the Asharn Marches and having established their homeworld on the planet Dekara, these proud sons of Dorn suffer from an extreme lack of supplies, Ork raids, and more. Though under strength and lacking equipment, they managed to forge an interstellar kingdom loyal to both Emperor and Imperium.", "conservators"), - new ChapterDataLite(eCHAPTERS.CUSTOM_1, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter"), - new ChapterDataLite(eCHAPTERS.CUSTOM_2, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter"), - new ChapterDataLite(eCHAPTERS.CUSTOM_3, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter"), - new ChapterDataLite(eCHAPTERS.CUSTOM_4, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter"), - new ChapterDataLite(eCHAPTERS.CUSTOM_5, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter"), - new ChapterDataLite(eCHAPTERS.CUSTOM_6, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter"), - new ChapterDataLite(eCHAPTERS.CUSTOM_7, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter"), - new ChapterDataLite(eCHAPTERS.CUSTOM_8, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter"), - new ChapterDataLite(eCHAPTERS.CUSTOM_9, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter"), - new ChapterDataLite(eCHAPTERS.CUSTOM_10, eCHAPTER_ORIGINS.CUSTOM, 0, "Custom", "Your Chapter") + new ChapterDataLite(eCHAPTERS.ANGRY_MARINES, eCHAPTER_ORIGINS.NON_CANON, eCHAPTERS.UNKNOWN, "Angry Marines", "Frothing with pathological rage since the day their Primarch emerged from his pod with naught but a dented copy of battletoads. Every last Angry Marine is a homicidal, suicidal berserker with a voice that projects, and are always angry, all the time. A /tg/ classic.", "angry_marines"), + new ChapterDataLite(eCHAPTERS.EMPERORS_NIGHTMARE, eCHAPTER_ORIGINS.NON_CANON, eCHAPTERS.UNKNOWN, "Emperor’s Nightmare", "The Emperor's Nightmare bear the curse of a bizarre mutation within their gene-seed. The Catalepsean Node is in a state of decay and thus do not sleep for months at a time until falling asleep suddenly. They prefer shock and awe tactics with stealth.", "emperors_nightmare"), + new ChapterDataLite(eCHAPTERS.STAR_KRAKENS, eCHAPTER_ORIGINS.NON_CANON, eCHAPTERS.UNKNOWN, "Star Krakens", "In darkness, they dwell in The Deep. The Star Krakens stand divided in individual companies but united in the form of the Ten-Flag Council. They utilize boarding tactics and are the sole guardians of the ancient sensor array called “The Lighthouse”.", "star_krakens"), + new ChapterDataLite(eCHAPTERS.CONSERVATORS, eCHAPTER_ORIGINS.NON_CANON, eCHAPTERS.UNKNOWN, "Conservators", "Hailing from the Asharn Marches and having established their homeworld on the planet Dekara, these proud sons of Dorn suffer from an extreme lack of supplies, Ork raids, and more. Though under strength and lacking equipment, they managed to forge an interstellar kingdom loyal to both Emperor and Imperium.", "conservators"), + new ChapterDataLite(eCHAPTERS.CUSTOM_1, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter"), + new ChapterDataLite(eCHAPTERS.CUSTOM_2, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter"), + new ChapterDataLite(eCHAPTERS.CUSTOM_3, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter"), + new ChapterDataLite(eCHAPTERS.CUSTOM_4, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter"), + new ChapterDataLite(eCHAPTERS.CUSTOM_5, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter"), + new ChapterDataLite(eCHAPTERS.CUSTOM_6, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter"), + new ChapterDataLite(eCHAPTERS.CUSTOM_7, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter"), + new ChapterDataLite(eCHAPTERS.CUSTOM_8, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter"), + new ChapterDataLite(eCHAPTERS.CUSTOM_9, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter"), + new ChapterDataLite(eCHAPTERS.CUSTOM_10, eCHAPTER_ORIGINS.CUSTOM, eCHAPTERS.UNKNOWN, "Custom", "Your Chapter") ]; var missing_splash = 99; @@ -401,11 +402,6 @@ custom_chapters = array_filter(all_chapters, function(item) { other_chapters = array_filter(all_chapters, function(item) { return item.origin == eCHAPTER_ORIGINS.NON_CANON; }); -// LOGGER.debug($"founding: {founding_chapters}"); -// LOGGER.debug($"successor: {successor_chapters}"); -// LOGGER.debug($"custom: {custom_chapters}"); -// LOGGER.debug($"other: {other_chapters}"); - // TODO refactor into struct constructors stored in which are struct arrays // meta provides a universal way to control not having contradictory advatages and disadvantages @@ -417,10 +413,6 @@ chapter_trait_meta = []; setup_chapter_traits(); -// disadvantage[i]="Embargo";dis_tooltip[i]="NOT IMPLEMENTED YET.";i+=1;// Greatly increases the cost of common wargear and disallows advanced items. -// disadvantage[i]="First In, Last Out";dis_tooltip[i]="NOT IMPLEMENTED YET.";i+=1; -// disadvantage[i]="Rival Brotherhood";dis_tooltip[i]="NOT IMPLEMENTED YET.";i+=1; - race = []; role = []; wep1 = []; @@ -444,6 +436,14 @@ for (var slot = 99; slot <= 103; slot++) { defaults_slot = 100; +/// @description +/// @param {Real} _role_id +/// @param {String} _role_name +/// @param {String} _wep1 +/// @param {String} _wep2 +/// @param {String} _armour +/// @param {String} _mobi +/// @param {String} _gear load_default_gear = function(_role_id, _role_name, _wep1, _wep2, _armour, _mobi, _gear) { role[defaults_slot][_role_id] = _role_name; wep1[defaults_slot][_role_id] = _wep1; @@ -485,11 +485,9 @@ if (global.restart > 0) { slide_show = 2; reset_creation_variables(); - //with(obj_restart_vars){instance_destroy();} global.restart = 0; } -/* */ col = []; col_r = []; col_g = []; @@ -592,6 +590,5 @@ weapon_colour_replace = [ col_g[weapon_color] / 255, col_b[weapon_color] / 255 ]; -/* */ + alarm_set(1, 30); -/* */ diff --git a/objects/obj_creation/Draw_0.gml b/objects/obj_creation/Draw_0.gml index a8ecc0d4e8..f866158d21 100644 --- a/objects/obj_creation/Draw_0.gml +++ b/objects/obj_creation/Draw_0.gml @@ -2,18 +2,16 @@ add_draw_return_values(); draw_set_valign(fa_top); try { //read - // 850,860 var xx = 375; var yy = 10; + allow_colour_click = (custom == eCHAPTER_TYPE.CUSTOM) && (!instance_exists(obj_creation_popup)); tooltip = ""; tooltip2 = ""; draw_set_alpha(1); - // draw_sprite(spr_creation_slate,0,xx,yy); scr_image("creation/slate", 1, xx, yy, 850, 860); draw_set_alpha(1 - (slate1 / 30)); - // draw_sprite(spr_creation_slate,1,xx,yy); scr_image("creation/slate", 2, xx, yy, 850, 860); draw_set_color(#5B872E); @@ -36,8 +34,6 @@ try { draw_line(xx + 30, yy + 70 + (slate3 * 36), xx + 790, yy + 70 + (slate3 * 36)); } - allow_colour_click = (custom == eCHAPTER_TYPE.CUSTOM) && (!instance_exists(obj_creation_popup)); - draw_set_alpha(slate4 / 30); if (slate4 > 0) { /* Chapter Selection grid */ @@ -181,6 +177,7 @@ try { t_tip2: "Your Astartes lack the detoxifying gland called the Preomnor- they are more susceptible to poisons and toxins.", data: preomnor, mutation_points: 1, + disposition: [], }, { t_tip: "Disturbing Voice", @@ -215,42 +212,49 @@ try { t_tip2: "Lacking a working Lyman's ear, all deep-striked Astartes receive moderate penalties to both attack and defense.", data: lyman, mutation_points: 1, + disposition: [], }, { t_tip: "Hyper-Stimulated Omophagea", t_tip2: "After every battle the Astartes have a chance to feast upon their fallen enemies, or seldom, their allies.", data: omophagea, mutation_points: 1, + disposition: [], }, { t_tip: "Hyperactive Ossmodula", t_tip2: "Instead of wound tissue bone is generated; Apothecaries must spend twice the normal time healing your Astartes.", data: ossmodula, mutation_points: 1, + disposition: [], }, { t_tip: "Lost Zygote", t_tip2: "One of the Zygotes is faulty or missing. The Astartes only have one each and generate half the normal Gene-Seed.", data: zygote, mutation_points: 2, + disposition: [], }, { t_tip: "Inactive Sus-an Membrane", t_tip2: "Your Astartes do not have a Sus-an Membrane; they cannot enter suspended animation and receive more casualties as a result.", data: membrane, mutation_points: 1, + disposition: [], }, { t_tip: "Missing Betchers Gland", t_tip2: "Your Astartes cannot spit acid, and as a result, have slightly less attack in melee combat.", data: betchers, mutation_points: 1, + disposition: [], }, { t_tip: "Mutated Catalepsean Node", t_tip2: "Your Astartes have reduced awareness when tired. Slightly less attack in ranged and melee combat.", data: catalepsean, mutation_points: 1, + disposition: [], }, { t_tip: "Oolitic Secretions", @@ -312,7 +316,7 @@ try { x1 = 450; y1 = 260; for (var i = 0; i < array_length(mutations_defects); i++) { - mutation_data = mutations_defects[i]; + var mutation_data = mutations_defects[i]; draw_sprite(spr_creation_check, mutation_data.data, x1, y1); if (point_and_click([x1, y1, x1 + 32, y1 + 32]) && allow_colour_click) { var onceh = 0; @@ -438,7 +442,7 @@ try { var str_width, hei; str_width = max(350, string_width(string_hash_to_newline(chapter_master_name))); hei = string_height(string_hash_to_newline(chapter_master_name)); - if (scr_hit(580 - 2, 144 - 2, 582 + str_width, 146 + hei)) { + if (scr_hit(578, 142, 582 + str_width, 146 + hei)) { obj_cursor.image_index = 2; if (mouse_button_clicked() && !instance_exists(obj_creation_popup)) { text_selected = "cm"; @@ -448,7 +452,7 @@ try { if (text_selected == "cm") { chapter_master_name = keyboard_string; } - draw_rectangle(580 - 2, 144 - 2, 582 + 350, 146 + hei, 1); + draw_rectangle(578, 142, 932, 146 + hei, 1); var _refresh_cm_name_btn = [ 943, diff --git a/objects/obj_creation_popup/Create_0.gml b/objects/obj_creation_popup/Create_0.gml index d7a7963bf5..94a744c9b5 100644 --- a/objects/obj_creation_popup/Create_0.gml +++ b/objects/obj_creation_popup/Create_0.gml @@ -8,9 +8,13 @@ rows = 0; picker = new ColourPicker(20, 550, 350); picker.disable_textures = true; start_colour = -1; +col_shift = false; +bulk_buttons = []; tooltip = ""; tooltip2 = ""; +item_name = []; +role_names_all = ""; type_names = { "1": "Primary Color", diff --git a/objects/obj_creation_popup/Step_0.gml b/objects/obj_creation_popup/Step_0.gml index b8c9de7e38..957631718e 100644 --- a/objects/obj_creation_popup/Step_0.gml +++ b/objects/obj_creation_popup/Step_0.gml @@ -1,59 +1,50 @@ role_names_all = ""; -var derpaderp, z, idd; -derpaderp = 0; -idd = 0; if (!is_string(type)) { - if (type >= 100) { - z = type - 100; - } - if (type < 100) { - z = type; - } + var z = (type >= 100) ? type - 100 : type; if (type >= 100) { - repeat (13) { - derpaderp += 1; - if (derpaderp == 1) { + for (var i = 1 ; i <= 13; i++) { + var idd = 0; + if (i == 1) { idd = 15; } - if (derpaderp == 2) { + if (i == 2) { idd = 14; } - if (derpaderp == 3) { + if (i == 3) { idd = 17; } - if (derpaderp == 4) { + if (i == 4) { idd = 16; } - if (derpaderp == 5) { + if (i == 5) { idd = 5; } - if (derpaderp == 6) { + if (i == 6) { idd = 2; } - if (derpaderp == 7) { + if (i == 7) { idd = 4; } - if (derpaderp == 8) { + if (i == 8) { idd = 3; } - if (derpaderp == 9) { + if (i == 9) { idd = 6; } - if (derpaderp == 10) { + if (i == 10) { idd = 8; } - if (derpaderp == 11) { + if (i == 11) { idd = 9; } - if (derpaderp == 12) { + if (i == 12) { idd = 10; } - if (derpaderp == 13) { + if (i == 13) { idd = 12; } - role_names_all += string(obj_creation.role[100][idd]) + "|"; } @@ -61,8 +52,6 @@ if (!is_string(type)) { role_names_all += "Master of Sanctity|"; role_names_all += "Master of the Apothecarion|"; role_names_all += "Forge Master|"; - // role_names_all+="Crusader|"; - // role_names_all+="Ranger|"; if (obj_creation.role[100][z] != "") { if (string_count(obj_creation.role[100][z], role_names_all) > 1) { diff --git a/objects/obj_credits/Draw_0.gml b/objects/obj_credits/Draw_0.gml index bdbab00d62..0d5cc1ddf2 100644 --- a/objects/obj_credits/Draw_0.gml +++ b/objects/obj_credits/Draw_0.gml @@ -31,14 +31,8 @@ draw_text_transformed(802 - 200, 472, string_hash_to_newline("ASSISTANT ARTISTS" draw_text(802 - 200, 498, string_hash_to_newline("sinndogg#efngn#Toni ''TrashMan'' Stanicic")); draw_text_transformed(802, 373, string_hash_to_newline("SUPPORTERS AND LEGACY CODERS"), 0.85, 0.85, 0); -// draw_text_transformed(802,472,"FORMER SUPPORTERS",0.85,0.85,0); draw_text(802, 397, string_hash_to_newline("Duke#Paul-Ross#MANDOZERTHEGREAT#Alex Norry#Carli")); -// draw_text(802,496,""); - -draw_set_font(fnt_cul_18); -draw_set_halign(fa_center); -draw_text_ext(room_width / 2, 706 - 25, string_hash_to_newline(obj_main_menu.legal_text), -1, 1406); draw_set_font(fnt_cul_14); draw_set_halign(fa_left); @@ -48,30 +42,8 @@ draw_text_ext(991, 92 + 15, string_hash_to_newline(@" Late 2011 /tg/ came up wi -Duke"), -1, 570); -// 253,96 - -var bhih; -bhih = 0; -if ((scr_hit(319, 307, 393, 324) == false) && (obj_main_menu.browser == 1)) { - obj_main_menu.browser = 0; -} -if (scr_hit(319, 307, 393, 324) == true) { - bhih = 1; - if ((obj_main_menu.browser == 0) && mouse_button_clicked()) { - /*switch(show_question("Open your browser?")) { - case 1:*/ - // url_open_ext( 'http://planetofthebrandons.com/donate.html', '_blank');browser=1; - if (obj_main_menu.blog_url != "Error") { - url_open_ext(obj_main_menu.blog_url, "_blank"); - } - obj_main_menu.browser = 1; - // break; - // } - } -} draw_text(257, 96, string_hash_to_newline("DukeFluffy")); draw_text_ext_transformed(257, 96, string_hash_to_newline("#A hobbyist game producer with insomnia and way too much time on his hands. Duke has created several pen and paper RPG's, namely ChromeStrike and the Morrowind RPG. He has aspirations of one day working on robots."), -1, 208 * 1.1, 0.9, 0.9, 0); -draw_sprite(spr_blog, bhih, 319, 307); if (fade_in > 0) { draw_set_color(0); @@ -88,5 +60,3 @@ if (instance_exists(obj_main_menu_buttons)) { } draw_set_alpha(1); } -/* */ -/* */ diff --git a/objects/obj_drop_select/Alarm_2.gml b/objects/obj_drop_select/Alarm_2.gml index fefcbb61e4..486ef6d44e 100644 --- a/objects/obj_drop_select/Alarm_2.gml +++ b/objects/obj_drop_select/Alarm_2.gml @@ -1,16 +1,11 @@ -var i; -i = -1; -repeat (31) { - i += 1; - ship[i] = ""; - ship_all[i] = 0; - ship_use[i] = 0; - ship_max[i] = 0; - ship_ide[i] = -1; -} +ship = array_create(31, ""); +ship_all = array_create(31, 0); +ship_use = array_create(31, 0); +ship_max = array_create(31, 0); +ship_ide = array_create(31, -1); max_ships = 0; -if (sh_target != -50) { +if (sh_target != noone) { max_ships = sh_target.capital_number + sh_target.frigate_number + sh_target.escort_number; } @@ -24,36 +19,35 @@ if (l_size > 0) { l_size = l_size * -1; } -if (sh_target != -50) { - var tump = 0; +if (sh_target != noone) { var i = 0; - for (var q = 0; q < sh_target.capital_number; q++) { - if ((sh_target.capital[q] != "") && (obj_ini.ship_carrying[sh_target.capital_num[q]] > 0)) { - ship[i] = sh_target.capital[i]; + for (var s = 0; s < sh_target.capital_number; s++) { + if ((sh_target.capital[s] != "") && (obj_ini.ship_carrying[sh_target.capital_num[s]] > 0)) { + ship[i] = sh_target.capital[s]; ship_use[i] = 0; - tump = sh_target.capital_num[i]; + var tump = sh_target.capital_num[s]; ship_max[i] = obj_ini.ship_carrying[tump]; ship_ide[i] = tump; ship_size[i] = 3; i += 1; } } - for (var q = 0; q < sh_target.frigate_number; q++) { - if ((sh_target.frigate[q] != "") && (obj_ini.ship_carrying[sh_target.frigate_num[q]] > 0)) { - ship[i] = sh_target.frigate[q]; + for (var s = 0; s < sh_target.frigate_number; s++) { + if ((sh_target.frigate[s] != "") && (obj_ini.ship_carrying[sh_target.frigate_num[s]] > 0)) { + ship[i] = sh_target.frigate[s]; ship_use[i] = 0; - tump = sh_target.frigate_num[q]; + var tump = sh_target.frigate_num[s]; ship_max[i] = obj_ini.ship_carrying[tump]; ship_ide[i] = tump; ship_size[i] = 2; i += 1; } } - for (var q = 0; q < sh_target.escort_number; q++) { - if ((sh_target.escort[q] != "") && (obj_ini.ship_carrying[sh_target.escort_num[q]] > 0)) { - ship[i] = sh_target.escort[q]; + for (var s = 0; s < sh_target.escort_number; s++) { + if ((sh_target.escort[s] != "") && (obj_ini.ship_carrying[sh_target.escort_num[s]] > 0)) { + ship[i] = sh_target.escort[s]; ship_use[i] = 0; - tump = sh_target.escort_num[q]; + var tump = sh_target.escort_num[s]; ship_max[i] = obj_ini.ship_carrying[tump]; ship_ide[i] = tump; ship_size[i] = 1; diff --git a/objects/obj_drop_select/Alarm_3.gml b/objects/obj_drop_select/Alarm_3.gml index 95134e0c6f..0b91fa8255 100644 --- a/objects/obj_drop_select/Alarm_3.gml +++ b/objects/obj_drop_select/Alarm_3.gml @@ -1,34 +1,22 @@ -var i; -i = -1; -repeat (61) { - i += 1; - ship[i] = ""; - ship_all[i] = 0; - ship_use[i] = 0; - ship_max[i] = 0; - ship_ide[i] = -1; -} +ship = array_create(61, ""); +ship_all = array_create(61, 0); +ship_use = array_create(61, 0); +ship_max = array_create(61, 0); +ship_ide = array_create(61, -1); max_ships = 0; -if (sh_target != -50) { +if (sh_target != noone) { max_ships = sh_target.capital_number + sh_target.frigate_number + sh_target.escort_number; - var tump; - tump = 0; - - var i, q, b; - i = 0; - q = 0; - b = 0; - repeat (sh_target.capital_number) { - b += 1; - if (sh_target.capital[b] != "") { + var i = 0; + for (var s = 1; s <= sh_target.capital_number; s++) { + if (sh_target.capital[s] != "") { i += 1; - ship[i] = sh_target.capital[i]; + ship[i] = sh_target.capital[s]; ship_use[i] = 0; - tump = sh_target.capital_num[i]; + var tump = sh_target.capital_num[s]; ship_max[i] = obj_ini.ship_carrying[tump]; ship_ide[i] = tump; ship_size[i] = 3; @@ -38,15 +26,13 @@ if (sh_target != -50) { purge_c += ship_max[i]; } } - q = 0; - repeat (sh_target.frigate_number) { - q += 1; - if (sh_target.frigate[q] != "") { + for (var s = 1; s <= sh_target.frigate_number; s++) { + if (sh_target.frigate[s] != "") { i += 1; - ship[i] = sh_target.frigate[q]; + ship[i] = sh_target.frigate[s]; ship_use[i] = 0; - tump = sh_target.frigate_num[q]; + var tump = sh_target.frigate_num[s]; ship_max[i] = obj_ini.ship_carrying[tump]; ship_ide[i] = tump; ship_size[i] = 2; @@ -56,15 +42,13 @@ if (sh_target != -50) { purge_c += ship_max[i]; } } - q = 0; - repeat (sh_target.escort_number) { - q += 1; - if ((sh_target.escort[q] != "") && (obj_ini.ship_carrying[sh_target.escort_num[q]] > 0)) { + for (var s = 1; s <= sh_target.escort_number; s++) { + if ((sh_target.escort[s] != "") && (obj_ini.ship_carrying[sh_target.escort_num[s]] > 0)) { i += 1; - ship[i] = sh_target.escort[q]; + ship[i] = sh_target.escort[s]; ship_use[i] = 0; - tump = sh_target.escort_num[q]; + var tump = sh_target.escort_num[s]; ship_max[i] = obj_ini.ship_carrying[tump]; ship_ide[i] = tump; ship_size[i] = 1; diff --git a/objects/obj_drop_select/Alarm_4.gml b/objects/obj_drop_select/Alarm_4.gml index da2daf698f..f8f2febae1 100644 --- a/objects/obj_drop_select/Alarm_4.gml +++ b/objects/obj_drop_select/Alarm_4.gml @@ -1,36 +1,23 @@ // This confirms the number of ships available for bombarding - -var i; -i = -1; -repeat (61) { - i += 1; - ship[i] = ""; - ship_all[i] = 0; - ship_use[i] = 0; - ship_max[i] = 0; - ship_ide[i] = -1; -} +ship = array_create(61, ""); +ship_all = array_create(61, 0); +ship_use = array_create(61, 0); +ship_max = array_create(61, 0); +ship_ide = array_create(61, -1); max_ships = 0; -if (sh_target != -50) { +if (sh_target != noone) { max_ships = sh_target.capital_number + sh_target.frigate_number + sh_target.escort_number; - var tump; - tump = 0; - - var i, q, b; - i = 0; - q = 0; - b = 0; - repeat (sh_target.capital_number) { - b += 1; - if (sh_target.capital[b] != "") { + var i = 0; + for (var s = 1; s <= sh_target.capital_number; s++) { + if (sh_target.capital[s] != "") { i += 1; - ship[i] = sh_target.capital[i]; + ship[i] = sh_target.capital[s]; ship_use[i] = 0; - tump = sh_target.capital_num[i]; + var tump = sh_target.capital_num[s]; ship_max[i] = obj_ini.ship_carrying[tump]; ship_ide[i] = tump; ship_size[i] = 3; @@ -40,15 +27,13 @@ if (sh_target != -50) { purge_c += ship_max[i]; } } - q = 0; - repeat (sh_target.frigate_number) { - q += 1; - if (sh_target.frigate[q] != "") { + for (var s = 1; s <= sh_target.frigate_number; s++) { + if (sh_target.frigate[s] != "") { i += 1; - ship[i] = sh_target.frigate[q]; + ship[i] = sh_target.frigate[s]; ship_use[i] = 0; - tump = sh_target.frigate_num[q]; + var tump = sh_target.frigate_num[s]; ship_max[i] = obj_ini.ship_carrying[tump]; ship_ide[i] = tump; ship_size[i] = 2; diff --git a/objects/obj_drop_select/Create_0.gml b/objects/obj_drop_select/Create_0.gml index f0d6bf76b9..9d5ba32067 100644 --- a/objects/obj_drop_select/Create_0.gml +++ b/objects/obj_drop_select/Create_0.gml @@ -1,9 +1,12 @@ -if (!variable_instance_exists(self, "attack")) { - attack = 0; -} set_zoom_to_default(); //bandaid the purge screen flying off screen if zoomed out once_only = 0; +var _vars = ["purge", "planet_number", "attack"]; +for (var i = 0; i < array_length(_vars); i++) { + if (!variable_instance_exists(self, _vars[i])) { + variable_instance_set(self, _vars[i], 0); + } +} raid_tact = 1; raid_vet = 1; @@ -16,14 +19,11 @@ raid_wounded = obj_controller.select_wounded; refresh_raid = 0; remove_local = 1; -// - main_slate = new DataSlate(); draw = drop_select_draw; main_slate.inside_method = draw; roster_slate = new DataSlate(); local_content_slate = new DataSlate(); -var i = -1; formation_current = -1; via = array_create(100, 0); formation_possible = []; @@ -59,7 +59,6 @@ if (!instance_exists(obj_saveload)) { tooltip2 = ""; all_sel = 0; - var i = -1; var _ship_index = array_length(obj_ini.ship); ship = array_create(_ship_index, ""); ship_size = array_create(_ship_index, 0); @@ -68,13 +67,12 @@ if (!instance_exists(obj_saveload)) { ship_max = array_create(_ship_index, 0); ship_ide = array_create(_ship_index, -1); - i = 500; - ship[i] = "Local"; - ship_size[i] = 0; - ship_all[i] = 0; - ship_use[i] = 0; - ship_max[i] = 0; - ship_ide[i] = -42; + ship[500] = "Local"; + ship_size[500] = 0; + ship_all[500] = 0; + ship_use[500] = 0; + ship_max[500] = 0; + ship_ide[500] = -42; menu = 0; @@ -101,7 +99,7 @@ if (!instance_exists(obj_saveload)) { demons = 0; // Formation check - var i = 0, is = 0, arright = false; + var is = 0; var _formations = obj_controller.bat_formation; var _formation_types = obj_controller.bat_formation_type; @@ -236,9 +234,7 @@ if (purge == 0) { attacking = 9; } - var forces, t_attack; - forces = 0; - t_attack = 0; + var forces = 0; if (sisters > 0) { forces += 1; force_present[forces] = 5; diff --git a/objects/obj_drop_select/Draw_64.gml b/objects/obj_drop_select/Draw_64.gml index 7809223906..7a61185ff0 100644 --- a/objects/obj_drop_select/Draw_64.gml +++ b/objects/obj_drop_select/Draw_64.gml @@ -39,13 +39,7 @@ try { instance_destroy(); } } - var _xx = local_content_slate.XX; - /*if (instance_exists(p_target)) { - if (p_target.p_type[planet_number] = "Shrine") then nup = true; - } - */ - // 89,31 draw_set_halign(fa_left); for (var i = 0; i < array_length(purge_options); i++) { var _purge_button = purge_options[i]; @@ -83,7 +77,7 @@ try { } else if (purge > eDROP_TYPE.PURGESELECT) { draw_text_ext(_xx, _yy, "Purge Insight", -1, roster_slate.width - 40); _yy += 30; - var hers, influ, poppy; + var poppy = "0"; var hers = p_target.p_heresy[planet_number] + p_target.p_heresy_secret[planet_number]; var influ = p_target.p_influence[planet_number]; if (p_target.p_large[planet_number] == 1) { @@ -108,7 +102,7 @@ try { var _draw_y = _y_center; if (purge > eDROP_TYPE.PURGESELECT) { if (roster_slate.XX < _x_center + 660) { - var _draw_x = min(roster_slate.XX + 15, _x_center + 660); + _draw_x = min(roster_slate.XX + 15, _x_center + 660); } else { _draw_x = roster_slate.XX; } diff --git a/objects/obj_dropdown_sel/Create_0.gml b/objects/obj_dropdown_sel/Create_0.gml index 7c611022e6..de586a0c67 100644 --- a/objects/obj_dropdown_sel/Create_0.gml +++ b/objects/obj_dropdown_sel/Create_0.gml @@ -7,23 +7,13 @@ opened = 0; my_menu = 12.1; determined_planets = 0; -var ii; -ii = -1; -repeat (51) { - ii += 1; - option[ii] = ""; - option_id[ii] = 0; - option_star[ii] = 0; -} +option = array_create(51, ""); +option_id = array_create(51, 0); +option_star = array_create(51, 0); -var ii; -ii = -1; -repeat (101) { - ii += 1; - star[ii] = ""; - star_planet[ii] = 0; - star_mahreens[ii] = 0; -} +star = array_create(101, ""); +star_planet = array_create(101, 0); +star_mahreens = array_create(101, 0); width = 124; height = 24; diff --git a/objects/obj_dropdown_sel/Draw_0.gml b/objects/obj_dropdown_sel/Draw_0.gml index ff85508442..fcf2af60b1 100644 --- a/objects/obj_dropdown_sel/Draw_0.gml +++ b/objects/obj_dropdown_sel/Draw_0.gml @@ -41,15 +41,12 @@ if ((scr_hit(x, y, x + width, y + height) == true) && (obj_controller.dropdown_o } if (opened == 1) { - var ii, y5, yyy, hi; - ii = 0; - yyy = 24; - y5 = y; - hi = 24; - - repeat (options) { - ii += 1; - if ((ii != option_selected) && (ii <= options)) { + var yyy = 24; + var y5 = y; + var hi = 24; + + for (var i = 1; i <= options; i++) { + if ((i != option_selected) && (i <= options)) { y5 += hi; yyy += hi; @@ -59,7 +56,7 @@ if (opened == 1) { draw_set_font(fnt_40k_14); draw_set_color(c_black); draw_set_halign(fa_center); - draw_text(x + (width / 2), y5 + 2, string_hash_to_newline(string(option[ii]))); + draw_text(x + (width / 2), y5 + 2, string_hash_to_newline(string(option[i]))); draw_rectangle(x, y5, x + width, y5 + hi, 1); if (scr_hit(x, y5, x + width, y5 + hi) == true) { @@ -67,12 +64,12 @@ if (opened == 1) { draw_set_color(c_white); draw_rectangle(x, y5, x + width, y5 + hi, 0); - tooltip = option[ii]; - if ((target == "event_display") && (option[ii] != "None")) { - tooltip = option[ii]; - tooltip2 = fetch_artifact(option_id[ii]).description(); + tooltip = option[i]; + if ((target == "event_display") && (option[i] != "None")) { + tooltip = option[i]; + tooltip2 = fetch_artifact(option_id[i]).description(); } - if ((target == "event_display") && (option[ii] == "None")) { + if ((target == "event_display") && (option[i] == "None")) { tooltip = "Display"; tooltip2 = "There is no Artifact set to be displayed at the event."; } @@ -81,17 +78,16 @@ if (opened == 1) { obj_controller.dropdown_open = 0; opened = 0; - var no; - no = false; - if ((target == "event_type") && (option[ii] != "Great Feast")) { + var no = false; + if ((target == "event_type") && (option[i] != "Great Feast")) { no = true; } if (no == false) { - option_selected = ii; + option_selected = i; } - if ((target == "event_type") && (option[ii] == "Great Feast")) { - obj_controller.fest_type = option[ii]; + if ((target == "event_type") && (option[i] == "Great Feast")) { + obj_controller.fest_type = option[i]; with (obj_dropdown_sel) { if (target == "event_public") { option[1] = ""; @@ -138,34 +134,34 @@ if (opened == 1) { obj_controller.fest_display = option_id[option_selected]; } if (target == "event_public") { - obj_controller.fest_locals = ii - 1; + obj_controller.fest_locals = i - 1; } if (target == "event_loc") { if (obj_controller.fest_planet == 0) { - obj_controller.fest_sid = option_id[ii]; + obj_controller.fest_sid = option_id[i]; obj_controller.fest_wid = 0; - if (option_id[ii] > 0) { - if ((obj_controller.fest_warp == 0) && (obj_ini.ship_location[option_id[ii]] == "Warp")) { + if (option_id[i] > 0) { + if ((obj_controller.fest_warp == 0) && (obj_ini.ship_location[option_id[i]] == "Warp")) { obj_controller.fest_warp = 1; } - if ((obj_controller.fest_warp == 1) && (obj_ini.ship_location[option_id[ii]] != "Warp")) { + if ((obj_controller.fest_warp == 1) && (obj_ini.ship_location[option_id[i]] != "Warp")) { obj_controller.fest_warp = 0; } - obj_controller.fest_attend = scr_event_dudes(0, 0, "", option_id[ii]); + obj_controller.fest_attend = scr_event_dudes(0, 0, "", option_id[i]); } - if (option[ii] == "None Selected") { + if (option[i] == "None Selected") { obj_controller.fest_sid = 0; obj_controller.fest_attend = ""; } } if (obj_controller.fest_planet == 1) { - obj_controller.fest_wid = option_id[ii]; + obj_controller.fest_wid = option_id[i]; obj_controller.fest_sid = 0; - obj_controller.fest_star = option_star[ii]; - if (option[ii] != "None Selected") { - obj_controller.fest_attend = scr_event_dudes(0, 1, option_star[ii], option_id[ii]); + obj_controller.fest_star = option_star[i]; + if (option[i] != "None Selected") { + obj_controller.fest_attend = scr_event_dudes(0, 1, option_star[i], option_id[i]); } - if (option[ii] == "None Selected") { + if (option[i] == "None Selected") { obj_controller.fest_wid = 0; obj_controller.fest_star = ""; obj_controller.fest_attend = ""; @@ -173,13 +169,13 @@ if (opened == 1) { } } if (target == "event_lavish") { - obj_controller.fest_lav = ii; + obj_controller.fest_lav = i; } if (target == "event_repeat") { - if (ii <= 4) { - obj_controller.fest_repeats = ii; + if (i <= 4) { + obj_controller.fest_repeats = i; } - if (ii == 5) { + if (i == 5) { obj_controller.fest_repeats = 12; } } @@ -202,20 +198,11 @@ if ((tooltip != "Great Feast") && (target == "event_type")) { tooltip2 = "(NOT COMPLETED YET)"; } -/* -if (tooltip="Tournament") then tooltip2="Hosts a non-lethal tournament for friendly competition."; -if (tooltip="Deathmatch") then tooltip2="Pits all those present to fight until one remains standing. HQ are unable to participate."; -if (tooltip="Imperial Mass") then tooltip2="Hosts Imperial Cult Mass for your astartes, in praise of the Emperor."; -if (tooltip="Chapter Sermon") then tooltip2="Hosts a Chapter Cult sermon for your astartes, praising the "+string(global.chapter_name)+"."; -if (tooltip="Chapter Relic") then tooltip2="Instructs your "+string(obj_ini.role[100][16])+"s and "+string(obj_ini.role[100][14])+"s to construct a Chapter artifact."; -if (tooltip="Triumphal March") then tooltip2="Present Astartes will participate in a massive march to present a show of arms and power."; -*/ - if ((tooltip != "") && (tooltip2 != "")) { draw_set_alpha(1); draw_set_font(fnt_40k_14); draw_set_halign(fa_left); - draw_set_color(0); + draw_set_color(c_black); draw_rectangle(mouse_x + 18, mouse_y + 20, mouse_x + string_width_ext(string_hash_to_newline(tooltip2), -1, 500) + 24, mouse_y + 44 + string_height_ext(string_hash_to_newline(tooltip2), -1, 500), 0); draw_set_color(c_gray); draw_rectangle(mouse_x + 18, mouse_y + 20, mouse_x + string_width_ext(string_hash_to_newline(tooltip2), -1, 500) + 24, mouse_y + 44 + string_height_ext(string_hash_to_newline(tooltip2), -1, 500), 1); @@ -224,6 +211,3 @@ if ((tooltip != "") && (tooltip2 != "")) { draw_set_font(fnt_40k_14); draw_text_ext(mouse_x + 22, mouse_y + 42, string_hash_to_newline(string(tooltip2)), -1, 500); } - -/* */ -/* */ diff --git a/objects/obj_dropdown_sel/Step_0.gml b/objects/obj_dropdown_sel/Step_0.gml index 91b94bbab1..70868f4554 100644 --- a/objects/obj_dropdown_sel/Step_0.gml +++ b/objects/obj_dropdown_sel/Step_0.gml @@ -5,35 +5,10 @@ if (obj_controller.menu != my_menu) { instance_destroy(); } -/* - - - - -option[1]="Great Feast"; -option[2]="Tournament"; -option[3]="Deathmatch"; -option[4]="Commision Relic"; -option[5]="Imperial Mass"; -option[6]="Cult Sermon"; -dro=instance_create(xx+1064,yy+126,obj_dropdown_sel);dro.target="event_type"; - dro=instance_create(xx+1100,yy+184,obj_dropdown_sel);dro.target="event_loc"; - dro=instance_create(xx+1088,yy+271,obj_dropdown_sel);dro.target="event_lavish"; - dro=instance_create(xx+1041,yy+385,obj_dropdown_sel);dro.target="event_display"; - dro=instance_create(xx+1041,yy+443,obj_dropdown_sel);dro.target="event_repeat"; - - -*/ - if (target == "event_type") { with (obj_controller) { fest_cost = 0; - /* - option[2]="Tournament"; - option[3]="Deathmatch"; - */ - if (fest_type == "Great Feast") { fest_cost = fest_lav * 20; if (fest_lav == 0) { @@ -42,8 +17,7 @@ if (target == "event_type") { if (fest_locals > 0) { fest_cost += 20 * fest_locals; } - var tt; - tt = fest_cost; + var tt = fest_cost; if (fest_feature1 == 0) { fest_cost = 0; } @@ -62,8 +36,7 @@ if (target == "event_type") { if (fest_locals > 0) { fest_cost += 20 * fest_locals; } - var tt; - tt = fest_cost; + var tt = fest_cost; if (fest_feature2 > 0) { fest_cost += 30; @@ -71,10 +44,6 @@ if (target == "event_type") { if ((fest_type == "Tournament") && (fest_feature3 > 0)) { fest_cost += 100; } - - /*if (fest_feature1=0) then fest_cost=0; - if (fest_feature2>0) then fest_cost+=round(tt/2); - if (fest_feature3>0) then fest_cost+=tt;*/ } if (fest_type == "Chapter Relic") { if (fest_feature1 == 1) { @@ -99,8 +68,7 @@ if (target == "event_type") { if (fest_locals > 0) { fest_cost += 40 * fest_locals; } - var tt; - tt = fest_cost; + var tt = fest_cost; if (fest_feature2 > 0) { fest_cost += 100; } @@ -116,8 +84,7 @@ if (target == "event_type") { if (fest_locals > 0) { fest_cost += 20 * fest_locals; } - var tt; - tt = fest_cost; + var tt = fest_cost; if (fest_feature2 > 0) { fest_cost += round(tt / 2); } @@ -133,8 +100,7 @@ if (target == "event_type") { if (fest_locals > 0) { fest_cost += 10 * fest_locals; } - var tt; - tt = fest_cost; + var tt = fest_cost; if (fest_feature1 > 0) { fest_cost += tt; } @@ -157,40 +123,27 @@ if (target == "event_honor") { if ((target == "event_loc") && (determined_planets == 0)) { // Fill out the options for planets - var coo, ide, q; - coo = -1; - ide = 0; - q = 0; - - repeat (11) { - coo += 1; - ide = 0; - - repeat (300) { - ide += 1; + for (var coo = 0; coo <= 10; coo++) { + for (var ide = 1; ide <= 300; ide++) { var _unit = fetch_unit([coo, ide]); if ((_unit.role() != obj_ini.role[100][6]) && (_unit.role() != "Venerable " + string(obj_ini.role[100][6])) && (_unit.planet_location > 0)) { - var stahp, first_open; - stahp = 0; - q = 0; - first_open = 0; + var stahp = 0; + var first_open = 0; - repeat (100) { - if (stahp == 0) { - q += 1; - if ((star[q] == "") && (first_open == 0)) { - first_open = q; - } - if (star[q] == _unit.location_string && star_planet[q] == _unit.planet_location) { - stahp = 1; - star_mahreens[q] += 1; - } + for (var q = 1; q <= 100; q++) { + if ((star[q] == "") && (first_open == 0)) { + first_open = q; + } + if (star[q] == _unit.location_string && star_planet[q] == _unit.planet_location) { + stahp = 1; + star_mahreens[q] += 1; + break; } } if (stahp == 0) { star[first_open] = _unit.location_string; star_planet[first_open] = _unit.planet_location; - star_marheens[first_open] = 1; + star_mahreens[first_open] = 1; } } } @@ -233,13 +186,8 @@ if (target == "event_public") { } if (option[1] == "") { - var ii; - ii = 0; - repeat (50) { - ii += 1; - option[ii] = ""; - option_id[ii] = 0; - } + option = array_create(50, ""); + option_id = array_create(50, 0); if (target == "event_type") { option[1] = "Great Feast"; @@ -253,10 +201,8 @@ if (option[1] == "") { option_selected = 1; } if (target == "event_loc") { - var q, works, thatone; - q = 0; - works = 1; - thatone = false; + var works = 1; + var thatone = false; option[1] = "None Selected"; option_id[1] = -50; options = 1; @@ -264,13 +210,12 @@ if (option[1] == "") { // Present ship options if (obj_controller.fest_planet == 0) { - repeat (70) { - q += 1; + for (var i = 1; i <= 70; i++) { thatone = false; - if ((obj_ini.ship[q] != "") && (obj_ini.ship_carrying[q] > 0)) { + if ((obj_ini.ship[i] != "") && (obj_ini.ship_carrying[i] > 0)) { works += 1; - option[works] = obj_ini.ship[q]; - option_id[works] = q; + option[works] = obj_ini.ship[i]; + option_id[works] = i; options += 1; thatone = false; } @@ -279,13 +224,12 @@ if (option[1] == "") { // Present planet options if (obj_controller.fest_planet == 1) { - repeat (80) { - q += 1; - if ((star[q] != "") && (star_mahreens[q] > 0)) { + for (var i = 1; i <= 80; i++) { + if ((star[i] != "") && (star_mahreens[i] > 0)) { options += 1; - option_star[options] = string(star[q]); - option[options] = string(star[q]) + " " + scr_roman(star_planet[q]); - option_id[options] = star_planet[q]; + option_star[options] = string(star[i]); + option[options] = string(star[i]) + " " + scr_roman(star_planet[i]); + option_id[options] = star_planet[i]; } } } @@ -300,39 +244,36 @@ if (option[1] == "") { options = 5; } if (target == "event_display") { - var q, arti_work, thatone; - q = 0; - arti_work = 1; - thatone = false; + var arti_work = 1; + var thatone = false; option[1] = "None"; option_id[1] = -50; options = 1; option_selected = 1; - repeat (obj_controller.artifacts) { - q += 1; + for (var i = 1; i <= obj_controller.artifacts; i++) { thatone = false; - if (obj_ini.artifact[q] == "Casket") { + if (obj_ini.artifact[i] == "Casket") { thatone = true; } - if (obj_ini.artifact[q] == "Chalice") { + if (obj_ini.artifact[i] == "Chalice") { thatone = true; } - if (obj_ini.artifact[q] == "Statue") { + if (obj_ini.artifact[i] == "Statue") { thatone = true; } - if (obj_ini.artifact[q] == "Tome") { + if (obj_ini.artifact[i] == "Tome") { thatone = true; } - if (obj_ini.artifact[q] == "Robot") { + if (obj_ini.artifact[i] == "Robot") { thatone = true; } if (thatone == true) { arti_work += 1; - option[arti_work] = obj_ini.artifact[q]; - option_id[arti_work] = q; + option[arti_work] = obj_ini.artifact[i]; + option_id[arti_work] = i; options += 1; thatone = false; } @@ -391,6 +332,3 @@ if (option[1] == "") { options = 4; } } - -/* */ -/* */ diff --git a/objects/obj_en_fleet/Alarm_1.gml b/objects/obj_en_fleet/Alarm_1.gml index 7dcc5e8375..19e9aa7202 100644 --- a/objects/obj_en_fleet/Alarm_1.gml +++ b/objects/obj_en_fleet/Alarm_1.gml @@ -2,19 +2,18 @@ try { var orb = orbiting; if ((round(owner) != eFACTION.IMPERIUM) && (navy == 1)) { - owner = noone; + owner = 0; } //TODO centralise orbiting logic var _is_orbiting = is_orbiting(); - if (orbiting != 0 && action == "" && owner != noone) { - var orbiting_found = _is_orbiting; - if (orbiting_found) { - orbiting_found = variable_instance_exists(orbiting, "present_fleet"); + if (action == "" && owner != 0) { + if (_is_orbiting) { + var orbiting_found = variable_instance_exists(orbiting, "present_fleet"); if (orbiting_found) { orbiting.present_fleet[owner] += 1; } - } else if (!orbiting_found) { + } else if (!_is_orbiting) { orbiting = instance_nearest(x, y, obj_star); orbiting.present_fleet[owner]++; } @@ -65,13 +64,8 @@ try { } } - // 1355; - if (instance_exists(obj_crusade) && (owner == eFACTION.ORK) && (orbiting.owner == eFACTION.ORK)) { // Ork crusade AI - var max_dis; - max_dis = 400; - var fleet_owner = owner; with (obj_crusade) { if (owner != fleet_owner) { @@ -127,45 +121,6 @@ try { instance_activate_object(obj_crusade); instance_activate_object(obj_en_fleet); - /*if (action="") and (owner = eFACTION.IMPERIUM){// Defend nearby systems and return when done - - with(obj_star){ - // 137 ; might want for it to defend under other circumstances - if (present_fleet[8]>0) and (owner<=5) and (x>2) and (y>2) then instance_create(x,y,obj_temp3); - } - if (instance_number(obj_temp3)=0) then ret=1; - if (instance_number(obj_temp3)>0){ - var you,dis,mem; - you=instance_nearest(x,y,obj_temp3); - dis=point_distance(x,y,you.x,you.y); - - if (dis<300) and (image_index>=3){ - action_x=you.x;action_y=you.y; - home_x=instance_nearest(x,y,obj_star).x; - home_y=instance_nearest(x,y,obj_star).y; - set_fleet_movement();with(obj_temp3){instance_destroy();} - exit; - } - if (dis>=300) then ret=1; - } - - if (instance_exists(obj_crusade)){ - var cru;cru=instance_nearest(x,y,obj_crusade); - if (cru.owner=self.owner) and (point_distance(x,y,cru.x,cru.y)0){ - action_x=home_x; - action_y=home_y; - set_fleet_movement(); - } - } - - with(obj_temp3){instance_destroy();} - }*/ - if (owner == eFACTION.INQUISITION) { var valid = true; if (instance_exists(target)) { @@ -188,28 +143,28 @@ try { scr_loyalty("Heretic Homeworld", "+"); } - var whom = -1; - whom = inquisitor; + var whom = inquisitor; var inquisitors = obj_controller.inquisitor; var inquis_string = $"Inquisitor {whom > -1 ? inquisitors[whom] : inquisitors[0]}"; // INVESTIGATE DEAD HERE 137 ; INVESTIGATE DEAD HERE 137 ; INVESTIGATE DEAD HERE 137 ; INVESTIGATE DEAD HERE 137 ; - var cur_star, t, type, cha, dem, tem1, tem1_base, perc, popup; - t = 0; - type = 0; - cha = 0; - dem = 0; - tem1 = 0; - popup = 0; - perc = 0; - tem1_base = 0; - - cur_star = instance_nearest(x, y, obj_star); + var t = 0; + var type = 0; + var cha = 0; + var dem = 0; + var tem1 = 0; + var popup = 0; + var perc = 0; + var tem1_base = 0; + + var cur_star = instance_nearest(x, y, obj_star); if (string_count("investigate", trade_goods) > 0) { // Check for xenos or demon-equip items on those planets //TODO update this to check weapon or artifact tags - var e = 0, ia = -1, ca = 0; + var e = 0; + var ia = -1; + var ca = 0; var _unit; repeat (4400) { if ((ca <= 10) && (ca >= 0)) { @@ -259,9 +214,7 @@ try { orbiting = instance_nearest(x, y, obj_star); - // 135; if (obj_controller.loyalty_hidden <= 0) { - // obj_controller.alarm[7]=1;global.defeat=2; var moo = false; if ((obj_controller.penitent == 1) && (moo == false)) { obj_controller.alarm[8] = 1; @@ -289,23 +242,6 @@ try { obj_controller.known[eFACTION.TAU] = 1; } } - - /*if (image_index>=4){ - with(obj_star){ - if (owner = eFACTION.TAU) and (present_fleets>0) and (tau_fleets=0){ - instance_create(x,y,obj_temp5); - } - } - if (instance_exists(obj_temp5)){ - var wop;wop=instance_nearest(x,y,obj_temp5); - if (wop!=0) and (point_distance(x,y,wop.x,wop.y)<300) and (wop.x>5) and (wop.y>5){ - target_x=wop.x;target_y=wop.y; - home_x=x;home_y=y; - set_fleet_movement(); - } - } - with(obj_temp5){instance_destroy();} - }*/ } if (owner == eFACTION.TYRANIDS) { @@ -344,12 +280,11 @@ try { } if (n) { - var xx, yy, good, plin, plin2; - xx = 0; - yy = 0; - good = 0; - plin = 0; - plin2 = 0; + var xx = 0; + var yy = 0; + var good = 0; + var plin = 0; + var plin2 = 0; if (capital_number > 5) { n = 5; @@ -394,11 +329,6 @@ try { new_fleet.sprite_index = spr_fleet_tyranid; new_fleet.image_index = 1; - /*with(new_fleet){ - var ii;ii=0;ii+=capital_number;ii+=round((frigate_number/2));ii+=round((escort_number/4)); - if (ii<=1) then ii=1;image_index=ii; - }*/ - new_fleet.action_x = plin2.x; new_fleet.action_y = plin2.y; with (new_fleet) { @@ -452,17 +382,13 @@ try { action_eta -= 1; - /*if (owner>5){ - - }*/ - if ((action_eta == 2) && (owner == eFACTION.INQUISITION) && (inquisitor > -1)) { inquisitor_ship_approaches(); } else if (action_eta == 0) { action = ""; if (array_length(complex_route) > 0) { var target_loc = find_star_by_name(complex_route[0]); - if (target_loc != "none") { + if (target_loc != noone) { array_delete(complex_route, 0, 1); action_x = target_loc.x; action_y = target_loc.y; diff --git a/objects/obj_en_fleet/Alarm_3.gml b/objects/obj_en_fleet/Alarm_3.gml index f26bcbe2ab..82e7e5d05c 100644 --- a/objects/obj_en_fleet/Alarm_3.gml +++ b/objects/obj_en_fleet/Alarm_3.gml @@ -8,9 +8,7 @@ obj_controller.fleet_minimized = 0; obj_controller.selected = instance_nearest(x, y, obj_en_fleet); -// obj_controller.selected=self; obj_controller.sel_owner = self.owner; -// show_message(obj_controller.selected); obj_controller.cooldown = 8; if (obj_controller.zoomed == 1) { @@ -21,8 +19,6 @@ if (obj_controller.zoomed == 1) { obj_cursor.image_yscale = 1; } -// Pass variables to obj_controller.temp[t]=""; here -// Pass variables to obj_controller.temp[t]=""; here with (obj_fleet_select) { instance_destroy(); } diff --git a/objects/obj_en_fleet/Alarm_4.gml b/objects/obj_en_fleet/Alarm_4.gml index cfe41c63f2..e1ed832c5a 100644 --- a/objects/obj_en_fleet/Alarm_4.gml +++ b/objects/obj_en_fleet/Alarm_4.gml @@ -1,30 +1,12 @@ try { if (action != "") { - var sys, sys_dist, mine, connected, cont; - sys_dist = 9999; - connected = 0; - cont = 0; - - sys = instance_nearest(action_x, action_y, obj_star); - sys_dist = point_distance(action_x, action_y, sys.x, sys.y); + var sys = instance_nearest(action_x, action_y, obj_star); act_dist = point_distance(x, y, sys.x, sys.y); - mine = instance_nearest(x, y, obj_star); - if ((mine.x == sys.x2) && (mine.y == sys.y2)) { - connected = 1; - } - - var eta; - eta = 0; - eta = floor(point_distance(x, y, action_x, action_y) / action_spd) + 1; - if (connected == 0) { - eta = eta * 2; - } + var mine = instance_nearest(x, y, obj_star); if ((owner == eFACTION.INQUISITION) && (action_eta < 2)) { action_eta = 2; } - // action_x=sys.x; - // action_y=sys.y; action = "move"; if ((owner != eFACTION.ELDAR) && (mine.storm > 0)) { @@ -36,84 +18,65 @@ try { } if (action == "") { - var sys, sys_dist, mine, connected, cont, target_dist; - sys_dist = 9999; - connected = 0; - cont = 0; - target_dist = 0; - - sys = instance_nearest(action_x, action_y, obj_star); - sys_dist = point_distance(action_x, action_y, sys.x, sys.y); + var sys = instance_nearest(action_x, action_y, obj_star); + var sys_dist = point_distance(action_x, action_y, sys.x, sys.y); + var target_dist = 0; if (scr_valid_fleet_target(target)) { target_dist = point_distance(x, y, target.action_x, target.action_y); } else { - target = 0; + target = noone; } act_dist = point_distance(x, y, sys.x, sys.y); - mine = instance_nearest(x, y, obj_star); + var mine = instance_nearest(x, y, obj_star); - // if (owner = eFACTION.TAU) then mine.tau_fleets-=1; - // if (owner = eFACTION.TAU) and (image_index!=1) then mine.tau_fleets-=1; - // mine.present_fleets-=1; + var connected = determine_warp_join(mine, sys); - connected = determine_warp_join(mine, sys); - cont = 1; + // Move the entire fleet, don't worry about the other crap + turns_static = 0; - if (cont == 1) { - cont = 20; - } - - if (cont == 20) { - // Move the entire fleet, don't worry about the other crap - turns_static = 0; - var eta = 0; - - if ((trade_goods != "") && (owner != eFACTION.TYRANIDS) && (owner != eFACTION.CHAOS) && (string_count("Inqis", trade_goods) == 0) && (string_count("merge", trade_goods) == 0) && (string_count("_her", trade_goods) == 0) && (trade_goods != "cancel_inspection") && (trade_goods != "return")) { - if (scr_valid_fleet_target(target)) { - if (target.action != "") { - if (target_dist > sys_dist) { - action_x = target.action_x; - action_y = target.action_y; - sys = instance_nearest(action_x, action_y, obj_star); - } + if ((trade_goods != "") && (owner != eFACTION.TYRANIDS) && (owner != eFACTION.CHAOS) && (string_count("Inqis", trade_goods) == 0) && (string_count("merge", trade_goods) == 0) && (string_count("_her", trade_goods) == 0) && (trade_goods != "cancel_inspection") && (trade_goods != "return")) { + if (scr_valid_fleet_target(target)) { + if (target.action != "") { + if (target_dist > sys_dist) { + action_x = target.action_x; + action_y = target.action_y; + sys = instance_nearest(action_x, action_y, obj_star); } - } else { - target = 0; } + } else { + target = noone; } + } - eta = floor(point_distance(x, y, action_x, action_y) / action_spd) + 1; - if (connected == 0) { - eta = eta * 2; - } - - if ((action_eta <= 0) || (owner != eFACTION.INQUISITION)) { - action_eta = eta; - if ((owner == eFACTION.INQUISITION) && (action_eta < 2) && (string_count("_her", trade_goods) == 0)) { - action_eta = 2; - } - } + var eta = floor(point_distance(x, y, action_x, action_y) / action_spd) + 1; + if (connected == 0) { + eta = eta * 2; + } - if ((owner != eFACTION.ELDAR) && (mine.storm > 0)) { - action_eta += 10000; + if ((action_eta <= 0) || (owner != eFACTION.INQUISITION)) { + action_eta = eta; + if ((owner == eFACTION.INQUISITION) && (action_eta < 2) && (string_count("_her", trade_goods) == 0)) { + action_eta = 2; } + } - // action_x=sys.x; - // action_y=sys.y; - action = "move"; + if ((owner != eFACTION.ELDAR) && (mine.storm > 0)) { + action_eta += 10000; + } - if ((minimum_eta > action_eta) && (minimum_eta > 0)) { - action_eta = minimum_eta; - } - minimum_eta = 0; - if ((etah > action_eta) && (etah != 0)) { - action_eta = etah; - } + action = "move"; - x = x + lengthdir_x(24, point_direction(x, y, sys.x, sys.y)); - y = y + lengthdir_y(24, point_direction(x, y, sys.x, sys.y)); + if ((minimum_eta > action_eta) && (minimum_eta > 0)) { + action_eta = minimum_eta; + } + minimum_eta = 0; + if ((etah > action_eta) && (etah != 0)) { + action_eta = etah; } + + x = x + lengthdir_x(24, point_direction(x, y, sys.x, sys.y)); + y = y + lengthdir_y(24, point_direction(x, y, sys.x, sys.y)); } etah = 0; diff --git a/objects/obj_en_fleet/Alarm_5.gml b/objects/obj_en_fleet/Alarm_5.gml index 5f31ff9eb2..24533f6691 100644 --- a/objects/obj_en_fleet/Alarm_5.gml +++ b/objects/obj_en_fleet/Alarm_5.gml @@ -11,9 +11,6 @@ if (rep > 0) { } if (rep == 0) { - // if (id mod 2 == 0) then action_eta=obj_controller.temp[90]; - // else{action_eta=obj_controller.temp[90]-1;} - action_eta = obj_controller.temp[90] - choose(0, 1); rep = 3; diff --git a/objects/obj_en_fleet/Alarm_8.gml b/objects/obj_en_fleet/Alarm_8.gml index c2b74fb6d2..f575c966b7 100644 --- a/objects/obj_en_fleet/Alarm_8.gml +++ b/objects/obj_en_fleet/Alarm_8.gml @@ -1,5 +1,4 @@ -var wop; -wop = instance_nearest(x, y, obj_star); +var wop = instance_nearest(x, y, obj_star); if (instance_exists(wop)) { if (point_distance(x, y, wop.x, wop.y) <= 40) { wop.present_fleet[owner] += 1; diff --git a/objects/obj_en_fleet/Collision_obj_pnunit.gml b/objects/obj_en_fleet/Collision_obj_pnunit.gml index 0a10a77ae4..e69de29bb2 100644 --- a/objects/obj_en_fleet/Collision_obj_pnunit.gml +++ b/objects/obj_en_fleet/Collision_obj_pnunit.gml @@ -1,14 +0,0 @@ -/* -if (other.sprite_index != self.sprite_index) { - if (other.action="") and (action="") and (other.owner=owner) and (string_count("her",trade_goods)=0) and (string_count("her",string(other.trade_goods))=0){ - if (obj_controller.faction_status[eFACTION.IMPERIUM]="War") and (instance_nearest(x,y,obj_star).owner = eFACTION.PLAYER) and (owner = eFACTION.IMPERIUM) and (other.owner = eFACTION.IMPERIUM){ - if (id>other.id){ - guardsmen+=other.guardsmen; - capital_number+=other.capital_number; - frigate_number+=other.frigate_number; - escort_number+=other.escort_number; - with(other){instance_destroy();} - } - } - } -} */ // No colonists and fleets bashing together \ No newline at end of file diff --git a/objects/obj_en_fleet/Create_0.gml b/objects/obj_en_fleet/Create_0.gml index 5228a687f7..4ff5ba0b55 100644 --- a/objects/obj_en_fleet/Create_0.gml +++ b/objects/obj_en_fleet/Create_0.gml @@ -8,8 +8,8 @@ home_y = 0; selected = 0; ret = 0; hurt = 0; -/// @type {Asset.GMObject.obj_star} -orbiting = 0; +/// @type {Id.Instance.obj_star} +orbiting = noone; rep = 3; minimum_eta = 2; turns_static = 0; @@ -116,15 +116,14 @@ deserialize = function(save_data) { continue; } var loaded_value = struct_get(save_data, var_name); - // LOGGER.debug($"en_fleet {en_fleet_instance.id} - var: {var_name} - val: {loaded_value}"); try { - variable_struct_set(self, var_name, loaded_value); + variable_instance_set(self, var_name, loaded_value); } catch (e) { LOGGER.exception("Deserialization failed", e); } } if (struct_exists(save_data, "cargo_data")) { - variable_struct_set(self, "cargo_data", save_data.cargo_data); + variable_instance_set(self, "cargo_data", save_data.cargo_data); if (fleet_has_cargo("ork_warboss")) { var _boss = new NewPlanetFeature(eP_FEATURES.ORKWARBOSS); _boss.load_json_data(cargo_data.ork_warboss); @@ -132,10 +131,8 @@ deserialize = function(save_data) { } } - if (save_data.orbiting != 0 && action == "") { - var nearest_star = instance_nearest(x, y, obj_star); - orbiting = nearest_star; - // LOGGER.debug($"p_fleet id {id} deserialized: {self}"); + if (save_data.orbiting != noone && action == "") { + orbiting = instance_nearest(x, y, obj_star); } }; diff --git a/objects/obj_en_fleet/Destroy_0.gml b/objects/obj_en_fleet/Destroy_0.gml index 205e6cddac..e8dfacde7d 100644 --- a/objects/obj_en_fleet/Destroy_0.gml +++ b/objects/obj_en_fleet/Destroy_0.gml @@ -1,12 +1,8 @@ -/*if (owner = eFACTION.CHAOS){ - show_message("Trade Goods: "+string(trade_goods)+"#Alarms: "+string(alarm[0])+"|"+string(alarm[1])+"|"+string(alarm[2])+"|"+string(alarm[4])); -}*/ - -if ((action == "") && (orbiting != 0)) { +if ((action == "") && (orbiting != noone)) { if (orbiting == instance_nearest(x, y, obj_star)) { orbiting.present_fleet[owner] -= 1; } - orbiting = 0; + orbiting = noone; } if (instance_exists(obj_controller)) { @@ -21,6 +17,3 @@ if (instance_exists(obj_controller)) { } } } - -/* */ -/* */ diff --git a/objects/obj_en_fleet/Draw_0.gml b/objects/obj_en_fleet/Draw_0.gml index 050ea8b33f..5eaf44cc36 100644 --- a/objects/obj_en_fleet/Draw_0.gml +++ b/objects/obj_en_fleet/Draw_0.gml @@ -20,7 +20,7 @@ var coords = [ ]; var near_star = instance_nearest(x, y, obj_star); if (x == near_star.x && y == near_star.y) { - var coords = fleet_star_draw_offsets(); + coords = fleet_star_draw_offsets(); } if (image_index > 9) { @@ -48,8 +48,6 @@ if (obj_controller.zoomed == 1) { } } -// if (obj_controller.selected!=0) and (selected=1) then within=1; - if (obj_controller.selecting_planet > 0) { if ((mouse_x >= camera_get_view_x(view_camera[0]) + 529) && (mouse_y >= camera_get_view_y(view_camera[0]) + 234) && (mouse_x < camera_get_view_x(view_camera[0]) + 611) && (mouse_y < camera_get_view_y(view_camera[0]) + 249)) { if (instance_exists(obj_star_select)) { @@ -79,7 +77,6 @@ if (action != "") { draw_set_alpha(1); draw_set_color(c_white); draw_line_width(x, y, action_x, action_y, 1); - // draw_set_font(fnt_40k_14b); if (obj_controller.zoomed == 0) { draw_text_transformed(x + 12, y, string_hash_to_newline("ETA " + string(action_eta)), 1, 1, 0); @@ -88,9 +85,9 @@ if (action != "") { draw_text_transformed(x + 24, y, string_hash_to_newline("ETA " + string(action_eta)), 2, 2, 0); } // was 1.4 } +var _has_warboss = false; switch (owner) { case eFACTION.ORK: - var _has_warboss = false; if (fleet_has_cargo("ork_warboss")) { draw_icon = true; _has_warboss = true; @@ -103,7 +100,6 @@ if ((within == 1) || (selected > 0)) { draw_set_font(fnt_40k_14b); draw_set_halign(fa_center); - var fleet_descript = ""; if (owner == eFACTION.PLAYER) { fleet_descript = "Renegade Fleet"; } @@ -123,7 +119,6 @@ if ((within == 1) || (selected > 0)) { } } } - // if (navy=1) then fleet_descript=string(trade_goods)+" ("+string(guardsmen_unloaded)+"/"+string(guardsmen_ratio)+")"; switch (owner) { case eFACTION.MECHANICUS: fleet_descript = "Mechanicus Fleet"; @@ -161,15 +156,10 @@ if ((within == 1) || (selected > 0)) { break; } - // if (owner = eFACTION.IMPERIUM) and (navy=1){fleet_descript=string(capital_max_imp[1]+frigate_max_imp[1]+escort_max_imp[1]);} - if (global.cheat_debug == true) { fleet_descript += "C" + string(capital_number) + "|F" + string(frigate_number) + "|E" + string(escort_number); } - // fleet_descript=string(capital_number)+"|"+string(frigate_number)+"|"+string(escort_number); - // fleet_descript+="|"+string(trade_goods); - draw_set_halign(fa_left); } @@ -194,19 +184,9 @@ if (draw_icon) { } draw_sprite_ext(sprite_index, image_index, x + (coords[0] * scale), y + (coords[1] * scale), 1 * scale, 1 * scale, 0, c_white, 1); -/*if (owner = eFACTION.ORK){ - draw_set_font(fnt_small); - draw_set_halign(fa_center); - draw_set_color(c_white); - draw_text(x,y+32,string(escort_number)+"/"+string(frigate_number)+"/"+string(capital_number)); -}*/ - if (instance_exists(target)) { draw_set_color(c_red); draw_set_alpha(0.5); draw_line(x, y, target.x, target.y); draw_set_alpha(1); } - -/* */ -/* */ diff --git a/objects/obj_en_fleet/KeyPress_73.gml b/objects/obj_en_fleet/KeyPress_73.gml index 871f147a6a..e69de29bb2 100644 --- a/objects/obj_en_fleet/KeyPress_73.gml +++ b/objects/obj_en_fleet/KeyPress_73.gml @@ -1,12 +0,0 @@ -/*if (navy=1){ - var fid,tot,i;i=-1; - fid=self.id;tot=0; - - repeat(21){i+=1;tot+=capital_imp[i];} - i=-1;repeat(31){i+=1;tot+=frigate_imp[i]} - - show_message("Fleet: "+string(fid)+"#Action: "+string(trade_goods)+"#E"+string(escort_number)+"|F"+string(frigate_number)+"|C:"+string(capital_number)+"#Total Guardsmen: "+string(scr_display_number(tot))); -}*/ - -/* */ -/* */ diff --git a/objects/obj_en_fleet/Step_0.gml b/objects/obj_en_fleet/Step_0.gml index f6ef070d0f..baabf203df 100644 --- a/objects/obj_en_fleet/Step_0.gml +++ b/objects/obj_en_fleet/Step_0.gml @@ -2,16 +2,16 @@ if ((global.load >= 0) || instance_exists(obj_saveload)) { exit; } -if ((action != "") && (orbiting != 0)) { +if ((action != "") && (orbiting != noone)) { if (instance_exists(orbiting)) { if (variable_instance_exists(orbiting, "present_fleet")) { orbiting.present_fleet[owner] -= 1; - orbiting = 0; + orbiting = noone; } else { orbiting = instance_nearest(x, y, obj_star); var cur_owner_fleet = orbiting.present_fleet[owner]; orbiting.present_fleet[owner] = cur_owner_fleet > 0 ? cur_owner_fleet - 1 : cur_owner_fleet == 0; - orbiting = 0; + orbiting = noone; } } } @@ -45,8 +45,7 @@ if (ii_check == 0) { ii_check = 10; if ((owner != eFACTION.ELDAR) && (owner != eFACTION.INQUISITION)) { - var ii = 0; - ii += capital_number; + var ii = capital_number; ii += round((frigate_number / 2)); ii += round((escort_number / 4)); if (ii <= 1) { @@ -56,9 +55,7 @@ if (ii_check == 0) { image_index = min(image_index, 9); } if (owner == eFACTION.ELDAR) { - var ii; - ii = 0; - ii += capital_number; + var ii = capital_number; ii += round((frigate_number / 2)); ii += round((escort_number / 4)); if (ii <= 1) { @@ -75,8 +72,7 @@ if (ii_check == 0) { if (owner == eFACTION.TYRANIDS) { image_alpha = 0; if (instance_exists(obj_p_fleet)) { - var bundy; - bundy = instance_nearest(x, y, obj_p_fleet); + var bundy = instance_nearest(x, y, obj_p_fleet); if ((bundy.action == "") && (self.action == "") && (point_distance(bundy.x, bundy.y, x, y) < 90) && (bundy.x > x) && (bundy.y < y)) { image_alpha = 1; } @@ -89,7 +85,6 @@ if (owner == eFACTION.TYRANIDS) { if ((owner == eFACTION.TAU) && (action_spd != 32)) { action_spd = 32; } -// if (owner = eFACTION.TAU) and (image_index>1) if (owner == eFACTION.MECHANICUS) { if (action != "") { direction = point_direction(x, y, action_x, action_y); @@ -103,13 +98,12 @@ if ((owner == eFACTION.ELDAR) && (trade_goods != "") && (action == "move")) { if ((owner == eFACTION.TAU) && (action == "") && (obj_controller.tau_messenger >= 30) && (frigate_number > 0) && (escort_number + capital_number > 0)) { obj_controller.tau_messenger = 0; - var fleet, good, stir, xx, yy; - stir = 0; - xx = 0; - yy = 0; - good = 0; + var stir = 0; + var xx = 0; + var yy = 0; + var good = 0; - fleet = instance_nearest(x, y, obj_star); + var fleet = instance_nearest(x, y, obj_star); fleet.tau_fleets += 1; fleet.present_fleets += 1; instance_deactivate_object(fleet); diff --git a/objects/obj_en_ship/Alarm_0.gml b/objects/obj_en_ship/Alarm_0.gml index 5f40906f56..b4e28c2640 100644 --- a/objects/obj_en_ship/Alarm_0.gml +++ b/objects/obj_en_ship/Alarm_0.gml @@ -1246,22 +1246,6 @@ if ((owner != eFACTION.ELDAR) && (owner != eFACTION.NECRONS)) { bridge = maxhp; -/* -if (obj_fleet.enemy == 2) { - hp = hp * 0.75; - maxhp = hp; - shields = shields * 0.75; - maxshields = shields; -} - */ -// hp=1; -shields = 1; - -// if (obj_fleet.enemy="orks") then name=global.name_generator.GenerateFromSet("ork_ship"); +// shields = 1; name = "sdagdsagdasg"; - -// show_message(string(class)); - -/* */ -/* */ diff --git a/objects/obj_en_ship/Create_0.gml b/objects/obj_en_ship/Create_0.gml index 959fba43ae..6955f5ce31 100644 --- a/objects/obj_en_ship/Create_0.gml +++ b/objects/obj_en_ship/Create_0.gml @@ -3,7 +3,6 @@ owner = 0; action = ""; direction = 180; -// if (instance_exists(obj_p_ship)){target=instance_nearest(x,y,obj_p_ship);} /// @type {Asset.GMObject.obj_p_ship} target_l = 0; diff --git a/objects/obj_en_ship/Draw_0.gml b/objects/obj_en_ship/Draw_0.gml index ff36fa9843..738f09e7d5 100644 --- a/objects/obj_en_ship/Draw_0.gml +++ b/objects/obj_en_ship/Draw_0.gml @@ -1,13 +1,6 @@ if (name != "") { draw_set_font(fnt_info); draw_set_halign(fa_center); - - // 135; - /*if (action="broadside"){ - draw_set_color(c_blue);if (instance_exists(target_l)) then draw_line(x,y,target_l.x,target_l.y); - draw_set_color(c_red);if (instance_exists(target_r)) then draw_line(x,y,target_r.x,target_r.y); - }draw_set_color(CM_GREEN_COLOR);*/ - draw_set_alpha(1); if ((lightning > 1) && instance_exists(target)) { diff --git a/objects/obj_en_ship/Step_0.gml b/objects/obj_en_ship/Step_0.gml index b5987450da..04c45c9327 100644 --- a/objects/obj_en_ship/Step_0.gml +++ b/objects/obj_en_ship/Step_0.gml @@ -1,4 +1,4 @@ -if (owner != 6) { +if (owner != eFACTION.ELDAR) { image_angle = direction; if (obj_fleet.start != 5) { @@ -9,8 +9,6 @@ if (owner != 6) { image_alpha += 0.006; } - var o_dist, dist, ch_rang, ex, spid; - spid = 0; if ((shields > 0) && (shields < maxshields)) { shields += 0.02; @@ -26,9 +24,8 @@ if (owner != 6) { target = instance_nearest(x, y, obj_al_ship); } if (instance_exists(obj_p_ship) && instance_exists(obj_al_ship)) { - var tp1, tp2; - tp1 = instance_nearest(x, y, obj_p_ship); - tp2 = instance_nearest(x, y, obj_al_ship); + var tp1 = instance_nearest(x, y, obj_p_ship); + var tp2 = instance_nearest(x, y, obj_al_ship); if (point_distance(x, y, tp1.x, tp1.y) <= point_distance(x, y, tp2.x, tp2.y)) { target = tp1; } @@ -41,13 +38,10 @@ if (owner != 6) { } if (hp <= 0) { - var wh, gud; - wh = 0; - gud = 0; - repeat (5) { - wh += 1; - if (obj_fleet.enemy[wh] == owner) { - gud = wh; + var gud = 0; + for (var i = 1; i <= 5; i++) { + if (obj_fleet.enemy[i] == owner) { + gud = i; } } @@ -64,18 +58,14 @@ if (owner != 6) { image_alpha = 0.5; if (owner != eFACTION.TYRANIDS) { - // ex=instance_create(x,y,obj_explosion); - // ex.image_xscale=2;ex.image_yscale=2;ex.image_speed=0.75; - var husk; - husk = instance_create(x, y, obj_en_husk); + var husk = instance_create(x, y, obj_en_husk); husk.sprite_index = sprite_index; husk.direction = direction; husk.image_angle = image_angle; husk.depth = depth; husk.image_speed = 0; repeat (choose(4, 5, 6)) { - var explo; - explo = instance_create(x, y, obj_explosion); + var explo = instance_create(x, y, obj_explosion); explo.image_xscale = 0.5; explo.image_yscale = 0.5; explo.x += random_range(sprite_width * 0.25, sprite_width * -0.25); @@ -89,6 +79,8 @@ if (owner != 6) { } if ((hp > 0) && instance_exists(obj_p_ship)) { + var spid = 0; + var o_dist = 0; if (class == "Apocalypse Class Battleship") { o_dist = 500; action = "attack"; @@ -191,11 +183,9 @@ if (owner != 6) { spid = 45; } - // if (class!="big") then flank!!!! + spid *= speed_bonus; - spid = spid * speed_bonus; - - dist = point_distance(x, y, target.x, target.y) - max(sprite_get_width(sprite_index), sprite_get_height(sprite_index)); + var dist = point_distance(x, y, target.x, target.y) - max(sprite_get_width(sprite_index), sprite_get_height(sprite_index)); if ((target != 0) && (action == "attack")) { direction = turn_towards_point(direction, x, y, target.x, target.y, 0.1); @@ -220,42 +210,6 @@ if (owner != 6) { } } - /*if (target!=0) and (action="broadside") and (o_dist>=dist){ - direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - }*/ - - /*if (target!=0) and (action="broadside") and (o_dist>=dist){ - var re_deh;re_deh=relative_direction(direction,target.direction); - - // if (re_deh<45) or (re_deh>315) or ((re_deh>135) and (re_deh<225)) then direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - - var wok; - wok=0; - - if (!instance_exists(target_l)) then wok=2; - if (!instance_exists(target_r)) then wok=1; - - if (instance_exists(target_l)) and (instance_exists(target_r)){ - if (point_distance(x,y,target_l.x,target_l.y))<(point_distance(x,y,target_r.x,target_r.y)) then wok=1; - else{wok=2;} - - } - - - if (wok=1){ - direction=turn_towards_point(direction,x,y,x+lengthdir_x(256,90),y+lengthdir_y(256,90),.2) - } - - if (wok=2){ - direction=turn_towards_point(direction,x,y,x+lengthdir_x(256,270),y+lengthdir_y(256,270),.2) - } - - // direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - - - - }*/ - if (action == "attack") { if ((dist > o_dist) && (speed < (spid / 10))) { speed += 0.005; @@ -296,58 +250,35 @@ if (owner != 6) { turret_cool -= 1; } - var bull, targe, rdir, dirr, dist, xx, yy, ok; - targe = 0; - rdir = 0; - dirr = ""; - dist = 9999; - xx = x; - yy = y; - if ((turrets > 0) && instance_exists(obj_p_small) && (turret_cool == 0)) { - /// @type {Asset.GMObject.obj_p_small} - targe = instance_nearest(x, y, obj_p_small); + var targe = instance_nearest(x, y, obj_p_small); if (instance_exists(targe)) { dist = point_distance(x, y, targe.x, targe.y); - } - - if ((dist > 64) && (dist < 300)) { - /// @type {Asset.GMObject.obj_en_round} - bull = instance_create(x, y, obj_en_round); - bull.direction = point_direction(x, y, targe.x, targe.y); - if (owner == eFACTION.TYRANIDS) { - bull.sprite_index = spr_glob; - } - bull.speed = 20; - bull.dam = 3; - bull.image_xscale = 0.5; - bull.image_yscale = 0.5; - turret_cool = floor(60 / turrets); - if (owner == eFACTION.NECRONS) { - bull.sprite_index = spr_green_las; - bull.image_yscale = 1; + if ((dist > 64) && (dist < 300)) { + var bull = instance_create(x, y, obj_en_round); + bull.direction = point_direction(x, y, targe.x, targe.y); + if (owner == eFACTION.TYRANIDS) { + bull.sprite_index = spr_glob; + } + bull.speed = 20; + bull.dam = 3; + bull.image_xscale = 0.5; + bull.image_yscale = 0.5; + turret_cool = floor(60 / turrets); + if (owner == eFACTION.NECRONS) { + bull.sprite_index = spr_green_las; + bull.image_yscale = 1; + } + bull.direction += choose(random(10), 1 * -random(10)); } - bull.direction += choose(random(10), 1 * -random(10)); } } - targe = 0; - rdir = 0; - dirr = ""; - dist = 9999; - - xx = lengthdir_x(64, direction + 90); - yy = lengthdir_y(64, direction + 90); - var front, right, left, rear; - front = 0; - right = 0; - left = 0; - rear = 0; + var front = 0; + var right = 0; + var left = 0; + var rear = 0; - targe = instance_nearest(xx, yy, obj_p_ship); - rdir = point_direction(x, y, target.x, target.y); - // if (rdir>45) and (rdir<=135) and (targe!=target){target_r=targe;right=1;} - // if (rdir>225) and (rdir<=315) and (targe!=target) and (targe!=target_r){target_l=targe;left=1;} target_l = instance_nearest(x + lengthdir_x(64, direction + 90), y + lengthdir_y(64, direction + 90), obj_p_ship); target_r = instance_nearest(x + lengthdir_x(64, direction + 270), y + lengthdir_y(64, direction + 270), obj_p_ship); @@ -355,39 +286,26 @@ if (owner != 6) { front = 1; } - var f, facing, ammo, range, wep, dam, gg; - f = 0; - facing = ""; - ammo = 0; - range = 0; - wep = ""; - dam = 0; - gg = 0; - lightning = 0; - repeat (weapons) { - gg += 1; + for (var i = 1; i <= weapons; i++) { + var ok = 0; + var facing = ""; + var ammo = 0; + var range = 0; + var wep = ""; + var bull = noone; - ok = 0; - f += 1; - facing = ""; - ammo = 0; - range = 0; - wep = ""; - - //weapon[gg]=0;weapon_ammo[gg]=0;weapon_range[gg]=0; - - if ((cooldown[gg] <= 0) && (weapon[gg] != "") && (weapon_ammo[gg] > 0)) { + if ((cooldown[i] <= 0) && (weapon[i] != "") && (weapon_ammo[i] > 0)) { ok = 1; } if (ok == 1) { - facing = weapon_facing[gg]; - ammo = weapon_ammo[gg]; - range = weapon_range[gg]; + facing = weapon_facing[i]; + ammo = weapon_ammo[i]; + range = weapon_range[i]; } - targe = target; + var targe = target; if ((facing == "front") && (front == 1)) { ok = 2; } @@ -395,13 +313,6 @@ if (owner != 6) { ok = 2; } - /* - if (facing="right") then targe=target_r; - if (facing="left") then targe=target_l; - if ((facing="front") or (facing="most")) and (front=1) then ok=2; - if (facing="right") or (facing="most") and (right=1) then ok=2; - if (facing="left") or (facing="most") and (left=1) then ok=2; - */ if (facing == "special") { ok = 2; } @@ -417,25 +328,19 @@ if (owner != 6) { ok = 2; } - /*var re_deh;re_deh=relative_direction(direction,target.direction); - if (re_deh<45) or (re_deh>315) or ((re_deh>135) and (re_deh<225)) then direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - */ - if ((ok == 2) && (dist < (range + max(sprite_get_width(sprite_index), sprite_get_height(sprite_index))))) { if ((ammo > 0) && (ammo < 900)) { ammo -= 1; } - weapon_ammo[gg] = ammo; - cooldown[gg] = weapon_cooldown[gg]; - wep = weapon[gg]; - dam = weapon_dam[gg]; - - // if (f=3) and (ship_id=2) then show_message("ammo: "+string(ammo)+" | range: "+string(range)); + weapon_ammo[i] = ammo; + cooldown[i] = weapon_cooldown[i]; + wep = weapon[i]; + var dam = weapon_dam[i]; + ok = 3; if (ammo < 0) { ok = 0; } - ok = 3; if ((string_count("orpedo", wep) == 0) && (string_count("Interceptor", wep) == 0) && (string_count("ommerz", wep) == 0) && (string_count("Claws", wep) == 0) && (string_count("endrils", wep) == 0) && (ok == 3) && (owner != eFACTION.NECRONS)) { bull = instance_create(x + lengthdir_x(32, direction), y + lengthdir_y(32, direction), obj_en_round); @@ -552,7 +457,6 @@ if (owner != 6) { } } if ((wep == "Star Pulse Generator") && (ok == 3) && instance_exists(target)) { - /// @type {Asset.GMObject.obj_en_pulse} bull = instance_create(x + lengthdir_x(32, direction), y + lengthdir_y(32, direction), obj_en_pulse); bull.speed = 20; if (targe == target) { @@ -574,7 +478,6 @@ if (owner != 6) { } } if (((string_count("Interceptor", wep) == 1) || (string_count("ommerz", wep) == 1) || (string_count("Manta", wep) == 1) || (string_count("Glands", wep) == 1) || (string_count("Eldar Launch", wep) == 1)) && (ok == 3)) { - /// @type {Asset.GMObject.obj_en_in} bull = instance_create(x, y + lengthdir_y(-30, direction + 90), obj_en_in); bull.direction = self.direction; bull.owner = self.owner; @@ -582,8 +485,6 @@ if (owner != 6) { } } } - - /* */ } if (owner == 6) { image_angle = direction; @@ -592,9 +493,6 @@ if (owner == 6) { exit; } - var o_dist, dist, ch_rang, ex, spid; - spid = 0; - if ((shields > 0) && (shields < maxshields)) { shields += 0.03; } @@ -606,13 +504,10 @@ if (owner == 6) { } if (hp <= 0) { - var wh, gud; - wh = 0; - gud = 0; - repeat (5) { - wh += 1; - if (obj_fleet.enemy[wh] == owner) { - gud = wh; + var gud = 0; + for (var i = 1; i <= 5; i++) { + if (obj_fleet.enemy[i] == owner) { + gud = i; } } @@ -628,18 +523,14 @@ if (owner == 6) { image_alpha = 0.5; - // ex=instance_create(x,y,obj_explosion); - // ex.image_xscale=2;ex.image_yscale=2;ex.image_speed=0.75; - var husk; - husk = instance_create(x, y, obj_en_husk); + var husk = instance_create(x, y, obj_en_husk); husk.sprite_index = sprite_index; husk.direction = direction; husk.image_angle = image_angle; husk.depth = depth; husk.image_speed = 0; repeat (choose(4, 5, 6)) { - var explo; - explo = instance_create(x, y, obj_explosion); + var explo = instance_create(x, y, obj_explosion); explo.image_xscale = 0.5; explo.image_yscale = 0.5; explo.x += random_range(sprite_width * 0.25, sprite_width * -0.25); @@ -650,6 +541,8 @@ if (owner == 6) { } if ((hp > 0) && instance_exists(obj_p_ship)) { + var spid = 0; + var o_dist = 0; if (class == "Void Stalker") { o_dist = 300; action = "swoop"; @@ -666,16 +559,13 @@ if (owner == 6) { spid = 100; } - dist = point_distance(x, y, target.x, target.y) - max(sprite_get_width(target.sprite_index), sprite_get_height(sprite_index)); - if (target != 0) { if (speed < (spid / 10)) { speed += 0.02; } - var dist, range; if (instance_exists(target)) { - dist = point_distance(x, y, target.x, target.y); + var dist = point_distance(x, y, target.x, target.y); if (action == "swoop") { direction = turn_towards_point(direction, x, y, target.x, target.y, 5 - ship_size); @@ -718,56 +608,37 @@ if (owner == 6) { turret_cool -= 1; } - var bull, targe, rdir, dirr, dist, xx, yy, ok; - targe = 0; - rdir = 0; - dirr = ""; - dist = 9999; - xx = x; - yy = y; if ((turrets > 0) && instance_exists(obj_p_small) && (turret_cool == 0)) { - targe = instance_nearest(x, y, obj_p_small); + var targe = instance_nearest(x, y, obj_p_small); if (instance_exists(targe)) { - dist = point_distance(x, y, targe.x, targe.y); + var dist = point_distance(x, y, targe.x, targe.y); + if ((dist > 64) && (dist < 300)) { + var bull = instance_create(x, y, obj_en_round); + bull.direction = point_direction(x, y, targe.x, targe.y); + if (owner == eFACTION.TYRANIDS) { + bull.sprite_index = spr_glob; + } + if ((owner == eFACTION.TAU) || (owner == eFACTION.ELDAR)) { + bull.sprite_index = spr_pulse; + } + bull.speed = 20; + bull.dam = 3; + bull.image_xscale = 0.5; + bull.image_yscale = 0.5; + turret_cool = floor(60 / turrets); + bull.direction += choose(random(10), 1 * -random(10)); + } } - if ((dist > 64) && (dist < 300)) { - /// @type {Asset.GMObject.obj_en_round} - bull = instance_create(x, y, obj_en_round); - bull.direction = point_direction(x, y, targe.x, targe.y); - if (owner == eFACTION.TYRANIDS) { - bull.sprite_index = spr_glob; - } - if ((owner == eFACTION.TAU) || (owner == eFACTION.ELDAR)) { - bull.sprite_index = spr_pulse; - } - bull.speed = 20; - bull.dam = 3; - bull.image_xscale = 0.5; - bull.image_yscale = 0.5; - turret_cool = floor(60 / turrets); - bull.direction += choose(random(10), 1 * -random(10)); - } - } - targe = 0; - rdir = 0; - dirr = ""; - dist = 9999; - - xx = lengthdir_x(64, direction + 90); - yy = lengthdir_y(64, direction + 90); - - var front, right, left, rear; - front = 0; - right = 0; - left = 0; - rear = 0; - - targe = instance_nearest(xx, yy, obj_p_ship); - rdir = point_direction(x, y, target.x, target.y); - // if (rdir>45) and (rdir<=135) and (targe!=target){target_r=targe;right=1;} - // if (rdir>225) and (rdir<=315) and (targe!=target) and (targe!=target_r){target_l=targe;left=1;} + + } + + var front = 0; + var right = 0; + var left = 0; + var rear = 0; + target_l = instance_nearest(x + lengthdir_x(64, direction + 90), y + lengthdir_y(64, direction + 90), obj_p_ship); target_r = instance_nearest(x + lengthdir_x(64, direction + 270), y + lengthdir_y(64, direction + 270), obj_p_ship); @@ -775,37 +646,24 @@ if (owner == 6) { front = 1; } - var f, facing, ammo, range, wep, dam, gg; - f = 0; - facing = ""; - ammo = 0; - range = 0; - wep = ""; - dam = 0; - gg = 0; - - repeat (weapons) { - gg += 1; + for (var i = 1; i <= weapons; i++) { + var ok = 0; + var facing = ""; + var ammo = 0; + var range = 0; + var wep = ""; + var bull = noone; - ok = 0; - f += 1; - facing = ""; - ammo = 0; - range = 0; - wep = ""; - - //weapon[gg]=0;weapon_ammo[gg]=0;weapon_range[gg]=0; - - if ((cooldown[gg] <= 0) && (weapon[gg] != "") && (weapon_ammo[gg] > 0)) { + if ((cooldown[i] <= 0) && (weapon[i] != "") && (weapon_ammo[i] > 0)) { ok = 1; } if (ok == 1) { - facing = weapon_facing[gg]; - ammo = weapon_ammo[gg]; - range = weapon_range[gg]; + facing = weapon_facing[i]; + ammo = weapon_ammo[i]; + range = weapon_range[i]; } - targe = target; + var targe = target; if ((facing == "front") && (front == 1)) { ok = 2; } @@ -813,20 +671,13 @@ if (owner == 6) { ok = 2; } - /* - if (facing="right") then targe=target_r; - if (facing="left") then targe=target_l; - if ((facing="front") or (facing="most")) and (front=1) then ok=2; - if (facing="right") or (facing="most") and (right=1) then ok=2; - if (facing="left") or (facing="most") and (left=1) then ok=2; - */ if (facing == "special") { ok = 2; } if (!instance_exists(targe)) { exit; } - dist = point_distance(x, y, targe.x, targe.y); + var dist = point_distance(x, y, targe.x, targe.y); if ((facing == "right") && (point_direction(x, y, target_r.x, target_r.y) < 337) && (point_direction(x, y, target_r.x, target_r.y) > 203)) { ok = 2; @@ -835,25 +686,19 @@ if (owner == 6) { ok = 2; } - /*var re_deh;re_deh=relative_direction(direction,target.direction); - if (re_deh<45) or (re_deh>315) or ((re_deh>135) and (re_deh<225)) then direction=turn_towards_point(direction,x+lengthdir_x(128,target.direction-90),y,target.x,target.y+lengthdir_y(128,target.direction-90),.2) - */ - if ((ok == 2) && (dist < (range + max(sprite_get_width(sprite_index), sprite_get_height(sprite_index))))) { if ((ammo > 0) && (ammo < 900)) { ammo -= 1; } - weapon_ammo[gg] = ammo; - cooldown[gg] = weapon_cooldown[gg]; - wep = weapon[gg]; - dam = weapon_dam[gg]; - - // if (f=3) and (ship_id=2) then show_message("ammo: "+string(ammo)+" | range: "+string(range)); + weapon_ammo[i] = ammo; + cooldown[i] = weapon_cooldown[i]; + wep = weapon[i]; + var dam = weapon_dam[i]; + ok = 3; if (ammo < 0) { ok = 0; } - ok = 3; if ((string_count("orpedo", wep) == 0) && (string_count("Interceptor", wep) == 0) && (string_count("ommerz", wep) == 0) && (string_count("Claws", wep) == 0) && (string_count("endrils", wep) == 0) && (ok == 3)) { bull = instance_create(x + lengthdir_x(32, direction), y + lengthdir_y(32, direction), obj_en_round); @@ -951,7 +796,6 @@ if (owner == 6) { } } if (((string_count("Interceptor", wep) == 1) || (string_count("ommerz", wep) == 1) || (string_count("Manta", wep) == 1) || (string_count("Glands", wep) == 1) || (string_count("Eldar Launch", wep) == 1)) && (ok == 3)) { - /// @type {Asset.GMObject.obj_en_in} bull = instance_create(x, y + lengthdir_y(-30, direction + 90), obj_en_in); bull.direction = self.direction; bull.owner = self.owner; @@ -959,7 +803,4 @@ if (owner == 6) { } } } - - /* */ } -/* */ diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index 438018f8c4..fa61211d58 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -159,7 +159,7 @@ if (!engaged) { repeat (instance_number(obj_pnunit) - 1) { x2 += !flank ? 10 : -10; - var enemy2 = instance_nearest(x2, y, obj_pnunit); + enemy2 = instance_nearest(x2, y, obj_pnunit); if (!target_block_is_valid(enemy2, obj_pnunit)) { continue; } @@ -197,7 +197,7 @@ if (!engaged) { var x2 = enemy.x; repeat (instance_number(obj_pnunit) - 1) { x2 += flank == 0 ? -10 : 10; - var enemy2 = instance_nearest(x2, y, obj_pnunit); + enemy2 = instance_nearest(x2, y, obj_pnunit); if (!target_block_is_valid(enemy2, obj_pnunit)) { continue; } diff --git a/objects/obj_enunit/Create_0.gml b/objects/obj_enunit/Create_0.gml index 51a9373e1c..c5d7de3fcf 100644 --- a/objects/obj_enunit/Create_0.gml +++ b/objects/obj_enunit/Create_0.gml @@ -29,8 +29,8 @@ if (obj_ncombat.enemy < array_length(global.star_name_colors) && obj_ncombat.ene column_draw_colour = c_dkgrey; } -enemy = 0; -enemy2 = 0; +enemy = noone; +enemy2 = noone; avg_attack = 1; avg_ranged = 1; @@ -76,10 +76,6 @@ dudes_gear = array_create(_array_size, ""); dudges_mobi = array_create(_array_size, ""); alarm[1] = 5; -alarm[5] = 6; -if (obj_ncombat.enemy == 1) { - alarm[6] = 10; -} hit = function() { return scr_hit(x1, y1, x2, y2) && obj_ncombat.fadein <= 0; diff --git a/objects/obj_event_log/Create_0.gml b/objects/obj_event_log/Create_0.gml index d9c01930f4..6848ad602b 100644 --- a/objects/obj_event_log/Create_0.gml +++ b/objects/obj_event_log/Create_0.gml @@ -1,34 +1,20 @@ top = 1; entries = 0; scroll_cool = 0; -var t = -1; -event = []; // Get upon load? -t = 0; event = []; -// help = 0; help_topics = 0; topic = ""; info = ""; strategy = ""; main_info = ""; -topics[0] = ""; -related[0] = ""; -related[1] = ""; -related[2] = ""; -related[3] = ""; -var e = -1; -repeat (101) { - e += 1; - topics[e] = ""; -} +topics = array_create(101, ""); +related = array_create(4, ""); + if (file_exists(PATH_HELP_INI)) { ini_open(PATH_HELP_INI); - var ch; - ch = 0; - repeat (100) { - ch += 1; + for (var ch = 1; ch <= 100; ch++) { if (ini_section_exists(string(ch))) { help_topics += 1; topics[help_topics] = ini_read_string(string(ch), "topic", "Error"); diff --git a/objects/obj_event_log/Draw_0.gml b/objects/obj_event_log/Draw_0.gml index e3acdc8111..56f94fd0c6 100644 --- a/objects/obj_event_log/Draw_0.gml +++ b/objects/obj_event_log/Draw_0.gml @@ -1,15 +1,9 @@ if (help == 0) { - var bad = 1; - if (instance_exists(obj_controller)) { - if (obj_controller.menu == eMENU.EVENT_LOG) { - bad = 0; - } - } - if (bad == 0) { + if (instance_exists(obj_controller) && (obj_controller.menu == eMENU.EVENT_LOG)) { var xx = camera_get_view_x(view_camera[0]); var yy = camera_get_view_y(view_camera[0]); draw_set_alpha(1); - draw_set_color(0); + draw_set_color(c_black); draw_rectangle(xx, yy, xx + 1600, yy + 900, 0); draw_set_alpha(0.5); draw_sprite(spr_rock_bg, 0, xx, yy); @@ -19,26 +13,25 @@ if (help == 0) { draw_set_halign(fa_center); draw_text(xx + 800, yy + 74, string(global.chapter_name) + " Event Log"); draw_set_halign(fa_left); - var t = 0, p = -1, cur_event; var ent = array_length(event); draw_set_color(CM_GREEN_COLOR); if (ent == 0) { draw_text(xx + 25, yy + 120, "No entries logged."); } else { - p = -1; + var p = -1; draw_set_font(fnt_40k_14); draw_set_alpha(0.8); for (var t = top - 1; t < ent; t++) { p++; - cur_event = event[t]; + var cur_event = event[t]; if (cur_event.text != "") { // 1554 set_alert_draw_colour(cur_event.colour); draw_text_ext(xx + 25, yy + 120 + (p * 26), $"{cur_event.date} (Turn {cur_event.turn}) - {cur_event.text}", -1, 1554); - if (cur_event.event_target != "none") { + if (cur_event.event_target != noone) { if (point_and_click(draw_unit_buttons([xx + 1400, yy + 120 + (p * 26)], "View", [1, 1], c_green,, fnt_40k_14b, 1, true))) { var view_star = find_star_by_name(cur_event.event_target); - if (view_star != "none") { + if (view_star != noone) { main_map_defaults(); obj_controller.x = view_star.x; obj_controller.y = view_star.y; @@ -48,26 +41,25 @@ if (help == 0) { } } } - var x1, y1, x2, y2, scrolly, chunk_size, my, y5; - x1 = xx + 1557; - y1 = yy + 117; - x2 = xx + 1583; - y2 = yy + 823; + var x1 = xx + 1557; + var y1 = yy + 117; + var x2 = xx + 1583; + var y2 = yy + 823; draw_rectangle(x1, y1, x2, y2, 1); cubey = 30; - scrolly = (y2 - y1) + 12; // The maximum amount of moving around that the cube does - my = max(1, ent - 24); // The maximum number of scroll chunks - chunk_size = scrolly / my; - y5 = (top - 1) * chunk_size; + var scrolly = (y2 - y1) + 12; // The maximum amount of moving around that the cube does + var my = max(1, ent - 24); // The maximum number of scroll chunks + var chunk_size = scrolly / my; + var y5 = (top - 1) * chunk_size; draw_rectangle(x1, y1 + y5, x2, y1 + y5 + cubey, 0); + draw_set_alpha(1); } - draw_set_alpha(1); } if (help == 1) { var xx = camera_get_view_x(view_camera[0]); var yy = camera_get_view_y(view_camera[0]); - draw_set_color(0); + draw_set_color(c_black); draw_set_alpha(0.75); draw_rectangle(0, 0, room_width, room_height, 0); draw_set_alpha(1); @@ -87,10 +79,6 @@ if (help == 1) { help = 0; } } - var t, x1, y1; - x1 = 0; - y1 = 0; - t = 0; draw_set_color(c_black); draw_rectangle(xx + 466, yy + 136, xx + 644, yy + 166, 0); draw_set_color(c_gray); @@ -99,10 +87,9 @@ if (help == 1) { draw_set_font(fnt_40k_14b); draw_set_halign(fa_left); draw_text(xx + 466 + 4, yy + 136 + 6, string_hash_to_newline("Topics")); - x1 = xx + 466; - y1 = yy + 166; - repeat (20) { - t += 1; + var x1 = xx + 466; + var y1 = yy + 166; + for (var t = 1; t <= 20; t++) { if (topics[t] != "") { draw_set_color(c_gray); draw_set_alpha(0.75); @@ -132,7 +119,6 @@ if (help == 1) { draw_set_alpha(1); draw_set_color(c_gray); draw_set_halign(fa_center); - // draw_rectangle(xx+664,yy+148,xx+805,yy+316,0); if (topic != "") { draw_set_font(fnt_40k_14b); draw_text_transformed(xx + 897, yy + 131, string_hash_to_newline(string(topic)), 1.25, 1.25, 0); @@ -141,9 +127,8 @@ if (help == 1) { draw_text(xx + 663, yy + 177, string_hash_to_newline("Game Info:")); } draw_set_font(fnt_40k_14); - var p1, y2; - y2 = 0; - p1 = string(info); + var y2 = 0; + var p1 = string(info); if (info != "") { draw_text_ext(xx + 663, yy + 197, string_hash_to_newline(string(p1)), -1, 469); } diff --git a/objects/obj_event_log/Mouse_60.gml b/objects/obj_event_log/Mouse_60.gml index 70202f1328..979c58bbd2 100644 --- a/objects/obj_event_log/Mouse_60.gml +++ b/objects/obj_event_log/Mouse_60.gml @@ -1,9 +1,3 @@ -// if (scroll_cool<=0){ -// scroll_cool=1; if (top > 1) { top -= 1; } -if (top > 1) { - top -= 1; -} -// } diff --git a/objects/obj_event_log/Mouse_61.gml b/objects/obj_event_log/Mouse_61.gml index fb48e44b58..932eaeb14d 100644 --- a/objects/obj_event_log/Mouse_61.gml +++ b/objects/obj_event_log/Mouse_61.gml @@ -1,15 +1,4 @@ -// if (scroll_cool<=0){ -// scroll_cool=1; - -var t, p; -ent = 0; -p = top - 1; -t = 0; ent = array_length(event); if (ent - 24 > top) { top += 1; } -if (ent - 24 > top) { - top += 1; -} -// } diff --git a/objects/obj_fleet/Alarm_1.gml b/objects/obj_fleet/Alarm_1.gml index ad405efc5b..d14b29edde 100644 --- a/objects/obj_fleet/Alarm_1.gml +++ b/objects/obj_fleet/Alarm_1.gml @@ -1,5 +1,3 @@ -// if (csm_exp!=0) then show_message(string(csm_exp)); - if (control == 1) { instance_activate_object(obj_cursor); } @@ -17,9 +15,7 @@ if (enemy == 2) { en_size[3] = 2; } - var i; - i = 0; - i = en_capital; + var i = en_capital; if (i > 0) { en_column[2] = "Apocalypse Class Battleship"; en_num[2] = floor(random(i)) + 1; @@ -76,32 +72,30 @@ if (enemy == 7) { en_num[2] = irandom_range(1, i); i -= en_num[2]; en_size[2] = 3; - } // en_num[2]+=en_num[1]+1; + } if (i > 0) { en_column[3] = "Kroolboy"; en_num[3] = i; i -= en_num[3]; en_size[3] = 3; - } // en_num[3]+=en_num[2]+1; + } if (en_frigate > 0) { en_column[4] = "Battlekroozer"; en_num[4] = en_frigate; en_size[4] = 2; - } // en_num[4]+=en_num[3]+1; + } if (en_escort > 0) { en_column[5] = "Ravager"; en_num[5] = en_escort; en_size[5] = 1; - } // en_num[5]+=en_num[4]+1; + } } if (enemy == 8) { - var i; - i = 0; - i = en_frigate; + var i = en_frigate; if (en_capital > 0) { en_column[1] = "Custodian"; @@ -121,7 +115,7 @@ if (enemy == 8) { en_num[3] = i; i -= en_num[3]; en_size[3] = 2; - } // en_num[3]+=en_num[2]+1; + } if (en_escort > 0) { en_column[4] = "Castellan"; @@ -137,9 +131,7 @@ if (enemy == 8) { } if (enemy == 9) { - var i; - i = 0; - i = en_escort; + var i = en_escort; if (en_capital > 0) { en_column[1] = "Leviathan"; @@ -158,19 +150,17 @@ if (enemy == 9) { en_column[3] = "Razorfiend"; en_num[3] = en_frigate; en_size[3] = 2; - } // en_num[2]+=en_num[1]+1; + } if (i > 0) { en_column[4] = "Prowler"; en_num[4] = i; en_size[4] = 1; - } // en_num[5]+=en_num[4]+1; + } } if (enemy == 10) { - var i; - i = 0; - i = en_frigate; + var i = en_frigate; if (en_capital > 0) { en_column[1] = "Desecrator"; @@ -190,83 +180,28 @@ if (enemy == 10) { en_num[3] = floor(random(i)) + 1; i -= en_num[3]; en_size[3] = 2; - } // en_num[2]+=en_num[1]+1; + } if (i > 0) { en_column[4] = "Daemon"; en_num[4] = i; i -= en_num[4]; en_size[4] = 2; - } // en_num[3]+=en_num[2]+1; + } if (en_escort > 0) { en_column[5] = "Iconoclast"; en_num[5] = en_escort; en_size[5] = 1; - } // en_num[5]+=en_num[4]+1; + } } -// show_message("Dethdeala "+string(en_num[1])+" | Gorbag "+string(en_num[2])+" | Kroolboy "+string(en_num[3])+" | Frigate "+string(en_num[4])+" | Escort "+string(en_num[5])); - en_capital = 0; en_frigate = 0; en_escort = 0; en_ships_max = 0; -/* -if (enemy="orks"){ - if (threat=1){ - en_column[1]="Ravager";en_num[1]=floor(random_range(1,3));en_size[1]=1; - } - if (threat=2){ - en_column[1]=choose("Deathdeala","Gorbag's Revenge","Battlekroozer");en_num[1]=choose(0,1);en_size[1]=3; - en_column[2]="Ravager";en_num[2]=floor(random_range(1,5));en_size[2]=1; - } - if (threat=3){ - en_column[1]="Dethdeala";en_num[1]=choose(1,1);en_size[1]=3; - en_column[2]="Gorbag's Revenge";en_num[2]=choose(0,1);en_size[2]=3; - en_column[3]="Battlekroozer";en_num[3]=floor(random_range(0,1));en_size[3]=3; - en_column[4]="Ravager";en_num[4]=floor(random_range(3,8));en_size[4]=1; - } - if (threat=4){ - en_column[1]="Dethdeala";en_num[1]=choose(1,2);en_size[1]=3; - en_column[2]="Gorbag's Revenge";en_num[2]=choose(0,1,1);en_size[2]=3; - en_column[3]="Battlekroozer";en_num[3]=floor(random_range(1,1));en_size[3]=3; - en_column[4]="Ravager";en_num[4]=floor(random_range(4,10));en_size[4]=1; - } - if (threat=5){ - en_column[1]="Dethdeala";en_num[1]=choose(1,2,3);en_size[1]=3; - en_column[2]="Gorbag's Revenge";en_num[2]=choose(0,1,2);en_size[2]=3; - en_column[3]="Kroolboy";en_num[3]=choose(0,1,2);en_size[3]=3; - en_column[4]="Battlekroozer";en_num[4]=floor(random_range(0,5));en_size[4]=3; - en_column[5]="Ravager";en_num[5]=floor(random_range(6,15));en_size[5]=1; - } -} - -*/ - -/*if (en_num[2]=0) then en_num[2]=en_num[1]+1; -if (en_num[3]=0) then en_num[3]=en_num[2]+1; -if (en_num[4]=0) then en_num[4]=en_num[3]+1; -if (en_num[5]=0) then en_num[5]=en_num[4]+1; - -if (en_num[2]!=0) then en_num[2]+=en_num[1]; -if (en_num[3]!=0) then en_num[3]+=en_num[3]; -if (en_num[4]!=0) then en_num[4]+=en_num[4]; -if (en_num[5]!=0) then en_num[5]+=en_num[5];*/ - -/*var i;i=0; -repeat(5){i+=1; - if (en_column[4]="") and (en_column[5]!="") and (en_num[5]>0){en_column[4]=en_column[5];en_num[4]=en_num[5];en_column[5]="";en_num[5]=0;} - if (en_column[3]="") and (en_column[4]!="") and (en_num[4]>0){en_column[3]=en_column[4];en_num[3]=en_num[4];en_column[4]="";en_num[4]=0;} - if (en_column[2]="") and (en_column[3]!="") and (en_num[3]>0){en_column[2]=en_column[3];en_num[2]=en_num[3];en_column[3]="";en_num[3]=0;} - if (en_column[1]="") and (en_column[2]!="") and (en_num[2]>0){en_column[1]=en_column[2];en_num[1]=en_num[2];en_column[2]="";en_num[2]=0;} -}*/ - -var i; -i = 0; -repeat (5) { - i += 1; +for (var i = 1; i <= 5; i++) { if (en_column[i] == "Avenger Class Grand Cruiser") { en_width[i] = 196; en_height[i] = 96; @@ -386,24 +321,14 @@ repeat (5) { } } -/* */ - attack_mode = "offensive"; -// if (ambushers=1) or (enemy=8) then attack_mode="offensive"; -// if (enemy=9) then attack_mode="defensive"; - if ((ambushers == 1) && (ambushers == 999)) { global_attack = global_attack * 1.1; } // Need to finish this if (bolter_drilling == 1) { global_bolter = global_bolter * 1.1; } -// if (enemy_eldar=1) and (enemy=6){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} -// if (enemy_fallen=1) and (enemy=10){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} -// if (enemy_orks=1) and (enemy=7){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} -// if (enemy_tau=1) and (enemy=8){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} -// if (enemy_tyranids=1) and (enemy=10){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} if ((siege == 1) && (siege == 555)) { global_attack = global_attack * 1.2; } // Need to finish this @@ -414,11 +339,9 @@ if (slow == 1) { if (melee == 1) { global_melee = global_melee * 1.15; } -// if (shitty_luck == 1) { global_defense = global_defense * 0.9; } -// if (lyman=1) and (dropping=1) then ||| handle within each object if (ossmodula == 1) { global_attack = global_attack * 0.95; global_defense = global_defense * 0.95; @@ -429,17 +352,5 @@ if (betchers == 1) { if (catalepsean == 1) { global_attack = global_attack * 0.95; } -// if (occulobe=1){if (time=5) or (time=6) then global_attack=global_attack*0.7;global_defense=global_defense*0.9;} - -/* -global.chapter_name=5; -obj_ini.main_color=obj_creation.main_color; -obj_ini.secondary_color=obj_creation.secondary_color; -obj_ini.lens_color=obj_creation.lens_color; -obj_ini.weapon_color=obj_creation.weapon_color; -*/ alarm[2] = 1; - -/* */ -/* */ diff --git a/objects/obj_fleet/Alarm_2.gml b/objects/obj_fleet/Alarm_2.gml index 6aa95b0ba4..ec9f7fc85d 100644 --- a/objects/obj_fleet/Alarm_2.gml +++ b/objects/obj_fleet/Alarm_2.gml @@ -2,30 +2,16 @@ capital_max = capital; frigate_max = frigate; escort_max = escort; -var i, k, temp1, temp2, x2, hei, man, sizz; -i = 0; -k = 0; -temp1 = 0; -temp2 = 0; -x2 = 224; -hei = 0; -man = 0; -sizz = 0; +var x2 = 1200; +var man = noone; +var yy = 0; sort_ships_into_columns(self); player_fleet_ship_spawner(); -if (enemy == 2) { - // This is an orderly Tau ship formation - var xx, yy, i, temp1, x2, man; - xx = 0; - yy = 0; - i = 0; - temp1 = 0; - x2 = 1200; - man = 0; - +if (enemy == eFACTION.IMPERIUM) { + // This is an orderly Imperium ship formation if (en_num[4] > 0) { yy = (room_height / 2) - ((en_height[4] * en_num[4]) / 2); yy += en_height[4] / 2; @@ -67,23 +53,8 @@ if (enemy == 2) { } } -/* -if (en_escort>0){en_column[4]="Aconite";en_num[4]=max(1,floor(en_escort/2));en_size[4]=1;} -if (en_escort>1){en_column[3]="Hellebore";en_num[3]=max(1,floor(en_escort/2));en_size[3]=1;} -if (en_frigate>0){en_column[2]="Shadow Class";en_num[2]=en_frigate;en_size[2]=2;} -if (en_capital>0){en_column[1]="Void Stalker";en_num[1]=en_capital;en_size[1]=3;} -*/ - -if (enemy == 6) { - // This is an orderly Tau ship formation - var xx, yy, i, temp1, x2, man; - xx = 0; - yy = 0; - i = 0; - temp1 = 0; - x2 = 1200; - man = 0; - +if (enemy == eFACTION.ELDAR) { + // This is an orderly Eldar ship formation if (en_num[4] > 0) { yy = 128; repeat (en_num[4]) { @@ -123,22 +94,9 @@ if (enemy == 6) { } } -if ((enemy == 7) || (enemy == 10)) { +if ((enemy == eFACTION.ORK) || (enemy == eFACTION.CHAOS)) { // This is spew out random ships without regard for formations - var xx, yy, dist, targ, numb, man; - xx = 0; - yy = 0; - dist = 0; - target = 0; - numb = 0; - man = 0; - - var i; - i = 0; - - repeat (5) { - i += 1; - + for (var i = 1; i <= 5; i++) { if (en_column[i] != "") { for (s = 0; s < en_num[i]; s += 1) { if (en_size[i] > 1) { @@ -153,16 +111,8 @@ if ((enemy == 7) || (enemy == 10)) { } } -if (enemy == 8) { +if (enemy == eFACTION.TAU) { // This is an orderly Tau ship formation - var xx, yy, i, temp1, x2, man; - xx = 0; - yy = 0; - i = 0; - temp1 = 0; - x2 = 1200; - man = 0; - yy = (room_height / 2) - ((en_height[5] * en_num[5]) / 2); yy += en_height[5] / 2; repeat (en_num[5]) { @@ -205,16 +155,8 @@ if (enemy == 8) { } } -if (enemy == 9) { +if (enemy == eFACTION.TYRANIDS) { // This is an orderly Tyranid ship formation - var xx, yy, i, temp1, x2, man; - xx = 0; - yy = 0; - i = 0; - temp1 = 0; - x2 = 1200; - man = 0; - yy = (room_height / 2) - ((en_height[4] * en_num[4]) / 2); yy += en_height[4] / 2; repeat (en_num[4]) { @@ -251,5 +193,4 @@ if (enemy == 9) { } } -/* */ alarm_set(3, 2); diff --git a/objects/obj_fleet/Alarm_4.gml b/objects/obj_fleet/Alarm_4.gml index 020d812e45..ff3ec16f70 100644 --- a/objects/obj_fleet/Alarm_4.gml +++ b/objects/obj_fleet/Alarm_4.gml @@ -38,8 +38,6 @@ with (obj_en_husk) { instance_activate_all(); obj_controller.combat = 0; instance_activate_object(obj_turn_end); -// instance_activate_object(obj_star_select); -// show_message(obj_turn_end.current_battle); if (player_started == 0) { with (obj_turn_end) { @@ -48,10 +46,7 @@ if (player_started == 0) { } } if (player_started == 1) { - var taxt; - taxt = ""; - - taxt = string(global.chapter_name) + " engage and destroy a"; + var taxt = string(global.chapter_name) + " engage and destroy a"; if ((enemy[1] == 2) || (enemy[1] == 4) || (enemy[1] == 5) || (enemy[1] == 6)) { taxt += "n"; } @@ -88,7 +83,6 @@ if (view_x + view_y > 0) { obj_controller.y = view_y; } -// show_message(obj_turn_end.current_battle); with (obj_controller) { instance_activate_all(); } diff --git a/objects/obj_fleet/Alarm_6.gml b/objects/obj_fleet/Alarm_6.gml index 8355b668ff..694f857f81 100644 --- a/objects/obj_fleet/Alarm_6.gml +++ b/objects/obj_fleet/Alarm_6.gml @@ -1,53 +1,30 @@ -/* -enemy[2]=6;enemy_status[2]=1; -en_capital[2]=2;en_frigate[2]=3;en_escort[2]=5; -en_capital_max[2]=2;en_frigate_max[2]=3;en_escort_max[2]=5; -en_ships_max[2]=10; +var total_enemies = 0; +var total_allies = 1; -enemy[3]=2;enemy_status[3]=1; -en_capital[3]=1;en_frigate[3]=2;en_escort[3]=3; -en_capital_max[3]=1;en_frigate_max[3]=2;en_escort_max[3]=3; -en_ships_max[3]=6; -*/ - -var total_enemies, total_allies, t, tt, y1, y2, fug, spawner; -total_enemies = 0; -total_allies = 1; -spawner = 0; -t = 0; -y1 = 0; -y2 = 0; -tt = 0; -fug = 0; - -repeat (6) { - t += 1; - if (enemy[t] != 0) { - if (enemy_status[t] < 0) { +for (var i = 1; i <= 6; i++) { + if (enemy[i] != 0) { + if (enemy_status[i] < 0) { total_enemies += 1; } - if (enemy_status[t] > 0) { + if (enemy_status[i] > 0) { total_allies += 1; } - - // show_message("Computer "+string(t)+":"+string(enemy[t])+", status:"+string(enemy_status[t])); } } if (total_enemies > 0) { - t = 1; - y2 = room_height / total_enemies / 2; - tt = 0; - repeat (5) { - fug += 1; - if (enemy_status[fug] < 0) { + var t = 1; + var y2 = room_height / total_enemies / 2; + var tt = 0; + for (var i = 1; i <= 5; i++) { + if (enemy_status[i] < 0) { tt += 1; - y1 = t * y2; + var y1 = t * y2; - spawner = instance_create(room_width + 200, y1, obj_fleet_spawner); - spawner.owner = enemy[fug]; + var spawner = instance_create(room_width + 200, y1, obj_fleet_spawner); + spawner.owner = enemy[i]; spawner.height = y2; - spawner.number = fug; + spawner.number = i; t += 2; } @@ -55,41 +32,33 @@ if (total_enemies > 0) { } if (total_allies > 0) { - y1 = 0; - fug = 0; - t = 1; - y2 = room_height / total_allies / 2; - tt = 0; - repeat (5) { - fug += 1; - if (enemy_status[fug] > 0) { + var t = 1; + var y2 = room_height / total_allies / 2; + var tt = 0; + for (var i = 1; i <= 5; i++) { + if (enemy_status[i] > 0) { tt += 1; - y1 = t * y2; + var y1 = t * y2; - spawner = instance_create(200, y1, obj_fleet_spawner); + var spawner = instance_create(200, y1, obj_fleet_spawner); - if (fug == 1) { + if (i == 1) { spawner.owner = eFACTION.PLAYER; } - if (fug > 1) { - spawner.owner = enemy[fug]; + if (i > 1) { + spawner.owner = enemy[i]; } // Get the ENEMY after the actual enemies spawner.height = y2; - spawner.number = fug; + spawner.number = i; t += 2; } } } -// show_message("Total Enemies: "+string(total_enemies)); -// show_message("Total Allies: "+string(total_allies)); - // Buffs here -// if (ambushers=1) or (enemy=8) then attack_mode = "offensive"; -// if (enemy=9) then attack_mode="defensive"; if ((ambushers == 1) && (ambushers == 999)) { global_attack = global_attack * 1.1; @@ -97,11 +66,6 @@ if ((ambushers == 1) && (ambushers == 999)) { if (bolter_drilling == 1) { global_bolter = global_bolter * 1.1; } -// if (enemy_eldar=1) and (enemy=6){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} -// if (enemy_fallen=1) and (enemy=10){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} -// if (enemy_orks=1) and (enemy=7){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} -// if (enemy_tau=1) and (enemy=8){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} -// if (enemy_tyranids=1) and (enemy=10){global_attack=global_attack*1.1;global_defense=global_defense*1.1;} if ((siege == 1) && (siege == 555)) { global_attack = global_attack * 1.2; } // Need to finish this @@ -112,11 +76,9 @@ if (slow == 1) { if (melee == 1) { global_melee = global_melee * 1.15; } -// if (shitty_luck == 1) { global_defense = global_defense * 0.9; } -// if (lyman=1) and (dropping=1) then ||| handle within each object if (ossmodula == 1) { global_attack = global_attack * 0.95; global_defense = global_defense * 0.95; @@ -127,20 +89,10 @@ if (betchers == 1) { if (catalepsean == 1) { global_attack = global_attack * 0.95; } -// if (occulobe=1){if (time=5) or (time=6) then global_attack=global_attack*0.7;global_defense=global_defense*0.9;} - // More prep for player -var i = 0, k = 0, onceh = 0; - -// instance_activate_object(obj_combat_info); - capital_max = capital; frigate_max = frigate; escort_max = escort; obj_fleet_spawner.alarm[0] = 1; - -// alarm[1]=2; -/* */ -/* */ diff --git a/objects/obj_fleet/Alarm_7.gml b/objects/obj_fleet/Alarm_7.gml index 7597b88ea2..105ef32455 100644 --- a/objects/obj_fleet/Alarm_7.gml +++ b/objects/obj_fleet/Alarm_7.gml @@ -1,12 +1,10 @@ try { - var _player_battle_fleet, yeehaw2, tstar; - _player_battle_fleet = 0; - yeehaw2 = 0; - tstar = 0; + var _player_battle_fleet = noone; + var killer = false; + var killer_tg = 0; if (player_started == 1) { _player_battle_fleet = pla_fleet; - yeehaw2 = ene_fleet; } if ((player_started == 0) && instance_exists(obj_turn_end)) { @@ -32,12 +30,6 @@ try { } } - var op, ii, killer, killer_tg; - op = 0; - killer = 0; - killer_tg = 0; - ii = -50; - if ((player_started == 0) && instance_exists(obj_turn_end)) { with (obj_star) { if (name != obj_turn_end.battle_location[obj_turn_end.current_battle]) { @@ -54,8 +46,8 @@ try { } } } - ii = instance_nearest(room_width, room_height, obj_star); - obj_controller.temp[1070] = ii.id; + var _random_star = instance_nearest(room_width, room_height, obj_star); + obj_controller.temp[1070] = _random_star.id; with (obj_star) { if ((x < -5000) && (y < -5000)) { x += 10000; @@ -63,17 +55,10 @@ try { } } - op = 0; - var ofleet; - ofleet = 0; - repeat (5) { - op += 1; + for (var op = 1; op <= 5; op++) { if ((enemy[op] != 0) && (enemy[op] != 4)) { - ofleet = 0; obj_controller.temp[1071] = enemy[op]; - // show_message("Hiding all but the fleet owned by "+string(obj_controller.temp[1071])); - with (obj_en_fleet) { if ((owner != obj_controller.temp[1071]) || (orbiting != obj_controller.temp[1070])) { x -= 10000; @@ -81,30 +66,23 @@ try { } } - ofleet = instance_nearest(room_width / 2, room_height / 2, obj_en_fleet); - // show_message("Fleet: "+string(ofleet.capital_number)+"/"+string(ofleet.frigate_number)+"/"+string(ofleet.escort_number)+", lost "+string(en_capital_lost[op])+"/"+string(en_frigate_lost[op])+"/"+string(en_escort_lost[op])); - repeat (50) { - if (!instance_exists(ofleet)) { - ofleet = instance_nearest(room_width / 2, room_height / 2, obj_en_fleet); - } - if (instance_exists(ofleet)) { + /// @type {Id.Instance.obj_en_fleet} + var ofleet = instance_nearest(room_width / 2, room_height / 2, obj_en_fleet); + if (ofleet != noone) { if (ofleet.trade_goods == "player_hold") { ofleet.trade_goods = ""; } - // show_message("ofleet x:"+string(ofleet.x)+", ofleet y:"+string(ofleet.y)+", ofleet owner: "+string(ofleet.owner)+" wants "+string(enemy[op])); if ((ofleet.x > -7000) && (ofleet.y > -7000) && (ofleet.owner == enemy[op])) { if (en_capital_lost[op] + en_frigate_lost[op] + en_escort_lost[op] >= ofleet.capital_number + ofleet.frigate_number + ofleet.escort_number) { en_capital_lost[op] -= ofleet.capital_number; en_frigate_lost[op] -= ofleet.frigate_number; en_escort_lost[op] -= ofleet.escort_number; - // show_message("Fleet baleeted"); with (ofleet) { instance_destroy(); } } if ((en_capital_lost[op] + en_frigate_lost[op] + en_escort_lost[op] > 0) && instance_exists(ofleet)) { - // show_message("Fleet: "+string(ofleet.capital_number)+"/"+string(ofleet.frigate_number)+"/"+string(ofleet.escort_number)+", lost "+string(en_capital_lost[op])+"/"+string(en_frigate_lost[op])+"/"+string(en_escort_lost[op])); if ((en_capital_lost[op] > 0) && (ofleet.capital_number > 0)) { en_capital_lost[op] -= 1; ofleet.capital_number -= 1; @@ -133,13 +111,8 @@ try { y += 10000; } } - - // if (instance_exists(ofleet)){show_message("Fleet: "+string(ofleet.capital_number)+"/"+string(ofleet.frigate_number)+"/"+string(ofleet.escort_number));} - // if (!instance_exists(ofleet)){show_message("FlEET WAS DELETED");} } - // show_message("End ship removing"); - if ((enemy[op] == 4) && (enemy_status[op] < 0)) { obj_controller.temp[1071] = enemy[op]; with (obj_en_fleet) { @@ -148,8 +121,8 @@ try { y -= 10000; } } - ofleet = instance_nearest(room_width / 2, room_height / 2, obj_en_fleet); - killer = 1; + var ofleet = instance_nearest(room_width / 2, room_height / 2, obj_en_fleet); + killer = true; obj_controller.temp[1071] = enemy[op]; killer_tg = ofleet.inquisitor; with (ofleet) { @@ -164,7 +137,7 @@ try { obj_controller.cooldown = 20; - if (killer > 0) { + if (killer) { scr_loyalty("Inquisitor Killer", "+"); if (obj_controller.loyalty >= 85) { obj_controller.last_inquisitor_inspection -= 44; @@ -179,11 +152,11 @@ try { scr_loyalty("Inquisitor Killer", "+"); } - var msg = "", msg2 = "", i = 0; + var msg = ""; + var inquis_name = ""; if (killer_tg > 0) { - var inquis_name = obj_controller.inquisitor[killer_tg]; - msg += $"Inquisitor {inquis_name} has been killed!"; - msg2 = $"Inquisitor {inquis_name}"; + inquis_name = $"Inquisitor {obj_controller.inquisitor[killer_tg]}"; + msg += $"{inquis_name} has been killed!"; } if (obj_controller.inquisitor_type[killer_tg] == "Ordo Hereticus") { scr_loyalty("Inquisitor Killer", "+"); @@ -205,11 +178,10 @@ try { instance_activate_object(obj_turn_end); if (instance_exists(obj_turn_end)) { - scr_alert("red", "inqis", string(msg), ii.x + 16, ii.y - 24); + scr_alert("red", "inqis", string(msg), _random_star.x + 16, _random_star.y - 24); } if ((!instance_exists(obj_turn_end)) && (obj_controller.faction_status[eFACTION.INQUISITION] != "War")) { - var pip; - pip = instance_create(0, 0, obj_popup); + var pip = instance_create(0, 0, obj_popup); pip.title = "Inquisitor Killed"; pip.text = msg; pip.image = "inquisition"; @@ -217,13 +189,10 @@ try { if (obj_controller.known[eFACTION.INQUISITION] < 3) { pip.title = "EXCOMMUNICATUS TRAITORUS"; - pip.text = $"The Inquisition has noticed your uncalled murder of {msg2} and declared your chapter Excommunicatus Traitorus."; + pip.text = $"The Inquisition has noticed your uncalled murder of {inquis_name} and declared your chapter Excommunicatus Traitorus."; obj_controller.alarm[8] = 1; } } - - // if (obj_controller.known[eFACTION.INQUISITION]<3) then with(obj_popup){instance_destroy();} - // excommunicatus traitorus } diff --git a/objects/obj_fleet/Create_0.gml b/objects/obj_fleet/Create_0.gml index 724718dacf..9004826a78 100644 --- a/objects/obj_fleet/Create_0.gml +++ b/objects/obj_fleet/Create_0.gml @@ -13,7 +13,6 @@ battle_special = ""; csm_exp = 0; star_name = ""; -// woohoo=0; left_down = 0; view_x = obj_controller.x; @@ -41,8 +40,8 @@ player_started = 0; player_lasers = 0; player_lasers_cd = 70; player_lasers_target = 0; -pla_fleet = 0; -ene_fleet = 0; +pla_fleet = instance_nearest(x, y, obj_p_fleet); +ene_fleet = instance_nearest(x, y, obj_en_fleet); victory = false; instance_deactivate_all(true); @@ -103,7 +102,6 @@ en_mutation[0] = ""; en_mutation[1] = ""; en_mutation[2] = ""; -// ambushers = scr_has_adv("Ambushers"); bolter_drilling = scr_has_adv("Bolter Drilling"); enemy_eldar = scr_has_adv("Enemy: Eldar"); @@ -114,7 +112,7 @@ enemy_tyranids = scr_has_adv("Enemy: Tyranids"); siege = scr_has_adv("Siege Masters"); slow = scr_has_adv("Devastator Doctrine"); melee = scr_has_adv("Assault Doctrine"); -// + black_rage = scr_has_disadv("Black Rage"); shitty_luck = scr_has_disadv("Shitty Luck"); favoured_by_the_warp = scr_has_adv("Favoured By The Warp"); @@ -126,7 +124,7 @@ betchers = obj_ini.betchers; // slight melee penalty catalepsean = obj_ini.catalepsean; // minor global attack decrease occulobe = obj_ini.occulobe; // penalty if morning and susceptible to flash grenades mucranoid = obj_ini.mucranoid; // chance to short-circuit -// + global_melee = 1; global_bolter = 1; global_attack = 1; @@ -150,7 +148,6 @@ if (scr_has_adv("Kings of Space")) { global_attack += 0.1; } -// master = 0; time = 0; @@ -186,7 +183,6 @@ ship_lost = []; // screwing around below here alarm[6] = 2; -// // waiting at this point- show loading screen // in this time the obj_controller passes over which units will be fighting, similar to the below code @@ -203,6 +199,3 @@ column[5] = "escort"; column_width[5] = 76; color_index = 0; - -/* */ -/* */ diff --git a/objects/obj_fleet/Draw_64.gml b/objects/obj_fleet/Draw_64.gml index 436410a156..0381e7b108 100644 --- a/objects/obj_fleet/Draw_64.gml +++ b/objects/obj_fleet/Draw_64.gml @@ -50,7 +50,7 @@ if (start == 0) { } // fast forward icon -if (gamespeed_fps != 90 && start == 5) { +if (game_get_speed(gamespeed_fps) != 90 && start == 5) { draw_set_alpha(1); var _ff_h = sprite_get_height(spr_fast_forward); draw_sprite(spr_fast_forward, 0, 12, (_surface_h / 2) - (_ff_h / 2)); diff --git a/objects/obj_fleet/KeyPress_67.gml b/objects/obj_fleet/KeyPress_67.gml index 632facf1c3..e69de29bb2 100644 --- a/objects/obj_fleet/KeyPress_67.gml +++ b/objects/obj_fleet/KeyPress_67.gml @@ -1,11 +0,0 @@ -/*obj_p_capital.hp=0; -obj_en_ship.hp=0; -obj_en_ship.shields=0; -with(obj_en_ship){instance_destroy();} -*/ - -/*obj_p_ship.hp=0; -player_lasers=48;*/ - -/* */ -/* */ diff --git a/objects/obj_fleet/Mouse_56.gml b/objects/obj_fleet/Mouse_56.gml index 0765ef3893..2c62e6353a 100644 --- a/objects/obj_fleet/Mouse_56.gml +++ b/objects/obj_fleet/Mouse_56.gml @@ -1,5 +1,3 @@ -var pressy; -pressy = 0; sel_x1 = 0; sel_y1 = 0; @@ -42,12 +40,12 @@ if (instance_exists(obj_p_ship) && (control == 1)) { //Why is this here? if ((start == 5) && (obj_controller.zoomed == 0)) { - if ((mouse_x >= camera_get_view_x(view_camera[0]) + 12) && (mouse_y >= camera_get_view_y(view_camera[0]) + 436) && (mouse_x < camera_get_view_x(view_camera[0]) + 48) && (mouse_y < camera_get_view_y(view_camera[0]) + 480) && (gamespeed_fps < 90)) { + if ((mouse_x >= camera_get_view_x(view_camera[0]) + 12) && (mouse_y >= camera_get_view_y(view_camera[0]) + 436) && (mouse_x < camera_get_view_x(view_camera[0]) + 48) && (mouse_y < camera_get_view_y(view_camera[0]) + 480) && (game_get_speed(gamespeed_fps) < 90)) { game_set_speed(game_get_speed(gamespeed_fps) + 30, gamespeed_fps); } } if ((start == 5) && (obj_controller.zoomed == 1)) { - if ((mouse_x > 24) && (mouse_y > 872) && (mouse_x < 90) && (mouse_y < 960) && (gamespeed_fps < 90)) { + if ((mouse_x > 24) && (mouse_y > 872) && (mouse_x < 90) && (mouse_y < 960) && (game_get_speed(gamespeed_fps) < 90)) { game_set_speed(game_get_speed(gamespeed_fps) + 30, gamespeed_fps); } } diff --git a/objects/obj_fleet/Step_0.gml b/objects/obj_fleet/Step_0.gml index c31d146b9d..65390ce41b 100644 --- a/objects/obj_fleet/Step_0.gml +++ b/objects/obj_fleet/Step_0.gml @@ -1,6 +1,4 @@ -// if (woohoo<60) then woohoo+=1; - -if (beg != 0) /* and (instance_exists(obj_fleet_controller))*/ { +if (beg != 0) { if ((combat_end > -1) && (!instance_exists(obj_en_ship))) { combat_end -= 1; victory = true; @@ -59,6 +57,3 @@ if (start == 5) { } } } - -/* */ -/* */ diff --git a/objects/obj_fleet_select/Create_0.gml b/objects/obj_fleet_select/Create_0.gml index 33aee50fe0..73a672ea75 100644 --- a/objects/obj_fleet_select/Create_0.gml +++ b/objects/obj_fleet_select/Create_0.gml @@ -29,15 +29,12 @@ selection_window.inside_method = function() { var width = selection_window.width; var height = selection_window.height; - // draw_text(view_xview[0]+46,view_yview[0]+117,"Title"); - // draw_text(view_xview[0]+46,view_yview[0]+142,"1#2#3#4#5#6#7#8#9#10#11#1#13#14#15#16#17#18#19#20#21#22#23#24#25"); + var lines = 0, posi = -1, colu = 1, x3 = 48, y3 = 60, ty = 0, name = "", selection_box, scale = 1, void_h = 122, shew, ship_health = 0; + var escorts = escort; + var frigates = frigate; + var capitals = capital; - var type = "capital", lines = 0, posi = -1, colu = 1, x3 = 48, y3 = 60, escorts, frigates, capitals, ty = 0, current_ship = 0, current_fleet = 0, name = "", sal = 0, selection_box, scale = 1, void_h = 122, shew, ship_health = 0; - escorts = escort; - frigates = frigate; - capitals = capital; - - current_fleet = instance_nearest(x, y, obj_p_fleet); + var current_fleet = instance_nearest(x, y, obj_p_fleet); if (escorts > 0) { ty++; @@ -159,14 +156,6 @@ selection_window.inside_method = function() { ship_select = fleet_all; } - /*if (y3>670) and (posi<=escorts+frigates+capitals){ - lines=1; - y3=30; - x3+=223; - posi++; - colu++; - }*/ - if ((posi <= escorts + frigates + capitals) && is_array(ship_type) && current_ship < array_length(ship_type)) { name = ship_type[current_ship]; if (string_width(name) * scale > 179) { diff --git a/objects/obj_fleet_select/Draw_0.gml b/objects/obj_fleet_select/Draw_0.gml index d28e51c2c4..a7c91ad80b 100644 --- a/objects/obj_fleet_select/Draw_0.gml +++ b/objects/obj_fleet_select/Draw_0.gml @@ -142,10 +142,9 @@ if (!instance_exists(obj_drop_select) && !instance_exists(obj_bomb_select)) { } else { move_fleet = split_selected_into_new_fleet(player_fleet); } + var final_course = star_travel.final_array_path(); if (keyboard_check(vk_shift)) { final_course = [sys.name]; - } else { - var final_course = star_travel.final_array_path(); } with (move_fleet) { set_new_player_fleet_course(final_course); diff --git a/objects/obj_ingame_menu/Step_0.gml b/objects/obj_ingame_menu/Step_0.gml index 990916a4c8..75b1473934 100644 --- a/objects/obj_ingame_menu/Step_0.gml +++ b/objects/obj_ingame_menu/Step_0.gml @@ -22,11 +22,11 @@ switch (effect) { var _sav = instance_create_depth(0, 0, -20005, obj_saveload); _sav.menu = (effect == eIN_GAME_MENU_EFFECT.SAVE) ? 1 : 2; - var _b = instance_create_depth(707, 830, -20010, obj_new_button); - _b.button_text = "Back"; - _b.target = eIN_GAME_MENU_EFFECT.BACK_FROM_SAVELOAD; - _b.scaling = 1.5; - _b.button_id = 1; + var _load_button = instance_create_depth(707, 830, -20010, obj_new_button); + _load_button.button_text = "Back"; + _load_button.target = eIN_GAME_MENU_EFFECT.BACK_FROM_SAVELOAD; + _load_button.scaling = 1.5; + _load_button.button_id = 1; break; case eIN_GAME_MENU_EFFECT.OPTIONS: @@ -34,12 +34,12 @@ switch (effect) { x -= 2000; y -= 2000; } - var _b = instance_create_depth(653, 664, -20010, obj_new_button); - _b.sprite_index = spr_ui_but_1; - _b.button_text = "Back"; - _b.target = eIN_GAME_MENU_EFFECT.BACK_FROM_SETTINGS; - _b.scaling = 1.5; - _b.button_id = 1; + var _options_button = instance_create_depth(653, 664, -20010, obj_new_button); + _options_button.sprite_index = spr_ui_but_1; + _options_button.button_text = "Back"; + _options_button.target = eIN_GAME_MENU_EFFECT.BACK_FROM_SETTINGS; + _options_button.scaling = 1.5; + _options_button.button_id = 1; settings = 1; cooldown = 8; diff --git a/objects/obj_ini/Create_0.gml b/objects/obj_ini/Create_0.gml index f66a3ef83e..742f805467 100644 --- a/objects/obj_ini/Create_0.gml +++ b/objects/obj_ini/Create_0.gml @@ -1,5 +1,3 @@ -// Global singletons -// global.NameGenerator = new NameGenerator(); LOGGER.debug("Creating obj_ini"); // normal stuff @@ -19,8 +17,6 @@ commands = 0; heh1 = 0; heh2 = 0; -// strin=""; -// strin2=""; companies = 10; progenitor = ePROGENITOR.NONE; aspirant_trial = 0; @@ -123,16 +119,6 @@ veh_acc = array_create_2d(_max_companies, _max_vehicles, ""); // Unit Init defaults_slot = 100; -load_default_gear = function(_role_id, _role_name, _wep1, _wep2, _armour, _mobi, _gear) { - role[defaults_slot][_role_id] = _role_name; - wep1[defaults_slot][_role_id] = _wep1; - wep2[defaults_slot][_role_id] = _wep2; - armour[defaults_slot][_role_id] = _armour; - mobi[defaults_slot][_role_id] = _mobi; - gear[defaults_slot][_role_id] = _gear; - race[defaults_slot][_role_id] = 1; -}; - /// @type {Array} race = [[]]; /// @type {Array>} @@ -158,12 +144,15 @@ god = [[]]; /// @type {Array>} TTRPG = [[]]; -/*if (obj_creation.fleet_type=3){ - obj_controller.penitent=1; - obj_controller.penitent_max=(obj_creation.maximum_size*1000)+300; - if (obj_creation.chapter_name="Lamenters") then obj_controller.penitent_max=100300; - obj_controller.penitent_current=300; -}*/ +load_default_gear = function(_role_id, _role_name, _wep1, _wep2, _armour, _mobi, _gear) { + role[defaults_slot][_role_id] = _role_name; + wep1[defaults_slot][_role_id] = _wep1; + wep2[defaults_slot][_role_id] = _wep2; + armour[defaults_slot][_role_id] = _armour; + mobi[defaults_slot][_role_id] = _mobi; + gear[defaults_slot][_role_id] = _gear; + race[defaults_slot][_role_id] = 1; +}; check_number = 0; year_fraction = 0; @@ -194,8 +183,6 @@ if (global.load == -1) { /// Called from save function to take all object variables and convert them to a json savable format and return it serialize = function() { - var object_ini = self; - var _marines = array_create(0); for (var _coy = 0; _coy <= 10; _coy++) { // Iterate the company's full restored length, not a fixed 0..500, so guardsmen in overflow @@ -238,8 +225,8 @@ serialize = function() { chapter_squad_arrangement: chapter_squad_arrangement, }; - if (struct_exists(object_ini, "last_ship")) { - save_data.last_ship = object_ini.last_ship; + if (variable_instance_exists(self, "last_ship")) { + save_data.last_ship = last_ship; } var excluded_from_save = [ @@ -258,7 +245,7 @@ serialize = function() { "chapter_squad_arrangement" ]; - copy_serializable_fields(object_ini, save_data, excluded_from_save); + copy_serializable_fields(self, save_data, excluded_from_save); return save_data; }; @@ -281,15 +268,13 @@ deserialize = function(save_data) { obj_ini.chapter_squad_arrangement = json_to_gamemaker(working_directory + $"main/squads/company_squad_builds.json", json_parse); } - var _len = array_length(all_names); - for (var i = 0; i < _len; i++) { + for (var i = 0; i < array_length(all_names); i++) { var var_name = all_names[i]; if (array_contains(exclusions, var_name)) { continue; } var loaded_value = struct_get(save_data, var_name); - // LOGGER.debug($"obj_ini var: {var_name} - val: {loaded_value}"); try { variable_struct_set(obj_ini, var_name, loaded_value); } catch (e) { diff --git a/objects/obj_managment_panel/Create_0.gml b/objects/obj_managment_panel/Create_0.gml index 63e0a70013..262e78cc80 100644 --- a/objects/obj_managment_panel/Create_0.gml +++ b/objects/obj_managment_panel/Create_0.gml @@ -45,6 +45,7 @@ draw_lines = function(_x, _y, increment, truncate_line) { draw_set_font(fnt_40k_12); var _draw_func = draw_text; + var _line = truncate_line ? string_truncate(line[l], 134) : line[l]; var _is_struct = is_struct(line[l]); if (_is_struct) { var _struc = line[l]; @@ -54,9 +55,7 @@ draw_lines = function(_x, _y, increment, truncate_line) { if (_struc.bold) { _draw_func = draw_text_bold; } - var _line = truncate_line ? string_truncate(_struc.str1, 134) : _struc.str1; - } else { - var _line = truncate_line ? string_truncate(line[l], 134) : line[l]; + _line = truncate_line ? string_truncate(_struc.str1, 134) : _struc.str1; } _draw_func(_x, _y + _y_depth - scroll_offset, _line); diff --git a/objects/obj_ncombat/Alarm_0.gml b/objects/obj_ncombat/Alarm_0.gml index b01e676c8c..8ff85db560 100644 --- a/objects/obj_ncombat/Alarm_0.gml +++ b/objects/obj_ncombat/Alarm_0.gml @@ -7,9 +7,6 @@ try { instance_activate_object(obj_enunit); - // show_message("Leader?: "+string(leader)); - - // if (enemy=1) then show_message("exiting obj_ncombat_Alarm 0_2 due to enemy=1"); if (enemy == 1) { instance_activate_object(obj_enunit); exit; @@ -30,8 +27,7 @@ try { fortified = 0; } - var i = 0, u; - i = xxx / 10; + var u; if ((fortified > 1) && (enemy + threat != 17)) { u = instance_create(0, 0, obj_nfort); @@ -63,10 +59,11 @@ try { u.maxhp[1] = u.hp[1]; } + var _num = xxx / 10; for (var j = 0; j < 10; j++) { - i -= 1; - u = instance_create(i * 10, 240, obj_enunit); - u.column = i - ((xxx / 10) - 10); + _num -= 1; + u = instance_create(_num * 10, 240, obj_enunit); + u.column = _num - ((xxx / 10) - 10); } // *** Enemy Forces Special Event *** // * Malcadon Spyrer * @@ -287,8 +284,8 @@ try { } // ** Space Hulk Forces ** if (battle_special == "space_hulk") { - var make, modi; - // show_message("space hulk battle, player forces: "+string(player_forces)); + var make; + var modi; with (obj_enunit) { instance_destroy(); } @@ -347,7 +344,6 @@ try { } // * CSM Space Hulk * if (enemy == 10) { - var make, modi; modi = random_range(0.80, 1.20) + 1; make = round(max(3, player_starting_dudes * modi)); @@ -374,7 +370,6 @@ try { hulk_forces = make; } - // show_message(string(instance_number(obj_enunit))+"x enemy blocks"); instance_activate_object(obj_enunit); exit; } @@ -397,11 +392,9 @@ try { u.dudes[5] = "Venerable Chaos Chosen"; u.dudes_num[5] = 50; - // u.dudes[4]="Chaos Basilisk";u.dudes_num[4]=18; instance_deactivate_object(u); u = instance_nearest(xxx + 10, 240, obj_enunit); - // u.dudes[1]="Chaos Leman Russ";u.dudes_num[1]=40; u.dudes[1] = "Chaos Sorcerer"; u.dudes_num[1] = 4; u.dudes[2] = "Chaos Space Marine"; @@ -412,7 +405,6 @@ try { u.dudes_num[4] = 20; u.dudes[5] = "Bloodletter"; u.dudes_num[5] = 30; - // u.dudes[3]="Vindicator";u.dudes_num[3]=10; instance_deactivate_object(u); u = instance_nearest(xxx + 20, 240, obj_enunit); @@ -427,16 +419,11 @@ try { u = instance_nearest(xxx + 30, 240, obj_enunit); u.dudes[1] = "Cultist Elite"; u.dudes_num[1] = 1500; - // u.dudes[2]="Cultist Elite";u.dudes_num[2]=1500; u.dudes[2] = "Helbrute"; u.dudes_num[2] = 3; - // u.dudes[3]="Predator";u.dudes_num[3]=6; - // u.dudes[4]="Vindicator";u.dudes_num[4]=3; - // u.dudes[5]="Land Raider";u.dudes_num[5]=2; instance_deactivate_object(u); u = instance_nearest(xxx + 40, 240, obj_enunit); - // u.dudes[1]="Mutant";u.dudes_num[1]=8000; u.dudes[1] = "Cultist"; u.dudes_num[1] = 1500; u.dudes[2] = "Helbrute"; @@ -458,11 +445,9 @@ try { u.dudes_num[4] = 20; u.dudes[5] = "Venerable Chaos Chosen"; u.dudes_num[5] = 50; - // u.dudes[4]="Chaos Basilisk";u.dudes_num[4]=18; instance_deactivate_object(u); u = instance_nearest(xxx + 10, 240, obj_enunit); - // u.dudes[1]="Chaos Leman Russ";u.dudes_num[1]=40; u.dudes[1] = "Chaos Sorcerer"; u.dudes_num[1] = 2; u.dudes[1] = "Cultist"; @@ -476,15 +461,6 @@ try { guard_total = threat; guard_score = 6; - /*if (guard_total>=15000000) then guard_score=6; - if (guard_total<15000000) and (guard_total>=6000000) then guard_score=5; - if (guard_total<6000000) and (guard_total>=1000000) then guard_score=4; - if (guard_total<1000000) and (guard_total>=50000) then guard_score=3; - if (guard_total<50000) and (guard_total>=500) then guard_score=2; - if (guard_total<500) then guard_score=1;*/ - - // guard_effective=floor(guard_total)/8; - var f = 0, guar = threat / 10; // Guardsmen @@ -569,16 +545,6 @@ try { u.flank = 1; u.flyer = 1; } - - /*u=instance_nearest(xxx,240,obj_enunit);enemy_dudes=threat; - u.dudes[1]="Imperial Guardsman";u.dudes_num[1]=floor(guard_effective*0.6);enemies[1]=u.dudes[1]; - u.dudes[2]="Heavy Weapons Team";u.dudes_num[2]=min(1000,floor(guard_effective*0.1));enemies[2]=u.dudes[2]; - if (threat>1){u.dudes[3]="Leman Russ Battle Tank";u.dudes_num[3]=min(1000,floor(guard_effective*0.1));enemies[3]=u.dudes[3];} - - u=instance_nearest(xxx,240+10,obj_enunit);enemy_dudes=threat; - u.dudes[1]="Imperial Guardsman";u.dudes_num[1]=floor(guard_effective*0.6);enemies[1]=u.dudes[1]; - u.dudes[2]="Heavy Weapons Team";u.dudes_num[2]=min(1000,floor(guard_effective*0.1));enemies[2]=u.dudes[2]; - if (threat>1){u.dudes[3]="Leman Russ Battle Tank";u.dudes_num[3]=min(1000,floor(guard_effective*0.1));enemies[3]=u.dudes[3];}*/ } // ** Aeldar Force ** diff --git a/objects/obj_ncombat/Alarm_1.gml b/objects/obj_ncombat/Alarm_1.gml index 62d194cebb..1afad2cd9d 100644 --- a/objects/obj_ncombat/Alarm_1.gml +++ b/objects/obj_ncombat/Alarm_1.gml @@ -1,5 +1,4 @@ -var a1; -a1 = ""; +var a1 = ""; if ((ally > 0) && (ally_forces > 0)) { if (ally == 3) { @@ -39,8 +38,7 @@ temp += techmarines + honors + dreadnoughts + terminators + captains; temp += standard_bearers + champions + important_dudes + chaplains + apothecaries; temp += sgts + vet_sgts; -var color_descr; -color_descr = ""; +var color_descr = ""; if (obj_ini.main_color != obj_ini.secondary_color) { color_descr = string(obj_controller.col[obj_ini.main_color]) + " and " + string(obj_controller.col[obj_ini.secondary_color]); @@ -49,15 +47,8 @@ if (obj_ini.main_color == obj_ini.secondary_color) { color_descr = string(obj_controller.col[obj_ini.main_color]); } -/*show_message(scouts+tacticals+veterans+devastators+assaults+librarians); -show_message(techmarines+honors+dreadnoughts+terminators+captains); -show_message(standard_bearers+important_dudes+chaplains+apothecaries); -show_message(temp);*/ - // Random variations; dark out, rain pooling down, dawn shining off of the armour, etc. -var variation; -variation = ""; -variation = choose("", "dawn", "rain"); +var variation = choose("", "dawn", "rain"); if (battle_special == "ship_demon") { p1 = "As the Artifact is smashed and melted down some foul smoke begins to erupt from it, spilling outward and upward. After a sparse handful of seconds it takes form into a "; @@ -102,12 +93,6 @@ if (battle_special == "") { if (temp - dreadnoughts > 0) { // lyman p1 = "The air rumbles and quakes as " + string(temp) + " " + string(global.chapter_name) + " descend in drop-pods. "; - - /*if (variation=""){ - if (lyman=0) then p1="The air rumbles and quakes as "+string(temp)+" "+string(global.chapter_name)+" descend in drop-pods. Before the enemy can bring their full ranged power to bear the pods smash down. With practiced speed your marines pour on free. Their ranks are made up of "; - if (lyman=1) then p1="The air rumbles and quakes as "+string(temp)+" "+string(global.chapter_name)+" descend in drop-pods. Before the enemy can bring their full ranged power to bear the pods smash down. Your marines exit the vehicles, shaking off their vertigo and nausea with varying degrees of success. Your ranks are made up of "; - } - */ } } } @@ -308,17 +293,14 @@ if (temp6 > 0) { p2 += string(temp6) + " other various Astartes, "; } -var woo; -woo = string_length(p2); +var woo = string_length(p2); p2 = string_delete(p2, woo - 1, 2); if (string_count(", ", p2) > 1) { - var woo; woo = string_rpos(", ", p2); p2 = string_insert(" and", p2, woo + 1); } if (string_count(", ", p2) == 1) { - var woo; woo = string_rpos(", ", p2); p2 = string_delete(p2, woo - 1, 2); p2 = string_insert(" and", p2, woo + 1); @@ -375,17 +357,14 @@ if (dreadnoughts + predators + land_raiders > 3) { // Other vehicles here? - var woo; woo = string_length(p6); p6 = string_delete(p6, woo - 1, 2); if (string_count(", ", p6) > 1) { - var woo; woo = string_rpos(", ", p6); p6 = string_insert(" and", p6, woo + 1); } if (string_count(", ", p6) == 1) { - var woo; woo = string_rpos(", ", p6); p6 = string_delete(p6, woo - 1, 2); p6 = string_insert(" and", p6, woo + 1); @@ -459,14 +438,6 @@ temp3 = 0; temp4 = 0; temp5 = 0; -/*if (terrain=""){rand=choose(1,2,3);// Variations for terrain - if (rand<4) then - // if (rand=2) then p1="Encroaching upon your forces are "; - // if (rand=3) then p1="Advancing upon your forces are "; -} - -// p1+=string(enemy_dudes);// The number descriptor*/ - if (enemy == 2) { p1 = "Opposing your forces are a total of " + scr_display_number(floor(guard_effective)) + " Guardsmen, including Heavy Weapons and Armour."; p2 = ""; @@ -493,11 +464,10 @@ if ((enemy == 5) && (dropping == 0)) { } if ((enemy == 6) && (dropping == 0)) { - // p1+=" Eldar";// Need a few random descriptors here + // Need a few random descriptors here rand = choose(1, 2, 3); } if ((enemy == 7) && (dropping == 0)) { - // p1+=" Orks"; rand = choose(1, 2, 3); if (rand < 4) { p1 = "Howls and grunts ring from the surrounding terrain as the Orks announce their presence. "; @@ -513,11 +483,9 @@ if ((enemy == 7) && (dropping == 1)) { } if ((enemy == 8) && (dropping == 0)) { - // p1+=" Tau"; rand = choose(1, 2, 3); } if ((enemy == 9) && (dropping == 0)) { - // p1+=" Tyranids"; rand = choose(1, 2, 3); } if ((enemy == 9) && (dropping == 1)) { @@ -525,7 +493,6 @@ if ((enemy == 9) && (dropping == 1)) { } if ((enemy == 10) && (dropping == 0)) { - // p1+=" heretics"; rand = choose(1, 2, 3); } @@ -542,7 +509,6 @@ if ((enemy == 10) && (threat == 7)) { } if ((enemy == 11) && (dropping == 0)) { - // p1+=" Chaos Space Marines"; rand = choose(1, 2, 3); } @@ -632,7 +598,6 @@ if ((fortified > 1) && (dropping == 0) && (enemy + threat != 17)) { } // Check for battlecry here -// if (temp>=100) and (threat>1) and (big_mofo!=10) and (dropping=0){ if ((temp >= 100) && (threat > 1) && (big_mofo > 0) && (big_mofo < 10) && (dropping == 0)) { p1 = ""; p2 = ""; @@ -659,11 +624,9 @@ if ((temp >= 100) && (threat > 1) && (big_mofo > 0) && (big_mofo < 10) && (dropp p1 = "A Chaplain "; } - var standard_cry; - standard_cry = 0; + var standard_cry = 0; if (global.chapter_name == "Salamanders") { standard_cry = 1; - var rand; rand = choose(1, 2, 3, 4, 5); if ((rand == 1) && (big_mofo != 1)) { p2 = "breaks the silence, begining the Chapter Battlecry-"; @@ -720,7 +683,6 @@ if ((temp >= 100) && (threat > 1) && (big_mofo > 0) && (big_mofo < 10) && (dropp } if (obj_ini.battle_cry == "...") { standard_cry = 1; - var rand; rand = choose(1, 2, 3); if ((rand == 1) && (big_mofo != 1)) { p2 = "remains silent as the Chapter forms for battle-"; @@ -764,11 +726,8 @@ if ((temp >= 100) && (threat > 1) && (big_mofo > 0) && (big_mofo < 10) && (dropp scr_newtext(); } - // show_message(string(global.chapter_name)+"|"+string(global.custom)+"|"+string(standard_cry)); - if ((global.chapter_name == "Iron Warriors") && (global.custom == eCHAPTER_TYPE.PREMADE)) { standard_cry = 1; - var rand; rand = choose(1, 2, 3, 4, 5); if ((rand == 1) && (big_mofo != 1)) { p2 = "breaks the silence, begining the Chapter Battlecry-"; @@ -826,7 +785,6 @@ if ((temp >= 100) && (threat > 1) && (big_mofo > 0) && (big_mofo < 10) && (dropp if (standard_cry == 0) { standard_cry = 1; - var rand; rand = choose(1, 2, 3, 4); if (rand == 1) { if (big_mofo != 1) { @@ -894,6 +852,3 @@ newline = line_break; scr_newtext(); newline = line_break; scr_newtext(); - -/* */ -/* */ diff --git a/objects/obj_ncombat/Alarm_2.gml b/objects/obj_ncombat/Alarm_2.gml index c1201cff51..7d76826361 100644 --- a/objects/obj_ncombat/Alarm_2.gml +++ b/objects/obj_ncombat/Alarm_2.gml @@ -7,17 +7,15 @@ if (dropping) { squeeze_map_forces(); } +//TODO refactor so that unit structs are created for ally forces +/* if ((ally > 0) && (ally_forces > 0)) { if (ally == 3) { if (ally_forces >= 1) { - var thata, ii, good; - thata = instance_nearest(0, 240, obj_pnunit); - ii = 0; - good = 0; + var thata = instance_nearest(0, 240, obj_pnunit); + var ii = 0; + var good = 0; - //TODO refactor so that unit structs are created for ally forces - - /* if (instance_exists(thata)){ ii=array_length(marine_type); @@ -57,9 +55,9 @@ if ((ally > 0) && (ally_forces > 0)) { repeat(50){if (good=0){ii+=1;if (thata.dudes[ii]="") and (thata.dudes_num[ii]=0) then good=ii;}} if (good>0){thata.dudes[ii]="Skitarii";thata.dudes_num[ii]=20;thata.dudes_vehicle[ii]=0;} thata.alarm[1]=1; - }*/ + } } } -} +}*/ instance_activate_object(obj_enunit); diff --git a/objects/obj_ncombat/Alarm_3.gml b/objects/obj_ncombat/Alarm_3.gml index f0249ee4ad..a73a772141 100644 --- a/objects/obj_ncombat/Alarm_3.gml +++ b/objects/obj_ncombat/Alarm_3.gml @@ -1,4 +1,3 @@ -// if (battle_over=1) then exit; if (defeat_message == 1) { exit; } @@ -7,25 +6,12 @@ if (wall_destroyed == 1) { wall_destroyed = 0; } -var i, good, changed; -i = 0; -good = 0; -changed = 0; - -// if (messages_to_show = 24) and (messages_shown=0) then alarm[6]=75; -// if (messages_shown=105) then exit; - -/*i+=1;if (message[i]!="") then show_message(message[i]); -i+=1;if (message[i]!="") then show_message(message[i]); -i+=1;if (message[i]!="") then show_message(message[i]); -i+=1;if (message[i]!="") then show_message(message[i]); -i+=1;if (message[i]!="") then show_message(message[i]); -i+=1;if (message[i]!="") then show_message(message[i]);*/ +var good = 0; +var changed = 0; repeat (100) { if (good == 0) { changed = 0; - i = 0; repeat (COMBAT_LOG_CAPACITY) { i += 1; @@ -110,13 +96,8 @@ if (messages == 0) { messages_shown = 999; } -/*var noloss;noloss=instance_nearest(50,300,obj_pnunit); -if (!instance_exists(noloss)) then player_forces=0; -if (instance_exists(noloss)){if (point_distance(50,300,noloss.x,noloss.y)>500) then player_forces=0;}*/ - if (instance_exists(obj_pnunit)) { - var plnear; - plnear = instance_nearest(room_width, 240, obj_pnunit); + var plnear = instance_nearest(room_width, 240, obj_pnunit); if (plnear.x < -40) { player_forces = 0; } @@ -132,10 +113,7 @@ if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { } newline_color = "yellow"; if (obj_ncombat.enemy == 6) { - var jims; - jims = 0; - repeat (20) { - jims += 1; + for (var jims = 1; jims <= 20; jims++) { if ((dead_jim[jims] != "") && (dead_jims > 0)) { newline = dead_jim[jims]; newline_color = "red"; @@ -148,8 +126,7 @@ if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { newline = string(global.chapter_name) + " at " + string(round((player_forces / player_max) * 100)) + "%"; four_show = 0; } - var plnear; - plnear = instance_nearest(room_width, 240, obj_pnunit); + var plnear = instance_nearest(room_width, 240, obj_pnunit); if (((player_forces <= 0) || (plnear.x < -40)) && (defeat_message == 0)) { defeat_message = 1; newline = string(global.chapter_name) + " Defeated"; @@ -170,10 +147,7 @@ if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (timer_stage == 5)) && (four_show == 0)) { newline_color = "yellow"; if (obj_ncombat.enemy != 6) { - var jims; - jims = 0; - repeat (20) { - jims += 1; + for (var jims = 1; jims <= 20; jims++) { if ((dead_jim[jims] != "") && (dead_jims > 0)) { newline = dead_jim[jims]; newline_color = "red"; @@ -186,8 +160,7 @@ if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (time newline = string(global.chapter_name) + " at " + string(round((player_forces / player_max) * 100)) + "%"; four_show = 1; } - var plnear; - plnear = instance_nearest(room_width, 240, obj_pnunit); + var plnear = instance_nearest(room_width, 240, obj_pnunit); if (((player_forces <= 0) || (plnear.x < -40)) && (defeat_message == 0)) { defeat_message = 1; newline = string(global.chapter_name) + " Defeated"; @@ -218,6 +191,3 @@ if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (time timer_stage = 5; exit; } - -/* */ -/* */ diff --git a/objects/obj_ncombat/Alarm_4.gml b/objects/obj_ncombat/Alarm_4.gml index cb52e8a14b..52ebeeff05 100644 --- a/objects/obj_ncombat/Alarm_4.gml +++ b/objects/obj_ncombat/Alarm_4.gml @@ -1,8 +1,4 @@ -var jims; -jims = 0; -repeat (20) { - jims += 1; - +for (var jims = 1; jims <= 20; jims++) { if (dead_jim[jims] != "") { newline = dead_jim[jims]; newline_color = "red"; diff --git a/objects/obj_ncombat/Alarm_5.gml b/objects/obj_ncombat/Alarm_5.gml index 24b2f41e0b..beb08c7551 100644 --- a/objects/obj_ncombat/Alarm_5.gml +++ b/objects/obj_ncombat/Alarm_5.gml @@ -507,7 +507,7 @@ if (defeat == 0 && _reduce_power) { who_cleansed = "Gene Stealer Cult"; make_alert = true; delete_features(p_feature[battle_planet], eP_FEATURES.GENE_STEALER_CULT); - adjust_influence(eFACTION.TYRANIDS, -25, battle_planet); + adjust_influence(eFACTION.TYRANIDS, -25, battle_planet, self); } if (make_alert) { if (p_first[battle_planet] == 1) { @@ -697,9 +697,8 @@ if ((leader || ((battle_special == "ChaosWarband") && (!obj_controller.faction_d } } -var endline, inq_eated; -endline = 1; -inq_eated = false; +var endline = 1; +var inq_eated = false; if (obj_ini.omophagea) { var eatme = roll_dice_chapter(1, 100, "high"); @@ -770,7 +769,6 @@ if (obj_ini.omophagea) { // check for inquisitor eatme = roll_dice_chapter(1, 100, "high"); if ((eatme <= 40) && (present_inquisitor == 1)) { - var thatta = 0, remove = 0, i = 0; obj_controller.disposition[4] -= 10; inq_eated = true; instance_activate_object(obj_en_fleet); @@ -792,7 +790,8 @@ if (obj_ini.omophagea) { scr_loyalty("Inquisitor Killer", "+"); } - var msg = "", msg2 = "", i = 0, remove = 0; + var msg = ""; + var remove = 0; // if (string_count("Inqis",inquisitor_ship.trade_goods)>0) then show_message("B"); if (inquisitor_ship.inquisitor > 0) { var inquis_name = obj_controller.inquisitor[inquisitor_ship.inquisitor]; @@ -807,7 +806,7 @@ if (obj_ini.omophagea) { scr_loyalty("Inquisitor Killer", "+"); } - i = remove; + var i = remove; repeat (10 - remove) { if (i < 10) { obj_controller.inquisitor_gender[i] = obj_controller.inquisitor_gender[i + 1]; diff --git a/objects/obj_ncombat/Alarm_7.gml b/objects/obj_ncombat/Alarm_7.gml index bef6f9528e..9e380eb233 100644 --- a/objects/obj_ncombat/Alarm_7.gml +++ b/objects/obj_ncombat/Alarm_7.gml @@ -1,5 +1,4 @@ try { - // LOGGER.debug("alarm 7 start"); audio_stop_sound(snd_battle); audio_play_sound(snd_royal, 0, true); audio_sound_gain(snd_royal, 1, 5000); @@ -14,20 +13,15 @@ try { // If battling own dudes, then remove the loyalists after the fact if (enemy == 1) { - var j = -1; var cleann = array_create(11, false); with (obj_enunit) { - var q = 0; - repeat (700) { - q += 1; + for (var q = 1; q <= 700; q++) { if (dude_id[q] > 0) { var commandy = false; var nco = dude_co[q]; var nid = dude_id[q]; cleann[nco] = true; - // show_message("dude ID:"+string(q)+" ("+string(obj_ini.name[nco,nid])+") is being removed from the array"); - commandy = is_specialist(obj_ini.role[nco][nid]); if (commandy == true) { obj_controller.command -= 1; @@ -44,7 +38,7 @@ try { } } - for (j = 0; j <= 10; j++) { + for (var j = 0; j <= 10; j++) { if (cleann[j]) { with (obj_ini) { scr_company_order(j); @@ -60,16 +54,14 @@ try { with (obj_star) { if (name == obj_ncombat.battle_loc) { instance_create(x, y, obj_temp_meeting); - var i = 0, ii = 0, otm, good = 0, master_present = 0; - var run = 0, s = 0, chaos_meeting = 0; + var master_present = 0; var master_index = array_get_index(obj_ini.role[0], obj_ini.role[100][eROLE.CHAPTERMASTER]); - chaos_meeting = fetch_unit([0, master_index]).planet_location; + var chaos_meeting = fetch_unit([0, master_index]).planet_location; - // show_message("meeting planet:"+string(chaos_meeting)); for (var co = 0; co <= 10; co++) { for (var i = 0; i < array_length(obj_ini.TTRPG[co]); i++) { - good = 0; + var good = 0; _unit = fetch_unit([co, i]); if (_unit.role() == "" || _unit.location_string != name) { continue; @@ -84,11 +76,9 @@ try { good += 1; } - // if (good>=3) then show_message(string(obj_ini.role[co][i])+": "+string(co)+"."+string(i)); - if (good >= 3) { obj_temp_meeting.dudes += 1; - otm = obj_temp_meeting.dudes; + var otm = obj_temp_meeting.dudes; obj_temp_meeting.present[otm] = 1; obj_temp_meeting.co[otm] = co; obj_temp_meeting.ide[otm] = i; @@ -98,7 +88,6 @@ try { } } } - // show_message("obj_temp_meeting.dudes:"+string(obj_temp_meeting.dudes)); } } } @@ -114,7 +103,6 @@ try { obj_ground_mission.defeat = defeat; obj_ground_mission.explore_feature.ruins_combat_end(); } else if ((battle_special == "WL10_reveal") || (battle_special == "WL10_later")) { - var moar, ox, oy; with (obj_temp8) { instance_destroy(); } @@ -127,28 +115,24 @@ try { if (battle_special == "WL10_reveal") { instance_create(battle_object.x, battle_object.y, obj_temp8); - ox = battle_object.x; - oy = battle_object.y; // battle_object.owner = eFACTION.CHAOS; + var ox = battle_object.x; + var oy = battle_object.y; battle_object.p_traitors[battle_id] = 6; battle_object.p_chaos[battle_id] = 4; battle_object.p_pdf[battle_id] = 0; battle_object.p_owner[battle_id] = 10; - var corro; - corro = 0; + var corro = 0; repeat (100) { - var ii; - ii = 0; if (corro <= 5) { - moar = instance_nearest(ox, oy, obj_star); + var moar = instance_nearest(ox, oy, obj_star); if (moar.owner <= 3) { corro += 1; - repeat (4) { - ii += 1; - if (moar.p_owner[ii] <= 3) { - moar.p_heresy[ii] = min(100, moar.p_heresy[ii] + floor(random_range(30, 50))); + for (var i = 1; i <= 4; i++) { + if (moar.p_owner[i] <= 3) { + moar.p_heresy[i] = min(100, moar.p_heresy[i] + floor(random_range(30, 50))); } } } @@ -213,8 +197,6 @@ try { if ((battle_special == "study2a") || (battle_special == "study2b")) { if (defeat == 1) { - var ii = 0, good = 0; - if (remove_planet_problem(battle_id, "mech_tomb", battle_object)) { obj_controller.disposition[3] -= 10; @@ -247,11 +229,6 @@ try { if ((string_count("mech", battle_special) > 0) && (defeat == 0)) { with (obj_ground_mission) { - var comp, plan, i; - i = 0; - comp = 0; - plan = 0; - plan = instance_nearest(x, y, obj_star); scr_return_ship(obj_ground_mission.loc, obj_ground_mission, obj_ground_mission.num); with (obj_ground_mission) { instance_destroy(); @@ -315,7 +292,7 @@ try { if ((string_count("ruins", battle_special) > 0) && (defeat == 1)) { //TODO this logic is wrong assumes all player units died in ruins var _combat_star = find_star_by_name(obj_ncombat.battle_loc); - if (_combat_star != "none") { + if (_combat_star != noone) { _combat_star.p_player[obj_ncombat.battle_id] -= obj_ncombat.world_size; } } @@ -324,10 +301,8 @@ try { necron_tomb_raid_post_battle_sequence(); } - if ((string_count("spyrer", battle_special) > 0) /* and (string_count("demon",battle_special)>0))*/ && (defeat == 0)) { + if ((string_count("spyrer", battle_special) > 0) && (defeat == 0)) { instance_activate_object(obj_star); - // show_message(obj_turn_end.current_battle); - // show_message(obj_turn_end.battle_world[obj_turn_end.current_battle]); // title / text / image / speshul var cur_star = obj_turn_end.battle_object[obj_turn_end.current_battle]; var planet = obj_turn_end.battle_world[obj_turn_end.current_battle]; @@ -356,13 +331,13 @@ try { hunt_fallen_battle_aftermath(); } else if ((defeat == 0) && (enemy == 9) && (battle_special == "tyranid_org")) { if (captured_gaunt > 1) { - _pop = instance_create(0, 0, obj_popup); + var _pop = instance_create(0, 0, obj_popup); _pop.image = "inquisition"; _pop.title = "Inquisition Mission Completed"; _pop.text = "You have captured several Gaunt organisms. The Inquisitor is pleased with your work, though she notes that only one is needed- the rest are to be purged. It will be stored until it may be retrieved. The mission is a success."; } if (captured_gaunt == 1) { - _pop = instance_create(0, 0, obj_popup); + var _pop = instance_create(0, 0, obj_popup); _pop.image = "inquisition"; _pop.title = "Inquisition Mission Completed"; _pop.text = "You have captured a Gaunt organism- the Inquisitor is pleased with your work. The Tyranid will be stored until it may be retrieved. The mission is a success."; @@ -371,7 +346,7 @@ try { var diceh = roll_dice_chapter(1, 100, "high"); if (diceh <= 15) { - var ship, ship_hp, i = -1; + var ship, ship_hp; for (var i = 0; i < array_length(obj_ini.ship); i++) { ship[i] = obj_ini.ship[i]; ship_hp[i] = obj_ini.ship_hp[i]; @@ -418,7 +393,7 @@ try { instance_destroy(); } if (instance_exists(obj_turn_end)) { - obj_turn_end.combating = 0; // obj_turn_end.alarm[1]=1; + obj_turn_end.combating = 0; } var pip; pip = instance_create(0, 0, obj_popup); @@ -442,7 +417,7 @@ try { instance_destroy(); } if (instance_exists(obj_turn_end)) { - obj_turn_end.combating = 0; // obj_turn_end.alarm[1]=1; + obj_turn_end.combating = 0; } var pip = instance_create(0, 0, obj_popup); pip.title = "Survived"; @@ -489,7 +464,7 @@ try { instance_destroy(); } if (instance_exists(obj_turn_end)) { - obj_turn_end.combating = 0; // obj_turn_end.alarm[1]=1; + obj_turn_end.combating = 0; } var pip = instance_create(0, 0, obj_popup); pip.title = "Chaos Lord Killed"; @@ -544,7 +519,7 @@ try { } } if (battle_special == "ChaosWarband") { - obj_controller.faction_defeated[10] = 1; // show_message("WL10 defeated"); + obj_controller.faction_defeated[10] = 1; if (instance_exists(obj_turn_end)) { scr_event_log("", "Enemy Leader Assassinated: Chaos Lord"); scr_alert("", "ass", "Chaos Lord " + string(obj_controller.faction_leader[eFACTION.CHAOS]) + " has been killed.", 0, 0); @@ -581,9 +556,6 @@ try { } instance_destroy(); - - /* */ - /* */ } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); } diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index b4af9cda48..d48fdc7e4b 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -3,10 +3,6 @@ if (instance_number(obj_ncombat) > 1) { } set_zoom_to_default(); -var co, i; -co = -1; -co = 0; -i = 0; hue = 0; turn_count = 0; @@ -50,10 +46,9 @@ instance_activate_object(obj_cursor); instance_activate_object(obj_ini); instance_activate_object(obj_img); -var i, u; -i = 11; -repeat (10) { - i -= 1; // This creates the objects to then be filled in +var u = noone; +for (var i = 10; i > 0; i--) { + // This creates the objects to then be filled in u = instance_create(i * 10, 240, obj_pnunit); } @@ -137,7 +132,6 @@ enemy_forces = 0; enemy_max = 0; hulk_forces = 0; -i = -1; messages = 0; messages_to_show = 24; messages_shown = 0; @@ -149,23 +143,16 @@ dead_enemies = 0; units_lost_counts = {}; vehicles_lost_counts = {}; -repeat (70) { - i += 1; - lines[i] = ""; - lines_color[i] = ""; - message[i] = ""; - message_sz[i] = 0; - message_priority[i] = 0; - dead_jim[i] = ""; - dead_ene[i] = ""; - dead_ene_n[i] = 0; - - crunch[i] = 0; - - if (i <= 10) { - mucra[i] = 0; - } -} +lines = array_create(70, ""); +lines_color = array_create(70, ""); +message = array_create(70, ""); +message_sz = array_create(70, 0); +message_priority = array_create(70, 0); +dead_jim = array_create(70, ""); +dead_ene = array_create(70, ""); +dead_ene_n = array_create(70, 0); +crunch = array_create(70, 0); +mucra = array_create(11, 0); // The combat-log queue must hold at least COMBAT_LOG_CAPACITY entries so a long turn fully drains. // The status line ("Enemy Forces at X%" / "Defeated") only renders once `messages` reaches 0, and @@ -223,8 +210,6 @@ timer_maxspeed = 1; timer_pause = -1; turns = 1; -// - scouts = 0; tacticals = 0; veterans = 0; @@ -273,8 +258,6 @@ en_apothecaries = 0; en_big_mofo = 10; en_important_dudes = 0; -// - defending = true; // 1 is defensive dropping = 0; // 0 is was on ground attacking = 0; // 1 means attacked from space/local @@ -353,12 +336,12 @@ betchers = obj_ini.betchers; // slight melee penalty catalepsean = obj_ini.catalepsean; // minor global attack decrease occulobe = obj_ini.occulobe; // penalty if morning and susceptible to flash grenades mucranoid = obj_ini.mucranoid; // chance to short-circuit -// + global_melee = 1; global_bolter = 1; global_attack = 1; global_defense = 1; -// + if ((ambushers == 1) && (ambushers == 999)) { global_attack = global_attack * 1.1; } @@ -405,7 +388,6 @@ if (lightning == 1) { if (melee == 1) { global_melee = global_melee * 1.15; } -// if (shitty_luck == 1) { global_defense = global_defense * 0.9; } diff --git a/objects/obj_ncombat/Draw_0.gml b/objects/obj_ncombat/Draw_0.gml index 545c40124b..4cd4e4f5ae 100644 --- a/objects/obj_ncombat/Draw_0.gml +++ b/objects/obj_ncombat/Draw_0.gml @@ -7,8 +7,7 @@ draw_rectangle(818, 235, 1578, 666, 0); draw_set_color(CM_GREEN_COLOR); -var l; -l = 0; +var l = 0; draw_set_alpha(1); draw_rectangle(0 + l, 0 + l, 800 - l, 900 - l, 1); l += 1; @@ -140,11 +139,6 @@ if (click_stall_timer <= 0) { draw_set_halign(fa_left); draw_set_alpha(1); -// Timer -// draw_rectangle(16,464,min(16+(timer*2.026),624),472,0); - -// draw_text(320,300,"Turn: "+string(turns)); - draw_set_color(c_black); draw_set_alpha(fadein / 30); draw_rectangle(0, 0, 1600, 900, 0); diff --git a/objects/obj_ncombat/KeyPress_13.gml b/objects/obj_ncombat/KeyPress_13.gml index 2a7c097145..858bf01ac6 100644 --- a/objects/obj_ncombat/KeyPress_13.gml +++ b/objects/obj_ncombat/KeyPress_13.gml @@ -1,11 +1,6 @@ if (!instance_exists(obj_popup)) { if (cd < 1) { if (click_stall_timer < 1) { - // with(ob_ennt){shomesge(string(dudes[1])+"|"+string(dudes_num[1])+"|"+string(men+medi)+"|"+string(dudes_hp[1]));} - - // 135; - // instance_activate_object(obj_cursor); - if (enemy_forces <= 0) { // Combat for whatever reason sometimes bugs out when there are no enemies, so if enter is pressed 6 times at this state it will set started to 2 enter_pressed++; @@ -29,17 +24,13 @@ if (!instance_exists(obj_popup)) { click_stall_timer = 15; } - // if (done>=1) then exit; - if (turn_count >= 50 || enter_pressed > 5) { started = 2; } if ((started == 2) || (started == 4)) { instance_activate_object(obj_pnunit); instance_activate_object(obj_enunit); - // started=3;alarm[5]=3;obj_pnunit.alarm[4]=1;obj_pnunit.alarm[5]=2;obj_enunit.alarm[1]=3; started = 3; - // obj_pnunit.alarm[4]=2;obj_pnunit.alarm[5]=3;obj_enunit.alarm[1]=1; var _quad_factor = 10; total_battle_exp_gain = _quad_factor * sqr(threat); if (instance_exists(obj_enunit)) { @@ -94,14 +85,12 @@ if (!instance_exists(obj_popup)) { four_show = 0; click_stall_timer = 15; - // if (battle_over!=1) then alarm[8]=15; if (enemy != 6) { if (instance_exists(obj_enunit)) { obj_enunit.alarm[1] = 1; } set_up_player_blocks_turn(); - // alarm[9]=5; } else if (enemy == 6) { if (instance_exists(obj_enunit)) { obj_enunit.alarm[1] = 2; @@ -143,7 +132,6 @@ if (!instance_exists(obj_popup)) { if (instance_exists(obj_enunit)) { obj_enunit.alarm[1] = 1; } - // alarm[9]=5; reset_combat_message_arrays(); } } diff --git a/objects/obj_ncombat/Step_0.gml b/objects/obj_ncombat/Step_0.gml index 5a71266b52..5552091b30 100644 --- a/objects/obj_ncombat/Step_0.gml +++ b/objects/obj_ncombat/Step_0.gml @@ -42,7 +42,6 @@ if (cd >= 0) { if (click_stall_timer >= 0) { click_stall_timer -= 1; } -// if (done>=1) then done+=1; if (!instance_exists(obj_enunit)) { enemy_forces = 0; @@ -99,7 +98,6 @@ if (((fugg >= 60) || (fugg2 >= 60)) && (messages_shown == 0) && (messages_to_sho exit; } - // show_message("Shown: "+string(messages_shown)+"#Messages: "+string(messages)+"#Timer Stage: "+string(timer_stage)); if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (timer_stage == 5)) && (four_show == 0)) { newline_color = "yellow"; if (obj_ncombat.enemy != 6) { @@ -133,7 +131,6 @@ if (((fugg >= 60) || (fugg2 >= 60)) && (messages_shown == 0) && (messages_to_sho exit; } -// if (player_forces>0) and (enemy_forces>0) and (battle_over=0){ if (timer_stage == 2) { fugg += 1; } diff --git a/objects/obj_p_assra/Step_0.gml b/objects/obj_p_assra/Step_0.gml index c469ce1083..519cf2d065 100644 --- a/objects/obj_p_assra/Step_0.gml +++ b/objects/obj_p_assra/Step_0.gml @@ -93,8 +93,7 @@ if ((boarding == true) && (board_cooldown >= 0) && instance_exists(target) && in if (board_cooldown == 0) { board_cooldown = 60; - var o, challenge, boarding_odds, boarding_advantage, boarding_disadvantage, gear_bonus, marine_bonus, outcome_roll, damage_roll, attack, arp, wep, ac, dr, co, i, hits, hurt, damaged_ship, bridge_damage; - o = firstest - 1; + var challenge, boarding_odds, boarding_advantage, boarding_disadvantage, gear_bonus, marine_bonus, outcome_roll, damage_roll, attack, arp, wep, ac, dr, co, i, hits, hurt, damaged_ship, bridge_damage; boarding_odds = 0; challenge = 0; outcome_roll = 0; @@ -116,9 +115,6 @@ if ((boarding == true) && (board_cooldown >= 0) && instance_exists(target) && in exit; } - // show_message(origin); - // show_message(string(origin.board_co[1])); - co = origin.board_co[o]; i = origin.board_id[o]; ac = 0; @@ -141,8 +137,8 @@ if ((boarding == true) && (board_cooldown >= 0) && instance_exists(target) && in if (!is_struct(_weapons[0]) && !is_struct(_weapons[1])) { gear_bonus -= 10; } else { - for (var i = 0; i <= 1; i++) { - var _weapon = _weapons[i]; + for (var j = 0; j <= 1; j++) { + var _weapon = _weapons[j]; if (!is_struct(_weapon)) { continue; } @@ -566,16 +562,11 @@ if ((boarding == true) && (board_cooldown >= 0) && instance_exists(target) && in apothecary_had -= 1; } } - - // show_message(string(obj_ini.role[co][i])+" "+string(obj_ini.role[co][i])+" hit by "+string(hits)+"x "+string(wep)+", "+string(obj_ini.hp[co][i])+" HP remaining"); } } - - // board_co[i]=0;board_id[i]=0;board_location[i]=0;board_raft[i]=0; } if (experience > 0) { - var o = 0, co = 0, i = 0; var new_exp, unit_exp, exp_roll; for (var o = 0; o < array_length(origin.board_co); o++) { co = origin.board_co[o]; diff --git a/objects/obj_p_fleet/Alarm_1.gml b/objects/obj_p_fleet/Alarm_1.gml index 232a4a1c6e..f53c6325b7 100644 --- a/objects/obj_p_fleet/Alarm_1.gml +++ b/objects/obj_p_fleet/Alarm_1.gml @@ -1,23 +1,18 @@ try { - var spid, dir; - spid = 0; - dir = 0; - acted = 0; if (action == "Lost") { set_fleet_location("Lost"); exit; } else if (action == "") { - spid = instance_nearest(x, y, obj_star); - // spid.present_fleets+=1; + var spid = instance_nearest(x, y, obj_star); spid.present_fleet[1] += 1; if (spid.vision == 0) { spid.vision = 1; } orbiting = spid; - if ((orbiting != 0) && instance_exists(orbiting)) { + if ((orbiting != noone) && instance_exists(orbiting)) { if (orbiting.visited == 0) { for (var planet_num = 1; planet_num <= orbiting.planets; planet_num += 1) { if (array_length(orbiting.p_feature[planet_num]) != 0) { @@ -32,16 +27,15 @@ try { meet_system_governors(orbiting); } } else if (array_contains(global.fleet_move_options, action)) { - var i; set_fleet_location("Warp"); if (instance_nearest(action_x, action_y, obj_star).storm > 0) { exit; } - spid = point_distance(x, y, action_x, action_y); + var spid = point_distance(x, y, action_x, action_y); spid = spid / max(1, action_eta); - dir = point_direction(x, y, action_x, action_y); + var dir = point_direction(x, y, action_x, action_y); x = x + lengthdir_x(spid, dir); y = y + lengthdir_y(spid, dir); @@ -63,7 +57,7 @@ try { } var enemies = false; for (var i = 6; i < 13; i++) { - if (scr_orbiting_fleet(i) != "none") { + if (scr_orbiting_fleet(i) != noone) { enemies = true; break; } @@ -95,7 +89,6 @@ try { } steh.present_fleet[1] += 1; orbiting = steh; - // show_message("Present Fleets at alarm[1]: "+string(steh.present_fleets)); meet_system_governors(steh); @@ -144,8 +137,7 @@ try { } } - var steh; - steh = instance_nearest(x, y, obj_star); + var steh = instance_nearest(x, y, obj_star); if (instance_exists(steh) && (steh != 0)) { if (steh.p_type[1] == "Craftworld") { var dist, rando; @@ -153,8 +145,6 @@ try { rando = floor(random(100)) + 1; dist = point_distance(x, y, steh.old_x, steh.old_y); - // show_message("Dist: "+string(dist)+", Rando: "+string(rando)); - if ((rando >= 95) && (dist <= 300)) { obj_controller.known[eFACTION.ELDAR] = 1; scr_alert("green", "elfs", "Eldar Craftworld discovered.", steh.old_x, steh.old_y); diff --git a/objects/obj_p_fleet/Alarm_11.gml b/objects/obj_p_fleet/Alarm_11.gml index 718c564b5a..f146c8727b 100644 --- a/objects/obj_p_fleet/Alarm_11.gml +++ b/objects/obj_p_fleet/Alarm_11.gml @@ -1,4 +1,4 @@ -if ((action == "") && (orbiting != 0)) { +if ((action == "") && (orbiting != noone)) { orbiting = instance_nearest(x, y, obj_star); orbiting.present_fleet[1] += 1; } diff --git a/objects/obj_p_fleet/Alarm_3.gml b/objects/obj_p_fleet/Alarm_3.gml index faff553a20..d88b008cad 100644 --- a/objects/obj_p_fleet/Alarm_3.gml +++ b/objects/obj_p_fleet/Alarm_3.gml @@ -6,24 +6,19 @@ obj_controller.popup = 1; // 1: fleet, 2: other fleet, 3: other selected = 1; obj_controller.fleet_minimized = 0; -var xx = x, yy = y; - obj_controller.selected = id; if (instance_exists(obj_fleet_select)) { if (obj_controller.selected == obj_fleet_select.id) { exit; } } -// obj_controller.selected=self; obj_controller.sel_owner = self.owner; -// show_message(obj_controller.selected); obj_controller.cooldown = 8; if (obj_controller.zoomed) { scr_zoom(); } -// Pass variables to obj_controller.temp[t]=""; here with (obj_fleet_select) { instance_destroy(); } @@ -34,9 +29,7 @@ obj_fleet_select.escort = escort_number; obj_fleet_select.frigate = frigate_number; obj_fleet_select.capital = capital_number; -var i = -1; -repeat (91) { - i += 1; +for (var i = 0; i <= 90; i++) { if (i <= 20) { capital_sel[i] = 1; } @@ -57,9 +50,3 @@ repeat (91) { } } } - -/*var ii;ii=0;ii+=capital_number;ii+=round((frigate_number/2));ii+=round((escort_number/4)); -if (ii<=1) then ii=1;image_index=ii;*/ - -/* */ -/* */ diff --git a/objects/obj_p_fleet/Alarm_4.gml b/objects/obj_p_fleet/Alarm_4.gml index 98ad26b469..73eca50db5 100644 --- a/objects/obj_p_fleet/Alarm_4.gml +++ b/objects/obj_p_fleet/Alarm_4.gml @@ -1,15 +1,5 @@ -var sys_dist, mine, connected, fleet, cont; -sys_dist = 9999; -connected = 0; -cont = 0; - var eta = calculate_fleet_eta(x, y, action_x, action_y, action_spd, false, false, warp_able); -// if (connected=0) then eta=eta*2; -// if (connected=1) then connected=1; -// if (web=1) then eta=1; -action_eta = eta; -// if (action="crusade2") then action="crusade3"; -// if (action="crusade1") then action="crusade2"; +action_eta = eta; set_fleet_location("Warp"); diff --git a/objects/obj_p_fleet/Alarm_5.gml b/objects/obj_p_fleet/Alarm_5.gml index 9012a59566..c39419c485 100644 --- a/objects/obj_p_fleet/Alarm_5.gml +++ b/objects/obj_p_fleet/Alarm_5.gml @@ -1,9 +1,6 @@ -var i, minhp, maxhp; - if (capital_number > 0) { - i = 0; - minhp = 0; - maxhp = 0; + var minhp = 0; + var maxhp = 0; for (var i = 0; i < array_length(capital); i++) { if ((capital[i] != "") && (capital_num[i] > -1)) { minhp += obj_ini.ship_hp[i]; @@ -18,9 +15,8 @@ if (capital_number > 0) { } if (frigate_number > 0) { - i = 0; - minhp = 0; - maxhp = 0; + var minhp = 0; + var maxhp = 0; for (var i = 0; i < array_length(frigate); i++) { if (frigate[i] != "" && frigate_num[i] > -1 && frigate_num[i] < array_length(obj_ini.ship_hp)) { minhp += obj_ini.ship_hp[i]; @@ -35,9 +31,8 @@ if (frigate_number > 0) { } if (escort_number > 0) { - i = 0; - minhp = 0; - maxhp = 0; + var minhp = 0; + var maxhp = 0; for (var i = 0; i < array_length(escort); i++) { if ((escort[i] != "") && (escort_num[i] > -1)) { minhp += obj_ini.ship_hp[i]; diff --git a/objects/obj_p_fleet/Alarm_6.gml b/objects/obj_p_fleet/Alarm_6.gml index 0e1de6d0be..9f215138d3 100644 --- a/objects/obj_p_fleet/Alarm_6.gml +++ b/objects/obj_p_fleet/Alarm_6.gml @@ -5,6 +5,3 @@ with (obj_ini) { if (player_fleet_ship_count() == 0) { instance_destroy(); } - -/* */ -/* */ diff --git a/objects/obj_p_fleet/Alarm_7.gml b/objects/obj_p_fleet/Alarm_7.gml index 7f1765c106..2a300c2cd2 100644 --- a/objects/obj_p_fleet/Alarm_7.gml +++ b/objects/obj_p_fleet/Alarm_7.gml @@ -3,7 +3,8 @@ if (capital_number == 0) { exit; } -var c = 0, good = 0; +var c = 0; +var good = 0; var capital_id; var capital_list = fleet_full_ship_array(,, true, true); for (var i = 0; i < array_length(capital_list); i++) { diff --git a/objects/obj_p_fleet/Create_0.gml b/objects/obj_p_fleet/Create_0.gml index 290aef21a0..53cf95ae69 100644 --- a/objects/obj_p_fleet/Create_0.gml +++ b/objects/obj_p_fleet/Create_0.gml @@ -3,7 +3,7 @@ capital_number = 0; frigate_number = 0; escort_number = 0; selected = 0; -orbiting = 0; +orbiting = noone; warp_able = true; ii_check = choose(8, 9, 10, 11, 12); @@ -19,7 +19,6 @@ point_breakdown = single_loc_point_data(); image_xscale = 1.25; image_yscale = 1.25; -var i = -1; capital = []; capital_num = []; capital_sel = []; @@ -95,7 +94,7 @@ deserialize = function(save_data) { } } - if (save_data.orbiting != 0) { + if (save_data.orbiting != noone) { var nearest_star = instance_nearest(x, y, obj_star); set_player_fleet_image(); orbiting = nearest_star; diff --git a/objects/obj_p_fleet/Destroy_0.gml b/objects/obj_p_fleet/Destroy_0.gml index 0d9ab96c6c..28facfa8b8 100644 --- a/objects/obj_p_fleet/Destroy_0.gml +++ b/objects/obj_p_fleet/Destroy_0.gml @@ -1,6 +1,6 @@ -if ((action == "") && (orbiting != 0)) { +if ((action == "") && (orbiting != noone)) { if (instance_exists(orbiting)) { orbiting.present_fleet[1] -= 1; } - orbiting = 0; + orbiting = noone; } diff --git a/objects/obj_p_fleet/Draw_0.gml b/objects/obj_p_fleet/Draw_0.gml index 916758ec3a..9b352f166e 100644 --- a/objects/obj_p_fleet/Draw_0.gml +++ b/objects/obj_p_fleet/Draw_0.gml @@ -22,7 +22,7 @@ var coords = [ var near_star = instance_nearest(x, y, obj_star); if (x == near_star.x && y == near_star.y) { - var coords = [ + coords = [ 24, -24 ]; @@ -65,7 +65,6 @@ if (!keyboard_check(vk_shift)) { } } } -// if (obj_controller.selected!=0) and (selected=1) then within=1; if (obj_controller.selecting_planet > 0) { if ((mouse_x >= camera_get_view_x(view_camera[0]) + 529) && (mouse_y >= camera_get_view_y(view_camera[0]) + 234) && (mouse_x < camera_get_view_x(view_camera[0]) + 611) && (mouse_y < camera_get_view_y(view_camera[0]) + 249)) { @@ -91,7 +90,6 @@ if (obj_controller.selecting_planet > 0) { } } -var line_width = obj_controller.zoomed ? 6 : 1; var line_width = sqr(scale); var text_size = sqr(scale); @@ -100,7 +98,6 @@ if (action != "") { draw_set_alpha(1); draw_set_color(c_white); draw_line_width(x, y, action_x, action_y, line_width); - // draw_set_font(fnt_40k_14b); draw_text_transformed(x + 12, y, string_hash_to_newline("ETA " + string(action_eta)), text_size, text_size, 0); @@ -130,8 +127,6 @@ if ((within == 1) || (selected > 0)) { if ((capital_number == 0) && (frigate_number == 0) && (escort_number == 1)) { ppp = escort[0]; } - // ppp=acted; - // draw_set_color(CM_GREEN_COLOR); draw_set_font(fnt_40k_14b); draw_set_halign(fa_center); @@ -148,12 +143,4 @@ if ((within == 1) || (selected > 0)) { draw_set_alpha(1); } -// if (is_orbiting()){ -// orbiting = instance_nearest(x,y ,obj_star); -// var draw_x = x - orbiting.x; -// var draw_y = y - orbiting.y; -// } - draw_sprite_ext(sprite_index, image_index, x + (coords[0] * scale), y + (coords[1] * scale), 1 * scale, 1 * scale, 0, c_white, 1); - -// draw_sprite_ext(sprite_index,image_index,(draw_x*scale),(draw_y*scale),1*scale,1*scale,0,c_white,1) diff --git a/objects/obj_p_fleet/Step_0.gml b/objects/obj_p_fleet/Step_0.gml index 1c712b0f0a..13cafe81f7 100644 --- a/objects/obj_p_fleet/Step_0.gml +++ b/objects/obj_p_fleet/Step_0.gml @@ -2,10 +2,10 @@ ii_check -= 1; if (action == "Lost") { exit; } -if ((action != "") && (orbiting != 0)) { +if ((action != "") && (orbiting != noone)) { orbiting = instance_nearest(x, y, obj_star); orbiting.present_fleet[1] -= 1; - orbiting = 0; + orbiting = noone; } action_spd = calculate_action_speed(); diff --git a/objects/obj_p_ship/Alarm_0.gml b/objects/obj_p_ship/Alarm_0.gml index 14382cbf0f..2c72938d10 100644 --- a/objects/obj_p_ship/Alarm_0.gml +++ b/objects/obj_p_ship/Alarm_0.gml @@ -1,12 +1,6 @@ action = ""; direction = 0; -cooldown1 = 0; -cooldown2 = 0; -cooldown3 = 0; -cooldown4 = 0; -cooldown5 = 0; - name = obj_ini.ship[ship_id]; class = obj_ini.ship_class[ship_id]; hp = obj_ini.ship_hp[ship_id] * 1; @@ -18,7 +12,6 @@ armour_front = obj_ini.ship_front_armour[ship_id]; armour_other = obj_ini.ship_other_armour[ship_id]; weapons = obj_ini.ship_weapons[ship_id]; turrets = 0; -ship_colour = obj_controller.body_colour_replace; weapon = obj_ini.ship_wep[ship_id]; weapon_facing[1] = ""; @@ -191,14 +184,12 @@ if (obj_controller.stc_bonus[6] == 2) { armour_other = round(armour_other * 1.1); } -var i = 0, unit, b = 0; - for (var co = 0; co <= obj_ini.companies; co++) { - for (i = 0; i < array_length(obj_ini.name[co]); i++) { + for (var i = 0; i < array_length(obj_ini.name[co]); i++) { if (obj_ini.name[co][i] == "") { continue; } - unit = fetch_unit([co, i]); + var unit = fetch_unit([co, i]); if (unit.ship_location == ship_id) { if (unit.is_boarder && unit.hp() > (unit.max_health() / 10)) { array_push(board_co, co); diff --git a/objects/obj_p_ship/Create_0.gml b/objects/obj_p_ship/Create_0.gml index 0c53712f9a..3cf0c6a883 100644 --- a/objects/obj_p_ship/Create_0.gml +++ b/objects/obj_p_ship/Create_0.gml @@ -16,7 +16,7 @@ action_dis = 0; action_dir = 0; action_fac = 0; direction = 0; -target = -50; +target = noone; if (instance_exists(obj_en_ship)) { target = instance_nearest(x, y, obj_en_ship); } diff --git a/objects/obj_p_ship/Step_0.gml b/objects/obj_p_ship/Step_0.gml index a08c002be8..16c69ac2a9 100644 --- a/objects/obj_p_ship/Step_0.gml +++ b/objects/obj_p_ship/Step_0.gml @@ -18,10 +18,10 @@ if (board_cooldown >= 0) { if (instance_exists(target)) { if (((target.x < 3) && (target.y < 3)) || (target.hp < 0)) { - target = -50; + target = noone; } } -if ((!instance_exists(target)) || (target == -50)) { +if ((!instance_exists(target)) || (target == noone)) { with (obj_en_ship) { if (((x < 3) && (y < 3)) || (hp <= 0)) { instance_deactivate_object(id); @@ -156,9 +156,8 @@ if ((hp > 0) && instance_exists(target)) { } // STC Bonuses - var speed_up, speed_down; - speed_up = 0.005; - speed_down = 0.025; + var speed_up = 0.005; + var speed_down = 0.025; if (obj_controller.stc_bonus[6] == 3) { speed_up = 0.008; speed_down = 0.037; @@ -216,7 +215,6 @@ if ((hp > 0) && instance_exists(target)) { } if ((paction == "move") || (paction == "attack_move")) { direction = turn_towards_point(direction, x, y, target_x, target_y, ts / 2); - var dist; dist = point_distance(x, y, target_x, target_y); if (y > target_y) { direction = turn_towards_point(direction, x, y, target_x, target_y, ts); @@ -252,22 +250,15 @@ if ((hp > 0) && instance_exists(target)) { turret_cool -= 1; } - var bull, targe, rdir, dirr, dist, xx, yy, ok; - targe = 0; - rdir = 0; - dirr = ""; - dist = 9999; - xx = x; - yy = y; - if ((turrets > 0) && instance_exists(obj_en_in) && (turret_cool == 0)) { - targe = instance_nearest(x, y, obj_en_in); + dist = 9999; + var targe = instance_nearest(x, y, obj_en_in); if (instance_exists(targe)) { dist = point_distance(x, y, targe.x, targe.y); } if ((dist > 64) && (dist < 300)) { - bull = instance_create(x, y, obj_p_round); + var bull = instance_create(x, y, obj_p_round); bull.direction = point_direction(x, y, targe.x, targe.y); bull.speed = 20; bull.dam = 3; @@ -277,21 +268,18 @@ if ((hp > 0) && instance_exists(target)) { bull.direction += choose(random(3), 1 * -random(3)); } } - targe = 0; - rdir = 0; - dirr = ""; - dist = 9999; + var rdir = 0; - xx = lengthdir_x(64, direction + 90); - yy = lengthdir_y(64, direction + 90); + var xx = lengthdir_x(64, direction + 90); + var yy = lengthdir_y(64, direction + 90); - var front, right, left, rear; - front = 0; - right = 0; - left = 0; - rear = 0; + var front = 0; + var right = 0; + var left = 0; + var rear = 0; - targe = instance_nearest(xx, yy, obj_en_ship); + var bull = noone; + var targe = instance_nearest(xx, yy, obj_en_ship); if (instance_exists(targe)) { rdir = point_direction(x, y, target.x, target.y); if ((rdir > 45) && (rdir <= 135) && (targe != target)) { @@ -309,9 +297,7 @@ if ((hp > 0) && instance_exists(target)) { var f = 0, facing = "", ammo = 0, range = 0, wep = "", dam = 0; for (var gg = 1; gg < array_length(weapon); gg++) { - // if (cooldown[gg]>0) then cooldown[gg]-=1; - - ok = 0; + var ok = 0; f += 1; facing = ""; ammo = 0; @@ -351,14 +337,11 @@ if ((hp > 0) && instance_exists(target)) { dist = point_distance(x, y, targe.x, targe.y); if ((ok == 2) && (dist < (range + max(sprite_get_width(sprite_index), sprite_get_height(sprite_index))))) { - //if (ammo>0) and (ammo<500) then ammo-=1; weapon_ammo[gg] = ammo; cooldown[gg] = weapon_cooldown[gg]; wep = weapon[gg]; dam = weapon_dam[gg]; - // if (f=3) and (ship_id=2) then show_message("ammo: "+string(ammo)+" | range: "+string(range)); - if (ammo < 0) { ok = 0; } @@ -427,14 +410,11 @@ if ((hp > 0) && instance_exists(target)) { } } -/* */ //Deploy boarding craft logic if (instance_exists(obj_en_ship) && (boarders > 0) && (board_cooldown <= 0) && ((board_capital == true) || (board_frigate == true))) { - var eh = 0, te = 0; - repeat (2) { - eh += 1; - te = 0; + for (var eh = 1; eh <= 2; eh++) { + var te = 0; if ((eh == 1) && (board_capital == true)) { if (instance_exists(obj_en_capital)) { te = instance_nearest(x, y, obj_en_capital); @@ -452,6 +432,3 @@ if (instance_exists(obj_en_ship) && (boarders > 0) && (board_cooldown <= 0) && ( } } } - -/* */ -/* */ diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index d689667c56..a0319f75d5 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -1,8 +1,4 @@ try { - // with(obj_enunit){show_message(string(dudes[1])+"|"+string(dudes_num[1])+"|"+string(men+medi)+"|"+string(dudes_hp[1]));} - - var rightest, charge = 0, enemy2 = 0; // psy=false; - if (instance_number(obj_enunit) != 1) { obj_ncombat.flank_x = self.x; with (obj_enunit) { @@ -12,9 +8,7 @@ try { } } - rightest = get_rightmost(); // Right most pnunit enemy = instance_nearest(0, y, obj_enunit); // Left most enemy - enemy2 = enemy; if (obj_ncombat.dropping || (!obj_ncombat.defending && obj_ncombat.formation_set != 2)) { move_unit_block("east"); @@ -84,14 +78,12 @@ try { weapon_data = gear_weapon_data("weapon", wep[i]); once_only = 0; enemy = instance_nearest(0, y, obj_enunit); - enemy2 = enemy; if (enemy.men + enemy.veh + enemy.medi <= 0) { var x5 = enemy.x; with (enemy) { instance_destroy(); } enemy = instance_nearest(0, y, obj_enunit); - enemy2 = enemy; } // Speed Force sweeps the whole field - bypass normal targeting/range. @@ -118,6 +110,7 @@ try { if ((range_shoot == "ranged") && (range[i] >= dist)) { // Weapon meets preliminary checks var ap = 0; + var good = 0; if (apa[i] > att[i]) { ap = 1; } // Determines if it is AP or not @@ -138,7 +131,7 @@ try { if ((ap == 1) && (once_only == 0)) { // Check for vehicles - var enemy2, g = 0, good = 0; + var g = 0; if (enemy.veh > 0) { good = scr_target(enemy, "veh"); // First target has vehicles, blow it to hell @@ -150,7 +143,7 @@ try { repeat (instance_number(obj_enunit) - 1) { if (good == 0) { x2 += 10; - enemy2 = instance_nearest(x2, y, obj_enunit); + var enemy2 = instance_nearest(x2, y, obj_enunit); if ((enemy2.veh > 0) && (good == 0)) { good = scr_target(enemy2, "veh"); // This target has vehicles, blow it to hell scr_shoot(i, enemy2, good, "arp", "ranged"); @@ -176,7 +169,7 @@ try { repeat (instance_number(obj_enunit) - 1) { if (good == 0) { x2 += 10; - enemy2 = instance_nearest(x2, y, obj_enunit); + var enemy2 = instance_nearest(x2, y, obj_enunit); if ((enemy2.veh > 0) && (good == 0)) { good = scr_target(enemy2, "medi"); // This target has vehicles, blow it to hell scr_shoot(i, enemy2, good, "medi", "ranged"); @@ -195,8 +188,7 @@ try { if (instance_exists(enemy)) { if ((ap == 0) && (once_only == 0)) { // Check for men - var g, good, enemy2; - g = 0; + var g = 0; good = 0; if (enemy.men + enemy.medi > 0) { @@ -205,12 +197,11 @@ try { } if ((good == 0) && (instance_number(obj_enunit) > 1)) { // First target does not have vehicles, cycle through objects to find one that has vehicles - var x2; - x2 = enemy.x; + var x2 = enemy.x; repeat (instance_number(obj_enunit) - 1) { if (good == 0) { x2 += 10; - enemy2 = instance_nearest(x2, y, obj_enunit); + var enemy2 = instance_nearest(x2, y, obj_enunit); if ((enemy2.men > 0) && (good == 0)) { good = scr_target(enemy2, "men"); // This target has vehicles, blow it to hell scr_shoot(i, enemy2, good, "att", "ranged"); @@ -235,7 +226,7 @@ try { if ((apa[i] == 1) && (once_only == 0)) { // Check for vehicles - var enemy2, g = 0, good = 0; + var g = 0, good = 0; if (enemy.veh > 0) { good = scr_target(enemy, "veh"); // First target has vehicles, blow it to hell @@ -253,7 +244,7 @@ try { if ((enemy.veh == 0) && (enemy.medi > 0) && (once_only == 0)) { // Check for vehicles - var enemy2, g = 0, good = 0; + var g = 0, good = 0; if (enemy.medi > 0) { good = scr_target(enemy, "medi"); // First target has vehicles, blow it to hell @@ -271,10 +262,9 @@ try { if ((ap == 0) && (once_only == 0)) { // Check for men - var g = 0, good = 0, enemy2; + var g = 0, good = 0; if ((enemy.men > 0) && (once_only == 0)) { - // show_message(string(wep[i])+" attacking"); good = scr_target(enemy, "men"); if (range[i] == 1) { scr_shoot(i, enemy, good, "att", "melee"); @@ -330,12 +320,6 @@ try { flush_psychic_summary(_psy_log); } } -// LOGGER.debug($"known_powers: {known_powers}"); -// LOGGER.debug($"buff_powers: {buff_powers}"); -// LOGGER.debug($"buff_cast: {buff_cast}"); -// LOGGER.debug($"power_index: {power_index}"); -// LOGGER.debug($"known_attack_powers: {known_attack_powers}"); catch (_exception) { - // LOGGER.debug($"known_buff_powers: {known_buff_powers}"); ERROR_HANDLER.handle_exception(_exception); } diff --git a/objects/obj_pnunit/Alarm_1.gml b/objects/obj_pnunit/Alarm_1.gml index 9327b39df8..a776c983aa 100644 --- a/objects/obj_pnunit/Alarm_1.gml +++ b/objects/obj_pnunit/Alarm_1.gml @@ -1,5 +1 @@ -/* */ -/* */ scr_player_combat_weapon_stacks(); - -//LOGGER.debug("{0},/n{1},/n{2},/n{3},/n{4},/n{5}",wep_num,range,wep,att,wep_solo,wep_title); diff --git a/objects/obj_pnunit/Alarm_3.gml b/objects/obj_pnunit/Alarm_3.gml index a1f7f38b1b..3a30236c2e 100644 --- a/objects/obj_pnunit/Alarm_3.gml +++ b/objects/obj_pnunit/Alarm_3.gml @@ -1,14 +1,10 @@ try { if (obj_ncombat.started == 0) { if (men + dreads + veh <= 0) { - //LOGGER.debug($"column destroyed {x}") instance_destroy(); } - // if (veh+dreads>0) then instance_destroy(); - if (guard == 0) { - obj_ncombat.player_forces += self.men + self.veh + self.dreads; - obj_ncombat.player_max += self.men + self.veh + self.dreads; - } + obj_ncombat.player_forces += self.men + self.veh + self.dreads; + obj_ncombat.player_max += self.men + self.veh + self.dreads; //TODO centralise a method for moving units between columns /*if (men<=4) and (veh=0) and (dreads=0){// Squish leftt @@ -20,7 +16,7 @@ try { if ((obj_ncombat.red_thirst >= 2) && (obj_ncombat.battle_over == 0)) { if (men > 0) { - var raar = 0, miss = "", r_lost = 0; + var miss = "", r_lost = 0; for (var raar; raar < (men + dreads); raar++) { r_roll = floor(random(1000)) + 1; @@ -43,9 +39,7 @@ try { if ((marine_dead[raar] == 0) && (marine_type[raar] != "Death Company") && (marine_type[raar] != obj_ini.role[100][eROLE.CHAPTERMASTER]) && (r_roll <= 4)) { r_lost += 1; marine_type[raar] = "Death Company"; - //marine_attack[raar]+=1; marine_defense[raar] = 0.75; - //marine_ranged[raar]=0.75; obj_ncombat.red_thirst += 1; if (r_lost == 1) { miss += "Battle Brother " + string(obj_ini.name[marine_co[raar]][marine_id[raar]]) + ", "; @@ -63,13 +57,10 @@ try { miss = string_delete(miss, woo - 1, 2); // remove last if (string_count(", ", miss) == 1) { - /*var woo;woo=string_rpos(", ",miss); - miss=string_insert(" and",miss,woo+1);*/ - miss = string_replace(miss, ", ", " and "); } if (string_count(", ", miss) > 1) { - var woo = string_rpos(", ", miss); + woo = string_rpos(", ", miss); miss = string_delete(miss, woo - 1, 3); if (r_lost >= 3) { @@ -109,13 +100,9 @@ try { var neares = instance_nearest(x + 10, y, obj_enunit); if ((neares.men == 0) && (neares.veh > 0)) { - var norun; - norun = 0; + var norun = 0; - var i; - i = 0; - repeat (20) { - i += 1; + for (var i = 1; i <= 20; i++) { if (apa[i] >= 30) { norun = 1; } @@ -136,9 +123,6 @@ try { } } } - - /* */ - /* */ } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); } diff --git a/objects/obj_pnunit/Alarm_6.gml b/objects/obj_pnunit/Alarm_6.gml index a318f8dafa..a9a58d7f4f 100644 --- a/objects/obj_pnunit/Alarm_6.gml +++ b/objects/obj_pnunit/Alarm_6.gml @@ -6,19 +6,16 @@ // Remove from the controller // Remove from any planetary bodies -// show_message("pnunit alarm 6"); - -var i = -1, unit; for (var i = 0; i < array_length(unit_struct); i++) { if ((marine_dead[i] > 0) && (marine_type[i] != "") && (ally[i] == false)) { - unit = unit_struct[i]; + var unit = unit_struct[i]; if (!is_struct(unit)) { continue; } if (unit.name() == "") { continue; } - man_size = unit.get_unit_size(); + var man_size = unit.get_unit_size(); if (unit.planet_location > 0) { obj_ncombat.world_size += man_size; @@ -32,19 +29,9 @@ for (var i = 0; i < array_length(unit_struct); i++) { } for (var i = 0; i < array_length(veh_type); i++) { - // if (veh_type[i]="Predator") or (veh_type[i]="Land Raider") then show_message(string(veh_type[i])+" ("+string(veh_co[i])+"."+string(veh_id[i])+")#HP: "+string(veh_hp[i])+"#Dead: "+string(veh_dead[i])+""); - if ((veh_dead[i] > 0) && (veh_type[i] != "") && (veh_ally[i] == false)) { var man_size = scr_unit_size("", veh_type[i], true); - /* - if (veh_type[i]="Rhino") then man_size+=10; - if (veh_type[i]="Predator") then man_size+=10; - if (veh_type[i]="Land Raider") then man_size+=20; - if (veh_type[i]="Bike") then man_size+=2; - if (veh_type[i]="Land Speeder") then man_size+=6; - if (veh_type[i]="Whirlwind") then man_size+=10;*/ - if (obj_ini.veh_wid[veh_co[i]][veh_id[i]] > -1) { obj_ncombat.world_size += man_size; } @@ -52,15 +39,9 @@ for (var i = 0; i < array_length(veh_type); i++) { obj_ini.ship_carrying[obj_ini.veh_lid[veh_co[i]][veh_id[i]]] -= man_size; } - // show_message(string(veh_type[i])+" ("+string(veh_co[i])+"."+string(veh_id[i])+") dead"); - - // destroy_vehicle(veh_co[i], veh_id[i]); } if ((veh_dead[i] == 0) && (veh_type[i] != "") && (veh_ally[i] == false)) { obj_ini.veh_hp[veh_co[i]][veh_id[i]] = veh_hp[i] / veh_hp_multiplier[i]; } } - -/* */ -/* */ diff --git a/objects/obj_pnunit/KeyPress_73.gml b/objects/obj_pnunit/KeyPress_73.gml index 78b64c7e29..e69de29bb2 100644 --- a/objects/obj_pnunit/KeyPress_73.gml +++ b/objects/obj_pnunit/KeyPress_73.gml @@ -1,34 +0,0 @@ -/*show_message("X: "+string(x)+", Y: "+string(y)+" -"+string(dudes_num[1])+"x "+string(dudes[1])+" "+string(dudes_vehicle[1])+" -"+string(dudes_num[2])+"x "+string(dudes[2])+" "+string(dudes_vehicle[2])+" -"+string(dudes_num[3])+"x "+string(dudes[3])+" "+string(dudes_vehicle[3])+" -"+string(dudes_num[4])+"x "+string(dudes[4])+" "+string(dudes_vehicle[4])+" -"+string(dudes_num[5])+"x "+string(dudes[5])+" "+string(dudes_vehicle[5])+" -"+string(dudes_num[6])+"x "+string(dudes[6])+" "+string(dudes_vehicle[6])+" -"+string(dudes_num[7])+"x "+string(dudes[7])+" "+string(dudes_vehicle[7])+" -"+string(dudes_num[8])+"x "+string(dudes[8])+" "+string(dudes_vehicle[8])+" -"+string(dudes_num[9])+"x "+string(dudes[9])+" "+string(dudes_vehicle[9])+" -"+string(dudes_num[10])+"x "+string(dudes[10])+" "+string(dudes_vehicle[10]));*/ - -/* - -show_message("Engaged "+string(engaged)+" -"+string(wep_num[1])+"x "+string(wep[1])+": ATT"+string(att[1])+" ARP"+string(apa[1])+" splash:"+string(splash[1])+" -"+string(wep_num[2])+"x "+string(wep[2])+": ATT"+string(att[2])+" ARP"+string(apa[2])+" splash:"+string(splash[2])+" -"+string(wep_num[3])+"x "+string(wep[3])+": ATT"+string(att[3])+" ARP"+string(apa[3])+" splash:"+string(splash[3])+" -"+string(wep_num[4])+"x "+string(wep[4])+": ATT"+string(att[4])+" ARP"+string(apa[4])+" splash:"+string(splash[4])+" -"+string(wep_num[5])+"x "+string(wep[5])+": ATT"+string(att[5])+" ARP"+string(apa[5])+" splash:"+string(splash[5])+" -"+string(wep_num[6])+"x "+string(wep[6])+": ATT"+string(att[6])+" ARP"+string(apa[6])+" splash:"+string(splash[6])+" -"+string(wep_num[7])+"x "+string(wep[7])+": ATT"+string(att[7])+" ARP"+string(apa[7])+" splash:"+string(splash[7])+" -"+string(wep_num[8])+"x "+string(wep[8])+": ATT"+string(att[8])+" ARP"+string(apa[8])+" splash:"+string(splash[8])+" -"+string(wep_num[9])+"x "+string(wep[9])+": ATT"+string(att[9])+" ARP"+string(apa[9])+" splash:"+string(splash[9])+" -"+string(wep_num[10])+"x "+string(wep[10])+": ATT"+string(att[10])+" ARP"+string(apa[10])+" splash:"+string(splash[10])+" -"+string(wep_num[11])+"x "+string(wep[11])+": ATT"+string(att[11])+" ARP"+string(apa[11])+" splash:"+string(splash[11])+" -"+string(wep_num[12])+"x "+string(wep[12])+": ATT"+string(att[12])+" ARP"+string(apa[12])+" splash:"+string(splash[12])+" -"+string(wep_num[13])+"x "+string(wep[13])+": ATT"+string(att[13])+" ARP"+string(apa[13])+" splash:"+string(splash[13])+" -"+string(wep_num[14])+"x "+string(wep[14])+": ATT"+string(att[14])+" ARP"+string(apa[14])+" splash:"+string(splash[14])+" -"+string(wep_num[15])+"x "+string(wep[15])+": ATT"+string(att[15])+" ARP"+string(apa[15])+" splash:"+string(splash[15])); -*/ - -/* */ -/* */ diff --git a/objects/obj_pnunit/KeyPress_84.gml b/objects/obj_pnunit/KeyPress_84.gml index a4b90bee18..e69de29bb2 100644 --- a/objects/obj_pnunit/KeyPress_84.gml +++ b/objects/obj_pnunit/KeyPress_84.gml @@ -1,22 +0,0 @@ -/*instance_activate_object(obj_pnunit); - -show_message("Engaged "+string(engaged)+" -"+string(dudes_num[1])+"x "+string(dudes[1])+" "+string(dudes_vehicle[1])+" -"+string(dudes_num[2])+"x "+string(dudes[2])+" "+string(dudes_vehicle[2])+" -"+string(dudes_num[3])+"x "+string(dudes[3])+" "+string(dudes_vehicle[3])+" -"+string(dudes_num[4])+"x "+string(dudes[4])+" "+string(dudes_vehicle[4])+" -"+string(dudes_num[5])+"x "+string(dudes[5])+" "+string(dudes_vehicle[5])+" -"+string(dudes_num[6])+"x "+string(dudes[6])+" "+string(dudes_vehicle[6])+" -"+string(dudes_num[7])+"x "+string(dudes[7])+" "+string(dudes_vehicle[7])+" -"+string(dudes_num[8])+"x "+string(dudes[8])+" "+string(dudes_vehicle[8])+" -"+string(dudes_num[9])+"x "+string(dudes[9])+" "+string(dudes_vehicle[9])+" -"+string(dudes_num[10])+"x "+string(dudes[10])+" "+string(dudes_vehicle[10])+" -"+string(dudes_num[11])+"x "+string(dudes[11])+" "+string(dudes_vehicle[11])+" -"+string(dudes_num[12])+"x "+string(dudes[12])+" "+string(dudes_vehicle[12])+" -"+string(dudes_num[13])+"x "+string(dudes[13])+" "+string(dudes_vehicle[13])+" -"+string(dudes_num[14])+"x "+string(dudes[14])+" "+string(dudes_vehicle[14])+" -"+string(dudes_num[15])+"x "+string(dudes[15])+" "+string(dudes_vehicle[15])+" -"+string(dudes_num[16])+"x "+string(dudes[16])+" "+string(dudes_vehicle[16]));*/ - -/* */ -/* */ diff --git a/objects/obj_pnunit/obj_pnunit.yy b/objects/obj_pnunit/obj_pnunit.yy index 89cc44022f..1296b63952 100644 --- a/objects/obj_pnunit/obj_pnunit.yy +++ b/objects/obj_pnunit/obj_pnunit.yy @@ -35,8 +35,8 @@ "physicsSensor":false, "physicsShape":0, "physicsShapePoints":[ - {"x":0,"y":0,}, - {"x":5,"y":5,}, + {"x":0.0,"y":0.0,}, + {"x":5.0,"y":5.0,}, ], "physicsStartAwake":true, "properties":[], diff --git a/objects/obj_popup/Create_0.gml b/objects/obj_popup/Create_0.gml index ce80f45a21..f93e1217f3 100644 --- a/objects/obj_popup/Create_0.gml +++ b/objects/obj_popup/Create_0.gml @@ -120,20 +120,15 @@ company_promote_data = [ } //10th company ]; -for (var i = 0; i <= 10; i++) { - i += 1; - role_name[i] = ""; - role_exp[i] = 0; -} +role_name = array_create(11, ""); +role_exp = array_create(11, 0); // TODO: connect this logic with the other_manage_data() to reduce verboseness; get_unit_promotion_options = function() { var spec = 0; - for (var i = 0; i <= 11; i++) { - role_name[i] = ""; - role_exp[i] = 0; - } - i = 0; + role_name = array_create(11, ""); + role_exp = array_create(11, 0); + var i = 0; // this area does the required exp for roles per company if (unit_role == obj_ini.role[100][16]) { //techmarine diff --git a/objects/obj_popup/Destroy_0.gml b/objects/obj_popup/Destroy_0.gml index dd8b57bbe0..5f061ba49b 100644 --- a/objects/obj_popup/Destroy_0.gml +++ b/objects/obj_popup/Destroy_0.gml @@ -40,7 +40,7 @@ if (instance_exists(obj_controller)) { instance_create(0, 0, obj_ncombat); obj_ncombat.battle_special = "cs_meeting_battle10"; - var meeting_star = "none"; + var meeting_star = noone; var meeting_planet; with (obj_star) { var meeting = has_problem_star("meeting"); @@ -54,7 +54,7 @@ if (instance_exists(obj_controller)) { } } } - if (meeting_star == "none") { + if (meeting_star == noone) { instance_activate_object(obj_star); with (obj_star) { if (string_count(name, scr_master_loc()) > 0) { @@ -63,7 +63,7 @@ if (instance_exists(obj_controller)) { } } } - if (meeting_star != "none") { + if (meeting_star != noone) { obj_ncombat.battle_object = meeting_star; obj_ncombat.battle_loc = meeting_star.name; obj_ncombat.battle_id = meeting_planet; diff --git a/objects/obj_popup/Keyboard_13.gml b/objects/obj_popup/Keyboard_13.gml index 0f7c77addc..3b4ce730e4 100644 --- a/objects/obj_popup/Keyboard_13.gml +++ b/objects/obj_popup/Keyboard_13.gml @@ -15,7 +15,7 @@ if (cooldown > 0) { exit; } - if (array_length(options == 0) && type < 5) { + if (array_length(options) == 0 && type < 5) { obj_controller.cooldown = 10; if ((number != 0) && (obj_controller.complex_event == false)) { if (instance_exists(obj_turn_end)) { diff --git a/objects/obj_popup/Step_0.gml b/objects/obj_popup/Step_0.gml index ec49edb825..e125134993 100644 --- a/objects/obj_popup/Step_0.gml +++ b/objects/obj_popup/Step_0.gml @@ -65,7 +65,7 @@ try { obj_controller.disposition[10] -= 10; text = "The heretic is killed in a most violent fashion. With a lack of go-between the meeting cannot proceed."; reset_popup_options(); - mission = ""; // image=""; + mission = ""; if (obj_controller.blood_debt == 1) { obj_controller.penitent_current += 1; obj_controller.penitent_turn = 0; @@ -199,8 +199,6 @@ try { if ((press == 0) && array_length(options) || ((demand == 1) && (mission != "") && (string_count("Inquisition", title) > 0)) || ((demand == 1) && (title == "Inquisition Recon"))) { if (title == "Inquisition Recon") { - var mission_star, onceh; - onceh = 0; obj_controller.temp[200] = string(loc); var mission_star = find_star_by_name(obj_controller.temp[200]); if (add_new_problem(planet, "recon", estimate, mission_star)) { @@ -215,12 +213,10 @@ try { if ((mission != "") && (title == "Inquisition Mission")) { obj_controller.temp[200] = string(loc); - var mission_star, onceh; - mission_star = 0; - onceh = 0; + var onceh = 0; var mission_star = find_star_by_name(obj_controller.temp[200]); var mission_is_go = false; - if (mission_star != "none" && planet > 0) { + if (mission_star != noone && planet > 0) { var _estimate = estimate; var _planet = planet; var _mission = mission; diff --git a/objects/obj_saveload/Alarm_0.gml b/objects/obj_saveload/Alarm_0.gml index 8a8a51ece7..ed0352779e 100644 --- a/objects/obj_saveload/Alarm_0.gml +++ b/objects/obj_saveload/Alarm_0.gml @@ -63,7 +63,6 @@ if (load_part == 6) { txt = "Praise be to the Emperor"; } with (obj_controller) { - // LOGGER.debug($"load section 5"); scr_load(5, global.load); } trickle = 2; @@ -76,7 +75,6 @@ if (load_part == 5) { } with (obj_controller) { - // LOGGER.debug($"load section 4"); scr_load(4, global.load); } trickle = 2; @@ -89,7 +87,6 @@ if (load_part == 4) { txt = "Donning Power Armour"; } with (obj_controller) { - // LOGGER.debug($"load section 3"); scr_load(3, global.load); } trickle = 2; @@ -102,7 +99,6 @@ if (load_part == 3) { txt = "Rousing the Machine Spirit"; } with (obj_controller) { - // LOGGER.debug($"load section 2"); scr_load(2, global.load); } trickle = 2; @@ -115,7 +111,6 @@ if (load_part == 2) { txt = "Turtle Waxing Scalp"; } with (obj_controller) { - // LOGGER.debug($"load section 1"); scr_load(1, global.load); } trickle = 2; diff --git a/objects/obj_saveload/Create_0.gml b/objects/obj_saveload/Create_0.gml index ec94f28527..436d719df9 100644 --- a/objects/obj_saveload/Create_0.gml +++ b/objects/obj_saveload/Create_0.gml @@ -53,9 +53,7 @@ save_icon = array_create(201, -1); saves = 0; -var i = 0; - -repeat (100) { +for (var i = 0; i < 100; i++) { if (file_exists(string(PATH_SAVE_FILES, i))) { save[saves] = i; saves += 1; @@ -66,7 +64,6 @@ repeat (100) { if (file_exists(string(PATH_SAVE_FILES, i + 1)) && (max_ini > 0)) { max_ini = 0; } - i += 1; } first_open = saves; diff --git a/objects/obj_saveload/Draw_64.gml b/objects/obj_saveload/Draw_64.gml index 12ab3aee61..2d86e926db 100644 --- a/objects/obj_saveload/Draw_64.gml +++ b/objects/obj_saveload/Draw_64.gml @@ -6,10 +6,7 @@ if (!hide) { if (save_part + load_part > 0) { draw_set_color(0); - // - // draw_sprite(spr_load_splash,splash,0+0,0+0); scr_image("loading", splash, 0, 0, 1600, 900); - // draw_sprite(spr_loadbar_empty, 0, 1047, 875); draw_sprite(spr_loadbar, 0, 1047, 875); @@ -85,13 +82,12 @@ if (!hide) { var _chapter_icon = scr_load_chapter_icon(save_icon[save[slot_index]]); var _icon_size = 94; draw_sprite_stretched(_chapter_icon, 0, slot_left + 147 - (_icon_size / 2), slot_top + 28, _icon_size, _icon_size); - var ohboy, result, tsec, tmin, thour, tday; - ohboy = save_time[save[slot_index]]; - result = ""; - tsec = 0; - tmin = 0; - thour = 0; - tday = 0; + var ohboy = save_time[save[slot_index]]; + var result = ""; + var tsec = 0; + var tmin = 0; + var thour = 0; + var tday = 0; if (ohboy > 0) { tday = floor(ohboy / 86400); if (tday >= 1) { @@ -164,8 +160,7 @@ if (!hide) { draw_set_alpha(1); if (mouse_button_clicked(,, true) && !instance_exists(obj_popup)) { // Clear - var com; - com = instance_create_depth(0, 0, -200010, obj_popup); + var com = instance_create_depth(0, 0, -200010, obj_popup); com.image = "fuklaw"; com.title = "Delete Save Game?"; com.text = "Are you sure you wish to delete Save " + string(save[slot_index]) + "- " + string(save_chapter[save[slot_index]]) + "?"; @@ -222,8 +217,6 @@ if (!hide) { obj_cursor.image_alpha = 0; splash = choose(0, 1, 2, 3, 4); - // show_message("loading 'save"+string(save[slot_index])+".json'"); - if (instance_exists(obj_main_menu)) { with (obj_main_menu) { instance_destroy(); @@ -316,7 +309,5 @@ if (!hide) { slot_index += 1; slot_top += 158; } - - // 32,166 } } diff --git a/objects/obj_star/Alarm_1.gml b/objects/obj_star/Alarm_1.gml index 0e57d05e7f..abfec6e0b7 100644 --- a/objects/obj_star/Alarm_1.gml +++ b/objects/obj_star/Alarm_1.gml @@ -346,7 +346,7 @@ for (var i = 1; i <= planets; i++) { p_owner[i] = 5; p_first[i] = 5; p_sisters[i] = 4; - adjust_influence(eFACTION.ECCLESIARCHY, (p_sisters[i] * 10) - irandom(5), i); + adjust_influence(eFACTION.ECCLESIARCHY, (p_sisters[i] * 10) - irandom(5), i, self); } // if (p_owner[i]=3) or (p_owner[i]=5){p_feature[i]="Artifact|";}Testing ; 137 } @@ -362,10 +362,9 @@ if ((name == "Kim Jong") && (owner == eFACTION.CHAOS)) { obj_controller.alarm[3] = 1; -var i = choose(0, 1); -if ((i == 1) && (planets > 0)) { +if ((choose(0, 1) == 1) && (planets > 0)) { var nostart = false, aa = 0; - i = floor(random(planets)) + 1; + var _ran_num = floor(random(planets)) + 1; if (instance_exists(obj_p_fleet)) { aa = instance_nearest(x, y, obj_p_fleet); @@ -377,10 +376,8 @@ if ((i == 1) && (planets > 0)) { nostart = true; } - if ((array_length(p_feature[i]) == 0) && (p_owner[i] != 1) && nostart) { + if ((array_length(p_feature[_ran_num]) == 0) && (p_owner[_ran_num] != 1) && nostart) { var ranb = 0; - // if (ranb=1) and (p_owner[i]!=1) and (p_owner[i]!=2) and (p_owner[i]!=3) then ranb=floor(random(4))+2; - // var goo = 0; if (goo == 0) { for (var j = 0; j < 10; j++) { @@ -402,46 +399,46 @@ if ((i == 1) && (planets > 0)) { if (goo == 0) { switch (ranb) { case 1: - array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.SORORITAS_CATHEDRAL)); - if (p_heresy[i] > 10) { - p_heresy[i] -= 10; + array_push(p_feature[_ran_num], new NewPlanetFeature(eP_FEATURES.SORORITAS_CATHEDRAL)); + if (p_heresy[_ran_num] > 10) { + p_heresy[_ran_num] -= 10; } - p_sisters[i] = choose(2, 2, 3); - adjust_influence(eFACTION.ECCLESIARCHY, (p_sisters[i] * 10) - irandom(3), i); + p_sisters[_ran_num] = choose(2, 2, 3); + adjust_influence(eFACTION.ECCLESIARCHY, (p_sisters[_ran_num] * 10) - irandom(3), _ran_num, self); goo = 1; break; case 2: - if ((p_type[i] != "Hive") && (p_type[i] != "Lava") && (goo == 0)) { - array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.NECRON_TOMB)); + if ((p_type[_ran_num] != "Hive") && (p_type[_ran_num] != "Lava") && (goo == 0)) { + array_push(p_feature[_ran_num], new NewPlanetFeature(eP_FEATURES.NECRON_TOMB)); goo = 1; } break; case 3: - array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.ARTIFACT)); + array_push(p_feature[_ran_num], new NewPlanetFeature(eP_FEATURES.ARTIFACT)); goo = 1; break; case 4: - array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.STC_FRAGMENT)); + array_push(p_feature[_ran_num], new NewPlanetFeature(eP_FEATURES.STC_FRAGMENT)); goo = 1; break; case 5: - if ((p_type[i] != "Ice") && (p_type[i] != "Dead") && (p_type[i] != "Feudal")) { + if ((p_type[_ran_num] != "Ice") && (p_type[_ran_num] != "Dead") && (p_type[_ran_num] != "Feudal")) { goo = 1; - array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.ANCIENT_RUINS)); + array_push(p_feature[_ran_num], new NewPlanetFeature(eP_FEATURES.ANCIENT_RUINS)); } break; //alternative spawn for necron tomb probably needs merging with other method case 6: - if ((p_type[i] == "Ice") || (p_type[i] == "Dead")) { - array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.NECRON_TOMB)); + if ((p_type[_ran_num] == "Ice") || (p_type[_ran_num] == "Dead")) { + array_push(p_feature[_ran_num], new NewPlanetFeature(eP_FEATURES.NECRON_TOMB)); goo = 1; } break; case 7: - if ((p_type[i] == "Dead") || (p_type[i] == "Desert")) { + if ((p_type[_ran_num] == "Dead") || (p_type[_ran_num] == "Desert")) { var randum = floor(random(100)) + 1; if (randum <= 25) { - array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.CAVE_NETWORK)); + array_push(p_feature[_ran_num], new NewPlanetFeature(eP_FEATURES.CAVE_NETWORK)); goo = 1; } } @@ -454,76 +451,25 @@ if ((i == 1) && (planets > 0)) { } } -var hyu = 0; +var hyu = false; for (var i = 1; i <= 4; i++) { if (p_tyranids[i] >= 5) { p_guardsmen[i] = 0; p_pdf[i] = 0; p_population[i] = 0; - hyu += 1; + hyu = true; p_owner[i] = 9; } if ((p_first[i] <= 5) && (dispo[i] > -5000)) { dispo[i] = -20; } } -if ((hyu == 0) && (owner == eFACTION.TYRANIDS)) { +if ((!hyu) && (owner == eFACTION.TYRANIDS)) { owner = eFACTION.IMPERIUM; } scr_star_ownership(false); -if (obj_controller.is_test_map == true) { - /*if (p_owner[1]=3) then p_feature[1]="STC Fragment|"; - if (p_owner[2]=3) then p_feature[2]="STC Fragment|"; - if (p_owner[3]=3) then p_feature[3]="STC Fragment|"; - - - // Testing new guardsmen - p_guardsmen[1]=5000000; - p_tyranids[1]=4; - - p_guardsmen[2]=500000; - p_tyranids[2]=3; - - p_guardsmen[3]=100000; - p_tyranids[3]=2; - - p_orks[1]=0;p_orks[2]=0;p_orks[3]=0;*/ -} - -// if (obj_controller.is_test_map=true) and (p_owner[2]=1){ - -if (p_owner[2] == 1) { - /* - p_guardsmen[2]=10000000; - p_pdf[2]=0; - obj_controller.faction_status[eFACTION.IMPERIUM]="War"; - */ - - // p_type[1]="Dead"; - // p_feature[2]=""; - - // p_orks[2]=3; - // p_feature[2]="Starship!0!|"; - - /*repeat(4){ - var fleet;fleet=instance_create(x+(floor(random_range(100,200))*choose(1,-1)),y+(floor(random_range(100,200))*choose(1,-1)),obj_en_fleet); - fleet.owner = eFACTION.CHAOS;fleet.sprite_index=spr_fleet_chaos;fleet.orbiting=0; - fleet.action_x=x;fleet.action_y=y;fleet.alarm[4]=1; - - fleet.capital_number=0; - fleet.frigate_number=1; - fleet.escort_number=2; - - // Create ships here - fleet.image_speed=0; - var ii;ii=0;ii+=capital-1;ii+=round((frigate/2));ii+=round((escort/4)); - if (ii<=1) and (capital+frigate+escort>0) then ii=1; - fleet.image_index=ii; - }*/ -} - if ((obj_controller.is_test_map != true) && (p_owner[2] != 1)) { for (var i = 1; i <= 4; i++) { p_guardsmen[i] = 0; diff --git a/objects/obj_star/Alarm_3.gml b/objects/obj_star/Alarm_3.gml index b9e503f956..5ab629e7d6 100644 --- a/objects/obj_star/Alarm_3.gml +++ b/objects/obj_star/Alarm_3.gml @@ -39,9 +39,9 @@ try { if (!struct_exists(_data, "system")) { _data.system = id; } - if (_data.system != "none") { + if (_data.system != noone) { if (struct_exists(_data, "feature")) { - if (_data.feature != " none") { + if (_data.feature != "none") { if (is_struct(_data.feature)) { if (struct_exists(_data.feature, "f_type")) { if (_data.feature.f_type != "none") { diff --git a/objects/obj_star/Create_0.gml b/objects/obj_star/Create_0.gml index 92aea029ac..73f19bbdef 100644 --- a/objects/obj_star/Create_0.gml +++ b/objects/obj_star/Create_0.gml @@ -1,5 +1,5 @@ // Creates all variables, sets up default variables for different planets and if there is a fleet orbiting a system/planet -craftworld = 0; // orbit_angle=0;orbit_radius=0; +craftworld = 0; space_hulk = 0; old_x = 0; old_y = 0; @@ -10,9 +10,8 @@ if ((((x >= (room_width - 150)) && (y <= 450)) || (y < 100)) && (global.load == } scale = 1; -var run = 0; name = ""; -star = ""; +star = noone; planets = 0; owner = eFACTION.IMPERIUM; image_speed = 0; @@ -145,8 +144,6 @@ var _array_size = 23; present_fleet = array_create(_array_size, 0); vision = 1; -// present_fleets=0; -// tau_fleets=0; ai_a = -1; ai_b = -1; @@ -232,8 +229,7 @@ function deserialize(save_data) { // Automatic var setting var all_names = struct_get_names(save_data); - var _len = array_length(all_names); - for (var i = 0; i < _len; i++) { + for (var i = 0; i < array_length(all_names); i++) { var var_name = all_names[i]; if (array_contains(exclusions, var_name)) { continue; @@ -250,8 +246,7 @@ function deserialize(save_data) { var _temp_features = false; if (struct_exists(save_data, "planet_data")) { var planet_arr = save_data.planet_data; - var _len = array_length(planet_arr); - for (var p = 1; p < _len; p++) { + for (var p = 1; p < array_length(planet_arr); p++) { var planet = planet_arr[p]; var var_names = struct_get_names(planet); for (var v = 0; v < array_length(var_names); v++) { @@ -274,12 +269,7 @@ function deserialize(save_data) { continue; } var val = planet[$ var_name]; - // var_name = "p_type" - // planet = {"p_type":"hive"}; - // val = planet[$var_name] = "hive" - self[$ var_name][p] = val; - // variable_struct_set(self, var_name, planet[$var_name]); } } } diff --git a/objects/obj_star_select/Alarm_0.gml b/objects/obj_star_select/Alarm_0.gml index 9799664c59..f334b62e23 100644 --- a/objects/obj_star_select/Alarm_0.gml +++ b/objects/obj_star_select/Alarm_0.gml @@ -1,43 +1,15 @@ -/*if (instance_exists(target)){ - if (target.craftworld=1) or (target.space_hulk=1){ - // 135 ; - obj_controller.selecting_planet=1; - - if (instance_exists(obj_p_fleet)){ - var targ_targ;targ_targ=instance_nearest(target.x+24,target.y-24,obj_p_fleet); - - if (instance_exists(targ_targ)){ - if (targ_targ.action="") and (point_distance(target.x+24,target.y-24,targ_targ.x,targ_targ.y)<=40){ - - // if (target.p_owner[obj_controller.selecting_planet]>5){ - if (button1!=""){button1="Raid";if (targ_targ.capital_number>0) or (targ_targ.frigate_number>0) then button2="Bombard";} - if (button1=""){button2="Raid";if (targ_targ.capital_number>0) or (targ_targ.frigate_number>0) then button3="Bombard";} - // } - } - } - } - } -}*/ - if (loading == 0) { exit; } // check for the right star - -var xb, yb, good, tiber; -xb = 0; -yb = 0; -good = 0; -tiber = 0; - with (obj_star) { if (name == obj_star_select.loading_name) { instance_create(x, y, obj_temp2); } } if (instance_exists(obj_temp2)) { - tiber = instance_nearest(obj_temp2.x, obj_temp2.y, obj_star); + var tiber = instance_nearest(obj_temp2.x, obj_temp2.y, obj_star); target = tiber; } with (obj_temp2) { @@ -45,6 +17,3 @@ with (obj_temp2) { } instance_activate_object(obj_star); - -/* */ -/* */ diff --git a/objects/obj_star_select/Alarm_1.gml b/objects/obj_star_select/Alarm_1.gml index 9c1fc9fafe..7609ee3d93 100644 --- a/objects/obj_star_select/Alarm_1.gml +++ b/objects/obj_star_select/Alarm_1.gml @@ -8,18 +8,10 @@ tau_fleet = target.present_fleet[8]; tyranid_fleet = target.present_fleet[9]; heretic_fleet = target.present_fleet[10]; -en_fleet[0] = 0; -var i; -i = -1; -repeat (15) { - i += 1; - en_fleet[i] = 0; -} +en_fleet = array_create(15, 0); if ((player_fleet > 0) && (imperial_fleet + mechanicus_fleet + inquisitor_fleet + eldar_fleet + ork_fleet + tau_fleet + heretic_fleet > 0)) { - var open; - open = 1; - i = -1; + var open = 1; if (imperial_fleet > 0) { en_fleet[open] = 2; diff --git a/objects/obj_star_select/Create_0.gml b/objects/obj_star_select/Create_0.gml index a9499ca01a..3a90a26f6c 100644 --- a/objects/obj_star_select/Create_0.gml +++ b/objects/obj_star_select/Create_0.gml @@ -16,13 +16,11 @@ has_player_forces = array_sum(target.p_player) > 0; manage_units_button = new UnitButtonObject({x1: 115, y1: 200, style: "pixel", label: "Manage Units"}); -//if (global.cheat_debug){ debug_button = new UnitButtonObject({x1: 36, y1: 185, style: "pixel", label: "Debug"}); debug_options = new RadioSet([{str1: "Edit Forces"}, {str1: "Add Problem"}, {str1: "Add Feature"}], "Debug options", {x1: 36, y1: 129, max_width: 300}); debug_slate = new DataSlate({style: "plain", XX: 36, YY: 100, set_width: true, width: 310, height: 900}); -//} torpedo = scr_item_count("Cyclonic Torpedo"); @@ -122,13 +120,7 @@ tau_fleet = 0; tyranid_fleet = 0; heretic_fleet = 0; -en_fleet[0] = 0; -var i; -i = -1; -repeat (15) { - i += 1; - en_fleet[i] = 0; -} +en_fleet = array_create(15, 0); if (obj_controller.menu == 0) { alarm[1] = 1; diff --git a/objects/obj_star_select/Draw_64.gml b/objects/obj_star_select/Draw_64.gml index 92b0e3f5de..0abf773016 100644 --- a/objects/obj_star_select/Draw_64.gml +++ b/objects/obj_star_select/Draw_64.gml @@ -19,16 +19,7 @@ draw_set_valign(fa_top); draw_set_color(0); try { - var temp1 = 0; - var xx = 0; - var yy = 0; if (loading == 1) { - xx = xx; - yy = yy; - } else if (loading == 1) { - var temp1, dist; - dist = 999; - obj_controller.selecting_planet = 0; button1 = ""; button2 = ""; @@ -48,11 +39,10 @@ try { var click_accepted = (!obj_controller.menu) && (!obj_controller.zoomed) && (!instance_exists(obj_bomb_select)) && (!instance_exists(obj_drop_select)); if (click_accepted && (!debug || !debug_slate.entered())) { if (mouse_button_clicked(, 0)) { - var closes = 0, sta1 = 0, sta2 = 0; var mouse_consts = return_mouse_consts(); - sta1 = instance_nearest(mouse_consts[0], mouse_consts[1], obj_star); - sta2 = point_distance(mouse_consts[0], mouse_consts[1], sta1.x, sta1.y); - closes = true; + var sta1 = instance_nearest(mouse_consts[0], mouse_consts[1], obj_star); + var sta2 = point_distance(mouse_consts[0], mouse_consts[1], sta1.x, sta1.y); + var closes = true; if (sta2 > 15) { if (scr_hit(27, 165, 300, 165 + 294)) { closes = false; @@ -70,7 +60,6 @@ try { } } } - var shutter_button; var shutters = [ shutter_1, shutter_2, @@ -78,7 +67,7 @@ try { shutter_4 ]; for (var i = 0; i < 4; i++) { - shutter_button = shutters[i]; + var shutter_button = shutters[i]; if (shutter_button.hit()) { closes = false; break; @@ -164,14 +153,13 @@ try { } // Buttons that are available if (!buttons_selected) { + var is_enemy = false; if ((obj_controller.faction_status[eFACTION.IMPERIUM] != "War" && p_data.current_owner > 5) || (obj_controller.faction_status[eFACTION.IMPERIUM] == "War" && p_data.at_war(0, 1, 1) && p_data.player_disposition <= 50)) { - var is_enemy = true; - } else { - var is_enemy = false; + is_enemy = true; } if (p_data.planet > 0) { - if (target.present_fleet[1] == 0) /* and (target.p_type[obj_controller.selecting_planet]!="Dead")*/ { + if (target.present_fleet[1] == 0) { if (p_data.player_forces > 0) { if (is_enemy) { button1 = "Attack"; @@ -181,7 +169,7 @@ try { } } } - if (target.present_fleet[1] > 0) /* and (target.p_type[obj_controller.selecting_planet]!="Dead")*/ { + if (target.present_fleet[1] > 0) { if (is_enemy) { button1 = "Attack"; button2 = "Raid"; @@ -344,28 +332,31 @@ try { instance_destroy(); } } else if (current_button == "Raid" && instance_nearest(x, y, obj_p_fleet).acted <= 1) { + // feather ignore once GM2064 instance_create_layer(x, y, layer_get_all()[0], obj_drop_select, {p_target: target, planet_number: obj_controller.selecting_planet, sh_target: instance_nearest(x, y, obj_p_fleet), purge: 0}); } else if (current_button == "Attack") { var _allow_attack = true; - var _targ = !target.present_fleet[1] ? -50 : instance_nearest(x, y, obj_p_fleet); + var _targ = !target.present_fleet[1] ? noone : instance_nearest(x, y, obj_p_fleet); if (instance_exists(_targ)) { if (_targ.acted >= 2) { _allow_attack = false; } } if (_allow_attack) { + // feather ignore once GM2064 instance_create_layer(x, y, layer_get_all()[0], obj_drop_select, {p_target: target, planet_number: obj_controller.selecting_planet, attack: true, sh_target: _targ, purge: 0}); } } else if (current_button == "Purge") { var _allow_attack = true; - var _targ = !target.present_fleet[1] ? -50 : instance_nearest(x, y, obj_p_fleet); + var _targ = !target.present_fleet[1] ? noone : instance_nearest(x, y, obj_p_fleet); if (instance_exists(_targ)) { if (_targ.acted >= 2) { _allow_attack = false; } } if (_allow_attack) { - instance_create_layer(x, y, layer_get_all()[0], obj_drop_select, {p_target: target, purge: 1, planet_number: obj_controller.selecting_planet, sh_target: _targ}); + // feather ignore once GM2064 + instance_create_layer(x, y, layer_get_all()[0], obj_drop_select, {p_target: target, planet_number: obj_controller.selecting_planet, sh_target: _targ, purge: 1}); } } else if (current_button == "Bombard") { instance_create(x, y, obj_bomb_select); @@ -407,7 +398,7 @@ try { button4 = ""; } } - // 135 ; popup? + // popup? } } } else if (current_button == "Cyclonic Torpedo") { @@ -423,8 +414,6 @@ try { draw_rectangle(37, 413, 270, 452, 0); draw_set_alpha(1); - /*draw_set_color(CM_GREEN_COLOR);draw_rectangle(40,247,253,273,1);*/ - draw_set_halign(fa_left); draw_set_color(0); @@ -435,12 +424,10 @@ try { draw_set_font(fnt_40k_14b); draw_text(37.5, 413.5, "Select Fleet Combat"); - // x3=46;y3=252; var x3 = 49, y3 = 441; for (var i = 1; i <= 7; i++) { if (en_fleet[i] > 0) { - // draw_sprite_ext(spr_force_icon,en_fleet[i],x3,y3,0.5,0.5,0,c_white,1); scr_image("ui/force", en_fleet[i], x3 - 16, y3 - 16, 32, 32); x3 += 64; } @@ -453,7 +440,3 @@ try { ERROR_HANDLER.handle_exception(_exception); instance_destroy(); } - -/* */ - -/* */ diff --git a/objects/obj_star_select/Mouse_50.gml b/objects/obj_star_select/Mouse_50.gml index 0733d86c25..cd1cffb440 100644 --- a/objects/obj_star_select/Mouse_50.gml +++ b/objects/obj_star_select/Mouse_50.gml @@ -62,16 +62,13 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select)) { purge = 0; if ((player_fleet > 0) && (imperial_fleet + mechanicus_fleet + inquisitor_fleet + eldar_fleet + ork_fleet + tau_fleet + heretic_fleet > 0) && (obj_controller.cooldown <= 0)) { - var i, x3, y3; - i = 0; - // x3=xx+46;y3=yy+252; + var x3, y3; x3 = xx + 49; y3 = yy + 441; var combating = 0; - repeat (7) { - i += 1; + for (var i = 1; i <= 7; i++) { if ((en_fleet[i] > 0) && (mouse_x >= x3 - 24) && (mouse_y >= y3 - 24) && (mouse_x < x3 + 48) && (mouse_y < y3 + 48) && (obj_controller.cooldown <= 0)) { obj_controller.cooldown = 8; combating = en_fleet[i]; @@ -82,7 +79,7 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select)) { if (combating > 0) { obj_controller.combat = combating; - var xx = false, yy = false, good = false, e1 = false, e2 = false, e3 = false; + var e1 = false, e2 = false, e3 = false; var enemy_fleet = array_create(20, 0); var allied_fleet = array_create(20, 0); @@ -93,18 +90,18 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select)) { var afri = array_create(20, 0); var aesc = array_create(20, 0); - good = 1; + var good = true; var p_fleet = get_nearest_player_fleet(x, y, true); obj_controller.temp[1099] = target.name; - good = p_fleet != "none" && instance_exists(target); + good = p_fleet != noone && instance_exists(target); if (good == 1) { // trying to find the star instance_activate_object(obj_star); obj_controller.x = target.x; - obj_controller.y = target.y; // show=current_battle; + obj_controller.y = target.y; strin[1] = string(p_fleet.capital_number); strin[2] = string(p_fleet.frigate_number); @@ -181,13 +178,11 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select)) { instance_deactivate_all(true); instance_activate_object(obj_controller); instance_activate_object(obj_ini); - // instance_activate_object(battle_object[current_battle]); instance_activate_object(p_fleet); instance_activate_object(obj_star); instance_create(0, 0, obj_fleet); obj_fleet.star_name = target.name; - // obj_fleet.enemy[1] = enemy_fleet[1]; obj_fleet.enemy_status[1] = -1; @@ -214,7 +209,6 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select)) { add_fleet_ships_to_combat(p_fleet, obj_fleet); - // instance_deactivate_object(battle_object[current_battle]); instance_deactivate_object(p_fleet); obj_controller.combat = 1; diff --git a/objects/obj_star_select/Step_0.gml b/objects/obj_star_select/Step_0.gml index 6d02e8eb8c..5f0b8b453f 100644 --- a/objects/obj_star_select/Step_0.gml +++ b/objects/obj_star_select/Step_0.gml @@ -7,6 +7,3 @@ if ((obj_controller.popup < 3) && (loading == 0)) { instance_destroy(); } } - -/* */ -/* */ diff --git a/objects/obj_temp_build/Create_0.gml b/objects/obj_temp_build/Create_0.gml index 2b0c1461d1..75d57c24b6 100644 --- a/objects/obj_temp_build/Create_0.gml +++ b/objects/obj_temp_build/Create_0.gml @@ -1,5 +1,5 @@ target = noone; -planet = noone; +planet = (planet > 0) ? planet : 0; lair = false; arsenal = false; diff --git a/objects/obj_turn_end/Alarm_0.gml b/objects/obj_turn_end/Alarm_0.gml index f62d5f1296..805c4fcc84 100644 --- a/objects/obj_turn_end/Alarm_0.gml +++ b/objects/obj_turn_end/Alarm_0.gml @@ -2,28 +2,21 @@ try { instance_activate_object(obj_star); combating = 0; - var i; - - i = 50; - repeat (50) { - i -= 1; - + for (var i = 49; i >= 0; i--) { if ((battles <= i) && (i >= 2)) { - if ((battle[i] != 0) && (battle[i - 1] != 0) && (battle_world[i] == -50) && (battle_world[i - 1] > 0)) { - var tem1, tem2, tem3, tem4, tem5, tem6, tem7; - tem1 = battle[i - 1]; - tem2 = battle_location[i - 1]; - tem3 = battle_world[i - 1]; - tem4 = battle_opponent[i - 1]; - tem5 = battle_object[i - 1]; - tem6 = battle_pobject[i - 1]; - tem7 = battle_special[i - 1]; + if ((battle[i] != 0) && (battle[i - 1] != 0) && (battle_world[i] == noone) && (battle_world[i - 1] > 0)) { + var tem1 = battle[i - 1]; + var tem2 = battle_location[i - 1]; + var tem3 = battle_world[i - 1]; + var tem4 = battle_opponent[i - 1]; + var tem5 = battle_object[i - 1]; + var tem6 = battle_pobject[i - 1]; + var tem7 = battle_special[i - 1]; battle[i - 1] = battle[i]; battle_location[i - 1] = battle_location[i]; battle_world[i - 1] = battle_world[i]; battle_opponent[i - 1] = battle_opponent[i]; - // battle_object[i-1]=battle_object[i]; battle_pobject[i - 1] = battle_pobject[i]; battle_special[i - 1] = battle_special[i]; @@ -43,19 +36,15 @@ try { // Ground battles after if ((battles > 0) && (current_battle <= battles)) { - var ii, xx, yy, good; - ii = 0; - good = 0; - var battle_star = find_star_by_name(battle_location[current_battle]); - if (battle_star != "none") { + if (battle_star != noone) { // trying to find the star obj_controller.x = battle_star.x; obj_controller.y = battle_star.y; show = current_battle; - if (battle_world[current_battle] == -50) { + if (battle_world[current_battle] == noone) { strin[1] = string(round(battle_pobject[current_battle].capital_number)); strin[2] = string(round(battle_pobject[current_battle].frigate_number)); strin[3] = string(round(battle_pobject[current_battle].escort_number)); @@ -66,9 +55,7 @@ try { // pull enemy ships here - var e = 1; - repeat (10) { - e += 1; + for (var e = 2; e <= 11; e++) { if (e == 11) { e = 13; } @@ -87,9 +74,8 @@ try { } } - var l1, l2; - l1 = 0; - l2 = 0; + var l1 = 0; + var l2 = 0; if (obj_controller.faction_status[e] != "War") { repeat (10) { l1 += 1; @@ -135,8 +121,7 @@ try { strin[3] = ""; - var tempy = 0; - tempy = battle_object[current_battle].p_owner[battle_world[current_battle]]; + var tempy = battle_object[current_battle].p_owner[battle_world[current_battle]]; if ((tempy == 1) || (tempy == 2) || (tempy == 3)) { var array_string = [ @@ -187,8 +172,6 @@ try { if (tempy == 6) { strin[4] = "Overwhelming"; } - - // if (battle_opponent[current_battle]=2) then obj_controller.alarm[7]=1; obj_controller.cooldown = 9999; } @@ -211,9 +194,6 @@ try { } alarm[1] = 1; } - - /* */ - /* */ } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); } diff --git a/objects/obj_turn_end/Alarm_1.gml b/objects/obj_turn_end/Alarm_1.gml index 33cc7d7554..ffda7b59e3 100644 --- a/objects/obj_turn_end/Alarm_1.gml +++ b/objects/obj_turn_end/Alarm_1.gml @@ -1,6 +1,7 @@ var _is_audience = false; +var current_audience = noone; if (array_length(audience_stack) > 0) { - var current_audience = audience_stack[0]; + current_audience = audience_stack[0]; _is_audience = true; } @@ -41,14 +42,11 @@ if (_is_audience) { exit; } -// if (current_audience<=audiences) then alarm[1]=5; - if (!_is_audience) { current_popup += 1; if (popup[current_popup] != 0) { - var pip; - pip = instance_create(0, 0, obj_popup); + var pip = instance_create(0, 0, obj_popup); pip.title = popup_type[current_popup]; pip.text = popup_text[current_popup]; pip.image = popup_image[current_popup]; @@ -77,7 +75,6 @@ if (!_is_audience) { explode_script(popup_special[current_popup], "|"); pip.mission = string(explode[0]); pip.loc = string(explode[1]); - // "mech_raider!0!|"+string(you2.name)); "mech_bionics!0!|"+string(you2.name)); } if (string_count("meeting_", popup_special[current_popup]) > 0) { pip.mission = popup_special[current_popup]; @@ -98,25 +95,10 @@ if (!_is_audience) { if (popups_end == 0) { popups_end = 1; } - // obj_controller.x=first_x; - // obj_controller.y=first_y; - // instance_destroy(); } - - // obj_controller.x=first_x; - // obj_controller.y=first_y; - // instance_destroy(); } -// if (current_popup>popups) or (popup[1]=0) then popups_end=1; - if (popups_end == 1) { - /*if (popups=0){ - obj_controller.x=first_x; - obj_controller.y=first_y; - instance_destroy(); - }*/ - obj_controller.x = first_x; obj_controller.y = first_y; @@ -134,9 +116,5 @@ if (popups_end == 1) { millenium += 1; year -= 1000; } - // menu=0; } } - -/* */ -/* */ diff --git a/objects/obj_turn_end/Alarm_4.gml b/objects/obj_turn_end/Alarm_4.gml index 725d0b442a..dc62948b5d 100644 --- a/objects/obj_turn_end/Alarm_4.gml +++ b/objects/obj_turn_end/Alarm_4.gml @@ -1,21 +1,18 @@ -var battle_o; -battle_o = 0; current_battle += 1; combating = 0; instance_activate_object(obj_star); if ((battles > 0) && (current_battle <= battles)) { - var ii = 0, good = 0; var battle_star = find_star_by_name(battle_location[current_battle]); obj_controller.temp[1060] = battle_location[current_battle]; - if (battle_star != "none") { + if (battle_star != noone) { obj_controller.x = battle_star.x; obj_controller.y = battle_star.y; show = current_battle; - if (battle_world[current_battle] == -50) { + if (battle_world[current_battle] == noone) { strin[1] = string(battle_pobject[current_battle].capital_number); strin[2] = string(battle_pobject[current_battle].frigate_number); strin[3] = string(battle_pobject[current_battle].escort_number); @@ -51,9 +48,7 @@ if ((battles > 0) && (current_battle <= battles)) { strin[3] = ""; - var tempy; - tempy = 0; - tempy = battle_object[current_battle].p_owner[battle_world[current_battle]]; + var tempy = battle_object[current_battle].p_owner[battle_world[current_battle]]; if ((tempy == 1) || (tempy == 2) || (tempy == 3)) { if (battle_object[current_battle].p_fortified[battle_world[current_battle]] == 1) { diff --git a/objects/obj_turn_end/Create_0.gml b/objects/obj_turn_end/Create_0.gml index 2dad46637a..06f4ee3521 100644 --- a/objects/obj_turn_end/Create_0.gml +++ b/objects/obj_turn_end/Create_0.gml @@ -2,8 +2,6 @@ instance_deactivate_object(obj_star_select); instance_deactivate_object(obj_drop_select); instance_deactivate_object(obj_bomb_select); -var i; -i = -1; keywords = ""; last_open = 1; @@ -72,16 +70,13 @@ audience_stack = []; alert_alpha[1] = 0.2; alert_char[1] = 1; -i = -1; handle_discovered_governor_assasinations(); if (audiences > 0) { // This is a one-off change all messages to declare war - var i = 0; var war; - repeat (15) { - i += 1; + for (var i = 1; i <= 15; i++) { war[i] = 0; } for (var i = 0; i < array_length(audience_stack); i++) { @@ -98,6 +93,3 @@ if (audiences > 0) { alerts = 0; fast = 0; show = 0; - -/* */ -/* */ diff --git a/objects/obj_turn_end/Draw_0.gml b/objects/obj_turn_end/Draw_0.gml index f35608d78f..bdeb948003 100644 --- a/objects/obj_turn_end/Draw_0.gml +++ b/objects/obj_turn_end/Draw_0.gml @@ -26,7 +26,7 @@ if ((show > 0) && (current_battle <= battles)) { var i = current_battle; draw_sprite(spr_purge_panel, 0, xxx, yyy); - if (battle_world[i] == -50) { + if (battle_world[i] == noone) { scr_image("attacked", 1, xxx + 12, yyy + 54, 254, 174); } if (battle_world[i] > 0) { @@ -44,12 +44,11 @@ if ((show > 0) && (current_battle <= battles)) { if (battle_world[i] > 0) { draw_text_transformed(xxx + 265, yyy + 11, string_hash_to_newline("Forces Attacked! (" + string(battle_location[i]) + " " + scr_roman(battle_world[i]) + ")"), 0.7, 0.7, 0); } - if (battle_world[i] == -50) { + if (battle_world[i] == noone) { draw_text_transformed(xxx + 265, yyy + 11, string_hash_to_newline("Fleet Attacked! (" + string(battle_location[i]) + " System)"), 0.7, 0.7, 0); } scr_image("ui/force", 1, xxx + 378 - 32, yyy + 86 - 32, 64, 64); - // draw_sprite(spr_force_icon,1,xxx+378,yyy+86); draw_set_font(fnt_40k_14); draw_set_halign(fa_left); @@ -83,7 +82,6 @@ if ((show > 0) && (current_battle <= battles)) { draw_set_halign(fa_center); if (enemy_fleet[1] != 0) { - // draw_sprite(spr_force_icon,enemy_fleet[1],xxx+44,yyy+269); scr_image("ui/force", enemy_fleet[1], xxx + 44 - 32, yyy + 269 - 32, 64, 64); var shw; shw = ""; @@ -111,7 +109,6 @@ if ((show > 0) && (current_battle <= battles)) { draw_set_font(fnt_40k_14b); } if (enemy_fleet[2] != 0) { - // draw_sprite(spr_force_icon,enemy_fleet[2],xxx+154,yyy+269); scr_image("ui/force", enemy_fleet[2], xxx + 154 - 32, yyy + 269 - 32, 64, 64); var shw; shw = ""; @@ -139,7 +136,6 @@ if ((show > 0) && (current_battle <= battles)) { draw_set_font(fnt_40k_14b); } if (enemy_fleet[3] != 0) { - // draw_sprite(spr_force_icon,enemy_fleet[3],xxx+264,yyy+269); scr_image("ui/force", enemy_fleet[3], xxx + 264 - 32, yyy + 269 - 32, 64, 64); var shw; shw = ""; @@ -168,7 +164,6 @@ if ((show > 0) && (current_battle <= battles)) { } if (allied_fleet[1] != 0) { - // draw_sprite(spr_force_icon,allied_fleet[1],xxx+374,yyy+269); scr_image("ui/force", allied_fleet[1], xxx + 374 - 32, yyy + 269 - 32, 64, 64); var shw; shw = ""; @@ -196,7 +191,6 @@ if ((show > 0) && (current_battle <= battles)) { draw_set_font(fnt_40k_14b); } if (allied_fleet[2] != 0) { - // draw_sprite(spr_force_icon,allied_fleet[1],xxx+484,yyy+269); scr_image("ui/force", allied_fleet[1], xxx + 484 - 32, yyy + 269 - 32, 64, 64); var shw; shw = ""; @@ -261,7 +255,6 @@ if ((show > 0) && (current_battle <= battles)) { draw_text(xxx + 332, yyy + 237, string_hash_to_newline("Allies:")); draw_set_halign(fa_center); - // draw_sprite(spr_force_icon,battle_opponent[i],xxx+44,yyy+289); scr_image("ui/force", battle_opponent[i], xxx + 44 - 32, yyy + 289 - 32, 64, 64); draw_text_transformed(xxx + 44, yyy + 316, string_hash_to_newline(string(strin[4])), 0.75, 1, 0); draw_set_halign(fa_center); @@ -288,99 +281,3 @@ if ((show > 0) && (current_battle <= battles)) { } } } - -/* - -if (show>0) and (current_battle<=battles){ - var xxx,yyy,i; - xxx=view_xview[0]; - yyy=view_yview[0]; - i=current_battle; - - if (battle_world[i]>0) then draw_sprite(spr_attacked,0,xxx+90,yyy+101); - if (battle_world[i]=-50) then draw_sprite(spr_attacked,1,xxx+90,yyy+101); - - draw_set_font(fnt_info);draw_set_halign(fa_left);draw_set_color(CM_GREEN_COLOR); - draw_text(xxx+103,yyy+115,string(i)+"/"+string(battles)); - - draw_set_halign(fa_center); - draw_set_font(fnt_fancy); - - if (battle_world[i]>0) then draw_text_transformed(xxx+313,yyy+111,"Forces Attacked!",1.5,1.5,0); - if (battle_world[i]=-50) then draw_text_transformed(xxx+313,yyy+111,"Fleet Attacked!",1.5,1.5,0); - - if (battle_world[i]>0) then draw_text_transformed(xxx+313,yyy+144,"Planet "+string(battle_location[i])+" "+string(battle_world[i]),1,1,0); - if (battle_world[i]=-50) then draw_text_transformed(xxx+313,yyy+144,string(battle_location[i])+" System",1,1,0); - - draw_sprite(spr_force_icon,1,xxx+340,yyy+191); - if (battle_world[i]>0) then draw_sprite(spr_force_icon,battle_opponent[i],xxx+340,yyy+285); - draw_set_font(fnt_40k_14);draw_set_halign(fa_left); - - - - - if (battle_world[i]=-50){ - if (strin[1]!="0"){ - if (string(strin[1])="1") then draw_text(xxx+367,yyy+210,string(strin[1])+" Battleship ("+string(strin[4])+"% HP)"); - if (string(strin[1])!="1") then draw_text(xxx+367,yyy+210,string(strin[1])+" Battleships ("+string(strin[4])+"% HP)");} - - if (strin[2]!="0"){ - if (string(strin[2])="1") then draw_text(xxx+367,yyy+222,string(strin[2])+" Cruiser ("+string(strin[5])+"% HP)"); - if (string(strin[2])!="1") then draw_text(xxx+367,yyy+222,string(strin[2])+" Cruisers ("+string(strin[5])+"% HP)");} - - if (strin[3]!="0"){ - if (string(strin[3])="1") then draw_text(xxx+367,yyy+234,string(strin[3])+" Escort ("+string(strin[6])+"% HP)"); - if (string(strin[3])!="1") then draw_text(xxx+367,yyy+234,string(strin[3])+" Escorts ("+string(strin[6])+"% HP)");} - - - if (strin[7]!="0"){ - if (string(strin[7])="1") draw_text(xxx+367,yyy+302,string(strin[7])+" Battleship ("+string(strin[10])+"% HP)"); - if (string(strin[7])!="1") draw_text(xxx+367,yyy+302,string(strin[7])+" Battleships ("+string(strin[10])+"% HP)");} - - if (strin[8]!="0"){ - if (string(strin[8])="1") draw_text(xxx+367,yyy+314,string(strin[8])+" Cruiser ("+string(strin[11])+"% HP)"); - if (string(strin[8])!="1") draw_text(xxx+367,yyy+314,string(strin[8])+" Cruisers ("+string(strin[11])+"% HP)");} - - if (strin[9]!="0"){ - if (string(strin[9])="1") draw_text(xxx+367,yyy+326,string(strin[9])+" Escort ("+string(strin[12])+"% HP)"); - if (string(strin[9])!="1") draw_text(xxx+367,yyy+326,string(strin[9])+" Escorts ("+string(strin[12])+"% HP)");} - - draw_rectangle(xxx+188,yyy+350,xxx+297,yyy+372,1);draw_rectangle(xxx+328,yyy+350,xxx+437,yyy+372,1); - draw_set_alpha(0.5); - draw_rectangle(xxx+189,yyy+351,xxx+296,yyy+371,1);draw_rectangle(xxx+329,yyy+351,xxx+436,yyy+371,1); - draw_set_alpha(1); - - draw_set_halign(fa_center); - draw_text(xxx+241,yyy+353,"Fight");draw_text(xxx+383,yyy+353,"Retreat"); - draw_set_halign(fa_left); - } - - - if (battle_world[i]>=1){ - if (battle_opponent[i]<=20){ - draw_text(xxx+367,yyy+210,string(strin[1])+" Marines"); - draw_text(xxx+367,yyy+222,string(strin[2])+" Vehicles"); - if (strin[3]!="") then draw_text(xxx+367,yyy+234,string(strin[3])+" Fortified");// Not / Barely / Lightly / Moderately / Highly / Maximally - } - - draw_set_halign(fa_center); - draw_text(xxx+440,yyy+302,string(strin[4])); - - draw_rectangle(xxx+188,yyy+350,xxx+297,yyy+372,1);draw_rectangle(xxx+328,yyy+350,xxx+437,yyy+372,1); - draw_set_alpha(0.5); - draw_rectangle(xxx+189,yyy+351,xxx+296,yyy+371,1);draw_rectangle(xxx+329,yyy+351,xxx+436,yyy+371,1); - draw_set_alpha(1); - - draw_text(xxx+241,yyy+353,"Offensive");draw_text(xxx+383,yyy+353,"Defensive"); - draw_set_halign(fa_left); - } - - - - -}*/ - -/* */ - -/* */ -/* */ diff --git a/objects/obj_turn_end/Draw_64.gml b/objects/obj_turn_end/Draw_64.gml index 1dbe9b418b..6705411cc2 100644 --- a/objects/obj_turn_end/Draw_64.gml +++ b/objects/obj_turn_end/Draw_64.gml @@ -1,30 +1,21 @@ /// @description Insert description here // You can write your code in this editor -var i = 0; - draw_set_font(fnt_40k_14b); draw_set_halign(fa_left); draw_set_color(CM_GREEN_COLOR); if ((alerts > 0) && (popups_end == 1)) { - repeat (alerts) { - i += 1; + for (var i = 1; i <= alerts; i++) { set_alert_draw_colour(alert_color[i]); draw_set_alpha(min(1, alert_alpha[i])); if (obj_controller.zoomed == 0) { draw_text(32, +46 + (i * 20), string_hash_to_newline(string(alert_txt[i]))); - // draw_text(view_xview[0]+16.5,view_yview[0]+40.5+(i*12),string(alert_txt[i])); } - /*if (obj_controller.zoomed=1){ - draw_text_transformed(80,80+(i*24),string(alert_txt[i]),2,2,0); - draw_text_transformed(81,81+(i*24),string(alert_txt[i]),2,2,0); - }*/ if (obj_controller.zoomed == 1) { draw_text_transformed(32, 92 + (i * 40), string_hash_to_newline(string(alert_txt[i])), 2, 2, 0); - // draw_text_transformed(122,122+(i*36),string(alert_txt[i]),3,3,0); } } } diff --git a/objects/obj_turn_end/Mouse_56.gml b/objects/obj_turn_end/Mouse_56.gml index dcd58601e9..9a267f3e77 100644 --- a/objects/obj_turn_end/Mouse_56.gml +++ b/objects/obj_turn_end/Mouse_56.gml @@ -7,7 +7,7 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e var xxx = camera_get_view_x(view_camera[0]) + 535; var yyy = camera_get_view_y(view_camera[0]) + 200; - if ((cooldown <= 0) && (battle_world[current_battle] == -50) && (combating == 0)) { + if ((cooldown <= 0) && (battle_world[current_battle] == noone) && (combating == 0)) { if ((mouse_x >= xxx + 132) && (mouse_y >= yyy + 354) && (mouse_x < xxx + 259) && (mouse_y < yyy + 389)) { // Run like hell, space with (obj_fleet_select) { @@ -31,7 +31,6 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e combating = 1; instance_create(0, 0, obj_fleet); - // obj_fleet.enemy[1] = enemy_fleet[1]; obj_fleet.enemy_status[1] = -1; @@ -42,10 +41,8 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e // Plug in all of the enemies first // And then plug in the allies after then with their status set to positive - var g = 1; ee = 1; - repeat (5) { - g += 1; + for (var g = 2; g <= 6; g++) { if (enemy_fleet[g] != 0) { ee += 1; obj_fleet.enemy[ee] = enemy_fleet[g]; @@ -56,9 +53,7 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e obj_fleet.en_escort[ee] = eesc[g]; } } - var g = 0; - repeat (6) { - g += 1; + for (var g = 1; g <= 6; g++) { if (allied_fleet[g] != 0) { ee += 1; obj_fleet.enemy[ee] = allied_fleet[g]; @@ -92,13 +87,11 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e instance_activate_object(obj_ini); instance_activate_object(obj_fleet); instance_activate_object(obj_cursor); - // instance_deactivate_object(battle_pobject[current_battle]); } } if ((cooldown <= 0) && (battle_world[current_battle] > 0) && (combating == 0)) { - var tip; - tip = ""; + var tip = ""; if ((mouse_x >= xxx + 132) && (mouse_y >= yyy + 354) && (mouse_x < xxx + 259) && (mouse_y < yyy + 389)) { tip = "offensive"; @@ -163,14 +156,6 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e obj_ncombat.battle_special = battle_special[current_battle]; obj_ncombat.battle_climate = _planet_data.planet_type; - // show_message(string(battle_object[current_battle].p_feature[battle_world[current_battle]])); - /*if (scr_planetary_feature.plant_feature_bool(battle_object[current_battle].p_feature[battle_world[current_battle]], eP_FEATURES.MONASTERY)==1){ - // show_message(string(battle_object[current_battle].p_defenses[battle_world[current_battle]])); - // show_message(string(battle_object[current_battle].p_silo[battle_world[current_battle]])); - obj_ncombat.player_defenses+=battle_object[current_battle].p_defenses[battle_world[current_battle]]; - obj_ncombat.player_silos+=battle_object[current_battle].p_silo[battle_world[current_battle]]; - }*/ - if (_enemy == eFACTION.IMPERIUM) { obj_ncombat.threat = min(1000000, _planet_data.guardsmen); } else if (obj_ncombat.enemy < 14 && _enemy > 5) { @@ -179,7 +164,6 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e obj_ncombat.threat = 1; } - // _roster = new Roster(); with (_roster) { roster_location = _loc; diff --git a/objects/obj_turn_end/Step_0.gml b/objects/obj_turn_end/Step_0.gml index c187d532ff..a3c79d9d2c 100644 --- a/objects/obj_turn_end/Step_0.gml +++ b/objects/obj_turn_end/Step_0.gml @@ -1,14 +1,9 @@ -var i; -i = 0; - if (cooldown >= 0) { cooldown -= 1; } if ((alerts > 0) && (popups_end == 1) && (fadeout == 0)) { - repeat (alerts) { - i += 1; - + for (var i = 1; i <= alerts; i++) { if ((fast >= i) && (string_length(alert_txt[i]) < string_length(alert_text[i]))) { alert_char[i] += 1; alert_txt[i] = string_copy(alert_text[i], 0, alert_char[i]); @@ -20,9 +15,7 @@ if ((alerts > 0) && (popups_end == 1) && (fadeout == 0)) { } if (fadeout == 1) { - i = 0; - repeat (alerts) { - i += 1; + for (var i = 1; i <= alerts; i++) { alert_alpha[i] -= 0.05; if ((i == 1) && (alert_alpha[1] <= 0)) { instance_destroy(); diff --git a/scripts/Armamentarium/Armamentarium.gml b/scripts/Armamentarium/Armamentarium.gml index 360c61c0f5..72215cedeb 100644 --- a/scripts/Armamentarium/Armamentarium.gml +++ b/scripts/Armamentarium/Armamentarium.gml @@ -161,11 +161,10 @@ function ShopItem(_name) constructor { } /// @desc Handles the display and interaction for STC fragment research and bonuses. -/// @param {Id.Instance} _controller_ref Reference to the object holding STC data (usually obj_controller). +/// @param {Id.Instance.obj_controller} _controller_ref Reference to the object holding STC data (usually obj_controller). /// @param {Function} _on_change_callback Callback after identification. /// @return {Struct.STCResearchPanel} function STCResearchPanel(_controller_ref, _on_change_callback) constructor { - /// @type {Asset.GMObject.obj_controller} controller = _controller_ref; on_change = _on_change_callback; @@ -416,7 +415,7 @@ function STCResearchPanel(_controller_ref, _on_change_callback) constructor { } /// @desc Primary controller for the Chapter's armory and technologies. -/// @param {Asset.GMObject.obj_controller} _controller +/// @param {Id.Instance.obj_controller} _controller /// @returns {Struct.Armamentarium} function Armamentarium(_controller) constructor { controller = _controller; diff --git a/scripts/ColourItem/ColourItem.gml b/scripts/ColourItem/ColourItem.gml index 7b12235588..911032194e 100644 --- a/scripts/ColourItem/ColourItem.gml +++ b/scripts/ColourItem/ColourItem.gml @@ -443,13 +443,13 @@ function ColourItem(_xx, _yy) constructor { }; colour_pick = false; - dummy_marine = false; - dummy_image = false; + dummy_marine = undefined; + dummy_image = undefined; static reset_image = function() { if (is_struct(dummy_image)) { delete dummy_image; - dummy_image = false; + dummy_image = undefined; } }; @@ -524,7 +524,7 @@ function ColourItem(_xx, _yy) constructor { break; } delete dummy_image; - dummy_image = false; + dummy_image = undefined; } } } @@ -554,8 +554,7 @@ function ColourItem(_xx, _yy) constructor { } image_location_maps.company_marks = move_location_relative(draw_unit_buttons([xx - 30, yy - 40], "Company Marks"), -xx, -yy); - //draw_sprite(sprite_index, 0, x, y); - if (dummy_marine == false) { + if (dummy_marine ?? true) { dummy_marine = new DummyMarine(); } if (!is_struct(dummy_image)) { diff --git a/scripts/DebugView/DebugView.gml b/scripts/DebugView/DebugView.gml index eb65eee8c5..7e98b9fd86 100644 --- a/scripts/DebugView/DebugView.gml +++ b/scripts/DebugView/DebugView.gml @@ -29,19 +29,19 @@ function DebugView(view_name, obj) constructor { return self; }; - static add_slider_int = function(_name, min, max, label = _name, step = 1) { + static add_slider_int = function(_name, _min, _max, label = _name, step = 1) { if (update) { return self; } - dbg_slider_int(ref_create(self.obj_ref, _name), min, max, label, step); + dbg_slider_int(ref_create(self.obj_ref, _name), _min, _max, label, step); return self; }; - static add_slider = function(_name, min, max, label = _name, step = 0.01) { + static add_slider = function(_name, _min, _max, label = _name, step = 0.01) { if (update) { return self; } - dbg_slider(ref_create(self.obj_ref, _name), min, max, label == name, step); + dbg_slider(ref_create(self.obj_ref, _name), _min, _max, label, step); return self; }; diff --git a/scripts/NameGenerator/NameGenerator.gml b/scripts/NameGenerator/NameGenerator.gml index 07ce8bf667..3f2c56ced8 100644 --- a/scripts/NameGenerator/NameGenerator.gml +++ b/scripts/NameGenerator/NameGenerator.gml @@ -6,15 +6,15 @@ function NameTracker(set_name) constructor { composite_names = []; - composite_components = {}; + composite_components = { + prefixes : [], + suffixes : [], + special : [] + }; generic_counter = 0; static LoadSimpleNames = function(file_name, fallback_value, json_names_property_name = "names") { - if (json_names_property_name == noone) { - json_names_property_name = "names"; - } - var file_loader = new JsonFileListLoader(); var load_result = file_loader.load_list_from_json_file($"main/names/{file_name}.json", [json_names_property_name]); @@ -36,21 +36,17 @@ function NameTracker(set_name) constructor { "special" ] ) { - if (json_names_property_names == noone) { - json_names_property_names = [ - "prefixes", - "suffixes", - "special" - ]; - } - composite_names = json_names_property_names; var file_loader = new JsonFileListLoader(); var load_result = file_loader.load_list_from_json_file($"main/names/{file_name}.json", json_names_property_names); - var result = {}; + var result = { + prefixes : [], + suffixes : [], + special : [] + }; for (var i = 0; i < array_length(json_names_property_names); i++) { var _property_name = json_names_property_names[i]; diff --git a/scripts/instance_create/instance_create.gml b/scripts/instance_create/instance_create.gml index 9ff3d86578..89d7c8b462 100644 --- a/scripts/instance_create/instance_create.gml +++ b/scripts/instance_create/instance_create.gml @@ -1,9 +1,9 @@ /// @function instance_create /// @description Creates an instance of a given object at a given position. -/// @param {real} _x The x position the object will be created at. -/// @param {real} _y The y position the object will be created at. +/// @param {Real} _x The x position the object will be created at. +/// @param {Real} _y The y position the object will be created at. /// @param {Asset.GMObject} _obj The object to create an instance of. -/// @returns {Asset.GMObject} +/// @returns {Id.Instance} function instance_create(_x, _y, _obj) { var myDepth = object_get_depth(_obj); return instance_create_depth(_x, _y, myDepth, _obj); @@ -11,8 +11,8 @@ function instance_create(_x, _y, _obj) { /// @function instances_exist_any /// @description Checks if any of the provided instances exist -/// @param {array} instance_set Array of instances to check for existence -/// @returns {bool} +/// @param {Array} instance_set Array of instances to check for existence +/// @returns {Bool} function instances_exist_any(instance_set = []) { var _exists = false; for (var i = 0; i < array_length(instance_set); i++) { diff --git a/scripts/is_specialist/is_specialist.gml b/scripts/is_specialist/is_specialist.gml index 1907ca498b..0581a0c37b 100644 --- a/scripts/is_specialist/is_specialist.gml +++ b/scripts/is_specialist/is_specialist.gml @@ -15,17 +15,17 @@ #macro SPECIALISTS_HEADS "heads" /// @description Retrieves the active roles from the game, either from the obj_creation or obj_ini object. -/// @returns {array} +/// @returns {Array} function active_roles() { var _roles = instance_exists(obj_creation) ? obj_creation.role[100] : obj_ini.role[100]; return _roles; } /// @description Returns a list of roles based on the specified group, with optional inclusion of trainees and heads. -/// @param {integer} group The group of roles to retrieve (e.g., SPECIALISTS_STANDARD, SPECIALISTS_LIBRARIANS). -/// @param {bool} include_trainee Whether to include trainee roles (default is false). -/// @param {bool} include_heads Whether to include head roles (default is true). -/// @returns {array} +/// @param {Real} group The group of roles to retrieve (e.g., SPECIALISTS_STANDARD, SPECIALISTS_LIBRARIANS). +/// @param {Bool} include_trainee Whether to include trainee roles (default is false). +/// @param {Bool} include_heads Whether to include head roles (default is true). +/// @returns {Array} function role_groups(group, include_trainee = false, include_heads = true) { var _role_list = []; var _roles = active_roles(); @@ -217,11 +217,11 @@ function role_groups(group, include_trainee = false, include_heads = true) { } /// @description Checks if a given unit's role is a specialist within a specific role group. -/// @param {string} unit_role The role of the unit to check. -/// @param {integer} type The type of specialist group to check (default is SPECIALISTS_STANDARD). -/// @param {bool} include_trainee Whether to include trainee roles (default is false). -/// @param {bool} include_heads Whether to include head roles (default is true). -/// @returns {bool} +/// @param {String} unit_role The role of the unit to check. +/// @param {String} type The type of specialist group to check (default is SPECIALISTS_STANDARD). +/// @param {Bool} include_trainee Whether to include trainee roles (default is false). +/// @param {Bool} include_heads Whether to include head roles (default is true). +/// @returns {Bool} function is_specialist(unit_role, type = SPECIALISTS_STANDARD, include_trainee = false, include_heads = true) { var _specialists = role_groups(type, include_trainee, include_heads); diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 27b15dda2e..4d9be9d137 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -180,7 +180,8 @@ enum eINQUISITION_MISSION { TOMB_WORLD, TYRANID_ORGANISM, ETHEREAL, - DEMON_WORLD + DEMON_WORLD, + RANDOM = 100, } enum eEVENT { diff --git a/scripts/scr_ChapterTraits/scr_ChapterTraits.gml b/scripts/scr_ChapterTraits/scr_ChapterTraits.gml index ef930d94aa..7fc5c23783 100644 --- a/scripts/scr_ChapterTraits/scr_ChapterTraits.gml +++ b/scripts/scr_ChapterTraits/scr_ChapterTraits.gml @@ -469,10 +469,11 @@ function ChapterGameData(data = {}) constructor { function draw_chapter_trait_list(type) { add_draw_return_values(); + var _list = []; if (type) { - var _list = obj_creation.all_advantages; + _list = obj_creation.all_advantages; } else { - var _list = obj_creation.all_disadvantages; + _list = obj_creation.all_disadvantages; } var _title = type ? "Advantages" : "Disadvantage"; @@ -553,12 +554,14 @@ function draw_selected_chapter_traits(type) { add_draw_return_values(); + var _title_x = 0; + var _advarray = []; if (bool(type)) { - var _title_x = 436; - var _advarray = obj_creation.all_advantages; + _title_x = 436; + _advarray = obj_creation.all_advantages; } else { - var _title_x = 810; - var _advarray = obj_creation.all_disadvantages; + _title_x = 810; + _advarray = obj_creation.all_disadvantages; } var _adv_txt = { @@ -580,9 +583,10 @@ function draw_selected_chapter_traits(type) { var _advantages = 0; for (var i = 0; i < array_length(_advarray); i++) { var _adv = _advarray[i]; + var _array = []; if (_adv.activated) { if (_advantages < _max_advantage_count) { - var _array = draw_unit_buttons([_adv_txt.x1, _adv_txt.y1 + (_advantages * _adv_txt.h)], $"[-] {_adv.name}", [0.75, 0.75], CM_GREEN_COLOR); + _array = draw_unit_buttons([_adv_txt.x1, _adv_txt.y1 + (_advantages * _adv_txt.h)], $"[-] {_adv.name}", [0.75, 0.75], CM_GREEN_COLOR); _advantages++; } else { _adv.remove(); diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index d3e7cdd75a..7db5d3be33 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -1,6 +1,3 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information - global.force_strength_descriptions = [ "none", "Minimal", @@ -8,21 +5,20 @@ global.force_strength_descriptions = [ "Moderate", "Numerous", "Very Numerous", - "Overwhelming" + "Overwhelming", ]; -/// @param {real} planet -/// @param {Asset.GMObject.obj_star} system +/// @param {Real} planet +/// @param {Id.Instance.obj_star} system function PlanetData(planet, system) constructor { //safeguards // TODO LOW DEBUG_LOGGING // Log when tripped somewhere //disposition - // static large_pop_conversion = 1000000000; self.planet = planet; self.system = system; - static refresh_data = function(){ + static refresh_data = function() { features = system.p_feature[planet]; current_owner = system.p_owner[planet]; origional_owner = system.p_first[planet]; @@ -38,7 +34,7 @@ function PlanetData(planet, system) constructor { planet_type = system.p_type[planet]; operatives = system.p_operatives[planet]; pdf = system.p_pdf[planet]; - fortification_level = system.p_fortified[planet]; + fortification_level = system.p_fortified[planet]; star_station = system.p_station[planet]; pdf_loss_reduction = 0; @@ -54,25 +50,25 @@ function PlanetData(planet, system) constructor { guardsmen = system.p_guardsmen[planet]; pdf = system.p_pdf[planet]; - try{ + try { planet_forces[eFACTION.PLAYER] = player_forces; - planet_forces[eFACTION.IMPERIUM] = guardsmen; + planet_forces[eFACTION.IMPERIUM] = guardsmen; - planet_forces[eFACTION.ECCLESIARCHY] = system.p_sisters[planet]; - planet_forces[eFACTION.ELDAR] = system.p_eldar[planet]; - planet_forces[eFACTION.ORK] = system.p_orks[planet]; - planet_forces[eFACTION.TAU] = system.p_tau[planet]; - planet_forces[eFACTION.TYRANIDS] = system.p_tyranids[planet]; - planet_forces[eFACTION.CHAOS] = system.p_chaos[planet]+ system.p_demons[planet]; - planet_forces[eFACTION.HERETICS] = system.p_traitors[planet]; + planet_forces[eFACTION.ECCLESIARCHY] = system.p_sisters[planet]; + planet_forces[eFACTION.ELDAR] = system.p_eldar[planet]; + planet_forces[eFACTION.ORK] = system.p_orks[planet]; + planet_forces[eFACTION.TAU] = system.p_tau[planet]; + planet_forces[eFACTION.TYRANIDS] = system.p_tyranids[planet]; + planet_forces[eFACTION.CHAOS] = system.p_chaos[planet] + system.p_demons[planet]; + planet_forces[eFACTION.HERETICS] = system.p_traitors[planet]; planet_forces[eFACTION.NECRONS] = system.p_necrons[planet]; - }catch(_exception){ - handle_exception(_exception); + } catch (_exception) { + ERROR_HANDLER.handle_exception(_exception); } - - fortification_level = system.p_fortified[planet]; + + fortification_level = system.p_fortified[planet]; is_heretic = system.p_hurssy[planet]; @@ -85,7 +81,7 @@ function PlanetData(planet, system) constructor { population_influences = system.p_influence[planet]; raided_this_turn = system.p_raided[planet]; - // + governor = system.p_governor[planet]; problems = system.p_problem[planet]; @@ -97,21 +93,22 @@ function PlanetData(planet, system) constructor { requests_help = system.p_halp[planet]; - //safeguards // TODO LOW DEBUG_LOGGING // Log when tripped somewhere + //safeguards // TODO LOW DEBUG_LOGGING // Log when tripped somewhere //disposition - if (system.dispo[planet] < -100 && system.dispo[planet] > -1000 && system.p_owner[planet] != eFACTION.PLAYER ) { // Personal Rule code be doing some interesting things + if (system.dispo[planet] < -100 && system.dispo[planet] > -1000 && system.p_owner[planet] != eFACTION.PLAYER) { + // Personal Rule code be doing some interesting things system.dispo[planet] = -100; // TODO LOW DISPOSITION_REVAMP // Consider revamping the disposition system } else if (system.dispo[planet] > 100) { system.dispo[planet] = 100; } garrisons = system.system_garrison[planet]; - if (garrisons == 0){ - garrisons = system.get_garrison(planet) + if (garrisons == 0) { + garrisons = system.get_garrison(planet); } sabatours = system.system_sabatours[planet]; - if (sabatours == 0){ - sabatours = system.get_sabatours(planet) + if (sabatours == 0) { + sabatours = system.get_sabatours(planet); } system.system_datas[planet] = self; @@ -123,14 +120,17 @@ function PlanetData(planet, system) constructor { system.p_influence[planet][i] = 0; } } - } - refresh_data(); + secret_corruption = system.p_heresy_secret[planet]; + corruption = system.p_heresy[planet]; + }; - static total_corruption = function(){ + refresh_data(); + + static total_corruption = function() { return secret_corruption + corruption; - } + }; function add_operatives(new_ops) { array_push(system.p_operatives[planet], new_ops); @@ -171,28 +171,28 @@ function PlanetData(planet, system) constructor { return pop_value; }; - static population_as_small = function(){ + static population_as_small = function() { if (large_population) { return population * large_pop_conversion; } else { return population; } - } + }; - static end_turn_population_growth = function(){ + static end_turn_population_growth = function() { if ((population < max_population) && (planet_type != "Dead") && (planet_type != "Craftworld") && (current_owner <= 5) && (planet_forces[eFACTION.HERETICS] == 0) && (planet_forces[eFACTION.TAU] == 0) && (planet_forces[eFACTION.ORK] == 0) && (planet_forces[eFACTION.NECRONS] == 0) && (planet_forces[eFACTION.TYRANIDS] == 0)) { if (!large_population) { set_population(round(population * 1.0008)); } else if (large_population == 1) { edit_population(choose(0, 0.01)); } - } - } + } + }; - static alter_influence = function(faction,value){ + static alter_influence = function(faction, value) { adjust_influence(faction, value, planet, system); population_influences = system.p_influence[planet]; - } + }; static send_colony_ship = function(target, targ_planet, type) { new_colony_fleet(system, planet, target, targ_planet, type); @@ -259,11 +259,11 @@ function PlanetData(planet, system) constructor { guardsmen = system.p_guardsmen[planet]; }; - static edit_pdf = function(edit_val){ + static edit_pdf = function(edit_val) { system.p_pdf[planet] = max(0, system.p_pdf[planet] + edit_val); - pdf = system.p_pdf[planet] - } - + pdf = system.p_pdf[planet]; + }; + pdf = system.p_pdf[planet]; fortification_level = system.p_fortified[planet]; @@ -278,8 +278,7 @@ function PlanetData(planet, system) constructor { if (large_population) { new_pdf *= large_pop_conversion; } - pdf += new_pdf; - system.p_pdf[planet] = pdf; + edit_pdf(new_pdf); return new_pdf; }; @@ -294,9 +293,9 @@ function PlanetData(planet, system) constructor { player_forces = system.p_player[planet]; }; - static collect_planet_group = function(group="all",opposite=false,search_conditions = {companies:"all"} , return_as_UnitGroup = true){ - return collect_role_group(group,[system.name,planet],opposite,search_conditions, return_as_UnitGroup); - } + static collect_planet_group = function(group = "all", opposite = false, search_conditions = {companies: "all"}, return_as_UnitGroup = true) { + return collect_role_group(group, [system.name, planet], opposite, search_conditions, return_as_UnitGroup); + }; defence_lasers = system.p_lasers[planet]; defence_silos = system.p_silo[planet]; @@ -364,57 +363,50 @@ function PlanetData(planet, system) constructor { static assasinate_governor = function(assaination_type, discovery_modifier) { var randa = roll_dice_chapter(1, 100, "high"); var randa2 = roll_dice(1, 100); + var _text = $"All of the successors for {name()} are removed or otherwise made indisposed. Paperwork is slightly altered. Rather than any sort of offical one of your Chapter Serfs is installed as the Planetary Governor. The planet is effectively under your control."; + var _discovery_rate = 25; //type 1 is install a sympathectic else it's a straight serf installation if (assaination_type == 1) { - var _discovery_rate = 10; + _discovery_rate = 10; set_player_disposition(70 + floor(random_range(5, 15)) + 1); - var _text = $"Many of the successors for {name()} are removed or otherwise made indisposed. Your chapter ensures that the new Planetary Governor is sympathetic to your plight and more than willing to heed your advice. A powerful new ally may be in the making."; + _text = $"Many of the successors for {name()} are removed or otherwise made indisposed. Your chapter ensures that the new Planetary Governor is sympathetic to your plight and more than willing to heed your advice. A powerful new ally may be in the making."; scr_event_log("", $"Planetary Governor of {name()} assassinated. A more suitable Governor is installed."); } else { - var _discovery_rate = 25; if (origional_owner != 3) { set_new_owner(eFACTION.PLAYER); } set_player_disposition(101); scr_event_log("", $"Planetary Governor of {name()} assassinated. One of your Chapter Serfs take their position."); - var _text = $"All of the successors for {name()} are removed or otherwise made indisposed. Paperwork is slightly altered. Rather than any sort of offical one of your Chapter Serfs is installed as the Planetary Governor. The planet is effectively under your control."; } if (randa2 <= (_discovery_rate * discovery_modifier)) { + var _duration = (choose(1, 2) * 6) + choose(-3, -2, -1, 0, 1, 2, 3); if (assaination_type == 1) { - var _duration = ((choose(1, 2, 3, 4, 5, 6) + choose(1, 2, 3, 4, 5, 6)) * 6) + choose(-3, -2, -1, 0, 1, 2, 3); - } else { - var _duration = (choose(1, 2) * 6) + choose(-3, -2, -1, 0, 1, 2, 3); + _duration = ((choose(1, 2, 3, 4, 5, 6) + choose(1, 2, 3, 4, 5, 6)) * 6) + choose(-3, -2, -1, 0, 1, 2, 3); } - add_event({ - duration: _duration, e_id: - "governor_assassination", - variant: assaination_type, - system: system.name, - planet - }); + add_event({duration: _duration, e_id: "governor_assassination", variant: assaination_type, system: system.name, planet}); } return _text; }; + static purge = scr_purge_world; - static assasinate_governor_setup = function(action_score){ - var aroll=roll_dice_chapter(1, 100, "high"); + static assasinate_governor_setup = function(action_score) { + var aroll = roll_dice_chapter(1, 100, "high"); var chance = 100; - // var siz_penalty=0; - var o=0; - var yep=0; - + var o = 0; + var yep = 0; + // Disposition aroll += floor(player_disposition / 10); // Advantages - if (scr_has_adv("Ambushers")){ - aroll+=10; + if (scr_has_adv("Ambushers")) { + aroll += 10; } - if (scr_has_adv("Lightning Warriors")){ - aroll+=5; + if (scr_has_adv("Lightning Warriors")) { + aroll += 5; } // Size - unused @@ -424,102 +416,127 @@ function PlanetData(planet, system) constructor { // if ((action_score > 50) && (action_score <= 100)) { siz_penalty = 50; } // if ((action_score > 100) && (action_score <= 200)) { siz_penalty = 75; } // if (action_score > 200) { siz_penalty = 125; } - - var spec1=0,spec2=0,txt=""; // TODO consider making it a battle with Planetary governor's guards - txt=$"Your Astartes descend upon the surface of {name()} and plot the movements and schedule of the governor. "; - txt+="Once the time is right their target is ambushed " - txt+=choose("in their home","in the streets","while driving","taking a piss")+" and tranquilized. "; - - if (scr_has_disadv("Never Forgive")){ - spec1=1; - } - if (global.chapter_name="Space Wolves" || obj_ini.progenitor == ePROGENITOR.SPACE_WOLVES) { - spec1=3; + + var spec1 = 0, spec2 = 0, txt = ""; // TODO consider making it a battle with Planetary governor's guards + txt = $"Your Astartes descend upon the surface of {name()} and plot the movements and schedule of the governor. "; + txt += "Once the time is right their target is ambushed "; + txt += choose("in their home", "in the streets", "while driving", "taking a piss") + " and tranquilized. "; + + if (scr_has_disadv("Never Forgive")) { + spec1 = 1; } - else if (scr_has_adv("Tech-Brothers")) { - spec1=6; + if (global.chapter_name == "Space Wolves" || obj_ini.progenitor == ePROGENITOR.SPACE_WOLVES) { + spec1 = 3; + } else if (scr_has_adv("Tech-Brothers")) { + spec1 = 6; } - if (obj_ini.omophagea=1){ - spec1=choose(spec1,20); + if (obj_ini.omophagea == 1) { + spec1 = choose(spec1, 20); } var _gov_gender = set_gender(); var _gender_third = string_gender_third_person(_gov_gender); var _gender_pronouns = string_gender_pronouns(_gov_gender); - - if (spec1=1) then txt+=$"They are brought to the already-prepared facilities for Fallen, tortured to make {_gender_pronouns} appear a heretic, and then incinerated. "; - if (spec1=3) then txt+=$"{_gender_third} is tossed to the Fenrisian Wolves and viciously mauled, torn apart, and eaten. The beasts leave nothing but bloody scraps. "; - if (spec1=6) then txt+=$"{_gender_third} is stuck in with the other criminals, and scum, to be turned into a servitor. Soon nothing remains that could be likened to the former Governor. "; - if (spec1=20){ - if (action_score>1) then txt+=$"Things get out of hand, and the Governor is torn limb from limb and consumed. {_gender_pronouns}flesh is torn off and eaten, bone pulverized, and marrow sucked free. "; - if (action_score=1) then txt+=$"Your battle brother chops apart the Governor and eats a sizeable portion of {_gender_pronouns} flesh, focusing upon the eyes, teeth, and fingers. Once full the rest is disposed of. "; - } - - if (spec1=0){ - spec2=choose(1,2,3,4,5,5,5); - if (spec2=1) then txt+=$"Their still-living body is disintegrated by acid. "; - if (spec2=2) then txt+=$"The Governor is jettisoned into the local star at the first opportunity. "; - if (spec2=3) then txt+=$"{_gender_third} is burned as fuel for one of your vessels. "; - if (spec2=4) then txt+=$"A few grenades is all it takes to blow {_gender_pronouns} body to smithereens. "; - if (spec2=5) then txt+=$"{_gender_third} is executed in a mundane fashion and buried. "; - } - - txt+="What is thy will?"; - - var pip = instance_create(0,0,obj_popup); + + if (spec1 == 1) { + txt += $"They are brought to the already-prepared facilities for Fallen, tortured to make {_gender_pronouns} appear a heretic, and then incinerated. "; + } + if (spec1 == 3) { + txt += $"{_gender_third} is tossed to the Fenrisian Wolves and viciously mauled, torn apart, and eaten. The beasts leave nothing but bloody scraps. "; + } + if (spec1 == 6) { + txt += $"{_gender_third} is stuck in with the other criminals, and scum, to be turned into a servitor. Soon nothing remains that could be likened to the former Governor. "; + } + if (spec1 == 20) { + if (action_score > 1) { + txt += $"Things get out of hand, and the Governor is torn limb from limb and consumed. {_gender_pronouns}flesh is torn off and eaten, bone pulverized, and marrow sucked free. "; + } + if (action_score == 1) { + txt += $"Your battle brother chops apart the Governor and eats a sizeable portion of {_gender_pronouns} flesh, focusing upon the eyes, teeth, and fingers. Once full the rest is disposed of. "; + } + } + + if (spec1 == 0) { + spec2 = choose(1, 2, 3, 4, 5, 5, 5); + if (spec2 == 1) { + txt += $"Their still-living body is disintegrated by acid. "; + } + if (spec2 == 2) { + txt += $"The Governor is jettisoned into the local star at the first opportunity. "; + } + if (spec2 == 3) { + txt += $"{_gender_third} is burned as fuel for one of your vessels. "; + } + if (spec2 == 4) { + txt += $"A few grenades is all it takes to blow {_gender_pronouns} body to smithereens. "; + } + if (spec2 == 5) { + txt += $"{_gender_third} is executed in a mundane fashion and buried. "; + } + } + + txt += "What is thy will?"; + + var pip = instance_create(0, 0, obj_popup); pip.title = "Planetary Governor Assassinated"; pip.text = txt; pip.planet = planet; pip.p_data = self; var options = [ { - str1 : "Allow the official successor to become Planetary Governor.", - choice_func : allow_governor_successor, - }, + str1: "Allow the official successor to become Planetary Governor.", + choice_func: allow_governor_successor, + }, { - str1 : "Ensure that a sympathetic successor will be the one to rule.", - choice_func : install_sympathetic_successor, + str1: "Ensure that a sympathetic successor will be the one to rule.", + choice_func: install_sympathetic_successor, }, { - str1 : "Remove all successors and install a loyal Chapter Serf.", - choice_func : install_chapter_surf, + str1: "Remove all successors and install a loyal Chapter Serf.", + choice_func: install_chapter_surf, }, - ] - pip.add_option(options); - pip.cooldown=20; - + ]; + pip.add_option(options); + pip.cooldown = 20; + // Result- this is the multiplier for the chance of discovery with the inquisition, can also be used to determine // the new Governor disposition if they are the official successor - if (aroll < chance){// Discovered - pip.estimate=2; - } else if (aroll >= chance){// Success - pip.estimate=1; + if (aroll < chance) { + // Discovered + pip.estimate = 2; + } else if (aroll >= chance) { + // Success + pip.estimate = 1; } // If there are enemy non-chaos forces then they may be used as a cover // Does not work with chaos because if the governor dies, with chaos present, the new governor would possibly be investigated - if (planet_forces[eFACTION.ORK]>=4) or (planet_forces[eFACTION.NECRONS]>=3) or (planet_forces[eFACTION.TYRANIDS]>=5){ - pip.estimate = pip.estimate*0.5; + if ((planet_forces[eFACTION.ORK] >= 4) || (planet_forces[eFACTION.NECRONS] >= 3) || (planet_forces[eFACTION.TYRANIDS] >= 5)) { + pip.estimate = pip.estimate * 0.5; } - } - static grow_ork_forces = function(){ + }; + + static grow_ork_forces = function() { var contin = 0; - var _rando = roll_dice(1,100);// This part handles the spreading - // if (_rando<30){ + var _rando = roll_dice(1, 100); // This part handles the spreading var _non_deads = planets_without_type("dead", system); var _has_warboss = has_feature(eP_FEATURES.ORKWARBOSS); var _has_stronghold = has_feature(eP_FEATURES.ORKSTRONGHOLD); var _build_ships = false; - if (_has_stronghold){ - var _stronghold = get_features(eP_FEATURES.ORKSTRONGHOLD)[0]; + var _stronghold = []; + var _warboss = []; + var _orks = planet_forces[eFACTION.ORK]; + + if (_has_stronghold) { + _stronghold = get_features(eP_FEATURES.ORKSTRONGHOLD)[0]; } - if (_has_warboss){ - var _warboss = get_features(eP_FEATURES.ORKWARBOSS)[0]; + if (_has_warboss) { + _warboss = get_features(eP_FEATURES.ORKWARBOSS)[0]; _warboss.turns_static++; } var _roll_num = 100; - if (_has_stronghold){ + if (_has_stronghold) { _roll_num -= (_has_stronghold + 1) * 3; } var _ork_growth = roll_dice_chapter(1, 100, "high"); @@ -527,13 +544,12 @@ function PlanetData(planet, system) constructor { var _ork_growth_threshold = 13; - if (_has_warboss){ + if (_has_warboss) { _ork_growth_threshold *= 2; } - var _orks = planet_forces[eFACTION.ORK]; if ((current_owner == eFACTION.ORK) && (_orks < 5) && (planet_forces[eFACTION.HERETICS] == 0) && (player_forces <= 0 || !is_garrison_force)) { - if ((_orks> 0) && (_ork_growth <= _ork_growth_threshold)) { + if ((_orks > 0) && (_ork_growth <= _ork_growth_threshold)) { var _grow_orks = true; if (sabatours.garrison_force) { if (irandom(3) < 2) { @@ -541,197 +557,200 @@ function PlanetData(planet, system) constructor { _grow_orks = false; } } - if (_grow_orks){ - add_forces(eFACTION.ORK,1); + if (_grow_orks) { + add_forces(eFACTION.ORK, 1); } } } - if (array_length(_non_deads)>0 && _rando>40){ + if (array_length(_non_deads) > 0 && _rando > 40) { var _ork_spread_planet = array_random_element(_non_deads); - var _orks = planet_forces[eFACTION.ORK] var _ork_target = system.p_orks[_ork_spread_planet]; - var _spread_orks = (current_owner==eFACTION.ORK && ((pdf + guardsmen + planet_forces[8] + planet_forces[10]+planet_forces[1]) == 0 )); - if (_spread_orks){ + var _spread_orks = current_owner == eFACTION.ORK && ((pdf + guardsmen + planet_forces[8] + planet_forces[10] + planet_forces[1]) == 0); + if (_spread_orks) { // determine maximum Ork presence on the source planet var _ork_max = planet_forces[eFACTION.ORK]; - if (_ork_max<5 && _ork_target<2) then system.p_orks[_ork_spread_planet]++; - if (_orks>4 && _ork_target<3){ + if (_ork_max < 5 && _ork_target < 2) { + system.p_orks[_ork_spread_planet]++; + } + if (_orks > 4 && _ork_target < 3) { system.p_orks[_ork_spread_planet]++; - if (_ork_target<3){ + if (_ork_target < 3) { system.p_orks[_ork_spread_planet]++; add_forces(eFACTION.ORK, -1); } } - } } - contin=0; - _rando=roll_dice(1,100);// This part handles the ship building - if (population>0 && pdf==0 && guardsmen==0 && planet_forces[10]==0) and (planet_forces[eFACTION.TAU]==0){ - if (!large_population){ - set_population(population*0.97); - }else { + contin = 0; + _rando = roll_dice(1, 100); // This part handles the ship building + if ((population > 0 && pdf == 0 && guardsmen == 0 && planet_forces[10] == 0) && (planet_forces[eFACTION.TAU] == 0)) { + if (!large_population) { + set_population(population * 0.97); + } else { edit_population(-0.01); } - - }; - - var enemies_present=false; - with (system){ - for (var n=0;n=1) and ((p_pdf[plan]>0) or (p_guardsmen[plan]>0) or (p_traitors[plan]>0) or (p_tau[plan]>0)){ - enemies_present=true; + if ((planets >= 1) && ((p_pdf[plan] > 0) || (p_guardsmen[plan] > 0) || (p_traitors[plan] > 0) || (p_tau[plan] > 0))) { + enemies_present = true; } } } - if (_has_warboss && !_has_stronghold){ - _rando=roll_dice_chapter(1,100, "low"); - if (_rando<30){ + if (_has_warboss && !_has_stronghold) { + _rando = roll_dice_chapter(1, 100, "low"); + if (_rando < 30) { add_feature(eP_FEATURES.ORKSTRONGHOLD); } } else { - if (_has_stronghold){ + if (_has_stronghold) { growth = 0.01; - if (_has_warboss){ + if (_has_warboss) { growth *= 2; } - if (_stronghold.tier0) then _rando-=10;// Empire bonus, was 15 before - + if (obj_controller.known[eFACTION.ORK] > 0) { + _rando -= 10; + } // Empire bonus, was 15 before + // 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 + 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 (instance_exists(obj_p_fleet)){ - var ppp=instance_nearest(x,y,obj_p_fleet); - if (point_distance(x,y,ppp.x,ppp.y)<50) and (ppp.action=""){ + if (instance_exists(obj_p_fleet)) { + var ppp = instance_nearest(x, y, obj_p_fleet); + if ((point_distance(x, y, ppp.x, ppp.y) < 50) && (ppp.action == "")) { exit; - }; + } } - if (planet_type == "Forge"){ - _rando-=80; - } else if (planet_type == "Hive" || planet_type == "Temperate"){ - _rando-=30; - }else if (planet_type == "Agri"){ - _rando-=10; + if (planet_type == "Forge") { + _rando -= 80; + } else if (planet_type == "Hive" || planet_type == "Temperate") { + _rando -= 30; + } else if (planet_type == "Agri") { + _rando -= 10; } - var _ork_fleet = scr_orbiting_fleet(eFACTION.ORK, system); - if (_ork_fleet=="none"){ - if (_rando<=20){ - new_ork_fleet(x,y); + _ork_fleet = scr_orbiting_fleet(eFACTION.ORK, system); + if (_ork_fleet == noone) { + if (_rando <= 20) { + new_ork_fleet(x, y); } } else { - _build_ships = true; - - } - } + } + } } - if (_build_ships){ + if (_build_ships) { var _pdata = self; - with (_ork_fleet){ - // Increase ship number for this object? - var _rando=irandom(101); - if (obj_controller.known[eFACTION.ORK]>0) then _rando-=10; + with (_ork_fleet) { + // Increase ship number for this object? + _rando = irandom(101); + if (obj_controller.known[eFACTION.ORK] > 0) { + _rando -= 10; + } var _planet_type = _pdata.planet_type; - if (_planet_type=="Forge"){ - _rando-=20; - } else if (_planet_type=="Hive"){ - _rando-=10; - }else if (_planet_type=="Shrine" || _planet_type=="Temperate"){ - _rando-=5; + if (_planet_type == "Forge") { + _rando -= 20; + } else if (_planet_type == "Hive") { + _rando -= 10; + } else if (_planet_type == "Shrine" || _planet_type == "Temperate") { + _rando -= 5; } - if (_rando<=15){// was 25 - _rando=choose(1,1,1,1,1,1,1,2,2,2); - var _big_stronghold = false - if (_has_stronghold){ - if (_stronghold.tier>=2){ + if (_rando <= 15) { + // was 25 + _rando = choose(1, 1, 1, 1, 1, 1, 1, 2, 2, 2); + var _big_stronghold = false; + if (_has_stronghold) { + if (_stronghold.tier >= 2) { _big_stronghold = true; } } - if (_planet_type=="Forge" || _big_stronghold || _has_warboss){ - if (!irandom(10)){ + if (_planet_type == "Forge" || _big_stronghold || _has_warboss) { + if (!irandom(10)) { _rando = 3; } - }else if (_has_stronghold || _planet_type=="Hive"){ - if (!irandom(30)){ + } else if (_has_stronghold || _planet_type == "Hive") { + if (!irandom(30)) { _rando = 3; } } - if (capital_number<=0){ + if (capital_number <= 0) { _rando = 3; } - switch(_rando){ + switch (_rando) { case 3: - capital_number+=1; + capital_number += 1; break; case 2: - frigate_number+=1; + frigate_number += 1; break; case 1: - escort_number+=1; + escort_number += 1; break; - } } - var ii=round(standard_fleet_strength_calc()); - if (ii<=1) then ii=1; - image_index=ii; + var ii = round(standard_fleet_strength_calc()); + if (ii <= 1) { + ii = 1; + } + image_index = ii; //if big enough flee bugger off to new star - if (image_index>=5){ + if (image_index >= 5) { instance_deactivate_object(_pdata.system); - with(obj_star){ - if (is_dead_star()){ + with (obj_star) { + if (is_dead_star()) { instance_deactivate_object(id); } else { - if (owner == eFACTION.ORK || array_contains(p_owner, eFACTION.ORK)){ + if (owner == eFACTION.ORK || array_contains(p_owner, eFACTION.ORK)) { instance_deactivate_object(id); - } + } } } - var new_wagh_star = instance_nearest(x,y,obj_star); - if (instance_exists(new_wagh_star)){ - action_x=new_wagh_star.x; - action_y=new_wagh_star.y; + var new_wagh_star = instance_nearest(x, y, obj_star); + if (instance_exists(new_wagh_star)) { + action_x = new_wagh_star.x; + action_y = new_wagh_star.y; action = ""; set_fleet_movement(); } - } instance_activate_object(obj_star); } } - if (_has_warboss){ - _rando=roll_dice(1,100)+10; - var _ork_fleet = scr_orbiting_fleet(eFACTION.ORK, system); - if (_ork_fleet!="none" && _rando < _warboss.turns_static){ + if (_has_warboss) { + _rando = roll_dice(1, 100) + 10; + _ork_fleet = scr_orbiting_fleet(eFACTION.ORK, system); + if (_ork_fleet != noone && _rando < _warboss.turns_static) { _warboss.turns_static = 0; _ork_fleet.cargo_data.ork_warboss = _warboss; delete_feature(eP_FEATURES.ORKWARBOSS); - if (!_warboss.player_hidden || !irandom(5)){ - scr_alert("red","ork",$"{_warboss.name} departs {name()} as his waaagh gains momentum",0,0); + if (!_warboss.player_hidden || !irandom(5)) { + scr_alert("red", "ork", $"{_warboss.name} departs {name()} as his waaagh gains momentum", 0, 0); } } } - }; deamons = system.p_demons[planet]; @@ -746,7 +765,7 @@ function PlanetData(planet, system) constructor { corruption = system.p_heresy[planet]; }; - static set_corruption = function(value){ + static set_corruption = function(value) { system.p_heresy[planet] = value; corruption = system.p_heresy[planet]; }; @@ -760,7 +779,7 @@ function PlanetData(planet, system) constructor { population_influences = system.p_influence[planet]; raided_this_turn = system.p_raided[planet]; - // + governor = system.p_governor[planet]; problems = system.p_problem[planet]; @@ -885,7 +904,6 @@ function PlanetData(planet, system) constructor { scr_alert("green", "owner", $"{_requisition_spend} Requision spent on Ancient Ship repairs in materials and outfitting (outfitting {(_starship.funds_spent / _target_spend) * 100}%)", system.x, system.y); } if (_starship.funds_spent >= _target_spend && _starship.engineer_score >= 2000) { - // u2=tar; //TODO refactor into general new ship logic delete_feature(eP_FEATURES.STARSHIP); @@ -1285,7 +1303,7 @@ function PlanetData(planet, system) constructor { "Moderate", "Heavy", "Major", - "Extreme" + "Extreme", ]; var planet_forti = $"Defenses: {forti_string[fortification_level]}"; @@ -1338,7 +1356,7 @@ function PlanetData(planet, system) constructor { "Chaos", "Traitors", "Daemons", - "Necrons" + "Necrons", ]; var faction_ids = [ "p_sisters", @@ -1348,7 +1366,7 @@ function PlanetData(planet, system) constructor { "p_traitors", "p_chaos", "p_demons", - "p_necrons" + "p_necrons", ]; var blurbs = [ "Minima", @@ -1356,7 +1374,7 @@ function PlanetData(planet, system) constructor { "Moderatus", "Significus", "Enormicus", - "Extremis" + "Extremis", ]; for (var t = 0; t < array_length(faction_names); t++) { @@ -1384,21 +1402,19 @@ function PlanetData(planet, system) constructor { draw_text(xx + 349, yy + 346, string_hash_to_newline(string(presence_text))); var to_show = 0, temp9 = ""; - t = -1; var fit = array_create(11, ""); - var planet_displays = [], i; - var feat_count, _cur_feature; + var planet_displays = []; var feat_count = array_length(features); var upgrade_count = array_length(upgrades); var size = [ "", "Small", "", - "Large" + "Large", ]; if (feat_count > 0) { - for (i = 0; i < feat_count; i++) { + for (var i = 0; i < feat_count; i++) { var cur_feature = features[i]; try { if (cur_feature.planet_display != 0) { @@ -1426,7 +1442,7 @@ function PlanetData(planet, system) constructor { } } if (upgrade_count > 0) { - for (i = 0; i < upgrade_count; i++) { + for (var i = 0; i < upgrade_count; i++) { var _upgrade = upgrades[i]; if (_upgrade.f_type == eP_FEATURES.SECRET_BASE) { if (_upgrade.forge > 0) { @@ -1438,7 +1454,7 @@ function PlanetData(planet, system) constructor { } } - for (i = 0; i < array_length(problems); i++) { + for (var i = 0; i < array_length(problems); i++) { if (problems[i] == "") { continue; } @@ -1455,9 +1471,8 @@ function PlanetData(planet, system) constructor { } } - t = 0; var button_size, y_move = 0, button_colour; - for (i = 0; i < array_length(planet_displays); i++) { + for (var i = 0; i < array_length(planet_displays); i++) { button_colour = c_green; if (planet_displays[i][0] == "????") { button_colour = c_red; @@ -1473,30 +1488,9 @@ function PlanetData(planet, system) constructor { } } if (planet > 0) { - var current_planet = planet; + current_planet = planet; draw_set_color(c_black); draw_set_halign(fa_center); - - /*if (obj_controller.recruiting_worlds_bought>0) and (system.p_owner[planet]<=5) and (obj_controller.faction_status[system.p_owner[planet]]!="War"){ - if (string_count("Recr",system.p_feature[planet])=0){ - button4="+Recruiting"; - } - }*/ - - /*if (origional_owner=1){ - if (mouse_x>=xx+363) and (mouse_y>=yy+194) and (mouse_x0){ - var wid,hei,tex;draw_set_halign(fa_left); - tex=string(system.p_lasers[current_planet])+" Defense Laser, "+string(system.p_defenses[current_planet])+" Weapon Emplacements, "+string(system.p_silo[current_planet])+" Missile Silo"; - hei=string_height_ext(tex,-1,200)+4;wid=string_width_ext(tex,-1,200)+4; - draw_set_color(c_black); - draw_rectangle(xx+363,yy+210,xx+363+wid,yy+210+hei,0); - draw_set_color(CM_GREEN_COLOR); - draw_rectangle(xx+363,yy+210,xx+363+wid,yy+210+hei,1); - draw_text_ext(xx+365,yy+212,tex,-1,200); - } - } - }*/ } }; @@ -1592,17 +1586,17 @@ function PlanetData(planet, system) constructor { instance_destroy(obj_star_select); }; - static set_star_select_planet = function(){ + static set_star_select_planet = function() { obj_star_select.garrison = garrisons; system.garrison = garrisons.garrison_force; obj_star_select.feature = ""; buttons_selected = false; garrisons.update(); - if (garrisons.garrison_force){ + if (garrisons.garrison_force) { garrisons.find_leader(); - garrisons.garrison_disposition_change(true); - } - } + garrisons.garrison_disposition_change(true); + } + }; static planet_selection_logic = function() { var planet_is_allies = scr_is_planet_owned_by_allies(system, planet); @@ -1735,8 +1729,7 @@ function PlanetData(planet, system) constructor { } }; - static end_of_turn_population_influence_and_enemy_growth = function(){ - + static end_of_turn_population_influence_and_enemy_growth = function() { sabotage_force = sabatours.garrison_force; total_garrison = garrisons.total_garrison; is_garrison_force = garrisons.garrison_force; @@ -1747,8 +1740,7 @@ function PlanetData(planet, system) constructor { // increasing necrons if (array_length(features) != 0) { - var has_awake_tomb = false, - nfleet = 0; + var has_awake_tomb = false, nfleet = 0; if (awake_tomb_world(features) == 1) { has_awake_tomb = true; } @@ -1767,7 +1759,7 @@ function PlanetData(planet, system) constructor { if (has_awake_tomb) { // Necron fleets, woooo //necrons kill populatin - if ((population > 0) && (player_forces + pdf + guardsmen + planet_forces[eFACTION.TYRANIDS] == 0)) { + if ((population > 0) && (player_forces + pdf + guardsmen + planet_forces[eFACTION.TYRANIDS] == 0)) { set_population(population * 0.75); if ((large_population == 0) && (population <= 5000)) { set_population(0); @@ -1800,7 +1792,7 @@ function PlanetData(planet, system) constructor { system.present_fleet[eFACTION.NECRONS] += 1; } var enemy_fleets = 0; - with(necron_fleet) { + with (necron_fleet) { if (owner == eFACTION.NECRONS) { var ii = 0; ii += capital_number; @@ -1808,7 +1800,7 @@ function PlanetData(planet, system) constructor { ii += round((escort_number / 4)); if (ii <= 1) { ii = 1; - } // image_index=max(8,round(ii)); + } if ((ii >= 7) && (capital_number > 1)) { for (var fleet_n = 1; fleet_n <= 10; fleet_n++) { @@ -1820,11 +1812,9 @@ function PlanetData(planet, system) constructor { } } if (enemy_fleets > 0) { - var necron_fleet2; - necron_fleet2 = instance_create(x, y, obj_en_fleet); + var necron_fleet2 = instance_create(x, y, obj_en_fleet); necron_fleet2.owner = eFACTION.NECRONS; necron_fleet2.sprite_index = spr_fleet_necron; - // necron_fleet2.image_index=0; necron_fleet.image_speed = 0; necron_fleet2.capital_number = 1; necron_fleet2.frigate_number = round(necron_fleet.frigate_number / 2); @@ -1838,8 +1828,8 @@ function PlanetData(planet, system) constructor { var _found_near_planet = false; var _distance = 0; var _start_star = system.id; - with(obj_star) { - if (id == _start_star){ + with (obj_star) { + if (id == _start_star) { continue; } if (present_fleet[eFACTION.NECRONS] > 0) { @@ -1857,13 +1847,13 @@ function PlanetData(planet, system) constructor { } } - if (!_valid_owners){ + if (!_valid_owners) { continue; } var _point_dist = object_distance(_start_star, self); - if (_distance == 0 || _point_dist < _distance){ + if (_distance == 0 || _point_dist < _distance) { _nearest_planet = self.id; _found_near_planet = true; _distance = _point_dist; @@ -1875,7 +1865,7 @@ function PlanetData(planet, system) constructor { necron_fleet2.action_x = _nearest_planet.x; necron_fleet2.action_y = _nearest_planet.y; - with (necron_fleet2){ + with (necron_fleet2) { set_fleet_movement(); } } @@ -1888,37 +1878,32 @@ function PlanetData(planet, system) constructor { end_turn_genestealer_cults(); - // Spread influence on controlled sector if ((planet_type != "Space Hulk") && (planet_type != "Dead")) { - if ((corruption < 70 && current_owner == 10)) { - if (current_owner == 10){ + if (corruption < 70 && current_owner == 10) { + if (current_owner == 10) { alter_corruption(2); } - } - if (current_owner == eFACTION.TAU && population_influences[eFACTION.TYRANIDS]<70){ - var _influ_chance = roll_dice(1,100); - if (_influ_chance <= 5 && population_influences[eFACTION.TYRANIDS]>=20){ + if (current_owner == eFACTION.TAU && population_influences[eFACTION.TYRANIDS] < 70) { + var _influ_chance = roll_dice(1, 100); + if (_influ_chance <= 5 && population_influences[eFACTION.TYRANIDS] >= 20) { alter_influence(eFACTION.TAU, 1); } } - if (planet_type == "Daemon"){ - if (pdf > 0) { - pdf = 0; + if (planet_type == "Daemon") { + if (pdf > 0) { + pdf = 0; } if (guardsmen > 0) { guardsmen = 0; } } - } - - } - + }; - static end_turn_genestealer_cults = function(){ + static end_turn_genestealer_cults = function() { // Genestealer cults grow in number if (has_feature(eP_FEATURES.GENE_STEALER_CULT)) { var cult = get_features(eP_FEATURES.GENE_STEALER_CULT)[0]; @@ -1931,7 +1916,7 @@ function PlanetData(planet, system) constructor { var find_cult_chance = irandom(50); var alert_text = $"A hidden Genestealer Cult on {name()} Has suddenly burst forth from hiding!"; if (planet_garrison.garrison_force) { - var alert_text = $"A hidden Genestealer Cult on {name()} Has been discovered by marine garrisons!"; + alert_text = $"A hidden Genestealer Cult on {name()} Has been discovered by marine garrisons!"; find_cult_chance -= 25; } if (find_cult_chance < 1) { @@ -1939,7 +1924,7 @@ function PlanetData(planet, system) constructor { scr_popup("System Lost", alert_text, "Genestealer Cult", ""); set_new_owner(eFACTION.TYRANIDS); scr_event_log("red", $"A hidden Genestealer Cult on {name()} has Started a revolt.", system.name); - edit_forces(eFACTION.TYRANIDS,1); + edit_forces(eFACTION.TYRANIDS, 1); } } } @@ -1972,15 +1957,13 @@ function PlanetData(planet, system) constructor { add_feature(eP_FEATURES.GENE_STEALER_CULT); } } - } + }; - static end_turn_heretics_and_corruption_growth = function(){ + static end_turn_heretics_and_corruption_growth = function() { // traitors cults - var notixt; - var is_ork; - notixt = false; + var notixt = false; - var _rando = roll_dice(1,100); + var _rando = roll_dice(1, 100); if ((current_owner == eFACTION.CHAOS) && (corruption < 80)) { alter_corruption(1); @@ -1988,22 +1971,16 @@ function PlanetData(planet, system) constructor { if ((current_owner != eFACTION.CHAOS) && (current_owner != eFACTION.HERETICS) && (current_owner != eFACTION.ELDAR) && (planet_type != "Dead") && (planet_type != "Craftworld")) { success = false; - is_ork = current_owner == eFACTION.ORK; - if (!is_ork) { + if (!current_owner == eFACTION.ORK) { //made a linear function for this while here...now the minimum for the roll is a bit higher, but var score_to_beat = (3 / 4) * (corruption + secret_corruption) - 27.5; - - //if (corruption+secret_corruption>=25) and (_rando<=3) then success=true; - //if (corruption+secret_corruption>=50) and (_rando<=10) then success=true; - //if (corruption+secret_corruption>=70) and (_rando<=25) then success=true; - //if (corruption+secret_corruption>=90) and (_rando<=40) then success=true; if (_rando < score_to_beat) { success = true; } } - if (success && (pdf == 0) && (guardsmen == 0) && (planet_forces[eFACTION.TAU] == 0) && (planet_forces[eFACTION.ORK] == 0)) { + if (success && (pdf == 0) && (guardsmen == 0) && (planet_forces[eFACTION.TAU] == 0) && (planet_forces[eFACTION.ORK] == 0)) { set_new_owner(eFACTION.HERETICS); scr_alert("red", "owner", $"{name()} has fallen to heretics!", x, y); @@ -2011,7 +1988,7 @@ function PlanetData(planet, system) constructor { //visited variable check whether the star has been visited or not 1 for true 0 for false if (planet_type == "Forge") { add_disposition(-10); - // 10 disposition decreases for the respective planet + // 10 disposition decreases for the respective planet obj_controller.disposition[3] -= 3; // 10 disposition decrease for the toaster Fetishest since they aren't that numerous } else if (has_feature(eP_FEATURES.SORORITAS_CATHEDRAL) || (planet_type == "Shrine")) { add_disposition(-4); // similarly 10 disposition decrease, note those nurses are a bit pissy and @@ -2024,8 +2001,7 @@ function PlanetData(planet, system) constructor { } if (success && (planet_type != "Space Hulk")) { - _rando = roll_dice(1,100); - // // // obj_controller.x=self.x;obj_controller.y=self.y; + _rando = roll_dice(1, 100); if (is_garrison_force) { _rando -= total_garrison; } @@ -2044,19 +2020,19 @@ function PlanetData(planet, system) constructor { } if (garrison_mod > 0) { - var lost = floor(pdf * garrison_mod); + var lost = floor(pdf * garrison_mod); - if (pdf <= 500) { - lost = pdf ; + if (pdf <= 500) { + lost = pdf; edit_forces(eFACTION.HERETICS, 1); } edit_pdf(-lost); if (planet_forces[eFACTION.HERETICS] == 0) { - if (pdf > 0) { + if (pdf > 0) { tixt = $"{scr_display_number(lost)} PDF killed in a rebellion on {name()}."; - } else if (pdf == 0) { + } else if (pdf == 0) { tixt = $"Heretic cults have appeared in {name()}."; } @@ -2086,17 +2062,17 @@ function PlanetData(planet, system) constructor { } else { traitor_mod = 3; } - edit_forces(eFACTION.HERETICS,traitor_mod); + edit_forces(eFACTION.HERETICS, traitor_mod); tixt = $"Heretic cults have spread around {name()}."; } // Major uprising // major and huge uprisings are impossible as long as a garrisons of at least 10 marines is present if ((_rando >= 91) && (_rando < 100) && (planet_forces[eFACTION.HERETICS] < 4)) { notixt = true; - edit_forces(eFACTION.HERETICS,4); + edit_forces(eFACTION.HERETICS, 4); if ((obj_controller.faction_defeated[10] == 0) && (obj_controller.faction_gender[10] == 1)) { - edit_forces(eFACTION.HERETICS,5); + edit_forces(eFACTION.HERETICS, 5); } var n_name = name(); @@ -2106,11 +2082,11 @@ function PlanetData(planet, system) constructor { } // Huge uprising if ((_rando >= 100) && (planet_forces[eFACTION.HERETICS] < 5)) { - edit_forces(eFACTION.HERETICS,6); - set_new_owner(eFACTION.HERETICS) + edit_forces(eFACTION.HERETICS, 6); + set_new_owner(eFACTION.HERETICS); add_feature(eP_FEATURES.DAEMONIC_INCURSION); - set_corruption(corruption < 80 ? 80 : 95) + set_corruption(corruption < 80 ? 80 : 95); tixt = $"Daemonic incursion on {name()}!"; } // Oh god what @@ -2119,9 +2095,46 @@ function PlanetData(planet, system) constructor { scr_alert("red", "owner", tixt, x, y); scr_event_log("purple", tixt, system.name); } - // if (planet_forces[eFACTION.HERETICS]>2){obj_controller.x=self.x;obj_controller.y=self.y;} } // End traitors cult } + }; - } -} \ No newline at end of file + static create_alert = function() { + return instance_create(system.x + 16, system.y - 24, obj_star_event); + }; + + static init_war_of_succession = function() { + add_feature(eP_FEATURES.SUCCESSION_WAR); + add_problem("succession", irandom(6) + 4); + set_player_disposition(-5000); + + scr_popup("War of Succession", $"The planetary governor of {name()} has died. Several subordinates and other parties each claim to be the true heir and successor- war has erupted across the planet as a result. Heresy thrives in chaos.", "succession", ""); + var _star_alert = create_alert(); + _star_alert.image_alpha = 1; + _star_alert.image_speed = 1; + _star_alert.col = "red"; + scr_event_log("red", $"War of Succession on {name()}"); + }; + + static init_fallen_marines = function() { + var _eta = scr_mission_eta(system.x, system.y, 1); + + LOGGER.info($"Fallen: found star {name()} as candidate"); + + var assigned_problem = add_problem("fallen", _eta); + LOGGER.info($"assigned_problem {assigned_problem}"); + + if (!assigned_problem) { + LOGGER.error("RE: Hunt the Fallen, coulnd't assign a problem to the planet"); + return; + } + + var _text = $"Sources indicate one of the Fallen may be upon {name()}. We have {_eta} months to send out a strike team and scour the planet. Any longer and any Fallen that might be there will have escaped."; + scr_popup("Hunt the Fallen", _text, "fallen", ""); + scr_event_log("", $"Sources indicate one of the Fallen may be upon {name()}. We have {_eta} months to investigate."); + var star_alert = create_alert(); + star_alert.image_alpha = 1; + star_alert.image_speed = 1; + star_alert.col = "purple"; + }; +} diff --git a/scripts/scr_Table/scr_Table.gml b/scripts/scr_Table/scr_Table.gml index f300597cff..e3d91a7817 100644 --- a/scripts/scr_Table/scr_Table.gml +++ b/scripts/scr_Table/scr_Table.gml @@ -34,7 +34,7 @@ function Table(data) constructor { headings[i] = new ReactiveString(_heading, 0, 0, {scale_text: true}); } - var _heading = headings[i]; + _heading = headings[i]; if (i < array_length(set_column_widths) && set_column_widths[i] > 0) { array_push(column_widths, set_column_widths[i]); @@ -65,7 +65,6 @@ function Table(data) constructor { } if (struct_exists(_row, "hover")) { - //LOGGER.debug($"click : {struct_exists(_row,"click_left")}"); _row.hover(); } diff --git a/scripts/scr_UnitGroup/scr_UnitGroup.gml b/scripts/scr_UnitGroup/scr_UnitGroup.gml index 08a51d7cd2..35e8259574 100644 --- a/scripts/scr_UnitGroup/scr_UnitGroup.gml +++ b/scripts/scr_UnitGroup/scr_UnitGroup.gml @@ -279,13 +279,14 @@ function UnitGroup(units) constructor { /*and ((squad_fulfilment[$ obj_ini.role[100][8]] > 4)or (squad_fulfilment[$ obj_ini.role[100][10]] > 4) or (squad_fulfilment[$ obj_ini.role[100][9]] > 4)or (squad_fulfilment[$ obj_ini.role[100][3]] > 4) )*/ var _members = squad.get_members(true); + var _exp_unit = 0; if (!bool(_members.number())) { return [false, squad.uid]; } for (var s = 0; s < 2; s++) { var _sgt_type = sgt_types[s]; if (struct_exists(squad_fulfilment, _sgt_type) && (!sergeant_found)) { - var _exp_unit = _members.highest_exp(); + _exp_unit = _members.highest_exp(); squad_fulfilment[$ _sgt_type]++; } diff --git a/scripts/scr_add_artifact/scr_add_artifact.gml b/scripts/scr_add_artifact/scr_add_artifact.gml index 9cf59a26a5..563f1486b7 100644 --- a/scripts/scr_add_artifact/scr_add_artifact.gml +++ b/scripts/scr_add_artifact/scr_add_artifact.gml @@ -1,5 +1,5 @@ function find_open_artifact_slot() { - var i = 0, last_artifact = -1; + var last_artifact = -1; for (var i = 0; i < array_length(obj_ini.artifact); i++) { if (last_artifact == -1) { if (obj_ini.artifact[i] == "") { @@ -215,7 +215,6 @@ function scr_add_artifact(artifact_type = "random", artifact_tags = "", is_ident } var big = choose(1, 2); - // if (big=1 || artifact_tags="minor") then t5=""; if (artifact_tags == "minor") { t4 = ""; t5 = ""; @@ -241,7 +240,6 @@ function scr_add_artifact(artifact_type = "random", artifact_tags = "", is_ident array_push(tags, "daemonic"); array_push(tags, "chaos_gift"); } - // show_message(string(t3)); if (artifact_location == "") { if (obj_ini.fleet_type == ePLAYER_BASE.HOME_WORLD) { @@ -255,8 +253,6 @@ function scr_add_artifact(artifact_type = "random", artifact_tags = "", is_ident obj_ini.artifact[last_artifact] = base_type_detail; obj_ini.artifact_tags[last_artifact] = tags; - // show_message(string(obj_ini.artifact_tags[last_artifact])); - obj_ini.artifact_identified[last_artifact] = is_identified; obj_ini.artifact_condition[last_artifact] = 100; obj_ini.artifact_loc[last_artifact] = artifact_location; @@ -539,11 +535,10 @@ function ArtifactStruct(Index) constructor { var _b_type = determine_base_type(); var _bearer = false; var _bearer_found = false; - var _unit; if (_b_type == "weapon") { for (var co = 0; co < obj_ini.companies; co++) { for (var i = 0; i < array_length(obj_ini.role[co]); i++) { - _unit = fetch_unit([co, i]); + var _unit = fetch_unit([co, i]); if (_unit.weapon_one(true) == index) { _unit.update_weapon_one("", false, true); _bearer_found = true; @@ -561,14 +556,15 @@ function ArtifactStruct(Index) constructor { } } else { var _find_function = ""; + var _update_function = ""; if (_b_type == "gear") { - var _update_function = "update_gear"; + _update_function = "update_gear"; _find_function = "gear"; } else if (_b_type == "armour") { - var _update_function = "update_armour"; + _update_function = "update_armour"; _find_function = "armour"; } else if (_b_type == "mobility") { - var _update_function = "update_mobility_item"; + _update_function = "update_mobility_item"; _find_function = "mobility_item"; } if (_find_function != "") { @@ -868,12 +864,6 @@ function delete_artifact(index) { artifact_equipped[index] = false; artifact_struct[index] = new ArtifactStruct(index); } - /*for (var i=index;i 0) { array_push(ships, capital_num[i]); @@ -32,7 +26,7 @@ function scr_add_corruption(is_fleet, modifier_type) { if (obj_ini.name[co][i] == "") { continue; } - unit = fetch_unit([co, i]); + var unit = fetch_unit([co, i]); if (array_contains(ships, unit.ship_location)) { if (modifier_type == "1d3") { unit.edit_corruption(choose(1, 2, 3)); diff --git a/scripts/scr_add_vehicle/scr_add_vehicle.gml b/scripts/scr_add_vehicle/scr_add_vehicle.gml index 8d91861855..77cc7b5e71 100644 --- a/scripts/scr_add_vehicle/scr_add_vehicle.gml +++ b/scripts/scr_add_vehicle/scr_add_vehicle.gml @@ -1,8 +1,17 @@ +/// @function scr_add_vehicle(vehicle_type, target_company, otherdata, weapon1, weapon2, weapon3, upgrade, accessory) +/// @description +/// @param {String} vehicle_type +/// @param {Real} target_company +/// @param {Struct} otherdata +/// @param {String} weapon1 +/// @param {String} weapon2 +/// @param {String} weapon3 +/// @param {String} upgrade +/// @param {String} accessory function scr_add_vehicle(vehicle_type, target_company, otherdata = {}, weapon1 = "standard", weapon2 = "standard", weapon3 = "standard", upgrade = "standard", accessory = "standard") { try { // That should be sufficient to add stuff in a highly modifiable fashion - var i = 0; var e = 0; var good = 0; var wep1 = ""; @@ -32,7 +41,8 @@ function scr_add_vehicle(vehicle_type, target_company, otherdata = {}, weapon1 = if (obj_ini.fleet_type != ePLAYER_BASE.HOME_WORLD) { // Need a more elaborate ship_carrying += here for the different types of units - var first = -1, backup = -1, i = 0; + var first = -1; + var backup = -1; for (var i = 0; i < array_length(obj_ini.ship_class); i++) { if ((obj_ini.ship_class[i] == "Battle Barge") && (first == -1) && (obj_ini.ship_capacity[i] > obj_ini.ship_carrying[i])) { first = i; @@ -151,6 +161,10 @@ function scr_add_vehicle(vehicle_type, target_company, otherdata = {}, weapon1 = } } +/// @function destroy_vehicle(co, num) +/// @description +/// @param {Real} co +/// @param {Real} num function destroy_vehicle(co, num) { try { obj_ini.veh_race[co][num] = 0; diff --git a/scripts/scr_apothecary_ground/scr_apothecary_ground.gml b/scripts/scr_apothecary_ground/scr_apothecary_ground.gml index 2792949cc0..2bb1db36e4 100644 --- a/scripts/scr_apothecary_ground/scr_apothecary_ground.gml +++ b/scripts/scr_apothecary_ground/scr_apothecary_ground.gml @@ -24,8 +24,8 @@ function calculate_full_chapter_spread() { var _apoth_spread = {}; var _unit_spread = {}; for (var company = 0; company < 11; company++) { - var _marine_len = array_length(obj_ini.name[company]); - var _veh_len = array_length(obj_ini.veh_hp[company]); + var _marine_len = array_length(obj_ini.name[company]) - 1; + var _veh_len = array_length(obj_ini.veh_hp[company]) - 1; var _company_length = max(_marine_len, _veh_len); for (var v = 0; v < _company_length; v++) { @@ -174,7 +174,7 @@ function system_point_data_spawn() { /// @self Struct.SpecialistPointHandler function process_specialist_points() { - var _spreads = chapter_spread(); + var _spreads = calculate_full_chapter_spread(); var _tech_spread = _spreads[0]; var _apoth_spread = _spreads[1]; var _unit_spread = _spreads[2]; @@ -201,75 +201,6 @@ function process_specialist_points() { array_push(_unit_spread[$ name], self); } - // --- Step 2: Process Locations --- - for (var i = 0; i < _loc_count; i++) { - var _cur_loc = _locations[i]; - var _loc_slots = _unit_spread[$ _cur_loc]; - var _star_inst = (array_length(_loc_slots) > STAR_INSTANCE_INDEX) ? _loc_slots[STAR_INSTANCE_INDEX] : pointer_null; - - if (_star_inst != pointer_null) { - point_breakdown.systems[$ _star_inst.name] = system_point_data_spawn(); - } - - for (var _p = 0; _p < PLANET_SLOT_COUNT; _p++) { - var _cur_units = _loc_slots[_p]; - var _unit_count = array_length(_cur_units); - if (_unit_count == 0) { - continue; - } - - var _cur_apoths = _apoth_spread[$ _cur_loc][_p]; - var _cur_techs = _tech_spread[$ _cur_loc][_p]; - - var _pool = { - heal: 0, - forge: 0, - }; - - // Calculate Generation - for (var a = 0, _al = array_length(_cur_apoths); a < _al; a++) { - _pool.heal += _cur_apoths[a].apothecary_point_generation(turn_end)[0]; - } - for (var t = 0, _tl = array_length(_cur_techs); t < _tl; t++) { - _pool.forge += _cur_techs[t].forge_point_generation(turn_end)[0]; - } - - var _initial_heal = _pool.heal; - var _initial_forge = _pool.forge; - - // Process Maintenance and Repairs/Heal - for (var u = 0; u < _unit_count; u++) { - var _unit = _cur_units[u]; - if (is_array(_unit)) { - _process_vehicle_maintenance(_unit, _pool); - } else if (is_struct(_unit)) { - _process_marine_maintenance(_unit, _pool); - } - } - - // Record Stats - var _stats = { - heal_points: _initial_heal, - forge_points: _initial_forge, - heal_points_use: _initial_heal - _pool.heal, - forge_points_use: _initial_forge - _pool.forge, - }; - - if (_star_inst != pointer_null) { - point_breakdown.systems[$ _star_inst.name][_p] = _stats; - - // Planet specific logic (Orbit is 0, Planets are 1-4) - if (turn_end && _p > 0 && array_length(_star_inst.p_feature[_p]) > 0) { - var _planet_data = _star_inst.get_planet_data(_p); - _planet_data.recover_starship(_cur_techs); - _planet_data.planet_training(_pool.heal); - } - } else if (_p == 0 && string_pos("ref instance", _cur_loc) > 0) { - _handle_instance_point_recording(_cur_loc, _stats); - } - } - } - /// @param {Array} _unit /// @param {Struct} _pool static _process_vehicle_maintenance = function(_unit, _pool) { @@ -355,4 +286,73 @@ function process_specialist_points() { LOGGER.error($"Failed to parse instance ID from location string: {_loc_str} | Error: {_ex.message}"); } }; + + // --- Step 2: Process Locations --- + for (var i = 0; i < _loc_count; i++) { + var _cur_loc = _locations[i]; + var _loc_slots = _unit_spread[$ _cur_loc]; + var _star_inst = (array_length(_loc_slots) > STAR_INSTANCE_INDEX) ? _loc_slots[STAR_INSTANCE_INDEX] : pointer_null; + + if (_star_inst != pointer_null) { + point_breakdown.systems[$ _star_inst.name] = system_point_data_spawn(); + } + + for (var _p = 0; _p < PLANET_SLOT_COUNT; _p++) { + var _cur_units = _loc_slots[_p]; + var _unit_count = array_length(_cur_units); + if (_unit_count == 0) { + continue; + } + + var _cur_apoths = _apoth_spread[$ _cur_loc][_p]; + var _cur_techs = _tech_spread[$ _cur_loc][_p]; + + var _pool = { + heal: 0, + forge: 0, + }; + + // Calculate Generation + for (var a = 0, _al = array_length(_cur_apoths); a < _al; a++) { + _pool.heal += _cur_apoths[a].apothecary_point_generation(turn_end)[0]; + } + for (var t = 0, _tl = array_length(_cur_techs); t < _tl; t++) { + _pool.forge += _cur_techs[t].forge_point_generation(turn_end)[0]; + } + + var _initial_heal = _pool.heal; + var _initial_forge = _pool.forge; + + // Process Maintenance and Repairs/Heal + for (var u = 0; u < _unit_count; u++) { + var _unit = _cur_units[u]; + if (is_array(_unit)) { + _process_vehicle_maintenance(_unit, _pool); + } else if (is_struct(_unit)) { + _process_marine_maintenance(_unit, _pool); + } + } + + // Record Stats + var _stats = { + heal_points: _initial_heal, + forge_points: _initial_forge, + heal_points_use: _initial_heal - _pool.heal, + forge_points_use: _initial_forge - _pool.forge, + }; + + if (_star_inst != pointer_null) { + point_breakdown.systems[$ _star_inst.name][_p] = _stats; + + // Planet specific logic (Orbit is 0, Planets are 1-4) + if (turn_end && _p > 0 && array_length(_star_inst.p_feature[_p]) > 0) { + var _planet_data = _star_inst.get_planet_data(_p); + _planet_data.recover_starship(_cur_techs); + _planet_data.planet_training(_pool.heal); + } + } else if (_p == 0 && string_pos("ref instance", _cur_loc) > 0) { + _handle_instance_point_recording(_cur_loc, _stats); + } + } + } } diff --git a/scripts/scr_array_functions/scr_array_functions.gml b/scripts/scr_array_functions/scr_array_functions.gml index 193c4877fe..806d25e087 100644 --- a/scripts/scr_array_functions/scr_array_functions.gml +++ b/scripts/scr_array_functions/scr_array_functions.gml @@ -128,13 +128,13 @@ function array_delete_random_index(choice_array) { /// @function array_to_string_list /// @description Converts an array into a string, with each element on a newline. -/// @param {array} stacktrace stacktrace. +/// @param {array} _array stacktrace. /// @return {string} function array_to_string_list(_array, _pop_last = false) { var _string_list = ""; if (!is_array(_array)) { - return; + return _string_list; } if (_pop_last) { diff --git a/scripts/scr_battle_sort/scr_battle_sort.gml b/scripts/scr_battle_sort/scr_battle_sort.gml index ec0dab8d8f..2df63bad59 100644 --- a/scripts/scr_battle_sort/scr_battle_sort.gml +++ b/scripts/scr_battle_sort/scr_battle_sort.gml @@ -9,7 +9,7 @@ function scr_battle_sort() { i -= 1; if ((battles <= i) && (i >= 2) && (battles > 0)) { - if ((battle[i] != 0) && (battle[i - 1] != 0) && (battle_world[i] == -50) && (battle_world[i - 1] > 0)) { + if ((battle[i] != 0) && (battle[i - 1] != 0) && (battle_world[i] == noone) && (battle_world[i - 1] > 0)) { var tem1, tem2, tem3, tem4, tem5, tem6, tem7; tem1 = battle[i - 1]; tem2 = battle_location[i - 1]; diff --git a/scripts/scr_boarding_actions/scr_boarding_actions.gml b/scripts/scr_boarding_actions/scr_boarding_actions.gml index 1fb3a37b37..64934848ee 100644 --- a/scripts/scr_boarding_actions/scr_boarding_actions.gml +++ b/scripts/scr_boarding_actions/scr_boarding_actions.gml @@ -1,9 +1,10 @@ function create_boarding_craft(target_ship) { - var first = 0, o = 1; + var first = 0; for (var o = 0; o < array_length(board_id); o++) { - if ((first == 0) && (board_id[o] != 0) && (board_location[o] == 0)) { + if ((board_id[o] != 0) && (board_location[o] == 0)) { first = o; + break; } } @@ -11,7 +12,6 @@ function create_boarding_craft(target_ship) { var bear = instance_create(x, y, obj_p_assra); bear.apothecary = 0; - o = first; for (var o = 0; o < array_length(board_id); o++) { if ((board_id[o] != 0) && (board_location[o] == 0)) { diff --git a/scripts/scr_buttons/scr_buttons.gml b/scripts/scr_buttons/scr_buttons.gml index a5839b12ce..e3721885e8 100644 --- a/scripts/scr_buttons/scr_buttons.gml +++ b/scripts/scr_buttons/scr_buttons.gml @@ -51,16 +51,16 @@ function standard_loc_data() { /// @function draw_unit_buttons(position, text, size_mod, colour, halign, font, alpha_mult, bg, bg_color) /// @category Draw Helpers /// @description Draws a styled button with text, optional background and hover effects. -/// @param {array} position Either [x, y] or [x1, y1, x2, y2]. -/// @param {string} text Text to display. -/// @param {array} size_mod Text scaling. -/// @param {color} colour Text color. -/// @param {real} _halign Text horizontal alignment. -/// @param {font} font Font resource. -/// @param {real} alpha_mult Alpha multiplier. -/// @param {bool} bg Draw background rectangle. -/// @param {color} bg_color Background color. -/// @returns {array} [x1, y1, x2, y2] bounding box. +/// @param {Array} position Either [x, y] or [x1, y1, x2, y2]. +/// @param {String} text Text to display. +/// @param {Array} size_mod Text scaling. +/// @param {Constant.Color} colour Text color. +/// @param {Constant.HAlign} _halign Text horizontal alignment. +/// @param {Asset.GMFont} font Font resource. +/// @param {Real} alpha_mult Alpha multiplier. +/// @param {Bool} bg Draw background rectangle. +/// @param {Constant.Color} bg_color Background color. +/// @returns {Array} [x1, y1, x2, y2] bounding box. function draw_unit_buttons(position, text, size_mod = [1.5, 1.5], colour = c_gray, _halign = fa_center, font = fnt_40k_14b, alpha_mult = 1, bg = false, bg_color = c_black) { // TODO: fix halign usage add_draw_return_values(); @@ -415,8 +415,7 @@ function LabeledIcon(icon_param, text_param, x1_param = 0, y1_param = 0, data = /// @constructor /// @category UI /// @desc A clickable sprite-based button component that manages its own state and hover logic. -/// @param {Asset.GMSprite} _sprite The default sprite to display. -/// @param {Asset.GMSprite} _hover_sprite Optional sprite to show when hovered. +/// @param {Struct} data Property overrides (sprite, hover_sprite, scale_x/y, alpha_*, etc.). /// @returns {Struct.SpriteButton} function SpriteButton(data) constructor { standard_loc_data(); @@ -449,8 +448,6 @@ function SpriteButton(data) constructor { update(data); /// @desc Updates interaction state and draws the button. - /// @param {real} _x The X position to draw at. - /// @param {real} _y The Y position to draw at. /// @param {bool} _enabled If false, interaction is disabled and the button appears faded. static draw = function(_enabled = true) { diff --git a/scripts/scr_chapter_managent_events/scr_chapter_managent_events.gml b/scripts/scr_chapter_managent_events/scr_chapter_managent_events.gml index 92d9f8caf7..9952151679 100644 --- a/scripts/scr_chapter_managent_events/scr_chapter_managent_events.gml +++ b/scripts/scr_chapter_managent_events/scr_chapter_managent_events.gml @@ -1,9 +1,8 @@ /// @self Asset.GMObject.obj_popup function tech_uprising_event_aftermath() { - var tech, t, i, check_tech, location_techs, location_heretics, delete_positions; - techs = collect_role_group(SPECIALISTS_TECHS); + var techs = collect_role_group(SPECIALISTS_TECHS); var tech_count = array_length(techs); - for (i = 0; i < tech_count; i++) { + for (var i = 0; i < tech_count; i++) { var heretic_data = [ 0, 0, @@ -14,11 +13,11 @@ function tech_uprising_event_aftermath() { 0, 0 ]; - delete_positions = []; - location_techs = []; - location_heretics = []; + var delete_positions = []; + var location_techs = []; + var location_heretics = []; /// @type {Struct.TTRPG_stats} - tech = techs[i]; + var tech = techs[i]; if (tech.has_trait("tech_heretic")) { array_push(location_heretics, tech); heretic_data[0] += tech.weapon_skill; @@ -31,8 +30,8 @@ function tech_uprising_event_aftermath() { loyal_data[2] += tech.ballistic_skill; } //loop techs to fins out which techs are in the same location - for (t = i + 1; t < tech_count; t++) { - check_tech = techs[t].marine_location(); + for (var t = i + 1; t < tech_count; t++) { + var check_tech = techs[t].marine_location(); if (locations_are_equal(tech.marine_location(), check_tech)) { if (techs[t].has_trait("tech_heretic")) { array_push(location_heretics, techs[t]); @@ -49,12 +48,11 @@ function tech_uprising_event_aftermath() { } } if (array_length(location_heretics) > 0 && array_length(location_techs) > 0) { - var purge_target = "none"; + var purge_target = noone; if (press == 0) { - var tal; var heretic_tally = 0; var loyal_tally = 0; - for (tal = 0; tal < 3; tal++) { + for (var tal = 0; tal < 3; tal++) { if (heretic_data[tal] > loyal_data[0]) { heretic_tally++; } else if (heretic_data[tal] < loyal_data[0]) { @@ -66,7 +64,7 @@ function tech_uprising_event_aftermath() { } else if (heretic_tally < loyal_tally) { purge_target = location_heretics; } - if (purge_target == "none") { + if (purge_target == noone) { purge_target = choose(location_heretics, location_techs); } } else if (press == 1) { @@ -74,14 +72,14 @@ function tech_uprising_event_aftermath() { } else if (press == 2) { purge_target = location_heretics; } - if (purge_target != "none") { - for (tal = 0; tal < array_length(purge_target); tal++) { + if (purge_target != noone) { + for (var tal = 0; tal < array_length(purge_target); tal++) { kill_and_recover(purge_target[tal].company, purge_target[tal].marine_number); } } } if (array_length(delete_positions) > 0) { - for (t = array_length(delete_positions) - 1; t >= 0; t--) { + for (var t = array_length(delete_positions) - 1; t >= 0; t--) { array_delete(techs, delete_positions[t], 1); tech_count--; } @@ -140,7 +138,7 @@ function setup_new_forge_master_popup(techs) { } } - for (i = 1; i < array_length(techs); i++) { + for (var i = 1; i < array_length(techs); i++) { if (_pop_data.charisma_pick.charisma < techs[i].charisma) { _pop_data.charisma_pick = techs[i]; } @@ -230,10 +228,10 @@ function new_forge_master_chosen(pick) { } } - if (pick != "none") { + if (pick != noone) { pick.update_role("Forge Master"); - var likability; + var likability = ""; if (dislike <= 5) { likability = "He is generally well liked"; } @@ -276,10 +274,10 @@ function new_forge_master_chosen(pick) { if (pick.company > 0) { for (var i = 1; i < 500; i++) { if (obj_ini.name[0][i] == "") { + scr_move_unit_info(pick.company, 0, pick.marine_number, i); break; } } - scr_move_unit_info(pick.company, 0, pick.marine_number, i); } } } diff --git a/scripts/scr_chapter_new/scr_chapter_new.gml b/scripts/scr_chapter_new/scr_chapter_new.gml index 320f32742d..8b5c7af2af 100644 --- a/scripts/scr_chapter_new/scr_chapter_new.gml +++ b/scripts/scr_chapter_new/scr_chapter_new.gml @@ -6,7 +6,7 @@ function ChapterData() constructor { points = 0; flavor = ""; origin = eCHAPTER_ORIGINS.NONE; - founding = ePROGENITOR.NONE; + founding = eCHAPTERS.UNKNOWN; successors = 0; splash = 0; icon_name = "unknown"; @@ -159,7 +159,6 @@ function ChapterData() constructor { load_result = file_loader.load_struct_from_json_file($"main/chapters/{chapter_id}.json", "chapter", false); } if (!load_result.is_success) { - // LOGGER.error($"No chapter json exits for chapter_id {chapter_id}"); return false; } var json_chapter = load_result.value.chapter; @@ -203,7 +202,6 @@ function scr_chapter_new(chapter_identifier) { //9th captain = relic_master_name //10th captain = recruiter_name - var i = 0; world = array_create(20, ""); world_type = array_create(20, ""); world_feature = array_create(20, ""); diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index 44462b3c5e..832fb30008 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -128,8 +128,8 @@ function check_dead_marines(unit_struct, unit_index) { return unit_lost; } -/// @self Asset.GMObject.obj_pnunit -/// @param {Asset.GMObject.obj_pnunit} target_object +/// @self Id.Instance.obj_pnunit +/// @param {Id.Instance.obj_pnunit} target_object function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position) { // Converts enemy scr_shoot damage into player marine or vehicle casualties. // diff --git a/scripts/scr_company_order/scr_company_order.gml b/scripts/scr_company_order/scr_company_order.gml index f0855871cb..b7996fc3cc 100644 --- a/scripts/scr_company_order/scr_company_order.gml +++ b/scripts/scr_company_order/scr_company_order.gml @@ -22,10 +22,7 @@ function scr_company_order(company) { // This sorts and crunches the marine variables for the company var co = company; - var i = -1; - var _empty_squads = []; - var _squadless = {}; var _roles = active_roles(); @@ -36,9 +33,9 @@ function scr_company_order(company) { // find units not in a _squad //at this point check that all squads have the right types and numbers of units in them - var _squad, wanted_roles; + var wanted_roles; var _squad_ids = get_squad_ids(); - for (i = 0; i < array_length(_squad_ids); i++) { + for (var i = 0; i < array_length(_squad_ids); i++) { var _squad = fetch_squad(_squad_ids[i]); if (_squad.base_company != co) { if (!bool(array_length(_squad.members))) { @@ -69,7 +66,7 @@ function scr_company_order(company) { } } - var _squadless = _squadless_index.turn_to_UnitGroup(); + _squadless = _squadless_index.turn_to_UnitGroup(); if (_squadless.number() > 3) { var _squad_index = _company_marines.index_squads(); @@ -109,25 +106,17 @@ function scr_company_order(company) { var _squads = _company_marines.count_squads("all", true); for (var i = 0; i < array_length(_squads); i++) { - _squad = fetch_squad(_squads[i]); + var _squad = fetch_squad(_squads[i]); _squad.members = []; } var _temps = []; - for (i = 0; i < array_length(_company_marines.units); i++) { + for (var i = 0; i < array_length(_company_marines.units); i++) { var _unit = _company_marines.units[i]; array_push(_temps, {unit: _unit, race: _unit.race(), name: _unit.name(), role: _unit.role(), wep1: _unit.weapon_one(true), wep2: _unit.weapon_two(true), armour: _unit.armour(true), gear: _unit.gear(true), mobi: _unit.mobility_item(true), age: _unit.age(), spe: _unit.specials(), god: _unit.god_status()}); } - //position 2 in role order - /*if (global.chapter_name!="Space Wolves") and (global.chapter_name!="Iron Hands"){ - i=0;repeat(300){i+=1; - if (role[co][i]=_roles[Roles.CHAPLAIN]){v+=1; - temp_marine_variables(co, i ,v); - } - }*/ - - for (i = 0; i < array_length(_temps); i++) { + for (var i = 0; i < array_length(_temps); i++) { var _unit = _temps[i]; var _struc = _unit.unit; TTRPG[co][i] = _struc; @@ -156,21 +145,6 @@ function scr_company_order(company) { } _struc.movement_after_math(co, i, false); } - /* i=0;repeat(300){i+=1; - if (role[co][i]="Death Company"){ - if (string_count("Dreadnought",armour[co][i])>0){v+=1; - temp_marine_variables(co, i ,v); - } - } - } - - i=0;repeat(300){i+=1; - if (role[co][i]="Death Company"){ - if (string_count("Dreadnought",armour[co][i])=0) and (string_count("Terminator",armour[co][i])=0) and (armour[co][i]!="Tartaros"){v+=1; - temp_marine_variables(co, i ,v); - } - } - }*/ } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); } diff --git a/scripts/scr_company_struct/scr_company_struct.gml b/scripts/scr_company_struct/scr_company_struct.gml index 9fcea8a5af..51efe0f984 100644 --- a/scripts/scr_company_struct/scr_company_struct.gml +++ b/scripts/scr_company_struct/scr_company_struct.gml @@ -181,7 +181,7 @@ function CompanyStruct(comp) constructor { _reset_surface = true; } for (var i = 0; i < array_length(_cur_squad.members); i++) { - var _member = _cur_squad.fetch_member(i); + _member = _cur_squad.fetch_member(i); if (_reset_surface) { array_push(squad_draw_surfaces, [_member.uid, _member.draw_unit_image()]); @@ -224,7 +224,7 @@ function CompanyStruct(comp) constructor { } if (is_struct(sprite_draw_delay)) { - var _member = sprite_draw_delay.unit; + _member = sprite_draw_delay.unit; unit_sprite_coords = sprite_draw_delay.draw_coords; var _surface = sprite_draw_delay.unit_surface; _surface.draw_part(unit_sprite_coords.x1, unit_sprite_coords.y1, 0, 0, 166, 231, true); @@ -311,7 +311,7 @@ function CompanyStruct(comp) constructor { if (point_and_click(garrison_but)) { var garrrison_star = find_star_by_name(cur_assignment.location); obj_controller.view_squad = false; - if (garrrison_star != "none") { + if (garrrison_star != noone) { scr_toggle_manage(); obj_controller.x = garrrison_star.x; obj_controller.y = garrrison_star.y; diff --git a/scripts/scr_complex_colour_kit/scr_complex_colour_kit.gml b/scripts/scr_complex_colour_kit/scr_complex_colour_kit.gml index ce09a6bee1..63be9f3f6d 100644 --- a/scripts/scr_complex_colour_kit/scr_complex_colour_kit.gml +++ b/scripts/scr_complex_colour_kit/scr_complex_colour_kit.gml @@ -42,10 +42,10 @@ function setup_complex_livery_shader(setup_role, unit = "none") { shader_set(full_livery_shader); var _in_creation = instance_exists(obj_creation); - + var data_set = {}; var _is_unit = unit != "none"; if (_in_creation) { - var data_set = variable_clone(obj_creation.livery_picker.map_colour); + data_set = variable_clone(obj_creation.livery_picker.map_colour); if (obj_creation.livery_selection_options.current_selection == 2) { var _base = obj_creation.full_liveries[0]; var _component_names = struct_get_names(_base); @@ -62,7 +62,7 @@ function setup_complex_livery_shader(setup_role, unit = "none") { } else { var _full_liveries = obj_ini.full_liveries; var _roles = obj_ini.role[100]; - var data_set = obj_ini.full_liveries[0]; + data_set = obj_ini.full_liveries[0]; if (is_specialist(setup_role, SPECIALISTS_LIBRARIANS)) { data_set = _full_liveries[eROLE.LIBRARIAN]; } else if (is_specialist(setup_role, SPECIALISTS_HEADS)) { @@ -325,7 +325,7 @@ function setup_complex_livery_shader(setup_role, unit = "none") { } main_key = get_marine_icon_set(_data.type); if (sub_key != "" && is_struct(main_key)) { - var _tex_set = variable_clone(main_key[$ sub_key]); + _tex_set = variable_clone(main_key[$ sub_key]); } if (is_struct(_tex_set)) { if (struct_exists(_tex_set, _data.icon)) { @@ -351,20 +351,19 @@ function setup_complex_livery_shader(setup_role, unit = "none") { function get_shader_colour_from_arrays(colour) { var colours_instance = instance_exists(obj_creation) ? obj_creation : obj_controller; + var colour_set = [ + 0, + 0, + 0 + ]; try { - var colour_set = [ + colour_set = [ colours_instance.col_r[colour] / 255, colours_instance.col_g[colour] / 255, colours_instance.col_b[colour] / 255 ]; - } - catch (_exception) { - //ERROR_HANDLER.handle_exception(_exception); - var colour_set = [ - 0, - 0, - 0 - ]; + } catch (_exception) { + ERROR_HANDLER.assert_popup(_exception); } return colour_set; diff --git a/scripts/scr_creation_home_planet_create/scr_creation_home_planet_create.gml b/scripts/scr_creation_home_planet_create/scr_creation_home_planet_create.gml index dbd7932a36..5c9bf0693a 100644 --- a/scripts/scr_creation_home_planet_create/scr_creation_home_planet_create.gml +++ b/scripts/scr_creation_home_planet_create/scr_creation_home_planet_create.gml @@ -29,11 +29,9 @@ function player_recruit_planet_selection() { recruiting = list_traveler(planet_types, recruiting, [1265, 285, 1265 + 32, 285 + 32], [1455, 285, 1455 + 32, 285 + 32]); } - // draw_sprite(spr_planet_splash,_cur_planet_index2,580+333,244); scr_image("ui/planet", _cur_planet_index2, 980 + 333, 244, 128, 128); draw_text_transformed(1044 + 333, 378, recruiting, 0.5, 0.5, 0); - // draw_text_transformed(644+333,398,string(recruiting_name),0.5,0.5,0); if (_recruit_world_type < 2) { recruiting_name = homeworld_name; @@ -42,6 +40,7 @@ function player_recruit_planet_selection() { recruiting_name = global.name_generator.GenerateFromSet("star", false); } } + var name_bad = 0; if ((fleet_type == 1 && _recruit_world_type < 2) && (homeworld_name == recruiting_name)) { name_bad = 1; } @@ -83,7 +82,6 @@ function player_recruit_planet_selection() { draw_unit_buttons(_refresh_rec_name_btn, "?", [1, 1], CM_GREEN_COLOR,, fnt_40k_14b); if (point_and_click(_refresh_rec_name_btn)) { var _new_rec_name = global.name_generator.GenerateFromSet("star", false); - //LOGGER.debug($"regen name of recruiting_name from {recruiting_name} to {_new_rec_name}"); recruiting_name = _new_rec_name; } } @@ -97,8 +95,6 @@ function scr_creation_home_planet_create() { var fleet_type_text = fleet_type == ePLAYER_BASE.HOME_WORLD ? "Homeworld" : "Flagship"; draw_text_transformed(644, 218, fleet_type_text, 0.6, 0.6, 0); - var _cur_planet_index = 0, _cur_planet_index2 = 0, name_bad = 0; - var _cur_planet_index = scr_planet_image_numbers(homeworld); if (fleet_type != 1) { _cur_planet_index = 16; @@ -106,10 +102,8 @@ function scr_creation_home_planet_create() { if (fleet_type == ePLAYER_BASE.HOME_WORLD) { scr_image("ui/planet", _cur_planet_index, 580, 244, 128, 128); - // draw_sprite(spr_planet_splash,_cur_planet_index,580,244); draw_text_transformed(644, 378, homeworld, 0.5, 0.5, 0); - // draw_text_transformed(644,398,string(homeworld_name),0.5,0.5,0); if ((text_selected != "home_name") || (custom != eCHAPTER_TYPE.CUSTOM)) { draw_text_transformed(644, 398, homeworld_name, 0.5, 0.5, 0); } @@ -141,7 +135,6 @@ function scr_creation_home_planet_create() { draw_unit_buttons(_refresh_hw_name_btn, "?", [1, 1], CM_GREEN_COLOR,, fnt_40k_14b); if (point_and_click(_refresh_hw_name_btn)) { var _new_hw_name = global.name_generator.GenerateFromSet("star", false); - //LOGGER.debug($"regen name of homeworld from {homeworld_name} to {_new_hw_name}"); homeworld_name = _new_hw_name; } } @@ -158,11 +151,9 @@ function scr_creation_home_planet_create() { draw_set_font(fnt_40k_30b); } if (fleet_type != ePLAYER_BASE.HOME_WORLD) { - // draw_sprite(spr_planet_splash,_cur_planet_index,580,244); scr_image("ui/planet", _cur_planet_index, 580, 244, 128, 128); draw_text_transformed(644, 378, "Battle Barge", 0.5, 0.5, 0); - // draw_text_transformed(644,398,string(homeworld_name),0.5,0.5,0); if ((text_selected != "flagship_name") || (custom == eCHAPTER_TYPE.PREMADE)) { draw_text_transformed(644, 398, flagship_name, 0.5, 0.5, 0); } @@ -212,7 +203,6 @@ function scr_creation_home_planet_create() { right_data_slate.draw(1210, 5, 0.45, 1); if (recruiting_exists == 0 && homeworld_exists == 1) { - // draw_sprite(spr_planet_splash,_cur_planet_index,580+333,244); scr_image("ui/planet", _cur_planet_index, 580 + 333, 244, 128, 128); draw_set_alpha(0.5); @@ -239,9 +229,6 @@ function scr_creation_home_planet_create() { draw_line(445, 456, 1125, 456); draw_line(445, 457, 1125, 457); - // homeworld_rule=0; - // aspirant_trial=eTRIALS.BLOODDUEL; - draw_set_halign(fa_left); //TODO move to OOP checkboxes diff --git a/scripts/scr_crusade/scr_crusade.gml b/scripts/scr_crusade/scr_crusade.gml index ed9e4ca50a..dc27c3b8f5 100644 --- a/scripts/scr_crusade/scr_crusade.gml +++ b/scripts/scr_crusade/scr_crusade.gml @@ -1,3 +1,4 @@ +/// @self Id.Instance.obj_fleet function scr_crusade() { // Executed to kill the fuck out of the player's marines // Think it is ran in the obj_p_fleet object when arriving back from crusade @@ -89,12 +90,12 @@ function scr_crusade() { death_determination -= 10; } - var dead = false; + var _dead = false; if (death_determination > death_data[0] || death_determination_2 > death_data[1]) { - dead = true; + _dead = true; if (unit.role() == obj_ini.role[100][5]) { if (irandom(20) < unit.luck) { - dead = false; + _dead = false; } else { if (irandom(100) < unit.weapon_skill) { var heroic_deed = choose("holding a breach in imperial defenses allowing allied forces to regroup,", "slaying the enemy leader in glorious combat, while victorious he ultimately succumbed to his wounds,", "leading an imortant boarding mission,",); @@ -107,10 +108,10 @@ function scr_crusade() { } } } else if (unit.role() == obj_ini.role[100][11] || unit.role() == obj_ini.role[100][eROLE.CHAPTERMASTER]) { - dead = false; + _dead = false; } } - if (dead) { + if (_dead) { var man_size = 0; obj_ini.ship_carrying[unit.ship_location] -= unit.get_unit_size(); if (unit.IsSpecialist(SPECIALISTS_STANDARD, true)) { @@ -149,15 +150,11 @@ function scr_crusade() { obj_controller.gene_seed += seed; } - // i=-1; - // repeat(11){ - // i+=1; with (obj_ini) { for (i = 0; i <= 10; i++) { scr_company_order(i); } } - // } if (roll3 <= 10) { artifacts += 1; @@ -220,13 +217,13 @@ function scr_crusade() { //TODO never place the star out of reach of a player fleet, eiter increase allowed response time or find nearer planet function launch_crusade() { var star_id = scr_random_find(2, true, "", ""); - if (star_id == undefined) { + if (star_id == noone) { LOGGER.error("RE: Crusade, couldn't find a star for the crusade"); return false; } else { //TODO decide the target/purpose of the crusade to create more variety and to help with post crusade rewards var _nearest_player_fleet = get_nearest_player_fleet(star_id.x, star_id.y); - if (_nearest_player_fleet == "none") { + if (_nearest_player_fleet == noone) { return false; } var travel_leeway = 10; diff --git a/scripts/scr_culture_visuals/scr_culture_visuals.gml b/scripts/scr_culture_visuals/scr_culture_visuals.gml index d151b148dd..465c41a459 100644 --- a/scripts/scr_culture_visuals/scr_culture_visuals.gml +++ b/scripts/scr_culture_visuals/scr_culture_visuals.gml @@ -107,10 +107,11 @@ function load_vis_set_to_global(directory, data) { if (directory_exists(directory + $"/{_sprite_item.name}")) { var _sprite_direct = directory + $"/{_sprite_item.name}"; + var _new_sprite = undefined; // --- MAIN SPRITE LOADING --- if (file_exists($"{_sprite_direct}/1.png")) { - var _new_sprite = sprite_add(_sprite_direct + "/1.png", 1, 0, 0, 0, 0); + _new_sprite = sprite_add(_sprite_direct + "/1.png", 1, 0, 0, 0, 0); var s = 2; while (file_exists(_sprite_direct + $"/{s}.png")) { var _merge_sprite = sprite_add(_sprite_direct + $"/{s}.png", 1, 0, 0, 0, 0); @@ -1945,9 +1946,10 @@ function DummyMarine() constructor { static armour = function() { var armours = global.list_basic_power_armour; var _last_armour = last_armour; + var _armour = ""; with (obj_creation) { if (!livery_picker.freeze_armour) { - var _armour = armour[100][livery_picker.role_set > 0 ? livery_picker.role_set : eROLE.TACTICAL]; + _armour = armour[100][livery_picker.role_set > 0 ? livery_picker.role_set : eROLE.TACTICAL]; if (array_contains(armours, _armour) || _armour == STR_ANY_POWER_ARMOUR) { _armour = array_random_element(armours); } else if (array_contains(global.list_terminator_armour, _armour) || _armour == STR_ANY_POWER_ARMOUR) { @@ -2188,8 +2190,9 @@ function add_purity_seal_markers() { } function format_weapon_visuals(weapon_name) { + var _weapon_visual_data = {}; if (struct_exists(global.weapon_visual_data, weapon_name)) { - var _weapon_visual_data = global.weapon_visual_data[$ weapon_name]; + _weapon_visual_data = global.weapon_visual_data[$ weapon_name]; } else { return []; } diff --git a/scripts/scr_destroy_planet/scr_destroy_planet.gml b/scripts/scr_destroy_planet/scr_destroy_planet.gml index ab4a9adbc3..3560c67ae3 100644 --- a/scripts/scr_destroy_planet/scr_destroy_planet.gml +++ b/scripts/scr_destroy_planet/scr_destroy_planet.gml @@ -3,17 +3,17 @@ function scr_destroy_planet(destruction_method) { var baid = 0; enemy9 = 0; + var you = noone; + var pip = instance_create(0, 0, obj_popup); if (destruction_method == 2) { - var pip; - pip = instance_create(0, 0, obj_popup); with (pip) { title = "Exterminatus"; image = "exterminatus"; text = "You give the order to fire the Cyclonic Torpedo. After a short descent it lands upon the surface and detonates- the air itself igniting across "; } - var you = obj_star_select.target; + you = obj_star_select.target; pip.text += you.name; pip.text += " " + scr_roman(obj_controller.selecting_planet); baid = obj_controller.selecting_planet; @@ -21,7 +21,6 @@ function scr_destroy_planet(destruction_method) { obj_star_select.torpedo -= 1; enemy9 = you.p_owner[obj_controller.selecting_planet]; } else if (destruction_method == 1) { - var pip = instance_create(0, 0, obj_popup); with (pip) { title = "Exterminatus"; image = "exterminatus"; @@ -31,7 +30,7 @@ function scr_destroy_planet(destruction_method) { } instance_activate_object(obj_star); - var you = battle_object; + you = battle_object; pip.text += planet_numeral_name(obj_ncombat.battle_id, battle_object); baid = obj_ncombat.battle_id; @@ -41,10 +40,9 @@ function scr_destroy_planet(destruction_method) { } // No survivors! - var unit; for (var cah = 0; cah <= obj_ini.companies; cah++) { for (var ed = 0; ed < array_length(obj_ini.role[cah]); ed++) { - unit = fetch_unit([cah, ed]); + var unit = fetch_unit([cah, ed]); if ((unit.location_string == you.name) && (unit.planet_location == baid)) { if (unit.role() == obj_ini.role[100][eROLE.CHAPTERMASTER]) { obj_controller.alarm[7] = 15; @@ -56,7 +54,6 @@ function scr_destroy_planet(destruction_method) { if (obj_ini.race[cah][ed] == 1) { var comm = unit.IsSpecialist(, true); - // if (obj_ini.race[cah,ed]=1) then obj_controller.marines-=1; if (comm == false) { obj_controller.marines -= 1; } diff --git a/scripts/scr_dialogue/scr_dialogue.gml b/scripts/scr_dialogue/scr_dialogue.gml index fb971c6088..80610ceb82 100644 --- a/scripts/scr_dialogue/scr_dialogue.gml +++ b/scripts/scr_dialogue/scr_dialogue.gml @@ -26,7 +26,7 @@ function interpret_diag_string(string_data, data) { // Relationship-based dialogue if (struct_exists(string_data, "relationship")) { - var _string = string_data.relationship[$ data.relationship]; + _string = string_data.relationship[$ data.relationship]; if (is_string(_string)) { return string_interpolate_from_struct(_string, data); } else { @@ -178,8 +178,8 @@ function scr_dialogue(diplo_keyphrase, data = {}) { // Option4 here if all the right conditions are met var born = false; - for (var ii = 1; i <= 200; i++) { - if ((obj_ini.role[0][ii] == obj_ini.role[100][eROLE.CHAPTERMASTER]) && (string_count("$", obj_ini.spe[0][ii]) > 0)) { + for (var i = 1; i <= 200; i++) { + if ((obj_ini.role[0][i] == obj_ini.role[100][eROLE.CHAPTERMASTER]) && (string_count("$", obj_ini.spe[0][i]) > 0)) { born = true; } } @@ -221,10 +221,10 @@ function scr_dialogue(diplo_keyphrase, data = {}) { var _string = $"Stand with me my brothers! Fight for the future of your Chapter, and slay {_master_of_sanct.name()}! [Battle loyalist {global.chapter_name}"; add_diplomacy_option({option_text: _string, goto: "cs_meeting_battle1", goto: "cs_meeting_battle1"}); - var _string = $"{global.chapter_name}, I order you to hold your fire! {_master_of_sanct.name()}, if you doubt my leadership then let it be decided by single combat! [Duel your Master of Sanctity]"; + _string = $"{global.chapter_name}, I order you to hold your fire! {_master_of_sanct.name()}, if you doubt my leadership then let it be decided by single combat! [Duel your Master of Sanctity]"; add_diplomacy_option({option_text: _string, goto: "cs_meeting_battle2"}); - var _string = $"I deny you {obj_controller.faction_leader[eFACTION.CHAOS]}. And now I shall destroy you. For the Emperor! [Attack Chaos forces]"; + _string = $"I deny you {obj_controller.faction_leader[eFACTION.CHAOS]}. And now I shall destroy you. For the Emperor! [Attack Chaos forces]"; add_diplomacy_option({option_text: _string, goto: "cs_meeting_battle5"}); } @@ -331,7 +331,6 @@ function scr_dialogue(diplo_keyphrase, data = {}) { if (diplo_keyphrase == "cs_meeting137") { diplo_text = $"When enough of your warriors have embraced Chaos, assemble them together in one place and then speak with me, and I will show you the beginning of the Eightfold Path. Now, begone.\n[[As you leave he calls out to you one more time.]]\nAnd {obj_ini.master_name}, I expect action within a few years. My patience, unlike Chaos, is not infinite."; complex_event = true; - current_eventing = ""; force_goodbye = 1; faction_status[eFACTION.CHAOS] = "Antagonism"; @@ -368,7 +367,8 @@ function scr_dialogue(diplo_keyphrase, data = {}) { instance_destroy(); } var _found = false; - var _star, _planet; + var _star = noone; + var _planet = noone; with (obj_star) { if (has_problem_star("meeting") > 0 && has_problem_star("meeting") > 0) { _found = true; @@ -381,14 +381,13 @@ function scr_dialogue(diplo_keyphrase, data = {}) { var _master = fetch_unit([0, 0]); if (_master.planet_location > 0) { var _master_star = find_star_by_name(_master.location_string); - if (_master_star != "none") { + if (_master_star != noone) { _found = true; _planet = _master.planet_location; _star = _master_star; } } } - // show_message(string(instance_number(obj_ground_mission))); if (_found) { instance_create(0, 0, obj_ncombat); @@ -2988,7 +2987,7 @@ function scr_dialogue(diplo_keyphrase, data = {}) { instance_destroy(); } with (obj_star) { - for (var i = 1; i <= 4; i++) { + for (var j = 1; j <= 4; j++) { if (planet_feature_bool(p_feature[1], eP_FEATURES.WARLORD10) == 1) { instance_create(x, y, obj_temp5); } @@ -2998,9 +2997,9 @@ function scr_dialogue(diplo_keyphrase, data = {}) { var you, nuum, plan = 0; you = instance_nearest(obj_temp5.x, obj_temp5.y, obj_star); nuum = you.name; - for (var i = 1; i <= you.planets; i++) { + for (var j = 1; j <= you.planets; j++) { if (planet_feature_bool(you.p_feature[1], eP_FEATURES.WARLORD10) == 1) { - plan = i; + plan = j; } } found = 1; @@ -3023,7 +3022,7 @@ function scr_dialogue(diplo_keyphrase, data = {}) { instance_destroy(); } with (obj_star) { - for (var i = 1; i <= 4; i++) { + for (var j = 1; j <= 4; j++) { if (planet_feature_bool(p_feature[1], eP_FEATURES.ORKWARBOSS) == 1) { instance_create(x, y, obj_temp5); } @@ -3033,9 +3032,9 @@ function scr_dialogue(diplo_keyphrase, data = {}) { var you, nuum, plan = 0; you = instance_nearest(obj_temp5.x, obj_temp5.y, obj_star); nuum = you.name; - for (var i = 1; i <= you.planets; i++) { + for (var j = 1; j <= you.planets; j++) { if (planet_feature_bool(you.p_feature[1], eP_FEATURES.ORKWARBOSS) == 1) { - plan = i; + plan = j; } } if (you.p_orks[plan] < 6) { @@ -3101,7 +3100,7 @@ function scr_dialogue(diplo_keyphrase, data = {}) { } var that, good = 0; that = instance_nearest(random(room_width), random(room_height), obj_star); - for (var i = 0; i < 5; i++) { + for (var index = 0; index < 5; index++) { if (good == 0) { with (that) { var j = 0, onceh = 0; @@ -3167,9 +3166,9 @@ function scr_dialogue(diplo_keyphrase, data = {}) { with (that) { var onceh = 0; for (var k = 0; k < 10; k++) { - var i = floor(random(planets)) + 1; - if ((array_length(p_feature[i]) == 0) && (onceh == 0)) { - onceh = i; + var l = floor(random(planets)) + 1; + if ((array_length(p_feature[l]) == 0) && (onceh == 0)) { + onceh = l; } } if (onceh != 0) { diff --git a/scripts/scr_diplomacy_helpers/scr_diplomacy_helpers.gml b/scripts/scr_diplomacy_helpers/scr_diplomacy_helpers.gml index 01ba720870..914a8d87d4 100644 --- a/scripts/scr_diplomacy_helpers/scr_diplomacy_helpers.gml +++ b/scripts/scr_diplomacy_helpers/scr_diplomacy_helpers.gml @@ -238,7 +238,7 @@ function evaluate_chosen_diplomacy_option(diplo_pressed) { } } -function scr_diplomacy_hit(selection, new_path = undefined, complex_path = "none") { +function scr_diplomacy_hit(selection, new_path = undefined, complex_path = undefined) { if (array_length(option_selections) > selection) { if (point_and_click(option_selections[selection])) { if (!is_method(complex_path)) { @@ -277,7 +277,7 @@ function scr_emmisary_diplomacy_routes() { //grab a random librarian var lib = scr_random_marine(SPECIALISTS_LIBRARIANS, 0); if (lib != "none") { - var chapter_master = obj_ini.TTRPG[0][1]; + chapter_master = obj_ini.TTRPG[0][1]; var dead_lib = obj_ini.TTRPG[lib[0]][lib[1]]; pop_up = instance_create(0, 0, obj_popup); pop_up.title = "Skull for the Skull Throne"; @@ -308,9 +308,6 @@ function scr_emmisary_diplomacy_routes() { pop_up.text = $"You summon {dead_champ.name_role()} to your personal chambers. Darting from the shadows towards {dead_champ.name()} who is a cunning warrior and reacts with precision to your attack, however eventually you prevail and strike him down. With the flesh removed from his skull you place it upon a hastily erected shrine."; pop_up.type = 98; pop_up.image = "chaos"; - // obj_duel = instance_create(0,0,obj_duel); - // obj_duel.title = "Ambush Champion"; - // pop.type="duel"; kill_and_recover(champ[0], champ[1]); } else { diplomacy_pathway = "daemon_scorn"; diff --git a/scripts/scr_draw_management_unit/scr_draw_management_unit.gml b/scripts/scr_draw_management_unit/scr_draw_management_unit.gml index ddbf2f4d5a..9b93b7bfe6 100644 --- a/scripts/scr_draw_management_unit/scr_draw_management_unit.gml +++ b/scripts/scr_draw_management_unit/scr_draw_management_unit.gml @@ -1,13 +1,15 @@ /// @self Asset.GMObject.obj_controller function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_lock = false) { var assignment = "none"; - var _unit; + var _unit = noone; var string_role = ""; var health_string = ""; var eventing = false; var jailed = false; var impossible = !is_struct(display_unit[selected]) && !is_array(display_unit[selected]); var is_man = false; + var unit_location_string = ""; + var unit_specialist = false; if (man[selected] == "man" && is_struct(display_unit[selected])) { is_man = true; _unit = display_unit[selected]; @@ -32,8 +34,7 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l return "continue"; } } - var unit_specialist = is_specialist(_unit.role()); - var unit_location_string = ""; + unit_specialist = is_specialist(_unit.role()); if (_unit.in_jail()) { jailed = true; unit_location_string = "=Penitorium="; @@ -68,8 +69,6 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l if (draw) { health_string = ma_health_string[selected]; - var exp_string = $"{round(ma_exp[selected])} EXP"; - ma_ar = ""; ma_we1 = ""; ma_we2 = ""; @@ -105,7 +104,6 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l } } } else if (man[selected] == "vehicle" && is_array(display_unit[selected]) && draw) { - // string_role="v "+string(managing)+"."+string(ide[selected]); string_role = string(ma_role[selected]); unit_location_string = string(ma_loc[selected]); @@ -116,7 +114,6 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l unit_location_string = obj_ini.ship[ma_lid[selected]]; } health_string = string(round(ma_health[selected])) + "% HP"; - exp_string = ""; // Need abbreviations here ma_ar = ""; @@ -150,7 +147,6 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l if (ma_wep2[selected] != "") { ma_we2 = gear_weapon_data("weapon", ma_wep2[selected], "abbreviation"); ma_we2 = is_string(ma_we2) ? ma_we2 : ""; - // temp5=string(ma_wep1[selected])+", "+string(ma_wep2[selected])+" + "+string(ma_gear[selected]); } } @@ -174,13 +170,13 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l draw_set_alpha(1); draw_rectangle(xx + 25, yy + 64, xx + 974, yy + 85, 1); if (man[selected] == "man" && is_struct(display_unit[selected])) { - var _unit = display_unit[selected]; + _unit = display_unit[selected]; var _is_rank_file = is_specialist(_unit.role(), SPECIALISTS_RANK_AND_FILE); if (_is_rank_file) { var _role = _unit.role(); var _experience = _unit.experience; - var _data, valid = false; + var _data; var _circle_coords = [ xx + 321, yy + 77 @@ -298,8 +294,6 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l } draw_line(xx + 25 + 8, yy + 64, xx + 25 + 8, yy + 85); - // was 885 - // 974 if ((man[selected] == "man") && (ma_ar == "")) { draw_set_alpha(0.5); @@ -312,6 +306,7 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l } } + var exp_string = $"{round(ma_exp[selected])} EXP"; var hpText = [ xx + 240 + 8, yy + 66, @@ -360,8 +355,7 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l draw_sprite(spr_loc_icon, 2, xx + 427 + 8, yy + 66); } else { if (man[selected] == "man") { - c = managing <= 10 ? managing : 0; - var _unit = display_unit[selected]; + _unit = display_unit[selected]; if ((ma_lid[selected] > -1) && (ma_wid[selected] == 0)) { draw_sprite(spr_loc_icon, _unit.is_boarder ? 2 : 1, xx + 427 + 8, yy + 66); diff --git a/scripts/scr_draw_unit_stat_data/scr_draw_unit_stat_data.gml b/scripts/scr_draw_unit_stat_data/scr_draw_unit_stat_data.gml index 8f279cde8c..efb3eccebb 100644 --- a/scripts/scr_draw_unit_stat_data/scr_draw_unit_stat_data.gml +++ b/scripts/scr_draw_unit_stat_data/scr_draw_unit_stat_data.gml @@ -1,18 +1,15 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information function scr_draw_unit_stat_data(manage = false, data_block = {x1: 1008, y1: 520, w: 569, h: 303}, squeezed = false) { var _cur_font = draw_get_font(); draw_set_font(fnt_40k_14); + var xx = camera_get_view_x(view_camera[0]); + var yy = camera_get_view_y(view_camera[0]); if (event_number == ev_gui) { xx = 0; yy = 0; - } else { - var xx = camera_get_view_x(view_camera[0]); - var yy = camera_get_view_y(view_camera[0]); } - var stat_tool_tips = []; - var trait_tool_tips = []; - var unit_name = name(); + var _stat_tool_tips = []; + var _trait_tool_tips = []; + var _unit_name = self.name(); if (psionic < 0) { var _psy_levels = global.arr_negative_psy_levels; var _psionic_assignment = _psy_levels[psionic * -1]; @@ -27,7 +24,7 @@ function scr_draw_unit_stat_data(manage = false, data_block = {x1: 1008, y1: 520 data_block.x_mid = (data_block.x1 + data_block.x2) / 2; data_block.y_mid = (data_block.y1 + data_block.y2) / 2; - var attribute_box = { + var _attribute_box = { x1: data_block.x1 + (squeezed ? 42 : 84), y1: data_block.y1 + 8, w: 32, @@ -39,10 +36,10 @@ function scr_draw_unit_stat_data(manage = false, data_block = {x1: 1008, y1: 520 draw_rectangle(x1, y1, x2, y2, outline); }, }; - attribute_box.x2 = attribute_box.x1 + attribute_box.w; - attribute_box.y2 = attribute_box.y1 + attribute_box.h; - attribute_box.x_mid = (attribute_box.x1 + attribute_box.x2) / 2; - attribute_box.y_mid = (attribute_box.y1 + attribute_box.y2) / 2; + _attribute_box.x2 = _attribute_box.x1 + _attribute_box.w; + _attribute_box.y2 = _attribute_box.y1 + _attribute_box.h; + _attribute_box.x_mid = (_attribute_box.x1 + _attribute_box.x2) / 2; + _attribute_box.y_mid = (_attribute_box.y1 + _attribute_box.y2) / 2; stat_display_list = [ [ @@ -90,221 +87,153 @@ function scr_draw_unit_stat_data(manage = false, data_block = {x1: 1008, y1: 520 "charisma" ] ]; - // draw_set_color(c_gray); - // draw_rectangle(stat_block.x1,stat_block.y1, stat_block.x1 + (36*array_length(stat_display_list)), stat_block.y1+48+8, 0) - // draw_set_color(c_black); - // draw_rectangle(stat_block.x1,stat_block.y1, stat_block.x1 + (4*array_length(stat_display_list)), stat_block.y1+48+4, 1) - var viewing_stat, icon_colour; for (var i = 0; i < array_length(stat_display_list); i++) { - var stat_data = stat_display_list[i]; - var stat_key = stat_data[1]; - var stat_abbreviation = global.stat_shorts[$ stat_key]; - var _stat_name = global.stat_display_strings[$ stat_key]; - var _icon = global.stat_icons[$ stat_key]; - var _stat_description = stat_data[0]; - var _stat_col = global.stat_display_colour[$ stat_key]; - - if (attribute_box.enter()) { - icon_colour = c_white; + var _stat_data = stat_display_list[i]; + var _stat_key = _stat_data[1]; + var _stat_abbreviation = global.stat_shorts[$ _stat_key]; + var _stat_name = global.stat_display_strings[$ _stat_key]; + var _icon = global.stat_icons[$ _stat_key]; + var _stat_description = _stat_data[0]; + var _stat_col = global.stat_display_colour[$ _stat_key]; + var _icon_colour = c_gray; + + if (_attribute_box.enter()) { + _icon_colour = c_white; draw_set_color(_stat_col); - attribute_box.draw(false); - } else { - icon_colour = c_gray; + _attribute_box.draw(false); } - //draw_rectangle(stat_square.x1-1,stat_square.y1-1,stat_square.x1+33,stat_square.y1+49, 1); draw_set_color(c_gray); - attribute_box.draw(true); - draw_sprite_ext(_icon, 0, attribute_box.x1, attribute_box.y1, 0.5, 0.5, 0, icon_colour, 1); + _attribute_box.draw(true); + draw_sprite_ext(_icon, 0, _attribute_box.x1, _attribute_box.y1, 0.5, 0.5, 0, _icon_colour, 1); draw_set_color(#50a076); draw_set_halign(fa_center); - draw_text((attribute_box.x1 + attribute_box.x2) / 2, attribute_box.y1 + 32, $"{self[$ stat_key]}"); + draw_text((_attribute_box.x1 + _attribute_box.x2) / 2, _attribute_box.y1 + 32, $"{self[$ _stat_key]}"); draw_set_halign(fa_left); if (manage) { - if (point_and_click([attribute_box.x1, attribute_box.y1, attribute_box.x2, attribute_box.y1 + 45])) { - filter_and_sort_company("stat", stat_key); + if (point_and_click([_attribute_box.x1, _attribute_box.y1, _attribute_box.x2, _attribute_box.y1 + 45])) { + filter_and_sort_company("stat", _stat_key); obj_controller.unit_bio = false; } } var stat_percentage = 0; if (is_struct(obj_controller.temp[122])) { - if (struct_exists(obj_controller.temp[122], stat_key)) { - stat_percentage = obj_controller.temp[122][$ stat_key]; + if (struct_exists(obj_controller.temp[122], _stat_key)) { + stat_percentage = obj_controller.temp[122][$ _stat_key]; } } var _final_string = $"{_stat_description} #Click to order by highest {_stat_name}#{stat_percentage}% chance of growth"; - array_push(stat_tool_tips, [attribute_box.x1, attribute_box.y1, attribute_box.x2, attribute_box.y2, _final_string, $"{_stat_name} ({stat_abbreviation})"]); - attribute_box.x1 += 36; - attribute_box.x2 += 36; + array_push(_stat_tool_tips, [_attribute_box.x1, _attribute_box.y1, _attribute_box.x2, _attribute_box.y2, _final_string, $"{_stat_name} ({_stat_abbreviation})"]); + _attribute_box.x1 += 36; + _attribute_box.x2 += 36; } - // var data_block.x_mid = stats_block.x1+((attribute_box.x1 - stats_block.x1)/2); - // var data_block.y_mid = attribute_box.y2+4; - - // draw_set_color(c_gray); - // draw_rectangle(data_block.x_mid-70,data_block.y_mid, data_block.x_mid+67, data_block.y_mid+70, 0); - // draw_set_color(c_black); - // draw_rectangle(data_block.x_mid-66,data_block.y_mid+1, data_block.x_mid-1, data_block.y_mid+65, 1); - // draw_rectangle(data_block.x_mid-66,data_block.y_mid,data_block.x_mid-1,data_block.y_mid+64, 0); - - // var psy_box = { - // x1: attribute_box.x2-36, - // y1: attribute_box.y1, - // w: attribute_box.w, - // h: attribute_box.h, - // } - // psy_box.x2 = psy_box.x1 + psy_box.w; - // psy_box.y2 = psy_box.y1 + psy_box.h; - // psy_box.x_mid = (psy_box.x1 + psy_box.x2) / 2; - // psy_box.y_mid = (psy_box.y1 + psy_box.y2) / 2; - // draw_set_color(c_gray); - // draw_rectangle(psy_box.x1,psy_box.y1,psy_box.x2,psy_box.y2, 1); - // draw_set_color(c_white); - // draw_sprite_stretched(spr_warp_level_icon, 2, psy_box.x1, psy_box.y1, psy_box.w, psy_box.h); - // draw_set_halign(fa_center); - // draw_set_valign(fa_middle); - // draw_text(psy_box.x_mid, psy_box.y_mid+3, $"{psionic}") - // var assignment_description = "The Imperium measures and records the psionic activity and power level of psychic individuals through a rating system called The Assignment. Comprised of a twenty-four point scale, The Assignment simplifies the comparison of psykers to aid Imperial authorities in recognizing possible threats."; - // array_push(stat_tool_tips, [psy_box.x1, psy_box.y1, psy_box.x2, psy_box.y2, assignment_description, "The Assignment"]); - - // var forge_box = { - // x1: attribute_box.x2, - // y1: attribute_box.y1, - // w: attribute_box.w, - // h: attribute_box.h, - // } - // forge_box.x2 = forge_box.x1 + forge_box.w; - // forge_box.y2 = forge_box.y1 + forge_box.h; - // forge_box.x_mid = (forge_box.x1 + forge_box.x2) / 2; - // forge_box.y_mid = (forge_box.y1 + forge_box.y2) / 2; - // //draw_rectangle(data_block.x_mid+1,data_block.y_mid+2,data_block.x_mid+1,data_block.y_mid+34, 0); - // var is_forge = IsSpecialist(SPECIALISTS_TECHS); - // if (is_forge){ - // draw_set_color(c_gray); - // draw_rectangle(forge_box.x1,forge_box.y1,forge_box.x2,forge_box.y2, 1); - // draw_set_color(c_white); - // draw_sprite_stretched(spr_forge_points_icon, 1, forge_box.x1-6, forge_box.y1-4, forge_box.w+12, forge_box.h+8); - // draw_set_halign(fa_center); - // draw_set_valign(fa_middle); - // draw_text(forge_box.x_mid, forge_box.y_mid, $"{forge_point_generation()[0]}"); - // var forge_description = ""; - // array_push(stat_tool_tips, [forge_box.x1,forge_box.y1,forge_box.x2,forge_box.y2, $"{forge_point_generation()}", "Craftsmanship"]); - // } - - //var warp_box_size = tooltip_draw(stat_square.x1,stat_square.y1+56,$"Warp Level:{psionic}"); - //draw_set_color(c_red); - //if (IsSpecialist(SPECIALISTS_TECHS)){ - // tooltip_draw(stat_square.x1,stat_square.y1+45+warp_box_size[1],$"Forge Points:{forge_point_generation()}"); - //} - // draw_line(stat_block.x1, yy+519, stat_block.x1, yy+957); - // draw_line(stat_square.x1, yy+519, stat_square.x1, yy+957); - draw_set_halign(fa_left); draw_set_valign(fa_top); draw_set_color(#50a076); if (!obj_controller.view_squad && obj_controller.unit_bio) { - var unit_data_string = unit_profile_text(); - tooltip_draw(unit_data_string, 925, [xx + 23, yy + 141],,,,, true); + var _unit_data_string = unit_profile_text(); + tooltip_draw(_unit_data_string, 925, [xx + 23, yy + 141],,,,, true); } - var data_lines = []; - var data_entry = {}; - data_entry.text = $"Loyalty: {loyalty}\n"; - data_entry.tooltip = "Loyalty represents the unwavering devotion to one's Chapter, their Primarch, and the Emperor himself. It is a measure of their ability to resist the temptations of Chaos, the influence of xenos artifacts, and the machinations of the Warp."; - array_push(data_lines, data_entry); - - data_entry = {}; - data_entry.text = $"Corruption: {corruption}\n"; - data_entry.tooltip = "Corruption reflects exposure to the malevolent forces of the Warp. High Corruption may indicate that the person is teetering on the brink of damnation, while a low score suggests relative purity."; - array_push(data_lines, data_entry); - - data_entry = {}; - data_entry.text = $"Assignment: {_psionic_assignment} ({psionic})\n"; - data_entry.tooltip = "The Imperium measures and records the psionic activity and power level of psychic individuals through a rating system called The Assignment. Comprised of a twenty-four point scale, The Assignment simplifies the comparison of psykers to aid Imperial authorities in recognizing possible threats."; - array_push(data_lines, data_entry); - - var forge_gen = forge_point_generation(); - - data_entry = {}; - data_entry.tooltip = ""; - var gen_reasons = forge_gen[1]; - data_entry.text = $"Forge Production: {forge_gen[0]}\n"; - if (struct_exists(gen_reasons, "trained")) { - data_entry.tooltip += $"Trained On Mars (TEC/10): {gen_reasons.trained}\n"; - if (struct_exists(gen_reasons, "at_forge")) { - data_entry.tooltip += $"{gen_reasons.at_forge}(at Forge)\n"; + var _data_lines = []; + var _data_entry = {}; + _data_entry.text = $"Loyalty: {loyalty}\n"; + _data_entry.tooltip = "Loyalty represents the unwavering devotion to one's Chapter, their Primarch, and the Emperor himself. It is a measure of their ability to resist the temptations of Chaos, the influence of xenos artifacts, and the machinations of the Warp."; + array_push(_data_lines, _data_entry); + + _data_entry = {}; + _data_entry.text = $"Corruption: {corruption}\n"; + _data_entry.tooltip = "Corruption reflects exposure to the malevolent forces of the Warp. High Corruption may indicate that the person is teetering on the brink of damnation, while a low score suggests relative purity."; + array_push(_data_lines, _data_entry); + + _data_entry = {}; + _data_entry.text = $"Assignment: {_psionic_assignment} ({psionic})\n"; + _data_entry.tooltip = "The Imperium measures and records the psionic activity and power level of psychic individuals through a rating system called The Assignment. Comprised of a twenty-four point scale, The Assignment simplifies the comparison of psykers to aid Imperial authorities in recognizing possible threats."; + array_push(_data_lines, _data_entry); + + var _forge_gen = forge_point_generation(); + + _data_entry = {}; + _data_entry.tooltip = ""; + var _gen_reasons = _forge_gen[1]; + _data_entry.text = $"Forge Production: {_forge_gen[0]}\n"; + if (struct_exists(_gen_reasons, "trained")) { + _data_entry.tooltip += $"Trained On Mars (TEC/10): {_gen_reasons.trained}\n"; + if (struct_exists(_gen_reasons, "at_forge")) { + _data_entry.tooltip += $"{_gen_reasons.at_forge}(at Forge)\n"; } } - if (struct_exists(gen_reasons, "master")) { - data_entry.tooltip += $"Forge Master: +{gen_reasons.master}\n"; + if (struct_exists(_gen_reasons, "master")) { + _data_entry.tooltip += $"Forge Master: +{_gen_reasons.master}\n"; } - if (struct_exists(gen_reasons, "crafter")) { - data_entry.tooltip += $"Crafter: +{gen_reasons.crafter}\n"; + if (struct_exists(_gen_reasons, "crafter")) { + _data_entry.tooltip += $"Crafter: +{_gen_reasons.crafter}\n"; } - if (struct_exists(gen_reasons, "maintenance")) { - data_entry.tooltip += $"Maintenance: {gen_reasons.maintenance}"; + if (struct_exists(_gen_reasons, "maintenance")) { + _data_entry.tooltip += $"Maintenance: {_gen_reasons.maintenance}"; } - array_push(data_lines, data_entry); + array_push(_data_lines, _data_entry); - for (var i = 0; i < array_length(data_lines); i++) { - draw_text(data_block.x1 + 16, attribute_box.y2 + 16 + (i * 24), data_lines[i].text); // Adjust the y-coordinate for the new line - array_push(stat_tool_tips, [data_block.x1 + 16, attribute_box.y2 + 16 + (i * 24), data_block.x1 + 16 + string_width(data_lines[i].text), attribute_box.y2 + 16 + (i * 24) + string_height(data_lines[i].text), data_lines[i].tooltip, ""]); + for (var i = 0; i < array_length(_data_lines); i++) { + draw_text(data_block.x1 + 16, _attribute_box.y2 + 16 + (i * 24), _data_lines[i].text); // Adjust the y-coordinate for the new line + array_push(_stat_tool_tips, [data_block.x1 + 16, _attribute_box.y2 + 16 + (i * 24), data_block.x1 + 16 + string_width(_data_lines[i].text), _attribute_box.y2 + 16 + (i * 24) + string_height(_data_lines[i].text), _data_lines[i].tooltip, ""]); } var x1 = squeezed ? data_block.x1 + ((data_block.x2 - data_block.x1) / 2) + 32 : data_block.x2 - 16; if (array_length(traits) != 0) { for (var i = 0; i < array_length(traits); i++) { - var trait = global.trait_list[$ traits[i]]; - var trait_name = trait.display_name; - var trait_description = string(trait.flavour_text, unit_name); - var trait_effect = ""; - if (struct_exists(trait, "effect")) { - trait_effect = string(trait.effect + "." + "\n\n"); + var _trait = global.trait_list[$ traits[i]]; + var _trait_name = _trait.display_name; + var _trait_description = string(_trait.flavour_text, _unit_name); + var _trait_effect = ""; + if (struct_exists(_trait, "effect")) { + _trait_effect = string(_trait.effect + "." + "\n\n"); } - var y1 = attribute_box.y2 + 16 + (i * 24); + var y1 = _attribute_box.y2 + 16 + (i * 24); draw_set_halign(fa_right); - draw_text(x1, y1, trait_name); + draw_text(x1, y1, _trait_name); draw_set_halign(fa_left); - var x2 = x1 - string_width(trait_name); - var y2 = y1 + string_height(trait_name); + var x2 = x1 - string_width(_trait_name); + var y2 = y1 + string_height(_trait_name); var _trait_growth_effect = ""; var _stat_list = global.stat_list; for (var j = 0; j < array_length(_stat_list); j++) { var _stat = _stat_list[j]; var _stat_name = global.stat_display_strings[$ _stat]; - if (struct_exists(trait, _stat)) { - var _stat_val = eval_trait_stat_data(trait[$ _stat]); - var descriptive_string = ""; + if (struct_exists(_trait, _stat)) { + var _stat_val = eval_trait_stat_data(_trait[$ _stat]); + var _descriptive_string = ""; if (_stat_val > 0) { repeat (max(floor(_stat_val / 2), 1)) { - descriptive_string += "+"; + _descriptive_string += "+"; } } else { repeat (max(floor((_stat_val * -1) / 2), 1)) { - descriptive_string += "-"; + _descriptive_string += "-"; } } - _trait_growth_effect += $"{_stat_name} : {descriptive_string}\n"; + _trait_growth_effect += $"{_stat_name} : {_descriptive_string}\n"; } } - array_push(trait_tool_tips, [x1, y1, x2, y2, $"{trait_description}\n{trait_effect}\n{_trait_growth_effect}" + trait_effect]); + array_push(_trait_tool_tips, [x1, y1, x2, y2, $"{_trait_description}\n{_trait_effect}\n{_trait_growth_effect}" + _trait_effect]); } } else { draw_set_halign(fa_right); - draw_text(data_block.x2 - 16, attribute_box.y2 + 16, "No Traits"); + draw_text(data_block.x2 - 16, _attribute_box.y2 + 16, "No Traits"); draw_set_halign(fa_left); } - for (var i = 0; i < array_length(stat_tool_tips); i++) { - if (scr_hit(stat_tool_tips[i])) { - tooltip_draw(stat_tool_tips[i][4], 300, [stat_tool_tips[i][0], stat_tool_tips[i][3]],,, stat_tool_tips[i][5]); + for (var i = 0; i < array_length(_stat_tool_tips); i++) { + if (scr_hit(_stat_tool_tips[i])) { + tooltip_draw(_stat_tool_tips[i][4], 300, [_stat_tool_tips[i][0], _stat_tool_tips[i][3]],,, _stat_tool_tips[i][5]); } } - for (var i = 0; i < array_length(trait_tool_tips); i++) { - if (point_in_rectangle(mouse_x, mouse_y, trait_tool_tips[i][2], trait_tool_tips[i][1], trait_tool_tips[i][0], trait_tool_tips[i][3])) { - tooltip_draw(trait_tool_tips[i][4], 300); + for (var i = 0; i < array_length(_trait_tool_tips); i++) { + if (point_in_rectangle(mouse_x, mouse_y, _trait_tool_tips[i][2], _trait_tool_tips[i][1], _trait_tool_tips[i][0], _trait_tool_tips[i][3])) { + tooltip_draw(_trait_tool_tips[i][4], 300); } } diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index 2f513d4e65..f7d54123b1 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -22,9 +22,6 @@ function drop_select_unit_selection() { if (purge == eDROP_TYPE.RAIDATTACK) { draw_set_font(fnt_40k_30b); - - // var xx,yy; - // xx=view_xview[0]+545;yy=view_yview[0]+212; draw_set_halign(fa_left); draw_set_color(c_gray); var attack_type = attack ? "Attacking" : "Raiding"; @@ -147,12 +144,11 @@ function drop_select_unit_selection() { _x_offset += _button.width + 10; } - // draw_text(x2 + 14, y2 + 352, string_hash_to_newline("Selection: " + string(smin) + "/" + string(smax))); - // Target var race_quantity = 0; if (purge == eDROP_TYPE.RAIDATTACK) { - var target_race = "", target_threat = "", race_quantity = 0; + var target_race = ""; + var target_threat = ""; if (attacking >= 5 && attacking <= 13) { race_quantity = race_quantities[attacking - 4]; @@ -235,7 +231,7 @@ function drop_select_unit_selection() { instance_activate_object(obj_drop_select); // 135 ; temporary balancing - if (sh_target != -50) { + if (sh_target != noone) { sh_target.acted += 1; } @@ -435,7 +431,7 @@ function drop_select_draw() { draw_text_transformed(x2 + 14, y2 + 12, string(_purge_strings[purge - 2], _planet_string), 0.6, 0.6, 0); // Disposition here - var succession = 0, pp = planet_number; + var pp = planet_number; var succession = has_problem_planet(pp, "succession", p_target); @@ -501,7 +497,7 @@ function collect_local_units() { purge_d = ship_max[500]; if (purge == 1) { - if (sh_target != -50) { + if (sh_target != noone) { max_ships = sh_target.capital_number + sh_target.frigate_number + sh_target.escort_number; if (sh_target.acted >= 1) { diff --git a/scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml b/scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml index 74039d9832..88fc4e9775 100644 --- a/scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml +++ b/scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml @@ -1,8 +1,8 @@ /// @self Asset.GMObject.obj_star function scr_enemy_ai_a() { + var _garrison = noone; for (var i = 1; i <= planets; i++) { - var _ops = p_operatives[i]; - var _garrison = get_garrison(i); + _garrison = get_garrison(i); _garrison.increase_time_on_planet(); get_sabatours(i); get_planet_data(i); @@ -458,10 +458,9 @@ function scr_enemy_ai_a() { } if (guard_attack == "pdf") { + var pdf_mod = irandom(5) + 1; if (pdf_with_player) { pdf_mod = irandom_range(1, 6 + _garrison.total_garrison * 0.1); - } else { - pdf_mod = irandom(5) + 1; } rand1 = (choose(3, 4, 5, 6) * guard_score) * choose(1, 1.25, 1.25); rand2 = (pdf_mod * pdf_score) * choose(1, 1.25); @@ -489,7 +488,7 @@ function scr_enemy_ai_a() { if (_planet_data.population_influences[eFACTION.TYRANIDS] > 50 && _planet_data.has_feature(eP_FEATURES.GENE_STEALER_CULT)) { var _cur_influ = p_influence[_run][eFACTION.TYRANIDS]; var _influence_reduction = _cur_influ * (p_pdf[_run] / _pdf_before); - adjust_influence(eFACTION.TYRANIDS, -min(_influence_reduction, _cur_influ - 3), _run); + adjust_influence(eFACTION.TYRANIDS, -min(_influence_reduction, _cur_influ - 3), _run, self); if (p_influence[_run][eFACTION.TYRANIDS] < 20) { _planet_data.delete_feature(eP_FEATURES.GENE_STEALER_CULT); } @@ -1190,7 +1189,7 @@ function scr_enemy_ai_a() { if (p_tyranids[_run] != after_combat_tyranids) { p_tyranids[_run] = after_combat_tyranids; if (_planet_data.has_feature(eP_FEATURES.GENE_STEALER_CULT)) { - adjust_influence(eFACTION.TYRANIDS, -min(p_influence[_run][eFACTION.TYRANIDS] - 4, 5), _run); + adjust_influence(eFACTION.TYRANIDS, -min(p_influence[_run][eFACTION.TYRANIDS] - 4, 5), _run, self); var _cult = _planet_data.get_features(eP_FEATURES.GENE_STEALER_CULT)[0]; if (p_influence[_run][eFACTION.TYRANIDS] < 5) { _cult.hiding = true; @@ -1228,7 +1227,7 @@ function scr_enemy_ai_a() { who_cleansed = "Gene Stealer Cult"; make_alert = true; delete_features(p_feature[_run], eP_FEATURES.GENE_STEALER_CULT); - adjust_influence(eFACTION.TYRANIDS, -25, _run); + adjust_influence(eFACTION.TYRANIDS, -25, _run, self); } if (make_alert) { if (p_first[_run] == 1) { diff --git a/scripts/scr_enemy_ai_b/scr_enemy_ai_b.gml b/scripts/scr_enemy_ai_b/scr_enemy_ai_b.gml index 0d67059886..abc912ea51 100644 --- a/scripts/scr_enemy_ai_b/scr_enemy_ai_b.gml +++ b/scripts/scr_enemy_ai_b/scr_enemy_ai_b.gml @@ -3,39 +3,35 @@ function scr_enemy_ai_b() { // Imperial Repleneshes numbers // If no enemies and guard < pop /470 then increase guardsman // If no enemies and population < max_pop then increase by like 1% - var rando = 0, success = false, i = 0, is_garrison_force = false, total_garrison = 0, sabotage_force = false; - - i = 0; - for (i = 1; i <= planets; i++) { - system_datas[i].refresh_data(); - system_datas[i].end_of_turn_population_influence_and_enemy_growth(); - // if (p_heresy[i]>0) and (owner != eFACTION.CHAOS) then p_heresy[i]-=2; + for (var i = 1; i <= planets; i++) { + system_datas[i].refresh_data(); + system_datas[i].end_of_turn_population_influence_and_enemy_growth(); } // Tau rebellions if ((present_fleet[8] >= 1) && (owner != eFACTION.TAU)) { - var flit, ran1, ran2, tau_chance; - flit = scr_orbiting_fleet(eFACTION.TAU); - ran1 = 0; - ran2 = floor(random(planets)) + 1; + var tau_chance; + var flit = scr_orbiting_fleet(eFACTION.TAU); + var ran1 = 0; + var ran2 = floor(random(planets)) + 1; - if (flit != "none") { + if (flit != noone) { ran1 = floor(random(100)) + 1; var tau_influence = p_influence[ran2][eFACTION.TAU]; if (tau_influence < 90 && (p_type[ran2] != "Dead")) { if ((flit.image_index == 1) && (ran1 <= 90)) { - adjust_influence(eFACTION.TAU, choose(2, 3), ran2); + adjust_influence(eFACTION.TAU, choose(2, 3), ran2, self); if ((p_type[ran2] == "Forge") && (tau_influence >= 3)) { - adjust_influence(eFACTION.TAU, -3, ran2); + adjust_influence(eFACTION.TAU, -3, ran2, self); } } else if ((flit.image_index > 1) && (flit.image_index < 4) && (ran1 <= 90)) { - adjust_influence(eFACTION.TAU, choose(7, 9, 11, 13), ran2); + adjust_influence(eFACTION.TAU, choose(7, 9, 11, 13), ran2, self); if ((p_type[ran2] == "Forge") && (tau_influence >= 10)) { - adjust_influence(eFACTION.TAU, -10, ran2); + adjust_influence(eFACTION.TAU, -10, ran2, self); } } else if (flit.image_index >= 4) { - adjust_influence(eFACTION.TAU, choose(9, 11, 13, 15, 17), ran2); + adjust_influence(eFACTION.TAU, choose(9, 11, 13, 15, 17), ran2, self); if ((p_type[ran2] == "Forge") && (tau_influence >= 13)) { - adjust_influence(eFACTION.TAU, -13, ran2); + adjust_influence(eFACTION.TAU, -13, ran2, self); } } } @@ -44,7 +40,7 @@ function scr_enemy_ai_b() { } } - for (i = 1; i <= planets; i++) { + for (var i = 1; i <= planets; i++) { var tau_influence = p_influence[i][eFACTION.TAU]; tau_chance = floor(random(100)) + 1; @@ -55,14 +51,10 @@ function scr_enemy_ai_b() { } } - if (flit != "none" && flit.owner == eFACTION.TAU) { + if (flit != noone && flit.owner == eFACTION.TAU) { tau_chance += (flit.image_index * 5) - 5; } - if (tau_chance >= 95) { - /*obj_controller.x=self.x;obj_controller.y=self.y;show_message(string(tau_chance)+" |"+string(p_orks[i])+"|"+string(p_traitors[i]));*/ - } - if ((tau_chance >= 95) && (p_orks[i] == 0) && (p_traitors[i] == 0) && (p_necrons[i] == 0) && (p_demons[i] == 0) && (p_chaos[i] == 0)) { p_owner[i] = 8; if (p_guardsmen[i] > 0) { @@ -70,9 +62,10 @@ function scr_enemy_ai_b() { p_guardsmen[i] = 0; } - var targ = 0, have = 0, badd = 1; + var have = 0; + var badd = 1; - targ = planets; + var targ = planets; for (var s = 1; s <= planets; s++) { if (p_type[s] == "Dead") { targ -= 1; diff --git a/scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml b/scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml index 4f2801929c..a2c2b11d7a 100644 --- a/scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml +++ b/scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml @@ -1,9 +1,7 @@ /// @self Asset.GMObject.obj_star function scr_enemy_ai_c() { - var rando, contin, i; - rando = 0; - contin = 0; - i = 0; + var rando = 0; + var contin = 0; with (obj_star) { if ((craftworld == 1) || (space_hulk == 1)) { @@ -16,10 +14,9 @@ function scr_enemy_ai_c() { orks_end_turn_growth(); // traitors below here - i = 0; if (array_sum(p_traitors)) { var traitor_system = true; - for (i = 1; i <= planets; i++) { + for (var i = 1; i <= planets; i++) { if (p_owner[i] != 10) { traitor_system = false; } else if ((p_pdf[i] > 0) || (p_guardsmen[i] > 0) || (p_orks[i] > 0) || (p_tau[i] > 0)) { @@ -29,10 +26,9 @@ function scr_enemy_ai_c() { break; } } - for (i = 1; i <= planets; i++) { + for (var i = 1; i <= planets; i++) { contin = 0; rando = irandom(100) + 1; // This part handles the spreading - // if (rando<30){ contin = floor(random(planets)) + 1; repeat (30) { if ((p_type[contin] == "Dead") || (contin == i)) { @@ -44,15 +40,12 @@ function scr_enemy_ai_c() { contin = 500; } - // if (contin<100) then show_message(string(name)+"."+string(i)+" to "+string(contin)); - if (contin < 100) { if ((p_traitors[i] >= 3) && (p_traitors[contin] < ceil(p_traitors[i] / 2)) && (p_type[contin] != "Dead")) { p_traitors[contin] += 1; contin = 500; } } - // } contin = 0; rando = floor(random(100)) + 1; // This part handles the ship building @@ -63,8 +56,7 @@ function scr_enemy_ai_c() { if ((p_type[i] != "Dead") && (p_type[i] != "Lava")) { if ((p_traitors[i] >= 2) && (p_heresy[i] >= 80)) { // Have the proppa facilities and size - var fleet; - fleet = 0; + var fleet = noone; contin = 2; if (!instance_exists(obj_en_fleet)) { contin = 3; @@ -74,8 +66,7 @@ function scr_enemy_ai_c() { } if (instance_exists(obj_p_fleet)) { - var ppp; - ppp = instance_nearest(x, y, obj_p_fleet); + var ppp = instance_nearest(x, y, obj_p_fleet); if ((point_distance(x, y, ppp.x, ppp.y) < 50) && (ppp.action == "")) { contin = 0; } @@ -83,7 +74,7 @@ function scr_enemy_ai_c() { if (contin == 2) { fleet = scr_orbiting_fleet(eFACTION.CHAOS); - if (fleet == "none") { + if (fleet == noone) { contin = 3; } else if ((fleet.action == "") && (contin != 3)) { // Increase ship number for this object? @@ -103,11 +94,9 @@ function scr_enemy_ai_c() { if (fleet.image_index >= 5) { // eh heh heh - var stue, stue2; - stue = 0; - stue2 = 0; - var goood; - goood = 0; + var stue = 0; + var stue2 = 0; + var goood = 0; with (obj_star) { if ((planets == 1) && (p_type[1] == "Dead")) { @@ -159,12 +148,6 @@ function scr_enemy_ai_c() { present_fleet[10] += 1; obj_controller.chaos_fleets += 1; } - /*if (fleet!=0){ - if (instance_exists(fleet)) then with(fleet){ - var ii;ii=0;ii+=capital_number;ii+=round((frigate_number/2));ii+=round((escort_number/4)); - if (ii<=1) then ii=1;image_index=ii; - } - }*/ } } } @@ -172,18 +155,15 @@ function scr_enemy_ai_c() { } // This is the traitors corruption code - var boat, kay, temp5, temp6, temp7; - boat = 0; - kay = 0; - temp5 = 0; - temp6 = 0; - temp7 = 0; + var kay = 0; + var temp5 = 0; + var temp6 = 0; + var temp7 = 0; - boat = scr_orbiting_fleet(eFACTION.CHAOS); + var boat = scr_orbiting_fleet(eFACTION.CHAOS); - if ((present_fleet[10] > 0) && (present_fleet[1] + present_fleet[2] == 0) && (boat != "none") && (owner != eFACTION.CHAOS) && (planets > 0)) { - var i = 0; - repeat (5) { + if ((present_fleet[10] > 0) && (present_fleet[1] + present_fleet[2] == 0) && (boat != noone) && (owner != eFACTION.CHAOS) && (planets > 0)) { + for (var i = 0; i < 5; i++) { if ((p_type[1] != "Dead") && (p_owner[1] != 10)) { kay = 1; } @@ -242,8 +222,7 @@ function scr_enemy_ai_c() { if ((kay > 0) && (kay != 50)) { // Ere we go! - var cor; - cor = floor(image_index) + 1; + var cor = floor(image_index) + 1; if (p_type[kay] == "Shrine") { cor = round(cor / 3); @@ -255,22 +234,14 @@ function scr_enemy_ai_c() { } } } - i += 1; - } // End repeat + } } // End corruption code // This is the CSM landing code - var boat, kay, temp5, temp6, temp7; - boat = 0; - kay = 0; - temp5 = 0; - temp6 = 0; - temp7 = 0; - boat = scr_orbiting_fleet(eFACTION.CHAOS); var aler = 0; - if ((present_fleet[10] > 0) && (present_fleet[1] + present_fleet[2] == 0) && (boat != "none") && (planets > 0)) { + if ((present_fleet[10] > 0) && (present_fleet[1] + present_fleet[2] == 0) && (boat != noone) && (planets > 0)) { var ii = 0, gud = 0; repeat (planets) { ii += 1; @@ -300,12 +271,8 @@ function scr_enemy_ai_c() { } // End landing portion of code // Tau Here - i = 0; - if (array_sum(p_tau) > 0) { - repeat (4) { - i += 1; - + for (var i = 1; i <= 4; i++) { contin = 0; rando = floor(random(100)) + 1; // This part handles the spreading // if (rando<30){ @@ -320,8 +287,6 @@ function scr_enemy_ai_c() { contin = 500; } - // if (contin<100) then show_message(string(name)+"."+string(i)+" to "+string(contin)); - if (contin < 100) { if ((p_tau[i] == 3) && (p_tau[contin] < 2) && (p_type[contin] != "Dead") && (p_population[contin] > 0)) { p_tau[contin] += 1; @@ -346,7 +311,6 @@ function scr_enemy_ai_c() { contin = 500; } } - // } contin = 0; rando = floor(random(100)) + 1; // This part handles the ship building @@ -405,10 +369,10 @@ function scr_enemy_ai_c() { if (contin == 2) { fleet = scr_orbiting_fleet(eFACTION.TAU); - if (fleet == "none") { + if (fleet == noone) { contin = 3; } - if ((fleet != "none") && (contin != 3)) { + if ((fleet != noone) && (contin != 3)) { // Increase ship number for this object? if ((rando <= 10) && (fleet.image_index < 5)) { rando = choose(1, 2, 2, 3, 3, 3, 3); @@ -424,16 +388,13 @@ function scr_enemy_ai_c() { } if (fleet.image_index >= 5) { - var kawaii, think, xx, yy; - kawaii = 0; - think = 0; - xx = 0; - yy = 0; + var kawaii = 0; + var think = 0; repeat (50) { if ((think == 0) && (kawaii == 0)) { - xx = x + floor(choose(random(300), random(300) * -1)); - yy = y + floor(choose(random(300), random(300) * -1)); + var xx = x + floor(choose(random(300), random(300) * -1)); + var yy = y + floor(choose(random(300), random(300) * -1)); think = instance_nearest(xx, yy, obj_star); if ((think.owner != eFACTION.TAU) && (think.owner != eFACTION.ELDAR) && (think.present_fleet[8] + think.present_fleet[1] + think.present_fleet[2] == 0) && (think.planets > 0)) { kawaii = 1; @@ -456,10 +417,9 @@ function scr_enemy_ai_c() { if ((kawaii == 1) && instance_exists(obj_crusade)) { // NOPE, stay home and defend - var him, own, dis; - him = instance_nearest(x, y, obj_crusade); - own = him.owner; - dis = him.radius; + var him = instance_nearest(x, y, obj_crusade); + var own = him.owner; + var dis = him.radius; if (point_distance(x, y, him.x, him.y) <= dis) { kawaii = 0; } @@ -485,12 +445,6 @@ function scr_enemy_ai_c() { present_fleet[8] += 1; obj_controller.tau_fleets += 1; } - /*if (fleet!=0){ - if (instance_exists(fleet)) then with(fleet){ - var ii;ii=0;ii+=capital_number;ii+=round((frigate_number/2));ii+=round((escort_number/4)); - if (ii<=1) then ii=1;image_index=ii; - } - }*/ } } } @@ -498,12 +452,10 @@ function scr_enemy_ai_c() { } // Tyranids here - var i = 0; - repeat (planets) { - i += 1; + for (var i = 1; i <= planets; i++) { if ((p_tyranids[i] >= 5) && (planets >= i) && (p_player[i] + p_orks[i] + p_guardsmen[i] + p_pdf[i] + p_chaos[i] == 0)) { var ship = scr_orbiting_fleet(eFACTION.TYRANIDS); - if ((ship != "none") && (p_type[i] != "Dead") && (array_length(p_feature[i]) != 0)) { + if ((ship != noone) && (p_type[i] != "Dead") && (array_length(p_feature[i]) != 0)) { if (ship.capital_number > 0) { if (planet_feature_bool(p_feature[i], eP_FEATURES.RECLAMATION_POOLS) == 1) { p_tyranids[i] = 0; @@ -514,7 +466,7 @@ function scr_enemy_ai_c() { ship.escort_number += 3; ship.image_index = floor(ship.capital_number + (ship.frigate_number / 2) + (ship.escort_number / 4)); p_type[i] = "Dead"; - delete_features(p_feature[i], eP_FEATURES.RECLAMATION_POOLS); // show_message("D"); + delete_features(p_feature[i], eP_FEATURES.RECLAMATION_POOLS); if ((planets == 1) && (p_type[1] == "Dead")) { image_alpha = 0.33; } @@ -536,10 +488,10 @@ function scr_enemy_ai_c() { if ((planet_feature_bool(p_feature[i], eP_FEATURES.CAPILLARY_TOWERS) == 1) && (p_type[i] != "Dead")) { p_feature[i] = []; array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.CAPILLARY_TOWERS), new NewPlanetFeature(eP_FEATURES.RECLAMATION_POOLS)); - p_population[i] = 0; // show_message("C"); + p_population[i] = 0; } if ((planet_feature_bool(p_feature[i], eP_FEATURES.CAPILLARY_TOWERS) == 0) && (planet_feature_bool(p_feature[i], eP_FEATURES.RECLAMATION_POOLS) == 0) && (p_type[i] != "Dead")) { - array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.CAPILLARY_TOWERS)); // show_message("B"); + array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.CAPILLARY_TOWERS)); } } } diff --git a/scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml b/scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml index 50984068c6..1d976d438c 100644 --- a/scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml +++ b/scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml @@ -104,13 +104,7 @@ function scr_enemy_ai_e() { instance_activate_object(obj_en_fleet); if ((battle2 > 0) && (battle == 0)) { // AI only battle - var i, f, shiyp; - i = 0; - f = 1; - shiyp = 0; - - repeat (10) { - f += 1; + for (var f = 2; f <= 11; f++) { if (f == 11) { f = 13; } @@ -141,8 +135,6 @@ function scr_enemy_ai_e() { strength[13] = strength[13] * 2; } - // if (f=10) or (f=2) then show_message("["+string(f)+"] Fleet strength: "+string(strength[f])); - with (obj_en_ship) { if ((x < -7000) && (y < -7000)) { x += 10000; @@ -161,14 +153,12 @@ function scr_enemy_ai_e() { y += 10000; } } - // show_message(string(name)+"] Owner: "+string(f)+", strength: "+string(strength[f])); } } // This grabs the "strength" from all present fleets and adds it to the temporary variable for this AI battle // Determine who will attack who - var still_battling, rond; - still_battling = true; - rond = 0; + var still_battling = true; + var rond = 0; repeat (5) { rond += 1; @@ -195,14 +185,9 @@ function scr_enemy_ai_e() { still_battling = true; } - // show_message(string(name)+" Round "+string(rond)+": "+string(still_battling)); - if (still_battling == true) { - var who; - who = 0; - // Imperial Fleet Attacks - who = 2; + var who = 2; if (strength[who] > 0) { if ((strength[9] > 0) && (attack[who] == 0)) { attack[who] = 9; @@ -223,21 +208,16 @@ function scr_enemy_ai_e() { attack[who] = 6; } damage[attack[who]] += strength[who] / 2; - - // if (attack[who]=10) then show_message("Imperial Fleet damage: "+string(damage[10])+", Strength: "+string(strength[2])); - // show_message(string(who)+" attacking "+string(attack[who])+" for "+string(strength[who]/2)); } // Eldar Fleet Attacks who = 6; if (strength[who] > 0) { - i = 11; if ((strength[13] > 0) && (13 != who)) { attack[who] = 13; } if (attack[who] != 13) { - repeat (9) { - i -= 1; + for (var i = 10; i >= 2; i--) { if ((strength[i] > 0) && (i != who)) { attack[who] = i; } @@ -268,7 +248,6 @@ function scr_enemy_ai_e() { attack[who] = 6; } damage[attack[who]] += strength[who] / 2; - // show_message(string(who)+" attacking "+string(attack[who])+" for "+string(strength[who]/2)); } // Tau Fleet Attacks @@ -295,13 +274,11 @@ function scr_enemy_ai_e() { // Tyranid Fleet Attacks who = 9; if (strength[who] > 0) { - i = 1; if ((strength[13] > 0) && (13 != who)) { attack[who] = 13; } if (attack[who] != 13) { - repeat (9) { - i += 1; + for (var i = 2; i <= 10; i++) { if ((strength[i] > 0) && (i != who)) { attack[who] = i; } @@ -332,7 +309,6 @@ function scr_enemy_ai_e() { attack[who] = 8; } damage[attack[who]] += strength[who] / 2; - // if (attack[who]=2) then show_message("Chaos Fleet damage: "+string(damage[2])+", Strength: "+string(strength[10])); } // Necron Fleet Attacks @@ -360,15 +336,10 @@ function scr_enemy_ai_e() { } // Attacking has been determined, work out damage - var i; - i = 1; - repeat (9) { - i += 1; + for (var i = 2; i <= 10; i++) { strength[i] -= damage[i]; damage[i] = 0; - // if (strength[i]>0) and (present_fleet[i]>0) then show_message(string(name)+"] Fleet:"+string(i)+" surviving at "+string(strength[i])+" in round "+string(rond)); if ((strength[i] <= 0) && (present_fleet[i] > 0)) { - // show_message(string(name)+"] Fleet:"+string(i)+" beat to shit in round "+string(rond)); obj_controller.temp[1049] = i; obj_controller.temp[1050] = self.id; with (obj_en_fleet) { @@ -381,9 +352,7 @@ function scr_enemy_ai_e() { strength[13] -= damage[13]; damage[13] = 0; - // if (strength[i]>0) and (present_fleet[i]>0) then show_message(string(name)+"] Fleet:"+string(i)+" surviving at "+string(strength[i])+" in round "+string(rond)); if ((strength[13] <= 0) && (present_fleet[13] > 0)) { - // show_message(string(name)+"] Fleet:"+string(i)+" beat to shit in round "+string(rond)); obj_controller.temp[1049] = 13; obj_controller.temp[1050] = self.id; with (obj_en_fleet) { @@ -398,10 +367,7 @@ function scr_enemy_ai_e() { // Those 5 battle intervals have finished // Clean up the surviving fleet(s) - var i; - i = 1; - repeat (10) { - i += 1; + for (var i = 2; i <= 11; i++) { if (i == 11) { i = 13; } @@ -424,10 +390,6 @@ function scr_enemy_ai_e() { } } - // show_message("Fleet "+string(owner)+" has "+string(obj_controller.temp[1048])+" strength remaining after the battle"); - - // if (i=10) and (strength[i]>0) then show_message("STR "+string(strength[10])+" < "+string(obj_controller.temp[1048])+" ?"); - if (strength[i] < obj_controller.temp[1048]) { // Need to remove ships if != repeat (40) { @@ -437,7 +399,6 @@ function scr_enemy_ai_e() { if ((escort_number > 0) && (escort_number + frigate_number + capital_number != 1)) { escort_number -= 1; obj_controller.temp[1047] -= 1; - // show_message("removed an escort, escorts left: "+string(escort_number)); if (escort_number + frigate_number + capital_number <= 0) { instance_destroy(); } @@ -455,7 +416,6 @@ function scr_enemy_ai_e() { if ((frigate_number > 0) && (escort_number + frigate_number + capital_number != 1)) { frigate_number -= 1; obj_controller.temp[1047] -= 4; - // show_message("removed a frigate, frigates left: "+string(frigate_number)); if (escort_number + frigate_number + capital_number <= 0) { instance_destroy(); } @@ -471,7 +431,6 @@ function scr_enemy_ai_e() { if ((capital_number > 0) && (escort_number + frigate_number + capital_number != 1)) { capital_number -= 1; obj_controller.temp[1047] -= 8; - // show_message("removed a capital ship, capitals left: "+string(capital_number)); if (escort_number + frigate_number + capital_number <= 0) { instance_destroy(); } @@ -483,7 +442,6 @@ function scr_enemy_ai_e() { } strength[i] = obj_controller.temp[1047]; - // show_message("Surviving fleet ("+string(i)+") strength: "+string(strength[i])); // I'd hope that removes enough ships from the survivor } with (obj_en_fleet) { @@ -512,10 +470,9 @@ function scr_enemy_ai_e() { // Quene battle obj_turn_end.battles += 1; obj_turn_end.battle[obj_turn_end.battles] = 1; - obj_turn_end.battle_world[obj_turn_end.battles] = -50; + obj_turn_end.battle_world[obj_turn_end.battles] = noone; obj_turn_end.battle_opponent[obj_turn_end.battles] = i; // Who triggered it first obj_turn_end.battle_location[obj_turn_end.battles] = name; - // obj_turn_end.battle_object[obj_turn_end.battles]=instance_nearest(x,y,obj_en_fleet); obj_turn_end.battle_pobject[obj_turn_end.battles] = instance_nearest(x, y, obj_p_fleet); if (i == 10) { @@ -587,8 +544,7 @@ function scr_enemy_ai_e() { } if (has_problem_planet(run, "spyrer")) { if (p_player[run] > 20) { - var tixt; - tixt = "The Spyrer on " + planet_numeral_name(run); + var tixt = "The Spyrer on " + planet_numeral_name(run); tixt += " seems to have vanished, presumably gone into hiding."; scr_popup("Spyrer Rampage", tixt, "spyrer", ""); } else if (p_player[run] <= 20) { @@ -620,7 +576,7 @@ function scr_enemy_ai_e() { } } else if (chan >= 3) { if (remove_planet_problem(run, "fallen")) { - tixt = "Your marines have scoured " + planet_numeral_name(run); + var tixt = "Your marines have scoured " + planet_numeral_name(run); tixt += " in search of the Fallen. Despite their best efforts, and meticulous searching, none have been found. It appears as though the information was faulty or out of date."; scr_popup("Hunt the Fallen", tixt, "fallen", ""); scr_event_log("", $"Mission Successful: No Fallen located upon {planet_numeral_name(run)}"); @@ -634,6 +590,7 @@ function scr_enemy_ai_e() { if ((p_player[run] > 0) && (force_count > 0)) { for (force = 2; force < 14; force++) { battle_opponent = 0; + var pause = false; switch (force) { case 3: // mechanicus aren't quite in yet @@ -674,14 +631,14 @@ function scr_enemy_ai_e() { } break; case 10: - var pause = has_problem_planet(run, "meeting") || has_problem_planet(run, "meeting_trap"); - if (p_guardsmen[run] + p_pdf[run] == 0 && p_player[run] > 0 && p_traitors[run] > 0 && pause == 0 && obj_controller.faction_status[10] == "War") { + pause = has_problem_planet(run, "meeting") || has_problem_planet(run, "meeting_trap"); + if (p_guardsmen[run] + p_pdf[run] == 0 && p_player[run] > 0 && p_traitors[run] > 0 && !pause && obj_controller.faction_status[10] == "War") { battle_opponent = 10; } break; case 11: - var pause = has_problem_planet(run, "meeting") || has_problem_planet(run, "meeting_trap"); - if (p_guardsmen[run] + p_pdf[run] == 0 && p_player[run] > 0 && p_chaos[run] > 0 && pause == 0 && obj_controller.faction_status[10] == "War") { + pause = has_problem_planet(run, "meeting") || has_problem_planet(run, "meeting_trap"); + if (p_guardsmen[run] + p_pdf[run] == 0 && p_player[run] > 0 && p_chaos[run] > 0 && !pause && obj_controller.faction_status[10] == "War") { battle_opponent = 11; } break; @@ -694,7 +651,6 @@ function scr_enemy_ai_e() { // other battle crap here if (battle_opponent > 0) { - // obj_controller.x=self.x;obj_controller.y=self.y; obj_turn_end.battles += 1; obj_turn_end.battle[obj_turn_end.battles] = 1; obj_turn_end.battle_world[obj_turn_end.battles] = run; diff --git a/scripts/scr_equipment_struct/scr_equipment_struct.gml b/scripts/scr_equipment_struct/scr_equipment_struct.gml index de6b92c9b6..02abe764f7 100644 --- a/scripts/scr_equipment_struct/scr_equipment_struct.gml +++ b/scripts/scr_equipment_struct/scr_equipment_struct.gml @@ -68,7 +68,6 @@ function EquipmentStruct(item_data, core_type, quality_request = "none", arti_st self[$ _struct_key] = self[$ _struct_key][$ quality]; } } - // _struct_key = ""; } } @@ -266,7 +265,6 @@ function EquipmentStruct(item_data, core_type, quality_request = "none", arti_st array_push(special_properties_array, second_profiles[h]); } } - //item_desc_tooltip += $"#Properties:#{special_properties_string}#" } if (is_struct(specials)) { diff --git a/scripts/scr_event_code/scr_event_code.gml b/scripts/scr_event_code/scr_event_code.gml index 6b6562b288..019af1f22a 100644 --- a/scripts/scr_event_code/scr_event_code.gml +++ b/scripts/scr_event_code/scr_event_code.gml @@ -52,7 +52,7 @@ function event_end_turn_action() { var _star_name = _event.system; var _event_star = find_star_by_name(_event.system); var _planet = _event.planet; - if (_event_star != "none") { + if (_event_star != noone) { _event_star.dispo[_planet] = -10; // Resets var twix = $"Inquisition executes Chapter Serf in control of {planet_numeral_name(_planet, _event_star)} and installs a new Planetary Governor."; if (_event_star.p_owner[_planet] == eFACTION.PLAYER) { @@ -89,7 +89,7 @@ function event_end_turn_action() { if (_event.e_id == "chaos_invasion") { var xx = 0, yy = 0, flee = 0, dirr = 0; var star_id = scr_random_find(1, true, "", ""); - if (star_id != undefined) { + if (star_id != noone) { scr_event_log("purple", $"Chaos Fleets exit the warp near the {star_id.name} system.", star_id.name); for (var j = 0; j < 4; j++) { dirr += irandom_range(50, 100); @@ -163,6 +163,7 @@ function event_end_turn_action() { var marine_num = _event.marine; var _unit = fetch_unit([comp, marine_num]); var item = _event.crafted; + var _pop_data = {}; LOGGER.warning($"comp: {comp}, marine_num: {marine_num}"); @@ -235,14 +236,12 @@ function event_end_turn_action() { choice_func: popup_default_close, } ]; - var _pop_data = { + _pop_data = { options: options, marine_number: marine_num, company: comp, marine_name: marine_name, }; - } else { - _pop_data = ""; } scr_popup("He Built It", tixt, "tech_build", _pop_data); @@ -358,7 +357,7 @@ function strange_build_event() { if (marine_is_planetside && heritical_item) { var _system = find_star_by_name(_unit.location_string); var _planet = _unit.planet_location; - if (_system != "none") { + if (_system != noone) { with (_system) { p_hurssy[_planet] += 6; p_hurssy_time[_planet] = 2; @@ -366,7 +365,7 @@ function strange_build_event() { } } else if (!marine_is_planetside && heritical_item) { var _fleet = find_ships_fleet(_unit.ship_location); - if (_fleet != "none") { + if (_fleet != noone) { //the intended code for here was to add some sort of chaos event on the ship stashed up ready to fire in a few turns } } diff --git a/scripts/scr_event_log/scr_event_log.gml b/scripts/scr_event_log/scr_event_log.gml index e71b2224ce..8a3fad3aa8 100644 --- a/scripts/scr_event_log/scr_event_log.gml +++ b/scripts/scr_event_log/scr_event_log.gml @@ -1,4 +1,4 @@ -function scr_event_log(event_colour, event_text, target = "none") { +function scr_event_log(event_colour, event_text, target = noone) { LOGGER.info($"Adding event to log: {event_text}"); if (instance_exists(obj_event_log)) { var yf; diff --git a/scripts/scr_event_newlines/scr_event_newlines.gml b/scripts/scr_event_newlines/scr_event_newlines.gml index 5fbd9ae77d..d584d3404e 100644 --- a/scripts/scr_event_newlines/scr_event_newlines.gml +++ b/scripts/scr_event_newlines/scr_event_newlines.gml @@ -1,27 +1,15 @@ function scr_event_newlines(argument0) { // argument0: string being added to the event display - need to verify string height - // show_message(string(argument0)); - if (argument0 != "") { - var nl, nls, lo, q, onceh; draw_set_font(fnt_40k_14); - onceh = 0; - lo = 0; - - nls = string_height_ext(string_hash_to_newline(argument0), -1, 916) / 21; - // show_message(string(nls)); + var nls = string_height_ext(string_hash_to_newline(argument0), -1, 916) / 21; if (lines + nls > 17) { // Going to need to move some lines around - nl = (lines + nls) - 17; - - repeat (nl) { - var q; - q = 0; - repeat (17) { - q += 1; - line[q] = line[q + 1]; + repeat ((lines + nls) - 17) { + for (var i = 1; i <= 17; i++) { + line[i] = line[i + 1]; } line[17] = ""; lines -= 1; @@ -31,12 +19,10 @@ function scr_event_newlines(argument0) { if (lines + nls <= 17) { // Slap in text without worrying about lines // get first open - q = 0; - lo = 0; - repeat (17) { - q += 1; - if ((line[q] == "") && (lo == 0)) { - lo = q; + var lo = 0; + for (var i = 1; i <= 17; i++) { + if ((line[i] == "") && (lo == 0)) { + lo = i; } } @@ -46,14 +32,12 @@ function scr_event_newlines(argument0) { // If it is composed of several lines than make those lines beneath it blank as needed if (nls > 1) { - q = nls - 1; - repeat (q) { + repeat (nls - 1) { lo += 1; line[lo] = "---"; lines += 1; } } - onceh = 1; } } } diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index 098bc1b875..e9d2c9c469 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -29,10 +29,10 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo exit; } - var m1, m2, m3, mes; - m1 = ""; - m2 = ""; - m3 = ""; + var mes = ""; + var m1 = ""; + var m2 = ""; + var m3 = ""; var _hostile_range, _hostile_weapon, _hostile_shots; _hostile_range = 0; @@ -70,19 +70,6 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo var flavor = 0; - /* - if (lost_units_count="Venom Claws"){atta=200;arp=0;rang=1;spli=0;if (obj_ini.preomnor=1){atta=240;}} - if (lost_units_count="Web Spinner"){atta=40;arp=0;rang=2.1;spli=1;amm=1;} - if (lost_units_count="Warpsword"){atta=300;arp=200;rang=1;spli=1;} - if (lost_units_count="Iron Claw"){atta=300;arp=400;rang=1;spli=0;} - if (lost_units_count="Maulerfiend Claws"){atta=300;arp=300;rang=1;spli=1;} - - if (lost_units_count="Eldritch Fire"){atta=80;arp=40;rang=5.1;} - if (lost_units_count="Khorne Demon Melee"){atta=350;arp=400;rang=1;spli=1;} - if (lost_units_count="Demon Melee"){atta=250;arp=300;rang=1;spli=1;} - if (lost_units_count="Lash Whip"){atta=80;arp=0;rang=2;} - */ - if (_hostile_weapon == "Daemonette Melee") { flavor = 1; if (_hostile_shots > 1) { @@ -161,8 +148,7 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } if (_hostile_weapon == "Shoota") { flavor = 1; - var ranz; - ranz = choose(1, 2, 3, 4); + var ranz = choose(1, 2, 3, 4); if (ranz == 1) { m1 = string(_hostile_shots) + " " + string(_hostile_weapon) + "z fire away at " + string(target_type) + ". "; } @@ -293,8 +279,7 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } if (_hostile_weapon == "Slugga") { flavor = 1; - var ranz; - ranz = choose(1, 2, 3, 4); + var ranz = choose(1, 2, 3, 4); if (ranz == 1) { m1 = string(_hostile_shots) + " " + string(_hostile_weapon) + "z fire away at " + string(target_type) + ". "; } @@ -339,8 +324,7 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo if (_hostile_weapon == "Staff of Light") { flavor = 1; if (_hostile_shots == 1) { - var ranz; - ranz = choose(1, 2, 3); + var ranz = choose(1, 2, 3); if (ranz == 1) { m1 = "A " + string(_hostile_weapon) + " crackles and is swung into " + string(target_type) + ". "; } @@ -352,8 +336,7 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } } if (_hostile_shots > 1) { - var ranz; - ranz = choose(1, 2, 3); + var ranz = choose(1, 2, 3); if (ranz == 1) { m1 = string(_hostile_shots) + " Staves of Light strike at " + string(target_type) + ". "; } @@ -367,8 +350,7 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } if (_hostile_weapon == "Warscythe") { flavor = 1; - var ranz; - ranz = choose(1, 2, 3); + var ranz = choose(1, 2, 3); if (ranz == 1) { m1 = string(_hostile_shots) + " Warscythes strike at " + string(target_type) + ". "; } @@ -382,8 +364,7 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo if (_hostile_weapon == "Claws") { flavor = 1; if (_hostile_shots == 1) { - var ranz; - ranz = choose(1, 2, 3); + var ranz = choose(1, 2, 3); if (ranz == 1) { m1 = "A massive claw slices through " + string(target_type) + ". "; } @@ -395,8 +376,7 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } } if (_hostile_shots > 1) { - var ranz; - ranz = choose(1, 2, 3); + var ranz = choose(1, 2, 3); if (ranz == 1) { m1 = string(_hostile_shots) + " massive claws strike and slice at " + string(target_type) + ". "; } @@ -419,10 +399,6 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } } - // show_message(mes); - - // m2="Blah blah blah"; - if (target_type == "wall") { var _wall_destroyed = obj_nfort.hp[1] <= 0 ? true : false; @@ -440,8 +416,6 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo obj_ncombat.alarm[3] = 2; } if (obj_nfort.hp[1] <= 0) { - s = 0; - him = 0; obj_ncombat.dead_jims += 1; obj_ncombat.dead_jim[obj_ncombat.dead_jims] = "The fortified wall has been breached!"; obj_ncombat.wall_destroyed = 1; @@ -495,22 +469,15 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo var unce = 0; if (string_count(", ", m2) > 1) { - // show_message(m2); - - var lis, y1, y2; - lis = string_rpos(", ", m2); + var lis = string_rpos(", ", m2); m2 = string_delete(m2, lis, 3); // This clears the last ', ' and replaces it with the end statement if (lost_units_count > 0) { m2 += " lost."; } - // show_message(m2); - lis = string_rpos(", ", m2); // Find the new last ', ' and replace it with the and part m2 = string_delete(m2, lis, 2); - // show_message(m2); - if (string_count(",", m2) > 1) { m2 = string_insert(", and ", m2, lis); } @@ -518,22 +485,18 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo m2 = string_insert(" and ", m2, lis); } - // show_message(m2); - unce = 1; } if ((string_count(", ", m2) == 1) && (unce == 0) && (hostile_weapon != "Web Spinner")) { - var lis, y1, y2; - lis = string_rpos(", ", m2); + var lis = string_rpos(", ", m2); m2 = string_delete(m2, lis, 3); if (lost_units_count > 0) { m2 += " lost."; } } if ((string_count(", ", m2) == 1) && (unce == 0) && (hostile_weapon == "Web Spinner")) { - var lis, y1, y2; - lis = string_rpos(", ", m2); + var lis = string_rpos(", ", m2); m2 = string_delete(m2, lis, 3); if (lost_units_count > 1) { m2 += " have been incapacitated."; @@ -551,7 +514,6 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } mes = m1 + m2 + m3; - // show_message(mes); if (string_length(mes) > 3) { // Yellow when the enemy hurt your forces but destroyed nothing (damage, no kill). Kills carry diff --git a/scripts/scr_fleet_functions/scr_fleet_functions.gml b/scripts/scr_fleet_functions/scr_fleet_functions.gml index 9937992eeb..67785568b5 100644 --- a/scripts/scr_fleet_functions/scr_fleet_functions.gml +++ b/scripts/scr_fleet_functions/scr_fleet_functions.gml @@ -1,3 +1,5 @@ +/// @param {Real} strength +/// @param {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} fleet function distribute_strength_to_fleet(strength, fleet) { while (strength > 0) { var ship_type = choose(1, 1, 1, 1, 2, 2, 3); @@ -12,26 +14,34 @@ function distribute_strength_to_fleet(strength, fleet) { } } -function standard_fleet_strength_calc(fleet = undefined){ - if (is_undefined(fleet)){ +/// @self Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet +/// @param {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} fleet +function standard_fleet_strength_calc(fleet = noone){ + if (fleet == noone) { fleet = self; } return fleet.capital_number + (fleet.frigate_number/2) + (fleet.escort_number/4); } -/// @self Asset.GMObject.obj_en_fleet function random_sector_exit_point() { action_x = choose(room_width * -1, room_width * 2); action_y = choose(room_height * -1, room_height * 2); } -/// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet -function in_room(object = undefined) { - object ??= self; +/// @self Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet +/// @param {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} object +/// @return {Bool} +function in_room(object = noone) { + if (object == noone) { + object = self; + } return !(object.x < 0 || object.x > room_width || object.y < 0 || object.y > room_height); } -/// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet +/// @self Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet +/// @param {Real} targ_x +/// @param {Real} targ_y +/// @param {Id.Instance.obj_fleet} final_target function set_fleet_target(targ_x, targ_y, final_target) { action_x = targ_x; action_y = targ_y; @@ -39,7 +49,7 @@ function set_fleet_target(targ_x, targ_y, final_target) { action_eta = floor(point_distance(x, y, targ_x, targ_y) / 128) + 1; } -/// @param {Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet} target +/// @param {Id.Instance} target function scr_valid_fleet_target(target) { if (target == noone) { return false; @@ -56,22 +66,22 @@ function scr_valid_fleet_target(target) { } function get_fleet_uid(search_uid) { - var _fleet = undefined; + var _fleet = noone; with (obj_en_fleet) { if (uid == search_uid) { - _fleet = id; + _fleet = self; break; } } return _fleet; } - /// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet -/// @param {Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet} fleet -function fleets_next_location(fleet = "none", visited = []) { - var targ_location = "none"; +/// @param {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} fleet +/// @param {Array} visited +function fleets_next_location(fleet = noone, visited = []) { + var targ_location = noone; - if (fleet == "none") { + if (fleet == noone) { fleet = self; } @@ -99,15 +109,17 @@ function fleets_next_location(fleet = "none", visited = []) { } } // If targ_location was not set to anything else, default to the nearest star - if (targ_location == "none") { + if (targ_location == noone) { targ_location = instance_nearest(fleet.x, fleet.y, obj_star); } return targ_location; } +/// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet +/// @param {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} target function chase_fleet_target_set(target) { var targ_location = fleets_next_location(target); - if (targ_location != "none") { + if (targ_location != noone) { action_x = targ_location.x; action_y = targ_location.y; action = ""; @@ -126,11 +138,11 @@ function fleet_intercept_time_calculate(target_intercept) { } function get_largest_player_fleet() { - var chosen_fleet = "none"; + var chosen_fleet = noone; if (instance_exists(obj_p_fleet)) { with (obj_p_fleet) { if (point_in_rectangle(x, y, 0, 0, room_width, room_height) && point_in_rectangle(action_x, action_y, 0, 0, room_width, room_height)) { - if (chosen_fleet == "none") { + if (chosen_fleet == noone) { chosen_fleet = self; continue; } @@ -154,8 +166,8 @@ function get_largest_player_fleet() { } /// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet -function is_orbiting(fleet = "none") { - if (fleet == "none") { +function is_orbiting(fleet = noone) { + if (fleet == noone) { if (action != "") { return false; } @@ -165,7 +177,7 @@ function is_orbiting(fleet = "none") { orbiting = nearest.id; return true; } - orbiting = false; + orbiting = noone; } catch (_exception) { return false; } @@ -191,7 +203,7 @@ function set_fleet_movement(fastest_route = true, new_action = "move", minimum_e var path = star_travel.final_array_path(); if (array_length(path) > 1) { var targ = find_star_by_name(path[1]); - if (targ != "none") { + if (targ != noone) { array_delete(path, 0, 2); complex_route = path; action_x = targ.x; @@ -226,15 +238,15 @@ function set_fleet_movement(fastest_route = true, new_action = "move", minimum_e } } - // action_x=sys.x; - // action_y=sys.y; - orbiting = false; + orbiting = noone; action = new_action; action_eta = clamp(action_eta, minimum_eta, maximum_eta); } } } +/// @param {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} fleet +/// @param {Struct} unit function load_unit_to_fleet(fleet, unit) { var loaded = false; var all_ships = fleet_full_ship_array(fleet); @@ -253,22 +265,24 @@ function load_unit_to_fleet(fleet, unit) { return loaded; } -function calculate_fleet_eta(xx, yy, xxx, yyy, fleet_speed, star1 = true, star2 = true, warp_able = false) { - var warp_lane = false; - var eta = 0; - //Some duke unfinished webway stuff copied here for reference - /*for (var w = 1;w<5;w++){ - if (planet_feature_bool(mine.p_feature[w], eP_FEATURES.WEBWAY)==1) then web1=1; - if (planet_feature_bool(sys.p_feature[w], eP_FEATURES.WEBWAY)==1) then web2=1; - }*/ - if (star1 && star2) { +/// @param {Real} xx +/// @param {Real} yy +/// @param {Real} xxx +/// @param {Real} yyy +/// @param {Real} fleet_speed +/// @param {Id.Instance.obj_star} star1 +/// @param {Id.Instance.obj_star} star2 +/// @param {Bool} warp_able +function calculate_fleet_eta(xx, yy, xxx, yyy, fleet_speed, star1 = noone, star2 = noone, warp_able = false) { + var warp_lane = 0; + if (star1 == noone && star2 == noone) { star1 = instance_nearest(xx, yy, obj_star); star2 = instance_nearest(xxx, yyy, obj_star); warp_lane = determine_warp_join(star1.id, star2.id); - } else if (star1) { + } else if (star1 == noone) { star1 = instance_nearest(xx, yy, obj_star); } - eta = floor(point_distance(xx, yy, xxx, yyy) / fleet_speed) + 1; + var eta = floor(point_distance(xx, yy, xxx, yyy) / fleet_speed) + 1; if (!warp_lane) { eta *= 2; } @@ -291,9 +305,11 @@ function calculate_fleet_eta(xx, yy, xxx, yyy, fleet_speed, star1 = true, star2 } /// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet -function calculate_action_speed(fleet = "none", selected = false) { +/// @param {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} fleet +/// @param {Bool} selected +function calculate_action_speed(fleet = noone, selected = false) { try { - if (fleet == "none") { + if (fleet == noone) { var capitals = 0, frigates = 0, escorts = 0, i; var _is_player_fleet = object_index == obj_p_fleet; if (_is_player_fleet) { @@ -387,7 +403,7 @@ function scr_efleet_arrive_at_trade_loc() { //if no fleet find a valid planet with player forces if (action == "") { var _player_star = nearest_star_with_ownership(x, y, 1); - if (_player_star != "none") { + if (_player_star != noone) { action_x = _player_star.x; action_y = _player_star.y; set_fleet_movement(); @@ -406,7 +422,7 @@ function scr_efleet_arrive_at_trade_loc() { //if no other viable options drop off at random imperial planet if (action == "") { var _imp = nearest_star_with_ownership(x, y, 2); - if (_imp != "none") { + if (_imp != noone) { if (x == _imp.x && y == _imp.y) { _valid_planet = true; } else { @@ -442,7 +458,7 @@ function scr_efleet_arrive_at_trade_loc() { if (owner == eFACTION.ELDAR) { cur_star = nearest_star_with_ownership(xx, yy, eFACTION.ELDAR); - if (cur_star != "none") { + if (cur_star != noone) { cur_star = targ.x; cur_star = targ.y; } @@ -462,17 +478,17 @@ function scr_efleet_arrive_at_trade_loc() { /// @function scr_orbiting_fleet(faction, system) /// @description Returns the ID of a fleet orbiting the given system/star that matches the specified faction. -/// @param {any|array} faction +/// @param {Real|Array} faction /// The faction identifier to check against. Can be a single faction ID or an array of multiple factions. -/// @param {any} [system="none"] -/// The system instance or star to check. If `"none"`, the function uses the calling instance's position. -/// @returns {real|string} The ID of the matching fleet instance, or `"none"` if no valid fleet is found. +/// @param {Id.Instance.obj_star} system +/// The system instance or star to check. If `noone`, the function uses the calling instance's position. +/// @returns {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} The ID of the matching fleet instance, or `noone` if no valid fleet is found. /// /// @example /// ```gml /// // Find a fleet orbiting this star that belongs to faction 3 /// var fleet_id = scr_orbiting_fleet(3); -/// if (fleet_id != "none") { +/// if (fleet_id != noone) { /// LOGGER.debug("Faction fleet found: " + string(fleet_id)); /// } /// @@ -480,13 +496,11 @@ function scr_efleet_arrive_at_trade_loc() { /// var factions = [1, 2, 5]; /// var fleet_id = scr_orbiting_fleet(factions, some_system); /// ``` -/// - -function scr_orbiting_fleet(faction, system = "none") { - var _found_fleet = "none"; +function scr_orbiting_fleet(faction, system = noone) { + var _found_fleet = noone; var _faction_list = is_array(faction); - var xx = system == "none" ? x : system.x; - var yy = system == "none" ? y : system.y; + var xx = system == noone ? x : system.x; + var yy = system == noone ? y : system.y; with (obj_en_fleet) { if (x == xx && y == yy) { var _valid = false; @@ -508,9 +522,9 @@ function scr_orbiting_fleet(faction, system = "none") { /// @function object_distance(obj_1, obj_2) /// @description Returns the distance in pixels between two instances or objects based on their `x` and `y` coordinates. -/// @param {instance} obj_1 The first object or instance. -/// @param {instance} obj_2 The second object or instance. -/// @returns {real} The distance in pixels between `obj_1` and `obj_2`. +/// @param {Id.Instance} obj_1 The first object or instance. +/// @param {Id.Instance} obj_2 The second object or instance. +/// @returns {Real} The distance in pixels between `obj_1` and `obj_2`. /// /// @example /// ```gml @@ -519,17 +533,15 @@ function scr_orbiting_fleet(faction, system = "none") { /// LOGGER.debug("Enemy is within range!"); /// } /// ``` -/// - function object_distance(obj_1, obj_2) { return point_distance(obj_1.x, obj_1.y, obj_2.x, obj_2.y); } /// @function scr_orbiting_player_fleet(system) /// @description Returns the ID of the nearest player fleet orbiting the given system or star. -/// @param {any} [system="none"] -/// The system instance or identifier to check. If `"none"`, the function checks the calling star instance. -/// @returns {real} The instance ID of the orbiting player fleet, or -1 if none is found. +/// @param {Id.Instance.obj_star} system +/// The system instance or identifier to check. If `noone`, the function checks the calling star instance. +/// @returns {Id.Instance.obj_p_fleet} The instance ID of the orbiting player fleet, or -1 if none is found. /// /// @example /// ```gml @@ -538,16 +550,15 @@ function object_distance(obj_1, obj_2) { /// LOGGER.debug("Fleet orbiting star: " + string(fleet_id)); /// } /// ``` -/// -function scr_orbiting_player_fleet(system = "none") { - if (system == "none" && !is_struct(self) && object_index == obj_star) { +function scr_orbiting_player_fleet(system = noone) { + if (system == noone && !is_struct(self) && object_index == obj_star) { var _fleet = instance_nearest(x, y, obj_p_fleet); if (object_distance(self, _fleet) > 0) { return -1; } else { return _fleet.id; } - } else if (system != "none") { + } else if (system != noone) { try { with (system) { return scr_orbiting_player_fleet(); @@ -560,11 +571,11 @@ function scr_orbiting_player_fleet(system = "none") { return -1; } -function get_orbiting_fleets(faction, system = "none") { +function get_orbiting_fleets(faction, system = noone) { var _fleets = []; var _faction_list = is_array(faction); - var xx = system == "none" ? x : system.x; - var yy = system == "none" ? y : system.y; + var xx = system == noone ? x : system.x; + var yy = system == noone ? y : system.y; with (obj_en_fleet) { if (x == xx && y == yy) { var _valid = false; @@ -686,8 +697,6 @@ function fleet_arrival_logic() { sta = instance_nearest(action_x, action_y, obj_star); is_orbiting(); - // cur_star.present_fleets+=1;if (owner = eFACTION.TAU) then cur_star.tau_fleets+=1; - if (owner == eFACTION.MECHANICUS) { if (trade_goods == "mars_spelunk1") { trade_goods = "mars_spelunk2"; @@ -709,7 +718,6 @@ function fleet_arrival_logic() { } if (trade_goods == "return") { - // with(instance_nearest(x,y,obj_star)){present_fleets-=1;} instance_destroy(); } @@ -881,7 +889,7 @@ function fleet_arrival_logic() { action_x = 0; action_y = 0; - // 135 ; fleet chase + // fleet chase if ((string_count("Inqis", trade_goods) > 0) && (string_count("fleet", trade_goods) > 0) && (!string_count("_her", trade_goods))) { inquisition_fleet_inspection_chase(); } @@ -916,24 +924,18 @@ function fleet_arrival_logic() { mergus = 0; } - if ((owner == eFACTION.TAU) && (image_index == 1)) { - // show_message("Tau||| Other Owner: "+string(cur_star.owner)+" ret: "+string(ret)+" mergus: "+string(mergus)); - } - if ((owner == eFACTION.CHAOS) && fleet_has_cargo("csm") || fleet_has_cargo("warband")) { mergus = 0; } - // if (cur_star.owner!=owner) then mergus=0; if ((cur_star.x == old_x) && (cur_star.y == old_y) && (cur_star.owner == self.owner) && (cur_star.action == "") && (mergus == 1999)) { // Merge the fleets cur_star.escort_number += self.escort_number; - cur_star.frigate_number += self.frigate_number; // show_message("Tau fleet merging"); + cur_star.frigate_number += self.frigate_number; cur_star.capital_number += self.capital_number; cur_star.guardsmen += self.guardsmen; cur_star = instance_nearest(old_x, old_y, obj_star); - // if (cur_star.present_fleets>=1) then cur_star.present_fleets-=1; if (owner == eFACTION.TAU) { obj_controller.tau_fleets -= 1; cur_star.tau_fleets -= 1; @@ -947,9 +949,8 @@ function fleet_arrival_logic() { if ((owner == eFACTION.TAU) && (mergus == 15)) { // Get the fuck out - var new_star, stue; - new_star = 0; - stue = 0; + var new_star = 0; + var stue = 0; ret = 1; instance_activate_object(obj_star); // new_star @@ -969,14 +970,14 @@ function fleet_arrival_logic() { if ((tau_influence_chance <= 70) && (tau_influence < 70)) { adjust_influence[tau_influence_planet](eFACTION.TAU, 10, tau_influence_planet); if (p_type[tau_influence_planet] == "Forge") { - adjust_influence(eFACTION.TAU, -5, tau_influence_planet); + adjust_influence(eFACTION.TAU, -5, tau_influence_planet, self); } } if ((tau_influence_chance <= 3) && (tau_influence < 70)) { - adjust_influence(eFACTION.TAU, 30, tau_influence_planet); + adjust_influence(eFACTION.TAU, 30, tau_influence_planet, self); if (p_type[tau_influence_planet] == "Forge") { - adjust_influence(eFACTION.TAU, -25, tau_influence_planet); + adjust_influence(eFACTION.TAU, -25, tau_influence_planet, self); } } } @@ -987,18 +988,16 @@ function fleet_arrival_logic() { with (obj_star) { if (owner != eFACTION.TAU) { - instance_deactivate_object(instance_id); + instance_deactivate_object(self); } } - var good; - good = 0; + var good = 0; repeat (100) { - var xx, yy; if (good == 0) { - xx = x + choose(random(300), random(300) * -1); - yy = y + choose(random(300), random(300) * -1); + var xx = x + choose(random(300), random(300) * -1); + var yy = y + choose(random(300), random(300) * -1); new_star = instance_nearest(xx, yy, obj_star); if (new_star.owner != eFACTION.TAU) { with (new_star) { @@ -1011,10 +1010,7 @@ function fleet_arrival_logic() { } } - // show_message("Get the fuck out working?: "+string(good)); - if (new_star.owner == eFACTION.TAU) { - // show_message("Tau fleet actually fleeing"); action_x = new_star.x; action_y = new_star.y; set_fleet_movement(); @@ -1031,9 +1027,7 @@ function fleet_arrival_logic() { if ((cur_star.x == old_x) && (cur_star.y == old_y) && (cur_star.owner == self.owner) && (cur_star.action == "") && ((owner == eFACTION.TAU) || (owner == eFACTION.CHAOS)) && (mergus == 10) && (!_csm)) { // Move somewhere new - var stue, stue2; - stue = 0; - stue2 = 0; + var stue2 = noone; var goood = 0; with (obj_star) { @@ -1041,7 +1035,7 @@ function fleet_arrival_logic() { instance_deactivate_object(id); } } - stue = instance_nearest(x, y, obj_star); + var stue = instance_nearest(x, y, obj_star); instance_deactivate_object(stue); repeat (10) { if (goood == 0) { @@ -1065,7 +1059,7 @@ function fleet_arrival_logic() { } action_x = stue2.x; action_y = stue2.y; - set_fleet_movement(); // stue.present_fleets-=1; + set_fleet_movement(); instance_activate_object(obj_star); } @@ -1084,7 +1078,7 @@ function fleet_arrival_logic() { var kay = 0, temp5 = 0, temp6 = 0, temp7 = 0; - var cur_star = instance_nearest(x, y, obj_star); + cur_star = instance_nearest(x, y, obj_star); // This is the new check to go along code; if doesn't add up to all planets = 7 then they exit if (!is_dead_star(cur_star)) { @@ -1102,7 +1096,7 @@ function fleet_arrival_logic() { if (owner == eFACTION.ORK) { with (obj_star) { if (owner == eFACTION.ORK) { - instance_deactivate_object(instance_id); + instance_deactivate_object(self); } } } @@ -1130,7 +1124,6 @@ function fleet_arrival_logic() { action_y = temp7.y; set_fleet_movement(); - // cur_star.present_fleets-=1; } instance_activate_object(obj_star); @@ -1141,7 +1134,7 @@ function fleet_arrival_logic() { instance_activate_object(obj_star); } - exit; // end of eta=0 + exit; } /// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet @@ -1170,8 +1163,8 @@ function choose_fleet_sprite_image() { image_speed = 0; } -/// @param {Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet} main_fleet -/// @param {Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet} merge_fleet +/// @param {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} main_fleet +/// @param {Id.Instance.obj_en_fleet|Id.Instance.obj_p_fleet} merge_fleet function merge_fleets(main_fleet, merge_fleet) { main_fleet.capital_number += merge_fleet.capital_number; main_fleet.frigate_number += merge_fleet.frigate_number; @@ -1216,7 +1209,6 @@ function fleet_respond_crusade() { } var enemu; - //var cs with (obj_star) { var cs = instance_nearest(x, y, obj_crusade); diff --git a/scripts/scr_forge_world_functions/scr_forge_world_functions.gml b/scripts/scr_forge_world_functions/scr_forge_world_functions.gml index 3826cea3f2..3733008d02 100644 --- a/scripts/scr_forge_world_functions/scr_forge_world_functions.gml +++ b/scripts/scr_forge_world_functions/scr_forge_world_functions.gml @@ -186,12 +186,12 @@ function build_planet_defence_fleets() { var forge = array_random_element(_mechanicus_worlds); var _current_imperial_fleet = scr_orbiting_fleet(eFACTION.IMPERIUM, forge); var _defence_fleet = false; - if (_current_imperial_fleet != "none") { + if (_current_imperial_fleet != noone) { if (!_current_imperial_fleet.navy) { _defence_fleet = true; } } else { - var _current_imperial_fleet = instance_create(forge.x, forge.y, obj_en_fleet); + _current_imperial_fleet = instance_create(forge.x, forge.y, obj_en_fleet); _defence_fleet = true; with (_current_imperial_fleet) { navy = false; diff --git a/scripts/scr_garrison/scr_garrison.gml b/scripts/scr_garrison/scr_garrison.gml index 9439e40c4e..746a20eac7 100644 --- a/scripts/scr_garrison/scr_garrison.gml +++ b/scripts/scr_garrison/scr_garrison.gml @@ -280,7 +280,6 @@ function GarrisonForce(system, planet, type = "garrison") constructor { static determine_battle = function(attack_defend, win, margin, enemy, location, planet = 0, ship = 0) { var _sim = global.character_tester; if (win) {} else { - //var squad_positions; var _leader; var m; var _unit; @@ -342,12 +341,12 @@ function GarrisonForce(system, planet, type = "garrison") constructor { }; } -function determine_pdf_defence(pdf, garrison = "none", planet_forti = 0, enemy = 0) { +function determine_pdf_defence(pdf, garrison = noone, planet_forti = 0, enemy = 0) { var explanations = ""; var defence_mult = planet_forti * 0.1; var pdf_score = 0; explanations += $"Planet Defences:X{defence_mult + 1}#"; - if (garrison != "none") { + if (garrison != noone) { //if player supports give garrison bonus var garrison_mult = garrison.viable_garrison * (0.008 + (0.001 * planet_forti)); var siege_masters = scr_has_adv("Siege Masters"); diff --git a/scripts/scr_get_item_names/scr_get_item_names.gml b/scripts/scr_get_item_names/scr_get_item_names.gml index 9f91a71d50..ee9430e912 100644 --- a/scripts/scr_get_item_names/scr_get_item_names.gml +++ b/scripts/scr_get_item_names/scr_get_item_names.gml @@ -762,7 +762,7 @@ function scr_get_item_names(_item_names, _role, _slot, _engagement, _include_com undefined, // no range filter false, // not master crafted undefined, // no required tags - ["vehicle"], // exclude vehicle gear + ["vehicle", "no_equip"], // exclude vehicle gear + unequippable items _with_none_if_not_skip, true // with_any ); diff --git a/scripts/scr_gift_items/scr_gift_items.gml b/scripts/scr_gift_items/scr_gift_items.gml index 2d9d809857..b1b22bd940 100644 --- a/scripts/scr_gift_items/scr_gift_items.gml +++ b/scripts/scr_gift_items/scr_gift_items.gml @@ -55,8 +55,6 @@ function gift_artifact(give_to, known = true) { var artifact_struct = obj_ini.artifact_struct[arti_index]; var cur_tags = obj_ini.artifact_tags[arti_index]; - // obj_controller.artifacts-=1; // this is done by delete_artifact() that is run later; - obj_controller.cooldown = 10; if (obj_controller.menu_artifact > obj_controller.artifacts) { obj_controller.menu_artifact = obj_controller.artifacts; @@ -214,16 +212,13 @@ function setup_gift_popup() { fac_buttons = []; + var _y1 = 131; for (var i = 2; i <= 8; i++) { if (i == 7) { continue; } - var _y1 = 131; - if (i > 2) { - var _y1 = _last_y; - } var _fac_but = new UnitButtonObject({x1: 660, w: 147, set_width: true, y1: _y1, style: "pixel", label: obj_controller.faction[i], faction: i, tooltip: $"Disposition : {obj_controller.disposition[i]}"}); - var _last_y = _fac_but.y2; + _y1 = _fac_but.y2; array_push(fac_buttons, _fac_but); } } @@ -243,10 +238,9 @@ function setup_gift_stc_popup() { } function gift_stc_fragment() { - var r1, r2, cn; - r2 = 0; - cn = obj_controller; - r1 = floor(random(cn.stc_wargear_un + cn.stc_vehicles_un + cn.stc_ships_un)) + 1; + var r2 = 0; + var cn = obj_controller; + var r1 = floor(random(cn.stc_wargear_un + cn.stc_vehicles_un + cn.stc_ships_un)) + 1; if ((r1 < cn.stc_wargear_un) && (cn.stc_wargear_un > 0)) { r2 = 1; @@ -301,8 +295,7 @@ function gift_stc_fragment() { scr_toggle_diplomacy(); obj_controller.diplomacy = giveto; obj_controller.force_goodbye = -1; - var the; - the = ""; + var the = ""; if ((giveto != eFACTION.ORK) && (giveto != eFACTION.CHAOS)) { the = "the "; } diff --git a/scripts/scr_ground_ai_helpers/scr_ground_ai_helpers.gml b/scripts/scr_ground_ai_helpers/scr_ground_ai_helpers.gml index fb6bd8f317..c86f369f98 100644 --- a/scripts/scr_ground_ai_helpers/scr_ground_ai_helpers.gml +++ b/scripts/scr_ground_ai_helpers/scr_ground_ai_helpers.gml @@ -1,5 +1,3 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information function system_guard_total() { var total = 0; for (var i = 1; i <= planets; i++) { @@ -8,8 +6,8 @@ function system_guard_total() { return total; } -function planet_imperial_base_enemies(planet, star = "none") { - if (star == "none") { +function planet_imperial_base_enemies(planet, star = noone) { + if (star == noone) { return p_orks[planet] + p_tau[planet] + p_chaos[planet] + p_traitors[planet] + p_tyranids[planet] + p_necrons[planet]; } else { with (star) { diff --git a/scripts/scr_has_adv/scr_has_adv.gml b/scripts/scr_has_adv/scr_has_adv.gml index e67a46ad2b..b5428d6407 100644 --- a/scripts/scr_has_adv/scr_has_adv.gml +++ b/scripts/scr_has_adv/scr_has_adv.gml @@ -3,8 +3,8 @@ * @return {Bool} */ function scr_has_adv(advantage) { + var result = false; try { - var result; if (instance_exists(obj_creation)) { result = selected_chapter_trait(advantage); } else { @@ -12,15 +12,6 @@ function scr_has_adv(advantage) { } } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); - result = false; } return result; - - // var adv_count = array_length(obj_ini.adv); - // for(var i = 0; i < adv_count; i++){ - // if(obj_ini.adv[i] == advantage){ - // return true; - // } - // } - // return false; } diff --git a/scripts/scr_has_disadv/scr_has_disadv.gml b/scripts/scr_has_disadv/scr_has_disadv.gml index 41b3f787f1..4907eb46b7 100644 --- a/scripts/scr_has_disadv/scr_has_disadv.gml +++ b/scripts/scr_has_disadv/scr_has_disadv.gml @@ -3,8 +3,8 @@ * @return {Bool} */ function scr_has_disadv(disadvantage) { + var result = false; try { - var result; if (instance_exists(obj_creation)) { result = selected_chapter_trait(disadvantage); } else { @@ -12,14 +12,6 @@ function scr_has_disadv(disadvantage) { } } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); - result = false; } return result; - // var disadv_count = array_length(obj_ini.dis); - // for(var i = 0; i < disadv_count; i++){ - // if(obj_ini.dis[i] == disadvantage){ - // return true; - // } - // } - // return false; } diff --git a/scripts/scr_hit/scr_hit.gml b/scripts/scr_hit/scr_hit.gml index eac8d57182..f41d4a714f 100644 --- a/scripts/scr_hit/scr_hit.gml +++ b/scripts/scr_hit/scr_hit.gml @@ -1,7 +1,12 @@ /// @function scr_hit /// @description Returns true if mouse is hovering on the specified rectangle area. -/// @returns {bool} -function scr_hit(x1 = 0, y1 = 0, x2 = 0, y2 = 0, force_gui = false) { +/// @param {Real|Array} x1 +/// @param {Real} y1 +/// @param {Real} x2 +/// @param {Real} y2 +/// @param {Bool} force_gui +/// @returns {Bool} +function scr_hit(x1, y1 = 0, x2 = 0, y2 = 0, force_gui = false) { var _mouse_consts = force_gui ? [device_mouse_x_to_gui(0), device_mouse_y_to_gui(0)] : return_mouse_consts(); if (is_array(x1)) { return point_in_rectangle(_mouse_consts[0], _mouse_consts[1], x1[0], x1[1], x1[2], x1[3]); @@ -12,28 +17,52 @@ function scr_hit(x1 = 0, y1 = 0, x2 = 0, y2 = 0, force_gui = false) { /// @function sr_hit_struct /// @description Returns true if mouse is hovering on the specified rectangle area runs withi any valid strucct with x1, y1, x2, y2. -/// @returns {bool} +/// @param {Bool} force_gui +/// @returns {Bool} /// @mixin function sr_hit_struct(force_gui = false){ var _mouse_consts = force_gui ? [device_mouse_x_to_gui(0), device_mouse_y_to_gui(0)] : return_mouse_consts(); return point_in_rectangle(_mouse_consts[0], _mouse_consts[1], x1, y1, x2, y2); } +/// @function scr_hit_object +/// @description +/// @param {Bool} force_gui +/// @returns {Bool} function scr_hit_object(force_gui = false){ var _mouse_consts = force_gui ? [device_mouse_x_to_gui(0), device_mouse_y_to_gui(0)] : return_mouse_consts(); return point_in_rectangle(_mouse_consts[0], _mouse_consts[1], x, y, x + width, y + height); } +/// @function scr_hit_relative +/// @description +/// @param {Array} x1 +/// @param {Array} relative +/// @returns {Bool} function scr_hit_relative(x1, relative = [0, 0]) { var _mouse_consts = return_mouse_consts(); return point_in_rectangle(_mouse_consts[0], _mouse_consts[1], relative[0] + x1[0], relative[1] + x1[1], relative[0] + x1[2], relative[1] + x1[3]); } +/// @function scr_hit_dimensions +/// @description +/// @param {Real} x1 +/// @param {Real} y1 +/// @param {Real} w +/// @param {Real} h +/// @returns {Bool} function scr_hit_dimensions(x1 = 0, y1 = 0, w = 0, h = 0) { var _mouse_consts = return_mouse_consts(); return point_in_rectangle(_mouse_consts[0], _mouse_consts[1], x1, y1, x1 + w, y1 + h); } +/// @function _point_and_click_logic +/// @description +/// @param {Array} _rect +/// @param {Real} _cooldown +/// @param {Bool} _lock_bypass +/// @param {Bool} _inverted +/// @returns {Bool} function _point_and_click_logic(_rect, _cooldown = 60, _lock_bypass = false, _inverted = false) { if (!_lock_bypass && global.ui_click_lock) { return false; @@ -105,12 +134,26 @@ function point_outside_and_click(_rect, _cooldown = 60, _lock_bypass = false) { return _point_and_click_logic(_rect, _cooldown, _lock_bypass, true); } +/// @function point_and_click_sprite +/// @description +/// @param {Real} x1 +/// @param {Real} y1 +/// @param {Asset.GMSprite} sprite +/// @param {Real} x_scale +/// @param {Real} y_scale +/// @returns {Bool} function point_and_click_sprite(x1, y1, sprite, x_scale = 1, y_scale = 1) { var _width = sprite_get_width(sprite) * x_scale; var _height = sprite_get_height(sprite) * y_scale; return point_and_click([x1, y1, x1 + _width, y1 + _height]); } +/// @function mouse_button_clicked +/// @description +/// @param {Constant} button +/// @param {Real} cooldown +/// @param {Bool} lock_bypass +/// @returns {Bool} function mouse_button_clicked(button = mb_left, cooldown = 60, lock_bypass = false) { if (lock_bypass == false && global.ui_click_lock == true) { return false; @@ -165,6 +208,10 @@ function mouse_button_clicked(button = mb_left, cooldown = 60, lock_bypass = fal return mouse_clicked; } +/// @function mouse_button_held +/// @description +/// @param {Constant} _button +/// @returns {Bool} function mouse_button_held(_button = mb_left) { var mouse_held = event_number == ev_gui ? device_mouse_check_button(0, _button) : mouse_check_button(_button); if (!mouse_held) { @@ -200,19 +247,21 @@ function mouse_button_held(_button = mb_left) { return mouse_held; } +/// @function return_mouse_consts +/// @description +/// @returns {Array} function return_mouse_consts() { - var mouse_const_x; - var mouse_const_y; - if (event_number == ev_gui) { - mouse_const_x = device_mouse_x_to_gui(0); - mouse_const_y = device_mouse_y_to_gui(0); - } else { - mouse_const_x = mouse_x; - mouse_const_y = mouse_y; - } + var mouse_const_x = (event_number == ev_gui) ? device_mouse_x_to_gui(0) : mouse_x; + var mouse_const_y = (event_number == ev_gui) ? device_mouse_y_to_gui(0) : mouse_y; return [mouse_const_x, mouse_const_y]; } +/// @function mouse_distance_less +/// @description +/// @param {Real} xx +/// @param {Real} yy +/// @param {Real} distance +/// @returns {Bool} function mouse_distance_less(xx, yy, distance) { var _mouse_consts = return_mouse_consts(); return point_distance(xx, yy, _mouse_consts[0], _mouse_consts[1]) <= distance; diff --git a/scripts/scr_image/scr_image.gml b/scripts/scr_image/scr_image.gml index 80842ab002..31d92be2bd 100644 --- a/scripts/scr_image/scr_image.gml +++ b/scripts/scr_image/scr_image.gml @@ -282,11 +282,8 @@ function scr_image(path, image_id, x1, y1, width, height) { with (obj_img) { // Initialize these images - var i, single_image; - i = -1; - single_image = false; - repeat (80) { - i += 1; + var single_image = false; + for (var i = 0; i < 80; i++) { if ((path == "creation") && (creation_exists[i] > 0) && sprite_exists(creation[i])) { sprite_delete(creation[i]); @@ -507,12 +504,9 @@ function scr_image(path, image_id, x1, y1, width, height) { } if (single_image == false) { - var i, w; - i = 0; - w = 0; + var w = 0; - repeat (40) { - i += 1; + for (var i = 1; i <= 40; i++) { if (path == "main_splash") { if (file_exists(working_directory + "/images/creation/main" + string(i) + ".png")) { main[i - 1] = sprite_add(working_directory + "/images/creation/main" + string(i) + ".png", 1, false, false, 0, 0); @@ -738,16 +732,15 @@ function scr_image(path, image_id, x1, y1, width, height) { if ((path != "") && (image_id >= 0) && (image_id != 666)) { with (obj_img) { // Draw the image - var drawing_sprite, drawing_exists, old_alpha, old_color, x13, y13, x14, y14; - drawing_sprite = 0; - drawing_exists = false; - x13 = 0; - y13 = 0; - x14 = 0; - y14 = 0; + var drawing_sprite = undefined; + var drawing_exists = false; + var x13 = 0; + var y13 = 0; + var x14 = 0; + var y14 = 0; - old_alpha = draw_get_alpha(); - old_color = draw_get_colour(); + var old_alpha = draw_get_alpha(); + var old_color = draw_get_colour(); if (path == "creation") { if ((creation_exists[1] > 0) && sprite_exists(creation[1])) { @@ -930,7 +923,7 @@ function scr_image(path, image_id, x1, y1, width, height) { /// @param {Bool} use_app_data determines whether reading from `datafiles` or `%LocalAppData%\ChapterMaster` folder function scr_image_cache(path, image_id, use_app_data = false) { try { - var drawing_sprite; + var drawing_sprite = undefined; var cache_arr_exists = struct_exists(obj_img.image_cache, path); if (!cache_arr_exists) { variable_struct_set(obj_img.image_cache, path, array_create(100, -1)); @@ -979,6 +972,7 @@ function scr_image_cache(path, image_id, use_app_data = false) { /// @description Simplified handling of chapter icon stuff for both Creation and player chapter icon /// attempting to keep things consistent and easy through save/load and etc +/// @param {String} _name /// @param {Bool} update_global_var set to true when wanting to update the player's icon, false if you just want to return the sprite for further use function scr_load_chapter_icon(_name, update_global_var = false) { if (!ds_map_exists(global.chapter_icons_map, _name)) { diff --git a/scripts/scr_imperial_manage_fleet_functions/scr_imperial_manage_fleet_functions.gml b/scripts/scr_imperial_manage_fleet_functions/scr_imperial_manage_fleet_functions.gml index 44a93f9fa9..474c49b8a8 100644 --- a/scripts/scr_imperial_manage_fleet_functions/scr_imperial_manage_fleet_functions.gml +++ b/scripts/scr_imperial_manage_fleet_functions/scr_imperial_manage_fleet_functions.gml @@ -41,8 +41,8 @@ function new_colony_fleet(doner_star, doner_planet, target, target_planet, missi scr_event_log("green", $"New colony fleet departs from {doner_star.name}. for the {target.name} system", doner_star.name); } -function fleet_has_cargo(desired_cargo, fleet = "none") { - if (fleet == "none") { +function fleet_has_cargo(desired_cargo, fleet = noone) { + if (fleet == noone) { return struct_exists(cargo_data, desired_cargo); } else { var has_cargo = false; @@ -53,8 +53,8 @@ function fleet_has_cargo(desired_cargo, fleet = "none") { } } -function fleet_add_cargo(new_cargo, data, overwrite = false, fleet = "none") { - if (fleet == "none") { +function fleet_add_cargo(new_cargo, data, overwrite = false, fleet = noone) { + if (fleet == noone) { var _add = true; if (fleet_has_cargo(new_cargo) && !overwrite) { _add = false; diff --git a/scripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gml b/scripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gml index 9006474a97..4365e7ec68 100644 --- a/scripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gml +++ b/scripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gml @@ -86,11 +86,9 @@ function navy_orbiting_planet_end_turn_action() { /// @self Asset.GMObject.obj_en_fleet function check_navy_guard_still_live() { - var o = 0; if (guardsmen_unloaded) { - var o = 0, guardsmen_dead = true; - repeat (orbiting.planets) { - o += 1; + var guardsmen_dead = true; + for (var o = 1; o <= orbiting.planets; o++) { if (orbiting.p_guardsmen[o] > 0) { guardsmen_dead = false; break; @@ -141,9 +139,9 @@ function build_new_navy_fleet(construction_forge) { /// @self Asset.GMObject.obj_en_fleet function new_navy_ships_forge() { if (trade_goods == "building_ships") { - var onceh = 0, advance = false, p = 0; + var onceh = 0; + var advance = false; - p = 0; is_orbiting(); for (var p = 1; p <= orbiting.planets; p++) { if (orbiting.p_type[p] == "Forge") { @@ -198,7 +196,6 @@ function new_navy_ships_forge() { trade_goods = ""; } - //if (trade_goods="building_ships" || !advance) then exit; end_sequence_finished = true; } } @@ -306,7 +303,7 @@ function navy_hunt_player_assets() { if (hold) { // Chase player fleets var chase_fleet = get_nearest_player_fleet(x, y, false, true); - if (chase_fleet != "none") { + if (chase_fleet != noone) { var thatp, my_dis; etah = chase_fleet.eta; @@ -420,22 +417,6 @@ function navy_hunt_player_assets() { with (obj_temp8) { instance_destroy(); } - - /*var homeworld_distance,homeworld_nearby,fleet_nearby,fleet_distance; - homeworld_distance=9999;fleet_distance=9999;fleet_nearby=0;homeworld_nearby=0; - - with(obj_p_fleet){if (action!="") then y-=20000;}// Disable non-stationary player fleets - if (instance_exists(obj_p_fleet)){fleet_nearby=instance_nearest(x,y,obj_p_fleet);fleet_distance=point_distance(x,y,fleet_nearby.x,fleet_nearby.y);}// Get closest player fleet - with(obj_star){if (owner = eFACTION.PLAYER) then instance_create(x,y,obj_temp7);}// Create temp7 at player stars - if (instance_exists(obj_temp7)){homeworld_nearby=instance_nearest(x,y,obj_temp7);homeworld_distance=point_distance(x,y,homeworld_nearby.x,homeworld_nearby.y);}// Get closest star - with(obj_p_fleet){if (y<-10000) then y+=20000;}// Enable non-stationary player fleets - - if (homeworld_distance<=fleet_distance && homeworld_distance<7000 && instance_exists(homeworld_nearby)){// Go towards planet - action_x=homeworld_nearby.x;action_y=homeworld_nearby.y;set_fleet_movement();;exit; - } - - - */ } } @@ -471,33 +452,26 @@ function navy_attack_player_world() { if (obj_controller.faction_status[eFACTION.IMPERIUM] == "War" && trade_goods == "invade_player" && guardsmen_unloaded == 0) { if (instance_exists(orbiting)) { var tar = 0; - var i = 0; - for (i = 1; i <= orbiting.planets; i++) { + for (var i = 1; i <= orbiting.planets; i++) { if ((orbiting.p_owner[i] == eFACTION.PLAYER) && (planet_feature_bool(orbiting.p_feature[i], eP_FEATURES.MONASTERY) == 0) && (orbiting.p_guardsmen[i] == 0)) { tar = i; } } if (tar) { guardsmen_unloaded = 1; - i = 0; - repeat (20) { - i += 1; + for (var i = 1; i <= 20; i++) { if (capital_imp[i] > 0) { orbiting.p_guardsmen[tar] += capital_imp[i]; capital_imp[i] = 0; } } - i = 0; - repeat (30) { - i += 1; + for (var i = 1; i <= 30; i++) { if (frigate_imp[i] > 0) { orbiting.p_guardsmen[tar] += frigate_imp[i]; frigate_imp[i] = 0; } } - i = 0; - repeat (30) { - i += 1; + for (var i = 1; i <= 30; i++) { if (escort_imp[i] > 0) { orbiting.p_guardsmen[tar] += escort_imp[i]; escort_imp[i] = 0; @@ -529,7 +503,7 @@ function navy_bombard_player_world() { hostile_fleet_count += present_fleet[eFACTION.PLAYER] + present_fleet[eFACTION.ELDAR] + present_fleet[eFACTION.ORK] + present_fleet[eFACTION.TAU] + present_fleet[eFACTION.TYRANIDS] + present_fleet[eFACTION.CHAOS] + present_fleet[eFACTION.NECRONS]; } if (hostile_fleet_count == 0) { - var bombard = 0, deaths = 0, hurss = 0, onceh = 0, wob = 0, kill = 0; + var deaths = 0, hurss = 0, onceh = 0, wob = 0, kill = 0; for (var o = 1; o <= orbiting.planets; o++) { if (orbiting.p_owner[o] == eFACTION.PLAYER) { @@ -890,7 +864,7 @@ function scr_navy_has_unloaded_guardsmen_turn_end() { /// @self Asset.GMObject.obj_en_fleet function scr_navy_recruit_new_guard() { - var o = 0, that = 0, te = 0, te_large = 0; + var that = 0, te = 0, te_large = 0; for (var o = 1; o <= orbiting.planets; o++) { if (orbiting.p_owner[o] <= 5) { var _imp_enemies = has_imperial_enemies(o, orbiting); @@ -914,7 +888,6 @@ function scr_navy_recruit_new_guard() { var recruit_planet = orbiting.get_planet_data(that); - // if (orbiting.p_population[that] guard_wanted || recruit_planet.large_population) { if (recruit_planet.large_population) { guard_wanted = recruit_planet.population_large_conversion(1000000000); diff --git a/scripts/scr_ini_ship_cleanup/scr_ini_ship_cleanup.gml b/scripts/scr_ini_ship_cleanup/scr_ini_ship_cleanup.gml index e60b9dca76..ae90424800 100644 --- a/scripts/scr_ini_ship_cleanup/scr_ini_ship_cleanup.gml +++ b/scripts/scr_ini_ship_cleanup/scr_ini_ship_cleanup.gml @@ -31,10 +31,11 @@ function scr_kill_ship(index) { var in_warp = ship_location[index] == "Warp"; var _available_ships = []; var _ship_fleet = find_ships_fleet(index); + var _nearest_star = noone; if (!in_warp) { - var _nearest_star = find_star_by_name(ship_location[index]); + _nearest_star = find_star_by_name(ship_location[index]); } - if (_ship_fleet != "none") { + if (_ship_fleet != noone) { delete_ship_from_fleet(index, _ship_fleet); _available_ships = fleet_full_ship_array(_ship_fleet); } @@ -103,7 +104,7 @@ function scr_kill_ship(index) { array_delete(ship_guardsmen_max, index, 1); if (!in_warp) { - if (_nearest_star != "none") { + if (_nearest_star != noone) { while (array_length(_units_on_ship) > 0) { _unit = array_pop(_units_on_ship); if (irandom(100) > 100 - _unit.luck) { diff --git a/scripts/scr_initialize_custom/scr_initialize_custom.gml b/scripts/scr_initialize_custom/scr_initialize_custom.gml index 34acd5719a..7bee2adb51 100644 --- a/scripts/scr_initialize_custom/scr_initialize_custom.gml +++ b/scripts/scr_initialize_custom/scr_initialize_custom.gml @@ -719,8 +719,6 @@ function trial_map(trial_name) { /// @self Asset.GMObject.obj_ini function scr_initialize_custom() { - // LOGGER.debug("Executing scr_initialize_custom"); - progenitor = obj_creation.founding; successors = obj_creation.successors; homeworld_rule = obj_creation.homeworld_rule; @@ -731,38 +729,14 @@ function scr_initialize_custom() { recruit_relative_loc = obj_creation.buttons.recruit_home_relationship.current_selection; culture_styles = obj_creation.buttons.culture_styles.selections(); - if (struct_exists(obj_creation, "custom_advisors")) { + if (variable_instance_exists(obj_creation, "custom_advisors")) { obj_ini.custom_advisors = obj_creation.custom_advisors; } - // Initializes all of the marine/vehicle/ship variables for the chapter. - - techmarines = 8; - apothecary = 8; - epistolary = 2; - codiciery = 2; - lexicanum = 4; - terminator = 40; - veteran = 70; - second = 100; - third = 100; - fourth = 100; - fifth = 100; - sixth = 100; - seventh = 100; - eighth = 100; - ninth = 100; - tenth = 100; - assault = 20; - devastator = 20; - siege = 0; - recruit_trial = obj_creation.aspirant_trial; purity = obj_creation.purity; stability = obj_creation.stability; - // show_message(instance_number(obj_controller)); - global.chapter_name = obj_creation.chapter_name; global.founding = obj_creation.founding; global.founding_secret = ""; @@ -786,7 +760,7 @@ function scr_initialize_custom() { "", "" ]; - if (struct_exists(obj_creation, "company_title")) { + if (variable_instance_exists(obj_creation, "company_title")) { for (var ct = 0; ct < array_length(obj_creation.company_title); ct++) { company_title[ct] = obj_creation.company_title[ct]; } @@ -832,7 +806,6 @@ function scr_initialize_custom() { for (var i = 0; i < array_length(obj_creation.all_advantages); i++) { var _adv = obj_creation.all_advantages[i]; if (_adv.activated) { - // LOGGER.info($"{_adv}"); array_push(adv, _adv.name); chapter_data.add_trait_data(_adv); } @@ -841,7 +814,6 @@ function scr_initialize_custom() { for (var i = 0; i < array_length(obj_creation.all_disadvantages); i++) { var _disadv = obj_creation.all_disadvantages[i]; if (_disadv.activated) { - // LOGGER.info($"{_disadv}"); array_push(dis, _disadv.name); chapter_data.add_trait_data(_disadv); } @@ -912,7 +884,7 @@ function scr_initialize_custom() { if (scr_has_adv("Boarders")) { strike_cruisers += 2; } - if (struct_exists(obj_creation, "extra_ships")) { + if (variable_instance_exists(obj_creation, "extra_ships")) { battle_barges = battle_barges + obj_creation.extra_ships.battle_barges; strike_cruisers = strike_cruisers + obj_creation.extra_ships.strike_cruisers; gladius = gladius + obj_creation.extra_ships.gladius; @@ -920,13 +892,11 @@ function scr_initialize_custom() { } var ship_summary_str = $"Ships: bb: {battle_barges} sc: {strike_cruisers} g: {gladius} h: {hunters}"; - // LOGGER.info(ship_summary_str); - // LOGGER.debug(ship_summary_str); if (battle_barges >= 1) { - for (v = 0; v < battle_barges; v++) { + for (var i = 0; i < battle_barges; i++) { var new_ship = new_player_ship("Battle Barge", "home"); - if ((flagship_name != "") && (v == 0)) { + if ((flagship_name != "") && (i == 0)) { ship[new_ship] = flagship_name; } } @@ -991,15 +961,42 @@ function scr_initialize_custom() { millenium = 41; #region Determine Total Number of Marines per Company and Role - var company = 0; - var second = 100, third = 100, fourth = 100, fifth = 100, sixth = 100, seventh = 100, eighth = 100, ninth = 100, tenth = 100; - var siege = 0, temp1 = 0, intolerant = 0; - var k, v; - k = 0; - v = 0; + var intolerant = 0; /* Default Specialists */ - var chaplains = 8, chaplains_per_company = 1, techmarines = 8, techmarines_per_company = 1, apothecary = 8, apothecary_per_company = 1, epistolary = 2, epistolary_per_company = 1, codiciery = 2, lexicanum = 4, terminator = 20, veteran = 85, assault = 20, devastator = 20, dreadnought = 1, rhino = 8, whirlwind = 4, landspeeder = 2, predator = 2, landraider = 6; + var chaplains_per_company = 1; + var techmarines_per_company = 1; + var apothecary_per_company = 1; + var epistolary_per_company = 1; + + var rhino = 8; + var whirlwind = 4; + var landspeeder = 2; + var predator = 2; + var landraider = 6; + + var chaplains = 8; + var techmarines = 8; + var apothecary = 8; + var epistolary = 2; + var codiciery = 2; + var lexicanum = 4; + var terminator = 20; + var dreadnought = 1; + var veteran = 85; + var assault = 20; + var devastator = 20; + var siege = 0; + + var second = 100; + var third = 100; + var fourth = 100; + var fifth = 100; + var sixth = 100; + var seventh = 100; + var eighth = 100; + var ninth = 100; + var tenth = 100; /* Used for summing total count */ specials = 0; @@ -1014,11 +1011,6 @@ function scr_initialize_custom() { ninths = 0; tenths = 0; - /*techs=20;epistolary=5;apothecary=6;codiciery=6;lexicanum=10;terminator=30;veteran=30; - second=9;third=9;fourth=9;fifth=9;sixth=9;seventh=9;ei; - ninth=9;tenth=10; - assault=2;siege=0;devastator=2;*/ - var chapter_option, o; if (scr_has_adv("Lightning Warriors")) { rhino -= 2; @@ -1202,9 +1194,9 @@ function scr_initialize_custom() { if (scr_has_disadv("Obliterated")) { bonus_marines = (obj_creation.strength - 1) * 10; } - var i = 0; + var _bm = 0; while (bonus_marines >= 5) { - switch (i % 10) { + switch (_bm % 10) { case 0: if (veteran > 0) { bonus_marines -= 5; @@ -1266,16 +1258,15 @@ function scr_initialize_custom() { } break; } - i++; + _bm++; } - if (struct_exists(obj_creation, "extra_specialists")) { + if (variable_instance_exists(obj_creation, "extra_specialists")) { var c_specialists = obj_creation.extra_specialists; var c_specialist_names = struct_get_names(c_specialists); for (var s = 0; s < array_length(c_specialist_names); s++) { var s_name = c_specialist_names[s]; var s_val = struct_get(c_specialists, s_name); - // LOGGER.debug($"updating specialist {s_name} with {s_val})"); switch (s_name) { case "chaplains": chaplains = chaplains + real(s_val); @@ -1327,7 +1318,7 @@ function scr_initialize_custom() { } } - if (struct_exists(obj_creation, "extra_marines")) { + if (variable_instance_exists(obj_creation, "extra_marines")) { var c_marines = obj_creation.extra_marines; var c_marines_names = struct_get_names(c_marines); for (var s = 0; s < array_length(c_marines_names); s++) { @@ -1426,11 +1417,6 @@ function scr_initialize_custom() { } } - /*main_color=obj_creation.main_color; - secondary_color=obj_creation.secondary_color; - lens_color=obj_creation.lens_color; - weapon_color=obj_creation.weapon_color;*/ - master_name = obj_creation.chapter_master_name; chief_librarian_name = obj_creation.clibrarian; high_chaplain_name = obj_creation.hchaplain; @@ -1506,7 +1492,7 @@ function scr_initialize_custom() { if (scr_has_disadv("Psyker Intolerant")) { race[defaults_slot][eROLE.LIBRARIAN] = 0; } - if (struct_exists(obj_creation, "custom_roles")) { + if (variable_instance_exists(obj_creation, "custom_roles")) { var c_roles = obj_creation.custom_roles; var possible_custom_roles = [ [ @@ -1603,9 +1589,6 @@ function scr_initialize_custom() { var attribute = possible_custom_attributes[a]; if (struct_exists(c_roles[$ c_rolename], attribute)) { var value = c_roles[$ c_rolename][$ attribute]; - // var dbg_m = $"role {c_roleid} {c_rolename} updated {attribute} to {typeof(value)} {value}"; - // LOGGER.info(dbg_m); - // LOGGER.debug(dbg_m); switch (attribute) { case "name": role[defaults_slot][c_roleid] = value; @@ -1626,8 +1609,6 @@ function scr_initialize_custom() { mobi[defaults_slot][c_roleid] = value; break; } - // array_set_value(obj_ini[attribute][100][c_roleid], value); - // [$attribute][100][c_roleid] = value; } } } @@ -1654,7 +1635,6 @@ function scr_initialize_custom() { sergeant: role[defaults_slot][eROLE.SERGEANT], veteran_sergeant: role[defaults_slot][eROLE.VETERANSERGEANT], }; - // LOGGER.info($"roles: {json_stringify(roles, true)}") #endregion @@ -1687,7 +1667,7 @@ function scr_initialize_custom() { _squad_name = "Clave"; } } - if (struct_exists(obj_creation, "squad_name")) { + if (variable_instance_exists(obj_creation, "squad_name")) { _squad_name = obj_creation.squad_name; } @@ -1769,8 +1749,7 @@ function scr_initialize_custom() { ]; var _roles_player = obj_ini.role[100]; var _default_player = obj_ini.role[101]; - var i; - for (i = 1; i < 20; i++) { + for (var i = 1; i < 20; i++) { if (_roles_player[i] == "") { continue; } @@ -1784,25 +1763,21 @@ function scr_initialize_custom() { array_push(_swaps, _set); } - for (i = 1; i < 20; i++) { + for (var i = 1; i < 20; i++) { var _set = {}; var _key = $"wep1[{i}]"; var _val = obj_ini.wep1[100][i]; variable_struct_set(_set, _key, _val); array_push(_swaps, _set); - var _set = {}; + _set = {}; _key = $"wep2[{i}]"; _val = obj_ini.wep2[100][i]; variable_struct_set(_set, _key, _val); - array_push(_swaps, _set); } - // LOGGER.debug($"squads object for chapter {chapter_name}"); - // LOGGER.debug($"{custom_squads}"); - - if (struct_exists(obj_creation, "squad_builder")) { + if (variable_instance_exists(obj_creation, "squad_builder")) { for (var s = 0; s < array_length(obj_creation.squad_builder); s++) { var _custom_build = obj_creation.squad_builder[s]; for (var i = 0; i < array_length(obj_ini.chapter_squad_arrangement.companies); i++) { @@ -1814,7 +1789,7 @@ function scr_initialize_custom() { } } - if (struct_exists(obj_creation, "custom_squads")) { + if (variable_instance_exists(obj_creation, "custom_squads")) { var _customs = obj_creation.custom_squads; with (squad_types) { move_data_to_current_scope(_customs); @@ -1822,8 +1797,6 @@ function scr_initialize_custom() { } json_inject_swaps(squad_types, _swaps); - // LOGGER.debug($"roles object for chapter {chapter_name} after setting from obj"); - // LOGGER.debug($"{custom_squads}"); if (global.chapter_name == "Salamanders") { squad_types.assault_squad.loadout = { @@ -1974,8 +1947,6 @@ function scr_initialize_custom() { array_push(_class_data, "scout"); } */ - // LOGGER.debug("Squad types"); - // LOGGER.debug(squad_types); #endregion for (var i = 0; i <= 20; i++) { @@ -1995,12 +1966,15 @@ function scr_initialize_custom() { } initialized = 500; // How many array variables have been prepared - v = 0; - company = 0; + + var _marine_i = 0; + var _vehicle_i = 0; + var _company_i = 0; // TODO: When modding support is implemented, uncomment this init. Otherwise traits are initialized at compile. //loads up marine traits potential modding potential; // initialize_marine_traits(); + #region Chapter HQ for (var c = 0; c < 11; c++) { for (var i = 0; i < 501; i++) { @@ -2022,15 +1996,15 @@ function scr_initialize_custom() { // Chapter Master // This needs work - name[company][0] = obj_creation.chapter_master_name; + name[_company_i][_marine_i] = obj_creation.chapter_master_name; var cm_equip = load_chapter_master_equipment(); - var chapter_master = add_unit_to_company("chapter_master", 0, 0, roles.chapter_master, eROLE.CHAPTERMASTER, cm_equip.wep1, cm_equip.wep2, cm_equip.gear, cm_equip.mobi, cm_equip.armour); + var chapter_master = add_unit_to_company("chapter_master", _company_i, _marine_i, roles.chapter_master, eROLE.CHAPTERMASTER, cm_equip.wep1, cm_equip.wep2, cm_equip.gear, cm_equip.mobi, cm_equip.armour); repeat (cm_equip.bionics) { chapter_master.add_bionics("none", "standard", false); } - spe[company][0] = ""; + spe[_company_i][_marine_i] = ""; chapter_master.add_trait("lead_example"); //builds in which of the three chapter master types your CM is @@ -2038,11 +2012,11 @@ function scr_initialize_custom() { switch (obj_creation.chapter_master_specialty) { case 1: chapter_master.add_exp(550); - spe[company][0] += "$"; + spe[_company_i][_marine_i] += "$"; break; case 2: chapter_master.add_exp(650); - spe[company][0] += "@"; + spe[_company_i][_marine_i] += "@"; chapter_master.add_trait("champion"); break; case 3: @@ -2063,13 +2037,12 @@ function scr_initialize_custom() { if (scr_has_disadv("Poor Equipment")) { _hq_armour = "MK6 Corvus"; } - - k += 1; + _marine_i += 1; commands = 1; // Forge Master - name[company][1] = obj_creation.fmaster; - var _forge_master = add_unit_to_company("marine", company, 1, "Forge Master", eROLE.TECHMARINE, "Infernus Pistol", "Omnissian Axe", "default", "Servo-harness", _hq_armour); + name[_company_i][_marine_i] = obj_creation.fmaster; + var _forge_master = add_unit_to_company("marine", _company_i, _marine_i, "Forge Master", eROLE.TECHMARINE, "Infernus Pistol", "Omnissian Axe", "default", "Servo-harness", _hq_armour); if (_forge_master.technology < 40) { _forge_master.technology = 40; } @@ -2085,87 +2058,87 @@ function scr_initialize_custom() { _forge_master.add_bionics("none", "standard", false); } } - k += 1; + _marine_i += 1; commands += 1; // Master of Sanctity (Chaplain) if (chaplains > 0) { - name[company][2] = high_chaplain_name; - var _hchap = add_unit_to_company("marine", company, 2, "Master of Sanctity", eROLE.CHAPLAIN, "default", "Plasma Pistol", "default", "default", _hq_armour); + name[_company_i][_marine_i] = high_chaplain_name; + var _hchap = add_unit_to_company("marine", _company_i, _marine_i, "Master of Sanctity", eROLE.CHAPLAIN, "default", "Plasma Pistol", "default", "default", _hq_armour); _hchap.edit_corruption(-100); if (_hchap.piety < 45) { _hchap.piety = 45; } _hchap.add_trait("zealous_faith"); - k += 1; + _marine_i += 1; commands += 1; } // Maser of the Apothecarion (Apothecary) - name[company][3] = obj_creation.hapothecary; - var _hapoth = add_unit_to_company("marine", company, 3, "Master of the Apothecarion", eROLE.APOTHECARY, "default", "Plasma Pistol", "default", "default", _hq_armour); + name[_company_i][_marine_i] = obj_creation.hapothecary; + var _hapoth = add_unit_to_company("marine", _company_i, _marine_i, "Master of the Apothecarion", eROLE.APOTHECARY, "default", "Plasma Pistol", "default", "default", _hq_armour); _hapoth.edit_corruption(0); - k += 1; + _marine_i += 1; commands += 1; // Chief Librarian if (!scr_has_disadv("Psyker Intolerant")) { - name[company][4] = obj_creation.clibrarian; - var _clibrarian = add_unit_to_company("marine", company, 4, string("Chief {0}", roles.librarian), eROLE.LIBRARIAN, "default", "Plasma Pistol", "default", "default", _hq_armour); + name[_company_i][_marine_i] = obj_creation.clibrarian; + var _clibrarian = add_unit_to_company("marine", _company_i, _marine_i, string("Chief {0}", roles.librarian), eROLE.LIBRARIAN, "default", "Plasma Pistol", "default", "default", _hq_armour); _clibrarian.edit_corruption(0); _clibrarian.psionic = choose(11, 12); _clibrarian.update_powers(); _clibrarian.add_trait("favoured_by_the_warp"); - k += 1; + _marine_i += 1; commands += 1; } - man_size = k; + man_size = _marine_i; // Techmarines in the armoury repeat (techmarines) { - k += 1; + _marine_i += 1; commands += 1; man_size += 1; - add_unit_to_company("marine", company, k, roles.techmarine, eROLE.TECHMARINE, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); + add_unit_to_company("marine", _company_i, _marine_i, roles.techmarine, eROLE.TECHMARINE, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); } // Librarians in the librarium repeat (epistolary) { - k += 1; + _marine_i += 1; commands += 1; man_size += 1; - var _epi = add_unit_to_company("marine", company, k, roles.librarian, eROLE.LIBRARIAN, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); + var _epi = add_unit_to_company("marine", _company_i, _marine_i, roles.librarian, eROLE.LIBRARIAN, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); } // Codiciery repeat (codiciery) { - k += 1; + _marine_i += 1; commands += 1; man_size += 1; - var _codi = add_unit_to_company("marine", company, k, "Codiciery", eROLE.LIBRARIAN, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); + var _codi = add_unit_to_company("marine", _company_i, _marine_i, "Codiciery", eROLE.LIBRARIAN, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); } // Lexicanum repeat (lexicanum) { - k += 1; + _marine_i += 1; commands += 1; man_size += 1; - var _lexi = add_unit_to_company("marine", company, k, "Lexicanum", eROLE.LIBRARIAN, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); + var _lexi = add_unit_to_company("marine", _company_i, _marine_i, "Lexicanum", eROLE.LIBRARIAN, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); } // Apothecaries in Apothecarion repeat (apothecary) { - k += 1; + _marine_i += 1; commands += 1; man_size += 1; - add_unit_to_company("marine", company, k, roles.apothecary, eROLE.APOTHECARY, "Chainsword", choose_weighted(global.weapon_list_weighted_ranged_pistols)); + add_unit_to_company("marine", _company_i, _marine_i, roles.apothecary, eROLE.APOTHECARY, "Chainsword", choose_weighted(global.weapon_list_weighted_ranged_pistols)); } // Chaplains in Reclusium repeat (chaplains) { - k += 1; + _marine_i += 1; commands += 1; man_size += 1; - add_unit_to_company("marine", company, k, roles.chaplain, eROLE.CHAPLAIN, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); + add_unit_to_company("marine", _company_i, _marine_i, roles.chaplain, eROLE.CHAPLAIN, "default", choose_weighted(global.weapon_list_weighted_ranged_pistols)); } // Honour Guard @@ -2180,13 +2153,13 @@ function scr_initialize_custom() { _honour_guard_count = 3; } for (var i = 0; i < min(_honour_guard_count, 10); i++) { - k += 1; + _marine_i += 1; commands += 1; man_size += 1; - add_unit_to_company("marine", company, k, roles.honour_guard, eROLE.HONOURGUARD); + add_unit_to_company("marine", _company_i, _marine_i, roles.honour_guard, eROLE.HONOURGUARD); } - specials = k; + specials = _marine_i; #endregion #region New Totals Per Company Adjusted @@ -2282,7 +2255,6 @@ function scr_initialize_custom() { }, }; - // LOGGER.info($"Pre balancing company totals: {json_stringify(companies, true)}"); // Extra vehicles loaded from json files all get dumped into the 10th company for the player to sort out var vehicle_keys = [ @@ -2292,9 +2264,9 @@ function scr_initialize_custom() { "land_raider", "land_speeder" ]; - if (struct_exists(obj_creation, "extra_vehicles")) { - for (var v = 0; v < array_length(vehicle_keys); v++) { - var key = vehicle_keys[v]; + if (variable_instance_exists(obj_creation, "extra_vehicles")) { + for (var i = 0; i < array_length(vehicle_keys); i++) { + var key = vehicle_keys[i]; if (struct_exists(obj_creation.extra_vehicles, key) && real(obj_creation.extra_vehicles[$ key]) > 0) { var coy_key = ""; switch (key) { @@ -2321,8 +2293,8 @@ function scr_initialize_custom() { var squad_distribution = obj_creation.squad_distribution; var scout_company_behaviour = 0; - if (struct_exists(obj_creation, "scout_company_behaviour")) { - var scout_company_behaviour = obj_creation.scout_company_behaviour; + if (variable_instance_exists(obj_creation, "scout_company_behaviour")) { + scout_company_behaviour = obj_creation.scout_company_behaviour; } if (scout_company_behaviour == 1) { load_default_gear(eROLE.SCOUT, "Neophyte", "Bolter", "", "Scout Armour", "", ""); @@ -2348,10 +2320,10 @@ function scr_initialize_custom() { } for (var _c = 0, _clen = array_length(_coys); _c < _clen; _c++) { - var k = 0, v = 0; //k = marine slot, v = vehicle slot - var _name = _coys[_c]; var _coy = companies[$ _name]; + _marine_i = 0; + _vehicle_i = 0; if (_coy.total <= 0) { continue; } @@ -2388,9 +2360,6 @@ function scr_initialize_custom() { /// comp 9: dev 100 /// comp 10: tac 40: scout 50; if (squad_distribution == 1 || squad_distribution == 3) { - // LOGGER.info("balancing for equal specialists") - // LOGGER.info($"equal_scouts? {equal_scouts}") - if (_coy.coy >= 2 && _coy.coy <= 9) { if (equal_scouts) { if (companies.tenth.scouts > 10) { @@ -2414,7 +2383,6 @@ function scr_initialize_custom() { _coy.tacticals = _moved_scouts; } } else { - // LOGGER.info("balancing for non-equal specialists") /// Default specialist behaviour, battle companies 2-7 have 90 tacticals each /// and the assaults go into the 8th and devastators into the 9th if (_coy.coy >= 2 && _coy.coy <= 5) { @@ -2468,21 +2436,17 @@ function scr_initialize_custom() { } } - // LOGGER.info($"New Company Totals: eq specialists: {equal_specialists}: scout coy {scout_company_behaviour} equal_scouts: {equal_scouts}"); - // LOGGER.info($"Company {_coy.coy}: {json_stringify(_coy, true)}"); - var _set_company_makeup = function(old_values, new_values) { var _override_keys = struct_get_names(new_values); var _override_keys_count = array_length(_override_keys); for (var j = 0; j < _override_keys_count; j++) { var _okey_hash = _override_keys[j]; var _okey_ins = new_values[$ _okey_hash]; - // LOGGER.info($"{_okey_hash}<{_okey_ins}<{old_values}"); old_values[$ _okey_hash] = _okey_ins; } return old_values; }; - if (struct_exists(obj_creation, "companies")) { + if (variable_instance_exists(obj_creation, "companies")) { var _company_keys = [ "first", "second", @@ -2505,7 +2469,6 @@ function scr_initialize_custom() { } } } - // LOGGER.info($"attrs {attrs}"); var attrs = struct_get_names(_coy); @@ -2529,7 +2492,6 @@ function scr_initialize_custom() { continue; } - // LOGGER.info($"processing: coy {_coy.coy} role {_role} count {_count}"); switch (_role) { // MAINLINE case "tacticals": @@ -2590,34 +2552,34 @@ function scr_initialize_custom() { case "captains": switch (_coy.coy) { case 1: - name[_coy.coy][k] = honor_captain_name != "" ? honor_captain_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = honor_captain_name != "" ? honor_captain_name : global.name_generator.ChapterMemberNameGeneration(); break; case 2: - name[_coy.coy][k] = watch_master_name != "" ? watch_master_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = watch_master_name != "" ? watch_master_name : global.name_generator.ChapterMemberNameGeneration(); break; case 3: - name[_coy.coy][k] = arsenal_master_name != "" ? arsenal_master_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = arsenal_master_name != "" ? arsenal_master_name : global.name_generator.ChapterMemberNameGeneration(); break; case 4: - name[_coy.coy][k] = lord_admiral_name != "" ? lord_admiral_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = lord_admiral_name != "" ? lord_admiral_name : global.name_generator.ChapterMemberNameGeneration(); break; case 5: - name[_coy.coy][k] = march_master_name != "" ? march_master_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = march_master_name != "" ? march_master_name : global.name_generator.ChapterMemberNameGeneration(); break; case 6: - name[_coy.coy][k] = rites_master_name != "" ? rites_master_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = rites_master_name != "" ? rites_master_name : global.name_generator.ChapterMemberNameGeneration(); break; case 7: - name[_coy.coy][k] = chief_victualler_name != "" ? chief_victualler_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = chief_victualler_name != "" ? chief_victualler_name : global.name_generator.ChapterMemberNameGeneration(); break; case 8: - name[_coy.coy][k] = lord_executioner_name != "" ? lord_executioner_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = lord_executioner_name != "" ? lord_executioner_name : global.name_generator.ChapterMemberNameGeneration(); break; case 9: - name[_coy.coy][k] = relic_master_name != "" ? relic_master_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = relic_master_name != "" ? relic_master_name : global.name_generator.ChapterMemberNameGeneration(); break; case 10: - name[_coy.coy][k] = recruiter_name != "" ? recruiter_name : global.name_generator.ChapterMemberNameGeneration(); + name[_coy.coy][_marine_i] = recruiter_name != "" ? recruiter_name : global.name_generator.ChapterMemberNameGeneration(); break; } commands++; @@ -2768,7 +2730,6 @@ function scr_initialize_custom() { _is_vehicle = true; _rolename = "Predator"; _erole = eROLE.PREDATOR; - var variant = choose(1, 1, 2, 3); // 1st company relic predators if (_coy.coy == 1) { _upgrade = "Artificer Hull"; @@ -2819,48 +2780,52 @@ function scr_initialize_custom() { } repeat (_count) { if (_is_vehicle) { - add_veh_to_company(_rolename, _coy.coy, v, _wep1, _wep2, _wep3, _upgrade, _accessory); - v++; - man_size += 10; + if (_vehicle_i < 205) { + add_veh_to_company(_rolename, _coy.coy, _vehicle_i, _wep1, _wep2, _wep3, _upgrade, _accessory); + man_size += 10; + _vehicle_i++; + } } else { - add_unit_to_company(_unit_type, _coy.coy, k, _rolename, _erole, _wep1, _wep2, _gear, _mobi, _armour); - k++; - man_size++; - if (_is_terminator(_armour)) { + if (_marine_i < 500) { + add_unit_to_company(_unit_type, _coy.coy, _marine_i, _rolename, _erole, _wep1, _wep2, _gear, _mobi, _armour); + _marine_i++; man_size++; + if (_is_terminator(_armour)) { + man_size++; + } } } } switch (_coy.coy) { case 1: - firsts = k; + firsts = _marine_i; break; case 2: - seconds = k; + seconds = _marine_i; break; case 3: - thirds = k; + thirds = _marine_i; break; case 4: - fourths = k; + fourths = _marine_i; break; case 5: - fifths = k; + fifths = _marine_i; break; case 6: - sixths = k; + sixths = _marine_i; break; case 7: - sevenths = k; + sevenths = _marine_i; break; case 8: - eighths = k; + eighths = _marine_i; break; case 9: - ninths = k; + ninths = _marine_i; break; case 10: - tenths = k; + tenths = _marine_i; break; } } @@ -2868,20 +2833,16 @@ function scr_initialize_custom() { #endregion - var c; - c = 0; - k = 0; - company = 0; - repeat (200) { - c += 1; - if (k == 0) { - if ((role[0][c] != "") && (role[0][c + 1] == "")) { - k = c; - } - } - } - - // obj_controller.marines-=commands; + //? Seems to be dead code; prove me wrong + // _marine_i = 0; + // company = 0; + // for (var c = 0; c <= 200; c++) { + // if (_marine_i == 0) { + // if ((role[0][c] != "") && (role[0][c + 1] == "")) { + // _marine_i = c; + // } + // } + // } scr_add_item("Bolter", 20); scr_add_item("Chainsword", 20); @@ -2901,7 +2862,7 @@ function scr_initialize_custom() { scr_add_item("Bike", 40); - if (struct_exists(obj_creation, "extra_equipment")) { + if (variable_instance_exists(obj_creation, "extra_equipment")) { for (var e = 0; e < array_length(obj_creation.extra_equipment); e++) { var e_name = obj_creation.extra_equipment[e][0]; var e_qty = obj_creation.extra_equipment[e][1]; @@ -2945,8 +2906,6 @@ function scr_initialize_custom() { scr_add_item("Close Combat Weapon", 4); } - // man_size+=80;// bikes - if (scr_has_adv("Crafters") && scr_has_adv("Melee Enthusiasts")) { scr_add_item("MK3 Iron Armour", irandom_range(2, 12)); } @@ -2958,8 +2917,7 @@ function scr_initialize_custom() { //Fixed Loot tagble if (scr_has_adv("Ancient Armoury")) { //armour - var armm5 = ""; - armm5 = choose("Tartaros", "Cataphractii"); + var armm5 = choose("Tartaros", "Cataphractii"); scr_add_item("MK3 Iron Armour", irandom_range(2, 5)); scr_add_item("MK4 Maximus", irandom_range(5, 10)); scr_add_item("MK5 Heresy", irandom_range(5, 10)); @@ -2994,9 +2952,7 @@ function scr_initialize_custom() { gene_slaves = []; - var bloo = 0, o = 0; if (scr_has_disadv("Blood Debt")) { - bloo = 1; if (instance_exists(obj_controller)) { obj_controller.blood_debt = 1; penitent = 1; @@ -3014,7 +2970,6 @@ function scr_initialize_custom() { if (obj_creation.chapter_name == "Lamenters") { penitent_max = 600; penitent_end = 600; - // obj_controller.loyalty=50;obj_controller.loyalty_hidden=50; } } } @@ -3024,10 +2979,16 @@ function scr_initialize_custom() { game_start_squads(); } -/// @description helper function to streamline code inside of scr_initialize_custom, should only be used as part of -/// game setup and not during normal gameplay +/// @description helper function to streamline code inside of scr_initialize_custom, should only be used as part of game setup and not during normal gameplay +/// @param {String} name +/// @param {Real} company +/// @param {Real} slot +/// @param {String} wep1 +/// @param {String} wep2 +/// @param {String} wep3 +/// @param {String} upgrade +/// @param {String} accessory function add_veh_to_company(name, company, slot, wep1, wep2, wep3, upgrade, accessory) { - // LOGGER.info($"adding vehicle name {name} company {company} slot {slot} ") obj_ini.veh_race[company][slot] = 1; obj_ini.veh_loc[company][slot] = obj_ini.home_name; obj_ini.veh_role[company][slot] = name; @@ -3048,7 +3009,6 @@ function add_veh_to_company(name, company, slot, wep1, wep2, wep3, upgrade, acce /// Use "" if you want to set weapons and gear via squad layouts. /// "default" will set it to the value in the default slot for the given role, see `load_default_gear` function add_unit_to_company(ttrpg_name, company, slot, role_name, role_id, wep1 = "default", wep2 = "default", gear = "default", mobi = "default", armour = "default") { - // LOGGER.info($"adding unit to company ttrpg_name {ttrpg_name}, company {company}, slot {slot}, role_name {role_name}, role_id {role_id}") obj_ini.TTRPG[company][slot] = new TTRPG_stats("chapter", company, slot, ttrpg_name); var spawn_unit = fetch_unit([company, slot]); obj_ini.race[company][slot] = 1; @@ -3079,8 +3039,6 @@ function add_unit_to_company(ttrpg_name, company, slot, role_name, role_id, wep1 } else { spawn_unit.update_armour(armour, false, false); } - - // LOGGER.debug($"updating coy {company}:{slot} {role_name} armour to {armour}: {_msg} : {spawn_unit.armour()} : {obj_ini.armour[company][slot]}"); } if (gear != "") { if (gear == "default") { @@ -3153,7 +3111,6 @@ function load_chapter_master_equipment() { break; case 3: chapter_master_equip.wep1 = "Relic Blade"; - //wep1[0,1]="Relic Blade&MNR|"; break; case 4: chapter_master_equip.wep1 = "Thunder Hammer"; @@ -3208,7 +3165,7 @@ function load_chapter_master_equipment() { var arti; // From json - if (struct_exists(obj_creation, "artifact")) { + if (variable_instance_exists(obj_creation, "artifact")) { if (is_struct(obj_creation.artifact) && struct_exists(obj_creation.artifact, "name")) { arti = obj_ini.artifact_struct[last_artifact]; arti.name = obj_creation.artifact.name; @@ -3253,7 +3210,7 @@ function load_chapter_master_equipment() { } } - if (struct_exists(obj_creation, "chapter_master")) { + if (variable_instance_exists(obj_creation, "chapter_master")) { if (struct_exists(obj_creation.chapter_master, "gear") && obj_creation.chapter_master.gear != "") { chapter_master_equip.gear = obj_creation.chapter_master.gear; } diff --git a/scripts/scr_inquisition_fleet_functions/scr_inquisition_fleet_functions.gml b/scripts/scr_inquisition_fleet_functions/scr_inquisition_fleet_functions.gml index a64980367f..bb65ba7f97 100644 --- a/scripts/scr_inquisition_fleet_functions/scr_inquisition_fleet_functions.gml +++ b/scripts/scr_inquisition_fleet_functions/scr_inquisition_fleet_functions.gml @@ -21,7 +21,7 @@ function radical_inquisitor_mission_ship_arrival() { //TODO make a centralised player_fleet present method var _p_fleet = instance_nearest(x, y, obj_p_fleet); var _intercept_fleet = -1; - if (point_distance(x, y, _p_fleet.x, _p_fleet.y) < 10 && is_orbiting(obj_p_fleet)) { + if (point_distance(x, y, _p_fleet.x, _p_fleet.y) < 10 && is_orbiting(_p_fleet)) { _intercept_fleet = _p_fleet; } @@ -53,7 +53,6 @@ function radical_inquisitor_mission_ship_arrival() { _radical_inquisitor.inquisitor_ship = self.id; scr_popup("Inquisitor Located", _tixt, "inquisition", _radical_inquisitor); } - //instance_destroy(); exit; } @@ -66,7 +65,7 @@ function inquisition_fleet_inspection_chase() { if (reset) { // Reaquire target var target_player_fleet = get_largest_player_fleet(); - if (target_player_fleet != "none") { + if (target_player_fleet != noone) { if (target_player_fleet.action == "") { set_fleet_target(target_player_fleet.x, target_player_fleet.y, target_player_fleet); } else { @@ -86,8 +85,6 @@ function inquisition_fleet_inspection_chase() { scr_loyalty("Avoiding Inspections", "+"); } - // if (string_count("!",trade_goods)>=3) then demand stop fleet - //Inquisitor is pissed as hell if (string_count("!", trade_goods) == 5) { obj_controller.alarm[8] = 10; @@ -140,10 +137,9 @@ function inquisition_fleet_inspection_chase() { // Sets up an inquisitor ship to do an inspection on the HomeWorld function new_inquisitor_inspection() { - var target_system = "none"; - var new_inquis_fleet; + var target_system = noone; if (obj_ini.fleet_type == ePLAYER_BASE.HOME_WORLD) { - var monestary_system = "none"; + var monestary_system = noone; // If player does not own their homeworld than do a fleet inspection instead var player_stars = []; with (obj_star) { @@ -154,21 +150,20 @@ function new_inquisitor_inspection() { monestary_system = self; } } - if (monestary_system != "none") { + if (monestary_system != noone) { target_system = monestary_system; } else if (array_length(player_stars) > 0) { target_system = player_stars[0]; } - if (target_system != "none") { + if (target_system != noone) { var target_star = target_system; - var tar, new_inquis_fleet; var xx = target_star.x; var yy = target_star.y; //get the second or third closest planet to launch inquisitor from var from_star = distance_removed_star(target_star.x, target_star.y); - new_inquis_fleet = instance_create(from_star.x, from_star.y, obj_en_fleet); + var new_inquis_fleet = instance_create(from_star.x, from_star.y, obj_en_fleet); with (new_inquis_fleet) { base_inquis_fleet(); @@ -187,11 +182,11 @@ function new_inquisitor_inspection() { // otherwise, do a fleet inspection. var target_player_fleet = get_largest_player_fleet(); - if (target_player_fleet != "none") { + if (target_player_fleet != noone) { //get the second or third closest planet to launch inquisitor from var from_star = distance_removed_star(target_player_fleet.x, target_player_fleet.y); - new_inquis_fleet = instance_create(from_star.x, from_star.y, obj_en_fleet); + var new_inquis_fleet = instance_create(from_star.x, from_star.y, obj_en_fleet); var obj; with (new_inquis_fleet) { base_inquis_fleet(); @@ -222,7 +217,7 @@ function inquisitor_ship_approaches() { var do_alert = false; if (string_count("fleet", trade_goods) > 0 && scr_valid_fleet_target(target)) { var player_fleet_location = fleets_next_location(target); - if (player_fleet_location != "none") { + if (player_fleet_location != noone) { if (approach_system.name == player_fleet_location.name) { inquis_string = $"Our navigators report that an inquisitor's ship is currently warping towards our flagship. It is likely that the inquisitor on board (provided he/she makes it) will attempt to perform an inspection of our flagship."; do_alert = true; @@ -240,7 +235,7 @@ function inquisitor_ship_approaches() { } } if (do_alert) { - var approach_system = instance_nearest(action_x, action_y, obj_star).name; + approach_system = instance_nearest(action_x, action_y, obj_star).name; if (inquisitor == 0) { scr_alert("green", "duhuhuhu", $"Inquisitor Ship approaches {approach_system}.", x, y); } else { @@ -260,8 +255,6 @@ function inquisitor_inspect_base() { chapter_asset_discovery = roll_dice_chapter(2, 100, "high"); } - // 137 ; chapter_asset_discovery=floor(random(20))+1; - var cur_planet = 0; if (chapter_asset_discovery <= 5) { repeat (planets) { @@ -297,7 +290,7 @@ function inquisitor_inspect_base() { var _current_planet_name = name; var launch_planet, launch_point_found = false; launch_planet = nearest_star_with_ownership(x, y, [eFACTION.IMPERIUM, eFACTION.MECHANICUS], self.id); - if (launch_planet != "none") { + if (launch_planet != noone) { if (instance_exists(launch_planet)) { flee = instance_create(launch_planet.x, launch_planet.y, obj_en_fleet); with (flee) { diff --git a/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml b/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml index 47348cbc1b..06f69c5baa 100644 --- a/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml +++ b/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml @@ -21,11 +21,12 @@ function check_for_next_inquisitor_inspection() { } if (obj_ini.fleet_type != ePLAYER_BASE.HOME_WORLD) { + var _player_fleet = instance_nearest(x, y, obj_p_fleet); var _player_fleets = instance_number(obj_p_fleet); if (_player_fleets == 1) { //can't inspect if fleet not in room //can't innspect if on other non negotiable action e.g crusading - _inspec = in_room(obj_p_fleet) && !fleet_engaged(obj_p_fleet); + _inspec = in_room(_player_fleet) && !fleet_engaged(_player_fleet); } else if (_player_fleets == 0) { _inspec = false; } diff --git a/scripts/scr_inquisition_mission/scr_inquisition_mission.gml b/scripts/scr_inquisition_mission/scr_inquisition_mission.gml index a890181ed0..29c0737d4a 100644 --- a/scripts/scr_inquisition_mission/scr_inquisition_mission.gml +++ b/scripts/scr_inquisition_mission/scr_inquisition_mission.gml @@ -17,7 +17,7 @@ /// @param {Enum.eEVENT} event /// @param {Enum.eINQUISITION_MISSION} forced_mission optional -function scr_inquisition_mission(event, forced_mission = -1) { +function scr_inquisition_mission(event, forced_mission = eINQUISITION_MISSION.RANDOM) { LOGGER.info($"RE: Inquisition Mission, event {event}, forced_mission {forced_mission}"); if ((obj_controller.known[eFACTION.INQUISITION] == 0 || obj_controller.faction_status[eFACTION.INQUISITION] == "War") && !global.cheat_debug) { LOGGER.info("Player is either hasn't met or is at war with Inquisition, not proceeding with inquisition mission"); @@ -52,7 +52,7 @@ function scr_inquisition_mission(event, forced_mission = -1) { found_sleeping_necrons = true; } - if (star_has_planet_with_forces(_star, "Demons", 1)) { + if (star_has_planet_with_forces(_star, eFACTION.HERETICS, 1)) { // array_push(demon_worlds, _star); // turning this off til i have a way to finish the mission } @@ -81,26 +81,9 @@ function scr_inquisition_mission(event, forced_mission = -1) { LOGGER.info($"Couldn't find any planets with demons for inquisition mission"); } - //if (string_count("Tau",obj_controller.useful_info)=0){ - // var found_tau = false; - // with(obj_star){ - // if (found_tau){ - // break; - // } - // for(var i = 1; i <= planets; i++) - // { - // if (p_tau[i]>4) { - // array_push(inquisition_missions, eINQUISITION_MISSION.ETHEREAL); - // found_tau = true - // break; - // } - // } - // } - //} - - var chosen_mission = choose_array(inquisition_missions); - if (forced_mission != -1) { - chosen_mission = forced_mission; + var chosen_mission = forced_mission; + if (chosen_mission == eINQUISITION_MISSION.RANDOM) { + chosen_mission = choose_array(inquisition_missions); } switch (chosen_mission) { case eINQUISITION_MISSION.PURGE: @@ -188,7 +171,7 @@ function mission_inquisition_tyranid_organism(worlds) { } var eta = scr_mission_eta(_star.x, _star.y, 1); - var eta = min(max(eta, 6), 50); + eta = min(max(eta, 6), 50); var text = $"An Inquisitor is trusting you with a special mission. The planet {string(_star.name)} {scr_roman(planet)}"; text += " is ripe with Tyranid organisms. They require that you capture one of the Gaunt species for research purposes. Can your chapter handle this mission?"; @@ -197,8 +180,9 @@ function mission_inquisition_tyranid_organism(worlds) { function mission_inquisition_tomb_world(tomb_worlds) { LOGGER.info("RE: Necron Tomb Bombing"); + var _star = noone; if (is_array(tomb_worlds)) { - var _star = array_random_element(tomb_worlds); + _star = array_random_element(tomb_worlds); } else { _star = tomb_worlds; } @@ -242,7 +226,7 @@ function mission_inquisition_tomb_world(tomb_worlds) { /// @self Asset.GMObject.obj_popup function init_mission_inquisition_tomb_world() { mission_star = find_star_by_name(pop_data.system); - if (mission_star == "none") { + if (mission_star == noone) { popup_default_close(); exit; } @@ -274,23 +258,13 @@ function mission_inquisition_artifact() { scr_popup("Inquisition Mission", text, "inquisition", $"artifact|bop|0|{string(irandom_range(6, 26))}|"); } -function mission_inquistion_hunt_inquisitor(star_id = -1) { +function mission_inquistion_hunt_inquisitor(star_id = noone) { LOGGER.info("RE: Inquisitor Hunt"); var stars = scr_get_stars(); - /*var _valid_stars = array_filter_ext(stars, - function(_star,index){ - var _p_fleet = instance_nearest(_star.x,_star.y,obj_p_fleet); - if (instance_exists(_p_fleet)){ - var _distance = point_distance(_star.x,_star.y,_p_fleet.x,_p_fleet.y); - if (100 <= _distance & _distance <= 300){ - return true; - } - } - return false; - });*/ + var _star = noone; - if (star_id == -1) { + if (star_id == noone) { var _valid_stars = stars; if (array_length(_valid_stars) == 0) { @@ -298,7 +272,7 @@ function mission_inquistion_hunt_inquisitor(star_id = -1) { exit; } - var _star = array_random_element(_valid_stars); + _star = array_random_element(_valid_stars); } else { _star = star_id; } @@ -351,7 +325,7 @@ function add_new_inquis_mission() { /// @self Asset.GMObject.obj_popup function init_mission_hunt_inquisitor() { mission_star = find_star_by_name(pop_data.system); - if (mission_star == "none") { + if (mission_star == noone) { popup_default_close(); exit; } diff --git a/scripts/scr_json_functions/scr_json_functions.gml b/scripts/scr_json_functions/scr_json_functions.gml index 071c386187..0bb663d798 100644 --- a/scripts/scr_json_functions/scr_json_functions.gml +++ b/scripts/scr_json_functions/scr_json_functions.gml @@ -6,9 +6,6 @@ function json_to_gamemaker(_json_path, _func) { var file_buffer = undefined; try { if (file_exists(_json_path)) { - var _json_string = ""; - var _parsed_json = {}; - file_buffer = buffer_load(_json_path); if (file_buffer == -1) { diff --git a/scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gml b/scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gml index de1c39b8d9..127d2b3c07 100644 --- a/scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gml +++ b/scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gml @@ -1,5 +1,3 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information function khorne_fleet_cargo() { //This handles khorne fleets killing planet popultions moving planet and then choosing a new target ot chase warband = cargo_data.warband; @@ -7,39 +5,37 @@ function khorne_fleet_cargo() { if (_is_orbiting && (action == "")) { _orb = orbiting; if (_orb.present_fleet[1] + _orb.present_fleet[2] + _orb.present_fleet[3] + _orb.present_fleet[6] + _orb.present_fleet[7] + _orb.present_fleet[9] + _orb.present_fleet[13] == 0) { - var ii = 0, good = 0, part = 0, find_new_planet = false; + var good = 0; + var find_new_planet = false; // No forces already landed var _fleet = self; with (_orb) { - repeat (planets) { - ii += 1; - if (planet_feature_bool(p_feature[ii], eP_FEATURES.CHAOSWARBAND) == 1) { + for (var i = 1; i <= planets; i++) { + if (planet_feature_bool(p_feature[i], eP_FEATURES.CHAOSWARBAND) == 1) { good -= 1; - if (planet_imperium_ground_total(ii) <= 0) { - if (p_population[ii] > p_max_population[ii] / 20) { - p_population[ii] = round(p_population[ii] / 2); - if (p_population[ii] <= p_max_population[ii] / 20) { + if (planet_imperium_ground_total(i) <= 0) { + if (p_population[i] > p_max_population[i] / 20) { + p_population[i] = round(p_population[i] / 2); + if (p_population[i] <= p_max_population[i] / 20) { find_new_planet = true; } } - } else if (p_population[ii] <= p_max_population[ii] / 20) { + } else if (p_population[i] <= p_max_population[i] / 20) { find_new_planet = true; } } } // Next planet; rembark the chaos forces if (find_new_planet == true) { - ii = 0; find_new_planet = false; - repeat (planets) { - ii += 1; - if (planet_feature_bool(p_feature[ii], eP_FEATURES.CHAOSWARBAND) == 1) { - p_chaos[ii] = 0; - p_traitors[ii] = max(4, p_traitors[ii] + 1); - delete_features(p_feature[ii], eP_FEATURES.CHAOSWARBAND); + for (var i = 1; i <= planets; i++) { + if (planet_feature_bool(p_feature[i], eP_FEATURES.CHAOSWARBAND) == 1) { + p_chaos[i] = 0; + p_traitors[i] = max(4, p_traitors[i] + 1); + delete_features(p_feature[i], eP_FEATURES.CHAOSWARBAND); find_new_planet = true; } } @@ -48,24 +44,22 @@ function khorne_fleet_cargo() { // No forces landed if ((good == 0) || (find_new_planet == true)) { - ii = 0; var landing_planet = 0; with (_orb) { - repeat (planets) { - ii += 1; + for (var i = 1; i <= planets; i++) { if (landing_planet == 0) { - if ((planet_imperium_ground_total(ii) > 0) && (p_population[ii] > p_max_population[ii] / 20)) { - array_push(p_feature[ii], new NewPlanetFeature(eP_FEATURES.CHAOSWARBAND)); - landing_planet = ii; - p_chaos[ii] = 6; + if ((planet_imperium_ground_total(i) > 0) && (p_population[i] > p_max_population[i] / 20)) { + array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.CHAOSWARBAND)); + landing_planet = i; + p_chaos[i] = 6; break; } // Forces landed } if (landing_planet == 0) { - if ((p_player[ii] > 0) && (p_population[ii] > p_max_population[ii] / 20)) { - landing_planet = ii; - p_chaos[ii] = 6; - array_push(p_feature[ii], new NewPlanetFeature(eP_FEATURES.CHAOSWARBAND)); + if ((p_player[i] > 0) && (p_population[i] > p_max_population[i] / 20)) { + landing_planet = i; + p_chaos[i] = 6; + array_push(p_feature[i], new NewPlanetFeature(eP_FEATURES.CHAOSWARBAND)); break; } // Forces landed } @@ -74,7 +68,6 @@ function khorne_fleet_cargo() { if ((landing_planet == 0) && (trade_goods != "khorne_warband_landing_force")) { // Nothing to see here, continue to next star*/ - ii = 0; with (_orb) { instance_deactivate_object(id); @@ -109,21 +102,18 @@ function khorne_fleet_cargo() { } } - var nx, ny, n2, yy2, ndir, next_star; - next_star = 0; - ndir = point_direction(x, y, home_x, home_y); - nx = x + lengthdir_x(250, ndir); - ny = y + lengthdir_y(250, ndir); - n2 = x + lengthdir_x(450, ndir); - yy2 = y + lengthdir_y(450, ndir); + var ndir = point_direction(x, y, home_x, home_y); + var nx = x + lengthdir_x(250, ndir); + var ny = y + lengthdir_y(250, ndir); + var n2 = x + lengthdir_x(450, ndir); + var yy2 = y + lengthdir_y(450, ndir); if (!point_in_rectangle(n2, yy2, 50, 50, room_width, room_height)) { trade_goods = "khorne_warband_landing_force"; - // show_message("khorne_warband_landing_force"); } if (trade_goods != "khorne_warband_landing_force") { - next_star = instance_nearest(nx, ny, obj_star); + var next_star = instance_nearest(nx, ny, obj_star); action_x = next_star.x; action_y = next_star.y; action = ""; @@ -151,7 +141,7 @@ function khorne_fleet_cargo() { if (player_stars > 0) { var pee1 = instance_nearest(x, y, obj_star); instance_activate_object(obj_star); - next_star = distance_removed_star(pee1.x, pee1.y, choose(1, 1, 2)); + var next_star = distance_removed_star(pee1.x, pee1.y, choose(1, 1, 2)); action_x = next_star.x; action_y = next_star.y; action = ""; @@ -167,7 +157,7 @@ function khorne_fleet_cargo() { } var chase_fleet = get_nearest_player_fleet(nearest_x, nearest_y); - if ((chase_fleet != "none") && (action == "")) { + if ((chase_fleet != noone) && (action == "")) { var intercept_time = fleet_intercept_time_calculate(chase_fleet); if (chase_fleet.action != "") { if (intercept_time <= chase_fleet.eta) { @@ -195,7 +185,7 @@ function khorne_fleet_cargo() { if (player_stars > 0) { var nearest_star = instance_nearest(x, y, obj_star); instance_activate_object(obj_star); - if (chase_fleet == "none") { + if (chase_fleet == noone) { action_x = nearest_star.x; action_y = nearest_star.y; set_fleet_movement(); @@ -238,12 +228,12 @@ function spawn_chaos_warlord() { scr_audience(eFACTION.CHAOS, "intro", 0, "", 0, 2); fdir = terra_direction + choose(-90, 90); fdir += floor(random_range(-35, 35)); - var len, width, height, t, c, s; - width = room_width; - height = room_height; - t = degtorad(fdir); - c = abs(cos(t)); - s = abs(sin(t)); + var len = 0; + var width = room_width; + var height = room_height; + var t = degtorad(fdir); + var c = abs(cos(t)); + var s = abs(sin(t)); if (c * height > s * width) { len = (width / 2) / c; } else { @@ -264,13 +254,11 @@ function spawn_chaos_warlord() { frigate_number = 20; escort_number = 40; } - var rep, filtered_array, candidate_systems; - candidate_systems = []; + var candidate_systems = []; with (obj_star) { - rep = 0; ya = false; //should probably get turned into its own helper if used multiple times - filtered_array = array_filter(p_owner, function(val, idx) { + var filtered_array = array_filter(p_owner, function(val, idx) { return scr_is_planet_owned_by_allies(self, idx); }); if (array_length(filtered_array)) { diff --git a/scripts/scr_livery_setup/scr_livery_setup.gml b/scripts/scr_livery_setup/scr_livery_setup.gml index a9e650855d..fdc1b33c5b 100644 --- a/scripts/scr_livery_setup/scr_livery_setup.gml +++ b/scripts/scr_livery_setup/scr_livery_setup.gml @@ -198,11 +198,6 @@ function scr_livery_setup() { _cultures.x1 = right_data_slate.XX + 30; _cultures.y1 = right_data_slate.YY + 80; _cultures.max_width = right_data_slate.width - 120; - _cultures.on_change = function() { - var _picker = obj_creation.livery_picker; - _picker.shuffle_dummy(); - _picker.reset_image(); - }; _cultures.draw(); }; diff --git a/scripts/scr_load/scr_load.gml b/scripts/scr_load/scr_load.gml index 3e629e0566..ff3f006676 100644 --- a/scripts/scr_load/scr_load.gml +++ b/scripts/scr_load/scr_load.gml @@ -1,6 +1,7 @@ function scr_load(save_part, save_id) { var t1 = get_timer(); var filename = string(PATH_SAVE_FILES, save_id); + var json_game_save = {}; if (save_id == 0) { filename = string(PATH_AUTOSAVE_FILE); LOGGER.info("Loading from Autosave"); @@ -9,7 +10,7 @@ function scr_load(save_part, save_id) { var _gamesave_buffer = buffer_load(filename); var _gamesave_string = buffer_read(_gamesave_buffer, buffer_string); buffer_delete(_gamesave_buffer); - var json_game_save = json_parse(_gamesave_string); + json_game_save = json_parse(_gamesave_string); } if (!struct_exists(obj_saveload.GameSave, "Save")) { @@ -63,7 +64,7 @@ function scr_load(save_part, save_id) { "point_breakdown", "apothecary_points", "forge_points", - "chapter_master_data" + "chapter_master_data", ]; // skip automatic setting of certain vars, handle explicitly later // Automatic var setting @@ -75,9 +76,8 @@ function scr_load(save_part, save_id) { continue; } var loaded_value = struct_get(save_data, var_name); - // LOGGER.debug($"obj_controller var: {var_name} - val: {loaded_value}"); try { - variable_struct_set(obj_controller, var_name, loaded_value); + variable_instance_set(obj_controller, var_name, loaded_value); } catch (e) { LOGGER.debug(e); } @@ -149,7 +149,6 @@ function scr_load(save_part, save_id) { global.load = -1; scr_image("force", -50, 0, 0, 0, 0); LOGGER.info("Loading completed"); - // room_goto(rm_game); } var t2 = get_timer(); diff --git a/scripts/scr_manage_tags/scr_manage_tags.gml b/scripts/scr_manage_tags/scr_manage_tags.gml index 1bf7b7082b..f177064a2f 100644 --- a/scripts/scr_manage_tags/scr_manage_tags.gml +++ b/scripts/scr_manage_tags/scr_manage_tags.gml @@ -93,7 +93,7 @@ function draw_tag_manager() { } tag_selects = new MultiSelect(_selecs, "Tags", {max_width: 500, x1: 1040, y1: 210}); } - var _tool = "Remove Tags from current Marine selection"; + _tool = "Remove Tags from current Marine selection"; remove_tag_button.disabled = false; if (!_addable) { _tool = "Make some tags to Remove them from marines"; @@ -127,7 +127,6 @@ function draw_tag_manager() { } } tag_selects = new MultiSelect(_selecs, "Tags", {max_width: 500, x1: 1040, y1: 210}); - //new_tag = ""; } } diff --git a/scripts/scr_management/scr_management.gml b/scripts/scr_management/scr_management.gml index fed4ba9abb..d416d61509 100644 --- a/scripts/scr_management/scr_management.gml +++ b/scripts/scr_management/scr_management.gml @@ -3,11 +3,7 @@ function scr_management(argument0) { // Creates the company blocks in the main management screen and assigns text to them // Variable creation - var num = 0, nam = "", company = 50, q = 0; - var romanNumerals = scr_roman_numerals(); var chapter_name = global.chapter_name; - var role_names = obj_ini.role[100]; - var unit; if (argument0 == 1) { with (obj_managment_panel) { @@ -25,7 +21,7 @@ function scr_management(argument0) { var _reclusium_units = _command_company.get_from({group: [SPECIALISTS_CHAPLAINS, true, true]}, true, true); - var _reclusium_units = _reclusium_units.index_roles(); + _reclusium_units = _reclusium_units.index_roles(); pane.line = array_join(pane.line, _reclusium_units.create_plural_strings_array()); @@ -37,7 +33,7 @@ function scr_management(argument0) { var _apothecary_units = _command_company.get_from({group: [SPECIALISTS_APOTHECARIES, true, true]}, true, true); - var _apothecary_units = _apothecary_units.index_roles(); + _apothecary_units = _apothecary_units.index_roles(); pane.line = array_join(pane.line, _apothecary_units.create_plural_strings_array()); @@ -48,7 +44,7 @@ function scr_management(argument0) { pane.title = "ARMOURY"; var _armoury_units = _command_company.get_from({group: [SPECIALISTS_TECHS, true, true]}, true, true); - var _armoury_units = _armoury_units.index_roles(); + _armoury_units = _armoury_units.index_roles(); pane.line = array_join(pane.line, _armoury_units.create_plural_strings_array()); @@ -61,7 +57,7 @@ function scr_management(argument0) { var _lib_units = _command_company.get_from({group: [SPECIALISTS_LIBRARIANS, true, true]}, true, true); - var _lib_units = _lib_units.index_roles(); + _lib_units = _lib_units.index_roles(); pane.line = array_join(pane.line, _lib_units.create_plural_strings_array()); @@ -88,13 +84,14 @@ function scr_management(argument0) { pane.line = array_join(pane.line, _command_units.create_plural_strings_array()); // Coordinates declaration and text initiation - var xx = 25, yy = 400 - 48, t; + var xx = 25; + var yy = 352; // Creates the first 10 companies using roman numerals for (var company = 1; company <= 10; company++) { - t = string_upper(scr_convert_company_to_string(company)); + var t = string_upper(scr_convert_company_to_string(company)); - var pane = instance_create(xx, yy, obj_managment_panel); + pane = instance_create(xx, yy, obj_managment_panel); pane.company = company; pane.manage = company; pane.header = 1; @@ -125,7 +122,6 @@ function scr_management(argument0) { if (num[d] > 0) { if (d == 1) { array_push(pane.line, {str1: nam[d], bold: true, italic: false}); - // obj_managment_panel.italic[q] = 1; } else { array_push(pane.line, nam[d], string_plural_count(nam[d], num[d], false)); } diff --git a/scripts/scr_map_and_warp_functions/scr_map_and_warp_functions.gml b/scripts/scr_map_and_warp_functions/scr_map_and_warp_functions.gml index d4a663ce78..0e74b9c8b5 100644 --- a/scripts/scr_map_and_warp_functions/scr_map_and_warp_functions.gml +++ b/scripts/scr_map_and_warp_functions/scr_map_and_warp_functions.gml @@ -1,10 +1,3 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information -// function set_warp_point_data(){ -// warp_point_hover = true; -// } -// Main menu movement - function in_camera_view(rect) { var x1 = camera_get_view_x(view_camera[0]); var y1 = camera_get_view_y(view_camera[0]); @@ -66,25 +59,21 @@ function draw_warp_lanes() { routes = []; var star_degrade_list = []; var total_stars = instance_number(obj_star); - var cur_star, this_star, connection, i, check_star; - for (i = 0; i < total_stars; i++) { + for (var i = 0; i < total_stars; i++) { array_push(star_degrade_list, i); } - for (i = 0; i < total_stars; i++) { - cur_star = instance_find(obj_star, star_degrade_list[i]); + for (var i = 0; i < total_stars; i++) { + var cur_star = instance_find(obj_star, star_degrade_list[i]); var this_star = cur_star.id; var in_view = true; - //var in_view = in_camera_view(star_box_shape(this_star)); - //if (!in_view) then in_view = zoomed; if (array_length(cur_star.warp_lanes) > 0) { for (var s = 0; s < total_stars; s++) { if (s == i) { continue; } - check_star = instance_find(obj_star, star_degrade_list[s]); - //if (!in_view && !in_camera_view(star_box_shape(check_star))) then continue; - connection = determine_warp_join(check_star.id, this_star); + var check_star = instance_find(obj_star, star_degrade_list[s]); + var connection = determine_warp_join(check_star.id, this_star); if (connection) { array_push(routes, [[check_star.x, check_star.y, this_star.x, this_star.y], connection]); } @@ -101,8 +90,6 @@ function draw_warp_lanes() { if (warp_image == 58) { warp_image = 0; } - // if (!warp_point_hover) then hover_time=0; - // warp_point_hover = false; for (var i = 0; i < array_length(routes); i++) { draw_set_color(c_gray); route = routes[i]; @@ -114,20 +101,15 @@ function draw_warp_lanes() { } else if (route[1] == 4) { draw_set_color(c_yellow); //TODO abstract code as a ratio distance function - //static debug_c = 0; var direction_x = route_coords[2] - route_coords[0]; var direction_y = route_coords[3] - route_coords[1]; var forward = direction_x >= 0 ? 1 : -1; var downward = direction_y >= 0 ? 1 : -1; - //var grade = direction_x/direction_y; var total_dist = 80; var pythag_dist = sqr(total_dist); var sum = (direction_x * forward) + (direction_y * downward); var x_ratio = direction_x * forward / sum; var y_ratio = direction_y * downward / sum; - /*if (debug_c<100){ - LOGGER.debug($"{x_ratio},{forward},{y_ratio},{downward}"); - }*/ var dist_x = sqrt(pythag_dist * x_ratio) * forward; var dist_y = sqrt(pythag_dist * y_ratio) * downward; @@ -167,20 +149,12 @@ function draw_warp_lanes() { if (!star_overlap) { var to = instance_nearest(route_coords[2], route_coords[3], obj_star); - // warp_point_hover = true; if (_allow_tooltips) { tooltip_draw(string(warp_route_tooltip, to.name)); } - /* if (array_equals(hover_loc,[route_coords[0] ,route_coords[1]])){ - hover_time++; - } else { - hover_loc = [route_coords[0] ,route_coords[1]]; - hover_time = 0; - }*/ - - if (mouse_check_button_pressed(mb_left) && keyboard_check(vk_shift) /* || (instance_exists(obj_fleet_select) && hover_time>=30) */) { + if (mouse_check_button_pressed(mb_left) && keyboard_check(vk_shift)) { set_map_pan_to_loc(to); } } @@ -207,25 +181,16 @@ function draw_warp_lanes() { } if (!star_overlap) { var to = instance_nearest(route_coords[0], route_coords[1], obj_star); - // warp_point_hover = true; if (_allow_tooltips) { tooltip_draw(string(warp_route_tooltip, to.name)); } - // if (array_equals(hover_loc,[route_coords[2] ,route_coords[3]])){ - // hover_time++; - // } else { - // hover_loc = [route_coords[2] ,route_coords[3]]; - // hover_time = 0; - // } - - if (mouse_check_button_pressed(mb_left) && keyboard_check(vk_shift) /* || (instance_exists(obj_fleet_select) && hover_time>=30) */) { + if (mouse_check_button_pressed(mb_left) && keyboard_check(vk_shift)) { set_map_pan_to_loc(to); } } } - //debug_c++; } } } @@ -302,9 +267,9 @@ function create_complex_star_routes(player_star) { continue; } if (player_hub_overide) { - for (var i = 0; i < array_length(set); i++) { - if (set[i] == player_star) { - WarpHub = set[i]; + for (var j = 0; j < array_length(set); j++) { + if (set[j] == player_star) { + WarpHub = set[j]; break; } } @@ -321,10 +286,6 @@ function create_complex_star_routes(player_star) { if (s == i || set_count == 0) { continue; } - /*//if (irandom(1)) then continue; - for (var i=0;i 2) { if (edit_stat[2] == "max") { variable_struct_set(self, stats[stat_iter], max(stat_mod, edit_stat[0])); @@ -650,21 +624,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} so as an example salamanders could have the chapter values as */ loyalty = 0; - static alter_loyalty = function(alt_val) { - if (alt_val < 0) { - if (has_trait("honorable")) { - alt_val /= 2; - } - if (has_trait("jaded")) { - alt_val *= 2; - } - } - if (has_trait("old_guard")) { - alt_val /= 2; - } - loyalty = clamp(loyalty + alt_val, 0, 100); - }; - switch (base_group) { case "astartes": //basic marine class //adds specific mechanics not releveant to most units loyalty = 100; @@ -695,13 +654,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} allegiance = global.chapter_name; } - assign_inherent_mutations(); - assign_random_mutations(); - - if (gene_seed_mutations[$ "voice"] == 1) { - charisma -= 2; - } - static assign_inherent_mutations = function() { gene_seed_mutations = { "preomnor": obj_ini.preomnor, @@ -751,9 +703,12 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} } }; - //array index 0 == trait to add - // array index 1 == probability e.g 99,98 == if (irandom(99)>98){add_trait} - // array index 3 == probability modifiers + assign_inherent_mutations(); + assign_random_mutations(); + + if (gene_seed_mutations[$ "voice"] == 1) { + charisma -= 2; + } if ((global.chapter_name == "Space Wolves") || (obj_ini.progenitor == ePROGENITOR.SPACE_WOLVES)) { religion_sub_cult = "The Allfather"; @@ -812,6 +767,21 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} return obj_ini.race[company][marine_number]; }; + static alter_loyalty = function(alt_val) { + if (alt_val < 0) { + if (has_trait("honorable")) { + alt_val /= 2; + } + if (has_trait("jaded")) { + alt_val *= 2; + } + } + if (has_trait("old_guard")) { + alt_val /= 2; + } + loyalty = clamp(loyalty + alt_val, 0, 100); + }; + static update_loyalty = function(change_value) { loyalty = clamp(loyalty + change_value, 0, 100); }; @@ -833,9 +803,9 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} return false; }; - /// @param {string} area - /// @param {string} bionic_quality - /// @param {bool} from_armoury + /// @param {string} _area + /// @param {string} _quality + /// @param {bool} _from_armoury static add_bionics = function(_area = "none", _quality = "any", _from_armoury = true) { if (bionics >= 10) { return false; @@ -968,7 +938,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} is_boarder = false; gear_quality = "standard"; - static update_gear = scr_update_unit_gear; if (base_group != "none") { update_health(max_health()); //set marine unit_health to max @@ -1795,6 +1764,7 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} //quick way of getting name and role combined in string static name_role = function(include_epithet = true, include_role = true) { var _name = name(); + var _epithet = ""; if (include_role) { var _temp_role = squad_role(); @@ -1802,7 +1772,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} } if (include_epithet) { - var _epithet = ""; if (array_length(epithets)) { _epithet += $"{epithets[0].title}"; } @@ -1827,7 +1796,7 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} return $"{scr_roman_numerals()[company - 1]}"; }; - static load_marine = function(ship, star = "none") { + static load_marine = function(ship, star = noone) { get_unit_size(); // make sure marines size given it's current equipment is correct var current_location = marine_location(); var system = current_location[2]; @@ -1851,10 +1820,10 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} ship_location = ship; //id of ship marine is now loaded on obj_ini.ship_carrying[ship] += size; //update ship capacity - if (star == "none") { + if (star == noone) { star = find_star_by_name(system); } - if (star != "none") { + if (star != noone) { if (star.p_player[current_location[1]] > 0) { star.p_player[current_location[1]] -= size; } @@ -1907,7 +1876,7 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} }; static allocate_unit_to_fresh_spawn = function(type = "default") { - var homestar = "none"; + var homestar = noone; var spawn_location_chosen = false; if (type == "home_planet") { // Place on the chapter's actual owned planet in the home system and keep the unit @@ -1929,14 +1898,11 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} return; } if (((type == "home") || (type == "default")) && (obj_ini.fleet_type == ePLAYER_BASE.HOME_WORLD)) { - var homestar = find_star_by_name(obj_ini.home_name); + homestar = find_star_by_name(obj_ini.home_name); } else if (type != "ship") { - var homestar = find_star_by_name(type); + homestar = find_star_by_name(type); } - /* if (!spawn_location_chosen){ - - }*/ - if (homestar != "none") { + if (homestar != noone) { for (var i = 1; i <= homestar.planets; i++) { if (homestar.p_owner[i] == eFACTION.PLAYER || (obj_controller.faction_status[eFACTION.IMPERIUM] != "War" && array_contains(obj_controller.imperial_factions, homestar.p_owner[i]))) { planet_location = i; @@ -1947,14 +1913,14 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} } if (!spawn_location_chosen) { var player_fleet = get_largest_player_fleet(); - if (player_fleet != "none") { + if (player_fleet != noone) { get_unit_size(); load_unit_to_fleet(player_fleet, self); spawn_location_chosen = true; } //TODO add more work arounds in case of no valid spawn point if (!spawn_location_chosen) { - if (player_fleet != "none") {} + if (player_fleet != noone) {} } } }; @@ -2010,11 +1976,10 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} static roll_age = scr_marine_spawn_age; static roll_experience = function() { - var _exp = 0; var _age_bonus = age(); var _gauss_sd_mod = 14; - _exp = _age_bonus; + var _exp = _age_bonus; _exp = max(0, floor(gauss(_exp, _exp / _gauss_sd_mod))); add_exp(_exp); }; @@ -2331,7 +2296,11 @@ function jsonify_marine_struct(company, marine, stringify = true) { /// @param {Array} unit where unit[0] is company and unit[1] is the position /// @returns {Struct.TTRPG_stats} unit function fetch_unit(unit) { - return obj_ini.TTRPG[unit[0]][unit[1]]; + try { + return obj_ini.TTRPG[unit[0]][unit[1]]; + } catch (_exception) { + ERROR_HANDLER.assert_popup(_exception); + } } function fetch_unit_uid(uuid) { diff --git a/scripts/scr_mechanicus_missions/scr_mechanicus_missions.gml b/scripts/scr_mechanicus_missions/scr_mechanicus_missions.gml index 951c15494a..2e2056b4f1 100644 --- a/scripts/scr_mechanicus_missions/scr_mechanicus_missions.gml +++ b/scripts/scr_mechanicus_missions/scr_mechanicus_missions.gml @@ -104,7 +104,7 @@ function mechanicus_missions_end_turn(planet) { var _marines = collect_role_group("all", [name, planet, -1]); if (array_length(_marines) >= 20) { remove_planet_problem(planet, "mech_tomb1"); - add_new_problem(planet, "mech_tomb2", 999, star == "none", other_data == {turns: 0}); + add_new_problem(planet, "mech_tomb2", 999, noone, {turns: 0}); scr_popup("Mechanicus Research", "The Mechanicus Research team on planet " + string(name) + " " + scr_roman(planet) + " has taken note of your Astartes and are now prepared to begin their research. Your marines are to stay on the planet until further notice.", "necron_cave", ""); } else {} } @@ -182,13 +182,13 @@ function spawn_mechanicus_mission(chosen_mission = "random") { } var star = array_random_element(_forge_stars); - + var text = ""; var _mission_data = { star: star.id, }; var _name = star.name; if (chosen_mission == "mech_raider") { - var text = $"The Adeptus Mechanicus are trusting you with a special mission. They wish for you to bring a Land Raider and six {obj_ini.role[100][16]} to a Forge World in {_name} for testing and training, for a duration of 24 months. You have four years to complete this. Can your chapter handle this mission?"; + text = $"The Adeptus Mechanicus are trusting you with a special mission. They wish for you to bring a Land Raider and six {obj_ini.role[100][16]} to a Forge World in {_name} for testing and training, for a duration of 24 months. You have four years to complete this. Can your chapter handle this mission?"; _mission_data.options = [ { str1: "Accept", @@ -201,7 +201,7 @@ function spawn_mechanicus_mission(chosen_mission = "random") { ]; _evented = true; } else if (chosen_mission == "mech_bionics") { - var text = $"The Adeptus Mechanicus are trusting you with a special mission. They desire a squad of Astartes with bionics to stay upon a Forge World in {_name} for testing, for a duration of 24 months. You have four years to complete this. Can your chapter handle this mission?"; + text = $"The Adeptus Mechanicus are trusting you with a special mission. They desire a squad of Astartes with bionics to stay upon a Forge World in {_name} for testing, for a duration of 24 months. You have four years to complete this. Can your chapter handle this mission?"; _mission_data.options = [ { str1: "Accept", @@ -214,7 +214,7 @@ function spawn_mechanicus_mission(chosen_mission = "random") { ]; _evented = true; } else { - var text = $"The local Adeptus Mechanicus are preparing to embark on a voyage to Mars, to delve into the catacombs in search of lost technology. Due to your close relations they have made the offer to take some of your {obj_ini.role[100][16]}s with them for both their unique abilities to function as both scientific helpers and as helpers (high Weapon Skill and Technology is reccomended). Can your chapter handle this mission?"; + text = $"The local Adeptus Mechanicus are preparing to embark on a voyage to Mars, to delve into the catacombs in search of lost technology. Due to your close relations they have made the offer to take some of your {obj_ini.role[100][16]}s with them for both their unique abilities to function as both scientific helpers and as helpers (high Weapon Skill and Technology is reccomended). Can your chapter handle this mission?"; _mission_data.options = [ { str1: "Accept", @@ -249,7 +249,7 @@ function spawn_mechanicus_mission(chosen_mission = "random") { exit; } var star = array_random_element(valid_stars); - _mission_data = { + var _mission_data = { star: star.id, pathway_id: chosen_mission, }; diff --git a/scripts/scr_mission_eta/scr_mission_eta.gml b/scripts/scr_mission_eta/scr_mission_eta.gml index 41fe6c7f3b..3ea001f119 100644 --- a/scripts/scr_mission_eta/scr_mission_eta.gml +++ b/scripts/scr_mission_eta/scr_mission_eta.gml @@ -15,7 +15,7 @@ function scr_mission_eta(star_x, star_y, type = 1, leeway = 10) { if (instance_exists(obj_p_fleet)) { if (type == 1) { var nearest_fleet = get_nearest_player_fleet(star_x, star_y); - if (nearest_fleet != "none") { + if (nearest_fleet != noone) { eta1 = get_viable_travel_time(leeway, nearest_fleet.x, nearest_fleet.y, star_x, star_y, nearest_fleet, false); } // n1=instance_nearest(x,y,obj_p_fleet); diff --git a/scripts/scr_mission_functions/scr_mission_functions.gml b/scripts/scr_mission_functions/scr_mission_functions.gml index 84a494ae52..1f98b0e5ca 100644 --- a/scripts/scr_mission_functions/scr_mission_functions.gml +++ b/scripts/scr_mission_functions/scr_mission_functions.gml @@ -568,10 +568,10 @@ function complete_garrison_mission(problem_index) { if (_result == "none") { //TODO make a dedicated plus minus string function if there isn't one already } else if (_result < 0) { - var _effect = _result * irandom_range(1, 5); + _effect = _result * irandom_range(1, 5); _mission_string += $"A number of diplomatic incidents occured over the period which had considerable negative effects on our disposition with the planetary governor (disposition -{_effect})"; } else { - var _effect = _result * irandom_range(1, 5); + _effect = _result * irandom_range(1, 5); _mission_string += $"As a diplomatic mission the duration of the stay was a success with our political position with the planet being enhanced greatly (disposition +{_effect})"; } @@ -777,8 +777,8 @@ function complete_beast_hunt_mission(targ_planet, problem_index) { //TODO allow most of these functions to be condensed and allow arrays of problems or planets and maybe increase filtering options //filtering options could be done via universal methods that all the filters to be passed to many other game systems /// @self Asset.GMObject.obj_star -function has_any_problem_planet(planet, star = "none") { - if (star == "none") { +function has_any_problem_planet(planet, star = noone) { + if (star == noone) { for (var i = 0; i < array_length(p_problem[planet]); i++) { if (p_problem[planet][i] != "") { return true; @@ -793,9 +793,9 @@ function has_any_problem_planet(planet, star = "none") { } /// @self Asset.GMObject.obj_star -function planet_problemless(planet, star = "none") { +function planet_problemless(planet, star = noone) { var _problemless = true; - if (star == "none") { + if (star == noone) { for (var i = 0; i < array_length(p_problem[planet]); i++) { if (p_problem[planet][i] != "") { _problemless = false; @@ -818,9 +818,9 @@ function star_problemless(){ // returns a bool for if any planet on a given star has the given problem /// @self Asset.GMObject.obj_star -function has_problem_star(problem, star = "none") { +function has_problem_star(problem, star = noone) { var has_problem = false; - if (star == "none") { + if (star == noone) { for (var i = 1; i <= planets; i++) { has_problem = has_problem_planet(i, problem); if (has_problem) { @@ -838,8 +838,8 @@ function has_problem_star(problem, star = "none") { //returns a bool for if a planet has a given problem /// @self Asset.GMObject.obj_star -function has_problem_planet(planet, problem, star = "none") { - if (star == "none") { +function has_problem_planet(planet, problem, star = noone) { + if (star == noone) { return array_contains(p_problem[planet], problem); } else { with (star) { @@ -850,9 +850,9 @@ function has_problem_planet(planet, problem, star = "none") { //returns the array position of a given problem on a given planet if the specfied time is given /// @self Asset.GMObject.obj_star -function has_problem_planet_and_time(planet, problem, time, star = "none") { +function has_problem_planet_and_time(planet, problem, time, star = noone) { var _had_problem = -1; - if (star == "none") { + if (star == noone) { for (var i = 0; i < array_length(p_problem[planet]); i++) { if (p_problem[planet][i] == problem) { if (p_timer[planet][i] == time) { @@ -870,9 +870,9 @@ function has_problem_planet_and_time(planet, problem, time, star = "none") { //returns the array position of a given problem on a given planet if the specfied time is above 0 /// @self Asset.GMObject.obj_star -function has_problem_planet_with_time(planet, problem, star = "none") { +function has_problem_planet_with_time(planet, problem, star = noone) { var _had_problem = -1; - if (star == "none") { + if (star == noone) { for (var i = 0; i < array_length(p_problem[planet]); i++) { if (p_problem[planet][i] == problem) { if (p_timer[planet][i] > 0) { @@ -890,8 +890,8 @@ function has_problem_planet_with_time(planet, problem, star = "none") { //returns the array position of a gien problem on a given planet /// @self Asset.GMObject.obj_star -function find_problem_planet(planet, problem, star = "none") { - if (star == "none") { +function find_problem_planet(planet, problem, star = noone) { + if (star == noone) { for (var i = 0; i < array_length(p_problem[planet]); i++) { if (p_problem[planet][i] == problem) { return i; @@ -907,9 +907,9 @@ function find_problem_planet(planet, problem, star = "none") { ///removie all of a given problem from a planet /// @self Asset.GMObject.obj_star -function remove_planet_problem(planet, problem, star = "none") { +function remove_planet_problem(planet, problem, star = noone) { var _had_problem = -1; - if (star == "none") { + if (star == noone) { for (var i = 0; i < array_length(p_problem[planet]); i++) { if (p_problem[planet][i] == problem) { p_problem[planet][i] = ""; @@ -928,8 +928,8 @@ function remove_planet_problem(planet, problem, star = "none") { //find an open problem slot on a given planet /// @self Asset.GMObject.obj_star -function open_problem_slot(planet, star = "none") { - if (star == "none") { +function open_problem_slot(planet, star = noone) { + if (star == noone) { for (var i = 0; i < array_length(p_problem[planet]); i++) { if (p_problem[planet][i] == "") { return i; @@ -945,8 +945,8 @@ function open_problem_slot(planet, star = "none") { //remove all of a given problem types from a star /// @self Asset.GMObject.obj_star -function remove_star_problem(problem, star = "none") { - if (star == "none") { +function remove_star_problem(problem, star = noone) { + if (star == noone) { for (var i = 1; i <= planets; i++) { remove_planet_problem(i, problem); } @@ -973,9 +973,9 @@ function problem_count_down(planet, count_change = 1) { //add a new problem /// @self Asset.GMObject.obj_star -function add_new_problem(planet, problem, timer, star = "none", other_data = {}) { +function add_new_problem(planet, problem, timer, star = noone, other_data = {}) { var problem_added = false; - if (star == "none") { + if (star == noone) { for (var i = 0; i < array_length(p_problem[planet]); i++) { if (p_problem[planet][i] == "") { p_problem[planet][i] = problem; @@ -987,7 +987,7 @@ function add_new_problem(planet, problem, timer, star = "none", other_data = {}) } } else { with (star) { - problem_added = add_new_problem(planet, problem, timer, "none", other_data); + problem_added = add_new_problem(planet, problem, timer, noone, other_data); } } return problem_added; @@ -1009,9 +1009,9 @@ function increment_mission_completion(mission_data) { //search problem data for a given and key and iff applicable value on that key //TODO increase filtering and search options /// @self Asset.GMObject.obj_star -function problem_has_key_and_value(planet, problem, key, value = "", star = "none") { +function problem_has_key_and_value(planet, problem, key, value = "", star = noone) { var has_data = false; - if (star == "none") { + if (star == noone) { var problem_data = p_problem_other_data[planet][problem]; if (struct_exists(problem_data, key)) { if (value == "") { diff --git a/scripts/scr_mission_reward/scr_mission_reward.gml b/scripts/scr_mission_reward/scr_mission_reward.gml index 88db7585bf..be982d132e 100644 --- a/scripts/scr_mission_reward/scr_mission_reward.gml +++ b/scripts/scr_mission_reward/scr_mission_reward.gml @@ -6,13 +6,7 @@ function scr_mission_reward(mission, star, planet) { // "mech_bionics",id,i // "mech_raider",id,i - var cleanup, i; - cleanup = 0; - i = -1; - repeat (11) { - i += 1; - cleanup[i] = 0; - } + var cleanup = array_create(11, 0); if (mission == "mars_spelunk") { var roll1 = roll_dice_chapter(1, 100, "high"); // For the first STC @@ -100,20 +94,14 @@ function scr_mission_reward(mission, star, planet) { if (_tech_point_gain) { tixt += $"\n{_tech_point_gain} {string_plural("Tech Point", _tech_point_gain)} gained"; } - // scr_alert("green","mission",tixt,star.x,star.y,); scr_event_log("green", tixt); - /*if (found_artifact=1) then scr_event_log("","Artifact recovered from Mars Catacombs."); - if (found_artifact>1) then scr_event_log("",string(found_artifact)+" Artifacts recovered from Mars Catacombs."); - if (found_stc=1) then scr_event_log("","STC Fragment recovered from Mars Catacombs."); - if (found_stc>1) then scr_event_log("",string(found_artifact)+" STC Fragments recovered from Mars Catacombs.");*/ sort_all_companies_to_map(cleanup); } if (mission == "mech_raider") { - var roll1, result; - roll1 = roll_dice_chapter(1, 100, "low"); - result = ""; + var roll1 = roll_dice_chapter(1, 100, "low"); + var result = ""; if (roll1 <= 33) { result = "New"; @@ -129,16 +117,10 @@ function scr_mission_reward(mission, star, planet) { scr_popup("Mechanicus Mission Completed", $"Your {obj_ini.role[100][16]} have worked with the Adeptus Mechanicus in a satisfactory manor. The testing and training went well, but your Land Raider was ultimately lost. 300 Requisition has been given to your Chapter and relations are better than before.", "mechanicus", ""); obj_controller.requisition += 300; obj_controller.disposition[3] += 2; - var com, i, onceh; - onceh = 0; - com = -1; - i = 0; - repeat (11) { + var onceh = 0; + for (var com = 0; com <= 10; com++) { if (onceh == 0) { - com += 1; - i = 0; - repeat (100) { - i += 1; + for (var i = 1; i <= 100; i++) { if ((obj_ini.veh_role[com][i] == "Land Raider") && (obj_ini.veh_loc[com][i] == star.name) && (obj_ini.veh_wid[com][i] == planet)) { onceh = 1; obj_ini.veh_race[com][i] = 0; @@ -158,27 +140,25 @@ function scr_mission_reward(mission, star, planet) { star.p_player[planet] -= 20; } } + } else { + break; } } } if (result == "Land Raider") { scr_popup("Mechanicus Mission Completed", "Your " + string(obj_ini.role[100][16]) + " have worked with the Adeptus Mechanicus in a satisfactory manor. The testing and training went well, but your Land Raider was ultimately lost. A new Land Raider has been provided in return.", "mechanicus", ""); - var com, i, onceh; - onceh = 0; - com = -1; - i = 0; + var onceh = 0; obj_controller.disposition[3] += 1; - repeat (11) { + for (var com = 0; com <= 10; com++) { if (onceh == 0) { - com += 1; - i = 0; - repeat (100) { - i += 1; + for (var i = 1; i <= 100; i++) { if ((obj_ini.veh_role[com][i] == "Land Raider") && (obj_ini.veh_loc[com][i] == star.name) && (obj_ini.veh_wid[com][i] == planet)) { onceh = 1; obj_ini.veh_hp[com][i] = 100; } } + } else { + break; } } } @@ -188,9 +168,7 @@ function scr_mission_reward(mission, star, planet) { obj_controller.disposition[3] += 1; } - i = -1; - repeat (11) { - i += 1; + for (var i = 0; i <= 10; i++) { if (cleanup[i] == 1) { obj_controller.temp[3000] = real(i); with (obj_ini) { @@ -200,16 +178,11 @@ function scr_mission_reward(mission, star, planet) { } } - i = -1; - repeat (11) { - i += 1; - cleanup[i] = 0; - } + cleanup = array_create(11, 0); if (mission == "mech_bionics") { - var roll1, result; - roll1 = roll_dice_chapter(1, 100, "low"); - result = ""; + var roll1 = roll_dice_chapter(1, 100, "low"); + var result = ""; if (roll1 <= 33) { result = "Requisition"; @@ -229,7 +202,6 @@ function scr_mission_reward(mission, star, planet) { obj_controller.requisition += 150 * _marines.number(); _marines.kill_percent(100); } else if (result == "Bionics" || result == "Requisition") { - var _new_bionics = irandom_range(40, 100); obj_controller.disposition[3] += 1; mech_disp_change = 1; diff --git a/scripts/scr_move_unit_info/scr_move_unit_info.gml b/scripts/scr_move_unit_info/scr_move_unit_info.gml index 95870c4c52..ee8a427ea5 100644 --- a/scripts/scr_move_unit_info/scr_move_unit_info.gml +++ b/scripts/scr_move_unit_info/scr_move_unit_info.gml @@ -26,7 +26,7 @@ function scr_move_unit_info(start_company, end_company, start_slot, end_slot, ev _temp_struct.company = start_company; _temp_struct.marine_number = start_slot; - var _temp_struct = fetch_unit([end_company, end_slot]); + _temp_struct = fetch_unit([end_company, end_slot]); if (is_struct(_temp_struct)) { _temp_struct.company = end_company; _temp_struct.marine_number = end_slot; diff --git a/scripts/scr_ork_fleet_functions/scr_ork_fleet_functions.gml b/scripts/scr_ork_fleet_functions/scr_ork_fleet_functions.gml index 3a73a7c08b..777250e6fe 100644 --- a/scripts/scr_ork_fleet_functions/scr_ork_fleet_functions.gml +++ b/scripts/scr_ork_fleet_functions/scr_ork_fleet_functions.gml @@ -41,7 +41,7 @@ function ork_fleet_move() { } with (obj_star) { - if (is_dead_star() || owner == eFACTION.ORK || scr_orbiting_fleet(eFACTION.ORK) != "none") { + if (is_dead_star() || owner == eFACTION.ORK || scr_orbiting_fleet(eFACTION.ORK) != noone) { instance_deactivate_object(id); } } @@ -58,13 +58,13 @@ function ork_fleet_move() { function ork_fleet_arrive_target() { instance_activate_object(obj_en_fleet); var _ork_fleet = scr_orbiting_fleet(eFACTION.ORK); - if (_ork_fleet == "none") { + if (_ork_fleet == noone) { return; } var aler = 0; var _imperial_ship = scr_orbiting_fleet([eFACTION.IMPERIUM, eFACTION.MECHANICUS]); - if (_imperial_ship == "none" && planets > 0 && !has_orbiting_player_fleet()) { + if (_imperial_ship == noone && planets > 0 && !has_orbiting_player_fleet()) { var _allow_landing = true, ork_attack_planet = 0, l = 0; var _planets = shuffled_planet_array(); for (var i = 0; i < array_length(_planets); i++) { @@ -83,9 +83,9 @@ function ork_fleet_arrive_target() { if (p_tyranids[ork_attack_planet] <= 0) { if (planet_feature_bool(p_feature[ork_attack_planet], eP_FEATURES.GENE_STEALER_CULT)) { _pdata.delete_feature(eP_FEATURES.GENE_STEALER_CULT); - adjust_influence(eFACTION.TYRANIDS, -25, ork_attack_planet); + adjust_influence(eFACTION.TYRANIDS, -25, ork_attack_planet, self); var nearest_imperial = nearest_star_with_ownership(x, y, eFACTION.IMPERIUM, self.id); - if (nearest_imperial != "none") { + if (nearest_imperial != noone) { var targ_planet = scr_get_planet_with_owner(nearest_imperial, eFACTION.IMPERIUM); if (targ_planet == -1) { targ_planet = irandom_range(1, nearest_imperial.planets); @@ -97,6 +97,7 @@ function ork_fleet_arrive_target() { } _allow_landing = !is_dead_star(); + var _fleet_persists = false; if (_allow_landing) { for (var i = 0; i < planets; i++) { var _planet = _planets[i]; @@ -104,8 +105,6 @@ function ork_fleet_arrive_target() { if ((p_type[_planet] != "Dead") && (p_orks[_planet] < 4) && (i <= planets)) { p_orks[_planet] += max(2, floor(_ork_fleet.image_index * 0.8)); - var _fleet_persists = false; - if (fleet_has_cargo("ork_warboss", _ork_fleet)) { array_push(p_feature[_planet], _ork_fleet.cargo_data.ork_warboss); p_orks[_planet] = 6; @@ -207,17 +206,19 @@ function init_ork_waagh(override = false) { } } + var _waaagh_star = noone; var _waaagh_star_found = false; if (array_length(ork_waagh_activity)) { - var _waaagh_star = array_random_element(ork_waagh_activity); + _waaagh_star = array_random_element(ork_waagh_activity); _waaagh_star_found = true; } else if (array_length(_any_ork_star) > 0) { - var _waaagh_star = array_random_element(_any_ork_star); + _waaagh_star = array_random_element(_any_ork_star); _waaagh_star_found = true; } + var _pdata = noone; if (_waaagh_star_found) { - var _pdata = _waaagh_star[0].get_planet_data(_waaagh_star[1]); + _pdata = _waaagh_star[0].get_planet_data(_waaagh_star[1]); var _boss = _pdata.add_feature(eP_FEATURES.ORKWARBOSS); if (override) { diff --git a/scripts/scr_ork_planet_functions/scr_ork_planet_functions.gml b/scripts/scr_ork_planet_functions/scr_ork_planet_functions.gml index fc914789a9..974d0a0483 100644 --- a/scripts/scr_ork_planet_functions/scr_ork_planet_functions.gml +++ b/scripts/scr_ork_planet_functions/scr_ork_planet_functions.gml @@ -25,10 +25,10 @@ function ork_ship_production(planet) { } if (contin == 2) { fleet = scr_orbiting_fleet(eFACTION.ORK); - if (fleet == "none") { + if (fleet == noone) { contin = 3; } - if ((fleet != "none") && (contin != 3)) { + if ((fleet != noone) && (contin != 3)) { rando = choose(1, 1, 1, 1, 1, 2, 2, 2, 2); switch (rando) { case 1: diff --git a/scripts/scr_perils_table/scr_perils_table.gml b/scripts/scr_perils_table/scr_perils_table.gml index 73a9152519..4f3a3a1b79 100644 --- a/scripts/scr_perils_table/scr_perils_table.gml +++ b/scripts/scr_perils_table/scr_perils_table.gml @@ -5,17 +5,15 @@ function scr_perils_table(perils_strength, unit, psy_discipline, power_name, uni 1, function(perils_strength, unit, psy_discipline, power_name, unit_id) { unit.corruption += roll_dice_chapter(1, 6, "low"); - var flavour_text2 = "He begins to gibber as psychic backlash overtakes him."; - return flavour_text2; - } + return "He begins to gibber as psychic backlash overtakes him."; + }, ], [ 5, function(perils_strength, unit, psy_discipline, power_name, unit_id) { marine_casting_cooldown[unit_id] += roll_dice_chapter(1, 6, "low"); - var flavour_text2 = "His mind is burned fiercely by the warp."; - return flavour_text2; - } + return "His mind is burned fiercely by the warp."; + }, ], [ 15, @@ -31,44 +29,39 @@ function scr_perils_table(perils_strength, unit, psy_discipline, power_name, uni } } } - var flavour_text2 = $"Psychic energy outlash knocks him out for {_cooldown} hours, and stuns nearby marines for {_cooldown2}."; - return flavour_text2; - } + return $"Psychic energy outlash knocks him out for {_cooldown} hours, and stuns nearby marines for {_cooldown2}."; + }, ], [ 20, function(perils_strength, unit, psy_discipline, power_name, unit_id) { unit.add_or_sub_health(roll_dice_chapter(1, 50, "low") * -1); + var flavour_text2 = "The psychic blast he had prepared runs loose, striking himself!"; switch (psy_discipline) { case "biomancy": - var flavour_text2 = "The psychic blast he had prepared runs loose, boiling his own blood!"; + flavour_text2 = "The psychic blast he had prepared runs loose, boiling his own blood!"; break; case "pyromancy": - var flavour_text2 = "He lights on fire from the inside out, burning in agony!"; + flavour_text2 = "He lights on fire from the inside out, burning in agony!"; break; case "telekinesis": - var flavour_text2 = "The blast he had prepared runs loose, smashing himself into the ground!"; - break; - default: - var flavour_text2 = "The psychic blast he had prepared runs loose, striking himself!"; + flavour_text2 = "The blast he had prepared runs loose, smashing himself into the ground!"; break; } return flavour_text2; - } + }, ], [ 30, function(perils_strength, unit, psy_discipline, power_name, unit_id) { marine_casting_cooldown[unit_id] += 20; unit.corruption += roll_dice_chapter(1, 6, "low"); - var flavour_text2 = $"His mind is seared by the warp, now unable to cast more powers for {marine_casting_cooldown[unit_id]} hours."; - return flavour_text2; - } + return $"His mind is seared by the warp, now unable to cast more powers for {marine_casting_cooldown[unit_id]} hours."; + }, ], [ 40, function(perils_strength, unit, psy_discipline, power_name, unit_id) { - var flavour_text2 = "Capricious voices eminate from the surrounding area, whispering poisonous lies and horrible truths."; unit.corruption += roll_dice_chapter(1, 10, "low"); if (men > 0) { repeat (6) { @@ -79,16 +72,14 @@ function scr_perils_table(perils_strength, unit, psy_discipline, power_name, uni } } } - return flavour_text2; - } + return "Capricious voices eminate from the surrounding area, whispering poisonous lies and horrible truths."; + }, ], [ 50, function(perils_strength, unit, psy_discipline, power_name, unit_id) { - var flavour_text2 = "Dark, shifting lights form into several "; var d1 = 0, d2 = 0, d3 = 0; var dem = choose("Pink Horror", "Daemonette", "Bloodletter", "Plaguebearer"); - flavour_text2 += string(dem) + "s."; d1 = instance_nearest(x, y, obj_enunit); var exist; exist = 0; @@ -131,13 +122,12 @@ function scr_perils_table(perils_strength, unit, psy_discipline, power_name, uni obj_ncombat.enemy_forces += d2; obj_ncombat.enemy_max += d2; } - return flavour_text2; - } + return "Dark, shifting lights form into several " + string(dem) + "s."; + }, ], [ 60, function(perils_strength, unit, psy_discipline, power_name, unit_id) { - var flavour_text2 = "There is a massive explosion of warp energy which injures him and several other marines!"; unit.add_or_sub_health(roll_dice_chapter(1, 50, "low") * -1); if (men > 0) { repeat (6) { @@ -147,16 +137,15 @@ function scr_perils_table(perils_strength, unit, psy_discipline, power_name, uni } } } - return flavour_text2; - } + return "There is a massive explosion of warp energy which injures him and several other marines!"; + }, ], [ 70, function(perils_strength, unit, psy_discipline, power_name, unit_id) { obj_ncombat.global_perils += 10; - var flavour_text2 = "Wind shrieks and blood pours from the sky! The warp feels unstable."; - return flavour_text2; - } + return "Wind shrieks and blood pours from the sky! The warp feels unstable."; + }, ], [ 80, @@ -171,33 +160,19 @@ function scr_perils_table(perils_strength, unit, psy_discipline, power_name, uni } } unit.add_equipment_repairs(eEQUIPMENT_SLOT.ALL); - var flavour_text2 = "A massive shockwave eminates from the marine, who is knocked out cold! All of his equipment is damaged!"; - return flavour_text2; - } + return "A massive shockwave eminates from the marine, who is knocked out cold! All of his equipment is damaged!"; + }, ], [ 90, function(perils_strength, unit, psy_discipline, power_name, unit_id) { - var flavour_text2; marine_casting_cooldown[unit_id] += 999; unit.corruption += roll_dice_chapter(5, 10, "low"); - flavour_text2 = "The marine's flesh begins to twist and rip, seemingly turning inside out. His form looms up, and up, and up. Within seconds a Greater Daemon of "; var dem = choose("Slaanesh", "Nurgle", "Tzeentch"); - /* if (using_tome != "") { - if (string_count("daemonic", marine_gear[unit_id]) > 0) { - if (string_count("SLAANESH", marine_gear[unit_id]) > 0) { - dem = "Slaanesh"; - } - if (string_count("NURGLE", marine_gear[unit_id]) > 0) { - dem = "Nurgle"; - } - if (string_count("TZEENTCH", marine_gear[unit_id]) > 0) { - dem = "Tzeentch"; - } - } - } */ - var d1 = 0, d2 = 0, d3 = 0, d1 = instance_nearest(x, y, obj_enunit); + var d1 = instance_nearest(x, y, obj_enunit); + var d2 = 0; + var d3 = 0; repeat (30) { if (d3 == 0) { d2 += 1; @@ -220,28 +195,26 @@ function scr_perils_table(perils_strength, unit, psy_discipline, power_name, uni d1.neww = 1; d1.alarm[1] = 1; - flavour_text2 += string(dem) + " has taken form."; - return flavour_text2; - } + return "The marine's flesh begins to twist and rip, seemingly turning inside out. His form looms up, and up, and up. Within seconds a Greater Daemon of " + string(dem) + " has taken form."; + }, ], [ 100, function(perils_strength, unit, psy_discipline, power_name, unit_id) { - var flavour_text2 = ""; + var flavour_text2 = choose("There is a snap, and pop, and he disappears entirely.", "He explodes into a cloud of gore, splattering guts and ceramite across the battlefield."); if (unit.role() == obj_ini.role[100][eROLE.CHAPTERMASTER]) { - var flavour_text2 = "There is a snap, and pop, and he disappears entirely. Reappearing minutes later, barely alive and stunned."; + flavour_text2 = "There is a snap, and pop, and he disappears entirely. Reappearing minutes later, barely alive and stunned."; unit.update_health(10); marine_casting_cooldown[unit_id] = 999; } else { - flavour_text2 = choose("There is a snap, and pop, and he disappears entirely.", "He explodes into a cloud of gore, splattering guts and ceramite across the battlefield."); unit.update_health(0); marine_dead[unit_id] = 2; } return flavour_text2; - } - ] + }, + ], ]; for (var i = array_length(combat_perils) - 1; i >= 0; i--) { diff --git a/scripts/scr_planetary_feature/scr_planetary_feature.gml b/scripts/scr_planetary_feature/scr_planetary_feature.gml index d5b33a64c6..58300f6705 100644 --- a/scripts/scr_planetary_feature/scr_planetary_feature.gml +++ b/scripts/scr_planetary_feature/scr_planetary_feature.gml @@ -291,33 +291,25 @@ function awake_tomb_world(planet) { //selas a tomb world and switche off awake so will no longer spawn necrons or necron fleets function seal_tomb_world(planet) { - var awake_tomb = 0; var tombs = search_planet_features(planet, eP_FEATURES.NECRON_TOMB); if (array_length(tombs) > 0) { for (var tomb = 0; tomb < array_length(tombs); tomb++) { - awake_tomb = 1; planet[tombs[tomb]].awake = 0; planet[tombs[tomb]].sealed = 1; planet[tombs[tomb]].planet_display = "Sealed Necron Tomb"; - if (awake_tomb == 1) { - break; - } + break; } } } //awakens a tomb world so necrons and necron fleets will spawn function awaken_tomb_world(planet) { - var awake_tomb = 0; var tombs = search_planet_features(planet, eP_FEATURES.NECRON_TOMB); if (array_length(tombs) > 0) { for (var tomb = 0; tomb < array_length(tombs); tomb++) { if (planet[tombs[tomb]].awake == 0) { - awake_tomb = 1; planet[tombs[tomb]].awake = 1; planet[tombs[tomb]].planet_display = "Active Necron Tomb"; - } - if (awake_tomb == 1) { break; } } @@ -333,12 +325,13 @@ function scr_planetary_feature(planet_num) { if (feat.player_hidden == 1) { feat.player_hidden = 0; var numeral_n = planet_numeral_name(planet_num); + var lop = ""; switch (feat.f_type) { case eP_FEATURES.SORORITAS_CATHEDRAL: if (obj_controller.known[eFACTION.ECCLESIARCHY] == 0) { obj_controller.known[eFACTION.ECCLESIARCHY] = 1; } - var lop = $"Sororitas Cathedral discovered on {numeral_n}."; + lop = $"Sororitas Cathedral discovered on {numeral_n}."; scr_alert("green", "feature", lop, x, y); scr_event_log("", lop); if (p_heresy[planet_num] > 10) { @@ -348,32 +341,32 @@ function scr_planetary_feature(planet_num) { goo = 1; break; case eP_FEATURES.NECRON_TOMB: - var lop = $"Necron Tomb discovered on {numeral_n}."; + lop = $"Necron Tomb discovered on {numeral_n}."; scr_alert("red", "feature", lop, x, y); scr_event_log("red", lop); break; case eP_FEATURES.ARTIFACT: - var lop = $"Artifact discovered on {numeral_n}."; + lop = $"Artifact discovered on {numeral_n}."; scr_alert("green", "feature", lop, x, y); scr_event_log("", lop); break; case eP_FEATURES.STC_FRAGMENT: - var lop = $"STC Fragment located on {numeral_n}."; + lop = $"STC Fragment located on {numeral_n}."; scr_alert("green", "feature", lop, x, y); scr_event_log("", lop); break; case eP_FEATURES.ANCIENT_RUINS: - var lop = $"A {feat.ruins_size} Ancient Ruins discovered on {string(name)} {scr_roman(planet_num)}."; + lop = $"A {feat.ruins_size} Ancient Ruins discovered on {string(name)} {scr_roman(planet_num)}."; scr_alert("green", "feature", lop, x, y); scr_event_log("", lop); break; case eP_FEATURES.CAVE_NETWORK: - var lop = $"Extensive Cave Network discovered on {numeral_n}."; + lop = $"Extensive Cave Network discovered on {numeral_n}."; scr_alert("green", "feature", lop, x, y); scr_event_log("", lop); break; case eP_FEATURES.ORKWARBOSS: - var lop = $"Ork Warboss discovered on {numeral_n}."; + lop = $"Ork Warboss discovered on {numeral_n}."; scr_alert("red", "feature", lop, x, y); scr_event_log("red", lop); break; @@ -384,7 +377,7 @@ function scr_planetary_feature(planet_num) { function create_starship_event() { var star = scr_random_find(2, true, "", ""); - if (star == undefined) { + if (star == noone) { LOGGER.error("RE: couldn't find starship target"); return false; } else { @@ -408,10 +401,6 @@ function ground_mission_leave_it_function() { /// @self Struct.PlanetData function discover_artifact_popup(feature) { obj_controller.menu = eMENU.DEFAULT; - /*if ((planet_type == "Dead" || current_owner == eFACTION.PLAYER)) { - alarm[4] = 1; - exit; - }*/ var pop = instance_create(0, 0, obj_popup); pop.image = "artifact"; @@ -628,17 +617,10 @@ function ground_forces_collect_artifact() { with (obj_ground_mission) { scr_return_ship(pdata.system.name, self, pdata.planet); - var man_size, ship_id, comp, i; - i = 0; - ship_id = 0; - man_size = 0; - comp = 0; - ship_id = get_valid_player_ship("", loc); + var ship_id = get_valid_player_ship("", loc); var last_artifact = scr_add_artifact("random", "random", 4, loc, ship_id + 500); - var i = 0; - var mission = "bad"; var mission_roll = irandom(100) + 1; if (scr_has_adv("Ambushers")) { @@ -646,14 +628,12 @@ function ground_forces_collect_artifact() { } if (mission_roll <= 60) { mission = "good"; - } // 135 + } if (pdata.planet_type == "Dead") { mission = "good"; } - // mission="bad"; - var pop; - pop = instance_create(0, 0, obj_popup); + var pop = instance_create(0, 0, obj_popup); pop.image = "artifact_recovered"; pop.title = "Artifact Recovered!"; @@ -668,7 +648,7 @@ function ground_forces_collect_artifact() { } if (pdata.current_owner == eFACTION.MECHANICUS) { obj_controller.disposition[3] -= 10; - } // max(obj_controller.disposition/4,10) + } if (pdata.current_owner == 4) { obj_controller.disposition[4] -= max(obj_controller.disposition[4] / 4, 10); } @@ -710,7 +690,12 @@ function ground_forces_collect_artifact() { } if (scr_has_adv("Tech-Scavengers")) { - var ex1 = "", ex1_num = 0, ex2 = "", ex2_num = 0, ex3 = "", ex3_num = 0; + var ex1 = ""; + var ex1_num = 0; + var ex2 = ""; + var ex2_num = 0; + var ex3 = ""; + var ex3_num = 0; var stah = instance_nearest(x, y, obj_star); @@ -821,14 +806,6 @@ function governor_negotiate_artifact() { function remove_stc_from_planet() { with (obj_ground_mission) { - var comp, plan, i; - i = 0; - comp = 0; - plan = 0; - plan = instance_nearest(x, y, obj_star); - - var mission, mission_roll; - var mission = "bad"; var mission_roll = floor(random(100)) + 1; @@ -840,14 +817,12 @@ function remove_stc_from_planet() { } if (mission_roll <= 60) { mission = "good"; - } // 135 + } if (pdata.planet_type == "Dead") { mission = "good"; } - // mission="bad"; - var pop; - pop = instance_create(0, 0, obj_popup); + var pop = instance_create(0, 0, obj_popup); pop.image = "artifact_recovered"; pop.title = "STC Recovered!"; @@ -860,34 +835,16 @@ function remove_stc_from_planet() { if (mission == "good" && pdata.origional_owner == 3 && pdata.planet_type == "Forge") { pop.text = "Your forces descend into the vaults of the Mechanicus Forge, bypassing sentries, automated defenses, and blast doors on the way.##"; pop.text += "The STC Fragment has been safely recovered and stowed away. It is ready to be decrypted or gifted at your convenience."; - - /*if (pdata.planet_type!="Dead"){ - if (pdata.current_owner=2) then obj_controller.disposition[2]-=1; - if (pdata.current_owner=eFACTION.MECHANICUS) then obj_controller.disposition[3]-=10;// max(obj_controller.disposition/4,10) - if (pdata.current_owner=4) then obj_controller.disposition[4]-=max(obj_controller.disposition[4]/4,10); - if (pdata.current_owner=5) then obj_controller.disposition[5]-=3; - if (pdata.current_owner=8) then obj_controller.disposition[8]-=3; - }*/ scr_return_ship(pdata.system.name, self, pdata.planet); } if (mission == "bad" && pdata.origional_owner == eFACTION.MECHANICUS && pdata.planet_type == "Forge") { - /*pop.text="Your marines converge upon the STC Fragment; resistance is light and easily dealt with. After a brief firefight it is retrieved.##"; - pop.text+="The fragment been safely stowed away, and is ready to be decrypted or gifted at your convenience."; - - */ - pop.image = "thallax"; pop.text = "Your forces descend into the vaults of the Mechanicus Forge. Sentries, automated defenses, and blast doors stand in their way.##"; pop.text += "Half-way through the mission a small army of Praetorian Servitors and Skitarii bear down upon your men. The Mechanicus guards seem to be upset."; - /*if (pdata.current_owner=2) then obj_controller.disposition[2]-=2;*/ if (pdata.current_owner == eFACTION.MECHANICUS) { obj_controller.disposition[3] -= 40; } - /*if (pdata.current_owner=4) then obj_controller.disposition[4]-=max(obj_controller.disposition[4]/3,20); - if (pdata.current_owner=5) then obj_controller.disposition[5]-=max(obj_controller.disposition[3]/4,15); - if (pdata.current_owner=6) then obj_controller.disposition[6]-=15; - if (pdata.current_owner=8) then obj_controller.disposition[8]-=8;*/ if (pdata.current_owner > 3 && pdata.current_owner <= 6) { scr_audience(pdata.current_owner, "artifact_angry",); @@ -909,16 +866,14 @@ function remove_stc_from_planet() { } if (scr_has_adv("Tech-Scavengers")) { - var ex1, ex1_num, ex2, ex2_num, ex3, ex3_num; - ex1 = ""; - ex1_num = 0; - ex2 = ""; - ex2_num = 0; - ex3 = ""; - ex3_num = 0; + var ex1 = ""; + var ex1_num = 0; + var ex2 = ""; + var ex2_num = 0; + var ex3 = ""; + var ex3_num = 0; - var stah; - stah = instance_nearest(x, y, obj_star); + var stah = instance_nearest(x, y, obj_star); if (pdata.origional_owner == 2) { ex1 = "Meltagun"; @@ -976,9 +931,6 @@ function remove_stc_from_planet() { clear_diplo_choices(); obj_controller.menu = 0; instance_destroy(); - - /* */ - /* */ } instance_destroy(); } @@ -986,13 +938,8 @@ function remove_stc_from_planet() { function recieve_artifact_in_discussion() { scr_return_ship(loc, self, num); - var man_size, comp, plan, i; - i = 0; - man_size = 0; - comp = 0; - plan = 0; var ship_id = get_valid_player_ship("", loc); - plan = instance_nearest(x, y, obj_star); + var plan = instance_nearest(x, y, obj_star); var last_artifact = scr_add_artifact("random", "random", 4, loc, ship_id + 500); var pop = instance_create(0, 0, obj_popup); @@ -1017,8 +964,7 @@ function recieve_artifact_in_discussion() { function send_stc_to_adeptus_mech() { with (obj_ground_mission) { - var _target_planet; - _target_planet = instance_nearest(x, y, obj_star); + var _target_planet = instance_nearest(x, y, obj_star); pdata.delete_feature(eP_FEATURES.STC_FRAGMENT); scr_return_ship(pdata.system.name, self, pdata.planet); @@ -1085,8 +1031,7 @@ function send_stc_to_adeptus_mech() { } } - var _enemy_fleet; - var _target = -1; + var _target = noone; if (instance_exists(obj_temp2)) { _target = nearest_star_with_ownership(obj_temp2.x, obj_temp2.y, obj_controller.diplomacy); @@ -1095,7 +1040,7 @@ function send_stc_to_adeptus_mech() { } else if ((!instance_exists(obj_temp2)) && (!instance_exists(obj_temp7)) && instance_exists(obj_p_fleet) && (obj_ini.fleet_type == ePLAYER_BASE.HOME_WORLD)) { // If player fleet is flying about then get their target for new target with (obj_p_fleet) { - var pop; + var pop = noone; if ((capital_number > 0) && (action != "")) { pop = instance_create(action_x, action_y, obj_temp2); pop.action_eta = action_eta; @@ -1108,7 +1053,7 @@ function send_stc_to_adeptus_mech() { } if (is_struct(_target)) { - _enemy_fleet = instance_create(_target.x, _target.y, obj_en_fleet); + var _enemy_fleet = instance_create(_target.x, _target.y, obj_en_fleet); _enemy_fleet.owner = obj_controller.diplomacy; _enemy_fleet.home_x = _target.x; diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index 2dcad296f9..3a4592724e 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -1,6 +1,3 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information - /// @self Asset.GMObject.obj_pnunit function add_second_profiles_to_stack(weapon, head_role = false, unit = "none") { if (array_length(weapon.second_profiles) > 0) { @@ -269,10 +266,8 @@ function scr_player_combat_weapon_stacks() { veh = 0; men = 0; dreads = 0; - for (i = 0; i < array_length(att); i++) { - // dudes[i]=""; + for (var i = 0; i < array_length(att); i++) { dudes_num[i] = 0; - // dudes_vehicle[i]=0; att[i] = 0; apa[i] = 0; wep_num[i] = 0; @@ -280,11 +275,10 @@ function scr_player_combat_weapon_stacks() { // if (wep_owner[i]!="") and (wep_num[i]>1) then wep_owner[i]="assorted";// What if they are using two ranged weapons? Hmmmmm? } - var dreaded = false, unit; + var dreaded = false; - var mobi_item; - for (g = 0; g < array_length(unit_struct); g++) { - unit = unit_struct[g]; + for (var g = 0; g < array_length(unit_struct); g++) { + var unit = unit_struct[g]; if (is_struct(unit)) { if (unit.hp() > 0) { marine_dead[g] = 0; @@ -367,13 +361,10 @@ function scr_player_combat_weapon_stacks() { } } - var j = 0, good = 0, open = 0; // Counts the number and types of marines within this object - for (j = 0; j <= 40; j++) { + var good = 0, open = 0; // Counts the number and types of marines within this object + for (var j = 0; j <= 40; j++) { if ((dudes[j] == "") && (open == 0)) { open = j; // Determine if vehicle here - - //if (dudes[j]="Venerable "+string(obj_ini.role[100][6])) then dudes_vehicle[j]=1; - //if (dudes[j]=obj_ini.role[100][6]) then dudes_vehicle[j]=1; } if (marine_type[g] == dudes[j]) { good = 1; @@ -419,7 +410,7 @@ function scr_player_combat_weapon_stacks() { } var primary_melee = unit.melee_damage_data[3]; //collect unit melee data - var weapon_stack_index = find_stack_index(primary_melee.name, head_role, unit); + weapon_stack_index = find_stack_index(primary_melee.name, head_role, unit); if (weapon_stack_index > -1) { if (range[weapon_stack_index] > 1.9) { continue; @@ -437,7 +428,7 @@ function scr_player_combat_weapon_stacks() { } } } - for (g = 0; g < array_length(veh_id); g++) { + for (var g = 0; g < array_length(veh_id); g++) { if ((veh_id[g] > 0) && (veh_hp[g] > 0) && (veh_dead[g] != 1)) { if ((veh_id[g] > 0) && (veh_hp[g] > 0)) { veh_dead[g] = 0; @@ -446,10 +437,11 @@ function scr_player_combat_weapon_stacks() { veh++; } - var j = 0, good = 0, open = 0; // Counts the number and types of marines within this object + // Counts the number and types of marines within this object if (veh_dead[g] != 1) { - repeat (40) { - j += 1; + var good = 0; + var open = 0; + for (var j = 1; j <= 40; j++) { if ((dudes[j] == "") && (open == 0)) { open = j; } @@ -466,9 +458,8 @@ function scr_player_combat_weapon_stacks() { } } - var j = 0, good = 0, open = 0, weapon, vehicle_weapon_set; if (veh_dead[g] != 1) { - vehicle_weapon_set = [ + var vehicle_weapon_set = [ veh_wep1[g], veh_wep2[g], veh_wep3[g] @@ -476,9 +467,9 @@ function scr_player_combat_weapon_stacks() { for (var wep_slot = 0; wep_slot < 3; wep_slot++) { var weapon_check = vehicle_weapon_set[wep_slot]; if (weapon_check != "") { - weapon = gear_weapon_data("weapon", weapon_check, "all", false, "standard"); + var weapon = gear_weapon_data("weapon", weapon_check, "all", false, "standard"); if (is_struct(weapon)) { - for (j = 0; j <= 40; j++) { + for (var j = 0; j <= 40; j++) { if (wep[j] == "" || wep[j] == weapon.name) { add_data_to_stack(j, weapon,,, "vehicle"); break; @@ -502,7 +493,7 @@ function scr_player_combat_weapon_stacks() { var h = 0; for (var i = 0; i < array_length(unit_struct); i++) { if (h == 0) { - unit = unit_struct[i]; + var unit = unit_struct[i]; if (!is_struct(unit)) { continue; } diff --git a/scripts/scr_player_fleet_combat_functions/scr_player_fleet_combat_functions.gml b/scripts/scr_player_fleet_combat_functions/scr_player_fleet_combat_functions.gml index ee42ff8c85..cd7e0efa79 100644 --- a/scripts/scr_player_fleet_combat_functions/scr_player_fleet_combat_functions.gml +++ b/scripts/scr_player_fleet_combat_functions/scr_player_fleet_combat_functions.gml @@ -1,6 +1,5 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information -/// @param {Asset.GMObject.obj_fleet} combat +/// @param {Id.Instance.obj_p_fleet} fleet +/// @param {Id.Instance.obj_fleet} combat function add_fleet_ships_to_combat(fleet, combat) { var capital_count = array_length(fleet.capital); var _ship_id; @@ -53,7 +52,7 @@ function add_fleet_ships_to_combat(fleet, combat) { } } -/// @param {Asset.GMObject.obj_fleet} combat +/// @param {Id.Instance.obj_fleet} combat function sort_ships_into_columns(combat) { var col = 5; with (combat) { @@ -129,7 +128,6 @@ function player_fleet_ship_spawner() { hei = 160; sizz = 3; } - // if (column[col]="Slaughtersong"){hei=200;sizz=3;} if (column[col] == "Strike Cruiser" || column[col] == "frigate") { hei = 96; sizz = 2; @@ -150,7 +148,6 @@ function player_fleet_ship_spawner() { temp2 += 20; } - // show_message(string(column_num[col])+" "+string(column[col])+" X:"+string(x2)); for (var k = 0; k < array_length(ship_id); k++) { if (ship_class[k] == column[col] || (player_ships_class(ship_id[k]) == column[col])) { man = -1; diff --git a/scripts/scr_player_fleet_functions/scr_player_fleet_functions.gml b/scripts/scr_player_fleet_functions/scr_player_fleet_functions.gml index 44d5157973..2064f118ed 100644 --- a/scripts/scr_player_fleet_functions/scr_player_fleet_functions.gml +++ b/scripts/scr_player_fleet_functions/scr_player_fleet_functions.gml @@ -1,12 +1,9 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more informationype -function fleet_has_roles(fleet = "none", roles) { +function fleet_has_roles(fleet, roles = []) { var all_ships = fleet_full_ship_array(fleet); - var unit; for (var i = 0; i <= 10; i++) { for (var s = 0; s < array_length(obj_ini.TTRPG[i]); s++) { - unit = fetch_unit([i, s]); + var unit = fetch_unit([i, s]); if (unit.planet_location < 1) { if (array_contains(all_ships, unit.ship_location)) { if (array_contains(roles, unit.role())) { @@ -18,9 +15,8 @@ function fleet_has_roles(fleet = "none", roles) { } } -function fleet_engaged(fleet = undefined) { +function fleet_engaged(fleet) { var _engaged = false; - fleet ??= self; var _fleet_action = fleet.action; if (_fleet_action != "" && _fleet_action != "move") { //don't inspect if engaged in non negotiable actions @@ -32,15 +28,14 @@ function fleet_engaged(fleet = undefined) { return _engaged; } -function split_selected_into_new_fleet(start_fleet = "none") { - var new_fleet; - if (start_fleet == "none") { - new_fleet = instance_create(x, y, obj_p_fleet); - new_fleet.owner = eFACTION.PLAYER; +function split_selected_into_new_fleet(start_fleet) { + var new_fleet = instance_create(x, y, obj_p_fleet); + new_fleet.owner = eFACTION.PLAYER; + with (start_fleet) { // Pass over ships to the new fleet, if they are selected var cap_number = array_length(capital); - for (i = 0; i < cap_number; i++) { + for (var i = 0; i < cap_number; i++) { if ((capital[i] != "") && capital_sel[i]) { move_ship_between_player_fleets(self, new_fleet, "capital", i); i--; @@ -48,7 +43,7 @@ function split_selected_into_new_fleet(start_fleet = "none") { } } var frig_number = array_length(frigate); - for (i = 0; i < frig_number; i++) { + for (var i = 0; i < frig_number; i++) { if ((frigate[i] != "") && frigate_sel[i]) { move_ship_between_player_fleets(self, new_fleet, "frigate", i); i--; @@ -56,7 +51,7 @@ function split_selected_into_new_fleet(start_fleet = "none") { } } var esc_number = array_length(escort); - for (i = 0; i < esc_number; i++) { + for (var i = 0; i < esc_number; i++) { if ((escort[i] != "") && escort_sel[i]) { move_ship_between_player_fleets(self, new_fleet, "escort", i); i--; @@ -64,10 +59,6 @@ function split_selected_into_new_fleet(start_fleet = "none") { } } set_player_fleet_image(); - } else { - with (start_fleet) { - new_fleet = split_selected_into_new_fleet(); - } } return new_fleet; } @@ -88,7 +79,7 @@ function set_new_player_fleet_course(target_array) { var target_planet = find_star_by_name(target_array[0]); var nearest_planet = instance_nearest(x, y, obj_star); var from_star = point_distance(nearest_planet.x, nearest_planet.y, x, y) < 75; - var valid = target_planet != "none"; + var valid = target_planet != noone; if (valid) { valid = !(target_planet.id == nearest_planet.id && from_star); } @@ -110,7 +101,7 @@ function set_new_player_fleet_course(target_array) { action_y = target_planet.y; action = "move"; just_left = true; - orbiting = 0; + orbiting = noone; x = x + lengthdir_x(48, point_direction(x, y, action_x, action_y)); y = y + lengthdir_y(48, point_direction(x, y, action_x, action_y)); set_fleet_location("Warp"); @@ -235,7 +226,7 @@ function set_player_fleet_image() { } function find_ships_fleet(index) { - var _chosen_fleet = "none"; + var _chosen_fleet = noone; with (obj_p_fleet) { if (array_contains(capital_num, index) || array_contains(frigate_num, index) || array_contains(escort_num, index)) { _chosen_fleet = self; @@ -244,7 +235,7 @@ function find_ships_fleet(index) { return _chosen_fleet; } -function add_ship_to_fleet(index, fleet = "none") { +function add_ship_to_fleet(index, fleet = noone) { var _escorts = [ "Escort", "Hunter", @@ -256,7 +247,7 @@ function add_ship_to_fleet(index, fleet = "none") { ]; var _frigates = ["Strike Cruiser"]; - if (fleet == "none") { + if (fleet == noone) { if (array_contains(_capitals, obj_ini.ship_class[index])) { array_push(capital, obj_ini.ship[index]); array_push(capital_num, index); @@ -285,16 +276,14 @@ function add_ship_to_fleet(index, fleet = "none") { function player_retreat_from_fleet_combat() { try { - var p_strength, ratio, diceh, _roll_100; var mfleet = obj_turn_end.battle_pobject[obj_turn_end.current_battle]; - var _fleet_ships = fleet_full_ship_array(mfleet); var en_strength = 0; var p_strength = mfleet.escort_number; p_strength += mfleet.frigate_number * 3; p_strength += mfleet.capital_number * 8; - _roll_100 = roll_dice_chapter(1, 100, "low"); + var _roll_100 = roll_dice_chapter(1, 100, "low"); var _loc_star = find_star_by_name(obj_turn_end.battle_location[obj_turn_end.current_battle]); @@ -315,14 +304,13 @@ function player_retreat_from_fleet_combat() { en_strength += frig_total * 2; en_strength += escort_total; - ratio = 9999; + var ratio = 9999; if ((p_strength > 0) && (en_strength > 0)) { ratio = (en_strength / p_strength) * 100; } var esc_lost = 0, frig_lost = 0, cap_lost = 0, which = 0, sayd = 0; - i = -1; // var ship_lost,i; var ship_lost = []; if (scr_has_adv("Kings of Space")) { @@ -334,7 +322,7 @@ function player_retreat_from_fleet_combat() { if (_roll_100 != -5) { repeat (50) { - diceh = roll_dice_chapter(1, 100, "high"); + var diceh = roll_dice_chapter(1, 100, "high"); if (diceh <= ratio) { ratio -= 100; var onceh = 0; @@ -373,7 +361,6 @@ function player_retreat_from_fleet_combat() { if (!(mfleet.capital_number + mfleet.frigate_number + mfleet.escort_number)) { break; } - // show_message("Ship lost"); } } } @@ -409,6 +396,7 @@ function player_retreat_from_fleet_combat() { instance_destroy(); } + var text = "Your fleet is given the command to fall back. The vessels turn and prepare to enter the Warp, constantly under a hail of enemy fire. "; if ((esc_lost + frig_lost + cap_lost > 0) && (mfleet.escort_number + mfleet.frigate_number + mfleet.capital_number > 0)) { text = "Your fleet is given the command to fall back. The vesels turn and prepare to enter the Warp, constantly under a hail of enemy fire. Some of your ships remain behind to draw off the attack and give the rest of your fleet a chance to escape. "; @@ -432,7 +420,6 @@ function player_retreat_from_fleet_combat() { text += string(esc_lost) + " Escorts were destroyed. "; } } - var text = "Your fleet is given the command to fall back. The vessels turn and prepare to enter the Warp, constantly under a hail of enemy fire. "; if (esc_lost + frig_lost + cap_lost == 0) { text += "The entire fleet manages to escape with minimal damage."; } @@ -458,27 +445,26 @@ function player_retreat_from_fleet_combat() { } } -function fleet_full_ship_array(fleet = "none", exclude_capitals = false, exclude_frigates = false, exclude_escorts = false) { +function fleet_full_ship_array(fleet = noone, exclude_capitals = false, exclude_frigates = false, exclude_escorts = false) { var all_ships = []; - var i; var _ship_count = array_length(obj_ini.ship); - if (fleet == "none") { + if (fleet == noone) { if (!exclude_capitals) { - for (i = 0; i < array_length(capital_num); i++) { + for (var i = 0; i < array_length(capital_num); i++) { if (capital_num[i] < _ship_count) { array_push(all_ships, capital_num[i]); } } } if (!exclude_frigates) { - for (i = 0; i < array_length(frigate_num); i++) { + for (var i = 0; i < array_length(frigate_num); i++) { if (frigate_num[i] < _ship_count) { array_push(all_ships, frigate_num[i]); } } } if (!exclude_escorts) { - for (i = 0; i < array_length(escort_num); i++) { + for (var i = 0; i < array_length(escort_num); i++) { if (escort_num[i] < _ship_count) { array_push(all_ships, escort_num[i]); } @@ -494,17 +480,15 @@ function fleet_full_ship_array(fleet = "none", exclude_capitals = false, exclude function set_fleet_location(location) { var fleet_ships = fleet_full_ship_array(); - var temp; for (var i = 0; i < array_length(fleet_ships); i++) { - temp = fleet_ships[i]; + var temp = fleet_ships[i]; if (temp >= 0 && temp < array_length(obj_ini.ship_location)) { obj_ini.ship_location[temp] = location; } } - var unit; for (var co = 0; co <= obj_ini.companies; co++) { - for (i = 0; i < array_length(obj_ini.name[co]); i++) { - unit = fetch_unit([co, i]); + for (var i = 0; i < array_length(obj_ini.name[co]); i++) { + var unit = fetch_unit([co, i]); if (array_contains(fleet_ships, unit.ship_location)) { unit.location_string = location; } @@ -513,20 +497,22 @@ function set_fleet_location(location) { } function selected_ship_types() { - var capitals = 0, frigates = 0, escorts = 0, i; - for (i = 0; i < array_length(capital); i++) { + var capitals = false; + var frigates = false; + var escorts = false; + for (var i = 0; i < array_length(capital); i++) { if (capital[i] != "" && capital_sel[i]) { capitals = true; break; } } - for (i = 0; i < array_length(frigate); i++) { + for (var i = 0; i < array_length(frigate); i++) { if (frigate[i] != "" && frigate_sel[i]) { frigates = true; break; } } - for (i = 0; i < array_length(escort); i++) { + for (var i = 0; i < array_length(escort); i++) { if (escort[i] != "" && escort_sel[i]) { escorts = true; break; @@ -535,26 +521,26 @@ function selected_ship_types() { return [capitals, frigates, escorts]; } -function player_fleet_ship_count(fleet = "none") { +function player_fleet_ship_count(fleet = noone) { var ship_count = 0; - if (fleet == "none") { + if (fleet == noone) { capital_number = 0; frigate_number = 0; escort_number = 0; - for (i = 0; i < array_length(capital); i++) { + for (var i = 0; i < array_length(capital); i++) { if (capital[i] != "") { ship_count++; capital_number++; } } - for (i = 0; i < array_length(frigate); i++) { + for (var i = 0; i < array_length(frigate); i++) { if (frigate[i] != "") { ship_count++; frigate_number++; } } - for (i = 0; i < array_length(escort); i++) { + for (var i = 0; i < array_length(escort); i++) { if (escort[i] != "") { ship_count++; escort_number++; @@ -568,20 +554,20 @@ function player_fleet_ship_count(fleet = "none") { return ship_count; } -function player_fleet_selected_count(fleet = "none") { +function player_fleet_selected_count(fleet = noone) { var ship_count = 0; - if (fleet == "none") { - for (i = 0; i < array_length(capital); i++) { + if (fleet == noone) { + for (var i = 0; i < array_length(capital); i++) { if (capital[i] != "" && capital_sel[i]) { ship_count++; } } - for (i = 0; i < array_length(frigate); i++) { + for (var i = 0; i < array_length(frigate); i++) { if (frigate[i] != "" && frigate_sel[i]) { ship_count++; } } - for (i = 0; i < array_length(escort); i++) { + for (var i = 0; i < array_length(escort); i++) { if (escort[i] != "" && escort_sel[i]) { ship_count++; } @@ -595,7 +581,7 @@ function player_fleet_selected_count(fleet = "none") { } function get_nearest_player_fleet(nearest_x, nearest_y, is_static = false, is_moving = false, stop_complex_actions = true) { - var chosen_fleet = "none"; + var chosen_fleet = noone; if (instance_exists(obj_p_fleet)) { with (obj_p_fleet) { var viable = !(is_static && action != ""); @@ -613,7 +599,7 @@ function get_nearest_player_fleet(nearest_x, nearest_y, is_static = false, is_mo continue; } if (point_in_rectangle(x, y, 0, 0, room_width, room_height)) { - if (chosen_fleet == "none") { + if (chosen_fleet == noone) { chosen_fleet = self; } if (point_distance(nearest_x, nearest_y, x, y) < point_distance(nearest_x, nearest_y, chosen_fleet.x, chosen_fleet.y)) { diff --git a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml index 7b39c1e4b6..599c6576ac 100644 --- a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml +++ b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml @@ -9,7 +9,7 @@ function return_lost_ships_chance() { function return_lost_ship() { var _return_id = get_valid_player_ship("Lost"); if (_return_id != -1) { - var _lost_fleet = "none"; + var _lost_fleet = noone; with (obj_p_fleet) { if (action == "Lost") { _lost_fleet = id; @@ -19,7 +19,7 @@ function return_lost_ship() { var _star = instance_find(obj_star, irandom(instance_number(obj_star) - 1)); _new_fleet = instance_create(_star.x, _star.y, obj_p_fleet); _new_fleet.owner = eFACTION.PLAYER; - if (_lost_fleet != "none") { + if (_lost_fleet != noone) { find_and_move_ship_between_fleets(_lost_fleet, _new_fleet, _return_id); if (player_fleet_ship_count(_lost_fleet) == 0) { with (_lost_fleet) { @@ -92,7 +92,7 @@ function return_lost_ship() { //More scenarios needed but this is a good start } scr_popup("Ship Returns", _text, "lost_warp", ""); - if (_lost_fleet != "none") { + if (_lost_fleet != noone) { if (!player_fleet_ship_count(_lost_fleet)) { with (_lost_fleet) { instance_destroy(); @@ -190,14 +190,14 @@ function loose_ship_to_warp_event() { text += $" {marine_count} Battle Brothers were onboard."; } scr_event_log("red", text); - var _lost_ship_fleet = "none"; + var _lost_ship_fleet = noone; with (obj_p_fleet) { if (action == "Lost") { _lost_ship_fleet = id; } } - if (_lost_ship_fleet == "none") { - var _lost_ship_fleet = instance_create(-500, -500, obj_p_fleet); + if (_lost_ship_fleet == noone) { + _lost_ship_fleet = instance_create(-500, -500, obj_p_fleet); _lost_ship_fleet.owner = eFACTION.PLAYER; } @@ -238,7 +238,6 @@ function loose_ship_to_warp_event() { //TODO make method for setting ship weaponry function new_player_ship(type, start_loc = "home", new_name = "") { - var ship_names = "", index = 0; var index = new_player_ship_defaults(); for (var k = 0; k <= 200; k++) { diff --git a/scripts/scr_population_influence/scr_population_influence.gml b/scripts/scr_population_influence/scr_population_influence.gml index 0d92015a40..8df7598b6e 100644 --- a/scripts/scr_population_influence/scr_population_influence.gml +++ b/scripts/scr_population_influence/scr_population_influence.gml @@ -1,7 +1,5 @@ -// Script assets have changed for v2.3.0 see -// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information -function adjust_influence(faction, value, planet, star = "none") { - if (star == "none") { +function adjust_influence(faction, value, planet, star) { + with (star) { p_influence[planet][faction] += value; var total_influence = array_sum(p_influence[planet]); var loop = 0; @@ -27,10 +25,6 @@ function adjust_influence(faction, value, planet, star = "none") { } } } - } else { - with (star) { - adjust_influence(faction, value, planet); - } } } @@ -39,6 +33,6 @@ function merge_influences(doner_influence, planet) { if (i == 2) { continue; } - adjust_influence(i, (p_influence[planet][i] + doner_influence[i] / 2), planet); + adjust_influence(i, (p_influence[planet][i] + doner_influence[i] / 2), planet, self); } } diff --git a/scripts/scr_popup_functions/scr_popup_functions.gml b/scripts/scr_popup_functions/scr_popup_functions.gml index 1251954c72..6fa2266ffc 100644 --- a/scripts/scr_popup_functions/scr_popup_functions.gml +++ b/scripts/scr_popup_functions/scr_popup_functions.gml @@ -152,10 +152,9 @@ function replace_options(option, if_empty = false, use_default_option = true) { function evaluate_popup_option(opt) { var _allow = true; + var _requirements = {}; if (struct_exists(opt, "requires")) { - var _requirements = opt.requires; - } else { - return true; + _requirements = opt.requires; } if (struct_exists(_requirements, "req")) { @@ -202,7 +201,7 @@ function draw_popup_options() { _opt_string = _opt.str1; } - var _opt_string = $"{i + 1}. {_opt_string}"; + _opt_string = $"{i + 1}. {_opt_string}"; var _string_x = x1 + 25.5; var _string_y = y1 + 20 + sz; @@ -258,7 +257,7 @@ function draw_popup_options() { /// @self Asset.GMObject.obj_popup function calculate_equipment_needs() { - var i = 0, rall = "", all_good = 0; + var all_good = 0; req_armour = ""; req_armour_num = 0; @@ -276,11 +275,8 @@ function calculate_equipment_needs() { req_wep2_num = 0; have_wep2_num = 0; - rall = role_name[target_role]; + var rall = role_name[target_role]; - /*if (rall=obj_ini.role[100][14]) and (global.chapter_name!="Space Wolves") and (global.chapter_name!="Iron Hands"){ - req_armour="";req_armour_num=0;req_wep1="";req_wep1_num=0;req_wep2="";req_wep2_num=0;req_mobi="";req_mobi_num=0; - }*/ if (rall == "Codiciery") { req_armour = ""; req_armour_num = 0; @@ -380,19 +376,17 @@ function calculate_equipment_needs() { } } } - - // if (n_wep1=n_wep2) and ((o_wep1!=n_wep1) or (o_wep2!=n_wep2)){have_wep1_num-=1;have_wep2_num-=1;} } // End Repeat // This checks to see if there is any more in the armoury if (req_armour == STR_ANY_POWER_ARMOUR) { var _armour_list = global.list_basic_power_armour; - for (i = 0; i < array_length(_armour_list); i++) { + for (var i = 0; i < array_length(_armour_list); i++) { have_armour_num += scr_item_count(_armour_list[i]); } } else if (req_armour == STR_ANY_TERMINATOR_ARMOUR) { var _armour_list = global.list_terminator_armour; - for (i = 0; i < array_length(_armour_list); i++) { + for (var i = 0; i < array_length(_armour_list); i++) { have_armour_num += scr_item_count(_armour_list[i]); } } else if (req_armour == "Dreadnought") { @@ -584,7 +578,7 @@ function allow_governor_successor() { _text_last = "Regrettably he has a dim view of your chapter"; } if (randa >= 95) { - _newdisp = max(p_data.player_disposition, 60 + choose(1, 2, 3, 4, 5, 6) * 3); + var _newdisp = max(p_data.player_disposition, 60 + choose(1, 2, 3, 4, 5, 6) * 3); p_data.set_player_disposition(_newdisp); _text_last = "Fortunately you already have good relations with the new governor"; } diff --git a/scripts/scr_post_battle_events/scr_post_battle_events.gml b/scripts/scr_post_battle_events/scr_post_battle_events.gml index be55ab8b40..0ca3342f3d 100644 --- a/scripts/scr_post_battle_events/scr_post_battle_events.gml +++ b/scripts/scr_post_battle_events/scr_post_battle_events.gml @@ -30,7 +30,7 @@ function necron_tomb_raid_post_battle_sequence() { } var _star_obj = find_star_by_name(battle_loc); - if (_star_obj != "none") { + if (_star_obj != noone) { with (_star_obj) { var planet = obj_ncombat.battle_id; if (remove_planet_problem(planet, "necron")) { diff --git a/scripts/scr_powers/scr_powers.gml b/scripts/scr_powers/scr_powers.gml index cf72d96661..65268acada 100644 --- a/scripts/scr_powers/scr_powers.gml +++ b/scripts/scr_powers/scr_powers.gml @@ -5,7 +5,7 @@ global.psy_disciplines_starting = [ "biomancy", "pyromancy", "telekinesis", - "rune_magic" + "rune_magic", ]; #macro PSY_PERILS_CHANCE_MIN 1 @@ -383,13 +383,14 @@ function flush_psychic_summary(_psy_log) { function get_discipline_data(_discipline_name, _data_name) { // Check if the power exists in the global.disciplines_data if (struct_exists(global.disciplines_data, _discipline_name)) { + var _data_content = {}; var _discipline_object = global.disciplines_data[$ _discipline_name]; // Check if the data exists for that power if (struct_exists(_discipline_object, _data_name)) { - var _data_content = _discipline_object[$ _data_name]; + _data_content = _discipline_object[$ _data_name]; } else { _discipline_object = global.disciplines_data[$ "example"]; - var _data_content = _discipline_object[$ _data_name]; + _data_content = _discipline_object[$ _data_name]; } return _data_content; } else { @@ -405,16 +406,17 @@ function get_discipline_data(_discipline_name, _data_name) { function get_power_data(_power_id, _data_name = "") { // Check if the power exists in the global.powers_data if (struct_exists(global.powers_data, _power_id)) { + var _data_content = {}; var _power_object = global.powers_data[$ _power_id]; // Check if the data exists for that power if (_data_name == "") { return _power_object; } else if (struct_exists(_power_object, _data_name)) { - var _data_content = _power_object[$ _data_name]; + _data_content = _power_object[$ _data_name]; } else { _power_object = global.powers_data[$ "example"]; - var _data_content = _power_object[$ _data_name]; + _data_content = _power_object[$ _data_name]; } if (_data_name == "flavour_text") { diff --git a/scripts/scr_promote/scr_promote.gml b/scripts/scr_promote/scr_promote.gml index 7f1282b74c..fe90a8191e 100644 --- a/scripts/scr_promote/scr_promote.gml +++ b/scripts/scr_promote/scr_promote.gml @@ -25,13 +25,13 @@ function setup_promotion_popup() { units = nuuum; promote_button = new UnitButtonObject({x1: 1450, y1: 491, style: "pixel", label: "Promote"}); promote_button.bind_method = function() { - var mahreens = 0, i = -1; + var mahreens = 0; if (target_comp > 10) { target_comp = 0; } - for (i = 0; i < 498; i++) { + for (var i = 0; i < 498; i++) { if (obj_ini.name[target_comp][i] == "" && obj_ini.name[target_comp][i + 1] == "") { mahreens = i; break; @@ -47,7 +47,7 @@ function setup_promotion_popup() { variable_struct_set(role_squad_equivilances, obj_ini.role[100][3], "veteran_squad"); variable_struct_set(role_squad_equivilances, obj_ini.role[100][4], "terminator_squad"); - for (i = 0; i < array_length(obj_controller.display_unit) && mahreens < 500; i++) { + for (var i = 0; i < array_length(obj_controller.display_unit) && mahreens < 500; i++) { if ((obj_controller.man[i] == "man") && (obj_controller.man_sel[i] == 1) && (obj_controller.ma_exp[i] >= min_exp)) { moveable = true; unit = obj_controller.display_unit[i]; @@ -78,8 +78,8 @@ function setup_promotion_popup() { } //move squad if (moveable) { - var mem_unit; - for (var mem = 0; mem < array_length(move_members); mem++) { + var mem; + for (mem = 0; mem < array_length(move_members); mem++) { var mem_unit = fetch_unit(move_members[mem]); if (mem_unit.company != target_comp) { scr_move_unit_info(mem_unit.company, target_comp, mem_unit.marine_number, mahreens, false); @@ -210,7 +210,6 @@ function draw_popup_promotion() { target_role = 0; get_unit_promotion_options(); } - // } draw_set_halign(fa_left); draw_text(1020, 290, "Target Role:"); //choose new role var role_x = 0; diff --git a/scripts/scr_purge_world/scr_purge_world.gml b/scripts/scr_purge_world/scr_purge_world.gml index 12ee94c3d8..3278143439 100644 --- a/scripts/scr_purge_world/scr_purge_world.gml +++ b/scripts/scr_purge_world/scr_purge_world.gml @@ -1,259 +1,242 @@ +function PlayerPurge(action_type, action_score, planet_data) constructor { + pop_before = 0; + max_kill = 0; + pop_after = 0; + overkill = 0; + self.planet_data = planet_data; + self.action_type = action_type; + self.action_score = action_score; + population_reduction_percentage = 0; + + heres_after = 0; + heres_before = 0; + + static calculate_max_kills = function() { + switch (action_type) { + case eDROP_TYPE.PURGEBOMBARD: + max_kill = 15000000 * action_score; + if (pop_before > 0) { + overkill = max(pop_before * 0.1, ((heres_before / 200) * pop_before)); + } + break; + case eDROP_TYPE.PURGEFIRE: + max_kill = 12000 * action_score; + if (pop_before > 0) { + overkill = max(pop_before * 0.1, ((heres_before / 200) * pop_before)); + } + break; + case eDROP_TYPE.PURGESELECTIVE: + max_kill = action_score * 30; + break; + } + kill = min(max_kill, pop_before); + + if (overkill > 0) { + kill = min(kill, overkill); + } + }; + + calculate_influence_reduction = function() { + switch (action_type) { + case eDROP_TYPE.PURGEBOMBARD: + if (population_reduction_percentage > 0) { + influence_reduction = min((population_reduction_percentage * 2), action_score * 2); // How much hurresy to get rid of + } + break; + case eDROP_TYPE.PURGEFIRE: + influence_reduction = min((population_reduction_percentage * 2), round(action_score / 25)); + break; + case eDROP_TYPE.PURGESELECTIVE: + influence_reduction = round(action_score / 50); + break; + } + influence_reduction = min(influence_reduction, heres_before); + }; + + static calculate_deaths = function() { + calculate_max_kills(); + + pop_after = pop_before - kill; + + population_reduction_percentage = (pop_after / pop_before) * 100; // Relative % of people murderized -function PlayerPurge(action_type, action_score, planet_data) constructor{ - pop_before = 0; - max_kill = 0; - pop_after = 0; - overkill = 0; - self.planet_data = planet_data; - self.action_type = action_type; - self.action_score = action_score; - population_reduction_percentage = 0; - - heres_after = 0; - heres_before = 0; - - - static calculate_max_kills = function(){ - switch (action_type){ - case eDROP_TYPE.PURGEBOMBARD: - max_kill = 15000000 * action_score; - if (pop_before > 0){ - overkill = max(pop_before * 0.1, ((heres_before / 200) * pop_before)); - } - break; - case eDROP_TYPE.PURGEFIRE: - max_kill = 12000 * action_score; - if (pop_before > 0){ - overkill = max(pop_before * 0.1, ((heres_before / 200) * pop_before)); - } - break; - case eDROP_TYPE.PURGESELECTIVE: - max_kill=action_score * 30; - break; - } - kill=min(max_kill, pop_before); - - if (overkill > 0){ - kill=min(kill, overkill); - } - } - - calculate_influence_reduction = function(){ - switch (action_type){ - case eDROP_TYPE.PURGEBOMBARD: - if (population_reduction_percentage>0){ - influence_reduction=min((population_reduction_percentage*2), action_score*2);// How much hurresy to get rid of - } - break; - case eDROP_TYPE.PURGEFIRE: - influence_reduction = min((population_reduction_percentage * 2), round(action_score / 25)); - break; - case eDROP_TYPE.PURGESELECTIVE: - influence_reduction = round(action_score / 50); - break; - } - influence_reduction = min(influence_reduction, heres_before); - } - - static calculate_deaths = function(){ - - - calculate_max_kills(); - - pop_after = (pop_before - kill); - - population_reduction_percentage = (pop_after/pop_before)*100;// Relative % of people murderized - - - calculate_influence_reduction(); - - heres_after = max(heres_before - influence_reduction, 0); - } - - static population_death_string = function(){ - var _death_string = "\n\nThe planet had a population of " - if (!planet_data.large_population){ - _death_string += $"{scr_display_number(floor(pop_before))} and {scr_display_number(floor(kill))}"; + calculate_influence_reduction(); + + heres_after = max(heres_before - influence_reduction, 0); + }; + + static population_death_string = function() { + var _death_string = "\n\nThe planet had a population of "; + if (!planet_data.large_population) { + _death_string += $"{scr_display_number(floor(pop_before))} and {scr_display_number(floor(kill))}"; } else { - _death_string += $"{pop_before / LARGE_PLANET_MOD} billion and {scr_display_number(kill)}"; + _death_string += $"{pop_before / LARGE_PLANET_MOD} billion and {scr_display_number(kill)}"; } - switch (action_type){ - case eDROP_TYPE.PURGEBOMBARD: - _death_string += "were purged over the duration of the bombardment."; - break; - case eDROP_TYPE.PURGEFIRE: - _death_string += " over the duration of the cleansing." - break; - case eDROP_TYPE.PURGESELECTIVE: - _death_string += " over the duration of the search."; - break; - } + switch (action_type) { + case eDROP_TYPE.PURGEBOMBARD: + _death_string += "were purged over the duration of the bombardment."; + break; + case eDROP_TYPE.PURGEFIRE: + _death_string += " over the duration of the cleansing."; + break; + case eDROP_TYPE.PURGESELECTIVE: + _death_string += " over the duration of the search."; + break; + } _death_string += " were purged"; - switch(heres_target){ - case "corruption": - _death_string += $"\n\nHeresy has fallen to {heres_after}%."; - break; - case "tau": - _death_string += $"\n\Tau influence is now effecting {heres_after}% of the population."; - break; - case "genestealers": - _death_string += $"\n\Genestealer influence is now effecting {heres_after}% of the population."; - break; - } + switch (heres_target) { + case "corruption": + _death_string += $"\n\nHeresy has fallen to {heres_after}%."; + break; + case "tau": + _death_string += $"\n\Tau influence is now effecting {heres_after}% of the population."; + break; + case "genestealers": + _death_string += $"\n\Genestealer influence is now effecting {heres_after}% of the population."; + break; + } return _death_string; - } - - static bombard_repercussions = function(){ - var _type = planet_data.planet_type; - - if (pop_after <=0 ){ - if (planet_data.current_owner == eFACTION.IMPERIUM && planet_data.owner_status() != "War"){ - if (_type == "Temperate" || _type == "Hive" || _type == "Desert"){ - var _disp_hit = -10; - if (_type = "Temperate"){ - _disp_hit = -5; - } - if (_type="Desert"){ - _disp_hit = -3; - } - scr_audience(eFACTION.IMPERIUM, "bombard_angry", _disp_hit, "", 0, 0); - } - } - } - if (planet_data.current_owner == eFACTION.MECHANICUS && planet_data.owner_status() != "War"){ - - if (_type="Forge"){ - _disp_hit =-15; - } - if (_type="Ice"){ - _disp_hit =-7; - } - scr_audience(eFACTION.INQUISITION, "bombard_angry", _disp_hit, "", 0, 0); - - } - } + }; + + static bombard_repercussions = function() { + var _type = planet_data.planet_type; + + if (pop_after <= 0) { + if (planet_data.current_owner == eFACTION.IMPERIUM && planet_data.owner_status() != "War") { + if (_type == "Temperate" || _type == "Hive" || _type == "Desert") { + var _disp_hit = -10; + if (_type == "Temperate") { + _disp_hit = -5; + } + if (_type == "Desert") { + _disp_hit = -3; + } + scr_audience(eFACTION.IMPERIUM, "bombard_angry", _disp_hit, "", 0, 0); + } + } + } + if (planet_data.current_owner == eFACTION.MECHANICUS && planet_data.owner_status() != "War") { + var _disp_hit = 0; + if (_type == "Forge") { + _disp_hit = -15; + } + if (_type == "Ice") { + _disp_hit = -7; + } + scr_audience(eFACTION.INQUISITION, "bombard_angry", _disp_hit, "", 0, 0); + } + }; } function scr_purge_world(action_type, action_score) { + var _purge = new PlayerPurge(action_type, action_score, self); - var _purge = new PlayerPurge(action_type, action_score, self); - - var _isquest=0,_thequest="",_questnum=0; - - - _purge.pop_before = population_as_small(); - - _purge.heres_before = max(total_corruption(), population_influences[eFACTION.TAU],population_influences[eFACTION.TYRANIDS]);// Starting heresy - - - if (action_type != eDROP_TYPE.PURGEASSASSINATE){ - _purge.calculate_deaths(); - } - var _heres_target = "corruption"; - - if (max(population_influences[eFACTION.TAU],population_influences[eFACTION.TYRANIDS]) > total_corruption()){ - if (population_influences[eFACTION.TAU] > population_influences[eFACTION.TYRANIDS]){ - _heres_target = "tau"; - } else{ - _heres_target = "genestealers"; - } - - } - - _purge.heres_target = _heres_target; - - - var _no_chaos = (planet_forces[eFACTION.HERETICS] + planet_forces[eFACTION.CHAOS]) == 0; - if ((action_type==eDROP_TYPE.PURGEFIRE || action_type==eDROP_TYPE.PURGESELECTIVE) && _no_chaos && obj_controller.turn>=obj_controller.chaos_turn){ - if (has_feature(eP_FEATURES.WARLORD10) && obj_controller.known[10]=0 && obj_controller.faction_gender[10]=1){ - with(obj_drop_select){ - var pop=instance_create(0,0,obj_popup); - pop.image="chaos_symbol"; - pop.title="Concealed Heresy"; - pop.text=$"Your astartes set out and begin to cleanse {name()} of possible heresy. The general populace appears to be devout in their faith, but a disturbing trend appears- the odd citizen cursing your forces, frothing at the mouth, and screaming out heresy most foul. One week into the cleansing a large hostile force is detected approaching and encircling your forces."; - exit; - } - } - if (has_feature(eP_FEATURES.WARLORD10) && obj_controller.known[10]>=2 && obj_controller.faction_gender[10]=1){ - with(obj_drop_select){ - - attacking=10; - obj_controller.cooldown=30; - combating=1;// Start battle here - - instance_deactivate_all(true); - instance_activate_object(obj_controller); - instance_activate_object(obj_ini); - instance_activate_object(obj_drop_select); - - instance_create(0,0,obj_ncombat); - obj_ncombat.battle_object=p_target; - obj_ncombat.battle_loc=p_target.name; - obj_ncombat.battle_id=obj_controller.selecting_planet; - obj_ncombat.dropping=0; - obj_ncombat.attacking=10; - obj_ncombat.enemy=10; - obj_ncombat.formation_set=1; - - obj_ncombat.leader=1; - obj_ncombat.threat=5; - obj_ncombat.battle_special="WL10_later"; - scr_battle_allies(); - setup_battle_formations(); - roster.add_to_battle(); - } - } - } - - - // TODO - while I don't expect Surface to Orbit weapons retaliating against player's purge bombardment, it might still be worthwhile to consider possible situations - - if (action_type=eDROP_TYPE.PURGEBOMBARD){// Bombardment - var _ship = string_plural("ship", obj_drop_select.ships_selected); - _popup_text=choose($"Your cruiser and larger {_ship}", $"The heavens rumble and thunder as your {_ship}"); - _popup_text+=choose(" position themselves over the target in close orbit, and unleash", " unload"); - var _adjective = choose("tearing ground", "hammering", "battering", "thundering"); - _popup_text+= $" annihilation upon {name()}. Even from space the explosions can be seen, {_adjective} across the planet's surface."; - - _purge.bombard_repercussions(); - } - - - if (action_type=eDROP_TYPE.PURGEFIRE){// Burn baby burn - var i=0; - if (has_problem("cleanse")){ - _isquest = true; - _thequest="cleanse"; - _questnum=i; - } - - if (_isquest){ - if (_thequest="cleanse" && action_score>=20){ - remove_problem(_thequest); - - alter_disposition(eFACTION.INQUISITION,obj_controller.demanding ? choose(0,0,1) :1); - - _popup_text="Your marines scour the underhive of {name()}, spraying mutants down with promethium as they go. It takes several days but a sizeable dent is put in their numbers."; - scr_event_log("","Inquisition Mission Completed: The mutants of {name()} have been cleansed by promethium."); - add_disposition(choose(1,2,3)); - } - }else { // TODO add more variation, with planets, features, marine equipment perhaps? - _popup_text=choose( - $"Timing their visits right, Your forces scour {name()} burning down whatever the local heretic communities call their homes. Their screams were quickly extinguished by fire, turning whatever it was before, into ash.", - $"Your forces scour {name()}, burning homes and towns that reek of heresy. The screams and wails of the damned carry through the air." - ); - - - var nid_influence = population_influences[eFACTION.TYRANIDS]; + var _isquest = 0, _thequest = "", _questnum = 0; + + _purge.pop_before = population_as_small(); + + _purge.heres_before = max(total_corruption(), population_influences[eFACTION.TAU], population_influences[eFACTION.TYRANIDS]); // Starting heresy + + if (action_type != eDROP_TYPE.PURGEASSASSINATE) { + _purge.calculate_deaths(); + } + var _heres_target = "corruption"; + + if (max(population_influences[eFACTION.TAU], population_influences[eFACTION.TYRANIDS]) > total_corruption()) { + if (population_influences[eFACTION.TAU] > population_influences[eFACTION.TYRANIDS]) { + _heres_target = "tau"; + } else { + _heres_target = "genestealers"; + } + } + + _purge.heres_target = _heres_target; + + var _no_chaos = (planet_forces[eFACTION.HERETICS] + planet_forces[eFACTION.CHAOS]) == 0; + if ((action_type == eDROP_TYPE.PURGEFIRE || action_type == eDROP_TYPE.PURGESELECTIVE) && _no_chaos && obj_controller.turn >= obj_controller.chaos_turn) { + if (has_feature(eP_FEATURES.WARLORD10) && obj_controller.known[10] == 0 && obj_controller.faction_gender[10] == 1) { + with (obj_drop_select) { + var pop = instance_create(0, 0, obj_popup); + pop.image = "chaos_symbol"; + pop.title = "Concealed Heresy"; + pop.text = $"Your astartes set out and begin to cleanse {name()} of possible heresy. The general populace appears to be devout in their faith, but a disturbing trend appears- the odd citizen cursing your forces, frothing at the mouth, and screaming out heresy most foul. One week into the cleansing a large hostile force is detected approaching and encircling your forces."; + exit; + } + } + if (has_feature(eP_FEATURES.WARLORD10) && obj_controller.known[10] >= 2 && obj_controller.faction_gender[10] == 1) { + with (obj_drop_select) { + attacking = 10; + obj_controller.cooldown = 30; + combating = 1; // Start battle here + + instance_deactivate_all(true); + instance_activate_object(obj_controller); + instance_activate_object(obj_ini); + instance_activate_object(obj_drop_select); + + instance_create(0, 0, obj_ncombat); + obj_ncombat.battle_object = p_target; + obj_ncombat.battle_loc = p_target.name; + obj_ncombat.battle_id = obj_controller.selecting_planet; + obj_ncombat.dropping = 0; + obj_ncombat.attacking = 10; + obj_ncombat.enemy = 10; + obj_ncombat.formation_set = 1; + + obj_ncombat.leader = 1; + obj_ncombat.threat = 5; + obj_ncombat.battle_special = "WL10_later"; + scr_battle_allies(); + setup_battle_formations(); + roster.add_to_battle(); + } + } + } + + // TODO - while I don't expect Surface to Orbit weapons retaliating against player's purge bombardment, it might still be worthwhile to consider possible situations + + if (action_type == eDROP_TYPE.PURGEBOMBARD) { + // Bombardment + var _ship = string_plural("ship", obj_drop_select.ships_selected); + _popup_text = choose($"Your cruiser and larger {_ship}", $"The heavens rumble and thunder as your {_ship}"); + _popup_text += choose(" position themselves over the target in close orbit, and unleash", " unload"); + var _adjective = choose("tearing ground", "hammering", "battering", "thundering"); + _popup_text += $" annihilation upon {name()}. Even from space the explosions can be seen, {_adjective} across the planet's surface."; + + _purge.bombard_repercussions(); + } + + if (action_type == eDROP_TYPE.PURGEFIRE) { + // Burn baby burn + var i = 0; + if (has_problem("cleanse")) { + _isquest = true; + _thequest = "cleanse"; + _questnum = i; + } + + if (_isquest) { + if (_thequest == "cleanse" && action_score >= 20) { + remove_problem(_thequest); + + alter_disposition(eFACTION.INQUISITION, obj_controller.demanding ? choose(0, 0, 1) : 1); + + _popup_text = "Your marines scour the underhive of {name()}, spraying mutants down with promethium as they go. It takes several days but a sizeable dent is put in their numbers."; + scr_event_log("", "Inquisition Mission Completed: The mutants of {name()} have been cleansed by promethium."); + add_disposition(choose(1, 2, 3)); + } + } else { + // TODO add more variation, with planets, features, marine equipment perhaps? + _popup_text = choose($"Timing their visits right, Your forces scour {name()} burning down whatever the local heretic communities call their homes. Their screams were quickly extinguished by fire, turning whatever it was before, into ash.", $"Your forces scour {name()}, burning homes and towns that reek of heresy. The screams and wails of the damned carry through the air."); + + var nid_influence = population_influences[eFACTION.TYRANIDS]; if (has_feature(eP_FEATURES.GENE_STEALER_CULT)) { var cult = get_features(eP_FEATURES.GENE_STEALER_CULT)[0]; - if (cult.hiding) { - - } + if (cult.hiding) {} } else { if (nid_influence > 25) { _popup_text += " Scores of mutant offspring from a genestealer infestation are burnt, while we have damaged their influence over this world, the mutants appear to lack the organisation of a true cult"; @@ -263,86 +246,75 @@ function scr_purge_world(action_type, action_score) { } } - _popup_text += _purge.population_death_string(); - - } - } - - - if (action_type=eDROP_TYPE.PURGESELECTIVE){// Blam! - var i=0; - if (has_problem("purge")){ - _isquest=1; - _thequest="purge"; - _questnum=i; - } - - if (_isquest=1){ - if (_thequest="purge" && action_score>=10){ - remove_problem("purge"); - - alter_disposition(eFACTION.INQUISITION,obj_controller.demanding ? choose(0,0,1) :1); - - _popup_text="Your marines drop fast and hard, blowing through guards and mercenaries with minimal resistance. Before ten minutes have passed all your targets are executed."; - scr_event_log("","Inquisition Mission Completed: The unruly Nobles of {name()} have been purged."); - add_disposition(choose(1,2,3)); - } - } - else if (_isquest=0){ // TODO add more variation, with planets, features, possibly marine equipment - _popup_text = $"Your marines move across {name()}," - _popup_text += choose( - $"searching for high profile targets. Once found, they are dragged outside from their lairs. Their execution would soon follow.", - $"rooting out sources of corruption. Heretics are dragged from their lairs and executed in the streets." - ); - - _popup_text += _purge.population_death_string(); - } - } - - - - if (action_type == eDROP_TYPE.PURGEASSASSINATE){ - assasinate_governor_setup(action_score); - } - - else if (action_type!=eDROP_TYPE.PURGEASSASSINATE){ - if (_isquest=0){// DO EET - var _txt2=_popup_text; - switch(_purge.heres_target){ - case "corruption": - alter_corruption(-_purge.influence_reduction); - break; - case "tau": - alter_influence(eFACTION.TAU , -_purge.influence_reduction); - break; - case "genestealers": - alter_influence(eFACTION.TYRANIDS , -_purge.influence_reduction); - break; - } - - set_population(population_large_conversion(_purge.pop_after)); - - var pip=instance_create(0,0,obj_popup); - pip.title="Purge Results"; - pip.text=_txt2; - } - if (_isquest){// DO EET - var pip=instance_create(0,0,obj_popup); - scr_popup("Inquisition Mission Completed", _popup_text, "inquisition") - // scr_event_log("","Inquisition Mission Completed: The unruly nobles of {name()} have been silenced."); - } - } - - - if instance_exists(obj_drop_select){ - with(obj_drop_select){ - if (instance_exists(sh_target)){ - sh_target.acted=5; - } - instance_destroy(); - } - } + _popup_text += _purge.population_death_string(); + } + } + + if (action_type == eDROP_TYPE.PURGESELECTIVE) { + // Blam! + var i = 0; + if (has_problem("purge")) { + _isquest = 1; + _thequest = "purge"; + _questnum = i; + } + if (_isquest == 1) { + if (_thequest == "purge" && action_score >= 10) { + remove_problem("purge"); -} + alter_disposition(eFACTION.INQUISITION, obj_controller.demanding ? choose(0, 0, 1) : 1); + + _popup_text = "Your marines drop fast and hard, blowing through guards and mercenaries with minimal resistance. Before ten minutes have passed all your targets are executed."; + scr_event_log("", "Inquisition Mission Completed: The unruly Nobles of {name()} have been purged."); + add_disposition(choose(1, 2, 3)); + } + } else if (_isquest == 0) { + // TODO add more variation, with planets, features, possibly marine equipment + _popup_text = $"Your marines move across {name()},"; + _popup_text += choose($"searching for high profile targets. Once found, they are dragged outside from their lairs. Their execution would soon follow.", $"rooting out sources of corruption. Heretics are dragged from their lairs and executed in the streets."); + + _popup_text += _purge.population_death_string(); + } + } + + if (action_type == eDROP_TYPE.PURGEASSASSINATE) { + assasinate_governor_setup(action_score); + } else if (action_type != eDROP_TYPE.PURGEASSASSINATE) { + if (_isquest == 0) { + // DO EET + var _txt2 = _popup_text; + switch (_purge.heres_target) { + case "corruption": + alter_corruption(-_purge.influence_reduction); + break; + case "tau": + alter_influence(eFACTION.TAU, -_purge.influence_reduction); + break; + case "genestealers": + alter_influence(eFACTION.TYRANIDS, -_purge.influence_reduction); + break; + } + + set_population(population_large_conversion(_purge.pop_after)); + var pip = instance_create(0, 0, obj_popup); + pip.title = "Purge Results"; + pip.text = _txt2; + } + if (_isquest) { + // DO EET + var pip = instance_create(0, 0, obj_popup); + scr_popup("Inquisition Mission Completed", _popup_text, "inquisition"); + } + } + + if (instance_exists(obj_drop_select)) { + with (obj_drop_select) { + if (instance_exists(sh_target)) { + sh_target.acted = 5; + } + instance_destroy(); + } + } +} diff --git a/scripts/scr_quest/scr_quest.gml b/scripts/scr_quest/scr_quest.gml index 4bcb4480da..bf61508cec 100644 --- a/scripts/scr_quest/scr_quest.gml +++ b/scripts/scr_quest/scr_quest.gml @@ -1,121 +1,109 @@ -function scr_quest(quest_satus = 0, quest_name, quest_fac, quest_end) { +function scr_quest(quest_satus, quest_name, quest_fac, quest_end) { // quest_satus: 0/1/2/3/4 create/fail/accomplish/clear/check // quest_name: quest name // quest_fac: faction // quest_end: duration before end - var quick_trade; - quick_trade = 0; + var quick_trade = 0; + var max_quests = 30; if (quest_satus == 0) { // Create - var first_quest, i; - first_quest = 0; - i = 0; - - repeat (30) { - if (first_quest == 0) { - i += 1; - if (obj_controller.quest[i] == "") { - first_quest = i; - } + var _first_empty_quest_slot = -1; + + for (var i = 1; i <= max_quests; i++) { + if (obj_controller.quest[i] == "") { + _first_empty_quest_slot = i; + break; } } - obj_controller.quest[i] = quest_name; - obj_controller.quest_faction[i] = quest_fac; - obj_controller.quest_end[i] = obj_controller.turn + quest_end; + if (_first_empty_quest_slot != -1) { + obj_controller.quest[_first_empty_quest_slot] = quest_name; + obj_controller.quest_faction[_first_empty_quest_slot] = quest_fac; + obj_controller.quest_end[_first_empty_quest_slot] = obj_controller.turn + quest_end; + } else { + LOGGER.error($"Warning: Quest log is full. Could not add: {quest_name}"); + } + } else if (quest_satus > 0) { - // 1 = Fail, 2 = Accomplish, 3 = Clear - var que = 0; + // 1 = Fail, 2 = Accomplish, 3 = Clear, 4 = Check + var que = -1; - for (var i = 1; i <= 10; i += 1) { - if (que == 0 && obj_controller.quest[i] == quest_name) { + for (var i = 1; i <= max_quests; i++) { + if (obj_controller.quest[i] == quest_name) { que = i; break; } } - if ((quest_name == "fund_elder") && (quest_satus == 1)) { + if (que != -1 || quest_satus == 4) { + if ((quest_name == "fund_elder") && (quest_satus == 1)) { // obj_controller.disposition[6]-=2;// Player going 'maybe' and then waiting out the quest duration - scr_audience(6, "mission1_failed", -2, "", 0, 0); - scr_event_log("red", "Eldar Mission Failed: Several years have passed since offering to assist the Eldar with resources."); - } else if ((quest_name == "artifact_return") && (quest_satus == 1)) { + scr_audience(6, "mission1_failed", -2, "", 0, 0); + scr_event_log("red", "Eldar Mission Failed: Several years have passed since offering to assist the Eldar with resources."); + } else if ((quest_name == "artifact_return") && (quest_satus == 1)) { // Inq are now pissed - obj_controller.alarm[8] = 1; - } else if ((quest_name == "artifact_loan") && (quest_satus == 1)) { + obj_controller.alarm[8] = 1; + } else if ((quest_name == "artifact_loan") && (quest_satus == 1)) { // Inq want the artifact back - var wanted_arti = -1; - for (var i = 0; i < array_length(obj_ini.artifact); i++) { - if (obj_ini.artifact[i] != "") { - if (obj_ini.artifact_struct[i].has_tag("inq")) { - wanted_arti = i; - break; + var wanted_arti = -1; + for (var i = 0; i < array_length(obj_ini.artifact); i++) { + if (obj_ini.artifact[i] != "") { + if (obj_ini.artifact_struct[i].has_tag("inq")) { + wanted_arti = i; + break; + } } } - } - var failed = false; - if (wanted_arti < 0) { - failed = true; - } else { - var arti = obj_ini.artifact_struct[wanted_arti]; - if (arti.equipped() && is_array(arti.bearer)) { + var failed = false; + if (wanted_arti < 0) { failed = true; + } else { + var arti = obj_ini.artifact_struct[wanted_arti]; + if (arti.equipped() && is_array(arti.bearer)) { + failed = true; + } } - } - if (failed) { - scr_popup("Inquisition Artifact", "The Inquisition has asked for the return of the Artifact left in your care. Despite your Marine's best efforts they were unable to waylay the Inquisition, who are now furious. They demand the Artifact's immediate return.", "inquisition", ""); - scr_event_log("red", "Inquisition Mission: The Inquisition Artifact entrusted to your Chapter is not retrievable."); - disposition[4] -= 10; - obj_controller.qsfx = 1; - } else { - var _result_text = ""; - delete_artifact(wanted_arti); - i = wanted_arti; - if (obj_controller.demanding == 0) { - obj_controller.disposition[4] += 1; - obj_controller.inspection_passes++; - _result_text = "(Disposition : 1\nInspection Passes : +1(yieldable in diplommacy))"; - } - if (obj_controller.demanding == 1) { - obj_controller.disposition[4] += choose(0, 0, 1); + if (failed) { + scr_popup("Inquisition Artifact", "The Inquisition has asked for the return of the Artifact left in your care. Despite your Marine's best efforts they were unable to waylay the Inquisition, who are now furious. They demand the Artifact's immediate return.", "inquisition", ""); + scr_event_log("red", "Inquisition Mission: The Inquisition Artifact entrusted to your Chapter is not retrievable."); + obj_controller.disposition[4] -= 10; // Explicitly use obj_controller scope + obj_controller.qsfx = 1; + } else { + var _result_text = ""; + delete_artifact(wanted_arti); + if (obj_controller.demanding == 0) { + obj_controller.disposition[4] += 1; + obj_controller.inspection_passes++; + _result_text = "(Disposition : +1\nInspection Passes : +1(yieldable in diplomacy))"; + } + if (obj_controller.demanding == 1) { + obj_controller.disposition[4] += choose(0, 0, 1); + } + scr_popup("Inquisition Mission Completed", "The Inquisition has asked for the return of the Artifact, and your Chapter was able to hand it over without complications. The mission has been accomplished." + _result_text, "inquisition", ""); + scr_event_log("", "Inquisition Mission Completed: The entrusted Artifact has been returned to the Inquisition."); } - scr_popup("Inquisition Mission Completed", "The Inquisition has asked for the return of the Artifact, and your Chapter was able to hand it over without complications. The mission has been accomplished." + _result_text, "inquisition", ""); - scr_event_log("", "Inquisition Mission Completed: The entrusted Artifact has been returned to the Inquisition."); } - } - if ((quest_name == "fund_elder") && (quest_satus == 2)) { - if (trading == 0) { - quick_trade = 6; + if ((quest_name == "fund_elder") && (quest_satus == 2)) { + if (obj_controller.trading == 0) { + quick_trade = 6; + } + obj_controller.known[eFACTION.ELDAR] += 1; + obj_controller.disposition[6] += 10; } - obj_controller.known[eFACTION.ELDAR] += 1; - obj_controller.disposition[6] += 10; - } - if (quest_satus == 4) { - var first_quest, i; - first_quest = 0; - i = 0; - - repeat (30) { - if (first_quest == 0) { - i += 1; - if (obj_controller.quest[i] == quest_name) { - first_quest = i; - } - } + if (quest_satus == 4) { + return que; } - if (first_quest != 0) { - return first_quest; + if (que != -1) { + obj_controller.quest[que] = ""; + obj_controller.quest_faction[que] = 0; + obj_controller.quest_end[que] = 0; } - exit; } - - obj_controller.quest[que] = ""; - obj_controller.quest_faction[que] = 0; - obj_controller.quest_end[que] = 0; } if (quick_trade != 0) { @@ -145,9 +133,7 @@ function scr_quest(quest_satus = 0, quest_name, quest_fac, quest_end) { } } - var targ, flit, goods, i, chasing; - goods = ""; - chasing = 0; // Set target + var targ = noone; if (instance_exists(obj_temp2)) { targ = instance_nearest(obj_temp2.x, obj_temp2.y, obj_temp3); } @@ -157,7 +143,6 @@ function scr_quest(quest_satus = 0, quest_name, quest_fac, quest_end) { // If player fleet is flying about then get their target for new target if ((!instance_exists(obj_temp2)) && (!instance_exists(obj_ground_mission)) && instance_exists(obj_p_fleet)) { - chasing = 1; with (obj_p_fleet) { var pop; if ((capital_number > 0) && (action != "")) { @@ -177,7 +162,7 @@ function scr_quest(quest_satus = 0, quest_name, quest_fac, quest_end) { targ = instance_nearest(obj_ground_mission.x, obj_ground_mission.y, obj_temp3); } - flit = instance_create(targ.x, targ.y, obj_en_fleet); + var flit = instance_create(targ.x, targ.y, obj_en_fleet); flit.owner = quick_trade; if (quick_trade == 2) { diff --git a/scripts/scr_random_event/scr_random_event.gml b/scripts/scr_random_event/scr_random_event.gml index 2abdde5f2e..608d7f7a5b 100644 --- a/scripts/scr_random_event/scr_random_event.gml +++ b/scripts/scr_random_event/scr_random_event.gml @@ -157,27 +157,27 @@ function scr_random_event(execute_now) { } break; case eEVENT.FLEET_DELAY: - var has_moving_fleet = false; + var _delayed_fleet_moving = false; with (obj_p_fleet) { if (action == "move") { - has_moving_fleet = true; + _delayed_fleet_moving = true; break; } } - if (!has_moving_fleet) { + if (!_delayed_fleet_moving) { events_share[i] -= 1; events_total -= 1; } break; case eEVENT.SHIP_LOST: - var has_moving_fleet = false; + var _lost_fleet_moving = false; with (obj_p_fleet) { if (action == "move") { - has_moving_fleet = true; + _lost_fleet_moving = true; break; } } - if (!has_moving_fleet) { + if (!_lost_fleet_moving) { events_share[i] -= 1; events_total -= 1; } @@ -220,17 +220,17 @@ function scr_random_event(execute_now) { var own = choose(1, 1, 2); var star_id = scr_random_find(own, true, "", ""); - if (star_id == undefined && own == 1) { + if (star_id == noone && own == 1) { // find the nearest star to a player fleet and user that one, dukecode did that // we could also try to find to find another star but this one is owned by the imperium and not the player, this code is doing that own = 2; star_id = scr_random_find(own, true, "", ""); } - if (star_id == undefined && own == 2) { + if (star_id == noone && own == 2) { star_id = scr_random_find(0, true, "", ""); // try for litteraly any star } - if (star_id == undefined) { + if (star_id == noone) { LOGGER.error("RE: Space Hulk, couldn't find a star for the spacehulk"); exit; } else { @@ -300,12 +300,12 @@ function scr_random_event(execute_now) { own = choose(1, 2); var star_id = scr_random_find(own, true, "", ""); - if (star_id == undefined && own == 1) { + if (star_id == noone && own == 1) { own = 2; star_id = scr_random_find(own, true, "", ""); } - if (star_id == undefined) { + if (star_id == noone) { LOGGER.error("RE: Sororitas Company, couldn't find a star for the company"); exit; } else { @@ -555,16 +555,16 @@ function scr_random_event(execute_now) { } var star_id = scr_random_find(own, true, "", ""); - if (star_id == undefined && own == 1) { + if (star_id == noone && own == 1) { own = 2; star_id = scr_random_find(own, true, "", ""); } - if (star_id == undefined && own == 2) { + if (star_id == noone && own == 2) { own = 0; star_id = scr_random_find(own, true, "", ""); } - if (star_id == undefined) { + if (star_id == noone) { LOGGER.error("RE: Warp Storm, couldn't pick a star for the warp storm"); exit; } else { @@ -586,16 +586,16 @@ function scr_random_event(execute_now) { } var star_id = scr_random_find(own, true, "", ""); - if (star_id == undefined && own == 1) { + if (star_id == noone && own == 1) { own = 2; star_id = scr_random_find(own, true, "", ""); } - if (star_id == undefined && own == 2) { + if (star_id == noone && own == 2) { own = 3; star_id = scr_random_find(own, true, "", ""); } - if (star_id == undefined) { + if (star_id == noone) { LOGGER.error("RE: Enemy Forces, couldn't find a star for the enemy"); exit; } else { diff --git a/scripts/scr_random_find/scr_random_find.gml b/scripts/scr_random_find/scr_random_find.gml index a458e7ab49..404bac6827 100644 --- a/scripts/scr_random_find/scr_random_find.gml +++ b/scripts/scr_random_find/scr_random_find.gml @@ -17,7 +17,7 @@ function scr_random_find(owner, is_planet, ship_action, feature) { var star = stars[star_index]; return star; // use that to get the obj } else { - return undefined; + return noone; } } else if (!is_planet && instance_exists(obj_all_fleet)) { var ships = []; @@ -35,9 +35,9 @@ function scr_random_find(owner, is_planet, ship_action, feature) { var ship = ships[ship_index]; return ship; } else { - return undefined; + return noone; } } else { - return undefined; //?? I think it would return that regardless + return noone; //?? I think it would return that regardless } } diff --git a/scripts/scr_random_marine/scr_random_marine.gml b/scripts/scr_random_marine/scr_random_marine.gml index 6e38a9f3f0..520610d15c 100644 --- a/scripts/scr_random_marine/scr_random_marine.gml +++ b/scripts/scr_random_marine/scr_random_marine.gml @@ -1,11 +1,7 @@ -function scr_random_marine(role, exp_req, search_params = "none") { - // role : role - // exp_req: exp - //search params : a struct giving extra search information defaults to "none" - - var company, i, comp_size, unit, match, r, unit_role, marine_list; - company = 0; - i = 0; +/// @param {string|Array} role +/// @param {Real} exp_req +/// @param {Struct} search_params a struct giving extra search information +function scr_random_marine(role, exp_req, search_params = {}) { var company_list = [ 0, 1, @@ -19,13 +15,13 @@ function scr_random_marine(role, exp_req, search_params = "none") { 9, 10 ]; - if (role == SPECIALISTS_LIBRARIANS) { + if (!is_array(role) && role == SPECIALISTS_LIBRARIANS) { role = role_groups(SPECIALISTS_LIBRARIANS); } for (var comp_shuffle = 0; comp_shuffle < 11; comp_shuffle++) { // this ensures that companies are searched randomly var new_comp = irandom(array_length(company_list) - 1); - company = company_list[new_comp]; + var company = company_list[new_comp]; array_delete(company_list, new_comp, 1); if (!is_array(role)) { if (string_count("Aspirant", role) > 0) { @@ -34,18 +30,18 @@ function scr_random_marine(role, exp_req, search_params = "none") { } } if (company <= 10) { - comp_size = array_length(obj_ini.name[company]); + var comp_size = array_length(obj_ini.name[company]); //This makes sure that cmopanies are searched randomly by creating an array of array positions to be randomly accessed - marine_list = []; - for (i = 0; i < comp_size; i++) { + var marine_list = []; + for (var i = 0; i < comp_size; i++) { marine_list[i] = i; } while (comp_size > 0) { var list_place = irandom(comp_size - 1); - i = marine_list[list_place]; - match = true; - unit = obj_ini.TTRPG[company][i]; + var _dude_index = marine_list[list_place]; + var match = true; + var unit = obj_ini.TTRPG[company][_dude_index]; //exit if not real name if ((unit.name() == "") || (unit.name() == 0)) { @@ -55,7 +51,7 @@ function scr_random_marine(role, exp_req, search_params = "none") { } //check correct search param roles - unit_role = unit.role(); + var unit_role = unit.role(); if (unit_role == obj_ini.role[100][eROLE.CHAPTERMASTER]) { array_delete(marine_list, list_place, 1); comp_size--; @@ -64,7 +60,7 @@ function scr_random_marine(role, exp_req, search_params = "none") { //if list of matchable roles given if (is_array(role)) { match = false; - for (r = 0; r < array_length(role); r++) { + for (var r = 0; r < array_length(role); r++) { if (unit_role == role[r]) { match = true; break; @@ -184,7 +180,7 @@ function scr_random_marine(role, exp_req, search_params = "none") { } //if match made exit loop and return unit if (match) { - return [company, i]; + return [company, _dude_index]; } } } diff --git a/scripts/scr_recent/scr_recent.gml b/scripts/scr_recent/scr_recent.gml index 5c9f4c0bdb..b40a25fec6 100644 --- a/scripts/scr_recent/scr_recent.gml +++ b/scripts/scr_recent/scr_recent.gml @@ -5,7 +5,6 @@ function scr_recent(recent_type = "", keyword = "", numerical_data = 0) { // Add an entry to the end of the argument2array if ((string(recent_type) != "") && (string(keyword) != "")) { - i = obj_controller.recent_happenings; array_push(obj_controller.recent_type, recent_type); array_push(obj_controller.recent_keyword, keyword); array_push(obj_controller.recent_turn, obj_controller.turn); @@ -21,9 +20,8 @@ function scr_recent(recent_type = "", keyword = "", numerical_data = 0) { array_push(delete_positions, i); } } - var del_pos; for (var i = 0; i < array_length(delete_positions); i++) { - del_pos = delete_positions[i]; + var del_pos = delete_positions[i]; array_delete(obj_controller.recent_type, del_pos, 1); array_delete(obj_controller.recent_keyword, del_pos, 1); array_delete(obj_controller.recent_turn, del_pos, 1); diff --git a/scripts/scr_recruit_data/scr_recruit_data.gml b/scripts/scr_recruit_data/scr_recruit_data.gml index 4d550cebe3..fcbfa2aec0 100644 --- a/scripts/scr_recruit_data/scr_recruit_data.gml +++ b/scripts/scr_recruit_data/scr_recruit_data.gml @@ -107,14 +107,14 @@ function find_recruit_success_chance(local_apothecary_points, system, planet, ui } else if (p_data.at_war(0, 0, 0) && p_data.player_disposition < 0) { recruit_chance = 2000; } else if (p_data.player_disposition < -1000 && p_data.current_owner == eFACTION.PLAYER) { - var recruit_chance = 1500 - _recruit_cost * 100; + recruit_chance = 1500 - _recruit_cost * 100; } else { var _frictious = p_data.at_war(0, 1, 1) && p_data.player_disposition <= 50; var _disp_mod = -((_frictious ? 30 : 10) * p_data.player_disposition); var _faction_disp_mod = !_frictious ? 2000 : 3000; var _recruit_cost_mod = -_recruit_cost * 100; - var recruit_chance = _disp_mod + _recruit_cost_mod + _faction_disp_mod; + recruit_chance = _disp_mod + _recruit_cost_mod + _faction_disp_mod; } if (_recruit_world.recruit_type == 1) { @@ -123,10 +123,9 @@ function find_recruit_success_chance(local_apothecary_points, system, planet, ui recruit_chance = 300; } if (ui == 0) { + var droll = irandom(100); if (scr_has_adv("Ambushers")) { - var droll = irandom(400); - } else { - var droll = irandom(100); + droll = irandom(400); } if (droll == 0) { @@ -158,10 +157,9 @@ function find_recruit_success_chance(local_apothecary_points, system, planet, ui } } } + var _success_chance = 0; if (recruit_chance != 0) { - var _success_chance = recruit_chance_total / recruit_chance; - } else { - var _success_chance = 0; + _success_chance = recruit_chance_total / recruit_chance; } return _success_chance; } @@ -345,7 +343,6 @@ function planet_training_sequence(local_apothecary_points) { // xp gain for the recruit is here // as well as planet type buffs or nerfs if (aspirant) { - var i = 0; var new_recruit = 0; // gets the next empty recruit space on the array diff --git a/scripts/scr_reequip_units/scr_reequip_units.gml b/scripts/scr_reequip_units/scr_reequip_units.gml index 6607e7d131..45bbe63069 100644 --- a/scripts/scr_reequip_units/scr_reequip_units.gml +++ b/scripts/scr_reequip_units/scr_reequip_units.gml @@ -1,7 +1,7 @@ /// @self Asset.GMObject.obj_controller function set_up_equip_popup() { if (!instance_exists(obj_popup)) { - var f = 0, god = 0, nuuum = 0; + var nuuum = 0; var o_wep1 = "", o_wep2 = "", o_armour = "", o_gear = "", o_mobi = ""; var b_wep1 = 0, b_wep2 = 0, b_armour = 0, b_gear = 0, b_mobi = 0; var vih = 0, _unit; @@ -461,11 +461,9 @@ function draw_popup_equip() { //TODO wrap this up in a function if (weapon_one_data.req_exp > 0) { - var g = -1, exp_check = 0; for (var g = 0; g < array_length(obj_controller.display_unit); g++) { if (obj_controller.man_sel[g] == 1 && is_struct(obj_controller.display_unit[g])) { if (obj_controller.display_unit[g].experience < weapon_one_data.req_exp) { - exp_check = 1; n_good1 = 0; warning = $"A unit must have {weapon_one_data.req_exp}+ EXP to use a {weapon_one_data.name}."; break; @@ -488,9 +486,7 @@ function draw_popup_equip() { // Check numbers req_wep2_num = units; have_wep2_num = 0; - var i = -1; - repeat (array_length(obj_controller.display_unit)) { - i += 1; + for (var i = 0; i < array_length(obj_controller.display_unit); i++) { if ((vehicle_equipment != -1) && (obj_controller.ma_wep2[i] == n_wep2)) { have_wep2_num += 1; } @@ -508,13 +504,9 @@ function draw_popup_equip() { } //TODO standardise exp check if (weapon_two_data.req_exp > 0) { - var g, exp_check; - g = -1; - exp_check = 0; for (var g = 0; g < array_length(obj_controller.display_unit); g++) { if (obj_controller.man_sel[g] == 1 && is_struct(obj_controller.display_unit[g])) { if (obj_controller.display_unit[g].experience < weapon_two_data.req_exp) { - exp_check = 1; n_good2 = 0; warning = $"A unit must have {weapon_two_data.req_exp}+ EXP to use a {weapon_two_data.name}."; break; @@ -543,10 +535,7 @@ function draw_popup_equip() { // Check numbers req_armour_num = units; have_armour_num = 0; - var i; - i = -1; - repeat (array_length(obj_controller.display_unit)) { - i += 1; + for (var i = 0; i < array_length(obj_controller.display_unit); i++) { if ((vehicle_equipment != -1) && (obj_controller.man_sel[i] == 1) && (obj_controller.ma_armour[i] == n_armour)) { have_armour_num += 1; } @@ -561,16 +550,11 @@ function draw_popup_equip() { warning = $"Not enough {n_armour} : {req_armour_num - have_armour_num} more are required."; } - var g = -1, exp_check = 0; if (armour_data.has_tag("terminator")) { if (armour_data.req_exp > 0) { - var g, exp_check; - g = -1; - exp_check = 0; for (var g = 0; g < array_length(obj_controller.display_unit); g++) { if (obj_controller.man_sel[g] == 1 && is_struct(obj_controller.display_unit[g])) { if (obj_controller.display_unit[g].experience < armour_data.req_exp) { - exp_check = 1; n_good3 = 0; warning = $"A unit must have {armour_data.req_exp}+ EXP to use a {armour_data.name}."; break; @@ -608,13 +592,13 @@ function draw_popup_equip() { } if (is_struct(armour_data) && is_struct(gear_data)) { - if (armour_data.has_tag("terminator") && !gear_data.has_tag("terminator") && !gear_data.has_tag("terminator_only")) { + /*if (armour_data.has_tag("terminator") && !gear_data.has_tag("terminator") && !gear_data.has_tag("terminator_only")) { n_good4 = 0; warning = "Cannot use this with Terminator Armour."; } else if (!armour_data.has_tag("terminator") && gear_data.has_tag("terminator_only")) { n_good4 = 0; warning = "Cannot use this without Terminator Armour."; - } else if (armour_data.has_tag("dreadnought") && !gear_data.has_tag("dreadnought") && !gear_data.has_tag("dreadnought_only")) { + } else*/ if (armour_data.has_tag("dreadnought") && !gear_data.has_tag("dreadnought") && !gear_data.has_tag("dreadnought_only")) { n_good4 = 0; warning = "Cannot use this with Dreadnought Armour."; } else if (!armour_data.has_tag("dreadnought") && gear_data.has_tag("dreadnought_only")) { @@ -627,10 +611,7 @@ function draw_popup_equip() { // Check numbers req_mobi_num = units; have_mobi_num = 0; - var i; - i = -1; - repeat (array_length(obj_controller.display_unit)) { - i += 1; + for (var i = 0; i < array_length(obj_controller.display_unit); i++) { if ((vehicle_equipment != -1) && (obj_controller.man_sel[i] == 1) && (obj_controller.ma_mobi[i] == n_mobi)) { have_mobi_num += 1; } diff --git a/scripts/scr_return_ship/scr_return_ship.gml b/scripts/scr_return_ship/scr_return_ship.gml index c04bf731cc..946a7d7af6 100644 --- a/scripts/scr_return_ship/scr_return_ship.gml +++ b/scripts/scr_return_ship/scr_return_ship.gml @@ -2,24 +2,12 @@ function scr_return_ship(ship_name, object, planet_number) { // ship_name: name of ship // object: object with man_selecting // planet_number: planet number - var man_size, i; - i = 0; - man_size = 0; - /*repeat(30){ - i+=1;if (obj_ini.ship[i]=ship_name) then ship_id=i; - }*/ - i = 0; - - // Increase ship storage ship_carrying[i] - - var unit; var return_planet = obj_controller.return_object; with (object) { - var man_size; for (var i = 0; i < array_length(display_unit); i++) { if (object.man_sel[i] > 0) { - unit = display_unit[i]; + var unit = display_unit[i]; if (is_struct(unit)) { if (return_place[i] > 0) { unit.load_marine(return_place[i], return_planet); diff --git a/scripts/scr_role_count/scr_role_count.gml b/scripts/scr_role_count/scr_role_count.gml index 09847c2dfb..3b64024bb7 100644 --- a/scripts/scr_role_count/scr_role_count.gml +++ b/scripts/scr_role_count/scr_role_count.gml @@ -1,11 +1,8 @@ function scr_role_count(target_role, search_location = "", return_type = "count") { // Take a guess - - var com, count, coom, units = [], unit, match; - - count = 0; - com = 0; - coom = -999; + var units = []; + var count = 0; + var coom = -999; if (is_string(search_location)) { if (search_location == "0") { @@ -36,27 +33,25 @@ function scr_role_count(target_role, search_location = "", return_type = "count" } if (coom >= 0) { - com = coom; - for (var i = 0; i < array_length(obj_ini.TTRPG[com]); i++) { - unit = obj_ini.TTRPG[com][i]; + for (var i = 0; i < array_length(obj_ini.TTRPG[coom]); i++) { + var unit = obj_ini.TTRPG[coom][i]; if (unit.name() == "") { continue; } - if ((unit.role() == target_role) && (obj_ini.god[com][i] < 10)) { + if ((unit.role() == target_role) && (obj_ini.god[coom][i] < 10)) { count += 1; if (return_type == "units") { - array_push(units, obj_ini.TTRPG[com][i]); + array_push(units, obj_ini.TTRPG[coom][i]); } } } - com += 1; } if (coom < 0) { for (var com = 0; com <= obj_ini.companies; com++) { for (var i = 0; i < array_length(obj_ini.TTRPG[com]); i++) { - match = false; - unit = fetch_unit([com, i]); + var match = false; + var unit = fetch_unit([com, i]); if (unit.name() == "") { continue; } diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index dc81c09e0e..c47893aa0f 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -103,7 +103,7 @@ function Roster() constructor { continue; } if (_unit.squad_type() != "none") { - var _valid_type = array_contains(_valid_squad_types, _unit.squad_type()); + _valid_type = array_contains(_valid_squad_types, _unit.squad_type()); } else { var _armour_data = _unit.get_armour_data(); if (is_struct(_armour_data)) { @@ -230,7 +230,7 @@ function Roster() constructor { roster_local_string += "\n"; roster_local_string += "Remaining\n"; - var _roster_types = struct_get_names(possible_local_roster); + _roster_types = struct_get_names(possible_local_roster); for (var i = 0; i < array_length(_roster_types); i++) { var _roster_type_name = _roster_types[i]; var _roster_type_count = possible_local_roster[$ _roster_type_name]; @@ -381,13 +381,11 @@ function Roster() constructor { var size_count = 0; var _limit = obj_ncombat.man_size_limit; var _has_limit = _limit > 0; - var _add; - var _unit, _size; for (var i = 0; i < array_length(selected_units); i++) { if (_has_limit && _limit == size_count) { break; } - _add = true; + var _add = true; if (is_struct(selected_units[i])) { var _unit = selected_units[i]; @@ -517,9 +515,8 @@ function add_unit_to_battle(unit, meeting, is_local) { //Same as co/company and v, but with extra comprovations in case of a meeting (meeting?) var _role = obj_ini.role[100]; - var cooh, va; - cooh = 0; - va = 0; + var cooh = 0; + var va = 0; var v = unit.marine_number; var company = unit.company; if (!meeting) { @@ -645,12 +642,6 @@ function add_unit_to_battle(unit, meeting, is_local) { if (_unit_role == _role[7]) { new_combat.champions++; } - - //if (company = 1) { - // col = obj_controller.bat_veteran_column; - // if (obj_ini.armour[cooh][va] = "Terminator Armour") then col = obj_controller.bat_terminator_column; - // if (obj_ini.armour[cooh][va] = "Tartaros Armour") then col = obj_controller.bat_terminator_column; - //} if (company >= 2) { col = obj_controller.bat_tactical_column; } diff --git a/scripts/scr_ruins_reward/scr_ruins_reward.gml b/scripts/scr_ruins_reward/scr_ruins_reward.gml index e0e8dd5461..6a7f1122be 100644 --- a/scripts/scr_ruins_reward/scr_ruins_reward.gml +++ b/scripts/scr_ruins_reward/scr_ruins_reward.gml @@ -35,7 +35,7 @@ function LootPool(_data) constructor { } /// @desc Processes rewards for exploring ancient ruins. -/// @param {Asset.GMObject.obj_star} _star_system The star system object. +/// @param {Id.Instance.obj_star} _star_system The star system object. /// @param {Real} _pid_idx Planet index within the system. /// @param {Struct.NewPlanetFeature} _ruins The ruins feature struct. function scr_ruins_reward(_star_system, _pid_idx, _ruins) { @@ -47,7 +47,7 @@ function scr_ruins_reward(_star_system, _pid_idx, _ruins) { /// @desc Internal logic for handling Gear distribution via JSON data. /// @param {Real} _race The ID of the ruins race. - /// @param {Asset.GMObject.obj_popup} _popup The popup instance to populate. + /// @param {Id.Instance.obj_popup} _popup The popup instance to populate. static _process_gear_reward = function(_race, _popup) { static _loot_registry = undefined; @@ -104,7 +104,9 @@ function scr_ruins_reward(_star_system, _pid_idx, _ruins) { }; /// @desc Internal logic for handling Artifact retrieval. - /// @param {Asset.GMObject.obj_popup} _popup + /// @param {Id.Instance.obj_star} _star + /// @param {String} _pidx + /// @param {Id.Instance.obj_popup} _popup static _process_artifact_reward = function(_star, _pidx, _popup) { var _chosen_ship = -1; var _fleet = scr_orbiting_player_fleet(_star); @@ -218,7 +220,7 @@ function scr_ruins_reward(_star_system, _pid_idx, _ruins) { _ruins.ruins_explored(); } -/// @param {Asset.GMObject.obj_popup} _popup The popup instance to populate. +/// @param {Id.Instance.obj_popup} _popup The popup instance to populate. function ancient_gene_lab_ruins_loot(_popup) { _popup.image = "geneseed_lab"; _popup.title = "Ancient Ruins: Gene-seed"; @@ -266,10 +268,10 @@ function ancient_gene_lab_ruins_loot(_popup) { }; } -/// @param {Asset.GMObject.obj_star} _star +/// @param {Id.Instance.obj_star} _star /// @param {Real} _planet /// @param {Struct} _ruins -/// @param {Asset.GMObject.obj_popup} _popup +/// @param {Id.Instance.obj_popup} _popup function ancient_fortress_ruins_loot(_star, _planet, _ruins, _popup) { _popup.image = "ruins_fort"; _popup.title = "Ancient Ruins: Fortress"; diff --git a/scripts/scr_serialization_functions/scr_serialization_functions.gml b/scripts/scr_serialization_functions/scr_serialization_functions.gml index 3ab0e0dcf9..f4ce04a7c5 100644 --- a/scripts/scr_serialization_functions/scr_serialization_functions.gml +++ b/scripts/scr_serialization_functions/scr_serialization_functions.gml @@ -1,8 +1,8 @@ /// @desc Copies simple (serializable) variables from one struct to another, excluding specified names and prefixes. Useful for building save-data structs. -/// @param {struct} _source - The struct to copy variables from. -/// @param {struct} _destination - The struct to copy variables into. -/// @param {array} _exclude - List of variable names to exclude. -/// @param {array} _exclude_start - List of string prefixes; variables starting with any of these will be excluded. +/// @param {Id.Instance|Struct} _source - The struct to copy variables from. +/// @param {Id.Instance|Struct} _destination - The struct to copy variables into. +/// @param {Array} _exclude - List of variable names to exclude. +/// @param {Array} _exclude_start - List of string prefixes; variables starting with any of these will be excluded. function copy_serializable_fields(_source, _destination, _exclude = [], _exclude_start = []) { /// Check all object variable values types and save the simple ones dynamically. /// simple types are numbers, strings, bools. arrays of only simple types are also considered simple. diff --git a/scripts/scr_ship_count/scr_ship_count.gml b/scripts/scr_ship_count/scr_ship_count.gml index 000dfb14ee..00bd30e0e0 100644 --- a/scripts/scr_ship_count/scr_ship_count.gml +++ b/scripts/scr_ship_count/scr_ship_count.gml @@ -1,7 +1,7 @@ function scr_ship_count(wanted_ship_class) { // Mi color favorito es bicicleta. - var count = 0, i = 0; + var count = 0; for (var i = 0; i < array_length(obj_ini.ship_class); i++) { if (obj_ini.ship_class[i] == wanted_ship_class) { @@ -10,8 +10,4 @@ function scr_ship_count(wanted_ship_class) { } return count; - - // temp[36]=scr_role_count("Chaplain","field"); - // temp[37]=scr_role_count("Chaplain","home"); - // temp[37]=scr_role_count("Chaplain",""); } diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index 267c0f784e..49a02bd51b 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -1,11 +1,11 @@ +/// @self Id.Instance.obj_enunit|Id.Instance.obj_pnunit +/// @param {Real} weapon_index_position Weapon number +/// @param {Id.Instance.obj_enunit|Id.Instance.obj_pnunit} target_object Target object +/// @param {Real} target_type Target dudes +/// @param {String} damage_data "att" or "arp" or "highest" +/// @param {String} melee_or_ranged melee or ranged function scr_shoot(weapon_index_position, target_object, target_type, damage_data, melee_or_ranged) { try { - // weapon_index_position: Weapon number - // target_object: Target object - // target_type: Target dudes - // damage_data: "att" or "arp" or "highest" - // melee_or_ranged: melee or ranged - // This massive clusterfuck of a script uses the newly determined weapon and target data to attack and assign damage var hostile_type; var hostile_damage; @@ -19,12 +19,11 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat } if ((weapon_index_position >= 0) && instance_exists(target_object) && (owner == 2)) { - var stop, damage_type, doom; var shots_fired = wep_num[weapon_index_position]; if (shots_fired == 0 || ammo[weapon_index_position] == 0) { exit; } - doom = 0; + var doom = 0; if ((shots_fired != 1) && (melee_or_ranged != "melee")) { switch (obj_ncombat.enemy) { case eFACTION.ECCLESIARCHY: @@ -52,8 +51,8 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat doom = 1; } - damage_type = ""; - stop = 0; + var damage_type = ""; + var stop = 0; if (ammo[weapon_index_position] > 0) { ammo[weapon_index_position] -= 1; @@ -184,7 +183,6 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat } if (instance_exists(target_object) && (owner == eFACTION.PLAYER)) { - // LOGGER.debug("{0}, {1}, {2}, {3}, {4}", wep_num[weapon_index_position], wep[weapon_index_position], splash[weapon_index_position], range[weapon_index_position], att[weapon_index_position]) var shots_fired = 0; var stop = 0; var damage_type = ""; diff --git a/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml b/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml index 97aa509017..c719e838a8 100644 --- a/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml +++ b/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml @@ -1,5 +1,4 @@ function SpecialistPointHandler() constructor { - static chapter_spread = calculate_full_chapter_spread; forge_queue = []; techs = []; apoths = []; @@ -239,7 +238,7 @@ function SpecialistPointHandler() constructor { var _new_pursuasion; for (var i = 0; i < array_length(techs) && heretics_persuade_chances > 0; i++) { _same_location = false; - var _new_pursuasion = array_random_index(techs); + _new_pursuasion = array_random_index(techs); //if tech is also heretic skip if (array_contains(heretics, _new_pursuasion)) { continue; @@ -291,7 +290,6 @@ function SpecialistPointHandler() constructor { _noticed_heresy = true; scr_event_log("purple", $"{techs[forge_master].name_role()} Has noticed signs of tech heresy amoung the Armentarium ranks"); scr_alert("purple", "Tech Heresy", $"{techs[forge_master].name_role()} Has noticed signs of tech heresy amoung the Armentarium ranks"); - //pip=instance_create(0,0,obj_popup); } } } @@ -302,18 +300,10 @@ function SpecialistPointHandler() constructor { } } //add check to see if tech heretic is anywhere near mechanicus forge if so maybe do stuff?? - /*if (_heretic_location==eLOCATION_TYPES.PLANET){ - if - }*/ } if (array_length(techs) > array_length(heretics) && !_heritecs) { if (array_length(heretics) / array_length(techs) >= 0.35) { if (!irandom(9)) { - /*var text_string = "You Recive an Urgent Transmision from"; - if (forge_master>-1){ - - }*/ - tech_uprising_event(); } } @@ -517,7 +507,4 @@ function SpecialistPointHandler() constructor { ERROR_HANDLER.handle_exception(_exception); } }; - /*static apothecary_points_calc(){ - - }*/ } diff --git a/scripts/scr_specialist_points/scr_specialist_points.gml b/scripts/scr_specialist_points/scr_specialist_points.gml index 1789dc2aa9..b46792f589 100644 --- a/scripts/scr_specialist_points/scr_specialist_points.gml +++ b/scripts/scr_specialist_points/scr_specialist_points.gml @@ -3,7 +3,7 @@ function unit_apothecary_points_gen(turn_end = false) { var reasons = {}; var points = 0; if (_trained_person) { - var points = ((technology / 2) + (wisdom / 2) + intelligence) / 8; + points = ((technology / 2) + (wisdom / 2) + intelligence) / 8; reasons.points = points; } return [points, reasons]; @@ -15,7 +15,7 @@ function unit_forge_point_generation(turn_end = false) { var reasons = {}; var points = 0; if (_trained_person) { - var points = technology / 5; + points = technology / 5; reasons.trained = points; } if (job != "none") { diff --git a/scripts/scr_specialist_training/scr_specialist_training.gml b/scripts/scr_specialist_training/scr_specialist_training.gml index cdc28f5404..93cdf547e6 100644 --- a/scripts/scr_specialist_training/scr_specialist_training.gml +++ b/scripts/scr_specialist_training/scr_specialist_training.gml @@ -1,4 +1,6 @@ /// @self Struct.TTRPG_stats +/// @param {String} specialist +/// @param {Real} req_exp function specialistfunct(specialist, req_exp) { var spec_tips = [ string("{0} Potential", obj_ini.role[100][16]), @@ -92,6 +94,7 @@ function specialistfunct(specialist, req_exp) { // Parameters: // specialist - Integer index (0: Techmarine, 1: Librarian, 2: Chaplain, 3: Apothecary) // Returns: Array containing company and position of selected marine, or "none" if no suitable marine found +/// @param {Real} specialist function spec_data_set(specialist) { var _data = obj_controller.spec_train_data[specialist]; var _search = { @@ -127,11 +130,7 @@ function apothecary_training() { if (apothecary_recruit_points >= 48) { if (recruit_count > 0) { var random_marine = scr_random_marine(novice_type, 0); - // show_message(marine_position); - // show_message(obj_ini.role[0,marine_position]); if (random_marine != "none") { - marine_position = random_marine[1]; - marine_company = random_marine[0]; apothecary_recruit_points -= 48; /// @type {Struct.TTRPG_stats} var unit = fetch_unit(random_marine); @@ -211,7 +210,6 @@ function chaplain_training() { if (recruit_count > 0) { var random_marine = scr_random_marine(novice_type, 0); if (random_marine != "none") { - marine_position = random_marine[1]; var unit = fetch_unit(random_marine); scr_alert("green", "recruitment", unit.name_role() + " has finished training.", 0, 0); chaplain_points -= 48; @@ -288,7 +286,6 @@ function librarian_training() { recruit_count = scr_role_count(novice_type, ""); if (psyker_points >= goal) { if (recruit_count > 0) { - marine_position = 0; var random_marine = scr_random_marine(novice_type, 0, {"stat": [["psionic", 2, "more"]]}); if (random_marine != "none") { var unit = fetch_unit(random_marine); @@ -357,11 +354,10 @@ function techmarine_training() { var novice_type = string("{0} Aspirant", obj_ini.role[100][16]); if (training_techmarine > 0) { recruit_count = scr_role_count(novice_type, ""); + var _threshold = 252; if (obj_controller.faction_status[eFACTION.MECHANICUS] != "War") { - var _threshold = 360; - } else { - var _threshold = 252; + _threshold = 360; } if (tech_points >= _threshold) { diff --git a/scripts/scr_sprite_helpers/scr_sprite_helpers.gml b/scripts/scr_sprite_helpers/scr_sprite_helpers.gml index 4d512b072b..86dd088349 100644 --- a/scripts/scr_sprite_helpers/scr_sprite_helpers.gml +++ b/scripts/scr_sprite_helpers/scr_sprite_helpers.gml @@ -7,18 +7,16 @@ function draw_sprite_flipped(_sprite, _subimg, _x, _y) { } /// @function return_sprite_mirrored(sprite) -/// @param sprite The sprite index to mirror -/// @returns A new sprite index that is the mirrored version -/// @function return_sprite_mirrored(sprite) -/// @param sprite The sprite index to mirror -/// @returns A new sprite index that is the mirrored version +/// @param {Asset.GMSprite} _spr The sprite index to mirror +/// @param {Bool} delete_sprite +/// @returns {Asset.GMSprite} A new sprite index that is the mirrored version function return_sprite_mirrored(_spr, delete_sprite = true) { var _w = sprite_get_width(_spr); var _h = sprite_get_height(_spr); var _frames = sprite_get_number(_spr); // New mirrored sprite we’ll build - var _new_sprite = -1; + var _new_sprite = undefined; for (var _i = 0; _i < _frames; _i++) { // Create surface for this frame diff --git a/scripts/scr_squads/scr_squads.gml b/scripts/scr_squads/scr_squads.gml index eaafb6a7ca..7cabad2454 100644 --- a/scripts/scr_squads/scr_squads.gml +++ b/scripts/scr_squads/scr_squads.gml @@ -242,10 +242,6 @@ function UnitSquad(squad_type = undefined, company = 0) constructor { uid = scr_uuid_generate(); allow_bulk_swap = true; - if (squad_type != undefined) { - change_type(squad_type); - } - //TODO introduce loyalty hits from long periods of exile from hierarchy nodes // nodes will be captains chapter masters and other senior staff time_from_parent_node = 0; @@ -286,6 +282,10 @@ function UnitSquad(squad_type = undefined, company = 0) constructor { add_type_data(obj_ini.squad_types[$ type].type_data); }; + if (squad_type != undefined) { + change_type(squad_type); + } + static find_squad_unit_types = function() { //find out what type of units squad consists of var fill_squad = obj_ini.squad_types[$ type]; @@ -586,14 +586,13 @@ function UnitSquad(squad_type = undefined, company = 0) constructor { //this means the highest ranking dude in a squad will always be the squad leader //failing that the highest experience dude static determine_leader = function() { - var _unit; var member_length = array_length(members); var hierarchy = role_hierarchy(); var leader_hier_pos = array_length(hierarchy); - var leader = "none", _unit; + var leader = "none"; var highest_exp = 0; for (var i = 0; i < member_length; i++) { - _unit = fetch_unit(members[i]); + var _unit = fetch_unit(members[i]); if (_unit.name() == "") { array_delete(members, i, 1); member_length--; @@ -656,24 +655,23 @@ function UnitSquad(squad_type = undefined, company = 0) constructor { static set_location = function(loc, lid, wid) { var member_length = array_length(members); var member_location; - var system = "none"; + var system = noone; with (obj_star) { if (name == loc) { system = self; break; } } - if (system == "none") { + if (system == noone) { return "invalid system"; } member_loop(set_member_loc, {loc: loc, lid: lid, wid: wid, system: system}); }; static member_loop = function(member_func, data_pack) { - var _unit; member_length = array_length(members); for (var i = 0; i < member_length; i++) { - _unit = fetch_unit(members[i]); + var _unit = fetch_unit(members[i]); if (_unit.name() == "") { array_delete(members, i, 1); member_length--; diff --git a/scripts/scr_system_search_helpers/scr_system_search_helpers.gml b/scripts/scr_system_search_helpers/scr_system_search_helpers.gml index 796720a22f..7ef17e63bc 100644 --- a/scripts/scr_system_search_helpers/scr_system_search_helpers.gml +++ b/scripts/scr_system_search_helpers/scr_system_search_helpers.gml @@ -74,8 +74,8 @@ function scr_star_has_planet_with_feature(star, feature) { return scr_get_planet_with_feature(star, feature) != -1; } -function scr_planet_owned_by_group(planet_id, group, star = "none") { - if (star == "none") { +function scr_planet_owned_by_group(planet_id, group, star = noone) { + if (star == noone) { return array_contains(group, p_owner[planet_id]); } else { var is_in_group = false; @@ -133,9 +133,9 @@ function stars_with_faction_fleets(search_faction) { return _stars_with_fleets; } -function planets_without_type(type, star = "none") { +function planets_without_type(type, star = noone) { var return_planets = []; - if (star == "none") { + if (star == noone) { for (var i = 1; i <= planets; i++) { if (p_type[i] != type) { array_push(return_planets, i); @@ -172,10 +172,8 @@ function scr_get_stars(shuffled = false, ownership = [], types = []) { var _owner_sort = array_length(ownership); var _types_sort = array_length(types); with (obj_star) { - if (!_owner_sort && !_types_sort) { - var _add = true; - } else { - var _add = true; + var _add = true; + if (_owner_sort || _types_sort) { if (_owner_sort && !array_contains(ownership, owner)) { _add = false; } @@ -208,11 +206,11 @@ function planet_imperium_ground_total(planet_check) { /// @function find_star_by_name(search_name) /// @description Searches all `obj_star` instances and returns the one with a matching name. /// @param {String} search_name The name of the star to find. -/// @returns {Id.Instance.obj_star | String} Returns the `obj_star` instance that matches `search_name`, or the string `"none"` if no matching star is found. +/// @returns {Id.Instance.obj_star | noone} Returns the `obj_star` instance that matches `search_name`, or the 'noone' object reference if no matching star is found. function find_star_by_name(search_name) { if (!instance_exists(obj_star)) { ERROR_HANDLER.assert_popup("Not a single instance of obj_star exists!"); - return "none"; + return noone; } with (obj_star) { @@ -221,7 +219,7 @@ function find_star_by_name(search_name) { } } - return "none"; + return noone; } //use this to quickly make a loop through a stars planets in an unordered way @@ -308,7 +306,7 @@ function distance_removed_star(origional_x, origional_y, star_offset = choose(2, } function nearest_star_proper(xx, yy) { - var cur_star; + var cur_star = noone; for (var i = 0; i < 100; i++) { cur_star = instance_nearest(xx, yy, obj_star); if (!cur_star.craftworld && !cur_star.space_hulk) { @@ -317,24 +315,24 @@ function nearest_star_proper(xx, yy) { } instance_deactivate_object(cur_star.id); } - return "none"; + return noone; } -function nearest_star_with_ownership(xx, yy, ownership, start_star = "none", ignore_dead = true) { - var nearest = "none"; +function nearest_star_with_ownership(xx, yy, ownership, start_star = noone, ignore_dead = true) { + var nearest = noone; var _deactivated = []; var total_stars = instance_number(obj_star); var i = 0; if (!is_array(ownership)) { ownership = [ownership]; } - while (nearest == "none" && i < total_stars) { + while (nearest == noone && i < total_stars) { i++; var cur_star = instance_nearest(xx, yy, obj_star); if (!instance_exists(cur_star)) { break; } - if (start_star != "none") { + if (start_star != noone) { if (start_star.id == cur_star.id || (ignore_dead && is_dead_star(cur_star))) { array_push(_deactivated, cur_star.id); instance_deactivate_object(cur_star.id); @@ -369,13 +367,11 @@ function find_population_doners(doner_to = 0) { return pop_doner_options; } -function planet_numeral_name(planet, star = "none") { - if (star == "none") { - //LOGGER.debug($"{planet}, numeral name") +function planet_numeral_name(planet, star = noone) { + if (star == noone) { return $"{name} {int_to_roman(planet)}"; } else { with (star) { - //LOGGER.debug($"{planet}, numeral name") return $"{name} {int_to_roman(planet)}"; } } @@ -400,9 +396,9 @@ function nearest_from_array(xx, yy, list) { return _nearest; } -function is_dead_star(star = "none") { +function is_dead_star(star = noone) { var dead_star = true; - if (star == "none") { + if (star == noone) { for (var i = 1; i <= planets; i++) { if (string_lower(p_type[i]) != "dead") { dead_star = false; @@ -489,15 +485,6 @@ function scr_planet_image_numbers(p_type) { return 0; } -//function scr_get_player_fleets() { -// var player_fleets = []; -// with(obj_p_fleet){ -// array_push(player_fleets,id); -// } -// return player_fleets; - -//} - /// @param {Id.Instance.obj_star} star /// @param {Enum.eFACTION} faction /// @param {Real} minimum_strength diff --git a/scripts/scr_system_spawn_functions/scr_system_spawn_functions.gml b/scripts/scr_system_spawn_functions/scr_system_spawn_functions.gml index b3e7f09945..046faa0f6f 100644 --- a/scripts/scr_system_spawn_functions/scr_system_spawn_functions.gml +++ b/scripts/scr_system_spawn_functions/scr_system_spawn_functions.gml @@ -25,6 +25,7 @@ enum ePLAYER_BASE { function find_player_spawn_star() { instance_activate_object(obj_star); var _spawn_star; + var _chosen_star = noone; var _allowable = false; var _allowables = [ "Temperate", @@ -36,7 +37,8 @@ function find_player_spawn_star() { "Lava" ]; for (var i = 0; i < 100; i++) { - var y_loc, x_loc; + var x_loc = irandom_range(0 + (room_width / 2), room_width - (room_width / 2)); + var y_loc = irandom_range(0 + (room_height / 2), room_height - (room_height / 2)); if (obj_ini.homeworld_relative_loc == 0) { if (irandom(1)) { y_loc = choose(0, room_height); @@ -45,11 +47,8 @@ function find_player_spawn_star() { x_loc = choose(0, room_width); y_loc = irandom(room_height); } - } else { - x_loc = irandom_range(0 + (room_width / 2), room_width - (room_width / 2)); - y_loc = irandom_range(0 + (room_height / 2), room_height - (room_height / 2)); } - var _chosen_star = instance_nearest(x_loc, y_loc, obj_star); + _chosen_star = instance_nearest(x_loc, y_loc, obj_star); if (instance_exists(_chosen_star)) { for (var p = 0; p < array_length(_chosen_star.p_type); p++) { if (array_contains(_allowables, _chosen_star.p_type[p])) { @@ -66,6 +65,7 @@ function find_player_spawn_star() { return _chosen_star.id; } +/// @self Id.Instance.obj_star function player_home_star(home_planet) { var _star_names = global.name_generator.name_sets.star; p_type[home_planet] = obj_ini.home_type; @@ -75,7 +75,7 @@ function player_home_star(home_planet) { if (obj_ini.home_name != "random") { _star_names.AddUsedName(obj_ini.home_name); var _old_name_star = find_star_by_name(obj_ini.home_name); - if (_old_name_star != "none") { + if (_old_name_star != noone) { _old_name_star.name = global.name_generator.GenerateFromSet("star", false); } name = obj_ini.home_name; @@ -114,10 +114,9 @@ function player_home_star(home_planet) { p_player[home_planet] = obj_ini.man_size; - var unit; for (var co = 0; co <= obj_ini.companies; co++) { - for (i = 0; i < array_length(obj_ini.name[co]); i++) { - unit = fetch_unit([co, i]); + for (var i = 0; i < array_length(obj_ini.name[co]); i++) { + var unit = fetch_unit([co, i]); if (unit.location_string == name) { unit.planet_location = home_planet; } @@ -133,7 +132,7 @@ function set_player_recruit_planet(recruit_planet) { var recruit_name = obj_ini.recruiting_name; if (recruit_name != "random") { _star_names.AddUsedName(recruit_name); - if (find_star_by_name(recruit_name) != "none") { + if (find_star_by_name(recruit_name) != noone) { find_star_by_name(recruit_name).name = global.name_generator.GenerateFromSet("star", false); } name = recruit_name; @@ -141,7 +140,7 @@ function set_player_recruit_planet(recruit_planet) { } else { if (obj_ini.home_name != "random") { _star_names.AddUsedName(obj_ini.home_name); - if (find_star_by_name(obj_ini.home_name) != "none") { + if (find_star_by_name(obj_ini.home_name) != noone) { find_star_by_name(obj_ini.home_name).name = global.name_generator.GenerateFromSet("star", false); } name = obj_ini.home_name; diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 52c0e2cb83..9dffdfdfa2 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -434,7 +434,6 @@ function TradeAttempt(diplomacy) constructor { _option.disabled = true; _option.tooltip = $"{trade_disp} disposition required"; } - //_option.bind_scope = _option; array_push(demand_options, _option); }; @@ -466,7 +465,6 @@ function TradeAttempt(diplomacy) constructor { new_demand_buttons(60, "Cyclonic Torpedo", "equip", 1); break; case 5: - //new_demand_buttons(30, "Inferno Bolts", "equip"); new_demand_buttons(40, "Sister of Battle", "merc", 5); new_demand_buttons(45, "Sister Hospitaler", "merc", 3); break; @@ -546,7 +544,6 @@ function TradeAttempt(diplomacy) constructor { draw_set_font(fnt_40k_14); draw_set_color(CM_GREEN_COLOR); var _requested_count = 0; - //if (obj_controller.trading_artifact = 0){ for (var i = 0; i < array_length(demand_options); i++) { var _opt = demand_options[i]; if (_opt.number != _opt.number_last) { @@ -574,9 +571,8 @@ function TradeAttempt(diplomacy) constructor { _requested_count++; } } - //} - var _requested_count = 0; + _requested_count = 0; draw_text(507, 529, $"{global.chapter_name}:"); for (var i = 0; i < array_length(offer_options); i++) { var _opt = offer_options[i]; diff --git a/scripts/scr_trade_dep/scr_trade_dep.gml b/scripts/scr_trade_dep/scr_trade_dep.gml index f8343cd279..6506d37f27 100644 --- a/scripts/scr_trade_dep/scr_trade_dep.gml +++ b/scripts/scr_trade_dep/scr_trade_dep.gml @@ -1,3 +1,4 @@ +/// @self Id.Instance.obj_en_fleet function scr_trade_dep() { var _goods = cargo_data.player_goods; diff --git a/scripts/scr_transfer_marines/scr_transfer_marines.gml b/scripts/scr_transfer_marines/scr_transfer_marines.gml index 83fcf7875b..a964c2b6e7 100644 --- a/scripts/scr_transfer_marines/scr_transfer_marines.gml +++ b/scripts/scr_transfer_marines/scr_transfer_marines.gml @@ -20,31 +20,29 @@ function draw_popup_transfer() { } function transfer_marines() { - var mahreens = 0, w = 0, god = 0, vehi = 0, god2 = 0; + var vehi = 0; - mahreens = find_company_open_slot(target_comp); + var mahreens = find_company_open_slot(target_comp); - for (w = 1; w < 101; w++) { + for (var w = 1; w < 101; w++) { // Gets the number of vehicles in the target company - if (god2 == 0 && obj_ini.veh_role[target_comp][w] == "") { - god2 = 1; + if (obj_ini.veh_role[target_comp][w] == "") { vehi = w; break; } } // The MAHREENS and TARGET/FROM seems to check out - var unit, move_squad, move_members, moveable, squad; - for (w = 0; w < array_length(obj_controller.display_unit); w++) { + for (var w = 0; w < array_length(obj_controller.display_unit); w++) { if (obj_controller.man_sel[w] == 1) { if (obj_controller.man[w] == "man" && is_struct(obj_controller.display_unit[w])) { - moveable = true; - unit = obj_controller.display_unit[w]; + var moveable = true; + var unit = obj_controller.display_unit[w]; if (unit.squad != "none") { // this evaluates if you are tryin to move a whole squad and if so moves teh squad to a new company var move_squad = unit.squad; - squad = fetch_squad(move_squad); - move_members = squad.members; + var squad = fetch_squad(move_squad); + var move_members = squad.members; for (var mem = 0; mem < array_length(move_members); mem++) { //check all members have been selected and are in the same company if (w + mem < array_length(obj_controller.display_unit)) { diff --git a/scripts/scr_turn_first/scr_turn_first.gml b/scripts/scr_turn_first/scr_turn_first.gml index 2c415f592d..a32796250a 100644 --- a/scripts/scr_turn_first/scr_turn_first.gml +++ b/scripts/scr_turn_first/scr_turn_first.gml @@ -21,7 +21,7 @@ function scr_turn_first() { if (instance_exists(obj_p_fleet) && (!_identifiable)) { var _arti_fleet = find_ships_fleet(_cur_arti.ship_id()); - if (_arti_fleet != "none") { + if (_arti_fleet != noone) { if (array_length(_arti_fleet.capital_num)) { _identifiable = true; _cur_arti.set_ship_id(_arti_fleet.capital_num[0]); diff --git a/scripts/scr_ui_diplomacy/scr_ui_diplomacy.gml b/scripts/scr_ui_diplomacy/scr_ui_diplomacy.gml index 008ce5b5e1..7dd59ebd35 100644 --- a/scripts/scr_ui_diplomacy/scr_ui_diplomacy.gml +++ b/scripts/scr_ui_diplomacy/scr_ui_diplomacy.gml @@ -317,11 +317,11 @@ function set_up_diplomacy_persons() { management_buttons = { audience: new UnitButtonObject({ style: "pixel", - label: "Request Audience", //tooltip: "." + label: "Request Audience", }), ignore: new UnitButtonObject({ style: "pixel", - label: "Ignore", //tooltip: "." + label: "Ignore", }), unignore: new UnitButtonObject({style: "pixel", label: "Unignore", tooltip: "Click here or press B to Toggle Unit Biography."}), screen_slate: new DataSlate(), @@ -371,11 +371,6 @@ function set_up_diplomacy_persons() { _ignore_status.update({x1: _audience.x2 + 1, y1: yy + 85}); _ignore_status.draw(); - - /*var fis;fis="[Request Audience]"; - if (turns_ignored[2]>0) then fis=" "; - if (ignore[eFACTION.IMPERIUM]<1) then draw_text_transformed(xx+189,yy+354,string(fis)+" [Ignore]",0.7,0.7,0); - if (ignore[eFACTION.IMPERIUM]>=1) then draw_text_transformed(xx+189,yy+354,string(fis)+"[Unignore]",0.7,0.7,0);*/ } }; } @@ -417,17 +412,6 @@ function scr_ui_diplomacy() { if (diplomacy == 0) { // Main diplomacy screen - /*draw_set_color(CM_GREEN_COLOR); - draw_rectangle(xx+31,yy+281,xx+438,yy+416,0); - draw_rectangle(xx+31,yy+417,xx+438,yy+552,0); - draw_rectangle(xx+31,yy+553,xx+438,yy+688,0); - draw_rectangle(xx+31,yy+689,xx+438,yy+824,0); - // - draw_rectangle(xx+451,yy+281,xx+858,yy+125,0); - draw_rectangle(xx+451,yy+417,xx+858,yy+125+91,0); - draw_rectangle(xx+451,yy+553,xx+858,yy+125+182,0); - draw_rectangle(xx+451,yy+689,xx+858,yy+125+273,0);*/ - draw_set_color(CM_GREEN_COLOR); draw_set_font(fnt_40k_30b); draw_set_halign(fa_center); @@ -456,28 +440,9 @@ function scr_ui_diplomacy() { scr_image("symbol", 1, xx + 525, yy + 174, 109, 54); scr_image("symbol", 2, xx + 1147, yy + 174, 217, 107); - //draws chapter diplomacy - /*draw_rectangle(xx+451,yy+281,xx+675,yy+416,1); - draw_line(xx+604,yy+281,xx+604,yy+416); - draw_rectangle(xx+451,yy+417,xx+675,yy+552,1); - draw_line(xx+604,yy+417,xx+604,yy+553); - draw_rectangle(xx+451,yy+553,xx+675,yy+688,1); - draw_line(xx+604,yy+553,xx+604,yy+689); - draw_rectangle(xx+451,yy+689,xx+675,yy+824,1); - draw_line(xx+604,yy+689,xx+604,yy+824); - */ - draw_set_font(fnt_40k_14b); draw_set_halign(fa_left); - //draw faction names, etc - /* - draw_text(xx+609,yy+285,"Chapter 1"); - draw_text(xx+609,yy+421,"Chapter 2"); - draw_text(xx+609,yy+557,"Chapter 3"); - draw_text(xx+609,yy+693,"Chapter 4"); - */ - //render status, i.e. whether at war, that stuff draw_set_font(fnt_40k_14); draw_set_halign(fa_right); @@ -522,8 +487,6 @@ function scr_ui_diplomacy() { if (!is_struct(character_diplomacy)) { LOGGER.debug("no valid diplomacy target"); diplomacy = 0; - } else { - // draw_sprite(spr_diplo_splash,diplomacy,xx+916,yy+33); } } @@ -534,9 +497,7 @@ function scr_ui_diplomacy() { if ((diplomacy > 10) && (diplomacy < 11)) { daemon = true; } - // draw_sprite(spr_diplo_splash,diplomacy,xx+916,yy+33); if (diplomacy == 10.1) { - // if (diplomacy=10.1) then draw_sprite(spr_diplomacy_dae,0,xx+16,yy+43); daemon = true; scr_image("diplomacy_daemon", 0, xx + 16, yy + 43, 310, 828); show_stuff = false; @@ -586,7 +547,6 @@ function scr_ui_diplomacy() { draw_set_font(fnt_40k_14); if (daemon == false) { _disposition_rating = $"Disposition: {faction_disposition_rating_string(diplomacy)} ({disposition[diplomacy]})"; - // draw_set_halign(fa_center); draw_text(xx + 622, yy + 144, _disposition_rating); scr_draw_rainbow(xx + 366, yy + 165, xx + 871, yy + 175, (disposition[diplomacy] / 200) + 0.5); } @@ -612,7 +572,5 @@ function scr_ui_diplomacy() { draw_rectangle(mouse_x - 2, mouse_y + 20, mouse_x + 2 + string_width_ext(warn, -1, 600), mouse_y + 24 + string_height_ext(warn, -1, 600), 1); draw_text_ext(mouse_x, mouse_y + 22, warn, -1, 600); } - - //scr_dialogue(diplomacy_pathway); basic_diplomacy_screen(); } diff --git a/scripts/scr_ui_formation_bars/scr_ui_formation_bars.gml b/scripts/scr_ui_formation_bars/scr_ui_formation_bars.gml index a77072a730..c902f4b290 100644 --- a/scripts/scr_ui_formation_bars/scr_ui_formation_bars.gml +++ b/scripts/scr_ui_formation_bars/scr_ui_formation_bars.gml @@ -1,7 +1,7 @@ /// @self Asset.GMObject.obj_controller function scr_ui_formation_bars() { var ui_formations_data = { - nbar: 0, + nbar: noone, abar: 0, te: 4700, x9: 49, diff --git a/scripts/scr_ui_manage/scr_ui_manage.gml b/scripts/scr_ui_manage/scr_ui_manage.gml index ec9c778e5d..e73e68a429 100644 --- a/scripts/scr_ui_manage/scr_ui_manage.gml +++ b/scripts/scr_ui_manage/scr_ui_manage.gml @@ -49,11 +49,12 @@ function load_marines_into_ship(system, ship, units, reload = false) { } } + var _unit_size = 0; if (_is_marine) { - var _unit_size = man_size; + _unit_size = man_size; } else { var _vehic_size = scr_unit_size("", ma_role[q], true); - var _unit_size = _vehic_size; + _unit_size = _vehic_size; } if (_unit_ship_id == -1) { @@ -155,7 +156,7 @@ function reset_manage_unit_constants(unit) { // Gear - var _data = { + _data = { tooltip: $"==Gear==\n{is_struct(_equip_data.gear_data) ? _equip_data.gear_data.item_tooltip_desc_gen() : ""}", colour: quality_color(unit.gear_quality), max_width: 187, @@ -164,7 +165,7 @@ function reset_manage_unit_constants(unit) { unit_manage_constants.gear_string = new ReactiveString(unit.equipments_qual_string("gear", true), 0, 0, _data); //mobility - var _data = { + _data = { tooltip: $"==Back/Mobilitiy==\n{is_struct(_equip_data.mobility_data) ? _equip_data.mobility_data.item_tooltip_desc_gen() : ""}", colour: quality_color(unit.mobility_item_quality), max_width: 187, @@ -172,7 +173,7 @@ function reset_manage_unit_constants(unit) { unit_manage_constants.mobi_string = new ReactiveString(unit.equipments_qual_string("mobi", true), 0, 0, _data); - var _data = { + _data = { tooltip: $"==First Weapon==\n{is_struct(_equip_data.weapon_one_data) ? _equip_data.weapon_one_data.item_tooltip_desc_gen() : ""}", colour: quality_color(unit.weapon_one_quality), max_width: 187, @@ -181,7 +182,7 @@ function reset_manage_unit_constants(unit) { unit_manage_constants.wep1_string = new ReactiveString(unit.equipments_qual_string("wep1", true), 0, 0, _data); //mobility - var _data = { + _data = { tooltip: $"==Second Weapon==\n{is_struct(_equip_data.weapon_two_data) ? _equip_data.weapon_two_data.item_tooltip_desc_gen() : ""}", colour: quality_color(unit.weapon_two_quality), max_width: 187, @@ -342,7 +343,7 @@ function reset_manage_unit_constants(unit) { var _range = unit.ranged_attack(); unit_manage_constants.ranged_attack = new LabeledIcon(spr_icon_ballistic_skill, $"{round(_range[0])}", 0, 0, {icon_width: 24, icon_height: 24, tooltip: $"==Ranged Attack==\n{_range[1]}", colour: unit.encumbered_ranged ? #bf4040 : CM_GREEN_COLOR}); - var _carry = _range[2]; + _carry = _range[2]; unit_manage_constants.ranged_burden = new LabeledIcon(spr_icon_weight, $"{_carry[0]}/{_carry[1]}", 0, 0, {icon_width: 24, icon_height: 24, tooltip: $"==Ranged Burden==\n{_carry[2]}", colour: unit.encumbered_ranged ? #bf4040 : CM_GREEN_COLOR}); // ------------------------- @@ -1103,8 +1104,6 @@ function scr_ui_manage() { sel_all = ""; draw_set_color(c_black); - xx = camera_get_view_x(view_camera[0]); - yy = camera_get_view_y(view_camera[0]); draw_rectangle(xx + 974, yy + 165, xx + 1005, yy + 822, 0); draw_set_color(c_gray); draw_rectangle(xx + 974, yy + 165, xx + 1005, yy + 822, 1); @@ -1122,17 +1121,6 @@ function scr_ui_manage() { draw_sprite_stretched(spr_arrow, 2, xx + 974, yy + 141, 31, 30); draw_sprite_stretched(spr_arrow, 3, xx + 974, yy + 791, 31, 30); - /* - draw_set_color(c_black);draw_rectangle(xx+25,yy+400,xx+600,yy+417,0); - draw_set_color(CM_GREEN_COLOR);draw_rectangle(xx+25,yy+400,xx+600,yy+417,1); - draw_line(xx+160,yy+400,xx+160,yy+417); - draw_line(xx+304,yy+400,xx+304,yy+417); - draw_line(xx+448,yy+400,xx+448,yy+417); - - draw_set_font(fnt_menu); - draw_set_halign(fa_center); - */ - yy += 8; var _draw_selec_buttons = !obj_controller.unit_profile && !stats_displayed; if (_draw_selec_buttons && instance_exists(obj_popup)) { @@ -1149,8 +1137,6 @@ function scr_ui_manage() { var selected_unit = obj_controller.unit_focus; if ((selected_unit.name() != "") && (selected_unit.race() != 0)) { draw_set_alpha(1); - var xx = camera_get_view_x(view_camera[0]); - var yy = camera_get_view_y(view_camera[0]); if (obj_controller.unit_profile && !instance_exists(obj_popup)) { stats_displayed = true; selected_unit.stat_display(true); diff --git a/scripts/scr_ui_tooltip/scr_ui_tooltip.gml b/scripts/scr_ui_tooltip/scr_ui_tooltip.gml index 28f531bfb3..760977ba0e 100644 --- a/scripts/scr_ui_tooltip/scr_ui_tooltip.gml +++ b/scripts/scr_ui_tooltip/scr_ui_tooltip.gml @@ -2,8 +2,8 @@ /// @category UI /// @description Handles tooltip logics around the main play screen function scr_ui_tooltip() { - if ((selected != 0) && (!instance_exists(selected))) { - selected = 0; + if ((selected != noone) && (!instance_exists(selected))) { + selected = noone; } if (zoomed != 0) { exit; diff --git a/scripts/scr_unit_equip_functions/scr_unit_equip_functions.gml b/scripts/scr_unit_equip_functions/scr_unit_equip_functions.gml index c10a822a12..70df34808c 100644 --- a/scripts/scr_unit_equip_functions/scr_unit_equip_functions.gml +++ b/scripts/scr_unit_equip_functions/scr_unit_equip_functions.gml @@ -108,11 +108,12 @@ function scr_update_unit_armour(new_armour, from_armoury = true, to_armoury = tr } else { armour_quality = quality; } - var new_arm_data = get_armour_data(); if (is_struct(new_arm_data)) { if (new_arm_data.has_tag("terminator")) { - update_mobility_item(""); + var _cur_mobility_data = gear_weapon_data("mobility", mobility_item()); + if (is_struct(_cur_mobility_data) && !_cur_mobility_data.has_tag("terminator") && !_cur_mobility_data.has_tag("terminator_only")) + update_mobility_item(""); } if (new_arm_data.has_tag("dreadnought")) { @@ -391,10 +392,6 @@ function scr_update_unit_mobility_item(new_mobility_item, from_armoury = true, t return false; } } else { - if (new_mobility_item == "Jump Pack") { - LOGGER.error($"Failed to equip {new_mobility_item} for {name()} - requires armour!"); - return false; - } if (_mobility_data.has_tag("terminator") || _mobility_data.has_tag("terminator_only")) { LOGGER.error($"Failed to equip {new_mobility_item} for {name()} - requires terminator armour!"); return false; diff --git a/scripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gml b/scripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gml index 329349f63e..1ae836dbb0 100644 --- a/scripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gml +++ b/scripts/scr_unit_quick_find_pane/scr_unit_quick_find_pane.gml @@ -16,7 +16,7 @@ function UnitQuickFindPanel() constructor { static detail_slate = new DataSlateMKTwo(); view_area = "fleets"; - hover_item = "none"; + hover_item = noone; travel_target = []; travel_time = 0; travel_increments = []; @@ -43,7 +43,7 @@ function UnitQuickFindPanel() constructor { var _stars = []; for (var i = 0; i < array_length(_names); i++) { var _star = find_star_by_name(_names[i]); - if (_star != "none") { + if (_star != noone) { array_push(_stars, _star); } } @@ -250,11 +250,10 @@ function UnitQuickFindPanel() constructor { update_mission_log = function() { mission_log = []; var temp_log = []; - var p, i, problems; with (obj_star) { - for (i = 1; i <= planets; i++) { - problems = p_problem[i]; - for (p = 0; p < array_length(problems); p++) { + for (var i = 1; i <= planets; i++) { + var problems = p_problem[i]; + for (var p = 0; p < array_length(problems); p++) { if (problems[p] == "") { continue; } @@ -371,7 +370,7 @@ function UnitQuickFindPanel() constructor { var system_names = struct_get_names(garrison_log); var hover_entered = false; var any_hover = false; - if (hover_item != "none") { + if (hover_item != noone) { var loc = hover_item.location; hover_entered = scr_hit(loc[0], loc[1], loc[2], loc[3]); } @@ -431,7 +430,7 @@ function UnitQuickFindPanel() constructor { if (!hover_entered) { if (point_and_click([xx + 10, yy + 90 + (20 * i) - 2, xx + main_panel.width, yy + 90 + (20 * i) + 18])) { var star = find_star_by_name(system_names[i]); - if (star != "none") { + if (star != noone) { travel_target = [ star.x, star.y @@ -459,8 +458,8 @@ function UnitQuickFindPanel() constructor { if (!any_hover && !hover_entered) { current_hover = -1; hover_count = 0; - hover_item = "none"; - } else if (hover_item != "none") { + hover_item = noone; + } else if (hover_item != noone) { if (point_and_click(hover_item.draw(xx + 10, yy + 90 + (20 * hover_item.root_item), "Manage"))) { group_selection(garrison_log[$ system_names[hover_item.root_item]].units, {purpose: $"{system_names[hover_item.root_item]} Management", purpose_code: "manage", number: 0, system: find_star_by_name(system_names[hover_item.root_item]).id, feature: "none", planet: 0, selections: []}); } @@ -541,7 +540,7 @@ function UnitQuickFindPanel() constructor { } function HoverBox() constructor { - root_item = "none"; + root_item = noone; relative_x = 0; relative_y = 0; location = [ @@ -574,7 +573,7 @@ function update_garrison_manage() { var _planets = 0; if (struct_exists(selection_data, "system") && instance_exists(selection_data.system)) { if (struct_exists(location_viewer.garrison_log, selection_data.system.name)) { - var sys_name = selection_data.system.name; + sys_name = selection_data.system.name; } } @@ -727,7 +726,7 @@ function unload_selection() { cooldown = 8000; var boba = 0; var unload_star = find_star_by_name(selecting_location); - if (unload_star != "none") { + if (unload_star != noone) { if (unload_star.space_hulk != 1) { for (var t = 0; t < array_length(display_unit); t++) { if (man_sel[t] == 1) { @@ -753,12 +752,11 @@ function unload_selection() { /// @self Asset.GMObject.obj_controller function reset_selection_equipment() { - var _unit; for (var f = 0; f < array_length(display_unit); f++) { // If come across a man, set vih to 1 if ((man[f] == "man") && (man_sel[f] == 1)) { if (is_struct(display_unit[f])) { - _unit = display_unit[f]; + var _unit = display_unit[f]; _unit.set_default_equipment(); } } @@ -767,12 +765,11 @@ function reset_selection_equipment() { /// @self Asset.GMObject.obj_controller function add_tag_to_selection(new_tag) { - var _unit; for (var f = 0; f < array_length(display_unit); f++) { // If come across a man, set vih to 1 if ((man[f] == "man") && (man_sel[f] == 1)) { if (is_struct(display_unit[f])) { - _unit = display_unit[f]; + var _unit = display_unit[f]; _unit[$ new_tag] = !_unit[$ new_tag]; } } diff --git a/scripts/scr_unit_spawn_functions/scr_unit_spawn_functions.gml b/scripts/scr_unit_spawn_functions/scr_unit_spawn_functions.gml index e20371c459..717a5f27ba 100644 --- a/scripts/scr_unit_spawn_functions/scr_unit_spawn_functions.gml +++ b/scripts/scr_unit_spawn_functions/scr_unit_spawn_functions.gml @@ -419,20 +419,20 @@ function scr_marine_game_spawn_constructions() { } else { bionic_count = choose(1, 1, 1, 2, 3); } + var tech_heresy = irandom(49); if ((_chap_name == "Iron Hands") || (obj_ini.progenitor == ePROGENITOR.IRON_HANDS) || scr_has_disadv("Tech-Heresy")) { add_bionics("right_arm", "standard", false); bionic_count = choose(6, 6, 7, 7, 7, 8, 9); add_trait("flesh_is_weak"); - var tech_heresy = irandom(19); + tech_heresy = irandom(19); } else { bionic_count = irandom(5) + 1; if (irandom(2) == 0) { add_trait("flesh_is_weak"); } - var tech_heresy = irandom(49); } if (scr_has_disadv("Tech-Heresy")) { - var tech_heresy = irandom(10); + tech_heresy = irandom(10); technology += 4; } if (tech_heresy == 0) { diff --git a/scripts/scr_vehicle_helpers/scr_vehicle_helpers.gml b/scripts/scr_vehicle_helpers/scr_vehicle_helpers.gml index ffae74c964..d1ed904bd7 100644 --- a/scripts/scr_vehicle_helpers/scr_vehicle_helpers.gml +++ b/scripts/scr_vehicle_helpers/scr_vehicle_helpers.gml @@ -1,16 +1,15 @@ // Records or nullifies the association between a vehicle and its last ship function set_vehicle_last_ship(vehic_array, empty = false) { + var _last_ship_data = { + uid: "", + name: "", + }; if (!empty) { var vehic_ini = obj_ini.veh_lid[vehic_array[0]][vehic_array[1]]; - var _last_ship_data = { + _last_ship_data = { uid: obj_ini.ship_uid[vehic_ini], name: obj_ini.ship[vehic_ini], }; - } else { - var _last_ship_data = { - uid: "", - name: "", - }; } obj_ini.last_ship[vehic_array[0]][vehic_array[1]] = _last_ship_data; } From b966f8246036e24fe37d59bd356d658f1b83ebaf Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 29 Jun 2026 09:14:37 +0300 Subject: [PATCH 045/140] Fix dropped loop initializers from the upstream merge The upstream-merge commit kept the mod's combat/log loop bodies but resolved the surrounding declaration blocks toward the refactor, dropping the i initializers in obj_ncombat\Alarm_3 (crash on combat start: i not set before reading) and risking the same in other mod-owned files. Restore obj_ncombat\Alarm_3, Draw_0, Step_0, obj_pnunit\Alarm_3, obj_enunit\Alarm_0, obj_ini\Create_0, scr_flavor2, scr_player_combat_weapon_stacks, and scr_shoot to their committed versions. The refactor only reformatted these; the mod owns their logic. Upstream sync content is unaffected (auto-merged files, scr_PlanetData events, scr_marine_struct and obj_p_fleet blends remain). --- objects/obj_enunit/Alarm_0.gml | 4 +- objects/obj_ini/Create_0.gml | 41 ++++++++---- objects/obj_ncombat/Alarm_3.gml | 44 +++++++++++-- objects/obj_ncombat/Draw_0.gml | 8 ++- objects/obj_ncombat/Step_0.gml | 3 + objects/obj_pnunit/Alarm_3.gml | 28 ++++++-- scripts/scr_flavor2/scr_flavor2.gml | 66 +++++++++++++++---- .../scr_player_combat_weapon_stacks.gml | 41 +++++++----- scripts/scr_shoot/scr_shoot.gml | 20 +++--- 9 files changed, 187 insertions(+), 68 deletions(-) diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index fa61211d58..438018f8c4 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -159,7 +159,7 @@ if (!engaged) { repeat (instance_number(obj_pnunit) - 1) { x2 += !flank ? 10 : -10; - enemy2 = instance_nearest(x2, y, obj_pnunit); + var enemy2 = instance_nearest(x2, y, obj_pnunit); if (!target_block_is_valid(enemy2, obj_pnunit)) { continue; } @@ -197,7 +197,7 @@ if (!engaged) { var x2 = enemy.x; repeat (instance_number(obj_pnunit) - 1) { x2 += flank == 0 ? -10 : 10; - enemy2 = instance_nearest(x2, y, obj_pnunit); + var enemy2 = instance_nearest(x2, y, obj_pnunit); if (!target_block_is_valid(enemy2, obj_pnunit)) { continue; } diff --git a/objects/obj_ini/Create_0.gml b/objects/obj_ini/Create_0.gml index 742f805467..f66a3ef83e 100644 --- a/objects/obj_ini/Create_0.gml +++ b/objects/obj_ini/Create_0.gml @@ -1,3 +1,5 @@ +// Global singletons +// global.NameGenerator = new NameGenerator(); LOGGER.debug("Creating obj_ini"); // normal stuff @@ -17,6 +19,8 @@ commands = 0; heh1 = 0; heh2 = 0; +// strin=""; +// strin2=""; companies = 10; progenitor = ePROGENITOR.NONE; aspirant_trial = 0; @@ -119,6 +123,16 @@ veh_acc = array_create_2d(_max_companies, _max_vehicles, ""); // Unit Init defaults_slot = 100; +load_default_gear = function(_role_id, _role_name, _wep1, _wep2, _armour, _mobi, _gear) { + role[defaults_slot][_role_id] = _role_name; + wep1[defaults_slot][_role_id] = _wep1; + wep2[defaults_slot][_role_id] = _wep2; + armour[defaults_slot][_role_id] = _armour; + mobi[defaults_slot][_role_id] = _mobi; + gear[defaults_slot][_role_id] = _gear; + race[defaults_slot][_role_id] = 1; +}; + /// @type {Array} race = [[]]; /// @type {Array>} @@ -144,15 +158,12 @@ god = [[]]; /// @type {Array>} TTRPG = [[]]; -load_default_gear = function(_role_id, _role_name, _wep1, _wep2, _armour, _mobi, _gear) { - role[defaults_slot][_role_id] = _role_name; - wep1[defaults_slot][_role_id] = _wep1; - wep2[defaults_slot][_role_id] = _wep2; - armour[defaults_slot][_role_id] = _armour; - mobi[defaults_slot][_role_id] = _mobi; - gear[defaults_slot][_role_id] = _gear; - race[defaults_slot][_role_id] = 1; -}; +/*if (obj_creation.fleet_type=3){ + obj_controller.penitent=1; + obj_controller.penitent_max=(obj_creation.maximum_size*1000)+300; + if (obj_creation.chapter_name="Lamenters") then obj_controller.penitent_max=100300; + obj_controller.penitent_current=300; +}*/ check_number = 0; year_fraction = 0; @@ -183,6 +194,8 @@ if (global.load == -1) { /// Called from save function to take all object variables and convert them to a json savable format and return it serialize = function() { + var object_ini = self; + var _marines = array_create(0); for (var _coy = 0; _coy <= 10; _coy++) { // Iterate the company's full restored length, not a fixed 0..500, so guardsmen in overflow @@ -225,8 +238,8 @@ serialize = function() { chapter_squad_arrangement: chapter_squad_arrangement, }; - if (variable_instance_exists(self, "last_ship")) { - save_data.last_ship = last_ship; + if (struct_exists(object_ini, "last_ship")) { + save_data.last_ship = object_ini.last_ship; } var excluded_from_save = [ @@ -245,7 +258,7 @@ serialize = function() { "chapter_squad_arrangement" ]; - copy_serializable_fields(self, save_data, excluded_from_save); + copy_serializable_fields(object_ini, save_data, excluded_from_save); return save_data; }; @@ -268,13 +281,15 @@ deserialize = function(save_data) { obj_ini.chapter_squad_arrangement = json_to_gamemaker(working_directory + $"main/squads/company_squad_builds.json", json_parse); } - for (var i = 0; i < array_length(all_names); i++) { + var _len = array_length(all_names); + for (var i = 0; i < _len; i++) { var var_name = all_names[i]; if (array_contains(exclusions, var_name)) { continue; } var loaded_value = struct_get(save_data, var_name); + // LOGGER.debug($"obj_ini var: {var_name} - val: {loaded_value}"); try { variable_struct_set(obj_ini, var_name, loaded_value); } catch (e) { diff --git a/objects/obj_ncombat/Alarm_3.gml b/objects/obj_ncombat/Alarm_3.gml index a73a772141..f0249ee4ad 100644 --- a/objects/obj_ncombat/Alarm_3.gml +++ b/objects/obj_ncombat/Alarm_3.gml @@ -1,3 +1,4 @@ +// if (battle_over=1) then exit; if (defeat_message == 1) { exit; } @@ -6,12 +7,25 @@ if (wall_destroyed == 1) { wall_destroyed = 0; } -var good = 0; -var changed = 0; +var i, good, changed; +i = 0; +good = 0; +changed = 0; + +// if (messages_to_show = 24) and (messages_shown=0) then alarm[6]=75; +// if (messages_shown=105) then exit; + +/*i+=1;if (message[i]!="") then show_message(message[i]); +i+=1;if (message[i]!="") then show_message(message[i]); +i+=1;if (message[i]!="") then show_message(message[i]); +i+=1;if (message[i]!="") then show_message(message[i]); +i+=1;if (message[i]!="") then show_message(message[i]); +i+=1;if (message[i]!="") then show_message(message[i]);*/ repeat (100) { if (good == 0) { changed = 0; + i = 0; repeat (COMBAT_LOG_CAPACITY) { i += 1; @@ -96,8 +110,13 @@ if (messages == 0) { messages_shown = 999; } +/*var noloss;noloss=instance_nearest(50,300,obj_pnunit); +if (!instance_exists(noloss)) then player_forces=0; +if (instance_exists(noloss)){if (point_distance(50,300,noloss.x,noloss.y)>500) then player_forces=0;}*/ + if (instance_exists(obj_pnunit)) { - var plnear = instance_nearest(room_width, 240, obj_pnunit); + var plnear; + plnear = instance_nearest(room_width, 240, obj_pnunit); if (plnear.x < -40) { player_forces = 0; } @@ -113,7 +132,10 @@ if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { } newline_color = "yellow"; if (obj_ncombat.enemy == 6) { - for (var jims = 1; jims <= 20; jims++) { + var jims; + jims = 0; + repeat (20) { + jims += 1; if ((dead_jim[jims] != "") && (dead_jims > 0)) { newline = dead_jim[jims]; newline_color = "red"; @@ -126,7 +148,8 @@ if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { newline = string(global.chapter_name) + " at " + string(round((player_forces / player_max) * 100)) + "%"; four_show = 0; } - var plnear = instance_nearest(room_width, 240, obj_pnunit); + var plnear; + plnear = instance_nearest(room_width, 240, obj_pnunit); if (((player_forces <= 0) || (plnear.x < -40)) && (defeat_message == 0)) { defeat_message = 1; newline = string(global.chapter_name) + " Defeated"; @@ -147,7 +170,10 @@ if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (timer_stage == 5)) && (four_show == 0)) { newline_color = "yellow"; if (obj_ncombat.enemy != 6) { - for (var jims = 1; jims <= 20; jims++) { + var jims; + jims = 0; + repeat (20) { + jims += 1; if ((dead_jim[jims] != "") && (dead_jims > 0)) { newline = dead_jim[jims]; newline_color = "red"; @@ -160,7 +186,8 @@ if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (time newline = string(global.chapter_name) + " at " + string(round((player_forces / player_max) * 100)) + "%"; four_show = 1; } - var plnear = instance_nearest(room_width, 240, obj_pnunit); + var plnear; + plnear = instance_nearest(room_width, 240, obj_pnunit); if (((player_forces <= 0) || (plnear.x < -40)) && (defeat_message == 0)) { defeat_message = 1; newline = string(global.chapter_name) + " Defeated"; @@ -191,3 +218,6 @@ if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (time timer_stage = 5; exit; } + +/* */ +/* */ diff --git a/objects/obj_ncombat/Draw_0.gml b/objects/obj_ncombat/Draw_0.gml index 4cd4e4f5ae..545c40124b 100644 --- a/objects/obj_ncombat/Draw_0.gml +++ b/objects/obj_ncombat/Draw_0.gml @@ -7,7 +7,8 @@ draw_rectangle(818, 235, 1578, 666, 0); draw_set_color(CM_GREEN_COLOR); -var l = 0; +var l; +l = 0; draw_set_alpha(1); draw_rectangle(0 + l, 0 + l, 800 - l, 900 - l, 1); l += 1; @@ -139,6 +140,11 @@ if (click_stall_timer <= 0) { draw_set_halign(fa_left); draw_set_alpha(1); +// Timer +// draw_rectangle(16,464,min(16+(timer*2.026),624),472,0); + +// draw_text(320,300,"Turn: "+string(turns)); + draw_set_color(c_black); draw_set_alpha(fadein / 30); draw_rectangle(0, 0, 1600, 900, 0); diff --git a/objects/obj_ncombat/Step_0.gml b/objects/obj_ncombat/Step_0.gml index 5552091b30..5a71266b52 100644 --- a/objects/obj_ncombat/Step_0.gml +++ b/objects/obj_ncombat/Step_0.gml @@ -42,6 +42,7 @@ if (cd >= 0) { if (click_stall_timer >= 0) { click_stall_timer -= 1; } +// if (done>=1) then done+=1; if (!instance_exists(obj_enunit)) { enemy_forces = 0; @@ -98,6 +99,7 @@ if (((fugg >= 60) || (fugg2 >= 60)) && (messages_shown == 0) && (messages_to_sho exit; } + // show_message("Shown: "+string(messages_shown)+"#Messages: "+string(messages)+"#Timer Stage: "+string(timer_stage)); if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (timer_stage == 5)) && (four_show == 0)) { newline_color = "yellow"; if (obj_ncombat.enemy != 6) { @@ -131,6 +133,7 @@ if (((fugg >= 60) || (fugg2 >= 60)) && (messages_shown == 0) && (messages_to_sho exit; } +// if (player_forces>0) and (enemy_forces>0) and (battle_over=0){ if (timer_stage == 2) { fugg += 1; } diff --git a/objects/obj_pnunit/Alarm_3.gml b/objects/obj_pnunit/Alarm_3.gml index 3a30236c2e..a1f7f38b1b 100644 --- a/objects/obj_pnunit/Alarm_3.gml +++ b/objects/obj_pnunit/Alarm_3.gml @@ -1,10 +1,14 @@ try { if (obj_ncombat.started == 0) { if (men + dreads + veh <= 0) { + //LOGGER.debug($"column destroyed {x}") instance_destroy(); } - obj_ncombat.player_forces += self.men + self.veh + self.dreads; - obj_ncombat.player_max += self.men + self.veh + self.dreads; + // if (veh+dreads>0) then instance_destroy(); + if (guard == 0) { + obj_ncombat.player_forces += self.men + self.veh + self.dreads; + obj_ncombat.player_max += self.men + self.veh + self.dreads; + } //TODO centralise a method for moving units between columns /*if (men<=4) and (veh=0) and (dreads=0){// Squish leftt @@ -16,7 +20,7 @@ try { if ((obj_ncombat.red_thirst >= 2) && (obj_ncombat.battle_over == 0)) { if (men > 0) { - var miss = "", r_lost = 0; + var raar = 0, miss = "", r_lost = 0; for (var raar; raar < (men + dreads); raar++) { r_roll = floor(random(1000)) + 1; @@ -39,7 +43,9 @@ try { if ((marine_dead[raar] == 0) && (marine_type[raar] != "Death Company") && (marine_type[raar] != obj_ini.role[100][eROLE.CHAPTERMASTER]) && (r_roll <= 4)) { r_lost += 1; marine_type[raar] = "Death Company"; + //marine_attack[raar]+=1; marine_defense[raar] = 0.75; + //marine_ranged[raar]=0.75; obj_ncombat.red_thirst += 1; if (r_lost == 1) { miss += "Battle Brother " + string(obj_ini.name[marine_co[raar]][marine_id[raar]]) + ", "; @@ -57,10 +63,13 @@ try { miss = string_delete(miss, woo - 1, 2); // remove last if (string_count(", ", miss) == 1) { + /*var woo;woo=string_rpos(", ",miss); + miss=string_insert(" and",miss,woo+1);*/ + miss = string_replace(miss, ", ", " and "); } if (string_count(", ", miss) > 1) { - woo = string_rpos(", ", miss); + var woo = string_rpos(", ", miss); miss = string_delete(miss, woo - 1, 3); if (r_lost >= 3) { @@ -100,9 +109,13 @@ try { var neares = instance_nearest(x + 10, y, obj_enunit); if ((neares.men == 0) && (neares.veh > 0)) { - var norun = 0; + var norun; + norun = 0; - for (var i = 1; i <= 20; i++) { + var i; + i = 0; + repeat (20) { + i += 1; if (apa[i] >= 30) { norun = 1; } @@ -123,6 +136,9 @@ try { } } } + + /* */ + /* */ } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); } diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index e9d2c9c469..098bc1b875 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -29,10 +29,10 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo exit; } - var mes = ""; - var m1 = ""; - var m2 = ""; - var m3 = ""; + var m1, m2, m3, mes; + m1 = ""; + m2 = ""; + m3 = ""; var _hostile_range, _hostile_weapon, _hostile_shots; _hostile_range = 0; @@ -70,6 +70,19 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo var flavor = 0; + /* + if (lost_units_count="Venom Claws"){atta=200;arp=0;rang=1;spli=0;if (obj_ini.preomnor=1){atta=240;}} + if (lost_units_count="Web Spinner"){atta=40;arp=0;rang=2.1;spli=1;amm=1;} + if (lost_units_count="Warpsword"){atta=300;arp=200;rang=1;spli=1;} + if (lost_units_count="Iron Claw"){atta=300;arp=400;rang=1;spli=0;} + if (lost_units_count="Maulerfiend Claws"){atta=300;arp=300;rang=1;spli=1;} + + if (lost_units_count="Eldritch Fire"){atta=80;arp=40;rang=5.1;} + if (lost_units_count="Khorne Demon Melee"){atta=350;arp=400;rang=1;spli=1;} + if (lost_units_count="Demon Melee"){atta=250;arp=300;rang=1;spli=1;} + if (lost_units_count="Lash Whip"){atta=80;arp=0;rang=2;} + */ + if (_hostile_weapon == "Daemonette Melee") { flavor = 1; if (_hostile_shots > 1) { @@ -148,7 +161,8 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } if (_hostile_weapon == "Shoota") { flavor = 1; - var ranz = choose(1, 2, 3, 4); + var ranz; + ranz = choose(1, 2, 3, 4); if (ranz == 1) { m1 = string(_hostile_shots) + " " + string(_hostile_weapon) + "z fire away at " + string(target_type) + ". "; } @@ -279,7 +293,8 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } if (_hostile_weapon == "Slugga") { flavor = 1; - var ranz = choose(1, 2, 3, 4); + var ranz; + ranz = choose(1, 2, 3, 4); if (ranz == 1) { m1 = string(_hostile_shots) + " " + string(_hostile_weapon) + "z fire away at " + string(target_type) + ". "; } @@ -324,7 +339,8 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo if (_hostile_weapon == "Staff of Light") { flavor = 1; if (_hostile_shots == 1) { - var ranz = choose(1, 2, 3); + var ranz; + ranz = choose(1, 2, 3); if (ranz == 1) { m1 = "A " + string(_hostile_weapon) + " crackles and is swung into " + string(target_type) + ". "; } @@ -336,7 +352,8 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } } if (_hostile_shots > 1) { - var ranz = choose(1, 2, 3); + var ranz; + ranz = choose(1, 2, 3); if (ranz == 1) { m1 = string(_hostile_shots) + " Staves of Light strike at " + string(target_type) + ". "; } @@ -350,7 +367,8 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } if (_hostile_weapon == "Warscythe") { flavor = 1; - var ranz = choose(1, 2, 3); + var ranz; + ranz = choose(1, 2, 3); if (ranz == 1) { m1 = string(_hostile_shots) + " Warscythes strike at " + string(target_type) + ". "; } @@ -364,7 +382,8 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo if (_hostile_weapon == "Claws") { flavor = 1; if (_hostile_shots == 1) { - var ranz = choose(1, 2, 3); + var ranz; + ranz = choose(1, 2, 3); if (ranz == 1) { m1 = "A massive claw slices through " + string(target_type) + ". "; } @@ -376,7 +395,8 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } } if (_hostile_shots > 1) { - var ranz = choose(1, 2, 3); + var ranz; + ranz = choose(1, 2, 3); if (ranz == 1) { m1 = string(_hostile_shots) + " massive claws strike and slice at " + string(target_type) + ". "; } @@ -399,6 +419,10 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } } + // show_message(mes); + + // m2="Blah blah blah"; + if (target_type == "wall") { var _wall_destroyed = obj_nfort.hp[1] <= 0 ? true : false; @@ -416,6 +440,8 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo obj_ncombat.alarm[3] = 2; } if (obj_nfort.hp[1] <= 0) { + s = 0; + him = 0; obj_ncombat.dead_jims += 1; obj_ncombat.dead_jim[obj_ncombat.dead_jims] = "The fortified wall has been breached!"; obj_ncombat.wall_destroyed = 1; @@ -469,15 +495,22 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo var unce = 0; if (string_count(", ", m2) > 1) { - var lis = string_rpos(", ", m2); + // show_message(m2); + + var lis, y1, y2; + lis = string_rpos(", ", m2); m2 = string_delete(m2, lis, 3); // This clears the last ', ' and replaces it with the end statement if (lost_units_count > 0) { m2 += " lost."; } + // show_message(m2); + lis = string_rpos(", ", m2); // Find the new last ', ' and replace it with the and part m2 = string_delete(m2, lis, 2); + // show_message(m2); + if (string_count(",", m2) > 1) { m2 = string_insert(", and ", m2, lis); } @@ -485,18 +518,22 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo m2 = string_insert(" and ", m2, lis); } + // show_message(m2); + unce = 1; } if ((string_count(", ", m2) == 1) && (unce == 0) && (hostile_weapon != "Web Spinner")) { - var lis = string_rpos(", ", m2); + var lis, y1, y2; + lis = string_rpos(", ", m2); m2 = string_delete(m2, lis, 3); if (lost_units_count > 0) { m2 += " lost."; } } if ((string_count(", ", m2) == 1) && (unce == 0) && (hostile_weapon == "Web Spinner")) { - var lis = string_rpos(", ", m2); + var lis, y1, y2; + lis = string_rpos(", ", m2); m2 = string_delete(m2, lis, 3); if (lost_units_count > 1) { m2 += " have been incapacitated."; @@ -514,6 +551,7 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } mes = m1 + m2 + m3; + // show_message(mes); if (string_length(mes) > 3) { // Yellow when the enemy hurt your forces but destroyed nothing (damage, no kill). Kills carry diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index 3a4592724e..2dcad296f9 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -1,3 +1,6 @@ +// Script assets have changed for v2.3.0 see +// https://help.yoyogames.com/hc/en-us/articles/360005277377 for more information + /// @self Asset.GMObject.obj_pnunit function add_second_profiles_to_stack(weapon, head_role = false, unit = "none") { if (array_length(weapon.second_profiles) > 0) { @@ -266,8 +269,10 @@ function scr_player_combat_weapon_stacks() { veh = 0; men = 0; dreads = 0; - for (var i = 0; i < array_length(att); i++) { + for (i = 0; i < array_length(att); i++) { + // dudes[i]=""; dudes_num[i] = 0; + // dudes_vehicle[i]=0; att[i] = 0; apa[i] = 0; wep_num[i] = 0; @@ -275,10 +280,11 @@ function scr_player_combat_weapon_stacks() { // if (wep_owner[i]!="") and (wep_num[i]>1) then wep_owner[i]="assorted";// What if they are using two ranged weapons? Hmmmmm? } - var dreaded = false; + var dreaded = false, unit; - for (var g = 0; g < array_length(unit_struct); g++) { - var unit = unit_struct[g]; + var mobi_item; + for (g = 0; g < array_length(unit_struct); g++) { + unit = unit_struct[g]; if (is_struct(unit)) { if (unit.hp() > 0) { marine_dead[g] = 0; @@ -361,10 +367,13 @@ function scr_player_combat_weapon_stacks() { } } - var good = 0, open = 0; // Counts the number and types of marines within this object - for (var j = 0; j <= 40; j++) { + var j = 0, good = 0, open = 0; // Counts the number and types of marines within this object + for (j = 0; j <= 40; j++) { if ((dudes[j] == "") && (open == 0)) { open = j; // Determine if vehicle here + + //if (dudes[j]="Venerable "+string(obj_ini.role[100][6])) then dudes_vehicle[j]=1; + //if (dudes[j]=obj_ini.role[100][6]) then dudes_vehicle[j]=1; } if (marine_type[g] == dudes[j]) { good = 1; @@ -410,7 +419,7 @@ function scr_player_combat_weapon_stacks() { } var primary_melee = unit.melee_damage_data[3]; //collect unit melee data - weapon_stack_index = find_stack_index(primary_melee.name, head_role, unit); + var weapon_stack_index = find_stack_index(primary_melee.name, head_role, unit); if (weapon_stack_index > -1) { if (range[weapon_stack_index] > 1.9) { continue; @@ -428,7 +437,7 @@ function scr_player_combat_weapon_stacks() { } } } - for (var g = 0; g < array_length(veh_id); g++) { + for (g = 0; g < array_length(veh_id); g++) { if ((veh_id[g] > 0) && (veh_hp[g] > 0) && (veh_dead[g] != 1)) { if ((veh_id[g] > 0) && (veh_hp[g] > 0)) { veh_dead[g] = 0; @@ -437,11 +446,10 @@ function scr_player_combat_weapon_stacks() { veh++; } - // Counts the number and types of marines within this object + var j = 0, good = 0, open = 0; // Counts the number and types of marines within this object if (veh_dead[g] != 1) { - var good = 0; - var open = 0; - for (var j = 1; j <= 40; j++) { + repeat (40) { + j += 1; if ((dudes[j] == "") && (open == 0)) { open = j; } @@ -458,8 +466,9 @@ function scr_player_combat_weapon_stacks() { } } + var j = 0, good = 0, open = 0, weapon, vehicle_weapon_set; if (veh_dead[g] != 1) { - var vehicle_weapon_set = [ + vehicle_weapon_set = [ veh_wep1[g], veh_wep2[g], veh_wep3[g] @@ -467,9 +476,9 @@ function scr_player_combat_weapon_stacks() { for (var wep_slot = 0; wep_slot < 3; wep_slot++) { var weapon_check = vehicle_weapon_set[wep_slot]; if (weapon_check != "") { - var weapon = gear_weapon_data("weapon", weapon_check, "all", false, "standard"); + weapon = gear_weapon_data("weapon", weapon_check, "all", false, "standard"); if (is_struct(weapon)) { - for (var j = 0; j <= 40; j++) { + for (j = 0; j <= 40; j++) { if (wep[j] == "" || wep[j] == weapon.name) { add_data_to_stack(j, weapon,,, "vehicle"); break; @@ -493,7 +502,7 @@ function scr_player_combat_weapon_stacks() { var h = 0; for (var i = 0; i < array_length(unit_struct); i++) { if (h == 0) { - var unit = unit_struct[i]; + unit = unit_struct[i]; if (!is_struct(unit)) { continue; } diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index 49a02bd51b..267c0f784e 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -1,11 +1,11 @@ -/// @self Id.Instance.obj_enunit|Id.Instance.obj_pnunit -/// @param {Real} weapon_index_position Weapon number -/// @param {Id.Instance.obj_enunit|Id.Instance.obj_pnunit} target_object Target object -/// @param {Real} target_type Target dudes -/// @param {String} damage_data "att" or "arp" or "highest" -/// @param {String} melee_or_ranged melee or ranged function scr_shoot(weapon_index_position, target_object, target_type, damage_data, melee_or_ranged) { try { + // weapon_index_position: Weapon number + // target_object: Target object + // target_type: Target dudes + // damage_data: "att" or "arp" or "highest" + // melee_or_ranged: melee or ranged + // This massive clusterfuck of a script uses the newly determined weapon and target data to attack and assign damage var hostile_type; var hostile_damage; @@ -19,11 +19,12 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat } if ((weapon_index_position >= 0) && instance_exists(target_object) && (owner == 2)) { + var stop, damage_type, doom; var shots_fired = wep_num[weapon_index_position]; if (shots_fired == 0 || ammo[weapon_index_position] == 0) { exit; } - var doom = 0; + doom = 0; if ((shots_fired != 1) && (melee_or_ranged != "melee")) { switch (obj_ncombat.enemy) { case eFACTION.ECCLESIARCHY: @@ -51,8 +52,8 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat doom = 1; } - var damage_type = ""; - var stop = 0; + damage_type = ""; + stop = 0; if (ammo[weapon_index_position] > 0) { ammo[weapon_index_position] -= 1; @@ -183,6 +184,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat } if (instance_exists(target_object) && (owner == eFACTION.PLAYER)) { + // LOGGER.debug("{0}, {1}, {2}, {3}, {4}", wep_num[weapon_index_position], wep[weapon_index_position], splash[weapon_index_position], range[weapon_index_position], att[weapon_index_position]) var shots_fired = 0; var stop = 0; var damage_type = ""; From 9be3199353f89ee33e8b38ec28aa51ca33dd2e26 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 29 Jun 2026 12:55:24 +0300 Subject: [PATCH 046/140] Crash fix. Fixed crash that was happening at random --- scripts/scr_promote/scr_promote.gml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/scr_promote/scr_promote.gml b/scripts/scr_promote/scr_promote.gml index fe90a8191e..90906d38e4 100644 --- a/scripts/scr_promote/scr_promote.gml +++ b/scripts/scr_promote/scr_promote.gml @@ -215,7 +215,7 @@ function draw_popup_promotion() { var role_x = 0; role_y = 0; if (target_comp != -1) { - for (var r = 1; r <= 11; r++) { + for (var r = 1; r < array_length(role_name); r++) { if (role_name[r] != "") { draw_set_alpha(1); check = " "; From 15c914500301cbbdd64427cf7f57944df2bd2537 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 29 Jun 2026 17:54:59 +0300 Subject: [PATCH 047/140] Fix build-menu crash from half-initialised obj_temp_build + Recruit Guard button obj_temp_build is created via instance_create (Create runs immediately) with planet assigned only on the following line, so Create's line-2 planet read hit an unset variable and aborted before isnew was set. scr_menu_clear_up then crashed reading isnew on the half-built instance. Guard the planet read in Create so it always completes, and guard the isnew read in scr_menu_clear_up with variable_instance_exists as a backstop. Normal building is unchanged; planet is still set right after creation. Repurpose the obsolete Recruit Guard button so it raises real units instead of filling the abstract p_guardsmen pool. On a player-owned world with at least 1000 PDF, one click draws 1000 from that planet's PDF and spawns 1000 individual Guardsman units at the home planet via scr_add_man, the same path the Sector Governor uses. Keeps the 50 requisition cost. Adds an owner re-check in the handler and runs the spawn loop under obj_controller scope. Guardsmen only: no Sergeants, Heavy Weapons Teams or vehicles. --- objects/obj_star_select/Create_0.gml | 22 ++++++++++++------- objects/obj_temp_build/Create_0.gml | 2 +- .../scr_controller_helpers.gml | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/objects/obj_star_select/Create_0.gml b/objects/obj_star_select/Create_0.gml index 3a90a26f6c..45f412b0b4 100644 --- a/objects/obj_star_select/Create_0.gml +++ b/objects/obj_star_select/Create_0.gml @@ -42,17 +42,23 @@ colonist_button.bind_method = function() { new_colony_fleet(doner[0], doner[1], target.id, obj_controller.selecting_planet, "bolster_population"); }; -// Recruit Guard: raise Imperial Guard from this world's Defense Force (PDF) in fixed -// elements of 1000, so it cannot be spammed off civilians and is bounded by the PDF on -// hand. Costs a small 50 requisition per 1000. Recruited Guard go into the deployable -// pool (p_guardsmen) to embark and deploy. -guard_recruit_button = new PurchaseButton(50); -guard_recruit_button.update({tooltip: "Raise 1000 Imperial Guard from this world's Defense Force (PDF). They join the deployable Guard pool, ready to embark and deploy. Drawn in fixed elements of 1000. /n Costs 50 requisition, requires at least 1000 PDF", label: "Recruit Guard", target: target}); +// Recruit Guard: levy Imperial Guard from a world's Planetary Defense Force. Player +// worlds only (you can only mobilise your own PDF), drawn in fixed elements of 1000 and +// bounded by the PDF on hand so it cannot be spammed. Costs 50 requisition per 1000. +// Each PDF trooper raised joins the chapter as an individual Guardsman unit mustering at +// the home planet, the same singular Guardsmen the Sector Governor supplies. Guardsmen +// only: no Sergeants, Heavy Weapons Teams or vehicles. +guard_recruit_button = new PurchaseButton(100); +guard_recruit_button.update({tooltip: "Levy 1000 Imperial Guard from this world's PDF. Each joins your chapter as an individual Guardsman, mustering at your home planet. Drawn in fixed elements of 1000. /n Costs 50 requisition, requires personal control of the planet and at least 1000 PDF", label: "Recruit Guard", target: target}); guard_recruit_button.bind_method = function() { var _p = obj_controller.selecting_planet; - if (target.p_pdf[_p] >= 1000) { + if (target.p_owner[_p] == eFACTION.PLAYER && target.p_pdf[_p] >= 1000) { target.p_pdf[_p] -= 1000; - target.p_guardsmen[_p] += 1000; + with (obj_controller) { + repeat (1000) { + scr_add_man("Guardsman", 0, "", "", 0, true, "home_planet", {skip_company_order: true}); + } + } } }; diff --git a/objects/obj_temp_build/Create_0.gml b/objects/obj_temp_build/Create_0.gml index 75d57c24b6..23d429f387 100644 --- a/objects/obj_temp_build/Create_0.gml +++ b/objects/obj_temp_build/Create_0.gml @@ -1,5 +1,5 @@ target = noone; -planet = (planet > 0) ? planet : 0; +planet = (variable_instance_exists(id, "planet") && planet > 0) ? planet : 0; lair = false; arsenal = false; diff --git a/scripts/scr_controller_helpers/scr_controller_helpers.gml b/scripts/scr_controller_helpers/scr_controller_helpers.gml index d68a3a44aa..d0e21fe3be 100644 --- a/scripts/scr_controller_helpers/scr_controller_helpers.gml +++ b/scripts/scr_controller_helpers/scr_controller_helpers.gml @@ -47,7 +47,7 @@ function scr_menu_clear_up(specific_area_function) { } // 136 ; if (instance_exists(obj_temp_build)) { - if (obj_temp_build.isnew) { + if (variable_instance_exists(obj_temp_build, "isnew") && obj_temp_build.isnew) { exit; } } From c7d21e7135ebb4fad40a7576c27881c166d2e926 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 29 Jun 2026 23:16:01 +0300 Subject: [PATCH 048/140] Fix fleet ETA ignoring warp lanes on actual travel calculate_fleet_eta only computed the warp-lane multiplier when star1/star2 were both omitted (the map preview path). Every real-travel caller passes a boolean (from_star, is_orbiting(), _target_is_sys, true/false) in those slots, so warp_lane stayed 0: lanes gave no speed bonus, the no-lane x2 penalty always applied, and the destination warp-storm check was skipped via an early return. Resolve both endpoints to real stars from the coordinates regardless of the passed args, compute the lane, apply bonus/penalty, and always run the storm check. Fixes all fleet callers so real transit matches the preview and lane routes are actually faster. Upstream has the same bug. --- .../scr_fleet_functions.gml | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/scripts/scr_fleet_functions/scr_fleet_functions.gml b/scripts/scr_fleet_functions/scr_fleet_functions.gml index 67785568b5..c540b26ba9 100644 --- a/scripts/scr_fleet_functions/scr_fleet_functions.gml +++ b/scripts/scr_fleet_functions/scr_fleet_functions.gml @@ -274,14 +274,15 @@ function load_unit_to_fleet(fleet, unit) { /// @param {Id.Instance.obj_star} star2 /// @param {Bool} warp_able function calculate_fleet_eta(xx, yy, xxx, yyy, fleet_speed, star1 = noone, star2 = noone, warp_able = false) { - var warp_lane = 0; - if (star1 == noone && star2 == noone) { - star1 = instance_nearest(xx, yy, obj_star); - star2 = instance_nearest(xxx, yyy, obj_star); - warp_lane = determine_warp_join(star1.id, star2.id); - } else if (star1 == noone) { - star1 = instance_nearest(xx, yy, obj_star); - } + // Always resolve both endpoints to real star instances from the coordinates. + // Every real-travel caller historically passes booleans (from_star, is_orbiting(), + // true/false) in the star1/star2 slots, which left warp_lane at 0 and made actual + // jumps ignore lanes entirely (doubling the time and skipping the storm check), while + // the map preview, which omits these args, computed lanes correctly. Resolving from + // coords here ignores those bad args and keeps the preview and the real transit in sync. + star1 = instance_nearest(xx, yy, obj_star); + star2 = instance_nearest(xxx, yyy, obj_star); + var warp_lane = determine_warp_join(star1.id, star2.id); var eta = floor(point_distance(xx, yy, xxx, yyy) / fleet_speed) + 1; if (!warp_lane) { eta *= 2; @@ -289,17 +290,10 @@ function calculate_fleet_eta(xx, yy, xxx, yyy, fleet_speed, star1 = noone, star2 if (warp_lane && warp_able) { eta = ceil(eta / warp_lane); } - if (!star2) { - return eta; - } //check end location for warp storm - if (instance_exists(star2)) { - if (star2.object_index == obj_star) { - if (star2.storm) { - eta += 10000; - } - } + if (instance_exists(star2) && (star2.object_index == obj_star) && star2.storm) { + eta += 10000; } return eta; } From 7f7f5cabf5dbb3f9b403dbfe16b557a55d2df9fa Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 29 Jun 2026 23:37:57 +0300 Subject: [PATCH 049/140] Fix obj_controller NaN-coordinate crash on room change A fleet whose x/y went NaN before the action_eta divide-by-zero fix stays NaN (point_distance keeps propagating it) and gets copied into the persistent obj_controller via the fleet-focus path. obj_controller then carries the NaN across rooms and crashes the collision grid when obj_cursor is recreated (invalid -nan bound). scr_load now sanitizes NaN x/y on obj_controller and all fleets at load time, snapping broken instances to a valid star, and the obj_p_fleet Alarm_3 focus copy only runs when the fleet position is finite, so a NaN can never reach the controller again. Repairs existing affected saves. --- objects/obj_p_fleet/Alarm_3.gml | 2 +- scripts/scr_load/scr_load.gml | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/objects/obj_p_fleet/Alarm_3.gml b/objects/obj_p_fleet/Alarm_3.gml index d88b008cad..2a23b39138 100644 --- a/objects/obj_p_fleet/Alarm_3.gml +++ b/objects/obj_p_fleet/Alarm_3.gml @@ -1,4 +1,4 @@ -if (obj_controller.zoomed == 1) { +if (obj_controller.zoomed == 1 && !is_nan(self.x) && !is_nan(self.y)) { obj_controller.x = self.x; obj_controller.y = self.y; } diff --git a/scripts/scr_load/scr_load.gml b/scripts/scr_load/scr_load.gml index ff3f006676..06b5d12aa4 100644 --- a/scripts/scr_load/scr_load.gml +++ b/scripts/scr_load/scr_load.gml @@ -144,6 +144,31 @@ function scr_load(save_part, save_id) { obj_event_log.event = obj_saveload.GameSave.EventLog; LOGGER.info("EVENT LOG Loaded"); + // Sanitize NaN coordinates baked into older saves. A fleet whose x/y went NaN + // (from the pre-fix action_eta divide-by-zero) keeps re-baking that NaN into + // obj_controller through the fleet-focus copy, which then crashes the collision + // grid when obj_cursor is recreated on a room change. Snap any broken instance + // back to a valid star so the bad value can never reach the controller again. + var _anchor = instance_nearest(0, 0, obj_star); + var _ax = instance_exists(_anchor) ? _anchor.x : 0; + var _ay = instance_exists(_anchor) ? _anchor.y : 0; + with (obj_p_fleet) { + if (is_nan(x) || is_nan(y)) { + x = _ax; + y = _ay; + } + } + with (obj_en_fleet) { + if (is_nan(x) || is_nan(y)) { + x = _ax; + y = _ay; + } + } + if (is_nan(obj_controller.x) || is_nan(obj_controller.y)) { + obj_controller.x = _ax; + obj_controller.y = _ay; + } + obj_saveload.alarm[1] = 5; obj_controller.invis = false; global.load = -1; From ef73a7555da9a03055438a1a38c3e930af3f7b76 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 30 Jun 2026 14:35:18 +0300 Subject: [PATCH 050/140] Fixes planet heretic/traitor forces being unbeatable --- objects/obj_ncombat/Alarm_5.gml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/objects/obj_ncombat/Alarm_5.gml b/objects/obj_ncombat/Alarm_5.gml index beb08c7551..4c445c459b 100644 --- a/objects/obj_ncombat/Alarm_5.gml +++ b/objects/obj_ncombat/Alarm_5.gml @@ -572,7 +572,20 @@ if (defeat == 0 && _reduce_power) { } if (enemy >= 5) { - p_data.edit_forces(enemy, new_power); + // Combat numbers the Chaos/Heretic pair opposite to eFACTION. enemy 10 (eFACTION.CHAOS) + // is fought as the Heretic/traitor force and its strength is read from p_traitors above; + // enemy 11 (eFACTION.HERETICS) is fought as the Chaos Space Marine force read from p_chaos. + // edit_forces maps by eFACTION (CHAOS -> p_chaos, HERETICS -> p_traitors), so passing the + // raw combat enemy wrote the reduced strength into the OTHER slot, leaving the force that + // was actually fought untouched and often inflating the other one. Swap the pair so the + // reduction lands on the same force the battle was drawn from. Mirrors the space_hulk fix. + var _reduce_faction = enemy; + if (enemy == eFACTION.CHAOS) { + _reduce_faction = eFACTION.HERETICS; + } else if (enemy == eFACTION.HERETICS) { + _reduce_faction = eFACTION.CHAOS; + } + p_data.edit_forces(_reduce_faction, new_power); } if ((enemy != 2) && (string_count("cs_meeting_battle", battle_special) == 0)) { From bdbb51f98b0e329dc64a70b7b0fe5643701a0889 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 2 Jul 2026 18:51:40 +0300 Subject: [PATCH 051/140] Fix equip popup terminator blocks, dread lascannon default, Omnissian Axe availability - scr_reequip_units: remove blanket rule that invalidated all weapon-two changes for Terminator/Tartaros/Dreadnought armour whenever a mobility item was equipped. It hard-locked the second weapon slot for terminators with a Cyclone Missile System or Servo-arm/harness with no warning text, even for light weapons. The burden system already prices these items in via hands cap maluses and encumbrance penalties. - scr_reequip_units: mixed armour selections collapse to "Assortment", which blanket-rejected terminator_only mobility items even when every selected unit wore terminator plate (e.g. Tartaros + Indomitus). Now checks each selected unit's real armour tags. - scr_initialize_custom: dreadnought default wep2 was "Lascannon", which is not in the dreadnought ranged weapon list, so starting dreads carried a weapon they could never re-equip. Changed to "Twin Linked Lascannon". - Omnissian Axe: added to the marine melee equip list and given value 80, seller mechanicus, forge requirement power_1 in weapons.json so it is buyable and forgeable. Previously techpriest ordination pulled it from an empty armoury and alerted "Not enough equipment". All four bugs exist upstream.Equip bug fixes --- datafiles/data/weapons.json | 9 ++++- .../scr_get_item_names/scr_get_item_names.gml | 5 ++- .../scr_initialize_custom.gml | 4 +- .../scr_reequip_units/scr_reequip_units.gml | 40 ++++++++++++++----- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index f4a3054d91..dc528a6d7d 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -2005,6 +2005,12 @@ }, "range": 1, "ranged_hands": 0, + "requires_to_forge": [ + "power_1" + ], + "sellers": [ + "mechanicus" + ], "specials": { "combi_tool": 1 }, @@ -2014,7 +2020,8 @@ "axe", "savage", "boarding 3" - ] + ], + "value": 80 }, "Phaestos Flamer": { "abbreviation": "PhFlmr", diff --git a/scripts/scr_get_item_names/scr_get_item_names.gml b/scripts/scr_get_item_names/scr_get_item_names.gml index ee9430e912..efd9fbdc29 100644 --- a/scripts/scr_get_item_names/scr_get_item_names.gml +++ b/scripts/scr_get_item_names/scr_get_item_names.gml @@ -62,7 +62,7 @@ function push_marine_ranged_weapons_item_names(_item_names) { /// @param {array} _item_names - The list to append to. /// @returns {void} function push_marine_melee_weapons_item_names(_item_names) { - var item_count = 19; + var item_count = 20; var initial_size = array_length(_item_names); array_resize(_item_names, initial_size + item_count); @@ -82,10 +82,11 @@ function push_marine_melee_weapons_item_names(_item_names) { _item_names[@ index++] = "Thunder Hammer"; _item_names[@ index++] = "Heavy Thunder Hammer"; _item_names[@ index++] = "Crozius Arcanum"; + _item_names[@ index++] = "Omnissian Axe"; _item_names[@ index++] = "Boarding Shield"; _item_names[@ index++] = "Storm Shield"; _item_names[@ index++] = "Bolt Pistol"; - _item_names[@ index++] = "Bolter"; // 19 + _item_names[@ index++] = "Bolter"; // 20 } /// @description This function appends the list of marine armour items to the given list. diff --git a/scripts/scr_initialize_custom/scr_initialize_custom.gml b/scripts/scr_initialize_custom/scr_initialize_custom.gml index 7bee2adb51..99780f0f8e 100644 --- a/scripts/scr_initialize_custom/scr_initialize_custom.gml +++ b/scripts/scr_initialize_custom/scr_initialize_custom.gml @@ -1475,7 +1475,9 @@ function scr_initialize_custom() { load_default_gear(eROLE.VETERAN, "Veteran", "Combiflamer", "Combat Knife", STR_ANY_POWER_ARMOUR, "", ""); load_default_gear(eROLE.TERMINATOR, "Terminator", "Power Fist", "Storm Bolter", "Terminator Armour", "", ""); load_default_gear(eROLE.CAPTAIN, "Captain", "Power Sword", "Bolt Pistol", STR_ANY_POWER_ARMOUR, "", "Iron Halo"); - load_default_gear(eROLE.DREADNOUGHT, "Dreadnought", "Close Combat Weapon", "Lascannon", "Dreadnought", "", ""); + // "Lascannon" is not in the dreadnought ranged weapon list (push_dreadnought_ranged_weapons_item_names), + // so start-of-game dreads spawned with it could never re-equip one. Use the dread-pattern twin-linked version. + load_default_gear(eROLE.DREADNOUGHT, "Dreadnought", "Close Combat Weapon", "Twin Linked Lascannon", "Dreadnought", "", ""); load_default_gear(eROLE.CHAMPION, "Champion", "Power Sword", "Bolt Pistol", STR_ANY_POWER_ARMOUR, "", "Combat Shield"); load_default_gear(eROLE.TACTICAL, "Tactical", "Bolter", "Combat Knife", STR_ANY_POWER_ARMOUR, "", ""); load_default_gear(eROLE.DEVASTATOR, "Devastator", "", "Combat Knife", STR_ANY_POWER_ARMOUR, "", ""); diff --git a/scripts/scr_reequip_units/scr_reequip_units.gml b/scripts/scr_reequip_units/scr_reequip_units.gml index 45bbe63069..aa89acba82 100644 --- a/scripts/scr_reequip_units/scr_reequip_units.gml +++ b/scripts/scr_reequip_units/scr_reequip_units.gml @@ -523,12 +523,12 @@ function draw_popup_equip() { n_good2 = 0; warning = "Only " + string(obj_ini.role[100][6]) + " can use Close Combat Weapons."; } - if (((string_count("Terminator", n_armour) > 0) || (string_count("Tartaros", n_armour) > 0) || (string_count("Dreadnought", n_armour) > 0)) && (n_mobi != "")) { - n_good2 = 0; - } - if (((string_count("Terminator", o_armour) > 0) || (string_count("Tartaros", o_armour) > 0) || (string_count("Dreadnought", o_armour) > 0)) && (n_mobi != "")) { - n_good2 = 0; - } + // Removed the blanket block that invalidated any weapon-two change for + // Terminator/Tartaros/Dreadnought armour whenever a mobility item was equipped. + // It hard-locked the second weapon slot for terminators with a Cyclone Missile + // System or Servo-arm/harness (with no warning text), even for light weapons. + // The burden system in scr_marine_struct already prices these items in via + // their melee_hands/ranged_hands cap maluses and encumbrance penalties. } } if ((equipmet_area == eEQUIPMENT_SLOT.ARMOUR) && is_struct(armour_data)) { @@ -641,12 +641,32 @@ function draw_popup_equip() { warning = "Cannot use this without Dreadnought Armour."; } } else if (!is_struct(armour_data) && is_struct(mobility_data)) { + // Mixed armour selections collapse n_armour to "Assortment", so armour_data is + // not a struct even when every selected unit wears terminator plate (e.g. one in + // Tartaros and one in Indomitus). Check each selected unit's real armour tags + // instead of blanket-rejecting terminator/dreadnought mobility items. if (mobility_data.has_tag("terminator") || mobility_data.has_tag("terminator_only")) { - n_good5 = 0; - warning = "Cannot use this without Terminator Armour."; + for (var g = 0; g < array_length(obj_controller.display_unit); g++) { + if (obj_controller.man_sel[g] == 1 && is_struct(obj_controller.display_unit[g])) { + var _unit_armour_data = obj_controller.display_unit[g].get_armour_data(); + if (!is_struct(_unit_armour_data) || !_unit_armour_data.has_tag("terminator")) { + n_good5 = 0; + warning = "Cannot use this without Terminator Armour."; + break; + } + } + } } else if (mobility_data.has_tag("dreadnought") || mobility_data.has_tag("dreadnought_only")) { - n_good5 = 0; - warning = "Cannot use this without Dreadnought Armour."; + for (var g = 0; g < array_length(obj_controller.display_unit); g++) { + if (obj_controller.man_sel[g] == 1 && is_struct(obj_controller.display_unit[g])) { + var _unit_armour_data = obj_controller.display_unit[g].get_armour_data(); + if (!is_struct(_unit_armour_data) || !_unit_armour_data.has_tag("dreadnought")) { + n_good5 = 0; + warning = "Cannot use this without Dreadnought Armour."; + break; + } + } + } } } } From 8a09701e344d7746d8a3e21ba4dcc13be34d8e52 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 2 Jul 2026 19:01:59 +0300 Subject: [PATCH 052/140] Fix bombardment hitting wrong Chaos/Traitor arrays and false annihilation reports - scr_bomb_world: bombarding target 10 ("Chaos") read and reported strength from planet_forces[eFACTION.CHAOS] (p_chaos + p_demons) but wrote the reduction to p_traitors. The bombarded force never shrank, p_traitors could go negative, and the report could claim total annihilation while the chaos force was intact. Case 10 now reduces p_chaos with spillover into p_demons, clamped at 0. - scr_bomb_world: target 11 (p_traitors) was selectable but had no name, no protection entry, and no reduction case, so bombarding it reported losses while changing nothing. Added protection (tier 2) and a clamped p_traitors reduction. - scr_bomb_world: zero-reduction bombardments printed both "no losses" and "some losses ... decreased by 0". The losses text is now skipped when reduction is 0. - scr_PlanetData: suffer_navy_bombard set p_chaos = max(0, p_traitors - 1), reading the wrong array; a world with more traitors than chaos had its chaos force RAISED by navy bombardment. Now reduces p_chaos from p_chaos. - obj_bomb_select: added "Traitors" display name for bombard target 11. Both root bugs exist verbatim in upstream main. Note the bombard path is keyed by raw eFACTION (planet_forces[10] = p_chaos + p_demons, [11] = p_traitors), unlike the inverted combat enemy numbering fixed in obj_ncombat Alarm_5. --- objects/obj_bomb_select/Draw_0.gml | 3 ++ scripts/scr_PlanetData/scr_PlanetData.gml | 4 +- scripts/scr_bomb_world/scr_bomb_world.gml | 64 +++++++++++++++-------- 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/objects/obj_bomb_select/Draw_0.gml b/objects/obj_bomb_select/Draw_0.gml index 5ff3d97ced..60faedc28b 100644 --- a/objects/obj_bomb_select/Draw_0.gml +++ b/objects/obj_bomb_select/Draw_0.gml @@ -82,6 +82,9 @@ if ((max_ships > 0) && instance_exists(obj_star_select)) { case 10: t_name = "Chaos"; break; + case 11: + t_name = "Traitors"; + break; case 13: t_name = "Necrons"; break; diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index 7db5d3be33..a5a17db3b9 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -1524,7 +1524,9 @@ function PlanetData(planet, system) constructor { strength = strength > 2 ? 2 : 0; if (system.p_chaos[planet] > 0) { - system.p_chaos[planet] = max(0, system.p_traitors[planet] - 1); + // Was max(0, p_traitors - 1): read the wrong array, so a world with more + // traitors than chaos had its chaos force RAISED by navy bombardment. + system.p_chaos[planet] = max(0, system.p_chaos[planet] - 1); } else if (system.p_traitors[planet] > 0) { system.p_traitors[planet] = max(0, system.p_traitors[planet] - 2); } diff --git a/scripts/scr_bomb_world/scr_bomb_world.gml b/scripts/scr_bomb_world/scr_bomb_world.gml index 30b56bdf62..5287b7e24b 100644 --- a/scripts/scr_bomb_world/scr_bomb_world.gml +++ b/scripts/scr_bomb_world/scr_bomb_world.gml @@ -103,10 +103,12 @@ function scr_bomb_world(bombard_target_faction, bombard_ment_power, target_stren bombard_protection = 2; } break; - // case 11: - // txt2="##The Chaos Space Marine forces are difficult to bombard; "; - // bombard_protection=3; - // break; + case 11: + // Traitor Guard: renegade IG, "competent protection" tier like loyalist IG + // and standard chaos forces per the bombard_protect_scores comment below. + txt2 = "##The Traitor forces are suitably fortified; "; + bombard_protection = 2; + break; // case 12: // txt2="##The Daemonic forces are incredibly difficult to bombard; "; // bombard_protection=4; @@ -170,22 +172,27 @@ function scr_bomb_world(bombard_target_faction, bombard_ment_power, target_stren // if (rel>0 && rel<=20 && (target_strength-strength_reduction)>0){ // txt2+=" minor losses from the bombardment, decreasing "+string(strength_reduction)+" stages."; // ? - if ((target_strength - strength_reduction) <= 0) { - txt2 += " total annihilation from the bombardment and are wiped clean from the planet."; - } else { - var _losses_text = ""; - if (rel > 0 && rel <= 20) { - _losses_text = "minor losses"; - } else if (rel > 20 && rel <= 40) { - _losses_text = "moderate losses"; - } else if (rel > 40 && rel <= 60) { - _losses_text = "heavy losses"; - } else if (rel > 60 && (target_strength - strength_reduction) > 0) { - _losses_text = "devastating losses"; + // Only describe losses when there was a reduction; otherwise the "no losses" line + // above already covered it and this used to append a second, contradictory + // "some losses ... decreased by 0" sentence. + if (strength_reduction > 0) { + if ((target_strength - strength_reduction) <= 0) { + txt2 += " total annihilation from the bombardment and are wiped clean from the planet."; } else { - _losses_text = "some losses"; + var _losses_text = ""; + if (rel > 0 && rel <= 20) { + _losses_text = "minor losses"; + } else if (rel > 20 && rel <= 40) { + _losses_text = "moderate losses"; + } else if (rel > 40 && rel <= 60) { + _losses_text = "heavy losses"; + } else if (rel > 60 && (target_strength - strength_reduction) > 0) { + _losses_text = "devastating losses"; + } else { + _losses_text = "some losses"; + } + txt2 += $" {_losses_text} from the bombardment, having presence decreased by {strength_reduction}."; } - txt2 += $" {_losses_text} from the bombardment, having presence decreased by {strength_reduction}."; } // 135; ? @@ -254,12 +261,23 @@ function scr_bomb_world(bombard_target_faction, bombard_ment_power, target_stren case 9: system.p_tyranids[planet] -= strength_reduction; break; - case 10: - system.p_traitors[planet] -= strength_reduction; + case 10: { + // planet_forces[eFACTION.CHAOS] (the strength this bombardment was aimed + // and reported against) is p_chaos + p_demons, but this wrote p_traitors, + // the eFACTION.HERETICS force. The bombarded Chaos force never shrank (and + // p_traitors could go negative) while the report could claim total + // annihilation. Reduce p_chaos first, spill any remainder into p_demons. + var _chaos_cut = min(system.p_chaos[planet], strength_reduction); + system.p_chaos[planet] -= _chaos_cut; + var _demon_spill = strength_reduction - _chaos_cut; + if (_demon_spill > 0) { + system.p_demons[planet] = max(0, system.p_demons[planet] - _demon_spill); + } + break; + } + case 11: + system.p_traitors[planet] = max(0, system.p_traitors[planet] - strength_reduction); break; - // case 11: - // system.p_csm[planet]-=strength_reduction; - // break; // case 12: // system.p_demons[planet]-=strength_reduction; // break; From 9c420092d377225bf00769a51742368068c6cfb4 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 2 Jul 2026 19:20:16 +0300 Subject: [PATCH 053/140] =?UTF-8?q?Merge=20upstream=20main=200a47a1b=20(33?= =?UTF-8?q?=20commits)=20preserving=20Auxilia=20mod;=20includes=20bombardm?= =?UTF-8?q?ent=20fix=20Commit=20description:=20Content-level=20merge=20of?= =?UTF-8?q?=20Adeptus-Dominus/main=20up=20to=200a47a1b=20onto=20the=20mod,?= =?UTF-8?q?=20built=20as=20three-way=20merges=20(base=208218b2c)=20per=20f?= =?UTF-8?q?ile.=20Highlights=20from=20upstream:=20ncombat=20cleanup=20and?= =?UTF-8?q?=20eFACTION=20standardization,=20max=20health=20rework,=20fleet?= =?UTF-8?q?=20ETA=20repair,=20space=20combat=20zoom/speed=20fixes,=20Armam?= =?UTF-8?q?entarium=20sell=20price=20fix,=20promotion=20and=20temp=5Fbuild?= =?UTF-8?q?=20fixes,=20.yyp=20cleanup,=20new=20scr=5Fship=5Ffunctions=20sc?= =?UTF-8?q?ript.=20=20Merge=20decisions:=20-=20Kept=20the=20Chaos/Heretic?= =?UTF-8?q?=20pair=20translation=20in=20obj=5Fncombat=20Alarm=5F5:=20upstr?= =?UTF-8?q?eam's=20=20=20standardization=20renamed=20literals=20but=20the?= =?UTF-8?q?=20inverted=20read=20plus=20raw=20edit=5Fforces=20write=20=20?= =?UTF-8?q?=20remain,=20so=20the=20ground-assault=20bug=20still=20exists?= =?UTF-8?q?=20upstream.=20-=20Dropped=20our=20fleet=20ETA,=20promotion=20l?= =?UTF-8?q?oop,=20and=20temp=5Fbuild=20fixes=20in=20favor=20of=20=20=20ups?= =?UTF-8?q?tream's=20equivalents.=20-=20Re-anchored=20Guard=20Squad=20/=20?= =?UTF-8?q?Heavy=20Weapons=20Team=20pooled=20health=20into=20the=20reworke?= =?UTF-8?q?d=20=20=20max=5Fhealth;=20preserved=20AP=20look-behind=20screen?= =?UTF-8?q?ing,=20scrollable=20combat=20log,=20stage=20=20=20timeout=20gua?= =?UTF-8?q?rds,=20and=20combat=5Femit=5Fenemy=5Fstatus=20through=20upstrea?= =?UTF-8?q?m's=20refactors.=20-=20Re-applied=20the=20suffer=5Fnavy=5Fbomba?= =?UTF-8?q?rd=20p=5Fchaos=20fix=20and=20included=20the=20scr=5Fbomb=5Fworl?= =?UTF-8?q?d=20/=20=20=20obj=5Fbomb=5Fselect=20bombardment=20fixes.=20-=20?= =?UTF-8?q?obj=5Ffleet=20KeyPress=5F32=20emptied=20(upstream=20deleted=20t?= =?UTF-8?q?he=20file=20but=20obj=5Ffleet.yy=20still=20=20=20lists=20the=20?= =?UTF-8?q?event).=20Workflows=20intentionally=20remain=20absent=20from=20?= =?UTF-8?q?this=20fork.=20Upstream's=20=20=20deleted=20notes=20files=20are?= =?UTF-8?q?=20unreferenced=20by=20the=20merged=20.yyp=20and=20can=20be=20r?= =?UTF-8?q?emoved=20manually.Upstream=20syncZIP=C2=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Content-level merge of Adeptus-Dominus/main up to 0a47a1b onto the mod, built as three-way merges (base 8218b2c) per file. Highlights from upstream: ncombat cleanup and eFACTION standardization, max health rework, fleet ETA repair, space combat zoom/speed fixes, Armamentarium sell price fix, promotion and temp_build fixes, .yyp cleanup, new scr_ship_functions script. Merge decisions: - Kept the Chaos/Heretic pair translation in obj_ncombat Alarm_5: upstream's standardization renamed literals but the inverted read plus raw edit_forces write remain, so the ground-assault bug still exists upstream. - Dropped our fleet ETA, promotion loop, and temp_build fixes in favor of upstream's equivalents. - Re-anchored Guard Squad / Heavy Weapons Team pooled health into the reworked max_health; preserved AP look-behind screening, scrollable combat log, stage timeout guards, and combat_emit_enemy_status through upstream's refactors. - Re-applied the suffer_navy_bombard p_chaos fix and included the scr_bomb_world / obj_bomb_select bombardment fixes. - obj_fleet KeyPress_32 emptied (upstream deleted the file but obj_fleet.yy still lists the event). Workflows intentionally remain absent from this fork. Upstream's deleted notes files are unreferenced by the merged .yyp and can be removed manually. --- ChapterMaster.yyp | 14 +- docs/README.md | 10 +- objects/obj_al_ship/Draw_0.gml | 11 +- objects/obj_en_ship/Draw_0.gml | 12 +- objects/obj_enunit/Alarm_0.gml | 4 +- objects/obj_enunit/Alarm_1.gml | 2 +- objects/obj_enunit/Draw_0.gml | 2 +- objects/obj_fleet/Create_0.gml | 6 +- objects/obj_fleet/Draw_64.gml | 7 +- objects/obj_fleet/KeyPress_32.gml | 8 +- objects/obj_fleet/Mouse_56.gml | 12 - objects/obj_fleet/Step_0.gml | 11 + objects/obj_fleet_select/Create_0.gml | 4 +- objects/obj_fleet_select/Draw_0.gml | 2 +- objects/obj_ncombat/Alarm_0.gml | 662 ++++++++------- objects/obj_ncombat/Alarm_1.gml | 111 ++- objects/obj_ncombat/Alarm_3.gml | 10 +- objects/obj_ncombat/Alarm_5.gml | 167 ++-- objects/obj_ncombat/Alarm_6.gml | 27 - objects/obj_ncombat/Alarm_7.gml | 35 +- objects/obj_ncombat/Alarm_8.gml | 28 +- objects/obj_ncombat/Create_0.gml | 191 +---- objects/obj_ncombat/Draw_0.gml | 35 +- objects/obj_ncombat/KeyPress_13.gml | 3 - objects/obj_ncombat/Step_0.gml | 13 +- objects/obj_p_fleet/Alarm_1.gml | 6 +- objects/obj_p_fleet/Alarm_4.gml | 2 +- objects/obj_p_ship/Draw_0.gml | 20 +- objects/obj_pnunit/Alarm_3.gml | 6 +- objects/obj_popup/Alarm_0.gml | 2 +- objects/obj_popup/Create_0.gml | 8 +- objects/obj_popup/Destroy_0.gml | 4 +- objects/obj_temp_build/Create_0.gml | 2 +- objects/obj_turn_end/Mouse_56.gml | 12 +- scripts/Armamentarium/Armamentarium.gml | 53 +- scripts/scr_ComplexSet/scr_ComplexSet.gml | 753 +++++++++--------- scripts/scr_PlanetData/scr_PlanetData.gml | 33 +- scripts/scr_add_artifact/scr_add_artifact.gml | 2 +- scripts/scr_add_man/scr_add_man.gml | 2 +- scripts/scr_buttons/scr_buttons.gml | 10 +- scripts/scr_crusade/scr_crusade.gml | 2 +- scripts/scr_dialogue/scr_dialogue.gml | 12 +- .../scr_draw_management_unit.gml | 2 +- .../scr_drop_select_function.gml | 22 +- scripts/scr_flavor/scr_flavor.gml | 4 +- .../scr_fleet_functions.gml | 326 ++++---- .../scr_imperial_navy_functions.gml | 2 +- .../scr_inquisition_inspection.gml | 2 +- .../scr_inquisition_mission.gml | 2 +- .../scr_khornate_fleet_functions.gml | 4 +- .../scr_marine_struct/scr_marine_struct.gml | 535 +++++++------ .../scr_mission_functions.gml | 6 +- .../scr_pen_And_paper/scr_pen_And_paper.gml | 10 +- .../scr_player_fleet_functions.gml | 16 +- .../scr_player_ship_functions.gml | 7 +- .../scr_population_influence.gml | 9 +- scripts/scr_powers/scr_powers.gml | 2 +- scripts/scr_promote/scr_promote.gml | 8 +- scripts/scr_purge_world/scr_purge_world.gml | 10 +- .../scr_ship_functions/scr_ship_functions.gml | 28 + .../scr_ship_functions/scr_ship_functions.yy | 13 + scripts/scr_shoot/scr_shoot.gml | 4 +- scripts/scr_ui_manage/scr_ui_manage.gml | 4 +- scripts/scr_zoom/scr_zoom.gml | 5 +- 64 files changed, 1645 insertions(+), 1692 deletions(-) create mode 100644 scripts/scr_ship_functions/scr_ship_functions.gml create mode 100644 scripts/scr_ship_functions/scr_ship_functions.yy diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index 79fe03c2e5..e908dc453d 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -12,30 +12,22 @@ }, "defaultScriptType":1, "Folders":[ - {"$GMFolder":"","%Name":"Animation Curves","folderPath":"folders/Animation Curves.yy","name":"Animation Curves","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"Extensions","folderPath":"folders/Extensions.yy","name":"Extensions","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Fonts","folderPath":"folders/Fonts.yy","name":"Fonts","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"New Fonts","folderPath":"folders/Fonts/New Fonts.yy","name":"New Fonts","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Libraries","folderPath":"folders/Libraries.yy","name":"Libraries","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"GMHook","folderPath":"folders/Libraries/GMHook.yy","name":"GMHook","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"Notes","folderPath":"folders/Notes.yy","name":"Notes","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Objects","folderPath":"folders/Objects.yy","name":"Objects","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Combat_Fleet","folderPath":"folders/Objects/Combat_Fleet.yy","name":"Combat_Fleet","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"New Combat","folderPath":"folders/Objects/New Combat.yy","name":"New Combat","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"New UI","folderPath":"folders/Objects/New UI.yy","name":"New UI","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Temp","folderPath":"folders/Objects/Temp.yy","name":"Temp","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"Paths","folderPath":"folders/Paths.yy","name":"Paths","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Rooms","folderPath":"folders/Rooms.yy","name":"Rooms","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"unused","folderPath":"folders/Rooms/unused.yy","name":"unused","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Scripts","folderPath":"folders/Scripts.yy","name":"Scripts","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Combat","folderPath":"folders/Scripts/Combat.yy","name":"Combat","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"compatibility","folderPath":"folders/Scripts/compatibility.yy","name":"compatibility","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"action","folderPath":"folders/Scripts/compatibility/action.yy","name":"action","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"d3d","folderPath":"folders/Scripts/compatibility/d3d.yy","name":"d3d","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"draw","folderPath":"folders/Scripts/compatibility/draw.yy","name":"draw","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"instance","folderPath":"folders/Scripts/compatibility/instance.yy","name":"instance","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"object","folderPath":"folders/Scripts/compatibility/object.yy","name":"object","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"view","folderPath":"folders/Scripts/compatibility/view.yy","name":"view","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Constructors","folderPath":"folders/Scripts/Constructors.yy","name":"Constructors","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Diplomacy","folderPath":"folders/Scripts/Diplomacy.yy","name":"Diplomacy","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"events_and_missions","folderPath":"folders/Scripts/events_and_missions.yy","name":"events_and_missions","resourceType":"GMFolder","resourceVersion":"2.0",}, @@ -53,7 +45,6 @@ {"$GMFolder":"","%Name":"Components","folderPath":"folders/Scripts/User Interface/Components.yy","name":"Components","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Diplomacy","folderPath":"folders/Scripts/User Interface/Diplomacy.yy","name":"Diplomacy","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Common","folderPath":"folders/Scripts/User Interface/Diplomacy/Common.yy","name":"Common","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$GMFolder":"","%Name":"Sequences","folderPath":"folders/Sequences.yy","name":"Sequences","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Shaders","folderPath":"folders/Shaders.yy","name":"Shaders","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Sounds","folderPath":"folders/Sounds.yy","name":"Sounds","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Themes","folderPath":"folders/Sounds/Themes.yy","name":"Themes","resourceType":"GMFolder","resourceVersion":"2.0",}, @@ -117,8 +108,6 @@ {"$GMFolder":"","%Name":"Deprecated","folderPath":"folders/Sprites/Unused/Deprecated.yy","name":"Deprecated","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"Groundside","folderPath":"folders/Sprites/Unused/Groundside.yy","name":"Groundside","resourceType":"GMFolder","resourceVersion":"2.0",}, {"$GMFolder":"","%Name":"New Ground","folderPath":"folders/Sprites/Unused/Groundside/New Ground.yy","name":"New Ground","resourceType":"GMFolder","resourceVersion":"2.0",}, - {"$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":[ {"link":"io.gamemaker.sdfshaders-1.0.0","name":"io.gamemaker.sdfshaders-1.0.0","path":"io.gamemaker.sdfshaders-1.0.0.yyp",}, @@ -630,8 +619,6 @@ {"id":{"name":"fnt_menu","path":"fonts/fnt_menu/fnt_menu.yy",},}, {"id":{"name":"fnt_small","path":"fonts/fnt_small/fnt_small.yy",},}, {"id":{"name":"fnt_tiny","path":"fonts/fnt_tiny/fnt_tiny.yy",},}, - {"id":{"name":"compatibility_report_040421_2234143414","path":"notes/compatibility_report_040421_2234143414/compatibility_report_040421_2234143414.yy",},}, - {"id":{"name":"notes","path":"notes/notes/notes.yy",},}, {"id":{"name":"obj_al_capital","path":"objects/obj_al_capital/obj_al_capital.yy",},}, {"id":{"name":"obj_al_cruiser","path":"objects/obj_al_cruiser/obj_al_cruiser.yy",},}, {"id":{"name":"obj_al_in","path":"objects/obj_al_in/obj_al_in.yy",},}, @@ -923,6 +910,7 @@ {"id":{"name":"scr_shader_initialize","path":"scripts/scr_shader_initialize/scr_shader_initialize.yy",},}, {"id":{"name":"scr_ship_battle","path":"scripts/scr_ship_battle/scr_ship_battle.yy",},}, {"id":{"name":"scr_ship_count","path":"scripts/scr_ship_count/scr_ship_count.yy",},}, + {"id":{"name":"scr_ship_functions","path":"scripts/scr_ship_functions/scr_ship_functions.yy",},}, {"id":{"name":"scr_ship_occupants","path":"scripts/scr_ship_occupants/scr_ship_occupants.yy",},}, {"id":{"name":"scr_shoot","path":"scripts/scr_shoot/scr_shoot.yy",},}, {"id":{"name":"scr_special_view","path":"scripts/scr_special_view/scr_special_view.yy",},}, diff --git a/docs/README.md b/docs/README.md index 10f93eb6ec..fc4bd1cc26 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,7 +4,7 @@ # Chapter Master - Adeptus Dominus -[![Release-Development](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/release_dev.yml/badge.svg)](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/release_dev.yml) +[![Development Release](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/create_release.yml/badge.svg?branch=main)](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/create_release.yml) [![](https://dcbadge.limes.pink/api/server/https://discord.gg/zAGpqHzsXQ?style=flat)](https://discord.gg/zAGpqHzsXQ) [![GitHub repo size](https://img.shields.io/github/repo-size/Adeptus-Dominus/ChapterMaster?style=flat&label=Repo%20Size&labelColor=4493f8&color=545454)](https://github.com/Adeptus-Dominus/ChapterMaster) @@ -46,11 +46,11 @@ Download the [latest release](https://github.com/Adeptus-Dominus/ChapterMaster/r Best bet is to ask about everything in our Discord, because things bellow are probably not very helpful at the moment. -- [Working with GameMaker projects](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Working-with-GameMaker-projects) +- [CONTRIBUTING.md](https://github.com/Adeptus-Dominus/ChapterMaster/blob/main/docs/CONTRIBUTING.md) +- [CODE_STYLE.md](https://github.com/Adeptus-Dominus/ChapterMaster/blob/main/docs/CODE_STYLE.md) - [Useful Tools/Resources](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Useful-resources) -- [Contributing](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Contributing) wiki page (not filled properly) -- [Code Style](https://github.com/Adeptus-Dominus/ChapterMaster/blob/main/docs/CODE_STYLE.md) (may be a bit dated) -- [Code Guidance](https://github.com/Adeptus-Dominus/ChapterMaster/blob/main/docs/code_guidance.md) (probably dated as well) +- [Working with GameMaker projects](https://github.com/Adeptus-Dominus/ChapterMaster/wiki/Working-with-GameMaker-projects) +- [Code Tips](https://github.com/Adeptus-Dominus/ChapterMaster/blob/main/docs/code_guidance.md) (probably outdated) This project exists thanks to all the people who have contributed: diff --git a/objects/obj_al_ship/Draw_0.gml b/objects/obj_al_ship/Draw_0.gml index f31394cb2e..6f283aa7a9 100644 --- a/objects/obj_al_ship/Draw_0.gml +++ b/objects/obj_al_ship/Draw_0.gml @@ -1,17 +1,8 @@ if (name != "") { draw_self(); - draw_set_color(CM_GREEN_COLOR); draw_set_font(fnt_info); draw_set_halign(fa_center); - if (maxhp != 0) { - var _value = shields <= 0 ? hp / maxhp : shields / maxshields; - - if (obj_controller.zoomed == 0) { - draw_text(x, y - sprite_height, string_hash_to_newline(string(floor(_value * 100)) + "%")); - } else { - draw_text_transformed(x, y - sprite_height, string_hash_to_newline(string(floor(_value * 100)) + "%"), 2, 2, 0); - } - } + draw_ship_status_overlay(self, CM_GREEN_COLOR, COL_REQUISITION); } diff --git a/objects/obj_en_ship/Draw_0.gml b/objects/obj_en_ship/Draw_0.gml index 738f09e7d5..4914e2462d 100644 --- a/objects/obj_en_ship/Draw_0.gml +++ b/objects/obj_en_ship/Draw_0.gml @@ -15,21 +15,11 @@ if (name != "") { scr_bolt(x - 1, y + 1, target.x - 1, target.y + 1, 0); } - draw_set_color(CM_GREEN_COLOR); - if (class == "Battlekroozer") { draw_sprite_ext(sprite_index, 0, x, y, 0.75, 0.75, direction, c_white, 1); } else { draw_self(); } - if (maxhp != 0) { - var _value = shields <= 0 ? hp / maxhp : shields / maxshields; - - if (obj_controller.zoomed == 0) { - draw_text(x, y - sprite_height, string_hash_to_newline(string(floor(_value * 100)) + "%")); - } else { - draw_text_transformed(x, y - sprite_height, string_hash_to_newline(string(floor(_value * 100)) + "%"), 2, 2, 0); - } - } + draw_ship_status_overlay(self, CM_GREEN_COLOR, COL_REQUISITION); } diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index 438018f8c4..161d67253d 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -96,7 +96,7 @@ if (!engaged) { // to shooting the men instead of idling. The original code gated // this whole fallback behind a multi-block check, so a lone // men-only block left every AP weapon firing zero shots. - if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != 7)) { + if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != eFACTION.ORK)) { var _column_size_value = enemy.column_size; var x2 = enemy.x; repeat (instance_number(obj_pnunit) - 1) { @@ -193,7 +193,7 @@ if (!engaged) { if (block_has_armour(enemy) || (enemy.veh_type[1] == "Defenses")) { scr_shoot(i, enemy, target_unit_index, "att", "ranged"); continue; - } else if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != 7)) { + } else if ((instance_number(obj_pnunit) > 1) && (obj_ncombat.enemy != eFACTION.ORK)) { var x2 = enemy.x; repeat (instance_number(obj_pnunit) - 1) { x2 += flank == 0 ? -10 : 10; diff --git a/objects/obj_enunit/Alarm_1.gml b/objects/obj_enunit/Alarm_1.gml index 9294cb8ea7..08d92a1af1 100644 --- a/objects/obj_enunit/Alarm_1.gml +++ b/objects/obj_enunit/Alarm_1.gml @@ -184,7 +184,7 @@ if ((men == 1) && (veh == 0) && (instance_number(obj_enunit) == 1)) { } } -if (obj_ncombat.enemy == 1) { +if (obj_ncombat.enemy == eFACTION.PLAYER) { men = 0; for (var j = 1; j <= 100; j++) { veh = 0; diff --git a/objects/obj_enunit/Draw_0.gml b/objects/obj_enunit/Draw_0.gml index 0006f1603e..a69290cd23 100644 --- a/objects/obj_enunit/Draw_0.gml +++ b/objects/obj_enunit/Draw_0.gml @@ -22,7 +22,7 @@ if (draw_size > 0) { if (hit()) { if (unit_count != unit_count_old) { unit_count_old = unit_count; - if (obj_ncombat.enemy != 1) { + if (obj_ncombat.enemy != eFACTION.PLAYER) { composition_string = block_composition_string(); } else { var variety = []; diff --git a/objects/obj_fleet/Create_0.gml b/objects/obj_fleet/Create_0.gml index 9004826a78..37f9f038fb 100644 --- a/objects/obj_fleet/Create_0.gml +++ b/objects/obj_fleet/Create_0.gml @@ -20,7 +20,6 @@ view_y = obj_controller.y; obj_controller.x = 0; obj_controller.y = 240; obj_controller.combat = 1; -is_zoomed = obj_controller.zoomed; start = 0; combat_end = 170; @@ -30,6 +29,11 @@ if (obj_controller.zoomed == 0) { } } +var _surface_h = surface_get_height(application_surface); +speed_button = new SpriteButton({sprite: spr_fast_forward, x1: 10, y1: _surface_h / 2}); +original_speed = game_get_speed(gamespeed_fps); +speed_mode = 0; + enemy = 0; enemy_status = "attacking"; diff --git a/objects/obj_fleet/Draw_64.gml b/objects/obj_fleet/Draw_64.gml index 0381e7b108..6868a94ec9 100644 --- a/objects/obj_fleet/Draw_64.gml +++ b/objects/obj_fleet/Draw_64.gml @@ -49,11 +49,8 @@ if (start == 0) { draw_text(_begin_x, _begin_y, _begin_text); } -// fast forward icon -if (game_get_speed(gamespeed_fps) != 90 && start == 5) { - draw_set_alpha(1); - var _ff_h = sprite_get_height(spr_fast_forward); - draw_sprite(spr_fast_forward, 0, 12, (_surface_h / 2) - (_ff_h / 2)); +if (start == 5) { + speed_button.draw(); } // battle stat box diff --git a/objects/obj_fleet/KeyPress_32.gml b/objects/obj_fleet/KeyPress_32.gml index 20958c9684..1e700ee017 100644 --- a/objects/obj_fleet/KeyPress_32.gml +++ b/objects/obj_fleet/KeyPress_32.gml @@ -1,6 +1,2 @@ -if (obj_controller.cooldown <= 0) { - obj_controller.cooldown = 8; - with (obj_controller) { - scr_zoom(); - } -} +// Emptied to match upstream ff9b33eff (space combat zooming glitch fix deleted this +// event file; obj_fleet.yy still lists the event, so an empty no-op is the safe drop-in). diff --git a/objects/obj_fleet/Mouse_56.gml b/objects/obj_fleet/Mouse_56.gml index 2c62e6353a..e34f82c544 100644 --- a/objects/obj_fleet/Mouse_56.gml +++ b/objects/obj_fleet/Mouse_56.gml @@ -37,15 +37,3 @@ if (instance_exists(obj_p_ship) && (control == 1)) { sel_y2 = 0; } } - -//Why is this here? -if ((start == 5) && (obj_controller.zoomed == 0)) { - if ((mouse_x >= camera_get_view_x(view_camera[0]) + 12) && (mouse_y >= camera_get_view_y(view_camera[0]) + 436) && (mouse_x < camera_get_view_x(view_camera[0]) + 48) && (mouse_y < camera_get_view_y(view_camera[0]) + 480) && (game_get_speed(gamespeed_fps) < 90)) { - game_set_speed(game_get_speed(gamespeed_fps) + 30, gamespeed_fps); - } -} -if ((start == 5) && (obj_controller.zoomed == 1)) { - if ((mouse_x > 24) && (mouse_y > 872) && (mouse_x < 90) && (mouse_y < 960) && (game_get_speed(gamespeed_fps) < 90)) { - game_set_speed(game_get_speed(gamespeed_fps) + 30, gamespeed_fps); - } -} diff --git a/objects/obj_fleet/Step_0.gml b/objects/obj_fleet/Step_0.gml index 65390ce41b..ab02d8735b 100644 --- a/objects/obj_fleet/Step_0.gml +++ b/objects/obj_fleet/Step_0.gml @@ -56,4 +56,15 @@ if (start == 5) { } } } + + if (speed_button.is_clicked) { + speed_mode = (speed_mode + 1) % 3; + var new_speed = 0; + if (speed_mode == 0) { + new_speed = original_speed; + } else { + new_speed = original_speed + 30 * speed_mode; + } + game_set_speed(new_speed, gamespeed_fps); + } } diff --git a/objects/obj_fleet_select/Create_0.gml b/objects/obj_fleet_select/Create_0.gml index 73a672ea75..ee149bbe7d 100644 --- a/objects/obj_fleet_select/Create_0.gml +++ b/objects/obj_fleet_select/Create_0.gml @@ -184,8 +184,8 @@ selection_window.inside_method = function() { } } } - if (obj_ini.ship_maxhp[current_ship] > 0) { - ship_health = round((obj_ini.ship_hp[current_ship] / obj_ini.ship_maxhp[current_ship]) * 100); + if (obj_ini.ship_maxhp[full_id] > 0) { + ship_health = round((obj_ini.ship_hp[full_id] / obj_ini.ship_maxhp[full_id]) * 100); } if (ship_select == 0) { diff --git a/objects/obj_fleet_select/Draw_0.gml b/objects/obj_fleet_select/Draw_0.gml index a7c91ad80b..958ed9a716 100644 --- a/objects/obj_fleet_select/Draw_0.gml +++ b/objects/obj_fleet_select/Draw_0.gml @@ -101,7 +101,7 @@ if (!instance_exists(obj_drop_select) && !instance_exists(obj_bomb_select)) { draw_set_font(fnt_40k_14b); var eta = 0; - eta = calculate_fleet_eta(mine.x, mine.y, sys.x, sys.y, selection_travel_speed,,, player_fleet.warp_able); + eta = calculate_fleet_eta(mine.x, mine.y, sys.x, sys.y, selection_travel_speed, true, true, player_fleet.warp_able); if ((sys.storm > 0) || (instance_nearest(x, y, obj_star).storm > 0)) { eta = "N/A"; diff --git a/objects/obj_ncombat/Alarm_0.gml b/objects/obj_ncombat/Alarm_0.gml index 8ff85db560..0ca6c3665d 100644 --- a/objects/obj_ncombat/Alarm_0.gml +++ b/objects/obj_ncombat/Alarm_0.gml @@ -1,35 +1,101 @@ -// Sets up the number of enemies based on the threath level, enemy type and specific story events - +/// @description Initial Setup Alarm, spawns units and sets combat bonuses try { - if (battle_special == "cs_meeting_battle5") { - alpha_strike = 1; - } - instance_activate_object(obj_enunit); + instance_activate_object(obj_pnunit); - if (enemy == 1) { - instance_activate_object(obj_enunit); + if (enemy == eFACTION.PLAYER || !instance_exists(obj_pnunit)) { exit; } + if (ambushers) { + global_attack *= 1.1; + } + if (bolter_drilling) { + global_bolter *= 1.1; + } + if (slow) { + global_attack -= 0.1; + global_defense += 0.2; + } + if (lightning) { + global_attack += 0.2; + global_defense -= 0.1; + } + if (melee) { + global_melee *= 1.15; + } + if (shitty_luck) { + global_defense *= 0.9; + } + if (enemy_eldar && (enemy == eFACTION.ELDAR)) { + global_attack *= 1.1; + global_defense *= 1.1; + } + if (enemy_fallen && (enemy == eFACTION.CHAOS)) { + global_attack *= 1.1; + global_defense *= 1.1; + } + if (enemy_orks && (enemy == eFACTION.ORK)) { + global_attack *= 1.1; + global_defense *= 1.1; + } + if (enemy_tau && (enemy == eFACTION.TAU)) { + global_attack *= 1.1; + global_defense *= 1.1; + } + if (enemy_tyranids && (enemy == eFACTION.TYRANIDS)) { + global_attack *= 1.1; + global_defense *= 1.1; + } + if (enemy_necrons && (enemy == eFACTION.NECRONS)) { + global_attack *= 1.1; + global_defense *= 1.1; + } + if (siege && (enemy_fortified >= 3) && !defending) { + global_attack *= 1.2; + } + if ((lyman == 1) && (dropping)) { + global_attack *= 0.85; + global_defense *= 0.9; + } + if (ossmodula == 1) { + global_attack *= 0.95; + global_defense *= 0.95; + } + if (betchers == 1) { + global_melee *= 0.95; + } + if (catalepsean == 1) { + global_attack *= 0.95; + } + if (occulobe == 1) { + if ((time == 5) || (time == 6)) { + global_attack *= 0.7; + global_defense *= 0.8; + } + } + + global_defense = 2 - global_defense; + + // Sets up the number of enemies based on the threath level, enemy type and specific story events + if (battle_special == "cs_meeting_battle5") { + alpha_strike = 1; + } + if ((battle_special == "study2a") || (battle_special == "study2b")) { ally = 3; ally_forces = 1; } - instance_activate_object(obj_pnunit); - if (!instance_exists(obj_pnunit)) { - exit; - } - xxx = instance_nearest(1000, 240, obj_pnunit); - xxx = xxx.x + 80; + + xxx = instance_nearest(1000, 240, obj_pnunit).x + 80; if ((string_count("spyrer", battle_special) > 0) || (string_count("fallen", battle_special) > 0) || (string_count("mech", battle_special) > 0) || (battle_special == "space_hulk") || (battle_special == "study2a") || (battle_special == "study2b")) { fortified = 0; } - var u; + var u = noone; - if ((fortified > 1) && (enemy + threat != 17)) { + if ((fortified > 1) && !(enemy == eFACTION.CHAOS && threat == 7)) { u = instance_create(0, 0, obj_nfort); u.image_speed = 0; u.image_alpha = 0.5; @@ -51,8 +117,8 @@ try { u.hp[1] = 1500; } - if ((siege == 1) && (fortified > 0) && (defending == true)) { - global_attack = global_attack * 1.1; + if (siege && (fortified > 0) && defending) { + global_attack *= 1.1; u.hp[1] = round(u.hp[1] * 1.2); } @@ -60,11 +126,11 @@ try { } var _num = xxx / 10; - for (var j = 0; j < 10; j++) { - _num -= 1; - u = instance_create(_num * 10, 240, obj_enunit); - u.column = _num - ((xxx / 10) - 10); + for (var j = 1; j <= 10; j++) { + u = instance_create((_num - j) * 10, 240, obj_enunit); + u.column = (_num - j) - ((xxx / 10) - 10); } + // *** Enemy Forces Special Event *** // * Malcadon Spyrer * if (string_count("spyrer", battle_special) > 0) { @@ -145,7 +211,7 @@ try { with (obj_enunit) { instance_destroy(); } - enemy = 10; + enemy = eFACTION.CHAOS; u = instance_create(10, 240, obj_enunit); enemy_dudes = "1"; u.dudes[1] = choose("Greater Daemon of Khorne", "Greater Daemon of Slaanesh", "Greater Daemon of Tzeentch", "Greater Daemon of Nurgle"); @@ -171,7 +237,7 @@ try { u.dudes[2] = "Necron Wraith"; u.dudes_num[2] = 1; enemies[2] = 1; - u.engaged = 1; // u.flank=1; + u.engaged = 1; with (instance_nearest(x + 1000, 240, obj_pnunit)) { engaged = 1; } @@ -190,7 +256,7 @@ try { u.dudes[2] = "Canoptek Scarab"; u.dudes_num[2] = 20; enemies[2] = u.dudes[2]; - u.engaged = 1; // u.flank=1; + u.engaged = 1; with (instance_nearest(x + 1000, 240, obj_pnunit)) { engaged = 1; } @@ -206,7 +272,7 @@ try { u.dudes[1] = "Tomb Stalker"; u.dudes_num[1] = 1; enemies[1] = 1; - u.engaged = 1; // u.flank=1; + u.engaged = 1; with (instance_nearest(x + 1000, 240, obj_pnunit)) { engaged = 1; } @@ -262,24 +328,24 @@ try { } // * Tomb world attack enemy setup * if (battle_special == "wake1_attack") { - enemy = 13; + enemy = eFACTION.NECRONS; threat = 2; } if (battle_special == "wake2_attack") { - enemy = 13; + enemy = eFACTION.NECRONS; threat = 3; } if (battle_special == "wake3_attack") { - enemy = 13; + enemy = eFACTION.NECRONS; threat = 5; } // * Tomb world study attack enemy setup * if (battle_special == "study2a") { - enemy = 13; + enemy = eFACTION.NECRONS; threat = 2; } if (battle_special == "study2b") { - enemy = 13; + enemy = eFACTION.NECRONS; threat = 3; } // ** Space Hulk Forces ** @@ -290,11 +356,11 @@ try { instance_destroy(); } // * Ork Space Hulk * - if (enemy == 7) { + if (enemy == eFACTION.ORK) { modi = random_range(0.80, 1.20) + 1; make = round(max(3, player_starting_dudes * modi)); - u = instance_create(instance_nearest(x - 1000, 240, obj_pnunit).x - 10, 240, obj_enunit); + u = instance_create(xxx - 90, 240, obj_enunit); u.dudes[1] = "Meganob"; u.dudes_num[1] = make; enemies[1] = u.dudes[1]; @@ -304,7 +370,7 @@ try { engaged = 1; } - u = instance_create(instance_nearest(x + 1000, 240, obj_pnunit).x + 20, 240, obj_enunit); + u = instance_create(xxx - 60, 240, obj_enunit); u.dudes[1] = "Slugga Boy"; u.dudes_num[1] = make; enemies[1] = u.dudes[1]; @@ -316,11 +382,11 @@ try { hulk_forces = make * 3; } // * Genestealer Space Hulk * - if (enemy == 9) { + if (enemy == eFACTION.TYRANIDS) { modi = random_range(0.80, 1.20) + 1; make = round(max(3, player_starting_dudes * modi)) * 2; - u = instance_create(instance_nearest(x - 1000, 240, obj_pnunit).x - 10, 240, obj_enunit); + u = instance_create(xxx - 90, 240, obj_enunit); u.dudes[1] = "Genestealer"; u.dudes_num[1] = round(make / 3); enemies[1] = u.dudes[1]; @@ -330,12 +396,12 @@ try { engaged = 1; } - u = instance_create(instance_nearest(x + 1000, 240, obj_pnunit).x + 10, 240, obj_enunit); + u = instance_create(xxx - 70, 240, obj_enunit); u.dudes[1] = "Genestealer"; u.dudes_num[1] = round(make / 3); enemies[1] = u.dudes[1]; - u = instance_create(instance_nearest(x + 1000, 240, obj_pnunit).x + 50, 240, obj_enunit); + u = instance_create(xxx - 30, 240, obj_enunit); u.dudes[1] = "Genestealer"; u.dudes_num[1] = make - (round(make / 3) * 2); enemies[1] = u.dudes[1]; @@ -343,11 +409,11 @@ try { hulk_forces = make; } // * CSM Space Hulk * - if (enemy == 10) { + if (enemy == eFACTION.CHAOS) { modi = random_range(0.80, 1.20) + 1; make = round(max(3, player_starting_dudes * modi)); - u = instance_create(instance_nearest(x - 1000, 240, obj_pnunit).x - 10, 240, obj_enunit); + u = instance_create(xxx - 90, 240, obj_enunit); u.dudes[1] = "Chaos Terminator"; u.dudes_num[1] = round(make * 0.25); enemies[1] = u.dudes[1]; @@ -357,12 +423,12 @@ try { engaged = 1; } - u = instance_create(instance_nearest(x + 1000, 240, obj_pnunit).x + 10, 240, obj_enunit); + u = instance_create(xxx - 70, 240, obj_enunit); u.dudes[1] = "Chaos Space Marine"; u.dudes_num[1] = round(make * 0.25); enemies[1] = u.dudes[1]; - u = instance_create(instance_nearest(x + 1000, 240, obj_pnunit).x + 50, 240, obj_enunit); + u = instance_create(xxx - 30, 240, obj_enunit); u.dudes[1] = "Cultist"; u.dudes_num[1] = round(make * 0.5); enemies[1] = u.dudes[1]; @@ -457,11 +523,10 @@ try { instance_deactivate_object(u); } // * Imperial Guard Force * - if (enemy == 2) { + if (enemy == eFACTION.IMPERIUM) { guard_total = threat; - guard_score = 6; - var f = 0, guar = threat / 10; + var guar = threat / 10; // Guardsmen u = instance_create(xxx, 240, obj_enunit); @@ -471,7 +536,7 @@ try { enemies[1] = u.dudes[1]; instance_deactivate_object(u); - f = round(threat / 20000); + var f = round(threat / 20000); // Leman Russ D and Ogryn if (f > 0) { u = instance_create(xxx + 10, 240, obj_enunit); @@ -548,7 +613,7 @@ try { } // ** Aeldar Force ** - if (enemy == 6) { + if (enemy == eFACTION.ELDAR) { // Ranger Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -959,7 +1024,7 @@ try { } // ** Sisters Force ** - if (enemy == 5) { + if (enemy == eFACTION.ECCLESIARCHY) { // Small Sister Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -1233,10 +1298,7 @@ try { } // ** Orks Forces ** - if (enemy == 7) { - // u=instance_create(-10,240,obj_enunit); - // u.dudes[1]="Stormboy";u.dudes_num[1]=2500;u.flank=1;// enemies[1]=u.dudes[1]; - + if (enemy == eFACTION.ORK) { // Small Ork Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -1494,7 +1556,7 @@ try { } // ** Tau Forces ** - if (enemy == 8) { + if (enemy == eFACTION.TAU) { // Small Tau Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -1749,16 +1811,13 @@ try { // ** Tyranid Forces ** // Tyranid story event - if ((enemy == 9) && (battle_special == "tyranid_org")) { + if ((enemy == eFACTION.TYRANIDS) || (battle_special == "tyranid_org")) { u = instance_nearest(xxx, 240, obj_enunit); enemy_dudes = "81"; u.dudes[1] = "Termagaunt"; u.dudes_num[1] = 40; u.dudes[2] = "Hormagaunt"; u.dudes_num[2] = 40; - // u.dudes[3]="Lictor";u.dudes_num[3]=1; - } - if ((enemy == 9) && (battle_special != "tyranid_org")) { // Small Genestealer Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -1992,9 +2051,7 @@ try { } // ** Chaos Forces ** - if ((enemy == 10) && (battle_special != "ship_demon") && (battle_special != "fallen1") && (battle_special != "fallen2") && (battle_special != "WL10_reveal") && (battle_special != "WL10_later") && (string_count("cs_meeting_battle", battle_special) == 0)) { - // u=instance_create(-10,240,obj_enunit); - // u.dudes[1]="Stormboy";u.dudes_num[1]=2500;u.flank=1;// enemies[1]=u.dudes[1]; + if ((enemy == eFACTION.CHAOS) && (battle_special != "ship_demon") && (battle_special != "fallen1") && (battle_special != "fallen2") && (battle_special != "WL10_reveal") && (battle_special != "WL10_later") && (string_count("cs_meeting_battle", battle_special) == 0)) { // Small Chaos Cult Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -2168,12 +2225,10 @@ try { u.dudes_num[1] = 1; u.dudes[2] = "Greater Daemon of Slaanesh"; u.dudes_num[2] = 1; - // u.dudes[3]="Greater Daemon of Slaanesh";u.dudes_num[3]=1; u.dudes[4] = "Greater Daemon of Tzeentch"; u.dudes_num[4] = 1; u.dudes[5] = "Greater Daemon of Tzeentch"; u.dudes_num[5] = 1; - // u.dudes[6]="Greater Daemon of Tzeentch";u.dudes_num[6]=1; u.dudes[7] = "Soul Grinder"; u.dudes_num[7] = 3; instance_deactivate_object(u); @@ -2184,12 +2239,10 @@ try { u.dudes_num[1] = 1; u.dudes[2] = "Greater Daemon of Khorne"; u.dudes_num[2] = 1; - // u.dudes[3]="Greater Daemon of Khorne";u.dudes_num[3]=1; u.dudes[4] = "Greater Daemon of Nurgle"; u.dudes_num[4] = 1; u.dudes[5] = "Greater Daemon of Nurgle"; u.dudes_num[5] = 1; - // u.dudes[6]="Greater Daemon of Nurgle";u.dudes_num[6]=1; instance_deactivate_object(u); u = instance_nearest(xxx + 20, 240, obj_enunit); @@ -2204,15 +2257,241 @@ try { u.dudes[5] = "Maulerfiend"; u.dudes_num[5] = 3; instance_deactivate_object(u); + } + } + + // ** Daemon Forces ** - The faction for the check is the Genestealers but the forces being setup are clearly Daemons. + if (enemy == eFACTION.CHAOS && (battle_special == "ship_demon" || battle_special == "ruins_eldar")) { + // If we want to have multiple story events regarding specific Chaos Gods, we could name slaa into gods and just check the value? TBD + var slaa = false; + if (battle_special == "ruins_eldar") { + slaa = true; + } + // Small Daemon Group + if (threat == 1) { + u = instance_nearest(xxx, 240, obj_enunit); + enemy_dudes = "5"; + + u.dudes[1] = choose("Bloodletter", "Daemonette", "Plaguebearer", "Pink Horror"); + if (slaa) { + u.dudes[1] = "Daemonette"; + } + u.dudes_num[1] = 5; + enemies[1] = u.dudes[1]; + u.dudes[2] = "Cultist Elite"; + u.dudes_num[2] = 30; + enemies[2] = u.dudes[2]; + } + // Medium Daemon Group + if (threat == 2) { + u = instance_nearest(xxx, 240, obj_enunit); + enemy_dudes = "90"; + + u.dudes[1] = choose("Bloodletter", "Daemonette", "Plaguebearer", "Pink Horror"); + if (slaa) { + u.dudes[1] = "Daemonette"; + } + u.dudes_num[1] = 30; + + instance_deactivate_object(u); + u = instance_nearest(xxx + 10, 240, obj_enunit); + u.dudes[1] = choose("Bloodletter", "Daemonette", "Plaguebearer", "Pink Horror"); + if (slaa) { + u.dudes[1] = "Daemonette"; + } + u.dudes_num[1] = 30; + u.dudes[2] = "Defiler"; + u.dudes_num[2] = 1; + } + // Large Daemon Group + if (threat == 3) { + u = instance_nearest(xxx, 240, obj_enunit); + enemy_dudes = "240"; + + u.dudes[1] = "Greater Daemon of " + choose("Tzeentch", "Slaanesh", "Nurgle", "Khorne"); + if (slaa) { + u.dudes[1] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[1] = 1; + u.dudes[2] = "Chaos Sorcerer"; + u.dudes_num[2] = 1; + u.dudes[3] = "Pink Horror"; + if (slaa) { + u.dudes[3] = "Daemonette"; + } + u.dudes_num[3] = 60; + + instance_deactivate_object(u); + u = instance_nearest(xxx + 10, 240, obj_enunit); + u.dudes[1] = "Defiler"; + u.dudes_num[1] = 2; + + instance_deactivate_object(u); + u = instance_nearest(xxx + 20, 240, obj_enunit); + if (slaa) { + u.dudes[1] = "Daemonette"; + u.dudes_num[1] = 240; + } else { + u.dudes[1] = "Bloodletter"; + u.dudes_num[1] = 60; + u.dudes[2] = "Plaguebearer"; + u.dudes_num[2] = 60; + u.dudes[3] = "Daemonette"; + u.dudes_num[3] = 60; + u.dudes[4] = "Maulerfiend"; + u.dudes_num[4] = 2; + } + } + // Small Daemon Army + if (threat == 4) { + u = instance_nearest(xxx + 40, 240, obj_enunit); + enemy_dudes = "400"; + u.neww = 1; + + u.dudes[1] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch")); + if (slaa) { + u.dudes[1] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[1] = 1; + u.dudes[2] = "Greater Daemon of " + string(choose("Nurgle", "Khorne")); + if (slaa) { + u.dudes[2] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[2] = 1; + u.dudes[3] = "Soul Grinder"; + u.dudes_num[3] = 1; + instance_deactivate_object(u); + + u = instance_nearest(xxx + 20, 240, obj_enunit); + if (slaa) { + u.dudes[1] = "Daemonette"; + u.dudes_num[1] = 400; + u.dudes[2] = "Maulerfiend"; + u.dudes_num[2] = 2; + } else { + u.dudes[1] = "Bloodletter"; + u.dudes_num[1] = 100; + u.dudes[2] = "Daemonette"; + u.dudes_num[2] = 100; + u.dudes[3] = "Plaguebearer"; + u.dudes_num[3] = 100; + u.dudes[4] = "Pink Horror"; + u.dudes_num[4] = 100; + u.dudes[5] = "Maulerfiend"; + u.dudes_num[5] = 2; + } + instance_deactivate_object(u); + } + // Medium Daemon Army + if (threat == 5) { + u = instance_nearest(xxx + 40, 240, obj_enunit); + enemy_dudes = "1000"; + u.neww = 1; + + u.dudes[1] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); + if (slaa) { + u.dudes[1] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[1] = 1; + u.dudes[2] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); + if (slaa) { + u.dudes[2] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[2] = 1; + u.dudes[3] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); + if (slaa) { + u.dudes[3] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[3] = 1; + u.dudes[4] = "Soul Grinder"; + u.dudes_num[4] = 2; + instance_deactivate_object(u); + + u = instance_nearest(xxx + 20, 240, obj_enunit); + if (slaa) { + u.dudes[1] = "Daemonette"; + u.dudes_num[1] = 1000; + u.dudes[2] = "Maulerfiend"; + u.dudes_num[2] = 2; + } else { + u.dudes[1] = "Bloodletter"; + u.dudes_num[1] = 250; + u.dudes[2] = "Daemonette"; + u.dudes_num[2] = 250; + u.dudes[3] = "Plaguebearer"; + u.dudes_num[3] = 250; + u.dudes[4] = "Pink Horror"; + u.dudes_num[4] = 250; + u.dudes[5] = "Maulerfiend"; + u.dudes_num[5] = 2; + } + instance_deactivate_object(u); + } + // Large Daemon Army + if (threat == 6) { + u = instance_nearest(xxx + 40, 240, obj_enunit); + enemy_dudes = "2000"; + u.neww = 1; + + u.dudes[1] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); + if (slaa) { + u.dudes[1] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[1] = 1; + u.dudes[2] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); + if (slaa) { + u.dudes[2] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[2] = 1; + u.dudes[3] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); + if (slaa) { + u.dudes[3] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[3] = 1; + u.dudes[4] = "Soul Grinder"; + u.dudes_num[4] = 1; + instance_deactivate_object(u); + + u = instance_nearest(xxx + 30, 240, obj_enunit); + u.neww = 1; + u.dudes[1] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); + if (slaa) { + u.dudes[1] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[1] = 1; + u.dudes[2] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); + if (slaa) { + u.dudes[2] = "Greater Daemon of Slaanesh"; + } + u.dudes_num[2] = 1; + u.dudes[3] = "Soul Grinder"; + u.dudes_num[3] = 1; + instance_deactivate_object(u); - // u=instance_nearest(xxx+10,240,obj_enunit); - // u.dudes[1]="Mutant";u.dudes_num[1]=6000; - // instance_deactivate_object(u); + u = instance_nearest(xxx + 20, 240, obj_enunit); + if (slaa) { + u.dudes[1] = "Daemonette"; + u.dudes_num[1] = 2000; + u.dudes[2] = "Maulerfiend"; + u.dudes_num[2] = 3; + } else { + u.dudes[1] = "Bloodletter"; + u.dudes_num[1] = 500; + u.dudes[2] = "Daemonette"; + u.dudes_num[2] = 500; + u.dudes[3] = "Plaguebearer"; + u.dudes_num[3] = 500; + u.dudes[4] = "Pink Horror"; + u.dudes_num[4] = 500; + u.dudes[5] = "Maulerfiend"; + u.dudes_num[5] = 3; + } + instance_deactivate_object(u); } } // ** Chaos Space Marines Forces ** - if ((enemy == 11) && (battle_special != "ChaosWarband") && (string_count("cs_meeting_battle", battle_special) == 0)) { + if ((enemy == eFACTION.HERETICS) && (battle_special != "ChaosWarband") && (string_count("cs_meeting_battle", battle_special) == 0)) { // Small CSM Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -2289,7 +2568,6 @@ try { u.dudes_num[2] = 2; u.dudes[3] = "Chaos Chosen"; u.dudes_num[3] = 10; - // u.dudes[4]="Chaos Terminator";u.dudes_num[4]=5; instance_deactivate_object(u); u = instance_nearest(xxx + 10, 240, obj_enunit); @@ -2434,7 +2712,7 @@ try { } // ** World Eaters Forces ** - if ((enemy == 11) && (battle_special == "ChaosWarband")) { + if ((enemy == eFACTION.HERETICS) && (battle_special == "ChaosWarband")) { // Small WE Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -2527,7 +2805,6 @@ try { u.dudes_num[2] = 2; u.dudes[3] = "World Eater Terminator"; u.dudes_num[3] = 10; - // u.dudes[4]="Chaos Terminator";u.dudes_num[4]=5; instance_deactivate_object(u); u = instance_nearest(xxx + 10, 240, obj_enunit); @@ -2680,239 +2957,8 @@ try { } } - // ** Daemon Forces ** - if (enemy == 12) { - // If we want to have multiple story events regarding specific Chaos Gods, we could name slaa into gods and just check the value? TBD - var slaa = false; - if (battle_special == "ruins_eldar") { - slaa = true; - } - // Small Daemon Group - if (threat == 1) { - u = instance_nearest(xxx, 240, obj_enunit); - enemy_dudes = "5"; - - u.dudes[1] = choose("Bloodletter", "Daemonette", "Plaguebearer", "Pink Horror"); - if (slaa) { - u.dudes[1] = "Daemonette"; - } - u.dudes_num[1] = 5; - enemies[1] = u.dudes[1]; - u.dudes[2] = "Cultist Elite"; - u.dudes_num[2] = 30; - enemies[2] = u.dudes[2]; - } - // Medium Daemon Group - if (threat == 2) { - u = instance_nearest(xxx, 240, obj_enunit); - enemy_dudes = "90"; - - u.dudes[1] = choose("Bloodletter", "Daemonette", "Plaguebearer", "Pink Horror"); - if (slaa) { - u.dudes[1] = "Daemonette"; - } - u.dudes_num[1] = 30; - - instance_deactivate_object(u); - u = instance_nearest(xxx + 10, 240, obj_enunit); - u.dudes[1] = choose("Bloodletter", "Daemonette", "Plaguebearer", "Pink Horror"); - if (slaa) { - u.dudes[1] = "Daemonette"; - } - u.dudes_num[1] = 30; - u.dudes[2] = "Defiler"; - u.dudes_num[2] = 1; - } - // Large Daemon Group - if (threat == 3) { - u = instance_nearest(xxx, 240, obj_enunit); - enemy_dudes = "240"; - - u.dudes[1] = "Greater Daemon of " + choose("Tzeentch", "Slaanesh", "Nurgle", "Khorne"); - if (slaa) { - u.dudes[1] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[1] = 1; - u.dudes[2] = "Chaos Sorcerer"; - u.dudes_num[2] = 1; - u.dudes[3] = "Pink Horror"; - if (slaa) { - u.dudes[3] = "Daemonette"; - } - u.dudes_num[3] = 60; - - instance_deactivate_object(u); - u = instance_nearest(xxx + 10, 240, obj_enunit); - u.dudes[1] = "Defiler"; - u.dudes_num[1] = 2; - - instance_deactivate_object(u); - u = instance_nearest(xxx + 20, 240, obj_enunit); - if (slaa) { - u.dudes[1] = "Daemonette"; - u.dudes_num[1] = 240; - } else { - u.dudes[1] = "Bloodletter"; - u.dudes_num[1] = 60; - u.dudes[2] = "Plaguebearer"; - u.dudes_num[2] = 60; - u.dudes[3] = "Daemonette"; - u.dudes_num[3] = 60; - u.dudes[4] = "Maulerfiend"; - u.dudes_num[4] = 2; - } - } - // Small Daemon Army - if (threat == 4) { - u = instance_nearest(xxx + 40, 240, obj_enunit); - enemy_dudes = "400"; - u.neww = 1; - - u.dudes[1] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch")); - if (slaa) { - u.dudes[1] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[1] = 1; - u.dudes[2] = "Greater Daemon of " + string(choose("Nurgle", "Khorne")); - if (slaa) { - u.dudes[2] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[2] = 1; - // u.dudes[6]="Greater Daemon of Tzeentch";u.dudes_num[6]=1; - u.dudes[3] = "Soul Grinder"; - u.dudes_num[3] = 1; - instance_deactivate_object(u); - - u = instance_nearest(xxx + 20, 240, obj_enunit); - if (slaa) { - u.dudes[1] = "Daemonette"; - u.dudes_num[1] = 400; - u.dudes[2] = "Maulerfiend"; - u.dudes_num[2] = 2; - } else { - u.dudes[1] = "Bloodletter"; - u.dudes_num[1] = 100; - u.dudes[2] = "Daemonette"; - u.dudes_num[2] = 100; - u.dudes[3] = "Plaguebearer"; - u.dudes_num[3] = 100; - u.dudes[4] = "Pink Horror"; - u.dudes_num[4] = 100; - u.dudes[5] = "Maulerfiend"; - u.dudes_num[5] = 2; - } - instance_deactivate_object(u); - } - // Medium Daemon Army - if (threat == 5) { - u = instance_nearest(xxx + 40, 240, obj_enunit); - enemy_dudes = "1000"; - u.neww = 1; - - u.dudes[1] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); - if (slaa) { - u.dudes[1] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[1] = 1; - u.dudes[2] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); - if (slaa) { - u.dudes[2] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[2] = 1; - u.dudes[3] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); - if (slaa) { - u.dudes[3] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[3] = 1; - u.dudes[4] = "Soul Grinder"; - u.dudes_num[4] = 2; - instance_deactivate_object(u); - - u = instance_nearest(xxx + 20, 240, obj_enunit); - if (slaa) { - u.dudes[1] = "Daemonette"; - u.dudes_num[1] = 1000; - u.dudes[2] = "Maulerfiend"; - u.dudes_num[2] = 2; - } else { - u.dudes[1] = "Bloodletter"; - u.dudes_num[1] = 250; - u.dudes[2] = "Daemonette"; - u.dudes_num[2] = 250; - u.dudes[3] = "Plaguebearer"; - u.dudes_num[3] = 250; - u.dudes[4] = "Pink Horror"; - u.dudes_num[4] = 250; - u.dudes[5] = "Maulerfiend"; - u.dudes_num[5] = 2; - } - instance_deactivate_object(u); - } - // Large Daemon Army - if (threat == 6) { - u = instance_nearest(xxx + 40, 240, obj_enunit); - enemy_dudes = "2000"; - u.neww = 1; - - u.dudes[1] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); - if (slaa) { - u.dudes[1] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[1] = 1; - u.dudes[2] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); - if (slaa) { - u.dudes[2] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[2] = 1; - u.dudes[3] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); - if (slaa) { - u.dudes[3] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[3] = 1; - u.dudes[4] = "Soul Grinder"; - u.dudes_num[4] = 1; - instance_deactivate_object(u); - - u = instance_nearest(xxx + 30, 240, obj_enunit); - u.neww = 1; - u.dudes[1] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); - if (slaa) { - u.dudes[1] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[1] = 1; - u.dudes[2] = "Greater Daemon of " + string(choose("Slaanesh", "Tzeentch", "Khorne", "Nurgle")); - if (slaa) { - u.dudes[2] = "Greater Daemon of Slaanesh"; - } - u.dudes_num[2] = 1; - u.dudes[3] = "Soul Grinder"; - u.dudes_num[3] = 1; - instance_deactivate_object(u); - - u = instance_nearest(xxx + 20, 240, obj_enunit); - if (slaa) { - u.dudes[1] = "Daemonette"; - u.dudes_num[1] = 2000; - u.dudes[2] = "Maulerfiend"; - u.dudes_num[2] = 3; - } else { - u.dudes[1] = "Bloodletter"; - u.dudes_num[1] = 500; - u.dudes[2] = "Daemonette"; - u.dudes_num[2] = 500; - u.dudes[3] = "Plaguebearer"; - u.dudes_num[3] = 500; - u.dudes[4] = "Pink Horror"; - u.dudes_num[4] = 500; - u.dudes[5] = "Maulerfiend"; - u.dudes_num[5] = 3; - } - instance_deactivate_object(u); - } - } - // ** Necron Forces ** - if ((enemy == 13) && ((string_count("_attack", battle_special) == 0) || (string_count("wake", battle_special) > 0))) { + if ((enemy == eFACTION.NECRONS) && ((string_count("_attack", battle_special) == 0) || (string_count("wake", battle_special) > 0))) { // Small Necron Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -3132,7 +3178,11 @@ try { instance_activate_object(obj_enunit); } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); - instance_destroy(obj_enunit); - instance_destroy(obj_pnunit); - instance_destroy(obj_ncombat); + with (obj_enunit) { + instance_destroy(); + } + with (obj_pnunit) { + instance_destroy(); + } + instance_destroy(); } diff --git a/objects/obj_ncombat/Alarm_1.gml b/objects/obj_ncombat/Alarm_1.gml index 1afad2cd9d..22f9af57b9 100644 --- a/objects/obj_ncombat/Alarm_1.gml +++ b/objects/obj_ncombat/Alarm_1.gml @@ -9,35 +9,33 @@ if ((ally > 0) && (ally_forces > 0)) { } // Player crap here -var p1, p2, p3, p4, p5, p6, p8, temp, temp2, temp3, temp4, temp5, temp6; -p1 = ""; -p2 = ""; -p3 = ""; -p4 = ""; -p5 = ""; -p6 = ""; -p8 = ""; -temp = 0; -temp2 = 0; -temp3 = 0; -temp4 = 0; -temp5 = 0; -temp6 = 0; -var d1, d2, d3, d4, d5, d6, d7, d8; -d1 = ""; -d2 = ""; -d3 = ""; -d4 = ""; -d5 = ""; -d6 = ""; -d7 = ""; -d8 = ""; - -temp = scouts + tacticals + veterans + devastators + assaults + librarians; +var p1 = ""; +var p2 = ""; +var p3 = ""; +var p4 = ""; +var p5 = ""; +var p6 = ""; +var p8 = ""; +var temp2 = 0; +var temp3 = 0; +var temp4 = 0; +var temp5 = 0; +var temp6 = 0; +var d1 = ""; +var d2 = ""; +var d3 = ""; +var d4 = ""; +var d5 = ""; +var d6 = ""; +var d7 = ""; + +var temp = scouts + tacticals + veterans + devastators + assaults + librarians; temp += techmarines + honors + dreadnoughts + terminators + captains; temp += standard_bearers + champions + important_dudes + chaplains + apothecaries; temp += sgts + vet_sgts; +// Random variations; dark out, rain pooling down, dawn shining off of the armour, etc. +var variation = choose("", "dawn", "rain"); var color_descr = ""; if (obj_ini.main_color != obj_ini.secondary_color) { @@ -47,9 +45,6 @@ if (obj_ini.main_color == obj_ini.secondary_color) { color_descr = string(obj_controller.col[obj_ini.main_color]); } -// Random variations; dark out, rain pooling down, dawn shining off of the armour, etc. -var variation = choose("", "dawn", "rain"); - if (battle_special == "ship_demon") { p1 = "As the Artifact is smashed and melted down some foul smoke begins to erupt from it, spilling outward and upward. After a sparse handful of seconds it takes form into a "; p1 += string(obj_enunit.dudes[1]); @@ -76,7 +71,7 @@ if (battle_special == "space_hulk") { } if (battle_special == "") { - if (dropping == 0) { + if (!dropping) { if (temp - dreadnoughts > 0) { if (variation == "") { p1 = "Dirt crunches beneath the soles of " + string(temp) + " " + string(global.chapter_name) + " as they form up. Your ranks are made up of "; @@ -89,7 +84,7 @@ if (battle_special == "") { } } } - if (dropping == 1) { + if (dropping) { if (temp - dreadnoughts > 0) { // lyman p1 = "The air rumbles and quakes as " + string(temp) + " " + string(global.chapter_name) + " descend in drop-pods. "; @@ -129,8 +124,7 @@ if (string_count("fallen", battle_special) > 0) { } if (string_count("_attack", battle_special) > 0) { - var wh; - wh = choose(1, 2); + var wh = choose(1, 2); if (wh == 1) { p1 = "Cave dirt crunches beneath the soles of your marines as they continue their descent. There is little warning before "; } @@ -272,7 +266,6 @@ if (scouts > 0) { } } -// temp5=string_length(p2);p2=string_delete(p2,temp5-1,2);// p2+="."; temp6 = honors + captains + important_dudes + standard_bearers; if (temp >= 200) { temp6 += terminators; @@ -307,7 +300,7 @@ if (string_count(", ", p2) == 1) { } p2 += "."; -if ((standard_bearers > 1) && (dropping == 0)) { +if ((standard_bearers > 1) && (!dropping)) { p5 = " Chapter Ancients hold your Chapter heraldry high and proud."; } @@ -387,7 +380,7 @@ if (battle_special == "space_hulk") { exit; } -if (dropping == 0) { +if (!dropping) { newline = p1 + p2 + p3 + p4 + p5 + p6; scr_newtext(); if (a1 != "") { @@ -396,7 +389,7 @@ if (dropping == 0) { } } -if ((dropping == 1) && (battle_special != "space_hulk")) { +if ((dropping) && (battle_special != "space_hulk")) { d1 = p1; d2 = p2; d3 = p3; @@ -408,16 +401,16 @@ if ((dropping == 1) && (battle_special != "space_hulk")) { if ((battle_special == "ruins") || (battle_special == "ruins_eldar")) { newline = "The enemy forces are made up of " + string(enemy_dudes); - if (enemy == 6) { + if (enemy == eFACTION.ELDAR) { newline += " Craftworld Eldar."; } - if (enemy == 10) { + if (enemy == eFACTION.CHAOS && threat != 7) { newline += " Cultists and Mutants."; } - if (enemy == 11) { + if (enemy == eFACTION.HERETICS) { newline += " Chaos Space Marines."; } - if (enemy == 12) { + if (enemy == eFACTION.CHAOS && threat == 7) { newline += " Daemons."; } @@ -426,7 +419,7 @@ if ((battle_special == "ruins") || (battle_special == "ruins_eldar")) { } // Enemy crap here -var rand; +var rand = 0; p1 = ""; p2 = ""; p3 = ""; @@ -438,13 +431,13 @@ temp3 = 0; temp4 = 0; temp5 = 0; -if (enemy == 2) { +if (enemy == eFACTION.IMPERIUM) { p1 = "Opposing your forces are a total of " + scr_display_number(floor(guard_effective)) + " Guardsmen, including Heavy Weapons and Armour."; p2 = ""; p3 = ""; } -if ((enemy == 5) && (dropping == 0)) { +if ((enemy == eFACTION.ECCLESIARCHY) && (!dropping)) { p1 = "Marching to face your forces "; if (threat == 1) { p2 = "are a squad of Adepta Sororitas, back up by a dozen priests. Forming up a protective shield around them are a large group of religious followers, gnashing and screaming out litanies to the Emperor."; @@ -463,11 +456,11 @@ if ((enemy == 5) && (dropping == 0)) { } } -if ((enemy == 6) && (dropping == 0)) { +if ((enemy == eFACTION.ELDAR) && (!dropping)) { // Need a few random descriptors here rand = choose(1, 2, 3); } -if ((enemy == 7) && (dropping == 0)) { +if ((enemy == eFACTION.ORK) && (!dropping)) { rand = choose(1, 2, 3); if (rand < 4) { p1 = "Howls and grunts ring from the surrounding terrain as the Orks announce their presence. "; @@ -478,25 +471,25 @@ if ((enemy == 7) && (dropping == 0)) { p2 = string_upper(p2); // Capitalize the ENEMY DUDES first letter } } -if ((enemy == 7) && (dropping == 1)) { +if ((enemy == eFACTION.ORK) && (dropping)) { p1 = "The " + string(enemy_dudes) + "-some Orks howl and roar at the oncoming marines. Many of the beasts fire their weapons, more or less spraying rounds aimlessly into the sky."; } -if ((enemy == 8) && (dropping == 0)) { +if ((enemy == eFACTION.TAU) && (!dropping)) { rand = choose(1, 2, 3); } -if ((enemy == 9) && (dropping == 0)) { +if ((enemy == eFACTION.TYRANIDS) && (!dropping)) { rand = choose(1, 2, 3); } -if ((enemy == 9) && (dropping == 1)) { +if ((enemy == eFACTION.TYRANIDS) && (dropping)) { p1 = "The " + string(enemy_dudes) + "-some Tyranids hiss and chitter as your marines rain down. Blasts of acid and spikes fill the sky, but none seem to quite find their mark."; } -if ((enemy == 10) && (dropping == 0)) { +if ((enemy == eFACTION.CHAOS) && (!dropping)) { rand = choose(1, 2, 3); } -if ((enemy == 10) && (threat == 7)) { +if ((enemy == eFACTION.CHAOS) && (threat == 7)) { rand = choose(1, 2); if (rand == 1) { p1 = "Laying before them is a hellish landscape, fitting for nightmares. Twisted, flesh-like spires reach for the sky, each containing a multitude of fanged maws or eyes. Lightning crackles through the red sky. "; @@ -508,15 +501,11 @@ if ((enemy == 10) && (threat == 7)) { p8 = "The enemy forces are made up of over 3000 lesser Daemons. Their front and rear ranks are made up of Maulerfiends and Soulgrinders, backed up by nearly a dozen Greater Daemons. Each of the four Chaos Gods are represented."; } -if ((enemy == 11) && (dropping == 0)) { +if ((enemy == eFACTION.HERETICS) && (dropping == 0)) { rand = choose(1, 2, 3); } -if ((enemy == 12) && (dropping == 0)) { - // Daemons -} - -if ((enemy == 13) && (dropping == 0)) { +if ((enemy == eFACTION.NECRONS) && (dropping == 0)) { rand = choose(1, 2, 3); if (rand < 4) { p1 = "Dirt crunches beneath the feet of the Necrons as they make their silent advance. "; @@ -528,7 +517,7 @@ if ((enemy == 13) && (dropping == 0)) { } } -if (dropping == 0) { +if (!dropping) { newline = p1 + p2 + p3 + p4 + p5 + p6; scr_newtext(); if (a1 != "") { @@ -541,7 +530,7 @@ if (dropping == 0) { } } -if (dropping == 1) { +if (dropping) { newline = d1 + p1; scr_newtext(); if (lyman == 0) { @@ -570,7 +559,7 @@ if ((occulobe == 1) && (battle_special != "space_hulk")) { } } -if ((fortified > 1) && (dropping == 0) && (enemy + threat != 17)) { +if ((fortified > 1) && !dropping && !(enemy == eFACTION.CHAOS && threat == 7)) { if (fortified == 2) { newline = "An Aegis Defense Line protects your forces."; } @@ -598,7 +587,7 @@ if ((fortified > 1) && (dropping == 0) && (enemy + threat != 17)) { } // Check for battlecry here -if ((temp >= 100) && (threat > 1) && (big_mofo > 0) && (big_mofo < 10) && (dropping == 0)) { +if ((temp >= 100) && (threat > 1) && (big_mofo > 0) && (big_mofo < 10) && !dropping) { p1 = ""; p2 = ""; p3 = ""; diff --git a/objects/obj_ncombat/Alarm_3.gml b/objects/obj_ncombat/Alarm_3.gml index f0249ee4ad..4fe55137ed 100644 --- a/objects/obj_ncombat/Alarm_3.gml +++ b/objects/obj_ncombat/Alarm_3.gml @@ -49,6 +49,8 @@ repeat (100) { good = 1; } } + } else { + break; } } @@ -127,11 +129,11 @@ if (!instance_exists(obj_pnunit)) { if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { newline_color = "yellow"; - if (obj_ncombat.enemy != 6) { + if (enemy != eFACTION.ELDAR) { combat_emit_enemy_status(); } newline_color = "yellow"; - if (obj_ncombat.enemy == 6) { + if (enemy == eFACTION.ELDAR) { var jims; jims = 0; repeat (20) { @@ -169,7 +171,7 @@ if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (timer_stage == 5)) && (four_show == 0)) { newline_color = "yellow"; - if (obj_ncombat.enemy != 6) { + if (enemy != eFACTION.ELDAR) { var jims; jims = 0; repeat (20) { @@ -199,7 +201,7 @@ if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (time } } newline_color = "yellow"; - if (obj_ncombat.enemy == 6) { + if (enemy == eFACTION.ELDAR) { if (enemy_forces > 0) { newline = "Enemy Forces at " + string(max(1, round((enemy_forces / enemy_max) * 100))) + "%"; } diff --git a/objects/obj_ncombat/Alarm_5.gml b/objects/obj_ncombat/Alarm_5.gml index 4c445c459b..ef088b0a49 100644 --- a/objects/obj_ncombat/Alarm_5.gml +++ b/objects/obj_ncombat/Alarm_5.gml @@ -5,13 +5,12 @@ battle_over = 1; alarm[8] = 999999; var line_break = "------------------------------------------------------------------------------"; -// show_message("Final Deaths: "+string(final_marine_deaths)); if (turn_count >= 50) { part1 = "Your forces make a fighting retreat \n"; } -p_data = battle_object.get_planet_data(battle_id); +var p_data = battle_object.get_planet_data(battle_id); // check for wounded marines here to finish off, if defeated defending var roles = obj_ini.role[100]; var ground_mission = instance_exists(obj_ground_mission); @@ -20,7 +19,7 @@ with (obj_pnunit) { after_battle_part1(); } -if (obj_ncombat.defeat == 0) { +if (defeat == 0) { marines_to_recover = ds_priority_create(); vehicles_to_recover = ds_priority_create(); @@ -44,10 +43,10 @@ if (obj_ncombat.defeat == 0) { unit_recovery_score--; units_saved_count++; - if (!struct_exists(obj_ncombat.units_saved_counts, _unit_role)) { - obj_ncombat.units_saved_counts[$ _unit_role] = 1; + if (!struct_exists(units_saved_counts, _unit_role)) { + units_saved_counts[$ _unit_role] = 1; } else { - obj_ncombat.units_saved_counts[$ _unit_role]++; + units_saved_counts[$ _unit_role]++; } continue; } @@ -81,10 +80,10 @@ if (obj_ncombat.defeat == 0) { _column_id.veh_dead[_vehicle_id] = false; vehicles_saved_count++; - if (!struct_exists(obj_ncombat.vehicles_saved_counts, _vehicle_type)) { - obj_ncombat.vehicles_saved_counts[$ _vehicle_type] = 1; + if (!struct_exists(vehicles_saved_counts, _vehicle_type)) { + vehicles_saved_counts[$ _vehicle_type] = 1; } else { - obj_ncombat.vehicles_saved_counts[$ _vehicle_type]++; + vehicles_saved_counts[$ _vehicle_type]++; } continue; } @@ -96,10 +95,10 @@ if (obj_ncombat.defeat == 0) { vehicle_recovery_score -= _candidate.priority; vehicles_saved_count++; - if (!struct_exists(obj_ncombat.vehicles_saved_counts, _vehicle_type)) { - obj_ncombat.vehicles_saved_counts[$ _vehicle_type] = 1; + if (!struct_exists(vehicles_saved_counts, _vehicle_type)) { + vehicles_saved_counts[$ _vehicle_type] = 1; } else { - obj_ncombat.vehicles_saved_counts[$ _vehicle_type]++; + vehicles_saved_counts[$ _vehicle_type]++; } } } @@ -312,7 +311,7 @@ if (string_count("_attack", battle_special) > 0) { if (battle_special == "ship_demon") { reduce_fortification = false; } -if (enemy + threat == 17) { +if (enemy == eFACTION.CHAOS && threat == 7) { reduce_fortification = false; } if (battle_special == "ruins") { @@ -344,15 +343,8 @@ if ((fortified > 0) && (!instance_exists(obj_nfort)) && (reduce_fortification == battle_object.p_fortified[battle_id] -= 1; } -/*if (enemy=5){ - if (obj_controller.faction_status[eFACTION.ECCLESIARCHY]!="War"){ - - } -}*/ - if ((!defeat) && (battle_special == "space_hulk")) { var enemy_power = 0, loot = 0, dicey = roll_dice_chapter(1, 100, "low"); - ex = 0; // Reduce the hulk garrison by one and read the strength left behind. A Chaos hulk keeps its // strength in the traitor (p_traitors) slot, which edit_forces reaches through the HERETICS @@ -372,7 +364,7 @@ if ((!defeat) && (battle_special == "space_hulk")) { } part10 = "Space Hulk Exploration at "; - ex = min(100, 100 - ((enemy_power - 1) * 20)); + var ex = min(100, 100 - ((enemy_power - 1) * 20)); part10 += string(ex) + "%"; newline = part10; if (ex == 100) { @@ -380,11 +372,9 @@ if ((!defeat) && (battle_special == "space_hulk")) { } scr_newtext(); - // show_message("Roll Under: "+string(enemy_power*10)+", Roll: "+string(dicey)); - if (dicey <= (enemy_power * 10)) { loot = choose(1, 2, 3, 4); - if (enemy != 10) { + if (enemy != eFACTION.CHAOS) { loot = choose(1, 1, 2, 3); } hulk_treasure = loot; @@ -436,37 +426,36 @@ if (array_contains(_non_power_reduce_events, battle_special)) { if (defeat == 0 && _reduce_power) { var enemy_power = 0, new_power = 0, power_reduction = 0, requisition_reward = 0; - if (enemy == 2) { + if (enemy == eFACTION.IMPERIUM) { enemy_power = battle_object.p_guardsmen[battle_id]; battle_object.p_guardsmen[battle_id] -= threat; - // if (threat=1) or (threat=2) then battle_object.p_guardsmen[battle_id]=0; } - if (enemy == 5) { + if (enemy == eFACTION.ECCLESIARCHY) { enemy_power = battle_object.p_sisters[battle_id]; part10 = "Ecclesiarchy"; - } else if (enemy == 6) { + } else if (enemy == eFACTION.ELDAR) { enemy_power = battle_object.p_eldar[battle_id]; part10 = "Eldar"; - } else if (enemy == 7) { + } else if (enemy == eFACTION.ORK) { enemy_power = battle_object.p_orks[battle_id]; part10 = "Ork"; - } else if (enemy == 8) { + } else if (enemy == eFACTION.TAU) { enemy_power = battle_object.p_tau[battle_id]; part10 = "Tau"; - } else if (enemy == 9) { + } else if (enemy == eFACTION.TYRANIDS) { enemy_power = battle_object.p_tyranids[battle_id]; part10 = "Tyranid"; - } else if (enemy == 10) { + } else if (enemy == eFACTION.CHAOS) { enemy_power = battle_object.p_traitors[battle_id]; part10 = "Heretic"; if (threat == 7) { part10 = "Daemon"; } - } else if (enemy == 11) { + } else if (enemy == eFACTION.HERETICS) { enemy_power = battle_object.p_chaos[battle_id]; part10 = "Chaos Space Marine"; - } else if (enemy == 13) { + } else if (enemy == eFACTION.NECRONS) { enemy_power = battle_object.p_necrons[battle_id]; part10 = "Necrons"; } @@ -477,8 +466,8 @@ if (defeat == 0 && _reduce_power) { } } - if (enemy != 2) { - if (dropping == true || defending == true) { + if (enemy != eFACTION.IMPERIUM) { + if (dropping || defending) { power_reduction = 1; } else { power_reduction = 2; @@ -496,7 +485,7 @@ if (defeat == 0 && _reduce_power) { if (part10 == "Daemon") { new_power = 7; } - if ((enemy == 9) && (new_power == 0)) { + if ((enemy == eFACTION.TYRANIDS) && (new_power == 0)) { var battle_planet = battle_id; with (battle_object) { var who_cleansed = "Tyranids"; @@ -507,7 +496,7 @@ if (defeat == 0 && _reduce_power) { who_cleansed = "Gene Stealer Cult"; make_alert = true; delete_features(p_feature[battle_planet], eP_FEATURES.GENE_STEALER_CULT); - adjust_influence(eFACTION.TYRANIDS, -25, battle_planet, self); + adjust_influence(eFACTION.TYRANIDS, -25, battle_planet, id); } if (make_alert) { if (p_first[battle_planet] == 1) { @@ -533,14 +522,14 @@ if (defeat == 0 && _reduce_power) { } } } - if ((enemy == 11) && (enemy_power != floor(enemy_power))) { + if ((enemy == eFACTION.HERETICS) && (enemy_power != floor(enemy_power))) { enemy_power = floor(enemy_power); } } if ((obj_controller.blood_debt == 1) && (defeat == 0) && enemy_power > 0) { final_pow = min(enemy_power, 6) - 1; - if ((enemy == 6) || (enemy == 9) || (enemy == 11) || (enemy == 13)) { + if ((enemy == eFACTION.ELDAR) || (enemy == eFACTION.TYRANIDS) || (enemy == eFACTION.HERETICS) || (enemy == eFACTION.NECRONS)) { obj_controller.penitent_turn = 0; obj_controller.penitent_turnly = 0; var penitent_crusade_chart = [ @@ -554,7 +543,7 @@ if (defeat == 0 && _reduce_power) { final_pow = min(enemy_power, 6) - 1; obj_controller.penitent_current += penitent_crusade_chart[final_pow]; - } else if ((enemy == 7) || (enemy == 8) || (enemy == 10)) { + } else if ((enemy == eFACTION.ORK) || (enemy == eFACTION.TAU) || (enemy == eFACTION.CHAOS)) { obj_controller.penitent_turn = 0; obj_controller.penitent_turnly = 0; final_pow = min(enemy_power, 7) - 1; @@ -571,14 +560,16 @@ if (defeat == 0 && _reduce_power) { } } - if (enemy >= 5) { - // Combat numbers the Chaos/Heretic pair opposite to eFACTION. enemy 10 (eFACTION.CHAOS) - // is fought as the Heretic/traitor force and its strength is read from p_traitors above; - // enemy 11 (eFACTION.HERETICS) is fought as the Chaos Space Marine force read from p_chaos. - // edit_forces maps by eFACTION (CHAOS -> p_chaos, HERETICS -> p_traitors), so passing the - // raw combat enemy wrote the reduced strength into the OTHER slot, leaving the force that - // was actually fought untouched and often inflating the other one. Swap the pair so the - // reduction lands on the same force the battle was drawn from. Mirrors the space_hulk fix. + if (enemy >= eFACTION.ECCLESIARCHY) { + // Combat still numbers the Chaos/Heretic pair opposite to eFACTION even after the + // upstream eFACTION standardization: enemy eFACTION.CHAOS is fought as the + // Heretic/traitor force and its strength is read from p_traitors above, while enemy + // eFACTION.HERETICS is fought as the Chaos Space Marine force read from p_chaos. + // edit_forces maps by raw eFACTION (CHAOS -> p_chaos, HERETICS -> p_traitors), so + // passing the raw combat enemy wrote the reduced strength into the OTHER slot, leaving + // the force that was actually fought untouched and often inflating the other one. Swap + // the pair so the reduction lands on the same force the battle was drawn from. + // Mirrors the space_hulk fix. var _reduce_faction = enemy; if (enemy == eFACTION.CHAOS) { _reduce_faction = eFACTION.HERETICS; @@ -588,7 +579,7 @@ if (defeat == 0 && _reduce_power) { p_data.edit_forces(_reduce_faction, new_power); } - if ((enemy != 2) && (string_count("cs_meeting_battle", battle_special) == 0)) { + if ((enemy != eFACTION.IMPERIUM) && (string_count("cs_meeting_battle", battle_special) == 0)) { part10 += $" forces on {p_data.name()}"; if (new_power == 0) { part10 += $" were completely wiped out. Previous power: {enemy_power}. Reduction: {power_reduction}."; @@ -605,38 +596,31 @@ if (defeat == 0 && _reduce_power) { battle_object.p_raided[battle_id] = 1; } } - if (enemy == 2) { + if (enemy == eFACTION.IMPERIUM) { part10 += $" Imperial Guard Forces on {p_data.name()}"; part10 += " were reduced to " + string(battle_object.p_guardsmen[battle_id]) + " (" + string(enemy_power) + "-" + string(threat) + ")"; newline = part10; scr_newtext(); } - if ((enemy == 8) && (ethereal > 0) && (defeat == 0)) { + if ((enemy == eFACTION.TAU) && (ethereal > 0) && (defeat == 0)) { newline = "Tau Ethereal Captured"; newline_color = "yellow"; scr_newtext(); } if (enemy == eFACTION.NECRONS && p_data.planet_forces[eFACTION.NECRONS] < 3 && awake_tomb_world(p_data.features) == 1) { - // var bombs;bombs=scr_check_equip("Plasma Bomb",battle_loc,battle_id,0); - // var bombs;bombs=scr_check_equip("Plasma Bomb","","",0); - - // show_message(string(bombs)); - if (plasma_bomb > 0) { - // scr_check_equip("Plasma Bomb",battle_loc,battle_id,1); - // scr_check_equip("Plasma Bomb","","",1); newline = "Plasma Bomb used to seal the Necron Tomb."; newline_color = "yellow"; scr_newtext(); seal_tomb_world(p_data.features); } else if (plasma_bomb <= 0) { p_data.edit_forces(enemy, 3); - if (dropping != 0) { + if (dropping) { newline = "Deep Strike Ineffective; Plasma Bomb required"; } - if (dropping == 0) { + if (!dropping) { newline = "Attack Ineffective; Plasma Bomb required"; } scr_newtext(); @@ -645,8 +629,6 @@ if (defeat == 0 && _reduce_power) { } if ((defeat == 0) && (enemy == eFACTION.TYRANIDS) && (battle_special == "tyranid_org")) { - // show_message(string(captured_gaunt)); - newline = $"{string_plural_count("Gaunt organism", captured_gaunt)} have been captured."; scr_newtext(); @@ -688,24 +670,24 @@ if ((leader || ((battle_special == "ChaosWarband") && (!obj_controller.faction_d newline = line_break; scr_newtext(); instance_activate_object(obj_event_log); - if (enemy == 5) { + if (enemy == eFACTION.ECCLESIARCHY) { scr_event_log("", "Enemy Leader Assassinated: Ecclesiarchy Prioress"); } - if (enemy == 6) { + if (enemy == eFACTION.ELDAR) { scr_event_log("", "Enemy Leader Assassinated: Eldar Farseer"); } - if (enemy == 7) { + if (enemy == eFACTION.ORK) { scr_event_log("", "Enemy Leader Assassinated: Ork Warboss"); - if (Warlord != 0) { + if (instance_exists(Warlord)) { with (Warlord) { kill_warboss(); } } } - if (enemy == 8) { + if (enemy == eFACTION.TAU) { scr_event_log("", "Enemy Leader Assassinated: Tau Diplomat"); } - if (enemy == 10) { + if (enemy == eFACTION.CHAOS) { scr_event_log("", "Enemy Leader Assassinated: Chaos Lord"); } } @@ -715,10 +697,10 @@ var inq_eated = false; if (obj_ini.omophagea) { var eatme = roll_dice_chapter(1, 100, "high"); - if ((enemy == 13) || (enemy == 9) || (battle_special == "ship_demon")) { + if ((enemy == eFACTION.NECRONS) || (enemy == eFACTION.TYRANIDS) || (battle_special == "ship_demon")) { eatme += 100; } - if ((enemy == 10) && (battle_object.p_traitors[battle_id] == 7)) { + if ((enemy == eFACTION.CHAOS) && (battle_object.p_traitors[battle_id] == 7)) { eatme += 200; } @@ -867,14 +849,14 @@ if (obj_ini.omophagea) { } } -if ((inq_eated == false) && (obj_ncombat.sorcery_seen >= 2)) { +if ((inq_eated == false) && (sorcery_seen >= 2)) { scr_loyalty("Use of Sorcery", "+"); newline = "Inquisitor " + string(obj_controller.inquisitor[1]) + " witnessed your Chapter using sorcery."; scr_event_log("green", string(newline)); scr_newtext(); } -if ((exterminatus > 0) && (dropping != 0)) { +if ((exterminatus > 0) && dropping) { newline = "Exterminatus has been succesfully placed."; newline_color = "yellow"; endline = 0; @@ -885,12 +867,12 @@ instance_activate_object(obj_star); instance_activate_object(obj_turn_end); //If not fleet based and... -if ((obj_ini.fleet_type != ePLAYER_BASE.HOME_WORLD) && (defeat == 1) && (dropping == 0)) { - var monastery_list = search_planet_features(battle_object.p_feature[obj_ncombat.battle_id], eP_FEATURES.MONASTERY); +if ((obj_ini.fleet_type != ePLAYER_BASE.HOME_WORLD) && (defeat == 1) && !dropping) { + var monastery_list = search_planet_features(battle_object.p_feature[battle_id], eP_FEATURES.MONASTERY); var monastery_count = array_length(monastery_list); if (monastery_count > 0) { for (var mon = 0; mon < monastery_count; mon++) { - battle_object.p_feature[obj_ncombat.battle_id][monastery_list[mon]].status = "destroyed"; + battle_object.p_feature[battle_id][monastery_list[mon]].status = "destroyed"; } if (obj_controller.und_gene_vaults == 0) { @@ -913,48 +895,47 @@ if ((obj_ini.fleet_type != ePLAYER_BASE.HOME_WORLD) && (defeat == 1) && (droppin if (player_defenses > 0) { defenses_lost = round(player_defenses * 0.75); } - if (battle_object.p_silo[obj_ncombat.battle_id] > 0) { - silos_lost = round(battle_object.p_silo[obj_ncombat.battle_id] * 0.75); + if (battle_object.p_silo[battle_id] > 0) { + silos_lost = round(battle_object.p_silo[battle_id] * 0.75); } - if (battle_object.p_lasers[obj_ncombat.battle_id] > 0) { - lasers_lost = round(battle_object.p_lasers[obj_ncombat.battle_id] * 0.75); + if (battle_object.p_lasers[battle_id] > 0) { + lasers_lost = round(battle_object.p_lasers[battle_id] * 0.75); } if (player_defenses < 30) { defenses_lost = player_defenses; } - if (battle_object.p_silo[obj_ncombat.battle_id] < 30) { - silos_lost = battle_object.p_silo[obj_ncombat.battle_id]; + if (battle_object.p_silo[battle_id] < 30) { + silos_lost = battle_object.p_silo[battle_id]; } - if (battle_object.p_lasers[obj_ncombat.battle_id] < 8) { - lasers_lost = battle_object.p_lasers[obj_ncombat.battle_id]; + if (battle_object.p_lasers[battle_id] < 8) { + lasers_lost = battle_object.p_lasers[battle_id]; } - var percent; - percent = 0; + var percent = 0; newline = ""; if (defenses_lost > 0) { percent = round((defenses_lost / player_defenses) * 100); newline = string(defenses_lost) + " Weapon Emplacements have been lost (" + string(percent) + "%)."; } if (silos_lost > 0) { - percent = round((silos_lost / battle_object.p_silo[obj_ncombat.battle_id]) * 100); + percent = round((silos_lost / battle_object.p_silo[battle_id]) * 100); if (defenses_lost > 0) { newline += " "; } newline += string(silos_lost) + $" Missile Silos have been lost ({percent}%)."; } if (lasers_lost > 0) { - percent = round((lasers_lost / battle_object.p_lasers[obj_ncombat.battle_id]) * 100); + percent = round((lasers_lost / battle_object.p_lasers[battle_id]) * 100); if ((silos_lost > 0) || (defenses_lost > 0)) { newline += " "; } newline += string(lasers_lost) + " Defense Lasers have been lost (" + string(percent) + "%)."; } - battle_object.p_defenses[obj_ncombat.battle_id] -= defenses_lost; - battle_object.p_silo[obj_ncombat.battle_id] -= silos_lost; - battle_object.p_lasers[obj_ncombat.battle_id] -= lasers_lost; + battle_object.p_defenses[battle_id] -= defenses_lost; + battle_object.p_silo[battle_id] -= silos_lost; + battle_object.p_lasers[battle_id] -= lasers_lost; if (defenses_lost + silos_lost + lasers_lost > 0) { newline_color = "red"; scr_newtext(); @@ -988,11 +969,9 @@ if (defeat == 1) { } } -gene_slaves = []; +obj_ini.gene_slaves = []; instance_deactivate_object(obj_star); instance_deactivate_object(obj_ground_mission); LOGGER.debug($"{started}"); -/* */ -/* */ diff --git a/objects/obj_ncombat/Alarm_6.gml b/objects/obj_ncombat/Alarm_6.gml index aec8c6c53f..2904002e0a 100644 --- a/objects/obj_ncombat/Alarm_6.gml +++ b/objects/obj_ncombat/Alarm_6.gml @@ -1,30 +1,3 @@ if (battle_over == 1) { exit; } - -/*if (messages_to_show = 24){ - if (enemy_forces<=0) or (!instance_exists(obj_enunit)) and (defeat_message=0){defeat_message=1; - newline_color="yellow";newline="Enemy Forces Defeated";timer_maxspeed=0; - timer_speed=0;timer=0;started=2;messages_shown=105;// done=1;// alarm[3]=-1; - scr_newtext();exit; - } - if (player_forces<=0) and (defeat_message=0){defeat_message=1; - newline_color="yellow";newline=string(global.chapter_name)+" Defeated"; - timer_maxspeed=0;timer_speed=0;started=4;messages_shown=105;defeat=1;// done=1; - scr_newtext();exit; - } - if (instance_exists(obj_enunit)){ - if (timer_stage=2){ - timer_stage=3; - timer=0; - } - if (timer_stage=4){ - timer_stage=5; - timer=0; - } - } -} -*/ - -/* */ -/* */ diff --git a/objects/obj_ncombat/Alarm_7.gml b/objects/obj_ncombat/Alarm_7.gml index 9e380eb233..e2e0f6cb17 100644 --- a/objects/obj_ncombat/Alarm_7.gml +++ b/objects/obj_ncombat/Alarm_7.gml @@ -12,7 +12,7 @@ try { // If battling own dudes, then remove the loyalists after the fact - if (enemy == 1) { + if (enemy == eFACTION.PLAYER) { var cleann = array_create(11, false); with (obj_enunit) { for (var q = 1; q <= 700; q++) { @@ -217,13 +217,13 @@ try { } } - if ((enemy == 5) && (obj_controller.faction_status[eFACTION.ECCLESIARCHY] != "War")) { + if ((enemy == eFACTION.ECCLESIARCHY) && (obj_controller.faction_status[eFACTION.ECCLESIARCHY] != "War")) { obj_controller.loyalty -= 50; obj_controller.loyalty_hidden -= 50; decare_war_on_imperium_audiences(); } - if ((exterminatus > 0) && (dropping != 0) && (string_count("mech", battle_special) == 0)) { + if ((exterminatus > 0) && dropping && (string_count("mech", battle_special) == 0)) { scr_destroy_planet(1); } @@ -263,13 +263,13 @@ try { scr_recent("battle_defeat", $"{enemy}, {final_marine_deaths + final_command_deaths}"); } - if (((dropping == 1) || (attacking == 1)) && (string_count("_attack", battle_special) == 0) && (string_count("mech", battle_special) == 0) && (string_count("ruins", battle_special) == 0) && (battle_special != "ship_demon")) { + if ((dropping || (attacking == 1)) && (string_count("_attack", battle_special) == 0) && (string_count("mech", battle_special) == 0) && (string_count("ruins", battle_special) == 0) && (battle_special != "ship_demon")) { obj_controller.combat = 0; with (obj_drop_select) { instance_destroy(); } } - if ((dropping + attacking == 0) && (string_count("_attack", battle_special) == 0) && (string_count("mech", battle_special) == 0) && (string_count("ruins", battle_special) == 0) && (battle_special != "ship_demon") && (string_count("cs_meeting", battle_special) == 0)) { + if ((!dropping && attacking == 0) && (string_count("_attack", battle_special) == 0) && (string_count("mech", battle_special) == 0) && (string_count("ruins", battle_special) == 0) && (battle_special != "ship_demon") && (string_count("cs_meeting", battle_special) == 0)) { if (instance_exists(obj_turn_end)) { var _battle_index = obj_turn_end.current_battle; if (_battle_index < array_length(obj_turn_end.battle_object)) { @@ -291,9 +291,9 @@ try { } if ((string_count("ruins", battle_special) > 0) && (defeat == 1)) { //TODO this logic is wrong assumes all player units died in ruins - var _combat_star = find_star_by_name(obj_ncombat.battle_loc); + var _combat_star = find_star_by_name(battle_loc); if (_combat_star != noone) { - _combat_star.p_player[obj_ncombat.battle_id] -= obj_ncombat.world_size; + _combat_star.p_player[battle_id] -= world_size; } } @@ -321,7 +321,7 @@ try { obj_controller.disposition[4] += choose(0, 0, 1); } - scr_event_log("", "Inquisition Mission Completed: The Spyrer on {cur_star.name} {planet} has been removed.", cur_star.name); + scr_event_log("", $"Inquisition Mission Completed: The Spyrer on {cur_star.name} {planet} has been removed.", cur_star.name); scr_gov_disp(cur_star.name, planet, choose(1, 2, 3, 4)); instance_deactivate_object(obj_star); @@ -329,7 +329,7 @@ try { protect_raiders_battle_aftermath(); } else if (string_count("fallen", battle_special) > 0) { hunt_fallen_battle_aftermath(); - } else if ((defeat == 0) && (enemy == 9) && (battle_special == "tyranid_org")) { + } else if ((defeat == 0) && (enemy == eFACTION.TYRANIDS) && (battle_special == "tyranid_org")) { if (captured_gaunt > 1) { var _pop = instance_create(0, 0, obj_popup); _pop.image = "inquisition"; @@ -342,7 +342,7 @@ try { _pop.title = "Inquisition Mission Completed"; _pop.text = "You have captured a Gaunt organism- the Inquisitor is pleased with your work. The Tyranid will be stored until it may be retrieved. The mission is a success."; } - } else if ((enemy == 1) && (on_ship == true) && (defeat == 0)) { + } else if ((enemy == eFACTION.PLAYER) && (on_ship == true) && (defeat == 0)) { var diceh = roll_dice_chapter(1, 100, "high"); if (diceh <= 15) { @@ -366,7 +366,7 @@ try { } } - if (enemy == 1) { + if (enemy == eFACTION.PLAYER) { if ((battle_special == "cs_meeting_battle1") || (battle_special == "cs_meeting_battle2")) { obj_controller.diplomacy = 10; scr_toggle_diplomacy(); @@ -402,7 +402,7 @@ try { } } - if (enemy == 10) { + if (enemy == eFACTION.CHAOS) { if ((battle_special == "cs_meeting_battle10") && (defeat == 0)) { obj_controller.complex_event = false; obj_controller.diplomacy = 0; @@ -478,12 +478,7 @@ try { if (battle_special == "ship_demon") { if (defeat == 1) { - var ship, ship_hp, i; - i = -1; - repeat (51) { - i += 1; - ship[i] = obj_ini.ship[i]; - ship_hp[i] = obj_ini.ship_hp[i]; + for (var i = 0; i <= 50; i++) { if (i == battle_id) { obj_ini.ship_hp[i] = -50; scr_recent("ship_destroyed", obj_ini.ship[i], i); @@ -513,8 +508,8 @@ try { if (battle_special != "ChaosWarband") { with (obj_star) { - if (string_count("WL" + string(obj_ncombat.enemy), p_feature[obj_ncombat.battle_id]) > 0) { - p_feature[obj_ncombat.battle_id] = string_replace(p_feature[obj_ncombat.battle_id], "WL" + string(obj_ncombat.enemy) + "|", ""); + if (string_count("WL" + string(enemy), p_feature[battle_id]) > 0) { + p_feature[battle_id] = string_replace(p_feature[battle_id], "WL" + string(enemy) + "|", ""); } } } diff --git a/objects/obj_ncombat/Alarm_8.gml b/objects/obj_ncombat/Alarm_8.gml index 3065c5f81b..6a5b98ce43 100644 --- a/objects/obj_ncombat/Alarm_8.gml +++ b/objects/obj_ncombat/Alarm_8.gml @@ -1,5 +1,5 @@ if ((enemy_forces != 0) && (player_forces != 0) && (battle_over == 0)) { - if ((enemy == 6) && (timer_stage == 2)) { + if (timer_stage == 2) { timer_stage = 3; messages = 0; @@ -8,31 +8,7 @@ if ((enemy_forces != 0) && (player_forces != 0) && (battle_over == 0)) { random_messages = 0; priority = 0; messages_shown = 0; - } - - if ((enemy != 6) && (timer_stage == 2)) { - timer_stage = 3; - - messages = 0; - messages_to_show = 24; - largest = 0; - random_messages = 0; - priority = 0; - messages_shown = 0; - } - - if ((enemy == 6) && (timer_stage == 4)) { - timer_stage = 5; - - messages = 0; - messages_to_show = 24; - largest = 0; - random_messages = 0; - priority = 0; - messages_shown = 0; - } - - if ((enemy != 6) && (timer_stage == 4)) { + } else if (timer_stage == 4) { timer_stage = 5; messages = 0; diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index d48fdc7e4b..4c15f0137c 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -3,15 +3,15 @@ if (instance_number(obj_ncombat) > 1) { } set_zoom_to_default(); -hue = 0; - -turn_count = 0; LOGGER.info("Ground Combat Started"); audio_stop_sound(snd_royal); audio_play_sound(snd_battle, 0, true); audio_sound_gain(snd_battle, 1, 5000); +hue = 0; +turn_count = 0; + //limit on the size of the players forces allowed enter_pressed = 0; man_size_limit = 0; @@ -24,7 +24,7 @@ click_stall_timer = 0; formation_set = 0; on_ship = false; alpha_strike = 0; -Warlord = 0; +Warlord = noone; total_battle_exp_gain = 0; marines_to_recover = 0; vehicles_to_recover = 0; @@ -57,15 +57,19 @@ instance_create(0, 0, obj_centerline); local_forces = 0; battle_loc = ""; battle_climate = ""; -battle_id = 0; /// @type {Asset.GMObject.obj_star} -battle_object = 0; +if (instance_exists(obj_star)) { + battle_object = instance_nearest(x, y, obj_star); +} else { + battle_object = noone; + LOGGER.error("No obj_star instance found for combat; battle_object defaulted to noone"); +} +battle_id = 0; battle_mission = ""; battle_special = ""; battle_data = {}; defeat = 0; defeat_message = 0; -red_thirst = 0; fugg = 0; fugg2 = 0; battle_over = 0; @@ -113,13 +117,13 @@ started = 0; charged = 0; fadein = 40; -enemy = 0; +enemy = undefined; +enem = "Orks"; +enem_sing = "Ork"; threat = 0; fortified = 0; enemy_fortified = 0; wall_destroyed = 0; -enem = "Orks"; -enem_sing = "Ork"; flank_x = 0; player_forces = 0; @@ -179,7 +183,6 @@ seed_lost = 0; seed_harvestable = 0; units_saved_count = 0; units_saved_counts = {}; -vehicles_saved_counts = {}; command_saved = 0; vehicles_saved_count = 0; vehicles_saved_counts = {}; @@ -237,6 +240,8 @@ whirlwinds = 0; big_mofo = 10; +enemy_dudes = ""; + en_scouts = 0; en_tacticals = 0; en_sgts = 0; @@ -256,77 +261,35 @@ en_chaplains = 0; en_apothecaries = 0; en_big_mofo = 10; -en_important_dudes = 0; defending = true; // 1 is defensive -dropping = 0; // 0 is was on ground +dropping = false; // 0 is was on ground attacking = 0; // 1 means attacked from space/local time = floor(random(24)) + 1; terrain = ""; weather = ""; -ambushers = 0; -if (scr_has_adv("Ambushers")) { - ambushers = 1; -} -bolter_drilling = 0; -if (scr_has_adv("Bolter Drilling")) { - bolter_drilling = 1; -} -enemy_eldar = 0; -if (scr_has_adv("Enemy: Eldar")) { - enemy_eldar = 1; -} -enemy_fallen = 0; -if (scr_has_adv("Enemy: Fallen")) { - enemy_fallen = 1; -} -enemy_orks = 0; -if (scr_has_adv("Enemy: Orks")) { - enemy_orks = 1; -} -enemy_tau = 0; -if (scr_has_adv("Enemy: Tau")) { - enemy_tau = 1; -} -enemy_tyranids = 0; -if (scr_has_adv("Enemy: Tyranids")) { - enemy_tyranids = 1; -} -enemy_necrons = 0; -if (scr_has_adv("Enemy: Necrons")) { - enemy_necrons = 1; -} -lightning = 0; -if (scr_has_adv("Lightning Warriors")) { - lightning = 1; -} -siege = 0; -if (scr_has_adv("Siege Masters")) { - siege = 1; -} -slow = 0; -if (scr_has_adv("Devastator Doctrine")) { - slow = 1; -} -melee = 0; -if (scr_has_adv("Assault Doctrine")) { - melee = 1; -} -// -black_rage = 0; -if (scr_has_disadv("Black Rage")) { - black_rage = 1; - red_thirst = 1; -} -shitty_luck = 0; -if (scr_has_disadv("Shitty Luck")) { - shitty_luck = 1; -} -favoured_by_the_warp = 0; -if (scr_has_adv("Favoured By The Warp")) { - favoured_by_the_warp = 1; -} +global_melee = 1; +global_bolter = 1; +global_attack = 1; +global_defense = 1; + +ambushers = scr_has_adv("Ambushers"); +bolter_drilling = scr_has_adv("Bolter Drilling"); +enemy_eldar = scr_has_adv("Enemy: Eldar"); +enemy_fallen = scr_has_adv("Enemy: Fallen"); +enemy_orks = scr_has_adv("Enemy: Orks"); +enemy_tau = scr_has_adv("Enemy: Tau"); +enemy_tyranids = scr_has_adv("Enemy: Tyranids"); +enemy_necrons = scr_has_adv("Enemy: Necrons"); +lightning = scr_has_adv("Lightning Warriors"); +siege = scr_has_adv("Siege Masters"); +slow = scr_has_adv("Devastator Doctrine"); +melee = scr_has_adv("Assault Doctrine"); +black_rage = scr_has_disadv("Black Rage"); +red_thirst = scr_has_disadv("Black Rage"); +shitty_luck = scr_has_disadv("Shitty Luck"); +favoured_by_the_warp = scr_has_adv("Favoured By The Warp"); lyman = obj_ini.lyman; // drop pod penalties omophagea = obj_ini.omophagea; // feast @@ -336,81 +299,3 @@ betchers = obj_ini.betchers; // slight melee penalty catalepsean = obj_ini.catalepsean; // minor global attack decrease occulobe = obj_ini.occulobe; // penalty if morning and susceptible to flash grenades mucranoid = obj_ini.mucranoid; // chance to short-circuit - -global_melee = 1; -global_bolter = 1; -global_attack = 1; -global_defense = 1; - -if ((ambushers == 1) && (ambushers == 999)) { - global_attack = global_attack * 1.1; -} -if (bolter_drilling == 1) { - global_bolter = global_bolter * 1.1; -} -if ((enemy_eldar == 1) && (enemy == 6)) { - global_attack = global_attack * 1.1; - global_defense = global_defense * 1.1; -} -if ((enemy_fallen == 1) && (enemy == 10)) { - global_attack = global_attack * 1.1; - global_defense = global_defense * 1.1; -} -if ((enemy_orks == 1) && (enemy == 7)) { - global_attack = global_attack * 1.1; - global_defense = global_defense * 1.1; -} -if ((enemy_tau == 1) && (enemy == 8)) { - global_attack = global_attack * 1.1; - global_defense = global_defense * 1.1; -} -if ((enemy_tyranids == 1) && (enemy == 9)) { - global_attack = global_attack * 1.1; - global_defense = global_defense * 1.1; -} -if ((enemy_necrons == 1) && (enemy == 13)) { - global_attack = global_attack * 1.1; - global_defense = global_defense * 1.1; -} - -if ((siege == 1) && (enemy_fortified >= 3) && (defending == false)) { - global_attack = global_attack * 1.2; -} - -if (slow == 1) { - global_attack -= 0.1; - global_defense += 0.2; -} -if (lightning == 1) { - global_attack += 0.2; - global_defense -= 0.1; -} -if (melee == 1) { - global_melee = global_melee * 1.15; -} -if (shitty_luck == 1) { - global_defense = global_defense * 0.9; -} -if ((lyman == 1) && (dropping == 1)) { - global_attack = global_attack * 0.85; - global_defense = global_defense * 0.9; -} -if (ossmodula == 1) { - global_attack = global_attack * 0.95; - global_defense = global_defense * 0.95; -} -if (betchers == 1) { - global_melee = global_melee * 0.95; -} -if (catalepsean == 1) { - global_attack = global_attack * 0.95; -} -if (occulobe == 1) { - if ((time == 5) || (time == 6)) { - global_attack = global_attack * 0.7; - global_defense = global_defense * 0.8; - } -} - -enemy_dudes = ""; -global_defense = 2 - global_defense; diff --git a/objects/obj_ncombat/Draw_0.gml b/objects/obj_ncombat/Draw_0.gml index 545c40124b..ca2a6a3f76 100644 --- a/objects/obj_ncombat/Draw_0.gml +++ b/objects/obj_ncombat/Draw_0.gml @@ -7,34 +7,11 @@ draw_rectangle(818, 235, 1578, 666, 0); draw_set_color(CM_GREEN_COLOR); -var l; -l = 0; -draw_set_alpha(1); -draw_rectangle(0 + l, 0 + l, 800 - l, 900 - l, 1); -l += 1; -draw_set_alpha(0.75); -draw_rectangle(0 + l, 0 + l, 800 - l, 900 - l, 1); -l += 1; -draw_set_alpha(0.5); -draw_rectangle(0 + l, 0 + l, 800 - l, 900 - l, 1); -l += 1; -draw_set_alpha(0.25); -draw_rectangle(0 + l, 0 + l, 6800 - l, 900 - l, 1); - -l = 0; -draw_set_alpha(1); -draw_rectangle(818 + l, 235 + l, 1578 - l, 666 - l, 1); -l += 1; -draw_set_alpha(0.75); -draw_rectangle(818 + l, 235 + l, 1578 - l, 666 - l, 1); -l += 1; -draw_set_alpha(0.5); -draw_rectangle(818 + l, 235 + l, 1578 - l, 666 - l, 1); -l += 1; -draw_set_alpha(0.25); -draw_rectangle(818 + l, 235 + l, 1578 - l, 666 - l, 1); - -l = 0; +for (var l = 0; l <= 3; l++) { + draw_set_alpha(1 - (0.25 * l)); + draw_rectangle(0 + l, 0 + l, 800 - l, 900 - l, 1); + draw_rectangle(818 + l, 235 + l, 1578 - l, 666 - l, 1); +} draw_set_alpha(1); draw_set_font(fnt_40k_14); @@ -51,6 +28,7 @@ if ((display_p2 > 0) && (enemy_forces > 0)) { draw_set_halign(fa_left); +var l = 0; // When pinned to the bottom (log_scroll == 0) the live 45-row window is drawn exactly as before; // when scrolled up, page back through the retained log_history instead. var _log_total = array_length(log_history); @@ -148,4 +126,5 @@ draw_set_alpha(1); draw_set_color(c_black); draw_set_alpha(fadein / 30); draw_rectangle(0, 0, 1600, 900, 0); +draw_set_color(c_white); draw_set_alpha(1); diff --git a/objects/obj_ncombat/KeyPress_13.gml b/objects/obj_ncombat/KeyPress_13.gml index 858bf01ac6..86130f5ea2 100644 --- a/objects/obj_ncombat/KeyPress_13.gml +++ b/objects/obj_ncombat/KeyPress_13.gml @@ -56,9 +56,6 @@ if (!instance_exists(obj_popup)) { timer_stage = 1; timer = 100; - if (enemy == 30) { - timer_stage = 3; - } if (battle_special == "ship_demon") { timer_stage = 3; } diff --git a/objects/obj_ncombat/Step_0.gml b/objects/obj_ncombat/Step_0.gml index 5a71266b52..f98e7d04eb 100644 --- a/objects/obj_ncombat/Step_0.gml +++ b/objects/obj_ncombat/Step_0.gml @@ -36,9 +36,11 @@ log_scroll = clamp(log_scroll, 0, _log_max_scroll); if (fadein > -30) { fadein -= 1; } + if (cd >= 0) { cd -= 1; } + if (click_stall_timer >= 0) { click_stall_timer -= 1; } @@ -47,6 +49,7 @@ if (click_stall_timer >= 0) { if (!instance_exists(obj_enunit)) { enemy_forces = 0; } + if (!instance_exists(obj_pnunit)) { player_forces = 0; } @@ -54,6 +57,7 @@ if (!instance_exists(obj_pnunit)) { if (fack == 1) { instance_activate_object(obj_pnunit); } + instance_activate_object(obj_centerline); instance_activate_object(obj_cursor); @@ -77,11 +81,11 @@ if (((fugg >= 60) || (fugg2 >= 60)) && (messages_shown == 0) && (messages_to_sho } if (((messages_shown == 999) || (messages == 0)) && (timer_stage == 2)) { newline_color = "yellow"; - if (obj_ncombat.enemy != 6) { + if (enemy != eFACTION.ELDAR) { combat_emit_enemy_status(); } newline_color = "yellow"; - if (obj_ncombat.enemy == 6) { + if (enemy == eFACTION.ELDAR) { if (((player_forces <= 0) || (!instance_exists(obj_pnunit))) && (defeat_message == 0)) { defeat_message = 1; newline = string(global.chapter_name) + " Defeated"; @@ -102,7 +106,7 @@ if (((fugg >= 60) || (fugg2 >= 60)) && (messages_shown == 0) && (messages_to_sho // show_message("Shown: "+string(messages_shown)+"#Messages: "+string(messages)+"#Timer Stage: "+string(timer_stage)); if (((messages_shown == 999) || (messages == 0)) && ((timer_stage == 4) || (timer_stage == 5)) && (four_show == 0)) { newline_color = "yellow"; - if (obj_ncombat.enemy != 6) { + if (enemy != eFACTION.ELDAR) { if (((player_forces <= 0) || (!instance_exists(obj_pnunit))) && (defeat_message == 0)) { defeat_message = 1; newline = string(global.chapter_name) + " Defeated"; @@ -114,7 +118,7 @@ if (((fugg >= 60) || (fugg2 >= 60)) && (messages_shown == 0) && (messages_to_sho } } newline_color = "yellow"; - if (obj_ncombat.enemy == 6) { + if (enemy == eFACTION.ELDAR) { if (((enemy_forces <= 0) || (!instance_exists(obj_enunit))) && (defeat_message == 0)) { defeat_message = 1; newline = "Enemy Forces Defeated"; @@ -147,6 +151,7 @@ if ((timer_stage == 2) && (((fugg > 60) && (messages == 0)) || (fugg > COMBAT_ST if (timer_stage != 2) { fugg = 0; } + if (timer_stage == 4) { fugg2 += 1; } diff --git a/objects/obj_p_fleet/Alarm_1.gml b/objects/obj_p_fleet/Alarm_1.gml index f53c6325b7..ccd0e17df9 100644 --- a/objects/obj_p_fleet/Alarm_1.gml +++ b/objects/obj_p_fleet/Alarm_1.gml @@ -6,11 +6,7 @@ try { exit; } else if (action == "") { var spid = instance_nearest(x, y, obj_star); - spid.present_fleet[1] += 1; - if (spid.vision == 0) { - spid.vision = 1; - } - orbiting = spid; + set_fleet_orbiting(self, spid); if ((orbiting != noone) && instance_exists(orbiting)) { if (orbiting.visited == 0) { diff --git a/objects/obj_p_fleet/Alarm_4.gml b/objects/obj_p_fleet/Alarm_4.gml index 73eca50db5..12a03b108e 100644 --- a/objects/obj_p_fleet/Alarm_4.gml +++ b/objects/obj_p_fleet/Alarm_4.gml @@ -1,4 +1,4 @@ -var eta = calculate_fleet_eta(x, y, action_x, action_y, action_spd, false, false, warp_able); +var eta = calculate_fleet_eta(x, y, action_x, action_y, action_spd, true, true, warp_able); action_eta = eta; diff --git a/objects/obj_p_ship/Draw_0.gml b/objects/obj_p_ship/Draw_0.gml index 2ec9036cd3..c56a1205ca 100644 --- a/objects/obj_p_ship/Draw_0.gml +++ b/objects/obj_p_ship/Draw_0.gml @@ -34,7 +34,6 @@ if (name != "") { draw_self(); shader_reset(); - draw_set_color(CM_GREEN_COLOR); draw_set_font(fnt_info); draw_set_halign(fa_center); @@ -42,25 +41,10 @@ if (name != "") { // draw_sprite(spr_force_icon,0,x-16,y+12); scr_image("ui/force", 1, x - 16 - 32, y + 12 - 32, 64, 64); - draw_set_color(0); - draw_text(x - 16, y + 12, string_hash_to_newline(string(boarders))); - draw_text(x - 16 - 1, y + 12 - 1, string_hash_to_newline(string(boarders))); - draw_text(x - 16 + 1, y + 12 + 1, string_hash_to_newline(string(boarders))); - draw_text(x - 16 + 1, y + 12, string_hash_to_newline(string(boarders))); - draw_set_color(c_white); - draw_text(x - 16, y + 12, string_hash_to_newline(string(boarders))); + draw_text_outline(x - 16, y + 12, boarders,,c_white); } - draw_set_color(CM_GREEN_COLOR); - if (maxhp != 0) { - var _value = shields <= 0 ? hp / maxhp : shields / maxshields; - - if (obj_controller.zoomed == 0) { - draw_text(x, y - sprite_height, string_hash_to_newline(string(floor(_value * 100)) + "%")); - } else { - draw_text_transformed(x, y - sprite_height, string_hash_to_newline(string(floor(_value * 100)) + "%"), 2, 2, 0); - } - } + draw_ship_status_overlay(self, CM_GREEN_COLOR, COL_REQUISITION); if (master_present != 0) { draw_sprite_ext(spr_popup_select, 0, x, y, 2, 2, 0, c_white, 1); diff --git a/objects/obj_pnunit/Alarm_3.gml b/objects/obj_pnunit/Alarm_3.gml index a1f7f38b1b..8bb63ddfab 100644 --- a/objects/obj_pnunit/Alarm_3.gml +++ b/objects/obj_pnunit/Alarm_3.gml @@ -22,7 +22,7 @@ try { if (men > 0) { var raar = 0, miss = "", r_lost = 0; - for (var raar; raar < (men + dreads); raar++) { + for (var raar = 0; raar < (men + dreads); raar++) { r_roll = floor(random(1000)) + 1; if (obj_ncombat.player_forces < (obj_ncombat.player_max * 0.75)) { r_roll -= 8; @@ -48,10 +48,10 @@ try { //marine_ranged[raar]=0.75; obj_ncombat.red_thirst += 1; if (r_lost == 1) { - miss += "Battle Brother " + string(obj_ini.name[marine_co[raar]][marine_id[raar]]) + ", "; + miss += "Battle Brother " + string(unit_struct[raar].name()) + ", "; } if (r_lost > 1) { - miss += string(obj_ini.name[marine_co[raar]][marine_id[raar]]) + ", "; + miss += string(unit_struct[raar].name()) + ", "; } } } diff --git a/objects/obj_popup/Alarm_0.gml b/objects/obj_popup/Alarm_0.gml index aafda1e01e..f5fd2074f1 100644 --- a/objects/obj_popup/Alarm_0.gml +++ b/objects/obj_popup/Alarm_0.gml @@ -12,7 +12,7 @@ if (battle_special == 3.1) { instance_activate_all(); instance_create(0, 0, obj_ncombat); - obj_ncombat.enemy = 3; + obj_ncombat.enemy = eFACTION.MECHANICUS; obj_ncombat.battle_object = that; obj_ncombat.battle_loc = loc; obj_ncombat.battle_id = planet; diff --git a/objects/obj_popup/Create_0.gml b/objects/obj_popup/Create_0.gml index f93e1217f3..633e6523b4 100644 --- a/objects/obj_popup/Create_0.gml +++ b/objects/obj_popup/Create_0.gml @@ -120,14 +120,14 @@ company_promote_data = [ } //10th company ]; -role_name = array_create(11, ""); -role_exp = array_create(11, 0); +role_name = array_create(12, ""); +role_exp = array_create(12, 0); // TODO: connect this logic with the other_manage_data() to reduce verboseness; get_unit_promotion_options = function() { var spec = 0; - role_name = array_create(11, ""); - role_exp = array_create(11, 0); + array_set_value(role_name, ""); + array_set_value(role_exp, 0); var i = 0; // this area does the required exp for roles per company if (unit_role == obj_ini.role[100][16]) { diff --git a/objects/obj_popup/Destroy_0.gml b/objects/obj_popup/Destroy_0.gml index 5f061ba49b..25e050fb3e 100644 --- a/objects/obj_popup/Destroy_0.gml +++ b/objects/obj_popup/Destroy_0.gml @@ -15,7 +15,7 @@ if ((image == "chaos_symbol") && (title == "Concealed Heresy") && instance_exist obj_ncombat.battle_id = obj_controller.selecting_planet; obj_ncombat.dropping = 0; obj_ncombat.attacking = 10; - obj_ncombat.enemy = 10; + obj_ncombat.enemy = eFACTION.CHAOS; obj_ncombat.formation_set = 2; obj_ncombat.leader = 1; obj_ncombat.threat = 5; @@ -72,7 +72,7 @@ if (instance_exists(obj_controller)) { obj_ncombat.dropping = 0; obj_ncombat.attacking = 1; obj_ncombat.local_forces = 0; - obj_ncombat.enemy = 10; + obj_ncombat.enemy = eFACTION.CHAOS; obj_ncombat.threat = 3; with (obj_star) { diff --git a/objects/obj_temp_build/Create_0.gml b/objects/obj_temp_build/Create_0.gml index 23d429f387..2b0c1461d1 100644 --- a/objects/obj_temp_build/Create_0.gml +++ b/objects/obj_temp_build/Create_0.gml @@ -1,5 +1,5 @@ target = noone; -planet = (variable_instance_exists(id, "planet") && planet > 0) ? planet : 0; +planet = noone; lair = false; arsenal = false; diff --git a/objects/obj_turn_end/Mouse_56.gml b/objects/obj_turn_end/Mouse_56.gml index 9a267f3e77..c547d21d17 100644 --- a/objects/obj_turn_end/Mouse_56.gml +++ b/objects/obj_turn_end/Mouse_56.gml @@ -23,6 +23,12 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e if ((mouse_x >= xxx + 272) && (mouse_y >= yyy + 354) && (mouse_x < xxx + 399) && (mouse_y < yyy + 389)) { // Fight fight fight, space + var _battle_fleet = battle_pobject[current_battle]; + if (_battle_fleet.capital_number + _battle_fleet.frigate_number + _battle_fleet.escort_number <= 0) { + alarm[4] = 1; + exit; + } + obj_controller.cooldown = 8000; instance_activate_all(); @@ -149,7 +155,7 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e obj_ncombat.fortified = _planet_data.fortification_level; } - if (obj_ncombat.enemy == 13) { + if (obj_ncombat.enemy == eFACTION.NECRONS) { obj_ncombat.fortified = 0; } @@ -158,10 +164,8 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e if (_enemy == eFACTION.IMPERIUM) { obj_ncombat.threat = min(1000000, _planet_data.guardsmen); - } else if (obj_ncombat.enemy < 14 && _enemy > 5) { + } else if (obj_ncombat.enemy <= eFACTION.NECRONS && _enemy >= eFACTION.ELDAR) { obj_ncombat.threat = _planet_data.planet_forces[_enemy]; - } else if (_enemy == 30) { - obj_ncombat.threat = 1; } _roster = new Roster(); diff --git a/scripts/Armamentarium/Armamentarium.gml b/scripts/Armamentarium/Armamentarium.gml index 72215cedeb..b6d0b4c71c 100644 --- a/scripts/Armamentarium/Armamentarium.gml +++ b/scripts/Armamentarium/Armamentarium.gml @@ -1,4 +1,6 @@ -#macro SHOP_SELL_MOD 0.8 +#macro SHOP_SELL_MOD 0.5 +#macro SHOP_BUY_MIN_MOD 0.5 +#macro SHOP_SELL_MIN_MOD 0.1 #macro ROGUE_TRADER_DISCOUNT 0.8 #macro SHOP_FORGE_MOD 6 #macro WAR_PENALTY 0.5 @@ -22,6 +24,7 @@ function ShopItem(_name) constructor { value = 0; buy_cost = 0; + sell_cost = 0; buyable = true; buy_cost_mod = 1; best_seller = "unknown"; @@ -95,7 +98,12 @@ function ShopItem(_name) constructor { forge_cost_mod = _forge_mod; forge_cost = round(value * SHOP_FORGE_MOD * forge_cost_mod); } else { - buy_cost = round(value * buy_cost_mod); + var _min_buy_cost = round(value * SHOP_BUY_MIN_MOD); + buy_cost = max(round(value * buy_cost_mod), _min_buy_cost); + var _sell_mod = SHOP_SELL_MOD * (2.0 - buy_cost_mod); + _sell_mod = clamp(_sell_mod, SHOP_SELL_MIN_MOD, 1.0); + sell_cost = round(value * _sell_mod); + sell_cost = min(sell_cost, buy_cost); } }; @@ -142,7 +150,7 @@ function ShopItem(_name) constructor { static _get_tech_display_name = function(_tech_key) { static _name_cache = {}; - if (variable_struct_exists(_name_cache, _tech_key)) { + if (struct_exists(_name_cache, _tech_key)) { return _name_cache[$ _tech_key]; } @@ -245,7 +253,7 @@ function STCResearchPanel(_controller_ref, _on_change_callback) constructor { return; } - var _level = variable_instance_get(controller, $"stc_{_focus}"); + var _level = variable_instance_get(controller, $"stc_{_focus}") ?? 0; var _remaining = (STC_POINTS_PER_LEVEL * (_level + 1)) - controller.stc_research[$ _focus]; var _months = ceil(_remaining / _points_per_turn); @@ -492,10 +500,10 @@ function Armamentarium(_controller) constructor { value: "technologies", } ]; - + category_dropdown = new UIDropdown(_cat_options, 200); - - _cat_options = []; + + var _comp_options = []; var _roman = [ "I", "II", @@ -506,16 +514,16 @@ function Armamentarium(_controller) constructor { "VII", "VIII", "IX", - "X" + "X", ]; - + var _roman_length = array_length(_roman); - for (var i = 0; i < min(obj_ini.companies, _roman_length); i++) { - array_push(_cat_options, {label: $"{_roman[i]} Company", value: i + 1}); + for (var i = 0, _limit = min(obj_ini.companies, _roman_length); i < _limit; i++) { + array_push(_comp_options, {label: $"{_roman[i]} Company", value: i + 1}); } - company_dropdown = new UIDropdown(_cat_options, 180); + company_dropdown = new UIDropdown(_comp_options, 180); // --- Data Storage --- shop_items = { @@ -634,7 +642,8 @@ function Armamentarium(_controller) constructor { forge_cost_mod = max(0.1, 1.0 - (discount_stc / 100)); - var _has_hangars = array_length(controller.player_forge_data.vehicle_hanger) > 0; + var _hangers = controller.player_forge_data[$ "vehicle_hanger"] ?? []; + var _has_hangars = array_length(_hangers) > 0; for (var i = 0, len = array_length(master_catalog); i < len; i++) { /// @type {Struct.ShopItem} @@ -829,15 +838,14 @@ function Armamentarium(_controller) constructor { /// @desc Sells an item back to the market. /// @param {Struct.ShopItem} _item The item to sell. /// @param {real} _count Quantity to sell. - /// @param {real} _modifier Price multiplier for selling. /// @returns {bool} Success of the transaction. - static _sell_item = function(_item, _count, _modifier) { + static _sell_item = function(_item, _count) { if (_item.stocked < 1) { return false; } var _sold_count = min(_item.stocked, _count); - var _sell_price = round((_item.value * _modifier) * _sold_count); + var _sell_price = _item.sell_cost * _sold_count; scr_add_item(_item.name, -_sold_count, "standard"); _item.stocked -= _sold_count; @@ -858,11 +866,12 @@ function Armamentarium(_controller) constructor { // 1. Warships if (shop_type == "ships") { add_event({e_id: "ship_construction", ship_class: _item.name, duration: _item.request_duration}); + audio_play_sound(snd_click, 10, false); return; } // 2. Vehicles - if (variable_struct_exists(global.vehicles, _item.name)) { + if (struct_exists(global.vehicles, _item.name)) { repeat (_count) { scr_add_vehicle(_item.name, target_comp, {}); } @@ -1021,7 +1030,7 @@ function Armamentarium(_controller) constructor { tooltip_text: _can_forge ? "Add to Forge Queue" : _item.get_missing_technologies_tooltip(), x1: 1530, y1 : _y + 2 - }) + }); forge_button.draw(_can_forge); @@ -1055,15 +1064,15 @@ function Armamentarium(_controller) constructor { var _can_sell = !array_contains(["ships", "vehicles"], shop_type) && _item.stocked > 0; sell_button.update({ - tooltip_text : $"Sell for {round(_item.value * SHOP_SELL_MOD)} (x{SHOP_SELL_MOD} of value)", + tooltip_text : $"Sell for {_item.sell_cost * min(_item.stocked, _count)}", x1 : 1480, y1 : _y + 2 - }) + }); sell_button.draw(_can_sell); if (sell_button.is_clicked) { - _sell_item(_item, _count, SHOP_SELL_MOD); + _sell_item(_item, _count); } draw_set_alpha(1); @@ -1170,7 +1179,7 @@ function Armamentarium(_controller) constructor { for (var j = 0, _rlen = array_length(_reqs); j < _rlen; j++) { var _tech_key = _reqs[j]; - if (!variable_struct_exists(_unlock_map, _tech_key)) { + if (!struct_exists(_unlock_map, _tech_key)) { _unlock_map[$ _tech_key] = []; } array_push(_unlock_map[$ _tech_key], _item.display_name); diff --git a/scripts/scr_ComplexSet/scr_ComplexSet.gml b/scripts/scr_ComplexSet/scr_ComplexSet.gml index 8764033b01..af200469ba 100644 --- a/scripts/scr_ComplexSet/scr_ComplexSet.gml +++ b/scripts/scr_ComplexSet/scr_ComplexSet.gml @@ -1,8 +1,9 @@ +/// @param {String|Array} style +/// @return {Bool} function scr_has_style(style) { var result = false; if (!is_array(style)) { try { - var result; if (instance_exists(obj_creation)) { result = array_contains(obj_creation.buttons.culture_styles.selections(), style); } else { @@ -14,25 +15,27 @@ function scr_has_style(style) { } } else { for (var i = 0; i < array_length(style); i++) { - var _specific = scr_has_style(style[i]); - if (_specific) { - return _specific; + result = scr_has_style(style[i]); + if (result) { + break; } } } return result; } +/// @param {Array} data +/// @return {Bool} function valid_sprite_transform_data(data) { return is_array(data) && array_length(data) == 4; } -///@func sprite_get_uvs_transformed(sprite1, subimg1, sprite2, subimg2) -///@desc Returns a transform array that can be used in a shader to align the UVs of sprite2 with sprite1 (takes cropping into account) -///@param spr1 {Sprite} The sprite align the UVs to -///@param subimg1 {real} The sprite subimage to align the UVs to -///@param spr2 {Sprite} The sprite with UVs that will be aligned -///@param subimg1 {real} The sprite subimage with UVs that will be aligned +/// @desc Returns a transform array that can be used in a shader to align the UVs of _spr2 with _spr1 (takes cropping into account) +/// @param {Asset.GMSprite} _spr1 The sprite align the UVs to +/// @param {Real} _subimg1 The sprite subimage to align the UVs to +/// @param {Asset.GMSprite} _spr2 The sprite with UVs that will be aligned +/// @param {Real} _subimg2 The sprite subimage with UVs that will be aligned +/// @return {Array} function sprite_get_uvs_transformed(_spr1, _subimg1, _spr2, _subimg2) { //Get the uvs of the sprites var _uv1 = sprite_get_uvs(_spr1, _subimg1); @@ -83,15 +86,132 @@ function sprite_get_uvs_transformed(_spr1, _subimg1, _spr2, _subimg2) { return [_x_offset, _y_offset, _x_scale, _y_scale]; } +/// @param {Struct.TTRPG_stats} _unit function ComplexSet(_unit) constructor { overides = {}; subcomponents = {}; unit_armour = _unit.armour(); unit = _unit; draw_helms = instance_exists(obj_creation) ? obj_creation.draw_helms : obj_controller.draw_helms; - //draw_helms = false; current_texture_draws = {}; + _has_exceptions = false; + exceptions = []; + + left_arm_data = []; + + right_arm_data = []; + + hand_scratchpads = [ + { + total: 0, + sources: [0], + offsets: [0], + source_frames: [0], + flip_x: false + }, + { + total: 0, + sources: [0], + offsets: [0], + source_frames: [0], + flip_x: true + } + ]; + + // Tracks sprites that ComplexSet owns (e.g. weapon duplicates) for cleanup + owned_sprites = []; + + offsets = []; + position_overides = {}; + shadow_set = {}; + + blocked = []; + banned = []; + variation_map = { + backpack: unit.get_body_data("backpack_variation", "torso"), + armour: unit.get_body_data("armour_choice", "torso"), + chest_variants: unit.get_body_data("chest_variation", "torso"), + thorax_variants: unit.get_body_data("thorax_variation", "torso"), + leg_variants: unit.get_body_data("leg_variants", "left_leg"), + left_leg: unit.get_body_data("leg_variants", "left_leg"), + right_leg: unit.get_body_data("leg_variants", "right_leg"), + left_shin: unit.get_body_data("shin_variant", "left_leg"), + right_shin: unit.get_body_data("shin_variant", "right_leg"), + left_knee: unit.get_body_data("knee_variant", "left_leg"), + right_knee: unit.get_body_data("knee_variant", "right_leg"), + left_trim: unit.get_body_data("trim_variation", "left_arm"), + right_trim: unit.get_body_data("trim_variation", "right_arm"), + left_arm: unit.get_body_data("variation", "left_arm"), + right_arm: unit.get_body_data("variation", "right_arm"), + gorget: unit.get_body_data("variant", "throat"), + right_pauldron_icons: unit.get_body_data("pad_variation", "right_arm"), + left_pauldron_icons: unit.get_body_data("pad_variation", "left_arm"), + right_pauldron_base: unit.get_body_data("pad_variation", "right_arm"), + left_pauldron_base: unit.get_body_data("pad_variation", "left_arm"), + right_pauldron_embeleshments: unit.get_body_data("pad_variation", "right_arm"), + left_pauldron_embeleshments: unit.get_body_data("pad_variation", "left_arm"), + right_pauldron_hangings: unit.get_body_data("pad_variation", "right_arm"), + left_pauldron_hangings: unit.get_body_data("pad_variation", "left_arm"), + left_personal_livery: unit.get_body_data("personal_livery", "left_arm"), + tabbard: unit.get_body_data("tabbard_variation", "torso"), + robe: unit.get_body_data("tabbard_variation", "torso"), + crest: unit.get_body_data("crest_variation", "head"), + head: unit.get_body_data("variation", "head"), + bare_head: unit.get_body_data("variation", "head"), + bare_neck: unit.get_body_data("variation", "head"), + bare_eyes: unit.get_body_data("variation", "head"), + mouth_variants: unit.get_body_data("variant", "jaw"), + left_eye: unit.get_body_data("variant", "left_eye"), + right_eye: unit.get_body_data("variant", "right_eye"), + crown: unit.get_body_data("crown_variation", "head"), + forehead: unit.get_body_data("forehead_variation", "head"), + backpack_decoration: unit.get_body_data("backpack_decoration_variation", "torso"), + belt: unit.get_body_data("belt_variation", "torso"), + cloak: unit.get_body_data("variant", "cloak"), + cloak_image: unit.get_body_data("image_0", "cloak"), + cloak_trim: unit.get_body_data("image_1", "cloak"), + backpack_augment: unit.get_body_data("backpack_augment_variation", "torso"), + chest_fastening: unit.get_body_data("chest_fastening", "torso"), + left_weapon: unit.get_body_data("weapon_variation", "left_arm"), + right_weapon: unit.get_body_data("weapon_variation", "right_arm"), + necklace: unit.get_body_data("hanging_variant", "throat"), + foreground_item: unit.get_body_data("variant", "throat"), + }; + + component_final_draw_x = 0; + component_final_draw_y = 0; + shadow_enabled = false; + component_map_choice = 0; + + use_shadow_uniform = shader_get_uniform(full_livery_shader, "use_shadow"); + shadow_transform_uniform = shader_get_uniform(full_livery_shader, "In_Shadow_Transform"); + + shadow_sampler = shader_get_sampler_index(full_livery_shader, "shadow_texture"); + armour_shadow_sampler = shader_get_sampler_index(armour_texture, "shadow_texture"); + armour_texture_sampler = shader_get_sampler_index(armour_texture, "armour_texture"); + + texture_blend_uniform = shader_get_uniform(armour_texture, "blend"); + texture_blend_colour_uniform = shader_get_uniform(armour_texture, "blend_colour"); + texture_replace_col_uniform = shader_get_uniform(armour_texture, "replace_colour"); + + texture_use_shadow_uniform = shader_get_uniform(armour_texture, "use_shadow"); + texture_shadow_transform_uniform = shader_get_uniform(armour_texture, "In_Shadow_Transform"); + texture_mask_transform = shader_get_uniform(armour_texture, "mask_transform"); + + if (!surface_exists(global.base_component_surface)) { + global.base_component_surface = surface_create(600, 600); + } + + base_armour(); + + if (unit.IsSpecialist(SPECIALISTS_TECHS)) { + if (array_contains(["MK5 Heresy", "MK6 Corvus", "MK7 Aquila", "MK8 Errant", "Artificer Armour"], unit_armour)) { + if (unit.has_trait("tinkerer")) { + add_group({"armour": spr_techmarine_complex, "right_trim": spr_techmarine_right_trim, "left_trim": spr_techmarine_left_trim}); + } + } + } static mk7_bits = { armour: spr_mk7_complex, @@ -104,9 +224,99 @@ function ComplexSet(_unit) constructor { right_knee: spr_mk7_complex_knees, }; - _has_exceptions = false; - exceptions = []; + static weapon_preset_data = { + "shield": { + arm_type: 2, + ui_spec: true, + }, + "ranged_twohand": { + ui_spec: true, + ui_twoh: true, + }, + "normal_ranged": { + arm_type: 1, + }, + "terminator_ranged": { + arm_type: 1, + hand_type: 0, + }, + "terminator_fist": { + arm_type: 1, + ui_spec: true, + }, + "melee_onehand": { + hand_on_top: true, + }, + "melee_twohand": { + ui_spec: true, + single_left_right_profile: true, + hand_type: 2, + hand_on_top: true, + }, + }; + static skin_tones = { + standard: [ + [ + 1.0, + 218.0 / 255.0, + 179.0 / 255.0 + ], + [ + 1.0, + 192.0 / 255.0, + 134.0 / 255.0 + ], + [ + 252.0 / 255.0, + 206.0 / 255.0, + 159.0 / 255.0 + ], + [ + 254.0 / 255.0, + 206.0 / 255.0, + 163.0 / 255.0 + ], + [ + 255.0 / 255.0, + 221.0 / 255.0, + 191.0 / 255.0 + ], + [ + 230.0 / 255.0, + 177.0 / 255.0, + 131.0 / 255.0 + ], + [ + 255.0 / 255.0, + 205.0 / 255.0, + 163.0 / 255.0 + ], + [ + 57.0 / 255.0, + 37.0 / 255.0, + 17.0 / 255.0 + ] + ], + coal: [ + 34.0 / 255.0, + 34.0 / 255.0, + 34.0 / 255.0 + ], + }; + + static head_draw_order = [ + "crest", + "head", + "forehead", + "mouth_variants", + "left_eye", + "right_eye", + "crown" + ]; + + /// @param {Any} exception_key + /// @return {Bool} static check_exception = function(exception_key) { if (_has_exceptions) { var array_position = array_find_value(exceptions, exception_key); @@ -125,30 +335,8 @@ function ComplexSet(_unit) constructor { } }; - left_arm_data = []; - - right_arm_data = []; - - hand_scratchpads = [ - { - total: 0, - sources: [0], - offsets: [0], - source_frames: [0], - flip_x: false - }, - { - total: 0, - sources: [0], - offsets: [0], - source_frames: [0], - flip_x: true - } - ]; - - // Tracks sprites that ComplexSet owns (e.g. weapon duplicates) for cleanup - owned_sprites = []; - + /// @param {Struct} mod_item + /// @return {Bool} static base_modulars_checks = function(mod_item) { _has_exceptions = false; var _mod = mod_item; @@ -485,21 +673,24 @@ function ComplexSet(_unit) constructor { return true; }; - static assign_modulars = function(modulars = global.modular_drawing_items, position = false) { - var _mod = {}; - + /// @param {Array} modulars + /// @param {String} position + static assign_modulars = function(modulars = global.modular_drawing_items, position = "") { try { for (var i = 0; i < array_length(modulars); i++) { _sub_comps = "none"; _shadows = "none"; - _mod = modulars[i]; + var _mod = modulars[i]; + if (position != "") { + _mod.position = position; + } var _allowed = base_modulars_checks(_mod); if (!_allowed) { continue; } - if (position != false) { - if (position == "weapon") { + if (_mod.position != "") { + if (_mod.position == "weapon") { var _weapon_map = _mod.weapon_map; if (unit.weapon_one() == _weapon_map) { array_push(right_arm_data, _mod.weapon_data); @@ -507,9 +698,9 @@ function ComplexSet(_unit) constructor { if (unit.weapon_two() == _weapon_map) { array_push(left_arm_data, _mod.weapon_data); } + } else { + add_to_area(_mod.position, _mod.sprite, _overides, _sub_comps, _shadows); } - } else { - add_to_area(_mod.position, _mod.sprite, _overides, _sub_comps, _shadows); } if (struct_exists(_mod, "prevent_others")) { replace_area(_mod.position, _mod.sprite, _overides, _sub_comps, _shadows); @@ -528,83 +719,8 @@ function ComplexSet(_unit) constructor { } }; - blocked = []; - banned = []; - variation_map = { - backpack: unit.get_body_data("backpack_variation", "torso"), - armour: unit.get_body_data("armour_choice", "torso"), - chest_variants: unit.get_body_data("chest_variation", "torso"), - thorax_variants: unit.get_body_data("thorax_variation", "torso"), - leg_variants: unit.get_body_data("leg_variants", "left_leg"), - left_leg: unit.get_body_data("leg_variants", "left_leg"), - right_leg: unit.get_body_data("leg_variants", "right_leg"), - left_shin: unit.get_body_data("shin_variant", "left_leg"), - right_shin: unit.get_body_data("shin_variant", "right_leg"), - left_knee: unit.get_body_data("knee_variant", "left_leg"), - right_knee: unit.get_body_data("knee_variant", "right_leg"), - left_trim: unit.get_body_data("trim_variation", "left_arm"), - right_trim: unit.get_body_data("trim_variation", "right_arm"), - left_arm: unit.get_body_data("variation", "left_arm"), - right_arm: unit.get_body_data("variation", "right_arm"), - gorget: unit.get_body_data("variant", "throat"), - right_pauldron_icons: unit.get_body_data("pad_variation", "right_arm"), - left_pauldron_icons: unit.get_body_data("pad_variation", "left_arm"), - right_pauldron_base: unit.get_body_data("pad_variation", "right_arm"), - left_pauldron_base: unit.get_body_data("pad_variation", "left_arm"), - right_pauldron_embeleshments: unit.get_body_data("pad_variation", "right_arm"), - left_pauldron_embeleshments: unit.get_body_data("pad_variation", "left_arm"), - right_pauldron_hangings: unit.get_body_data("pad_variation", "right_arm"), - left_pauldron_hangings: unit.get_body_data("pad_variation", "left_arm"), - left_personal_livery: unit.get_body_data("personal_livery", "left_arm"), - tabbard: unit.get_body_data("tabbard_variation", "torso"), - robe: unit.get_body_data("tabbard_variation", "torso"), - crest: unit.get_body_data("crest_variation", "head"), - head: unit.get_body_data("variation", "head"), - bare_head: unit.get_body_data("variation", "head"), - bare_neck: unit.get_body_data("variation", "head"), - bare_eyes: unit.get_body_data("variation", "head"), - mouth_variants: unit.get_body_data("variant", "jaw"), - left_eye: unit.get_body_data("variant", "left_eye"), - right_eye: unit.get_body_data("variant", "right_eye"), - crown: unit.get_body_data("crown_variation", "head"), - forehead: unit.get_body_data("forehead_variation", "head"), - backpack_decoration: unit.get_body_data("backpack_decoration_variation", "torso"), - belt: unit.get_body_data("belt_variation", "torso"), - cloak: unit.get_body_data("variant", "cloak"), - cloak_image: unit.get_body_data("image_0", "cloak"), - cloak_trim: unit.get_body_data("image_1", "cloak"), - backpack_augment: unit.get_body_data("backpack_augment_variation", "torso"), - chest_fastening: unit.get_body_data("chest_fastening", "torso"), - left_weapon: unit.get_body_data("weapon_variation", "left_arm"), - right_weapon: unit.get_body_data("weapon_variation", "right_arm"), - necklace: unit.get_body_data("hanging_variant", "throat"), - foreground_item: unit.get_body_data("variant", "throat"), - }; - - component_final_draw_x = 0; - component_final_draw_y = 0; - shadow_enabled = false; - component_map_choice = 0; - - use_shadow_uniform = shader_get_uniform(full_livery_shader, "use_shadow"); - shadow_transform_uniform = shader_get_uniform(full_livery_shader, "In_Shadow_Transform"); - - shadow_sampler = shader_get_sampler_index(full_livery_shader, "shadow_texture"); - armour_shadow_sampler = shader_get_sampler_index(armour_texture, "shadow_texture"); - armour_texture_sampler = shader_get_sampler_index(armour_texture, "armour_texture"); - - texture_blend_uniform = shader_get_uniform(armour_texture, "blend"); - texture_blend_colour_uniform = shader_get_uniform(armour_texture, "blend_colour"); - static texture_replace_col_uniform = shader_get_uniform(armour_texture, "replace_colour"); - - texture_use_shadow_uniform = shader_get_uniform(armour_texture, "use_shadow"); - texture_shadow_transform_uniform = shader_get_uniform(armour_texture, "In_Shadow_Transform"); - texture_mask_transform = shader_get_uniform(armour_texture, "mask_transform"); - - if (!surface_exists(global.base_component_surface)) { - global.base_component_surface = surface_create(600, 600); - } - + /// @param {String} component_name + /// @param {Real} choice static check_component_overides = function(component_name, choice) { if (struct_exists(overides, component_name)) { var _overide_set = overides[$ component_name]; @@ -630,35 +746,40 @@ function ComplexSet(_unit) constructor { } }; - /// Resolves a global frame choice for an area into (source_sprite, local_frame) - static resolve_area = function(area_name, global_choice) { - if (!struct_exists(self, area_name)) { - return undefined; + /// @desc Resolves a global frame choice for an area into (source_sprite, local_frame) + /// @param {String} _area_name + /// @param {Real} _global_choice + /// @return {Struct|Undefined} + static resolve_area = function(_area_name, _global_choice) { + if (!struct_exists(self, _area_name)) { + return; } - var _area_data = self[$ area_name]; + var _area_data = self[$ _area_name]; if (is_struct(_area_data)) { // Composite area with source references var _total = _area_data.total; - var _choice = global_choice % _total; + var _choice = _global_choice % _total; for (var i = 0; i < array_length(_area_data.sources); i++) { if (_choice < _area_data.offsets[i] + _area_data.source_frames[i]) { return {sprite: _area_data.sources[i], frame: _choice - _area_data.offsets[i]}; } } - return undefined; + return; } // Raw sprite ID (complex_helms head, or backward compat) if (!sprite_exists(_area_data)) { - return undefined; + return; } - return {sprite: _area_data, frame: global_choice % sprite_get_number(_area_data)}; + return {sprite: _area_data, frame: _global_choice % sprite_get_number(_area_data)}; }; - /// Gets the total number of frames for an area + /// @desc Gets the total number of frames for an area + /// @param {String} area_name + /// @return {Real} static area_total_frames = function(area_name) { if (!struct_exists(self, area_name)) { return 0; @@ -676,6 +797,10 @@ function ComplexSet(_unit) constructor { return 0; }; + /// @param {String} component_name + /// @param {Real} choice + /// @param {Asset.GMSprite} resolved_sprite + /// @param {Real} resolved_frame static set_component_shadow_packs = function(component_name, choice, resolved_sprite, resolved_frame) { if (struct_exists(shadow_set, component_name)) { var _shadow_set = shadow_set[$ component_name]; @@ -684,7 +809,6 @@ function ComplexSet(_unit) constructor { if (_spec_shadow[0] <= choice && _spec_shadow[1] > choice) { var _shadow_item = _spec_shadow[2]; var _final_shadow_index = choice - _spec_shadow[0]; - //LOGGER.debug($"final_index {_final_shadow_index}, {_spec_shadow[0]}, {_spec_shadow[1]}, {choice},{_shadow_item}"); // Compute UV transform for this shadow texture if (!sprite_exists(resolved_sprite) || !sprite_exists(_shadow_item)) { @@ -714,6 +838,8 @@ function ComplexSet(_unit) constructor { } }; + /// @param {String} component_name + /// @param {Real} choice static handle_component_subcomponents = function(component_name, choice) { if (struct_exists(subcomponents, component_name)) { var _component_set; @@ -752,10 +878,13 @@ function ComplexSet(_unit) constructor { } } } - //sprite_delete(_sprite); } }; + /// @param {Asset.GMSprite} resolved_sprite + /// @param {Real} resolved_choice + /// @param {String} component_name + /// @param {Bool} flip_x static draw_component_with_textures = function(resolved_sprite, resolved_choice, component_name, flip_x = false) { var _return_surface = surface_get_target(); surface_reset_target(); @@ -830,11 +959,14 @@ function ComplexSet(_unit) constructor { draw_surface(global.base_component_surface, 0, 0); }; - // Main function + /// @desc Main function + /// @param {String} component_name + /// @param {Struct} texture_draws + /// @param {Real} choice_lock static draw_component = function(component_name, texture_draws = undefined, choice_lock = -1) { texture_draws ??= {}; if (array_contains(banned, component_name)) { - return "banned component"; + return; } if (struct_exists(self, component_name)) { shadow_enabled = 0; @@ -855,7 +987,7 @@ function ComplexSet(_unit) constructor { // Resolve to (source_sprite, local_frame) var _resolved = resolve_area(component_name, _choice); if (!is_struct(_resolved) || !sprite_exists(_resolved.sprite)) { - return "error failed no sprite found"; + return; } resolved_original_choice = _choice; @@ -883,11 +1015,10 @@ function ComplexSet(_unit) constructor { } handle_component_subcomponents(component_name, _choice); - } else { - return "error failed no sprite found"; } }; + /// @param {Struct} texture_draws static draw_unit_arms = function(texture_draws = undefined) { texture_draws ??= {}; var _bionic_options = []; @@ -901,7 +1032,7 @@ function ComplexSet(_unit) constructor { var _arm_string = _right_left == 0 ? "right_arm" : "left_arm"; var _bionic_arm = unit.get_body_data("bionic", _arm_string); - _bio = []; + var _bio = []; if (eARMOUR_TYPE.TERMINATOR == armour_type) { if (_variant == 2) { _bio = [ @@ -940,6 +1071,8 @@ function ComplexSet(_unit) constructor { } }; + /// @param {Real} right_left + /// @param {Struct} texture_draws static draw_unit_hands = function(right_left, texture_draws = undefined) { texture_draws ??= {}; var _arm_data = arms_data[right_left]; @@ -1029,6 +1162,7 @@ function ComplexSet(_unit) constructor { } }; + /// @param {Struct} texture_draws static draw_weapon_and_hands = function(texture_draws = undefined) { texture_draws ??= {}; if (armour_type == eARMOUR_TYPE.DREADNOUGHT) { @@ -1084,6 +1218,10 @@ function ComplexSet(_unit) constructor { } }; + /// @param {Struct} weapon + /// @param {String} position + /// @param {Real} choice_lock + /// @param {Struct} texture_draws static draw_weapon = function(weapon, position, choice_lock = -1, texture_draws = undefined) { texture_draws ??= {}; x_surface_offset += weapon.ui_xmod; @@ -1093,8 +1231,6 @@ function ComplexSet(_unit) constructor { var _shadows = struct_exists(weapon, "shadows") ? weapon.shadows : "none"; - //LOGGER.debug($" shadows {_shadows}"); - add_to_area(position, weapon.sprite, "none", _subs, _shadows); if (struct_exists(self, position)) { @@ -1110,37 +1246,6 @@ function ComplexSet(_unit) constructor { y_surface_offset -= weapon.ui_ymod; }; - static weapon_preset_data = { - "shield": { - arm_type: 2, - ui_spec: true, - }, - "ranged_twohand": { - ui_spec: true, - ui_twoh: true, - }, - "normal_ranged": { - arm_type: 1, - }, - "terminator_ranged": { - arm_type: 1, - hand_type: 0, - }, - "terminator_fist": { - arm_type: 1, - ui_spec: true, - }, - "melee_onehand": { - hand_on_top: true, - }, - "melee_twohand": { - ui_spec: true, - single_left_right_profile: true, - hand_type: 2, - hand_on_top: true, - }, - }; - static draw = function() { var _final_surface = surface_get_target(); surface_reset_target(); @@ -1149,9 +1254,7 @@ function ComplexSet(_unit) constructor { var _texture_draws = setup_complex_livery_shader(unit.role(), unit); - // LOGGER.debug(_texture_draws); draw_cloaks(); - //draw_unit_arms(x_surface_offset, y_surface_offset, armour_type, specialist_colours, hide_bionics, complex_set); if (array_length(left_arm_data)) { weapon_left = variable_clone(left_arm_data[variation_map.left_weapon % array_length(left_arm_data)]); @@ -1240,16 +1343,16 @@ function ComplexSet(_unit) constructor { } draw_unit_arms(_texture_draws); var _complex_helm = false; - var unit_role = unit.role(); + var _unit_role = unit.role(); var _role = active_roles(); var _comp_helms = instance_exists(obj_creation) ? obj_creation.complex_livery_data : obj_ini.complex_livery_data; - if (unit_role == _role[eROLE.SERGEANT]) { + if (_unit_role == _role[eROLE.SERGEANT]) { _complex_helm = _comp_helms.sgt; - } else if (unit_role == _role[eROLE.VETERANSERGEANT]) { + } else if (_unit_role == _role[eROLE.VETERANSERGEANT]) { _complex_helm = _comp_helms.vet_sgt; - } else if (unit_role == _role[eROLE.CAPTAIN]) { + } else if (_unit_role == _role[eROLE.CAPTAIN]) { _complex_helm = _comp_helms.captain; - } else if (unit_role == _role[eROLE.VETERAN] || (unit_role == _role[eROLE.TERMINATOR] && unit.company == 1)) { + } else if (_unit_role == _role[eROLE.VETERAN] || (_unit_role == _role[eROLE.TERMINATOR] && unit.company == 1)) { _complex_helm = _comp_helms.veteran; } else if (struct_exists(_comp_helms, "all_others")) { // there's probably room to improve this but consecrators demand the stripe @@ -1259,6 +1362,42 @@ function ComplexSet(_unit) constructor { complex_helms(_complex_helm); } + var _draw_order = [ + "backpack", + "backpack_augment", + "backpack_decoration", + "armour", + "thorax_variants", + "chest_variants", + "chest_fastening", + "leg_variants", + "left_leg", + "left_shin", + "right_leg", + "right_shin", + "knees", + "left_knee", + "right_knee", + "head", + "gorget", + "necklace", + "left_pauldron_base", + "right_pauldron_base", + "left_trim", + "right_trim", + "right_pauldron_icons", + "left_pauldron_icons", + "right_pauldron_embeleshments", + "left_pauldron_embeleshments", + "right_pauldron_hangings", + "left_pauldron_hangings", + "tabbard", + "robe", + "belt", + "left_personal_livery", + "foreground_item" + ]; + if (unit_armour == "MK4 Maximus" || unit_armour == "MK3 Iron Armour") { _draw_order = [ "backpack", @@ -1294,43 +1433,8 @@ function ComplexSet(_unit) constructor { "left_personal_livery", "foreground_item" ]; - } else { - _draw_order = [ - "backpack", - "backpack_augment", - "backpack_decoration", - "armour", - "thorax_variants", - "chest_variants", - "chest_fastening", - "leg_variants", - "left_leg", - "left_shin", - "right_leg", - "right_shin", - "knees", - "left_knee", - "right_knee", - "head", - "gorget", - "necklace", - "left_pauldron_base", - "right_pauldron_base", - "left_trim", - "right_trim", - "right_pauldron_icons", - "left_pauldron_icons", - "right_pauldron_embeleshments", - "left_pauldron_embeleshments", - "right_pauldron_hangings", - "left_pauldron_hangings", - "tabbard", - "robe", - "belt", - "left_personal_livery", - "foreground_item" - ]; } + for (var i = 0; i < array_length(_draw_order); i++) { if (_draw_order[i] == "head") { draw_head(_texture_draws); @@ -1368,8 +1472,22 @@ function ComplexSet(_unit) constructor { var _y_offset = y_surface_offset + (armour_type == eARMOUR_TYPE.NORMAL ? 0 : -38); if (struct_exists(_torso_data, "purity_seal")) { var _torso_purity_seals = _torso_data[$ "purity_seal"]; + var positions = [ + [ + 117, + 115 + ], + [ + 51, + 139 + ], + [ + 131, + 136 + ] + ]; if (armour_type == eARMOUR_TYPE.NORMAL) { - var positions = [ + positions = [ [ 60, 88 @@ -1383,21 +1501,6 @@ function ComplexSet(_unit) constructor { 64 ] ]; - } else { - var positions = [ - [ - 117, - 115 - ], - [ - 51, - 139 - ], - [ - 131, - 136 - ] - ]; } for (var i = 0; i < array_length(_torso_purity_seals); i++) { if (i >= array_length(positions)) { @@ -1414,8 +1517,22 @@ function ComplexSet(_unit) constructor { if (struct_exists(_body[$ "left_arm"], "purity_seal")) { var _arm_seals = _body[$ "left_arm"][$ "purity_seal"]; + var positions = [ + [ + 163, + 92 + ], + [ + 148, + 94 + ], + [ + 126, + 84 + ] + ]; if (armour_type == eARMOUR_TYPE.NORMAL) { - var positions = [ + positions = [ [ 135, 69 @@ -1425,21 +1542,6 @@ function ComplexSet(_unit) constructor { 73 ] ]; - } else { - var positions = [ - [ - 163, - 92 - ], - [ - 148, - 94 - ], - [ - 126, - 84 - ] - ]; } for (var i = 0; i < array_length(_arm_seals); i++) { if (i >= array_length(positions)) { @@ -1456,8 +1558,22 @@ function ComplexSet(_unit) constructor { if (struct_exists(_body[$ "right_arm"], "purity_seal")) { var _arm_seals = _body[$ "right_arm"][$ "purity_seal"]; + var positions = [ + [ + 11, + 91 + ], + [ + 39, + 90 + ], + [ + 66, + 86 + ] + ]; if (armour_type == eARMOUR_TYPE.NORMAL) { - var positions = [ + positions = [ [ 44, 76 @@ -1471,21 +1587,6 @@ function ComplexSet(_unit) constructor { 69 ] ]; - } else { - var positions = [ - [ - 11, - 91 - ], - [ - 39, - 90 - ], - [ - 66, - 86 - ] - ]; } for (var i = 0; i < array_length(_arm_seals); i++) { if (i >= array_length(positions)) { @@ -1517,9 +1618,6 @@ function ComplexSet(_unit) constructor { case "MK5 Heresy": add_group({armour: spr_mk5_complex, backpack: spr_mk5_complex_backpack, left_trim: spr_mk7_left_trim, right_trim: spr_mk7_right_trim, head: spr_mk5_head_variants, chest_variants: spr_mk5_chest_variants, knees: spr_mk7_complex_knees}); armour_type = eARMOUR_TYPE.NORMAL; - /*if (scr_has_style("Prussian")){ - add_to_area("chest_variants", spr_mk7_prussia_chest); - }*/ break; case "MK4 Maximus": add_group({chest_variants: spr_mk4_chest_variants, armour: spr_mk4_complex, backpack: spr_mk4_complex_backpack, leg_variants: spr_mk4_leg_variants, left_trim: spr_mk4_left_trim, right_trim: spr_mk4_right_trim, mouth_variants: spr_mk4_mouth_variants, head: spr_mk4_head_variants}); @@ -1587,14 +1685,6 @@ function ComplexSet(_unit) constructor { } }; - if (unit.IsSpecialist(SPECIALISTS_TECHS)) { - if (array_contains(["MK5 Heresy", "MK6 Corvus", "MK7 Aquila", "MK8 Errant", "Artificer Armour"], unit_armour)) { - if (unit.has_trait("tinkerer")) { - add_group({"armour": spr_techmarine_complex, "right_trim": spr_techmarine_right_trim, "left_trim": spr_techmarine_left_trim}); - } - } - } - static draw_cloaks = function() { var _shader_set_multiply_blend = function(_r, _g, _b) { shader_set(shd_multiply_blend); @@ -1603,7 +1693,6 @@ function ComplexSet(_unit) constructor { _shader_set_multiply_blend(127, 107, 89); draw_component("cloak"); - //_shader_set_multiply_blend(obj_controller.trim_colour_replace[0]*255, obj_controller.trim_colour_replace[1]*255, obj_controller.trim_colour_replace[2]*255); draw_component("cloak_image"); draw_component("cloak_trim"); @@ -1614,11 +1703,11 @@ function ComplexSet(_unit) constructor { /// @desc Add a sprite reference to an area without duplicating or merging pixel data. /// Stores source references in a composite struct. At draw time, resolve_area() /// maps a global frame choice to the correct source sprite + local frame. - /// @param area {string} Area name - /// @param add_sprite {sprite} Source sprite to add (not duplicated — we store the reference!) - /// @param overide_data {any} Override data for this sprite's frame range - /// @param sub_components {any} Sub-component data for this sprite's frame range - /// @param shadow {any} Shadow data for this sprite's frame range + /// @param {String} area Area name + /// @param {Asset.GMSprite} add_sprite Source sprite to add (not duplicated — we store the reference!) + /// @param {Struct} overide_data Override data for this sprite's frame range + /// @param {Struct} sub_components Sub-component data for this sprite's frame range + /// @param {Asset.GMSprite} shadow Shadow data for this sprite's frame range static add_to_area = function(area, add_sprite, overide_data = "none", sub_components = "none", shadow = "none") { if (sprite_exists(add_sprite)) { var _add_sprite_length = sprite_get_number(add_sprite); @@ -1681,10 +1770,16 @@ function ComplexSet(_unit) constructor { } }; - offsets = []; - + /// @param {String} area + /// @param {Real} _offset_start + /// @param {Real} sprite_length + /// @param {Struct} overide_data static add_offsets = function(area, _offset_start, sprite_length, overide_data) {}; + /// @param {String} area + /// @param {Real} _overide_start + /// @param {Real} sprite_length + /// @param {Struct} overide_data static add_overide = function(area, _overide_start, sprite_length, overide_data) { if (!struct_exists(overides, area)) { overides[$ area] = []; @@ -1692,15 +1787,21 @@ function ComplexSet(_unit) constructor { array_push(overides[$ area], [_overide_start, _overide_start + sprite_length, overide_data]); }; - shadow_set = {}; - - static add_shadow_set = function(area, _shadow_set_start, sprite_length, shadow_data) { + /// @param {String} area + /// @param {Real} _shadow_set_start + /// @param {Real} sprite_length + /// @param {Asset.GMSprite} shadow + static add_shadow_set = function(area, _shadow_set_start, sprite_length, shadow) { if (!struct_exists(shadow_set, area)) { shadow_set[$ area] = []; } - array_push(shadow_set[$ area], [_shadow_set_start, _shadow_set_start + sprite_length, shadow_data]); + array_push(shadow_set[$ area], [_shadow_set_start, _shadow_set_start + sprite_length, shadow]); }; + /// @param {String} area + /// @param {Real} _overide_start + /// @param {Real} sprite_length + /// @param {Struct} sub_components static add_sub_components = function(area, _overide_start, sprite_length, sub_components) { if (!struct_exists(subcomponents, area)) { subcomponents[$ area] = []; @@ -1727,11 +1828,17 @@ function ComplexSet(_unit) constructor { array_push(subcomponents[$ area], [_overide_start, _overide_start + sprite_length, _accepted_subs]); }; + /// @param {String} area + /// @param {Asset.GMSprite} add_sprite + /// @param {Struct} overide_data + /// @param {Struct} sub_components + /// @param {Asset.GMSprite} shadow static replace_area = function(area, add_sprite, overide_data = "none", sub_components = "none", shadow = "none") { remove_area(area); add_to_area(area, add_sprite, overide_data, sub_components); }; + /// @param {String} area static remove_area = function(area) { if (struct_exists(self, area)) { struct_remove(self, area); @@ -1744,6 +1851,7 @@ function ComplexSet(_unit) constructor { } }; + /// @param {Struct} group static add_group = function(group) { var _areas = struct_get_names(group); for (var i = 0; i < array_length(_areas); i++) { @@ -1752,68 +1860,7 @@ function ComplexSet(_unit) constructor { } }; - position_overides = {}; - - static skin_tones = { - standard: [ - [ - 1.0, - 218.0 / 255.0, - 179.0 / 255.0 - ], - [ - 1.0, - 192.0 / 255.0, - 134.0 / 255.0 - ], - [ - 252.0 / 255.0, - 206.0 / 255.0, - 159.0 / 255.0 - ], - [ - 254.0 / 255.0, - 206.0 / 255.0, - 163.0 / 255.0 - ], - [ - 255.0 / 255.0, - 221.0 / 255.0, - 191.0 / 255.0 - ], - [ - 230.0 / 255.0, - 177.0 / 255.0, - 131.0 / 255.0 - ], - [ - 255.0 / 255.0, - 205.0 / 255.0, - 163.0 / 255.0 - ], - [ - 57.0 / 255.0, - 37.0 / 255.0, - 17.0 / 255.0 - ] - ], - coal: [ - 34.0 / 255.0, - 34.0 / 255.0, - 34.0 / 255.0 - ], - }; - - static head_draw_order = [ - "crest", - "head", - "forehead", - "mouth_variants", - "left_eye", - "right_eye", - "crown" - ]; - + /// @param {Struct} texture_draws static draw_head = function(texture_draws = {}) { if (draw_helms) { if (struct_exists(self, "head")) { @@ -1835,6 +1882,7 @@ function ComplexSet(_unit) constructor { } }; + /// @param {Struct} data static complex_helms = function(data) { var _head_resolved = resolve_area("head", variation_map.head % area_total_frames("head")); if (!is_struct(_head_resolved) || !sprite_exists(_head_resolved.sprite)) { @@ -1851,7 +1899,6 @@ function ComplexSet(_unit) constructor { var _surface_width = sprite_get_width(_head_resolved.sprite); var _surface_height = sprite_get_height(_head_resolved.sprite); var _head_surface = surface_create(_surface_width, 60); - //var _decoration_surface = surface_create(_surface_width, 60); surface_set_target(_head_surface); var _temp = [ x_surface_offset, @@ -1885,10 +1932,6 @@ function ComplexSet(_unit) constructor { remove_area("right_eye"); remove_area("crown"); - //shader_set(helm_shader); - //surface_set_target(_decoration_surface); - //shader_set_uniform_f_array(shader_get_uniform(helm_shader, "replace_colour"), get_shader_array(data.helm_secondary)); - //draw_sprite(spr_helm_stripe, data.helm_pattern==1?0:1, 0, 0); surface_reset_target(); var _new_head = sprite_create_from_surface(_head_surface, 0, 0, _surface_width, 60, false, false, 0, 0); @@ -1909,6 +1952,4 @@ function ComplexSet(_unit) constructor { owned_sprites = []; }; - - base_armour(); } diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index a5a17db3b9..f0fe5bc345 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -8,15 +8,15 @@ global.force_strength_descriptions = [ "Overwhelming", ]; -/// @param {Real} planet -/// @param {Id.Instance.obj_star} system -function PlanetData(planet, system) constructor { +/// @param {Real} _planet +/// @param {Id.Instance.obj_star} _system +function PlanetData(_planet, _system) constructor { //safeguards // TODO LOW DEBUG_LOGGING // Log when tripped somewhere //disposition static large_pop_conversion = 1000000000; - self.planet = planet; - self.system = system; + planet = _planet; + system = _system; static refresh_data = function() { features = system.p_feature[planet]; @@ -1661,18 +1661,19 @@ function PlanetData(planet, system) constructor { }; static draw_planet_population_controls = function() { - draw_set_color(c_gray); - var _gar_slate = obj_star_select.garrison_data_slate; - _gar_slate.sub_title = ""; - _gar_slate.body_text = ""; - _gar_slate.title = ""; - var xx = _gar_slate.XX; - var yy = _gar_slate.YY; - var _half_way = _gar_slate.height / 2; - var spacing_x = 100; - var spacing_y = 65; - draw_set_halign(fa_left); if (!is_hulk) { + draw_set_color(c_gray); + var _gar_slate = obj_star_select.garrison_data_slate; + _gar_slate.sub_title = ""; + _gar_slate.body_text = ""; + _gar_slate.title = ""; + var xx = _gar_slate.XX; + var yy = _gar_slate.YY; + var _half_way = _gar_slate.height / 2; + var spacing_x = 100; + var spacing_y = 65; + draw_set_halign(fa_left); + var _imperium_status = obj_controller.faction_status[eFACTION.IMPERIUM]; if ((_imperium_status != "War" && current_owner <= 5) || (_imperium_status == "War")) { var _col_button = obj_star_select.colonist_button; diff --git a/scripts/scr_add_artifact/scr_add_artifact.gml b/scripts/scr_add_artifact/scr_add_artifact.gml index 563f1486b7..b1dcee9585 100644 --- a/scripts/scr_add_artifact/scr_add_artifact.gml +++ b/scripts/scr_add_artifact/scr_add_artifact.gml @@ -832,7 +832,7 @@ function corrupt_artifact_collectors(last_artifact) { _unit.edit_corruption(choose(0, 2, 4, 6, 8)); } } else if (obj_controller.man[i] == "vehicle" && is_array(_unit)) { - var _val = get_deep_array(obj_ini.veh_chaos, _unit); + var _val = fetch_deep_array(obj_ini.veh_chaos, _unit); _val += choose(0, 2, 4, 6, 8); alter_deep_array(obj_ini.veh_chaos, _unit, _val); } diff --git a/scripts/scr_add_man/scr_add_man.gml b/scripts/scr_add_man/scr_add_man.gml index a5e241b893..a798f53cb3 100644 --- a/scripts/scr_add_man/scr_add_man.gml +++ b/scripts/scr_add_man/scr_add_man.gml @@ -85,7 +85,7 @@ function scr_add_man(man_role, target_company, spawn_exp, spawn_name, corruption case "Ork Sniper": spawn_exp = 20; obj_ini.race[target_company][_company_slot] = eFACTION.ORK; - _unit = new TTRPG_stats("ork", target_company, _company_slot, "ork_Sniper"); + _unit = new TTRPG_stats("ork", target_company, _company_slot, "ork_sniper"); break; case "Flash Git": spawn_exp = 40; diff --git a/scripts/scr_buttons/scr_buttons.gml b/scripts/scr_buttons/scr_buttons.gml index e3721885e8..f5708bd97f 100644 --- a/scripts/scr_buttons/scr_buttons.gml +++ b/scripts/scr_buttons/scr_buttons.gml @@ -424,6 +424,12 @@ function SpriteButton(data) constructor { cycle_index = false; draw_index = 0; + width = 0; + height = 0; + x1 = 0; + x2 = 0; + y1 = 0; + y2 = 0; scale_x = 1.0; scale_y = 1.0; alpha_hover = 1.0; @@ -445,8 +451,6 @@ function SpriteButton(data) constructor { y2 = y1 + (height * scale_y); } - update(data); - /// @desc Updates interaction state and draws the button. /// @param {bool} _enabled If false, interaction is disabled and the button appears faded. static draw = function(_enabled = true) { @@ -473,6 +477,8 @@ function SpriteButton(data) constructor { draw_sprite_ext(_draw_sprite, draw_index, x1, y1, scale_x, scale_y, 0, c_white, _draw_alpha); pop_draw_return_values(); }; + + update(data); } /// @function UnitButtonObject(data) diff --git a/scripts/scr_crusade/scr_crusade.gml b/scripts/scr_crusade/scr_crusade.gml index dc27c3b8f5..5e1138b8c3 100644 --- a/scripts/scr_crusade/scr_crusade.gml +++ b/scripts/scr_crusade/scr_crusade.gml @@ -48,7 +48,7 @@ function scr_crusade() { if (death_determination <= 50) { type = "normal"; artifacts = choose(0, 0, 0, 0, 0, 1); - } else if (death_determination > 50) { + } else if (death_determination > 50 && death_determination <= 80) { type = "hard"; artifacts = choose(0, 0, 1); } else if (death_determination > 80) { diff --git a/scripts/scr_dialogue/scr_dialogue.gml b/scripts/scr_dialogue/scr_dialogue.gml index 80610ceb82..df6c66f354 100644 --- a/scripts/scr_dialogue/scr_dialogue.gml +++ b/scripts/scr_dialogue/scr_dialogue.gml @@ -402,27 +402,27 @@ function scr_dialogue(diplo_keyphrase, data = {}) { obj_ncombat.local_forces = 0; if (diplo_keyphrase == "cs_meeting_battle1") { - obj_ncombat.enemy = 1; + obj_ncombat.enemy = eFACTION.PLAYER; obj_ncombat.threat = 2; } if (diplo_keyphrase == "cs_meeting_battle2") { - obj_ncombat.enemy = 1; + obj_ncombat.enemy = eFACTION.PLAYER; obj_ncombat.threat = 1; } if (diplo_keyphrase == "cs_meeting_battle5") { - obj_ncombat.enemy = 10; + obj_ncombat.enemy = eFACTION.CHAOS; obj_ncombat.threat = 3; } if (diplo_keyphrase == "cs_meeting_battle6") { - obj_ncombat.enemy = 10; + obj_ncombat.enemy = eFACTION.CHAOS; obj_ncombat.threat = 3; } if (diplo_keyphrase == "cs_meeting_battle7") { - obj_ncombat.enemy = 1; + obj_ncombat.enemy = eFACTION.PLAYER; obj_ncombat.threat = 2; } - if ((obj_ncombat.enemy == 10) && (obj_controller.faction_defeated[10] == 0)) { + if ((obj_ncombat.enemy == eFACTION.CHAOS) && (obj_controller.faction_defeated[10] == 0)) { obj_ncombat.leader = 1; with (obj_star) { diff --git a/scripts/scr_draw_management_unit/scr_draw_management_unit.gml b/scripts/scr_draw_management_unit/scr_draw_management_unit.gml index 9b93b7bfe6..e945d66275 100644 --- a/scripts/scr_draw_management_unit/scr_draw_management_unit.gml +++ b/scripts/scr_draw_management_unit/scr_draw_management_unit.gml @@ -589,7 +589,7 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l } if (is_man) { force_tool = 0; - if ((temp[101] == $"{_unit.role()} {_unit.name}") && ((temp[102] != _unit.armour()) || (temp[104] != _unit.gear()) || (temp[106] == _unit.mobility_item()) || (temp[108] != _unit.weapon_one()) || (temp[110] != _unit.weapon_two()) || (temp[114] == "refresh"))) { + if ((temp[101] == $"{_unit.role()} {_unit.name}") && ((temp[102] != _unit.armour()) || (temp[104] != _unit.gear()) || (temp[106] != _unit.mobility_item()) || (temp[108] != _unit.weapon_one()) || (temp[110] != _unit.weapon_two()))) { force_tool = 1; } diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index f7d54123b1..b7c70add79 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -260,23 +260,23 @@ function drop_select_unit_selection() { if (obj_ncombat.battle_object.space_hulk == 1) { obj_ncombat.battle_special = "space_hulk"; } - if ((planet_feature_bool(_planet, eP_FEATURES.WARLORD6) == 1) && (obj_ncombat.enemy == 6) && (obj_controller.faction_defeated[6] == 0)) { + if ((planet_feature_bool(_planet, eP_FEATURES.WARLORD6) == 1) && (obj_ncombat.enemy == eFACTION.ELDAR) && (obj_controller.faction_defeated[6] == 0)) { obj_ncombat.leader = 1; } - if ((obj_ncombat.enemy == 7) && (obj_controller.faction_defeated[7] <= 0)) { + if ((obj_ncombat.enemy == eFACTION.ORK) && (obj_controller.faction_defeated[7] <= 0)) { if (planet_feature_bool(_planet, eP_FEATURES.ORKWARBOSS)) { obj_ncombat.leader = 1; obj_ncombat.Warlord = _planet[search_planet_features(_planet, eP_FEATURES.ORKWARBOSS)[0]]; } } - if ((obj_ncombat.enemy == 9) && (obj_ncombat.battle_object.space_hulk == 0)) { + if ((obj_ncombat.enemy == eFACTION.TYRANIDS) && (obj_ncombat.battle_object.space_hulk == 0)) { if (has_problem_planet(planet_number, "tyranid_org", p_target)) { obj_ncombat.battle_special = "tyranid_org"; } } - if (obj_ncombat.enemy == 11) { + if (obj_ncombat.enemy == eFACTION.HERETICS) { if (planet_feature_bool(obj_ncombat.battle_object.p_feature[obj_ncombat.battle_id], eP_FEATURES.CHAOSWARBAND) == 1) { obj_ncombat.battle_special = "ChaosWarband"; obj_ncombat.leader = 1; @@ -299,14 +299,12 @@ function drop_select_unit_selection() { demons, necrons ]; - if (obj_ncombat.enemy >= 5 && obj_ncombat.enemy <= 13) { + if (obj_ncombat.enemy >= eFACTION.ECCLESIARCHY && obj_ncombat.enemy <= eFACTION.NECRONS) { obj_ncombat.threat = _threats[obj_ncombat.enemy]; } - if (obj_ncombat.enemy == 8) { - var eth; - eth = 0; - eth = scr_quest(4, "ethereal_capture", 8, 0); + if (obj_ncombat.enemy == eFACTION.TAU) { + var eth = scr_quest(4, "ethereal_capture", 8, 0); if ((eth > 0) && (obj_ncombat.battle_object.p_owner[obj_ncombat.battle_id] == 8)) { var rolli; rolli = irandom_range(1, 100); @@ -323,17 +321,15 @@ function drop_select_unit_selection() { obj_ncombat.ethereal = 1; } } - // show_message("Ethereal Quest?: "+string(eth)+"#Ethereal?: "+string(obj_ncombat.ethereal)); } - // if (obj_ncombat.threat>1) and (obj_ncombat.enemy!=13) then obj_ncombat.threat-=1; if ((obj_ncombat.threat > 1) && (obj_ncombat.battle_special != "ChaosWarband") && (attack == 0)) { obj_ncombat.threat -= 1; } if (obj_ncombat.threat < 1) { obj_ncombat.threat = 1; } - if ((obj_ncombat.enemy == 10) && (obj_ncombat.battle_object.p_type[obj_ncombat.battle_id] == "Daemon")) { + if ((obj_ncombat.enemy == eFACTION.CHAOS) && (obj_ncombat.battle_object.p_type[obj_ncombat.battle_id] == "Daemon")) { obj_ncombat.threat = 7; } @@ -363,7 +359,7 @@ function drop_select_unit_selection() { } if (obj_controller.known[eFACTION.CHAOS] >= 2 && obj_controller.faction_gender[10] == 1) { with (obj_drop_select) { - obj_ncombat.enemy = 11; + obj_ncombat.enemy = eFACTION.HERETICS; obj_ncombat.threat = 0; cancel_combat(); combating = 0; diff --git a/scripts/scr_flavor/scr_flavor.gml b/scripts/scr_flavor/scr_flavor.gml index e41abd8ec7..5e272f6ffb 100644 --- a/scripts/scr_flavor/scr_flavor.gml +++ b/scripts/scr_flavor/scr_flavor.gml @@ -114,7 +114,7 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot var target_name = target.dudes[targeh]; - if ((target_name == "Leader") && (obj_ncombat.enemy <= 10)) { + if ((target_name == "Leader") && (obj_ncombat.enemy <= eFACTION.CHAOS)) { target_name = obj_controller.faction_leader[obj_ncombat.enemy]; } @@ -705,7 +705,7 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot // } var message_priority = 0; - if (obj_ncombat.enemy <= 10) { + if (obj_ncombat.enemy <= eFACTION.CHAOS) { if (target_name == obj_controller.faction_leader[obj_ncombat.enemy]) { // Cleaning up the message for the enemy leader leader_message = string_replace(leader_message, "a " + target_name, target_name); diff --git a/scripts/scr_fleet_functions/scr_fleet_functions.gml b/scripts/scr_fleet_functions/scr_fleet_functions.gml index c540b26ba9..488a2b3ddf 100644 --- a/scripts/scr_fleet_functions/scr_fleet_functions.gml +++ b/scripts/scr_fleet_functions/scr_fleet_functions.gml @@ -166,6 +166,7 @@ function get_largest_player_fleet() { } /// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet +/// @return {bool} function is_orbiting(fleet = noone) { if (fleet == noone) { if (action != "") { @@ -265,37 +266,50 @@ function load_unit_to_fleet(fleet, unit) { return loaded; } -/// @param {Real} xx -/// @param {Real} yy -/// @param {Real} xxx -/// @param {Real} yyy +/// @param {Real} self_x +/// @param {Real} self_y +/// @param {Real} target_x +/// @param {Real} target_y /// @param {Real} fleet_speed -/// @param {Id.Instance.obj_star} star1 -/// @param {Id.Instance.obj_star} star2 +/// @param {Bool} from_star +/// @param {Bool} to_star /// @param {Bool} warp_able -function calculate_fleet_eta(xx, yy, xxx, yyy, fleet_speed, star1 = noone, star2 = noone, warp_able = false) { - // Always resolve both endpoints to real star instances from the coordinates. - // Every real-travel caller historically passes booleans (from_star, is_orbiting(), - // true/false) in the star1/star2 slots, which left warp_lane at 0 and made actual - // jumps ignore lanes entirely (doubling the time and skipping the storm check), while - // the map preview, which omits these args, computed lanes correctly. Resolving from - // coords here ignores those bad args and keeps the preview and the real transit in sync. - star1 = instance_nearest(xx, yy, obj_star); - star2 = instance_nearest(xxx, yyy, obj_star); - var warp_lane = determine_warp_join(star1.id, star2.id); - var eta = floor(point_distance(xx, yy, xxx, yyy) / fleet_speed) + 1; - if (!warp_lane) { - eta *= 2; +function calculate_fleet_eta(self_x, self_y, target_x, target_y, fleet_speed, from_star = true, to_star = true, warp_able = false) { + var _eta = floor(point_distance(self_x, self_y, target_x, target_y) / fleet_speed) + 1; + var _lane_strength = 0; + /// @type {Id.Instance.obj_star} + var _departure_star = noone; + /// @type {Id.Instance.obj_star} + var _destanation_star = noone; + + if (from_star) { + _departure_star = instance_nearest(self_x, self_y, obj_star); } - if (warp_lane && warp_able) { - eta = ceil(eta / warp_lane); + + if (to_star) { + _destanation_star = instance_nearest(target_x, target_y, obj_star); + } + + if (_departure_star != noone && _destanation_star != noone) { + _lane_strength = determine_warp_join(_departure_star.id, _destanation_star.id); + } + + if (_lane_strength > 0) { + if (warp_able) { + _eta = ceil(_eta / _lane_strength); + } + } else { + _eta *= 2; } - //check end location for warp storm - if (instance_exists(star2) && (star2.object_index == obj_star) && star2.storm) { - eta += 10000; + if (_destanation_star != noone) { + //check end location for warp storm + if (_destanation_star.storm) { + _eta += 10000; + } } - return eta; + + return _eta; } /// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet @@ -1175,118 +1189,143 @@ function merge_fleets(main_fleet, merge_fleet) { /// @self Asset.GMObject.obj_en_fleet|Asset.GMObject.obj_p_fleet function fleet_respond_crusade() { - if (owner != eFACTION.IMPERIUM) { - exit; - } - if (!navy) { - exit; - } - if (orbiting.owner > eFACTION.ECCLESIARCHY) { - exit; - } - if (trade_goods != "") { - exit; - } - if (action != "") { - exit; - } - if (guardsmen_unloaded > 0) { - exit; - } - - // Crusade AI - obj_controller.temp[88] = owner; - with (obj_crusade) { - if (owner != obj_controller.temp[88]) { - y -= 20000; + try { + if (owner != eFACTION.IMPERIUM) { + exit; } - } - - var enemu; - with (obj_star) { - var cs = instance_nearest(x, y, obj_crusade); - - if (point_distance(x, y, cs.x, cs.y) > cs.radius) { - y -= 20000; + if (!navy) { + exit; } - enemu = 0; - - var nids = array_reduce( - p_tyranids, - function(prev, curr) { - return prev || curr > 3; - }, - false - ); - - var tau = array_reduce( - p_tau, - function(prev, curr) { - return prev || curr > 0; - }, - false - ); - - enemu += nids + tau; - - if (present_fleet[eFACTION.ELDAR] > 0) { - enemu += 2; + if (orbiting.owner > eFACTION.ECCLESIARCHY) { + exit; } - if (present_fleet[eFACTION.ORK] > 0) { - enemu += 2; + if (trade_goods != "") { + exit; } - if (present_fleet[eFACTION.TAU] > 0) { - enemu += 2; + if (action != "") { + exit; } - if (present_fleet[eFACTION.TYRANIDS] > 0) { - enemu += 2; + if (guardsmen_unloaded > 0) { + exit; } - if (present_fleet[eFACTION.CHAOS] > 0) { - enemu += 2; + + // Crusade AI + obj_controller.temp[88] = owner; + with (obj_crusade) { + if (owner != obj_controller.temp[88]) { + y -= 20000; + } } - //nothing for heritics faction - if (present_fleet[eFACTION.NECRONS] > 0) { - enemu += 2; + + var enemu; + with (obj_star) { + var cs = instance_nearest(x, y, obj_crusade); + + if (point_distance(x, y, cs.x, cs.y) > cs.radius) { + y -= 20000; + } + enemu = 0; + + var nids = array_reduce( + p_tyranids, + function(prev, curr) { + return prev || curr > 3; + }, + false + ); + + var tau = array_reduce( + p_tau, + function(prev, curr) { + return prev || curr > 0; + }, + false + ); + + enemu += nids + tau; + + if (present_fleet[eFACTION.ELDAR] > 0) { + enemu += 2; + } + if (present_fleet[eFACTION.ORK] > 0) { + enemu += 2; + } + if (present_fleet[eFACTION.TAU] > 0) { + enemu += 2; + } + if (present_fleet[eFACTION.TYRANIDS] > 0) { + enemu += 2; + } + if (present_fleet[eFACTION.CHAOS] > 0) { + enemu += 2; + } + //nothing for heritics faction + if (present_fleet[eFACTION.NECRONS] > 0) { + enemu += 2; + } } - } - var ns = instance_nearest(x, y, obj_star); - var ok = false; - var max_dist = 800; - var min_dist = 40; - var to_ignore = [ - eFACTION.IMPERIUM, - eFACTION.MECHANICUS, - eFACTION.INQUISITION, - eFACTION.ECCLESIARCHY - ]; - - var dist = point_distance(x, y, ns.x, ns.y); - var valid_target = !array_contains_ext(ns.p_owner, to_ignore, false); - if (valid_target && dist <= max_dist && dist >= min_dist && (owner == eFACTION.IMPERIUM)) { - ok = true; - } - - // if ((ns.owner>5) or (ns.owner = eFACTION.PLAYER)) and (point_distance(x,y,ns.x,ns.y)<=max_dis) and (point_distance(x,y,ns.x,ns.y)>40) and (owner = eFACTION.IMPERIUM){ - if (ok) { - action_x = ns.x; - action_y = ns.y; - set_fleet_movement(); - orbiting.present_fleet[owner] -= 1; - home_x = orbiting.x; - home_y = orbiting.y; - - var i; - i = 0; - repeat (orbiting.planets) { - i += 1; - if ((orbiting.p_owner[i] == eFACTION.IMPERIUM) && (orbiting.p_guardsmen[i] > 500)) { - guardsmen += round(orbiting.p_guardsmen[i] / 2); - orbiting.p_guardsmen[i] = round(orbiting.p_guardsmen[i] / 2); + var ns = instance_nearest(x, y, obj_star); + var ok = false; + var max_dist = 800; + var min_dist = 40; + var to_ignore = [ + eFACTION.IMPERIUM, + eFACTION.MECHANICUS, + eFACTION.INQUISITION, + eFACTION.ECCLESIARCHY + ]; + + var dist = point_distance(x, y, ns.x, ns.y); + var valid_target = !array_contains_ext(ns.p_owner, to_ignore, false); + if (valid_target && dist <= max_dist && dist >= min_dist && (owner == eFACTION.IMPERIUM)) { + ok = true; + } + + // if ((ns.owner>5) or (ns.owner = eFACTION.PLAYER)) and (point_distance(x,y,ns.x,ns.y)<=max_dis) and (point_distance(x,y,ns.x,ns.y)>40) and (owner = eFACTION.IMPERIUM){ + if (ok) { + action_x = ns.x; + action_y = ns.y; + set_fleet_movement(); + orbiting.present_fleet[owner] -= 1; + home_x = orbiting.x; + home_y = orbiting.y; + + var i; + i = 0; + repeat (orbiting.planets) { + i += 1; + if ((orbiting.p_owner[i] == eFACTION.IMPERIUM) && (orbiting.p_guardsmen[i] > 500)) { + guardsmen += round(orbiting.p_guardsmen[i] / 2); + orbiting.p_guardsmen[i] = round(orbiting.p_guardsmen[i] / 2); + } + } + + alarm[5] = 2; + + with (obj_crusade) { + if (y < -10000) { + y += 20000; + } + } + with (obj_crusade) { + if (y < -10000) { + y += 20000; + } + } + with (obj_star) { + if (y < -10000) { + y += 20000; + } } + with (obj_star) { + if (y < -10000) { + y += 20000; + } + } + + exit; } - - alarm[5] = 2; - + with (obj_crusade) { if (y < -10000) { y += 20000; @@ -1306,29 +1345,14 @@ function fleet_respond_crusade() { if (y < -10000) { y += 20000; } - } - - exit; - } - - with (obj_crusade) { - if (y < -10000) { - y += 20000; - } - } - with (obj_crusade) { - if (y < -10000) { - y += 20000; - } - } - with (obj_star) { - if (y < -10000) { - y += 20000; - } - } - with (obj_star) { - if (y < -10000) { - y += 20000; - } + } + } catch (_ex) { + LOGGER.error(self); + LOGGER.error($"owner: {owner}"); + LOGGER.error($"orbiting: {orbiting}"); + if (instance_exists(orbiting)) { + LOGGER.error($"orbiting.present_fleet: {orbiting.present_fleet}"); + } + ERROR_HANDLER.handle_exception(_ex); } } diff --git a/scripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gml b/scripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gml index 4365e7ec68..53913e3ecb 100644 --- a/scripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gml +++ b/scripts/scr_imperial_navy_functions/scr_imperial_navy_functions.gml @@ -305,7 +305,7 @@ function navy_hunt_player_assets() { var chase_fleet = get_nearest_player_fleet(x, y, false, true); if (chase_fleet != noone) { var thatp, my_dis; - etah = chase_fleet.eta; + etah = chase_fleet.action_eta; var intercept = fleet_intercept_time_calculate(chase_fleet); if (intercept) { diff --git a/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml b/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml index 06f69c5baa..ac4f99ce3f 100644 --- a/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml +++ b/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml @@ -509,7 +509,7 @@ function inquisitor_inspection_structure() constructor { scr_alert("red", "inspect", _msg, 0, 0); } } - if (finds.daemonic == 0 && !_struct_exists(finds, "xenos_mercs")) { + if (finds.daemonic == 0 && !struct_exists(finds, "xenos_mercs")) { scr_alert("red", "inspect", "Inquisitor discovers heretical material in your posession.", 0, 0); } diff --git a/scripts/scr_inquisition_mission/scr_inquisition_mission.gml b/scripts/scr_inquisition_mission/scr_inquisition_mission.gml index 29c0737d4a..55c3a2da88 100644 --- a/scripts/scr_inquisition_mission/scr_inquisition_mission.gml +++ b/scripts/scr_inquisition_mission/scr_inquisition_mission.gml @@ -815,7 +815,7 @@ function necron_tomb_mission_sequence() { obj_ncombat.battle_id = pop_data.planet; obj_ncombat.dropping = 0; obj_ncombat.attacking = 0; - obj_ncombat.enemy = 13; + obj_ncombat.enemy = eFACTION.NECRONS; obj_ncombat.threat = 1; obj_ncombat.formation_set = 1; obj_ncombat.battle_mission = "necron_tomb_excursion"; diff --git a/scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gml b/scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gml index 127d2b3c07..47696e833c 100644 --- a/scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gml +++ b/scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.gml @@ -1,3 +1,4 @@ +/// @self Id.Instance.obj_en_fleet function khorne_fleet_cargo() { //This handles khorne fleets killing planet popultions moving planet and then choosing a new target ot chase warband = cargo_data.warband; @@ -160,7 +161,7 @@ function khorne_fleet_cargo() { if ((chase_fleet != noone) && (action == "")) { var intercept_time = fleet_intercept_time_calculate(chase_fleet); if (chase_fleet.action != "") { - if (intercept_time <= chase_fleet.eta) { + if (intercept_time <= chase_fleet.action_eta) { target = chase_fleet; chase_fleet_target_set(target); target_chosen = true; @@ -291,6 +292,7 @@ function spawn_chaos_warlord() { } //TODO make this make sense +/// @self Id.Instance.obj_en_fleet function destroy_khorne_fleet() { var chaos_lord_killed = false; with (instance_nearest(x, y, obj_star)) { diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index 3624896e31..51385c0e7c 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -85,8 +85,25 @@ enum eEQUIPMENT_SLOT { ALL, } +enum eROLE_TAG { + Techmarine = 0, + Librarian = 1, + Chaplain = 2, + Apothecary = 3, +} + function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {}) constructor { + // Metadata uid = scr_uuid_generate(); + company = comp; //marine company + marine_number = mar; //marine number in company + squad = "none"; + base_group = "none"; + job = "none"; + manage_tags = []; + spawn_data = other_spawn_data; + + // Core RPG Stats constitution = 0; strength = 0; luck = 0; @@ -98,60 +115,275 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} intelligence = 0; weapon_skill = 0; ballistic_skill = 0; - size = 0; + + // Location Data planet_location = 0; location_string = ""; - if (!instance_exists(obj_controller) && class != "blank") { - //game start unit planet location - planet_location = obj_ini.home_planet; - } ship_location = -1; last_ship = { uid: "", name: "", }; - religion = "none"; - job = "none"; - psionic = 0; - corruption = 0; - religion_sub_cult = "none"; - base_group = "none"; - role_history = []; + + // Lore + allegiance = faction; //faction alligience defaults to the chapter + loyalty = 0; epithets = []; - enum eROLE_TAG { - Techmarine = 0, - Librarian = 1, - Chaplain = 2, - Apothecary = 3, - } + role_history = []; role_tag = [ 0, 0, 0, 0 - ]; // [Techmarine, Librarian, Chaplain, Apothecary] // maybe add to list instead? + ]; // [Techmarine, Librarian, Chaplain, Apothecary] maybe add to list instead? + + // Psy and religion + religion = "none"; + religion_sub_cult = "none"; + corruption = 0; + psionic = 0; + powers_known = []; + + // Health + body = generate_marine_body(); + unit_health = 0; + bionics = 0; + size = 0; + + // Progression + experience = 0; + stat_point_exp_marker = 0; + turn_stat_gains = {}; + traits = []; //marine trait list + feats = []; + + // Customization + personal_livery = {}; + + // Equipment + gear_quality = "standard"; + armour_quality = "standard"; + mobility_item_quality = "standard"; + weapon_one_quality = "standard"; + weapon_two_quality = "standard"; + weapon_one_data = { + quality: "standard", + }; + + // Combat States encumbered_ranged = false; encumbered_melee = false; - company = comp; //marine company - marine_number = mar; //marine number in company - squad = "none"; - stat_point_exp_marker = 0; - bionics = 0; - spawn_data = other_spawn_data; - unit_health = 0; + is_boarder = false; + + if (!instance_exists(obj_controller) && class != "blank") { + //game start unit planet location + planet_location = obj_ini.home_planet; + } + if (faction == "chapter" && !struct_exists(spawn_data, "recruit_data")) { spawn_data.recruit_data = { recruit_world: obj_ini.recruiting_type, aspirant_trial: obj_ini.recruit_trial, }; } - experience = 0; - turn_stat_gains = {}; - powers_known = []; - personal_livery = {}; + //takes dict and plumbs dict values into unit struct + if (array_contains(variable_struct_get_names(global.base_stats), class)) { + load_json_data(global.base_stats[$ class]); + } - manage_tags = []; + if (struct_exists(self, "start_gear")) { + if (base_group != "marine") { + alter_equipment(start_gear, false, false); + } else { + alter_equipment(start_gear, true, true); + } + } + + var stats = [ + "constitution", + "strength", + "luck", + "dexterity", + "wisdom", + "piety", + "charisma", + "technology", + "intelligence", + "weapon_skill", + "ballistic_skill" + ]; + + for (var stat_iter = 0; stat_iter < array_length(stats); stat_iter++) { + if (struct_exists(self, stats[stat_iter])) { + if (is_array(variable_struct_get(self, stats[stat_iter]))) { + var edit_stat = variable_struct_get(self, stats[stat_iter]); + var stat_mod = floor(gauss(edit_stat[0], edit_stat[1])); + if (array_length(edit_stat) > 2) { + if (edit_stat[2] == "max") { + variable_struct_set(self, stats[stat_iter], max(stat_mod, edit_stat[0])); + } else if (edit_stat[2] == "min") { + variable_struct_set(self, stats[stat_iter], min(stat_mod, edit_stat[0])); + } else { + variable_struct_set(self, stats[stat_iter], stat_mod); + } + } else { + variable_struct_set(self, stats[stat_iter], stat_mod); + } + } + } + } + + /*ey so i got this concept where basically take away luck, ballistic_skill and weapon_skill + there are 8 other stats each of which will have more attached aspects and game play elements + they effect as time goes on, so that means between the 8 other stats if you had a choice of two + there are 64 (or 56 if you exclude double counts) variations of a choice of two, this means each + chapter could have two "values" maybe in terms of recruitment maybe in terms of just general chapter stuff. + that could be chosen to give boostes to the other stats + so as an example salamanders could have the chapter values as */ + + switch (base_group) { + case "astartes": //basic marine class //adds specific mechanics not releveant to most units + loyalty = 100; + + var _astartes_trait_dist = global.astartes_trait_dist; + distribute_traits(_astartes_trait_dist); + + if (instance_exists(obj_controller)) { + role_history = [ + [ + obj_ini.role[company][marine_number], + obj_controller.turn + ] + ]; //marines_promotion and demotion history + marine_ascension = (obj_controller.millenium * 1000) + obj_controller.year; // on what day did this marine begin to exist + } else { + role_history = []; + marine_ascension = 0; // on what turn did this marine begin to exist + } + + roll_psionics(); + + alter_body("torso", "black_carapace", true); + if (class == "scout" && global.chapter_name != "Space Wolves") { + alter_body("torso", "black_carapace", false); + } + if (faction == "chapter") { + allegiance = global.chapter_name; + } + + static assign_inherent_mutations = function() { + gene_seed_mutations = { + "preomnor": obj_ini.preomnor, + "lyman": obj_ini.lyman, + "omophagea": obj_ini.omophagea, + "ossmodula": obj_ini.ossmodula, + "zygote": obj_ini.zygote, + "betchers": obj_ini.betchers, + "catalepsean": obj_ini.catalepsean, + "occulobe": obj_ini.occulobe, + "mucranoid": obj_ini.mucranoid, + "membrane": obj_ini.membrane, + "voice": obj_ini.voice, + }; + }; + + static assign_random_mutations = function() { + var _mutation_roll = roll_dice_unit(1, 100, "high", self); + var _mutation_threshold = 100 - obj_ini.stability; + if (_mutation_roll <= _mutation_threshold) { + var _mutation_names = struct_get_names(gene_seed_mutations); + var _possible_mutations = []; + for (var i = 0; i < array_length(_mutation_names); i++) { + var _mutation = _mutation_names[i]; + if (gene_seed_mutations[$ _mutation] == 0) { + array_push(_possible_mutations, _mutation); + } + } + + var _mutations_assigned = 0; + repeat (array_length(_possible_mutations)) { + if (array_length(_possible_mutations) > 0) { + var _picked_mutation = array_random_index(_possible_mutations); + gene_seed_mutations[$ _possible_mutations[_picked_mutation]] = 1; + array_delete(_possible_mutations, _picked_mutation, 1); + _mutations_assigned++; + _mutation_threshold = max(_mutation_threshold - 5 * _mutations_assigned, 0); + if (_mutation_roll <= _mutation_threshold) { + continue; + } else { + break; + } + } else { + break; + } + } + } + }; + + assign_inherent_mutations(); + assign_random_mutations(); + + if (gene_seed_mutations[$ "voice"] == 1) { + charisma -= 2; + } + + if ((global.chapter_name == "Space Wolves") || (obj_ini.progenitor == ePROGENITOR.SPACE_WOLVES)) { + religion_sub_cult = "The Allfather"; + } else if ((global.chapter_name == "Salamanders") || (obj_ini.progenitor == ePROGENITOR.SALAMANDERS)) { + religion_sub_cult = "The Promethean Cult"; + } else if (global.chapter_name == "Iron Hands" || obj_ini.progenitor == ePROGENITOR.IRON_HANDS) { + religion_sub_cult = "The Cult of Iron"; + } + + if (global.chapter_name == "Deathwatch") { + personal_livery.right_pauldron = irandom(30); + } + + var _robe_chance = 5; + if (global.chapter_name == "Black Templars") { + _robe_chance += 70; + } else if (scr_has_style("Knightly")) { + _robe_chance += 50; + } + if (irandom(100) <= _robe_chance) { + body.torso.robes = irandom(2); + if (body[$ "torso"].robes == 0 && irandom(1) == 0) { + body[$ "head"].hood = 1; + } + } + + var _cloak_chance = 5; + if (role() == obj_ini.role[100][eROLE.CHAPLAIN]) { + _cloak_chance += 25; + } else if (IsSpecialist(SPECIALISTS_LIBRARIANS)) { + _cloak_chance += 75; + } + if (irandom(100) <= _cloak_chance) { + if (global.chapter_name == "Salamanders") { + body.cloak.type = "scale"; + } else if (global.chapter_name == "Space Wolves") { + body.cloak.type = "pelt"; + } else { + body.cloak.type = "cloth"; + body.cloak.variation = irandom(100); + body.cloak.image_0 = irandom(100); + body.cloak.image_1 = irandom(100); + } + } + break; + case "tech_priest": + loyalty = obj_controller.disposition[eFACTION.MECHANICUS] - 10; + religion = "cult_mechanicus"; + bionics = irandom(5) + 4; + add_trait("flesh_is_weak"); + psionic = irandom(4); + break; + } + + if (base_group != "none") { + update_health(max_health()); //set marine unit_health to max + } static set_exp = function(new_val) { experience = new_val; @@ -360,9 +592,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} return size; }; - mobility_item_quality = "standard"; - armour_quality = "standard"; - //Unit update equip slot functions held in sscr_unit_equip_functions static update_armour = scr_update_unit_armour; static update_weapon_one = scr_update_unit_weapon_one; @@ -371,25 +600,26 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} static update_mobility_item = scr_update_unit_mobility_item; static max_health = function(base = false) { - var max_h = 100 * (1 + ((constitution - 40) * 0.05)); + var _max_h = max(1, constitution * 3); + if (!base) { - max_h += gear_weapon_data("armour", armour(), "hp_mod"); - max_h += gear_weapon_data("gear", gear(), "hp_mod"); - max_h += gear_weapon_data("mobility", mobility_item(), "hp_mod"); - max_h += gear_weapon_data("weapon", weapon_one(), "hp_mod"); - max_h += gear_weapon_data("weapon", weapon_two(), "hp_mod"); + var _gear_mod = 100; + _gear_mod += get_armour_data("hp_mod"); + _gear_mod += get_gear_data("hp_mod"); + _gear_mod += get_mobility_data("hp_mod"); + _gear_mod += get_weapon_one_data("hp_mod"); + _gear_mod += get_weapon_two_data("hp_mod"); + _gear_mod /= 100; + _max_h *= _gear_mod; } if (role() == "Guard Squad") { - max_h *= GUARD_SQUAD_SIZE; // a squad shares one pooled health bar and dies as a whole + _max_h *= GUARD_SQUAD_SIZE; // a squad shares one pooled health bar and dies as a whole } if (role() == "Heavy Weapons Team") { - max_h *= GUARD_HEAVY_WEAPONS_TEAM_SIZE; // a 3-man weapons team shares one pooled health bar + _max_h *= GUARD_HEAVY_WEAPONS_TEAM_SIZE; // a 3-man weapons team shares one pooled health bar } - return max_h; - }; - static increase_max_health = function(increase) { - return max_health() + (increase * (1 + ((constitution - 40) * 0.05))); //calculate the effect of unit_health buffs + return round(_max_h); }; // used both to load unit data from save and to add preset base_stats @@ -405,10 +635,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} } }; - traits = []; //marine trait list - feats = []; - allegiance = faction; //faction alligience defaults to the chapter - static stat_boosts = function(stat_boosters) { var stats = global.stat_list; var edits = struct_get_names(stat_boosters); @@ -514,44 +740,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} return equip_data; }; - //takes dict and plumbs dict values into unit struct - if (array_contains(variable_struct_get_names(global.base_stats), class)) { - load_json_data(global.base_stats[$ class]); - } - var stats = [ - "constitution", - "strength", - "luck", - "dexterity", - "wisdom", - "piety", - "charisma", - "technology", - "intelligence", - "weapon_skill", - "ballistic_skill" - ]; - for (var stat_iter = 0; stat_iter < array_length(stats); stat_iter++) { - if (struct_exists(self, stats[stat_iter])) { - if (is_array(variable_struct_get(self, stats[stat_iter]))) { - var edit_stat = variable_struct_get(self, stats[stat_iter]); - var stat_mod = floor(gauss(edit_stat[0], edit_stat[1])); - if (array_length(edit_stat) > 2) { - if (edit_stat[2] == "max") { - variable_struct_set(self, stats[stat_iter], max(stat_mod, edit_stat[0])); - } else if (edit_stat[2] == "min") { - variable_struct_set(self, stats[stat_iter], min(stat_mod, edit_stat[0])); - } else { - variable_struct_set(self, stats[stat_iter], stat_mod); - } - } else { - variable_struct_set(self, stats[stat_iter], stat_mod); - } - } - } - } - body = generate_marine_body(); - //body parts list can be extended as much as people want static alter_body = function(body_slot, body_item_key, new_body_data, overwrite = true) { @@ -567,14 +755,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} static get_body_data = scr_get_body_data; - if (struct_exists(self, "start_gear")) { - if (base_group != "marine") { - alter_equipment(start_gear, false, false); - } else { - alter_equipment(start_gear, true, true); - } - } - static equipment_has_tag = function(tag, area) { var _tags = []; switch (area) { @@ -615,154 +795,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} return burden; }; - /*ey so i got this concept where basically take away luck, ballistic_skill and weapon_skill - there are 8 other stats each of which will have more attached aspects and game play elements - they effect as time goes on, so that means between the 8 other stats if you had a choice of two - there are 64 (or 56 if you exclude double counts) variations of a choice of two, this means each - chapter could have two "values" maybe in terms of recruitment maybe in terms of just general chapter stuff. - that could be chosen to give boostes to the other stats - so as an example salamanders could have the chapter values as */ - loyalty = 0; - - switch (base_group) { - case "astartes": //basic marine class //adds specific mechanics not releveant to most units - loyalty = 100; - - var _astartes_trait_dist = global.astartes_trait_dist; - distribute_traits(_astartes_trait_dist); - - if (instance_exists(obj_controller)) { - role_history = [ - [ - obj_ini.role[company][marine_number], - obj_controller.turn - ] - ]; //marines_promotion and demotion history - marine_ascension = (obj_controller.millenium * 1000) + obj_controller.year; // on what day did this marine begin to exist - } else { - role_history = []; - marine_ascension = 0; // on what turn did this marine begin to exist - } - - roll_psionics(); - - alter_body("torso", "black_carapace", true); - if (class == "scout" && global.chapter_name != "Space Wolves") { - alter_body("torso", "black_carapace", false); - } - if (faction == "chapter") { - allegiance = global.chapter_name; - } - - static assign_inherent_mutations = function() { - gene_seed_mutations = { - "preomnor": obj_ini.preomnor, - "lyman": obj_ini.lyman, - "omophagea": obj_ini.omophagea, - "ossmodula": obj_ini.ossmodula, - "zygote": obj_ini.zygote, - "betchers": obj_ini.betchers, - "catalepsean": obj_ini.catalepsean, - "occulobe": obj_ini.occulobe, - "mucranoid": obj_ini.mucranoid, - "membrane": obj_ini.membrane, - "voice": obj_ini.voice, - }; - }; - - static assign_random_mutations = function() { - var _mutation_roll = roll_dice_unit(1, 100, "high", self); - var _mutation_threshold = 100 - obj_ini.stability; - if (_mutation_roll <= _mutation_threshold) { - var _mutation_names = struct_get_names(gene_seed_mutations); - var _possible_mutations = []; - for (var i = 0; i < array_length(_mutation_names); i++) { - var _mutation = _mutation_names[i]; - if (gene_seed_mutations[$ _mutation] == 0) { - array_push(_possible_mutations, _mutation); - } - } - - var _mutations_assigned = 0; - repeat (array_length(_possible_mutations)) { - if (array_length(_possible_mutations) > 0) { - var _picked_mutation = array_random_index(_possible_mutations); - gene_seed_mutations[$ _possible_mutations[_picked_mutation]] = 1; - array_delete(_possible_mutations, _picked_mutation, 1); - _mutations_assigned++; - _mutation_threshold = max(_mutation_threshold - 5 * _mutations_assigned, 0); - if (_mutation_roll <= _mutation_threshold) { - continue; - } else { - break; - } - } else { - break; - } - } - } - }; - - assign_inherent_mutations(); - assign_random_mutations(); - - if (gene_seed_mutations[$ "voice"] == 1) { - charisma -= 2; - } - - if ((global.chapter_name == "Space Wolves") || (obj_ini.progenitor == ePROGENITOR.SPACE_WOLVES)) { - religion_sub_cult = "The Allfather"; - } else if ((global.chapter_name == "Salamanders") || (obj_ini.progenitor == ePROGENITOR.SALAMANDERS)) { - religion_sub_cult = "The Promethean Cult"; - } else if (global.chapter_name == "Iron Hands" || obj_ini.progenitor == ePROGENITOR.IRON_HANDS) { - religion_sub_cult = "The Cult of Iron"; - } - - if (global.chapter_name == "Deathwatch") { - personal_livery.right_pauldron = irandom(30); - } - - var _robe_chance = 5; - if (global.chapter_name == "Black Templars") { - _robe_chance += 70; - } else if (scr_has_style("Knightly")) { - _robe_chance += 50; - } - if (irandom(100) <= _robe_chance) { - body.torso.robes = irandom(2); - if (body[$ "torso"].robes == 0 && irandom(1) == 0) { - body[$ "head"].hood = 1; - } - } - - var _cloak_chance = 5; - if (role() == obj_ini.role[100][eROLE.CHAPLAIN]) { - _cloak_chance += 25; - } else if (IsSpecialist(SPECIALISTS_LIBRARIANS)) { - _cloak_chance += 75; - } - if (irandom(100) <= _cloak_chance) { - if (global.chapter_name == "Salamanders") { - body.cloak.type = "scale"; - } else if (global.chapter_name == "Space Wolves") { - body.cloak.type = "pelt"; - } else { - body.cloak.type = "cloth"; - body.cloak.variation = irandom(100); - body.cloak.image_0 = irandom(100); - body.cloak.image_1 = irandom(100); - } - } - break; - case "tech_priest": - loyalty = obj_controller.disposition[eFACTION.MECHANICUS] - 10; - religeon = "cult_mechanicus"; - bionics = irandom(5) + 4; - add_trait("flesh_is_weak"); - psionic = irandom(4); - break; - } - static race = function() { return obj_ini.race[company][marine_number]; }; @@ -935,14 +967,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} return obj_ini.artifact[wep]; }; - is_boarder = false; - - gear_quality = "standard"; - - if (base_group != "none") { - update_health(max_health()); //set marine unit_health to max - } - static weapon_one = function(raw = false) { var wep = obj_ini.wep1[company][marine_number]; if (is_string(wep) || raw) { @@ -991,11 +1015,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} } }; - weapon_one_data = { - quality: "standard", - }; - weapon_one_quality = "standard"; - static weapon_viable = function(new_weapon, quality) { viable = true; qual_string = quality; @@ -1031,8 +1050,6 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} return obj_ini.artifact[wep]; }; - weapon_two_quality = "standard"; - static specials = function() { return obj_ini.spe[company][marine_number]; }; diff --git a/scripts/scr_mission_functions/scr_mission_functions.gml b/scripts/scr_mission_functions/scr_mission_functions.gml index 1f98b0e5ca..8a38d2204c 100644 --- a/scripts/scr_mission_functions/scr_mission_functions.gml +++ b/scripts/scr_mission_functions/scr_mission_functions.gml @@ -86,6 +86,7 @@ function mission_name_key(mission) { /// @self Struct.PlanetData function problem_end_turn_checks(){ + /// @self Struct.PlanetData static problem_functions = { "succession" : function(problem_index){ if (problem_timers[problem_index] > 0){ @@ -194,10 +195,9 @@ function problem_end_turn_checks(){ if (problem_timers[problem_index] > 0){ return; } - var _alert_text = "The Necron Tomb of planet "; alter_disposition(eFACTION.INQUISITION, -8); - _alert_text += $"{numeral_name} has not been deactivated in time. It has awakened, rank upon rank of Necrons pouring out to the planet's surface. The Inquisition is not pleased with your failure."; + var _alert_text = $"The Necron Tomb of planet {name()} has not been deactivated in time. It has awakened, rank upon rank of Necrons pouring out to the planet's surface. The Inquisition is not pleased with your failure."; scr_popup("Inquisition Mission Failed", _alert_text, "necron_army", ""); scr_event_log("red", $"Inquisition Mission Failed: Bombing run failed; the Necron Tomb on {name()} has become active."); @@ -952,7 +952,7 @@ function remove_star_problem(problem, star = noone) { } } else { with (star) { - remove_remove_star_problem(problem); + remove_star_problem(problem); } } } diff --git a/scripts/scr_pen_And_paper/scr_pen_And_paper.gml b/scripts/scr_pen_And_paper/scr_pen_And_paper.gml index a2982203d1..1a908bdb6c 100644 --- a/scripts/scr_pen_And_paper/scr_pen_And_paper.gml +++ b/scripts/scr_pen_And_paper/scr_pen_And_paper.gml @@ -158,11 +158,11 @@ function roll_dice(dices = 1, faces = 6) { } /// @description Roll a custom dice, influenced by the chapter' luck, return sum of all rolls. -/// @param {real} dices - how many dices to roll. -/// @param {real} faces - how many faces each dice has. -/// @param {real} player_benefit_at - will the player benefit from low or high rolls, for the luck logic. -/// @returns {real} -function roll_dice_chapter(dices = 1, faces = 6, player_benefit_at) { +/// @param {Real} dices - how many dices to roll. +/// @param {Real} faces - how many faces each dice has. +/// @param {String} player_benefit_at - will the player benefit from low or high rolls, for the luck logic. +/// @returns {Real} +function roll_dice_chapter(dices = 1, faces = 6, player_benefit_at = "high") { var _total_roll = 0; var _roll = 0; diff --git a/scripts/scr_player_fleet_functions/scr_player_fleet_functions.gml b/scripts/scr_player_fleet_functions/scr_player_fleet_functions.gml index 2064f118ed..371bf1212d 100644 --- a/scripts/scr_player_fleet_functions/scr_player_fleet_functions.gml +++ b/scripts/scr_player_fleet_functions/scr_player_fleet_functions.gml @@ -63,6 +63,17 @@ function split_selected_into_new_fleet(start_fleet) { return new_fleet; } +/// @param {Id.Instance.obj_p_fleet} _fleet +/// @param {Id.Instance.obj_star} _star +function set_fleet_orbiting(_fleet, _star) { + _star.present_fleet[1] += 1; + if (_star.vision == 0) { + _star.vision = 1; + } + _fleet.orbiting = _star; +} + +/// @self Id.Instance.obj_p_fleet function cancel_fleet_movement() { var nearest_star = instance_nearest(x, y, obj_star); action = ""; @@ -72,6 +83,8 @@ function cancel_fleet_movement() { action_y = 0; complex_route = []; just_left = false; + set_fleet_location(nearest_star.name); + set_fleet_orbiting(self, nearest_star); } function set_new_player_fleet_course(target_array) { @@ -96,7 +109,7 @@ function set_new_player_fleet_course(target_array) { complex_route = target_array; var from_x = from_star ? nearest_planet.x : x; var from_y = from_star ? nearest_planet.y : y; - action_eta = calculate_fleet_eta(from_x, from_y, target_planet.x, target_planet.y, action_spd, from_star,, warp_able); + action_eta = calculate_fleet_eta(from_x, from_y, target_planet.x, target_planet.y, action_spd, from_star, true, warp_able); action_x = target_planet.x; action_y = target_planet.y; action = "move"; @@ -580,6 +593,7 @@ function player_fleet_selected_count(fleet = noone) { return ship_count; } +/// @returns {Id.Instance.obj_p_fleet} function get_nearest_player_fleet(nearest_x, nearest_y, is_static = false, is_moving = false, stop_complex_actions = true) { var chosen_fleet = noone; if (instance_exists(obj_p_fleet)) { diff --git a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml index 599c6576ac..d1c3625d42 100644 --- a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml +++ b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml @@ -17,7 +17,7 @@ function return_lost_ship() { } } var _star = instance_find(obj_star, irandom(instance_number(obj_star) - 1)); - _new_fleet = instance_create(_star.x, _star.y, obj_p_fleet); + var _new_fleet = instance_create(_star.x, _star.y, obj_p_fleet); _new_fleet.owner = eFACTION.PLAYER; if (_lost_fleet != noone) { find_and_move_ship_between_fleets(_lost_fleet, _new_fleet, _return_id); @@ -84,6 +84,11 @@ function return_lost_ship() { } else { _text += $"The fate of your ship {obj_ini.ship[_return_id]} has now become clear. While it did not survive it's travels through the warp and tore itself apart somewhere in the {_star.name} system. "; scr_kill_ship(_return_id); + if (player_fleet_ship_count(_new_fleet) == 0) { + with (_new_fleet) { + instance_destroy(); + } + } if (array_length(_units) > 0) { _text += "Some of your astartes may have been able to jetison and survive the ships destruction"; } diff --git a/scripts/scr_population_influence/scr_population_influence.gml b/scripts/scr_population_influence/scr_population_influence.gml index 8df7598b6e..06b1fe6bef 100644 --- a/scripts/scr_population_influence/scr_population_influence.gml +++ b/scripts/scr_population_influence/scr_population_influence.gml @@ -1,3 +1,7 @@ +/// @param {Enum.eFACTION} faction +/// @param {Real} value +/// @param {Real} planet +/// @param {Id.Instance.obj_star} star function adjust_influence(faction, value, planet, star) { with (star) { p_influence[planet][faction] += value; @@ -28,11 +32,14 @@ function adjust_influence(faction, value, planet, star) { } } +/// @self Asset.GMObject.obj_star +/// @param {Array} doner_influence +/// @param {Real} planet function merge_influences(doner_influence, planet) { for (var i = 0; i < 15; i++) { if (i == 2) { continue; } - adjust_influence(i, (p_influence[planet][i] + doner_influence[i] / 2), planet, self); + adjust_influence(i, (p_influence[planet][i] + doner_influence[i] / 2), planet, id); } } diff --git a/scripts/scr_powers/scr_powers.gml b/scripts/scr_powers/scr_powers.gml index 65268acada..8e552dbada 100644 --- a/scripts/scr_powers/scr_powers.gml +++ b/scripts/scr_powers/scr_powers.gml @@ -773,7 +773,7 @@ function select_psychic_power(_unit) { // Flip anti-vehicle powers into smite; var _power_target_type = get_power_data(_power_id, "target_type"); if (_power_target_type == "enemy_vehicle") { - if (obj_enunit.veh < 1 || obj_ncombat.enemy == 9) { + if (obj_enunit.veh < 1 || obj_ncombat.enemy == eFACTION.TYRANIDS) { _power_id = "smite"; } } diff --git a/scripts/scr_promote/scr_promote.gml b/scripts/scr_promote/scr_promote.gml index 90906d38e4..5c050be414 100644 --- a/scripts/scr_promote/scr_promote.gml +++ b/scripts/scr_promote/scr_promote.gml @@ -1,5 +1,7 @@ +/// @self Id.Instance.obj_controller function setup_promotion_popup() { if ((sel_promoting == 1) && (!instance_exists(obj_popup))) { + /// @self Id.Instance.obj_popup var pip = instance_create(0, 0, obj_popup); pip.type = 5; pip.company = managing; @@ -150,10 +152,13 @@ function setup_promotion_popup() { cancel_button = new UnitButtonObject({x1: 1061, y1: 491, style: "pixel", label: "Cancel"}); main_slate = new DataSlate({style: "decorated", XX: 1006, YY: 143, set_width: true, width: 571, height: 350}); target_company_radio(min_exp); + target_comp = 0; + get_unit_promotion_options(); } } } +/// @self Id.Instance.obj_popup function target_company_radio(min_exp = 0) { var _company_options = [ { @@ -179,6 +184,7 @@ function target_company_radio(min_exp = 0) { companies_select.current_selection = 0; } +/// @self Id.Instance.obj_popup function draw_popup_promotion() { add_draw_return_values(); manag = obj_controller.managing; @@ -215,7 +221,7 @@ function draw_popup_promotion() { var role_x = 0; role_y = 0; if (target_comp != -1) { - for (var r = 1; r < array_length(role_name); r++) { + for (var r = 1, l = array_length(role_name); r < l; r++) { if (role_name[r] != "") { draw_set_alpha(1); check = " "; diff --git a/scripts/scr_purge_world/scr_purge_world.gml b/scripts/scr_purge_world/scr_purge_world.gml index 3278143439..5e4d979d0a 100644 --- a/scripts/scr_purge_world/scr_purge_world.gml +++ b/scripts/scr_purge_world/scr_purge_world.gml @@ -132,10 +132,14 @@ function PlayerPurge(action_type, action_score, planet_data) constructor { }; } +/// @self Struct.PlanetData function scr_purge_world(action_type, action_score) { var _purge = new PlayerPurge(action_type, action_score, self); - var _isquest = 0, _thequest = "", _questnum = 0; + var _isquest = 0; + var _thequest = ""; + var _questnum = 0; + var _popup_text = ""; _purge.pop_before = population_as_small(); @@ -184,7 +188,7 @@ function scr_purge_world(action_type, action_score) { obj_ncombat.battle_id = obj_controller.selecting_planet; obj_ncombat.dropping = 0; obj_ncombat.attacking = 10; - obj_ncombat.enemy = 10; + obj_ncombat.enemy = eFACTION.CHAOS; obj_ncombat.formation_set = 1; obj_ncombat.leader = 1; @@ -240,7 +244,7 @@ function scr_purge_world(action_type, action_score) { } else { if (nid_influence > 25) { _popup_text += " Scores of mutant offspring from a genestealer infestation are burnt, while we have damaged their influence over this world, the mutants appear to lack the organisation of a true cult"; - adjust_influence(eFACTION.TYRANIDS, -10, planet, star); + adjust_influence(eFACTION.TYRANIDS, -10, planet, system); } else if (nid_influence > 0) { _popup_text += " There are signs of a genestealer infestation but the cultists are too unorganized to do any real damage to their influence on this world"; } diff --git a/scripts/scr_ship_functions/scr_ship_functions.gml b/scripts/scr_ship_functions/scr_ship_functions.gml new file mode 100644 index 0000000000..7e26810b22 --- /dev/null +++ b/scripts/scr_ship_functions/scr_ship_functions.gml @@ -0,0 +1,28 @@ +/// @param {Id.Instance.obj_p_ship} _ship +function draw_ship_status_overlay(_ship, _hp_color, _shield_color) { + if (!instance_exists(_ship)) { + return; + } + + var _maxhp = _ship.maxhp; + if (_maxhp <= 0) { + return; + } + + var _shields = _ship.shields; + var _maxshields = _ship.maxshields; + var _has_shields = _shields > 0 && _maxshields > 0; + + var _display_value = _has_shields ? (_shields / _maxshields) : (_ship.hp / _maxhp); + var _color = _has_shields ? _shield_color : _hp_color; + + var _zoomed = false; + if (instance_exists(obj_controller)) { + _zoomed = obj_controller.zoomed != 0; + } + + var _scale = _zoomed ? 2 : 1; + var _text = $"{floor(_display_value * 100)}%"; + + draw_text_transformed_outline(_ship.x, _ship.y - _ship.sprite_height, _text, _scale, _scale, 0,,_color); +} diff --git a/scripts/scr_ship_functions/scr_ship_functions.yy b/scripts/scr_ship_functions/scr_ship_functions.yy new file mode 100644 index 0000000000..c6b3f3712d --- /dev/null +++ b/scripts/scr_ship_functions/scr_ship_functions.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"v1", + "%Name":"scr_ship_functions", + "isCompatibility":false, + "isDnD":false, + "name":"scr_ship_functions", + "parent":{ + "name":"Scripts", + "path":"folders/Scripts.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index 267c0f784e..012c201af2 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -44,11 +44,11 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat break; } } - if (obj_ncombat.enemy == 11) { + if (obj_ncombat.enemy == eFACTION.HERETICS) { aggregate_damage = round(aggregate_damage * 1.15); armour_pierce = round(armour_pierce * 1.15); } - if ((obj_ncombat.enemy == 10) && (obj_ncombat.threat == 7)) { + if ((obj_ncombat.enemy == eFACTION.CHAOS) && (obj_ncombat.threat == 7)) { doom = 1; } diff --git a/scripts/scr_ui_manage/scr_ui_manage.gml b/scripts/scr_ui_manage/scr_ui_manage.gml index e73e68a429..2e1b382d88 100644 --- a/scripts/scr_ui_manage/scr_ui_manage.gml +++ b/scripts/scr_ui_manage/scr_ui_manage.gml @@ -250,9 +250,9 @@ function reset_manage_unit_constants(unit) { _res_tool += $"CON: {round(unit.constitution / 2)}%"; unit_manage_constants.damage_res = new LabeledIcon(spr_icon_iron_halo, $"{_damage_res}%", 0, 0, {icon_width: 24, icon_height: 24, tooltip: _res_tool}); - var _hp_val = $"{round(unit.hp())}/{round(unit.max_health())}"; + var _hp_val = $"{round(unit.hp())}/{unit.max_health()}"; var _hp_tool = "A measure of how much punishment the creature can take. Marines can go into the negatives and still survive, but they'll require a bionic to become fighting fit once more.\n\nContributing factors:\n"; - _hp_tool += $"CON: {round(100 * (1 + ((unit.constitution - 40) * 0.025)))}\n"; + _hp_tool += $"CON: {unit.constitution * 3}\n"; for (var i = 0; i < array_length(equipment_types); i++) { var equipment_type = equipment_types[i]; diff --git a/scripts/scr_zoom/scr_zoom.gml b/scripts/scr_zoom/scr_zoom.gml index a3a28e4d6d..875d905d99 100644 --- a/scripts/scr_zoom/scr_zoom.gml +++ b/scripts/scr_zoom/scr_zoom.gml @@ -31,10 +31,11 @@ function set_zoom_to_default() { /// @description This script will zoom in and out of the game view based on the keys pressed. /// @self obj_controller function scr_zoom_keys() { - static zoom_speed = 0.1; static min_zoom = 0.3; static max_zoom = 2.5; + var zoom_speed = 0.1; + if (keyboard_check(vk_shift)) { zoom_speed *= 2; } @@ -64,7 +65,7 @@ function scr_zoom_keys() { var old_w = camera_get_view_width(view_camera[0]); var old_h = camera_get_view_height(view_camera[0]); if (old_w > 0 && old_h > 0) { - var zoom_factor = 1 - zoom_speed * zoom_delta; + var zoom_factor = max(0.1, 1 - zoom_speed * zoom_delta); var new_w = old_w * zoom_factor; var new_h = old_h * zoom_factor; camera_set_view_size(view_camera[0], new_w, new_h); From 82e24635e866c5f0c37b80e74786a5d4841e3f48 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 2 Jul 2026 19:56:45 +0300 Subject: [PATCH 054/140] Fix Governor Guardsman purchase crash from un-rolled array stats in max_health Buying Guardsmen from the Sector Governor crashed with "Variable is malformed" in max_health (constitution * 3) and the unit was never created. unit_stats.json defines ranged stats as arrays (guardsman constitution [28, 1, "max"]), and the TTRPG_stats constructor applied start_gear BEFORE rolling those arrays into numbers. Equipping armour runs hp_portion -> max_health, which reads constitution directly since the upstream max-health rework, so it multiplied the raw array. Moved the stat-rolling loop to run immediately after load_json_data, before start_gear is applied. Fixes any class with array-form stats plus start_gear; behavior-neutral for scalar stats. Upstream main has the identical latent ordering bug. --- .../scr_marine_struct/scr_marine_struct.gml | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index 51385c0e7c..d9f9705be3 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -192,14 +192,13 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} load_json_data(global.base_stats[$ class]); } - if (struct_exists(self, "start_gear")) { - if (base_group != "marine") { - alter_equipment(start_gear, false, false); - } else { - alter_equipment(start_gear, true, true); - } - } - + // Roll array-form stats into numbers BEFORE any equipment is applied. Classes with + // ranged stats in unit_stats.json (e.g. guardsman constitution [28, 1, "max"]) used to + // keep the raw array until after alter_equipment below, but equipping armour runs + // hp_portion -> max_health, which since the max-health rework reads constitution + // directly. Multiplying the un-rolled array threw "Variable is malformed" and aborted + // unit creation (Governor-bought Guardsmen crashed and never arrived). Upstream main + // has the same latent ordering bug. var stats = [ "constitution", "strength", @@ -234,6 +233,14 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} } } + if (struct_exists(self, "start_gear")) { + if (base_group != "marine") { + alter_equipment(start_gear, false, false); + } else { + alter_equipment(start_gear, true, true); + } + } + /*ey so i got this concept where basically take away luck, ballistic_skill and weapon_skill there are 8 other stats each of which will have more attached aspects and game play elements they effect as time goes on, so that means between the 8 other stats if you had a choice of two From c0f45c50e5e2460604dd6462a6d9ccf1dbe7c212 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 2 Jul 2026 20:23:23 +0300 Subject: [PATCH 055/140] Fix enemy armour pierce reading the player's weapon table; repair enemy AT tiers - scr_clean: damage_infantry/damage_vehicles run in the target obj_pnunit context and read apa[_weapon_index] there, indexing the PLAYER's weapon-stack arp table with the ENEMY's stack number. Enemy volleys inherited whatever armour pierce the player stack at that index had: apa 4 made enemy lasguns ignore armour (small arms wiping Dreadnoughts and Land Raiders), anything else made real anti-tank bounce. The attacker's armour_pierce is now passed from scr_shoot through scr_clean into both damage functions. - scr_clean: vehicle armour tier for arp 1 was mod 6, identical to arp 0, and nearly all enemy anti-tank weapons are arp 1, so enemy AT fire could not damage vehicles (Rokkit 150 - Rhino 30x6 = 0). Remapped arp 1 to mod 3. - scr_clean: spillover passed the full hostile_shots to the secondary path instead of the unspent remainder, double-firing volleys across unit types. - scr_clean: added a per-volley pen-vs-armour LOGGER.debug in damage_vehicles (MOD_IDEAS P5 debug trail). - scr_en_weapon: apa accumulated += arp per merged dude group; it is a per-weapon tier and is now assigned. - obj_enunit Alarm_1: stack reset loops started at index 1 while scr_en_weapon fills from 0, so the first weapon stack of every block accumulated shots, damage, and arp across all rebuilds for the entire battle. Loops now start at 0. All bugs exist verbatim in upstream main. --- ChapterMaster.yyp | 1 + datafiles/images/units/Guardsman Test.png | Bin 0 -> 45359 bytes datafiles/images/units/guardsman.png | Bin 45359 -> 26986 bytes objects/obj_enunit/Alarm_1.gml | 8 +++- scripts/scr_clean/scr_clean.gml | 43 +++++++++++++++++----- scripts/scr_en_weapon/scr_en_weapon.gml | 9 ++++- scripts/scr_shoot/scr_shoot.gml | 6 +-- 7 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 datafiles/images/units/Guardsman Test.png diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index e908dc453d..89c86ff604 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -511,6 +511,7 @@ {"$GMIncludedFile":"","%Name":"purge8.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"purge8.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"raid1.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"raid1.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"resources.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"resources.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, + {"$GMIncludedFile":"","%Name":"Guardsman Test.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Guardsman Test.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"sarge.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"sarge.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, diff --git a/datafiles/images/units/Guardsman Test.png b/datafiles/images/units/Guardsman Test.png new file mode 100644 index 0000000000000000000000000000000000000000..59ac96dbf596e122721186072d091c24b5e4b98f GIT binary patch literal 45359 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 }dCJ83Q}m`sXh1xoT#1B|hj(KQ@<_2l9`f1~$Pm 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 f{Qp1j1 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 literal 45359 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 }dCJ83Q}m`sXh1xoT#1B|hj(KQ@<_2l9`f1~$Pm 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 f{Qp1j 0) { - damage_vehicles(damage_data, hostile_shots, hostile_damage, weapon_index_position); + damage_vehicles(damage_data, hostile_shots, hostile_damage, weapon_index_position, hostile_arp); } // ### Marine + Dreadnought Processing ### if (target_is_infantry && (men + dreads > 0)) { - damage_infantry(damage_data, hostile_shots, hostile_damage, weapon_index_position, hostile_splash); + damage_infantry(damage_data, hostile_shots, hostile_damage, weapon_index_position, hostile_splash, hostile_arp); } if (damage_data.hits < hostile_shots) { + // Spillover: only the shots the primary path did not spend carry over. + // This used to pass the full hostile_shots again, so a volley that had + // already resolved against the primary target fired its entire count a + // second time at the secondary one. + var _remaining_shots = hostile_shots - damage_data.hits; + // ### Vehicle Damage Processing ### if (target_is_infantry && veh > 0) { - damage_vehicles(damage_data, hostile_shots, hostile_damage, weapon_index_position); + damage_vehicles(damage_data, _remaining_shots, hostile_damage, weapon_index_position, hostile_arp); } // ### Marine + Dreadnought Processing ### if (!target_is_infantry && (men + dreads > 0)) { - damage_infantry(damage_data, hostile_shots, hostile_damage, weapon_index_position, hostile_splash); + damage_infantry(damage_data, _remaining_shots, hostile_damage, weapon_index_position, hostile_splash, hostile_arp); } } @@ -204,8 +210,14 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam } /// @self Asset.GMObject.obj_pnunit -function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash) { - var _armour_pierce = apa[_weapon_index]; +function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash, _arp = 0) { + // _arp is the ATTACKER's armour pierce, passed down from scr_shoot. This used to read + // apa[_weapon_index], but this function runs in the TARGET obj_pnunit's context, so + // that indexed the PLAYER's own weapon-stack arp table with the ENEMY's stack number. + // Whatever player stack shared the index decided the enemy's armour penetration: land + // on a stack with apa 4 and enemy lasguns ignored armour entirely (dreadnoughts and + // vehicles melting to small arms); land elsewhere and real anti-tank bounced off. + var _armour_pierce = _arp; var _armour_mod = 0; switch (_armour_pierce) { case 4: @@ -453,8 +465,10 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash) } /// @self Asset.GMObject.obj_pnunit -function damage_vehicles(_damage_data, _shots, _damage, _weapon_index) { - var _armour_pierce = apa[_weapon_index]; +function damage_vehicles(_damage_data, _shots, _damage, _weapon_index, _arp = 0) { + // See damage_infantry: _arp is the attacker's real armour pierce. The old + // apa[_weapon_index] read pulled from the player's own stack table by index. + var _armour_pierce = _arp; var _armour_mod = 0; switch (_armour_pierce) { case 4: @@ -467,7 +481,12 @@ function damage_vehicles(_damage_data, _shots, _damage, _weapon_index) { _armour_mod = 4; break; case 1: - _armour_mod = 6; + // Was 6, identical to no armour pierce at all. Nearly every enemy anti-tank + // weapon (Rokkit Launcha, Lascannon, Missile Launcher, Kannon) is arp 1, so + // enemy AT fire did literally nothing to player vehicles: a Rokkit at att 150 + // against a Rhino (AC 30 x 6 = 180) resolved to 0. At mod 3 the same Rokkit + // does 60 per shot to a Rhino and still bounces off heavier hulls. + _armour_mod = 3; break; default: _armour_mod = 6; @@ -476,6 +495,10 @@ function damage_vehicles(_damage_data, _shots, _damage, _weapon_index) { var veh_index = -1; + // Pen-vs-armour debug trail (MOD_IDEAS P5): one line per volley so "my rockets did + // nothing" reports can be diagnosed from last_messages.log instead of guesswork. + LOGGER.debug($"veh volley: arp {_armour_pierce} mod {_armour_mod} dmg/shot {_damage} shots {_shots} target_ac {(array_length(veh_ac) > 1 ? veh_ac[1] : -1)}"); + // Find valid vehicle targets var valid_vehicles = []; for (var v = 0, l = array_length(veh_hp); v < l; v++) { diff --git a/scripts/scr_en_weapon/scr_en_weapon.gml b/scripts/scr_en_weapon/scr_en_weapon.gml index c6e771f734..4a567c20ae 100644 --- a/scripts/scr_en_weapon/scr_en_weapon.gml +++ b/scripts/scr_en_weapon/scr_en_weapon.gml @@ -1094,7 +1094,12 @@ function scr_en_weapon(name, is_man, man_number, man_type, group) { for (var b = 0; b < 30; b++) { if ((wep[b] == name) && (goody == 0)) { att[b] += atta * man_number; - apa[b] += arp; + // apa is the weapon's armour-pierce TIER, a property of the weapon, not a + // pool. It used to accumulate (+= arp) once per merged dude group and, via + // the un-reset slot 0, once per turn, so the tier drifted with block + // composition and battle length: two lascannon groups read as tier 2, four + // as tier 4 (ignore armour), five as junk. Set it, don't sum it. + apa[b] = arp; range[b] = rang; wep_num[b] += man_number; if (obj_ncombat.started == 0) { @@ -1117,7 +1122,7 @@ function scr_en_weapon(name, is_man, man_number, man_type, group) { wep[first] = name; splash[first] = spli; att[first] += atta * man_number; - apa[first] += arp; + apa[first] = arp; range[first] = rang; wep_num[first] += man_number; if (obj_ncombat.started == 0) { diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index 012c201af2..e4bf253248 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -90,7 +90,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat hostile_range = range[weapon_index_position]; hostile_splash = attack_count_mod; - scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position); + scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce); } } else if ((damage_type == "att") && (aggregate_damage > 0) && (stop == 0) && (shots_fired > 0)) { var damage_per_weapon, hit_number; @@ -126,7 +126,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat hostile_range = range[weapon_index_position]; hostile_splash = attack_count_mod; - scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position); + scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce); } } else if (((damage_type == "arp") || (damage_type == "dread")) && (armour_pierce > 0) && (stop == 0) && (shots_fired > 0)) { var damage_per_weapon, hit_number; @@ -177,7 +177,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat target_object.hostile_shooters = (wep_owner[weapon_index_position] == "assorted") ? 999 : 1; hostile_type = 0; - scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position); + scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce); } } } From 3e256ae604b260b01fb4b716da3ec2cfcfeb631e Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 2 Jul 2026 20:30:51 +0300 Subject: [PATCH 056/140] Give Heavy Weapons Teams crew-sized carry capacity and a half berth Heavy Weapons Teams fired permanently encumbered: the burden caps come from base_group, humans get base 1, and every HWT weapon is ranged_hands 2, so the team was over cap by existing. The unit represents GUARD_HEAVY_WEAPONS_TEAM_SIZE crew serving one deployed emplacement, so both hands limits now use the crew size for the "Heavy Weapons Team" role, scaling with the same macro as their pooled HP. Transport size moves from the shared guardsman tenth-slot to a dedicated 0.5 berth (three crew plus the gun and ammunition); ship_carrying is rebuilt from unit sizes on load so saves adjust automatically. Also fixed the melee burden tooltip hardcoding "Base: 2" regardless of the unit's actual base. --- .../scr_marine_struct/scr_marine_struct.gml | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index d9f9705be3..53abe65e85 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -583,10 +583,16 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} // Astartes, so a single trooper takes only a tenth of a marine's berth. A Guard // Squad is left at a full slot, since one already stands in for a whole squad. A // Guard Sergeant bunks with his men, so he takes the same tenth-slot as a trooper. - if (unit_role == "Guardsman" || unit_role == "Guard Sergeant" || unit_role == "Veteran Guard" || unit_role == "Heavy Weapons Team") { + if (unit_role == "Guardsman" || unit_role == "Guard Sergeant" || unit_role == "Veteran Guard") { size = 0.1; return size; } + // Heavy Weapons Team: three crew plus the gun and its ammunition. Half a marine + // berth rather than a lone trooper's tenth-slot. + if (unit_role == "Heavy Weapons Team") { + size = 0.5; + return size; + } if (string_count("Dread", arm) > 0) { sz += 5; } else if (array_contains(global.list_terminator_armour, arm)) { @@ -1249,6 +1255,14 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} } else if (base_group == "human") { ranged_hands_limit = 1; } + if (role() == "Heavy Weapons Team") { + // A weapons team is GUARD_HEAVY_WEAPONS_TEAM_SIZE crew serving one deployed + // emplacement, not one man hauling it. The human base of 1 left every + // ranged_hands 2 heavy weapon (Heavy Bolter, Lascannon, Autocannon) over the + // cap, so the team fired its own gun permanently encumbered. Give the unit + // the crew's combined hands instead. + ranged_hands_limit = GUARD_HEAVY_WEAPONS_TEAM_SIZE; + } carry_string += $"Base: {ranged_hands_limit}#"; if (strength >= 50) { ranged_hands_limit += 0.5; @@ -1445,7 +1459,11 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} } else if (base_group == "human") { melee_hands_limit = 1; } - carry_string += "Base: 2#"; + if (role() == "Heavy Weapons Team") { + // Crew hands, matching the ranged cap above. + melee_hands_limit = GUARD_HEAVY_WEAPONS_TEAM_SIZE; + } + carry_string += $"Base: {melee_hands_limit}#"; if (strength >= 50) { melee_hands_limit += 0.25; carry_string += "STR: +0.25#"; From 8030430a5cff1a6dd8aeed2a812dd39c18d849d4 Mon Sep 17 00:00:00 2001 From: KestasV Date: Thu, 2 Jul 2026 20:41:26 +0300 Subject: [PATCH 057/140] Reprice auxilia trade: Leman Russ 300, Basilisk 400, guardsmen 0.5 p - Leman Russ trade value 800 -> 300. - Basilisk had no relative_trade_values entry at all; the worth calculation skips missing labels via struct_exists, so Basilisks negotiated as free once the 50-disposition Mechanicus gate was passed. Priced at 400. - Guardsmen 0.1 -> 0.5 requisition per man (500 per 1000) in both the value table and the flat-levy deal override, priced for the combined-arms levy they arrive with (sergeant per squad, Heavy Weapons Team per 100, Chimera per 200). - Per-tank disposition cost (1 per vehicle, against the selling faction) already existed for both Leman Russ and Basilisk purchases; unchanged. --- scripts/scr_trade/scr_trade.gml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/scr_trade/scr_trade.gml b/scripts/scr_trade/scr_trade.gml index 9dffdfdfa2..812d94389c 100644 --- a/scripts/scr_trade/scr_trade.gml +++ b/scripts/scr_trade/scr_trade.gml @@ -17,8 +17,12 @@ function TradeAttempt(diplomacy) constructor { "Inferno Bolts": 5, "Sister of Battle": 40, "Sister Hospitaler": 75, - "Guardsman": 0.1, - "Leman Russ": 800, + "Guardsman": 0.5, + "Leman Russ": 300, + // A Basilisk had no entry here at all; the worth calculation is guarded by + // struct_exists, so missing entries contribute 0 and Basilisks negotiated as + // free once the 50-disposition gate was passed. + "Basilisk": 400, "Eldar Power Sword": 50, "Archeotech Laspistol": 150, "Ranger": 100, @@ -752,7 +756,9 @@ function TradeAttempt(diplomacy) constructor { // Guardsmen are abundant Imperial line troops the Sector Governor hands over by the // thousand, not a haggled rarity, so the base trade overhead does not apply to a - // pure Guard levy. They cost a flat 0.1 requisition each (100 per 1000). If the + // pure Guard levy. They cost a flat 0.5 requisition each (500 per 1000), priced + // for the full combined-arms levy that arrives with them: a Guard Sergeant per + // squad, a Heavy Weapons Team per 100, and a Chimera per 200. If the // offered requisition covers the guardsmen demanded the Governor obliges outright, // otherwise he declines. Only triggers when guardsmen are the sole demand, so it // cannot be used to slip other goods through cheaply. @@ -774,7 +780,7 @@ function TradeAttempt(diplomacy) constructor { _req_offered += offer_options[ri].number; } } - deal_chance = _req_offered >= ceil(_guard_num * 0.1) ? 100 : 0; + deal_chance = _req_offered >= ceil(_guard_num * 0.5) ? 100 : 0; } var _chance = clamp(floor((deal_chance / 20)), 0, 6); From f168e29bed022cad1773b46b20db5d02e0c63e57 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 00:16:16 +0300 Subject: [PATCH 058/140] Auxilia squad collapse view: one selectable row per Guard squad for ship loading The Auxilia roster rendered every guardsman as an individual row, making ship loading a per-man clicking exercise. The Auxilia view (managing 16) now defaults to a collapsed squad view: one row per Guard squad (a Guard Sergeant plus up to GUARD_SQUAD_SIZE Guardsmen at the same location) showing troop count, transport space, and location. Clicking a row selects or deselects the whole squad, mirroring scr_draw_management_unit's eligibility gates and selection side effects, so the existing Load-to-ships flow works unchanged. HWTs, Veteran Guard, and vehicles keep individual rows; the first roster row toggles squad/individual views; select-all, scrollbar, and paging work in both. Marine screens untouched (gated on managing 16). Note: stats_displayed is a function-scoped static of the manage draw function and is passed into draw_auxilia_squad_rows as a parameter; reading it bare from a separate function crashes with an unset-variable error. --- scripts/scr_ui_manage/scr_ui_manage.gml | 257 ++++++++++++++++++++++++ 1 file changed, 257 insertions(+) diff --git a/scripts/scr_ui_manage/scr_ui_manage.gml b/scripts/scr_ui_manage/scr_ui_manage.gml index 2e1b382d88..a947fa7eff 100644 --- a/scripts/scr_ui_manage/scr_ui_manage.gml +++ b/scripts/scr_ui_manage/scr_ui_manage.gml @@ -1040,8 +1040,30 @@ function scr_ui_manage() { }; if (!obj_controller.view_squad) { + // Auxilia squad collapse (managing 16): render Guard squads as single + // selectable rows instead of hundreds of individual guardsman rows, so ship + // loading is squad clicks rather than per-man clicks. Toggleable; defaults on. + if (!variable_instance_exists(id, "auxilia_squad_collapse")) { + auxilia_squad_collapse = true; + } + if ((managing == 16) && auxilia_squad_collapse) { + draw_auxilia_squad_rows(xx, yy, stats_displayed); + } else { var repetitions = min(man_max, MANAGE_MAN_SEE); man_count = 0; + if (managing == 16) { + // First roster row becomes the view toggle, consuming a row slot the same + // way company command-slot prompts do. + var _sq_btn = draw_unit_buttons([xx + 25, yy + 64, xx + 974, yy + 85], "Switch to Squad View", [1, 1], CM_GREEN_COLOR, fa_center, fnt_40k_14b); + draw_set_halign(fa_left); + draw_set_valign(fa_top); + if (point_and_click(_sq_btn)) { + auxilia_squad_collapse = true; + man_current = 0; + } + yy += 20; + repetitions--; + } var _command_slots_data = get_command_slots_data(); draw_set_font(fnt_40k_14); @@ -1132,6 +1154,7 @@ function scr_ui_manage() { draw_set_color(#3f7e5d); scr_scrollbar(974, 172, 1005, 790, 34, man_max, man_current); + } } if (instance_exists(obj_controller) && is_struct(obj_controller.unit_focus)) { var selected_unit = obj_controller.unit_focus; @@ -1627,3 +1650,237 @@ function draw_manage_selection_buttons(xx, yy) { } } } + +/// @self Asset.GMObject.obj_controller +/// @desc Collapsed squad rows for the Auxilia view (managing 16). Each Guard squad +/// (one Guard Sergeant plus up to GUARD_SQUAD_SIZE Guardsmen at the same location) +/// renders as a single row; clicking it selects or deselects every member, mirroring +/// the eligibility gates and selection side effects of scr_draw_management_unit so +/// the normal Load-to-ships flow (man_sel / man_size / selecting_location) just works. +/// Heavy Weapons Teams, Veteran Guard, and vehicles keep their normal individual rows. +function draw_auxilia_squad_rows(xx, yy, _stats_displayed = false) { + // Select-all buttons still work through the standard per-unit path. + if (sel_all != "" || squad_sel_count > 0) { + for (var i = 0; i < array_length(display_unit); i++) { + scr_draw_management_unit(i, yy, xx, false); + } + } + sel_all = ""; + + // ---- Bucket sergeants and guardsmen per location, in encounter order ---- + var _locs = []; + var _buckets = {}; + var _other_rows = []; + for (var i = 0; i < array_length(display_unit); i++) { + if (man[i] == "hide") { + continue; + } + var _is_unit = (man[i] == "man") && is_struct(display_unit[i]); + var _role = _is_unit ? display_unit[i].role() : ""; + if ((_role == "Guard Sergeant") || (_role == "Guardsman")) { + var _loc = string(ma_loc[i]); + if (!struct_exists(_buckets, _loc)) { + _buckets[$ _loc] = {sgts: [], grds: []}; + array_push(_locs, _loc); + } + if (_role == "Guard Sergeant") { + array_push(_buckets[$ _loc].sgts, i); + } else { + array_push(_buckets[$ _loc].grds, i); + } + } else { + array_push(_other_rows, i); + } + } + + // ---- Pair into squads: one sergeant heads up to GUARD_SQUAD_SIZE guardsmen ---- + var _rows = []; + for (var l = 0; l < array_length(_locs); l++) { + var _b = _buckets[$ _locs[l]]; + var _g = 0; + var _sg = 0; + var _sq = 0; + while ((_g < array_length(_b.grds)) || (_sg < array_length(_b.sgts))) { + var _members = []; + if (_sg < array_length(_b.sgts)) { + array_push(_members, _b.sgts[_sg]); + _sg++; + } + var _take = 0; + while ((_take < GUARD_SQUAD_SIZE) && (_g < array_length(_b.grds))) { + array_push(_members, _b.grds[_g]); + _g++; + _take++; + } + _sq++; + array_push(_rows, {squad_members: _members, squad_no: _sq, loc: _locs[l]}); + } + } + for (var o = 0; o < array_length(_other_rows); o++) { + array_push(_rows, {unit_row: _other_rows[o]}); + } + + var _row_max = array_length(_rows) + 1; // +1 for the toggle row + man_max = _row_max; // scrollbar drag math reads obj_controller.man_max directly + man_current = clamp(man_current, 0, max(0, _row_max - MANAGE_MAN_SEE)); + + // ---- Toggle row ---- + var _yy = yy; + var _sq_btn = draw_unit_buttons([xx + 25, _yy + 64, xx + 974, _yy + 85], "Switch to Individual View", [1, 1], CM_GREEN_COLOR, fa_center, fnt_40k_14b); + draw_set_halign(fa_left); + draw_set_valign(fa_top); + if (point_and_click(_sq_btn)) { + auxilia_squad_collapse = false; + man_max = MANAGE_MAN_MAX; + man_current = 0; + exit; + } + _yy += 20; + + // ---- Rows ---- + draw_set_font(fnt_40k_14); + var _visible = min(MANAGE_MAN_SEE - 1, _row_max - 1 - man_current); + for (var r = 0; r < _visible; r++) { + var _row = _rows[man_current + r]; + if (struct_exists(_row, "unit_row")) { + scr_draw_management_unit(_row.unit_row, _yy, xx, true); + draw_set_font(fnt_40k_14); + _yy += 20; + continue; + } + + var _members = _row.squad_members; + var _count = array_length(_members); + var _sel_count = 0; + var _size_sum = 0; + for (var m = 0; m < _count; m++) { + if (man_sel[_members[m]] == 1) { + _sel_count++; + } + if (is_struct(display_unit[_members[m]])) { + _size_sum += display_unit[_members[m]].get_unit_size(); + } + } + var _all_sel = (_count > 0) && (_sel_count == _count); + var _lead = display_unit[_members[0]]; + var _has_sgt = is_struct(_lead) && (_lead.role() == "Guard Sergeant"); + + var _label = $"Squad {_row.squad_no}"; + if (_has_sgt) { + _label += $" - Sgt. {_lead.name()}"; + } else { + _label += " - no sergeant"; + } + _label += $" | {_count} troops | {string_format(_size_sum, 1, 1)} space | {_row.loc}"; + if ((_sel_count > 0) && !_all_sel) { + _label += $" ({_sel_count}/{_count} selected)"; + } + + var _rect = [xx + 25, _yy + 64, xx + 974, _yy + 85]; + draw_set_color(c_black); + draw_rectangle(_rect[0], _rect[1], _rect[2], _rect[3], 0); + if (_sel_count > 0) { + draw_set_alpha(_all_sel ? 0.45 : 0.2); + draw_set_color(#1e5c40); + draw_rectangle(_rect[0], _rect[1], _rect[2], _rect[3], 0); + draw_set_alpha(1); + } + draw_set_color(_all_sel ? CM_GREEN_COLOR : c_gray); + draw_rectangle(_rect[0], _rect[1], _rect[2], _rect[3], 1); + draw_set_color(CM_GREEN_COLOR); + draw_text(xx + 35, _yy + 66, _label); + + // Hover focus so the Load / selection buttons render, like unit rows do. + if ((mouse_x >= _rect[0]) && (mouse_y >= _rect[1]) && (mouse_x < _rect[2]) && (mouse_y < _rect[3]) && is_struct(_lead)) { + unit_focus = _lead; + } + + // Click toggles the whole squad, mirroring scr_draw_management_unit's gates + // and side effects per member. + if (point_and_click(_rect) && (scrollbar_engaged == 0) && !instance_exists(obj_star_select)) { + var _target = _all_sel ? 0 : 1; + for (var m = 0; m < _count; m++) { + var _idx = _members[m]; + if (man_sel[_idx] == _target) { + continue; + } + if (!ma_view[_idx]) { + continue; + } + var _u = display_unit[_idx]; + if (!is_struct(_u)) { + continue; + } + if (_target == 1) { + if (!_u.controllable() || _u.in_jail()) { + continue; + } + if (selecting_location != "") { + var _wrong = false; + if (selecting_ship > -1) { + if (ma_lid[_idx] == -1) { + _wrong = true; + } else { + _wrong = obj_ini.ship_location[ma_lid[_idx]] != selecting_location; + } + } else { + _wrong = ma_loc[_idx] != selecting_location; + } + if (_wrong) { + continue; + } + } + if (selecting_location == "") { + selecting_location = ma_loc[_idx]; + selecting_ship = ma_lid[_idx]; + selecting_planet = ma_wid[_idx]; + } + ma_loc[_idx] = selecting_location; + } + man_sel[_idx] = _target; + if (_target == 1) { + man_size += _u.get_unit_size(); + } else { + man_size -= _u.get_unit_size(); + } + } + } + _yy += 20; + } + + // ---- Scroll furniture, selection buttons, scrollbar (mirrors the individual view tail) ---- + draw_set_color(c_black); + draw_rectangle(xx + 974, yy + 165, xx + 1005, yy + 822, 0); + draw_set_color(c_gray); + draw_rectangle(xx + 974, yy + 165, xx + 1005, yy + 822, 1); + draw_rectangle(xx + 25, yy + 142, xx + 14 + 8, yy + 822, 1); + draw_set_color(0); + draw_rectangle(xx + 974, yy + 141, xx + 1005, yy + 172, 0); + draw_rectangle(xx + 974, yy + 790, xx + 1005, yy + 822, 0); + draw_set_color(c_gray); + draw_rectangle(xx + 974, yy + 141, xx + 1005, yy + 172, 1); + draw_rectangle(xx + 974, yy + 790, xx + 1005, yy + 822, 1); + draw_sprite_stretched(spr_arrow, 2, xx + 974, yy + 141, 31, 30); + draw_sprite_stretched(spr_arrow, 3, xx + 974, yy + 791, 31, 30); + if (point_and_click([xx + 974, yy + 141, xx + 1005, yy + 172])) { + man_current = max(0, man_current - 1); + } + if (point_and_click([xx + 974, yy + 790, xx + 1005, yy + 822])) { + man_current = min(max(0, _row_max - MANAGE_MAN_SEE), man_current + 1); + } + + yy += 8; + // stats_displayed is a function-scoped static of the manage draw function, not an + // instance variable; reading it bare from this separate function crashed with an + // unset-variable error on the first Auxilia frame after loading. It is passed in + // as a parameter from the scope that owns it. + var _draw_selec_buttons = !obj_controller.unit_profile && !_stats_displayed; + if (_draw_selec_buttons && instance_exists(obj_popup)) { + _draw_selec_buttons = obj_popup.type != ePOPUP_TYPE.EQUIP; + } + if (_draw_selec_buttons && is_struct(obj_controller.unit_focus)) { + draw_manage_selection_buttons(xx, yy); + } + draw_set_color(#3f7e5d); + scr_scrollbar(974, 172, 1005, 790, 34, _row_max, man_current); +} From 6c8ad14347778f17fb8d779a075fdd33e9076165 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 00:45:48 +0300 Subject: [PATCH 059/140] Marine squad collapse view: one selectable row per squad, named by type Extends the Auxilia squad collapse to marine companies (managing 1-10). Units are grouped by their real squad membership (unit.squad ids in obj_ini.squads), one row per squad per location so rows are always fully loadable, labeled by squad type and numbered per type in roster order ("Tactical Squad 2", "Devastator Squad 1"), with nicknames and the actual Sergeant/Veteran Sergeant named. Clicking a row selects or deselects every member, mirroring scr_draw_management_unit's eligibility gates and selection side effects so the Load-to-ships flow works unchanged. Non-squad units (Captain, specialists, unassigned marines, vehicles) keep individual rows in roster order, and command-slot prompts (Captain Required, etc.) still render inside the collapsed view. Toggleable per view ("Switch to Squad List View" / "Switch to Individual View", named to avoid clashing with the existing Squad View button); defaults on. Auxilia collapse (managing 16) and the built-in Squad View untouched. --- scripts/scr_ui_manage/scr_ui_manage.gml | 268 +++++++++++++++++++++++- 1 file changed, 264 insertions(+), 4 deletions(-) diff --git a/scripts/scr_ui_manage/scr_ui_manage.gml b/scripts/scr_ui_manage/scr_ui_manage.gml index a947fa7eff..bd5eb64ace 100644 --- a/scripts/scr_ui_manage/scr_ui_manage.gml +++ b/scripts/scr_ui_manage/scr_ui_manage.gml @@ -1046,19 +1046,33 @@ function scr_ui_manage() { if (!variable_instance_exists(id, "auxilia_squad_collapse")) { auxilia_squad_collapse = true; } + if (!variable_instance_exists(id, "marine_squad_collapse")) { + marine_squad_collapse = true; + } if ((managing == 16) && auxilia_squad_collapse) { draw_auxilia_squad_rows(xx, yy, stats_displayed); + } else if ((managing >= 1) && (managing <= 10) && marine_squad_collapse) { + // Marine squad collapse: same collapsed-row treatment as the Auxilia + // view, but grouped by the real squads system (unit.squad ids), with + // squad-type names ("Tactical Squad 2") instead of generic numbering. + draw_marine_squad_rows(xx, yy, stats_displayed, get_command_slots_data()); } else { var repetitions = min(man_max, MANAGE_MAN_SEE); man_count = 0; - if (managing == 16) { + if ((managing == 16) || ((managing >= 1) && (managing <= 10))) { // First roster row becomes the view toggle, consuming a row slot the same - // way company command-slot prompts do. - var _sq_btn = draw_unit_buttons([xx + 25, yy + 64, xx + 974, yy + 85], "Switch to Squad View", [1, 1], CM_GREEN_COLOR, fa_center, fnt_40k_14b); + // way company command-slot prompts do. "Squad List" for marines to avoid + // clashing with the existing Squad View button in the unit panel. + var _sq_label = (managing == 16) ? "Switch to Squad View" : "Switch to Squad List View"; + var _sq_btn = draw_unit_buttons([xx + 25, yy + 64, xx + 974, yy + 85], _sq_label, [1, 1], CM_GREEN_COLOR, fa_center, fnt_40k_14b); draw_set_halign(fa_left); draw_set_valign(fa_top); if (point_and_click(_sq_btn)) { - auxilia_squad_collapse = true; + if (managing == 16) { + auxilia_squad_collapse = true; + } else { + marine_squad_collapse = true; + } man_current = 0; } yy += 20; @@ -1884,3 +1898,249 @@ function draw_auxilia_squad_rows(xx, yy, _stats_displayed = false) { draw_set_color(#3f7e5d); scr_scrollbar(974, 172, 1005, 790, 34, _row_max, man_current); } + +/// @self Asset.GMObject.obj_controller +/// @desc Collapsed squad rows for marine companies (managing 1-10). Units are grouped +/// by their real squad membership (unit.squad ids from obj_ini.squads) and location, +/// rendered one row per squad named by type: "Tactical Squad 2", "Devastator Squad 1", +/// etc., numbered per type in roster order, with the squad nickname when set. Clicking +/// a row selects or deselects every member, mirroring the eligibility gates and +/// selection side effects of scr_draw_management_unit so the normal Load-to-ships flow +/// (man_sel / man_size / selecting_location) just works. Units without a squad +/// (Captain, specialists, unassigned marines, vehicles) keep their normal individual +/// rows in roster order. Command-slot prompts (Captain Required, etc.) still render. +/// A squad split across locations shows one row per location so a row is always fully +/// loadable. _stats_displayed is passed in because it is a function-scoped static of +/// the manage draw function (see draw_auxilia_squad_rows). +function draw_marine_squad_rows(xx, yy, _stats_displayed = false, _command_slots = []) { + // Select-all buttons still work through the standard per-unit path. + if (sel_all != "" || squad_sel_count > 0) { + for (var i = 0; i < array_length(display_unit); i++) { + scr_draw_management_unit(i, yy, xx, false); + } + } + sel_all = ""; + + // ---- Group roster rows by (squad id, location), preserving encounter order ---- + var _rows = []; + var _groups = {}; + var _squad_num = {}; // squad id -> per-type number + var _type_counts = {}; // display_name -> squads seen so far + for (var i = 0; i < array_length(display_unit); i++) { + if (man[i] == "hide") { + continue; + } + var _is_unit = (man[i] == "man") && is_struct(display_unit[i]); + var _sq_id = "none"; + if (_is_unit && variable_struct_exists(display_unit[i], "squad")) { + _sq_id = display_unit[i].squad; + } + if ((_sq_id != "none") && is_string(_sq_id) && struct_exists(obj_ini.squads, _sq_id)) { + var _key = _sq_id + "|" + string(ma_loc[i]); + if (!struct_exists(_groups, _key)) { + var _grp = {squad_members: [], squad_id: _sq_id, loc: string(ma_loc[i])}; + _groups[$ _key] = _grp; + array_push(_rows, _grp); + if (!struct_exists(_squad_num, _sq_id)) { + var _sq = fetch_squad(_sq_id); + var _tname = "Squad"; + if (struct_exists(_sq, "display_name") && is_string(_sq.display_name) && (_sq.display_name != "")) { + _tname = _sq.display_name; + } + if (!struct_exists(_type_counts, _tname)) { + _type_counts[$ _tname] = 0; + } + _type_counts[$ _tname]++; + _squad_num[$ _sq_id] = {num: _type_counts[$ _tname], tname: _tname}; + } + } + array_push(_groups[$ _key].squad_members, i); + } else { + array_push(_rows, {unit_row: i}); + } + } + + // ---- Fixed rows: toggle + any open command-slot prompts ---- + var _empty_slots = []; + for (var r = 0; r < array_length(_command_slots); r++) { + if (company_data[$ _command_slots[r].unit_check] == "none") { + array_push(_empty_slots, _command_slots[r]); + } + } + var _fixed = 1 + array_length(_empty_slots); + var _row_max = array_length(_rows) + _fixed; + man_max = _row_max; // scrollbar drag math reads obj_controller.man_max directly + man_current = clamp(man_current, 0, max(0, _row_max - MANAGE_MAN_SEE)); + + // ---- Toggle row ---- + var _yy = yy; + var _sq_btn = draw_unit_buttons([xx + 25, _yy + 64, xx + 974, _yy + 85], "Switch to Individual View", [1, 1], CM_GREEN_COLOR, fa_center, fnt_40k_14b); + draw_set_halign(fa_left); + draw_set_valign(fa_top); + if (point_and_click(_sq_btn)) { + marine_squad_collapse = false; + man_max = MANAGE_MAN_MAX; + man_current = 0; + exit; + } + _yy += 20; + + // ---- Command-slot prompts (Captain Required, etc.) ---- + draw_set_font(fnt_40k_14); + for (var r = 0; r < array_length(_empty_slots); r++) { + var _slot = _empty_slots[r]; + if (command_slot_draw(xx, _yy, _slot.button_text)) { + command_slot_prompt(_slot.search_params, _slot.role_group_params, _slot.purpose, _slot.purpose_code); + } + _yy += 20; + } + + // ---- Rows ---- + var _visible = min(MANAGE_MAN_SEE - _fixed, array_length(_rows) - man_current); + for (var r = 0; r < _visible; r++) { + var _row = _rows[man_current + r]; + if (struct_exists(_row, "unit_row")) { + scr_draw_management_unit(_row.unit_row, _yy, xx, true); + draw_set_font(fnt_40k_14); + _yy += 20; + continue; + } + + var _members = _row.squad_members; + var _count = array_length(_members); + var _sel_count = 0; + var _size_sum = 0; + var _sgt = noone; + for (var m = 0; m < _count; m++) { + if (man_sel[_members[m]] == 1) { + _sel_count++; + } + var _mu = display_unit[_members[m]]; + if (is_struct(_mu)) { + _size_sum += _mu.get_unit_size(); + if ((_sgt == noone) && _mu.IsSpecialist(SPECIALISTS_SQUAD_LEADERS)) { + _sgt = _mu; + } + } + } + var _all_sel = (_count > 0) && (_sel_count == _count); + var _lead = is_struct(_sgt) ? _sgt : display_unit[_members[0]]; + + var _nd = _squad_num[$ _row.squad_id]; + var _label = $"{_nd.tname} {_nd.num}"; + var _sq = fetch_squad(_row.squad_id); + if (struct_exists(_sq, "nickname") && is_string(_sq.nickname) && (_sq.nickname != "")) { + _label += $" \"{_sq.nickname}\""; + } + if (is_struct(_sgt)) { + _label += $" - Sgt. {_sgt.name()}"; + } + _label += $" | {_count} troops | {string_format(_size_sum, 1, 1)} space | {_row.loc}"; + if ((_sel_count > 0) && !_all_sel) { + _label += $" ({_sel_count}/{_count} selected)"; + } + + var _rect = [xx + 25, _yy + 64, xx + 974, _yy + 85]; + draw_set_color(c_black); + draw_rectangle(_rect[0], _rect[1], _rect[2], _rect[3], 0); + if (_sel_count > 0) { + draw_set_alpha(_all_sel ? 0.45 : 0.2); + draw_set_color(#1e5c40); + draw_rectangle(_rect[0], _rect[1], _rect[2], _rect[3], 0); + draw_set_alpha(1); + } + draw_set_color(_all_sel ? CM_GREEN_COLOR : c_gray); + draw_rectangle(_rect[0], _rect[1], _rect[2], _rect[3], 1); + draw_set_color(CM_GREEN_COLOR); + draw_text(xx + 35, _yy + 66, _label); + + // Hover focus so the Load / selection buttons render, like unit rows do. + if ((mouse_x >= _rect[0]) && (mouse_y >= _rect[1]) && (mouse_x < _rect[2]) && (mouse_y < _rect[3]) && is_struct(_lead)) { + unit_focus = _lead; + } + + // Click toggles the whole squad, mirroring scr_draw_management_unit's gates + // and side effects per member. + if (point_and_click(_rect) && (scrollbar_engaged == 0) && !instance_exists(obj_star_select)) { + var _target = _all_sel ? 0 : 1; + for (var m = 0; m < _count; m++) { + var _idx = _members[m]; + if (man_sel[_idx] == _target) { + continue; + } + if (!ma_view[_idx]) { + continue; + } + var _u = display_unit[_idx]; + if (!is_struct(_u)) { + continue; + } + if (_target == 1) { + if (!_u.controllable() || _u.in_jail()) { + continue; + } + if (selecting_location != "") { + var _wrong = false; + if (selecting_ship > -1) { + if (ma_lid[_idx] == -1) { + _wrong = true; + } else { + _wrong = obj_ini.ship_location[ma_lid[_idx]] != selecting_location; + } + } else { + _wrong = ma_loc[_idx] != selecting_location; + } + if (_wrong) { + continue; + } + } + if (selecting_location == "") { + selecting_location = ma_loc[_idx]; + selecting_ship = ma_lid[_idx]; + selecting_planet = ma_wid[_idx]; + } + ma_loc[_idx] = selecting_location; + } + man_sel[_idx] = _target; + if (_target == 1) { + man_size += _u.get_unit_size(); + } else { + man_size -= _u.get_unit_size(); + } + } + } + _yy += 20; + } + + // ---- Scroll furniture, selection buttons, scrollbar (mirrors the individual view tail) ---- + draw_set_color(c_black); + draw_rectangle(xx + 974, yy + 165, xx + 1005, yy + 822, 0); + draw_set_color(c_gray); + draw_rectangle(xx + 974, yy + 165, xx + 1005, yy + 822, 1); + draw_rectangle(xx + 25, yy + 142, xx + 14 + 8, yy + 822, 1); + draw_set_color(0); + draw_rectangle(xx + 974, yy + 141, xx + 1005, yy + 172, 0); + draw_rectangle(xx + 974, yy + 790, xx + 1005, yy + 822, 0); + draw_set_color(c_gray); + draw_rectangle(xx + 974, yy + 141, xx + 1005, yy + 172, 1); + draw_rectangle(xx + 974, yy + 790, xx + 1005, yy + 822, 1); + draw_sprite_stretched(spr_arrow, 2, xx + 974, yy + 141, 31, 30); + draw_sprite_stretched(spr_arrow, 3, xx + 974, yy + 791, 31, 30); + if (point_and_click([xx + 974, yy + 141, xx + 1005, yy + 172])) { + man_current = max(0, man_current - 1); + } + if (point_and_click([xx + 974, yy + 790, xx + 1005, yy + 822])) { + man_current = min(max(0, _row_max - MANAGE_MAN_SEE), man_current + 1); + } + + yy += 8; + var _draw_selec_buttons = !obj_controller.unit_profile && !_stats_displayed; + if (_draw_selec_buttons && instance_exists(obj_popup)) { + _draw_selec_buttons = obj_popup.type != ePOPUP_TYPE.EQUIP; + } + if (_draw_selec_buttons && is_struct(obj_controller.unit_focus)) { + draw_manage_selection_buttons(xx, yy); + } + draw_set_color(#3f7e5d); + scr_scrollbar(974, 172, 1005, 790, 34, _row_max, man_current); +} From 380ee8a1c00720d5e79f7665fcfd277b4ad77e3d Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 02:28:51 +0300 Subject: [PATCH 060/140] Column piercing v3: scale partial-volley damage, spread remainder across armour lines Two fixes to the column piercing mechanic. First, scr_shoot's shot_override reduced the hit count without scaling aggregate damage: att[] is the stack's total (the builder accumulates atta * man_number) and per-hit damage is aggregate / hits, so a 50-shot remainder of a 146-autogun stack hit at 175 per shot instead of 60, punching through vehicle armour that normally bounces small arms (the "6 Autoguns kill a Leman Russ" report; the announced 6 was damage_vehicles breaking out early once the last vehicle died). Partial volleys now carry a proportional slice of the aggregate; apa is per-weapon and stays untouched. Second, the stopped-shot remainder previously landed entirely on the front block; every men-less armour line between the shooter and the first infantry rank now counts as wall and the remainder splits evenly across them, so a Chimera/Rhino second line soaks its share instead of the Leman Russ line eating everything. --- objects/obj_enunit/Alarm_0.gml | 121 ++++++++++++++++++++++++++------ scripts/macros/macros.gml | 9 +++ scripts/scr_shoot/scr_shoot.gml | 22 +++++- 3 files changed, 129 insertions(+), 23 deletions(-) diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index 161d67253d..cc5e7f6411 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -154,35 +154,114 @@ if (!engaged) { continue; } else if (instance_number(obj_pnunit) > 1) { // There were no marines in the first column, looking behind; - var _column_size_value = enemy.column_size; - var x2 = enemy.x; - - repeat (instance_number(obj_pnunit) - 1) { - x2 += !flank ? 10 : -10; - var enemy2 = instance_nearest(x2, y, obj_pnunit); + // Column piercing. This branch only runs when the front block has zero + // men, i.e. a tank wall (or similar armour-only block) is screening the + // infantry. The old code rolled a per-block "screening" chance that, + // behind a small vehicle block, pinned at its 80% cap and skipped the + // infantry, so ~4 of 5 anti-infantry volleys fell through to the vehicle + // fallback and plinked the armour. One tank became a bullet sponge for a + // thousand men behind it. Instead the volley now pierces by depth: the + // first men-bearing block behind the wall is hit by ENEMY_PIERCE_RANK2_SHOTS + // of the stack's shots, the second by ENEMY_PIERCE_RANK3_SHOTS, deeper + // blocks by nothing, and the front armour takes the shots that failed to + // pass. Men-behind-men screening is unaffected: a front block with men in + // it still absorbs the whole volley above. + // Finding the ranks: the old probe walked x2 in 10px steps with + // instance_nearest, and inherited vanilla's direction bug: the men + // look-behind stepped +10 for the main force (toward the enemy), + // opposite to the -10 the vehicle look-behinds correctly use, so it + // only ever resolved the front block itself and never reached the + // ranks behind. Blocks behind the front are instead collected + // directly (main force fronts are the rightmost block, so behind is + // lower x; flank fronts are leftmost, behind is higher x), sorted + // nearest-behind first, and the first two men-bearing blocks in + // weapon range become rank 2 and rank 3. + var _front_x = enemy.x; + var _behind = []; + with (obj_pnunit) { + if (id == other.enemy) { + continue; + } + if (x <= 0) { + continue; + } + var _is_behind = other.flank ? (x > _front_x) : (x < _front_x); + if (_is_behind) { + array_push(_behind, id); + } + } + if (flank) { + array_sort(_behind, function(_a, _b) { + return _a.x - _b.x; + }); + } else { + array_sort(_behind, function(_a, _b) { + return _b.x - _a.x; + }); + } + var _rank_blocks = []; + var _wall_blocks = []; + if (block_has_armour(enemy) || (enemy.veh_type[1] == "Defenses")) { + array_push(_wall_blocks, enemy); + } + for (var b = 0; b < array_length(_behind); b++) { + var enemy2 = _behind[b]; if (!target_block_is_valid(enemy2, obj_pnunit)) { continue; } - if (range[i] < get_block_distance(enemy2)) { break; } - - var _back_column_size_value = enemy2.column_size; - if (_back_column_size_value < _column_size_value) { - continue; - } else { - // Calculate chance of shots passing through to back row - // Higher ratio of back column size to front column size increases pass-through chance - // Maximum chance capped at 40% to ensure some protection remains - var _pass_chance = ((_back_column_size_value / _column_size_value) - 1) * 100; - if (irandom_range(1, 100) < min(_pass_chance, 80)) { - continue; + if (enemy2.men > 0) { + array_push(_rank_blocks, enemy2); + if (array_length(_rank_blocks) >= 2) { + break; } + } else if ((array_length(_rank_blocks) == 0) && block_has_armour(enemy2)) { + // A men-less armour line between the shooter and the first + // infantry rank (Chimeras/Rhinos behind the Leman Russ line) + // is part of the wall: it soaks a share of the stopped shots + // instead of the front block eating them all. + array_push(_wall_blocks, enemy2); + } + } + if (array_length(_rank_blocks) > 0) { + var _total_shots = wep_num[i]; + var _rank2_shots = floor(_total_shots * ENEMY_PIERCE_RANK2_SHOTS); + var _rank3_shots = floor(_total_shots * ENEMY_PIERCE_RANK3_SHOTS); + var _front_shots = _total_shots - _rank2_shots; + var _ammo_spent = false; + if (_rank2_shots > 0) { + scr_shoot(i, _rank_blocks[0], target_unit_index, "att", "ranged", _rank2_shots, !_ammo_spent); + _ammo_spent = true; + _shot = true; + } + if ((array_length(_rank_blocks) > 1) && (_rank3_shots > 0)) { + scr_shoot(i, _rank_blocks[1], target_unit_index, "att", "ranged", _rank3_shots, !_ammo_spent); + _ammo_spent = true; + _shot = true; + } + // The shots stopped by the wall still land on the wall, split + // across every armour line in front of the infantry (Leman Russ + // line, then Chimeras/Rhinos), so armour keeps taking chip fire + // and no single front block eats the whole remainder. + var _wall_count = array_length(_wall_blocks); + if ((_front_shots > 0) && (_wall_count > 0)) { + var _per_wall = floor(_front_shots / _wall_count); + var _extra = _front_shots - (_per_wall * _wall_count); + for (var w = 0; w < _wall_count; w++) { + var _w_shots = _per_wall + ((w == 0) ? _extra : 0); + if (_w_shots <= 0) { + continue; + } + scr_shoot(i, _wall_blocks[w], target_unit_index, "att", "ranged", _w_shots, !_ammo_spent); + _ammo_spent = true; + _shot = true; + } + } + if (_shot) { + continue; } - scr_shoot(i, enemy2, target_unit_index, "att", "ranged"); - _shot = true; - break; } } diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 4d9be9d137..6323989ec9 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -33,6 +33,15 @@ // heaviest guns chase tanks; drop toward 1 for the old behaviour where almost everything did. #macro GUARD_ENEMY_ANTITANK_AP 3 +// Enemy column piercing: when the player's front block has no men (a tank wall), enemy +// anti-infantry weapons no longer dump whole volleys into the armour. The volley splits by +// depth: the first men-bearing block behind the wall is hit by RANK2 of the shots, the second +// by RANK3, anything deeper by nothing, and the front armour takes the shots that failed to +// pass (1 - RANK2). Tune both toward 0 to restore the old bullet-sponge wall, toward 1 to make +// armour fully transparent to small-arms fire. +#macro ENEMY_PIERCE_RANK2_SHOTS 0.66 +#macro ENEMY_PIERCE_RANK3_SHOTS 0.33 + // Guard volley size: how many rank-and-file guardsmen share one firing stack in combat. The // regiment splits into capped stacks of this size instead of merging into one giant lasgun // volley, so each chunk fires and targets independently like an enemy obj_enunit block (those diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index e4bf253248..b5a6c4625c 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -1,10 +1,15 @@ -function scr_shoot(weapon_index_position, target_object, target_type, damage_data, melee_or_ranged) { +function scr_shoot(weapon_index_position, target_object, target_type, damage_data, melee_or_ranged, shot_override = -1, consume_ammo = true) { try { // weapon_index_position: Weapon number // target_object: Target object // target_type: Target dudes // damage_data: "att" or "arp" or "highest" // melee_or_ranged: melee or ranged + // shot_override: fire only this many of the stack's shots (-1 = full stack, the + // default and the behaviour of every pre-existing caller). Used by enemy column + // piercing to split one volley across several player blocks. + // consume_ammo: when one weapon stack fires several sub-volleys in the same alarm + // (column piercing), only the first call spends the turn's ammo tick. // This massive clusterfuck of a script uses the newly determined weapon and target data to attack and assign damage var hostile_type; @@ -21,6 +26,19 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat if ((weapon_index_position >= 0) && instance_exists(target_object) && (owner == 2)) { var stop, damage_type, doom; var shots_fired = wep_num[weapon_index_position]; + if (shot_override > -1) { + var _stack_shots = shots_fired; + shots_fired = min(shot_override, shots_fired); + // att[] is the stack's TOTAL damage (the builder accumulates + // atta * man_number), and per-hit damage is aggregate / hit count. + // A partial volley must carry a proportional slice of the aggregate, + // otherwise 50 shots deliver the whole stack's damage and chip fire + // one-shots vehicles it should bounce off. apa[] is per-weapon + // (set, not summed in the builder) and stays untouched. + if ((_stack_shots > 0) && (shots_fired < _stack_shots)) { + aggregate_damage = (aggregate_damage * shots_fired) / _stack_shots; + } + } if (shots_fired == 0 || ammo[weapon_index_position] == 0) { exit; } @@ -55,7 +73,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat damage_type = ""; stop = 0; - if (ammo[weapon_index_position] > 0) { + if (consume_ammo && (ammo[weapon_index_position] > 0)) { ammo[weapon_index_position] -= 1; } From df6cde6ae4fb4a1079d15f8bd34a7d50c8d80049 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 03:13:46 +0300 Subject: [PATCH 061/140] Vehicle portraits: hover a vehicle row to show its picture, Chimera wired Vehicles never route through scr_draw_unit_image and set no unit_focus, so they had no portrait anywhere in the game. Hovering a vehicle row in the manage screen now stores its role (scr_draw_management_unit), and the portrait slot in the unit panel (scr_ui_manage) maps roles to runtime PNGs loaded from images\units\, scaled and centered to the 166x232 frame; hovering a unit hands the slot back to the normal unit image. Adding future vehicle portraits is one line in the _veh_portrait_files lookup plus the PNG. Chimera wired to images\units\chimera.png (shipped). Runtime PNG loading mirrors the guardsman/sarge portrait hooks since the mod cannot add compiled sprite assets. --- ChapterMaster.yyp | 1 + datafiles/images/units/chimera.png | Bin 0 -> 82479 bytes .../scr_draw_management_unit.gml | 9 ++++++ scripts/scr_ui_manage/scr_ui_manage.gml | 30 +++++++++++++++++- 4 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 datafiles/images/units/chimera.png diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index 89c86ff604..4dff18ed57 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -511,6 +511,7 @@ {"$GMIncludedFile":"","%Name":"purge8.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"purge8.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"raid1.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"raid1.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"resources.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"resources.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, + {"$GMIncludedFile":"","%Name":"chimera.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"chimera.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Guardsman Test.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Guardsman Test.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, diff --git a/datafiles/images/units/chimera.png b/datafiles/images/units/chimera.png new file mode 100644 index 0000000000000000000000000000000000000000..3f3af15259b17f5bb057b34e22d4852baffd5ff1 GIT binary patch literal 82479 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

TN{@bQc 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 literal 0 HcmV?d00001 diff --git a/scripts/scr_draw_management_unit/scr_draw_management_unit.gml b/scripts/scr_draw_management_unit/scr_draw_management_unit.gml index e945d66275..8a93c28e0d 100644 --- a/scripts/scr_draw_management_unit/scr_draw_management_unit.gml +++ b/scripts/scr_draw_management_unit/scr_draw_management_unit.gml @@ -595,6 +595,15 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l if (((mouse_x >= xx + 25 && mouse_y >= yy + 64 && mouse_x < xx + 974 && mouse_y < yy + 85) || force_tool == 1) && is_struct(_unit)) { unit_focus = _unit; // unit_struct + // Hovering back onto a unit hands the portrait slot back to the unit image. + vehicle_portrait_role = ""; + } + } else if ((man[selected] == "vehicle") && draw) { + // Vehicle portraits (mod): vehicles set no unit_focus, so the portrait slot + // never knew a vehicle was hovered. Store the role; the manage panel maps it + // to a runtime PNG (see draw_sprite_and_unit_equip_data in scr_ui_manage). + if (mouse_x >= xx + 25 && mouse_y >= yy + 64 && mouse_x < xx + 974 && mouse_y < yy + 85) { + vehicle_portrait_role = string(ma_role[selected]); } } if (!ma_view[selected]) { diff --git a/scripts/scr_ui_manage/scr_ui_manage.gml b/scripts/scr_ui_manage/scr_ui_manage.gml index bd5eb64ace..688efd0546 100644 --- a/scripts/scr_ui_manage/scr_ui_manage.gml +++ b/scripts/scr_ui_manage/scr_ui_manage.gml @@ -663,7 +663,35 @@ function draw_sprite_and_unit_equip_data() { // Draw unit image draw_set_color(c_white); - if (is_struct(obj_controller.unit_manage_image)) { + // ===== Vehicle portraits (mod) ===== + // Vehicles never route through scr_draw_unit_image and set no unit_focus, so + // they had no portrait anywhere. Hovering a vehicle row (see + // scr_draw_management_unit) stores its role in vehicle_portrait_role, and the + // portrait slot draws a runtime PNG from images\units\ instead of the last + // unit's image, scaled to fit the frame. Adding a new vehicle portrait is one + // line in the struct below: role name on the left, PNG filename on the right. + var _veh_portrait_files = { + Chimera: "chimera", + }; + var _veh_p_role = variable_instance_exists(id, "vehicle_portrait_role") ? vehicle_portrait_role : ""; + var _veh_p_drawn = false; + if ((_veh_p_role != "") && struct_exists(_veh_portrait_files, _veh_p_role)) { + if (!variable_global_exists("vehicle_portraits")) { + global.vehicle_portraits = {}; + } + if (!struct_exists(global.vehicle_portraits, _veh_p_role)) { + global.vehicle_portraits[$ _veh_p_role] = sprite_add(working_directory + "/images/units/" + _veh_portrait_files[$ _veh_p_role] + ".png", 1, false, false, 0, 0); + } + var _veh_spr = global.vehicle_portraits[$ _veh_p_role]; + if (sprite_exists(_veh_spr)) { + var _vp_w = sprite_get_width(_veh_spr); + var _vp_h = sprite_get_height(_veh_spr); + var _vp_scale = min(1, 166 / _vp_w, 232 / _vp_h); + draw_sprite_ext(_veh_spr, 0, xx + 320 + ((166 - (_vp_w * _vp_scale)) / 2), yy + 109 + ((232 - (_vp_h * _vp_scale)) / 2), _vp_scale, _vp_scale, 0, c_white, 1); + _veh_p_drawn = true; + } + } + if (!_veh_p_drawn && is_struct(obj_controller.unit_manage_image)) { obj_controller.unit_manage_image.draw(xx + 320, yy + 109); } From bec6b367cae9b6b7ac0868043cde294ffc7d9701 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 15:48:07 +0300 Subject: [PATCH 062/140] Ship economy of attacks capped at 2 turns per ship instead of fleet wide as in vanilla Two revisions to the per-ship assault economy. Exhausted ships are no longer hidden from the drop roster: they stay listed as locked red toggles with an explanatory tooltip, and a sweep in scr_drop_select_function forces them back off after clicks and Select All (ToggleButton.clicked flips state unconditionally, so the lock is enforced at the consumer rather than in the shared button classes). Second, planetside local forces are capped at SHIP_ASSAULTS_PER_TURN ground assault supports per planet per turn, closing the exploit of deploying troops to the surface and attacking endlessly for free; any assault including local units spends one planet use, the Local Forces button locks red when spent, and the Attack gate treats exhausted locals as unavailable. Local-only attacks with no fleet in orbit, previously ungated entirely (also in vanilla), now respect planet exhaustion. Counters use the same turn-keyed pattern as ships (stored on the star instance, no save-format changes). Raids and purges still spend nothing. --- objects/obj_star_select/Draw_64.gml | 21 ++++- scripts/macros/macros.gml | 8 ++ .../scr_drop_select_function.gml | 56 ++++++++++++ .../scr_player_ship_functions.gml | 87 +++++++++++++++++++ scripts/scr_roster/scr_roster.gml | 16 ++++ 5 files changed, 186 insertions(+), 2 deletions(-) diff --git a/objects/obj_star_select/Draw_64.gml b/objects/obj_star_select/Draw_64.gml index 0abf773016..33ca1d17c7 100644 --- a/objects/obj_star_select/Draw_64.gml +++ b/objects/obj_star_select/Draw_64.gml @@ -337,11 +337,28 @@ try { } else if (current_button == "Attack") { var _allow_attack = true; var _targ = !target.present_fleet[1] ? noone : instance_nearest(x, y, obj_p_fleet); + // Ship assault economy: the old fleet-wide gate (acted >= 2) is + // replaced for ground assaults. An attack is possible while any + // carrying ship at this star still has support uses left this turn, + // or while planetside forces do and can fight without ship support. + // Local-only attacks (no fleet present) were previously ungated + // entirely; they now respect the planet's local exhaustion. Raid, + // Purge, and Bombard keep their fleet-level gates. + var _ship_available = false; if (instance_exists(_targ)) { - if (_targ.acted >= 2) { - _allow_attack = false; + var _gate_ships = get_player_ships(target.name); + for (var _gs = 0; _gs < array_length(_gate_ships); _gs++) { + if ((obj_ini.ship_carrying[_gate_ships[_gs]] > 0) && (ship_assaults_used(_gate_ships[_gs]) < SHIP_ASSAULTS_PER_TURN)) { + _ship_available = true; + break; + } } } + var _local_available = (p_data.player_forces > 0) && (local_assaults_used(target, obj_controller.selecting_planet) < SHIP_ASSAULTS_PER_TURN); + if (!_ship_available && !_local_available) { + _allow_attack = false; + scr_popup("Ground Assault", "Your forces at this world have already supported the maximum number of ground assaults this turn.", ""); + } if (_allow_attack) { // feather ignore once GM2064 instance_create_layer(x, y, layer_get_all()[0], obj_drop_select, {p_target: target, planet_number: obj_controller.selecting_planet, attack: true, sh_target: _targ, purge: 0}); diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 6323989ec9..1459011afc 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -42,6 +42,14 @@ #macro ENEMY_PIERCE_RANK2_SHOTS 0.66 #macro ENEMY_PIERCE_RANK3_SHOTS 0.33 +// Ship assault economy: how many ground assaults each ship can support per turn. The old +// rule capped the whole fleet at 2 attacks per turn regardless of size, so deploying +// everything on every assault cost nothing. Now each carrying ship supports this many +// assaults per turn, one use spent per assault it contributes units to; bigger fleets +// can clear a system in one turn, but every launch spends real capacity. Raids, purges, +// and bombardment keep their old fleet-level rules. +#macro SHIP_ASSAULTS_PER_TURN 2 + // Guard volley size: how many rank-and-file guardsmen share one firing stack in combat. The // regiment splits into capped stacks of this size instead of merging into one giant lasgun // volley, so each chunk fires and targets independently like an enemy obj_enunit block (those diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index b7c70add79..b8eab94262 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -78,11 +78,28 @@ function drop_select_unit_selection() { if (purge != eDROP_TYPE.PURGEBOMBARD) { var _local_button = roster.local_button; + // Local force exhaustion: planetside forces also support at most + // SHIP_ASSAULTS_PER_TURN ground assaults per turn, closing the loop of + // deploying troops to the surface and attacking endlessly for free. When + // spent, the button locks red like an exhausted ship. Attacks only. + var _locals_spent = (attack == 1) && (local_assaults_used(p_target, planet_number) >= SHIP_ASSAULTS_PER_TURN); + if (_locals_spent) { + if (_local_button.active) { + _local_button.active = false; + roster.update_roster(); + } + _local_button.text_color = c_red; + _local_button.button_color = c_red; + _local_button.tooltip = "This planet's forces have already supported the maximum number of ground assaults this turn."; + } _local_button.x1 = _buttons_x; _local_button.y1 = _buttons_y; _local_button.update(); _local_button.draw(); if (_local_button.clicked()) { + if (_locals_spent) { + _local_button.active = false; + } roster.update_roster(); } } @@ -97,6 +114,17 @@ function drop_select_unit_selection() { roster.ship_multi_selector.select_all(); } + // Ship assault economy: assault-exhausted ships are drawn locked and red (see + // scr_roster). ToggleButton clicks and Select All still flip their active flag, + // so force locked ships back off here before the selection is consumed. + for (var _ls = 0; _ls < array_length(roster.ships); _ls++) { + var _ls_btn = roster.ships[_ls]; + if (variable_struct_exists(_ls_btn, "assault_locked") && _ls_btn.assault_locked && _ls_btn.active) { + _ls_btn.active = false; + roster.ship_multi_selector.changed = true; + } + } + if (roster.ship_multi_selector.changed) { roster.update_roster(); } @@ -235,6 +263,34 @@ function drop_select_unit_selection() { sh_target.acted += 1; } + // Ship assault economy: each distinct ship contributing units to this + // ground assault spends one support use this turn (SHIP_ASSAULTS_PER_TURN + // max). fleet.acted above still ticks so raid and bombardment gating are + // unchanged. Local planetside forces (ship id -1) cost nothing. Raids do + // not spend uses. + if (attack == 1) { + var _spent_ships = []; + var _local_participated = false; + for (var _su = 0; _su < array_length(roster.selected_units); _su++) { + var _sel = roster.selected_units[_su]; + var _sel_ship = is_struct(_sel) ? _sel.ship_location : obj_ini.veh_lid[_sel[0]][_sel[1]]; + if (_sel_ship > -1) { + if (!array_contains(_spent_ships, _sel_ship)) { + array_push(_spent_ships, _sel_ship); + ship_assault_spend(_sel_ship); + } + } else { + _local_participated = true; + } + } + // Planetside forces joining the assault spend one of the planet's + // local support uses, so troops cannot be dropped onto the surface + // and used for unlimited free attacks. + if (_local_participated) { + local_assault_spend(p_target, planet_number); + } + } + if ((attacking == 10) || (attacking == 11)) { remove_planet_problem(planet_number, "meeting", p_target); remove_planet_problem(planet_number, "meeting_trap", p_target); diff --git a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml index d1c3625d42..f684388381 100644 --- a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml +++ b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml @@ -123,6 +123,93 @@ function get_player_ships(location = "", name = "") { return _ships; } +/// @desc How many ground assaults this ship has supported this turn. The counters are +/// keyed to obj_controller.turn: a stored count from any earlier turn reads as zero, so +/// there is no per-turn reset pass and nothing new needs saving (after a load the +/// counters simply start fresh). Out-of-range or missing arrays also read as zero. +function ship_assaults_used(ship_index) { + if (ship_index < 0) { + return 0; + } + if (!variable_instance_exists(obj_ini, "ship_assault_uses") || !variable_instance_exists(obj_ini, "ship_assault_turn")) { + return 0; + } + if ((ship_index >= array_length(obj_ini.ship_assault_uses)) || (ship_index >= array_length(obj_ini.ship_assault_turn))) { + return 0; + } + if (obj_ini.ship_assault_turn[ship_index] != obj_controller.turn) { + return 0; + } + return obj_ini.ship_assault_uses[ship_index]; +} + +/// @desc Spend one ground assault support use on this ship for the current turn. +function ship_assault_spend(ship_index) { + if (ship_index < 0) { + return; + } + if (!variable_instance_exists(obj_ini, "ship_assault_uses")) { + obj_ini.ship_assault_uses = []; + } + if (!variable_instance_exists(obj_ini, "ship_assault_turn")) { + obj_ini.ship_assault_turn = []; + } + while (array_length(obj_ini.ship_assault_uses) <= ship_index) { + array_push(obj_ini.ship_assault_uses, 0); + } + while (array_length(obj_ini.ship_assault_turn) <= ship_index) { + array_push(obj_ini.ship_assault_turn, -1); + } + if (obj_ini.ship_assault_turn[ship_index] != obj_controller.turn) { + obj_ini.ship_assault_turn[ship_index] = obj_controller.turn; + obj_ini.ship_assault_uses[ship_index] = 0; + } + obj_ini.ship_assault_uses[ship_index] += 1; +} + +/// @desc How many ground assaults this planet's local forces have supported this turn. +/// Same epoch-keyed pattern as the ship counters, stored on the star instance: counts +/// from earlier turns read as zero, missing arrays read as zero, nothing new is saved. +function local_assaults_used(star_object, planet_number) { + if (!instance_exists(star_object) || (planet_number < 0)) { + return 0; + } + if (!variable_instance_exists(star_object, "local_assault_uses") || !variable_instance_exists(star_object, "local_assault_turn")) { + return 0; + } + if ((planet_number >= array_length(star_object.local_assault_uses)) || (planet_number >= array_length(star_object.local_assault_turn))) { + return 0; + } + if (star_object.local_assault_turn[planet_number] != obj_controller.turn) { + return 0; + } + return star_object.local_assault_uses[planet_number]; +} + +/// @desc Spend one ground assault support use from this planet's local forces. +function local_assault_spend(star_object, planet_number) { + if (!instance_exists(star_object) || (planet_number < 0)) { + return; + } + if (!variable_instance_exists(star_object, "local_assault_uses")) { + star_object.local_assault_uses = []; + } + if (!variable_instance_exists(star_object, "local_assault_turn")) { + star_object.local_assault_turn = []; + } + while (array_length(star_object.local_assault_uses) <= planet_number) { + array_push(star_object.local_assault_uses, 0); + } + while (array_length(star_object.local_assault_turn) <= planet_number) { + array_push(star_object.local_assault_turn, -1); + } + if (star_object.local_assault_turn[planet_number] != obj_controller.turn) { + star_object.local_assault_turn[planet_number] = obj_controller.turn; + star_object.local_assault_uses[planet_number] = 0; + } + star_object.local_assault_uses[planet_number] += 1; +} + function new_player_ship_defaults() { with (obj_ini) { array_push(ship, ""); diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index c47893aa0f..933ce47668 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -364,6 +364,22 @@ function Roster() constructor { _ship_index = _ships[s]; if (obj_ini.ship_carrying[_ship_index] > 0) { new_ship_button(obj_ini.ship[_ship_index], _ship_index); + // Ship assault economy: a ship that has already supported its maximum + // ground assaults this turn stays listed but locked and red, so the + // player can see it is spent. The lock is enforced in + // scr_drop_select_function (clicks and Select All are forced back off), + // and update_roster only admits units whose ship toggle is active. + // Applies to attacks only; raids and purges do not spend uses. + if (instance_exists(obj_drop_select)) { + if (obj_drop_select.attack && (ship_assaults_used(_ship_index) >= SHIP_ASSAULTS_PER_TURN)) { + var _spent_btn = ships[array_length(ships) - 1]; + _spent_btn.assault_locked = true; + _spent_btn.active = false; + _spent_btn.text_color = c_red; + _spent_btn.button_color = c_red; + _spent_btn.tooltip = "This ship has already supported the maximum number of ground assaults this turn."; + } + } } } }; From 41bf628b48c26728c13f956d0899370d036e3a67 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 15:52:13 +0300 Subject: [PATCH 063/140] Eldar craftworld hunt: warhost incursions, intelligence clues, craftworld reveal Reactivates the dormant Eldar. The hidden craftworld, its garrison, and the full Eldar battle roster have always spawned; nothing ever raised p_eldar on normal worlds and the only discovery path was a 5% roll when parking a fleet within 300px of an invisible star. Now: every ELDAR_INCURSION_INTERVAL (15) turns a warhost strikes a random inhabited imperial world, with strength ELDAR_INCURSION_FORCE_BASE (3) plus one per intelligence clue collected, capped at ELDAR_INCURSION_FORCE_MAX (5), reserving max-tier Eldar for the craftworld (garrison 6). Each ground victory over Eldar while the craftworld is hidden grants one clue (popup with flavor and progress); at ELDAR_INTEL_REQUIRED (3) clues the craftworld is revealed. The reveal from battle context only flips known[ELDAR] and defers the map alert and fleet un-hiding to the next end-turn tick, since battle aftermath runs with map instances deactivated. The craftworld's escort fleet spawn is gated behind ELDAR_FLEET_ENABLED (0 for now) to avoid Eldar naval combat until fleet battles get attention. Intel counter is a guarded instance variable; no save-format changes. After this one's tested, natural follow-ups from the backlog and this design: the combat log armour-hit coloring that's still queued, or Phase 3 of the Eldar (the roaming craftworld using the existing old_x/old_y scaffolding).Eldar craftworld huntZIP --- objects/obj_controller/Alarm_1.gml | 21 +++-- objects/obj_ncombat/Alarm_5.gml | 7 ++ scripts/macros/macros.gml | 17 ++++ .../scr_controller_helpers.gml | 89 +++++++++++++++++++ 4 files changed, 126 insertions(+), 8 deletions(-) diff --git a/objects/obj_controller/Alarm_1.gml b/objects/obj_controller/Alarm_1.gml index ec35ac28aa..e7bf09349c 100644 --- a/objects/obj_controller/Alarm_1.gml +++ b/objects/obj_controller/Alarm_1.gml @@ -514,14 +514,19 @@ for (var i = 0; i < 100; i++) { go = 999; array_push(craft.p_feature[1], new NewPlanetFeature(eP_FEATURES.WARLORD6)); - var elforce = instance_create(xx, yy, obj_en_fleet); - elforce.sprite_index = spr_fleet_eldar; - elforce.owner = eFACTION.ELDAR; - elforce.capital_number = choose(2, 3); - elforce.frigate_number = choose(4, 5, 6); - elforce.escort_number = floor(random_range(7, 11)) + 1; - elforce.image_alpha = 0; - elforce.orbiting = craft; + // Eldar naval combat is currently miserable to play against, so the + // craftworld's escort fleet is disabled until fleet battles get attention. + // Flip ELDAR_FLEET_ENABLED in macros.gml to restore it. + if (ELDAR_FLEET_ENABLED) { + var elforce = instance_create(xx, yy, obj_en_fleet); + elforce.sprite_index = spr_fleet_eldar; + elforce.owner = eFACTION.ELDAR; + elforce.capital_number = choose(2, 3); + elforce.frigate_number = choose(4, 5, 6); + elforce.escort_number = floor(random_range(7, 11)) + 1; + elforce.image_alpha = 0; + elforce.orbiting = craft; + } } } // End craftworld diff --git a/objects/obj_ncombat/Alarm_5.gml b/objects/obj_ncombat/Alarm_5.gml index ef088b0a49..bb376c4d3f 100644 --- a/objects/obj_ncombat/Alarm_5.gml +++ b/objects/obj_ncombat/Alarm_5.gml @@ -460,6 +460,13 @@ if (defeat == 0 && _reduce_power) { part10 = "Necrons"; } + // Eldar craftworld hunt: a ground victory over an Eldar warhost yields one piece + // of intelligence toward locating the hidden craftworld. Only while it remains + // hidden; battles after the reveal grant nothing. + if ((enemy == eFACTION.ELDAR) && (obj_controller.known[eFACTION.ELDAR] == 0)) { + eldar_intel_grant(); + } + if (instance_exists(battle_object) && (enemy_power > 2)) { if (awake_tomb_world(battle_object.p_feature[battle_id]) != 0) { scr_gov_disp(battle_object.name, battle_id, floor(enemy_power / 2)); diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 1459011afc..a5443d4f5e 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -50,6 +50,23 @@ // and bombardment keep their old fleet-level rules. #macro SHIP_ASSAULTS_PER_TURN 2 +// Eldar craftworld hunt. The hidden craftworld and the full Eldar battle roster have +// always been in the game; what was missing is any way for Eldar to appear (nothing +// ever raised p_eldar on normal worlds) and any realistic way to find the craftworld +// (a 5% roll when parking a fleet within 300px of an invisible star). Now an Eldar +// warhost strikes an inhabited world every ELDAR_INCURSION_INTERVAL turns; each ground +// victory against them yields one piece of intelligence, and at ELDAR_INTEL_REQUIRED +// pieces the craftworld is revealed for invasion. Warhost strength starts at +// FORCE_BASE and ramps by one per clue collected up to FORCE_MAX, keeping max-tier +// Eldar for the craftworld itself (its garrison is 6). ELDAR_FLEET_ENABLED gates the +// craftworld's orbiting fleet, disabled for now so the reveal never forces Eldar +// naval combat; flip to 1 to restore it. +#macro ELDAR_INCURSION_INTERVAL 15 +#macro ELDAR_INCURSION_FORCE_BASE 3 +#macro ELDAR_INCURSION_FORCE_MAX 5 +#macro ELDAR_INTEL_REQUIRED 3 +#macro ELDAR_FLEET_ENABLED 0 + // Guard volley size: how many rank-and-file guardsmen share one firing stack in combat. The // regiment splits into capped stacks of this size instead of merging into one giant lasgun // volley, so each chunk fires and targets independently like an enemy obj_enunit block (those diff --git a/scripts/scr_controller_helpers/scr_controller_helpers.gml b/scripts/scr_controller_helpers/scr_controller_helpers.gml index d0e21fe3be..1b95b2d25e 100644 --- a/scripts/scr_controller_helpers/scr_controller_helpers.gml +++ b/scripts/scr_controller_helpers/scr_controller_helpers.gml @@ -460,6 +460,7 @@ function scr_end_turn() { audio_play_sound(snd_end_turn, -50, false); turn += 1; + eldar_incursion_tick(); with (obj_star) { for (var i = 0; i <= 21; i++) { present_fleet[i] = 0; @@ -516,3 +517,91 @@ function scr_end_turn() { } }); } + +/// @desc How many pieces of Eldar intelligence have been collected. Guarded read so +/// old saves and fresh campaigns start at zero without any save-format changes. +function eldar_intel_count() { + if (!variable_instance_exists(obj_controller, "eldar_intel")) { + return 0; + } + return obj_controller.eldar_intel; +} + +/// @desc Grant one piece of Eldar intelligence after a ground victory over a warhost. +/// At ELDAR_INTEL_REQUIRED pieces the craftworld is revealed. Called from the battle +/// aftermath (obj_ncombat\Alarm_5), where most map instances are deactivated, so the +/// reveal only flips obj_controller.known (the craftworld un-hides itself through its +/// own Draw check) and defers the map alert and fleet un-hiding to the next end-turn +/// tick via eldar_reveal_alert_pending. +function eldar_intel_grant() { + if (obj_controller.known[eFACTION.ELDAR] != 0) { + return; + } + if (!variable_instance_exists(obj_controller, "eldar_intel")) { + obj_controller.eldar_intel = 0; + } + obj_controller.eldar_intel += 1; + var _n = obj_controller.eldar_intel; + var _clue_texts = [ + "Among the alien dead your Apothecaries recover spirit stones that pulse in unison, all straining toward some distant point in the void. The Librarium begins triangulating.", + "A dying Warlock's staff yields a shard of wraithbone etched with webway routes. Cross-referenced with the spirit stones, the search narrows to a handful of sectors.", + "A captured wayseer's runes, broken under the Librarium's interrogation, complete the pattern. The hidden Craftworld's position is laid bare." + ]; + var _text = _clue_texts[min(_n, array_length(_clue_texts)) - 1]; + if (_n >= ELDAR_INTEL_REQUIRED) { + scr_popup("Eldar Intelligence", _text + $"\n\nIntelligence complete ({min(_n, ELDAR_INTEL_REQUIRED)}/{ELDAR_INTEL_REQUIRED}). The Eldar Craftworld has been located.", ""); + obj_controller.known[eFACTION.ELDAR] = 1; + obj_controller.eldar_reveal_alert_pending = true; + } else { + scr_popup("Eldar Intelligence", _text + $"\n\nIntelligence gathered: {_n}/{ELDAR_INTEL_REQUIRED}.", ""); + } +} + +/// @desc End-of-turn Eldar processing: fires the deferred craftworld reveal alert, +/// then every ELDAR_INCURSION_INTERVAL turns lands a warhost on a random inhabited +/// imperial world. Warhost strength ramps with collected intelligence +/// (FORCE_BASE + clues, capped at FORCE_MAX), keeping the strongest Eldar for the +/// craftworld itself. The planetary AI never acts on p_eldar (its pdf_attack line is +/// commented out upstream), so a landed warhost persists as a fightable target until +/// the player clears it. +function eldar_incursion_tick() { + if (variable_instance_exists(obj_controller, "eldar_reveal_alert_pending") && obj_controller.eldar_reveal_alert_pending) { + obj_controller.eldar_reveal_alert_pending = false; + with (obj_star) { + if (p_type[1] == "Craftworld") { + scr_alert("green", "elfs", "Eldar Craftworld discovered.", x, y); + } + } + with (obj_en_fleet) { + if (owner == eFACTION.ELDAR) { + image_alpha = 1; + } + } + } + if (obj_controller.faction_defeated[eFACTION.ELDAR] != 0) { + return; + } + if ((obj_controller.turn < ELDAR_INCURSION_INTERVAL) || ((obj_controller.turn % ELDAR_INCURSION_INTERVAL) != 0)) { + return; + } + var _force = min(ELDAR_INCURSION_FORCE_BASE + eldar_intel_count(), ELDAR_INCURSION_FORCE_MAX); + var _targets = []; + with (obj_star) { + if (craftworld || space_hulk) { + continue; + } + for (var i = 1; i <= planets; i++) { + if ((p_type[i] != "Dead") && (p_owner[i] >= 1) && (p_owner[i] <= 5) && (p_eldar[i] == 0)) { + array_push(_targets, [id, i]); + } + } + } + if (array_length(_targets) == 0) { + return; + } + var _pick = _targets[irandom(array_length(_targets) - 1)]; + var _star = _pick[0]; + var _planet = _pick[1]; + _star.p_eldar[_planet] = _force; + scr_alert("red", "elfs", $"An Eldar warhost has struck {_star.name} {scr_roman(_planet)}.", _star.x, _star.y); +} From 90d23325c2c699730aa4d944ef65cbb095d290ae Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 16:12:40 +0300 Subject: [PATCH 064/140] Eldar craftworld hunt: warhost incursions, intelligence clues, craftworld reveal Reactivates the dormant Eldar. The hidden craftworld, its garrison, and the full Eldar battle roster have always spawned; nothing ever raised p_eldar on normal worlds and the only discovery path was a 5% roll when parking a fleet within 300px of an invisible star. Now: every ELDAR_INCURSION_INTERVAL (15) turns a warhost strikes a random inhabited imperial world (red alert plus event log entry, matching native invasion presentation), with strength ELDAR_INCURSION_FORCE_BASE (3) plus one per intelligence clue collected, capped at ELDAR_INCURSION_FORCE_MAX (5), reserving max-tier Eldar for the craftworld (garrison 6). Each ground victory over Eldar while the craftworld is hidden grants one clue (popup with flavor and progress); at ELDAR_INTEL_REQUIRED (3) clues the craftworld is revealed. The reveal from battle context only flips known[ELDAR] and defers the map alert, event log entry, and fleet un-hiding to the next end-turn tick, since battle aftermath runs with map instances deactivated. The craftworld's escort fleet spawn is gated behind ELDAR_FLEET_ENABLED (0 for now) to avoid Eldar naval combat until fleet battles get attention. Intel counter is a guarded instance variable; no save-format changes. --- scripts/scr_controller_helpers/scr_controller_helpers.gml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/scr_controller_helpers/scr_controller_helpers.gml b/scripts/scr_controller_helpers/scr_controller_helpers.gml index 1b95b2d25e..b0267b4bbb 100644 --- a/scripts/scr_controller_helpers/scr_controller_helpers.gml +++ b/scripts/scr_controller_helpers/scr_controller_helpers.gml @@ -570,6 +570,7 @@ function eldar_incursion_tick() { with (obj_star) { if (p_type[1] == "Craftworld") { scr_alert("green", "elfs", "Eldar Craftworld discovered.", x, y); + scr_event_log("green", "Eldar Craftworld discovered."); } } with (obj_en_fleet) { @@ -604,4 +605,5 @@ function eldar_incursion_tick() { var _planet = _pick[1]; _star.p_eldar[_planet] = _force; scr_alert("red", "elfs", $"An Eldar warhost has struck {_star.name} {scr_roman(_planet)}.", _star.x, _star.y); + scr_event_log("red", $"An Eldar warhost has struck {_star.name} {scr_roman(_planet)}."); } From 1e63070f689b9882ec95c1ba2841eadaa493bc3b Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 16:22:33 +0300 Subject: [PATCH 065/140] Combat log: enemy fire held by armour now renders light blue Completes the armour-hit log coloring. Player-side lines were already done (bounces white, wounds-without-kills light green), but enemy fire stopped by the player's vehicle armour (damage severity < 0.10, the "Bouncing off the hull" chip tier) still rendered plain green at priority 0. Those lines now carry priority 135, which the existing Alarm_3 map draws as c_aqua, so wasted enemy volleys can be skimmed past. Gated to vehicle targets because non-severity-tracking targets (guardsmen) report severity 0 even when hits landed, and would otherwise be mislabeled as armour holds. Enemy-line palette is now: red losses, yellow damage without kills, light blue armour held, green otherwise. --- scripts/scr_flavor2/scr_flavor2.gml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index 098bc1b875..24e87dfb49 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -556,9 +556,15 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo if (string_length(mes) > 3) { // Yellow when the enemy hurt your forces but destroyed nothing (damage, no kill). Kills carry // the word "lost" and are coloured red elsewhere, so they are left at priority 0 here. + // Light blue (135 -> c_aqua) when your armour held: the chip tier against vehicles + // (severity < 0.10, "Bouncing off the hull" and friends), so wasted enemy fire can be + // skimmed past, mirroring the white player-side "cannot penetrate" lines. Vehicle-gated + // because non-tracking targets report severity 0 even when hits landed. var _enemy_priority = 0; if ((lost_units_count == 0) && (hostile_shots > 0) && (damage_severity >= 0.10)) { _enemy_priority = 136; + } else if ((lost_units_count == 0) && (hostile_shots > 0) && target_is_vehicle && (damage_severity < 0.10)) { + _enemy_priority = 135; } obj_ncombat.messages += 1; obj_ncombat.message[obj_ncombat.messages] = mes; From 4ca6e3cddb38fd9186e4f325b7863a1c412a01f7 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 16:41:49 +0300 Subject: [PATCH 066/140] Player column piercing: anti-infantry fire pays the same toll through armour walls Mirrors the enemy column piercing mechanic for the player, replacing an asymmetry: vanilla's player men look-behind fired the FULL volley at the first infantry block behind an enemy tank wall (a free 100% pass through armour), and silently wasted the entire volley when its 10px probe found no infantry. Against a men-less enemy front, the first infantry rank in range is now hit by PLAYER_PIERCE_RANK2_SHOTS (0.66) of the volley, the second by PLAYER_PIERCE_RANK3_SHOTS (0.33), and the stopped shots chip the armour wall (split across a second armour line when present) instead of vanishing. The probe is replaced with a deterministic collection sorted along the shooter-to-front axis, so main and flank enemy fronts both walk the correct direction, and the no-infantry-in-range case fires the full volley at the wall for visible feedback. scr_shoot's shot_override and consume_ammo now apply in the player branch; no aggregate scaling is needed there because player per-shot damage divides by wep_num rather than shots fired. Fronts with infantry, AP weapons, medi targeting, and melee are unchanged. --- objects/obj_pnunit/Alarm_0.gml | 115 +++++++++++++++++++++++++++++--- scripts/macros/macros.gml | 10 +++ scripts/scr_shoot/scr_shoot.gml | 9 ++- 3 files changed, 122 insertions(+), 12 deletions(-) diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index a0319f75d5..5785360fdd 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -192,21 +192,114 @@ try { good = 0; if (enemy.men + enemy.medi > 0) { - good = scr_target(enemy, "men"); // First target has vehicles, blow it to hell + good = scr_target(enemy, "men"); // First target has infantry, engage it scr_shoot(i, enemy, good, "att", "ranged"); } if ((good == 0) && (instance_number(obj_enunit) > 1)) { - // First target does not have vehicles, cycle through objects to find one that has vehicles - var x2 = enemy.x; - repeat (instance_number(obj_enunit) - 1) { - if (good == 0) { - x2 += 10; - var enemy2 = instance_nearest(x2, y, obj_enunit); - if ((enemy2.men > 0) && (good == 0)) { - good = scr_target(enemy2, "men"); // This target has vehicles, blow it to hell - scr_shoot(i, enemy2, good, "att", "ranged"); - once_only = 1; + // Column piercing (player side), mirroring the enemy mechanic. The + // front enemy block has no infantry (a tank wall). Vanilla walked a + // 10px instance_nearest probe and fired the FULL volley at the first + // men-bearing block found (a free 100% pass through armour), or + // silently wasted the whole volley when the probe found nothing. + // Instead: blocks beyond the front are collected along the + // shooter-to-front axis (so main and flank fronts both walk the right + // way), sorted nearest-first; the first infantry rank in range eats + // PLAYER_PIERCE_RANK2_SHOTS of the volley, the second + // PLAYER_PIERCE_RANK3_SHOTS, deeper ranks nothing, and the stopped + // shots chip the armour wall instead of vanishing. + var _front_x = enemy.x; + var _dir = sign(_front_x - x); + if (_dir == 0) { + _dir = 1; + } + var _beyond = []; + with (obj_enunit) { + if (id == other.enemy) { + continue; + } + if (((x - _front_x) * _dir) <= 0) { + continue; + } + array_push(_beyond, id); + } + if (_dir > 0) { + array_sort(_beyond, function(_a, _b) { + return _a.x - _b.x; + }); + } else { + array_sort(_beyond, function(_a, _b) { + return _b.x - _a.x; + }); + } + var _rank_blocks = []; + var _wall_blocks = []; + if (block_has_armour(enemy) > 0) { + array_push(_wall_blocks, enemy); + } + for (var b = 0; b < array_length(_beyond); b++) { + var enemy2 = _beyond[b]; + if (!target_block_is_valid(enemy2, obj_enunit)) { + continue; + } + if (range[i] < get_block_distance(enemy2)) { + break; + } + if (enemy2.men > 0) { + array_push(_rank_blocks, enemy2); + if (array_length(_rank_blocks) >= 2) { + break; } + } else if ((array_length(_rank_blocks) == 0) && (block_has_armour(enemy2) > 0)) { + // A second armour line between the shooter and the enemy + // infantry shares the stopped shots with the front wall. + array_push(_wall_blocks, enemy2); + } + } + if (array_length(_rank_blocks) > 0) { + var _total_shots = wep_num[i]; + var _rank2_shots = floor(_total_shots * PLAYER_PIERCE_RANK2_SHOTS); + var _rank3_shots = floor(_total_shots * PLAYER_PIERCE_RANK3_SHOTS); + var _front_shots = _total_shots - _rank2_shots; + var _ammo_spent = false; + var _rank_target = scr_target(_rank_blocks[0], "men"); + if ((_rank2_shots > 0) && (_rank_target != 0)) { + scr_shoot(i, _rank_blocks[0], _rank_target, "att", "ranged", _rank2_shots, !_ammo_spent); + _ammo_spent = true; + } + if ((array_length(_rank_blocks) > 1) && (_rank3_shots > 0)) { + _rank_target = scr_target(_rank_blocks[1], "men"); + if (_rank_target != 0) { + scr_shoot(i, _rank_blocks[1], _rank_target, "att", "ranged", _rank3_shots, !_ammo_spent); + _ammo_spent = true; + } + } + var _wall_count = array_length(_wall_blocks); + if ((_front_shots > 0) && (_wall_count > 0)) { + var _per_wall = floor(_front_shots / _wall_count); + var _extra = _front_shots - (_per_wall * _wall_count); + for (var w = 0; w < _wall_count; w++) { + var _w_shots = _per_wall + ((w == 0) ? _extra : 0); + if (_w_shots <= 0) { + continue; + } + var _w_target = scr_target(_wall_blocks[w], "veh"); + if (_w_target != 0) { + scr_shoot(i, _wall_blocks[w], _w_target, "att", "ranged", _w_shots, !_ammo_spent); + _ammo_spent = true; + } + } + } + if (_ammo_spent) { + once_only = 1; + } + } else if (block_has_armour(enemy) > 0) { + // No infantry in range beyond the wall: the whole volley chips + // the wall instead of vanishing silently (vanilla fired nothing + // at all here and the shots were simply lost). + var _w_target = scr_target(enemy, "veh"); + if (_w_target != 0) { + scr_shoot(i, enemy, _w_target, "att", "ranged"); + once_only = 1; } } } diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index a5443d4f5e..c521af115e 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -42,6 +42,16 @@ #macro ENEMY_PIERCE_RANK2_SHOTS 0.66 #macro ENEMY_PIERCE_RANK3_SHOTS 0.33 +// Player-side column piercing, mirroring the enemy mechanic. Vanilla player targeting +// gave anti-infantry weapons a 100% free pass through enemy tank walls (the men +// look-behind fired the full volley at the first infantry block behind, no shots lost), +// and silently wasted the volley entirely when no infantry was found. Now the wall +// costs the same toll in both directions: the first enemy infantry rank behind armour +// is hit by RANK2 of the shots, the second by RANK3, and the shots that fail to pass +// chip the wall instead of vanishing. +#macro PLAYER_PIERCE_RANK2_SHOTS 0.66 +#macro PLAYER_PIERCE_RANK3_SHOTS 0.33 + // Ship assault economy: how many ground assaults each ship can support per turn. The old // rule capped the whole fleet at 2 attacks per turn regardless of size, so deploying // everything on every assault cost nothing. Now each carrying ship supports this many diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index b5a6c4625c..a13d75f0f9 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -210,6 +210,13 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat if (weapon_index_position >= 0) { shots_fired = wep_num[weapon_index_position]; } + // Column piercing sub-volleys (player side). Unlike the enemy branch, no + // aggregate scaling is needed: player per-shot damage divides by wep_num + // (the full stack) rather than by shots fired, so a partial volley already + // deals a clean linear share of the stack's damage. + if (shot_override > -1) { + shots_fired = min(shot_override, shots_fired); + } if (shots_fired == 0) { exit; @@ -248,7 +255,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat if (ammo[weapon_index_position] == 0) { stop = 1; } - if (ammo[weapon_index_position] > 0) { + if (consume_ammo && (ammo[weapon_index_position] > 0)) { ammo[weapon_index_position] -= 1; } } From 285d91f96d680e0e3bd4a5b5b74b4b8fba1edee8 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 19:14:13 +0300 Subject: [PATCH 067/140] Priority 23: blocked fleet actions explain themselves, mission requirements clarified Blocked planet actions no longer fail silently. Raid (fleet spent 2+ actions), Purge (same), and Bombard (fleet already acted; vanilla created the bombard screen and destroyed it in the same frame) now pop a plain-language explanation of the action economy instead of a dead click. Attack was already covered by the ship assault economy warnings. The governor garrison request now states its real mechanics instead of "the garrison leader will need to be capable of conducting himself in a diplomatic manner": any squads qualify regardless of rank, the garrison's leader is the most senior squad leader among the garrisoned squads, the disposition outcome keys off that leader having the Honorable trait, and a separate wisdom test (siege specialists excel) can add fortifications. Also fixes the "leeader" typo. Active missions are marked: mission structs already track stage (preliminary/active), so the planet feature panel prepends ++MISSION IN PROGRESS++ to any initiated mission's description, confirming the assignment registered and the clock is running. --- objects/obj_star_select/Draw_64.gml | 9 +++++++++ .../scr_draw_planet_features.gml | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/objects/obj_star_select/Draw_64.gml b/objects/obj_star_select/Draw_64.gml index 33ca1d17c7..c13401a595 100644 --- a/objects/obj_star_select/Draw_64.gml +++ b/objects/obj_star_select/Draw_64.gml @@ -334,6 +334,10 @@ try { } else if (current_button == "Raid" && instance_nearest(x, y, obj_p_fleet).acted <= 1) { // feather ignore once GM2064 instance_create_layer(x, y, layer_get_all()[0], obj_drop_select, {p_target: target, planet_number: obj_controller.selecting_planet, sh_target: instance_nearest(x, y, obj_p_fleet), purge: 0}); + } else if (current_button == "Raid") { + // Blocked actions say why instead of silently doing nothing (players + // assumed the game broke when clicks had no effect). + scr_popup("Raid", "This fleet has already expended its actions this turn and cannot launch a raid. Raiding requires a fleet that has spent at most one action.", ""); } else if (current_button == "Attack") { var _allow_attack = true; var _targ = !target.present_fleet[1] ? noone : instance_nearest(x, y, obj_p_fleet); @@ -369,6 +373,8 @@ try { if (instance_exists(_targ)) { if (_targ.acted >= 2) { _allow_attack = false; + // Blocked actions say why instead of silently doing nothing. + scr_popup("Purge", "This fleet has already expended its actions this turn and cannot conduct a purge.", ""); } } if (_allow_attack) { @@ -385,6 +391,9 @@ try { with (obj_bomb_select) { instance_destroy(); } + // Vanilla created the bombard screen and instantly destroyed it, + // leaving the player with a dead click and no explanation. + scr_popup("Bombardment", "This fleet has already acted this turn. Orbital bombardment must be the fleet's first action of the turn.", ""); } } } else if (current_button == "Deploy Guard") { diff --git a/scripts/scr_draw_planet_features/scr_draw_planet_features.gml b/scripts/scr_draw_planet_features/scr_draw_planet_features.gml index 3a924566bf..fd2242ddcc 100644 --- a/scripts/scr_draw_planet_features/scr_draw_planet_features.gml +++ b/scripts/scr_draw_planet_features/scr_draw_planet_features.gml @@ -240,7 +240,14 @@ function FeatureSelected(_feature, _system, _planet) constructor { case "provide_garrison": var reason; if (feature.reason == "importance") {} - mission_description = $"The governor of {planet_name} has requested a force of marines might stay behind following your departure.\n\n\n assign a squad to garrison to initiate mission, The garrison leeader will need to be capable of conducting himself in a diplomatic manner in order for the garrison duration to be a success"; + // The requirement here used to be vague ("capable of conducting + // himself in a diplomatic manner"). The actual mechanics: the + // garrison's leader is the most senior squad leader among the + // garrisoned squads (rank does not gate the mission, it only + // decides who is tested); the disposition outcome keys off the + // leader having the Honorable trait, and a separate wisdom test + // (siege specialists excel) can add fortifications. + mission_description = $"The governor of {planet_name} has requested a force of marines might stay behind following your departure.\n\nAssign squads to Garrison Duty on this world to initiate the mission. Any squads qualify; the outcome rests on the garrison's leader, the most senior squad leader among those garrisoned. An Honorable leader will secure the diplomatic gains, while a leader lacking the trait risks incidents that sour relations. A wise leader (siege specialists excel) may also leave the world better fortified."; break; case "join_communion": @@ -284,6 +291,12 @@ function FeatureSelected(_feature, _system, _planet) constructor { draw_text_transformed(xx + (area_width / 2), yy + 5, mission_name_key(feature.problem), 2, 2, 0); draw_set_halign(fa_left); draw_set_color(c_gray); + // Initiated missions are clearly marked so the player knows the + // assignment registered and the clock is running (mission structs flip + // stage from "preliminary" to "active" in their init functions). + if (variable_struct_exists(feature, "stage") && (feature.stage == "active")) { + mission_description = "++MISSION IN PROGRESS++\n\n" + mission_description; + } draw_text_ext(xx + 10, yy + 40, mission_description, -1, area_width - 20); var text_body_height = string_height_ext(string_hash_to_newline(mission_description), -1, area_width - 20); if (help != "none") { From 43951fcff691cd388d6f0ce268ae84456d5c8a28 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 20:39:21 +0300 Subject: [PATCH 068/140] =?UTF-8?q?Decoded=20ownership=20mechanics:=20disp?= =?UTF-8?q?osition=20threshold=20and=20liberation=20timing=20determine=20w?= =?UTF-8?q?orld=20acquisitionDecoded=20ownership=20mechanics:=20dispositio?= =?UTF-8?q?n=20threshold=20and=20liberation=20timing=20determine=20world?= =?UTF-8?q?=20acquisitionThe=20full=20mechanism=20is=20now=20traced,=20and?= =?UTF-8?q?=20your=20player's=20detective=20work=20is=20impressively=20clo?= =?UTF-8?q?se.=20Here's=20a=20relay-ready=20answer:=20=20Worlds=20pledge?= =?UTF-8?q?=20to=20the=20chapter=20at=20exactly=20one=20moment:=20the=20in?= =?UTF-8?q?stant=20they're=20cleansed=20of=20an=20occupying=20enemy.=20Whe?= =?UTF-8?q?n=20the=20last=20xenos/heretic=20force=20on=20a=20planet=20is?= =?UTF-8?q?=20destroyed=20(by=20your=20ground=20assault,=20or=20by=20the?= =?UTF-8?q?=20planet's=20own=20resolution),=20the=20game=20returns=20the?= =?UTF-8?q?=20world=20to=20its=20original=20holder,=20and=20then=20two=20s?= =?UTF-8?q?pecial=20cases=20run.=20If=20the=20planet=20was=20yours=20first?= =?UTF-8?q?=20(p=5Ffirst,=20basically=20your=20home=20world=20or=20a=20wor?= =?UTF-8?q?ld=20you=20already=20flipped=20once),=20it=20returns=20to=20you?= =?UTF-8?q?.=20Otherwise=20it=20goes=20back=20to=20the=20Imperium=20or=20M?= =?UTF-8?q?echanicus,=20BUT=20the=20liberation=20grants=20+10=20dispositio?= =?UTF-8?q?n=20on=20the=20spot,=20and=20immediately=20after=20that=20bonus?= =?UTF-8?q?=20lands=20there's=20a=20check:=20disposition=20101=20or=20high?= =?UTF-8?q?er,=20the=20world=20pledges=20to=20the=20chapter=20instead.=20T?= =?UTF-8?q?he=20catch=20that=20makes=20this=20feel=20random:=20disposition?= =?UTF-8?q?=20is=20hard-clamped=20at=20100=20everywhere=20else=20in=20the?= =?UTF-8?q?=20game.=20You=20can=20never=20sit=20at=20101.=20The=20only=20w?= =?UTF-8?q?ay=20to=20cross=20the=20threshold=20is=20to=20be=20at=2091-100?= =?UTF-8?q?=20at=20the=20exact=20moment=20of=20liberation,=20so=20the=20+1?= =?UTF-8?q?0=20gratitude=20bonus=20momentarily=20spikes=20past=20101=20bef?= =?UTF-8?q?ore=20the=20clamp=20catches=20it.=20So,=20testing=20your=20gues?= =?UTF-8?q?ses:=20previous=20occupation=20being=20essential=20is=20CORRECT?= =?UTF-8?q?,=20the=20pledge=20check=20literally=20only=20exists=20inside?= =?UTF-8?q?=20the=20liberation=20event,=20and=20a=20peaceful=20world=20tha?= =?UTF-8?q?t=20loves=20you=20at=20100=20can=20never=20flip=20because=20the?= =?UTF-8?q?=20check=20never=20runs=20for=20it.=20Single-world=20systems=20?= =?UTF-8?q?being=20essential=20is=20WRONG,=20it's=20all=20per-planet,=20sy?= =?UTF-8?q?stem=20size=20is=20irrelevant.=20Purgatrex=20flipped=20because?= =?UTF-8?q?=20its=20disposition=20was=20already=2091+=20when=20you=20clean?= =?UTF-8?q?sed=20it.=20Your=20three-world=20ex-tyranid=20system=20stayed?= =?UTF-8?q?=20imperial=20because=20each=20planet's=20disposition=20was=20b?= =?UTF-8?q?elow=2091=20at=20the=20moment=20it=20was=20cleansed,=20and=20lo?= =?UTF-8?q?ve=20earned=20afterward=20doesn't=20matter,=20the=20check=20is?= =?UTF-8?q?=20a=20one-shot=20that=20already=20happened.=20The=20recipe,=20?= =?UTF-8?q?then:=20get=20the=20world=20to=2091+=20disposition=20FIRST=20(g?= =?UTF-8?q?arrisons,=20defending=20it,=20aid),=20and=20only=20then=20finis?= =?UTF-8?q?h=20off=20the=20occupiers.=20An=20unoccupied=20world=20can't=20?= =?UTF-8?q?be=20earned=20at=20all=20unless=20something=20invades=20it=20ag?= =?UTF-8?q?ain=20and=20hands=20you=20another=20liberation=20moment.=20Cons?= =?UTF-8?q?olation=20prize:=20worlds=20at=20disposition=20100=20already=20?= =?UTF-8?q?pay=20you=20tribute=20income=20without=20being=20yours,=20and?= =?UTF-8?q?=20if=20you=20ever=20declare=20war=20on=20the=20Imperium,=20dis?= =?UTF-8?q?po-100=20worlds=20are=20the=20ones=20you=20don't=20lose.=20=20T?= =?UTF-8?q?wo=20honest=20caveats=20for=20you=20rather=20than=20the=20playe?= =?UTF-8?q?r:=20the=2091+=20threshold=20is=20my=20derivation=20from=20the?= =?UTF-8?q?=20+10=20bonus=20against=20the=20101=20check,=20edge-exact=20va?= =?UTF-8?q?lues=20depend=20on=20whatever=20the=20disposition=20was=20pre-c?= =?UTF-8?q?lamp=20that=20frame,=20so=20"have=20it=20comfortably=20above=20?= =?UTF-8?q?90"=20is=20the=20safe=20phrasing.=20And=20this=20whole=20mechan?= =?UTF-8?q?ic=20is=20invisible=20in-game,=20which=20makes=20it=20a=20natur?= =?UTF-8?q?al=20Priority=2023=20candidate:=20a=20one-line=20hint=20on=20oc?= =?UTF-8?q?cupied=20worlds=20("The=20governor=20would=20pledge=20this=20wo?= =?UTF-8?q?rld=20to=20the=20Chapter=20if=20liberated=20now"=20when=20dispo?= =?UTF-8?q?=20is=20in=20range,=20or=20"loyalty=20is=20not=20yet=20sufficie?= =?UTF-8?q?nt"=20when=20below)=20would=20turn=20a=20hidden=20one-shot=20ch?= =?UTF-8?q?eck=20into=20an=20actual=20gameplay=20goal.=20Say=20the=20word?= =?UTF-8?q?=20and=20I'll=20build=20it=20as=20a=20small=20drop."I=20think?= =?UTF-8?q?=20this=20little=20system=20is=20currently=20very=20hard=20to?= =?UTF-8?q?=20actually=20make=20use=20of,=20since=20you=20can't=20garrison?= =?UTF-8?q?=20an=20enemy=20occupied=20world,=20so=20apart=20from=20tau=20w?= =?UTF-8?q?ho=20also=20use=20influence,=20what=20I=20did=20with=20purgatre?= =?UTF-8?q?x=20is=20the=20only=20possible=20way=20to=20get=20a=20world=20u?= =?UTF-8?q?sing=20it=20GAY=5FWEED=5FDAD=5F69=20=E2=80=94=207:25=20PM=20Yep?= =?UTF-8?q?,=20basically.=20It's=20really=20strange,=20almost=20like=20a?= =?UTF-8?q?=20bug,=20but=20a=20feature=20Basically=20the=20entire=20Imperi?= =?UTF-8?q?al=20admin=20is=20dead,=20you=20liberated=20the=20world=20and?= =?UTF-8?q?=20installed=20your=20puppets=20=20[BoJ],=20=20Tophat#7692=20[B?= =?UTF-8?q?oJ],=20=20=E2=80=94=207:25=20PM=20or=20if=20you're=20a=20bit=20?= =?UTF-8?q?deranged=20I=20guess=20you=20could=20specifically=20get=20a=20w?= =?UTF-8?q?orld=20to=20~95=20disposition=20and=20then=20let=20orks=20hit?= =?UTF-8?q?=20it=20and=20come=20in=20to=20save=20the=20day=20Tophat#7692?= =?UTF-8?q?=20[BoJ],=20=20=E2=80=94=207:26=20PM=20there's=20actually=20a?= =?UTF-8?q?=20system=20that=20might=20be=20about=20suited=20for=20this,=20?= =?UTF-8?q?though=20I've=20not=20tested=20it=20and=20can't=20say=20this=20?= =?UTF-8?q?isn't=20already=20how=20it=20works=20GAY=5FWEED=5FDAD=5F69=20?= =?UTF-8?q?=E2=80=94=207:26=20PM=20That's=20the=20type=20of=20politicking?= =?UTF-8?q?=20opportunism=20that=20i=20exactly=20love=20out=20of=20this=20?= =?UTF-8?q?game=20and=20would=20like=20as=20a=20feature=20Tophat#7692=20[B?= =?UTF-8?q?oJ],=20=20=E2=80=94=207:26=20PM=20one=20of=20your=20purge=20opt?= =?UTF-8?q?ions=20is=20to=20assassinate=20the=20governor,=20and=20that=20g?= =?UTF-8?q?ives=20you=20a=20range=20of=20options=20-=20the=20legitimate=20?= =?UTF-8?q?successor,=20a=20friendly=20successor,=20or=20a=20chapter=20ser?= =?UTF-8?q?f"Show=20moreAnalyzing=20assassination=20succession=20mechanics?= =?UTF-8?q?=20and=20disposition=20outcomesAnalyzing=20assassination=20succ?= =?UTF-8?q?ession=20mechanics=20and=20disposition=20outcomesTell=20Tophat?= =?UTF-8?q?=20his=20memory=20is=20exactly=20right,=20and=20better=20than?= =?UTF-8?q?=20he=20thinks:=20I=20traced=20the=20whole=20thing,=20and=20it'?= =?UTF-8?q?s=20not=20only=20"about=20suited=20for=20this,"=20it's=20alread?= =?UTF-8?q?y=20a=20fully=20wired=20annexation=20mechanic.=20Relay-ready:?= =?UTF-8?q?=20=20The=20assassinate-governor=20purge=20option=20exists=20an?= =?UTF-8?q?d=20works.=20All=20three=20successor=20choices=20are=20implemen?= =?UTF-8?q?ted=20(scr=5Fpopup=5Ffunctions=20=E2=86=92=20scr=5FPlanetData.a?= =?UTF-8?q?ssasinate=5Fgovernor),=20and=20they're=20mechanically=20very=20?= =?UTF-8?q?different:=20Legitimate=20successor:=20next=20in=20line=20takes?= =?UTF-8?q?=20over.=20Small=20dice=20drama=20(3%=20chance=20the=20heir=20h?= =?UTF-8?q?ates=20you=20and=20disposition=20craters,=205%=20chance=20you?= =?UTF-8?q?=20luck=20into=20a=20friendly=20one=20at=2060+),=20otherwise=20?= =?UTF-8?q?nothing=20changes.=20Notably,=20this=20path=20creates=20no=20di?= =?UTF-8?q?scovery=20event=20at=20all=20in=20code,=20killing=20a=20governo?= =?UTF-8?q?r=20and=20letting=20lawful=20succession=20run=20is=20consequenc?= =?UTF-8?q?e-free.=20Sympathetic=20successor:=20disposition=20jumps=20to?= =?UTF-8?q?=20roughly=2076-86=20("a=20powerful=20new=20ally=20may=20be=20i?= =?UTF-8?q?n=20the=20making").=2010%=20base=20discovery=20chance.=20Chapte?= =?UTF-8?q?r=20Serf:=20set=5Fnew=5Fowner(eFACTION.PLAYER),=20the=20world?= =?UTF-8?q?=20becomes=20yours=20outright,=20disposition=20set=20to=20101,?= =?UTF-8?q?=20no=20liberation=20dance,=20no=2091+=20threshold,=20no=20wait?= =?UTF-8?q?ing=20for=20orks.=20One=20hard=20exception:=20worlds=20original?= =?UTF-8?q?ly=20belonging=20to=20the=20Mechanicus=20(origional=5Fowner=20?= =?UTF-8?q?=3D=3D=203)=20keep=20their=20owner,=20you=20only=20get=20the=20?= =?UTF-8?q?disposition.=2025%=20base=20discovery=20chance.=20Discovery=20i?= =?UTF-8?q?s=20a=20delayed=20time=20bomb=20(handle=5Fdiscovered=5Fgovernor?= =?UTF-8?q?=5Fassasinations):=20if=20the=20roll=20catches=20you,=20an=20ev?= =?UTF-8?q?ent=20fires=20months=20later,=20oddly=20with=20asymmetric=20tim?= =?UTF-8?q?ing,=20a=20serf=20installation=20surfaces=20within=20about=203-?= =?UTF-8?q?15=20months=20while=20a=20sympathetic=20one=20can=20take=20year?= =?UTF-8?q?s.=20When=20it=20lands:=20imperial=20worlds=20across=20the=20se?= =?UTF-8?q?ctor=20lose=20disposition,=20faction=20hits=20land=20(sympathet?= =?UTF-8?q?ic=20discovery=20is=20strangely=20the=20harsher=20one:=20Imperi?= =?UTF-8?q?um=20-7,=20Inquisition=20-10,=20Ecclesiarchy=20-5,=20versus=20j?= =?UTF-8?q?ust=20Inquisition=20-3=20for=20the=20serf),=20and=20you=20get?= =?UTF-8?q?=20hauled=20into=20an=20angry=20audience=20with=20the=20sector?= =?UTF-8?q?=20commander,=20or=20worse=20if=20your=20Imperium/Inquisition?= =?UTF-8?q?=20standing=20is=20already=20at=20zero.=20So=20the=20opportunis?= =?UTF-8?q?t's=20toolkit=20is:=20worlds=20occupied=20by=20xenos=20?= =?UTF-8?q?=E2=86=92=20garrison-adjacent=20worlds=20to=2091+=20and=20liber?= =?UTF-8?q?ate=20for=20the=20pledge;=20peaceful=20worlds=20you=20covet=20?= =?UTF-8?q?=E2=86=92=20purge,=20assassinate,=20install=20a=20serf,=20and?= =?UTF-8?q?=20pray=20the=20Inquisition's=20roll=20goes=20your=20way.=20You?= =?UTF-8?q?r=20"let=20the=20orks=20hit=20it=20and=20save=20the=20day"=20ga?= =?UTF-8?q?mbit=20also=20genuinely=20works=20within=20the=20pledge=20rules?= =?UTF-8?q?,=20for=20the=20record.=20=20Two=20design=20observations=20for?= =?UTF-8?q?=20you=20rather=20than=20the=20chat,=20since=20you=20said=20thi?= =?UTF-8?q?s=20is=20the=20politicking=20you=20want=20more=20of=20as=20a=20?= =?UTF-8?q?feature:=20first,=20the=20discovery-penalty=20asymmetry=20(inst?= =?UTF-8?q?alling=20a=20sympathizer=20punished=20harder=20than=20seizing?= =?UTF-8?q?=20the=20planet=20outright=20with=20a=20serf)=20reads=20like=20?= =?UTF-8?q?a=20bug=20or=20at=20least=20an=20unbalanced=20leftover,=20worth?= =?UTF-8?q?=20flagging=20to=20Tavish=20since=20it's=20upstream=20code.=20S?= =?UTF-8?q?econd,=20the=20legitimate-successor=20option=20having=20zero=20?= =?UTF-8?q?discovery=20risk=20makes=20it=20strictly=20free,=20which=20is?= =?UTF-8?q?=20either=20intentional=20(it's=20also=20nearly=20rewardless)?= =?UTF-8?q?=20or=20an=20oversight.=20If=20you=20want,=20I=20can=20do=20a?= =?UTF-8?q?=20balance-and-clarity=20pass=20on=20this=20system=20as=20its?= =?UTF-8?q?=20own=20drop:=20surface=20the=20risks=20and=20rewards=20in=20t?= =?UTF-8?q?he=20option=20tooltips=20Priority-23=20style,=20and=20optionall?= =?UTF-8?q?y=20rebalance=20the=20discovery=20table.=20But=20it=20works=20t?= =?UTF-8?q?oday,=20and=20nothing=20needs=20fixing=20for=20your=20player=20?= =?UTF-8?q?to=20start=20scheming.I=20guess=20the=20only=20option=20i=20see?= =?UTF-8?q?=20is=20the=20ability=20to=20MOUSE=20over=20all=20of=20the=20op?= =?UTF-8?q?tions=20(like=20assasinating=20the=20Governor/Bombard/Purge=20e?= =?UTF-8?q?tc.)=20so=20they=20tell=20you=20what=20they=20do=20in=20short?= =?UTF-8?q?=20tooltips.=20Can=20you=20do=20that=3FLeveraged=20existing=20t?= =?UTF-8?q?ooltip=20infrastructure=20and=20identified=20button=20valuesLev?= =?UTF-8?q?eraged=20existing=20tooltip=20infrastructure=20and=20identified?= =?UTF-8?q?=20button=20valuesdraw=5Fshutter=20already=20renders=20a=20tool?= =?UTF-8?q?tip=20on=20hover;=20nothing=20ever=20sets=20one.=20So=20the=20p?= =?UTF-8?q?lumbing=20exists=20and=20this=20is=20purely=20wiring.=20Enumera?= =?UTF-8?q?ting=20every=20button=20value=20and=20checking=20the=20purge/su?= =?UTF-8?q?ccessor=20surfaces:Identified=20existing=20hover=20callback=20s?= =?UTF-8?q?ystem=20for=20tooltip=20implementationIdentified=20existing=20h?= =?UTF-8?q?over=20callback=20system=20for=20tooltip=20implementationEnumer?= =?UTF-8?q?ate=20buttons,=20find=20purge=20type=20UI=20and=20successor=20o?= =?UTF-8?q?ptionsScriptRead=20the=20purge=20type=20buttons=20and=20success?= =?UTF-8?q?or=20option=20creationScriptI=20need=20to=20trace=20where=20the?= =?UTF-8?q?=20purge=20type=20selection=20happens=E2=80=94whether=20it's=20?= =?UTF-8?q?a=20popup=20menu=20triggered=20by=20clicking=20Purge,=20or=20if?= =?UTF-8?q?=20the=20four=20options=20(bombard,=20fire=20cleansing,=20selec?= =?UTF-8?q?tive,=20assassinate)=20are=20displayed=20elsewhere.=20I=20shoul?= =?UTF-8?q?d=20search=20for=20where=20those=20purge=20type=20buttons=20are?= =?UTF-8?q?=20drawn=20or=20where=20the=20selection=20menu=20gets=20created?= =?UTF-8?q?,=20then=20find=20how=20the=20assassination=20result=20popup=20?= =?UTF-8?q?builds=20its=20options.Find=20the=20purge=20type=20picker=20and?= =?UTF-8?q?=20successor=20option=20creation=20siteScriptRead=20successor?= =?UTF-8?q?=20options,=20popup=20tooltip=20support,=20purge=20type=20picke?= =?UTF-8?q?rScriptI=20need=20to=20track=20down=20where=20the=20popup=20opt?= =?UTF-8?q?ions=20are=20being=20rendered=20since=20Draw=5F64=20doesn't=20h?= =?UTF-8?q?ave=20the=20tooltip=20matches.=20I'm=20searching=20through=20th?= =?UTF-8?q?e=20obj=5Fpopup=20files=20to=20find=20where=20the=20option=20bu?= =?UTF-8?q?ttons=20get=20drawn,=20and=20I=20also=20need=20to=20figure=20ou?= =?UTF-8?q?t=20how=20the=20purge=20type=20picker=20works=E2=80=94whether?= =?UTF-8?q?=20it's=20handled=20in=20the=20dropdown=20select=20function=20o?= =?UTF-8?q?r=20if=20the=20Purge=20button=20directly=20creates=20the=20obj?= =?UTF-8?q?=5Fdrop=5Fselect=20object.Find=20purge=20type=20selection=20flo?= =?UTF-8?q?w=20and=20popup=20option=20drawingScriptRead=20popup=20option?= =?UTF-8?q?=20drawing=20for=20tooltip=20capability=20and=20purge=20type=20?= =?UTF-8?q?menuScriptRead=20option=20hover=20region=20and=20the=20purge=20?= =?UTF-8?q?type=20chooser=20at=20purge=201ScriptI=20just=20realized=20the?= =?UTF-8?q?=20popup=20options=20already=20have=20built-in=20support=20for?= =?UTF-8?q?=20a=20per-option=20hover=20callback,=20so=20I=20can=20leverage?= =?UTF-8?q?=20that=20to=20add=20tooltips=20by=20attaching=20a=20hover=20fu?= =?UTF-8?q?nction=20to=20each=20option=20struct=20that=20triggers=20the=20?= =?UTF-8?q?tooltip=20drawing.=20Now=20I=20need=20to=20figure=20out=20the?= =?UTF-8?q?=20purge=20type=20selection=E2=80=94purge=20=3D=3D=201=20is=20t?= =?UTF-8?q?he=20setup=20screen=20where=20ship=20allocation=20happens,=20an?= =?UTF-8?q?d=20the=20four=20purge=20types=20get=20selected=20somewhere=20i?= =?UTF-8?q?n=20that=20interface.Find=20the=20purge=20type=20buttonsScriptH?= =?UTF-8?q?unt=20the=20purge=20type=20transitionScriptRead=20PurgeButton?= =?UTF-8?q?=20class=20and=20its=20draw=20for=20tooltip=20capabilityScriptD?= =?UTF-8?q?onelast=5Fmessages.loglog3-7-2026-104236=5Ferror.log28=20linesl?= =?UTF-8?q?ogFor=20now=20i=20need=20to=20fix=20this=20error.Devised=20stra?= =?UTF-8?q?tegy=20to=20refactor=20code=20through=20variable=20extractionDe?= =?UTF-8?q?vised=20strategy=20to=20refactor=20code=20through=20variable=20?= =?UTF-8?q?extractionSingle-file=20drop:=20scripts\scr=5Fpurge=5Fworld\scr?= =?UTF-8?q?=5Fpurge=5Fworld.gml,=20built=20fresh=20on=20your=20Priority=20?= =?UTF-8?q?23=20commit=20(285d91f),=20balance-checked.=20The=20crash:=20yo?= =?UTF-8?q?ur=20Feather=20Serpents=20ran=20a=20Fire=20Cleansing=20or=20Sel?= =?UTF-8?q?ective=20Purge=20on=20a=20world=20hiding=20a=20concealed=20Chao?= =?UTF-8?q?s=20warlord=20(the=20WARLORD10=20planet=20feature)=20while=20Ch?= =?UTF-8?q?aos=20was=20still=20unknown=20to=20you.=20That's=20the=20"Conce?= =?UTF-8?q?aled=20Heresy"=20ambush=20event,=20and=20its=20popup=20text=20b?= =?UTF-8?q?uilds=20inside=20a=20with=20(obj=5Fdrop=5Fselect)=20block,=20wh?= =?UTF-8?q?ich=20switches=20self=20to=20the=20drop-select=20screen.=20The?= =?UTF-8?q?=20text=20then=20interpolates=20{name()},=20and=20inside=20that?= =?UTF-8?q?=20with,=20name()=20resolves=20against=20obj=5Fdrop=5Fselect,?= =?UTF-8?q?=20which=20has=20no=20such=20thing:=20instant=20caught=20error,?= =?UTF-8?q?=20blank=20popup,=20ambush=20narrative=20eaten.=20It=20has=20al?= =?UTF-8?q?most=20certainly=20never=20worked;=20the=20fix=20captures=20the?= =?UTF-8?q?=20planet=20name=20in=20PlanetData=20scope=20before=20entering?= =?UTF-8?q?=20the=20with=20and=20interpolates=20the=20local.=20The=20audit?= =?UTF-8?q?=20also=20turned=20up=20three=20quiet=20siblings=20in=20the=20s?= =?UTF-8?q?ame=20file,=20all=20now=20fixed:=20the=20mutant-purge=20Inquisi?= =?UTF-8?q?tion=20mission=20text=20and=20event=20log,=20and=20the=20noble-?= =?UTF-8?q?purge=20event=20log,=20all=20had=20{name()}=20in=20strings=20mi?= =?UTF-8?q?ssing=20the=20$=20template=20prefix,=20so=20instead=20of=20cras?= =?UTF-8?q?hing=20they've=20been=20showing=20players=20the=20literal=20tex?= =?UTF-8?q?t=20"{name()}"=20in=20popups=20and=20the=20event=20log=20this?= =?UTF-8?q?=20whole=20time.=20Worth=20knowing=20about=20the=20event=20itse?= =?UTF-8?q?lf=20now=20that=20it=20works:=20the=20known-Chaos=20variant=20o?= =?UTF-8?q?f=20the=20same=20trigger=20(known[10]=20>=3D=202)=20throws=20yo?= =?UTF-8?q?u=20straight=20into=20a=20battle,=20so=20with=20this=20fix=20th?= =?UTF-8?q?e=20unknown-Chaos=20variant=20properly=20delivers=20its=20ambus?= =?UTF-8?q?h=20popup=20instead=20of=20a=20caught=20error.=20Your=20save=20?= =?UTF-8?q?should=20be=20fine,=20the=20error=20was=20caught=20and=20nothin?= =?UTF-8?q?g=20corrupted;=20re-running=20a=20purge=20on=20that=20same=20wo?= =?UTF-8?q?rld=20will=20now=20show=20the=20event=20properly.=20Test:=20pur?= =?UTF-8?q?ge=20that=20same=20world=20again=20(fire=20or=20selective)=20an?= =?UTF-8?q?d=20confirm=20the=20Concealed=20Heresy=20popup=20appears=20with?= =?UTF-8?q?=20the=20planet=20named=20in=20the=20text.=20If=20you=20can=20t?= =?UTF-8?q?rigger=20the=20Inquisition=20mutant-purge=20or=20noble-purge=20?= =?UTF-8?q?missions,=20confirm=20their=20texts=20name=20the=20planet=20ins?= =?UTF-8?q?tead=20of=20showing=20"{name()}".=20Commit=20title:=20Fix=20Con?= =?UTF-8?q?cealed=20Heresy=20purge=20crash:=20name()=20interpolated=20insi?= =?UTF-8?q?de=20wrong=20scope?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purging (fire or selective) a world hiding a concealed Chaos warlord (WARLORD10, Chaos unknown) crashed with "Variable obj_drop_select.name not set": the Concealed Heresy popup text interpolates {name()} inside a with (obj_drop_select) block, where self is the drop-select instance and name() does not exist, so the ambush event has never displayed. The planet name is now captured in PlanetData scope before the with block. The audit also found three strings in the same file with {name()} but no $ template prefix (mutant-purge popup and event log, noble-purge event log), which printed the literal text "{name()}" to players; prefixes added. --- scripts/scr_purge_world/scr_purge_world.gml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/scr_purge_world/scr_purge_world.gml b/scripts/scr_purge_world/scr_purge_world.gml index 5e4d979d0a..098684dd2c 100644 --- a/scripts/scr_purge_world/scr_purge_world.gml +++ b/scripts/scr_purge_world/scr_purge_world.gml @@ -163,11 +163,16 @@ function scr_purge_world(action_type, action_score) { var _no_chaos = (planet_forces[eFACTION.HERETICS] + planet_forces[eFACTION.CHAOS]) == 0; if ((action_type == eDROP_TYPE.PURGEFIRE || action_type == eDROP_TYPE.PURGESELECTIVE) && _no_chaos && obj_controller.turn >= obj_controller.chaos_turn) { if (has_feature(eP_FEATURES.WARLORD10) && obj_controller.known[10] == 0 && obj_controller.faction_gender[10] == 1) { + // {name()} was being interpolated inside with (obj_drop_select), where self + // is the drop-select instance and name() does not exist: a caught error and + // a blank popup every time a purge uncovered a concealed Chaos warlord. + // Capture the planet name in PlanetData scope before entering the with. + var _planet_name = name(); with (obj_drop_select) { var pop = instance_create(0, 0, obj_popup); pop.image = "chaos_symbol"; pop.title = "Concealed Heresy"; - pop.text = $"Your astartes set out and begin to cleanse {name()} of possible heresy. The general populace appears to be devout in their faith, but a disturbing trend appears- the odd citizen cursing your forces, frothing at the mouth, and screaming out heresy most foul. One week into the cleansing a large hostile force is detected approaching and encircling your forces."; + pop.text = $"Your astartes set out and begin to cleanse {_planet_name} of possible heresy. The general populace appears to be devout in their faith, but a disturbing trend appears- the odd citizen cursing your forces, frothing at the mouth, and screaming out heresy most foul. One week into the cleansing a large hostile force is detected approaching and encircling your forces."; exit; } } @@ -229,8 +234,8 @@ function scr_purge_world(action_type, action_score) { alter_disposition(eFACTION.INQUISITION, obj_controller.demanding ? choose(0, 0, 1) : 1); - _popup_text = "Your marines scour the underhive of {name()}, spraying mutants down with promethium as they go. It takes several days but a sizeable dent is put in their numbers."; - scr_event_log("", "Inquisition Mission Completed: The mutants of {name()} have been cleansed by promethium."); + _popup_text = $"Your marines scour the underhive of {name()}, spraying mutants down with promethium as they go. It takes several days but a sizeable dent is put in their numbers."; + scr_event_log("", $"Inquisition Mission Completed: The mutants of {name()} have been cleansed by promethium."); add_disposition(choose(1, 2, 3)); } } else { @@ -270,7 +275,7 @@ function scr_purge_world(action_type, action_score) { alter_disposition(eFACTION.INQUISITION, obj_controller.demanding ? choose(0, 0, 1) : 1); _popup_text = "Your marines drop fast and hard, blowing through guards and mercenaries with minimal resistance. Before ten minutes have passed all your targets are executed."; - scr_event_log("", "Inquisition Mission Completed: The unruly Nobles of {name()} have been purged."); + scr_event_log("", $"Inquisition Mission Completed: The unruly Nobles of {name()} have been purged."); add_disposition(choose(1, 2, 3)); } } else if (_isquest == 0) { From e105fb86c7128ebbb4fd6474e6a412a2fa4720ea Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 20:56:57 +0300 Subject: [PATCH 069/140] Hover tooltips for planet actions, purge types, and governor succession choices Every planet action now explains itself on hover. The shutter buttons (Attack, Raid, Bombard, Purge, Cyclonic Torpedo, Deploy Guard, +Recruiting, Build/Base/Arsenal/Gene-Vault) get short mechanical tooltips via a new planet_action_tooltip lookup; ShutterButton has always rendered its tooltip field on hover but nothing ever set one. PurgeButton had authored descriptions for all four purge types sitting in a description field that draw() never rendered (verbatim upstream, so these texts have never been shown to any player); the class now draws them as hover tooltips, with inactive buttons explaining why they are unavailable, and the assassinate option's one-liner expanded to state the succession mechanics and Inquisition discovery risk. The governor succession popup's three choices use the popup option system's existing per-option hover hook to explain their outcomes: lawful heir (no discovery risk), sympathetic successor (ally disposition, small delayed discovery risk), Chapter Serf (world joins the chapter except Mechanicus-first worlds, highest discovery risk). --- objects/obj_drop_select/Create_0.gml | 2 +- objects/obj_star_select/Draw_64.gml | 6 +++++ scripts/scr_DataSlate/scr_DataSlate.gml | 30 +++++++++++++++++++++++ scripts/scr_PlanetData/scr_PlanetData.gml | 9 +++++++ scripts/scr_roster/scr_roster.gml | 9 +++++++ 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/objects/obj_drop_select/Create_0.gml b/objects/obj_drop_select/Create_0.gml index 9d5ba32067..b89fa4bcd4 100644 --- a/objects/obj_drop_select/Create_0.gml +++ b/objects/obj_drop_select/Create_0.gml @@ -322,7 +322,7 @@ if (purge == 0) { assasinate_purge = new PurgeButton(7, 631, 450, eDROP_TYPE.PURGEASSASSINATE); assasinate_purge.active = _viable_ground_forces; - assasinate_purge.description = "Often the simplest solution is a single bolt shell or the swift knife the heart. Kill the Leader."; + assasinate_purge.description = "Often the simplest solution is a single bolt shell or the swift knife to the heart. Kill the Planetary Governor, then choose the succession: the lawful heir, a governor sympathetic to your chapter, or a Chapter Serf who places the world under your control. Manipulating the succession carries a risk of Inquisition discovery, with consequences that may surface months or years later."; purge_options = [ bombard_purge, diff --git a/objects/obj_star_select/Draw_64.gml b/objects/obj_star_select/Draw_64.gml index c13401a595..2859e821eb 100644 --- a/objects/obj_star_select/Draw_64.gml +++ b/objects/obj_star_select/Draw_64.gml @@ -301,6 +301,12 @@ try { var shutter_x = main_data_slate.XX - 165; var shutter_y = 296 + 165; if (!debug) { + // Every planet action explains itself on hover (the shutter class has + // always rendered tooltips; they were simply never set). + shutter_1.tooltip = planet_action_tooltip(button1); + shutter_2.tooltip = planet_action_tooltip(button2); + shutter_3.tooltip = planet_action_tooltip(button3); + shutter_4.tooltip = planet_action_tooltip(button4); if (shutter_1.draw_shutter(shutter_x, shutter_y, button1, 0.5, true)) { current_button = button1; } diff --git a/scripts/scr_DataSlate/scr_DataSlate.gml b/scripts/scr_DataSlate/scr_DataSlate.gml index 4b94a6a912..ad47be75ea 100644 --- a/scripts/scr_DataSlate/scr_DataSlate.gml +++ b/scripts/scr_DataSlate/scr_DataSlate.gml @@ -543,3 +543,33 @@ function ShutterButton() constructor { } }; } + +/// @desc Short hover tooltip for the planet action shutter buttons (obj_star_select). +/// ShutterButton.draw_shutter has always rendered its tooltip field on hover; nothing +/// ever set one. Unknown actions return "" (no tooltip), so new buttons are safe. +function planet_action_tooltip(_action) { + switch (_action) { + case "Attack": + return "Launch a ground assault to destroy enemy forces on this world. Each ship carrying troops can support up to 2 assaults per turn; planetside forces fight without ship support."; + case "Raid": + return "A limited strike that chips away at enemy forces without committing to a full battle. Requires a fleet that has spent at most one action this turn."; + case "Bombard": + return "Orbital bombardment: devastating to enemy forces, the population, and the world itself. Must be the fleet's first action of the turn."; + case "Purge": + return "Cleanse this world's population of heresy and xenos taint. Opens a choice of methods, from orbital purging to assassinating the Planetary Governor. Ends the fleet's actions for the turn."; + case "Cyclonic Torpedo": + return "Exterminatus. Destroys the planet and everything on it, permanently. There is no taking this back."; + case "Deploy Guard": + return "Land every Guardsman aboard your orbiting ships onto this world. They join its local forces and can fight in battles here without ship support."; + case "+Recruiting": + return "Designate this world as a recruiting world, letting your chapter draw aspirants from its population. Requires an available recruiting-world right and a world not at war."; + case "Build": + return "Begin construction of a chapter facility on this world."; + case "Base": + case "Arsenal": + case "Gene-Vault": + return "Manage your chapter facilities on this world."; + default: + return ""; + } +} diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index f0fe5bc345..847144ec01 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -486,14 +486,23 @@ function PlanetData(_planet, _system) constructor { { str1: "Allow the official successor to become Planetary Governor.", choice_func: allow_governor_successor, + hover: function() { + tooltip_draw("The lawful heir takes power. Relations usually carry over unchanged, with a small chance the new governor arrives loving or loathing your chapter. No risk of discovery."); + }, }, { str1: "Ensure that a sympathetic successor will be the one to rule.", choice_func: install_sympathetic_successor, + hover: function() { + tooltip_draw("A governor friendly to your chapter is quietly maneuvered into power. Disposition rises to a strong ally's. Small risk of Inquisition discovery, and discovered manipulation angers the Imperium, Inquisition, and Ecclesiarchy, sometimes years later."); + }, }, { str1: "Remove all successors and install a loyal Chapter Serf.", choice_func: install_chapter_surf, + hover: function() { + tooltip_draw("The line of succession is erased and your serf takes the throne: the world comes under your chapter's direct control with maximum disposition (worlds originally of the Mechanicus keep their owner). The boldest option and the likeliest to be discovered by the Inquisition."); + }, }, ]; pip.add_option(options); diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 933ce47668..475dbf5a38 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -493,6 +493,15 @@ function PurgeButton(purge_image, xx, yy, purge_type) constructor { shader_set_uniform_f(shader_get_uniform(light_dark_shader, "highlight"), bright_shader); scr_image("purge", purge_image, x1, y1, width, height); shader_reset(); + // The description field existed but was never rendered. Drawn after the + // shader resets so the tooltip is not tinted; inactive buttons explain why. + if ((description != "") && hover()) { + var _tip = description; + if (!active) { + _tip += "\n\nYour selected force cannot perform this purge."; + } + tooltip_draw(_tip); + } }; static clicked = function() { From ca4c9bf972e742452b07c167f58dd9d9cee1bf58 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 21:33:06 +0300 Subject: [PATCH 070/140] Fix Test-Slave Incubator batches wiped silently after every battle obj_ncombat\Alarm_5 ended battle resolution with an unconditional obj_ini.gene_slaves = [];, deleting every maturing Test-Slave Incubator batch after EVERY battle: the gene-seed inside the batches and the Gene Pod Incubator items consumed to start them were destroyed with no recovery, no event, and no log entry. It presented as gene-seed randomly disappearing between saves because batches only survived while the player avoided fighting. The legitimate wipe (homeworld falling with no underground gene vaults) is already handled above via destroy_all_gene_slaves(false) inside its proper guard, so the line is removed with an explanatory comment. Present verbatim in upstream main (Alarm_5:944); reported by two players. --- objects/obj_ncombat/Alarm_5.gml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/objects/obj_ncombat/Alarm_5.gml b/objects/obj_ncombat/Alarm_5.gml index bb376c4d3f..ad5b5ed2cd 100644 --- a/objects/obj_ncombat/Alarm_5.gml +++ b/objects/obj_ncombat/Alarm_5.gml @@ -976,7 +976,13 @@ if (defeat == 1) { } } -obj_ini.gene_slaves = []; +// The line "obj_ini.gene_slaves = [];" was removed here. It ran unconditionally at +// the end of EVERY battle resolution, silently deleting all Test-Slave Incubator +// batches raw (no gene-seed recovery, no incubator item refund, no event) any time +// the player fought anything while batches were maturing. The legitimate wipe (the +// homeworld falling with no underground gene vaults) is already handled above via +// destroy_all_gene_slaves(false) inside its proper guard. Present verbatim in +// upstream main (objects\obj_ncombat\Alarm_5.gml). instance_deactivate_object(obj_star); instance_deactivate_object(obj_ground_mission); From 2c2991275b14ded7421f471e308c83d229bd1175 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 21:42:54 +0300 Subject: [PATCH 071/140] Eldar phase 2: warhosts visible on planets, small craftworld fleet, saner ship speed Three changes. First, a display bug fix: the planet screen's Planetary Presence section iterates a hardcoded faction array that never included Eldar, so incursion warhosts landed (attackable, bombardable) but were invisible on the planet panel, reported as "no eldar force on the ground". Eldar added to the presence arrays. Second, the craftworld's escort fleet is re-enabled (ELDAR_FLEET_ENABLED 1) at reduced size: 1 capital, 1-2 frigates, 2-4 escorts, versus vanilla's 2-3/4-6/8-11, so the craftworld reveal leads to a modest naval fight rather than a fleet wall; applies to new campaigns. Third, Eldar naval speed: vanilla Eldar ships run spid 60-100 while every other faction runs 20-45, which is the mechanical cause of the infamous endless chase loops. A new ELDAR_SHIP_SPEED_MULT macro (0.65) scales the whole Eldar class table (Void Stalker 39, Shadow 52, Hellebore/Aconite 65), keeping them the fastest ships in the game but catchable; 1.0 restores vanilla. --- objects/obj_controller/Alarm_1.gml | 13 +++++++------ objects/obj_en_ship/Step_0.gml | 5 +++++ scripts/macros/macros.gml | 9 ++++++++- scripts/scr_PlanetData/scr_PlanetData.gml | 2 ++ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/objects/obj_controller/Alarm_1.gml b/objects/obj_controller/Alarm_1.gml index e7bf09349c..a212b4e748 100644 --- a/objects/obj_controller/Alarm_1.gml +++ b/objects/obj_controller/Alarm_1.gml @@ -514,16 +514,17 @@ for (var i = 0; i < 100; i++) { go = 999; array_push(craft.p_feature[1], new NewPlanetFeature(eP_FEATURES.WARLORD6)); - // Eldar naval combat is currently miserable to play against, so the - // craftworld's escort fleet is disabled until fleet battles get attention. - // Flip ELDAR_FLEET_ENABLED in macros.gml to restore it. + // Eldar naval combat is rough to play against, so the escort fleet is kept + // small (vanilla spawned 2-3 capitals, 4-6 frigates, 8-11 escorts) and Eldar + // ship speed is toned down via ELDAR_SHIP_SPEED_MULT. Set ELDAR_FLEET_ENABLED + // to 0 in macros.gml to remove the fleet entirely. if (ELDAR_FLEET_ENABLED) { var elforce = instance_create(xx, yy, obj_en_fleet); elforce.sprite_index = spr_fleet_eldar; elforce.owner = eFACTION.ELDAR; - elforce.capital_number = choose(2, 3); - elforce.frigate_number = choose(4, 5, 6); - elforce.escort_number = floor(random_range(7, 11)) + 1; + elforce.capital_number = 1; + elforce.frigate_number = choose(1, 2); + elforce.escort_number = choose(2, 3, 4); elforce.image_alpha = 0; elforce.orbiting = craft; } diff --git a/objects/obj_en_ship/Step_0.gml b/objects/obj_en_ship/Step_0.gml index 04c45c9327..3a27ba529f 100644 --- a/objects/obj_en_ship/Step_0.gml +++ b/objects/obj_en_ship/Step_0.gml @@ -559,6 +559,11 @@ if (owner == 6) { spid = 100; } + // Vanilla Eldar run spid 60-100 against everyone else's 20-45, producing + // endless chase loops. Scaled here so the whole class table tunes from one + // macro; they stay the fastest ships in the game. + spid *= ELDAR_SHIP_SPEED_MULT; + if (target != 0) { if (speed < (spid / 10)) { speed += 0.02; diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index c521af115e..8de3ea1380 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -75,7 +75,14 @@ #macro ELDAR_INCURSION_FORCE_BASE 3 #macro ELDAR_INCURSION_FORCE_MAX 5 #macro ELDAR_INTEL_REQUIRED 3 -#macro ELDAR_FLEET_ENABLED 0 +#macro ELDAR_FLEET_ENABLED 1 + +// Eldar naval combat tuning. Vanilla Eldar ships move at spid 60-100 while every other +// faction's ships run 20-45, which is why fights against them degenerate into endless +// chase loops. This multiplier scales the whole Eldar speed table; at 0.65 they run +// 39-65, still comfortably the fastest ships in the game but catchable. 1.0 restores +// vanilla darting. +#macro ELDAR_SHIP_SPEED_MULT 0.65 // Guard volley size: how many rank-and-file guardsmen share one firing stack in combat. The // regiment splits into capped stacks of this size instead of merging into one giant lasgun diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index 847144ec01..ce8229b362 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -1359,6 +1359,7 @@ function PlanetData(_planet, _system) constructor { var presence_text = ""; var faction_names = [ "Adeptas", + "Eldar", "Orks", "Tau", "Tyranids", @@ -1369,6 +1370,7 @@ function PlanetData(_planet, _system) constructor { ]; var faction_ids = [ "p_sisters", + "p_eldar", "p_orks", "p_tau", "p_tyranids", From 0b87329d4fbfa8e1e7018dbe237e962a8eb17a70 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 22:21:38 +0300 Subject: [PATCH 072/140] Bombardment fix The planet screen's Planetary Presence panel mapped its parallel name and array lists with the Chaos/Traitors pair crossed: the "Chaos" label displayed p_traitors and "Traitors" displayed p_chaos (fork-only, introduced in a merge resolution; upstream is aligned). All mechanical systems (bombardment targeting, battle enemy selection, force reduction) use the correct arrays, so the practical symptom was a strength-6 Traitor Guard garrison displayed as "Chaos: Extremis (6)" that orbital bombardment of the Chaos target could never reduce, while the report truthfully announced annihilating the planet's small real Chaos presence, reported as "bombardment fails to damage chaos forces". Labels realigned to their arrays; the p_chaos-above-6 "Daemons" display case and the Eldar presence entry are unaffected. --- scripts/scr_PlanetData/scr_PlanetData.gml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index ce8229b362..173f396501 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -1374,8 +1374,14 @@ function PlanetData(_planet, _system) constructor { "p_orks", "p_tau", "p_tyranids", - "p_traitors", + // "Chaos" must read p_chaos and "Traitors" p_traitors. These two were + // crossed (a merge casualty; upstream is aligned), so the panel showed + // Traitor Guard strength under the "Chaos" label and vice versa: + // bombarding the "Chaos" target then annihilated the real p_chaos while + // the mislabeled traitor 6 sat untouched on the panel, reported as + // "bombardment fails to damage chaos forces". "p_chaos", + "p_traitors", "p_demons", "p_necrons", ]; From 2d09e5b5116d22147d563d3782dec3ca2df45625 Mon Sep 17 00:00:00 2001 From: KestasV Date: Fri, 3 Jul 2026 22:40:40 +0300 Subject: [PATCH 073/140] Vehicle-only blocks keep firing when engaged, ending the last-survivor stall The vanilla engaged rule stops all ranged fire for a block in melee contact. Vehicle-only blocks (Whirlwinds, Land Speeders, tank remnants) carry no melee weapons, so a last-surviving vehicle block reaching the enemy line could do nothing at all, while enemy chip melee did nothing back and the enemy rear often sat out of ammunition: a total stalemate with a silent combat log that upstream's battle timer exists to paper over. The engaged ranged gate now excepts blocks with men <= 0, mirroring the existing Guard exception, so vehicle blocks fire their guns point-blank and battles resolve. Marine infantry keep the vanilla rule. --- objects/obj_pnunit/Alarm_0.gml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index 5785360fdd..718f695e08 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -99,7 +99,13 @@ try { // reaches it instead of standing mute. Marines keep the vanilla rule of // ranged only while not engaged. The bayonet (range 1) still resolves on // the melee line below, so engaged Guard both shoot and stab. - if ((range[i] != 1) && ((engaged == 0) || (guard > 0))) { + // Vehicle-only blocks (men <= 0: Whirlwinds, Land Speeders, tank + // remnants) also keep firing when engaged: they carry no melee weapons + // at all, so the vanilla rule left them sitting mute in contact while + // enemy knives chip uselessly at their hulls, the last-survivors + // stalemate the battle timer exists to paper over. A vehicle firing + // its guns point-blank is no stranger than the Guard doing it. + if ((range[i] != 1) && ((engaged == 0) || (guard > 0) || (men <= 0))) { range_shoot = "ranged"; } if ((range[i] != floor(range[i]) || floor(range[i]) == 1) && engaged == 1) { From 6d4922744aba53c47dc30043623994fec5c4348e Mon Sep 17 00:00:00 2001 From: KestasV Date: Sat, 4 Jul 2026 01:54:18 +0300 Subject: [PATCH 074/140] Melee hook changes Changes melee 1 bug that causes it to not be used. --- scripts/scr_en_weapon/scr_en_weapon.gml | 31 ++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/scripts/scr_en_weapon/scr_en_weapon.gml b/scripts/scr_en_weapon/scr_en_weapon.gml index 4a567c20ae..8f3061409d 100644 --- a/scripts/scr_en_weapon/scr_en_weapon.gml +++ b/scripts/scr_en_weapon/scr_en_weapon.gml @@ -23,6 +23,31 @@ function scr_en_weapon(name, is_man, man_number, man_type, group) { //if (obj_ncombat.enemy=5) then faith_bonus=faith[man_type]; switch (name) { + // "Melee1" is the roster's generic sidearm-melee slot, carried by ten unit + // types across three factions (Eldar Guardians, Dire Avengers, Pathfinders, + // Fire Dragons, Dark Reapers and Exarchs; Ork Tankbustas; Chaos Havocs, + // Noise Marines, Rubric Marines). It never had stats anywhere (verbatim + // upstream), so every one of those units built an attack-0 range-0 weapon + // stack: "broken range" error spam each turn and no melee capability at all, + // a major silent contributor to the last-survivor melee stalemates. Statted + // here as a modest close-combat weapon; units with a real melee identity + // already carry proper weapons alongside it. + case "Melee1": + atta = 40; + arp = 1; + rang = 1; + break; + // Flesh Hooks are carried by Lictors (Tyranid battles) AND Mutants (Chaos + // and Heretic rosters). Their stats lived only under the Tyranid faction + // gate below, so Mutant flesh hooks were attack-0 range-0 in every battle + // mutants actually appear in. Weapon stats in this file are faction-gated; + // any weapon shared across factions must live in this ungated switch. + case "Flesh Hooks": + atta = 100; + arp = 2; + rang = 2; + amm = 1; + break; case "Venom Claws": atta = 200; arp = 4; @@ -660,12 +685,6 @@ function scr_en_weapon(name, is_man, man_number, man_type, group) { arp = 3; rang = 1; break; - case "Flesh Hooks": - atta = 100; - arp = 2; - rang = 2; - amm = 1; - break; default: break; } From 7277e18b9e69d2f1c7f7bfe1f25ba654fd2784cf Mon Sep 17 00:00:00 2001 From: KestasV Date: Sat, 4 Jul 2026 01:58:29 +0300 Subject: [PATCH 075/140] Port upstream 173a6500: chaos/heretics renumbered to eFACTION, fork compensators removed Applies EttyKitty's upstream commit 173a6500 ("fix: The entire chaos vs heretics standoff") which renumbers the Chaos/Heretic pair to match eFACTION across the codebase: drop-select enemy selection (chaos 10, traitors 11), obj_ncombat Alarm_5 strength reads, planet_forces[10]/[11] mapping, the planetary AI resolution, fleets, events, and cheats. The planet_forces flip is the root fix for bombardment failing to reduce traitor forces: the old mapping showed traitor strength under the Chaos label and target index, so bombardments were routed into the empty chaos array while truthfully reporting the computed reduction. This fork's two compensating swaps, built against the old inverted numbering, are removed since they would now invert a correct pair: the Chaos/Heretic translation before edit_forces in Alarm_5, and the space-hulk _hulk_faction swap (chaos-rolled hulks store garrisons in p_traitors and arrive as HERETICS under the new chain, so the raw enemy id routes correctly, old saves included). The presence-panel hunk resolved as a no-op against this fork's existing fix, keeping the Eldar entry; the panel label follows upstream's "Heretics" naming. Fork bombardment fixes in scr_bomb_world are eFACTION-keyed and unaffected. --- objects/obj_drop_select/Create_0.gml | 20 +-- objects/obj_en_fleet/Draw_0.gml | 2 +- objects/obj_fleet/Create_0.gml | 2 +- objects/obj_ncombat/Alarm_5.gml | 46 ++--- objects/obj_ncombat/Create_0.gml | 2 +- objects/obj_p_assra/KeyPress_49.gml | 2 +- objects/obj_p_assra/KeyPress_50.gml | 2 +- objects/obj_p_assra/Step_0.gml | 10 +- objects/obj_star/Create_0.gml | 1 + objects/obj_star_select/Mouse_50.gml | 12 +- objects/obj_turn_end/Alarm_0.gml | 3 + objects/obj_turn_end/Mouse_56.gml | 6 +- scripts/scr_PlanetData/scr_PlanetData.gml | 10 +- scripts/scr_cheatcode/scr_cheatcode.gml | 6 +- .../scr_drop_select_function.gml | 2 +- scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml | 168 +++++++++--------- scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml | 2 +- scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml | 4 +- scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml | 8 +- scripts/scr_event_code/scr_event_code.gml | 2 +- .../scr_fleet_functions.gml | 8 +- 21 files changed, 156 insertions(+), 162 deletions(-) diff --git a/objects/obj_drop_select/Create_0.gml b/objects/obj_drop_select/Create_0.gml index b89fa4bcd4..1e6d51946f 100644 --- a/objects/obj_drop_select/Create_0.gml +++ b/objects/obj_drop_select/Create_0.gml @@ -94,7 +94,7 @@ if (!instance_exists(obj_saveload)) { tau = 0; traitors = 0; tyranids = 0; - csm = 0; + chaos = 0; necrons = 0; demons = 0; @@ -174,7 +174,7 @@ if (purge == 0) { ork = p_target.p_orks[planet_number]; tau = p_target.p_tau[planet_number]; tyranids = p_target.p_tyranids[planet_number]; - csm = p_target.p_chaos[planet_number]; + chaos = p_target.p_chaos[planet_number]; traitors = p_target.p_traitors[planet_number]; necrons = p_target.p_necrons[planet_number]; demons = p_target.p_demons[planet_number]; @@ -204,13 +204,13 @@ if (purge == 0) { bes = 9; bes_score = tyranids; } - if (traitors > bes_score) { + if (chaos > bes_score) { bes = 10; - bes_score = traitors; + bes_score = chaos; } - if (csm > bes_score) { + if (traitors > bes_score) { bes = 11; - bes_score = csm; + bes_score = traitors; } if (necrons > bes_score) { bes = 13; @@ -255,11 +255,11 @@ if (purge == 0) { forces += 1; force_present[forces] = 9; } - if ((traitors > 0) || ((traitors == 0) && (spesh == true))) { + if (chaos > 0) { forces += 1; force_present[forces] = 10; } - if (csm > 0) { + if ((traitors > 0) || ((traitors == 0) && (spesh == true))) { forces += 1; force_present[forces] = 11; } @@ -280,8 +280,8 @@ if (purge == 0) { ork, tau, tyranids, + chaos, traitors, - csm, demons, necrons ]; @@ -292,8 +292,8 @@ if (purge == 0) { "Orks", "Tau", "Tyranids", + "Chaos", "Heretics", - "CSMs", "Daemons", "Necrons" ]; diff --git a/objects/obj_en_fleet/Draw_0.gml b/objects/obj_en_fleet/Draw_0.gml index 5eaf44cc36..0a1d187bea 100644 --- a/objects/obj_en_fleet/Draw_0.gml +++ b/objects/obj_en_fleet/Draw_0.gml @@ -144,7 +144,7 @@ if ((within == 1) || (selected > 0)) { break; case eFACTION.CHAOS: fleet_descript = "Heretic Fleet"; - if (fleet_has_cargo("warband") || fleet_has_cargo("csm")) { + if (fleet_has_cargo("warband") || fleet_has_cargo("chaos")) { fleet_descript = string(obj_controller.faction_leader[eFACTION.CHAOS]) + "'s Fleet"; if (string_count("s's Fleet", fleet_descript) > 0) { fleet_descript = string_replace(fleet_descript, "s's Fleet", "s' Fleet"); diff --git a/objects/obj_fleet/Create_0.gml b/objects/obj_fleet/Create_0.gml index 37f9f038fb..420610062a 100644 --- a/objects/obj_fleet/Create_0.gml +++ b/objects/obj_fleet/Create_0.gml @@ -10,7 +10,7 @@ sel_y1 = 0; control = 0; ships_selected = 0; battle_special = ""; -csm_exp = 0; +chaos_exp = 0; star_name = ""; left_down = 0; diff --git a/objects/obj_ncombat/Alarm_5.gml b/objects/obj_ncombat/Alarm_5.gml index ad5b5ed2cd..dd8258b849 100644 --- a/objects/obj_ncombat/Alarm_5.gml +++ b/objects/obj_ncombat/Alarm_5.gml @@ -346,16 +346,15 @@ if ((fortified > 0) && (!instance_exists(obj_nfort)) && (reduce_fortification == if ((!defeat) && (battle_special == "space_hulk")) { var enemy_power = 0, loot = 0, dicey = roll_dice_chapter(1, 100, "low"); - // Reduce the hulk garrison by one and read the strength left behind. A Chaos hulk keeps its - // strength in the traitor (p_traitors) slot, which edit_forces reaches through the HERETICS - // case, so it is reduced as HERETICS. This also lets Chaos hulks lose forces, clear, and roll - // loot at all, which they previously never could. - var _hulk_faction = enemy; - if (enemy == eFACTION.CHAOS) { - _hulk_faction = eFACTION.HERETICS; - } + // Reduce the hulk garrison by one and read the strength left behind. Chaos-rolled + // hulks store their garrison in p_traitors (obj_star Alarm_0), so under the + // corrected Chaos/Heretic numbering (upstream 173a6500) their battles arrive as + // eFACTION.HERETICS and the raw enemy id reaches the right slot; the old swap + // this fork carried predates the renumbering and would now misroute. This block + // also lets hulks lose forces, clear, and roll loot at all, which they + // previously never could. if (enemy == eFACTION.ORK || enemy == eFACTION.TYRANIDS || enemy == eFACTION.HERETICS || enemy == eFACTION.CHAOS) { - enemy_power = p_data.add_forces(_hulk_faction, -1); + enemy_power = p_data.add_forces(enemy, -1); // Garrison wiped out: the hulk is cleared. The salvage choice is offered post-battle in // space_hulk_explore_battle_aftermath (scr_post_battle_events). if (enemy_power <= 0) { @@ -447,13 +446,13 @@ if (defeat == 0 && _reduce_power) { enemy_power = battle_object.p_tyranids[battle_id]; part10 = "Tyranid"; } else if (enemy == eFACTION.CHAOS) { - enemy_power = battle_object.p_traitors[battle_id]; + enemy_power = battle_object.p_chaos[battle_id]; part10 = "Heretic"; if (threat == 7) { part10 = "Daemon"; } } else if (enemy == eFACTION.HERETICS) { - enemy_power = battle_object.p_chaos[battle_id]; + enemy_power = battle_object.p_traitors[battle_id]; part10 = "Chaos Space Marine"; } else if (enemy == eFACTION.NECRONS) { enemy_power = battle_object.p_necrons[battle_id]; @@ -568,22 +567,13 @@ if (defeat == 0 && _reduce_power) { } if (enemy >= eFACTION.ECCLESIARCHY) { - // Combat still numbers the Chaos/Heretic pair opposite to eFACTION even after the - // upstream eFACTION standardization: enemy eFACTION.CHAOS is fought as the - // Heretic/traitor force and its strength is read from p_traitors above, while enemy - // eFACTION.HERETICS is fought as the Chaos Space Marine force read from p_chaos. - // edit_forces maps by raw eFACTION (CHAOS -> p_chaos, HERETICS -> p_traitors), so - // passing the raw combat enemy wrote the reduced strength into the OTHER slot, leaving - // the force that was actually fought untouched and often inflating the other one. Swap - // the pair so the reduction lands on the same force the battle was drawn from. - // Mirrors the space_hulk fix. - var _reduce_faction = enemy; - if (enemy == eFACTION.CHAOS) { - _reduce_faction = eFACTION.HERETICS; - } else if (enemy == eFACTION.HERETICS) { - _reduce_faction = eFACTION.CHAOS; - } - p_data.edit_forces(_reduce_faction, new_power); + // Upstream commit 173a6500 ("fix: The entire chaos vs heretics standoff") + // renumbered the Chaos/Heretic pair to match eFACTION everywhere: enemy + // eFACTION.CHAOS now reads p_chaos above and eFACTION.HERETICS reads + // p_traitors, the same mapping edit_forces uses. The compensating swap this + // fork carried (translating the pair before edit_forces) is therefore + // removed; with the renumbering in place it would invert a correct pair. + p_data.edit_forces(enemy, new_power); } if ((enemy != eFACTION.IMPERIUM) && (string_count("cs_meeting_battle", battle_special) == 0)) { @@ -707,7 +697,7 @@ if (obj_ini.omophagea) { if ((enemy == eFACTION.NECRONS) || (enemy == eFACTION.TYRANIDS) || (battle_special == "ship_demon")) { eatme += 100; } - if ((enemy == eFACTION.CHAOS) && (battle_object.p_traitors[battle_id] == 7)) { + if ((enemy == eFACTION.CHAOS) && (battle_object.p_chaos[battle_id] == 7)) { eatme += 200; } diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index 4c15f0137c..a915865e3b 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -57,8 +57,8 @@ instance_create(0, 0, obj_centerline); local_forces = 0; battle_loc = ""; battle_climate = ""; -/// @type {Asset.GMObject.obj_star} if (instance_exists(obj_star)) { + /// @type {Id.Instance.obj_star} battle_object = instance_nearest(x, y, obj_star); } else { battle_object = noone; diff --git a/objects/obj_p_assra/KeyPress_49.gml b/objects/obj_p_assra/KeyPress_49.gml index fea04756e4..3139e0c3de 100644 --- a/objects/obj_p_assra/KeyPress_49.gml +++ b/objects/obj_p_assra/KeyPress_49.gml @@ -1 +1 @@ -obj_fleet.csm_exp = 1; +obj_fleet.chaos_exp = 1; diff --git a/objects/obj_p_assra/KeyPress_50.gml b/objects/obj_p_assra/KeyPress_50.gml index 41d9f9d154..b33241cfbc 100644 --- a/objects/obj_p_assra/KeyPress_50.gml +++ b/objects/obj_p_assra/KeyPress_50.gml @@ -1 +1 @@ -obj_fleet.csm_exp = 2; +obj_fleet.chaos_exp = 2; diff --git a/objects/obj_p_assra/Step_0.gml b/objects/obj_p_assra/Step_0.gml index 519cf2d065..657c275ce8 100644 --- a/objects/obj_p_assra/Step_0.gml +++ b/objects/obj_p_assra/Step_0.gml @@ -173,16 +173,16 @@ if ((boarding == true) && (board_cooldown >= 0) && instance_exists(target) && in boarding_disadvantage -= 5; } } - if ((target.owner == eFACTION.IMPERIUM) || ((target.owner == eFACTION.CHAOS) && (obj_fleet.csm_exp == 0))) { + if ((target.owner == eFACTION.IMPERIUM) || ((target.owner == eFACTION.CHAOS) && (obj_fleet.chaos_exp == 0))) { boarding_disadvantage -= 0; } // Cultists/Pirates/Humans if ((target.owner == eFACTION.PLAYER) || (target.owner == eFACTION.ECCLESIARCHY) || (target.owner == eFACTION.ORK) || (target.owner == eFACTION.ELDAR) || (target.owner == eFACTION.NECRONS)) { boarding_disadvantage -= 10; } - if ((target.owner == eFACTION.CHAOS) && (obj_fleet.csm_exp == 1)) { + if ((target.owner == eFACTION.CHAOS) && (obj_fleet.chaos_exp == 1)) { boarding_disadvantage -= 20; } // Veteran marines - if (((target.owner == eFACTION.CHAOS) && (obj_fleet.csm_exp == 2)) || (target.owner == eFACTION.TYRANIDS)) { + if (((target.owner == eFACTION.CHAOS) && (obj_fleet.chaos_exp == 2)) || (target.owner == eFACTION.TYRANIDS)) { boarding_disadvantage -= 30; } // Daemons, veteran CSM, tyranids @@ -226,10 +226,10 @@ if ((boarding == true) && (board_cooldown >= 0) && instance_exists(target) && in if ((target.owner == eFACTION.ECCLESIARCHY) || (target.owner == eFACTION.ORK) || (target.owner == eFACTION.ELDAR) || (target.owner == eFACTION.NECRONS)) { experience += 1; } - if ((target.owner == eFACTION.CHAOS) && (obj_fleet.csm_exp == 1)) { + if ((target.owner == eFACTION.CHAOS) && (obj_fleet.chaos_exp == 1)) { experience += 2; } - if ((target.owner == eFACTION.CHAOS) && (obj_fleet.csm_exp == 2)) { + if ((target.owner == eFACTION.CHAOS) && (obj_fleet.chaos_exp == 2)) { experience += 3; } if (target.owner == eFACTION.TYRANIDS) { diff --git a/objects/obj_star/Create_0.gml b/objects/obj_star/Create_0.gml index 73f19bbdef..66a43a4f86 100644 --- a/objects/obj_star/Create_0.gml +++ b/objects/obj_star/Create_0.gml @@ -117,6 +117,7 @@ get_sabatours = function(planet){ return _gar; } +/// @returns {Struct.PlanetData} get_planet_data = function(planet){ var _gar = system_datas[planet]; if (_gar == false){ diff --git a/objects/obj_star_select/Mouse_50.gml b/objects/obj_star_select/Mouse_50.gml index cd1cffb440..ee6a23ade0 100644 --- a/objects/obj_star_select/Mouse_50.gml +++ b/objects/obj_star_select/Mouse_50.gml @@ -115,7 +115,7 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select)) { var e = 1; var khorne_count = 0; - var chaos_space_marine_count = 0; + var chaos_count = 0; var en_capitals, en_frigates, en_escorts; repeat (9) { e += 1; @@ -134,8 +134,8 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select)) { if (fleet_has_cargo("warband")) { khorne_count++; } - if (fleet_has_cargo("csm")) { - chaos_space_marine_count++; + if (fleet_has_cargo("chaos")) { + chaos_count++; } } } @@ -193,11 +193,11 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select)) { // Plug in all of the enemies first // And then plug in the allies after then with their status set to positive - if (chaos_space_marine_count) { - obj_fleet.csm_exp = 1; + if (chaos_count) { + obj_fleet.chaos_exp = 1; } if (khorne_count) { - obj_fleet.csm_exp = 2; + obj_fleet.chaos_exp = 2; } for (var i = 0; i < target.planets; i++) { diff --git a/objects/obj_turn_end/Alarm_0.gml b/objects/obj_turn_end/Alarm_0.gml index 805c4fcc84..13e6810739 100644 --- a/objects/obj_turn_end/Alarm_0.gml +++ b/objects/obj_turn_end/Alarm_0.gml @@ -148,6 +148,9 @@ try { tempy = battle_object[current_battle].p_tyranids[battle_world[current_battle]]; } if (battle_opponent[current_battle] == 10) { + tempy = battle_object[current_battle].p_chaos[battle_world[current_battle]]; + } + if (battle_opponent[current_battle] == 11) { tempy = battle_object[current_battle].p_traitors[battle_world[current_battle]]; } if (battle_opponent[current_battle] == 13) { diff --git a/objects/obj_turn_end/Mouse_56.gml b/objects/obj_turn_end/Mouse_56.gml index c547d21d17..6a3a601036 100644 --- a/objects/obj_turn_end/Mouse_56.gml +++ b/objects/obj_turn_end/Mouse_56.gml @@ -71,11 +71,11 @@ if (!instance_exists(obj_saveload) && !instance_exists(obj_popup) && !instance_e } } - if (battle_special[current_battle] == "csm") { - obj_fleet.csm_exp = 1; + if (battle_special[current_battle] == "chaos") { + obj_fleet.chaos_exp = 1; } if (battle_special[current_battle] == "BLOOD") { - obj_fleet.csm_exp = 2; + obj_fleet.chaos_exp = 2; } instance_activate_all(); diff --git a/scripts/scr_PlanetData/scr_PlanetData.gml b/scripts/scr_PlanetData/scr_PlanetData.gml index 173f396501..485f7e891d 100644 --- a/scripts/scr_PlanetData/scr_PlanetData.gml +++ b/scripts/scr_PlanetData/scr_PlanetData.gml @@ -314,8 +314,8 @@ function PlanetData(_planet, _system) constructor { planet_forces[7] = system.p_orks[planet]; planet_forces[8] = system.p_tau[planet]; planet_forces[9] = system.p_tyranids[planet]; - planet_forces[10] = system.p_traitors[planet]; - planet_forces[11] = system.p_chaos[planet] + system.p_demons[planet]; + planet_forces[10] = system.p_chaos[planet] + system.p_demons[planet]; + planet_forces[11] = system.p_traitors[planet]; planet_forces[13] = system.p_necrons[planet]; } catch (_exception) { @@ -1040,7 +1040,7 @@ function PlanetData(_planet, _system) constructor { } } if (planet_forces[eFACTION.CHAOS] > 0) { - guard_attack = "csm"; + guard_attack = "chaos"; } if ((pdf > 0) && (current_owner == eFACTION.TAU)) { guard_attack = "pdf"; @@ -1103,7 +1103,7 @@ function PlanetData(_planet, _system) constructor { if (_pdf_attack == "") { if (planet_forces[eFACTION.CHAOS] > 0) { - _pdf_attack = "csm"; + _pdf_attack = "chaos"; } else if (planet_forces[eFACTION.HERETICS] > 0) { _pdf_attack = "traitors"; } else if (planet_forces[eFACTION.ORK] > 0) { @@ -1364,7 +1364,7 @@ function PlanetData(_planet, _system) constructor { "Tau", "Tyranids", "Chaos", - "Traitors", + "Heretics", "Daemons", "Necrons", ]; diff --git a/scripts/scr_cheatcode/scr_cheatcode.gml b/scripts/scr_cheatcode/scr_cheatcode.gml index 8cdeb77b9e..524c8332d5 100644 --- a/scripts/scr_cheatcode/scr_cheatcode.gml +++ b/scripts/scr_cheatcode/scr_cheatcode.gml @@ -550,8 +550,8 @@ function draw_planet_debug_forces() { "Orks", "Tau", "Tyranids", - "Traitors", - "CSM", + "Chaos", + "Heretics", "Daemons", "Necrons", "Sisters" @@ -560,8 +560,8 @@ function draw_planet_debug_forces() { "p_orks", "p_tau", "p_tyranids", - "p_traitors", "p_chaos", + "p_traitors", "p_demons", "p_necrons", "p_sisters" diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index b8eab94262..55be0d7a82 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -351,7 +351,7 @@ function drop_select_unit_selection() { tau, tyranids, traitors, - csm, + chaos, demons, necrons ]; diff --git a/scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml b/scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml index 88fc4e9775..2ed459f9e3 100644 --- a/scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml +++ b/scripts/scr_enemy_ai_a/scr_enemy_ai_a.gml @@ -86,11 +86,11 @@ function scr_enemy_ai_a() { var pdf_score = 0; var eldar_score = 0; - var guard_attack = "", pdf_attack = "", ork_attack = "", tau_attack = "", traitors_attack = "", csm_attack = ""; + var guard_attack = "", pdf_attack = "", ork_attack = "", tau_attack = "", traitors_attack = "", chaos_attack = ""; var eldar_attack = "", tyranids_attack = "", necrons_attack = "", sisters_attack = ""; var traitors_score = p_traitors[_run]; - var csm_score = p_chaos[_run]; + var chaos_score = p_chaos[_run]; var tyranids_score = p_tyranids[_run]; var necrons_score = p_necrons[_run]; var sisters_score = p_sisters[_run]; @@ -167,7 +167,7 @@ function scr_enemy_ai_a() { sisters_attack = "traitors"; } if (p_chaos[_run] > 0) { - sisters_attack = "csm"; + sisters_attack = "chaos"; } if ((p_player[_run] > 0) && (obj_controller.faction_status[5] == "War")) { sisters_attack = "player"; @@ -196,7 +196,7 @@ function scr_enemy_ai_a() { ork_attack = "traitors"; } if ((rand == 4) && (p_chaos[_run] > 0)) { - ork_attack = "csm"; + ork_attack = "chaos"; } if ((rand == 5) && (p_sisters[_run] > 0)) { ork_attack = "sisters"; @@ -227,19 +227,19 @@ function scr_enemy_ai_a() { } if ((p_chaos[_run] > 0) && (stop != 1)) { if ((planet_forces[eFACTION.ORK] == 0) && (planet_forces[eFACTION.TAU] == 0)) { - csm_attack = "imp"; + chaos_attack = "imp"; } if ((planet_forces[eFACTION.ORK] > planet_forces[eFACTION.TAU]) && (planet_forces[eFACTION.ORK] > guard_score) && (planet_forces[eFACTION.ORK] > pdf_score)) { - csm_attack = "orks"; + chaos_attack = "orks"; } if ((sisters_score > planet_forces[eFACTION.TAU]) && (sisters_score > planet_forces[eFACTION.ORK]) && (sisters_score > pdf_score)) { - csm_attack = "sisters"; + chaos_attack = "sisters"; } if ((guard_score > planet_forces[eFACTION.TAU]) && (guard_score > planet_forces[eFACTION.ORK])) { - csm_attack = "imp"; + chaos_attack = "imp"; } - if ((csm_attack == "") && (p_player[_run] > 0)) { - csm_attack = "player"; + if ((chaos_attack == "") && (p_player[_run] > 0)) { + chaos_attack = "player"; } } @@ -252,8 +252,8 @@ function scr_enemy_ai_a() { if (traitors_score > 0) { tau_attack = "traitors"; } - if (csm_score > 0) { - tau_attack = "csm"; + if (chaos_score > 0) { + tau_attack = "chaos"; } if (planet_forces[eFACTION.ORK] > 0) { tau_attack = "ork"; @@ -264,11 +264,11 @@ function scr_enemy_ai_a() { if (traitors_score >= 4) { tau_attack = "traitors"; } - if ((csm_score >= 3) && (planet_forces[eFACTION.ORK] <= 2)) { - tau_attack = "csm"; + if ((chaos_score >= 3) && (planet_forces[eFACTION.ORK] <= 2)) { + tau_attack = "chaos"; } - if (csm_score >= 4) { - tau_attack = "csm"; + if (chaos_score >= 4) { + tau_attack = "chaos"; } if (planet_forces[eFACTION.ORK] >= 4) { tau_attack = "ork"; @@ -295,8 +295,8 @@ function scr_enemy_ai_a() { if (traitors_score >= 4) { tau_attack = "traitors"; } - if (csm_score >= 4) { - tau_attack = "csm"; + if (chaos_score >= 4) { + tau_attack = "chaos"; } if (planet_forces[eFACTION.ORK] >= 4) { tau_attack = "ork"; @@ -328,7 +328,7 @@ function scr_enemy_ai_a() { tyranids_attack = "orks"; } if ((rand == 5) && (p_chaos[_run] > 0)) { - tyranids_attack = "csm"; + tyranids_attack = "chaos"; } if ((rand == 6) && (p_sisters[_run] > 0)) { tyranids_attack = "sisters"; @@ -358,7 +358,7 @@ function scr_enemy_ai_a() { necrons_attack = "orks"; } if ((rand == 5) && (p_chaos[_run] > 0)) { - necrons_attack = "csm"; + necrons_attack = "chaos"; } if ((rand == 6) && (p_sisters[_run] > 0)) { necrons_attack = "sisters"; @@ -382,8 +382,8 @@ function scr_enemy_ai_a() { traitors_attack = default_imperium_attack; } - if (csm_attack == "imp") { - csm_attack = default_imperium_attack; + if (chaos_attack == "imp") { + chaos_attack = default_imperium_attack; } if (necrons_attack == "imp") { @@ -410,9 +410,9 @@ function scr_enemy_ai_a() { var after_combat_ork_force = planet_forces[eFACTION.ORK]; var after_combat_tau = planet_forces[eFACTION.TAU]; var after_combat_traitor = traitors_score; - var after_combat_csm = csm_score; - if (csm_score == 6.1) { - csm_score = 8; + var after_combat_chaos = chaos_score; + if (chaos_score == 6.1) { + chaos_score = 8; } var after_combat_necrons = necrons_score; var after_combat_tyranids = tyranids_score; @@ -432,8 +432,8 @@ function scr_enemy_ai_a() { if (guard_attack == "traitors") { tempor = choose(1, 2, 3, 4, 5, 6) * traitors_score; } - if (guard_attack == "csm") { - tempor = choose(2, 3, 4, 5, 6, 7) * csm_score; + if (guard_attack == "chaos") { + tempor = choose(2, 3, 4, 5, 6, 7) * chaos_score; } if (guard_attack == "tyranids") { tempor = choose(2, 3, 4, 5, 6, 7) * tyranids_score; @@ -450,7 +450,7 @@ function scr_enemy_ai_a() { if ((guard_attack == "traitors") && (traitors_score > guard_score)) { rand1 = 0; } - if ((guard_attack == "csm") && (csm_score > guard_score)) { + if ((guard_attack == "chaos") && (chaos_score > guard_score)) { rand1 = 0; } if ((guard_attack == "tyranids") && (tyranids_score > guard_score)) { @@ -511,8 +511,8 @@ function scr_enemy_ai_a() { if (guard_attack == "traitors") { after_combat_traitor -= 1; } - if (guard_attack == "csm") { - after_combat_csm -= 1; + if (guard_attack == "chaos") { + after_combat_chaos -= 1; } if (guard_attack == "tyranids") { after_combat_tyranids -= 1; @@ -531,8 +531,8 @@ function scr_enemy_ai_a() { if (pdf_attack == "traitors") { tempor = traitors_score; } - if (pdf_attack == "csm") { - tempor = csm_score; + if (pdf_attack == "chaos") { + tempor = chaos_score; } if (pdf_attack == "guard") { tempor = guard_score; @@ -553,7 +553,7 @@ function scr_enemy_ai_a() { if ((pdf_attack == "traitors") && (traitors_score >= 6)) { rand2 = 1; } - if ((pdf_attack == "csm") && (csm_score >= 3)) { + if ((pdf_attack == "chaos") && (chaos_score >= 3)) { rand2 = 1; } if ((pdf_attack == "tyranids") && (tyranids_score >= pdf_score)) { @@ -579,8 +579,8 @@ function scr_enemy_ai_a() { if (pdf_attack == "traitors") { after_combat_traitor = tempor; } - if (pdf_attack == "csm") { - after_combat_csm = tempor; + if (pdf_attack == "chaos") { + after_combat_chaos = tempor; } if ((pdf_attack == "tyranids") && (tyranids_score >= 4)) { after_combat_tyranids = tempor; @@ -628,13 +628,13 @@ function scr_enemy_ai_a() { if (rand1 > rand2) { after_combat_traitor -= 1; } - } else if (sisters_attack == "csm") { - rand2 = (choose(2, 3, 4, 5, 6) * csm_score) * choose(1, 1.25); - if (csm_score == 6.1) { + } else if (sisters_attack == "chaos") { + rand2 = (choose(2, 3, 4, 5, 6) * chaos_score) * choose(1, 1.25); + if (chaos_score == 6.1) { rand2 = 999; } if (rand1 > rand2) { - after_combat_csm -= 1; + after_combat_chaos -= 1; } } else if (sisters_attack == "necrons") { rand2 = (choose(4, 5, 6, 7) * necrons_score) * choose(1, 1.25); @@ -649,25 +649,25 @@ function scr_enemy_ai_a() { } else if (sisters_attack == "pdf") { rand2 = (choose(1, 2, 3, 4, 5) * pdf_score) * choose(1, 1.25); if (rand1 > rand2) { - if (csm_score >= 6) { + if (chaos_score >= 6) { p_pdf[_run] = 0; } - if (csm_score <= 3) { + if (chaos_score <= 3) { p_pdf[_run] = floor(p_pdf[_run] * min(0.95, 0.75 + pdf_loss_reduction)); } - if (csm_score >= 4) { + if (chaos_score >= 4) { p_pdf[_run] = floor(p_pdf[_run] * min(0.95, 0.65 + pdf_loss_reduction)); } - if ((csm_score >= 4) && (p_pdf[_run] < 60000)) { + if ((chaos_score >= 4) && (p_pdf[_run] < 60000)) { p_pdf[_run] = 0; } - if ((csm_score >= 3) && (p_pdf[_run] < 20000)) { + if ((chaos_score >= 3) && (p_pdf[_run] < 20000)) { p_pdf[_run] = 0; } - if ((csm_score >= 2) && (p_pdf[_run] < 3000)) { + if ((chaos_score >= 2) && (p_pdf[_run] < 3000)) { p_pdf[_run] = 0; } - if ((csm_score >= 1) && (p_pdf[_run] < 1000)) { + if ((chaos_score >= 1) && (p_pdf[_run] < 1000)) { p_pdf[_run] = 0; } } @@ -688,13 +688,13 @@ function scr_enemy_ai_a() { if ((rand1 > rand2) && (traitors_score != 7)) { after_combat_traitor -= 1; } - } else if (tau_attack == "csm") { - rand2 = (choose(1, 2, 3, 4, 5, 6) * csm_score) * choose(1, 1.25); - if (csm_score == 6.1) { + } else if (tau_attack == "chaos") { + rand2 = (choose(1, 2, 3, 4, 5, 6) * chaos_score) * choose(1, 1.25); + if (chaos_score == 6.1) { rand2 = 999; } if (rand1 > rand2) { - after_combat_csm -= 1; + after_combat_chaos -= 1; } } else if (tau_attack == "guard") { rand2 = (choose(1, 2, 3, 4, 5, 6) * guard_score) * choose(1, 1.25); @@ -738,10 +738,10 @@ function scr_enemy_ai_a() { if ((rand1 > rand2) && (traitors_score < 6)) { after_combat_traitor -= 1; } - } else if (ork_attack == "csm") { - rand2 = (choose(1, 2, 3, 4, 5, 6) * csm_score) * choose(1, 1.25); - if ((rand1 > rand2) && (csm_score != 6)) { - after_combat_csm -= 1; + } else if (ork_attack == "chaos") { + rand2 = (choose(1, 2, 3, 4, 5, 6) * chaos_score) * choose(1, 1.25); + if ((rand1 > rand2) && (chaos_score != 6)) { + after_combat_chaos -= 1; } } else if (ork_attack == "guard") { var onc = 0; @@ -908,73 +908,73 @@ function scr_enemy_ai_a() { } // CSM attack - if ((csm_score > 0) && (csm_attack != "") && (csm_attack != "player")) { - rand1 = choose(2, 3, 4, 5, 6, 7) * csm_score; - if (csm_score >= 5) { + if ((chaos_score > 0) && (chaos_attack != "") && (chaos_attack != "player")) { + rand1 = choose(2, 3, 4, 5, 6, 7) * chaos_score; + if (chaos_score >= 5) { rand1 = choose(30, 36); } - if (csm_attack == "tau") { + if (chaos_attack == "tau") { rand2 = (choose(1, 2, 3, 4, 5) * planet_forces[eFACTION.TAU]) * choose(1, 1.25); if (rand1 > rand2) { after_combat_tau -= 1; } - } else if (csm_attack == "ork") { + } else if (chaos_attack == "ork") { rand2 = (choose(1, 2, 3, 4, 5) * planet_forces[eFACTION.ORK]) * choose(1, 1.25); if (rand1 > rand2) { after_combat_ork_force -= 1; } - } else if (csm_attack == "guard") { + } else if (chaos_attack == "guard") { rand2 = (choose(1, 2, 3, 4, 5) * guard_score) * choose(1, 1.25); if (rand1 > rand2) { - if (csm_score <= 3) { + if (chaos_score <= 3) { p_guardsmen[_run] = floor(p_guardsmen[_run] * 0.7); } - if (csm_score >= 4) { + if (chaos_score >= 4) { p_guardsmen[_run] = floor(p_guardsmen[_run] * 0.6); } - if (csm_score >= 6) { + if (chaos_score >= 6) { p_guardsmen[_run] = floor(p_guardsmen[_run] * 0.3); } - if ((csm_score >= 4) && (p_guardsmen[_run] < 15000)) { + if ((chaos_score >= 4) && (p_guardsmen[_run] < 15000)) { p_guardsmen[_run] = 0; } - if ((csm_score >= 3) && (p_guardsmen[_run] < 5000)) { + if ((chaos_score >= 3) && (p_guardsmen[_run] < 5000)) { p_guardsmen[_run] = 0; } - if ((csm_score >= 2) && (p_guardsmen[_run] < 1000)) { + if ((chaos_score >= 2) && (p_guardsmen[_run] < 1000)) { p_guardsmen[_run] = 0; } - if ((csm_score >= 1) && (p_guardsmen[_run] < 500)) { + if ((chaos_score >= 1) && (p_guardsmen[_run] < 500)) { p_guardsmen[_run] = 0; } } - } else if (csm_attack == "pdf") { + } else if (chaos_attack == "pdf") { rand2 = (choose(1, 2, 3, 4, 5) * pdf_score) * choose(1, 1.25); if (rand1 > rand2) { - if (csm_score >= 6) { + if (chaos_score >= 6) { p_pdf[_run] = 0; } - if (csm_score <= 3) { + if (chaos_score <= 3) { p_pdf[_run] = floor(p_pdf[_run] * min(0.95, 0.75 + pdf_loss_reduction)); } - if (csm_score >= 4) { + if (chaos_score >= 4) { p_pdf[_run] = floor(p_pdf[_run] * min(0.95, 0.55 + pdf_loss_reduction)); } - if ((csm_score >= 4) && (p_pdf[_run] < 60000)) { + if ((chaos_score >= 4) && (p_pdf[_run] < 60000)) { p_pdf[_run] = 0; } - if ((csm_score >= 3) && (p_pdf[_run] < 20000)) { + if ((chaos_score >= 3) && (p_pdf[_run] < 20000)) { p_pdf[_run] = 0; } - if ((csm_score >= 2) && (p_pdf[_run] < 3000)) { + if ((chaos_score >= 2) && (p_pdf[_run] < 3000)) { p_pdf[_run] = 0; } - if ((csm_score >= 1) && (p_pdf[_run] < 1000)) { + if ((chaos_score >= 1) && (p_pdf[_run] < 1000)) { p_pdf[_run] = 0; } } - } else if (csm_attack == "sisters") { + } else if (chaos_attack == "sisters") { rand2 = (choose(2, 3, 4, 5, 6) * sisters_score) * choose(1, 1.25); if (rand1 > rand2) { after_combat_sisters -= 1; @@ -1000,10 +1000,10 @@ function scr_enemy_ai_a() { if (rand1 > rand2) { after_combat_ork_force -= 1; } - } else if (tyranids_attack == "csm") { - rand2 = (choose(1, 2, 3, 4, 5) * csm_score) * choose(1, 1.25); + } else if (tyranids_attack == "chaos") { + rand2 = (choose(1, 2, 3, 4, 5) * chaos_score) * choose(1, 1.25); if (rand1 > rand2) { - after_combat_csm -= 1; + after_combat_chaos -= 1; } } else if (tyranids_attack == "traitors") { rand2 = (choose(1, 2, 3, 4, 5) * traitors_score) * choose(1, 1.25); @@ -1095,15 +1095,15 @@ function scr_enemy_ai_a() { if (rand1 > rand2) { after_combat_ork_force -= 1; } - } else if (necrons_attack == "csm") { - rand2 = (choose(1, 2, 3, 4, 5) * csm_score) * choose(1, 1.25); + } else if (necrons_attack == "chaos") { + rand2 = (choose(1, 2, 3, 4, 5) * chaos_score) * choose(1, 1.25); if (rand1 > rand2) { - after_combat_csm -= 1; + after_combat_chaos -= 1; } } else if (necrons_attack == "traitors") { rand2 = (choose(1, 2, 3, 4, 5) * traitors_score) * choose(1, 1.25); if ((rand1 > rand2) && (traitors_score != 7)) { - after_combat_csm -= 1; + after_combat_chaos -= 1; } } else if (necrons_attack == "imp") { if (p_pdf[_run] > 0) { @@ -1184,7 +1184,7 @@ function scr_enemy_ai_a() { p_orks[_run] = after_combat_ork_force; p_tau[_run] = after_combat_tau; p_traitors[_run] = after_combat_traitor; - p_chaos[_run] = after_combat_csm; + p_chaos[_run] = after_combat_chaos; p_necrons[_run] = after_combat_necrons; if (p_tyranids[_run] != after_combat_tyranids) { p_tyranids[_run] = after_combat_tyranids; diff --git a/scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml b/scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml index a2c2b11d7a..f282f025e2 100644 --- a/scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml +++ b/scripts/scr_enemy_ai_c/scr_enemy_ai_c.gml @@ -253,7 +253,7 @@ function scr_enemy_ai_c() { } if ((gud != 0) && instance_exists(boat)) { - if (fleet_has_cargo("csm", boat)) { + if (fleet_has_cargo("chaos", boat)) { if (p_chaos[gud] < 4) { p_chaos[gud] += max(1, floor(boat.image_index * 0.5)); if (p_chaos[gud] > 4) { diff --git a/scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml b/scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml index 5ad3c137cc..aad2453bfd 100644 --- a/scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml +++ b/scripts/scr_enemy_ai_d/scr_enemy_ai_d.gml @@ -54,11 +54,11 @@ function scr_enemy_ai_d() { enemy1 = "Tau"; enemies += 1; } - if (p_traitors[i] >= minimum) { + if (p_chaos[i] >= minimum) { enemy1 = "Heretic"; enemies += 1; } - if (p_chaos[i] >= minimum) { + if (p_traitors[i] >= minimum) { enemy1 = "Chaos Space Marine"; enemies += 1; } diff --git a/scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml b/scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml index 1d976d438c..09e080f45a 100644 --- a/scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml +++ b/scripts/scr_enemy_ai_e/scr_enemy_ai_e.gml @@ -488,7 +488,7 @@ function scr_enemy_ai_e() { if (string_count("warband", trade_goods) > 0) { instance_create(x, y, obj_temp2); } - if (string_lower(trade_goods) == "csm") { + if (string_lower(trade_goods) == "chaos") { instance_create(x, y, obj_temp3); } } @@ -500,7 +500,7 @@ function scr_enemy_ai_e() { } } if (instance_exists(obj_temp3)) { - obj_turn_end.battle_special[obj_turn_end.battles] = "CSM"; + obj_turn_end.battle_special[obj_turn_end.battles] = "CHAOS"; with (obj_temp2) { instance_destroy(); } @@ -632,13 +632,13 @@ function scr_enemy_ai_e() { break; case 10: pause = has_problem_planet(run, "meeting") || has_problem_planet(run, "meeting_trap"); - if (p_guardsmen[run] + p_pdf[run] == 0 && p_player[run] > 0 && p_traitors[run] > 0 && !pause && obj_controller.faction_status[10] == "War") { + if (p_guardsmen[run] + p_pdf[run] == 0 && p_player[run] > 0 && p_chaos[run] > 0 && !pause && obj_controller.faction_status[10] == "War") { battle_opponent = 10; } break; case 11: pause = has_problem_planet(run, "meeting") || has_problem_planet(run, "meeting_trap"); - if (p_guardsmen[run] + p_pdf[run] == 0 && p_player[run] > 0 && p_chaos[run] > 0 && !pause && obj_controller.faction_status[10] == "War") { + if (p_guardsmen[run] + p_pdf[run] == 0 && p_player[run] > 0 && p_traitors[run] > 0 && !pause && obj_controller.faction_status[10] == "War") { battle_opponent = 11; } break; diff --git a/scripts/scr_event_code/scr_event_code.gml b/scripts/scr_event_code/scr_event_code.gml index 019af1f22a..7de483671d 100644 --- a/scripts/scr_event_code/scr_event_code.gml +++ b/scripts/scr_event_code/scr_event_code.gml @@ -102,7 +102,7 @@ function event_end_turn_action() { flee.capital_number = choose(0, 1); flee.frigate_number = choose(2, 3); flee.escort_number = choose(4, 5, 6); - flee.cargo_data.csm = true; + flee.cargo_data.chaos = true; obj_controller.chaos_fleets += 1; flee.action_x = star_id.x; flee.action_y = star_id.y; diff --git a/scripts/scr_fleet_functions/scr_fleet_functions.gml b/scripts/scr_fleet_functions/scr_fleet_functions.gml index 488a2b3ddf..9606acfcfe 100644 --- a/scripts/scr_fleet_functions/scr_fleet_functions.gml +++ b/scripts/scr_fleet_functions/scr_fleet_functions.gml @@ -791,7 +791,7 @@ function fleet_arrival_logic() { if (fleet_has_cargo("ork_warboss")) { cancel = true; } - if (fleet_has_cargo("csm")) { + if (fleet_has_cargo("chaos")) { cancel = true; } @@ -932,7 +932,7 @@ function fleet_arrival_logic() { mergus = 0; } - if ((owner == eFACTION.CHAOS) && fleet_has_cargo("csm") || fleet_has_cargo("warband")) { + if ((owner == eFACTION.CHAOS) && fleet_has_cargo("chaos") || fleet_has_cargo("warband")) { mergus = 0; } @@ -1031,9 +1031,9 @@ function fleet_arrival_logic() { x = old_x; y = old_y; - var _csm = fleet_has_cargo("warband"); + var _chaos = fleet_has_cargo("warband"); - if ((cur_star.x == old_x) && (cur_star.y == old_y) && (cur_star.owner == self.owner) && (cur_star.action == "") && ((owner == eFACTION.TAU) || (owner == eFACTION.CHAOS)) && (mergus == 10) && (!_csm)) { + if ((cur_star.x == old_x) && (cur_star.y == old_y) && (cur_star.owner == self.owner) && (cur_star.action == "") && ((owner == eFACTION.TAU) || (owner == eFACTION.CHAOS)) && (mergus == 10) && (!_chaos)) { // Move somewhere new var stue2 = noone; var goood = 0; From a2c1c61049ea24bdfe50cd869f12b6e63f71c5dd Mon Sep 17 00:00:00 2001 From: KestasV Date: Sat, 4 Jul 2026 02:07:22 +0300 Subject: [PATCH 076/140] Fix fleet action tick written to a deactivated instance; raids could go unlimited The drop launch ran instance_deactivate_all(true) and only afterwards ticked sh_target.acted += 1, writing to a deactivated fleet instance by stored id. Whether that write lands is runtime-dependent in GameMaker; when it silently no-ops (tester repro on the compiled build: unlimited raids from a stationary fleet, the third raid never blocked), acted never climbs and the raid gate (acted <= 1) always passes. The tick now runs before deactivation, on an unquestionably live instance. Diagnostic LOGGER lines added: each launch logs the fleet's acted value and each ship assault spend logs the ship's uses, so the session log verifies the action economy end to end. The per-ship assault spends were never affected since obj_ini is explicitly reactivated before them. Same deactivated-write pattern exists verbatim upstream, so vanilla's raid and legacy attack limits may be silently broken on compiled builds. --- .../scr_drop_select_function.gml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index 55be0d7a82..8cdac5a663 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -253,16 +253,23 @@ function drop_select_unit_selection() { obj_controller.last_raid_form = _chosen_form; } + // The fleet action tick used to run AFTER instance_deactivate_all, writing + // to a deactivated instance by id. Whether that write lands is + // runtime-dependent, and the tester's repro (unlimited raids from a + // stationary fleet, third raid never blocked) matches it silently failing + // in the compiled build: acted never climbed, so the raid gate + // (acted <= 1) always passed. Ticked before deactivation instead, with a + // proof line for the session log. + if (sh_target != noone) { + sh_target.acted += 1; + LOGGER.info($"DROP LAUNCH {((attack == 1) ? "attack" : "raid")}: fleet acted now {sh_target.acted}"); + } + instance_deactivate_all(true); instance_activate_object(obj_controller); instance_activate_object(obj_ini); instance_activate_object(obj_drop_select); - // 135 ; temporary balancing - if (sh_target != noone) { - sh_target.acted += 1; - } - // Ship assault economy: each distinct ship contributing units to this // ground assault spends one support use this turn (SHIP_ASSAULTS_PER_TURN // max). fleet.acted above still ticks so raid and bombardment gating are @@ -278,6 +285,7 @@ function drop_select_unit_selection() { if (!array_contains(_spent_ships, _sel_ship)) { array_push(_spent_ships, _sel_ship); ship_assault_spend(_sel_ship); + LOGGER.info($"ASSAULT SPEND ship {_sel_ship}: uses now {ship_assaults_used(_sel_ship)}/{SHIP_ASSAULTS_PER_TURN}"); } } else { _local_participated = true; From 4287c307e22bcaafe08a16604839eb882eee45ba Mon Sep 17 00:00:00 2001 From: KestasV Date: Sat, 4 Jul 2026 02:30:02 +0300 Subject: [PATCH 077/140] Fix combat log overwriting its newest message and going silent on phantom counts The combat log queue used the messages counter as both the queue count and the write index. Displaying a message clears a front slot and decrements the count, so until the next compaction pass the count points at the newest queued message: any line posted in that window silently overwrote it and inflated the counter by one phantom. This destroyed arbitrary lines in message-heavy turns (reported as vehicle deaths never appearing: the "1 Rhino lost" lines were generated correctly by damage_vehicles/scr_flavor2 and then overwritten), and the accumulated phantoms left battles with messages > 0 over an empty queue, the pump spinning and the log permanently silent while fighting continued. Column piercing amplified the exposure by multiplying messages per enemy turn but did not cause it; the post-at-count pattern is verbatim vanilla. All three post sites (add_battle_log_message and both inline posts in scr_flavor2) now append via battle_log_tail_slot(), the first free slot after the last queued message, preserving chronological order and dropping rather than overwriting when genuinely full. Alarm_3 additionally self-heals a nonzero count over an empty queue instead of spinning forever. --- objects/obj_ncombat/Alarm_3.gml | 6 ++++++ scripts/scr_flavor/scr_flavor.gml | 31 +++++++++++++++++++++++++++-- scripts/scr_flavor2/scr_flavor2.gml | 30 ++++++++++++++++++---------- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/objects/obj_ncombat/Alarm_3.gml b/objects/obj_ncombat/Alarm_3.gml index 4fe55137ed..060e1ffd6b 100644 --- a/objects/obj_ncombat/Alarm_3.gml +++ b/objects/obj_ncombat/Alarm_3.gml @@ -103,6 +103,12 @@ if (messages > 0) { message_sz[that] = 0; message_priority[that] = 0; messages -= 1; + } else { + // Self-heal: no queued content but a nonzero count means the counter drifted + // (phantom messages from the old post-at-count overwrite bug, or any future + // desync). Without this the pump spins forever on an empty queue and the log + // goes silent for the rest of the battle. + messages = 0; } alarm[3] = 2; diff --git a/scripts/scr_flavor/scr_flavor.gml b/scripts/scr_flavor/scr_flavor.gml index 5e272f6ffb..85df970ebd 100644 --- a/scripts/scr_flavor/scr_flavor.gml +++ b/scripts/scr_flavor/scr_flavor.gml @@ -1,3 +1,27 @@ +/// @function battle_log_tail_slot +/// @desc First free slot AFTER the last queued message. The old posting scheme wrote +/// at index `messages`, which is a COUNT, not a tail pointer: every displayed message +/// clears a slot at the FRONT of the queue and decrements the count, so until the +/// next compaction tick the count points AT the newest queued message. Any post +/// landing in that window overwrote it (silently destroying lines, vehicle-loss +/// lines in message-heavy piercing turns being the reported casualties) and inflated +/// `messages` by one phantom per overwrite, which is how battles ended with the pump +/// spinning on a nonzero count over empty slots, printing nothing. +/// @returns {real} slot index, or -1 when the log is genuinely full (drop, never overwrite) +function battle_log_tail_slot() { + var _last = 0; + for (var _m = COMBAT_LOG_CAPACITY; _m >= 1; _m--) { + if (obj_ncombat.message[_m] != "") { + _last = _m; + break; + } + } + if (_last >= COMBAT_LOG_CAPACITY) { + return -1; + } + return _last + 1; +} + /// @function add_battle_log_message /// @param {string} _message - The message text to add to the battle log /// @param {real} [_message_size=0] - The size/importance of the message (higher values = higher display priority; affects sorting order) @@ -5,11 +29,14 @@ /// @returns {real} The index of the newly added message function add_battle_log_message(_message, _message_size = 0, _message_priority = 0) { if (instance_exists(obj_ncombat)) { + var _message_index = battle_log_tail_slot(); + if (_message_index < 0) { + return -1; + } obj_ncombat.messages++; - var _message_index = obj_ncombat.messages; obj_ncombat.message[_message_index] = _message; - obj_ncombat.message_sz[_message_index] = _message_size + (0.5 - (obj_ncombat.messages / 100)); + obj_ncombat.message_sz[_message_index] = _message_size + (0.5 - (_message_index / 100)); obj_ncombat.message_priority[_message_index] = _message_priority; return _message_index; diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index 24e87dfb49..13d4f89e24 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -433,11 +433,15 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } if (string_length(mes) > 3) { - obj_ncombat.messages += 1; - obj_ncombat.message[obj_ncombat.messages] = mes; - obj_ncombat.message_sz[obj_ncombat.messages] = 999; - obj_ncombat.message_priority[obj_ncombat.messages] = 0; - obj_ncombat.alarm[3] = 2; + // Tail slot, not the messages count; see battle_log_tail_slot in scr_flavor. + var _log_slot = battle_log_tail_slot(); + if (_log_slot >= 0) { + obj_ncombat.messages += 1; + obj_ncombat.message[_log_slot] = mes; + obj_ncombat.message_sz[_log_slot] = 999; + obj_ncombat.message_priority[_log_slot] = 0; + obj_ncombat.alarm[3] = 2; + } } if (obj_nfort.hp[1] <= 0) { s = 0; @@ -566,10 +570,16 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } else if ((lost_units_count == 0) && (hostile_shots > 0) && target_is_vehicle && (damage_severity < 0.10)) { _enemy_priority = 135; } - obj_ncombat.messages += 1; - obj_ncombat.message[obj_ncombat.messages] = mes; - obj_ncombat.message_sz[obj_ncombat.messages] = lost_units_count + (0.5 - (obj_ncombat.messages / 100)); - obj_ncombat.message_priority[obj_ncombat.messages] = _enemy_priority; - obj_ncombat.alarm[3] = 2; + // Posted through the tail slot, not the messages count: posting at the count + // overwrote the newest queued message whenever a display had just opened a + // front gap (see battle_log_tail_slot in scr_flavor). + var _log_slot = battle_log_tail_slot(); + if (_log_slot >= 0) { + obj_ncombat.messages += 1; + obj_ncombat.message[_log_slot] = mes; + obj_ncombat.message_sz[_log_slot] = lost_units_count + (0.5 - (_log_slot / 100)); + obj_ncombat.message_priority[_log_slot] = _enemy_priority; + obj_ncombat.alarm[3] = 2; + } } } From 199faefe2644ab52f08e8f569c91e500efb48cf5 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 01:43:50 +0300 Subject: [PATCH 078/140] Basic combat orders: per-block advance/hold toggle with friendly leapfrogging Adds the first layer of tactical combat control. Every player block carries a move_order ("advance" or "hold"), seeded on its first tick from the vanilla movement rule (raids and attacks advance, defense and the static formation hold), so untouched battles are unchanged. Left-clicking a block's bar toggles its order, using the drawn bar's existing hit() hover box (the same hitbox as the Row Composition panel) rather than the instance sprite mask; a green chevron marks advancing blocks and an orange bar holding ones. Advancing blocks may leapfrog: when the slot ahead is occupied by a FRIENDLY block, move_unit_block (new leapfrog parameter) hops over the contiguous friendly column to the first free slot beyond, probing at most PLAYER_LEAPFROG_MAX_COLUMNS (6) columns and never landing on or vaulting past an enemy block. This also resolves the oldest movement limitation in the mod: rear-placed blocks (the original Guard screen problem) can finally pass through their own line on order. The Defenses pseudo-block takes no orders, no clicks, no marker, and never moves. Orders are combat-scoped instance state; no save changes. --- objects/obj_pnunit/Alarm_0.gml | 13 +++++++-- objects/obj_pnunit/Create_0.gml | 4 +++ objects/obj_pnunit/Draw_0.gml | 15 ++++++++++ objects/obj_pnunit/Step_0.gml | 9 ++++++ scripts/macros/macros.gml | 5 ++++ .../scr_punit_combat_heplers.gml | 29 +++++++++++++++++-- 6 files changed, 70 insertions(+), 5 deletions(-) diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index 718f695e08..289cfdc777 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -10,8 +10,17 @@ try { enemy = instance_nearest(0, y, obj_enunit); // Left most enemy - if (obj_ncombat.dropping || (!obj_ncombat.defending && obj_ncombat.formation_set != 2)) { - move_unit_block("east"); + // Basic combat orders: every block carries a move_order ("advance" or "hold"), + // seeded on its first tick from the vanilla movement rule (raids and attacks + // advance, defense and the static formation hold) and toggled by clicking the + // block's bar (obj_pnunit Step_0). Advancing blocks may leapfrog over friendly + // blocks directly ahead. The Defenses pseudo-block takes no orders and never + // moves. + if (move_order == "") { + move_order = (obj_ncombat.dropping || (!obj_ncombat.defending && obj_ncombat.formation_set != 2)) ? "advance" : "hold"; + } + if ((move_order == "advance") && (veh_type[1] != "Defenses")) { + move_unit_block("east", 1, false, true); } if (!instance_exists(enemy)) { diff --git a/objects/obj_pnunit/Create_0.gml b/objects/obj_pnunit/Create_0.gml index 35b3bb9ace..2dc70154c8 100644 --- a/objects/obj_pnunit/Create_0.gml +++ b/objects/obj_pnunit/Create_0.gml @@ -17,6 +17,10 @@ composition_string = ""; column_size = 0; +// Basic combat orders: "" until seeded from the battle type on the block's first +// Alarm_0 tick, then "advance" or "hold", toggled by clicking the block's bar. +move_order = ""; + centerline_offset = 0; pos = 880; draw_size = 0; diff --git a/objects/obj_pnunit/Draw_0.gml b/objects/obj_pnunit/Draw_0.gml index 755c8bd33a..08ede57674 100644 --- a/objects/obj_pnunit/Draw_0.gml +++ b/objects/obj_pnunit/Draw_0.gml @@ -28,6 +28,21 @@ if (draw_size > 0) { draw_rectangle(x1, y1, x2, y2, 0); + // Order indicator (basic combat orders): a green chevron above advancing blocks, + // an orange bar above holding ones, so each column's order reads at a glance. + // The Defenses pseudo-block takes no orders and gets no marker. + if ((move_order != "") && (veh_type[1] != "Defenses")) { + draw_set_font(fnt_40k_14b); + if (move_order == "advance") { + draw_set_color(c_lime); + draw_text(x1, y1 - 20, ">"); + } else { + draw_set_color(c_orange); + draw_text(x1, y1 - 20, "="); + } + draw_set_color(c_red); + } + if (hit()) { if (unit_count != unit_count_old) { unit_count_old = unit_count; diff --git a/objects/obj_pnunit/Step_0.gml b/objects/obj_pnunit/Step_0.gml index a515dacaa7..5def3ed066 100644 --- a/objects/obj_pnunit/Step_0.gml +++ b/objects/obj_pnunit/Step_0.gml @@ -5,3 +5,12 @@ array_resize(lost_num, 0); update_block_size(); update_block_unit_count(); + +// Basic combat orders: left-clicking a block's bar toggles it between advancing and +// holding. hit() is the drawn bar's own hover box (fadein-guarded), the same hitbox +// the Row Composition panel keys off, so clicks land exactly where the player is +// pointing rather than on the instance's sprite mask. Orders only exist once seeded +// (move_order != ""), and the Defenses pseudo-block is not orderable. +if (mouse_check_button_pressed(mb_left) && (move_order != "") && (veh_type[1] != "Defenses") && hit()) { + move_order = (move_order == "advance") ? "hold" : "advance"; +} diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 8de3ea1380..79ab7a2758 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -52,6 +52,11 @@ #macro PLAYER_PIERCE_RANK2_SHOTS 0.66 #macro PLAYER_PIERCE_RANK3_SHOTS 0.33 +// Basic combat orders: an advancing block that finds a friendly block directly +// ahead may leapfrog over it, landing on the first free slot beyond, probing at +// most this many columns. It never lands on or vaults past an enemy block. +#macro PLAYER_LEAPFROG_MAX_COLUMNS 6 + // Ship assault economy: how many ground assaults each ship can support per turn. The old // rule capped the whole fleet at 2 attacks per turn regardless of size, so deploying // everything on every assault cost nothing. Now each carrying ship supports this many diff --git a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml index 0364003fcc..d1157d6b41 100644 --- a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml +++ b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml @@ -170,25 +170,48 @@ function block_position_collision(position_x, position_y) { /// @param {string} direction In what direction to move ("east" or "west") /// @param {real} blocks How far to move (in unit blocks) /// @param {bool} allow_collision Are unit blocks allowed to passthrough other unit blocks +/// @param {bool} leapfrog When the destination is blocked by a FRIENDLY block, hop over the +/// contiguous friendly column(s) to the first free slot beyond (probing at most +/// PLAYER_LEAPFROG_MAX_COLUMNS columns). Never lands on or vaults past an enemy block, so +/// contact with the enemy is still made by normal one-step movement and engagement. /// @return {bool} /// @self Asset.GMObject.obj_pnunit -function move_unit_block(direction, blocks = 1, allow_collision = false) { +function move_unit_block(direction, blocks = 1, allow_collision = false, leapfrog = false) { try { var distance = 10 * blocks; var _new_pos = x; + var _step = 0; if (direction == "east") { + _step = distance; _new_pos = x + distance; } else if (direction == "west") { + _step = -distance; _new_pos = x - distance; } if (allow_collision == true || !block_position_collision(_new_pos, y)) { x = _new_pos; return true; - } else { - return false; } + + // Leapfrogging (basic combat orders): only when the immediate blocker is a + // friendly block and not an enemy. + if (leapfrog && (_step != 0) && collision_point(_new_pos, y, obj_pnunit, 0, 1) && !collision_point(_new_pos, y, obj_enunit, 0, 1)) { + var _hop = _new_pos + _step; + repeat (PLAYER_LEAPFROG_MAX_COLUMNS) { + if (collision_point(_hop, y, obj_enunit, 0, 1)) { + break; + } + if (!collision_point(_hop, y, obj_pnunit, 0, 1)) { + x = _hop; + return true; + } + _hop += _step; + } + } + + return false; } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); } From 3bcd4e2f9381182facb5f36e44fb6192c8f61fa4 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 01:50:01 +0300 Subject: [PATCH 079/140] Spawn-side chaos/heretics renumbering, empty hulks, ghost bombard target, necron chip crash, Eldar discovery encounters grant intel clues instead of bypassing the reveal gate Completes the chaos/heretics renumbering (173a6500) on the spawn side, which that commit did not touch: the threat-scaled cult/traitor horde compositions were gated on CHAOS while heretic worlds now arrive as HERETICS, so every heretic battle spawned the constant small CSM warband (~5 CSM + 30 cultists at all strengths); gates swapped to match the renumbering. Space hulk defender spawns only handled ORK/TYRANIDS/CHAOS, and hulk garrisons (rolled CHAOS, stored in p_traitors) now arrive as HERETICS, so heretic hulks boarded empty; the hulk branch accepts both. The bombardment screen validates its initial target on first draw, skipping zero-strength factions instead of opening on "Chaos, Strength: 0". Fixes a first-turn crash in damage_vehicles: the Necron minimum-chip rule read `enemy` in obj_pnunit scope (the block's target instance, unset before its first tick) instead of obj_ncombat.enemy. Both vanilla craftworld discovery paths (arriving at an Eldar-held system, and the 5% proximity roll near the hidden craftworld) set known[ELDAR] directly, bypassing the intelligence hunt: the tester's craftworld revealed at two clues by merely entering a system with Eldar forces. Both paths now call eldar_intel_grant(), so space encounters feed the hunt as one clue each and the craftworld stays hidden until ELDAR_INTEL_REQUIRED clues; fleet un-hiding happens only in the reveal path. --- objects/obj_bomb_select/Create_0.gml | 3 +++ objects/obj_bomb_select/Draw_0.gml | 14 ++++++++++++++ objects/obj_ncombat/Alarm_0.gml | 19 +++++++++++++++---- objects/obj_p_fleet/Alarm_1.gml | 12 ++++++++---- scripts/scr_clean/scr_clean.gml | 7 ++++++- 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/objects/obj_bomb_select/Create_0.gml b/objects/obj_bomb_select/Create_0.gml index 8a1ade408e..4503b12d6d 100644 --- a/objects/obj_bomb_select/Create_0.gml +++ b/objects/obj_bomb_select/Create_0.gml @@ -1,6 +1,9 @@ // Resets vars and also checks if target can be bombarded ship_names = ""; p_target = 0; +// Lazy initial-target validation flag (see Draw_0): honest presence numbers can +// leave the default bombard target on a zero-strength faction ("Chaos, Strength: 0"). +target_initialized = 0; max_ships = 0; ships_selected = 0; target = 0; diff --git a/objects/obj_bomb_select/Draw_0.gml b/objects/obj_bomb_select/Draw_0.gml index 60faedc28b..70be3341db 100644 --- a/objects/obj_bomb_select/Draw_0.gml +++ b/objects/obj_bomb_select/Draw_0.gml @@ -95,6 +95,20 @@ if ((max_ships > 0) && instance_exists(obj_star_select)) { var str_string = ""; // TODO a centralised point to be able to fetch display names from factions identifying number + // First-draw validation: if the default target has no force, advance to the + // first faction that does, so the screen never opens on a ghost target the + // player must cycle past. + if (target_initialized != 1) { + target_initialized = 1; + if (p_data.planet_forces[target] <= 0) { + for (var _t0 = 2; _t0 < array_length(p_data.planet_forces); _t0++) { + if (p_data.planet_forces[_t0] > 0) { + target = _t0; + break; + } + } + } + } str = floor(p_data.planet_forces[target]); if (target == 2.5) { str = determine_pdf_defence(p_data.pdf,, p_data.fortification_level)[0]; diff --git a/objects/obj_ncombat/Alarm_0.gml b/objects/obj_ncombat/Alarm_0.gml index 0ca6c3665d..69582cd5c4 100644 --- a/objects/obj_ncombat/Alarm_0.gml +++ b/objects/obj_ncombat/Alarm_0.gml @@ -409,7 +409,11 @@ try { hulk_forces = make; } // * CSM Space Hulk * - if (enemy == eFACTION.CHAOS) { + if ((enemy == eFACTION.CHAOS) || (enemy == eFACTION.HERETICS)) { + // Hulk garrisons roll faction CHAOS but store strength in p_traitors + // (obj_star Alarm_0), so under the corrected numbering their battles + // arrive as HERETICS: without this the hulk spawned no defenders at all + // (reported four out of four boardings empty). modi = random_range(0.80, 1.20) + 1; make = round(max(3, player_starting_dudes * modi)); @@ -2051,7 +2055,12 @@ try { } // ** Chaos Forces ** - if ((enemy == eFACTION.CHAOS) && (battle_special != "ship_demon") && (battle_special != "fallen1") && (battle_special != "fallen2") && (battle_special != "WL10_reveal") && (battle_special != "WL10_later") && (string_count("cs_meeting_battle", battle_special) == 0)) { + // Spawn-side half of the chaos/heretics renumbering (upstream 173a6500 flipped + // battle RESOLUTION but not these composition gates): the threat-scaled cult and + // traitor horde compositions belong to HERETICS worlds (p_traitors), which now + // arrive as eFACTION.HERETICS. Before this swap they received the small CSM + // warband below (a constant ~5 CSM + 30 cultists at every strength). + if ((enemy == eFACTION.HERETICS) && (battle_special != "ship_demon") && (battle_special != "fallen1") && (battle_special != "fallen2") && (battle_special != "WL10_reveal") && (battle_special != "WL10_later") && (string_count("cs_meeting_battle", battle_special) == 0)) { // Small Chaos Cult Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -2491,7 +2500,9 @@ try { } // ** Chaos Space Marines Forces ** - if ((enemy == eFACTION.HERETICS) && (battle_special != "ChaosWarband") && (string_count("cs_meeting_battle", battle_special) == 0)) { + // The CSM warband compositions belong to true Chaos forces (p_chaos), which now + // arrive as eFACTION.CHAOS. Second half of the spawn-side renumbering swap. + if ((enemy == eFACTION.CHAOS) && (battle_special != "ChaosWarband") && (string_count("cs_meeting_battle", battle_special) == 0)) { // Small CSM Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -2712,7 +2723,7 @@ try { } // ** World Eaters Forces ** - if ((enemy == eFACTION.HERETICS) && (battle_special == "ChaosWarband")) { + if ((enemy == eFACTION.CHAOS) && (battle_special == "ChaosWarband")) { // Small WE Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); diff --git a/objects/obj_p_fleet/Alarm_1.gml b/objects/obj_p_fleet/Alarm_1.gml index ccd0e17df9..2b6e7383f2 100644 --- a/objects/obj_p_fleet/Alarm_1.gml +++ b/objects/obj_p_fleet/Alarm_1.gml @@ -94,7 +94,11 @@ try { } } if ((steh.owner == eFACTION.ELDAR) && (obj_controller.faction_defeated[6] == 0) && (obj_controller.known[eFACTION.ELDAR] == 0)) { - obj_controller.known[eFACTION.ELDAR] = 1; + // Encountering an Eldar-held system yields one intelligence clue + // rather than instantly revealing the craftworld: the reveal stays + // gated behind ELDAR_INTEL_REQUIRED clues (tester's craftworld + // appeared at 2 clues by merely entering such a system). + eldar_intel_grant(); } if ((steh.owner == eFACTION.TAU) && (obj_controller.faction_defeated[8] == 0) && (obj_controller.known[eFACTION.TAU] == 0)) { obj_controller.known[eFACTION.TAU] = 1; @@ -142,11 +146,11 @@ try { dist = point_distance(x, y, steh.old_x, steh.old_y); if ((rando >= 95) && (dist <= 300)) { - obj_controller.known[eFACTION.ELDAR] = 1; - scr_alert("green", "elfs", "Eldar Craftworld discovered.", steh.old_x, steh.old_y); + // A lucky close pass grants a clue, never a full reveal. + eldar_intel_grant(); with (obj_en_fleet) { if (owner == eFACTION.ELDAR) { - image_alpha = 1; + // Un-hiding now happens in the intel reveal path only. } } } diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index e6192360d2..19b7a5a189 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -523,7 +523,12 @@ function damage_vehicles(_damage_data, _shots, _damage, _weapon_index, _arp = 0) if (_modified_damage < 0) { _modified_damage = 0; } - if (enemy == 13 && _modified_damage < 1) { + // This ran in the obj_pnunit context, where `enemy` is the block's TARGET + // instance variable (set in its own Alarm_0), so enemy fire landing before + // the block's first tick crashed with an unset read; and comparing a target + // instance id to 13 was wrong regardless. The battle faction lives on + // obj_ncombat. + if (obj_ncombat.enemy == eFACTION.NECRONS && _modified_damage < 1) { _modified_damage = 1; } var _veh_hp_before = veh_hp[veh_index]; From ebbf70b9011ba81d3feb1447ee527e22388184dd Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 02:27:53 +0300 Subject: [PATCH 080/140] Overkill spill stops at air gaps: cross-formation carry requires touching columns The player volley kill cascade spills surplus damage across ranks and, once a formation is wiped, into the formation behind it, but get_next_enemy_formation had no distance concept: spill leapt any gap, so 11 Heavy Thunder Hammers that overkilled a Terminator block slaughtered cultists standing two empty rows back across open ground (tester report). Cross-formation spill now requires the next formation to stand directly behind the wiped one, within OVERKILL_SPILL_MAX_GAP (15px against the 10px column grid); an air gap ends the spill for melee and ranged alike. Within-block rank spill is unchanged, and formation spacing now works as a deliberate firebreak on both sides. --- scripts/macros/macros.gml | 6 ++++++ scripts/scr_shoot/scr_shoot.gml | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 79ab7a2758..1f160377c7 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -280,3 +280,9 @@ enum eIN_GAME_MENU_EFFECT { BACK_FROM_SETTINGS = 25, CLOSE_SAVELOAD = 30 } + +// Overkill spill from a wiped enemy formation only reaches a formation standing +// directly behind it (touching columns, 10px apart; 15 tolerates float jitter). An +// air gap stops the spill: neither hammer blows nor the torrent of fire leap across +// open ground to a formation two rows back. +#macro OVERKILL_SPILL_MAX_GAP 15 diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index a13d75f0f9..d4eed64437 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -408,10 +408,19 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat // Next target: a living rank in this formation, else the formation behind. var next_rank = find_next_alive_rank(spill_block, spill_block.dudes_vehicle[spill_rank]); if (next_rank == -1) { + var _spent_x = spill_block.x; spill_block = get_next_enemy_formation(spill_block); if (spill_block == noone) { break; } + // Overkill only spills into a formation standing directly + // behind the one just wiped (touching columns). An air gap + // stops it: the tester's cultists two rows back, with open + // ground between them and the CSM, were being slaughtered + // by thunder hammer spill leaping the gap. + if (abs(spill_block.x - _spent_x) > OVERKILL_SPILL_MAX_GAP) { + break; + } array_push(touched_blocks, spill_block); next_rank = find_next_alive_rank(spill_block, -1); if (next_rank == -1) { From abff2194aadd984209d006223f676a50d3cb0208 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 02:41:25 +0300 Subject: [PATCH 081/140] Eldar clues granted only on full planetary clearance; space encounters once per campaign Intelligence clues were granted per ground victory against Eldar, so repeated raids against one warhost farmed the craftworld reveal (tester: three raids, three clues). The grant now fires at the force write-back in battle resolution, only when the warhost's strength reaches zero, so clearing the planet is what yields intelligence and raids only count when they land the finishing blow. The space-encounter clue paths (arriving at an Eldar-held system, the lucky proximity pass) were similarly farmable by re-entering a system; both now share a once-per-campaign first-contact flag (guarded instance variable, no save changes). The craftworld reveal remains gated at ELDAR_INTEL_REQUIRED clues. --- objects/obj_ncombat/Alarm_5.gml | 15 +++++++++------ objects/obj_p_fleet/Alarm_1.gml | 27 ++++++++++++++++++++------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/objects/obj_ncombat/Alarm_5.gml b/objects/obj_ncombat/Alarm_5.gml index dd8258b849..d236db6ada 100644 --- a/objects/obj_ncombat/Alarm_5.gml +++ b/objects/obj_ncombat/Alarm_5.gml @@ -459,12 +459,6 @@ if (defeat == 0 && _reduce_power) { part10 = "Necrons"; } - // Eldar craftworld hunt: a ground victory over an Eldar warhost yields one piece - // of intelligence toward locating the hidden craftworld. Only while it remains - // hidden; battles after the reveal grant nothing. - if ((enemy == eFACTION.ELDAR) && (obj_controller.known[eFACTION.ELDAR] == 0)) { - eldar_intel_grant(); - } if (instance_exists(battle_object) && (enemy_power > 2)) { if (awake_tomb_world(battle_object.p_feature[battle_id]) != 0) { @@ -481,6 +475,15 @@ if (defeat == 0 && _reduce_power) { new_power = enemy_power - power_reduction; new_power = max(new_power, 0); + // Eldar craftworld hunt: intelligence is recovered only when the warhost is + // wiped from the planet entirely (its force reaches zero), never per battle, + // so repeated raids against the same warhost cannot farm clues (tester found + // three raids on one world yielded three clues). Only while the craftworld + // remains hidden. + if ((enemy == eFACTION.ELDAR) && (new_power <= 0) && (obj_controller.known[eFACTION.ELDAR] == 0)) { + eldar_intel_grant(); + } + // Give some money for killing enemies? var _quad_factor = 6; requisition_reward = _quad_factor * sqr(threat); diff --git a/objects/obj_p_fleet/Alarm_1.gml b/objects/obj_p_fleet/Alarm_1.gml index 2b6e7383f2..94144db28f 100644 --- a/objects/obj_p_fleet/Alarm_1.gml +++ b/objects/obj_p_fleet/Alarm_1.gml @@ -94,11 +94,17 @@ try { } } if ((steh.owner == eFACTION.ELDAR) && (obj_controller.faction_defeated[6] == 0) && (obj_controller.known[eFACTION.ELDAR] == 0)) { - // Encountering an Eldar-held system yields one intelligence clue - // rather than instantly revealing the craftworld: the reveal stays - // gated behind ELDAR_INTEL_REQUIRED clues (tester's craftworld - // appeared at 2 clues by merely entering such a system). - eldar_intel_grant(); + // Encountering an Eldar-held system yields first-contact + // intelligence, once per campaign (hopping in and out of the system + // must not farm clues); the reveal stays gated behind + // ELDAR_INTEL_REQUIRED clues. + if (!variable_instance_exists(obj_controller, "eldar_space_clue_granted")) { + obj_controller.eldar_space_clue_granted = false; + } + if (!obj_controller.eldar_space_clue_granted) { + obj_controller.eldar_space_clue_granted = true; + eldar_intel_grant(); + } } if ((steh.owner == eFACTION.TAU) && (obj_controller.faction_defeated[8] == 0) && (obj_controller.known[eFACTION.TAU] == 0)) { obj_controller.known[eFACTION.TAU] = 1; @@ -146,8 +152,15 @@ try { dist = point_distance(x, y, steh.old_x, steh.old_y); if ((rando >= 95) && (dist <= 300)) { - // A lucky close pass grants a clue, never a full reveal. - eldar_intel_grant(); + // A lucky close pass grants the same once-per-campaign + // first-contact clue, never a full reveal. + if (!variable_instance_exists(obj_controller, "eldar_space_clue_granted")) { + obj_controller.eldar_space_clue_granted = false; + } + if (!obj_controller.eldar_space_clue_granted) { + obj_controller.eldar_space_clue_granted = true; + eldar_intel_grant(); + } with (obj_en_fleet) { if (owner == eFACTION.ELDAR) { // Un-hiding now happens in the intel reveal path only. From 5cb08561fccfcf008cecb7a89c7f1ce0d1b128b2 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 06:27:07 +0300 Subject: [PATCH 082/140] Revealed craftworld is clickable and targetable: vision granted at reveal, self-healing gate The craftworld spawns unseen and nothing ever granted its fog-of-war vision flag; the reveal only flips known, which un-hides the drawing. obj_star Mouse_50 exits on vision == 0 before any interaction, so a revealed craftworld rendered but rejected every click: it could not be selected or set as a travel destination (move orders fell to the neighboring system, so fleets never registered as present) and therefore never offered fleet combat or Attack/Bombard. Vision is now granted in the reveal path for new campaigns, and the Mouse_50 craftworld gate sets vision itself when the craftworld is known, self-healing saves where the reveal already happened. Noted for later, not fixed here: naval battle results can overcount escort losses ("4 of my 3 escorts", likely vanilla), and the craftworld population renders oddly ("8..02", cosmetic formatting). --- objects/obj_star/Mouse_50.gml | 14 ++++++++++++-- .../scr_controller_helpers.gml | 3 +++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/objects/obj_star/Mouse_50.gml b/objects/obj_star/Mouse_50.gml index 827c27f6db..8e8a6f7652 100644 --- a/objects/obj_star/Mouse_50.gml +++ b/objects/obj_star/Mouse_50.gml @@ -12,8 +12,18 @@ if (!global.ui_click_lock) { if (obj_controller.location_viewer.is_entered) { exit; } - if ((p_type[1] == "Craftworld") && (obj_controller.known[eFACTION.ELDAR] == 0)) { - exit; + if (p_type[1] == "Craftworld") { + if (obj_controller.known[eFACTION.ELDAR] == 0) { + exit; + } + // A revealed craftworld is fully visible and clickable regardless of the + // fog-of-war vision flag. It spawns unseen at the galaxy's edge and nothing + // ever granted it vision, so the star drew after the reveal but rejected + // every click: it could not be selected, targeted for travel, or attacked + // (tester arrived "next to" it because move orders fell to the neighboring + // system). Setting vision here also self-heals saves where the reveal + // already happened. + vision = 1; } if (vision == 0) { exit; diff --git a/scripts/scr_controller_helpers/scr_controller_helpers.gml b/scripts/scr_controller_helpers/scr_controller_helpers.gml index b0267b4bbb..e05fa1113e 100644 --- a/scripts/scr_controller_helpers/scr_controller_helpers.gml +++ b/scripts/scr_controller_helpers/scr_controller_helpers.gml @@ -569,6 +569,9 @@ function eldar_incursion_tick() { obj_controller.eldar_reveal_alert_pending = false; with (obj_star) { if (p_type[1] == "Craftworld") { + // Grant fog-of-war vision with the reveal so the craftworld is + // immediately selectable and targetable (see obj_star Mouse_50). + vision = 1; scr_alert("green", "elfs", "Eldar Craftworld discovered.", x, y); scr_event_log("green", "Eldar Craftworld discovered."); } From fede9d9482099cfdd39b219decd9e28a7a126d87 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 06:27:52 +0300 Subject: [PATCH 083/140] Leapfrogging restricted to manually ordered blocks; auto-advance keeps formation The combat-orders leapfrog fired during default auto-advance: blocks moving in the same tick routinely find the block ahead still in its slot (processing order, or a front line engaged and stationary), and where vanilla stalled them, preserving formation shape, the leapfrog vaulted them over their own line. A raid with no orders given reordered itself, tacticals jumping the engaged front (tester report). Blocks now carry an order_manual flag set only when the player clicks them: untouched blocks advance with vanilla stall behavior and formations hold their authored shape, while clicked blocks retain full leapfrog movement. This matches the feature's intent: leapfrogging belongs to orders the player gives, not the ambient march. --- objects/obj_pnunit/Alarm_0.gml | 6 +++++- objects/obj_pnunit/Create_0.gml | 5 +++++ objects/obj_pnunit/Step_0.gml | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index 289cfdc777..a2c86424c7 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -20,7 +20,11 @@ try { move_order = (obj_ncombat.dropping || (!obj_ncombat.defending && obj_ncombat.formation_set != 2)) ? "advance" : "hold"; } if ((move_order == "advance") && (veh_type[1] != "Defenses")) { - move_unit_block("east", 1, false, true); + // Leapfrogging only for blocks the player has clicked (order_manual): + // default auto-advance keeps vanilla stall behavior, otherwise same-tick + // processing order and an engaged front line make rear blocks vault their + // own formation with no orders given. + move_unit_block("east", 1, false, order_manual); } if (!instance_exists(enemy)) { diff --git a/objects/obj_pnunit/Create_0.gml b/objects/obj_pnunit/Create_0.gml index 2dc70154c8..aa8bda9a30 100644 --- a/objects/obj_pnunit/Create_0.gml +++ b/objects/obj_pnunit/Create_0.gml @@ -20,6 +20,11 @@ column_size = 0; // Basic combat orders: "" until seeded from the battle type on the block's first // Alarm_0 tick, then "advance" or "hold", toggled by clicking the block's bar. move_order = ""; +// True only once the player has clicked this block. Leapfrogging is reserved for +// manually ordered blocks: the seeded auto-advance must keep vanilla stall behavior +// or formations scramble on their own (tester's raid reordered itself with no +// orders given, tacticals vaulting the engaged front line). +order_manual = false; centerline_offset = 0; pos = 880; diff --git a/objects/obj_pnunit/Step_0.gml b/objects/obj_pnunit/Step_0.gml index 5def3ed066..2a6f612780 100644 --- a/objects/obj_pnunit/Step_0.gml +++ b/objects/obj_pnunit/Step_0.gml @@ -13,4 +13,7 @@ update_block_unit_count(); // (move_order != ""), and the Defenses pseudo-block is not orderable. if (mouse_check_button_pressed(mb_left) && (move_order != "") && (veh_type[1] != "Defenses") && hit()) { move_order = (move_order == "advance") ? "hold" : "advance"; + // Player-issued orders unlock leapfrogging for this block; untouched blocks + // keep vanilla movement (stall behind friendlies) so formations hold shape. + order_manual = true; } From 5e1923300be7fa433710cb09722184c16ed9b07f Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 07:03:41 +0300 Subject: [PATCH 084/140] Update ChapterMaster.yyp --- ChapterMaster.yyp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index b9f19aeacd..4dff18ed57 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -721,7 +721,6 @@ {"id":{"name":"Armamentarium","path":"scripts/Armamentarium/Armamentarium.yy",},}, {"id":{"name":"ColourItem","path":"scripts/ColourItem/ColourItem.yy",},}, {"id":{"name":"ColourPicker","path":"scripts/ColourPicker/ColourPicker.yy",},}, - {"id":{"name":"CombatLog","path":"scripts/CombatLog/CombatLog.yy",},}, {"id":{"name":"DebugView","path":"scripts/DebugView/DebugView.yy",},}, {"id":{"name":"DiploBasicNodes","path":"scripts/DiploBasicNodes/DiploBasicNodes.yy",},}, {"id":{"name":"DiploCommonComponents","path":"scripts/DiploCommonComponents/DiploCommonComponents.yy",},}, @@ -847,6 +846,8 @@ {"id":{"name":"scr_khornate_fleet_functions","path":"scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.yy",},}, {"id":{"name":"scr_kill_unit","path":"scripts/scr_kill_unit/scr_kill_unit.yy",},}, {"id":{"name":"scr_librarium","path":"scripts/scr_librarium/scr_librarium.yy",},}, + {"id":{"name":"scr_lines_increase","path":"scripts/scr_lines_increase/scr_lines_increase.yy",},}, + {"id":{"name":"scr_lines","path":"scripts/scr_lines/scr_lines.yy",},}, {"id":{"name":"scr_livery_setup","path":"scripts/scr_livery_setup/scr_livery_setup.yy",},}, {"id":{"name":"scr_load_all","path":"scripts/scr_load_all/scr_load_all.yy",},}, {"id":{"name":"scr_load_controller","path":"scripts/scr_load_controller/scr_load_controller.yy",},}, @@ -868,6 +869,7 @@ {"id":{"name":"scr_move_unit_info","path":"scripts/scr_move_unit_info/scr_move_unit_info.yy",},}, {"id":{"name":"scr_music","path":"scripts/scr_music/scr_music.yy",},}, {"id":{"name":"scr_necron_tombs","path":"scripts/scr_necron_tombs/scr_necron_tombs.yy",},}, + {"id":{"name":"scr_newtext","path":"scripts/scr_newtext/scr_newtext.yy",},}, {"id":{"name":"scr_ork_fleet_functions","path":"scripts/scr_ork_fleet_functions/scr_ork_fleet_functions.yy",},}, {"id":{"name":"scr_ork_planet_functions","path":"scripts/scr_ork_planet_functions/scr_ork_planet_functions.yy",},}, {"id":{"name":"scr_pen_And_paper","path":"scripts/scr_pen_And_paper/scr_pen_And_paper.yy",},}, From 221fb72d1f67aea266802dda6864fbfd8a9faee0 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 11:49:45 +0300 Subject: [PATCH 085/140] Fix merge compile errors: truncated incoming_damage_flavor, duplicate psychic helpers Two merge-seam defects broke compilation. The seam restoration of incoming_damage_flavor in scr_flavor2 had appended a truncated fragment (anchored on the doc comment rather than the definition), ending the script mid-declaration; GameMaker degraded the unparseable script to zero-argument functions, cascading into "scr_flavor2 expects 0 arguments" errors at the scr_clean and scr_shoot call sites. The complete 23-line function is restored verbatim from the merge's pre-merge parent. scr_powers carried duplicate definitions of accumulate_psychic_cast and flush_psychic_summary: the fork's Tavish-lineage copies (with a legacy 3-argument add_battle_log_message call) survived alongside upstream's rebuilt versions; the duplicates are excised, keeping upstream's eMSG_COLOR-API copies. Verified: single definitions, the 8-parameter scr_flavor2 signature intact, and zero legacy 3-argument log calls remaining anywhere. --- ChapterMaster.yyp | 6 +---- scripts/scr_flavor2/scr_flavor2.gml | 21 ++++++++++++++-- scripts/scr_powers/scr_powers.gml | 39 +++-------------------------- 3 files changed, 23 insertions(+), 43 deletions(-) diff --git a/ChapterMaster.yyp b/ChapterMaster.yyp index 4dff18ed57..140f06810b 100644 --- a/ChapterMaster.yyp +++ b/ChapterMaster.yyp @@ -513,10 +513,8 @@ {"$GMIncludedFile":"","%Name":"resources.png","CopyToMask":-1,"filePath":"datafiles/images/ui","name":"resources.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chimera.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"chimera.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Guardsman Test.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Guardsman Test.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, - {"$GMIncludedFile":"","%Name":"guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"Guardsman.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Guardsman.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"sarge.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"sarge.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, - {"$GMIncludedFile":"","%Name":"Sarge.png","CopyToMask":-1,"filePath":"datafiles/images/units","name":"Sarge.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_advantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_advantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"chapter_disadvantages.json","CopyToMask":-1,"filePath":"datafiles/main","name":"chapter_disadvantages.json","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, {"$GMIncludedFile":"","%Name":"pauldron.png","CopyToMask":-1,"filePath":"datafiles/main/chapter_symbols/darkangels","name":"pauldron.png","resourceType":"GMIncludedFile","resourceVersion":"2.0",}, @@ -721,6 +719,7 @@ {"id":{"name":"Armamentarium","path":"scripts/Armamentarium/Armamentarium.yy",},}, {"id":{"name":"ColourItem","path":"scripts/ColourItem/ColourItem.yy",},}, {"id":{"name":"ColourPicker","path":"scripts/ColourPicker/ColourPicker.yy",},}, + {"id":{"name":"CombatLog","path":"scripts/CombatLog/CombatLog.yy",},}, {"id":{"name":"DebugView","path":"scripts/DebugView/DebugView.yy",},}, {"id":{"name":"DiploBasicNodes","path":"scripts/DiploBasicNodes/DiploBasicNodes.yy",},}, {"id":{"name":"DiploCommonComponents","path":"scripts/DiploCommonComponents/DiploCommonComponents.yy",},}, @@ -846,8 +845,6 @@ {"id":{"name":"scr_khornate_fleet_functions","path":"scripts/scr_khornate_fleet_functions/scr_khornate_fleet_functions.yy",},}, {"id":{"name":"scr_kill_unit","path":"scripts/scr_kill_unit/scr_kill_unit.yy",},}, {"id":{"name":"scr_librarium","path":"scripts/scr_librarium/scr_librarium.yy",},}, - {"id":{"name":"scr_lines_increase","path":"scripts/scr_lines_increase/scr_lines_increase.yy",},}, - {"id":{"name":"scr_lines","path":"scripts/scr_lines/scr_lines.yy",},}, {"id":{"name":"scr_livery_setup","path":"scripts/scr_livery_setup/scr_livery_setup.yy",},}, {"id":{"name":"scr_load_all","path":"scripts/scr_load_all/scr_load_all.yy",},}, {"id":{"name":"scr_load_controller","path":"scripts/scr_load_controller/scr_load_controller.yy",},}, @@ -869,7 +866,6 @@ {"id":{"name":"scr_move_unit_info","path":"scripts/scr_move_unit_info/scr_move_unit_info.yy",},}, {"id":{"name":"scr_music","path":"scripts/scr_music/scr_music.yy",},}, {"id":{"name":"scr_necron_tombs","path":"scripts/scr_necron_tombs/scr_necron_tombs.yy",},}, - {"id":{"name":"scr_newtext","path":"scripts/scr_newtext/scr_newtext.yy",},}, {"id":{"name":"scr_ork_fleet_functions","path":"scripts/scr_ork_fleet_functions/scr_ork_fleet_functions.yy",},}, {"id":{"name":"scr_ork_planet_functions","path":"scripts/scr_ork_planet_functions/scr_ork_planet_functions.yy",},}, {"id":{"name":"scr_pen_And_paper","path":"scripts/scr_pen_And_paper/scr_pen_And_paper.yy",},}, diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index 73ddba275e..a976fe3e42 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -490,8 +490,11 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo } } -// Merge seam: fork-owned severity flavor retained on upstream's rebuilt log. -function incoming_damage_flavor + +// Merge seam: fork-owned severity flavor (restored complete from the pre-merge +// tree; the first restoration appended a truncated fragment that broke the whole +// script's parse, degrading scr_flavor2 to a zero-argument function). +/// @function incoming_damage_flavor /// @description Combat-log sentence for an enemy hit that did NOT kill, scaled by how close it came /// to a kill (_severity = damage over the target's health before the hit, 0..1). Vehicles get /// armour/hull language, infantry get wound language. Appended after the attack verb, e.g. @@ -500,3 +503,17 @@ function incoming_damage_flavor /// @param {real} _severity 0..1 /// @param {bool} _is_vehicle target is a vehicle /// @returns {string} +function incoming_damage_flavor(_severity, _is_vehicle) { + if (_is_vehicle) { + if (_severity < 0.10) return choose("Only peeling the paint.", "Just chipping the paint.", "Pinging off the armour.", "Bouncing off the hull.", "Only scratching the armour."); + if (_severity < 0.35) return choose("Barely putting a dent in the armour.", "Leaving a few dents in the hull.", "Only scuffing the armour."); + if (_severity < 0.65) return choose("Piercing the armour.", "Punching through the plating.", "Cracking the armour open."); + if (_severity < 0.90) return choose("Punching a huge hole in the armour.", "Tearing a gash through the hull.", "Blowing a hole in the plating."); + return choose("Almost destroying it.", "Leaving it a smoking wreck.", "Nearly tearing it apart."); + } + if (_severity < 0.10) return choose("But the armour holds.", "But it is shrugged off."); + if (_severity < 0.35) return choose("Drawing blood.", "Causing light wounds.", "Leaving a few grazes."); + if (_severity < 0.65) return choose("Wounding several.", "Bloodying the ranks.", "Leaving wounded behind."); + if (_severity < 0.90) return choose("Leaving deep wounds.", "Savaging the ranks.", "Leaving many badly wounded."); + return choose("Leaving the survivors maimed and reeling.", "All but breaking them.", "Leaving them maimed and scattered."); +} diff --git a/scripts/scr_powers/scr_powers.gml b/scripts/scr_powers/scr_powers.gml index e5b4c4be9f..ea30c726ef 100644 --- a/scripts/scr_powers/scr_powers.gml +++ b/scripts/scr_powers/scr_powers.gml @@ -376,42 +376,9 @@ function flush_psychic_summary(_psy_log) { /// @desc Folds one attack-power cast into the per-formation psychic summary, keyed by power + target, /// so many identical Librarian casts collapse into a single battle-log line. /// @param {Struct} _psy_log The accumulator struct (one per formation casting phase). -function accumulate_psychic_cast(_psy_log, _power_name, _power_flavour, _target_name, _verb, _is_vehicle, _kills) { - var _key = _power_name + "|" + _target_name; - if (!variable_struct_exists(_psy_log, _key)) { - _psy_log[$ _key] = { - power: _power_name, - flavour: _power_flavour, - target: _target_name, - verb: _verb, - vehicle: _is_vehicle, - casts: 0, - kills: 0, - }; - } - var _entry = _psy_log[$ _key]; - _entry.casts += 1; - _entry.kills += _kills; -} - -/// @desc Emits one battle-log line per power+target accumulated during a formation's casting phase. -/// Mirrors scr_powers' own concatenation so spacing matches the individual-cast lines. -/// @param {Struct} _psy_log The accumulator filled by accumulate_psychic_cast. -function flush_psychic_summary(_psy_log) { - if (!is_struct(_psy_log)) { - return; - } - var _keys = variable_struct_get_names(_psy_log); - for (var i = 0; i < array_length(_keys); i++) { - var _e = _psy_log[$ _keys[i]]; - var _cast_word = (_e.casts == 1) ? "casting" : "castings"; - var _message = $"{_e.casts} {_cast_word} of '{_e.power}'{_e.flavour} {_e.kills} {_e.target} are {_e.verb}."; - var _size = _e.vehicle ? (_e.kills * 12) : (_e.kills * 3); - add_battle_log_message(_message, _size, 134); - } - if (array_length(_keys) > 0) { - } -} +// Duplicate accumulate_psychic_cast / flush_psychic_summary removed here: the +// fork carried Tavish-lineage copies (legacy 3-argument add_battle_log_message) +// alongside upstream's rebuilt versions above, producing duplicate script names. /// @desc Function to get requested data from the disciplines_data structure. Returns The requested data, or undefined if not found. /// @param _discipline_name - The name of the discipline From d0eb6d7cf5c9aa23d40d4b1784fc19b86db918d9 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 11:56:46 +0300 Subject: [PATCH 086/140] Fix uninitialized slaa crash in Chaos compositions; warband gate excludes chaos specials GM2043 triage found one live defect among the warnings: var slaa was declared inside the Daemon Forces block (CHAOS + ship_demon/ruins_eldar) but read 39 times inside the mutually exclusive CSM warband composition block, so any plain Chaos ground battle whose composition reached an if (slaa) case read an uninitialized local, a hard crash in this build. Present in vanilla's old numbering as well. The declaration is hoisted above both blocks. The triage also exposed a gate gap from the spawn-side renumbering: the CSM warband block's CHAOS gate lacked the chaos-special exclusions (ship_demon, ruins_eldar, fallen1/2, WL10_reveal/later) that its HERETICS sibling carries, so those special battles would have spawned a CSM warband on top of their own composition; the exclusions are added. Remaining GM2043/GM2044 warnings are vanilla lint (function-scoped locals, write-before-read event assignments, redeclarations), runtime-safe and deliberately left untouched to avoid merge churn against upstream. --- objects/obj_ncombat/Alarm_0.gml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/objects/obj_ncombat/Alarm_0.gml b/objects/obj_ncombat/Alarm_0.gml index efb4c6ce25..d14e35793a 100644 --- a/objects/obj_ncombat/Alarm_0.gml +++ b/objects/obj_ncombat/Alarm_0.gml @@ -2304,13 +2304,19 @@ try { } } + // Hoisted above both Chaos-side composition blocks: the CSM warband block below + // reads slaa 39 times but the declaration only executed inside this daemon block, + // so any plain Chaos ground battle hit an uninitialized local at its first + // if (slaa) case (GM2043 was flagging a real latent crash, present in vanilla's + // old numbering too). If we want multiple story events for specific Chaos Gods, + // slaa could become a gods value instead (upstream TBD note preserved). + var slaa = false; + if (battle_special == "ruins_eldar") { + slaa = true; + } + // ** Daemon Forces ** - The faction for the check is the Genestealers but the forces being setup are clearly Daemons. if (enemy == eFACTION.CHAOS && (battle_special == "ship_demon" || battle_special == "ruins_eldar")) { - // If we want to have multiple story events regarding specific Chaos Gods, we could name slaa into gods and just check the value? TBD - var slaa = false; - if (battle_special == "ruins_eldar") { - slaa = true; - } // Small Daemon Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); @@ -2537,7 +2543,12 @@ try { // ** Chaos Space Marines Forces ** // The CSM warband compositions belong to true Chaos forces (p_chaos), which now // arrive as eFACTION.CHAOS. Second half of the spawn-side renumbering swap. - if ((enemy == eFACTION.CHAOS) && (battle_special != "ChaosWarband") && (string_count("cs_meeting_battle", battle_special) == 0)) { + // The renumbering moved this block to CHAOS, whose battles include the daemon, + // fallen, and concealed-warlord specials (each with its own composition above); + // without these exclusions those battles would spawn a CSM warband on top of + // their special forces. The HERETICS block carries the same list for the same + // reason. + if ((enemy == eFACTION.CHAOS) && (battle_special != "ChaosWarband") && (battle_special != "ship_demon") && (battle_special != "ruins_eldar") && (battle_special != "fallen1") && (battle_special != "fallen2") && (battle_special != "WL10_reveal") && (battle_special != "WL10_later") && (string_count("cs_meeting_battle", battle_special) == 0)) { // Small CSM Group if (threat == 1) { u = instance_nearest(xxx, 240, obj_enunit); From 7489da5443c64503c3c8b9de60f458b2b810d053 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 12:11:01 +0300 Subject: [PATCH 087/140] Added new chimera portrait by Chad Drywall Changed it so it's bigger, matches the size of portraits. Experimental feature for all future portraits of vehicles --- datafiles/images/units/chimera.png | Bin 82479 -> 14865 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/datafiles/images/units/chimera.png b/datafiles/images/units/chimera.png index 3f3af15259b17f5bb057b34e22d4852baffd5ff1..c76e7ec15e4d5c19eba5e50671ada8e52740a39e 100644 GIT binary patch literal 14865 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 literal 82479 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

TN{@bQc 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 From 54f082bab9125feaf5fced1e8c74548a113449da Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 12:29:19 +0300 Subject: [PATCH 088/140] Fix instant crash on new campaign: restore craftworld placement initializer lost in merge Starting any new campaign crashed to desktop at obj_controller Alarm_1:491 ("Variable obj_controller.go not set before reading it"). The craftworld placement loop's state variable was initialized by "var go = 0;" immediately above the loop; upstream's initialization cleanup removed that line in a hunk that auto-applied through the merge without conflicting, while the fork's side of the file kept every read. Galaxy generation therefore died at the first "if (go == 0)" on every new game, any chapter or seed; existing saves were unaffected since Alarm_1 only runs at creation. The declaration is restored above the loop with a comment. Region diff confirms this was the only lost line there; upstream's other changes in the block are kept. --- objects/obj_controller/Alarm_1.gml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/objects/obj_controller/Alarm_1.gml b/objects/obj_controller/Alarm_1.gml index 8f74869b20..fc2cf9e331 100644 --- a/objects/obj_controller/Alarm_1.gml +++ b/objects/obj_controller/Alarm_1.gml @@ -487,6 +487,11 @@ if (did != 0) { // Eldar craftworld here craftworld = 1; +// Restored: upstream's initialization cleanup removed this declaration in an +// auto-merged hunk while the placement loop below kept every read, so starting +// any new campaign crashed instantly at "if (go == 0)" with an unset variable. +var go = 0; + for (var i = 0; i < 100; i++) { if (go == 0) { xx = floor(random(1152 + 600)) + 104; From 3ffca728f53750179d1fd79482e29bd23df152bd Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 13:07:19 +0300 Subject: [PATCH 089/140] Fix attack screen crash (formation button rename) and two blended log posts in Alarm_5 Clicking Attack crashed the drop screen on draw: upstream's UI refactor renamed the formation selector button to btn_formation in obj_drop_select's Create (auto-merged), while the fork's kept drop_select_unit_selection still addressed the old name. The five references are renamed to match. A systematic sweep of all Create-event initializers deleted or renamed by the merge, cross-referenced against every OURS-kept file, found no further unset reads (remaining hits were cross-object or comment false positives) but exposed two blended log defects in obj_ncombat Alarm_5: the plasma-bomb-ineffective path pushed the stale _newline in red beside its real message, re-posting the previous log line on every tomb resolution, and the Exterminatus announcement pushed stale _newline instead of its own text (legacy newline assignments beside upstream's push). Both sites now post one correct line each. --- objects/obj_ncombat/Alarm_5.gml | 10 ++++++---- .../scr_drop_select_function.gml | 12 +++++++----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/objects/obj_ncombat/Alarm_5.gml b/objects/obj_ncombat/Alarm_5.gml index 5c9f1bb09f..781b8a10bc 100644 --- a/objects/obj_ncombat/Alarm_5.gml +++ b/objects/obj_ncombat/Alarm_5.gml @@ -596,7 +596,9 @@ if (defeat == 0 && _reduce_power) { // This message was assigned but never posted (dead newline under the // legacy log too); posted properly on the rebuilt log. add_battle_log_message(newline, eMSG_COLOR.YELLOW); - combat_log.push(_newline, eMSG_COLOR.RED); + // A blended merge hunk also pushed the stale _newline here in red, + // re-posting the previous log line on every plasma-ineffective result; + // removed. } } } @@ -825,10 +827,10 @@ if ((inq_eated == false) && (sorcery_seen >= 2)) { } if ((exterminatus > 0) && dropping) { - newline = "Exterminatus has been succesfully placed."; - newline_color = "yellow"; endline = 0; - combat_log.push(_newline, eMSG_COLOR.YELLOW); + // Was a legacy newline/newline_color assignment beside a blended push of the + // stale _newline, so the wrong text posted; posts its own line now. + combat_log.push("Exterminatus has been succesfully placed.", eMSG_COLOR.YELLOW); } instance_activate_object(obj_star); diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index 585775e7ad..2a8b345acb 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -54,11 +54,13 @@ function drop_select_unit_selection() { formation_current = clamp(formation_current, 0, array_length(formation_possible) - 1); _formation_str = $"Formation: {obj_controller.bat_formation[formation_possible[formation_current]]}"; } - formation.x1 = x2 - 40 - (string_width(_formation_str) + 4); - formation.y1 = y1 + 80; - formation.update({str1: _formation_str}); - formation.draw(); - if (formation.clicked()) { + // Upstream renamed this button to btn_formation in obj_drop_select Create_0; + // the old name here crashed the whole attack screen on draw. + btn_formation.x1 = x2 - 40 - (string_width(_formation_str) + 4); + btn_formation.y1 = y1 + 80; + btn_formation.update({str1: _formation_str}); + btn_formation.draw(); + if (btn_formation.clicked()) { if (array_length(formation_possible) > 0) { formation_current++; if (formation_current >= array_length(formation_possible)) { From cf27960af4db679e11a979bfef740c9e184c0a88 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 13:25:40 +0300 Subject: [PATCH 090/140] Fix silent Genestealer Cult weapons and pnunit noone crash Port upstream's eight Genestealer Cult weapon cases (Hand Flamer, Force Staff, Heavy Maul, Heavy Mining Laser, Heavy Stubber, Demolition Charges, Drilldozer Blade, Autocannon) into the Tyranid-gated switch in scr_en_weapon. Cult revolt battles run under the TYRANIDS gate and these cases were added upstream after the fork diverged, so all cult heavy weapons resolved with range 0, never fired, and spammed "has broken range!" errors. Stats match upstream verbatim including Drilldozer spli = 2. Port upstream's instance_exists guard into obj_pnunit Alarm_0 after the instance_nearest call. When the last enemy block dies between the turn driver pulsing alarm[0] and a player block's tick, instance_nearest returns noone and the enemy.x read at the distance calculation throws "Unable to find instance for object index -4". Early exit is safe since set_up_player_blocks_turn re-arms the alarm each round. --- objects/obj_pnunit/Alarm_0.gml | 9 +++++ scripts/scr_en_weapon/scr_en_weapon.gml | 50 +++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index 3125662c0b..c22444f157 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -10,6 +10,15 @@ try { enemy = instance_nearest(0, y, obj_enunit); // Left most enemy + // Ported from upstream: instance_nearest returns noone when the last enemy + // block dies between the turn driver pulsing alarm[0] and this block's tick, + // and reading enemy.x below then throws "Unable to find instance for object + // index -4". Exit early; set_up_player_blocks_turn re-arms this alarm next turn. + if (!instance_exists(enemy)) { + engaged = false; + exit; + } + // Basic combat orders: every block carries a move_order ("advance" or "hold"), // seeded on its first tick from the vanilla movement rule (raids and attacks // advance, defense and the static formation hold) and toggled by clicking the diff --git a/scripts/scr_en_weapon/scr_en_weapon.gml b/scripts/scr_en_weapon/scr_en_weapon.gml index 18ee562905..d2b1d98ab1 100644 --- a/scripts/scr_en_weapon/scr_en_weapon.gml +++ b/scripts/scr_en_weapon/scr_en_weapon.gml @@ -690,6 +690,56 @@ function scr_en_weapon(name, is_man, man_number, man_type, group) { arp = 3; rang = 1; break; + // Genestealer Cult arsenal, ported verbatim from upstream scr_en_weapon. + // Cult revolt battles run under the TYRANIDS gate; without these cases + // every cult heavy weapon fell through with range 0 and never fired + // ("has broken range!" log spam, one-sided battles, no red loss lines). + case "Hand Flamer": + atta = 40; + arp = 1; + rang = 2; + amm = 5; + break; + case "Force Staff": + atta = 100; + arp = 3; + rang = 1; + break; + case "Heavy Maul": + atta = 80; + arp = 2; + rang = 1; + break; + case "Heavy Mining Laser": + atta = 100; + arp = 4; + rang = 4; + amm = 6; + break; + case "Heavy Stubber": + atta = 100; + arp = 1; + rang = 6; + amm = 8; + break; + case "Demolition Charges": + atta = 100; + arp = 3; + rang = 2; + amm = 3; + break; + case "Drilldozer Blade": + atta = 120; + arp = 3; + rang = 1; + spli = 2; + break; + case "Autocannon": + atta = 80; + arp = 3; + rang = 12; + amm = 10; + break; default: break; } From 05bf9fa244b100f6f317b6ae7b3e1da2e919e312 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 13:38:54 +0300 Subject: [PATCH 091/140] Restore volley kill consolidation lost in upstream merge The upstream merge 32f45d731 dropped the scr_flavor half of the volley kill consolidation (commit 8a1fa4fac) while keeping the obj_pnunit Alarm_0 half, leaving an orphaned combat_kill_tally_flush() call that threw "not set before reading it" every block tick. The crash was previously masked by the enemy.x noone crash at line 34, fixed in the prior commit. Restore combat_kill_tally_add and combat_kill_tally_flush in scr_flavor, the volley struct fields (weapon, shots, kills, volley), and the buffering branches in emit_volley_flavour, adapted to the post-merge log API: (text, color) calls instead of (text, size, priority), and tally state homed on obj_ncombat instead of globals, matching where the merge moved the ctally state. Initialize ktally fields in obj_ncombat Create_0 and point the Alarm_0 per-block reset at the obj_ncombat fields, replacing dead global writes. Split volleys of the same weapon on the same target once again collapse into one summed log line. --- objects/obj_ncombat/Create_0.gml | 4 ++ objects/obj_pnunit/Alarm_0.gml | 14 +++--- scripts/scr_flavor/scr_flavor.gml | 75 ++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 9 deletions(-) diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index af88edb5db..4674645234 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -180,6 +180,10 @@ combat_log.log_font = fnt_aldrich_12; ctally_target = undefined; ctally_bounce = []; ctally_injure = []; +ktally_target = undefined; +ktally_weapons = {}; +ktally_order = []; +ktally_leaders = []; world_size = 0; diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index c22444f157..156b5e31f3 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -68,13 +68,13 @@ try { } if (instance_exists(obj_enunit)) { - global.ctally_target = undefined; - global.ctally_bounce = []; - global.ctally_injure = []; - global.ktally_target = undefined; - global.ktally_weapons = {}; - global.ktally_order = []; - global.ktally_leaders = []; + obj_ncombat.ctally_target = undefined; + obj_ncombat.ctally_bounce = []; + obj_ncombat.ctally_injure = []; + obj_ncombat.ktally_target = undefined; + obj_ncombat.ktally_weapons = {}; + obj_ncombat.ktally_order = []; + obj_ncombat.ktally_leaders = []; for (var i = 0; i < array_length(wep); i++) { // Enemies wiped before every weapon got to fire (e.g. spill-over cleared the line). // Report who held fire and stop, rather than swinging at empty air. diff --git a/scripts/scr_flavor/scr_flavor.gml b/scripts/scr_flavor/scr_flavor.gml index 1511a90b5e..17ec236391 100644 --- a/scripts/scr_flavor/scr_flavor.gml +++ b/scripts/scr_flavor/scr_flavor.gml @@ -177,6 +177,10 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot firing_subject = $"{number_of_shots} {weapon_plural}"; } + // A plain volley line (" ", no character title) can be summed with other volleys + // of the same weapon on the same target into one consolidated kill line (see emit_volley_flavour). + var _volley_line = (!(character_shot && unit_name != "")) && (number_of_shots > 1); + var flavoured = false; if (weapon_data.has_tag("bolt")) { @@ -748,6 +752,10 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot injured: (!shots_bounced && casulties == 0), target: target_name, subject: firing_subject, + weapon: weapon_plural, + shots: number_of_shots, + kills: casulties, + volley: _volley_line, }; } @@ -795,13 +803,25 @@ function emit_volley_flavour(_primary, _spill_kills) { // Non-killing volley (armour-bounce or a wound that dropped no-one, and nothing spilled): // consolidate into one chronological line per target instead of one line per weapon. if (is_struct(_primary) && (_primary.bounced || _primary.injured) && _list == "") { + combat_kill_tally_flush(); combat_tally_add(_primary.target, _primary.subject, _primary.injured); return; } - // A killing volley posts immediately; flush any pending bounce/injure tally first so the log - // stays in chronological order. + // Simple killing volley with no spill-over: buffer it so consecutive volleys of the same weapon + // on the same target (e.g. a split lasgun volley firing in sub-stacks) collapse into one summed + // line. A single unmerged volley keeps its original rich flavour on flush. Flush the wound/bounce + // tally first so the log stays chronological. + if (is_struct(_primary) && _list == "" && _primary.volley && _primary.kills > 0) { + combat_tally_flush(); + combat_kill_tally_add(_primary.target, _primary.weapon, _primary.shots, _primary.kills, _primary.attack, _primary.color, _primary.leader); + return; + } + + // A killing volley with spill-over, or a titled/lone shot, posts immediately; flush both pending + // tallies first so the log stays in chronological order. combat_tally_flush(); + combat_kill_tally_flush(); if (!is_struct(_primary)) { // No primary line (scr_flavor bailed on a dead target - shouldn't happen now that emptied @@ -857,6 +877,57 @@ function combat_tally_flush() { obj_ncombat.ctally_injure = []; } +/// @desc Buffers killing volleys that share a weapon and target, summing shots and kills so a split +/// volley (many sub-stacks firing at one target) collapses into one line. The first volley's +/// rich flavour is kept and used verbatim if no second volley merges with it. Switching target +/// flushes the previous target first, keeping the log chronological. +function combat_kill_tally_add(_target, _weapon, _shots, _kills, _attack, _color, _leader) { + if (obj_ncombat.ktally_target != _target) { + combat_kill_tally_flush(); + obj_ncombat.ktally_target = _target; + obj_ncombat.ktally_weapons = {}; + obj_ncombat.ktally_order = []; + obj_ncombat.ktally_leaders = []; + } + if (!variable_struct_exists(obj_ncombat.ktally_weapons, _weapon)) { + obj_ncombat.ktally_weapons[$ _weapon] = { shots: 0, kills: 0, count: 0, attack: _attack, color: _color }; + array_push(obj_ncombat.ktally_order, _weapon); + } + var _acc = obj_ncombat.ktally_weapons[$ _weapon]; + _acc.shots += _shots; + _acc.kills += _kills; + _acc.count += 1; + if (_leader != "") { + array_push(obj_ncombat.ktally_leaders, { text: _leader, color: _color }); + } +} + +/// @desc Posts the buffered kills for the current target: one line per weapon (the original rich +/// line when only a single volley landed, otherwise a summed " strike at the +/// ranks, killing "), then any deferred leader lines, and clears. +function combat_kill_tally_flush() { + if (obj_ncombat.ktally_target == undefined) { + return; + } + var _t = obj_ncombat.ktally_target; + for (var _i = 0; _i < array_length(obj_ncombat.ktally_order); _i++) { + var _w = obj_ncombat.ktally_order[_i]; + var _acc = obj_ncombat.ktally_weapons[$ _w]; + if (_acc.count == 1) { + add_battle_log_message(_acc.attack, _acc.color); + } else { + add_battle_log_message($"{_acc.shots} {_w} strike at the {_t} ranks, killing {_acc.kills}.", _acc.color); + } + } + for (var _i = 0; _i < array_length(obj_ncombat.ktally_leaders); _i++) { + add_battle_log_message(obj_ncombat.ktally_leaders[_i].text, obj_ncombat.ktally_leaders[_i].color); + } + obj_ncombat.ktally_target = undefined; + obj_ncombat.ktally_weapons = {}; + obj_ncombat.ktally_order = []; + obj_ncombat.ktally_leaders = []; +} + /// @desc Joins firing subjects into "A", "A and B", or "A, B, and C". function combat_subject_join(_subjects) { return string_join_oxford_comma(_subjects); From 43433ddff12fe3caef9583d71da6b5553f30303a Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 14:09:14 +0300 Subject: [PATCH 092/140] Depth-based column piercing, target strength readout, Tavish log colors Rework column piercing on both sides to depth-based soak: the volley reaches at most PIERCE_MAX_DEPTH (3) lines, each armour line soaks PIERCE_LINE_SOAK (0.33) of the original volley as bounced chip fire, and everything still travelling lands on the first men-bearing line. So 100 autoguns against Predator/Scouts put 33 on the tank and 67 on the Scouts; against Predator/Rhino/Scouts they put 33, 33, 34. Infantry behind three or more lines is out of reach and the volley falls back to plinking the front armour. Replaces the RANK2/RANK3 fraction macros with shared PIERCE_LINE_SOAK / PIERCE_MAX_DEPTH. Enemy strike lines now report what was hit and its living strength ("strikes at Assault ranks (18 strong)", "Land Raider (2 remaining)"), computed from the target block's own arrays inside scr_flavor2. Port Tavish's combat log color coding (CptMacTavish2224/CM-Poligon, tag LW_Beta_1.2, credited in comments): no-effect bounces white, wounding non-kill hits light green, on both the enemy severity lines and the player wound tally line. Adds eMSG_COLOR.LIGHTGREEN and its render case to CombatLog. --- objects/obj_enunit/Alarm_0.gml | 93 +++++++++++++---------------- objects/obj_pnunit/Alarm_0.gml | 83 +++++++++++++------------ scripts/CombatLog/CombatLog.gml | 6 ++ scripts/macros/macros.gml | 28 ++++----- scripts/scr_flavor/scr_flavor.gml | 4 +- scripts/scr_flavor2/scr_flavor2.gml | 39 ++++++++++++ 6 files changed, 140 insertions(+), 113 deletions(-) diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index 87c32d6cda..c1fbc8e40c 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -160,12 +160,12 @@ if (!engaged) { // behind a small vehicle block, pinned at its 80% cap and skipped the // infantry, so ~4 of 5 anti-infantry volleys fell through to the vehicle // fallback and plinked the armour. One tank became a bullet sponge for a - // thousand men behind it. Instead the volley now pierces by depth: the - // first men-bearing block behind the wall is hit by ENEMY_PIERCE_RANK2_SHOTS - // of the stack's shots, the second by ENEMY_PIERCE_RANK3_SHOTS, deeper - // blocks by nothing, and the front armour takes the shots that failed to - // pass. Men-behind-men screening is unaffected: a front block with men in - // it still absorbs the whole volley above. + // thousand men behind it. Instead the volley now pierces by depth (see + // PIERCE_LINE_SOAK / PIERCE_MAX_DEPTH in macros.gml): each armour line + // soaks a third of the original volley as bounced chip fire, whatever + // gets through lands on the first men-bearing line, and nothing reaches + // past the third line. Men-behind-men screening is unaffected: a front + // block with men in it still absorbs the whole volley above. // Finding the ranks: the old probe walked x2 in 10px steps with // instance_nearest, and inherited vanilla's direction bug: the men // look-behind stepped +10 for the main force (toward the enemy), @@ -199,12 +199,15 @@ if (!engaged) { return _b.x - _a.x; }); } - var _rank_blocks = []; var _wall_blocks = []; - if (block_has_armour(enemy) || (enemy.veh_type[1] == "Defenses")) { - array_push(_wall_blocks, enemy); - } + var _wall_shots = []; + // Collect the lines the volley can interact with: the front wall plus + // blocks behind it, valid and in range, capped at PIERCE_MAX_DEPTH. + var _lines = [enemy]; for (var b = 0; b < array_length(_behind); b++) { + if (array_length(_lines) >= PIERCE_MAX_DEPTH) { + break; + } var enemy2 = _behind[b]; if (!target_block_is_valid(enemy2, obj_pnunit)) { continue; @@ -212,52 +215,40 @@ if (!engaged) { if (range[i] < get_block_distance(enemy2)) { break; } - if (enemy2.men > 0) { - array_push(_rank_blocks, enemy2); - if (array_length(_rank_blocks) >= 2) { + array_push(_lines, enemy2); + } + var _total_shots = wep_num[i]; + var _soak_shots = max(1, floor(_total_shots * PIERCE_LINE_SOAK)); + var _remaining = _total_shots; + var _rank_block = noone; + for (var l = 0; l < array_length(_lines); l++) { + var _line = _lines[l]; + if (_line.men > 0) { + _rank_block = _line; + break; + } + if (block_has_armour(_line) || (_line.veh_type[1] == "Defenses")) { + var _w_soak = min(_soak_shots, _remaining); + if (_w_soak > 0) { + array_push(_wall_blocks, _line); + array_push(_wall_shots, _w_soak); + _remaining -= _w_soak; + } + if (_remaining <= 0) { break; } - } else if ((array_length(_rank_blocks) == 0) && block_has_armour(enemy2)) { - // A men-less armour line between the shooter and the first - // infantry rank (Chimeras/Rhinos behind the Leman Russ line) - // is part of the wall: it soaks a share of the stopped shots - // instead of the front block eating them all. - array_push(_wall_blocks, enemy2); } } - if (array_length(_rank_blocks) > 0) { - var _total_shots = wep_num[i]; - var _rank2_shots = floor(_total_shots * ENEMY_PIERCE_RANK2_SHOTS); - var _rank3_shots = floor(_total_shots * ENEMY_PIERCE_RANK3_SHOTS); - var _front_shots = _total_shots - _rank2_shots; + if ((_rank_block != noone) && (_remaining > 0)) { var _ammo_spent = false; - if (_rank2_shots > 0) { - scr_shoot(i, _rank_blocks[0], target_unit_index, "att", "ranged", _rank2_shots, !_ammo_spent); - _ammo_spent = true; - _shot = true; - } - if ((array_length(_rank_blocks) > 1) && (_rank3_shots > 0)) { - scr_shoot(i, _rank_blocks[1], target_unit_index, "att", "ranged", _rank3_shots, !_ammo_spent); - _ammo_spent = true; - _shot = true; - } - // The shots stopped by the wall still land on the wall, split - // across every armour line in front of the infantry (Leman Russ - // line, then Chimeras/Rhinos), so armour keeps taking chip fire - // and no single front block eats the whole remainder. - var _wall_count = array_length(_wall_blocks); - if ((_front_shots > 0) && (_wall_count > 0)) { - var _per_wall = floor(_front_shots / _wall_count); - var _extra = _front_shots - (_per_wall * _wall_count); - for (var w = 0; w < _wall_count; w++) { - var _w_shots = _per_wall + ((w == 0) ? _extra : 0); - if (_w_shots <= 0) { - continue; - } - scr_shoot(i, _wall_blocks[w], target_unit_index, "att", "ranged", _w_shots, !_ammo_spent); - _ammo_spent = true; - _shot = true; - } + scr_shoot(i, _rank_block, target_unit_index, "att", "ranged", _remaining, !_ammo_spent); + _ammo_spent = true; + _shot = true; + // The soaked shots still land on the armour lines they bounced + // off, so the walls keep taking chip fire instead of the stopped + // shots vanishing. + for (var w = 0; w < array_length(_wall_blocks); w++) { + scr_shoot(i, _wall_blocks[w], target_unit_index, "att", "ranged", _wall_shots[w], !_ammo_spent); } if (_shot) { continue; diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index 156b5e31f3..ccc22242eb 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -225,10 +225,10 @@ try { // silently wasted the whole volley when the probe found nothing. // Instead: blocks beyond the front are collected along the // shooter-to-front axis (so main and flank fronts both walk the right - // way), sorted nearest-first; the first infantry rank in range eats - // PLAYER_PIERCE_RANK2_SHOTS of the volley, the second - // PLAYER_PIERCE_RANK3_SHOTS, deeper ranks nothing, and the stopped - // shots chip the armour wall instead of vanishing. + // way), sorted nearest-first; the volley pierces by depth (see + // PIERCE_LINE_SOAK / PIERCE_MAX_DEPTH in macros.gml), each armour + // line soaking a third of the original volley, the rest landing on + // the first infantry rank, nothing reaching past the third line. var _front_x = enemy.x; var _dir = sign(_front_x - x); if (_dir == 0) { @@ -253,12 +253,15 @@ try { return _b.x - _a.x; }); } - var _rank_blocks = []; var _wall_blocks = []; - if (block_has_armour(enemy) > 0) { - array_push(_wall_blocks, enemy); - } + var _wall_shots = []; + // Lines the volley can interact with: front wall plus blocks + // beyond, valid and in range, capped at PIERCE_MAX_DEPTH. + var _lines = [enemy]; for (var b = 0; b < array_length(_beyond); b++) { + if (array_length(_lines) >= PIERCE_MAX_DEPTH) { + break; + } var enemy2 = _beyond[b]; if (!target_block_is_valid(enemy2, obj_enunit)) { continue; @@ -266,51 +269,45 @@ try { if (range[i] < get_block_distance(enemy2)) { break; } - if (enemy2.men > 0) { - array_push(_rank_blocks, enemy2); - if (array_length(_rank_blocks) >= 2) { + array_push(_lines, enemy2); + } + var _total_shots = wep_num[i]; + var _soak_shots = max(1, floor(_total_shots * PIERCE_LINE_SOAK)); + var _remaining = _total_shots; + var _rank_block = noone; + for (var l = 0; l < array_length(_lines); l++) { + var _line = _lines[l]; + if (_line.men > 0) { + _rank_block = _line; + break; + } + if (block_has_armour(_line) > 0) { + var _w_soak = min(_soak_shots, _remaining); + if (_w_soak > 0) { + array_push(_wall_blocks, _line); + array_push(_wall_shots, _w_soak); + _remaining -= _w_soak; + } + if (_remaining <= 0) { break; } - } else if ((array_length(_rank_blocks) == 0) && (block_has_armour(enemy2) > 0)) { - // A second armour line between the shooter and the enemy - // infantry shares the stopped shots with the front wall. - array_push(_wall_blocks, enemy2); } } - if (array_length(_rank_blocks) > 0) { - var _total_shots = wep_num[i]; - var _rank2_shots = floor(_total_shots * PLAYER_PIERCE_RANK2_SHOTS); - var _rank3_shots = floor(_total_shots * PLAYER_PIERCE_RANK3_SHOTS); - var _front_shots = _total_shots - _rank2_shots; + if ((_rank_block != noone) && (_remaining > 0)) { var _ammo_spent = false; - var _rank_target = scr_target(_rank_blocks[0], "men"); - if ((_rank2_shots > 0) && (_rank_target != 0)) { - scr_shoot(i, _rank_blocks[0], _rank_target, "att", "ranged", _rank2_shots, !_ammo_spent); + var _rank_target = scr_target(_rank_block, "men"); + if (_rank_target != 0) { + scr_shoot(i, _rank_block, _rank_target, "att", "ranged", _remaining, !_ammo_spent); _ammo_spent = true; } - if ((array_length(_rank_blocks) > 1) && (_rank3_shots > 0)) { - _rank_target = scr_target(_rank_blocks[1], "men"); - if (_rank_target != 0) { - scr_shoot(i, _rank_blocks[1], _rank_target, "att", "ranged", _rank3_shots, !_ammo_spent); + // Soaked shots chip the armour lines they bounced off. + for (var w = 0; w < array_length(_wall_blocks); w++) { + var _w_target = scr_target(_wall_blocks[w], "veh"); + if (_w_target != 0) { + scr_shoot(i, _wall_blocks[w], _w_target, "att", "ranged", _wall_shots[w], !_ammo_spent); _ammo_spent = true; } } - var _wall_count = array_length(_wall_blocks); - if ((_front_shots > 0) && (_wall_count > 0)) { - var _per_wall = floor(_front_shots / _wall_count); - var _extra = _front_shots - (_per_wall * _wall_count); - for (var w = 0; w < _wall_count; w++) { - var _w_shots = _per_wall + ((w == 0) ? _extra : 0); - if (_w_shots <= 0) { - continue; - } - var _w_target = scr_target(_wall_blocks[w], "veh"); - if (_w_target != 0) { - scr_shoot(i, _wall_blocks[w], _w_target, "att", "ranged", _w_shots, !_ammo_spent); - _ammo_spent = true; - } - } - } if (_ammo_spent) { once_only = 1; } diff --git a/scripts/CombatLog/CombatLog.gml b/scripts/CombatLog/CombatLog.gml index a089af865e..5605f73ca8 100644 --- a/scripts/CombatLog/CombatLog.gml +++ b/scripts/CombatLog/CombatLog.gml @@ -4,6 +4,9 @@ enum eMSG_COLOR { AQUA = 5, RED = 6, YELLOW = 8, + // Light green tier ported from Tavish's CM-Poligon color coding (CptMacTavish2224, + // tag LW_Beta_1.2): hits that wounded without killing. + LIGHTGREEN = 9, } /// @param {Id.Instance} _owner The optional owning instance or controller. @@ -120,6 +123,9 @@ function CombatLog(_owner = undefined) constructor { case eMSG_COLOR.YELLOW: _final_color = 3055825; break; + case eMSG_COLOR.LIGHTGREEN: + _final_color = c_lime; + break; } // Wrap individual line segment if width limits are set diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 377d09caf1..513b1985c8 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -33,24 +33,16 @@ // heaviest guns chase tanks; drop toward 1 for the old behaviour where almost everything did. #macro GUARD_ENEMY_ANTITANK_AP 3 -// Enemy column piercing: when the player's front block has no men (a tank wall), enemy -// anti-infantry weapons no longer dump whole volleys into the armour. The volley splits by -// depth: the first men-bearing block behind the wall is hit by RANK2 of the shots, the second -// by RANK3, anything deeper by nothing, and the front armour takes the shots that failed to -// pass (1 - RANK2). Tune both toward 0 to restore the old bullet-sponge wall, toward 1 to make -// armour fully transparent to small-arms fire. -#macro ENEMY_PIERCE_RANK2_SHOTS 0.66 -#macro ENEMY_PIERCE_RANK3_SHOTS 0.33 - -// Player-side column piercing, mirroring the enemy mechanic. Vanilla player targeting -// gave anti-infantry weapons a 100% free pass through enemy tank walls (the men -// look-behind fired the full volley at the first infantry block behind, no shots lost), -// and silently wasted the volley entirely when no infantry was found. Now the wall -// costs the same toll in both directions: the first enemy infantry rank behind armour -// is hit by RANK2 of the shots, the second by RANK3, and the shots that fail to pass -// chip the wall instead of vanishing. -#macro PLAYER_PIERCE_RANK2_SHOTS 0.66 -#macro PLAYER_PIERCE_RANK3_SHOTS 0.33 +// Column piercing (both sides): when a front block has no men (an armour wall), an +// anti-infantry volley pushes through by depth instead of dumping into the wall. The +// volley reaches at most PIERCE_MAX_DEPTH lines, front included. Every armour line it +// passes soaks PIERCE_LINE_SOAK of the ORIGINAL volley as bounced chip fire, and +// everything still travelling lands on the first men-bearing line. Through one wall +// ~66% of the shots reach the infantry, through two walls ~33%, and infantry behind +// three or more lines cannot be reached at all. Men-behind-men screening is unchanged: +// a front block with men in it still absorbs the whole volley. +#macro PIERCE_LINE_SOAK 0.33 +#macro PIERCE_MAX_DEPTH 3 // Basic combat orders: an advancing block that finds a friendly block directly // ahead may leapfrog over it, landing on the first free slot beyond, probing at diff --git a/scripts/scr_flavor/scr_flavor.gml b/scripts/scr_flavor/scr_flavor.gml index 17ec236391..953c1468e3 100644 --- a/scripts/scr_flavor/scr_flavor.gml +++ b/scripts/scr_flavor/scr_flavor.gml @@ -867,7 +867,9 @@ function combat_tally_flush() { } var _t = obj_ncombat.ctally_target; if (array_length(obj_ncombat.ctally_injure) > 0) { - add_battle_log_message($"Fire from {combat_subject_join(obj_ncombat.ctally_injure)} wounded the {_t} but didn't bring it down.", eMSG_COLOR.WHITE); + // Light green for wounded-but-standing, per Tavish's CM-Poligon color coding + // (CptMacTavish2224, tag LW_Beta_1.2). + add_battle_log_message($"Fire from {combat_subject_join(obj_ncombat.ctally_injure)} wounded the {_t} but didn't bring it down.", eMSG_COLOR.LIGHTGREEN); } if (array_length(obj_ncombat.ctally_bounce) > 0) { add_battle_log_message($"Fire from {combat_subject_join(obj_ncombat.ctally_bounce)} cannot penetrate the {_t}'s armour.", eMSG_COLOR.WHITE); diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index a976fe3e42..9db3ec4bd3 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -40,6 +40,40 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo _hostile_shots = max(1, round(_hostile_shots / 3)); } + // Target readout: the bare unit name ("strikes at Assault") says nothing about what + // was hit or how many stand there. Append the block's living strength for that unit + // type. scr_flavor2 runs in the target block's own scope, so the arrays are directly + // readable. Only the "wall" comparisons below care about the raw value, and walls + // are never modified here. + if ((target_type != "wall") && is_string(target_type) && (target_type != "")) { + var _target_count = 0; + if (target_is_vehicle) { + if (variable_instance_exists(id, "veh_type")) { + for (var _tc = 0; _tc < array_length(veh_type); _tc++) { + if ((veh_type[_tc] == target_type) && (_tc < array_length(veh_dead)) && (veh_dead[_tc] == 0) && (_tc < array_length(veh_hp)) && (veh_hp[_tc] > 0)) { + _target_count++; + } + } + } + if (_target_count > 0) { + target_type = $"{target_type} ({_target_count} remaining)"; + } + } else if (target_type == "Imperial Guardsman") { + if (variable_instance_exists(id, "men") && (men > 0)) { + target_type = $"{target_type} ranks ({men} strong)"; + } + } else if (variable_instance_exists(id, "marine_type")) { + for (var _tc = 0; _tc < array_length(marine_type); _tc++) { + if ((marine_type[_tc] == target_type) && (_tc < array_length(marine_dead)) && (marine_dead[_tc] == 0)) { + _target_count++; + } + } + if (_target_count > 0) { + target_type = $"{target_type} ranks ({_target_count} strong)"; + } + } + } + var flavor = 0; if (_hostile_weapon == "Daemonette Melee") { @@ -480,6 +514,11 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo // which lands on the lowest tier. if ((m2 == "") && (lost_units_count == 0) && (hostile_shots > 0) && (target_type != "wall")) { m2 = incoming_damage_flavor(damage_severity, target_is_vehicle); + // Color coding ported from Tavish's CM-Poligon (CptMacTavish2224, tag + // LW_Beta_1.2): outcome reads at a glance against the red kill lines. Shots + // that bounced with no effect render white, hits that wounded without + // killing render light green. + mes_color = (damage_severity < 0.10) ? eMSG_COLOR.WHITE : eMSG_COLOR.LIGHTGREEN; } mes = m1 + m2 + m3; From 4e60ecc991bbfa277c8138130ac834e6d4a00510 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 14:23:17 +0300 Subject: [PATCH 093/140] Guard melee chain against target block destroyed mid-turn Within a single weapon's turn in obj_pnunit Alarm_0, the melee chain's vehicle swing can destroy the enemy block (emptied enemy formations are destroyed immediately), after which the medi and men sub-branches read enemy.veh and enemy.men on a destroyed instance and throw "Unable to find instance". The ranged chain already carries instance_exists guards between its sub-branches; the melee chain was missing them. Add instance_exists(enemy) to the melee medi and men sub-branch conditions, and a guard after the per-iteration empty-block reacquire, which can hand back noone when the block just destroyed was the last active enemy formation. --- objects/obj_pnunit/Alarm_0.gml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index ccc22242eb..99934e9f88 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -101,6 +101,12 @@ try { } enemy = instance_nearest(0, y, obj_enunit); } + // That destroy may have removed the last active enemy block, leaving the + // reacquire with noone; and reads on noone throw. Skip the weapon; the + // held-fire check at the top of the next iteration reports and stops. + if (!instance_exists(enemy)) { + continue; + } // Speed Force sweeps the whole field - bypass normal targeting/range. if (wep[i] == "Speed Force" || wep[i] == "Speed Force (Ranged)") { @@ -354,7 +360,11 @@ try { } // Fuck it, shoot at infantry } - if ((enemy.veh == 0) && (enemy.medi > 0) && (once_only == 0)) { + // instance_exists guard: the vehicle swing above can destroy the block + // (emptied enemy formations are destroyed immediately), and reading a + // destroyed instance throws. The ranged chain above already carries the + // same guards between its sub-branches; the melee chain was missing them. + if (instance_exists(enemy) && (enemy.veh == 0) && (enemy.medi > 0) && (once_only == 0)) { // Check for vehicles var g = 0, good = 0; @@ -372,7 +382,7 @@ try { } // Fuck it, shoot at infantry } - if ((ap == 0) && (once_only == 0)) { + if ((ap == 0) && (once_only == 0) && instance_exists(enemy)) { // Check for men var g = 0, good = 0; From 4087f5b57ed6c361749bcff16d09ee39a4841426 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 14:46:14 +0300 Subject: [PATCH 094/140] Fix CTD and occupancy corruption when moving formation bars obj_formation_bar Draw_64 reset col_parent to 0 every idle frame (upstream commit 6730ae794), but col_parent is the bar's home bracket assigned by init_combat_bars, and the drop handler needs it to decrement the source bracket's occupancy (temp[4800 + col_parent]) and for the same-bracket snap-back check. Zeroed, every drop read and wrote temp[4800], an uninitialized slot outside the per-bracket 4801-4810 range: a hard crash ("unable to convert string to float") when that slot holds a string, and silent occupancy drift (source bracket never decremented) when it holds a number, which is what periodically tripped the >10 layout reset in scr_ui_formation_bars. Remove col_parent from the idle reset. Bug exists verbatim in upstream main; relayed to Tavish. --- objects/obj_formation_bar/Draw_64.gml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/objects/obj_formation_bar/Draw_64.gml b/objects/obj_formation_bar/Draw_64.gml index 0958332620..9614254c29 100644 --- a/objects/obj_formation_bar/Draw_64.gml +++ b/objects/obj_formation_bar/Draw_64.gml @@ -51,7 +51,15 @@ if (dragging == false) { rel_mousey = 0; old_x = 0; old_y = 0; - col_parent = 0; + // col_parent deliberately NOT reset here. It is the bar's home bracket, assigned + // once by init_combat_bars, and mouse_release needs it on drop: both for the + // same-bracket snap-back check and for decrementing the source bracket's + // occupancy (temp[4800 + col_parent]). Zeroing it every idle frame (upstream + // commit 6730ae794) made every drop read and subtract from temp[4800], an + // uninitialized slot outside the per-bracket 4801-4810 range: a hard crash when + // that slot holds a string, and silent occupancy-count corruption (source + // bracket never decremented) when it holds a number. Bug exists verbatim in + // upstream main. col_target = 0; above_neighbor = 0; nearest_col = 0; From 58a90f5b70ed777f5401a100727dabeb830a8312 Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 16:04:10 +0300 Subject: [PATCH 095/140] Fix inspection verdict texts sitting on wrong branches inspection_report showed the "chosen to turn a blind eye to your heretical dealings" popup to chapters with zero findings, so clean chapters were always told something was found, and showed nothing at all when findings existed but the Inquisitor's tolerance roll let them slide. Clean chapters now get a "found nothing of concern" popup, the blind-eye text (typos fixed) moves to the tolerated-findings branch, and the caught branch is unchanged. Bug exists verbatim in upstream main; relayed to Tavish. --- .../scr_inquisition_inspection.gml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml b/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml index ac4f99ce3f..eee038d10a 100644 --- a/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml +++ b/scripts/scr_inquisition_inspection/scr_inquisition_inspection.gml @@ -514,9 +514,19 @@ function inquisitor_inspection_structure() constructor { } finalize_contraband_popup(); + } else { + // Findings existed but the Inquisitor's tolerance roll let them slide. + // This branch was previously silent, while the "blind eye" text below + // sat on the CLEAN branch, so a spotless chapter was told the + // Inquisitor had overlooked its "heretical dealings" and a chapter + // with real findings heard nothing. This is the community-reported + // "inspections always find something but never say what". Bug exists + // verbatim in upstream main. + var _tolerated_string = "The Inquisitor has chosen to turn a blind eye to some of your more questionable dealings on this occasion. It would perhaps be wise to be more careful in future."; + scr_popup("Inquisitor Finish Inspection", _tolerated_string, "inquisition"); } } else { - var _inspection_passed_string = "The inquisitor Has chosen to turnj a blind eye to some of your more heretical dealings on this occaision. However, it would perhaps be wise to be more careful in furture "; + var _inspection_passed_string = "The Inquisitor concludes the inspection having found nothing of concern. The chapter's conduct is, for now, beyond reproach."; scr_popup("Inquisitor Finish Inspection", _inspection_passed_string, "inquisition"); } }; From e3f8de3220472d2420f7b6ebdfb590b00da794ac Mon Sep 17 00:00:00 2001 From: KestasV Date: Sun, 5 Jul 2026 16:04:32 +0300 Subject: [PATCH 096/140] Port upstream fix: attack screen crash on worlds with no enemies left drop_select_unit_selection only assigned _target_str when the attacked world had enemy forces, so opening the attack screen on a cleared world read an unset local at the string_width call and threw. Port upstream's fix declaring _target_str as "No Target". --- scripts/scr_drop_select_function/scr_drop_select_function.gml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index 2a8b345acb..a66533c69b 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -178,6 +178,10 @@ function drop_select_unit_selection() { if (purge == eDROP_TYPE.RAIDATTACK) { var target_race = ""; var target_threat = ""; + // Ported from upstream: without this declaration, attacking a world with no + // enemy forces left (race_quantity 0) skips the only assignment below and the + // string_width read throws "not set before reading it". + var _target_str = "No Target"; if (attacking >= 5 && attacking <= 13) { race_quantity = race_quantities[attacking - 4]; From e00d24202ce65d1fdd8e21f50be1e77d5f34ed0f Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Sun, 5 Jul 2026 16:59:21 +0300 Subject: [PATCH 097/140] =?UTF-8?q?Revise=20README=20for=20Chapter=20Maste?= =?UTF-8?q?r=201.5=20=E2=80=93=20Adeptus=20Indomitus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated project name and description in README. --- docs/README.md | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/docs/README.md b/docs/README.md index f055a9f683..6570d567db 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,36 +2,19 @@ Chapter Master - Adeptus Dominus Logo

-# Chapter Master - Adeptus Dominus +# Chapter Master 1.5 – Adeptus Indomitus -[![Development Release](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/create_release.yml/badge.svg?branch=main)](https://github.com/Adeptus-Dominus/ChapterMaster/actions/workflows/create_release.yml) -[![](https://dcbadge.limes.pink/api/server/https://discord.gg/zAGpqHzsXQ?style=flat)](https://discord.gg/zAGpqHzsXQ) -[![GitHub repo size](https://img.shields.io/github/repo-size/Adeptus-Dominus/ChapterMaster?style=flat&label=Repo%20Size&labelColor=4493f8&color=545454)](https://github.com/Adeptus-Dominus/ChapterMaster) +**Chapter Master 1.5 – Adeptus Indomitus** is a major continuation fork of *Chapter Master: Adeptus Dominus*, expanding the game from a pure Space Marine Chapter command simulator into a broader Imperial war effort. -**Chapter Master** (aka CM) is a strategy/simulation game, written in **Game Maker Language**, originally designed and developed by Duke.\ -This project aims to continue development on the game, fix any bugs, expand and add features. +The central addition is a fieldable **Imperial Guard / Astra Militarum Auxilia** layer. The player can bargain with Imperial and Mechanicus authorities to raise Guardsmen, Guard Sergeants, Heavy Weapons Teams, Chimeras, Leman Russ tanks, and Basilisk artillery, then deploy them alongside the Chapter as a supporting Imperial force. -**Adeptus Dominus** is just how the team of primordial collaborators decided to call themselves and the new version of the game. +This fork adds new Guard unit profiles, Guard weapons, vehicle weapons, armour, Auxilia organization, and dedicated combat behaviour. Guardsmen are not just renamed Marines: they fight as mass infantry screens, split into capped lasgun volleys, shield more valuable forces behind them, and require armour, tanks, artillery, and Astartes support to survive serious threats. -## Links +Ground combat has been heavily reworked. Targeting now better distinguishes anti-infantry and anti-tank fire, armour walls no longer create absurd all-or-nothing shooting behaviour, partial volleys can pierce through vehicle screens, splash damage can carry over, vehicle weapons remain relevant at point-blank range, and dead or empty formations are cleaned up more reliably. -Our discord server: [Chapter Master Discord](https://discord.gg/zAGpqHzsXQ) - - Where most of the development talk, feature suggestion and bug-reporting takes place. - - GitHub issues are not used at the moment, as such we use #bug-report-forum in this server to handle bug reports. - - If you can code, draw, design, help with the GitHub stuff or just want to help in any way possible - you'll be welcomed with open arms. - - If you just love WH40K and want to chat - you'll have a great time in the server as well. +The campaign layer has also been expanded with Auxilia recruitment through diplomacy, Mechanicus armour support, per-ship assault capacity, local assault counters, lost-in-the-Warp ship events, Eldar incursion and craftworld-intel systems, improved fleet handling, better management UI, richer unit profile tooltips, and numerous bug fixes. -1d6Chan Wiki: [Chapter Master: Adeptus Dominus](https://1d6chan.miraheze.org/wiki/Chapter_Master:_Adeptus_Dominus) - - With some helpful pages that explain some of the new systems added in the Adeptus Dominus version. - - Help with expanding it will be welcomed. - -Main repository: [Adeptus-Dominus/ChapterMaster](https://github.com/Adeptus-Dominus/ChapterMaster) - -## Playing - -### Windows, Linux, macOS - -Download the [latest release](https://github.com/Adeptus-Dominus/ChapterMaster/releases/latest) or a [development pre-release](https://github.com/Adeptus-Dominus/ChapterMaster/releases), unzip and launch. +This is an unofficial fan fork intended to preserve and expand the spirit of *Chapter Master* while pushing it toward a larger, more dynamic Imperial command experience. ## Compiling from source From 7e784d5a58b0df1bbce0f0382f993e4ddabc8325 Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Sun, 5 Jul 2026 17:08:00 +0300 Subject: [PATCH 098/140] Update README with new features and improvements Added detailed descriptions of new features and improvements, including the Imperial Guard system, diplomatic recruitment, new wargear, combat model changes, and management UI enhancements. --- docs/README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/README.md b/docs/README.md index 6570d567db..ab71394689 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,6 +16,24 @@ The campaign layer has also been expanded with Auxilia recruitment through diplo This is an unofficial fan fork intended to preserve and expand the spirit of *Chapter Master* while pushing it toward a larger, more dynamic Imperial command experience. +## The biggest concrete changes I would advertise are these: + +Imperial Guard / Auxilia system. You added real Guard-side content: Guardsmen, Guard Squads, Heavy Weapons Teams, and Guard Sergeants, with human base stats, Flak Armour, Lasguns, Bayonets, Heavy Bolters, Guard Chainswords, and Laspistols. + +Diplomatic recruitment and attached armour. Sector Governor trade now raises Guardsmen directly at the homeworld, adds one Guard Sergeant per full squad, one Chimera per 200 Guardsmen, and one Heavy Weapons Team per 100 Guardsmen; Mechanicus trade can now provide Leman Russ tanks and Basilisks for the Auxilia company. + +New Astra Militarum wargear and vehicles. You added or integrated Flak Armour, Lasguns, Hellguns, Earthshaker Cannons, Battle Cannons, Multi-Lasers, Chimeras, Leman Russ loadouts, and Basilisk artillery loadouts. + +Combat model overhaul. Guard screens occupy forward columns, anti-tank weapons now have a dedicated target-preference threshold, volleys pierce armour walls by depth instead of passing through for free or vanishing, and Guardsmen split into capped lasgun stacks instead of forming one giant unrealistic volley. + +Better targeting, armour, and casualty logic. Enemy weapons now prefer vehicles only when their AP role justifies it, Guard screens can actually shield vehicles behind them, column piercing works on both sides, partial volleys scale damage correctly, stale casualty reports are cleared, and vehicle armour penetration was fixed so enemy anti-tank weapons can actually hurt vehicles. + +Fleet, assault, and campaign-layer additions. Ships now have per-turn ground-assault support counters, planets have local assault counters, new ship defaults include Guard-related capacity fields, and lost-in-the-Warp ships can return with damage, corruption, mutiny, Chaos capture, or destruction outcomes. + +Eldar campaign improvements. Eldar are no longer only a hidden craftworld oddity: you added incursion/intel settings, craftworld reveal requirements, first-contact clues, and Eldar ship speed tuning. + +Management UI and quality-of-life. The management screen now recognizes an Auxilia company, includes richer unit profile UI/tooltips, and has buttons for squad view, profile, bio, and capture image. + ## Compiling from source 1. Install the **GameMaker** IDE matching your system (available on the [GameMaker website](https://releases.gamemaker.io/release-notes/2026/0) or [Steam](https://store.steampowered.com/app/1670460/GameMaker/)). @@ -27,6 +45,7 @@ This is an unofficial fan fork intended to preserve and expand the spirit of *Ch ## Contributing +**To contribute to this fork please contact me on Discord, hopefully we can work together. I take ALL input and suggestions in, even if you're not a coder. If there's somethin you wanna personally see in the game then please tell me.** https://discord.com/channels/714022226810372107/1520160266120204409 Best bet is to ask about everything in our Discord, because things bellow are probably not very helpful at the moment. - [CONTRIBUTING.md](https://github.com/Adeptus-Dominus/ChapterMaster/blob/main/docs/CONTRIBUTING.md) (required read before any contribution) From 097d7735e654567118b7aa04a88ff27118d2fb78 Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Sun, 5 Jul 2026 17:09:54 +0300 Subject: [PATCH 099/140] Revise README for clarity and consistency Updated the README to enhance clarity and consistency in the descriptions of game features and systems, including the Imperial Guard/Auxilia system, combat model, and management UI improvements. --- docs/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/README.md b/docs/README.md index ab71394689..39dfdd8bb4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,27 +16,27 @@ The campaign layer has also been expanded with Auxilia recruitment through diplo This is an unofficial fan fork intended to preserve and expand the spirit of *Chapter Master* while pushing it toward a larger, more dynamic Imperial command experience. -## The biggest concrete changes I would advertise are these: +## The biggest concrete changes -Imperial Guard / Auxilia system. You added real Guard-side content: Guardsmen, Guard Squads, Heavy Weapons Teams, and Guard Sergeants, with human base stats, Flak Armour, Lasguns, Bayonets, Heavy Bolters, Guard Chainswords, and Laspistols. +_Imperial Guard / Auxilia system_. Added real Guard-side content: Guardsmen, Guard Squads, Heavy Weapons Teams, and Guard Sergeants, with human base stats, Flak Armour, Lasguns, Bayonets, Heavy Bolters, Guard Chainswords, and Laspistols. -Diplomatic recruitment and attached armour. Sector Governor trade now raises Guardsmen directly at the homeworld, adds one Guard Sergeant per full squad, one Chimera per 200 Guardsmen, and one Heavy Weapons Team per 100 Guardsmen; Mechanicus trade can now provide Leman Russ tanks and Basilisks for the Auxilia company. +_Diplomatic recruitment and attached armour_. Sector Governor trade now raises Guardsmen directly at the homeworld, adds one Guard Sergeant per full squad, one Chimera per 200 Guardsmen, and one Heavy Weapons Team per 100 Guardsmen; Mechanicus trade can now provide Leman Russ tanks and Basilisks for the Auxilia company. -New Astra Militarum wargear and vehicles. You added or integrated Flak Armour, Lasguns, Hellguns, Earthshaker Cannons, Battle Cannons, Multi-Lasers, Chimeras, Leman Russ loadouts, and Basilisk artillery loadouts. +_New Astra Militarum wargear and vehicles_. Added or integrated Flak Armour, Lasguns, Hellguns, Earthshaker Cannons, Battle Cannons, Multi-Lasers, Chimeras, Leman Russ loadouts, and Basilisk artillery loadouts. +_ +Combat model overhaul._ Guard screens occupy forward columns, anti-tank weapons now have a dedicated target-preference threshold, volleys pierce armour walls by depth instead of passing through for free or vanishing, and Guardsmen split into capped lasgun stacks instead of forming one giant unrealistic volley. -Combat model overhaul. Guard screens occupy forward columns, anti-tank weapons now have a dedicated target-preference threshold, volleys pierce armour walls by depth instead of passing through for free or vanishing, and Guardsmen split into capped lasgun stacks instead of forming one giant unrealistic volley. +_Better targeting, armour, and casualty logic_. Enemy weapons now prefer vehicles only when their AP role justifies it, Guard screens can actually shield vehicles behind them, column piercing works on both sides, partial volleys scale damage correctly, stale casualty reports are cleared, and vehicle armour penetration was fixed so enemy anti-tank weapons can actually hurt vehicles. -Better targeting, armour, and casualty logic. Enemy weapons now prefer vehicles only when their AP role justifies it, Guard screens can actually shield vehicles behind them, column piercing works on both sides, partial volleys scale damage correctly, stale casualty reports are cleared, and vehicle armour penetration was fixed so enemy anti-tank weapons can actually hurt vehicles. +_Fleet, assault, and campaign-layer additions._ Ships now have per-turn ground-assault support counters, planets have local assault counters, new ship defaults include Guard-related capacity fields, and lost-in-the-Warp ships can return with damage, corruption, mutiny, Chaos capture, or destruction outcomes. -Fleet, assault, and campaign-layer additions. Ships now have per-turn ground-assault support counters, planets have local assault counters, new ship defaults include Guard-related capacity fields, and lost-in-the-Warp ships can return with damage, corruption, mutiny, Chaos capture, or destruction outcomes. +_Eldar campaign restoration and improvement_. Eldar are no longer only a hidden craftworld oddity: added incursion/intel settings, craftworld reveal requirements, first-contact clues, and Eldar ship speed tuning. -Eldar campaign improvements. Eldar are no longer only a hidden craftworld oddity: you added incursion/intel settings, craftworld reveal requirements, first-contact clues, and Eldar ship speed tuning. - -Management UI and quality-of-life. The management screen now recognizes an Auxilia company, includes richer unit profile UI/tooltips, and has buttons for squad view, profile, bio, and capture image. +_Management UI and quality-of-life_. The management screen now recognizes an Auxilia company, includes richer unit profile UI/tooltips, and has buttons for squad view, profile, bio, and capture image. ## Compiling from source -1. Install the **GameMaker** IDE matching your system (available on the [GameMaker website](https://releases.gamemaker.io/release-notes/2026/0) or [Steam](https://store.steampowered.com/app/1670460/GameMaker/)). +1. Install the **GameMaker** IDE matching r system (available on the [GameMaker website](https://releases.gamemaker.io/release-notes/2026/0) or [Steam](https://store.steampowered.com/app/1670460/GameMaker/)). 2. Clone or download the repository (find the green **<>Code** button and select **Download ZIP**). 3. Find **ChapterMaster.yyp** in the downloaded folder and open it with **GameMaker**. 4. Select the target platform in the IDE: **Windows, macOS, Ubuntu**. @@ -45,7 +45,7 @@ Management UI and quality-of-life. The management screen now recognizes an Auxil ## Contributing -**To contribute to this fork please contact me on Discord, hopefully we can work together. I take ALL input and suggestions in, even if you're not a coder. If there's somethin you wanna personally see in the game then please tell me.** https://discord.com/channels/714022226810372107/1520160266120204409 +**To contribute to this fork please contact me on Discord, hopefully we can work together. I take ALL input and suggestions in, even if 're not a coder. If there's somethin wanna personally see in the game then please tell me.** https://discord.com/channels/714022226810372107/1520160266120204409 Best bet is to ask about everything in our Discord, because things bellow are probably not very helpful at the moment. - [CONTRIBUTING.md](https://github.com/Adeptus-Dominus/ChapterMaster/blob/main/docs/CONTRIBUTING.md) (required read before any contribution) From 54caf77f4f428ab6a02f0f882f759eea401eabe2 Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Sun, 5 Jul 2026 17:11:44 +0300 Subject: [PATCH 100/140] Fix formatting issues in README.md --- docs/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/README.md b/docs/README.md index 39dfdd8bb4..10d92b0618 100644 --- a/docs/README.md +++ b/docs/README.md @@ -18,21 +18,21 @@ This is an unofficial fan fork intended to preserve and expand the spirit of *Ch ## The biggest concrete changes -_Imperial Guard / Auxilia system_. Added real Guard-side content: Guardsmen, Guard Squads, Heavy Weapons Teams, and Guard Sergeants, with human base stats, Flak Armour, Lasguns, Bayonets, Heavy Bolters, Guard Chainswords, and Laspistols. +*****_Imperial Guard / Auxilia system_. Added real Guard-side content: Guardsmen, Guard Squads, Heavy Weapons Teams, and Guard Sergeants, with human base stats, Flak Armour, Lasguns, Bayonets, Heavy Bolters, Guard Chainswords, and Laspistols. -_Diplomatic recruitment and attached armour_. Sector Governor trade now raises Guardsmen directly at the homeworld, adds one Guard Sergeant per full squad, one Chimera per 200 Guardsmen, and one Heavy Weapons Team per 100 Guardsmen; Mechanicus trade can now provide Leman Russ tanks and Basilisks for the Auxilia company. +*****_Diplomatic recruitment and attached armour_. Sector Governor trade now raises Guardsmen directly at the homeworld, adds one Guard Sergeant per full squad, one Chimera per 200 Guardsmen, and one Heavy Weapons Team per 100 Guardsmen; Mechanicus trade can now provide Leman Russ tanks and Basilisks for the Auxilia company. -_New Astra Militarum wargear and vehicles_. Added or integrated Flak Armour, Lasguns, Hellguns, Earthshaker Cannons, Battle Cannons, Multi-Lasers, Chimeras, Leman Russ loadouts, and Basilisk artillery loadouts. -_ -Combat model overhaul._ Guard screens occupy forward columns, anti-tank weapons now have a dedicated target-preference threshold, volleys pierce armour walls by depth instead of passing through for free or vanishing, and Guardsmen split into capped lasgun stacks instead of forming one giant unrealistic volley. +*****_New Astra Militarum wargear and vehicles_. Added or integrated Flak Armour, Lasguns, Hellguns, Earthshaker Cannons, Battle Cannons, Multi-Lasers, Chimeras, Leman Russ loadouts, and Basilisk artillery loadouts. -_Better targeting, armour, and casualty logic_. Enemy weapons now prefer vehicles only when their AP role justifies it, Guard screens can actually shield vehicles behind them, column piercing works on both sides, partial volleys scale damage correctly, stale casualty reports are cleared, and vehicle armour penetration was fixed so enemy anti-tank weapons can actually hurt vehicles. +*****_Combat model overhaul._ Guard screens occupy forward columns, anti-tank weapons now have a dedicated target-preference threshold, volleys pierce armour walls by depth instead of passing through for free or vanishing, and Guardsmen split into capped lasgun stacks instead of forming one giant unrealistic volley. -_Fleet, assault, and campaign-layer additions._ Ships now have per-turn ground-assault support counters, planets have local assault counters, new ship defaults include Guard-related capacity fields, and lost-in-the-Warp ships can return with damage, corruption, mutiny, Chaos capture, or destruction outcomes. +*****_Better targeting, armour, and casualty logic_. Enemy weapons now prefer vehicles only when their AP role justifies it, Guard screens can actually shield vehicles behind them, column piercing works on both sides, partial volleys scale damage correctly, stale casualty reports are cleared, and vehicle armour penetration was fixed so enemy anti-tank weapons can actually hurt vehicles. -_Eldar campaign restoration and improvement_. Eldar are no longer only a hidden craftworld oddity: added incursion/intel settings, craftworld reveal requirements, first-contact clues, and Eldar ship speed tuning. +*****_Fleet, assault, and campaign-layer additions._ Ships now have per-turn ground-assault support counters, planets have local assault counters, new ship defaults include Guard-related capacity fields, and lost-in-the-Warp ships can return with damage, corruption, mutiny, Chaos capture, or destruction outcomes. -_Management UI and quality-of-life_. The management screen now recognizes an Auxilia company, includes richer unit profile UI/tooltips, and has buttons for squad view, profile, bio, and capture image. +*****_Eldar campaign restoration and improvement_. Eldar are no longer only a hidden craftworld oddity: added incursion/intel settings, craftworld reveal requirements, first-contact clues, and Eldar ship speed tuning. + +*****_Management UI and quality-of-life_. The management screen now recognizes an Auxilia company, includes richer unit profile UI/tooltips, and has buttons for squad view, profile, bio, and capture image. ## Compiling from source From dcbbb563ea9c373b5db1d92e95a95b19b92bb48b Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Sun, 5 Jul 2026 19:41:20 +0300 Subject: [PATCH 101/140] Update README with contributor acknowledgments Added acknowledgments for contributors Tavish and Chad Drywall in the README. --- docs/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/README.md b/docs/README.md index 10d92b0618..ed7cc8e968 100644 --- a/docs/README.md +++ b/docs/README.md @@ -45,6 +45,8 @@ This is an unofficial fan fork intended to preserve and expand the spirit of *Ch ## Contributing +BIG thanks to **Tavish** for the combat changes adapted and worked on from his LGW 1.2 fork and **Chad Drywall** for the new guardsmen/vehicle graphics + **To contribute to this fork please contact me on Discord, hopefully we can work together. I take ALL input and suggestions in, even if 're not a coder. If there's somethin wanna personally see in the game then please tell me.** https://discord.com/channels/714022226810372107/1520160266120204409 Best bet is to ask about everything in our Discord, because things bellow are probably not very helpful at the moment. From cc447e869558428620c905a0ad78dcede7e67d28 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 6 Jul 2026 00:45:40 +0300 Subject: [PATCH 102/140] Eldar warhosts: slower, taint-seeking, fight PDF, withdraw when done Raise ELDAR_INCURSION_INTERVAL from 15 to 35 turns. Warhost target selection now weights worlds with heresy, chaos or traitor presence ELDAR_TAINT_SPAWN_WEIGHT (5) times heavier than clean imperial worlds. Each incursion tick, warhosts already on the ground are processed: on a tainted world the warhost stays, battles the planetary defense force (p_pdf reduced by up to warhost strength, warhost takes occasional attrition, never below 1) and purges one point of heresy, chaos and traitor presence per tick; on a clean world it withdraws with an event log line, so warhosts no longer accumulate as permanent garrisons. Applies to existing saves immediately: no new saved state, departure is decided from world condition at tick time. Existing warhost buildup self-cleans on the next tick. --- scripts/macros/macros.gml | 8 ++- .../scr_controller_helpers.gml | 52 ++++++++++++++++--- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 513b1985c8..4fe813136e 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -68,11 +68,17 @@ // Eldar for the craftworld itself (its garrison is 6). ELDAR_FLEET_ENABLED gates the // craftworld's orbiting fleet, disabled for now so the reveal never forces Eldar // naval combat; flip to 1 to restore it. -#macro ELDAR_INCURSION_INTERVAL 15 +#macro ELDAR_INCURSION_INTERVAL 35 #macro ELDAR_INCURSION_FORCE_BASE 3 #macro ELDAR_INCURSION_FORCE_MAX 5 #macro ELDAR_INTEL_REQUIRED 3 #macro ELDAR_FLEET_ENABLED 1 +// Warhosts prefer worlds touched by the Great Enemy: a planet with heresy, chaos or +// traitor presence is this many times likelier to be struck than a clean one. On +// tainted worlds the warhost stays, battles the planetary defense force each +// incursion tick and purges the taint; on clean worlds it withdraws after one +// interval (its "secret mission" done) instead of garrisoning the sector forever. +#macro ELDAR_TAINT_SPAWN_WEIGHT 5 // Eldar naval combat tuning. Vanilla Eldar ships move at spid 60-100 while every other // faction's ships run 20-45, which is why fights against them degenerate into endless diff --git a/scripts/scr_controller_helpers/scr_controller_helpers.gml b/scripts/scr_controller_helpers/scr_controller_helpers.gml index e715d42fae..a5900e77c7 100644 --- a/scripts/scr_controller_helpers/scr_controller_helpers.gml +++ b/scripts/scr_controller_helpers/scr_controller_helpers.gml @@ -541,12 +541,14 @@ function eldar_intel_grant() { } /// @desc End-of-turn Eldar processing: fires the deferred craftworld reveal alert, -/// then every ELDAR_INCURSION_INTERVAL turns lands a warhost on a random inhabited -/// imperial world. Warhost strength ramps with collected intelligence -/// (FORCE_BASE + clues, capped at FORCE_MAX), keeping the strongest Eldar for the -/// craftworld itself. The planetary AI never acts on p_eldar (its pdf_attack line is -/// commented out upstream), so a landed warhost persists as a fightable target until -/// the player clears it. +/// then every ELDAR_INCURSION_INTERVAL turns processes warhosts on the ground +/// (tainted worlds: fight the PDF and purge the taint; clean worlds: withdraw) +/// and lands a new warhost on an inhabited imperial world, preferring worlds with +/// heresy, chaos or traitor presence (ELDAR_TAINT_SPAWN_WEIGHT). Warhost strength +/// ramps with collected intelligence (FORCE_BASE + clues, capped at FORCE_MAX), +/// keeping the strongest Eldar for the craftworld itself. The planetary AI never +/// acts on p_eldar (its pdf_attack line is commented out upstream); the fighting +/// on tainted worlds is handled here instead. function eldar_incursion_tick() { if (variable_instance_exists(obj_controller, "eldar_reveal_alert_pending") && obj_controller.eldar_reveal_alert_pending) { obj_controller.eldar_reveal_alert_pending = false; @@ -571,6 +573,38 @@ function eldar_incursion_tick() { if ((obj_controller.turn < ELDAR_INCURSION_INTERVAL) || ((obj_controller.turn % ELDAR_INCURSION_INTERVAL) != 0)) { return; } + // Process warhosts already on the ground before landing a new one. On a world + // touched by the Great Enemy (heresy, chaos or traitor presence) the warhost + // stays: it battles the planetary defense force (whose loyalty it does not + // trust) and purges the taint itself, taking attrition. On a clean world its + // secret mission is done and it withdraws, so warhosts stop accumulating as + // permanent garrisons across the sector. + with (obj_star) { + if (craftworld || space_hulk) { + continue; + } + for (var i = 1; i <= planets; i++) { + if (p_eldar[i] <= 0) { + continue; + } + var _tainted = (p_hurssy[i] > 0) || (p_chaos[i] > 0) || (p_traitors[i] > 0); + if (_tainted) { + if (p_pdf[i] > 0) { + p_pdf[i] = max(0, p_pdf[i] - irandom_range(1, p_eldar[i])); + if (irandom(2) == 0) { + p_eldar[i] = max(1, p_eldar[i] - 1); + } + scr_event_log("red", $"The Eldar warhost on {name} {scr_roman(i)} battles the planetary defense forces."); + } + p_hurssy[i] = max(0, p_hurssy[i] - 1); + p_chaos[i] = max(0, p_chaos[i] - 1); + p_traitors[i] = max(0, p_traitors[i] - 1); + } else { + p_eldar[i] = 0; + scr_event_log("green", $"The Eldar warhost on {name} {scr_roman(i)} has vanished as suddenly as it arrived."); + } + } + } var _force = min(ELDAR_INCURSION_FORCE_BASE + eldar_intel_count(), ELDAR_INCURSION_FORCE_MAX); var _targets = []; with (obj_star) { @@ -580,6 +614,12 @@ function eldar_incursion_tick() { for (var i = 1; i <= planets; i++) { if ((p_type[i] != "Dead") && (p_owner[i] >= 1) && (p_owner[i] <= 5) && (p_eldar[i] == 0)) { array_push(_targets, [id, i]); + // Tainted worlds draw the Eldar: weight them heavier in the pick. + if ((p_hurssy[i] > 0) || (p_chaos[i] > 0) || (p_traitors[i] > 0)) { + repeat (ELDAR_TAINT_SPAWN_WEIGHT - 1) { + array_push(_targets, [id, i]); + } + } } } } From 4b77febfab1a8502708e2c733fdf3cd304e9ac17 Mon Sep 17 00:00:00 2001 From: KestasV Date: Mon, 6 Jul 2026 00:53:18 +0300 Subject: [PATCH 103/140] Eldar warhosts: slower, taint-seeking, scour tainted worlds, withdraw when done Raise ELDAR_INCURSION_INTERVAL from 15 to 35 turns. Warhost target selection weights worlds with heresy, chaos or traitor presence ELDAR_TAINT_SPAWN_WEIGHT (5) times heavier than clean imperial worlds. Each incursion tick, warhosts on the ground are processed. On a tainted world the warhost scours it: ELDAR_PURGE_POP_FRACTION (25%) of the population is culled, the PDF is halved and reduced by warhost strength, the planet's Guard pool is halved, one point of heresy, chaos and traitor presence is purged, and the warhost takes occasional attrition (never below 1). A red alert and event log line announce the scouring so the player can intervene. On a clean world the warhost withdraws with an event log line, so warhosts no longer accumulate as permanent garrisons. Letting the Eldar handle chaos now costs the world its people; throwing them off a tainted world protects the population but leaves the taint. Applies to existing saves immediately: no new saved state. Existing warhost buildup self-cleans on the next tick. --- scripts/macros/macros.gml | 11 ++++++--- .../scr_controller_helpers.gml | 24 ++++++++++++------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 4fe813136e..0795ae0bed 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -74,11 +74,16 @@ #macro ELDAR_INTEL_REQUIRED 3 #macro ELDAR_FLEET_ENABLED 1 // Warhosts prefer worlds touched by the Great Enemy: a planet with heresy, chaos or -// traitor presence is this many times likelier to be struck than a clean one. On -// tainted worlds the warhost stays, battles the planetary defense force each -// incursion tick and purges the taint; on clean worlds it withdraws after one +// traitor presence is this many times likelier to be struck than a clean one. The +// Eldar do not do proportionality: on a tainted world the warhost stays and scours +// it each incursion tick, culling ELDAR_PURGE_POP_FRACTION of the population and +// ELDAR_PURGE_DEFENSE_FRACTION of the PDF and Guard while purging the taint, so +// leaving them to "clean up chaos for you" costs the world its people and clearing +// them off is a real choice. On clean worlds the warhost withdraws after one // interval (its "secret mission" done) instead of garrisoning the sector forever. #macro ELDAR_TAINT_SPAWN_WEIGHT 5 +#macro ELDAR_PURGE_POP_FRACTION 0.25 +#macro ELDAR_PURGE_DEFENSE_FRACTION 0.5 // Eldar naval combat tuning. Vanilla Eldar ships move at spid 60-100 while every other // faction's ships run 20-45, which is why fights against them degenerate into endless diff --git a/scripts/scr_controller_helpers/scr_controller_helpers.gml b/scripts/scr_controller_helpers/scr_controller_helpers.gml index a5900e77c7..a5d8e468e2 100644 --- a/scripts/scr_controller_helpers/scr_controller_helpers.gml +++ b/scripts/scr_controller_helpers/scr_controller_helpers.gml @@ -542,8 +542,8 @@ function eldar_intel_grant() { /// @desc End-of-turn Eldar processing: fires the deferred craftworld reveal alert, /// then every ELDAR_INCURSION_INTERVAL turns processes warhosts on the ground -/// (tainted worlds: fight the PDF and purge the taint; clean worlds: withdraw) -/// and lands a new warhost on an inhabited imperial world, preferring worlds with +/// (tainted worlds: scour the population, PDF and Guard while purging the taint; +/// clean worlds: withdraw) and lands a new warhost on an inhabited imperial world, preferring worlds with /// heresy, chaos or traitor presence (ELDAR_TAINT_SPAWN_WEIGHT). Warhost strength /// ramps with collected intelligence (FORCE_BASE + clues, capped at FORCE_MAX), /// keeping the strongest Eldar for the craftworld itself. The planetary AI never @@ -589,16 +589,24 @@ function eldar_incursion_tick() { } var _tainted = (p_hurssy[i] > 0) || (p_chaos[i] > 0) || (p_traitors[i] > 0); if (_tainted) { - if (p_pdf[i] > 0) { - p_pdf[i] = max(0, p_pdf[i] - irandom_range(1, p_eldar[i])); - if (irandom(2) == 0) { - p_eldar[i] = max(1, p_eldar[i] - 1); - } - scr_event_log("red", $"The Eldar warhost on {name} {scr_roman(i)} battles the planetary defense forces."); + // The Eldar do not do proportionality. Any trace of the Great Enemy + // condemns the world: each incursion tick the warhost culls a large + // share of the population, cuts the defense forces and Guard down, + // and purges the taint itself, taking some attrition in return. + // Letting a warhost squat on a tainted world is therefore expensive, + // and clearing them off it is a real decision rather than free + // chaos-cleanup. + p_population[i] = max(0, p_population[i] - floor(p_population[i] * ELDAR_PURGE_POP_FRACTION)); + p_pdf[i] = max(0, floor(p_pdf[i] * (1 - ELDAR_PURGE_DEFENSE_FRACTION)) - p_eldar[i]); + p_guardsmen[i] = max(0, floor(p_guardsmen[i] * (1 - ELDAR_PURGE_DEFENSE_FRACTION))); + if (irandom(2) == 0) { + p_eldar[i] = max(1, p_eldar[i] - 1); } p_hurssy[i] = max(0, p_hurssy[i] - 1); p_chaos[i] = max(0, p_chaos[i] - 1); p_traitors[i] = max(0, p_traitors[i] - 1); + scr_alert("red", "elfs", $"The Eldar have judged {name} {scr_roman(i)} tainted and are putting its population to the sword.", x, y); + scr_event_log("red", $"The Eldar warhost scours {name} {scr_roman(i)}: the defense forces are cut down and the population culled."); } else { p_eldar[i] = 0; scr_event_log("green", $"The Eldar warhost on {name} {scr_roman(i)} has vanished as suddenly as it arrived."); From b5a55915ea0a1cf6da722ac4e0c04d28b1fcc6b5 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 03:56:15 +0300 Subject: [PATCH 104/140] Fix enemy firing on wrong column (get_leftmost/rightmost); keep formation together get_leftmost and get_rightmost in scr_punit_combat_heplers seeded their result with block_type.id on the first valid block. Inside with (block_type), block_type.id resolves to obj_pnunit.id, the first instance in the list, not the current instance (id), so the first valid block was recorded as the first-created block. When that block was not the actual edge, the function returned the wrong block and the enemy fired on the wrong column even with the formation in correct order (a flanking force, which targets get_leftmost, hit the bulk block created first instead of the rear column closest to it). Both now assign id. Bug exists verbatim in upstream main; relayed to Tavish. Also make the player formation advance as a body and halt together the moment any block reaches the enemy line ahead (obj_ncombat .player_front_contact, latched per battle), replacing the per-block auto-advance that let front blocks pull ahead while rear blocks froze at spawn, so the line kept its shape and spacing. The move_order seed moves above the dead-enemy early-exit so frozen blocks still show a marker. Re-add the empty-target "strikes at ." guard in scr_flavor2, lost when a prior drop was not committed. Runtime combat logic only; no new game required. --- options/mac/options_mac.yy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/options/mac/options_mac.yy b/options/mac/options_mac.yy index a92ce6ebe4..b94080f074 100644 --- a/options/mac/options_mac.yy +++ b/options/mac/options_mac.yy @@ -35,4 +35,4 @@ "option_mac_x86_64":true, "resourceType":"GMMacOptions", "resourceVersion":"2.0", -} +} \ No newline at end of file From 0b834f97d8d66f465e731aed9490c52a93dfa10a Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 04:01:03 +0300 Subject: [PATCH 105/140] Fix enemy firing on wrong column (get_leftmost/get_rightmost), Preserve planet numeral when truncating unit locations get_leftmost and get_rightmost in scr_punit_combat_heplers seeded their result with block_type.id on the first valid block. Inside with (block_type), block_type.id resolves to obj_pnunit.id, the first instance in the list, not the current instance (id), so the first valid block was recorded as the first-created block. When that block was not the actual edge, the function returned the wrong block and the enemy fired on the wrong column even with the formation in correct order (a flanking force, which targets get_leftmost, hit the bulk block created first instead of the rear column closest to it). Both now assign id. Bug exists verbatim in upstream main; relayed to Tavish. Add string_truncate_planet: like string_truncate but keeps a trailing planet numeral, so "Mandragoran III" truncates to "Mandrag... III" instead of dropping the numeral and rendering squads on different planets in one system as identical "Mandragoran II..." rows. The numeral is detected by matching the tokens scr_roman appends, longest match first so IV is not read as a bare V; strings with no numeral (ship names, =Penitorium=, =Event=) fall back to plain string_truncate. Used for the location label in scr_draw_management_unit. --- .../scr_draw_management_unit.gml | 2 +- .../scr_punit_combat_heplers.gml | 17 +++++- .../scr_string_functions.gml | 56 +++++++++++++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/scripts/scr_draw_management_unit/scr_draw_management_unit.gml b/scripts/scr_draw_management_unit/scr_draw_management_unit.gml index 8a93c28e0d..3d72be33fa 100644 --- a/scripts/scr_draw_management_unit/scr_draw_management_unit.gml +++ b/scripts/scr_draw_management_unit/scr_draw_management_unit.gml @@ -347,7 +347,7 @@ function scr_draw_management_unit(selected, yy = 0, xx = 0, draw = true, click_l if (location_out_of_player_control(unit_location_string) || (unit_location_string == "=Penitorium=") || (assignment != "none")) { draw_set_alpha(0.5); } - var truncatedLocation = string_truncate(string(unit_location_string), 130); // Truncate the location string to 100 pixels + var truncatedLocation = string_truncate_planet(string(unit_location_string), 130); // Truncate but keep the planet numeral draw_text(xx + 430 + 8, yy + 66, truncatedLocation); // LOC draw_set_alpha(1); diff --git a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml index d1157d6b41..3ce16b7295 100644 --- a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml +++ b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml @@ -74,7 +74,14 @@ function get_rightmost(block_type = obj_pnunit, include_flanking = true, include } } if (rightmost == noone && x > 0) { - rightmost = block_type.id; + // Was block_type.id, which resolves to obj_pnunit.id (the first + // instance in the list) rather than the current instance in this + // with-loop, so the first valid block reaching here was recorded as + // whatever block was created first. When that first-created block + // was not the actual edge, get_rightmost returned the wrong block + // and the enemy fired on the wrong column even with the formation + // in correct order. Bug exists verbatim in upstream main. + rightmost = id; } else { if (x > rightmost.x) { rightmost = id; @@ -115,7 +122,13 @@ function get_leftmost(block_type = obj_pnunit, include_flanking = true) { } } if (left_most == noone && x > 0) { - left_most = block_type.id; + // Same bug as get_rightmost above: block_type.id is the first + // instance in the list, not the current one, so the first valid + // block was recorded as the first-created block. This is why a + // flanking force (which targets get_leftmost, the rear column) hit + // the wrong line, striking the bulk block created first rather than + // the block actually closest to it. Bug exists verbatim in upstream. + left_most = id; } else { if (x < left_most.x && x > 0) { left_most = id; diff --git a/scripts/scr_string_functions/scr_string_functions.gml b/scripts/scr_string_functions/scr_string_functions.gml index d0af0b475c..da1b68bbbf 100644 --- a/scripts/scr_string_functions/scr_string_functions.gml +++ b/scripts/scr_string_functions/scr_string_functions.gml @@ -127,6 +127,62 @@ function string_truncate(_string, _max_width) { } } +/// @function string_truncate_planet +/// @description Like string_truncate, but preserves a trailing planet numeral so a +/// location such as "Mandragoran III" truncates to "Mandrag... III" instead +/// of chopping the numeral off the end. Keeps squads assigned to different +/// planets in the same system distinguishable in the management list. +/// Strings with no planet numeral (ship names, "=Penitorium=", "=Event=") +/// fall back to plain string_truncate. +/// @param {string} _string +/// @param {real} _max_width The maximum allowable pixel width for the string. +/// @returns {string} +function string_truncate_planet(_string, _max_width) { + _string = string(_string); + if (string_width(_string) <= _max_width) { + return _string; + } + + // Detect a trailing planet numeral by matching the numerals the game actually + // appends (scr_roman). Longest match wins so "IV" is not mistaken for a bare + // trailing "V", and matching known tokens avoids splitting a name that merely ends + // in a roman-numeral letter. + var _numeral = ""; + var _name = _string; + var _best_len = 0; + for (var n = 1; n <= 12; n++) { + var _r = scr_roman(n); + if (is_undefined(_r) || (_r == "")) { + continue; + } + var _rlen = string_length(_r); + if ((_rlen > _best_len) && (string_length(_string) > _rlen) && (string_copy(_string, string_length(_string) - _rlen + 1, _rlen) == _r)) { + _best_len = _rlen; + _numeral = _r; + _name = string_copy(_string, 1, string_length(_string) - _rlen); + } + } + + if (_numeral == "") { + return string_truncate(_string, _max_width); + } + + // Drop any spaces the name had before the numeral; a single separating space is + // re-added with the ellipsis. + while ((string_length(_name) > 0) && (string_char_at(_name, string_length(_name)) == " ")) { + _name = string_copy(_name, 1, string_length(_name) - 1); + } + + var _tail = "... " + _numeral; + var _tail_width = string_width(_tail); + var _name_trunc = _name; + while (((string_width(_name_trunc) + _tail_width) > _max_width) && (string_length(_name_trunc) > 0)) { + _name_trunc = string_copy(_name_trunc, 1, string_length(_name_trunc) - 1); + } + + return _name_trunc + _tail; +} + /// @function integer_to_words /// @description Converts an integer to an english word. /// @param {real} _integer From 93ece5633b2e835f4ef1700326190d167ebeee06 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 04:08:59 +0300 Subject: [PATCH 106/140] Keep player formation together on advance; re-add empty-target guard Make the player formation advance as a body and halt together the moment any block reaches the enemy line ahead (obj_ncombat.player_front_contact, latched per battle), replacing the per-block auto-advance that opened gaps: when a block's front enemy died it surged east into the vacated space while blocks still engaged held, separating the line even in correct order, and blocks whose turn came after the enemy was gone froze mid-field with no marker. The latch only trips on east-side contact so rear-spawning flankers don't freeze the main advance. The move_order seed moves above the dead-enemy early-exit so frozen blocks still show a marker. Manually ordered blocks (order_manual) still advance and leapfrog freely. Re-add the empty-target "strikes at ." guard in scr_flavor2, lost again on the remote. Runtime combat logic only; no new game required. --- objects/obj_ncombat/Create_0.gml | 5 +++ objects/obj_pnunit/Alarm_0.gml | 49 ++++++++++++++++++++--------- scripts/scr_flavor2/scr_flavor2.gml | 7 +++++ 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index 4674645234..46b7bdaa47 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -245,6 +245,11 @@ en_big_mofo = 10; defending = true; // 1 is defensive dropping = false; // 0 is was on ground +// Basic combat orders: latched true the first time any player block reaches the +// enemy line to its front (east), which stops the formation-wide auto-advance so +// the line holds at contact instead of individual blocks surging into gaps as +// enemies die. Reset per battle here. +player_front_contact = false; attacking = 0; // 1 means attacked from space/local time = floor(random(24)) + 1; terrain = ""; diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index 99934e9f88..3c95d159cf 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -1,4 +1,14 @@ try { + // Basic combat orders: seed each block's move_order on its first tick from the + // vanilla movement rule (raids and attacks advance to contact, defense and the + // static formation hold), toggled by clicking the block's bar (obj_pnunit + // Step_0). Seeded here, above the dead-enemy early-exit below, so a block whose + // turn comes after the enemy is already destroyed still shows its order marker + // instead of a blank column. + if (move_order == "") { + move_order = (obj_ncombat.dropping || (!obj_ncombat.defending && obj_ncombat.formation_set != 2)) ? "advance" : "hold"; + } + if (instance_number(obj_enunit) != 1) { obj_ncombat.flank_x = self.x; with (obj_enunit) { @@ -19,25 +29,36 @@ try { exit; } - // Basic combat orders: every block carries a move_order ("advance" or "hold"), - // seeded on its first tick from the vanilla movement rule (raids and attacks - // advance, defense and the static formation hold) and toggled by clicking the - // block's bar (obj_pnunit Step_0). Advancing blocks may leapfrog over friendly - // blocks directly ahead. The Defenses pseudo-block takes no orders and never - // moves. - if (move_order == "") { - move_order = (obj_ncombat.dropping || (!obj_ncombat.defending && obj_ncombat.formation_set != 2)) ? "advance" : "hold"; - } + // Auto-advance to contact: the enemy never moves (its own movement is commented + // out below), so an advancing formation has to close the gap itself. It advances + // as a body, one column per tick, and the WHOLE formation stops the moment any + // block reaches the enemy line (obj_ncombat.player_front_contact latches once and + // is not reset during the battle). This replaces the per-block auto-advance that + // let the formation drift apart: when a block's own front enemy died it surged + // east into the vacated space while blocks still engaged held, opening gaps even + // with the line in correct order, and blocks whose turn came after the enemy was + // gone froze mid-field with no order marker. A block the player has personally + // ordered (order_manual) still advances and leapfrogs freely for manual maneuver, + // ignoring the latch. if ((move_order == "advance") && (veh_type[1] != "Defenses")) { - // Leapfrogging only for blocks the player has clicked (order_manual): - // default auto-advance keeps vanilla stall behavior, otherwise same-tick - // processing order and an engaged front line make rear blocks vault their - // own formation with no orders given. - move_unit_block("east", 1, false, order_manual); + if (order_manual) { + move_unit_block("east", 1, false, true); + } else if (!obj_ncombat.player_front_contact) { + move_unit_block("east", 1, false, false); + } } engaged = collision_point(x - 14, y, obj_enunit, 0, 1) != noone || collision_point(x + 14, y, obj_enunit, 0, 1) != noone; + // Latch formation contact the first time any block reaches the enemy line to its + // east (the front). Flankers spawn behind the formation to the west, so a west + // side (x - 14) touch must not trip the latch or the main body would stop closing + // with the enemy ahead. Never reset during the battle: once the line is met the + // formation holds instead of surging into gaps as enemies die. + if (collision_point(x + 14, y, obj_enunit, 0, 1)) { + obj_ncombat.player_front_contact = true; + } + var once_only = 0; var range_shoot = ""; var dist = point_distance(x, y, enemy.x, enemy.y) / 10; diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index 9db3ec4bd3..4d8d69f8a1 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -40,6 +40,13 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo _hostile_shots = max(1, round(_hostile_shots / 3)); } + // A resolution that attributed no unit at all (damage_data.unit_type left empty: + // the shot landed on a block whose relevant pool was already gone) produces + // "X strikes at ." lines. They carry no information; skip them entirely. + if ((target_type == "") && (lost_units_count == 0)) { + exit; + } + // Target readout: the bare unit name ("strikes at Assault") says nothing about what // was hit or how many stand there. Append the block's living strength for that unit // type. scr_flavor2 runs in the target block's own scope, so the arrays are directly From f130d6db68524441b6f521bff1933a52968947e0 Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Tue, 7 Jul 2026 04:47:59 +0300 Subject: [PATCH 107/140] Update README with additional contributor acknowledgment Added acknowledgment for Claude Fable 5 and Opus 4.8 in the contributing section. --- docs/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/README.md b/docs/README.md index ed7cc8e968..2bfdc060f6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -46,6 +46,7 @@ This is an unofficial fan fork intended to preserve and expand the spirit of *Ch ## Contributing BIG thanks to **Tavish** for the combat changes adapted and worked on from his LGW 1.2 fork and **Chad Drywall** for the new guardsmen/vehicle graphics +This mod was made with assistance from Claude Fable 5 and Opus 4.8 on code consultation **To contribute to this fork please contact me on Discord, hopefully we can work together. I take ALL input and suggestions in, even if 're not a coder. If there's somethin wanna personally see in the game then please tell me.** https://discord.com/channels/714022226810372107/1520160266120204409 Best bet is to ask about everything in our Discord, because things bellow are probably not very helpful at the moment. From a51d8e876f6a36c5a805156c162d076c37478fc4 Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Tue, 7 Jul 2026 04:50:57 +0300 Subject: [PATCH 108/140] Fix contributor reference in README Corrected the reference to Tavish's fork in the contributing section. --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 2bfdc060f6..d034732a03 100644 --- a/docs/README.md +++ b/docs/README.md @@ -45,7 +45,7 @@ This is an unofficial fan fork intended to preserve and expand the spirit of *Ch ## Contributing -BIG thanks to **Tavish** for the combat changes adapted and worked on from his LGW 1.2 fork and **Chad Drywall** for the new guardsmen/vehicle graphics +BIG thanks to **Tavish** for the combat changes adapted and worked on from his "LW_Beta_1.2" fork and **Chad Drywall** for the new guardsmen/vehicle graphics This mod was made with assistance from Claude Fable 5 and Opus 4.8 on code consultation **To contribute to this fork please contact me on Discord, hopefully we can work together. I take ALL input and suggestions in, even if 're not a coder. If there's somethin wanna personally see in the game then please tell me.** https://discord.com/channels/714022226810372107/1520160266120204409 From 58697f70068e236f8a69f2a0cde0945a3b7f4d60 Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Tue, 7 Jul 2026 04:52:56 +0300 Subject: [PATCH 109/140] Update README to remove contributor acknowledgment Removed mention of Chad Drywall from the contributing section. --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index d034732a03..e09cd898fd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -45,7 +45,7 @@ This is an unofficial fan fork intended to preserve and expand the spirit of *Ch ## Contributing -BIG thanks to **Tavish** for the combat changes adapted and worked on from his "LW_Beta_1.2" fork and **Chad Drywall** for the new guardsmen/vehicle graphics +BIG thanks to **Tavish** for the combat changes adapted and worked on from his "LW_Beta_1.2" fork This mod was made with assistance from Claude Fable 5 and Opus 4.8 on code consultation **To contribute to this fork please contact me on Discord, hopefully we can work together. I take ALL input and suggestions in, even if 're not a coder. If there's somethin wanna personally see in the game then please tell me.** https://discord.com/channels/714022226810372107/1520160266120204409 From 5943209fc0e92eb6e506711ffa08ea319b04319e Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 05:10:30 +0300 Subject: [PATCH 110/140] Restored Grazing hits to full functionality and fixed them Now they appear both in enemy ranks and in player ranks instead of using the old, gated ". " fix --- objects/obj_ncombat/Create_0.gml | 4 ++++ scripts/scr_flavor/scr_flavor.gml | 24 ++++++++++++++++++------ scripts/scr_shoot/scr_shoot.gml | 6 +++++- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/objects/obj_ncombat/Create_0.gml b/objects/obj_ncombat/Create_0.gml index 46b7bdaa47..b9154fe76e 100644 --- a/objects/obj_ncombat/Create_0.gml +++ b/objects/obj_ncombat/Create_0.gml @@ -180,6 +180,10 @@ combat_log.log_font = fnt_aldrich_12; ctally_target = undefined; ctally_bounce = []; ctally_injure = []; +// Grazing flavor: worst wound severity (0..1) and vehicle flag for the current injured +// tally group, so the consolidated wound line can be graded like the enemy side's. +ctally_injure_severity = 0; +ctally_is_vehicle = false; ktally_target = undefined; ktally_weapons = {}; ktally_order = []; diff --git a/scripts/scr_flavor/scr_flavor.gml b/scripts/scr_flavor/scr_flavor.gml index 953c1468e3..ecc29dc2c4 100644 --- a/scripts/scr_flavor/scr_flavor.gml +++ b/scripts/scr_flavor/scr_flavor.gml @@ -67,7 +67,7 @@ function report_held_fire(_weapon_names) { add_battle_log_message($"{_list} held fire lacking live targets.", eMSG_COLOR.WHITE); } -function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shots, casulties, shots_bounced = false, _defer = false) { +function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shots, casulties, shots_bounced = false, _defer = false, _graze_severity = 0) { // Generates flavor based on the damage and casualties from scr_shoot, only for the player // shots_bounced: true when armour stopped the shots outright (AP too low) and nothing died, // so the log can explain *why* instead of a flat "no casualties". @@ -750,6 +750,8 @@ function scr_flavor(id_of_attacking_weapons, target, target_type, number_of_shot color: message_color, bounced: (shots_bounced && casulties == 0), injured: (!shots_bounced && casulties == 0), + severity: _graze_severity, + is_vehicle: (instance_exists(target) ? (target.dudes_vehicle[targeh] != 0) : false), target: target_name, subject: firing_subject, weapon: weapon_plural, @@ -804,7 +806,7 @@ function emit_volley_flavour(_primary, _spill_kills) { // consolidate into one chronological line per target instead of one line per weapon. if (is_struct(_primary) && (_primary.bounced || _primary.injured) && _list == "") { combat_kill_tally_flush(); - combat_tally_add(_primary.target, _primary.subject, _primary.injured); + combat_tally_add(_primary.target, _primary.subject, _primary.injured, _primary.severity, _primary.is_vehicle); return; } @@ -848,13 +850,17 @@ function emit_volley_flavour(_primary, _spill_kills) { /// @desc Buffers a non-killing volley (wound or armour-bounce) against a target. Consecutive volleys /// on the same target merge; switching target flushes the previous one, keeping the log /// chronological. _injured true = penetrated but no kill; false = bounced off armour. -function combat_tally_add(_target, _subject, _injured) { +function combat_tally_add(_target, _subject, _injured, _severity = 0, _is_vehicle = false) { if (obj_ncombat.ctally_target != _target) { combat_tally_flush(); obj_ncombat.ctally_target = _target; } if (_injured) { array_push(obj_ncombat.ctally_injure, _subject); + // Keep the worst wound in the group so the consolidated line grades by the + // heaviest hit, and remember whether the target is a vehicle for the tier table. + obj_ncombat.ctally_injure_severity = max(obj_ncombat.ctally_injure_severity, _severity); + obj_ncombat.ctally_is_vehicle = _is_vehicle; } else { array_push(obj_ncombat.ctally_bounce, _subject); } @@ -867,9 +873,13 @@ function combat_tally_flush() { } var _t = obj_ncombat.ctally_target; if (array_length(obj_ncombat.ctally_injure) > 0) { - // Light green for wounded-but-standing, per Tavish's CM-Poligon color coding - // (CptMacTavish2224, tag LW_Beta_1.2). - add_battle_log_message($"Fire from {combat_subject_join(obj_ncombat.ctally_injure)} wounded the {_t} but didn't bring it down.", eMSG_COLOR.LIGHTGREEN); + // Grade the wound by how much got through, reusing the enemy side's severity tiers + // (incoming_damage_flavor). Injured means damage landed, so floor the severity at the + // graze tier (0.10) so it never shows the "shrugged off" band. Light green for + // wounded-but-standing, per Tavish's CM-Poligon color coding (CptMacTavish2224, + // tag LW_Beta_1.2). + var _wound_grade = incoming_damage_flavor(max(0.10, obj_ncombat.ctally_injure_severity), obj_ncombat.ctally_is_vehicle); + add_battle_log_message($"Fire from {combat_subject_join(obj_ncombat.ctally_injure)} hits the {_t}. {_wound_grade}", eMSG_COLOR.LIGHTGREEN); } if (array_length(obj_ncombat.ctally_bounce) > 0) { add_battle_log_message($"Fire from {combat_subject_join(obj_ncombat.ctally_bounce)} cannot penetrate the {_t}'s armour.", eMSG_COLOR.WHITE); @@ -877,6 +887,8 @@ function combat_tally_flush() { obj_ncombat.ctally_target = undefined; obj_ncombat.ctally_bounce = []; obj_ncombat.ctally_injure = []; + obj_ncombat.ctally_injure_severity = 0; + obj_ncombat.ctally_is_vehicle = false; } /// @desc Buffers killing volleys that share a weapon and target, summing shots and kills so a split diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index 423af06a1e..9ce105f7bf 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -377,7 +377,11 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat // the full weapon count); later targets just contribute to the kill list. // final_hit <= 0 means armour stopped the shots cold (AP too low). if (_first_target) { - _primary_flavour = scr_flavor(weapon_index_position, spill_block, spill_rank, shots_fired, casualties, final_hit <= 0, true); + // Grazing severity for the wound-no-kill case: how far this volley's + // damage got toward killing one model (0..1), so scr_flavor can grade the + // player's wound line the way the enemy side already grades incoming fire. + var _graze_sev = ((final_hit > 0) && (casualties == 0) && (rank_hp > 0)) ? clamp(total_damage / rank_hp, 0, 1) : 0; + _primary_flavour = scr_flavor(weapon_index_position, spill_block, spill_rank, shots_fired, casualties, final_hit <= 0, true, _graze_sev); _first_target = false; } else if (casualties > 0) { array_push(_spill_kills, { name: spill_block.dudes[spill_rank], count: casualties }); From 1456c434026578f3cb088bf4e89d71e0e723226c Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Tue, 7 Jul 2026 06:04:32 +0300 Subject: [PATCH 111/140] Enhance contributing section in README Updated README to acknowledge contributors and provide contact information for contributions. --- docs/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/README.md b/docs/README.md index e09cd898fd..5e624a60a0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -46,8 +46,11 @@ This is an unofficial fan fork intended to preserve and expand the spirit of *Ch ## Contributing BIG thanks to **Tavish** for the combat changes adapted and worked on from his "LW_Beta_1.2" fork +Another big thanks to Tophat#7692 for testing and helping with the design. Half of the errors, bugs and design ideas wouldn't have been possible without you +And shoutouts to the developers at main for upkeeping this old legacy code so i can work on improvements! This mod was made with assistance from Claude Fable 5 and Opus 4.8 on code consultation + **To contribute to this fork please contact me on Discord, hopefully we can work together. I take ALL input and suggestions in, even if 're not a coder. If there's somethin wanna personally see in the game then please tell me.** https://discord.com/channels/714022226810372107/1520160266120204409 Best bet is to ask about everything in our Discord, because things bellow are probably not very helpful at the moment. From cbb52b803dd7a4727bc7ce9956c8930b7d106f80 Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Tue, 7 Jul 2026 06:05:44 +0300 Subject: [PATCH 112/140] Improve contributor acknowledgments in README Enhanced acknowledgments section with bold formatting for contributors. --- docs/README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 5e624a60a0..1eb43efc59 100644 --- a/docs/README.md +++ b/docs/README.md @@ -45,12 +45,17 @@ This is an unofficial fan fork intended to preserve and expand the spirit of *Ch ## Contributing -BIG thanks to **Tavish** for the combat changes adapted and worked on from his "LW_Beta_1.2" fork -Another big thanks to Tophat#7692 for testing and helping with the design. Half of the errors, bugs and design ideas wouldn't have been possible without you -And shoutouts to the developers at main for upkeeping this old legacy code so i can work on improvements! +**++**BIG thanks to **Tavish** for the combat changes adapted and worked on from his "LW_Beta_1.2" fork**++** + +**++**Another big thanks to Tophat#7692 for testing and helping with the design. Half of the errors, bugs and design ideas wouldn't have been possible without you**++** + +**++**And shoutouts to the developers at main for upkeeping this old legacy code so i can work on improvements!**++** + This mod was made with assistance from Claude Fable 5 and Opus 4.8 on code consultation + + **To contribute to this fork please contact me on Discord, hopefully we can work together. I take ALL input and suggestions in, even if 're not a coder. If there's somethin wanna personally see in the game then please tell me.** https://discord.com/channels/714022226810372107/1520160266120204409 Best bet is to ask about everything in our Discord, because things bellow are probably not very helpful at the moment. From a1db3c7d3135aede5dd97a209bddd82bc1869511 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 08:53:35 +0300 Subject: [PATCH 113/140] Clean up fork-owned Feather scope warnings (no upstream files) Resolve the 15 GM2043/GM2044 Feather warnings in fork-owned files by making variable scope explicit. Behavior-neutral: GML already hoists var to function/event scope, so these only make the shared scope explicit. - scr_shoot: declare attack_count_mod once at function scope (init 1), drop the inner var (clears 5 GM2043 at 294/300/316/362/368). - obj_enunit Alarm_0: declare enemy2 once at event scope, drop the two inner vars (clears 5 GM2043 at 270-278). - scr_player_combat_weapon_stacks: stop re-declaring i/g in four for loops, using the existing var i, g (clears 4 GM2044). - scr_management: stop re-declaring _auxilia_units (clears 1 GM2044). Upstream-owned files (scr_ComplexSet, scr_marine_struct, scr_buttons, scr_equipment_struct, obj_controller) are intentionally left untouched to avoid merge conflicts against Adeptus Dominus; their warnings are harmless style flags. --- objects/obj_enunit/Alarm_0.gml | 10 ++++++++-- scripts/scr_management/scr_management.gml | 2 +- .../scr_player_combat_weapon_stacks.gml | 8 ++++---- scripts/scr_shoot/scr_shoot.gml | 7 ++++++- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/objects/obj_enunit/Alarm_0.gml b/objects/obj_enunit/Alarm_0.gml index c1fbc8e40c..bb5678cd0c 100644 --- a/objects/obj_enunit/Alarm_0.gml +++ b/objects/obj_enunit/Alarm_0.gml @@ -9,6 +9,12 @@ if (enemy == noone) { exit; } +// enemy2 is used across several sibling blocks below (the two column-piercing +// passes and the older melee/vehicle chain). Declare it once here at event scope; +// GML hoists var anyway, so this only makes the shared scope explicit and silences +// the GM2043 "outside its scope" warnings. +var enemy2 = noone; + //In melee check engaged = collision_point(x - 10, y, obj_pnunit, 0, 1) || collision_point(x + 10, y, obj_pnunit, 0, 1); @@ -101,7 +107,7 @@ if (!engaged) { var x2 = enemy.x; repeat (instance_number(obj_pnunit) - 1) { x2 += flank == 0 ? -10 : 10; - var enemy2 = instance_nearest(x2, y, obj_pnunit); + enemy2 = instance_nearest(x2, y, obj_pnunit); if (!target_block_is_valid(enemy2, obj_pnunit)) { continue; } @@ -208,7 +214,7 @@ if (!engaged) { if (array_length(_lines) >= PIERCE_MAX_DEPTH) { break; } - var enemy2 = _behind[b]; + enemy2 = _behind[b]; if (!target_block_is_valid(enemy2, obj_pnunit)) { continue; } diff --git a/scripts/scr_management/scr_management.gml b/scripts/scr_management/scr_management.gml index d416d61509..17ad1579c4 100644 --- a/scripts/scr_management/scr_management.gml +++ b/scripts/scr_management/scr_management.gml @@ -69,7 +69,7 @@ function scr_management(argument0) { var _auxilia_units = collect_role_group("all", "", false, {roles: auxilia_roles()}, true); - var _auxilia_units = _auxilia_units.index_roles(); + _auxilia_units = _auxilia_units.index_roles(); pane.line = array_join(pane.line, _auxilia_units.create_plural_strings_array()); diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index e299516d38..aee37b397d 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -266,7 +266,7 @@ function scr_player_combat_weapon_stacks() { veh = 0; men = 0; dreads = 0; - for (var i = 0; i < array_length(att); i++) { + for (i = 0; i < array_length(att); i++) { dudes_num[i] = 0; att[i] = 0; apa[i] = 0; @@ -277,7 +277,7 @@ function scr_player_combat_weapon_stacks() { var dreaded = false; - for (var g = 0; g < array_length(unit_struct); g++) { + for (g = 0; g < array_length(unit_struct); g++) { var unit = unit_struct[g]; if (is_struct(unit)) { if (unit.hp() > 0) { @@ -428,7 +428,7 @@ function scr_player_combat_weapon_stacks() { } } } - for (var g = 0; g < array_length(veh_id); g++) { + for (g = 0; g < array_length(veh_id); g++) { if ((veh_id[g] > 0) && (veh_hp[g] > 0) && (veh_dead[g] != 1)) { if ((veh_id[g] > 0) && (veh_hp[g] > 0)) { veh_dead[g] = 0; @@ -491,7 +491,7 @@ function scr_player_combat_weapon_stacks() { if ((men == 1) && (veh == 0) && (obj_ncombat.player_forces == 1)) { var h = 0; - for (var i = 0; i < array_length(unit_struct); i++) { + for (i = 0; i < array_length(unit_struct); i++) { if (h == 0) { var unit = unit_struct[i]; if (!is_struct(unit)) { diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index 9ce105f7bf..9b2e3a8d6a 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -12,6 +12,11 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat // (column piercing), only the first call spends the turn's ammo tick. // This massive clusterfuck of a script uses the newly determined weapon and target data to attack and assign damage + // attack_count_mod is declared once here at function scope. It is set in the + // early weapon block and reset/recomputed in the that_works damage block; GML + // hoists var to function scope anyway, so this only makes the shared scope + // explicit and silences the GM2043 "outside its scope" warnings. + var attack_count_mod = 1; var hostile_type; var hostile_damage; var hostile_weapon; @@ -88,7 +93,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat damage_type = "status"; } - var attack_count_mod = max(1, splash[weapon_index_position]); + attack_count_mod = max(1, splash[weapon_index_position]); if ((damage_type == "status") && (stop == 0) && (shots_fired > 0)) { var damage_per_weapon = 0, hit_number = shots_fired; From 3cf3ad1907766fef3162b3cc6362b9992667c7ff Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 09:00:29 +0300 Subject: [PATCH 114/140] Eldar: variable incursion cadence, clue expiry, craftworld relocation Replace the fixed 35-turn incursion modulo with a scheduled cadence that picks the next strike a random ELDAR_INTERVAL_MIN..ELDAR_INTERVAL_MAX (30..60) turns out, so warhost arrivals are not perfectly predictable. Gathered intelligence now stamps the turn (eldar_intel_turn). If the hunt is not completed and acted on within ELDAR_CLUE_EXPIRY (400) turns, the clues are lost and the craftworld relocates: eldar_craftworld_relocate() moves the craftworld and its escort fleet to a fresh position under the same worldgen placement constraints, re-hides both (known -> 0, vision 0, fleet alpha 0) and resets intel. Allied Eldar (known >= 2) are exempt. 400 is sized well above a sector crossing (~40-50 turns) so there is ample time to locate, travel to and assault the craftworld. New instance vars lazy-init on load like the existing eldar_intel, so no save-format change. End-of-turn logic; applies to existing saves. --- scripts/macros/macros.gml | 11 +- .../scr_controller_helpers.gml | 106 +++++++++++++++++- 2 files changed, 112 insertions(+), 5 deletions(-) diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 0795ae0bed..0046bb433d 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -61,14 +61,19 @@ // always been in the game; what was missing is any way for Eldar to appear (nothing // ever raised p_eldar on normal worlds) and any realistic way to find the craftworld // (a 5% roll when parking a fleet within 300px of an invisible star). Now an Eldar -// warhost strikes an inhabited world every ELDAR_INCURSION_INTERVAL turns; each ground +// warhost strikes an inhabited world on a random cadence between ELDAR_INTERVAL_MIN +// and ELDAR_INTERVAL_MAX turns; each ground // victory against them yields one piece of intelligence, and at ELDAR_INTEL_REQUIRED // pieces the craftworld is revealed for invasion. Warhost strength starts at // FORCE_BASE and ramps by one per clue collected up to FORCE_MAX, keeping max-tier // Eldar for the craftworld itself (its garrison is 6). ELDAR_FLEET_ENABLED gates the // craftworld's orbiting fleet, disabled for now so the reveal never forces Eldar -// naval combat; flip to 1 to restore it. -#macro ELDAR_INCURSION_INTERVAL 35 +// naval combat; flip to 1 to restore it. Gathered intelligence goes stale after +// ELDAR_CLUE_EXPIRY turns: the clues are lost and the craftworld slips away to a new +// hidden location, so it must be located, reached and assaulted within that window. +#macro ELDAR_INTERVAL_MIN 30 +#macro ELDAR_INTERVAL_MAX 60 +#macro ELDAR_CLUE_EXPIRY 400 #macro ELDAR_INCURSION_FORCE_BASE 3 #macro ELDAR_INCURSION_FORCE_MAX 5 #macro ELDAR_INTEL_REQUIRED 3 diff --git a/scripts/scr_controller_helpers/scr_controller_helpers.gml b/scripts/scr_controller_helpers/scr_controller_helpers.gml index a5d8e468e2..d1969a6efe 100644 --- a/scripts/scr_controller_helpers/scr_controller_helpers.gml +++ b/scripts/scr_controller_helpers/scr_controller_helpers.gml @@ -524,6 +524,9 @@ function eldar_intel_grant() { obj_controller.eldar_intel = 0; } obj_controller.eldar_intel += 1; + // Stamp the turn so the clue-expiry timer (see eldar_incursion_tick / + // ELDAR_CLUE_EXPIRY) measures from the most recent piece of intelligence. + obj_controller.eldar_intel_turn = obj_controller.turn; var _n = obj_controller.eldar_intel; var _clue_texts = [ "Among the alien dead your Apothecaries recover spirit stones that pulse in unison, all straining toward some distant point in the void. The Librarium begins triangulating.", @@ -540,8 +543,87 @@ function eldar_intel_grant() { } } +/// @desc Move the hidden craftworld to a fresh location and reset the hunt: clears +/// gathered intelligence, re-hides the craftworld (known -> 0) and its escort fleet, +/// and relocates both to a new valid position under the same placement constraints as +/// initial worldgen. Called when gathered clues expire (see ELDAR_CLUE_EXPIRY). If no +/// valid site is found in the search budget the craftworld stays put but the hunt +/// still resets. +function eldar_craftworld_relocate() { + if (obj_controller.faction_defeated[eFACTION.ELDAR] != 0) { + return; + } + var _craft = noone; + with (obj_star) { + if (craftworld) { + _craft = id; + break; + } + } + if (_craft == noone) { + return; + } + // Move the craftworld off-map during the search so instance_nearest doesn't + // measure the placement distance against itself. + var _old_x = _craft.x; + var _old_y = _craft.y; + _craft.x = -99999; + _craft.y = -99999; + var _nx = _old_x; + var _ny = _old_y; + var _go = 0; + // Same constraints as the worldgen placement in obj_controller Alarm_1: away from + // the sector centre, at least 150px from the nearest star, inside the bounds. + for (var _i = 0; _i < 200; _i++) { + if (_go == 0) { + _nx = floor(random(1152 + 600)) + 104; + _ny = floor(random(748 + 440)) + 104; + if (point_distance(room_width / 2, room_height / 2, _nx, _ny) >= 50) { + _go = 1; + } + var _me = instance_nearest(_nx, _ny, obj_star); + if ((_go == 1) && (point_distance(_me.x, _me.y, _nx, _ny) >= 150)) { + _go = 2; + } + if (_go == 1) { + _go = 0; + } + if ((_nx >= 1050 + 640) || (_ny <= 300 + 480)) { + _go = 0; + } + } + } + if (_go != 2) { + // No valid site found: leave it where it was. + _nx = _old_x; + _ny = _old_y; + } + _craft.x = _nx; + _craft.y = _ny; + _craft.old_x = _nx; + _craft.old_y = _ny; + _craft.vision = 0; + // Move and re-hide the escort fleet(s) orbiting the craftworld. + with (obj_en_fleet) { + if ((owner == eFACTION.ELDAR) && (orbiting == _craft)) { + x = _nx; + y = _ny; + image_alpha = 0; + } + } + // Reset the hunt: re-lock targeting (known -> 0), clear clues, restamp the timer. + // No map ping is fired, so the new position stays hidden. + obj_controller.known[eFACTION.ELDAR] = 0; + obj_controller.eldar_intel = 0; + obj_controller.eldar_intel_turn = obj_controller.turn; + obj_controller.eldar_reveal_alert_pending = false; + scr_event_log("green", "The Eldar Craftworld has slipped away. The trail has gone cold and the gathered intelligence is lost."); + scr_popup("Eldar Intelligence", "The gathered intelligence has gone stale. The Craftworld has moved beyond the reach of the runes, and the hunt must begin anew.", ""); +} + /// @desc End-of-turn Eldar processing: fires the deferred craftworld reveal alert, -/// then every ELDAR_INCURSION_INTERVAL turns processes warhosts on the ground +/// expires stale clues (relocating the craftworld), then on a random +/// ELDAR_INTERVAL_MIN..ELDAR_INTERVAL_MAX cadence processes warhosts on the ground /// (tainted worlds: scour the population, PDF and Guard while purging the taint; /// clean worlds: withdraw) and lands a new warhost on an inhabited imperial world, preferring worlds with /// heresy, chaos or traitor presence (ELDAR_TAINT_SPAWN_WEIGHT). Warhost strength @@ -570,9 +652,29 @@ function eldar_incursion_tick() { if (obj_controller.faction_defeated[eFACTION.ELDAR] != 0) { return; } - if ((obj_controller.turn < ELDAR_INCURSION_INTERVAL) || ((obj_controller.turn % ELDAR_INCURSION_INTERVAL) != 0)) { + // Clue expiry: intelligence gathered but not acted upon goes cold after + // ELDAR_CLUE_EXPIRY turns. The clues are lost and the craftworld relocates, so a + // located craftworld must be reached and assaulted within that window (well above + // a sector crossing of ~40-50 turns). Allied Eldar (known >= 2) are exempt. Runs + // every turn, before the incursion cadence gate below. + if (variable_instance_exists(obj_controller, "eldar_intel") && (obj_controller.eldar_intel > 0) && (obj_controller.known[eFACTION.ELDAR] < 2)) { + if (!variable_instance_exists(obj_controller, "eldar_intel_turn")) { + obj_controller.eldar_intel_turn = obj_controller.turn; + } + if ((obj_controller.turn - obj_controller.eldar_intel_turn) >= ELDAR_CLUE_EXPIRY) { + eldar_craftworld_relocate(); + } + } + // Variable incursion cadence: schedule the next strike a random + // ELDAR_INTERVAL_MIN..ELDAR_INTERVAL_MAX turns out instead of a fixed modulo, so + // arrivals are not perfectly predictable. Lazy-init on first run. + if (!variable_instance_exists(obj_controller, "eldar_next_incursion")) { + obj_controller.eldar_next_incursion = obj_controller.turn + irandom_range(ELDAR_INTERVAL_MIN, ELDAR_INTERVAL_MAX); + } + if (obj_controller.turn < obj_controller.eldar_next_incursion) { return; } + obj_controller.eldar_next_incursion = obj_controller.turn + irandom_range(ELDAR_INTERVAL_MIN, ELDAR_INTERVAL_MAX); // Process warhosts already on the ground before landing a new one. On a world // touched by the Great Enemy (heresy, chaos or traitor presence) the warhost // stays: it battles the planetary defense force (whose loyalty it does not From f40a678688e20178c0155d629527fd5015987caf Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 09:07:24 +0300 Subject: [PATCH 115/140] Fix vehicle forge cost drifting to zero (vehicle_hanger not reset per turn) The per-turn forge recompute resets player_forge_data.player_forges to 0 before scr_enemy_ai_e re-scans monasteries and secret bases and re-pushes their hangars, but player_forge_data.vehicle_hanger was never reset. It therefore grew by one entry per forge hangar every turn. The Vehicle STC & Hangars discount is (stc_vehicles + array_length(vehicle_hanger) - 1) * 3, so vehicle forge cost fell ~3% per turn until it bottomed at the x0.10 clamp (Land Raiders at 10% of base). Reset vehicle_hanger = [] alongside player_forges = 0 so the per-turn scan rebuilds the true list instead of appending. Self-heals on existing saves at the next end-turn tick. Bug is upstream-verbatim; relayed to the Adeptus Dominus maintainers. --- scripts/scr_controller_helpers/scr_controller_helpers.gml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/scr_controller_helpers/scr_controller_helpers.gml b/scripts/scr_controller_helpers/scr_controller_helpers.gml index d1969a6efe..19f6eda31a 100644 --- a/scripts/scr_controller_helpers/scr_controller_helpers.gml +++ b/scripts/scr_controller_helpers/scr_controller_helpers.gml @@ -477,6 +477,13 @@ function scr_end_turn() { } player_forge_data.player_forges = 0; + // Reset the hangar list too: the per-turn forge scan in + // scr_enemy_ai_e re-pushes every forge hangar (player_forges is + // recomputed the same way and reset just above). Without this reset + // the array grew by one entry per hangar every turn, inflating the + // Vehicle STC & Hangars discount by 3% per turn (hanger_bonus reads + // its length) until vehicle costs bottomed out at the x0.10 clamp. + player_forge_data.vehicle_hanger = []; requisition += income; scr_income(); gene_tithe -= 1; From d2884a6cc1dbcbb7a21d5b3f4e29b7b13b11cd3d Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 09:36:21 +0300 Subject: [PATCH 116/140] Fix planet action buttons: raidable invaders, bombardable dead worlds 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. --- objects/obj_star_select/Draw_64.gml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/objects/obj_star_select/Draw_64.gml b/objects/obj_star_select/Draw_64.gml index 2859e821eb..f7f6bb1c08 100644 --- a/objects/obj_star_select/Draw_64.gml +++ b/objects/obj_star_select/Draw_64.gml @@ -176,9 +176,25 @@ try { button3 = "Bombard"; } else { button1 = "Attack"; - button2 = "Raid"; - if (p_data.population) { + // Raid while an enemy force is present, so invaders on an + // imperial or unowned world can be struck proactively. Purge + // used to overwrite Raid the moment the world had any + // population, which made a landed-but-not-yet-winning enemy + // unraidable. Purge returns once the world is clear of enemies. + if (p_data.xenos_and_heretics() > 0) { + button2 = "Raid"; + // Dead worlds have no friendly population to shield, so + // orbital bombardment of the enemy force is offered here. + // Dead worlds never register as enemy-owned, so this else + // branch is the only one they reach and it never set + // Bombard, which is why it was missing on dead enemy worlds. + if (p_data.planet_type == "Dead") { + button3 = "Bombard"; + } + } else if (p_data.population) { button2 = "Purge"; + } else { + button2 = "Raid"; } } From ca9278b520e3017b96203c4469a8e5916b30e64d Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 09:49:24 +0300 Subject: [PATCH 117/140] Per-ship gating for Raid (2/ship) and Bombard (1/ship), Fire purges now 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. --- objects/obj_star_select/Draw_64.gml | 46 +++++++++++-------- scripts/macros/macros.gml | 6 +++ scripts/scr_bomb_world/scr_bomb_world.gml | 4 ++ .../scr_drop_select_function.gml | 12 +++-- .../scr_player_ship_functions.gml | 45 ++++++++++++++++++ scripts/scr_purge_world/scr_purge_world.gml | 15 ++++++ 6 files changed, 105 insertions(+), 23 deletions(-) diff --git a/objects/obj_star_select/Draw_64.gml b/objects/obj_star_select/Draw_64.gml index f7f6bb1c08..4537c76763 100644 --- a/objects/obj_star_select/Draw_64.gml +++ b/objects/obj_star_select/Draw_64.gml @@ -353,13 +353,21 @@ try { with (obj_star_select) { instance_destroy(); } - } else if (current_button == "Raid" && instance_nearest(x, y, obj_p_fleet).acted <= 1) { - // feather ignore once GM2064 - instance_create_layer(x, y, layer_get_all()[0], obj_drop_select, {p_target: target, planet_number: obj_controller.selecting_planet, sh_target: instance_nearest(x, y, obj_p_fleet), purge: 0}); } else if (current_button == "Raid") { - // Blocked actions say why instead of silently doing nothing (players - // assumed the game broke when clicks had no effect). - scr_popup("Raid", "This fleet has already expended its actions this turn and cannot launch a raid. Raiding requires a fleet that has spent at most one action.", ""); + // Per-ship gate, matching Attack: a raid deploys troops from ships just + // like an assault, so it is allowed while any carrying ship at this star + // still has support uses left this turn (SHIP_ASSAULTS_PER_TURN, i.e. 2), + // or while local forces do. Replaces the old fleet-wide gate + // (fleet.acted <= 1) that blocked the whole fleet after two raids + // regardless of how many ships were involved. + if (can_ground_deploy(target, obj_controller.selecting_planet)) { + // feather ignore once GM2064 + instance_create_layer(x, y, layer_get_all()[0], obj_drop_select, {p_target: target, planet_number: obj_controller.selecting_planet, sh_target: instance_nearest(x, y, obj_p_fleet), purge: 0}); + } else { + // Blocked actions say why instead of silently doing nothing (players + // assumed the game broke when clicks had no effect). + scr_popup("Raid", "Every ship and local force at this world has already supported the maximum number of raids and assaults this turn.", ""); + } } else if (current_button == "Attack") { var _allow_attack = true; var _targ = !target.present_fleet[1] ? noone : instance_nearest(x, y, obj_p_fleet); @@ -404,18 +412,20 @@ try { instance_create_layer(x, y, layer_get_all()[0], obj_drop_select, {p_target: target, planet_number: obj_controller.selecting_planet, sh_target: _targ, purge: 1}); } } else if (current_button == "Bombard") { - instance_create(x, y, obj_bomb_select); - if (instance_exists(obj_bomb_select)) { - obj_bomb_select.p_target = target; - obj_bomb_select.sh_target = instance_nearest(x, y, obj_p_fleet); - obj_bomb_select.p_data = p_data; - if (instance_nearest(x, y, obj_p_fleet).acted > 0) { - with (obj_bomb_select) { - instance_destroy(); - } - // Vanilla created the bombard screen and instantly destroyed it, - // leaving the player with a dead click and no explanation. - scr_popup("Bombardment", "This fleet has already acted this turn. Orbital bombardment must be the fleet's first action of the turn.", ""); + // Per-ship gate: orbital bombardment is one per ship per turn and + // consumes that ship's whole support allowance, so it needs a ship at + // this star that has done nothing else this turn. Replaces the old + // fleet-wide gate (fleet.acted > 0) that let the whole fleet bombard + // only once regardless of ship count. + if (get_fresh_bombard_ship(target.name) == -1) { + // Blocked actions say why instead of a dead click. + scr_popup("Bombardment", "No ship in orbit is free to bombard this turn. Each ship can bombard once per turn, and a ship that has already raided or supported an assault cannot.", ""); + } else { + instance_create(x, y, obj_bomb_select); + if (instance_exists(obj_bomb_select)) { + obj_bomb_select.p_target = target; + obj_bomb_select.sh_target = instance_nearest(x, y, obj_p_fleet); + obj_bomb_select.p_data = p_data; } } } else if (current_button == "Deploy Guard") { diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 0046bb433d..54f2e61435 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -56,6 +56,12 @@ // can clear a system in one turn, but every launch spends real capacity. Raids, purges, // and bombardment keep their old fleet-level rules. #macro SHIP_ASSAULTS_PER_TURN 2 +// Disposition drop a full indiscriminate fire purge (100% of the population burned) +// inflicts on a world's regard for the Chapter. Scaled down by the actual share killed +// per purge, so a light burn costs a little and a total one costs this much. Selective +// purges (targeted heretics) and governor assassinations carry no penalty. Tune down +// toward 0 to soften, up for harsher consequences. +#macro PURGE_FIRE_DISPO_PENALTY 40 // Eldar craftworld hunt. The hidden craftworld and the full Eldar battle roster have // always been in the game; what was missing is any way for Eldar to appear (nothing diff --git a/scripts/scr_bomb_world/scr_bomb_world.gml b/scripts/scr_bomb_world/scr_bomb_world.gml index 5287b7e24b..fe0130db1c 100644 --- a/scripts/scr_bomb_world/scr_bomb_world.gml +++ b/scripts/scr_bomb_world/scr_bomb_world.gml @@ -412,7 +412,11 @@ function scr_bomb_world(bombard_target_faction, bombard_ment_power, target_stren pip.text = txt1 + txt2 + txt3; } + // Fleet movement lock preserved (bombarding ends the fleet's turn for movement), + // and the bombarding ship spends its whole support allowance so it is one + // bombardment per ship per turn (see get_fresh_bombard_ship / the Bombard gate). obj_bomb_select.sh_target.acted = 5; + ship_bombard_spend(get_fresh_bombard_ship(system.name)); with (obj_bomb_select) { instance_destroy(); } diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index a66533c69b..69961e9a6a 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -293,11 +293,13 @@ function drop_select_unit_selection() { instance_activate_object(obj_drop_select); // Ship assault economy: each distinct ship contributing units to this - // ground assault spends one support use this turn (SHIP_ASSAULTS_PER_TURN - // max). fleet.acted above still ticks so raid and bombardment gating are - // unchanged. Local planetside forces (ship id -1) cost nothing. Raids do - // not spend uses. - if (attack == 1) { + // ground deployment spends one support use this turn (SHIP_ASSAULTS_PER_TURN + // max). This now covers raids as well as attacks (both are RAIDATTACK drops + // that land troops from ships), so a raid is gated per ship like an assault + // rather than by the fleet-wide acted counter. fleet.acted above still ticks + // for movement and the unconverted purge gate. Local planetside forces + // (ship id -1) cost nothing here; they spend a local use just below. + if (purge == eDROP_TYPE.RAIDATTACK) { var _spent_ships = []; var _local_participated = false; for (var _su = 0; _su < array_length(roster.selected_units); _su++) { diff --git a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml index f684388381..9f51dcc965 100644 --- a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml +++ b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml @@ -711,3 +711,48 @@ function player_guardsmen_at(system_name) { } return _total; } + +/// @desc Whether a ground deployment (attack or raid) can still be supported at this +/// star this turn: any carrying ship with support uses left, or the planet's local +/// forces with local uses left. Ships and local forces are tracked independently, so +/// spending one ship does not lock the rest of the fleet (the point of the per-ship +/// action economy). +function can_ground_deploy(star_object, planet_number) { + if (!instance_exists(star_object)) { + return false; + } + var _ships = get_player_ships(star_object.name); + for (var i = 0; i < array_length(_ships); i++) { + if ((obj_ini.ship_carrying[_ships[i]] > 0) && (ship_assaults_used(_ships[i]) < SHIP_ASSAULTS_PER_TURN)) { + return true; + } + } + if ((star_object.p_player[planet_number] > 0) && (local_assaults_used(star_object, planet_number) < SHIP_ASSAULTS_PER_TURN)) { + return true; + } + return false; +} + +/// @desc First ship at this star that has spent no support use this turn, or -1. +/// Orbital bombardment is one per ship per turn and consumes the ship's whole support +/// allowance for the turn, so it needs a completely fresh ship. +function get_fresh_bombard_ship(location) { + var _ships = get_player_ships(location); + for (var i = 0; i < array_length(_ships); i++) { + if (ship_assaults_used(_ships[i]) == 0) { + return _ships[i]; + } + } + return -1; +} + +/// @desc Spend a ship's entire support allowance on an orbital bombardment (one per +/// ship per turn, mutually exclusive with that ship's ground support for the turn). +function ship_bombard_spend(ship_index) { + if (ship_index < 0) { + return; + } + repeat (SHIP_ASSAULTS_PER_TURN) { + ship_assault_spend(ship_index); + } +} diff --git a/scripts/scr_purge_world/scr_purge_world.gml b/scripts/scr_purge_world/scr_purge_world.gml index 098684dd2c..efe546a797 100644 --- a/scripts/scr_purge_world/scr_purge_world.gml +++ b/scripts/scr_purge_world/scr_purge_world.gml @@ -256,6 +256,21 @@ function scr_purge_world(action_type, action_score) { } _popup_text += _purge.population_death_string(); + + // Indiscriminate fire purges turn the surviving populace against the + // Chapter, scaled by the share of the population put to the torch. Before + // this, a fire purge of a world with no active Inquisition quest changed + // disposition not at all, so burning millions of your own citizens cost + // nothing. Selective purges (targeted heretics) and assassinations keep no + // penalty, matching the intent that precision killing of known enemies is + // tolerated while razing hab blocks is not. + if (_purge.pop_before > 0) { + var _fire_dispo_drop = round((_purge.kill / _purge.pop_before) * PURGE_FIRE_DISPO_PENALTY); + if (_fire_dispo_drop > 0) { + add_disposition(-_fire_dispo_drop); + _popup_text += " Word of the burnings spreads, and the survivors' regard for your Chapter falls."; + } + } } } From 96dbaf916922b9137a2cdc7720d107fdaa2da4bb Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 12:19:10 +0300 Subject: [PATCH 118/140] Fix player fleet map icon stuck at tiny size after load or ship change; 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. --- objects/obj_bomb_select/Alarm_1.gml | 5 +++++ objects/obj_bomb_select/Create_0.gml | 1 + objects/obj_bomb_select/Draw_0.gml | 15 +++++++++++---- objects/obj_p_fleet/Step_0.gml | 7 +++++++ scripts/scr_bomb_world/scr_bomb_world.gml | 17 +++++++++++++---- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/objects/obj_bomb_select/Alarm_1.gml b/objects/obj_bomb_select/Alarm_1.gml index 9e092cb908..dd5212c675 100644 --- a/objects/obj_bomb_select/Alarm_1.gml +++ b/objects/obj_bomb_select/Alarm_1.gml @@ -4,6 +4,7 @@ ship_all = []; ship_use = []; ship_max = []; ship_ide = []; +ship_spent = []; var _ships = fleet_full_ship_array(sh_target); max_ships = array_length(_ships); @@ -19,6 +20,10 @@ for (var i = 0; i < array_length(_ships); i++) { array_push(ship, obj_ini.ship[_ships[i]]); array_push(ship_use, 0); array_push(ship_all, 0); + // A ship that has spent any support use this turn (bombarded, or supported a + // ground assault or raid) cannot bombard, since bombardment needs a fully + // fresh ship. Such ships are listed but locked in the selection grid. + array_push(ship_spent, ship_assaults_used(_ships[i]) > 0); } } diff --git a/objects/obj_bomb_select/Create_0.gml b/objects/obj_bomb_select/Create_0.gml index 4503b12d6d..866ef9ec90 100644 --- a/objects/obj_bomb_select/Create_0.gml +++ b/objects/obj_bomb_select/Create_0.gml @@ -23,6 +23,7 @@ for (var i = 0; i < 31; i++) { ship_use[i] = 0; ship_max[i] = 0; ship_ide[i] = -1; + ship_spent[i] = 0; } menu = 0; diff --git a/objects/obj_bomb_select/Draw_0.gml b/objects/obj_bomb_select/Draw_0.gml index 70be3341db..162a79daa8 100644 --- a/objects/obj_bomb_select/Draw_0.gml +++ b/objects/obj_bomb_select/Draw_0.gml @@ -153,8 +153,9 @@ if ((max_ships > 0) && instance_exists(obj_star_select)) { var sel_all_button = draw_unit_buttons([bomb_window.x2 - 55, bomb_window.y1 + 150, bomb_window.x2 - 40, bomb_window.y1 + 165], sel_all_label, [1, 1], #34bc75, fa_center, fnt_40k_14b); if (point_and_click(sel_all_button)) { for (var i = 0; i < array_length(ship); i++) { - // Limit to the first 5 ships with buttons - if (ship[ship_index] != "" && ship_all[i] == all_sel) { + // Limit to the first 5 ships with buttons. Spent ships are skipped so + // Select All never toggles a ship that has already used its turn. + if (ship[ship_index] != "" && ship_all[i] == all_sel && !ship_spent[i]) { ship_all[i] = !all_sel; ships_selected += all_sel ? -1 : 1; } @@ -194,8 +195,14 @@ if ((max_ships > 0) && instance_exists(obj_star_select)) { var buttonX = bomb_window.x1 + 24 + col * buttonSpacingX; var buttonY = bomb_window.y1 + 172 + row * buttonSpacingY; - // Draw the unit buttons and handle selection - if (point_and_click(draw_unit_buttons([buttonX, buttonY, buttonX + 105, buttonY + 20], string_truncate(num, 200), [1, 1], ship_all[ship_index] ? #34bc75 : #bf4040, fa_center, fnt_40k_10, ship_all[ship_index] ? 1 : 0.5))) { + // Draw the unit buttons and handle selection. A ship that has already + // spent its support this turn shows locked in red and rejects clicks, + // matching the attack roster. Bombardment needs a fully fresh ship. + var _spent = ship_spent[ship_index]; + var _btn_col = _spent ? c_red : (ship_all[ship_index] ? #34bc75 : #bf4040); + var _btn_alpha = _spent ? 0.5 : (ship_all[ship_index] ? 1 : 0.5); + var _ship_clicked = point_and_click(draw_unit_buttons([buttonX, buttonY, buttonX + 105, buttonY + 20], string_truncate(num, 200), [1, 1], _btn_col, fa_center, fnt_40k_10, _btn_alpha)); + if (_ship_clicked && !_spent) { ship_all[ship_index] = !ship_all[ship_index]; ships_selected += ship_all[ship_index] ? 1 : -1; diff --git a/objects/obj_p_fleet/Step_0.gml b/objects/obj_p_fleet/Step_0.gml index 13cafe81f7..6ecb726a93 100644 --- a/objects/obj_p_fleet/Step_0.gml +++ b/objects/obj_p_fleet/Step_0.gml @@ -11,6 +11,13 @@ if ((action != "") && (orbiting != noone)) { action_spd = calculate_action_speed(); if (ii_check == 0) { + // Refresh the map icon frame on a fixed 10-step cadence, matching obj_en_fleet. + // Without this reset the countdown hit 0 only once (roughly 10 steps after the + // fleet was created), so set_player_fleet_image ran a single time. A fleet loaded + // from a save has its ship counts populated by the load pass, and any fleet that + // gains or loses ships in play, so that one early frame calculation went stale and + // the icon stuck at the tiny frame regardless of real size. + ii_check = 10; set_player_fleet_image(); } diff --git a/scripts/scr_bomb_world/scr_bomb_world.gml b/scripts/scr_bomb_world/scr_bomb_world.gml index fe0130db1c..3f6ce559dd 100644 --- a/scripts/scr_bomb_world/scr_bomb_world.gml +++ b/scripts/scr_bomb_world/scr_bomb_world.gml @@ -412,11 +412,20 @@ function scr_bomb_world(bombard_target_faction, bombard_ment_power, target_stren pip.text = txt1 + txt2 + txt3; } - // Fleet movement lock preserved (bombarding ends the fleet's turn for movement), - // and the bombarding ship spends its whole support allowance so it is one - // bombardment per ship per turn (see get_fresh_bombard_ship / the Bombard gate). + // Fleet movement lock preserved (bombarding ends the fleet's turn for movement). + // Every ship the player selected spends its whole support allowance, so each ship + // bombards at most once per turn. Previously only the first fresh ship was spent + // regardless of 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, letting one fleet fire several times over. obj_bomb_select.sh_target.acted = 5; - ship_bombard_spend(get_fresh_bombard_ship(system.name)); + with (obj_bomb_select) { + for (var _bspend = 0; _bspend < array_length(ship_ide); _bspend++) { + if ((ship_all[_bspend] == 1) && (ship_ide[_bspend] >= 0)) { + ship_bombard_spend(ship_ide[_bspend]); + } + } + } with (obj_bomb_select) { instance_destroy(); } From 130329dd6cb8bc81a2e1bc4dfbf6d204d08f33ee Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 12:42:05 +0300 Subject: [PATCH 119/140] Fix player fleet rendering as a tiny blip after load 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. --- objects/obj_p_fleet/Step_0.gml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/objects/obj_p_fleet/Step_0.gml b/objects/obj_p_fleet/Step_0.gml index 6ecb726a93..50d27d4002 100644 --- a/objects/obj_p_fleet/Step_0.gml +++ b/objects/obj_p_fleet/Step_0.gml @@ -10,15 +10,15 @@ if ((action != "") && (orbiting != noone)) { action_spd = calculate_action_speed(); -if (ii_check == 0) { - // Refresh the map icon frame on a fixed 10-step cadence, matching obj_en_fleet. - // Without this reset the countdown hit 0 only once (roughly 10 steps after the - // fleet was created), so set_player_fleet_image ran a single time. A fleet loaded - // from a save has its ship counts populated by the load pass, and any fleet that - // gains or loses ships in play, so that one early frame calculation went stale and - // the icon stuck at the tiny frame regardless of real size. - ii_check = 10; +if (ii_check <= 0) { + // Refresh the fleet's map sprite size, then rearm the timer. Previously this fired + // exactly once (ii_check hit 0 then went negative and never reset), so a fleet + // whose serialized ii_check was already negative never recomputed its size after a + // load and rendered as a single tiny blip regardless of its real strength. The + // enemy fleet (obj_en_fleet) already rearms this timer; the player fleet did not. + // Using <= 0 also lets a loaded fleet with a negative timer heal on the next step. set_player_fleet_image(); + ii_check = 10; } if ((global.load >= 0) && (sprite_index != spr_fleet_tiny)) { From 3dfce99e72faa6af07779d53bdac2141dfd51b7a Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 13:16:20 +0300 Subject: [PATCH 120/140] Bombardment effect preview: show population and enemy loss estimates 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. --- objects/obj_bomb_select/Draw_0.gml | 29 ++++++++ scripts/scr_bomb_world/scr_bomb_world.gml | 87 +++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/objects/obj_bomb_select/Draw_0.gml b/objects/obj_bomb_select/Draw_0.gml index 162a79daa8..b6cd77b0b4 100644 --- a/objects/obj_bomb_select/Draw_0.gml +++ b/objects/obj_bomb_select/Draw_0.gml @@ -214,6 +214,35 @@ if ((max_ships > 0) && instance_exists(obj_star_select)) { } } + // Bombardment effect preview. Estimate what a bombard with the currently selected + // ships would do to this world and show it at a glance, so a small-population planet + // is not wiped out to shave a point off an entrenched enemy without the player + // seeing it coming. Population loss is fixed per world (the kill does not scale with + // ship count); enemy loss scales with the selected bombard score. + var _est_bomb = 0; + for (var i = 0; i < array_length(ship_ide); i++) { + if (ship_all[i] == 1) { + var _c = player_ships_class(ship_ide[i]); + if (_c == "capital") { + _est_bomb += 3; + } else if (_c == "frigate") { + _est_bomb += 1; + } + } + } + var _est = bombard_effect_estimate(p_data, target, _est_bomb, str); + var _rows_used = max(1, ceil(array_length(ship_ide) / 4)); + var _est_y = min(bomb_window.y1 + 172 + _rows_used * buttonSpacingY + 16, bomb_window.y2 - 74); + draw_set_halign(fa_left); + draw_set_font(fnt_info); + draw_set_color(#34bc75); + draw_text_bold(bomb_window.x1 + 20, _est_y, "If bombarded now:"); + draw_set_color(bombard_effect_bracket_color(_est.population)); + draw_text_bold(bomb_window.x1 + 20, _est_y + 18, $"Population loss: {_est.population}"); + draw_set_color(bombard_effect_bracket_color(_est.enemy)); + draw_text_bold(bomb_window.x1 + 20, _est_y + 36, $"Enemy losses: {_est.enemy}"); + draw_set_color(#34bc75); + // Confirm and Cancel buttons var button_alpha = 1; if (!ships_selected) { diff --git a/scripts/scr_bomb_world/scr_bomb_world.gml b/scripts/scr_bomb_world/scr_bomb_world.gml index 3f6ce559dd..96cbea8a67 100644 --- a/scripts/scr_bomb_world/scr_bomb_world.gml +++ b/scripts/scr_bomb_world/scr_bomb_world.gml @@ -431,3 +431,90 @@ function scr_bomb_world(bombard_target_faction, bombard_ment_power, target_stren } // show_message("Pop: "+string(pop_before)+" -> "+string(pop_after)+"#killed: "+string(kill)+"#Heresy: "+string(heres_before)+" -> "+string(heres_after)); } + +/// @desc Rough, bracketed preview of a bombardment's effect for the selection dialog, +/// so the player can see roughly what a bombard will do before committing. Mirrors the +/// kill and strength_reduction math in scr_bomb_world above. Returns a struct with two +/// labels, population and enemy, each one of None / Negligible / Low / Medium / High / +/// Massive. It is an estimate: it ignores the sub-1 random reduction roll and the Ork +/// Stronghold / Daemon-world specials. +function bombard_effect_estimate(_planet, _target_faction, _bomb_power, _target_strength) { + // Population: scr_bomb_world kills a fixed slice (0.15) of the planet's own scale, + // subtracted straight from population, so it does not scale with ship count. On a + // small world that fixed slice dwarfs the whole population and wipes it out, which + // is the surprise this preview exists to warn about. + var _pop_pct = 0; + var _pop_before = _planet.population; + if ((_pop_before > 0) && (_planet.planet_type != "Space Hulk")) { + var _kill = _planet.population_small_conversion(0.15); + _pop_pct = (min(_pop_before, _kill) / _pop_before) * 100; + } + + // Enemy: same reduction math as scr_bomb_world. The reduced score, scaled by the + // target's bombard protection, is how many strength stages come off. + var _en_pct = 0; + if (_target_strength > 0) { + var _reduced = _bomb_power / 3; + var _protection = clamp(bombard_protection_estimate(_target_faction), 0, 4); + var _protect_scores = [4, 0.9, 0.75, 0.5, 0.34]; + var _stages = floor(_reduced * _protect_scores[_protection]); + _en_pct = (min(_stages, _target_strength) / _target_strength) * 100; + } + + return { + population: bombard_effect_bracket(_pop_pct), + enemy: bombard_effect_bracket(_en_pct), + }; +} + +/// @desc Base bombard protection tier per target faction, matching the switch in +/// scr_bomb_world (Ork Stronghold and Daemon-world bonuses are left out of the estimate). +function bombard_protection_estimate(_faction) { + switch (_faction) { + case 2: return 2; + case 2.5: return 1; + case 3: return 3; + case 5: return 1; + case 6: return 4; + case 7: return 2; + case 8: return 3; + case 9: return 0; + case 10: return 2; + case 11: return 2; + case 13: return 4; + } + return 1; +} + +/// @desc Map a 0-100 percentage to a coarse severity label for the bombard preview. +function bombard_effect_bracket(_pct) { + if (_pct <= 0) { + return "None"; + } + if (_pct < 5) { + return "Negligible"; + } + if (_pct < 20) { + return "Low"; + } + if (_pct < 45) { + return "Medium"; + } + if (_pct < 80) { + return "High"; + } + return "Massive"; +} + +/// @desc Colour for a bombard severity label so the worst outcomes read at a glance. +function bombard_effect_bracket_color(_label) { + switch (_label) { + case "None": return c_gray; + case "Negligible": return #34bc75; + case "Low": return #34bc75; + case "Medium": return c_yellow; + case "High": return c_orange; + case "Massive": return c_red; + } + return c_white; +} From ecc7a36a6d458e8b9d7cc62cd98f14d6b1080e36 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 14:05:54 +0300 Subject: [PATCH 121/140] Bombardment depopulates worlds to zero over several strikes without killing 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. --- scripts/scr_bomb_world/scr_bomb_world.gml | 81 ++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/scripts/scr_bomb_world/scr_bomb_world.gml b/scripts/scr_bomb_world/scr_bomb_world.gml index 96cbea8a67..f002e0e779 100644 --- a/scripts/scr_bomb_world/scr_bomb_world.gml +++ b/scripts/scr_bomb_world/scr_bomb_world.gml @@ -1,3 +1,80 @@ +// --------------------------------------------------------------------------------- +// Bombardment tuning. These govern how much of a world a single bombardment kills. +// Casualties are a share of the world's population CAPACITY (its max population), not of +// whoever is left, so a world is depopulated in a handful of bombards down to zero +// rather than a fixed absolute figure that wipes small worlds in one shot or a fraction +// of the survivors that only ever asymptotes. Bombardment never turns a world Dead; the +// world keeps its type at zero population and can regrow once its enemies are cleared. +// All values are macros so balance can be tuned without touching logic. +// --------------------------------------------------------------------------------- + +// BASE is the share of world capacity a bombardment kills before the factor multipliers. +// MAX caps a single bombard, so the fastest a world can be emptied is 1 / MAX bombards. +#macro BOMBARD_BASE_FRACTION 0.20 +#macro BOMBARD_MAX_FRACTION 0.34 + +/// @desc World-type multiplier on bombardment population casualties. Dense hive cities +/// burn hardest; spread-out agri and feudal worlds lose fewer people per bombardment. +function bombard_planet_type_pop_mult(_type) { + switch (_type) { + case "Hive": return 1.5; + case "Desert": return 0.8; + case "Agri": return 0.6; + case "Feudal": return 0.5; + } + return 1.0; // Temperate / civilised and everything else +} + +/// @desc Enemy-presence multiplier on bombardment population casualties. A larger, more +/// deeply embedded enemy (strength tier 0 none .. 6 Overwhelming) means the bombardment +/// has to hit more of the world to root it out, so more civilians die alongside it. +function bombard_presence_pop_mult(_tier) { + var _mults = [0.6, 0.7, 0.85, 1.0, 1.2, 1.4, 1.6]; + return _mults[clamp(_tier, 0, 6)]; +} + +/// @desc Ratio multiplier: how far the enemy has overrun the world. A large enemy on a +/// lightly populated world drives collateral up; a small enemy on a teeming world keeps +/// it down. Compares the enemy strength tier to a coarse population bucket. +function bombard_ratio_pop_mult(_planet, _tier) { + var _pop = _planet.population_as_small(); + var _pop_tier = 0; + if (_pop >= 1000000000) { + _pop_tier = 5; + } else if (_pop >= 100000000) { + _pop_tier = 4; + } else if (_pop >= 10000000) { + _pop_tier = 3; + } else if (_pop >= 1000000) { + _pop_tier = 2; + } else if (_pop >= 100000) { + _pop_tier = 1; + } + var _diff = clamp(_tier - _pop_tier, -3, 3); + return clamp(1 + _diff * 0.15, 0.6, 1.5); +} + +/// @desc Share of a world's population CAPACITY killed by one bombardment, from world +/// type, enemy presence, and enemy-to-population ratio, capped at BOMBARD_MAX_FRACTION. +function bombard_pop_kill_fraction(_planet, _enemy_tier) { + var _frac = BOMBARD_BASE_FRACTION; + _frac *= bombard_planet_type_pop_mult(_planet.planet_type); + _frac *= bombard_presence_pop_mult(_enemy_tier); + _frac *= bombard_ratio_pop_mult(_planet, _enemy_tier); + return clamp(_frac, 0, BOMBARD_MAX_FRACTION); +} + +/// @desc Population killed by one bombardment, in the planet's own population scale. A +/// bombard removes a share of the world's capacity (max population), so repeated bombards +/// grind a world down to zero in a handful of strikes regardless of its size, but never +/// exceed the population actually present. Used by both scr_bomb_world and the dialog +/// preview so the estimate and the real outcome always agree. +function bombard_population_kill(_planet, _enemy_tier) { + var _capacity = max(_planet.max_population, _planet.population); + var _kill = _capacity * bombard_pop_kill_fraction(_planet, _enemy_tier); + return min(_planet.population, _kill); +} + function scr_bomb_world(bombard_target_faction, bombard_ment_power, target_strength) { var pop_after = 0, reduced_bombard_score = 0, strength_reduction = 0, txt2 = "", txt3 = "", txt4 = "", max_kill, overkill, roll, kill; @@ -15,7 +92,7 @@ function scr_bomb_world(bombard_target_faction, bombard_ment_power, target_stren } txt1 += $" annihilation upon {name()}. Even from space the explosions can be seen, {choose("tearing ground", "hammering", "battering", "thundering")} across the planet's surface."; - kill = population_small_conversion(0.15); + kill = bombard_population_kill(self, target_strength); var pop_before = population; @@ -446,7 +523,7 @@ function bombard_effect_estimate(_planet, _target_faction, _bomb_power, _target_ var _pop_pct = 0; var _pop_before = _planet.population; if ((_pop_before > 0) && (_planet.planet_type != "Space Hulk")) { - var _kill = _planet.population_small_conversion(0.15); + var _kill = bombard_population_kill(_planet, _target_strength); _pop_pct = (min(_pop_before, _kill) / _pop_before) * 100; } From 697e9e9ee55e4a6a06aed66743b5192479cf6157 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 14:22:59 +0300 Subject: [PATCH 122/140] Bombardment population damage scales with fleet firepower, world type, 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. --- scripts/scr_bomb_world/scr_bomb_world.gml | 62 +++++++++++++++-------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/scripts/scr_bomb_world/scr_bomb_world.gml b/scripts/scr_bomb_world/scr_bomb_world.gml index f002e0e779..9d8a4435df 100644 --- a/scripts/scr_bomb_world/scr_bomb_world.gml +++ b/scripts/scr_bomb_world/scr_bomb_world.gml @@ -1,17 +1,25 @@ // --------------------------------------------------------------------------------- // Bombardment tuning. These govern how much of a world a single bombardment kills. -// Casualties are a share of the world's population CAPACITY (its max population), not of -// whoever is left, so a world is depopulated in a handful of bombards down to zero -// rather than a fixed absolute figure that wipes small worlds in one shot or a fraction -// of the survivors that only ever asymptotes. Bombardment never turns a world Dead; the -// world keeps its type at zero population and can regrow once its enemies are cleared. -// All values are macros so balance can be tuned without touching logic. +// Casualties are a share of the world's population CAPACITY (its max population) so a +// world is depopulated down to zero over repeated strikes rather than a fixed absolute +// figure that wipes small worlds in one shot. The share scales with how much fleet +// firepower is committed and is shaped by world type, enemy size, how far the enemy has +// overrun the world, and the world's fortifications. Bombardment never turns a world +// Dead; the world keeps its type at zero population and can regrow once its enemies are +// cleared. All values are macros so balance can be tuned without touching logic. // --------------------------------------------------------------------------------- -// BASE is the share of world capacity a bombardment kills before the factor multipliers. -// MAX caps a single bombard, so the fastest a world can be emptied is 1 / MAX bombards. -#macro BOMBARD_BASE_FRACTION 0.20 -#macro BOMBARD_MAX_FRACTION 0.34 +// Share of world capacity killed per point of bombard score, before the factor +// multipliers. Bombard score is Battle Barge 3, Strike Cruiser 1, escorts 0, so more +// ships (and bigger ships) do more population damage. Zero ships do nothing. +#macro BOMBARD_POP_PER_POWER 0.06 +// Hard ceiling on a single bombard's share of capacity. At 1.0 an overwhelming fleet can +// depopulate a world in one strike; a lone ship takes many. +#macro BOMBARD_MAX_FRACTION 1.0 +// Each fortification level (0 none .. 5 fully fortified) cuts population casualties by +// this much, down to the floor, since bunkers and shelters protect civilians. +#macro BOMBARD_DEFENSE_REDUCTION 0.15 +#macro BOMBARD_DEFENSE_FLOOR 0.20 /// @desc World-type multiplier on bombardment population casualties. Dense hive cities /// burn hardest; spread-out agri and feudal worlds lose fewer people per bombardment. @@ -54,24 +62,34 @@ function bombard_ratio_pop_mult(_planet, _tier) { return clamp(1 + _diff * 0.15, 0.6, 1.5); } -/// @desc Share of a world's population CAPACITY killed by one bombardment, from world -/// type, enemy presence, and enemy-to-population ratio, capped at BOMBARD_MAX_FRACTION. -function bombard_pop_kill_fraction(_planet, _enemy_tier) { - var _frac = BOMBARD_BASE_FRACTION; +/// @desc Fortification multiplier on bombardment population casualties. Planet defenses +/// (fortification_level 0 none .. 5 fully fortified) shelter civilians in bunkers, so a +/// well-defended world loses far fewer people to orbital fire. +function bombard_defense_pop_mult(_planet) { + var _level = clamp(_planet.fortification_level, 0, 5); + return clamp(1 - _level * BOMBARD_DEFENSE_REDUCTION, BOMBARD_DEFENSE_FLOOR, 1); +} + +/// @desc Share of a world's population CAPACITY killed by one bombardment. Driven by the +/// committed bombard score (ship count and type), then shaped by world type, enemy size, +/// enemy-to-population ratio, and fortifications, capped at BOMBARD_MAX_FRACTION. +function bombard_pop_kill_fraction(_planet, _enemy_tier, _bomb_power) { + var _frac = _bomb_power * BOMBARD_POP_PER_POWER; _frac *= bombard_planet_type_pop_mult(_planet.planet_type); _frac *= bombard_presence_pop_mult(_enemy_tier); _frac *= bombard_ratio_pop_mult(_planet, _enemy_tier); + _frac *= bombard_defense_pop_mult(_planet); return clamp(_frac, 0, BOMBARD_MAX_FRACTION); } /// @desc Population killed by one bombardment, in the planet's own population scale. A -/// bombard removes a share of the world's capacity (max population), so repeated bombards -/// grind a world down to zero in a handful of strikes regardless of its size, but never -/// exceed the population actually present. Used by both scr_bomb_world and the dialog -/// preview so the estimate and the real outcome always agree. -function bombard_population_kill(_planet, _enemy_tier) { +/// bombard removes a share of the world's capacity (max population) that grows with the +/// fleet firepower committed, so a small strike chips away while an overwhelming fleet can +/// depopulate a world in one blow, but never more than the population actually present. +/// Used by both scr_bomb_world and the dialog preview so estimate and outcome agree. +function bombard_population_kill(_planet, _enemy_tier, _bomb_power) { var _capacity = max(_planet.max_population, _planet.population); - var _kill = _capacity * bombard_pop_kill_fraction(_planet, _enemy_tier); + var _kill = _capacity * bombard_pop_kill_fraction(_planet, _enemy_tier, _bomb_power); return min(_planet.population, _kill); } @@ -92,7 +110,7 @@ function scr_bomb_world(bombard_target_faction, bombard_ment_power, target_stren } txt1 += $" annihilation upon {name()}. Even from space the explosions can be seen, {choose("tearing ground", "hammering", "battering", "thundering")} across the planet's surface."; - kill = bombard_population_kill(self, target_strength); + kill = bombard_population_kill(self, target_strength, bombard_ment_power); var pop_before = population; @@ -523,7 +541,7 @@ function bombard_effect_estimate(_planet, _target_faction, _bomb_power, _target_ var _pop_pct = 0; var _pop_before = _planet.population; if ((_pop_before > 0) && (_planet.planet_type != "Space Hulk")) { - var _kill = bombard_population_kill(_planet, _target_strength); + var _kill = bombard_population_kill(_planet, _target_strength, _bomb_power); _pop_pct = (min(_pop_before, _kill) / _pop_before) * 100; } From 17e70591467f273090a5298d41ae5eeca059b7ce Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 17:20:12 +0300 Subject: [PATCH 123/140] Fix input lock: block star-panel clicks under the open bombard dialog 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. --- objects/obj_star_select/Mouse_50.gml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objects/obj_star_select/Mouse_50.gml b/objects/obj_star_select/Mouse_50.gml index ee6a23ade0..46dd3e500d 100644 --- a/objects/obj_star_select/Mouse_50.gml +++ b/objects/obj_star_select/Mouse_50.gml @@ -1,4 +1,4 @@ -if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select)) { +if (!instance_exists(obj_saveload) && !instance_exists(obj_drop_select) && !instance_exists(obj_bomb_select)) { if (obj_controller.diplomacy == 0) { draw_set_font(fnt_fancy); draw_set_halign(fa_center); From 3f97542764cd80743ebb0a881d03929aef11aef4 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 18:28:04 +0300 Subject: [PATCH 124/140] Add live, distance-scaled cover save for Marines and Guard auxilia 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. --- scripts/macros/macros.gml | 29 +++++++++-- scripts/scr_cheatcode/scr_cheatcode.gml | 11 ++++ scripts/scr_clean/scr_clean.gml | 68 +++++++++++++++++++++++-- scripts/scr_shoot/scr_shoot.gml | 10 ++-- 4 files changed, 107 insertions(+), 11 deletions(-) diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 54f2e61435..ffd40563a9 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -10,11 +10,32 @@ // the health of this many guardsmen (see scr_marine_struct max_health()). 3 = a 3-man weapons team. #macro GUARD_HEAVY_WEAPONS_TEAM_SIZE 3 -// Imperial Guard cover save: fraction of would-be ground-combat casualties treated as -// missed, standing in for spacing, terrain use and a low profile that the combat model -// does not simulate. Applied after armour, so it also blunts armour-piercing weapons -// (choppaz, power klawz) that ignore Flak entirely. 0 = no save, 0.4 = 40% fewer losses. +// Ground-combat cover save: fraction of would-be casualties treated as missed, standing +// in for spacing, terrain use and a low profile the combat model does not simulate. +// Rolled per incoming shot in damage_infantry, after armour, so it also blunts +// armour-piercing weapons that ignore Flak. A successful save posts a combat-log line. +// Astartes are bulky and hide poorly, so their save is much weaker than the Guard's. #macro GUARD_COVER_SAVE 0.4 +#macro MARINE_COVER_SAVE 0.15 + +// Cover fades as the enemy closes: the save is scaled by shooter distance (block units, +// point_distance / 10). At or beyond COVER_SAVE_FULL_RANGE the full save applies; point +// blank it drops to COVER_SAVE_MIN_FACTOR of it, so hugging the line strips cover. +#macro COVER_SAVE_FULL_RANGE 10 +#macro COVER_SAVE_MIN_FACTOR 0.25 + +// Anti-tank penetration roll. A shot that can hurt a vehicle still has to roll to bite, +// so a big volley (a stack of 50 Rokkits) no longer deletes armour outright. Chance +// starts at BASE, rises with the weapon's AP tier, and falls the tougher the target hull +// is (armour class above AC_BASELINE), clamped between MIN and MAX. Rolled per shot in +// damage_vehicles; on a failed roll the shot bounces for no damage. Structured as a +// damage multiplier so a future tiered result (little / medium / severe) can slot in. +#macro AT_PEN_BASE_CHANCE 0.5 +#macro AT_PEN_AP_BONUS 0.12 +#macro AT_PEN_AC_BASELINE 30 +#macro AT_PEN_AC_PENALTY 0.01 +#macro AT_PEN_MIN 0.1 +#macro AT_PEN_MAX 0.95 // Imperial Guard auxilia screen: the front-most battle columns guardsmen are dealt across. // Ten obj_pnunit columns exist (1 back to 10 front, higher column = nearer the enemy); the diff --git a/scripts/scr_cheatcode/scr_cheatcode.gml b/scripts/scr_cheatcode/scr_cheatcode.gml index 524c8332d5..a102c626e2 100644 --- a/scripts/scr_cheatcode/scr_cheatcode.gml +++ b/scripts/scr_cheatcode/scr_cheatcode.gml @@ -119,6 +119,17 @@ function scr_cheatcode(argument0) { scr_company_order(0); } break; + case "veteranguard": + // Promote every basic Guardsman to Veteran Guard (role swap, veteran + // stat buff, Hellgun equip unlocked). promote_auxilia_to_veteran was + // built but never wired to anything, so this is the test trigger; the + // Auxilia "Promote All" button can call the same function. + var _vet_promoted = promote_auxilia_to_veteran(); + with (obj_ini) { + scr_company_order(0); + } + scr_popup("Veteran Guard", $"Promoted {_vet_promoted} Guardsmen to Veteran Guard.", ""); + break; case "chaosfleetspawn": spawn_chaos_warlord(); break; diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index 19b7a5a189..5afc7f5be0 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -128,9 +128,33 @@ function check_dead_marines(unit_struct, unit_index) { return unit_lost; } +/// @desc True if a unit role is Guard auxilia rather than Astartes. Matches the guard +/// role grouping in scr_marine_struct. Used to pick the cover-save rate (Guardsmen use +/// cover well; bulky Astartes do not). +function unit_role_is_guard(_role) { + return (_role == "Guardsman") + || (_role == "Guard Sergeant") + || (_role == "Veteran Guard") + || (_role == "Heavy Weapons Team"); +} + +/// @desc Per-shot anti-tank penetration roll. A shot that can already hurt the vehicle +/// still has to roll to actually bite, so a large volley does not delete armour outright. +/// Chance rises with the attacker's AP tier and falls with the target's armour class. +/// Returns a damage multiplier: currently binary (1 penetrate, 0 bounce). A future tiered +/// version can return partial bands (little / medium / severe) from the same roll without +/// touching the caller. +function at_penetration_multiplier(_arp, _veh_ac) { + var _chance = AT_PEN_BASE_CHANCE + + (_arp - 1) * AT_PEN_AP_BONUS + - max(0, _veh_ac - AT_PEN_AC_BASELINE) * AT_PEN_AC_PENALTY; + _chance = clamp(_chance, AT_PEN_MIN, AT_PEN_MAX); + return (random(1) < _chance) ? 1 : 0; +} + /// @self Id.Instance.obj_pnunit /// @param {Id.Instance.obj_pnunit} target_object -function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, hostile_arp = 0) { +function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, hostile_arp = 0, hostile_dist = 0) { // Converts enemy scr_shoot damage into player marine or vehicle casualties. // // Parameters: @@ -174,7 +198,7 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam // ### Marine + Dreadnought Processing ### if (target_is_infantry && (men + dreads > 0)) { - damage_infantry(damage_data, hostile_shots, hostile_damage, weapon_index_position, hostile_splash, hostile_arp); + damage_infantry(damage_data, hostile_shots, hostile_damage, weapon_index_position, hostile_splash, hostile_arp, hostile_dist); } if (damage_data.hits < hostile_shots) { @@ -191,7 +215,7 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam // ### Marine + Dreadnought Processing ### if (!target_is_infantry && (men + dreads > 0)) { - damage_infantry(damage_data, _remaining_shots, hostile_damage, weapon_index_position, hostile_splash, hostile_arp); + damage_infantry(damage_data, _remaining_shots, hostile_damage, weapon_index_position, hostile_splash, hostile_arp, hostile_dist); } } @@ -210,7 +234,7 @@ function scr_clean(target_object, target_is_infantry, hostile_shots, hostile_dam } /// @self Asset.GMObject.obj_pnunit -function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash, _arp = 0) { +function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash, _arp = 0, _dist = 0) { // _arp is the ATTACKER's armour pierce, passed down from scr_shoot. This used to read // apa[_weapon_index], but this function runs in the TARGET obj_pnunit's context, so // that indexed the PLAYER's own weapon-stack arp table with the ENEMY's stack number. @@ -316,6 +340,19 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash, var _killed_roles = []; var _killed_counts = []; + // Cover save. A fraction of incoming shots are treated as deflected by spacing, + // terrain and a low profile the model does not otherwise simulate. Guard auxilia are + // trained to use cover and get the full GUARD_COVER_SAVE; Astartes are bulky and hide + // poorly, so they get the weaker MARINE_COVER_SAVE. The rate is chosen per unit from + // its role, since the old block-level guard flag is dead and live guardsmen are just + // unit_struct units. The save fades as the enemy closes: it is scaled by shooter + // distance so hugging the line strips it (see COVER_SAVE_FULL_RANGE / + // COVER_SAVE_MIN_FACTOR). Rolled per shot below, after armour, so it also blunts + // armour-piercing weapons that ignore Flak entirely. + var _cover_dist_factor = clamp(_dist / COVER_SAVE_FULL_RANGE, COVER_SAVE_MIN_FACTOR, 1); + var _cover_saved = 0; + var _cover_role = ""; + // Apply damage for each shot for (var shot = 0; shot < _shots; shot++) { if (array_length(valid_marines) == 0) { @@ -329,6 +366,16 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash, var marine = unit_struct[marine_index]; _damage_data.unit_type = marine.role(); + // Cover save: the shot is spent (counts as a hit above) but deflected, so it does + // no damage. Only whole shots are saved, so a save never partially wounds. Rate is + // the unit's own (Guard auxilia get more cover than bulky Astartes). + var _cover_save = (unit_role_is_guard(marine.role()) ? GUARD_COVER_SAVE : MARINE_COVER_SAVE) * _cover_dist_factor; + if ((_cover_save > 0) && (random(1) < _cover_save)) { + _cover_saved++; + _cover_role = marine.role(); + continue; + } + // Apply damage var _shot_luck = roll_dice_chapter(1, 100, "low"); var _modified_damage = 0; @@ -461,6 +508,13 @@ function damage_infantry(_damage_data, _shots, _damage, _weapon_index, _splash, _damage_data.unit_type = _killed_roles[_top]; } + // Report the cover save in the combat log so a volley that hits little or nothing is + // explained rather than looking like a miss. Light blue, matching the non-lethal + // (armour-holds) family of lines. + if ((_cover_saved > 0) && (_cover_role != "")) { + obj_ncombat.combat_log.push($"The {_cover_role} weather the fire from effective cover!", make_color_rgb(120, 190, 225)); + } + return; } @@ -523,6 +577,12 @@ function damage_vehicles(_damage_data, _shots, _damage, _weapon_index, _arp = 0) if (_modified_damage < 0) { _modified_damage = 0; } + // Anti-tank penetration roll: a shot that can bite still has to roll to do so, so + // a stack of many shots does not automatically shred armour. A failed roll bounces + // for no damage. Only capable shots roll; ones already soaked to zero just bounce. + if (_modified_damage > 0) { + _modified_damage *= at_penetration_multiplier(_armour_pierce, veh_ac[veh_index]); + } // This ran in the obj_pnunit context, where `enemy` is the block's TARGET // instance variable (set in its own Alarm_0), so enemy fire landing before // the block's first tick crashed with an unset read; and comparing a target diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index 9b2e3a8d6a..2884bbee75 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -24,6 +24,10 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat var hostile_splash; var aggregate_damage = att[weapon_index_position]; var armour_pierce = apa[weapon_index_position]; + + // Shooter-to-target distance in block units, threaded into scr_clean so the cover + // save can fade as the enemy closes (see damage_infantry / COVER_SAVE_FULL_RANGE). + var _shot_dist = instance_exists(target_object) ? point_distance(x, y, target_object.x, target_object.y) / 10 : 0; if (obj_ncombat.wall_destroyed == 1) { exit; } @@ -112,7 +116,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat hostile_range = range[weapon_index_position]; hostile_splash = attack_count_mod; - scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce); + scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce, _shot_dist); } } else if ((damage_type == "att") && (aggregate_damage > 0) && (stop == 0) && (shots_fired > 0)) { var damage_per_weapon, hit_number; @@ -148,7 +152,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat hostile_range = range[weapon_index_position]; hostile_splash = attack_count_mod; - scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce); + scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce, _shot_dist); } } else if (((damage_type == "arp") || (damage_type == "dread")) && (armour_pierce > 0) && (stop == 0) && (shots_fired > 0)) { var damage_per_weapon, hit_number; @@ -199,7 +203,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat target_object.hostile_shooters = (wep_owner[weapon_index_position] == "assorted") ? 999 : 1; hostile_type = 0; - scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce); + scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce, _shot_dist); } } } From 97a3812a2ecc5efadedee0fdad3d2b41e064f17e Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 18:33:27 +0300 Subject: [PATCH 125/140] Enemy wounds and armour-piercing now render bright red, not green 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. --- scripts/CombatLog/CombatLog.gml | 13 +++++++++++++ scripts/scr_flavor2/scr_flavor2.gml | 12 +++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/scripts/CombatLog/CombatLog.gml b/scripts/CombatLog/CombatLog.gml index 5605f73ca8..e8427808e8 100644 --- a/scripts/CombatLog/CombatLog.gml +++ b/scripts/CombatLog/CombatLog.gml @@ -7,6 +7,13 @@ enum eMSG_COLOR { // Light green tier ported from Tavish's CM-Poligon color coding (CptMacTavish2224, // tag LW_Beta_1.2): hits that wounded without killing. LIGHTGREEN = 9, + // Bright red: the enemy's mirror of LIGHTGREEN. Enemy fire that wounds or pierces + // armour without killing, so incoming damage reads as a threat (red family) instead + // of borrowing the player's green. Kills stay the muted RED; this is the brighter + // "it hurt but nobody died yet" tier. + BRIGHT_RED = 10, + // Bright blue: reserved for continuous / ongoing-narration log lines. + BRIGHT_BLUE = 11, } /// @param {Id.Instance} _owner The optional owning instance or controller. @@ -126,6 +133,12 @@ function CombatLog(_owner = undefined) constructor { case eMSG_COLOR.LIGHTGREEN: _final_color = c_lime; break; + case eMSG_COLOR.BRIGHT_RED: + _final_color = make_color_rgb(255, 60, 60); + break; + case eMSG_COLOR.BRIGHT_BLUE: + _final_color = make_color_rgb(70, 150, 255); + break; } // Wrap individual line segment if width limits are set diff --git a/scripts/scr_flavor2/scr_flavor2.gml b/scripts/scr_flavor2/scr_flavor2.gml index 4d8d69f8a1..c60cd6a4c9 100644 --- a/scripts/scr_flavor2/scr_flavor2.gml +++ b/scripts/scr_flavor2/scr_flavor2.gml @@ -521,11 +521,13 @@ function scr_flavor2(lost_units_count, target_type, hostile_range, hostile_weapo // which lands on the lowest tier. if ((m2 == "") && (lost_units_count == 0) && (hostile_shots > 0) && (target_type != "wall")) { m2 = incoming_damage_flavor(damage_severity, target_is_vehicle); - // Color coding ported from Tavish's CM-Poligon (CptMacTavish2224, tag - // LW_Beta_1.2): outcome reads at a glance against the red kill lines. Shots - // that bounced with no effect render white, hits that wounded without - // killing render light green. - mes_color = (damage_severity < 0.10) ? eMSG_COLOR.WHITE : eMSG_COLOR.LIGHTGREEN; + // Enemy fire reads in the red family, mirroring the player's green. A shot that + // bounces with no effect renders grey (neutral, same as armour-holds on both + // sides); a hit that wounds or pierces without killing renders bright red so + // incoming damage stands out as a threat rather than borrowing the player's + // light green. (Colour paradigm: green/light green = you dealing damage, + // red/bright red = the enemy dealing damage, grey = a save with no effect.) + mes_color = (damage_severity < 0.10) ? eMSG_COLOR.WHITE : eMSG_COLOR.BRIGHT_RED; } mes = m1 + m2 + m3; From 6f1b10cc17776ee363e1c153c5cfca7706e55e45 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 18:52:14 +0300 Subject: [PATCH 126/140] Make the Hellgun forgeable in the Armamentariuml; Guardsman veterancy: 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. --- datafiles/data/weapons.json | 3 ++- objects/obj_ncombat/Alarm_7.gml | 15 +++++++++++++++ scripts/macros/macros.gml | 6 ++++++ scripts/scr_cheatcode/scr_cheatcode.gml | 16 ++++++++++++++++ scripts/scr_roster/scr_roster.gml | 6 ++++++ 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index aa35817329..036d65ec58 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1326,7 +1326,8 @@ "tags": [ "las", "veteran_guard_only" - ] + ], + "value": 8 }, "Hellrifle": { "abbreviation": "HllRifle", diff --git a/objects/obj_ncombat/Alarm_7.gml b/objects/obj_ncombat/Alarm_7.gml index 962ebc5405..e85ff9815a 100644 --- a/objects/obj_ncombat/Alarm_7.gml +++ b/objects/obj_ncombat/Alarm_7.gml @@ -10,6 +10,21 @@ try { LOGGER.info($"Ground Combat - {(defeat ? "Defeat" : "Victory")} - Enemy:{enemy} ({battle_special})"); + // Guardsman veterancy: award battle experience to Guardsmen who fought here and + // lived, identified as basic Guardsmen still on the roster at the battle location + // (the same star-name match the meeting muster below uses). Only on victory. Around + // GUARD_VETERAN_XP / GUARD_BATTLE_XP survived battles makes one eligible for + // promotion to Veteran Guard (see promote_auxilia_to_veteran). + if (!defeat) { + var _grd_survivors = collect_role_group("all", "", false, { roles: ["Guardsman"] }); + for (var _gs = 0; _gs < array_length(_grd_survivors); _gs++) { + var _grd = _grd_survivors[_gs]; + if (_grd.location_string == obj_ncombat.battle_loc) { + _grd.add_experience(GUARD_BATTLE_XP); + } + } + } + // If battling own dudes, then remove the loyalists after the fact if (enemy == eFACTION.PLAYER) { diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index ffd40563a9..68d13ae467 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -16,6 +16,12 @@ // armour-piercing weapons that ignore Flak. A successful save posts a combat-log line. // Astartes are bulky and hide poorly, so their save is much weaker than the Guard's. #macro GUARD_COVER_SAVE 0.4 +// Guardsman veterancy: a Guardsman who fights at the battle location and survives earns +// GUARD_BATTLE_XP experience per victory. At GUARD_VETERAN_XP total they become eligible +// for promotion to Veteran Guard, so a trooper must live through roughly +// GUARD_VETERAN_XP / GUARD_BATTLE_XP battles (90 / 25 ~= 3-4). Both are tunable. +#macro GUARD_BATTLE_XP 25 +#macro GUARD_VETERAN_XP 90 #macro MARINE_COVER_SAVE 0.15 // Cover fades as the enemy closes: the save is scaled by shooter distance (block units, diff --git a/scripts/scr_cheatcode/scr_cheatcode.gml b/scripts/scr_cheatcode/scr_cheatcode.gml index a102c626e2..04e4847d81 100644 --- a/scripts/scr_cheatcode/scr_cheatcode.gml +++ b/scripts/scr_cheatcode/scr_cheatcode.gml @@ -130,6 +130,22 @@ function scr_cheatcode(argument0) { } scr_popup("Veteran Guard", $"Promoted {_vet_promoted} Guardsmen to Veteran Guard.", ""); break; + case "guardxp": + // Grant experience to every basic Guardsman for testing the veterancy + // gate without fighting several battles. "guardxp" alone grants exactly + // enough to promote (GUARD_VETERAN_XP); "guardxp N" grants N. Follow with + // the veteranguard cheat (or the Promote All button) to promote the now + // eligible troopers. + var _xp_amt = real(cheat_arguments[0]); + if (_xp_amt <= 1) { + _xp_amt = GUARD_VETERAN_XP; + } + var _grd_all = collect_role_group("all", "", false, { roles: ["Guardsman"] }); + for (var _gx = 0; _gx < array_length(_grd_all); _gx++) { + _grd_all[_gx].add_experience(_xp_amt); + } + scr_popup("Guard XP", $"Granted {_xp_amt} experience to {array_length(_grd_all)} Guardsmen.", ""); + break; case "chaosfleetspawn": spawn_chaos_warlord(); break; diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 1e4ef6a7b3..7f69ff2e0d 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -905,6 +905,12 @@ function promote_auxilia_to_veteran(_company = undefined) { if (_company != undefined && _unit.company != _company) { continue; } + // Only battle-hardened Guardsmen qualify: they must have earned GUARD_VETERAN_XP + // experience, roughly GUARD_VETERAN_XP / GUARD_BATTLE_XP survived battles. Fresh + // recruits are skipped until they have bled for it. + if (_unit.experience < GUARD_VETERAN_XP) { + continue; + } _unit.update_role("Veteran Guard"); _unit.stat_boosts({ ballistic_skill: 8, From a646b5ccceaf4d61c8160bc691d46fe82052436c Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 19:00:21 +0300 Subject: [PATCH 127/140] Guardsman Veterancy fix, Hellgun forgeable, Range damage Falloff feature 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. --- scripts/macros/macros.gml | 16 ++++++++++------ scripts/scr_shoot/scr_shoot.gml | 20 +++++++++++++++----- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 68d13ae467..26afc82202 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -16,12 +16,6 @@ // armour-piercing weapons that ignore Flak. A successful save posts a combat-log line. // Astartes are bulky and hide poorly, so their save is much weaker than the Guard's. #macro GUARD_COVER_SAVE 0.4 -// Guardsman veterancy: a Guardsman who fights at the battle location and survives earns -// GUARD_BATTLE_XP experience per victory. At GUARD_VETERAN_XP total they become eligible -// for promotion to Veteran Guard, so a trooper must live through roughly -// GUARD_VETERAN_XP / GUARD_BATTLE_XP battles (90 / 25 ~= 3-4). Both are tunable. -#macro GUARD_BATTLE_XP 25 -#macro GUARD_VETERAN_XP 90 #macro MARINE_COVER_SAVE 0.15 // Cover fades as the enemy closes: the save is scaled by shooter distance (block units, @@ -43,6 +37,16 @@ #macro AT_PEN_MIN 0.1 #macro AT_PEN_MAX 0.95 +// Range accuracy/damage falloff for ranged fire. Damage is scaled by how far the target +// is relative to the weapon's range: at point blank it gets RANGE_POINT_BLANK_BONUS, and +// it falls by up to RANGE_FALLOFF at maximum range, floored at RANGE_MIN_MULT. Short-range +// weapons (Shotgun, Flamer) can only ever fire close, so they live in the bonus band and +// hit hard; long-range weapons soften at the edge of their reach. Melee and wall fire are +// exempt. Applied to dealt damage in scr_shoot. +#macro RANGE_POINT_BLANK_BONUS 1.25 +#macro RANGE_FALLOFF 0.5 +#macro RANGE_MIN_MULT 0.6 + // Imperial Guard auxilia screen: the front-most battle columns guardsmen are dealt across. // Ten obj_pnunit columns exist (1 back to 10 front, higher column = nearer the enemy); the // Marine and vehicle roles only use columns 1-7, so 8-10 are free front-most positions. diff --git a/scripts/scr_shoot/scr_shoot.gml b/scripts/scr_shoot/scr_shoot.gml index 2884bbee75..1ee09982d3 100644 --- a/scripts/scr_shoot/scr_shoot.gml +++ b/scripts/scr_shoot/scr_shoot.gml @@ -28,6 +28,16 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat // Shooter-to-target distance in block units, threaded into scr_clean so the cover // save can fade as the enemy closes (see damage_infantry / COVER_SAVE_FULL_RANGE). var _shot_dist = instance_exists(target_object) ? point_distance(x, y, target_object.x, target_object.y) / 10 : 0; + + // Range accuracy/damage falloff. Ranged fire hits hardest up close and softens + // toward the weapon's maximum range; melee and wall fire are exempt (a knife does + // not care about distance). Applied to dealt damage below. See RANGE_* macros. + var _range_mult = 1; + if (melee_or_ranged == "ranged") { + var _weapon_range = range[weapon_index_position]; + var _range_ratio = (_weapon_range > 0) ? clamp(_shot_dist / _weapon_range, 0, 1) : 0; + _range_mult = clamp(RANGE_POINT_BLANK_BONUS - _range_ratio * RANGE_FALLOFF, RANGE_MIN_MULT, RANGE_POINT_BLANK_BONUS); + } if (obj_ncombat.wall_destroyed == 1) { exit; } @@ -116,7 +126,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat hostile_range = range[weapon_index_position]; hostile_splash = attack_count_mod; - scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce, _shot_dist); + scr_clean(target_object, hostile_type, hit_number, (hostile_damage * _range_mult), hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce, _shot_dist); } } else if ((damage_type == "att") && (aggregate_damage > 0) && (stop == 0) && (shots_fired > 0)) { var damage_per_weapon, hit_number; @@ -152,7 +162,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat hostile_range = range[weapon_index_position]; hostile_splash = attack_count_mod; - scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce, _shot_dist); + scr_clean(target_object, hostile_type, hit_number, (hostile_damage * _range_mult), hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce, _shot_dist); } } else if (((damage_type == "arp") || (damage_type == "dread")) && (armour_pierce > 0) && (stop == 0) && (shots_fired > 0)) { var damage_per_weapon, hit_number; @@ -203,7 +213,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat target_object.hostile_shooters = (wep_owner[weapon_index_position] == "assorted") ? 999 : 1; hostile_type = 0; - scr_clean(target_object, hostile_type, hit_number, hostile_damage, hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce, _shot_dist); + scr_clean(target_object, hostile_type, hit_number, (hostile_damage * _range_mult), hostile_weapon, hostile_range, hostile_splash, weapon_index_position, armour_pierce, _shot_dist); } } } @@ -368,7 +378,7 @@ function scr_shoot(weapon_index_position, target_object, target_type, damage_dat var _ap_table = spill_block.dudes_vehicle[spill_rank] ? _veh_ap : _inf_ap; _armour *= _ap_table[armour_pierce]; } - var final_hit = max(0, (damage_per_weapon - (_armour * attack_count_mod)) * spill_block.dudes_dr[spill_rank]); + var final_hit = max(0, (damage_per_weapon * _range_mult - (_armour * attack_count_mod)) * spill_block.dudes_dr[spill_rank]); var rank_num = spill_block.dudes_num[spill_rank]; var rank_hp = spill_block.dudes_hp[spill_rank]; @@ -578,7 +588,7 @@ function scr_shoot_spread(weapon_index_position) { } var _rank_shots = _shots * (_f.dudes_num[r] / _total); - var _final_hit = max(0, (_dpw - (_armour * _mod)) * _f.dudes_dr[r]); + var _final_hit = max(0, (_dpw * _range_mult - (_armour * _mod)) * _f.dudes_dr[r]); var _kills = min(floor((_rank_shots * _final_hit) / _f.dudes_hp[r]), _f.dudes_num[r]); if (_kills < 0) { _kills = 0; From 8686fdd9f4d64a24059ed5e34da61dac5bb01efe Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 19:18:50 +0300 Subject: [PATCH 128/140] Advance the player line front-first in one ordered sweep, fixing rear-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. --- objects/obj_pnunit/Alarm_0.gml | 12 ++--- .../scr_player_combat_weapon_stacks.gml | 5 ++ .../scr_punit_combat_heplers.gml | 46 +++++++++++++++++++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/objects/obj_pnunit/Alarm_0.gml b/objects/obj_pnunit/Alarm_0.gml index 3c95d159cf..a537f90959 100644 --- a/objects/obj_pnunit/Alarm_0.gml +++ b/objects/obj_pnunit/Alarm_0.gml @@ -40,13 +40,11 @@ try { // gone froze mid-field with no order marker. A block the player has personally // ordered (order_manual) still advances and leapfrogs freely for manual maneuver, // ignoring the latch. - if ((move_order == "advance") && (veh_type[1] != "Defenses")) { - if (order_manual) { - move_unit_block("east", 1, false, true); - } else if (!obj_ncombat.player_front_contact) { - move_unit_block("east", 1, false, false); - } - } + // Advance-to-contact movement now runs once per turn in move_player_blocks (called + // from set_up_player_blocks_turn) as a front-first ordered sweep, so a rear block no + // longer stalls behind a front block that has not moved yet. By the time this alarm + // fires the line has already advanced; this event only resolves fire. The front-contact + // latch is still refreshed below from this block's post-move position. engaged = collision_point(x - 14, y, obj_enunit, 0, 1) != noone || collision_point(x + 14, y, obj_enunit, 0, 1) != noone; diff --git a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml index aee37b397d..8b2a6d4632 100644 --- a/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml +++ b/scripts/scr_player_combat_weapon_stacks/scr_player_combat_weapon_stacks.gml @@ -511,6 +511,11 @@ function scr_player_combat_weapon_stacks() { /// @self Asset.GMObject.obj_ncombat function set_up_player_blocks_turn() { if (instance_exists(obj_pnunit)) { + // Advance the line front-first as one ordered pass before any block fires, so a + // rear block never stalls behind a front block that has not moved yet (see + // move_player_blocks). Movement used to run per-block inside Alarm_0 in arbitrary + // instance order, which drifted rear vehicles out of the formation. + move_player_blocks(); with (obj_pnunit) { alarm[3] = 2; wait_and_execute(3, scr_player_combat_weapon_stacks); diff --git a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml index 3ce16b7295..44f86273ae 100644 --- a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml +++ b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml @@ -256,6 +256,52 @@ function move_enemy_blocks() { ds_priority_destroy(_enemy_movement_queue); } +/// @self Asset.GMObject.obj_pnunit +/// @desc One player block's advance-to-contact step. Seeds this block's order on its +/// first tick (raids/attacks advance, defense/static hold), advances one column east if +/// ordered to (a personally ordered block leapfrogs; the auto-advancing body stops once +/// the formation has met the enemy line), then latches formation contact so blocks +/// processed later in the same front-first sweep hold instead of surging into gaps. +/// Extracted from obj_pnunit Alarm_0 so movement can run in a single ordered pass. +function move_player_block() { + if (move_order == "") { + move_order = (obj_ncombat.dropping || (!obj_ncombat.defending && obj_ncombat.formation_set != 2)) ? "advance" : "hold"; + } + if ((move_order == "advance") && (veh_type[1] != "Defenses")) { + if (order_manual) { + move_unit_block("east", 1, false, true); + } else if (!obj_ncombat.player_front_contact) { + move_unit_block("east", 1, false, false); + } + } + if (collision_point(x + 14, y, obj_enunit, 0, 1)) { + obj_ncombat.player_front_contact = true; + } +} + +/// @self Asset.GMObject.obj_controller +/// @desc Advance the whole player line front-first, mirroring move_enemy_blocks. Player +/// front is the high-x (east) side, so the queue is drained highest-x first: the frontmost +/// block advances and clears its column before the block behind it tries to move, so a rear +/// block (a Rhino sitting behind the infantry) no longer stalls against a slot the front +/// block has not vacated yet and drift out of the line. Replaces the old arbitrary +/// instance-order per-block advance in obj_pnunit Alarm_0. +function move_player_blocks() { + var _player_movement_queue = ds_priority_create(); + with (obj_pnunit) { + ds_priority_add(_player_movement_queue, id, x); + } + while (!ds_priority_empty(_player_movement_queue)) { + var _player_block = ds_priority_delete_max(_player_movement_queue); + if (instance_exists(_player_block)) { + with (_player_block) { + move_player_block(); + } + } + } + ds_priority_destroy(_player_movement_queue); +} + /// @self Asset.GMObject.obj_enunit|Asset.GMObject.obj_pnunit function block_composition_string() { var _composition_string = $"{unit_count}x Total; "; From f589666da4aa78e5cbf5d6a9c2436dfce43c0de1 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 19:28:33 +0300 Subject: [PATCH 129/140] Drive anti-tank penetration off vehicle cost tier, not weapon AP (Land 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. --- scripts/macros/macros.gml | 16 +++--------- scripts/scr_clean/scr_clean.gml | 45 +++++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 26afc82202..1c20baea33 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -24,18 +24,10 @@ #macro COVER_SAVE_FULL_RANGE 10 #macro COVER_SAVE_MIN_FACTOR 0.25 -// Anti-tank penetration roll. A shot that can hurt a vehicle still has to roll to bite, -// so a big volley (a stack of 50 Rokkits) no longer deletes armour outright. Chance -// starts at BASE, rises with the weapon's AP tier, and falls the tougher the target hull -// is (armour class above AC_BASELINE), clamped between MIN and MAX. Rolled per shot in -// damage_vehicles; on a failed roll the shot bounces for no damage. Structured as a -// damage multiplier so a future tiered result (little / medium / severe) can slot in. -#macro AT_PEN_BASE_CHANCE 0.5 -#macro AT_PEN_AP_BONUS 0.12 -#macro AT_PEN_AC_BASELINE 30 -#macro AT_PEN_AC_PENALTY 0.01 -#macro AT_PEN_MIN 0.1 -#macro AT_PEN_MAX 0.95 +// Anti-tank penetration is now a per-vehicle, cost-tiered weak-spot chance defined in +// vehicle_penetration_chance (scr_clean), not a weapon-AP formula: a capable shot rolls +// that chance to get through, so an armour-ignoring volley cannot brute-force a heavy hull +// (a Land Raider sits at 5%). Tune the chances there, per vehicle type. // Range accuracy/damage falloff for ranged fire. Damage is scaled by how far the target // is relative to the weapon's range: at point blank it gets RANGE_POINT_BLANK_BONUS, and diff --git a/scripts/scr_clean/scr_clean.gml b/scripts/scr_clean/scr_clean.gml index 5afc7f5be0..62f1c90a70 100644 --- a/scripts/scr_clean/scr_clean.gml +++ b/scripts/scr_clean/scr_clean.gml @@ -138,18 +138,37 @@ function unit_role_is_guard(_role) { || (_role == "Heavy Weapons Team"); } -/// @desc Per-shot anti-tank penetration roll. A shot that can already hurt the vehicle -/// still has to roll to actually bite, so a large volley does not delete armour outright. -/// Chance rises with the attacker's AP tier and falls with the target's armour class. -/// Returns a damage multiplier: currently binary (1 penetrate, 0 bounce). A future tiered -/// version can return partial bands (little / medium / severe) from the same roll without -/// touching the caller. -function at_penetration_multiplier(_arp, _veh_ac) { - var _chance = AT_PEN_BASE_CHANCE - + (_arp - 1) * AT_PEN_AP_BONUS - - max(0, _veh_ac - AT_PEN_AC_BASELINE) * AT_PEN_AC_PENALTY; - _chance = clamp(_chance, AT_PEN_MIN, AT_PEN_MAX); - return (random(1) < _chance) ? 1 : 0; +/// @desc Penetration (critical-hit) chance for a capable anti-tank shot, keyed to the +/// vehicle's cost tier rather than the weapon's AP. Expensive war machines present almost +/// no weak spot, so only a rare lucky hit to the right area gets through: a Land Raider +/// (value 500) sits at 5%, cheaper hulls climb toward the light APCs. This is what stops a +/// handful of Rokkits from deleting a Land Raider line: an arp-4 shot ignores armour and +/// one-shots on a hit, so the CHANCE is the gate, not the damage. Values track +/// vehicles.json costs (Land Raider 500, Predator 240, Whirlwind 180, Rhino/Land Speeder +/// 120) and are the balance knob. +function vehicle_penetration_chance(_veh_type) { + switch (_veh_type) { + case "Land Raider": return 0.05; // value 500, tankiest hull + case "Leman Russ": return 0.10; // Guard heavy battle tank + case "Predator": return 0.15; // value 240 + case "Whirlwind": return 0.22; // value 180, armoured artillery + case "Basilisk": return 0.28; // Guard artillery, thin armour + case "Chimera": return 0.40; // Guard APC + case "Rhino": return 0.45; // value 120, light APC + case "Land Speeder": return 0.55; // value 120, fast and lightly armoured + } + return 0.35; // any unlisted vehicle +} + +/// @desc Anti-tank penetration roll for one capable shot. The caller only invokes this +/// once the shot would deal damage, so this decides whether it actually gets through. +/// Chance is the vehicle's cost-tiered weak-spot chance (see vehicle_penetration_chance), +/// deliberately independent of the weapon's AP so a big AP volley cannot brute-force a +/// heavy hull. Returns a damage multiplier: binary today (1 penetrate, 0 bounce); a future +/// tiered result (little / medium / severe, or a disable band) can come from the same roll +/// without touching the caller. +function at_penetration_multiplier(_veh_type) { + return (random(1) < vehicle_penetration_chance(_veh_type)) ? 1 : 0; } /// @self Id.Instance.obj_pnunit @@ -581,7 +600,7 @@ function damage_vehicles(_damage_data, _shots, _damage, _weapon_index, _arp = 0) // a stack of many shots does not automatically shred armour. A failed roll bounces // for no damage. Only capable shots roll; ones already soaked to zero just bounce. if (_modified_damage > 0) { - _modified_damage *= at_penetration_multiplier(_armour_pierce, veh_ac[veh_index]); + _modified_damage *= at_penetration_multiplier(veh_type[veh_index]); } // This ran in the obj_pnunit context, where `enemy` is the block's TARGET // instance variable (set in its own Alarm_0), so enemy fire landing before From 9cfa395e6b84c97050db869b4581a5a561ecbf25 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 19:42:48 +0300 Subject: [PATCH 130/140] Replace leapfrog teleport with parallel-lane pass so ordered formations 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. --- scripts/macros/macros.gml | 8 ++++ .../scr_punit_combat_heplers.gml | 39 ++++++++++++------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 1c20baea33..32e6951d90 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -29,6 +29,14 @@ // that chance to get through, so an armour-ignoring volley cannot brute-force a heavy hull // (a Land Raider sits at 5%). Tune the chances there, per vehicle type. +// Combat lane geometry. Blocks form up on the home lane (created at y = 240). When a +// personally ordered formation has to pass a friendly block ahead, it steps into a +// parallel lane this many pixels off the home lane, advances past, then re-forms onto the +// home lane once its column is clear (see move_unit_block / move_player_block). The offset +// must clear a block's drawn height so lanes do not overlap; tune if tall formations touch. +#macro COMBAT_HOME_LANE_Y 240 +#macro PLAYER_LANE_OFFSET 40 + // Range accuracy/damage falloff for ranged fire. Damage is scaled by how far the target // is relative to the weapon's range: at point blank it gets RANGE_POINT_BLANK_BONUS, and // it falls by up to RANGE_FALLOFF at maximum range, floored at RANGE_MIN_MULT. Short-range diff --git a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml index 44f86273ae..25a4577fa6 100644 --- a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml +++ b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml @@ -183,10 +183,11 @@ function block_position_collision(position_x, position_y) { /// @param {string} direction In what direction to move ("east" or "west") /// @param {real} blocks How far to move (in unit blocks) /// @param {bool} allow_collision Are unit blocks allowed to passthrough other unit blocks -/// @param {bool} leapfrog When the destination is blocked by a FRIENDLY block, hop over the -/// contiguous friendly column(s) to the first free slot beyond (probing at most -/// PLAYER_LEAPFROG_MAX_COLUMNS columns). Never lands on or vaults past an enemy block, so -/// contact with the enemy is still made by normal one-step movement and engagement. +/// @param {bool} leapfrog When the destination is blocked by a FRIENDLY block, step into a +/// free parallel lane (offset from the home lane by PLAYER_LANE_OFFSET) and advance past it +/// instead of stalling, keeping this formation's own order; the block re-forms onto the home +/// lane once its column is clear (see move_player_block). Never steps onto a position an +/// enemy holds, so contact is still made by normal one-step movement and engagement. /// @return {bool} /// @self Asset.GMObject.obj_pnunit function move_unit_block(direction, blocks = 1, allow_collision = false, leapfrog = false) { @@ -208,19 +209,23 @@ function move_unit_block(direction, blocks = 1, allow_collision = false, leapfro return true; } - // Leapfrogging (basic combat orders): only when the immediate blocker is a - // friendly block and not an enemy. + // Lane side-step (basic combat orders): a personally ordered formation blocked by + // a friendly block ahead steps into a free parallel lane and advances past it, + // keeping its own order, instead of teleporting over the line. It re-forms onto the + // home lane once its column is clear (see move_player_block). It never steps onto a + // position an enemy holds. This replaces the old leapfrog teleport, which jumped the + // block to the next empty column and tangled formations (the back line snapping to + // the front). Only manual orders pass leapfrog == true, so the auto-advancing body + // never side-steps; it still advances to contact in lane. if (leapfrog && (_step != 0) && collision_point(_new_pos, y, obj_pnunit, 0, 1) && !collision_point(_new_pos, y, obj_enunit, 0, 1)) { - var _hop = _new_pos + _step; - repeat (PLAYER_LEAPFROG_MAX_COLUMNS) { - if (collision_point(_hop, y, obj_enunit, 0, 1)) { - break; - } - if (!collision_point(_hop, y, obj_pnunit, 0, 1)) { - x = _hop; + var _lane_tries = [PLAYER_LANE_OFFSET, -PLAYER_LANE_OFFSET, PLAYER_LANE_OFFSET * 2, -PLAYER_LANE_OFFSET * 2]; + for (var _lt = 0; _lt < array_length(_lane_tries); _lt++) { + var _lane_y = COMBAT_HOME_LANE_Y + _lane_tries[_lt]; + if (!block_position_collision(_new_pos, _lane_y)) { + x = _new_pos; + y = _lane_y; return true; } - _hop += _step; } } @@ -274,6 +279,12 @@ function move_player_block() { move_unit_block("east", 1, false, false); } } + // Re-form: a formation that stepped into a parallel lane to pass slides back onto the + // home lane as soon as its column there is clear, so the line closes up instead of + // leaving blocks strung out in side lanes. + if ((y != COMBAT_HOME_LANE_Y) && !block_position_collision(x, COMBAT_HOME_LANE_Y)) { + y = COMBAT_HOME_LANE_Y; + } if (collision_point(x + 14, y, obj_enunit, 0, 1)) { obj_ncombat.player_front_contact = true; } From 9028db50a7492333b370b55c858cf62e61dce692 Mon Sep 17 00:00:00 2001 From: KestasV Date: Tue, 7 Jul 2026 20:03:43 +0300 Subject: [PATCH 131/140] Revert combat lane offset; formations stay on one line 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. --- scripts/macros/macros.gml | 8 ---- .../scr_punit_combat_heplers.gml | 40 +++++-------------- 2 files changed, 9 insertions(+), 39 deletions(-) diff --git a/scripts/macros/macros.gml b/scripts/macros/macros.gml index 32e6951d90..1c20baea33 100644 --- a/scripts/macros/macros.gml +++ b/scripts/macros/macros.gml @@ -29,14 +29,6 @@ // that chance to get through, so an armour-ignoring volley cannot brute-force a heavy hull // (a Land Raider sits at 5%). Tune the chances there, per vehicle type. -// Combat lane geometry. Blocks form up on the home lane (created at y = 240). When a -// personally ordered formation has to pass a friendly block ahead, it steps into a -// parallel lane this many pixels off the home lane, advances past, then re-forms onto the -// home lane once its column is clear (see move_unit_block / move_player_block). The offset -// must clear a block's drawn height so lanes do not overlap; tune if tall formations touch. -#macro COMBAT_HOME_LANE_Y 240 -#macro PLAYER_LANE_OFFSET 40 - // Range accuracy/damage falloff for ranged fire. Damage is scaled by how far the target // is relative to the weapon's range: at point blank it gets RANGE_POINT_BLANK_BONUS, and // it falls by up to RANGE_FALLOFF at maximum range, floored at RANGE_MIN_MULT. Short-range diff --git a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml index 25a4577fa6..deeff17675 100644 --- a/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml +++ b/scripts/scr_punit_combat_heplers/scr_punit_combat_heplers.gml @@ -183,11 +183,10 @@ function block_position_collision(position_x, position_y) { /// @param {string} direction In what direction to move ("east" or "west") /// @param {real} blocks How far to move (in unit blocks) /// @param {bool} allow_collision Are unit blocks allowed to passthrough other unit blocks -/// @param {bool} leapfrog When the destination is blocked by a FRIENDLY block, step into a -/// free parallel lane (offset from the home lane by PLAYER_LANE_OFFSET) and advance past it -/// instead of stalling, keeping this formation's own order; the block re-forms onto the home -/// lane once its column is clear (see move_player_block). Never steps onto a position an -/// enemy holds, so contact is still made by normal one-step movement and engagement. +/// @param {bool} leapfrog Retained for callers; the move-through behaviours this once +/// enabled (leapfrog teleport, parallel-lane pass) were tried and reverted, so a block +/// blocked by a friendly currently just holds. Movement-through will return with the +/// per-unit-type formation rework. /// @return {bool} /// @self Asset.GMObject.obj_pnunit function move_unit_block(direction, blocks = 1, allow_collision = false, leapfrog = false) { @@ -209,26 +208,11 @@ function move_unit_block(direction, blocks = 1, allow_collision = false, leapfro return true; } - // Lane side-step (basic combat orders): a personally ordered formation blocked by - // a friendly block ahead steps into a free parallel lane and advances past it, - // keeping its own order, instead of teleporting over the line. It re-forms onto the - // home lane once its column is clear (see move_player_block). It never steps onto a - // position an enemy holds. This replaces the old leapfrog teleport, which jumped the - // block to the next empty column and tangled formations (the back line snapping to - // the front). Only manual orders pass leapfrog == true, so the auto-advancing body - // never side-steps; it still advances to contact in lane. - if (leapfrog && (_step != 0) && collision_point(_new_pos, y, obj_pnunit, 0, 1) && !collision_point(_new_pos, y, obj_enunit, 0, 1)) { - var _lane_tries = [PLAYER_LANE_OFFSET, -PLAYER_LANE_OFFSET, PLAYER_LANE_OFFSET * 2, -PLAYER_LANE_OFFSET * 2]; - for (var _lt = 0; _lt < array_length(_lane_tries); _lt++) { - var _lane_y = COMBAT_HOME_LANE_Y + _lane_tries[_lt]; - if (!block_position_collision(_new_pos, _lane_y)) { - x = _new_pos; - y = _lane_y; - return true; - } - } - } - + // A block blocked by a friendly ahead simply holds this tick rather than + // teleporting over the line or side-stepping into a parallel lane (both tried and + // reverted). Movement-through will be revisited with the per-unit-type formation + // rework; for now the auto-advancing body closes to contact and manual orders + // advance until something is in the way. return false; } catch (_exception) { ERROR_HANDLER.handle_exception(_exception); @@ -279,12 +263,6 @@ function move_player_block() { move_unit_block("east", 1, false, false); } } - // Re-form: a formation that stepped into a parallel lane to pass slides back onto the - // home lane as soon as its column there is clear, so the line closes up instead of - // leaving blocks strung out in side lanes. - if ((y != COMBAT_HOME_LANE_Y) && !block_position_collision(x, COMBAT_HOME_LANE_Y)) { - y = COMBAT_HOME_LANE_Y; - } if (collision_point(x + 14, y, obj_enunit, 0, 1)) { obj_ncombat.player_front_contact = true; } From d0adc327cdfde905712eddf2dd62aa02d91f24c5 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 8 Jul 2026 04:22:16 +0300 Subject: [PATCH 132/140] Dreadnoughts fire infantry weapon versions; HK Missile penetration to 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. --- datafiles/data/weapons.json | 7 +++-- .../scr_marine_struct/scr_marine_struct.gml | 26 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index 036d65ec58..778ac027e1 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -1326,8 +1326,7 @@ "tags": [ "las", "veteran_guard_only" - ], - "value": 8 + ] }, "Hellrifle": { "abbreviation": "HllRifle", @@ -1355,7 +1354,7 @@ "HK Missile": { "abbreviation": "HKMssl", "ammo": 1, - "arp": 1, + "arp": 4, "attack": { "artifact": 450, "master_crafted": 400, @@ -3410,4 +3409,4 @@ "xenos" ] } -} +} \ No newline at end of file diff --git a/scripts/scr_marine_struct/scr_marine_struct.gml b/scripts/scr_marine_struct/scr_marine_struct.gml index f7f7648ee6..081762014b 100644 --- a/scripts/scr_marine_struct/scr_marine_struct.gml +++ b/scripts/scr_marine_struct/scr_marine_struct.gml @@ -1210,10 +1210,16 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} }; static get_weapon_one_data = function(type = "all") { + if (is_dreadnought()) { + return gear_weapon_data("weapon", dread_infantry_weapon(weapon_one()), type, false, weapon_one_quality, dread_infantry_weapon(weapon_one(true))); + } return gear_weapon_data("weapon", weapon_one(), type, false, weapon_one_quality, weapon_one(true)); }; static get_weapon_two_data = function(type = "all") { + if (is_dreadnought()) { + return gear_weapon_data("weapon", dread_infantry_weapon(weapon_two()), type, false, weapon_two_quality, dread_infantry_weapon(weapon_two(true))); + } return gear_weapon_data("weapon", weapon_two(), type, false, weapon_two_quality, weapon_two(true)); }; @@ -2315,6 +2321,26 @@ function TTRPG_stats(faction, comp, mar, class = "marine", other_spawn_data = {} }; } +/// @desc Maps a dreadnought's heavy Mount/Sponson weapon variant to its infantry +/// equivalent. Per upstream direction, a dreadnought fires the infantry version of what it +/// carries: the Mount/Sponson variants exist for vehicles and hit far harder, which was +/// only ever a way to brute-force vehicle damage before the penetration roll existed. +/// Weapons that are already infantry, or unique dreadnought weapons without an infantry +/// counterpart (Kheres Assault Cannon, Inferno Cannon), pass through unchanged, as do +/// non-string equips (artifacts). +function dread_infantry_weapon(_weapon) { + if (!is_string(_weapon)) { + return _weapon; + } + switch (_weapon) { + case "Twin Linked Assault Cannon Mount": return "Assault Cannon"; + case "Twin Linked Heavy Bolter Mount": return "Twin Linked Heavy Bolter"; + case "Twin Linked Lascannon Mount": return "Twin Linked Lascannon"; + case "Twin Linked Heavy Flamer Sponsons": return "Heavy Flamer"; + } + return _weapon; +} + function jsonify_marine_struct(company, marine, stringify = true) { var copy_marine_struct = obj_ini.TTRPG[company][marine]; //grab marine structure var new_marine = {}; From 2e772ac0cfe6332fb27fe009f20bbdd2ae453f34 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 8 Jul 2026 04:54:36 +0300 Subject: [PATCH 133/140] Sync upstream: welcome + formation-bar refactors, CODE_STYLE (Combat is held OURS) Merge of the 4 upstream commits fork main was behind. Adopted: docs CODE_STYLE (#1305), welcome-message fold in obj_controller Create (#1303, untouched here), and the formation-bar collapse + for_arr->bat_for rename (#1304) in obj_formation_bar Create and scr_ui_formation_bars (rename self-contained, fields preserved). Kept OURS: scr_shoot (#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 #1304 removed the same col_parent idle reset we already fixed, so our version already covers it plus the comment). --- docs/CODE_STYLE.md | 2 +- objects/obj_controller/Create_0.gml | 330 ++++-------------- objects/obj_formation_bar/Create_0.gml | 120 ++----- .../scr_ui_formation_bars.gml | 38 +- 4 files changed, 108 insertions(+), 382 deletions(-) diff --git a/docs/CODE_STYLE.md b/docs/CODE_STYLE.md index efaa6a265b..26a7412ec5 100644 --- a/docs/CODE_STYLE.md +++ b/docs/CODE_STYLE.md @@ -108,7 +108,7 @@ All variable names, function names, etc., should use `snake_case` unless stated ### Performance -- **Precalculate array length for loops.** `for (var i = 0, l = array_length(array); i < l; i++)`. +- **Precalculate array length for loops in hotpaths.** `for (var i = 0, l = array_length(array); i < l; i++)` if the loop runs somewhere where loop speed matters. - **Keep heavy logic (loops, allocations) out of Draw and Step events**. These events run every frame and can destroy performance. - **Prefer `arrays` and `structs` over `ds_*` structures** (`ds_map`, `ds_list`, `ds_grid`, `ds_stack`, `ds_queue`). If you must use a `ds_*` structure, always pair it with a corresponding `ds_destroy` call to avoid memory leaks. diff --git a/objects/obj_controller/Create_0.gml b/objects/obj_controller/Create_0.gml index 80c980eec1..c50a540b35 100644 --- a/objects/obj_controller/Create_0.gml +++ b/objects/obj_controller/Create_0.gml @@ -1382,6 +1382,7 @@ if (global.load == -1) { } // **** INTRO SCREEN **** +#region Intro Scroll temp[30] = string(check_number) + " " + string(year_fraction) + " " + string(year) + ".M" + string(millenium); // Date temp[31] = string_upper(adept_name); // Adept name temp[32] = string_upper(obj_ini.name[0][0]); // Master name @@ -1389,286 +1390,79 @@ temp[33] = string_upper(scr_thought()); // Thought of the day // Game start welcoming message LOGGER.info("Game start welcoming message"); -var njm = 34, com = 0, vih = 0, word = "", masta = 0, forga = 0, chapla = 0, apa = 0, liba = 0, techa = 0, libra = 0, coda = 0, lexa = 0, apotha = 0, old_dudes = 0; -var honoh = 0, termi = 0, veter = 0, capt = 0, chap = 0, apoth = 0, stand = 0, dread = 0, champ = 0, tact = 0, assa = 0, deva = 0, rhino = 0, speeder = 0, raider = 0, standard = 0, bike = 0, scou = 0, whirl = 0, pred = 0, lib = 0, serg = 0, vet_serg = 0; -for (var mm = 0; mm <= 100; mm++) { - if (obj_ini.role[com][mm] == obj_ini.role[100][eROLE.CHAPTERMASTER]) { - masta = 1; - } - if (obj_ini.role[com][mm] == "Forge Master") { - forga = 1; - } - if (obj_ini.role[com][mm] == "Master of Sanctity") { - chapla = 1; - } - if (obj_ini.role[com][mm] == "Master of the Apothecarion") { - apa = 1; - } - if (obj_ini.role[com][mm] == "Chief " + string(obj_ini.role[100][eROLE.LIBRARIAN])) { - liba = 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][eROLE.TECHMARINE]) { - techa += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][eROLE.LIBRARIAN]) { - libra += 1; - } - if (obj_ini.role[com][mm] == "Codiciery") { - coda += 1; - } - if (obj_ini.role[com][mm] == "Lexicanum") { - lexa += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][eROLE.CHAPLAIN]) { - old_dudes += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][eROLE.APOTHECARY]) { - apotha += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][eROLE.HONOURGUARD]) { - honoh += 1; - } -} - -temp[njm] = "Command staff made of"; +var _canon = obj_ini.role[100]; -// Command staff names start at index 1 rather than 0 to align with the chapter company structure -if (masta == 1) { - temp[njm] += $", your majesty Chapter Master {obj_ini.name[com][0]}"; -} -if (forga == 1) { - temp[njm] += $", Forge Master {obj_ini.name[com][1]}"; -} -if (chapla == 1) { - temp[njm] += $", Master of Sanctity {obj_ini.name[com][2]}"; -} -if (apa == 1) { - temp[njm] += $", Master of the Apothecarion {obj_ini.name[com][3]}"; -} -if (liba == 1) { - temp[njm] += $", and Chief Librarian {obj_ini.name[com][4]}. "; -} +var _build_clause = function(_prefix, _parts) { + if (array_length(_parts) == 0) { + return ""; + } + return $"{_prefix} {string_join_ext(", ", _parts)}."; +}; -vih = string_pos(",", temp[njm]); -temp[njm] = string_delete(temp[njm], vih, 1); -njm += 1; -temp[njm] = "Specialist branches staffed by"; -if (techa > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][16], techa)}"; -} -if (old_dudes > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][14], old_dudes)}"; -} -if (apotha > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][15], apotha)}"; -} -if (libra > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][17], libra)}"; -} -if (coda > 0) { - temp[njm] += $", {string_plural_count("Codiciery", coda)}"; -} -if (lexa > 0) { - temp[njm] += $", {string_plural_count("Lexicanum", lexa)}."; -} +var _hq_index = collect_company(0).index_roles(); +var _command_staff = [ + { role: _canon[eROLE.CHAPTERMASTER], name_slot: 0, prefix: "your majesty " }, + { role: "Forge Master", name_slot: 1, prefix: "" }, + { role: "Master of Sanctity", name_slot: 2, prefix: "" }, + { role: "Master of the Apothecarion", name_slot: 3, prefix: "" }, + { role: $"Chief {_canon[eROLE.LIBRARIAN]}", name_slot: 4, prefix: "and " }, +]; -vih = string_pos(",", temp[njm]); -temp[njm] = string_delete(temp[njm], vih, 1); +var _parts = []; +for (var i = 0, l = array_length(_command_staff); i < l; i++) { + var _officer = _command_staff[i]; + if (_hq_index.has_role(_officer.role)) { + array_push(_parts, $"{_officer.prefix}{_officer.role} {obj_ini.name[0][_officer.name_slot]}"); + } +}; +temp[34] = _build_clause("Command staff made of", _parts); -if (honoh > 0) { - temp[njm] += $"\n\nHonour Guard, having the {honoh} most veteran {string_plural("marine", honoh)} of your chapter serving in it."; -} +var _specialist_display = [ + _canon[eROLE.TECHMARINE], _canon[eROLE.CHAPLAIN], _canon[eROLE.APOTHECARY], + _canon[eROLE.LIBRARIAN], "Codiciery", "Lexicanum", +]; +_parts = []; +for (var i = 0, l = array_length(_specialist_display); i < l; i++) { + var _role_name = _specialist_display[i]; + var _count = _hq_index.has_role(_role_name) ? _hq_index.role_count(_role_name) : 0; + if (_count > 0) { + array_push(_parts, string_plural_count(_role_name, _count)); + } +}; +temp[35] = _build_clause("Specialist branches staffed by", _parts); +var _honour_guard_count = _hq_index.has_role(_canon[eROLE.HONOURGUARD]) ? _hq_index.role_count(_canon[eROLE.HONOURGUARD]) : 0; +if (_honour_guard_count > 0) { + temp[35] += $"\n\nHonour Guard, having the {_honour_guard_count} most veteran {string_plural("marine", _honour_guard_count)} of your chapter serving in it."; +}; -for (var company = 0; company < 10; company++) { - njm++; - com++; - fisted = 0; - techa = 0; - termi = 0; - veter = 0; - capt = 0; - chap = 0; - apoth = 0; - stand = 0; - dread = 0; - champ = 0; - tact = 0; - assa = 0; - deva = 0; - rhino = 0; - speeder = 0; - raider = 0; - standard = 0; - bike = 0; - scou = 0; - whirl = 0; - pred = 0; - lib = 0; - serg = 0; - vet_serg = 0; - for (var mm = 1; mm <= 400; mm++) { - if (obj_ini.role[com][mm] == obj_ini.role[100][3]) { - veter += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][4]) { - termi += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][5]) { - capt += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][6]) { - dread += 1; - } - if (obj_ini.role[com][mm] == "Venerable " + string(obj_ini.role[100][6])) { - dread += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][7]) { - champ += 1; - } +var _vehicle_display = ["Land Raider", "Predator", "Whirlwind", "Rhino", "Land Speeder"]; - if (obj_ini.role[com][mm] == obj_ini.role[100][8]) { - tact += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][9]) { - deva += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][10]) { - assa += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][11]) { - standard += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][12]) { - scou += 1; - } - - if (obj_ini.role[com][mm] == obj_ini.role[100][14]) { - chap += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][15]) { - apoth += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][16]) { - techa += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][17]) { - lib += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][18]) { - serg += 1; - } - if (obj_ini.role[com][mm] == obj_ini.role[100][19]) { - vet_serg += 1; +for (var _com = 1; _com <= 10; _com++) { + var _index = collect_company(_com).index_roles(); + var _veh_counts = {}; + for (var v = 1; v <= 100; v++) { + var _veh = obj_ini.veh_role[_com][v]; + if (_veh != "") { + _veh_counts[$ _veh] = (_veh_counts[$ _veh] ?? 0) + 1; } } - for (vih = 1; vih <= 100; vih++) { - if (obj_ini.veh_role[com][vih] == "Land Raider") { - raider += 1; - } - if (obj_ini.veh_role[com][vih] == "Rhino") { - rhino += 1; - } - if (obj_ini.veh_role[com][vih] == "Land Speeder") { - speeder += 1; - } - if (obj_ini.veh_role[com][vih] == "Bike") { - bike += 1; - } - if (obj_ini.veh_role[com][vih] == "Predator") { - pred += 1; - } - if (obj_ini.veh_role[com][vih] == "Whirlwind") { - whirl += 1; + _parts = []; + var _keys = _index.hierarchy_keys(); + for (var i = 0, l = array_length(_keys); i < l; i++) { + var _count = _index.role_count(_keys[i]); + if (_count > 0) { + array_push(_parts, string_plural_count(_keys[i], _count)); } } - - if (com > 0) { - if (veter + termi + stand + dread + tact + assa + deva + rhino + raider + standard + scou + whirl > 0) { - temp[njm] = $"{integer_to_words(com, true, true)} company made of"; - } else { - temp[njm] = ""; + for (var i = 0, l = array_length(_vehicle_display); i < l; i++) { + var _count = _veh_counts[$ _vehicle_display[i]] ?? 0; + if (_count > 0) { + array_push(_parts, string_plural_count(_vehicle_display[i], _count)); } } - - if (capt > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][5], capt)}"; - } - if (chap > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][14], chap)}"; - } - if (apoth > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][15], apoth)}"; - } - if (techa > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][16], techa)}"; - } - if (standard > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][11], standard)}"; - } - if (champ > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][7], champ)}"; - } - if (lib > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][17], lib)}"; - } - - if (serg > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][18], serg)}"; - } - if (vet_serg > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][19], vet_serg)}"; - } - if (termi > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][4], termi)}"; - } - if (veter > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][3], veter)}"; - } - if (tact > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][8], tact)}"; - } - if (assa > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][10], assa)}"; - } - if (deva > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][9], deva)}"; - } - if (scou > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][12], scou)}"; - } - if (dread > 0) { - temp[njm] += $", {string_plural_count(obj_ini.role[100][6], dread)}"; - } - - if (raider > 0) { - temp[njm] += $", {string_plural_count("Land Raider", raider)}"; - } - if (pred > 0) { - temp[njm] += $", {string_plural_count("Predator", pred)}"; - } - if (whirl > 0) { - temp[njm] += $", {string_plural_count("Whirlwind", whirl)}"; - } - if (rhino > 0) { - temp[njm] += $", {string_plural_count("Rhino", rhino)}"; - } - if (speeder > 0) { - temp[njm] += $", {string_plural_count("Land Speeder", speeder)}"; - } - if (bike > 0) { - temp[njm] += $", {string_plural_count("Attack Bike", bike)}"; - } - - if (string_length(temp[njm]) > 0) { - temp[njm] += "."; - } - - if (njm != 0) { - vih = string_pos(",", temp[njm]); - temp[njm] = string_delete(temp[njm], vih, 1); - } -} + temp[35 + _com] = _build_clause($"{integer_to_words(_com, true, true)} company made of", _parts); +}; LOGGER.info("create Ships"); @@ -1828,5 +1622,5 @@ alarm_set(0, 2); location_viewer.update_fleet_table(); armamentarium = new Armamentarium(self); - +#endregion //**! DO NOT PUT THINGS AT THE BOTTOM OF THIS FILE IF YOU NEED THEM TO WORK AFTER LOADING FROM A SAVE, SEE LINE 1550 -ish */ diff --git a/objects/obj_formation_bar/Create_0.gml b/objects/obj_formation_bar/Create_0.gml index 14d65d3f8e..4fe48ba0ba 100644 --- a/objects/obj_formation_bar/Create_0.gml +++ b/objects/obj_formation_bar/Create_0.gml @@ -6,6 +6,8 @@ old_y = 0; unit_type = ""; unit_id = 0; +/// @desc Reference to the controller's bat_*_for array, injected via move_data_to_current_scope in init_combat_bars +bat_for = undefined; size = 0; col_parent = 0; @@ -91,7 +93,6 @@ drag_logic = function(){ rel_mousey = 0; old_x = 0; old_y = 0; - col_parent = 0; col_target = 0; above_neighbor = 0; nearest_col = 0; @@ -130,102 +131,33 @@ mouse_release = function(){ } if ((dragging == true) && instance_exists(mah_target)) { - if ((x >= mah_target.x - 5) && (x <= mah_target.x + 42) && (mouse_consts[1] >= 222) && (mouse_consts[1] <= 688)) { - var himcol, te; - himcol = mah_target.col_parent; - te = 0; - te = 4800 + himcol; - nexti = false; - - if (obj_controller.temp[te] + size <= 10) { - obj_controller.temp[4800 + col_parent] -= size; - obj_controller.click = 1; - if (unit_id == 1) { - obj_controller.bat_comm_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 2) { - obj_controller.bat_hono_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 3) { - obj_controller.bat_libr_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 4) { - obj_controller.bat_tech_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 5) { - obj_controller.bat_term_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 6) { - obj_controller.bat_vete_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 7) { - obj_controller.bat_tact_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 8) { - obj_controller.bat_deva_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 9) { - obj_controller.bat_assa_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 10) { - obj_controller.bat_scou_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 11) { - obj_controller.bat_drea_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 12) { - obj_controller.bat_hire_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 13) { - obj_controller.bat_rhin_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 14) { - obj_controller.bat_pred_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 15) { - obj_controller.bat_landraid_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 16) { - obj_controller.bat_landspee_for[obj_controller.formating] = mah_target.col_parent; - } - if (unit_id == 17) { - obj_controller.bat_whirl_for[obj_controller.formating] = mah_target.col_parent; - } - obj_cursor.dragging = 0; - obj_cursor.image_index = 0; - - // show_message("-> slot "+string(mah_target.col_parent)+", now "+string(obj_controller.temp[te]+size)+"/10 full, old slot is "+string(obj_controller.temp[4800+col_parent])+"/10"); - - with (obj_temp8) { - instance_destroy(); - } - with (obj_controller) { - bar_fix = true; - } - exit; + var _in_drop_zone = (x >= mah_target.x - 5) && (x <= mah_target.x + 42) && (mouse_consts[1] >= 222) && (mouse_consts[1] <= 688); + var te = 4800 + mah_target.col_parent; + + if (_in_drop_zone && (obj_controller.temp[te] + size <= 10)) { + obj_controller.temp[4800 + col_parent] -= size; + obj_controller.click = 1; + bat_for[@ obj_controller.formating] = mah_target.col_parent; + obj_cursor.dragging = 0; + obj_cursor.image_index = 0; + + with (obj_temp8) { + instance_destroy(); } - if (obj_controller.temp[te] + size > 10) { - dragging = false; - x = old_x; - y = old_y; - obj_cursor.dragging = 0; - obj_cursor.image_index = 0; - if ((global.settings.master_volume > 0) && (global.settings.sfx_volume > 0)) { - audio_play_sound(snd_error, -80, false); - } + with (obj_controller) { + bar_fix = true; } + exit; } - if (instance_exists(mah_target)) { - if ((x < mah_target.x - 5) || (x > mah_target.x + 42) || ( 222) || (mouse_consts[1] > 688)) { - dragging = false; - x = old_x; - y = old_y; - obj_cursor.dragging = 0; - obj_cursor.image_index = 0; - if ((global.settings.master_volume > 0) && (global.settings.sfx_volume > 0)) { - audio_play_sound(snd_error, -80, false); - } - } + + // Column full, or dropped outside the drop zone: snap back + dragging = false; + x = old_x; + y = old_y; + obj_cursor.dragging = 0; + obj_cursor.image_index = 0; + if ((global.settings.master_volume > 0) && (global.settings.sfx_volume > 0)) { + audio_play_sound(snd_error, -80, false); } } diff --git a/scripts/scr_ui_formation_bars/scr_ui_formation_bars.gml b/scripts/scr_ui_formation_bars/scr_ui_formation_bars.gml index c902f4b290..36bcf1ad74 100644 --- a/scripts/scr_ui_formation_bars/scr_ui_formation_bars.gml +++ b/scripts/scr_ui_formation_bars/scr_ui_formation_bars.gml @@ -18,25 +18,25 @@ function scr_ui_formation_bars() { } var _bar_configs = [ - { unit_id: 1, for_arr: bat_comm_for, size: 2, image_index: 0, unit_type: "HQ", tooltip: "Headquarters", tooltip2: "You and your advisors will be placed within this section. It is strongly advisable you give them backup in this same column." }, - { unit_id: 2, for_arr: bat_hono_for, size: 1, image_index: 1, unit_type: "Hono", tooltip: "Honour Guard", tooltip2: "Any Honour Guard within your Headquarters will be placed here. The best place for them within the formation depends on loadout." }, - { unit_id: 3, for_arr: bat_libr_for, size: 1, image_index: 8, unit_type: "Lib", tooltip: "Librarians", tooltip2: "Epistolary, Lexicanum, and Codiciery make up this section. They tend to deal decent damage and offer useful buffs for other units." }, - { unit_id: 4, for_arr: bat_tech_for, size: 1, image_index: 9, unit_type: "Tech", tooltip: "Techmarines", tooltip2: "Techmarines and their servitors are placed within this block. It is advisable that they are placed near your vehicles and armour." }, - { unit_id: 5, for_arr: bat_term_for, size: 1, image_index: 10, unit_type: "Term", tooltip: "Terminators", tooltip2: "Any Terminators that you may have will be placed here. They can very easily soak lots of damage and dish it back in return." }, - { unit_id: 6, for_arr: bat_vete_for, size: 2, image_index: 6, unit_type: "Veteran", tooltip: "Veterans", tooltip2: "Veterans, the most experienced tacticals of your Chapter, are placed here. Their best position in the formation depends on loadout." }, - { unit_id: 7, for_arr: bat_tact_for, size: 6, image_index: 3, unit_type: "Tactical", tooltip: "Tacticals", tooltip2: "The greater bulk of your Chapter, the tactical marines, go here. Tactical marines may be situated nearly anywhere. Note that Apothecaries and Chaplains without jump-packs will also be placed here." }, - { unit_id: 8, for_arr: bat_deva_for, size: 3, image_index: 2, unit_type: "Devastator", tooltip: "Devastators", tooltip2: "Devastators offer much long ranged firepower. As a result they are best placed in the rear of your formation." }, - { unit_id: 9, for_arr: bat_assa_for, size: 3, image_index: 5, unit_type: "Assault", tooltip: "Assaults", tooltip2: "Assault marines are damage powerhouses, but tend to be squisher. You may or may not wish for them to be on the front lines. Note that Apothecaries and Chaplains with jump-packs will be placed here." }, - { unit_id: 10, for_arr: bat_scou_for, size: 1, image_index: 4, unit_type: "Sco", tooltip: "Scouts", tooltip2: "Scouts are not-yet full fledged Astartes. Striking a balance between exposure to the enemy, for experience, and safety is key." }, - { unit_id: 11, for_arr: bat_drea_for, size: 2, image_index: 11, unit_type: "Dread", tooltip: "Dreadnoughts", tooltip2: "Dreadnoughts are the most durable and tough marines within your chapter. They are best suited for the front lines." }, - { unit_id: 12, for_arr: bat_hire_for, size: 1, image_index: 7, unit_type: "???", tooltip: "Hirelings", tooltip2: "Any and all units that you recieve from other factions are placed within this block." }, - { unit_id: 16, for_arr: bat_landspee_for, size: 2, image_index: 14, unit_type: "Land Speeder", tooltip: "Land Speeders", tooltip2: "Land Speeders are incredibly agile attack vehicles that offer a light highly mobile heavy weapon platform." }, + { unit_id: 1, bat_for: bat_comm_for, size: 2, image_index: 0, unit_type: "HQ", tooltip: "Headquarters", tooltip2: "You and your advisors will be placed within this section. It is strongly advisable you give them backup in this same column." }, + { unit_id: 2, bat_for: bat_hono_for, size: 1, image_index: 1, unit_type: "Hono", tooltip: "Honour Guard", tooltip2: "Any Honour Guard within your Headquarters will be placed here. The best place for them within the formation depends on loadout." }, + { unit_id: 3, bat_for: bat_libr_for, size: 1, image_index: 8, unit_type: "Lib", tooltip: "Librarians", tooltip2: "Epistolary, Lexicanum, and Codiciery make up this section. They tend to deal decent damage and offer useful buffs for other units." }, + { unit_id: 4, bat_for: bat_tech_for, size: 1, image_index: 9, unit_type: "Tech", tooltip: "Techmarines", tooltip2: "Techmarines and their servitors are placed within this block. It is advisable that they are placed near your vehicles and armour." }, + { unit_id: 5, bat_for: bat_term_for, size: 1, image_index: 10, unit_type: "Term", tooltip: "Terminators", tooltip2: "Any Terminators that you may have will be placed here. They can very easily soak lots of damage and dish it back in return." }, + { unit_id: 6, bat_for: bat_vete_for, size: 2, image_index: 6, unit_type: "Veteran", tooltip: "Veterans", tooltip2: "Veterans, the most experienced tacticals of your Chapter, are placed here. Their best position in the formation depends on loadout." }, + { unit_id: 7, bat_for: bat_tact_for, size: 6, image_index: 3, unit_type: "Tactical", tooltip: "Tacticals", tooltip2: "The greater bulk of your Chapter, the tactical marines, go here. Tactical marines may be situated nearly anywhere. Note that Apothecaries and Chaplains without jump-packs will also be placed here." }, + { unit_id: 8, bat_for: bat_deva_for, size: 3, image_index: 2, unit_type: "Devastator", tooltip: "Devastators", tooltip2: "Devastators offer much long ranged firepower. As a result they are best placed in the rear of your formation." }, + { unit_id: 9, bat_for: bat_assa_for, size: 3, image_index: 5, unit_type: "Assault", tooltip: "Assaults", tooltip2: "Assault marines are damage powerhouses, but tend to be squisher. You may or may not wish for them to be on the front lines. Note that Apothecaries and Chaplains with jump-packs will be placed here." }, + { unit_id: 10, bat_for: bat_scou_for, size: 1, image_index: 4, unit_type: "Sco", tooltip: "Scouts", tooltip2: "Scouts are not-yet full fledged Astartes. Striking a balance between exposure to the enemy, for experience, and safety is key." }, + { unit_id: 11, bat_for: bat_drea_for, size: 2, image_index: 11, unit_type: "Dread", tooltip: "Dreadnoughts", tooltip2: "Dreadnoughts are the most durable and tough marines within your chapter. They are best suited for the front lines." }, + { unit_id: 12, bat_for: bat_hire_for, size: 1, image_index: 7, unit_type: "???", tooltip: "Hirelings", tooltip2: "Any and all units that you recieve from other factions are placed within this block." }, + { unit_id: 16, bat_for: bat_landspee_for, size: 2, image_index: 14, unit_type: "Land Speeder", tooltip: "Land Speeders", tooltip2: "Land Speeders are incredibly agile attack vehicles that offer a light highly mobile heavy weapon platform." }, ]; var _attack_only_options = [ - { unit_id: 13, for_arr: bat_rhin_for, size: 4, image_index: 12, unit_type: "Rhino", tooltip: "Rhinos", tooltip2: "Rhinos offer protection for units behind them but are not well armoured and lacking in firepower." }, - { unit_id: 14, for_arr: bat_pred_for, size: 2, image_index: 13, unit_type: "Predator", tooltip: "Predators", tooltip2: "Predators offer protection for units behind them and have a decent amount of long ranged firepower." }, - { unit_id: 15, for_arr: bat_landraid_for, size: 2, image_index: 14, unit_type: "Land Raider",tooltip: "Land Raiders", tooltip2: "Land Raiders are incredibly tanky war machines that protect rear columns and offer tremendous amounts of firepower. Other super-heavy vehicles will also be placed here." }, - { unit_id: 17, for_arr: bat_whirl_for, size: 2, image_index: 14, unit_type: "Whirlwind", tooltip: "Whirlwinds", tooltip2: "Whirlwinds are armoured fire-support capable of supporting assaults from a long range safe from enemy retaliation." }, + { unit_id: 13, bat_for: bat_rhin_for, size: 4, image_index: 12, unit_type: "Rhino", tooltip: "Rhinos", tooltip2: "Rhinos offer protection for units behind them but are not well armoured and lacking in firepower." }, + { unit_id: 14, bat_for: bat_pred_for, size: 2, image_index: 13, unit_type: "Predator", tooltip: "Predators", tooltip2: "Predators offer protection for units behind them and have a decent amount of long ranged firepower." }, + { unit_id: 15, bat_for: bat_landraid_for, size: 2, image_index: 14, unit_type: "Land Raider",tooltip: "Land Raiders", tooltip2: "Land Raiders are incredibly tanky war machines that protect rear columns and offer tremendous amounts of firepower. Other super-heavy vehicles will also be placed here." }, + { unit_id: 17, bat_for: bat_whirl_for, size: 2, image_index: 14, unit_type: "Whirlwind", tooltip: "Whirlwinds", tooltip2: "Whirlwinds are armoured fire-support capable of supporting assaults from a long range safe from enemy retaliation." }, ]; for (var bar = 1; bar <= 10; bar++) { @@ -52,7 +52,7 @@ function scr_ui_formation_bars() { for (var _i = 0; _i < array_length(_bar_configs); _i++) { var _cfg = _bar_configs[_i]; - if ((_cfg.unit_id == unit_id) && (_cfg.for_arr[_formatting] == bar)) { + if ((_cfg.unit_id == unit_id) && (_cfg.bat_for[_formatting] == bar)) { init_combat_bars(bar, ui_formations_data, _cfg); break; } @@ -60,7 +60,7 @@ function scr_ui_formation_bars() { if (bat_formation_type[_formatting] != 2) { for (var _i = 0; _i < array_length(_attack_only_options); _i++) { var _cfg = _attack_only_options[_i]; - if ((_cfg.unit_id == unit_id) && (_cfg.for_arr[_formatting] == bar)) { + if ((_cfg.unit_id == unit_id) && (_cfg.bat_for[_formatting] == bar)) { init_combat_bars(bar, ui_formations_data, _cfg); break; } From 4cb046af472275fc7be60688f740aeeb3122da7d Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 8 Jul 2026 05:11:44 +0300 Subject: [PATCH 134/140] Sync upstream (6 new): dread-tag removal, HK arp, forge/equip fixes (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 (#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). --- datafiles/data/weapons.json | 8 ++--- objects/obj_mass_equip/Step_0.gml | 7 +++- .../scr_get_item_names/scr_get_item_names.gml | 6 ++-- .../scr_specialist_point_handler.gml | 23 +++++++----- .../scr_struct_functions.gml | 36 ++++++++++++++----- 5 files changed, 52 insertions(+), 28 deletions(-) diff --git a/datafiles/data/weapons.json b/datafiles/data/weapons.json index 778ac027e1..1fa5e0cee6 100644 --- a/datafiles/data/weapons.json +++ b/datafiles/data/weapons.json @@ -2873,8 +2873,7 @@ "tags": [ "vehicle", "heavy_ranged", - "pintle", - "dreadnought" + "pintle" ], "value": 60 }, @@ -2967,7 +2966,6 @@ "spli": 21, "tags": [ "vehicle", - "dreadnought", "heavy_ranged", "bolt" ], @@ -2996,7 +2994,6 @@ "flame", "heavy_ranged", "vehicle", - "dreadnought", "sponson" ], "value": 150 @@ -3045,8 +3042,7 @@ "las", "energy", "vehicle", - "heavy_ranged", - "dreadnought" + "heavy_ranged" ] }, "Twin Linked Lascannon Sponsons": { diff --git a/objects/obj_mass_equip/Step_0.gml b/objects/obj_mass_equip/Step_0.gml index 69fd8e21c8..91d9004340 100644 --- a/objects/obj_mass_equip/Step_0.gml +++ b/objects/obj_mass_equip/Step_0.gml @@ -263,7 +263,12 @@ try { } // Add up messages - all_equip = $"In total they are equipped with: {_total_role_gear.get_total_string()}."; + var _totals_string = _total_role_gear.get_custom_string(function(_key, _count, _i, _keys) { + return $"{_count}x {_key}{smart_delimeter_sign(_keys, _i, false)}"; + }); + if (_totals_string != "") { + all_equip = $"In total they are equipped with: {_totals_string}."; + } refresh = false; diff --git a/scripts/scr_get_item_names/scr_get_item_names.gml b/scripts/scr_get_item_names/scr_get_item_names.gml index efd9fbdc29..fa61a18051 100644 --- a/scripts/scr_get_item_names/scr_get_item_names.gml +++ b/scripts/scr_get_item_names/scr_get_item_names.gml @@ -149,22 +149,20 @@ function push_marine_mobility_item_names(_item_names) { /// @param {array} _item_names - The list to append to. /// @returns {void} function push_dreadnought_ranged_weapons_item_names(_item_names) { - var item_count = 11; + var item_count = 9; var initial_size = array_length(_item_names); array_resize(_item_names, initial_size + item_count); var index = initial_size; _item_names[@ index++] = "Multi-Melta"; - _item_names[@ index++] = "Twin Linked Heavy Flamer Sponsons"; _item_names[@ index++] = "Plasma Cannon"; _item_names[@ index++] = "Assault Cannon"; _item_names[@ index++] = "Autocannon"; _item_names[@ index++] = "Missile Launcher"; _item_names[@ index++] = "Twin Linked Lascannon"; - _item_names[@ index++] = "Twin Linked Assault Cannon Mount"; _item_names[@ index++] = "Twin Linked Heavy Bolter"; _item_names[@ index++] = "Heavy Conversion Beam Projector"; - _item_names[@ index++] = "Twin-linked Volkite Culverins"; // 10 + _item_names[@ index++] = "Twin-linked Volkite Culverins"; // 8 } /// @description This function appends the list of dreadnought melee weapons to the given list. diff --git a/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml b/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml index b37e7e891b..54455eb5f2 100644 --- a/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml +++ b/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml @@ -463,12 +463,12 @@ function SpecialistPointHandler() constructor { if (master_craft_count > 0) { scr_add_item(_item.name, master_craft_count, "master_crafted"); var numerical_string = master_craft_count == 1 ? "was" : "were"; - quality_string = $"X{master_craft_count} {numerical_string} Completed to a Master Crafted standard"; + quality_string = $"x{master_craft_count} {numerical_string} completed to a Master Crafted standard!"; } else { - quality_string = $"all were completed to a standard STC compliant quality"; + quality_string = $"All were completed to a standard STC compliant quality!"; } - scr_popup("Forge Completed", $"{_item.display_name} X{_forge_order.count} construction finished {quality_string}", "", ""); + scr_popup("Forge Completed", $"Construction of x{_forge_order.count} {_item.display_name} is finished! {quality_string}", "", ""); }; static scr_evaluate_forge_item_completion = function(_forge_order) { @@ -481,18 +481,25 @@ function SpecialistPointHandler() constructor { if (!is_vehicle) { scr_forge_item(_forge_order); } else { - var _build_locs = []; - + var _loc_counts = new CountingMap(); + repeat (_forge_order.count) { var vehicle = scr_add_vehicle(_item.name, obj_controller.new_vehicles); var build_loc = array_random_element(obj_controller.player_forge_data.vehicle_hanger); obj_ini.veh_loc[vehicle[0]][vehicle[1]] = build_loc[0]; obj_ini.veh_wid[vehicle[0]][vehicle[1]] = build_loc[1]; obj_ini.veh_lid[vehicle[0]][vehicle[1]] = -1; - array_push(_build_locs, $"{build_loc[0]} {build_loc[1]}"); + _loc_counts.add($"{build_loc[0]} {build_loc[1]}"); } - - scr_popup("Forge Completed", $"{_item.display_name} x{_forge_order.count} construction finished! Vehicles waiting at hanger(s) on {string_join_ext(", ", _build_locs)}", "", ""); + + var _loc_summary = _loc_counts.get_custom_string(function(_key, _count) { + return $"{_count} at {_key}\n"; + }); + + var _company = obj_controller.new_vehicles; + var _company_name = (_company >= 1 && _company <= 10) ? $"{int_to_roman(_company)} Company" : "Reserve"; + + scr_popup("Forge Completed", $"Construction of x{_forge_order.count} {_item.display_name} is finished!\n\nAssigned to: {_company_name}\n\nReady at:\n{_loc_summary}", "", ""); } } else if (_item.forge_type == "research") { scr_advance_research(_item.name); diff --git a/scripts/scr_struct_functions/scr_struct_functions.gml b/scripts/scr_struct_functions/scr_struct_functions.gml index f276726acb..ef9f61264c 100644 --- a/scripts/scr_struct_functions/scr_struct_functions.gml +++ b/scripts/scr_struct_functions/scr_struct_functions.gml @@ -56,9 +56,13 @@ function gc_struct(vari) { delete vari; } -function CountingMap() constructor { +function CountingMap(_initial_array = undefined) constructor { map = {}; + if (_initial_array != undefined) { + add_all(_initial_array); + } + static add = function(_key, number = 1) { if (_key == "") { return; @@ -75,16 +79,30 @@ function CountingMap() constructor { } }; - static get_total_string = function() { - var result = ""; - var keys = struct_get_names(map); - - for (var i = 0; i < array_length(keys); i++) { - var key = keys[i]; - result += $"{map[$ key]}x {key}{smart_delimeter_sign(keys, i, false)}"; + static add_all = function(_array) { + if (!is_array(_array)) { + return; } + var _len = array_length(_array); + for (var _i = 0; _i < _len; _i++) { + add(_array[_i]); + } + }; - return result; + static get_custom_string = function(_callback) { + var _keys = struct_get_names(map); + var _len = array_length(_keys); + if (_len == 0) { + return ""; + } + + var _parts = array_create(_len); + for (var _i = 0; _i < _len; _i++) { + var _key = _keys[_i]; + _parts[_i] = _callback(_key, map[$ _key], _i, _keys); + } + + return string_join_ext("", _parts); }; static get_string = function(_key) { From 919817df695900545209bfde23e4701da0ea7160 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 8 Jul 2026 06:03:56 +0300 Subject: [PATCH 135/140] Decouple ship bombard, attack, and raid into independent per-turn counters 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__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. --- objects/obj_bomb_select/Alarm_1.gml | 2 +- .../scr_drop_select_function.gml | 5 +- .../scr_player_ship_functions.gml | 109 ++++++++++++------ scripts/scr_roster/scr_roster.gml | 8 +- 4 files changed, 81 insertions(+), 43 deletions(-) diff --git a/objects/obj_bomb_select/Alarm_1.gml b/objects/obj_bomb_select/Alarm_1.gml index dd5212c675..993b83db76 100644 --- a/objects/obj_bomb_select/Alarm_1.gml +++ b/objects/obj_bomb_select/Alarm_1.gml @@ -23,7 +23,7 @@ for (var i = 0; i < array_length(_ships); i++) { // A ship that has spent any support use this turn (bombarded, or supported a // ground assault or raid) cannot bombard, since bombardment needs a fully // fresh ship. Such ships are listed but locked in the selection grid. - array_push(ship_spent, ship_assaults_used(_ships[i]) > 0); + array_push(ship_spent, ship_bombards_used(_ships[i]) > 0); } } diff --git a/scripts/scr_drop_select_function/scr_drop_select_function.gml b/scripts/scr_drop_select_function/scr_drop_select_function.gml index 69961e9a6a..d4bc831c96 100644 --- a/scripts/scr_drop_select_function/scr_drop_select_function.gml +++ b/scripts/scr_drop_select_function/scr_drop_select_function.gml @@ -308,8 +308,9 @@ function drop_select_unit_selection() { if (_sel_ship > -1) { if (!array_contains(_spent_ships, _sel_ship)) { array_push(_spent_ships, _sel_ship); - ship_assault_spend(_sel_ship); - LOGGER.info($"ASSAULT SPEND ship {_sel_ship}: uses now {ship_assaults_used(_sel_ship)}/{SHIP_ASSAULTS_PER_TURN}"); + var _drop_kind = (attack == 1) ? "assault" : "raid"; + ship_action_spend(_sel_ship, _drop_kind); + LOGGER.info($"{string_upper(_drop_kind)} SPEND ship {_sel_ship}: uses now {ship_action_used(_sel_ship, _drop_kind)}/{SHIP_ASSAULTS_PER_TURN}"); } } else { _local_participated = true; diff --git a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml index 9f51dcc965..731ed58b29 100644 --- a/scripts/scr_player_ship_functions/scr_player_ship_functions.gml +++ b/scripts/scr_player_ship_functions/scr_player_ship_functions.gml @@ -123,48 +123,84 @@ function get_player_ships(location = "", name = "") { return _ships; } -/// @desc How many ground assaults this ship has supported this turn. The counters are -/// keyed to obj_controller.turn: a stored count from any earlier turn reads as zero, so -/// there is no per-turn reset pass and nothing new needs saving (after a load the -/// counters simply start fresh). Out-of-range or missing arrays also read as zero. -function ship_assaults_used(ship_index) { +/// @desc Generic per-ship, per-turn action-use counter for the ship action economy. _kind +/// is "assault" (ground assault), "bombard", or "raid"; each has its OWN independent +/// counter (obj_ini.ship__uses / obj_ini.ship__turn), so spending one action +/// never consumes another. Counters are keyed to obj_controller.turn, so a stored count +/// from any earlier turn reads as zero: no per-turn reset pass and nothing new to save +/// (after a load the counters simply start fresh). Out-of-range or missing arrays read as +/// zero. +function ship_action_used(ship_index, _kind) { if (ship_index < 0) { return 0; } - if (!variable_instance_exists(obj_ini, "ship_assault_uses") || !variable_instance_exists(obj_ini, "ship_assault_turn")) { + var _uses_var = "ship_" + _kind + "_uses"; + var _turn_var = "ship_" + _kind + "_turn"; + if (!variable_instance_exists(obj_ini, _uses_var) || !variable_instance_exists(obj_ini, _turn_var)) { return 0; } - if ((ship_index >= array_length(obj_ini.ship_assault_uses)) || (ship_index >= array_length(obj_ini.ship_assault_turn))) { + var _uses = variable_instance_get(obj_ini, _uses_var); + var _turn = variable_instance_get(obj_ini, _turn_var); + if ((ship_index >= array_length(_uses)) || (ship_index >= array_length(_turn))) { return 0; } - if (obj_ini.ship_assault_turn[ship_index] != obj_controller.turn) { + if (_turn[ship_index] != obj_controller.turn) { return 0; } - return obj_ini.ship_assault_uses[ship_index]; + return _uses[ship_index]; } -/// @desc Spend one ground assault support use on this ship for the current turn. -function ship_assault_spend(ship_index) { +/// @desc Spend one use of action _kind on this ship for the current turn. +function ship_action_spend(ship_index, _kind) { if (ship_index < 0) { return; } - if (!variable_instance_exists(obj_ini, "ship_assault_uses")) { - obj_ini.ship_assault_uses = []; + var _uses_var = "ship_" + _kind + "_uses"; + var _turn_var = "ship_" + _kind + "_turn"; + if (!variable_instance_exists(obj_ini, _uses_var)) { + variable_instance_set(obj_ini, _uses_var, []); } - if (!variable_instance_exists(obj_ini, "ship_assault_turn")) { - obj_ini.ship_assault_turn = []; + if (!variable_instance_exists(obj_ini, _turn_var)) { + variable_instance_set(obj_ini, _turn_var, []); } - while (array_length(obj_ini.ship_assault_uses) <= ship_index) { - array_push(obj_ini.ship_assault_uses, 0); + var _uses = variable_instance_get(obj_ini, _uses_var); + var _turn = variable_instance_get(obj_ini, _turn_var); + while (array_length(_uses) <= ship_index) { + array_push(_uses, 0); } - while (array_length(obj_ini.ship_assault_turn) <= ship_index) { - array_push(obj_ini.ship_assault_turn, -1); + while (array_length(_turn) <= ship_index) { + array_push(_turn, -1); } - if (obj_ini.ship_assault_turn[ship_index] != obj_controller.turn) { - obj_ini.ship_assault_turn[ship_index] = obj_controller.turn; - obj_ini.ship_assault_uses[ship_index] = 0; + if (_turn[ship_index] != obj_controller.turn) { + _turn[ship_index] = obj_controller.turn; + _uses[ship_index] = 0; } - obj_ini.ship_assault_uses[ship_index] += 1; + _uses[ship_index] += 1; + variable_instance_set(obj_ini, _uses_var, _uses); + variable_instance_set(obj_ini, _turn_var, _turn); +} + +/// @desc How many ground assaults this ship has supported this turn (its own counter, +/// independent of bombardment and raids). +function ship_assaults_used(ship_index) { + return ship_action_used(ship_index, "assault"); +} + +/// @desc Spend one ground assault support use on this ship for the current turn. +function ship_assault_spend(ship_index) { + ship_action_spend(ship_index, "assault"); +} + +/// @desc How many orbital bombardments this ship has run this turn (its own counter, +/// independent of ground assaults and raids). +function ship_bombards_used(ship_index) { + return ship_action_used(ship_index, "bombard"); +} + +/// @desc How many raids this ship has supported this turn (its own counter, independent +/// of ground assaults and bombardment). +function ship_raids_used(ship_index) { + return ship_action_used(ship_index, "raid"); } /// @desc How many ground assaults this planet's local forces have supported this turn. @@ -712,18 +748,17 @@ function player_guardsmen_at(system_name) { return _total; } -/// @desc Whether a ground deployment (attack or raid) can still be supported at this -/// star this turn: any carrying ship with support uses left, or the planet's local -/// forces with local uses left. Ships and local forces are tracked independently, so -/// spending one ship does not lock the rest of the fleet (the point of the per-ship -/// action economy). +/// @desc Whether a raid can still be supported at this star this turn: any carrying ship +/// with raid uses left (its own counter), or the planet's local forces with local uses +/// left. Ship raid uses are independent of ground-assault and bombardment uses, so +/// bombarding or attacking with a ship does not block raiding with it. function can_ground_deploy(star_object, planet_number) { if (!instance_exists(star_object)) { return false; } var _ships = get_player_ships(star_object.name); for (var i = 0; i < array_length(_ships); i++) { - if ((obj_ini.ship_carrying[_ships[i]] > 0) && (ship_assaults_used(_ships[i]) < SHIP_ASSAULTS_PER_TURN)) { + if ((obj_ini.ship_carrying[_ships[i]] > 0) && (ship_raids_used(_ships[i]) < SHIP_ASSAULTS_PER_TURN)) { return true; } } @@ -733,26 +768,24 @@ function can_ground_deploy(star_object, planet_number) { return false; } -/// @desc First ship at this star that has spent no support use this turn, or -1. -/// Orbital bombardment is one per ship per turn and consumes the ship's whole support -/// allowance for the turn, so it needs a completely fresh ship. +/// @desc First ship at this star that has not yet bombarded this turn, or -1. Bombardment +/// is one per ship per turn on its own counter, independent of ground support. function get_fresh_bombard_ship(location) { var _ships = get_player_ships(location); for (var i = 0; i < array_length(_ships); i++) { - if (ship_assaults_used(_ships[i]) == 0) { + if (ship_bombards_used(_ships[i]) == 0) { return _ships[i]; } } return -1; } -/// @desc Spend a ship's entire support allowance on an orbital bombardment (one per -/// ship per turn, mutually exclusive with that ship's ground support for the turn). +/// @desc Spend a ship's one bombardment use for the turn, on its own counter. This is +/// independent of the ship's ground assault and raid support, so a ship can bombard and +/// still land troops (attack or raid) the same turn. function ship_bombard_spend(ship_index) { if (ship_index < 0) { return; } - repeat (SHIP_ASSAULTS_PER_TURN) { - ship_assault_spend(ship_index); - } + ship_action_spend(ship_index, "bombard"); } diff --git a/scripts/scr_roster/scr_roster.gml b/scripts/scr_roster/scr_roster.gml index 7f69ff2e0d..e5a8c194ac 100644 --- a/scripts/scr_roster/scr_roster.gml +++ b/scripts/scr_roster/scr_roster.gml @@ -374,13 +374,17 @@ function Roster() constructor { // and update_roster only admits units whose ship toggle is active. // Applies to attacks only; raids and purges do not spend uses. if (instance_exists(obj_drop_select)) { - if (obj_drop_select.attack && (ship_assaults_used(_ship_index) >= SHIP_ASSAULTS_PER_TURN)) { + // Attack rosters gate on the ship's assault counter, raid rosters on + // its raid counter (each independent), so a ship spent on one action + // still shows available for the other. + var _dr_used = obj_drop_select.attack ? ship_assaults_used(_ship_index) : ship_raids_used(_ship_index); + if (_dr_used >= SHIP_ASSAULTS_PER_TURN) { var _spent_btn = ships[array_length(ships) - 1]; _spent_btn.assault_locked = true; _spent_btn.active = false; _spent_btn.text_color = c_red; _spent_btn.button_color = c_red; - _spent_btn.tooltip = "This ship has already supported the maximum number of ground assaults this turn."; + _spent_btn.tooltip = obj_drop_select.attack ? "This ship has already supported the maximum number of ground assaults this turn." : "This ship has already supported the maximum number of raids this turn."; } } } From 1896fcf14074f2a296d5fd96fa8c4bf1dd0a5c66 Mon Sep 17 00:00:00 2001 From: KestasV <37342061+KestasV@users.noreply.github.com> Date: Wed, 8 Jul 2026 06:32:42 +0300 Subject: [PATCH 136/140] Update README with new release link Added a link to the new release for Chapter Master 1.5. --- docs/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/README.md b/docs/README.md index 1eb43efc59..b0629c01f8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,6 +2,8 @@ Chapter Master - Adeptus Dominus Logo

+**NEW RELEASE HERE** https://github.com/KestasV/Chapter-Master-1.5-Adeptus-Indomitus/releases/tag/Exe1.1 + # Chapter Master 1.5 – Adeptus Indomitus **Chapter Master 1.5 – Adeptus Indomitus** is a major continuation fork of *Chapter Master: Adeptus Dominus*, expanding the game from a pure Space Marine Chapter command simulator into a broader Imperial war effort. From ba97738b0a88409adfa9c69be79dabcd67634b36 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 8 Jul 2026 12:58:36 +0300 Subject: [PATCH 137/140] Fix crash moving a marine in a company over 500 (pad parallel arrays 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. --- .../scr_move_unit_info/scr_move_unit_info.gml | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/scripts/scr_move_unit_info/scr_move_unit_info.gml b/scripts/scr_move_unit_info/scr_move_unit_info.gml index ee8a427ea5..6d43aeb433 100644 --- a/scripts/scr_move_unit_info/scr_move_unit_info.gml +++ b/scripts/scr_move_unit_info/scr_move_unit_info.gml @@ -1,6 +1,58 @@ +/// @desc Ensure every parallel per-company marine array (and TTRPG) for this company is +/// long enough to index this slot, appending the blank defaults find_company_open_slot +/// uses. Companies are uncapped, so a marine can occupy a slot beyond the legacy 501-length +/// arrays (for example a save where name[] grew past the flat arrays). Padding each array +/// independently up to the slot keeps them in sync so reads and writes at that slot never +/// go out of range. Each array is padded on its own length, so an array that already +/// reaches the slot is left untouched while a shorter sibling is caught up. +function ensure_marine_slot(_company, _slot) { + while (array_length(obj_ini.race[_company]) <= _slot) { + array_push(obj_ini.race[_company], 1); + } + while (array_length(obj_ini.name[_company]) <= _slot) { + array_push(obj_ini.name[_company], ""); + } + while (array_length(obj_ini.role[_company]) <= _slot) { + array_push(obj_ini.role[_company], ""); + } + while (array_length(obj_ini.wep1[_company]) <= _slot) { + array_push(obj_ini.wep1[_company], ""); + } + while (array_length(obj_ini.spe[_company]) <= _slot) { + array_push(obj_ini.spe[_company], ""); + } + while (array_length(obj_ini.wep2[_company]) <= _slot) { + array_push(obj_ini.wep2[_company], ""); + } + while (array_length(obj_ini.armour[_company]) <= _slot) { + array_push(obj_ini.armour[_company], ""); + } + while (array_length(obj_ini.gear[_company]) <= _slot) { + array_push(obj_ini.gear[_company], ""); + } + while (array_length(obj_ini.mobi[_company]) <= _slot) { + array_push(obj_ini.mobi[_company], ""); + } + while (array_length(obj_ini.age[_company]) <= _slot) { + array_push(obj_ini.age[_company], 0); + } + while (array_length(obj_ini.god[_company]) <= _slot) { + array_push(obj_ini.god[_company], 0); + } + while (array_length(obj_ini.TTRPG[_company]) <= _slot) { + array_push(obj_ini.TTRPG[_company], new TTRPG_stats("chapter", _company, array_length(obj_ini.TTRPG[_company]), "blank")); + } +} + function scr_move_unit_info(start_company, end_company, start_slot, end_slot, eval_squad = true) { //eval_squad : determine whether movement of units between companies should decide to check their squad coherency or not, defaults to true + // Companies are uncapped, so either slot can sit beyond the legacy 501-length parallel + // arrays. Pad every array for both companies up to the slots in use so the copies below + // never read or write out of range (the crash when a company exceeded 500 marines). + ensure_marine_slot(start_company, start_slot); + ensure_marine_slot(end_company, end_slot); + //this makes sure coherency of the unit's squad and the squads logging of the unit location are kept up to date var unit = obj_ini.TTRPG[start_company][start_slot]; if (eval_squad) { From d36ae3e11d9dd5eb67621275a5db7b7ec1a0e6e2 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 8 Jul 2026 13:33:25 +0300 Subject: [PATCH 138/140] Add spawnmarines cheat: drop N marines straight into a company for roster 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. --- scripts/scr_cheatcode/scr_cheatcode.gml | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/scripts/scr_cheatcode/scr_cheatcode.gml b/scripts/scr_cheatcode/scr_cheatcode.gml index 04e4847d81..a198d084da 100644 --- a/scripts/scr_cheatcode/scr_cheatcode.gml +++ b/scripts/scr_cheatcode/scr_cheatcode.gml @@ -399,8 +399,28 @@ function scr_cheatcode(argument0) { array_insert(obj_controller.recruit_exp, i, 20); array_insert(obj_controller.recruit_data, i, {}); array_insert(obj_controller.recruit_name, i, global.name_generator.GenerateFromSet("space_marine")); - scr_alert("green", "recruitment", (string(obj_controller.recruit_name[i]) + "has started training."), 0, 0); } + // One summary alert instead of one per recruit. Firing hundreds of + // alerts in a single frame (recruit 500) floods the notification + // system and hangs the game. + scr_alert("green", "recruitment", (string(real(cheat_arguments[0])) + " recruits have started training."), 0, 0); + break; + case "spawnmarines": + // Spawn N fully-formed marines straight into a company (1st by + // default), bypassing the training queue, for testing large rosters. + // Usage: "spawnmarines" (500 into company 1), "spawnmarines 800", or + // "spawnmarines 500 3" for company 3. Uses the same default recruit + // role the game grants on recruitment completion, and posts one + // summary alert rather than one per marine, so a big count does not + // flood the notification system the way the old recruit loop did. + var _spawn_count = (array_length(cheat_arguments) > 0) ? real(cheat_arguments[0]) : 500; + var _spawn_company = (array_length(cheat_arguments) > 1) ? real(cheat_arguments[1]) : 1; + with (obj_controller) { + repeat (_spawn_count) { + scr_add_man(obj_ini.role[100][12], _spawn_company, 20, global.name_generator.GenerateFromSet("space_marine"), 0, false, "default", {}); + } + } + scr_alert("green", "recruitment", (string(_spawn_count) + " marines spawned in company " + string(_spawn_company) + "."), 0, 0); break; case "shiplostevent": loose_ship_to_warp_event(); From 0831f4022783da98c1dd25f03e252f7a61c6027a Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 8 Jul 2026 19:21:03 +0300 Subject: [PATCH 139/140] Fix squad deletion on marine transfer (re-find open slot instead of blind 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. --- scripts/scr_transfer_marines/scr_transfer_marines.gml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/scr_transfer_marines/scr_transfer_marines.gml b/scripts/scr_transfer_marines/scr_transfer_marines.gml index a964c2b6e7..3426337fae 100644 --- a/scripts/scr_transfer_marines/scr_transfer_marines.gml +++ b/scripts/scr_transfer_marines/scr_transfer_marines.gml @@ -68,7 +68,11 @@ function transfer_marines() { _unit.squad = move_squad; squad.members[mem][0] = target_comp; squad.members[mem][1] = mahreens; - mahreens++; + // Re-find a genuinely empty slot for the next member rather + // than blindly incrementing: incrementing can walk into an + // occupied slot (a gap before the command squad) and overwrite + // and wipe that marine, which was deleting squads on transfer. + mahreens = find_company_open_slot(target_comp); } squad.base_company = target_comp; } @@ -78,7 +82,10 @@ function transfer_marines() { //move individual if (!moveable) { scr_move_unit_info(unit.company, target_comp, unit.marine_number, mahreens, true); - mahreens++; + // Re-find the next empty slot rather than incrementing, so a marine is + // never placed onto an occupied slot (which overwrites and wipes the + // marine already there). + mahreens = find_company_open_slot(target_comp); } var check = 0; } else if (obj_controller.man[w] == "vehicle" && is_array(obj_controller.display_unit[w])) { From cec693607e5e80e368ff08404b0c826f456f6d80 Mon Sep 17 00:00:00 2001 From: KestasV Date: Wed, 8 Jul 2026 19:32:45 +0300 Subject: [PATCH 140/140] Mass-equip now includes squad Sergeants, not just their battle brothers 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. --- objects/obj_mass_equip/Create_0.gml | 67 ++++++++++++++++++++++++ objects/obj_mass_equip/Step_0.gml | 81 +++++++---------------------- 2 files changed, 86 insertions(+), 62 deletions(-) diff --git a/objects/obj_mass_equip/Create_0.gml b/objects/obj_mass_equip/Create_0.gml index dd866bb41f..a3aeb06fa3 100644 --- a/objects/obj_mass_equip/Create_0.gml +++ b/objects/obj_mass_equip/Create_0.gml @@ -65,3 +65,70 @@ can_assign_weapon = function(unit, weapon_name) { return true; } }; + +/// @desc Apply the current mass-equip requirement (req_armour/wep1/wep2/gear/mobi) to one +/// unit. Factored out of the engage loop so both a matched marine and its squad's Sergeant +/// can be equipped by the same code. Artifact/non-standard weapons are left alone (the +/// is_string / can_assign_weapon guards), so a Sergeant keeps a special weapon he can't +/// swap while still receiving the same armour and standard kit as his squad. +apply_gear = function(_unit) { + var _list_basic_armour = global.list_basic_power_armour; + var _list_term_armour = global.list_terminator_armour; + + // ** Armour ** + var unit_armour = _unit.get_armour_data(); + var has_valid_armour = is_struct(unit_armour); + if (has_valid_armour) { + switch (req_armour) { + case STR_ANY_POWER_ARMOUR: + has_valid_armour = array_contains(_list_basic_armour, unit_armour.name); + break; + case STR_ANY_TERMINATOR_ARMOUR: + has_valid_armour = array_contains(_list_term_armour, unit_armour.name); + break; + default: + has_valid_armour = req_armour == unit_armour.name; + } + } + if (!has_valid_armour) { + var result = _unit.update_armour(req_armour); + if (result != "complete" && req_armour == STR_ANY_POWER_ARMOUR) { + _unit.update_armour(STR_ANY_TERMINATOR_ARMOUR); + } + unit_armour = _unit.get_armour_data(); + } + + // ** Weapons ** + if (_unit.weapon_one() != req_wep1) { + if (is_string(_unit.weapon_one(true))) { + if (can_assign_weapon(_unit, req_wep1)) { + _unit.update_weapon_one(req_wep1); + } + } + } + if (_unit.weapon_two() != req_wep2) { + if (is_string(_unit.weapon_two(true))) { + if (can_assign_weapon(_unit, req_wep2)) { + _unit.update_weapon_two(req_wep2); + } + } + } + + // ** Gear ** + if (is_string(_unit.gear(true))) { + _unit.update_gear(req_gear); + } + + // ** Mobility ** + if (_unit.mobility_item() != req_mobi) { + var _forbidden_tags = [ + "terminator", + "dreadnought" + ]; + if (is_struct(unit_armour) && unit_armour.has_tags(_forbidden_tags)) { + _unit.update_mobility_item(""); + } else { + _unit.update_mobility_item(req_mobi); + } + } +}; diff --git a/objects/obj_mass_equip/Step_0.gml b/objects/obj_mass_equip/Step_0.gml index 91d9004340..2820d5be65 100644 --- a/objects/obj_mass_equip/Step_0.gml +++ b/objects/obj_mass_equip/Step_0.gml @@ -7,82 +7,39 @@ try { var _list_term_armour = global.list_terminator_armour; if (engage == true) { + var _done_squad_sergeants = {}; for (var co = 0; co <= obj_ini.companies; co++) { if (role_number[co] > 0) { for (var i = 0; i < array_length(obj_ini.role[co]); i++) { if (obj_ini.role[co][i] == obj_ini.role[100][role]) { var _unit = fetch_unit([co, i]); + var _squad = undefined; if (_unit.squad != "none") { - var _squad = fetch_squad(_unit.squad); + _squad = fetch_squad(_unit.squad); if (!_squad.allow_bulk_swap) { continue; } } - // ** Start Armour ** - var unit_armour = _unit.get_armour_data(); - var has_valid_armour = is_struct(unit_armour); - - // Check if unit_armour is a struct and evaluate tag-based or name-based compatibility - if (has_valid_armour) { - switch (req_armour) { - case STR_ANY_POWER_ARMOUR: - has_valid_armour = array_contains(_list_basic_armour, unit_armour.name); - break; - case STR_ANY_TERMINATOR_ARMOUR: - has_valid_armour = array_contains(_list_term_armour, unit_armour.name); - break; - default: - has_valid_armour = req_armour == unit_armour.name; - } - } - - // Attempt to equip if not valid - if (!has_valid_armour) { - var result = _unit.update_armour(req_armour); - - // Fallback: If request was for Power Armour but update failed, try Terminator - if (result != "complete" && req_armour == STR_ANY_POWER_ARMOUR) { - _unit.update_armour(STR_ANY_TERMINATOR_ARMOUR); - } - - // Refresh unit_armour after update - unit_armour = _unit.get_armour_data(); - } - // ** End Armour ** - - // ** Start Weapons ** - if (_unit.weapon_one() != req_wep1) { - if (is_string(_unit.weapon_one(true))) { - if (can_assign_weapon(_unit, req_wep1)) { - _unit.update_weapon_one(req_wep1); - } - } - } - if (_unit.weapon_two() != req_wep2) { - if (is_string(_unit.weapon_two(true))) { - if (can_assign_weapon(_unit, req_wep2)) { - _unit.update_weapon_two(req_wep2); + apply_gear(_unit); + + // Equip this squad's Sergeant with the same kit, once per squad. + // The Sergeant (role slot 18) or Veteran Sergeant (19) carries a + // different role than the base role this loop keys on, so leaders + // were being skipped: their battle brothers got the mass equip and + // they did not. Only runs for bulk-swappable squads, same as above. + if (is_struct(_squad) && !variable_struct_exists(_done_squad_sergeants, _unit.squad)) { + _done_squad_sergeants[$ _unit.squad] = true; + var _sgt_role = obj_ini.role[100][18]; + var _vet_sgt_role = obj_ini.role[100][19]; + var _members = _squad.members; + for (var _m = 0; _m < array_length(_members); _m++) { + var _member = fetch_unit(_members[_m]); + if (is_struct(_member) && ((_member.role() == _sgt_role) || (_member.role() == _vet_sgt_role))) { + apply_gear(_member); } } } - // ** Start Gear ** - if (is_string(_unit.gear(true))) { - _unit.update_gear(req_gear); - } - - // ** Start Mobility Items ** - if (_unit.mobility_item() != req_mobi) { - var _forbidden_tags = [ - "terminator", - "dreadnought" - ]; - if (is_struct(unit_armour) && unit_armour.has_tags(_forbidden_tags)) { - _unit.update_mobility_item(""); - } else { - _unit.update_mobility_item(req_mobi); - } - } // ** End role check ** } // ** End this marine **