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;