From e6d0ec4859bb349656bc9fbd7c039226d7e52f6b Mon Sep 17 00:00:00 2001 From: "giacomand@gmail.com" Date: Thu, 17 Jan 2013 20:34:47 +0000 Subject: [PATCH] - Major optimisations to handle_reactions(). How is this an improvement? Before we looped through every possible reaction to see if a reaction would occure with our list of reagents. Now we already make a list of reagents which can have a reactions, cutting down on searching every single time. This will decrease the loop expensive iterations from 100s to only a handful. How does it work? We format our chemical_reactions_list like this: chemical_reactions_list[reagent_id] = list() And then we fill that list of possible reactions. Thanks to Exadv1, to cut down on redundancy we only need to have a reaction in a single list at a single time, because our handle_reaction() loop will handle that. Here is a paste of the structure of the list on runtime. http://privatepaste.com/327bb61628 (has: = an entry in the list that it is nested in) - Fixed mecha weapons shooting over people lying down. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@5569 316c924e-a436-60f5-8080-3fe189b3f50e --- code/__HELPERS/global_lists.dm | 11 ++ code/game/mecha/equipment/weapons/weapons.dm | 6 +- code/modules/reagents/Chemistry-Holder.dm | 148 +++++++++++-------- 3 files changed, 100 insertions(+), 65 deletions(-) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index dc9c73b44d4..222daffd883 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -58,3 +58,14 @@ var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel") facial_hair_styles_male_list += H.name facial_hair_styles_female_list += H.name +/* // Uncomment to debug chemical reaction list. +/client/verb/debug_chemical_list() + + for (var/reaction in chemical_reactions_list) + . += "chemical_reactions_list\[\"[reaction]\"\] = \"[chemical_reactions_list[reaction]]\"\n" + if(islist(chemical_reactions_list[reaction])) + var/list/L = chemical_reactions_list[reaction] + for(var/t in L) + . += " has: [t]\n" + world << . +*/ \ No newline at end of file diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index c25616ae059..91b2455eb03 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -27,7 +27,7 @@ set_ready_state(0) playsound(chassis, fire_sound, 50, 1) var/obj/item/projectile/A = new projectile(curloc) - A.original = targloc + A.original = target A.current = curloc A.yo = targloc.y - curloc.y A.xo = targloc.x - curloc.x @@ -209,7 +209,7 @@ playsound(chassis, fire_sound, 80, 1) var/obj/item/projectile/A = new projectile(curloc) src.projectiles-- - A.original = targloc + A.original = target A.current = curloc A.yo = targloc.y - curloc.y A.xo = targloc.x - curloc.x @@ -251,7 +251,7 @@ playsound(chassis, fire_sound, 50, 1) var/obj/item/projectile/A = new projectile(curloc) src.projectiles-- - A.original = targloc + A.original = target A.current = curloc A.yo = targloc.y - curloc.y A.xo = targloc.x - curloc.x diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 8a61821ca57..92edcab68ab 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -24,12 +24,29 @@ datum var/datum/reagent/D = new path() chemical_reagents_list[D.id] = D if(!chemical_reactions_list) - //Chemical Reactions - Initialises all /datum/chemical_reaction into a list (without an index) + //Chemical Reactions - Initialises all /datum/chemical_reaction into a list + // It is filtered into multiple lists within a list. + // For example: + // chemical_reaction_list["plasma"] is a list of all reactions relating to plasma + var/paths = typesof(/datum/chemical_reaction) - /datum/chemical_reaction chemical_reactions_list = list() + for(var/path in paths) + var/datum/chemical_reaction/D = new path() - chemical_reactions_list += D + var/list/reaction_ids = list() + + if(D.required_reagents && D.required_reagents.len) + for(var/reaction in D.required_reagents) + reaction_ids += reaction + + // Create filters based on each reagent id in the required reagents list + for(var/id in reaction_ids) + if(!chemical_reactions_list[id]) + chemical_reactions_list[id] = list() + chemical_reactions_list[id] += D + break // Don't bother adding ourselves to other reagent ids, it is redundant. proc @@ -198,83 +215,90 @@ datum var/reaction_occured = 0 do reaction_occured = 0 - for(var/datum/chemical_reaction/C in chemical_reactions_list) - var/total_required_reagents = C.required_reagents.len - var/total_matching_reagents = 0 - var/total_required_catalysts = C.required_catalysts.len - var/total_matching_catalysts= 0 - var/matching_container = 0 - var/matching_other = 0 - var/list/multipliers = new/list() + for(var/datum/reagent/R in reagent_list) // Usually a small list + for(var/reaction in chemical_reactions_list[R.id]) // Was a big list but now it should be smaller since we filtered it with our reagent id - for(var/B in C.required_reagents) - if(!has_reagent(B, C.required_reagents[B])) break - total_matching_reagents++ - multipliers += round(get_reagent_amount(B) / C.required_reagents[B]) - for(var/B in C.required_catalysts) - if(!has_reagent(B, C.required_catalysts[B])) break - total_matching_catalysts++ + if(!reaction) + continue - if(!C.required_container) - matching_container = 1 + var/datum/chemical_reaction/C = reaction + var/total_required_reagents = C.required_reagents.len + var/total_matching_reagents = 0 + var/total_required_catalysts = C.required_catalysts.len + var/total_matching_catalysts= 0 + var/matching_container = 0 + var/matching_other = 0 + var/list/multipliers = new/list() - else - if(my_atom.type == C.required_container) + for(var/B in C.required_reagents) + if(!has_reagent(B, C.required_reagents[B])) break + total_matching_reagents++ + multipliers += round(get_reagent_amount(B) / C.required_reagents[B]) + for(var/B in C.required_catalysts) + if(!has_reagent(B, C.required_catalysts[B])) break + total_matching_catalysts++ + + if(!C.required_container) matching_container = 1 - if(!C.required_other) - matching_other = 1 + else + if(my_atom.type == C.required_container) + matching_container = 1 - else - /*if(istype(my_atom, /obj/item/slime_core)) - var/obj/item/slime_core/M = my_atom + if(!C.required_other) + matching_other = 1 - if(M.POWERFLAG == C.required_other && M.Uses > 0) // added a limit to slime cores -- Muskets requested this - matching_other = 1*/ - if(istype(my_atom, /obj/item/slime_extract)) - var/obj/item/slime_extract/M = my_atom + else + /*if(istype(my_atom, /obj/item/slime_core)) + var/obj/item/slime_core/M = my_atom - if(M.Uses > 0) // added a limit to slime cores -- Muskets requested this - matching_other = 1 + if(M.POWERFLAG == C.required_other && M.Uses > 0) // added a limit to slime cores -- Muskets requested this + matching_other = 1*/ + if(istype(my_atom, /obj/item/slime_extract)) + var/obj/item/slime_extract/M = my_atom + + if(M.Uses > 0) // added a limit to slime cores -- Muskets requested this + matching_other = 1 - if(total_matching_reagents == total_required_reagents && total_matching_catalysts == total_required_catalysts && matching_container && matching_other) - var/multiplier = min(multipliers) - for(var/B in C.required_reagents) - remove_reagent(B, (multiplier * C.required_reagents[B]), safety = 1) + if(total_matching_reagents == total_required_reagents && total_matching_catalysts == total_required_catalysts && matching_container && matching_other) + var/multiplier = min(multipliers) + for(var/B in C.required_reagents) + remove_reagent(B, (multiplier * C.required_reagents[B]), safety = 1) - var/created_volume = C.result_amount*multiplier - if(C.result) - feedback_add_details("chemical_reaction","[C.result]|[C.result_amount*multiplier]") - multiplier = max(multiplier, 1) //this shouldnt happen ... - add_reagent(C.result, C.result_amount*multiplier) + var/created_volume = C.result_amount*multiplier + if(C.result) + feedback_add_details("chemical_reaction","[C.result]|[C.result_amount*multiplier]") + multiplier = max(multiplier, 1) //this shouldnt happen ... + add_reagent(C.result, C.result_amount*multiplier) - for(var/mob/M in viewers(4, get_turf(my_atom)) ) - M << "\blue \icon[my_atom] The solution begins to bubble." + var/list/seen = viewers(4, get_turf(my_atom)) + for(var/mob/M in seen) + M << "\blue \icon[my_atom] The solution begins to bubble." - /* if(istype(my_atom, /obj/item/slime_core)) - var/obj/item/slime_core/ME = my_atom - ME.Uses-- - if(ME.Uses <= 0) // give the notification that the slime core is dead - for(var/mob/M in viewers(4, get_turf(my_atom)) ) - M << "\blue \icon[my_atom] The innards begin to boil!" - */ - if(istype(my_atom, /obj/item/slime_extract)) - var/obj/item/slime_extract/ME2 = my_atom - ME2.Uses-- - if(ME2.Uses <= 0) // give the notification that the slime core is dead - for(var/mob/M in viewers(4, get_turf(my_atom)) ) - M << "\blue \icon[my_atom] The [my_atom]'s power is consumed in the reaction." - ME2.name = "used slime extract" - ME2.desc = "This extract has been used up." + /* if(istype(my_atom, /obj/item/slime_core)) + var/obj/item/slime_core/ME = my_atom + ME.Uses-- + if(ME.Uses <= 0) // give the notification that the slime core is dead + for(var/mob/M in viewers(4, get_turf(my_atom)) ) + M << "\blue \icon[my_atom] The innards begin to boil!" + */ + if(istype(my_atom, /obj/item/slime_extract)) + var/obj/item/slime_extract/ME2 = my_atom + ME2.Uses-- + if(ME2.Uses <= 0) // give the notification that the slime core is dead + for(var/mob/M in seen) + M << "\blue \icon[my_atom] The [my_atom]'s power is consumed in the reaction." + ME2.name = "used slime extract" + ME2.desc = "This extract has been used up." - playsound(get_turf(my_atom), 'sound/effects/bubbles.ogg', 80, 1) + playsound(get_turf(my_atom), 'sound/effects/bubbles.ogg', 80, 1) - C.on_reaction(src, created_volume) - reaction_occured = 1 - break + C.on_reaction(src, created_volume) + reaction_occured = 1 + break while(reaction_occured) update_total()