diff --git a/_maps/map_files/cyberiad/cyberiad.dmm b/_maps/map_files/cyberiad/cyberiad.dmm
index cea4d6143cd..37976a9e749 100644
--- a/_maps/map_files/cyberiad/cyberiad.dmm
+++ b/_maps/map_files/cyberiad/cyberiad.dmm
@@ -4121,7 +4121,7 @@
"bBo" = (/obj/machinery/hologram/holopad,/turf/simulated/floor/plasteel,/area/quartermaster/office)
"bBp" = (/obj/structure/table,/obj/machinery/light{dir = 4},/obj/machinery/recharger,/turf/simulated/floor/plasteel{icon_state = "arrival"; dir = 4},/area/quartermaster/office)
"bBq" = (/obj/machinery/atm{pixel_x = -32},/turf/simulated/floor/plasteel{dir = 8; icon_state = "browncorner"},/area/hallway/primary/central/west)
-"bBr" = (/obj/item/weapon/hand_labeler,/obj/item/device/assembly/timer,/obj/structure/table,/turf/simulated/floor/wood,/area/bridge/meeting_room)
+"bBr" = (/obj/item/device/assembly/timer,/obj/structure/table,/obj/item/stack/packageWrap,/obj/item/weapon/hand_labeler,/turf/simulated/floor/wood,/area/bridge/meeting_room)
"bBs" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/wood,/area/bridge/meeting_room)
"bBt" = (/obj/structure/stool/bed/chair/comfy/black{dir = 4},/turf/simulated/floor/carpet,/area/bridge/meeting_room)
"bBu" = (/obj/structure/table/woodentable,/obj/item/device/radio/intercom/command,/turf/simulated/floor/carpet,/area/bridge/meeting_room)
@@ -4803,7 +4803,7 @@
"bOu" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plasteel,/area/hallway/primary/central/sw)
"bOv" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; on = 1},/obj/item/device/radio/intercom{dir = 4; name = "station intercom (General)"; pixel_x = 28},/turf/simulated/floor/plasteel{dir = 2; icon_state = "redcorner"},/area/hallway/primary/central/sw)
"bOw" = (/obj/machinery/computer/secure_data,/obj/machinery/flasher_button{id = "hopflash"; pixel_x = 6; pixel_y = 36},/obj/machinery/door_control{id = "hopqueue"; name = "Queue Privacy Shutters Control"; pixel_x = -4; pixel_y = 25; req_access_txt = "28"},/obj/machinery/door_control{id = "hop"; name = "Privacy Shutters Control"; pixel_x = 6; pixel_y = 25; req_access_txt = "28"},/obj/machinery/light_switch{pixel_x = -4; pixel_y = 36},/turf/simulated/floor/plasteel{dir = 9; icon_state = "blue"},/area/crew_quarters/heads)
-"bOx" = (/obj/structure/table,/obj/machinery/newscaster/security_unit{pixel_x = 0; pixel_y = 32},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/item/stack/packageWrap,/obj/item/weapon/hand_labeler,/turf/simulated/floor/plasteel,/area/crew_quarters/heads)
+"bOx" = (/obj/structure/table,/obj/machinery/newscaster/security_unit{pixel_x = 0; pixel_y = 32},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/computer/skills{req_access_txt = "57"},/turf/simulated/floor/plasteel,/area/crew_quarters/heads)
"bOy" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/obj/machinery/recharger/wallcharger{pixel_x = 0; pixel_y = 30},/turf/simulated/floor/plasteel,/area/crew_quarters/heads)
"bOz" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/photocopier,/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/turf/simulated/floor/plasteel,/area/crew_quarters/heads)
"bOA" = (/obj/machinery/light{dir = 4; icon_state = "tube1"},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/structure/disposalpipe/segment,/obj/structure/cable{d1 = 2; d2 = 8; icon_state = "2-8"; tag = ""},/turf/simulated/floor/plasteel,/area/crew_quarters/heads)
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index a20efc98a06..0090dd654fd 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -3,15 +3,18 @@
//PUBLIC - call these wherever you want
-/mob/proc/throw_alert(category, type, severity, obj/new_master)
+/mob/proc/throw_alert(category, type, severity, obj/new_master, override = FALSE)
-/* Proc to create or update an alert. Returns the alert if the alert is new or updated, 0 if it was thrown already
+/*
+ Proc to create or update an alert. Returns the alert if the alert is new or updated, 0 if it was thrown already
category is a text string. Each mob may only have one alert per category; the previous one will be replaced
path is a type path of the actual alert type to throw
severity is an optional number that will be placed at the end of the icon_state for this alert
For example, high pressure's icon_state is "highpressure" and can be serverity 1 or 2 to get "highpressure1" or "highpressure2"
new_master is optional and sets the alert's icon state to "template" in the ui_style icons with the master as an overlay.
- Clicks are forwarded to master */
+ Clicks are forwarded to master
+ Override makes it so the alert is not replaced until cleared by a clear_alert with clear_override, and it's used for hallucinations.
+ */
if(!category)
return
@@ -19,6 +22,8 @@
var/obj/screen/alert/alert
if(alerts[category])
alert = alerts[category]
+ if(alert.override_alerts)
+ return 0
if(new_master && new_master != alert.master)
WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [alert.master]")
clear_alert(category)
@@ -33,7 +38,10 @@
else //no need to update
return 0
else
- alert = new type
+ alert = new type()
+ alert.override_alerts = override
+ if(override)
+ alert.timeout = null
if(new_master)
var/old_layer = new_master.layer
@@ -63,10 +71,12 @@
return alert
// Proc to clear an existing alert.
-/mob/proc/clear_alert(category)
+/mob/proc/clear_alert(category, clear_override = FALSE)
var/obj/screen/alert/alert = alerts[category]
if(!alert)
return 0
+ if(alert.override_alerts && !clear_override)
+ return 0
alerts -= category
if(client && hud_used)
@@ -83,6 +93,7 @@
var/timeout = 0 //If set to a number, this alert will clear itself after that many deciseconds
var/severity = 0
var/alerttooltipstyle = ""
+ var/override_alerts = FALSE //If it is overriding other alerts of the same type
/obj/screen/alert/MouseEntered(location,control,params)
@@ -197,12 +208,12 @@ The box in your backpack has an oxygen tank and gas mask in it."
name = "High Pressure"
desc = "The air around you is hazardously thick. A fire suit would protect you."
icon_state = "highpressure"
-
+
/obj/screen/alert/lightexposure
name = "Light Exposure"
desc = "You're exposed to light."
icon_state = "lightexposure"
-
+
/obj/screen/alert/nolight
name = "No Light"
desc = "You're not exposed to any light."
diff --git a/code/game/gamemodes/miniantags/slaughter/slaughter.dm b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
index 6988d2b16dd..62c3a9a00b0 100644
--- a/code/game/gamemodes/miniantags/slaughter/slaughter.dm
+++ b/code/game/gamemodes/miniantags/slaughter/slaughter.dm
@@ -104,9 +104,7 @@
speed = 0
boost = world.time + 60
-
-
-
+// Cult slaughter demon
/mob/living/simple_animal/slaughter/cult //Summoned as part of the cult objective "Bring the Slaughter"
name = "harbringer of the slaughter"
real_name = "harbringer of the Slaughter"
@@ -154,17 +152,18 @@
/mob/living/simple_animal/slaughter/cult/New()
..()
spawn(5)
- var/list/demon_candidates = get_candidates(ROLE_CULTIST)
+ var/list/demon_candidates = pollCandidates("Do you want to play as a slaughter demon?", ROLE_DEMON, 1, 100)
if(!demon_candidates.len)
visible_message("[src] disappears in a flash of red light!")
qdel(src)
return 0
- var/client/C = pick(demon_candidates)
+ var/mob/M = pick(demon_candidates)
var/mob/living/simple_animal/slaughter/cult/S = src
- if(!C)
+ if(!M || !M.client)
visible_message("[src] disappears in a flash of red light!")
qdel(src)
return 0
+ var/client/C = M.client
S.key = C.key
S.mind.assigned_role = "Harbringer of the Slaughter"
@@ -181,7 +180,7 @@
////////////////////The Powers
-//Paradise Port:I added this cuase..SPOOPY DEMON IN YOUR BRAIN
+//Paradise Port: I added this because..SPOOPY DEMON IN YOUR BRAIN
/datum/action/innate/demon/whisper
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 194d5655eb1..a708e06fe93 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -110,6 +110,7 @@
return
add_fingerprint(user)
+ user.changeNext_move(CLICK_CD_MELEE)
if(can_force && (!glass || user.a_intent != I_HELP))
user.visible_message("[user] begins forcing \the [src].", \
@@ -119,7 +120,6 @@
"You force \the [src].")
open()
else if(glass)
- user.changeNext_move(CLICK_CD_MELEE)
user.visible_message("[user] bangs on \the [src].",
"You bang on \the [src].")
playsound(get_turf(src), 'sound/effects/Glassknock.ogg', 10, 1)
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 48e01dba29b..9ac4897c8f3 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -35,6 +35,7 @@
return 0
on = !on
+ playsound(user, 'sound/weapons/empty.ogg', 100, 1)
update_brightness(user)
for(var/X in actions)
var/datum/action/A = X
diff --git a/code/game/objects/items/weapons/RCL.dm b/code/game/objects/items/weapons/RCL.dm
new file mode 100644
index 00000000000..524fd38eb80
--- /dev/null
+++ b/code/game/objects/items/weapons/RCL.dm
@@ -0,0 +1,151 @@
+/obj/item/weapon/twohanded/rcl
+ name = "rapid cable layer (RCL)"
+ desc = "A device used to rapidly deploy cables. It has screws on the side which can be removed to slide off the cables."
+ icon = 'icons/obj/tools.dmi'
+ icon_state = "rcl-0"
+ item_state = "rcl-0"
+ opacity = 0
+ force = 5 //Plastic is soft
+ throwforce = 5
+ throw_speed = 1
+ throw_range = 7
+ w_class = WEIGHT_CLASS_NORMAL
+ origin_tech = "engineering=4;materials=4"
+ var/max_amount = 90
+ var/active = 0
+ var/obj/structure/cable/last = null
+ var/obj/item/stack/cable_coil/loaded = null
+
+/obj/item/weapon/twohanded/rcl/attackby(obj/item/weapon/W, mob/user)
+ if(istype(W, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/C = W
+ if(!loaded)
+ if(user.drop_item())
+ loaded = W
+ loaded.forceMove(src)
+ loaded.max_amount = max_amount //We store a lot.
+ else
+ to_chat(user, "[user.get_active_hand()] is stuck to your hand!")
+ return
+ else
+ if(loaded.amount < max_amount)
+ var/amount = min(loaded.amount + C.amount, max_amount)
+ C.use(amount - loaded.amount)
+ loaded.amount = amount
+ else
+ return
+ update_icon()
+ to_chat(user, "You add the cables to the [src]. It now contains [loaded.amount].")
+ else if(isscrewdriver(W))
+ if(!loaded)
+ return
+ to_chat(user, "You loosen the securing screws on the side, allowing you to lower the guiding edge and retrieve the wires.")
+ while(loaded.amount > 30) //There are only two kinds of situations: "nodiff" (60,90), or "diff" (31-59, 61-89)
+ var/diff = loaded.amount % 30
+ if(diff)
+ loaded.use(diff)
+ new /obj/item/stack/cable_coil(user.loc, diff)
+ else
+ loaded.use(30)
+ new /obj/item/stack/cable_coil(user.loc, 30)
+ loaded.max_amount = initial(loaded.max_amount)
+ loaded.forceMove(user.loc)
+ user.put_in_hands(loaded)
+ loaded = null
+ update_icon()
+ else
+ ..()
+
+/obj/item/weapon/twohanded/rcl/examine(mob/user)
+ ..()
+ if(loaded)
+ to_chat(user, "It contains [loaded.amount]/[max_amount] cables.")
+
+/obj/item/weapon/twohanded/rcl/Destroy()
+ if(loaded)
+ qdel(loaded)
+ loaded = null
+ last = null
+ active = 0
+ return ..()
+
+/obj/item/weapon/twohanded/rcl/update_icon()
+ if(!loaded)
+ icon_state = "rcl-0"
+ item_state = "rcl-0"
+ return
+ switch(loaded.amount)
+ if(61 to INFINITY)
+ icon_state = "rcl-30"
+ item_state = "rcl"
+ if(31 to 60)
+ icon_state = "rcl-20"
+ item_state = "rcl"
+ if(1 to 30)
+ icon_state = "rcl-10"
+ item_state = "rcl"
+ else
+ icon_state = "rcl-0"
+ item_state = "rcl-0"
+
+/obj/item/weapon/twohanded/rcl/proc/is_empty(mob/user, loud = 1)
+ update_icon()
+ if(!loaded || !loaded.amount)
+ if(loud)
+ to_chat(user, "The last of the cables unreel from [src].")
+ if(loaded)
+ qdel(loaded)
+ loaded = null
+ unwield(user)
+ active = wielded
+ return 1
+ return 0
+
+/obj/item/weapon/twohanded/rcl/dropped(mob/wearer)
+ ..()
+ active = 0
+ last = null
+
+/obj/item/weapon/twohanded/rcl/attack_self(mob/user)
+ ..()
+ active = wielded
+ if(!active)
+ last = null
+ else if(!last)
+ for(var/obj/structure/cable/C in get_turf(user))
+ if(C.d1 == 0 || C.d2 == 0)
+ last = C
+ break
+
+/obj/item/weapon/twohanded/rcl/moved(mob/user, turf/old_loc, direct)
+ if(active)
+ trigger(user)
+
+/obj/item/weapon/twohanded/rcl/proc/trigger(mob/user)
+ if(is_empty(user, 0))
+ to_chat(user, "\The [src] is empty!")
+ return
+ if(last)
+ if(get_dist(last, user) == 1) //hacky, but it works
+ var/turf/T = get_turf(user)
+ if(!isturf(T) || T.intact || !T.can_have_cabling())
+ last = null
+ return
+ if(get_dir(last, user) == last.d2)
+ //Did we just walk backwards? Well, that's the one direction we CAN'T complete a stub.
+ last = null
+ return
+ loaded.cable_join(last, user)
+ if(is_empty(user))
+ return //If we've run out, display message and exit
+ else
+ last = null
+ last = loaded.place_turf(get_turf(loc), user, turn(user.dir, 180))
+ is_empty(user) //If we've run out, display message
+
+/obj/item/weapon/twohanded/rcl/pre_loaded/New() //Comes preloaded with cable, for testing stuff
+ ..()
+ loaded = new()
+ loaded.max_amount = max_amount
+ loaded.amount = max_amount
+ update_icon()
\ No newline at end of file
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
index e1c42feb07c..6e1ba7eb742 100644
--- a/code/game/objects/structures/statues.dm
+++ b/code/game/objects/structures/statues.dm
@@ -58,16 +58,18 @@
qdel(src)
else if(iswelder(W) && !anchored)
- playsound(loc, W.usesound, 40, 1)
- user.visible_message("[user] is slicing apart the [name].", \
- "You are slicing apart the [name]...")
- if(do_after(user, 40 * W.toolspeed, target = src))
- if(!loc)
- return
- playsound(loc, W.usesound, 50, 1)
- user.visible_message("[user] slices apart the [name].", \
- "You slice apart the [name]!")
- Dismantle(TRUE)
+ var/obj/item/weapon/weldingtool/WT = W
+ if(WT.remove_fuel(0, user))
+ playsound(loc, W.usesound, 40, 1)
+ user.visible_message("[user] is slicing apart the [name].", \
+ "You are slicing apart the [name]...")
+ if(do_after(user, 40 * W.toolspeed, target = src))
+ if(!loc)
+ return
+ playsound(loc, W.usesound, 50, 1)
+ user.visible_message("[user] slices apart the [name].", \
+ "You slice apart the [name]!")
+ Dismantle(TRUE)
else
hardness -= W.force/100
..()
diff --git a/code/game/turfs/simulated/walls_reinforced.dm b/code/game/turfs/simulated/walls_reinforced.dm
index 2cc77fc46b8..dca0d24742c 100644
--- a/code/game/turfs/simulated/walls_reinforced.dm
+++ b/code/game/turfs/simulated/walls_reinforced.dm
@@ -313,4 +313,3 @@
else
smooth = SMOOTH_TRUE
icon_state = ""
-
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 69b0df22ae3..a5e4190d6ea 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -386,15 +386,25 @@
if(ticker)
cameranet.updateVisibility(src)
-/turf/attackby(obj/item/C, mob/user, params)
- if(can_lay_cable() && istype(C, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/coil = C
- for(var/obj/structure/cable/LC in src)
- if((LC.d1==0)||(LC.d2==0))
- LC.attackby(C,user)
- return
- coil.place_turf(src, user)
- return 1
+/turf/attackby(obj/item/I, mob/user, params)
+ if(can_lay_cable())
+ if(istype(I, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/C = I
+ for(var/obj/structure/cable/LC in src)
+ if(LC.d1 == 0 || LC.d2==0)
+ LC.attackby(C,user)
+ return
+ C.place_turf(src, user)
+ return 1
+ else if(istype(I, /obj/item/weapon/twohanded/rcl))
+ var/obj/item/weapon/twohanded/rcl/R = I
+ if(R.loaded)
+ for(var/obj/structure/cable/LC in src)
+ if(LC.d1 == 0 || LC.d2==0)
+ LC.attackby(R, user)
+ return
+ R.loaded.place_turf(src, user)
+ R.is_empty(user)
return 0
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 08123d6934e..0e52ba46d3d 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -135,12 +135,24 @@
desc = "A paramedic EVA helmet. Used in the recovery of bodies from space."
icon_state = "paramedic-eva-helmet"
item_state = "paramedic-eva-helmet"
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/helmet.dmi'
+ )
+ sprite_sheets_obj = list(
+ "Vox" = 'icons/obj/clothing/species/vox/hats.dmi'
+ )
/obj/item/clothing/suit/space/eva/paramedic
name = "Paramedic EVA suit"
icon_state = "paramedic-eva"
item_state = "paramedic-eva"
desc = "A paramedic EVA suit. Used in the recovery of bodies from space."
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/suit.dmi'
+ )
+ sprite_sheets_obj = list(
+ "Vox" = 'icons/obj/clothing/species/vox/suits.dmi'
+ )
/obj/item/clothing/suit/space/eva
name = "EVA suit"
@@ -149,12 +161,13 @@
desc = "A lightweight space suit with the basic ability to protect the wearer from the vacuum of space during emergencies."
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
species_restricted = list("exclude", "Diona", "Wryn")
- species_fit = list("Vox")
+ species_fit = list("Vox", "Vulpkanin")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/suit.dmi'
+ "Vox" = 'icons/mob/species/vox/suit.dmi',
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/suit.dmi'
)
sprite_sheets_obj = list(
- "Vox" = 'icons/obj/clothing/species/vox/suits.dmi',
+ "Vox" = 'icons/obj/clothing/species/vox/suits.dmi'
)
/obj/item/clothing/head/helmet/space/eva
@@ -166,9 +179,10 @@
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("Vox")
+ species_fit = list("Vox", "Vulpkanin")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/helmet.dmi'
+ "Vox" = 'icons/mob/species/vox/helmet.dmi',
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi'
)
sprite_sheets_obj = list(
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi'
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index d0599fa7ebc..2a77dcd8965 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -17,7 +17,19 @@
if(turfs.len) //Pick a turf to spawn at if we can
var/turf/T = pick(turfs)
- new/obj/effect/spacevine_controller(T) //spawn a controller at turf
+ var/obj/effect/spacevine_controller/SC = new /obj/effect/spacevine_controller(T, , rand(30,70),rand(5,2)) //spawn a controller at turf
+
+ // Make the event start fun - give the vine a random hostile mutation
+ if(SC.vines.len)
+ SV = SC.vines[1]
+ var/list/mutations = SC.mutations_list.Copy()
+ while(mutations.len)
+ var/datum/spacevine_mutation/SM = pick_n_take(mutations)
+ if(SM.quality == NEGATIVE && !SM.nofun)
+ SM.add_mutation_to_vinepiece(SV)
+ break
+ mutations.Cut()
+ mutations = null
/datum/spacevine_mutation
@@ -25,11 +37,22 @@
var/severity = 1
var/hue
var/quality
+ // For stuff that isn't fun as a random-event vine
+ var/nofun = FALSE
/datum/spacevine_mutation/proc/add_mutation_to_vinepiece(obj/effect/spacevine/holder)
holder.mutations |= src
holder.color = hue
+/datum/spacevine_mutation/proc/remove_mutation_from_vinepiece(obj/effect/spacevine/holder)
+ holder.mutations -= src
+ var/datum/spacevine_mutation/oldmutation
+ if(holder.mutations.len)
+ oldmutation = pick(holder.mutations)
+ holder.color = oldmutation.hue
+ else
+ holder.color = ""
+
/datum/spacevine_mutation/proc/process_mutation(obj/effect/spacevine/holder)
return
@@ -136,6 +159,11 @@
/datum/spacevine_mutation/space_covering/on_grow(obj/effect/spacevine/holder)
process_mutation(holder)
+/datum/spacevine_mutation/space_covering/on_spread(obj/effect/spacevine/holder, turf/target)
+ if(target.type == /turf/space && !locate(/obj/effect/spacevine) in target)
+ holder.master.spawn_spacevine_piece(target, holder)
+ . = TRUE
+
/datum/spacevine_mutation/space_covering/process_mutation(obj/effect/spacevine/holder)
var/turf/T = get_turf(holder)
if(is_type_in_typecache(T, coverable_turfs))
@@ -155,7 +183,12 @@
/datum/spacevine_mutation/bluespace/on_spread(obj/effect/spacevine/holder, turf/target)
if(holder.energy > 1 && !locate(/obj/effect/spacevine) in target)
+ // Lose bluespace upon piercing a single tile, and drop it from our own mutations too
+ // Representing a loss in "high potential"
+ // also conveniently prevents this from spreading too crazily
+ remove_mutation_from_vinepiece(holder)
holder.master.spawn_spacevine_piece(target, holder)
+ playsound(holder, 'sound/misc/interference.ogg', 50, 1)
. = TRUE
/datum/spacevine_mutation/light
@@ -190,6 +223,8 @@
hue = "#ff0000"
quality = NEGATIVE
severity = 2
+ // kaboom events aren't fun
+ nofun = TRUE
/datum/spacevine_mutation/explosive/on_explosion(explosion_severity, obj/effect/spacevine/holder)
if(explosion_severity < 3)
@@ -234,6 +269,15 @@
quality = NEGATIVE
/datum/spacevine_mutation/aggressive_spread/on_spread(obj/effect/spacevine/holder, turf/target)
+ if(istype(target, /turf/simulated/wall/r_wall))
+ // Too tough to pierce - should lead to interesting spread patterns
+ return
+ // Bust through windows or other stuff blocking the way
+ if(!target.Enter(holder))
+ for(var/atom/movable/AM in target)
+ if(istype(AM, /obj/effect/spacevine) || !AM.density)
+ continue
+ AM.ex_act(severity)
target.ex_act(severity) // vine immunity handled at /mob/ex_act
. = TRUE
@@ -406,8 +450,8 @@
if(!master.vines.len)
var/obj/item/seeds/kudzu/KZ = new(loc)
KZ.mutations |= mutations
- KZ.set_potency(master.mutativeness * 10)
- KZ.set_production((master.spread_cap / initial(master.spread_cap)) * 5)
+ KZ.set_potency(10 ** sqrt(master.mutativeness))
+ KZ.set_production(10 - (master.spread_cap / 10))
qdel(master)
master = null
mutations.Cut()
@@ -499,11 +543,19 @@
spawn_spacevine_piece(loc, , muts)
processing_objects.Add(src)
init_subtypes(/datum/spacevine_mutation/, mutations_list)
- if(potency != null)
- mutativeness = potency / 10
+ if(potency != null && potency > 0)
+ // 1 mutativeness at 10 potency
+ // 4 mutativeness at 100 potency
+ mutativeness = log(10, potency) ** 2
if(production != null)
- spread_cap /= production / 5
- spread_multiplier *= production / 5
+ // 1 production is crazy powerful
+ var/spread_value = max(10 - production, 1)
+ // 40 at 6 production
+ // 90 at 1 production
+ spread_cap = spread_value * 10
+ // 6 vines/spread at 6 production
+ // ~2.5 vines/spread at 1 production
+ spread_multiplier /= spread_value / 5
..()
@@ -618,7 +670,8 @@
for(var/datum/spacevine_mutation/SM in mutations)
spread_success |= SM.on_spread(src, stepturf) // If this returns 1, spreading succeeded
if(!locate(/obj/effect/spacevine, stepturf))
- if(stepturf.Enter(src))
+ // snowflake for space turf, but space turf is super common and a big deal
+ if(!istype(stepturf, /turf/space) && stepturf.Enter(src))
if(master)
master.spawn_spacevine_piece(stepturf, src)
spread_success = TRUE
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 4c120db79e0..26d22bc0610 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -11,54 +11,57 @@ Gunshots/explosions/opening doors/less rare audio (done)
*/
-/mob/living/carbon/
+#define SCREWYHUD_NONE 0
+#define SCREWYHUD_CRIT 1
+#define SCREWYHUD_DEAD 2
+#define SCREWYHUD_HEALTHY 3
+
+/mob/living/carbon
var/image/halimage
var/image/halbody
var/obj/halitem
- var/hal_screwyhud = 0 //1 - critical, 2 - dead, 3 - oxygen indicator, 4 - toxin indicator
+ var/hal_screwyhud = SCREWYHUD_NONE
var/handling_hal = 0
- var/hal_crit = 0
/mob/living/carbon/proc/handle_hallucinations()
if(handling_hal)
return
//Least obvious
- var/list/minor = list("sounds"=20,"bolts_minor"=10,"whispers"=15,"message"=5)
+ var/list/minor = list("sounds"=25,"bolts_minor"=5,"whispers"=15,"message"=10,"hudscrew"=15)
//Something's wrong here
- var/list/medium = list("hudscrew"=15,"items"=15,"dangerflash"=15,"bolts"=10,"flood"=10,"husks"=10,"battle"=10)
- //AAAAH
- var/list/major = list("fake"=10,"death"=5,"xeno"=10,"singulo"=10,"delusion"=10)
-
- var/grade = 0
- var/current = list()
- var/trip_length = 0
+ var/list/medium = list("fake_alert"=15,"items"=10,"items_other"=10,"dangerflash"=10,"bolts"=5,"flood"=5,"husks"=10,"battle"=15,"self_delusion"=10)
+ //AAAAHg
+ var/list/major = list("fake"=20,"death"=10,"xeno"=10,"singulo"=10,"borer"=10,"delusion"=20,"koolaid"=10)
handling_hal = 1
while(hallucination > 20)
- sleep(rand(200,500)/(hallucination/25))
- trip_length += 1
- if(prob(min(20,trip_length*2)))
- grade = min(3,grade+1)
+ sleep(rand(200, 500) / (hallucination / 25))
if(prob(20))
continue
- current = list()
- for(var/a in minor)
- current[a] = minor[a] * (grade==0?2:1)
- for(var/b in medium)
- current[b] = medium[b] * (grade==1?2:1)
- for(var/c in major)
- current[c] = major[c] * (grade==2?2:1)
+ var/list/current = list()
+ switch(rand(100))
+ if(1 to 50)
+ current = minor
+ if(51 to 85)
+ current = medium
+ if(86 to 100)
+ current = major
var/halpick = pickweight(current)
hallucinate(halpick)
handling_hal = 0
+
/obj/effect/hallucination
invisibility = INVISIBILITY_OBSERVER
var/mob/living/carbon/target = null
+/obj/effect/hallucination/proc/wake_and_restore()
+ target.hal_screwyhud = SCREWYHUD_NONE
+ target.SetSleeping(0)
+
/obj/effect/hallucination/simple
var/image_icon = 'icons/mob/alien.dmi'
var/image_state = "alienh_pounce"
@@ -69,28 +72,31 @@ Gunshots/explosions/opening doors/less rare audio (done)
var/image_layer = MOB_LAYER
var/active = 1 //qdelery
-/obj/effect/hallucination/simple/New(loc,var/mob/living/carbon/T)
+/obj/effect/hallucination/simple/New(loc, mob/living/carbon/T)
+ ..()
target = T
current_image = GetImage()
- if(target.client) target.client.images |= current_image
- return
+ if(target.client)
+ target.client.images |= current_image
/obj/effect/hallucination/simple/proc/GetImage()
- var/image/I = image(image_icon,loc,image_state,image_layer,dir=src.dir)
+ var/image/I = image(image_icon, src, image_state, image_layer, dir = dir)
I.pixel_x = px
I.pixel_y = py
if(col_mod)
I.color = col_mod
return I
-/obj/effect/hallucination/simple/proc/Show(var/update=1)
+/obj/effect/hallucination/simple/proc/Show(update = 1)
if(active)
- if(target.client) target.client.images.Remove(current_image)
+ if(target.client)
+ target.client.images.Remove(current_image)
if(update)
current_image = GetImage()
- if(target.client) target.client.images |= current_image
+ if(target.client)
+ target.client.images |= current_image
-/obj/effect/hallucination/simple/update_icon(var/new_state,var/new_icon,var/new_px=0,var/new_py=0)
+/obj/effect/hallucination/simple/update_icon(new_state, new_icon, new_px = 0, new_py = 0)
image_state = new_state
if(new_icon)
image_icon = new_icon
@@ -105,15 +111,16 @@ Gunshots/explosions/opening doors/less rare audio (done)
Show()
/obj/effect/hallucination/simple/Destroy()
- if(target.client) target.client.images.Remove(current_image)
+ if(target.client)
+ target.client.images.Remove(current_image)
active = 0
return ..()
-#define FAKE_FLOOD_EXPAND_TIME 30
-#define FAKE_FLOOD_MAX_RADIUS 7
+#define FAKE_FLOOD_EXPAND_TIME 20
+#define FAKE_FLOOD_MAX_RADIUS 10
/obj/effect/hallucination/fake_flood
- //Plasma/N2O starts flooding from the nearby vent
+ //Plasma starts flooding from the nearby vent
var/list/flood_images = list()
var/list/turf/flood_turfs = list()
var/image_icon = 'icons/effects/tile_effects.dmi'
@@ -121,17 +128,17 @@ Gunshots/explosions/opening doors/less rare audio (done)
var/radius = 0
var/next_expand = 0
-/obj/effect/hallucination/fake_flood/New(loc,var/mob/living/carbon/T)
+/obj/effect/hallucination/fake_flood/New(loc, mob/living/carbon/T)
..()
target = T
for(var/obj/machinery/atmospherics/unary/vent_pump/U in orange(7,target))
if(!U.welded)
src.loc = U.loc
break
- image_state = pick("plasma","sleeping_agent")
flood_images += image(image_icon,src,image_state,MOB_LAYER)
flood_turfs += get_turf(src.loc)
- if(target.client) target.client.images |= flood_images
+ if(target.client)
+ target.client.images |= flood_images
next_expand = world.time + FAKE_FLOOD_EXPAND_TIME
processing_objects += src
@@ -141,26 +148,30 @@ Gunshots/explosions/opening doors/less rare audio (done)
if(radius > FAKE_FLOOD_MAX_RADIUS)
qdel(src)
Expand()
+ if((get_turf(target) in flood_turfs) && !target.internal)
+ target.hallucinate("fake_alert", "tox_in_air")
next_expand = world.time + FAKE_FLOOD_EXPAND_TIME
- return
/obj/effect/hallucination/fake_flood/proc/Expand()
- if(!flood_turfs) //for qdel
- return
- for(var/turf/T in circlerangeturfs(loc,radius))
- if((T in flood_turfs)|| T.blocks_air)
- continue
- flood_images += image(image_icon,T,image_state,MOB_LAYER)
- flood_turfs += T
- if(target.client) target.client.images |= flood_images
- return
+ for(var/turf/FT in flood_turfs)
+ for(var/dir in cardinal)
+ var/turf/T = get_step(FT, dir)
+ if((T in flood_turfs) || !FT.CanAtmosPass(T))
+ continue
+ flood_images += image(image_icon,T,image_state,MOB_LAYER)
+ flood_turfs += T
+ if(target.client)
+ target.client.images |= flood_images
/obj/effect/hallucination/fake_flood/Destroy()
processing_objects -= src
qdel(flood_turfs)
- if(target.client) target.client.images.Remove(flood_images)
+ flood_turfs = list()
+ if(target.client)
+ target.client.images.Remove(flood_images)
target = null
qdel(flood_images)
+ flood_images = list()
return ..()
/obj/effect/hallucination/simple/xeno
@@ -170,15 +181,15 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/simple/xeno/New(loc,var/mob/living/carbon/T)
..()
name = "alien hunter ([rand(1, 1000)])"
- return
/obj/effect/hallucination/simple/xeno/throw_at(atom/target, range, speed) // TODO : Make diagonal trhow into proc/property
- if(!target || !src || (flags & NODROP)) return 0
+ if(!target || !src || (flags & NODROP))
+ return 0
- src.throwing = 1
+ throwing = 1
- var/dist_x = abs(target.x - src.x)
- var/dist_y = abs(target.y - src.y)
+ var/dist_x = abs(target.x - x)
+ var/dist_y = abs(target.y - y)
var/dist_travelled = 0
var/dist_since_sleep = 0
@@ -190,15 +201,16 @@ Gunshots/explosions/opening doors/less rare audio (done)
tdist_y = dist_x;
var/error = tdist_x/2 - tdist_y
- while(target && (((((dist_x > dist_y) && ((src.x < target.x) || (src.x > target.x))) || ((dist_x <= dist_y) && ((src.y < target.y) || (src.y > target.y))) || (src.x > target.x)) && dist_travelled < range) || !has_gravity(src)))
+ while(target && (((((dist_x > dist_y) && ((x < target.x) || (x > target.x))) || ((dist_x <= dist_y) && ((y < target.y) || (y > target.y))) || (x > target.x)) && dist_travelled < range) || !has_gravity(src)))
+ if(!throwing)
+ break
+ if(!istype(loc, /turf))
+ break
- if(!src.throwing) break
- if(!istype(src.loc, /turf)) break
-
- var/atom/step = get_step(src, get_dir(src,target))
+ var/atom/step = get_step(src, get_dir(src, target))
if(!step)
break
- src.Move(step, get_dir(src, step))
+ Move(step, get_dir(src, step))
hit_check()
error += (error < 0) ? tdist_x : -tdist_y;
dist_travelled++
@@ -208,8 +220,8 @@ Gunshots/explosions/opening doors/less rare audio (done)
sleep(1)
- src.throwing = 0
- src.throw_impact(get_turf(src))
+ throwing = 0
+ throw_impact(get_turf(src))
return 1
@@ -224,49 +236,155 @@ Gunshots/explosions/opening doors/less rare audio (done)
var/obj/machinery/atmospherics/unary/vent_pump/pump = null
var/obj/effect/hallucination/simple/xeno/xeno = null
-/obj/effect/hallucination/xeno_attack/New(loc,var/mob/living/carbon/T)
+/obj/effect/hallucination/xeno_attack/New(loc, mob/living/carbon/T)
target = T
for(var/obj/machinery/atmospherics/unary/vent_pump/U in orange(7,target))
if(!U.welded)
pump = U
break
- if(!pump) return 0
+ if(!pump)
+ return 0
xeno = new(pump.loc,target)
sleep(10)
- if(!xeno) return
+ if(!xeno)
+ return
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(target,7,1)
sleep(10)
- if(!xeno) return
+ if(!xeno)
+ return
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(pump,7,1)
sleep(10)
- if(!xeno) return
+ if(!xeno)
+ return
var/xeno_name = xeno.name
to_chat(target, "[xeno_name] begins climbing into the ventilation system...")
sleep(10)
- if(!xeno) return
+ if(!xeno)
+ return
qdel(xeno)
to_chat(target, "[xeno_name] scrambles into the ventilation ducts!")
qdel(src)
+/obj/effect/hallucination/simple/clown
+ image_icon = 'icons/mob/animal.dmi'
+ image_state = "clown"
+
+/obj/effect/hallucination/simple/clown/New(loc, mob/living/carbon/T, duration)
+ ..(loc, T)
+ name = pick(clown_names)
+ sleep(duration)
+ qdel(src)
+
+/obj/effect/hallucination/simple/clown/scary
+ image_state = "scary_clown"
+
+/obj/effect/hallucination/simple/borer
+ image_icon = 'icons/mob/animal.dmi'
+ image_state = "brainslug"
+
+/obj/effect/hallucination/borer
+ //A borer paralyzes you and crawls in your ear
+ var/obj/machinery/atmospherics/unary/vent_pump/pump = null
+ var/obj/effect/hallucination/simple/borer/borer = null
+
+/obj/effect/hallucination/borer/New(loc, mob/living/carbon/T)
+ ..()
+ target = T
+ for(var/obj/machinery/atmospherics/unary/vent_pump/U in orange(7, target))
+ if(!U.welded)
+ pump = U
+ break
+ if(pump)
+ borer = new(pump.loc,target)
+ for(var/i=0, i<11, i++)
+ walk_to(borer, get_step(borer, get_cardinal_dir(borer, T)))
+ if(borer.Adjacent(T))
+ to_chat(T, "You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing.")
+ T.Stun(4)
+ sleep(50)
+ qdel(borer)
+ sleep(rand(60, 90))
+ to_chat(T, "Primary [rand(1000,9999)] states: [pick("Hello","Hi","You're my slave now!","Don't try to get rid of me...")]")
+ break
+ sleep(4)
+ if(!qdeleted(borer))
+ qdel(borer)
+ qdel(src)
+
+/obj/effect/hallucination/simple/bubblegum
+ name = "Bubblegum"
+ image_icon = 'icons/mob/lavaland/96x96megafauna.dmi'
+ image_state = "bubblegum"
+ px = -32
+
+/obj/effect/hallucination/oh_yeah
+ var/turf/simulated/wall/wall
+ var/obj/effect/hallucination/simple/bubblegum/bubblegum = null
+ var/image/fakebroken
+ var/image/fakerune
+
+/obj/effect/hallucination/oh_yeah/New(loc, mob/living/carbon/T)
+ ..()
+ target = T
+ for(var/turf/simulated/wall/W in range(7,target))
+ wall = W
+ break
+ if(wall)
+ fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER)
+ var/turf/landing = get_turf(target)
+ var/turf/landing_image_turf = get_step(landing, SOUTHWEST) //the icon is 3x3
+ fakerune = image('icons/effects/96x96.dmi', landing_image_turf, "landing", layer = ABOVE_OPEN_TURF_LAYER)
+ fakebroken.override = TRUE
+ if(target.client)
+ target.client.images |= fakebroken
+ target.client.images |= fakerune
+ target.playsound_local(wall,'sound/effects/meteorimpact.ogg', 150, 1)
+ bubblegum = new(wall, target)
+ sleep(10) //ominous wait
+ var/charged = FALSE //only get hit once
+ while(get_turf(bubblegum) != landing && target)
+ bubblegum.forceMove(get_step_towards(bubblegum, landing))
+ bubblegum.setDir(get_dir(bubblegum, landing))
+ target.playsound_local(get_turf(bubblegum), 'sound/effects/meteorimpact.ogg', 150, 1)
+ shake_camera(target, 2, 1)
+ if(bubblegum.Adjacent(target) && !charged)
+ charged = TRUE
+ target.Weaken(4)
+ target.staminaloss += 40
+ step_away(target, bubblegum)
+ shake_camera(target, 4, 3)
+ target.visible_message("[target] jumps backwards, falling on the ground!","[bubblegum] slams into you!")
+ sleep(2)
+ sleep(30)
+ qdel(bubblegum)
+ qdel(src)
+
+/obj/effect/hallucination/oh_yeah/Destroy()
+ if(target.client)
+ target.client.images.Remove(fakebroken)
+ target.client.images.Remove(fakerune)
+ return ..()
+
/obj/effect/hallucination/singularity_scare
//Singularity moving towards you.
//todo Hide where it moved with fake space images
var/obj/effect/hallucination/simple/singularity/s = null
-/obj/effect/hallucination/singularity_scare/New(loc,var/mob/living/carbon/T)
+/obj/effect/hallucination/singularity_scare/New(loc, mob/living/carbon/T)
target = T
- var/turf/start = T.loc
- var/screen_border = pick(SOUTH,EAST,WEST,NORTH)
+ var/turf/start = get_turf(T)
+ var/screen_border = pick(cardinal)
for(var/i = 0,i<11,i++)
- start = get_step(start,screen_border)
+ start = get_step(start, screen_border)
s = new(start,target)
for(var/i = 0,i<11,i++)
sleep(5)
- s.loc = get_step(get_turf(s),get_dir(s,target))
+ s.loc = get_step(get_turf(s), get_dir(s, target))
s.Show()
s.Eat()
+ addtimer(src, "wake_and_restore", rand(50, 100))
qdel(s)
/obj/effect/hallucination/simple/singularity
@@ -277,50 +395,98 @@ Gunshots/explosions/opening doors/less rare audio (done)
py = -96
/obj/effect/hallucination/simple/singularity/proc/Eat(atom/OldLoc, Dir)
- var/target_dist = get_dist(src,target)
- if(target_dist<=3) //"Eaten"
- target.Sleeping(20)
- target.hal_crit = 1
- target.hal_screwyhud = 1
- spawn(rand(50,100))
- target.SetSleeping(0)
- target.hal_crit = 0
- target.hal_screwyhud = 0
+ var/target_dist = get_dist(src, target)
+ if(target_dist <= 3) //"Eaten"
+ target.hal_screwyhud = SCREWYHUD_CRIT
+ target.SetSleeping(8, no_alert = TRUE)
/obj/effect/hallucination/battle
-/obj/effect/hallucination/battle/New(loc,var/mob/living/carbon/T)
+/obj/effect/hallucination/battle/New(loc, mob/living/carbon/T)
target = T
var/hits = rand(3,6)
switch(rand(1,5))
if(1) //Laser fight
for(var/i=0,i...wabbajack...wabbajack...")
+ target.playsound_local(target,'sound/magic/Staff_Change.ogg', 50, 1, -1)
+ delusion = A
+ target.client.images |= A
+ sleep(duration)
qdel(src)
-/obj/effect/hallucination/fakeattacker/New(loc,var/mob/living/carbon/T)
+/obj/effect/hallucination/self_delusion/Destroy()
+ if(target.client)
+ target.client.images.Remove(delusion)
+ return ..()
+
+/obj/effect/hallucination/fakeattacker/New(loc, mob/living/carbon/T)
+ ..()
target = T
var/mob/living/carbon/human/clone = null
var/clone_weapon = null
@@ -417,25 +629,25 @@ Gunshots/explosions/opening doors/less rare audio (done)
var/health = 100
-/obj/effect/fake_attacker/attackby(var/obj/item/weapon/P as obj, mob/living/user as mob, params)
+/obj/effect/fake_attacker/attackby(obj/item/weapon/P, mob/living/user, params)
step_away(src,my_target,2)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
- my_target << sound(pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg'))
+ my_target.playsound_local(src, P.hitsound, 1)
my_target.visible_message("[my_target] flails around wildly.", \
"[my_target] has attacked [src]!")
- src.health -= P.force
+ health -= P.force
return
-/obj/effect/fake_attacker/Crossed(var/mob/M, somenumber)
+/obj/effect/fake_attacker/Crossed(mob/M, somenumber)
if(M == my_target)
step_away(src,my_target,2)
if(prob(30))
for(var/mob/O in oviewers(world.view , my_target))
to_chat(O, "[my_target] stumbles around.")
-/obj/effect/fake_attacker/New(loc,var/mob/living/carbon/T)
+/obj/effect/fake_attacker/New(loc, mob/living/carbon/T)
..()
my_target = T
spawn(300)
@@ -447,25 +659,25 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/fake_attacker/proc/updateimage()
// qdel(src.currentimage)
- if(src.dir == NORTH)
+ if(dir == NORTH)
qdel(src.currentimage)
- src.currentimage = new /image(up,src)
- else if(src.dir == SOUTH)
+ currentimage = new /image(up, src)
+ else if(dir == SOUTH)
qdel(src.currentimage)
- src.currentimage = new /image(down,src)
- else if(src.dir == EAST)
+ currentimage = new /image(down, src)
+ else if(dir == EAST)
qdel(src.currentimage)
- src.currentimage = new /image(right,src)
- else if(src.dir == WEST)
+ currentimage = new /image(right, src)
+ else if(dir == WEST)
qdel(src.currentimage)
- src.currentimage = new /image(left,src)
+ currentimage = new /image(left, src)
my_target << currentimage
/obj/effect/fake_attacker/proc/attack_loop()
while(1)
sleep(rand(5,10))
- if(src.health < 0)
+ if(src.health < 0 || my_target.stat)
collapse()
continue
if(get_dist(src,my_target) > 1)
@@ -474,9 +686,8 @@ Gunshots/explosions/opening doors/less rare audio (done)
updateimage()
else
if(prob(15))
- src.do_attack_animation(my_target)
if(weapon_name)
- my_target << sound(pick('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg'))
+ my_target.playsound_local(my_target, weap.hitsound, 1)
my_target.show_message("[src.name] has attacked [my_target] with [weapon_name]!", 1)
my_target.staminaloss += 30
if(prob(20))
@@ -485,7 +696,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
if(!locate(/obj/effect/overlay) in my_target.loc)
fake_blood(my_target)
else
- my_target << sound(pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'))
+ my_target.playsound_local(my_target, pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'), 25, 1, -1)
my_target.show_message("[src.name] has punched [my_target]!", 1)
my_target.staminaloss += 30
if(prob(33))
@@ -498,8 +709,9 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/fake_attacker/proc/collapse()
collapse = 1
updateimage()
+ qdel(src)
-/obj/effect/fake_attacker/proc/fake_blood(var/mob/target)
+/obj/effect/fake_attacker/proc/fake_blood(mob/target)
var/obj/effect/overlay/O = new/obj/effect/overlay(target.loc)
O.name = "blood"
var/image/I = image('icons/effects/blood.dmi',O,"floor[rand(1,7)]",O.dir,1)
@@ -527,7 +739,7 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
/obj/effect/hallucination/bolts
var/list/doors = list()
-/obj/effect/hallucination/bolts/New(loc,var/mob/living/carbon/T,var/door_number=-1) //-1 for sever 1-2 for subtle
+/obj/effect/hallucination/bolts/New(loc, mob/living/carbon/T, door_number = -1) //-1 for sever 1-2 for subtle
target = T
var/image/I = null
var/count = 0
@@ -535,23 +747,26 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
if(count>door_number && door_number>0)
break
count++
- I = image(A.icon,A,"door_locked",layer=A.layer+0.1)
+ I = image(A.icon, get_turf(A), "door_locked", layer=A.layer+0.1)
doors += I
if(target.client)
target.client.images |= I
- sleep(2)
+ target.playsound_local(get_turf(A), 'sound/machines/BoltsDown.ogg',30,0,3)
+ sleep(rand(6,12))
sleep(100)
for(var/image/B in doors)
if(target.client)
target.client.images.Remove(B)
+ target.playsound_local(get_turf(B), 'sound/machines/BoltsUp.ogg',30,0,3)
+ sleep(rand(6,12))
qdel(src)
/obj/effect/hallucination/whispers
/obj/effect/hallucination/whispers/New(loc,var/mob/living/carbon/T)
target = T
- var/speak_messages = list("I'm watching you...","[target.name]!","Go away!","Kchck-Chkck? Kchchck!","Did you hear that?","What did you do ?","Why?","Give me that!","Honk!","HELP!!")
- var/radio_messages = list("Xenos!","Singularity loose!","They are arming the nuke!","They butchered Ian!","H-help!","[pick(teleportlocs)]!!","Where's [target.name]?","Call the shuttle!")
+ var/speak_messages = list("I'm watching you...","[target.name]!","Get out!","Kchck-Chkck? Kchchck!","Did you hear that?","What did you do ?","Why?","Give me that!","Honk!","HELP!!", "EI NATH!!", "RUN!!", "Kill me!","O bidai nabora se'sma!")
+ var/radio_messages = list("Xenos!","Singularity loose!","Comms down!","They are arming the nuke!","They butchered Ian!","H-help!","[pick("Cult", "Wizard", "Ling", "Ops", "Revenant", "Murderer", "Harm", "I hear flashing", "Help")] in [pick(teleportlocs)][prob(50)?"!":"!!"]","Where's [target.name]?","Call the shuttle!","AI rogue!!")
var/list/mob/living/carbon/people = list()
var/list/mob/living/carbon/person = null
@@ -565,7 +780,12 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
person = H
people += H
if(person) //Basic talk
+ var/image/speech_overlay = image('icons/mob/talk.dmi', person, "h0", layer = ABOVE_MOB_LAYER)
target.hear_say(pick(speak_messages),language = pick(person.languages),speaker = person)
+ if(target.client)
+ target.client.images |= speech_overlay
+ sleep(30)
+ target.client.images.Remove(speech_overlay)
else // Radio talk
var/list/humans = list()
for(var/mob/living/carbon/human/H in living_mob_list)
@@ -578,76 +798,93 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
/obj/effect/hallucination/message/New(loc,var/mob/living/carbon/T)
target = T
- var/chosen = pick("The light burns you!", \
- "You don't feel like yourself.", \
- "Unknown has punched [target]!", \
- "You hear something squeezing through the ducts...", \
- "You hear a distant scream.", \
- "You feel invincible, nothing can hurt you!", \
- "[target] sneezes.", \
- "You feel faint.", \
- "You hear a strange, alien voice in your head...[pick("Hiss","Ssss")]", \
+ var/chosen = pick("The light burns you!",
+ "You don't feel like yourself.",
+ "Unknown has punched [target]!",
+ "You hear something squeezing through the ducts...",
+ "You hear a distant scream.",
+ "You feel invincible, nothing can hurt you!",
+ "You feel a tiny prick!",
+ "[target] sneezes.",
+ "You feel faint.",
+ "You hear a strange, alien voice in your head...[pick("Hiss","Ssss")]",
"You can see...everything!")
to_chat(target, chosen)
qdel(src)
-/mob/living/carbon/proc/hallucinate(var/hal_type) // Todo -> proc / defines
+/mob/living/carbon/proc/hallucinate(hal_type, specific) // specific is used to specify a particular hallucination
switch(hal_type)
if("xeno")
- new /obj/effect/hallucination/xeno_attack(src.loc,src)
+ new /obj/effect/hallucination/xeno_attack(loc, src)
+ if("borer")
+ new /obj/effect/hallucination/borer(loc, src)
if("singulo")
- new /obj/effect/hallucination/singularity_scare(src.loc,src)
+ new /obj/effect/hallucination/singularity_scare(loc, src)
+ if("koolaid")
+ new /obj/effect/hallucination/oh_yeah(loc, src)
if("battle")
- new /obj/effect/hallucination/battle(src.loc,src)
+ new /obj/effect/hallucination/battle(loc, src)
if("flood")
- new /obj/effect/hallucination/fake_flood(src.loc,src)
+ new /obj/effect/hallucination/fake_flood(loc, src)
if("delusion")
- new /obj/effect/hallucination/delusion(src.loc,src)
+ new /obj/effect/hallucination/delusion(loc, src)
+ if("self_delusion")
+ new /obj/effect/hallucination/self_delusion(loc, src)
if("fake")
- new /obj/effect/hallucination/fakeattacker(src.loc,src)
+ new /obj/effect/hallucination/fakeattacker(loc, src)
if("bolts")
- new /obj/effect/hallucination/bolts(src.loc,src)
+ new /obj/effect/hallucination/bolts(loc, src)
if("bolts_minor")
- new /obj/effect/hallucination/bolts(src.loc,src,rand(1,2))
+ new /obj/effect/hallucination/bolts(loc,src, rand(1,2))
if("whispers")
- new /obj/effect/hallucination/whispers(src.loc,src)
+ new /obj/effect/hallucination/whispers(loc, src)
if("message")
- new /obj/effect/hallucination/message(src.loc,src)
+ new /obj/effect/hallucination/message(loc, src)
+ if("items_other")
+ new /obj/effect/hallucination/items_other(src.loc,src)
if("sounds")
//Strange audio
// to_chat(src, "Strange Audio")
switch(rand(1,18))
if(1)
- src << 'sound/machines/airlock.ogg'
+ playsound_local(null,'sound/machines/airlock.ogg', 15, 1)
if(2)
if(prob(50))
- src << 'sound/effects/Explosion1.ogg'
+ playsound_local(null,'sound/effects/Explosion1.ogg', 50, 1)
else
- src << 'sound/effects/Explosion2.ogg'
+ playsound_local(null, 'sound/effects/Explosion2.ogg', 50, 1)
if(3)
- src << 'sound/effects/explosionfar.ogg'
+ playsound_local(null, 'sound/effects/explosionfar.ogg', 50, 1)
if(4)
- src << 'sound/effects/Glassbr1.ogg'
+ playsound_local(null, pick('sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg'), 50, 1)
if(5)
- src << 'sound/effects/Glassbr2.ogg'
+ playsound_local(null, 'sound/weapons/ring.ogg', 35)
+ sleep(15)
+ playsound_local(null, 'sound/weapons/ring.ogg', 35)
+ sleep(15)
+ playsound_local(null, 'sound/weapons/ring.ogg', 35)
if(6)
- src << 'sound/effects/Glassbr3.ogg'
+ playsound_local(null, 'sound/magic/Summon_guns.ogg', 50, 1)
if(7)
- src << 'sound/machines/twobeep.ogg'
+ playsound_local(null, 'sound/machines/Alarm.ogg', 100, 0)
if(8)
- src << 'sound/machines/windowdoor.ogg'
+ playsound_local(null, 'sound/voice/bfreeze.ogg', 35, 0)
if(9)
//To make it more realistic, I added two gunshots (enough to kill)
- src << 'sound/weapons/Gunshot.ogg'
+ playsound_local(null, 'sound/weapons/Gunshot.ogg', 25, 1)
spawn(rand(10,30))
- src << 'sound/weapons/Gunshot.ogg'
+ playsound_local(null, 'sound/weapons/Gunshot.ogg', 25, 1)
+ sleep(rand(5,10))
+ playsound_local(null, sound(get_sfx("bodyfall"), 25), 25, 1)
if(10)
- src << 'sound/weapons/smash.ogg'
+ playsound_local(null, 'sound/effects/pray_chaplain.ogg', 50)
if(11)
//Same as above, but with tasers.
- src << 'sound/weapons/Taser.ogg'
+ playsound_local(null, 'sound/weapons/Taser.ogg', 25, 1)
spawn(rand(10,30))
- src << 'sound/weapons/Taser.ogg'
+ playsound_local(null, 'sound/weapons/Taser.ogg', 25, 1)
+ sleep(rand(5,10))
+ playsound_local(null, sound(get_sfx("bodyfall"), 25), 25, 1)
//Rare audio
if(12)
//These sounds are (mostly) taken from Hidden: Source
@@ -656,40 +893,112 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\
'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\
'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg')
- src << pick(creepyasssounds)
+ playsound_local(null, pick(creepyasssounds), 50, 1)
if(13)
to_chat(src, "You feel a tiny prick!")
if(14)
to_chat(src, "Priority Announcement
")
to_chat(src, "
The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.
")
- src << sound('sound/AI/shuttledock.ogg')
+ playsound_local(null, 'sound/AI/shuttledock.ogg', 100)
if(15)
- src << 'sound/items/Welder.ogg'
+ playsound_local(null, 'sound/items/Welder.ogg', 15, 1)
+ sleep(105)
+ playsound_local(null, 'sound/items/Welder2.ogg', 15, 1)
+ sleep(15)
+ playsound_local(null, 'sound/items/Ratchet.ogg', 15, 1)
if(16)
- src << 'sound/items/Screwdriver.ogg'
+ playsound_local(null, 'sound/items/Screwdriver.ogg', 15, 1)
+ sleep(rand(10,30))
+ for(var/i = rand(1,3), i>0, i--)
+ playsound_local(null, 'sound/weapons/empty.ogg', 15, 1)
+ sleep(rand(10,30))
+ playsound_local(null, 'sound/machines/airlockforced.ogg', 15, 1)
if(17)
- src << 'sound/weapons/saberon.ogg'
+ playsound_local(null, 'sound/weapons/saberon.ogg', 35, 1)
if(18)
- src << 'sound/weapons/saberoff.ogg'
+ to_chat(src, "Biohazard Alert
")
+ to_chat(src, "
Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.
")
+ playsound_local(null, 'sound/AI/outbreak5.ogg')
+ if(19) //Tesla loose!
+ playsound_local(null, 'sound/magic/lightningbolt.ogg', 35, 1)
+ sleep(20)
+ playsound_local(null, 'sound/magic/lightningbolt.ogg', 65, 1)
+ sleep(20)
+ playsound_local(null, 'sound/magic/lightningbolt.ogg', 100, 1)
+ if(20) //AI is doomsdaying!
+ to_chat(src, "Anomaly Alert
")
+ to_chat(src, "
Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.
")
+ playsound_local(null, 'sound/AI/aimalf.ogg')
if("hudscrew")
//Screwy HUD
-// to_chat(src, "Screwy HUD")
- hal_screwyhud = pick(1,2,3,3,4,4)
- spawn(rand(100,250))
- hal_screwyhud = 0
+ hal_screwyhud = pick(SCREWYHUD_NONE, SCREWYHUD_CRIT, SCREWYHUD_DEAD, SCREWYHUD_HEALTHY)
+ sleep(rand(100,250))
+ hal_screwyhud = SCREWYHUD_NONE
+ if("fake_alert")
+ var/alert_type = pick("oxy","not_enough_tox","not_enough_co2","too_much_oxy","too_much_co2","tox_in_air","newlaw","nutrition","charge","weightless","fire","locked","hacked","temp","pressure")
+ if(specific)
+ alert_type = specific
+ switch(alert_type)
+ if("oxy")
+ throw_alert("oxy", /obj/screen/alert/oxy, override = TRUE)
+ if("not_enough_tox")
+ throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox, override = TRUE)
+ if("not_enough_co2")
+ throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2, override = TRUE)
+ if("too_much_oxy")
+ throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy, override = TRUE)
+ if("too_much_co2")
+ throw_alert("too_much_co2", /obj/screen/alert/too_much_co2, override = TRUE)
+ if("tox_in_air")
+ throw_alert("tox_in_air", /obj/screen/alert/tox_in_air, override = TRUE)
+ if("nutrition")
+ if(prob(50))
+ throw_alert("nutrition", /obj/screen/alert/fat, override = TRUE)
+ else
+ throw_alert("nutrition", /obj/screen/alert/starving, override = TRUE)
+ if("weightless")
+ throw_alert("weightless", /obj/screen/alert/weightless, override = TRUE)
+ if("fire")
+ throw_alert("fire", /obj/screen/alert/fire, override = TRUE)
+ if("temp")
+ if(prob(50))
+ throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE)
+ else
+ throw_alert("temp", /obj/screen/alert/cold, 3, override = TRUE)
+ if("pressure")
+ if(prob(50))
+ throw_alert("pressure", /obj/screen/alert/highpressure, 2, override = TRUE)
+ else
+ throw_alert("pressure", /obj/screen/alert/lowpressure, 2, override = TRUE)
+ //BEEP BOOP I AM A ROBOT
+ if("newlaw")
+ throw_alert("newlaw", /obj/screen/alert/newlaw, override = TRUE)
+ if("locked")
+ throw_alert("locked", /obj/screen/alert/locked, override = TRUE)
+ if("hacked")
+ throw_alert("hacked", /obj/screen/alert/hacked, override = TRUE)
+ if("charge")
+ throw_alert("charge",/obj/screen/alert/emptycell, override = TRUE)
+ sleep(rand(100,200))
+ clear_alert(alert_type, clear_override = TRUE)
if("items")
//Strange items
// to_chat(src, "Traitor Items")
if(!halitem)
halitem = new
var/list/slots_free = list(ui_lhand,ui_rhand)
- if(l_hand) slots_free -= ui_lhand
- if(r_hand) slots_free -= ui_rhand
+ if(l_hand)
+ slots_free -= ui_lhand
+ if(r_hand)
+ slots_free -= ui_rhand
if(istype(src,/mob/living/carbon/human))
var/mob/living/carbon/human/H = src
- if(!H.belt) slots_free += ui_belt
- if(!H.l_store) slots_free += ui_storage1
- if(!H.r_store) slots_free += ui_storage2
+ if(!H.belt)
+ slots_free += ui_belt
+ if(!H.l_store)
+ slots_free += ui_storage1
+ if(!H.r_store)
+ slots_free += ui_storage2
if(slots_free.len)
halitem.screen_loc = pick(slots_free)
halitem.layer = 50
@@ -726,7 +1035,6 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
qdel(halitem)
if("dangerflash")
//Flashes of danger
-// to_chat(src, "Danger Flash")
if(!halimage)
var/list/possible_points = list()
for(var/turf/simulated/floor/F in view(src,world.view))
@@ -734,31 +1042,38 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
if(possible_points.len)
var/turf/simulated/floor/target = pick(possible_points)
- switch(rand(1,3))
+ switch(rand(1,4))
if(1)
-// to_chat(src, "Space")
halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER)
if(2)
-// to_chat(src, "Fire")
- halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER)
+ halimage = image('icons/turf/floors/lava.dmi',target,"smooth",TURF_LAYER)
if(3)
-// to_chat(src, "C4")
+ halimage = image('icons/turf/floors/Chasms.dmi',target,"smooth",TURF_LAYER)
+ if(4)
halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01)
- if(client) client.images += halimage
- spawn(rand(10,50)) //Only seen for a brief moment.
- if(client) client.images -= halimage
- halimage = null
+ if(client)
+ client.images += halimage
+ sleep(rand(40,60)) //Only seen for a brief moment.
+ if(client)
+ client.images -= halimage
+ halimage = null
if("death")
- //Fake death
- Sleeping(20)
- hal_crit = 1
- hal_screwyhud = 1
- spawn(rand(50,100))
- SetSleeping(0)
- hal_crit = 0
- hal_screwyhud = 0
+ hal_screwyhud = SCREWYHUD_DEAD
+ SetSleeping(20, no_alert = TRUE)
+ if(prob(50))
+ var/list/dead_people = list()
+ for(var/mob/dead/observer/G in player_list)
+ dead_people += G
+ var/mob/dead/observer/fakemob = pick(dead_people)
+ if(fakemob)
+ sleep(rand(30, 60))
+ to_chat(src, "[fakemob.name](FOLLOW) [pick("complains", "moans", "whines", "laments", "blubbers", "salts")], \"[pick("rip","welcome [name]","you too?","is the AI malf?",\
+ "i[prob(50)?" fucking":""] hate [pick("blood cult", "clock cult", "revenants", "abductors","double agents","viruses","badmins","you")]")]\"")
+ sleep(rand(50,70))
+ hal_screwyhud = SCREWYHUD_NONE
+ SetSleeping(0)
if("husks")
if(!halbody)
var/list/possible_points = list()
@@ -768,17 +1083,19 @@ var/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/projectile, /obj/ite
var/turf/simulated/floor/target = pick(possible_points)
switch(rand(1,4))
if(1)
- var/image/body = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER)
+ var/image/body = image('icons/mob/human.dmi', target, "husk_s", TURF_LAYER)
var/matrix/M = matrix()
M.Turn(90)
body.transform = M
halbody = body
if(2,3)
- halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER)
+ halbody = image('icons/mob/human.dmi', target, "husk_s", TURF_LAYER)
if(4)
- halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER)
+ halbody = image('icons/mob/alien.dmi', target, "alienother", TURF_LAYER)
- if(client) client.images += halbody
- spawn(rand(50,80)) //Only seen for a brief moment.
- if(client) client.images -= halbody
+ if(client)
+ client.images += halbody
+ spawn(rand(30,50)) //Only seen for a brief moment.
+ if(client)
+ client.images -= halbody
halbody = null
diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm
index 4e0cf476879..54550a0f560 100644
--- a/code/modules/mob/living/carbon/human/species/species.dm
+++ b/code/modules/mob/living/carbon/human/species/species.dm
@@ -528,9 +528,9 @@
H.healths.icon_state = "health7"
else
switch(H.hal_screwyhud)
- if(1) H.healths.icon_state = "health6"
- if(2) H.healths.icon_state = "health7"
- if(5) H.healths.icon_state = "health0"
+ if(SCREWYHUD_CRIT) H.healths.icon_state = "health6"
+ if(SCREWYHUD_DEAD) H.healths.icon_state = "health7"
+ if(SCREWYHUD_HEALTHY) H.healths.icon_state = "health0"
else
switch(100 - ((flags & NO_PAIN) ? 0 : H.traumatic_shock) - H.staminaloss)
if(100 to INFINITY) H.healths.icon_state = "health0"
diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm
index 5ca23f89f4f..5f74f202603 100644
--- a/code/modules/mob/living/carbon/human/status_procs.dm
+++ b/code/modules/mob/living/carbon/human/status_procs.dm
@@ -13,7 +13,7 @@
amount = amount * species.stun_mod
..()
-/mob/living/carbon/human/SetSleeping(amount, updating = 1)
+/mob/living/carbon/human/SetSleeping(amount, updating = 1, no_alert = FALSE)
if(species)
amount = amount * species.stun_mod
..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index d24471dc7e2..61906d0c967 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -1202,7 +1202,7 @@ var/global/list/damage_icon_parts = list()
var/icon/tail_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[tail]_s")
if(species.bodyflags & HAS_SKIN_COLOR)
tail_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
- if(tail_marking_icon)
+ if(tail_marking_icon && !tail_marking_style.tails_allowed)
tail_s.Blend(tail_marking_icon, ICON_OVERLAY)
if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this)
// Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway.
@@ -1270,7 +1270,7 @@ var/global/list/damage_icon_parts = list()
var/icon/tailw_s = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[tail]w_s")
if(species.bodyflags & HAS_SKIN_COLOR)
tailw_s.Blend(rgb(r_skin, g_skin, b_skin), ICON_ADD)
- if(tail_marking_icon)
+ if(tail_marking_icon && !tail_marking_style.tails_allowed)
tailw_s.Blend(tail_marking_icon, ICON_OVERLAY)
if((!body_accessory || istype(body_accessory, /datum/body_accessory/tail)) && species.bodyflags & TAIL_OVERLAPPED) // If the player has a species whose tail is overlapped by limbs... (having a non-tail body accessory like the snake body will override this)
// Gives the underlimbs layer SEW direction icons since it's overlayed by limbs and just about everything else anyway.
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 91661304144..da764cafda3 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -345,7 +345,7 @@
if(..())
handle_dreams()
adjustStaminaLoss(-10)
- if(prob(10) && health && !hal_crit)
+ if(prob(10) && health && hal_screwyhud != SCREWYHUD_CRIT)
spawn(0)
emote("snore")
// Keep SSD people asleep
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index e95381d19cf..30fe030bdcb 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -354,19 +354,19 @@
// SLEEPING
-/mob/living/Sleeping(amount, updating = 1)
- SetSleeping(max(sleeping, amount), updating)
+/mob/living/Sleeping(amount, updating = 1, no_alert = FALSE)
+ SetSleeping(max(sleeping, amount), updating, no_alert)
-/mob/living/SetSleeping(amount, updating = 1)
+/mob/living/SetSleeping(amount, updating = 1, no_alert = FALSE)
sleeping = max(amount, 0)
- update_sleeping_effects()
+ update_sleeping_effects(no_alert)
if(updating)
update_stat()
update_canmove()
-/mob/living/AdjustSleeping(amount, bound_lower = 0, bound_upper = INFINITY, updating = 1)
+/mob/living/AdjustSleeping(amount, bound_lower = 0, bound_upper = INFINITY, updating = 1, no_alert = FALSE)
var/new_value = directional_bounded_sum(sleeping, amount, bound_lower, bound_upper)
- SetSleeping(new_value, updating)
+ SetSleeping(new_value, updating, no_alert)
// SLOWED
diff --git a/code/modules/mob/living/update_status.dm b/code/modules/mob/living/update_status.dm
index 59b7077e79e..257a4bc87c1 100644
--- a/code/modules/mob/living/update_status.dm
+++ b/code/modules/mob/living/update_status.dm
@@ -30,9 +30,10 @@
else
clear_fullscreen("nearsighted")
-/mob/living/update_sleeping_effects()
+/mob/living/update_sleeping_effects(no_alert = FALSE)
if(sleeping)
- throw_alert("asleep", /obj/screen/alert/asleep)
+ if(!no_alert)
+ throw_alert("asleep", /obj/screen/alert/asleep)
else
clear_alert("asleep")
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 8b8fafd32b7..52fdbdf0328 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -199,6 +199,10 @@
var/atom/O = mob.loc
return O.relaymove(mob, direct)
+ if(istype(mob.get_active_hand(), /obj/item))
+ var/obj/item/I = mob.get_active_hand()
+ I.moved(mob, n, direct)
+
if(!mob.Process_Spacemove(direct))
return 0
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 849511a48e7..176ce72f005 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -114,7 +114,7 @@ By design, d1 is the smallest direction and d2 is the highest
//
/obj/structure/cable/attackby(obj/item/W, mob/user)
- var/turf/T = src.loc
+ var/turf/T = get_turf(src)
if(T.intact)
return
@@ -149,7 +149,7 @@ By design, d1 is the smallest direction and d2 is the highest
if(c.d1 == 12 || c.d2 == 12)
c.qdel()*/
///// Z-Level Stuff
- investigate_log("was cut by [key_name(usr, usr.client)] in [user.loc.loc]([T.x], [T.y], [T.z] - JMP)","wires")
+ investigate_log("was cut by [key_name(usr, usr.client)] in [get_area(user)]([T.x], [T.y], [T.z] - [ADMIN_JMP(T)])","wires")
qdel(src) // qdel
return
@@ -162,6 +162,12 @@ By design, d1 is the smallest direction and d2 is the highest
return
coil.cable_join(src, user)
+ else if(istype(W, /obj/item/weapon/twohanded/rcl))
+ var/obj/item/weapon/twohanded/rcl/R = W
+ if(R.loaded)
+ R.loaded.cable_join(src, user)
+ R.is_empty(user)
+
else if(istype(W, /obj/item/device/multitool))
if(powernet && (powernet.avail > 0)) // is it powered?
@@ -197,12 +203,12 @@ By design, d1 is the smallest direction and d2 is the highest
qdel(src) // qdel
if(2.0)
if(prob(50))
- new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, color)
+ new/obj/item/stack/cable_coil(get_turf(src), src.d1 ? 2 : 1, color)
qdel(src) // qdel
if(3.0)
if(prob(25))
- new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, color)
+ new/obj/item/stack/cable_coil(get_turf(src), src.d1 ? 2 : 1, color)
qdel(src) // qdel
return
@@ -505,7 +511,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
// General procedures
///////////////////////////////////
//you can use wires to heal robotics
-/obj/item/stack/cable_coil/attack(mob/M as mob, mob/user as mob)
+/obj/item/stack/cable_coil/attack(mob/M, mob/user)
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/external/S = H.organs_by_name[user.zone_sel.selecting]
@@ -613,11 +619,11 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
return C
// called when cable_coil is clicked on a turf/simulated/floor
-/obj/item/stack/cable_coil/proc/place_turf(turf/T, mob/user)
+/obj/item/stack/cable_coil/proc/place_turf(turf/T, mob/user, dirnew)
if(!isturf(user.loc))
return
- if(!T.can_have_cabling())
+ if(!isturf(T) || T.intact || !T.can_have_cabling())
to_chat(user, "You can only lay cables on catwalks and plating!")
return
@@ -629,44 +635,46 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
to_chat(user, "You can't lay cable at a place that far away!")
return
- else
- var/dirn
-
+ var/dirn = null
+ if(!dirnew) //If we weren't given a direction, come up with one! (Called as null from catwalk.dm and floor.dm)
if(user.loc == T)
- dirn = user.dir // if laying on the tile we're on, lay in the direction we're facing
+ dirn = user.dir //If laying on the tile we're on, lay in the direction we're facing
else
dirn = get_dir(T, user)
+ else
+ dirn = dirnew
- for(var/obj/structure/cable/LC in T)
- if(LC.d2 == dirn && LC.d1 == 0)
- to_chat(user, "There's already a cable at that position!")
- return
+ for(var/obj/structure/cable/LC in T)
+ if(LC.d2 == dirn && LC.d1 == 0)
+ to_chat(user, "There's already a cable at that position!")
+ return
- var/obj/structure/cable/C = get_new_cable(T)
+ var/obj/structure/cable/C = get_new_cable(T)
- //set up the new cable
- C.d1 = 0 //it's a O-X node cable
- C.d2 = dirn
- C.add_fingerprint(user)
- C.updateicon()
+ //set up the new cable
+ C.d1 = 0 //it's a O-X node cable
+ C.d2 = dirn
+ C.add_fingerprint(user)
+ C.updateicon()
- //create a new powernet with the cable, if needed it will be merged later
- var/datum/powernet/PN = new()
- PN.add_cable(C)
+ //create a new powernet with the cable, if needed it will be merged later
+ var/datum/powernet/PN = new()
+ PN.add_cable(C)
- C.mergeConnectedNetworks(C.d2) //merge the powernet with adjacents powernets
- C.mergeConnectedNetworksOnTurf() //merge the powernet with on turf powernets
+ C.mergeConnectedNetworks(C.d2) //merge the powernet with adjacents powernets
+ C.mergeConnectedNetworksOnTurf() //merge the powernet with on turf powernets
- if(C.d2 & (C.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions
- C.mergeDiagonalsNetworks(C.d2)
+ if(C.d2 & (C.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions
+ C.mergeDiagonalsNetworks(C.d2)
+ use(1)
- use(1)
+ if(C.shock(user, 50))
+ if(prob(50)) //fail
+ new /obj/item/stack/cable_coil(get_turf(C), 1, C.color)
+ qdel(C) // qdel
- if(C.shock(user, 50))
- if(prob(50)) //fail
- new/obj/item/stack/cable_coil(C.loc, 1, C.color)
- qdel(C) // qdel
+ return C
// called when cable_coil is click on an installed obj/cable
// or click on a turf that already contains a "node" cable
@@ -675,7 +683,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
if(!isturf(U))
return
- var/turf/T = C.loc
+ var/turf/T = get_turf(C)
if(!isturf(T) || T.intact) // sanity checks, also stop use interacting with T-scanner revealed cable
return
@@ -700,38 +708,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
// cable is pointing at us, we're standing on an open tile
// so create a stub pointing at the clicked cable on our tile
- var/fdirn = turn(dirn, 180) // the opposite direction
-
- for(var/obj/structure/cable/LC in U) // check to make sure there's not a cable there already
- if(LC.d1 == fdirn || LC.d2 == fdirn)
- to_chat(user, "There's already a cable at that position.")
- return
-
- var/obj/structure/cable/NC = new(U)
- NC.cableColor(color)
-
- NC.d1 = 0
- NC.d2 = fdirn
- NC.add_fingerprint()
- NC.updateicon()
-
- //create a new powernet with the cable, if needed it will be merged later
- var/datum/powernet/newPN = new()
- newPN.add_cable(NC)
-
- NC.mergeConnectedNetworks(NC.d2) //merge the powernet with adjacents powernets
- NC.mergeConnectedNetworksOnTurf() //merge the powernet with on turf powernets
-
- if(NC.d2 & (NC.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions
- NC.mergeDiagonalsNetworks(NC.d2)
-
- use(1)
-
- if(NC.shock(user, 50))
- if(prob(50)) //fail
- new/obj/item/stack/cable_coil(NC.loc, 1, NC.color)
- qdel(NC) // qdel
-
+ place_turf(T, user, turn(dirn, 180))
return
// exisiting cable doesn't point at our position, so see if it's a stub
@@ -777,7 +754,7 @@ var/global/list/datum/stack_recipe/cable_coil_recipes = list(
if(C.shock(user, 50))
if(prob(50)) //fail
- new/obj/item/stack/cable_coil(C.loc, 2, C.color)
+ new/obj/item/stack/cable_coil(get_turf(C), 2, C.color)
qdel(C) // qdel
return
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index ccab76f6e92..5c8d5136324 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -81,13 +81,14 @@
/obj/item/projectile/bullet/pellet
name = "pellet"
- damage = 15
+ damage = 12.5
/obj/item/projectile/bullet/pellet/weak
damage = 6
/obj/item/projectile/bullet/pellet/weak/New()
- range = rand(8)
+ range = rand(1, 8)
+ ..()
/obj/item/projectile/bullet/pellet/weak/on_range()
var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread
@@ -99,7 +100,8 @@
damage = 3
/obj/item/projectile/bullet/pellet/overload/New()
- range = rand(10)
+ range = rand(1, 10)
+ ..()
/obj/item/projectile/bullet/pellet/overload/on_hit(atom/target, blocked = 0)
..()
diff --git a/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm b/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm
index 9e9de74e73e..c3e29fe8638 100644
--- a/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm
+++ b/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm
@@ -23,6 +23,9 @@
item_state = "cespace_suit"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 100)
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank)
+ species_fit = null
+ sprite_sheets = null
+ sprite_sheets_obj = null
/obj/item/clothing/head/helmet/space/eva/anomaly
name = "Excavation hood"
@@ -30,3 +33,6 @@
icon_state = "cespace_helmet"
item_state = "cespace_helmet"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 100)
+ species_fit = null
+ sprite_sheets = null
+ sprite_sheets_obj = null
diff --git a/html/changelog.html b/html/changelog.html
index 5c7d200cb58..97656cf4d69 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -55,7 +55,54 @@
-->
+
12 March 2017
+
Crazylemon64 updated:
+
+ - Kudzu should now be less of (but still) a station-destroying force of nature.
+ - Bluespace kudzu now only pierces a single layer of walls before losing its "charge".
+ - Aggressive spread now does not bust rwalls, but does attack obstructing objects in its path.
+ - Kudzu now only spreads on space turfs when it has specific mutations to do so.
+ - Kudzu events should be more interesting on their own.
+
+
Jovaniph updated:
+
+ - Adds Vulpkanin EVA suit sprite
+
+
Markolie updated:
+
+ - The system for picking ghosts to inhabit cultist slaughter demons now shows a confirmation prompt like most other role checks.
+ - Fixed an issue where you could join as a cultist slaughter demon despite having antagHUD enabled.
+ - Fixed an issue where it was possible to weld statues without any fuel.
+ - It is no longer possible to spam the firelock force message.
+
+
Twinmold93 updated:
+
+ - Employment record laptop to Head of Personnel's Office. Moves package wrap that was there to meeting room to be paired with the hand labeler there.
+
+
11 March 2017
+
Developed by XDTM, ported by davipatury updated:
+
+ - Hallucinations have been modified to increase the creepiness factor and reduce the boring factor.
+ - Added some new hallucinations.
+ - Fixed a bug where the singularity hallucination was stunning for longer than intended and leaving the fake HUD crit icon permanently.
+
+
Flatty Patty updated:
+
+ - all the tools have icons again
+
+
FlattyPatty updated:
+
+ - Improved Nanotrasen click manufacturing procedures now allow the flashlights to make that classic clicking sound you know and love.
+
+
Fox McCloud updated:
+
+ - Buckshot now does a max of 70 damage, down from 90
+
+
KasparoVy updated:
+
+ - Fixes a bug with certain tail markings rendering when they shouldn't.
+
Markolie updated:
- Firelocks forced by AI's, cyborgs at range or admin ghosts will now autoclose if there's still an atmospherics alarm present.
@@ -65,6 +112,7 @@
davipatury updated:
- Ported Modular Computers from /tg/.
+ - Ported Rapid Cable Layer from /vg/.
uraniummeltdown updated:
diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml
index c6b164576ae..392f5402f66 100644
--- a/html/changelogs/.all_changelog.yml
+++ b/html/changelogs/.all_changelog.yml
@@ -4061,6 +4061,21 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
crystals (for construction).
- rscdel: Removes the pipe fitting on the table from atmospherics as it was broken.
2017-03-11:
+ Developed by XDTM, ported by davipatury:
+ - tweak: Hallucinations have been modified to increase the creepiness factor and
+ reduce the boring factor.
+ - rscadd: Added some new hallucinations.
+ - bugfix: Fixed a bug where the singularity hallucination was stunning for longer
+ than intended and leaving the fake HUD crit icon permanently.
+ Flatty Patty:
+ - bugfix: all the tools have icons again
+ FlattyPatty:
+ - tweak: Improved Nanotrasen click manufacturing procedures now allow the flashlights
+ to make that classic clicking sound you know and love.
+ Fox McCloud:
+ - tweak: Buckshot now does a max of 70 damage, down from 90
+ KasparoVy:
+ - bugfix: Fixes a bug with certain tail markings rendering when they shouldn't.
Markolie:
- tweak: Firelocks forced by AI's, cyborgs at range or admin ghosts will now autoclose
if there's still an atmospherics alarm present.
@@ -4070,7 +4085,31 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- tweak: Added a visible message to forcing airlocks with the Jaws of Life.
davipatury:
- rscadd: Ported Modular Computers from /tg/.
+ - rscadd: Ported Rapid Cable Layer from /vg/.
uraniummeltdown:
- rscadd: EVA has 2 more EVA Suits
- rscdel: Removed Vox-only EVA suits (the grey ones in EVA)
- tweak: Vox can now wear EVA suits
+2017-03-12:
+ Crazylemon64:
+ - bugfix: Kudzu should now be less of (but still) a station-destroying force of
+ nature.
+ - tweak: Bluespace kudzu now only pierces a single layer of walls before losing
+ its "charge".
+ - tweak: Aggressive spread now does not bust rwalls, but does attack obstructing
+ objects in its path.
+ - tweak: Kudzu now only spreads on space turfs when it has specific mutations to
+ do so.
+ - tweak: Kudzu events should be more interesting on their own.
+ Jovaniph:
+ - rscadd: Adds Vulpkanin EVA suit sprite
+ Markolie:
+ - tweak: The system for picking ghosts to inhabit cultist slaughter demons now shows
+ a confirmation prompt like most other role checks.
+ - bugfix: Fixed an issue where you could join as a cultist slaughter demon despite
+ having antagHUD enabled.
+ - bugfix: Fixed an issue where it was possible to weld statues without any fuel.
+ - tweak: It is no longer possible to spam the firelock force message.
+ Twinmold93:
+ - rscadd: Employment record laptop to Head of Personnel's Office. Moves package
+ wrap that was there to meeting room to be paired with the hand labeler there.
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index db8191aed53..e5a33e76de3 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index 0c9090c5b81..9682a110971 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index 0f889055ad0..023222ad451 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/mob/species/vulpkanin/helmet.dmi b/icons/mob/species/vulpkanin/helmet.dmi
index 1fb7f5be545..ce0f9c0e548 100644
Binary files a/icons/mob/species/vulpkanin/helmet.dmi and b/icons/mob/species/vulpkanin/helmet.dmi differ
diff --git a/icons/mob/species/vulpkanin/suit.dmi b/icons/mob/species/vulpkanin/suit.dmi
index ea5e2b4c71e..6245547df30 100644
Binary files a/icons/mob/species/vulpkanin/suit.dmi and b/icons/mob/species/vulpkanin/suit.dmi differ
diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi
index d1aca5822c3..a78a0babdc4 100644
Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ
diff --git a/paradise.dme b/paradise.dme
index c0fe429cc82..258cabc1507 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -807,6 +807,7 @@
#include "code\game\objects\items\weapons\power_cells.dm"
#include "code\game\objects\items\weapons\powerfist.dm"
#include "code\game\objects\items\weapons\RCD.dm"
+#include "code\game\objects\items\weapons\RCL.dm"
#include "code\game\objects\items\weapons\RSF.dm"
#include "code\game\objects\items\weapons\scissors.dm"
#include "code\game\objects\items\weapons\scrolls.dm"
diff --git a/sound/effects/pray_chaplain.ogg b/sound/effects/pray_chaplain.ogg
new file mode 100644
index 00000000000..1b543275311
Binary files /dev/null and b/sound/effects/pray_chaplain.ogg differ