diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index ab2ba54431..0af06dc005 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -18,6 +18,8 @@ SUBSYSTEM_DEF(mapping) var/list/shuttle_templates = list() var/list/shelter_templates = list() + var/list/areas_in_z = list() + var/loading_ruins = FALSE /datum/controller/subsystem/mapping/PreInit() diff --git a/code/datums/looping_sounds/weather.dm b/code/datums/looping_sounds/weather.dm new file mode 100644 index 0000000000..1867a097d3 --- /dev/null +++ b/code/datums/looping_sounds/weather.dm @@ -0,0 +1,47 @@ +/datum/looping_sound/active_outside_ashstorm + mid_sounds = list( + 'sound/weather/ashstorm/outside/active_mid1.ogg'=1, + 'sound/weather/ashstorm/outside/active_mid1.ogg'=1, + 'sound/weather/ashstorm/outside/active_mid1.ogg'=1 + ) + mid_length = 80 + start_sound = 'sound/weather/ashstorm/outside/active_start.ogg' + start_length = 130 + end_sound = 'sound/weather/ashstorm/outside/active_end.ogg' + volume = 80 + +/datum/looping_sound/active_inside_ashstorm + mid_sounds = list( + 'sound/weather/ashstorm/inside/active_mid1.ogg'=1, + 'sound/weather/ashstorm/inside/active_mid2.ogg'=1, + 'sound/weather/ashstorm/inside/active_mid3.ogg'=1 + ) + mid_length = 80 + start_sound = 'sound/weather/ashstorm/inside/active_start.ogg' + start_length = 130 + end_sound = 'sound/weather/ashstorm/inside/active_end.ogg' + volume = 80 + +/datum/looping_sound/weak_outside_ashstorm + mid_sounds = list( + 'sound/weather/ashstorm/outside/weak_mid1.ogg'=1, + 'sound/weather/ashstorm/outside/weak_mid2.ogg'=1, + 'sound/weather/ashstorm/outside/weak_mid3.ogg'=1 + ) + mid_length = 80 + start_sound = 'sound/weather/ashstorm/outside/weak_start.ogg' + start_length = 130 + end_sound = 'sound/weather/ashstorm/outside/weak_end.ogg' + volume = 50 + +/datum/looping_sound/weak_inside_ashstorm + mid_sounds = list( + 'sound/weather/ashstorm/inside/weak_mid1.ogg'=1, + 'sound/weather/ashstorm/inside/weak_mid2.ogg'=1, + 'sound/weather/ashstorm/inside/weak_mid3.ogg'=1 + ) + mid_length = 80 + start_sound = 'sound/weather/ashstorm/inside/weak_start.ogg' + start_length = 130 + end_sound = 'sound/weather/ashstorm/inside/weak_end.ogg' + volume = 50 \ No newline at end of file diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm index a1dc9ece69..14133c6a11 100644 --- a/code/datums/weather/weather_types/ash_storm.dm +++ b/code/datums/weather/weather_types/ash_storm.dm @@ -5,18 +5,15 @@ telegraph_message = "An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter." telegraph_duration = 300 - telegraph_sound = 'sound/lavaland/ash_storm_windup.ogg' telegraph_overlay = "light_ash" weather_message = "Smoldering clouds of scorching ash billow down around you! Get inside!" weather_duration_lower = 600 weather_duration_upper = 1200 - weather_sound = 'sound/lavaland/ash_storm_start.ogg' weather_overlay = "ash_storm" end_message = "The shrieking wind whips away the last of the ash and falls to its usual murmur. It should be safe to go outside now." end_duration = 300 - end_sound = 'sound/lavaland/ash_storm_end.ogg' end_overlay = "light_ash" area_type = /area/lavaland/surface/outdoors @@ -26,6 +23,53 @@ probability = 90 + var/datum/looping_sound/active_outside_ashstorm/sound_ao = new(list(), FALSE, TRUE) + var/datum/looping_sound/active_inside_ashstorm/sound_ai = new(list(), FALSE, TRUE) + var/datum/looping_sound/weak_outside_ashstorm/sound_wo = new(list(), FALSE, TRUE) + var/datum/looping_sound/weak_inside_ashstorm/sound_wi = new(list(), FALSE, TRUE) + +/datum/weather/ash_storm/telegraph() + . = ..() + var/list/inside_areas = list() + var/list/outside_areas = list() + var/list/eligible_areas = SSmapping.areas_in_z["[target_z]"] + for(var/i in 1 to eligible_areas.len) + var/area/place = eligible_areas[i] + if(place.outdoors) + outside_areas += place + else + inside_areas += place + CHECK_TICK + + sound_ao.output_atoms = outside_areas + sound_ai.output_atoms = inside_areas + sound_wo.output_atoms = outside_areas + sound_wi.output_atoms = inside_areas + + sound_wo.start() + sound_wi.start() + +/datum/weather/ash_storm/start() + . = ..() + sound_wo.stop() + sound_wi.stop() + + sound_ao.start() + sound_ai.start() + +/datum/weather/ash_storm/wind_down() + . = ..() + sound_ao.stop() + sound_ai.stop() + + sound_wo.start() + sound_wi.start() + +/datum/weather/ash_storm/end() + . = ..() + sound_wo.stop() + sound_wi.stop() + /datum/weather/ash_storm/proc/is_ash_immune(mob/living/L) if(ismecha(L.loc)) //Mechs are immune return TRUE @@ -50,7 +94,6 @@ desc = "A passing ash storm blankets the area in harmless embers." weather_message = "Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by..." - weather_sound = 'sound/lavaland/ash_storm_windup.ogg' weather_overlay = "light_ash" end_message = "The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet." diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 2d372d4c33..3b5e5d5d68 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -132,6 +132,22 @@ GLOBAL_LIST_EMPTY(teleportlocs) if(!IS_DYNAMIC_LIGHTING(src)) add_overlay(/obj/effect/fullbright) + if(contents.len) + var/list/areas_in_z = SSmapping.areas_in_z + var/z + for(var/i in 1 to contents.len) + var/atom/thing = contents[i] + if(!thing) + continue + z = thing.z + break + if(!z) + WARNING("No z found for [src]") + return + if(!areas_in_z["[z]"]) + areas_in_z["[z]"] = list() + areas_in_z["[z]"] += src + /area/Destroy() STOP_PROCESSING(SSobj, src) return ..() diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index d9d47bd771..63900d0f89 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -273,6 +273,7 @@ Credit where due: if(plasmaman && !visualsOnly) //If we need to breathe from the plasma tank, we should probably start doing that H.internal = H.get_item_for_held_index(2) H.update_internals_hud_icon(1) + H.sec_hud_set_ID() /obj/item/paper/servant_primer name = "The Ark And You: A Primer On Servitude" diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 43582b99a3..f5aec83c4c 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -83,7 +83,7 @@ /datum/game_mode/traitor/proc/add_latejoin_traitor(datum/mind/character) var/datum/antagonist/traitor/new_antag = new antag_datum(character) new_antag.should_specialise = TRUE - character.add_antag_datum(antag_datum) + character.add_antag_datum(new_antag) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 60260d2a4f..286bcee1f8 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -506,3 +506,14 @@ Class Procs: . = ..() if (AM == occupant) occupant = null + +/obj/machinery/proc/adjust_item_drop_location(atom/movable/AM) // Adjust item drop location to a 3x3 grid inside the tile, returns slot id from 0 to 8 + var/md5 = md5(AM.name) // Oh, and it's deterministic too. A specific item will always drop from the same slot. +#if DM_VERSION > 511 +#warn Refactor the loop in /obj/machinery/proc/adjust_item_drop_location() to make use of 512's list-like access to characters in a string +#endif + for (var/i in 1 to 32) + . += hex2num(copytext(md5,i,i+1)) + . = . % 9 + AM.pixel_x = -8 + ((.%3)*8) + AM.pixel_y = -8 + (round( . / 3)*8) \ No newline at end of file diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index 10c0b7e39a..ccacd133e8 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -106,7 +106,7 @@ if(recharge_port && !QDELETED(recharge_port)) data["recharge_port"] = list("mech" = null) if(recharge_port.recharging_mech && !QDELETED(recharge_port.recharging_mech)) - data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mech.obj_integrity, "max_integrity" = recharge_port.recharging_mech.max_integrity, "cell" = null) + data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mech.obj_integrity, "maxhealth" = recharge_port.recharging_mech.max_integrity, "cell" = null) if(recharge_port.recharging_mech.cell && !QDELETED(recharge_port.recharging_mech.cell)) data["recharge_port"]["mech"]["cell"] = list( "critfail" = recharge_port.recharging_mech.cell.crit_fail, diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 915279d7fb..ade619ec6b 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -301,6 +301,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM item_state = "spliffoff" smoketime = 180 chem_volume = 50 + list_reagents = null /obj/item/clothing/mask/cigarette/rollie/New() ..() diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 5f4d02fd8e..fd56c6283f 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -210,6 +210,7 @@ item_state = "lamp" lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' righthand_file = 'icons/mob/inhands/items_righthand.dmi' + force = 10 brightness_on = 5 w_class = WEIGHT_CLASS_BULKY flags_1 = CONDUCT_1 diff --git a/code/game/objects/items/devices/instruments.dm b/code/game/objects/items/devices/instruments.dm index acdfa1bc79..06e8898e15 100644 --- a/code/game/objects/items/devices/instruments.dm +++ b/code/game/objects/items/devices/instruments.dm @@ -2,6 +2,7 @@ /obj/item/device/instrument name = "generic instrument" resistance_flags = FLAMMABLE + force = 10 max_integrity = 100 icon = 'icons/obj/musician.dmi' lefthand_file = 'icons/mob/inhands/equipment/instruments_lefthand.dmi' @@ -49,7 +50,6 @@ desc = "A wooden musical instrument with four strings and a bow. \"The devil went down to space, he was looking for an assistant to grief.\"" icon_state = "violin" item_state = "violin" - force = 10 hitsound = "swing_hit" instrumentId = "violin" @@ -80,7 +80,6 @@ icon_state = "guitar" item_state = "guitar" instrumentExt = "ogg" - force = 10 attack_verb = list("played metal on", "serenaded", "crashed", "smashed") hitsound = 'sound/weapons/stringsmash.ogg' instrumentId = "guitar" @@ -185,6 +184,7 @@ /obj/item/device/instrument/recorder name = "recorder" desc = "Just like in school, playing ability and all." + force = 5 icon_state = "recorder" item_state = "recorder" instrumentId = "recorder" diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm index f9224682a0..3821f6206b 100644 --- a/code/game/objects/items/devices/lightreplacer.dm +++ b/code/game/objects/items/devices/lightreplacer.dm @@ -52,6 +52,7 @@ flags_1 = CONDUCT_1 slot_flags = SLOT_BELT origin_tech = "magnets=3;engineering=4" + force = 8 var/max_uses = 20 var/uses = 0 diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index ef914666c8..ada7b613e4 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -51,7 +51,7 @@ origin_tech = "syndicate=3" icon_state = "syndie_headset" item_state = "syndie_headset" - flags_2 = BANG_PROTECT_2 + flags_2 = BANG_PROTECT_2 | NO_EMP_WIRES_2 /obj/item/device/radio/headset/syndicate/alt/leader name = "team leader headset" @@ -80,7 +80,7 @@ desc = "This is used by your elite security force. Protects ears from flashbangs.\nTo access the security channel, use :s." icon_state = "sec_headset_alt" item_state = "sec_headset_alt" - flags_2 = BANG_PROTECT_2 + flags_2 = BANG_PROTECT_2 | NO_EMP_WIRES_2 /obj/item/device/radio/headset/headset_eng name = "engineering radio headset" @@ -132,7 +132,7 @@ desc = "The headset of the boss. Protects ears from flashbangs.\nChannels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :v - service, :m - medical, :n - science." icon_state = "com_headset_alt" item_state = "com_headset_alt" - flags_2 = BANG_PROTECT_2 + flags_2 = BANG_PROTECT_2 | NO_EMP_WIRES_2 /obj/item/device/radio/headset/heads/rd name = "\proper the research director's headset" @@ -151,7 +151,7 @@ desc = "The headset of the man in charge of keeping order and protecting the station. Protects ears from flashbangs.\nTo access the security channel, use :s. For command, use :c." icon_state = "com_headset_alt" item_state = "com_headset_alt" - flags_2 = BANG_PROTECT_2 + flags_2 = BANG_PROTECT_2 | NO_EMP_WIRES_2 /obj/item/device/radio/headset/heads/ce name = "\proper the chief engineer's headset" @@ -205,7 +205,7 @@ icon_state = "cent_headset_alt" item_state = "cent_headset_alt" keyslot = null - flags_2 = BANG_PROTECT_2 + flags_2 = BANG_PROTECT_2 | NO_EMP_WIRES_2 /obj/item/device/radio/headset/ai name = "\proper Integrated Subspace Transceiver " diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 18ba79ae94..7675c09776 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -29,6 +29,7 @@ var/emped = 0 //Highjacked to track the number of consecutive EMPs on the radio, allowing consecutive EMP's to stack properly. // "Example" = FREQ_LISTENING|FREQ_BROADCASTING flags_1 = CONDUCT_1 | HEAR_1 + flags_2 = NO_EMP_WIRES_2 slot_flags = SLOT_BELT throw_speed = 3 throw_range = 7 diff --git a/code/game/objects/items/grenades/grenade.dm b/code/game/objects/items/grenades/grenade.dm index bf2f6dd4bb..e444ecce25 100644 --- a/code/game/objects/items/grenades/grenade.dm +++ b/code/game/objects/items/grenades/grenade.dm @@ -1,50 +1,50 @@ -/obj/item/grenade - name = "grenade" - desc = "It has an adjustable timer." - w_class = WEIGHT_CLASS_SMALL - icon = 'icons/obj/grenade.dmi' - icon_state = "grenade" - item_state = "flashbang" - lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' - throw_speed = 3 - throw_range = 7 - flags_1 = CONDUCT_1 - slot_flags = SLOT_BELT - resistance_flags = FLAMMABLE - max_integrity = 40 - var/active = 0 - var/det_time = 50 - var/display_timer = 1 - -/obj/item/grenade/deconstruct(disassembled = TRUE) - if(!disassembled) - prime() - if(!QDELETED(src)) - qdel(src) - -/obj/item/grenade/proc/clown_check(mob/living/carbon/human/user) - if(user.disabilities & CLUMSY && prob(50)) - to_chat(user, "Huh? How does this thing work?") +/obj/item/grenade + name = "grenade" + desc = "It has an adjustable timer." + w_class = WEIGHT_CLASS_SMALL + icon = 'icons/obj/grenade.dmi' + icon_state = "grenade" + item_state = "flashbang" + lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' + throw_speed = 3 + throw_range = 7 + flags_1 = CONDUCT_1 + slot_flags = SLOT_BELT + resistance_flags = FLAMMABLE + max_integrity = 40 + var/active = 0 + var/det_time = 50 + var/display_timer = 1 + +/obj/item/grenade/deconstruct(disassembled = TRUE) + if(!disassembled) + prime() + if(!QDELETED(src)) + qdel(src) + +/obj/item/grenade/proc/clown_check(mob/living/carbon/human/user) + if(user.disabilities & CLUMSY && prob(50)) + to_chat(user, "Huh? How does this thing work?") preprime(user, 5, FALSE) return FALSE return TRUE - - -/obj/item/grenade/examine(mob/user) - ..() - if(display_timer) - if(det_time > 1) - to_chat(user, "The timer is set to [det_time/10] second\s.") - else - to_chat(user, "\The [src] is set for instant detonation.") - - -/obj/item/grenade/attack_self(mob/user) - if(!active) - if(clown_check(user)) - preprime(user) - + + +/obj/item/grenade/examine(mob/user) + ..() + if(display_timer) + if(det_time > 1) + to_chat(user, "The timer is set to [det_time/10] second\s.") + else + to_chat(user, "\The [src] is set for instant detonation.") + + +/obj/item/grenade/attack_self(mob/user) + if(!active) + if(clown_check(user)) + preprime(user) + /obj/item/grenade/proc/log_grenade(mob/user, turf/T) var/area/A = get_area(T) var/message = "[ADMIN_LOOKUPFLW(user)]) has primed \a [src] for detonation at [ADMIN_COORDJMP(T)]" @@ -52,57 +52,58 @@ message_admins(message) log_game("[key_name(user)] has primed \a [src] for detonation at [A.name] [COORD(T)].") -/obj/item/grenade/proc/preprime(mob/user, delayoverride, msg = TRUE) +/obj/item/grenade/proc/preprime(mob/user, delayoverride, msg = TRUE, volume = 60) var/turf/T = get_turf(src) - log_grenade(user, T) - if(iscarbon(user)) - var/mob/living/carbon/C = user - C.throw_mode_on() - if(msg) - to_chat(user, "You prime \the [src]! [det_time/10] seconds!") - playsound(loc, 'sound/weapons/armbomb.ogg', 60, 1) - active = TRUE - icon_state = initial(icon_state) + "_active" - add_fingerprint(user) + log_grenade(user, T) //Inbuilt admin procs already handle null users + if(user) + add_fingerprint(user) + if(iscarbon(user)) + var/mob/living/carbon/C = user + C.throw_mode_on() + if(msg) + to_chat(user, "You prime \the [src]! [det_time/10] seconds!") + playsound(src, 'sound/weapons/armbomb.ogg', volume, 1) + active = TRUE + icon_state = initial(icon_state) + "_active" addtimer(CALLBACK(src, .proc/prime), isnull(delayoverride)? det_time : delayoverride) - -/obj/item/grenade/proc/prime() - -/obj/item/grenade/proc/update_mob() - if(ismob(loc)) - var/mob/M = loc - M.dropItemToGround(src) - - -/obj/item/grenade/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/screwdriver)) - switch(det_time) - if ("1") - det_time = 10 - to_chat(user, "You set the [name] for 1 second detonation time.") - if ("10") - det_time = 30 - to_chat(user, "You set the [name] for 3 second detonation time.") - if ("30") - det_time = 50 - to_chat(user, "You set the [name] for 5 second detonation time.") - if ("50") - det_time = 1 - to_chat(user, "You set the [name] for instant detonation.") - add_fingerprint(user) - else - return ..() - -/obj/item/grenade/attack_hand() - walk(src, null, null) - ..() - -/obj/item/grenade/attack_paw(mob/user) - return attack_hand(user) - -/obj/item/grenade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - var/obj/item/projectile/P = hitby - if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(15)) - owner.visible_message("[attack_text] hits [owner]'s [src], setting it off! What a shot!") - prime() + +/obj/item/grenade/proc/prime() + +/obj/item/grenade/proc/update_mob() + if(ismob(loc)) + var/mob/M = loc + M.dropItemToGround(src) + + +/obj/item/grenade/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/screwdriver)) + switch(det_time) + if ("1") + det_time = 10 + to_chat(user, "You set the [name] for 1 second detonation time.") + if ("10") + det_time = 30 + to_chat(user, "You set the [name] for 3 second detonation time.") + if ("30") + det_time = 50 + to_chat(user, "You set the [name] for 5 second detonation time.") + if ("50") + det_time = 1 + to_chat(user, "You set the [name] for instant detonation.") + add_fingerprint(user) + else + return ..() + +/obj/item/grenade/attack_hand() + walk(src, null, null) + ..() + +/obj/item/grenade/attack_paw(mob/user) + return attack_hand(user) + +/obj/item/grenade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + var/obj/item/projectile/P = hitby + if(damage && attack_type == PROJECTILE_ATTACK && P.damage_type != STAMINA && prob(15)) + owner.visible_message("[attack_text] hits [owner]'s [src], setting it off! What a shot!") + prime() return TRUE //It hit the grenade, not them diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index ec5f349ca9..d1d7f4d289 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -7,14 +7,66 @@ w_class = WEIGHT_CLASS_SMALL resistance_flags = FLAMMABLE var/list/squeak_override //Weighted list; If you want your plush to have different squeak sounds use this + var/stuffed = TRUE //If the plushie has stuffing in it + var/obj/item/grenade/grenade //You can remove the stuffing from a plushie and add a grenade to it for *nefarious uses* /obj/item/toy/plush/Initialize() . = ..() AddComponent(/datum/component/squeak, squeak_override) +/obj/item/toy/plush/Destroy() + QDEL_NULL(grenade) + return ..() + +/obj/item/toy/plush/handle_atom_del(atom/A) + if(A == grenade) + grenade = null + ..() + /obj/item/toy/plush/attack_self(mob/user) . = ..() - to_chat(user, "You pet [src]. D'awww.") + if(stuffed || grenade) + to_chat(user, "You pet [src]. D'awww.") + if(grenade && !grenade.active) + if(istype(grenade, /obj/item/grenade/chem_grenade)) + var/obj/item/grenade/chem_grenade/G = grenade + if(G.nadeassembly) //We're activated through different methods + return + log_game("[key_name(user)] activated a hidden grenade in [src].") + grenade.preprime(user, msg = FALSE, volume = 10) + else + to_chat(user, "You try to pet [src], but it has no stuffing. Aww...") + +/obj/item/toy/plush/attackby(obj/item/I, mob/living/user, params) + if(I.is_sharp()) + if(!grenade) + if(!stuffed) + to_chat(user, "You already murdered it!") + return + user.visible_message("[user] tears out the stuffing from [src]!", "You rip a bunch of the stuffing from [src]. Murderer.") + playsound(I, I.usesound, 50, TRUE) + stuffed = FALSE + else + to_chat(user, "You remove the grenade from [src].") + user.put_in_hands(grenade) + grenade = null + return + if(istype(I, /obj/item/grenade)) + if(stuffed) + to_chat(user, "You need to remove some stuffing first!") + return + if(grenade) + to_chat(user, "[src] already has a grenade!") + return + if(!user.transferItemToLoc(I, src)) + return + user.visible_message("[user] slides [grenade] into [src].", \ + "You slide [I] into [src].") + grenade = I + var/turf/T = get_turf(user) + log_game("[key_name(user)] added a grenade ([I.name]) to [src] at [COORD(T)].") + return + return ..() /obj/item/toy/plush/carpplushie name = "space carp plushie" diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index d899d48354..59eef9a170 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -320,7 +320,7 @@ /obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R) if(..()) return - for(var/obj/item/reagent_containers/borghypo/H in R.module) + for(var/obj/item/reagent_containers/borghypo/H in R.module.modules) if(H.accepts_reagent_upgrades) for(var/re in additional_reagents) H.add_reagent(re) @@ -355,7 +355,7 @@ return var/found_hypo = FALSE - for(var/obj/item/reagent_containers/borghypo/H in R.module) + for(var/obj/item/reagent_containers/borghypo/H in R.module.modules) H.bypass_protection = TRUE found_hypo = TRUE diff --git a/code/game/objects/items/sharpener.dm b/code/game/objects/items/sharpener.dm index ce2d73eff0..fb25cb1d76 100644 --- a/code/game/objects/items/sharpener.dm +++ b/code/game/objects/items/sharpener.dm @@ -3,6 +3,7 @@ icon = 'icons/obj/kitchen.dmi' icon_state = "sharpener" desc = "A block that makes things sharp." + force = 5 var/used = 0 var/increment = 4 var/max = 30 diff --git a/code/game/objects/items/tools.dm b/code/game/objects/items/tools.dm index d18799c681..bd618f217e 100644 --- a/code/game/objects/items/tools.dm +++ b/code/game/objects/items/tools.dm @@ -457,6 +457,15 @@ flamethrower_screwdriver(I, user) else if(istype(I, /obj/item/stack/rods)) flamethrower_rods(I, user) + else if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) + var/amountNeeded = max_fuel - get_fuel() + var/obj/item/reagent_containers/container = I + if(length(container.reagents.reagent_list) > 1) + to_chat(user, "[container] has too many chemicals mixed into it. You wouldn't want to put the wrong chemicals into [src].") + return ..() + if(amountNeeded > 0 && container.reagents.has_reagent("welding_fuel")) + container.reagents.trans_id_to(src, "welding_fuel", amountNeeded) + to_chat(user, "You transfer some fuel from [container] to [src].") else return ..() diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index 2d4dbf7aa0..14d29e96a7 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -101,7 +101,7 @@ desc = "A collapsed roller bed that can be carried around." icon = 'icons/obj/rollerbed.dmi' icon_state = "folded" - w_class = WEIGHT_CLASS_BULKY // Can't be put in backpacks. + w_class = WEIGHT_CLASS_NORMAL // No more excuses, stop getting blood everywhere /obj/item/roller/attackby(obj/item/I, mob/living/user, params) if(istype(I, /obj/item/roller/robo)) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 0cb6451116..0e5675a5a0 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -498,7 +498,7 @@ flick("baton_active", src) var/stunforce = B.stunforce user.Knockdown(stunforce) - user.stuttering = stunforce + user.stuttering = stunforce/20 B.deductcharge(B.hitcost) user.visible_message("[user] shocks themself while attempting to wash the active [B.name]!", \ "You unwisely attempt to wash [B] while it's still on.") diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index 0014f92378..105fc9f570 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -130,6 +130,10 @@ var/backpack_contents = -1 var/suit_store = -1 + var/hair_style + var/facial_hair_style + var/skin_tone + /obj/effect/mob_spawn/human/Initialize() if(ispath(outfit)) outfit = new outfit() @@ -147,6 +151,20 @@ H.underwear = "Nude" H.undershirt = "Nude" H.socks = "Nude" + if(hair_style) + H.hair_style = hair_style + else + H.hair_style = random_hair_style(gender) + if(facial_hair_style) + H.facial_hair_style = facial_hair_style + else + H.facial_hair_style = random_facial_hair_style(gender) + if(skin_tone) + H.skin_tone = skin_tone + else + H.skin_tone = random_skin_tone() + H.update_hair() + H.update_body() if(outfit) var/static/list/slots = list("uniform", "r_hand", "l_hand", "suit", "shoes", "gloves", "ears", "glasses", "mask", "head", "belt", "r_pocket", "l_pocket", "back", "id", "neck", "backpack_contents", "suit_store") for(var/slot in slots) diff --git a/code/modules/client/verbs/ooc.dm b/code/modules/client/verbs/ooc.dm index e2022729be..a0c1e2135a 100644 --- a/code/modules/client/verbs/ooc.dm +++ b/code/modules/client/verbs/ooc.dm @@ -259,9 +259,19 @@ GLOBAL_VAR_INIT(normal_ooc_colour, OOC_COLOR) set category = "OOC" set desc ="Ignore a player's messages on the OOC channel" - var/selection = input("Please, select a player!", "Ignore", null, null) as null|anything in sortKey(GLOB.clients) - if(!selection) + + var/see_ghost_names = isobserver(mob) + var/list/choices = list() + for(var/client/C in GLOB.clients) + if(isobserver(C.mob) && see_ghost_names) + choices["[C.mob]([C])"] = C + else + choices[C] = C + choices = sortList(choices) + var/selection = input("Please, select a player!", "Ignore", null, null) as null|anything in choices + if(!selection || !(selection in choices)) return + selection = choices[selection] if(selection == src) to_chat(src, "You can't ignore yourself.") return diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm index 7940eaeec8..b651294308 100644 --- a/code/modules/events/meteor_wave.dm +++ b/code/modules/events/meteor_wave.dm @@ -4,8 +4,9 @@ name = "Meteor Wave: Normal" typepath = /datum/round_event/meteor_wave weight = 4 - min_players = 5 + min_players = 15 max_occurrences = 3 + earliest_start = 25 MINUTES /datum/round_event/meteor_wave startWhen = 6 @@ -54,9 +55,10 @@ /datum/round_event_control/meteor_wave/threatening name = "Meteor Wave: Threatening" typepath = /datum/round_event/meteor_wave/threatening - weight = 2 - min_players = 5 + weight = 5 + min_players = 20 max_occurrences = 3 + earliest_start = 35 MINUTES /datum/round_event/meteor_wave/threatening wave_name = "threatening" @@ -64,9 +66,10 @@ /datum/round_event_control/meteor_wave/catastrophic name = "Meteor Wave: Catastrophic" typepath = /datum/round_event/meteor_wave/catastrophic - weight = 1 - min_players = 5 + weight = 7 + min_players = 25 max_occurrences = 3 + earliest_start = 45 MINUTES /datum/round_event/meteor_wave/catastrophic wave_name = "catastrophic" diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index efd877b9dc..46e2f3ea5f 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -194,6 +194,7 @@ break if(O.name == params["name"]) O.forceMove(drop_location()) + adjust_item_drop_location(O) desired-- return TRUE return FALSE diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 89a30f0733..991fd7a94d 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -75,24 +75,54 @@ /datum/emote/living/carbon/human/wag/run_emote(mob/user, params) . = ..() var/mob/living/carbon/human/H = user - if(.) + if(!H.is_wagging_tail()) H.startTailWag() else H.endTailWag() +/mob/living/carbon/human/proc/is_wagging_tail() + return (dna && dna.species && ("waggingtail_lizard" in dna.species.mutant_bodyparts || "waggingtail_human" in dna.species.mutant_bodyparts)) + /datum/emote/living/carbon/human/wag/can_run_emote(mob/user, status_check = TRUE) if(!..()) return FALSE var/mob/living/carbon/human/H = user - if(H.dna && H.dna.species && ((H.dna.features["tail_lizard"] != "None") || (H.dna.features["tail_human"] != "None") || ("mam_tail" in H.dna.species.mutant_bodyparts))) + if(H.dna && H.dna.species && (("tail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_lizard" in H.dna.species.mutant_bodyparts) || (H.dna.features["tail_human"] != "None"))) return TRUE /datum/emote/living/carbon/human/wag/select_message_type(mob/user) . = ..() var/mob/living/carbon/human/H = user - if(("waggingtail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_human" in H.dna.species.mutant_bodyparts) || ("mam_waggingtail" in H.dna.species.mutant_bodyparts)) + if(("waggingtail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_human" in H.dna.species.mutant_bodyparts)) . = null +//Don't know where else to put this, it's basically an emote +/mob/living/carbon/human/proc/startTailWag() + if(!dna || !dna.species) + return + if("tail_lizard" in dna.species.mutant_bodyparts) + dna.species.mutant_bodyparts -= "tail_lizard" + dna.species.mutant_bodyparts -= "spines" + dna.species.mutant_bodyparts |= "waggingtail_lizard" + dna.species.mutant_bodyparts |= "waggingspines" + if("tail_human" in dna.species.mutant_bodyparts) + dna.species.mutant_bodyparts -= "tail_human" + dna.species.mutant_bodyparts |= "waggingtail_human" + update_body() + +/mob/living/carbon/human/proc/endTailWag() + if(!dna || !dna.species) + return + if("waggingtail_lizard" in dna.species.mutant_bodyparts) + dna.species.mutant_bodyparts -= "waggingtail_lizard" + dna.species.mutant_bodyparts -= "waggingspines" + dna.species.mutant_bodyparts |= "tail_lizard" + dna.species.mutant_bodyparts |= "spines" + if("waggingtail_human" in dna.species.mutant_bodyparts) + dna.species.mutant_bodyparts -= "waggingtail_human" + dna.species.mutant_bodyparts |= "tail_human" + update_body() + /datum/emote/living/carbon/human/wing key = "wing" key_third_person = "wings" @@ -121,41 +151,7 @@ var/mob/living/carbon/human/H = user if(H.dna && H.dna.species && (H.dna.features["wings"] != "None")) return TRUE - -//Don't know where else to put this, it's basically an emote -/mob/living/carbon/human/proc/startTailWag() - if(!dna || !dna.species) - return - if("tail_lizard" in dna.species.mutant_bodyparts) - dna.species.mutant_bodyparts -= "tail_lizard" - dna.species.mutant_bodyparts -= "spines" - dna.species.mutant_bodyparts |= "waggingtail_lizard" - dna.species.mutant_bodyparts |= "waggingspines" - if("tail_human" in dna.species.mutant_bodyparts) - dna.species.mutant_bodyparts -= "tail_human" - dna.species.mutant_bodyparts |= "waggingtail_human" - if("mam_tail" in dna.species.mutant_bodyparts) - dna.species.mutant_bodyparts -= "mam_tail" - dna.species.mutant_bodyparts |= "mam_waggingtail" - update_body() - - -/mob/living/carbon/human/proc/endTailWag() - if(!dna || !dna.species) - return - if("waggingtail_lizard" in dna.species.mutant_bodyparts) - dna.species.mutant_bodyparts -= "waggingtail_lizard" - dna.species.mutant_bodyparts -= "waggingspines" - dna.species.mutant_bodyparts |= "tail_lizard" - dna.species.mutant_bodyparts |= "spines" - if("waggingtail_human" in dna.species.mutant_bodyparts) - dna.species.mutant_bodyparts -= "waggingtail_human" - dna.species.mutant_bodyparts |= "tail_human" - if("mam_waggingtail" in dna.species.mutant_bodyparts) - dna.species.mutant_bodyparts -= "mam_waggingtail" - dna.species.mutant_bodyparts |= "mam_tail" - update_body() - + /mob/living/carbon/human/proc/OpenWings() if(!dna || !dna.species) return diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index c2cf238677..59607279b9 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -22,6 +22,7 @@ limbs_id = "golem" fixed_mut_color = "aaa" var/info_text = "As an Iron Golem, you don't have any special traits." + var/random_eligible = TRUE //If false, the golem subtype can't be made through golem mutation toxin var/prefix = "Iron" var/list/special_names @@ -44,6 +45,7 @@ name = "Random Golem" blacklisted = FALSE dangerous_existence = FALSE + var/static/list/random_golem_types /datum/species/golem/random/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() @@ -601,7 +603,7 @@ info_text = "As a clockwork golem, you are faster than \ other types of golem (being a machine), and are immune to electric shocks." species_traits = list(NO_UNDERWEAR, NOTRANSSTING, NOBREATH, NOZOMBIE, VIRUSIMMUNE, RADIMMUNE, NOBLOOD, RESISTCOLD, RESISTPRESSURE, PIERCEIMMUNE) - armor = 40 //Reinforced, but also slim to allow for fast movement + armor = 20 //Reinforced, but much less so to allow for fast movement attack_verb = "smash" attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg' sexes = FALSE @@ -643,7 +645,8 @@ has_corpse = TRUE blacklisted = TRUE dangerous_existence = TRUE - + random_eligible = FALSE + /datum/species/golem/cloth name = "Cloth Golem" id = "cloth golem" diff --git a/code/modules/mob/living/simple_animal/corpse.dm b/code/modules/mob/living/simple_animal/corpse.dm index cf1b9b08cc..73cdd6f866 100644 --- a/code/modules/mob/living/simple_animal/corpse.dm +++ b/code/modules/mob/living/simple_animal/corpse.dm @@ -12,6 +12,8 @@ name = "Syndicate Operative" id_job = "Operative" id_access_list = list(ACCESS_SYNDICATE) + hair_style = "Bald" + facial_hair_style = "Shaved" outfit = /datum/outfit/syndicatesoldiercorpse /datum/outfit/syndicatesoldiercorpse @@ -31,6 +33,8 @@ name = "Syndicate Commando" id_job = "Operative" id_access_list = list(ACCESS_SYNDICATE) + hair_style = "Bald" + facial_hair_style = "Shaved" outfit = /datum/outfit/syndicatecommandocorpse /datum/outfit/syndicatecommandocorpse @@ -50,6 +54,8 @@ name = "Syndicate Stormtrooper" id_job = "Operative" id_access_list = list(ACCESS_SYNDICATE) + hair_style = "Bald" + facial_hair_style = "Shaved" outfit = /datum/outfit/syndicatestormtroopercorpse /datum/outfit/syndicatestormtroopercorpse @@ -67,11 +73,16 @@ /obj/effect/mob_spawn/human/clown/corpse roundstart = FALSE instant = TRUE - + skin_tone = "caucasian1" + hair_style = "Bald" + facial_hair_style = "Shaved" /obj/effect/mob_spawn/human/corpse/pirate name = "Pirate" + skin_tone = "Caucasian1" //all pirates are white because it's easier that way outfit = /datum/outfit/piratecorpse + hair_style = "Bald" + facial_hair_style = "Shaved" /datum/outfit/piratecorpse name = "Pirate Corpse" @@ -94,12 +105,17 @@ /obj/effect/mob_spawn/human/corpse/russian name = "Russian" outfit = /datum/outfit/russiancorpse + hair_style = "Bald" + facial_hair_style = "Shaved" /datum/outfit/russiancorpse name = "Russian Corpse" uniform = /obj/item/clothing/under/soviet shoes = /obj/item/clothing/shoes/jackboots head = /obj/item/clothing/head/bearpelt + gloves = /obj/item/clothing/gloves/color/black + mask = /obj/item/clothing/mask/gas + /obj/effect/mob_spawn/human/corpse/russian/ranged @@ -109,6 +125,7 @@ name = "Ranged Russian Corpse" head = /obj/item/clothing/head/ushanka + /obj/effect/mob_spawn/human/corpse/russian/ranged/trooper outfit = /datum/outfit/russiancorpse/ranged/trooper @@ -119,8 +136,8 @@ shoes = /obj/item/clothing/shoes/combat gloves = /obj/item/clothing/gloves/combat ears = /obj/item/device/radio/headset - mask = /obj/item/clothing/mask/balaclava head = /obj/item/clothing/head/helmet/alt + mask = /obj/item/clothing/mask/balaclava /obj/effect/mob_spawn/human/corpse/russian/ranged/officer @@ -131,7 +148,7 @@ name = "Russian Officer Corpse" uniform = /obj/item/clothing/under/rank/security/navyblue/russian suit = /obj/item/clothing/suit/security/officer/russian - shoes = /obj/item/clothing/shoes/laceup + shoes = /obj/item/clothing/shoes/combat ears = /obj/item/device/radio/headset head = /obj/item/clothing/head/ushanka @@ -139,6 +156,9 @@ /obj/effect/mob_spawn/human/corpse/wizard name = "Space Wizard Corpse" outfit = /datum/outfit/wizardcorpse + hair_style = "Bald" + facial_hair_style = "Long Beard" + skin_tone = "Caucasian1" /datum/outfit/wizardcorpse name = "Space Wizard Corpse" @@ -153,6 +173,8 @@ id_job = "Private Security Force" id_access = "Security Officer" outfit = /datum/outfit/nanotrasensoldiercorpse2 + hair_style = "Bald" + facial_hair_style = "Shaved" /datum/outfit/nanotrasensoldiercorpse2 name = "NT Private Security Officer Corpse" diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm index d6d46b1a46..d050b4143d 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/spaceman.dm @@ -23,7 +23,7 @@ environment_smash = ENVIRONMENT_SMASH_NONE del_on_death = 0 -/mob/living/simple_animal/hostile/retaliate/nanotrasenpeace +/mob/living/simple_animal/hostile/retaliate/nanotrasenpeace //this should be in a different file name = "Nanotrasen Private Security Officer" desc = "An officer part of Nanotrasen's private security force." icon = 'icons/mob/simple_human.dmi' diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index b207b82e26..8fc327702b 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -45,8 +45,6 @@ sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS anchored = TRUE - gold_core_spawnable = 1 - var/cannot_be_seen = 1 var/mob/living/creator = null diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index f1da846ebc..7c764e26cb 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -62,11 +62,13 @@ /obj/machinery/chem_master/attackby(obj/item/I, mob/user, params) if(default_deconstruction_screwdriver(user, "mixer0_nopower", "mixer0", I)) if(beaker) - beaker.loc = src.loc + beaker.forceMove(drop_location()) + adjust_item_drop_location(beaker) beaker = null reagents.clear_reagents() if(bottle) - bottle.loc = src.loc + bottle.forceMove(drop_location()) + adjust_item_drop_location(bottle) bottle = null return @@ -153,7 +155,8 @@ switch(action) if("eject") if(beaker) - beaker.loc = src.loc + beaker.forceMove(drop_location()) + adjust_item_drop_location(beaker) beaker = null reagents.clear_reagents() icon_state = "mixer0" @@ -161,7 +164,8 @@ if("ejectp") if(bottle) - bottle.loc = src.loc + bottle.forceMove(drop_location()) + adjust_item_drop_location(bottle) bottle = null . = TRUE @@ -214,16 +218,15 @@ if(bottle && bottle.contents.len < bottle.storage_slots) P = new/obj/item/reagent_containers/pill(bottle) else - P = new/obj/item/reagent_containers/pill(src.loc) + P = new/obj/item/reagent_containers/pill(drop_location()) P.name = trim("[name] pill") - P.pixel_x = rand(-7, 7) //random position - P.pixel_y = rand(-7, 7) + adjust_item_drop_location(P) reagents.trans_to(P,vol_each) else var/name = stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN) if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, be_close=TRUE)) return - var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(src.loc) + var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(drop_location()) P.originalname = name P.name = trim("[name] pack") @@ -248,10 +251,9 @@ var/obj/item/reagent_containers/pill/P for(var/i = 0; i < amount; i++) - P = new/obj/item/reagent_containers/pill/patch(src.loc) + P = new/obj/item/reagent_containers/pill/patch(drop_location()) P.name = trim("[name] patch") - P.pixel_x = rand(-7, 7) //random position - P.pixel_y = rand(-7, 7) + adjust_item_drop_location(P) reagents.trans_to(P,vol_each) . = TRUE @@ -264,7 +266,7 @@ var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN) if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, be_close=TRUE)) return - var/obj/item/reagent_containers/food/condiment/P = new(src.loc) + var/obj/item/reagent_containers/food/condiment/P = new(drop_location()) P.originalname = name P.name = trim("[name] bottle") reagents.trans_to(P, P.volume) @@ -280,15 +282,15 @@ var/obj/item/reagent_containers/glass/bottle/P for(var/i = 0; i < amount_full; i++) - P = new/obj/item/reagent_containers/glass/bottle(src.loc) - P.pixel_x = rand(-7, 7) //random position - P.pixel_y = rand(-7, 7) + P = new/obj/item/reagent_containers/glass/bottle(drop_location()) P.name = trim("[name] bottle") + adjust_item_drop_location(P) reagents.trans_to(P, 30) if(vol_part) - P = new/obj/item/reagent_containers/glass/bottle(src.loc) + P = new/obj/item/reagent_containers/glass/bottle(drop_location()) P.name = trim("[name] bottle") + adjust_item_drop_location(P) reagents.trans_to(P, vol_part) . = TRUE @@ -328,6 +330,29 @@ return 0 +/obj/machinery/chem_master/adjust_item_drop_location(atom/movable/AM) // Special version for chemmasters and condimasters + if (AM == beaker) + AM.pixel_x = -8 + AM.pixel_y = 8 + return null + else if (AM == bottle) + if (length(bottle.contents)) + AM.pixel_x = -13 + else + AM.pixel_x = -7 + AM.pixel_y = -8 + return null + else + var/md5 = md5(AM.name) +#if DM_VERSION > 511 +#warn Refactor the loop in /obj/machinery/chem_master/adjust_item_drop_location() to make use of 512's list-like access to characters in a string +#endif + for (var/i in 1 to 32) + . += hex2num(copytext(md5,i,i+1)) + . = . % 9 + AM.pixel_x = ((.%3)*6) + AM.pixel_y = -8 + (round( . / 3)*8) + /obj/machinery/chem_master/condimaster name = "CondiMaster 3000" desc = "Used to create condiments and other cooking supplies." diff --git a/code/modules/reagents/chemistry/machinery/smoke_machine.dm b/code/modules/reagents/chemistry/machinery/smoke_machine.dm index 63f7e48281..2365bb03ed 100644 --- a/code/modules/reagents/chemistry/machinery/smoke_machine.dm +++ b/code/modules/reagents/chemistry/machinery/smoke_machine.dm @@ -66,7 +66,7 @@ /obj/machinery/smoke_machine/attackby(obj/item/I, mob/user, params) add_fingerprint(user) - if(istype(I, /obj/item/reagent_containers)) + if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) var/obj/item/reagent_containers/RC = I var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this) if(units) diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index c0b69e658c..a4d317ad2a 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -124,39 +124,37 @@ cut_overlays() . = ..() if(dropped) //certain overlays only appear when the limb is being detached from its owner. - var/datum/sprite_accessory/S if(status != BODYPART_ROBOTIC) //having a robotic head hides certain features. //facial hair if(facial_hair_style) - S = GLOB.facial_hair_styles_list[facial_hair_style] + var/datum/sprite_accessory/S = GLOB.facial_hair_styles_list[facial_hair_style] if(S) var/image/facial_overlay = image(S.icon, "[S.icon_state]", -HAIR_LAYER, SOUTH) facial_overlay.color = "#" + facial_hair_color facial_overlay.alpha = hair_alpha . += facial_overlay - var/image/hair_overlay = image(layer = -HAIR_LAYER, dir = SOUTH) - . += hair_overlay //Applies the debrained overlay if there is no brain if(!brain) + var/image/debrain_overlay = image(layer = -HAIR_LAYER, dir = SOUTH) if(animal_origin == ALIEN_BODYPART) - hair_overlay.icon = 'icons/mob/animal_parts.dmi' - hair_overlay.icon_state = "debrained_alien" + debrain_overlay.icon = 'icons/mob/animal_parts.dmi' + debrain_overlay.icon_state = "debrained_alien" else if(animal_origin == LARVA_BODYPART) - hair_overlay.icon = 'icons/mob/animal_parts.dmi' - hair_overlay.icon_state = "debrained_larva" + debrain_overlay.icon = 'icons/mob/animal_parts.dmi' + debrain_overlay.icon_state = "debrained_larva" else if(!(NOBLOOD in species_flags_list)) - hair_overlay.icon = 'icons/mob/human_face.dmi' - hair_overlay.icon_state = "debrained" + debrain_overlay.icon = 'icons/mob/human_face.dmi' + debrain_overlay.icon_state = "debrained" + . += debrain_overlay else - if(hair_style) - S = GLOB.hair_styles_list[hair_style] - if(S) - hair_overlay.icon = icon - hair_overlay.icon_state = "[S.icon_state]" - hair_overlay.color = "#" + hair_color - hair_overlay.alpha = hair_alpha + var/datum/sprite_accessory/S2 = GLOB.hair_styles_list[hair_style] + if(S2) + var/image/hair_overlay = image(S2.icon, "[S2.icon_state]", -HAIR_LAYER, SOUTH) + hair_overlay.color = "#" + hair_color + hair_overlay.alpha = hair_alpha + . += hair_overlay // lipstick diff --git a/icons/mob/simple_human.dmi b/icons/mob/simple_human.dmi index b3bc59378b..f3345c0825 100644 Binary files a/icons/mob/simple_human.dmi and b/icons/mob/simple_human.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 024a00b067..f563af642f 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/sound/lavaland/ash_storm_end.ogg b/sound/lavaland/ash_storm_end.ogg deleted file mode 100644 index f9b01453dd..0000000000 Binary files a/sound/lavaland/ash_storm_end.ogg and /dev/null differ diff --git a/sound/lavaland/ash_storm_start.ogg b/sound/lavaland/ash_storm_start.ogg deleted file mode 100644 index 4b9bebffd0..0000000000 Binary files a/sound/lavaland/ash_storm_start.ogg and /dev/null differ diff --git a/sound/lavaland/ash_storm_windup.ogg b/sound/lavaland/ash_storm_windup.ogg deleted file mode 100644 index a9f0fa3270..0000000000 Binary files a/sound/lavaland/ash_storm_windup.ogg and /dev/null differ diff --git a/sound/weather/ashstorm/inside/active_end.ogg b/sound/weather/ashstorm/inside/active_end.ogg new file mode 100644 index 0000000000..959bf5773e Binary files /dev/null and b/sound/weather/ashstorm/inside/active_end.ogg differ diff --git a/sound/weather/ashstorm/inside/active_mid1.ogg b/sound/weather/ashstorm/inside/active_mid1.ogg new file mode 100644 index 0000000000..95244cd2b7 Binary files /dev/null and b/sound/weather/ashstorm/inside/active_mid1.ogg differ diff --git a/sound/weather/ashstorm/inside/active_mid2.ogg b/sound/weather/ashstorm/inside/active_mid2.ogg new file mode 100644 index 0000000000..a45584b9f3 Binary files /dev/null and b/sound/weather/ashstorm/inside/active_mid2.ogg differ diff --git a/sound/weather/ashstorm/inside/active_mid3.ogg b/sound/weather/ashstorm/inside/active_mid3.ogg new file mode 100644 index 0000000000..be2e672fa0 Binary files /dev/null and b/sound/weather/ashstorm/inside/active_mid3.ogg differ diff --git a/sound/weather/ashstorm/inside/active_start.ogg b/sound/weather/ashstorm/inside/active_start.ogg new file mode 100644 index 0000000000..3efab12ef2 Binary files /dev/null and b/sound/weather/ashstorm/inside/active_start.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_end.ogg b/sound/weather/ashstorm/inside/weak_end.ogg new file mode 100644 index 0000000000..416b75a9b8 Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_end.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_mid1.ogg b/sound/weather/ashstorm/inside/weak_mid1.ogg new file mode 100644 index 0000000000..d3211c6b5f Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_mid1.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_mid2.ogg b/sound/weather/ashstorm/inside/weak_mid2.ogg new file mode 100644 index 0000000000..b6491a7afb Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_mid2.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_mid3.ogg b/sound/weather/ashstorm/inside/weak_mid3.ogg new file mode 100644 index 0000000000..95238c72d4 Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_mid3.ogg differ diff --git a/sound/weather/ashstorm/inside/weak_start.ogg b/sound/weather/ashstorm/inside/weak_start.ogg new file mode 100644 index 0000000000..59abf1937d Binary files /dev/null and b/sound/weather/ashstorm/inside/weak_start.ogg differ diff --git a/sound/weather/ashstorm/outside/active_end.ogg b/sound/weather/ashstorm/outside/active_end.ogg new file mode 100644 index 0000000000..95149d846c Binary files /dev/null and b/sound/weather/ashstorm/outside/active_end.ogg differ diff --git a/sound/weather/ashstorm/outside/active_mid1.ogg b/sound/weather/ashstorm/outside/active_mid1.ogg new file mode 100644 index 0000000000..189528ab56 Binary files /dev/null and b/sound/weather/ashstorm/outside/active_mid1.ogg differ diff --git a/sound/weather/ashstorm/outside/active_mid2.ogg b/sound/weather/ashstorm/outside/active_mid2.ogg new file mode 100644 index 0000000000..92317f2e0a Binary files /dev/null and b/sound/weather/ashstorm/outside/active_mid2.ogg differ diff --git a/sound/weather/ashstorm/outside/active_mid3.ogg b/sound/weather/ashstorm/outside/active_mid3.ogg new file mode 100644 index 0000000000..34846bfd42 Binary files /dev/null and b/sound/weather/ashstorm/outside/active_mid3.ogg differ diff --git a/sound/weather/ashstorm/outside/active_start.ogg b/sound/weather/ashstorm/outside/active_start.ogg new file mode 100644 index 0000000000..8b3acf1a15 Binary files /dev/null and b/sound/weather/ashstorm/outside/active_start.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_end.ogg b/sound/weather/ashstorm/outside/weak_end.ogg new file mode 100644 index 0000000000..55db2fc356 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_end.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_mid1.ogg b/sound/weather/ashstorm/outside/weak_mid1.ogg new file mode 100644 index 0000000000..56faa9ad26 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_mid1.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_mid2.ogg b/sound/weather/ashstorm/outside/weak_mid2.ogg new file mode 100644 index 0000000000..0c836ad220 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_mid2.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_mid3.ogg b/sound/weather/ashstorm/outside/weak_mid3.ogg new file mode 100644 index 0000000000..f2cbfb0f4b Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_mid3.ogg differ diff --git a/sound/weather/ashstorm/outside/weak_start.ogg b/sound/weather/ashstorm/outside/weak_start.ogg new file mode 100644 index 0000000000..1ac59c36f0 Binary files /dev/null and b/sound/weather/ashstorm/outside/weak_start.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 71fe026012..1f7eec78df 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -386,6 +386,7 @@ #include "code\datums\looping_sounds\item_sounds.dm" #include "code\datums\looping_sounds\looping_sound.dm" #include "code\datums\looping_sounds\machinery_sounds.dm" +#include "code\datums\looping_sounds\weather.dm" #include "code\datums\martial\boxing.dm" #include "code\datums\martial\cqc.dm" #include "code\datums\martial\krav_maga.dm" @@ -1727,6 +1728,7 @@ #include "code\modules\mob\living\carbon\human\species_types\android.dm" #include "code\modules\mob\living\carbon\human\species_types\angel.dm" #include "code\modules\mob\living\carbon\human\species_types\corporate.dm" +#include "code\modules\mob\living\carbon\human\species_types\dullahan.dm" #include "code\modules\mob\living\carbon\human\species_types\flypeople.dm" #include "code\modules\mob\living\carbon\human\species_types\furrypeople.dm" #include "code\modules\mob\living\carbon\human\species_types\golems.dm" diff --git a/tools/WebhookProcessor/github_webhook_processor.php b/tools/WebhookProcessor/github_webhook_processor.php index da5b037237..37805aae7a 100644 --- a/tools/WebhookProcessor/github_webhook_processor.php +++ b/tools/WebhookProcessor/github_webhook_processor.php @@ -547,7 +547,7 @@ function has_tree_been_edited($payload, $tree){ } //find things in the _maps/map_files tree //e.g. diff --git a/_maps/map_files/Cerestation/cerestation.dmm b/_maps/map_files/Cerestation/cerestation.dmm - return $github_diff !== FALSE && strpos($github_diff, 'diff --git a/' . $tree) !== FALSE; + return $github_diff !== FALSE && preg_match('/^diff --git a\/' . preg_quote($tree, '/') . '/m') !== FALSE; } $no_changelog = false;