diff --git a/objects/obj_controller/Create_0.gml b/objects/obj_controller/Create_0.gml index f19aef502..91bb5c77b 100644 --- a/objects/obj_controller/Create_0.gml +++ b/objects/obj_controller/Create_0.gml @@ -536,6 +536,7 @@ forge_points = 0; master_craft_chance = 0; tech_status = "cult_mechanicus"; forge_string = ""; +apothecary_string = ""; player_forge_data = { player_forges: 0, vehicle_hanger: [], diff --git a/objects/obj_controller/Draw_64.gml b/objects/obj_controller/Draw_64.gml index a5f55f558..5983c3cbc 100644 --- a/objects/obj_controller/Draw_64.gml +++ b/objects/obj_controller/Draw_64.gml @@ -209,9 +209,9 @@ if (!zoomed && !zui) { draw_text(180, 16, string(forge_points)); draw_text(180.5, 16.5, string(forge_points)); // Draws apothecary points - var _apoth_string = $"apothecary points : {specialist_point_handler.apothecary_points}"; - draw_text(180, 32, _apoth_string); - draw_text(180.5, 32.5, _apoth_string); + // var _apoth_string = $"apothecary points : {specialist_point_handler.apothecary_points}"; + // draw_text(180, 32, _apoth_string); + // draw_text(180.5, 32.5, _apoth_string); // Draws the current loyalty draw_sprite(spr_new_resource, 1, 267, 17); draw_set_color(1164001); diff --git a/scripts/scr_apothecary_ground/scr_apothecary_ground.gml b/scripts/scr_apothecary_ground/scr_apothecary_ground.gml index 97bcb402f..845c0c921 100644 --- a/scripts/scr_apothecary_ground/scr_apothecary_ground.gml +++ b/scripts/scr_apothecary_ground/scr_apothecary_ground.gml @@ -1,3 +1,12 @@ +#macro PLANET_SLOT_COUNT 5 +#macro STAR_INSTANCE_INDEX 5 +#macro VEHICLE_MAINTENANCE_SMALL 0.2 +#macro VEHICLE_MAINTENANCE_BIG 1 +#macro VEHICLE_REPAIR_SMALL 0.2 +#macro VEHICLE_REPAIR_BIG 3 +#macro VEHICLE_REPAIR_LIMIT 10 +#macro UNIT_HEAL_SMALL 1 + enum eSYSTEM_LOC { ORBIT, PLANET1, @@ -6,6 +15,7 @@ enum eSYSTEM_LOC { PLANET4, } +/// @mixin function calculate_full_chapter_spread() { obj_controller.command = 0; obj_controller.marines = 0; @@ -31,7 +41,7 @@ function calculate_full_chapter_spread() { obj_controller.marines++; } } - tech_points_used += _unit.equipment_maintenance_burden(); + forge_equipment_maintenance += _unit.equipment_maintenance_burden(); _is_tech = _unit.IsSpecialist(SPECIALISTS_TECHS); if (_is_tech) { add_forge_points_to_stack(_unit); @@ -162,165 +172,187 @@ function system_point_data_spawn() { return [variable_clone(_single_point_pos), variable_clone(_single_point_pos), variable_clone(_single_point_pos), variable_clone(_single_point_pos), variable_clone(_single_point_pos)]; } -function apothecary_simple() { - var _unit; +/// @mixin +function process_specialist_points() { var _spreads = chapter_spread(); var _tech_spread = _spreads[0]; var _apoth_spread = _spreads[1]; var _unit_spread = _spreads[2]; - forge_string += $"Equipment Maintenance : -{tech_points_used}#"; - //marines-=1; var _locations = struct_get_names(_unit_spread); - var cur_apoths; + var _loc_count = array_length(_locations); + + // --- Step 1: Map Stars to Locations --- + var _gene_seed_empty = obj_controller.gene_seed <= 0 && obj_controller.recruiting > 0; with (obj_star) { - var marines_present = false; - for (var i = 0; i < array_length(_locations); i++) { - if (_locations[i] == name) { - array_push(_unit_spread[$ _locations[i]], self); - marines_present = true; - } + var _in_spread = variable_struct_exists(_unit_spread, name); + + if (_gene_seed_empty && system_feature_bool(self.p_feature, eP_FEATURES.RECRUITING_WORLD)) { + obj_controller.recruiting = 0; + scr_alert("red", "recruiting", "The Chapter has run out of gene-seed!", 0, 0); + _gene_seed_empty = false; } - if (!marines_present) { - if ((obj_controller.gene_seed == 0) && (obj_controller.recruiting > 0)) { - var _training_ground = system_feature_bool(self.p_feature, eP_FEATURES.RECRUITING_WORLD); - if (_training_ground) { - obj_controller.recruiting = 0; - scr_alert("red", "recruiting", "The Chapter has run out of gene-seed!", 0, 0); - } - } + + if (!_in_spread) { + continue; } + + array_push(_unit_spread[$ name], self); } - var cur_units, cur_techs, _loc_heal_points, veh_health, points_spent, cur_system, features; - var total_bionics = scr_item_count("Bionics"); - for (i = 0; i < array_length(_locations); i++) { + // --- Step 2: Process Locations --- + for (var i = 0; i < _loc_count; i++) { var _cur_loc = _locations[i]; - cur_system = ""; - if (array_length(_unit_spread[$ _cur_loc]) == 6) { - cur_system = _unit_spread[$ _cur_loc][5]; - } - if (cur_system != "") { - point_breakdown.systems[$ cur_system.name] = system_point_data_spawn(); - } - - var _loc_forge_points = 0; - var _point_breakdown = {}; - for (var p = 0; p < 5; p++) { - _point_breakdown = { - heal_points: 0, - forge_points: 0, - heal_points_use: 0, - forge_points_use: 0, - }; + var _loc_slots = _unit_spread[$ _cur_loc]; + var _star_inst = (array_length(_loc_slots) > STAR_INSTANCE_INDEX) ? _loc_slots[STAR_INSTANCE_INDEX] : pointer_null; - _loc_heal_points = 0; - _loc_forge_points = 0; + if (_star_inst != pointer_null) { + point_breakdown.systems[$ _star_inst.name] = system_point_data_spawn(); + } - if (array_length(_unit_spread[$ _cur_loc][p]) == 0) { + 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; } - cur_units = _unit_spread[$ _cur_loc][p]; - cur_apoths = _apoth_spread[$ _cur_loc][p]; - cur_techs = _tech_spread[$ _cur_loc][p]; - for (var a = 0; a < array_length(cur_apoths); a++) { - _unit = cur_apoths[a]; - _loc_heal_points += _unit.apothecary_point_generation(turn_end)[0]; + + 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 a = 0; a < array_length(cur_techs); a++) { - _unit = cur_techs[a]; - var tech_gen = _unit.forge_point_generation(turn_end)[0]; - _loc_forge_points += tech_gen; + for (var t = 0, _tl = array_length(_cur_techs); t < _tl; t++) { + _pool.forge += _cur_techs[t].forge_point_generation(turn_end)[0]; } - _point_breakdown.heal_points = _loc_heal_points; - _point_breakdown.forge_points = _loc_forge_points; - for (var a = 0; a < array_length(cur_units); a++) { - points_spent = 0; - _unit = cur_units[a]; - if (is_array(_unit) && _loc_forge_points > 0) { - if (array_length(_unit) > 1) { - var _role = obj_ini.veh_role[_unit[0]][_unit[1]]; - if (_role == "Land Raider") { - forge_veh_maintenance.land_raider = struct_exists(forge_veh_maintenance, "land_raider") ? forge_veh_maintenance.land_raider + 1 : 1; - _loc_forge_points--; - tech_points_used++; - } else if (array_contains(["Rhino", "Predator", "Whirlwind"], _role)) { - forge_veh_maintenance.small_vehicles = struct_exists(forge_veh_maintenance, "small_vehicles") ? forge_veh_maintenance.small_vehicles + 0.2 : 0.2; - _loc_forge_points -= 0.2; - tech_points_used += 0.2; - } - while (points_spent < 10 && obj_ini.veh_hp[_unit[0]][_unit[1]] < 100 && _loc_forge_points > 0) { - points_spent++; - if (turn_end) { - obj_ini.veh_hp[_unit[0]][_unit[1]]++; - } - forge_veh_maintenance.repairs++; - _loc_forge_points--; - tech_points_used++; - } - } + + 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)) { - _loc_forge_points -= _unit.equipment_maintenance_burden(); - if (_unit.hp() < _unit.max_health()) { - if (!_unit.is_dreadnought()) { - if (_unit.hp() > 0) { - if (_loc_heal_points > 0) { - if (turn_end) { - _unit.healing(true); - } - _loc_heal_points--; - apothecary_points_used--; - } else { - if (turn_end) { - _unit.healing(false); - } - } - } else if (_loc_heal_points > 0 && _loc_forge_points >= 3 && _unit.bionics < 10) { - _unit.add_bionics(); - _loc_heal_points--; - apothecary_points_used--; - tech_points_used++; - _loc_forge_points--; - } - } else { - if (_loc_heal_points > 0 && _loc_forge_points >= 3 && _unit.hp() > 0) { - if (turn_end) { - _unit.healing(true); - } - _loc_heal_points--; - apothecary_points_used--; - tech_points_used += 3; - _loc_forge_points -= 3; - } - } - } + _process_marine_maintenance(_unit, _pool); } } - _point_breakdown.heal_points_use = _point_breakdown.heal_points - _loc_heal_points; - _point_breakdown.forge_points_use = _point_breakdown.forge_points - _loc_forge_points; - if (cur_system != "") { - point_breakdown.systems[$ cur_system.name][p] = variable_clone(_point_breakdown); - } else if (p == 0 && string_count("ref instance", _cur_loc)) { - try { - var _instance_int = real(string_replace(_cur_loc, "ref instance ", "")); - if (instance_exists(_instance_int)) { - var _instance = _instance_int; - _instance.point_breakdown = variable_clone(_point_breakdown); - } - } catch (_exception) { - handle_exception(_exception); + + // 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 = new PlanetData(_p, _star_inst); + _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); } - if (cur_system != "" && p > 0 && turn_end) { - with (cur_system) { - if (array_length(p_feature[p]) != 0) { - var _planet_data = new PlanetData(p, self); - _planet_data.recover_starship(cur_techs); - if (_planet_data.planet_training(_loc_heal_points)) {} - } + } + } + + /// @param {Array} _unit + /// @param {Struct} _pool + static _process_vehicle_maintenance = function(_unit, _pool) { + if (_pool.forge <= 0) { + return; + } + + var _co = _unit[0]; + var _idx = _unit[1]; + var _role = obj_ini.veh_role[_co][_idx]; + + if (_role == "Land Raider") { + forge_veh_maintenance.land_raider = (forge_veh_maintenance[$ "land_raider"] ?? 0) + VEHICLE_MAINTENANCE_BIG; + _pool.forge -= VEHICLE_MAINTENANCE_BIG; + } else if (array_contains(["Rhino", "Predator", "Whirlwind"], _role)) { + forge_veh_maintenance.small_vehicles = (forge_veh_maintenance[$ "small_vehicles"] ?? 0) + VEHICLE_MAINTENANCE_SMALL; + _pool.forge -= VEHICLE_MAINTENANCE_SMALL; + } + + var _repairs_done = 0; + var _simulated_hp = obj_ini.veh_hp[_co][_idx]; + while (_repairs_done < VEHICLE_REPAIR_LIMIT && _simulated_hp < 100 && _pool.forge >= VEHICLE_REPAIR_SMALL) { + if (turn_end) { + LOGGER.debug(_pool.forge); + obj_ini.veh_hp[_co][_idx]++; + } + _simulated_hp++; + + forge_veh_maintenance.repairs += VEHICLE_REPAIR_SMALL; + _pool.forge -= VEHICLE_REPAIR_SMALL; + _repairs_done++; + } + }; + + /// @param {Struct.TTRPG_stats} _unit + /// @param {Struct} _pool + static _process_marine_maintenance = function(_unit, _pool) { + // Equipment burden is always deducted if possible + var _burden = _unit.equipment_maintenance_burden(); + _pool.forge -= _burden; + + if (_unit.hp() >= _unit.max_health()) { + return; + } + + if (!_unit.is_dreadnought()) { + if (_unit.hp() > 0) { + var _can_heal = _pool.heal >= UNIT_HEAL_SMALL; + if (turn_end) { + _unit.healing(_can_heal); + } + + if (_can_heal) { + _pool.heal -= UNIT_HEAL_SMALL; + apothecary_points_used += UNIT_HEAL_SMALL; } + } else if (turn_end) { + var _application_success = true; + while (_application_success && _unit.hp() <= 0 && _unit.bionics < 10) { + _application_success = _unit.add_bionics(); + } + } + } else if (_pool.heal >= UNIT_HEAL_SMALL && _pool.forge >= VEHICLE_REPAIR_BIG && _unit.hp() > 0) { + // Dreadnoughts require both specialists + if (turn_end) { + _unit.healing(true); } + + _pool.heal -= UNIT_HEAL_SMALL; + _pool.forge -= VEHICLE_REPAIR_BIG; + apothecary_points_used += UNIT_HEAL_SMALL; + forge_veh_maintenance.repairs += VEHICLE_REPAIR_BIG; } - } + }; + + static _handle_instance_point_recording = function(_loc_str, _stats) { + try { + var _inst_id = real(string_digits(_loc_str)); + if (instance_exists(_inst_id)) { + _inst_id.point_breakdown = _stats; + } + } catch (_ex) { + LOGGER.error($"Failed to parse instance ID from location string: {_loc_str} | Error: {_ex.message}"); + } + }; } 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 d29adc46f..3daf4aaed 100644 --- a/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml +++ b/scripts/scr_specialist_point_handler/scr_specialist_point_handler.gml @@ -1,19 +1,13 @@ function SpecialistPointHandler() constructor { static chapter_spread = calculate_full_chapter_spread; - static healing_and_point_use = apothecary_simple; forge_queue = []; techs = []; apoths = []; forge_master = -1; master_craft_chance = 0; - - forge_reasons = {}; - - forge_string = ""; at_forge = 0; apothecary_points = 0; armoury_repairs = {}; - apothecary_string = ""; apothecary_training_points = 0; forge_points = 0; point_breakdown = {}; @@ -34,84 +28,105 @@ function SpecialistPointHandler() constructor { static pre_error_wrapped_research_points = function() { research_points = 0; forge_points = 0; - master_craft_chance = 0; + master_craft_chance = (obj_controller.tech_status == "heretics") ? 5 : 0; - apoth_points_used = 0; apothecary_points = 0; - apothecary_training_points = 0; apothecary_points_used = 0; - tech_points_used = 0; + + forge_equipment_maintenance = 0; crafters = 0; at_forge = 0; - if (obj_controller.tech_status == "heretics") { - master_craft_chance += 5; - } - apoths = []; - techs = []; heretics = []; - delete point_breakdown; + point_breakdown = { fleets: {}, systems: {}, }; - forge_string = $"Forge Production Rate#"; forge_master = -1; forge_veh_maintenance = { repairs: 0, }; - healing_and_point_use(); - var at_forge = 0; - tech_locations = []; - var _cur_tech; + process_specialist_points(); + total_techs = array_length(techs); - for (var i = 0; i < array_length(techs); i++) { + tech_locations = array_create(total_techs); + for (var i = 0; i < total_techs; i++) { tech_locations[i] = techs[i].marine_location(); } - if (forge_master > -1) { + + if (forge_master > -1 && forge_master < total_techs) { obj_controller.master_of_forge = techs[forge_master]; } - apothecary_string = "Apothecaries : +{apothecaries}"; - apothecary_string = "Apothecary Healing : {apothecary_points_used}"; + + var apothecary_string = "AP Production#"; + apothecary_string += $"Apothecaries: {apothecary_points}#"; + + apothecary_string += "#AP Consumption#"; + apothecary_string += $"Healing: {apothecary_points_used}#"; apothecary_points -= apothecary_points_used; - apothecary_string = "Recruit screening : -{apothecary_training_points}"; + apothecary_string += $"Recruit Screening: {apothecary_training_points}#"; apothecary_points -= apothecary_training_points; - //TODO extract to the apothecary simple script - forge_string += $"Techmarines: +{floor(forge_points)}#"; - forge_points -= tech_points_used; - forge_string += $"Vehicle Repairs:#"; - forge_string += $" Combat Repairs : {forge_veh_maintenance.repairs}#"; - if (struct_exists(forge_veh_maintenance, "land_raider")) { - forge_string += $" Land Raider Maintenance: -{forge_veh_maintenance.land_raider}#"; - forge_points -= forge_veh_maintenance.land_raider; - } - if (struct_exists(forge_veh_maintenance, "small_vehicles")) { - if (floor(forge_veh_maintenance.small_vehicles) > 0) { - forge_string += $" Small Vehicle Maintenance: -{floor(forge_veh_maintenance.small_vehicles)}#"; - forge_points -= floor(forge_veh_maintenance.small_vehicles); - } - } + + apothecary_string += $"#Total AP: {apothecary_points}"; + + var forge_string = "FP Production#"; + forge_string += $"Techmarines: {floor(forge_points)}#"; + var _forge_data = obj_controller.player_forge_data; if (_forge_data.player_forges > 0) { - forge_points += 5 * _forge_data.player_forges; - forge_string += $"Forges: +{5 * _forge_data.player_forges}#"; + var _forge_gain = 5 * _forge_data.player_forges; + forge_points += _forge_gain; + forge_string += $"Forges: {_forge_gain}#"; } - var _armoury_maintenance_names = struct_get_names(armoury_repairs); - var _name_length = array_length(_armoury_maintenance_names); - for (var i = 0; i < _name_length; i++) { - var _maintain_item = _armoury_maintenance_names[i]; - forge_points -= gear_weapon_data("any", _maintain_item, "maintenance") * armoury_repairs[$ _maintain_item]; + forge_string += "#FP Consumption#"; + forge_points -= forge_equipment_maintenance; + forge_string += $"Equipment Maintenance: {forge_equipment_maintenance}#"; + + var _armoury_names = struct_get_names(armoury_repairs); + for (var i = 0, _count = array_length(_armoury_names); i < _count; i++) { + var _item = _armoury_names[i]; + var _repair_cost = gear_weapon_data("any", _item, "maintenance") * armoury_repairs[$ _item]; + forge_points -= _repair_cost; + forge_string += $"Equipment Repairs ({_item}): {_repair_cost}#"; + } + + var _v_maintenance = [ + { + key: "land_raider", + label: "Land Raider", + }, + { + key: "small_vehicles", + label: "Small Vehicle", + } + ]; + + for (var i = 0; i < array_length(_v_maintenance); i++) { + var _item = _v_maintenance[i]; + var _maint = forge_veh_maintenance[$ _item.key] ?? 0; + if (_maint > 0) { + forge_string += $"{_item.label} Maintenance: {_maint}#"; + forge_points -= _maint; + } } + + if (forge_veh_maintenance.repairs > 0) { + forge_string += $"Vehicle Repairs: {forge_veh_maintenance.repairs}#"; + } + + forge_string += $"#Total FP: {forge_points}"; + forge_points = floor(forge_points); - //in this instance tech are techmarines with the "tech_heretic" trait + if (turn_end) { - if (array_length(techs) == 0) { + if (total_techs == 0) { scr_loyalty("Upset Machine Spirits", "+"); } @@ -119,24 +134,25 @@ function SpecialistPointHandler() constructor { new_tech_heretic_spawn(); if (forge_master == -1) { - var tech_count = scr_role_count(obj_ini.role[100][16]); - if (tech_count > 1) { + var _tech_units = scr_role_count(obj_ini.role[100][16], "", "units"); + var _count = array_length(_tech_units); + if (_count > 1) { setup_new_forge_master_popup(techs); - } else if (tech_count == 1) { - scr_role_count(obj_ini.role[100][16], "", "units")[0].update_role("Forge Master"); + } else if (_count == 1) { + _tech_units[0].update_role("Forge Master"); } } - forge_queue_logic(); + forge_queue_logic(); gene_slave_logic(); + armoury_repairs = {}; } + obj_controller.research_points = research_points; obj_controller.forge_points = forge_points; obj_controller.master_craft_chance = master_craft_chance; obj_controller.forge_string = forge_string; - if (turn_end) { - armoury_repairs = {}; - } + obj_controller.apothecary_string = apothecary_string; }; static calculate_research_points = function(turn_end) { @@ -287,7 +303,7 @@ 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 }*/ } if (array_length(techs) > array_length(heretics) && !_heritecs) { diff --git a/scripts/scr_ui_popup/scr_ui_popup.gml b/scripts/scr_ui_popup/scr_ui_popup.gml index 52b58ee4c..605b6580d 100644 --- a/scripts/scr_ui_popup/scr_ui_popup.gml +++ b/scripts/scr_ui_popup/scr_ui_popup.gml @@ -763,7 +763,7 @@ function scr_ui_popup() { // Stored Gene-Seed tooltip if (scr_hit(xx + 373, yy + 10, xx + 443, yy + 38)) { var tx = 0, ty = 0, tool1 = "", tool2 = "", plu = ""; - tool1 = "Gene-Seed"; + tool1 = "Gene-Seed##" + obj_controller.apothecary_string; if (tool1 != "") { tooltip_draw(tool1); }