diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 96be9da5546d..776014c4dfb5 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -261,6 +261,30 @@ result = first ^ second return result +/** + * Picks a random element from a list based on a weighting system: + * 1. Adds up the total of weights for each element + * 2. Gets a number between 1 and that total + * 3. For each element in the list, subtracts its weighting from that number + * 4. If that makes the number 0 or less, return that element. + * Will output null sometimes if you use decimals (e.g. 0.1 instead of 10) as rand() uses integers, not floats +**/ +/proc/pick_weight(list/list_to_pick) + var/total = 0 + var/item + for(item in list_to_pick) + if(!list_to_pick[item]) + list_to_pick[item] = 1 + total += list_to_pick[item] + + total = rand(1, total) + for(item in list_to_pick) + total -= list_to_pick[item] + if(total <= 0) + return item + + return null + /** * Picks a random element from a list based on a weighting system. * For example, given the following list: @@ -271,7 +295,7 @@ * and D would have a 0% chance of being picked. * You should only pass integers in. */ -/proc/pick_weight(list/list_to_pick) +/proc/pick_weight_allow_zero(list/list_to_pick) //The original pick_weight proc will sometimes pick entries with zero weight. I'm not sure if changing the original will break anything, so I left it be. if(length(list_to_pick) == 0) return null @@ -330,22 +354,6 @@ return final_list -/proc/pickweightAllowZero(list/L) //The original pick_weight proc will sometimes pick entries with zero weight. I'm not sure if changing the original will break anything, so I left it be. - var/total = 0 - var/item - for (item in L) - if (!L[item]) - L[item] = 0 - total += L[item] - - total = rand(0, total) - for (item in L) - total -=L [item] - if (total <= 0 && L[item]) - return item - - return null - /// Takes a weighted list (see above) and expands it into raw entries /// This eats more memory, but saves time when actually picking from it /proc/expand_weights(list/list_to_pick) diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 91c42572dbcc..148bf17ed210 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -264,7 +264,7 @@ var/datum/ai_laws/lawtype var/list/law_weights = CONFIG_GET(keyed_list/law_weight) while(!lawtype && law_weights.len) - var/possible_id = pickweightAllowZero(law_weights) + var/possible_id = pick_weight_allow_zero(law_weights) lawtype = lawid_to_type(possible_id) if(!lawtype) law_weights -= possible_id diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 2a367ff159cd..eca77ba4df5a 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -272,7 +272,7 @@ reports += config.mode_reports[report_type] Count++ for(var/i in Count to rand(3,5)) //Between three and five wrong entries on the list. - var/false_report_type = pickweightAllowZero(report_weights) + var/false_report_type = pick_weight_allow_zero(report_weights) report_weights[false_report_type] = 0 //Make it so the same false report won't be selected twice reports += config.mode_reports[false_report_type] diff --git a/code/game/objects/effects/spawners/random.dm/maintenance.dm b/code/game/objects/effects/spawners/random.dm/maintenance.dm index 44d0ab2d8c0d..53a61e0f877d 100644 --- a/code/game/objects/effects/spawners/random.dm/maintenance.dm +++ b/code/game/objects/effects/spawners/random.dm/maintenance.dm @@ -21,10 +21,12 @@ lootcount_override = spawn_loot_count . = ..() + /* Fucks everything. Investigate further // In addition, closets that are closed will have the maintenance loot inserted inside. for(var/obj/structure/closet/closet in get_turf(src)) if(!closet.opened) closet.take_contents() + */ /obj/effect/spawner/random/maintenance/two name = "2 x maintenance loot spawner" diff --git a/code/modules/overmap/objects/dynamic_datum.dm b/code/modules/overmap/objects/dynamic_datum.dm index 1ca28df922aa..ad7d5007ca6d 100644 --- a/code/modules/overmap/objects/dynamic_datum.dm +++ b/code/modules/overmap/objects/dynamic_datum.dm @@ -128,7 +128,7 @@ probabilities = list() for(var/datum/planet_type/planet_type as anything in subtypesof(/datum/planet_type)) probabilities[initial(planet_type.planet)] = initial(planet_type.weight) - planet = SSmapping.planet_types[force_encounter ? force_encounter : pickweightAllowZero(probabilities)] + planet = SSmapping.planet_types[force_encounter ? force_encounter : pick_weight_allow_zero(probabilities)] if(planet.planet !=DYNAMIC_WORLD_ASTEROID && planet.planet != DYNAMIC_WORLD_SPACERUIN) //these aren't real planets @@ -192,7 +192,7 @@ log_shuttle("[src] [REF(src)] LEVEL_INIT") // use the ruin type in template if it exists, or pick from ruin list if IT exists; otherwise null - var/selected_ruin = template || (ruin_type ? pickweightAllowZero(SSmapping.ruin_types_probabilities[ruin_type]) : null) + var/selected_ruin = template || (ruin_type ? pick_weight_allow_zero(SSmapping.ruin_types_probabilities[ruin_type]) : null) var/list/dynamic_encounter_values = SSovermap.spawn_dynamic_encounter(src, selected_ruin) if(!length(dynamic_encounter_values)) return FALSE