")
text = replacetext(text, "\[cell\]", "")
text = replacetext(text, "\[logo\]", " ")
-
+ if(P)
text = "[text]"
-
+ else
+ text = "[text]"
text = copytext(text, 1, MAX_PAPER_MESSAGE_LEN)
return text
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 82b2ea8b419..c90db77effb 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1081,6 +1081,21 @@ proc/get_mob_with_client_list()
return get_turf(location)
+//For objects that should embed, but make no sense being is_sharp or is_pointed()
+//e.g: rods
+var/list/can_embed_types = typecacheof(list(
+ /obj/item/stack/rods,
+ /obj/item/pipe))
+
+/proc/can_embed(obj/item/W)
+ if(is_sharp(W))
+ return 1
+ if(is_pointed(W))
+ return 1
+
+ if(is_type_in_typecache(W, can_embed_types))
+ return 1
+
//Quick type checks for some tools
var/global/list/common_tools = list(
/obj/item/stack/cable_coil,
@@ -1199,22 +1214,6 @@ var/global/list/common_tools = list(
if(O.edge) return 1
return 0
-//Returns 1 if the given item is capable of popping things like balloons, inflatable barriers, or cutting police tape.
-/proc/can_puncture(obj/item/W as obj) // For the record, WHAT THE HELL IS THIS METHOD OF DOING IT?
- if(!istype(W)) return 0
- if(!W) return 0
- if(W.sharp) return 1
- return ( \
- W.sharp || \
- istype(W, /obj/item/weapon/screwdriver) || \
- istype(W, /obj/item/weapon/pen) || \
- istype(W, /obj/item/weapon/weldingtool) || \
- istype(W, /obj/item/weapon/lighter/zippo) || \
- istype(W, /obj/item/weapon/match) || \
- istype(W, /obj/item/clothing/mask/cigarette) || \
- istype(W, /obj/item/weapon/shovel) \
- )
-
/proc/is_surgery_tool(obj/item/W as obj)
return ( \
istype(W, /obj/item/weapon/scalpel) || \
@@ -1891,4 +1890,4 @@ var/global/list/g_fancy_list_of_types = null
var/num = pick(num_sample)
num_sample -= num
result += (1 << num)
- return result
+ return result
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index e453d748428..5e7fb5d0bd3 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -42,4 +42,4 @@ var/global/list/global_radios = list() //list of all radios, across all z-lev
var/global/list/meteor_list = list() //list of all meteors
var/global/list/poi_list = list() //list of points of interest for observe/follow
-
+var/global/list/active_jammers = list() // List of active radio jammers
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index e969751e1dd..51afe833ea3 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -199,6 +199,11 @@
Topic(src, list("src" = UID(), "command"="lights", "activate" = "0"), 1)
return
+/obj/machinery/ai_slipper/AICtrlClick() //Turns liquid dispenser on or off
+ ToggleOn()
+
+/obj/machinery/ai_slipper/AIAltClick() //Dispenses liquid if on
+ Activate()
//
// Override AdjacentQuick for AltClicking
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index a15176af87c..a8de6127c41 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -169,6 +169,12 @@
/obj/machinery/turretid/BorgAltClick() //turret lethal on/off. Forwards to AI code.
AIAltClick()
+/obj/machinery/ai_slipper/BorgCtrlClick() //Turns liquid dispenser on or off
+ ToggleOn()
+
+/obj/machinery/ai_slipper/BorgAltClick() //Dispenses liquid if on
+ Activate()
+
/*
As with AI, these are not used in click code,
because the code for robots is specific, not generic.
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index 5ebe1f9ac6d..1d5d419ba82 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -235,6 +235,12 @@ or something covering your eyes."
desc = "All that alcohol you've been drinking is impairing your speech, motor skills, and mental cognition. Make sure to act like it."
icon_state = "drunk"
+/obj/screen/alert/embeddedobject
+ name = "Embedded Object"
+ desc = "Something got lodged into your flesh and is causing major bleeding. It might fall out with time, but surgery is the safest way. \
+ If you're feeling frisky, click yourself in help intent to pull the object out."
+ icon_state = "embeddedobject"
+
/obj/screen/alert/embeddedobject/Click()
if(isliving(usr))
var/mob/living/carbon/human/M = usr
diff --git a/code/datums/spells/summonitem.dm b/code/datums/spells/summonitem.dm
index 32472fe1ec0..7524e7f31d6 100644
--- a/code/datums/spells/summonitem.dm
+++ b/code/datums/spells/summonitem.dm
@@ -79,6 +79,14 @@
add_logs(target, C, "magically debrained", addition="INTENT: [uppertext(target.a_intent)]")*/
if(C.stomach_contents && item_to_retrive in C.stomach_contents)
C.stomach_contents -= item_to_retrive
+ for(var/X in C.bodyparts)
+ var/obj/item/organ/external/part = X
+ if(item_to_retrive in part.embedded_objects)
+ part.embedded_objects -= item_to_retrive
+ to_chat(C, "The [item_to_retrive] that was embedded in your [part] has mysteriously vanished. How fortunate!")
+ if(!C.has_embedded_objects())
+ C.clear_alert("embeddedobject")
+ break
else
if(istype(item_to_retrive.loc,/obj/machinery/portable_atmospherics/)) //Edge cases for moved machinery
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index ef3b4a4e278..14732318aab 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -332,7 +332,7 @@ var/list/uplink_items = list()
reference = "TPB"
item = /obj/item/weapon/reagent_containers/glass/bottle/traitor
cost = 2
- job = list("Research Director", "Chief Medical Officer", "Medical Doctor", "Psychiatrist", "Paramedic", "Virologist", "Bartender", "Chef")
+ job = list("Research Director", "Chief Medical Officer", "Medical Doctor", "Psychiatrist", "Chemist", "Paramedic", "Virologist", "Bartender", "Chef")
// Paper contact poison pen
@@ -737,6 +737,14 @@ var/list/uplink_items = list()
cost = 17
excludefrom = list(/datum/game_mode/nuclear)
+/datum/uplink_item/stealthy_weapons/throwingweapons
+ name = "Box of Throwing Weapons"
+ desc = "A box of shurikens and reinforced bolas from ancient Earth martial arts. They are highly effective \
+ throwing weapons. The bolas can knock a target down and the shurikens will embed into limbs."
+ reference = "STK"
+ item = /obj/item/weapon/storage/box/syndie_kit/throwing_weapons
+ cost = 3
+
/datum/uplink_item/stealthy_weapons/edagger
name = "Energy Dagger"
desc = "A dagger made of energy that looks and functions as a pen when off."
@@ -1116,6 +1124,13 @@ var/list/uplink_items = list()
cost = 1
surplus = 0
+/datum/uplink_item/device_tools/jammer
+ name = "Radio Jammer"
+ desc = "This device will disrupt any nearby outgoing radio communication when activated."
+ reference = "RJ"
+ item = /obj/item/device/jammer
+ cost = 5
+
/datum/uplink_item/device_tools/teleporter
name = "Teleporter Circuit Board"
desc = "A printed circuit board that completes the teleporter onboard the mothership. Advise you test fire the teleporter before entering it, as malfunctions can occur."
diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm
index d1fe6217058..616429b8cd8 100644
--- a/code/datums/wires/syndicatebomb.dm
+++ b/code/datums/wires/syndicatebomb.dm
@@ -1,5 +1,5 @@
/datum/wires/syndicatebomb
- random = 1
+ random = TRUE
holder_type = /obj/machinery/syndicatebomb
wire_count = 5
@@ -13,83 +13,90 @@ var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if
switch(index)
if(WIRE_BOOM)
return "Explode"
-
+
if(WIRE_UNBOLT)
return "Unbolt"
-
+
if(WIRE_DELAY)
return "Delay"
-
+
if(WIRE_PROCEED)
return "Proceed"
-
+
if(WIRE_ACTIVATE)
return "Activate"
/datum/wires/syndicatebomb/CanUse(mob/living/L)
var/obj/machinery/syndicatebomb/P = holder
if(P.open_panel)
- return 1
- return 0
+ return TRUE
+ return FALSE
/datum/wires/syndicatebomb/UpdatePulsed(index)
- var/obj/machinery/syndicatebomb/P = holder
+ var/obj/machinery/syndicatebomb/B = holder
switch(index)
if(WIRE_BOOM)
- if(P.active)
- P.loc.visible_message("[bicon(holder)] An alarm sounds! It's go-")
- P.timer = 0
+ if(B.active)
+ holder.visible_message("[bicon(B)] An alarm sounds! It's go-")
+ B.explode_now = TRUE
if(WIRE_UNBOLT)
- P.loc.visible_message("[bicon(holder)] The bolts spin in place for a moment.")
+ holder.visible_message("[bicon(holder)] The bolts spin in place for a moment.")
if(WIRE_DELAY)
- playsound(P.loc, 'sound/machines/chime.ogg', 30, 1)
- P.loc.visible_message("[bicon(holder)] The bomb chirps.")
- P.timer += 10
- if(WIRE_PROCEED)
- playsound(P.loc, 'sound/machines/buzz-sigh.ogg', 30, 1)
- P.loc.visible_message("[bicon(holder)] The bomb buzzes ominously!")
- if(P.timer >= 61) //Long fuse bombs can suddenly become more dangerous if you tinker with them
- P.timer = 60
- if(P.timer >= 21)
- P.timer -= 10
- else if(P.timer >= 11) //both to prevent negative timers and to have a little mercy
- P.timer = 10
- if(WIRE_ACTIVATE)
- if(!P.active && !P.defused)
- playsound(P.loc, 'sound/machines/click.ogg', 30, 1)
- P.loc.visible_message("[bicon(holder)] You hear the bomb start ticking!")
- P.active = 1
- P.icon_state = "[initial(P.icon_state)]-active[P.open_panel ? "-wires" : ""]"
+ if(B.delayedbig)
+ holder.visible_message("[bicon(B)] The bomb has already been delayed.")
else
- P.loc.visible_message("[bicon(holder)] The bomb seems to hesitate for a moment.")
- P.timer += 5
+ holder.visible_message("[bicon(B)] The bomb chirps.")
+ playsound(B, 'sound/machines/chime.ogg', 30, 1)
+ B.detonation_timer += 300
+ B.delayedbig = TRUE
+ if(WIRE_PROCEED)
+ holder.visible_message("[bicon(B)] The bomb buzzes ominously!")
+ playsound(B, 'sound/machines/buzz-sigh.ogg', 30, 1)
+ var/seconds = B.seconds_remaining()
+ if(seconds >= 61) // Long fuse bombs can suddenly become more dangerous if you tinker with them.
+ B.detonation_timer = world.time + 600
+ else if(seconds >= 21)
+ B.detonation_timer -= 100
+ else if(seconds >= 11) // Both to prevent negative timers and to have a little mercy.
+ B.detonation_timer = world.time + 100
+ if(WIRE_ACTIVATE)
+ if(!B.active && !B.defused)
+ holder.visible_message("[bicon(B)] You hear the bomb start ticking!")
+ B.activate()
+ B.update_icon()
+ else if(B.delayedlittle)
+ holder.visible_message("[bicon(B)] Nothing happens.")
+ else
+ holder.visible_message("[bicon(B)] The bomb seems to hesitate for a moment.")
+ B.detonation_timer += 100
+ B.delayedlittle = TRUE
..()
/datum/wires/syndicatebomb/UpdateCut(index, mended)
- var/obj/machinery/syndicatebomb/P = holder
+ var/obj/machinery/syndicatebomb/B = holder
switch(index)
if(WIRE_EXPLODE)
- if(!mended)
- if(P.active)
- P.loc.visible_message("[bicon(holder)] An alarm sounds! It's go-")
- P.timer = 0
- else
- P.defused = 1
+ if(mended)
+ B.defused = FALSE // Cutting and mending all the wires of an inactive bomb will thus cure any sabotage.
else
- P.defused = 0 //cutting and mending all the wires of an inactive bomb will thus cure any sabotage
+ if(B.active)
+ holder.visible_message("[bicon(B)] An alarm sounds! It's go-")
+ B.explode_now = TRUE
+ else
+ B.defused = TRUE
if(WIRE_UNBOLT)
- if(!mended && P.anchored)
- playsound(P.loc, 'sound/effects/stealthoff.ogg', 30, 1)
- P.loc.visible_message("[bicon(holder)] The bolts lift out of the ground!")
- P.anchored = 0
+ if(!mended && B.anchored)
+ holder.visible_message("[bicon(B)] The bolts lift out of the ground!")
+ playsound(B, 'sound/effects/stealthoff.ogg', 30, 1)
+ B.anchored = FALSE
if(WIRE_PROCEED)
- if(!mended && P.active)
- P.loc.visible_message("[bicon(holder)] An alarm sounds! It's go-")
- P.timer = 0
+ if(!mended && B.active)
+ holder.visible_message("[bicon(B)] An alarm sounds! It's go-")
+ B.explode_now = TRUE
if(WIRE_ACTIVATE)
- if(!mended && P.active)
- P.loc.visible_message("[bicon(holder)] The timer stops! The bomb has been defused!")
- P.icon_state = "[initial(P.icon_state)]-inactive[P.open_panel ? "-wires" : ""]"
- P.active = 0
- P.defused = 1
+ if(!mended && B.active)
+ holder.visible_message("[bicon(B)] The timer stops! The bomb has been defused!")
+ B.active = FALSE
+ B.defused = TRUE
+ B.update_icon()
..()
\ No newline at end of file
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 2a6aa2b3a39..5d6b9da47bc 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -190,7 +190,7 @@
/mob/living/carbon/human/proc/sec_hud_set_security_status()
var/image/holder = hud_list[WANTED_HUD]
- var/perpname = get_face_name(get_id_name(""))
+ var/perpname = get_visible_name(TRUE) //gets the name of the perp, works if they have an id or if their face is uncovered
if(!ticker) return //wait till the game starts or the monkeys runtime....
if(perpname)
var/datum/data/record/R = find_record("name", perpname, data_core.security)
diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm
index 52b62f6cabf..194a82f0001 100644
--- a/code/game/dna/genes/goon_powers.dm
+++ b/code/game/dna/genes/goon_powers.dm
@@ -414,9 +414,6 @@
else
M.stop_pulling()
- if(user.pinned.len)
- failure = 1
-
user.visible_message("[user.name] takes a huge leap!")
playsound(user.loc, 'sound/weapons/thudswoosh.ogg', 50, 1)
if(failure)
diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm
index e159aa44247..32a6a58cbb3 100644
--- a/code/game/dna/genes/vg_powers.dm
+++ b/code/game/dna/genes/vg_powers.dm
@@ -211,11 +211,11 @@
/obj/effect/proc_holder/spell/targeted/remotetalk/choose_targets(mob/user = usr)
var/list/targets = new /list()
var/list/validtargets = new /list()
- for(var/mob/M in view(user.client.view, user))
+ var/turf/T = get_turf(user)
+ for(var/mob/M in range(14, T))
if(M && M.mind)
if(M == user)
continue
-
validtargets += M
if(!validtargets.len)
@@ -237,14 +237,15 @@
if(!say)
return
say = strip_html(say)
+ say = pencode_to_html(say, usr, format = 0, fields = 0)
for(var/mob/living/target in targets)
log_say("Project Mind: [key_name(user)]->[key_name(target)]: [say]")
if(REMOTE_TALK in target.mutations)
- target.show_message("You hear [user.real_name]'s voice: [say]")
+ target.show_message("You hear [user.real_name]'s voice: [say]")
else
- target.show_message("You hear a voice that seems to echo around the room: [say]")
- user.show_message("You project your mind into [target.real_name]: [say]")
+ target.show_message("You hear a voice that seems to echo around the room: [say]")
+ user.show_message("You project your mind into [target.name]: [say]")
for(var/mob/dead/observer/G in player_list)
G.show_message("Telepathic message from [user] ([ghost_follow_link(user, ghost=G)]) to [target] ([ghost_follow_link(target, ghost=G)]): [say]")
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index 5fd98986332..9077f623a2c 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -39,10 +39,6 @@
var/obj/item/organ/external/O = H.bodyparts_by_name[organ_name]
if(!O)
continue
- for(var/obj/item/weapon/shard/shrapnel/s in O.implants)
- O.implants -= s
- H.contents -= s
- qdel(s)
O.brute_dam = 0
O.burn_dam = 0
O.damage_state = "00"
@@ -58,6 +54,7 @@
for(var/obj/item/organ/internal/IO in H.internal_organs)
IO.damage = 0
IO.trace_chemicals.Cut()
+ H.remove_all_embedded_objects()
H.updatehealth()
to_chat(user, "We have regenerated.")
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 97511414e7a..bf2c692a0c0 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -41,6 +41,7 @@
w_class = WEIGHT_CLASS_SMALL
force = 15
throwforce = 25
+ embed_chance = 75
var/cooldown = 0
/obj/item/weapon/melee/cultblade/dagger/afterattack(mob/living/target as mob, mob/living/carbon/human/user as mob)
diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm
index a9975618435..a98090d186a 100644
--- a/code/game/gamemodes/miniantags/borer/borer.dm
+++ b/code/game/gamemodes/miniantags/borer/borer.dm
@@ -361,11 +361,6 @@
host = M
forceMove(M)
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- var/obj/item/organ/external/head = H.get_organ("head")
- head.implants += src
-
host.status_flags |= PASSEMOTES
RemoveBorerActions()
@@ -746,11 +741,6 @@
controlling = FALSE
- if(ishuman(host))
- var/mob/living/carbon/human/H = host
- var/obj/item/organ/external/head = H.get_organ("head")
- head.implants -= src
-
reset_perspective(null)
machine = null
diff --git a/code/game/gamemodes/wizard/artefact.dm b/code/game/gamemodes/wizard/artefact.dm
index 4f9af54457c..faef00612ca 100644
--- a/code/game/gamemodes/wizard/artefact.dm
+++ b/code/game/gamemodes/wizard/artefact.dm
@@ -780,7 +780,7 @@ var/global/list/multiverse = list()
to_chat(target, "You suddenly feel very hot")
target.bodytemperature += 50
GiveHint(target)
- else if(can_puncture(I))
+ else if(is_pointed(I))
to_chat(target, "You feel a stabbing pain in [parse_zone(user.zone_sel.selecting)]!")
target.Weaken(2)
GiveHint(target)
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index 41dc37ab43f..6d7264e9256 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -398,7 +398,7 @@
organData["broken"] = E.min_broken_damage
var/shrapnelData[0]
- for(var/obj/I in E.implants)
+ for(var/obj/I in E.embedded_objects)
var/shrapnelSubData[0]
shrapnelSubData["name"] = I.name
@@ -605,7 +605,7 @@
infected = "Septic:"
var/unknown_body = 0
- for(var/I in e.implants)
+ for(var/I in e.embedded_objects)
unknown_body++
if(unknown_body || e.hidden)
diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm
index 4d059043329..63aeee28b2f 100644
--- a/code/game/machinery/ai_slipper.dm
+++ b/code/game/machinery/ai_slipper.dm
@@ -5,12 +5,12 @@
layer = 3
anchored = 1.0
var/uses = 20
- var/disabled = 1
+ var/disabled = TRUE
var/lethal = 0
- var/locked = 1
+ var/locked = TRUE
var/cooldown_time = 0
var/cooldown_timeleft = 0
- var/cooldown_on = 0
+ var/cooldown_on = FALSE
req_access = list(access_ai_upload)
/obj/machinery/ai_slipper/power_change()
@@ -22,6 +22,7 @@
else
icon_state = "motion0"
stat |= NOPOWER
+ disabled = TRUE
/obj/machinery/ai_slipper/proc/setState(var/enabled, var/uses)
disabled = disabled
@@ -49,6 +50,24 @@
return
return
+/obj/machinery/ai_slipper/proc/ToggleOn()
+ if(stat & (NOPOWER|BROKEN))
+ return
+ disabled = !disabled
+ icon_state = disabled? "motion0":"motion3"
+
+/obj/machinery/ai_slipper/proc/Activate()
+ if(stat & (NOPOWER|BROKEN))
+ return
+ if(cooldown_on || disabled)
+ return
+ else
+ new /obj/structure/foam(loc)
+ uses--
+ cooldown_on = TRUE
+ cooldown_time = world.timeofday + 100
+ slip_process()
+
/obj/machinery/ai_slipper/attack_ai(mob/user)
return attack_hand(user)
@@ -87,18 +106,10 @@
return 1
if(href_list["toggleOn"])
- disabled = !disabled
- icon_state = disabled? "motion0":"motion3"
+ ToggleOn()
+
if(href_list["toggleUse"])
- if(cooldown_on || disabled)
- return
- else
- new /obj/structure/foam(loc)
- uses--
- cooldown_on = 1
- cooldown_time = world.timeofday + 100
- slip_process()
- return
+ Activate()
attack_hand(usr)
@@ -115,5 +126,5 @@
if(uses <= 0)
return
if(uses >= 0)
- cooldown_on = 0
+ cooldown_on = FALSE
power_change()
\ No newline at end of file
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index 10f6fc1c8c5..153fc50bf91 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -1,3 +1,6 @@
+#define BUTTON_COOLDOWN 60 // cant delay the bomb forever
+#define BUTTON_DELAY 50 //five seconds
+
/obj/machinery/syndicatebomb
icon = 'icons/obj/assemblies.dmi'
name = "syndicate bomb"
@@ -6,71 +9,119 @@
anchored = 0
density = 0
- layer = MOB_LAYER - 0.1 //so people can't hide it and it's REALLY OBVIOUS
+ layer = BELOW_MOB_LAYER //so people can't hide it and it's REALLY OBVIOUS
unacidable = 1
var/datum/wires/syndicatebomb/wires = null
- var/timer = 120
- var/open_panel = 0 //are the wires exposed?
- var/active = 0 //is the bomb counting down?
- var/defused = 0 //is the bomb capable of exploding?
- var/obj/item/weapon/bombcore/payload = /obj/item/weapon/bombcore/
+ var/minimum_timer = 90
+ var/timer_set = 90
+ var/maximum_timer = 60000
+
+ var/can_unanchor = TRUE
+
+ var/open_panel = FALSE //are the wires exposed?
+ var/active = FALSE //is the bomb counting down?
+ var/defused = FALSE //is the bomb capable of exploding?
+ var/obj/item/weapon/bombcore/payload = /obj/item/weapon/bombcore
var/beepsound = 'sound/items/timer.ogg'
+ var/delayedbig = FALSE //delay wire pulsed?
+ var/delayedlittle = FALSE //activation wire pulsed?
+ var/obj/effect/countdown/syndicatebomb/countdown
+
+ var/next_beep
+ var/detonation_timer
+ var/explode_now = FALSE
+
+/obj/machinery/syndicatebomb/proc/try_detonate(ignore_active = FALSE)
+ . = (payload in src) && (active || ignore_active) && !defused
+ if(.)
+ payload.detonate()
/obj/machinery/syndicatebomb/process()
- if(active && !defused && (timer > 0)) //Tick Tock
- var/volume = (timer <= 20 ? 40 : 10) // Tick louder when the bomb is closer to being detonated.
- playsound(loc, beepsound, volume, 0)
- timer = max(timer - 2,0) // 2 seconds per process()
- if(active && !defused && (timer <= 0)) //Boom
- active = 0
- timer = 120
- update_icon()
- if(payload in src)
- payload.detonate()
+ if(!active)
+ fast_processing -= src
+ detonation_timer = null
+ next_beep = null
+ countdown.stop()
return
- if(!active || defused) //Counter terrorists win
+
+ if(!isnull(next_beep) && (next_beep <= world.time))
+ var/volume
+ switch(seconds_remaining())
+ if(0 to 5)
+ volume = 50
+ if(5 to 10)
+ volume = 40
+ if(10 to 15)
+ volume = 30
+ if(15 to 20)
+ volume = 20
+ if(20 to 25)
+ volume = 10
+ else
+ volume = 5
+ playsound(loc, beepsound, volume, 0)
+ next_beep = world.time + 10
+
+ if(active && !defused && ((detonation_timer <= world.time) || explode_now))
+ active = FALSE
+ timer_set = initial(timer_set)
+ update_icon()
+ try_detonate(TRUE)
+ //Counter terrorists win
+ else if(!active || defused)
if(defused && payload in src)
payload.defuse()
- return
+ countdown.stop()
+ fast_processing -= src
/obj/machinery/syndicatebomb/New()
wires = new(src)
- payload = new payload(src)
+ if(payload)
+ payload = new payload(src)
update_icon()
+ countdown = new(src)
..()
/obj/machinery/syndicatebomb/Destroy()
QDEL_NULL(wires)
+ QDEL_NULL(countdown)
+ fast_processing -= src
return ..()
/obj/machinery/syndicatebomb/examine(mob/user)
..(user)
- to_chat(user, "A digital display on it reads \"[timer]\".")
+ to_chat(user, "A digital display on it reads \"[seconds_remaining()]\".")
/obj/machinery/syndicatebomb/update_icon()
icon_state = "[initial(icon_state)][active ? "-active" : "-inactive"][open_panel ? "-wires" : ""]"
-/obj/machinery/syndicatebomb/attackby(var/obj/item/I, var/mob/user, params)
- if(istype(I, /obj/item/weapon/wrench))
+/obj/machinery/syndicatebomb/proc/seconds_remaining()
+ if(active)
+ . = max(0, round((detonation_timer - world.time) / 10))
+ else
+ . = timer_set
+
+/obj/machinery/syndicatebomb/attackby(obj/item/I, mob/user, params)
+ if(iswrench(I) && can_unanchor)
if(!anchored)
- if(!isturf(src.loc) || istype(src.loc, /turf/space))
- to_chat(user, "The bomb must be placed on solid ground to attach it")
+ if(!isturf(loc) || isspaceturf(loc))
+ to_chat(user, "The bomb must be placed on solid ground to attach it.")
else
- to_chat(user, "You firmly wrench the bomb to the floor")
+ to_chat(user, "You firmly wrench the bomb to the floor.")
playsound(loc, I.usesound, 50, 1)
anchored = 1
if(active)
- to_chat(user, "The bolts lock in place")
+ to_chat(user, "The bolts lock in place.")
else
if(!active)
- to_chat(user, "You wrench the bomb from the floor")
+ to_chat(user, "You wrench the bomb from the floor.")
playsound(loc, I.usesound, 50, 1)
anchored = 0
else
to_chat(user, "The bolts are locked down!")
- else if(istype(I, /obj/item/weapon/screwdriver))
+ else if(isscrewdriver(I))
open_panel = !open_panel
update_icon()
to_chat(user, "You [open_panel ? "open" : "close"] the wire panel.")
@@ -79,28 +130,47 @@
if(open_panel)
wires.Interact(user)
- else if(istype(I, /obj/item/weapon/crowbar))
- if(open_panel && isWireCut(WIRE_BOOM) && isWireCut(WIRE_UNBOLT) && isWireCut(WIRE_DELAY) && isWireCut(WIRE_PROCEED) && isWireCut(WIRE_ACTIVATE))
+ else if(iscrowbar(I))
+ if(open_panel && wires.IsAllCut())
if(payload)
to_chat(user, "You carefully pry out [payload].")
payload.loc = user.loc
payload = null
else
- to_chat(user, "There isn't anything in here to remove!")
+ to_chat(user, "There isn't anything in here to remove!")
else if(open_panel)
- to_chat(user, "The wires connecting the shell to the explosives are holding it down!")
+ to_chat(user, "The wires connecting the shell to the explosives are holding it down!")
else
- to_chat(user, "The cover is screwed on, it won't pry off!")
+ to_chat(user, "The cover is screwed on, it won't pry off!")
else if(istype(I, /obj/item/weapon/bombcore))
if(!payload)
+ if(!user.drop_item())
+ return
payload = I
to_chat(user, "You place [payload] into [src].")
- user.drop_item()
- payload.loc = src
+ payload.forceMove(src)
else
to_chat(user, "[payload] is already loaded into [src], you'll have to remove it first.")
+ else if(iswelder(I))
+ if(payload || !wires.IsAllCut() || !open_panel)
+ return
+ var/obj/item/weapon/weldingtool/WT = I
+ if(!WT.isOn())
+ return
+ if(WT.get_fuel() < 5) //uses up 5 fuel.
+ to_chat(user, "You need more fuel to complete this task!")
+ return
+
+ playsound(loc, WT.usesound, 50, 1)
+ to_chat(user, "You start to cut the [src] apart...")
+ if(do_after(user, 20*I.toolspeed, target = src))
+ if(!WT.isOn() || !WT.remove_fuel(5, user))
+ return
+ to_chat(user, "You cut the [src] apart.")
+ new /obj/item/stack/sheet/plasteel(loc, 5)
+ qdel(src)
else
- ..()
+ return ..()
/obj/machinery/syndicatebomb/attack_ghost(mob/user)
interact(user)
@@ -133,21 +203,27 @@
return FALSE
return TRUE
+/obj/machinery/syndicatebomb/proc/activate()
+ active = TRUE
+ fast_processing += src
+ countdown.start()
+ next_beep = world.time + 10
+ detonation_timer = world.time + (timer_set * 10)
+ playsound(loc, 'sound/machines/click.ogg', 30, 1)
+
/obj/machinery/syndicatebomb/proc/settings(mob/user)
- var/newtime = input(user, "Please set the timer.", "Timer", "[timer]") as num
- newtime = Clamp(newtime, 120, 60000)
+ var/new_timer = input(user, "Please set the timer.", "Timer", "[timer_set]") as num
if(can_interact(user)) //No running off and setting bombs from across the station
- timer = newtime
- loc.visible_message("[bicon(src)] timer set for [timer] seconds.")
+ timer_set = Clamp(new_timer, minimum_timer, maximum_timer)
+ loc.visible_message("[bicon(src)] timer set for [timer_set] seconds.")
if(alert(user,"Would you like to start the countdown now?",,"Yes","No") == "Yes" && can_interact(user))
if(defused || active)
if(defused)
loc.visible_message("[bicon(src)] Device error: User intervention required.")
return
else
- loc.visible_message("[bicon(src)] [timer] seconds until detonation, please clear the area.")
- playsound(loc, 'sound/machines/click.ogg', 30, 1)
- active = 1
+ loc.visible_message("[bicon(src)] [timer_set] seconds until detonation, please clear the area.")
+ activate()
update_icon()
add_fingerprint(user)
@@ -167,12 +243,12 @@
name = "training bomb"
icon_state = "training-bomb"
desc = "A salvaged syndicate device gutted of its explosives to be used as a training aid for aspiring bomb defusers."
- payload = /obj/item/weapon/bombcore/training/
+ payload = /obj/item/weapon/bombcore/training
/obj/machinery/syndicatebomb/badmin
name = "generic summoning badmin bomb"
desc = "Oh god what is in this thing?"
- payload = /obj/item/weapon/bombcore/badmin/summon/
+ payload = /obj/item/weapon/bombcore/badmin/summon
/obj/machinery/syndicatebomb/badmin/clown
name = "clown bomb"
@@ -181,8 +257,23 @@
payload = /obj/item/weapon/bombcore/badmin/summon/clown
beepsound = 'sound/items/bikehorn.ogg'
-/obj/machinery/syndicatebomb/badmin/varplosion
- payload = /obj/item/weapon/bombcore/badmin/explosion/
+/obj/machinery/syndicatebomb/empty
+ name = "bomb"
+ icon_state = "base-bomb"
+ desc = "An ominous looking device designed to detonate an explosive payload. Can be bolted down using a wrench."
+ payload = null
+ open_panel = TRUE
+ timer_set = 120
+
+/obj/machinery/syndicatebomb/empty/New()
+ ..()
+ wires.CutAll()
+
+/obj/machinery/syndicatebomb/self_destruct
+ name = "self destruct device"
+ desc = "Do not taunt. Warranty invalid if exposed to high temperature. Not suitable for agents under 3 years of age."
+ payload = /obj/item/weapon/bombcore/large
+ can_unanchor = FALSE
///Bomb Cores///
@@ -196,17 +287,26 @@
origin_tech = "syndicate=5;combat=6"
burn_state = FLAMMABLE //Burnable (but the casing isn't)
var/adminlog = null
+ var/range_heavy = 3
+ var/range_medium = 9
+ var/range_light = 17
+ var/range_flame = 17
/obj/item/weapon/bombcore/ex_act(severity) //Little boom can chain a big boom
- src.detonate()
+ detonate()
+
+
+/obj/item/weapon/bombcore/burn()
+ detonate()
+ ..()
/obj/item/weapon/bombcore/proc/detonate()
if(adminlog)
message_admins(adminlog)
log_game(adminlog)
- explosion(get_turf(src),3,9,17, flame_range = 17)
- if(src.loc && istype(src.loc,/obj/machinery/syndicatebomb/))
- qdel(src.loc)
+ explosion(get_turf(src), range_heavy, range_medium, range_light, flame_range = range_flame)
+ if(loc && istype(loc, /obj/machinery/syndicatebomb))
+ qdel(loc)
qdel(src)
/obj/item/weapon/bombcore/proc/defuse()
@@ -223,17 +323,20 @@
var/attempts = 0
/obj/item/weapon/bombcore/training/proc/reset()
- var/obj/machinery/syndicatebomb/holder = src.loc
+ var/obj/machinery/syndicatebomb/holder = loc
if(istype(holder))
if(holder.wires)
holder.wires.Shuffle()
holder.defused = 0
holder.open_panel = 0
+ holder.delayedbig = FALSE
+ holder.delayedlittle = FALSE
+ holder.explode_now = FALSE
holder.update_icon()
holder.updateDialog()
/obj/item/weapon/bombcore/training/detonate()
- var/obj/machinery/syndicatebomb/holder = src.loc
+ var/obj/machinery/syndicatebomb/holder = loc
if(istype(holder))
attempts++
holder.loc.visible_message("[bicon(holder)] Alert: Bomb has detonated. Your score is now [defusals] for [attempts]. Resetting wires...")
@@ -242,7 +345,7 @@
qdel(src)
/obj/item/weapon/bombcore/training/defuse()
- var/obj/machinery/syndicatebomb/holder = src.loc
+ var/obj/machinery/syndicatebomb/holder = loc
if(istype(holder))
attempts++
defusals++
@@ -257,11 +360,11 @@
origin_tech = null
/obj/item/weapon/bombcore/badmin/defuse() //because we wouldn't want them being harvested by players
- var/obj/machinery/syndicatebomb/B = src.loc
+ var/obj/machinery/syndicatebomb/B = loc
qdel(B)
qdel(src)
-/obj/item/weapon/bombcore/badmin/summon/
+/obj/item/weapon/bombcore/badmin/summon
var/summon_path = /obj/item/weapon/reagent_containers/food/snacks/cookie
var/amt_summon = 1
@@ -285,42 +388,165 @@
playsound(src.loc, 'sound/misc/sadtrombone.ogg', 50)
..()
-/obj/item/weapon/bombcore/badmin/explosion/
- var/HeavyExplosion = 2
- var/MediumExplosion = 5
- var/LightExplosion = 11
- var/Flames = 11
+/obj/item/weapon/bombcore/large
+ name = "large bomb payload"
+ range_heavy = 5
+ range_medium = 10
+ range_light = 20
+ range_flame = 20
-/obj/item/weapon/bombcore/badmin/explosion/detonate()
- explosion(get_turf(src),HeavyExplosion,MediumExplosion,LightExplosion, flame_range = Flames)
+/obj/item/weapon/bombcore/large/underwall
+ layer = ABOVE_OPEN_TURF_LAYER
/obj/item/weapon/bombcore/miniature
name = "small bomb core"
w_class = WEIGHT_CLASS_SMALL
+ range_heavy = 1
+ range_medium = 2
+ range_light = 4
+ range_flame = 2
-/obj/item/weapon/bombcore/miniature/detonate()
- explosion(src.loc,1,2,4,flame_range = 2) //Identical to a minibomb
+/obj/item/weapon/bombcore/chemical
+ name = "chemical payload"
+ desc = "An explosive payload designed to spread chemicals, dangerous or otherwise, across a large area. It is able to hold up to four chemical containers, and must be loaded before use."
+ origin_tech = "combat=4;materials=3"
+ icon_state = "chemcore"
+ var/list/beakers = list()
+ var/max_beakers = 1
+ var/spread_range = 5
+ var/temp_boost = 50
+ var/time_release = 0
+
+/obj/item/weapon/bombcore/chemical/detonate()
+
+ if(time_release > 0)
+ var/total_volume = 0
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ total_volume += RC.reagents.total_volume
+
+ if(total_volume < time_release) // If it's empty, the detonation is complete.
+ if(loc && istype(loc, /obj/machinery/syndicatebomb))
+ qdel(loc)
+ qdel(src)
+ return
+
+ var/fraction = time_release/total_volume
+ var/datum/reagents/reactants = new(time_release)
+ reactants.my_atom = src
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ RC.reagents.trans_to(reactants, RC.reagents.total_volume*fraction, 1, 1, 1)
+ chem_splash(get_turf(src), spread_range, list(reactants), temp_boost)
+
+ // Detonate it again in one second, until it's out of juice.
+ addtimer(src, "detonate", 10)
+
+ // If it's not a time release bomb, do normal explosion
+
+ var/list/reactants = list()
+
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ reactants += G.reagents
+
+ for(var/obj/item/slime_extract/S in beakers)
+ if(S.Uses)
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ G.reagents.trans_to(S, G.reagents.total_volume)
+
+ if(S && S.reagents && S.reagents.total_volume)
+ reactants += S.reagents
+
+ if(!chem_splash(get_turf(src), spread_range, reactants, temp_boost))
+ playsound(loc, 'sound/items/Screwdriver2.ogg', 50, 1)
+ return // The Explosion didn't do anything. No need to log, or disappear.
+
+ if(adminlog)
+ message_admins(adminlog)
+ log_game(adminlog)
+
+ playsound(loc, 'sound/effects/bamf.ogg', 75, 1, 5)
+
+ if(loc && istype(loc, /obj/machinery/syndicatebomb))
+ qdel(loc)
qdel(src)
+/obj/item/weapon/bombcore/chemical/attackby(obj/item/I, mob/user, params)
+ if(iscrowbar(I) && beakers.len > 0)
+ playsound(loc, I.usesound, 50, 1)
+ for (var/obj/item/B in beakers)
+ B.loc = get_turf(src)
+ beakers -= B
+ return
+ else if(istype(I, /obj/item/weapon/reagent_containers/glass/beaker) || istype(I, /obj/item/weapon/reagent_containers/glass/bottle))
+ if(beakers.len < max_beakers)
+ if(!user.drop_item())
+ return
+ beakers += I
+ to_chat(user, "You load [src] with [I].")
+ I.loc = src
+ else
+ to_chat(user, "The [I] wont fit! The [src] can only hold up to [max_beakers] containers.")
+ return
+ ..()
+
+/obj/item/weapon/bombcore/chemical/CheckParts(list/parts_list)
+ ..()
+ // Using different grenade casings, causes the payload to have different properties.
+ var/obj/item/weapon/stock_parts/matter_bin/MB = locate(/obj/item/weapon/stock_parts/matter_bin) in src
+ if(MB)
+ max_beakers += MB.rating // max beakers = 2-5.
+ qdel(MB)
+ for(var/obj/item/weapon/grenade/chem_grenade/G in src)
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/large))
+ var/obj/item/weapon/grenade/chem_grenade/large/LG = G
+ max_beakers += 1 // Adding two large grenades only allows for a maximum of 7 beakers.
+ spread_range += 2 // Extra range, reduced density.
+ temp_boost += 50 // maximum of +150K blast using only large beakers. Not enough to self ignite.
+ for(var/obj/item/slime_extract/S in LG.beakers) // And slime cores.
+ if(beakers.len < max_beakers)
+ beakers += S
+ S.loc = src
+ else
+ S.loc = get_turf(src)
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/cryo))
+ spread_range -= 1 // Reduced range, but increased density.
+ temp_boost -= 100 // minimum of -150K blast.
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/pyro))
+ temp_boost += 150 // maximum of +350K blast, which is enough to self ignite. Which means a self igniting bomb can't take advantage of other grenade casing properties. Sorry?
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/adv_release))
+ time_release += 50 // A typical bomb, using basic beakers, will explode over 2-4 seconds. Using two will make the reaction last for less time, but it will be more dangerous overall.
+
+ for(var/obj/item/weapon/reagent_containers/glass/B in G)
+ if(beakers.len < max_beakers)
+ beakers += B
+ B.loc = src
+ else
+ B.loc = get_turf(src)
+
+ qdel(G)
+
///Syndicate Detonator (aka the big red button)///
/obj/item/device/syndicatedetonator
name = "big red button"
- desc = "Nothing good can come of pressing a button this garish..."
+ desc = "Your standard issue bomb synchronizing button. Five second safety delay to prevent 'accidents'."
icon = 'icons/obj/assemblies.dmi'
icon_state = "bigred"
item_state = "electronic"
w_class = WEIGHT_CLASS_TINY
origin_tech = "syndicate=3"
- var/cooldown = 0
+ var/timer = 0
var/detonated = 0
var/existant = 0
-/obj/item/device/syndicatedetonator/attack_self(mob/user as mob)
- if(!cooldown)
+/obj/item/device/syndicatedetonator/attack_self(mob/user)
+ if(timer < world.time)
for(var/obj/machinery/syndicatebomb/B in machines)
if(B.active)
- B.timer = 0
+ B.detonation_timer = world.time + BUTTON_DELAY
detonated++
existant++
playsound(user, 'sound/machines/click.ogg', 20, 1)
@@ -334,5 +560,7 @@
log_game("[key_name(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] ([T.x],[T.y],[T.z])")
detonated = 0
existant = 0
- cooldown = 1
- spawn(30) cooldown = 0
+ timer = world.time + BUTTON_COOLDOWN
+
+#undef BUTTON_COOLDOWN
+#undef BUTTON_DELAY
\ No newline at end of file
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index ae198664806..294dda0d674 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -4,7 +4,6 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
name = "item"
icon = 'icons/obj/items.dmi'
var/discrete = 0 // used in item_attack.dm to make an item not show an attack message to viewers
- var/no_embed = 0 // For use in item_attack.dm
var/image/blood_overlay = null //this saves our blood splatter overlay, which will be processed not to go over the edges of the sprite
var/blood_overlay_color = null
var/item_state = null
@@ -63,6 +62,17 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d
var/mob/thrownby = null
+ //So items can have custom embedd values
+ //Because customisation is king
+ var/embed_chance = EMBED_CHANCE
+ var/embedded_fall_chance = EMBEDDED_ITEM_FALLOUT
+ var/embedded_pain_chance = EMBEDDED_PAIN_CHANCE
+ var/embedded_pain_multiplier = EMBEDDED_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does while embedded (this*w_class)
+ var/embedded_fall_pain_multiplier = EMBEDDED_FALL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when falling out of a limb (this*w_class)
+ var/embedded_impact_pain_multiplier = EMBEDDED_IMPACT_PAIN_MULTIPLIER //The coefficient of multiplication for the damage this item does when first embedded (this*w_class)
+ var/embedded_unsafe_removal_pain_multiplier = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER //The coefficient of multiplication for the damage removing this without surgery causes (this*w_class)
+ var/embedded_unsafe_removal_time = EMBEDDED_UNSAFE_REMOVAL_TIME //A time in ticks, multiplied by the w_class.
+
var/toolspeed = 1 // If this item is a tool, the speed multiplier
/* Species-specific sprites, concept stolen from Paradise//vg/.
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 3c9c0211663..3d1f1001b06 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -247,6 +247,13 @@ var/global/list/default_medbay_channels = list(
A.name = from
A.role = role
A.message = message
+ var/jammed = FALSE
+ for(var/obj/item/device/jammer/jammer in active_jammers)
+ if(get_dist(get_turf(src), get_turf(jammer)) < jammer.range)
+ jammed = TRUE
+ break
+ if(jammed)
+ message = Gibberish(message, 100)
Broadcast_Message(connection, A,
0, "*garbled automated announcement*", src,
message, from, "Automated Announcement", from, "synthesized voice",
@@ -332,6 +339,12 @@ var/global/list/default_medbay_channels = list(
var/datum/radio_frequency/connection = message_mode
var/turf/position = get_turf(src)
+ var/jammed = FALSE
+ for(var/obj/item/device/jammer/jammer in active_jammers)
+ if(get_dist(position, get_turf(jammer)) < jammer.range)
+ jammed = TRUE
+ break
+
//#### Tagging the signal with all appropriate identity values ####//
// ||-- The mob's name identity --||
@@ -345,6 +358,9 @@ var/global/list/default_medbay_channels = list(
var/jobname // the mob's "job"
+ if(jammed)
+ message = Gibberish(message, 100)
+
// --- Human: use their actual job ---
if(ishuman(M))
var/mob/living/carbon/human/H = M
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 5f140f05d03..6b48dea1910 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -146,3 +146,22 @@ effective or pretty fucking useless.
attack_self(usr)
add_fingerprint(usr)
return
+
+/obj/item/device/jammer
+ name = "radio jammer"
+ desc = "Device used to disrupt nearby radio communication."
+ icon_state = "jammer"
+ var/active = FALSE
+ var/range = 12
+
+/obj/item/device/jammer/Destroy()
+ active_jammers -= src
+ return ..()
+
+/obj/item/device/jammer/attack_self(mob/user)
+ to_chat(user,"You [active ? "deactivate" : "activate"] the [src].")
+ active = !active
+ if(active)
+ active_jammers |= src
+ else
+ active_jammers -= src
\ No newline at end of file
diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm
index 5f55a5acdcc..dccc8f041f6 100644
--- a/code/game/objects/items/latexballoon.dm
+++ b/code/game/objects/items/latexballoon.dm
@@ -59,5 +59,5 @@
var/obj/item/weapon/tank/T = W
blow(T, user)
return
- if(is_sharp(W) || is_hot(W) || can_puncture(W))
+ if(is_sharp(W) || is_hot(W) || is_pointed(W))
burst()
diff --git a/code/game/objects/items/policetape.dm b/code/game/objects/items/policetape.dm
index 56fd5eadbad..bea99b5d98b 100644
--- a/code/game/objects/items/policetape.dm
+++ b/code/game/objects/items/policetape.dm
@@ -174,7 +174,7 @@ var/list/tape_roll_applications = list()
breaktape(/obj/item/weapon/wirecutters,user)
/obj/item/tape/proc/breaktape(obj/item/weapon/W as obj, mob/user as mob)
- if(user.a_intent == INTENT_HELP && ((!can_puncture(W) && src.allowed(user))))
+ if(user.a_intent == INTENT_HELP && ((!is_pointed(W) && src.allowed(user))))
to_chat(user, "You can't break the [src] with that!")
return
user.visible_message("[user] breaks the [src]!", "You break the [src]!")
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 67755655fe3..029cb8cd4a5 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -123,6 +123,7 @@ var/global/list/datum/stack_recipe/metal_recipes = list(
*/
var/global/list/datum/stack_recipe/plasteel_recipes = list(
new /datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = 1),
+ new /datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50),
new /datum/stack_recipe("Surgery Table", /obj/machinery/optable, 5, time = 50, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("Metal crate", /obj/structure/closet/crate, 10, time = 50, one_per_turf = 1),
new /datum/stack_recipe("Mass Driver frame", /obj/machinery/mass_driver_frame, 3, time = 50, one_per_turf = 1)
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index f21914a7c32..707eac2fbce 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -19,6 +19,9 @@
var/obj/item/device/assembly_holder/nadeassembly = null
var/label = null
var/assemblyattacher
+ var/ignition_temp = 10 // The amount of heat added to the reagents when this grenade goes off.
+ var/threatscale = 1 // Used by advanced grenades to make them slightly more worthy.
+ var/no_splash = FALSE //If the grenade deletes even if it has no reagents to splash with. Used for slime core reactions.
/obj/item/weapon/grenade/chem_grenade/New()
create_reagents(1000)
@@ -99,6 +102,7 @@
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])")
bombers += "[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])"
to_chat(user, "You prime the [name]! [det_time / 10] second\s!")
+ playsound(user.loc, 'sound/weapons/armbomb.ogg', 60, 1)
active = 1
update_icon()
if(iscarbon(user))
@@ -264,13 +268,18 @@
if(stage != READY)
return
- var/has_reagents = 0
+ var/list/datum/reagents/reactants = list()
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- if(G.reagents.total_volume)
- has_reagents = 1
+ reactants += G.reagents
- if(!has_reagents)
- playsound(loc, usesound, 50, 1)
+ if(!chem_splash(get_turf(src), affected_area, reactants, ignition_temp, threatscale) && !no_splash)
+ playsound(loc, 'sound/items/Screwdriver2.ogg', 50, 1)
+ if(beakers.len)
+ for(var/obj/O in beakers)
+ O.forceMove(get_turf(src))
+ beakers = list()
+ stage = EMPTY
+ update_icon()
return
if(nadeassembly)
@@ -281,31 +290,9 @@
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)](?) ([admin_jump_link(M)]) and last touched by [key_name_admin(last)](?) ([admin_jump_link(last)]) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP).")
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
- playsound(loc, 'sound/effects/bamf.ogg', 50, 1)
-
update_mob()
- invisibility = INVISIBILITY_MAXIMUM //kaboom
- qdel(nadeassembly) // do this now to stop infrared beams
- var/end_temp = 0
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- G.reagents.trans_to(src, G.reagents.total_volume)
- end_temp += G.reagents.chem_temp
- reagents.chem_temp = end_temp
- if(reagents.total_volume) //The possible reactions didnt use up all reagents.
- var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread()
- steam.set_up(10, 0, get_turf(src))
- steam.attach(src)
- steam.start()
-
- for(var/atom/A in view(affected_area, loc))
- if(A == src)
- continue
- reagents.reaction(A, 1, 10)
-
-
- spawn(15) //Making sure all reagents can work
- qdel(src) //correctly before deleting the grenade.
+ qdel(src)
/obj/item/weapon/grenade/chem_grenade/proc/CreateDefaultTrigger(var/typekey)
if(ispath(typekey,/obj/item/device/assembly))
@@ -327,64 +314,37 @@
//Large chem grenades accept slime cores and use the appropriately.
/obj/item/weapon/grenade/chem_grenade/large
name = "large grenade casing"
- desc = "For oversized grenades; fits additional contents and affects a greater area."
+ desc = "A custom made large grenade. It affects a larger area."
icon_state = "large_grenade"
bomb_state = "largebomb"
allowed_containers = list(/obj/item/weapon/reagent_containers/glass,/obj/item/weapon/reagent_containers/food/condiment,
/obj/item/weapon/reagent_containers/food/drinks)
origin_tech = "combat=3;engineering=3"
- affected_area = 4
-
+ affected_area = 5
+ ignition_temp = 25 // Large grenades are slightly more effective at setting off heat-sensitive mixtures than smaller grenades.
+ threatscale = 1.1 // 10% more effective.
/obj/item/weapon/grenade/chem_grenade/large/prime()
if(stage != READY)
return
- var/has_reagents = 0
- var/obj/item/slime_extract/valid_core = null
+ for(var/obj/item/slime_extract/S in beakers)
+ if(S.Uses)
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ G.reagents.trans_to(S, G.reagents.total_volume)
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- if(!istype(G)) continue
- if(G.reagents.total_volume) has_reagents = 1
- for(var/obj/item/slime_extract/E in beakers)
- if(!istype(E)) continue
- if(E.Uses) valid_core = E
- if(E.reagents.total_volume) has_reagents = 1
+ //If there is still a core (sometimes it's used up)
+ //and there are reagents left, behave normally,
+ //otherwise drop it on the ground for timed reactions like gold.
- if(!has_reagents)
- playsound(loc, prime_sound, 50, 1)
- return
-
- playsound(loc, 'sound/effects/bamf.ogg', 50, 1)
-
- update_mob()
-
- if(valid_core)
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- G.reagents.trans_to(valid_core, G.reagents.total_volume)
-
- //If there is still a core (sometimes it's used up)
- //and there are reagents left, behave normally
-
- if(valid_core && valid_core.reagents && valid_core.reagents.total_volume)
- valid_core.reagents.trans_to(src,valid_core.reagents.total_volume)
- else
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- G.reagents.trans_to(src, G.reagents.total_volume)
-
- if(reagents.total_volume) //The possible reactions didnt use up all reagents.
- var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread()
- steam.set_up(10, 0, get_turf(src))
- steam.attach(src)
- steam.start()
-
- for(var/atom/A in view(affected_area, loc))
- if( A == src ) continue
- reagents.reaction(A, 1, 10)
-
- invisibility = INVISIBILITY_MAXIMUM //Why am i doing this?
- spawn(50) //To make sure all reagents can work
- qdel(src) //correctly before deleting the grenade.
+ if(S)
+ if(S.reagents && S.reagents.total_volume)
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ S.reagents.trans_to(G, S.reagents.total_volume)
+ else
+ S.forceMove(get_turf(src))
+ no_splash = TRUE
+ ..()
//I tried to just put it in the allowed_containers list but
@@ -399,6 +359,71 @@
else
return ..()
+/obj/item/weapon/grenade/chem_grenade/cryo // Intended for rare cryogenic mixes. Cools the area moderately upon detonation.
+ name = "cryo grenade"
+ desc = "A custom made cryogenic grenade. It rapidly cools its contents upon detonation."
+ icon_state = "cryog"
+ affected_area = 2
+ ignition_temp = -100
+
+/obj/item/weapon/grenade/chem_grenade/pyro // Intended for pyrotechnical mixes. Produces a small fire upon detonation, igniting potentially flammable mixtures.
+ name = "pyro grenade"
+ desc = "A custom made pyrotechnical grenade. It heats up and ignites its contents upon detonation."
+ icon_state = "pyrog"
+ origin_tech = "combat=4;engineering=4"
+ affected_area = 3
+ ignition_temp = 500 // This is enough to expose a hotspot.
+
+/obj/item/weapon/grenade/chem_grenade/adv_release // Intended for weaker, but longer lasting effects. Could have some interesting uses.
+ name = "advanced release grenade"
+ desc = "A custom made advanced release grenade. It is able to be detonated more than once. Can be configured using a multitool."
+ icon_state = "timeg"
+ origin_tech = "combat=3;engineering=4"
+ var/unit_spread = 10 // Amount of units per repeat. Can be altered with a multitool.
+
+/obj/item/weapon/grenade/chem_grenade/adv_release/attackby(obj/item/I, mob/user, params)
+ if(ismultitool(I))
+ switch(unit_spread)
+ if(0 to 24)
+ unit_spread += 5
+ if(25 to 99)
+ unit_spread += 25
+ else
+ unit_spread = 5
+ to_chat(user, " You set the time release to [unit_spread] units per detonation.")
+ return
+ ..()
+
+/obj/item/weapon/grenade/chem_grenade/adv_release/prime()
+ if(stage != READY)
+ return
+
+ var/total_volume = 0
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ total_volume += RC.reagents.total_volume
+ if(!total_volume)
+ qdel(src)
+ qdel(nadeassembly)
+ return
+ var/fraction = unit_spread/total_volume
+ var/datum/reagents/reactants = new(unit_spread)
+ reactants.my_atom = src
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ RC.reagents.trans_to(reactants, RC.reagents.total_volume*fraction, threatscale, 1, 1)
+ chem_splash(get_turf(src), affected_area, list(reactants), ignition_temp, threatscale)
+
+ if(nadeassembly)
+ var/mob/M = get_mob_by_ckey(assemblyattacher)
+ var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
+ var/turf/T = get_turf(src)
+ var/area/A = get_area(T)
+ message_admins("grenade primed by an assembly, attached by [key_name_admin(M)](?) (FLW) and last touched by [key_name_admin(last)](?) (FLW) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP).")
+ log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
+ else
+ addtimer(src, "prime", det_time)
+ var/turf/DT = get_turf(src)
+ var/area/DA = get_area(DT)
+ log_game("A grenade detonated at [DA.name] ([DT.x], [DT.y], [DT.z])")
/obj/item/weapon/grenade/chem_grenade/metalfoam
payload_name = "metal foam"
diff --git a/code/game/objects/items/weapons/implants/implant_death_alarm.dm b/code/game/objects/items/weapons/implants/implant_death_alarm.dm
index da9560122ad..d4807a18701 100644
--- a/code/game/objects/items/weapons/implants/implant_death_alarm.dm
+++ b/code/game/objects/items/weapons/implants/implant_death_alarm.dm
@@ -35,7 +35,7 @@
var/mob/M = imp_in
var/area/t = get_area(M)
- var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null)
+ var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(src)
a.follow_target = M
switch(cause)
@@ -52,7 +52,7 @@
else
a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm")
qdel(src)
-
+
qdel(a)
/obj/item/weapon/implant/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this
diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm
index c642226a8d6..82c6b14f880 100644
--- a/code/game/objects/items/weapons/kitchen.dm
+++ b/code/game/objects/items/weapons/kitchen.dm
@@ -98,7 +98,6 @@
throw_range = 6
materials = list(MAT_METAL=12000)
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
- no_embed = 1
sharp = 1
edge = 1
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 2bb2924837d..810be365fa8 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -6,7 +6,6 @@
var/w_class_on = WEIGHT_CLASS_BULKY
var/icon_state_on = "axe1"
var/list/attack_verb_on = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
- no_embed = 1 // Physically impossible for energy weapons to embed themselves into people, this should fix that. -- Dave
hitsound = 'sound/weapons/blade1.ogg' // Probably more appropriate than the previous hitsound. -- Dave
usesound = 'sound/weapons/blade1.ogg'
toolspeed = 1
@@ -25,6 +24,7 @@
force = force_on
throwforce = throwforce_on
hitsound = 'sound/weapons/blade1.ogg'
+ throw_speed = 4
if(attack_verb_on.len)
attack_verb = attack_verb_on
if(!item_color)
@@ -38,6 +38,7 @@
force = initial(force)
throwforce = initial(throwforce)
hitsound = initial(hitsound)
+ throw_speed = initial(throw_speed)
if(attack_verb_on.len)
attack_verb = list()
icon_state = initial(icon_state)
@@ -85,6 +86,8 @@
throw_speed = 3
throw_range = 5
hitsound = "swing_hit"
+ embed_chance = 75
+ embedded_impact_pain_multiplier = 10
armour_penetration = 35
origin_tech = "combat=3;magnets=4;syndicate=4"
block_chance = 50
diff --git a/code/game/objects/items/weapons/shards.dm b/code/game/objects/items/weapons/shards.dm
index 554347224eb..272e66ee11a 100644
--- a/code/game/objects/items/weapons/shards.dm
+++ b/code/game/objects/items/weapons/shards.dm
@@ -88,28 +88,4 @@
if(affecting.take_damage(5, 0))
H.UpdateDamageIcon()
H.updatehealth()
- ..()
-
-// Shrapnel
-
-/obj/item/weapon/shard/shrapnel
- name = "shrapnel"
- icon = 'icons/obj/shards.dmi'
- icon_state = "shrapnellarge"
- desc = "A bunch of tiny bits of shattered metal."
-
-/obj/item/weapon/shard/shrapnel/New()
-
- src.icon_state = pick("shrapnellarge", "shrapnelmedium", "shrapnelsmall")
- switch(src.icon_state)
- if("shrapnelsmall")
- src.pixel_x = rand(-12, 12)
- src.pixel_y = rand(-12, 12)
- if("shrapnelmedium")
- src.pixel_x = rand(-8, 8)
- src.pixel_y = rand(-8, 8)
- if("shrapnellarge")
- src.pixel_x = rand(-5, 5)
- src.pixel_y = rand(-5, 5)
- else
- return
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 9efc5f625a6..c5f32121d4f 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -157,6 +157,22 @@
new /obj/item/weapon/grenade/empgrenade(src)
new /obj/item/weapon/implanter/emp/(src)
+/obj/item/weapon/storage/box/syndie_kit/throwing_weapons
+ name = "boxed throwing kit"
+ can_hold = list(/obj/item/weapon/throwing_star, /obj/item/weapon/restraints/legcuffs/bola/tactical)
+ max_combined_w_class = 16
+ max_w_class = WEIGHT_CLASS_NORMAL
+
+/obj/item/weapon/storage/box/syndie_kit/throwing_weapons/New()
+ ..()
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/throwing_star(src)
+ new /obj/item/weapon/restraints/legcuffs/bola/tactical(src)
+ new /obj/item/weapon/restraints/legcuffs/bola/tactical(src)
+
/obj/item/weapon/storage/box/syndie_kit/sarin
name = "Sarin Gas Grenades"
diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm
index c07c658a7bf..11da88ae680 100644
--- a/code/game/objects/items/weapons/teleportation.dm
+++ b/code/game/objects/items/weapons/teleportation.dm
@@ -128,7 +128,7 @@ Frequency:
if(turfs.len)
L["None (Dangerous)"] = pick(turfs)
var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") as null|anything in L
- if(!t1 || (user.is_in_active_hand(src) || user.stat || user.restrained()))
+ if(!t1 || (!user.is_in_active_hand(src) || user.stat || user.restrained()))
return
if(active_portals >= 3)
user.show_message("\The [src] is recharging!")
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index cdd8b8a5de1..9f4ebf36611 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -210,7 +210,6 @@
block_chance = 75
sharp = 1
edge = 1
- no_embed = 1 // Like with the single-handed esword, this shouldn't be embedding in people.
/obj/item/weapon/twohanded/dualsaber/New()
blade_color = pick("red", "blue", "green", "purple")
@@ -500,7 +499,6 @@
attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered")
sharp = 1
edge = 1
- no_embed = 1
/obj/item/weapon/twohanded/chainsaw/update_icon()
if(wielded)
@@ -539,7 +537,6 @@
icon_state = "mjollnir0"
flags = CONDUCT
slot_flags = SLOT_BACK
- no_embed = 1
force = 5
force_unwielded = 5
force_wielded = 20
@@ -604,7 +601,6 @@
icon_state = "mjollnir0"
flags = CONDUCT
slot_flags = SLOT_BACK
- no_embed = 1
force = 5
force_unwielded = 5
force_wielded = 25
@@ -652,7 +648,6 @@
icon_state = "knighthammer0"
flags = CONDUCT
slot_flags = SLOT_BACK
- no_embed = 1
force = 5
force_unwielded = 5
force_wielded = 30
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index 95317b7f0a6..586b24bc719 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -130,6 +130,21 @@ obj/item/weapon/wirerod/attackby(obj/item/I, mob/user, params)
qdel(I)
qdel(src)
+/obj/item/weapon/throwing_star
+ name = "throwing star"
+ desc = "An ancient weapon still used to this day due to it's ease of lodging itself into victim's body parts"
+ icon_state = "throwingstar"
+ item_state = "eshield0"
+ force = 2
+ throwforce = 20 //This is never used on mobs since this has a 100% embed chance.
+ throw_speed = 4
+ embedded_pain_multiplier = 4
+ w_class = WEIGHT_CLASS_SMALL
+ embed_chance = 100
+ embedded_fall_chance = 0 //Hahaha!
+ sharp = 1
+ edge = 1
+ materials = list(MAT_METAL=500, MAT_GLASS=500)
/obj/item/weapon/spear/kidan
icon_state = "kidanspear"
diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
index d651ad55adb..e9d9781bf0e 100644
--- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
+++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
@@ -251,6 +251,10 @@
new /obj/item/clothing/under/rank/medical/skirt(src)
new /obj/item/clothing/under/rank/medical/skirt(src)
new /obj/item/clothing/head/surgery/purple(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
new /obj/item/clothing/shoes/black(src)
new /obj/item/clothing/shoes/black(src)
new /obj/item/clothing/shoes/black(src)
@@ -406,6 +410,10 @@
new /obj/item/clothing/suit/storage/labcoat(src)
new /obj/item/clothing/mask/surgical(src)
new /obj/item/clothing/mask/surgical(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
/obj/structure/closet/wardrobe/grey
diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm
index 14f1357af87..2cdcfc18376 100644
--- a/code/game/objects/structures/inflatable.dm
+++ b/code/game/objects/structures/inflatable.dm
@@ -96,7 +96,7 @@
/obj/structure/inflatable/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(!istype(W))
return
- if(can_puncture(W))
+ if(is_pointed(W))
visible_message("[user] pierces [src] with [W]!")
deflate(1)
if(W.damtype == BRUTE || W.damtype == BURN)
diff --git a/code/game/objects/structures/signs.dm b/code/game/objects/structures/signs.dm
index 3f4eea3dbf4..b1cf367ba1f 100644
--- a/code/game/objects/structures/signs.dm
+++ b/code/game/objects/structures/signs.dm
@@ -182,10 +182,15 @@
icon_state = "nuke"
/obj/structure/sign/clown
- name = "\improper mech painting"
+ name = "\improper clown painting"
desc = "A painting of the clown and mime. Awwww."
icon_state = "clown"
+/obj/structure/sign/bobross
+ name = "\improper calming painting"
+ desc = "We don't make mistakes, just happy little accidents."
+ icon_state = "bob"
+
/obj/structure/sign/singulo
name = "\improper singulo painting"
desc = "A mesmerizing painting of a singularity. It seems to suck you in..."
diff --git a/code/game/response_team.dm b/code/game/response_team.dm
index 344a9b72054..ebfe10f71e0 100644
--- a/code/game/response_team.dm
+++ b/code/game/response_team.dm
@@ -387,12 +387,13 @@ var/ert_request_answered = 0
/obj/item/clothing/head/helmet/space/hardsuit/ert/commander = 1,
/obj/item/clothing/mask/gas/sechailer/swat = 1,
/obj/item/weapon/restraints/handcuffs = 1,
+ /obj/item/clothing/shoes/magboots = 1,
/obj/item/weapon/storage/lockbox/mindshield = 1
)
/datum/outfit/job/centcom/response_team/commander/gamma
name = "RT Commander (Gamma)"
- shoes = /obj/item/clothing/shoes/combat/swat
+ shoes = /obj/item/clothing/shoes/magboots/advance
gloves = /obj/item/clothing/gloves/combat
suit = /obj/item/clothing/suit/space/hardsuit/ert/commander
glasses = /obj/item/clothing/glasses/hud/security/night
@@ -457,6 +458,7 @@ var/ert_request_answered = 0
backpack_contents = list(
/obj/item/clothing/head/helmet/space/hardsuit/ert/security = 1,
/obj/item/clothing/mask/gas/sechailer = 1,
+ /obj/item/clothing/shoes/magboots = 1,
/obj/item/weapon/storage/box/handcuffs = 1,
/obj/item/weapon/gun/energy/ionrifle/carbine = 1
)
@@ -464,7 +466,7 @@ var/ert_request_answered = 0
/datum/outfit/job/centcom/response_team/security/gamma
name = "RT Security (Gamma)"
has_grenades = TRUE
- shoes = /obj/item/clothing/shoes/combat/swat
+ shoes = /obj/item/clothing/shoes/magboots/advance
gloves = /obj/item/clothing/gloves/combat
suit = /obj/item/clothing/suit/space/hardsuit/ert/security
suit_store = /obj/item/weapon/gun/energy/gun/nuclear
@@ -509,7 +511,7 @@ var/ert_request_answered = 0
/datum/outfit/job/centcom/response_team/engineer/red
name = "RT Engineer (Red)"
- shoes = /obj/item/clothing/shoes/magboots
+ shoes = /obj/item/clothing/shoes/magboots/advance
gloves = /obj/item/clothing/gloves/color/yellow
suit = /obj/item/clothing/suit/space/hardsuit/ert/engineer
suit_store = /obj/item/weapon/tank/emergency_oxygen/engi
@@ -594,12 +596,13 @@ var/ert_request_answered = 0
/obj/item/weapon/storage/firstaid/toxin = 1,
/obj/item/weapon/storage/firstaid/adv = 1,
/obj/item/weapon/storage/firstaid/surgery = 1,
- /obj/item/weapon/gun/energy/gun = 1
+ /obj/item/weapon/gun/energy/gun = 1,
+ /obj/item/clothing/shoes/magboots = 1
)
/datum/outfit/job/centcom/response_team/medic/gamma
name = "RT Medic (Gamma)"
- shoes = /obj/item/clothing/shoes/combat/swat
+ shoes = /obj/item/clothing/shoes/magboots/advance
gloves = /obj/item/clothing/gloves/combat
suit = /obj/item/clothing/suit/space/hardsuit/ert/medical
glasses = /obj/item/clothing/glasses/hud/health/night
diff --git a/code/modules/admin/verbs/gimmick_team.dm b/code/modules/admin/verbs/gimmick_team.dm
index 9aecae47d17..2ca1d3c27df 100644
--- a/code/modules/admin/verbs/gimmick_team.dm
+++ b/code/modules/admin/verbs/gimmick_team.dm
@@ -12,6 +12,7 @@
return
if(alert("Do you want to spawn a Gimmick Team at YOUR CURRENT LOCATION?",,"Yes","No")=="No")
return
+ var/turf/T = get_turf(mob)
var/pick_manually = 0
if(alert("Pick the team members manually? If you select yes, you pick from ghosts. If you select no, ghosts get offered the chance to join.",,"Yes","No")=="Yes")
pick_manually = 1
@@ -34,6 +35,9 @@
var/dresscode = input("Select Outfit", "Dress-a-mob") as null|anything in outfit_list
if(isnull(dresscode))
return
+ var/is_syndicate = 0
+ if(alert("Do you want these characters automatically classified as antagonists?",,"Yes","No")=="Yes")
+ is_syndicate = 1
var/list/players_to_spawn = list()
if(pick_manually)
@@ -55,7 +59,8 @@
return 0
var/datum/outfit/O = outfit_list[dresscode]
- var/turf/T = get_turf(mob)
+
+ var/players_spawned = 0
for(var/mob/thisplayer in players_to_spawn)
var/mob/living/carbon/human/H = new /mob/living/carbon/human(T)
H.name = random_name(pick(MALE,FEMALE))
@@ -67,13 +72,20 @@
H.mind_initialize()
H.mind.assigned_role = "MODE"
H.mind.special_role = "Event Character"
- ticker.mode.traitors |= H.mind //Adds them to extra antag list
H.key = thisplayer.key
H.equipOutfit(O, FALSE)
to_chat(H, " [themission]")
+ H.mind.store_memory("[themission]
")
+
+ if(is_syndicate)
+ ticker.mode.traitors |= H.mind //Adds them to extra antag list
+
+ players_spawned++
+ if(players_spawned >= teamsize)
+ break
message_admins("[key_name_admin(src)] has spawned a Gimmick Team.", 1)
diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm
index 9e40914da9b..5f3cc4dec2b 100644
--- a/code/modules/client/preference/preferences.dm
+++ b/code/modules/client/preference/preferences.dm
@@ -2154,7 +2154,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
else if(status == "cyborg")
if(rlimb_data[name])
- O.robotize(rlimb_data[name])
+ O.robotize(rlimb_data[name], convert_all = 0)
else
O.robotize()
else
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index c7c7c3afcb0..d120ef04528 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -90,7 +90,8 @@
scan_reagents = 1 //You can see reagents while wearing science goggles
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
actions_types = list(/datum/action/item_action/toggle_research_scanner)
@@ -138,7 +139,8 @@
item_state = "eyepatch"
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/monocle
@@ -150,7 +152,8 @@
species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/eyes.dmi',
- "Drask" = 'icons/mob/species/drask/eyes.dmi'
+ "Drask" = 'icons/mob/species/drask/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/material
@@ -163,7 +166,8 @@
species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/eyes.dmi',
- "Drask" = 'icons/mob/species/drask/eyes.dmi'
+ "Drask" = 'icons/mob/species/drask/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/material/cyber
@@ -182,7 +186,8 @@
prescription = 1
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/regular/hipster
@@ -198,7 +203,8 @@
item_state = "3d"
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/gglasses
@@ -208,7 +214,8 @@
item_state = "gglasses"
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
prescription_upgradable = 1
@@ -379,7 +386,8 @@
flash_protect = -1
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
emp_act(severity)
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index 818ed3f2f10..ff8de1a6a82 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -62,7 +62,8 @@
HUDType = DATA_HUD_DIAGNOSTIC
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/hud/diagnostic/night
@@ -85,7 +86,8 @@
species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/eyes.dmi',
- "Drask" = 'icons/mob/species/drask/eyes.dmi'
+ "Drask" = 'icons/mob/species/drask/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/hud/security/chameleon
@@ -138,7 +140,8 @@
HUDType = DATA_HUD_HYDROPONIC
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/hud/hydroponic/night
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index c73a6f21306..ae694f8edf2 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -70,4 +70,8 @@
heat_protection = HEAD
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
cold_protection = HEAD
- min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
\ No newline at end of file
+ min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
+ species_fit = list("Grey")
+ sprite_sheets = list(
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
+ )
\ No newline at end of file
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 1bb6c1ec382..c3595288213 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -13,10 +13,11 @@
max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT
strip_delay = 60
burn_state = FIRE_PROOF
- species_fit = list("Vox", "Drask")
+ species_fit = list("Vox", "Drask", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/helmet.dmi',
- "Drask" = 'icons/mob/species/drask/helmet.dmi'
+ "Drask" = 'icons/mob/species/drask/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
/obj/item/clothing/head/helmet/attack_self(mob/user)
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index aa5a81c2063..ee0610471c8 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -24,12 +24,13 @@
flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE)
actions_types = list(/datum/action/item_action/toggle)
burn_state = FIRE_PROOF
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/head.dmi',
"Unathi" = 'icons/mob/species/unathi/helmet.dmi',
"Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
/obj/item/clothing/head/welding/flamedecal
diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm
index 59081cf3d00..d66daf59760 100644
--- a/code/modules/clothing/masks/boxing.dm
+++ b/code/modules/clothing/masks/boxing.dm
@@ -8,12 +8,13 @@
w_class = WEIGHT_CLASS_SMALL
actions_types = list(/datum/action/item_action/adjust)
adjusted_flags = SLOT_HEAD
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi',
"Drask" = 'icons/mob/species/drask/mask.dmi'
)
@@ -28,12 +29,13 @@
flags = BLOCKHAIR
flags_inv = HIDEFACE
w_class = WEIGHT_CLASS_SMALL
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi',
"Drask" = 'icons/mob/species/drask/mask.dmi'
)
diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm
index 851c10db354..afefbbc93cc 100644
--- a/code/modules/clothing/masks/breath.dm
+++ b/code/modules/clothing/masks/breath.dm
@@ -10,13 +10,14 @@
permeability_coefficient = 0.50
actions_types = list(/datum/action/item_action/adjust)
burn_state = FIRE_PROOF
- species_fit = list("Vox", "Vox Armalis", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Vox Armalis", "Unathi", "Tajaran", "Vulpkanin", "Grey" )
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Vox Armalis" = 'icons/mob/species/armalis/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi',
"Drask" = 'icons/mob/species/drask/mask.dmi'
)
@@ -30,7 +31,7 @@
item_state = "medical"
permeability_coefficient = 0.01
put_on_delay = 10
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
/obj/item/clothing/mask/breath/vox
desc = "A weirdly-shaped breath mask."
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index d524d87e3d8..5ac05685079 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -34,12 +34,13 @@
w_class = WEIGHT_CLASS_TINY
resist_time = 150
mute = 0
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi'
)
/obj/item/clothing/mask/muzzle/tapegag/dropped(mob/living/carbon/human/user)
@@ -65,12 +66,13 @@
permeability_coefficient = 0.01
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 25, rad = 0)
actions_types = list(/datum/action/item_action/adjust)
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi'
)
@@ -83,12 +85,13 @@
icon_state = "fake-moustache"
flags_inv = HIDEFACE
actions_types = list(/datum/action/item_action/pontificate)
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi'
)
/obj/item/clothing/mask/fakemoustache/attack_self(mob/user)
@@ -267,12 +270,13 @@
slot_flags = SLOT_MASK
adjusted_flags = SLOT_HEAD
icon_state = "bandbotany"
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi'
)
actions_types = list(/datum/action/item_action/adjust)
diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm
index 80257cda101..90d61fa0313 100644
--- a/code/modules/clothing/spacesuits/ert.dm
+++ b/code/modules/clothing/spacesuits/ert.dm
@@ -9,6 +9,10 @@
var/obj/machinery/camera/camera
var/has_camera = TRUE
strip_delay = 130
+ species_fit = list("Grey")
+ sprite_sheets = list(
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
+ )
/obj/item/clothing/head/helmet/space/hardsuit/ert/attack_self(mob/user)
if(camera || !has_camera)
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 802f39ad361..5483ca65072 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -20,14 +20,15 @@
"Skrell" = 'icons/mob/species/skrell/helmet.dmi',
"Vox" = 'icons/mob/species/vox/helmet.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi',
- "Drask" = 'icons/mob/species/drask/helmet.dmi'
+ "Drask" = 'icons/mob/species/drask/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
sprite_sheets_obj = list(
"Unathi" = 'icons/obj/clothing/species/unathi/hats.dmi',
"Tajaran" = 'icons/obj/clothing/species/tajaran/hats.dmi',
"Skrell" = 'icons/obj/clothing/species/skrell/hats.dmi',
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi',
- "Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/hats.dmi',
+ "Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/hats.dmi'
)
/obj/item/clothing/head/helmet/space/hardsuit/equip_to_best_slot(mob/M)
@@ -83,7 +84,7 @@
"Tajaran" = 'icons/obj/clothing/species/tajaran/suits.dmi',
"Skrell" = 'icons/obj/clothing/species/skrell/suits.dmi',
"Vox" = 'icons/obj/clothing/species/vox/suits.dmi',
- "Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/suits.dmi',
+ "Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/suits.dmi'
)
//Breach thresholds, should ideally be inherited by most (if not all) hardsuits.
@@ -440,7 +441,10 @@
heat_protection = HEAD //Uncomment to enable firesuit protection
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
unacidable = 1
- sprite_sheets = null
+ species_fit = list("Grey")
+ sprite_sheets = list(
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
+ )
/obj/item/clothing/suit/space/hardsuit/wizard
icon_state = "hardsuit-wiz"
@@ -538,7 +542,6 @@
icon_state = "hardsuit0-hos"
item_color = "hos"
armor = list(melee = 45, bullet = 25, laser = 30,energy = 10, bomb = 25, bio = 100, rad = 50)
- sprite_sheets = null
/obj/item/clothing/suit/space/hardsuit/security/hos
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 20d9809f2b2..60e76418a53 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -8,9 +8,10 @@
permeability_coefficient = 0.01
armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
species_restricted = list("exclude", "Diona", "Wryn")
- species_fit = list("Vox")
+ species_fit = list("Vox", "Grey")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/helmet.dmi'
+ "Vox" = 'icons/mob/species/vox/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
/obj/item/clothing/head/helmet/space/capspace/equipped(mob/living/carbon/human/user, slot)
@@ -136,9 +137,10 @@
desc = "A paramedic EVA helmet. Used in the recovery of bodies from space."
icon_state = "paramedic-eva-helmet"
item_state = "paramedic-eva-helmet"
- species_fit = list("Vox")
+ species_fit = list("Vox", "Grey")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/helmet.dmi'
+ "Vox" = 'icons/mob/species/vox/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
sprite_sheets_obj = list(
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi'
@@ -187,12 +189,13 @@
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
flash_protect = 0
species_restricted = list("exclude", "Diona", "Wryn")
- species_fit = list("Tajaran", "Unathi", "Vox", "Vulpkanin")
+ species_fit = list("Tajaran", "Unathi", "Vox", "Vulpkanin", "Grey")
sprite_sheets = list(
"Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
"Unathi" = 'icons/mob/species/unathi/helmet.dmi',
"Vox" = 'icons/mob/species/vox/helmet.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
sprite_sheets_obj = list(
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi',
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 273dab0c787..eda243a859a 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -116,7 +116,7 @@
armor = list(melee = 10, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 0)
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
flash_protect = 2
-
+
/obj/item/clothing/suit/space/eva/plasmaman/engineer
name = "plasmaman engineer suit"
icon_state = "plasmamanEngineer_suit"
@@ -128,7 +128,7 @@
base_state = "plasmamanEngineer_helmet"
armor = list(melee = 10, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 75)
flash_protect = 2
-
+
/obj/item/clothing/suit/space/eva/plasmaman/engineer/ce
name = "plasmaman chief engineer suit"
icon_state = "plasmaman_CE"
@@ -269,6 +269,24 @@
icon_state = "plasmaman_CMO_helmet0"
base_state = "plasmaman_CMO_helmet"
+/obj/item/clothing/suit/space/eva/plasmaman/medical/coroner
+ name = "plasmaman coroner suit"
+ icon_state = "plasmaman_Coroner"
+
+/obj/item/clothing/head/helmet/space/eva/plasmaman/medical/coroner
+ name = "plasmaman coroner helmet"
+ icon_state = "plasmaman_Coroner_helmet0"
+ base_state = "plasmaman_Coroner_helmet"
+
+/obj/item/clothing/suit/space/eva/plasmaman/medical/virologist
+ name = "plasmaman virologist suit"
+ icon_state = "plasmaman_Virologist"
+
+/obj/item/clothing/head/helmet/space/eva/plasmaman/medical/virologist
+ name = "plasmaman virologist helmet"
+ icon_state = "plasmaman_Virologist_helmet0"
+ base_state = "plasmaman_Virologist_helmet"
+
/obj/item/clothing/suit/space/eva/plasmaman/science
name = "plasmaman scientist suit"
icon_state = "plasmamanScience_suit"
@@ -278,6 +296,15 @@
icon_state = "plasmamanScience_helmet0"
base_state = "plasmamanScience_helmet"
+/obj/item/clothing/suit/space/eva/plasmaman/science/geneticist
+ name = "plasmaman geneticist suit"
+ icon_state = "plasmaman_Geneticist"
+
+/obj/item/clothing/head/helmet/space/eva/plasmaman/science/geneticist
+ name = "plasmaman geneticist helmet"
+ icon_state = "plasmaman_Geneticist_helmet0"
+ base_state = "plasmaman_Geneticist_helmet"
+
/obj/item/clothing/suit/space/eva/plasmaman/science/rd
name = "plasmaman research director suit"
icon_state = "plasmaman_RD"
diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm
index da181368cc5..f1fb29ed645 100644
--- a/code/modules/clothing/spacesuits/rig/rig.dm
+++ b/code/modules/clothing/spacesuits/rig/rig.dm
@@ -978,10 +978,6 @@
else
M.stop_pulling()
- if(wearer.pinned.len)
- to_chat(src, "Your host is pinned to a wall by [wearer.pinned[1]]!")
- return 0
-
// AIs are a bit slower than regular and ignore move intent.
wearer_move_delay = world.time + ai_controlled_move_delay
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 43b89d315d9..a5340ed91bc 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -952,17 +952,17 @@
/obj/item/clothing/suit/tailcoat
name = "victorian tailcoat"
- desc = "a fancy victorian tailcoat."
+ desc = "A fancy victorian tailcoat."
icon_state = "tailcoat"
item_state = "tailcoat"
/obj/item/clothing/suit/victcoat
name = "ladies victorian coat"
- desc = "a fancy victorian coat."
+ desc = "A fancy victorian coat."
icon_state = "ladiesvictoriancoat"
item_state = "ladiesvictoriancoat"
/obj/item/clothing/suit/victcoat/red
name = "ladies red victorian coat"
icon_state = "ladiesredvictoriancoat"
- item_state = "ladiesredvictoriancoat"
\ No newline at end of file
+ item_state = "ladiesredvictoriancoat"
diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm
index 5f358ac58f4..8f4b65e6030 100644
--- a/code/modules/clothing/under/accessories/accessory.dm
+++ b/code/modules/clothing/under/accessories/accessory.dm
@@ -620,7 +620,7 @@
return
var/area/t = get_area(M)
- var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null)
+ var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(src)
if(istype(t, /area/syndicate_station) || istype(t, /area/syndicate_mothership) || istype(t, /area/shuttle/syndicate_elite) )
//give the syndicats a bit of stealth
a.autosay("[M] has been vandalized in Space!", "[M]'s Death Alarm")
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 4fa40404c46..6dc1e1f2991 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -791,10 +791,10 @@
/obj/item/clothing/under/victdress
name = "black victorian dress"
- desc = "a victorian style dress, fancy!."
+ desc = "A victorian style dress, fancy!"
icon_state = "victorianblackdress"
- item_state = "Victorianblackdress"
- item_color = "Victorianblackdress"
+ item_state = "victorianblackdress"
+ item_color = "victorianblackdress"
body_parts_covered = UPPER_TORSO|LOWER_TORSO
/obj/item/clothing/under/victdress/red
@@ -805,7 +805,7 @@
/obj/item/clothing/under/victsuit
name = "victorian suit"
- desc = "a victorian style suit, fancy!."
+ desc = "A victorian style suit, fancy!"
icon_state = "victorianvest"
item_state = "victorianvest"
item_color = "victorianvest"
@@ -822,3 +822,11 @@
icon_state = "victorianredvest"
item_state = "victorianredvest"
item_color = "victorianredvest"
+
+/obj/item/clothing/under/medigown
+ name = "medical gown"
+ desc = "a flimsy examination gown, the back ties never close."
+ icon_state = "medicalgown"
+ item_state = "medicalgown"
+ item_color = "medicalgown"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO
diff --git a/code/modules/countdown/countdown.dm b/code/modules/countdown/countdown.dm
index 2ef85d6a9d7..7e651fb910f 100644
--- a/code/modules/countdown/countdown.dm
+++ b/code/modules/countdown/countdown.dm
@@ -9,15 +9,19 @@
var/atom/attached_to
color = "#ff0000"
var/text_size = 4
- var/started = 0
+ var/started = FALSE
invisibility = INVISIBILITY_OBSERVER
- anchored = 1
- layer = 5
+ anchored = TRUE
+ layer = GHOST_LAYER
/obj/effect/countdown/New(atom/A)
. = ..()
attach(A)
+/obj/effect/countdown/examine(mob/user)
+ . = ..()
+ to_chat(user, "This countdown is displaying: [displayed_text]")
+
/obj/effect/countdown/proc/attach(atom/A)
attached_to = A
loc = get_turf(A)
@@ -25,13 +29,13 @@
/obj/effect/countdown/proc/start()
if(!started)
fast_processing += src
- started = 1
+ started = TRUE
/obj/effect/countdown/proc/stop()
if(started)
maptext = null
fast_processing -= src
- started = 0
+ started = FALSE
/obj/effect/countdown/proc/get_value()
// Get the value from our atom
@@ -56,6 +60,19 @@
fast_processing -= src
return ..()
+/obj/effect/countdown/ex_act(severity) //immune to explosions
+ return
+
+/obj/effect/countdown/syndicatebomb
+ name = "syndicate bomb countdown"
+
+/obj/effect/countdown/syndicatebomb/get_value()
+ var/obj/machinery/syndicatebomb/S = attached_to
+ if(!istype(S))
+ return
+ else if(S.active)
+ return S.seconds_remaining()
+
/obj/effect/countdown/clonepod
name = "cloning pod countdown"
text_size = 1
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index 6f266c121e1..3fbcf39ed08 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -324,6 +324,30 @@
/obj/item/stack/rods = 1)
category = CAT_MISC
+/datum/crafting_recipe/chemical_payload
+ name = "Chemical Payload (C4)"
+ result = /obj/item/weapon/bombcore/chemical
+ reqs = list(
+ /obj/item/weapon/stock_parts/matter_bin = 1,
+ /obj/item/weapon/grenade/plastic/c4 = 1,
+ /obj/item/weapon/grenade/chem_grenade = 2
+ )
+ parts = list(/obj/item/weapon/stock_parts/matter_bin = 1, /obj/item/weapon/grenade/chem_grenade = 2)
+ time = 30
+ category = CAT_WEAPON
+
+/datum/crafting_recipe/chemical_payload2
+ name = "Chemical Payload (gibtonite)"
+ result = /obj/item/weapon/bombcore/chemical
+ reqs = list(
+ /obj/item/weapon/stock_parts/matter_bin = 1,
+ /obj/item/weapon/twohanded/required/gibtonite = 1,
+ /obj/item/weapon/grenade/chem_grenade = 2
+ )
+ parts = list(/obj/item/weapon/stock_parts/matter_bin = 1, /obj/item/weapon/grenade/chem_grenade = 2)
+ time = 50
+ category = CAT_WEAPON
+
/datum/crafting_recipe/bonfire
name = "Bonfire"
time = 60
diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm
index 98fe9fad27f..8b98dac200d 100644
--- a/code/modules/events/event_container.dm
+++ b/code/modules/events/event_container.dm
@@ -137,6 +137,7 @@ var/list/event_last_fired = list()
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mundane News", /datum/event/mundane_news, 300),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)),
+ new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Sentience", /datum/event/sentience, 50),
new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50))
)
diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm
new file mode 100644
index 00000000000..cfa0d24d98e
--- /dev/null
+++ b/code/modules/events/sentience.dm
@@ -0,0 +1,47 @@
+/datum/event/sentience
+
+/datum/event/sentience/start()
+ var/ghostmsg = "Do you want to awaken as a sentient being?"
+ var/list/candidates = pollCandidates(ghostmsg, ROLE_SENTIENT, 1)
+ var/list/potential = list()
+ var/sentience_type = SENTIENCE_ORGANIC
+
+ for(var/mob/living/simple_animal/L in living_mob_list)
+ var/turf/T = get_turf(L)
+ if (T.z != 1)
+ continue
+ if(!(L in player_list) && !L.mind && (L.sentience_type == sentience_type))
+ potential += L
+
+ var/mob/living/simple_animal/SA = pick(potential)
+ var/mob/SG = pick(candidates)
+
+ if(!SA || !SG) //if you can't find either a simple animal or a player, end
+ return FALSE
+
+ var/sentience_report = "[command_name()] Medium-Priority Update"
+
+ var/data = pick("scans from our long-range sensors", "our sophisticated probabilistic models", "our omnipotence", "the communications traffic on your station", "energy emissions we detected", "\[REDACTED\]", "Steve")
+ var/pets = pick("animals", "pets", "simple animals", "lesser lifeforms", "\[REDACTED\]")
+ var/strength = pick("human", "skrell", "vox", "grey", "diona", "IPC", "tajaran", "vulpakanin", "kidan", "plasmaman", "drask",
+ "slime", "monkey", "moderate", "lizard", "security", "command", "clown", "mime", "low", "very low", "greytide", "catgirl", "\[REDACTED\]")
+
+ sentience_report += "
Based on [data], we believe that one of the station's [pets] has developed [strength] level intelligence, and the ability to communicate."
+
+
+
+ SA.key = SG.key
+ SA.universal_speak = 1
+ SA.sentience_act()
+ SA.maxHealth = max(SA.maxHealth, 200)
+ SA.health = SA.maxHealth
+ SA.del_on_death = FALSE
+ greet_sentient(SA)
+ print_command_report(sentience_report, "[command_name()] Update")
+
+/datum/event/sentience/proc/greet_sentient(var/mob/living/carbon/human/M)
+ to_chat(M, "Hello world!")
+ to_chat(M, "Due to freak radiation, you have gained \
+ human level intelligence and the ability to speak and understand \
+ human language!")
+
diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm
index 36d84b0f72d..cc9ed1a27d6 100644
--- a/code/modules/mob/language.dm
+++ b/code/modules/mob/language.dm
@@ -96,6 +96,9 @@
return (copytext(message, length(message)) == "!") ? 2 : 1
/datum/language/proc/broadcast(mob/living/speaker, message, speaker_mask)
+ if(!check_can_speak(speaker))
+ return FALSE
+
log_say("[key_name(speaker)]: ([name]) [message]")
if(!speaker_mask)
@@ -114,6 +117,9 @@
/datum/language/proc/check_special_condition(mob/other, mob/living/speaker)
return TRUE
+/datum/language/proc/check_can_speak(mob/living/speaker)
+ return TRUE
+
/datum/language/proc/get_spoken_verb(msg_end)
switch(msg_end)
if("!")
@@ -292,8 +298,29 @@
/datum/language/grey/broadcast(mob/living/speaker, message, speaker_mask)
..(speaker,message,speaker.real_name)
+/datum/language/grey/check_can_speak(mob/living/speaker)
+ if(ishuman(speaker))
+ var/mob/living/carbon/human/S = speaker
+ var/obj/item/organ/external/rhand = S.get_organ("r_hand")
+ var/obj/item/organ/external/lhand = S.get_organ("l_hand")
+ if((!rhand || !rhand.is_usable()) && (!lhand || !lhand.is_usable()))
+ to_chat(speaker,"You can't communicate without the ability to use your hands!")
+ return FALSE
+ if(speaker.incapacitated(ignore_lying = 1))
+ to_chat(speaker,"You can't communicate while unable to move your hands to your head!")
+ return FALSE
+
+ var/their = "their"
+ if(speaker.gender == "female")
+ their = "her"
+ if(speaker.gender == "male")
+ their = "his"
+ speaker.visible_message("[speaker] touches [their] fingers to [their] temple.") //If placed in grey/broadcast, it will happen regardless of the success of the action.
+
+ return TRUE
+
/datum/language/grey/check_special_condition(mob/living/carbon/human/other, mob/living/carbon/human/speaker)
- if(other in range(7, speaker))
+ if(atoms_share_level(other, speaker))
return TRUE
return FALSE
diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm
index 7a12b570201..daeebf8442f 100644
--- a/code/modules/mob/living/carbon/brain/brain_item.dm
+++ b/code/modules/mob/living/carbon/brain/brain_item.dm
@@ -71,9 +71,9 @@
var/obj/item/organ/internal/brain/B = src
if(!special)
var/mob/living/simple_animal/borer/borer = owner.has_brain_worms()
-
if(borer)
- borer.detach() //Should remove borer if the brain is removed - RR
+ borer.leave_host() //Should remove borer if the brain is removed - RR
+
if(owner.mind && !non_primary)//don't transfer if the owner does not have a mind.
B.transfer_identity(user)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 8caecdb42d7..dd18495cc70 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -244,6 +244,10 @@
if(status == "")
status = "OK"
src.show_message(text("\t []My [] is [].",status=="OK"?"":"",org.name,status),1)
+
+ for(var/obj/item/I in org.embedded_objects)
+ to_chat(src, "\t There is \a [I] embedded in your [org.name]!")
+
if(staminaloss)
if(staminaloss > 30)
to_chat(src, "You're completely exhausted.")
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 206571bec93..bfc2737d4d7 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -90,8 +90,10 @@
if(src) qdel(src)
/mob/living/carbon/human/death(gibbed)
- if(stat == DEAD) return
- if(healths) healths.icon_state = "health5"
+ if(stat == DEAD)
+ return
+ if(healths)
+ healths.icon_state = "health5"
if(!gibbed)
emote("deathgasp") //let the world KNOW WE ARE DEAD
@@ -102,21 +104,8 @@
set_heartattack(FALSE)
//Handle species-specific deaths.
- if(species) species.handle_death(src)
-
- //Handle brain slugs.
- var/obj/item/organ/external/head = get_organ("head")
- var/mob/living/simple_animal/borer/B
-
- if(istype(head))
- for(var/I in head.implants)
- if(istype(I,/mob/living/simple_animal/borer))
- B = I
- if(B)
- if(B.controlling && B.host == src)
- B.detach()
-
- verbs -= /mob/living/carbon/proc/release_control
+ if(species)
+ species.handle_death(src)
callHook("death", list(src, gibbed))
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 693973ab42d..961ee9ffd0b 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -382,6 +382,9 @@
else
wound_flavor_text["[temp.limb_name]"] = ""
+ for(var/obj/item/I in temp.embedded_objects)
+ msg += "[t_He] [t_has] \a [bicon(I)] [I] embedded in [t_his] [temp.name]!\n"
+
//Handles the text strings being added to the actual description.
//If they have something that covers the limb, and it is not missing, put flavortext. If it is covered but bleeding, add other flavortext.
var/display_chest = 0
@@ -438,9 +441,6 @@
if(display_gloves)
msg += "[src] has blood running from under [t_his] gloves!\n"
-
- for(var/implant in get_visible_implants(0))
- msg += "[src] has \a [implant] sticking out of [t_his] flesh!\n"
if(digitalcamo)
msg += "[t_He] [t_is] repulsively uncanny!\n"
if(!(skipface || ( wear_mask && ( wear_mask.flags_inv & HIDEFACE || wear_mask.flags_cover & MASKCOVERSMOUTH) ) ) && is_thrall(src) && in_range(user,src))
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 2fec182504a..8a39920cae1 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -8,7 +8,6 @@
//why are these here and not in human_defines.dm
//var/list/hud_list[10]
var/datum/species/species //Contains icon generation and language information, set during New().
- var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us.
var/obj/item/weapon/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call.
/mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna = 0)
@@ -597,7 +596,7 @@
return
//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere
-/mob/living/carbon/human/get_visible_name()
+/mob/living/carbon/human/get_visible_name(var/id_override = FALSE)
if(name_override)
return name_override
if(wear_mask && (wear_mask.flags_inv & HIDEFACE)) //Wearing a mask which hides our face, use id-name if possible
@@ -606,7 +605,7 @@
return get_id_name("Unknown") //Likewise for hats
var/face_name = get_face_name()
var/id_name = get_id_name("")
- if(id_name && (id_name != face_name))
+ if(id_name && (id_name != face_name) && !id_override)
return "[face_name] (as [id_name])"
return face_name
@@ -700,6 +699,28 @@
if(G && G.pickpocket)
thief_mode = 1
+ if(href_list["embedded_object"])
+ var/obj/item/organ/external/L = locate(href_list["embedded_limb"]) in bodyparts
+ if(!L)
+ return
+ var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects
+ if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore
+ return
+ var/time_taken = I.embedded_unsafe_removal_time*I.w_class
+ usr.visible_message("[usr] attempts to remove [I] from their [L.name].","You attempt to remove [I] from your [L.name]... (It will take [time_taken/10] seconds.)")
+ if(do_after(usr, time_taken, needhand = 1, target = src))
+ if(!I || !L || I.loc != src || !(I in L.embedded_objects))
+ return
+ L.embedded_objects -= I
+ L.take_damage(I.embedded_unsafe_removal_pain_multiplier*I.w_class)//It hurts to rip it out, get surgery you dingus.
+ I.forceMove(get_turf(src))
+ usr.put_in_hands(I)
+ usr.emote("scream")
+ usr.visible_message("[usr] successfully rips [I] out of their [L.name]!","You successfully remove [I] from your [L.name].")
+ if(!has_embedded_objects())
+ clear_alert("embeddedobject")
+ return
+
if(href_list["item"])
var/slot = text2num(href_list["item"])
if(slot in check_obscured_slots())
@@ -1348,16 +1369,6 @@
else
..()
-/mob/living/carbon/human/get_visible_implants(var/class = 0)
-
- var/list/visible_implants = list()
- for(var/obj/item/organ/external/organ in bodyparts)
- for(var/obj/item/weapon/O in organ.implants)
- if(!istype(O,/obj/item/weapon/implant) && (O.w_class > class) && !istype(O,/obj/item/weapon/shard/shrapnel))
- visible_implants += O
-
- return(visible_implants)
-
/mob/living/carbon/human/generate_name()
name = species.makeName(gender,src)
real_name = name
@@ -1365,29 +1376,6 @@
dna.real_name = name
return name
-/mob/living/carbon/human/proc/handle_embedded_objects()
-
- for(var/obj/item/organ/external/organ in bodyparts)
- if(organ.status & ORGAN_SPLINTED) //Splints prevent movement.
- continue
- for(var/obj/item/weapon/O in organ.implants)
- if(!istype(O,/obj/item/weapon/implant) && prob(5)) //Moving with things stuck in you could be bad.
- // All kinds of embedded objects cause bleeding.
- var/msg = null
- switch(rand(1,3))
- if(1)
- msg ="A spike of pain jolts your [organ.name] as you bump [O] inside."
- if(2)
- msg ="Your movement jostles [O] in your [organ.name] painfully."
- if(3)
- msg ="[O] in your [organ.name] twists painfully as you move."
- to_chat(src, msg)
-
- organ.take_damage(rand(1,3), 0, 0)
- if(!(organ.status & ORGAN_ROBOT)) //There is no blood in protheses.
- organ.status |= ORGAN_BLEEDING
- src.adjustToxLoss(rand(1,3))
-
/mob/living/carbon/human/verb/check_pulse()
set category = null
set name = "Check pulse"
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index bbe57fa66f9..917d9d9b0f7 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -8,7 +8,7 @@ emp_act
*/
-/mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone)
+/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone)
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
if(check_reflect(def_zone)) // Checks if you've passed a reflection% check
@@ -41,19 +41,6 @@ emp_act
. = bullet_act(P, "chest") //act on chest instead
return
- //Shrapnel
- if(P.damage_type == BRUTE)
- var/armor = getarmor_organ(organ, "bullet")
- if((P.embed && prob(20 + max(P.damage - armor, -10))))
- var/obj/item/weapon/shard/shrapnel/SP = new()
- (SP.name) = "[P.name] shrapnel"
- if(P.ammo_casing && P.ammo_casing.caliber)
- (SP.desc) = "[SP.desc] It looks like it is a [P.ammo_casing.caliber] caliber round."
- else
- (SP.desc) = "[SP.desc] The round's caliber is unidentifiable."
- (SP.loc) = organ
- organ.embed(SP)
-
organ.add_autopsy_data(P.name, P.damage) // Add the bullet's name to the autopsy data
return (..(P , def_zone))
@@ -297,21 +284,6 @@ emp_act
if(Iforce > 10 || Iforce >= 5 && prob(33))
forcesay(hit_appends) //forcesay checks stat already
-/* //Melee weapon embedded object code. Commented out, as most people on the forums seem to find this annoying and think it does not contribute to general gameplay. - Dave
- if(I.damtype == BRUTE && !I.is_robot_module())
- var/damage = I.force
- if(armor)
- damage /= armor+1
-
- //blunt objects should really not be embedding in things unless a huge amount of force is involved
- var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3)
- var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class
-
- //Sharp objects will always embed if they do enough damage.
- if(((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance))) && (I.no_embed == 0) )
- affecting.embed(I)
- return 1*/
-
//this proc handles being hit by a thrown atom
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
var/obj/item/I
@@ -325,24 +297,19 @@ emp_act
hitpush = 0
skipcatch = 1
blocked = 1
- /*else if(I)
+ else if(I)
if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD)
- if(!I.is_robot_module())
- var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].", I.armour_penetration) //I guess "melee" is the best fit here
- var/sharp = is_sharp(I)
- var/damage = throwpower * (I.throw_speed / 5)
- if(armor)
- damage /= armor + 1
-
- //blunt objects should really not be embedding in things unless a huge amount of force is involved
- var/embed_chance = sharp? damage / I.w_class : damage/(I.w_class * 3)
- var/embed_threshold = sharp? 5 * I.w_class : 15 * I.w_class
-
- //Sharp objects will always embed if they do enough damage.
- //Thrown sharp objects have some momentum already and have a small chance to embed even if the damage is below the threshold
-
- if(((sharp && prob(damage / (10 * I.w_class) * 100)) || (damage > embed_threshold && prob(embed_chance))) && (I.no_embed == 0))
- affecting.embed(I)*/
+ if(can_embed(I))
+ if(prob(I.embed_chance))
+ throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
+ var/obj/item/organ/external/L = pick(bodyparts)
+ L.embedded_objects |= I
+// I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
+ I.forceMove(src)
+ L.take_damage(I.w_class*I.embedded_impact_pain_multiplier)
+ visible_message("[I] embeds itself in [src]'s [L.name]!","[I] embeds itself in your [L.name]!")
+ hitpush = 0
+ skipcatch = 1 //can't catch the now embedded item
return ..()
/mob/living/carbon/human/proc/bloody_hands(var/mob/living/source, var/amount = 2)
@@ -421,5 +388,5 @@ emp_act
/mob/living/carbon/human/water_act(volume, temperature, source)
..()
- if(temperature >= 330) bodytemperature = bodytemperature + (temperature - bodytemperature)
- if(temperature <= 280) bodytemperature = bodytemperature - (bodytemperature - temperature)
+ species.water_act(src,volume,temperature,source)
+
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 5a67b1c09a2..cba5e4eb458 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -40,6 +40,10 @@
if(!client)
species.handle_npc(src)
+ if(stat != DEAD)
+ //Stuff jammed in your limbs hurts
+ handle_embedded_objects()
+
if(stat == DEAD)
handle_decay()
@@ -814,13 +818,6 @@
blinded = 1
stat = UNCONSCIOUS
- if(embedded_flag && !(mob_master.current_cycle % 10))
- var/list/E
- E = get_visible_implants(0)
- if(!E.len)
- embedded_flag = 0
-
-
//Vision //god knows why this is here
var/obj/item/organ/vision
if(species.vision_organ)
@@ -933,6 +930,22 @@
adjustToxLoss(-3)
lastpuke = 0
+/mob/living/carbon/human/proc/handle_embedded_objects()
+ for(var/X in bodyparts)
+ var/obj/item/organ/external/BP = X
+ for(var/obj/item/I in BP.embedded_objects)
+ if(prob(I.embedded_pain_chance))
+ BP.take_damage(I.w_class*I.embedded_pain_multiplier)
+ to_chat(src, "[I] embedded in your [BP.name] hurts!")
+
+ if(prob(I.embedded_fall_chance))
+ BP.take_damage(I.w_class*I.embedded_fall_pain_multiplier)
+ BP.embedded_objects -= I
+ I.forceMove(get_turf(src))
+ visible_message("[I] falls out of [name]'s [BP.name]!","[I] falls out of your [BP.name]!")
+ if(!has_embedded_objects())
+ clear_alert("embeddedobject")
+
/mob/living/carbon/human/handle_changeling()
if(mind)
if(mind.changeling)
diff --git a/code/modules/mob/living/carbon/human/species/plasmaman.dm b/code/modules/mob/living/carbon/human/species/plasmaman.dm
index 9f5d32e838a..4563fb2029f 100644
--- a/code/modules/mob/living/carbon/human/species/plasmaman.dm
+++ b/code/modules/mob/living/carbon/human/species/plasmaman.dm
@@ -49,9 +49,12 @@
var/tank_slot_name = "suit storage"
switch(assigned_role)
- if("Scientist","Geneticist","Roboticist")
+ if("Scientist","Roboticist")
suit=/obj/item/clothing/suit/space/eva/plasmaman/science
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/science
+ if("Geneticist")
+ suit=/obj/item/clothing/suit/space/eva/plasmaman/science/geneticist
+ helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/science/geneticist
if("Research Director")
suit=/obj/item/clothing/suit/space/eva/plasmaman/science/rd
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/science/rd
@@ -103,6 +106,12 @@
if("Chief Medical Officer")
suit=/obj/item/clothing/suit/space/eva/plasmaman/medical/cmo
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/medical/cmo
+ if("Coroner")
+ suit=/obj/item/clothing/suit/space/eva/plasmaman/medical/coroner
+ helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/medical/coroner
+ if("Virologist")
+ suit=/obj/item/clothing/suit/space/eva/plasmaman/medical/virologist
+ helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/medical/virologist
if("Bartender", "Chef")
suit=/obj/item/clothing/suit/space/eva/plasmaman/service
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/service
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index c1d1a169c1d..52e5de89876 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -399,9 +399,6 @@
if(has_gravity(H))
gravity = 1
- if(H.embedded_flag)
- H.handle_embedded_objects() //Moving with objects stuck in you can cause bad times.
-
if(!ignoreslow && gravity)
if(slowdown)
. = slowdown
@@ -743,3 +740,9 @@ It'll return null if the organ doesn't correspond, so include null checks when u
if(H.see_override) //Override all
H.see_invisible = H.see_override
+
+/datum/species/proc/water_act(mob/living/carbon/human/M, volume, temperature, source)
+ if(temperature >= 330)
+ M.bodytemperature = M.bodytemperature + (temperature - M.bodytemperature)
+ if(temperature <= 280)
+ M.bodytemperature = M.bodytemperature - (M.bodytemperature - temperature)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm
index 52c66369fe9..60e71f7e8ab 100644
--- a/code/modules/mob/living/carbon/human/species/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station.dm
@@ -753,6 +753,11 @@
genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED)
..()
+/datum/species/grey/water_act(var/mob/living/carbon/C, volume, temperature, source)
+ ..()
+ C.take_organ_damage(5,min(volume,20))
+ C.emote("scream")
+
/datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H)
var/speech_pref = H.client.prefs.speciesprefs
if(speech_pref)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 90003c12e65..7215c05a8e2 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -512,6 +512,7 @@
human_mob.restore_blood()
human_mob.shock_stage = 0
human_mob.decaylevel = 0
+ human_mob.remove_all_embedded_objects()
restore_all_organs()
surgeries.Cut() //End all surgeries.
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
index 16c8f1a3ef0..3454a6597ab 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
@@ -260,10 +260,6 @@
stored_comms["glass"]++
else if(istype(W,/obj/item/ammo_casing))
stored_comms["metal"]++
- else if(istype(W,/obj/item/weapon/shard/shrapnel))
- stored_comms["metal"]++
- stored_comms["metal"]++
- stored_comms["metal"]++
else if(istype(W,/obj/item/weapon/shard))
stored_comms["glass"]++
stored_comms["glass"]++
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 226e568f09e..aadd5a74c1b 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1052,104 +1052,6 @@ var/list/slot_equipment_priority = list( \
/mob/proc/get_species()
return ""
-/mob/proc/get_visible_implants(var/class = 0)
- var/list/visible_implants = list()
- for(var/obj/item/O in embedded)
- if(O.w_class > class)
- visible_implants += O
- return visible_implants
-
-/mob/proc/yank_out_object()
- set category = "Object"
- set name = "Yank out object"
- set desc = "Remove an embedded item at the cost of bleeding and pain."
- set src in view(1)
-
- if(!isliving(usr) || usr.next_move > world.time)
- return
- usr.changeNext_move(CLICK_CD_RESIST)
-
- if(usr.stat == 1)
- to_chat(usr, "You are unconcious and cannot do that!")
- return
-
- if(usr.restrained())
- to_chat(usr, "You are restrained and cannot do that!")
- return
-
- var/mob/S = src
- var/mob/U = usr
- var/list/valid_objects = list()
- var/self = null
-
- if(S == U)
- self = 1 // Removing object from yourself.
-
- valid_objects = get_visible_implants(0)
- if(!valid_objects.len)
- if(self)
- to_chat(src, "You have nothing stuck in your body that is large enough to remove.")
- else
- to_chat(U, "[src] has nothing stuck in their wounds that is large enough to remove.")
- return
-
- var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects
-
- if(self)
- visible_message("[usr] appears to be trying to extract an object from their body.")
- to_chat(src, "You attempt to get a good grip on [selection] in your body.")
- else
- visible_message("[usr] attempts to get a good grip on [selection] in [S]'s body.")
- to_chat(U, "You attempt to get a good grip on [selection] in [S]'s body.")
-
- if(!do_after(U, 80, target = S))
- return
- if(!selection || !S || !U)
- return
-
- if(self)
- visible_message("[src] rips [selection] out of their body.","You rip [selection] out of your body.")
- else
- visible_message("[usr] rips [selection] out of [src]'s body.","[usr] rips [selection] out of your body.")
- valid_objects = get_visible_implants(0)
- if(valid_objects.len == 1) //Yanking out last object - removing verb.
- src.verbs -= /mob/proc/yank_out_object
-
- if(ishuman(src))
-
- var/mob/living/carbon/human/H = src
- var/obj/item/organ/external/affected
-
- for(var/obj/item/organ/external/organ in H.bodyparts) //Grab the organ holding the implant.
- for(var/obj/item/weapon/O in organ.implants)
- if(O == selection)
- affected = organ
-
- affected.implants -= selection
- H.shock_stage+=10
-
- if(prob(10)) //I'M SO ANEMIC I COULD JUST -DIE-.
- var/datum/wound/internal_bleeding/I = new ()
- affected.wounds += I
- H.custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 1)
-
- if(ishuman(U))
- var/mob/living/carbon/human/human_user = U
- human_user.bloody_hands(H)
-
- selection.forceMove(get_turf(src))
- if(!(U.l_hand && U.r_hand))
- U.put_in_hands(selection)
-
- for(var/obj/item/weapon/O in pinned)
- if(O == selection)
- pinned -= O
- if(!pinned.len)
- anchored = 0
- return 1
-
-
-
/mob/dead/observer/verb/respawn()
set name = "Respawn as NPC"
set category = "Ghost"
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 700e5d912e7..25131513c4d 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -53,8 +53,6 @@
var/lastpuke = 0
var/unacidable = 0
var/can_strip = 1
- var/list/pinned = list() //List of things pinning this creature to walls (see living_defense.dm)
- var/list/embedded = list() //Embedded items, since simple mobs don't have organs.
var/list/languages = list() // For speaking/listening.
var/list/abilities = list() // For species-derived or admin-given powers.
var/list/speak_emote = list("says") // Verbs used when speaking. Defaults to 'say' if speak_emote is null.
@@ -122,6 +120,7 @@
var/has_enabled_antagHUD = 0
var/antagHUD = 0
+ var/can_change_intents = 1 //all mobs can change intents by default.
//Generic list for proc holders. Only way I can see to enable certain verbs/procs. Should be modified if needed.
var/proc_holder_list[] = list()
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index f8b8f7c84d7..43b12417215 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -242,7 +242,7 @@ proc/slur(phrase, var/list/slurletters = ("'"))//use a different list as an inpu
return sanitize(copytext(t,1,MAX_MESSAGE_LEN))
-proc/Gibberish(t, p)//t is the inputted message, and any value higher than 70 for p will cause letters to be replaced instead of added
+/proc/Gibberish(t, p)//t is the inputted message, and any value higher than 70 for p will cause letters to be replaced instead of added
/* Turn text into complete gibberish! */
var/returntext = ""
for(var/i = 1, i <= length(t), i++)
@@ -337,30 +337,31 @@ var/list/intents = list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM)
set name = "a-intent"
set hidden = 1
- if(ishuman(src) || isalienadult(src) || isbrain(src))
- switch(input)
- if(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM)
- a_intent = input
- if("right")
- a_intent = intent_numeric((intent_numeric(a_intent)+1) % 4)
- if("left")
- a_intent = intent_numeric((intent_numeric(a_intent)+3) % 4)
- if(hud_used && hud_used.action_intent)
- hud_used.action_intent.icon_state = "[a_intent]"
+ if(can_change_intents)
+ if(ishuman(src) || isalienadult(src) || isbrain(src))
+ switch(input)
+ if(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM)
+ a_intent = input
+ if("right")
+ a_intent = intent_numeric((intent_numeric(a_intent)+1) % 4)
+ if("left")
+ a_intent = intent_numeric((intent_numeric(a_intent)+3) % 4)
+ if(hud_used && hud_used.action_intent)
+ hud_used.action_intent.icon_state = "[a_intent]"
- else if(isrobot(src) || islarva(src))
- switch(input)
- if(INTENT_HELP)
- a_intent = INTENT_HELP
- if(INTENT_HARM)
- a_intent = INTENT_HARM
- if("right","left")
- a_intent = intent_numeric(intent_numeric(a_intent) - 3)
- if(hud_used && hud_used.action_intent)
- if(a_intent == INTENT_HARM)
- hud_used.action_intent.icon_state = "harm"
- else
- hud_used.action_intent.icon_state = "help"
+ else if(isrobot(src) || islarva(src))
+ switch(input)
+ if(INTENT_HELP)
+ a_intent = INTENT_HELP
+ if(INTENT_HARM)
+ a_intent = INTENT_HARM
+ if("right","left")
+ a_intent = intent_numeric(intent_numeric(a_intent) - 3)
+ if(hud_used && hud_used.action_intent)
+ if(a_intent == INTENT_HARM)
+ hud_used.action_intent.icon_state = "harm"
+ else
+ hud_used.action_intent.icon_state = "help"
/mob/living/verb/mob_sleep()
diff --git a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm
index 20c4e92fd98..a868c0958ea 100644
--- a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm
+++ b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm
@@ -43,7 +43,7 @@
if(!istype(file))
data["error"] = "I/O ERROR: Unable to open file."
else
- data["filedata"] = pencode_to_html(file.stored_data, sign = 0, fields = 0)
+ data["filedata"] = pencode_to_html(file.stored_data, format = 1, sign = 0, fields = 0)
data["filename"] = "[file.filename].[file.filetype]"
else
if(!computer || !HDD)
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 250abe3d682..cd5b065b3ca 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -203,7 +203,7 @@
/obj/item/weapon/paper/proc/parsepencode(var/t, var/obj/item/weapon/pen/P, mob/user as mob)
- t = pencode_to_html(t, usr, P, TRUE, TRUE, deffont, signfont, crayonfont)
+ t = pencode_to_html(t, usr, P, TRUE, TRUE, TRUE, deffont, signfont, crayonfont)
//Count the fields
var/laststart = 1
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 9f5d3534215..7780f057b19 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -159,6 +159,7 @@
w_class = initial(w_class)
name = initial(name)
hitsound = initial(hitsound)
+ embed_chance = initial(embed_chance)
throwforce = initial(throwforce)
playsound(user, 'sound/weapons/saberoff.ogg', 5, 1)
to_chat(user, "[src] can now be concealed.")
@@ -170,6 +171,7 @@
w_class = WEIGHT_CLASS_NORMAL
name = "energy dagger"
hitsound = 'sound/weapons/blade1.ogg'
+ embed_chance = 100 //rule of cool
throwforce = 35
playsound(user, 'sound/weapons/saberon.ogg', 5, 1)
to_chat(user, "[src] is now active.")
diff --git a/code/modules/projectiles/guns/alien.dm b/code/modules/projectiles/guns/alien.dm
index f541ca2a94a..5900e9a249e 100644
--- a/code/modules/projectiles/guns/alien.dm
+++ b/code/modules/projectiles/guns/alien.dm
@@ -101,6 +101,5 @@
flag = "bullet"
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
- embed = 0
weaken = 5
stun = 5
diff --git a/code/modules/projectiles/guns/throw/crossbow.dm b/code/modules/projectiles/guns/throw/crossbow.dm
index 77d3e89eade..a06aac35be5 100644
--- a/code/modules/projectiles/guns/throw/crossbow.dm
+++ b/code/modules/projectiles/guns/throw/crossbow.dm
@@ -170,8 +170,6 @@
/obj/item/weapon/arrow/rod/removed()
if(superheated) // The rod has been superheated - we don't want it to be useable when removed from the bow.
visible_message("[src] shatters into a scattering of overstressed metal shards as it leaves the crossbow.")
- var/obj/item/weapon/shard/shrapnel/S = new /obj/item/weapon/shard/shrapnel
- S.loc = get_turf(src)
qdel(src)
#undef XBOW_TENSION_20
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 4a3afd18684..20957e18786 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -48,7 +48,6 @@
var/drowsy = 0
var/stamina = 0
var/jitter = 0
- var/embed = 0 // whether or not the projectile can embed itself in the mob
var/forcedodge = 0 //to pass through everything
var/dismemberment = 0 //The higher the number, the greater the bonus to dismembering. 0 will not dismember at all.
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 7434038eb91..2c55431fba0 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -4,7 +4,6 @@
damage = 60
damage_type = BRUTE
flag = "bullet"
- embed = 1
sharp = 1
hitsound_wall = "ricochet"
@@ -14,11 +13,9 @@
stamina = 80
/obj/item/projectile/bullet/weakbullet/rubber //beanbag that shells that don't embed
- embed = 0
sharp = 0
/obj/item/projectile/bullet/weakbullet/booze
- embed = 0
/obj/item/projectile/bullet/weakbullet/booze/on_hit(atom/target, blocked = 0)
if(..(target, blocked))
@@ -45,7 +42,6 @@
icon_state = "bullet-r"
/obj/item/projectile/bullet/weakbullet2/rubber //detective's bullets that don't embed
- embed = 0
sharp = 0
/obj/item/projectile/bullet/weakbullet3
@@ -56,7 +52,6 @@
damage = 5
stamina = 30
icon_state = "bullet-r"
- embed = 0
sharp = 0
/obj/item/projectile/bullet/toxinbullet
@@ -145,7 +140,6 @@
name = "rubber pellet"
damage = 3
stamina = 25
- embed = 0
sharp = 0
icon_state = "bullet-r"
@@ -157,7 +151,6 @@
stutter = 5
jitter = 20
range = 7
- embed = 0
sharp = 0
icon_state = "spark"
color = "#FFFF00"
@@ -209,7 +202,6 @@
stun = 5
forcedodge = 1
nodamage = 1
- embed = 0
sharp = 0
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
hitsound = 'sound/items/bikehorn.ogg'
@@ -244,7 +236,6 @@
name = "dart"
icon_state = "cbbolt"
damage = 6
- embed = 0
sharp = 0
var/piercing = 0
@@ -307,7 +298,6 @@
name = "cap"
damage = 0
nodamage = 1
- embed = 0
sharp = 0
/obj/item/projectile/bullet/cap/fire()
diff --git a/code/modules/projectiles/projectile/force.dm b/code/modules/projectiles/projectile/force.dm
index 4e5c6d27700..4d62550a852 100644
--- a/code/modules/projectiles/projectile/force.dm
+++ b/code/modules/projectiles/projectile/force.dm
@@ -4,7 +4,6 @@
icon_state = "ice_1"
damage = 20
flag = "energy"
- embed = 1
/obj/item/projectile/forcebolt/strong
name = "force bolt"
diff --git a/code/modules/projectiles/projectile/reusable.dm b/code/modules/projectiles/projectile/reusable.dm
index a223f415165..8592a7a46ee 100644
--- a/code/modules/projectiles/projectile/reusable.dm
+++ b/code/modules/projectiles/projectile/reusable.dm
@@ -36,7 +36,6 @@
range = 10
var/obj/item/weapon/pen/pen = null
edge = 0
- embed = 0
log_override = TRUE//it won't log even when there's a pen inside, but since the damage will be so low, I don't think there's any point in making it any more complex
/obj/item/projectile/bullet/reusable/foam_dart/handle_drop()
diff --git a/code/modules/reagents/chem_splash.dm b/code/modules/reagents/chem_splash.dm
new file mode 100644
index 00000000000..7c16bf1ab9a
--- /dev/null
+++ b/code/modules/reagents/chem_splash.dm
@@ -0,0 +1,78 @@
+// Replaces chemgrenade stuff, allowing reagent explosions to be called from anywhere.
+// It should be called using a location, the range, and a list of reagents involved.
+
+// Threatscale is a multiplier for the 'threat' of the grenade. If you're increasing the affected range drastically, you might want to improve this.
+// Extra heat affects the temperature of the mixture, and may cause it to react in different ways.
+
+
+/proc/chem_splash(turf/epicenter, affected_range = 3, list/datum/reagents/reactants = list(), extra_heat = 0, threatscale = 1, adminlog = 1)
+ if(!isturf(epicenter) || !reactants.len || threatscale <= 0)
+ return
+ var/has_reagents
+ var/total_reagents
+ for(var/datum/reagents/R in reactants)
+ if(R.total_volume)
+ has_reagents = 1
+ total_reagents += R.total_volume
+
+ if(!has_reagents)
+ return
+
+ var/datum/reagents/splash_holder = new/datum/reagents(total_reagents*threatscale)
+ splash_holder.my_atom = epicenter // For some reason this is setting my_atom to null, and causing runtime errors.
+ var/total_temp = 0
+
+ for(var/datum/reagents/R in reactants)
+ R.trans_to(splash_holder, R.total_volume, threatscale, 1, 1)
+ total_temp += R.chem_temp
+ splash_holder.chem_temp = (total_temp/reactants.len) + extra_heat // Average temperature of reagents + extra heat.
+ splash_holder.handle_reactions() // React them now.
+
+ if(splash_holder.total_volume && affected_range >= 0) //The possible reactions didnt use up all reagents, so we spread it around.
+ var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread()
+ steam.set_up(10, 0, epicenter)
+ steam.attach(epicenter)
+ steam.start()
+
+ var/list/viewable = view(affected_range, epicenter)
+
+ var/list/accessible = list(epicenter)
+ for(var/i=1; i<=affected_range; i++)
+ var/list/turflist = list()
+ for(var/turf/T in (orange(i, epicenter) - orange(i-1, epicenter)))
+ turflist |= T
+ for(var/turf/T in turflist)
+ if( !(get_dir(T,epicenter) in cardinal) && (abs(T.x - epicenter.x) == abs(T.y - epicenter.y) ))
+ turflist.Remove(T)
+ turflist.Add(T) // we move the purely diagonal turfs to the end of the list.
+ for(var/turf/T in turflist)
+ if(accessible[T])
+ continue
+ for(var/thing in T.GetAtmosAdjacentTurfs(alldir = TRUE))
+ var/turf/NT = thing
+ if(!(NT in accessible))
+ continue
+ if(!(get_dir(T,NT) in cardinal))
+ continue
+ accessible[T] = 1
+ break
+ var/list/reactable = accessible
+ for(var/turf/T in accessible)
+ for(var/atom/A in T.GetAllContents())
+ if(!(A in viewable))
+ continue
+ reactable |= A
+ if(extra_heat >= 300)
+ T.hotspot_expose(extra_heat*2, 5)
+ if(!reactable.len) //Nothing to react with. Probably means we're in nullspace.
+ return
+ for(var/thing in reactable)
+ var/atom/A = thing
+ var/distance = max(1,get_dist(A, epicenter))
+ var/fraction = 0.5/(2 ** distance) //50/25/12/6... for a 200u splash, 25/12/6/3... for a 100u, 12/6/3/1 for a 50u
+ splash_holder.reaction(A, TOUCH, fraction)
+
+ qdel(splash_holder)
+ return 1
+
+
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index c65c628353b..662843e337a 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -108,7 +108,7 @@ var/const/INGEST = 2
return the_id
-/datum/reagents/proc/trans_to(target, amount=1, multiplier=1, preserve_data=1)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred.
+/datum/reagents/proc/trans_to(target, amount=1, multiplier=1, preserve_data=1, no_react = 0)//if preserve_data=0, the reagents data will be lost. Usefull if you use data for some strange stuff and don't want it to be transferred.
if(!target)
return
if(total_volume <= 0)
@@ -143,13 +143,14 @@ var/const/INGEST = 2
if(preserve_data)
trans_data = copy_data(current_reagent)
- R.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data, chem_temp)
+ R.add_reagent(current_reagent.id, (current_reagent_transfer * multiplier), trans_data, chem_temp, no_react = 1)
remove_reagent(current_reagent.id, current_reagent_transfer)
update_total()
R.update_total()
- R.handle_reactions()
- handle_reactions()
+ if(!no_react)
+ R.handle_reactions()
+ handle_reactions()
return amount
/datum/reagents/proc/copy_to(obj/target, amount=1, multiplier=1, preserve_data=1, safety = 0)
@@ -537,7 +538,7 @@ var/const/INGEST = 2
var/amt = list_reagents[r_id]
add_reagent(r_id, amt, data)
-/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300)
+/datum/reagents/proc/add_reagent(reagent, amount, list/data=null, reagtemp = 300, no_react = 0)
if(!isnum(amount))
return 1
update_total()
@@ -554,7 +555,8 @@ var/const/INGEST = 2
update_total()
my_atom.on_reagent_change()
R.on_merge(data)
- handle_reactions()
+ if(!no_react)
+ handle_reactions()
return 0
var/datum/reagent/D = chemical_reagents_list[reagent]
@@ -570,7 +572,8 @@ var/const/INGEST = 2
update_total()
my_atom.on_reagent_change()
- handle_reactions()
+ if(!no_react)
+ handle_reactions()
return 0
else
warning("[my_atom] attempted to add a reagent called '[reagent]' which doesn't exist. ([usr])")
diff --git a/code/modules/reagents/chemistry/reagents/misc.dm b/code/modules/reagents/chemistry/reagents/misc.dm
index 241370668e0..9670c80afef 100644
--- a/code/modules/reagents/chemistry/reagents/misc.dm
+++ b/code/modules/reagents/chemistry/reagents/misc.dm
@@ -371,10 +371,12 @@
description = "What is this emotion you humans call \"love?\" Oh, it's this? This is it? Huh, well okay then, thanks."
reagent_state = LIQUID
color = "#FF83A5"
+ process_flags = ORGANIC | SYNTHETIC // That's the power of love~
/datum/reagent/love/on_mob_life(mob/living/M)
- if(M.a_intent == INTENT_HARM)
- M.a_intent = INTENT_HELP
+ if(M.a_intent != INTENT_HELP)
+ M.a_intent_change(INTENT_HELP)
+ M.can_change_intents = 0 //Now you have no choice but to be helpful.
if(prob(8))
var/lovely_phrase = pick("appreciated", "loved", "pretty good", "really nice", "pretty happy with yourself, even though things haven't always gone as well as they could")
@@ -391,9 +393,14 @@
break
..()
+/datum/reagent/love/on_mob_delete(mob/living/M)
+ M.can_change_intents = 1
+ ..()
+
/datum/reagent/love/reaction_mob(mob/living/M, method=TOUCH, volume)
to_chat(M, "You feel loved!")
+
/datum/reagent/royal_bee_jelly
name = "royal bee jelly"
id = "royal_bee_jelly"
diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm
index 40d9cb1c481..8aa18899ac1 100644
--- a/code/modules/reagents/chemistry/reagents/toxins.dm
+++ b/code/modules/reagents/chemistry/reagents/toxins.dm
@@ -221,6 +221,8 @@
if(method == TOUCH)
if(ishuman(M))
var/mob/living/carbon/human/H = M
+ if(H.get_species() == "Grey")
+ return
if(volume > 25)
@@ -247,6 +249,8 @@
if(method == INGEST)
if(ishuman(M))
var/mob/living/carbon/human/H = M
+ if(H.get_species() == "Grey")
+ return
if(volume < 10)
to_chat(M, "The greenish acidic substance stings you, but isn't concentrated enough to harm you!")
diff --git a/code/modules/reagents/chemistry/reagents/water.dm b/code/modules/reagents/chemistry/reagents/water.dm
index 70d2a9f76c0..773d03c6006 100644
--- a/code/modules/reagents/chemistry/reagents/water.dm
+++ b/code/modules/reagents/chemistry/reagents/water.dm
@@ -20,10 +20,65 @@
drink_desc = "The father of all refreshments."
/datum/reagent/water/reaction_mob(mob/living/M, method=TOUCH, volume)
-// Put out fire
if(method == TOUCH)
+ // Put out fire
M.adjust_fire_stacks(-(volume / 10))
M.ExtinguishMob()
+ if(ishuman(M))
+
+ var/mob/living/carbon/human/H = M
+
+ if(H.get_species() != "Grey") //God this is so gross I hate it.
+ return
+
+ if(volume > 25)
+
+ if(H.wear_mask)
+ to_chat(H, "Your mask protects you from the water!")
+ return
+
+ if(H.head)
+ to_chat(H, "Your helmet protects you from the water!")
+ return
+
+ if(!M.unacidable)
+ if(prob(75))
+ var/obj/item/organ/external/affecting = H.get_organ("head")
+ if(affecting)
+ affecting.take_damage(5, 10)
+ H.UpdateDamageIcon()
+ H.emote("scream")
+ else
+ M.take_organ_damage(5,10)
+ else
+ M.take_organ_damage(5,10)
+
+ if(method == INGEST)
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+
+ if(H.get_species() != "Grey")
+ return
+
+ if(volume < 10)
+ to_chat(M, "The watery solvent substance stings you, but isn't concentrated enough to harm you!")
+
+ if(volume >=10 && volume <=25)
+ if(!H.unacidable)
+ M.take_organ_damage(0,min(max(volume-10,2)*2,20))
+ M.emote("scream")
+
+
+ if(volume > 25)
+ if(!M.unacidable)
+ if(prob(75))
+ var/obj/item/organ/external/affecting = H.get_organ("head")
+ if(affecting)
+ affecting.take_damage(0, 20)
+ H.UpdateDamageIcon()
+ H.emote("scream")
+ else
+ M.take_organ_damage(0,20)
/datum/reagent/water/reaction_turf(turf/simulated/T, volume)
if(!istype(T))
diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm
index f60efa3b784..63db086cef8 100644
--- a/code/modules/reagents/reagent_containers/glass_containers.dm
+++ b/code/modules/reagents/reagent_containers/glass_containers.dm
@@ -40,7 +40,8 @@
/obj/machinery/biogenerator,
/obj/machinery/hydroponics,
/obj/machinery/constructable_frame,
- /obj/machinery/icemachine)
+ /obj/machinery/icemachine,
+ /obj/item/weapon/bombcore/chemical)
/obj/item/weapon/reagent_containers/glass/New()
..()
diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm
index d406dcaf0ef..eb43698d451 100644
--- a/code/modules/reagents/reagent_dispenser.dm
+++ b/code/modules/reagents/reagent_dispenser.dm
@@ -29,6 +29,7 @@
/obj/structure/reagent_dispensers/proc/boom()
visible_message("[src] ruptures!")
+ chem_splash(loc, 5, list(reagents))
qdel(src)
/obj/structure/reagent_dispensers/ex_act(severity)
@@ -53,15 +54,6 @@
desc = "A water tank."
icon_state = "water"
-/obj/structure/reagent_dispensers/watertank/boom()
- playsound(loc, 'sound/effects/spray2.ogg', 50, 1, -6)
- new /obj/effect/effect/water(loc)
- for(var/turf/simulated/T in view(5, loc))
- T.MakeSlippery()
- for(var/mob/living/L in T)
- L.adjust_fire_stacks(-20)
- ..()
-
/obj/structure/reagent_dispensers/watertank/high
name = "high-capacity water tank"
desc = "A highly-pressurized water tank made to hold gargantuan amounts of water.."
diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm
index 9391af77424..09b17748dfd 100644
--- a/code/modules/research/designs/weapon_designs.dm
+++ b/code/modules/research/designs/weapon_designs.dm
@@ -80,6 +80,36 @@
build_path = /obj/item/weapon/grenade/chem_grenade/large
category = list("Weapons")
+/datum/design/pyro_grenade
+ name = "Pyro Grenade"
+ desc = "An advanced grenade that is able to self ignite its mixture."
+ id = "pyro_Grenade"
+ req_tech = list("combat" = 4, "engineering" = 4)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 2000, MAT_PLASMA = 500)
+ build_path = /obj/item/weapon/grenade/chem_grenade/pyro
+ category = list("Weapons")
+
+/datum/design/cryo_grenade
+ name = "Cryo Grenade"
+ desc = "An advanced grenade that rapidly cools its contents upon detonation."
+ id = "cryo_Grenade"
+ req_tech = list("combat" = 3, "materials" = 3)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 2000, MAT_SILVER = 500)
+ build_path = /obj/item/weapon/grenade/chem_grenade/cryo
+ category = list("Weapons")
+
+/datum/design/adv_grenade
+ name = "Advanced Release Grenade"
+ desc = "An advanced grenade that can be detonated several times, best used with a repeating igniter."
+ id = "adv_Grenade"
+ req_tech = list("combat" = 3, "engineering" = 4)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 3000, MAT_GLASS = 500)
+ build_path = /obj/item/weapon/grenade/chem_grenade/adv_release
+ category = list("Weapons")
+
/datum/design/tele_shield
name = "Telescopic Riot Shield"
desc = "An advanced riot shield made of lightweight materials that collapses for easy storage."
diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/cavity_implant.dm
similarity index 53%
rename from code/modules/surgery/implant.dm
rename to code/modules/surgery/cavity_implant.dm
index 498976c4635..bd82e7192ae 100644
--- a/code/modules/surgery/implant.dm
+++ b/code/modules/surgery/cavity_implant.dm
@@ -1,10 +1,3 @@
-//Procedures in this file: Putting items in body cavity. Implant removal. Items removal.
-
-
-//////////////////////////////////////////////////////////////////
-// ITEM PLACEMENT SURGERY //
-//////////////////////////////////////////////////////////////////
-
/datum/surgery/cavity_implant
name = "Cavity Implant/Removal"
steps = list(/datum/surgery_step/generic/cut_open,/datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/open_encased/saw,
@@ -199,198 +192,15 @@
affected.wounds += I
affected.owner.custom_pain("You feel something rip in your [affected.name]!", 1)
user.drop_item()
- target.internal_organs += tool
+ affected.hidden = tool
tool.forceMove(affected)
return 1
else
if(IC)
user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "You pull [IC] out of [target]'s [target_zone].")
user.put_in_hands(IC)
- target.internal_organs -= IC
+ affected.hidden = null
return 1
else
to_chat(user, "You don't find anything in [target]'s [target_zone].")
- return 0
-
-
-//////////////////////////////////////////////////////////////////
-// IMPLANT/ITEM REMOVAL SURGERY //
-//////////////////////////////////////////////////////////////////
-
-/datum/surgery/cavity_implant_rem
- name = "Implant Removal"
- steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin,/datum/surgery_step/cavity/implant_removal,/datum/surgery_step/cavity/close_space,/datum/surgery_step/generic/cauterize/)
- possible_locs = list("chest")//head is for borers..i can put it elsewhere
-
-/datum/surgery/cavity_implant_rem/synth
- name = "Implant Removal"
- steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/cavity/implant_removal,/datum/surgery_step/robotics/external/close_hatch)
- possible_locs = list("chest")//head is for borers..i can put it elsewhere
-
-/datum/surgery/cavity_implant_rem/can_start(mob/user, mob/living/carbon/human/target)
- if(!istype(target))
- return 0
- var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
- if(!affected)
- return 0
- if(affected.status & ORGAN_ROBOT)
- return 0
- return 1
-
-/datum/surgery/cavity_implant_rem/synth/can_start(mob/user, mob/living/carbon/human/target)
- if(!istype(target))
- return 0
- var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
- if(!affected)
- return 0
- if(!(affected.status & ORGAN_ROBOT))
- return 0
-
- return 1
-
-/datum/surgery_step/cavity/implant_removal
- name = "extract implant"
- allowed_tools = list(
- /obj/item/weapon/hemostat = 100, \
- /obj/item/weapon/wirecutters = 75, \
- /obj/item/weapon/kitchen/utensil/fork = 20
- )
- var/obj/item/weapon/implant/I = null
- time = 64
-
-/datum/surgery_step/cavity/implant_removal/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
- I = locate(/obj/item/weapon/implant) in target
- user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \
- "You start poking around inside [target]'s [affected.name] with \the [tool]." )
- target.custom_pain("The pain in your [affected.name] is living hell!",1)
- ..()
-
-/datum/surgery_step/cavity/implant_removal/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
- var/obj/item/organ/external/affected = target.get_organ(target_zone)
- I = locate(/obj/item/weapon/implant) in target
- if(I && (target_zone == "chest")) //implant removal only works on the chest.
- user.visible_message("[user] takes something out of [target]'s [affected.name] with \the [tool].", \
- "You take [I] out of [target]'s [affected.name]s with \the [tool]." )
-
- I.removed(target)
-
- var/obj/item/weapon/implantcase/case
-
- if(istype(user.get_item_by_slot(slot_l_hand), /obj/item/weapon/implantcase))
- case = user.get_item_by_slot(slot_l_hand)
- else if(istype(user.get_item_by_slot(slot_r_hand), /obj/item/weapon/implantcase))
- case = user.get_item_by_slot(slot_r_hand)
- else
- case = locate(/obj/item/weapon/implantcase) in get_turf(target)
-
- if(case && !case.imp)
- case.imp = I
- I.loc = case
- case.update_icon()
- user.visible_message("[user] places [I] into [case]!", "You place [I] into [case].")
- else
- qdel(I)
- return 1
- else
- user.visible_message(" [user] could not find anything inside [target]'s [affected.name], and pulls \the [tool] out.", \
- "You could not find anything inside [target]'s [affected.name].")
- return 1
-
-/datum/surgery_step/cavity/implant_removal/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
- ..()
- var/obj/item/organ/external/chest/affected = target.get_organ(target_zone)
- if(affected.implants.len)
- var/fail_prob = 10
- fail_prob += 100 - tool_quality(tool)
- if(prob(fail_prob))
- var/obj/item/weapon/implant/imp = affected.implants[1]
- user.visible_message(" Something beeps inside [target]'s [affected.name]!")
- playsound(imp.loc, 'sound/items/countdown.ogg', 75, 1, -3)
- spawn(25)
- imp.activate()
- return 0
-
-
-//////////////////////////////////////////////////////////////////
-// EMBEDDED ITEM REOMOVAL //
-//////////////////////////////////////////////////////////////////
-
-/datum/surgery/embedded_removal
- name = "Removal of Embedded Objects"
- steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/remove_object, /datum/surgery_step/generic/cauterize)
- possible_locs = list("r_arm","l_arm","r_leg","l_leg","r_hand","r_foot","l_hand","l_foot","groin","chest","head")
-
-/datum/surgery/embedded_removal/synth
- steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch, /datum/surgery_step/remove_object, /datum/surgery_step/robotics/external/close_hatch)
- possible_locs = list("r_arm","l_arm","r_leg","l_leg","r_hand","r_foot","l_hand","l_foot","groin","chest","head")
-
-
-/datum/surgery/embedded_removal/can_start(mob/user, mob/living/carbon/human/target)
- if(!istype(target))
- return 0
- var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
- if(!affected)
- return 0
- if(affected.status & ORGAN_ROBOT)
- return 0
- return 1
-
-/datum/surgery/embedded_removal/synth/can_start(mob/user, mob/living/carbon/human/target)
- if(!istype(target))
- return 0
- var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
- if(!affected)
- return 0
- if(!(affected.status & ORGAN_ROBOT))
- return 0
- return 1
-
-/datum/surgery_step/remove_object
- name = "remove embedded objects"
- time = 32
- allowed_tools = list(
- /obj/item/weapon/scalpel/laser/manager = 100, \
- /obj/item/weapon/hemostat = 100, \
- /obj/item/stack/cable_coil = 75, \
- /obj/item/device/assembly/mousetrap = 20
- )
- var/obj/item/organ/external/L = null
-
-
-/datum/surgery_step/remove_object/begin_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery)
- L = target.get_organ(target_zone)
- if(L)
- user.visible_message("[user] looks for objects embedded in [target]'s [target_zone].", "You look for objects embedded in [target]'s [target_zone]...")
- else
- user.visible_message("[user] looks for [target]'s [target_zone].", "You look for [target]'s [target_zone]...")
-
-
-/datum/surgery_step/remove_object/end_step(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery)
- if(L)
- if(ishuman(target))
- var/mob/living/carbon/human/H = target
- var/objects = 0
- for(var/obj/item/I in L.implants)
- if(!istype(I,/obj/item/weapon/implant))
- objects++
- I.forceMove(get_turf(H))
- L.implants -= I
-
- //Handle possessive brain borers.
- if(H.has_brain_worms() && target_zone == "head")//remove worms outside the loop
- var/mob/living/simple_animal/borer/worm = H.has_brain_worms()
- if(worm.controlling)
- target.release_control()
- worm.detach()
- worm.leave_host()
- user.visible_message("a slug like creature wiggles out of [H]'s [target_zone]!")
-
- if(objects > 0)
- user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L.limb_name]!", "You sucessfully remove [objects] objects from [H]'s [L.limb_name].")
- else
- to_chat(user, "You find no objects embedded in [H]'s [L.limb_name]!")
- else
- to_chat(user, "You can't find [target]'s [target_zone], let alone any objects embedded in it!")
-
- return 1
+ return 0
\ No newline at end of file
diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm
new file mode 100644
index 00000000000..7b04be81e1d
--- /dev/null
+++ b/code/modules/surgery/implant_removal.dm
@@ -0,0 +1,78 @@
+//////////////////////////////////////////////////////////////////
+// IMPLANT REMOVAL SURGERY //
+//////////////////////////////////////////////////////////////////
+
+/datum/surgery/implant_removal
+ name = "Implant Removal"
+ steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin,/datum/surgery_step/extract_implant,/datum/surgery_step/generic/cauterize)
+ possible_locs = list("chest")
+
+/datum/surgery/implant_removal/synth
+ name = "Implant Removal"
+ steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/extract_implant,/datum/surgery_step/robotics/external/close_hatch)
+ possible_locs = list("chest")
+
+/datum/surgery/implant_removal/can_start(mob/user, mob/living/carbon/human/target)
+ if(!istype(target))
+ return 0
+ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
+ if(!affected)
+ return 0
+ if(affected.status & ORGAN_ROBOT)
+ return 0
+ return 1
+
+/datum/surgery/implant_removal/synth/can_start(mob/user, mob/living/carbon/human/target)
+ if(!istype(target))
+ return 0
+ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
+ if(!affected)
+ return 0
+ if(!(affected.status & ORGAN_ROBOT))
+ return 0
+
+ return 1
+
+/datum/surgery_step/extract_implant
+ name = "extract implant"
+ allowed_tools = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/crowbar = 65)
+ time = 64
+ var/obj/item/weapon/implant/I = null
+
+/datum/surgery_step/extract_implant/begin_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ I = locate(/obj/item/weapon/implant) in target
+ user.visible_message("[user] starts poking around inside [target]'s [affected.name] with \the [tool].", \
+ "You start poking around inside [target]'s [affected.name] with \the [tool]." )
+ target.custom_pain("The pain in your [affected.name] is living hell!",1)
+ ..()
+
+/datum/surgery_step/extract_implant/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
+ var/obj/item/organ/external/affected = target.get_organ(target_zone)
+ I = locate(/obj/item/weapon/implant) in target
+ if(I && (target_zone == "chest")) //implant removal only works on the chest.
+ user.visible_message("[user] takes something out of [target]'s [affected.name] with \the [tool].", \
+ "You take [I] out of [target]'s [affected.name]s with \the [tool]." )
+
+ I.removed(target)
+
+ var/obj/item/weapon/implantcase/case
+
+ if(istype(user.get_item_by_slot(slot_l_hand), /obj/item/weapon/implantcase))
+ case = user.get_item_by_slot(slot_l_hand)
+ else if(istype(user.get_item_by_slot(slot_r_hand), /obj/item/weapon/implantcase))
+ case = user.get_item_by_slot(slot_r_hand)
+ else
+ case = locate(/obj/item/weapon/implantcase) in get_turf(target)
+
+ if(case && !case.imp)
+ case.imp = I
+ I.forceMove(case)
+ case.update_icon()
+ user.visible_message("[user] places [I] into [case]!", "You place [I] into [case].")
+ else
+ qdel(I)
+ else
+ user.visible_message(" [user] could not find anything inside [target]'s [affected.name], and pulls \the [tool] out.", \
+ "You could not find anything inside [target]'s [affected.name].")
+ return 1
\ No newline at end of file
diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm
index 174076c5fab..773508c88ea 100644
--- a/code/modules/surgery/limb_augmentation.dm
+++ b/code/modules/surgery/limb_augmentation.dm
@@ -52,4 +52,7 @@
qdel(tool)
+ affected.open = 0
+ affected.germ_level = 0
+ affected.status &= ~ORGAN_BLEEDING
return 1
\ No newline at end of file
diff --git a/code/modules/surgery/organs/organ_external.dm b/code/modules/surgery/organs/organ_external.dm
index 7d544a61cda..00addd62b9a 100644
--- a/code/modules/surgery/organs/organ_external.dm
+++ b/code/modules/surgery/organs/organ_external.dm
@@ -59,7 +59,7 @@
var/encased // Needs to be opened with a saw to access the organs.
var/obj/item/hidden = null
- var/list/implants = list()
+ var/list/embedded_objects = list()
// how often wounds should be updated, a higher number means less often
var/wound_update_accuracy = 1
@@ -105,7 +105,7 @@
QDEL_LIST(wounds)
- QDEL_LIST(implants)
+ QDEL_LIST(embedded_objects)
QDEL_NULL(hidden)
@@ -363,12 +363,6 @@ This function completely restores a damaged organ to perfect condition.
for(var/obj/item/organ/external/EO in contents)
EO.rejuvenate()
- // remove embedded objects and drop them on the floor
- for(var/obj/implanted_object in implants)
- if(!istype(implanted_object,/obj/item/weapon/implant)) // We don't want to remove REAL implants. Just shrapnel etc.
- implanted_object.loc = owner.loc
- implants -= implanted_object
-
owner.updatehealth()
update_icon()
if(!owner)
@@ -911,20 +905,6 @@ Note that amputating the affected organ does in fact remove the infection from t
/obj/item/organ/external/proc/is_malfunctioning()
return ((status & ORGAN_ROBOT) && (brute_dam + burn_dam) >= 10 && prob(brute_dam + burn_dam) && !tough)
-/obj/item/organ/external/proc/embed(var/obj/item/weapon/W, var/silent = 0)
- if(!owner || loc != owner)
- return
- if(!silent)
- owner.visible_message("\The [W] sticks in the wound!")
- implants += W
- owner.embedded_flag = 1
- owner.verbs += /mob/proc/yank_out_object
- W.add_blood(owner)
- if(ismob(W.loc))
- var/mob/living/H = W.loc
- H.drop_item()
- W.loc = owner
-
/obj/item/organ/external/proc/open_enough_for_surgery()
return (encased ? (open == 3) : (open == 2))
@@ -935,14 +915,17 @@ Note that amputating the affected organ does in fact remove the infection from t
var/is_robotic = status & ORGAN_ROBOT
var/mob/living/carbon/human/victim = owner
+ for(var/obj/item/I in embedded_objects)
+ embedded_objects -= I
+ I.forceMove(src)
+ if(!owner.has_embedded_objects())
+ owner.clear_alert("embeddedobject")
+
. = ..()
status |= ORGAN_DESTROYED
victim.bad_external_organs -= src
- for(var/implant in implants) //todo: check if this can be left alone
- qdel(implant)
-
// Attached organs also fly off.
if(!ignore_children)
for(var/obj/item/organ/external/O in children)
@@ -1022,3 +1005,22 @@ Note that amputating the affected organ does in fact remove the infection from t
..() // Parent call loads in the DNA
if(data["dna"])
sync_colour_to_dna()
+
+//Remove all embedded objects from all limbs on the carbon mob
+/mob/living/carbon/human/proc/remove_all_embedded_objects()
+ var/turf/T = get_turf(src)
+
+ for(var/X in bodyparts)
+ var/obj/item/organ/external/L = X
+ for(var/obj/item/I in L.embedded_objects)
+ L.embedded_objects -= I
+ I.forceMove(T)
+
+ clear_alert("embeddedobject")
+
+/mob/living/carbon/human/proc/has_embedded_objects()
+ . = 0
+ for(var/X in bodyparts)
+ var/obj/item/organ/external/L = X
+ for(var/obj/item/I in L.embedded_objects)
+ return 1
\ No newline at end of file
diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm
index 5dcb5954da5..da41915249c 100644
--- a/code/modules/surgery/organs_internal.dm
+++ b/code/modules/surgery/organs_internal.dm
@@ -159,6 +159,11 @@
else if(implement_type in implements_extract)
current_type = "extract"
var/list/organs = target.get_organs_zone(target_zone)
+ var/mob/living/simple_animal/borer/B = target.has_brain_worms()
+ if(target_zone == "head" && B)
+ user.visible_message("[user] begins to extract [B] from [target]'s [parse_zone(target_zone)].",
+ "You begin to extract [B] from [target]'s [parse_zone(target_zone)]...")
+ return TRUE
if(!organs.len)
to_chat(user, "There are no removeable organs in [target]'s [parse_zone(target_zone)]!")
return -1
@@ -262,6 +267,13 @@
I.status &= ~ORGAN_CUT_AWAY
else if(current_type == "extract")
+ var/mob/living/simple_animal/borer/B = target.has_brain_worms()
+ if(target_zone == "head" && B && B.host == target)
+ user.visible_message("[user] successfully extracts [B] from [target]'s [parse_zone(target_zone)]!",
+ "You successfully extract [B] from [target]'s [parse_zone(target_zone)].")
+ add_logs(user, target, "surgically removed [B] from", addition="INTENT: [uppertext(user.a_intent)]")
+ B.leave_host()
+ return FALSE
if(I && I.owner == target)
user.visible_message(" [user] has separated and extracts [target]'s [I] with [tool].",
" You have separated and extracted [target]'s [I] with [tool].")
diff --git a/code/modules/surgery/remove_embedded_object.dm b/code/modules/surgery/remove_embedded_object.dm
new file mode 100644
index 00000000000..d7fe8b7fb53
--- /dev/null
+++ b/code/modules/surgery/remove_embedded_object.dm
@@ -0,0 +1,65 @@
+/datum/surgery/embedded_removal
+ name = "Removal of Embedded Objects"
+ steps = list(/datum/surgery_step/generic/cut_open, /datum/surgery_step/generic/clamp_bleeders, /datum/surgery_step/generic/retract_skin, /datum/surgery_step/remove_object,/datum/surgery_step/generic/cauterize)
+ possible_locs = list("head", "chest", "l_arm", "l_hand", "r_arm", "r_hand","r_leg", "r_foot", "l_leg", "l_foot", "groin")
+
+/datum/surgery/embedded_removal/synth
+ steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/remove_object,/datum/surgery_step/robotics/external/close_hatch)
+
+/datum/surgery/embedded_removal/can_start(mob/user, mob/living/carbon/human/target)
+ if(!istype(target))
+ return 0
+ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
+ if(!affected)
+ return 0
+ if(affected.status & ORGAN_ROBOT)
+ return 0
+ return 1
+
+/datum/surgery/embedded_removal/synth/can_start(mob/user, mob/living/carbon/human/target)
+ if(!istype(target))
+ return 0
+ var/obj/item/organ/external/affected = target.get_organ(user.zone_sel.selecting)
+ if(!affected)
+ return 0
+ if(!(affected.status & ORGAN_ROBOT))
+ return 0
+
+ return 1
+
+/datum/surgery_step/remove_object
+ name = "Remove Embedded Objects"
+ time = 32
+ accept_hand = 1
+ var/obj/item/organ/external/L = null
+
+
+/datum/surgery_step/remove_object/begin_step(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ L = surgery.organ_ref
+ if(L)
+ user.visible_message("[user] looks for objects embedded in [target]'s [parse_zone(user.zone_sel.selecting)].", "You look for objects embedded in [target]'s [parse_zone(user.zone_sel.selecting)]...")
+ else
+ user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_sel.selecting)].", "You look for [target]'s [parse_zone(user.zone_sel.selecting)]...")
+
+
+/datum/surgery_step/remove_object/end_step(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ if(L)
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ var/objects = 0
+ for(var/obj/item/I in L.embedded_objects)
+ objects++
+ I.forceMove(get_turf(H))
+ L.embedded_objects -= I
+ if(!H.has_embedded_objects())
+ H.clear_alert("embeddedobject")
+
+ if(objects > 0)
+ user.visible_message("[user] sucessfully removes [objects] objects from [H]'s [L]!", "You successfully remove [objects] objects from [H]'s [L.name].")
+ else
+ to_chat(user, "You find no objects embedded in [H]'s [L]!")
+
+ else
+ to_chat(user, "You can't find [target]'s [parse_zone(user.zone_sel.selecting)], let alone any objects embedded in it!")
+
+ return 1
\ No newline at end of file
diff --git a/code/world.dm b/code/world.dm
index 34d61dbbc21..e293058cdf6 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -244,6 +244,27 @@ var/world_topic_spam_protect_time = world.timeofday
for(var/client/C in clients)
to_chat(C, "PR: [input["announce"]]")
+ else if("kick" in input)
+ /*
+ We have a kick request over coms.
+ Only needed portion is the ckey
+ */
+ if(!key_valid)
+ return keySpamProtect(addr)
+
+ var/client/C
+
+ for(var/client/K in clients)
+ if(K.ckey == input["kick"])
+ C = K
+ break
+ if(!C)
+ return "No client with that name on server"
+
+ del(C)
+
+ return "Kick Successful"
+
/proc/keySpamProtect(var/addr)
if(world_topic_spam_protect_ip == addr && abs(world_topic_spam_protect_time - world.time) < 50)
spawn(50)
diff --git a/html/changelog.html b/html/changelog.html
index 70f2ffdb953..4ff84de803b 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -55,6 +55,56 @@
-->
+ 03 July 2017
+ Fethas updated:
+
+ - fixes issue with hand teleporter not working in active hands
+
+ fludd12 updated:
+
+ - Greys are now PROPERLY immune to sulfuric acid.
+ - Greys don't pretend to touch their heads when they don't manage to anymore.
+
+
+ 01 July 2017
+ Fox McCloud updated:
+
+ - Re-enables object embedding system; embedding objects now cause more damage than before
+ - Adds in throwing stars kit to the traitor uplink
+ - bullets no longer leave shrapnel
+
+
+ 30 June 2017
+ fludd12 updated:
+
+ - Greys treat Sulfuric Acid as if it were water. They also treat water as if it were sulfuric acid.
+ - Grey language is now Z-level wide, but requires you to be able to put a finger to your temple. (Requires at least one hand not disabled and not stunned.)
+ - Remote Talk is buffed to have a range of two screens, and has some minor formatting changes!
+ - Remote Talk no longer lets you magically know the true name of whoever you speak with.
+
+
+ 29 June 2017
+ Fox McCloud updated:
+
+ - Fixes limbs being an open wound after augmentation
+
+ Kluys updated:
+
+ - Bob ross painting in the captains office called "calming painting".
+Also changes around the entertainment monitor and light switch to accomodate.
+ - Clown painting was named "\improper mech painting"
+
+
+ 28 June 2017
+ Fox McCloud updated:
+
+ - Fix's IPC head customization
+
+ Purpose2 and Re-Opened by Fethas updated:
+
+ - Rare Sentience event, the mice now want coffee!
+
+
27 June 2017
Alexshreds updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index 24dd1649beb..ca7bf4d64d6 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -5054,3 +5054,39 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
these.
tigercat2000:
- tweak: Karma returned to the Special Verbs tab
+2017-06-28:
+ Fox McCloud:
+ - bugfix: Fix's IPC head customization
+ Purpose2 and Re-Opened by Fethas:
+ - rscadd: Rare Sentience event, the mice now want coffee!
+2017-06-29:
+ Fox McCloud:
+ - bugfix: Fixes limbs being an open wound after augmentation
+ Kluys:
+ - rscadd: 'Bob ross painting in the captains office called "calming painting".
+
+ Also changes around the entertainment monitor and light switch to accomodate.'
+ - bugfix: Clown painting was named "\improper mech painting"
+2017-06-30:
+ fludd12:
+ - tweak: Greys treat Sulfuric Acid as if it were water. They also treat water as
+ if it were sulfuric acid.
+ - experiment: Grey language is now Z-level wide, but requires you to be able to
+ put a finger to your temple. (Requires at least one hand not disabled and not
+ stunned.)
+ - tweak: Remote Talk is buffed to have a range of two screens, and has some minor
+ formatting changes!
+ - bugfix: Remote Talk no longer lets you magically know the true name of whoever
+ you speak with.
+2017-07-01:
+ Fox McCloud:
+ - bugfix: Re-enables object embedding system; embedding objects now cause more damage
+ than before
+ - rscadd: Adds in throwing stars kit to the traitor uplink
+ - rscdel: bullets no longer leave shrapnel
+2017-07-03:
+ Fethas:
+ - bugfix: fixes issue with hand teleporter not working in active hands
+ fludd12:
+ - bugfix: Greys are now PROPERLY immune to sulfuric acid.
+ - bugfix: Greys don't pretend to touch their heads when they don't manage to anymore.
diff --git a/html/changelogs/AutoChangeLog-pr-7653.yml b/html/changelogs/AutoChangeLog-pr-7653.yml
new file mode 100644
index 00000000000..dfa4fa794a4
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7653.yml
@@ -0,0 +1,4 @@
+author: "Kyep"
+delete-after: True
+changes:
+ - tweak: "Gimmick Teams are now more configurable."
diff --git a/html/changelogs/AutoChangeLog-pr-7669.yml b/html/changelogs/AutoChangeLog-pr-7669.yml
new file mode 100644
index 00000000000..b326c95fbb5
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7669.yml
@@ -0,0 +1,4 @@
+author: "Vivalas"
+delete-after: True
+changes:
+ - bugfix: "\"Tweaks\" SecHUDs to only display criminal status of people if their face is uncovered or they have no ID."
diff --git a/html/changelogs/AutoChangeLog-pr-7672.yml b/html/changelogs/AutoChangeLog-pr-7672.yml
new file mode 100644
index 00000000000..9e6b51d13e0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7672.yml
@@ -0,0 +1,8 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - rscadd: "Syndicate bombs now have visible timers for observers"
+ - rscadd: "Syndicate bombs tick more often"
+ - rscadd: "Syndnicate bombs can be deconstructed into plasteel if it is fully defused and has no bomb core"
+ - rscadd: "Can make Cryo, Pyro, and time released chemical grenades at R&D"
+ - rscadd: "Can make syndicate chemical bombs utilizing crafting"
diff --git a/html/changelogs/AutoChangeLog-pr-7674.yml b/html/changelogs/AutoChangeLog-pr-7674.yml
new file mode 100644
index 00000000000..82d4da45fcf
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7674.yml
@@ -0,0 +1,4 @@
+author: "Citinited"
+delete-after: True
+changes:
+ - tweak: "AIs and cyborgs can now toggle liquid dispensers by ctrl-clicking them, and can make them dispense foam by alt-clicking."
diff --git a/html/changelogs/AutoChangeLog-pr-7675.yml b/html/changelogs/AutoChangeLog-pr-7675.yml
new file mode 100644
index 00000000000..0e87d4e3ca1
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7675.yml
@@ -0,0 +1,4 @@
+author: "Ionward"
+delete-after: True
+changes:
+ - bugfix: "Greys now have properly fitting sprites for most head clothing items!"
diff --git a/html/changelogs/AutoChangeLog-pr-7681.yml b/html/changelogs/AutoChangeLog-pr-7681.yml
new file mode 100644
index 00000000000..79c175b54aa
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7681.yml
@@ -0,0 +1,4 @@
+author: "Birdtalon"
+delete-after: True
+changes:
+ - tweak: "Traitor medical chemists can now access syndicate poison bottles."
diff --git a/html/changelogs/AutoChangeLog-pr-7682.yml b/html/changelogs/AutoChangeLog-pr-7682.yml
new file mode 100644
index 00000000000..24bd2ec7ae5
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7682.yml
@@ -0,0 +1,4 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - rscadd: "Adds in radio jammers to the traitor uplink"
diff --git a/html/changelogs/AutoChangeLog-pr-7684.yml b/html/changelogs/AutoChangeLog-pr-7684.yml
new file mode 100644
index 00000000000..11b48f89c8f
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7684.yml
@@ -0,0 +1,4 @@
+author: "Citinited & LightFire53"
+delete-after: True
+changes:
+ - rscadd: "Adds the plasmaman coroner suit, the plasmaman geneticist suit, and the plasmaman virologist suit. Spooky purple skeletons everywhere rejoice!"
diff --git a/html/changelogs/AutoChangeLog-pr-7689.yml b/html/changelogs/AutoChangeLog-pr-7689.yml
new file mode 100644
index 00000000000..5a05e8eacdd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7689.yml
@@ -0,0 +1,5 @@
+author: "Fox McCloud"
+delete-after: True
+changes:
+ - tweak: "love just got more powerful; it now prevents a mob from being on anything other than help intent"
+ - tweak: "IPCs can now process the love reagent"
diff --git a/html/changelogs/AutoChangeLog-pr-7690.yml b/html/changelogs/AutoChangeLog-pr-7690.yml
new file mode 100644
index 00000000000..d154cf0cf82
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-7690.yml
@@ -0,0 +1,4 @@
+author: "Fethas"
+delete-after: True
+changes:
+ - rscadd: "Adds medical gowns to medical wardrobes."
diff --git a/html/templates/header.html b/html/templates/header.html
index bcd9595f02b..fac4d7b280a 100644
--- a/html/templates/header.html
+++ b/html/templates/header.html
@@ -26,7 +26,7 @@
Paradise Station
- Visit our IRC channel: #crew on neko.sneeza.me
+ Visit our Discord channel:-Click Here-
|
@@ -54,4 +54,4 @@
*** DO NOT FUCK WITH THIS FILE OR YOU WILL CAUSE MERGE CONFLICTS. ***
-->
-