diff --git a/code/__defines/_byond_version_compat.dm b/code/__defines/_byond_version_compat.dm index 61d61853a893..8e843d66d713 100644 --- a/code/__defines/_byond_version_compat.dm +++ b/code/__defines/_byond_version_compat.dm @@ -1,5 +1,5 @@ -#define REQUIRED_DM_VERSION 515 +#define REQUIRED_DM_VERSION 516 #if DM_VERSION < REQUIRED_DM_VERSION -#warn Nebula is not tested on BYOND versions older than 515. The code may not compile, and if it does compile it may have severe problems. +#warn Nebula is not tested on BYOND versions older than 516. The code may not compile, and if it does compile it may have severe problems. #endif \ No newline at end of file diff --git a/code/__defines/math_physics.dm b/code/__defines/math_physics.dm index 4edf99ad88af..64dd03e8c1d3 100644 --- a/code/__defines/math_physics.dm +++ b/code/__defines/math_physics.dm @@ -27,7 +27,7 @@ #define ATM *ONE_ATMOSPHERE #define ATMOS_PRECISION 0.0001 -#define QUANTIZE(variable) (round(variable, ATMOS_PRECISION)) +#define QUANTIZE(variable) (NONUNIT_FLOOR(variable, ATMOS_PRECISION)) #define INFINITY 1.#INF diff --git a/code/_helpers/lists.dm b/code/_helpers/lists.dm index a39367a43233..0a0c554c5fb0 100644 --- a/code/_helpers/lists.dm +++ b/code/_helpers/lists.dm @@ -272,6 +272,13 @@ Checks if a list has the same entries and values as an element of big. else .[key] = call(merge_method)(.[key], b_value) +// Picks a key in an alist. This is awful but hey, what can you do? +/proc/apick(alist/target_alist) + var/index = rand(1, length(target_alist)) + for(var/key in target_alist) + if(--index == 0) + return key + //Pretends to pick an element based on its weight but really just seems to pick a random element. /proc/pickweight(list/target_list) var/total = 0 diff --git a/code/_helpers/serde.dm b/code/_helpers/serde.dm index 9d50f3fae347..4ff9ff8e3004 100644 --- a/code/_helpers/serde.dm +++ b/code/_helpers/serde.dm @@ -51,7 +51,7 @@ if(!area) area = new load_path(null) instanced_areas[load_path] = area - ChangeArea(spawn_loc, area) + spawn_loc.ChangeArea(area) else if(ispath(load_path, /atom)) created_instance = new load_path(spawn_loc) diff --git a/code/_helpers/turfs.dm b/code/_helpers/turfs.dm index d74b742f97a5..c39b745f6b03 100644 --- a/code/_helpers/turfs.dm +++ b/code/_helpers/turfs.dm @@ -120,9 +120,9 @@ if(target) if(base_area) - ChangeArea(target, get_area(source)) + target.ChangeArea(get_area(source)) . += transport_turf_contents(source, target, ignore_background, translate_air, angle = angle) - ChangeArea(source, base_area) + source.ChangeArea(base_area) else . += transport_turf_contents(source, target, ignore_background, translate_air, angle = angle) //change the old turfs diff --git a/code/_onclick/hud/hud_types/_hud.dm b/code/_onclick/hud/hud_types/_hud.dm index 5a64f04f09a9..1e9b6337df0f 100644 --- a/code/_onclick/hud/hud_types/_hud.dm +++ b/code/_onclick/hud/hud_types/_hud.dm @@ -220,9 +220,9 @@ mymob.remove_mob_modifier(/decl/mob_modifier/restrained, source = mymob) if(mymob.current_posture?.prone) - mymob.add_mob_modifier(/decl/mob_modifier/prone, source = mymob) + mymob.add_mob_modifier(/decl/mob_modifier/lying, source = mymob) else - mymob.remove_mob_modifier(/decl/mob_modifier/prone, source = mymob) + mymob.remove_mob_modifier(/decl/mob_modifier/lying, source = mymob) for(var/obj/screen/elem as anything in hud_elements_update_in_life) elem.update_icon() diff --git a/code/_onclick/hud/screen/_screen.dm b/code/_onclick/hud/screen/_screen.dm index da0c7b5478af..cf3709acd140 100644 --- a/code/_onclick/hud/screen/_screen.dm +++ b/code/_onclick/hud/screen/_screen.dm @@ -71,7 +71,7 @@ /obj/screen/get_color() return color -/obj/screen/set_color(new_color) +/obj/screen/set_color(new_color, skip_update) if(color != new_color) color = new_color return TRUE diff --git a/code/_onclick/hud/screen/screen_exosuit.dm b/code/_onclick/hud/screen/screen_exosuit.dm index ad9171ed446d..5aaf6c0c9c8a 100644 --- a/code/_onclick/hud/screen/screen_exosuit.dm +++ b/code/_onclick/hud/screen/screen_exosuit.dm @@ -198,6 +198,7 @@ maptext_x = -16 maptext_width = 64 maptext_y = -8 + screen_loc = "RIGHT-2:28,CENTER+1:22" /obj/screen/exosuit/toggle name = "toggle" @@ -363,9 +364,9 @@ /obj/screen/exosuit/heat name = "heat probe" icon_state = "heatprobe" + screen_loc = "RIGHT-2:28,CENTER+1:12" var/celsius = TRUE var/obj/screen/exosuit/needle/gauge_needle = null - desc = "TEST" /obj/screen/exosuit/heat/Initialize(mapload, mob/_owner, ui_style, ui_color, ui_alpha) . = ..() @@ -417,6 +418,7 @@ /obj/screen/exosuit/health name = "exosuit integrity" icon_state = "health" + screen_loc = "RIGHT-2:28,CENTER:12" /obj/screen/exosuit/health/handle_click(mob/user, params) if(!..()) diff --git a/code/_onclick/hud/screen/screen_mob_modifier.dm b/code/_onclick/hud/screen/screen_mob_modifier.dm index d8d32bd3c586..a229d9d7db4b 100644 --- a/code/_onclick/hud/screen/screen_mob_modifier.dm +++ b/code/_onclick/hud/screen/screen_mob_modifier.dm @@ -1,5 +1,5 @@ /obj/screen/mob_modifiers - screen_loc = "CENTER,TOP" + screen_loc = "CENTER:8,TOP" icon_state = "blank" requires_ui_style = FALSE diff --git a/code/controllers/subsystems/initialization/robots.dm b/code/controllers/subsystems/initialization/robots.dm index 75c70a7fe4cc..337f8c14e593 100644 --- a/code/controllers/subsystems/initialization/robots.dm +++ b/code/controllers/subsystems/initialization/robots.dm @@ -10,14 +10,11 @@ SUBSYSTEM_DEF(robots) var/list/robot_alt_titles = list() var/list/mob_types_by_title = list( - "cyborg, flying" = /mob/living/silicon/robot/flying, "robot, flying" = /mob/living/silicon/robot/flying ) - var/list/mmi_types_by_title = list( - "cyborg" = /obj/item/organ/internal/brain_interface, + var/list/processor_types_by_title = list( "robot" = /obj/item/organ/internal/brain/robotic, - "cyborg, flying" = /obj/item/organ/internal/brain_interface, "robot, flying" = /obj/item/organ/internal/brain/robotic ) @@ -25,7 +22,7 @@ SUBSYSTEM_DEF(robots) . = ..() // This is done via loop instead of just assignment in order to trim associations. - for(var/title in (mob_types_by_title|mmi_types_by_title)) + for(var/title in (mob_types_by_title|processor_types_by_title)) robot_alt_titles |= capitalize(title) sortTim(robot_alt_titles, /proc/cmp_text_asc) @@ -58,7 +55,7 @@ SUBSYSTEM_DEF(robots) .[include_override] = modules[include_override] /datum/controller/subsystem/robots/proc/get_brain_type_by_title(var/check_title) - . = mmi_types_by_title[lowertext(trim(check_title))] || /obj/item/organ/internal/brain/robotic + . = processor_types_by_title[lowertext(trim(check_title))] || /obj/item/organ/internal/brain/robotic /datum/controller/subsystem/robots/proc/get_mob_type_by_title(var/check_title) . = mob_types_by_title[lowertext(trim(check_title))] || /mob/living/silicon/robot \ No newline at end of file diff --git a/code/datums/extensions/abilities/ability_button.dm b/code/datums/extensions/abilities/ability_button.dm index 5ab2d44e66b8..7bebb71a1993 100644 --- a/code/datums/extensions/abilities/ability_button.dm +++ b/code/datums/extensions/abilities/ability_button.dm @@ -65,7 +65,7 @@ /obj/screen/ability/button/handle_click(mob/user, params) if(owning_handler.prepared_ability == ability) owning_handler.cancel_prepared_ability() - else if(ability.use_ability(user, get_turf(user), owning_handler)) // tmp, needs better/multi-step target selection + else if(ability.use_ability(user, user, owning_handler)) // tmp, needs better/multi-step target selection update_icon() addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), ability.get_cooldown_time(ability.get_metadata_for_user(user)) + 1) diff --git a/code/datums/extensions/abilities/ability_decl.dm b/code/datums/extensions/abilities/ability_decl.dm index a3cb3726f89f..1c11a89414d4 100644 --- a/code/datums/extensions/abilities/ability_decl.dm +++ b/code/datums/extensions/abilities/ability_decl.dm @@ -182,7 +182,7 @@ else // Otherwise, just apply to the target directly. - apply_effect(user, target, metadata) + apply_ability_effect(user, target, metadata) if(end_prep_on_cast && handler.prepared_ability == src) handler.cancel_prepared_ability() @@ -325,7 +325,7 @@ return TRUE -/decl/ability/proc/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) +/decl/ability/proc/apply_ability_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) SHOULD_CALL_PARENT(TRUE) if(use_sound) playsound(get_turf(user), use_sound, use_sound_volume, 1) @@ -339,7 +339,7 @@ show_ability_cast_msg(user, targets, metadata) while(length(targets)) var/target = targets[1] - apply_effect_to(user, target, metadata) + apply_ability_effect_to(user, target, metadata) targets = prune_targets(user, target, targets, metadata) finish_casting(user, hit_target, metadata) @@ -366,7 +366,7 @@ ability_overlay.set_density(FALSE) QDEL_IN(ability_overlay, overlay_lifespan) -/decl/ability/proc/apply_effect_to(mob/user, atom/target, list/metadata) +/decl/ability/proc/apply_ability_effect_to(mob/living/user, atom/target, list/metadata) SHOULD_CALL_PARENT(TRUE) SHOULD_NOT_SLEEP(TRUE) apply_visuals(user, target, metadata) diff --git a/code/datums/extensions/abilities/ability_handler.dm b/code/datums/extensions/abilities/ability_handler.dm index 0b773cb469d5..d81a8bd023b8 100644 --- a/code/datums/extensions/abilities/ability_handler.dm +++ b/code/datums/extensions/abilities/ability_handler.dm @@ -125,7 +125,7 @@ add_screen_element(category_toggle, "toggle", TRUE) toggle_category_visibility(TRUE) -/datum/ability_handler/proc/refresh_element_positioning(row = 1, col = 1) +/datum/ability_handler/proc/refresh_element_positioning(row = 1, col = 0) if(!LAZYLEN(screen_elements)) return 0 var/button_pos = col @@ -134,14 +134,14 @@ for(var/ability in screen_elements) var/obj/screen/element = screen_elements[ability] if(istype(element, /obj/screen/ability/category)) - element.screen_loc = "RIGHT-[col]:-4,TOP-[row]" + element.screen_loc = "RIGHT-[col]:-4,TOP-[row]:-24" else if(!element.invisibility) button_pos++ if((button_pos-col) > 5) button_row++ .++ button_pos = col+1 - element.screen_loc = "RIGHT-[button_pos]:-4,TOP-[button_row]" + element.screen_loc = "RIGHT-[button_pos]:-4,TOP-[button_row]:-24" /datum/ability_handler/proc/toggle_category_visibility(force_state) showing_abilities = isnull(force_state) ? !showing_abilities : force_state diff --git a/code/datums/extensions/abilities/ability_item.dm b/code/datums/extensions/abilities/ability_item.dm index b4838fd41458..666d6d268e36 100644 --- a/code/datums/extensions/abilities/ability_item.dm +++ b/code/datums/extensions/abilities/ability_item.dm @@ -54,8 +54,8 @@ // Fire a projectile if that is how this ability works. ability.fire_projectile_at(user, target, metadata) else - // Otherwise, apply to the target. Range checking etc. will be handled in apply_effect(). - ability.apply_effect(user, target, metadata) + // Otherwise, apply to the target. Range checking etc. will be handled in apply_ability_effect(). + ability.apply_ability_effect(user, target, metadata) // Clean up our item if needed. if(ability.item_end_on_cast) diff --git a/code/datums/extensions/abilities/ability_projectile.dm b/code/datums/extensions/abilities/ability_projectile.dm index 896acba2e95a..5b5f2f10b373 100644 --- a/code/datums/extensions/abilities/ability_projectile.dm +++ b/code/datums/extensions/abilities/ability_projectile.dm @@ -22,10 +22,10 @@ /obj/item/projectile/ability/Bump(var/atom/A, forced=0) if(loc && carried_ability && !expended) - carried_ability.apply_effect(owner, A, ability_metadata, src) + carried_ability.apply_ability_effect(owner, A, ability_metadata, src) return TRUE /obj/item/projectile/ability/on_impact(var/atom/A) if(loc && carried_ability && !expended) - carried_ability.apply_effect(owner, A, ability_metadata, src) + carried_ability.apply_ability_effect(owner, A, ability_metadata, src) return TRUE diff --git a/code/datums/extensions/abilities/ability_targeting.dm b/code/datums/extensions/abilities/ability_targeting.dm index 52f7ee8166c5..e93a59c3a793 100644 --- a/code/datums/extensions/abilities/ability_targeting.dm +++ b/code/datums/extensions/abilities/ability_targeting.dm @@ -72,19 +72,35 @@ return FALSE return TRUE +/decl/ability_targeting/target_self + target_turf = FALSE + +/decl/ability_targeting/target_self/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) + return target == user + +/decl/ability_targeting/target_self/get_affected(mob/user, atom/hit_target, list/metadata, decl/ability/ability, obj/item/projectile/ability/projectile) + return list(user) + /decl/ability_targeting/clear_turf ignore_dense_turfs = TRUE /decl/ability_targeting/clear_turf/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) . = ..() && isturf(target) if(.) - var/turf/target_turf = target - return !target_turf.contains_dense_objects(user) + var/turf/turf_to_target = target + return !turf_to_target.contains_dense_objects(user) + +/decl/ability_targeting/single_atom + target_turf = FALSE + user_is_immune = TRUE + +/decl/ability_targeting/single_atom/can_target_user + user_is_immune = FALSE -/decl/ability_targeting/living_mob - target_turf = FALSE +/decl/ability_targeting/single_atom/get_affected(mob/user, atom/hit_target, list/metadata, decl/ability/ability, obj/item/projectile/ability/projectile) + return list(hit_target) -/decl/ability_targeting/living_mob/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) +/decl/ability_targeting/single_atom/living_mob/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) . = ..() && isliving(target) if(.) var/mob/living/victim = target diff --git a/code/datums/trading/traders/goods.dm b/code/datums/trading/traders/goods.dm index 81d294268dcd..c497455ab77f 100644 --- a/code/datums/trading/traders/goods.dm +++ b/code/datums/trading/traders/goods.dm @@ -247,7 +247,6 @@ Sells devices, odds and ends, and medical stuff /obj/item/synthesized_instrument/violin = TRADER_THIS_TYPE, /obj/item/hailer = TRADER_THIS_TYPE, /obj/item/uv_light = TRADER_THIS_TYPE, - /obj/item/organ/internal/brain_interface = TRADER_SUBTYPES_ONLY, /obj/item/robotanalyzer = TRADER_THIS_TYPE, /obj/item/chems/toner_cartridge = TRADER_THIS_TYPE, /obj/item/camera_film = TRADER_THIS_TYPE, diff --git a/code/datums/traits/_traits.dm b/code/datums/traits/_traits.dm index b3e7103fe9d4..94ce0f5da28d 100644 --- a/code/datums/traits/_traits.dm +++ b/code/datums/traits/_traits.dm @@ -106,6 +106,8 @@ var/available_at_map_tech = MAP_TECH_LEVEL_ANY /// Whether or not a rejuvenation should apply this aspect. var/reapply_on_rejuvenation = FALSE + /// Whether this trait should be copied and applied by mob snapshots. + var/is_heritable = TRUE /// What species can select this trait in chargen? var/list/permitted_species /// What species cannot select this trait in chargen? diff --git a/code/datums/traits/maluses/amputations.dm b/code/datums/traits/maluses/amputations.dm index 8ce9bc5d4186..5b576e2ef5f8 100644 --- a/code/datums/traits/maluses/amputations.dm +++ b/code/datums/traits/maluses/amputations.dm @@ -3,6 +3,7 @@ category = "Missing Limbs" abstract_type = /decl/trait/malus/amputation reapply_on_rejuvenation = TRUE + is_heritable = FALSE var/list/apply_to_limbs var/list/ban_traits_relating_to_limbs diff --git a/code/datums/traits/prosthetics/prosthetic_limbs.dm b/code/datums/traits/prosthetics/prosthetic_limbs.dm index a620ebef2942..ace1236f36d4 100644 --- a/code/datums/traits/prosthetics/prosthetic_limbs.dm +++ b/code/datums/traits/prosthetics/prosthetic_limbs.dm @@ -6,6 +6,7 @@ available_at_map_tech = MAP_TECH_LEVEL_ANY // the base trait must be available so that wooden prostheses are available abstract_type = /decl/trait/prosthetic_limb reapply_on_rejuvenation = TRUE + is_heritable = FALSE var/fullbody_synthetic_only = FALSE var/replace_children = TRUE var/check_bodytype diff --git a/code/datums/traits/prosthetics/prosthetic_organs.dm b/code/datums/traits/prosthetics/prosthetic_organs.dm index 0ae6ce949569..513da35f6e2d 100644 --- a/code/datums/traits/prosthetics/prosthetic_organs.dm +++ b/code/datums/traits/prosthetics/prosthetic_organs.dm @@ -5,6 +5,7 @@ available_at_map_tech = MAP_TECH_LEVEL_SPACE category = "Prosthetic Organs" reapply_on_rejuvenation = TRUE + is_heritable = FALSE var/synthetic_bodytype_restricted = FALSE var/apply_to_organ diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 2499f40ab471..e59bc1aca7ab 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -137,46 +137,46 @@ var/global/list/areas = list() ..() return QDEL_HINT_HARDDEL -// Changes the area of T to A. Do not do this manually. +// Changes the area of src to A. Do not do this manually. // Area is expected to be a non-null instance. -/proc/ChangeArea(var/turf/T, var/area/A) +/turf/proc/ChangeArea(var/area/A) if(!istype(A)) CRASH("Area change attempt failed: invalid area supplied.") - var/old_outside = T.is_outside() - var/area/old_area = get_area(T) + var/old_outside = is_outside() + var/area/old_area = get_area(src) if(old_area == A) return var/old_area_ambience = old_area?.interior_ambient_light_modifier - A.contents.Add(T) + A.contents.Add(src) if(old_area) - old_area.Exited(T, A) - for(var/atom/movable/AM as anything in T) + old_area.Exited(src, A) + for(var/atom/movable/AM as anything in src) old_area.Exited(AM, A) // Note: this _will_ raise exited events. - A.Entered(T, old_area) - for(var/atom/movable/AM as anything in T) + A.Entered(src, old_area) + for(var/atom/movable/AM as anything in src) A.Entered(AM, old_area) // Note: this will _not_ raise moved or entered events. If you change this, you must also change everything which uses them. - for(var/obj/machinery/M in T) + for(var/obj/machinery/M in src) M.area_changed(old_area, A) // They usually get moved events, but this is the one way an area can change without triggering one. - T.update_registrations_on_adjacent_area_change() + update_registrations_on_adjacent_area_change() for(var/direction in global.cardinal) - var/turf/adjacent_turf = get_step(T, direction) + var/turf/adjacent_turf = get_step(src, direction) if(adjacent_turf) adjacent_turf.update_registrations_on_adjacent_area_change() // Handle updating weather and atmos if the outside status of the turf changed. - if(T.is_outside == OUTSIDE_AREA) - T.update_external_atmos_participation() // Refreshes outside status and adds exterior air to turf air if necessary. + if(is_outside == OUTSIDE_AREA) + update_external_atmos_participation() // Refreshes outside status and adds exterior air to turf air if necessary. - if(T.is_outside() != old_outside) - T.update_weather() + if(is_outside() != old_outside) + update_weather() if(SSambience.initialized) // if not initialized, we'll loop over all turfs anyway - AMBIENCE_QUEUE_TURF(T) + AMBIENCE_QUEUE_TURF(src) else if(A.interior_ambient_light_modifier != old_area_ambience && SSambience.initialized) - AMBIENCE_QUEUE_TURF(T) + AMBIENCE_QUEUE_TURF(src) /turf/proc/update_registrations_on_adjacent_area_change() for(var/obj/machinery/door/firedoor/door in src) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index e698467579de..0d0b617fc5a5 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -847,7 +847,7 @@ /* Set the atom colour. This is a stub effectively due to the broad use of direct setting. */ // TODO: implement this everywhere that it should be used instead of direct setting. -/atom/proc/set_color(var/new_color) +/atom/proc/set_color(new_color, skip_update) if(isnull(new_color)) return reset_color() if(color != new_color) diff --git a/code/game/machinery/air_sensor.dm b/code/game/machinery/air_sensor.dm index bfbb9236ed3e..6a4774c0759b 100644 --- a/code/game/machinery/air_sensor.dm +++ b/code/game/machinery/air_sensor.dm @@ -46,9 +46,9 @@ if(total_moles <= 0) return . = list() - for(var/gas in air_sample.gas) - var/decl/material/mat = GET_DECL(gas) - var/gaspercent = round(air_sample.gas[gas]*100/total_moles,0.01) + for(var/gas_type, gas_amount in air_sample.gas) + var/decl/material/mat = GET_DECL(gas_type) + var/gaspercent = round(gas_amount*100/total_moles,0.01) var/gas_list = list("symbol" = mat.gas_symbol_html, "percent" = gaspercent) . += list(gas_list) diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm index 3de7c00f4368..b788ebfe1e8a 100644 --- a/code/game/machinery/atmoalter/portable_atmospherics.dm +++ b/code/game/machinery/atmoalter/portable_atmospherics.dm @@ -12,9 +12,9 @@ /obj/machinery/portable_atmospherics/get_single_monetary_worth() . = ..() - for(var/gas in air_contents?.gas) - var/decl/material/gas_data = GET_DECL(gas) - . += gas_data.get_value() * air_contents.gas[gas] * GAS_WORTH_MULTIPLIER + for(var/gas_type, gas_amount in air_contents?.gas) + var/decl/material/gas_data = GET_DECL(gas_type) + . += gas_data.get_value() * gas_amount * GAS_WORTH_MULTIPLIER . = max(1, round(.)) /obj/machinery/portable_atmospherics/Initialize() diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 79bb78e9540e..b023cc39b312 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -51,7 +51,7 @@ var/global/list/empty_playable_ai_cores = list() if(open_for_latejoin) empty_playable_ai_cores += D else - var/mob/living/silicon/ai/A = new /mob/living/silicon/ai ( loc, laws, brain ) + var/mob/living/silicon/ai/A = new /mob/living/silicon/ai ( loc, laws, brain.get_brainmob() ) if(A) //if there's no brain, the mob is deleted and a structure/AIcore is created A.on_mob_init() A.rename_self("ai", 1) diff --git a/code/game/machinery/doors/_door.dm b/code/game/machinery/doors/_door.dm index 3b1aec756003..2aef4698196b 100644 --- a/code/game/machinery/doors/_door.dm +++ b/code/game/machinery/doors/_door.dm @@ -465,8 +465,8 @@ close_door_at = 0 do_animate("closing") - sleep(0.5 SECONDS) src.set_density(TRUE) + sleep(0.5 SECONDS) update_nearby_tiles() src.layer = closed_layer diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm index c91249ac56d6..01fb7b136788 100644 --- a/code/game/machinery/turret_control.dm +++ b/code/game/machinery/turret_control.dm @@ -48,6 +48,10 @@ . = ..() /obj/machinery/turretid/Initialize() + . = ..() + return INITIALIZE_HINT_LATELOAD // Because areas initialize AFTER these! + +/obj/machinery/turretid/LateInitialize() if(!control_area) control_area = get_area(src) else if(istext(control_area)) @@ -55,6 +59,8 @@ if(A.name && A.name==control_area) control_area = A break + else if(ispath(control_area)) + control_area = locate(control_area) in global.areas if(control_area) var/area/A = control_area diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm index 9528d9d7b556..1716a5662e97 100644 --- a/code/game/objects/effects/spawners/bombspawner.dm +++ b/code/game/objects/effects/spawners/bombspawner.dm @@ -75,7 +75,7 @@ OT.master = V PT.valve_welded = TRUE - PT.air_contents.gas = list() + PT.air_contents.gas = alist() PT.air_contents.gas[accelerant_type] = accelerant_amount PT.air_contents.gas[filler_type] = filler_amount PT.air_contents.total_moles = accelerant_amount + filler_amount @@ -83,7 +83,7 @@ PT.air_contents.update_values() OT.valve_welded = TRUE - OT.air_contents.gas = list() + OT.air_contents.gas = alist() OT.air_contents.gas[oxidizer_type] = oxidizer_amount OT.air_contents.total_moles = oxidizer_amount OT.air_contents.temperature = FLAMMABLE_GAS_MINIMUM_BURN_TEMPERATURE+1 diff --git a/code/game/objects/items/__item.dm b/code/game/objects/items/__item.dm index 2a8d149f734c..1bed5d4cf0f6 100644 --- a/code/game/objects/items/__item.dm +++ b/code/game/objects/items/__item.dm @@ -155,13 +155,14 @@ return material.color return initial(color) -/obj/item/set_color(new_color) +/obj/item/set_color(new_color, skip_update) if(new_color == COLOR_WHITE) new_color = null if(paint_color != new_color) paint_color = new_color . = TRUE - refresh_color() + if(!skip_update) + refresh_color() /obj/item/refresh_color() if(paint_color) diff --git a/code/game/objects/items/devices/inducer.dm b/code/game/objects/items/devices/inducer.dm index bb84d497a164..1c2cf2ccd90b 100644 --- a/code/game/objects/items/devices/inducer.dm +++ b/code/game/objects/items/devices/inducer.dm @@ -47,8 +47,18 @@ return FALSE /obj/item/inducer/attackby(obj/item/used_item, mob/user) - if(CannotUse(user) || recharge(used_item, user)) + var/obj/item/cell/my_cell = get_cell() + var/datum/extension/loaded_cell/panel/cell_loaded = get_extension(src, /datum/extension/loaded_cell) + + if(cell_loaded?.has_tool_unload_interaction(used_item)) + return cell_loaded.try_unload(user, used_item) + + else if(!istype(my_cell) && istype(used_item, /obj/item/cell)) + return cell_loaded?.try_load(user, used_item) + + else if(CannotUse(user) || recharge(used_item, user)) return TRUE + return ..() /obj/item/inducer/proc/recharge(atom/A, mob/user) diff --git a/code/game/objects/items/robot/robot_frame.dm b/code/game/objects/items/robot/robot_frame.dm index 2759cbc834e3..b4edb454766e 100644 --- a/code/game/objects/items/robot/robot_frame.dm +++ b/code/game/objects/items/robot/robot_frame.dm @@ -32,6 +32,9 @@ SSstatistics.add_field("cyborg_frames_built",1) return TRUE +/obj/item/robot_parts/robot_suit/proc/is_valid_processor(obj/item/used_item) + return istype(used_item, /obj/item/organ/internal/brain/robotic) + /obj/item/robot_parts/robot_suit/attackby(obj/item/used_item, mob/user) // Uninstall a robotic part. @@ -61,28 +64,28 @@ return TRUE // Install a brain. - else if(istype(used_item, /obj/item/organ/internal/brain_interface)) + else if(istype(used_item, /obj/item/organ/internal) && is_valid_processor(used_item)) + var/obj/item/organ/internal/processor = used_item if(!isturf(loc)) - to_chat(user, SPAN_WARNING("You can't put \the [used_item] in without the frame being on the ground.")) + to_chat(user, SPAN_WARNING("You can't put \the [processor] in without the frame being on the ground.")) return TRUE if(!check_completion()) to_chat(user, SPAN_WARNING("The frame is not ready for the central processor to be installed.")) return TRUE - var/obj/item/organ/internal/brain_interface/M = used_item - var/mob/living/brainmob = M?.get_brainmob() + var/mob/living/brainmob = processor.get_brainmob() if(!brainmob) - to_chat(user, SPAN_WARNING("Sticking an empty [used_item.name] into the frame would sort of defeat the purpose.")) + to_chat(user, SPAN_WARNING("Sticking an empty [processor.name] into the frame would sort of defeat the purpose.")) return TRUE if(jobban_isbanned(brainmob, ASSIGNMENT_ROBOT)) - to_chat(user, SPAN_WARNING("\The [used_item] does not seem to fit.")) + to_chat(user, SPAN_WARNING("\The [processor] does not seem to fit.")) return TRUE if(brainmob.stat == DEAD) - to_chat(user, SPAN_WARNING("Sticking a dead [used_item.name] into the frame would sort of defeat the purpose.")) + to_chat(user, SPAN_WARNING("Sticking a dead [processor.name] into the frame would sort of defeat the purpose.")) return TRUE var/ghost_can_reenter = 0 @@ -95,10 +98,10 @@ else ghost_can_reenter = 1 if(!ghost_can_reenter) - to_chat(user, SPAN_WARNING("\The [used_item] is completely unresponsive; there's no point.")) + to_chat(user, SPAN_WARNING("\The [processor] is completely unresponsive; there's no point.")) return TRUE - if(!user.try_unequip(used_item)) + if(!user.try_unequip(processor)) return TRUE SSstatistics.add_field("cyborg_frames_built",1) @@ -106,7 +109,7 @@ if(!O) return TRUE - O.central_processor = used_item + O.central_processor = processor O.set_invisibility(INVISIBILITY_NONE) O.custom_name = created_name O.updatename("Default") @@ -120,7 +123,7 @@ var/obj/item/robot_parts/chest/chest = parts[BP_CHEST] chest.cell.forceMove(O) - used_item.forceMove(O) //Should fix cybros run time erroring when blown up. It got deleted before, along with the frame. + processor.forceMove(O) //Should fix cybros run time erroring when blown up. It got deleted before, along with the frame. // Since we "magically" installed a cell, we also have to update the correct component. if(O.cell) diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index 73ae28e1dcc2..b191b55e56da 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -80,9 +80,9 @@ var/global/list/global/tank_gauge_cache = list() /obj/item/tank/get_single_monetary_worth() . = ..() - for(var/gas in air_contents?.gas) - var/decl/material/gas_data = GET_DECL(gas) - . += gas_data.get_value() * air_contents.gas[gas] * GAS_WORTH_MULTIPLIER + for(var/gas_type, gas_amount in air_contents?.gas) + var/decl/material/gas_data = GET_DECL(gas_type) + . += gas_data.get_value() * gas_amount * GAS_WORTH_MULTIPLIER . = max(1, round(.)) /obj/item/tank/get_examine_strings(mob/user, distance, infix, suffix) diff --git a/code/game/objects/structures/__structure.dm b/code/game/objects/structures/__structure.dm index 27239ec9127b..7184dc4797b4 100644 --- a/code/game/objects/structures/__structure.dm +++ b/code/game/objects/structures/__structure.dm @@ -24,13 +24,14 @@ return material.color return initial(color) -/obj/structure/set_color(new_color) +/obj/structure/set_color(new_color, skip_update) if(new_color == COLOR_WHITE) new_color = null if(paint_color != new_color) paint_color = new_color . = TRUE - refresh_color() + if(!skip_update) + refresh_color() /obj/structure/refresh_color() if(paint_color) diff --git a/code/game/objects/structures/fires.dm b/code/game/objects/structures/fires.dm index b05b4cfba864..a92571c8a8f0 100644 --- a/code/game/objects/structures/fires.dm +++ b/code/game/objects/structures/fires.dm @@ -151,8 +151,8 @@ /obj/structure/fire_source/proc/check_atmos() var/datum/gas_mixture/GM = loc?.return_air() - for(var/g in GM?.gas) - var/decl/material/oxidizer = GET_DECL(g) + for(var/gas_type in GM?.gas) + var/decl/material/oxidizer = GET_DECL(gas_type) if(oxidizer.gas_flags & XGM_GAS_OXIDIZER) return TRUE diff --git a/code/game/turfs/floors/subtypes/floor_circuit.dm b/code/game/turfs/floors/subtypes/floor_circuit.dm index 77bb38e13a45..2737352de969 100644 --- a/code/game/turfs/floors/subtypes/floor_circuit.dm +++ b/code/game/turfs/floors/subtypes/floor_circuit.dm @@ -29,7 +29,7 @@ temperature = TCMB /turf/floor/greengrid/nitrogen - initial_gas = list(/decl/material/gas/nitrogen = MOLES_N2STANDARD) + initial_gas = alist(/decl/material/gas/nitrogen = MOLES_N2STANDARD) /turf/floor/blackgrid name = "mainframe floor" diff --git a/code/game/turfs/floors/subtypes/floor_reinforced.dm b/code/game/turfs/floors/subtypes/floor_reinforced.dm index 551786ed357b..a322fb767ce0 100644 --- a/code/game/turfs/floors/subtypes/floor_reinforced.dm +++ b/code/game/turfs/floors/subtypes/floor_reinforced.dm @@ -8,32 +8,32 @@ initial_gas = null /turf/floor/reinforced/airmix - initial_gas = list( + initial_gas = alist( /decl/material/gas/oxygen = MOLES_O2ATMOS, /decl/material/gas/nitrogen = MOLES_N2ATMOS ) /turf/floor/reinforced/nitrogen - initial_gas = list(/decl/material/gas/nitrogen = ATMOSTANK_NITROGEN) + initial_gas = alist(/decl/material/gas/nitrogen = ATMOSTANK_NITROGEN) /turf/floor/reinforced/hydrogen - initial_gas = list(/decl/material/gas/hydrogen = ATMOSTANK_HYDROGEN) + initial_gas = alist(/decl/material/gas/hydrogen = ATMOSTANK_HYDROGEN) /turf/floor/reinforced/oxygen - initial_gas = list(/decl/material/gas/oxygen = ATMOSTANK_OXYGEN) + initial_gas = alist(/decl/material/gas/oxygen = ATMOSTANK_OXYGEN) /turf/floor/reinforced/nitrogen/engine name = "engine floor" - initial_gas = list(/decl/material/gas/nitrogen = MOLES_N2STANDARD) + initial_gas = alist(/decl/material/gas/nitrogen = MOLES_N2STANDARD) /turf/floor/reinforced/hydrogen/fuel - initial_gas = list(/decl/material/gas/hydrogen = ATMOSTANK_HYDROGEN_FUEL) + initial_gas = alist(/decl/material/gas/hydrogen = ATMOSTANK_HYDROGEN_FUEL) /turf/floor/reinforced/carbon_dioxide - initial_gas = list(/decl/material/gas/carbon_dioxide = ATMOSTANK_CO2) + initial_gas = alist(/decl/material/gas/carbon_dioxide = ATMOSTANK_CO2) /turf/floor/reinforced/n20 - initial_gas = list(/decl/material/gas/nitrous_oxide = ATMOSTANK_NITROUSOXIDE) + initial_gas = alist(/decl/material/gas/nitrous_oxide = ATMOSTANK_NITROUSOXIDE) /turf/floor/reinforced/airless name = "vacuum floor" diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index eb63e73c3ccf..21fce02894d7 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -60,7 +60,7 @@ /turf/space/LateInitialize() if(SSmapping.base_floor_area) var/area/new_area = locate(SSmapping.base_floor_area) || new SSmapping.base_floor_area - ChangeArea(src, new_area) + ChangeArea(new_area) ChangeTurf(SSmapping.base_floor_type) /turf/space/proc/toggle_transit(var/direction) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index b677b30f83c7..28171b7c2394 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -18,7 +18,7 @@ var/turf_flags /// Either a mapping of material decls to mol amounts, or a reserved initial gas define like GAS_STANDARD_AIRMIX. - var/list/initial_gas + var/alist/initial_gas //Properties for airtight tiles (/wall) var/thermal_conductivity = 0.05 diff --git a/code/game/turfs/turf_enter.dm b/code/game/turfs/turf_enter.dm index cb1849868ab6..f419ff75cc63 100644 --- a/code/game/turfs/turf_enter.dm +++ b/code/game/turfs/turf_enter.dm @@ -59,9 +59,9 @@ var/datum/gas_mixture/env = return_air(1) if(!env) return - for(var/g in env.gas) - var/decl/material/mat = GET_DECL(g) - if((mat.gas_flags & XGM_GAS_CONTAMINANT) && env.gas[g] > mat.gas_overlay_limit + 1) + for(var/gas_type, gas_amount in env.gas) + var/decl/material/mat = GET_DECL(gas_type) + if((mat.gas_flags & XGM_GAS_CONTAMINANT) && gas_amount > mat.gas_overlay_limit + 1) I.contaminate() break diff --git a/code/game/turfs/walls/_wall.dm b/code/game/turfs/walls/_wall.dm index 3706a99fcfa1..e73bea10dcb7 100644 --- a/code/game/turfs/walls/_wall.dm +++ b/code/game/turfs/walls/_wall.dm @@ -301,9 +301,13 @@ var/global/list/wall_fullblend_objects = list( addtimer(CALLBACK(wall, TYPE_PROC_REF(/turf/wall, burn), temperature/4), 2) physically_destroyed() -/turf/wall/set_color(new_color) - paint_color = new_color - update_icon() +/turf/wall/set_color(new_color, skip_update) + if(paint_color != new_color) + paint_color = new_color + if(!skip_update) + update_icon() + return TRUE + return FALSE /turf/wall/proc/CheckPenetration(var/base_chance, var/damage) return round(damage/material.integrity*180) diff --git a/code/modules/ZAS/Diagnostic.dm b/code/modules/ZAS/Diagnostic.dm index 71641a66eef1..4892aa15e51b 100644 --- a/code/modules/ZAS/Diagnostic.dm +++ b/code/modules/ZAS/Diagnostic.dm @@ -10,8 +10,8 @@ to_chat(mob, "ZONE: No zone here.") var/datum/gas_mixture/mix = T.return_air() to_chat(mob, "ZONE: [mix.return_pressure()] kPa [mix.temperature] k") - for(var/g in mix.gas) - to_chat(mob, "ZONE GASES: [g]: [mix.gas[g]]\n") + for(var/gas_type, gas_amount in mix.gas) + to_chat(mob, "ZONE GASES: [gas_type]: [gas_amount]\n") /client/proc/Test_ZAS_Connection(var/turf/T) set category = "Debug" diff --git a/code/modules/ZAS/Fire.dm b/code/modules/ZAS/Fire.dm index 8e68d92a22f9..d6365ddce8df 100644 --- a/code/modules/ZAS/Fire.dm +++ b/code/modules/ZAS/Fire.dm @@ -187,12 +187,12 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin var/total_oxidizers = 0 //*** Get the fuel and oxidizer amounts - for(var/g in gas) - var/decl/material/mat = GET_DECL(g) + for(var/gas_type, gas_amount in gas) + var/decl/material/mat = GET_DECL(gas_type) if(mat.gas_flags & XGM_GAS_FUEL) - total_fuel += gas[g] + total_fuel += gas_amount if(mat.gas_flags & XGM_GAS_OXIDIZER) - total_oxidizers += gas[g] + total_oxidizers += gas_amount total_fuel *= group_multiplier total_oxidizers *= group_multiplier @@ -233,9 +233,9 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin //remove_by_flag() and adjust_gas() handle the group_multiplier for us. remove_by_flag(XGM_GAS_OXIDIZER, used_oxidizers) var/datum/gas_mixture/burned_fuel = remove_by_flag(XGM_GAS_FUEL, used_fuel) - for(var/g in burned_fuel.gas) - var/decl/material/mat = GET_DECL(g) - mat.add_burn_product(src, burned_fuel.gas[g]) + for(var/gas_type, gas_amount in burned_fuel.gas) + var/decl/material/mat = GET_DECL(gas_type) + mat.add_burn_product(src, gas_amount) //calculate the energy produced by the reaction and then set the new temperature of the mix temperature = (starting_energy + vsc.fire_fuel_energy_release * used_fuel) / heat_capacity() @@ -249,44 +249,32 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin return firelevel /datum/gas_mixture/proc/check_recombustibility() + var/const/HAS_OXIDIZER = BITFLAG(0) + var/const/HAS_FUEL = BITFLAG(1) . = 0 - for(var/g in gas) - if(gas[g] >= 0.1) - var/decl/material/gas = GET_DECL(g) + for(var/gas_type, gas_amount in gas) + if(gas_amount >= 0.1) + var/decl/material/gas = GET_DECL(gas_type) if(gas.gas_flags & XGM_GAS_OXIDIZER) - . = 1 - break - - if(!.) - return 0 - - . = 0 - for(var/g in gas) - if(gas[g] >= 0.1) - var/decl/material/gas = GET_DECL(g) - if(gas.gas_flags & XGM_GAS_OXIDIZER) - . = 1 - break + . |= HAS_OXIDIZER + if(gas.gas_flags & XGM_GAS_FUEL) + . |= HAS_FUEL + if(. == (HAS_OXIDIZER|HAS_FUEL)) + return TRUE /datum/gas_mixture/proc/check_combustibility() + var/const/HAS_OXIDIZER = BITFLAG(0) + var/const/HAS_FUEL = BITFLAG(1) . = 0 - for(var/g in gas) - if(QUANTIZE(gas[g] * vsc.fire_consuption_rate) >= 0.1) - var/decl/material/gas = GET_DECL(g) + for(var/gas_type, gas_amount in gas) + if(QUANTIZE(gas_amount * vsc.fire_consuption_rate) >= 0.1) + var/decl/material/gas = GET_DECL(gas_type) if(gas.gas_flags & XGM_GAS_OXIDIZER) - . = 1 - break - - if(!.) - return 0 - - . = 0 - for(var/g in gas) - if(QUANTIZE(gas[g] * vsc.fire_consuption_rate) >= 0.1) - var/decl/material/gas = GET_DECL(g) + . |= HAS_OXIDIZER if(gas.gas_flags & XGM_GAS_FUEL) - . = 1 - break + . |= HAS_FUEL + if(. == (HAS_OXIDIZER|HAS_FUEL)) + return TRUE //returns a value between 0 and vsc.fire_firelevel_multiplier /datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit, gas_volume) diff --git a/code/modules/ZAS/Turf.dm b/code/modules/ZAS/Turf.dm index 016d69b4c53e..95f4c9c6f34e 100644 --- a/code/modules/ZAS/Turf.dm +++ b/code/modules/ZAS/Turf.dm @@ -223,7 +223,7 @@ return TRUE return FALSE -var/global/list/STANDARD_AIRMIX = list( +var/global/alist/STANDARD_AIRMIX = alist( /decl/material/gas/oxygen = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD ) diff --git a/code/modules/ZAS/Zone.dm b/code/modules/ZAS/Zone.dm index cac84cb69bf5..10fab6f56161 100644 --- a/code/modules/ZAS/Zone.dm +++ b/code/modules/ZAS/Zone.dm @@ -180,26 +180,26 @@ Class Procs: /zone/proc/handle_condensation() set waitfor = FALSE condensing = TRUE - for(var/g in air.gas) - var/decl/material/mat = GET_DECL(g) + for(var/gas_type, gas_amount in air.gas) + var/decl/material/mat = GET_DECL(gas_type) if(!isnull(mat.gas_condensation_point) && (air.temperature <= mat.gas_condensation_point)) var/condensation_area = air.group_multiplier / length(air.gas) while(condensation_area > 0 && length(contents)) condensation_area-- var/turf/flooding = pick(contents) - var/condense_amt = min(air.gas[g], rand(1,3)) + var/condense_amt = min(gas_amount, rand(1,3)) if(condense_amt < 1) break - air.adjust_gas(g, -condense_amt) - flooding.add_to_reagents(g, condense_amt * REAGENT_UNITS_PER_GAS_MOLE) + air.adjust_gas(gas_type, -condense_amt) + flooding.add_to_reagents(gas_type, condense_amt * REAGENT_UNITS_PER_GAS_MOLE) CHECK_TICK condensing = FALSE /zone/proc/dbg_data(mob/M) to_chat(M, name) - for(var/g in air.gas) - var/decl/material/mat = GET_DECL(g) - to_chat(M, "[capitalize(mat.gas_name)]: [air.gas[g]]") + for(var/gas_type, gas_amount in air.gas) + var/decl/material/mat = GET_DECL(gas_type) + to_chat(M, "[capitalize(mat.gas_name)]: [gas_amount]") to_chat(M, "P: [air.return_pressure()] kPa V: [air.total_volume]L T: [air.temperature]°K ([air.temperature - T0C]°C)") to_chat(M, "O2 per N2: [(air.gas[/decl/material/gas/nitrogen] ? air.gas[/decl/material/gas/oxygen]/air.gas[/decl/material/gas/nitrogen] : "N/A")] Moles: [air.total_moles]") to_chat(M, "Simulated: [contents.len] ([air.group_multiplier])") diff --git a/code/modules/admin/buildmode/mode_areas.dm b/code/modules/admin/buildmode/mode_areas.dm index 4df3b7e41797..92366800d9ad 100644 --- a/code/modules/admin/buildmode/mode_areas.dm +++ b/code/modules/admin/buildmode/mode_areas.dm @@ -119,7 +119,7 @@ if(!istype(T) || !istype(area_mode)) return FALSE if (area_mode.selected_area) - ChangeArea(T, area_mode.selected_area) + T.ChangeArea(area_mode.selected_area) to_chat(build_mode.user, SPAN_NOTICE("Set area of turf [T.name] to [area_mode.selected_area.proper_name]")) return TRUE to_chat(build_mode.user, SPAN_WARNING("Pick or create an area first")) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 480a29e13010..c9b324c94e9d 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -16,8 +16,8 @@ var/t = "Coordinates: [T.x],[T.y],[T.z]\n" t += "Temperature: [env.temperature]\n" t += "Pressure: [env.return_pressure()]kPa\n" - for(var/g in env.gas) - t += "[g]: [env.gas[g]] / [env.gas[g] * R_IDEAL_GAS_EQUATION * env.temperature / env.total_volume]kPa\n" + for(var/gas_type, gas_amount in env.gas) + t += "[gas_type]: [gas_amount] / [gas_amount * R_IDEAL_GAS_EQUATION * env.temperature / env.total_volume]kPa\n" usr.show_message(t, 1) SSstatistics.add_field_details("admin_verb","ASL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! diff --git a/code/modules/atmospherics/atmos_primitives.dm b/code/modules/atmospherics/atmos_primitives.dm index 6a09490b3251..13a0044acfc6 100644 --- a/code/modules/atmospherics/atmos_primitives.dm +++ b/code/modules/atmospherics/atmos_primitives.dm @@ -110,27 +110,28 @@ if (source.total_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing return -1 - filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &= + // this takes the associated values of the left side, e.g. source.gas + filtering = source.gas & filtering //only filter gasses that are actually there. DO NOT USE &= //Determine the specific power of each filterable gas type, and the total amount of filterable gas (gasses selected to be scrubbed) - var/total_filterable_moles = 0 //the total amount of filterable gas - var/list/specific_power_gas = list() //the power required to remove one mole of pure gas, for each gas type - for (var/g in filtering) - if (source.gas[g] < MINIMUM_MOLES_TO_FILTER) + var/total_filterable_moles = 0 //the total amount of filterable gas + var/alist/specific_power_gas = alist() //the power required to remove one mole of pure gas, for each gas type + ///the power required to scrub one mol of input gas + var/power_per_mol = 0 + for (var/gas_type, gas_amount in filtering) + if (gas_amount < MINIMUM_MOLES_TO_FILTER) continue - var/specific_power = calculate_specific_power_gas(g, source, sink)/ATMOS_FILTER_EFFICIENCY - specific_power_gas[g] = specific_power - total_filterable_moles += source.gas[g] + var/specific_power = calculate_specific_power_gas(gas_type, source, sink)/ATMOS_FILTER_EFFICIENCY + specific_power_gas[gas_type] = specific_power + power_per_mol += gas_amount * specific_power + total_filterable_moles += gas_amount if (total_filterable_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing return -1 //now that we know the total amount of filterable gas, we can calculate the amount of power needed to scrub one mole of gas - var/total_specific_power = 0 //the power required to remove one mole of filterable gas - for (var/g in filtering) - var/ratio = source.gas[g]/total_filterable_moles //this converts the specific power per mole of pure gas to specific power per mole of scrubbed gas - total_specific_power += specific_power_gas[g]*ratio + power_per_mol /= total_filterable_moles //this converts the specific power per mole of pure gas to specific power per mole of scrubbed gas //Figure out how much of each gas to filter if (isnull(total_transfer_moles)) @@ -139,8 +140,8 @@ total_transfer_moles = min(total_transfer_moles, total_filterable_moles) //limit transfer_moles based on available power - if (!isnull(available_power) && total_specific_power > 0) - total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power) + if (!isnull(available_power) && power_per_mol > 0) + total_transfer_moles = min(total_transfer_moles, available_power/power_per_mol) if (total_transfer_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing return -1 @@ -154,16 +155,15 @@ P.last_flow_rate = (total_transfer_moles/source.total_moles)*source.total_volume //group_multiplier gets divided out here var/power_draw = 0 - for (var/g in filtering) - var/transfer_moles = source.gas[g] + for (var/gas_type, gas_amount in filtering) //filter gas in proportion to the mole ratio - transfer_moles = min(transfer_moles, total_transfer_moles*(source.gas[g]/total_filterable_moles)) + var/transfer_moles = min(gas_amount, total_transfer_moles*(gas_amount/total_filterable_moles)) //use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop. - source.adjust_gas(g, -transfer_moles, update=0) - sink.adjust_gas_temp(g, transfer_moles, source.temperature, update=0) + source.adjust_gas(gas_type, -transfer_moles, update=0) + sink.adjust_gas_temp(gas_type, transfer_moles, source.temperature, update=0) - power_draw += specific_power_gas[g]*transfer_moles + power_draw += specific_power_gas[gas_type]*transfer_moles //Remix the resulting gases sink.update_values() @@ -181,25 +181,16 @@ if (source.total_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing return -1 - filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &= + filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &= - var/total_specific_power = 0 //the power required to remove one mole of input gas - var/total_filterable_moles = 0 //the total amount of filterable gas - var/total_unfilterable_moles = 0 //the total amount of non-filterable gas - var/list/specific_power_gas = list() //the power required to remove one mole of pure gas, for each gas type - for (var/g in source.gas) - if (source.gas[g] < MINIMUM_MOLES_TO_FILTER) + var/power_per_mol = 0 + for (var/gas_type, gas_amount in source.gas) + if (gas_amount < MINIMUM_MOLES_TO_FILTER) continue + //the power required to move all the moles of this gas from source to sink + power_per_mol += gas_amount * calculate_specific_power_gas(gas_type, source, (gas_type in filtering) ? sink_filtered : sink_clean)/ATMOS_FILTER_EFFICIENCY - if (g in filtering) - specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_filtered)/ATMOS_FILTER_EFFICIENCY - total_filterable_moles += source.gas[g] - else - specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_clean)/ATMOS_FILTER_EFFICIENCY - total_unfilterable_moles += source.gas[g] - - var/ratio = source.gas[g]/source.total_moles //converts the specific power per mole of pure gas to specific power per mole of input gas mix - total_specific_power += specific_power_gas[g]*ratio + power_per_mol /= source.total_moles //converts the sum of specific powers per mole of pure gas to specific power per mole of input gas mix //Figure out how much of each gas to filter if (isnull(total_transfer_moles)) @@ -208,8 +199,8 @@ total_transfer_moles = min(total_transfer_moles, source.total_moles) //limit transfer_moles based on available power - if (!isnull(available_power) && total_specific_power > 0) - total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power) + if (!isnull(available_power) && power_per_mol > 0) + total_transfer_moles = min(total_transfer_moles, available_power/power_per_mol) if (total_transfer_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing return -1 @@ -223,28 +214,21 @@ P.last_flow_rate = (total_transfer_moles/source.total_moles)*source.total_volume //group_multiplier gets divided out here var/datum/gas_mixture/removed = source.remove(total_transfer_moles) - if (!removed) //Just in case + if (!removed?.total_moles) //Just in case return -1 - var/filtered_power_used = 0 //power used to move filterable gas to sink_filtered - var/unfiltered_power_used = 0 //power used to move unfilterable gas to sink_clean - for (var/g in removed.gas) - var/power_used = specific_power_gas[g]*removed.gas[g] - - if (g in filtering) - //use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop. - sink_filtered.adjust_gas_temp(g, removed.gas[g], removed.temperature, update=0) - removed.adjust_gas(g, -removed.gas[g], update=0) - filtered_power_used += power_used - else - unfiltered_power_used += power_used + // total power draw + . = power_per_mol * removed.total_moles + for (var/gas_type, gas_amount in removed.gas & filtering) // only the filtered gases + //use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop. + sink_filtered.adjust_gas_temp(gas_type, gas_amount, removed.temperature, update=0) + removed.adjust_gas(gas_type, -gas_amount, update=0) sink_filtered.update_values() removed.update_values() - sink_clean.merge(removed) - return filtered_power_used + unfiltered_power_used + return . //For omni devices. Instead filtering is an associative list mapping gasids to gas mixtures. //I don't like the copypasta, but I decided to keep both versions of gas filtering as filter_gas is slightly faster (doesn't create as many temporary lists, doesn't call update_values() as much) @@ -253,26 +237,15 @@ if (source.total_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing return -1 - filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &= + filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &= - var/total_specific_power = 0 //the power required to remove one mole of input gas - var/total_filterable_moles = 0 //the total amount of filterable gas - var/total_unfilterable_moles = 0 //the total amount of non-filterable gas - var/list/specific_power_gas = list() //the power required to remove one mole of pure gas, for each gas type - for (var/g in source.gas) - if (source.gas[g] < MINIMUM_MOLES_TO_FILTER) + var/power_per_mol = 0 + for (var/gas_type, gas_amount in source.gas) + if (gas_amount < MINIMUM_MOLES_TO_FILTER) continue - - if (g in filtering) - var/datum/gas_mixture/sink_filtered = filtering[g] - specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_filtered)/ATMOS_FILTER_EFFICIENCY - total_filterable_moles += source.gas[g] - else - specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_clean)/ATMOS_FILTER_EFFICIENCY - total_unfilterable_moles += source.gas[g] - - var/ratio = source.gas[g]/source.total_moles //converts the specific power per mole of pure gas to specific power per mole of input gas mix - total_specific_power += specific_power_gas[g]*ratio + power_per_mol += gas_amount * (calculate_specific_power_gas(gas_type, source, filtering[gas_type] || sink_clean)/ATMOS_FILTER_EFFICIENCY) + //converts the sum of specific powers per mole of pure gas to specific power per mole of input gas mix + power_per_mol /= source.total_moles //Figure out how much of each gas to filter if (isnull(total_transfer_moles)) @@ -281,8 +254,8 @@ total_transfer_moles = min(total_transfer_moles, source.total_moles) //limit transfer_moles based on available power - if (!isnull(available_power) && total_specific_power > 0) - total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power) + if (!isnull(available_power) && power_per_mol > 0) + total_transfer_moles = min(total_transfer_moles, available_power/power_per_mol) if (total_transfer_moles < MINIMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing return -1 @@ -299,27 +272,14 @@ if (!removed) //Just in case return -1 - var/list/filtered_power_used = list() //power used to move filterable gas to the filtered gas mixes - var/unfiltered_power_used = 0 //power used to move unfilterable gas to sink_clean - for (var/g in removed.gas) - var/power_used = specific_power_gas[g]*removed.gas[g] - - if (g in filtering) - var/datum/gas_mixture/sink_filtered = filtering[g] - //use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop. - sink_filtered.adjust_gas_temp(g, removed.gas[g], removed.temperature, update=1) - removed.adjust_gas(g, -removed.gas[g], update=0) - if (power_used) - filtered_power_used[sink_filtered] = power_used - else - unfiltered_power_used += power_used - + // for some reason we used to separate filtered and unfiltered power but then we just added it back up anyway?? + var/power_draw = power_per_mol * removed.total_moles + for (var/gas_type, gas_amount in removed.gas & filtering) // keys in both with the values of the former + var/datum/gas_mixture/sink_filtered = filtering[gas_type] + //use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop. + sink_filtered.adjust_gas_temp(gas_type, gas_amount, removed.temperature, update=1) + removed.adjust_gas(gas_type, -gas_amount, update=FALSE) removed.update_values() - - var/power_draw = unfiltered_power_used - for (var/datum/gas_mixture/sink_filtered in filtered_power_used) - power_draw += filtered_power_used[sink_filtered] - sink_clean.merge(removed) return power_draw diff --git a/code/modules/atmospherics/components/unary/unary_base.dm b/code/modules/atmospherics/components/unary/unary_base.dm index 6cbe3cb184b6..21734409daa8 100644 --- a/code/modules/atmospherics/components/unary/unary_base.dm +++ b/code/modules/atmospherics/components/unary/unary_base.dm @@ -12,9 +12,9 @@ /obj/machinery/atmospherics/unary/get_single_monetary_worth() . = ..() - for(var/gas in air_contents?.gas) - var/decl/material/gas_data = GET_DECL(gas) - . += gas_data.get_value() * air_contents.gas[gas] * GAS_WORTH_MULTIPLIER + for(var/gas_type, gas_amount in air_contents?.gas) + var/decl/material/gas_data = GET_DECL(gas_type) + . += gas_data.get_value() * gas_amount * GAS_WORTH_MULTIPLIER . = max(1, round(.)) /obj/machinery/atmospherics/unary/Initialize() diff --git a/code/modules/atmospherics/he_pipes.dm b/code/modules/atmospherics/he_pipes.dm index 2a11c6cde77d..d066b446d916 100644 --- a/code/modules/atmospherics/he_pipes.dm +++ b/code/modules/atmospherics/he_pipes.dm @@ -63,6 +63,7 @@ // Handle pipe heat exchange. var/turf/turf = loc var/datum/gas_mixture/pipe_air = return_air() + var/heat_radiated = FALSE if(istype(loc, /turf/space)) parent.radiate_heat_to_space(surface, 1) else if(istype(turf) && turf.simulated) @@ -71,8 +72,13 @@ environment_temperature = turf.temperature else var/datum/gas_mixture/environment = turf.return_air() + if(environment.get_total_moles() == 0) // We're in a vacuum + if(loc.is_outside()) // But we're outside, so we're in space + parent.radiate_heat_to_space(surface, 0.5) // Radiate out at half efficiency + // Else, we're inside, no gas means no heat capacity. Nothing to do, heat was dealt with either way + heat_radiated = TRUE // Skip temperature_interact() either way environment_temperature = environment?.temperature || 0 - if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference) + if(!heat_radiated && abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference) parent.temperature_interact(turf, gas_volume, thermal_conductivity) // Burn mobs buckled to this pipe. diff --git a/code/modules/atmospherics/pipes.dm b/code/modules/atmospherics/pipes.dm index 5d7ee7e8cb1f..f31cd7a5c53e 100644 --- a/code/modules/atmospherics/pipes.dm +++ b/code/modules/atmospherics/pipes.dm @@ -165,9 +165,13 @@ /obj/machinery/atmospherics/get_color() return pipe_color -/obj/machinery/atmospherics/set_color(new_color) - pipe_color = new_color - update_icon() +/obj/machinery/atmospherics/set_color(new_color, skip_update) + if(pipe_color != new_color) + pipe_color = new_color + if(!skip_update) + update_icon() + return TRUE + return FALSE /obj/machinery/atmospherics/pipe/color_cache_name(var/obj/machinery/atmospherics/node) if(istype(src, /obj/machinery/atmospherics/unary/tank)) @@ -183,11 +187,12 @@ else return pipe_color -/obj/machinery/atmospherics/pipe/set_color(new_color) - ..() - //for updating connected atmos device pipes (i.e. vents, manifolds, etc) - for(var/obj/machinery/atmospherics/node as anything in nodes_to_networks) - node.update_icon() +/obj/machinery/atmospherics/pipe/set_color(new_color, skip_update) + . = ..() + if(. && !skip_update) + //for updating connected atmos device pipes (i.e. vents, manifolds, etc) + for(var/obj/machinery/atmospherics/node as anything in nodes_to_networks) + node.update_icon() /obj/machinery/atmospherics/pipe/proc/try_leak() var/missing = FALSE diff --git a/code/modules/backgrounds/citizenship/_citizenship.dm b/code/modules/backgrounds/citizenship/_citizenship.dm index e16cc9455ac7..8ff6186f88a3 100644 --- a/code/modules/backgrounds/citizenship/_citizenship.dm +++ b/code/modules/backgrounds/citizenship/_citizenship.dm @@ -1,18 +1,10 @@ /decl/background_detail/citizenship abstract_type = /decl/background_detail/citizenship category = /decl/background_category/citizenship - var/ruling_body = "Other Faction" - var/capital - var/size_heading = "Systems" - var/size_value - var/founded + var/issuing_body /decl/background_detail/citizenship/get_text_details() . = list() - if(!isnull(capital)) - . += "Capital: [capital]." - if(!isnull(size_value) && !isnull(size_heading)) - . += "Extent: [size_value] [size_heading]." - if(!isnull(founded)) - . += "Founded: [founded]" + if(!isnull(issuing_body)) + . += "Issuing body: [issuing_body]." . += ..() diff --git a/code/modules/backgrounds/citizenship/citizenship_other.dm b/code/modules/backgrounds/citizenship/citizenship_other.dm index cfeed30a29cf..8e9b9ab29408 100644 --- a/code/modules/backgrounds/citizenship/citizenship_other.dm +++ b/code/modules/backgrounds/citizenship/citizenship_other.dm @@ -13,7 +13,6 @@ uid = "stateless" description = "You do not possess any kind of official citizenship." economic_power = 0 - capital = "None" /decl/background_detail/citizenship/synthetic name = "Stateless Drone" diff --git a/code/modules/bodytype/_bodytype.dm b/code/modules/bodytype/_bodytype.dm index 600043bdc11b..03aae1595c27 100644 --- a/code/modules/bodytype/_bodytype.dm +++ b/code/modules/bodytype/_bodytype.dm @@ -639,7 +639,7 @@ var/global/list/bodytypes_by_category = list() set_extension(limb, /datum/extension/armor, natural_armour_values) //fully_replace: If true, all existing organs will be discarded. Useful when doing mob transformations, and not caring about the existing organs -/decl/bodytype/proc/create_missing_organs(mob/living/human/H, fully_replace = FALSE) +/decl/bodytype/proc/create_missing_organs(mob/living/human/H, fully_replace = FALSE, datum/mob_snapshot/snapshot_to_use = null) if(fully_replace) H.delete_organs() @@ -659,8 +659,10 @@ var/global/list/bodytypes_by_category = list() qdel(O) //Create missing limbs - var/datum/mob_snapshot/supplied_data = H.get_mob_snapshot() - supplied_data.root_bodytype = src // This may not have been set on the target mob torso yet. + var/datum/mob_snapshot/supplied_data = snapshot_to_use + if(!supplied_data) + supplied_data = H.get_mob_snapshot() + supplied_data.root_bodytype = src // This may not have been set on the target mob torso yet. for(var/limb_type in has_limbs) if(GET_EXTERNAL_ORGAN(H, limb_type)) //Skip existing diff --git a/code/modules/bodytype/bodytype_prosthetic.dm b/code/modules/bodytype/bodytype_prosthetic.dm index 7423faf51b70..9cc143a05500 100644 --- a/code/modules/bodytype/bodytype_prosthetic.dm +++ b/code/modules/bodytype/bodytype_prosthetic.dm @@ -35,7 +35,6 @@ 'sound/foley/metal1.ogg' ) has_organ = list( - BP_BRAIN = /obj/item/organ/internal/brain_interface, BP_EYES = /obj/item/organ/internal/eyes, BP_CELL = /obj/item/organ/internal/cell ) diff --git a/code/modules/client/preference_setup/general/03_traits.dm b/code/modules/client/preference_setup/general/03_traits.dm index b61d8b02b201..e2a06b282568 100644 --- a/code/modules/client/preference_setup/general/03_traits.dm +++ b/code/modules/client/preference_setup/general/03_traits.dm @@ -39,10 +39,18 @@ else pref.prune_invalid_traits() +/datum/category_item/player_setup_item/traits/populate_mob_snapshot(datum/mob_snapshot/snapshot, is_preview_copy) + for(var/trait_type in pref.traits) + var/decl/trait/trait = GET_DECL(trait_type) + if(trait.is_heritable) + LAZYSET(snapshot.heritable_traits, trait_type, pref.traits[trait_type] || TRAIT_LEVEL_EXISTS) + /datum/category_item/player_setup_item/traits/apply_post_snapshot_preferences(mob/living/human/character, is_preview_copy = FALSE) - character.clear_extrinsic_traits() + // apply non-heritable traits now for(var/trait_type in pref.traits) - character.set_trait(trait_type, (pref.traits[trait_type] || TRAIT_LEVEL_EXISTS)) + var/decl/trait/trait = GET_DECL(trait_type) + if(!trait.is_heritable) + character.set_trait(trait_type, (pref.traits[trait_type] || TRAIT_LEVEL_EXISTS)) /datum/category_item/player_setup_item/traits/save_character(datum/pref_record_writer/writer) var/list/trait_ids = list() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index cdfe05e2c66c..e851c2513908 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -309,6 +309,7 @@ var/global/list/time_prefs_fixed = list() if(href_list["save"]) save_preferences() save_character() + return TRUE // don't regenerate our preview, that's wasteful else if(href_list["reload"]) load_preferences() load_character() @@ -325,6 +326,8 @@ var/global/list/time_prefs_fixed = list() if(isnewplayer(client.mob)) var/mob/new_player/M = client.mob M.show_lobby_menu() + update_setup_window(usr) + return TRUE // don't do a duplicate icon update else if(href_list["resetslot"]) if(real_name != input("This will reset the current slot. Enter the character's full name to confirm.")) @@ -339,12 +342,15 @@ var/global/list/time_prefs_fixed = list() equip_preview_mob ^= text2num(href_list["toggle_preview_value"]) else if(href_list["cycle_bg"]) bgstate = next_in_list(bgstate, global.using_map.char_preview_bgstate_options) + update_preview_icon(redress_mob = FALSE) + return TRUE else return FALSE + // this should get hit for reset, reload, load, slot change, and equipment preview toggle update_preview_icon() update_setup_window(usr) - return 1 + return TRUE /datum/category_item/player_setup_item/records/character_info/apply_post_snapshot_preferences(mob/living/human/character, is_preview_copy = FALSE) if(is_preview_copy) diff --git a/code/modules/clothing/_clothing.dm b/code/modules/clothing/_clothing.dm index 6ac430b952f5..67483c57d4f8 100644 --- a/code/modules/clothing/_clothing.dm +++ b/code/modules/clothing/_clothing.dm @@ -452,11 +452,12 @@ if(get_vitals_sensor()) LAZYADD(., /decl/interaction_handler/clothing_set_sensors) -/obj/item/clothing/proc/set_markings_color(new_color) +/obj/item/clothing/proc/set_markings_color(new_color, skip_update) if(markings_color != new_color) markings_color = new_color - update_icon() - update_clothing_icon() + if(!skip_update) + update_icon() + update_clothing_icon() return TRUE return FALSE diff --git a/code/modules/clothing/spacesuits/rig/modules/computer.dm b/code/modules/clothing/spacesuits/rig/modules/computer.dm index 673ecb204be0..7b4b78c9dfb3 100644 --- a/code/modules/clothing/spacesuits/rig/modules/computer.dm +++ b/code/modules/clothing/spacesuits/rig/modules/computer.dm @@ -59,6 +59,7 @@ var/mob/living/integrated_ai // Direct reference to the actual mob held in the suit. var/obj/item/ai_card // Reference to the object previously holding the AI. var/obj/item/ai_verbs/verb_holder + var/list/simple_insert_types = list(/obj/item/paicard) /mob/living var/get_rig_stats = 0 @@ -133,7 +134,7 @@ return 1 // Okay, it wasn't a terminal being touched, check for all the simple insertions. - if(input_device.type in list(/obj/item/paicard, /obj/item/organ/internal/brain_interface)) + if(is_type_in_list(input_device, simple_insert_types)) if(integrated_ai) integrated_ai.attackby(input_device,user) // If the transfer was successful, we can clear out our vars. diff --git a/code/modules/clothing/suits/_suit_hood.dm b/code/modules/clothing/suits/_suit_hood.dm index ba02cf546900..c4227a0cc66e 100644 --- a/code/modules/clothing/suits/_suit_hood.dm +++ b/code/modules/clothing/suits/_suit_hood.dm @@ -3,20 +3,23 @@ /obj/item/clothing/suit/Initialize() if(ispath(hood)) - hood = new hood(src) - hood.paint_color = paint_color - hood.markings_color = markings_color + hood = new hood(src, material) + hood.canremove = FALSE + if(markings_color) + hood.set_markings_color(markings_color, skip_update = TRUE) + if(paint_color) + hood.set_color(paint_color, skip_update = TRUE) if(isnull(hood.markings_state_modifier)) hood.markings_state_modifier = markings_state_modifier hood.update_icon() return ..() -/obj/item/clothing/suit/set_color(new_color) +/obj/item/clothing/suit/set_color(new_color, skip_update) . = ..() if(. && istype(hood)) - hood.set_color(new_color) + hood.set_color(new_color, skip_update) -/obj/item/clothing/suit/set_markings_color(new_color) +/obj/item/clothing/suit/set_markings_color(new_color, skip_update) . = ..() if(istype(hood)) hood.set_markings_color(new_color) @@ -48,18 +51,6 @@ if(length(.) && istype(hood)) // this is considered a component rather than a contained item . -= hood -/obj/item/clothing/suit/Initialize() - if(ispath(hood)) - hood = new hood(src, material) - if(paint_color) - hood.set_color(paint_color) - return ..() - -/obj/item/clothing/suit/Destroy() - if(istype(hood)) - QDEL_NULL(hood) - return ..() - /obj/item/clothing/suit/equipped(mob/user, slot) if(slot != slot_wear_suit_str) remove_hood() diff --git a/code/modules/emotes/emote_mob.dm b/code/modules/emotes/emote_mob.dm index b91444de9608..dd9e49236490 100644 --- a/code/modules/emotes/emote_mob.dm +++ b/code/modules/emotes/emote_mob.dm @@ -15,8 +15,8 @@ /mob/living/check_mob_can_emote(var/emote_type) return ..() && !(HAS_STATUS(src, STAT_SILENCE) && emote_type == AUDIBLE_MESSAGE) -/mob/living/brain/check_mob_can_emote(var/emote_type) - return ..() && istype(get_container(), /obj/item/organ/internal/brain_interface) +/mob/living/brain/check_mob_can_emote(var/emote_type, allow_brain_emote = FALSE) + return ..() && allow_brain_emote #define EMOTE_REFRESH_SPAM_COOLDOWN (5 SECONDS) /mob/proc/emote(var/act, var/m_type, var/message) diff --git a/code/modules/fabrication/designs/protolathe/designs_machine_intelligence.dm b/code/modules/fabrication/designs/protolathe/designs_machine_intelligence.dm index 3b52762f8f94..2dd5145d0b56 100644 --- a/code/modules/fabrication/designs/protolathe/designs_machine_intelligence.dm +++ b/code/modules/fabrication/designs/protolathe/designs_machine_intelligence.dm @@ -1,16 +1,10 @@ /datum/fabricator_recipe/protolathe/brains category = "Machine Intelligence" - path = /obj/item/organ/internal/brain_interface/empty + path = /obj/item/organ/internal/brain/robotic /datum/fabricator_recipe/protolathe/brains/get_product_name() . = "intelligence storage ([..()])" -/datum/fabricator_recipe/protolathe/brains/robotic - path = /obj/item/organ/internal/brain/robotic - -/datum/fabricator_recipe/protolathe/brains/mmi_radio - path = /obj/item/organ/internal/brain_interface/radio_enabled/empty - /datum/fabricator_recipe/protolathe/brains/paicard path = /obj/item/paicard diff --git a/code/modules/fusion/core/core_field.dm b/code/modules/fusion/core/core_field.dm index f9c366bc4960..fdd171b839c2 100644 --- a/code/modules/fusion/core/core_field.dm +++ b/code/modules/fusion/core/core_field.dm @@ -100,11 +100,11 @@ var/datum/gas_mixture/uptake_gas = owned_core.loc.return_air() if(uptake_gas) uptake_gas = uptake_gas.remove_by_flag(MAT_FLAG_FUSION_FUEL, rand(50,100), TRUE) - if(uptake_gas && uptake_gas.total_moles) - for(var/gasname in uptake_gas.gas) - if(uptake_gas.gas[gasname]*10 > reactants[gasname]) - AddParticles(gasname, uptake_gas.gas[gasname]*10) - uptake_gas.adjust_gas(gasname, -(uptake_gas.gas[gasname]), update=FALSE) + if(uptake_gas?.total_moles) + for(var/gas_type, gas_amount in uptake_gas.gas) + if(gas_amount*10 > reactants[gas_type]) + AddParticles(gas_type, gas_amount*10) + uptake_gas.adjust_gas(gas_type, -gas_amount, update=FALSE) added_particles = TRUE if(added_particles) uptake_gas.update_values() diff --git a/code/modules/lights/light_bulbs_tubes.dm b/code/modules/lights/light_bulbs_tubes.dm index 496ca639c1c4..1c70ad67bb80 100644 --- a/code/modules/lights/light_bulbs_tubes.dm +++ b/code/modules/lights/light_bulbs_tubes.dm @@ -31,9 +31,10 @@ /obj/item/light/get_color() return b_color -/obj/item/light/set_color(color) +/obj/item/light/set_color(new_color, skip_update) b_color = isnull(color) ? COLOR_WHITE : color - queue_icon_update() // avoid running update_icon before Initialize + if(!skip_update) + queue_icon_update() // avoid running update_icon before Initialize /obj/item/light/tube name = "light tube" diff --git a/code/modules/lights/light_fixture_base.dm b/code/modules/lights/light_fixture_base.dm index 0f2f5741a626..1afdd5b1552f 100644 --- a/code/modules/lights/light_fixture_base.dm +++ b/code/modules/lights/light_fixture_base.dm @@ -39,9 +39,9 @@ /obj/machinery/light/get_color() return lightbulb?.get_color() -/obj/machinery/light/set_color(color) - . = lightbulb?.set_color(color) - if(.) +/obj/machinery/light/set_color(new_color, skip_update) + . = lightbulb?.set_color(color, skip_update) + if(. && !skip_update) update_light_status(TRUE) update_icon() diff --git a/code/modules/maps/reader.dm b/code/modules/maps/reader.dm index 9f7dff608187..1704be274b26 100644 --- a/code/modules/maps/reader.dm +++ b/code/modules/maps/reader.dm @@ -348,7 +348,7 @@ var/global/dmm_suite/preloader/_preloader = new instance = new atype(null) initialized_areas_by_type[atype] = instance if(crds) - ChangeArea(crds, instance) + crds.ChangeArea(instance) //then instance the /turf and, if multiple tiles are presents, simulates the DMM underlays piling effect diff --git a/code/modules/maps/template_types/random_exoplanet/flora_generator.dm b/code/modules/maps/template_types/random_exoplanet/flora_generator.dm index 75c97b70ffc0..1ee8cf4f83cf 100644 --- a/code/modules/maps/template_types/random_exoplanet/flora_generator.dm +++ b/code/modules/maps/template_types/random_exoplanet/flora_generator.dm @@ -71,9 +71,9 @@ S.exude_gasses -= exuded_gases_exclusions if(length(atmos.gas)) if(S.consume_gasses) - S.consume_gasses = list(pick(atmos.gas)) // ensure that if the plant consumes a gas, the atmosphere will have it - for(var/g in atmos.gas) - var/decl/material/mat = GET_DECL(g) + S.consume_gasses = list(apick(atmos.gas)) // ensure that if the plant consumes a gas, the atmosphere will have it + for(var/gas_type in atmos.gas) + var/decl/material/mat = GET_DECL(gas_type) if(mat.gas_flags & XGM_GAS_CONTAMINANT) S.set_trait(TRAIT_TOXINS_TOLERANCE, rand(10,15)) if(prob(50)) diff --git a/code/modules/maps/template_types/random_exoplanet/planetoid_data.dm b/code/modules/maps/template_types/random_exoplanet/planetoid_data.dm index 95df86b82f93..5591ee519965 100644 --- a/code/modules/maps/template_types/random_exoplanet/planetoid_data.dm +++ b/code/modules/maps/template_types/random_exoplanet/planetoid_data.dm @@ -16,8 +16,6 @@ var/width ///Preferred height for all the planet z-levels. Null means it's up to each z-levels. Not reliable for telling the height of the levels under this planet. var/height - ///Preferred amount of vertically connected z-levels for this planets. Null means it's up to each z-levels. - var/tallness = 1 ///Topmost level data datum id of the root z stack (ID only, because this datum has an uncontrolled lifetime, and we don't want dangling refs) var/topmost_level_id ///Level data id for the level that's considered to be the planet's surface. In other words, the topmost firm ground level of the root z stack. diff --git a/code/modules/materials/_materials.dm b/code/modules/materials/_materials.dm index ada5e9a86c73..e515e82710ae 100644 --- a/code/modules/materials/_materials.dm +++ b/code/modules/materials/_materials.dm @@ -391,6 +391,9 @@ var/global/list/materials_by_gas_symbol = list() else if(isnull(ignition_point) || (new_temperature_damage_threshold > ignition_point)) temperature_damage_threshold = new_temperature_damage_threshold + global.cached_specific_heat[type] = gas_specific_heat + global.cached_molar_mass[type] = molar_mass + if(!shard_icon) shard_icon = shard_name if(!burn_armor) diff --git a/code/modules/mechs/mech.dm b/code/modules/mechs/_mech.dm similarity index 98% rename from code/modules/mechs/mech.dm rename to code/modules/mechs/_mech.dm index 25f9ecbf7873..957fe6f236a4 100644 --- a/code/modules/mechs/mech.dm +++ b/code/modules/mechs/_mech.dm @@ -68,10 +68,10 @@ var/mob/living/current_user = null - -//Pixel projectiles need a client, so we need a way to pass who the last user was for view calcs -/mob/living/proc/get_effective_gunner() - return src +/mob/living/exosuit/carried_mob_intent_changed(mob/user, decl/intent/new_intent) + if(user in pilots) + return set_intent(new_intent) + return ..() /mob/living/exosuit/get_effective_gunner() return current_user @@ -260,4 +260,3 @@ if(current_user) return FALSE return ..() - diff --git a/code/modules/mechs/components/body.dm b/code/modules/mechs/components/body.dm index 90890403e105..83869776a9c4 100644 --- a/code/modules/mechs/components/body.dm +++ b/code/modules/mechs/components/body.dm @@ -57,8 +57,8 @@ var/datum/gas_mixture/air = loc.return_air() if(air) //Essentially at this point its like we created a vacuum, but realistically making a bottle doesnt actually increase volume of a room and neither should a mech - for(var/g in air.gas) - cockpit.gas[g] = (air.gas[g] / air.total_volume) * cockpit.total_volume + for(var/gas_type, gas_amount in air.gas) + cockpit.gas[gas_type] = (gas_amount / air.total_volume) * cockpit.total_volume cockpit.temperature = air.temperature cockpit.update_values() diff --git a/code/modules/mechs/components/frame.dm b/code/modules/mechs/components/frame.dm index 867a6b831ec7..439d0a28e639 100644 --- a/code/modules/mechs/components/frame.dm +++ b/code/modules/mechs/components/frame.dm @@ -18,12 +18,12 @@ var/is_reinforced = 0 var/set_name -/obj/structure/heavy_vehicle_frame/set_color(new_colour) +/obj/structure/heavy_vehicle_frame/set_color(new_color, skip_update) var/painted_component = FALSE for(var/obj/item/mech_component/comp in list(body, arms, legs, head)) - if(comp.set_color(new_colour)) + if(comp.set_color(new_color, skip_update)) painted_component = TRUE - if(painted_component) + if(!skip_update && painted_component) queue_icon_update() /obj/structure/heavy_vehicle_frame/Destroy() diff --git a/code/modules/mechs/equipment/_equipment.dm b/code/modules/mechs/equipment/_equipment.dm index ca8273afd3b2..c98994742c58 100644 --- a/code/modules/mechs/equipment/_equipment.dm +++ b/code/modules/mechs/equipment/_equipment.dm @@ -27,26 +27,24 @@ /obj/item/mech_equipment/afterattack(var/atom/target, var/mob/living/user, var/inrange, var/params) if(require_adjacent) if(!inrange) - return 0 + return FALSE if (owner && loc == owner && ((user in owner.pilots) || user == owner)) if(target in owner.contents) - return 0 - + return FALSE if(!(owner.get_cell()?.check_charge(active_power_use * CELLRATE))) to_chat(user, SPAN_WARNING("The power indicator flashes briefly as you attempt to use \the [src].")) - return 0 - return 1 - else - return 0 + return FALSE + return TRUE + return FALSE +// Per base attack_self(), return TRUE on an action performed (ie. no further action done) and FALSE to continue action. /obj/item/mech_equipment/attack_self(var/mob/user) - if (owner && loc == owner && ((user in owner.pilots) || user == owner)) - if(!(owner.get_cell()?.check_charge(active_power_use * CELLRATE))) - to_chat(user, SPAN_WARNING("The power indicator flashes briefly as you attempt to use \the [src].")) - return 0 - return 1 - else - return 0 + if(!owner || loc != owner || (!(user in owner.pilots) && user != owner)) + return TRUE + if(!(owner.get_cell()?.check_charge(active_power_use * CELLRATE))) + to_chat(user, SPAN_WARNING("The power indicator flashes briefly as you attempt to use \the [src].")) + return TRUE + return FALSE /obj/item/mech_equipment/get_examine_strings(mob/user, distance, infix, suffix) . = ..() @@ -89,50 +87,6 @@ //Installed equipment shall not be unequiped. return FALSE -/obj/item/mech_equipment/mounted_system - abstract_type = /obj/item/mech_equipment/mounted_system - var/obj/item/holding - -/obj/item/mech_equipment/mounted_system/attack_self(var/mob/user) - . = ..() - if(. && holding) - return holding.attack_self(user) - -/obj/item/mech_equipment/mounted_system/proc/forget_holding() - if(holding) //It'd be strange for this to be called with this var unset - events_repository.unregister(/decl/observ/destroyed, holding, src, PROC_REF(forget_holding)) - holding = null - if(!QDELETED(src)) - qdel(src) - -/obj/item/mech_equipment/mounted_system/Initialize() - . = ..() - if(ispath(holding)) - holding = new holding(src) - events_repository.register(/decl/observ/destroyed, holding, src, PROC_REF(forget_holding)) - if(!istype(holding)) - return - if(!icon_state) - icon = holding.icon - icon_state = holding.icon_state - SetName(holding.name) - desc = "[holding.desc] This one is suitable for installation on an exosuit." - -/obj/item/mech_equipment/mounted_system/Destroy() - events_repository.unregister(/decl/observ/destroyed, holding, src, PROC_REF(forget_holding)) - if(holding) - QDEL_NULL(holding) - . = ..() - -/obj/item/mech_equipment/mounted_system/get_effective_obj() - return (holding ? holding : src) - -/obj/item/mech_equipment/mounted_system/get_hardpoint_status_value() - return (holding ? holding.get_hardpoint_status_value() : null) - -/obj/item/mech_equipment/mounted_system/get_hardpoint_maptext() - return (holding ? holding.get_hardpoint_maptext() : null) - /obj/item/proc/get_hardpoint_status_value() return null diff --git a/code/modules/mechs/equipment/combat.dm b/code/modules/mechs/equipment/combat.dm index 750d69df49de..fa7e758282a8 100644 --- a/code/modules/mechs/equipment/combat.dm +++ b/code/modules/mechs/equipment/combat.dm @@ -79,8 +79,7 @@ . = ..() /obj/item/mech_equipment/shields/attack_self(var/mob/user) - . = ..() - if(.) + if(!(. = ..())) toggle() /obj/item/mech_equipment/shields/proc/stop_damage(var/damage) @@ -246,8 +245,7 @@ do_attack_effect(T, "smash") /obj/item/mech_equipment/ballistic_shield/attack_self(mob/user) - . = ..() - if (.) //FORM A SHIELD WALL! + if (!(. = ..())) //FORM A SHIELD WALL! if (last_max_block + 2 SECONDS < world.time) owner.visible_message(SPAN_WARNING("\The [owner] raises \the [src], locking it in place!"), blind_message = SPAN_WARNING("You hear the whir of motors and scratching metal!")) playsound(src ,'sound/effects/bamf.ogg',35,1) @@ -320,8 +318,7 @@ O.handle_flashed(flash_time, do_stun = FALSE) /obj/item/mech_equipment/flash/attack_self(mob/user) - . = ..() - if(.) + if(!(. = ..())) if(world.time < next_use) to_chat(user, SPAN_WARNING("\The [src] is recharging!")) return diff --git a/code/modules/mechs/equipment/combat_projectile.dm b/code/modules/mechs/equipment/combat_projectile.dm index f71d5a2a5e59..a717954a893f 100644 --- a/code/modules/mechs/equipment/combat_projectile.dm +++ b/code/modules/mechs/equipment/combat_projectile.dm @@ -1,3 +1,11 @@ +/obj/item/mech_equipment/mounted_system/projectile + name = "mounted submachine gun" + icon_state = "mech_ballistic" + holding = /obj/item/gun/projectile/automatic/smg/mech + restricted_hardpoints = list(HARDPOINT_LEFT_HAND, HARDPOINT_RIGHT_HAND) + restricted_software = list(MECH_SOFTWARE_WEAPONS) + origin_tech = @'{"programming":4,"combat":6,"engineering":5}' + /obj/item/mech_equipment/mounted_system/projectile/attackby(var/obj/item/used_item, var/mob/user) var/obj/item/gun/projectile/automatic/A = holding if(!istype(A)) @@ -10,12 +18,6 @@ to_chat(user, SPAN_NOTICE("You load the ammo magazine into \the [src].")) return TRUE -/obj/item/mech_equipment/mounted_system/projectile/attack_self(var/mob/user) - . = ..() - if(. && holding) - var/obj/item/gun/M = holding - return M.switch_firemodes() - /obj/item/gun/projectile/automatic/get_hardpoint_status_value() if(!isnull(ammo_magazine)) return ammo_magazine.get_stored_ammo_count() @@ -26,14 +28,6 @@ return 0 //Weapons below this. -/obj/item/mech_equipment/mounted_system/projectile - name = "mounted submachine gun" - icon_state = "mech_ballistic" - holding = /obj/item/gun/projectile/automatic/smg/mech - restricted_hardpoints = list(HARDPOINT_LEFT_HAND, HARDPOINT_RIGHT_HAND) - restricted_software = list(MECH_SOFTWARE_WEAPONS) - origin_tech = @'{"programming":4,"combat":6,"engineering":5}' - /obj/item/gun/projectile/automatic/smg/mech magazine_type = /obj/item/ammo_magazine/mech/smg_top allowed_magazines = /obj/item/ammo_magazine/mech/smg_top @@ -167,4 +161,4 @@ gun.set_autofire(over_object, owner, FALSE) return - gun.clear_autofire() \ No newline at end of file + gun.clear_autofire() diff --git a/code/modules/mechs/equipment/engineering.dm b/code/modules/mechs/equipment/engineering.dm index 607226f683e0..00ed16ae5e14 100644 --- a/code/modules/mechs/equipment/engineering.dm +++ b/code/modules/mechs/equipment/engineering.dm @@ -179,8 +179,7 @@ owner.update_icon() /obj/item/mech_equipment/atmos_shields/attack_self(mob/user) - . = ..() - if(.) + if(!(. = ..())) if(active) deactivate() else diff --git a/code/modules/mechs/equipment/medical.dm b/code/modules/mechs/equipment/medical.dm index f18d56ea2e0e..15f415cd6478 100644 --- a/code/modules/mechs/equipment/medical.dm +++ b/code/modules/mechs/equipment/medical.dm @@ -25,8 +25,7 @@ sleeper?.go_out() /obj/item/mech_equipment/sleeper/attack_self(var/mob/user) - . = ..() - if(.) + if(!(. = ..())) sleeper.ui_interact(user) /obj/item/mech_equipment/sleeper/attackby(var/obj/item/used_item, var/mob/user) diff --git a/code/modules/mechs/equipment/mounted_system.dm b/code/modules/mechs/equipment/mounted_system.dm new file mode 100644 index 000000000000..d8a62f70a8fb --- /dev/null +++ b/code/modules/mechs/equipment/mounted_system.dm @@ -0,0 +1,41 @@ +/obj/item/mech_equipment/mounted_system + abstract_type = /obj/item/mech_equipment/mounted_system + var/obj/item/holding + +/obj/item/mech_equipment/mounted_system/attack_self(var/mob/user) + return holding ? holding.attack_self(user) : ..() + +/obj/item/mech_equipment/mounted_system/proc/forget_holding() + if(holding) //It'd be strange for this to be called with this var unset + events_repository.unregister(/decl/observ/destroyed, holding, src, PROC_REF(forget_holding)) + holding = null + if(!QDELETED(src)) + qdel(src) + +/obj/item/mech_equipment/mounted_system/Initialize() + . = ..() + if(ispath(holding)) + holding = new holding(src) + events_repository.register(/decl/observ/destroyed, holding, src, PROC_REF(forget_holding)) + if(!istype(holding)) + return + if(!icon_state) + icon = holding.icon + icon_state = holding.icon_state + SetName(holding.name) + desc = "[holding.desc] This one is suitable for installation on an exosuit." + +/obj/item/mech_equipment/mounted_system/Destroy() + events_repository.unregister(/decl/observ/destroyed, holding, src, PROC_REF(forget_holding)) + if(holding) + QDEL_NULL(holding) + . = ..() + +/obj/item/mech_equipment/mounted_system/get_effective_obj() + return (holding ? holding : src) + +/obj/item/mech_equipment/mounted_system/get_hardpoint_status_value() + return (holding ? holding.get_hardpoint_status_value() : null) + +/obj/item/mech_equipment/mounted_system/get_hardpoint_maptext() + return (holding ? holding.get_hardpoint_maptext() : null) diff --git a/code/modules/mechs/equipment/utility.dm b/code/modules/mechs/equipment/utility.dm index 37b955a8ddfe..81ed2e6b9fe3 100644 --- a/code/modules/mechs/equipment/utility.dm +++ b/code/modules/mechs/equipment/utility.dm @@ -135,8 +135,7 @@ owner.visible_message("[owner] pushes [target] out of the way.") /obj/item/mech_equipment/clamp/attack_self(var/mob/user) - . = ..() - if(.) + if(!(. = ..())) drop_carrying(user, TRUE) /obj/item/mech_equipment/clamp/get_alt_interactions(mob/user) @@ -221,8 +220,7 @@ update_icon() /obj/item/mech_equipment/light/attack_self(var/mob/user) - . = ..() - if(.) + if(!(. = ..())) toggle() to_chat(user, "You switch \the [src] [on ? "on" : "off"].") @@ -276,15 +274,12 @@ else string += "Push" return string - /obj/item/mech_equipment/catapult/attack_self(var/mob/user) - . = ..() - if(.) + if(!(. = ..())) mode = mode == CATAPULT_SINGLE ? CATAPULT_AREA : CATAPULT_SINGLE to_chat(user, SPAN_NOTICE("You set \the [src] to [mode == CATAPULT_SINGLE ? "single" : "multi"]-target mode.")) update_icon() - /obj/item/mech_equipment/catapult/afterattack(var/atom/target, var/mob/living/user, var/inrange, var/params) . = ..() if(.) @@ -393,11 +388,9 @@ drill_head = new drill_head(src) /obj/item/mech_equipment/drill/attack_self(var/mob/user) - . = ..() - if(.) - if(drill_head) - owner.visible_message(SPAN_WARNING("[owner] revs the [drill_head], menancingly.")) - playsound(src, 'sound/mecha/mechdrill.ogg', 50, 1) + if(!(. = ..()) && drill_head) + owner.visible_message(SPAN_WARNING("[owner] revs the [drill_head] menancingly.")) + playsound(src, 'sound/mecha/mechdrill.ogg', 50, 1) /obj/item/mech_equipment/drill/get_hardpoint_maptext() if(drill_head) @@ -615,14 +608,11 @@ return FALSE /obj/item/mech_equipment/ionjets/attack_self(mob/user) - . = ..() - if (!.) - return - - if (active) - deactivate() - else - activate() + if(!(. = ..())) + if(active) + deactivate() + else + activate() /obj/item/mech_equipment/ionjets/proc/activate() passive_power_use = activated_passive_power @@ -763,8 +753,7 @@ D.ui_interact(user) /obj/item/mech_equipment/camera/attack_self(mob/user) - . = ..() - if(.) + if(!(. = ..())) if(active) deactivate() else diff --git a/code/modules/mechs/interface/_interface.dm b/code/modules/mechs/interface/_interface.dm index f2985acc7324..a77bc9d53b7a 100644 --- a/code/modules/mechs/interface/_interface.dm +++ b/code/modules/mechs/interface/_interface.dm @@ -25,32 +25,28 @@ var/i = 1 for(var/hardpoint in hardpoints) var/obj/screen/exosuit/hardpoint/H = new(null, src, null, null, null, null, hardpoint) - H.screen_loc = "LEFT:6,TOP-[i]:-16" + H.screen_loc = "LEFT+1:6,TOP-[i]:-16" hud_elements |= H hardpoint_hud_elements[hardpoint] = H i++ if(body && body.pilot_coverage >= 100) additional_hud_elements += /obj/screen/exosuit/toggle/air - i = 0 - var/pos = 7 + i = 16 for(var/additional_hud in additional_hud_elements) var/obj/screen/exosuit/M = new additional_hud(null, src) - M.screen_loc = "LEFT:6,BOTTOM+[pos]:[i]" + M.screen_loc = "LEFT:6,TOP-1:-[i]" hud_elements |= M - i -= M.height + i += M.height hud_health = new /obj/screen/exosuit/health(null, src) - hud_health.screen_loc = "RIGHT-1:28,CENTER-3:11" hud_elements |= hud_health hud_open = locate(/obj/screen/exosuit/toggle/hatch_open) in hud_elements hud_power = new /obj/screen/exosuit/power(null, src) - hud_power.screen_loc = "RIGHT-1:28,CENTER-4:25" hud_elements |= hud_power hud_power_control = locate(/obj/screen/exosuit/toggle/power_control) in hud_elements hud_camera = locate(/obj/screen/exosuit/toggle/camera) in hud_elements hud_heat = new /obj/screen/exosuit/heat(null, src) - hud_heat.screen_loc = "RIGHT-1:28,CENTER-4" hud_elements |= hud_heat refresh_hud() diff --git a/code/modules/mechs/mech_construction.dm b/code/modules/mechs/mech_construction.dm index fb4f5f6b705e..41a213d4893a 100644 --- a/code/modules/mechs/mech_construction.dm +++ b/code/modules/mechs/mech_construction.dm @@ -61,15 +61,19 @@ /mob/living/exosuit/proc/install_system(var/obj/item/system, var/system_hardpoint, var/mob/user) set waitfor = FALSE + if(hardpoints_locked || hardpoints[system_hardpoint]) + to_chat(user, SPAN_WARNING("\The [system] could not be installed in that hardpoint, as it is locked or occupied.")) return FALSE var/obj/item/mech_equipment/ME = system if(istype(ME)) if(ME.restricted_hardpoints && !(system_hardpoint in ME.restricted_hardpoints)) + to_chat(user, SPAN_WARNING("\The [system] could not be installed in that hardpoint, as it is restricted.")) return FALSE if(ME.restricted_software) if(!head || !head.software) + to_chat(user, SPAN_WARNING("\The [system] could not be installed in that hardpoint, as it requires specialist software.")) return FALSE var/found for(var/software in ME.restricted_software) @@ -77,6 +81,7 @@ found = TRUE break if(!found) + to_chat(user, SPAN_WARNING("\The [system] could not be installed in that hardpoint, as it requires specialist software.")) return FALSE else return FALSE @@ -91,10 +96,10 @@ if(!do_after(user, delay, src) || user.get_active_held_item() != system) return FALSE - if(user.try_unequip(system)) - to_chat(user, SPAN_NOTICE("You install \the [system] in \the [src]'s [system_hardpoint].")) - playsound(user.loc, 'sound/items/Screwdriver.ogg', 100, 1) - else return FALSE + if(!user.try_unequip(system)) + return FALSE + to_chat(user, SPAN_NOTICE("You install \the [system] in \the [src]'s [system_hardpoint].")) + playsound(user.loc, 'sound/items/Screwdriver.ogg', 100, 1) events_repository.register(/decl/observ/destroyed, system, src, PROC_REF(forget_module)) diff --git a/code/modules/mechs/mech_interaction.dm b/code/modules/mechs/mech_interaction.dm index 8a8e9b671675..eb900899d021 100644 --- a/code/modules/mechs/mech_interaction.dm +++ b/code/modules/mechs/mech_interaction.dm @@ -349,8 +349,8 @@ var/to_place = input("Where would you like to install it?") as null|anything in (realThing.restricted_hardpoints & free_hardpoints) if(!to_place) to_chat(user, SPAN_WARNING("There is no room to install \the [used_item].")) - else if(!install_system(used_item, to_place, user)) - to_chat(user, SPAN_WARNING("\The [used_item] could not be installed in that hardpoint.")) + else + install_system(used_item, to_place, user) return TRUE // Apply customisation. diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index a565d1e1aae0..8f2f8a2212f0 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -389,6 +389,11 @@ for(var/thing in get_held_items()) try_unequip(thing, drop_loc) +/mob/proc/drop_equipped_items(drop_loc = loc, include_carried = FALSE) + SHOULD_CALL_PARENT(TRUE) + for(var/thing in get_equipped_items(include_carried)) + try_unequip(thing, drop_loc) + //Returns the item equipped to the specified slot, if any. /mob/proc/get_equipped_item(var/slot) SHOULD_CALL_PARENT(TRUE) diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm index 7fbab9b36654..ea6366c8c7e2 100644 --- a/code/modules/mob/living/brain/brain.dm +++ b/code/modules/mob/living/brain/brain.dm @@ -41,18 +41,18 @@ /mob/living/brain/proc/get_container() return get_recursive_loc_of_type(/obj/item/organ/internal) +/mob/living/brain/proc/on_container_login(obj/item/organ/internal/container) + container.update_icon() + /mob/living/brain/Login() . = ..() var/obj/item/organ/internal/container = get_container() if(istype(container)) - var/obj/item/organ/internal/brain_interface/interface = container - if(istype(interface)) - interface.locked = TRUE - container.update_icon() + on_container_login(container) /mob/living/brain/proc/is_in_interface() var/container = get_container() - return istype(container, /obj/item/organ/internal/brain_interface) || istype(container, /obj/item/organ/internal/brain/robotic) + return istype(container, /obj/item/organ/internal/brain/robotic) /mob/living/brain/can_emote(emote_type, show_message) return is_in_interface() && ..() diff --git a/code/modules/mob/living/brain/death.dm b/code/modules/mob/living/brain/death.dm index 1c185d241c60..ee2313275490 100644 --- a/code/modules/mob/living/brain/death.dm +++ b/code/modules/mob/living/brain/death.dm @@ -1,25 +1,12 @@ -/mob/living/brain/get_death_message(gibbed) - var/obj/item/organ/internal/brain_interface/container = get_container() - if(!gibbed && istype(container)) - return "beeps shrilly as \the [container] flatlines!" - return ..() - /mob/living/brain/death(gibbed) var/obj/item/organ/holder = loc - var/obj/item/organ/internal/brain_interface/container = get_container() . = ..() if(.) if(stat == DEAD && istype(holder)) holder.die() - if(istype(container) && !QDELETED(container)) - container.update_icon() /mob/living/brain/gib(do_gibs = TRUE) - var/obj/item/organ/internal/brain_interface/container = get_container() var/obj/item/organ/internal/brain/sponge = loc . = ..() - if(.) - if(istype(container) && !QDELETED(container)) - qdel(container) - if(istype(sponge) && !QDELETED(sponge)) - qdel(sponge) + if(. && istype(sponge) && !QDELETED(sponge)) + qdel(sponge) diff --git a/code/modules/mob/living/brain/say.dm b/code/modules/mob/living/brain/say.dm index c2542360968b..98946a423659 100644 --- a/code/modules/mob/living/brain/say.dm +++ b/code/modules/mob/living/brain/say.dm @@ -10,7 +10,3 @@ if(radio) radio.hear_talk(src, sanitize(message), verb, speaking) -/mob/living/brain/get_radio() - var/obj/item/organ/internal/brain_interface/container = get_container() - if(istype(container)) - return container.get_radio() diff --git a/code/modules/mob/living/human/human.dm b/code/modules/mob/living/human/human.dm index 00c520947984..4e60c2cc91d8 100644 --- a/code/modules/mob/living/human/human.dm +++ b/code/modules/mob/living/human/human.dm @@ -462,7 +462,7 @@ /mob/proc/set_bodytype(var/decl/bodytype/new_bodytype) return -/mob/living/human/set_bodytype(var/decl/bodytype/new_bodytype) +/mob/living/human/set_bodytype(var/decl/bodytype/new_bodytype, var/datum/mob_snapshot/snapshot_to_use = null) var/decl/bodytype/old_bodytype = get_bodytype() if(ispath(new_bodytype)) @@ -489,7 +489,7 @@ //set_species should not handle the entirety of initing the mob, and should not trigger deep updates //It focuses on setting up species-related data, without force applying them uppon organs and the mob's appearance. // For transforming an existing mob, look at change_species() -/mob/living/human/set_species(var/new_species_uid, var/new_bodytype = null) +/mob/living/human/set_species(var/new_species_uid, var/new_bodytype = null, var/datum/mob_snapshot/snapshot_to_use = null) if(!new_species_uid) CRASH("set_species on mob '[src]' was passed a null species uid!") var/decl/species/new_species = decls_repository.get_decl_by_id(new_species_uid) @@ -518,7 +518,7 @@ //Handle bodytype if(!new_bodytype) new_bodytype = species.get_bodytype_by_pronouns(new_pronouns) - set_bodytype(new_bodytype) + set_bodytype(new_bodytype, snapshot_to_use = snapshot_to_use) available_maneuvers = species.maneuvers.Copy() @@ -894,20 +894,10 @@ if(!defer_language_update) update_languages() -/mob/living/proc/get_background_datum_by_flag(background_flag) - var/list/all_categories = global.using_map.get_background_categories() - for(var/cat_type in all_categories) - var/decl/background_category/background_cat = all_categories[cat_type] - if(background_cat.background_flags && (background_cat.background_flags & background_flag)) - return get_background_datum(cat_type) - -/mob/living/proc/get_background_datum(cat_type) - return null - /mob/living/human/get_background_datum(cat_type) . = LAZYACCESS(background_info, cat_type) if(!istype(., /decl/background_detail)) - . = global.using_map.default_background_info[cat_type] + . = ..() PRINT_STACK_TRACE("get_background_datum() tried to return a non-instance value for background category '[cat_type]' - full background list: [json_encode(background_info)] default species culture list: [json_encode(global.using_map.default_background_info)]") /mob/living/human/get_digestion_product() @@ -984,7 +974,7 @@ else if(!species_uid) species_uid = global.using_map.default_species //Humans cannot exist without a species! - set_species(species_uid, supplied_appearance?.root_bodytype) + set_species(species_uid, supplied_appearance?.root_bodytype, snapshot_to_use = supplied_appearance) var/decl/bodytype/root_bodytype = get_bodytype() // root bodytype is set in set_species ASSERT((!supplied_appearance?.root_bodytype) || (root_bodytype == supplied_appearance.root_bodytype)) if(!get_skin_colour()) diff --git a/code/modules/mob/living/human/life.dm b/code/modules/mob/living/human/life.dm index 21aa9577627e..b5588d76bde8 100644 --- a/code/modules/mob/living/human/life.dm +++ b/code/modules/mob/living/human/life.dm @@ -157,9 +157,9 @@ var/adjusted_pressure = calculate_affecting_pressure(pressure) //Check for contaminants before anything else because we don't want to skip it. - for(var/g in environment.gas) - var/decl/material/mat = GET_DECL(g) - if((mat.gas_flags & XGM_GAS_CONTAMINANT) && environment.gas[g] > mat.gas_overlay_limit + 1) + for(var/gas_type, gas_amount in environment.gas) + var/decl/material/mat = GET_DECL(gas_type) + if((mat.gas_flags & XGM_GAS_CONTAMINANT) && gas_amount > mat.gas_overlay_limit + 1) handle_contaminants() break diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 24bb4de3f4b9..55e94083cb93 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2017,3 +2017,6 @@ default behaviour is: /mob/living/proc/is_tagging_suitable() return !key && !client +//Pixel projectiles need a client, so we need a way to pass who the last user was for view calcs +/mob/living/proc/get_effective_gunner() + return src diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index e72e3798f8cc..28beeb784990 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -103,7 +103,7 @@ var/global/list/ai_verbs_default = list( src.verbs -= ai_verbs_default src.verbs += /mob/living/verb/ghost -/mob/living/silicon/ai/Initialize(mapload, var/datum/ai_laws/L, var/obj/item/organ/internal/brain_interface/B, var/safety = 0) +/mob/living/silicon/ai/Initialize(mapload, var/datum/ai_laws/L, var/mob/living/brain/brainmob, var/safety = 0) announcement = new() announcement.title = "A.I. Announcement" announcement.announcement_type = "A.I. Announcement" @@ -143,7 +143,6 @@ var/global/list/ai_verbs_default = list( add_language(/decl/language/sign, 0) if(!safety)//Only used by AIize() to successfully spawn an AI. - var/mob/living/brainmob = B?.get_brainmob() if(!brainmob) // If there is no player/brain inside. empty_playable_ai_cores += new/obj/structure/aicore/deactivated(loc)//New empty terminal. . = INITIALIZE_HINT_QDEL diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index b113096f13be..53c6a4859bfe 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -234,11 +234,11 @@ var/t_moles = env.total_moles var/gases[0] - for(var/g in env.gas) + for(var/gas_type, gas_amount in env.gas) var/gas[0] - var/decl/material/mat = GET_DECL(g) + var/decl/material/mat = GET_DECL(gas_type) gas["name"] = capitalize(mat.gas_name) - gas["percent"] = round((env.gas[g] / t_moles) * 100) + gas["percent"] = round((gas_amount / t_moles) * 100) gases[++gases.len] = gas data["gas"] = gases diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index 969dd3dac640..fa013a27914f 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -76,7 +76,6 @@ can_hold = list( /obj/item/cell, /obj/item/stock_parts, - /obj/item/organ/internal/brain_interface, /obj/item/robot_parts, /obj/item/borg/upgrade, /obj/item/flash, diff --git a/code/modules/mob/living/simple_animal/_simple_animal.dm b/code/modules/mob/living/simple_animal/_simple_animal.dm index 7b62adcc2ed0..7c30f1cfcc6d 100644 --- a/code/modules/mob/living/simple_animal/_simple_animal.dm +++ b/code/modules/mob/living/simple_animal/_simple_animal.dm @@ -496,12 +496,11 @@ var/global/list/simplemob_icon_bitflag_cache = list() if(!level_data.exterior_atmosphere) return - for(var/gas in level_data.exterior_atmosphere.gas) - var/gas_amt = level_data.exterior_atmosphere.gas[gas] + for(var/gas_type, gas_amt in level_data.exterior_atmosphere.gas) if(min_gas) - min_gas[gas] = round(gas_amt * 0.5) + min_gas[gas_type] = round(gas_amt * 0.5) if(max_gas) - min_gas[gas] = round(gas_amt * 1.5) + min_gas[gas_type] = round(gas_amt * 1.5) // Simple filler bodytype so animals get offsets for their inventory slots. /decl/bodytype/animal diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 8d3083ecbf9d..612a4e888b47 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -695,10 +695,10 @@ var/global/const/ACTION_DANGER_ALL = 2 return ..() /mob/proc/pull_damage() - return 0 + return FALSE /mob/living/human/pull_damage() - if(!current_posture.prone|| get_damage(BRUTE) + get_damage(BURN) < 100) + if(buckled || !current_posture.prone || get_damage(BRUTE) + get_damage(BURN) < 100) return FALSE for(var/obj/item/organ/external/e in get_external_organs()) if((e.status & ORGAN_BROKEN) && !e.splinted) @@ -1603,3 +1603,13 @@ var/global/const/ACTION_DANGER_ALL = 2 // Returns true if the mob is cloaked, otherwise false /mob/proc/is_cloaked() return FALSE + +/mob/proc/get_background_datum_by_flag(background_flag) + var/list/all_categories = global.using_map.get_background_categories() + for(var/cat_type in all_categories) + var/decl/background_category/background_cat = all_categories[cat_type] + if(background_cat.background_flags && (background_cat.background_flags & background_flag)) + return get_background_datum(cat_type) + +/mob/proc/get_background_datum(cat_type) + return global.using_map.default_background_info[cat_type] diff --git a/code/modules/mob/mob_intent.dm b/code/modules/mob/mob_intent.dm index f9271fb64fec..4eeeaaff9ff4 100644 --- a/code/modules/mob/mob_intent.dm +++ b/code/modules/mob/mob_intent.dm @@ -115,10 +115,16 @@ _a_intent = new_intent if(istype(hud_used)) hud_used.refresh_element(HUD_INTENT) + if(ismob(loc)) + var/mob/holder = loc + holder.carried_mob_intent_changed(src, _a_intent) return TRUE return FALSE +/mob/proc/carried_mob_intent_changed(mob/user, decl/intent/new_intent) + return + /mob/proc/get_intent() RETURN_TYPE(/decl/intent) var/list/available_intents = get_available_intents() diff --git a/code/modules/mob/mob_snapshot.dm b/code/modules/mob/mob_snapshot.dm index c876a47857c6..271fade652b2 100644 --- a/code/modules/mob/mob_snapshot.dm +++ b/code/modules/mob/mob_snapshot.dm @@ -16,6 +16,8 @@ var/list/genetic_conditions /// Please find a better way to do this. This is done to add tails if we have the tail accessory selected... var/list/extra_limbs + /// A list of trait levels to add. Should contain only 'heritable' traits... whatever that means. + var/list/heritable_traits /datum/mob_snapshot/New(mob/living/donor, genetic_info_only = FALSE) @@ -74,6 +76,10 @@ else if(istype(root_bodytype) && target.get_bodytype() != root_bodytype) target.set_bodytype(root_bodytype) + // we try to set traits as soon as possible after species set + for(var/target_trait in heritable_traits) + target.set_trait(target_trait, heritable_traits[target_trait]) + target.set_fingerprint(fingerprint) target.set_unique_enzymes(unique_enzymes) target.set_skin_colour(skin_color) diff --git a/code/modules/mob/new_player/preferences_setup.dm b/code/modules/mob/new_player/preferences_setup.dm index 5a8b7f89ecbe..b1104cadc6cf 100644 --- a/code/modules/mob/new_player/preferences_setup.dm +++ b/code/modules/mob/new_player/preferences_setup.dm @@ -109,11 +109,12 @@ mannequin.update_icon() mannequin.compile_overlays() -/datum/preferences/proc/update_preview_icon() +/datum/preferences/proc/update_preview_icon(redress_mob = TRUE) var/mob/living/human/dummy/mannequin/mannequin = get_mannequin(client?.ckey) if(mannequin) - mannequin.delete_inventory(TRUE) - dress_preview_mob(mannequin) + if(redress_mob) + mannequin.delete_inventory(TRUE) + dress_preview_mob(mannequin) update_character_previews(mannequin) /datum/preferences/proc/get_random_name() diff --git a/code/modules/mob/observer/eye/blueprints_eye.dm b/code/modules/mob/observer/eye/blueprints_eye.dm index c7bae7b5f9c7..6309e82b166d 100644 --- a/code/modules/mob/observer/eye/blueprints_eye.dm +++ b/code/modules/mob/observer/eye/blueprints_eye.dm @@ -66,7 +66,7 @@ var/area/A = new A.SetName(area_name) for(var/turf/T in selected_turfs) - ChangeArea(T, A) + T.ChangeArea(A) finalize_area(A) remove_selection() // Reset the selection for clarity. @@ -90,7 +90,7 @@ var/datum/level_data/our_level_data = SSmapping.levels_by_z[our_turf.z] var/area/base_area = our_level_data.get_base_area_instance() for(var/turf/T in A.contents) - ChangeArea(T, base_area) + T.ChangeArea(base_area) if(!(locate(/turf) in A)) qdel(A) // uh oh, is this safe? @@ -316,7 +316,7 @@ var/datum/level_data/our_level_data = SSmapping.levels_by_z[our_turf.z] var/area/base_area = our_level_data.get_base_area_instance() for(var/turf/T in A.contents) - ChangeArea(T, base_area) + T.ChangeArea(base_area) if(!(locate(/turf) in A)) qdel(A) // uh oh, is this safe? diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index bebc25e3b4b5..d358e28ba7d4 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -51,8 +51,8 @@ /mob/living/AIize(move = TRUE) if (HAS_TRANSFORMATION_MOVEMENT_HANDLER(src)) return - for(var/t in get_external_organs()) - qdel(t) + delete_organs() + drop_equipped_items() for(var/obj/item/thing in src) drop_from_inventory(thing) ADD_TRANSFORMATION_MOVEMENT_HANDLER(src) @@ -65,7 +65,7 @@ sound_to(src, sound(null, repeat = 0, wait = 0, volume = 85, channel = sound_channels.lobby_channel))// stop the jams for AIs - var/mob/living/silicon/ai/O = new (loc, global.using_map.default_law_type,,1)//No brain but safety is in effect. + var/mob/living/silicon/ai/O = new (loc, global.using_map.default_law_type,null,1)//No brain but safety is in effect. O.set_invisibility(INVISIBILITY_NONE) O.aiRestorePowerRoutine = 0 if(mind) @@ -101,28 +101,23 @@ qdel(src) return O -//human -> robot -/mob/living/human/proc/Robotize(var/supplied_robot_type = /mob/living/silicon/robot) +//living mob -> robot +/mob/living/proc/Robotize(var/supplied_robot_type = ASSIGNMENT_ROBOT, skip_qdel = FALSE) if (HAS_TRANSFORMATION_MOVEMENT_HANDLER(src)) return - QDEL_NULL_LIST(worn_underwear) - for(var/obj/item/thing in src) - drop_from_inventory(thing) - try_refresh_visible_overlays() ADD_TRANSFORMATION_MOVEMENT_HANDLER(src) - icon = null - set_invisibility(INVISIBILITY_ABSTRACT) - for(var/t in get_external_organs()) - qdel(t) - - var/mob/living/silicon/robot/O = new supplied_robot_type( loc ) + drop_equipped_items() + var/robot_type_path = SSrobots.get_mob_type_by_title(supplied_robot_type) + var/mob/living/silicon/robot/O = new robot_type_path(loc) - O.set_gender(gender) + O.set_gender(get_gender()) O.set_invisibility(INVISIBILITY_NONE) if(!mind) mind_initialize() mind.assigned_role = ASSIGNMENT_ROBOT + if(supplied_robot_type != ASSIGNMENT_ROBOT) + mind.role_alt_title = supplied_robot_type mind.active = TRUE mind.transfer_to(O) if(O.mind && O.mind.assigned_role == ASSIGNMENT_ROBOT) @@ -135,7 +130,8 @@ RAISE_EVENT(/decl/observ/cyborg_created, O) O.Namepick() - qdel(src) + if(!skip_qdel) + qdel(src) return O /mob/living/human/proc/corgize() diff --git a/code/modules/mob_modifiers/definitions/modifiers_prone.dm b/code/modules/mob_modifiers/definitions/modifiers_prone.dm index caf5b30c53b6..14d04ecac121 100644 --- a/code/modules/mob_modifiers/definitions/modifiers_prone.dm +++ b/code/modules/mob_modifiers/definitions/modifiers_prone.dm @@ -1,10 +1,10 @@ -/decl/mob_modifier/prone - name = "Prone" - desc = "You are lying prone and may need to stand up before taking action." +/decl/mob_modifier/lying + name = "Lying" + desc = "You are lying down and may need to stand up before taking action." hud_icon_state = "prone" show_indefinite_duration = FALSE -/decl/mob_modifier/prone/on_modifier_datum_click(mob/living/_owner, decl/mob_modifier/modifier, params) +/decl/mob_modifier/lying/on_modifier_datum_click(mob/living/_owner, decl/mob_modifier/modifier, params) if(_owner.current_posture?.prone) _owner.lay_down() return TRUE diff --git a/code/modules/multiz/level_data.dm b/code/modules/multiz/level_data.dm index 73f2054e5696..c88b80a285ea 100644 --- a/code/modules/multiz/level_data.dm +++ b/code/modules/multiz/level_data.dm @@ -232,7 +232,7 @@ if(change_turf) T = T.ChangeTurf(picked_turf) if(change_area) - ChangeArea(T, A) + T.ChangeArea(A) ///Prepare level for being used. Setup borders, lateral z connections, ambient lighting, atmosphere, etc.. /datum/level_data/proc/setup_level_data(var/skip_gen = FALSE) @@ -410,11 +410,11 @@ exterior_atmosphere.update_values() //Might as well update exterior_atmosphere.check_tile_graphic() return - var/list/exterior_atmos_composition = exterior_atmosphere + var/alist/exterior_atmos_composition = exterior_atmosphere exterior_atmosphere = new - if(islist(exterior_atmos_composition)) - for(var/gas in exterior_atmos_composition) - exterior_atmosphere.adjust_gas(gas, exterior_atmos_composition[gas], FALSE) + if(istype(exterior_atmos_composition, /alist)) + for(var/gas, gas_amount in exterior_atmos_composition) + exterior_atmosphere.adjust_gas(gas, gas_amount, FALSE) exterior_atmosphere.temperature = exterior_atmos_temp exterior_atmosphere.update_values() exterior_atmosphere.check_tile_graphic() diff --git a/code/modules/organs/internal/lungs.dm b/code/modules/organs/internal/lungs.dm index aeea20125422..934534fc6323 100644 --- a/code/modules/organs/internal/lungs.dm +++ b/code/modules/organs/internal/lungs.dm @@ -210,9 +210,9 @@ if(!failed_inhale) // Enough gas to tell we're being poisoned via chemical burns or whatever. var/poison_total = 0 if(poison_types) - for(var/gname in breath.gas) - if(poison_types[gname]) - poison_total += breath.gas[gname] + for(var/gas_type, gas_amount in breath.gas) + if(poison_types[gas_type]) + poison_total += gas_amount if(((poison_total/breath.total_moles)*breath_pressure) > safe_toxins_max) SET_HUD_ALERT(owner, HUD_TOX, 1) diff --git a/code/modules/overmap/_overmap.dm b/code/modules/overmap/_overmap.dm index 96d9180a2402..690abc887fc5 100644 --- a/code/modules/overmap/_overmap.dm +++ b/code/modules/overmap/_overmap.dm @@ -43,7 +43,7 @@ square = square.ChangeTurf(overmap_edge_type) else square = square.ChangeTurf(overmap_turf_type) - ChangeArea(square, A) + square.ChangeArea(A) /datum/overmap/proc/generate_overmap() testing("Building overmap [name]...") diff --git a/code/modules/overmap/planetoids/_planetoids.dm b/code/modules/overmap/planetoids/_planetoids.dm index 16ea48dfe92b..f28b871ef26b 100644 --- a/code/modules/overmap/planetoids/_planetoids.dm +++ b/code/modules/overmap/planetoids/_planetoids.dm @@ -56,9 +56,9 @@ if(atmosphere) if(user.skill_check(SKILL_SCIENCE, SKILL_EXPERT) || user.skill_check(SKILL_ATMOS, SKILL_EXPERT)) var/list/gases = list() - for(var/g in atmosphere.gas) - if(atmosphere.gas[g] > atmosphere.total_moles * 0.05) - var/decl/material/mat = GET_DECL(g) + for(var/gas_type, gas_amount in atmosphere.gas) + if(gas_amount > atmosphere.total_moles * 0.05) + var/decl/material/mat = GET_DECL(gas_type) gases += mat.gas_name . += "Atmosphere composition: [english_list(gases)]
" var/inaccuracy = rand(8,12)/10 diff --git a/code/modules/overmap/planetoids/planetoid_skybox.dm b/code/modules/overmap/planetoids/planetoid_skybox.dm index d9528a9bfc38..f0b30e4bc25b 100644 --- a/code/modules/overmap/planetoids/planetoid_skybox.dm +++ b/code/modules/overmap/planetoids/planetoid_skybox.dm @@ -27,10 +27,8 @@ var/list/colors = list() for(var/lvl in map_z) var/datum/level_data/level_data = SSmapping.levels_by_z[lvl] - ///#TODO: Check if the z-level is visible from space - for(var/g in level_data.exterior_atmosphere?.gas) - var/decl/material/mat = GET_DECL(g) - colors += mat.color + if(level_data.exterior_atmosphere) + colors += level_data.exterior_atmosphere.get_overall_color() if(length(colors)) return MixColors(colors) diff --git a/code/modules/overmap/ships/device_types/gas_thruster.dm b/code/modules/overmap/ships/device_types/gas_thruster.dm index 1f09c65b3187..1c9c32381827 100644 --- a/code/modules/overmap/ships/device_types/gas_thruster.dm +++ b/code/modules/overmap/ships/device_types/gas_thruster.dm @@ -74,12 +74,12 @@ if(!propellant || !length(propellant.gas) || !propellant.total_moles) return 0.01 // Divide by zero protection. - for(var/mat in propellant.gas) + for(var/mat, amt in propellant.gas) var/decl/material/gas/G = GET_DECL(mat) // 0.08 chosen to get the RATIO of the specific heat, we don't have cV/cP here, so this is a rough approximate. var/ratio = (G.gas_specific_heat / 25) + 0.8// These numbers are meaningless, just magic numbers to calibrate range. - ratio_specific_heat += ratio * (propellant.gas[mat] / propellant.total_moles) - ratio_specific_heat = ratio_specific_heat / length(propellant.gas) + ratio_specific_heat += ratio * (amt / propellant.total_moles) + ratio_specific_heat /= length(propellant.gas) if(ratio_specific_heat == 0 || ratio_specific_heat == 1) // rare case of avoiding a divide by zero error. ratio_specific_heat += 0.01 diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm index cd70fdbc44a5..b271e18090ea 100644 --- a/code/modules/power/singularity/collector.dm +++ b/code/modules/power/singularity/collector.dm @@ -64,7 +64,7 @@ var/global/list/rad_collectors = list() receive_pulse(12.5*(last_rads/max_rads)/(0.3+(last_rads/max_rads))) if(loaded_tank) - if(loaded_tank.air_contents.gas[/decl/material/gas/hydrogen] == 0) + if(!loaded_tank.air_contents.get_gas(/decl/material/gas/hydrogen)) investigate_log("out of fuel.","singulo") eject() else @@ -85,7 +85,8 @@ var/global/list/rad_collectors = list() toggle_power() user.visible_message("[user.name] turns \the [src] [active? "on":"off"].", \ "You turn \the [src] [active? "on":"off"].") - investigate_log("turned [active?"on":"off"] by [user.key]. [loaded_tank?"Fuel: [round(loaded_tank.air_contents.gas[/decl/material/gas/hydrogen]/0.29)]%":"It is empty"].","singulo") + // WHY DOES THIS DIVIDE BY 0.29 + investigate_log("turned [active?"on":"off"] by [user.key]. [loaded_tank?"Fuel: [round(loaded_tank.air_contents.get_gas(/decl/material/gas/hydrogen)/0.29)]%":"It is empty"].","singulo") else to_chat(user, SPAN_WARNING("The controls are locked!")) @@ -177,7 +178,7 @@ var/global/list/rad_collectors = list() /obj/machinery/rad_collector/proc/receive_pulse(var/pulse_strength) if(loaded_tank && active) var/power_produced = 0 - power_produced = min(100*loaded_tank.air_contents.gas[/decl/material/gas/hydrogen]*pulse_strength*pulse_coeff,max_power) + power_produced = min(100*loaded_tank.air_contents.get_gas(/decl/material/gas/hydrogen)*pulse_strength*pulse_coeff,max_power) generate_power(power_produced) last_power_new = power_produced return diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm index 7e498de80efc..7628644b405a 100644 --- a/code/modules/projectiles/projectile/change.dm +++ b/code/modules/projectiles/projectile/change.dm @@ -9,59 +9,57 @@ /obj/item/projectile/change/on_hit(var/atom/change) wabbajack(change) -/obj/item/projectile/change/proc/get_random_transformation_options(var/mob/M) +/obj/item/projectile/change/proc/get_random_transformation_options(var/mob/living/victim) . = list() - if(!isrobot(M)) + if(!isrobot(victim)) . += "robot" for(var/decl/species/species as anything in decls_repository.get_decls_of_subtype_unassociated(/decl/species)) . += species.uid - if(ishuman(M)) - var/mob/living/human/H = M - . -= H.species.uid + if(ishuman(victim)) + var/mob/living/human/human_victim = victim + . -= human_victim.species.uid -/obj/item/projectile/change/proc/apply_transformation(var/mob/M, var/choice) +/obj/item/projectile/change/proc/make_robot(var/mob/living/victim, robot_title = ASSIGNMENT_ROBOT) + return victim.Robotize(robot_title, skip_qdel = TRUE) + +/obj/item/projectile/change/proc/apply_transformation(var/mob/living/victim, var/choice) if(choice == "robot") - var/mob/living/silicon/robot/robot = new(get_turf(M)) - robot.set_gender(M.get_gender()) - robot.job = ASSIGNMENT_ROBOT - robot.central_processor = new /obj/item/organ/internal/brain_interface(robot) - transfer_key_from_mob_to_mob(M, robot) - return robot + return make_robot() if(decls_repository.get_decl_by_id(choice)) - var/mob/living/human/H = M - if(!istype(H)) - H = new(get_turf(M)) - H.set_gender(M.get_gender()) - H.name = "unknown" // This will cause set_species() to randomize the mob name. - H.real_name = H.name - H.change_species(choice) - H.universal_speak = TRUE + var/mob/living/human/human_victim = victim + if(!istype(human_victim)) + human_victim = new(get_turf(victim)) + human_victim.set_gender(victim.get_gender()) + human_victim.name = "unknown" // This will cause set_species() to randomize the mob name. + human_victim.real_name = human_victim.name + human_victim.change_species(choice) + human_victim.universal_speak = TRUE var/datum/preferences/A = new() - A.randomize_appearance_and_body_for(H) - return H + A.randomize_appearance_and_body_for(human_victim) + return human_victim -/obj/item/projectile/change/proc/wabbajack(var/mob/M) +/obj/item/projectile/change/proc/wabbajack(var/mob/living/victim) - if(!isliving(M) || M.stat == DEAD) + if(!isliving(victim) || victim.stat == DEAD) return - if(HAS_TRANSFORMATION_MOVEMENT_HANDLER(M)) + if(HAS_TRANSFORMATION_MOVEMENT_HANDLER(victim)) return - M.handle_pre_transformation() - var/choice = pick(get_random_transformation_options(M)) - var/mob/living/new_mob = apply_transformation(M, choice) + victim.handle_pre_transformation() + var/choice = pick(get_random_transformation_options(victim)) + var/mob/living/new_mob = apply_transformation(victim, choice) if(new_mob) new_mob.set_intent(I_FLAG_HARM) - new_mob.copy_abilities_from(M) - transfer_key_from_mob_to_mob(M, new_mob) + new_mob.copy_abilities_from(victim) + transfer_key_from_mob_to_mob(victim, new_mob) to_chat(new_mob, "Your form morphs into that of \a [choice].") else - new_mob = M + new_mob = victim if(new_mob) to_chat(new_mob, SPAN_WARNING("Your form morphs into that of \a [choice].")) - if(new_mob != M && !QDELETED(M)) - qdel(M) + if(new_mob != victim && !QDELETED(victim)) + qdel(victim) diff --git a/code/modules/random_map/random_map.dm b/code/modules/random_map/random_map.dm index 10c390dfcd47..c4bce943eefb 100644 --- a/code/modules/random_map/random_map.dm +++ b/code/modules/random_map/random_map.dm @@ -175,7 +175,8 @@ var/global/list/map_count = list() . = (newpath && !istype(T, newpath)) ? T.ChangeTurf(newpath) : T get_additional_spawns(map[current_cell], ., get_spawn_dir(x, y)) if(use_area) - ChangeArea(., use_area) + T = . + T.ChangeArea(use_area) /datum/random_map/proc/get_spawn_dir() return 0 diff --git a/code/modules/scanners/gas.dm b/code/modules/scanners/gas.dm index 397ea46d74bf..3637da7d02e4 100644 --- a/code/modules/scanners/gas.dm +++ b/code/modules/scanners/gas.dm @@ -57,14 +57,14 @@ . += "Pressure: [round(pressure,0.01)] kPa" var/perGas_add_string = "" - for(var/mix in mixture.gas) - var/percentage = round(mixture.gas[mix]/total_moles * 100, 0.01) + for(var/gas_type, gas_moles in mixture.gas) + var/percentage = round(gas_moles/total_moles * 100, 0.01) if(!percentage) continue - var/decl/material/mat = GET_DECL(mix) + var/decl/material/mat = GET_DECL(gas_type) switch(mode) if(MV_MODE) - perGas_add_string = ", Moles: [round(mixture.gas[mix], 0.01)]" + perGas_add_string = ", Moles: [round(gas_moles, 0.01)]" if(MAT_TRAIT_MODE) var/list/traits = list() if(mat.gas_flags & XGM_GAS_FUEL) diff --git a/code/modules/turbolift/turbolift_map.dm b/code/modules/turbolift/turbolift_map.dm index bbea91dd8cc4..d69a39fd5bb8 100644 --- a/code/modules/turbolift/turbolift_map.dm +++ b/code/modules/turbolift/turbolift_map.dm @@ -186,8 +186,8 @@ INITIALIZE_IMMEDIATE(/obj/abstract/turbolift_spawner) var/area_path = areas_to_use[az] var/area/A = locate(area_path) || new area_path() - for(var/T in floor_turfs) - ChangeArea(T, A) + for(var/turf/T as anything in floor_turfs) + T.ChangeArea(A) cfloor.set_area_ref("\ref[A]") // Place exterior doors. diff --git a/code/modules/xgm/xgm_gas_mixture.dm b/code/modules/xgm/xgm_gas_mixture.dm index d88010d37564..59b19c52794e 100644 --- a/code/modules/xgm/xgm_gas_mixture.dm +++ b/code/modules/xgm/xgm_gas_mixture.dm @@ -1,7 +1,16 @@ +// These variables are used to speed up certain calculations by using dot products. +var/global/alist/cached_specific_heat = alist() +var/global/alist/cached_molar_mass = alist() +var/global/alist/cached_mat_r = alist() +var/global/alist/cached_mat_g = alist() +var/global/alist/cached_mat_b = alist() +var/global/alist/cached_mat_a = alist() +var/global/alist/cached_mat_color_weight = alist() + /datum/gas_mixture //Associative list of gas moles. //Gases with 0 moles are not tracked and are pruned by update_values() - var/list/gas = list() + var/alist/gas = alist() //Temperature in Kelvin of this gas mix. var/temperature = 0 @@ -86,11 +95,12 @@ temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity if((group_multiplier != 1)||(giver.group_multiplier != 1)) - for(var/g in giver.gas) - gas[g] += giver.gas[g] * giver.group_multiplier / group_multiplier + var/scale_factor = giver.group_multiplier / group_multiplier + for(var/gas_type, gas_amount in giver.gas) + gas[gas_type] += gas_amount * scale_factor else - for(var/g in giver.gas) - gas[g] += giver.gas[g] + for(var/gas_type, gas_amount in giver.gas) + gas[gas_type] += gas_amount update_values() return TRUE @@ -105,11 +115,13 @@ gas.Cut() sharer.gas.Cut() - for(var/g in gas|sharer.gas) - var/comb = gas[g] + sharer.gas[g] - comb /= total_volume + sharer.total_volume - gas[g] = comb * total_volume - sharer.gas[g] = comb * sharer.total_volume + var/scale_factor = total_volume + sharer.total_volume + var/origin_scale_factor = total_volume / scale_factor + var/sharer_scale_factor = sharer.total_volume / scale_factor + for(var/gas_type in gas|sharer.gas) // we can only iterate keys here since merging alists doesn't combine values + var/comb = gas[gas_type] + sharer.gas[gas_type] + gas[gas_type] = comb * origin_scale_factor + sharer.gas[gas_type] = comb * sharer_scale_factor if(our_heatcap + share_heatcap) temperature = ((temperature * our_heatcap) + (sharer.temperature * share_heatcap)) / (our_heatcap + share_heatcap) @@ -123,12 +135,7 @@ //Returns the heat capacity of the gas mix based on the specific heat of the gases. /datum/gas_mixture/proc/heat_capacity() - . = 0 - for(var/g in gas) - var/decl/material/mat = GET_DECL(g) - . += mat.gas_specific_heat * gas[g] - . *= max(1, group_multiplier) - + return values_dot(gas, global.cached_specific_heat) * max(1, group_multiplier) //Adds or removes thermal energy. Returns the actual thermal energy change, as in the case of removing energy we can't go below TCMB. /datum/gas_mixture/proc/add_thermal_energy(var/thermal_energy) @@ -152,7 +159,6 @@ /datum/gas_mixture/proc/get_thermal_energy_change(var/new_temperature) return heat_capacity()*(max(new_temperature, 0) - temperature) - //Technically vacuum doesn't have a specific entropy. Just use a really big number (infinity would be ideal) here so that it's easy to add gas to vacuum and hard to take gas out. #define SPECIFIC_ENTROPY_VACUUM 150000 @@ -197,13 +203,8 @@ //Updates the total_moles count and trims any empty gases. /datum/gas_mixture/proc/update_values() - total_moles = 0 - for(var/g in gas) - if(gas[g] <= 0) - gas -= g - else - total_moles += gas[g] - + values_cut_under(gas, ATMOS_PRECISION) + total_moles = values_sum(gas) //Mark the cached color for update cached_mix_color = null @@ -222,9 +223,9 @@ var/datum/gas_mixture/removed = new - for(var/g in gas) - removed.gas[g] = QUANTIZE((gas[g] / total_moles) * amount) - gas[g] -= removed.gas[g] / group_multiplier + for(var/gas_type, gas_amount in gas) + removed.gas[gas_type] = QUANTIZE((gas_amount / total_moles) * amount) + gas[gas_type] -= removed.gas[gas_type] / group_multiplier removed.temperature = temperature update_values() @@ -244,9 +245,9 @@ var/datum/gas_mixture/removed = new removed.group_multiplier = out_group_multiplier - for(var/g in gas) - removed.gas[g] = (gas[g] * ratio * group_multiplier / out_group_multiplier) - gas[g] = gas[g] * (1 - ratio) + for(var/gas_type, gas_amount in gas) + removed.gas[gas_type] = (gas_amount * ratio * group_multiplier / out_group_multiplier) + gas[gas_type] = gas_amount * (1 - ratio) removed.temperature = temperature removed.total_volume = total_volume * group_multiplier / out_group_multiplier @@ -269,18 +270,18 @@ return removed var/sum = 0 - for(var/g in gas) - var/decl/material/mat = GET_DECL(g) - var/list/check = mat_flag ? mat.flags : mat.gas_flags + for(var/gas_type, gas_amount in gas) + var/decl/material/mat = GET_DECL(gas_type) + var/check = mat_flag ? mat.flags : mat.gas_flags if(check & flag) - sum += gas[g] + sum += gas_amount - for(var/g in gas) - var/decl/material/mat = GET_DECL(g) - var/list/check = mat_flag ? mat.flags : mat.gas_flags + for(var/gas_type, gas_amount in gas) + var/decl/material/mat = GET_DECL(gas_type) + var/check = mat_flag ? mat.flags : mat.gas_flags if(check & flag) - removed.gas[g] = QUANTIZE((gas[g] / sum) * amount) - gas[g] -= removed.gas[g] / group_multiplier + removed.gas[gas_type] = QUANTIZE((gas_amount / sum) * amount) + gas[gas_type] -= removed.gas[gas_type] / group_multiplier removed.temperature = temperature update_values() @@ -291,10 +292,10 @@ //Returns the amount of gas that has the given flag, in moles /datum/gas_mixture/proc/get_by_flag(flag) . = 0 - for(var/g in gas) - var/decl/material/mat = GET_DECL(g) + for(var/gas_type, gas_amount in gas) + var/decl/material/mat = GET_DECL(gas_type) if(mat.gas_flags & flag) - . += gas[g] + . += gas_amount //Copies gas and temperature from another gas_mixture. /datum/gas_mixture/proc/copy_from(const/datum/gas_mixture/sample) @@ -324,22 +325,22 @@ if(total_moles == 0 && sample.total_moles != 0 || sample.total_moles == 0 && total_moles != 0) return 0 - var/list/marked = list() - for(var/g in gas) - if((abs(gas[g] - sample.gas[g]) > MINIMUM_AIR_TO_SUSPEND) && \ - ((gas[g] < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g]) || \ - (gas[g] > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g]))) + var/alist/marked = alist() + for(var/gas_type, gas_amount in gas) + if((abs(gas_amount - sample.gas[gas_type]) > MINIMUM_AIR_TO_SUSPEND) && \ + ((gas_amount < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[gas_type]) || \ + (gas_amount > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[gas_type]))) return 0 - marked[g] = 1 + marked[gas_type] = 1 if(abs(return_pressure() - sample.return_pressure()) > MINIMUM_PRESSURE_DIFFERENCE_TO_SUSPEND) return 0 - for(var/g in sample.gas) - if(!marked[g]) - if((abs(gas[g] - sample.gas[g]) > MINIMUM_AIR_TO_SUSPEND) && \ - ((gas[g] < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g]) || \ - (gas[g] > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g]))) + for(var/sample_type, sample_moles in sample.gas) + if(!marked[sample_type]) + if((abs(gas[sample_type] - sample_moles) > MINIMUM_AIR_TO_SUSPEND) && \ + ((gas[sample_type] < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample_moles) || \ + (gas[sample_type] > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample_moles))) return 0 if(total_moles > MINIMUM_AIR_TO_SUSPEND) @@ -358,13 +359,13 @@ for(var/obj/effect/gas_overlay/O in graphic) if(gas[O.material.type] <= O.material.gas_overlay_limit) LAZYADD(graphic_remove, O) - for(var/g in gas) + for(var/gas_type, gas_amount in gas) + var/decl/material/mat = GET_DECL(gas_type) //Overlay isn't applied for this gas, check if it's valid and needs to be added. - var/decl/material/mat = GET_DECL(g) - if(!isnull(mat.gas_overlay_limit) && gas[g] > mat.gas_overlay_limit) - if(!LAZYACCESS(tile_overlay_cache, g)) - LAZYSET(tile_overlay_cache, g, new /obj/effect/gas_overlay(null, g)) - var/tile_overlay = tile_overlay_cache[g] + if(!isnull(mat.gas_overlay_limit) && gas_amount > mat.gas_overlay_limit) + if(!LAZYACCESS(tile_overlay_cache, gas_type)) + LAZYSET(tile_overlay_cache, gas_type, new /obj/effect/gas_overlay(null, gas_type)) + var/tile_overlay = tile_overlay_cache[gas_type] if(!(tile_overlay in graphic)) LAZYADD(graphic_add, tile_overlay) . = FALSE @@ -413,16 +414,16 @@ var/full_heat_capacity = heat_capacity() var/s_full_heat_capacity = other.heat_capacity() - var/list/avg_gas = list() + var/alist/avg_gas = alist() + var/scale_factor = (size + share_size) + var/self_scale_factor = size / scale_factor + var/other_scale_factor = share_size / scale_factor - for(var/g in gas) - avg_gas[g] += gas[g] * size + for(var/gas_type, gas_moles in gas) + avg_gas[gas_type] += gas_moles * self_scale_factor - for(var/g in other.gas) - avg_gas[g] += other.gas[g] * share_size - - for(var/g in avg_gas) - avg_gas[g] /= (size + share_size) + for(var/gas_type, gas_moles in other.gas) + avg_gas[gas_type] += gas_moles * other_scale_factor var/temp_avg = 0 if(full_heat_capacity + s_full_heat_capacity) @@ -433,10 +434,10 @@ ratio = sharing_lookup_table[connecting_tiles] //WOOT WOOT DO NOT TOUCH THIS. - for(var/g in avg_gas) - gas[g] = max(0, (gas[g] - avg_gas[g]) * (1 - ratio) + avg_gas[g]) + for(var/gas_type, gas_amount in avg_gas) + gas[gas_type] = max(0, (gas[gas_type] - gas_amount) * (1 - ratio) + gas_amount) if(!one_way) - other.gas[g] = max(0, (other.gas[g] - avg_gas[g]) * (1 - ratio) + avg_gas[g]) + other.gas[gas_type] = max(0, (other.gas[gas_type] - gas_amount) * (1 - ratio) + gas_amount) temperature = max(0, (temperature - temp_avg) * (1-ratio) + temp_avg) if(!one_way) @@ -459,14 +460,14 @@ var/total_thermal_energy = 0 var/total_heat_capacity = 0 - var/list/total_gas = list() + var/alist/total_gas = alist() for(var/datum/gas_mixture/gasmix in gases) total_volume += gasmix.total_volume var/temp_heatcap = gasmix.heat_capacity() total_thermal_energy += gasmix.temperature * temp_heatcap total_heat_capacity += temp_heatcap - for(var/g in gasmix.gas) - total_gas[g] += gasmix.gas[g] + for(var/gas_type, gas_amount in gasmix.gas) + total_gas[gas_type] += gas_amount if(total_volume > 0) var/datum/gas_mixture/combined = new(total_volume) @@ -481,8 +482,7 @@ combined.react() //Average out the gases - for(var/g in combined.gas) - combined.gas[g] /= total_volume + combined.divide(total_volume) //Update individual gas_mixtures for(var/datum/gas_mixture/gasmix in gases) @@ -493,10 +493,7 @@ return 1 /datum/gas_mixture/proc/get_mass() - . = 0 - for(var/g in gas) - var/decl/material/mat = GET_DECL(g) - . += gas[g] * mat.molar_mass * group_multiplier + return values_dot(gas, global.cached_molar_mass) * group_multiplier /datum/gas_mixture/proc/specific_mass() var/M = get_total_moles() @@ -507,30 +504,23 @@ ///Returns a color blended from all materials the gas mixture contains /datum/gas_mixture/proc/get_overall_color() if(!cached_mix_color) - if(!LAZYLEN(gas)) + if(!length(gas)) cached_mix_color = "#ffffffff" return cached_mix_color - if(LAZYLEN(gas) == 1) - var/decl/material/G = GET_DECL(gas[1]) - cached_mix_color = G.color + num2hex(G.opacity * 255) + if(length(gas) == 1) + for(var/gas_type in gas) + var/decl/material/G = GET_DECL(gas_type) + cached_mix_color = G.color + num2hex(G.opacity * 255) return cached_mix_color //If we really have to, add up all colors - var/list/colors = list(0, 0, 0, 0) - var/total_color_weight = 0 - - for(var/mat_path in gas) + cached_mix_color = rgb(255,255,255,255) + for(var/mat_path, mat_moles in gas) var/decl/material/G = GET_DECL(mat_path) if(G.color_weight <= 0) continue var/hex = uppertext(G.color) + num2hex(G.opacity * 255) - var/mod = gas[mat_path] * G.color_weight - colors[1] += HEX_RED(hex) * mod - colors[2] += HEX_GREEN(hex) * mod - colors[3] += HEX_BLUE(hex) * mod - colors[4] += HEX_ALPHA(hex) * mod - total_color_weight += mod - cached_mix_color = rgb(colors[1] / total_color_weight, colors[2] / total_color_weight, colors[3] / total_color_weight, colors[4] / total_color_weight) + cached_mix_color = BlendHSV(cached_mix_color, hex, (mat_moles * G.color_weight) / total_moles) return cached_mix_color diff --git a/code/unit_tests/atmospherics_tests.dm b/code/unit_tests/atmospherics_tests.dm index e28fcc06a378..ea7ed3b20eb3 100644 --- a/code/unit_tests/atmospherics_tests.dm +++ b/code/unit_tests/atmospherics_tests.dm @@ -62,7 +62,7 @@ test_cases = list( uphill = list( source = list( - initial_gas = list( + initial_gas = alist( /decl/material/gas/oxygen = 5, /decl/material/gas/nitrogen = 10, /decl/material/gas/carbon_dioxide = 5, @@ -72,7 +72,7 @@ temperature = T20C - 5, ), sink = list( - initial_gas = list( + initial_gas = alist( /decl/material/gas/oxygen = 10, /decl/material/gas/nitrogen = 20, /decl/material/gas/carbon_dioxide = 10, @@ -84,7 +84,7 @@ ), downhill = list( source = list( - initial_gas = list( + initial_gas = alist( /decl/material/gas/oxygen = 10, /decl/material/gas/nitrogen = 20, /decl/material/gas/carbon_dioxide = 10, @@ -94,7 +94,7 @@ temperature = T20C + 5, ), sink = list( - initial_gas = list( + initial_gas = alist( /decl/material/gas/oxygen = 5, /decl/material/gas/nitrogen = 10, /decl/material/gas/carbon_dioxide = 5, @@ -106,7 +106,7 @@ ), flat = list( source = list( - initial_gas = list( + initial_gas = alist( /decl/material/gas/oxygen = 10, /decl/material/gas/nitrogen = 20, /decl/material/gas/carbon_dioxide = 10, @@ -116,7 +116,7 @@ temperature = T20C, ), sink = list( - initial_gas = list( + initial_gas = alist( /decl/material/gas/oxygen = 10, /decl/material/gas/nitrogen = 20, /decl/material/gas/carbon_dioxide = 10, @@ -128,7 +128,7 @@ ), vacuum_sink = list( source = list( - initial_gas = list( + initial_gas = alist( /decl/material/gas/oxygen = 10, /decl/material/gas/nitrogen = 20, /decl/material/gas/carbon_dioxide = 10, @@ -138,17 +138,17 @@ temperature = T20C, ), sink = list( - initial_gas = list(), + initial_gas = alist(), temperature = 0, ), ), vacuum_source = list( source = list( - initial_gas = list(), + initial_gas = alist(), temperature = 0, ), sink = list( - initial_gas = list( + initial_gas = alist( /decl/material/gas/oxygen = 10, /decl/material/gas/nitrogen = 20, /decl/material/gas/carbon_dioxide = 10, diff --git a/maps/away/bearcat/bearcat.dm b/maps/away/bearcat/bearcat.dm index dc13ca07d873..c022e64c5308 100644 --- a/maps/away/bearcat/bearcat.dm +++ b/maps/away/bearcat/bearcat.dm @@ -89,16 +89,16 @@ door_color = COLOR_AMBER /turf/floor/usedup - initial_gas = list(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) + initial_gas = alist(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) /turf/floor/tiled/usedup - initial_gas = list(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) + initial_gas = alist(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) /turf/floor/tiled/dark/usedup - initial_gas = list(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) + initial_gas = alist(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) /turf/floor/tiled/white/usedup - initial_gas = list(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) + initial_gas = alist(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) /obj/abstract/landmark/corpse/deadcap name = "Dead Captain" diff --git a/maps/exodus/exodus.dm b/maps/exodus/exodus.dm index a5bb07e061cf..3553f269e878 100644 --- a/maps/exodus/exodus.dm +++ b/maps/exodus/exodus.dm @@ -7,6 +7,7 @@ #include "../../mods/content/beekeeping/_beekeeping.dme" #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/blob/_blob.dme" + #include "../../mods/content/brain_interface/_brain_interface.dme" #include "../../mods/content/corporate/_corporate.dme" #include "../../mods/content/government/_government.dme" #include "../../mods/content/integrated_electronics/_integrated_electronics.dme" diff --git a/maps/ministation/ministation-0.dmm b/maps/ministation/ministation-0.dmm index 45af5c6f8e6b..e3f4b0c453f8 100644 --- a/maps/ministation/ministation-0.dmm +++ b/maps/ministation/ministation-0.dmm @@ -10255,7 +10255,7 @@ dir = 1 }, /obj/machinery/turretid/stun{ - control_area = "\improper AI Upload Chamber"; + control_area = /area/ministation/ai_core; id_tag = "aihome"; pixel_y = -24; dir = 1 @@ -13371,7 +13371,6 @@ /obj/machinery/turretid/stun{ name = "AI Upload turret control"; id_tag = "upload"; - control_area = "\improper AI Upload Chamber"; pixel_y = -24; dir = 1 }, diff --git a/maps/ministation/ministation.dm b/maps/ministation/ministation.dm index a44a244232b9..cf34155e64f2 100644 --- a/maps/ministation/ministation.dm +++ b/maps/ministation/ministation.dm @@ -23,6 +23,7 @@ Twice... #include "../../mods/content/augments/_augments.dme" #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/blob/_blob.dme" + #include "../../mods/content/brain_interface/_brain_interface.dme" #include "../../mods/content/corporate/_corporate.dme" #include "../../mods/content/government/_government.dme" #include "../../mods/content/integrated_electronics/_integrated_electronics.dme" diff --git a/maps/modpack_testing/modpack_testing.dm b/maps/modpack_testing/modpack_testing.dm index d334f4879d6c..aed6b8e3022a 100644 --- a/maps/modpack_testing/modpack_testing.dm +++ b/maps/modpack_testing/modpack_testing.dm @@ -12,6 +12,7 @@ #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/biomods/_biomods.dme" #include "../../mods/content/blob/_blob.dme" + #include "../../mods/content/brain_interface/_brain_interface.dme" #include "../../mods/content/breath_holding/_breath_holding.dme" #include "../../mods/content/byond_membership/_byond_membership.dm" #include "../../mods/content/corporate/_corporate.dme" diff --git a/maps/planets/test_planet/test_planet.dm b/maps/planets/test_planet/test_planet.dm index 83c42703e654..9d7d0f324d71 100644 --- a/maps/planets/test_planet/test_planet.dm +++ b/maps/planets/test_planet/test_planet.dm @@ -7,7 +7,7 @@ /datum/gas_mixture/atmos_neutralia temperature = T20C - gas = list( + gas = alist( /decl/material/gas/oxygen = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD, ) diff --git a/maps/random_ruins/exoplanet_ruins/lodge/lodge.dm b/maps/random_ruins/exoplanet_ruins/lodge/lodge.dm index 893ebdb5c648..b92079557e2e 100644 --- a/maps/random_ruins/exoplanet_ruins/lodge/lodge.dm +++ b/maps/random_ruins/exoplanet_ruins/lodge/lodge.dm @@ -7,4 +7,4 @@ template_tags = TEMPLATE_TAG_HUMAN|TEMPLATE_TAG_HABITAT /turf/floor/wood/usedup - initial_gas = list(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) \ No newline at end of file + initial_gas = alist(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD) \ No newline at end of file diff --git a/maps/shaded_hills/levels/_levels.dm b/maps/shaded_hills/levels/_levels.dm index 411714f57c56..cf7081b88e51 100644 --- a/maps/shaded_hills/levels/_levels.dm +++ b/maps/shaded_hills/levels/_levels.dm @@ -9,7 +9,7 @@ ambient_light_level = 1 ambient_light_color = "#f3e6ca" strata = /decl/strata/shaded_hills - exterior_atmosphere = list( + exterior_atmosphere = alist( /decl/material/gas/oxygen = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD ) diff --git a/maps/tradeship/tradeship.dm b/maps/tradeship/tradeship.dm index 28f3b208c5a1..2101d73bb84f 100644 --- a/maps/tradeship/tradeship.dm +++ b/maps/tradeship/tradeship.dm @@ -20,6 +20,7 @@ #include "../../mods/content/beekeeping/_beekeeping.dme" #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/blob/_blob.dme" + #include "../../mods/content/brain_interface/_brain_interface.dme" #include "../../mods/content/breath_holding/_breath_holding.dme" #include "../../mods/content/corporate/_corporate.dme" #include "../../mods/content/dungeon_loot/_dungeon_loot.dme" diff --git a/mods/content/biomods/ears_animal.dm b/mods/content/biomods/ears_animal.dm index 3e39b6567dd1..71785dd8f32f 100644 --- a/mods/content/biomods/ears_animal.dm +++ b/mods/content/biomods/ears_animal.dm @@ -19,7 +19,7 @@ icon_state = "fox" uid = "accessory_ears_fox" -/decl/sprite_accessory/ears/biomods/antlers +/decl/sprite_accessory/ears/biomods/animal/antlers name = "Antlers" icon_state = "antlers" uid = "accessory_ears_antlers" diff --git a/mods/content/brain_interface/_brain_interface.dme b/mods/content/brain_interface/_brain_interface.dme new file mode 100644 index 000000000000..41d2d720d0d7 --- /dev/null +++ b/mods/content/brain_interface/_brain_interface.dme @@ -0,0 +1,11 @@ +#ifndef CONTENT_PACK_BRAIN_INTERFACE +#define CONTENT_PACK_BRAIN_INTERFACE +// BEGIN_INCLUDE +#include "brain_interface.dm" +#include "brain_interface_organ.dm" +#include "brainmob_overrides.dm" +#include "fabricator_recipes.dm" +#include "interface_radio.dm" +#include "misc_overrides.dm" +// END_INCLUDE +#endif \ No newline at end of file diff --git a/mods/content/brain_interface/brain_interface.dm b/mods/content/brain_interface/brain_interface.dm new file mode 100644 index 000000000000..e861d74778a9 --- /dev/null +++ b/mods/content/brain_interface/brain_interface.dm @@ -0,0 +1,3 @@ +/decl/modpack/brain_interface + name = "Brain Interface" + desc = "Adds brain-computer interfaces, used as organs in full-body prostheses and in cyborgs." diff --git a/code/modules/brain_interface/_brain_interface.dm b/mods/content/brain_interface/brain_interface_organ.dm similarity index 98% rename from code/modules/brain_interface/_brain_interface.dm rename to mods/content/brain_interface/brain_interface_organ.dm index abd19c34b0f9..6696cc39b37f 100644 --- a/code/modules/brain_interface/_brain_interface.dm +++ b/mods/content/brain_interface/brain_interface_organ.dm @@ -5,7 +5,7 @@ organ_tag = BP_BRAIN parent_organ = BP_HEAD origin_tech = @'{"biotech":3}' - icon = 'icons/obj/items/brain_interface_organic.dmi' + icon = 'mods/content/brain_interface/icons/brain_interface_organic.dmi' icon_state = ICON_STATE_WORLD req_access = list(access_robotics) material = /decl/material/solid/metal/steel diff --git a/mods/content/brain_interface/brainmob_overrides.dm b/mods/content/brain_interface/brainmob_overrides.dm new file mode 100644 index 000000000000..d01d72a31d91 --- /dev/null +++ b/mods/content/brain_interface/brainmob_overrides.dm @@ -0,0 +1,35 @@ +/mob/living/brain/get_radio() + var/obj/item/organ/internal/brain_interface/container = get_container() + if(istype(container)) + return container.get_radio() + +/mob/living/brain/get_death_message(gibbed) + var/obj/item/organ/internal/brain_interface/container = get_container() + if(!gibbed && istype(container)) + return "beeps shrilly as \the [container] flatlines!" + return ..() + +/mob/living/brain/death(gibbed) + var/obj/item/organ/internal/brain_interface/container = get_container() + . = ..() + if(. && istype(container) && !QDELETED(container)) + container.update_icon() + +/mob/living/brain/gib(do_gibs = TRUE) + var/obj/item/organ/internal/brain_interface/container = get_container() + . = ..() + if(. && istype(container) && !QDELETED(container)) + qdel(container) + +/mob/living/brain/on_container_login(obj/item/organ/internal/container) + var/obj/item/organ/internal/brain_interface/interface = container + if(istype(interface)) + interface.locked = TRUE + . = ..() + +/mob/living/brain/is_in_interface() + var/container = get_container() + return ..() || istype(container, /obj/item/organ/internal/brain_interface) + +/mob/living/brain/check_mob_can_emote(var/emote_type, allow_brain_emote = FALSE) + return ..(emote_type, istype(get_container(), /obj/item/organ/internal/brain_interface)) diff --git a/mods/content/brain_interface/fabricator_recipes.dm b/mods/content/brain_interface/fabricator_recipes.dm new file mode 100644 index 000000000000..9ccce7c6fddc --- /dev/null +++ b/mods/content/brain_interface/fabricator_recipes.dm @@ -0,0 +1,5 @@ +/datum/fabricator_recipe/protolathe/brains/mmi + path = /obj/item/organ/internal/brain_interface/empty + +/datum/fabricator_recipe/protolathe/brains/mmi_radio + path = /obj/item/organ/internal/brain_interface/radio_enabled/empty \ No newline at end of file diff --git a/icons/obj/items/brain_interface_organic.dmi b/mods/content/brain_interface/icons/brain_interface_organic.dmi similarity index 100% rename from icons/obj/items/brain_interface_organic.dmi rename to mods/content/brain_interface/icons/brain_interface_organic.dmi diff --git a/code/modules/brain_interface/interface_radio.dm b/mods/content/brain_interface/interface_radio.dm similarity index 100% rename from code/modules/brain_interface/interface_radio.dm rename to mods/content/brain_interface/interface_radio.dm diff --git a/mods/content/brain_interface/misc_overrides.dm b/mods/content/brain_interface/misc_overrides.dm new file mode 100644 index 000000000000..9c11536d62cd --- /dev/null +++ b/mods/content/brain_interface/misc_overrides.dm @@ -0,0 +1,31 @@ +/datum/trader/devices/New() + LAZYSET(possible_trading_items, /obj/item/organ/internal/brain_interface, TRADER_SUBTYPES_ONLY) + . = ..() + +/datum/controller/subsystem/robots/PreInit() + . = ..() + LAZYSET(mob_types_by_title, "cyborg, flying", /mob/living/silicon/robot/flying) + LAZYSET(processor_types_by_title, "cyborg", /obj/item/organ/internal/brain_interface) + LAZYSET(processor_types_by_title, "cyborg, flying", /obj/item/organ/internal/brain_interface) + +// Override to use MMIs for mobs with brains +/obj/item/projectile/change/make_robot(var/mob/living/victim, robot_title = ASSIGNMENT_ROBOT) + var/obj/item/organ/internal/brain/victim_brain = victim.get_organ(BP_BRAIN, /obj/item/organ/internal/brain) + if(istype(victim_brain) && victim_brain.can_use_brain_interface) + robot_title = "Cyborg" + return ..(victim, robot_title) + +/obj/item/robot_parts/robot_suit/is_valid_processor(obj/item/used_item) + return ..() || istype(used_item, /obj/item/organ/internal/brain_interface) + +/decl/bodytype/prosthetic/Initialize() + LAZYSET(has_organ, BP_BRAIN, /obj/item/organ/internal/brain_interface) + . = ..() + +/obj/item/rig_module/ai_container/Initialize(mapload) + simple_insert_types |= /obj/item/organ/internal/brain_interface + . = ..() + +/obj/item/gripper/research/Initialize(ml, material_key) + can_hold += /obj/item/organ/internal/brain_interface + . = ..() diff --git a/mods/content/government/ruins/ec_old_crash/ec_old_crash.dm b/mods/content/government/ruins/ec_old_crash/ec_old_crash.dm index bc42e4e157af..4942a9d83b02 100644 --- a/mods/content/government/ruins/ec_old_crash/ec_old_crash.dm +++ b/mods/content/government/ruins/ec_old_crash/ec_old_crash.dm @@ -43,10 +43,10 @@ external_pressure_bound = 0.25 ATM /turf/floor/tiled/lowpressure - initial_gas = list(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD) + initial_gas = alist(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD) /turf/floor/tiled/white/lowpressure - initial_gas = list(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD) + initial_gas = alist(/decl/material/gas/carbon_dioxide = MOLES_O2STANDARD) /obj/item/disk/astrodata name = "astronomical data disk" diff --git a/mods/content/integrated_electronics/components/manipulation.dm b/mods/content/integrated_electronics/components/manipulation.dm index 4148ac842ee5..0a231032e345 100644 --- a/mods/content/integrated_electronics/components/manipulation.dm +++ b/mods/content/integrated_electronics/components/manipulation.dm @@ -652,9 +652,11 @@ aicard = null controlling = null +/obj/item/integrated_circuit/manipulation/ai/proc/can_load_ai(obj/item/used_item, mob/user) + return istype(used_item, /obj/item/aicard) || istype(used_item, /obj/item/paicard) || istype(used_item, /obj/item/organ/internal/brain/robotic) /obj/item/integrated_circuit/manipulation/ai/attackby(var/obj/item/used_item, var/mob/user) - if(is_type_in_list(used_item, list(/obj/item/aicard, /obj/item/paicard, /obj/item/organ/internal/brain_interface))) + if(can_load_ai(used_item, user)) load_ai(user, used_item) return TRUE else return ..() diff --git a/mods/content/standard_jobs/jobs/synthetics.dm b/mods/content/standard_jobs/jobs/synthetics.dm index 23f768d4ac62..cbea8c6bf826 100644 --- a/mods/content/standard_jobs/jobs/synthetics.dm +++ b/mods/content/standard_jobs/jobs/synthetics.dm @@ -70,7 +70,7 @@ /datum/job/standard/robot/handle_variant_join(var/mob/living/human/H, var/alt_title) if(H) - return H.Robotize(SSrobots.get_mob_type_by_title(alt_title || title)) + return H.Robotize(alt_title || title) /datum/job/standard/robot/equip_job(var/mob/living/human/H) return !!H diff --git a/mods/gamemodes/cult/abilities/construct.dm b/mods/gamemodes/cult/abilities/construct.dm index 60138eaba356..bbf1a5bc0de3 100644 --- a/mods/gamemodes/cult/abilities/construct.dm +++ b/mods/gamemodes/cult/abilities/construct.dm @@ -2,10 +2,9 @@ /decl/ability/cult/construct name = "Artificer" desc = "This spell conjures a construct which may be controlled by shades." - target_selector = /decl/ability_targeting/clear_turf + target_selector = /decl/ability_targeting/clear_turf/construct overlay_icon = 'mods/gamemodes/cult/icons/effects.dmi' overlay_icon_state = "sparkles" - target_selector = /decl/ability_targeting/clear_turf/construct var/summon_type = /obj/structure/constructshell /decl/ability_targeting/clear_turf/construct/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) @@ -14,14 +13,14 @@ return FALSE return ..() && !istype(target, cult_ability.summon_type) && !(locate(cult_ability.summon_type) in target) -/decl/ability/cult/construct/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) +/decl/ability/cult/construct/apply_ability_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) . = ..() var/turf/target_turf = get_turf(hit_target) if(istype(target_turf)) if(ispath(summon_type, /turf)) target_turf = target_turf.ChangeTurf(summon_type, TRUE, FALSE, TRUE, TRUE, FALSE) if(target_turf) // We reapply effects as target no longer exists. - apply_effect_to(user, target_turf, metadata) + apply_ability_effect_to(user, target_turf, metadata) else if(ispath(summon_type, /atom)) new summon_type(target_turf) @@ -87,7 +86,7 @@ return TRUE return FALSE -/decl/ability/cult/construct/pylon/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) +/decl/ability/cult/construct/pylon/apply_ability_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) for(var/obj/structure/cult/pylon/P in get_turf(hit_target)) if(P.isbroken) P.repair(user) diff --git a/mods/gamemodes/cult/abilities/harvest.dm b/mods/gamemodes/cult/abilities/harvest.dm index 49569d6a25ef..dc8bfc1002ff 100644 --- a/mods/gamemodes/cult/abilities/harvest.dm +++ b/mods/gamemodes/cult/abilities/harvest.dm @@ -9,7 +9,7 @@ prepare_message_3p_str = "Space around $USER$ begins to bubble and decay as a terrible vista begins to intrude..." prepare_message_1p_str = "You bore through space and time, seeking the essence of the Geometer of Blood." fail_cast_1p_str = "Reality reasserts itself, preventing your return to Nar-Sie." - target_selector = /decl/ability_targeting/living_mob + target_selector = /decl/ability_targeting/single_atom/living_mob /decl/ability/cult/construct/harvest/can_use_ability(mob/user, list/metadata, silent) . = ..() @@ -22,7 +22,7 @@ to_chat(user, SPAN_DANGER("You cannot sense the Geometer of Blood!")) return FALSE -/decl/ability/cult/construct/harvest/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) +/decl/ability/cult/construct/harvest/apply_ability_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) ..() var/destination = null for(var/obj/effect/narsie/N in global.narsie_list) diff --git a/mods/pyrelight/datum/wyrdling/ears.dm b/mods/pyrelight/datum/wyrdling/ears.dm index 639e675d0684..278dd93c7dba 100644 --- a/mods/pyrelight/datum/wyrdling/ears.dm +++ b/mods/pyrelight/datum/wyrdling/ears.dm @@ -1,2 +1,2 @@ /decl/sprite_accessory/ears/biomods/animal - //required_traits = list(/decl/trait/wyrd/wild) + required_traits = list(/decl/trait/wyrd/wild) diff --git a/mods/pyrelight/datum/wyrdling/tails.dm b/mods/pyrelight/datum/wyrdling/tails.dm index 3f93a80f1681..44203ca2433d 100644 --- a/mods/pyrelight/datum/wyrdling/tails.dm +++ b/mods/pyrelight/datum/wyrdling/tails.dm @@ -1,2 +1,2 @@ /decl/sprite_accessory/tail/biomods - //required_traits = list(/decl/trait/wyrd/wild) + required_traits = list(/decl/trait/wyrd/wild) diff --git a/mods/species/ascent/turfs/ship.dm b/mods/species/ascent/turfs/ship.dm index 320a2d8c30e2..03e991d57619 100644 --- a/mods/species/ascent/turfs/ship.dm +++ b/mods/species/ascent/turfs/ship.dm @@ -43,7 +43,7 @@ _base_flooring = /decl/flooring/plating/ascent icon_state = "curvy" icon = 'icons/turf/flooring/alium.dmi' - initial_gas = list( + initial_gas = alist( /decl/material/gas/methyl_bromide = MOLES_CELLSTANDARD * 0.5, /decl/material/gas/oxygen = MOLES_CELLSTANDARD * 0.5 ) @@ -58,7 +58,7 @@ icon_state = "jaggy" color = COLOR_GRAY40 _flooring = /decl/flooring/tiling_ascent - initial_gas = list( + initial_gas = alist( /decl/material/gas/methyl_bromide = MOLES_CELLSTANDARD * 0.5, /decl/material/gas/oxygen = MOLES_CELLSTANDARD * 0.5 ) diff --git a/mods/~compatibility/patches/circuits.dm b/mods/~compatibility/patches/circuits.dm index afa15ae3f36c..ed8e9ad9b1ef 100644 --- a/mods/~compatibility/patches/circuits.dm +++ b/mods/~compatibility/patches/circuits.dm @@ -9,4 +9,8 @@ // Add augment assembly for circuits. #ifdef CONTENT_PACK_AUGMENTS #include "circuits/augment_circuits.dm" +#endif +// Add support for MMIs to the AI manipulator circuit. +#ifdef CONTENT_PACK_BRAIN_INTERFACE +#include "circuits/brain_interface_circuits.dm" #endif \ No newline at end of file diff --git a/mods/~compatibility/patches/circuits/brain_interface_circuits.dm b/mods/~compatibility/patches/circuits/brain_interface_circuits.dm new file mode 100644 index 000000000000..83d0b5c9c6c9 --- /dev/null +++ b/mods/~compatibility/patches/circuits/brain_interface_circuits.dm @@ -0,0 +1,2 @@ +/obj/item/integrated_circuit/manipulation/ai/can_load_ai(obj/item/used_item, mob/user) + return ..() || istype(used_item, /obj/item/organ/internal/brain_interface) \ No newline at end of file diff --git a/nebula.dme b/nebula.dme index 0deecff31456..b40eee57081c 100644 --- a/nebula.dme +++ b/nebula.dme @@ -1849,8 +1849,6 @@ #include "code\modules\bodytype\bodytype_prosthetic_models.dm" #include "code\modules\bodytype\bodytype_quadruped.dm" #include "code\modules\bodytype\bodytype_random.dm" -#include "code\modules\brain_interface\_brain_interface.dm" -#include "code\modules\brain_interface\interface_radio.dm" #include "code\modules\butchery\_butchery.dm" #include "code\modules\butchery\butchery_data.dm" #include "code\modules\butchery\butchery_data_animal.dm" @@ -2772,8 +2770,8 @@ #include "code\modules\materials\stack_types\material_stack_misc.dm" #include "code\modules\materials\stack_types\material_stack_nail.dm" #include "code\modules\materials\stack_types\material_stack_ore.dm" +#include "code\modules\mechs\_mech.dm" #include "code\modules\mechs\_mech_setup.dm" -#include "code\modules\mechs\mech.dm" #include "code\modules\mechs\mech_construction.dm" #include "code\modules\mechs\mech_damage.dm" #include "code\modules\mechs\mech_damage_immunity.dm" @@ -2796,6 +2794,7 @@ #include "code\modules\mechs\equipment\combat_projectile.dm" #include "code\modules\mechs\equipment\engineering.dm" #include "code\modules\mechs\equipment\medical.dm" +#include "code\modules\mechs\equipment\mounted_system.dm" #include "code\modules\mechs\equipment\utility.dm" #include "code\modules\mechs\interface\_interface.dm" #include "code\modules\mechs\premade\_premade.dm"