diff --git a/objects/obj_controller/Create_0.gml b/objects/obj_controller/Create_0.gml index a045313fbb..b77af755f8 100644 --- a/objects/obj_controller/Create_0.gml +++ b/objects/obj_controller/Create_0.gml @@ -1695,7 +1695,7 @@ temp[60] = $"{temp[59]}\n\n{temp[34]}\n\n{temp[35]}##{temp[36]}##{temp[37]}##{te temp[61]="\n\nYour armamentarium contains some spare equipment- \n"; -temp[61] += arrays_to_string_with_counts(obj_ini.equipment, obj_ini.equipment_number, true, true); +temp[61] += equipment_struct_to_string(obj_ini.equipment, true, true); temp[62]="##Your fleet contains "; diff --git a/objects/obj_ini/Create_0.gml b/objects/obj_ini/Create_0.gml index 13c7edf62f..17725b456c 100644 --- a/objects/obj_ini/Create_0.gml +++ b/objects/obj_ini/Create_0.gml @@ -34,13 +34,9 @@ home_planet = 2; artifact_struct = array_create(200); // Equipment- maybe the bikes should go here or something? yes they should +equipment = {}; i=-1; repeat(200){i+=1; - equipment[i]=""; - equipment_type[i]=""; - equipment_number[i]=0; - equipment_condition[i]=100; - equipment_quality[i]=[]; artifact[i]=""; artifact_equipped[i]=false; artifact_tags[i]=[]; @@ -156,6 +152,7 @@ serialize = function(){ artifact_struct: artifact_struct_trimmed, marine_structs: marines, squad_structs: squads, + equipment: equipment // marines, // squads } diff --git a/scripts/scr_add_item/scr_add_item.gml b/scripts/scr_add_item/scr_add_item.gml index 9d5449f1ea..578cb9ff84 100644 --- a/scripts/scr_add_item/scr_add_item.gml +++ b/scripts/scr_add_item/scr_add_item.gml @@ -1,114 +1,99 @@ -function scr_add_item(item_name, number_of_items = 1, quality = "any", from_marine = false) { - if (item_name == "") { - exit; +/// @description Adds or removes an item from the equipment struct, supporting quality levels and special keywords +/// @param {string} _item_name The name of the item to add or remove +/// @param {real} _quantity The number of items to add (positive) or remove (negative) +/// @param {string} _quality The quality to add/remove: specific level, or "any", "best", or "worst" (default is "any") +/// @return {string} Returns the affected quality string, or "no_item" if the operation failed +function scr_add_item(_item_name, _quantity = 1, _quality = "any") { + if (_item_name == "" || _quantity == 0) { + return "no_item"; } - var i, last_open, match_slot, open_slot = false, matched = false; - var ok = 0; - var last_slot = array_length(obj_ini.equipment); - for (i = 0; i < last_slot; i++) { - if ((obj_ini.equipment[i] == "") && (open_slot == false)) { - last_open = i; - open_slot = true; - } - if ((obj_ini.equipment[i] == item_name) && (obj_ini.equipment_condition[i] > 0) && (matched == false)) { - matched = true; - match_slot = i; - break; - } + // Normalize quality if adding + if (_quantity > 0 && _quality == "any") { + _quality = "standard"; } - if (matched) { - var start_count = obj_ini.equipment_number[match_slot]; - if (start_count < 0) { - start_count = 0; - obj_ini.equipment_number[match_slot] = 0; - } - obj_ini.equipment_number[match_slot] += number_of_items; + // Create the item if it doesn't exist + if (!struct_exists(obj_ini.equipment, _item_name)) { + if (_quantity > 0) { + obj_ini.equipment[$ _item_name] = { + name: _item_name, + quantity: {} + }; + } else { + return "no_item"; + } + } - if (number_of_items > 0) { - if (quality == "any") { - quality = "standard"; - } - for (var q = start_count; q < obj_ini.equipment_number[match_slot]; q++) { - obj_ini.equipment_quality[match_slot][q] = quality; - } - // this is to make sure people can't de=equip items to get around maintenance values - if (instance_exists(obj_controller)) { - obj_controller.specialist_point_handler.add_to_armoury_repair(item_name, number_of_items); - } - } else if (number_of_items < 0) { - if (start_count == 0) { - return "no_item"; - } - var end_count = obj_ini.equipment_number[match_slot]; - if (end_count < 0) { - end_count = 0; - } - if (number_of_items == -1) { - if (quality == "any") { - if (array_length(obj_ini.equipment_quality[match_slot]) > 0) { - return array_pop(obj_ini.equipment_quality[match_slot]); - } else { - return "standard"; - } - } else { - var quality_item_found = false; - for (var q = 0; q < array_length(obj_ini.equipment_quality[match_slot]); q++) { - if (obj_ini.equipment_quality[match_slot][q] == quality) { - array_delete(obj_ini.equipment_quality[match_slot], q, 1); - quality_item_found = true; - break; - } - if (quality_item_found) { - return quality; - } else { - obj_ini.equipment_number[match_slot]++; - return "no_item"; - } - } - } - } else { - for (var q = start_count - 1; q > end_count; q--) { - array_delete(obj_ini.equipment_quality[match_slot], q, 1); - if (q == 0) { - break; - } - } - } - } - } else if (open_slot) { - obj_ini.equipment[last_open] = item_name; - obj_ini.equipment_number[last_open] = number_of_items; - obj_ini.equipment_condition[last_open] = 100; - if (quality == "any") { - quality = "standard"; - } - for (var q = 0; q < number_of_items; q++) { - obj_ini.equipment_quality[last_open][q] = quality; - } - if ((string_count("MK", item_name) > 0) || (string_count("Armour", item_name) > 0) || (item_name == "Tartaros")) { - obj_ini.equipment_type[last_open] = "armour"; - } - if (string_count("Bolts", item_name) > 0) { - obj_ini.equipment_type[last_open] = "gear"; - } - } else { - array_set(obj_ini.equipment, last_slot, item_name); - array_set(obj_ini.equipment_number, last_slot, number_of_items); - array_set(obj_ini.equipment_condition, last_slot, 100); - array_set(obj_ini.equipment_quality, last_slot, []); - if (quality == "any") { - quality = "standard"; - } - for (var q = 0; q < number_of_items; q++) { - obj_ini.equipment_quality[last_slot][q] = quality; - } - if ((string_count("MK", item_name) > 0) || (string_count("Armour", item_name) > 0) || (item_name == "Tartaros")) { - obj_ini.equipment_type[last_slot] = "armour"; + var _item_entry = obj_ini.equipment[$ _item_name]; + var _quantities = struct_exists(_item_entry, "quantity") ? _item_entry.quantity : {}; + + // Adding items + if (_quantity > 0) { + if (!struct_exists(_quantities, _quality)) { + _quantities[$ _quality] = 0; } - if (string_count("Bolts", item_name) > 0) { - obj_ini.equipment_type[last_slot] = "gear"; + + _quantities[$ _quality] += _quantity; + + // Maintenance hook + if (instance_exists(obj_controller)) { + obj_controller.specialist_point_handler.add_to_armoury_repair(_item_name, _quantity); } } -} + + // Removing items + else if (_quantity < 0) { + // Get list of existing qualities + var _available_qualities = variable_struct_get_names(_quantities); + if (array_length(_available_qualities) == 0) { + return "no_item"; + } + + // Handle special quality keywords + var _priority_list = ["standard", "exemplary", "master_crafted", "artificer", "artifact"]; + switch (_quality) { + case "any": + _quality = array_random_element(_available_qualities); // random pick + break; + + case "worst": + for (var i = 0; i < array_length(_priority_list); i++) { + if (array_contains(_available_qualities, _priority_list[i])) { + _quality = _priority_list[i]; + break; + } + } + if (_quality == "worst") return "no_item"; // fallback, unchanged + break; + + case "best": + for (var i = array_length(_priority_list) - 1; i >= 0; i--) { + if (array_contains(_available_qualities, _priority_list[i])) { + _quality = _priority_list[i]; + break; + } + } + if (_quality == "best") return "no_item"; // fallback, unchanged + break; + } + + // Now actually remove + if (!struct_exists(_quantities, _quality) || _quantities[$ _quality] <= 0) { + return "no_item"; + } + + _quantities[$ _quality] += _quantity; + + if (_quantities[$ _quality] <= 0) { + struct_remove(_quantities, _quality); + } + + // If no more qualities, remove item + if (array_length(variable_struct_get_names(_quantities)) == 0) { + struct_remove(obj_ini.equipment, _item_name); + } + + return _quality; + } +} \ No newline at end of file diff --git a/scripts/scr_array_functions/scr_array_functions.gml b/scripts/scr_array_functions/scr_array_functions.gml index 6afd8656d8..fc173d2cc6 100644 --- a/scripts/scr_array_functions/scr_array_functions.gml +++ b/scripts/scr_array_functions/scr_array_functions.gml @@ -144,6 +144,50 @@ function arrays_to_string_with_counts(_names_array, _counts_array, _exclude_null return _result_string; } +/// @description Converts the equipment struct into a formatted string with pluralized counts +/// @param {struct} _equipment The equipment struct +/// @param {bool} _exclude_null Whether to exclude entries with zero total +/// @param {bool} _dot_end Whether to end the string with a period +/// @return {string} +function equipment_struct_to_string(_equipment, _exclude_null = false, _dot_end = true) { + var _names_array = []; + var _counts_array = []; + + var _item_keys = variable_struct_get_names(_equipment); + var _count = 0; + + for (var i = 0; i < array_length(_item_keys); i++) { + var _item_name = _item_keys[i]; + var _item_data = _equipment[$ _item_name]; + + if (!is_struct(_item_data) || !struct_exists(_item_data, "quantity")) { + continue; + } + + var _quantities = _item_data.quantity; + var _quality_keys = variable_struct_get_names(_quantities); + var _total = 0; + + for (var q = 0; q < array_length(_quality_keys); q++) { + _total += _quantities[$ _quality_keys[q]]; + } + + if (_exclude_null && _total == 0) { + continue; + } + + array_push(_names_array, _item_name); + array_push(_counts_array, _total); + _count++; + } + + if (_count == 0) { + return ""; + } + + return arrays_to_string_with_counts(_names_array, _counts_array, false, _dot_end); +} + /// @function alter_deep_array /// @description Modifies a value in a deeply nested array structure. /// @param {array} array The array to modify 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 a2a95ff1ef..6cb2c509af 100644 --- a/scripts/scr_get_item_names/scr_get_item_names.gml +++ b/scripts/scr_get_item_names/scr_get_item_names.gml @@ -428,42 +428,55 @@ function push_tank_accessory_item_names(_item_names, _is_land_raider=false, _is_ /// @param {bool} _with_none - Include "(None)" in the list. /// @param {bool} _with_any - Include "(any)" in the list. /// @returns {array} item_names - The filtered list of equipment names. -function get_filtered_equipment_item_names(_item_names, _equip_category, _melee_or_ranged, _is_master_crafted=false, _required_tags=undefined, _excluded_tags=undefined, _with_none=false, _with_any=false) { +function get_filtered_equipment_item_names(_item_names, _equip_category, _melee_or_ranged, _is_master_crafted = false, _required_tags = undefined, _excluded_tags = undefined, _with_none = false, _with_any = false) { get_none_or_any_item_names(_item_names, _with_none, _with_any); - var matched_indexes = []; + var _matched_names = []; + var _equipment_keys = variable_struct_get_names(obj_ini.equipment); - for (var _i = 0; _i < array_length(obj_ini.equipment); _i++) { - if (_is_master_crafted && !array_contains(obj_ini.equipment_quality[_i], "master_crafted")) { + for (var i = 0; i < array_length(_equipment_keys); i++) { + var _item_name = _equipment_keys[i]; + var _item_struct = obj_ini.equipment[$ _item_name]; + + if (!is_struct(_item_struct) || !is_struct(_item_struct.quantity)) { + continue; + } + + if (_is_master_crafted && scr_item_count(_item_name, "master_crafted") <= 0) { + continue; + } + + if (scr_item_count(_item_name, "any") <= 0) { continue; } - var equip_data = gear_weapon_data(_equip_category, obj_ini.equipment[_i]); - if (!is_struct(equip_data) || obj_ini.equipment_number[_i] <= 0) { + var equip_data = gear_weapon_data(_equip_category, _item_name); + if (!is_struct(equip_data)) { continue; } + // Melee or ranged filter if (_melee_or_ranged != undefined) { if ((_melee_or_ranged && equip_data.range > 1.1) || (!_melee_or_ranged && equip_data.range <= 1.1)) { continue; } } - // Check required tags + // Required tags var valid = true; if (_required_tags != undefined) { - for (var _t = 0; _t < array_length(_required_tags); _t++) { - if (!equip_data.has_tag(_required_tags[_t])) { + for (var t = 0; t < array_length(_required_tags); t++) { + if (!equip_data.has_tag(_required_tags[t])) { valid = false; break; } } } - // Check excluded tags + // Excluded tags if (valid && _excluded_tags != undefined) { - for (var _t = 0; _t < array_length(_excluded_tags); _t++) { - if (equip_data.has_tag(_excluded_tags[_t])) { + for (var t = 0; t < array_length(_excluded_tags); t++) { + if (equip_data.has_tag(_excluded_tags[t])) { valid = false; break; } @@ -471,17 +484,18 @@ function get_filtered_equipment_item_names(_item_names, _equip_category, _melee_ } if (valid) { - array_push(matched_indexes, _i); + array_push(_matched_names, _item_name); } } + // Append matched item names to the output array var initial_size = array_length(_item_names); - array_resize(_item_names, initial_size + array_length(matched_indexes)); + array_resize(_item_names, initial_size + array_length(_matched_names)); var index = initial_size; - for (var j = 0; j < array_length(matched_indexes); j++) { - var equip_index = matched_indexes[j]; - var equip_data = gear_weapon_data(_equip_category, obj_ini.equipment[equip_index]); + for (var j = 0; j < array_length(_matched_names); j++) { + var _item_name = _matched_names[j]; + var equip_data = gear_weapon_data(_equip_category, _item_name); _item_names[@ index++] = equip_data.name; } diff --git a/scripts/scr_item_count/scr_item_count.gml b/scripts/scr_item_count/scr_item_count.gml index 6b46115b77..c517fd8601 100644 --- a/scripts/scr_item_count/scr_item_count.gml +++ b/scripts/scr_item_count/scr_item_count.gml @@ -1,26 +1,28 @@ -function scr_item_count(item_type, quality="any") { +/// @description Returns the total quantity of an item, optionally filtered by quality +/// @param {string} _item_name The name of the item to count +/// @param {string} _quality The quality to count ("any", or specific like "standard", "master_crafted", etc.) +/// @return {real} The total count of the item at the specified quality +function scr_item_count(_item_name, _quality = "any") { + var _count = 0; - // This script checks the equipment variables for the named item and returns the combined quantity + if (!struct_exists(obj_ini.equipment, _item_name)) { + return 0; + } - var von=0; - for (var i=0;i