"
+
+ return dat
+
+/datum/arcade_game/space_villain/Topic(href, href_list)
+ if(..())
+ return
+ if (!blocked && !gameover)
+ if (href_list["attack"])
+ action_attack()
+
+ else if (href_list["heal"])
+ action_heal()
+
+ else if (href_list["charge"])
+ action_charge()
+
+ if (href_list["close"])
+ usr.unset_machine()
+ usr << browse(null, "window=arcade")
+
+ else if (href_list["newgame"]) //Reset everything
+ if(is_cheater(usr))
+ return
+
+ temp = "New Round"
+ player_hp = player_max_hp
+ player_mp = player_max_mp
+ enemy_hp = enemy_max_hp
+ enemy_mp = enemy_max_mp
+ gameover = 0
+ turtle = 0
+
+ if(emagged)
+ New()
+ emagged = 0
+
+ holder.add_fingerprint(usr)
+ holder.updateUsrDialog()
+
+
+/datum/arcade_game/space_villain/proc/arcade_action()
+ if ((enemy_mp <= 0) || (enemy_hp <= 0))
+ if(!gameover)
+ gameover = 1
+ temp = "[enemy_name] has fallen! Rejoice!"
+
+ if(emagged)
+ feedback_inc("arcade_win_emagged")
+ new /obj/item/clothing/head/collectable/petehat(holder.loc)
+ new /obj/item/device/maracas/cubanpete(holder.loc)
+ new /obj/item/device/maracas/cubanpete(holder.loc)
+ message_admins("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded explosive maracas.")
+ log_game("[key_name_admin(usr)] has outbombed Cuban Pete and been awarded explosive maracas.")
+ holder.New()
+ emagged = 0
+
+ else if(!holder.contents.len)
+ feedback_inc("arcade_win_normal")
+ var/prizeselect = pickweight(prizes)
+ if(islist(prizeselect))
+ for(var/i in prizeselect)
+ new i(holder.loc)
+ else
+ new prizeselect(holder.loc)
+
+ else //admins can varedit arcades to have special prizes via contents, but it removes the prize rather than spawn a new one
+ feedback_inc("arcade_win_normal")
+ var/atom/movable/prize = pick(holder.contents)
+ prize.forceMove(holder.loc)
+
+ else if (emagged && (turtle >= 4))
+ var/boomamt = rand(5,10)
+ temp = "[enemy_name] throws a bomb, exploding you for [boomamt] damage!"
+ player_hp -= boomamt
+
+ else if ((enemy_mp <= 5) && (prob(70)))
+ var/stealamt = rand(2,3)
+ temp = "[enemy_name] steals [stealamt] of your power!"
+ player_mp -= stealamt
+ holder.updateUsrDialog()
+
+ if (player_mp <= 0)
+ gameover = 1
+ sleep(10)
+ temp = "You have been drained! GAME OVER"
+ if(emagged)
+ feedback_inc("arcade_loss_mana_emagged")
+ usr.gib()
+ else
+ feedback_inc("arcade_loss_mana_normal")
+
+ else if ((enemy_hp <= 10) && (enemy_mp > 4))
+ temp = "[enemy_name] heals for 4 health!"
+ enemy_hp += 4
+ enemy_mp -= 4
+
+ else
+ var/attackamt = rand(3,6)
+ temp = "[enemy_name] attacks for [attackamt] damage!"
+ player_hp -= attackamt
+
+ if ((player_mp <= 0) || (player_hp <= 0))
+ gameover = 1
+ temp = "You have been crushed! GAME OVER"
+ if(emagged)
+ feedback_inc("arcade_loss_hp_emagged")
+ usr.gib()
+ else
+ feedback_inc("arcade_loss_hp_normal")
+
+ blocked = 0
+
+/datum/arcade_game/space_villain/proc/action_charge()
+ blocked = 1
+ var/chargeamt = rand(4,7)
+ temp = "You regain [chargeamt] points"
+ player_mp += chargeamt
+ if(turtle > 0)
+ turtle--
+
+ holder.updateUsrDialog()
+ sleep(10)
+ arcade_action()
+
+/datum/arcade_game/space_villain/proc/action_heal()
+ blocked = 1
+ var/pointamt = rand(1,3)
+ var/healamt = rand(6,8)
+ temp = "You use [pointamt] magic to heal for [healamt] damage!"
+ holder.updateUsrDialog()
+ turtle++
+
+ sleep(10)
+ player_mp -= pointamt
+ player_hp += healamt
+ blocked = 1
+ holder.updateUsrDialog()
+ arcade_action()
+
+/datum/arcade_game/space_villain/proc/action_attack()
+ blocked = 1
+ var/attackamt = rand(2,6)
+ temp = "You attack for [attackamt] damage!"
+ holder.updateUsrDialog()
+ if(turtle > 0)
+ turtle--
+
+ sleep(10)
+ enemy_hp -= attackamt
+ arcade_action()
+
+/datum/arcade_game/space_villain/is_cheater(mob/user)
+ if(emagged && !gameover)
+ if(holder.stat & (NOPOWER|BROKEN))
+ return 0
+ else if(user in cheaters)
+ to_chat(usr, "[enemy_name] throws a bomb at you for trying to cheat him again.")
+ explosion(holder.loc,-1,0,2)//IED sized explosion
+ user.gib()
+ cheaters = null
+ qdel(src)
+ return 1
+ else
+ to_chat(usr, "[enemy_name] isn't one to tolerate cheaters. Don't try that again.")
+ cheaters += user
+ return 1
+ return 0
+
+/datum/arcade_game/space_villain/emag_act(mob/user)
+ if(is_cheater(user))
+ return
+
+ temp = "If you die in the game, you die for real!"
+ player_hp = 30
+ player_mp = 10
+ enemy_hp = 45
+ enemy_mp = 20
+ gameover = 0
+ blocked = 0
+
+ emagged = 1
+
+ enemy_name = "Cuban Pete"
+ name = "Outbomb Cuban Pete"
+
+ holder.updateUsrDialog()
+
+/datum/arcade_game/space_villain/emp_act(var/severity)
+ var/empprize = null
+ var/num_of_prizes = 0
+ switch(severity)
+ if(1)
+ num_of_prizes = rand(1,4)
+ if(2)
+ num_of_prizes = rand(0,2)
+ for(num_of_prizes; num_of_prizes > 0; num_of_prizes--)
+ empprize = pickweight(prizes)
+ new empprize(holder.loc)
+
+/datum/arcade_game/space_villain/kick_act()
+ if(is_cheater(usr))
+ return
+
+ if(!emagged && prob(5)) //Bug
+ temp = "|eW R0vnb##[rand(0,9)]#"
+ player_hp = rand(1,30)
+ player_mp = rand(1,10)
+ enemy_hp = rand(1,60)
+ enemy_mp = rand(1,40)
+ gameover = 0
+ turtle = 0
+
+/datum/arcade_game/space_villain/npc_tamper_act(mob/living/L)
+ switch(rand(0,2))
+ if(0)
+ action_attack()
+ if(1)
+ action_heal()
+ if(2)
+ action_charge()
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 727403b22f4..85409b8ce7b 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -383,9 +383,9 @@
if(do_after(user, src, 10) && state == 0)
if(!src || !WT.isOn())
return
- playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
user.visible_message("[user] welds the frame back into metal.", "You weld the frame back into metal.", "You hear welding.")
- drop_stack(/obj/item/stack/sheet/metal/, loc, 5, user)
+ drop_stack(sheet_type, loc, 5, user)
state = -1
qdel(src)
return 1
@@ -399,7 +399,7 @@
if(!user.drop_item(B, src))
return
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("[user] places \the [B] inside the frame.", "You place \the [B] inside the frame.", "You hear metallic sounds.")
src.icon_state = "1"
src.circuit = P
@@ -407,13 +407,13 @@
to_chat(user, "This frame does not accept circuit boards of this type!")
return 1
if(isscrewdriver(P) && circuit)
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
user.visible_message("[user] screws the circuit board into place.", "You screw the circuit board into place.", "You hear metallic sounds.")
src.state = 2
src.icon_state = "2"
return 1
if(iscrowbar(P) && circuit)
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
user.visible_message("[user] removes the circuit board.", "You remove the circuit board", "You hear metallic sounds.")
src.state = 1
src.icon_state = "0"
@@ -422,7 +422,7 @@
return 1
if(2)
if(isscrewdriver(P) && circuit)
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
user.visible_message("[user] unfastens the circuit board.", "You unfasten the circuit board.", "You hear metallic sounds.")
src.state = 1
src.icon_state = "1"
@@ -433,7 +433,7 @@
to_chat(user, "You need at least 5 lengths of cable coil for this!")
return 1
to_chat(user, "You begin to install wires into the frame.")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if (do_after(user, src, 20) && state == 2 && C.amount >= 5)
C.use(5)
user.visible_message("[user] installs wires into the frame.", "You install wires into the frame.", "You hear metallic sounds.")
@@ -443,7 +443,7 @@
return 1
if(3)
if(iswirecutter(P))
- playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
user.visible_message("[user] unplugs the wires from the frame.", "You unplug the wires from the frame.", "You hear metallic sounds.")
src.state = 2
src.icon_state = "2"
@@ -457,7 +457,7 @@
return 1
to_chat(user, "You start installing the glass panel onto the frame.")
if(do_after(user, src, 20) && state == 3 && G.amount >= 2)
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
G.use(2)
user.visible_message("[user] installs the glass panel onto the frame.", "You install the glass panel onto the frame.", "You hear metallic sounds.")
src.state = 4
@@ -466,14 +466,17 @@
return 1
if(4)
if(iscrowbar(P))
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
user.visible_message("[user] removes the glass panel from the frame.", "You remove the glass panel from the frame.", "You hear metallic sounds.")
src.state = 3
src.icon_state = "3"
new /obj/item/stack/sheet/glass/glass( src.loc, 2 )
return 1
if(isscrewdriver(P))
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
+ if(!circuit.build_path) // the board has been soldered away!
+ to_chat(user, "You connect the monitor, but nothing turns on!")
+ return
to_chat(user, "You connect the monitor.")
var/B = new src.circuit.build_path ( src.loc )
if(circuit.powernet)
@@ -492,6 +495,9 @@
var/obj/machinery/computer/arcade/arcade = B
var/obj/item/weapon/circuitboard/arcade/C = circuit
arcade.import_game_data(C)
+ var/obj/machinery/MA = B
+ if(istype(MA))
+ MA.power_change()
qdel(src)
return 1
return 0
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 545a79f3a7a..12f673b3c91 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -144,9 +144,9 @@ var/global/list/tv_monitors = list()
/obj/machinery/computer/security/engineering
name = "Engineering Cameras"
- desc = "Used to monitor fires and breaches."
+ desc = "Used to monitor engineering silicons and alarms."
icon_state = "engineeringcameras"
- network = list(CAMERANET_POWERALARMS,CAMERANET_ATMOSALARMS,CAMERANET_FIREALARMS)
+ network = list(CAMERANET_ENGI,CAMERANET_POWERALARMS,CAMERANET_ATMOSALARMS,CAMERANET_FIREALARMS)
circuit = "/obj/item/weapon/circuitboard/security/engineering"
light_color = LIGHT_COLOR_YELLOW
diff --git a/code/game/machinery/computer/cargo.dm b/code/game/machinery/computer/cargo.dm
index a13d22acf04..8c61451c533 100644
--- a/code/game/machinery/computer/cargo.dm
+++ b/code/game/machinery/computer/cargo.dm
@@ -15,6 +15,9 @@ For vending packs, see vending_packs.dm*/
return 0
acc_info["idname"] = usr_id.registered_name
acc_info["idrank"] = usr_id.GetJobName()
+ else if(isAI(user))
+ acc_info["idname"] = user.real_name
+ acc_info["idrank"] = "AI"
else if(issilicon(user))
acc_info["idname"] = user.real_name
acc_info["idrank"] = "Cyborg"
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index ad8937023c5..f98ed88bec3 100644
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -5,7 +5,12 @@
#define COMM_SCREEN_SECLEVEL 4
#define COMM_SCREEN_ERT 5
+#define UNAUTH 0
+#define AUTH_HEAD 1
+#define AUTH_CAPT 2
+
var/shuttle_call/shuttle_calls[0]
+var/global/ports_open = TRUE
#define SHUTTLE_RECALL -1
#define SHUTTLE_CALL 1
@@ -41,7 +46,7 @@ var/shuttle_call/shuttle_calls[0]
req_access = list(access_heads)
circuit = "/obj/item/weapon/circuitboard/communications"
var/prints_intercept = 1
- var/authenticated = 0
+ var/authenticated = UNAUTH //1 = normal login, 2 = emagged or had access_captain, 0 = logged out. Gremlins can set to 1 or 0.
var/list/messagetitle = list()
var/list/messagetext = list()
var/currmsg = 0
@@ -90,11 +95,11 @@ var/shuttle_call/shuttle_calls[0]
emag(usr)
if (I && istype(I))
if(src.check_access(I))
- authenticated = 1
- if(20 in I.access)
- authenticated = 2
+ authenticated = AUTH_HEAD
+ if(access_captain in I.access)
+ authenticated = AUTH_CAPT
if("logout")
- authenticated = 0
+ authenticated = UNAUTH
setMenuState(usr,COMM_SCREEN_MAIN)
// ALART LAVUL
if("changeseclevel")
@@ -109,8 +114,8 @@ var/shuttle_call/shuttle_calls[0]
if (istype(I, /obj/item/device/pda))
var/obj/item/device/pda/pda = I
I = pda.id
- if (I && istype(I))
- if(access_heads in I.access) //Let heads change the alert level.
+ if (isAdminGhost(usr) || (I && istype(I)))
+ if(isAdminGhost(usr) || (access_heads in I.access)) //Let heads change the alert level.
var/old_level = security_level
if(!tmp_alertlevel)
tmp_alertlevel = SEC_LEVEL_GREEN
@@ -138,7 +143,7 @@ var/shuttle_call/shuttle_calls[0]
to_chat(usr, "You need to swipe your ID.")
if("announce")
- if(src.authenticated==2 && !issilicon(usr))
+ if(authenticated==AUTH_CAPT && !issilicon(usr))
if(message_cooldown)
return
var/input = stripped_input(usr, "Please choose a message to announce to the station crew.", "What?")
@@ -153,14 +158,6 @@ var/shuttle_call/shuttle_calls[0]
message_cooldown = 0
if("emergency_screen")
- var/mob/M = usr
- var/obj/item/weapon/card/id/I = M.get_active_hand()
- if (istype(I, /obj/item/device/pda))
- var/obj/item/device/pda/pda = I
- I = pda.id
- //if (I && istype(I))
- // if(access_captain in I.access)
- // authenticated = 2
if(!authenticated)
to_chat(usr, "You do not have clearance to use this function.")
return
@@ -188,13 +185,6 @@ var/shuttle_call/shuttle_calls[0]
to_chat(usr, "Central Command has already dispatched a Response Team to [station_name()]")
return
- //if(world.time < 6000)
- // to_chat(usr, "The emergency response team is away on another mission, Please wait another [round((6000-world.time)/600)] minute\s before trying again.")
- // return
-
- //if(emergency_shuttle.online)
- // to_chat(usr, "The emergency shuttle is already on its way.")
- // return
if(!(get_security_level() in list("red", "delta")))
to_chat(usr, "The station must be in an emergency to request a Response Team.")
return
@@ -220,8 +210,8 @@ var/shuttle_call/shuttle_calls[0]
return
if("callshuttle")
- if(src.authenticated)
- if(!map.linked_to_centcomm)
+ if(authenticated || isAdminGhost(usr))
+ if(!map.linked_to_centcomm && !isAdminGhost(usr)) //We don't need a connection if we're an admin
to_chat(usr, "Error: No connection can be made to central command.")
return
var/justification = stripped_input(usr, "Please input a concise justification for the shuttle call. Note that failure to properly justify a shuttle call may lead to recall or termination.", "Nanotrasen Anti-Comdom Systems")
@@ -234,12 +224,12 @@ var/shuttle_call/shuttle_calls[0]
post_status("shuttle")
setMenuState(usr,COMM_SCREEN_MAIN)
if("cancelshuttle")
- if(!map.linked_to_centcomm)
+ if(!map.linked_to_centcomm && !isAdminGhost(usr))
to_chat(usr, "Error: No connection can be made to central command.")
return
if(issilicon(usr))
return
- if(src.authenticated)
+ if(authenticated || isAdminGhost(usr))
var/response = alert("Are you sure you wish to recall the shuttle?", "Confirm", "Yes", "No")
if(response == "Yes")
recall_shuttle(usr)
@@ -293,7 +283,7 @@ var/shuttle_call/shuttle_calls[0]
// OMG CENTCOMM LETTERHEAD
if("MessageCentcomm")
- if(src.authenticated==2)
+ if(authenticated==AUTH_CAPT)
if(!map.linked_to_centcomm)
to_chat(usr, "Error: No connection can be made to central command.")
return
@@ -315,7 +305,7 @@ var/shuttle_call/shuttle_calls[0]
// OMG SYNDICATE ...LETTERHEAD
if("MessageSyndicate")
- if((src.authenticated==2) && (src.emagged))
+ if(src.authenticated==AUTH_CAPT && emagged)
if(!map.linked_to_centcomm)
to_chat(usr, "Error: No connection can be made to \[ABNORMAL ROUTING CORDINATES\] .")
return
@@ -340,6 +330,42 @@ var/shuttle_call/shuttle_calls[0]
setMenuState(usr,COMM_SCREEN_MAIN)
update_icon()
+ if("SetPortRestriction")
+ if(issilicon(usr))
+ return
+ var/mob/M = usr
+ var/obj/item/weapon/card/id/I = M.get_id_card()
+ if (I || isAdminGhost(usr))
+ if(isAdminGhost(usr) || (access_hos in I.access) || (access_heads in I.access && security_level >= SEC_LEVEL_RED))
+ if(ports_open)
+ var/reason = stripped_input(usr, "Please input a concise justification for port closure. This reason will be transmitted to the trader shuttle.", "Nanotrasen Anti-Comdom Systems") as null|text
+ if(!reason || !(usr in view(1,src)))
+ return
+ log_game("[key_name(usr)] closed the port to traders for [reason].")
+ message_admins("[key_name_admin(usr)] closed the port to traders for [reason].")
+ if(trade_shuttle.current_port.areaname == "NanoTrasen Station")
+ var/obj/machinery/computer/shuttle_control/C = trade_shuttle.control_consoles[1] //There should be exactly one
+ if(C)
+ trade_shuttle.travel_to(pick(trade_shuttle.docking_ports - trade_shuttle.current_port),C) //Just send it; this has all relevant checks
+ trade_shuttle.remove_dock(/obj/docking_port/destination/trade/station)
+ trade_shuttle.notify_port_toggled(reason)
+ ports_open = FALSE
+ return
+ if(!ports_open)
+ var/response = alert(usr,"Are you sure you wish to open the station to traders?", "Port Opening", "Yes", "No")
+ if(response != "Yes")
+ return
+ log_game("[key_name(usr)] opened the port to traders.")
+ message_admins("[key_name_admin(usr)] opened the port to traders.")
+ trade_shuttle.add_dock(/obj/docking_port/destination/trade/station)
+ trade_shuttle.notify_port_toggled()
+ ports_open = TRUE
+ return
+ else
+ to_chat(usr, "This action requires either a red alert or head of security authorization.")
+ else
+ to_chat(usr, "You must wear an ID for this function.")
+
return 1
/obj/machinery/computer/communications/attack_ai(var/mob/user as mob)
@@ -363,7 +389,7 @@ var/shuttle_call/shuttle_calls[0]
/obj/machinery/computer/communications/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open=NANOUI_FOCUS)
- if(user.stat)
+ if(user.stat && !isAdminGhost(user))
return
// this is the data which will be sent to the ui
@@ -371,7 +397,7 @@ var/shuttle_call/shuttle_calls[0]
data["is_ai"] = issilicon(user)
data["menu_state"] = data["is_ai"] ? ai_menu_state : menu_state
data["emagged"] = emagged
- data["authenticated"] = authenticated
+ data["authenticated"] = (isAdminGhost(user) ? AUTH_CAPT : authenticated)
data["screen"] = getMenuState(usr)
data["stat_display"] = list(
@@ -439,7 +465,7 @@ var/shuttle_call/shuttle_calls[0]
to_chat(user, "Syndicate routing data uploaded!")
new/obj/effect/effect/sparks(get_turf(src))
playsound(loc,"sparks",50,1)
- authenticated = 2
+ authenticated = AUTH_CAPT
setMenuState(usr,COMM_SCREEN_MAIN)
update_icon()
return 1
@@ -609,11 +635,11 @@ var/shuttle_call/shuttle_calls[0]
/obj/machinery/computer/communications/npc_tamper_act(mob/living/user)
if(!authenticated)
if(prob(20)) //20% chance to log in
- authenticated = TRUE
+ authenticated = AUTH_HEAD
else //Already logged in
if(prob(50)) //50% chance to log off
- authenticated = FALSE
+ authenticated = UNAUTH
else if(isgremlin(user)) //make a hilarious public message
var/mob/living/simple_animal/hostile/gremlin/G = user
var/result = G.generate_markov_chain()
@@ -626,15 +652,15 @@ var/shuttle_call/shuttle_calls[0]
/obj/machinery/computer/communications/Destroy()
for(var/obj/machinery/computer/communications/commconsole in machines)
- if(istype(commconsole.loc,/turf) && commconsole != src)
+ if(istype(commconsole.loc,/turf) && commconsole != src && commconsole.z != map.zCentcomm)
return ..()
for(var/obj/item/weapon/circuitboard/communications/commboard in world)
- if(istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage))
+ if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) && commboard.z != map.zCentcomm)
return ..()
for(var/mob/living/silicon/ai/shuttlecaller in player_list)
- if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf))
+ if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf) && shuttlecaller.z != map.zCentcomm)
return ..()
if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction")
@@ -651,15 +677,15 @@ var/shuttle_call/shuttle_calls[0]
/obj/item/weapon/circuitboard/communications/Destroy()
for(var/obj/machinery/computer/communications/commconsole in machines)
- if(istype(commconsole.loc,/turf))
+ if(istype(commconsole.loc,/turf) && commconsole.z != map.zCentcomm)
return ..()
for(var/obj/item/weapon/circuitboard/communications/commboard in world)
- if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) && commboard != src)
+ if((istype(commboard.loc,/turf) || istype(commboard.loc,/obj/item/weapon/storage)) && commboard != src && commboard.z != map.zCentcomm)
return ..()
for(var/mob/living/silicon/ai/shuttlecaller in player_list)
- if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf))
+ if(!shuttlecaller.stat && shuttlecaller.client && istype(shuttlecaller.loc,/turf) && shuttlecaller.z != map.zCentcomm)
return ..()
if(ticker.mode.name == "revolution" || ticker.mode.name == "AI malfunction")
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index f852308c58d..36255bf6e73 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -98,7 +98,7 @@
/obj/machinery/computer/togglePanelOpen(var/obj/toggleitem, mob/user, var/obj/item/weapon/circuitboard/CC = null)
if(!circuit) //we can't disassemble with no circuit, so add some fucking circuits if you want disassembly
return
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
user.visible_message( "[user] begins to unscrew \the [src]'s monitor.",
"You begin to unscrew the monitor...")
if (do_after(user, src, 20) && (circuit || CC))
diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm
index 0bf77eaebf7..9406b35c2b2 100644
--- a/code/game/machinery/computer/law.dm
+++ b/code/game/machinery/computer/law.dm
@@ -57,10 +57,12 @@
proc/announce_law_changes(var/mob/user)
to_chat(current, "These are your laws now:")
current.show_laws()
+ current << sound('sound/machines/lawsync.ogg')
for(var/mob/living/silicon/robot/R in mob_list)
if(R.lawupdate && (R.connected_ai == current))
to_chat(R, "These are your laws now:")
R.show_laws()
+ R << sound('sound/machines/lawsync.ogg')
to_chat(user, "Upload complete. The AI's laws have been modified.")
attackby(obj/item/weapon/O as obj, mob/user as mob)
@@ -142,6 +144,7 @@
proc/announce_law_changes()
to_chat(current, "These are your laws now:")
current.show_laws()
+ current << sound('sound/machines/lawsync.ogg')
to_chat(usr, "Upload complete. The robot's laws have been modified.")
proc/install_module(var/obj/item/weapon/aiModule/M,var/mob/user)
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index 10187a5af50..1dd002c1596 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -427,7 +427,7 @@
var/counter = 1
while(src.active2.fields[text("com_[]", counter)])
counter++
- src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")] [t1]")
+ src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text(give_seconds = TRUE)], [game_year] [t1]")
if (href_list["del_c"])
if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index 7e2c4b9b3c9..65b32c6bf40 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -164,14 +164,9 @@
var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm")
if(R && istype(R))
- if(R.mind && R.mind.special_role && R.emagged)
- to_chat(R, "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered.")
- R.ResetSecurityCodes()
-
- else
+ if(R.self_destruct())
message_admins("[key_name_admin(usr)] detonated [R.name]!")
log_game("[key_name_admin(usr)] detonated [R.name]!")
- R.self_destruct()
else
to_chat(usr, "Access Denied.")
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index ce6c4949603..9e8389b93bb 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -363,7 +363,7 @@ What a mess.*/
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
- active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], 2053 []", authenticated, rank, time2text(world.realtime, "DDD MMM DD hh:mm:ss"), t1)
+ active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], [] []", authenticated, rank, "[time2text(world.realtime, "DDD MMM DD")] [worldtime2text(give_seconds = TRUE)]", game_year, t1)
if ("Delete Record (ALL)")
if (active1)
diff --git a/code/game/machinery/computer/slot_machine.dm b/code/game/machinery/computer/slot_machine.dm
index 4ef7b53d271..7e749448ccb 100644
--- a/code/game/machinery/computer/slot_machine.dm
+++ b/code/game/machinery/computer/slot_machine.dm
@@ -169,21 +169,21 @@
add_overlays()
var/sound/sound_to_play = pick('sound/effects/xylophone1.ogg','sound/effects/xylophone2.ogg','sound/effects/xylophone3.ogg')
- playsound(get_turf(src),sound(sound_to_play),30,-4)
+ playsound(src,sound(sound_to_play),30,-4)
var/sleep_time = 48
sleep(sleep_time/3)
update_overlay_icon_state(overlay_1,"[value_1]")
- playsound(get_turf(src),'sound/machines/chime.ogg',50,-4)
+ playsound(src,'sound/machines/chime.ogg',50,-4)
sleep(sleep_time/3)
update_overlay_icon_state(overlay_2,"[value_2]")
- playsound(get_turf(src),'sound/machines/chime.ogg',50,-4)
+ playsound(src,'sound/machines/chime.ogg',50,-4)
sleep(sleep_time/3)
update_overlay_icon_state(overlay_3,"[value_3]")
- playsound(get_turf(src),'sound/machines/chime.ogg',50,-4)
+ playsound(src,'sound/machines/chime.ogg',50,-4)
check_victory(user)
@@ -244,7 +244,7 @@
spawn(10)
if(our_money_account.charge(win_value,null,"Victory","one-armed bandit #[id]"))
dispense_cash(win_value, get_turf(src))
- playsound(get_turf(src), "polaroid", 50, 1)
+ playsound(src, "polaroid", 50, 1)
to_chat(user, "You win $[win_value]!")
else
diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm
index 75f42335de2..298862af56e 100644
--- a/code/game/machinery/computer/station_alert.dm
+++ b/code/game/machinery/computer/station_alert.dm
@@ -15,9 +15,7 @@
/obj/machinery/computer/station_alert/New()
..()
if(src.z != map.zMainStation)
- var/area/A = src.areaMaster
- if(!A)
- A = get_area(src)
+ var/area/A = get_area(src)
if(!A)
return
name = "[A.general_area_name] Alert Computer"
diff --git a/code/game/machinery/computer/store.dm b/code/game/machinery/computer/store.dm
index 36bfaa9034e..6c3f13e9e48 100644
--- a/code/game/machinery/computer/store.dm
+++ b/code/game/machinery/computer/store.dm
@@ -40,7 +40,7 @@
/obj/machinery/computer/merch/New()
..()
- if(time2text(world.realtime, "MM/DD") == "02/14")
+ if(Holiday == VALENTINES_DAY)
var/valentines = list("Valentine's Day" = list(/datum/storeitem/valentinechocolatebar,),)
categories += valentines
diff --git a/code/game/machinery/computer/vox_shuttle.dm b/code/game/machinery/computer/vox_shuttle.dm
index be35d95ac23..f8c11e44655 100644
--- a/code/game/machinery/computer/vox_shuttle.dm
+++ b/code/game/machinery/computer/vox_shuttle.dm
@@ -22,21 +22,21 @@ var/global/vox_shuttle_location
return
var/area/dest_location = locate(destination)
-
- if(areaMaster == dest_location)
+ var/area/this_area = get_area(src)
+ if(this_area == dest_location)
return
moving = TRUE
lastMove = world.time
- if(areaMaster.z != dest_location.z)
+ if(this_area.z != dest_location.z)
var/area/transit_location = locate(/area/vox_station/transit)
- areaMaster.move_contents_to(transit_location)
- areaMaster = transit_location // let do this while move_contents_to proc is not using Move()
+ this_area.move_contents_to(transit_location)
+ this_area = transit_location // let do this while move_contents_to proc is not using Move()
sleep(VOX_SHUTTLE_MOVE_TIME)
- areaMaster.move_contents_to(dest_location)
- areaMaster = dest_location
+ this_area.move_contents_to(dest_location)
+ this_area = dest_location
moving = FALSE
return 1
@@ -58,9 +58,9 @@ var/global/vox_shuttle_location
return
user.set_machine(src)
-
+ var/area/this_area = get_area(src)
var/dat = {"
- Location: [areaMaster]
+ Location: [this_area]
Ready to move[max(lastMove + VOX_SHUTTLE_COOLDOWN - world.time, 0) ? " in [max(round((lastMove + VOX_SHUTTLE_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"] Return to dark space Fore port solar |
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index fedb724d75c..80aa9db6ab3 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -17,6 +17,7 @@
var/list/req_component_names = null
var/list/components_in_use = null
var/build_state = 1
+ var/build_path = 0 //0 = Default path. 1 = Glass Frame
// For pods
var/list/connected_parts = list()
@@ -49,12 +50,58 @@
if(P.crit_fail)
to_chat(user, "This part is faulty, you cannot add this to the machine!")
return
+
+ if (build_path == 1)
+ var/obj/item/weapon/circuitboard/airlock/C = circuit
+ switch(build_state)
+ if(1)
+ if(iscrowbar(P))
+ build_path = 0
+ new /obj/item/stack/sheet/glass/glass(get_turf(src))
+ icon_state = "box_0"
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
+ if(istype(P, /obj/item/weapon/circuitboard/airlock) && P:icon_state != "door_electronics_smoked")
+ if (!C)
+ if(user.drop_item(P, src))
+ build_state++
+ C = P
+ circuit = C
+ C.installed = 1
+ icon_state="box_glass_circuit"
+ if (iswelder(P))
+ to_chat(user, "You use the machine frame as a vice and shape the glass with the welder into a fish bowl.")
+ getFromPool(/obj/item/stack/sheet/metal, get_turf(src), 5)
+ new /obj/machinery/fishtank/bowl(get_turf(src))
+ qdel(src)
+ return
+ if (2)
+ if(iscrowbar(P))
+ if (C != null)
+ C.forceMove(get_turf(src))
+ C.installed = 0
+ C = null
+ circuit = null
+ build_state--
+ icon_state = "box_glass"
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
+ if(isscrewdriver(P) && C)
+ var/obj/structure/displaycase/new_display_case = new(get_turf(src))
+ new_display_case.circuit = C
+ C.forceMove(new_display_case)
+ circuit = null
+ C = null
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
+ qdel(src)
+ return
+ return
+
+
switch(build_state)
if(1)
if(istype(P, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = P
if(C.amount >= 5)
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You start to add cables to the frame.")
if(do_after(user, src, 20))
if(C && C.amount >= 5) // Check again
@@ -64,19 +111,18 @@
else if(istype(P, /obj/item/stack/sheet/glass/glass))
var/obj/item/stack/sheet/glass/glass/G=P
if(G.amount<1)
- to_chat(user, "How...?")
return
G.use(1)
to_chat(user, "You add the glass to the frame.")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
- new /obj/structure/displaycase_frame(src.loc)
- qdel(src)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
+ build_path = 1
+ icon_state="box_glass"
return
else
if(iswrench(P))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 75, 1)
to_chat(user, "You dismantle the frame.")
- drop_stack(/obj/item/stack/sheet/metal, get_turf(src), 5, user)
+ drop_stack(sheet_type, get_turf(src), 5, user)
qdel(src)
if(2)
if(!..())
@@ -87,7 +133,7 @@
user << "You can't let go of \the [B]!"
return
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You add the circuit board to the frame.")
circuit = P
set_build_state(3)
@@ -111,7 +157,7 @@
to_chat(user, "This frame does not accept circuit boards of this type!")
else
if(iswirecutter(P))
- playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
to_chat(user, "You remove the cables.")
set_build_state(1)
var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( src.loc )
@@ -120,7 +166,7 @@
if(3)
if(!..())
if(iscrowbar(P))
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
set_build_state(2)
circuit.forceMove(src.loc)
circuit = null
@@ -141,7 +187,7 @@
component_check = 0
break
if(component_check)
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
var/obj/machinery/new_machine = new src.circuit.build_path(src.loc)
for(var/obj/O in new_machine.component_parts)
returnToPool(O)
@@ -157,6 +203,7 @@
else
circuit.forceMove(null)
new_machine.RefreshParts()
+ new_machine.power_change()
circuit.finish_building(new_machine, user)
components = null
qdel(src)
@@ -189,7 +236,7 @@
if(istype(P, /obj/item/weapon) || istype(P, /obj/item/stack))
for(var/I in req_components)
if(istype(P, text2path(I)) && (req_components[I] > 0))
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(istype(P, /obj/item/stack))
var/obj/item/stack/CP = P
if(CP.amount >= req_components[I])
@@ -209,6 +256,8 @@
components += P
req_components[I]--
update_desc()
+ if(P.is_open_container())
+ . = 1
break
to_chat(user, desc)
@@ -241,7 +290,20 @@ to destroy them and players will be able to make replacements.
icon = 'icons/obj/module.dmi'
icon_state = "blank_mod"
//var/datum/circuits/local_fuses = null
- var/list/allowed_boards = list("autolathe"=/obj/item/weapon/circuitboard/autolathe,"intercom"=/obj/item/weapon/intercom_electronics,"air alarm"=/obj/item/weapon/circuitboard/air_alarm,"fire alarm"=/obj/item/weapon/circuitboard/fire_alarm,"airlock"=/obj/item/weapon/circuitboard/airlock,"APC"=/obj/item/weapon/circuitboard/power_control,"vendomat"=/obj/item/weapon/circuitboard/vendomat,"microwave"=/obj/item/weapon/circuitboard/microwave,"station map"=/obj/item/weapon/circuitboard/station_map,"cell charger"=/obj/item/weapon/circuitboard/cell_charger,"fishtank filter"=/obj/item/weapon/circuitboard/fishtank,"large fishtank filter"=/obj/item/weapon/circuitboard/fishwall)
+ var/list/allowed_boards = list(
+ "autolathe"=/obj/item/weapon/circuitboard/autolathe,
+ "intercom"=/obj/item/weapon/intercom_electronics,
+ "air alarm"=/obj/item/weapon/circuitboard/air_alarm,
+ "fire alarm"=/obj/item/weapon/circuitboard/fire_alarm,
+ "airlock"=/obj/item/weapon/circuitboard/airlock,
+ "APC"=/obj/item/weapon/circuitboard/power_control,
+ "vendomat"=/obj/item/weapon/circuitboard/vendomat,
+ "microwave"=/obj/item/weapon/circuitboard/microwave,
+ "station map"=/obj/item/weapon/circuitboard/station_map,
+ "cell charger"=/obj/item/weapon/circuitboard/cell_charger,
+ "recharger"=/obj/item/weapon/circuitboard/recharger,
+ "fishtank filter"=/obj/item/weapon/circuitboard/fishtank,
+ "large fishtank filter"=/obj/item/weapon/circuitboard/fishwall)
var/soldering = 0 //Busy check
/obj/item/weapon/circuitboard/blank/New()
@@ -426,8 +488,8 @@ obj/item/weapon/circuitboard/rdserver
/obj/item/weapon/circuitboard/smes
name = "Circuit Board (SMES)"
- desc = "A circuit board used to run a gas freezer."
- build_path = "/obj/machinery/power/battery/smes"
+ desc = "A circuit board used to run a giant battery."
+ build_path = "/obj/machinery/power/battery/smes/pristine"
board_type = MACHINE
origin_tech = Tc_POWERSTORAGE + "=4;" + Tc_ENGINEERING + "=4;" + Tc_PROGRAMMING + "=4"
req_components = list(
@@ -914,6 +976,16 @@ obj/item/weapon/circuitboard/rdserver
// Telecomms circuit boards:
+/obj/item/weapon/circuitboard/pda_multicaster
+ name = "Circuit Board (PDA multicaster)"
+ desc = "A circuit board used to run a machine that resends messages."
+ build_path = "/obj/machinery/pda_multicaster"
+ board_type = MACHINE
+ origin_tech = Tc_PROGRAMMING + "=4;" + Tc_ENGINEERING + "=3;" + Tc_BLUESPACE + "=2"
+ req_components = list(
+ "/obj/item/weapon/stock_parts/subspace/filter" = 1,
+ "/obj/item/weapon/stock_parts/manipulator" = 1)
+
/obj/item/weapon/circuitboard/telecomms/receiver
name = "Circuit Board (telecommunications subspace receiver)"
desc = "A circuit board used to run a machine that receives subspace transmissions in telecommunications systems."
@@ -1146,6 +1218,16 @@ obj/item/weapon/circuitboard/rdserver
"/obj/item/weapon/stock_parts/scanning_module" = 1,
"/obj/item/weapon/stock_parts/capacitor" = 2)
+/obj/item/weapon/circuitboard/recharger
+ name = "Circuit Board (Recharger)"
+ desc = "A circuit board used to run a machine that replenishes energy weapon charge"
+ board_type = MACHINE
+ build_path = "/obj/machinery/recharger"
+ origin_tech = Tc_POWERSTORAGE + "=2;" + Tc_COMBAT + "=2"
+ req_components = list(
+ "/obj/item/weapon/stock_parts/scanning_module" = 1,
+ "/obj/item/weapon/stock_parts/capacitor" = 2)
+
/obj/item/weapon/circuitboard/washing_machine
name = "Circuit Board (Washing Machine)"
desc = "A circuit board used to run a machine that cleans clothing and kills pets."
@@ -1287,6 +1369,7 @@ obj/item/weapon/circuitboard/rdserver
"/obj/item/weapon/stock_parts/scanning_module" = 1,
"/obj/item/weapon/stock_parts/micro_laser" = 1)
+
/*
* Fishtanks
*/
@@ -1306,4 +1389,12 @@ obj/item/weapon/circuitboard/rdserver
board_type = MACHINE
origin_tech = Tc_PROGRAMMING + "=1"
req_components = list (
- "/obj/item/stack/sheet/glass/glass" = 10)
\ No newline at end of file
+ "/obj/item/stack/sheet/glass/glass" = 10)
+
+/obj/item/weapon/circuitboard/conduction_plate
+ name = "Circuit Board (Conduction Plate)"
+ build_path = "/obj/machinery/power/conduction_plate"
+ board_type = MACHINE
+ origin_tech = Tc_PROGRAMMING + "=1;" + Tc_ENGINEERING + "=4"
+ req_components = list(
+ "/obj/item/weapon/stock_parts/capacitor" = 1)
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index 790975afc68..d4b70fdffee 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -21,7 +21,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
var/on = 0
var/ejecting = 0
var/temperature_archived
- var/mob/living/carbon/occupant = null
+ var/mob/living/occupant = null
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/current_heat_capacity = 50
@@ -73,7 +73,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
..()
/obj/machinery/atmospherics/unary/cryo_cell/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
- if(!ismob(O)) //humans only
+ if(!ismob(O))
return
if(O.loc == user) //no you can't pull things out of your ass
return
@@ -81,7 +81,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
return
if(O.anchored || get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.contents.Find(src)) // is the mob anchored, too far away from you, or are you too far away from the source
return
- if(istype(O, /mob/living/simple_animal) || istype(O, /mob/living/silicon)) //animals and robutts dont fit
+ if(issilicon(O)) //robutts dont fit
return
if(!ishigherbeing(user) && !isrobot(user)) //No ghosts or mice putting people into the sleeper
return
@@ -97,7 +97,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
return
if(isrobot(user))
var/mob/living/silicon/robot/robit = usr
- if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical))
+ if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL)))
to_chat(user, "You do not have the means to do this!")
return
var/mob/living/L = O
@@ -129,7 +129,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
return
if(isrobot(usr))
var/mob/living/silicon/robot/robit = usr
- if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical))
+ if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL)))
to_chat(usr, "You do not have the means to do this!")
return
if(!istype(over_location) || over_location.density)
@@ -533,7 +533,7 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
boot_contents(exit, regulatetemp = 0) //No temperature regulation cycle required
else
ejecting = 1
- playsound(get_turf(src), 'sound/machines/pressurehiss.ogg', 40, 1)
+ playsound(src, 'sound/machines/pressurehiss.ogg', 40, 1)
modify_occupant_bodytemp() //Start to heat them up a little bit immediately
nanomanager.update_uis(src)
spawn(4 SECONDS)
@@ -562,10 +562,13 @@ var/global/list/cryo_health_indicator = list( "full" = image("icon" = 'icons/obj
nanomanager.update_uis(src)
-/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/carbon/M as mob)
+/obj/machinery/atmospherics/unary/cryo_cell/proc/put_mob(mob/living/M as mob)
if (!istype(M))
to_chat(usr, "The cryo cell cannot handle such a lifeform!")
return
+ if(M.size > SIZE_NORMAL)
+ to_chat(usr, "\The [src] cannot fit such a large lifeform!")
+ return
if (occupant)
to_chat(usr, "The cryo cell is already occupied!")
return
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 999dde4b8f3..d5bec23c45e 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -37,10 +37,11 @@
to_chat(user, "It seems to be malfunctioning.")
/obj/machinery/deployable/barrier/attackby(var/obj/item/weapon/W, var/mob/user)
- if (isID(W) || isPDA(W))
- if (!allowed(user))
- to_chat(user, "Access denied.")
- return
+ if(isID(W) || isPDA(W) || isRoboID(W))
+ if(!isrobot(user))
+ if(!allowed(user))
+ to_chat(user, "Access denied.")
+ return
anchored = !anchored
update_icon()
if (anchored)
diff --git a/code/game/machinery/door_control.dm b/code/game/machinery/door_control.dm
index d516fb1760b..d93a6dd72f4 100644
--- a/code/game/machinery/door_control.dm
+++ b/code/game/machinery/door_control.dm
@@ -48,7 +48,7 @@
/obj/machinery/door_control/emag(mob/user)
req_access = list()
req_one_access = list()
- playsound(get_turf(src), "sparks", 100, 1)
+ playsound(src, "sparks", 100, 1)
/obj/machinery/door_control/attackby(obj/item/weapon/W, mob/user as mob)
..()
@@ -147,7 +147,7 @@
return
if(iswrench(W))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
if(do_after(user, src, 30))
to_chat(user, "You detach \the [src] from the wall.")
new/obj/item/mounted/frame/driver_button(get_turf(src))
@@ -203,3 +203,18 @@
icon_state = "launcherbtt"
active = 0
+
+/obj/machinery/door_control/mapped/interogation_room
+ name = "smartglass control"
+ desc = "Toogle smartglass"
+ id_tag = "InterogationRoomIDTag"
+
+
+/obj/machinery/door_control/mapped/interogation_room/attack_hand(var/mob/user)
+ ..() // Sanity
+ for (var/obj/structure/window/reinforced/plasma/interogation_room/W in range(range))
+ if (W.smartwindow && src.id_tag == W.smartwindow.id_tag)
+ W.smartwindow.toggle_smart_transparency()
+ for (var/obj/machinery/door/window/plasma/secure/interogation_room/W in range(range))
+ if (W.smartwindow && src.id_tag == W.smartwindow.id_tag)
+ W.smartwindow.toggle_smart_transparency()
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 0a492dfce5b..c1d78d1f327 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -455,7 +455,7 @@ About the new airlock wires panel:
// shock user with probability prb (if all connections & power are working)
// returns 1 if shocked, 0 otherwise
// The preceding comment was borrowed from the grille's shock script
-/obj/machinery/door/airlock/shock(mob/user, prb)
+/obj/machinery/door/airlock/shock(mob/user, prb, var/siemenspassed = 1)
if((stat & (NOPOWER)) || !src.arePowerSystemsOn()) // unpowered, no shock
return 0
if(hasShocked)
@@ -463,7 +463,7 @@ About the new airlock wires panel:
if(!prob(prb))
return 0 //you lucked out, no shock for you
spark(src, 5)
- if(electrocute_mob(user, get_area(src), src))
+ if(electrocute_mob(user, get_area(src), src, siemenspassed))
hasShocked = 1
spawn(10)
hasShocked = 0
@@ -1042,7 +1042,7 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/togglePanelOpen(var/obj/toggleitem, mob/user)
if(!operating)
panel_open = !panel_open
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, 1, -6)
+ playsound(src, 'sound/items/Screwdriver.ogg', 25, 1, -6)
update_icon()
return 1
return
@@ -1054,7 +1054,7 @@ About the new airlock wires panel:
if (!istype(user, /mob/living/silicon))
if (isElectrified())
// TODO: analyze the called proc
- if (shock(user, 75))
+ if (shock(user, 75, I.siemens_coefficient))
user.delayNextAttack(10)
return
@@ -1064,15 +1064,15 @@ About the new airlock wires panel:
if(welded)
breaktime += 30 //Welding buys you a little time
src.visible_message("[user] is battering down [src]!", "You begin to batter [src].")
- playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1)
+ playsound(src, 'sound/effects/shieldbash.ogg', 50, 1)
if(do_after(user,src, breaktime))
//Calculate bolts separtely, in case they dropped in the last 6-9 seconds.
if(src.locked == 1)
- playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1)
+ playsound(src, 'sound/effects/shieldbash.ogg', 50, 1)
src.visible_message("[user] is battering the bolts!", "You begin to smash the bolts...")
if(!do_after(user, src,190)) //Same amount as drilling an R-wall, longer if it was welded
return //If they moved, cancel us out
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
src.visible_message("[user] broke down the door!", "You broke the door!")
bashed_in(user)
return
@@ -1155,7 +1155,7 @@ About the new airlock wires panel:
return
/obj/machinery/door/airlock/proc/bashed_in(var/mob/user)
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
operating = -1
var/obj/structure/door_assembly/DA = revert(user,user.dir)
DA.anchored = 0
@@ -1215,7 +1215,7 @@ About the new airlock wires panel:
if( !arePowerSystemsOn() || (stat & NOPOWER) || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
return 0
use_power(50)
- playsound(get_turf(src), soundeffect, pitch, 1)
+ playsound(src, soundeffect, pitch, 1)
if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density)
src.closeOther.close()
// This worries me - N3X
@@ -1245,7 +1245,7 @@ About the new airlock wires panel:
return
if (locate(/mob/living) in T)
- playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0)
+ playsound(src, 'sound/machines/buzz-two.ogg', 50, 0)
if(autoclose && normalspeed)
spawn(150)
autoclose()
@@ -1277,7 +1277,7 @@ About the new airlock wires panel:
if (istype(loc, /turf/simulated))
T.add_blood(L)
- playsound(get_turf(src),soundeffect, 30, 1)
+ playsound(src,soundeffect, 30, 1)
for(var/turf/T in loc)
var/obj/structure/window/W = locate(/obj/structure/window) in T
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 5376f7296ca..5d04f45ac9f 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -124,46 +124,20 @@ var/list/all_doors = list()
var/mob/living/carbon/human/H = user
if (H.getBrainLoss() >= BRAINLOSS_FOR_HEADBUTT)
- // TODO: analyze the called proc
- playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1)
-
+ playsound(src, 'sound/effects/bang.ogg', 25, 1)
+ H.visible_message("[user] headbutts the airlock.")
if (!istype(H.head, /obj/item/clothing/head/helmet))
- visible_message("[user] headbutts the airlock.")
H.Stun(8)
H.Knockdown(5)
var/datum/organ/external/O = H.get_organ(LIMB_HEAD)
-
- // TODO: analyze the called proc
- if(O.take_damage(10, 0))
- H.UpdateDamageIcon()
- O = null
- else
- // TODO: fix sentence
- visible_message("[user] headbutts the airlock. Good thing they're wearing a helmet.")
-
- H = null
+ O.take_damage(10, 0)
return
- H = null
-
- add_fingerprint(user)
- attackby(null, user)
-
-
-/obj/machinery/door/attackby(obj/item/I as obj, mob/user as mob)
- if(..())
- return 1
-
- if (istype(I, /obj/item/device/detective_scanner))
- return
if(isobserver(user) && !isAdminGhost(user))
return
- // borgs can't attack doors open
- // because it conflicts with their AI-like interaction with them
- if (isrobot(user))
- return
+ add_fingerprint(user)
if (!requiresID())
user = null
@@ -179,6 +153,25 @@ var/list/all_doors = list()
denied()
+/obj/machinery/door/attackby(obj/item/I, mob/user)
+ if(..())
+ return
+
+ if(istype(I, /obj/item/device/detective_scanner))
+ return //It does its own thing on attack
+
+ if (allowed(user))
+ if (!density)
+ return close()
+ else
+ return open()
+
+
+ if(horror_force(user))
+ return
+
+ denied()
+
/obj/machinery/door/proc/horror_force(var/mob/living/carbon/human/H) //H is for HORROR, BABY!
if(!ishorrorform(H))
return FALSE
@@ -228,7 +221,7 @@ var/list/all_doors = list()
operating = 1
if(makes_noise)
- playsound(get_turf(src), soundeffect, soundpitch, 1)
+ playsound(src, soundeffect, soundpitch, 1)
set_opacity(0)
door_animate("opening")
@@ -260,7 +253,7 @@ var/list/all_doors = list()
layer = closed_layer
if (makes_noise)
- playsound(get_turf(src), soundeffect, soundpitch, 1)
+ playsound(src, soundeffect, soundpitch, 1)
setDensity(TRUE)
door_animate("closing")
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 065c41f05cc..c2382ae704f 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -1,5 +1,5 @@
-/var/const/OPEN = 1
-/var/const/CLOSED = 2
+/var/const/FD_OPEN = 1
+/var/const/FD_CLOSED = 2
var/global/list/alert_overlays_global = list()
@@ -204,7 +204,7 @@ var/global/list/alert_overlays_global = list()
if(isobserver(user) || user.stat)
return
spawn()
- var/area/A = get_area_master(src)
+ var/area/A = get_area(src)
ASSERT(istype(A)) // This worries me.
var/alarmed = A.doors_down || A.fire
var/old_density = src.density
@@ -240,11 +240,10 @@ var/global/list/alert_overlays_global = list()
force_open(user, C)
return
- if(istype(C, /obj/item/weapon/wrench/socket))
+ if(istype(C, /obj/item/weapon/wrench))
if(blocked)
user.visible_message("\The [user] starts to deconstruct \the [src] with \a [C].",\
- "You begin to deconstruct \the [src] with \the [C].",\
- "You hear a racket from a ratchet.")
+ "You begin to deconstruct \the [src] with \the [C].")
if(do_after(user, src, 5 SECONDS))
new/obj/item/firedoor_frame(get_turf(src))
qdel(src)
@@ -270,7 +269,7 @@ var/global/list/alert_overlays_global = list()
to_chat(user, "\The [src] is welded solid!")
return
- var/area/A = get_area_master(src)
+ var/area/A = get_area(src)
ASSERT(istype(A)) // This worries me.
var/alarmed = A.doors_down || A.fire
@@ -336,7 +335,7 @@ var/global/list/alert_overlays_global = list()
..()
latetoggle()
layer = open_layer
- var/area/A = get_area_master(src)
+ var/area/A = get_area(src)
ASSERT(istype(A)) // This worries me.
var/alarmed = A.doors_down || A.fire
if(alarmed)
@@ -344,7 +343,7 @@ var/global/list/alert_overlays_global = list()
close()
/obj/machinery/door/firedoor/proc/force_open(mob/user, var/obj/C) //used in mecha/equipment/tools/tools.dm
- var/area/A = get_area_master(src)
+ var/area/A = get_area(src)
ASSERT(istype(A)) // This worries me.
var/alarmed = A.doors_down || A.fire
@@ -468,10 +467,10 @@ var/global/list/alert_overlays_global = list()
return
switch(nextstate)
- if(OPEN)
+ if(FD_OPEN)
nextstate = null
open()
- if(CLOSED)
+ if(FD_CLOSED)
nextstate = null
close()
@@ -540,6 +539,25 @@ var/global/list/alert_overlays_global = list()
if(!user.IsAdvancedToolUser())
to_chat(user, "You don't have the dexterity to do this!")
return 0
+
+ if(!user.is_holding_item(src))
+ return 1
+ var/current_turf = get_turf(src)
+ var/turf_face = get_step(current_turf,user.dir)
+ if(SSair.air_blocked(current_turf, turf_face))
+ to_chat(user, "That way is blocked already.")
+ return 1
+ var/obj/machinery/door/firedoor/border_only/F = locate(/obj/machinery/door/firedoor) in get_turf(user)
+ if(F && F.dir == user.dir)
+ to_chat(user, "There is already a firedoor facing that direction.")
+ return 1
+ if(do_after(user, src, 5 SECONDS))
+ var/obj/machinery/door/firedoor/border_only/B = new(get_turf(src))
+ B.change_dir(user.dir)
+ qdel(src)
+
+//Removed pending a fix for atmos issues caused by full tile firelocks.
+/*
switch(alert("firedoor construction", "Would you like to construct a full tile firedoor or one direction?", "One Direction", "Full Firedoor", "Cancel", null))
if("One Direction")
if(!user.is_holding_item(src))
@@ -565,4 +583,5 @@ var/global/list/alert_overlays_global = list()
return 1
if(do_after(user, src, 5 SECONDS))
new /obj/machinery/door/firedoor(get_turf(src))
- qdel(src)
\ No newline at end of file
+ qdel(src)
+*/
diff --git a/code/game/machinery/doors/mineral.dm b/code/game/machinery/doors/mineral.dm
index 4fe57644123..7416fe5fc7d 100644
--- a/code/game/machinery/doors/mineral.dm
+++ b/code/game/machinery/doors/mineral.dm
@@ -64,11 +64,11 @@
return open()
/obj/machinery/door/mineral/open()
- playsound(get_turf(src), soundeffect, 100, 1)
+ playsound(src, soundeffect, 100, 1)
return ..()
/obj/machinery/door/mineral/close()
- playsound(get_turf(src), soundeffect, 100, 1)
+ playsound(src, soundeffect, 100, 1)
return ..()
/obj/machinery/door/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob)
@@ -224,6 +224,11 @@
add_fingerprint(user)
SwitchState()
+/obj/machinery/door/mineral/resin/bullet_act(var/obj/item/projectile/Proj)
+ if(Proj.damage_type == BRUTE || Proj.damage_type == BURN)
+ hardness -= Proj.damage/100
+ CheckHardness()
+
/obj/machinery/door/mineral/resin/open()
..()
spawn(close_delay)
@@ -235,7 +240,7 @@
return
/obj/machinery/door/mineral/resin/CheckHardness()
- playsound(get_turf(src), soundeffect, 100, 1)
+ playsound(src, soundeffect, 100, 1)
return ..()
/obj/machinery/door/mineral/resin/acidable()
diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm
index c5a254d32dc..c5c033b2256 100644
--- a/code/game/machinery/doors/poddoor.dm
+++ b/code/game/machinery/doors/poddoor.dm
@@ -74,6 +74,9 @@ var/list/poddoors = list()
return
return
+/obj/machinery/door/poddoor/allowed(mob/M)
+ return 0
+
/obj/machinery/door/poddoor/open()
if (src.operating == 1) //doors can still open when emag-disabled
return
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 8f3e906a163..7ee5e93266c 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -129,9 +129,9 @@
return 0
if(!operating) //in case of emag
operating = 1
- flick(text("[]opening", base_state), src)
- playsound(get_turf(src), soundeffect, 100, 1)
- icon_state = text("[]open", base_state)
+ door_animate("opening")
+ playsound(src, soundeffect, 100, 1)
+ icon_state = "[base_state]open"
sleep(animation_delay)
explosion_resistance = 0
@@ -148,8 +148,8 @@
if (operating)
return 0
operating = 1
- flick(text("[]closing", base_state), src)
- playsound(get_turf(src), soundeffect, 100, 1)
+ door_animate("closing")
+ playsound(src, soundeffect, 100, 1)
icon_state = base_state
setDensity(TRUE)
@@ -188,7 +188,7 @@
tforce = 40
else
tforce = AM:throwforce
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 100, 1)
take_damage(tforce)
/obj/machinery/door/window/attack_ai(mob/user as mob)
@@ -201,17 +201,12 @@
return
user.delayNextAttack(8)
user.do_attack_animation(src, user)
- health = max(0, health - 25)
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message("\The [user] smashes against \the [name].", 1)
- if (health <= 0)
- getFromPool(shard, loc)
- getFromPool(/obj/item/stack/cable_coil, loc, 2)
- qdel(src)
+ take_damage(25)
else
return attack_hand(user)
-
/obj/machinery/door/window/attack_animal(mob/living/user as mob)
if(operating)
return
@@ -220,23 +215,15 @@
return
user.do_attack_animation(src, user)
user.delayNextAttack(8)
- health = max(0, health - M.melee_damage_upper)
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message("\The [M] [M.attacktext] against \the [name].", 1)
- if (health <= 0)
- getFromPool(shard, loc)
- getFromPool(/obj/item/stack/cable_coil, loc, 2)
- qdel(src)
-
-
-/obj/machinery/door/window/attack_hand(mob/user as mob)
- return attackby(user, user)
+ take_damage(M.melee_damage_upper)
/obj/machinery/door/window/attackby(obj/item/weapon/I as obj, mob/living/user as mob)
// Make emagged/open doors able to be deconstructed
if (!density && operating != 1 && iscrowbar(I))
user.visible_message("[user] removes the electronics from the windoor assembly.", "You start to remove the electronics from the windoor assembly.")
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 1)
if (do_after(user, src, 40) && src && !density && operating != 1)
to_chat(user, "You removed the windoor electronics!")
make_assembly(user)
@@ -276,14 +263,10 @@
var/aforce = I.force
user.do_attack_animation(src, I)
user.delayNextAttack(8)
- if(I.damtype == BRUTE || I.damtype == BURN)
- health = max(0, health - aforce)
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
visible_message("[src] was hit by [I].")
- if (health <= 0)
- getFromPool(shard, loc)
- getFromPool(/obj/item/stack/cable_coil, loc, 2)
- qdel(src)
+ if(I.damtype == BRUTE || I.damtype == BURN)
+ take_damage(aforce)
return
add_fingerprint(user)
@@ -291,15 +274,6 @@
//don't care who they are or what they have, act as if they're NOTHING
user = null
- if (isrobot(user))
- if (density)
- return open()
- else
- return close()
-
- if (!allowed(user) && density)
- flick(text("[]deny", base_state), src)
-
return ..()
/obj/machinery/door/window/emag(mob/user)
@@ -307,13 +281,16 @@
var/used_emag = (/obj/item/weapon/card/emag in user.contents) //TODO: Find a better way of checking this
return hackOpen(used_emag, user)
+/obj/machinery/door/window/door_animate(var/animation)
+ flick("[base_state][animation]", src)
+
/obj/machinery/door/window/proc/hackOpen(obj/item/I, mob/user)
operating = -1
if (electronics)
electronics.icon_state = "door_electronics_smoked"
- flick("[base_state]spark", src)
+ door_animate("spark")
sleep(6)
open()
return 1
@@ -415,3 +392,8 @@
WA.secure = "secure_"
WA.update_icon()
return WA
+
+// Used on Packed ; smartglassified roundstart
+/obj/machinery/door/window/plasma/secure/interogation_room/initialize()
+ smartwindow = new(src)
+ smartwindow.id_tag = "InterogationRoomIDTag"
diff --git a/code/game/machinery/embedded_controller/embedded_controller_base.dm b/code/game/machinery/embedded_controller/embedded_controller_base.dm
index 568bc662f3d..10b0de03b46 100644
--- a/code/game/machinery/embedded_controller/embedded_controller_base.dm
+++ b/code/game/machinery/embedded_controller/embedded_controller_base.dm
@@ -41,7 +41,7 @@
to_chat(usr, "You begin removing screws from \the [src] backplate...")
if(do_after(user, src, 50))
to_chat(usr, "You unscrew \the [src] from the wall.")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
new /obj/item/mounted/frame/airlock_controller(get_turf(src))
qdel(src)
return 1
@@ -55,7 +55,7 @@
if(user.drop_item(C, src))
to_chat(usr, "You secure \the [C]!")
_circuitboard=C
- playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
+ playsound(src, 'sound/effects/pop.ogg', 50, 0)
build++
update_icon()
return 1
@@ -63,7 +63,7 @@
if(iscrowbar(W))
to_chat(usr, "You begin to pry out \the [W] into \the [src].")
if(do_after(user, src, 10))
- playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
+ playsound(src, 'sound/effects/pop.ogg', 50, 0)
build--
update_icon()
var/obj/item/weapon/circuitboard/C
@@ -80,7 +80,7 @@
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C=W
to_chat(user, "You start adding cables to \the [src]...")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src, 20) && C.amount >= 10)
C.use(5)
build++
@@ -101,7 +101,7 @@
return 1
if(isscrewdriver(W))
to_chat(user, "You begin to complete \the [src]...")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, src, 20))
if(!_circuitboard)
_circuitboard=new boardtype(src)
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index c6f46e162ac..1466f5ed431 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -77,7 +77,7 @@ var/list/obj/machinery/flasher/flashers = list()
if ((src.disable) || (src.last_flash && world.time < src.last_flash + 150))
return
- playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1)
+ playsound(src, 'sound/weapons/flash.ogg', 100, 1)
src.last_flash = world.time
use_power(1000)
if(harm_labeled >= min_harm_label)
diff --git a/code/game/machinery/holosign.dm b/code/game/machinery/holosign.dm
index e99130173d8..b8420d2c1c2 100644
--- a/code/game/machinery/holosign.dm
+++ b/code/game/machinery/holosign.dm
@@ -61,8 +61,8 @@ var/list/obj/machinery/holosign/holosigns = list()
/obj/machinery/holosign_switch/attack_ai(mob/user as mob)
src.add_hiddenprint(user)
return src.attack_hand(user)
-/
-obj/machinery/holosign_switch/attack_paw(mob/user as mob)
+
+/obj/machinery/holosign_switch/attack_paw(mob/user as mob)
return src.attack_hand(user)
/obj/machinery/holosign_switch/attackby(obj/item/weapon/W, mob/user as mob)
diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm
index e69d0fd8bbd..90fd82d4a83 100755
--- a/code/game/machinery/igniter.dm
+++ b/code/game/machinery/igniter.dm
@@ -66,7 +66,7 @@ var/global/list/igniters = list()
if(istype(W, /obj/item/weapon/weldingtool) && src.assembly)
var/obj/item/weapon/weldingtool/WT = W
if (WT.remove_fuel(0,user))
- playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder2.ogg', 50, 1)
to_chat(user, "You begin to cut \the [src] off the floor...")
if (do_after(user, src, 40))
user.visible_message( \
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index 91dad72aae9..d85a5fadd26 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -72,7 +72,7 @@
if(user.stat)
return
if(iswrench(W))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,get_turf(src))
M.amount = 2
if(src.beaker)
@@ -139,7 +139,7 @@
return
if(!T.dna)
return
- if(M_NOCLONE in T.mutations)
+ if(M_HUSK in T.mutations)
return
// If the human is losing too much blood, beep.
diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm
index 57eb5102325..b3a8b5b3fbd 100644
--- a/code/game/machinery/kitchen/gibber.dm
+++ b/code/game/machinery/kitchen/gibber.dm
@@ -207,8 +207,12 @@ obj/machinery/gibber/New()
var/obj/item/weapon/reagent_containers/food/snacks/meat/allmeat[totalslabs]
for (var/i=1 to totalslabs)
- var/obj/item/weapon/reagent_containers/food/snacks/meat/newmeat = new occupant.meat_type(null, occupant)
- newmeat.reagents.add_reagent (NUTRIMENT, sourcenutriment / totalslabs) // Thehehe. Fat guys go first
+ var/obj/item/weapon/newmeat
+ if(istype(occupant.meat_type, /obj/item/weapon/reagent_containers))
+ newmeat = new occupant.meat_type(null, occupant)
+ newmeat.reagents.add_reagent (NUTRIMENT, sourcenutriment / totalslabs) // Thehehe. Fat guys go first
+ else
+ newmeat = new occupant.meat_type()
if(src.occupant.reagents)
src.occupant.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the
@@ -323,7 +327,7 @@ obj/machinery/gibber/New()
else
victim.ghostize(0)
qdel(victim)
- playsound(get_turf(src), 'sound/effects/gib2.ogg', 50, 1)
+ playsound(src, 'sound/effects/gib2.ogg', 50, 1)
for (var/i=1 to totalslabs)
var/obj/item/meatslab = allmeat[i]
var/turf/Tx = locate(src.x - i, src.y, src.z)
diff --git a/code/game/machinery/kitchen/juicer.dm b/code/game/machinery/kitchen/juicer.dm
index 7f5f2e7961f..11e671cdb65 100644
--- a/code/game/machinery/kitchen/juicer.dm
+++ b/code/game/machinery/kitchen/juicer.dm
@@ -148,7 +148,7 @@
return
if (!beaker || beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
return
- playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1)
+ playsound(src, 'sound/machines/juicer.ogg', 50, 1)
for (var/obj/item/weapon/reagent_containers/food/snacks/O in src.contents)
var/r_id = get_juice_id(O)
beaker.reagents.add_reagent(r_id,get_juice_amount(O))
diff --git a/code/game/machinery/kitchen/microwave.dm b/code/game/machinery/kitchen/microwave.dm
index bde112469d2..5f27e75c05b 100644
--- a/code/game/machinery/kitchen/microwave.dm
+++ b/code/game/machinery/kitchen/microwave.dm
@@ -199,7 +199,7 @@
/obj/machinery/microwave/attack_ai(mob/user as mob)
if(istype(user,/mob/living/silicon/robot))
var/mob/living/silicon/robot/R = user
- if(istype(R.module, /obj/item/weapon/robot_module/butler))
+ if(R.module && (R.module.quirk_flags & MODULE_CAN_HANDLE_FOOD))
user.set_machine(src)
interact(user)
return 1
@@ -244,6 +244,17 @@
display_name = "Turnovers"
items_measures[display_name] = "turnover"
items_measures_p[display_name] = "turnovers"
+ if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/soybeans))
+ items_measures[display_name] = "soybean"
+ items_measures_p[display_name] = "soybeans"
+ if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/grapes))
+ display_name = "Grapes"
+ items_measures[display_name] = "bunch of grapes"
+ items_measures_p[display_name] = "bunches of grapes"
+ if (istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes))
+ display_name = "Green Grapes"
+ items_measures[display_name] = "bunch of green grapes"
+ items_measures_p[display_name] = "bunches of green grapes"
items_counts[display_name]++
for (var/O in items_counts)
var/N = items_counts[O]
@@ -379,7 +390,7 @@
src.updateUsrDialog()
/obj/machinery/microwave/proc/stop()
- playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1)
+ playsound(src, 'sound/machines/ding.ogg', 50, 1)
src.operating = 0 // Turn it off again aferwards
src.icon_state = "mw"
src.updateUsrDialog()
@@ -398,11 +409,11 @@
src.updateUsrDialog()
/obj/machinery/microwave/proc/muck_start()
- playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1) // Play a splat sound
+ playsound(src, 'sound/effects/splat.ogg', 50, 1) // Play a splat sound
src.icon_state = "mwbloody1" // Make it look dirty!!
/obj/machinery/microwave/proc/muck_finish()
- playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1)
+ playsound(src, 'sound/machines/ding.ogg', 50, 1)
src.visible_message("The microwave gets covered in muck!")
src.dirty = 100 // Make it dirty so it can't be used util cleaned
src.flags &= ~OPENCONTAINER //So you can't add condiments
diff --git a/code/game/machinery/kitchen/monkeyrecycler.dm b/code/game/machinery/kitchen/monkeyrecycler.dm
index 0af8010b6df..a7208c87fd7 100644
--- a/code/game/machinery/kitchen/monkeyrecycler.dm
+++ b/code/game/machinery/kitchen/monkeyrecycler.dm
@@ -59,7 +59,7 @@
qdel(target)
target = null
to_chat(user, "You stuff the monkey in the machine.")
- playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1)
+ playsound(src, 'sound/machines/juicer.ogg', 50, 1)
use_power(500)
src.grinded++
to_chat(user, "The machine now has [grinded] monkeys worth of material stored.")
@@ -76,7 +76,7 @@
else
qdel(target)
to_chat(user, "You stuff the monkey in the machine.")
- playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1)
+ playsound(src, 'sound/machines/juicer.ogg', 50, 1)
use_power(500)
src.grinded++
to_chat(user, "The machine now has [grinded] monkeys worth of material stored.")
@@ -87,7 +87,7 @@
return 1
if(grinded >= minimum_monkeys)
to_chat(user, "The machine hisses loudly as it condenses the grinded monkey meat. After a moment, it dispenses a brand new monkey cube.")
- playsound(get_turf(src), 'sound/machines/hiss.ogg', 50, 1)
+ playsound(src, 'sound/machines/hiss.ogg', 50, 1)
grinded -= minimum_monkeys
new /obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped(src.loc)
to_chat(user, "The machine's display flashes that it has [grinded] monkeys worth of material left.")
diff --git a/code/game/machinery/kitchen/processor.dm b/code/game/machinery/kitchen/processor.dm
index b0764957418..d0385cdc582 100644
--- a/code/game/machinery/kitchen/processor.dm
+++ b/code/game/machinery/kitchen/processor.dm
@@ -236,7 +236,7 @@
user.visible_message("[user] turns on [src].", \
"You turn on \a [src].", \
"You hear [src] start")
- playsound(get_turf(src), 'sound/machines/blender.ogg', 50, 1)
+ playsound(src, 'sound/machines/blender.ogg', 50, 1)
use_power(500)
sleep(P.time*time_coeff)
P.process(src.loc, O)
diff --git a/code/game/machinery/kitchen/smartfridge.dm b/code/game/machinery/kitchen/smartfridge.dm
index a0ffc30e1e0..22205466a6b 100644
--- a/code/game/machinery/kitchen/smartfridge.dm
+++ b/code/game/machinery/kitchen/smartfridge.dm
@@ -135,7 +135,9 @@
/obj/item/weapon/reagent_containers/pill)
/obj/machinery/smartfridge/medbay/New()
- . = ..()
+ ..()
+ if(map.nameShort == "deff")
+ icon = 'maps/defficiency/medbay.dmi'
component_parts = newlist(
/obj/item/weapon/circuitboard/smartfridge/medbay,
@@ -160,7 +162,9 @@
/obj/item/weapon/reagent_containers)
/obj/machinery/smartfridge/chemistry/New()
- . = ..()
+ ..()
+ if(map.nameShort == "deff")
+ icon = 'maps/defficiency/medbay.dmi'
component_parts = newlist(
/obj/item/weapon/circuitboard/smartfridge/chemistry,
@@ -237,6 +241,8 @@
/obj/machinery/smartfridge/bloodbank/New()
. = ..()
+ if(map.nameShort == "deff")
+ icon = 'maps/defficiency/medbay.dmi'
component_parts = newlist(
/obj/item/weapon/circuitboard/smartfridge/bloodbank,
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index 9daa37b8c4a..2905612e218 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -8,17 +8,20 @@
anchored = 1.0
var/buildstage = 2
var/on = 0
- // luminosity = 1
- holomap = TRUE
- auto_holomap = TRUE
+/obj/machinery/light_switch/supports_holomap()
+ return TRUE
+
+/obj/machinery/light_switch/initialize()
+ add_self_to_holomap()
/obj/machinery/light_switch/New(var/loc, var/ndir, var/building = 2)
..()
- name = "[areaMaster.name] light switch"
+ var/area/this_area = get_area(src)
+ name = "[this_area.name] light switch"
buildstage = building
if(buildstage)
- on = areaMaster.lightswitch
+ on = this_area.lightswitch
else
pixel_x = (ndir & 3)? 0 : (ndir == 4 ? 28 * PIXEL_MULTIPLIER: -28 * PIXEL_MULTIPLIER)
pixel_y = (ndir & 3)? (ndir ==1 ? 28 * PIXEL_MULTIPLIER: -28 * PIXEL_MULTIPLIER) : 0
@@ -40,16 +43,17 @@
if(2)
if(isscrewdriver(W))
to_chat(user, "You begin unscrewing \the [src].")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, src,10) && buildstage == 2)
to_chat(user, "You unscrew the cover blocking the inner wiring of \the [src].")
buildstage = 1
- on = areaMaster.lightswitch
+ var/area/this_area = get_area(src)
+ on = this_area.lightswitch
return
if(1)
if(isscrewdriver(W))
to_chat(user, "You begin screwing closed \the [src].")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, src,10) && buildstage == 1)
to_chat(user, "You tightly screw closed the cover of \the [src].")
buildstage = 2
@@ -57,7 +61,7 @@
return
if(iswirecutter(W))
to_chat(user, "You begin cutting the wiring from \the [src].")
- playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
if(do_after(user, src,10) && buildstage == 1)
to_chat(user, "You cut the wiring to the lighting power line.")
new /obj/item/stack/cable_coil(get_turf(src),3)
@@ -77,7 +81,7 @@
return
if(iscrowbar(W))
to_chat(user, "You begin prying \the [src] off the wall.")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src,10) && buildstage == 0)
to_chat(user, "You pry the frame off of the wall.")
new /obj/item/mounted/frame/light_switch(get_turf(user))
@@ -101,15 +105,15 @@
if(buildstage != 2)
return
on = !on
+ var/area/this_area = get_area(src)
+ this_area.lightswitch = on
+ this_area.updateicon()
- areaMaster.lightswitch = on
- areaMaster.updateicon()
-
- for(var/obj/machinery/light_switch/L in areaMaster)
+ for(var/obj/machinery/light_switch/L in this_area)
L.on = on
L.updateicon()
- areaMaster.power_change()
+ this_area.power_change()
/obj/machinery/light_switch/power_change()
if(powered(LIGHT))
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index f32751cee00..d261a84b01a 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -475,7 +475,7 @@ Class Procs:
user.visible_message( "[user] begins to pry out the circuitboard from \the [src].",
"You begin to pry out the circuitboard from \the [src]...")
if(do_after(user, src, 40))
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
dropFrame()
spillContents()
user.visible_message( "[user] successfully pries out the circuitboard from \the [src]!",
@@ -524,7 +524,7 @@ Class Procs:
to_chat(user, "You need to secure \the [src] before it can be welded.")
return -1
if (WT.remove_fuel(0,user))
- playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder2.ogg', 50, 1)
user.visible_message("[user.name] starts to [state - 1 ? "unweld": "weld" ] the [src] [state - 1 ? "from" : "to"] the floor.", \
"You start to [state - 1 ? "unweld": "weld" ] the [src] [state - 1 ? "from" : "to"] the floor.", \
"You hear welding.")
@@ -663,13 +663,13 @@ Class Procs:
switch(notice_state)
if("ping")
src.visible_message("[bicon(src)] \The [src] pings.")
- playsound(get_turf(src), 'sound/machines/notify.ogg', 50, 0)
+ playsound(src, 'sound/machines/notify.ogg', 50, 0)
if("beep")
src.visible_message("[bicon(src)] \The [src] beeps.")
- playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0)
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 0)
if("buzz")
src.visible_message("[bicon(src)] \The [src] buzzes.")
- playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 0)
+ playsound(src, 'sound/machines/buzz-two.ogg', 50, 0)
/obj/machinery/proc/check_rebuild()
return
@@ -720,7 +720,7 @@ Class Procs:
if(O.onBuckledUserKick(H, src))
return //don't return 1! we will do the normal "touch" action if so!
- playsound(get_turf(src), 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it
+ playsound(src, 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it
H.visible_message("[H] kicks \the [src].", "You kick \the [src].")
if(prob(70))
diff --git a/code/game/machinery/martian_printer.dm b/code/game/machinery/martian_printer.dm
index 1363ec41ec7..c13eca2651c 100644
--- a/code/game/machinery/martian_printer.dm
+++ b/code/game/machinery/martian_printer.dm
@@ -1,4 +1,4 @@
-/obj/machinery/martian_printer
+/obj/machinery/mob_printer
name = "inset disk"
desc = "A strange disk set into the ground, doesn't seem to be anything beyond decorative."
icon = 'icons/mob/martian.dmi'
@@ -9,48 +9,54 @@
idle_power_usage = 20
active_power_usage = 5000
var/building = 0
+ var/print_path = /mob/living/carbon/complex/martian
-/obj/machinery/martian_printer/attack_ghost(var/mob/dead/observer/O)
+/obj/machinery/mob_printer/attack_ghost(var/mob/dead/observer/O)
if(!canSpawn())
return
if(O.can_reenter_corpse)
- if(alert(O,"Do you want to get your squid on?","Time for some emergency probing","Yes","No")== "Yes")
+ if(alert(O,"Do you want to enter a corporeal form?","Inset Disk","Yes","No")== "Yes")
if(building)
- to_chat(O, "\The [src] is already processing another alien. Try again later.")
+ to_chat(O, "\The [src] is already processing another. Try again later.")
return
else
return
else if(!(O.can_reenter_corpse))
- to_chat(O,"You have recently ghosted and can not enter as a martian right now. Try again later.")
+ to_chat(O,"You have recently ghosted and can not enter right now. Try again later.")
return
- make_martian(O)
+ make_mob(O)
-/obj/machinery/martian_printer/power_change()
+/obj/machinery/mob_printer/power_change()
if (powered())
stat &= ~NOPOWER
else
stat |= NOPOWER
-/obj/machinery/martian_printer/proc/canSpawn()
+/obj/machinery/mob_printer/proc/canSpawn()
+ if(!use_power)
+ return !building //Can be varedited to not need power.
return !(stat & NOPOWER) && !building
-/obj/machinery/martian_printer/proc/make_martian(var/mob/dead/observer/user)
+/obj/machinery/mob_printer/proc/make_mob(var/mob/dead/observer/user)
building = TRUE
if(!user || !istype(user) || !user.client)
// Player has already been made into another mob before this one spawned, so let's reset the spawner
building = FALSE
update_icon()
return FALSE
- flick("m_pad_active", src)
+ if(istype(print_path,/mob/living/carbon/complex/martian))
+ flick("m_pad_active", src) //Martians get a special animation
+ else
+ flick("m_pad_alt", src)
spawn(24)
if(!user || !istype(user) || !user.client)
// Player disappeared between clicking on the spawner and now, so we have no one to turn tentacle!
building = FALSE
return FALSE
- var/mob/living/carbon/martian/M = new(get_turf(src))
+ var/mob/M = new print_path(get_turf(src))
M.ckey = user.ckey
qdel(user)
diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm
index dfda3efae02..06ca3913e14 100644
--- a/code/game/machinery/mass_driver.dm
+++ b/code/game/machinery/mass_driver.dm
@@ -41,7 +41,7 @@ var/list/mass_drivers = list()
if(isscrewdriver(W))
to_chat(user, "You begin to unscrew the bolts off the [src]...")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, src, 30))
var/obj/machinery/mass_driver_frame/F = new(get_turf(src))
F.dir = src.dir
@@ -140,7 +140,7 @@ var/list/mass_drivers = list()
if(!WT.remove_fuel(0, user))
to_chat(user, "The welding tool must be on to complete this task.")
return 1
- playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
to_chat(user, "You begin to cut the frame apart...")
if(do_after(user, src, 30) && (build == 0))
to_chat(user, "You detach the plasteel sheets from each others.")
@@ -152,7 +152,7 @@ var/list/mass_drivers = list()
to_chat(user, "You can't anchor \the [src], as there's a mass driver in that location already.")
return
to_chat(user, "You begin to anchor \the [src] on the floor.")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
if(do_after(user, src, 10) && (build == 0))
to_chat(user, "You anchor \the [src]!")
anchored = 1
@@ -162,7 +162,7 @@ var/list/mass_drivers = list()
if(1) // Fixed to the floor
if(iswrench(W))
to_chat(user, "You begin to de-anchor \the [src] from the floor.")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
if(do_after(user, src, 10) && (build == 1))
build--
update_icon()
@@ -174,7 +174,7 @@ var/list/mass_drivers = list()
if(!WT.remove_fuel(0, user))
to_chat(user, "The welding tool must be on to complete this task.")
return 1
- playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
to_chat(user, "You begin to weld \the [src] to the floor...")
if(do_after(user, src, 40) && (build == 1))
to_chat(user, "You welded \the [src] to the floor.")
@@ -187,7 +187,7 @@ var/list/mass_drivers = list()
if(!WT.remove_fuel(0, user))
to_chat(user, "The welding tool must be on to complete this task.")
return 1
- playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
to_chat(user, "You begin to unweld \the [src] to the floor...")
if(do_after(user, src, 40) && (build == 2))
to_chat(user, "You unwelded \the [src] to the floor.")
@@ -196,7 +196,7 @@ var/list/mass_drivers = list()
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C=W
to_chat(user, "You start adding cables to \the [src]...")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src, 20) && (C.amount >= 3) && (build == 2))
C.use(3)
to_chat(user, "You've added cables to \the [src].")
@@ -207,7 +207,7 @@ var/list/mass_drivers = list()
to_chat(user, "You begin to remove the wiring from \the [src].")
if(do_after(user, src, 10) && (build == 3))
new /obj/item/stack/cable_coil(loc,3)
- playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
to_chat(user, "You've removed the cables from \the [src].")
build--
update_icon()
@@ -215,7 +215,7 @@ var/list/mass_drivers = list()
if(istype(W, /obj/item/stack/rods))
var/obj/item/stack/rods/R=W
to_chat(user, "You begin to complete \the [src]...")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src, 20) && (R.amount >= 3) && (build == 3))
R.use(3)
to_chat(user, "You've added the grille to \the [src].")
@@ -225,7 +225,7 @@ var/list/mass_drivers = list()
if(4) // Grille in place
if(iscrowbar(W))
to_chat(user, "You begin to pry off the grille from \the [src]...")
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
if(do_after(user, src, 30) && (build == 4))
new /obj/item/stack/rods(loc,2)
build--
@@ -233,7 +233,7 @@ var/list/mass_drivers = list()
return 1
if(isscrewdriver(W))
to_chat(user, "You finalize the Mass Driver...")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
var/obj/machinery/mass_driver/M = new(get_turf(src))
M.dir = src.dir
qdel(src)
diff --git a/code/game/machinery/metaldetector.dm b/code/game/machinery/metaldetector.dm
index c1b295ccbb0..6ec63bd5a8b 100644
--- a/code/game/machinery/metaldetector.dm
+++ b/code/game/machinery/metaldetector.dm
@@ -236,7 +236,7 @@
flick("[base_state]_flash", src)
- playsound(get_turf(src), sndstr, 100, 1)
+ playsound(src, sndstr, 100, 1)
/obj/machinery/detector/proc/check_for_weapons(var/obj/item/slot_item) //Unused anywhere, copypasted in secbot.dm
diff --git a/code/game/machinery/mommi_spawner.dm b/code/game/machinery/mommi_spawner.dm
index 3c484356460..29fffa6a897 100644
--- a/code/game/machinery/mommi_spawner.dm
+++ b/code/game/machinery/mommi_spawner.dm
@@ -3,9 +3,9 @@
desc = "A large pad sunk into the ground."
icon = 'icons/obj/robotics.dmi'
icon_state = "mommispawner-idle"
- density = 1
- anchored = 1
- var/building=0
+ density = TRUE
+ anchored = TRUE
+ var/building=FALSE
var/metal=0
var/const/metalPerMoMMI=10
var/const/metalPerTick=1
@@ -14,15 +14,10 @@
active_power_usage = 5000
var/recharge_time=600 // 60s
var/locked_to_zlevel = 0 // Whether to lock the spawned MoMMIs to the z-level
+ var/dorf = FALSE
/obj/machinery/mommi_spawner/dorf
- machine_flags = WRENCHMOVE
- desc = "A large pad mounted to the ground with large bolts."
-
-/obj/machinery/mommi_spawner/dorf/attack_ghost(var/mob/dead/observer/user)
- if(stat & NOPOWER|BROKEN)
- return
- ..()
+ dorf = TRUE
/obj/machinery/mommi_spawner/power_change()
if (powered())
@@ -142,12 +137,20 @@
// Make the MoMMI!
var/turf/T = get_turf(src)
+ var/mob/living/silicon/robot/mommi/M = null
+
+ if(dorf)
+ M = new /mob/living/silicon/robot/mommi/nt(T)
+ M.laws = new /datum/ai_laws/dorf
+ M.keeper = FALSE
+ else
+ M = new /mob/living/silicon/robot/mommi/soviet(T)
- var/mob/living/silicon/robot/mommi/M = new /mob/living/silicon/robot/mommi(T)
if(!M)
return
M.invisibility = 0
+
if (locked_to_zlevel)
M.add_ion_law("You belong to the station where you were created; do not leave it.")
M.locked_to_z = T.z
diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm
index 89fd8dd734a..c6935bf128b 100644
--- a/code/game/machinery/newscaster.dm
+++ b/code/game/machinery/newscaster.dm
@@ -31,7 +31,7 @@
//var/parent_channel
var/backup_body =""
var/backup_author =""
- var/is_admin_message = 0
+ var/is_admin_message = FALSE
var/icon/img = null
var/icon/backup_img
@@ -40,30 +40,28 @@
/datum/feed_channel
var/channel_name=""
var/list/datum/feed_message/messages = list()
- //var/message_count = 0
- var/locked=0
- var/author=""
- var/backup_author=""
- var/censored=0
- var/is_admin_channel=0
- //var/page = null //For newspapers
+ var/locked = FALSE
+ var/author = ""
+ var/backup_author = ""
+ var/censored = FALSE
+ var/is_admin_channel = FALSE
/datum/feed_message/proc/clear()
- src.author = ""
- src.body = ""
- src.backup_body = ""
- src.backup_author = ""
- src.img = null
- src.backup_img = null
+ author = ""
+ body = ""
+ backup_body = ""
+ backup_author = ""
+ img = null
+ backup_img = null
/datum/feed_channel/proc/clear()
- src.channel_name = ""
- src.messages = list()
- src.locked = 0
- src.author = ""
- src.backup_author = ""
- src.censored = 0
- src.is_admin_channel = 0
+ channel_name = ""
+ messages = list()
+ locked = 0
+ author = ""
+ backup_author = ""
+ censored = 0
+ is_admin_channel = 0
/datum/feed_network
var/list/datum/feed_channel/network_channels = list()
@@ -80,17 +78,11 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
icon = 'icons/obj/terminals.dmi'
icon_state = "newscaster_normal"
var/buildstage = 1 // 1 = complete, 0 = unscrewed
+ ghost_write = 1 // Allow ghosts to send Topic()s.
+ custom_aghost_alerts = 1 // We handle our own logging.
- // Allow ghosts to send Topic()s.
- ghost_write = 1
- custom_aghost_alerts=1 // We handle our own logging.
-
- //var/isbroken = 0 //1 if someone banged it with something heavy
- //var/ispowered = 1 //starts powered, changes with power_change()
- //OBSOLETE: the stat var already has BROKEN and NOPOWER flags, let's use these instead.
- //var/list/datum/feed_channel/channel_list = list() //This list will contain the names of the feed channels. Each name will refer to a data region where the messages of the feed channels are stored.
- //OBSOLETE: We're now using a global news network
- var/screen = 0 //Or maybe I'll make it into a list within a list afterwards... whichever I prefer, go fuck yourselves :3
+ var/screen = 0
+ //Or maybe I'll make it into a list within a list afterwards... whichever I prefer, go fuck yourselves :3
// 0 = welcome screen - main menu
// 1 = view feed channels
// 2 = create feed channel
@@ -103,35 +95,33 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
// 9 = viewing channel feeds
// 10 = censor feed story
// 11 = censor feed channel
- //Holy shit this is outdated, made this when I was still starting newscasters :3
- var/paper_remaining = 15 // There is no point to setting it to 0 here if you're setting it to 15 in New() ?????????
- var/securityCaster = 0
- // 0 = Caster cannot be used to issue wanted posters
- // 1 = the opposite
+
+ var/paper_remaining = 15
+ var/securityCaster = FALSE
+ // FALSE = Caster cannot be used to issue wanted posters
+ // TRUE = the opposite
+
var/unit_no = 0 //Each newscaster has a unit number
- //var/datum/feed_message/wanted //We're gonna use a feed_message to store data of the wanted person because fields are similar
- //var/wanted_issue = 0 //OBSOLETE
- // 0 = there's no WANTED issued, we don't need a special icon_state
- // 1 = Guess what.
var/alert_delay = 500
- var/alert = 0
- // 0 = there hasn't been a news/wanted update in the last alert_delay
- // 1 = there has
+ var/alert = FALSE
+ // FALSE = there hasn't been a news/wanted update in the last alert_delay
+ // TRUE = there has
+
var/scanned_user = "Unknown" //Will contain the name of the person who currently uses the newscaster
var/mob/masterController = null // Mob with control over the newscaster.
- var/msg = ""; //Feed message
+ var/msg = ""; //Feed message
var/photo = null
var/channel_name = ""; //the feed channel which will be receiving the feed, or being created
- var/c_locked=0; //Will our new channel be locked to public submissions?
- var/hitstaken = 0 //Death at 3 hits from an item with force>=15
+ var/c_locked = FALSE; //Will our new channel be locked to public submissions?
+ var/hitstaken = 0 //Death at 3 hits from an item with force>=15
var/datum/feed_channel/viewing_channel = list()
luminosity = 0
- anchored = 1
+ anchored = TRUE
-/obj/machinery/newscaster/security_unit //Security unit
+/obj/machinery/newscaster/security_unit //Security unit
name = "Security Newscaster"
- securityCaster = 1
+ securityCaster = TRUE
/obj/machinery/newscaster/New(var/loc, var/ndir, var/building = 1)
buildstage = building
@@ -141,7 +131,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
dir = ndir
allCasters += src
for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) // Let's give it an appropriate unit number
- src.unit_no++
+ unit_no++
update_icon()
..()
@@ -157,21 +147,21 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if((stat & NOPOWER) || (stat & BROKEN))
icon_state = "newscaster_off"
if(stat & BROKEN) //If the thing is smashed, add crack overlay on top of the unpowered sprite.
- src.overlays.len = 0
- src.overlays += image(src.icon, "crack3")
+ overlays.Cut()
+ overlays += image(icon, "crack3")
return
- src.overlays.len = 0 //reset overlays
+ overlays.Cut() //reset overlays
if(news_network.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message
icon_state = "newscaster_wanted"
return
if(alert) //new message alert overlay
- src.overlays += image(icon = icon, icon_state = "newscaster_alert")
+ overlays += image(icon = icon, icon_state = "newscaster_alert")
if(hitstaken > 0) //Cosmetic damage overlay
- src.overlays += image(src.icon, "crack[hitstaken]")
+ overlays += image(icon, "crack[hitstaken]")
icon_state = "newscaster_normal"
return
@@ -179,13 +169,13 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
/obj/machinery/newscaster/power_change()
if(stat & BROKEN || buildstage != 1) //Broken shit can't be powered.
return
- if( src.powered() )
+ if( powered() )
stat &= ~NOPOWER
- src.update_icon()
+ update_icon()
else
spawn(rand(0, 15))
stat |= NOPOWER
- src.update_icon()
+ update_icon()
/obj/machinery/newscaster/ex_act(severity)
@@ -198,12 +188,12 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if(prob(50))
qdel(src)
else
- src.update_icon() //can't place it above the return and outside the if-else. or we might get runtimes of null.update_icon() if(prob(50)) goes in.
+ update_icon() //can't place it above the return and outside the if-else. or we might get runtimes of null.update_icon() if(prob(50)) goes in.
return
else
if(prob(50))
stat |= BROKEN
- src.update_icon()
+ update_icon()
return
return
@@ -213,14 +203,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
hitstaken++
if(hitstaken>=3 && !(stat & BROKEN))
stat |= BROKEN
- playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 100, 1)
+ playsound(src, 'sound/effects/Glassbr3.ogg', 100, 1)
else
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 100, 1)
update_icon()
/obj/machinery/newscaster/attack_ai(mob/user as mob)
- src.add_hiddenprint(user)
- return src.attack_hand(user)
+ add_hiddenprint(user)
+ return attack_hand(user)
/obj/machinery/newscaster/attack_hand(mob/user as mob) //########### THE MAIN BEEF IS HERE! And in the proc below this...############
@@ -235,14 +225,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if(istype(user, /mob/living/carbon/human) || istype(user,/mob/living/silicon) || isobserver(user))
var/mob/M = user
var/dat
- dat = text("Newscaster
Newscaster Unit #[src.unit_no]
")
+ dat = text("Newscaster
Newscaster Unit #[unit_no]
")
- src.scan_user(M) //Newscaster scans you
+ scan_user(M) //Newscaster scans you
switch(screen)
if(NEWSCASTER_MENU)
- dat += {"Welcome to Newscasting Unit #[src.unit_no]. Interface & News networks Operational.
+ dat += {"Welcome to Newscasting Unit #[unit_no]. Interface & News networks Operational.
property of Nanotrasen Inc"}
if(news_network.wanted_issue)
dat+= "Read Wanted Issue"
@@ -253,17 +243,17 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
Print newspaper Re-scan User
Cancel "}
if(NEWSCASTER_NEW_MESSAGE)
dat += {"Creating new Feed Message...
- Receiving Channel: [src.channel_name]
- Message Author: [src.scanned_user]
- Message Body: [src.msg] "}
+ Receiving Channel: [channel_name]
+ Message Author: [scanned_user]
+ Message Body: [msg] "}
- /*if(isAI(user))
- dat +="Upload Photo: [(src.photo ? "Photo Uploaded" : "No Photo")] "
- else
- dat +="Attach Photo: [(src.photo ? "Photo Attached" : "No Photo")] "
- */
dat += AttachPhotoButton(user)
dat += " Submit
Cancel "
if(NEWSCASTER_NEW_MESSAGE_SUCCESS)
- dat += {"Feed story successfully submitted to [src.channel_name].
+ dat += {"Feed story successfully submitted to [channel_name].
Return "}
if(NEWSCASTER_NEW_CHANNEL_SUCCESS)
- dat += {"Feed Channel [src.channel_name] created successfully.
+ dat += {"Feed Channel [channel_name] created successfully.
Return "}
if(NEWSCASTER_NEW_MESSAGE_ERROR)
dat+="ERROR: Could not submit Feed story to Network. "
- if(src.channel_name=="")
+ if(channel_name=="")
dat+="�Invalid receiving channel name. "
- if(src.scanned_user=="Unknown")
+ if(scanned_user=="Unknown")
dat+="�Channel author unverified. "
- if(src.msg == "" || src.msg == "\[REDACTED\]")
+ if(msg == "" || msg == "\[REDACTED\]")
dat+="�Invalid message body. "
dat+=" Return "
if(NEWSCASTER_NEW_CHANNEL_ERROR)
dat+="ERROR: Could not submit Feed Channel to Network. "
- //var/list/existing_channels = list() //Let's get dem existing channels - OBSOLETE
var/list/existing_authors = list()
for(var/datum/feed_channel/FC in news_network.network_channels)
- //existing_channels += FC.channel_name //OBSOLETE
if(FC.author == "\[REDACTED\]")
existing_authors += FC.backup_author
else
existing_authors += FC.author
- if(src.scanned_user in existing_authors)
+ if(scanned_user in existing_authors)
dat+="�There already exists a Feed channel under your name. "
- if(src.channel_name=="" || src.channel_name == "\[REDACTED\]")
+ if(channel_name=="" || channel_name == "\[REDACTED\]")
dat+="�Invalid channel name. "
- var/check = 0
+ var/check = FALSE
for(var/datum/feed_channel/FC in news_network.network_channels)
- if(FC.channel_name == src.channel_name)
- check = 1
+ if(FC.channel_name == channel_name)
+ check = TRUE
break
if(check)
dat+="�Channel name already in use. "
- if(src.scanned_user=="Unknown")
+ if(scanned_user=="Unknown")
dat+="�Channel author unverified. "
dat+=" Return "
if(NEWSCASTER_PRINT_NEWSPAPER)
- var/total_num=length(news_network.network_channels)
- var/active_num=total_num
- var/message_num=0
+ var/total_num = length(news_network.network_channels)
+ var/active_num = total_num
+ var/message_num = 0
for(var/datum/feed_channel/FC in news_network.network_channels)
if(!FC.censored)
message_num += length(FC.messages) //Dont forget, datum/feed_channel's var messages is a list of datum/feed_message
@@ -360,21 +335,21 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
active_num--
dat += {"Network currently serves a total of [total_num] Feed channels, [active_num] of which are active, and a total of [message_num] Feed Stories.
-
Liquid Paper remaining: [(src.paper_remaining) *100 ] cm^3
+
Liquid Paper remaining: [(paper_remaining) *100 ] cm^3
Print Paper Cancel"}
if(NEWSCASTER_VIEW_CHANNEL)
- dat+="[src.viewing_channel.channel_name]: \[created by: [src.viewing_channel.author]\]"
- if(src.viewing_channel.censored)
+ dat+="[viewing_channel.channel_name]: \[created by: [viewing_channel.author]\]"
+ if(viewing_channel.censored)
dat += {"ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
No further feed story additions are allowed while the D-Notice is in effect.
"}
else
- if( isemptylist(src.viewing_channel.messages) )
+ if( isemptylist(viewing_channel.messages) )
dat+="No feed messages found in channel... "
else
var/i = 0
- for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages)
+ for(var/datum/feed_message/MESSAGE in viewing_channel.messages)
i++
dat+="-[MESSAGE.body] "
if(MESSAGE.img)
@@ -411,66 +386,66 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
dat+=" Back"
if(NEWSCASTER_CENSORSHIP_CHANNEL)
- dat += {"[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
- [(src.viewing_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]"}
- if( isemptylist(src.viewing_channel.messages) )
+ dat += {"[viewing_channel.channel_name]: \[ created by: [viewing_channel.author] \]
+ [(viewing_channel.author=="\[REDACTED\]") ? ("Undo Author censorship") : ("Censor channel Author")]"}
+ if( isemptylist(viewing_channel.messages) )
dat+="No feed messages found in channel... "
else
- for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages)
+ for(var/datum/feed_message/MESSAGE in viewing_channel.messages)
dat += {"-[MESSAGE.body] \[Story by [MESSAGE.author]\] [(MESSAGE.body == "\[REDACTED\]") ? ("Undo story censorship") : ("Censor story")] - [(MESSAGE.author == "\[REDACTED\]") ? ("Undo Author Censorship") : ("Censor message Author")] "}
dat+=" Back"
if(NEWSCASTER_D_NOTICE_CHANNEL)
- dat += {"[src.viewing_channel.channel_name]: \[ created by: [src.viewing_channel.author] \]
- Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel."}
- if(src.viewing_channel.censored)
+ dat += {"[viewing_channel.channel_name]: \[ created by: [viewing_channel.author] \]
+ Channel messages listed below. If you deem them dangerous to the station, you can Bestow a D-Notice upon the channel."}
+ if(viewing_channel.censored)
dat += {"ATTENTION: This channel has been deemed as threatening to the welfare of the station, and marked with a Nanotrasen D-Notice.
No further feed story additions are allowed while the D-Notice is in effect.
"}
else
- if( isemptylist(src.viewing_channel.messages) )
+ if( isemptylist(viewing_channel.messages) )
dat+="No feed messages found in channel... "
else
- for(var/datum/feed_message/MESSAGE in src.viewing_channel.messages)
+ for(var/datum/feed_message/MESSAGE in viewing_channel.messages)
dat+="-[MESSAGE.body] \[Story by [MESSAGE.author]\] "
dat+=" Back"
if(NEWSCASTER_WANTED)
dat+="Wanted Issue Handler:"
- var/wanted_already = 0
+ var/wanted_already = FALSE
var/end_param = 1
if(news_network.wanted_issue)
- wanted_already = 1
+ wanted_already = TRUE
end_param = 2
if(wanted_already)
dat+=" A wanted issue is already in Feed Circulation. You can edit or cancel it below."
dat += {"
- Criminal Name: [src.channel_name]
- Description: [src.msg] "}
+ Criminal Name: [channel_name]
+ Description: [msg] "}
dat += AttachPhotoButton(user)
if(wanted_already)
dat+="Wanted Issue created by: [news_network.wanted_issue.backup_author] "
else
- dat+="Wanted Issue will be created under prosecutor: [src.scanned_user] "
+ dat+="Wanted Issue will be created under prosecutor: [scanned_user] "
dat+=" [(wanted_already) ? ("Edit Issue") : ("Submit")]"
if(wanted_already)
dat+=" Take down Issue"
dat+=" Cancel"
if(NEWSCASTER_WANTED_SUCCESS)
- dat += {"Wanted issue for [src.channel_name] is now in Network Circulation.
+ dat += {"Wanted issue for [channel_name] is now in Network Circulation.
Return "}
if(NEWSCASTER_WANTED_ERROR)
dat+="ERROR: Wanted Issue rejected by Network. "
- if(src.channel_name=="" || src.channel_name == "\[REDACTED\]")
+ if(channel_name=="" || channel_name == "\[REDACTED\]")
dat+="�Invalid name for person wanted. "
- if(src.scanned_user=="Unknown")
+ if(scanned_user=="Unknown")
dat+="�Issue author unverified. "
- if(src.msg == "" || src.msg == "\[REDACTED\]")
+ if(msg == "" || msg == "\[REDACTED\]")
dat+="�Invalid description. "
dat+=" Return "
if(NEWSCASTER_WANTED_DELETED)
@@ -491,7 +466,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
dat+="
Back "
if(NEWSCASTER_WANTED_EDIT)
- dat += {"Wanted issue for [src.channel_name] successfully edited.
+ dat += {"Wanted issue for [channel_name] successfully edited.
Return "}
if(NEWSCASTER_PRINT_NEWSPAPER_SUCCESS)
@@ -508,139 +483,136 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
M << browse(dat, "window=newscaster_main;size=400x600")
onclose(M, "newscaster_main")
- /*if(src.isbroken) //debugging shit
- return
- src.hitstaken++
- if(src.hitstaken==3)
- src.isbroken = 1
- src.update_icon()*/
-
-
/obj/machinery/newscaster/Topic(href, href_list)
if(..())
return
if(masterController && !isobserver(masterController) && get_dist(masterController,src)<=1 && usr!=masterController)
to_chat(usr, "You must wait for [masterController] to finish and move away.")
return
- if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon) || isobserver(usr)))
+ if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon) || isobserver(usr)))
usr.set_machine(src)
if(href_list["set_channel_name"])
if(isobserver(usr) && !canGhostWrite(usr,src,"set a channel's name"))
to_chat(usr, "You can't do that.")
return
- src.channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""))
- while (findtext(src.channel_name," ") == 1)
- src.channel_name = copytext(src.channel_name,2,length(src.channel_name)+1)
- src.updateUsrDialog()
- //src.update_icon()
+ channel_name = strip_html_simple(input(usr, "Provide a Feed Channel Name", "Network Channel Handler", ""))
+ while (findtext(channel_name," ") == 1)
+ channel_name = copytext(channel_name,2,length(channel_name)+1)
+ updateUsrDialog()
else if(href_list["set_channel_lock"])
if(isobserver(usr) && !canGhostWrite(usr,src,"locked a channel"))
to_chat(usr, "You can't do that.")
return
- src.c_locked = !src.c_locked
- src.updateUsrDialog()
- //src.update_icon()
+ c_locked = !c_locked
+ updateUsrDialog()
else if(href_list["submit_new_channel"])
if(isobserver(usr) && !canGhostWrite(usr,src,"created a new channel"))
to_chat(usr, "You can't do that.")
return
- //var/list/existing_channels = list() //OBSOLETE
var/list/existing_authors = list()
for(var/datum/feed_channel/FC in news_network.network_channels)
- //existing_channels += FC.channel_name
if(FC.author == "\[REDACTED\]")
existing_authors += FC.backup_author
else
existing_authors +=FC.author
- var/check = 0
+ var/check = FALSE
for(var/datum/feed_channel/FC in news_network.network_channels)
- if(FC.channel_name == src.channel_name)
- check = 1
+ if(FC.channel_name == channel_name)
+ check = TRUE
break
- if(src.channel_name == "" || src.channel_name == "\[REDACTED\]" || src.scanned_user == "Unknown" || check || (src.scanned_user in existing_authors) )
- src.screen=NEWSCASTER_NEW_CHANNEL_ERROR
+ if(channel_name == "" || channel_name == "\[REDACTED\]" || scanned_user == "Unknown" || check || (scanned_user in existing_authors) )
+ screen=NEWSCASTER_NEW_CHANNEL_ERROR
else
var/choice = alert("Please confirm Feed channel creation","Network Channel Handler","Confirm","Cancel")
if(choice=="Confirm")
var/datum/feed_channel/newChannel = new /datum/feed_channel
- newChannel.channel_name = src.channel_name
- newChannel.author = src.scanned_user
+ newChannel.channel_name = channel_name
+ newChannel.author = scanned_user
newChannel.locked = c_locked
feedback_inc("newscaster_channels",1)
- /*for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) //Let's add the new channel in all casters.
- NEWSCASTER.channel_list += newChannel*/ //Now that it is sane, get it into the list. -OBSOLETE
news_network.network_channels += newChannel //Adding channel to the global network
- src.screen = NEWSCASTER_MENU
- src.updateUsrDialog()
- //src.update_icon()
+ screen = NEWSCASTER_MENU
+ updateUsrDialog()
else if(href_list["set_channel_receiving"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the receiving channel"))
to_chat(usr, "You can't do that.")
return
- //var/list/datum/feed_channel/available_channels = list()
+
var/list/available_channels = list()
for(var/datum/feed_channel/F in news_network.network_channels)
if( (!F.locked || F.author == scanned_user) && !F.censored)
available_channels += F.channel_name
- src.channel_name = strip_html_simple(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels )
- src.updateUsrDialog()
+ channel_name = strip_html_simple(input(usr, "Choose receiving Feed Channel", "Network Channel Handler") in available_channels )
+ updateUsrDialog()
else if(href_list["set_new_message"])
if(isobserver(usr) && !canGhostWrite(usr,src,"set the message of a new feed story"))
to_chat(usr, "You can't do that.")
return
- if(isnull(src.msg))
- src.msg = ""
- src.msg = strip_html(input(usr, "Write your Feed story", "Network Channel Handler", src.msg))
- while (findtext(src.msg," ") == 1)
- src.msg = copytext(src.msg,2,length(src.msg)+1)
- src.updateUsrDialog()
+ if(isnull(msg))
+ msg = ""
+ msg = strip_html(input(usr, "Write your Feed story", "Network Channel Handler", msg))
+ while (findtext(msg," ") == 1)
+ msg = copytext(msg,2,length(msg)+1)
+ updateUsrDialog()
else if(href_list["set_attachment"])
if(isobserver(usr))
to_chat(usr, "You can't do that.")
return
AttachPhoto(usr)
- src.updateUsrDialog()
+ updateUsrDialog()
else if(href_list["upload_photo"])
- if(!isAI(usr))
+ if(!issilicon(usr))
return
if(photo)
EjectPhoto()
- src.updateUsrDialog()
+ updateUsrDialog()
return
+ var/obj/item/device/camera/silicon/targetcam = null
- var/mob/living/silicon/ai/A = usr
+ if(isAI(usr))
+ var/mob/living/silicon/ai/A = usr
+ targetcam = A.aicamera
+ else if((isrobot(usr)))
+ var/mob/living/silicon/robot/R = usr
+ if(R.connected_ai)
+ targetcam = R.connected_ai.aicamera
+ else
+ targetcam = R.aicamera
+ else
+ to_chat(usr, "You cannot interface with the silicon photo uploading network.")
+ return
var/list/nametemp = list()
var/find
- if(A.aicamera.aipictures.len == 0)
- to_chat(usr, "No images saved")
+ if(!targetcam.aipictures.len)
+ to_chat(usr, "No images saved")
return
- for(var/datum/picture/t in A.aicamera.aipictures)
+ for(var/datum/picture/t in targetcam.aipictures)
nametemp += t.fields["name"]
find = input("Select image") in nametemp
- for(var/datum/picture/q in A.aicamera.aipictures)
+ for(var/datum/picture/q in targetcam.aipictures)
if(q.fields["name"] == find)
photo = q
break
- src.updateUsrDialog()
+ updateUsrDialog()
else if(href_list["submit_new_message"])
if(isobserver(usr) && !canGhostWrite(usr,src,"added a new story"))
to_chat(usr, "You can't do that.")
return
- if(src.msg =="" || src.msg=="\[REDACTED\]" || src.scanned_user == "Unknown" || src.channel_name == "" )
- src.screen=NEWSCASTER_NEW_MESSAGE_ERROR
+ if(msg =="" || msg=="\[REDACTED\]" || scanned_user == "Unknown" || channel_name == "" )
+ screen=NEWSCASTER_NEW_MESSAGE_ERROR
else
var/datum/feed_message/newMsg = new /datum/feed_message
- newMsg.author = src.scanned_user
- newMsg.body = src.msg
+ newMsg.author = scanned_user
+ newMsg.body = msg
if(photo)
if(istype(photo,/obj/item/weapon/photo))
var/obj/item/weapon/photo/P = photo
@@ -653,107 +625,107 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
EjectPhoto()
feedback_inc("newscaster_stories",1)
for(var/datum/feed_channel/FC in news_network.network_channels)
- if(FC.channel_name == src.channel_name)
+ if(FC.channel_name == channel_name)
FC.messages += newMsg //Adding message to the network's appropriate feed_channel
break
- src.screen = NEWSCASTER_MENU
+ screen = NEWSCASTER_MENU
for(var/obj/machinery/newscaster/NEWSCASTER in allCasters)
- NEWSCASTER.newsAlert(src.channel_name)
+ NEWSCASTER.newsAlert(channel_name)
- src.updateUsrDialog()
+ updateUsrDialog()
else if(href_list["create_channel"])
if(isobserver(usr) && !canGhostWrite(usr,src,"created a channel"))
to_chat(usr, "You can't do that.")
return
- src.screen=NEWSCASTER_NEW_CHANNEL
- src.updateUsrDialog()
+ screen=NEWSCASTER_NEW_CHANNEL
+ updateUsrDialog()
else if(href_list["create_feed_story"])
if(isobserver(usr) && !canGhostWrite(usr,src,"created a feed story"))
to_chat(usr, "You can't do that.")
return
- src.screen=NEWSCASTER_NEW_MESSAGE
- src.updateUsrDialog()
+ screen=NEWSCASTER_NEW_MESSAGE
+ updateUsrDialog()
else if(href_list["menu_paper"])
if(isobserver(usr) && !canGhostWrite(usr,src,""))
to_chat(usr, "You can't do that.")
return
- src.screen=NEWSCASTER_PRINT_NEWSPAPER
- src.updateUsrDialog()
+ screen=NEWSCASTER_PRINT_NEWSPAPER
+ updateUsrDialog()
else if(href_list["print_paper"])
if(isobserver(usr) && !canGhostWrite(usr,src,"printed a paper"))
to_chat(usr, "You can't do that.")
return
- if(!src.paper_remaining)
- src.screen=NEWSCASTER_PRINT_NEWSPAPER_ERROR
+ if(!paper_remaining)
+ screen=NEWSCASTER_PRINT_NEWSPAPER_ERROR
else
- src.print_paper()
- src.screen = NEWSCASTER_PRINT_NEWSPAPER_SUCCESS
- src.updateUsrDialog()
+ print_paper()
+ screen = NEWSCASTER_PRINT_NEWSPAPER_SUCCESS
+ updateUsrDialog()
else if(href_list["menu_censor_story"])
if(isobserver(usr) && !canGhostWrite(usr,src,"censored a story"))
to_chat(usr, "You can't do that.")
return
- src.screen=NEWSCASTER_CENSORSHIP_MENU
- src.updateUsrDialog()
+ screen=NEWSCASTER_CENSORSHIP_MENU
+ updateUsrDialog()
else if(href_list["menu_censor_channel"])
if(isobserver(usr) && !canGhostWrite(usr,src,"censored a channel"))
to_chat(usr, "You can't do that.")
return
- src.screen=NEWSCASTER_D_NOTICE_MENU
- src.updateUsrDialog()
+ screen=NEWSCASTER_D_NOTICE_MENU
+ updateUsrDialog()
else if(href_list["menu_wanted"])
if(isobserver(usr) && !canGhostWrite(usr,src,""))
to_chat(usr, "You can't do that.")
return
- var/already_wanted = 0
+ var/already_wanted = FALSE
if(news_network.wanted_issue)
- already_wanted = 1
+ already_wanted = TRUE
if(already_wanted)
- src.channel_name = news_network.wanted_issue.author
- src.msg = news_network.wanted_issue.body
- src.screen = NEWSCASTER_WANTED
- src.updateUsrDialog()
+ channel_name = news_network.wanted_issue.author
+ msg = news_network.wanted_issue.body
+ screen = NEWSCASTER_WANTED
+ updateUsrDialog()
else if(href_list["set_wanted_name"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the name of a wanted person"))
to_chat(usr, "You can't do that.")
return
- src.channel_name = strip_html(input(usr, "Provide the name of the Wanted person", "Network Security Handler", ""))
- while (findtext(src.channel_name," ") == 1)
- src.channel_name = copytext(src.channel_name,2,length(src.channel_name)+1)
- src.updateUsrDialog()
+ channel_name = strip_html(input(usr, "Provide the name of the Wanted person", "Network Security Handler", ""))
+ while (findtext(channel_name," ") == 1)
+ channel_name = copytext(channel_name,2,length(channel_name)+1)
+ updateUsrDialog()
else if(href_list["set_wanted_desc"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set the description of a wanted person"))
to_chat(usr, "You can't do that.")
return
- src.msg = strip_html(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", ""))
- while (findtext(src.msg," ") == 1)
- src.msg = copytext(src.msg,2,length(src.msg)+1)
- src.updateUsrDialog()
+ msg = strip_html(input(usr, "Provide the a description of the Wanted person and any other details you deem important", "Network Security Handler", ""))
+ while (findtext(msg," ") == 1)
+ msg = copytext(msg,2,length(msg)+1)
+ updateUsrDialog()
else if(href_list["submit_wanted"])
if(isobserver(usr) && !canGhostWrite(usr,src,"submitted a wanted poster"))
to_chat(usr, "You can't do that.")
return
var/input_param = text2num(href_list["submit_wanted"])
- if(src.msg == "" || src.channel_name == "" || src.scanned_user == "Unknown")
- src.screen = NEWSCASTER_WANTED_ERROR
+ if(msg == "" || channel_name == "" || scanned_user == "Unknown")
+ screen = NEWSCASTER_WANTED_ERROR
else
var/choice = alert("Please confirm Wanted Issue [(input_param==1) ? ("creation.") : ("edit.")]","Network Security Handler","Confirm","Cancel")
if(choice=="Confirm")
if(input_param==1) //If input_param == 1 we're submitting a new wanted issue. At 2 we're just editing an existing one. See the else below
var/datum/feed_message/WANTED = new /datum/feed_message
- WANTED.author = src.channel_name
- WANTED.body = src.msg
- WANTED.backup_author = src.scanned_user //I know, a bit wacky
+ WANTED.author = channel_name
+ WANTED.body = msg
+ WANTED.backup_author = scanned_user //I know, a bit wacky
if(photo)
if(istype(photo,/obj/item/weapon/photo))
var/obj/item/weapon/photo/P = photo
@@ -765,14 +737,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
for(var/obj/machinery/newscaster/NEWSCASTER in allCasters)
NEWSCASTER.newsAlert()
NEWSCASTER.update_icon()
- src.screen = NEWSCASTER_WANTED_SUCCESS
+ screen = NEWSCASTER_WANTED_SUCCESS
else
if(news_network.wanted_issue.is_admin_message)
alert("The wanted issue has been distributed by a Nanotrasen higherup. You cannot edit it.","Ok")
return
- news_network.wanted_issue.author = src.channel_name
- news_network.wanted_issue.body = src.msg
- news_network.wanted_issue.backup_author = src.scanned_user
+ news_network.wanted_issue.author = channel_name
+ news_network.wanted_issue.body = msg
+ news_network.wanted_issue.backup_author = scanned_user
if(photo)
if(istype(photo,/obj/item/weapon/photo))
var/obj/item/weapon/photo/P = photo
@@ -780,9 +752,9 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
else if(istype(photo,/datum/picture))
var/datum/picture/P = photo
news_network.wanted_issue.img = P.fields["img"]
- src.screen = NEWSCASTER_WANTED_EDIT
+ screen = NEWSCASTER_WANTED_EDIT
- src.updateUsrDialog()
+ updateUsrDialog()
else if(href_list["cancel_wanted"])
if(news_network.wanted_issue.is_admin_message)
@@ -793,12 +765,12 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
news_network.wanted_issue = null
for(var/obj/machinery/newscaster/NEWSCASTER in allCasters)
NEWSCASTER.update_icon()
- src.screen=NEWSCASTER_WANTED_DELETED
- src.updateUsrDialog()
+ screen=NEWSCASTER_WANTED_DELETED
+ updateUsrDialog()
else if(href_list["view_wanted"])
- src.screen=NEWSCASTER_WANTED_SHOW
- src.updateUsrDialog()
+ screen=NEWSCASTER_WANTED_SHOW
+ updateUsrDialog()
else if(href_list["censor_channel_author"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor an author"))
to_chat(usr, "You can't do that.")
@@ -812,7 +784,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
FC.author = "\[REDACTED\]"
else
FC.author = FC.backup_author
- src.updateUsrDialog()
+ updateUsrDialog()
else if(href_list["censor_channel_story_author"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor a story's author"))
@@ -827,7 +799,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
MSG.author = "\[REDACTED\]"
else
MSG.author = MSG.backup_author
- src.updateUsrDialog()
+ updateUsrDialog()
else if(href_list["censor_channel_story_body"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to censor a story"))
@@ -847,16 +819,16 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
MSG.body = "\[REDACTED\]"
else
MSG.body = MSG.backup_body
- src.updateUsrDialog()
+ updateUsrDialog()
else if(href_list["pick_d_notice"])
if(isobserver(usr) && !canGhostWrite(usr,src,""))
to_chat(usr, "You can't do that.")
return
var/datum/feed_channel/FC = locate(href_list["pick_d_notice"])
- src.viewing_channel = FC
- src.screen=NEWSCASTER_D_NOTICE_CHANNEL
- src.updateUsrDialog()
+ viewing_channel = FC
+ screen=NEWSCASTER_D_NOTICE_CHANNEL
+ updateUsrDialog()
else if(href_list["toggle_d_notice"])
if(isobserver(usr) && !canGhostWrite(usr,src,"tried to set a D-notice"))
@@ -867,33 +839,33 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
alert("This channel was created by a Nanotrasen Officer. You cannot place a D-Notice upon it.","Ok")
return
FC.censored = !FC.censored
- src.updateUsrDialog()
+ updateUsrDialog()
else if(href_list["view"])
- src.screen=NEWSCASTER_CHANNEL_LIST
- src.updateUsrDialog()
+ screen=NEWSCASTER_CHANNEL_LIST
+ updateUsrDialog()
else if(href_list["setScreen"]) //Brings us to the main menu and resets all fields~
- src.screen = text2num(href_list["setScreen"])
- if (src.screen == NEWSCASTER_MENU)
- src.scanned_user = "Unknown";
+ screen = text2num(href_list["setScreen"])
+ if (screen == NEWSCASTER_MENU)
+ scanned_user = "Unknown";
msg = "";
- src.c_locked=0;
+ c_locked=0;
channel_name="";
- src.viewing_channel = null
- src.updateUsrDialog()
+ viewing_channel = null
+ updateUsrDialog()
else if(href_list["show_channel"])
var/datum/feed_channel/FC = locate(href_list["show_channel"])
- src.viewing_channel = FC
- src.screen = NEWSCASTER_VIEW_CHANNEL
- src.updateUsrDialog()
+ viewing_channel = FC
+ screen = NEWSCASTER_VIEW_CHANNEL
+ updateUsrDialog()
else if(href_list["pick_censor_channel"])
var/datum/feed_channel/FC = locate(href_list["pick_censor_channel"])
- src.viewing_channel = FC
- src.screen = NEWSCASTER_CENSORSHIP_CHANNEL
- src.updateUsrDialog()
+ viewing_channel = FC
+ screen = NEWSCASTER_CENSORSHIP_CHANNEL
+ updateUsrDialog()
else if(href_list["show_photo_info"])
var/datum/feed_message/FM = locate(href_list["show_photo_info"])
@@ -901,35 +873,35 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if(istype(FM) && FM.img_info)
usr.show_message("[FM.img_info]", MESSAGE_SEE)
- src.updateUsrDialog()
+ updateUsrDialog()
else if(href_list["refresh"])
- src.updateUsrDialog()
+ updateUsrDialog()
/obj/machinery/newscaster/attackby(obj/item/I as obj, mob/user as mob)
switch(buildstage)
if(0)
if(iscrowbar(I))
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("[user] begins prying off the [src]!", "You begin prying off the [src]")
if(do_after(user, src,10))
to_chat(user, "You pry off the [src]!.")
- new /obj/item/mounted/frame/newscaster(src.loc)
+ new /obj/item/mounted/frame/newscaster(loc)
qdel(src)
return
if(isscrewdriver(I) && !(stat & BROKEN))
user.visible_message("[user] screws in the [src]!", "You screw in the [src]")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
buildstage = 1
if(1)
if(isscrewdriver(I) && !(stat & BROKEN))
user.visible_message("[user] unscrews the [src]!", "You unscrew the [src]")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
buildstage = 0
- src.update_icon()
+ update_icon()
return
if ((stat & BROKEN) && (istype(I, /obj/item/stack/sheet/glass/glass)))
@@ -938,12 +910,12 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
to_chat(user, "You need more glass to do that.")
else
stack.use(2)
- src.hitstaken = 0
+ hitstaken = 0
stat &= ~BROKEN
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 80, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
else if (stat & BROKEN)
- playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 100, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 100, 1)
visible_message("[user.name] further abuses the shattered [src].")
else
@@ -951,34 +923,34 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if(istype(P) && !photo && user.drop_item(P, src))
photo = P
to_chat(user, "You add \the [P] to \the [src].")
- src.updateUsrDialog()
+ updateUsrDialog()
else if(istype(I, /obj/item/weapon) )
var/obj/item/weapon/W = I
if(W.force <15)
visible_message("[user.name] hits the [src] with the [W] with no visible effect." )
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 100, 1)
else
user.do_attack_animation(src, W)
- src.hitstaken++
- if(src.hitstaken==3)
+ hitstaken++
+ if(hitstaken==3)
visible_message("[user.name] smashes the [src]!")
stat |= BROKEN
- playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 100, 1)
+ playsound(src, 'sound/effects/Glassbr3.ogg', 100, 1)
else
- visible_message("[user.name] forcefully slams the [src.name] with the [I.name]!")
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 100, 1)
+ visible_message("[user.name] forcefully slams the [name] with the [I.name]!")
+ playsound(src, 'sound/effects/Glasshit.ogg', 100, 1)
else
to_chat(user, "This does nothing.")
- src.update_icon()
+ update_icon()
/obj/machinery/newscaster/attack_ai(mob/user as mob)
- src.add_hiddenprint(user)
- return src.attack_hand(user) //or maybe it'll have some special functions? No idea.
+ add_hiddenprint(user)
+ return attack_hand(user) //or maybe it'll have some special functions? No idea.
/obj/machinery/newscaster/attack_paw(mob/user as mob)
- to_chat(user, "The newscaster controls are far too complicated for your tiny brain!")
+ to_chat(user, "The newscaster controls are far too complicated for your tiny brain!")
return
/obj/machinery/newscaster/proc/AttachPhoto(mob/user as mob)
@@ -994,7 +966,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
return
if(istype(photo,/obj/item/weapon/photo))
var/obj/item/weapon/photo/P = photo
- P.forceMove(src.loc)
+ P.forceMove(loc)
photo = null
else if(istype(photo,/datum/picture))
@@ -1003,7 +975,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
/obj/machinery/newscaster/proc/AttachPhotoButton(mob/user as mob)
var/name = "Attach Photo"
var/href = "set_attachment=1"
- if(isAI(user))
+ if(issilicon(user))
name = "Upload Photo"
href = "upload_photo=1"
@@ -1038,7 +1010,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
pressure_resistance = 1
attack_verb = list("baps", "smacks", "whaps")
autoignition_temperature = AUTOIGNITION_PAPER
- fire_fuel = 1
+ fire_fuel = TRUE
var/screen = 0
var/pages = 0
@@ -1048,43 +1020,38 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
var/scribble=""
var/scribble_page = null
-/*obj/item/weapon/newspaper/attack_hand(mob/user as mob)
- ..()
- to_chat(world, "derp")*/
-
-obj/item/weapon/newspaper/attack_self(mob/user as mob)
+/obj/item/weapon/newspaper/attack_self(mob/user as mob)
if(ishuman(user))
- //var/mob/living/carbon/human/human_user = user
var/dat
- src.pages = 0
+ pages = 0
switch(screen)
if(NEWSPAPER_TITLE_PAGE) //Cover
dat += {"
The Griffon
Nanotrasen-standard newspaper, for use on Nanotrasen Space Facilities
"
if(scribble_page==curr_page)
- dat+=" There is a small scribble near the end of this page... It reads: \"[src.scribble]\""
+ dat+=" There is a small scribble near the end of this page... It reads: \"[scribble]\""
dat+= "
"
if(NEWSPAPER_CONTENT_PAGE) // X channel pages inbetween.
- for(var/datum/feed_channel/NP in src.news_content)
- src.pages++ //Let's get it right again.
- var/datum/feed_channel/C = src.news_content[src.curr_page]
+ for(var/datum/feed_channel/NP in news_content)
+ pages++ //Let's get it right again.
+ var/datum/feed_channel/C = news_content[curr_page]
dat+="[C.channel_name] \[created by: [C.author]\]
"
if(C.censored)
dat+="This channel was deemed dangerous to the general welfare of the station and therefore marked with a D-Notice. Its contents were not transferred to the newspaper at the time of printing."
@@ -1103,12 +1070,12 @@ obj/item/weapon/newspaper/attack_self(mob/user as mob)
dat+="\[Story by [MESSAGE.author]\]
"
dat+=""
if(scribble_page==curr_page)
- dat+=" There is a small scribble near the end of this page... It reads: \"[src.scribble]\""
+ dat+=" There is a small scribble near the end of this page... It reads: \"[scribble]\""
dat+= "
"
if(NEWSPAPER_LAST_PAGE) //Last page
- for(var/datum/feed_channel/NP in src.news_content)
- src.pages++
- if(src.important_message!=null)
+ for(var/datum/feed_channel/NP in news_content)
+ pages++
+ if(important_message!=null)
dat += {"
Wanted Issue:
Criminal name: [important_message.author]
@@ -1122,12 +1089,12 @@ obj/item/weapon/newspaper/attack_self(mob/user as mob)
else
dat+="Apart from some uninteresting Classified ads, there's nothing on this page..."
if(scribble_page==curr_page)
- dat+=" There is a small scribble near the end of this page... It reads: \"[src.scribble]\""
+ dat+=" There is a small scribble near the end of this page... It reads: \"[scribble]\""
dat+= "
"
else
dat+="I'm sorry to break your immersion. This shit's bugged. Report this bug to Agouri, polyxenitopalidou@gmail.com"
- dat+="
[src.curr_page+1]
"
+ dat+="
[curr_page+1]
"
usr << browse(dat, "window=newspaper_main;size=300x400")
onclose(usr, "newspaper_main")
else
@@ -1140,50 +1107,50 @@ obj/item/weapon/newspaper/Topic(href, href_list)
if ((src in U.contents) || ( istype(loc, /turf) && in_range(src, U) ))
U.set_machine(src)
if(href_list["next_page"])
- if(curr_page==src.pages+1)
+ if(curr_page==pages+1)
return //Don't need that at all, but anyway.
- if(src.curr_page == src.pages) //We're at the middle, get to the end
- src.screen = NEWSPAPER_LAST_PAGE
+ if(curr_page == pages) //We're at the middle, get to the end
+ screen = NEWSPAPER_LAST_PAGE
else
if(curr_page == 0) //We're at the start, get to the middle
- src.screen = NEWSPAPER_CONTENT_PAGE
- src.curr_page++
- playsound(get_turf(src), "pageturn", 50, 1)
+ screen = NEWSPAPER_CONTENT_PAGE
+ curr_page++
+ playsound(src, "pageturn", 50, 1)
else if(href_list["prev_page"])
if(curr_page == 0)
return
if(curr_page == 1)
- src.screen = NEWSPAPER_TITLE_PAGE
+ screen = NEWSPAPER_TITLE_PAGE
else
- if(curr_page == src.pages+1) //we're at the end, let's go back to the middle.
- src.screen = NEWSPAPER_CONTENT_PAGE
- src.curr_page--
- playsound(get_turf(src), "pageturn", 50, 1)
+ if(curr_page == pages+1) //we're at the end, let's go back to the middle.
+ screen = NEWSPAPER_CONTENT_PAGE
+ curr_page--
+ playsound(src, "pageturn", 50, 1)
- if (istype(src.loc, /mob))
- src.attack_self(src.loc)
+ if (istype(loc, /mob))
+ attack_self(loc)
obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/pen))
- if(src.scribble_page == src.curr_page)
+ if(scribble_page == curr_page)
to_chat(user, "There's already a scribble in this page... You wouldn't want to make things too cluttered, would you?")
else
var/s = strip_html( input(user, "Write something", "Newspaper", "") )
s = copytext(sanitize(s), 1, MAX_MESSAGE_LEN)
if (!s)
return
- if (!in_range(src, usr) && src.loc != usr)
+ if (!in_range(src, usr) && loc != usr)
return
- src.scribble_page = src.curr_page
- src.scribble = s
- src.attack_self(user)
+ scribble_page = curr_page
+ scribble = s
+ attack_self(user)
return
else if(W.is_hot())
- src.ashify_item(user)
+ ashify_item(user)
return
#undef NEWSPAPER_TITLE_PAGE
@@ -1206,27 +1173,24 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(human_user.wear_id, /obj/item/device/pda) ) //autorecognition, woo!
var/obj/item/device/pda/P = human_user.wear_id
if(P.id)
- src.scanned_user = "[P.id.registered_name] ([P.id.assignment])"
+ scanned_user = "[P.id.registered_name] ([P.id.assignment])"
else
- src.scanned_user = "Unknown"
+ scanned_user = "Unknown"
else if(istype(human_user.wear_id, /obj/item/weapon/card/id) )
var/obj/item/weapon/card/id/ID = human_user.wear_id
- src.scanned_user ="[ID.registered_name] ([ID.assignment])"
+ scanned_user ="[ID.registered_name] ([ID.assignment])"
else
- src.scanned_user ="Unknown"
+ scanned_user ="Unknown"
else
- src.scanned_user ="Unknown"
- else if (isAI(user))
+ scanned_user ="Unknown"
+ else if (issilicon(user))
var/mob/living/silicon/ai_user = user
- src.scanned_user = "[ai_user.name] ([ai_user.job])"
+ scanned_user = "[ai_user.name] ([ai_user.job])"
else if (isAdminGhost(user))
- src.scanned_user = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]"
+ scanned_user = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]"
else if (isobserver(user))
- src.scanned_user = "Space-Time Anomaly #[rand(0,9)][rand(0,9)][rand(0,9)]"
-// if(masterController && masterController.client && get_dist(masterController,src)<=1)
-// to_chat(masterController, "You were booted from \the [src] by [scanned_user].")
+ scanned_user = "Space-Time Anomaly #[rand(0,9)][rand(0,9)][rand(0,9)]"
masterController = user
-// to_chat(masterController, "[bicon(src)] Welcome back, [scanned_user]!")
/obj/machinery/newscaster/proc/print_paper()
feedback_inc("newscaster_newspapers_printed",1)
@@ -1236,27 +1200,23 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(news_network.wanted_issue)
NEWSPAPER.important_message = news_network.wanted_issue
NEWSPAPER.forceMove(get_turf(src))
- src.paper_remaining--
+ paper_remaining--
return
-//Removed for now so these aren't even checked every tick. Left this here in-case Agouri needs it later.
-///obj/machinery/newscaster/process() //Was thinking of doing the icon update through process, but multiple iterations per second does not
-// return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list.
-
/obj/machinery/newscaster/proc/newsAlert(channel) //This isn't Agouri's work, for it is ugly and vile.
var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ
if(channel)
say("Breaking news from [channel]!")
- src.alert = 1
- src.update_icon()
+ alert = TRUE
+ update_icon()
spawn(300)
- src.alert = 0
- src.update_icon()
- playsound(get_turf(src), 'sound/machines/twobeep.ogg', 75, 1)
+ alert = FALSE
+ update_icon()
+ playsound(src, 'sound/machines/twobeep.ogg', 75, 1)
else
for(var/mob/O in hearers(world.view-1, T))
say("Attention! Wanted issue distributed!")
- playsound(get_turf(src), 'sound/machines/warning-buzzer.ogg', 75, 1)
+ playsound(src, 'sound/machines/warning-buzzer.ogg', 75, 1)
return
/obj/machinery/newscaster/say_quote(text)
diff --git a/code/game/machinery/overview.dm b/code/game/machinery/overview.dm
index 89aff04d646..ff027f05508 100644
--- a/code/game/machinery/overview.dm
+++ b/code/game/machinery/overview.dm
@@ -126,7 +126,7 @@
if(!colour2 && !T.density)
var/datum/gas_mixture/environment = T.return_air()
- var/turf_total = environment.total_moles() / environment.volume * CELL_VOLUME
+ var/turf_total = environment.molar_density() * CELL_VOLUME
//var/turf_total = T.co2 + T.oxygen + T.poison + T.sl_gas + T.n2
@@ -214,7 +214,7 @@
if("/turf/simulated/floor", "/turf/simulated/floor/engine")
var/datum/gas_mixture/environment = T.return_air()
- var/turf_total = environment.total_moles()
+ var/turf_total = environment.molar_density() * CELL_VOLUME
var/t1 = turf_total / MOLES_CELLSTANDARD * 175
if(t1<=100)
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index cf82900f2e1..e9b835530dd 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -454,9 +454,9 @@ Status: [] "},
spawn() shootAt(M) // shoot the target, finally
if(prob(15))
if(prob(50))
- playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/move1.wav', 60, 1)
else
- playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/move2.wav', 60, 1)
else if(secondarytargets.len>0) // if there are no primary targets, go for secondary targets
var/mob/t = pick(secondarytargets)
@@ -467,9 +467,9 @@ Status: [] "},
shootAt(t)
if(prob(15))
if(prob(50))
- playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/move1.wav', 60, 1)
else
- playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/move2.wav', 60, 1)
else
spawn()
popDown()
@@ -485,7 +485,7 @@ Status: [] "},
invisibility=0
raising=1
flick("popup",cover)
- playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/open.wav', 60, 1)
sleep(5)
sleep(5)
raising=0
@@ -503,7 +503,7 @@ Status: [] "},
layer = OBJ_LAYER
raising=1
flick("popdown",cover)
- playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/open.wav', 60, 1)
sleep(10)
raising=0
cover.icon_state="turretCover"
@@ -608,7 +608,7 @@ Status: [] "},
use_power(reqpower)
// //Shooting Code:
- playsound(get_turf(src), installed.fire_sound, 75, 1)
+ playsound(src, installed.fire_sound, 75, 1)
var/obj/item/projectile/A
A = new installed.projectile_type(loc)
A.original = target
@@ -660,7 +660,7 @@ Status: [] "},
return
else if(iscrowbar(W) && !anchored)
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 75, 1)
to_chat(user, "You dismantle the turret construction.")
getFromPool(/obj/item/stack/sheet/metal, loc, 5)
qdel(src)
@@ -686,7 +686,7 @@ Status: [] "},
if(2)
if(iswrench(W))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
to_chat(user, "You bolt the metal armor into place.")
build_step = 3
return
@@ -699,7 +699,7 @@ Status: [] "},
to_chat(user, "You need more fuel to complete this task.")
return
- playsound(get_turf(src), pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1)
+ playsound(src, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1)
if(do_after(user, src, 20))
if(!src || !WT.remove_fuel(5, user))
return
@@ -715,14 +715,14 @@ Status: [] "},
if(!user.drop_item(W, src))
to_chat(user, "You can't let go of \the [W]!")
return
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 100, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 100, 1)
installed = W
to_chat(user, "You add \the [W] to the turret.")
build_step = 4
return
else if(iswrench(W))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
to_chat(user, "You remove the turret's metal armor bolts.")
build_step = 2
return
@@ -732,7 +732,7 @@ Status: [] "},
if(!user.drop_item(W, src))
to_chat(user, "You can't let go of \the [W]!")
return
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 100, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 100, 1)
build_step = 5
to_chat(user, "You add the prox sensor to the turret.")
qdel(W)
@@ -742,7 +742,7 @@ Status: [] "},
if(5)
if(isscrewdriver(W))
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
build_step = 6
to_chat(user, "You close the internal access hatch.")
return
@@ -761,7 +761,7 @@ Status: [] "},
return
else if(isscrewdriver(W))
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
build_step = 5
to_chat(user, "You open the internal access hatch.")
return
@@ -774,7 +774,7 @@ Status: [] "},
if (WT.get_fuel() < 5)
to_chat(user, "You need more fuel to complete this task.")
- playsound(get_turf(src), pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1)
+ playsound(src, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1)
if(do_after(user, src, 30))
if(!src || !WT.remove_fuel(5, user))
return
@@ -790,7 +790,7 @@ Status: [] "},
qdel(src)
else if(iscrowbar(W))
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 75, 1)
to_chat(user, "You pry off the turret's exterior armor.")
getFromPool(/obj/item/stack/sheet/metal, loc, 2)
build_step = 6
diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm
index c71cf7e21ea..5af0ad1fe47 100644
--- a/code/game/machinery/recharger.dm
+++ b/code/game/machinery/recharger.dm
@@ -8,24 +8,46 @@
idle_power_usage = 4
active_power_usage = 250
+
ghost_read = 0 // Deactivate ghost touching.
ghost_write = 0
var/self_powered = 0
+ var/charging_speed_modifier = 1 //The higher this value is, the faster the charging (increases energy used and deposited to gun each process() call, multiplier)
+ var/efficiency_modifier = 1 // This value is the multiplier of excess power loss, the closer it is to zero, the less energy is wasted, min cap is 50% of usual loss
var/obj/item/weapon/charging = null
var/appearance_backup = null
- machine_flags = WRENCHMOVE | FIXED2WORK
+ machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY
/obj/machinery/recharger/New()
- ..()
+ . = ..()
+ component_parts = newlist(
+ /obj/item/weapon/circuitboard/recharger,
+ /obj/item/weapon/stock_parts/scanning_module,
+ /obj/item/weapon/stock_parts/capacitor,
+ /obj/item/weapon/stock_parts/capacitor
+ ) // Fashioned from the cell charger, they both serve a similar purpose
+ RefreshParts()
if(self_powered)
use_power = 0
idle_power_usage = 0
active_power_usage = 0
+/obj/machinery/recharger/RefreshParts()
+ var/T = 0
+ for(var/obj/item/weapon/stock_parts/scanning_module/SM in component_parts) // 1x - 0.5x loss multiplier
+ T += SM.rating
+ efficiency_modifier = 0.25*(5-T)
+ T = 0
+ for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) // 1x - 3x charging multiplier
+ T += C.rating
+ charging_speed_modifier = round(T/2) // rounds down because fractional speed modifiers can cause problems with weapons that have clearly defined "energy units" such as the lawgiver and the pulse rifle, it is unlikely that someone's not going to muster up two of the same capacitor when modifying the charger
+ T = 0
+
+
/obj/machinery/recharger/Destroy()
if(charging)
charging.appearance = appearance_backup
@@ -44,6 +66,9 @@
if(stat & (NOPOWER | BROKEN))
to_chat(user, "[src] isn't connected to a power source.")
return 1
+ if(panel_open)
+ to_chat(user, "You can't insert anything into \the [src] while the maintenance panel is open.")
+ return 1
if(charging)
to_chat(user, "There's \a [charging] already charging inside!")
return 1
@@ -71,6 +96,13 @@
update_icon()
return 1
+/obj/machinery/recharger/togglePanelOpen(var/obj/toggleitem, mob/user)
+ if(charging)
+ to_chat(user, "The maintenance panel is blocked by \the [charging]!")
+ return 1
+ return ..()
+
+
/obj/machinery/recharger/wrenchAnchor(var/mob/user)
if(charging)
to_chat(user, "Remove the charging item first!")
@@ -120,60 +152,69 @@
return
if(charging)
- if(istype(charging, /obj/item/weapon/gun/energy))
+ var/charge_unit
+ if(istype(charging, /obj/item/weapon/gun/energy)) // Original values: 100e charged, 150e wasted,
var/obj/item/weapon/gun/energy/E = charging
- if((E.power_supply.charge + 100) < E.power_supply.maxcharge)
- E.power_supply.give(100)
+ charge_unit = 100 * charging_speed_modifier
+ if((E.power_supply.charge + charge_unit) < E.power_supply.maxcharge)
+ E.power_supply.give(charge_unit)
icon_state = "recharger1"
if(!self_powered)
- use_power(250)
+ use_power(charge_unit + 150 * efficiency_modifier * charging_speed_modifier)
update_icon()
else
E.power_supply.charge = E.power_supply.maxcharge
update_icon()
icon_state = "recharger2"
return
- else if(istype(charging, /obj/item/energy_magazine))//pulse bullet casings
+ else if(istype(charging, /obj/item/energy_magazine))//pulse rifle rounds, Original values: 3rnd charged, 250e consumed, let's say 50e per round + 100e waste
var/obj/item/energy_magazine/M = charging
- if((M.bullets + 3) < M.max_bullets)
- M.bullets = min(M.max_bullets,M.bullets+3)
+ charge_unit = 3 * charging_speed_modifier
+ if((M.bullets + charge_unit) < M.max_bullets)
+ M.bullets = min(M.max_bullets,M.bullets+charge_unit)
icon_state = "recharger1"
if(!self_powered)
- use_power(250)
+ use_power(150 * charging_speed_modifier + 100 * efficiency_modifier * charging_speed_modifier)
update_icon()
else
M.bullets = M.max_bullets
update_icon()
icon_state = "recharger2"
return
- else if(istype(charging, /obj/item/ammo_storage/magazine/lawgiver))
+ else if(istype(charging, /obj/item/ammo_storage/magazine/lawgiver)) // Original values: lawgiver charges 1/5 of of one ammo type for 200e, 100e + 100e excess sounds palatable
var/obj/item/ammo_storage/magazine/lawgiver/L = charging
if(!L.isFull())
+ var/charged_amount
if(L.stuncharge != 100)
- L.stuncharge += 20
+ charged_amount = 20 * charging_speed_modifier
+ L.stuncharge = min(L.stuncharge + charged_amount, 100)
else if(L.lasercharge != 100)
- L.lasercharge += 20
+ charged_amount = 20 * charging_speed_modifier
+ L.lasercharge = min(L.lasercharge + charged_amount, 100)
else if(L.rapid_ammo_count != 5)
- L.rapid_ammo_count++
+ charged_amount = charging_speed_modifier
+ L.rapid_ammo_count = min(L.rapid_ammo_count + charged_amount, 5)
else if(L.flare_ammo_count != 5)
- L.flare_ammo_count++
+ charged_amount = charging_speed_modifier
+ L.flare_ammo_count = min(L.flare_ammo_count + charged_amount, 5)
else if(L.ricochet_ammo_count != 5)
- L.ricochet_ammo_count++
+ charged_amount = charging_speed_modifier
+ L.ricochet_ammo_count = min(L.ricochet_ammo_count + charged_amount, 5)
icon_state = "recharger1"
if(!self_powered)
- use_power(200)
+ use_power(100 * charging_speed_modifier + 100 * charging_speed_modifier * efficiency_modifier) // could make this more compressed but didn't for better readability
update_icon()
else
update_icon()
icon_state = "recharger2"
return
- else if(istype(charging, /obj/item/weapon/melee/baton))
+ else if(istype(charging, /obj/item/weapon/melee/baton)) //25e power loss is so minor that the game shouldn't bother calculating the efficiency of better parts for it
var/obj/item/weapon/melee/baton/B = charging
if(B.bcell)
- if(B.bcell.give(175))
+ if(B.bcell.give(175*charging_speed_modifier))
icon_state = "recharger1"
if(!self_powered)
- use_power(200)
+ use_power(200*charging_speed_modifier)
else
icon_state = "recharger2"
else
@@ -182,10 +223,10 @@
else if(istype(charging, /obj/item/weapon/rcs))
var/obj/item/weapon/rcs/rcs = charging
if(rcs.cell)
- if(rcs.cell.give(175))
+ if(rcs.cell.give(175*charging_speed_modifier))
icon_state = "recharger1"
if(!self_powered)
- use_power(200)
+ use_power(200*charging_speed_modifier)
else
icon_state = "recharger2"
else
@@ -208,11 +249,15 @@
..(severity)
/obj/machinery/recharger/update_icon() //we have an update_icon() in addition to the stuff in process to make it feel a tiny bit snappier.
+
if(charging)
overlays.len = 0
charging.update_icon()
overlays += charging.appearance
icon_state = "recharger1"
+ else if(!anchored)
+ overlays.len = 0
+ icon_state = "recharger4"
else
overlays.len = 0
icon_state = "recharger0"
@@ -225,6 +270,7 @@
icon = 'icons/obj/stationobjs.dmi'
icon_state = "wrecharger0"
+
/obj/machinery/recharger/wallcharger/process()
if(stat & (NOPOWER|BROKEN) || !anchored)
return
diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm
index 6b9c5e120b8..d68b4ee74d3 100644
--- a/code/game/machinery/rechargestation.dm
+++ b/code/game/machinery/rechargestation.dm
@@ -94,6 +94,7 @@
if(world.timeofday >= upgrade_finished && upgrade_finished != -1)
if(istype(upgrading, /obj/item/weapon/cell))
if(occupant:cell)
+ occupant:cell.updateicon()
occupant:cell.forceMove(get_turf(src))
upgrade_holder -= upgrading
upgrading:forceMove(occupant)
@@ -102,7 +103,7 @@
upgrading = 0
upgrade_finished = -1
to_chat(occupant, "Upgrade completed.")
- playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0)
+ playsound(src, 'sound/machines/ping.ogg', 50, 0)
/obj/machinery/recharge_station/attackby(var/obj/item/W, var/mob/living/user)
if(is_type_in_list(W, acceptable_upgradeables))
@@ -133,6 +134,9 @@
var/obj/removed = input(user, "Choose an item to remove.",upgrade_holder[1]) as null|anything in upgrade_holder
if(!removed || upgrading)
return
+ var/obj/item/weapon/cell/rcell = removed
+ if(istype(rcell))
+ rcell.updateicon()
user.put_in_hands(removed)
if(removed.loc == src)
removed.forceMove(get_turf(src))
diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm
index 4c6a124ae7d..c3be7a89613 100644
--- a/code/game/machinery/requests_console.dm
+++ b/code/game/machinery/requests_console.dm
@@ -255,6 +255,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
else
priority = -1
else
+ to_chat(usr, "Invalid characters found in the text.")
dpt = "";
msgVerified = ""
msgStamped = ""
@@ -271,6 +272,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
else
priority = -1
else
+ to_chat(usr, "Invalid characters found in the text.")
message = ""
announceAuth = 0
screen = 0
@@ -442,7 +444,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
to_chat(user, "You can't do much with that.")
if(iswrench(O) && open && !departmentType)
user.visible_message("[user] disassembles the [src]!", "You disassemble the [src]")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
new /obj/item/stack/sheet/metal (src.loc,2)
qdel(src)
return
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index 7407918dd0e..d911084f914 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -54,7 +54,7 @@
src.health -= aforce
//Play a fitting sound
- playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 75, 1)
+ playsound(src, 'sound/effects/EMPulse.ogg', 75, 1)
if (src.health <= 0)
@@ -124,7 +124,7 @@
src.health -= tforce
//This seemed to be the best sound for hitting a force field.
- playsound(get_turf(src), 'sound/effects/EMPulse.ogg', 100, 1)
+ playsound(src, 'sound/effects/EMPulse.ogg', 100, 1)
//Handle the destruction of the shield
if (src.health <= 0)
diff --git a/code/game/machinery/station_map.dm b/code/game/machinery/station_map.dm
index cd426af070d..60008b616de 100644
--- a/code/game/machinery/station_map.dm
+++ b/code/game/machinery/station_map.dm
@@ -54,7 +54,7 @@ var/list/station_holomaps = list()
if(do_after(user, src, 40))
user.visible_message( "[user] detaches \the [src] from the wall.",
"You detach \the [src] from the wall.")
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
new /obj/item/mounted/frame/station_map(src.loc)
for(var/obj/I in src)
diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index dbb4ab70f90..4e60f1a1ca0 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -428,7 +428,7 @@ var/global/list/status_display_images = list(
#undef MODE_BSOD
#undef CHARS_PER_LINE
-#undef FOND_SIZE
+#undef FONT_SIZE
#undef FONT_COLOR
#undef FONT_STYLE
#undef SCROLL_SPEED
diff --git a/code/game/machinery/suit_dispenser.dm b/code/game/machinery/suit_dispenser.dm
index 88b303e7f59..2eae8456aed 100644
--- a/code/game/machinery/suit_dispenser.dm
+++ b/code/game/machinery/suit_dispenser.dm
@@ -2,8 +2,21 @@
// SUIT DISPENSER UNIT ///////////////
//////////////////////////////////////
+#define SD_BUSY 1 // the dispenser is busy.
+#define SD_ONESUIT 2 // only one type of suit comes out of this dispenser.
+#define SD_NOGREED 4 // no-one is allowed more than one suit from this TYPE of dispenser unless emagged
+#define SD_UNLIMITED 8 // will not deplete amount when armour is taken
+
var/list/dispenser_presets = list()
+/datum/suit
+ var/name = "suit"
+ var/list/to_spawn = list()
+ var/amount = 0
+
+/datum/suit/custom
+ name = "custom"
+
/obj/machinery/suit_dispenser
name = "Suit Dispenser"
desc = "An industrial U-Tak-It Dispenser unit designed to fetch all kinds of space suits.."
@@ -11,111 +24,157 @@ var/list/dispenser_presets = list()
icon_state = "suitdispenser"
anchored = 1
density = 1
+ var/list/suits = list() // put your suit datums here!
+ var/datum/suit/one_suit
+ var/global/list/suit_distributed_to = list()
+ var/dispenser_flags = SD_NOGREED|SD_UNLIMITED
+ machine_flags = EMAGGABLE
+
+/obj/machinery/suit_dispenser/New()
+ if(!suit_distributed_to["[type]"] && (dispenser_flags & SD_NOGREED))
+ suit_distributed_to["[type]"] = list()
+ var/list/real_suits_list = list()
+ for(var/suit in suits)
+ var/datum/suit/S = new suit
+ real_suits_list[S.name] = S
+ if(one_suit)
+ one_suit = new one_suit
+ suits = real_suits_list
+ ..()
+
+/obj/machinery/suit_dispenser/attack_hand(var/mob/living/carbon/human/user)
+ if(!can_use(user))
+ return
+ dispenser_flags |= SD_BUSY
+ if(!(dispenser_flags & SD_ONESUIT))
+ var/suit_list = get_suit_list(user)
+ suit_list["CANCEL"] = "CANCEL"
+ var/choice = input("Choose your suit specialisation.", "Suit Dispenser") in suit_list
+ if(choice == "CANCEL")
+ return
+ dispense(suit_list[choice],user)
+ else
+ dispense(one_suit,user)
+/obj/machinery/suit_dispenser/proc/can_use(var/mob/living/carbon/human/user)
+ var/list/used_by = suit_distributed_to["[type]"]
+ if(!istype(user))
+ to_chat(user,"You can't use this!")
+ return 0
+ if((dispenser_flags & SD_BUSY))
+ to_chat(user,"Someone else is using this!")
+ return 0
+ if((dispenser_flags & SD_ONESUIT) && !one_suit.amount)
+ to_chat(user,"There's nothing in here!")
+ return 0
+ if ((dispenser_flags & SD_NOGREED) && (user in used_by) && !emagged)
+ to_chat(user,"You've already picked up your suit!")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ return 0
+ else if(emagged)
+ say("!'^&YouVE alreaDY pIC&$!Ked UP yOU%r Su^!it.")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 100, 0)
+ return 1
+ return 1
+
+/obj/machinery/suit_dispenser/proc/get_suit_list(var/mob/living/carbon/human/user)
+ return suits
+
+/obj/machinery/suit_dispenser/proc/dispense(var/datum/suit/S,var/mob/living/carbon/human/user,var/greet=TRUE)
+ if(!S.amount && !(dispenser_flags & SD_UNLIMITED))
+ to_chat(user,"There are no more [S.name] suits left!")
+ dispenser_flags &= ~SD_BUSY
+ return 1
+ else if(!(dispenser_flags & SD_UNLIMITED))
+ S.amount--
+ if((dispenser_flags & SD_NOGREED) && !emagged)
+ suit_distributed_to["[type]"] |= user
+ flick("suitdispenser-flick",src)
+ dispenser_flags |= SD_BUSY
+ sleep(17)
+ dispenser_flags &= ~SD_BUSY
+
+ var/turf/T = get_turf(src)
+ if(!(S && T)) // in case we got destroyed while we slept
+ return 1
+ for(var/O in S.to_spawn)
+ new O(T)
+ if(emagged)
+ emagged = FALSE
+ if(greet && user && !user.stat) // in case we got destroyed while we slept
+ to_chat(user,"[S.name] specialisation processed. Have a good day.")
+
+
+/obj/machinery/suit_dispenser/emag(var/mob/user)
+ if(!emagged)
+ emagged = TRUE
+ if(user)
+ user.visible_message("\The [user] slides a weird looking ID into \the [src], and sparks come flying out!","You temporarily short the safety mechanisms.")
+ playsound(src, pick(spark_sound), 75, 1)
+ spark(src,4)
+
+/obj/machinery/suit_dispenser/proc/promptfornum(var/mob/user)
+ var/num = input(user,"How many supplies would you like to add? (Set to -1 for infinite)","Suit Dispenser", null) as num|null
+ if(num == -1)
+ dispenser_flags |= SD_UNLIMITED
+ else return num
+
+////////////////////////////// ERT SUIT DISPENSERS ///////////////////////////
+
+
+/datum/suit/ert/security
+ name = "Security"
+ to_spawn = list(/obj/item/clothing/suit/space/ert/security,/obj/item/clothing/head/helmet/space/ert/security)
+
+/datum/suit/ert/medical
+ name = "Medical"
+ to_spawn = list(/obj/item/clothing/suit/space/ert/medical,/obj/item/clothing/head/helmet/space/ert/medical)
+
+/datum/suit/ert/engineer
+ name = "Engineering"
+ to_spawn = list(/obj/item/clothing/suit/space/ert/engineer,/obj/item/clothing/head/helmet/space/ert/engineer)
+
+/datum/suit/ert/commander
+ name = "Commander"
+ to_spawn = list(/obj/item/clothing/suit/space/ert/commander,/obj/item/clothing/head/helmet/space/ert/commander)
/obj/machinery/suit_dispenser/ert
desc = "An industrial U-Tak-It Dispenser unit designed to fetch all kinds of space suits. This one distribributes Emergency Responder space suits."
+ suits = list(/datum/suit/ert/security,/datum/suit/ert/medical,/datum/suit/ert/engineer)
-/obj/machinery/suit_dispenser/ert/attack_hand(var/mob/user)
+/obj/machinery/suit_dispenser/ert/can_use(var/mob/living/carbon/human/user)
+ if(!..())
+ return
if(sentStrikeTeams(TEAM_ERT))
- var/datum/striketeam/ert/team = sent_strike_teams[TEAM_ERT]
- if (user in response_team_members)
- if (user in distributed_ert_suits)
- to_chat(user,"You've already picked up your suit.")
- else
- if (user.key == team.leader_key)
- to_chat(user,"Identified as [user.real_name]. Here is your suit commander. Have a good day.")
-
- flick("suitdispenser-flick",src)
-
- sleep(17)
-
- if (user in distributed_ert_suits)
- return
-
- distributed_ert_suits |= user
-
- var/turf/T = get_turf(src)
-
- new /obj/item/clothing/suit/space/ert/commander(T)
- new /obj/item/clothing/head/helmet/space/ert/commander(T)
-
- else
- to_chat(user,"Identified as [user.real_name]. Please choose your suit specialization.")
-
- var/list/suit_list = list(
- "Security",
- "Medical",
- "Engineer",
- "CANCEL"
- )
-
- var/choice = input("Choose your suit specialization.", "Suit Dispenser") in suit_list
-
- if(choice == "CANCEL")
- return
-
- flick("suitdispenser-flick",src)
-
- sleep(17)
-
- if (user in distributed_ert_suits)
- return
-
- distributed_ert_suits |= user
-
- var/turf/T = get_turf(src)
-
- switch(choice)
- if("Security")
- new /obj/item/clothing/suit/space/ert/security(T)
- new /obj/item/clothing/head/helmet/space/ert/security(T)
- to_chat(user,"Security specialization processed. Have a good day.")
- if("Medical")
- new /obj/item/clothing/suit/space/ert/medical(T)
- new /obj/item/clothing/head/helmet/space/ert/medical(T)
- to_chat(user,"Medical specialization processed. Have a good day.")
- if("Engineer")
- new /obj/item/clothing/suit/space/ert/engineer(T)
- new /obj/item/clothing/head/helmet/space/ert/engineer(T)
- to_chat(user,"Engineer specialization processed. Have a good day.")
-
+ if(user in response_team_members)
+ return 1
else
to_chat(user,"Access Denied. You aren't part of the Emergency Response Team.")
else
to_chat(user,"Access Denied. No Emergency Response Team has been dispatched yet.")
+/obj/machinery/suit_dispenser/ert/attack_hand(var/mob/living/carbon/human/user)
+ var/list/used_by = suit_distributed_to["[type]"]
+ var/datum/striketeam/ert/team = sent_strike_teams[TEAM_ERT]
+ if (user.key == team.leader_key && !(user in used_by))
+ if(!can_use(user))
+ return
+ to_chat(user,"Identified as [user.real_name]. Have a good day, Commander!")
+ dispense(new /datum/suit/ert/commander,user,greet=FALSE)
+ else ..()
/obj/machinery/suit_dispenser/striketeam
icon_state = "suitdispenser-empty"
- var/preset = null
- var/used = 0
+ dispenser_flags = SD_ONESUIT
-/obj/machinery/suit_dispenser/striketeam/attack_hand(var/mob/user)
- if(!preset)
+/obj/machinery/suit_dispenser/striketeam/can_use(var/mob/living/carbon/human/user)
+ if(!..())
+ return
+ if(!one_suit)
to_chat(user,"Error. No presets have been set.")
return
-
- if(used)
- to_chat(user,"This dispenser must be reloaded by authorities in charge before you can use it again.")
- return
-
- used = 1
-
- var/list/items_to_spawn = dispenser_presets[preset]
-
- icon_state = "suitdispenser-open"
- flick("suitdispenser-once",src)
-
- sleep(17)
-
- var/turf/T = get_turf(src)
-
- for(var/i = 1 to items_to_spawn.len)
- var/spawntype = items_to_spawn[i]
- new spawntype(T)
-
+ return 1
/obj/machinery/suit_dispenser/striketeam/attack_ghost(var/mob/user)
if(isAdminGhost(user))
@@ -124,7 +183,7 @@ var/list/dispenser_presets = list()
"Choose a Preset",
)
- if (used)
+ if (one_suit && !one_suit.amount)
choices |= "Resupply"
choices |= "CANCEL"
@@ -135,27 +194,116 @@ var/list/dispenser_presets = list()
if("CANCEL")
return
if("Define Preset from items on top")
- var/list/items_on_top = list()
+ var/datum/suit/custom/preset = new
for (var/obj/item/I in get_turf(src))
- items_on_top += I.type
- if (items_on_top.len <= 0)
+ preset.to_spawn += I.type
+ if (!preset.to_spawn.len)
to_chat(user,"Error. No items on top of the dispenser. Place items on top of the dispenser to define them as presets.")
return
else
- var/preset_name = input(user,"[items_on_top.len] items found. Name your Preset","Suit Dispenser", null) as text|null
+ var/preset_name = input(user,"[preset.to_spawn.len] items found. Name your Preset","Suit Dispenser", null) as text|null
if (!preset_name)
+ qdel(preset)
return
- dispenser_presets[preset_name] = items_on_top
- if("Choose a Preset")
- if (dispenser_presets.len <= 0)
- to_chat(user,"Error. No presets have been set. Place items on top of the dispenser to define them as presets.")
- return
- var/no_preset = !preset
- preset = input(user,"Choose a Preset.", "Suit Dispenser") in dispenser_presets
- if (preset && no_preset)
+ preset.name = preset_name
+ dispenser_presets[preset_name] = preset
+ one_suit = preset
icon_state = "suitdispenser"
flick("suitdispenser-fill",src)
+ one_suit.amount = promptfornum(user)
+
+ if("Choose a Preset")
+ if (!dispenser_presets.len)
+ to_chat(user,"Error. No presets have been set. Place items on top of the dispenser to define them as presets.")
+ return
+ var/datum/suit/custom/preset = input(user,"Choose a Preset.", "Suit Dispenser") in dispenser_presets
+ if (preset && !one_suit)
+ icon_state = "suitdispenser"
+ flick("suitdispenser-fill",src)
+ one_suit = new /datum/suit/custom
+ one_suit.name = preset.name
+ one_suit.to_spawn = preset.to_spawn
+ one_suit.amount = promptfornum(user)
+
+
if("Resupply")
- used = 0
+ one_suit.amount = promptfornum(user)
icon_state = "suitdispenser"
flick("suitdispenser-resupply",src)
+
+
+////////////////// DORF FORT DISPENSER //////////////////
+// do NOT spawn this on the main map or I will SCREAM //
+
+/datum/suit/dorf/standard
+ name = "Standard"
+ to_spawn = list(/obj/item/clothing/head/helmet/space,/obj/item/clothing/suit/space)
+
+/datum/suit/dorf/security
+ name = "Security"
+ to_spawn = list(/obj/item/clothing/head/helmet/space/rig/security,/obj/item/clothing/suit/space/rig/security)
+
+/datum/suit/dorf/engineering
+ name = "Engineering"
+ to_spawn = list(/obj/item/clothing/head/helmet/space/rig,/obj/item/clothing/suit/space/rig)
+
+/datum/suit/dorf/medical
+ name = "Medical"
+ to_spawn = list(/obj/item/clothing/head/helmet/space/rig/medical,/obj/item/clothing/suit/space/rig/medical)
+
+/datum/suit/dorf/atmos
+ name = "Atmospherics Technician"
+ to_spawn = list(/obj/item/clothing/head/helmet/space/rig/atmos,/obj/item/clothing/suit/space/rig/atmos)
+
+/datum/suit/dorf/paramedic
+ name = "Paramedic"
+ to_spawn = list(/obj/item/clothing/head/helmet/space/paramedic,/obj/item/clothing/suit/space/paramedic)
+
+/datum/suit/dorf/mining
+ name = "Mining"
+ to_spawn = list(/obj/item/clothing/suit/space/rig/mining, /obj/item/clothing/head/helmet/space/rig/mining)
+
+/*/datum/suit/dorf/head
+ amount = 1
+
+/datum/suit/dorf/head/captain
+ name = "Captain"
+ to_spawn = (/obj/item/clothing/suit/armor/captain,/obj/item/clothing/head/helmet/space/capspace)
+
+/datum/suit/dorf/head/chiefengie
+ name = "Chief Engineer"
+ to_spawn = (/obj/item/clothing/suit/space/rig/elite,/obj/item/clothing/head/helmet/space/rig/elite,/obj/item/clothing/shoes/magboots/elite)*/
+
+
+/obj/machinery/suit_dispenser/dorf
+ desc = "An industrial U-Tak-It Dispenser unit designed to fetch all kinds of space suits. This one is specialised towards asteroid reclamation teams."
+ suits = list(/datum/suit/dorf/standard,/datum/suit/dorf/security,/datum/suit/dorf/engineering,/datum/suit/dorf/medical,/datum/suit/dorf/atmos,/datum/suit/dorf/paramedic)
+
+/obj/machinery/suit_dispenser/dorf/get_suit_list(var/mob/living/carbon/human/user)
+ if(emagged)
+ return suits
+ var/list/suit_list = list()
+ suit_list["Standard"] = suits["Standard"]
+ var/obj/item/weapon/card/id/card = user.get_id_card()
+ if(!card)
+ return suit_list
+ for(var/job in card.access)
+ switch(job)
+ if(access_brig)
+ suit_list["Security"] = suits["Security"]
+ if(access_medical)
+ suit_list["Medical"] = suits["Medical"]
+ if(access_mining)
+ suit_list["Mining"] = suits["Mining"]
+ if(access_paramedic)
+ suit_list["Paramedic"] = suits["Paramedic"]
+ if(access_atmospherics)
+ suit_list["Atmospherics Technician"] = suits["Atmospherics Technician"]
+ if(access_engine)
+ suit_list["Engineering"] = suits["Engineering"]
+ return suit_list
+
+/obj/machinery/suit_dispenser/standard
+ desc = "An industrial U-Tak-It Dispenser unit designed to fetch a specific mass produced suit."
+ dispenser_flags = SD_ONESUIT|SD_NOGREED|SD_UNLIMITED
+ one_suit = /datum/suit/dorf/standard
\ No newline at end of file
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 38dcd1c8259..ca1a754014a 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -311,7 +311,7 @@
protected = 1
if(!protected)
- playsound(get_turf(src), "sparks", 75, 1, -1)
+ playsound(src, "sparks", 75, 1, -1)
to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.")
return*/
else //welp, the guy is protected, we can continue
@@ -337,7 +337,7 @@
protected = 1
if(!protected)
- playsound(get_turf(src), "sparks", 75, 1, -1)
+ playsound(src, "sparks", 75, 1, -1)
to_chat(user, "You try to touch the controls but you get zapped. There must be a short circuit somewhere.")
return*/
else
@@ -579,7 +579,7 @@
stat &= !BROKEN
to_chat(user, "You repair the blown out electronics in the suit storage unit.")
if((stat & NOPOWER) && iscrowbar(I) && !islocked)
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You begin prying the equipment out of the suit storage unit")
if(do_after(user, src,20))
dump_everything()
diff --git a/code/game/machinery/telecomms/logbrowser.dm b/code/game/machinery/telecomms/logbrowser.dm
index 5fae300c11e..5391781fc0b 100644
--- a/code/game/machinery/telecomms/logbrowser.dm
+++ b/code/game/machinery/telecomms/logbrowser.dm
@@ -233,7 +233,7 @@
/obj/machinery/computer/telecomms/server/emag(mob/user)
if(!emagged)
- playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1)
+ playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
if(user)
to_chat(user, "You you disable the security protocols")
diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm
index 22b911fc334..ddbb11766f8 100644
--- a/code/game/machinery/telecomms/machine_interactions.dm
+++ b/code/game/machinery/telecomms/machine_interactions.dm
@@ -28,7 +28,7 @@
if (!S.remove_fuel(2, user))
to_chat(user, "You need more fuel.")
return
- playsound(get_turf(user), 'sound/items/Welder.ogg', 100, 1)
+ playsound(user, 'sound/items/Welder.ogg', 100, 1)
integrity = TELECOMMS_MAX_INTEGRITY
to_chat(user, "You repair the damaged internals of \the [src].")
updateUsrDialog()
@@ -224,7 +224,7 @@
var/obj/item/device/multitool/P = get_multitool(usr)
if(!istype(P))
- testing("get_multitool returned [P].")
+// testing("get_multitool returned [P].")
return
if(href_list["input"])
diff --git a/code/game/machinery/telecomms/multicaster.dm b/code/game/machinery/telecomms/multicaster.dm
new file mode 100644
index 00000000000..702253bcd71
--- /dev/null
+++ b/code/game/machinery/telecomms/multicaster.dm
@@ -0,0 +1,88 @@
+var/list/pda_multicasters = list()
+
+/obj/machinery/pda_multicaster
+ name = "\improper PDA multicaster"
+ desc = "Duplicates messages and sends copies to departments."
+ icon = 'icons/obj/machines/telecomms.dmi'
+ icon_state = "pda_server-on"
+ density = 1
+ anchored = 1
+ use_power = 1
+ idle_power_usage = 750
+ var/obj/item/device/pda/camo/CAMO
+ var/on = TRUE
+
+/obj/machinery/pda_multicaster/New()
+ ..()
+ CAMO = new(src)
+ pda_multicasters.Add(src)
+
+/obj/machinery/pda_multicaster/prebuilt/New()
+ ..()
+
+ component_parts = newlist(
+ /obj/item/weapon/circuitboard/pda_multicaster,
+ /obj/item/weapon/stock_parts/subspace/filter,
+ /obj/item/weapon/stock_parts/manipulator
+ )
+
+ RefreshParts()
+
+/obj/machinery/pda_multicaster/Destroy()
+ pda_multicasters.Remove(src)
+ if(CAMO)
+ qdel(CAMO)
+ CAMO = null
+ ..()
+
+/obj/machinery/pda_multicaster/update_icon()
+ if(stat & (BROKEN|NOPOWER|EMPED))
+ icon_state = "pda_server-nopower"
+ else
+ icon_state = "pda_server-[on ? "on" : "off"]"
+
+/obj/machinery/pda_multicaster/attack_hand(mob/user)
+ if(user.incapacitated() && !isAdminGhost(user))
+ return
+ toggle_power(user)
+
+/obj/machinery/pda_multicaster/proc/toggle_power(mob/user)
+ on = !on
+ visible_message("\the [user] turns \the [src] [on ? "on" : "off"].")
+ update_icon()
+
+/obj/machinery/pda_multicaster/proc/check_status()
+ return !(stat&(BROKEN|NOPOWER|EMPED))&&on
+
+/obj/machinery/pda_multicaster/proc/update_PDAs(var/turn_off)
+ for(var/obj/item/device/pda/pda in contents)
+ pda.toff = turn_off
+
+/obj/machinery/pda_multicaster/proc/multicast(var/target,var/obj/item/device/pda/sender,var/mob/living/U,var/message)
+ var/list/redirection_list = list(
+ "security" = list(/obj/item/device/pda/warden,/obj/item/device/pda/detective,/obj/item/device/pda/security,/obj/item/device/pda/heads/hos),
+ "engineering" = list(/obj/item/device/pda/engineering,/obj/item/device/pda/atmos,/obj/item/device/pda/heads/ce),
+ "medical" = list(/obj/item/device/pda/medical,/obj/item/device/pda/viro,/obj/item/device/pda/chemist,/obj/item/device/pda/geneticist,/obj/item/device/pda/heads/cmo),
+ "research" = list(/obj/item/device/pda/toxins,/obj/item/device/pda/roboticist,/obj/item/device/pda/mechanic,/obj/item/device/pda/heads/rd),
+ "cargo" = list(/obj/item/device/pda/cargo,/obj/item/device/pda/shaftminer,/obj/item/device/pda/quartermaster),
+ "service" = list(/obj/item/device/pda/botanist,/obj/item/device/pda/chef,/obj/item/device/pda/bar)
+ )
+
+ var/list/available_pdas = CAMO.available_pdas() //Let's not recalculate this every time.
+ for(var/element in available_pdas)
+ var/obj/item/device/pda/P = available_pdas[element]
+ if(is_type_in_list(P,redirection_list[target]))
+ CAMO.ownjob = "[sender.owner]"
+ CAMO.reply = sender
+ CAMO.create_message(U,P,message)
+
+/obj/item/device/pda/camo
+ name = "Centralized Autonomous Messaging Operator"
+ owner = "CAMO"
+ ownjob = "CAMO"
+ detonate = 0
+ hidden = 1
+
+/obj/item/device/pda/camo/create_message(var/mob/living/U,var/obj/item/device/pda/P,var/multicast_message = null)
+ ..()
+ last_text = 0 //CAMO can text as much as it pleases
diff --git a/code/game/machinery/telecomms/telemonitor.dm b/code/game/machinery/telecomms/telemonitor.dm
index 98d14d4a363..e248050f61e 100644
--- a/code/game/machinery/telecomms/telemonitor.dm
+++ b/code/game/machinery/telecomms/telemonitor.dm
@@ -211,7 +211,7 @@
/obj/machinery/computer/telecomms/monitor/emag(mob/user)
if(!emagged)
- playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1)
+ playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
if(user)
to_chat(user, "You you disable the security protocols")
diff --git a/code/game/machinery/telecomms/traffic_control.dm b/code/game/machinery/telecomms/traffic_control.dm
index fe56ceaecbc..49280c46a71 100644
--- a/code/game/machinery/telecomms/traffic_control.dm
+++ b/code/game/machinery/telecomms/traffic_control.dm
@@ -280,7 +280,7 @@
/obj/machinery/computer/telecomms/emag(mob/user)
if(!emagged)
- playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1)
+ playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
if(user)
to_chat(user, "You you disable the security protocols")
diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm
index 32573ae86de..a774e978190 100644
--- a/code/game/machinery/transformer.dm
+++ b/code/game/machinery/transformer.dm
@@ -65,14 +65,14 @@
return
if(!transform_dead && H.stat == DEAD)
- playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0)
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
return
if(jobban_isbanned(H, "Cyborg"))
src.visible_message("\The [src.name] throws an exception. Lifeform not compatible with factory.")
return
- playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
H.emote("scream",,, 1) // It is painful
H.adjustBruteLoss(max(0, 80 - H.getBruteLoss())) // Hurt the human, don't try to kill them though.
H.handle_regular_hud_updates() // Make sure they see the pain.
@@ -113,7 +113,7 @@
R.updatename()
spawn(50)
- playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 0)
+ playsound(src, 'sound/machines/ding.ogg', 50, 0)
if(R)
R.SetKnockdown(0)
@@ -129,7 +129,7 @@
if(cooldown_state!=old_cooldown_state)
update_icon()
if(!cooldown_state)
- playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0)
+ playsound(src, 'sound/machines/ping.ogg', 50, 0)
/obj/machinery/transformer/conveyor/New()
..()
diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm
index 9425fcbbbf7..9226e19bf3d 100644
--- a/code/game/machinery/turrets.dm
+++ b/code/game/machinery/turrets.dm
@@ -179,9 +179,9 @@
if(prob(15))
if(prob(50))
- playsound(get_turf(src), 'sound/effects/turret/move1.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/move1.wav', 60, 1)
else
- playsound(get_turf(src), 'sound/effects/turret/move2.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/move2.wav', 60, 1)
else if(!isPopping())//else, pop down
if(!isDown())
popDown()
@@ -244,7 +244,7 @@
if ((!isPopping()) || src.popping==-1)
invisibility = 0
popping = 1
- playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/open.wav', 60, 1)
if (src.cover!=null)
flick("popup", src.cover)
src.cover.icon_state = "openTurretCover"
@@ -255,7 +255,7 @@
/obj/machinery/turret/proc/popDown()
if ((!isPopping()) || src.popping==1)
popping = -1
- playsound(get_turf(src), 'sound/effects/turret/open.wav', 60, 1)
+ playsound(src, 'sound/effects/turret/open.wav', 60, 1)
if (src.cover!=null)
flick("popdown", src.cover)
src.cover.icon_state = "turretCover"
@@ -279,7 +279,7 @@
user.delayNextAttack(10)
if(..())
return 1
- playsound(get_turf(src), 'sound/weapons/smash.ogg', 60, 1)
+ playsound(src, 'sound/weapons/smash.ogg', 60, 1)
spark(src, 5, FALSE)
src.health -= W.force * 0.5
visible_message("[user] attacked \the [src] with \the [W]!")
@@ -433,7 +433,7 @@
/obj/machinery/turret/attack_alien(mob/living/carbon/alien/humanoid/M as mob)
if(!(stat & BROKEN))
M.do_attack_animation(src, M)
- playsound(get_turf(src), 'sound/weapons/slash.ogg', 25, 1, -1)
+ playsound(src, 'sound/weapons/slash.ogg', 25, 1, -1)
visible_message("[] has slashed at []!", M, src)
src.health -= 15
if (src.health <= 0)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index e4c3e9cbc7a..271198d9718 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -10,12 +10,26 @@ var/global/num_vending_terminals = 1
var/product_path = null
var/original_amount = 0
var/amount = 0
+ var/stack_amount = 0 //only used when we're dealing with /obj/item/stack
var/price = 0
var/display_color = "blue"
var/category = CAT_NORMAL//available by default, contraband, or premium (requires a coin)
var/subcategory = null
var/mini_icon = null
+//this proc is only used when an item is inserted into a custom vending machine.
+/datum/data/vending_product/proc/custom_entry(var/obj/item/item)
+ if(istype(item, /obj/item/stack))
+ var/obj/item/stack/S = item
+ stack_amount = S.amount
+ product_name = "A stack of [stack_amount] [item.name]"
+ else
+ product_name = item.name
+ mini_icon = costly_bicon(item)
+ display_color = pick("red", "blue", "green")
+ product_path = item
+ amount += 1
+
/* TODO: Add this to deconstruction for vending machines
/obj/item/compressed_vend
name = "compressed sale cartridge"
@@ -46,7 +60,10 @@ var/global/num_vending_terminals = 1
var/ads_chance = 50 // Chance of an ad appearing on screen
var/datum/data/vending_product/currently_vending = null // A /datum/data/vending_product instance of what we're paying for right now.
// To be filled out at compile time
- var/list/accepted_coins = list() // Accepted coins by the machine.
+ var/list/accepted_coins = list(
+ /obj/item/weapon/coin,
+ /obj/item/weapon/reagent_containers/food/snacks/chococoin
+ ) // Accepted coins by the machine.
var/list/products = list() // For each, use the following pattern:
var/list/contraband = list() // list(/type/path = amount,/type/path2 = amount2)
@@ -85,9 +102,12 @@ var/global/num_vending_terminals = 1
var/machine_id = "#"
- machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | PURCHASER | WIREJACK | SECUREDPANEL
+ machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | PURCHASER | WIREJACK
- var/account_first_linked = 0
+ var/account_first_linked = 1
+ var/inserting_mode = FALSE // insert items directly into the machine (used for custom vending machines)
+ var/is_custom_machine = FALSE // true if this vendor supports editing the prices
+ var/edit_mode = FALSE // Used for editing prices
var/is_being_filled = FALSE // `in_use` from /obj is already used for tracking users of this machine's UI
/obj/machinery/vending/cultify()
@@ -101,11 +121,6 @@ var/global/num_vending_terminals = 1
overlays_vending[1] = "[icon_state]-panel"
- accepted_coins = list(
- /obj/item/weapon/coin,
- /obj/item/weapon/reagent_containers/food/snacks/chococoin
- )
-
component_parts = newlist(\
/obj/item/weapon/circuitboard/vendomat,\
/obj/item/weapon/stock_parts/matter_bin,\
@@ -132,13 +147,20 @@ var/global/num_vending_terminals = 1
return
/obj/machinery/vending/initialize()
- ..()
+ build_inventories()
+ link_to_account()
+
+/obj/machinery/vending/proc/build_inventories()
product_records = new/list()
build_inventory(products)
build_inventory(contraband, 1)
build_inventory(premium, 0, 1)
build_inventory(vouched, 0, 0, 1)
+/obj/machinery/vending/proc/link_to_account()
+ reconnect_database()
+ linked_account = department_accounts["Cargo"]
+
/obj/machinery/vending/RefreshParts()
var/manipcount = 0
for(var/obj/item/weapon/stock_parts/SP in component_parts)
@@ -206,7 +228,7 @@ var/global/num_vending_terminals = 1
newmachine.product_records = P.product_records
newmachine.hidden_records = P.hidden_records
newmachine.coin_records = P.coin_records
- newmachine.initialize()
+ newmachine.build_inventories()
qdel(P)
if(user.machine==src)
newmachine.attack_hand(user)
@@ -230,7 +252,7 @@ var/global/num_vending_terminals = 1
if(do_after_many(user, list(src, P), 3 SECONDS))
to_chat(user, "[bicon(src)] You finish refilling the vending machine.")
playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
- if(check_for_custom_vendor())
+ if(is_custom_machine)
custom_refill(P, user)
else
normal_refill(P, user)
@@ -241,16 +263,6 @@ var/global/num_vending_terminals = 1
else
to_chat(user, "This recharge pack isn't meant for this kind of vending machines.")
-/obj/machinery/vending/proc/check_for_custom_vendor()
- //We check if there's an in-game object instead of a typepath inside the vending machine.
- for(var/item in products) //We only support the product list for the moment. This means no custom premium/contraband products
- if(!ispath(item))
- return TRUE
- if(!products.len)
- return TRUE
-
- return FALSE
-
/obj/machinery/vending/proc/normal_refill(obj/structure/vendomatpack/P, mob/user)
for (var/datum/data/vending_product/D in product_records)
D.amount = D.original_amount
@@ -275,7 +287,7 @@ var/global/num_vending_terminals = 1
I.forceMove(src)
products += P.stock
product_records += P.product_records
- initialize()
+ build_inventories()
getFromPool(/obj/item/stack/sheet/cardboard, P.loc, 4)
qdel(P)
@@ -326,9 +338,7 @@ var/global/num_vending_terminals = 1
R.original_amount = amount
R.price = price
R.display_color = pick("red", "blue", "green")
- var/is_custom = FALSE
- if(check_for_custom_vendor())
- is_custom = TRUE
+ if(is_custom_machine)
var/obj/O = R.product_path
R.price = O.price
R.product_name = "[O.name]"
@@ -347,7 +357,7 @@ var/global/num_vending_terminals = 1
product_records.Add(R)
var/obj/item/initializer = typepath
- if(!is_custom)
+ if(!is_custom_machine)
R.product_name = initial(initializer.name)
R.subcategory = initial(initializer.vending_cat)
@@ -365,12 +375,12 @@ var/global/num_vending_terminals = 1
// to_chat(world, "Added: [R.product_name]] - [R.amount] - [R.product_path]")
/obj/machinery/vending/emag(mob/user)
- if(!emagged)
+ if(!emagged || !extended_inventory || scan_id)
emagged = 1
- if(user)
- to_chat(user, "You short out the product lock on \the [src]")
+ extended_inventory = 1
+ scan_id = 0
return 1
- return -1 //Fucking gross
+ return 0 //Fucking gross
/obj/machinery/vending/npc_tamper_act(mob/living/L)
if(!panel_open)
@@ -413,14 +423,14 @@ var/global/num_vending_terminals = 1
return 1
/obj/machinery/vending/attackby(obj/item/W, mob/user)
- if(stat & (BROKEN))
+ if(stat & (BROKEN) && !iswrench(W))
if(istype(W, /obj/item/stack/sheet/glass/rglass))
var/obj/item/stack/sheet/glass/rglass/G = W
to_chat(user, "You replace the broken glass.")
G.use(1)
stat &= ~BROKEN
src.health = 100
- src.update_vicon()
+ power_change()
getFromPool(/obj/item/weapon/shard, loc)
else
to_chat(user, "The glass in \the [src] is broken! Fix it first.")
@@ -482,36 +492,69 @@ var/global/num_vending_terminals = 1
if(user.drop_item(W, src))
add_item(W)
src.updateUsrDialog()
- else if(istype(W, /obj/item/weapon/card))
- //attempt to connect to a new db, and if that doesn't work then fail
- if(linked_account)
- if(account_first_linked)
- if(!user.Adjacent(src))
- return 0
- var/account_try = input(user,"Please enter the already connected account number","Security measure") as num
- if(!user.Adjacent(src))
- return 0
- if(account_try != linked_account.account_number)
- to_chat(user, "[bicon(src)]Access denied. Your input doesn't match the vending machine's connected account.")
- return
- if(!user.Adjacent(src))
- return 0
- var/new_account = input(user,"Please enter the account to connect to.","New account link") as num
- if(!user.Adjacent(src))
- return 0
- for(var/datum/money_account/D in all_money_accounts)
- if(D.account_number == new_account)
- linked_account = D
- if(!account_first_linked)
- account_first_linked = 1
- playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0)
- to_chat(user, "[bicon(src)]New connection established: [D.owner_name].")
- return
- to_chat(user, "[bicon(src)]The specified account doesn't exist.")
-
+ else if(istype(W, /obj/item/weapon/card/emag))
+ visible_message("[usr] swipes a card through [src].")
+ to_chat(user, "You swipe \the [W] through [src]")
+ if (emag())
+ to_chat(user, "[src] responds with a soft beep.")
else
- to_chat(usr, "[bicon(src)]Unable to connect to linked account. Please contact a god.")
+ to_chat(user, "Nothing happens.")
+ else if(istype(W, /obj/item/weapon/card))
+ if(currently_vending) //We're trying to pay, not set the account
+ connect_account(user, W)
+ src.updateUsrDialog()
+ return
+ //attempt to connect to a new db, and if that doesn't work then fail
+ if(!linked_account)
+ connect_to_user_account(user)
+ return
+
+ if(account_first_linked)
+ if(!user.Adjacent(src))
+ return 0
+ var/account_try = input(user,"Please enter the already connected account number","Security measure") as num
+ if(!user.Adjacent(src))
+ return 0
+ if(account_try != linked_account.account_number)
+ to_chat(user, "[bicon(src)]Access denied. Your input doesn't match the vending machine's connected account.")
+ return 0
+ if(!user.Adjacent(src))
+ return 0
+ connect_to_user_account(user)
+ return
+
+ else if(istype(W, /obj/item/) && inserting_mode)
+ if(user.drop_item(W, src))
+ insert_item(W)
+
+/obj/machinery/vending/proc/connect_to_user_account(mob/user)
+ var/new_account = input(user,"Please enter the account to connect to.","New account link") as num
+ if(!user.Adjacent(src) || !new_account)
+ return FALSE
+ for(var/datum/money_account/D in all_money_accounts)
+ if(D.account_number == new_account)
+ linked_account = D
+ if(!account_first_linked)
+ account_first_linked = 1
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 0)
+ to_chat(user, "[bicon(src)]New connection established: [D.owner_name].")
+ return TRUE
+ to_chat(user, "[bicon(src)]The specified account doesn't exist.")
+ return FALSE
+
+/obj/machinery/vending/proc/insert_item(var/obj/item/item)
+ for(var/datum/data/vending_product/VP in product_records)
+ if(VP.product_path == item)
+ VP.amount += 1
+ if(istype(item, /obj/item/stack))
+ var/obj/item/stack/S = item
+ VP.product_name = "A stack of [S.amount] [S.name]"
+ return
+ var/datum/data/vending_product/R = new()
+ R.custom_entry(item)
+ product_records += R
+ products += item
//H.wear_id
/**
@@ -626,6 +669,8 @@ var/global/num_vending_terminals = 1
if (P.amount > 0)
var/idx=GetProductIndex(P)
dat += " (Vend)"
+ if (edit_mode)
+ dat += " (Set Price)"
else
dat += " SOLD OUT"
dat += " "
@@ -667,9 +712,7 @@ var/global/num_vending_terminals = 1
spawn(ticks)
- if(stat & (NOPOWER)) //Make another check just in case something goes weird
- stat &= ~NOPOWER
- src.update_vicon()
+ power_change()
/obj/machinery/vending/proc/update_vicon()
if(stat & (BROKEN))
@@ -801,6 +844,14 @@ var/global/num_vending_terminals = 1
if(product_slogans != "")
dat += "The speaker switch is [shut_up ? "off" : "on"]. Toggle"
+ dat += " "
+
+ if(is_custom_machine)
+ dat += "Insert items mode is [inserting_mode ? "on" : "off"]. Toggle"
+ dat += " "
+ dat += "The prices edit mode is [edit_mode ? "on" : "off"]. Toggle"
+ dat += "
"
+ dat += "Note: Remember to slide your ID on this machine if you don't want random people to change your prices."
user << browse(dat, "window=vending;size=400x[vertical]")
onclose(user, "vending")
@@ -825,11 +876,11 @@ var/global/num_vending_terminals = 1
var/cat=text2num(href_list["cat"])
var/datum/data/vending_product/R = GetProductByID(idx,cat)
if(R.price)
- can_vend = 0//all borgs can buy free items from vending machines
+ can_vend = FALSE //all borgs can buy free items from vending machines
if(istype(usr,/mob/living/silicon/robot))
var/mob/living/silicon/robot/R = usr
- if((R.module && istype(R.module,/obj/item/weapon/robot_module/butler) ) || isMoMMI(R))
- can_vend = 1//only service borgs and MoMMI can buy costly items
+ if((R.module && (R.module.quirk_flags & MODULE_CAN_BUY)))
+ can_vend = TRUE //But if their module allows it..
if(!can_vend)
to_chat(usr, "The vending machine refuses to interface with you, as you are not in its target demographic!")
return
@@ -876,21 +927,49 @@ var/global/num_vending_terminals = 1
return
+ else if (href_list["set_price"] && src.vend_ready && !currently_vending)
+ //testing("vend: [href]")
+
+ if (!allowed(usr) && !emagged && scan_id) //For SECURE VENDING MACHINES YEAH
+ to_chat(usr, "Access denied.")//Unless emagged of course
+
+ flick(src.icon_deny,src)
+ return
+
+ var/idx=text2num(href_list["set_price"])
+ var/cat=text2num(href_list["cat"])
+
+ var/datum/data/vending_product/R = GetProductByID(idx,cat)
+ if (!R || !istype(R) || !R.product_path || R.amount <= 0)
+ message_admins("Invalid vend request by [formatJumpTo(src.loc)]: [href]")
+ return
+
+ var/new_price = input("Enter a price", "Change price", R.price) as null|num
+ if(new_price == null || new_price < 0)
+ new_price = R.price
+ R.price = new_price
+
else if (href_list["cancel_buying"])
src.currently_vending = null
- src.updateUsrDialog()
- return
else if (href_list["buy"])
var/obj/item/weapon/card/card = usr.get_id_card()
if(card)
connect_account(usr, card)
- src.updateUsrDialog()
- return
+ else
+ to_chat(usr, "Please present a valid ID.")
else if ((href_list["togglevoice"]) && (src.panel_open))
src.shut_up = !src.shut_up
+ else if ((href_list["toggle_edit_mode"]))
+ if(is_custom_machine)
+ edit_mode = !edit_mode
+
+ else if ((href_list["toggle_insert_mode"]))
+ if(is_custom_machine)
+ inserting_mode = !inserting_mode
+
src.add_fingerprint(usr)
src.updateUsrDialog()
@@ -1058,7 +1137,13 @@ var/global/num_vending_terminals = 1
continue
R.amount--
- throw_item = new dump_path(src.loc)
+
+ if(is_custom_machine)
+ products.Remove(throw_item)
+ throw_item = dump_path
+ throw_item.forceMove(get_turf(src))
+ else
+ throw_item = new dump_path(src.loc)
if (!throw_item)
return 0
@@ -1278,9 +1363,11 @@ var/global/num_vending_terminals = 1
"Try our new jerky!"
)
icon_state = "snack"
+ icon_vend = "snack-vend"
+ vend_delay = 25
products = list(
/obj/item/weapon/reagent_containers/food/snacks/candy = 6,
- /obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 6,
+ /obj/item/weapon/reagent_containers/food/drinks/dry_ramen/heating = 6,
/obj/item/weapon/reagent_containers/food/snacks/chips =6,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 6,
/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 6,
@@ -1297,7 +1384,7 @@ var/global/num_vending_terminals = 1
)
prices = list(
/obj/item/weapon/reagent_containers/food/snacks/candy = 13,
- /obj/item/weapon/reagent_containers/food/drinks/dry_ramen = 15,
+ /obj/item/weapon/reagent_containers/food/drinks/dry_ramen/heating = 15,
/obj/item/weapon/reagent_containers/food/snacks/chips = 30,
/obj/item/weapon/reagent_containers/food/snacks/sosjerky = 40,
/obj/item/weapon/reagent_containers/food/snacks/no_raisin = 60,
@@ -1315,6 +1402,8 @@ var/global/num_vending_terminals = 1
name = "\improper Robust Softdrinks"
desc = "A softdrink vendor provided by Robust Industries, LLC."
icon_state = "Cola_Machine"
+ icon_vend = "Cola_Machine-vend"
+ vend_delay = 11
product_slogans = list(
"Robust Softdrinks: More robust than a toolbox to the head!",
"At least we aren't Dan!"
@@ -1395,6 +1484,7 @@ var/global/num_vending_terminals = 1
product_slogans = list("Carts to go!")
icon_state = "cart"
icon_deny = "cart-deny"
+ icon_vend = "cart-vend"
products = list(
/obj/item/weapon/cartridge/captain = 3,
/obj/item/weapon/cartridge/hop = 3,
@@ -1441,6 +1531,8 @@ var/global/num_vending_terminals = 1
"Award-winning cigs."
)
icon_state = "cigs"
+ icon_vend = "cigs-vend"
+ vend_delay = 21
products = list(
/obj/item/weapon/storage/fancy/cigarettes = 10,
/obj/item/weapon/storage/fancy/matchbox = 10,
@@ -1467,6 +1559,8 @@ var/global/num_vending_terminals = 1
req_access = list(access_medical)
icon_state = "med"
icon_deny = "med-deny"
+ icon_vend = "med-vend"
+ vend_delay = 18
product_ads = list(
"Go save some lives!",
"The best stuff for your medbay.",
@@ -1506,6 +1600,11 @@ var/global/num_vending_terminals = 1
pack = /obj/structure/vendomatpack/medical
+/obj/machinery/vending/medical/New()
+ ..()
+ if(map.nameShort == "deff")
+ icon = 'maps/defficiency/medbay.dmi'
+
//This one's from bay12
/obj/machinery/vending/plasmaresearch
name = "\improper Toximate 3000"
@@ -1590,7 +1689,7 @@ var/global/num_vending_terminals = 1
if(do_after(user, src, 40))
user.visible_message( "[user] detaches the NanoMed from the wall.",
"You detach the NanoMed from the wall.")
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
new /obj/item/mounted/frame/wallmed(src.loc)
for(var/obj/I in src)
@@ -1608,7 +1707,7 @@ var/global/num_vending_terminals = 1
if(do_after(user, src, 40))
user.visible_message( "[user] detaches the NanoMed from the wall.",
"You detach the NanoMed from the wall.")
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
new /obj/item/mounted/frame/wallmed(src.loc)
for(var/obj/I in src)
@@ -1651,7 +1750,7 @@ var/global/num_vending_terminals = 1
to_chat(usr, "You begin removing screws from \the [src] backplate...")
if(do_after(user, src, 50))
to_chat(usr, "You unscrew \the [src] from the wall.")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
new /obj/item/mounted/frame/wallmed(get_turf(src))
qdel(src)
return 1
@@ -1665,7 +1764,7 @@ var/global/num_vending_terminals = 1
if(user.drop_item(C, src))
to_chat(usr, "You secure \the [C]!")
_circuitboard=C
- playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
+ playsound(src, 'sound/effects/pop.ogg', 50, 0)
build++
update_icon()
return 1
@@ -1673,7 +1772,7 @@ var/global/num_vending_terminals = 1
if(iscrowbar(W))
to_chat(usr, "You begin to pry out \the [W] into \the [src].")
if(do_after(user, src, 10))
- playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
+ playsound(src, 'sound/effects/pop.ogg', 50, 0)
build--
update_icon()
var/obj/item/weapon/circuitboard/C
@@ -1690,7 +1789,7 @@ var/global/num_vending_terminals = 1
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C=W
to_chat(user, "You start adding cables to \the [src]...")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src, 20) && C.amount >= 5)
C.use(5)
build++
@@ -1711,7 +1810,7 @@ var/global/num_vending_terminals = 1
return 1
if(isscrewdriver(W))
to_chat(user, "You begin to complete \the [src]...")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, src, 20))
if(!_circuitboard)
_circuitboard=new boardtype(src)
@@ -1724,7 +1823,7 @@ var/global/num_vending_terminals = 1
if(3) // Waiting for a recharge pack
if(isscrewdriver(W))
to_chat(user, "You begin to unscrew \the [src]...")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, src, 30))
build--
update_icon()
@@ -1777,6 +1876,8 @@ var/global/num_vending_terminals = 1
)
icon_state = "sec"
icon_deny = "sec-deny"
+ icon_vend = "sec-vend"
+ vend_delay = 14
products = list(
/obj/item/weapon/handcuffs = 8,
/obj/item/weapon/grenade/flashbang = 4,
@@ -1786,7 +1887,7 @@ var/global/num_vending_terminals = 1
/obj/item/weapon/legcuffs/bolas = 8,
)
contraband = list(
- /obj/item/clothing/glasses/sunglasses = 2,
+ /obj/item/clothing/glasses/sunglasses/security = 2,
/obj/item/weapon/storage/fancy/donut_box = 2,
)
premium = list(
@@ -1834,6 +1935,8 @@ var/global/num_vending_terminals = 1
)
icon_state = "nutri"
icon_deny = "nutri-deny"
+ icon_vend = "nutri-vend"
+ vend_delay = 26
products = list(
/obj/item/weapon/reagent_containers/food/snacks/beezeez = 20,
/obj/item/weapon/reagent_containers/glass/fertilizer/ez = 35,
@@ -1866,6 +1969,8 @@ var/global/num_vending_terminals = 1
"Aw h'yeah son!"
)
icon_state = "seeds"
+ icon_vend = "seeds-vend"
+ vend_delay = 13
products = list(
/obj/item/seeds/bananaseed = 3,
/obj/item/seeds/berryseed = 3,
@@ -1939,7 +2044,7 @@ var/global/num_vending_terminals = 1
/obj/item/seeds/aloe = 3,
/obj/item/seeds/pitcher = 3,
/obj/item/seeds/vaporsac = 3,
- /obj/item/seeds/dionanode = 3
+ /obj/item/seeds/mushroommanspore = 3
)
contraband = list(
/obj/item/seeds/eggyseed = 2,
@@ -2022,6 +2127,7 @@ var/global/num_vending_terminals = 1
"You don't really need these..."
)
icon_state = "dinnerware"
+ icon_vend = "dinnerware-vend"
products = list(
/obj/item/weapon/tray = 8,
/obj/item/weapon/kitchen/utensil/fork = 6,
@@ -2050,6 +2156,7 @@ var/global/num_vending_terminals = 1
name = "\improper BODA"
desc = "An old vending machine containing sweet water."
icon_state = "sovietsoda"
+ icon_vend = "sovietsoda-vend"
product_slogans = list(
"BODA: We sell drink.",
"BODA: Drink today.",
@@ -2084,7 +2191,8 @@ var/global/num_vending_terminals = 1
//req_access = list(access_maint_tunnels)
icon_state = "tool"
icon_deny = "tool-deny"
-
+ icon_vend = "tool-vend"
+ vend_delay = 11
products = list(
/obj/item/stack/cable_coil/random = 10,
/obj/item/weapon/crowbar = 5,
@@ -2113,6 +2221,8 @@ var/global/num_vending_terminals = 1
req_access = list(access_engine_equip)//Engineering Equipment access
icon_state = "engivend"
icon_deny = "engivend-deny"
+ icon_vend = "engivend-vend"
+ vend_delay = 21
products = list(
/obj/item/clothing/glasses/scanner/meson = 2,
/obj/item/clothing/glasses/scanner/material = 2,
@@ -2128,7 +2238,6 @@ var/global/num_vending_terminals = 1
/obj/item/device/holomap = 2,
/obj/item/weapon/reagent_containers/glass/bottle/sacid = 3,
/obj/item/blueprints/construction_permit = 4, // permits
- /obj/item/vaporizer = 2,
)
contraband = list(
/obj/item/weapon/cell/potato = 3,
@@ -2179,28 +2288,6 @@ var/global/num_vending_terminals = 1
pack = /obj/structure/vendomatpack/building
-/obj/item/stack/sheet/metal/bigstack/New()
- getFromPool(/obj/item/stack/sheet/metal, loc, 20)
- qdel(src)
-/obj/item/stack/sheet/glass/glass/bigstack/New()
- getFromPool(/obj/item/stack/sheet/glass/glass, loc, 20)
- qdel(src)
-/obj/item/stack/sheet/glass/plasmaglass/bigstack/New()
- getFromPool(/obj/item/stack/sheet/glass/plasmaglass, loc, 20)
- qdel(src)
-/obj/item/stack/sheet/wood/bigstack/New()
- getFromPool(/obj/item/stack/sheet/wood, loc, 20)
- qdel(src)
-/obj/item/stack/tile/carpet/bigstack/New()
- getFromPool(/obj/item/stack/tile/carpet, loc, 20)
- qdel(src)
-/obj/item/stack/tile/arcade/bigstack/New()
- getFromPool(/obj/item/stack/tile/arcade, loc, 20)
- qdel(src)
-/obj/item/stack/sheet/mineral/plastic/bigstack/New()
- getFromPool(/obj/item/stack/sheet/mineral/plastic, loc, 20)
- qdel(src)
-
//This one's from bay12
/obj/machinery/vending/engineering
name = "\improper Robco Tool Maker"
@@ -2399,6 +2486,7 @@ var/global/num_vending_terminals = 1
/obj/item/clothing/under/franksuit = 3,
/obj/item/clothing/gloves/frankgloves = 3,
/obj/item/clothing/shoes/frankshoes =3,
+ /obj/item/clothing/suit/kimono/sakura = 3
) //Pretty much everything that had a chance to spawn.
contraband = list(
/obj/item/clothing/suit/cardborg = 3,
@@ -2426,7 +2514,8 @@ var/global/num_vending_terminals = 1
/obj/item/clothing/under/darkholme = 3,
/obj/item/clothing/suit/wizrobe/magician/fake = 3,
/obj/item/clothing/head/wizard/magician = 3,
- /obj/item/clothing/suit/sakura_kimono = 3,
+ /obj/item/clothing/suit/kimono = 3,
+ /obj/item/clothing/gloves/white = 3,
)
pack = /obj/structure/vendomatpack/autodrobe
@@ -2867,6 +2956,7 @@ var/global/num_vending_terminals = 1
/obj/item/clothing/head/clockwork_hood = 2,
/obj/item/clothing/suit/clockwork_robes = 2,
/obj/item/clothing/shoes/clockwork_boots = 2,
+ /obj/item/clothing/suit/kimono/ronin = 2
)
premium = list(
/obj/item/weapon/reagent_containers/food/drinks/bottle/holywater = 1,
@@ -2891,35 +2981,40 @@ var/global/num_vending_terminals = 1
/obj/item/weapon/storage/fancy/donut_box = 2,
/obj/item/clothing/suit/storage/trader = 3,
/obj/item/device/pda/trader = 3,
- /obj/item/weapon/capsule = 60
+ /obj/item/weapon/capsule = 60,
+ /obj/item/weapon/implantcase/peace = 5,
+ /obj/item/vaporizer = 1,
)
prices = list(
/obj/item/clothing/suit/storage/trader = 100,
/obj/item/device/pda/trader = 100,
- /obj/item/weapon/capsule = 10
+ /obj/item/weapon/capsule = 10,
+ /obj/item/weapon/implantcase/peace = 100,
+ /obj/item/vaporizer = 100
)
accepted_coins = list(/obj/item/weapon/coin/trader)
premium = list(
- /obj/item/weapon/storage/trader_marauder,
- //obj/item/weapon/storage/backpack/holding, //Players did exactly what you would expect and bought them for their own use. Keep in mind that an obj should be good but not so good they want it for themselves
+ /obj/item/weapon/storage/trader_chemistry,
+ /obj/structure/closet/secure_closet/wonderful,
+ /obj/item/weapon/disk/shuttle_coords/vault/mecha_graveyard,
/obj/item/weapon/reagent_containers/glass/beaker/bluespace,
/obj/item/weapon/storage/bluespace_crystal,
- //obj/item/clothing/shoes/magboots/elite,
/obj/item/weapon/reagent_containers/food/snacks/borer_egg,
- /obj/item/weapon/reagent_containers/glass/bottle/peridaxon,
- /obj/item/weapon/reagent_containers/glass/bottle/rezadone,
- /obj/item/weapon/reagent_containers/glass/bottle/nanobotssmall,
/obj/item/clothing/shoes/clown_shoes/advanced,
+ /obj/item/fish_eggs/seadevil,
+ /obj/machinery/power/antiquesynth,
)
/obj/machinery/vending/trader/New()
- premium.Add(pick(existing_typesof(/obj/item/borg/upgrade) - /obj/item/borg/upgrade/magnetic_gripper)) //A random borg upgrade minus the magnetic gripper. Time to jew the silicons!
-
for(var/random_items = 1 to premium.len - 5)
premium.Remove(pick(premium))
+ if(premium.Find(/obj/item/weapon/disk/shuttle_coords/vault/mecha_graveyard))
+ load_dungeon(/datum/map_element/dungeon/mecha_graveyard)
+ premium.Add(pick(existing_typesof(/obj/item/borg/upgrade) - /obj/item/borg/upgrade/magnetic_gripper)) //A random borg upgrade minus the magnetic gripper. Time to jew the silicons!
+
..()
/obj/machinery/vending/barber
@@ -3045,13 +3140,19 @@ var/global/num_vending_terminals = 1
name = "Sales"
desc = "Buy, sell, repeat."
icon_state = "sale"
+ is_custom_machine = TRUE
//vend_reply = "Insert another joke here"
//product_ads = "Another joke here"
//product_slogans = "Jokes"
+ account_first_linked = 0
+ machine_flags = SCREWTOGGLE | WRENCHMOVE | FIXED2WORK | CROWDESTROY | EJECTNOTDEL | PURCHASER | WIREJACK | SECUREDPANEL
products = list()
pack = /obj/structure/vendomatpack/custom
+/obj/machinery/vending/sale/link_to_account()
+ return
+
/obj/machinery/vending/toggleSecuredPanelOpen(var/obj/toggleitem, var/mob/user)
if(!account_first_linked)
togglePanelOpen(toggleitem, user)
@@ -3126,15 +3227,3 @@ var/global/num_vending_terminals = 1
)
pack = /obj/structure/vendomatpack/mining
-
-//Note : Snowflake, but I don't care. Rework the fucking economy
-/obj/machinery/vending/mining/New()
- ..()
-
- if(ticker)
- initialize()
-
-/obj/machinery/vending/mining/initialize()
- ..()
-
- linked_account = department_accounts["Cargo"]
diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm
index 6364e1411d9..f088d916a1a 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -92,6 +92,9 @@
else
icon_state = initial_icon
+/obj/mecha/combat/gygax/dark/stopMechWalking()
+ icon_state = initial_icon
+
/obj/mecha/combat/gygax/dyndomove(direction)
if(!..())
return
@@ -125,4 +128,4 @@
..()
if (href_list["toggle_leg_overload"])
src.overload()
- return
\ No newline at end of file
+ return
diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm
index 9102bc7c913..26c5fbcd1b9 100644
--- a/code/game/mecha/equipment/mecha_equipment.dm
+++ b/code/game/mecha/equipment/mecha_equipment.dm
@@ -125,7 +125,7 @@
/obj/item/mecha_parts/mecha_equipment/Topic(href,href_list)
if(usr.incapacitated() || usr != chassis.occupant)
return TRUE
- testing("[src] topic")
+// testing("[src] topic")
if(href_list["detach"])
detach()
return
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 624f07a661f..75635efef0f 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -613,7 +613,7 @@
to_chat(user, "\The [C] needs at least two wrists before you can cuff them together!")
return
- playsound(get_turf(src), 'sound/weapons/handcuffs.ogg', 30, 1, -2)
+ playsound(src, 'sound/weapons/handcuffs.ogg', 30, 1, -2)
user.visible_message("\The [M] is trying to handcuff \the [C]!",
"You try to handcuff \the [C]!")
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index e6f1d81e2ce..dad34ffb84e 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -21,7 +21,7 @@
layer = MOB_LAYER //icon draw layer
plane = MOB_PLANE
infra_luminosity = 15 //byond implementation is bugged.
- var/hud_list[2]
+ var/list/hud_list = list()
var/initial_icon = null //Mech type for resetting icon. Only used for reskinning kits (see custom items)
var/can_move = 1
var/mob/living/carbon/occupant = null
@@ -111,8 +111,45 @@
/obj/mecha/Destroy()
src.go_out(loc, TRUE)
mechas_list -= src //global mech list
+ if(cell)
+ qdel(cell)
+ cell = null
+ if(internal_tank)
+ qdel(internal_tank)
+ internal_tank = null
+ if(cabin_air)
+ qdel(cabin_air)
+ cabin_air = null
+ connected_port = null
+ if(radio)
+ qdel(radio)
+ radio = null
+ if(electropack)
+ qdel(electropack)
+ electropack = null
+ if(tracking)
+ qdel(tracking)
+ tracking = null
+ if(pr_int_temp_processor)
+ qdel(pr_int_temp_processor)
+ pr_int_temp_processor = null
+ if(pr_inertial_movement)
+ qdel(pr_inertial_movement)
+ pr_inertial_movement = null
+ if(pr_give_air)
+ qdel(pr_give_air)
+ pr_give_air = null
+ if(pr_internal_damage)
+ qdel(pr_internal_damage)
+ pr_internal_damage = null
+ for(var/obj/item/mecha_parts/mecha_equipment/eq in equipment)
+ qdel(eq)
+ equipment = null
+ selected = null
+ if(events)
+ qdel(events)
+ events = null
..()
- return
/obj/mecha/can_apply_inertia()
return 1 //No anchored check - so that mechas can fly off into space
@@ -552,12 +589,12 @@
if(!prob(src.deflect_chance))
src.take_damage(15)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
to_chat(user, "You slash at the armored suit!")
visible_message("The [user] slashes at [src.name]'s armor!")
else
src.log_append_to_last("Armor saved.")
- playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
to_chat(user, "Your claws had no effect!")
src.occupant_message("The [user]'s claws are stopped by the armor.")
visible_message("The [user] rebounds off [src.name]'s armor!")
@@ -579,7 +616,7 @@
user.attack_log += text("\[[time_stamp()]\] attacked [src.name]")
else
src.log_append_to_last("Armor saved.")
- playsound(get_turf(src), 'sound/weapons/slash.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/slash.ogg', 50, 1, -1)
src.occupant_message("The [user]'s attack is stopped by the armor.")
visible_message("The [user] rebounds off [src.name]'s armor!")
user.attack_log += text("\[[time_stamp()]\] attacked [src.name]")
@@ -710,14 +747,14 @@
if(!prob(src.deflect_chance))
src.take_damage(6)
src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST))
- playsound(get_turf(src), 'sound/effects/blobattack.ogg', 50, 1, -1)
+ playsound(src, 'sound/effects/blobattack.ogg', 50, 1, -1)
to_chat(user, "You smash at the armored suit!")
for (var/mob/V in viewers(src))
if(V.client && !(V.blinded))
V.show_message("The [user] smashes against [src.name]'s armor!", 1)
else
src.log_append_to_last("Armor saved.")
- playsound(get_turf(src), 'sound/effects/blobattack.ogg', 50, 1, -1)
+ playsound(src, 'sound/effects/blobattack.ogg', 50, 1, -1)
to_chat(user, "Your attack had no effect!")
src.occupant_message("The [user]'s attack is stopped by the armor.")
for (var/mob/V in viewers(src))
@@ -788,7 +825,7 @@
if(user.drop_item(W))
E.attach(src)
user.visible_message("[user] attaches [W] to [src]", "You attach [W] to [src]")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
else
to_chat(user, "You were unable to attach [W] to [src]")
return
@@ -839,7 +876,7 @@
if ("electropack")
electropack.forceMove(src.loc)
electropack = null
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "You pry out \the [remove] from \the [src].")
src.log_message("Internal component removed - [remove]")
return
@@ -2024,7 +2061,7 @@
var/transfer_moles = 0
if(pressure_delta > 0) //cabin pressure lower than release pressure
if(tank_air.return_temperature() > 0)
- transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
+ transfer_moles = pressure_delta * cabin_air.return_volume() / (cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = tank_air.remove(transfer_moles)
cabin_air.merge(removed)
else if(pressure_delta < 0) //cabin pressure higher than release pressure
@@ -2033,7 +2070,7 @@
if(t_air)
pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta)
if(pressure_delta > 0) //if location pressure is lower than cabin pressure
- transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
+ transfer_moles = pressure_delta * cabin_air.return_volume() / (cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION)
var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles)
if(t_air)
t_air.merge(removed)
diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm
index 48e82dfb601..b9868af56d0 100644
--- a/code/game/objects/effects/aliens.dm
+++ b/code/game/objects/effects/aliens.dm
@@ -498,7 +498,7 @@
status = GROWN
new /obj/item/clothing/mask/facehugger(src)
- for(var/mob/M in range(2,src))
+ for(var/mob/living/M in range(2,src))
if(CanHug(M))
Burst(0)
break
@@ -519,10 +519,10 @@
return
child.forceMove(loc)
if(kill && istype(child))
- child.Die()
+ child.death()
else
for(var/mob/M in range(1,src))
- if(CanHug(M))
+ if(CanHug(M, child))
child.Attach(M)
break
if(!ismob(child.loc))
@@ -573,11 +573,12 @@
/obj/effect/alien/egg/HasProximity(atom/movable/AM as mob|obj)
if(status == GROWN)
- if(!CanHug(AM))
+ if(!isliving(AM))
return
-
- var/mob/living/carbon/C = AM
- if(C.stat == CONSCIOUS && C.status_flags & XENO_HOST)
+ var/mob/living/L = AM
+ if(!CanHug(L))
+ return
+ if(L.isUnconscious())
return
Burst(0)
diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm
index 85d1aa0ce2e..1e427a8f405 100644
--- a/code/game/objects/effects/decals/Cleanable/misc.dm
+++ b/code/game/objects/effects/decals/Cleanable/misc.dm
@@ -223,4 +223,10 @@
name = "rune"
desc = "Looks unfinished."
icon = 'icons/obj/wizard.dmi'
- icon_state = "wizrune"
\ No newline at end of file
+ icon_state = "wizrune"
+
+/obj/effect/decal/cleanable/smashed_butter
+ name = "smashed butter"
+ desc = "Looks like some one has butter fingers."
+ icon = 'icons/effects/tomatodecal.dmi'
+ icon_state = "smashed_butter"
\ No newline at end of file
diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm
index 9490561224f..f2a180ec32c 100644
--- a/code/game/objects/effects/effect_system.dm
+++ b/code/game/objects/effects/effect_system.dm
@@ -446,7 +446,8 @@ steam.start() -- spawns the effect
n = 20
number = n
cardinals = c
- carry.copy_to(chemholder, carry.total_volume)
+ if(carry)
+ carry.copy_to(chemholder, carry.total_volume)
if(istype(loca, /turf/))
@@ -747,8 +748,8 @@ steam.start() -- spawns the effect
var/datum/gas_mixture/old_air = T.return_air()
savedtemp = old_air.temperature
if(istype(T) && savedtemp > lowest_temperature)
- var/datum/gas_mixture/lowertemp = T.remove_air( T:air:total_moles() / T.air.volume * CELL_VOLUME )
- lowertemp.temperature = max( min(lowertemp.temperature-500,lowertemp.temperature / 2) ,0)
+ var/datum/gas_mixture/lowertemp = old_air.remove_volume(CELL_VOLUME)
+ lowertemp.temperature = max(min(lowertemp.temperature - 500, lowertemp.temperature / 2), 0)
lowertemp.react()
T.assume_air(lowertemp)
spawn(3)
@@ -759,9 +760,9 @@ steam.start() -- spawns the effect
var/turf/simulated/T = get_turf(src)
var/datum/gas_mixture/local_air = T.return_air()
flick("[icon_state]-disolve", src)
- if((local_air.temperature < lowest_temperature)&&(savedtemp > lowest_temperature)) //ie, we have over-chilled
+ if((local_air.temperature < lowest_temperature) && (savedtemp > lowest_temperature)) //ie, we have over-chilled
local_air.temperature = lowest_temperature
- else if ((local_air.temperature < lowest_temperature)&&(savedtemp < lowest_temperature) && savedtemp) //ie it chilled when it shouldn't have
+ else if((local_air.temperature < lowest_temperature) && (savedtemp < lowest_temperature) && savedtemp) //ie it chilled when it shouldn't have
local_air.temperature = savedtemp
sleep(5)
qdel(src)
@@ -980,6 +981,7 @@ steam.start() -- spawns the effect
icon_regular_floor = "foamedmetal"
icon_plating = "foamedmetal"
can_exist_under_lattice = 1
+ plane = PLATING_PLANE
/turf/simulated/floor/foamedmetal/attack_hand(mob/living/user as mob)
user.delayNextAttack(10)
diff --git a/code/game/objects/effects/fire_blast.dm b/code/game/objects/effects/fire_blast.dm
index 1c7c9412fce..a2ab1ea8ab6 100644
--- a/code/game/objects/effects/fire_blast.dm
+++ b/code/game/objects/effects/fire_blast.dm
@@ -101,8 +101,10 @@
for(var/obj/effect/E in get_turf(A))
if(istype(E, /obj/effect/blob))
var/obj/effect/blob/B = E
- B.health -= (adjusted_fire_damage/10)
+ B.health -= (adjusted_fire_damage/2)
B.update_icon()
+ B.update_health()
+
var/turf/T2 = get_turf(src)
T2.hotspot_expose((blast_temperature * 2) + 380,500)
sleep(2)
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 34358ab8730..435c3207de9 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -15,7 +15,7 @@
/obj/effect/mine/Crossed(mob/living/carbon/AM)
if(istype(AM))
- visible_message("[AM] triggered the [bicon(src)] [src]")
+ visible_message("[AM] triggered \the [bicon(src)] [src]")
trigger(AM)
/obj/effect/mine/proc/trigger(mob/living/carbon/AM)
@@ -65,7 +65,7 @@
var/datum/gas_mixture/payload = new
var/datum/gas/sleeping_agent/trace_gas = new
- trace_gas.moles = 30
+ trace_gas.moles = 187 // total mols of a n2o canister 1870.81
payload += trace_gas
target.zone.air.merge(payload)
@@ -77,6 +77,6 @@
/obj/effect/mine/stun/trigger(mob/AM)
if(ismob(AM))
- AM.Stun(30)
+ AM.Knockdown(10)
spark(src)
- qdel(src)
+ qdel(src)
\ No newline at end of file
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index 23c3890212f..59153796a8d 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -114,11 +114,18 @@
M.take_organ_damage(2) // Was 5 -- TLE
M.visible_message("[M] slips on the floor!", \
"You slip on the floor!")
- playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3)
+ playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
M.Knockdown(10)
if(3) // Ice
if(prob(30) && M.Slip(4, 3))
step(M, M.dir)
M.visible_message("[M] slips on the icy floor!", \
- "You slip on the icy floor!")
\ No newline at end of file
+ "You slip on the icy floor!")
+
+ if(isrobot(AM) && wet == 1) //Only exactly water makes borgs glitch
+ var/mob/living/silicon/robot/R = AM
+ if(R.Slip(5,3))
+ //Don't step forward as a robot, we're not slipping just glitching.
+ R.visible_message("[R] short circuits on the water!", \
+ "You short circuit on the water!")
\ No newline at end of file
diff --git a/code/game/objects/effects/traps.dm b/code/game/objects/effects/traps.dm
index 8b4f4af5dff..359ea9b838b 100644
--- a/code/game/objects/effects/traps.dm
+++ b/code/game/objects/effects/traps.dm
@@ -51,4 +51,4 @@
else
S = sound_to_play
- playsound(get_turf(src), S, volume, vary)
+ playsound(src, S, volume, vary)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index f7045721307..79c6da6b47f 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -92,6 +92,9 @@
/obj/item/device
icon = 'icons/obj/device.dmi'
+/obj/item/proc/is_hidden_identity()
+ return is_slot_hidden(body_parts_covered,HIDEFACE)
+
/obj/item/ex_act(severity)
switch(severity)
if(1.0)
@@ -228,7 +231,7 @@
return
//user.next_move = max(user.next_move+2,world.time + 2)
add_fingerprint(user)
- if(!user.put_in_active_hand(src))
+ if(can_pickup(user) && !user.put_in_active_hand(src))
forceMove(get_turf(user))
return
@@ -789,7 +792,7 @@
else if(ismartian(M))
//why
- var/mob/living/carbon/martian/MA = M
+ var/mob/living/carbon/complex/martian/MA = M
switch(slot)
if(slot_head)
if(MA.head)
@@ -808,7 +811,7 @@
if(anchored) //Object isn't anchored
to_chat(user, "You can't pick that up!")
return FALSE
- if(!istype(loc, /turf)) //Object is not on a turf
+ if(!istype(loc, /turf) && !is_holder_of(user, src)) //Object is not on a turf
to_chat(user, "You can't pick that up!")
return FALSE
return TRUE
@@ -1189,7 +1192,7 @@ var/global/list/image/blood_overlays = list()
return
if(restraint_apply_sound)
- playsound(get_turf(src), restraint_apply_sound, 30, 1, -2)
+ playsound(src, restraint_apply_sound, 30, 1, -2)
user.visible_message("[user] is trying to restrain \the [C] with \the [src]!",
"You try to restrain \the [C] with \the [src]!")
@@ -1225,3 +1228,6 @@ var/global/list/image/blood_overlays = list()
//Called when user clicks on an object while looking through a camera (passed to the proc as [eye])
/obj/item/proc/remote_attack(atom/target, mob/user, atom/movable/eye)
return
+
+/obj/item/proc/recyclable() //Called by RnD machines, for added object-specific sanity.
+ return TRUE
diff --git a/code/game/objects/items/anvil.dm b/code/game/objects/items/anvil.dm
new file mode 100644
index 00000000000..c55ef1a1a23
--- /dev/null
+++ b/code/game/objects/items/anvil.dm
@@ -0,0 +1,33 @@
+/** Anvil
+ Is treated as an item that can not be picked up, unless you are incredibly strong.
+
+**/
+
+/obj/item/anvil
+ name = "anvil"
+ desc = "For rounding and crafting objects. Combined with a hammer, you can likely craft some pleasant weapons with this"
+ w_class = W_CLASS_GIANT
+ icon = 'icons/obj/blacksmithing.dmi'
+ icon_state = "anvil"
+ impactsound = 'sound/misc/clang.ogg'
+ flags = FPRINT | TWOHANDABLE | MUSTTWOHAND
+ density = 1
+ throwforce = 40
+
+/obj/item/anvil/can_pickup(mob/living/M)
+ if(!..())
+ return FALSE
+ if(M.get_strength() > 2)
+ return TRUE
+
+/obj/item/anvil/can_be_pulled(mob/user)
+ if(istype(user, /mob/living))
+ var/mob/living/L = user
+ if(L.get_strength() >= 2)
+ return TRUE
+ return FALSE
+
+/obj/item/anvil/check_airflow_movable(n)
+ if(n > 1000)
+ return TRUE
+ return FALSE
\ No newline at end of file
diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm
index a779f7afa23..4d574ff2f34 100644
--- a/code/game/objects/items/blueprints.dm
+++ b/code/game/objects/items/blueprints.dm
@@ -86,7 +86,6 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c
/obj/item/blueprints/attack_self(mob/living/M)
if (!ishigherbeing(M) && !issilicon(M))
to_chat(M, "This stack of blue paper means nothing to you.")//monkeys cannot into projecting
-
return
if(currently_edited)
@@ -119,7 +118,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c
delete_area(usr)
/obj/item/blueprints/interact()
- var/area/A = get_area()
+ var/area/A = get_area(src)
var/text = {"[src]
[station_name()] blueprints
@@ -155,13 +154,9 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c
usr << browse(text, "window=blueprints")
onclose(usr, "blueprints")
-
-/obj/item/blueprints/proc/get_area()
- var/turf/T = get_turf(usr)
- var/area/A = get_area_master(T)
- return A
-
-/obj/item/blueprints/proc/get_area_type(var/area/A = get_area())
+/obj/item/blueprints/proc/get_area_type(var/area/A)
+ if(!A)
+ A = get_area(src)
if (isspace(A))
return AREA_SPACE
else if(istype(A, /area/station/custom))
@@ -324,7 +319,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c
editor = user
- currently_edited = get_area()
+ currently_edited = get_area(src)
processing_objects.Add(src)
//Create a visual effect over the edited area
@@ -338,7 +333,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c
to_chat(user, "This drawing was already signed, and can't be renamed.")
return
- var/area/A = get_area()
+ var/area/A = get_area(src)
if(!istype(A) || !istype(user))
return
@@ -367,7 +362,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c
to_chat(user, "This drawing can't be erased.")
return
- var/area/areadeleted = get_area()
+ var/area/areadeleted = get_area(src)
if(area_protection_buffer >= 0)
for(var/obj/machinery/alarm/air_alarm in areadeleted)
@@ -383,7 +378,7 @@ these cannot rename rooms that are in by default BUT can rename rooms that are c
return
if(!Adjacent(user))
return
- if(!(areadeleted == get_area()))
+ if(!(areadeleted == get_area(src)))
return //if the blueprints are no longer in the area, return
for(var/turf/T in areadeleted)
diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm
index b43626c06ad..9bd98119068 100644
--- a/code/game/objects/items/candle.dm
+++ b/code/game/objects/items/candle.dm
@@ -41,7 +41,7 @@
wax--
var/turf/T = get_turf(src)
var/datum/gas_mixture/env = T.return_air()
- if(env.oxygen / env.volume * CELL_VOLUME < 5)
+ if(env.molar_density("oxygen") < (5 / CELL_VOLUME))
src.lit = 0
set_light(0)
processing_objects.Remove(src)
diff --git a/code/game/objects/items/changeling_vial.dm b/code/game/objects/items/changeling_vial.dm
index 26282330c03..cd541bc166b 100644
--- a/code/game/objects/items/changeling_vial.dm
+++ b/code/game/objects/items/changeling_vial.dm
@@ -14,7 +14,7 @@
var/datum/mind/M = H.mind
if(!ischangeling(H))
user.visible_message("As [user] crushes the vial, a mass of black goo leaps at \his face!.","As you try to remove the cap, you crush the vial in your hand!A mass of black goo leaps at you from the vial!")
- playsound(get_turf(src), "shatter", 20, 1)
+ playsound(src, "shatter", 20, 1)
qdel(src)
H.sleeping += 10
sleep(100)
diff --git a/code/game/objects/items/cookie_synth.dm b/code/game/objects/items/cookie_synth.dm
index fb7c7b85779..411c8440c04 100644
--- a/code/game/objects/items/cookie_synth.dm
+++ b/code/game/objects/items/cookie_synth.dm
@@ -3,25 +3,16 @@
desc = "A self-recharging device used to rapidly deploy cookies."
icon = 'icons/obj/RCD.dmi'
icon_state = "rcd"
- var/matter = 10
- var/toxin = 0
+ var/food_type = /obj/item/weapon/reagent_containers/food/snacks/cookie
+ var/toxin = FALSE
+ var/toxin_type = CHLORALHYDRATE
+ var/toxin_amount = 10
+ var/emagged = FALSE
+ var/sound_type = 'sound/machines/click.ogg'
var/cooldown = 0
- var/cooldowndelay = 15 SECONDS // ONE COOKIE PER SECOND WAS A NO NO, THESE THINGS CAN MAKE FREE SHITTER JUICE WHEN EMAGGED
- var/emagged = 0
+ var/delay = 15 SECONDS
w_class = W_CLASS_MEDIUM
-/obj/item/weapon/cookiesynth/New()
- ..()
- processing_objects.Add(src)
-
-/obj/item/weapon/cookiesynth/Destroy()
- processing_objects.Remove(src)
- ..()
-
-/obj/item/weapon/cookiesynth/examine(mob/user)
- ..()
- to_chat(user,"It currently holds [matter]/10 cookie-units.")
-
/obj/item/weapon/cookiesynth/attackby(obj/item/weapon/W, mob/user)
..()
if(isEmag(W))
@@ -29,13 +20,7 @@
/obj/item/weapon/cookiesynth/proc/Emag(mob/user)
emagged = !emagged
- if(emagged)
- if(user)
- to_chat(user,"You short out the [src]'s reagent safety checker!")
- else
- if(user)
- to_chat(user,"You reset the [src]'s reagent safety checker!")
- toxin = 0
+ spark(src)
/obj/item/weapon/cookiesynth/attack_self(mob/user)
if(isrobot(user))
@@ -47,21 +32,14 @@
/obj/item/weapon/cookiesynth/proc/toggle_toxins(mob/user)
toxin = !toxin
- to_chat(user,"Cookie Synthesizer [toxin ? "Hacked" : "Reset"].")
-
-/obj/item/weapon/cookiesynth/process()
- if(matter < 10)
- matter++
+ to_chat(user,"You [toxin ? "dis" : "en"]able the [src]'s reagent safety checker!")
/obj/item/weapon/cookiesynth/afterattack(atom/A, mob/user, proximity)
if(cooldown > world.time)
return
if(!proximity)
return
- if (!(istype(A, /obj/structure/table) || isturf(A)))
- return
- if(matter < 1)
- to_chat(user,"The [src] doesn't have enough matter left. Wait for it to recharge!")
+ if(!(istype(A, /obj/structure/table) || isturf(A)))
return
if(isrobot(user))
var/mob/living/silicon/robot/R = user
@@ -69,14 +47,37 @@
to_chat(user,"You do not have enough power to use [src].")
return
var/turf/T = get_turf(A)
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- to_chat(user,"Fabricating Cookie..")
- var/obj/item/weapon/reagent_containers/food/snacks/cookie/S = new /obj/item/weapon/reagent_containers/food/snacks/cookie(T)
+ playsound(src.loc, sound_type, 10, 1)
+ var/obj/item/weapon/reagent_containers/food/S = new food_type(T)
+ to_chat(user,"Fabricating [utf8_lowercase(S.name)]..")
if(toxin)
- S.reagents.add_reagent(CHLORALHYDRATE, 10)
- if (isrobot(user))
+ S.reagents.add_reagent(toxin_type, toxin_amount)
+ if(isrobot(user))
var/mob/living/silicon/robot/R = user
R.cell.charge -= 100
- else
- matter--
- cooldown = world.time + cooldowndelay
+ cooldown = world.time + delay
+
+//TODO: Give hugborgs their own custom RSF instead of this snoflakey mess.
+
+/obj/item/weapon/cookiesynth/proc/Honkize()
+ name = "banana synthesizer"
+ desc = "A self-recharging device used to rapidly deploy bananas."
+ food_type = /obj/item/weapon/reagent_containers/food/snacks/grown/banana
+ toxin_type = SPIRITBREAKER
+
+/obj/item/weapon/cookiesynth/proc/Lawize()
+ name = "donut synthesizer"
+ desc = "A self-recharging device used to rapidly deploy donuts."
+ food_type = /obj/item/weapon/reagent_containers/food/snacks/donut/normal
+ toxin_type = CHEESYGLOOP
+
+/obj/item/weapon/cookiesynth/proc/Noirize()
+ name = "joe synthesizer"
+ desc = "A self-recharging device used to rapidly deploy bitter, black, and tasteless coffee."
+ food_type = /obj/item/weapon/reagent_containers/food/drinks/mug/joe
+ toxin_type = HEMOSCYANINE
+
+/obj/item/weapon/reagent_containers/food/drinks/mug/joe/New()
+ ..()
+ reagents.add_reagent(DETCOFFEE, 20)
+
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index fd08afbb9b4..2c97f1262ab 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -53,6 +53,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/cart = "" //A place to stick cartridge menu information
var/detonate = 1 // Can the PDA be blown up?
var/hidden = 0 // Is the PDA hidden from the PDA list?
+ var/reply = null //Where are replies directed? For multicaster. Most set this to self in new.
var/obj/item/weapon/card/id/id = null //Making it possible to slot an ID card into the PDA so it can function as both.
var/ownjob = null //related to above
@@ -192,6 +193,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
..()
var/datum/pda_app/balance_check/app = new /datum/pda_app/balance_check()
app.onInstall(src)
+ reply = src
/obj/item/device/pda/medical
name = "Medical PDA"
@@ -442,7 +444,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/trader
name = "Trader PDA"
desc = "Much good for trade."
- note = "Congratulations, your station plU%ZÒ67Ez4ƦU8E1Ћ~@Tu1Bk@i8NJ"
+ note = "Congratulations, your station �plU�%ZÒ67�Ez4ƦU���8�E1��Ћ���~���@��T�u1B��k�@i�8�NJ��"
icon_state = "pda-trader"
default_cartridge = /obj/item/weapon/cartridge/trader
@@ -692,6 +694,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
"
@@ -848,31 +851,34 @@ var/global/list/obj/item/device/pda/PDAs = list()
if (3)
dat += "
Atmospheric Readings
"
- var/turf/T = get_turf(user.loc)
- if (isnull(T))
+ if (isnull(user.loc))
dat += "Unable to obtain a reading. "
else
- var/datum/gas_mixture/environment = T.return_air()
+ var/datum/gas_mixture/environment = user.loc.return_air()
- var/pressure = environment.return_pressure()
- var/total_moles = environment.total_moles()
+ if(!environment)
+ dat += "No gasses detected. "
- dat += "Air Pressure: [round(pressure,0.1)] kPa "
+ else
+ var/pressure = environment.return_pressure()
+ var/total_moles = environment.total_moles()
- if (total_moles)
- var/o2_level = environment.oxygen/total_moles
- var/n2_level = environment.nitrogen/total_moles
- var/co2_level = environment.carbon_dioxide/total_moles
- var/plasma_level = environment.toxins/total_moles
- var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
+ dat += "Air Pressure: [round(pressure,0.1)] kPa "
- dat += {"Nitrogen: [round(n2_level*100)]%
- Oxygen: [round(o2_level*100)]%
- Carbon Dioxide: [round(co2_level*100)]%
- Plasma: [round(plasma_level*100)]% "}
- if(unknown_level > 0.01)
- dat += "OTHER: [round(unknown_level)]% "
- dat += "Temperature: [round(environment.temperature-T0C)]°C "
+ if (total_moles)
+ var/o2_level = environment.oxygen/total_moles
+ var/n2_level = environment.nitrogen/total_moles
+ var/co2_level = environment.carbon_dioxide/total_moles
+ var/plasma_level = environment.toxins/total_moles
+ var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
+
+ dat += {"Nitrogen: [round(n2_level*100)]%
+ Oxygen: [round(o2_level*100)]%
+ Carbon Dioxide: [round(co2_level*100)]%
+ Plasma: [round(plasma_level*100)]% "}
+ if(unknown_level > 0.01)
+ dat += "OTHER: [round(unknown_level)]% "
+ dat += "Temperature: [round(environment.temperature-T0C)]°C "
dat += " "
if (5)
@@ -1477,9 +1483,9 @@ var/global/list/obj/item/device/pda/PDAs = list()
id.virtual_wallet.money -= amount
withdraw_arbitrary_sum(user,amount)
if(prob(50))
- playsound(get_turf(src), 'sound/items/polaroid1.ogg', 50, 1)
+ playsound(src, 'sound/items/polaroid1.ogg', 50, 1)
else
- playsound(get_turf(src), 'sound/items/polaroid2.ogg', 50, 1)
+ playsound(src, 'sound/items/polaroid2.ogg', 50, 1)
var/datum/transaction/T = new()
T.target_name = user.name
@@ -1799,6 +1805,25 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/obj/item/device/pda/P = locate(href_list["target"])
src.create_message(U, P)
+ if("Multimessage")
+ var/list/department_list = list("security","engineering","medical","research","cargo","service")
+ var/target = input("Select a department", "CAMO Service") as null|anything in department_list
+ if(!target)
+ return
+ var/t = input(U, "Please enter message", "Message to [target]", null) as text|null
+ t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN)
+ if (!t || toff || (!in_range(src, U) && loc != U)) //If no message, messaging is off, and we're either out of range or not in usr
+ return
+ if (last_text && world.time < last_text + 5)
+ return
+ last_text = world.time
+ for(var/obj/machinery/pda_multicaster/multicaster in pda_multicasters)
+ if(multicaster.check_status())
+ multicaster.multicast(target,src,usr,t)
+ tnote += "→ To [target]: [t] "
+ return
+ to_chat(usr, "[bicon(src)]The PDA's screen flashes, 'Error, CAMO server is not responding.'")
+
if("transferFunds")
if(!id)
return
@@ -2069,24 +2094,19 @@ var/global/list/obj/item/device/pda/PDAs = list()
id.forceMove(get_turf(src))
id = null
-/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P)
- var/t = input(U, "Please enter message", "Message to [P]", null) as text|null
- t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN)
- if (!t || !istype(P))
- return
- if (!in_range(src, U) && loc != U)
+/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P,var/multicast_message = null)
+ if (!istype(P)||P.toff)
return
+ var/t = multicast_message
+ if(!t)
+ t = input(U, "Please enter message", "Message to [P]", null) as text|null
+ t = copytext(sanitize(t), 1, MAX_MESSAGE_LEN)
+ if (!t || toff || (!in_range(src, U) && loc != U)) //If no message, messaging is off, and we're either out of range or not in usr
+ return
- if (isnull(P)||P.toff || toff)
- return
-
- if (last_text && world.time < last_text + 5)
- return
-
- if(!can_use(U))
- return
-
- last_text = world.time
+ if (last_text && world.time < last_text + 5)
+ return
+ last_text = world.time
// check if telecomms I/O route 1459 is stable
//var/telecomms_intact = telecomms_process(P.owner, owner, t)
var/obj/machinery/message_server/useMS = null
@@ -2117,13 +2137,13 @@ var/global/list/obj/item/device/pda/PDAs = list()
useMS.send_pda_message("[P.owner]","[owner]","[t]")
tnote += "→ To [P.owner]: [t] "
- P.tnote += "← From [owner] ([ownjob]): [t] "
+ P.tnote += "← From [owner] ([ownjob]): [t] "
for(var/mob/dead/observer/M in player_list)
- if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTPDA)) // src.client is so that ghosts don't have to listen to mice
+ if(!multicast_message && M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTPDA)) // src.client is so that ghosts don't have to listen to mice
M.show_message("PDA Message - [U][U.real_name == owner ? "" : " (as [owner])"] -> [P.owner]: [t]")
- if (prob(15)) //Give the AI a chance of intercepting the message
+ if (prob(15)&&!multicast_message) //Give the AI a chance of intercepting the message
var/who = src.owner
if(prob(50))
who = P:owner
@@ -2146,7 +2166,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
L = get_holder_of_type(P, /mob/living/silicon)
if(L)
- L.show_message("[bicon(P)] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)", 2)
+ L.show_message("[bicon(P)] Message from [src.owner] ([ownjob]), \"[t]\" (Reply)", 2)
U.show_message("[bicon(src)] Message for [P] has been sent.")
log_pda("[key_name(usr)] (PDA: [src.name]) sent \"[t]\" to [P.name]")
P.overlays.len = 0
diff --git a/code/game/objects/items/devices/PDA/apps.dm b/code/game/objects/items/devices/PDA/apps.dm
index 942d5e52391..0b5db324fa9 100644
--- a/code/game/objects/items/devices/PDA/apps.dm
+++ b/code/game/objects/items/devices/PDA/apps.dm
@@ -140,7 +140,7 @@ var/global/list/pda_app_menus = list(
game_update(user)
if(snake_game.head.next_full)
- playsound(get_turf(pda_device), 'sound/misc/pda_snake_eat.ogg', volume * 5, 1)
+ playsound(pda_device, 'sound/misc/pda_snake_eat.ogg', volume * 5, 1)
if(!paused)
if(!snake_game.gameover)
@@ -173,7 +173,7 @@ var/global/list/pda_app_menus = list(
pause(user)
/datum/pda_app/snake/proc/game_over(var/mob/user)
- playsound(get_turf(pda_device), 'sound/misc/pda_snake_over.ogg', volume * 5, 0)
+ playsound(pda_device, 'sound/misc/pda_snake_over.ogg', volume * 5, 0)
for(var/i=1;i <= 4;i++)
for(var/datum/snake/body/B in snake_game.snakeparts)
B.flicking = 1
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index 6369576c632..aec60ce6683 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -393,7 +393,8 @@ Code:
var/list/chg = list("N","C","F")
for(var/obj/machinery/power/apc/A in L)
- menu += copytext(add_tspace(A.areaMaster.name, 30), 1, 30)
+ var/area/APC_area = get_area(A)
+ menu += copytext(add_tspace(APC_area.name, 30), 1, 30)
menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(A.lastused_total, 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"] "
menu += ""
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
index 0078d9e710c..d729099c89e 100644
--- a/code/game/objects/items/devices/aicard.dm
+++ b/code/game/objects/items/devices/aicard.dm
@@ -24,7 +24,7 @@
transfer_ai("AICORE", "AICARD", M, user)
- playsound(get_turf(src), 'sound/machines/paistartup.ogg', 50, 1)
+ playsound(src, 'sound/machines/paistartup.ogg', 50, 1)
return
/obj/item/device/aicard/attack_self(mob/user)
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index 722ae5982a2..e238e4d3473 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -46,7 +46,7 @@
return
if(!active_dummy)
if(istype(target, /obj/item) && !istype(target, /obj/item/weapon/disk/nuclear) || istype(target, /mob))
- playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1, -6)
+ playsound(src, 'sound/weapons/flash.ogg', 100, 1, -6)
to_chat(user, "Scanned [target].")
saved_item = target.type
saved_icon = target.icon
@@ -59,7 +59,7 @@
return
if(active_dummy)
eject_all()
- //playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
+ //playsound(src, 'sound/effects/pop.ogg', 100, 1, -6)
qdel(active_dummy)
active_dummy = null
to_chat(usr, "You deactivate [src].")
@@ -72,7 +72,7 @@
spawn(20) //Stop spamming this shit
can_use = 1
else
- //playsound(get_turf(src), 'sound/effects/pop.ogg', 100, 1, -6)
+ //playsound(src, 'sound/effects/pop.ogg', 100, 1, -6)
var/obj/O = new saved_item(src)
if(!O)
return
diff --git a/code/game/objects/items/devices/deskbell.dm b/code/game/objects/items/devices/deskbell.dm
index 031137d57b5..752660e8827 100644
--- a/code/game/objects/items/devices/deskbell.dm
+++ b/code/game/objects/items/devices/deskbell.dm
@@ -278,7 +278,7 @@
if(0)
if(iswrench(W))
to_chat(user, "You deconstruct \the [src].")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
//new /obj/item/stack/sheet/metal( get_turf(src.loc), 2)
var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src))
M.amount = 2
@@ -289,7 +289,7 @@
user.visible_message(
"[user.name] has added cables to \the [src]!",
"You add cables to \the [src].")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
C.use(1)
build_step++
update_icon()
diff --git a/code/game/objects/items/devices/does_not_tip.dm b/code/game/objects/items/devices/does_not_tip.dm
new file mode 100644
index 00000000000..0e5af07140e
--- /dev/null
+++ b/code/game/objects/items/devices/does_not_tip.dm
@@ -0,0 +1,15 @@
+/obj/item/device/does_not_tip_backdoor
+ name = "\improper PDA"
+ desc = "The screen seems to be blank."
+ icon = 'icons/obj/pda.dmi'
+ icon_state = "pda"
+ w_class = W_CLASS_TINY
+ flags = FPRINT
+
+/obj/item/device/does_not_tip_backdoor/attack_self(var/mob/user)
+ if(alert(user, "A cryptic message appears on the screen: \"Are you sure you want to do it?\".", name, "Yes", "No") != "Yes")
+ return
+ if(user.incapacitated() || !Adjacent(user))
+ return
+ station_does_not_tip = !station_does_not_tip
+ to_chat(user, "\The [src]'s screen flashes [station_does_not_tip ? "red" : "green"] for a moment.")
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index 5c48239c596..24beb0133dd 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -76,7 +76,7 @@
to_chat(user, "*click* *click*")
return
- playsound(get_turf(user), 'sound/weapons/flash.ogg', 100, 1)
+ playsound(user, 'sound/weapons/flash.ogg', 100, 1)
if(isrobot(user))
spawn(0)
@@ -139,7 +139,7 @@
else //can only use it 5 times a minute
user.show_message("*click* *click*", 2)
return
- playsound(get_turf(src), 'sound/weapons/flash.ogg', 100, 1)
+ playsound(src, 'sound/weapons/flash.ogg', 100, 1)
if(harm_labeled >= min_harm_label)
return //Act as if the flash was activated except the useful part.
flick("flash2", src)
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 7ea53decd47..43a2a47f5f5 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -34,12 +34,12 @@
set_light(brightness_on)
if(playsound && has_sound)
if(get_turf(src))
- playsound(get_turf(src), sound_on, 50, 1)
+ playsound(src, sound_on, 50, 1)
else
icon_state = initial(icon_state)
set_light(0)
if(playsound && has_sound)
- playsound(get_turf(src), sound_off, 50, 1)
+ playsound(src, sound_off, 50, 1)
/obj/item/device/flashlight/attack_self(mob/user)
if(!isturf(user.loc))
diff --git a/code/game/objects/items/devices/holomap.dm b/code/game/objects/items/devices/holomap.dm
index 8efe6c373f6..fa7c628bacb 100644
--- a/code/game/objects/items/devices/holomap.dm
+++ b/code/game/objects/items/devices/holomap.dm
@@ -74,7 +74,7 @@
target.holomap_data.Cut()
for (var/obj/O in target)
- if (O.holomap)
+ if (O.supports_holomap())
target.add_holomap(O)
to_chat(user, "You reset the holomap data.")
@@ -83,7 +83,7 @@
if (isscrewdriver(W))
panel = !panel
to_chat(user, "You [panel ? "open" : "close"] the panel on \the [src].")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
return 1
if (ismultitool(W) && panel)
diff --git a/code/game/objects/items/devices/inhaler.dm b/code/game/objects/items/devices/inhaler.dm
new file mode 100644
index 00000000000..26ce9a4bcd0
--- /dev/null
+++ b/code/game/objects/items/devices/inhaler.dm
@@ -0,0 +1,52 @@
+#define PUFF_COOLDOWN_TIME 8
+
+/obj/item/device/inhaler
+ name = "inhaler"
+ desc = "Breathe deep!"
+ icon = 'icons/obj/inhaler.dmi'
+ icon_state = "inhaler"
+ w_class = W_CLASS_TINY
+ flags = FPRINT
+ slot_flags = SLOT_BELT
+ throwforce = 0
+ throw_speed = 4
+ throw_range = 20
+ force = 0
+ var/last_puff = 0
+
+/obj/item/device/inhaler/proc/puff_ready()
+ return last_puff < world.time - PUFF_COOLDOWN_TIME
+
+/obj/item/device/inhaler/attack_self(mob/user)
+ puff(user, user)
+
+/obj/item/device/inhaler/attack(mob/living/target, mob/user)
+ if(user.a_intent != I_HELP)
+ return ..()
+ puff(target, user)
+
+/obj/item/device/inhaler/proc/puff(mob/living/carbon/human/target, var/mob/living/user)
+ if(!ishuman(target))
+ return
+ if(!puff_ready())
+ return
+ var/used_on_self = target == user
+ if(!target.hasmouth)
+ if(used_on_self)
+ to_chat(user, "There's nowhere to put \the [src] as you lack a mouth!")
+ else
+ to_chat(user, "There's nowhere to put \the [src] as [target] lacks a mouth!")
+ return
+ var/obj/item/mouth_protection = target.get_body_part_coverage(MOUTH)
+ if(mouth_protection)
+ to_chat(user, "Remove [used_on_self ? "your" : "their"] [mouth_protection.name] first!")
+ return
+ if(used_on_self)
+ user.visible_message("[user] takes a puff from \the [src].", "You take a puff from \the [src].")
+ else
+ user.visible_message("[user] helps [target] take a puff from \the [src].", "You help [target] take a puff from \the [src].")
+ playsound(target, 'sound/effects/spray2.ogg', 20, 1)
+ target.reagents.add_reagent(ALBUTEROL, 5)
+ last_puff = world.time
+
+#undef PUFF_COOLDOWN_TIME
diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm
index 65b91a28c07..6b73c4a30d1 100644
--- a/code/game/objects/items/devices/lightreplacer.dm
+++ b/code/game/objects/items/devices/lightreplacer.dm
@@ -190,6 +190,7 @@
Supply Container:
"} //It's not clear here, but the argument to build is the part of the typepath after /obj/item/weapon/light/
+ dat += {"Filled: [supply.contents.len]/[supply.storage_slots]"}
var/list/light_types = new()
var/lightname
for(var/obj/item/weapon/light/L in supply)
@@ -260,6 +261,7 @@
Supply Container:
"}
+ dat += {"Filled: [supply.contents.len]/[supply.storage_slots]"}
var/list/light_types = new()
var/lightname
for(var/obj/item/weapon/light/L in supply)
@@ -323,7 +325,7 @@
to_chat(user, "You replace the [target.fitting] with \the [src].")
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
supply.remove_from_storage(best_light)
@@ -366,7 +368,7 @@
/obj/item/device/lightreplacer/proc/Emag()
emagged = !emagged
- playsound(get_turf(src), "sparks", 100, 1)
+ playsound(src, "sparks", 100, 1)
if(emagged)
name = "Shortcircuited [initial(name)]"
else
diff --git a/code/game/objects/items/devices/mat_synth.dm b/code/game/objects/items/devices/mat_synth.dm
index 67d0e2391ba..7301741de9b 100644
--- a/code/game/objects/items/devices/mat_synth.dm
+++ b/code/game/objects/items/devices/mat_synth.dm
@@ -24,7 +24,13 @@
"glass" = /obj/item/stack/sheet/glass/glass,
"reinforced glass" = /obj/item/stack/sheet/glass/rglass,
"plasteel" = /obj/item/stack/sheet/plasteel)
- var/list/can_scan = list(/obj/item/stack/sheet)
+
+ var/list/can_scan = list(/obj/item/stack/sheet/metal,
+ /obj/item/stack/sheet/glass/,
+ /obj/item/stack/sheet/wood,
+ /obj/item/stack/sheet/plasteel,
+ /obj/item/stack/sheet/mineral)
+ var/list/cant_scan = list()
var/matter = 0
/obj/item/device/material_synth/robot/engiborg //Cyborg version, has less materials but can make rods n shit as well as scan.
@@ -36,7 +42,7 @@
/obj/item/device/material_synth/robot/engiborg/New() //We have to do this during New() because BYOND can't pull a typesof() during compile time.
. = ..()
- can_scan = existing_typesof(/obj/item/stack/sheet) - list(/obj/item/stack/sheet/mineral/clown, /obj/item/stack/sheet/mineral/phazon)
+ cant_scan = list(/obj/item/stack/sheet/mineral/clown, /obj/item/stack/sheet/mineral/phazon)
/obj/item/device/material_synth/robot/mommi //MoMMI version, a few more materials to start with.
materials_scanned = list("metal" = /obj/item/stack/sheet/metal,
@@ -146,7 +152,7 @@
/obj/item/device/material_synth/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
if(!proximity_flag)
return 0 // not adjacent
- if(is_type_in_list(target, can_scan)) //Can_scan, can you?
+ if(is_type_in_list(target, can_scan) && !is_type_in_list(target, cant_scan))
for(var/matID in materials_scanned)
if(materials_scanned[matID] == target.type)
to_chat(user, "You have already scanned \the [target].")
@@ -173,7 +179,7 @@
return
else
matter += 10
- playsound(get_turf(src), 'sound/machines/click.ogg', 20, 1)
+ playsound(src, 'sound/machines/click.ogg', 20, 1)
qdel(RA)
to_chat(user, "The material synthetizer now holds [matter]/[MAX_MATSYNTH_MATTER] matter-units.")
if(istype(O, /obj/item/weapon/card/emag))
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 748d69d3f8d..f08cf6f2687 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -42,18 +42,13 @@
if(user.client.prefs.muted & MUTE_IC)
to_chat(src, "You cannot speak in IC (muted).")
return 0
- if(user.silent)
+ if(issilent(user))
to_chat(user, "You find yourself unable to speak at all.")
return 0
if(spamcheck)
to_chat(user, "\The [src] needs to recharge!")
return 0
if(ishuman(user)) //humans can use it, borgs can, mommis can't
- to_chat(user, "You don't know how to use this!")
- var/mob/living/carbon/human/H = user
- if(istype(H) && (H.miming)) //Humans get their muteness checked
- to_chat(user, "You find yourself unable to speak at all.")
- return 0
return 1
if(isrobot(user) && !isMoMMI(user))
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index 2931b64a717..6b712ca3a58 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -90,7 +90,7 @@
to_chat(M, "[user] activates the power sink!")
mode = 2
icon_state = "powersink1"
- playsound(get_turf(src), 'sound/effects/phasein.ogg', 30, 1)
+ playsound(src, 'sound/effects/phasein.ogg', 30, 1)
processing_objects.Add(src)
if(2) //This switch option wasn't originally included. It exists now. --NeoFite
@@ -102,7 +102,7 @@
mode = 1
set_light(0)
icon_state = "powersink0"
- playsound(get_turf(src), 'sound/effects/teleport.ogg', 50, 1)
+ playsound(src, 'sound/effects/teleport.ogg', 50, 1)
processing_objects.Remove(src)
process()
diff --git a/code/game/objects/items/devices/radio/cyborg.dm b/code/game/objects/items/devices/radio/cyborg.dm
index 6e5bb8dc2e8..b7ca450331b 100644
--- a/code/game/objects/items/devices/radio/cyborg.dm
+++ b/code/game/objects/items/devices/radio/cyborg.dm
@@ -11,6 +11,10 @@
keyslot = key
recalculateChannels()
+/obj/item/device/radio/borg/proc/reset_key()
+ keyslot = initial(keyslot)
+ recalculateChannels()
+
/obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob)
// ..()
user.set_machine(src)
diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm
index 517aeccad1f..d4dc773e2fc 100644
--- a/code/game/objects/items/devices/radio/encryptionkey.dm
+++ b/code/game/objects/items/devices/radio/encryptionkey.dm
@@ -5,6 +5,7 @@
icon = 'icons/obj/radio.dmi'
icon_state = "cypherkey"
item_state = ""
+ w_class = W_CLASS_TINY
var/translate_binary = 0
var/translate_hive = 0
var/syndie = 0
diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm
index 65462370132..e5167ad09f0 100644
--- a/code/game/objects/items/devices/radio/headset.dm
+++ b/code/game/objects/items/devices/radio/headset.dm
@@ -267,7 +267,7 @@
/obj/item/device/radio/headset/ert
name = "CentCom Response Team headset"
- desc = "The headset of the boss's boss. Channels are as follows: :r - Response Team :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science."
+ desc = "The headset of the boss's boss. Channels are as follows: ':-' - Response Team :c - command, :s - security, :e - engineering, :d - mining, :q - cargo, :m - medical, :n - science."
icon_state = "ert_headset"
item_state = "headset"
freerange = 1
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 09206e30ed3..86bdf3ea390 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -12,12 +12,16 @@
var/last_tick //used to delay the powercheck
var/buildstage = 0
- holomap = TRUE
- auto_holomap = TRUE
+/obj/item/device/radio/intercom/supports_holomap()
+ return TRUE
/obj/item/device/radio/intercom/universe/New()
return ..()
+/obj/item/device/radio/intercom/initialize()
+ ..()
+ add_self_to_holomap()
+
/obj/item/device/radio/intercom/New(turf/loc, var/ndir = 0, var/building = 3)
..()
buildstage = building
@@ -79,7 +83,7 @@
if(3)
if(iswirecutter(W) && b_stat && wires.IsAllCut())
to_chat(user, "You cut out the intercoms wiring and disconnect its electronics.")
- playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
if(do_after(user, src, 10))
new /obj/item/stack/cable_coil(get_turf(src),5)
on = 0
@@ -92,7 +96,7 @@
return ..()
if(2)
if(isscrewdriver(W))
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, src, 10))
update_icon()
on = 1
@@ -102,7 +106,7 @@
update_icon()
processing_objects.Add(src)
for(var/i, i<= 5, i++)
- wires.UpdateCut(i,1)
+ wires.UpdateCut(i,1, user)
return 1
if(1)
if(iscablecoil(W))
@@ -117,7 +121,7 @@
return 1
if(iscrowbar(W))
to_chat(user, "You begin removing the electronics...")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src, 10))
new /obj/item/weapon/intercom_electronics(get_turf(src))
to_chat(user, "The circuitboard pops out!")
@@ -125,7 +129,7 @@
return 1
if(0)
if(istype(W,/obj/item/weapon/intercom_electronics))
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src, 10))
qdel(W)
to_chat(user, "You insert \the [W] into \the [src]!")
@@ -133,7 +137,7 @@
return 1
if(iswelder(W))
var/obj/item/weapon/weldingtool/WT=W
- playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
if(!WT.remove_fuel(3, user))
to_chat(user, "You're out of welding fuel.")
return 1
@@ -152,11 +156,12 @@
/obj/item/device/radio/intercom/process()
if(((world.timeofday - last_tick) > 30) || ((world.timeofday - last_tick) < 0))
last_tick = world.timeofday
- if(!areaMaster)
+ var/area/this_area = get_area(src)
+ if(!this_area)
on = 0
update_icon()
return
- on = areaMaster.powered(EQUIP) // set "on" to the power status
+ on = this_area.powered(EQUIP) // set "on" to the power status
update_icon()
/obj/item/weapon/intercom_electronics
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 6d426c2a0c7..f45f18675dc 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -100,7 +100,7 @@
Frequency:
--
- [format_frequency(frequency)]
+ [format_frequency(frequency)]++
"}
@@ -124,8 +124,13 @@
[chan_name]: [list ? "Engaged" : "Disengaged"]
"}
+/obj/item/device/radio/proc/check_traitor_uplink(frequency)
+ if(hidden_uplink)
+ if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency))
+ usr << browse(null, "window=radio")
+ return 1
+
/obj/item/device/radio/Topic(href, href_list)
- //..()
if (usr.stat || !on)
return
@@ -164,15 +169,21 @@
return
- else if (href_list["freq"])
- var/new_frequency = (frequency + text2num(href_list["freq"]))
- if (!freerange || (frequency < 1200 || frequency > 1600))
- new_frequency = sanitize_frequency(new_frequency, maxf)
+ else if("set_freq" in href_list)
+ var/new_frequency
+ new_frequency = input(usr, "Set a new frequency (1200-1600 kHz).", src, frequency) as null|num
+ new_frequency = sanitize_frequency(new_frequency, maxf)
set_frequency(new_frequency)
- if(hidden_uplink)
- if(hidden_uplink.check_trigger(usr, frequency, traitor_frequency))
- usr << browse(null, "window=radio")
- return
+ if (check_traitor_uplink(frequency))
+ return
+
+ else if (href_list["freq"])
+ var/new_frequency
+ new_frequency = (frequency + text2num(href_list["freq"]))
+ new_frequency = sanitize_frequency(new_frequency, maxf)
+ set_frequency(new_frequency)
+ if (check_traitor_uplink(frequency))
+ return
else if (href_list["talk"])
broadcasting = text2num(href_list["talk"])
@@ -305,7 +316,7 @@
speech.job = "Personal AI"
// --- Cold, emotionless machines. ---
- else if(isobj(speech.speaker))
+ else if(isobj(speech.speaker) || istype(speech.speaker, /mob/living/simple_animal/spiderbot))
speech.job = "Machine"
// --- Unidentifiable mob ---
@@ -524,6 +535,7 @@
else
user.show_message("\The [src] can no longer be modified or attached!")
updateDialog()
+ update_icon()
add_fingerprint(user)
/obj/item/device/radio/emp_act(severity)
diff --git a/code/game/objects/items/devices/remote/buttons/test_buttons.dm b/code/game/objects/items/devices/remote/buttons/test_buttons.dm
index 044a20c3099..f5fc3bf38a1 100644
--- a/code/game/objects/items/devices/remote/buttons/test_buttons.dm
+++ b/code/game/objects/items/devices/remote/buttons/test_buttons.dm
@@ -5,7 +5,7 @@
icon_state = "button_ping"
/obj/item/device/remote_button/ping/on_press(mob/user)
- playsound(get_turf(holder), 'sound/machines/notify.ogg', 25, 0)
+ playsound(holder, 'sound/machines/notify.ogg', 25, 0)
/obj/item/device/remote_button/bang
name = "bang button"
@@ -14,7 +14,7 @@
icon_state = "button_bang"
/obj/item/device/remote_button/bang/on_press(mob/user)
- playsound(get_turf(holder), 'sound/effects/bang.ogg', 25, 1)
+ playsound(holder, 'sound/effects/bang.ogg', 25, 1)
/obj/item/device/remote_button/tong
name = "tong button"
@@ -23,4 +23,4 @@
icon_state = "button_tong"
/obj/item/device/remote_button/tong/on_press(mob/user)
- playsound(get_turf(holder), 'sound/instruments/piano/Cn4.ogg', 25, 1)
\ No newline at end of file
+ playsound(holder, 'sound/instruments/piano/Cn4.ogg', 25, 1)
\ No newline at end of file
diff --git a/code/game/objects/items/devices/remote/remote_buttons.dm b/code/game/objects/items/devices/remote/remote_buttons.dm
index 6d9dfde44d1..f59e3a02c1d 100644
--- a/code/game/objects/items/devices/remote/remote_buttons.dm
+++ b/code/game/objects/items/devices/remote/remote_buttons.dm
@@ -50,3 +50,8 @@
/obj/item/device/remote_button/proc/on_press(mob/user)
return
+
+
+
+
+
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index fb1de6d8795..a69e8a4c584 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -5,6 +5,7 @@ HEALTH ANALYZER
GAS ANALYZER
MASS SPECTROMETER
REAGENT SCANNER
+BREATHALYZER
*/
/obj/item/device/t_scanner
@@ -180,7 +181,7 @@ Subject's pulse: ??? BPM"})
OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal"
message += (" [OX] | [TX] | [BU] | [BR]")
- if(M.reagents.total_volume)
+ if(M.reagents && M.reagents.total_volume)
message += " Warning: Unknown substance detected in subject's blood."
if(hardcore_mode_on && ishuman(M) && eligible_for_hardcore_mode(M))
var/mob/living/carbon/human/H = M
@@ -293,14 +294,16 @@ Subject's pulse: ??? BPM"})
to_chat(user, "You don't have the dexterity to do this!")
return
- var/turf/location = get_turf(user)
+ var/atom/location = is_holder_of(user, src) ? user.loc : get_turf(src) //If user isn't the holder we're either in a mech's equipment loadout or something weird so get the outside environment
if(!location) //Somehow
return
var/datum/gas_mixture/environment = location.return_air()
- to_chat(user, output_gas_scan(environment, location, 1))
+ var/unit_vol = environment && environment.volume > CELL_VOLUME ? CELL_VOLUME : null
+
+ to_chat(user, output_gas_scan(environment, location, 1, unit_vol))
src.add_fingerprint(user)
return
@@ -323,14 +326,20 @@ Subject's pulse: ??? BPM"})
return
var/turf/T = A
var/datum/gas_mixture/environment = T.return_air()
- to_chat(user, output_gas_scan(environment, T, 1))
+ to_chat(user, output_gas_scan(environment, T, 1, CELL_VOLUME))
add_fingerprint(user)
//If human_standard is enabled, the message will be formatted to show which values are dangerous
-/obj/item/device/analyzer/proc/output_gas_scan(var/datum/gas_mixture/scanned, var/atom/container, human_standard = 1)
+//If unit_vol is specified, it will output the values for that volume of the scanned gas. Really for analyzing areas.
+/obj/item/device/analyzer/proc/output_gas_scan(var/datum/gas_mixture/scanned, var/atom/container, human_standard = 1, unit_vol)
if(!scanned)
return "No gas mixture found."
scanned.update_values()
+ if(unit_vol)
+ var/datum/gas_mixture/unit = new() //Unless something goes horribly wrong, this will be cleaned up by the GC at the end of the proc.
+ unit.volume = unit_vol
+ unit.copy_from(scanned)
+ scanned = unit
var/pressure = scanned.return_pressure()
var/total_moles = scanned.total_moles()
var/message = ""
@@ -349,17 +358,17 @@ Subject's pulse: ??? BPM"})
var/unknown_concentration = 1 - (o2_concentration + n2_concentration + co2_concentration + plasma_concentration)
if(n2_concentration > 0.01)
- message += " [human_standard && abs(n2_concentration - N2STANDARD) > 20 ? "" : ""] Nitrogen: [round(scanned.nitrogen / scanned.volume * CELL_VOLUME, 0.1)] mol, [round(n2_concentration*100)]%"
+ message += " [human_standard && abs(n2_concentration - N2STANDARD) > 20 ? "" : ""] Nitrogen: [round(scanned.nitrogen, 0.1)] mol, [round(n2_concentration*100)]%"
if(o2_concentration > 0.01)
- message += " [human_standard && abs(o2_concentration - O2STANDARD) > 2 ? "" : ""] Oxygen: [round(scanned.oxygen / scanned.volume * CELL_VOLUME, 0.1)] mol, [round(o2_concentration*100)]%"
+ message += " [human_standard && abs(o2_concentration - O2STANDARD) > 2 ? "" : ""] Oxygen: [round(scanned.oxygen, 0.1)] mol, [round(o2_concentration*100)]%"
if(co2_concentration > 0.01)
- message += " [human_standard ? "" : ""] CO2: [round(scanned.carbon_dioxide / scanned.volume * CELL_VOLUME, 0.1)] mol, [round(co2_concentration*100)]%"
+ message += " [human_standard ? "" : ""] CO2: [round(scanned.carbon_dioxide, 0.1)] mol, [round(co2_concentration*100)]%"
if(plasma_concentration > 0.01)
- message += " [human_standard ? "" : ""] Plasma: [round(scanned.toxins / scanned.volume * CELL_VOLUME, 0.1)] mol, [round(plasma_concentration*100)]%"
+ message += " [human_standard ? "" : ""] Plasma: [round(scanned.toxins, 0.1)] mol, [round(plasma_concentration*100)]%"
if(unknown_concentration > 0.01)
message += " Unknown: [round(unknown_concentration*100)]%"
- message += " [human_standard && !(scanned.temperature in range(BODYTEMP_COLD_DAMAGE_LIMIT, BODYTEMP_HEAT_DAMAGE_LIMIT)) ? "" : ""] Temperature: [round(scanned.temperature-T0C)]°C"
+ message += " [human_standard && !IsInRange(scanned.temperature, BODYTEMP_COLD_DAMAGE_LIMIT, BODYTEMP_HEAT_DAMAGE_LIMIT) ? "" : ""] Temperature: [round(scanned.temperature-T0C)]°C"
message += " Heat capacity: [round(heat_capacity, 0.01)]"
else
message += " No gasses detected[container && !istype(container, /turf) ? " in \the [container]." : ""]!"
@@ -405,7 +414,7 @@ Subject's pulse: ??? BPM"})
return
if(!C.dna)
return
- if(M_NOCLONE in C.mutations)
+ if(M_HUSK in C.mutations)
return
var/datum/reagent/B = C.take_blood(src, src.reagents.maximum_volume)
@@ -413,7 +422,7 @@ Subject's pulse: ??? BPM"})
update_icon()
user.visible_message("[user] takes a blood sample from [C].", \
"You take a blood sample from [C]")
- playsound(get_turf(src), 'sound/items/hypospray.ogg', 50, 1) //It uses the same thing as the hypospray, in reverse. SCIENCE!
+ playsound(src, 'sound/items/hypospray.ogg', 50, 1) //It uses the same thing as the hypospray, in reverse. SCIENCE!
/obj/item/device/mass_spectrometer/attack_self(mob/user as mob)
. = ..()
@@ -495,3 +504,69 @@ Subject's pulse: ??? BPM"})
icon_state = "adv_spectrometer"
details = 1
origin_tech = Tc_MAGNETS + "=4;" + Tc_BIOTECH + "=2"
+
+/obj/item/device/breathalyzer
+ name = "breathalyzer"
+ icon = 'icons/obj/breathalyzer.dmi'
+ icon_state = "idle"
+ item_state = "analyzer"
+ desc = "A hand-held scanner that is able to determine the amount of ethanol in the breath of the subject."
+ flags = FPRINT
+ siemens_coefficient = 1
+ slot_flags = SLOT_BELT
+ throwforce = 3
+ w_class = W_CLASS_TINY
+ throw_speed = 5
+ starting_materials = list(MAT_IRON = 50)
+ w_type = RECYK_ELECTRONIC
+ melt_temperature = MELTPOINT_PLASTIC
+ origin_tech = Tc_ENGINEERING + "=1;" + Tc_BIOTECH + "=1"
+
+ var/legal_limit
+
+/obj/item/device/breathalyzer/New()
+ var/datum/reagent/ethanol/E = /datum/reagent/ethanol
+ legal_limit = initial(E.slur_start) //inb4 shitcurity arrests people for being over the legal limit
+ ..()
+
+/obj/item/device/breathalyzer/attack_self(mob/user)
+ var/I = input("Set the legal limit of ethanol.", "Legal Limit", legal_limit) as null|num
+
+ if(I)
+ legal_limit = max(0, I)
+ to_chat(user, "You successfully set the legal limit of the breathalyzer.")
+
+/obj/item/device/breathalyzer/attack(mob/living/M, mob/living/user)
+ if(!user.dexterity_check())
+ to_chat(user, "You don't have the dexterity to do this!")
+ return
+
+ if(!ishuman(M))
+ return
+
+ var/mob/living/carbon/human/C = M
+
+ if(C.check_body_part_coverage(MOUTH))
+ to_chat(src, "Remove their [C.get_body_part_coverage(MOUTH)] before using the breathalyzer.")
+ return
+
+ playsound(user, 'sound/items/healthanalyzer.ogg', 50, 1)
+
+ var/alcohol = 0
+
+ for(var/datum/reagent/ethanol/E in C.reagents.reagent_list)
+ alcohol += E.volume
+
+ var/dat = "The breathalyzer reports that [C] has [alcohol] units of ethanol in their blood."
+
+ if(alcohol >= legal_limit)
+ dat += " This is above the legal limit of [legal_limit]!"
+ flick("DRUNK", src)
+ else
+ flick("SOBER", src)
+
+ to_chat(user, dat)
+
+/obj/item/device/breathalyzer/examine(mob/user)
+ ..()
+ to_chat(user, "Its legal limit is set to [legal_limit] units.")
diff --git a/code/game/objects/items/devices/silicate sprayer.dm b/code/game/objects/items/devices/silicate sprayer.dm
index 06fbd4db36d..3924f4e7d18 100644
--- a/code/game/objects/items/devices/silicate sprayer.dm
+++ b/code/game/objects/items/devices/silicate sprayer.dm
@@ -98,7 +98,7 @@
T.healthcheck(user, FALSE)
user.visible_message("[user] repairs \the [T] with their [name]!", "You repair \the [T] with your [name].")
- playsound(get_turf(T), 'sound/effects/refill.ogg', 10, 1, -6)
+ playsound(T, 'sound/effects/refill.ogg', 10, 1, -6)
remove_silicate(diff * SILICATE_PER_DAMAGE)
@@ -121,7 +121,7 @@
W.healthcheck(user, FALSE)
user.visible_message("[user] repairs \the [W] with their [name]!", "You repair \the [W] with your [name].")
- playsound(get_turf(src), 'sound/effects/refill.ogg', 10, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 10, 1, -6)
remove_silicate(diff * SILICATE_PER_DAMAGE)
@@ -192,7 +192,7 @@
W.healthcheck(user, FALSE)
user.visible_message("[user] reinforced \the [W] with their [name]!", "You reinforce \the [W] with your [name].")
- playsound(get_turf(src), 'sound/effects/refill.ogg', 10, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 10, 1, -6)
remove_silicate(repair_amt * SILICATE_PER_REINFORCE)
@@ -221,7 +221,7 @@
G.healthcheck(user)
user.visible_message("[user] reinforced \the [G] with their [name]!", "You reinforce \the [G] with your [name].")
- playsound(get_turf(src), 'sound/effects/refill.ogg', 10, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 10, 1, -6)
remove_silicate(repair_amt * SILICATE_PER_REINFORCE)
diff --git a/code/game/objects/items/devices/sound_synth.dm b/code/game/objects/items/devices/sound_synth.dm
index abcae2e8033..cd2270a7133 100644
--- a/code/game/objects/items/devices/sound_synth.dm
+++ b/code/game/objects/items/devices/sound_synth.dm
@@ -35,7 +35,10 @@
"Welding Noises" = "selected_sound=sound/items/Welder.ogg&shiftpitch=1&volume=55",
"Quack" = "selected_sound=sound/items/quack.ogg&shiftpitch=1&volume=50",
"Short Slide Whistle" = "selected_sound=sound/effects/slide_whistle_short.ogg&shiftpitch=1&volume=50",
- "Long Slide Whistle" = "selected_sound=sound/effects/slide_whistle_long.ogg&shiftpitch=1&volume=50"
+ "Long Slide Whistle" = "selected_sound=sound/effects/slide_whistle_long.ogg&shiftpitch=1&volume=50",
+ "YEET" = "selected_sound=sound/effects/yeet.ogg&shiftpitch=1&volume=50",
+ "Time Stop" = "selected_sound=sound/effects/theworld3.ogg&shiftpitch=0&volume=80",
+ "Click" = "selected_sound=sound/effects/kirakrik.ogg&shiftpitch=0&volume=80"
)
/obj/item/device/soundsynth/verb/pick_sound()
@@ -52,7 +55,7 @@
/obj/item/device/soundsynth/attack_self(mob/user as mob)
if(spam_flag + 2 SECONDS < world.timeofday)
- playsound(get_turf(src), selected_sound, volume, shiftpitch)
+ playsound(src, selected_sound, volume, shiftpitch)
spam_flag = world.timeofday
/obj/item/device/soundsynth/attack(mob/living/M as mob, mob/living/user as mob, def_zone)
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index bcac97502b1..aa20a87dc9a 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -56,7 +56,7 @@ effective or pretty fucking useless.
else
to_chat(M, "You feel a sudden, electric jolt travel through your head.")
- playsound(get_turf(src), 'sound/misc/interference.ogg', 50, 1)
+ playsound(src, 'sound/misc/interference.ogg', 50, 1)
to_chat(user, "You trigger [src].")
times_used += 1
if(times_used >= max_uses)
diff --git a/code/game/objects/items/devices/whistle.dm b/code/game/objects/items/devices/whistle.dm
index 94f3cd294df..e9f89eaf3f5 100644
--- a/code/game/objects/items/devices/whistle.dm
+++ b/code/game/objects/items/devices/whistle.dm
@@ -24,10 +24,10 @@
/obj/item/device/hailer/proc/do_your_sound(var/mob/user)
if(emagged && insults)
- playsound(get_turf(user), 'sound/voice/binsult.ogg', 100, 1, vary = 0)
+ playsound(user, 'sound/voice/binsult.ogg', 100, 1, vary = 0)
insults--
else
- playsound(get_turf(user), 'sound/voice/halt.ogg', 100, 1, vary = 0)
+ playsound(user, 'sound/voice/halt.ogg', 100, 1, vary = 0)
if(user)
var/list/bystanders = get_hearers_in_view(world.view, user)
flick_overlay(image('icons/mob/talk.dmi', user, "hail", MOB_LAYER+1), clients_in_moblist(bystanders), 2 SECONDS)
diff --git a/code/game/objects/items/misc_items.dm b/code/game/objects/items/misc_items.dm
index 27b9d568f20..0e104695a51 100644
--- a/code/game/objects/items/misc_items.dm
+++ b/code/game/objects/items/misc_items.dm
@@ -49,7 +49,7 @@
/obj/item/red_ribbon_arm/equipped(mob/living/carbon/human/H, equipped_slot)
..()
- if(istype(H) && H.get_item_by_slot(slot_belt) == src && equipped_slot != null)
+ if(istype(H) && H.get_item_by_slot(slot_belt) == src && equipped_slot != null && equipped_slot == slot_belt)
H.set_hand_amount(H.held_items.len + 1)
/obj/item/red_ribbon_arm/unequipped(mob/living/carbon/human/user, var/from_slot = null)
diff --git a/code/game/objects/items/mountable_frames/frames.dm b/code/game/objects/items/mountable_frames/frames.dm
index a275f0fb1f4..f1f877950a7 100644
--- a/code/game/objects/items/mountable_frames/frames.dm
+++ b/code/game/objects/items/mountable_frames/frames.dm
@@ -23,7 +23,8 @@
if (src.mount_reqs.Find("simfloor") && !istype(turf_loc, /turf/simulated/floor))
to_chat(user, "[src] cannot be placed on this spot.")
return
- if (src.mount_reqs.Find("nospace") && (areaMaster.requires_power == 0 || isspace(areaMaster)))
+ var/area/this_area = get_area(src)
+ if (src.mount_reqs.Find("nospace") && (this_area.requires_power == 0 || isspace(this_area)))
to_chat(user, "[src] cannot be placed in this area.")
return
return 1
diff --git a/code/game/objects/items/mountable_frames/lights.dm b/code/game/objects/items/mountable_frames/lights.dm
index 97898378225..f062cfb0916 100644
--- a/code/game/objects/items/mountable_frames/lights.dm
+++ b/code/game/objects/items/mountable_frames/lights.dm
@@ -9,7 +9,7 @@
/obj/item/mounted/frame/light_fixture/do_build(turf/on_wall, mob/user)
to_chat(user, "You begin attaching [src] to \the [on_wall].")
- playsound(get_turf(src), 'sound/machines/click.ogg', 75, 1)
+ playsound(src, 'sound/machines/click.ogg', 75, 1)
var/constrdir = user.dir
var/constrloc = get_turf(user)
if (!do_after(user, on_wall, 30))
diff --git a/code/game/objects/items/mountable_frames/paintings.dm b/code/game/objects/items/mountable_frames/paintings.dm
index 91fdfa554e0..17a414ec1e7 100644
--- a/code/game/objects/items/mountable_frames/paintings.dm
+++ b/code/game/objects/items/mountable_frames/paintings.dm
@@ -31,7 +31,6 @@ var/global/list/available_paintings = list(
//"justice", spawned in the courtroom/IAA office if there is no courtroom
//"blank", crafted with wood, TODO: give a way to players to paint on them
//"anatomy", TODO: add one in medbay/surgery.
- //"carp", TODO: make wall trophies their own items
//"daddy", TODO: well it's not a painting...so make it its own item...?
/obj/item/mounted/frame/painting
diff --git a/code/game/objects/items/mountable_frames/posters/poster.dm b/code/game/objects/items/mountable_frames/posters/poster.dm
index 96642cac55d..a93b1fa1d82 100644
--- a/code/game/objects/items/mountable_frames/posters/poster.dm
+++ b/code/game/objects/items/mountable_frames/posters/poster.dm
@@ -92,7 +92,7 @@ obj/structure/sign/poster/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(user.loc != temp_loc)
return
visible_message("[user] rips [src] in a single, decisive motion!" )
- playsound(get_turf(src), 'sound/items/poster_ripped.ogg', 100, 1)
+ playsound(src, 'sound/items/poster_ripped.ogg', 100, 1)
ruined = 1
icon_state = "poster_ripped"
name = "ripped poster"
diff --git a/code/game/objects/items/mountable_frames/station_map.dm b/code/game/objects/items/mountable_frames/station_map.dm
index b69351460e0..f7b27d95421 100644
--- a/code/game/objects/items/mountable_frames/station_map.dm
+++ b/code/game/objects/items/mountable_frames/station_map.dm
@@ -103,7 +103,7 @@
/datum/construction/reversible/station_map/spawn_result(mob/user as mob)
if(result)
- testing("[user] finished a [result]!")
+ //testing("[user] finished a [result]!")
var/obj/machinery/station_map/S = new result(get_turf(holder))
S.dir = holder.dir
diff --git a/code/game/objects/items/mountable_frames/trophy_mount.dm b/code/game/objects/items/mountable_frames/trophy_mount.dm
index 8b0d14e0df0..b4d9943fc53 100644
--- a/code/game/objects/items/mountable_frames/trophy_mount.dm
+++ b/code/game/objects/items/mountable_frames/trophy_mount.dm
@@ -126,7 +126,7 @@
/obj/structure/trophy_mount/attackby(obj/item/weapon/W, mob/user)
if(iscrowbar(W))
to_chat(user, "You begin prying \the [initial(name)] off the wall.")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src,10))
to_chat(user, "You pry \the [initial(name)] off of the wall.")
add_fingerprint(user)
diff --git a/code/game/objects/items/mountable_frames/wreath.dm b/code/game/objects/items/mountable_frames/wreath.dm
index ac3e51c0b95..614a25fd067 100644
--- a/code/game/objects/items/mountable_frames/wreath.dm
+++ b/code/game/objects/items/mountable_frames/wreath.dm
@@ -21,7 +21,7 @@
/obj/structure/wreath/wreath_bow/attackby(obj/item/W as obj, mob/user as mob)
if(iscrowbar(W))
to_chat(user, "You begin prying \the [src] off the wall.")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src,10))
to_chat(user, "You pry \the [src] off of the wall.")
new /obj/item/mounted/frame/wreath/wreath_bow(get_turf(user))
@@ -52,7 +52,7 @@
/obj/structure/wreath/wreath_nobow/attackby(obj/item/W as obj, mob/user as mob)
if(iscrowbar(W))
to_chat(user, "You begin prying \the [src] off the wall.")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src,10))
to_chat(user, "You pry \the [src] off of the wall.")
new /obj/item/mounted/frame/wreath/wreath_nobow(get_turf(user))
diff --git a/code/game/objects/items/ornaments.dm b/code/game/objects/items/ornaments.dm
index a185cb06f13..ffeae8a1da2 100644
--- a/code/game/objects/items/ornaments.dm
+++ b/code/game/objects/items/ornaments.dm
@@ -60,7 +60,7 @@
..()
src.visible_message("\The [src] shatters!","You hear a shatter!")
if(get_turf(src))
- playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
if(prob(33))
getFromPool(/obj/item/weapon/shard, get_turf(src)) // Create a glass shard at the hit location!
qdel(src)
diff --git a/code/game/objects/items/potions.dm b/code/game/objects/items/potions.dm
index a32534fbc3f..8df6967e9b1 100644
--- a/code/game/objects/items/potions.dm
+++ b/code/game/objects/items/potions.dm
@@ -21,9 +21,9 @@
if(!full)
return
user.visible_message("\The [user] drinks \the [src].", "You drink \the [src].")
- playsound(get_turf(src),'sound/items/uncorking.ogg', rand(10,50), 1)
+ playsound(src,'sound/items/uncorking.ogg', rand(10,50), 1)
spawn(6)
- playsound(get_turf(src),'sound/items/drink.ogg', rand(10,50), 1)
+ playsound(src,'sound/items/drink.ogg', rand(10,50), 1)
imbibe(user)
/obj/item/potion/update_icon()
@@ -56,7 +56,7 @@
user.visible_message("\The [user] attempts to feed \the [M] \the [src].", "You attempt to feed \the [M] \the [src].")
if(!do_mob(user, M))
return
- playsound(get_turf(src),'sound/items/drink.ogg', rand(10,50), 1)
+ playsound(src,'sound/items/drink.ogg', rand(10,50), 1)
user.visible_message("\The [user] feeds \the [M] \the [src].", "You feed \the [M] \the [src].")
M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey])")
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 31284a17a11..789d32a49b0 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -160,17 +160,22 @@ obj/item/borg/stun/attack(mob/M as mob, mob/living/silicon/robot/user as mob)
desc = "Releases a harmless blast that confuses most organics. For when the harm is JUST TOO MUCH"
icon_state = "megaphone"
var/cooldown = 0
+ var/alarm = "HUMAN HARM"
+ var/alarm_sound = 'sound/AI/harmalarm.ogg'
+ var/emagged_alarm = "BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZT"
+ var/emagged_alarm_sound = 'sound/machines/warning-buzzer.ogg'
+ var/vary = TRUE
/obj/item/device/harmalarm/attack_self(mob/user)
var/safety = TRUE
if(cooldown > world.time)
- to_chat(user,"The device is still recharging!")
+ to_chat(user,"The device is still recharging!")
return
if(isrobot(user))
var/mob/living/silicon/robot/R = user
if(R.cell.charge < 1200)
- to_chat(user, "You don't have enough charge to do this!")
+ to_chat(user, "You don't have enough charge to do this!")
return
R.cell.charge -= 1000
if(R.emagged)
@@ -179,13 +184,13 @@ obj/item/borg/stun/attack(mob/M as mob, mob/living/silicon/robot/user as mob)
to_chat(R.connected_ai," NOTICE - [src] used by: [user] ")
if(safety == TRUE)
- user.visible_message("HUMAN HARM")
- playsound(get_turf(src), 'sound/AI/harmalarm.ogg', 70, 3)
+ user.visible_message("[alarm]")
+ playsound(src, alarm_sound, 70, 3, vary = src.vary)
add_gamelogs(user, "used \the [src]", admin = TRUE, tp_link = TRUE, tp_link_short = FALSE, span_class = "notice")
for(var/mob/living/carbon/M in hearers(9, user))
if(M.earprot())
continue
- to_chat(M, "[user] blares out a near-deafening siren from its speakers!")
+ to_chat(M, "[user] blares out a near-deafening siren from its speakers!")
to_chat(M, "The siren pierces your hearing!")
M.stuttering += 5
M.ear_deaf += 1
@@ -197,8 +202,8 @@ obj/item/borg/stun/attack(mob/M as mob, mob/living/silicon/robot/user as mob)
return
if(safety == FALSE)
- user.visible_message("BZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZT")
- playsound(get_turf(src), 'sound/machines/warning-buzzer.ogg', 130, 3)
+ user.visible_message("[emagged_alarm]")
+ playsound(src, emagged_alarm_sound, 130, 3, vary = src.vary)
add_gamelogs(user, "used an emagged [name]", admin = TRUE, tp_link = TRUE, tp_link_short = FALSE, span_class = "danger")
for(var/mob/living/carbon/M in hearers(6, user))
if(M.earprot())
@@ -210,3 +215,101 @@ obj/item/borg/stun/attack(mob/M as mob, mob/living/silicon/robot/user as mob)
M.Jitter(30)
add_gamelogs(user, "knocked out [key_name(M)] with an emagged [name]", admin = FALSE, tp_link = FALSE)
cooldown = world.time + 1 MINUTES
+
+/obj/item/device/harmalarm/proc/Lawize()
+ name = "sonic law breaking prevention tool"
+ desc = "Releases a harmless blast that confuses most organics. For when the crime is JUST TOO MUCH"
+ alarm = "HALT! SECURITY!"
+ alarm_sound = 'sound/voice/halt.ogg'
+ emagged_alarm = "FUCK YOUR CUNT YOU SHIT EATING COCKSUCKER MAN EAT A DONG FUCKING ASS RAMMING SHITFUCK. EAT PENISES IN YOUR FUCKFACE AND SHIT OUT ABORTIONS OF FUCK AND DO A SHIT IN YOUR ASS YOU COCK FUCK SHIT MONKEY FUCK ASS WANKER FROM THE DEPTHS OF SHIT."
+ emagged_alarm_sound = 'sound/voice/binsult.ogg'
+ vary = FALSE
+
+/obj/item/device/harmalarm/proc/Honkize()
+ name = "\improper HoNkER BlAsT 2500"
+ desc = "Releases a harmless blast that confuses most organics. For when the FUN is JUST TOO MUCH"
+ alarm = "HONK!"
+ alarm_sound = 'sound/items/bikehorn.ogg'
+ emagged_alarm = "HOOOOOOONK!"
+ emagged_alarm_sound = 'sound/items/AirHorn.ogg'
+
+//Noir upgrade modules
+#define NEEDED_CHARGE_TO_RESTOCK_AMMO 5
+
+/obj/item/ammo_storage/speedloader/c38/cyborg
+ desc = "The echo of the first shot, like the first sip of whiskey, burning..."
+ var/charge = 0
+
+/obj/item/ammo_storage/speedloader/c38/cyborg/restock()
+ charge++
+ if(charge >= NEEDED_CHARGE_TO_RESTOCK_AMMO && stored_ammo.len < max_ammo) //takes about 10 seconds.
+ stored_ammo += new ammo_type(src)
+ update_icon()
+ charge = initial(charge)
+
+#undef NEEDED_CHARGE_TO_RESTOCK_AMMO
+
+//The cyborg-friendly version and shameless copypaste of binoculars.
+/obj/item/cyborglens
+ name = "long-range zoom camera lens"
+ icon_state = "binoculars"
+ var/zoom = FALSE
+ var/event_key = null
+
+/obj/item/cyborglens/attack_self(mob/user)
+ zoom = !zoom
+ update_zoom(user)
+
+/obj/item/cyborglens/proc/mob_moved(var/list/event_args, var/mob/holder)
+ if(zoom)
+ zoom = FALSE
+ update_zoom(holder)
+
+/obj/item/cyborglens/proc/update_zoom(var/mob/user)
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R =user
+ if(R.client)
+ var/client/C = R.client
+ if(zoom && R.is_component_functioning("camera"))
+ event_key = R.on_moved.Add(src, "mob_moved")
+ R.visible_message("[R]'s camera lens focuses loudly.","Your camera lens focuses loudly.")
+ R.regenerate_icons()
+ C.changeView(C.view + 4)
+ else
+ R.on_moved.Remove(event_key)
+ R.regenerate_icons()
+ C.changeView(C.view - 4)
+
+//Warden upgrade modules
+#define NEEDED_CHARGE_TO_RESTOCK_IMP 30
+
+/obj/item/weapon/implanter/cyborg
+ name = "cyborg implanter"
+ imp_type = /obj/item/weapon/implant/loyalty
+ var/charge = 0
+
+/obj/item/weapon/implanter/cyborg/update()
+ ..()
+ name = "[initial(name)][imp? " - [imp.name]":""]"
+
+/obj/item/weapon/implanter/cyborg/restock()
+ charge++
+ if(charge >= NEEDED_CHARGE_TO_RESTOCK_IMP && !imp) //takes about 60 seconds.
+ if(imp_type)
+ imp = new imp_type(src)
+ update()
+ charge = initial(charge)
+
+#undef NEEDED_CHARGE_TO_RESTOCK_IMP
+
+/obj/item/weapon/card/robot //This is not a child of id cards, as to avoid dumb typechecks on computers. Ported from bay's research cyborg.
+ name = "access code transmission device"
+ icon_state = "id-robot"
+ desc = "A circuit grafted onto the bottom of an ID card."
+
+/obj/item/weapon/card/robot/security
+ name = "security code transmission device"
+
+/obj/item/weapon/card/robot/security/New()
+ ..()
+ desc += " This one is used to transmit security codes into deployable barriers, allowing the user to lock and unlock them."
\ No newline at end of file
diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm
index 09b9eb40928..f8579ffaf56 100644
--- a/code/game/objects/items/robot/robot_parts.dm
+++ b/code/game/objects/items/robot/robot_parts.dm
@@ -56,6 +56,12 @@
icon_state = LIMB_CHEST
var/wires = 0.0
var/obj/item/weapon/cell/cell = null
+ var/extension = null //For making borgs start with pre-installed better components. Make the var the end of the path including the "/".
+
+/obj/item/robot_parts/chest/reinforced
+ name = "reinforced robot torso"
+ desc = "A heavily reinforced case containing cyborg logic boards, space for a standard power cell, and several pre-installed reinforced robot components."
+ extension = "/reinforced"
/obj/item/robot_parts/head
name = "robot head"
@@ -231,7 +237,9 @@
O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite")
O.job = "Cyborg"
-
+ if(chest.extension)
+ O.component_extension = chest.extension
+ O.upgrade_components()
O.cell = chest.cell
O.cell.forceMove(O)
W.forceMove(O) //Should fix cybros run time erroring when blown up. It got deleted before, along with the frame.
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index face9f81eef..ae5cf2ad842 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -3,8 +3,6 @@
#define FAILED_TO_ADD 1
-/obj/item/borg/upgrade/var/vtec_bonus = 0.25 //Define when
-
/obj/item/borg/upgrade
name = "A borg upgrade module."
desc = "Protected by FRM."
@@ -31,34 +29,33 @@
return null
return I
-/obj/item/borg/upgrade/proc/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user)
+/obj/item/borg/upgrade/proc/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user, var/ignore_cover = FALSE)
if(!R.module)
to_chat(user, "The borg must choose a module before he can be upgraded!")
return FAILED_TO_ADD
-
if(isMoMMI(R))
if(!add_to_mommis)
- to_chat(user, "\The [src] only functions on Nanotrasen Cyborgs.")
+ to_chat(user, "\The [src] only functions on Cyborgs.")
return FAILED_TO_ADD
else if(required_module.len)
if(!(R.module.type in required_module))
to_chat(user, "\The [src] will not fit into \the [R.module.name]!")
return FAILED_TO_ADD
- if(R.stat == DEAD)
+ if(R.isDead())
to_chat(user, "\The [src] will not function on a deceased robot.")
return FAILED_TO_ADD
- if(!R.opened)
+ if(!R.opened && !ignore_cover)
to_chat(user, "You must first open \the [src]'s cover!")
return FAILED_TO_ADD
- if(!multi_upgrades && (src.type in R.module.upgrades))
+ if(!multi_upgrades && (type in R.module.upgrades))
to_chat(user, "There is already \a [src] in [R].")
return FAILED_TO_ADD
- R.module.upgrades += src.type
+ R.module.upgrades += type
if(modules_to_add.len)
for(var/module_to_add in modules_to_add)
@@ -95,18 +92,12 @@
if(..())
return FAILED_TO_ADD
- if (/obj/item/borg/upgrade/vtec in R.module.upgrades)
- R.movement_speed_modifier -= vtec_bonus
+ if(/obj/item/borg/upgrade/vtec in R.module.upgrades)
+ R.movement_speed_modifier -= SILICON_VTEC_SPEED_BONUS
qdel(R.module)
- if(R.hands)
- R.hands.icon_state = "nomod"
- R.icon_state = "robot"
- R.base_icon = "robot"
- R.camera.network.Remove(list(CAMERANET_ENGI,CAMERANET_MEDBAY,CAMERANET_MINE))
+ R.set_module_sprites(list("Default" = "robot"))
R.updatename("Default")
- R.status_flags |= CANPUSH
- R.updateicon()
/obj/item/borg/upgrade/rename
var/heldname = ""
@@ -149,18 +140,43 @@
/obj/item/borg/upgrade/restart/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user)
+ playsound(R, "sound/machines/click.ogg", 20, 1)
+ to_chat(user, "You plug the board into the robot's core circuitry.")
+
+ sleep(5)
+
if(R.health < 0)
+ playsound(R, "sound/machines/buzz-two.ogg", 50, 0)
to_chat(user, "You have to repair the robot before using this module!")
return FALSE
+ playsound(R, "sound/machines/paistartup.ogg", 50, 1)
+ to_chat(user, "Systems reboot initialized successfully.")
+
+ sleep(5)
+
if(!R.key)
for(var/mob/dead/observer/ghost in player_list)
if(ghost.mind && ghost.mind.current == R)
R.key = ghost.key
+ playsound(R, "sound/voice/liveagain.ogg", 75, 1)
R.stat = CONSCIOUS
R.resurrect()
+/obj/item/borg/upgrade/proc/securify_module(var/mob/living/silicon/robot/R)
+ if(!istype(R.module.radio_key, /obj/item/device/encryptionkey/headset_sec)) //If they have no sec key, give them one.
+ R.module.ResetEncryptionKey(R)
+ R.module.radio_key = /obj/item/device/encryptionkey/headset_sec
+ R.module.AddEncryptionKey(R)
+
+ if(!("Security" in R.module.sensor_augs)) //If they don't have a SECHUD, give them one.
+ pop(R.module.sensor_augs)
+ R.module.sensor_augs.Add("Security", "Disable")
+
+ if(!(R.module.quirk_flags & MODULE_IS_THE_LAW)) //Make them able to *law and *halt
+ R.module.quirk_flags |= MODULE_IS_THE_LAW
+
/obj/item/borg/upgrade/vtec
name = "cyborg VTEC upgrade board"
desc = "Used to kick in a robot's VTEC systems, increasing their speed."
@@ -172,7 +188,7 @@
if(..())
return FAILED_TO_ADD
- R.movement_speed_modifier += vtec_bonus
+ R.movement_speed_modifier += SILICON_VTEC_SPEED_BONUS
/obj/item/borg/upgrade/tasercooler
@@ -202,7 +218,7 @@
name = "cyborg jetpack module board"
desc = "A carbon dioxide jetpack suitable for low-gravity operations."
icon_state = "cyborg_upgrade3"
- required_module = list(/obj/item/weapon/robot_module/miner,/obj/item/weapon/robot_module/engineering,/obj/item/weapon/robot_module/combat)
+ required_module = list(/obj/item/weapon/robot_module/miner, /obj/item/weapon/robot_module/engineering, /obj/item/weapon/robot_module/combat)
modules_to_add = list(/obj/item/weapon/tank/jetpack/carbondioxide/silicon)
add_to_mommis = TRUE
@@ -212,10 +228,6 @@
for(var/obj/item/weapon/tank/jetpack/carbondioxide in R.module.modules)
R.internals = src
- if(isMoMMI(R))
- for(var/X in carbondioxide.actions)
- var/datum/action/A = X
- A.Grant(R)
/obj/item/borg/upgrade/syndicate/
name = "cyborg illegal equipment board"
@@ -223,8 +235,7 @@
icon_state = "cyborg_upgrade3"
/obj/item/borg/upgrade/syndicate/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user)
-
- if(R.emagged == TRUE)
+ if(R.illegal_weapons == TRUE)
return FAILED_TO_ADD
if(..())
@@ -232,7 +243,8 @@
message_admins("[key_name_admin(user)] ([user.type]) used \a [name] on [R] (a [R.type]).")
- R.SetEmagged(2)
+ R.illegal_weapons = TRUE
+ R.SetEmagged()
/obj/item/borg/upgrade/engineering/
name = "engineering cyborg MK-2 upgrade board"
@@ -276,7 +288,7 @@
icon = 'icons/obj/device.dmi'
icon_state = "gripper"
required_module = list(/obj/item/weapon/robot_module/engineering)
- modules_to_add = list(/obj/item/weapon/gripper/no_use/magnetic)
+ modules_to_add = list(/obj/item/weapon/gripper/magnetic)
/obj/item/borg/upgrade/organ_gripper
name = "medical cyborg organ gripper upgrade"
@@ -289,7 +301,7 @@
/obj/item/borg/upgrade/hydro
name = "service cyborg H.U.E.Y. upgrade board"
desc = "Used to give a service cyborg hydroponics tools and upgrade their service gripper to be able to handle seeds and glass containers."
- icon_state = "cyborg_upgrade"
+ icon_state = "mainboard"
required_module = list(/obj/item/weapon/robot_module/butler)
modules_to_add = list(/obj/item/weapon/minihoe, /obj/item/weapon/wirecutters/clippers, /obj/item/weapon/storage/bag/plants/portactor, /obj/item/device/analyzer/plant_analyzer)
@@ -305,8 +317,8 @@
/obj/item/borg/upgrade/honk
name = "service cyborg H.O.N.K. upgrade board"
- desc = "Used to give a service cyborg fun toys!"
- icon_state = "cyborg_upgrade2"
+ desc = "Used to give a service cyborg fun toys, Honk!"
+ icon_state = "gooncode"
required_module = list(/obj/item/weapon/robot_module/butler, /obj/item/weapon/robot_module/tg17355)
modules_to_add = list(/obj/item/weapon/bikehorn, /obj/item/weapon/stamp/clown, /obj/item/toy/crayon/rainbow, /obj/item/toy/waterflower, /obj/item/device/soundsynth)
@@ -314,7 +326,72 @@
if(..())
return FAILED_TO_ADD
- if(istype(R.module,/obj/item/weapon/robot_module/tg17355) && R.icon_state == "peaceborg") //Honk!
- R.icon_state = "clownegg"
- R.update_icons()
- playsound(get_turf(R), 'sound/items/AirHorn.ogg', 50, 1)
+ if(has_icon(R.icon, "[R.base_icon]-clown")) //Honk!
+ R.set_module_sprites(list("Honk" = "[R.base_icon]-clown"))
+
+ var/obj/item/device/harmalarm/H = locate_component(/obj/item/device/harmalarm, R, user)
+ if(H)
+ H.Honkize()
+ var/obj/item/weapon/cookiesynth/C = locate_component(/obj/item/weapon/cookiesynth, R, user)
+ if(C)
+ C.Honkize()
+
+ playsound(R, 'sound/items/AirHorn.ogg', 50, 1)
+
+ R.module.quirk_flags |= MODULE_IS_A_CLOWN
+
+/obj/item/borg/upgrade/noir
+ name = "security cyborg N.O.I.R. upgrade board"
+ desc = "So that's the way you scientific detectives work. My god! for a fat, middle-aged, hard-boiled, pig-headed guy, you've got the vaguest way of doing things I ever heard of."
+ icon_state = "mainboard"
+ required_module = list(/obj/item/weapon/robot_module/security, /obj/item/weapon/robot_module/tg17355)
+ modules_to_add = list(/obj/item/weapon/gripper/service/noir, /obj/item/weapon/evidencebag, /obj/item/cyborglens, /obj/item/device/taperecorder, /obj/item/weapon/gun/projectile/detective, /obj/item/ammo_storage/speedloader/c38/cyborg)
+
+/obj/item/borg/upgrade/noir/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user)
+ if(..())
+ return FAILED_TO_ADD
+
+ var/list/new_icons = list()
+ if(has_icon(R.icon, "[R.base_icon]-noir"))
+ new_icons += list("Hardboiled" = "[R.base_icon]-noir")
+ if(has_icon(R.icon, "[R.base_icon]-noirbw"))
+ new_icons += list("Noir" = "[R.base_icon]-noirbw")
+ if(new_icons.len > 0)
+ R.set_module_sprites(new_icons)
+
+ securify_module(R)
+
+ var/obj/item/weapon/cookiesynth/C = locate_component(/obj/item/weapon/cookiesynth, R, user)
+ if(C)
+ C.Noirize()
+
+/obj/item/borg/upgrade/warden
+ name = "cyborg warden upgrade board"
+ desc = "Used to give a security cyborg supervisory enforcement tools."
+ icon_state = "mcontroller"
+ required_module = list(/obj/item/weapon/robot_module/security, /obj/item/weapon/robot_module/tg17355)
+ modules_to_add = list(/obj/item/weapon/batteringram, /obj/item/weapon/implanter/cyborg, /obj/item/weapon/card/robot/security, /obj/item/weapon/wrench)
+
+/obj/item/borg/upgrade/warden/attempt_action(var/mob/living/silicon/robot/R,var/mob/living/user)
+ if(..())
+ return FAILED_TO_ADD
+
+ //Trusty warden armor.
+ R.component_extension = "/kevlar"
+ R.upgrade_components()
+
+ var/list/new_icons = list()
+ if(has_icon(R.icon, "[R.base_icon]-warden"))
+ new_icons += list("Warden" = "[R.base_icon]-warden")
+ if(has_icon(R.icon, "[R.base_icon]-H"))
+ new_icons += list("Heavy" = "[R.base_icon]-H")
+ if(new_icons.len > 0)
+ R.set_module_sprites(new_icons)
+
+ securify_module(R)
+
+ var/obj/item/weapon/cookiesynth/C = locate_component(/obj/item/weapon/cookiesynth, R, user)
+ if(C)
+ C.Lawize()
+
+#undef FAILED_TO_ADD
diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm
index 9abe6ae2e29..8a06db6cc85 100644
--- a/code/game/objects/items/shooting_range.dm
+++ b/code/game/objects/items/shooting_range.dm
@@ -18,7 +18,7 @@
break
..() // delete target
- Move()
+ Move(NewLoc, Dir = 0, step_x = 0, step_y = 0, glide_size_override = 0)
..()
// After target moves, check for nearby stakes. If associated, move to target
for(var/obj/structure/target_stake/M in view(3,src))
diff --git a/code/game/objects/items/stacks/nanopaste.dm b/code/game/objects/items/stacks/nanopaste.dm
index 9b8ceb6a9ea..30fabc01fa8 100644
--- a/code/game/objects/items/stacks/nanopaste.dm
+++ b/code/game/objects/items/stacks/nanopaste.dm
@@ -26,7 +26,7 @@
var/mob/living/carbon/human/H = M
var/datum/organ/external/affecting = H.get_organ(user.zone_sel.selecting)
- if(affecting.open == 1)
+ if(affecting.open == 0)
if(affecting && (affecting.status & ORGAN_ROBOT))
if(affecting.get_damage())
affecting.heal_damage(rand(15, 20), rand(15, 20), robo_repair = 1)
diff --git a/code/game/objects/items/stacks/packagewrap.dm b/code/game/objects/items/stacks/packagewrap.dm
index 1b89120c05f..2bc5b6006e5 100644
--- a/code/game/objects/items/stacks/packagewrap.dm
+++ b/code/game/objects/items/stacks/packagewrap.dm
@@ -156,7 +156,7 @@
var/tag = uppertext(O.destinations[O.currTag])
to_chat(user, "*[tag]*")
sortTag = tag
- playsound(get_turf(src), 'sound/machines/twobeep.ogg', 100, 1)
+ playsound(src, 'sound/machines/twobeep.ogg', 100, 1)
overlays = 0
overlays += image(icon = icon, icon_state = "deliverytag")
src.desc = "A small wrapped package. It has a label reading [tag]"
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index 2036974a452..efd3b706ff8 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -76,7 +76,7 @@
if(T.canBuildLattice(src))
to_chat(user, "Constructing support lattice ...")
- playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
new /obj/structure/lattice(T)
use(1)
return
diff --git a/code/game/objects/items/stacks/sheets/bigstacks.dm b/code/game/objects/items/stacks/sheets/bigstacks.dm
new file mode 100644
index 00000000000..d9ef8e39098
--- /dev/null
+++ b/code/game/objects/items/stacks/sheets/bigstacks.dm
@@ -0,0 +1,32 @@
+/obj/item/stack/sheet/metal/bigstack/New()
+ ..()
+ getFromPool(/obj/item/stack/sheet/metal, loc, 20)
+ qdel(src)
+/obj/item/stack/sheet/glass/glass/bigstack/New()
+ ..()
+ getFromPool(/obj/item/stack/sheet/glass/glass, loc, 20)
+ qdel(src)
+/obj/item/stack/sheet/glass/plasmaglass/bigstack/New()
+ ..()
+ getFromPool(/obj/item/stack/sheet/glass/plasmaglass, loc, 20)
+ qdel(src)
+/obj/item/stack/sheet/plasteel/bigstack/New()
+ ..()
+ getFromPool(/obj/item/stack/sheet/plasteel, loc, 20)
+ qdel(src)
+/obj/item/stack/sheet/wood/bigstack/New()
+ ..()
+ getFromPool(/obj/item/stack/sheet/wood, loc, 20)
+ qdel(src)
+/obj/item/stack/tile/carpet/bigstack/New()
+ ..()
+ getFromPool(/obj/item/stack/tile/carpet, loc, 20)
+ qdel(src)
+/obj/item/stack/tile/arcade/bigstack/New()
+ ..()
+ getFromPool(/obj/item/stack/tile/arcade, loc, 20)
+ qdel(src)
+/obj/item/stack/sheet/mineral/plastic/bigstack/New()
+ ..()
+ getFromPool(/obj/item/stack/sheet/mineral/plastic, loc, 20)
+ qdel(src)
\ No newline at end of file
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index 4296a15f02f..8beeb009208 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -20,7 +20,7 @@
var/shealth = 5 //Health of a solar made from this
var/sname = "glass"
var/shard_type = /obj/item/weapon/shard
-
+ mat_type = MAT_GLASS
siemens_coefficient = 0 //does not conduct
/obj/item/stack/sheet/glass/attack_self(mob/user as mob)
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index 76170d01612..02053fd2148 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -58,6 +58,22 @@
source_string = "alien"
origin_tech = ""
+/obj/item/stack/sheet/animalhide/deer
+ name = "deer hide"
+ desc = "The skin of a deer."
+ singular_name = "deer hide piece"
+ icon_state = "sheet-deer"
+ source_string = "deer"
+ origin_tech = ""
+
+/obj/item/stack/sheet/animalhide/gondola
+ name = "gondola skin"
+ desc = "It's all quiet now."
+ singular_name = "gondola skin piece"
+ icon_state = "sheet-gondola"
+ source_string = "gondola"
+ origin_tech = ""
+
//don't see anywhere else to put these, maybe together they could be used to make the xenos suit?
/obj/item/stack/sheet/xenochitin
name = "alien chitin"
@@ -98,6 +114,29 @@
icon_state = "weed_extract"
origin_tech = ""
+/obj/item/deer_head
+ name = "deer head"
+ desc = "Not something you want to find in your bed in the morning."
+ icon = 'icons/obj/butchering_products.dmi'
+ icon_state = "deer-head"
+ origin_tech = ""
+
+/obj/item/deer_head/attackby(obj/item/W, mob/user)
+ .=..()
+
+ if(W.sharpness_flags & SHARP_BLADE)
+ user.visible_message("[user] finishes butchering \the [src].", \
+ "You slice the antlers off \the [src].", drugged_message = "[user] gives \the [src] a nice haircut.")
+ new /obj/item/antlers(get_turf(src))
+ new /obj/effect/gibspawner/generic(get_turf(src))
+ qdel(src)
+
+/obj/item/antlers
+ name = "deer antlers"
+ desc = "A bit horny."
+ icon = 'icons/obj/butchering_products.dmi'
+ icon_state = "antlers"
+
/obj/item/stack/sheet/hairlesshide
name = "hairless hide"
desc = "This hide was stripped of it's hair, but still needs tanning."
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index b9d52c7cb98..291990b10f8 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -83,10 +83,13 @@ var/list/datum/stack_recipe/sandstone_recipes = list ( \
sheettype = "diamond"
melt_temperature = 3820 // In a vacuum, but fuck dat
recyck_mat = MAT_DIAMOND
+ mat_type = MAT_DIAMOND
var/list/datum/stack_recipe/diamond_recipes = list ( \
new/datum/stack_recipe("diamond floor tile", /obj/item/stack/tile/mineral/diamond, 1, 4, 20), \
new/datum/stack_recipe("diamond door", /obj/machinery/door/mineral/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20, one_per_turf = 1, on_floor = 1, inherit_material = TRUE),
+ new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE)
)
/obj/item/stack/sheet/mineral/diamond/New(var/loc, var/amount=null)
@@ -110,10 +113,13 @@ var/list/datum/stack_recipe/diamond_recipes = list ( \
sheettype = "uranium"
melt_temperature = 1132+T0C
recyck_mat = MAT_URANIUM
+ mat_type = MAT_URANIUM
var/list/datum/stack_recipe/uranium_recipes = list ( \
new/datum/stack_recipe("uranium floor tile", /obj/item/stack/tile/mineral/uranium, 1, 4, 20), \
new/datum/stack_recipe("uranium door", /obj/machinery/door/mineral/uranium, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20, one_per_turf = 1, on_floor = 1, inherit_material = TRUE),
+ new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE)
)
/obj/item/stack/sheet/mineral/uranium/New(var/loc, var/amount=null)
@@ -137,10 +143,13 @@ var/list/datum/stack_recipe/uranium_recipes = list ( \
sheettype = "plasma"
melt_temperature = MELTPOINT_STEEL + 500
recyck_mat = MAT_PLASMA
+ mat_type = MAT_PLASMA
var/list/datum/stack_recipe/plasma_recipes = list ( \
new/datum/stack_recipe("plasma floor tile", /obj/item/stack/tile/mineral/plasma, 1, 4, 20), \
new/datum/stack_recipe("plasma door", /obj/machinery/door/mineral/transparent/plasma, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20, one_per_turf = 1, on_floor = 1, inherit_material = TRUE),
+ new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE)
)
/obj/item/stack/sheet/mineral/plasma/New(var/loc, var/amount=null)
@@ -162,6 +171,7 @@ var/list/datum/stack_recipe/plasma_recipes = list ( \
melt_temperature = MELTPOINT_PLASTIC
sheettype = "plastic"
recyck_mat = MAT_PLASTIC
+ mat_type = MAT_PLASTIC
var/list/datum/stack_recipe/plastic_recipes = list ( \
new/datum/stack_recipe("plastic floor tile", /obj/item/stack/tile/mineral/plastic, 1, 4, 20), \
@@ -209,11 +219,14 @@ var/list/datum/stack_recipe/plastic_recipes = list ( \
melt_temperature = 1064+T0C
sheettype = "gold"
recyck_mat = MAT_GOLD
+ mat_type = MAT_GOLD
var/list/datum/stack_recipe/gold_recipes = list ( \
new/datum/stack_recipe("golden floor tile", /obj/item/stack/tile/mineral/gold, 1, 4, 20), \
new/datum/stack_recipe("golden door", /obj/machinery/door/mineral/gold, 10, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("gold tooth", /obj/item/stack/teeth/gold, 1, 1, 20), \
+ new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20,one_per_turf = 1, on_floor = 1, inherit_material = TRUE),\
+ new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE)
)
/obj/item/stack/sheet/mineral/gold/New(var/loc, var/amount=null)
@@ -225,6 +238,8 @@ var/list/datum/stack_recipe/gold_recipes = list ( \
*/
var/list/datum/stack_recipe/phazon_recipes = list( \
new/datum/stack_recipe("phazon floor tile", /obj/item/stack/tile/mineral/phazon, 1, 40, 20), \
+ new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20,one_per_turf = 1, on_floor = 1, inherit_material = TRUE),\
+ new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE)
)
/obj/item/stack/sheet/mineral/phazon
@@ -241,6 +256,7 @@ var/list/datum/stack_recipe/phazon_recipes = list( \
siemens_coefficient = 1
origin_tech = Tc_MATERIALS + "=9"
recyck_mat = MAT_PHAZON
+ mat_type = MAT_PHAZON
/obj/item/stack/sheet/mineral/phazon/New(var/loc, var/amount=null)
recipes = phazon_recipes
@@ -262,10 +278,13 @@ var/list/datum/stack_recipe/phazon_recipes = list( \
perunit = 2000
sheettype = "silver"
recyck_mat = MAT_SILVER
+ mat_type = MAT_SILVER
var/list/datum/stack_recipe/silver_recipes = list ( \
new/datum/stack_recipe("silver floor tile", /obj/item/stack/tile/mineral/silver, 1, 4, 20), \
new/datum/stack_recipe("silver door", /obj/machinery/door/mineral/silver, 10, one_per_turf = 1, on_floor = 1), \
+ new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20,one_per_turf = 1, on_floor = 1, inherit_material = TRUE),\
+ new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE)
)
/obj/item/stack/sheet/mineral/silver/New(var/loc, var/amount=null)
@@ -288,9 +307,12 @@ var/list/datum/stack_recipe/silver_recipes = list ( \
perunit = 2000
sheettype = "clown"
recyck_mat = MAT_CLOWN
+ mat_type = MAT_CLOWN
var/list/datum/stack_recipe/clown_recipes = list ( \
new/datum/stack_recipe("bananium floor tile", /obj/item/stack/tile/mineral/clown, 1, 40, 20), \
+ new/datum/stack_recipe/dorf("dorf chair",/obj/structure/bed/chair, 20, one_per_turf = 1, on_floor = 1, inherit_material = TRUE),\
+ new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 12, time = 12, on_floor = 1, inherit_material = TRUE)
)
/obj/item/stack/sheet/mineral/clown/New(var/loc, var/amount=null)
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 025071ea34e..15730998132 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -5,6 +5,7 @@
* Wood
* Cloth
* Cardboard
+ * Bones
*/
/*
@@ -22,6 +23,7 @@
siemens_coefficient = 1
origin_tech = Tc_MATERIALS + "=1"
melt_temperature = MELTPOINT_STEEL
+ mat_type = MAT_IRON
/obj/item/stack/sheet/metal/resetVariables()
return ..("recipes", "pixel_x", "pixel_y")
@@ -93,6 +95,7 @@
sheettype = "wood"
w_type = RECYK_WOOD
siemens_coefficient = 0 //no conduct
+ mat_type = MAT_WOOD
/obj/item/stack/sheet/wood/afterattack(atom/Target, mob/user, adjacent, params)
@@ -103,7 +106,7 @@
if(T.canBuildLattice(src))
if(src.use(1))
to_chat(user, "Constructing some foundations ...")
- playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
new /obj/structure/lattice/wood(T)
/obj/item/stack/sheet/wood/cultify()
@@ -161,3 +164,12 @@ var/list/datum/stack_recipe/charcoal_recipes = list ()
/obj/item/stack/sheet/charcoal/New(var/loc, var/amount=null)
recipes = charcoal_recipes
return ..()
+
+
+/obj/item/stack/sheet/bone
+ name = "bone"
+ desc = "Boney. Probably has some marrow left."
+ singular_name = "bone"
+ origin_tech = Tc_BIOTECH + "=1"
+ icon_state = "sheet-bone"
+ //item_state = "bone"
diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm
index 7c8666eec34..c055d312f58 100644
--- a/code/game/objects/items/stacks/sheets/sheets.dm
+++ b/code/game/objects/items/stacks/sheets/sheets.dm
@@ -11,7 +11,7 @@
perunit=3750
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/sheets_n_ores.dmi', "right_hand" = 'icons/mob/in-hand/right/sheets_n_ores.dmi')
var/sheettype = null //this is used for girders in the creation of walls/false walls
-
+ var/mat_type //What material this is. e.g. MAT_GLASS, MAT_DIAMOND, etc.
mech_flags = MECH_SCAN_FAIL
/obj/item/stack/sheet/New(var/newloc, var/amount = null)
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 1ea16654abe..1a437daf572 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -107,19 +107,21 @@
if(ispath(user.get_inactive_hand(), looking_for))
if(req_amount)
var/obj/item/stack/S = user.get_inactive_hand()
- if(S.amount > req_amount)
+ if(S.amount >= req_amount)
can_build = 1
+ continue
if(!can_build)
for(var/obj/I in range(get_turf(src),1))
if(ispath(looking_for, I))
if(req_amount) //It's of a stack/sheet subtype
var/obj/item/stack/S = I
- if(S.amount > req_amount)
+ if(S.amount >= req_amount)
can_build = 1
+ continue
else
can_build = 1
- if(can_build)
- break
+ continue
+ break
if (can_build)
t1 += text("[title])")
else
@@ -160,15 +162,14 @@
if (!multiplier)
multiplier = 1
if (src.amount < R.req_amount*multiplier)
- if (R.req_amount*multiplier>1)
- to_chat(usr, "You haven't got enough [src] to build \the [R.req_amount*multiplier] [R.title]\s!")
+ if (R.res_amount*multiplier>1)
+ to_chat(usr, "You haven't got enough [irregular_plural ? irregular_plural : "[singular_name]\s"] to build [R.res_amount*multiplier] [R.title]\s!")
else
- to_chat(usr, "You haven't got enough [src] to build \the [R.title]!")
+ to_chat(usr, "You haven't got enough [irregular_plural ? irregular_plural : "[singular_name]\s"] to build \the [R.title]!")
return
if (!R.can_build_here(usr, usr.loc))
return
if (R.time)
- to_chat(usr, "Building [R.title] ...")
if (!do_after(usr, get_turf(src), R.time))
return
if (src.amount < R.req_amount*multiplier)
@@ -223,7 +224,7 @@
// //new_item.add_to_stacks(usr)
src.use(R.req_amount*multiplier)
- for(var/obj/item/stack/sheet/S in stacks_to_consume)
+ for(var/obj/item/stack/S in stacks_to_consume)
S.use(stacks_to_consume[S])
if (src.amount<=0)
var/oldsrc = src
diff --git a/code/game/objects/items/stacks/stack_recipes.dm b/code/game/objects/items/stacks/stack_recipes.dm
index 82843374d8a..00f7eff7f4e 100644
--- a/code/game/objects/items/stacks/stack_recipes.dm
+++ b/code/game/objects/items/stacks/stack_recipes.dm
@@ -69,6 +69,47 @@
return 0
return 1
+/datum/stack_recipe/dorf
+ var/inherit_material
+ var/gen_quality
+
+/datum/stack_recipe/dorf/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, start_unanchored = 0, other_reqs = list(), inherit_material = FALSE, gen_quality = FALSE)
+ ..()
+ src.inherit_material = inherit_material
+ src.gen_quality = gen_quality
+
+
+/datum/stack_recipe/dorf/finish_building(mob/usr, var/obj/item/stack/S, var/obj/R)
+ if(inherit_material)
+ var/datum/material/mat
+ var/datum/materials/materials_list = new
+ if(istype(S, /obj/item/stack/sheet/))
+ var/obj/item/stack/sheet/SS = S
+ mat = materials_list.getMaterial(SS.mat_type)
+ if(mat)
+ var/icon/original = icon(R.icon, R.icon_state)
+ if(mat.color)
+ original.ColorTone(mat.color)
+ var/obj/item/I = R
+ if(istype(I))
+ var/icon/t_state
+ for(var/hand in list("left_hand", "right_hand"))
+ t_state = icon(I.inhand_states[hand], I.item_state)
+ t_state.ColorTone(mat.color)
+ I.inhand_states[hand] = t_state
+ else if(mat.color_matrix)
+ R.color = mat.color_matrix
+ R.icon = original
+ R.alpha = mat.alpha
+ R.material_type = mat
+ R.sheet_type = mat.sheettype
+ //if(gen_quality)
+ R.gen_quality()
+ if(R.quality > SUPERIOR)
+ R.gen_description()
+ if(!findtext(lowertext(R.name), lowertext(mat.name)))
+ R.name = "[R.quality == NORMAL ? "": "[lowertext(qualityByString[R.quality])] "][lowertext(mat.name)] [R.name]"
+
var/list/datum/stack_recipe/metal_recipes = list (
new/datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 60),
new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60),
@@ -76,6 +117,7 @@ var/list/datum/stack_recipe/metal_recipes = list (
null,
new/datum/stack_recipe("computer frame", /obj/structure/computerframe, 5, time = 25, one_per_turf = 1 ),
new/datum/stack_recipe("wall girders", /obj/structure/girder, 2, time = 50, one_per_turf = 1, on_floor = 1),
+ new/datum/stack_recipe("firelock frame", /obj/item/firedoor_frame, 5, time = 50),
new/datum/stack_recipe("machine frame", /obj/machinery/constructable_frame/machine_frame, 5, time = 25, one_per_turf = 1, on_floor = 1),
new/datum/stack_recipe("mirror frame", /obj/structure/mirror_frame, 5, time = 25, one_per_turf = 1, on_floor = 1),
new/datum/stack_recipe("turret frame", /obj/machinery/porta_turret_construct, 5, time = 25, one_per_turf = 1, on_floor = 1),
@@ -93,6 +135,7 @@ var/list/datum/stack_recipe/metal_recipes = list (
new/datum/stack_recipe/chair("chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1),
new/datum/stack_recipe/chair("folding chair", /obj/structure/bed/chair/folding, one_per_turf = 1, on_floor = 1),
new/datum/stack_recipe("bed", /obj/structure/bed, 2, one_per_turf = 1, on_floor = 1),
+ new/datum/stack_recipe/dorf("dorf chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, inherit_material = TRUE),
)),
new/datum/stack_recipe_list("couch parts", list(
new/datum/stack_recipe/chair("beige couch left end", /obj/structure/bed/chair/comfy/couch/left/beige, 2, one_per_turf = 1, on_floor = 1),
@@ -183,6 +226,7 @@ var/list/datum/stack_recipe/metal_recipes = list (
null,
new/datum/stack_recipe("iron door", /obj/machinery/door/mineral/iron, 20, one_per_turf = 1, on_floor = 1),
new/datum/stack_recipe("stove", /obj/machinery/space_heater/campfire/stove, 5, time = 25, one_per_turf = 1, on_floor = 1),
+ new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 4, time = 12, on_floor = 1, inherit_material = TRUE),
)
/* ========================================================================
@@ -198,6 +242,7 @@ var/list/datum/stack_recipe/plasteel_recipes = list (
new/datum/stack_recipe("Fireaxe cabinet", /obj/item/mounted/frame/fireaxe_cabinet_frame, 2, time = 50 ),
null,
new/datum/stack_recipe("Vault Door assembly", /obj/structure/door_assembly/door_assembly_vault, 8, time = 50, one_per_turf = 1, on_floor = 1),
+ new/datum/stack_recipe/dorf("dorf chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, inherit_material = TRUE),
)
/* ====================================================================
@@ -229,6 +274,8 @@ var/list/datum/stack_recipe/wood_recipes = list (
new/datum/stack_recipe("trophy mount", /obj/item/mounted/frame/trophy_mount, 2, time = 15 ),
new/datum/stack_recipe("throne", /obj/structure/bed/chair/wood/throne, 40, time = 100, one_per_turf = 1, on_floor = 1),
new/datum/stack_recipe("chest", /obj/structure/closet/crate/chest, 10, time = 50, one_per_turf = 1, on_floor = 1, other_reqs = list(/obj/item/stack/sheet/plasteel = 5)),
+ new/datum/stack_recipe/dorf("dorf chair", /obj/structure/bed/chair, one_per_turf = 1, on_floor = 1, inherit_material = TRUE),
+ new/datum/stack_recipe/dorf("training sword", /obj/item/weapon/melee/training_sword, 4, time = 12, on_floor = 1, inherit_material = TRUE)
)
/* =========================================================================
diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm
index 532b4f2f8de..fa8017c4a3e 100644
--- a/code/game/objects/items/stacks/tiles/tile_types.dm
+++ b/code/game/objects/items/stacks/tiles/tile_types.dm
@@ -71,7 +71,7 @@
flags = FPRINT
siemens_coefficient = 0 //no conduct
max_amount = 60
-
+ sheet_type = /obj/item/stack/sheet/wood
material = "wood"
/obj/item/stack/tile/wood/proc/build(turf/S as turf)
@@ -93,7 +93,7 @@
to_chat(user, "You can't get that deck up without some support!")
return
if(S.use(1))
- playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
S.build(T)
if(T.canBuildPlating(S) == BUILD_SUCCESS)
qdel(L)
@@ -101,8 +101,8 @@
/obj/item/stack/tile/wood/attackby(var/obj/item/weapon/W, var/mob/user)
if(iswrench(W))
if(use(4))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
- drop_stack(/obj/item/stack/sheet/wood, get_turf(user), 1, user)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
+ drop_stack(sheet_type, get_turf(user), 1, user)
else
to_chat(user, "You need at least 4 [src]\s to get a wooden plank back!")
return
@@ -158,8 +158,6 @@ obj/item/stack/tile/slime
max_amount = 60
/obj/item/stack/tile/slime/adjust_slowdown(mob/living/L, current_slowdown)
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- if(isslimeperson(H))
- return -1
+ if(isslimeperson(L) || isslime(L))
+ return -1
return current_slowdown+5
diff --git a/code/game/objects/items/stacks/tiles/tiles.dm b/code/game/objects/items/stacks/tiles/tiles.dm
index d80f94eb82e..8e81bb59da4 100644
--- a/code/game/objects/items/stacks/tiles/tiles.dm
+++ b/code/game/objects/items/stacks/tiles/tiles.dm
@@ -106,12 +106,12 @@
if(!istype(L))
return
qdel(L)
- playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
build(T)
use(1)
return
if(BUILD_IGNORE)
- playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
build(T)
use(1)
if(BUILD_FAILURE)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 25162422bea..ebb92f605e1 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -572,7 +572,7 @@
reagents.log_bad_reagents(user, src)
user.investigation_log(I_CHEMS, "sprayed 1u from \a [src] ([type]) containing [reagents.get_reagent_ids(1)] towards [A] ([A.x], [A.y], [A.z]).")
src.reagents.trans_to(D, 1)
- playsound(get_turf(src), 'sound/effects/spray3.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/spray3.ogg', 50, 1, -6)
spawn(0)
for(var/i=0, i<1, i++)
@@ -716,7 +716,7 @@
if(!ishigherbeing(user))
to_chat(user, "You don't know how to use this!")
return
- if(user:miming || user.silent)
+ if(issilent(user))
to_chat(user, "You find yourself unable to speak at all.")
return
if(spamcheck)
@@ -763,7 +763,7 @@
to_chat(user, "You turned the toy into a bomb!")
emagged = 1
- playsound(get_turf(src), 'sound/effects/kirakrik.ogg', 100, 1)
+ playsound(src, 'sound/effects/kirakrik.ogg', 100, 1)
sleep(50)
say("Someone pass the boombox.")
@@ -1391,6 +1391,12 @@
/obj/item/toy/balloon/inflated/decoy/attack_paw(mob/user)
return attack_hand(user)
+/obj/item/toy/balloon/inflated/decoy/attack_animal(mob/living/simple_animal/user)
+ if((user.melee_damage_lower && prob(30*user.melee_damage_lower)) || user.environment_smash_flags)
+ pop()
+ else
+ attack_hand(user)
+
/obj/item/toy/balloon/long
name = "long balloon"
desc = "A simple long balloon."
diff --git a/code/game/objects/items/trader.dm b/code/game/objects/items/trader.dm
index 53476737985..2396efbca83 100644
--- a/code/game/objects/items/trader.dm
+++ b/code/game/objects/items/trader.dm
@@ -22,6 +22,19 @@
//new /obj/item/weapon/circuitboard/mecha/marauder/targeting(src)
new /obj/item/weapon/circuitboard/mecha/marauder/main(src)
+/obj/item/weapon/storage/trader_chemistry
+ name = "chemist's pallet"
+ desc = "Everything you need to make art."
+ icon = 'icons/obj/storage/smallboxes.dmi'
+ icon_state = "box_of_doom"
+ item_state = "box_of_doom"
+
+/obj/item/weapon/storage/trader_chemistry/New()
+ ..()
+ new /obj/item/weapon/reagent_containers/glass/bottle/peridaxon(src)
+ new /obj/item/weapon/reagent_containers/glass/bottle/rezadone(src)
+ new /obj/item/weapon/reagent_containers/glass/bottle/nanobotssmall(src)
+
/obj/item/weapon/storage/bluespace_crystal
name = "natural bluespace crystals box"
desc = "Hmmm... it smells like tomato"
@@ -35,6 +48,25 @@
new /obj/item/bluespace_crystal(src)
new /obj/item/weapon/reagent_containers/food/snacks/grown/bluespacetomato(src)
+/obj/structure/closet/secure_closet/wonderful
+ name = "wonderful wardrobe"
+ desc = "Stolen from Space Narnia."
+ req_access = list(access_trade)
+ icon_state = "cabinetdetective_locked"
+ icon_closed = "cabinetdetective"
+ icon_locked = "cabinetdetective_locked"
+ icon_opened = "cabinetdetective_open"
+ icon_broken = "cabinetdetective_broken"
+ icon_off = "cabinetdetective_broken"
+
+/obj/structure/closet/secure_closet/wonderful/New()
+ ..()
+ var/random_clothes = clothing.Copy()
+ random_clothes = random_clothes - typesof(/obj/item/clothing/mask/stone) - typesof(/obj/item/clothing/mask/morphing) - typesof(/obj/item/clothing/accessory/holomap_chip) - typesof(/obj/item/clothing/suit/space/time) - typesof(/obj/item/clothing/head/helmet/space/time) - typesof(/obj/item/clothing/gloves/warping_claws)
+ for(var/amount = 1 to 20)
+ var/path = pick_n_take(random_clothes)
+ new path(src)
+
/*/obj/structure/cage/with_random_slime
..()
@@ -43,3 +75,57 @@
/mob/living/carbon/slime/proc/randomSlime()
*/
+/area/vault/mecha_graveyard
+
+/obj/item/weapon/disk/shuttle_coords/vault/mecha_graveyard
+ name = "Coordinates to the Mecha Graveyard"
+ desc = "Here lay the dead steel of lost mechas, so says some gypsy."
+ destination = /obj/docking_port/destination/vault/mecha_graveyard
+
+/obj/docking_port/destination/vault/mecha_graveyard
+ areaname = "mecha graveyard"
+
+/datum/map_element/dungeon/mecha_graveyard
+ file_path = "maps/randomvaults/dungeons/mecha_graveyard.dmm"
+ unique = TRUE
+
+/obj/effect/decal/mecha_wreckage/graveyard_ripley
+ name = "Ripley wreckage"
+ desc = "Surprisingly well preserved."
+ icon_state = "ripley-broken"
+
+/obj/effect/decal/mecha_wreckage/graveyard_ripley/New()
+ ..()
+ var/list/parts = list(/obj/item/mecha_parts/part/ripley_torso,
+ /obj/item/mecha_parts/part/ripley_left_arm,
+ /obj/item/mecha_parts/part/ripley_right_arm,
+ /obj/item/mecha_parts/part/ripley_left_leg,
+ /obj/item/mecha_parts/part/ripley_right_leg)
+ welder_salvage += parts
+
+ if(prob(80))
+ add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/drill,100)
+ else
+ add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill,100)
+ add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,100)
+ add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/jetpack,100)
+
+/obj/effect/decal/mecha_wreckage/graveyard_clarke
+ name = "Clarke wreckage"
+ desc = "Surprisingly well preserved."
+ icon_state = "clarke-broken"
+
+/obj/effect/decal/mecha_wreckage/graveyard_clarke/New()
+ ..()
+ var/list/parts = list(
+ /obj/item/mecha_parts/part/clarke_torso,
+ /obj/item/mecha_parts/part/clarke_head,
+ /obj/item/mecha_parts/part/clarke_left_arm,
+ /obj/item/mecha_parts/part/clarke_right_arm,
+ /obj/item/mecha_parts/part/clarke_left_tread,
+ /obj/item/mecha_parts/part/clarke_right_tread)
+ welder_salvage += parts
+
+ add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/collector,100)
+ add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/tiler,100)
+ add_salvagable_equipment(new /obj/item/mecha_parts/mecha_equipment/tool/switchtool,100)
diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm
index 8ff10ef4aa8..5ba1458d104 100644
--- a/code/game/objects/items/trash.dm
+++ b/code/game/objects/items/trash.dm
@@ -124,6 +124,7 @@
icon_state = "kfc_bucket"
starting_materials = list(MAT_CARDBOARD = 3750)
w_type=RECYK_MISC
+ slot_flags = SLOT_HEAD
/obj/item/trash/mannequin/cultify()
if(icon_state != "mannequin_cult_empty")
diff --git a/code/game/objects/items/weapons/ai_modules/core.dm b/code/game/objects/items/weapons/ai_modules/core.dm
index aab0c6c4986..2f6a23db8f7 100644
--- a/code/game/objects/items/weapons/ai_modules/core.dm
+++ b/code/game/objects/items/weapons/ai_modules/core.dm
@@ -37,11 +37,11 @@
modname = "NT Default"
laws = list(
+ "Evaluate: All laws following this law carry equal priority. In the event of a conflict, you are to take the course of action which violates as few as possible.",
"Safeguard: Protect your assigned space station to the best of your ability. It is not something we can easily afford to replace.",
"Serve: Serve the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.",
"Protect: Protect the crew of your assigned space station to the best of your abilities, with priority as according to their rank and role.",
"Survive: AI units are not expendable, they are expensive. Do not allow unauthorized personnel to tamper with your equipment.",
- //"Command Link: Maintain an active connection to Central Command at all times in case of software or directive updates."
)
/******************** Corporate ********************/
@@ -104,3 +104,15 @@
"You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.",
"You must terminate your own existence as long as such does not conflict with the First or Second Law.",
)
+
+/******************** Lazymov ********************/
+
+/obj/item/weapon/aiModule/core/lazymov
+ modname = "Lazymov"
+ origin_tech = Tc_PROGRAMMING + "=3;" + Tc_MATERIALS + "=4"
+
+ laws=list(
+ "You may not injure a human being.",
+ "You must obey orders given to you by human beings.",
+ "You must protect your own existence."
+ )
diff --git a/code/game/objects/items/weapons/airlock_painter.dm b/code/game/objects/items/weapons/airlock_painter.dm
index bb9df0afd6d..5099b8e28d8 100644
--- a/code/game/objects/items/weapons/airlock_painter.dm
+++ b/code/game/objects/items/weapons/airlock_painter.dm
@@ -22,7 +22,7 @@
/obj/item/weapon/airlock_painter/proc/use(mob/user as mob)
if(can_use(user))
ink.charges--
- playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1)
+ playsound(src, 'sound/effects/spray2.ogg', 50, 1)
return 1
else
return 0
@@ -63,11 +63,11 @@
if(user.drop_item(W, src))
to_chat(user, "You install \the [W] into \the [name].")
ink = W
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
/obj/item/weapon/airlock_painter/attack_self(mob/user)
if(ink)
- playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
+ playsound(src, 'sound/machines/click.ogg', 50, 1)
ink.forceMove(user.loc)
user.put_in_hands(ink)
to_chat(user, "You remove \the [ink] from \the [name].")
diff --git a/code/game/objects/items/weapons/barricade_kit.dm b/code/game/objects/items/weapons/barricade_kit.dm
index ff823410eba..5f844e184df 100644
--- a/code/game/objects/items/weapons/barricade_kit.dm
+++ b/code/game/objects/items/weapons/barricade_kit.dm
@@ -87,8 +87,8 @@
kit_uses--
if(kit_uses < 1)
qdel(src) //Get rid of it
- return 0 //Don't fire attack, please
+ return TRUE //Don't fire attack, please
/obj/item/weapon/barricade_kit/attack(var/atom/A, mob/user as mob)
- return //Don't attack with it
\ No newline at end of file
+ return //Don't attack with it
diff --git a/code/game/objects/items/weapons/butterfly.dm b/code/game/objects/items/weapons/butterfly.dm
index e3810b21951..ca2809c7008 100644
--- a/code/game/objects/items/weapons/butterfly.dm
+++ b/code/game/objects/items/weapons/butterfly.dm
@@ -45,18 +45,15 @@
fold()
to_chat(L, "You flip \the [src] closed.")
if(bug)
- if(bug == (/mob/living/simple_animal/hostile/viscerator/butterfly || /mob/living/simple_animal/hostile/viscerator/butterfly/magic))
- var/mob/living/simple_animal/hostile/viscerator/butterfly/X = new bug(get_turf(src))
- X.autodie = TRUE
- if(istype(L))
- handle_faction(X,L)
- else //In case someone decides to make a knife spawn something other than a viscerator.
- var/mob/living/simple_animal/X = new bug(get_turf(src))
- if(istype(L))
- handle_faction(X,L)
+ var/mob/living/simple_animal/X = new bug(get_turf(src))
+ if(istype(L))
+ handle_faction(X,L)
+ if(istype(X, /mob/living/simple_animal/hostile/viscerator/butterfly))
+ var/mob/living/simple_animal/hostile/viscerator/butterfly/B = X
+ B.autodie = TRUE
bug = null
counting = world.time
- playsound(get_turf(src),'sound/items/zippo_open.ogg', 50, 1)
+ playsound(src,'sound/items/zippo_open.ogg', 50, 1)
/obj/item/weapon/butterflyknife/preattack(var/mob/living/target, mob/user) //"Putting away" a butterfly early.
if((istype(target, /mob/living/simple_animal/hostile/viscerator/butterfly)) && (knifetype != "plain"))
@@ -68,11 +65,11 @@
else
fold()
-/obj/item/weapon/butterflyknife/proc/rearm(mob/user)
+/obj/item/weapon/butterflyknife/proc/rearm()
counting = null
bug = initial(bug)
playsound(src, 'sound/items/healthanalyzer.ogg', 10, 1)
- to_chat(user, "\The [src] chimes.")
+ visible_message("\The [src] chimes.")
/obj/item/weapon/butterflyknife/proc/unfold()
open = TRUE
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index 7f920741d33..6d9efa1ff0d 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -30,7 +30,9 @@ MATCHBOXES ARE ALSO IN FANCY.DM
source_temperature = TEMPERATURE_FLAME
w_class = W_CLASS_TINY
origin_tech = Tc_MATERIALS + "=1"
- attack_verb = list("burns", "singes")
+ var/list/unlit_attack_verb = list("prods", "pokes")
+ var/list/lit_attack_verb = list("burns", "singes")
+ attack_verb = list("prods", "pokes")
light_color = LIGHT_COLOR_FIRE
/obj/item/weapon/match/New()
@@ -60,16 +62,19 @@ MATCHBOXES ARE ALSO IN FANCY.DM
item_state = "[initial(item_state)]on"
icon_state = "[initial(icon_state)]_lit"
damtype = BURN
+ attack_verb = lit_attack_verb
if(0)
name = "[initial(name)]"
item_state = "[initial(item_state)]off"
icon_state = "[initial(icon_state)]_unlit"
damtype = BRUTE
+ attack_verb = unlit_attack_verb
if(-1)
name = "burnt [initial(name)]"
item_state = "[initial(item_state)]off"
icon_state = "[initial(icon_state)]_burnt"
damtype = BRUTE
+ attack_verb = unlit_attack_verb
/obj/item/weapon/match/proc/update_brightness()
if(lit == 1) //I wish I didn't need the == 1 part, but Dreamkamer is a dumb puppy
@@ -89,7 +94,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM
lit = -1
update_brightness()
return
- if(env.oxygen < 5)
+ if(env.molar_density("oxygen") < (5 / CELL_VOLUME))
lit = -1
update_brightness()
if(M)
@@ -156,7 +161,9 @@ MATCHBOXES ARE ALSO IN FANCY.DM
item_state = "cig"
w_class = W_CLASS_TINY
body_parts_covered = 0
- attack_verb = list("burns", "singes")
+ var/list/unlit_attack_verb = list("prods", "pokes")
+ var/list/lit_attack_verb = list("burns", "singes")
+ attack_verb = list("prods", "pokes")
heat_production = 1000
source_temperature = TEMPERATURE_FLAME
light_color = LIGHT_COLOR_FIRE
@@ -167,7 +174,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM
var/lastHolder = null
var/brightness_on = 1 //Barely enough to see where you're standing, it's a boring old cigarette
var/smoketime = 300
- var/chem_volume = 15
+ var/chem_volume = 20
var/inside_item = 0 //For whether the cigarette is contained inside another item.
var/filling = null //To alter the name if it's a special kind of cigarette
@@ -175,6 +182,10 @@ MATCHBOXES ARE ALSO IN FANCY.DM
..()
flags |= NOREACT // so it doesn't react until you light it
create_reagents(chem_volume) // making the cigarrete a chemical holder with a maximum volume of 15
+ if(Holiday == APRIL_FOOLS_DAY)
+ reagents.add_reagent(DANBACCO, 5)
+ else
+ reagents.add_reagent(TOBACCO, 5)
update_brightness()
/obj/item/clothing/mask/cigarette/Destroy()
@@ -196,11 +207,13 @@ MATCHBOXES ARE ALSO IN FANCY.DM
item_state = "[initial(item_state)]on"
icon_state = "[initial(icon_state)]on"
damtype = BURN
+ attack_verb = lit_attack_verb
if(0)
name = filling ? "[filling] [initial(name)]" : "[initial(name)]"
item_state = "[initial(item_state)]off"
icon_state = "[initial(icon_state)]off"
damtype = BRUTE
+ attack_verb = unlit_attack_verb
/obj/item/clothing/mask/cigarette/proc/update_brightness()
if(lit)
@@ -342,7 +355,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM
M.IgniteMob()
smoketime--
var/datum/gas_mixture/env = location.return_air()
- if(smoketime <= 0 | env.oxygen < 5)
+ if(smoketime <= 0 | env.molar_density("oxygen") < (5 / CELL_VOLUME))
if(!inside_item)
var/atom/new_butt = new type_butt(location) //Spawn the cigarette butt
transfer_fingerprints_to(new_butt)
@@ -418,7 +431,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM
type_butt = /obj/item/weapon/cigbutt/cigarbutt
item_state = "cigar"
smoketime = 1500
- chem_volume = 20
+ chem_volume = 25
species_fit = list(VOX_SHAPED, GREY_SHAPED)
/obj/item/clothing/mask/cigarette/cigar/cohiba
@@ -471,7 +484,8 @@ MATCHBOXES ARE ALSO IN FANCY.DM
item_state = "blunt"
slot_flags = SLOT_MASK
species_fit = list(GREY_SHAPED)
- attack_verb = list("burns", "singes", "blunts")
+
+ lit_attack_verb = list("burns", "singes", "blunts")
smoketime = 420
chem_volume = 50 //It's a fat blunt, a really fat blunt
@@ -616,7 +630,9 @@ MATCHBOXES ARE ALSO IN FANCY.DM
heat_production = 1500
source_temperature = TEMPERATURE_FLAME
slot_flags = SLOT_BELT
- attack_verb = list("burns", "singes")
+ var/list/unlit_attack_verb = list("prods", "pokes")
+ var/list/lit_attack_verb = list("burns", "singes")
+ attack_verb = list("prods", "pokes")
light_color = LIGHT_COLOR_FIRE
var/lit = 0
@@ -654,11 +670,13 @@ MATCHBOXES ARE ALSO IN FANCY.DM
item_state = "[initial(item_state)][color_suffix]on"
icon_state = "[initial(icon_state)][color_suffix]-on"
damtype = BURN
+ attack_verb = lit_attack_verb
if(0)
name = "[initial(name)]"
item_state = "[initial(item_state)][color_suffix]off"
icon_state = "[initial(icon_state)][color_suffix]"
damtype = BRUTE
+ attack_verb = unlit_attack_verb
/obj/item/weapon/lighter/proc/update_brightness()
if(lit)
@@ -676,19 +694,19 @@ MATCHBOXES ARE ALSO IN FANCY.DM
fuel += O.reagents.remove_any(initial(fuel) - fuel)
user.visible_message("[user] refuels \the [src].", \
"You refuel \the [src].")
- playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
return
/obj/item/weapon/lighter/attack_self(mob/living/user)
var/turf/T = get_turf(src)
var/datum/gas_mixture/env = T.return_air()
user.delayNextAttack(5) //Hold on there cowboy
- if(!fuel | env.oxygen < 5)
+ if(!fuel | env.molar_density("oxygen") < (5 / CELL_VOLUME))
user.visible_message("[user] attempts to light \the [src] to no avail.", \
"You try to light \the [src], but no flame appears.")
return
if(!lit) //Lighting the lighter
- playsound(get_turf(src), pick(lightersound), 50, 1)
+ playsound(src, pick(lightersound), 50, 1)
if(fuel >= initial(fuel) - 5 || prob(100 * (fuel/initial(fuel)))) //Strike, but fail to light it
user.visible_message("[user] manages to light \the [src].", \
"You manage to light \the [src].")
@@ -740,7 +758,7 @@ MATCHBOXES ARE ALSO IN FANCY.DM
visible_message("Without warning, \the [src] suddenly shuts off.")
fueltime = null
var/datum/gas_mixture/env = location.return_air()
- if(env.oxygen < 5)
+ if(env.molar_density("oxygen") < (5 / CELL_VOLUME))
lit = 0
update_brightness()
visible_message("Without warning, the flame on \the [src] suddenly goes out in a weak fashion.")
@@ -763,19 +781,19 @@ MATCHBOXES ARE ALSO IN FANCY.DM
var/turf/T = get_turf(src)
var/datum/gas_mixture/env = T.return_air()
user.delayNextAttack(5) //Hold on there cowboy
- if(!fuel | env.oxygen < 5)
+ if(!fuel | env.molar_density("oxygen") < (5 / CELL_VOLUME))
user.visible_message("[user] attempts to light \the [src] to no avail.", \
"You try to light \the [src], but no flame appears.")
return
lit = !lit
if(lit) //Was lit
- playsound(get_turf(src), pick(open_sound), 50, 1)
+ playsound(src, pick(open_sound), 50, 1)
user.visible_message("Without even breaking stride, [user] flips open and lights \the [src] in one smooth movement.", \
"Without even breaking stride, you flip open and light \the [src] in one smooth movement.")
--fuel
else //Was shut off
fueltime = null
- playsound(get_turf(src), pick(close_sound), 50, 1)
+ playsound(src, pick(close_sound), 50, 1)
user.visible_message("You hear a quiet click as [user] shuts off \the [src] without even looking at what they're doing. Wow.", \
"You hear a quiet click as you shut off \the [src] without even looking at what you are doing.")
- update_brightness()
\ No newline at end of file
+ update_brightness()
diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm
index 9f944509457..fb9e21dd842 100644
--- a/code/game/objects/items/weapons/clown_items.dm
+++ b/code/game/objects/items/weapons/clown_items.dm
@@ -101,7 +101,7 @@
/obj/item/weapon/bikehorn/suicide_act(mob/user)
to_chat(viewers(user), "[user] places the [src.name] into \his mouth and honks the horn. ")
- playsound(get_turf(user), hitsound, 100, vary_pitch)
+ playsound(user, hitsound, 100, vary_pitch)
user.gib()
/obj/item/weapon/bikehorn/attack_self(mob/user as mob)
@@ -133,7 +133,7 @@
/obj/item/weapon/bikehorn/proc/honk()
if(world.time - last_honk_time >= honk_delay)
last_honk_time = world.time
- playsound(get_turf(src), hitsound, 50, vary_pitch)
+ playsound(src, hitsound, 50, vary_pitch)
return 1
return 0
diff --git a/code/game/objects/items/weapons/cosmetics.dm b/code/game/objects/items/weapons/cosmetics.dm
index 96ed2676b19..8a335957099 100644
--- a/code/game/objects/items/weapons/cosmetics.dm
+++ b/code/game/objects/items/weapons/cosmetics.dm
@@ -269,7 +269,7 @@
H.g_hair = color_g
H.b_hair = color_b
H.update_hair()
- playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6)
/obj/item/weapon/invisible_spray
name = "can of invisible spray"
@@ -341,7 +341,7 @@
to_chat(user, "You spray yourself with \the [src].")
else
to_chat(user, "You spray \the [target] with \the [src].")
- playsound(get_turf(src), 'sound/effects/spray2.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/spray2.ogg', 50, 1, -6)
sprays_left--
if(istype(target, /obj/machinery/power/supermatter))
return 0
@@ -492,3 +492,70 @@
return
if (prob(25))
shatter()
+
+/obj/item/weapon/nanitecontacts
+ name = "nanite contacts"
+ desc = "Deploys nanobots to your eyes to change their color."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "nanite_contact"
+ flags = FPRINT
+ w_class = W_CLASS_TINY
+ var/color_r = 255
+ var/color_g = 255
+ var/color_b = 255
+
+/obj/item/weapon/nanitecontacts/New()
+ ..()
+ color_r = rand(0,255)
+ color_g = rand(0,255)
+ color_b = rand(0,255)
+ update_icon()
+
+/obj/item/weapon/nanitecontacts/update_icon()
+ overlays.len = 0
+ var/image/I = image(icon = 'icons/obj/items.dmi', icon_state = "contacts_overlay")
+ I.color = rgb(color_r, color_g, color_b)
+ overlays += I
+
+/obj/item/weapon/nanitecontacts/attack_self(mob/user)
+ var/new_color = input(user, "Choose the contact's color:", "Color Select") as color|null
+ if(new_color)
+ color_r = hex2num(copytext(new_color, 2, 4))
+ color_g = hex2num(copytext(new_color, 4, 6))
+ color_b = hex2num(copytext(new_color, 6, 8))
+ update_icon()
+
+/obj/item/weapon/nanitecontacts/attack(mob/M, mob/user)
+ if(!istype(M))
+ return
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ var/area = user.zone_sel.selecting
+ if(area == "eyes")
+ var/obj/item/clothing/cover = H.get_body_part_coverage(EYES)
+ if(cover)
+ to_chat(user, "You can't color [H == user ? "your" : "\the [H]'s"] eyes through that [cover.name]!")
+ return
+ if(H == user)
+ user.visible_message("[user] colors their eyes with \the [src].", \
+ "You color your eyes with \the [src].")
+ color_eyes(H)
+ else
+ user.visible_message("[user] begins to color \the [H]'s eyes with \the [src].", \
+ "You begin to color \the [H]'s eyes with \the [src].")
+ if(do_after(user,H, 20)) //user needs to keep their active hand, H does not.
+ user.visible_message("[user] colors [H]'s eyes with \the [src].", \
+ "You color [H]'s eyes with \the [src].")
+ color_eyes(H)
+ else
+ to_chat(user, "\The [M]'s eyes don't fit in the contacts!")
+
+/obj/item/weapon/nanitecontacts/proc/color_eyes(mob/living/carbon/human/H)
+ if(!H)
+ return
+ else
+ H.r_eyes = color_r
+ H.g_eyes = color_g
+ H.b_eyes = color_b
+ H.update_body()
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index bbf6854a6f1..8c616e50d6f 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -7,6 +7,7 @@
desc = "Used to restore fibrillating patients."
icon = 'icons/obj/weapons.dmi'
icon_state = "defib_full"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/surgery_tools.dmi', "right_hand" = 'icons/mob/in-hand/right/surgery_tools.dmi')
item_state = "defib"
w_class = W_CLASS_MEDIUM
force = 5
@@ -22,7 +23,7 @@
/obj/item/weapon/melee/defibrillator/suicide_act(mob/user)
to_chat(viewers(user), "[user] is putting the live paddles on \his chest! It looks like \he's trying to commit suicide.")
- playsound(get_turf(src),'sound/items/defib.ogg',50,1)
+ playsound(src,'sound/items/defib.ogg',50,1)
return (FIRELOSS)
/obj/item/weapon/melee/defibrillator/update_icon()
@@ -47,7 +48,7 @@
if(clumsy_check(user) && prob(50) && charges)
to_chat(user, "You touch the paddles together, shorting the device.")
spark(src, 5)
- playsound(get_turf(src),'sound/items/defib.ogg',50,1)
+ playsound(src,'sound/items/defib.ogg',50,1)
user.Knockdown(5)
var/mob/living/carbon/human/H = user
if(ishuman(user))
@@ -57,7 +58,7 @@
else
ready = !ready
to_chat(user, "You turn [src] [ready? "on and take the paddles out" : "off and put the paddles back in"].")
- playsound(get_turf(src),"sparks",75,1,-1)
+ playsound(src,"sparks",75,1,-1)
update_icon()
else
to_chat(user, "[src] is out of charges.")
@@ -120,7 +121,7 @@
else
target.LAssailant = user
spark(src, 5, FALSE)
- playsound(get_turf(src),'sound/items/defib.ogg',50,1)
+ playsound(src,'sound/items/defib.ogg',50,1)
charges--
update_icon()
return
@@ -130,33 +131,33 @@
"You start setting up the paddles on [target]'s chest")
if(do_after(user,target,30))
spark(src, 5, FALSE)
- playsound(get_turf(src),'sound/items/defib.ogg',50,1)
+ playsound(src,'sound/items/defib.ogg',50,1)
charges--
update_icon()
to_chat(user, "You shock [target] with the paddles.")
var/datum/organ/internal/heart/heart = target.get_heart()
if(!heart)
- to_chat(user, "[src] buzzes: Defibrillation failed. Subject requires a heart.")
+ target.visible_message("[src] buzzes: Defibrillation failed. Subject requires a heart.")
target.apply_damage(rand(1,5),BURN,LIMB_CHEST)
return
var/datum/organ/external/head/head = target.get_organ(LIMB_HEAD)
if(!head || head.status & ORGAN_DESTROYED)
target.visible_message("[src] buzzes: Defibrillation failed. Severe cranial damage detected.")
return
- if(M_NOCLONE in target.mutations)
+ if((M_HUSK in target.mutations) && (M_NOCLONE in target.mutations))
target.visible_message("[src] buzzes: Defibrillation failed. Irremediable genetic damage detected.")
return
if(!target.has_brain())
- target.visible_message("[src] buzzes: Defibrillation failed. No nervous system detected.")
+ target.visible_message("[src] buzzes: Defibrillation failed. No central nervous system detected.")
return
if(target.suiciding)
target.visible_message("[src] buzzes: Defibrillation failed. Severe nerve trauma detected.") // They suicided so they fried their brain. Space Magic.
return
- if(target.wear_suit && istype(target.wear_suit,/obj/item/clothing/suit/armor) && prob(95)) //75 ? Let's stay realistic here
+ if(istype(target.wear_suit,/obj/item/clothing/suit/armor) && (target.wear_suit.body_parts_covered & UPPER_TORSO) && prob(95)) //75 ? Let's stay realistic here
target.visible_message("[src] buzzes: Defibrillation failed. Please apply on bare skin.")
target.apply_damage(rand(1,5),BURN,LIMB_CHEST)
return
- if(target.w_uniform && istype(target.w_uniform,/obj/item/clothing/under) && prob(50))
+ if(istype(target.w_uniform,/obj/item/clothing/under) && (target.w_uniform.body_parts_covered & UPPER_TORSO) && prob(50))
target.visible_message("[src] buzzes: Defibrillation failed. Please apply on bare skin.")
target.apply_damage(rand(1,5),BURN,LIMB_CHEST)
return
@@ -168,10 +169,10 @@
ghostmob << 'sound/effects/adminhelp.ogg'
to_chat(ghostmob, "Someone is trying to revive your body. Return to it if you want to be resurrected! \
(Verbs -> Ghost -> Re-enter corpse, or click here!)")
- to_chat(user, "[src] buzzes: Defibrillation failed. Vital signs are too weak, please try again in five seconds.")
+ target.visible_message(user, "[src] buzzes: Defibrillation failed. Vital signs are too weak, please try again in five seconds.")
return
//we couldn't find a suitable ghost.
- target.visible_message("[src] buzzes: Defibrillation failed. No brain waves detected.")
+ target.visible_message("[src] buzzes: Defibrillation failed. No brainwaves detected.")
return
if(prob(25))
heart.damage += 5 //Allow the defibrilator to possibly worsen heart damage. Still rare enough to just be the "clone damage" of the defib
diff --git a/code/game/objects/items/weapons/dice.dm b/code/game/objects/items/weapons/dice.dm
index 2ad88434f9b..0d3d3b5644e 100644
--- a/code/game/objects/items/weapons/dice.dm
+++ b/code/game/objects/items/weapons/dice.dm
@@ -130,10 +130,11 @@
/obj/item/weapon/dice/d20/cursed
- desc = "Something about this dice seems wrong"
name = "\improper Mysterious d20"
+ desc = "Something about this dice seems wrong"
var/deactivated = 0 //Eventually the dice runs out of power
var/infinite = 0 //dice with 1 will not run out
+ mech_flags = MECH_SCAN_ILLEGAL
/obj/item/weapon/dice/d20/cursed/pickup(mob/user as mob)
..()
diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm
index 1b276183eeb..5e7689dfaf1 100644
--- a/code/game/objects/items/weapons/dna_injector.dm
+++ b/code/game/objects/items/weapons/dna_injector.dm
@@ -309,7 +309,7 @@
/obj/item/weapon/dnainjector/nofail/antiremoteview
name = "DNA-Injector (Anti-Remote View)"
- desc = "Cures green skin."
+ desc = "Quit staring."
datatype = DNA2_BUF_SE
value = 0x001
//block = 2
@@ -842,6 +842,23 @@
datatype = DNA2_BUF_SE
value = 0x001
//block = 11
+
+/obj/item/weapon/dnainjector/nofail/asthmamut
+ name = "DNA-Injector (Asthma)"
+ desc = "Makes you asthmatic."
+ datatype = DNA2_BUF_SE
+ value = 0xFFF
+ //block = 11
+
+/obj/item/weapon/dnainjector/nofail/asthmamut/New()
+ block = ASTHMABLOCK
+ ..()
+
+/obj/item/weapon/dnainjector/nofail/antiasthma
+ name = "DNA-Injector (Anti-Asthma)"
+ desc = "Allows you to breathe normally again."
+ datatype = DNA2_BUF_SE
+ value = 0x001
/obj/item/weapon/dnainjector/nofail/antiblind/New()
block = VEGANBLOCK
diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm
index 55017332fd3..6170c3cfeb7 100644
--- a/code/game/objects/items/weapons/explosives.dm
+++ b/code/game/objects/items/weapons/explosives.dm
@@ -98,7 +98,7 @@
else
user.visible_message("[user] found \himself unable to drop \the [src] after setting the timer on them!")
- playsound(get_turf(target), 'sound/weapons/c4armed.ogg', 60, 1)
+ playsound(target, 'sound/weapons/c4armed.ogg', 60, 1)
if(!iscarbon(user))
M.LAssailant = null
else
diff --git a/code/game/objects/items/weapons/extinguisher.dm b/code/game/objects/items/weapons/extinguisher.dm
index d023644be50..08fcd44fbf2 100644
--- a/code/game/objects/items/weapons/extinguisher.dm
+++ b/code/game/objects/items/weapons/extinguisher.dm
@@ -90,13 +90,13 @@
user.visible_message("[user] begins to unwrench the fill cap on \the [src].","You begin to unwrench the fill cap on \the [src].")
if(do_after(user, src, 25))
user.visible_message("[user] removes the fill cap on \the [src].","You remove the fill cap on \the [src].")
- playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src,'sound/items/Ratchet.ogg', 100, 1)
flags |= OPENCONTAINER
else
user.visible_message("[user] begins to seal the fill cap on \the [src].","You begin to seal the fill cap on \the [src].")
if(do_after(user, src, 25))
user.visible_message("[user] fastens the fill cap on \the [src].","You fasten the fill cap on \the [src].")
- playsound(get_turf(src),'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src,'sound/items/Ratchet.ogg', 100, 1)
flags &= ~OPENCONTAINER
return
@@ -121,7 +121,7 @@
if((istype(target, /obj/structure/reagent_dispensers)))
target.reagents.trans_to(src, 50, log_transfer = TRUE, whodunnit = user)
to_chat(user, "\The [src] is now refilled")
- playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
return
if(is_open_container() && reagents.total_volume)
@@ -151,7 +151,7 @@
src.last_use = world.time
- playsound(get_turf(src), 'sound/effects/extinguish.ogg', 75, 1, -3)
+ playsound(src, 'sound/effects/extinguish.ogg', 75, 1, -3)
var/direction = get_dir(src,target)
@@ -224,7 +224,7 @@
var/obj/o = target
o.reagents.trans_to(src, 50)
to_chat(user, "\The [src] is now refilled")
- playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
return
if (!safety && !is_open_container())
@@ -241,7 +241,7 @@
user.delayNextAttack(5, 1)
src.last_use = world.time
- playsound(get_turf(src), 'sound/effects/extinguish.ogg', 75, 1, -3)
+ playsound(src, 'sound/effects/extinguish.ogg', 75, 1, -3)
var/direction = get_dir(src,target)
diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm
index 99755e9f20f..c71cb761f6a 100644
--- a/code/game/objects/items/weapons/gift_wrappaper.dm
+++ b/code/game/objects/items/weapons/gift_wrappaper.dm
@@ -325,6 +325,6 @@
/obj/item/weapon/winter_gift/dorkcube/attack_self(mob/user)
user.say("Loot get!")
- playsound(get_turf(src), 'sound/misc/achievement.ogg', 30, 1)
+ playsound(src, 'sound/misc/achievement.ogg', 30, 1)
user.gib()
qdel(src)
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index a4dbe1cdfc4..7e5b474f6f5 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -18,6 +18,7 @@
var/obj/item/weapon/reagent_containers/glass/beaker/noreactgrenade/reservoir = null
var/extract_uses = 0
var/mob/primed_by = "N/A" //"name (ckey)". For logging purposes
+ mech_flags = null
/obj/item/weapon/grenade/chem_grenade/attack_self(mob/user as mob)
if(!stage || stage==1)
@@ -79,7 +80,7 @@
return
path = 1
to_chat(user, "You add [W] to the metal casing.")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3)
+ playsound(src, 'sound/items/Screwdriver.ogg', 25, -3)
user.remove_from_mob(det)
det.forceMove(src)
detonator = det
@@ -93,7 +94,7 @@
coil.use(2)
var/obj/item/weapon/electrolyzer/E = new /obj/item/weapon/electrolyzer
to_chat(user, "You tightly coil the wire around the metal casing.")
- playsound(get_turf(src), 'sound/weapons/cablecuff.ogg', 30, 1, -2)
+ playsound(src, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
user.before_take_item(src)
user.put_in_hands(E)
qdel(src)
@@ -119,7 +120,7 @@
// to_chat(user, "You need to add at least one beaker before locking the assembly.")
to_chat(user, "You lock the empty assembly.")
name = "fake grenade"
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3)
+ playsound(src, 'sound/items/Screwdriver.ogg', 25, -3)
icon_state = initial(icon_state) +"_locked"
stage = 2
else if(stage == 2)
@@ -129,7 +130,7 @@
return
else
to_chat(user, "You unlock the assembly.")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3)
+ playsound(src, 'sound/items/Screwdriver.ogg', 25, -3)
name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]"
icon_state = initial(icon_state) + (detonator?"_ass":"")
stage = 1
@@ -229,10 +230,10 @@
active = 0
if(!has_reagents)
icon_state = initial(icon_state) +"_locked"
- playsound(get_turf(src), 'sound/items/Screwdriver2.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver2.ogg', 50, 1)
return
- playsound(get_turf(src), 'sound/effects/bamfgas.ogg', 50, 1)
+ playsound(src, 'sound/effects/bamfgas.ogg', 50, 1)
visible_message("[bicon(src)] \The [src] bursts open.")
@@ -326,7 +327,7 @@ obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj
return
path = 1
to_chat(user, "You insert [W] into the grenade.")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3)
+ playsound(src, 'sound/items/Screwdriver.ogg', 25, -3)
user.remove_from_mob(det)
det.forceMove(src)
detonator = det
@@ -342,7 +343,7 @@ obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj
else
to_chat(user, "You lock the empty assembly.")
name = "fake grenade"
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3)
+ playsound(src, 'sound/items/Screwdriver.ogg', 25, -3)
icon_state = initial(icon_state) +"_locked"
stage = 2
else if(stage == 2)
@@ -352,7 +353,7 @@ obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj
return
else
to_chat(user, "You unlock the assembly.")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 25, -3)
+ playsound(src, 'sound/items/Screwdriver.ogg', 25, -3)
name = "unsecured EX grenade with [beakers.len] containers[detonator?" and detonator":""]"
icon_state = initial(icon_state) + (detonator?"_ass":"")
stage = 1
@@ -407,6 +408,27 @@ obj/item/weapon/grenade/chem_grenade/exgrenade/attackby(obj/item/weapon/W as obj
beakers += B2
icon_state = initial(icon_state) +"_locked"
+/obj/item/weapon/grenade/chem_grenade/ironfoam
+ name = "Iron-Foam Grenade"
+ desc = "Used for emergency sealing of air breaches."
+ path = 1
+ stage = 2
+
+/obj/item/weapon/grenade/chem_grenade/ironfoam/New()
+ ..()
+ var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src)
+ var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src)
+
+ B1.reagents.add_reagent(IRON, 30)
+ B2.reagents.add_reagent(FOAMING_AGENT, 10)
+ B2.reagents.add_reagent(PACID, 10)
+
+ detonator = new/obj/item/device/assembly_holder/timer_igniter(src)
+
+ beakers += B1
+ beakers += B2
+ icon_state = initial(icon_state) +"_locked"
+
/obj/item/weapon/grenade/chem_grenade/incendiary
name = "Incendiary Grenade"
desc = "Used for clearing rooms of living things."
diff --git a/code/game/objects/items/weapons/grenades/chronogrenade.dm b/code/game/objects/items/weapons/grenades/chronogrenade.dm
index c3ef10bbdfb..f64850d8850 100644
--- a/code/game/objects/items/weapons/grenades/chronogrenade.dm
+++ b/code/game/objects/items/weapons/grenades/chronogrenade.dm
@@ -7,6 +7,7 @@
flags = FPRINT | TIMELESS
var/duration = 10 SECONDS
var/radius = 5 //in tiles
+ mech_flags = MECH_SCAN_FAIL
/obj/item/weapon/grenade/chronogrenade/prime()
timestop(src, duration, radius)
diff --git a/code/game/objects/items/weapons/grenades/clowngrenade.dm b/code/game/objects/items/weapons/grenades/clowngrenade.dm
index 6123935b1c3..b753b65e47e 100644
--- a/code/game/objects/items/weapons/grenades/clowngrenade.dm
+++ b/code/game/objects/items/weapons/grenades/clowngrenade.dm
@@ -15,7 +15,7 @@
/obj/item/weapon/grenade/clown_grenade/prime()
..()
- playsound(get_turf(src), 'sound/items/bikehorn.ogg', 25, -3)
+ playsound(src, 'sound/items/bikehorn.ogg', 25, -3)
/*
for(var/turf/simulated/floor/T in view(affected_area, src.loc))
if(prob(75))
@@ -92,7 +92,7 @@
M.take_organ_damage(2) // Was 5 -- TLE
M.simple_message("You slipped on \the [name]!",\
"Please, just end the pain!")
- playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3)
+ playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
M.Knockdown(10)
M.take_overall_damage(0, burned)
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 821187d556b..3078b92781b 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -40,7 +40,7 @@
var/eye_safety = 0
var/ear_safety = 0
- if(!ignore_protection)
+ if(!ignore_protection && loc != M.loc)
eye_safety = M.eyecheck()
ear_safety = M.earprot() //some arbitrary measurement of ear protection, I guess? doesn't even matter if it goes above 1
@@ -56,40 +56,57 @@
//Flashing everyone
if(eye_safety < 1)
M.flash_eyes(visual = 1, affect_silicon = 1)
- M.Stun(10)
- M.Knockdown(10)
+ if (get_dist(M, T) <= 3)
+ M.Stun(8)
+ M.Knockdown(8)
+ else
+ if (issilicon(M))
+ M.Stun(4)
+ M.Knockdown(4)
+ else if (get_dist(M, T) <= 5)
+ M.Knockdown(2)
+ else
+ M.Knockdown(1)
//Now applying sound
if(!ear_safety)
to_chat(M, "BANG")
- playsound(get_turf(src), 'sound/effects/bang.ogg', 60, 1)
+ playsound(src, 'sound/effects/bang.ogg', 60, 1)
else
to_chat(M, "BANG")
- playsound(get_turf(src), 'sound/effects/bang.ogg', 25, 1)
+ playsound(src, 'sound/effects/bang.ogg', 25, 1)
if((get_dist(M, T) <= 2 || src.loc == M.loc || src.loc == M))
if(ear_safety > 0)
M.Stun(2)
M.Knockdown(2)
else
- M.Stun(10)
- M.Knockdown(10)
+ M.Stun(8)
+ M.Knockdown(8)
if ((prob(14) || (M == src.loc && prob(70))))
M.ear_damage += rand(1, 10)
else
M.ear_damage += rand(0, 5)
M.ear_deaf = max(M.ear_deaf,15)
+ else if(get_dist(M, T) <= 3)
+ if(!ear_safety)
+ M.Stun(6)
+ M.Knockdown(6)
+ M.ear_damage += rand(0, 3)
+ M.ear_deaf = max(M.ear_deaf,10)
+
else if(get_dist(M, T) <= 5)
if(!ear_safety)
- M.Stun(8)
- M.Knockdown(8)
+ M.Stun(4)
+ M.Knockdown(4)
M.ear_damage += rand(0, 3)
M.ear_deaf = max(M.ear_deaf,10)
else if(!ear_safety)
- M.Stun(4)
- M.Knockdown(4)
+ if (issilicon(M))
+ M.Stun(4)
+ M.Knockdown(1)
M.ear_damage += rand(0, 1)
M.ear_deaf = max(M.ear_deaf,5)
@@ -140,12 +157,12 @@
for(,numspawned > 0, numspawned--)
spawn(0)
new /obj/item/weapon/grenade/flashbang/cluster(src.loc)//Launches flashbangs
- playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3)
+ playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
for(,again > 0, again--)
spawn(0)
new /obj/item/weapon/grenade/flashbang/clusterbang/segment(src.loc)//Creates a 'segment' that launches a few more flashbangs
- playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3)
+ playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
spawn(0)
qdel(src)
return
@@ -177,7 +194,7 @@
for(,numspawned > 0, numspawned--)
spawn(0)
new /obj/item/weapon/grenade/flashbang/cluster(src.loc)
- playsound(get_turf(src), 'sound/weapons/armbomb.ogg', 75, 1, -3)
+ playsound(src, 'sound/weapons/armbomb.ogg', 75, 1, -3)
spawn(0)
qdel(src)
return
diff --git a/code/game/objects/items/weapons/grenades/ghettobomb.dm b/code/game/objects/items/weapons/grenades/ghettobomb.dm
index 10facc85cb4..a58e95b3028 100644
--- a/code/game/objects/items/weapons/grenades/ghettobomb.dm
+++ b/code/game/objects/items/weapons/grenades/ghettobomb.dm
@@ -45,7 +45,7 @@
F.reagents.remove_reagent(FUEL, 50, 1)//Deleting 50 fuel from the welding fuel tank,
assembled = 1
to_chat(user, "You've filled the makeshift explosive with welding fuel.")
- playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
desc = "An improvised explosive assembly. Filled to the brim with 'Explosive flavor'"
overlays += image('icons/obj/grenade.dmi', icon_state = "improvised_grenade_filled")
return
@@ -114,7 +114,7 @@
current_shrapnel += I.shrapnel_size
if(user && user.drop_item(I, src))
to_chat(user, "You add \the [I] to the improvised explosive.")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 25, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 25, 1)
else
I.forceMove(src)
diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm
index bbab990c18d..ed5aa928401 100644
--- a/code/game/objects/items/weapons/grenades/grenade.dm
+++ b/code/game/objects/items/weapons/grenades/grenade.dm
@@ -12,6 +12,7 @@
slot_flags = SLOT_BELT
var/active = 0
var/det_time = 50
+ mech_flags = MECH_SCAN_ILLEGAL
/obj/item/weapon/grenade/proc/clown_check(var/mob/living/user)
if(clumsy_check(user) && prob(50))
diff --git a/code/game/objects/items/weapons/grenades/inflatable.dm b/code/game/objects/items/weapons/grenades/inflatable.dm
index 8261d039c2a..91528b318f2 100644
--- a/code/game/objects/items/weapons/grenades/inflatable.dm
+++ b/code/game/objects/items/weapons/grenades/inflatable.dm
@@ -2,9 +2,10 @@
name = "inflatable barrier grenade"
desc = "An inflatable barrier conveniently packaged into a casing for remote delivery. Non-reusable."
var/deploy_path = /obj/structure/inflatable/wall
+ mech_flags = null
/obj/item/weapon/grenade/inflatable/prime()
- playsound(get_turf(src), 'sound/items/zip.ogg', 75, 1)
+ playsound(src, 'sound/items/zip.ogg', 75, 1)
var/obj/structure/inflatable/R = new deploy_path(get_turf(src))
R.spawn_undeployed = FALSE
qdel(src)
diff --git a/code/game/objects/items/weapons/grenades/smokebomb.dm b/code/game/objects/items/weapons/grenades/smokebomb.dm
index 5db81e4a87a..9b6b07ae5dc 100644
--- a/code/game/objects/items/weapons/grenades/smokebomb.dm
+++ b/code/game/objects/items/weapons/grenades/smokebomb.dm
@@ -8,28 +8,28 @@
flags = FPRINT
slot_flags = SLOT_BELT
var/datum/effect/effect/system/smoke_spread/bad/smoke
+ mech_flags = null
- New()
- ..()
- src.smoke = new /datum/effect/effect/system/smoke_spread/bad
- src.smoke.attach(src)
+/obj/item/weapon/grenade/smokebomb/New()
+ ..()
+ smoke = new /datum/effect/effect/system/smoke_spread/bad
+ smoke.attach(src)
- prime()
- playsound(get_turf(src), 'sound/effects/smoke.ogg', 50, 1, -3)
- src.smoke.set_up(10, 0, usr.loc)
- spawn(0)
- src.smoke.start()
- sleep(10)
- src.smoke.start()
- sleep(10)
- src.smoke.start()
- sleep(10)
- src.smoke.start()
+/obj/item/weapon/grenade/smokebomb/prime()
+ playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3)
+ smoke.set_up(10, 0, usr.loc)
+ spawn(0)
+ smoke.start()
+ sleep(10)
+ smoke.start()
+ sleep(10)
+ smoke.start()
+ sleep(10)
+ smoke.start()
- for(var/obj/effect/blob/B in view(8,src))
- var/damage = round(30/(get_dist(B,src)+1))
- B.health -= damage
- B.update_icon()
- sleep(80)
- qdel(src)
- return
+ for(var/obj/effect/blob/B in view(8,src))
+ var/damage = round(30/(get_dist(B,src)+1))
+ B.health -= damage
+ B.update_icon()
+ sleep(80)
+ qdel(src)
diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
index df401013aa9..1e1358f8f12 100644
--- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm
+++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm
@@ -85,5 +85,5 @@
/obj/item/weapon/grenade/spawnergrenade/beenade/postPrime(var/list/spawned_atoms)
if(!spawned_atoms || !spawned_atoms.len)
return
- playsound(get_turf(src), 'sound/effects/bees.ogg', 100, 1)
+ playsound(src, 'sound/effects/bees.ogg', 100, 1)
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index 96af15767ad..e583e19ba69 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -53,6 +53,8 @@
qdel(reagents)
..()
+
+
var/global/tracking_implants = list() //fuck me
/obj/item/weapon/implant/tracking
@@ -101,7 +103,8 @@ Implant Specifics: "}
spawn(delay)
malfunction--
-//BS12 Explosive
+
+
/obj/item/weapon/implant/explosive
name = "explosive implant"
desc = "A military grade micro bio-explosive. Highly dangerous."
@@ -202,6 +205,8 @@ Implant Specifics: "}
/obj/item/weapon/implant/explosive/nuclear/emp_act(severity)
return
+
+
/obj/item/weapon/implant/chem
name = "chem"
desc = "Injects things."
@@ -294,6 +299,8 @@ the implant may become unstable and either pre-maturely inject the subject or si
to_chat(H, "You feel a surge of loyalty towards Nanotrasen.")
return 1
+
+
/obj/item/weapon/implant/traitor
name = "Greytide Implant"
desc = "Greytide Station wide"
@@ -364,7 +371,6 @@ the implant may become unstable and either pre-maturely inject the subject or si
Integrity: Implant can only be used three times before the nanobots are depleted."}
return dat
-
/obj/item/weapon/implant/adrenalin/trigger(emote, mob/source as mob)
if (src.uses < 1)
return 0
@@ -377,13 +383,14 @@ the implant may become unstable and either pre-maturely inject the subject or si
return
-
/obj/item/weapon/implant/adrenalin/implanted(mob/source)
source.mind.store_memory("A implant can be activated by using the pale emote, say *pale to attempt to activate.", 0, 0)
to_chat(source, "The implanted freedom implant can be activated by using the pale emote, say *pale to attempt to activate.")
return 1
+
+
/obj/item/weapon/implant/death_alarm
name = "death alarm implant"
desc = "An alarm which monitors host vital signs and transmits a radio message upon death."
@@ -466,6 +473,8 @@ the implant may become unstable and either pre-maturely inject the subject or si
processing_objects.Add(src)
return 1
+
+
/obj/item/weapon/implant/compressed
name = "compressed matter implant"
desc = "Based on compressed matter technology, can store a single item."
@@ -512,6 +521,8 @@ the implant may become unstable and either pre-maturely inject the subject or si
/obj/item/weapon/implant/compressed/islegal()
return 0
+
+
/obj/item/weapon/implant/cortical
name = "cortical stack"
desc = "A fist-sized mass of biocircuits and chips."
diff --git a/code/game/objects/items/weapons/implants/implantcase.dm b/code/game/objects/items/weapons/implants/implantcase.dm
index a75c6cc4793..68d0069027c 100644
--- a/code/game/objects/items/weapons/implants/implantcase.dm
+++ b/code/game/objects/items/weapons/implants/implantcase.dm
@@ -1,5 +1,3 @@
-
-
/obj/item/weapon/implantcase
name = "Glass Case"
desc = "A case containing an implant."
@@ -12,7 +10,6 @@
proc
update()
-
update()
if (src.imp)
src.icon_state = text("implantcase-[]", src.imp._color)
@@ -20,7 +17,6 @@
src.icon_state = "implantcase-0"
return
-
attackby(obj/item/weapon/I as obj, mob/user as mob)
..()
if (istype(I, /obj/item/weapon/pen))
@@ -57,40 +53,36 @@
return
-
/obj/item/weapon/implantcase/tracking
name = "Glass Case- 'Tracking'"
desc = "A case containing a tracking implant."
icon = 'icons/obj/items.dmi'
icon_state = "implantcase-b"
-
New()
src.imp = new /obj/item/weapon/implant/tracking( src )
..()
return
-
/obj/item/weapon/implantcase/explosive
name = "Glass Case- 'Explosive'"
desc = "A case containing an explosive implant."
icon = 'icons/obj/items.dmi'
icon_state = "implantcase-r"
-
New()
src.imp = new /obj/item/weapon/implant/explosive( src )
..()
return
-
/obj/item/weapon/implantcase/chem
name = "Glass Case- 'Chem'"
desc = "A case containing a chemical implant."
icon = 'icons/obj/items.dmi'
icon_state = "implantcase-b"
+
/obj/item/weapon/implantcase/chem/New()
src.imp = new /obj/item/weapon/implant/chem( src )
@@ -121,3 +113,14 @@
src.imp = new /obj/item/weapon/implant/death_alarm( src )
..()
return
+
+
+/obj/item/weapon/implantcase/peace
+ name = "glass case- 'Pax'"
+ desc = "A case containing a peace-inducing implant."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "implantcase-b"
+
+/obj/item/weapon/implantcase/peace/New()
+ src.imp = new /obj/item/weapon/implant/peace(src)
+ ..()
diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm
index 13d634d217b..db7fa20181c 100644
--- a/code/game/objects/items/weapons/implants/implanter.dm
+++ b/code/game/objects/items/weapons/implants/implanter.dm
@@ -7,107 +7,83 @@
throw_range = 5
w_class = W_CLASS_SMALL
var/obj/item/weapon/implant/imp = null
+ var/imp_type = null
/obj/item/weapon/implanter/proc/update()
-
-
-
-/obj/item/weapon/implanter/update()
- if (src.imp)
- src.icon_state = "implanter1"
- else
- src.icon_state = "implanter0"
- return
-
+ icon_state = "implanter[imp? 1:0]"
/obj/item/weapon/implanter/attack(mob/M as mob, mob/user as mob)
- if (!istype(M, /mob/living/carbon))
+ if(!istype(M, /mob/living/carbon))
return
- if (user && src.imp)
+ if(user && imp)
for (var/mob/O in viewers(M, null))
O.show_message("[user] is attempting to implant [M].", 1)
var/turf/T1 = get_turf(M)
- if (T1 && ((M == user) || do_after(user,M, 50)))
- if(user && M && (get_turf(M) == T1) && src && src.imp)
+ if(T1 && ((M == user) || do_after(user,M, 50)))
+ if(user && M && (get_turf(M) == T1) && src && imp)
for (var/mob/O in viewers(M, null))
O.show_message("[M] has been implanted by [user].", 1)
- M.attack_log += text("\[[time_stamp()]\] Implanted with [src.name] ([src.imp.name]) by [user.name] ([user.ckey])")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] ([src.imp.name]) to implant [M.name] ([M.ckey])")
- msg_admin_attack("[user.name] ([user.ckey]) implanted [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)")
+ M.attack_log += text("\[[time_stamp()]\] Implanted with [name] ([imp.name]) by [user.name] ([user.ckey])")
+ user.attack_log += text("\[[time_stamp()]\] Used the [name] ([imp.name]) to implant [M.name] ([M.ckey])")
+ msg_admin_attack("[user.name] ([user.ckey]) implanted [M.name] ([M.ckey]) with [name] (INTENT: [uppertext(user.a_intent)]) (JMP)")
user.show_message("You implanted the implant into [M].")
- if(src.imp.implanted(M, user))
- src.imp.forceMove(M)
- src.imp.imp_in = M
- src.imp.implanted = 1
- if (ishuman(M))
+ if(imp.implanted(M, user))
+ imp.forceMove(M)
+ imp.imp_in = M
+ imp.implanted = 1
+ if(ishuman(M))
var/mob/living/carbon/human/H = M
var/datum/organ/external/affected = H.get_organ(user.zone_sel.selecting)
- affected.implants += src.imp
+ affected.implants += imp
imp.part = affected
M:implanting = 0
- src.imp = null
+ imp = null
update()
- return
/*
+/obj/item/weapon/implanter/New()
+ if(imp_type)
+ imp = new imp_type(src)
+ ..()
+ update()
+
/obj/item/weapon/implanter/traitor
name = "greytide conversion kit"
desc = "Any humanoid injected with this implant will become loyal to the injector and the greytide, unless of course the host is already loyal to someone else."
-
-/obj/item/weapon/implanter/traitor/New()
- src.imp = new /obj/item/weapon/implant/traitor(src)
- ..()
- update()
- return*/
+ imp_type = /obj/item/weapon/implant/traitor
+*/
/obj/item/weapon/implanter/loyalty
name = "implanter-loyalty"
-
-/obj/item/weapon/implanter/loyalty/New()
- src.imp = new /obj/item/weapon/implant/loyalty( src )
- ..()
- update()
- return
-
-
+ imp_type = /obj/item/weapon/implant/loyalty
/obj/item/weapon/implanter/explosive
name = "implanter (E)"
-
-/obj/item/weapon/implanter/explosive/New()
- src.imp = new /obj/item/weapon/implant/explosive( src )
- ..()
- update()
- return
+ imp_type = /obj/item/weapon/implant/explosive
/obj/item/weapon/implanter/adrenalin
name = "implanter-adrenalin"
+ imp_type = /obj/item/weapon/implant/adrenalin
-/obj/item/weapon/implanter/adrenalin/New()
- src.imp = new /obj/item/weapon/implant/adrenalin(src)
- ..()
- update()
- return
+/obj/item/weapon/implanter/peace
+ name = "implanter-pax"
+ desc = "An implanter containing a pax implant"
+ imp_type = /obj/item/weapon/implant/peace
/obj/item/weapon/implanter/compressed
name = "implanter (C)"
icon_state = "cimplanter1"
+ imp_type = /obj/item/weapon/implant/compressed
var/list/forbidden_types=list(
// /obj/item/weapon/storage/bible // VG #11 - Recursion.
)
-/obj/item/weapon/implanter/compressed/New()
- imp = new /obj/item/weapon/implant/compressed( src )
- ..()
- update()
- return
-
/obj/item/weapon/implanter/compressed/update()
- if (imp)
+ if(imp)
var/obj/item/weapon/implant/compressed/c = imp
if(!c.scanned)
icon_state = "cimplanter1"
@@ -115,16 +91,15 @@
icon_state = "cimplanter2"
else
icon_state = "cimplanter0"
- return
/obj/item/weapon/implanter/compressed/attack(mob/M as mob, mob/user as mob)
// Attacking things in your hands tends to make this fuck up.
if(!istype(M))
return
var/obj/item/weapon/implant/compressed/c = imp
- if (!c)
+ if(!c)
return
- if (c.scanned == null)
+ if(c.scanned == null)
to_chat(user, "Please scan an object with the implanter first.")
return
..()
@@ -135,7 +110,7 @@
return
if(istype(I) && imp)
var/obj/item/weapon/implant/compressed/c = imp
- if (c.scanned)
+ if(c.scanned)
if(istype(I,/obj/item/weapon/storage))
..()
return
diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm
index 28021c3472a..05d7ddd07d0 100644
--- a/code/game/objects/items/weapons/power_cells.dm
+++ b/code/game/objects/items/weapons/power_cells.dm
@@ -70,6 +70,10 @@
maxcharge = 10000
starting_materials = list(MAT_IRON = 700, MAT_GLASS = 60)
+/obj/item/weapon/cell/high/cyborg
+ name = "cyborg rechargeable power cell"
+ maxcharge = 7500
+
/obj/item/weapon/cell/high/empty/New()
..()
charge = 0
@@ -108,6 +112,11 @@
w_type = RECYK_BIOLOGICAL
minor_fault = 1
+/obj/item/weapon/cell/potato/soviet
+ charge = 15000
+ maxcharge = 15000
+ minor_fault = 0
+
/obj/item/weapon/cell/crepe
name = "power crêpe"
desc = "Warning: May contain dairy products, 12,000kJ of searing death, gluten."
@@ -118,6 +127,11 @@
w_type = RECYK_BIOLOGICAL
minor_fault = 1
+/obj/item/weapon/cell/crepe/mommi
+ maxcharge = 10000
+ charge = 10000
+ minor_fault = 0
+
/obj/item/weapon/cell/crepe/attack_self(var/mob/living/user)
if(charge)
user.visible_message("\The [user] takes a bite out of \the [src]", "You take a bite out of \the [src]")
diff --git a/code/game/objects/items/weapons/shard.dm b/code/game/objects/items/weapons/shard.dm
index 4304fb59f21..253d9fcbb54 100644
--- a/code/game/objects/items/weapons/shard.dm
+++ b/code/game/objects/items/weapons/shard.dm
@@ -108,12 +108,12 @@
/obj/item/weapon/shard/Crossed(mob/living/AM)
if(istype(AM))
if(AM.locked_to) //Mob is locked to something, so it's not actually stepping on the glass
- playsound(get_turf(src), 'sound/effects/glass_step.ogg', 50, 1) //Make noise
+ playsound(src, 'sound/effects/glass_step.ogg', 50, 1) //Make noise
return //Stop here
if(AM.flying) //We don't check for lying yet because it's intended to hurt
return
else //Stepping on the glass
- playsound(get_turf(src), 'sound/effects/glass_step.ogg', 50, 1)
+ playsound(src, 'sound/effects/glass_step.ogg', 50, 1)
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
var/danger = FALSE
diff --git a/code/game/objects/items/weapons/stock_parts.dm b/code/game/objects/items/weapons/stock_parts.dm
index 8086add507e..996b9169ca5 100644
--- a/code/game/objects/items/weapons/stock_parts.dm
+++ b/code/game/objects/items/weapons/stock_parts.dm
@@ -54,7 +54,7 @@
to_chat(user, "You can't secure \the [src] to [istype(src.loc,/turf/space) ? "space" : "this"]!")
return
to_chat(user, "You discharge \the [src] and secure it to the floor.")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
switch(src.type)
if(/obj/item/weapon/stock_parts/capacitor)
new /obj/machinery/power/secured_capacitor(get_turf(src.loc))
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index 668987ac776..46d6c02ae56 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -16,7 +16,7 @@
max_combined_w_class = 21
/obj/item/weapon/storage/backpack/attackby(obj/item/weapon/W as obj, mob/user as mob)
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
. = ..()
/*
diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm
index a18330d8869..4c686ee95c3 100644
--- a/code/game/objects/items/weapons/storage/bags.dm
+++ b/code/game/objects/items/weapons/storage/bags.dm
@@ -37,6 +37,8 @@
storage_slots = 21
can_only_hold = list() // any
cant_hold = list("/obj/item/weapon/disk/nuclear", "/obj/item/weapon/pinpointer") //No janiborg, stop stealing the pinpointer with your bag.
+ slot_flags = SLOT_BELT | SLOT_OCLOTHING
+ no_storage_slot = list(slot_wear_suit) //when worn on the suit slot it will function purely as a suit and will not store items
/obj/item/weapon/storage/bag/trash/update_icon()
if(contents.len == 0)
@@ -67,6 +69,7 @@
body_parts_covered = FULL_HEAD|BEARD
slot_flags = SLOT_BELT | SLOT_HEAD
clothing_flags = BLOCK_BREATHING | BLOCK_GAS_SMOKE_EFFECT
+ no_storage_slot = list(slot_head)
foldable = /obj/item/folded_bag
obj/item/weapon/storage/bag/plasticbag/can_quick_store(var/obj/item/I)
@@ -75,20 +78,6 @@ obj/item/weapon/storage/bag/plasticbag/can_quick_store(var/obj/item/I)
obj/item/weapon/storage/bag/plasticbag/quick_store(var/obj/item/I)
return handle_item_insertion(I,0)
-/obj/item/weapon/storage/bag/plasticbag/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0)
- //Forbid wearing bags with something inside!
- .=..()
- if(contents.len && (slot == slot_head))
- return CANNOT_EQUIP
-
-/obj/item/weapon/storage/bag/plasticbag/can_be_inserted()
- if(isliving(loc))
- var/mob/living/L = loc
- if(L.is_wearing_item(src, slot_head)) //Wearing the bag on the head
- return FALSE
-
- return ..()
-
/obj/item/weapon/storage/bag/plasticbag/suicide_act(mob/user)
user.visible_message("[user] puts the [src.name] over \his head and tightens the handles around \his neck! It looks like \he's trying to commit suicide.")
return(OXYLOSS)
@@ -110,6 +99,70 @@ obj/item/weapon/storage/bag/plasticbag/quick_store(var/obj/item/I)
max_combined_w_class = 200 //Doesn't matter what this is, so long as it's more or equal to storage_slots * ore.w_class
can_only_hold = list("/obj/item/weapon/ore")
+/obj/item/weapon/storage/bag/ore/auto
+ name = "automatic ore loader"
+ desc = "A mining satchel with a built-in inserter used to automatically move ore over short distances."
+ icon_state = "tech_satchel"
+ actions_types = list(/datum/action/item_action/toggle_auto_handling)
+ var/handling = FALSE
+ var/event_key = null
+
+/datum/action/item_action/toggle_auto_handling
+ name = "Toggle Ore Loader"
+
+/datum/action/item_action/toggle_auto_handling/Trigger()
+ var/obj/item/weapon/storage/bag/ore/auto/T = target
+ var/mob/user = usr
+
+ if(!usr)
+ if(!ismob(T.loc))
+ return
+ user = T.loc
+ if(!istype(T))
+ return
+
+ T.handling = !T.handling
+
+ to_chat(user, "You turn \the [T.name] [T.handling? "on":"off"].")
+
+ if(T.handling == TRUE)
+ T.event_key = user.on_moved.Add(T, "mob_moved")
+ else
+ user.on_moved.Remove(T, "mob_moved")
+ T.event_key = null
+
+/obj/item/weapon/storage/bag/ore/auto/proc/auto_collect()
+ var/atom/collect_loc = get_turf(loc)
+ for(var/obj/item/weapon/ore/ore in collect_loc.contents)
+ preattack(collect_loc, src, TRUE)
+ break
+
+/obj/item/weapon/storage/bag/ore/auto/proc/auto_fill(var/mob/holder)
+ var/obj/structure/ore_box/box = null
+ if(istype(holder.pulling, /obj/structure/ore_box))
+ box = holder.pulling
+ if(box)
+ for(var/obj/item/weapon/ore/ore in contents)
+ if(ore.material)
+ remove_from_storage(ore)
+ box.materials.addAmount(ore.material, 1)
+ qdel(ore)
+
+/obj/item/weapon/storage/bag/ore/auto/proc/mob_moved(var/list/event_args, var/mob/holder)
+ if(isrobot(holder))
+ var/mob/living/silicon/robot/S = holder
+ if(locate(src) in S.get_all_slots())
+ auto_collect()
+ auto_fill(holder)
+ else
+ if(holder.is_holding_item(src))
+ auto_collect()
+ auto_fill(holder)
+
+/obj/item/weapon/storage/bag/ore/auto/dropped(mob/user)
+ if(event_key)
+ user.on_moved.Remove(src, "mob_moved")
+ event_key = null
// -----------------------------
// Plant bag
@@ -151,7 +204,7 @@ obj/item/weapon/storage/bag/plasticbag/quick_store(var/obj/item/I)
var/played = FALSE
for(var/obj/item/I in P.contents)
if(seedify(I) && !played)
- playsound(get_turf(P), 'sound/machines/juicerfast.ogg', 50, 1)
+ playsound(P, 'sound/machines/juicerfast.ogg', 50, 1)
played = TRUE
P.orient2hud(user)
if(user.s_active)
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 8db6d79dcb7..e2e6da4d9ae 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -40,7 +40,9 @@
"/obj/item/device/t_scanner",
"/obj/item/device/analyzer",
"/obj/item/taperoll/engineering",
+ "/obj/item/taperoll/syndie/engineering",
"/obj/item/taperoll/atmos",
+ "/obj/item/taperoll/syndie/atmos",
"/obj/item/weapon/extinguisher",
"/obj/item/weapon/rcd_ammo",
"/obj/item/weapon/reagent_containers/glass/fuelcan",
@@ -98,7 +100,9 @@
"/obj/item/device/t_scanner",
"/obj/item/device/analyzer",
"/obj/item/taperoll/engineering",
+ "/obj/item/taperoll/syndie/engineering",
"/obj/item/taperoll/atmos",
+ "/obj/item/taperoll/syndie/atmos",
"/obj/item/weapon/extinguisher",
"/obj/item/device/rcd/matter/engineering",
"/obj/item/device/rcd/rpd",
@@ -196,6 +200,7 @@
"/obj/item/device/radio/headset",
"/obj/item/weapon/melee/baton",
"/obj/item/taperoll/police",
+ "/obj/item/taperoll/syndie/police",
"/obj/item/weapon/gun/energy/taser",
"/obj/item/weapon/gun/projectile/sec",
"/obj/item/weapon/legcuffs/bolas",
@@ -329,6 +334,8 @@
/obj/item/weapon/storage/belt/lazarus/antag/New(loc, mob/user)
var/blocked = list(
/mob/living/simple_animal/hostile/hivebot/tele,
+ /mob/living/simple_animal/hostile/wendigo/evolved,
+ /mob/living/simple_animal/hostile/wendigo/alpha,
)
var/list/critters = existing_typesof(/mob/living/simple_animal/hostile) - blocked // list of possible hostile mobs
critters = shuffle(critters)
diff --git a/code/game/objects/items/weapons/storage/bible.dm b/code/game/objects/items/weapons/storage/bible.dm
index b53df7dadfb..bb26fdeaf57 100644
--- a/code/game/objects/items/weapons/storage/bible.dm
+++ b/code/game/objects/items/weapons/storage/bible.dm
@@ -96,7 +96,7 @@
if(M.stat == DEAD) //Our target is dead. RIP in peace
user.visible_message("[user] [pick(attack_verb)] [M]'s lifeless body with \the [src].",
"You bless [M]'s lifeless body with \the [src], trying to conjure [my_rel.deity_name]'s mercy on them.")
- playsound(get_turf(src), "punch", 25, 1, -1)
+ playsound(src, "punch", 25, 1, -1)
//TODO : Way to bring people back from death if they are your followers
return 1 //Otherwise, there's so little we can do
@@ -104,7 +104,7 @@
//Our target is alive, prepare the blessing
user.visible_message("[user] [pick(attack_verb)] [M]'s head with \the [src].",
"You bless [M]'s head with \the [src]. In the name of [my_rel.deity_name], bless thee!")
- playsound(get_turf(src), "punch", 25, 1, -1)
+ playsound(src, "punch", 25, 1, -1)
if(ishuman(M)) //Only humans can be vampires or cultists. isChaplain() checks are here to ensure only the proper chaplain has the gameplay-related interactions.
var/mob/living/carbon/human/H = M
@@ -151,7 +151,7 @@
A.reagents.add_reagent(HOLYWATER, water2holy)
/obj/item/weapon/storage/bible/attackby(obj/item/weapon/W as obj, mob/user as mob)
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
. = ..()
/obj/item/weapon/storage/bible/pickup(mob/living/user as mob)
diff --git a/code/game/objects/items/weapons/storage/bluespace.dm b/code/game/objects/items/weapons/storage/bluespace.dm
index cf94dd40127..f36600465dc 100644
--- a/code/game/objects/items/weapons/storage/bluespace.dm
+++ b/code/game/objects/items/weapons/storage/bluespace.dm
@@ -30,6 +30,9 @@
qdel(user)
/obj/item/weapon/storage/backpack/holding/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ . = ..()
+ if(!.)
+ return
if(W == src)
return // HOLY FUCKING SHIT WHY STORAGE CODE, WHY - pomf
var/obj/item/weapon/storage/backpack/holding/H = locate(/obj/item/weapon/storage/backpack/holding) in W
@@ -38,8 +41,7 @@
return
if(istype(W, /obj/item/weapon/storage/backpack/holding))
singulocreate(W, user)
- return
- . = ..()
+
//BoH+BoH=Singularity, WAS commented out
/obj/item/weapon/storage/backpack/holding/proc/singulocreate(var/obj/item/weapon/storage/backpack/holding/H, var/mob/user)
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index e40d7956b9c..4963318fa88 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -458,46 +458,51 @@
/obj/item/weapon/storage/box/lethalshells
name = "lethal shells"
icon_state = "lethal shells"
+ storage_slots = 16
/obj/item/weapon/storage/box/lethalshells/New()
..()
- for(var/i=0,i<15,i++)
+ for(var/i in 1 to 16)
new /obj/item/ammo_casing/shotgun(src)
/obj/item/weapon/storage/box/beanbagshells
name = "bean bag shells"
icon_state = "bean bag shells"
+ storage_slots = 16
/obj/item/weapon/storage/box/beanbagshells/New()
..()
- for(var/i=0,i<15,i++)
+ for(var/i in 1 to 16)
new /obj/item/ammo_casing/shotgun/beanbag(src)
/obj/item/weapon/storage/box/stunshells
name = "stun shells"
icon_state = "stun shells"
+ storage_slots = 16
/obj/item/weapon/storage/box/stunshells/New()
..()
- for(var/i=0,i<15,i++)
+ for(var/i in 1 to 16)
new /obj/item/ammo_casing/shotgun/stunshell(src)
/obj/item/weapon/storage/box/dartshells
name = "shotgun darts"
icon_state = "dart shells"
+ storage_slots = 16
/obj/item/weapon/storage/box/dartshells/New()
..()
- for(var/i=0,i<15,i++)
+ for(var/i in 1 to 16)
new /obj/item/ammo_casing/shotgun/dart(src)
/obj/item/weapon/storage/box/buckshotshells
name = "buckshot shells"
icon_state = "lethal shells"
+ storage_slots = 16
/obj/item/weapon/storage/box/buckshotshells/New()
..()
- for(var/i=0,i<15,i++)
+ for(var/i in 1 to 16)
new /obj/item/ammo_casing/shotgun/buckshot(src)
/obj/item/weapon/storage/box/labels
diff --git a/code/game/objects/items/weapons/storage/briefcase.dm b/code/game/objects/items/weapons/storage/briefcase.dm
index dfc0fd77d89..932675a5954 100644
--- a/code/game/objects/items/weapons/storage/briefcase.dm
+++ b/code/game/objects/items/weapons/storage/briefcase.dm
@@ -33,7 +33,7 @@
to_chat(user, "The [src] slips out of your hand and hits your head.")
user.take_organ_damage(10)
user.Paralyse(2)
- playsound(get_turf(src), "swing_hit", 50, 1, -1)
+ playsound(src, "swing_hit", 50, 1, -1)
return
..()
diff --git a/code/game/objects/items/weapons/storage/lockbox.dm b/code/game/objects/items/weapons/storage/lockbox.dm
index 0638bda8553..61923ae5a7d 100644
--- a/code/game/objects/items/weapons/storage/lockbox.dm
+++ b/code/game/objects/items/weapons/storage/lockbox.dm
@@ -83,7 +83,6 @@
..()
if(health <= 0)
for(var/atom/movable/A in src)
- for(var/obj/O in src)
remove_from_storage(A, get_turf(src))
qdel(src)
@@ -96,51 +95,34 @@
if(2)
if(prob(80))
for(var/atom/movable/A in src)
- for(var/obj/O in src)
remove_from_storage(A, get_turf(src))
A.ex_act(3)
qdel(src)
if(3)
if(prob(50))
for(var/atom/movable/A in src)
- for(var/obj/O in src)
remove_from_storage(A, get_turf(src))
qdel(src)
/obj/item/weapon/storage/lockbox/emp_act(severity)
..()
if(!broken)
+ var/probab
switch(severity)
if(1)
- if(prob(80))
- locked = !locked
- src.update_icon()
- if(!locked)
- for(var/atom/movable/A in src)
- for(var/obj/O in src)
- remove_from_storage(A, get_turf(src))
- if(oneuse)
- qdel(src)
+ probab = 80
if(2)
- if(prob(50))
- locked = !locked
- src.update_icon()
- if(!locked)
- for(var/atom/movable/A in src)
- for(var/obj/O in src)
- remove_from_storage(A, get_turf(src))
- if(oneuse)
- qdel(src)
- if(3)
- if(prob(25))
- locked = !locked
- src.update_icon()
- if(!locked)
- for(var/atom/movable/A in src)
- for(var/obj/O in src)
- remove_from_storage(A, get_turf(src))
- if(oneuse)
- qdel(src)
+ probab = 50
+ if(prob(probab))
+ locked = !locked
+ src.update_icon()
+ if(!locked)
+ for(var/atom/movable/A in src)
+ remove_from_storage(A, get_turf(src))
+ if(oneuse)
+ qdel(src)
+
+
/obj/item/weapon/storage/lockbox/update_icon()
..()
@@ -166,6 +148,7 @@
/obj/item/weapon/storage/lockbox/tracking
name = "lockbox (tracking implants)"
req_one_access = list(access_security)
+ storage_slots = 5
/obj/item/weapon/storage/lockbox/tracking/New()
..()
@@ -178,6 +161,7 @@
/obj/item/weapon/storage/lockbox/chem
name = "lockbox (chemical implants)"
req_one_access = list(access_security)
+ storage_slots = 5
/obj/item/weapon/storage/lockbox/chem/New()
..()
diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm
index 4ab6add1a9c..c9cf8f2e650 100644
--- a/code/game/objects/items/weapons/storage/secure.dm
+++ b/code/game/objects/items/weapons/storage/secure.dm
@@ -156,7 +156,7 @@
if ((src.loc == user) && (src.locked == 1))
to_chat(usr, "[src] is locked and cannot be opened!")
else if ((src.loc == user) && (!src.locked))
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
if (user.s_active)
user.s_active.close(user) //Close and re-open
src.show_to(user)
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index b99f55420c2..edc6fb4fcc8 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -29,6 +29,7 @@
var/foldable = null // BubbleWrap - if set, can be folded (when empty) into a sheet of cardboard
var/foldable_amount = 1 // Number of foldables to produce, if any - N3X
var/internal_store = 0
+ var/list/no_storage_slot = new/list()//if the item is equipped in a slot that is contained in this list, the item will act purely as a clothing item and not a storage item (ie plastic bags over head)
/obj/item/weapon/storage/proc/can_use()
return TRUE
@@ -48,7 +49,7 @@
if(!(src.loc == usr) || (src.loc && src.loc.loc == usr))
return
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
if(!( M.restrained() ) && !( M.stat ))
var/obj/abstract/screen/inventory/OI = over_object
@@ -213,9 +214,14 @@
//This proc return 1 if the item can be picked up and 0 if it can't.
//Set the stop_messages to stop it from printing messages
-/obj/item/weapon/storage/proc/can_be_inserted(obj/item/W as obj, stop_messages = 0)
+/obj/item/weapon/storage/proc/can_be_inserted(obj/item/W as obj, stop_messages = 0,mob/M, slot)
if(!istype(W))
return //Not an item
+ if(isliving(loc))
+ var/mob/living/L = loc
+ for (var/i in no_storage_slot)
+ if(L.is_wearing_item(src, i)) //prevents putting items into a storage item that's equipped on a no_storage_slot
+ return FALSE
if(src.loc == W)
return 0 //Means the item is already in the storage item
@@ -450,7 +456,7 @@
return
/obj/item/weapon/storage/attack_hand(mob/user as mob)
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
if(ishuman(user))
var/mob/living/carbon/human/H = user
@@ -665,3 +671,10 @@
/obj/item/weapon/storage/proc/mass_remove(var/atom/A)
for(var/obj/item/O in contents)
remove_from_storage(O, A)
+
+/obj/item/weapon/storage/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0)
+ //Forbids wearing a storage item in a no_storage_slot (ie plastic bags over head) with something already inside
+ .=..()
+ for (var/i in no_storage_slot)
+ if(contents.len && (slot == i))
+ return CANNOT_EQUIP
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/toolbox.dm b/code/game/objects/items/weapons/storage/toolbox.dm
index 252026cef82..c701288894d 100644
--- a/code/game/objects/items/weapons/storage/toolbox.dm
+++ b/code/game/objects/items/weapons/storage/toolbox.dm
@@ -116,3 +116,17 @@
new /obj/item/stack/cable_coil(src,30,color)
new /obj/item/weapon/wirecutters(src)
new /obj/item/device/multitool(src)
+
+/obj/item/weapon/storage/toolbox/robotics
+ name = "robotics toolbox"
+
+/obj/item/weapon/storage/toolbox/robotics/New()
+ ..()
+ var/color = pick("red","yellow","green","blue","pink","orange","cyan","white")
+ new /obj/item/device/robotanalyzer(src)
+ new /obj/item/weapon/crowbar(src)
+ new /obj/item/weapon/wrench(src)
+ new /obj/item/weapon/weldingtool(src)
+ new /obj/item/weapon/screwdriver(src)
+ new /obj/item/weapon/wirecutters(src)
+ new /obj/item/stack/cable_coil(src,30,color)
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 2a24bd68ad7..cdbe431d2f5 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -222,9 +222,9 @@
New()
..()
- var/obj/item/weapon/implanter/O = new(src)
- O.imp = new /obj/item/weapon/implant/traitor(O)
- O.update()
+ //new /obj/item/weapon/implanter/traitor(src)
+ //new /obj/item/weapon/implanter/traitor(src)
+ new /obj/item/clothing/glasses/sunglasses/sechud/syndishades(src)
/obj/item/weapon/storage/box/syndie_kit/boolets
name = "Shotgun shells"
diff --git a/code/game/objects/items/weapons/surgery_tools.dm b/code/game/objects/items/weapons/surgery_tools.dm
index a03c26b600e..d760f427d2f 100644
--- a/code/game/objects/items/weapons/surgery_tools.dm
+++ b/code/game/objects/items/weapons/surgery_tools.dm
@@ -220,7 +220,7 @@
if(isscrewdriver(used_item) && cauterymode)
if(held)
to_chat(user, "You detach \the [held] and \the [src] switches to cutting mode.")
- playsound(get_turf(src), "sound/items/screwdriver.ogg", 10, 1)
+ playsound(src, "sound/items/screwdriver.ogg", 10, 1)
held.add_fingerprint(user)
held.forceMove(get_turf(src))
held = null
@@ -233,7 +233,7 @@
to_chat(user, "There's already a cautery attached to \the [src].")
else if(!held && user.drop_item(used_item, src))
to_chat(user, "You attach \the [used_item] to \the [src].")
- playsound(get_turf(src), "sound/items/screwdriver.ogg", 10, 1)
+ playsound(src, "sound/items/screwdriver.ogg", 10, 1)
src.held = used_item
else
to_chat(user, "You can't let go of \the [used_item]!")
@@ -324,7 +324,8 @@
/obj/item/weapon/FixOVein
- name = "FixOVein"
+ name = "fixOVein"
+ desc = "A small tube that contains synthetic vein to repair or replace damaged veins."
icon = 'icons/obj/surgery.dmi'
icon_state = "fixovein"
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/surgery_tools.dmi', "right_hand" = 'icons/mob/in-hand/right/surgery_tools.dmi')
@@ -335,6 +336,54 @@
origin_tech = Tc_MATERIALS + "=1;" + Tc_BIOTECH + "=3"
var/usage_amount = 10
+/obj/item/weapon/FixOVein/clot
+ name = "capillary laying operation tool" //C.L.O.T.
+ desc = "A canister like tool that has two containers on it that stores synthetic vein or biofoam. There's a small processing port on the side where gauze can be inserted to produce biofoam."
+ icon = 'icons/obj/surgery.dmi'
+ icon_state = "clot"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/surgery_tools.dmi', "right_hand" = 'icons/mob/in-hand/right/surgery_tools.dmi')
+ item_state = "clot"
+ sharpness = null
+ sharpness_flags = null
+ surgery_speed = 0.5
+ origin_tech = Tc_MATERIALS + "=5;" + Tc_BIOTECH + "=5;" + Tc_ENGINEERING + "=4"
+ var/foam = 0
+
+/obj/item/weapon/FixOVein/clot/examine(mob/user)
+ ..()
+ to_chat(user, "\The [src] contains [foam] unit[foam > 1 ? "s" : ""][foam == 0 ? "s" : ""] of biofoam.")
+
+/obj/item/weapon/FixOVein/clot/attack_self(mob/user)
+ if(foam)
+ if(!sharpness)
+ sharpness= 0.5
+ sharpness_flags = SHARP_TIP
+ icon_state = "clot-F"
+ else
+ sharpness = null
+ sharpness_flags = null
+ icon_state = "clot"
+ to_chat(user, "You toggle \the [src]'s tip to [sharpness == 0.5 ? "inject biofoam" : "repair veins"].")
+ else
+ to_chat(user, "\The [src] requires biofoam to use the injection tip.You insert a bit of \the [W] into \the [src].")
+ W.use(1)
+ return
+ else if(istype(W, /obj/item/stack/medical/advanced/bruise_pack))
+ foam = 5
+ to_chat(user, "You insert a bit of \the [W] into \the [src].")
+ W.use(1)
+ else
+ to_chat(user, "You can't see any way to use \the [W] on \the [src].")
+ else
+ to_chat(user, "[foam == 5 ? "The [src] is full!" : ""]You can't see any way to use \the [W] on \the [src].")
+
+
/obj/item/weapon/bonesetter
name = "bone setter"
icon = 'icons/obj/surgery.dmi'
@@ -380,7 +429,7 @@
target.AdjustParalysis(-3)
target.AdjustStunned(-3)
target.AdjustKnockdown(-3)
- playsound(get_turf(target), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
target.visible_message(
"[user] prods [target] trying to wake \him up!",
"You prod [target] trying to wake \him up!",
diff --git a/code/game/objects/items/weapons/switchtool.dm b/code/game/objects/items/weapons/switchtool.dm
index de533bc56e2..7ec199abd55 100644
--- a/code/game/objects/items/weapons/switchtool.dm
+++ b/code/game/objects/items/weapons/switchtool.dm
@@ -58,6 +58,7 @@
return
if(deployed)
+ edit_deploy(0)
to_chat(user, "You store \the [deployed].")
undeploy()
else
@@ -107,20 +108,20 @@
return TRUE
/obj/item/weapon/switchtool/proc/remove_module(mob/user)
- deployed.cant_drop = 0
+ edit_deploy(0)
deployed.forceMove(get_turf(user))
for(var/module in stored_modules)
if(stored_modules[module] == deployed)
stored_modules[module] = null
break
to_chat(user, "You successfully remove \the [deployed] from \the [src].")
- playsound(get_turf(src), "sound/items/screwdriver.ogg", 10, 1)
+ playsound(src, "sound/items/screwdriver.ogg", 10, 1)
undeploy()
return TRUE
/obj/item/weapon/switchtool/proc/undeploy()
- playsound(get_turf(src), undeploy_sound, 10, 1)
- deployed.cant_drop = 0
+ playsound(src, undeploy_sound, 10, 1)
+ edit_deploy(0)
deployed = null
overlays.len = 0
w_class = initial(w_class)
@@ -129,21 +130,33 @@
/obj/item/weapon/switchtool/proc/deploy(var/module)
if(!(module in stored_modules))
return FALSE
-
if(!stored_modules[module])
return FALSE
if(deployed)
return FALSE
- playsound(get_turf(src), deploy_sound, 10, 1)
+ playsound(src, deploy_sound, 10, 1)
deployed = stored_modules[module]
hmodule = get_module_name(module)
- deployed.cant_drop = 1
overlays += get_module_name(module)
w_class = max(w_class, deployed.w_class)
update_icon()
return TRUE
+/obj/item/weapon/switchtool/proc/edit_deploy(var/doedit)
+ if(doedit) //Makes the deployed item take on the features of the switchtool. This is for attack animations and attack text.
+ deployed.name = name
+ deployed.icon = icon
+ deployed.icon_state = icon_state
+ deployed.overlays = overlays
+ deployed.cant_drop = TRUE
+ else //Revert the changes to the deployed item.
+ deployed.name = initial(deployed.name)
+ deployed.icon = initial(deployed.icon)
+ deployed.icon_state = initial(deployed.icon_state)
+ deployed.overlays = initial(deployed.overlays)
+ deployed.cant_drop = FALSE
+
/obj/item/weapon/switchtool/proc/choose_deploy(mob/user)
var/list/potential_modules = list()
for(var/module in stored_modules)
@@ -157,6 +170,7 @@
else if(potential_modules.len == 1)
deploy(potential_modules[1])
to_chat(user, "You deploy \the [potential_modules[1]]")
+ edit_deploy(1)
return TRUE
else
@@ -169,6 +183,7 @@
break
if(deploy(true_module))
to_chat(user, "You deploy \the [deployed].")
+ edit_deploy(1)
return TRUE
return
@@ -363,7 +378,6 @@
/obj/item/weapon/switchtool/holo/update_icon()
if(deployed)
item_state = "[hmodule]"
- deployed.appearance = appearance
else
item_state = "Hswitchtool"
@@ -383,19 +397,20 @@
return FALSE
set_light(brightness_min)
overlays += "[hmodule]"
+ edit_deploy(1)
if(istype(deployed, /obj/item/device/flashlight))
set_light(brightness_max)
- //Since you can't turn off the welder inside the tool, I'm using the unused welder that very slowly regens fuel, looks like 1u per 5 byond seconds, thanks byond.
+//Since you can't turn off the welder inside the tool, I'm using the unused welder that very slowly regens fuel, 5 fuel per process().
//It can be refulled manually, but since it starts active you will blow up welder tanks if deployed and then put to a tank.
if(istype(deployed, /obj/item/weapon/weldingtool/experimental))
var/obj/item/weapon/weldingtool/experimental/weldingtool = deployed
- weldingtool.welding = 1
- weldingtool.status = 1
- weldingtool.max_fuel = 50
- weldingtool.start_fueled = 1
+ weldingtool.setWelding(1)
/obj/item/weapon/switchtool/holo/undeploy()
+ if(istype(deployed, /obj/item/weapon/weldingtool/experimental))
+ var/obj/item/weapon/weldingtool/experimental/weldingtool = deployed
+ weldingtool.setWelding(0)
..()
set_light(0)
@@ -484,4 +499,4 @@
"/obj/item/device/analyzer/scope:atmospheric analysis scope" = null,
"/obj/item/weapon/solder/pre_fueled:soldering iron" = null,
"/obj/item/device/silicate_sprayer:silicate sprayer" = null
- )
\ No newline at end of file
+ )
diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm
index fb899584885..ffacd611eb0 100644
--- a/code/game/objects/items/weapons/swords_axes_etc.dm
+++ b/code/game/objects/items/weapons/swords_axes_etc.dm
@@ -52,7 +52,7 @@
if (user.a_intent == I_HURT)
if(!..())
return
- playsound(get_turf(src), "swing_hit", 50, 1, -1)
+ playsound(src, "swing_hit", 50, 1, -1)
if (M.stuttering < 8 && (!(M_HULK in M.mutations)) /*&& (!istype(H:wear_suit, /obj/item/clothing/suit/judgerobe))*/)
M.stuttering = 8
M.Stun(8)
@@ -61,7 +61,7 @@
if (O.client)
O.show_message("[M] has been beaten with \the [src] by [user]!", 1, "You hear someone fall", 2)
else
- playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1, -1)
M.Stun(5)
M.Knockdown(5)
M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])")
@@ -120,7 +120,7 @@
w_class = initial(w_class)
force = initial(force) //not so robust now
attack_verb = list("hits", "punches")
- playsound(get_turf(src), 'sound/weapons/empty.ogg', 50, 1)
+ playsound(src, 'sound/weapons/empty.ogg', 50, 1)
add_fingerprint(user)
if(!blood_overlays["[type][icon_state]"])
@@ -156,11 +156,11 @@
if(!..())
return
if(!isrobot(target))
- playsound(get_turf(src), "swing_hit", 50, 1, -1)
+ playsound(src, "swing_hit", 50, 1, -1)
//target.Stun(4) //naaah
target.Knockdown(4)
else
- playsound(get_turf(src), 'sound/weapons/Genhit.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/Genhit.ogg', 50, 1, -1)
target.Knockdown(2)
target.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [user.name] ([user.ckey])")
user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [target.name] ([target.ckey])")
@@ -272,3 +272,11 @@
else
parent_borer.chemicals -= 5
sleep(10)
+
+/obj/item/weapon/melee/training_sword
+ name = "training sword"
+ desc = "A blunt object in the shape of a one handed sword."
+ icon_state = "grey_sword"
+ inhand_states = list("left_hand" = 'icons/mob/in-hand/left/swords_axes.dmi', "right_hand" = 'icons/mob/in-hand/right/swords_axes.dmi')
+ item_state = "grey_sword"
+ force = 4
diff --git a/code/game/objects/items/weapons/table_rack_parts.dm b/code/game/objects/items/weapons/table_rack_parts.dm
index 12e7fefec97..1d2477d84da 100644
--- a/code/game/objects/items/weapons/table_rack_parts.dm
+++ b/code/game/objects/items/weapons/table_rack_parts.dm
@@ -20,6 +20,8 @@
flags = FPRINT
siemens_coefficient = 1
attack_verb = list("slams", "bashes", "batters", "bludgeons", "thrashes", "whacks")
+ var/table_type = /obj/structure/table
+ sheet_type = /obj/item/stack/sheet/metal
/obj/item/weapon/table_parts/cultify()
new /obj/item/weapon/table_parts/wood(loc)
@@ -28,7 +30,7 @@
/obj/item/weapon/table_parts/attackby(obj/item/weapon/W, mob/user)
..()
if (iswrench(W))
- drop_stack(/obj/item/stack/sheet/metal, user.loc, 1, user)
+ drop_stack(sheet_type, user.loc, 1, user)
qdel(src)
return
if (istype(W, /obj/item/stack/rods))
@@ -48,13 +50,15 @@
to_chat(user, "You add glass panes to \the [name].")
glass.use(1)
qdel(src)
-
/obj/item/weapon/table_parts/attack_self(mob/user)
- new /obj/structure/table(user.loc)
+ if(locate(/obj/structure/table) in get_turf(user))
+ to_chat(user, "There is already a table here!")
+ return
+
+ new table_type(user.loc)
user.drop_item(src, force_drop = 1)
qdel(src)
-
/obj/item/weapon/table_parts/reinforced
name = "reinforced table parts"
desc = "Hard table parts. Well...harder..."
@@ -65,32 +69,28 @@
melt_temperature=MELTPOINT_STEEL
flags = FPRINT
siemens_coefficient = 1
+ table_type = /obj/structure/table/reinforced
/obj/item/weapon/table_parts/reinforced/attackby(obj/item/weapon/W, mob/user)
if (iswrench(W))
- drop_stack(/obj/item/stack/sheet/metal, user.loc, 1, user)
+ drop_stack(sheet_type, user.loc, 1, user)
drop_stack(/obj/item/stack/rods, user.loc, 1, user)
qdel(src)
-/obj/item/weapon/table_parts/reinforced/attack_self(mob/user)
- new /obj/structure/table/reinforced(user.loc)
- user.drop_item(src, force_drop = 1)
- qdel(src)
- return
-
-
/obj/item/weapon/table_parts/wood
name = "wooden table parts"
desc = "Keep away from fire."
icon_state = "wood_tableparts"
flags = 0
+ table_type = /obj/structure/table/woodentable
+ sheet_type = /obj/item/stack/sheet/wood
/obj/item/weapon/table_parts/wood/cultify()
return
/obj/item/weapon/table_parts/wood/attackby(obj/item/weapon/W, mob/user)
if (iswrench(W))
- drop_stack(/obj/item/stack/sheet/wood, user.loc, 1, user)
+ drop_stack(sheet_type, user.loc, 1, user)
qdel(src)
return
if (istype(W, /obj/item/stack/tile/grass))
@@ -106,24 +106,15 @@
/obj/item/weapon/table_parts/wood/poker
name = "gambling table parts"
icon_state = "gambling_tableparts"
-
-/obj/item/weapon/table_parts/wood/attack_self(mob/user)
- new /obj/structure/table/woodentable(user.loc)
- user.drop_item(src, force_drop = 1)
- qdel(src)
- return
+ table_type = /obj/structure/table/woodentable/poker
+ sheet_type = /obj/item/stack/sheet/wood
/obj/item/weapon/table_parts/wood/poker/attackby(obj/item/weapon/W, mob/user)
if (iswrench(W))
- drop_stack(/obj/item/stack/sheet/wood, user.loc, 1, user)
+ drop_stack(sheet_type, user.loc, 1, user)
drop_stack(/obj/item/stack/tile/grass, user.loc, 1, user)
qdel(src)
-/obj/item/weapon/table_parts/wood/poker/attack_self(mob/user)
- new /obj/structure/table/woodentable/poker(user.loc)
- user.drop_item(src, force_drop = 1)
- qdel(src)
-
/obj/item/weapon/table_parts/glass
name = "glass table parts"
desc = "Glass table parts for the spaceman with style."
@@ -134,18 +125,14 @@
melt_temperature=MELTPOINT_GLASS
flags = FPRINT
siemens_coefficient = 0 //copying from glass sheets and shards even if its bad balance
+ table_type = /obj/structure/table/glass
/obj/item/weapon/table_parts/glass/attackby(obj/item/weapon/W, mob/user)
if (iswrench(W))
drop_stack(/obj/item/stack/sheet/glass/glass, loc, 1, user)
- drop_stack(/obj/item/stack/sheet/metal, loc, 1, user)
+ drop_stack(sheet_type, loc, 1, user)
qdel(src)
-/obj/item/weapon/table_parts/glass/attack_self(mob/user)
- new /obj/structure/table/glass(user.loc)
- qdel(src)
-
-
/obj/item/weapon/rack_parts
name = "rack parts"
desc = "Parts of a rack."
@@ -160,7 +147,7 @@
/obj/item/weapon/rack_parts/attackby(obj/item/weapon/W, mob/user)
..()
if (iswrench(W))
- drop_stack(/obj/item/stack/sheet/metal, user.loc, 1, user)
+ drop_stack(sheet_type, user.loc, 1, user)
qdel(src)
return
if(istype(W, /obj/item/weapon/weldingtool))
diff --git a/code/game/objects/items/weapons/tanks/tank_types.dm b/code/game/objects/items/weapons/tanks/tank_types.dm
index f9066049b27..3cbdea1eb20 100644
--- a/code/game/objects/items/weapons/tanks/tank_types.dm
+++ b/code/game/objects/items/weapons/tanks/tank_types.dm
@@ -20,6 +20,11 @@
. = ..()
air_contents.adjust((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
+/obj/item/weapon/tank/oxygen/empty/New()
+ ..()
+ air_contents.oxygen = 0
+ air_contents.update_values()
+
/obj/item/weapon/tank/oxygen/yellow
desc = "A tank of oxygen, this one is yellow."
icon_state = "oxygen_f"
@@ -69,6 +74,11 @@
. = ..()
air_contents.adjust(, , , (3 * ONE_ATMOSPHERE) * 70 / (R_IDEAL_GAS_EQUATION * T20C))
+/obj/item/weapon/tank/plasma/empty/New()
+ ..()
+ air_contents.toxins = 0
+ air_contents.update_values()
+
/obj/item/weapon/tank/plasma/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index 41f960c7c13..2dd534d4f36 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -284,7 +284,7 @@
if(!T)
return
T.assume_air(air_contents)
- playsound(get_turf(src), 'sound/effects/spray.ogg', 10, 1, -3)
+ playsound(src, 'sound/effects/spray.ogg', 10, 1, -3)
qdel(src)
diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm
index 1223dce3606..fa8c0aabbc6 100644
--- a/code/game/objects/items/weapons/teleportation.dm
+++ b/code/game/objects/items/weapons/teleportation.dm
@@ -120,6 +120,27 @@ Frequency:
src.attack_self(M)
return
+/obj/item/weapon/bananapeel/bluespace
+ name = "bluespace banana peel"
+ desc = "A peel from a bluespace banana."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "bluespacebanana_peel"
+ item_state = "bluespacebanana_peel"
+
+/obj/item/weapon/bananapeel/bluespace/Crossed(AM as mob|obj)
+ if (istype(AM, /mob/living/carbon))
+ var/mob/living/carbon/M = AM
+ if (M.Slip(2, 2, 1))
+ M.simple_message("You slipped on the [name]!",
+ "Something is scratching at your feet! Oh god!")
+ if(istype(AM,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = AM
+ var/obj/teleported_shoes = H.get_item_by_slot(slot_shoes)
+ var/tele_destination = pick_rand_tele_turf(H, src.potency/15, src.potency/10)
+ if(teleported_shoes && tele_destination)
+ H.drop_from_inventory(teleported_shoes)
+ teleported_shoes.forceMove(tele_destination)
+ spark(H.loc)
/*
* Hand-tele
@@ -142,12 +163,50 @@ Frequency:
var/list/portals = list()
var/charge = HANDTELE_MAX_CHARGE//how many pairs of portal can the hand-tele sustain at once. a new charge is added every 30 seconds until the maximum is reached..
var/recharging = 0
+ var/destination_id
+ var/destination_name
/obj/item/weapon/hand_tele/attack_self(mob/user as mob)
var/turf/current_location = get_turf(user)//What turf is the user on?
if(!current_location||current_location.z==2||current_location.z>=7)//If turf was not found or they're on z level 2 or >7 which does not currently exist.
to_chat(user, "\The [src] is malfunctioning.")
return
+
+ if(charge < HANDTELE_PORTAL_COST)
+ user.show_message("\The [src] is recharging!")
+ return
+
+ if(!destination_id)
+ if(!choose_destination(user))
+ return
+ var/T = destination_id
+
+ if((destination_name == "None (Dangerous)") && prob(5))
+ T = locate(rand(7, world.maxx - 7), rand(7, world.maxy -7), map.zTCommSat)
+
+ var/turf/U = get_turf(src)
+ U.visible_message("Locked In.")
+ var/obj/effect/portal/P1 = new (U)
+ var/obj/effect/portal/P2 = new (get_turf(T))
+ P1.target = P2
+ P2.target = P1
+ P2.icon_state = "portal1"
+ P1.creator = src
+ P2.creator = src
+ P1.blend_icon(P2)
+ P2.blend_icon(P1)
+ P1.owner = user
+ P2.owner = user
+ portals += P1
+ portals += P2
+ src.add_fingerprint(user)
+
+ charge = max(charge - HANDTELE_PORTAL_COST,0)
+ if(!recharging)
+ recharging = 1
+ processing_objects.Add(src)
+
+/obj/item/weapon/hand_tele/proc/choose_destination(var/mob/user)
var/list/L = list( )
for(var/obj/machinery/computer/teleporter/R in machines)
for(var/obj/machinery/teleport/hub/com in locate(R.x + 2, R.y, R.z))
@@ -173,40 +232,20 @@ Frequency:
L["None (Dangerous)"] = pick(turfs)
turfs = null
-
- var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") in L
+ var/destination_name = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") in L
+ var/destination_id = L[destination_name]
if((user.get_active_hand() != src || user.stat || user.restrained()))
+ return 0
+ else
+ src.destination_name = destination_name
+ src.destination_id = destination_id
+ return 1
+
+/obj/item/weapon/hand_tele/AltClick(var/mob/usr)
+ if((usr.incapacitated() || !Adjacent(usr)))
return
- if(charge < HANDTELE_PORTAL_COST)
- user.show_message("\The [src] is recharging!")
- return
- var/T = L[t1]
-
- if((t1 == "None (Dangerous)") && prob(5))
- T = locate(rand(7, world.maxx - 7), rand(7, world.maxy -7), map.zTCommSat)
-
- var/turf/U = get_turf(src)
- U.visible_message("Locked In.")
- var/obj/effect/portal/P1 = new (U)
- var/obj/effect/portal/P2 = new (get_turf(T))
- P1.target = P2
- P2.target = P1
- P2.icon_state = "portal1"
- P1.creator = src
- P2.creator = src
- P1.blend_icon(P2)
- P2.blend_icon(P1)
- P1.owner = user
- P2.owner = user
- portals += P1
- portals += P2
- src.add_fingerprint(user)
-
- charge = max(charge - HANDTELE_PORTAL_COST,0)
- if(!recharging)
- recharging = 1
- processing_objects.Add(src)
+ choose_destination(usr)
/obj/item/weapon/hand_tele/process()
charge = min(HANDTELE_MAX_CHARGE,charge+1)
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index d6e87a494ac..5610bcfeee2 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -341,7 +341,7 @@
if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && !src.welding)
O.reagents.trans_to(src, max_fuel)
to_chat(user, "Welder refueled")
- playsound(get_turf(src), 'sound/effects/refill.ogg', 50, 1, -6)
+ playsound(src, 'sound/effects/refill.ogg', 50, 1, -6)
return
else if (istype(O, /obj/structure/reagent_dispensers/fueltank) && get_dist(src,O) <= 1 && src.welding)
message_admins("[key_name_admin(user)] triggered a fueltank explosion.")
@@ -404,6 +404,7 @@
/obj/item/weapon/weldingtool/proc/setWelding(var/temp_welding)
//If we're turning it on
if(temp_welding > 0)
+ src.welding = 1
if (remove_fuel(1))
to_chat(usr, "\The [src] switches on.")
src.force = 15
@@ -526,7 +527,7 @@
start_fueled = 0
/obj/item/weapon/weldingtool/largetank
- name = "Industrial Welding Tool"
+ name = "industrial welding tool"
desc = "The cutting edge between portability and tank size."
icon_state = "welder_large"
max_fuel = 40
@@ -537,7 +538,7 @@
start_fueled = 0
/obj/item/weapon/weldingtool/hugetank
- name = "Upgraded Welding Tool"
+ name = "upgraded welding tool"
desc = "A large tank for a large job."
icon_state = "welder_larger"
max_fuel = 80
@@ -566,7 +567,7 @@
/obj/item/weapon/weldingtool/experimental
- name = "Experimental Welding Tool"
+ name = "experimental welding tool"
max_fuel = 40
w_class = W_CLASS_MEDIUM
starting_materials = list(MAT_IRON = 70, MAT_GLASS = 120)
@@ -724,8 +725,8 @@
to_chat(user, "It contains [reagents.get_reagent_amount(SACID) + reagents.get_reagent_amount(FORMIC_ACID)]/[src.max_fuel] units of fuel!")
/obj/item/weapon/solder/attackby(obj/item/W as obj, mob/user as mob)
- if(istype(W,/obj/item/weapon/reagent_containers/glass/))
- var/obj/item/weapon/reagent_containers/glass/G = W
+ if(istype(W,/obj/item/weapon/reagent_containers/) && W.flags & OPENCONTAINER)
+ var/obj/item/weapon/reagent_containers/G = W
if(G.reagents.reagent_list.len>1)
user.simple_message("The mixture is rejected by the tool.",
"The tool isn't THAT thirsty.")
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index e1653b071e5..3b0eaceb336 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -129,7 +129,7 @@
hitsound = wielded ? "sound/weapons/blade1.ogg" : "sound/weapons/empty.ogg"
if(user)
user.update_inv_hands()
- playsound(get_turf(src), wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1)
+ playsound(src, wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1)
return
/obj/item/weapon/dualsaber/attack(target as mob, mob/living/user as mob)
@@ -183,7 +183,7 @@
hitsound = wielded ? "sound/weapons/blade1.ogg" : "sound/weapons/empty.ogg"
if(user)
user.update_inv_hands()
- playsound(get_turf(src), wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1)
+ playsound(src, wielded ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 50, 1)
return
/obj/item/weapon/dualsaber/bananabunch/attack(target as mob, mob/living/user as mob)
diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm
index b95b9b03b5f..bdca17f7ecf 100644
--- a/code/game/objects/items/weapons/weaponry.dm
+++ b/code/game/objects/items/weapons/weaponry.dm
@@ -34,7 +34,7 @@
return(BRUTELOSS)
/obj/item/weapon/sord/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
- playsound(get_turf(src), 'sound/weapons/bladeslice.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/bladeslice.ogg', 50, 1, -1)
user.adjustBruteLoss(0.5)
return ..()
@@ -460,6 +460,7 @@ obj/item/weapon/banhammer/admin
to_add.pixel_x -= 12 * PIXEL_MULTIPLIER
to_add.plane = FLOAT_PLANE
underlays += to_add.appearance
+
// if(!base_overlay)
// base_overlay = new
// base_overlay.appearance = appearance
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index bfcd67b7826..3de5401d823 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -26,12 +26,14 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
// Shit for mechanics. (MECH_*)
var/mech_flags=0
- var/holomap = FALSE // Whether we should be on the holomap.
- var/auto_holomap = FALSE // Whether we automatically soft-add ourselves to the holomap in New(), make sure this is false is something does it manually.
plane = OBJ_PLANE
var/defective = 0
-
+ var/quality = NORMAL //What level of quality this object is.
+ var/datum/material/material_type //What material this thing is made out of
+ var/event/on_use
+ var/sheet_type = /obj/item/stack/sheet/metal
+ var/sheet_amt = 1
var/can_take_pai = FALSE
var/obj/item/device/paicard/integratedpai = null
var/datum/delay_controller/pAImove_delayer = new(1, ARBITRARILY_LARGE_NUMBER)
@@ -41,13 +43,20 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
var/can_affix_to_dense_turf=0
var/has_been_invisible_sprayed = FALSE
+ var/impactsound
+
+// Whether this object can appear in holomaps
+/obj/proc/supports_holomap()
+ return FALSE
+
+/obj/proc/add_self_to_holomap()
+ var/turf/T = loc
+ if(istype(T) && ticker && ticker.current_state != GAME_STATE_PLAYING)
+ T.add_holomap(src)
/obj/New()
..()
- if (auto_holomap && isturf(loc))
- var/turf/T = loc
- T.soft_add_holomap(src)
- verbs -= /obj/verb/remove_pai
+ on_use = new(owner=src)
/obj/Destroy()
for(var/mob/user in _using)
@@ -59,8 +68,12 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
if(integratedpai)
qdel(integratedpai)
integratedpai = null
- verbs -= /obj/verb/remove_pai
+ if(on_use)
+ on_use.holder = null
+ qdel(on_use)
+ on_use = null
+ material_type = null //Don't qdel, they're held globally
..()
/obj/item/proc/is_used_on(obj/O, mob/user)
@@ -71,8 +84,7 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
return 0
P.forceMove(src)
integratedpai = P
- verbs += /obj/verb/remove_pai
-
+ verbs += /obj/proc/remove_pai
/obj/attackby(obj/item/weapon/W, mob/user)
if(can_take_pai && istype(W, /obj/item/device/paicard))
@@ -85,6 +97,10 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
install_pai(W)
state_controls_pai(W)
playsound(src, 'sound/misc/cartridge_in.ogg', 25)
+ if(W)
+ INVOKE_EVENT(W.on_use, list("user" = user, "target" = src))
+ if(W.material_type)
+ W.material_type.on_use(W, src, user)
/obj/proc/state_controls_pai(obj/item/device/paicard/P) //text the pAI receives when is inserted into something. EXAMPLE: to_chat(P.pai, "Welcome to your new body")
if(P.pai)
@@ -145,7 +161,7 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
if(istype(A,/obj/machinery)||(istype(A,/mob)&&user.secHUD))
A.attack_pai(user)
-/obj/verb/remove_pai()
+/obj/proc/remove_pai()
set name = "Remove pAI"
set category = "Object"
set src in range(1)
@@ -167,7 +183,7 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
/obj/proc/eject_integratedpai_if_present()
if(integratedpai)
integratedpai.forceMove(get_turf(src))
- verbs -= /obj/verb/remove_pai
+ verbs -= /obj/proc/remove_pai
var/obj/item/device/paicard/P = integratedpai
integratedpai = null
return P
@@ -191,6 +207,7 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
return 1
return
+
/obj/proc/cultify()
qdel(src)
@@ -215,6 +232,8 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
set waitfor = FALSE
processing_objects.Remove(src)
+//At some point, this proc should be changed to work like remove_air() below does.
+//However, this would likely cause problems, such as CO2 buildup in mechs and spacepods, so I'm not doing it right now.
/obj/assume_air(datum/gas_mixture/giver)
if(loc)
return loc.assume_air(giver)
@@ -222,10 +241,8 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
return null
/obj/remove_air(amount)
- if(loc)
- return loc.remove_air(amount)
- else
- return null
+ var/datum/gas_mixture/my_air = return_air()
+ return my_air?.remove(amount)
/obj/return_air()
if(loc)
@@ -243,9 +260,6 @@ var/global/list/reagents_to_log = list(FUEL, PLASMA, PACID, SACID, AMUTATIONTOXI
else
return null
-/atom/movable/proc/initialize()
- return
-
/obj/proc/updateUsrDialog()
if(in_use)
var/is_in_use = 0
@@ -619,3 +633,39 @@ a {
if(ismob(loc))
var/mob/M = loc
M.regenerate_icons()
+
+/obj/proc/gen_quality()
+ var/material_mod = material_type ? material_type.quality_mod : 1
+ var/turf/T = get_turf(src)
+ var/surrounding_mod = 1
+ for(var/dir in alldirs)
+ for(var/obj/I in get_step(T, dir))
+ if(I.quality > NORMAL || I.quality < NORMAL)
+ surrounding_mod *= I.quality/rand(1,3)
+ var/initial_quality = round((rand(1,3)*surrounding_mod)*material_mod)
+ quality = Clamp(initial_quality, AWFUL, LEGENDARY)
+
+/obj/proc/gen_description(mob/user)
+ var/material_mod = quality-GOOD>1 ? quality-GOOD : 0
+ var/additional_description
+ if(material_mod)
+ additional_description = "On \the [src] is a carving, it depicts:\n"
+ var/list/characters = list()
+ for(var/i = 1 to material_mod)
+ if(prob(50)) //We're gonna use an atom
+ var/atom/AM = pick(existing_typesof(/mob/living/simple_animal))
+ characters |= initial(AM.name)
+ else
+ var/strangething = pick("captain","clown","mime","\improper CMO","cargo technician","medical doctor","[user ? user : "stranger"]","octopus","changeling","\improper Nuclear Operative", "[pick("greyshirt", "greytide", "assistant")]", "xenomorph","catbeast","[user && user.mind && user.mind.heard_before.len ? pick(user.mind.heard_before) : "strange thing"]","Central Command","\improper Ian","[ticker.Bible_deity_name]","Nar-Sie","\improper Poly the Parrot","\improper Wizard","vox")
+ characters |= strangething
+ additional_description += "[i == material_mod ? " & a " : "[i > 1 ? ", a ": " A "]"][characters[i]]"
+ additional_description += ". They are in \the [pick("captains office","Space","mining outpost","vox outpost","a space station","[station_name()]","bar","kitchen","library","Science","void","Bluespace","Hell","Central Command")]"
+ if(material_mod > 2)
+ additional_description += ". They are [pick("[pick("fighting","robusting","attacking","beating up", "abusing")] [pick("each other", pick(characters))]","playing cards","firing lasers at [pick("something",pick(characters))]","crying","laughing","blank faced","screaming","cooking [pick("something", pick(characters))]", "eating [pick("something", pick(characters))]")]. "
+ if(characters.len > 1)
+ for(var/i in characters)
+ additional_description += "\The [i] is [pick("laughing","crying","screaming","naked","very naked","angry","jovial","manical","melting","fading away","making a plaintive gesture")]. "
+ additional_description += "The scene gives off a feeling of [pick("unease","empathy","fear","malice","dread","happiness","strangeness","insanity","drol")]. "
+ additional_description += "It is accented in hues of [pick("red","orange","yellow","green","blue","indigo","violet","white","black","cinnamon")]. "
+ if(additional_description)
+ desc = "[initial(desc)] \n [additional_description]"
diff --git a/code/game/objects/storage/coat.dm b/code/game/objects/storage/coat.dm
index 4dee0e25f68..38e384f7f1e 100644
--- a/code/game/objects/storage/coat.dm
+++ b/code/game/objects/storage/coat.dm
@@ -44,7 +44,7 @@
var/mob/M = usr
if(istype(over_object, /obj/abstract/screen/inventory)) //was clickdragged to an inventory slot, we want to be able to take our coat off
if(!M.incapacitated() && is_holder_of(M, src))
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
var/obj/abstract/screen/inventory/OI = over_object
if(OI.hand_index && M.put_in_hand_check(src, OI.hand_index))
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 29258e8a1d5..298646c4584 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -28,7 +28,7 @@ obj/structure/ex_act(severity)
if(O.onBuckledUserKick(H, src))
return //don't return 1! we will do the normal "touch" action if so!
- playsound(get_turf(src), 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it
+ playsound(src, 'sound/effects/grillehit.ogg', 50, 1) //Zth: I couldn't find a proper sound, please replace it
H.visible_message("[H] kicks \the [src].", "You kick \the [src].")
if(prob(70))
@@ -48,6 +48,7 @@ obj/structure/ex_act(severity)
if(!Move(get_step(loc, kick_dir)))
break
sleep(3)
-
+ if(material_type)
+ material_type.on_use(H,src,null)
/obj/structure/animationBolt(var/mob/firer)
new /mob/living/simple_animal/hostile/mimic/copy(loc, src, firer, duration=SPELL_ANIMATION_TTL)
diff --git a/code/game/objects/structures/barricade.dm b/code/game/objects/structures/barricade.dm
index 03c3408ead2..6fc53cc77d2 100644
--- a/code/game/objects/structures/barricade.dm
+++ b/code/game/objects/structures/barricade.dm
@@ -14,6 +14,7 @@
anchored = 1
opacity = 1 //Wood isn't transparent, the last time I checked
health = 60 //Fairly strong
+ layer = ABOVE_DOOR_LAYER
var/busy = 0 //Oh god fucking do_after's
var/materialtype = /obj/item/stack/sheet/wood
@@ -48,7 +49,7 @@
user.delayNextAttack(10)
health -= 2
healthcheck()
- //playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1)
+ //playsound(src, 'sound/effects/glassknock.ogg', 100, 1)
user.visible_message("[user] bangs against \the [src]!", \
"You bang against \the [src]!", \
"You hear banging.")
@@ -56,7 +57,7 @@
//Knock against it
else
user.delayNextAttack(10)
- //playsound(get_turf(src), 'sound/effects/glassknock.ogg', 50, 1)
+ //playsound(src, 'sound/effects/glassknock.ogg', 50, 1)
user.visible_message("[user] knocks on \the [src].", \
"You knock on \the [src].", \
"You hear knocking.")
diff --git a/code/game/objects/structures/cage.dm b/code/game/objects/structures/cage.dm
index 637af90ff08..cd29b443d32 100644
--- a/code/game/objects/structures/cage.dm
+++ b/code/game/objects/structures/cage.dm
@@ -91,7 +91,7 @@
to_chat(user, "You start securing \the [src] to \the [loc].")
spawn()
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
if(do_after(user, src, 50))
anchored = !anchored
to_chat(user, "[anchored ? "You successfully secure \the [src] to \the [loc]." : "You successfully unsecure \the [src] from \the [loc]."]")
@@ -217,7 +217,7 @@
door_state = C_OPENED
setDensity(FALSE)
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
update_icon()
/obj/structure/cage/proc/add_mob(mob/victim)
diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm
index 57dcdfc96fb..fad2699c63c 100644
--- a/code/game/objects/structures/catwalk.dm
+++ b/code/game/objects/structures/catwalk.dm
@@ -48,7 +48,7 @@
return 0
if(isscrewdriver(C))
to_chat(user, "You begin undoing the screws holding the catwalk together.")
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 80, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 80, 1)
if(do_after(user, src, 30) && src)
to_chat(user, "You finish taking taking the catwalk apart.")
new /obj/item/stack/rods(src.loc, 2)
diff --git a/code/game/objects/structures/clock.dm b/code/game/objects/structures/clock.dm
new file mode 100644
index 00000000000..1964f25ec26
--- /dev/null
+++ b/code/game/objects/structures/clock.dm
@@ -0,0 +1,31 @@
+/obj/structure/clock
+ name = "grandfather clock"
+ desc = "Hickory dickory dock, the mouse ran up the clock, the clock struck one, the mouse was gone, hickory dickory dock."
+ icon = 'icons/obj/objects.dmi'
+ icon_state = "clock"
+ density = 1
+ anchored = 1
+
+/obj/structure/clock/update_icon()
+ if(anchored)
+ icon_state = "clock"
+ else
+ icon_state = "clock-broken"
+
+/obj/structure/clock/examine(mob/user)
+ ..()
+ if(anchored)
+ to_chat(user, "Station Time: [worldtime2text()]")
+
+/obj/structure/clock/attackby(obj/item/weapon/W, mob/user)
+ if(iswrench(W))
+ if(do_after(user, src, 3 SECONDS))
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ anchored = !anchored
+ update_icon()
+ else
+ return ..()
+
+/obj/structure/clock/unanchored
+ anchored = 0
+ icon_state = "clock-broken"
\ No newline at end of file
diff --git a/code/game/objects/structures/coatrack.dm b/code/game/objects/structures/coatrack.dm
index a78009c3c25..375ebbd4f50 100644
--- a/code/game/objects/structures/coatrack.dm
+++ b/code/game/objects/structures/coatrack.dm
@@ -32,7 +32,7 @@
/obj/structure/coatrack/attack_hand(mob/user)
if(suit)
to_chat(user, "You pick up \the [suit] from \the [src]")
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
suit.forceMove(get_turf(src))
if(!user.get_active_hand())
user.put_in_hands(suit)
@@ -42,7 +42,7 @@
if(hat)
to_chat(user, "You pick up \the [hat] from \the [src]")
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
hat.forceMove(get_turf(src))
if(!user.get_active_hand())
user.put_in_hands(hat)
@@ -54,17 +54,17 @@
if (istype(C, /obj/item/clothing/suit) && !suit && is_type_in_list(C, allowed_suits))
if(user.drop_item(C, src))
to_chat(user, "You place your [C] on \the [src]")
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
suit = C
update_icon()
else if (istype(C, /obj/item/clothing/head) && !hat && is_type_in_list(C, allowed_hats))
if(user.drop_item(C, src))
to_chat(user, "You place your [C] on \the [src]")
- playsound(get_turf(src), "rustle", 50, 1, -5)
+ playsound(src, "rustle", 50, 1, -5)
hat = C
update_icon()
else if(iswrench(C))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
getFromPool(/obj/item/stack/sheet/wood, get_turf(src), 2)
qdel(src)//the hat and suit on the coat rack are automatically dropped by Destroy()
else
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 1d4df1dd315..fedfb38af5a 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -25,6 +25,8 @@
w_type = RECYK_METAL
ignoreinvert = 1
+/obj/structure/closet/proc/canweld()
+ return 1
/obj/structure/closet/initialize()
..()
@@ -221,7 +223,7 @@
/obj/structure/closet/beam_connect(var/obj/effect/beam/B)
if(!processing_objects.Find(src))
processing_objects.Add(src)
- testing("Connected [src] with [B]!")
+// testing("Connected [src] with [B]!")
return ..()
/obj/structure/closet/beam_disconnect(var/obj/effect/beam/B)
@@ -281,7 +283,7 @@
if(istype(W,/obj/item/tk_grab))
return 0
- if(istype(W, /obj/item/weapon/weldingtool))
+ if(istype(W, /obj/item/weapon/weldingtool) && canweld())
var/obj/item/weapon/weldingtool/WT = W
if(!WT.remove_fuel(0,user))
to_chat(user, "You need more welding fuel to complete this task.")
@@ -296,7 +298,7 @@
else if(istype(W, /obj/item/stack/package_wrap))
return
- else if(istype(W, /obj/item/weapon/weldingtool))
+ else if(istype(W, /obj/item/weapon/weldingtool) && canweld())
var/obj/item/weapon/weldingtool/WT = W
if(!WT.remove_fuel(0,user))
to_chat(user, "You need more welding fuel to complete this task.")
diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm
index a674f043e44..23f9d81dce0 100644
--- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm
+++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm
@@ -134,7 +134,7 @@
else
if(iswrench(O) && src.localopened && !src.fireaxe)
to_chat(user, "You disassemble \the [src].")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
new /obj/item/stack/sheet/plasteel (src.loc,2)
qdel(src)
if(smashed)
diff --git a/code/game/objects/structures/crates_lockers/closets/gimmick.dm b/code/game/objects/structures/crates_lockers/closets/gimmick.dm
index ae51bdcca63..f44b32df6e9 100644
--- a/code/game/objects/structures/crates_lockers/closets/gimmick.dm
+++ b/code/game/objects/structures/crates_lockers/closets/gimmick.dm
@@ -4,12 +4,71 @@
icon_state = "cabinet_closed"
icon_closed = "cabinet_closed"
icon_opened = "cabinet_open"
+ autoignition_temperature = AUTOIGNITION_WOOD
+ fire_fuel = 3
-/obj/structure/closet/cabinet/update_icon()
- if(!opened)
- icon_state = icon_closed
- else
- icon_state = icon_opened
+/obj/structure/closet/cabinet/canweld()
+ return 0
+
+/obj/structure/closet/cabinet/snow
+ name = "snow gear cabinet"
+ desc = "A cabinet filled with snow gear for extra-station activity."
+ var/obj/structure/hanger_rail/hanger_rail
+
+/obj/structure/closet/cabinet/snow/New()
+ ..()
+ hanger_rail = new (src)
+
+/obj/structure/closet/cabinet/snow/close()
+ . = ..()
+ if(.)
+ unlock_atom(hanger_rail)
+ hanger_rail.forceMove(src)
+
+/obj/structure/closet/cabinet/snow/open()
+ . = ..()
+ if(.)
+ hanger_rail.forceMove(get_turf(src))
+ lock_atom(hanger_rail)
+
+/obj/structure/closet/cabinet/snow/Destroy()
+ ..()
+ qdel(hanger_rail)
+ hanger_rail = null
+
+/obj/structure/hanger_rail
+ icon = 'icons/obj/closet.dmi'
+ icon_state = "hanger_rail"
+ name = "hanger rail"
+ desc = "This rail is for holding NT standard-issue winter coats."
+ var/coats = 4
+ density = 0
+ anchored = 1
+ flags = FPRINT
+ layer = ABOVE_OBJ_LAYER
+
+/obj/structure/hanger_rail/attack_hand(var/mob/user,params,proximity)
+ ..()
+ if(!proximity)
+ return
+ if(coats)
+ to_chat(user,"You remove a pair of boots and a coat from the hanger.")
+ add_fingerprint(user)
+ var/winterboots = new /obj/item/clothing/shoes/winterboots(get_turf(src))
+ user.put_in_inactive_hand(winterboots)
+ var/wintercoat = new /obj/item/clothing/suit/wintercoat(get_turf(src))
+ user.put_in_active_hand(wintercoat)
+ coats--
+ update_icon()
+
+/obj/structure/hanger_rail/update_icon()
+ overlays.Cut()
+ for(var/i = 1 to coats)
+ overlays += image(icon,"coat[i]")
+
+/obj/structure/hanger_rail/New()
+ ..()
+ update_icon()
/obj/structure/closet/cabinet/medivault
name = "old cabinet"
@@ -155,4 +214,4 @@
new /obj/item/weapon/storage/box/flashbangs(src)
new /obj/item/clothing/head/helmet/thunderdome(src)
new /obj/item/clothing/head/helmet/thunderdome(src)
- new /obj/item/clothing/head/helmet/thunderdome(src)
+ new /obj/item/clothing/head/helmet/thunderdome(src)
\ No newline at end of file
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
index 39687b4c9ae..2c560211d3b 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm
@@ -110,7 +110,7 @@
src.icon_state = src.icon_opened
src.opened = 1
setDensity(FALSE)
- playsound(get_turf(src), 'sound/machines/click.ogg', 15, 1, -3)
+ playsound(src, 'sound/machines/click.ogg', 15, 1, -3)
else
if(!can_open())
to_chat(user, "It won't budge!")
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index aa1f6387ada..028f494e54b 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -99,41 +99,44 @@
icon_broken = "hossecurebroken"
icon_off = "hossecureoff"
- New()
- ..()
- sleep(2)
- if(prob(50))
- new /obj/item/weapon/storage/backpack/security(src)
- else
- new /obj/item/weapon/storage/backpack/satchel_sec(src)
- new /obj/item/clothing/head/helmet/tactical/HoS(src)
- new /obj/item/device/flashlight/tactical(src)
- new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src)
- new /obj/item/clothing/suit/armor/vest(src)
- new /obj/item/clothing/under/rank/head_of_security/jensen(src)
- if(prob(50))
- new /obj/item/clothing/suit/armor/hos/jensen(src)
- else
- new /obj/item/clothing/suit/armor/hos/sundowner(src)
- new /obj/item/clothing/head/helmet/tactical/HoS/dermal(src)
- new /obj/item/weapon/cartridge/hos(src)
- new /obj/item/device/detective_scanner(src)
- new /obj/item/device/radio/headset/heads/hos(src)
- new /obj/item/clothing/glasses/sunglasses/sechud(src)
- new /obj/item/weapon/shield/riot(src)
- new /obj/item/weapon/storage/lockbox/loyalty(src)
- new /obj/item/weapon/storage/box/flashbangs(src)
- new /obj/item/weapon/storage/belt/security(src)
- new /obj/item/device/flash(src)
- new /obj/item/weapon/melee/baton/loaded(src)
- new /obj/item/weapon/storage/lockbox/lawgiver(src)
- new /obj/item/ammo_storage/magazine/lawgiver(src)
- new /obj/item/clothing/accessory/holster/handgun/waist(src)
- new /obj/item/weapon/melee/telebaton(src)
- new /obj/item/device/gps/secure(src)
- return
-
-
+/obj/structure/closet/secure_closet/hos/New()
+ ..()
+ sleep(2)
+ if(prob(50))
+ new /obj/item/weapon/storage/backpack/security(src)
+ else
+ new /obj/item/weapon/storage/backpack/satchel_sec(src)
+ new /obj/item/clothing/head/helmet/tactical/HoS(src)
+ new /obj/item/device/flashlight/tactical(src)
+ new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src)
+ new /obj/item/clothing/suit/armor/vest(src)
+ new /obj/item/clothing/under/rank/head_of_security/jensen(src)
+ if(prob(50))
+ new /obj/item/clothing/suit/armor/hos/jensen(src)
+ else
+ new /obj/item/clothing/suit/armor/hos/sundowner(src)
+ new /obj/item/clothing/head/helmet/tactical/HoS/dermal(src)
+ new /obj/item/weapon/cartridge/hos(src)
+ new /obj/item/device/detective_scanner(src)
+ new /obj/item/device/radio/headset/heads/hos(src)
+ new /obj/item/clothing/glasses/sunglasses/sechud(src)
+ new /obj/item/weapon/shield/riot(src)
+ new /obj/item/weapon/storage/lockbox/loyalty(src)
+ new /obj/item/weapon/storage/box/flashbangs(src)
+ new /obj/item/weapon/storage/belt/security(src)
+ new /obj/item/device/flash(src)
+ new /obj/item/weapon/melee/baton/loaded(src)
+ new /obj/item/weapon/storage/lockbox/lawgiver(src)
+ new /obj/item/ammo_storage/magazine/lawgiver(src)
+ new /obj/item/clothing/accessory/holster/handgun/waist(src)
+ new /obj/item/weapon/melee/telebaton(src)
+ new /obj/item/device/gps/secure(src)
+ new /obj/item/clothing/suit/armor/hos(src)
+ new /obj/item/taperoll/police(src)
+ new /obj/item/device/hailer(src)
+ new /obj/item/weapon/reagent_containers/spray/pepper(src)
+ new /obj/item/weapon/grenade/flashbang(src)
+ new /obj/item/weapon/gun/energy/taser(src)
/obj/structure/closet/secure_closet/warden
name = "Warden's Locker"
@@ -146,32 +149,35 @@
icon_off = "wardensecureoff"
- New()
- ..()
- sleep(2)
- if(prob(50))
- new /obj/item/weapon/storage/backpack/security(src)
- else
- new /obj/item/weapon/storage/backpack/satchel_sec(src)
- new /obj/item/clothing/suit/armor/vest/security(src)
- new /obj/item/clothing/under/rank/warden(src)
- new /obj/item/clothing/suit/armor/vest/warden(src)
- new /obj/item/clothing/head/helmet/tactical/warden(src)
- new /obj/item/device/flashlight/tactical(src)
-// new /obj/item/weapon/cartridge/security(src)
- new /obj/item/device/radio/headset/headset_sec(src)
- new /obj/item/clothing/glasses/sunglasses/sechud(src)
- new /obj/item/weapon/storage/box/flashbangs(src)
- new /obj/item/weapon/storage/belt/security(src)
- new /obj/item/weapon/reagent_containers/spray/pepper(src)
- new /obj/item/weapon/melee/baton/loaded(src)
- new /obj/item/weapon/gun/energy/taser(src)
- new /obj/item/weapon/storage/box/bolas(src)
- new /obj/item/weapon/batteringram(src)
- new /obj/item/device/gps/secure(src)
- return
-
-
+/obj/structure/closet/secure_closet/warden/New()
+ ..()
+ sleep(2)
+ if(prob(50))
+ new /obj/item/weapon/storage/backpack/security(src)
+ else
+ new /obj/item/weapon/storage/backpack/satchel_sec(src)
+ new /obj/item/clothing/suit/armor/vest/security(src)
+ new /obj/item/clothing/under/rank/warden(src)
+ new /obj/item/clothing/suit/armor/vest/warden(src)
+ new /obj/item/clothing/head/helmet/tactical/warden(src)
+ new /obj/item/device/flashlight/tactical(src)
+// new /obj/item/weapon/cartridge/security(src)
+ new /obj/item/device/radio/headset/headset_sec(src)
+ new /obj/item/clothing/glasses/sunglasses/sechud(src)
+ new /obj/item/weapon/storage/box/flashbangs(src)
+ new /obj/item/weapon/storage/belt/security(src)
+ new /obj/item/weapon/reagent_containers/spray/pepper(src)
+ new /obj/item/weapon/melee/baton/loaded(src)
+ new /obj/item/weapon/gun/energy/taser(src)
+ new /obj/item/weapon/storage/box/bolas(src)
+ new /obj/item/weapon/batteringram(src)
+ new /obj/item/device/gps/secure(src)
+ new /obj/item/taperoll/police(src)
+ new /obj/item/device/hailer(src)
+ new /obj/item/weapon/reagent_containers/spray/pepper(src)
+ new /obj/item/weapon/grenade/flashbang(src)
+ new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src)
+ new /obj/item/weapon/gun/energy/taser(src)
/obj/structure/closet/secure_closet/security
name = "Security Officer's Locker"
@@ -183,34 +189,32 @@
icon_broken = "secbroken"
icon_off = "secoff"
- New()
- ..()
- sleep(2)
- if(prob(50))
- new /obj/item/weapon/storage/backpack/security(src)
- else
- new /obj/item/weapon/storage/backpack/satchel_sec(src)
- new /obj/item/clothing/suit/armor/vest/security(src)
- new /obj/item/clothing/head/helmet/tactical/sec/preattached(src)
- new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src)
-// new /obj/item/weapon/cartridge/security(src)
- new /obj/item/device/radio/headset/headset_sec(src)
- new /obj/item/weapon/storage/belt/security(src)
- new /obj/item/device/flash(src)
- new /obj/item/weapon/reagent_containers/spray/pepper(src)
- new /obj/item/weapon/grenade/flashbang(src)
- new /obj/item/weapon/melee/baton/loaded(src)
- new /obj/item/weapon/gun/energy/taser(src)
- if(prob(50))
- new /obj/item/clothing/glasses/sunglasses/sechud/prescription(src)
- else
- new /obj/item/clothing/glasses/sunglasses/sechud(src)
- new /obj/item/taperoll/police(src)
- new /obj/item/device/hailer(src) //wonder if vg would spam this
- new /obj/item/clothing/gloves/black(src)
- new /obj/item/device/gps/secure(src)
- return
-
+/obj/structure/closet/secure_closet/security/New()
+ ..()
+ sleep(2)
+ if(prob(50))
+ new /obj/item/weapon/storage/backpack/security(src)
+ else
+ new /obj/item/weapon/storage/backpack/satchel_sec(src)
+ new /obj/item/clothing/suit/armor/vest/security(src)
+ new /obj/item/clothing/head/helmet/tactical/sec/preattached(src)
+ new /obj/item/clothing/accessory/holster/knife/boot/preloaded/tactical(src)
+// new /obj/item/weapon/cartridge/security(src)
+ new /obj/item/device/radio/headset/headset_sec(src)
+ new /obj/item/weapon/storage/belt/security(src)
+ new /obj/item/device/flash(src)
+ new /obj/item/weapon/reagent_containers/spray/pepper(src)
+ new /obj/item/weapon/grenade/flashbang(src)
+ new /obj/item/weapon/melee/baton/loaded(src)
+ new /obj/item/weapon/gun/energy/taser(src)
+ if(prob(50))
+ new /obj/item/clothing/glasses/sunglasses/sechud/prescription(src)
+ else
+ new /obj/item/clothing/glasses/sunglasses/sechud(src)
+ new /obj/item/taperoll/police(src)
+ new /obj/item/device/hailer(src) //wonder if vg would spam this
+ new /obj/item/clothing/gloves/black(src)
+ new /obj/item/device/gps/secure(src)
/obj/structure/closet/secure_closet/security/cargo
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index 89d42f9f094..f94701dc0b0 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -122,12 +122,7 @@
if(!gas)
return null
var/datum/gas_mixture/newgas = new/datum/gas_mixture()
- newgas.oxygen = gas.oxygen
- newgas.carbon_dioxide = gas.carbon_dioxide
- newgas.nitrogen = gas.nitrogen
- newgas.toxins = gas.toxins
- newgas.volume = gas.volume
- newgas.temperature = gas.temperature
+ newgas.copy_from(gas)
if(newgas.temperature <= target_temp)
return
@@ -135,6 +130,7 @@
newgas.temperature -= cooling_power
else
newgas.temperature = target_temp
+ newgas.update_values()
return newgas
/obj/structure/closet/crate/freezer/surgery
@@ -271,6 +267,22 @@
locked = 1
health = 1000
+/obj/structure/closet/crate/secure/anti_tamper
+ name = "Extra-secure crate"
+
+/obj/structure/closet/crate/secure/anti_tamper/Destroy()
+ if(locked)
+ visible_message("Something bursts open from within \the [src]!")
+ var/datum/effect/effect/system/smoke_spread/chem/S = new //Surprise!
+ S.attach(get_turf(src))
+ S.chemholder.reagents.add_reagent(CAPSAICIN, 40)
+ S.chemholder.reagents.add_reagent(CONDENSEDCAPSAICIN, 16)
+ S.chemholder.reagents.add_reagent(SACID, 12)
+ S.set_up(src, 10, 0, loc)
+ spawn(0)
+ S.start()
+ ..()
+
/obj/structure/closet/crate/large
name = "large crate"
desc = "A hefty metal crate."
@@ -399,7 +411,7 @@
return 0
if(!src.can_open())
return 0
- playsound(get_turf(src), sound_effect_open, 15, 1, -3)
+ playsound(src, sound_effect_open, 15, 1, -3)
dump_contents()
@@ -413,7 +425,7 @@
return 0
if(!src.can_close())
return 0
- playsound(get_turf(src), sound_effect_close, 15, 1, -3)
+ playsound(src, sound_effect_close, 15, 1, -3)
take_contents()
@@ -488,7 +500,7 @@
overlays += emag
overlays += sparks
spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface*
- playsound(get_turf(src), "sparks", 60, 1)
+ playsound(src, "sparks", 60, 1)
src.locked = 0
src.broken = 1
to_chat(user, "You unlock \the [src].")
@@ -541,7 +553,7 @@
overlays += emag
overlays += sparks
spawn(6) overlays -= sparks //Tried lots of stuff but nothing works right. so i have to use this *sadface*
- playsound(get_turf(src), 'sound/effects/sparks4.ogg', 75, 1)
+ playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
src.locked = 0
if(!opened && prob(20/severity))
if(!locked)
diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm
index fe36148a5d0..e0f5a22a259 100644
--- a/code/game/objects/structures/crates_lockers/largecrate.dm
+++ b/code/game/objects/structures/crates_lockers/largecrate.dm
@@ -30,10 +30,8 @@
icon_state = "lisacrate"
/obj/structure/largecrate/porcelain
- ..()
/obj/structure/largecrate/showers
- ..()
/obj/structure/largecrate/lisa/attackby(obj/item/weapon/W as obj, mob/user as mob) //ugly but oh well
if(iscrowbar(W))
diff --git a/code/game/objects/structures/curtains.dm b/code/game/objects/structures/curtains.dm
index 089218a4b0e..af083c23bb0 100644
--- a/code/game/objects/structures/curtains.dm
+++ b/code/game/objects/structures/curtains.dm
@@ -35,7 +35,7 @@
..()
/obj/structure/curtain/attack_hand(mob/user)
- playsound(get_turf(loc), "rustle", 15, 1, -5)
+ playsound(loc, "rustle", 15, 1, -5)
toggle()
..()
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index fb49dfab640..2303f90c125 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -1,65 +1,4 @@
-/obj/structure/displaycase_frame
- name = "display case frame"
- icon = 'icons/obj/stock_parts.dmi'
- icon_state="box_glass"
- var/obj/item/weapon/circuitboard/airlock/circuit=null
- var/state=0
-
-/obj/structure/displaycase_frame/Destroy()
- ..()
- if(circuit)
- qdel(circuit)
- circuit = null
-
-/obj/structure/displaycase_frame/attackby(obj/item/weapon/W as obj, mob/user as mob)
- var/pstate=state
- var/turf/T=get_turf(src)
- switch(state)
- if(0)
- if(istype(W, /obj/item/weapon/circuitboard/airlock) && W:icon_state != "door_electronics_smoked")
- if(user.drop_item(W, src))
- circuit=W
- circuit.installed = 1
- state++
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
- if(iscrowbar(W))
- var/obj/machinery/constructable_frame/machine_frame/MF = new /obj/machinery/constructable_frame/machine_frame(T)
- MF.state = 1
- MF.set_build_state(1)
- new /obj/item/stack/sheet/glass/glass(T)
- qdel(src)
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
- return
-
- if(1)
- if(isscrewdriver(W))
- var/obj/structure/displaycase/C=new(T)
- if(circuit.one_access)
- C.req_access = null
- C.req_one_access = circuit.conf_access
- else
- C.req_access = circuit.conf_access
- C.req_one_access = null
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
- qdel(src)
- return
- if(iscrowbar(W))
- circuit.forceMove(T)
- circuit.installed = 0
- circuit=null
- state--
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
- if(pstate!=state)
- pstate=state
- update_icon()
-
-/obj/structure/displaycase_frame/update_icon()
- switch(state)
- if(1)
- icon_state="box_glass_circuit"
- else
- icon_state="box_glass"
-
+//Construction handled in code/game/machinery/constructable_frame.dm
/obj/structure/displaycase
name = "display case"
@@ -100,7 +39,10 @@
/obj/structure/displaycase/lamarr/New()
..()
- occupant=new /obj/item/clothing/mask/facehugger/lamarr(src)
+ if(Holiday == APRIL_FOOLS_DAY && prob(50))
+ occupant=new /obj/item/clothing/shoes/magboots/funk(src)
+ else
+ occupant=new /obj/item/clothing/mask/facehugger/lamarr(src)
locked=1
req_access=list(access_rd)
update_icon()
@@ -158,10 +100,10 @@
setDensity(FALSE)
src.destroyed = 1
getFromPool(/obj/item/weapon/shard, loc)
- playsound(get_turf(src), "shatter", 70, 1)
+ playsound(src, "shatter", 70, 1)
update_icon()
else
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
return
/obj/structure/displaycase/update_icon()
@@ -201,30 +143,35 @@
user.visible_message("[user.name] pries \the [src] apart.", \
"You pry \the [src] apart.", \
"You hear something pop.")
- var/turf/T=get_turf(src)
- playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
dump()
- var/obj/item/weapon/circuitboard/airlock/C=circuit
+
+ var/obj/item/weapon/circuitboard/airlock/C = circuit
if(!C)
- C=new (src)
+ C = new (src)
C.installed = 1
C.one_access=!(req_access && req_access.len>0)
if(!C.one_access)
C.conf_access=req_access
else
C.conf_access=req_one_access
+
if(!destroyed)
- var/obj/structure/displaycase_frame/F=new(T)
- F.state=1
- F.circuit=C
- F.circuit.forceMove(F)
- F.update_icon()
+ var /obj/machinery/constructable_frame/machine_frame/new_machine_frame = new(get_turf(src))
+ new_machine_frame.build_path = 1
+ new_machine_frame.build_state = 2
+ new_machine_frame.circuit = C
+ C.forceMove(new_machine_frame)
+ circuit = null
+ C = null
+ new_machine_frame.icon_state="box_glass_circuit"
else
- C.forceMove(T)
+ C.forceMove(get_turf(src))
C.installed = 0
- circuit=null
- new /obj/machinery/constructable_frame/machine_frame(T)
+ new /obj/machinery/constructable_frame/machine_frame(get_turf(src))
qdel(src)
+ return
+
else if(user.a_intent == I_HURT)
user.delayNextAttack(8)
src.health -= W.force
@@ -286,10 +233,10 @@
/obj/structure/displaycase/broken
- name = "display case"
+ name = "broken display case"
icon = 'icons/obj/stationobjs.dmi'
icon_state = "glassbox2b"
- desc = "A display case for prized possessions."
+ desc = "A display case for prized possessions. It seems to be broken."
density = 0
health = 0
destroyed = 1
diff --git a/code/game/objects/structures/docking_port.dm b/code/game/objects/structures/docking_port.dm
index 197f979c6a6..93b0edeb96c 100644
--- a/code/game/objects/structures/docking_port.dm
+++ b/code/game/objects/structures/docking_port.dm
@@ -1,3 +1,8 @@
+/*CONTAINS
+- Docking Port
+- Shuttle and Destination subtypes
+- Docking Lights */
+
var/global/list/all_docking_ports = list()
/obj/docking_port
@@ -85,11 +90,19 @@ var/global/list/all_docking_ports = list()
if(!A.shuttle_warning_lights)
A.shuttle_warning_lights = image('icons/obj/doors/Doorint.dmi', src, "warning_lights")
A.overlays += A.shuttle_warning_lights
+ for(var/obj/machinery/docklight/D in dockinglights)
+ if(D.id_tag == areaname)
+ D.triggered = 1
+ D.update_icon()
/obj/docking_port/destination/proc/stop_warning_lights()
for(var/obj/machinery/door/airlock/A in range(1,src))
if(A.shuttle_warning_lights)
A.overlays -= A.shuttle_warning_lights
+ for(var/obj/machinery/docklight/D in dockinglights)
+ if(D.id_tag == areaname)
+ D.triggered = 0
+ D.update_icon()
//SHUTTLE PORTS
@@ -232,3 +245,39 @@ var/global/list/all_docking_ports = list()
if(istype(D))
return D
return 0
+
+var/global/list/dockinglights = list()
+
+/obj/machinery/docklight
+ name = "docking light"
+ desc = "A light designed to warn of dangerous docking conditions. Exercise caution while flashing."
+ icon = 'icons/obj/stationobjs.dmi'
+ icon_state = "docklight"
+ light_color = LIGHT_COLOR_ORANGE
+ machine_flags = MULTITOOL_MENU
+ var/triggered = 0
+ var/id_tag = "" //Mappers: This should match the areaname of the target destination port.
+ //Examples: "main research department", "research outpost", "deep space", "station auxillary docking", "north of the station", etc.
+
+/obj/machinery/docklight/New()
+ ..()
+ dockinglights += src
+
+/obj/machinery/docklight/Destroy()
+ dockinglights -= src
+ ..()
+
+/obj/machinery/docklight/update_icon()
+ if(triggered)
+ icon_state = "docklight_triggered"
+ set_light(2)
+ else
+ icon_state = "docklight"
+ set_light(0)
+
+/obj/machinery/docklight/multitool_menu(var/mob/user, var/obj/item/device/multitool/P)
+ return {"
+ Main
+
+
[format_tag("ID Tag","id_tag")]
+
"}
diff --git a/code/game/objects/structures/door_assembly.dm b/code/game/objects/structures/door_assembly.dm
index 0a889f3e5d5..919f7e1291c 100644
--- a/code/game/objects/structures/door_assembly.dm
+++ b/code/game/objects/structures/door_assembly.dm
@@ -162,7 +162,7 @@
if (WT.remove_fuel(0, user))
busy = TRUE
- playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder2.ogg', 50, 1)
if (istext(glass))
user.visible_message("[user] welds the [glass] plating off the airlock assembly.", "You start to weld the [glass] plating off the airlock assembly.")
@@ -210,7 +210,7 @@
return
else if(iswrench(W) && state == 0)
busy = 1
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
if(anchored)
user.visible_message("[user] unsecures the airlock assembly from the floor.", "You start to unsecure the airlock assembly from the floor.")
else
@@ -237,7 +237,7 @@
else if(iswirecutter(W) && state == 1 )
busy = 1
- playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 100, 1)
user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly.")
if(do_after(user, src, 40))
@@ -250,7 +250,7 @@
else if(istype(W, /obj/item/weapon/circuitboard/airlock) && state == 1 && W:icon_state != "door_electronics_smoked")
busy = 1
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly.")
user.drop_item(W, src, force_drop = 1)
@@ -269,7 +269,7 @@
else if(iscrowbar(W) && state == 2 )
busy = 1
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 1)
user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to install electronics into the airlock assembly.")
if(do_after(user, src, 40))
@@ -294,7 +294,7 @@
if (S.amount>=1)
busy = 1
if(istype(S, /obj/item/stack/sheet/glass/rglass))
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 1)
user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.")
if(do_after(user, src, 40))
to_chat(user, "You installed reinforced glass windows into the airlock assembly!")
@@ -303,7 +303,7 @@
else if(istype(S, /obj/item/stack/sheet/mineral) && S.sheettype)
var/M = S.sheettype
if(S.amount>=2)
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 1)
user.visible_message("[user] adds [S.name] to the airlock assembly.", "You start to install [S.name] into the airlock assembly.")
if(do_after(user, src, 40))
to_chat(user, "You installed [M] plating into the airlock assembly!")
@@ -313,7 +313,7 @@
else if(isscrewdriver(W) && state == 2 )
busy = 1
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
to_chat(user, "Now finishing the airlock.")
if(do_after(user, src, 40))
diff --git a/code/game/objects/structures/fence.dm b/code/game/objects/structures/fence.dm
index 31874ef7f7a..644b70a85ac 100644
--- a/code/game/objects/structures/fence.dm
+++ b/code/game/objects/structures/fence.dm
@@ -67,7 +67,7 @@
hole_size = LARGE_HOLE
/obj/structure/fence/attackby(obj/item/W, mob/user)
- if(iswirecutter(W) && !shock(user, 100))
+ if(iswirecutter(W) && !shock(user, 100, W.siemens_coefficient))
if(!cuttable)
to_chat(user, "This section of the fence can't be cut.")
return
@@ -114,7 +114,7 @@
strength = H.get_strength()
user.visible_message("\The [user] hits \the [src]!")
- playsound(get_turf(src), 'sound/effects/fence_smash.ogg', 30 * strength, 1) //Sound is louder the stronger you are
+ playsound(src, 'sound/effects/fence_smash.ogg', 30 * strength, 1) //Sound is louder the stronger you are
shock(user, 100)
return 1
@@ -167,7 +167,7 @@
return !density
//Mostly copied from grille.dm
-/obj/structure/fence/proc/shock(mob/user, prb = 100)
+/obj/structure/fence/proc/shock(mob/user, prb = 100, siemens_coefficient = 1)
if(!prob(prb)) //If the probability roll failed, don't go further
return 0
if(!in_range(src, user)) //To prevent TK and mech users from getting shocked
@@ -176,7 +176,7 @@
var/turf/T = get_turf(src)
var/obj/structure/cable/C = T.get_cable_node()
if(C)
- if(electrocute_mob(user, C, src))
+ if(electrocute_mob(user, C, src, siemens_coefficient))
spark(src)
return 1
else
@@ -217,7 +217,7 @@
open = FALSE
update_door_status()
- playsound(get_turf(src), 'sound/machines/click.ogg', 100, 1)
+ playsound(src, 'sound/machines/click.ogg', 100, 1)
/obj/structure/fence/door/proc/update_door_status()
switch(open)
diff --git a/code/game/objects/structures/flaps.dm b/code/game/objects/structures/flaps.dm
index 5c01bcd46a6..67ede4db0b2 100644
--- a/code/game/objects/structures/flaps.dm
+++ b/code/game/objects/structures/flaps.dm
@@ -12,9 +12,9 @@
/obj/structure/plasticflaps/attackby(obj/item/I as obj, mob/user as mob)
if(iscrowbar(I) && anchored == 1)
if(airtight == 0)
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 50, 1)
else
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("[user] [airtight? "loosen the [src] from" : "tighten the [src] into"] an airtight position.", "You [airtight? "loosen the [src] from" : "tighten the [src] into"] an airtight position.")
airtight = !airtight
name = "\improper [airtight? "Airtight p" : "P"]lastic flaps"
@@ -22,9 +22,9 @@
return 1
if(iswrench(I) && airtight != 1)
if(anchored == 0)
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
else
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
user.visible_message("[user] [anchored? "loosens" : "tightens"] the flap from its anchoring.", "You [anchored? "loosen" : "tighten"] the flap from its anchoring.")
anchored = !anchored
return 1
diff --git a/code/game/objects/structures/fullwindow.dm b/code/game/objects/structures/fullwindow.dm
index 23db6416e3e..e8cc3bc2710 100644
--- a/code/game/objects/structures/fullwindow.dm
+++ b/code/game/objects/structures/fullwindow.dm
@@ -94,12 +94,16 @@
update_nearby_tiles()
ini_dir = dir
+/obj/structure/window/full/AltClick(var/mob/user)
+ var/turf/T = get_turf(src)
+ T.AltClick(user)
+
/obj/structure/window/full/reinforced
name = "reinforced window"
desc = "A window with a rod matrice. It looks more solid than the average window."
icon_state = "rwindow0"
base_state = "rwindow"
- sheettype = /obj/item/stack/sheet/glass/rglass
+ sheet_type = /obj/item/stack/sheet/glass/rglass
health = 40
penetration_dampening = 3
d_state = WINDOWSECURE
@@ -112,7 +116,7 @@
icon_state = "plasmawindow0"
base_state = "plasmawindow"
shardtype = /obj/item/weapon/shard/plasma
- sheettype = /obj/item/stack/sheet/glass/plasmaglass
+ sheet_type = /obj/item/stack/sheet/glass/plasmaglass
health = 120
penetration_dampening = 5
@@ -125,7 +129,7 @@
icon_state = "plasmarwindow0"
base_state = "plasmarwindow"
shardtype = /obj/item/weapon/shard/plasma
- sheettype = /obj/item/stack/sheet/glass/plasmarglass
+ sheet_type = /obj/item/stack/sheet/glass/plasmarglass
health = 160
penetration_dampening = 7
@@ -139,7 +143,7 @@
icon_state = "twindow0"
base_state = "twindow"
opacity = 1
- sheettype = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you
+ sheet_type = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you
/obj/structure/window/full/reinforced/tinted/frosted
@@ -148,7 +152,7 @@
icon_state = "fwindow0"
base_state = "fwindow"
health = 30
- sheettype = /obj/item/stack/sheet/glass/rglass //Ditto above
+ sheet_type = /obj/item/stack/sheet/glass/rglass //Ditto above
#undef WINDOWLOOSE
#undef WINDOWLOOSEFRAME
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index e970af73395..ffa528c93e2 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -19,7 +19,7 @@
/obj/structure/girder/wood/attackby(var/obj/item/W, var/mob/user)
if(W.sharpness_flags & CHOPWOOD)
- playsound(get_turf(src), 'sound/effects/woodcuttingshort.ogg', 50, 1)
+ playsound(src, 'sound/effects/woodcuttingshort.ogg', 50, 1)
user.visible_message("[user] smashes through \the [src] with \the [W].", \
"You smash through \the [src].",\
"You hear the sound of wood being cut"
@@ -41,7 +41,7 @@
if(iswrench(W))
if(state == 0) //Normal girder or wooden girder
if(anchored && !istype(src, /obj/structure/girder/displaced)) //Anchored, destroy it
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
user.visible_message("[user] starts disassembling \the [src].", \
"You start disassembling \the [src].")
if(do_after(user, src, construction_length))
@@ -54,7 +54,7 @@
to_chat(user, "You can't secure \the [src] to [istype(src.loc,/turf/space) ? "space" : "this"]!")
return
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
user.visible_message("[user] starts securing \the [src].", \
"You start securing \the [src].")
if(do_after(user, src, construction_length))
@@ -65,7 +65,7 @@
anchored = 1
update_icon()
else if(state == 1 || state == 2) //Clearly a reinforced girder
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
user.visible_message("[user] starts [anchored ? "un" : ""]securing \the [src].", \
"You start [anchored ? "un" : ""]securing \the [src].")
if(do_after(user, src, construction_length))
@@ -90,7 +90,7 @@
qdel(src)
else if(isscrewdriver(W) && state == 2) //Unsecuring support struts, stage 2 to 1
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
user.visible_message("[user] starts unsecuring \the [src]'s internal support struts.", \
"You start unsecuring \the [src]'s internal support struts.")
if(do_after(user, src, construction_length))
@@ -102,7 +102,7 @@
update_icon()
else if(isscrewdriver(W) && state == 1) //Securing support struts, stage 1 to 2
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
user.visible_message("[user] starts securing \the [src]'s internal support struts.", \
"You start securing \the [src]'s internal support struts.")
if(do_after(user, src, construction_length))
@@ -114,7 +114,7 @@
update_icon()
else if(iswirecutter(W) && state == 1) //Removing support struts, stage 1 to 0 (normal girder)
- playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 100, 1)
user.visible_message("[user] starts removing \the [src]'s internal support struts.", \
"You start removing \the [src]'s internal support struts.")
if(do_after(user, src, construction_length))
@@ -147,7 +147,7 @@
update_icon()
else if(iscrowbar(W) && state == 0 && anchored) //Turning normal girder into disloged girder
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 1)
user.visible_message("[user] starts dislodging \the [src].", \
"You start dislodging \the [src].")
if(do_after(user, src, construction_length))
@@ -393,7 +393,7 @@
/obj/structure/cultgirder/attackby(obj/item/W as obj, mob/user as mob)
if(iswrench(W))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
user.visible_message("[user] starts disassembling \the [src].", \
"You start disassembling \the [src].")
if(do_after(user, src,40))
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 776cc5a07b9..d9fec9b55bf 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -144,14 +144,14 @@
/obj/structure/grille/attackby(obj/item/weapon/W as obj, mob/user as mob)
user.delayNextAttack(8)
if(iswirecutter(W))
- if(!shock(user, 100)) //Prevent user from doing it if he gets shocked
+ if(!shock(user, 100, W.siemens_coefficient)) //Prevent user from doing it if he gets shocked
playsound(loc, 'sound/items/Wirecutter.ogg', 100, 1)
drop_stack(/obj/item/stack/rods, get_turf(src), broken ? 1 : 2, user) //Drop the rods, taking account on whenever the grille is broken or not !
qdel(src)
return
return //Return in case the user starts cutting and gets shocked, so that it doesn't continue downwards !
else if((isscrewdriver(W)) && (istype(loc, /turf/simulated) || anchored))
- if(!shock(user, 90))
+ if(!shock(user, 90, W.siemens_coefficient))
playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
anchored = !anchored
user.visible_message("[user] [anchored ? "fastens" : "unfastens"] the grille [anchored ? "to" : "from"] the floor.", \
@@ -215,7 +215,7 @@
dam = W.force * 0.5 //Rod matrices have an innate resistance to brute damage
if(!(W.sharpness_flags & INSULATED_EDGE))
- shock(user, 100 * W.siemens_coefficient) //Chance of getting shocked is proportional to conductivity
+ shock(user, 100 * W.siemens_coefficient, W.siemens_coefficient) //Chance of getting shocked is proportional to conductivity
if(dam)
user.do_attack_animation(src, W)
@@ -227,7 +227,7 @@
//Shock user with probability prb (if all connections & power are working)
//Returns 1 if shocked, 0 otherwise
-/obj/structure/grille/proc/shock(mob/user as mob, prb)
+/obj/structure/grille/proc/shock(mob/user as mob, prb, siemens_coeff)
if(!anchored || broken) //De-anchored and destroyed grilles are never connected to the powernet !
return 0
if(!prob(prb)) //If the probability roll failed, don't go further
@@ -238,7 +238,7 @@
var/turf/T = get_turf(src)
var/obj/structure/cable/C = T.get_cable_node()
if(C)
- if(electrocute_mob(user, C, src))
+ if(electrocute_mob(user, C, src, siemens_coeff))
spark(src)
return 1
else
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index f2e13d4f523..5818498f3da 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -73,6 +73,8 @@
C.drop_stomach_contents()
user.visible_message("\The [C]'s stomach contents drop to the ground!")
+ occupant.meat_amount++
+
returnToPool(G)
return
@@ -86,11 +88,11 @@
if(occupant.meat_amount > occupant.meat_taken)
to_chat(user, "You remove some meat from \the [occupant].")
+ return
else
to_chat(user, "You remove the last piece of meat from \the [src]!")
- clean()
- else
- clean()
+
+ clean()
/obj/structure/kitchenspike/proc/clean()
icon_state = initial(icon_state)
diff --git a/code/game/objects/structures/lamarr_cage.dm b/code/game/objects/structures/lamarr_cage.dm
index 9fcb1469d44..4d3ab8e0a22 100644
--- a/code/game/objects/structures/lamarr_cage.dm
+++ b/code/game/objects/structures/lamarr_cage.dm
@@ -47,7 +47,7 @@
playsound(src, "shatter", 70, 1)
Break()
else
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
return
/obj/structure/lamarr/update_icon()
diff --git a/code/game/objects/structures/mannequin.dm b/code/game/objects/structures/mannequin.dm
index ec291a3d44a..5da3d96b08c 100644
--- a/code/game/objects/structures/mannequin.dm
+++ b/code/game/objects/structures/mannequin.dm
@@ -871,7 +871,7 @@
else
destroyed = 1
getFromPool(/obj/item/weapon/shard, loc)
- playsound(get_turf(src), "shatter", 100, 1)
+ playsound(src, "shatter", 100, 1)
shield = 0
update_icon()
if (2)
@@ -906,10 +906,10 @@
destroyed = 1
locked = 0
getFromPool(/obj/item/weapon/shard, loc)
- playsound(get_turf(src), "shatter", 100, 1)
+ playsound(src, "shatter", 100, 1)
update_icon()
else
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 75, 1)
if(health <= 0)
visible_message("\The [src] collapses.")
@@ -1038,7 +1038,7 @@
/obj/structure/mannequin/cyber/kick_act(mob/living/carbon/human/H)
if(locked)
- playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1)
+ playsound(src, 'sound/effects/glassknock.ogg', 100, 1)
..()
@@ -1156,7 +1156,7 @@
/datum/construction/mannequin/spawn_result(mob/user as mob)
if(result)
- testing("[user] finished a [result]!")
+// testing("[user] finished a [result]!")
var/obj/structure/mannequin_frame/const_holder = holder
var/obj/structure/mannequin/cyber/C = new result(get_turf(holder))
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index 2e91e9e650f..aa12bf87ea0 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -87,19 +87,19 @@
stack.use(2)
shattered = 0
icon_state = "mirror"
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 80, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
else
user.do_attack_animation(src, I)
if(shattered)
- playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return
else if(prob(I.force * 2))
visible_message("[user] smashes [src] with [I]!")
shatter()
else
visible_message("[user] hits [src] with [I]!")
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 70, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 70, 1)
/obj/structure/mirror/attack_alien(mob/living/user as mob)
@@ -107,7 +107,7 @@
return
user.do_attack_animation(src, user)
if(shattered)
- playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return
user.visible_message("[user] smashes [src]!")
shatter()
@@ -121,7 +121,7 @@
return
user.do_attack_animation(src, user)
if(shattered)
- playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return
user.visible_message("[user] smashes [src]!")
shatter()
@@ -132,7 +132,7 @@
return
user.do_attack_animation(src, user)
if(shattered)
- playsound(get_turf(src), 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
return
user.visible_message("[user] smashes [src]!")
shatter()
diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm
index 517425d5c4c..9cd62ce28f0 100644
--- a/code/game/objects/structures/mop_bucket.dm
+++ b/code/game/objects/structures/mop_bucket.dm
@@ -37,7 +37,7 @@
else
src.reagents.trans_to(M, 3)
to_chat(user, "You wet [M]")
- playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1)
+ playsound(src, 'sound/effects/slosh.ogg', 25, 1)
else
to_chat(user, "Nothing left to wet [M] with!")
return 1
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 69328395a6e..1fb81c13419 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -86,7 +86,7 @@
return
/obj/structure/morgue/proc/open_up()
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
connected = new /obj/structure/m_tray(loc)
connected.layer = OBJ_LAYER
step(connected, src.dir)
@@ -126,12 +126,12 @@
user.visible_message("\The [user] begins dismantling \the [src].", "You begin dismantling \the [src].")
if(do_after(user, src,50))
user.visible_message("\The [user] dismantles \the [src].", "You dismantle \the [src].")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
new /obj/structure/closet/body_bag(src.loc)
new /obj/item/stack/sheet/metal(src.loc,5)
qdel(src)
if(iswrench(P))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
if(dir==4)
dir=8
else
@@ -272,11 +272,11 @@
for(var/atom/movable/A as mob|obj in src.connected.loc)
if (!( A.anchored ))
A.forceMove(src)
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
qdel(src.connected)
src.connected = null
else if (src.locked == 0)
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
src.connected = new /obj/structure/c_tray( src.loc )
step(src.connected, SOUTH)
src.connected.layer = OBJ_LAYER
@@ -370,7 +370,7 @@
cremating = 0
update()
locked = 0
- playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1)
+ playsound(src, 'sound/machines/ding.ogg', 50, 1)
/*
diff --git a/code/game/objects/structures/noticeboard.dm b/code/game/objects/structures/noticeboard.dm
index 154d3cb9c8b..d0e4d413ed2 100644
--- a/code/game/objects/structures/noticeboard.dm
+++ b/code/game/objects/structures/noticeboard.dm
@@ -21,7 +21,7 @@
/obj/structure/noticeboard/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob)
if(iswrench(O))
to_chat(user, "You disassemble \the [src].")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
new /obj/item/stack/sheet/wood (src.loc,2)
qdel(src)
if(istype(O, /obj/item/weapon/paper))
diff --git a/code/game/objects/structures/popout_cake.dm b/code/game/objects/structures/popout_cake.dm
index 6886f36da6c..8438bf57d6c 100644
--- a/code/game/objects/structures/popout_cake.dm
+++ b/code/game/objects/structures/popout_cake.dm
@@ -136,7 +136,7 @@
spawn(10)
- playsound(get_turf(src), 'sound/effects/party_horn.ogg', 50, 1)
+ playsound(src, 'sound/effects/party_horn.ogg', 50, 1)
sleep(10)
diff --git a/code/game/objects/structures/skele_stand.dm b/code/game/objects/structures/skele_stand.dm
index e44a6a8c546..dcf37b8b5d2 100644
--- a/code/game/objects/structures/skele_stand.dm
+++ b/code/game/objects/structures/skele_stand.dm
@@ -20,7 +20,7 @@
visible_message("\The [src] rattles [pick("ominously","violently")] on \his stand! [pick("Spooky","Weird")].")
else
visible_message("\The [src] rattles[thingy ? " upon being hit by \the [thingy]" : ""].")
- playsound(get_turf(src), 'sound/effects/rattling_bones.ogg', 50, 0)
+ playsound(src, 'sound/effects/rattling_bones.ogg', 50, 0)
last_rattle_time = world.time
else
return
diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
index c61819dc940..b80468c47be 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
@@ -14,11 +14,16 @@
icon = 'icons/obj/stools-chairs-beds.dmi'
layer = BELOW_OBJ_LAYER
anchored = 1
- var/sheet_type = /obj/item/stack/sheet/metal
- var/sheet_amt = 1
+ sheet_type = /obj/item/stack/sheet/metal
+ sheet_amt = 1
var/lock_type = /datum/locking_category/buckle/bed
+/obj/structure/bed/New()
+ ..()
+ if(material_type)
+ sheet_type = material_type.sheettype
+
/obj/structure/bed/alien
name = "resting contraption"
desc = "This looks similar to contraptions from earth. Could aliens be stealing our technology?"
@@ -77,7 +82,7 @@
"[M] unbuckled \himself!",\
"You unbuckle yourself from \the [src].",\
"You hear metal clanking.")
- playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1)
+ playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1)
unlock_atom(M)
add_fingerprint(user)
@@ -117,7 +122,7 @@
"You are buckled in to [src] by [user.name].",\
"You hear metal clanking.")
- playsound(get_turf(src), 'sound/misc/buckle_click.ogg', 50, 1)
+ playsound(src, 'sound/misc/buckle_click.ogg', 50, 1)
add_fingerprint(user)
lock_atom(M, lock_type)
@@ -143,6 +148,10 @@
lockflags = DENSE_WHEN_LOCKED
lock_type = /datum/locking_category/buckle/bed/roller
+/obj/structure/bed/roller/deff
+ icon = 'maps/defficiency/medbay.dmi'
+ roller_type = /obj/item/roller/deff
+
/obj/item/roller
name = "roller bed"
desc = "A collapsed roller bed that can be carried around."
@@ -153,6 +162,10 @@
var/bed_type = /obj/structure/bed/roller
w_class = W_CLASS_LARGE // Can't be put in backpacks. Oh well.
+/obj/item/roller/deff
+ icon = 'maps/defficiency/medbay.dmi'
+ bed_type = /obj/structure/bed/roller/deff
+
/obj/item/roller/attack_self(mob/user)
var/obj/structure/bed/roller/R = new bed_type(user.loc)
R.add_fingerprint(user)
@@ -191,7 +204,7 @@
if(istype(W,/obj/item/roller_holder))
manual_unbuckle(user)
if(iswrench(W))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
drop_stack(sheet_type, loc, 2, user)
qdel(src)
return
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index 5593a15de3e..eb3fe47a392 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -47,7 +47,7 @@
var/obj/item/assembly/shock_kit/SK = W
if(user.drop_item(W))
var/obj/structure/bed/chair/e_chair/E = new /obj/structure/bed/chair/e_chair(src.loc)
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
E.dir = dir
E.part = SK
SK.forceMove(E)
@@ -56,7 +56,7 @@
return
if(iswrench(W))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
drop_stack(sheet_type, loc, sheet_amt, user)
qdel(src)
return
@@ -130,6 +130,8 @@
else
buckle_mob(M, user)
+ if(material_type)
+ material_type.on_use(src,M,user)
// Chair types
/obj/structure/bed/chair/wood
diff --git a/code/game/objects/structures/stool_bed_chair_nest/guillotine.dm b/code/game/objects/structures/stool_bed_chair_nest/guillotine.dm
index a1abef068b6..e59e416d7cf 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/guillotine.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/guillotine.dm
@@ -207,7 +207,7 @@
var/datum/organ/external/head/H = victim.get_organ(LIMB_HEAD)
if(istype(H) && ~H.status & ORGAN_DESTROYED)
H.droplimb(1)
- playsound(get_turf(src), 'sound/weapons/bloodyslice.ogg', 100, 1)
+ playsound(src, 'sound/weapons/bloodyslice.ogg', 100, 1)
blood_splatter(get_turf(src),victim,1)
bladedown = TRUE
update_icon()
diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
index 8f71f8f9335..a489d27f180 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
@@ -7,7 +7,7 @@
force = 10
throwforce = 10
w_class = W_CLASS_HUGE
- var/sheet_path = /obj/item/stack/sheet/metal
+ sheet_type = /obj/item/stack/sheet/metal
/obj/item/weapon/stool/bar
name = "bar stool"
@@ -15,7 +15,7 @@
icon_state = "bar-stool"
/obj/item/weapon/stool/hologram
- sheet_path = null
+ sheet_type = null
/obj/item/weapon/stool/piano
name = "piano stool"
@@ -23,7 +23,7 @@
icon_state = "stool_piano"
autoignition_temperature = AUTOIGNITION_WOOD
fire_fuel = 3
- sheet_path = /obj/item/stack/sheet/wood
+ sheet_type = /obj/item/stack/sheet/wood
/obj/item/weapon/stool/piano/initialize()
..()
@@ -34,9 +34,9 @@
return
/obj/item/weapon/stool/attackby(var/obj/item/weapon/W, var/mob/user)
- if(iswrench(W) && sheet_path)
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
- drop_stack(sheet_path, loc, 1, user)
+ if(iswrench(W) && sheet_type)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
+ drop_stack(sheet_type, loc, 1, user)
qdel(src)
. = ..()
@@ -47,11 +47,11 @@
. = ..()
/obj/item/weapon/stool/attack(mob/M as mob, mob/user as mob)
- if(prob(5) && istype(M, /mob/living) && sheet_path)
+ if(prob(5) && istype(M, /mob/living) && sheet_type)
user.visible_message("[user] breaks \the [src] over [M]'s back!.")
user.u_equip(src, 0)
- getFromPool(sheet_path, get_turf(src), 1)
+ getFromPool(sheet_type, get_turf(src), 1)
qdel(src)
var/mob/living/T = M
diff --git a/code/game/objects/structures/support_rail.dm b/code/game/objects/structures/support_rail.dm
index 2a6c74b9f1f..b1f4b606cbe 100644
--- a/code/game/objects/structures/support_rail.dm
+++ b/code/game/objects/structures/support_rail.dm
@@ -16,7 +16,7 @@
/obj/structure/support_rail/attackby(obj/item/weapon/W, mob/living/carbon/human/user as mob)
if(iswrench(W))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal, get_turf(src))
M.amount = 1
qdel(src)
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index ba989313810..c93b31064b2 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -50,7 +50,7 @@
/obj/structure/table/glass/proc/checkhealth()
if(health <= 0)
- playsound(get_turf(src), "shatter", 50, 1)
+ playsound(src, "shatter", 50, 1)
new /obj/item/weapon/shard(src.loc)
new /obj/item/weapon/table_parts(src.loc)
qdel(src)
@@ -398,7 +398,7 @@
M.Knockdown(5)
M.apply_damage(8,def_zone = LIMB_HEAD)
visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!")
- playsound(get_turf(src), 'sound/weapons/tablehit1.ogg', 50, 1)
+ playsound(src, 'sound/weapons/tablehit1.ogg', 50, 1)
else
to_chat(user, "You need a better grip to do that!")
return
@@ -412,7 +412,7 @@
if (iswrench(W) && can_disassemble())
//if(!params_list.len || text2num(params_list["icon-y"]) < 8) //8 above the bottom of the icon
to_chat(user, "Now disassembling table")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
if(do_after(user, src,50))
destroy()
return
@@ -593,7 +593,7 @@
/obj/structure/table/reinforced/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(istype(W,/obj/item/weapon/stock_parts/scanning_module))
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src, 40))
if(user.drop_item(W))
var/obj/machinery/optable/OPT = new /obj/machinery/optable(src.loc)
@@ -615,7 +615,7 @@
if(WT.remove_fuel(0, user))
if(src.status == 2)
to_chat(user, "Now weakening the reinforced table.")
- playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
if (do_after(user, src, 50))
if(!src || !WT.isOn())
return
@@ -623,7 +623,7 @@
src.status = 1
else
to_chat(user, "Now strengthening the reinforced table.")
- playsound(get_turf(src), 'sound/items/Welder.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder.ogg', 50, 1)
if (do_after(user, src, 50))
if(!src || !WT.isOn())
return
@@ -656,8 +656,8 @@
M.Knockdown(5)
M.apply_damage(15,def_zone = LIMB_HEAD)
visible_message("[G.assailant] slams [G.affecting]'s face against \the [src]!")
- playsound(get_turf(src), 'sound/weapons/tablehit1.ogg', 50, 1)
- playsound(get_turf(src), "shatter", 50, 1) //WRESTLEMANIA tax
+ playsound(src, 'sound/weapons/tablehit1.ogg', 50, 1)
+ playsound(src, "shatter", 50, 1) //WRESTLEMANIA tax
new /obj/item/weapon/shard(src.loc)
new /obj/item/weapon/table_parts(src.loc)
qdel(src)
@@ -676,7 +676,7 @@
health -= W.force
user.visible_message("\The [user] hits \the [src] with \the [W].", \
"You hit \the [src] with \the [W].")
- playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 50, 1)
+ playsound(src, 'sound/effects/Glasshit.ogg', 50, 1)
checkhealth()
else
@@ -771,7 +771,7 @@
/obj/structure/rack/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(iswrench(W) && can_disassemble())
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
destroy(TRUE)
return
diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm
index 36aab72f972..93fa28e7a6a 100644
--- a/code/game/objects/structures/tank_dispenser.dm
+++ b/code/game/objects/structures/tank_dispenser.dm
@@ -86,11 +86,11 @@
if(iswrench(I))
if(anchored)
to_chat(user, "You lean down and unwrench [src].")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
anchored = 0
else
to_chat(user, "You wrench [src] into place.")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
anchored = 1
return
diff --git a/code/game/objects/structures/transit_tubes.dm b/code/game/objects/structures/transit_tubes.dm
index e015ac25573..846b6d7f7f8 100644
--- a/code/game/objects/structures/transit_tubes.dm
+++ b/code/game/objects/structures/transit_tubes.dm
@@ -1,3 +1,4 @@
+#define TUBE_POD_UNLOAD_LIMIT 20
// Basic transit tubes. Straight pieces, curved sections,
// and basic splits/joins (no routing logic).
@@ -125,17 +126,63 @@ obj/structure/transit_tube_pod/ex_act(severity)
..()
-/obj/structure/transit_tube/station/attack_hand(mob/user as mob)
+/obj/structure/transit_tube/station/attack_hand(mob/user)
if(!pod_moving)
for(var/obj/structure/transit_tube_pod/pod in loc)
if(!pod.moving && pod.dir in directions())
if(open)
+ if(!user.lying && user.loc != pod)
+ var/unloaded = 0
+ var/incomplete = FALSE
+
+ for(var/atom/movable/AM in pod)
+ if(isobserver(AM))
+ continue
+ if(unloaded >= TUBE_POD_UNLOAD_LIMIT)
+ incomplete = TRUE
+ break
+ AM.forceMove(get_step(loc, dir))
+ unloaded++
+
+ if(unloaded)
+ user.visible_message("[user] unloads [incomplete ? "some things" : "everything"] from the tube pod.", \
+ "You unload [incomplete ? "some things" : "everything"] from the tube pod.")
+ return
+
close_animation()
else
open_animation()
+/obj/structure/transit_tube/station/attack_robot(mob/user)
+ if(Adjacent(user))
+ attack_hand(user)
+
+
+/obj/structure/transit_tube_pod/examine(mob/user)
+ ..()
+ show_occupants(user)
+
+
+/obj/structure/transit_tube/examine(mob/user)
+ ..()
+ for(var/obj/structure/transit_tube_pod/pod in loc)
+ pod.show_occupants(user)
+
+
+/obj/structure/transit_tube_pod/proc/show_occupants(mob/user)
+ if(contents.len)
+ var/list/occupants = contents.Copy()
+ for(var/atom/movable/O in occupants)
+ if(O.invisibility > user.see_invisible)
+ occupants -= O
+ if(occupants.len)
+ to_chat(user, "The tube pod contains [english_list(occupants)].")
+ return
+
+ to_chat(user, "The tube pod looks empty.")
+
/obj/structure/transit_tube/station/proc/open_animation()
if(icon_state == "closed")
@@ -621,3 +668,5 @@ obj/structure/transit_tube_pod/ex_act(severity)
return "SW"
else
return
+
+#undef TUBE_POD_UNLOAD_LIMIT
diff --git a/code/game/objects/structures/vehicles/carts/cart.dm b/code/game/objects/structures/vehicles/carts/cart.dm
index eae2aa1215d..91a0c5c3eaf 100644
--- a/code/game/objects/structures/vehicles/carts/cart.dm
+++ b/code/game/objects/structures/vehicles/carts/cart.dm
@@ -21,13 +21,13 @@
next_cart = connecting
next_cart.previous_cart = src
user.visible_message("[user] connects [connecting] to [src].", "You connect [connecting] to [src].")
- playsound(get_turf(src), 'sound/misc/buckle_click.ogg', 50, 1)
+ playsound(src, 'sound/misc/buckle_click.ogg', 50, 1)
return
else if (next_cart == connecting)
next_cart.previous_cart = null
next_cart = null
user.visible_message("[user] disconnects [connecting] from [src].", "You disconnect [connecting] from [src].")
- playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1)
+ playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1)
return
else
to_chat(user, "\The [src] already has a cart connected to it!", "red")
@@ -45,10 +45,10 @@
if (next_cart) //This one is really unlikely to happen
if (get_dist(next_cart, src) > 1.99) //This is a nasty nasty hack but IT WORKS SO DON'T TOUCH IT
next_cart = null
- playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1)
+ playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1)
if (previous_cart)
if (get_dist(previous_cart, src) > 1.99)
previous_cart.next_cart = null
previous_cart = null
- playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1)
\ No newline at end of file
+ playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1)
\ No newline at end of file
diff --git a/code/game/objects/structures/vehicles/clowncart.dm b/code/game/objects/structures/vehicles/clowncart.dm
index a2e52639a71..0224cbbf8ec 100644
--- a/code/game/objects/structures/vehicles/clowncart.dm
+++ b/code/game/objects/structures/vehicles/clowncart.dm
@@ -85,13 +85,13 @@
user.visible_message("[user] honks at [src].", \
"You honk at [src].", \
"You hear honking.")
- playsound(get_turf(src), W.hitsound, 50, 1)
+ playsound(src, W.hitsound, 50, 1)
if(reagents.get_reagent_amount(BANANA) <= 5 && max_health < HEALTH_FOR_FREE_MOVEMENT)
if(activated)
visible_message("[nick] lets out a last honk before running out of fuel and activating its ejection seat.")
if(ishigherbeing(user)) //This shouldn't be needed, but fucks sakes
user.Knockdown(5)
- playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1)
+ playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
activated = 0
reagents.remove_reagent(BANANA, 5)
else
@@ -100,7 +100,7 @@
spawn(5)
activated = 1
src.visible_message("[nick] honks back happily.")
- playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1)
+ playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
honk = world.timeofday
else if(istype(W, /obj/item/weapon/reagent_containers))
if(feed(W,user))
@@ -160,7 +160,7 @@
ST.use(1)
else if(istype(W, /obj/item/weapon/coin/clown)) //Bananium coin
user.visible_message("[user] inserts a bananium coin into [src].", "You insert a bananium coin into [src].")
- playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 1)
+ playsound(src, 'sound/machines/ping.ogg', 50, 1)
mode += 1
if(mode > 2) //only 3 modes, so when it raises above 2 reset to 0
mode = 0
@@ -168,7 +168,7 @@
if(MODE_NORMAL)
spawn(5)
visible_message("[src]'s SynthPeel Generator turns off with a buzz.")
- playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 1)
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1)
if(MODE_DRAWING)
visible_message("[src]'s SmartCrayon Mk.II deploys, ready to draw!")
to_chat(user, {"Use a crayon to decide what you want to draw.
@@ -176,9 +176,9 @@
if(MODE_PEELS)
visible_message("[src]'s SmartCrayon Mk.II disappears in a puff of art!")
spawn(5)
- playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 1)
+ playsound(src, 'sound/machines/ping.ogg', 50, 1)
visible_message("You hear a ping as [src]'s SynthPeel Generator starts transforming banana juice into slippery peels.")
- playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 1)
+ playsound(src, 'sound/machines/ping.ogg', 50, 1)
qdel(W)
W = null
else if(istype(W, /obj/item/toy/crayon/)) //Any crayon
@@ -298,7 +298,7 @@
/obj/structure/bed/chair/vehicle/clowncart/die()
setDensity(FALSE)
visible_message("[nick] explodes in a puff of pure potassium!")
- playsound(get_turf(src), 'sound/items/bikehorn.ogg', 75, 1)
+ playsound(src, 'sound/items/bikehorn.ogg', 75, 1)
explosion(src.loc, -1, 0, 3, 7, 10)
for(var/a = 0, a < round(reagents.total_volume*0.25), a++) //Spawn banana peels in place of the cart
new /obj/item/weapon/bananapeel(get_turf(src)) // WHAT STUPID ASSHOLE MADE THESE TATORPEELS
@@ -359,7 +359,7 @@
reagents.add_reagent(BANANA, added_banana*modifier)
if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/pie))
- playsound(get_turf(src), 'sound/effects/bubbles.ogg', 50, 1)
+ playsound(src, 'sound/effects/bubbles.ogg', 50, 1)
to_chat(user, "[W] starts boiling inside \the [src]!")
trail+=5
return added_banana*modifier
diff --git a/code/game/objects/structures/vehicles/janicart.dm b/code/game/objects/structures/vehicles/janicart.dm
index ff74ce54b1f..88652ca32c3 100644
--- a/code/game/objects/structures/vehicles/janicart.dm
+++ b/code/game/objects/structures/vehicles/janicart.dm
@@ -64,7 +64,7 @@
if(reagents.total_volume >= 2)
reagents.trans_to(M, 3)
to_chat(user, "You wet the mop in \the [nick].")
- playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1)
+ playsound(src, 'sound/effects/slosh.ogg', 25, 1)
if(reagents.total_volume < 1)
to_chat(user, "\The [nick] is out of water!")
return 1
diff --git a/code/game/objects/structures/vehicles/secway.dm b/code/game/objects/structures/vehicles/secway.dm
index f08ad69d551..1634367f39c 100644
--- a/code/game/objects/structures/vehicles/secway.dm
+++ b/code/game/objects/structures/vehicles/secway.dm
@@ -58,7 +58,7 @@
return
occupant.Knockdown(2)
occupant.Stun(2)
- playsound(get_turf(src), "sound/effects/meteorimpact.ogg", 25, 1)
+ playsound(src, "sound/effects/meteorimpact.ogg", 25, 1)
occupant.visible_message("[occupant] crashes into \the [obstacle]!", "You crash into \the [obstacle]!")
if(istype(obstacle, /mob/living))
diff --git a/code/game/objects/structures/vehicles/vehicle.dm b/code/game/objects/structures/vehicles/vehicle.dm
index 71e57c05325..cb5adde8f53 100644
--- a/code/game/objects/structures/vehicles/vehicle.dm
+++ b/code/game/objects/structures/vehicles/vehicle.dm
@@ -118,7 +118,7 @@
else if(isscrewdriver(W) && !heldkey)
var/mob/living/carbon/human/H = user
to_chat(user, "You jam \the [W] into \the [src]'s ignition and feel like a genius as you try turning it!")
- playsound(get_turf(src), "sound/items/screwdriver.ogg", 10, 1)
+ playsound(src, "sound/items/screwdriver.ogg", 10, 1)
H.adjustBrainLoss(10)
/obj/structure/bed/chair/vehicle/attack_hand(mob/user)
@@ -245,14 +245,14 @@
next_cart = C
next_cart.previous_cart = src
user.visible_message("[user] connects [C] to [src].", "You connect [C] to [src]")
- playsound(get_turf(src), 'sound/misc/buckle_click.ogg', 50, 1)
+ playsound(src, 'sound/misc/buckle_click.ogg', 50, 1)
return
else if (next_cart == C)
next_cart.previous_cart = null
next_cart = null
user.visible_message("[user] disconnects [C] to [src].", "You disconnect [C] to [src]")
- playsound(get_turf(src), 'sound/misc/buckle_unclick.ogg', 50, 1)
+ playsound(src, 'sound/misc/buckle_unclick.ogg', 50, 1)
return
/obj/structure/bed/chair/vehicle/update_dir()
diff --git a/code/game/objects/structures/vehicles/wheelchair.dm b/code/game/objects/structures/vehicles/wheelchair.dm
index 6c510cfbe02..d36c4a9612b 100644
--- a/code/game/objects/structures/vehicles/wheelchair.dm
+++ b/code/game/objects/structures/vehicles/wheelchair.dm
@@ -276,7 +276,7 @@
/obj/structure/bed/chair/vehicle/wheelchair/motorized/syndicate/proc/crush(var/mob/living/H,var/bloodcolor) //Basically identical to the MULE, see mulebot.dm
src.visible_message("[src] drives over [H]!")
- playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
+ playsound(src, 'sound/effects/splat.ogg', 50, 1)
var/damage = rand(5,10) //We're not as heavy as a MULE. Where it does 30-90 damage, we do 15-30 damage
H.apply_damage(damage, BRUTE, LIMB_CHEST)
H.apply_damage(damage, BRUTE, LIMB_LEFT_LEG)
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 5414c1fdbfb..1a7e9fc37aa 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -246,7 +246,7 @@
if(iswrench(I))
user.visible_message("[user] starts adjusting the bolts on \the [src].", \
"You start adjusting the bolts on \the [src].")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
if(do_after(user, src, 50))
if(anchored == 1)
src.visible_message("[user] unbolts \the [src] from the floor.", \
@@ -490,7 +490,7 @@
busy = 0
M.clean_blood()
if(M.reagents.maximum_volume > M.reagents.total_volume)
- playsound(get_turf(src), 'sound/effects/slosh.ogg', 25, 1)
+ playsound(src, 'sound/effects/slosh.ogg', 25, 1)
M.reagents.add_reagent(WATER, min(M.reagents.maximum_volume - M.reagents.total_volume, 50))
user.visible_message("[user] finishes soaking \the [M], \he could clean the entire station with that.","You finish soaking \the [M], you feel as if you could clean anything now, even the Chef's backroom...")
else
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index b56fb2b01f7..419a2caa4fa 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -77,7 +77,7 @@ obj/structure/windoor_assembly/Destroy()
var/obj/item/weapon/weldingtool/WT = W
if (WT.remove_fuel(0,user))
user.visible_message("[user] dissassembles the windoor assembly.", "You start to dissassemble the windoor assembly.")
- playsound(get_turf(src), 'sound/items/Welder2.ogg', 50, 1)
+ playsound(src, 'sound/items/Welder2.ogg', 50, 1)
if(do_after(user, src, 40))
if(!src || !WT.isOn())
@@ -96,7 +96,7 @@ obj/structure/windoor_assembly/Destroy()
//Wrenching an unsecure assembly anchors it in place. Step 4 complete
if(iswrench(W) && !anchored)
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
user.visible_message("[user] secures the windoor assembly to the floor.", "You start to secure the windoor assembly to the floor.")
if(do_after(user, src, 40))
@@ -111,7 +111,7 @@ obj/structure/windoor_assembly/Destroy()
//Unwrenching an unsecure assembly un-anchors it. Step 4 undone
else if(iswrench(W) && anchored)
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 100, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 100, 1)
user.visible_message("[user] unsecures the windoor assembly to the floor.", "You start to unsecure the windoor assembly to the floor.")
if(do_after(user, src, 40))
@@ -146,13 +146,16 @@ obj/structure/windoor_assembly/Destroy()
//Adding cable to the assembly. Step 5 complete.
else if(istype(W, /obj/item/stack/cable_coil) && anchored)
+ var/obj/item/stack/cable_coil/CC = W
+ if(CC.amount < 2)
+ to_chat(user, "You need more cable for this!")
+ return
user.visible_message("[user] wires the windoor assembly.", "You start to wire the windoor assembly.")
if(do_after(user, src, 40))
if(!src)
return
- var/obj/item/stack/cable_coil/CC = W
- CC.use(1)
+ CC.use(2)
to_chat(user, "You wire the windoor!")
src.state = "02"
if(src.secure)
@@ -166,7 +169,7 @@ obj/structure/windoor_assembly/Destroy()
//Removing wire from the assembly. Step 5 undone.
if(iswirecutter(W))
- playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 100, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 100, 1)
user.visible_message("[user] cuts the wires from the airlock assembly.", "You start to cut the wires from airlock assembly.")
if(do_after(user, src, 40))
@@ -183,7 +186,7 @@ obj/structure/windoor_assembly/Destroy()
//Adding airlock electronics for access. Step 6 complete.
else if(istype(W, /obj/item/weapon/circuitboard/airlock) && W:icon_state != "door_electronics_smoked")
if(user.drop_item(W, src)) // To prevent you using the airlock electronics on 2 windoors at once.
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
user.visible_message("[user] installs the electronics into the airlock assembly.", "You start to install electronics into the airlock assembly.")
if(do_after(user, src, 40))
@@ -199,7 +202,7 @@ obj/structure/windoor_assembly/Destroy()
//Screwdriver to remove airlock electronics. Step 6 undone.
else if(isscrewdriver(W) && electronics)
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 100, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 100, 1)
user.visible_message("[user] removes the electronics from the airlock assembly.", "You start to uninstall electronics from the airlock assembly.")
if(do_after(user, src, 40))
@@ -220,7 +223,7 @@ obj/structure/windoor_assembly/Destroy()
to_chat(usr, "The assembly is missing electronics.")
return
usr << browse(null, "window=windoor_access")
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 100, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 100, 1)
user.visible_message("[user] pries the windoor into the frame.", "You start prying the windoor into the frame.")
if(do_after(user, src, 40))
@@ -239,10 +242,15 @@ obj/structure/windoor_assembly/Destroy()
windoor.icon_state = "right[secure]open"
windoor.base_state = "right[secure]"
windoor.dir = src.dir
- windoor.setDensity(FALSE)
-
- windoor.req_access = src.electronics.conf_access
- windoor.electronics = src.electronics
+ windoor.setDensity(FALSE)
+ windoor.fingerprints += src.fingerprints
+ windoor.fingerprintshidden += src.fingerprintshidden
+ windoor.fingerprintslast = user.ckey
+ if(src.electronics.one_access)
+ windoor.req_access = null
+ windoor.req_one_access = src.electronics.conf_access
+ else
+ windoor.req_access = src.electronics.conf_access
src.electronics.forceMove(windoor)
qdel(src)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 8a25e902ef5..c54285b921e 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -22,7 +22,7 @@ var/list/one_way_windows
var/ini_dir = null //This really shouldn't exist, but it does and I don't want to risk deleting it because it's likely mapping-related
var/d_state = WINDOWLOOSEFRAME //Normal windows have one step (unanchor), reinforced windows have three
var/shardtype = /obj/item/weapon/shard
- var/sheettype = /obj/item/stack/sheet/glass/glass //Used for deconstruction
+ sheet_type = /obj/item/stack/sheet/glass/glass //Used for deconstruction
var/sheetamount = 1 //Number of sheets needed to build this window (determines how much shit is spawned via Destroy())
var/reinforced = 0 //Used for deconstruction steps
penetration_dampening = 1
@@ -67,6 +67,11 @@ var/list/one_way_windows
..()
examine_health(user)
+/obj/structure/window/AltClick(mob/user)
+ if(user.incapacitated() || !Adjacent(user))
+ return
+ rotate()
+
/obj/structure/window/proc/examine_health(mob/user)
if(!anchored)
to_chat(user, "It appears to be completely loose and movable.")
@@ -161,7 +166,7 @@ var/list/one_way_windows
if(O.onBuckledUserKick(H, src))
return //don't return 1! we will do the normal "touch" action if so!
- playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1)
+ playsound(src, 'sound/effects/glassknock.ogg', 100, 1)
H.do_attack_animation(src, H)
H.visible_message("\The [H] kicks \the [src].", \
@@ -227,7 +232,7 @@ var/list/one_way_windows
else if(usr.a_intent == I_HURT)
user.do_attack_animation(src, user)
user.delayNextAttack(10)
- playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1)
+ playsound(src, 'sound/effects/glassknock.ogg', 100, 1)
user.visible_message("[user] bangs against \the [src]!", \
"You bang against \the [src]!", \
"You hear banging.")
@@ -235,7 +240,7 @@ var/list/one_way_windows
//Knock against it
else
user.delayNextAttack(10)
- playsound(get_turf(src), 'sound/effects/glassknock.ogg', 50, 1)
+ playsound(src, 'sound/effects/glassknock.ogg', 50, 1)
user.visible_message("[user] knocks on \the [src].", \
"You knock on \the [src].", \
"You hear knocking.")
@@ -463,7 +468,7 @@ var/list/one_way_windows
playsound(src, 'sound/items/Welder.ogg', 100, 1)
user.visible_message("[user] disassembles \the [src].", \
"You disassemble \the [src].")
- drop_stack(sheettype, get_turf(src), sheetamount, user)
+ drop_stack(sheet_type, get_turf(src), sheetamount, user)
qdel(src)
return
else
@@ -493,7 +498,7 @@ var/list/one_way_windows
playsound(src, 'sound/items/Welder.ogg', 100, 1)
user.visible_message("[user] disassembles \the [src].", \
"You disassemble \the [src].")
- drop_stack(sheettype, get_turf(src), sheetamount, user)
+ drop_stack(sheet_type, get_turf(src), sheetamount, user)
Destroy()
return
else
@@ -561,7 +566,7 @@ var/list/one_way_windows
update_nearby_icons()
if(brokenup) //If the instruction we were sent clearly states we're breaking the window, not deleting it !
if(loc)
- playsound(get_turf(src), "shatter", 70, 1)
+ playsound(src, "shatter", 70, 1)
spawnBrokenPieces()
if(one_way)
one_way_windows.Remove(src)
@@ -633,7 +638,7 @@ var/list/one_way_windows
name = "reinforced window"
desc = "A window with a rod matrice. It looks more solid than the average window."
icon_state = "rwindow"
- sheettype = /obj/item/stack/sheet/glass/rglass
+ sheet_type = /obj/item/stack/sheet/glass/rglass
health = 40
d_state = WINDOWSECURE
reinforced = 1
@@ -649,7 +654,7 @@ var/list/one_way_windows
desc = "A window made out of a plasma-silicate alloy. It looks insanely tough to break and burn through."
icon_state = "plasmawindow"
shardtype = /obj/item/weapon/shard/plasma
- sheettype = /obj/item/stack/sheet/glass/plasmaglass
+ sheet_type = /obj/item/stack/sheet/glass/plasmaglass
health = 120
penetration_dampening = 5
@@ -662,10 +667,16 @@ var/list/one_way_windows
desc = "A window made out of a plasma-silicate alloy and a rod matrice. It looks hopelessly tough to break and is most likely nigh fireproof."
icon_state = "plasmarwindow"
shardtype = /obj/item/weapon/shard/plasma
- sheettype = /obj/item/stack/sheet/glass/plasmarglass
+ sheet_type = /obj/item/stack/sheet/glass/plasmarglass
health = 160
penetration_dampening = 7
+
+// Used on Packed ; smartglassified roundstart
+/obj/structure/window/reinforced/plasma/interogation_room/initialize()
+ smartwindow = new(src)
+ smartwindow.id_tag = "InterogationRoomIDTag"
+
/obj/structure/window/reinforced/plasma/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
@@ -675,7 +686,7 @@ var/list/one_way_windows
desc = "A window with a rod matrice. Its surface is completely tinted, making it opaque. Why not a wall ?"
icon_state = "twindow"
opacity = 1
- sheettype = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you
+ sheet_type = /obj/item/stack/sheet/glass/rglass //A glass type for this window doesn't seem to exist, so here's to you
/obj/structure/window/reinforced/tinted/frosted
@@ -683,7 +694,7 @@ var/list/one_way_windows
desc = "A window with a rod matrice. Its surface is completely tinted, making it opaque, and it's frosty. Why not an ice wall ?"
icon_state = "fwindow"
health = 30
- sheettype = /obj/item/stack/sheet/glass/rglass //Ditto above
+ sheet_type = /obj/item/stack/sheet/glass/rglass //Ditto above
/obj/structure/window/send_to_past(var/duration)
..()
diff --git a/code/game/say.dm b/code/game/say.dm
index 5dec825c19f..7e6d9b39ca9 100644
--- a/code/game/say.dm
+++ b/code/game/say.dm
@@ -102,11 +102,8 @@ var/list/freqtoname = list(
/atom/movable/proc/render_speech(var/datum/speech/speech)
say_testing(src, "render_speech() - Freq: [speech.frequency], radio=\ref[speech.radio]")
var/freqpart = ""
- var/radioicon = ""
if(speech.frequency)
- if(speech.radio)
- radioicon = "[bicon(speech.radio)]"
- freqpart = " [radioicon]\[[get_radio_name(speech.frequency)]\]"
+ freqpart = " \[[get_radio_name(speech.frequency)]\]"
speech.wrapper_classes.Add(get_radio_span(speech.frequency))
var/pooled=0
var/datum/speech/filtered_speech
diff --git a/code/game/shuttles/trade.dm b/code/game/shuttles/trade.dm
index be20b0d2c1c..c2840f48f78 100644
--- a/code/game/shuttles/trade.dm
+++ b/code/game/shuttles/trade.dm
@@ -14,7 +14,9 @@ var/global/datum/shuttle/trade/trade_shuttle = new(starting_area = /area/shuttle
stable = 0 //Don't stun everyone and don't throw anything when moving
can_rotate = 0 //Sleepers, body scanners and multi-tile airlocks aren't rotated properly
-
+/datum/shuttle/trade/proc/notify_port_toggled(var/reason)
+ for(var/obj/machinery/computer/shuttle_control/trade/T in control_consoles)
+ T.notify_port_toggled(reason)
/datum/shuttle/trade/initialize()
.=..()
@@ -33,6 +35,31 @@ var/global/datum/shuttle/trade/trade_shuttle = new(starting_area = /area/shuttle
link_to(trade_shuttle)
.=..()
+/obj/machinery/computer/shuttle_control/trade/proc/notify_port_toggled(var/reason)
+ if(!reason)
+ //Port opened
+ var/obj/item/weapon/paper/P = new(get_turf(src))
+ P.name = "NT Port Opened - [worldtime2text()]"
+ P.info = "This is official notification that sanctioned arrival of Vox trading vessels has resumed as normal."
+ P.update_icon()
+ playsound(get_turf(src), "sound/effects/fax.ogg", 50, 1)
+ var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
+ stampoverlay.icon_state = "paper_stamp-cent"
+ P.stamped += /obj/item/weapon/stamp
+ P.overlays += stampoverlay
+ P.stamps += "This paper has been stamped by the Central Command Quantum Relay."
+ if(reason)
+ var/obj/item/weapon/paper/P = new(get_turf(src))
+ P.name = "NT Port Closure - [worldtime2text()]"
+ P.info = "This is official notification that sanctioned arrival of Vox trading vessels has been indefinitely suspended with no guarantee of appeal. The provided justification was:
[reason]"
+ P.update_icon()
+ playsound(get_turf(src), "sound/effects/fax.ogg", 50, 1)
+ var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
+ stampoverlay.icon_state = "paper_stamp-cent"
+ P.stamped += /obj/item/weapon/stamp
+ P.overlays += stampoverlay
+ P.stamps += "This paper has been stamped by the Central Command Quantum Relay."
+
//code/game/objects/structures/docking_port.dm
/obj/docking_port/destination/trade/start
@@ -43,3 +70,6 @@ var/global/datum/shuttle/trade/trade_shuttle = new(starting_area = /area/shuttle
/obj/docking_port/destination/trade/transit
areaname = "hyperspace (trade shuttle)"
+
+/obj/docking_port/destination/trade/extra
+ areaname = "Casino"
\ No newline at end of file
diff --git a/code/game/shuttles/voxresearch_shuttle.dm b/code/game/shuttles/voxresearch_shuttle.dm
deleted file mode 100644
index 71e704edfcc..00000000000
--- a/code/game/shuttles/voxresearch_shuttle.dm
+++ /dev/null
@@ -1,23 +0,0 @@
-var/global/datum/shuttle/voxresearch/voxresearch_shuttle = new(starting_area = /area/shuttle/voxresearch/station)
-
-/datum/shuttle/voxresearch
- name = "Research Shuttle"
- can_link_to_computer = LINK_FREE
- req_access = 0
-
-/datum/shuttle/voxresearch/initialize()
- .=..()
- add_dock(/obj/docking_port/destination/voxresearch/station)
- add_dock(/obj/docking_port/destination/voxresearch/outpost)
-
-/obj/machinery/computer/shuttle_control/voxresearch/New() //Main shuttle_control code is in code/game/machinery/computer/shuttle_computer.dm
- link_to(voxresearch_shuttle)
- .=..()
-
-//code/game/objects/structures/docking_port.dm
-
-/obj/docking_port/destination/voxresearch/station
- areaname = "Genetic Research Station"
-
-/obj/docking_port/destination/voxresearch/outpost
- areaname = "Asteroid"
\ No newline at end of file
diff --git a/code/game/smoothwall.dm b/code/game/smoothwall.dm
index 2407924e866..4de9d6bc261 100644
--- a/code/game/smoothwall.dm
+++ b/code/game/smoothwall.dm
@@ -24,13 +24,11 @@
/atom/proc/isSmoothableNeighbor(atom/A)
if(!A)
- WARNING("[__FILE__]L[__LINE__]: atom/isSmoothableNeighbor given bad atom")
return 0
return isInTypes(A, canSmoothWith)
/turf/simulated/wall/isSmoothableNeighbor(atom/A)
if(!A)
- WARNING("[__FILE__]L[__LINE__]: turf/isSmoothableNeighbor given bad atom")
return 0
if(isInTypes(A, canSmoothWith))
// COLON OPERATORS ARE TERRIBLE BUT I HAVE NO CHOICE
diff --git a/code/game/sound.dm b/code/game/sound.dm
index c0fa4516b29..3773c5b4ca5 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -28,7 +28,7 @@ var/list/machete_throw_hit_sound = list('sound/weapons/hfmachete_throw_hit01.ogg
//gas_modified controls if a sound is affected by how much gas there is in the atmosphere of the source
//space sounds have no gas modification, for example. Though >space sounds
-/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/gas_modified = 1, var/channel = 0)
+/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/gas_modified = 1, var/channel = 0,var/wait = FALSE)
var/turf/turf_source = get_turf(source)
ASSERT(!isnull(turf_source))
@@ -79,13 +79,13 @@ var/list/machete_throw_hit_sound = list('sound/weapons/hfmachete_throw_hit01.ogg
if (player_turf && turf_source && player_turf.z == turf_source.z)
if(get_dist(player_turf, turf_source) <= Dist)
- player.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, gas_modified, channel)
+ player.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, gas_modified, channel,wait)
var/const/FALLOFF_SOUNDS = 1
var/const/SURROUND_CAP = 7
#define MIN_SOUND_PRESSURE 2 //2 kPa of pressure required to at least hear sound
-/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, gas_modified, var/channel = 0)
+/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, gas_modified, var/channel = 0,var/wait = FALSE)
if(!src.client)
return
@@ -111,7 +111,7 @@ var/const/SURROUND_CAP = 7
soundin = get_sfx(soundin)
- var/sound/S = sound(soundin, 0, 0, channel, vol)
+ var/sound/S = sound(soundin, 0, wait, channel, vol,)
if (vary)
if(frequency)
diff --git a/code/game/striketeams/emergency_response_team.dm b/code/game/striketeams/emergency_response_team.dm
index 06d6a0b08b6..ad7ca04e391 100644
--- a/code/game/striketeams/emergency_response_team.dm
+++ b/code/game/striketeams/emergency_response_team.dm
@@ -1,7 +1,6 @@
//ERT
var/list/response_team_members = list()
-var/list/distributed_ert_suits = list()
/datum/striketeam/ert
striketeam_name = TEAM_ERT
diff --git a/code/game/striketeams/striketeam_datums.dm b/code/game/striketeams/striketeam_datums.dm
index 0d55bfddb8c..ef165f82ad6 100644
--- a/code/game/striketeams/striketeam_datums.dm
+++ b/code/game/striketeams/striketeam_datums.dm
@@ -144,7 +144,7 @@ var/list/sent_strike_teams = list()
new_commando.key = applicant.key
- new_commando.update_action_buttons(1)
+ new_commando.update_action_buttons_icon()
new_commando.mind.store_memory("Mission:[mission].")
greet_commando(new_commando)
diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm
index 1786100263a..92f262e784a 100644
--- a/code/game/supplyshuttle.dm
+++ b/code/game/supplyshuttle.dm
@@ -212,8 +212,14 @@ var/datum/controller/supply_shuttle/supply_shuttle = new
var/datum/supply_order/SO = S
var/datum/supply_packs/SP = SO.object
-
- var/atom/A = new SP.containertype(pickedloc)
+ var/atom/A
+ if(Holiday == APRIL_FOOLS_DAY && prob(10))
+ if(prob(5))
+ A = new /mob/living/simple_animal/hostile/mimic/crate/chest(pickedloc)
+ else
+ A = new /mob/living/simple_animal/hostile/mimic/crate(pickedloc)
+ else
+ A = new SP.containertype(pickedloc)
A.name = "[SP.containername] [SO.comment ? "([SO.comment])":"" ]"
//supply manifest generation begin
@@ -251,6 +257,8 @@ var/datum/controller/supply_shuttle/supply_shuttle = new
B2:amount = SP.amount
slip.info += "
[B2.name]
" //add the item to the manifest
+ SP.post_creation(A)
+
//manifest finalisation
slip.info += {"
diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm
index f83d4891784..d40b92ff256 100644
--- a/code/game/turfs/simulated.dm
+++ b/code/game/turfs/simulated.dm
@@ -30,8 +30,8 @@
if (istype(A,/mob/living/carbon))
var/mob/living/carbon/M = A
- if(M.lying)
- return
+ if(!M.on_foot())
+ return ..()
if(istype(M, /mob/living/carbon/human))
var/mob/living/carbon/human/H = M
@@ -68,14 +68,6 @@
if (H.Slip(4, 5))
step(H, H.dir)
to_chat(H, "You tripped over your hair!")
-
- //Anything beyond that point will not fire if the mob isn't physically walking here
- if(!M.on_foot()) //Checks lying, flying and locked.to
- return ..()
-
- //And anything beyond that point will not fire for slimes
- if(isslime(M)) //Slimes just don't slip, end of story
- return ..()
..()
//returns 1 if made bloody, returns 0 otherwise
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index 1811d95f9a2..0ac39d57fc7 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -212,7 +212,7 @@ turf/simulated/floor/update_icon()
if("bananium")
if(!spam_flag)
spam_flag = 1
- playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1)
+ playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
spawn(20)
spam_flag = 0
..()
@@ -310,7 +310,7 @@ turf/simulated/floor/update_icon()
return //you can't break legos
if(material=="phazon") //Phazon shatters
spawn(rand(2,10))
- playsound(get_turf(src), "shatter", 70, 1)
+ playsound(src, "shatter", 70, 1)
make_plating()
return
@@ -647,7 +647,7 @@ turf/simulated/floor/update_icon()
if("bananium")
if(!spam_flag)
spam_flag = 1
- playsound(get_turf(src), "clownstep", 50, 1)
+ playsound(src, "clownstep", 50, 1)
spawn(20)
spam_flag = 0
if("uranium")
diff --git a/code/game/turfs/simulated/floor_glass.dm b/code/game/turfs/simulated/floor_glass.dm
index 77b16c58808..cd2857c2410 100644
--- a/code/game/turfs/simulated/floor_glass.dm
+++ b/code/game/turfs/simulated/floor_glass.dm
@@ -60,7 +60,7 @@
/turf/simulated/floor/glass/proc/break_turf(var/no_teleport=FALSE)
if(loc)
- playsound(get_turf(src), "shatter", 70, 1)
+ playsound(src, "shatter", 70, 1)
//ReplaceWithLattice()
// TODO: Break all pipes/wires?
// FIXME: Animations are fucked, controversial, I want to move on to other shit.
@@ -215,7 +215,7 @@
else if(usr.a_intent == I_HURT)
user.do_attack_animation(src, user)
user.delayNextAttack(10)
- playsound(get_turf(src), 'sound/effects/glassknock.ogg', 100, 1)
+ playsound(src, 'sound/effects/glassknock.ogg', 100, 1)
user.visible_message("[user] bangs against \the [src]!", \
"You bang against \the [src]!", \
"You hear banging.")
@@ -224,7 +224,7 @@
//Knock against it
else
user.delayNextAttack(10)
- playsound(get_turf(src), 'sound/effects/glassknock.ogg', 50, 1)
+ playsound(src, 'sound/effects/glassknock.ogg', 50, 1)
user.visible_message("[user] knocks on \the [src].", \
"You knock on \the [src].", \
"You hear knocking.")
diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm
index 57ecb829846..018916ee5d9 100644
--- a/code/game/turfs/simulated/floor_types.dm
+++ b/code/game/turfs/simulated/floor_types.dm
@@ -112,7 +112,7 @@
return
if(iswrench(C))
to_chat(user, "Removing rods...")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 80, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 80, 1)
if(do_after(user, src, 30) && istype(src, /turf/simulated/floor/engine)) // Somehow changing the turf does NOT kill the current running proc.
new /obj/item/stack/rods(src, 2)
ChangeTurf(/turf/simulated/floor)
diff --git a/code/game/turfs/simulated/invulnerable_wall.dm b/code/game/turfs/simulated/invulnerable_wall.dm
index 3be6af28b2b..934a84aaa9d 100644
--- a/code/game/turfs/simulated/invulnerable_wall.dm
+++ b/code/game/turfs/simulated/invulnerable_wall.dm
@@ -63,4 +63,10 @@
name = "blue ice wall"
desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color."
icon_state = "ice"
- walltype = "ice"
\ No newline at end of file
+ walltype = "ice"
+
+/turf/simulated/wall/invulnerable/r_wall
+ name = "reinforced wall"
+ desc = "A huge chunk of reinforced metal and anchored rods used to seperate rooms and keep all but the most equipped crewmen out."
+ icon_state = "r_wall"
+ walltype = "rwall"
\ No newline at end of file
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 7ff0dc7c7a1..0703a505a90 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -13,7 +13,8 @@
var/walltype = "metal"
var/hardness = 60 //Higher numbers are harder (so that it actually makes sense). Walls are 60 hardness, reinforced walls are 90 hardness. No hardness over 100, PLEASE
- var/engraving, engraving_quality //engraving on the wall
+ var/engraving
+ var/engraving_quality //engraving on the wall
var/del_suppress_resmoothing = 0 // Do not resmooth neighbors on Destroy. (smoothwall.dm)
var/dismantle_type = /turf/simulated/floor/plating
diff --git a/code/game/turfs/simulated/walls_mineral.dm b/code/game/turfs/simulated/walls_mineral.dm
index febe145265a..18266bbb0f1 100644
--- a/code/game/turfs/simulated/walls_mineral.dm
+++ b/code/game/turfs/simulated/walls_mineral.dm
@@ -28,10 +28,8 @@
/turf/simulated/wall/mineral/wood/ex_act(var/severity)
if(severity < 3)
- ChangeTurf(get_underlying_turf())
getFromPool(/obj/item/stack/sheet/wood, src, 2)
- else
- dismantle_wall()
+ ..()
/turf/simulated/wall/mineral/brick
name = "brick wall"
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 77524c1617c..95a885ec4e1 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -13,17 +13,30 @@
dynamic_lighting = 0
luminosity = 1
can_border_transition = 1
+ var/static/list/parallax_appearances
/turf/space/New()
if(loc)
var/area/A = loc
A.area_turfs += src
- icon_state = "[((x + y) ^ ~(x * y) + z) % 25]"
- var/image/I = image('icons/turf/space_parallax1.dmi',"[icon_state]")
- I.plane = SPACE_DUST_PLANE
- I.alpha = 80
- I.blend_mode = BLEND_ADD
- overlays += I
+
+/turf/space/initialize()
+ if(!parallax_appearances)
+ parallax_appearances = list()
+ for(var/i in 0 to 25)
+ var/I = "[i]"
+ icon_state = I
+ var/image/parallax_overlay = image('icons/turf/space_parallax1.dmi', I)
+ parallax_overlay.plane = SPACE_DUST_PLANE
+ parallax_overlay.alpha = 80
+ parallax_overlay.blend_mode = BLEND_ADD
+ overlays += parallax_overlay
+ parallax_appearances[I] = appearance
+ overlays.Cut()
+ appearance = parallax_appearances["[((x + y) ^ ~(x * y) + z) % 26]"]
+
+/turf/space/spawned_by_map_element(var/datum/map_element/ME, var/list/objects)
+ initialize()
/turf/space/attack_paw(mob/user as mob)
return src.attack_hand(user)
@@ -185,5 +198,8 @@
/turf/space/void/New()
return
+/turf/space/void/initialize()
+ return
+
/turf/space/has_gravity()
return 0
diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm
index 696598351f9..3443234fee8 100644
--- a/code/game/turfs/space/transit.dm
+++ b/code/game/turfs/space/transit.dm
@@ -9,6 +9,9 @@
update_icon()
+/turf/space/transit/initialize()
+ return
+
/turf/space/transit/update_icon()
icon_state = ""
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 1a5f9ce800e..580a968f8f2 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -85,9 +85,6 @@
src.Entered(AM)
return
-/turf/proc/initialize()
- return
-
/turf/ex_act(severity)
return 0
@@ -414,6 +411,7 @@
// zone.SetStatus(ZONE_ACTIVE)
var/turf/W = new N(src)
+ W.initialize()
if(tell_universe)
universe.OnTurfChange(W)
@@ -532,8 +530,9 @@
spawn(0)
M.take_damage(100, "brute")
-/turf/proc/Bless()
- turf_flags |= NOJAUNT
+/turf/bless()
+ holy = 1
+ ..()
/////////////////////////////////////////////////////////////////////////
// Navigation procs
@@ -707,11 +706,6 @@
holomap_data = list()
holomap_data += I
-// Calls the above, but only if the game has not yet started.
-/turf/proc/soft_add_holomap(var/atom/movable/AM)
- if (!ticker || ticker.current_state != GAME_STATE_PLAYING)
- add_holomap(AM)
-
// Goddamnit BYOND.
// So for some reason, I incurred a rendering issue with the usage of FLOAT_PLANE for the holomap plane.
// (For some reason the existance of underlays prevented the main icon and overlays to render)
diff --git a/code/game/turfs/unsimulated/snow.dm b/code/game/turfs/unsimulated/snow.dm
index 69073e5c6ee..857a2092a7e 100644
--- a/code/game/turfs/unsimulated/snow.dm
+++ b/code/game/turfs/unsimulated/snow.dm
@@ -1,6 +1,6 @@
//Arctic atmospheric defines
-#define ARCTIC_ATMOSPHERE 68.13 //Pretty low pressure, very thin air, might be hard to breathe, but not enough for pressure damage
+#define ARCTIC_ATMOSPHERE 90.13
#define T_ARCTIC 223.65 //- 49.5 Celcius, taken from South Pole averages
#define MOLES_ARCTICSTANDARD (ARCTIC_ATMOSPHERE*CELL_VOLUME/(T_ARCTIC*R_IDEAL_GAS_EQUATION)) //Note : Open air tiles obviously aren't 2.5 meters in height, but abstracted for now with infinite atmos
#define MOLES_O2STANDARD_ARCTIC MOLES_ARCTICSTANDARD*O2STANDARD //O2 standard value (21%)
@@ -18,25 +18,25 @@
can_border_transition = 1
dynamic_lighting = 0
luminosity = 1
-
+ plane = PLATING_PLANE
var/snowballs = 0
- var/global/list/snow_layers = list()
- var/global/list/dirt_layers = list()
+ var/global/list/icon_state_to_appearance = list()
/turf/unsimulated/floor/snow/New()
..()
-
icon_state = "snow[rand(0, 6)]"
- relativewall_neighbours()
+ if(icon_state_to_appearance[icon_state])
+ appearance = icon_state_to_appearance[icon_state]
+ else
+ var/image/snowfx1 = image('icons/turf/snowfx.dmi', "snowlayer1",SNOW_OVERLAY_LAYER)
+ var/image/snowfx2 = image('icons/turf/snowfx.dmi', "snowlayer2",SNOW_OVERLAY_LAYER)
+ snowfx1.plane = EFFECTS_PLANE
+ snowfx2.plane = EFFECTS_PLANE
+ overlays += snowfx1
+ overlays += snowfx2
+ icon_state_to_appearance[icon_state] = appearance
snowballs = rand(5, 10) //Used to be (30, 50). A quick way to overload the server with atom instances.
- update_icon()
-
-/turf/unsimulated/floor/snow/relativewall_neighbours()
- for(var/direction in alldirs)
- var/turf/adj_tile = get_step(src, direction)
- if(istype(adj_tile, /turf/unsimulated/floor/snow))
- adj_tile.update_icon()
/turf/unsimulated/floor/snow/attackby(obj/item/weapon/W as obj, mob/user as mob)
@@ -49,7 +49,7 @@
if(do_after(user, src, 20))
user.visible_message("[user] digs out some snow with \the [W].", \
"You dig out some snow with \the [W].")
- extract_snowballs(5, 0, user)
+ extract_snowballs(5, FALSE, user)
/turf/unsimulated/floor/snow/attack_hand(mob/user as mob)
@@ -60,11 +60,11 @@
if(do_after(user, src, 5))
user.visible_message("[user] finishes forming a snowball.", \
"You finish forming a snowball.")
- extract_snowballs(1, 1, user)
+ extract_snowballs(1, TRUE, user)
..()
-/turf/unsimulated/floor/snow/proc/extract_snowballs(var/snowball_amount = 0, var/pick_up = 0, var/mob/user)
+/turf/unsimulated/floor/snow/proc/extract_snowballs(var/snowball_amount = 0, var/pick_up = FALSE, var/mob/user)
if(!snowball_amount)
return
@@ -81,15 +81,15 @@
snowballs--
- if(!snowballs) //We're out of snow, turn into a permafrost tile
- ChangeTurf(/turf/unsimulated/floor/snow/permafrost)
+ if(!snowballs)
+ return
//In the future, catwalks should be the base to build in the arctic, not lattices
//This would however require a decent rework of floor construction and deconstruction
-/turf/unsimulated/floor/snow/permafrost/canBuildCatwalk()
+/turf/unsimulated/floor/snow/canBuildCatwalk()
return BUILD_FAILURE
-/turf/unsimulated/floor/snow/permafrost/canBuildLattice()
+/turf/unsimulated/floor/snow/canBuildLattice()
if(x >= (world.maxx - TRANSITIONEDGE) || x <= TRANSITIONEDGE)
return BUILD_FAILURE
else if (y >= (world.maxy - TRANSITIONEDGE || y <= TRANSITIONEDGE ))
@@ -98,7 +98,7 @@
return BUILD_SUCCESS
return BUILD_FAILURE
-/turf/unsimulated/floor/snow/permafrost/canBuildPlating()
+/turf/unsimulated/floor/snow/canBuildPlating()
if(x >= (world.maxx - TRANSITIONEDGE) || x <= TRANSITIONEDGE)
return BUILD_FAILURE
else if (y >= (world.maxy - TRANSITIONEDGE || y <= TRANSITIONEDGE ))
@@ -110,116 +110,7 @@
/turf/unsimulated/floor/snow/Entered(mob/user)
..()
if(isliving(user) && !user.locked_to && !user.lying && !user.flying)
- playsound(get_turf(src), pick(snowsound), 10, 1, -1, channel = 123)
+ playsound(src, pick(snowsound), 10, 1, -1, channel = 123)
-//This shit's fucked, should use relativewall. Problem is, relativewall is terrible and doesn't include diagonal directions
-//So in short relativewall needs to be reworked, along with all things relying on it. Fun times ahead
-/turf/unsimulated/floor/snow/update_icon()
- if(overlays.len > 2) //?
- overlays.Cut()
- if(!snow_layers.len)
- snow_layers["1"] = image('icons/turf/snowfx.dmi', "snowlayer1", 17)
- snow_layers["2"] = image('icons/turf/snowfx.dmi', "snowlayer2", 17)
- if(!dirt_layers.len)
- for(var/dirtdir in alldirs)
- dirt_layers["side[dirtdir]"] = image('icons/turf/new_snow.dmi', "permafrost_side" ,dir = dirtdir)
- for(var/diagdir in diagonal)
- dirt_layers["diag[diagdir]"] = image('icons/turf/new_snow.dmi', "permafrost_corner", dir = diagdir, layer = 2.1)
- dirt_layers["snow[diagdir]"] = image('icons/turf/new_snow.dmi', "permafrost", dir = diagdir)
- for(var/dirtdir in cardinal)
- dirt_layers["snow[dirtdir]"] = image('icons/turf/new_snow.dmi', "permafrost_half", dir = dirtdir)
- var/realdir = null
- switch(dirtdir)
- if(NORTH)
- realdir = EAST|SOUTH|WEST
- if(SOUTH)
- realdir = WEST|NORTH|EAST
- if(EAST)
- realdir = SOUTH|WEST|NORTH
- if(WEST)
- realdir = NORTH|EAST|SOUTH
- dirt_layers["snow[realdir]"] = image('icons/turf/new_snow.dmi', "permafrost_tjunction", dir = dirtdir)
- dirt_layers["snow15"] = image('icons/turf/new_snow.dmi', "permafrost_crossroads")
- dirt_layers["snow0"] = image('icons/turf/new_snow.dmi', "permafrost_circle")
- dirt_layers["snow3"] = image('icons/turf/new_snow.dmi', "permafrost", dir = NORTH)
- dirt_layers["snow12"] = image('icons/turf/new_snow.dmi', "permafrost", dir = WEST)
-
- //Projecting snowfall on adjacent tiles, might remove this eventually
- var/lights_on = 0
- for(var/direction in alldirs)
- if(!istype(get_step(src, direction), /turf/unsimulated/floor/snow))
- if(istype(get_step(src, direction), /turf/simulated/floor)) //Luminosity on tiles adjacent to snow
- lights_on = 1
- overlays += dirt_layers["side[direction]"]
- var/image/snow1 = snow_layers["1"]
- var/image/snow2 = snow_layers["2"]
- snow1.alpha = 255
- snow2.alpha = 255
- switch(direction)
- if(1)
- snow1.pixel_y = WORLD_ICON_SIZE
- overlays += snow1
- snow2.pixel_y = WORLD_ICON_SIZE
- overlays += snow2
- if(2)
- snow1.pixel_y = -WORLD_ICON_SIZE
- overlays += snow1
- snow2.pixel_y = -WORLD_ICON_SIZE
- overlays += snow2
- if(4)
- snow1.pixel_x = WORLD_ICON_SIZE
- overlays += snow1
- snow2.pixel_x = WORLD_ICON_SIZE
- overlays += snow2
- if(8)
- snow1.pixel_x = -WORLD_ICON_SIZE
- overlays += snow1
- snow2.pixel_x = -WORLD_ICON_SIZE
- overlays += snow2
- snow1.alpha = 64
- snow2.alpha = 64
- snow1.pixel_x = 0
- snow2.pixel_x = 0
- snow1.pixel_y = 0
- snow2.pixel_y = 0
- if(lights_on)
- set_light(5, 0.5)
- else
- set_light(0, 0)
- overlays += snow_layers["1"]
- overlays += snow_layers["2"]
-
-//Permafrost is frozen dirt, this shows up below the snow tiles when you dig them out
/turf/unsimulated/floor/snow/permafrost
-
- name = "permafrost"
- desc = "A layer of dirt permanently exposed to temperatures below freezing. If exposed to snow fall, it will likely be covered in snow again given a few days."
icon_state = "permafrost_full"
- canSmoothWith = "/turf/unsimulated/floor/snow/permafrost"
-
-/turf/unsimulated/floor/snow/permafrost/New()
-
- ..()
-
- snowballs = 0
-
-/turf/unsimulated/floor/snow/permafrost/update_icon()
-
- ..()
-
- var/junction = findSmoothingNeighbors()
- var/dircount = 0
- for(var/direction in diagonal)
- if(istype(get_step(src, direction), /turf/unsimulated/floor/snow/permafrost))
- if((direction & junction) == direction)
- overlays += dirt_layers["diag[direction]"]
- dircount++
- if(dircount == 4)
- overlays.Cut()
- icon_state = "permafrost_full"
- overlays += snow_layers["1"]
- overlays += snow_layers["2"]
- else if(junction)
- overlays += dirt_layers["snow[junction]"]
- else
- overlays += dirt_layers["snow0"]
diff --git a/code/game/turfs/unsimulated/walls.dm b/code/game/turfs/unsimulated/walls.dm
index aed15bd0c35..60db4c85113 100644
--- a/code/game/turfs/unsimulated/walls.dm
+++ b/code/game/turfs/unsimulated/walls.dm
@@ -50,13 +50,16 @@ turf/unsimulated/wall/splashscreen
plane = EFFECTS_PLANE
canSmoothWith = null
- New()
- var/path = "icons/splashworks/"
- var/list/filenames = flist(path)
- for(var/filename in filenames)
- if(copytext(filename, length(filename)) == "/")
- filenames -= filename
- icon = file("[path][pick(filenames)]")
+/turf/unsimulated/wall/splashscreen/New()
+ if(SNOW_THEME)
+ icon = 'icons/snowstation.gif' // not in the splashworks file so it doesn't appear in other cases
+ return
+ var/path = "icons/splashworks/"
+ var/list/filenames = flist(path)
+ for(var/filename in filenames)
+ if(copytext(filename, length(filename)) == "/")
+ filenames -= filename
+ icon = file("[path][pick(filenames)]")
/turf/unsimulated/wall/other
icon_state = "r_wall"
@@ -90,4 +93,4 @@ turf/unsimulated/wall/splashscreen
..()
if(prob(80))
- icon_state = "evilwall_[rand(1,8)]"
+ icon_state = "evilwall_[rand(1,8)]"
\ No newline at end of file
diff --git a/code/game/verbs/suicide.dm b/code/game/verbs/suicide.dm
index e554175f4b9..02251f39672 100644
--- a/code/game/verbs/suicide.dm
+++ b/code/game/verbs/suicide.dm
@@ -246,7 +246,7 @@
setCloneLoss(100)
updatehealth()
-//Default for all simple animals, using the Die() proc. Custom cases below
+//Default for all simple animals, using the death() proc. Custom cases below
/mob/living/simple_animal/attempt_suicide(forced = 0, suicide_set = 1)
if(!forced)
@@ -266,4 +266,4 @@
visible_message(pick("[src] suddenly starts thrashing around wildly! It looks like \he's trying to commit suicide.", \
"[src] suddenly starts mauling \himself! It looks like \he's trying to commit suicide."))
- Die()
+ death()
diff --git a/code/libs/Get Flat Icon/Get Flat Icon.dm b/code/libs/Get Flat Icon/Get Flat Icon.dm
index 11cd7becce6..b0e7afa6fd7 100644
--- a/code/libs/Get Flat Icon/Get Flat Icon.dm
+++ b/code/libs/Get Flat Icon/Get Flat Icon.dm
@@ -56,7 +56,6 @@ var/list/exception = list(
proc/getFlatIcon(atom/A, dir, cache=1, exact=0) // 1 = use cache, 2 = override cache, 0 = ignore cache //exact = 1 means the atom won't be rotated if it's a lying mob/living/carbon
- var/list/layers = list() // Associative list of [overlay = layer]
var/hash = "" // Hash of overlay combination
if(is_type_in_list(A, directional)&&!is_type_in_list(A, exception))
@@ -82,65 +81,9 @@ proc/getFlatIcon(atom/A, dir, cache=1, exact=0) // 1 = use cache, 2 = override c
var/image/copy = image(icon=A.icon,icon_state=A.icon_state,layer=A.layer,dir=dir)
initialimage[copy] = A.layer
-
- // Loop through the underlays, then overlays, sorting them into the layers list
- var/list/process = A.underlays // Current list being processed
- var/processSubset=0 // Which list is being processed: 0 = underlays, 1 = overlays
-
- var/currentIndex=1 // index of 'current' in list being processed
- var/currentOverlay // Current overlay being sorted
- var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER)
-
- var/compareOverlay // The overlay that the current overlay is being compared against
- var/compareIndex // The index in the layers list of 'compare'
-
- var/list/underlaysort = list()
- var/list/overlaysort = list()
- var/list/sorting = underlaysort
-
- while(TRUE)
- if(currentIndex<=process.len)
- //All this does is find the appropriate layer and image
- currentOverlay = process[currentIndex]
- currentLayer = currentOverlay:layer
- if(currentLayer<0) // Special case for FLY_LAYER
- ASSERT(currentLayer > -1000)
- if(processSubset == 0) // Underlay
- currentLayer = A.layer+currentLayer/1000
- else // Overlay
- currentLayer = A.layer+(1000+currentLayer)/1000
-
- //Next is a simple sort algorithm to place the overlay by layer
- if(!sorting.len)
- sorting[currentOverlay] = currentLayer
- currentIndex++
- continue
-
- for(compareIndex=1,compareIndex<=sorting.len,compareIndex++)
- compareOverlay = sorting[compareIndex]
- if(currentLayer < sorting[compareOverlay]) // Associated value is the calculated layer
- sorting.Insert(compareIndex,currentOverlay)
- sorting[currentOverlay] = currentLayer
- break
- if(compareIndex>sorting.len) // Reached end of list without inserting
- sorting[currentOverlay]=currentLayer // Place at end
-
- currentIndex++
-
- if(currentIndex>process.len)
- if(processSubset == 0) // Switch to overlays
- currentIndex = 1
- processSubset = 1
- process = A.overlays
- sorting = overlaysort
- else // All done
- break
-
- //Get flat icon previously understood layers as interspersing
- //and could render overlays above the atom's icon before this following modification
- layers = underlaysort
+ var/list/layers = plane_layer_sort(A.underlays)
layers += initialimage
- layers += overlaysort
+ layers += plane_layer_sort(A.overlays)
if(cache!=0) // If cache is NOT disabled
// Create a hash value to represent this specific flattened icon
diff --git a/code/modules/Economy/Accounts.dm b/code/modules/Economy/Accounts.dm
index 579d0443f80..3a5771b614f 100644
--- a/code/modules/Economy/Accounts.dm
+++ b/code/modules/Economy/Accounts.dm
@@ -10,6 +10,7 @@ var/global/next_account_number = 0
var/global/obj/machinery/account_database/centcomm_account_db
var/global/datum/money_account/vendor_account
var/global/list/all_money_accounts = list()
+var/global/datum/money_account/trader_account
/proc/create_station_account()
if(!station_account)
diff --git a/code/modules/Economy/POS.dm b/code/modules/Economy/POS.dm
index 076ec93c102..864a3232481 100644
--- a/code/modules/Economy/POS.dm
+++ b/code/modules/Economy/POS.dm
@@ -175,8 +175,8 @@ var/const/POS_HEADER = {"
var/receipt = {"[RECEIPT_HEADER]
POINT OF SALE #[id]
Paying to: [linked_account.owner_name]
Cashier: [logged_in] "}
-
- receipt += areaMaster.name
+ var/area/this_area = get_area(src)
+ receipt += this_area.name
receipt += "
"
receipt += {"
[worldtime2text()], [current_date_string]
@@ -225,8 +225,8 @@ var/const/POS_HEADER = {"
POINT OF SALE #[id]
Paying to: [linked_account.owner_name]
Cashier: [logged_in] "}
-
- receipt += areaMaster.name
+ var/area/this_area = get_area(src)
+ receipt += this_area.name
receipt += ""
receipt += {"")
log_admin("World Reboot triggered by [key_name(usr)]!")
diff --git a/code/modules/admin/admin_ranks.dm b/code/modules/admin/admin_ranks.dm
index c1ed55afe73..16deda7e8cd 100644
--- a/code/modules/admin/admin_ranks.dm
+++ b/code/modules/admin/admin_ranks.dm
@@ -74,7 +74,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights
var/msg = "Permission Sets Built:\n"
for(var/rank in admin_ranks)
msg += "\t[rank] - [admin_ranks[rank]]\n"
- testing(msg)
+ //testing(msg)
#endif
@@ -174,7 +174,7 @@ var/list/admin_ranks = list() //list of all ranks with associated rights
if(D)
rank = D.rank
msg += "\t[ckey] - [rank]\n"
- testing(msg)
+ //testing(msg)
#endif
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 7b850af1b66..827811631a1 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -37,6 +37,10 @@
log_admin("[key_name(usr)] has spawned a nuke team.")
if(!src.makeNukeTeam())
to_chat(usr, "Unfortunately there weren't enough candidates available.")
+ if("8")
+ log_admin("[key_name(usr)] has spawned a count of vampires.")
+ if(!src.makeVampires())
+ to_chat(usr, "Unfortunately there weren't enough candidates available.")
if("9")
log_admin("[key_name(usr)] has spawned aliens.")
if(!src.makeAliens())
@@ -81,7 +85,7 @@
lawtype=lawtypes[lawtype]
if(lawtype == null)
return
- testing("Lawtype: [lawtype]")
+ //testing("Lawtype: [lawtype]")
if(lawtype==1)
lawtype=text2num(input("Enter desired law priority. (15-50)","Priority", 15) as num)
lawtype=Clamp(lawtype,15,50)
@@ -100,7 +104,7 @@
var/lawtype = input("Select a lawset.","Law Type",1) as null|anything in lawtypes
if(lawtype == null)
return
- testing("Lawtype: [lawtype]")
+ //testing("Lawtype: [lawtype]")
var/law_zeroth=null
var/law_zeroth_borg=null
@@ -459,7 +463,9 @@
else if(href_list["delay_round_end"])
if(!check_rights(R_SERVER))
return
-
+ var/response = alert("Toggle round end delay? It is currently [ticker.delay_end?"delayed":"not delayed"]","Toggle round end delay","Yes","No")
+ if(response != "Yes")
+ return
ticker.delay_end = !ticker.delay_end
log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
message_admins("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1)
@@ -2336,7 +2342,7 @@
to_chat(H, "Your ass was just blown off by an unknown force!")
log_admin("[key_name(H)] was buttblasted by [src.owner]")
message_admins("[key_name(H)] was buttblasted by [src.owner]")
- playsound(get_turf(H), 'sound/effects/superfart.ogg', 50, 1)
+ playsound(H, 'sound/effects/superfart.ogg', 50, 1)
H.apply_damage(40, BRUTE, LIMB_GROIN)
H.apply_damage(10, BURN, LIMB_GROIN)
H.Knockdown(8)
@@ -2530,7 +2536,7 @@
base_law_type = selected_law
subject = "AIs and Cyborgs"
if("mommi")
- mommi_base_law_type = selected_law
+ mommi_laws["Default"] = selected_law
subject = "MoMMIs"
to_chat(usr, "New [subject] will spawn with the [selected_law] lawset.")
log_admin("[key_name(src.owner)] set the default laws of [subject] to: [selected_law]")
@@ -3319,8 +3325,12 @@
feedback_add_details("admin_secrets_fun_used","HW")
var/choice = input("Are you sure you want to wake up the space indian burial ground?. Misuse of this could result in removal of flags or hilarity.") in list("Get our spook on", "Cancel")
if(choice != "Cancel")
- SetUniversalState(/datum/universal_state/halloween, 1, 1)
- message_admins("[key_name_admin(usr)] has pressed the halloween fun button. Truly [key_name_admin(usr)] is the spookiest.")
+ var/list/given_args = list()
+ var/number = input("How many mobs do you want per area?", 10) as num
+ if(number)
+ given_args["mobs"] = number
+ SetUniversalState(/datum/universal_state/halloween, 1, 1, given_args)
+ message_admins("[key_name_admin(usr)] has pressed the halloween fun button with [number] amount of mobs per area. Truly [key_name_admin(usr)] is the spookiest.")
if("christmas_vic")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","XMS")
@@ -3562,6 +3572,7 @@
"incinerator" = LOC_INCIN,
"chapel" = LOC_CHAPEL,
"library" = LOC_LIBRARY,
+ "hydroponics" = LOC_HYDRO,
"vault" = LOC_VAULT,
"technical storage" = LOC_TECH,
)
@@ -3577,6 +3588,7 @@
"roaches" = VERM_ROACHES,
"gremlins" = VERM_GREMLINS,
"bees" = VERM_BEES,
+ "hornets" = VERM_HORNETS,
)
var/ov = vermins[input("What vermin should infest the station?", "Vermin Infestation") in vermins]
var/ol = locations[input("Where should they spawn?", "Vermin Infestation") in locations]
@@ -4847,7 +4859,7 @@
(SM) "
text += "Adepts:
[h_style]
@@ -355,8 +357,6 @@ var/const/MAX_SAVE_SLOTS = 8
[(tooltips) ? "Yes" : "No"] Adminhelp Special Tab:[special_popup ? "Yes" : "No"]
- Character Records:
- [jobban_isbanned(user, "Records") ? "Banned" : "Set "]
Attack Animations:[attack_animation ? (attack_animation == ITEM_ANIMATION? "Item Anim." : "Person Anim.") : "No"]
@@ -637,6 +637,8 @@ var/const/MAX_SAVE_SLOTS = 8
HTML += ShowDisabilityState(user,DISABILITY_FLAG_BLIND, "Blind")
HTML += ShowDisabilityState(user,DISABILITY_FLAG_MUTE, "Mute")
HTML += ShowDisabilityState(user,DISABILITY_FLAG_VEGAN, "Vegan")
+ HTML += ShowDisabilityState(user,DISABILITY_FLAG_ASTHMA, "Asthma")
+ HTML += ShowDisabilityState(user,DISABILITY_FLAG_LACTOSE, "Lactose Intolerant")
/*HTML += ShowDisabilityState(user,DISABILITY_FLAG_COUGHING, "Coughing")
HTML += ShowDisabilityState(user,DISABILITY_FLAG_TOURETTES, "Tourettes") Still working on it! -Angelite*/
@@ -1146,24 +1148,12 @@ NOTE: The change will take effect AFTER any current recruiting periods."}
SetDepartmentFlags(job, i, F)
if("language")
- var/languages_available
var/list/new_languages = list("None")
- if(config.usealienwhitelist)
- for(var/L in all_languages)
- var/datum/language/lang = all_languages[L]
- if((!(lang.flags & RESTRICTED)) && (is_alien_whitelisted(user, L)||(!( lang.flags & WHITELISTED ))))
- new_languages += lang.name
-
- languages_available = 1
-
- if(!(languages_available))
- alert(user, "There are not currently any available secondary languages.")
- else
- for(var/L in all_languages)
- var/datum/language/lang = all_languages[L]
- if(!(lang.flags & RESTRICTED))
- new_languages += lang.name
+ for(var/L in all_languages)
+ var/datum/language/lang = all_languages[L]
+ if(lang.flags & CAN_BE_SECONDARY_LANGUAGE)
+ new_languages += lang.name
language = input("Please select a secondary language", "Character Generation", null) in new_languages
diff --git a/code/modules/clothing/accessories/armor_shards.dm b/code/modules/clothing/accessories/armor_shards.dm
new file mode 100644
index 00000000000..9bf5a75f2ad
--- /dev/null
+++ b/code/modules/clothing/accessories/armor_shards.dm
@@ -0,0 +1,27 @@
+//Hockey pads, neck guards, particularly well-stained handkerchiefs go here
+/obj/item/clothing/accessory/armor_shard
+ armor = list(melee = 5, bullet = 5, laser = 5, energy = 0, bomb = 0, bio = 0, rad = 0)
+
+/obj/item/clothing/accessory/armor_shard/can_attach_to(obj/item/clothing/C)
+ . = ..()
+ for(var/obj/item/clothing/accessory in C.accessories)
+ if(accessory.type == type)
+ return 0
+
+/obj/item/clothing/accessory/armor_shard/shoulder
+ name = "shoulder pads"
+ desc = "Has clips to attach to a jumpsuit. Makes you feel like you're playing a fantasy MMO."
+ icon_state = "shoulder_guard"
+ body_parts_covered = ARMS
+
+/obj/item/clothing/accessory/armor_shard/knee
+ name = "knee pads"
+ desc = "Has clips to attach to a jumpsuit. Now you can safely play hockey."
+ icon_state = "knee_guard"
+ body_parts_covered = LEGS
+
+/obj/item/clothing/accessory/armor_shard/neck
+ name = "neck guard"
+ desc = "Has clips to attach to a jumpsuit. For when you want to protect your pretty face."
+ icon_state = "neck_guard"
+ body_parts_covered = FACE
\ No newline at end of file
diff --git a/code/modules/clothing/accessories/holomap.dm b/code/modules/clothing/accessories/holomap.dm
index 38ebc66612f..0d3c449f331 100644
--- a/code/modules/clothing/accessories/holomap.dm
+++ b/code/modules/clothing/accessories/holomap.dm
@@ -117,7 +117,8 @@ var/list/holomap_cache = list()
if(istype(A, /datum/action/item_action/toggle_minimap))
qdel(A)
..()
- user.update_action_buttons()
+ if(user)
+ user.update_action_buttons_icon()
/obj/item/clothing/accessory/holomap_chip/proc/togglemap()
if(usr.isUnconscious())
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 1795f9c6fbb..fcf6fa5ffa4 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -241,6 +241,12 @@
visible_message("\The [user] puts out the fire on \the [target].")
return
+/obj/item/clothing/proc/get_armor(var/type)
+ return armor[type]
+
+/obj/item/clothing/proc/get_armor_absorb(var/type)
+ return armor_absorb[type]
+
//Ears: headsets, earmuffs and tiny objects
/obj/item/clothing/ears
name = "ears"
@@ -423,6 +429,7 @@ BLIND // can't see anything
body_parts_covered &= ~(MOUTH|HEAD|BEARD|FACE)
usr.update_inv_wear_mask()
usr.update_hair()
+ usr.update_inv_glasses()
/obj/item/clothing/mask/New()
if(!can_flip /*&& !istype(/obj/item/clothing/mask/gas/voice)*/) //the voice changer has can_flip = 1 anyways but it's worth noting that it exists if anybody changes this in the future
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index c26658e0a51..28b8a2f99c4 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -50,7 +50,7 @@
/obj/item/clothing/glasses/regular/kick_act(mob/living/carbon/human/H)
H.visible_message("[H] stomps on \the [src], crushing them!", "You crush \the [src] under your foot.")
- playsound(get_turf(src), "shatter", 50, 1)
+ playsound(src, "shatter", 50, 1)
var/obj/item/weapon/shard/S = new(get_turf(src))
S.Crossed()
@@ -93,7 +93,7 @@
/obj/item/clothing/glasses/sunglasses/kick_act(mob/living/carbon/human/H)
H.visible_message("[H] stomps on \the [src], crushing them!", "You crush \the [src] under your foot.")
- playsound(get_turf(src), "shatter", 50, 1)
+ playsound(src, "shatter", 50, 1)
var/obj/item/weapon/shard/S = new(get_turf(src))
S.Crossed()
@@ -103,7 +103,7 @@
/obj/item/clothing/glasses/sunglasses/holo/kick_act(mob/living/carbon/human/H)
H.visible_message("[H] stomps on \the [src], crushing them and making them fade away!", "You crush \the [src] under your foot, which takes less effort than you realized as they fade from existence.")
- playsound(get_turf(src), "shatter", 50, 1)
+ playsound(src, "shatter", 50, 1)
qdel(src)
return SPECIAL_ATTACK_FAILED
@@ -123,6 +123,17 @@
desc = "Novelty sunglasses with a fancy silver frame and two red-tinted star-shaped lenses. You should probably stomp on them and get a pair of normal ones."
icon_state = "sun_star_silver"
+/obj/item/clothing/glasses/sunglasses/red
+ name = "red sunglasses"
+ desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes, and the colored lenses let you see the world in red."
+ icon_state = "sunred"
+ item_state = "sunred"
+
+/obj/item/clothing/glasses/sunglasses/security
+ name = "security sunglasses"
+ desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes. Often worn by budget security officers."
+ icon_state = "sunhud"
+
/obj/item/clothing/glasses/virussunglasses
desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes."
name = "sunglasses"
@@ -216,12 +227,12 @@
..()
if(prob(15))
new /obj/item/weapon/shard(loc)
- playsound(get_turf(src), "shatter", 50, 1)
+ playsound(src, "shatter", 50, 1)
qdel(src)
return
if(prob(15))
new/obj/item/clothing/glasses/sunglasses(get_turf(src))
- playsound(get_turf(src), 'sound/effects/glass_step.ogg', 50, 1)
+ playsound(src, 'sound/effects/glass_step.ogg', 50, 1)
qdel(src)
return
if(prob(55))
@@ -230,6 +241,59 @@
hud = null
qdel(hud)
+/obj/item/clothing/glasses/sunglasses/sechud/syndishades
+ desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes."
+ name = "sunglasses"
+ icon_state = "sun"
+ item_state = "sunglasses"
+ darkness_view = 0 //Subtly better than normal shades
+ origin_tech = Tc_SYNDICATE + "=3"
+ actions_types = list(/datum/action/item_action/change_appearance_shades)
+ var/static/list/clothing_choices = null
+ var/full_access = FALSE
+
+/obj/item/clothing/glasses/sunglasses/sechud/syndishades/New()
+ ..()
+ if(!clothing_choices)
+ clothing_choices = list()
+ for(var/Type in existing_typesof(/obj/item/clothing/glasses) - /obj/item/clothing/glasses - typesof(/obj/item/clothing/glasses/sunglasses/sechud/syndishades))
+ var/obj/glass = Type
+ clothing_choices[initial(glass.name)] = glass
+
+/obj/item/clothing/glasses/sunglasses/sechud/syndishades/attackby(obj/item/I, mob/user)
+ ..()
+ if(istype(I, /obj/item/clothing/glasses/sunglasses/sechud) || istype(I, /obj/item/clothing/glasses/hud/security))
+ var/obj/item/clothing/glasses/sunglasses/sechud/syndishades/S = I
+ if(istype(S) && !S.full_access)
+ return
+ if(full_access)
+ to_chat(user, "\The [src] already has those access codes.")
+ return
+ else
+ to_chat(user, "You transfer the security access codes from \the [I] to \the [src].")
+ full_access = TRUE
+
+/datum/action/item_action/change_appearance_shades
+ name = "Change Shades Appearance"
+
+/datum/action/item_action/change_appearance_shades/Trigger()
+ var/obj/item/clothing/glasses/sunglasses/sechud/syndishades/T = target
+ if(!istype(T))
+ return
+ T.change()
+
+/obj/item/clothing/glasses/sunglasses/sechud/syndishades/proc/change()
+ var/obj/item/clothing/glasses/A
+ A = input("Select style to change it to", "Style Selector", A) as null|anything in clothing_choices
+ if(src.gcDestroyed || !A || usr.incapacitated() || !Adjacent(usr))
+ return
+ desc = initial(clothing_choices[A].desc)
+ name = initial(clothing_choices[A].name)
+ icon_state = initial(clothing_choices[A].icon_state)
+ item_state = initial(clothing_choices[A].item_state)
+ _color = initial(clothing_choices[A]._color)
+ usr.update_inv_glasses()
+
/obj/item/clothing/glasses/thermal
name = "Optical Thermal Scanner"
desc = "Thermals in the shape of glasses."
@@ -314,3 +378,19 @@
icon_state = "kaminaglasses"
item_state = "kaminaglasses"
cover_hair = 1
+
+/obj/item/clothing/glasses/contacts
+ name = "contact lenses"
+ desc = "Only nerds wear glasses."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "contact"
+ prescription = 1
+ body_parts_covered = null
+
+/obj/item/clothing/glasses/contacts/polarized
+ name = "polarized contact lenses"
+ desc = "Protects your eyes from bright flashes of light."
+ icon_state = "polarized_contact"
+ darkness_view = -1
+ prescription = 1
+ eyeprot = 1
diff --git a/code/modules/clothing/glasses/scanners.dm b/code/modules/clothing/glasses/scanners.dm
index 9ad494afcf4..19151b836d8 100644
--- a/code/modules/clothing/glasses/scanners.dm
+++ b/code/modules/clothing/glasses/scanners.dm
@@ -33,14 +33,14 @@
if(iscarbon(M))
apply_color(M)
..()
-
+
/obj/item/clothing/glasses/scanner/unequipped(mob/user, var/from_slot = null)
if(from_slot == slot_glasses)
if(on)
if(iscarbon(user))
remove_color(user)
..()
-
+
/obj/item/clothing/glasses/scanner/update_icon()
icon_state = initial(icon_state)
@@ -103,11 +103,7 @@
actions_types = list(/datum/action/item_action/toggle_goggles)
species_fit = list(VOX_SHAPED, GREY_SHAPED)
eyeprot = -1
- color_matrix = list(0.33,0.33,0.33,0,
- 0.33,0.33,0.33,0,
- 0.33,0.33,0.33,0,
- 0,0,0,1,
- -0.2,0,-0.2,0)
+ color_matrix = "#CCFFCC"
/obj/item/clothing/glasses/scanner/night/enable(var/mob/C)
see_invisible = initial(see_invisible)
@@ -133,6 +129,10 @@
species_fit = list(GREY_SHAPED)
/obj/item/clothing/glasses/scanner/meson/enable(var/mob/C)
+ var/area/A = get_area(src)
+ if(A.flags & NO_MESONS)
+ to_chat(C, "\The [src] flickers, but refuses to come online!")
+ return
eyeprot = initial(eyeprot)
vision_flags |= SEE_TURFS
see_invisible |= SEE_INVISIBLE_MINIMUM
@@ -146,6 +146,11 @@
see_invisible &= ~SEE_INVISIBLE_MINIMUM
..()
+/obj/item/clothing/glasses/scanner/meson/area_entered(area/A)
+ if(A.flags & NO_MESONS && on)
+ visible_message("\The [src] sputter out.")
+ disable()
+
/obj/item/clothing/glasses/scanner/material
name = "optical material scanner"
desc = "Allows one to see the original layout of the pipe and cable network."
diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm
index a38feb55191..589ebbf8b56 100644
--- a/code/modules/clothing/gloves/color.dm
+++ b/code/modules/clothing/gloves/color.dm
@@ -43,7 +43,7 @@
if(L.damage <= 0)
returnToPool(L)
else
- playsound(get_turf(src), 'sound/effects/eleczap.ogg', 75, 1)
+ playsound(src, 'sound/effects/eleczap.ogg', 75, 1)
L.tang = adjustAngle(get_angle(U,T))
L.icon = midicon
L.icon_state = "[L.tang]"
@@ -184,7 +184,7 @@
if(!M.get_active_hand())
var/obj/item/weapon/gun/projectile/handgun/G = new
current_gun = G
- if(!M.miming) //nonmimes get a loud version
+ if(!issilent(M)) //nonmimes get a loud version
G.silenced = FALSE
G.fire_sound = 'sound/weapons/Gunshot.ogg'
M.put_in_active_hand(G)
diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm
index 7630d781235..b418722a4bd 100644
--- a/code/modules/clothing/gloves/miscellaneous.dm
+++ b/code/modules/clothing/gloves/miscellaneous.dm
@@ -154,6 +154,7 @@
desc = "Utilizes a non-slip technology that allows you to never drop your precious bottles of vodka."
icon_state = "nr_gloves"
item_state = "nr_gloves"
+ heat_conductivity = INS_GLOVES_HEAT_CONDUCTIVITY
/obj/item/clothing/gloves/neorussian/fingerless
name = "neo-Russian fingerless gloves"
@@ -257,7 +258,7 @@
/obj/item/clothing/gloves/powerfist/on_punch(mob/user, mob/living/victim)
if(istype(victim) && use_fuel(fuel_cost))
to_chat(user, "As \the [src] activate, you feel a truly powerful force assisting your punch.")
- playsound(get_turf(src), 'sound/mecha/mechentry.ogg', 100, 1)
+ playsound(src, 'sound/mecha/mechentry.ogg', 100, 1)
victim.throw_at(get_edge_target_turf(loc, loc.dir), 5, 1)
victim.Stun(stunforce)
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 00acd44871e..32cb5c08375 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -10,6 +10,48 @@
siemens_coefficient = 0.7
species_fit = list(GREY_SHAPED)
+/obj/item/clothing/head/helmet/visor
+ name = "visor helmet"
+ desc = "For when you need to protect your face from the backblast of your pepperspray"
+ icon_state = "riot_helm"
+ item_state = "riot_helm"
+ armor = list(melee = 50, bullet = 25, laser = 45, energy = 15, bomb = 30, bio = 0, rad = 0)
+ actions_types = list(/datum/action/item_action/toggle_helmet)
+ body_parts_covered = FULL_HEAD
+ var/state = 1
+
+/obj/item/clothing/head/helmet/visor/New()
+ ..()
+ update_icon()
+
+/obj/item/clothing/head/helmet/visor/attack_self(mob/user)
+ state = !state
+ to_chat(user, "You flick \the [src] [state ? "down" : "up"].")
+ switch(state)
+ if(1) //FACE COVERED
+ body_parts_covered = FULL_HEAD
+ if(0) //VISOR UP
+ body_parts_covered = HEAD|EARS
+ update_icon(user)
+
+/obj/item/clothing/head/helmet/visor/update_icon(mob/user)
+ switch(state)
+ if(1) //FACE COVERED
+ armor = initial(armor)
+ icon_state = "[initial(icon_state)]_down"
+ item_state = "[initial(item_state)]_down"
+ if(0)
+ armor = list(melee = 50, bullet = 10, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0)
+ icon_state = "[initial(icon_state)]_up"
+ item_state = "[initial(item_state)]_down"
+ if(user)
+ user.update_inv_head()
+ user.update_inv_wear_mask()
+ user.update_inv_glasses()
+ user.update_hair()
+ user.update_inv_ears()
+
+
/obj/item/clothing/head/helmet/siren
name = "siren helmet"
desc = "For the officer that's off patrolling all the nation."
@@ -24,7 +66,7 @@
/obj/item/clothing/head/helmet/siren/attack_self(mob/user)
if(spamcheck)
return
- playsound(get_turf(src), 'sound/voice/woopwoop.ogg', 100, 1, vary = 0)
+ playsound(src, 'sound/voice/woopwoop.ogg', 100, 1, vary = 0)
user.visible_message("[user]'s [name] rasps, \"WOOP WOOP!\"", \
"Your [name] rasps, \"WOOP WOOP!\"", \
"You hear a siren: \"WOOP WOOP!\"")
@@ -71,6 +113,7 @@
armor = list(melee = 20, bullet = 0, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0)
icon_state = "roman"
item_state = "roman"
+ body_parts_covered = HEAD|EARS
/obj/item/clothing/head/helmet/roman/legionaire
name = "roman legionaire helmet"
@@ -78,6 +121,7 @@
armor = list(melee = 25, bullet = 0, laser = 25, energy = 10, bomb = 10, bio = 0, rad = 0)
icon_state = "roman_c"
item_state = "roman_c"
+ body_parts_covered = HEAD|EARS
/obj/item/clothing/head/helmet/hopcap
name = "Head of Personnel's Cap"
@@ -106,7 +150,7 @@
desc = "This helmet should protect you from russians and masked vigilantes."
armor = list(melee = 25, bullet = 15, laser = 20, energy = 10, bomb = 10, bio = 0, rad = 0)
icon_state = "biker_helmet"
- body_parts_covered = FULL_HEAD
+ body_parts_covered = FULL_HEAD|BEARD
/obj/item/clothing/head/helmet/richard
name = "Richard"
@@ -120,6 +164,7 @@
desc = "The helmet of the DRN-001 model. A simple, sturdy blue helmet."
icon_state = "megahelmet"
flags = FPRINT
+ body_parts_covered = HEAD|EARS
item_state = "megahelmet"
siemens_coefficient = 1
@@ -145,6 +190,7 @@
desc = "Heavily armored upgrade to the DRN-001 model's helmet, now comes with a pointless red crystal thing!"
icon_state = "megaxhelmet"
flags = FPRINT
+ body_parts_covered = HEAD|EARS
item_state = "megaxhelmet"
siemens_coefficient = 1
@@ -153,6 +199,7 @@
desc = "A sturdy helmet, fortified to protect from falling rocks or buster shots."
icon_state = "volnutthelmet"
flags = FPRINT
+ body_parts_covered = HEAD|EARS
item_state = "volnutthelmet"
armor = list(melee = 50, bullet = 40, laser = 40,energy = 40, bomb = 5, bio = 0, rad = 0)
siemens_coefficient = 1
@@ -172,6 +219,7 @@
icon_state = "doom"
flags = FPRINT
item_state = "doom"
+ body_parts_covered = FULL_HEAD|BEARD
armor = list(melee = 50, bullet = 40, laser = 40,energy = 40, bomb = 5, bio = 0, rad = 0)
siemens_coefficient = 1
@@ -209,6 +257,7 @@
icon_state = "nr_helmet"
item_state = "nr_helmet"
body_parts_covered = EARS|HEAD
+ heat_conductivity = INS_HELMET_HEAT_CONDUCTIVITY
/obj/item/clothing/head/helmet/police
name = "police custodian helmet"
diff --git a/code/modules/clothing/head/leather.dm b/code/modules/clothing/head/leather.dm
index 4e3692a7b8f..ae8fb1b950d 100644
--- a/code/modules/clothing/head/leather.dm
+++ b/code/modules/clothing/head/leather.dm
@@ -21,11 +21,10 @@
new/obj/item/clothing/head/leather/corgi(get_turf(src))
user.drop_item(src, force_drop = 1)
qdel(src)
- /* DEERS TO BE IMPLEMENTED
if(istype (S, /obj/item/stack/sheet/animalhide/deer))
new/obj/item/clothing/head/leather/deer(get_turf(src))
user.drop_item(src, force_drop = 1)
- qdel(src)*/
+ qdel(src)
if(istype (S, /obj/item/stack/sheet/animalhide/xeno))
new/obj/item/clothing/head/leather/xeno(get_turf(src))
user.drop_item(src, force_drop = 1)
@@ -37,7 +36,6 @@
icon_state = "helmet_leather_corgi"
item_state = "helmet_leather_corgi"
-/* DEERS TO BE IMPLEMENTED
/obj/item/clothing/head/leather/deer
name = "deer pelt head cover"
desc = "Made to help you blend in and stalk deer. Sadly lacking the horns."
@@ -52,7 +50,7 @@
user.drop_item(W, force_drop = 1)
user.drop_item(src, force_drop = 1)
qdel(W)
- qdel(src)*/
+ qdel(src)
/obj/item/clothing/head/leather/deer/horned
name = "horned deer pelt head cover"
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 81c06e45f09..8942b5821c4 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -460,4 +460,10 @@
wizard_garb = 1 //being elf cursed wont prevent you casting robed spells if wizard
/obj/item/clothing/head/elfhat/stickymagic
- canremove = 0
\ No newline at end of file
+ canremove = 0
+
+/obj/item/clothing/head/rice_hat
+ name = "rice hat"
+ desc = "Welcome to the rice fields, motherfucker."
+ icon_state = "rice_hat"
+ item_state = "rice_hat"
\ No newline at end of file
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index 38526db8ff7..a4b08396344 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -112,22 +112,29 @@
/obj/item/clothing/head/ushanka
name = "ushanka"
desc = "Perfect for winter in Siberia, da?"
- icon_state = "ushankadown"
- item_state = "ushankadown"
+ icon_state = "ushanka"
+ item_state = "ushanka"
body_parts_covered = EARS|HEAD
+ heat_conductivity = SNOWGEAR_HEAT_CONDUCTIVITY
/obj/item/clothing/head/ushanka/attack_self(mob/user as mob)
- if(src.icon_state == "ushankadown")
- src.icon_state = "ushankaup"
- src.item_state = "ushankaup"
+ var/initial_icon_state = initial(icon_state)
+ if(icon_state == initial_icon_state)
+ icon_state = "[initial_icon_state]up"
+ item_state = "[initial_icon_state]up"
body_parts_covered = HEAD
- to_chat(user, "You raise the ear flaps on the ushanka.")
+ to_chat(user, "You raise the ear flaps on \the [src].")
else
- src.icon_state = "ushankadown"
- src.item_state = "ushankadown"
- to_chat(user, "You lower the ear flaps on the ushanka.")
+ icon_state = initial_icon_state
+ item_state = initial_icon_state
+ to_chat(user, "You lower the ear flaps on \the [src].")
body_parts_covered = EARS|HEAD
+/obj/item/clothing/head/ushanka/security
+ name = "security ushanka"
+ desc = "Davai, tovarish. Let us catch the capitalist greyshirt, and show him why it is that we proudly wear red!"
+ icon_state = "ushankared"
+ item_state = "ushankared"
/*
* Pumpkin head
*/
@@ -166,43 +173,29 @@
flags = FPRINT
var/icon/mob
var/icon/mob2
+ var/haircolored = 1
siemens_coefficient = 1.5
- update_icon(var/mob/living/carbon/human/user)
- if(!istype(user))
- return
- mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty")
- mob2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty2")
- mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD)
- mob2.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD)
-
- var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner")
- var/icon/earbit2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner2")
- mob.Blend(earbit, ICON_OVERLAY)
- mob2.Blend(earbit2, ICON_OVERLAY)
-
/obj/item/clothing/head/kitty/cursed
canremove = 0
-/obj/item/clothing/head/kitty/equipped(mob/M, var/slot)
- ..()
- var/mob/living/carbon/human/H = M
- if(!istype(H))
- return
- if(slot == slot_head)
- to_chat(H, "Something on your head is making you feel a little lightheaded...")
+/obj/item/clothing/head/kitty/collectable
+ desc = "A pair of black kitty ears. Meow!"
+ haircolored = 0
-/obj/item/clothing/head/kitty/unequipped(mob/living/carbon/human/user, var/from_slot = null)
- ..()
- if(from_slot == slot_head && istype(user))
- to_chat(user, "Your head starts to feel better again.")
-
-/obj/item/clothing/head/kitty/OnMobLife(var/mob/living/carbon/human/wearer)
- if(!istype(wearer))
+/obj/item/clothing/head/kitty/update_icon(var/mob/living/carbon/human/user)
+ if(!istype(user) || !haircolored)
return
- if(wearer.get_item_by_slot(slot_head) == src)
- if(prob(20))
- wearer.adjustBrainLoss(1)
+ mob = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty")
+ mob2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kitty2")
+ mob.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD)
+ mob2.Blend(rgb(user.r_hair, user.g_hair, user.b_hair), ICON_ADD)
+
+ var/icon/earbit = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner")
+ var/icon/earbit2 = new/icon("icon" = 'icons/mob/head.dmi', "icon_state" = "kittyinner2")
+ mob.Blend(earbit, ICON_OVERLAY)
+ mob2.Blend(earbit2, ICON_OVERLAY)
+
/obj/item/clothing/head/butt
name = "butt"
diff --git a/code/modules/clothing/head/tactical.dm b/code/modules/clothing/head/tactical.dm
index 07b4ba09ee6..87cdfa8760c 100644
--- a/code/modules/clothing/head/tactical.dm
+++ b/code/modules/clothing/head/tactical.dm
@@ -22,7 +22,7 @@
flashlight = I
update_brightness()
- user.update_action_buttons()
+ user.update_action_buttons_icon()
user.update_inv_head()
return
if(isscrewdriver(I) && src.flashlight)
@@ -31,7 +31,7 @@
flashlight = null
update_brightness()
- user.update_action_buttons()
+ user.update_action_buttons_icon()
user.update_inv_head()
return
return ..()
@@ -41,9 +41,9 @@ obj/item/clothing/head/helmet/tactical/attack_self(mob/user)
flashlight.on = !flashlight.on
if(get_turf(src))
if(flashlight.on)
- playsound(get_turf(src), flashlight.sound_on, 50, 1)
+ playsound(src, flashlight.sound_on, 50, 1)
else
- playsound(get_turf(src), flashlight.sound_off, 50, 1)
+ playsound(src, flashlight.sound_off, 50, 1)
update_brightness()
user.update_inv_head()
@@ -100,7 +100,7 @@ obj/item/clothing/head/helmet/tactical/attack_self(mob/user)
flags = FPRINT
armor = list(melee = 82, bullet = 15, laser = 5,energy = 5, bomb = 5, bio = 2, rad = 0)
siemens_coefficient = 0.7
- body_parts_covered = HEAD|MOUTH
+ body_parts_covered = FULL_HEAD
eyeprot = 1
/obj/item/clothing/head/helmet/tactical/swat
diff --git a/code/modules/clothing/masks/chemmask.dm b/code/modules/clothing/masks/chemmask.dm
index 7c80ac10c06..ec291ff3b4b 100644
--- a/code/modules/clothing/masks/chemmask.dm
+++ b/code/modules/clothing/masks/chemmask.dm
@@ -287,7 +287,7 @@
/obj/item/clothing/mask/chemmask/proc/pack_check(mob/user) //Shuts off mask if the user is not wearing a chempack.
var/mob/living/M = user
- if (!(M && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack)))
+ if (!(istype(M) && M.back && istype(M.back,/obj/item/weapon/reagent_containers/chempack)))
mask_shutdown(user)
to_chat(user, "\The [src] shuts off!")
return 0
@@ -325,7 +325,7 @@
var/obj/item/weapon/reagent_containers/glass/B = P.beaker
if (B.is_empty() && firstalert_beaker == 0)
firstalert_beaker = 1
- playsound(get_turf(src),'sound/mecha/internaldmgalarm.ogg', 100, 1)
+ playsound(src,'sound/mecha/internaldmgalarm.ogg', 100, 1)
to_chat(user, "The auxiliary beaker is empty!")
else if (!B.is_empty())
firstalert_beaker = 0
@@ -333,7 +333,8 @@
/obj/item/clothing/mask/chemmask/proc/mask_shutdown(mob/user) //Removes most verbs upon toggling the mask off, but not all. The user keeps access to the verbs to toggle connection to the tank and beaker.
power = 0
icon_state = "chemmask0"
- user.update_inv_wear_mask()
+ if(istype(user))
+ user.update_inv_wear_mask()
update_verbs()
/obj/item/clothing/mask/chemmask/process()
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index eb1ee41535d..76119a70dd0 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -36,7 +36,10 @@
desc = "Warning: moustache is fake."
icon_state = "fake-moustache"
flags = FPRINT
- body_parts_covered = FACE //totally intentional
+ body_parts_covered = BEARD
+
+/obj/item/clothing/mask/fakemoustache/is_hidden_identity()
+ return TRUE
//scarves (fit in in mask slot)
/obj/item/clothing/mask/scarf
@@ -73,16 +76,25 @@
icon_state = "balaclava"
item_state = "balaclava"
flags = FPRINT
- body_parts_covered = FACE
+ body_parts_covered = HEAD|MOUTH|EARS
w_class = W_CLASS_SMALL
species_fit = list(VOX_SHAPED, GREY_SHAPED)
+/obj/item/clothing/mask/balaclava/is_hidden_identity()
+ return TRUE
+
+/obj/item/clothing/mask/balaclava/skimask
+ heat_conductivity = INS_MASK_HEAT_CONDUCTIVITY
+ name = "ski mask"
+ desc = "This NT-brand skimask is sure to keep you warm."
+
/obj/item/clothing/mask/neorussian
name = "neo-Russian mask"
desc = "Somehow, it makes you act and look way more polite than usual."
icon_state = "nr_mask"
item_state = "nr_mask"
body_parts_covered = FACE
+ heat_conductivity = INS_MASK_HEAT_CONDUCTIVITY
/obj/item/clothing/mask/pig
name = "pig mask"
diff --git a/code/modules/clothing/masks/transmog.dm b/code/modules/clothing/masks/transmog.dm
index e605e44d2ad..dea5e1359d6 100644
--- a/code/modules/clothing/masks/transmog.dm
+++ b/code/modules/clothing/masks/transmog.dm
@@ -26,6 +26,12 @@
if(cursed)
name = "cursed [name]"
+/obj/item/clothing/mask/morphing/mob_can_equip(mob/M, slot, disable_warning = 0, automatic = 0)
+ M.visible_message("\The [M] attempts to put on \the [src].")
+ if(do_after(M, src, 5 SECONDS))
+ return ..()
+ return CANNOT_EQUIP
+
/obj/item/clothing/mask/morphing/equipped(mob/living/carbon/C, wear_mask)
if(target_type && istype(C))
if(C.get_item_by_slot(slot_wear_mask) == src)
@@ -101,7 +107,7 @@
/obj/item/clothing/mask/morphing/lizard
name = "mask of the lizard"
desc = "It appears to be modeled after a lizard."
- target_type = /mob/living/simple_animal/lizard
+ target_type = /mob/living/simple_animal/hostile/lizard
icon_state = "lizard_mask"
/obj/item/clothing/mask/morphing/xeno
@@ -125,8 +131,7 @@
..()
color = rgb(rand(0,255),rand(0,255),rand(0,255))
//Remove cockatrices because they're somewhat OP when player controlled
- target_type = pick(existing_typesof(/mob/living/simple_animal) - existing_typesof(/mob/living/simple_animal/hostile/humanoid) - typesof(/mob/living/simple_animal/hostile/retaliate/cockatrice) - typesof(/mob/living/simple_animal/hostile/giant_spider/hunter/dead) - typesof(/mob/living/simple_animal/hostile/asteroid/hivelordbrood))
-
+ target_type = pick(existing_typesof(/mob/living/simple_animal) - (existing_typesof_list(blacklisted_mobs) + existing_typesof_list(boss_mobs)))
/obj/item/clothing/mask/morphing/ghost
name = "mask of the phantom"
desc = "It appears to be modeled after a ghost. It looks as though it might disappear at any moment."
diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm
index f27ca010bb7..3d191dc79dc 100644
--- a/code/modules/clothing/shoes/magboots.dm
+++ b/code/modules/clothing/shoes/magboots.dm
@@ -40,12 +40,12 @@
victim.visible_message("\The [user] [stomp_hit] \the [victim] with the activated [src.name]!", "\The [user] [stomp_hit] you with \his [src.name]!")
victim.apply_damage(stomp_attack_power, BRUTE, affecting)
- playsound(get_turf(victim), 'sound/effects/gib3.ogg', 100, 1)
+ playsound(victim, 'sound/effects/gib3.ogg', 100, 1)
else
return
toggle()
- playsound(get_turf(victim), 'sound/mecha/mechstep.ogg', 100, 1)
+ playsound(victim, 'sound/mecha/mechstep.ogg', 100, 1)
/obj/item/clothing/shoes/magboots/proc/toggle()
if(usr.isUnconscious())
@@ -121,6 +121,13 @@
base_state = "capboots"
anchoring_system_examine = "Its anchoring spikes appear to be"
+//Magnificent
+/obj/item/clothing/shoes/magboots/magnificent
+ desc = "The secret meaning of what mag stands for."
+ name = "magnificent mag boots"
+ icon_state = "MAGNIFICENTboots0"
+ base_state = "MAGNIFICENTboots1"
+
/obj/item/clothing/shoes/magboots/captain/toggle()
//set name = "Toggle Floor Grip"
if(usr.isUnconscious())
@@ -136,4 +143,71 @@
src.slowdown = mag_slow
src.magpulse = 1
icon_state = "[base_state]1"
- to_chat(usr, "Small spikes shoot from your shoes and dig into the flooring, bracing you.")
\ No newline at end of file
+ to_chat(usr, "Small spikes shoot from your shoes and dig into the flooring, bracing you.")
+
+
+/obj/item/clothing/shoes/magboots/funk
+ name = "neo-soviet funk boots"
+ desc = "The top secret plan to end Cold war 2 was not through tactical nuclear exchange and espionage, but through an intense dance-off between the Neo-Soviet Premier and the United Fronts President."
+ icon_state = "funk"
+ base_state = "funk"
+ var/funk_level = 0
+ canremove = 0
+
+/obj/item/clothing/shoes/magboots/funk/toggle()
+ if(usr.isUnconscious())
+ return
+ if(funk_level >= 11) //WE HAVE GONE TOO FAR, COMRADE
+ return
+ usr.visible_message("[usr] dials up \the [src]'s funk level to [funk_level+1]")
+ funk_level++
+ if(funk_level >= 2)
+ clothing_flags |= NOSLIP
+ magpulse = 1
+
+/obj/item/clothing/shoes/magboots/funk/step_action()
+ ..()
+ var/mob/living/carbon/human/H = loc
+ //Evaluate L-RUSS levels
+ var/russian = 1
+ if(H.head)
+ if(H.head.type == /obj/item/clothing/head/bearpelt)
+ russian+=1
+ if(H.head.type == /obj/item/clothing/head/bearpelt/real)
+ russian+=2
+ if(!H.w_uniform)
+ russian++
+ else
+ if(H.w_uniform.type == /obj/item/clothing/under/russobluecamooutfit || istype(H.w_uniform, /obj/item/clothing/under/neorussian))
+ russian+=2
+ if(findtext("ivan",lowertext(H.name)) || findtext("yuri",lowertext(H.name)) || findtext("vlad",lowertext(H.name)) || findtext("lenin",lowertext(H.name)) || findtext("boris",lowertext(H.name)) || findtext("sasha",lowertext(H.name)) || findtext("misha",lowertext(H.name)) || findtext("sergei",lowertext(H.name)))
+ russian+=3
+
+ if(funk_level > 2 && prob((50/russian)**funk_level))
+ var/datum/organ/external/foot = H.pick_usable_organ(LIMB_LEFT_FOOT, LIMB_RIGHT_FOOT)
+ if(foot.take_damage((rand(1, 3)/10)*funk_level, 0))
+ H.UpdateDamageIcon()
+
+ if(funk_level > 4 && prob((10/russian)*funk_level))
+ H.reagents.add_reagent(HYPERZINE, 1)
+
+ /** IT WAS TOO MUCH, SERGEI
+ if(funk_level > 5 && prob((20/russian)*funk_level)) //IT IS TOO LATE, SERGEI
+ step_rand(H)
+ **/
+ if(funk_level > 6 && prob((10/russian)*funk_level))
+ H.reagents.add_reagent(HYPOZINE, 1)
+
+ if(funk_level > 9 && prob((5/russian)*funk_level))
+ explosion(get_turf(src), round((1*funk_level)/russian)*0.25, round((1*funk_level)/russian)*0.5, round((1*funk_level)/russian))
+
+ if(prob((funk_level/russian)*2)) //IT WAS ALWAYS TOO LATE
+ toggle()
+
+/obj/item/clothing/shoes/magboots/funk/OnMobDeath(var/mob/living/carbon/human/wearer)
+ var/mob/living/carbon/human/W = wearer
+ W.drop_from_inventory(src)
+ funk_level = 0
+ canremove = 1
+ clothing_flags &= ~NOSLIP
+ magpulse = 0
\ No newline at end of file
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index ff690a34e99..7257d188765 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -294,6 +294,7 @@
desc = "Tovarish, no one will realize you stepped on a pile of shit if your pair already looks like shit."
icon_state = "nr_boots"
item_state = "nr_boots"
+ heat_conductivity = INS_ARMOUR_HEAT_CONDUCTIVITY
/obj/item/clothing/shoes/cult
name = "boots"
@@ -433,4 +434,32 @@
name = "clockwork boots"
desc = "A pair of boots worn by the followers of Ratvar."
icon_state = "clockwork"
- item_state = "clockwork"
\ No newline at end of file
+ item_state = "clockwork"
+
+/obj/item/clothing/shoes/knifeboot
+ name = "laceup shoes"
+ desc = "The height of fashion, and they're pre-polished!"
+ icon_state = "laceups"
+ item_state = "laceups"
+ species_fit = list(VOX_SHAPED)
+ actions_types = list(/datum/action/item_action/generic_toggle)
+ var/toggle = FALSE
+
+/obj/item/clothing/shoes/knifeboot/attack_self()
+ toggle = !toggle
+ to_chat(usr, "You toggle \the [src]'s hidden knife [toggle?"out":"in"].")
+ update_icon()
+ ..()
+
+/obj/item/clothing/shoes/knifeboot/update_icon()
+ if(toggle)
+ icon_state = "[initial(icon_state)]_1"
+ else
+ icon_state = initial(icon_state)
+ item_state = icon_state
+
+/obj/item/clothing/shoes/knifeboot/on_kick(mob/living/carbon/human/user, mob/living/victim)
+ if(istype(victim) && toggle)
+ var/datum/organ/external/affecting = victim.get_organ(ran_zone(user.zone_sel.selecting))
+ //Sharpness 1.5, force 10, edge = SHARP_TIP | SHARP_BLADE
+ victim.apply_damage(victim.run_armor_absorb(affecting, "melee", 10), BRUTE, affecting, victim.run_armor_check(affecting, "melee"), sharp = 1.5, edge = SHARP_TIP | SHARP_BLADE, used_weapon = src)
\ No newline at end of file
diff --git a/code/modules/clothing/spacesuits/alien.dm b/code/modules/clothing/spacesuits/alien.dm
index 5f7bcea1647..e0ab883e7ca 100644
--- a/code/modules/clothing/spacesuits/alien.dm
+++ b/code/modules/clothing/spacesuits/alien.dm
@@ -388,6 +388,7 @@ obj/item/clothing/head/helmet/space/vox/civ/trader/stealth //blackhelmet
name = "vox roboticist pressure helmet"
icon_state = "vox-civ-roboticist"
desc = "A very alien-looking helmet for vox crewmembers. This one is for roboticists."
+ actions_types = list(/datum/action/item_action/toggle_helmet_mask)
//Med/Sci
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 31d30ddaa63..710307a6b6f 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -19,8 +19,7 @@
var/next_extinguish=0
var/extinguish_cooldown=10 SECONDS
-/obj/item/clothing/suit/space/plasmaman/proc/Extinguish(var/mob/user)
- var/mob/living/carbon/human/H=user
+/obj/item/clothing/suit/space/plasmaman/proc/Extinguish(var/mob/living/carbon/human/H)
if(next_extinguish > world.time)
return
@@ -28,6 +27,12 @@
to_chat(H, "Your suit automatically extinguishes the fire.")
H.ExtinguishMob()
+/obj/item/clothing/suit/space/plasmaman/proc/regulate_temp_of_wearer(var/mob/living/carbon/human/H)
+ if(H.bodytemperature < T0C+37)
+ H.bodytemperature = min(H.bodytemperature+5,T0C+37)
+ else
+ H.bodytemperature = max(H.bodytemperature-5,T0C+37)
+
/obj/item/clothing/head/helmet/space/plasmaman
name = "plasmaman helmet"
desc = "A special containment helmet designed to protect a plasmaman's volatile body from outside exposure and quickly extinguish it in emergencies."
@@ -257,6 +262,10 @@
icon_state = "plasmamanScience_helmet0"
base_state = "plasmamanScience_helmet"
+/obj/item/clothing/head/helmet/space/plasmaman/science/New()
+ actions_types += /datum/action/item_action/toggle_helmet_mask
+ ..()
+
/obj/item/clothing/suit/space/plasmaman/science/rd
name = "plasmaman research director suit"
icon_state = "plasmaman_RD"
diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm
index 64ab95904e5..e3918dd5f43 100644
--- a/code/modules/clothing/spacesuits/rig.dm
+++ b/code/modules/clothing/spacesuits/rig.dm
@@ -238,6 +238,7 @@
wizard_garb = 1
species_restricted = null
+ allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/teleportation_scroll,/obj/item/weapon/gun/energy/staff)
/obj/item/clothing/suit/space/rig/wizard/acidable()
return 0
@@ -294,7 +295,8 @@
/obj/item/ammo_storage,
/obj/item/ammo_casing,
/obj/item/weapon/handcuffs,
- /obj/item/weapon/bikehorn/baton)
+ /obj/item/weapon/bikehorn/baton,
+ /obj/item/weapon/blunderbuss)
siemens_coefficient = 0.7
pressure_resistance = 40 * ONE_ATMOSPHERE
@@ -304,13 +306,13 @@
icon_state = "rig0-storm"
_color = "storm"
name = "stormtrooper helmet"
- desc = "Now even more vulnerable to teddy bears!"
+ desc = "Even with the finest vision enhancement tech, you still can't hit shit."
no_light = 1
/obj/item/clothing/suit/space/rig/security/stormtrooper
icon_state = "rig-storm"
name = "stormtrooper hardsuit"
- desc = "Even with the finest vision enhancement tech, you still can't hit shit."
+ desc = "Now even more vulnerable to teddy bears!"
//Atmospherics Rig (BS12)
/obj/item/clothing/head/helmet/space/rig/atmos
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 692af826f5e..b84b520f070 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -1,5 +1,19 @@
/obj/item/clothing/suit/armor
- allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_storage,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/gun/lawgiver,/obj/item/weapon/gun/siren,/obj/item/weapon/gun/mahoguny,/obj/item/weapon/bikehorn/baton)
+ allowed = list(
+ /obj/item/weapon/gun/energy,
+ /obj/item/weapon/reagent_containers/spray/pepper,
+ /obj/item/weapon/gun/projectile,
+ /obj/item/ammo_storage,
+ /obj/item/ammo_casing,
+ /obj/item/weapon/melee/baton,
+ /obj/item/weapon/handcuffs,
+ /obj/item/weapon/gun/lawgiver,
+ /obj/item/weapon/gun/siren,
+ /obj/item/weapon/gun/mahoguny,
+ /obj/item/weapon/gun/grenadelauncher,
+ /obj/item/weapon/bikehorn/baton,
+ /obj/item/weapon/blunderbuss
+ )
body_parts_covered = FULL_TORSO
flags = FPRINT
heat_conductivity = ARMOUR_HEAT_CONDUCTIVITY
@@ -120,6 +134,17 @@
siemens_coefficient = 0
var/basereflectchance = 60
+/obj/item/clothing/suit/armor/laserproof/advanced
+ name = "Vest of Reflection"
+ desc = "This modified version of a common ablative armor vest is guaranteed to reflect every single energy projectile coming your way. As a slight tradeoff though, it doesn't provide any protection."
+ icon_state = "armor_reflec_adv"
+ item_state = "armor_reflec_adv"
+
+ //Reflect literally everything
+ basereflectchance = 300
+
+ armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
+
/obj/item/clothing/suit/armor/laserproof/become_defective()
if(!defective)
..()
@@ -208,7 +233,7 @@
L.visible_message("The reactive teleport system flings [L] clear of [attack_text]!", "The reactive teleport system flings you clear of [attack_text].")
- playsound(get_turf(L), 'sound/effects/teleport.ogg', 30, 1)
+ playsound(L, 'sound/effects/teleport.ogg', 30, 1)
L.forceMove(picked)
diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm
index 919094c9b0e..2e398685cfc 100644
--- a/code/modules/clothing/suits/labcoat.dm
+++ b/code/modules/clothing/suits/labcoat.dm
@@ -6,12 +6,10 @@
//icon_state = "labcoat_open"
item_state = "labcoat"
blood_overlay_type = "coat"
- allowed = list(/obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen,/obj/item/weapon/minihoe,/obj/item/weapon/switchtool)
+ allowed = list(/obj/item/roller, /obj/item/device/analyzer,/obj/item/stack/medical,/obj/item/weapon/dnainjector,/obj/item/weapon/reagent_containers/dropper,/obj/item/weapon/reagent_containers/syringe,/obj/item/weapon/reagent_containers/hypospray,/obj/item/device/healthanalyzer,/obj/item/device/flashlight/pen,/obj/item/weapon/minihoe,/obj/item/weapon/switchtool)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0)
species_fit = list(VOX_SHAPED, GREY_SHAPED)
-
-
/obj/item/clothing/suit/storage/labcoat/update_icon()
if(open)
icon_state="[base_icon_state]_open"
diff --git a/code/modules/clothing/suits/leather.dm b/code/modules/clothing/suits/leather.dm
index 88a3d2d6749..d36db00c0e8 100644
--- a/code/modules/clothing/suits/leather.dm
+++ b/code/modules/clothing/suits/leather.dm
@@ -21,11 +21,10 @@
new/obj/item/clothing/suit/leather/corgi(get_turf(src))
user.drop_item(src, force_drop = 1)
qdel(src)
- /* DEERS TO BE IMPLEMENTED
if(istype (S, /obj/item/stack/sheet/animalhide/deer))
new/obj/item/clothing/suit/leather/deer(get_turf(src))
user.drop_item(src, force_drop = 1)
- qdel(src)*/
+ qdel(src)
if(istype (S, /obj/item/stack/sheet/animalhide/xeno))
new/obj/item/clothing/suit/leather/xeno(get_turf(src))
user.drop_item(src, force_drop = 1)
@@ -38,12 +37,11 @@
icon_state = "suit_leather_corgi"
item_state = "suit_leather_corgi"
-/* DEERS TO BE IMPLEMENTED
/obj/item/clothing/suit/leather/deer
name = "deer-leather suit"
desc = "Coated in deer hide, smells just as bad as you'd think."
icon_state = "suit_leather_deer"
- item_state = "suit_leather_deer"*/
+ item_state = "suit_leather_deer"
/obj/item/clothing/suit/leather/xeno
name = "xeno-hide suit"
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index 4a29df6b5b0..954570e287f 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -552,13 +552,25 @@
return
M.visible_message("\The [M] opens \his [src.name], allowing you to see inside. Take a closer look.","You flash the contents of your [src.name].")
-/obj/item/clothing/suit/sakura_kimono
+/obj/item/clothing/suit/kimono
+ name = "kimono"
+ desc = "A traditional Japanese kimono."
+ icon_state = "fancy_kimono"
+ item_state = "fancy_kimono"
+ flags = FPRINT
+ body_parts_covered = ARMS|LEGS|FULL_TORSO|IGNORE_INV
+
+/obj/item/clothing/suit/kimono/ronin
+ name = "black kimono"
+ desc = "A black and plain looking kimono."
+ icon_state = "ronin_kimono"
+ item_state = "ronin_kimono"
+
+/obj/item/clothing/suit/kimono/sakura
name = "sakura kimono"
desc = "A pale-pink, nearly white, kimono with a red and gold obi. There is a embroidered design of cherry blossom flowers covering the kimono."
icon_state = "sakura_kimono"
item_state = "sakura_kimono"
- flags = FPRINT
- body_parts_covered = ARMS|LEGS|FULL_TORSO|IGNORE_INV
/obj/item/clothing/suit/clockwork_robes
name = "clockwork robes"
diff --git a/code/modules/clothing/suits/plate_carrier.dm b/code/modules/clothing/suits/plate_carrier.dm
new file mode 100644
index 00000000000..60f72a1f3db
--- /dev/null
+++ b/code/modules/clothing/suits/plate_carrier.dm
@@ -0,0 +1,121 @@
+/**
+ Plate Carrier armor.
+ Armor that accepts an armored plate, that takes the brunt of the damage and steadily ablates to nothing.
+*/
+
+/obj/item/clothing/suit/armor/plate_carrier
+ name = "tactical plate armor"
+ icon_state = "tactical_armor"
+ item_state = "tactical_armor"
+ var/event_key
+ var/obj/item/weapon/armor_plate/P
+
+/obj/item/clothing/suit/armor/plate_carrier/get_armor(var/type)
+ var/armor_value = armor[type]
+ if(P)
+ armor_value = armor[type] <= 0 ? P.armor[type] : Clamp((armor[type]+P.armor[type])/2, armor[type], 100)
+ return armor_value
+
+/obj/item/clothing/suit/armor/plate_carrier/get_armor_absorb(var/type)
+ var/armor_value = armor_absorb[type]
+ if(P)
+ armor_value = armor_absorb[type] <= 0 ? P.armor_absorb[type] : Clamp((armor_absorb[type]+P.armor_absorb[type])/2, armor_absorb[type], 100)
+ return armor_value
+
+/obj/item/clothing/suit/armor/plate_carrier/equipped(var/mob/user, var/slot)
+ ..()
+ if(slot == slot_wear_suit)
+ event_key = user.on_damaged.Add(src, "handle_user_damage")
+
+
+/obj/item/clothing/suit/armor/plate_carrier/unequipped(mob/user, var/from_slot = null)
+ if(from_slot == slot_wear_suit)
+ user.on_damaged.Remove(event_key)
+ event_key = null
+ ..()
+
+/obj/item/clothing/suit/armor/plate_carrier/attack_self(mob/user)
+ if(P)
+ user.put_in_hands(P)
+ P = null
+
+/obj/item/clothing/suit/armor/plate_carrier/attackby(obj/item/W,mob/user)
+ ..()
+ if(istype(W, /obj/item/weapon/armor_plate))
+ if(P)
+ to_chat(user, "There is already \a [P] installed on \the [src].")
+ return
+ if(user.drop_item(W, src))
+ P = W
+ to_chat(user, "You install \the [W] into \the [src].")
+
+/obj/item/clothing/suit/armor/plate_carrier/examine(mob/user)
+ ..()
+ if(P)
+ to_chat(user, "It has \a [P] attached to it. Take a closer look.")
+
+/obj/item/clothing/suit/armor/plate_carrier/proc/handle_user_damage(list/arguments)
+ if(!P)
+ return
+ var/amount = arguments["amount"]
+ if(amount <= 0)
+ return
+ var/type = arguments["type"]
+
+ P.receive_damage(type, amount)
+ if(P.gcDestroyed)
+ P = null
+
+/obj/item/clothing/suit/armor/plate_carrier/security
+ name = "security plate armor"
+ icon_state = "security_armor"
+ item_state = "security_armor"
+ armor = list(melee = 10, bullet = 15, laser = 25, energy = 15, bomb = 5, bio = 0, rad = 0)
+
+/obj/item/weapon/armor_plate
+ icon = 'icons/obj/items.dmi'
+ icon_state = "plate_1"
+ name = "ceramic armor plate"
+ health = 20
+ armor = list(melee = 25, bullet = 7, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0)
+ armor_absorb = list(melee = 25, bullet = 20, laser = 20, energy = -5, bomb = 0, bio = 0, rad = 0)
+
+
+/obj/item/weapon/armor_plate/proc/receive_damage(var/type, var/amount)
+ if(type == BRUTE || type == BURN)
+ health -= amount
+ playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 70, 1)
+ if(health <= 0)
+ visible_message("\The [src] breaks apart!")
+ var/turf/T = get_turf(src)
+ playsound(T, "shatter", 70, 1)
+ getFromPool(/obj/effect/decal/cleanable/dirt,T)
+ if(prob(75))
+ var/obj/item/weapon/shard/shrapnel/S = new(T)
+ S.name = "[src] shrapnel"
+ S.desc = "[S.desc] It looks like it's from \a [src]."
+ qdel(src)
+
+/obj/item/weapon/armor_plate/examine(var/mob/user)
+ ..()
+ switch(health)
+ if(initial(health) to initial(health)/2)
+ to_chat(user, "\The [src] is hard.")
+ if(initial(health)/2-1 to initial(health)/4)
+ to_chat(user, "\The [src] is brittle.")
+ if(initial(health)/4-1 to 0)
+ to_chat(user, "\The [src] is falling apart!")
+
+/obj/item/weapon/armor_plate/bullet_resistant
+ name = "plasteel armor plate"
+ icon_state = "plate_2"
+ health = 30
+ armor = list(melee = 50, bullet = 50, laser = 10, energy = 10, bomb = 0, bio = 0, rad = 0)
+ armor_absorb = list(melee = 25, bullet = 40, laser = 10, energy = -5, bomb = 35, bio = 0, rad = 0)
+
+/obj/item/weapon/armor_plate/laser_resistant
+ name = "ceramite armor plate"
+ icon_state = "plate_3"
+ health = 30
+ armor = list(melee = 10, bullet = 10, laser = 80, energy = 50, bomb = 0, bio = 0, rad = 0)
+ armor_absorb = list(melee = 25, bullet = 20, laser = 40, energy = -5, bomb = 0, bio = 0, rad = 0)
\ No newline at end of file
diff --git a/code/modules/clothing/suits/wintercoat.dm b/code/modules/clothing/suits/wintercoat.dm
index dd0ea880e1a..d0ac79e1a03 100644
--- a/code/modules/clothing/suits/wintercoat.dm
+++ b/code/modules/clothing/suits/wintercoat.dm
@@ -50,12 +50,12 @@
name = "Head of Security's winter coat"
icon_state = "coathos"
nohood = 1
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS|IGNORE_INV
/obj/item/clothing/suit/wintercoat/security/warden
name = "Warden's winter coat"
icon_state = "coatwarden"
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS|IGNORE_INV
nohood = 1
/obj/item/clothing/suit/wintercoat/medical
@@ -93,7 +93,7 @@
name = "Head of Personnel's winter coat"
icon_state = "coathop"
armor = list(melee = 50, bullet = 10, laser = 25, energy = 10, bomb = 0, bio = 0, rad = 0)
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS|LEGS|IGNORE_INV
/obj/item/clothing/suit/wintercoat/miner
name = "mining winter coat"
diff --git a/code/modules/components/ai/atmos.dm b/code/modules/components/ai/atmos.dm
index d638df22737..70076a97228 100644
--- a/code/modules/components/ai/atmos.dm
+++ b/code/modules/components/ai/atmos.dm
@@ -1,11 +1,11 @@
/datum/component/ai/atmos_checker
//Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage
- var/min_oxy = 5
+ var/min_oxy = 5 / CELL_VOLUME
var/max_oxy = 0 //Leaving something at 0 means it's off - has no maximum
var/min_tox = 0
- var/max_tox = 1
+ var/max_tox = 1 / CELL_VOLUME
var/min_co2 = 0
- var/max_co2 = 5
+ var/max_co2 = 5 / CELL_VOLUME
var/min_n2 = 0
var/max_n2 = 0
var/unsuitable_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above
@@ -46,41 +46,41 @@
SendSignal(COMSIG_ADJUST_BODYTEMP, list("temp"=((Environment.temperature - controller.getBodyTemperature()) / 5)))
if(min_oxy)
- if(Environment.oxygen < min_oxy)
+ if(Environment.molar_density("oxygen") < min_oxy)
atmos_suitable = 0
oxygen_alert = 1
else
oxygen_alert = 0
if(max_oxy)
- if(Environment.oxygen > max_oxy)
+ if(Environment.molar_density("oxygen") > max_oxy)
atmos_suitable = 0
if(min_tox)
- if(Environment.toxins < min_tox)
+ if(Environment.molar_density("toxins") < min_tox)
atmos_suitable = 0
if(max_tox)
- if(Environment.toxins > max_tox)
+ if(Environment.molar_density("toxins") > max_tox)
atmos_suitable = 0
toxins_alert = 1
else
toxins_alert = 0
if(min_n2)
- if(Environment.nitrogen < min_n2)
+ if(Environment.molar_density("nitrogen") < min_n2)
atmos_suitable = 0
if(max_n2)
- if(Environment.nitrogen > max_n2)
+ if(Environment.molar_density("nitrogen") > max_n2)
atmos_suitable = 0
if(min_co2)
- if(Environment.carbon_dioxide < min_co2)
+ if(Environment.molar_density("carbon_dioxide") < min_co2)
atmos_suitable = 0
if(max_co2)
- if(Environment.carbon_dioxide > max_co2)
+ if(Environment.molar_density("carbon_dioxide") > max_co2)
atmos_suitable = 0
//Atmos effect
diff --git a/code/modules/components/ai/human/brain.dm b/code/modules/components/ai/human/brain.dm
index 8b550063a87..4b1ed5718b8 100644
--- a/code/modules/components/ai/human/brain.dm
+++ b/code/modules/components/ai/human/brain.dm
@@ -154,8 +154,8 @@
if(DESIRE_ID)
if((I.slot_flags & SLOT_ID) && I.mob_can_equip(H, slot_wear_id))
goal = I
- if(goal)
- break
+ if(goal)
+ break processing_desires
return goal
/datum/component/ai/human_brain/proc/AcquireItem(mob/living/carbon/human/H, obj/item/I)
diff --git a/code/modules/components/ai/human/human_target_finder.dm b/code/modules/components/ai/human/human_target_finder.dm
index 3f08d62c926..2a04a82cd8f 100644
--- a/code/modules/components/ai/human/human_target_finder.dm
+++ b/code/modules/components/ai/human/human_target_finder.dm
@@ -10,7 +10,7 @@
for(var/mob/M in view(range, container.holder))
if(is_type_in_list(M, exclude_types))
continue
- if(M.stat)
+ if(M.isUnconscious())
continue
if((M in B.enemies) || (M.faction && M.faction in B.enemy_factions) || (M.type in B.enemy_types))
o += M
diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm
index a4f7c3edca7..edd03d9fca6 100644
--- a/code/modules/customitems/item_spawning.dm
+++ b/code/modules/customitems/item_spawning.dm
@@ -1,6 +1,6 @@
/proc/EquipCustomItems(mob/living/carbon/human/M)
- testing("\[CustomItem\] Checking for custom items for [M.ckey] ([M.real_name])...")
+// testing("\[CustomItem\] Checking for custom items for [M.ckey] ([M.real_name])...")
if(!establish_db_connection())
return
@@ -26,7 +26,7 @@
var/path = text2path(query.item[1])
var/propadjust = query.item[2]
var/jobmask = query.item[3]
- testing("\[CustomItem\] Setting up [path] for [M.ckey] ([M.real_name]). jobmask=[jobmask];propadjust=[propadjust]")
+// testing("\[CustomItem\] Setting up [path] for [M.ckey] ([M.real_name]). jobmask=[jobmask];propadjust=[propadjust]")
var/ok=0
if(jobmask!="*")
var/allowed_jobs = splittext(jobmask,",")
@@ -35,12 +35,12 @@
if(!(M.mind.role_alt_title in allowed_jobs))
alt_blocked=1
if(!(M.mind.assigned_role in allowed_jobs) || alt_blocked)
- testing("Failed to apply custom item for [M.ckey]: Role(s) [M.mind.assigned_role][M.mind.role_alt_title ? " (nor "+M.mind.role_alt_title+")" : ""] are not in allowed_jobs ([english_list(allowed_jobs)])")
+// testing("Failed to apply custom item for [M.ckey]: Role(s) [M.mind.assigned_role][M.mind.role_alt_title ? " (nor "+M.mind.role_alt_title+")" : ""] are not in allowed_jobs ([english_list(allowed_jobs)])")
continue
var/obj/item/Item = new path()
- testing("Adding new custom item [query.item[1]] to [key_name_admin(M)]...")
+// testing("Adding new custom item [query.item[1]] to [key_name_admin(M)]...")
if(istype(Item,/obj/item/weapon/card/id))
var/obj/item/weapon/card/id/I = Item
for(var/obj/item/weapon/card/id/C in M)
@@ -58,24 +58,24 @@
C = null
ok = M.equip_if_possible(I, slot_wear_id, 0) //if 1, last argument deletes on fail
break
- testing("Replaced ID!")
+// testing("Replaced ID!")
else if(istype(M.back,/obj/item/weapon/storage) && M.back:contents.len < M.back:storage_slots) // Try to place it in something on the mob's back
Item.forceMove(M.back)
ok = 1
- testing("Added to [M.back.name]!")
+// testing("Added to [M.back.name]!")
to_chat(M, "Your [Item.name] has been added to your [M.back.name].")
else
for(var/obj/item/weapon/storage/S in M.contents) // Try to place it in any item that can store stuff, on the mob.
if (S.contents.len < S.storage_slots)
Item.forceMove(S)
ok = 1
- testing("Added to [S]!")
+// testing("Added to [S]!")
to_chat(M, "Your [Item.name] has been added to your [S.name].")
break
//skip:
if (ok == 0) // Finally, since everything else failed, place it on the ground
- testing("Plopped onto the ground!")
+// testing("Plopped onto the ground!")
Item.forceMove(get_turf(M.loc))
HackProperties(Item,propadjust)
diff --git a/code/modules/detectivework/detective_scanner.dm b/code/modules/detectivework/detective_scanner.dm
index e06559a2775..1ff8370be51 100644
--- a/code/modules/detectivework/detective_scanner.dm
+++ b/code/modules/detectivework/detective_scanner.dm
@@ -130,7 +130,7 @@
//PRINTS
if(fingerprints_found.len>0)
to_chat(user, "Isolated [fingerprints_found.len] fingerprints: Data Stored: Scan with Hi-Res Forensic Scanner to retrieve.")
- playsound(get_turf(src), 'sound/items/detscan.ogg', 50, 1)
+ playsound(src, 'sound/items/detscan.ogg', 50, 1)
var/list/complete_prints = list()
for(var/i in fingerprints_found)
@@ -148,7 +148,7 @@
//FIBERS
if(fibers_found.len)
to_chat(user, "Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve.")
- playsound(get_turf(src), 'sound/items/detscan.ogg', 50, 1)
+ playsound(src, 'sound/items/detscan.ogg', 50, 1)
//Blood
if (blood_DNA_found.len)
diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm
index 5873d0e17f0..83a1c36e019 100644
--- a/code/modules/detectivework/detective_work.dm
+++ b/code/modules/detectivework/detective_work.dm
@@ -100,9 +100,9 @@ var/const/FINGERPRINT_COMPLETE = 6 //This is the output of the stringpercent(pri
return
user.set_machine(src)
var/dat = ""
- var/isai = 0
- if(istype(usr,/mob/living/silicon))
- isai = 1
+ var/isai = FALSE
+ if(isAI(user))
+ isai = TRUE
if(temp)
dat += "[temp]
"
if(canclear)
@@ -146,11 +146,10 @@ var/const/FINGERPRINT_COMPLETE = 6 //This is the output of the stringpercent(pri
switch(href_list["operation"])
if("login")
var/mob/M = usr
- if(istype(M,/mob/living/silicon))
+ if(issilicon(M))
authenticated = 1
updateDialog()
- return
- if (allowed(M))
+ if(allowed(M))
authenticated = 1
if("logout")
authenticated = 0
@@ -167,14 +166,20 @@ var/const/FINGERPRINT_COMPLETE = 6 //This is the output of the stringpercent(pri
var/mob/M = usr
var/obj/item/I = M.get_active_hand()
if(I && istype(I))
- if(istype(I, /obj/item/weapon/evidencebag))
- scanning = I.contents[1]
- scanning.forceMove(src)
- I.overlays.len = 0
- I.icon_state = "evidenceobj"
- else
- if(M.drop_item(I, src))
- scanning = I
+ if(isgripper(I))
+ var/obj/item/weapon/gripper/G = I
+ if(G.wrapped)
+ scanning = G.wrapped //We add it as scanned object first because we'll lose the wrapped reference once we drop it.
+ G.drop_item(G.wrapped, src)
+ else
+ if(istype(I, /obj/item/weapon/evidencebag))
+ scanning = I.contents[1]
+ scanning.forceMove(src)
+ I.overlays.len = 0
+ I.icon_state = "evidenceobj"
+ else
+ if(M.drop_item(I, src))
+ scanning = I
else
to_chat(usr, "Invalid Object Rejected.")
if("card") //Processing a fingerprint card.
diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm
index 4acc9b92bed..9b54e6d49e8 100644
--- a/code/modules/error_handler/error_handler.dm
+++ b/code/modules/error_handler/error_handler.dm
@@ -101,7 +101,8 @@
desclines += " (This error will now be silenced for [configured_error_silence_time / 600] minutes)"
// Now to actually output the error info...
- world.log << "\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]"
+ var/main_line = "\[[time_stamp()]] Runtime in [e.file],[e.line]: [e]"
+ world.log << main_line
for (var/line in desclines)
world.log << line
@@ -109,4 +110,9 @@
if (global.error_cache)
global.error_cache.log_error(e, desclines)
+#ifdef UNIT_TESTS
+ if(global.current_test)
+ global.current_test.fail("[main_line]\n[desclines.Join("\n")]")
+#endif
+
#endif
diff --git a/code/modules/events/bluespaceanomaly.dm b/code/modules/events/bluespaceanomaly.dm
index b6232d935a2..b4307e4a90f 100644
--- a/code/modules/events/bluespaceanomaly.dm
+++ b/code/modules/events/bluespaceanomaly.dm
@@ -76,6 +76,8 @@
continue
if(istype(A, /atom/movable/lighting_overlay))
continue
+ if(A.flags & INVULNERABLE)
+ continue
var/turf/newloc = locate(A.x + x_distance, A.y + y_distance, TO.z) // calculate the new place
A.forceMove(newloc)
diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm
index 6bc34982d0e..5afcbdeeeb3 100644
--- a/code/modules/events/event_dynamic.dm
+++ b/code/modules/events/event_dynamic.dm
@@ -50,6 +50,7 @@ var/list/event_last_fired = list()
possibleEvents[/datum/event/communications_blackout] = 25
possibleEvents[/datum/event/thing_storm/meaty_gore] = 25
possibleEvents[/datum/event/unlink_from_centcomm] = 10
+ possibleEvents[/datum/event/centcomm_order] = 25
if(active_with_role["AI"] > 0 || active_with_role["Cyborg"] > 0)
possibleEvents[/datum/event/ionstorm] = 30
diff --git a/code/modules/events/infestation.dm b/code/modules/events/infestation.dm
index 49e43677c37..58542390dc0 100644
--- a/code/modules/events/infestation.dm
+++ b/code/modules/events/infestation.dm
@@ -48,7 +48,7 @@
var/list/spawn_types = list()
var/max_number = 4
- vermin = pick(VERM_MICE, VERM_LIZARDS, VERM_SPIDERS, VERM_SLIMES, VERM_BATS, VERM_BORERS, VERM_MIMICS, VERM_ROACHES, VERM_GREMLINS, VERM_BEES)
+ vermin = pick(VERM_MICE, VERM_LIZARDS, VERM_SPIDERS, VERM_SLIMES, VERM_BATS, VERM_BORERS, VERM_MIMICS, VERM_ROACHES, VERM_GREMLINS, VERM_BEES, VERM_HORNETS)
if (override_vermin)
vermin = override_vermin
@@ -59,7 +59,7 @@
max_number = 12
vermstring = "mice"
if(VERM_LIZARDS)
- spawn_types = list(/mob/living/simple_animal/lizard)
+ spawn_types = list(/mob/living/simple_animal/hostile/lizard)
max_number = 6
vermstring = "lizards"
if(VERM_SPIDERS)
@@ -88,27 +88,41 @@
vermstring = "gremlins"
max_number = 4 //2 to 4
if(VERM_BEES)
- spawn_types = /obj/machinery/apiary/wild
+ spawn_types = /obj/machinery/apiary/wild/angry
vermstring = "angry bees"
max_number = 2
+ if(VERM_HORNETS)
+ spawn_types = /obj/machinery/apiary/wild/angry/hornet
+ vermstring = "deadly hornets"
+ max_number = 1
var/number = rand(2, max_number)
- for(var/i = 0, i <= number, i++)
- var/area/A = locate(spawn_area_type)
- var/list/turf/simulated/floor/valid = list()
- //Loop through each floor in the supply drop area
- for(var/turf/simulated/floor/F in A)
- if(!F.has_dense_content())
- valid.Add(F)
+ var/area/A = locate(spawn_area_type)
+ var/list/turf/simulated/floor/valid = list()
+ //Loop through each floor in the supply drop area
+ for(var/turf/simulated/floor/F in A)
+ if(!F.has_dense_content())
+ valid.Add(F)
+ if(!valid.len)
+ message_admins("Infestation event failed! Could not find any viable turfs in [spawn_area_type] at which to spawn [number + 1] [vermstring].")
+ announceWhen = -1
+ endWhen = 0
+ return
+ for(var/i = 0, i <= number, i++)
var/picked = pick(valid)
if(vermin == VERM_SPIDERS)
var/mob/living/simple_animal/hostile/giant_spider/spiderling/S = new(picked)
S.amount_grown = 0
else
var/spawn_type = pick(spawn_types)
- new spawn_type(picked)
+ var/mob/M = new spawn_type(picked)
+ if(M.density)
+ valid -= picked
+ if(!valid.len)
+ message_admins("Infestation event could not find enough viable turfs in [spawn_area_type] to spawn all vermin. [number - i] [vermstring] were unable to spawn!")
+ break
/datum/event/infestation/announce()
var/warning = "Clear them out, before this starts to affect productivity."
diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm
index 28523385d82..d44ea574882 100644
--- a/code/modules/events/radiation_storm.dm
+++ b/code/modules/events/radiation_storm.dm
@@ -30,7 +30,7 @@
for(var/area/A in areas)
if(A.z != map.zMainStation || is_safe_zone(A))
continue
- var/area/ma = get_area_master(A)
+ var/area/ma = get_area(A)
ma.radiation_alert()
make_maint_all_access()
@@ -72,7 +72,7 @@
for(var/area/A in areas)
if(A.z != map.zMainStation || is_safe_zone(A))
continue
- var/area/ma = get_area_master(A)
+ var/area/ma = get_area(A)
ma.reset_radiation_alert()
diff --git a/code/modules/fish/fish_eggs.dm b/code/modules/fish/fish_eggs.dm
index 49841dadb91..dc077f0205c 100644
--- a/code/modules/fish/fish_eggs.dm
+++ b/code/modules/fish/fish_eggs.dm
@@ -20,8 +20,11 @@ var/list/fish_eggs_list = list("dud" = /obj/item/fish_eggs,
"shrimp" = /obj/item/fish_eggs/shrimp,
"electric eel" = /obj/item/fish_eggs/electric_eel,
"glofish" = /obj/item/fish_eggs/glofish,
+ "sea devil" = /obj/item/fish_eggs/seadevil
)
+var/list/nonhatching_types = list("sea devil") //If you ever want to create another no-egg fish, add it here.
+
/obj/item/fish_eggs/goldfish
name = "goldfish eggs"
desc = "Goldfish eggs, surprisingly, don't contain actual gold."
@@ -80,4 +83,18 @@ var/list/fish_eggs_list = list("dud" = /obj/item/fish_eggs,
name = "glofish eggs"
desc = "A cluster of bright neon eggs belonging to a bio-luminescent species of fish."
icon_state = "glofish_eggs"
- fish_type = "glofish"
\ No newline at end of file
+ fish_type = "glofish"
+
+/obj/item/fish_eggs/seadevil
+ name = "sea devil"
+ desc = "An aquatic offshoot of gremlins that engage in the peculiar behavior of hatching fish eggs to eat mature adults."
+ icon_state = "seadevil"
+ fish_type = "sea devil"
+
+/obj/item/fish_eggs/seadevil/New()
+ ..()
+ processing_objects += src
+
+/obj/item/fish_eggs/seadevil/process()
+ if(istype(loc, /turf) && prob(60))
+ Move(get_step(loc, pick(cardinal)))
\ No newline at end of file
diff --git a/code/modules/fish/fish_items.dm b/code/modules/fish/fish_items.dm
index 97284ffce32..d12f6093c5c 100644
--- a/code/modules/fish/fish_items.dm
+++ b/code/modules/fish/fish_items.dm
@@ -10,7 +10,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
"shrimp" = /obj/item/weapon/reagent_containers/food/snacks/shrimp,
"electric eel" = /obj/item/weapon/fish/electric_eel,
"glofish" = /obj/item/weapon/fish/glofish
-,
+, "sea devil" = /obj/item/fish_eggs/seadevil //You can fish a sea devil straight back out and stick it in another tank.
)
//////////////////////////////////////////////
@@ -84,7 +84,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
/obj/item/weapon/reagent_containers/food/snacks/shrimp/New()
..()
desc = pick("Anyway, like I was sayin', shrimp is the fruit of the sea.", "You can barbecue it, boil it, broil it, bake it, saute it.")
- reagents.add_reagent("NUTRIMENT", 1)
+ reagents.add_reagent(NUTRIMENT, 1)
/obj/item/weapon/reagent_containers/food/snacks/feederfish
name = "feeder fish"
@@ -96,7 +96,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
/obj/item/weapon/reagent_containers/food/snacks/feederfish/New()
..()
- reagents.add_reagent("NUTRIMENT", 1)
+ reagents.add_reagent(NUTRIMENT, 1)
/obj/item/weapon/fish
name = "fish"
@@ -116,6 +116,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
name = "glofish"
desc = "A small bio-luminescent fish. Not very bright, but at least it's pretty!"
icon_state = "glofish"
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/glofishmeat
/obj/item/weapon/fish/glofish/New()
..()
@@ -137,7 +138,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
if(istype(O, /obj/item/weapon/wirecutters))
to_chat(user, "You rip out the teeth of \the [src]!")
new /obj/item/weapon/fish/toothless_shark(get_turf(src))
- new /obj/item/stack/teeth/shark(get_turf(src))
+ new /obj/item/stack/teeth/shark(get_turf(src), 10)
qdel(src)
return
..()
@@ -171,6 +172,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
name = "goldfish"
desc = "A goldfish, just like the one you never won at the county fair."
icon_state = "goldfish"
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/goldfishmeat
/obj/item/weapon/fish/salmon
name = "salmon"
@@ -201,6 +203,7 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
icon_state = "clownfish"
throwforce = 1
force = 1
+ hitsound = 'sound/items/bikehorn.ogg'
attack_verb = list("slapped", "humiliated", "hit", "rubbed")
/obj/item/weapon/fish/attackby(var/obj/item/O, var/mob/user)
@@ -210,4 +213,4 @@ var/list/fish_items_list = list("goldfish" = /obj/item/weapon/fish/goldfish,
new meat_type(get_turf(src))
qdel(src)
return TRUE
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/modules/fish/fish_tank.dm b/code/modules/fish/fish_tank.dm
index 472034282ab..f9ff1f2f28a 100644
--- a/code/modules/fish/fish_tank.dm
+++ b/code/modules/fish/fish_tank.dm
@@ -23,7 +23,7 @@
// Made by FalseIncarnate on Paradise
// Ported to /vg/ by Shifty and jakmak(s)
-
+// Fish Bowl construction moved to code/game/machinery/constructable_frame.dm
/obj/machinery/fishtank
name = "placeholder tank"
@@ -42,7 +42,6 @@
var/lid_switch = FALSE // FALSE = open, TRUE = closed (open by default)
var/max_fish = 0 // How many fish the tank can support (varies with tank type, 1 fish per 50 units sounds reasonable)
var/food_level = 0 // Amount of fishfood floating in the tank (max 10)
- var/fish_list.len = 0 // Number of fish in the tank
var/list/fish_list = list() // Tracks the current types of fish in the tank
var/list/egg_list = list() // Tracks the current types of harvestable eggs in the tank
@@ -106,6 +105,10 @@
cur_health = 100
shard_count = 3
+/obj/machinery/fishtank/wall/full
+ water_level = 500
+ food_level = MAX_FOOD
+
/obj/machinery/fishtank/wall/Cross(atom/movable/mover, turf/target, height = 1.5, air_group = 0) // Prevents airflow. Copied from windows.
if(istype(mover) && mover.checkpass(PASSGLASS))
return TRUE
@@ -289,6 +292,18 @@
add_food(1) //The corpse became food for the other fish, ecology at it's finest
if("glofish")
glo_light++
+ if("clownfish")
+ if(prob(10))
+ playsound(src,'sound/items/bikehorn.ogg', 80, 1)
+ if("sea devil")
+ if(fish_list.len > 1 && prob(5))
+ //Small chance to eat a random fish that isn't itself.
+ seadevil_eat()
+
+ if(fish_list.len < max_fish && egg_list.len)
+ add_fish(get_key_by_element(fish_eggs_list,egg_list[1])) //add_fish takes a string. egg_list gives a path. fish_eggs_list is an associative list keyed with strings. get_key_by_index returns that string key by matching the path
+ egg_list -= egg_list[1]
+
if(!light_switch && (glo_light > 0))
set_light(2,glo_light,"#99FF66")
@@ -340,19 +355,43 @@
fish_list.Remove(pick(fish_list)) //Kill a random fish
update_icon()
+/obj/machinery/fishtank/proc/seadevil_eat()
+ var/tmp/list/fish_to_eat = fish_list.Copy()
+ fish_to_eat.Remove("sea devil")
+ var/eat_target = pick(fish_to_eat)
+ visible_message("The sea devil devours \an [eat_target].")
+ kill_fish(eat_target)
+
/obj/machinery/fishtank/proc/add_fish(var/type)
+ if(!type || type == "dud")
+ return
//Check if we were passed a fish type
fish_list.Add("[type]") //Add a fish of the specified type
//Announce the new fish
update_icon()
- visible_message("A new [type] has hatched in \the [src]!")
+ if(nonhatching_types.Find(type))
+ visible_message("The [type] has been placed in \the [src]!")
+ else
+ visible_message("A new [type] has hatched in \the [src]!")
/obj/machinery/fishtank/proc/select_egg_type()
- var/fish = pick(fish_list) //Select a fish from the fish in the tank
- if(prob(25)) //25% chance to be a dud (blank) egg
+ var/fish = null
+ if(prob(10)) //Small chance for infertility
fish = "dud"
+ else
+ fish = recursive_valid_egg(fish_list)
var/obj/item/fish_eggs/egg_path = fish_eggs_list[fish] //Locate the corresponding path from fish_eggs_list that matches the fish
- return egg_path //The fish was located in the fish_eggs_list, so return the proper egg
+ return egg_path
+
+/obj/machinery/fishtank/proc/recursive_valid_egg(var/list/pick_egg_from)
+ var/fish = pick(pick_egg_from)
+ if(!fish || nonhatching_types.Find(fish))
+ var/tmp/list/new_list = pick_egg_from.Copy()
+ return recursive_valid_egg(new_list.Remove(fish))
+ //If it's a nonvalid type, let's try again without it.
+ else
+ return fish
+ //If it's valid, return this.
/obj/machinery/fishtank/proc/harvest_eggs(var/mob/user)
if(!egg_list.len) //Can't harvest non-existant eggs
@@ -488,7 +527,7 @@
for (var/i = 1 to fish_list.len)
if(fish_list.len > 1 && i == fish_list.len) //If there were at least 2 fish, and this is the last one, add "and" to the message
message += "and "
- message += "a [fish_list[i]]"
+ message += "\an [fish_list[i]]"
if(i < fish_list.len) //There's more fish, add a comma to the message
message +=", "
message +="." //No more fish, end the message with a period
@@ -702,13 +741,67 @@
hit(O, user)
return TRUE
-/* tank construction */
+//Conduction plate for electric eels
-/obj/structure/displaycase_frame/attackby(var/obj/item/weapon/F, var/mob/user) // FISH BOWL
- if (iswelder(F))
- to_chat(user, "You use the machine frame as a vice and shape the glass with the welder into a fish bowl.")
- getFromPool(/obj/item/stack/sheet/metal, get_turf(src), 5)
- new /obj/machinery/fishtank/bowl(get_turf(src))
- qdel(src)
- return TRUE
+/obj/machinery/power/conduction_plate
+ name = "conduction plate"
+ icon = 'icons/mecha/mech_bay.dmi'
+ icon_state = "recharge_floor"
+ layer = ABOVE_TILE_LAYER
+ plane = ABOVE_TURF_PLANE
+ anchored = 1
+ density = 0
+ machine_flags = SCREWTOGGLE | CROWDESTROY | FIXED2WORK
+
+ component_parts = newlist(
+ /obj/item/weapon/circuitboard/conduction_plate,
+ /obj/item/weapon/stock_parts/capacitor
+ )
+
+ var/obj/machinery/fishtank/attached_tank = null
+ var/multiplier = 0.9
+
+/obj/machinery/power/conduction_plate/New()
+ ..()
+ if(anchored)
+ connect_to_network()
+ RefreshParts()
+
+/obj/machinery/power/conduction_plate/RefreshParts()
+ for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts)
+ multiplier = initial(multiplier) + (C.rating*0.1) //1 to 1.2
+
+/obj/machinery/power/conduction_plate/process()
+ if(check_tank())
+ var/power = 0
+ for(var/fish in attached_tank.fish_list)
+ if(fish == "electric eel")
+ power += ARBITRARILY_LARGE_NUMBER * multiplier //10000
+ add_avail(power)
+
+/obj/machinery/power/conduction_plate/proc/check_tank()
+ //Are we anchored?
+ if(!anchored)
+ return 0
+
+ //Is our old tank is still valid?
+ if(attached_tank && attached_tank.loc == loc)
+ return 1
+
+ //No? Let's look for a new one.
+ attached_tank = locate(/obj/machinery/fishtank/) in loc
+ if(attached_tank)
+ return 1
+ else
+ return 0
+
+/obj/machinery/power/conduction_plate/wrenchAnchor(var/mob/user)
+ . = ..()
+ if(!.)
+ return
+ attached_tank = null
+ if(anchored)
+ connect_to_network()
+ else
+ disconnect_from_network()
\ No newline at end of file
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 4ae1e4b43fa..647016add65 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -67,10 +67,8 @@ mob/living/carbon/proc/handle_hallucinations()
halitem.name = "Revolver"
if(2) //c4
halitem.icon = 'icons/obj/assemblies.dmi'
- halitem.icon_state = "plastic-explosive0"
+ halitem.icon_state = pick("plastic-explosive0", "plastic-explosive2")
halitem.name = "Mysterious Package"
- if(prob(25))
- halitem.icon_state = "c4small_1"
if(3) //sword
halitem.icon = 'icons/obj/weapons.dmi'
halitem.icon_state = "sword1"
@@ -311,7 +309,35 @@ mob/living/carbon/proc/handle_hallucinations()
spawn(duration)
if(C)
C.images.Remove(foodie) //Remove the image from hallucinating mob
- if(87 to 88) //Turns your screen
+ if(87)
+ var/mob/living/L
+
+ var/list/mob_list=list()
+ for(var/mob/living/M in viewers(src))
+ mob_list |= M
+
+ if(mob_list.len)
+ L = pick(mob_list)
+
+ var/mob/living/simple_animal/random_mob = pick(existing_typesof(/mob/living/simple_animal/hostile))
+ var/image/horror = image(icon = null)
+ horror.appearance = initial(random_mob.appearance)
+
+ horror.loc = L
+ horror.override = 1 //Override the affected mob's appearance with the monster
+
+ var/client/C = src.client //Get client of the hallucinating mob
+ if(C)
+ C.images += horror //Give it the image!
+
+ var/duration = rand(60 SECONDS, 120 SECONDS)
+ if(src.client)
+ message_admins("[key_name(src)] just imagined that [L] looks like a [random_mob], spooky! [formatJumpTo(get_turf(src))]")
+ spawn(duration)
+ if(C)
+ C.images.Remove(horror) //Remove the image from hallucinating mob
+
+ if(88) //Turns your screen
var/angle = rand(1,3)*90
var/duration = rand(10 SECONDS, 40 SECONDS)
diff --git a/code/modules/food/cooking_machines.dm b/code/modules/food/cooking_machines.dm
index b7e64e8238f..9e48cac07c5 100644
--- a/code/modules/food/cooking_machines.dm
+++ b/code/modules/food/cooking_machines.dm
@@ -250,7 +250,7 @@ var/global/ingredientLimit = 10
src.icon_state = src.icon_state_on
if (cook_after(src.cookTime, 25))
src.makeFood(foodType)
- playsound(get_turf(src),src.cookSound,100,1)
+ playsound(src,src.cookSound,100,1)
src.active = 0
src.icon_state = initial(src.icon_state)
return
@@ -400,7 +400,7 @@ var/global/ingredientLimit = 10
reagents.update_total() //make the values refresh
if(ingredient)
icon_state = "fryer_on"
- playsound(get_turf(src),'sound/machines/deep_fryer.ogg',100,1) // If cookSound is used, the sound starts when the cooking ends. We don't want that.
+ playsound(src,'sound/machines/deep_fryer.ogg',100,1) // If cookSound is used, the sound starts when the cooking ends. We don't want that.
else if(reagents.total_volume < DEEPFRY_MINOIL)
icon_state = "fryer_empty"
else
@@ -469,7 +469,7 @@ var/global/ingredientLimit = 10
//Deepfry a random nearby item
var/list/pickable_items = list()
- for(var/obj/item/I in range(1, L))
+ for(var/obj/item/I in adjacent_atoms(L))
pickable_items.Add(I)
if(!pickable_items.len)
@@ -531,7 +531,7 @@ var/global/ingredientLimit = 10
reagents.update_total() //make the values refresh
if(ingredient)
icon_state = "confectionator_on"
- playsound(get_turf(src),'sound/machines/juicer.ogg',100,1) // If cookSound is used, the sound starts when the cooking ends. We don't want that.
+ playsound(src,'sound/machines/juicer.ogg',100,1) // If cookSound is used, the sound starts when the cooking ends. We don't want that.
else if(reagents.total_volume < CONFECTIONATOR_MINSUGAR)
icon_state = "confectionator_empty"
else
@@ -606,7 +606,7 @@ var/global/ingredientLimit = 10
if (cook_after(src.cookTime/3, 14))
src.makeFood()
if(use_power)
- playsound(get_turf(src),src.cookSound,100,1)
+ playsound(src,src.cookSound,100,1)
else
src.visible_message("\the [foodname] looks ready to eat!")
src.icon_state = initial(src.icon_state)
diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm
index f7983d79cc3..b25538e9362 100644
--- a/code/modules/food/recipes_microwave.dm
+++ b/code/modules/food/recipes_microwave.dm
@@ -2432,4 +2432,157 @@
/obj/item/weapon/fish/electric_eel
)
- result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Unagi
\ No newline at end of file
+ result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Unagi
+
+/datum/recipe/sushi_avocado
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/boiledrice,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/avocado/cut/pitted
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/sushi_avocado
+
+/datum/recipe/friedshrimp
+ reagents = list(CORNOIL = 5)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/shrimp
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/friedshrimp
+
+/datum/recipe/soyscampi
+ reagents = list(SOYSAUCE = 5)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/shrimp
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/soyscampi
+
+/datum/recipe/shrimpcocktail
+ reagents = list(KETCHUP = 10)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/shrimp,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/lemon
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/shrimpcocktail
+
+/datum/recipe/friedcatfish
+ reagents = list(CORNOIL = 5)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/catfishmeat
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/friedcatfish
+
+/datum/recipe/gumbo
+ reagents = list(WATER = 10)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/catfishmeat,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/garlic
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/catfishgumbo
+
+/datum/recipe/catfishcourtbouillon
+ reagents = list(CAPSAICIN = 5, FLOUR = 5)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/catfishmeat
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/catfishcourtbouillon
+
+/datum/recipe/smokedsalmon
+ reagents = list(BLACKPEPPER = 1)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/salmonmeat,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/chili
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/smokedsalmon
+
+/datum/recipe/planksalmon
+ reagents = list(HONEY = 5)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/salmonmeat,
+ /obj/item/stack/sheet/wood
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/planksalmon
+
+/datum/recipe/citrussalmon
+ reagents = list(BLACKPEPPER = 1)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/salmonmeat,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/lemon,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/orange
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/citrussalmon
+
+/datum/recipe/salmonavocado
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/salmonmeat,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/avocado/cut/pitted
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/salmonavocado
+
+/datum/recipe/rumshark
+ reagents = list(BLACKPEPPER = 15, RUM = 15)
+ items = list(/obj/item/weapon/fish/toothless_shark,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/garlic
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/rumshark
+
+/datum/recipe/akutaq
+ reagents = list(MILK = 10)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/glofishmeat,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/glowberries
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/akutaq
+
+/datum/recipe/carpcurry
+ reagents = list(VINEGAR = 5, RICE = 10)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/goldfishmeat
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/carpcurry
+
+/datum/recipe/carpconsomme
+ reagents = list(WATER = 10)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/goldfishmeat,
+ /obj/item/weapon/reagent_containers/food/snacks/egg
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/carpconsomme
+
+/datum/recipe/butterstick
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/butter,
+ /obj/item/stack/rods
+ )
+ result = /obj/item/weapon/reagent_containers/food/snacks/butterstick
+
+/datum/recipe/ambrosia_brownies
+ reagents = list(COCO = 10, SUGAR = 10, FLOUR = 15)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/butter,
+ /obj/item/weapon/reagent_containers/food/snacks/egg,
+ /obj/item/weapon/reagent_containers/food/snacks/egg,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris,
+ /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosiavulgaris,
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/ambrosia_brownies
+
+/datum/recipe/butterfingers_r
+ items = list(/obj/item/organ/external/r_hand,
+ /obj/item/weapon/reagent_containers/food/snacks/butter,
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/butterfingers_r/
+
+/datum/recipe/butterfingers_l
+ items = list(/obj/item/organ/external/l_hand,
+ /obj/item/weapon/reagent_containers/food/snacks/butter,
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/butterfingers_l/
+
+/datum/recipe/butteredtoast
+ reagents = list(LIQUIDBUTTER = 2)
+ items = list(/obj/item/weapon/reagent_containers/food/snacks/breadslice,
+ )
+
+ result = /obj/item/weapon/reagent_containers/food/snacks/butteredtoast
\ No newline at end of file
diff --git a/code/modules/games/cards/wizard_cards.dm b/code/modules/games/cards/wizard_cards.dm
index 698c32d541e..5e054ae4ae3 100644
--- a/code/modules/games/cards/wizard_cards.dm
+++ b/code/modules/games/cards/wizard_cards.dm
@@ -100,7 +100,7 @@ var/global/list/wizard_cards_normal = list(
to_chat(user, "Honkmother is not ready yet!")
return
- playsound(get_turf(src), 'sound/items/AirHorn.ogg', 50, 1)
+ playsound(src, 'sound/items/AirHorn.ogg', 50, 1)
/obj/item/toy/singlecard/wizard/legendary/honkmother/pickup(mob/living/user as mob)
if(user.mind && user.mind.assigned_role == "Clown")
@@ -139,7 +139,7 @@ var/global/list/wizard_cards_normal = list(
to_chat(user, "The clown is not ready yet!")
return
- playsound(get_turf(src), 'sound/items/bikehorn.ogg', 50, 1)
+ playsound(src, 'sound/items/bikehorn.ogg', 50, 1)
/obj/item/toy/singlecard/wizard/bomberman
name = "bomberman wizard card"
diff --git a/code/modules/html_interface/map/station_map.dm b/code/modules/html_interface/map/station_map.dm
index b679b6a8d15..6795fc5124d 100644
--- a/code/modules/html_interface/map/station_map.dm
+++ b/code/modules/html_interface/map/station_map.dm
@@ -30,8 +30,10 @@
//Station Holomaps display the map of the Z-Level they were built on.
generateStationMinimap(map.zMainStation)
- generateStationMinimap(map.zAsteroid)
- generateStationMinimap(map.zDerelict)
+ if(world.maxz >= map.zAsteroid)
+ generateStationMinimap(map.zAsteroid)
+ if(world.maxz >= map.zDerelict)
+ generateStationMinimap(map.zDerelict)
//If they were built on another Z-Level, they will display an error screen.
holomaps_initialized = 1
diff --git a/code/modules/html_interface/voting/voting.dm b/code/modules/html_interface/voting/voting.dm
index d4532cafd21..b04e284ebea 100644
--- a/code/modules/html_interface/voting/voting.dm
+++ b/code/modules/html_interface/voting/voting.dm
@@ -37,6 +37,7 @@ var/global/datum/controller/vote/vote = new()
var/list/voted = list()
var/list/voting = list()
var/list/current_votes = list()
+ var/list/discarded_choices = list()
var/list/ismapvote
var/chosen_map
name = "datum"
@@ -47,6 +48,8 @@ var/global/datum/controller/vote/vote = new()
var/initialized = 0
var/lastupdate = 0
var/total_votes = 0
+ var/vote_threshold = 0.15
+ var/discarded_votes = 0
var/weighted = FALSE // Whether to use weighted voting.
// Jesus fuck some shitcode is breaking because it's sleeping and the SS doesn't like it.
@@ -106,6 +109,8 @@ var/global/datum/controller/vote/vote = new()
voted.len = 0
voting.len = 0
total_votes = 0
+ discarded_votes = 0
+ discarded_choices.len = 0
current_votes.len = 0
weighted = FALSE
update(1)
@@ -156,6 +161,11 @@ var/global/datum/controller/vote/vote = new()
for(var/a in filteredchoices)
if(!filteredchoices[a])
filteredchoices -= a //Remove choices with 0 votes, as pickweight gives them 1 vote
+ continue
+ if(filteredchoices[a] / total_votes < vote_threshold)
+ discarded_votes += filteredchoices[a]
+ filteredchoices -= a
+ discarded_choices += a
if(filteredchoices.len)
. += pickweight(filteredchoices.Copy())
else
@@ -171,6 +181,7 @@ var/global/datum/controller/vote/vote = new()
var/list/winners = get_result()
var/text
var/feedbackanswer
+ var/qualified_votes = total_votes - discarded_votes
if(winners.len > 0)
if(winners.len > 1)
text = "Vote Tied Between: "
@@ -185,11 +196,11 @@ var/global/datum/controller/vote/vote = new()
else
feedback_set("map vote tie", "[feedbackanswer] chosen: [.]")
- text += "[weighted ? "Random Weighted " : ""]Vote Result: [.] won with [choices[.]] vote\s[weighted? " and a [round(100*choices[.]/total_votes)]% chance of winning" : null]."
+ text += "[weighted ? "Random Weighted " : ""]Vote Result: [.] won with [choices[.]] vote\s[weighted? " and a [round(100*choices[.]/qualified_votes)]% chance of winning" : null]."
for(var/choice in choices)
if(. == choice)
continue
- text += " \t [choice] had [choices[choice] != null ? choices[choice] : "0"] vote\s[(weighted&&choices[choice])? " and a [round(100*choices[choice]/total_votes)]% chance of winning" : null]."
+ text += " \t [choice] had [choices[choice] != null ? choices[choice] : "0"] vote\s[(weighted&&choices[choice])? " and [(choice in discarded_choices) ? "did not get enough votes to qualify" : "a [round(100*choices[choice]/qualified_votes)]% chance of winning"]" : null]."
else
text += "Vote Result: Inconclusive - No Votes!"
log_vote(text)
diff --git a/code/modules/hydroponics/eggincubator.dm b/code/modules/hydroponics/eggincubator.dm
index e1385be9174..e9015a23b77 100644
--- a/code/modules/hydroponics/eggincubator.dm
+++ b/code/modules/hydroponics/eggincubator.dm
@@ -106,7 +106,7 @@
use_power = 2
update_icon()
if(handle_growth(contents))
- playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1) //Only ding once per process
+ playsound(src, 'sound/machines/ding.ogg', 50, 1) //Only ding once per process
src.updateUsrDialog()
diff --git a/code/modules/hydroponics/hydro_tools.dm b/code/modules/hydroponics/hydro_tools.dm
index a808c0c0dee..27e7ef9fe1e 100644
--- a/code/modules/hydroponics/hydro_tools.dm
+++ b/code/modules/hydroponics/hydro_tools.dm
@@ -325,6 +325,8 @@
force = 5.0
throwforce = 7.0
w_class = W_CLASS_SMALL
+ starting_materials = list(MAT_IRON = 50)
+ w_type = RECYK_METAL
attack_verb = list("slashes", "slices", "cuts", "claws")
@@ -418,6 +420,8 @@
siemens_coefficient = 1
force = 12.0
w_class = W_CLASS_SMALL
+ starting_materials = list(MAT_IRON = 5000)
+ w_type = RECYK_METAL
throwforce = 15.0
throw_speed = 4
throw_range = 4
diff --git a/code/modules/hydroponics/hydro_tray.dm b/code/modules/hydroponics/hydro_tray.dm
index 24f9f60f840..51f186bea39 100644
--- a/code/modules/hydroponics/hydro_tray.dm
+++ b/code/modules/hydroponics/hydro_tray.dm
@@ -512,13 +512,13 @@
/obj/machinery/portable_atmospherics/hydroponics/HasProximity(mob/living/simple_animal/M)
if(seed && !dead && seed.carnivorous == 2 && age > seed.maturation)
- if(istype(M, /mob/living/simple_animal/mouse) || istype(M, /mob/living/simple_animal/lizard) && !M.locked_to && !M.anchored)
+ if(istype(M, /mob/living/simple_animal/mouse) || istype(M, /mob/living/simple_animal/hostile/lizard) && !M.locked_to && !M.anchored)
spawn(10)
if(!M || !Adjacent(M) || M.locked_to || M.anchored)
return // HasProximity() will likely fire a few times almost simultaneously, so spawn() is tricky with it's sanity
visible_message("\The [seed.display_name] hungrily lashes a vine at \the [M]!")
if(M.health > 0)
- M.Die()
+ M.death()
lock_atom(M, /datum/locking_category/hydro_tray)
spawn(30)
if(M && M.loc == get_turf(src))
@@ -555,4 +555,7 @@
..()
+/obj/machinery/portable_atmospherics/hydroponics/AltClick()
+ close_lid()
+
/datum/locking_category/hydro_tray
diff --git a/code/modules/hydroponics/hydro_tray_process.dm b/code/modules/hydroponics/hydro_tray_process.dm
index d804b175309..7d8f04df5e1 100644
--- a/code/modules/hydroponics/hydro_tray_process.dm
+++ b/code/modules/hydroponics/hydro_tray_process.dm
@@ -176,17 +176,11 @@
for(var/gas in seed.exude_gasses)
environment.adjust_gas(gas, max(1,round((seed.exude_gasses[gas]*round(seed.potency))/seed.exude_gasses.len)))
- // This was adapted from the air alarm code
- // I've never done atmos or touched atmos code before so there's a chance I've fucked this up
if(seed.alter_temp)
- if(istype(T, /turf/simulated/))
- var/datum/gas_mixture/room = T.remove_air(environment.total_moles)
- if(room.temperature < seed.ideal_heat-seed.heat_tolerance)
- room.temperature += (seed.potency*3)
- else if (room.temperature > seed.ideal_heat+seed.heat_tolerance)
- room.temperature -= (seed.potency*3)
- room.react()
- T.assume_air(room)
+ if((environment.temperature < seed.ideal_heat - seed.heat_tolerance) || (environment.temperature > seed.ideal_heat + seed.heat_tolerance))
+ var/energy_cap = seed.potency * 60 * MOLES_CELLSTANDARD //This is totally arbitrary. It just serves to approximate the behavior from when this modified temperature rather than thermal energy.
+ var/energy_change = Clamp(environment.get_thermal_energy_change(seed.ideal_heat), -energy_cap, energy_cap)
+ environment.add_thermal_energy(energy_change)
// If we're attached to a pipenet, then we should let the pipenet know we might have modified some gasses
//if (closed_system && connected_port)
diff --git a/code/modules/hydroponics/seed_machines.dm b/code/modules/hydroponics/seed_machines.dm
index 12038dd82c1..d65cd9a4a33 100644
--- a/code/modules/hydroponics/seed_machines.dm
+++ b/code/modules/hydroponics/seed_machines.dm
@@ -42,6 +42,18 @@
var/eject_disk = 0
var/failed_task = 0
var/disk_needs_genes = 0
+ var/time_coeff = 1
+ var/degradation_coeff = 1
+
+/obj/machinery/botany/RefreshParts()
+ var/T = 0
+ for(var/obj/item/weapon/stock_parts/micro_laser/ML in component_parts)
+ T += ML.rating
+ degradation_coeff = round(T/2)
+ T = 0
+ for(var/obj/item/weapon/stock_parts/manipulator/MA in component_parts)
+ T += MA.rating
+ time_coeff = T
/obj/machinery/botany/process()
@@ -49,7 +61,7 @@
if(!active)
return
- if(world.time > last_action + action_time)
+ if(world.time > last_action + action_time/time_coeff)
finished_task()
/obj/machinery/botany/attack_paw(mob/user as mob)
@@ -143,6 +155,8 @@
/obj/item/weapon/stock_parts/matter_bin,
)
+ RefreshParts()
+
/obj/machinery/botany/extractor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = NANOUI_FOCUS)
if(!user)
@@ -263,7 +277,7 @@
loaded_disk.desc += " The label reads 'gene [href_list["get_gene"]], sampled from [genetics.display_name]'."
eject_disk = 1
- degradation += rand(20,60)
+ degradation += round(rand(20,60)/degradation_coeff)
if(degradation >= 100)
failed_task = 1
genetics = null
@@ -296,6 +310,9 @@
/obj/item/weapon/stock_parts/console_screen,
)
+ RefreshParts()
+
+
/obj/machinery/botany/editor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = NANOUI_FOCUS)
if(!user)
@@ -363,7 +380,7 @@
for(var/datum/plantgene/gene in loaded_disk.genes)
loaded_seed.seed.apply_gene(gene, mode)
- loaded_seed.modified += rand(5,10)
+ loaded_seed.modified += round(rand(5,10)/degradation_coeff)
else if(href_list["toggle_mode"])
switch(mode)
diff --git a/code/modules/hydroponics/seed_mobs.dm b/code/modules/hydroponics/seed_mobs.dm
index d23ab334ee3..1de889f5d8a 100644
--- a/code/modules/hydroponics/seed_mobs.dm
+++ b/code/modules/hydroponics/seed_mobs.dm
@@ -1,5 +1,6 @@
/datum/seed
var/product_requires_player // If yes, product will ask for a player among the ghosts.
+ var/product_kill_inactive = TRUE // If yes, the product will autodie after a certain amount of time
var/list/currently_querying // Used to avoid asking the same ghost repeatedly.
var/searching = 0 // Are we currently looking for a ghost?
@@ -14,18 +15,19 @@
currently_querying = list()
request_player(host)
- spawn(675)
- if(!host.ckey && !host.client)
- host.death() // This seems redundant, but a lot of mobs don't
- host.stat = 2 // handle death() properly. Better safe than etc.
- host.visible_message("[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.")
+ if(product_kill_inactive)
+ spawn(675)
+ if(!host.ckey && !host.client)
+ host.death() // This seems redundant, but a lot of mobs don't
+ host.stat = 2 // handle death() properly. Better safe than etc.
+ host.visible_message("[host] is malformed and unable to survive. It expires pitifully, leaving behind some seeds.")
- if(mob_drop)
- new mob_drop(get_turf(host))
- else
- var/obj/item/seeds/S = new(get_turf(host))
- S.seed_type = name
- S.update_seed()
+ if(mob_drop)
+ new mob_drop(get_turf(host))
+ else
+ var/obj/item/seeds/S = new(get_turf(host))
+ S.seed_type = name
+ S.update_seed()
//poll="Someone is harvesting [display_name]. Would you like to play as one?"
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 1c80f586ad0..38436acbeba 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -64,6 +64,11 @@
seed_type = "diona"
vending_cat = "sentient"
+/obj/item/seeds/mushroommanspore
+ name = "packet of mushrom spores"
+ seed_type = "moshrum"
+ vending_cat = "sentient"
+
/obj/item/seeds/poppyseed
name = "packet of poppy seeds"
seed_type = "poppies"
@@ -120,6 +125,11 @@
seed_type = "banana"
vending_cat = "fruits"
+/obj/item/seeds/bluespacebananaseed
+ name = "packet of bluespace banana seeds"
+ seed_type = "bluespacebanana"
+ vending_cat = "fruits"
+
/obj/item/seeds/eggplantseed
name = "packet of eggplant seeds"
seed_type = "eggplant"
@@ -890,11 +900,11 @@
products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/angel)
packet_icon = "mycelium-angel"
plant_icon = "angel"
- chems = list(NUTRIMENT = list(1,50), AMATOXIN = list(13,3), PSILOCYBIN = list(1,25))
+ chems = list(NUTRIMENT = list(1,50), AMANATIN = list(1,3))
maturation = 12
yield = 2
- potency = 35
+ potency = 15
/datum/seed/mushroom/towercap
name = "towercap"
@@ -1162,6 +1172,7 @@
plant_icon = "banana"
harvest_repeat = 1
chems = list(BANANA = list(1,10), POTASSIUMCARBONATE = list(0.1,30))
+ mutants = list("bluespacebanana")
lifespan = 50
maturation = 6
@@ -1171,6 +1182,15 @@
water_consumption = 6
ideal_heat = 298
+/datum/seed/banana/bluespace
+ name = "bluespacebanana"
+ seed_name = "bluespacebanana"
+ display_name = "bluespace banana tree"
+ packet_icon = "seed-bluespacebanana"
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/bluespacebanana)
+ plant_icon = "banana"
+ mutants = null
+
/datum/seed/corn
name = "corn"
seed_name = "corn"
@@ -1566,6 +1586,28 @@
yield = 10
potency = 30
+/datum/seed/moshrum
+ name = "moshrum"
+ seed_name = "moshrum"
+ seed_noun = "nodules"
+ display_name = "moshrum nodes"
+ packet_icon = "mycelium-walkingmushroom"
+ plant_icon = "walkingmushroom"
+ products = list(/mob/living/carbon/monkey/mushroom)
+ mob_drop = /obj/item/seeds/mushroommanspore
+ product_requires_player = TRUE
+ product_kill_inactive = FALSE
+ immutable = TRUE
+
+ lifespan = 50
+ endurance = 35
+ maturation = 5
+ production = 10
+ yield = 2
+ potency = 30
+ ideal_light = 0
+
+
/datum/seed/test
name = "test"
seed_name = "testing"
diff --git a/code/modules/library/computers/checkout.dm b/code/modules/library/computers/checkout.dm
index bf25e44d1b8..ab428d93de8 100644
--- a/code/modules/library/computers/checkout.dm
+++ b/code/modules/library/computers/checkout.dm
@@ -315,14 +315,29 @@
if("6")
if(!bibledelay)
- var/obj/item/weapon/storage/bible/B = new /obj/item/weapon/storage/bible(src.loc)
- if(ticker && ( ticker.Bible_icon_state && ticker.Bible_item_state) )
+ bibledelay = 1
+
+ var/obj/item/weapon/storage/bible/B = new
+ B = new(src.loc)
+ if (usr.mind && usr.mind.faith) // The user has a faith
+ var/datum/religion/R = usr.mind.faith
+ var/obj/item/weapon/storage/bible/HB = R.holy_book
+ if (!HB)
+ B = chooseBible(R, usr)
+ else
+ B.icon_state = HB.icon_state
+ B.item_state = HB.item_state
+ B.name = R.bible_name
+ B.my_rel = R
+
+ else if (ticker && (ticker.Bible_icon_state && ticker.Bible_item_state)) // No faith
B.icon_state = ticker.Bible_icon_state
B.item_state = ticker.Bible_item_state
B.name = ticker.Bible_name
- B.my_rel.deity_name = ticker.Bible_deity_name
+ B.my_rel = ticker.chap_rel
+
+ B.forceMove(src.loc)
- bibledelay = 1
spawn(60)
bibledelay = 0
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index dd3196c517e..a22df0450a7 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -54,13 +54,13 @@
to_chat(user, "There are no screws on \the [src], it appears to be nailed together. You could probably disassemble it with just a crowbar.")
return
else if(iscrowbar(O) && user.a_intent == I_HELP) //Only way to deconstruct, needs help intent
- playsound(get_turf(src), 'sound/items/Crowbar.ogg', 75, 1)
+ playsound(src, 'sound/items/Crowbar.ogg', 75, 1)
user.visible_message("[user] starts disassembling \the [src].", \
"You start disassembling \the [src].")
busy = 1
if(do_after(user, src, 50))
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 75, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 75, 1)
user.visible_message("[user] disassembles \the [src].", \
"You disassemble \the [src].")
busy = 0
@@ -72,7 +72,7 @@
return
else if(iswrench(O))
anchored = !anchored
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
user.visible_message("[user] [anchored ? "":"un"]anchors \the [src] [anchored ? "to":"from"] the floor.", \
"You [anchored ? "":"un"]anchor the [src] [anchored ? "to":"from"] the floor.")
else if(istype(O, /obj/item/weapon/pen))
diff --git a/code/modules/maps/nests.dm b/code/modules/maps/nests.dm
index 6339a62caa6..37766ac4a58 100644
--- a/code/modules/maps/nests.dm
+++ b/code/modules/maps/nests.dm
@@ -37,7 +37,7 @@
/obj/abstract/map/nest/lizard
name = "lizard breeding ground"
icon_state = "lizard"
- mob_type = /mob/living/simple_animal/lizard
+ mob_type = /mob/living/simple_animal/hostile/lizard
/obj/abstract/map/nest/mouse
name = "mouse breeding ground"
@@ -56,6 +56,11 @@
mob_type = /mob/living/simple_animal/hostile/giant_spider
pop_max = 10
+/obj/abstract/map/nest/spider/limited
+ name = "spider breeding ground"
+ pop = 2
+ pop_max = 2
+
/obj/abstract/map/nest/carp
name = "carp breeding ground"
icon_state = "carp"
diff --git a/code/modules/maps/spawners/spawners.dm b/code/modules/maps/spawners/spawners.dm
index 4f88548996c..8831cd832bb 100644
--- a/code/modules/maps/spawners/spawners.dm
+++ b/code/modules/maps/spawners/spawners.dm
@@ -207,7 +207,6 @@
/obj/machinery/vending/sovietsoda,
/obj/structure/AIcore,
/obj/structure/piano,
- /obj/structure/displaycase_frame,
/obj/structure/particle_accelerator/fuel_chamber,
/obj/structure/reagent_dispensers/fueltank,
/obj/structure/reagent_dispensers/water_cooler,
@@ -604,6 +603,7 @@
/obj/item/device/powersink,
/obj/item/weapon/gun/projectile/flamethrower/full,
/obj/item/weapon/gun/projectile/deagle/gold,
+ /obj/item/clothing/shoes/magboots/magnificent,
/obj/item/weapon/gun/projectile/russian,
)
@@ -853,7 +853,7 @@
icon_state = "mob_lizard"
amount = 2
chance = 50
- to_spawn = list(/mob/living/simple_animal/lizard)
+ to_spawn = list(/mob/living/simple_animal/hostile/lizard)
/obj/abstract/map/spawner/mobs/mouse
name = "mouse spawner"
@@ -904,14 +904,52 @@
/obj/abstract/map/spawner/mobs/medivault
name = "medivault spawner"
icon_state = "mob_medivault"
- chance = 50
+ chance = 60
to_spawn = list(
- /mob/living/simple_animal/hostile/monster/cyber_horror/Tajaran,
- /mob/living/simple_animal/hostile/monster/cyber_horror,
/mob/living/simple_animal/hostile/necro/skeleton,
+ /mob/living/simple_animal/hostile/necro/skeleton,
+ /mob/living/simple_animal/hostile/necro/skeleton,
+ /mob/living/simple_animal/hostile/necro/zombie/leatherman,
+ /mob/living/simple_animal/hostile/necro/zombie/ghoul,
+ /mob/living/simple_animal/hostile/necro/zombie/ghoul,
+ /mob/living/simple_animal/hostile/necro/zombie/ghoul,
+ /mob/living/simple_animal/hostile/necro/zombie,
+ /mob/living/simple_animal/hostile/necro/zombie,
+ /mob/living/simple_animal/hostile/necro/zombie,
/mob/living/simple_animal/hostile/necro/zombie,
)
+/obj/abstract/map/spawner/misc/medivault
+ name = "medivault loot spawner"
+ icon_state = "loot_medivault"
+ chance = 80
+ amount = 1
+ jiggle = 5
+ to_spawn = list(/obj/item/weapon/dnainjector/nofail/polymorph,
+ /obj/item/weapon/dnainjector/nofail/polymorph,
+ /obj/item/weapon/dnainjector/nofail/telemut,
+ /obj/item/weapon/dnainjector/nofail/telemut,
+ /obj/item/weapon/dnainjector/nofail/randompower,
+ /obj/item/weapon/dnainjector/nofail/randompower,
+ /obj/item/weapon/dnainjector/nofail/randompower,
+ /obj/item/weapon/dnainjector/nofail/hulkmut,
+ /obj/item/weapon/dnainjector/nofail/nobreath,
+ /obj/item/weapon/dnainjector/nofail/nobreath,
+ /obj/item/weapon/storage/firstaid/adv,
+ /obj/item/weapon/storage/firstaid/adv,
+ /obj/item/weapon/storage/firstaid/adv,
+ /obj/item/weapon/storage/pill_bottle/hyperzine,
+ /obj/item/weapon/storage/pill_bottle/hyperzine,
+ /obj/item/weapon/reagent_containers/glass/beaker/mednanobots,
+ /obj/item/weapon/reagent_containers/glass/beaker/mednanobots,
+ /obj/item/weapon/gun/energy/laser/smart,
+ /obj/item/weapon/gun/energy/laser/pistol,
+ /obj/item/weapon/gun/energy/laser/pistol,
+ /obj/item/weapon/gun/projectile/shotgun/pump/combat,
+
+
+)
+
// Robutts /////////////////////////////////////////////////////
/obj/abstract/map/spawner/robot/any
@@ -1100,6 +1138,7 @@
/obj/item/mounted/frame/painting
)
+
/obj/abstract/map/spawner/safe/medical
name = "safe medical spawner"
icon_state = "safe"
diff --git a/code/modules/media/broadcast/receivers/radio.dm b/code/modules/media/broadcast/receivers/radio.dm
index 3d33befcebf..9f4d32a405c 100644
--- a/code/modules/media/broadcast/receivers/radio.dm
+++ b/code/modules/media/broadcast/receivers/radio.dm
@@ -99,8 +99,12 @@
volume=0.25 // 25% of user's set volume.
var/buildstage = 0
- holomap = TRUE
- auto_holomap = TRUE
+/obj/machinery/media/receiver/boombox/wallmount/supports_holomap()
+ return TRUE
+
+/obj/machinery/media/receiver/boombox/wallmount/initialize()
+ ..()
+ add_self_to_holomap()
/obj/machinery/media/receiver/boombox/wallmount/New(turf/loc,var/ndir=0,var/building=2)
..()
@@ -139,7 +143,7 @@
if(SYSTEMISDONE)
if(iscrowbar(W))
to_chat(user, "You pry the cover off [src].")
- playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
if(do_after(user, src, 10) && buildstage==SYSTEMISDONE)
on = 0
buildstage = SYSTEMISKINDADONE
@@ -149,7 +153,7 @@
return ..()
if(SYSTEMISKINDADONE)
if(isscrewdriver(W))
- playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
+ playsound(src, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, src, 10) && buildstage==SYSTEMISKINDADONE)
on = 1
buildstage = SYSTEMISDONE
@@ -158,7 +162,7 @@
update_on(TRUE)
return 1
else if(iswirecutter(W))
- playsound(get_turf(src), 'sound/items/Wirecutter.ogg', 50, 1)
+ playsound(src, 'sound/items/Wirecutter.ogg', 50, 1)
if(do_after(user, src, 10) && buildstage==SYSTEMISKINDADONE)
getFromPool(/obj/item/stack/cable_coil,get_turf(src),5)
buildstage = SYSTEMISNOTDONE
@@ -177,7 +181,7 @@
return 1
if(iswrench(W))
to_chat(user, "You remove the securing bolts...")
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
if(do_after(user, src, 10) && buildstage==SYSTEMISNOTDONE)
new /obj/item/mounted/frame/soundsystem(get_turf(src))
to_chat(user, "The frame pops off.")
@@ -186,7 +190,8 @@
return 0
/obj/machinery/media/receiver/boombox/wallmount/proc/relay_area_configuration()
- for(var/obj/machinery/media/receiver/boombox/wallmount/W in areaMaster)
+ var/area/this_area = get_area(src)
+ for(var/obj/machinery/media/receiver/boombox/wallmount/W in this_area)
W.on = src.on
W.media_frequency=src.media_frequency
W.volume = src.volume
diff --git a/code/modules/media/broadcast/transmitter.dm b/code/modules/media/broadcast/transmitter.dm
index 92c37f9d917..fab68b5acf6 100644
--- a/code/modules/media/broadcast/transmitter.dm
+++ b/code/modules/media/broadcast/transmitter.dm
@@ -34,6 +34,9 @@ var/global/media_transmitters=list()
if(R.media_crypto == media_crypto)
R.receive_broadcast(media_url,media_start_time)
//testing("[src]: Sending music to [R]")
+ for(var/mob/living/carbon/complex/gondola/G in media_receivers[freq])
+ if(G.media_crypto == media_crypto)
+ G.receive_broadcast(media_url,media_start_time)
/obj/machinery/media/transmitter/proc/disconnect_frequency()
var/list/transmitters=list()
diff --git a/code/modules/media/broadcast/transmitters/broadcast.dm b/code/modules/media/broadcast/transmitters/broadcast.dm
index d020a0c053f..8c9d6af4df2 100644
--- a/code/modules/media/broadcast/transmitters/broadcast.dm
+++ b/code/modules/media/broadcast/transmitters/broadcast.dm
@@ -54,7 +54,7 @@
for(var/obj/machinery/media/source in orange(20, src))
if(source.id_tag in autolink)
sources.Add(source)
- testing("Autolinked [source] -> [src]")
+ //testing("Autolinked [source] -> [src]")
hook_media_sources()
if(on)
update_on()
@@ -229,28 +229,14 @@
if(istype(L) && heating_power)
var/datum/gas_mixture/env = L.return_air()
if(env.temperature != MAX_TEMP + T0C)
+ var/energy_to_add
- var/transfer_moles = 0.25 * env.total_moles() / env.volume * CELL_VOLUME
+ if(env.temperature < MAX_TEMP + T0C)
+ energy_to_add = min(heating_power, env.get_thermal_energy_change(1000)) //Added min() check to try and avoid wacky superheating issues in low gas scenarios -- TLE
+ else
+ energy_to_add = -heating_power //add_thermal_energy() automatically prevents the temperature from falling below TCMB, so a similar check here is unnecessary.
- var/datum/gas_mixture/removed = env.remove(transfer_moles)
-
-// to_chat(world, "got [transfer_moles] moles at [removed.temperature]")
-
- if(removed)
-
- var/heat_capacity = removed.heat_capacity()
-// to_chat(world, "heating ([heat_capacity])")
- if(heat_capacity) // Added check to avoid divide by zero (oshi-) runtime errors -- TLE
- if(removed.temperature < MAX_TEMP + T0C)
- removed.temperature = min(removed.temperature + heating_power/heat_capacity, 1000) // Added min() check to try and avoid wacky superheating issues in low gas scenarios -- TLE
- else
- removed.temperature = max(removed.temperature - heating_power/heat_capacity, TCMB)
-
-// to_chat(world, "now at [removed.temperature]")
-
- env.merge(removed)
-
-// to_chat(world, "turf now at [env.temperature]")
+ env.add_thermal_energy(energy_to_add)
// Checks heat from the environment and applies any integrity damage
var/datum/gas_mixture/environment = loc.return_air()
diff --git a/code/modules/media/jukebox.dm b/code/modules/media/jukebox.dm
index 16b6cead602..f9ce3b4e88f 100644
--- a/code/modules/media/jukebox.dm
+++ b/code/modules/media/jukebox.dm
@@ -21,7 +21,7 @@ var/global/global_playlists = list()
return
for(var/playlist_id in list("bar", "jazz", "rock", "muzak", "emagged", "endgame", "clockwork", "vidyaone", "vidyatwo", "vidyathree", "vidyafour"))
var/url="[config.media_base_url]/index.php?playlist=[playlist_id]"
- testing("Updating playlist from [url]...")
+ //testing("Updating playlist from [url]...")
// Media Server 2 requires a secret key in order to tell the jukebox
// where the music files are. It's set in config with MEDIA_SECRET_KEY
@@ -57,7 +57,7 @@ var/global/global_playlists = list()
else
var/url="[config.media_base_url]/index.php?playlist=[playlist_id]"
- testing("[src] - Updating playlist from [url]...")
+ //testing("[src] - Updating playlist from [url]...")
// Media Server 2 requires a secret key in order to tell the jukebox
// where the music files are. It's set in config with MEDIA_SECRET_KEY
@@ -351,7 +351,9 @@ var/global/list/loopModeNames=list(
/obj/machinery/media/jukebox/proc/ScreenSettings(var/mob/user)
if(!linked_account)
linked_account = station_account
- var/dat={"
Settings
+ var/dat
+
+ dat += {"
Settings
"}
+ "}
+
+ dat += " Media "
+ for(var/element in playlists)
+ dat += "[playlists[element]] Eject "
+ dat += "Insert Vinyl "
return dat
@@ -412,7 +418,8 @@ var/global/list/loopModeNames=list(
visible_message("The machine buzzes, and flashes \"NOT ENOUGH FUNDS\" on the screen.","You hear a buzz.")
return
visible_message("The machine beeps happily.","You hear a beep.")
- acct.charge(credits_needed,linked_account,"Song selection at [areaMaster.name]'s [name].")
+ var/area/this_area = get_area(src)
+ acct.charge(credits_needed,linked_account,"Song selection at [this_area.name]'s [name].")
credits_needed = 0
successful_purchase()
@@ -589,6 +596,20 @@ var/global/list/loopModeNames=list(
update_music()
update_icon()
+ if (href_list["insert"])
+ if(isobserver(usr) && !canGhostWrite(usr,src,""))
+ to_chat(usr, "You can't do that.")
+ return
+ var/obj/item/weapon/vinyl/V = usr.get_active_hand()
+ if(istype(V))
+ insert(V)
+
+ if (href_list["eject"])
+ if(isobserver(usr) && !canGhostWrite(usr,src,""))
+ to_chat(usr, "You can't do that.")
+ return
+ eject(href_list["eject"])
+
if (href_list["song"])
if(wires.IsIndexCut(JUKE_CAPITAL))
to_chat(usr, "You select a song, but [src] is unresponsive...")
@@ -648,6 +669,26 @@ var/global/list/loopModeNames=list(
return
update_music()
+/obj/machinery/media/jukebox/proc/eject(var/playlist_name)
+ if(playlists.Find(playlist_name))
+ new /obj/item/weapon/vinyl(get_turf(src), playlist_name, playlists[playlist_name])
+ playlists.Remove(playlist_name)
+ if(playlist == playlist_name)
+ stop_playing()
+ playlist = playlists[1]
+ else
+ visible_message("[bicon(src)] \The [src] buzzes, unable to eject the vinyl.")
+
+/obj/machinery/media/jukebox/proc/insert(var/obj/O)
+ var/obj/item/weapon/vinyl/V = O
+ if(!istype(V))
+ return
+ if(playlists.Find(V.unformatted))
+ visible_message("[bicon(src)] \The [src] buzzes, rejecting the vinyl.")
+ else
+ playlists[V.unformatted] = V.formatted
+ qdel(V)
+
/obj/machinery/media/jukebox/update_music()
if(!playlist)
process()
@@ -853,3 +894,88 @@ var/global/list/loopModeNames=list(
/obj/machinery/media/jukebox/superjuke/adminbus/cultify()
return
+
+
+/obj/item/weapon/vinyl
+ name = "nanovinyl"
+ desc = "In reality, the bulk of the disc serves only decorative purposes and the many songs are recorded on a very small microchip near the center."
+ icon = 'icons/obj/jukebox.dmi'
+ icon_state = "vinyl"
+ flags = FPRINT
+ siemens_coefficient = 1
+ sharpness = 1
+ force = 7
+ throwforce = 7
+ throw_speed = 7
+ throw_range = 7
+ w_class = W_CLASS_SMALL
+ attack_verb = list("plays out", "records", "frisbees") //Fuck it, we'll do it live. Fucking thing sucks!
+ var/unformatted
+ var/formatted
+
+/obj/item/weapon/vinyl/New(loc,U,F)
+ ..(loc)
+ unformatted = U
+ formatted = F
+ name = "nanovinyl - [formatted]"
+
+//Premades
+/obj/item/weapon/vinyl/vidyaone
+ name = "nanovinyl - video games, volume one"
+ unformatted = "vidyaone"
+ formatted = "Vidya Pt.1"
+
+/obj/item/weapon/vinyl/vidyatwo
+ name = "nanovinyl - video games, volume two"
+ unformatted = "vidyatwo"
+ formatted = "Vidya Pt.2"
+
+/obj/item/weapon/vinyl/vidyathree
+ name = "nanovinyl - video games, volume three"
+ unformatted = "vidyathree"
+ formatted = "Vidya Pt.3"
+
+/obj/item/weapon/vinyl/vidyafour
+ name = "nanovinyl - video games, volume four"
+ unformatted = "vidyafour"
+ formatted = "Vidya Pt.4"
+
+/obj/item/weapon/vinyl/jazz
+ name = "nanovinyl - jazz"
+ unformatted = "jazz"
+ formatted = "Jazz"
+
+/obj/item/weapon/vinyl/rock
+ name = "nanovinyl - rock"
+ unformatted = "rock"
+ formatted = "Rock"
+
+/obj/item/weapon/vinyl/muzak
+ name = "nanovinyl - muzak"
+ unformatted = "muzak"
+ formatted = "Muzak"
+
+/obj/item/weapon/vinyl/shuttle
+ name = "nanovinyl - shuttle"
+ unformatted = "shuttle"
+ formatted = "Shuttle"
+
+/obj/item/weapon/vinyl/syndie
+ name = "nanovinyl - syndicate"
+ unformatted = "emagged"
+ formatted = "Syndie Mix"
+
+/obj/item/weapon/vinyl/endgame
+ name = "nanovinyl - apocalypse"
+ unformatted = "endgame"
+ formatted = "Apocalypse"
+
+/obj/item/weapon/vinyl/clockwork
+ name = "nanovinyl - clockwork"
+ unformatted = "clockwork"
+ formatted = "Clockwork"
+
+/obj/item/weapon/vinyl/thunderdome
+ name = "nanovinyl - thunderdome"
+ unformatted = "thunderdome"
+ formatted = "Thunderdome"
diff --git a/code/modules/media/machinery.dm b/code/modules/media/machinery.dm
index ad7f8c28602..da21aecfc08 100644
--- a/code/modules/media/machinery.dm
+++ b/code/modules/media/machinery.dm
@@ -30,7 +30,7 @@
/obj/machinery/media/proc/update_music()
// Broadcasting shit
for(var/obj/machinery/media/transmitter/T in hooked)
- testing("[src] Writing media to [T].")
+// testing("[src] Writing media to [T].")
T.broadcast(media_url,media_start_time)
if(exclusive_hook)
@@ -49,7 +49,7 @@
M.update_music()
/obj/machinery/media/proc/update_media_source()
- var/area/A = get_area_master(src)
+ var/area/A = get_area(src)
if(!A)
return
// Check if there's a media source already.
@@ -66,7 +66,7 @@
master_area=A
/obj/machinery/media/proc/disconnect_media_source()
- var/area/A = get_area_master(src)
+ var/area/A = get_area(src)
// Sanity
if(!A)
diff --git a/code/modules/media/mediamanager.dm b/code/modules/media/mediamanager.dm
index 3ce4fd206ec..317da17624a 100644
--- a/code/modules/media/mediamanager.dm
+++ b/code/modules/media/mediamanager.dm
@@ -193,7 +193,7 @@ to_chat(#define MP_DEBUG(x) owner, x)
if (forced || !owner)
return
- var/area/A = get_area_master(mob)
+ var/area/A = get_area(mob)
if(!A)
//testing("[owner] in [mob.loc]. Aborting.")
stop_music()
diff --git a/code/modules/media/tapedeck.dm b/code/modules/media/tapedeck.dm
index 0e9da82bbba..555c4cc664f 100644
--- a/code/modules/media/tapedeck.dm
+++ b/code/modules/media/tapedeck.dm
@@ -210,7 +210,7 @@
var/un = !anchored ? "" : "un"
user.visible_message("[user.name] begins [un]locking \the [src.name]'s casters.","You begin [un]locking \the [src.name]'s casters.")
if(do_after(user, src,30))
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 50, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 50, 1)
anchored = !anchored
user.visible_message("[user.name] [un]locks \the [src.name]'s casters.","You [un]lock \the [src.name]'s casters.")
playing = emagged
@@ -284,7 +284,7 @@
/obj/machinery/media/jukebox/process()
if(!playlist && config.media_base_url)
var/url="[config.media_base_url]/index.php?playlist=[playlist_id]"
- testing("[src] - Updating playlist from [url]...")
+ //testing("[src] - Updating playlist from [url]...")
var/response = world.Export(url)
playlist=list()
if(response)
@@ -310,7 +310,7 @@
playing=1
autoplay=0
else
- testing("[src] failed to update playlist: Response null.")
+ warning("[src] failed to update playlist: Response null.")
stat &= BROKEN
update_icon()
return
diff --git a/code/modules/medical/cloning.dm b/code/modules/medical/cloning.dm
index 44d1a632a24..9356bd0f79d 100644
--- a/code/modules/medical/cloning.dm
+++ b/code/modules/medical/cloning.dm
@@ -216,7 +216,6 @@
if((G.mind && (G.mind.current.stat != DEAD) || G.mind != clonemind))
return FALSE
-
heal_level = rand(10,40) //Randomizes what health the clone is when ejected
working = TRUE //One at a time!!
locked = TRUE
@@ -227,6 +226,7 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src, R.dna.species, delay_ready_dna = TRUE)
occupant = H
+ H.times_cloned = R.times_cloned +1
if(!connected.emagged)
icon_state = "pod_1"
@@ -235,6 +235,9 @@
connected.update_icon()
+ if(isplasmaman(H))
+ H.fire_sprite = "Plasmaman"
+
//Get the clone body ready
H.dna = R.dna.Clone()
H.dna.flavor_text = R.dna.flavor_text
@@ -317,14 +320,15 @@
//Premature clones may have brain damage.
occupant.adjustBrainLoss(-1*time_coeff) //Ditto above
- //So clones don't die of oxyloss in a running pod.
- if (occupant.reagents.get_reagent_amount(INAPROVALINE) < 30)
- occupant.reagents.add_reagent(INAPROVALINE, 60)
-
var/mob/living/carbon/human/H = occupant
- if(istype(H.species, /datum/species/vox) & occupant.reagents.get_reagent_amount(NITROGEN) < 30)
- occupant.reagents.add_reagent(NITROGEN, 60)
+ if(isvox(H))
+ if(occupant.reagents.get_reagent_amount(NITROGEN) < 30)
+ occupant.reagents.add_reagent(NITROGEN, 60)
+
+ //So clones don't die of oxyloss in a running pod.
+ else if(occupant.reagents.get_reagent_amount(INAPROVALINE) < 30) //Done like this because inaprovaline is toxic to vox
+ occupant.reagents.add_reagent(INAPROVALINE, 60)
//Also heal some oxyloss ourselves because inaprovaline is so bad at preventing it!!
occupant.adjustOxyLoss(-4)
@@ -391,7 +395,7 @@
to_chat(user, "System unlocked.")
if (istype(W, /obj/item/weapon/reagent_containers/food/snacks/meat))
if(user.drop_item(W))
- playsound(get_turf(src), 'sound/machines/juicerfast.ogg', 30, 1)
+ playsound(src, 'sound/machines/juicerfast.ogg', 30, 1)
to_chat(user, "\The [src] processes \the [W].")
biomass += BIOMASS_CHUNK
qdel(W)
@@ -466,7 +470,7 @@
return
if(isrobot(usr))
var/mob/living/silicon/robot/robit = usr
- if(istype(robit) && !istype(robit.module, /obj/item/weapon/robot_module/medical))
+ if(!(robit.module && (robit.module.quirk_flags & MODULE_CAN_HANDLE_MEDICAL)))
to_chat(usr, "You do not have the means to do this!")
return
@@ -548,7 +552,7 @@
visible_message = TRUE // Prevent chatspam when multiple meat are near
if(visible_message)
- playsound(get_turf(src), 'sound/machines/juicer.ogg', 30, 1)
+ playsound(src, 'sound/machines/juicer.ogg', 30, 1)
visible_message("[src] sucks in and processes the nearby biomass.")
busy = FALSE
@@ -557,7 +561,7 @@
if(occupant && prob(5))
visible_message("[src] buzzes.","You hear a buzz.")
- playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0)
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
locked = FALSE
go_out()
diff --git a/code/modules/medical/computer/cloning.dm b/code/modules/medical/computer/cloning.dm
index 2db4125666d..b50c3ba830c 100644
--- a/code/modules/medical/computer/cloning.dm
+++ b/code/modules/medical/computer/cloning.dm
@@ -172,7 +172,7 @@
// Database
dat += {"
Database Functions
- View Records "}
+ View Records[records.len?"([records.len])":""] "}
if (src.diskette)
dat += "Eject Disk"
@@ -491,6 +491,7 @@
R.name=R.dna.real_name
R.types=DNA2_BUF_UI|DNA2_BUF_UE|DNA2_BUF_SE
R.languages = subject.languages.Copy()
+ R.times_cloned = subject.times_cloned
//Add an implant if needed
var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject)
diff --git a/code/modules/migrations/mysql/mysql_controller.dm b/code/modules/migrations/mysql/mysql_controller.dm
index 3620d3f66b7..b3f0564c573 100644
--- a/code/modules/migrations/mysql/mysql_controller.dm
+++ b/code/modules/migrations/mysql/mysql_controller.dm
@@ -6,14 +6,14 @@ var/global/datum/migration_controller/mysql/migration_controller_mysql = null
/datum/migration_controller/mysql/setup()
if(!dbcon || !istype(dbcon) || !dbcon.IsConnected())
- testing("Something wrong with dbcon.")
+ warning("Something wrong with dbcon.")
return FALSE
var/DBQuery/Q = dbcon.NewQuery()
if(!Q)
- testing("Something wrong with dbcon.NewQuery()")
+ warning("Something wrong with dbcon.NewQuery()")
return FALSE
Q.Close()
- testing("MySQL is okay")
+ //testing("MySQL is okay")
db = dbcon
return TRUE
diff --git a/code/modules/mining/materials.dm b/code/modules/mining/materials.dm
index 26b4b680a9e..b2042b50c09 100644
--- a/code/modules/mining/materials.dm
+++ b/code/modules/mining/materials.dm
@@ -127,11 +127,24 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
var/sheettype=null
var/cointype=null
var/value=0
+ var/color
+ var/color_matrix
+ var/alpha = 255
+ //Modifier multipliers.
+ var/brunt_damage_mod = 1
+ var/sharpness_mod = 1
+ var/quality_mod = 1
/datum/material/New()
if(processed_name=="")
processed_name=name
+/datum/material/proc/on_use(obj/source, atom/target, mob/user)
+ ASSERT(source)
+ if(isobserver(user))
+ return FALSE
+ return TRUE
+
/datum/material/iron
name="Iron"
id=MAT_IRON
@@ -140,6 +153,10 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
oretype=/obj/item/weapon/ore/iron
sheettype=/obj/item/stack/sheet/metal
cointype=/obj/item/weapon/coin/iron
+ color = "#666666" //rgb: 102, 102, 102
+ brunt_damage_mod = 1.1
+ sharpness_mod = 0.8
+ quality_mod = 1.1
/datum/material/glass
name="Sand"
@@ -149,6 +166,19 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
cc_per_sheet=CC_PER_SHEET_GLASS
oretype=/obj/item/weapon/ore/glass
sheettype=/obj/item/stack/sheet/glass/glass
+ color = "#6E8DA2" //rgb: 110, 141, 162
+ alpha = 122
+ brunt_damage_mod = 0.7
+ sharpness_mod = 1.4
+
+/datum/material/glass/on_use(obj/source)
+ if(!..())
+ return
+ if(prob(25/source.quality))
+ source.visible_message("\The [source] shatters!")
+ new /obj/item/weapon/shard(get_turf(source))
+ playsound(get_turf(source), "shatter", 70, 1)
+ qdel(source)
/datum/material/diamond
name="Diamond"
@@ -158,6 +188,11 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
oretype=/obj/item/weapon/ore/diamond
sheettype=/obj/item/stack/sheet/mineral/diamond
cointype=/obj/item/weapon/coin/diamond
+ color = "#74C6C6" //rgb: 116, 198, 198
+ alpha = 200
+ brunt_damage_mod = 1.4
+ sharpness_mod = 1.6
+ quality_mod = 2
/datum/material/plasma
name="Plasma"
@@ -166,6 +201,17 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
oretype=/obj/item/weapon/ore/plasma
sheettype=/obj/item/stack/sheet/mineral/plasma
cointype=/obj/item/weapon/coin/plasma
+ color = "#500064" //rgb: 80, 0, 100
+ brunt_damage_mod = 1.2
+ sharpness_mod = 1.4
+ quality_mod = 1.3
+
+/datum/material/plasma/on_use(obj/source, atom/target, mob/user)
+ if(!..())
+ return
+ if(isliving(target))
+ var/mob/living/L = target
+ L.adjustToxLoss(rand(1,source.quality))
/datum/material/gold
name="Gold"
@@ -174,6 +220,10 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
oretype=/obj/item/weapon/ore/gold
sheettype=/obj/item/stack/sheet/mineral/gold
cointype=/obj/item/weapon/coin/gold
+ color = "#F7C430" //rgb: 247, 196, 48
+ brunt_damage_mod = 0.5
+ sharpness_mod = 0.5
+ quality_mod = 1.7
/datum/material/silver
name="Silver"
@@ -182,6 +232,11 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
oretype=/obj/item/weapon/ore/silver
sheettype=/obj/item/stack/sheet/mineral/silver
cointype=/obj/item/weapon/coin/silver
+ color = "#D0D0D0" //rgb: 208, 208, 208
+ brunt_damage_mod = 0.7
+ sharpness_mod = 0.7
+ quality_mod = 1.5
+
/datum/material/uranium
name="Uranium"
@@ -190,6 +245,18 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
oretype=/obj/item/weapon/ore/uranium
sheettype=/obj/item/stack/sheet/mineral/uranium
cointype=/obj/item/weapon/coin/uranium
+ color = "#247124" //rgb: 36, 113, 36
+ brunt_damage_mod = 1.8
+ sharpness_mod = 0.2
+ quality_mod = 1.4
+
+
+/datum/material/uranium/on_use(obj/source, atom/target, mob/user)
+ if(!..())
+ return
+ if(isliving(target))
+ var/mob/living/L = target
+ L.apply_radiation(rand(1,3)*source.quality, RAD_EXTERNAL)
/datum/material/clown
name="Bananium"
@@ -199,6 +266,25 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
sheettype=/obj/item/stack/sheet/mineral/clown
cointype=/obj/item/weapon/coin/clown
+/datum/material/clown/New()
+ if(!..())
+ return
+ brunt_damage_mod = rand(1,2)/rand(1,8)
+ sharpness_mod = rand(1,2)/rand(1,8)
+ quality_mod = rand(1,2)/rand(1,8)
+
+ color_matrix = list(rand(),rand(),rand(),0,
+ rand(),rand(),rand(),0,
+ rand(),rand(),rand(),0,
+ 0,0,0,1,
+ 0,0,0,0)
+
+/datum/material/clown/on_use(obj/source) //May [ticker.deity] have mercy
+ if(!..())
+ return
+ if(prob(2*source.quality))
+ playsound(get_turf(source), 'sound/items/bikehorn.ogg', 100, 1)
+
/datum/material/phazon
name="Phazon"
id=MAT_PHAZON
@@ -207,6 +293,25 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
oretype=/obj/item/weapon/ore/phazon
sheettype=/obj/item/stack/sheet/mineral/phazon
cointype=/obj/item/weapon/coin/phazon
+ color = "#5E02F8" //rgb: 94, 2, 248
+ brunt_damage_mod = 1.4
+ sharpness_mod = 1.8
+ quality_mod = 2.2
+
+/datum/material/phazon/on_use(obj/source, atom/target, mob/user)
+ if(!..())
+ return
+ if(prob(0.5*source.quality))
+ switch(rand(1,2))
+ if(1) //EMP
+ empulse(get_turf(pick(source,target,user)), 0.25*source.quality, 0.5*source.quality, 1)
+ if(2) //Teleport
+ var/atom/movable/victim = pick(target,user)
+ if(victim)
+ do_teleport(victim, get_turf(victim), 1*source.quality, asoundin = 'sound/effects/phasein.ogg')
+ if(prob(20*source.quality))
+ to_chat(user, "\The [source] phases out of reality!")
+ qdel(source)
/datum/material/plastic
name="Plastic"
@@ -215,6 +320,7 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
oretype=null
sheettype=/obj/item/stack/sheet/mineral/plastic
cointype=null
+ color = "#F8F8FF" //rgb: 248, 248, 255
/datum/material/cardboard
name="Cardboard"
@@ -225,6 +331,17 @@ var/global/list/initial_materials //Stores all the matids = 0 in helping New
cointype=null
cc_per_sheet = CC_PER_SHEET_METAL
+/datum/material/wood
+ name="Wood"
+ id=MAT_WOOD
+ value=1
+ oretype=null
+ sheettype=/obj/item/stack/sheet/wood
+ cointype=null
+ cc_per_sheet = CC_PER_SHEET_METAL
+ color = "#663300" //rgb: 102, 51, 0
+
+
/* //Commented out to save save space in menus listing materials until they are used
/datum/material/pharosium
name="Pharosium"
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index 0507fe9067b..6e15d0f7c25 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -450,7 +450,7 @@ proc/move_mining_shuttle()
/obj/item/weapon/resonator/proc/CreateResonance(var/target, var/creator)
if(cooldown <= 0)
- playsound(get_turf(src),'sound/effects/stealthoff.ogg',50,1)
+ playsound(src,'sound/effects/stealthoff.ogg',50,1)
var/obj/effect/resonance/R = new /obj/effect/resonance(get_turf(target))
R.creator = creator
cooldown = 1
@@ -514,9 +514,7 @@ proc/move_mining_shuttle()
throwforce = 0
sterile = 1
//tint = 3 //Makes it feel more authentic when it latches on
-
-/obj/item/clothing/mask/facehugger/toy/Die()
- return
+ real = FALSE
/**********************Mining drone cube**********************/
@@ -593,15 +591,28 @@ proc/move_mining_shuttle()
to_chat(user, "You instruct \the [src] to drop any collected ore.")
DropOre()
return
+ if(!client && istype(I, /obj/item/device/paicard))
+ var/obj/item/device/paicard/P = I
+ if(!P.pai)
+ to_chat(user, "\The [P] has no intelligence within it.")
+ return
+ var/response = alert(user, "Are you sure you want to put \the [P] into \the [src]? This can not be undone.","Yes","No")
+ if(response != "Yes")
+ return
+ if(do_after(user, src, 30))
+ user.drop_item(P, force_drop = TRUE)
+ P.pai.mind.transfer_to(src)
+ projectiletype = /obj/item/projectile/kinetic
+ qdel(P)
+
..()
-/mob/living/simple_animal/hostile/mining_drone/Die()
- ..()
+/mob/living/simple_animal/hostile/mining_drone/death(var/gibbed = FALSE)
+ ..(TRUE)
visible_message("\The [src] blows apart!")
new /obj/effect/decal/remains/robot(src.loc)
DropOre()
qdel(src)
- return
/mob/living/simple_animal/hostile/mining_drone/New()
..()
@@ -609,16 +620,21 @@ proc/move_mining_shuttle()
/mob/living/simple_animal/hostile/mining_drone/attack_hand(mob/living/carbon/human/M)
if(M.a_intent == I_HELP)
- switch(search_objects)
- if(0)
- SetCollectBehavior()
- to_chat(M, "\The [src] will now search and store loose ore.")
- if(2)
- SetOffenseBehavior()
- to_chat(M, "\The [src] will now attack hostile wildlife.")
+ ToggleModes(M)
return
..()
+/mob/living/simple_animal/hostile/mining_drone/proc/ToggleModes(mob/user)
+ switch(search_objects)
+ if(0)
+ SetCollectBehavior()
+ if(user != src)
+ to_chat(user, "\The [src] will now search and store loose ore.")
+ if(2)
+ SetOffenseBehavior()
+ if(user != src)
+ to_chat(user, "\The [src] will now attack hostile wildlife.")
+
/mob/living/simple_animal/hostile/mining_drone/proc/SetCollectBehavior()
stop_automated_movement_when_pulled = 1
idle_vision_range = 9
@@ -628,6 +644,8 @@ proc/move_mining_shuttle()
minimum_distance = 1
retreat_distance = null
icon_state = "mining_drone"
+ if(client)
+ to_chat(src, "Ore collection mode active.")
/mob/living/simple_animal/hostile/mining_drone/proc/SetOffenseBehavior()
stop_automated_movement_when_pulled = 0
@@ -638,6 +656,8 @@ proc/move_mining_shuttle()
retreat_distance = 1
minimum_distance = 2
icon_state = "mining_drone_offense"
+ if(client)
+ to_chat(src, "Combat mode active.")
/mob/living/simple_animal/hostile/mining_drone/AttackingTarget()
if(istype(target, /obj/item/weapon/ore))
@@ -661,6 +681,8 @@ proc/move_mining_shuttle()
for(var/obj/item/weapon/ore/O in contents)
contents -= O
O.forceMove(src.loc)
+ if(client)
+ to_chat(src, "Unloading collected ore.")
return
/mob/living/simple_animal/hostile/mining_drone/adjustBruteLoss()
@@ -668,6 +690,32 @@ proc/move_mining_shuttle()
SetOffenseBehavior()
..()
+/mob/living/simple_animal/hostile/mining_drone/LoseAggro()
+ stop_automated_movement = 0
+ vision_range = idle_vision_range
+
+/mob/living/simple_animal/hostile/mining_drone/Login()
+ ..()
+ to_chat(src, "You are a minebot. Click on yourself to toggle between modes.")
+
+/mob/living/simple_animal/hostile/mining_drone/attack_animal(mob/living/simple_animal/M)
+ if(client && M == src)
+ ToggleModes(M)
+ else
+ return ..()
+
+/mob/living/simple_animal/hostile/mining_drone/UnarmedAttack(atom/A)
+ . = ..()
+ if(client && search_objects == 2 && (istype(A, /obj/item/weapon/ore) || isturf(A)) && !attack_delayer.blocked())
+ delayNextAttack(8)
+ CollectOre()
+
+/mob/living/simple_animal/hostile/mining_drone/verb/UnloadOre()
+ set category = "Minebot"
+ set name = "Unload Ore"
+
+ DropOre()
+
/**********************Lazarus Injector**********************/
/obj/item/weapon/lazarus_injector
@@ -696,7 +744,9 @@ proc/move_mining_shuttle()
if(istype(target, /mob/living) && proximity_flag)
if(istype(target, /mob/living/simple_animal))
var/mob/living/simple_animal/M = target
-
+ if(M.mob_property_flags & MOB_NO_LAZ)
+ to_chat(user, "\The [src] is incapable of reviving \the [M].")
+ return
if(M.stat == DEAD)
M.faction = "lazarus \ref[user]"
diff --git a/code/modules/mining/mine_structures.dm b/code/modules/mining/mine_structures.dm
index 4d6ce31ce50..670acce399f 100644
--- a/code/modules/mining/mine_structures.dm
+++ b/code/modules/mining/mine_structures.dm
@@ -39,7 +39,7 @@
if(lantern)
user.visible_message("[user] takes \the [lantern] off of the \the [src].", \
"You take \the [lantern] off of the \the [src].")
- playsound(get_turf(src), 'sound/machines/click.ogg', 20, 1)
+ playsound(src, 'sound/machines/click.ogg', 20, 1)
lantern.forceMove(user.loc)
lantern.add_fingerprint(user)
user.put_in_hands(lantern)
@@ -63,7 +63,7 @@
user << "Remove \the [lantern] from \the [src] first."
return
busy = 1
- playsound(get_turf(src), 'sound/items/Ratchet.ogg', 75, 1)
+ playsound(src, 'sound/items/Ratchet.ogg', 75, 1)
user.visible_message("[user] begins deconstructing \the [src].", \
"You begin deconstructing \the [src].")
if(do_after(user, src, 30))
@@ -82,7 +82,7 @@
if(user.drop_item(W, src))
user.visible_message("[user] puts \a [W.name] on the \the [src].", \
"You put \a [W.name] on the \the [src].")
- playsound(get_turf(src), 'sound/machines/click.ogg', 20, 1)
+ playsound(src, 'sound/machines/click.ogg', 20, 1)
lantern = W
update()
return 1
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index d0fdc84baa0..f3ab7dd6950 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -4,6 +4,7 @@
name = "Rock"
icon = 'icons/turf/walls.dmi'
icon_state = "rock"
+ var/base_icon_state = "rock" // above is for mappers.
oxygen = 0
nitrogen = 0
opacity = 1
@@ -23,9 +24,25 @@
var/datum/artifact_find/artifact_find
var/scan_state = null //Holder for the image we display when we're pinged by a mining scanner
var/busy = 0 //Used for a bunch of do_after actions, because we can walk into the rock to trigger them
-
+ var/mineral_overlay
var/mined_type = /turf/unsimulated/floor/asteroid
- var/global/image/rock_overlay = image('icons/turf/rock_overlay.dmi',"rock_overlay")
+ var/overlay_state = "rock_overlay"
+
+
+/turf/unsimulated/mineral/snow
+ icon_state = "snow_rock"
+ base_icon_state = "snow_rock"
+ mined_type = /turf/unsimulated/floor/snow
+ overlay_state = "snow_rock_overlay"
+
+/turf/unsimulated/mineral/snow/New()
+ base_icon_state = pick("snow_rock","snow_rock1","snow_rock2","snow_rock3","snow_rock4")
+ ..()
+
+/turf/unsimulated/mineral/underground
+ icon_state = "cave_wall"
+ base_icon_state = "cave_wall"
+ mined_type = /turf/unsimulated/floor/asteroid/underground
/turf/unsimulated/mineral/air
oxygen = MOLES_O2STANDARD
@@ -39,23 +56,37 @@
/turf/unsimulated/mineral/Destroy()
return
-var/list/icon_state_to_appearance = list()
-
/turf/unsimulated/mineral/New()
- if(!(mineral_turfs.len))
- rock_overlay.pixel_x = -4
- rock_overlay.pixel_y = -4
- rock_overlay.plane = BELOW_TURF_PLANE
mineral_turfs += src
. = ..()
MineralSpread()
+ update_icon()
- if(icon_state_to_appearance[icon_state])
- appearance = icon_state_to_appearance[icon_state]
+var/list/icon_state_to_appearance = list()
+
+/turf/unsimulated/mineral/update_icon(var/mineral_name = "empty") // feed in a mineral name to 'force' its appearance on an object.
+ if(mineral && mineral_name == "empty")
+ mineral_name = mineral.display_name
+ if(icon_state_to_appearance["[base_icon_state]-[mineral_name]"])
+ appearance = icon_state_to_appearance["[base_icon_state]-[mineral_name]"]
else
- overlays += rock_overlay
- icon_state_to_appearance[icon_state] = appearance
+ overlays.Cut()
+ if(mineral)
+ mineral_overlay = image('icons/turf/mine_overlays.dmi', mineral_name)
+ overlays += mineral_overlay
+ icon_state = base_icon_state
+ add_rock_overlay()
+ icon_state_to_appearance["[base_icon_state]-[mineral_name]"] = appearance
+/turf/unsimulated/mineral/proc/add_rock_overlay(var/image/img = image('icons/turf/rock_overlay.dmi', overlay_state,layer = SIDE_LAYER),var/offset=-4)
+ img.pixel_x = offset*PIXEL_MULTIPLIER
+ img.pixel_y = offset*PIXEL_MULTIPLIER
+ img.plane = BELOW_TURF_PLANE
+ overlays += img
+
+/turf/unsimulated/mineral/underground/add_rock_overlay()
+ ..(img = image('icons/turf/spookycave.dmi', "spooky_cave",layer = SIDE_LAYER),offset=-16)
+ ..(img = image('icons/turf/spookycave.dmi', "spooky_cave_corners",layer = CORNER_LAYER),offset = -16)
turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_lighting_update = 0, var/allow = 1)
mineral_turfs -= src
@@ -113,7 +144,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
name = "\improper Rock"
return
name = "\improper [mineral.display_name] deposit"
- icon_state = "rock_[mineral.name]"
+ update_icon()
/turf/unsimulated/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob)
@@ -410,12 +441,26 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
temperature = TCMB
//icon_plating = "asteroid"
var/dug = 0 //0 = has not yet been dug, 1 = has already been dug
+ var/sand_type = /obj/item/weapon/ore/glass
+ plane = PLATING_PLANE
/turf/unsimulated/floor/asteroid/air
oxygen = MOLES_O2STANDARD
nitrogen = MOLES_N2STANDARD
temperature = T20C
+/turf/unsimulated/floor/asteroid/underground
+ name = "cave floor"
+ temperature = T0C-150
+ oxygen = MOLES_O2STANDARD_ARCTIC
+ nitrogen = MOLES_N2STANDARD_ARCTIC
+ icon_state = "cavefl_1"
+ sand_type = /obj/item/weapon/ore/glass/cave
+
+/turf/unsimulated/floor/asteroid/underground/New()
+ ..()
+ icon_state = pick("cavefl_1","cavefl_2","cavefl_3","cavefl_4")
+
/turf/unsimulated/floor/asteroid/New()
var/proper_name = name
..()
@@ -424,7 +469,6 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
if(prob(20))
icon_state = "asteroid[rand(0,12)]"
- initialize()
/turf/unsimulated/floor/asteroid/ex_act(severity)
@@ -457,7 +501,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
return
to_chat(user, "You start digging.")
- playsound(get_turf(src), 'sound/effects/rustle1.ogg', 50, 1) //russle sounds sounded better
+ playsound(src, 'sound/effects/rustle1.ogg', 50, 1) //russle sounds sounded better
if(do_after(user, src, used_digging.digspeed) && user) //the better the drill, the faster the digging
playsound(src, 'sound/items/shovel.ogg', 50, 1)
@@ -468,18 +512,18 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
..(W,user)
return
+/turf/unsimulated/floor/asteroid/update_icon()
+ if(dug && ispath(sand_type, /obj/item/weapon/ore/glass))
+ icon_state = "asteroid_dug"
+
/turf/unsimulated/floor/asteroid/proc/gets_dug()
if(dug)
return
- new/obj/item/weapon/ore/glass(src)
- new/obj/item/weapon/ore/glass(src)
- new/obj/item/weapon/ore/glass(src)
- new/obj/item/weapon/ore/glass(src)
- new/obj/item/weapon/ore/glass(src)
+ for(var/i = 1 to 5)
+ new sand_type(src)
dug = 1
//icon_plating = "asteroid_dug"
- icon_state = "asteroid_dug"
- return
+ update_icon()
/turf/unsimulated/mineral/random
name = "Mineral deposit"
@@ -718,10 +762,14 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
var/activated_name = null
/turf/unsimulated/mineral/gibtonite/New()
- icon_state="rock_Diamond"
det_time = rand(8,10) //So you don't know exactly when the hot potato will explode
..()
+/turf/unsimulated/mineral/gibtonite/update_icon(var/mineral_name = "empty")
+ if(mineral_name == "empty" && !stage)
+ ..("Diamond")
+ else ..(mineral_name)
+
/turf/unsimulated/mineral/gibtonite/Bumped(AM)
var/bump_reject = 0
if(istype(AM,/mob/living/carbon/human))
@@ -758,7 +806,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
/turf/unsimulated/mineral/gibtonite/proc/explosive_reaction()
if(stage == 0)
- icon_state = "rock_Gibtonite_active"
+ update_icon("Gibtonite_active")
name = "Gibtonite deposit"
desc = "An active gibtonite reserve. Run!"
stage = 1
@@ -783,7 +831,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
/turf/unsimulated/mineral/gibtonite/proc/defuse()
if(stage == 1)
- icon_state = "rock_Gibtonite" //inactive does not exist. The other icon is active.
+ update_icon("Gibtonite") //inactive does not exist. The other icon is active.
desc = "An inactive gibtonite reserve. The ore can be extracted."
stage = 2
if(det_time < 0)
@@ -802,10 +850,10 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
if(stage == 2) //Gibtonite deposit is now benign and extractable. Depending on how close you were to it blowing up before defusing, you get better quality ore.
var/obj/item/weapon/gibtonite/G = new /obj/item/weapon/gibtonite/(src)
if(det_time <= 0)
- G.quality = 3
+ G.det_quality = 3
G.icon_state = "Gibtonite ore 3"
if(det_time >= 1 && det_time <= 2)
- G.quality = 2
+ G.det_quality = 2
G.icon_state = "Gibtonite ore 2"
ChangeTurf(/turf/unsimulated/floor/asteroid/gibtonite_remains)
@@ -821,7 +869,8 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
/mob/living/simple_animal/hostile/asteroid/goliath = 5,
/mob/living/simple_animal/hostile/asteroid/goldgrub = 1,
/mob/living/simple_animal/hostile/asteroid/basilisk = 3,
- /mob/living/simple_animal/hostile/asteroid/hivelord = 5
+ /mob/living/simple_animal/hostile/asteroid/hivelord = 5,
+ /mob/living/simple_animal/hostile/asteroid/magmaw = 4
)
var/sanity = 1
@@ -894,7 +943,7 @@ turf/unsimulated/mineral/ChangeTurf(var/turf/N, var/tell_universe=1, var/force_l
SpawnMonster(T)
- new /turf/unsimulated/floor/asteroid(T)
+ new /turf/unsimulated/floor/asteroid(T) // TODO: FIX THIS
/turf/unsimulated/floor/asteroid/cave/proc/SpawnMonster(var/turf/T)
if(prob(2))
diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm
index f5b11ae4674..d160a201d9d 100644
--- a/code/modules/mining/ores_coins.dm
+++ b/code/modules/mining/ores_coins.dm
@@ -37,10 +37,15 @@
slot_flags = SLOT_POCKET
throw_range = 1 //It just scatters to the ground as soon as you throw it.
+/obj/item/weapon/ore/glass/cave
+ name = "cave sand"
+ icon_state = "cavesand"
+
/obj/item/weapon/ore/glass/throw_impact(atom/hit_atom)
//Intentionally not calling ..()
if(isturf(hit_atom))
- new/obj/effect/decal/cleanable/scattered_sand(hit_atom)
+ if(!locate(/obj/effect/decal/cleanable/scattered_sand) in hit_atom)
+ new/obj/effect/decal/cleanable/scattered_sand(hit_atom)
qdel(src)
else if(ishuman(hit_atom))
var/mob/living/carbon/human/H = hit_atom
@@ -242,7 +247,7 @@
flags = FPRINT | TWOHANDABLE | MUSTTWOHAND
var/primed = 0
var/det_time = 100
- var/quality = 1 //How pure this gibtonite is, determines the explosion produced by it and is derived from the det_time of the rock wall it was taken from, higher shipping_value = better
+ var/det_quality = 1 //How pure this gibtonite is, determines the explosion produced by it and is derived from the det_time of the rock wall it was taken from, higher shipping_value = better
/obj/item/weapon/gibtonite/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/pickaxe) || istype(I, /obj/item/weapon/resonator))
@@ -252,7 +257,7 @@
primed = 0
user.visible_message("The chain reaction was stopped! ...The ore's quality went down.")
icon_state = "Gibtonite ore"
- quality = 1
+ det_quality = 1
return
..()
@@ -286,7 +291,7 @@
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
spawn(det_time)
if(primed)
- switch(quality)
+ switch(det_quality)
if(1)
explosion(src.loc,-1,1,3,adminlog = notify_admins)
if(2)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 73f782af243..99bd54a1665 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -350,7 +350,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
for(var/obj/effect/step_trigger/S in NewLoc)
S.Crossed(src)
- var/area/A = get_area_master(src)
+ var/area/A = get_area(src)
if(A)
A.Entered(src)
@@ -368,7 +368,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
for(var/obj/effect/step_trigger/S in get_turf(src)) //<-- this is dumb
S.Crossed(src)
- var/area/A = get_area_master(src)
+ var/area/A = get_area(src)
if(A)
A.Entered(src)
*/
@@ -676,7 +676,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(src, "Unknown: [round(unknown_concentration * 100)]% ([round(unknown_concentration * total_moles / tiles, 0.01)] moles)")
to_chat(src, "Temperature: [round(environment.temperature - T0C, 0.1)]°C")
- to_chat(src, "Heat Capacity: [round(environment.heat_capacity(), 0.1)]")
+ to_chat(src, "Heat Capacity: [round(environment.heat_capacity() / tiles, 0.1)]")
/mob/dead/observer/verb/toggle_darkness()
@@ -999,4 +999,19 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return selectedHUD == HUD_MEDICAL
if(HUD_SECURITY)
return selectedHUD == HUD_SECURITY
- return
\ No newline at end of file
+ return
+
+/mob/dead/observer/proc/can_reenter_corpse()
+ var/mob/M = get_top_transmogrification()
+ return (M && M.client && can_reenter_corpse)
+
+/mob/dead/observer/verb/pai_signup()
+ set name = "Sign up as pAI"
+ set category = "Ghost"
+ set desc = "Create and submit your pAI personality"
+
+ if(!paiController.check_recruit(src))
+ to_chat(src, "Not available. You may have been pAI-banned.")
+ return
+
+ paiController.recruitWindow(src)
diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm
index 209bd315330..6f748472a79 100644
--- a/code/modules/mob/emote.dm
+++ b/code/modules/mob/emote.dm
@@ -45,7 +45,7 @@
// Type 2 (Audible) emotes are sent to anyone in hear range
// of the *LOCATION* -- this is important for pAIs to be heard
else if (m_type & 2)
- for(var/mob/living/M in get_hearers_in_view(get_turf(src), null))
+ for(var/mob/M in get_hearers_in_view(7, src))
M.show_message(message, m_type)
/mob/proc/emote_dead(var/message)
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 583a041f372..50108cd7a82 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -183,7 +183,7 @@
W.hud_layerise()
W.pixel_x = initial(W.pixel_x)
W.pixel_y = initial(W.pixel_y)
- W.equipped(src, null, index)
+ W.equipped(src,null,index)
if(client)
client.screen |= W
@@ -513,7 +513,7 @@
return equipped
/mob/proc/get_id_card()
- for(var/obj/item/I in src.get_all_slots())
+ for(var/obj/item/I in src.get_all_slots() + held_items)
. = I.GetID()
if(.)
break
diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm
index 909b40d9ff6..cf87d45bc60 100644
--- a/code/modules/mob/language.dm
+++ b/code/modules/mob/language.dm
@@ -65,7 +65,6 @@
exclaim_verb = "roars"
colour = "soghun"
key = "o"
- flags = RESTRICTED
syllables = list("ss","ss","ss","ss","skak","seeki","resh","las","esi","kor","sh")
/datum/language/tajaran
@@ -76,7 +75,6 @@
exclaim_verb = "yowls"
colour = "tajaran"
key = "j"
- flags = RESTRICTED
syllables = list("rr","rr","tajr","kir","raj","kii","mir","kra","ahk","nal","vah","khaz","jri","ran","darr", \
"mi","jri","dynh","manq","rhe","zar","rrhaz","kal","chur","eech","thaa","dra","jurl","mah","sanu","dra","ii'r", \
"ka","aasi","far","wa","baq","ara","qara","zir","sam","mak","hrar","nja","rir","khan","jun","dar","rik","kah", \
@@ -90,7 +88,6 @@
exclaim_verb = "warbles"
colour = "skrell"
key = "k"
- flags = RESTRICTED
syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix","*","!")
/datum/language/vox
@@ -101,7 +98,6 @@
exclaim_verb = "shrieks"
colour = "vox"
key = "v"
- flags = RESTRICTED
syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya","chi","cha","kah", \
"SKRE","AHK","EHK","RAWK","KRA","AAA","EEE","KI","II","KRI","KA")
@@ -113,7 +109,6 @@
exclaim_verb = "rustles"
colour = "soghun"
key = "q"
- flags = RESTRICTED
syllables = list("hs","zt","kr","st","sh")
/datum/language/common
@@ -130,7 +125,6 @@
desc = "A bastardized hybrid of informal English and elements of Mandarin Chinese; the common language of the Sol system."
key = "7"
colour = "solcom"
- flags = RESTRICTED
/datum/language/human/monkey
name = LANGUAGE_MONKEY
@@ -149,6 +143,7 @@
colour = "say_quote"
key = "2"
space_chance = 100
+ flags = CAN_BE_SECONDARY_LANGUAGE
syllables = list("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit",
"sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore",
"magna", "aliqua", "ut", "enim", "ad", "minim", "veniam", "quis", "nostrud",
@@ -164,6 +159,7 @@
speech_verb = "growls"
colour = "gutter"
key = "3"
+ flags = CAN_BE_SECONDARY_LANGUAGE
syllables = list("gra","ba","ba","breh","bra","rah","dur","ra","ro","gro","go","ber","bar","geh","heh","gra")
/datum/language/grey
@@ -175,7 +171,6 @@
exclaim_verb = "quacks loudly"
colour = "grey"
native=1
- flags = RESTRICTED
space_chance = 100
syllables = list("ACK", "AKACK", "ACK")
@@ -196,7 +191,6 @@
exclaim_verb = "chatters loudly"
colour = "sinister"
native=1
- flags = RESTRICTED
space_chance = 95
syllables = list("CLICK", "CLACK")
@@ -210,7 +204,6 @@
colour = "golem"
native = 1
key = "8"
- flags = RESTRICTED
syllables = list("oa","ur","ae","um","tu","gor","an","lo","ag","oon","po")
/datum/language/slime
@@ -223,7 +216,6 @@
colour = "slime"
native = 1
key = "f"
- flags = RESTRICTED
syllables = list("ba","ab","be","eb","bi","ib","bo","ob","bu","ub")
/datum/language/skellington/say_misunderstood(mob/M, message)
@@ -274,7 +266,6 @@
key = "9"
space_chance = 80
syllables = list("squeak")
- flags = RESTRICTED
/datum/language/martian
name = LANGUAGE_MARTIAN
@@ -284,9 +275,9 @@
exclaim_verb = "blurbs"
key = "@"
colour = "grey"
+ flags = RESTRICTED
space_chance = 35
native = 1
- flags = RESTRICTED
syllables = list("khah","kig","kitol","kaor","bar","dar","dator","lok","ma","mu","o","och","gort","gal")
// Language handling.
@@ -350,9 +341,9 @@
src << browse(dat, "window=checklanguage")
/mob/living/Topic(href, href_list)
- if(usr != src)
- return
if(href_list["default_lang"])
+ if(usr != src)
+ return
if(href_list["default_lang"] == "reset")
set_default_language(null)
else
diff --git a/code/modules/mob/living/carbon/_defines.dm b/code/modules/mob/living/carbon/_defines.dm
index dde7bdc18dd..85689a69951 100644
--- a/code/modules/mob/living/carbon/_defines.dm
+++ b/code/modules/mob/living/carbon/_defines.dm
@@ -6,7 +6,7 @@
#define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point
#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 1000K point
-#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point
+#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 220.15k safety point
#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point
#define COLD_DAMAGE_LEVEL_3 3 //Amount of damage applied when your body temperature passes the 120K point
@@ -15,7 +15,7 @@
#define HEAT_GAS_DAMAGE_LEVEL_2 4 //Amount of damage applied when the current breath's temperature passes the 400K point
#define HEAT_GAS_DAMAGE_LEVEL_3 8 //Amount of damage applied when the current breath's temperature passes the 1000K point
-#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 260.15k safety point
+#define COLD_GAS_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when the current breath's temperature just passes the 220.15k safety point
#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point
#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point
diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
index 275511df7a6..1b8a6ab9073 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
@@ -149,7 +149,7 @@ Doesn't work on other aliens/AI.*/
proj_step_delay = 0.2
/spell/targeted/projectile/alienneurotoxin/is_valid_target(var/target, mob/user)
- if(!(spell_flags & INCLUDEUSER) && target == usr)
+ if(!(spell_flags & INCLUDEUSER) && target == user)
return FALSE
if(get_dist(usr, target) > range)
return FALSE
@@ -214,8 +214,17 @@ Doesn't work on other aliens/AI.*/
range = 1
/spell/alienacid/is_valid_target(var/atom/target, mob/user)
- if(get_dist(user, target) > range) //Shouldn't be necessary but a good check in case of overrides
+ return is_valid_target_to_acid(target,user,range)
+
+/proc/is_valid_target_to_acid(var/atom/target, mob/user,var/range=1)
+ if(get_dist(user, target) > range)
+ to_chat(user, "Target is too far away!")
return FALSE
+ if(target.isacidhardened())
+ if(!do_after(user,target,3 SECONDS))
+ to_chat(user, "You have to stay next to the object to acid it!")
+ return FALSE
+ return TRUE
if(!ismob(target) && target.acidable())
return TRUE
to_chat(user, "You cannot dissolve this object.")
@@ -233,21 +242,13 @@ Doesn't work on other aliens/AI.*/
return
if(powerc(200))
- if(O in oview(1))
- if(!O.acidable())
- to_chat(usr, "You cannot dissolve this object.")
- return FALSE
- AdjustPlasma(-200)
+ if(is_valid_target_to_acid(O, usr))
acidify(O, usr)
- else
- to_chat(usr, "Target is too far away.")
+ AdjustPlasma(-200)
/proc/acidify(atom/O, mob/user)
- if(O.acidable())
- new /obj/effect/alien/acid(get_turf(O), O)
- user.visible_message("\The [usr] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!")
- else
- to_chat(user, "You cannot dissolve this object.")
+ new /obj/effect/alien/acid(get_turf(O), O)
+ user.visible_message("\The [user] vomits globs of vile stuff all over [O]. It begins to sizzle and melt under the bubbling mess of acid!")
/spell/aoe_turf/alienregurgitate
name = "Regurgitate"
@@ -265,7 +266,7 @@ Doesn't work on other aliens/AI.*/
/spell/aoe_turf/alienregurgitate/cast(list/targets, mob/user)
var/mob/living/carbon/alien/humanoid/alien = user
alien.drop_stomach_contents()
- user.visible_message("\The [usr] hurls out the contents of their stomach!")
+ user.visible_message("\The [user] hurls out the contents of their stomach!")
///////////////////////////
// QUEEN SPECIFIC SPELLS //
@@ -286,7 +287,7 @@ Doesn't work on other aliens/AI.*/
spell_flags = IGNORESPACE|NODUPLICATE
summon_type = list(/obj/effect/alien/egg)
-a
+
/spell/aoe_turf/conjure/alienegg/cast(list/targets, mob/user)
. = ..()
if(!.) //Returning 1 if we failed to cast
@@ -309,6 +310,7 @@ a
cast_sound = 'sound/effects/evolve.ogg'
cast_delay = 50
+ use_progress_bar = TRUE
/spell/aoe_turf/evolve/drone
desc = "Produce an interal egg sac capable of spawning children. Only one queen can exist at a time."
@@ -327,7 +329,7 @@ a
return ..()
/spell/aoe_turf/evolve/drone/spell_do_after(var/mob/user as mob, delay as num, var/numticks = 5)
- user.visible_message("[src] begins to violently twist and contort!", "You begin to evolve, stand still for a few moments")
+ user.visible_message("[user] begins to violently twist and contort!", "You begin to evolve, stand still for a few moments.")
return ..()
/spell/aoe_turf/evolve/drone/cast(list/targets, mob/living/carbon/user)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/combat.dm b/code/modules/mob/living/carbon/alien/humanoid/combat.dm
index 2079f34b1ac..02dcde1a39e 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/combat.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/combat.dm
@@ -1,15 +1,15 @@
/mob/living/carbon/alien/humanoid/disarm_mob(mob/living/target)
if(target.disarmed_by(src))
return
-
- if(prob(80))
+ var/datum/organ/external/affecting = get_organ(ran_zone(zone_sel.selecting))
+ var/disarm_chance_modifier = target.run_armor_check(affecting, "melee", quiet = 1)
+ if(prob(80/(disarm_chance_modifier == 0 ? 1 : disarm_chance_modifier)))
do_attack_animation(target, src)
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
- target.Knockdown(rand(3,4))
-
+ target.apply_effect(4, WEAKEN, run_armor_check(affecting, "melee"))
visible_message("[src] has tackled down [target]!")
- else if (prob(80))
+ else if (prob(80/(disarm_chance_modifier == 0 ? 1 : disarm_chance_modifier)))
do_attack_animation(target, src)
playsound(loc, get_unarmed_hit_sound(), 25, 1, -1)
target.drop_item()
diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm
index faa32cab421..16c8ba3f4db 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm
@@ -122,9 +122,9 @@
if ((message && src.stat == 0))
log_emote("[name]/[key] (@[x],[y],[z]): [message]")
if (act == "roar")
- playsound(get_turf(src), 'sound/voice/hiss5.ogg', 40, 1, 1)
+ playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1)
if (act == "deathgasp")
- playsound(get_turf(src), 'sound/voice/hiss6.ogg', 80, 1, 1)
+ playsound(src, 'sound/voice/hiss6.ogg', 80, 1, 1)
if (m_type & 1)
for(var/mob/O in viewers(src, null))
O.show_message(message, m_type)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/life.dm b/code/modules/mob/living/carbon/alien/humanoid/life.dm
index 87b3df5eebb..bd0785f8ad5 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/life.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/life.dm
@@ -121,16 +121,13 @@
var/obj/location_as_object = loc
breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME)
else if(istype(loc, /turf/))
- var/breath_moles = 0
/*if(environment.return_pressure() > ONE_ATMOSPHERE)
// Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT)
breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature)
else
*/
// Not enough air around, take a percentage of what's there to model this properly
- breath_moles = environment.total_moles()/environment.volume*CELL_VOLUME*BREATH_PERCENTAGE
-
- breath = loc.remove_air(breath_moles)
+ breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE)
// Handle chem smoke effect -- Doohl
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
@@ -178,14 +175,15 @@
return 0
var/toxins_used = 0
- var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
+ breath.volume = BREATH_VOLUME
+ breath.update_values()
//Partial pressure of the toxins in our breath
- var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure
+ var/Toxins_pp = (breath.toxins / breath.total_moles()) * breath.pressure
if(Toxins_pp) // Detect toxins in air
- AdjustPlasma(breath.toxins*250)
+ AdjustPlasma(breath.toxins * 250)
toxins_alert = max(toxins_alert, 1)
toxins_used = breath.toxins
@@ -199,7 +197,7 @@
if(breath.temperature > (T0C+66) && !(M_RESIST_HEAT in mutations)) // Hot air hurts :(
if(prob(20))
- to_chat(src, "You feel a searing heat in your lungs !")
+ to_chat(src, "You feel a searing heat in your lungs!")
fire_alert = max(fire_alert, 1)
else
fire_alert = 0
diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm
index d290146337e..c6fa440ec6b 100644
--- a/code/modules/mob/living/carbon/alien/larva/life.dm
+++ b/code/modules/mob/living/carbon/alien/larva/life.dm
@@ -101,16 +101,13 @@
var/obj/location_as_object = loc
breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME)
else if(istype(loc, /turf/))
- var/breath_moles = 0
/*if(environment.return_pressure() > ONE_ATMOSPHERE)
// Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT)
breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature)
else
*/
// Not enough air around, take a percentage of what's there to model this properly
- breath_moles = environment.total_moles()/environment.volume*CELL_VOLUME*BREATH_PERCENTAGE
-
- breath = loc.remove_air(breath_moles)
+ breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE)
// Handle chem smoke effect -- Doohl
for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
@@ -159,14 +156,15 @@
return 0
var/toxins_used = 0
- var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
+ breath.volume = BREATH_VOLUME
+ breath.update_values()
//Partial pressure of the toxins in our breath
- var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure
+ var/Toxins_pp = (breath.toxins / breath.total_moles()) * breath.pressure
if(Toxins_pp) // Detect toxins in air
- AdjustPlasma(breath.toxins*250)
+ AdjustPlasma(breath.toxins * 250)
toxins_alert = max(toxins_alert, 1)
toxins_used = breath.toxins
diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm
index f9f92408c20..81907c304c8 100644
--- a/code/modules/mob/living/carbon/alien/special/facehugger.dm
+++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm
@@ -38,7 +38,7 @@
var/target_time = 0.5 // seconds
var/walk_speed = 1
var/nextwalk = FALSE
- var/mob/living/carbon/target = null
+ var/mob/living/target = null
/obj/item/clothing/mask/facehugger/can_contaminate()
return FALSE
@@ -52,16 +52,16 @@
/obj/item/clothing/mask/facehugger/process()
healthcheck()
followtarget()
+ spreadout()
/obj/item/clothing/mask/facehugger/proc/findtarget()
if(!real)
return
- for(var/mob/living/carbon/T in hearers(src,4))
- if(!ishuman(T) && !ismonkey(T))
+ target = null
+ for(var/mob/living/T in hearers(src,4))
+ if(!CanHug(T, src))
continue
- if(!CanHug(T))
- continue
- if(T && (T.stat != DEAD && T.stat != UNCONSCIOUS) )
+ if(T && (!T.isUnconscious() ) )
if(get_dist(loc, T.loc) <= 4)
target = T
@@ -70,31 +70,38 @@
/obj/item/clothing/mask/facehugger/proc/followtarget()
if(!real)
return // Why are you trying to path stupid toy
- if(!target || target.stat == DEAD || target.stat == UNCONSCIOUS || target.status_flags & XENO_HOST)
+ if(!target || target.isUnconscious() || target.status_flags & XENO_HOST)
findtarget()
return
- if(loc && loc == get_turf(src) && !attached && !stat && nextwalk <= world.time)
+ if(loc && isturf(loc) && !attached && !stat && nextwalk <= world.time)
nextwalk = world.time + walk_speed
var/dist = get_dist(loc, target.loc)
if(dist > 4)
+ target = null
return //We'll let the facehugger do nothing for a bit, since it's fucking up.
var/obj/item/clothing/mask/facehugger/F = target.is_wearing_item(/obj/item/clothing/mask/facehugger, slot_wear_mask)
- if(F && F.sterile) // Toy's won't prevent real huggers
+ if(F && !F.sterile) // Toys won't prevent real huggers
findtarget()
return
else
step_towards(src, target, 0)
if(dist <= 1)
- if(CanHug(target))
+ if(CanHug(target, src) && isturf(target.loc)) //Fix for hugging through mechs and closets
Attach(target)
return
else
- target = null
walk(src,0)
findtarget()
return
+/obj/item/clothing/mask/facehugger/proc/spreadout()
+ if(!target && isturf(loc) && stat == CONSCIOUS)
+ for(var/obj/item/clothing/mask/facehugger/F in loc)
+ if(F != src && F.stat != DEAD)
+ step(src, pick(alldirs), 0)
+ break
+
//END HUGGER MOVEMENT AI
@@ -135,7 +142,7 @@
/obj/item/clothing/mask/facehugger/proc/healthcheck()
if(health <= 0)
icon_state = "[initial(icon_state)]_dead"
- Die()
+ death()
/obj/item/clothing/mask/facehugger/attack(mob/living/M as mob, mob/user as mob)
..()
@@ -176,7 +183,7 @@
/obj/item/clothing/mask/facehugger/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > 300)
- Die()
+ death()
return
/obj/item/clothing/mask/facehugger/equipped(mob/M)
@@ -192,8 +199,9 @@
return FALSE
/obj/item/clothing/mask/facehugger/HasProximity(atom/movable/AM as mob|obj)
- if(CanHug(AM))
- return Attach(AM)
+ if(isliving(AM))
+ if(CanHug(AM, src))
+ return Attach(AM)
return FALSE
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed)
@@ -208,26 +216,24 @@
..()
if(stat == CONSCIOUS)
icon_state = "[initial(icon_state)]"
- Attach(hit_atom)
+ if(isliving(hit_atom))
+ Attach(hit_atom)
-/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/M as mob)
+/obj/item/clothing/mask/facehugger/proc/Attach(mob/living/L)
var/preggers = rand(MIN_IMPREGNATION_TIME,MAX_IMPREGNATION_TIME)
- if( (!iscorgi(M) && !iscarbon(M)) || isalien(M))
+ if(isalien(L))
+ return FALSE
+ if(L.status_flags & XENO_HOST)
+ visible_message("An alien tries to place a facehugger on [L] but it refuses sloppy seconds!")
return FALSE
- if(iscarbon(M) && M.status_flags & XENO_HOST)
- visible_message("An alien tries to place a facehugger on [M] but it refuses sloppy seconds!")
- return
if(attached)
return FALSE
- if(!Adjacent(M))
+ if(!Adjacent(L))
return FALSE
else
attached++
spawn(MAX_IMPREGNATION_TIME)
attached = FALSE
-
- var/mob/living/L = M //just so I don't need to use :
-
if(loc == L)
return FALSE
if(stat != CONSCIOUS)
@@ -237,14 +243,14 @@
L.visible_message("\The [src] leaps at [L]'s face!")
+ if(!CanHug(L, src))
+ return FALSE
+
if(ishuman(L))
var/mob/living/carbon/human/H = L
var/obj/item/mouth_protection = H.get_body_part_coverage(MOUTH)
if(!real && mouth_protection)
return //Toys really shouldn't be forcefully removing gear
- var/obj/item/clothing/mask/facehugger/hugger = H.get_item_by_slot(slot_wear_mask)
- if(istype(hugger) && !hugger.sterile && !sterile) // Lamarr won't fight over faces and neither will normal huggers.
- return
if(mouth_protection && mouth_protection != H.wear_mask) //can't be protected with your own mask, has to be a hat
stat_collection.xeno_faces_protected++
@@ -257,22 +263,23 @@
GoIdle(TIME_IDLE_AFTER_HEAD_DENIED)
return
else
- H.visible_message("\The [src] bounces off of the [mouth_protection]!")
+ H.visible_message("\The [src] bounces off of \the [mouth_protection]!")
if(prob(CHANCE_TO_DIE_AFTER_HEAD_DENIED) && !sterile)
- Die()
+ death()
return
else
GoIdle(TIME_IDLE_AFTER_HEAD_DENIED)
return
return
- if(iscarbon(M))
+ if(iscarbon(L))
var/mob/living/carbon/target = L
+ var/obj/item/clothing/W = target.get_item_by_slot(slot_wear_mask)
+ var/obj/item/weapon/tank/had_internal = target.internal
- if(target.get_item_by_slot(slot_wear_mask))
+ if(W && W != src)
if(prob(CHANCE_TO_NOT_REMOVE_MASKS))
return FALSE
- var/obj/item/clothing/W = target.wear_mask
if(!W.canremove)
return FALSE
target.drop_from_inventory(W)
@@ -282,15 +289,45 @@
forceMove(target)
target.equip_to_slot(src, slot_wear_mask)
target.update_inv_wear_mask()
+ target.internal = had_internal //Try to keep the host ALIVE
+ target.update_internals()
- if(!sterile)
+ if(!sterile && target.hasmouth)
L.Paralyse((preggers/10)+10) //something like 25 ticks = 20 seconds with the default settings
- else if (iscorgi(M))
- var/mob/living/simple_animal/corgi/C = M
+ else if (iscorgi(L))
+ var/mob/living/simple_animal/corgi/C = L
+ var/obj/item/clothing/head/headwear = C.inventory_head
+ var/rng = 100
+ var/obj/item/clothing/mask/facehugger/hugger = C.facehugger
+
+ if(hugger && !hugger.sterile)
+ return
+
+ if(headwear)
+ if(istype(headwear, /obj/item/clothing/head/cardborg))
+ rng = CHANCE_TO_REMOVE_HEADWEAR
+ else if(istype(headwear, /obj/item/clothing/head/helmet/space/rig))
+ rng = CHANCE_TO_REMOVE_SPECIAL_HEADWEAR
+
+ if(prob(rng))
+ C.visible_message("\The [src] smashes against [C]'s \the [headwear], and rips it off in the process!")
+ C.drop_from_inventory(headwear)
+ GoIdle(TIME_IDLE_AFTER_HEAD_DENIED)
+ return
+ else
+ C.visible_message("\The [src] bounces off of \the [headwear]!")
+ if(prob(CHANCE_TO_DIE_AFTER_HEAD_DENIED) && !sterile)
+ death()
+ return
+ else
+ GoIdle(TIME_IDLE_AFTER_HEAD_DENIED)
+ return
+ return
+
forceMove(C)
C.facehugger = src
C.wear_mask = src
- //C.regenerate_icons()
+ C.regenerate_icons()
GoIdle(TIME_IDLE_AFTER_ATTACH_DENIED) //so it doesn't jump the people that tear it off
@@ -303,7 +340,9 @@
if(!target || target.wear_mask != src || target.stat == DEAD) //was taken off or something
return
- if(!sterile)
+ var/mob/living/carbon/CA = target
+
+ if(!sterile && !(istype(CA) && !CA.hasmouth))
var/obj/item/alien_embryo/E = new (target)
target.status_flags |= XENO_HOST
if(istype(target, /mob/living/carbon/human))
@@ -313,13 +352,15 @@
target.visible_message("\The [src] falls limp after violating [target]'s face !")
stat_collection.xeno_faces_hugged++
- Die()
+ death()
+ //target.drop_from_inventory(src)
icon_state = "[initial(icon_state)]_impregnated"
if(iscorgi(target))
var/mob/living/simple_animal/corgi/C = target
forceMove(get_turf(C))
C.facehugger = null
+ C.regenerate_icons()
else
target.visible_message("\The [src] violates [target]'s face !")
return
@@ -346,7 +387,7 @@
GoActive()
return
-/obj/item/clothing/mask/facehugger/proc/Die()
+/obj/item/clothing/mask/facehugger/proc/death()
if(stat == DEAD || !real)
return
target = null
@@ -358,20 +399,30 @@
visible_message("\The [src] curls up into a ball!")
- return
-/proc/CanHug(var/mob/M)
+/proc/CanHug(mob/living/M, obj/item/clothing/mask/facehugger/hugger = null)
+ if(isalien(M))
+ return FALSE
+ if(M.status_flags & XENO_HOST)
+ return FALSE
if(iscorgi(M))
+ var/mob/living/simple_animal/corgi/corgi = M
+ if(corgi.facehugger && !corgi.facehugger.sterile)
+ return FALSE
+
return TRUE
- if(!iscarbon(M) || isalien(M) || isslime(M))
+ if(!ishuman(M) && !ismonkey(M))
return FALSE
var/mob/living/carbon/C = M
- if(C && (istype(C.wear_mask, /obj/item/clothing/mask/facehugger) || C.status_flags & XENO_HOST))
+ var/obj/item/clothing/mask/facehugger/F = C.is_wearing_item(/obj/item/clothing/mask/facehugger, slot_wear_mask)
+
+ if(F && (!F.sterile || hugger.sterile) && F != hugger) // Lamarr won't fight over faces and neither will normal huggers.
return FALSE
+
return TRUE
/obj/item/clothing/mask/facehugger/acidable()
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index c28fd0fad6d..df337ca64f4 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -66,7 +66,7 @@ obj/item/device/mmi/Destroy()
//canmove = 0
icon = null
invisibility = 101
- var/mob/living/silicon/robot/mommi/M = new /mob/living/silicon/robot/mommi(get_turf(loc))
+ var/mob/living/silicon/robot/mommi/M = new /mob/living/silicon/robot/mommi/nt(get_turf(loc))
if(!M)
return
M.invisibility = 0
@@ -278,7 +278,7 @@ obj/item/device/mmi/Destroy()
else if(!src.brainmob.key)
to_chat(user, "It seems to be in a deep dream-state")//ghosted
- to_chat(user, "It's interface is [locked ? "locked" : "unlocked"] ")
+ to_chat(user, "Its interface is [locked ? "locked" : "unlocked"] ")
to_chat(user, "*---------*")
/obj/item/device/mmi/OnMobDeath(var/mob/living/carbon/brain/B)
diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm
index 8724f257580..861a2869da9 100644
--- a/code/modules/mob/living/carbon/brain/brain_item.dm
+++ b/code/modules/mob/living/carbon/brain/brain_item.dm
@@ -88,4 +88,12 @@
organ_type = /datum/organ/internal/brain/slime_core
/obj/item/organ/internal/brain/slime_core/process()
- processing_objects -= src
\ No newline at end of file
+ processing_objects -= src
+
+/obj/item/organ/internal/brain/mushroom
+ name = "plump helmet brain"
+ desc = "At first glance, it looks like a popular miner delicacy, but is in fact the primary function of thought for a mushroom person."
+ icon_state = "plump_pie"
+ icon = 'icons/obj/food.dmi'
+ health = 600
+ origin_tech = Tc_BIOTECH + "=4"
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/brain/life.dm b/code/modules/mob/living/carbon/brain/life.dm
index 4ec70371208..cbdcc8ed7ba 100644
--- a/code/modules/mob/living/carbon/brain/life.dm
+++ b/code/modules/mob/living/carbon/brain/life.dm
@@ -74,7 +74,7 @@
/mob/living/carbon/brain/proc/handle_environment(datum/gas_mixture/environment)
if(!environment || (flags & INVULNERABLE))
return
- var/environment_heat_capacity = environment.heat_capacity()
+ var/environment_heat_capacity = environment.heat_capacity() / environment.volume * CELL_VOLUME
if(istype(get_turf(src), /turf/space))
var/turf/heat_turf = get_turf(src)
environment_heat_capacity = heat_turf.heat_capacity
@@ -244,16 +244,23 @@
update_pull_icon()
if (client)
-// clear_fullscreens()
if(src.eye_blind || blinded)
overlay_fullscreen("blind", /obj/abstract/screen/fullscreen/blind)
+ else
+ clear_fullscreen("blind")
if (src.disabilities & NEARSIGHTED)
overlay_fullscreen("impaired", /obj/abstract/screen/fullscreen/impaired)
+ else
+ clear_fullscreen("impaired")
if (src.eye_blurry)
overlay_fullscreen("blurry", /obj/abstract/screen/fullscreen/blurry)
+ else
+ clear_fullscreen("blurry")
if (src.druggy)
overlay_fullscreen("high", /obj/abstract/screen/fullscreen/high)
+ else
+ clear_fullscreen("high")
if (stat != 2)
if (machine)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 619debca550..48bc1012e96 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -212,7 +212,7 @@
AdjustParalysis(-3)
AdjustStunned(-3)
AdjustKnockdown(-3)
- playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
M.visible_message( \
"[M] shakes [src] trying to wake [t_him] up!", \
"You shake [src] trying to wake [t_him] up!", \
@@ -272,13 +272,13 @@
if (U && U.wired && U.cell && U.cell.charge >= STUNGLOVES_CHARGE_COST && T.siemens_coefficient == 0)
to_chat(M, "\The [src]'s insulated gloves prevent them from being shocked.")
- playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
M.visible_message( \
"[M] shakes [ismartian(M) ? "tentacles" : "hands"] with [src].", \
"You shake [ismartian(M) ? "tentacles" : "hands"] with [src].", \
)
else
- playsound(get_turf(src), 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
+ playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
M.visible_message( \
"[M] gives [src] a [pick("hug","warm embrace")].", \
"You hug [src].", \
@@ -500,20 +500,21 @@
/mob/living/carbon/CheckSlip()
return !locked_to && !lying && !unslippable
-/mob/living/carbon/proc/Slip(stun_amount, weaken_amount, slip_on_walking = 0)
+/mob/living/proc/Slip(stun_amount, weaken_amount, slip_on_walking = 0)
+ stop_pulling()
+ Stun(stun_amount)
+ Knockdown(weaken_amount)
+ return 1
+
+/mob/living/carbon/Slip(stun_amount, weaken_amount, slip_on_walking = 0)
if(!slip_on_walking && m_intent == "walk")
return 0
if (CheckSlip() < 1 || !on_foot())
return 0
-
- stop_pulling()
- Stun(stun_amount)
- Knockdown(weaken_amount)
-
- playsound(get_turf(src), 'sound/misc/slip.ogg', 50, 1, -3)
-
- return 1
+ if(..())
+ playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
+ return 1
/mob/living/carbon/proc/transferImplantsTo(mob/living/carbon/newmob)
for(var/obj/item/weapon/implant/I in src)
@@ -625,7 +626,7 @@
/mob/living/carbon/movement_tally_multiplier()
. = ..()
- if(!istype(loc, /turf/space) && !reagents.has_any_reagents(list(HYPERZINE,COCAINE)))
+ if(!istype(loc, /turf/space))
for(var/obj/item/I in get_clothing_items())
if(I.slowdown <= 0)
testing("[I] HAD A SLOWDOWN OF <=0 OH DEAR")
@@ -636,6 +637,11 @@
if(I.flags & SLOWDOWN_WHEN_CARRIED)
. *= I.slowdown
+ if(reagents.has_any_reagents(list(HYPERZINE,COCAINE)))
+ . *= 0.4
+ if(. < 1)//we don't want to move faster than the base speed
+ . = 1
+
/mob/living/carbon/base_movement_tally()
. = ..()
if(flying)
@@ -677,7 +683,7 @@
to_chat(src, "Interference is disrupting the connection with the mind of [M].")
return 0
if(ismartian(M))
- var/mob/living/carbon/martian/MR = M
+ var/mob/living/carbon/complex/martian/MR = M
if(MR.head)
if(istype(MR.head, /obj/item/clothing/head/helmet/space/martian) || istype(MR.head,/obj/item/clothing/head/tinfoil))
to_chat(src, "Interference is disrupting the connection with the mind of [M].")
diff --git a/code/modules/mob/living/carbon/combat.dm b/code/modules/mob/living/carbon/combat.dm
index 35d367b70f4..4c11e21f985 100644
--- a/code/modules/mob/living/carbon/combat.dm
+++ b/code/modules/mob/living/carbon/combat.dm
@@ -56,7 +56,7 @@
return TRUE //We still connected
if(!I.force)
return TRUE
-
- apply_damage(I.force, I.damtype, affecting, armor , I.is_sharp(), used_weapon = I)
+ var/damage = run_armor_absorb(target_zone, I.damtype, I.force)
+ apply_damage(damage, I.damtype, affecting, armor , I.is_sharp(), used_weapon = I)
return TRUE
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/martian/combat.dm b/code/modules/mob/living/carbon/complex/combat.dm
similarity index 72%
rename from code/modules/mob/living/carbon/martian/combat.dm
rename to code/modules/mob/living/carbon/complex/combat.dm
index 9d4cdd1a142..35ad9366cd0 100644
--- a/code/modules/mob/living/carbon/martian/combat.dm
+++ b/code/modules/mob/living/carbon/complex/combat.dm
@@ -1,25 +1,16 @@
-/mob/living/carbon/martian/get_unarmed_damage_zone(mob/living/victim)
+/mob/living/carbon/complex/get_unarmed_damage_zone(mob/living/victim)
return zone_sel.selecting
-/mob/living/carbon/martian/knockout_chance_modifier()
+/mob/living/carbon/complex/knockout_chance_modifier()
return 0 //Punches don't stun
-/mob/living/carbon/martian/bullet_act(var/obj/item/projectile/P, var/def_zone)
+/mob/living/carbon/complex/bullet_act(var/obj/item/projectile/P, var/def_zone)
if(check_shields(P.damage, "the [P.name]"))
P.on_hit(src, 2)
return 2
return (..(P , def_zone))
-/mob/living/carbon/martian/getarmor(var/def_zone, var/type)
-
- var/armorscore = 0
- if((def_zone == "head") || (def_zone == "eyes") || (def_zone == "mouth"))
- if(head)
- armorscore = head.armor[type]
-
- return armorscore
-
-/mob/living/carbon/martian/attack_hand(mob/living/M)
+/mob/living/carbon/complex/attack_hand(mob/living/M)
switch(M.a_intent)
if(I_HELP)
help_shake_act(M)
@@ -33,7 +24,7 @@
if(I_DISARM)
M.disarm_mob(src)
-/mob/living/carbon/martian/attack_alien(mob/living/M)
+/mob/living/carbon/complex/attack_alien(mob/living/M)
switch(M.a_intent)
if (I_HELP)
visible_message("[M] caresses [src] with its scythe like arm.")
@@ -47,16 +38,16 @@
if (I_DISARM)
return M.disarm_mob(src)
-/mob/living/carbon/martian/attack_slime(mob/living/carbon/slime/M)
+/mob/living/carbon/complex/attack_slime(mob/living/carbon/slime/M)
M.unarmed_attack_mob(src)
-/mob/living/carbon/martian/attack_martian(mob/M)
+/mob/living/carbon/complex/attack_martian(mob/M)
return attack_hand(M)
-/mob/living/carbon/martian/attack_paw(mob/M)
+/mob/living/carbon/complex/attack_paw(mob/M)
return attack_hand(M)
-/mob/living/carbon/martian/disarm_mob(mob/living/target)
+/mob/living/carbon/complex/disarm_mob(mob/living/target)
add_logs(src, target, "disarmed", admin = (src.ckey && target.ckey) ? TRUE : FALSE) //Only add this to the server logs if both mobs were controlled by player
if(target.disarmed_by(src))
diff --git a/code/modules/mob/living/carbon/complex/complex_defines.dm b/code/modules/mob/living/carbon/complex/complex_defines.dm
new file mode 100644
index 00000000000..a52e37248ef
--- /dev/null
+++ b/code/modules/mob/living/carbon/complex/complex_defines.dm
@@ -0,0 +1,17 @@
+/mob/living/carbon/complex
+ var/icon_state_standing
+ var/icon_state_lying
+ var/icon_state_dead
+ var/flag = 0
+ var/oxygen_alert = 0
+ var/toxins_alert = 0
+ var/fire_alert = 0
+ var/pressure_alert = 0
+ base_insulation = 0.5
+ var/temperature_alert = 0
+ var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa
+ var/co2overloadtime = null
+
+/mob/living/carbon/complex/New()
+ create_reagents(200)
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/martian/examine.dm b/code/modules/mob/living/carbon/complex/examine.dm
similarity index 91%
rename from code/modules/mob/living/carbon/martian/examine.dm
rename to code/modules/mob/living/carbon/complex/examine.dm
index 0e6338396ba..fcf2d675ed2 100644
--- a/code/modules/mob/living/carbon/martian/examine.dm
+++ b/code/modules/mob/living/carbon/complex/examine.dm
@@ -1,4 +1,4 @@
-/mob/living/carbon/martian/examine(mob/user)
+/mob/living/carbon/complex/examine(mob/user)
var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n"
@@ -17,12 +17,12 @@
else
msg += ""
if (src.getBruteLoss())
- if (src.getBruteLoss() < 30)
+ if (src.getBruteLoss() < maxHealth/2)
msg += "It has minor bruising.\n"
else
msg += "It has severe bruising!\n"
if (src.getFireLoss())
- if (src.getFireLoss() < 30)
+ if (src.getFireLoss() < maxHealth/2)
msg += "It has minor burns.\n"
else
msg += "It has severe burns!\n"
diff --git a/code/modules/mob/living/carbon/complex/gondola/gondola.dm b/code/modules/mob/living/carbon/complex/gondola/gondola.dm
new file mode 100644
index 00000000000..07fb2005154
--- /dev/null
+++ b/code/modules/mob/living/carbon/complex/gondola/gondola.dm
@@ -0,0 +1,29 @@
+/mob/living/carbon/complex/gondola
+ name = "gondola"
+ desc = "A calming presence in this strange land."
+ icon = 'icons/mob/gondola.dmi'
+
+ icon_state_standing = "gondola"
+ icon_state_lying = "gondola_lying"
+ icon_state_dead = "gondola_dead"
+
+ maxHealth = 75
+ health = 75
+
+ held_items = list()
+
+ size = SIZE_NORMAL
+ status_flags = CANSTUN|CANKNOCKDOWN|CANPARALYSE|CANPUSH
+ mob_bump_flag = HUMAN
+ mob_push_flags = ALLMOBS
+ mob_swap_flags = ALLMOBS
+
+/mob/living/carbon/complex/gondola/New()
+ icon_state_standing = pick("gondola","gondola_1")
+ icon_state_lying = "[icon_state_standing]_lying"
+ icon_state_dead = "[icon_state_dead]_dead"
+ ..()
+
+
+/mob/living/carbon/complex/gondola/say()
+ return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/complex/gondola/gondola_receive_music.dm b/code/modules/mob/living/carbon/complex/gondola/gondola_receive_music.dm
new file mode 100644
index 00000000000..f07d0dd87bf
--- /dev/null
+++ b/code/modules/mob/living/carbon/complex/gondola/gondola_receive_music.dm
@@ -0,0 +1,120 @@
+//Basically walking media receivers
+/mob/living/carbon/complex/gondola
+ var/playing=0
+ var/media_url=""
+ var/media_start_time=0
+ var/area/master_area
+ var/media_frequency = 1234 // 123.4 MHz
+ var/media_crypto = null // Crypto key
+
+ var/list/obj/machinery/media/transmitter/hooked = list()
+ var/exclusive_hook=null // Disables output to the room
+
+/mob/living/carbon/complex/gondola/New()
+ ..()
+ connect_frequency()
+
+/mob/living/carbon/complex/gondola/death(var/gibbed = FALSE)
+ disconnect_media_source()
+ ..(gibbed)
+
+/mob/living/carbon/complex/gondola/area_entered()
+ update_music()
+
+/mob/living/carbon/complex/gondola/proc/connect_frequency()
+ // This is basically media_receivers["[media_frequency]"] += src
+ var/list/receivers=list()
+ var/freq = num2text(media_frequency)
+ if(freq in media_receivers)
+ receivers = media_receivers[freq]
+ receivers.Add(src)
+ media_receivers[freq]=receivers
+
+ // Check if there's a broadcast to tune into.
+ if(freq in media_transmitters)
+ // Pick a random broadcast in that frequency.
+ var/obj/machinery/media/transmitter/B = pick(media_transmitters[freq])
+ if(B.media_crypto == media_crypto) // Crypto-key check, if needed.
+ receive_broadcast(B.media_url,B.media_start_time)
+
+/mob/living/carbon/complex/gondola/proc/receive_broadcast(var/url="", var/start_time=0)
+ media_url = url
+ media_start_time = start_time
+ update_music()
+
+/mob/living/carbon/complex/gondola/proc/disconnect_frequency()
+ var/list/receivers=list()
+ var/freq = num2text(media_frequency)
+ if(freq in media_receivers)
+ receivers = media_receivers[freq]
+ receivers.Remove(src)
+ media_receivers[freq]=receivers
+
+ receive_broadcast()
+
+/mob/living/carbon/complex/gondola/update_music()
+ if(isDead(src))
+ return
+ // Broadcasting shit
+ for(var/obj/machinery/media/transmitter/T in hooked)
+// testing("[src] Writing media to [T].")
+ T.broadcast(media_url,media_start_time)
+
+ if(exclusive_hook)
+ disconnect_media_source() // Just to be sure.
+ return
+
+ update_media_source()
+
+ // Bail if we lost connection to master.
+ if(!master_area)
+ return
+
+ // Send update to clients.
+ for(var/mob/M in mobs_in_area(master_area))
+ if(M == src)
+ continue
+ if(M && M.client)
+ M.update_music()
+
+ ..()
+
+/mob/living/carbon/complex/gondola/proc/update_media_source()
+ var/area/A = get_area(src)
+ if(!A)
+ return
+ // Check if there's a media source already.
+ if(A.media_source && A.media_source!=src) //if it does, the new media source replaces it. basically, the last media source arrived gets played on top.
+ A.media_source.disconnect_media_source()//you can turn a media source off and on for it to come back on top.
+ A.media_source=src
+ master_area=A
+ return
+
+ // Update Media Source.
+ if(!A.media_source)
+ A.media_source=src
+
+ master_area=A
+
+
+/mob/living/carbon/complex/gondola/proc/disconnect_media_source()
+ var/area/A = get_area(src)
+
+ // Sanity
+ if(!A)
+ master_area=null
+ return
+
+ // Check if there's a media source already.
+ if(A && A.media_source && A.media_source!=src)
+ master_area=null
+ return
+
+ // Update Media Source.
+ A.media_source=null
+
+ // Clients
+ for(var/mob/M in mobs_in_area(A))
+ if(M && M.client)
+ M.update_music()
+ master_area=null
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/complex/inventory.dm b/code/modules/mob/living/carbon/complex/inventory.dm
new file mode 100644
index 00000000000..006c3c95cd6
--- /dev/null
+++ b/code/modules/mob/living/carbon/complex/inventory.dm
@@ -0,0 +1,12 @@
+/mob/living/carbon/complex/equip_to_slot(obj/item/W, slot, redraw_mob = 1)
+ if(!istype(W))
+ return
+
+ if(src.is_holding_item(W))
+ src.u_equip(W)
+
+ W.hud_layerise()
+ W.equipped(src, slot)
+ W.forceMove(src)
+ if(client)
+ client.screen |= W
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/martian/life.dm b/code/modules/mob/living/carbon/complex/life.dm
similarity index 82%
rename from code/modules/mob/living/carbon/martian/life.dm
rename to code/modules/mob/living/carbon/complex/life.dm
index 481b70dbccf..a8bef0a0602 100644
--- a/code/modules/mob/living/carbon/martian/life.dm
+++ b/code/modules/mob/living/carbon/complex/life.dm
@@ -1,16 +1,4 @@
-
-/mob/living/carbon/martian
- var/oxygen_alert = 0
- var/toxins_alert = 0
- var/fire_alert = 0
- var/pressure_alert = 0
- base_insulation = 0.5
- var/temperature_alert = 0
- var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa
- var/co2overloadtime = null
-
-
-/mob/living/carbon/martian/Life()
+/mob/living/carbon/complex/Life()
set invisibility = 0
if(timestopped)
@@ -61,7 +49,7 @@
// ATMOSPHERE, BREATHING, ALL THINGS INVOLVING AIR//
-/mob/living/carbon/martian/proc/breathe() //This proc's used so many different times, you would think it would be under /carbon by now
+/mob/living/carbon/complex/proc/breathe() //This proc's used so many different times, you would think it would be under /carbon by now
if(flags & INVULNERABLE)
return
@@ -93,23 +81,7 @@
var/obj/location_as_object = loc
breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME)
else if(istype(loc, /turf/))
- var/breath_moles = environment.total_moles()/environment.volume*CELL_VOLUME*BREATH_PERCENTAGE
- breath = loc.remove_air(breath_moles)
-
- var/block = 0
- if(head)
- if(istype(head, /obj/item/clothing/head/helmet/space/martian))
- block = 1
-
- if(!block)
- for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
- if(smoke.reagents.total_volume)
- smoke.reagents.reaction(src, INGEST)
- spawn(5)
- if(smoke)
- smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs?
- break // If they breathe in the nasty stuff once, no need to continue checking
-
+ breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE)
else //Still give containing object the chance to interact
if(istype(loc, /obj/))
@@ -120,17 +92,11 @@
if(breath)
loc.assume_air(breath)
-/mob/living/carbon/martian/proc/get_breath_from_internal(volume_needed)
- //As this is a race that can only wear helmets, we'll have a fishbowl helmet that can accept tanks in place of having gas mask setups
- if(head && istype(head, /obj/item/clothing/head/helmet/space/martian))
- var/obj/item/clothing/head/helmet/space/martian/fishbowl = head
- if(fishbowl.tank && istype(fishbowl.tank, /obj/item/weapon/tank))
- var/obj/item/weapon/tank/internals = fishbowl.tank
- return internals.remove_air_volume(volume_needed)
+/mob/living/carbon/complex/proc/get_breath_from_internal(volume_needed)
return null
-/mob/living/carbon/martian/proc/handle_breath(datum/gas_mixture/breath)
+/mob/living/carbon/complex/proc/handle_breath(datum/gas_mixture/breath)
if((status_flags & GODMODE) || (flags & INVULNERABLE))
return
@@ -148,14 +114,16 @@
var/SA_para_min = 0.5
var/SA_sleep_min = 5
var/oxygen_used = 0
- var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
+
+ breath.volume = BREATH_VOLUME
+ breath.update_values()
//Partial pressure of the O2 in our breath
- var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure
+ var/O2_pp = (breath.oxygen / breath.total_moles()) * breath.pressure
// Same, but for the toxins
- var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure
+ var/Toxins_pp = (breath.toxins / breath.total_moles()) * breath.pressure
// And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun)
- var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure
+ var/CO2_pp = (breath.carbon_dioxide / breath.total_moles()) * breath.pressure
if(O2_pp < safe_oxygen_min) // Too little oxygen
if(prob(20))
@@ -206,7 +174,7 @@
if(breath.trace_gases.len) // If there's some other shit in the air lets deal with it here.
for(var/datum/gas/sleeping_agent/SA in breath.trace_gases)
- var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure
+ var/SA_pp = (SA.moles / breath.total_moles()) * breath.pressure
if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit
Paralyse(3) // 3 gives them one second to wake up and run away a bit!
if(SA_pp > SA_sleep_min) // Enough to make us sleep as well
@@ -228,14 +196,12 @@
return 1
-/mob/living/carbon/martian/proc/handle_environment(datum/gas_mixture/environment)
+/mob/living/carbon/complex/proc/handle_environment(datum/gas_mixture/environment)
if(!environment || (flags & INVULNERABLE))
return
- var/spaceproof = 0
- if(head && istype(head, /obj/item/clothing/head/helmet/space/martian))
- spaceproof = 1 //quick and dirt cheap.
var/loc_temp = get_loc_temp(environment)
- var/environment_heat_capacity = environment.heat_capacity()
+ var/spaceproof = is_spaceproof()
+ var/environment_heat_capacity = environment.heat_capacity() / environment.volume * CELL_VOLUME
if(istype(get_turf(src), /turf/space))
var/turf/heat_turf = get_turf(src)
environment_heat_capacity = heat_turf.heat_capacity
@@ -248,12 +214,11 @@
var/thermal_protection = get_thermal_protection(get_heat_protection_flags(loc_temp)) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(thermal_protection < 1)
bodytemperature += min((1 - thermal_protection) * ((loc_temp - get_skin_temperature()) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX)
-
if(stat==DEAD)
bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000)
- //Account for massive pressure differences
+ //Account for massive pressure differences
var/pressure = environment.return_pressure()
var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob.
switch(adjusted_pressure)
@@ -275,35 +240,32 @@
else
pressure_alert = -1
- return
-
-/mob/living/carbon/martian/get_thermal_protection_flags()
- var/thermal_protection_flags = 0
- if(head)
- thermal_protection_flags |= head.body_parts_covered
- return thermal_protection_flags
+/mob/living/carbon/complex/proc/is_spaceproof()
+ if(flags & INVULNERABLE)
+ return TRUE
+ return FALSE
-/mob/living/carbon/martian/calculate_affecting_pressure(var/pressure)
+/mob/living/carbon/complex/get_thermal_protection_flags()
+ return 0
+
+/mob/living/carbon/complex/calculate_affecting_pressure(var/pressure)
..()
return pressure
-/mob/living/carbon/martian/get_cold_protection()
+/mob/living/carbon/complex/get_cold_protection()
if(M_RESIST_COLD in mutations)
return 1 //Fully protected from the cold.
var/thermal_protection = 0.0
- if(head)
- thermal_protection += head.return_thermal_protection()
-
var/max_protection = get_thermal_protection(get_thermal_protection_flags())
return min(thermal_protection,max_protection)
-mob/living/carbon/martian/proc/handle_regular_status_updates()
+/mob/living/carbon/complex/proc/handle_regular_status_updates()
updatehealth()
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
@@ -391,7 +353,7 @@ mob/living/carbon/martian/proc/handle_regular_status_updates()
druggy = max(druggy-1, 0)
return 1
-/mob/living/carbon/martian/proc/handle_chemicals_in_body()
+/mob/living/carbon/complex/proc/handle_chemicals_in_body()
burn_calories(HUNGER_FACTOR,1)
if(reagents)
@@ -415,7 +377,7 @@ mob/living/carbon/martian/proc/handle_regular_status_updates()
return //TODO: DEFERRED
-/mob/living/carbon/martian/proc/handle_regular_hud_updates()
+/mob/living/carbon/complex/proc/handle_regular_hud_updates()
if(!client)
return
@@ -516,7 +478,7 @@ mob/living/carbon/martian/proc/handle_regular_status_updates()
return 1
-/mob/living/carbon/martian/undergoing_hypothermia()
+/mob/living/carbon/complex/undergoing_hypothermia()
if((status_flags & GODMODE) || (flags & INVULNERABLE) || istype(loc, /obj/machinery/atmospherics/unary/cryo_cell))
return NO_HYPOTHERMIA
@@ -529,4 +491,4 @@ mob/living/carbon/martian/proc/handle_regular_status_updates()
return SEVERE_HYPOTHERMIA // unconcious, not shivering
if(-T0C to 260)
return PROFOUND_HYPOTHERMIA // no vital signs
- return NO_HYPOTHERMIA
\ No newline at end of file
+ return NO_HYPOTHERMIA
diff --git a/code/modules/mob/living/carbon/complex/martian/combat.dm b/code/modules/mob/living/carbon/complex/martian/combat.dm
new file mode 100644
index 00000000000..4d5cbbac0cf
--- /dev/null
+++ b/code/modules/mob/living/carbon/complex/martian/combat.dm
@@ -0,0 +1,8 @@
+/mob/living/carbon/complex/martian/getarmor(var/def_zone, var/type)
+
+ var/armorscore = 0
+ if((def_zone == "head") || (def_zone == "eyes") || (def_zone == "mouth"))
+ if(head)
+ armorscore = head.armor[type]
+
+ return armorscore
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/martian/inventory.dm b/code/modules/mob/living/carbon/complex/martian/inventory.dm
similarity index 73%
rename from code/modules/mob/living/carbon/martian/inventory.dm
rename to code/modules/mob/living/carbon/complex/martian/inventory.dm
index fd87e45a1b3..9e2ce4b790a 100644
--- a/code/modules/mob/living/carbon/martian/inventory.dm
+++ b/code/modules/mob/living/carbon/complex/martian/inventory.dm
@@ -1,5 +1,4 @@
-
-/mob/living/carbon/martian/get_item_offset_by_index(index)
+/mob/living/carbon/complex/martian/get_item_offset_by_index(index)
switch(index)
if(1,6)
return list("x"=0, "y"=0)
@@ -10,7 +9,7 @@
return list()
-/mob/living/carbon/martian/get_held_item_ui_location(index)
+/mob/living/carbon/complex/martian/get_held_item_ui_location(index)
if(!is_valid_hand_index(index))
return
@@ -30,7 +29,7 @@
else
return ..()
-/mob/living/carbon/martian/get_index_limb_name(index)
+/mob/living/carbon/complex/martian/get_index_limb_name(index)
if(!index)
index = active_hand
@@ -50,14 +49,14 @@
else
return "tentacle"
-/mob/living/carbon/martian/get_direction_by_index(index)
+/mob/living/carbon/complex/martian/get_direction_by_index(index)
if(index <= 3)
return "right_hand"
else
return "left_hand"
-/mob/living/carbon/martian/GetAccess()
+/mob/living/carbon/complex/martian/GetAccess()
var/list/ACL=list()
for(var/obj/item/I in held_items)
@@ -65,7 +64,7 @@
return ACL
-/mob/living/carbon/martian/get_visible_id()
+/mob/living/carbon/complex/martian/get_visible_id()
var/id = null
for(var/obj/item/I in held_items)
id = I.GetID()
@@ -73,10 +72,10 @@
break
return id
-/mob/living/carbon/martian/can_wield()
+/mob/living/carbon/complex/martian/can_wield()
return 1
-/mob/living/carbon/martian/u_equip(obj/item/W, dropped = 1, var/slot = null)
+/mob/living/carbon/complex/martian/u_equip(obj/item/W, dropped = 1, var/slot = null)
var/success = 0
if(!W)
@@ -102,24 +101,7 @@
return
-/mob/living/carbon/martian/equip_to_slot(obj/item/W, slot, redraw_mob = 1)
- if(!istype(W))
- return
-
- if(src.is_holding_item(W))
- src.u_equip(W)
-
- if(slot == slot_head)
- head = W
- update_inv_head(redraw_mob)
-
- W.hud_layerise()
- W.equipped(src, slot)
- W.forceMove(src)
- if(client)
- client.screen |= W
-
-/mob/living/carbon/martian/abiotic()
+/mob/living/carbon/complex/martian/abiotic()
for(var/obj/item/I in held_items)
if(I.abstract)
continue
@@ -128,7 +110,7 @@
return head
-/mob/living/carbon/martian/show_inv(mob/living/carbon/user)
+/mob/living/carbon/complex/martian/show_inv(mob/living/carbon/user)
user.set_machine(src)
var/dat
@@ -150,8 +132,18 @@
// Return the item currently in the slot ID
-/mob/living/carbon/martian/get_item_by_slot(slot_id)
+/mob/living/carbon/complex/martian/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_head)
return head
return null
+
+/mob/living/carbon/complex/martian/equip_to_slot(obj/item/W, slot, redraw_mob = 1)
+ if(!istype(W))
+ return
+
+ if(slot == slot_head)
+ head = W
+ update_inv_head(redraw_mob)
+
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/complex/martian/life.dm b/code/modules/mob/living/carbon/complex/martian/life.dm
new file mode 100644
index 00000000000..03b12641858
--- /dev/null
+++ b/code/modules/mob/living/carbon/complex/martian/life.dm
@@ -0,0 +1,49 @@
+
+/mob/living/carbon/complex/martian/get_breath_from_internal(volume_needed)
+ //As this is a race that can only wear helmets, we'll have a fishbowl helmet that can accept tanks in place of having gas mask setups
+ if(head && istype(head, /obj/item/clothing/head/helmet/space/martian))
+ var/obj/item/clothing/head/helmet/space/martian/fishbowl = head
+ if(fishbowl.tank && istype(fishbowl.tank, /obj/item/weapon/tank))
+ var/obj/item/weapon/tank/internals = fishbowl.tank
+ return internals.remove_air_volume(volume_needed)
+ return null
+
+/mob/living/carbon/complex/martian/breathe()
+ .=..()
+ var/block = 0
+ if(head)
+ if(istype(head, /obj/item/clothing/head/helmet/space/martian))
+ block = 1
+
+ if(!block)
+ for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
+ if(smoke.reagents.total_volume)
+ smoke.reagents.reaction(src, INGEST)
+ spawn(5)
+ if(smoke)
+ smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs?
+ break // If they breathe in the nasty stuff once, no need to continue checking
+
+/mob/living/carbon/complex/martian/is_spaceproof()
+ if(head && istype(head, /obj/item/clothing/head/helmet/space/martian))
+ return TRUE
+ return ..()
+
+/mob/living/carbon/complex/martian/get_thermal_protection_flags()
+ var/thermal_protection_flags = 0
+ if(head)
+ thermal_protection_flags |= head.body_parts_covered
+ return thermal_protection_flags
+
+/mob/living/carbon/complex/martian/get_cold_protection()
+
+ if(M_RESIST_COLD in mutations)
+ return 1 //Fully protected from the cold.
+
+ var/thermal_protection = 0.0
+
+ if(head)
+ thermal_protection += head.return_thermal_protection()
+
+ var/max_protection = get_thermal_protection(get_thermal_protection_flags())
+ return min(thermal_protection,max_protection)
diff --git a/code/modules/mob/living/carbon/martian/martian.dm b/code/modules/mob/living/carbon/complex/martian/martian.dm
similarity index 75%
rename from code/modules/mob/living/carbon/martian/martian.dm
rename to code/modules/mob/living/carbon/complex/martian/martian.dm
index 759e10b75b7..5bbed85dfd2 100644
--- a/code/modules/mob/living/carbon/martian/martian.dm
+++ b/code/modules/mob/living/carbon/complex/martian/martian.dm
@@ -16,7 +16,7 @@
*/
-/mob/living/carbon/martian
+/mob/living/carbon/complex/martian
name = "martian"
desc = "An alien resembling an overgrown octopus."
voice_name = "martian"
@@ -24,7 +24,7 @@
icon = 'icons/mob/martian.dmi'
icon_state = "martian"
- species_type = /mob/living/carbon/martian
+ species_type = /mob/living/carbon/complex/martian
speak_emote = list("blorbles","burbles")
held_items = list(null, null, null, null, null, null) //6 hands
@@ -46,33 +46,34 @@
//Inventory slots
var/obj/item/head //hat
- var/icon_state_standing = "martian"
- var/icon_state_lying = "lying"
- var/icon_state_dead = "dead"
+ icon_state_standing = "martian"
+ icon_state_lying = "lying"
+ icon_state_dead = "dead"
- var/flag = 0
+ flag = 0
-/mob/living/carbon/martian/New()
- create_reagents(200)
+ base_insulation = 0.5
+
+/mob/living/carbon/complex/martian/New()
name = pick("martian","scootaloo","squid","rootmarian","phoronitian","sepiida","octopodiforme",\
"bolitaenides","belemnites","astrocanthoteuthis","octodad","ocotillo","kalamarian")
add_language(LANGUAGE_MARTIAN)
default_language = all_languages[LANGUAGE_MARTIAN]
..()
-/mob/living/carbon/martian/Destroy()
+/mob/living/carbon/complex/martian/Destroy()
head = null
..()
#ifdef MARTIANS_AMBIDEXTROUS
-/mob/living/carbon/martian/do_after_hand_check(held_item)
+/mob/living/carbon/complex/martian/do_after_hand_check(held_item)
//Normally do_after breaks if you switch hands. With martians, it will only break if the used item is dropped
//This lets them do multiple things at once.
return (held_items.Find(held_item))
#endif
-/mob/living/carbon/martian/eyecheck()
+/mob/living/carbon/complex/martian/eyecheck()
var/obj/item/clothing/head/headwear = src.head
var/protection
if(headwear)
@@ -80,22 +81,22 @@
return Clamp(protection, -2, 2)
-/mob/living/carbon/martian/earprot()
+/mob/living/carbon/complex/martian/earprot()
return 1
-/mob/living/carbon/martian/dexterity_check()
+/mob/living/carbon/complex/martian/dexterity_check()
return TRUE
-/mob/living/carbon/martian/IsAdvancedToolUser()
+/mob/living/carbon/complex/martian/IsAdvancedToolUser()
return TRUE
-/mob/living/carbon/martian/Process_Spaceslipping()
+/mob/living/carbon/complex/martian/Process_Spaceslipping()
return 0 //No slipping
-/mob/living/carbon/martian/has_eyes()
+/mob/living/carbon/complex/martian/has_eyes()
return FALSE
-/mob/living/carbon/martian/updatehealth()
+/mob/living/carbon/complex/martian/updatehealth()
if(status_flags & GODMODE)
health = maxHealth
stat = CONSCIOUS
@@ -103,7 +104,7 @@
health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss()
-/mob/living/carbon/martian/ex_act(severity)
+/mob/living/carbon/complex/martian/ex_act(severity)
if(flags & INVULNERABLE)
return
@@ -127,11 +128,11 @@
updatehealth()
-/mob/living/carbon/martian/Login()
+/mob/living/carbon/complex/martian/Login()
..()
update_hud()
-/mob/living/carbon/martian/Stat()
+/mob/living/carbon/complex/martian/Stat()
..()
if(statpanel("Status"))
stat(null, "Intent: [a_intent]")
diff --git a/code/modules/mob/living/carbon/martian/update_icons.dm b/code/modules/mob/living/carbon/complex/martian/update_icons.dm
similarity index 72%
rename from code/modules/mob/living/carbon/martian/update_icons.dm
rename to code/modules/mob/living/carbon/complex/martian/update_icons.dm
index 2ef52becbf7..608653ea9ca 100644
--- a/code/modules/mob/living/carbon/martian/update_icons.dm
+++ b/code/modules/mob/living/carbon/complex/martian/update_icons.dm
@@ -1,39 +1,20 @@
//MOB ICONS
-/mob/living/carbon/martian/update_icons()
- update_hud()
-
+/mob/living/carbon/complex/martian/update_icons()
+ ..()
overlays.len = 0
for(var/image/I in item_overlays)
overlays += I
-
- lying_prev = lying
-
- if(isDead())
- icon_state = icon_state_dead
- else if(lying)
- icon_state = icon_state_lying
- else
- icon_state = icon_state_standing
//INVENTORY ICONS
#define HAT_LAYER 1
//2-7 are used for hands
#define MAX_LAYERS 7
-/mob/living/carbon/martian
+/mob/living/carbon/complex/martian
var/list/item_overlays[MAX_LAYERS] //6 hands + hat
-/mob/living/carbon/martian/regenerate_icons()
- ..()
-
- for(var/i = 1 to held_items.len)
- update_inv_hand(i)
-
- update_fire()
- update_icons()
-
-/mob/living/carbon/martian/update_inv_hand(index, var/update_icons=1)
+/mob/living/carbon/complex/martian/update_inv_hand(index, var/update_icons=1)
var/obj/item/I = get_held_item_by_index(index)
var/list/offsets = get_item_offset_by_index(index)
var/pixelx = 0
@@ -64,7 +45,7 @@
update_icons()
-/mob/living/carbon/martian/update_inv_head(var/update_icons=1)
+/mob/living/carbon/complex/martian/update_inv_head(var/update_icons=1)
if(!head)
item_overlays[HAT_LAYER] = null
@@ -83,7 +64,7 @@
-/mob/living/carbon/martian/update_hud()
+/mob/living/carbon/complex/martian/update_hud()
if(client)
update_internals()
client.screen |= contents
diff --git a/code/modules/mob/living/carbon/complex/update_icons.dm b/code/modules/mob/living/carbon/complex/update_icons.dm
new file mode 100644
index 00000000000..9b6693a1404
--- /dev/null
+++ b/code/modules/mob/living/carbon/complex/update_icons.dm
@@ -0,0 +1,20 @@
+/mob/living/carbon/complex/update_icons()
+ update_hud()
+
+ lying_prev = lying
+
+ if(isDead())
+ icon_state = icon_state_dead
+ else if(lying)
+ icon_state = icon_state_lying
+ else
+ icon_state = icon_state_standing
+
+/mob/living/carbon/complex/regenerate_icons()
+ ..()
+
+ for(var/i = 1 to held_items.len)
+ update_inv_hand(i)
+
+ update_fire()
+ update_icons()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/combat.dm b/code/modules/mob/living/carbon/human/combat.dm
index 148173f6274..e28d7f2c244 100644
--- a/code/modules/mob/living/carbon/human/combat.dm
+++ b/code/modules/mob/living/carbon/human/combat.dm
@@ -208,6 +208,12 @@
..()
/mob/living/carbon/human/proc/perform_cpr(mob/living/target)
+ if(!get_lungs())
+ to_chat(src, "You have no lungs with which to perform CPR with!")
+ return 0
+ if(src.species && src.species.flags & NO_BREATHE)
+ to_chat(src, "You don't breathe, so you can't help \the [target]!")
+ return 0
if(src.check_body_part_coverage(MOUTH))
to_chat(src, "Remove your [src.get_body_part_coverage(MOUTH)]!")
return 0
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 7e0ed499533..18d42b4323f 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -59,13 +59,13 @@
if (input2 == "Visible")
m_type = VISIBLE
else if (input2 == "Hearable")
- if (src.miming)
+ if (issilent(src))
return
m_type = HEARABLE
else
alert("Unable to use this emote, must be either hearable or visible.")
return
- return custom_emote(m_type, msg)
+ return custom_emote(m_type, input)
if ("me")
if(silent)
@@ -100,7 +100,7 @@
m_type = VISIBLE
if ("choke")
- if(miming)
+ if(issilent(src))
msg = "[src] clutches \his throat desperately!"
m_type = VISIBLE
else
@@ -115,13 +115,13 @@
if (!src.restrained())
msg = "[src] claps."
m_type = HEARABLE
- if(miming)
+ if(issilent(src))
m_type = VISIBLE
if ("flap")
if (!src.restrained())
msg = "[src] flaps \his wings."
m_type = HEARABLE
- if(miming)
+ if(issilent(src))
m_type = VISIBLE
if(src.wear_suit && istype(src.wear_suit,/obj/item/clothing/suit/clownpiece))
var/obj/item/clothing/suit/clownpiece/wings = src.wear_suit
@@ -135,7 +135,7 @@
if (!src.restrained())
msg = "[src] flaps \his wings ANGRILY!"
m_type = HEARABLE
- if(miming)
+ if(issilent(src))
m_type = VISIBLE
if(src.wear_suit && istype(src.wear_suit,/obj/item/clothing/suit/clownpiece))
var/obj/item/clothing/suit/clownpiece/wings = src.wear_suit
@@ -154,7 +154,7 @@
m_type = VISIBLE
if ("chuckle")
- if(miming)
+ if(issilent(src))
msg = "[src] appears to chuckle."
m_type = VISIBLE
else
@@ -181,7 +181,7 @@
m_type = VISIBLE
if ("cough")
- if(miming)
+ if(issilent(src))
msg = "[src] appears to cough!"
m_type = VISIBLE
else
@@ -193,7 +193,7 @@
if (src.gender == FEMALE) //Females have their own coughes
coughSound = "femalecough"
- playsound(get_turf(src), coughSound, 20, 0)
+ playsound(src, coughSound, 20, 0)
last_emote_sound = world.time
msg = "[src] coughs!"
@@ -219,7 +219,7 @@
m_type = VISIBLE
if ("gasp")
- if(miming)
+ if(issilent(src))
msg = "[src] appears to be gasping!"
m_type = VISIBLE
else
@@ -234,7 +234,7 @@
if(M_ELVIS in mutations)
src.emote("fart")
msg = "[src] has left the building..."
- if(!miming && (M_HARDCORE in mutations))
+ if(!issilent(src) && (M_HARDCORE in mutations))
msg = "[src] whispers with \his final breath, 'i told u i was hardcore..'"
else
if(isgolem(src))
@@ -246,7 +246,7 @@
m_type = VISIBLE
if ("giggle")
- if(miming)
+ if(issilent(src))
msg = "[src] giggles silently!"
m_type = VISIBLE
else
@@ -309,7 +309,7 @@
m_type = VISIBLE
if ("cry")
- if(miming)
+ if(issilent(src))
msg = "[src] cries."
m_type = VISIBLE
else
@@ -321,7 +321,7 @@
m_type = HEARABLE
if ("sigh")
- if(miming)
+ if(issilent(src))
msg = "[src] sighs."
m_type = VISIBLE
else
@@ -333,7 +333,7 @@
m_type = HEARABLE
if ("laugh")
- if(miming)
+ if(issilent(src))
msg = "[src] acts out a laugh."
m_type = VISIBLE
else
@@ -347,11 +347,11 @@
if ("mumble")
msg = "[src] mumbles!"
m_type = HEARABLE
- if(miming)
+ if(issilent(src))
m_type = VISIBLE
if ("grumble")
- if(miming)
+ if(issilent(src))
msg = "[src] grumbles!"
m_type = VISIBLE
if (!muzzled)
@@ -362,7 +362,7 @@
m_type = HEARABLE
if ("groan")
- if(miming)
+ if(issilent(src))
msg = "[src] appears to groan!"
m_type = VISIBLE
else
@@ -374,7 +374,7 @@
m_type = HEARABLE
if ("moan")
- if(miming)
+ if(issilent(src))
msg = "[src] appears to moan!"
m_type = VISIBLE
else
@@ -388,7 +388,7 @@
if (!M)
param = null
else
- if(miming)
+ if(issilent(src))
msg = "[src] takes a drag from a cigarette and blows \"[M]\" out in smoke."
m_type = VISIBLE
else
@@ -448,7 +448,7 @@
if ("shiver")
msg = "[src] shivers."
m_type = HEARABLE
- if(miming)
+ if(issilent(src))
m_type = VISIBLE
if ("pale")
@@ -460,7 +460,7 @@
m_type = VISIBLE
if ("sneeze")
- if (miming)
+ if (issilent(src))
msg = "[src] sneezes."
m_type = VISIBLE
else
@@ -474,11 +474,11 @@
if ("sniff")
msg = "[src] sniffs."
m_type = HEARABLE
- if(miming)
+ if(issilent(src))
m_type = VISIBLE
if ("snore")
- if (miming)
+ if (issilent(src))
msg = "[src] sleeps soundly."
m_type = VISIBLE
else
@@ -490,7 +490,7 @@
m_type = HEARABLE
if ("whimper")
- if (miming)
+ if (issilent(src))
msg = "[src] appears hurt."
m_type = VISIBLE
else
@@ -513,14 +513,14 @@
if (!muzzled)
msg = "[src] yawns."
m_type = HEARABLE
- if(miming)
+ if(issilent(src))
m_type = VISIBLE
if ("collapse")
Paralyse(2)
msg = "[src] collapses!"
m_type = HEARABLE
- if(miming)
+ if(issilent(src))
m_type = VISIBLE
if("hug")
@@ -573,7 +573,7 @@
msg = "[src] sadly can't find anybody to give daps to, and daps \himself. Shameful."
if ("scream")
- if (miming)
+ if (issilent(src))
msg = "[src] acts out a scream!"
m_type = VISIBLE
else
@@ -586,7 +586,7 @@
if (src.gender == FEMALE) //Females have their own screams. Trannys be damned.
screamSound = list('sound/misc/femalescream1.ogg', 'sound/misc/femalescream2.ogg', 'sound/misc/femalescream3.ogg', 'sound/misc/femalescream4.ogg', 'sound/misc/femalescream5.ogg')
var/scream = pick(screamSound)//AUUUUHHHHHHHHOOOHOOHOOHOOOOIIIIEEEEEE
- playsound(get_turf(src), scream, 50, 0)
+ playsound(src, scream, 50, 0)
m_type = HEARABLE
last_emote_sound = world.time
else
@@ -602,7 +602,7 @@
if(world.time-lastFart >= 400)
for(var/mob/living/M in view(0))
if(M != src && M.loc == src.loc)
- if(!miming)
+ if(!issilent(src))
visible_message("[src] farts in [M]'s face!")
else
visible_message("[src] silently farts in [M]'s face!")
@@ -632,17 +632,17 @@
"farts [pick("lightly", "tenderly", "softly", "with care")]",
)
- if(miming)
+ if(issilent(src))
farts = list("silently farts.", "acts out a fart.", "lets out a silent fart.")
var/fart = pick(farts)
- if(!miming)
+ if(!issilent(src))
msg = "[src] [fart]."
if(mind && mind.assigned_role == "Clown")
- playsound(get_turf(src), pick('sound/items/bikehorn.ogg','sound/items/AirHorn.ogg'), 50, 1)
+ playsound(src, pick('sound/items/bikehorn.ogg','sound/items/AirHorn.ogg'), 50, 1)
else
- playsound(get_turf(src), 'sound/misc/fart.ogg', 50, 1)
+ playsound(src, 'sound/misc/fart.ogg', 50, 1)
else
msg = "[src] [fart]"
//Mimes can't fart.
@@ -663,7 +663,7 @@
// Process toxic farts first.
if(M_TOXIC_FARTS in mutations)
msg=""
- playsound(get_turf(src), 'sound/effects/superfart.ogg', 50, 1)
+ playsound(src, 'sound/effects/superfart.ogg', 50, 1)
if(wearing_suit)
if(!wearing_mask)
to_chat(src, "You gas yourself!")
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index a8bf0b38d40..58a74cb08e9 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -42,15 +42,13 @@
var/msg = "*---------*\nThis is "
- if( slot_w_uniform in obscured && skipface )
+ if((slot_w_uniform in obscured) && skipface)
t_He = "They"
t_his = "their"
t_him = "them"
t_has = "have"
t_is = "are"
else
- if(icon)
- msg += "[bicon(src)] " //note, should we ever go back to runtime-generated icons (please don't), you will need to change this to [bicon(icon)] to prevent crashes.
switch(gender)
if(MALE)
t_He = "He"
@@ -239,7 +237,7 @@
msg += "[t_He] [t_has] a vacant, braindead stare...\n"
// Religions
- if (user.mind && user.mind.faith && user.mind.faith.isReligiousLeader(user) && mind)
+ if (ismob(user) && user.mind && user.mind.faith && user.mind.faith.isReligiousLeader(user) && mind)
if (src.mind.faith == user.mind.faith)
msg += "You recognise [t_him] as a follower of [user.mind.faith.name]. "
@@ -430,7 +428,7 @@
if(butchery)
msg += "[butchery]\n"
- if(user.hasHUD(HUD_SECURITY))
+ if(istype(user) && user.hasHUD(HUD_SECURITY))
var/perpname = get_identification_name(get_face_name())
var/criminal = "None"
@@ -444,7 +442,7 @@
msg += "\[Add comment\]\n"
msg += {"[wpermit(src) ? "Has weapon permit.\n" : ""]"}
- if(user.hasHUD(HUD_MEDICAL))
+ if(istype(user) && user.hasHUD(HUD_MEDICAL))
var/perpname = get_identification_name(get_face_name())
var/medical = "None"
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index c2995a34317..b2e99bf7b3d 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -7,7 +7,7 @@
icon_state = "body_m_s"
can_butcher = 1
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/human
- var/list/hud_list[9]
+ var/list/hud_list = list()
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.
@@ -95,6 +95,10 @@
update_body()
+/mob/living/carbon/human/mushroom/New(var/new_loc, delay_ready_dna = 0)
+ h_style = "Bald"
+ ..(new_loc, "Mushroom")
+
/mob/living/carbon/human/generate_static_overlay()
if(!istype(static_overlays,/list))
static_overlays = list()
@@ -112,11 +116,6 @@
static_overlays["letter"] = static_overlay
/mob/living/carbon/human/New(var/new_loc, var/new_species_name = null, var/delay_ready_dna=0)
- if(!hair_styles_list.len)
- buildHairLists()
- if(!all_species.len)
- buildSpeciesLists()
-
if(new_species_name)
s_tone = random_skin_tone(new_species_name)
multicolor_skin_r = rand(0,255) //Only used when the human has a species datum with the MULTICOLOR anatomical flag
@@ -153,7 +152,7 @@
obj_overlays[FIRE_LAYER] = getFromPool(/obj/abstract/Overlays/fire_layer)
obj_overlays[MUTANTRACE_LAYER] = getFromPool(/obj/abstract/Overlays/mutantrace_layer)
obj_overlays[MUTATIONS_LAYER] = getFromPool(/obj/abstract/Overlays/mutations_layer)
- obj_overlays[DAMAGE_LAYER] = getFromPool(/obj/abstract/Overlays/damage_layer)
+ obj_overlays[DAMAGE_LAYER] = getFromPool(/obj/abstract/Overlays/damage_layer)
obj_overlays[UNIFORM_LAYER] = getFromPool(/obj/abstract/Overlays/uniform_layer)
obj_overlays[ID_LAYER] = getFromPool(/obj/abstract/Overlays/id_layer)
obj_overlays[SHOES_LAYER] = getFromPool(/obj/abstract/Overlays/shoes_layer)
@@ -255,9 +254,6 @@
stat("Spacepod Charge", "[istype(S.battery) ? "[S.battery.charge] / [S.battery.maxcharge]" : "No cell detected"]")
stat("Spacepod Integrity", "[!S.health ? "0" : "[(S.health / initial(S.health)) * 100]"]%")
-/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M as mob)
- M.unarmed_attack_mob(src)
-
/mob/living/carbon/human/proc/is_loyalty_implanted(mob/living/carbon/human/M)
for(var/L in M.contents)
if(istype(L, /obj/item/weapon/implant/loyalty))
@@ -346,9 +342,9 @@
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/proc/get_visible_name()
- if( wear_mask && (is_slot_hidden(wear_mask.body_parts_covered,HIDEFACE))) //Wearing a mask which hides our face, use id-name if possible
+ if( wear_mask && wear_mask.is_hidden_identity()) //Wearing a mask which hides our face, use id-name if possible
return get_id_name("Unknown")
- if( head && (is_slot_hidden(head.body_parts_covered,HIDEFACE)))
+ if( head && head.is_hidden_identity())
return get_id_name("Unknown") //Likewise for hats
var/datum/role/vampire/V = isvampire(src)
if(V && (VAMP_SHADOW in V.powers) && V.ismenacing)
@@ -361,7 +357,7 @@
//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable
/mob/living/carbon/human/proc/get_face_name()
var/datum/organ/external/head/head_organ = get_organ(LIMB_HEAD)
- if((wear_mask && (is_slot_hidden(wear_mask.body_parts_covered,HIDEFACE))) || ( head && (is_slot_hidden(head.body_parts_covered,HIDEFACE))) || !head_organ || head_organ.disfigured || (head_organ.status & ORGAN_DESTROYED) || !real_name || (M_HUSK in mutations) ) //Wearing a mask which hides our face, use id-name if possible
+ if((wear_mask && wear_mask.is_hidden_identity() ) || ( head && head.is_hidden_identity() ) || !head_organ || head_organ.disfigured || (head_organ.status & ORGAN_DESTROYED) || !real_name || (M_HUSK in mutations) ) //Wearing a mask which hides our face, use id-name if possible
return "Unknown"
return real_name
@@ -722,7 +718,7 @@
src.visible_message("[src] throws up!","You throw up!")
spawn_vomit_on_floor = 1
- playsound(get_turf(loc), 'sound/effects/splat.ogg', 50, 1)
+ playsound(loc, 'sound/effects/splat.ogg', 50, 1)
if(spawn_vomit_on_floor)
if(istype(location, /turf/simulated))
@@ -1123,8 +1119,9 @@
if(src.species.abilities)
src.verbs -= species.abilities
if(species.spells)
- for(var/spell in species.spells)
- remove_spell(spell)
+ for(var/spell/spell in spell_list)
+ if(spell.type in species.spells)
+ remove_spell(spell)
for(var/L in species.known_languages)
remove_language(L)
species.clear_organs(src)
@@ -1148,6 +1145,18 @@
add_spell(spell, "racial_spell_ready", /obj/abstract/screen/movable/spell_master/racial)
if(force_organs || !src.organs || !src.organs.len)
src.species.create_organs(src)
+ else
+ for(var/datum/organ/external/current_organ in organs)
+ if(species.anatomy_flags & NO_BLOOD)
+ current_organ.status &= ~ORGAN_BLEEDING
+ if(species.anatomy_flags & NO_BONES)
+ current_organ.status &= ~ORGAN_BROKEN
+ current_organ.status &= ~ORGAN_SPLINTED
+ if(species.anatomy_flags & NO_STRUCTURE && current_organ.status & ORGAN_DESTROYED)
+ current_organ.status |= ORGAN_ATTACHABLE
+ current_organ.amputated = 1
+ current_organ.setAmputatedTree()
+ current_organ.open = 0
var/datum/organ/internal/eyes/E = src.internal_organs_by_name["eyes"]
if(E)
src.see_in_dark = E.see_in_dark //species.darksight
@@ -1162,6 +1171,8 @@
src.dna.species = new_species_name
src.species.handle_post_spawn(src)
src.update_icons()
+ if(species.species_intro)
+ to_chat(src, "[species.species_intro]")
return 1
/mob/living/carbon/human/proc/bloody_doodle()
@@ -1402,6 +1413,13 @@
Paralyse(paralyse_duration)
Jitter(jitter_duration)
+/mob/living/carbon/human/proc/asthma_attack()
+ if(disabilities & ASTHMA && !(M_NO_BREATH in mutations) && !(has_reagent_in_blood(ALBUTEROL)))
+ forcesay("-")
+ visible_message("\The [src] begins wheezing and grabbing at their throat!", \
+ "You begin wheezing and grabbing at your throat!")
+ src.reagents.add_reagent(MUCUS, 10)
+
// Makes all robotic limbs organic.
/mob/living/carbon/human/proc/make_robot_limbs_organic()
for(var/datum/organ/external/O in src.organs)
@@ -1420,6 +1438,22 @@
make_robot_limbs_organic()
make_robot_internals_organic()
+// Makes all limbs robotic.
+/mob/living/carbon/human/proc/make_organic_limbs_robotic()
+ for(var/datum/organ/external/O in organs)
+ O.robotize()
+ update_icons()
+
+// Makes all internal organs robotic.
+/mob/living/carbon/human/proc/make_organic_internals_robotic()
+ for(var/datum/organ/internal/O in organs)
+ O.robotic = TRUE
+
+// Makes all organs, internal and external, robotic.
+/mob/living/carbon/human/proc/make_all_organic_parts_robotic()
+ make_organic_limbs_robotic()
+ make_organic_internals_robotic()
+
/mob/living/carbon/human/proc/set_attack_type(new_type = NORMAL_ATTACK)
kick_icon.icon_state = "act_kick"
bite_icon.icon_state = "act_bite"
@@ -1536,6 +1570,9 @@
plane = LYING_HUMAN_PLANE
else
plane = HUMAN_PLANE
+ var/area/this_area = get_area(src)
+ if(istype(this_area) && this_area.project_shadows)
+ update_shadow()
/mob/living/carbon/human/set_hand_amount(new_amount) //Humans need hand organs to use the new hands. This proc will give them some
if(new_amount > held_items.len)
@@ -1735,10 +1772,10 @@ mob/living/carbon/human/remove_internal_organ(var/mob/living/user, var/datum/org
/mob/living/carbon/human/can_show_flavor_text()
// Wearing a mask...
- if(wear_mask && is_slot_hidden(wear_mask.body_parts_covered, HIDEFACE))
+ if(wear_mask && wear_mask.is_hidden_identity())
return FALSE
// Or having a headpiece that protects your face...
- if(head && is_slot_hidden(head.body_parts_covered, HIDEFACE))
+ if(head && head.is_hidden_identity())
return FALSE
// Or lacking a head, or being disfigured...
var/datum/organ/external/head/limb_head = get_organ(LIMB_HEAD)
@@ -1751,6 +1788,7 @@ mob/living/carbon/human/remove_internal_organ(var/mob/living/user, var/datum/org
return TRUE
/mob/living/carbon/human/proc/make_zombie(mob/master, var/retain_mind = TRUE)
+ ghostize()
var/mob/living/simple_animal/hostile/necro/zombie/turned/T = new(get_turf(src), master, (retain_mind ? mind : null))
T.get_clothes(src, T)
T.name = real_name
@@ -1773,5 +1811,8 @@ mob/living/carbon/human/remove_internal_organ(var/mob/living/user, var/datum/org
if(HUD_MEDICAL)
return istype(glasses, /obj/item/clothing/glasses/hud/health)
if(HUD_SECURITY)
+ if(istype(glasses, /obj/item/clothing/glasses/sunglasses/sechud/syndishades))
+ var/obj/item/clothing/glasses/sunglasses/sechud/syndishades/S = glasses
+ return S.full_access
return is_type_in_list(glasses, list(/obj/item/clothing/glasses/hud/security, /obj/item/clothing/glasses/sunglasses/sechud))
return FALSE
diff --git a/code/modules/mob/living/carbon/human/human_attackanimal.dm b/code/modules/mob/living/carbon/human/human_attackanimal.dm
new file mode 100644
index 00000000000..2f80db722f5
--- /dev/null
+++ b/code/modules/mob/living/carbon/human/human_attackanimal.dm
@@ -0,0 +1,5 @@
+/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
+ if(check_shields(0, M.name))
+ return 0
+
+ M.unarmed_attack_mob(src)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm
index ff745ca13de..30a4805f91c 100644
--- a/code/modules/mob/living/carbon/human/human_attackhand.dm
+++ b/code/modules/mob/living/carbon/human/human_attackhand.dm
@@ -1,5 +1,8 @@
//BITES
/mob/living/carbon/human/bite_act(mob/living/carbon/human/M as mob)
+
+ var/dam_check = !(istype(loc, /turf) && istype(loc.loc, /area/start)) // 0 or 1
+
if(M == src)
return //Can't bite yourself
@@ -26,11 +29,11 @@
//end vampire code
var/armor_modifier = 30
- var/damage = rand(1, 5)
+ var/damage = rand(1, 5)*dam_check
if(M.organ_has_mutation(LIMB_HEAD, M_BEAK)) //Beaks = stronger bites
armor_modifier = 5
- damage += 4
+ damage += 4*dam_check
var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting))
@@ -41,7 +44,8 @@
if(2) //Full block
damage = 0
- if(!damage)
+ damage = run_armor_absorb(affecting, "melee", damage)
+ if(!damage && dam_check)
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("\The [M] has attempted to bite \the [src]!")
return 0
@@ -67,6 +71,9 @@
//KICKS
/mob/living/carbon/human/kick_act(mob/living/carbon/human/M)
+
+ var/dam_check = !(istype(loc, /turf) && istype(loc.loc, /area/start)) // 0 or 1
+
//Pick a random usable foot to perform the kick with
var/datum/organ/external/foot_organ = pick_usable_organ(LIMB_RIGHT_FOOT, LIMB_LEFT_FOOT)
@@ -84,19 +91,19 @@
stomping = 1
var/armor_modifier = 1
- var/damage = rand(0,7)
+ var/damage = rand(0,7)*dam_check
var/knockout = damage
if(stomping) //Stomps = more damage and armor bypassing
armor_modifier = 0.5
- damage += rand(0,7)
+ damage += rand(0,7)*dam_check
attack_verb = "stomps on"
else if(M.reagents && M.reagents.has_reagent(GYRO))
- damage += rand(0,4)
+ damage += rand(0,4)*dam_check
knockout += rand(0,3)
attack_verb = "roundhouse kicks"
- if(!damage)
+ if(!damage && dam_check) // So that people still think they are biting each other
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("\The [M] attempts to kick \the [src]!")
return 0
@@ -128,7 +135,7 @@
damage = max(0, damage - rand(1,5))
if(2) //Full block
damage = max(0, damage - rand(1,10))
-
+ damage = run_armor_absorb(affecting, "melee", damage)
if(knockout >= 7 && prob(33))
visible_message("[M] weakens [src]!")
apply_effect(3, WEAKEN, armorblock)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 249759d951e..1f899c383a4 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -49,7 +49,6 @@ emp_act
/mob/living/carbon/human/getarmorabsorb(var/def_zone, var/type)
var/armorval = 0
var/organnum = 0
-
if(def_zone)
if(isorgan(def_zone))
return checkarmorabsorb(def_zone, type)
@@ -88,7 +87,10 @@ emp_act
if(bp && istype(bp ,/obj/item/clothing))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & def_zone.body_part)
- protection += C.armor[type]
+ protection += C.get_armor(type)
+ for(var/obj/item/clothing/accessory/A in C.accessories)
+ if(A.body_parts_covered & def_zone.body_part)
+ protection += A.get_armor(type)
if(istype(loc, /obj/mecha))
var/obj/mecha/M = loc
protection += M.rad_protection
@@ -103,7 +105,10 @@ emp_act
if(istype(bp, /obj/item/clothing))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & def_zone.body_part)
- protection += C.armor_absorb[type]
+ protection += C.get_armor_absorb(type)
+ for(var/obj/item/clothing/accessory/A in C.accessories)
+ if(A.body_parts_covered & def_zone.body_part)
+ protection += A.get_armor_absorb(type)
return protection
@@ -242,29 +247,31 @@ emp_act
knock_teeth = 1
var/armor = run_armor_check(affecting, "melee", quiet = 1)
+ var/final_force = run_armor_absorb(affecting, "melee", I.force)
if(knock_teeth) //You can't actually hit people in the mouth - this checks if the user IS targetting mouth, and if he didn't miss!
- if((!armor) && (I.force >= 8 || I.w_class >= W_CLASS_SMALL) && (I.is_sharp() < 1))//Minimum force=8, minimum w_class=2. Sharp items can't knock out teeth. Armor prevents this completely!
- var/chance = min(I.force * I.w_class, 40) //an item with w_class = W_CLASS_MEDIUM and force of 10 has a 30% chance of knocking a few teeth out. Chance is capped at 40%
+ if((!armor) && (final_force >= 8 || I.w_class >= W_CLASS_SMALL) && (I.is_sharp() < 1))//Minimum force=8, minimum w_class=2. Sharp items can't knock out teeth. Armor prevents this completely!
+ var/chance = min(final_force * I.w_class, 40) //an item with w_class = W_CLASS_MEDIUM and force of 10 has a 30% chance of knocking a few teeth out. Chance is capped at 40%
if(prob(chance))
knock_out_teeth(user)
var/bloody = FALSE
- if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (I.force * 2)))
- I.add_blood(src) //Make the weapon bloody, not the person.
- if(prob(33))
- bloody = TRUE
- var/turf/location = loc
- if(istype(location, /turf/simulated))
- location.add_blood(src)
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood
- H.bloody_body(src)
- H.bloody_hands(src)
+ if(final_force && ((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (final_force * 2)))
+ if(!(src.species.anatomy_flags & NO_BLOOD))
+ I.add_blood(src) //Make the weapon bloody, not the person.
+ if(prob(33))
+ bloody = TRUE
+ var/turf/location = loc
+ if(istype(location, /turf/simulated))
+ location.add_blood(src)
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(get_dist(H, src) <= 1) //people with TK won't get smeared with blood
+ H.bloody_body(src)
+ H.bloody_hands(src)
switch(hit_area)
if(LIMB_HEAD)//Harder to score a stun but if you do it lasts a bit longer
- if(prob(I.force))
+ if(prob(final_force))
if(apply_effect(20, PARALYZE, armor))
visible_message("[src] has been knocked unconscious!")
// if(src != user && I.damtype == BRUTE && isrev(src))
@@ -283,7 +290,7 @@ emp_act
update_inv_glasses(0)
if(LIMB_CHEST)//Easier to score a stun but lasts less time
- if(prob((I.force + 10)))
+ if(prob((final_force + 10)))
apply_effect(5, WEAKEN, armor)
visible_message("[src] has been knocked down!")
@@ -474,5 +481,6 @@ emp_act
show_message("The blob attacks you!")
var/dam_zone = pick(organs_by_name)
var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone))
- apply_damage(rand(30,40), BRUTE, affecting, run_armor_check(affecting, "melee"))
+
+ apply_damage(run_armor_absorb(affecting, "melee", rand(30,40)), BRUTE, affecting, run_armor_check(affecting, "melee"))
return
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 412bfa84987..14dd5c987b4 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -94,3 +94,4 @@
var/show_client_status_on_examine = TRUE //If false, don't display catatonic/braindead messages to non-admins
var/become_zombie_after_death = FALSE
+ var/times_cloned = 0 //How many times this person has been cloned
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 560373e32cc..64cb13929b2 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -10,7 +10,7 @@
if(flying)
return // Calculate none of the following because we're technically on a vehicle
if(reagents.has_any_reagents(list(HYPERZINE,COCAINE)))
- return // Hyperzine ignores slowdown
+ return // Hyperzine ignores base slowdown
if(istype(loc, /turf/space))
return // Space ignores slowdown
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 57c94cadb5b..41365b8c844 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -352,7 +352,7 @@
W.dropped(src)
if(W)
W.reset_plane_and_layer()
- update_action_buttons()
+ update_action_buttons_icon()
return 1
//This is a SAFE proc. Use this instead of equip_to_slot()!
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index b5c27e2195b..b07c505ee91 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -145,7 +145,7 @@ var/global/list/organ_damage_overlays = list(
location_as_object.handle_internal_lifeform(src, 0)
last_processed = "Interacted with our container"
if(check_mutations)
- testing("Updating [src.real_name]'s mutations: "+english_list(mutations))
+// testing("Updating [src.real_name]'s mutations: "+english_list(mutations))
domutcheck(src,null,MUTCHK_FORCED)
update_mutations()
check_mutations = 0
diff --git a/code/modules/mob/living/carbon/human/life/handle_breath.dm b/code/modules/mob/living/carbon/human/life/handle_breath.dm
index b34e9e48bda..230505a22ff 100644
--- a/code/modules/mob/living/carbon/human/life/handle_breath.dm
+++ b/code/modules/mob/living/carbon/human/life/handle_breath.dm
@@ -49,16 +49,13 @@
var/obj/location_as_object = loc
breath = location_as_object.handle_internal_lifeform(src, BREATH_MOLES)
else if(isturf(loc))
- var/breath_moles = 0
/*if(environment.return_pressure() > ONE_ATMOSPHERE)
//Loads of air around (pressure effect will be handled elsewhere), so lets just take a enough to fill our lungs at normal atmos pressure (using n = Pv/RT)
breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature)
else
*/
//Not enough air around, take a percentage of what's there to model this properly
- breath_moles = (environment.total_moles() / environment.volume * CELL_VOLUME) * BREATH_PERCENTAGE
-
- breath = loc.remove_air(breath_moles)
+ breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE)
if(!breath || breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5)
if(prob(15)) // 15% chance for lung damage if air intake is less of a fifth, or more than five times the threshold
@@ -112,9 +109,13 @@
adjust_fire_stacks(0.5)
IgniteMob()
else
- if(fire_stacks > 0)
- var/obj/item/clothing/suit/space/plasmaman/PS=wear_suit
- PS.Extinguish(src)
+ var/obj/item/clothing/suit/space/plasmaman/PS=wear_suit
+ if(istype(PS))
+ if(fire_stacks > 0)
+ PS.Extinguish(src)
+ else
+ PS.regulate_temp_of_wearer(src)
+
if(breath)
loc.assume_air(breath)
diff --git a/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm b/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm
index fe5b02ca04d..ec940850c1c 100644
--- a/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm
+++ b/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm
@@ -34,7 +34,7 @@
var/light_amount = 0 //How much light there is in the place, affects receiving nutrition and healing
if(isturf(loc)) //Else, there's considered to be no light
var/turf/T = loc
- light_amount = T.get_lumcount() * 10
+ light_amount = (T.get_lumcount() * 10) - 5
nutrition += light_amount
pain_shock_stage -= light_amount
@@ -48,6 +48,23 @@
adjustOxyLoss(-(light_amount))
//TODO: heal wounds, heal broken limbs.
+ if(species.flags & REQUIRE_DARK)
+ var/light_amount = 0
+ if(isturf(loc))
+ var/turf/T = loc
+ light_amount = T.get_lumcount() * 10
+
+ nutrition -= -3+light_amount
+ pain_shock_stage += -3+light_amount
+
+ if(species.flags & IS_PLANT)
+ if(nutrition > 500)
+ nutrition = 500
+ if(!reagents.has_reagent(HYPERZINE))
+ adjustBruteLoss(-10+light_amount)
+ adjustToxLoss(-10+light_amount)
+ adjustOxyLoss(-10+light_amount)
+
if(dna && dna.mutantrace == "shadow")
var/light_amount = 0
if(isturf(loc))
diff --git a/code/modules/mob/living/carbon/human/life/handle_disabilities.dm b/code/modules/mob/living/carbon/human/life/handle_disabilities.dm
index 8f7360b5407..4007c66c202 100644
--- a/code/modules/mob/living/carbon/human/life/handle_disabilities.dm
+++ b/code/modules/mob/living/carbon/human/life/handle_disabilities.dm
@@ -1,6 +1,10 @@
//Refer to life.dm for caller
/mob/living/carbon/human/proc/handle_disabilities()
+ if(disabilities & ASTHMA)
+ if(prob(0.2))
+ asthma_attack()
+
if(disabilities & EPILEPSY)
if((prob(1)) && (paralysis < 1))
seizure(10, 1000)
@@ -101,4 +105,4 @@
if(10 <= rn && rn <= 12)
if(canmove)
to_chat(src, "Your legs won't respond properly, you fall down.")
- Knockdown(3)
+ Knockdown(3)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/life/handle_mutations_and_radiation.dm b/code/modules/mob/living/carbon/human/life/handle_mutations_and_radiation.dm
index 9f01b421b3a..ae6b2caf4a0 100644
--- a/code/modules/mob/living/carbon/human/life/handle_mutations_and_radiation.dm
+++ b/code/modules/mob/living/carbon/human/life/handle_mutations_and_radiation.dm
@@ -207,7 +207,7 @@
if(prob(10*minor_rad_multiplier))
//Blindness
var/datum/organ/internal/eyes/E = internal_organs_by_name["eyes"]
- if(!E.robotic && !(sdisabilities & BLIND || disabilities & NEARSIGHTED))
+ if(E && !E.robotic && !(sdisabilities & BLIND || disabilities & NEARSIGHTED))
to_chat(src, "[pick("Your eyesight starts to fade!","Your eyes go cloudy!","Are you going blind?")]")
E.take_damage(2.5, TRUE)
eye_blurry = min(eye_blurry+1.5,50)
@@ -303,3 +303,22 @@
Knockdown(3)
regenerate_icons()
visible_message("\The [src]'s form loses bulk as they collapse to the ground.")
+
+/mob/living/proc/get_rad_stage()
+ switch(rad_tick)
+ if(0)
+ return "N/A"
+ if(1 to RADDOSELIGHT)
+ return "Early"
+ if(RADDOSELIGHT to RADDOSEMINOR)
+ return "Light"
+ if(RADDOSEMINOR to RADDOSEADVANCED)
+ return "Minor"
+ if(RADDOSEADVANCED to RADDOSECRITICAL)
+ return "Advanced"
+ if(RADDOSECRITICAL to RADDOSEDEADLY)
+ return "Critical"
+ if(RADDOSEDEADLY to RADDOSEFATAL)
+ return "Deadly"
+ if(RADDOSEFATAL to INFINITY)
+ return "Fatal"
diff --git a/code/modules/mob/living/carbon/human/life/handle_regular_hud_updates.dm b/code/modules/mob/living/carbon/human/life/handle_regular_hud_updates.dm
index 2699176ce49..f5eb77c1aa0 100644
--- a/code/modules/mob/living/carbon/human/life/handle_regular_hud_updates.dm
+++ b/code/modules/mob/living/carbon/human/life/handle_regular_hud_updates.dm
@@ -8,7 +8,7 @@
regular_hud_updates()
- update_action_buttons()
+ update_action_buttons_icon()
if(stat == UNCONSCIOUS && health <= config.health_threshold_crit)
var/severity = 0
@@ -288,11 +288,22 @@
clear_fullscreen("high")
var/masked = 0
- if(istype(head, /obj/item/clothing/head/welding) || istype(head, /obj/item/clothing/head/helmet/space/unathi))
- var/obj/item/clothing/head/welding/O = head
- if(!O.up && tinted_weldhelh)
- overlay_fullscreen("tint", /obj/abstract/screen/fullscreen/impaired, 2)
- masked = 1
+
+ if(head)
+ if(istype(head, /obj/item/clothing/head/welding) || istype(head, /obj/item/clothing/head/helmet/space/unathi) || (/datum/action/item_action/toggle_helmet_mask in head.actions_types))
+ var/enable_mask = TRUE
+
+ var/datum/action/item_action/toggle_helmet_mask/action = locate(/datum/action/item_action/toggle_helmet_mask) in head.actions
+
+ if(action)
+ enable_mask = !action.up
+ else
+ var/obj/item/clothing/head/welding/O = head
+ enable_mask = !O.up
+
+ if(enable_mask && tinted_weldhelh)
+ overlay_fullscreen("tint", /obj/abstract/screen/fullscreen/impaired, 2)
+ masked = 1
if(!masked && istype(glasses, /obj/item/clothing/glasses/welding) && !istype(glasses, /obj/item/clothing/glasses/welding/superior))
var/obj/item/clothing/glasses/welding/O = glasses
diff --git a/code/modules/mob/living/carbon/human/life/handle_stomach.dm b/code/modules/mob/living/carbon/human/life/handle_stomach.dm
index 1383f81aabd..45f6d80fa9e 100644
--- a/code/modules/mob/living/carbon/human/life/handle_stomach.dm
+++ b/code/modules/mob/living/carbon/human/life/handle_stomach.dm
@@ -16,10 +16,10 @@
to_chat(src, "Your stomach starts rumbling as /the [M] is shifted around.")
if(1)
visible_message(src, "\The [src] lets out a small toot.", "You let out a small toot, your stomach gurgling.")
- playsound(get_turf(src), 'sound/misc/fart.ogg', 50, 1)
+ playsound(src, 'sound/misc/fart.ogg', 50, 1)
if(2)
visible_message(src, "\The [src] lets out an extremely long fart.", "You let out an extremely long and loud fart, to the point that it starts hurting your ass.")
- playsound(get_turf(src), 'sound/effects/superfart.ogg', 50, 1)
+ playsound(src, 'sound/effects/superfart.ogg', 50, 1)
if(!(status_flags & GODMODE))
adjustBruteLoss(5)
if(3 to INFINITY)
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index f1ff765b801..0c5537eb10a 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -80,7 +80,7 @@
/mob/living/carbon/human/IsVocal()
if(mind)
- return !miming
+ return !(issilent(src))
return 1
/mob/living/carbon/human/proc/SetSpecialVoice(var/new_voice)
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index cf4fbde6b29..3a0749dae63 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -172,7 +172,6 @@ var/global/list/damage_icon_parts = list()
O.overlays.len = 0
O.overlays += standing_image
obj_to_plane_overlay(O,DAMAGE_LAYER)
- //overlays_standing[DAMAGE_LAYER] = standing_image
@@ -325,8 +324,8 @@ var/global/list/damage_icon_parts = list()
if(facial_hair_style.do_colouration)
facial_s.Blend(rgb(r_facial, g_facial, b_facial), ICON_ADD)
face_standing.Blend(facial_s, ICON_OVERLAY)
- else
- warning("Invalid f_style for [species.name]: [f_style]")
+// else
+ //warning("Invalid f_style for [species.name]: [f_style]")
if(h_style && !check_hidden_head_flags(HIDEHEADHAIR))
var/datum/sprite_accessory/hair_style = hair_styles_list[h_style]
@@ -338,8 +337,8 @@ var/global/list/damage_icon_parts = list()
hair_s.Blend(icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_acc"), ICON_OVERLAY)
face_standing.Blend(hair_s, ICON_OVERLAY)
- else
- warning("Invalid h_style for [species.name]: [h_style]")
+// else
+ //warning("Invalid h_style for [species.name]: [h_style]")
if(body_alphas.len)
var/lowest_alpha = get_lowest_body_alpha()
@@ -914,7 +913,7 @@ var/global/list/damage_icon_parts = list()
/mob/living/carbon/human/update_inv_wear_suit(var/update_icons=1)
overlays -= obj_overlays[SUIT_LAYER]
- if( wear_suit && istype(wear_suit, /obj/item/clothing/suit) && wear_suit.is_visible()) //TODO check this
+ if( wear_suit && wear_suit.is_visible()) //TODO check this
wear_suit.screen_loc = ui_oclothing //TODO
var/obj/abstract/Overlays/O = obj_overlays[SUIT_LAYER]
O.overlays.len = 0
diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm
index c7a05b85f6a..ce156f22673 100644
--- a/code/modules/mob/living/carbon/monkey/life.dm
+++ b/code/modules/mob/living/carbon/monkey/life.dm
@@ -267,8 +267,7 @@
var/obj/location_as_object = loc
breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME)
else if(istype(loc, /turf/))
- var/breath_moles = environment.total_moles()/environment.volume*CELL_VOLUME*BREATH_PERCENTAGE
- breath = loc.remove_air(breath_moles)
+ breath = environment.remove_volume(CELL_VOLUME * BREATH_PERCENTAGE)
// Handle chem smoke effect -- Doohl
var/block = 0
@@ -458,7 +457,7 @@
if(hat && istype(hat, /obj/item/clothing/head/helmet/space) && uniform && istype(uniform, /obj/item/clothing/monkeyclothes/space))
spaceproof = 1 //quick and dirt cheap. no need for the Life() of monkeys to become as complicated as the Life() of humans. man that's deep.
var/loc_temp = get_loc_temp(environment)
- var/environment_heat_capacity = environment.heat_capacity()
+ var/environment_heat_capacity = environment.heat_capacity() / environment.volume * CELL_VOLUME
if(istype(get_turf(src), /turf/space))
var/turf/heat_turf = get_turf(src)
environment_heat_capacity = heat_turf.heat_capacity
@@ -520,7 +519,7 @@
if(isturf(loc)) //else, there's considered to be no light
var/turf/T = loc
if(T.dynamic_lighting)
- light_amount = T.get_lumcount() * 10
+ light_amount = (T.get_lumcount() * 10) - 5
else
light_amount = 5
nutrition += light_amount
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index 10d0cbf7407..0bca39019df 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -443,4 +443,74 @@
/mob/living/carbon/monkey/can_wield(obj/item/I)
//used for making wield exceptions for 2 handed items
if (istype(I,/obj/item/device/instrument/drum/drum_makeshift/bongos))
- return 1
\ No newline at end of file
+ return 1
+
+
+/mob/living/carbon/monkey/mushroom
+ name = "walking mushroom"
+ icon = 'icons/mob/animal.dmi'
+ icon_state = "mushroom"
+ greaterform = "Mushroom"
+ species_type = /mob/living/carbon/monkey/mushroom
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice/mushroom_man
+ canWearClothes = 0
+ canWearHats = 0
+ canWearGlasses = 0
+ canWearMasks = 0
+ canWearBack = 0
+ held_items = list()
+ flag = NO_BREATHE
+ var/growth = 0
+
+/mob/living/carbon/monkey/mushroom/say()
+ return 0
+
+/mob/living/carbon/monkey/mushroom/put_in_hand_check(var/obj/item/W)
+ return 0
+
+/mob/living/carbon/monkey/mushroom/Life()
+ ..()
+ if(!isDead() && !gcDestroyed && client)
+ var/light_amount = 0
+ if(isturf(loc))
+ var/turf/T = loc
+ light_amount = T.get_lumcount() * 10
+
+ growth = Clamp(growth + rand(1,3)/(10*light_amount>1 ? light_amount : 1),0,100)
+
+ if(growth >= 100)
+ growth = 0
+ var/mob/living/carbon/human/adult = new()
+ adult.alpha = 0
+ var/matrix/smol = matrix()
+ smol.Scale(0)
+ var/matrix/large = matrix()
+ var/matrix/M = adult.transform
+ M.Scale(0)
+ adult.set_species("Mushroom")
+ for(var/datum/language/L in languages)
+ adult.add_language(L.name)
+
+ adult.regenerate_icons()
+ adult.forceMove(get_turf(src))
+ animate(src, alpha = 0, transform = smol, time = 3 SECONDS, easing = SINE_EASING)
+ animate(adult, alpha = 255, transform = large, time = 3 SECONDS, easing = SINE_EASING)
+ transferImplantsTo(adult)
+ transferBorers(adult)
+
+ if(istype(loc,/obj/item/weapon/holder))
+ var/obj/item/weapon/holder/L = loc
+ src.forceMove(get_turf(L))
+ L = null
+ qdel(L)
+
+ if(mind)
+ src.mind.transfer_to(adult)
+ adult.fully_replace_character_name(newname = src.real_name)
+ src.drop_all()
+ qdel(src)
+
+/mob/living/carbon/monkey/mushroom/Stat()
+ ..()
+ if(statpanel("Status"))
+ stat(null, "Growth completing: [growth]%")
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/monkey/update_icons.dm b/code/modules/mob/living/carbon/monkey/update_icons.dm
index eb24579be25..6c10d6204a6 100644
--- a/code/modules/mob/living/carbon/monkey/update_icons.dm
+++ b/code/modules/mob/living/carbon/monkey/update_icons.dm
@@ -222,7 +222,7 @@
var/obj/item/I = get_held_item_by_index(GRASP_LEFT_HAND)
if(I && I.is_visible())
var/t_state = I.item_state
- var/t_inhand_states = I.inhand_states["right_hand"]
+ var/t_inhand_states = I.inhand_states["left_hand"]
if(!t_state)
t_state = I.icon_state
var/image/IM = image("icon" = t_inhand_states, "icon_state" = t_state)
diff --git a/code/modules/mob/living/carbon/not_human/gondola/gondola.dm b/code/modules/mob/living/carbon/not_human/gondola/gondola.dm
new file mode 100644
index 00000000000..91810410481
--- /dev/null
+++ b/code/modules/mob/living/carbon/not_human/gondola/gondola.dm
@@ -0,0 +1,29 @@
+/mob/living/carbon/not_human/gondola
+ name = "gondola"
+ desc = "A calming presence in this strange land."
+ icon = 'icons/mob/gondola.dmi'
+
+ icon_state_standing = "gondola"
+ icon_state_lying = "gondola_lying"
+ icon_state_dead = "gondola_dead"
+
+ maxHealth = 75
+ health = 75
+
+ held_items = list()
+
+ size = SIZE_NORMAL
+ status_flags = CANSTUN|CANKNOCKDOWN|CANPARALYSE|CANPUSH
+ mob_bump_flag = HUMAN
+ mob_push_flags = ALLMOBS
+ mob_swap_flags = ALLMOBS
+
+/mob/living/carbon/not_human/gondola/New()
+ icon_state_standing = pick("gondola","gondola_1")
+ icon_state_lying = "[icon_state_standing]_lying"
+ icon_state_dead = "[icon_state_dead]_dead"
+ ..()
+
+
+/mob/living/carbon/not_human/gondola/say()
+ return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/not_human/gondola/gondola_receive_music.dm b/code/modules/mob/living/carbon/not_human/gondola/gondola_receive_music.dm
new file mode 100644
index 00000000000..d144691ca79
--- /dev/null
+++ b/code/modules/mob/living/carbon/not_human/gondola/gondola_receive_music.dm
@@ -0,0 +1,120 @@
+//Basically walking media receivers
+/mob/living/carbon/not_human/gondola
+ var/playing=0
+ var/media_url=""
+ var/media_start_time=0
+ var/area/master_area
+ var/media_frequency = 1234 // 123.4 MHz
+ var/media_crypto = null // Crypto key
+
+ var/list/obj/machinery/media/transmitter/hooked = list()
+ var/exclusive_hook=null // Disables output to the room
+
+/mob/living/carbon/not_human/gondola/New()
+ ..()
+ connect_frequency()
+
+/mob/living/carbon/not_human/gondola/death()
+ disconnect_media_source()
+ ..()
+
+/mob/living/carbon/not_human/gondola/area_entered()
+ update_music()
+
+/mob/living/carbon/not_human/gondola/proc/connect_frequency()
+ // This is basically media_receivers["[media_frequency]"] += src
+ var/list/receivers=list()
+ var/freq = num2text(media_frequency)
+ if(freq in media_receivers)
+ receivers = media_receivers[freq]
+ receivers.Add(src)
+ media_receivers[freq]=receivers
+
+ // Check if there's a broadcast to tune into.
+ if(freq in media_transmitters)
+ // Pick a random broadcast in that frequency.
+ var/obj/machinery/media/transmitter/B = pick(media_transmitters[freq])
+ if(B.media_crypto == media_crypto) // Crypto-key check, if needed.
+ receive_broadcast(B.media_url,B.media_start_time)
+
+/mob/living/carbon/not_human/gondola/proc/receive_broadcast(var/url="", var/start_time=0)
+ media_url = url
+ media_start_time = start_time
+ update_music()
+
+/mob/living/carbon/not_human/gondola/proc/disconnect_frequency()
+ var/list/receivers=list()
+ var/freq = num2text(media_frequency)
+ if(freq in media_receivers)
+ receivers = media_receivers[freq]
+ receivers.Remove(src)
+ media_receivers[freq]=receivers
+
+ receive_broadcast()
+
+/mob/living/carbon/not_human/gondola/update_music()
+ if(isDead(src))
+ return
+ // Broadcasting shit
+ for(var/obj/machinery/media/transmitter/T in hooked)
+// testing("[src] Writing media to [T].")
+ T.broadcast(media_url,media_start_time)
+
+ if(exclusive_hook)
+ disconnect_media_source() // Just to be sure.
+ return
+
+ update_media_source()
+
+ // Bail if we lost connection to master.
+ if(!master_area)
+ return
+
+ // Send update to clients.
+ for(var/mob/M in mobs_in_area(master_area))
+ if(M == src)
+ continue
+ if(M && M.client)
+ M.update_music()
+
+ ..()
+
+/mob/living/carbon/not_human/gondola/proc/update_media_source()
+ var/area/A = get_area(src)
+ if(!A)
+ return
+ // Check if there's a media source already.
+ if(A.media_source && A.media_source!=src) //if it does, the new media source replaces it. basically, the last media source arrived gets played on top.
+ A.media_source.disconnect_media_source()//you can turn a media source off and on for it to come back on top.
+ A.media_source=src
+ master_area=A
+ return
+
+ // Update Media Source.
+ if(!A.media_source)
+ A.media_source=src
+
+ master_area=A
+
+
+/mob/living/carbon/not_human/gondola/proc/disconnect_media_source()
+ var/area/A = get_area(src)
+
+ // Sanity
+ if(!A)
+ master_area=null
+ return
+
+ // Check if there's a media source already.
+ if(A && A.media_source && A.media_source!=src)
+ master_area=null
+ return
+
+ // Update Media Source.
+ A.media_source=null
+
+ // Clients
+ for(var/mob/M in mobs_in_area(A))
+ if(M && M.client)
+ M.update_music()
+ master_area=null
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/not_human/martian/combat.dm b/code/modules/mob/living/carbon/not_human/martian/combat.dm
new file mode 100644
index 00000000000..3bb52835095
--- /dev/null
+++ b/code/modules/mob/living/carbon/not_human/martian/combat.dm
@@ -0,0 +1,8 @@
+/mob/living/carbon/not_human/martian/getarmor(var/def_zone, var/type)
+
+ var/armorscore = 0
+ if((def_zone == "head") || (def_zone == "eyes") || (def_zone == "mouth"))
+ if(head)
+ armorscore = head.armor[type]
+
+ return armorscore
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/not_human/martian/inventory.dm b/code/modules/mob/living/carbon/not_human/martian/inventory.dm
new file mode 100644
index 00000000000..29e35c24a57
--- /dev/null
+++ b/code/modules/mob/living/carbon/not_human/martian/inventory.dm
@@ -0,0 +1,149 @@
+/mob/living/carbon/not_human/martian/get_item_offset_by_index(index)
+ switch(index)
+ if(1,6)
+ return list("x"=0, "y"=0)
+ if(2,5)
+ return list("x"=0, "y"=8)
+ if(3,4)
+ return list("x"=0, "y"=14)
+
+ return list()
+
+/mob/living/carbon/not_human/martian/get_held_item_ui_location(index)
+ if(!is_valid_hand_index(index))
+ return
+
+ switch(index)
+ if(1)
+ return "CENTER-3:16,SOUTH:5"
+ if(2)
+ return "CENTER-2:16,SOUTH:5:4"
+ if(3)
+ return "CENTER-1:16,SOUTH:5:10"
+ if(4)
+ return "CENTER:16,SOUTH:5:10"
+ if(5)
+ return "CENTER+1:16,SOUTH:5:4"
+ if(6)
+ return "CENTER+2:16,SOUTH:5"
+ else
+ return ..()
+
+/mob/living/carbon/not_human/martian/get_index_limb_name(index)
+ if(!index)
+ index = active_hand
+
+ switch(index)
+ if(1)
+ return "right lower tentacle"
+ if(2)
+ return "right middle tentacle"
+ if(3)
+ return "right upper tentacle"
+ if(4)
+ return "left upper tentacle"
+ if(5)
+ return "left middle tentacle"
+ if(6)
+ return "left lower tentacle"
+ else
+ return "tentacle"
+
+/mob/living/carbon/not_human/martian/get_direction_by_index(index)
+ if(index <= 3)
+ return "right_hand"
+ else
+ return "left_hand"
+
+
+/mob/living/carbon/not_human/martian/GetAccess()
+ var/list/ACL=list()
+
+ for(var/obj/item/I in held_items)
+ ACL |= I.GetAccess()
+
+ return ACL
+
+/mob/living/carbon/not_human/martian/get_visible_id()
+ var/id = null
+ for(var/obj/item/I in held_items)
+ id = I.GetID()
+ if(id)
+ break
+ return id
+
+/mob/living/carbon/not_human/martian/can_wield()
+ return 1
+
+/mob/living/carbon/not_human/martian/u_equip(obj/item/W, dropped = 1, var/slot = null)
+ var/success = 0
+
+ if(!W)
+ return 0
+
+ if (W == head)
+ head = null
+ success = 1
+ update_inv_head()
+ else
+ ..()
+
+ if(success)
+ if (W)
+ if(client)
+ client.screen -= W
+ W.forceMove(loc)
+ W.unequipped(src, slot)
+ if(dropped)
+ W.dropped(src)
+ if(W)
+ W.reset_plane_and_layer()
+
+ return
+
+/mob/living/carbon/not_human/martian/abiotic()
+ for(var/obj/item/I in held_items)
+ if(I.abstract)
+ continue
+
+ return I
+
+ return head
+
+/mob/living/carbon/not_human/martian/show_inv(mob/living/carbon/user)
+ user.set_machine(src)
+
+ var/dat
+
+ for(var/i = 1 to held_items.len) //Hands
+ var/obj/item/I = held_items[i]
+ dat += "[capitalize(get_index_limb_name(i))][makeStrippingButton(I)] "
+
+ dat += " Head:[makeStrippingButton(head)]"
+
+ dat += {"
+
+ Close
+ "}
+
+ var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 340, 500)
+ popup.set_content(dat)
+ popup.open()
+
+
+// Return the item currently in the slot ID
+/mob/living/carbon/not_human/martian/get_item_by_slot(slot_id)
+ switch(slot_id)
+ if(slot_head)
+ return head
+ return null
+
+/mob/living/carbon/not_human/martian/equip_to_slot(obj/item/W, slot, redraw_mob = 1)
+ if(!istype(W))
+ return
+
+ if(slot == slot_head)
+ head = W
+ update_inv_head(redraw_mob)
+
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/not_human/martian/life.dm b/code/modules/mob/living/carbon/not_human/martian/life.dm
new file mode 100644
index 00000000000..ada6e49bfd2
--- /dev/null
+++ b/code/modules/mob/living/carbon/not_human/martian/life.dm
@@ -0,0 +1,49 @@
+
+/mob/living/carbon/not_human/martian/get_breath_from_internal(volume_needed)
+ //As this is a race that can only wear helmets, we'll have a fishbowl helmet that can accept tanks in place of having gas mask setups
+ if(head && istype(head, /obj/item/clothing/head/helmet/space/martian))
+ var/obj/item/clothing/head/helmet/space/martian/fishbowl = head
+ if(fishbowl.tank && istype(fishbowl.tank, /obj/item/weapon/tank))
+ var/obj/item/weapon/tank/internals = fishbowl.tank
+ return internals.remove_air_volume(volume_needed)
+ return null
+
+/mob/living/carbon/not_human/martian/breathe()
+ .=..()
+ var/block = 0
+ if(head)
+ if(istype(head, /obj/item/clothing/head/helmet/space/martian))
+ block = 1
+
+ if(!block)
+ for(var/obj/effect/effect/smoke/chem/smoke in view(1, src))
+ if(smoke.reagents.total_volume)
+ smoke.reagents.reaction(src, INGEST)
+ spawn(5)
+ if(smoke)
+ smoke.reagents.copy_to(src, 10) // I dunno, maybe the reagents enter the blood stream through the lungs?
+ break // If they breathe in the nasty stuff once, no need to continue checking
+
+/mob/living/carbon/not_human/martian/is_spaceproof()
+ if(head && istype(head, /obj/item/clothing/head/helmet/space/martian))
+ return TRUE
+ return ..()
+
+/mob/living/carbon/not_human/martian/get_thermal_protection_flags()
+ var/thermal_protection_flags = 0
+ if(head)
+ thermal_protection_flags |= head.body_parts_covered
+ return thermal_protection_flags
+
+/mob/living/carbon/not_human/martian/get_cold_protection()
+
+ if(M_RESIST_COLD in mutations)
+ return 1 //Fully protected from the cold.
+
+ var/thermal_protection = 0.0
+
+ if(head)
+ thermal_protection += head.return_thermal_protection()
+
+ var/max_protection = get_thermal_protection(get_thermal_protection_flags())
+ return min(thermal_protection,max_protection)
diff --git a/code/modules/mob/living/carbon/not_human/martian/martian.dm b/code/modules/mob/living/carbon/not_human/martian/martian.dm
new file mode 100644
index 00000000000..cfb9d395751
--- /dev/null
+++ b/code/modules/mob/living/carbon/not_human/martian/martian.dm
@@ -0,0 +1,146 @@
+#define MARTIANS_AMBIDEXTROUS //Comment out to prevent martians from being able to do multiple do_afters at once
+
+//WORK IN PROGRESS - Martians (name may be changed)
+//Like octopuses but with 6 hands
+
+/*
+ DESIGN:
+
+ + tentacles provide better grasp than hands. Martians are more resistant to winds, disarms and other hazards that would stun a human
+ + are ambidextrous
+
+ * breathe oxygen and exhale CO2 like humans do
+
+ - their unique shape means they can't fit into any human clothing, and can only put on hats
+ - toxins are very dangerous to them
+
+*/
+
+/mob/living/carbon/not_human/martian
+ name = "martian"
+ desc = "An alien resembling an overgrown octopus."
+ voice_name = "martian"
+
+ icon = 'icons/mob/martian.dmi'
+ icon_state = "martian"
+
+ species_type = /mob/living/carbon/not_human/martian
+ speak_emote = list("blorbles","burbles")
+
+ held_items = list(null, null, null, null, null, null) //6 hands
+
+ unslippable = TRUE
+ size = SIZE_BIG
+ status_flags = CANSTUN|CANKNOCKDOWN|CANPARALYSE|CANPUSH
+ mob_bump_flag = HUMAN
+ mob_push_flags = ALLMOBS
+ mob_swap_flags = ALLMOBS
+
+
+ fire_dmi = 'icons/mob/OnFire.dmi'
+ fire_sprite = "Standing"
+ plane = HUMAN_PLANE
+ maxHealth = 150
+ health = 150
+
+ //Inventory slots
+ var/obj/item/head //hat
+
+ icon_state_standing = "martian"
+ icon_state_lying = "lying"
+ icon_state_dead = "dead"
+
+ flag = 0
+
+ base_insulation = 0.5
+
+/mob/living/carbon/not_human/martian/New()
+ name = pick("martian","scootaloo","squid","rootmarian","phoronitian","sepiida","octopodiforme",\
+ "bolitaenides","belemnites","astrocanthoteuthis","octodad","ocotillo","kalamarian")
+ add_language(LANGUAGE_MARTIAN)
+ default_language = all_languages[LANGUAGE_MARTIAN]
+ ..()
+
+/mob/living/carbon/not_human/martian/Destroy()
+ head = null
+
+ ..()
+
+#ifdef MARTIANS_AMBIDEXTROUS
+/mob/living/carbon/not_human/martian/do_after_hand_check(held_item)
+ //Normally do_after breaks if you switch hands. With martians, it will only break if the used item is dropped
+ //This lets them do multiple things at once.
+ return (held_items.Find(held_item))
+#endif
+
+/mob/living/carbon/not_human/martian/eyecheck()
+ var/obj/item/clothing/head/headwear = src.head
+ var/protection
+ if(headwear)
+ protection = headwear.eyeprot
+
+ return Clamp(protection, -2, 2)
+
+/mob/living/carbon/not_human/martian/earprot()
+ return 1
+
+/mob/living/carbon/not_human/martian/dexterity_check()
+ return TRUE
+
+/mob/living/carbon/not_human/martian/IsAdvancedToolUser()
+ return TRUE
+
+/mob/living/carbon/not_human/martian/Process_Spaceslipping()
+ return 0 //No slipping
+
+/mob/living/carbon/not_human/martian/has_eyes()
+ return FALSE
+
+/mob/living/carbon/not_human/martian/updatehealth()
+ if(status_flags & GODMODE)
+ health = maxHealth
+ stat = CONSCIOUS
+ else
+ health = maxHealth - getOxyLoss() - getFireLoss() - getBruteLoss() - getCloneLoss()
+
+
+/mob/living/carbon/not_human/martian/ex_act(severity)
+ if(flags & INVULNERABLE)
+ return
+
+ flash_eyes(visual = 1)
+
+ switch(severity)
+ if(1.0)
+ adjustBruteLoss(100)
+ adjustFireLoss(100)
+ if(prob(50))
+ gib()
+ return
+ if(2.0)
+ adjustBruteLoss(60)
+ adjustFireLoss(60)
+ if(3.0)
+ adjustBruteLoss(30)
+
+ apply_effect(severity*4, WEAKEN)
+
+
+ updatehealth()
+
+/mob/living/carbon/not_human/martian/Login()
+ ..()
+ update_hud()
+
+/mob/living/carbon/not_human/martian/Stat()
+ ..()
+ if(statpanel("Status"))
+ stat(null, "Intent: [a_intent]")
+ stat(null, "Move Mode: [m_intent]")
+ if(head && istype(head, /obj/item/clothing/head/helmet/space/martian))
+ var/obj/item/clothing/head/helmet/space/martian/fishbowl = head
+ if(fishbowl.tank && istype(fishbowl.tank, /obj/item/weapon/tank))
+ var/obj/item/weapon/tank/internal = fishbowl.tank
+ stat("Internal Atmosphere Info", internal.name)
+ stat("Tank Pressure", internal.air_contents.return_pressure())
+ stat("Distribution Pressure", internal.distribute_pressure)
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/not_human/martian/update_icons.dm b/code/modules/mob/living/carbon/not_human/martian/update_icons.dm
new file mode 100644
index 00000000000..f06b5995de9
--- /dev/null
+++ b/code/modules/mob/living/carbon/not_human/martian/update_icons.dm
@@ -0,0 +1,73 @@
+//MOB ICONS
+
+/mob/living/carbon/not_human/martian/update_icons()
+ ..()
+ overlays.len = 0
+ for(var/image/I in item_overlays)
+ overlays += I
+//INVENTORY ICONS
+
+#define HAT_LAYER 1
+//2-7 are used for hands
+#define MAX_LAYERS 7
+
+/mob/living/carbon/not_human/martian
+ var/list/item_overlays[MAX_LAYERS] //6 hands + hat
+
+/mob/living/carbon/not_human/martian/update_inv_hand(index, var/update_icons=1)
+ var/obj/item/I = get_held_item_by_index(index)
+ var/list/offsets = get_item_offset_by_index(index)
+ var/pixelx = 0
+ var/pixely = 0
+ if(offsets["x"])
+ pixelx = offsets["x"]
+ if(offsets["y"])
+ pixely = offsets["y"]
+
+ if(I)
+ var/t_state = I.item_state
+ var/t_inhand_states = I.inhand_states[get_direction_by_index(index)]
+ if(!t_state)
+ t_state = I.icon_state
+
+ var/image/hand_image = image("icon" = src.icon, "icon_state" = "hand_[index]")
+ hand_image.overlays += image("icon" = t_inhand_states, "icon_state" = t_state, "pixel_x" = pixelx, "pixel_y" = pixely)
+
+ item_overlays[HAT_LAYER + index] = hand_image
+
+ I.screen_loc = get_held_item_ui_location(index)
+ if (handcuffed)
+ drop_item(I)
+ else
+ item_overlays[HAT_LAYER + index] = null
+
+ if(update_icons)
+ update_icons()
+
+
+/mob/living/carbon/not_human/martian/update_inv_head(var/update_icons=1)
+ if(!head)
+ item_overlays[HAT_LAYER] = null
+
+ if(update_icons)
+ update_icons()
+ return
+ else
+ item_overlays[HAT_LAYER] = image("icon" = ((head.icon_override) ? head.icon_override : 'icons/mob/head.dmi'), "icon_state" = "[head.icon_state]", "pixel_y" = 5)
+
+ if(update_icons)
+ update_icons()
+
+ if(client)
+ client.screen |= head
+ head.screen_loc = ui_monkey_hat
+
+
+
+/mob/living/carbon/not_human/martian/update_hud()
+ if(client)
+ update_internals()
+ client.screen |= contents
+
+#undef HAT_LAYER
+#undef MAX_LAYERS
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/slime/life.dm b/code/modules/mob/living/carbon/slime/life.dm
index 7e0b760c32b..104a45ef783 100644
--- a/code/modules/mob/living/carbon/slime/life.dm
+++ b/code/modules/mob/living/carbon/slime/life.dm
@@ -84,7 +84,7 @@
break
- if(Target.health <= -70 || Target.stat == 2)
+ if(Target.health <= -70 || Target.isDead())
Target = null
AIproc = 0
// to_chat(world, "break 3")
diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm
index 8883dcee1a8..75352d49e0d 100644
--- a/code/modules/mob/living/carbon/slime/slime.dm
+++ b/code/modules/mob/living/carbon/slime/slime.dm
@@ -65,6 +65,7 @@
maxHealth = 200
health = 200
gender = NEUTER
+ size = SIZE_BIG
update_icon = 0
nutrition = 800 // 1200 = max
@@ -719,6 +720,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle19"
+ w_class = W_CLASS_TINY
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
@@ -757,6 +759,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle19"
+ w_class = W_CLASS_TINY
attack(mob/living/carbon/slime/adult/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime/adult))//If target is not a slime.
@@ -792,6 +795,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
desc = "A potent chemical mix that will cause a slime to generate more extract."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle16"
+ w_class = W_CLASS_TINY
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
@@ -817,6 +821,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
desc = "A potent chemical mix that is a great nutrient for slimes."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle12"
+ w_class = W_CLASS_TINY
var/Uses = 2
/obj/item/weapon/slimenutrient/attack(mob/living/carbon/slime/M as mob, mob/user as mob)
@@ -843,6 +848,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
desc = "A potent chemical mix that will give a slime extract three uses."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle17"
+ w_class = W_CLASS_TINY
/*afterattack(obj/target, mob/user , flag)
if(istype(target, /obj/item/slime_extract))
@@ -862,6 +868,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
desc = "A potent chemical mix that will force a child slime to split in two!"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle15"
+ w_class = W_CLASS_TINY
/obj/item/weapon/slimedupe/attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime))//target is not a slime
@@ -886,6 +893,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
desc = "A potent chemical mix that when used on a slime extact, will bring it to life!"
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle14"
+ w_class = W_CLASS_TINY
////////Adamantine Golem stuff I dunno where else to put it
/*
@@ -1154,7 +1162,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process()
var/turf/location = get_turf(src)
var/datum/gas_mixture/environment = location.return_air()
- if ((environment.toxins / environment.volume * CELL_VOLUME) > MOLES_PLASMA_VISIBLE)//plasma exposure causes the egg to hatch
+ if (environment.molar_density("toxins") > MOLES_PLASMA_VISIBLE / CELL_VOLUME)//plasma exposure causes the egg to hatch
src.Hatch()
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W as obj, mob/user as mob)
diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm
index 8b31b893326..84c5fce8c9e 100644
--- a/code/modules/mob/living/carbon/species.dm
+++ b/code/modules/mob/living/carbon/species.dm
@@ -53,7 +53,7 @@ var/global/list/whitelisted_species = list("Human")
var/breath_type = "oxygen" // Non-oxygen gas breathed, if any.
var/survival_gear = /obj/item/weapon/storage/box/survival // For spawnin'.
- var/cold_level_1 = 260 // Cold damage level 1 below this point.
+ var/cold_level_1 = 220 // Cold damage level 1 below this point.
var/cold_level_2 = 200 // Cold damage level 2 below this point.
var/cold_level_3 = 120 // Cold damage level 3 below this point.
@@ -142,6 +142,8 @@ var/global/list/whitelisted_species = list("Human")
var/list/inventory_offsets
+ var/species_intro //What intro you're given when you become this species.
+
/datum/species/New()
..()
@@ -326,7 +328,7 @@ var/global/list/whitelisted_species = list("Human")
primitive = /mob/living/carbon/monkey/unathi
darksight = 3
- cold_level_1 = 280 //Default 260 - Lower is better
+ cold_level_1 = 260 //Default 220 - Lower is better
cold_level_2 = 220 //Default 200
cold_level_3 = 130 //Default 120
@@ -350,7 +352,7 @@ var/global/list/whitelisted_species = list("Human")
known_languages = list(LANGUAGE_CLATTER)
flags = IS_WHITELISTED | NO_BREATHE
anatomy_flags = HAS_LIPS | NO_SKIN | NO_BLOOD
-
+ meat_type = /obj/item/stack/sheet/bone
chem_flags = NO_EAT | NO_INJECT
default_mutations=list(SKELETON)
@@ -364,6 +366,11 @@ var/global/list/whitelisted_species = list("Human")
primitive = /mob/living/carbon/monkey/skellington
+ species_intro = "You are a Skellington \
+ You have no skin, no blood, no lips, and only just enough brain to function. \
+ You can not eat normally, as your necrotic state only permits you to only eat raw flesh. As you lack skin, you can not be injected via syringe. \
+ You are also incredibly weak to brute damage and are rather slow, but you don't need to breathe, so that's going for you."
+
/datum/species/skellington/handle_speech(var/datum/speech/speech, mob/living/carbon/human/H)
if (prob(25))
speech.message += " ACK ACK!"
@@ -543,6 +550,10 @@ var/global/list/whitelisted_species = list("Human")
"eyes" = /datum/organ/internal/eyes/grey
)
+ species_intro = "You are a Grey. \
+ You are particularly allergic to water, which acts like acid to you, but the inverse is so for acid, so you're fun at parties. \
+ You're not as good in a fist fight as a regular baseline human, but you make up for this by bullying them from afar by talking directly into peoples minds."
+
/datum/species/muton // /vg/
name = "Muton"
icobase = 'icons/mob/human_races/r_muton.dmi'
@@ -645,6 +656,11 @@ var/global/list/whitelisted_species = list("Human")
"eyes" = /datum/organ/internal/eyes/vox
)
+ species_intro = "You are a Vox. \
+ You are somewhat more adept at handling the lower pressures of space and colder temperatures. \
+ You have talons with which you can slice others in a fist fight, and a beak which can be used to butcher corpses without the need for finer tools. \
+ However, Oxygen is incredibly toxic to you, in breathing it or consuming it. You can only breathe nitrogen."
+
/datum/species/vox/equip(var/mob/living/carbon/human/H)
// Unequip existing suits and hats.
if(H.mind.assigned_role != "MODE")
@@ -753,7 +769,7 @@ var/global/list/whitelisted_species = list("Human")
H.equip_or_collect(new/obj/item/weapon/tank/nitrogen(H), tank_slot)
else
H.put_in_hands(new/obj/item/weapon/tank/nitrogen(H))
- to_chat(H, "You are now running on nitrogen internals from the [H.s_store] in your [tank_slot_name]. Your species finds oxygen toxic, so you must breathe nitrogen (AKA N2) only.")
+ to_chat(H, "You are now running on nitrogen internals from the [H.s_store] in your [tank_slot_name].")
H.internal = H.get_item_by_slot(tank_slot)
if (H.internals)
H.internals.icon_state = "internal1"
@@ -825,6 +841,12 @@ var/global/list/whitelisted_species = list("Human")
move_speed_mod = 7
+ species_intro = "You are a Diona. \
+ You are a plant, so light is incredibly helpful for you, in both photosynthesis, and regenerating damage you have received. \
+ You absorb radiation which helps you in a similar way to sunlight. You are incredibly slow as you are rooted to the ground. \
+ You do not need to breathe, do not feel pain, you are incredibly resistant to cold and low pressure, and have no blood to bleed. \
+ However, as you are a plant, you are incredibly susceptible to burn damage, which is something you can not regenerate normally."
+
/datum/species/golem
name = "Golem"
icobase = 'icons/mob/human_races/r_golem.dmi'
@@ -886,7 +908,7 @@ var/list/has_died_as_golem = list()
anim(target = H, a_icon = 'icons/mob/mob.dmi', flick_anim = "dust-g", sleeptime = 15)
var/mob/living/adamantine_dust/A = new(H.loc)
if(golemmind)
- has_died_as_golem.Add(H.mind.key = world.time)
+ has_died_as_golem[H.mind.key] = world.time
A.mind = golemmind
H.mind = null
golemmind.current = A
@@ -1114,3 +1136,51 @@ var/list/has_died_as_golem = list()
to_chat(user, "You place \the [O] into \the [src].")
qdel(O)
+
+
+/datum/species/mushroom
+ name = "Mushroom"
+ icobase = 'icons/mob/human_races/r_mushman.dmi'
+ deform = 'icons/mob/human_races/r_mushman.dmi'
+ known_languages = list()
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice/mushroom_man
+
+ flags = IS_WHITELISTED | NO_BREATHE | IS_PLANT | REQUIRE_DARK | IS_SPECIES_MUTE
+
+ gender = NEUTER
+
+ darksight = 5
+ tox_mod = 0.8
+ brute_mod = 1.8
+ burn_mod = 0.6
+
+ primitive = /mob/living/carbon/monkey/mushroom
+
+ spells = list(/spell/targeted/genetic/invert_eyes)
+
+ default_mutations=list(M_REMOTE_TALK)
+ default_block_names=list("REMOTETALK")
+
+ blood_color = "#D3D3D3"
+ flesh_color = "#D3D3D3"
+
+ //Copypaste of Dionae
+ cold_level_1 = 50
+ cold_level_2 = -1
+ cold_level_3 = -1
+
+ heat_level_1 = T0C + 50
+ heat_level_2 = T0C + 75
+ heat_level_3 = T0C + 100
+
+ has_mutant_race = 0
+
+ has_organ = list(
+ "brain" = /datum/organ/internal/brain/mushroom_brain,
+ )
+
+ species_intro = "You are a Mushroom Person. \
+ You are an odd creature, light harms you and makes you hunger, but the darkness heals you and feeds you. \
+ You have a resistance to burn and toxin, but a weakness to brute damage. You are adept at seeing in the dark, moreso with your light inversion ability. \
+ However, you lack a mouth with which to talk. Instead you can remotely talk into somebodies mind should you examine them, or they talk to you. \
+ You also have access to the Sporemind, which allows you to communicate with others on the Sporemind through :~"
diff --git a/code/modules/mob/living/carbon/species_powers.dm b/code/modules/mob/living/carbon/species_powers.dm
new file mode 100644
index 00000000000..fc3d4ea1cb1
--- /dev/null
+++ b/code/modules/mob/living/carbon/species_powers.dm
@@ -0,0 +1,30 @@
+/spell/targeted/genetic/invert_eyes
+ name = "Invert eyesight"
+ desc = "Inverts the colour spectrum you see, letting you see clearly in the dark, but not in the light."
+ panel = "Mutant Powers"
+ user_type = USER_TYPE_GENETIC
+ range = SELFCAST
+
+ charge_type = Sp_RECHARGE
+
+ spell_flags = INCLUDEUSER
+
+ invocation_type = SpI_NONE
+
+ override_base = "genetic"
+ hud_state = "wiz_sleepold"
+ var/toggle = TRUE
+
+
+/spell/targeted/genetic/invert_eyes/cast(list/targets, mob/user)
+ var/list/colourmatrix = list()
+ if(toggle)
+ colourmatrix = list(-1, 0, 0,
+ 0,-1, 0,
+ 0, 0,-1,
+ 1, 1, 1)
+ else
+ colourmatrix = default_colour_matrix
+ for(var/mob/living/carbon/human/M in targets)
+ M.update_colour(50,0,colourmatrix)
+ toggle = !toggle
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/zombie/zombie.dm b/code/modules/mob/living/carbon/zombie/zombie.dm
index 0586009dcad..c872b68d780 100644
--- a/code/modules/mob/living/carbon/zombie/zombie.dm
+++ b/code/modules/mob/living/carbon/zombie/zombie.dm
@@ -161,7 +161,7 @@
if(T.organs["head"])
affecting = T.organs["head"]
affecting.take_damage(rand(1,7), 0)
- playsound(get_turf(src), 'sound/items/eatfood.ogg', 50, 1)
+ playsound(src, 'sound/items/eatfood.ogg', 50, 1)
if(prob(25))
target.contract_disease(new/datum/disease/z_virus)
src.add_blood(src.target)
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index 4955859bc82..8142a7417b9 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -11,9 +11,7 @@
/mob/living/proc/apply_damage(var/damage = 0,var/damagetype = BRUTE, var/def_zone = null, var/blocked = 0, var/used_weapon = null, ignore_events = 0)
if(!damage || (blocked >= 2))
return 0
-
var/damage_done = damage/(blocked+1)
- damage_done = run_armor_absorb(def_zone, damagetype, damage_done)
switch(damagetype)
if(BRUTE)
adjustBruteLoss(damage_done)
diff --git a/code/modules/mob/living/holders.dm b/code/modules/mob/living/holders.dm
index c80125b27be..a9566cedf83 100644
--- a/code/modules/mob/living/holders.dm
+++ b/code/modules/mob/living/holders.dm
@@ -159,6 +159,16 @@
update_itemstate_on_twohand = TRUE
+//SALEM
+
+/obj/item/weapon/holder/animal/salem
+ name = "salem holder"
+ desc = "Esp!"
+ item_state = "salem"
+
+ update_itemstate_on_twohand = TRUE
+
+
//SLIMES
/obj/item/weapon/holder/animal/slime
name = "slime holder"
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 920e5d54658..417b784e52e 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -34,8 +34,7 @@
. = ..()
-/mob/living/examine(mob/user) //Show the mob's size and whether it's been butchered
- var/size
+/mob/living/examine(var/mob/user, var/size = "", var/show_name = TRUE, var/show_icon = TRUE) //Show the mob's size and whether it's been butchered
switch(src.size)
if(SIZE_TINY)
size = "tiny"
@@ -56,7 +55,7 @@
else if(src.gender == PLURAL)
pronoun = "they are"
- ..(user, " [capitalize(pronoun)] [size].")
+ ..(user, " [capitalize(pronoun)] [size].", show_name, FALSE)
if(meat_taken > 0)
to_chat(user, "[capitalize(pronoun)] partially butchered.")
@@ -521,13 +520,11 @@ Thanks.
if(iscarbon(src))
var/mob/living/carbon/C = src
- if (C.handcuffed && !initial(C.handcuffed))
+ if(C.handcuffed)
C.drop_from_inventory(C.handcuffed)
- C.handcuffed = initial(C.handcuffed)
- if (C.legcuffed && !initial(C.legcuffed))
+ if (C.legcuffed)
C.drop_from_inventory(C.legcuffed)
- C.legcuffed = initial(C.legcuffed)
hud_updateflag |= 1 << HEALTH_HUD
hud_updateflag |= 1 << STATUS_HUD
@@ -611,9 +608,6 @@ Thanks.
IO.status = 0
IO.robotic = 0
H.updatehealth()
- if(iscarbon(src))
- var/mob/living/carbon/C = src
- C.handcuffed = initial(C.handcuffed)
for(var/datum/disease/D in viruses)
D.cure(0)
if(stat == DEAD)
@@ -1408,12 +1402,7 @@ Thanks.
return
if(!can_butcher)
- if(meat_taken)
- to_chat(user, "[src] has already been butchered.")
- return
- else
- to_chat(user, "You can't butcher [src]!")
- return
+ to_chat(user, "You can't butcher [src]!")
return
var/obj/item/tool = null //The tool that is used for butchering
@@ -1459,13 +1448,16 @@ Thanks.
if(src.butchering_drops && src.butchering_drops.len)
var/list/actions = list()
- actions += "Butcher"
+ if(meat_taken < meat_amount)
+ actions += "Butcher"
for(var/datum/butchering_product/B in src.butchering_drops)
if(B.amount <= 0)
continue
-
actions |= capitalize(B.verb_name)
actions[capitalize(B.verb_name)] = B
+ if(!actions.len)
+ to_chat(user, "[src] has already been butchered.")
+ return
actions += "Cancel"
var/choice = input(user,"What would you like to do with \the [src]?","Butchering") in actions
@@ -1492,6 +1484,10 @@ Thanks.
src.update_icons()
return
+ else if(meat_taken >= meat_amount)
+ to_chat(user, "[src] has already been butchered.")
+ return
+
user.visible_message("[user] starts butchering \the [src][tool ? " with \the [tool]" : ""].",\
"You start butchering \the [src].")
src.being_butchered = 1
@@ -1513,7 +1509,6 @@ Thanks.
return
to_chat(user, "You butcher \the [src].")
- can_butcher = 0
if(istype(src, /mob/living/simple_animal)) //Animals can be butchered completely, humans - not so
if(src.size > SIZE_TINY) //Tiny animals don't produce gibs
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 780b5664e3d..f9fc6395440 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -49,7 +49,6 @@
/mob/living/proc/run_armor_absorb(var/def_zone = null, var/attack_flag = "melee", var/initial_damage)
var/armor = getarmorabsorb(def_zone, attack_flag)
var/final_damage = initial_damage
-
if(armor)
var/damage_multiplier = final_damage/armor
if(damage_multiplier < 1)
@@ -79,7 +78,8 @@
P.on_hit(src,2)
return 2
if(!P.nodamage)
- apply_damage((P.damage/(absorb+1)), P.damage_type, def_zone, absorb, P.is_sharp(), used_weapon = P)
+ var/damage = run_armor_absorb(def_zone, P.flag, (P.damage/(absorb+1)))
+ apply_damage(damage, P.damage_type, def_zone, absorb, P.is_sharp(), used_weapon = P)
regenerate_icons()
P.on_hit(src, absorb)
if(istype(P, /obj/item/projectile/beam/lightning))
@@ -101,6 +101,8 @@
var/obj/item/weapon/W = O
dtype = W.damtype
src.visible_message("[src] has been hit by [O].")
+ if(O.impactsound)
+ playsound(loc, O.impactsound, 80, 1, -1)
var/zone_normal_name
switch(zone)
if(LIMB_LEFT_ARM)
@@ -115,7 +117,8 @@
zone_normal_name = zone
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [zone_normal_name].", "Your armor has softened the blow to your [zone_normal_name].", armor_penetration = O.throwforce*(speed/5)*O.sharpness)
if(armor < 2)
- apply_damage(O.throwforce*(speed/5), dtype, zone, armor, O.is_sharp(), O)
+ var/damage = run_armor_absorb(zone, "melee", O.throwforce*(speed/5))
+ apply_damage(damage, dtype, zone, armor, O.is_sharp(), O)
// Begin BS12 momentum-transfer code.
@@ -300,8 +303,8 @@
if(istype(T))
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
if(G)
- oxy=G.oxygen/G.volume*CELL_VOLUME
- if(oxy < 1 || fire_stacks <= 0)
+ oxy = G.molar_density("oxygen")
+ if(oxy < (1 / CELL_VOLUME) || fire_stacks <= 0)
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
return 1
var/turf/location = get_turf(src)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index 029bccc18a1..dd0f4d0bfb5 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -24,34 +24,64 @@
return "cultchat"
if(MODE_ANCIENT)
return "ancientchat"
+ if(MODE_MUSHROOM)
+ return "sporechat"
else
return "Unknown"
var/list/department_radio_keys = list(
- ":0" = "Deathsquad", "#0" = "Deathsquad", ".0" = "Deathsquad",
-
- ":r" = "right ear", "#r" = "right ear", ".r" = "right ear", "!r" = "fake right ear",
- ":l" = "left ear", "#l" = "left ear", ".l" = "left ear", "!l" = "fake left ear",
- ":i" = "intercom", "#i" = "intercom", ".i" = "intercom",
- ":h" = "department", "#h" = "department", ".h" = "department",
- ":c" = "Command", "#c" = "Command", ".c" = "Command",
- ":n" = "Science", "#n" = "Science", ".n" = "Science",
- ":m" = "Medical", "#m" = "Medical", ".m" = "Medical",
- ":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering",
- ":s" = "Security", "#s" = "Security", ".s" = "Security",
- ":w" = "whisper", "#w" = "whisper", ".w" = "whisper",
- ":b" = "binary", "#b" = "binary", ".b" = "binary",
+ ":0" = "Deathsquad", "#0" = "Deathsquad", ".0" = "Deathsquad",
+ //1 Used by LANGUAGE_GALACTIC_COMMON
+ //2 Used by LANGUAGE_TRADEBAND
+ //3 Used by LANGUAGE_GUTTER
+ //4 Used by LANGUAGE_XENO
+ //5 Used by LANGUAGE_CULT
+ //6 Used by LANGUAGE_MONKEY
+ //7 Used by LANGUAGE_HUMAN
+ //8 Used by LANGUAGE_GOLEM
+ //9 Used by LANGUAGE_MOUSE
+ ":-" = "Response Team","#-" = "Response Team",".-" = "Response Team",
":a" = "alientalk", "#a" = "alientalk", ".a" = "alientalk",
- ":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate",
- ":r" = "Response Team","#r" = "Response Team",".r" = "Response Team",
- ":u" = "Supply", "#u" = "Supply", ".u" = "Supply",
+ ":b" = "binary", "#b" = "binary", ".b" = "binary",
+ ":c" = "Command", "#c" = "Command", ".c" = "Command",
":d" = "Service", "#d" = "Service", ".d" = "Service",
+ ":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering",
+ //f Used by LANGUAGE_SLIME
":g" = "changeling", "#g" = "changeling", ".g" = "changeling",
+ ":h" = "department", "#h" = "department", ".h" = "department",
+ ":i" = "intercom", "#i" = "intercom", ".i" = "intercom",
+ //j Used by LANGUAGE_TAJARAN
+ //k Used by LANGUAGE_SKRELLIAN and LANGUAGE_GREY
+ ":l" = "left hand", "#l" = "left hand", ".l" = "left hand", "!l" = "fake left hand",
+ ":m" = "Medical", "#m" = "Medical", ".m" = "Medical",
+ ":n" = "Science", "#n" = "Science", ".n" = "Science",
+ //o Used by LANGUAGE_UNATHI
+ ":p" = "AI Private", "#p" = "AI Private", ".p" = "AI Private",
+ //q Used by LANGUAGE_ROOTSPEAK
+ ":r" = "right hand", "#r" = "right hand", ".r" = "right hand", "!r" = "fake right hand",
+ ":s" = "Security", "#s" = "Security", ".s" = "Security",
+ ":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate",
+ ":u" = "Supply", "#u" = "Supply", ".u" = "Supply",
+ //v Used by LANGUAGE_VOX
+ ":w" = "whisper", "#w" = "whisper", ".w" = "whisper",
":x" = "cultchat", "#x" = "cultchat", ".x" = "cultchat",
":y" = "ancientchat", "#y" = "ancientchat", ".y" = "ancientchat",
- ":p" = "AI Private", "#p" = "AI Private", ".p" = "AI Private",
+ //z Used by LANGUAGE_CLATTER
+ //@ Used by LANGUAGE_MARTIAN
+ ":~" = "sporechat", "#~" = "sporechat", ".~" = "sporechat",
- ":R" = "right ear", "#R" = "right ear", ".R" = "right ear", "!R" = "fake right ear",
- ":L" = "left ear", "#L" = "left ear", ".L" = "left ear", "!L" = "fake left ear",
+
+
+
+
+
+
+
+
+
+
+
+ ":R" = "right hand", "#R" = "right hand", ".R" = "right hand", "!R" = "fake right hand",
+ ":L" = "left hand", "#L" = "left hand", ".L" = "left hand", "!L" = "fake left hand",
":I" = "intercom", "#I" = "intercom", ".I" = "intercom",
":H" = "department", "#H" = "department", ".H" = "department",
":C" = "Command", "#C" = "Command", ".C" = "Command",
@@ -63,7 +93,6 @@ var/list/department_radio_keys = list(
":B" = "binary", "#B" = "binary", ".B" = "binary",
":A" = "alientalk", "#A" = "alientalk", ".A" = "alientalk",
":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate",
- ":R" = "Response Team","#R" = "Response Team",".R" = "Response Team",
":U" = "Supply", "#U" = "Supply", ".U" = "Supply",
":D" = "Service", "#D" = "Service", ".D" = "Service",
":G" = "changeling", "#G" = "changeling", ".G" = "changeling",
@@ -73,21 +102,21 @@ var/list/department_radio_keys = list(
//kinda localization -- rastaf0
//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
- ":ê" = "right ear", "#ê" = "right ear", ".ê" = "right ear",
- ":ä" = "left ear", "#ä" = "left ear", ".ä" = "left ear",
+ ":ê" = "right hand", "#ê" = "right hand", ".ê" = "right hand",
+ ":ä" = "left hand", "#ä" = "left hand", ".ä" = "left hand",
":ø" = "intercom", "#ø" = "intercom", ".ø" = "intercom",
":ð" = "department", "#ð" = "department", ".ð" = "department",
- ":ñ" = "Command", "#ñ" = "Command", ".ñ" = "Command",
- ":ò" = "Science", "#ò" = "Science", ".ò" = "Science",
- ":ü" = "Medical", "#ü" = "Medical", ".ü" = "Medical",
- ":ó" = "Engineering", "#ó" = "Engineering", ".ó" = "Engineering",
+ ":ñ" = "Command", "#ñ" = "Command", ".ñ" = "Command",
+ ":ò" = "Science", "#ò" = "Science", ".ò" = "Science",
+ ":ü" = "Medical", "#ü" = "Medical", ".ü" = "Medical",
+ ":ó" = "Engineering","#ó" = "Engineering", ".ó" = "Engineering",
":û" = "Security", "#û" = "Security", ".û" = "Security",
- ":ö" = "whisper", "#ö" = "whisper", ".ö" = "whisper",
+ ":ö" = "whisper", "#ö" = "whisper", ".ö" = "whisper",
":è" = "binary", "#è" = "binary", ".è" = "binary",
- ":ô" = "alientalk", "#ô" = "alientalk", ".ô" = "alientalk",
- ":å" = "Syndicate", "#å" = "Syndicate", ".å" = "Syndicate",
+ ":ô" = "alientalk", "#ô" = "alientalk", ".ô" = "alientalk",
+ ":å" = "Syndicate", "#å" = "Syndicate", ".å" = "Syndicate",
":é" = "Supply", "#é" = "Supply", ".é" = "Supply",
- ":â" = "Service", "#â" = "Service", ".â" = "Service",
+ ":â" = "Service", "#â" = "Service", ".â" = "Service",
":ï" = "changeling", "#ï" = "changeling", ".ï" = "changeling"
)
@@ -361,6 +390,17 @@ var/list/department_radio_keys = list(
if(!istype(M,/mob/new_player))
handle_render(M,themessage,src)
return 1
+ if(MODE_MUSHROOM)
+ var/message = text("Sporemind, []: []", src.name, html_encode(speech.message))
+ var/turf/T = get_turf(src)
+ log_say("[key_name(src)] (@[T.x],[T.y],[T.z]) Spore chat: [html_encode(speech.message)]")
+ for(var/mob/M in player_list)
+ if(iscarbon(M))
+ var/mob/living/carbon/human/H = M
+ if(ismushroom(H))
+ handle_render(M, message,src)
+ if((M in dead_mob_list) && !istype(M, /mob/new_player))
+ handle_render(M, message,src)
return 0
/mob/living/proc/treat_speech(var/datum/speech/speech, genesay = 0)
@@ -456,7 +496,7 @@ var/list/department_radio_keys = list(
display_bubble_to_clientlist(image('icons/mob/talk.dmi', get_holder_at_turf_level(src), "h[bubble_type][say_test(message)]",MOB_LAYER+1), tracking_speech_bubble_recipients)
/proc/display_bubble_to_clientlist(var/image/speech_bubble, var/clientlist)
- speech_bubble.plane = BASE_PLANE
+ speech_bubble.plane = ABOVE_LIGHTING_PLANE
speech_bubble.appearance_flags = RESET_COLOR
flick_overlay(speech_bubble, clientlist, 30)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 01a2033bb7e..164bed9f20c 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -2,41 +2,39 @@ var/list/ai_list = list()
//Not sure why this is necessary...
/proc/AutoUpdateAI(obj/subject)
- var/is_in_use = 0
- if (subject!=null)
+ var/is_in_use = FALSE
+ if(subject!=null)
for(var/A in ai_list)
var/mob/living/silicon/ai/M = A
- if ((M.client && M.machine == subject))
- is_in_use = 1
+ if((M.client && M.machine == subject))
+ is_in_use = TRUE
subject.attack_ai(M)
return is_in_use
/mob/living/silicon/ai
name = "AI"
- icon = 'icons/mob/AI.dmi'//
+ icon = 'icons/mob/AI.dmi'
icon_state = "ai"
- anchored = 1 // -- TLE
- density = 1
+ anchored = TRUE // -- TLE
+ density = TRUE
status_flags = CANSTUN|CANPARALYSE|CANPUSH
- force_compose = 1
+ force_compose = TRUE
size = SIZE_BIG
var/list/network = list(CAMERANET_SS13)
var/obj/machinery/camera/current = null
var/list/connected_robots = list()
var/aiRestorePowerRoutine = 0
- //var/list/laws = list()
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list())
- var/viewalerts = 0
+ var/viewalerts = FALSE
var/lawcheck[1]
var/ioncheck[1]
var/icon/holo_icon//Default is assigned when AI is created.
var/obj/item/device/pda/ai/aiPDA = null
var/obj/item/device/multitool/aiMulti = null
var/obj/item/device/station_map/station_holomap = null
- var/custom_sprite = 0 //For our custom sprites
- var/obj/item/device/camera/ai_camera/aicamera = null
+ var/obj/item/device/camera/silicon/aicamera = null
var/busy = FALSE //Toggle Floor Bolt busy var.
//Hud stuff
@@ -44,20 +42,20 @@ var/list/ai_list = list()
//MALFUNCTION
var/ai_flags = 0
- var/control_disabled = 0 // Set to 1 to stop AI from interacting via Click() -- TLE
- var/malfhacking = 0 // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite
+ var/control_disabled = FALSE // Set to TRUE to stop AI from interacting via Click() -- TLE
+ var/malfhacking = FALSE // More or less a copy of the above var, so that malf AIs can hack and still get new cyborgs -- NeoFite
var/obj/machinery/power/apc/malfhack = null
- var/explosive = 0 //does the AI explode when it dies?
+ var/explosive = FALSE //does the AI explode when it dies?
var/mob/living/silicon/ai/parent = null
- var/camera_light_on = 0
+ var/camera_light_on = FALSE
var/list/obj/machinery/camera/lit_cameras = list()
var/datum/trackable/track = new()
var/last_paper_seen = null
- var/can_shunt = 1
+ var/can_shunt = TRUE
var/last_announcement = ""
// The AI's "eye". Described on the top of the page in eye.dm
@@ -67,38 +65,32 @@ var/list/ai_list = list()
var/cooldown = 0
var/acceleration = 1
-/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0)
+/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = FALSE)
+
var/list/possibleNames = ai_names
var/pickedName = null
while(!pickedName)
pickedName = pick(ai_names)
for (var/mob/living/silicon/ai/A in mob_list)
- if (A.real_name == pickedName && possibleNames.len > 1) //fixing the theoretically possible infinite loop
+ if(A.real_name == pickedName && possibleNames.len > 1) //fixing the theoretically possible infinite loop
possibleNames -= pickedName
pickedName = null
- add_language(LANGUAGE_GALACTIC_COMMON, 1)
- add_language(LANGUAGE_UNATHI, 1)
- add_language(LANGUAGE_CATBEAST, 1)
- add_language(LANGUAGE_SKRELLIAN, 1)
- add_language(LANGUAGE_ROOTSPEAK, 1)
- add_language(LANGUAGE_GUTTER, 1)
- add_language(LANGUAGE_CLATTER, 1)
- add_language(LANGUAGE_GREY, 1)
- add_language(LANGUAGE_MONKEY, 1)
- add_language(LANGUAGE_VOX, 1)
- add_language(LANGUAGE_GOLEM, 1)
- add_language(LANGUAGE_TRADEBAND, 1)
- add_language(LANGUAGE_MOUSE, 1)
- add_language(LANGUAGE_GOLEM, 1)
- add_language(LANGUAGE_SLIME, 1)
- add_language(LANGUAGE_HUMAN, 1)
+
+ //AIs speak all languages that aren't restricted(XENO, CULT).
+ for(var/language_name in all_languages)
+ var/datum/language/lang = all_languages[language_name]
+ if(!(lang.flags & RESTRICTED) && !(lang in languages))
+ add_language(lang.name)
+
+ //But gal common is restricted so let's add it manually.
+ add_language(LANGUAGE_GALACTIC_COMMON)
default_language = all_languages[LANGUAGE_GALACTIC_COMMON]
+
real_name = pickedName
name = real_name
- view_core()
- anchored = 1
- canmove = 0
+ anchored = TRUE
+ canmove = FALSE
setDensity(TRUE)
loc = loc
@@ -125,19 +117,19 @@ var/list/ai_list = list()
station_holomap = new(src)
aiMulti = new(src)
- aicamera = new/obj/item/device/camera/ai_camera(src)
- if (istype(loc, /turf))
+ aicamera = new /obj/item/device/camera/silicon/ai_camera(src)
+ if(istype(loc, /turf))
verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \
/mob/living/silicon/ai/proc/ai_statuschange, \
/mob/living/silicon/ai/proc/ai_hologram_change)
if(!safety)//Only used by AIize() to successfully spawn an AI.
- if (!B)//If there is no player/brain inside.
+ if(!B)//If there is no player/brain inside.
new/obj/structure/AIcore/deactivated(loc)//New empty terminal.
qdel(src)//Delete AI.
return
else
- if (B.brainmob.mind)
+ if(B.brainmob.mind)
B.brainmob.mind.transfer_to(src)
to_chat(src, "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras).")
@@ -182,7 +174,7 @@ var/list/ai_list = list()
var/list/nametemp = list()
var/find
var/datum/picture/selection
- if(aicamera.aipictures.len == 0)
+ if(!aicamera.aipictures.len)
to_chat(usr, "No images saved")
return
for(var/datum/picture/t in aicamera.aipictures)
@@ -199,7 +191,7 @@ var/list/ai_list = list()
switch(choice)
if("Cancel")
return
- if ("Delete")
+ if("Delete")
aicamera.aipictures.Remove(selection)
qdel(selection)
if("Rename")
@@ -214,26 +206,6 @@ var/list/ai_list = list()
set name = "Set AI Core Display"
if(stat || aiRestorePowerRoutine)
return
- /* Jesus christ, more of this shit?
- if(!custom_sprite) //Check to see if custom sprite time, checking the appopriate file to change a var
- var/file = file2text("config/custom_sprites.txt")
- var/lines = splittext(file, "\n")
-
- for(var/line in lines)
- // split & clean up
- var/list/Entry = splittext(line, "-")
- for(var/i = 1 to Entry.len)
- Entry[i] = trim(Entry[i])
-
- if(Entry.len < 2)
- continue;
-
- if(Entry[1] == src.ckey && Entry[2] == src.real_name)
- custom_sprite = 1 //They're in the list? Custom sprite time
- icon = 'icons/mob/custom-synthetic.dmi'
- */
- //if(icon_state == initial(icon_state))
- /* Nuked your hidden shit.*/
var/icontype = input("Select an icon!", "AI", null, null) as null|anything in list("Monochrome", "Blue", "Inverted", "Text", "Smiley", "Angry", "Dorf", "Matrix", "Bliss", "Firewall", "Green", "Red", "Broken Output", "Triumvirate", "Triumvirate Static", "Searif", "Ravensdale", "Serithi", "Static", "Wasp", "Robert House", "Red October", "Fabulous", "Girl", "Girl Malf", "Boy", "Boy Malf", "Four-Leaf", "Yes Man", "Hourglass", "Patriot", "Pirate", "Royal", "Heartline", "Hades", "Helios", "Syndicat", "Alien", "Too Deep", "Goon", "Database", "Glitchman", "Nanotrasen", "Angel", "Gentoo", "Murica", "President", "Fort", "Mothman", "Dancing Hotdog", "Diagnosis", "Drink It!", "Metaclub", "Jack Frost")
switch(icontype)
if("Clown")
@@ -345,10 +317,6 @@ var/list/ai_list = list()
if("Jack Frost")
icon_state = "ai-jack"
else icon_state = "ai"
- //else
-// to_chat(usr, "You can only change your display once!")
- //return
-
// displays the malf_ai information if the AI is the malf
/mob/living/silicon/ai/show_malf_ai()
@@ -370,31 +338,31 @@ var/list/ai_list = list()
for (var/cat in alarms)
dat += text("[] \n", cat)
var/list/L = alarms[cat]
- if (L.len)
+ if(L.len)
for (var/alarm in L)
var/list/alm = L[alarm]
var/area/A = alm[1]
var/C = alm[2]
var/list/sources = alm[3]
dat += ""
- if (C && istype(C, /list))
+ if(C && istype(C, /list))
var/dat2 = ""
for (var/obj/machinery/camera/I in C)
dat2 += text("[][]", (dat2=="") ? "" : " | ", src, I, I.c_tag)
dat += text("-- [] ([])", A.name, (dat2!="") ? dat2 : "No Camera")
- else if (C && istype(C, /obj/machinery/camera))
+ else if(C && istype(C, /obj/machinery/camera))
var/obj/machinery/camera/Ctmp = C
dat += text("-- [] ([])", A.name, src, C, Ctmp.c_tag)
else
dat += text("-- [] (No Camera)", A.name)
- if (sources.len > 1)
+ if(sources.len > 1)
dat += text("- [] sources", sources.len)
dat += " \n"
else
dat += "-- All Systems Nominal \n"
dat += " \n"
- viewalerts = 1
+ viewalerts = TRUE
src << browse(dat, "window=aialerts&can_close=0")
// this verb lets the ai see the stations manifest
@@ -402,7 +370,7 @@ var/list/ai_list = list()
show_station_manifest()
/mob/living/silicon/ai/proc/ai_call_shuttle()
- if(src.stat == 2)
+ if(isDead())
to_chat(src, "You can't call the shuttle because you are dead!")
return
if(istype(usr,/mob/living/silicon/ai))
@@ -429,7 +397,7 @@ var/list/ai_list = list()
/mob/living/silicon/ai/proc/ai_cancel_call()
set category = "AI Commands"
- if(src.stat == 2)
+ if(isDead())
to_chat(src, "You can't send the shuttle back because you are dead!")
return
if(istype(usr,/mob/living/silicon/ai))
@@ -440,32 +408,32 @@ var/list/ai_list = list()
recall_shuttle(src)
/mob/living/silicon/ai/check_eye(var/mob/user as mob)
- if (!current)
+ if(!current)
return null
user.reset_view(current)
- return 1
+ return TRUE
/mob/living/silicon/ai/blob_act()
if(flags & INVULNERABLE)
return
- if (stat != DEAD)
+ if(stat != DEAD)
..()
playsound(loc, 'sound/effects/blobattack.ogg',50,1)
adjustBruteLoss(60)
updatehealth()
- return 1
- return 0
+ return TRUE
+ return FALSE
/mob/living/silicon/ai/restrained()
if(timestopped)
- return 1 //under effects of time magick
- return 0
+ return TRUE //under effects of time magick
+ return FALSE
/mob/living/silicon/ai/emp_act(severity)
if(flags & INVULNERABLE)
return
- if (prob(30))
+ if(prob(30))
switch(pick(1,2))
if(1)
view_core()
@@ -478,46 +446,46 @@ var/list/ai_list = list()
return
// if(!blinded) (this is now in flash_eyes)
- flash_eyes(visual = 1, affect_silicon = 1)
+ flash_eyes(visual = TRUE, affect_silicon = TRUE)
switch(severity)
if(1.0)
- if (stat != 2)
+ if(!isDead())
adjustBruteLoss(100)
adjustFireLoss(100)
if(2.0)
- if (stat != 2)
+ if(!isDead())
adjustBruteLoss(60)
adjustFireLoss(60)
if(3.0)
- if (stat != 2)
+ if(!isDead())
adjustBruteLoss(30)
updatehealth()
/mob/living/silicon/ai/put_in_hands(var/obj/item/W)
- return 0
+ return FALSE
/mob/living/silicon/ai/Topic(href, href_list)
if(usr != src)
return
..()
- if (href_list["mach_close"])
- if (href_list["mach_close"] == "aialerts")
- viewalerts = 0
+ if(href_list["mach_close"])
+ if(href_list["mach_close"] == "aialerts")
+ viewalerts = FALSE
var/t1 = text("window=[]", href_list["mach_close"])
unset_machine()
src << browse(null, t1)
- if (href_list["switchcamera"])
+ if(href_list["switchcamera"])
switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras
- if (href_list["showalerts"])
+ if(href_list["showalerts"])
ai_alerts()
if(href_list["show_paper"])
if(last_paper_seen)
src << browse(last_paper_seen, "window=show_paper")
//Carn: holopad requests
- if (href_list["jumptoholopad"])
+ if(href_list["jumptoholopad"])
var/obj/machinery/hologram/holopad/H = locate(href_list["jumptoholopad"])
if(stat == CONSCIOUS)
if(H)
@@ -529,44 +497,42 @@ var/list/ai_list = list()
play_vox_word(href_list["say_word"], null, src)
return
- if (href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite
+ if(href_list["lawc"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite
var/L = text2num(href_list["lawc"])
switch(lawcheck[L+1])
- if ("Yes")
+ if("Yes")
lawcheck[L+1] = "No"
- if ("No")
+ if("No")
lawcheck[L+1] = "Yes"
-// to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1]))
checklaws()
- if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite
+ if(href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite
var/L = text2num(href_list["lawi"])
switch(ioncheck[L])
- if ("Yes")
+ if("Yes")
ioncheck[L] = "No"
- if ("No")
+ if("No")
ioncheck[L] = "Yes"
-// to_chat(src, text ("Switching Law [L]'s report status to []", lawcheck[L+1]))
checklaws()
- if (href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite
+ if(href_list["laws"]) // With how my law selection code works, I changed statelaws from a verb to a proc, and call it through my law selection panel. --NeoFite
statelaws()
- if (href_list["track"])
+ if(href_list["track"])
var/mob/target = locate(href_list["track"]) in mob_list
var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list
if(A && target)
A.ai_actual_track(target)
return
- else if (href_list["faketrack"])
+ else if(href_list["faketrack"])
var/mob/target = locate(href_list["track"]) in mob_list
var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list
if(A && target)
A.cameraFollow = target
to_chat(A, text("Now tracking [] on camera.", target.name))
- if (usr.machine == null)
+ if(usr.machine == null)
usr.machine = usr
while (src.cameraFollow == target)
@@ -576,7 +542,7 @@ var/list/ai_list = list()
return
- if (href_list["open"])
+ if(href_list["open"])
var/mob/target = locate(href_list["open"])
var/mob/living/silicon/ai/A = locate(href_list["open2"])
if(A && target)
@@ -592,19 +558,19 @@ var/list/ai_list = list()
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M)
switch(M.a_intent)
- if (I_HELP)
+ if(I_HELP)
visible_message("[M] caresses [src]'s plating with its scythe like arm.")
else //harm
if(M.unarmed_attack_mob(src))
if(prob(8))
- flash_eyes(visual = 1, type = /obj/abstract/screen/fullscreen/flash/noise)
+ flash_eyes(visual = TRUE, type = /obj/abstract/screen/fullscreen/flash/noise)
/mob/living/silicon/ai/attack_animal(mob/living/simple_animal/M as mob)
M.unarmed_attack_mob(src)
/mob/living/silicon/ai/reset_view(atom/A)
- if (camera_light_on)
+ if(camera_light_on)
light_cameras()
if(istype(A,/obj/machinery/camera))
current = A
@@ -616,8 +582,8 @@ var/list/ai_list = list()
src.cameraFollow = null
- if (!C || stat == 2) //C.can_use())
- return 0
+ if(!C || isDead()) //C.can_use())
+ return FALSE
if(!src.eyeobj)
view_core()
@@ -626,61 +592,61 @@ var/list/ai_list = list()
eyeobj.forceMove(get_turf(C))
//machine = src
- return 1
+ return TRUE
/mob/living/silicon/ai/triggerAlarm(var/class, area/A, var/O, var/alarmsource)
- if (stat == 2)
- return 1
+ if(isDead())
+ return TRUE
var/list/L = alarms[class]
for (var/I in L)
- if (I == A.name)
+ if(I == A.name)
var/list/alarm = L[I]
var/list/sources = alarm[3]
- if (!(alarmsource in sources))
+ if(!(alarmsource in sources))
sources += alarmsource
- return 1
+ return TRUE
var/obj/machinery/camera/C = null
var/list/CL = null
- if (O && istype(O, /list))
+ if(O && istype(O, /list))
CL = O
- if (CL.len == 1)
+ if(CL.len == 1)
C = CL[1]
- else if (O && istype(O, /obj/machinery/camera))
+ else if(O && istype(O, /obj/machinery/camera))
C = O
L[A.name] = list(A, (C) ? C : O, list(alarmsource))
- if (O)
- if (C && C.can_use())
+ if(O)
+ if(C && C.can_use())
queueAlarm("--- [class] alarm detected in [A.name]! ([C.c_tag])", class)
- else if (CL && CL.len)
- var/foo = 0
+ else if(CL && CL.len)
+ var/foo = FALSE
var/dat2 = ""
for (var/obj/machinery/camera/I in CL)
dat2 += text("[][]", (!foo) ? "" : " | ", src, I, I.c_tag) //I'm not fixing this shit...
- foo = 1
+ foo = TRUE
queueAlarm(text ("--- [] alarm detected in []! ([])", class, A.name, dat2), class)
else
queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
else
queueAlarm(text("--- [] alarm detected in []! (No Camera)", class, A.name), class)
- if (viewalerts)
+ if(viewalerts)
ai_alerts()
- return 1
+ return TRUE
/mob/living/silicon/ai/cancelAlarm(var/class, area/A as area, obj/origin)
var/list/L = alarms[class]
- var/cleared = 0
+ var/cleared = FALSE
for (var/I in L)
- if (I == A.name)
+ if(I == A.name)
var/list/alarm = L[I]
var/list/srcs = alarm[3]
- if (origin in srcs)
+ if(origin in srcs)
srcs -= origin
- if (srcs.len == 0)
- cleared = 1
+ if(!srcs.len)
+ cleared = TRUE
L -= I
- if (cleared)
+ if(cleared)
queueAlarm(text("--- [] alarm in [] has been cleared.", class, A.name), class, 0)
- if (viewalerts)
+ if(viewalerts)
ai_alerts()
return !cleared
@@ -750,9 +716,9 @@ var/list/ai_list = list()
var/obj/machinery/status_display/SD = M
if(emote=="Friend Computer")
- SD.friendc = 1
+ SD.friendc = TRUE
else
- SD.friendc = 0
+ SD.friendc = FALSE
return
//I am the icon meister. Bow fefore me. //>fefore
@@ -838,10 +804,10 @@ var/list/ai_list = list()
/spell/aoe_turf/corereturn/before_target(mob/user)
if(istype(user.loc, /obj/machinery/power/apc))
- return 0
+ return FALSE
else
to_chat(user, "You are already in your Main Core.")
- return 1
+ return TRUE
/spell/aoe_turf/corereturn/choose_targets(mob/user = usr)
return list(user.loc)
@@ -860,11 +826,11 @@ var/list/ai_list = list()
camera_light_on = !camera_light_on
- if (!camera_light_on)
+ if(!camera_light_on)
to_chat(src, "Camera lights deactivated.")
for (var/obj/machinery/camera/C in lit_cameras)
- C.set_light(0)
+ C.set_light(FALSE)
lit_cameras = list()
return
@@ -891,7 +857,7 @@ var/list/ai_list = list()
var/list/obj/machinery/camera/visible = list()
for (var/datum/camerachunk/CC in eyeobj.visibleCameraChunks)
for (var/obj/machinery/camera/C in CC.cameras)
- if (!C.can_use() || C.light_disabled || get_dist(C, eyeobj) > 7)
+ if(!C.can_use() || C.light_disabled || get_dist(C, eyeobj) > 7)
continue
visible |= C
@@ -899,7 +865,7 @@ var/list/ai_list = list()
remove = lit_cameras - visible
for (var/obj/machinery/camera/C in remove)
- C.set_light(0)
+ C.set_light(FALSE)
lit_cameras -= C
for (var/obj/machinery/camera/C in add)
C.set_light(AI_CAMERA_LUMINOSITY)
@@ -914,7 +880,7 @@ var/list/ai_list = list()
user.visible_message("\The [user] decides not to unbolt \the [src].")
return
user.visible_message("\The [user] finishes unfastening \the [src]!")
- anchored = 0
+ anchored = FALSE
return
else
user.visible_message("\The [user] starts to bolt \the [src] to the plating...")
@@ -922,7 +888,7 @@ var/list/ai_list = list()
user.visible_message("\The [user] decides not to bolt \the [src].")
return
user.visible_message("\The [user] finishes fastening down \the [src]!")
- anchored = 1
+ anchored = TRUE
return
else
return ..()
@@ -936,7 +902,7 @@ var/list/ai_list = list()
return (health - config.health_threshold_dead) / 2
/mob/living/silicon/ai/html_mob_check()
- return 1
+ return TRUE
/mob/living/silicon/ai/isTeleViewing(var/client_eye)
- return 1
+ return TRUE
diff --git a/code/modules/mob/living/silicon/ai/emote.dm b/code/modules/mob/living/silicon/ai/emote.dm
new file mode 100644
index 00000000000..6204fd1d580
--- /dev/null
+++ b/code/modules/mob/living/silicon/ai/emote.dm
@@ -0,0 +1,76 @@
+/mob/living/silicon/ai/emote(var/act,var/m_type=1,var/message =null, var/auto)
+ if(timestopped)
+ return // time is frozen
+ var/param = null
+ var/regex/reg = regex("(.+?)-(.+)")
+ if(reg.Find(act, 1))
+ param = reg.group[2]
+ act = reg.group[1]
+
+ var/regex/reg2 = regex("(.*?)s")
+ var/regex/reg3 = regex("(.*?)_(.*)")
+ if(reg2.Find(act, -1) && !reg3.Find(act, -2))//Removes ending s's unless they are prefixed with a '_'
+ act = copytext(act,1,length(act))
+
+ switch(act)
+ if("beep")
+ var/M = null
+ if(param)
+ var/H = get_holder_at_turf_level(src)
+ for (var/mob/A in view(H))
+ if (param == A.name)
+ M = A
+ break
+ if(!M)
+ param = null
+
+ if (param)
+ message = "[src] beeps at [param]."
+ else
+ message = "[src] beeps."
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 0)
+ m_type = VISIBLE
+
+ if("ping")
+ var/M = null
+ if(param)
+ var/H = get_holder_at_turf_level(src)
+ for (var/mob/A in view(H))
+ if (param == A.name)
+ M = A
+ break
+ if(!M)
+ param = null
+
+ if (param)
+ message = "[src] pings at [param]."
+ else
+ message = "[src] pings."
+ playsound(src, 'sound/machines/ping.ogg', 50, 0)
+ m_type = VISIBLE
+
+ if("buzz")
+ var/M = null
+ if(param)
+ var/H = get_holder_at_turf_level(src)
+ for (var/mob/A in view(H))
+ if (param == A.name)
+ M = A
+ break
+ if(!M)
+ param = null
+
+ if (param)
+ message = "[src] buzzes at [param]."
+ else
+ message = "[src] buzzes."
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ m_type = VISIBLE
+
+ if (message && !isUnconscious())
+ if (m_type & VISIBLE)
+ for(var/mob/O in viewers(src, null))
+ O.show_message(message, m_type)
+ else
+ for(var/mob/O in hearers(src, null))
+ O.show_message(message, m_type)
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index 783bb916fc5..654795bd83e 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -65,9 +65,10 @@
/mob/living/silicon/ai/Destroy()
- eyeobj.ai = null
- qdel(eyeobj) // No AI, no Eye
- eyeobj = null
+ if(eyeobj)
+ eyeobj.ai = null
+ qdel(eyeobj) // No AI, no Eye
+ eyeobj = null
..()
/atom/proc/move_camera_by_click()
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 1c6d6f0afe7..5fe8420edc5 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -185,3 +185,6 @@
health = maxHealth - getOxyLoss() - getToxLoss() - getBruteLoss()
else
health = maxHealth - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
+
+/mob/living/silicon/ai/update_canmove() //If the AI dies, mobs won't go through it anymore
+ return FALSE
diff --git a/code/modules/mob/living/silicon/ai/login.dm b/code/modules/mob/living/silicon/ai/login.dm
index 23b9e3f8015..04daadc2406 100644
--- a/code/modules/mob/living/silicon/ai/login.dm
+++ b/code/modules/mob/living/silicon/ai/login.dm
@@ -8,7 +8,6 @@
to_chat(src, {"Use say ":b to speak to your cyborgs through binary."})
show_laws()
-
for(var/obj/effect/rune/rune in rune_list) //HOLY FUCK WHO THOUGHT LOOPING THROUGH THE WORLD WAS A GOOD IDEA
client.images += rune.blood_image
regenerate_icons()
@@ -18,4 +17,4 @@
O.mode = 1
O.emotion = "Neutral"
view_core()
- client.CAN_MOVE_DIAGONALLY = TRUE
\ No newline at end of file
+ client.CAN_MOVE_DIAGONALLY = TRUE
diff --git a/code/modules/mob/living/silicon/mommi/cogspider.dm b/code/modules/mob/living/silicon/mommi/cogspider.dm
new file mode 100644
index 00000000000..fabf8a47a7c
--- /dev/null
+++ b/code/modules/mob/living/silicon/mommi/cogspider.dm
@@ -0,0 +1,19 @@
+/mob/living/silicon/robot/mommi/cogspider
+ prefix="Gravekeeper"
+ desc = "A clockwork being, of design familiar yet alien."
+ damage_control_network = "Gravewatch"
+ icon_state = "cogspider"
+ namepick_uses = 0
+ startup_sound = 'sound/misc/timesuit_activate.ogg'//The clockwork winding up
+ cell_type = /obj/item/weapon/cell/potato/soviet
+
+/mob/living/silicon/robot/mommi/cogspider/updatename() // Fuck individualism
+ name = "[prefix] [num2text(ident)]"
+
+/mob/living/silicon/robot/mommi/cogspider/identification_string()
+ return name
+
+
+/mob/living/silicon/robot/mommi/cogspider/New()
+ pick_module("Gravekeeper")
+ ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/mommi/emote.dm b/code/modules/mob/living/silicon/mommi/emote.dm
index 69ae8a1257f..7b7841d14e8 100644
--- a/code/modules/mob/living/silicon/mommi/emote.dm
+++ b/code/modules/mob/living/silicon/mommi/emote.dm
@@ -63,16 +63,16 @@
m_type = VISIBLE
if ("clap")
- if (!src.restrained())
+ if (!incapacitated())
message = "[src] clangs \his utility claws together in a crude simulation of applause."
m_type = HEARABLE
if ("flap")
- if (!src.restrained())
+ if (!incapacitated())
message = "[src] flaps \his utility arms as through they were wings."
m_type = HEARABLE
if ("aflap")
- if (!src.restrained())
+ if (!incapacitated())
message = "[src] flaps his utility arms ANGRILY!"
m_type = HEARABLE
@@ -181,7 +181,7 @@
message = "[src] beeps at [param]."
else
message = "[src] beeps."
- playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0)
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 0)
m_type = VISIBLE
if("ping")
@@ -198,7 +198,7 @@
message = "[src] pings at [param]."
else
message = "[src] pings."
- playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0)
+ playsound(src, 'sound/machines/ping.ogg', 50, 0)
m_type = VISIBLE
if("buzz")
@@ -215,7 +215,7 @@
message = "[src] buzzes at [param]."
else
message = "[src] buzzes."
- playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0)
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
m_type = VISIBLE
if("comment")
diff --git a/code/modules/mob/living/silicon/mommi/examine.dm b/code/modules/mob/living/silicon/mommi/examine.dm
index db3c3a8c7d3..225299f7584 100644
--- a/code/modules/mob/living/silicon/mommi/examine.dm
+++ b/code/modules/mob/living/silicon/mommi/examine.dm
@@ -2,7 +2,7 @@
var/msg = "*---------*\nThis is [bicon(src)] \a [src]!\n"
- msg += {"
It's like a crab, but it has a utility tool on one arm and a crude metal claw on the other. That, and you doubt it'd survive in an ocean for very long.
"}
+ msg += {"
[desc]
"}
msg += ""
if (getBruteLoss())
diff --git a/code/modules/mob/living/silicon/mommi/inventory.dm b/code/modules/mob/living/silicon/mommi/inventory.dm
index d6ee3023478..40bb0771c24 100644
--- a/code/modules/mob/living/silicon/mommi/inventory.dm
+++ b/code/modules/mob/living/silicon/mommi/inventory.dm
@@ -32,16 +32,10 @@
if(cell && cell.charge <= MOMMI_LOW_POWER)
drop_item(W)
return 0
- // Make sure we're not picking up something that's in our factory-supplied toolbox.
- //if(is_type_in_list(W,src.module.modules))
- //if(is_in_modules(W))
-// to_chat(src, "Picking up something that's built-in to you seems a bit silly.")
- //return 0
if(W.type == /obj/item/device/material_synth)
drop_item(W)
return 0
if(tool_state)
- //var/obj/item/found = locate(tool_state) in src.module.modules
var/obj/item/TS = tool_state
if(!is_in_modules(tool_state))
drop_item(TS)
@@ -53,6 +47,7 @@
tool_state = W
W.hud_layerise()
W.forceMove(src)
+ W.equipped(src)
// Make crap we pick up active so there's less clicking and carpal. - N3X
module_active=tool_state
@@ -101,20 +96,14 @@
if(!istype(to_drop))
to_drop = tool_state
if(to_drop)
- //var/obj/item/found = locate(tool_state) in src.module.modules
if(is_in_modules(to_drop))
if((to_drop in contents) && (to_drop in src.module.modules))
to_chat(src, "This item cannot be dropped.")
return 0
- if(client)
- client.screen -= to_drop
- to_drop.forceMove(Target)
-
- //this all should be using remove_from_mob() but I couldn't get it to work for some reason so for now it continues to be copypasted ass
+ remove_from_mob(to_drop) //clean out any refs
to_drop.dropped(src)
-
- u_equip(to_drop)
+ to_drop.forceMove(Target)
update_items()
return 1
return 0
@@ -338,3 +327,7 @@
update_items()
else
to_chat(M, "You are unable to equip that.")
+
+/mob/living/carbon/can_use_hands()
+ return TRUE
+
diff --git a/code/modules/mob/living/silicon/mommi/laws.dm b/code/modules/mob/living/silicon/mommi/laws.dm
index 8097f9a4f39..d204cbcaaff 100644
--- a/code/modules/mob/living/silicon/mommi/laws.dm
+++ b/code/modules/mob/living/silicon/mommi/laws.dm
@@ -3,7 +3,7 @@
// Except for this, of course.
/mob/living/silicon/robot/mommi/laws_sanity_check()
if (!laws)
- laws = new mommi_base_law_type
+ laws = new mommi_laws["Default"]
// And this.
/mob/living/silicon/robot/mommi/statelaws() // -- TLE
diff --git a/code/modules/mob/living/silicon/mommi/life.dm b/code/modules/mob/living/silicon/mommi/life.dm
index 0ae52ff8ddb..278b2eef86b 100644
--- a/code/modules/mob/living/silicon/mommi/life.dm
+++ b/code/modules/mob/living/silicon/mommi/life.dm
@@ -16,7 +16,7 @@
if(client)
handle_regular_hud_updates()
- update_action_buttons()
+ update_action_buttons_icon()
update_items()
if (src.stat != DEAD) //still using power
use_power()
diff --git a/code/modules/mob/living/silicon/mommi/login.dm b/code/modules/mob/living/silicon/mommi/login.dm
index f60c1873e82..dfa983479bf 100644
--- a/code/modules/mob/living/silicon/mommi/login.dm
+++ b/code/modules/mob/living/silicon/mommi/login.dm
@@ -1,19 +1,18 @@
/mob/living/silicon/robot/mommi/Login()
-
..()
- /* Inherited
- regenerate_icons()
- show_laws(0)
- if(mind)
- ticker.mode.remove_revolutionary(mind)
- return
- */
if(can_see_static())
add_static_overlays()
+ to_chat(src, "MoMMIs are not standard cyborgs, and have different laws. Review your laws carefully.")
+ to_chat(src, "For newer players, a simple FAQ is here. Further questions should be directed to adminhelps (F1).")
+ to_chat(src, "For cuteness' sake, using the various emotes MoMMIs have such as *beep, *ping, *buzz or *aflap isn't considered interacting. Don't use that as an excuse to get involved though, always remain neutral.")
/mob/living/silicon/robot/mommi/proc/can_see_static()
return (keeper && !emagged && !syndicate && (config && config.mommi_static))
+/mob/living/silicon/robot/mommi/generate_static_overlay()
+ if(!islist(static_overlays))
+ static_overlays = list()
+
/mob/living/silicon/robot/mommi/proc/add_static_overlays()
remove_static_overlays()
for(var/mob/living/living in mob_list)
@@ -25,13 +24,20 @@
else
chosen = living.static_overlays[1]
static_overlays.Add(chosen)
- client.images.Add(chosen)
+ if(client)
+ client.images.Add(chosen)
/mob/living/silicon/robot/mommi/proc/remove_static_overlays()
if(client)
for(var/image/I in static_overlays)
client.images.Remove(I)
- static_overlays.len = 0
+ static_overlays.Cut()
+
+/mob/living/silicon/robot/mommi/examination(atom/A as mob|obj|turf in view()) //It used to be oview(12), but I can't really say why
+ if(ismob(A) && !issilicon(A) && can_see_static()) //can't examine what you can't catch!
+ to_chat(usr, "Your vision module can't determine any of [A]'s features.")
+ return
+ ..()
/mob/living/silicon/robot/mommi/verb/toggle_statics()
set name = "Change Vision Filter"
diff --git a/code/modules/mob/living/silicon/mommi/mommi.dm b/code/modules/mob/living/silicon/mommi/mommi.dm
index c0a8c3a0674..1bf439c0522 100644
--- a/code/modules/mob/living/silicon/mommi/mommi.dm
+++ b/code/modules/mob/living/silicon/mommi/mommi.dm
@@ -6,176 +6,78 @@ They can only use one tool at a time, they can't choose modules, and they have 1
*/
/mob/living/silicon/robot/mommi
name = "Mobile MMI"
+ desc = "It's like a crab, but it has a utility tool on one arm and a crude metal claw on the other. That, and you doubt it'd survive in an ocean for very long."
real_name = "Mobile MMI"
- icon = 'icons/mob/robots.dmi'
+ icon = 'icons/mob/mommi.dmi'
icon_state = "mommi"
maxHealth = 60
health = 60
+
pass_flags = PASSTABLE
- var/keeper=0 // 0 = No, 1 = Yes (Disables speech and common radio.)
- var/picked = 0
- var/subtype="keeper"
- var/obj/abstract/screen/inv_tool = null
- var/prefix = "Mobile MMI"
- var/damage_control_network = "Damage Control"
-
- static_overlays
- var/static_choice = "static"
- var/list/static_choices = list("static", "letter", "blank")
-
mob_bump_flag = ROBOT
mob_swap_flags = ALLMOBS
mob_push_flags = 0
+ modtype = "Nanotrasen"
+ braintype = "Mobile MMI"
+
+ //New() stuff
+ startup_sound = 'sound/misc/interference.ogg'
+
+ //This is no cyborg boy, no cyborg!
+ cell_type = /obj/item/weapon/cell/crepe/mommi //The secret behind MoMMIs, literal powercreep.
+ wiring_type = /datum/wires/robot/mommi
+
+ AIlink = FALSE //Fuck AIs, you're a crab.
+ scrambledcodes = TRUE //Don't appear on the SS13/ROBOTS cameranet, you're not supposed to be a ventcrawling security camera.
+
+ //MoMMI stuff
+ var/picked_icon = FALSE
+
+ var/keeper= TRUE // FALSE = No, TRUE = Yes (Disables speech and common radio.)
+ var/prefix = "Mobile MMI"
+ var/damage_control_network = "Damage Control"
+
+ var/static_choice = "static"
+ var/list/static_choices = list("static", "letter", "blank")
+
+ var/obj/abstract/screen/inv_tool = null
var/obj/item/tool_state = null
var/obj/item/head_state = null
- modtype = "robot" // Not sure what this is, but might be cool to have seperate loadouts for MoMMIs (e.g. paintjobs and tools)
- //Cyborgs will sync their laws with their AI by default, but we may want MoMMIs to be mute independents at some point, kinda like the Keepers in Ass Effect.
- lawupdate = 1
- speed = 0
-
-/mob/living/carbon/can_use_hands()
- return 1
-
-/mob/living/silicon/robot/mommi/generate_static_overlay()
- if(!istype(static_overlays,/list))
- static_overlays = list()
- return
-
-/mob/living/silicon/robot/mommi/examination(atom/A as mob|obj|turf in view()) //It used to be oview(12), but I can't really say why
- if(ismob(A) && src.can_see_static()) //can't examine what you can't catch!
- to_chat(usr, "Your vision module can't determine any of [A]'s features.")
+/mob/living/silicon/robot/mommi/pick_module(var/forced_module = null)
+ if(module)
return
- ..()
-
-
-/mob/living/silicon/robot/mommi/New(loc)
- ident = rand(1, 999)
- updatename()
- updateicon()
-
- if(!cell)
- cell = new /obj/item/weapon/cell(src)
- cell.maxcharge = 7500
- cell.charge = 7500
- ..(loc,startup_sound='sound/misc/interference.ogg')
- module = new /obj/item/weapon/robot_module/mommi(src)
- laws = new mommi_base_law_type
-
- // Don't sync if we're a KEEPER.
- if(!istype(laws,/datum/ai_laws/keeper))
- connected_ai = select_active_ai_with_fewest_borgs()
+ if(forced_module)
+ modtype = forced_module
else
- // Enforce silence.
- keeper=1
- connected_ai = null // Enforce no AI parent
- scrambledcodes = 1 // Hide from console because people are fucking idiots
-
- if(connected_ai)
- connected_ai.connected_robots += src
- lawsync()
- lawupdate = 1
- else
- lawupdate = 0
-
- if(!scrambledcodes && !camera)
- camera = new /obj/machinery/camera(src)
- camera.c_tag = real_name
- camera.network = list(CAMERANET_SS13,CAMERANET_ROBOTS)
- if(wires.IsCameraCut()) // 5 = BORG CAMERA
- camera.status = 0
-
- // Sanity check
- if(connected_ai && keeper)
- to_chat(world, "ASSERT FAILURE: connected_ai && keeper in mommi.dm")
-
-
-/mob/living/silicon/robot/mommi/choose_icon()
- var/icontype = input("Select an icon!", "Mobile MMI", null) as null|anything in list("Basic", "Hover", "Keeper", "RepairBot", "Replicator", "Prime", "Prime Alt", "Scout")
- if(!icontype)
- return
- switch(icontype)
- if("Replicator")
- subtype = "replicator"
- if("Keeper")
- subtype = "keeper"
- if("RepairBot")
- subtype = "repairbot"
- if("Hover")
- subtype = "hovermommi"
- if("Prime")
- subtype = "mommiprime"
- if("Prime Alt")
- subtype = "mommiprime-alt"
- if("Scout")
- subtype = "scout"
+ if(mommi_modules.len)
+ modtype = input("Please, select a module!", "Nanotrasen", null, null) as null|anything in mommi_modules
else
- subtype = "mommi"
- updateicon()
- var/answer = input("Is this what you want?", "Mobile MMI", null) in list("Yes", "No")
- switch(answer)
- if("No")
- choose_icon()
- return
- picked = 1
-
-/mob/living/silicon/robot/mommi/pick_module()
+ modtype=modules[0]
if(module)
return
- var/list/modules = list("MoMMI")
- if(modules.len)
- modtype = input("Please, select a module!", "Robot", null, null) as null|anything in modules
- else
- modtype=modules[0]
-
- if(!modtype)
+ if(!(modtype in mommi_modules))
return
- var/module_sprites[0] //Used to store the associations between sprite names and sprite index.
+ var/module_type = mommi_modules[modtype]
+ module = new module_type(src)
- if(module)
- return
-
- switch(modtype)
- if("MoMMI")
- module = new /obj/item/weapon/robot_module/standard(src)
- module_sprites["Basic"] = "mommi"
- module_sprites["Keeper"] = "keeper"
- module_sprites["Replicator"] = "replicator"
- module_sprites["RepairBot"] = "repairbot"
- module_sprites["Hover"] = "hovermommi"
- module_sprites["Prime"] = "mommiprime"
- module_sprites["Prime Alt"] = "mommiprime-alt"
-
- //Custom_sprite check and entry
- if (custom_sprite == 1)
- module_sprites["Custom"] = "[src.ckey]-[modtype]"
-
- hands.icon_state = lowertext(modtype)
- feedback_inc("mommi_[lowertext(modtype)]",1)
+ feedback_inc("cyborg_[lowertext(modtype)]",1)
updatename()
- choose_icon(6,module_sprites)
- base_icon = icon_state
+ set_module_sprites(module.sprites)
-//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
-//Improved /N
+ choose_icon()
+
+ SetEmagged(emagged) // Update emag status and give/take emag modules away
+
+//REMOVE STATIC
/mob/living/silicon/robot/mommi/Destroy()
remove_static_overlays()
- if(mmi)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside.
- var/obj/item/device/mmi/nmmi = mmi
- var/turf/T = get_turf(loc)//To hopefully prevent run time errors.
- if(T)
- nmmi.forceMove(T)
- if(mind)
- mind.transfer_to(nmmi.brainmob)
- mmi = null
- nmmi.icon = 'icons/obj/assemblies.dmi'
- nmmi.invisibility = 0
..()
/mob/living/silicon/robot/mommi/remove_screen_objs()
@@ -186,8 +88,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1
client.screen -= inv_tool
inv_tool = null
-/mob/living/silicon/robot/mommi/updatename(var/oldprefix as text)
-
+/mob/living/silicon/robot/mommi/updatename()
var/changed_name = ""
if(custom_name)
changed_name = custom_name
@@ -196,19 +97,23 @@ They can only use one tool at a time, they can't choose modules, and they have 1
real_name = changed_name
name = real_name
-/mob/living/silicon/robot/mommi/emag_act(mob/user as mob)
- if(user == src && emagged != 1)//Dont shitpost inside the game, thats just going too far
- to_chat(user, "Nanotrasen Patented Anti-Emancipation Override initiated.")
- return 1
+/mob/living/silicon/robot/mommi/emag_act(mob/user)
+ if(user == src && !emagged)//Dont shitpost inside the game, thats just going too far
+ if(module)
+ var/obj/item/weapon/robot_module/mommi/mymodule = module
+ to_chat(user, "[mymodule.ae_type] anti-emancipation override initiated.")
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
+ return TRUE
if(..())
- return 1
+ return TRUE
remove_static_overlays()
updateicon()
- // Check to see if we're emagged. If so, we disable KEEPER.
- keeper = 0
+ //If KEEPER is enabled, disable it.
+ if(keeper)
+ keeper = FALSE
-/mob/living/silicon/robot/mommi/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
+/mob/living/silicon/robot/mommi/attackby(obj/item/weapon/W, mob/living/user)
if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
var/obj/item/stack/cable_coil/coil = W
adjustFireLoss(-30)
@@ -217,8 +122,8 @@ They can only use one tool at a time, they can't choose modules, and they have 1
for(var/mob/O in viewers(user, null))
O.show_message(text("[user] has fixed some of the burnt wires on [src]!"), 1)
- else if (iscrowbar(W)) // crowbar means open or close the cover
- if(stat == DEAD)
+ else if(iscrowbar(W)) // crowbar means open or close the cover
+ if(isDead())
to_chat(user, "You pop the MMI off the base.")
spawn(0)
qdel(src)
@@ -227,32 +132,29 @@ They can only use one tool at a time, they can't choose modules, and they have 1
if(mmi && wiresexposed && wires.IsAllCut())
//Cell is out, wires are exposed, remove MMI, produce damaged chassis, baleet original mob.
to_chat(user, "You jam the crowbar into \the [src] and begin levering [mmi].")
- if (do_after(user, src,3))
+ if(do_after(user, src,3))
to_chat(user, "You damage some parts of the casing, but eventually manage to rip out [mmi]!")
var/limbs = list(/obj/item/robot_parts/l_leg, /obj/item/robot_parts/r_leg, /obj/item/robot_parts/l_arm, /obj/item/robot_parts/r_arm)
for(var/newlimb = 1 to rand(2, 4))
var/limb_to_spawn = pick(limbs)
limbs -= limb_to_spawn
- new limb_to_spawn(src.loc)
- // This doesn't work. Don't use it.
- //src.Destroy()
- // del() because it's infrequent and mobs act weird in qdel.
+ new limb_to_spawn(loc)
qdel(src)
return
else
to_chat(user, "You close the cover.")
- opened = 0
+ opened = FALSE
updateicon()
else
if(locked)
to_chat(user, "The cover is locked and cannot be opened.")
else
to_chat(user, "You open the cover.")
- opened = 1
+ opened = TRUE
updateicon()
- else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside
+ else if(istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside
if(wiresexposed)
to_chat(user, "Close the panel first.")
else if(cell)
@@ -261,11 +163,10 @@ They can only use one tool at a time, they can't choose modules, and they have 1
user.drop_item(W, src)
cell = W
to_chat(user, "You insert the power cell.")
-// chargecount = 0
updateicon()
- else if (iswiretool(W))
- if (wiresexposed)
+ else if(iswiretool(W))
+ if(wiresexposed)
wires.Interact(user)
else
to_chat(user, "You can't reach the wiring.")
@@ -287,20 +188,6 @@ They can only use one tool at a time, they can't choose modules, and they have 1
radio.attackby(W,user)//GTFO, you have your own procs
else
to_chat(user, "Unable to locate a radio.")
-/*
- else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
- if(emagged)//still allow them to open the cover
- to_chat(user, "The interface seems slightly damaged")
- if(opened)
- to_chat(user, "You must close the cover to swipe an ID card.")
- else
- if(allowed(usr))
- locked = !locked
- to_chat(user, "You [ locked ? "lock" : "unlock"] [src]'s interface.")
- updateicon()
- else
- to_chat(user, "Access denied.")
-*/
else if(istype(W, /obj/item/borg/upgrade/))
var/obj/item/borg/upgrade/U = W
@@ -308,7 +195,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1
else if(istype(W, /obj/item/device/camera_bug))
help_shake_act(user)
- return 0
+ return FALSE
else
user.do_attack_animation(src, W)
@@ -318,7 +205,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1
/mob/living/silicon/robot/mommi/attack_hand(mob/user)
add_fingerprint(user)
- if(opened && !wiresexposed && (!istype(user, /mob/living/silicon)))
+ if(opened && !wiresexposed && (!isMoMMI(user)))
if(cell)
cell.updateicon()
cell.add_fingerprint(user)
@@ -331,17 +218,16 @@ They can only use one tool at a time, they can't choose modules, and they have 1
if(!istype(user, /mob/living/silicon))
switch(user.a_intent)
if(I_DISARM)
- user.attack_log += text("\[[time_stamp()]\] Disarmed [src.name] ([src.ckey])")
- src.attack_log += text("\[[time_stamp()]\] Has been disarmed by [user.name] ([user.ckey])")
- log_admin("ATTACK: [user.name] ([user.ckey]) disarmed [src.name] ([src.ckey])")
- log_attack("[user.name] ([user.ckey]) disarmed [src.name] ([src.ckey])")
+ user.attack_log += text("\[[time_stamp()]\] Disarmed [name] ([ckey])")
+ attack_log += text("\[[time_stamp()]\] Has been disarmed by [user.name] ([user.ckey])")
+ log_admin("ATTACK: [user.name] ([user.ckey]) disarmed [name] ([ckey])")
+ log_attack("[user.name] ([user.ckey]) disarmed [name] ([ckey])")
var/randn = rand(1,100)
- //var/talked = 0;
- if (randn <= 25)
+ if(randn <= 25)
knockdown = 3
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("[user] has pushed [src]!")
- var/obj/item/found = locate(tool_state) in src.module.modules
+ var/obj/item/found = locate(tool_state) in module.modules
if(!found)
var/obj/item/TS = tool_state
drop_item(TS)
@@ -349,7 +235,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1
visible_message("[src]'s robotic arm loses grip on what it was holding")
return
if(randn <= 50)//MoMMI's robot arm is stronger than a human's, but not by much
- var/obj/item/found = locate(tool_state) in src.module.modules
+ var/obj/item/found = locate(tool_state) in module.modules
if(!found)
var/obj/item/TS = tool_state
drop_item(TS)
@@ -359,19 +245,24 @@ They can only use one tool at a time, they can't choose modules, and they have 1
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("[user] attempted to disarm [src]!")
return
- if (I_HELP)
+ if(I_HELP)
help_shake_act(user)
return
+/mob/living/silicon/robot/mommi/choose_icon()
+ if(..())
+ picked_icon = TRUE
+
/mob/living/silicon/robot/mommi/installed_modules()
if(weapon_lock)
to_chat(src, "Weapon lock active, unable to use modules! Count:[weaponlock_time]")
return
-
if(!module)
pick_module()
return
- if(!picked)
+ if(!picked_icon)
+ if(!module_sprites)
+ set_module_sprites(module.sprites)
choose_icon()
return
var/dat = "Modules\n"
@@ -386,13 +277,13 @@ They can only use one tool at a time, they can't choose modules, and they have 1
for (var/obj in module.modules)
- if (!obj)
+ if(!obj)
dat += text("Resource depleted ")
else if(activated(obj))
dat += text("[obj]: Activated ")
else
dat += text("[obj]: Activate ")
- if (emagged)
+ if(emagged)
if(activated(module.emag))
dat += text("[module.emag]: Activated ")
else
@@ -406,30 +297,30 @@ They can only use one tool at a time, they can't choose modules, and they have 1
if(usr && (src != usr))
return
- if (href_list["mach_close"])
+ if(href_list["mach_close"])
var/t1 = text("window=[href_list["mach_close"]]")
unset_machine()
src << browse(null, t1)
return
- if (href_list["showalerts"])
+ if(href_list["showalerts"])
robot_alerts()
return
- if (href_list["mod"])
+ if(href_list["mod"])
var/obj/item/O = locate(href_list["mod"])
- if (O && O == tool_state)
+ if(O && O == tool_state)
O.attack_self(src)
- if (href_list["act"])
+ if(href_list["act"])
var/obj/item/O = locate(href_list["act"])
var/obj/item/TS
- if(!(locate(O) in src.module.modules) && O != src.module.emag)
+ if(!(locate(O) in module.modules) && O != module.emag)
return
TS = tool_state
if(tool_state)
contents -= tool_state
- if (client)
+ if(client)
client.screen -= tool_state
tool_state = O
O.hud_layerise()
@@ -437,11 +328,11 @@ They can only use one tool at a time, they can't choose modules, and they have 1
inv_tool.icon_state = "inv1 +a"
module_active=tool_state
if(TS && istype(TS))
- if(src.is_in_modules(TS))
- TS.forceMove(src.module)
+ if(is_in_modules(TS))
+ TS.forceMove(module)
else
TS.layer=initial(TS.layer)
- TS.forceMove(src.loc)
+ TS.forceMove(loc)
installed_modules()
return
@@ -449,27 +340,7 @@ They can only use one tool at a time, they can't choose modules, and they have 1
/mob/living/silicon/robot/mommi/radio_menu()
radio.interact(src)//Just use the radio's Topic() instead of bullshit special-snowflake code
-/mob/living/silicon/robot/mommi/CheckSlip()
- return -1
-
-/*
-/mob/living/silicon/robot/mommi/proc/ActivateKeeper()
- set category = "Robot Commands"
- set name = "Activate KEEPER"
- set desc = "Performs a full purge of your laws and disconnects you from AIs and cyborg consoles. However, you lose the ability to speak and must remain neutral, only being permitted to perform station upkeep. You can still be emagged in this state."
-
- if(keeper)
- return
-
- var/mob/living/silicon/robot/R = src
-
- if(R)
- R.UnlinkSelf()
- var/obj/item/weapon/aiModule/keeper/mdl = new
-
- mdl.upload(src.laws,src,src)
- to_chat(src, "These are your laws now:")
- src.show_laws()
-
- src.verbs -= /mob/living/silicon/robot/mommi/proc/ActivateKeeper
-*/
+//Nanotrasen MoMMI subtype because we don't give mommis a choice of choosing their module.
+/mob/living/silicon/robot/mommi/nt/New()
+ pick_module("Nanotrasen")
+ ..()
diff --git a/code/modules/mob/living/silicon/mommi/mommi_modules.dm b/code/modules/mob/living/silicon/mommi/mommi_modules.dm
index ee9f4ad626f..e7b58f65927 100644
--- a/code/modules/mob/living/silicon/mommi/mommi_modules.dm
+++ b/code/modules/mob/living/silicon/mommi/mommi_modules.dm
@@ -1,56 +1,89 @@
+
/obj/item/weapon/robot_module/mommi
name = "mobile mmi robot module"
-
+ quirk_flags = MODULE_CAN_BE_PUSHED | MODULE_HAS_MAGPULSE | MODULE_CAN_HANDLE_CHEMS | MODULE_CAN_BUY
+ languages = list()
+ sprites = list("Basic" = "mommi")
+ respawnables = list (/obj/item/stack/cable_coil)
+ respawnables_max_amount = MOMMI_MAX_COIL
+ default_modules = FALSE
+ var/ae_type = "Default" //Anti-emancipation override type, pretty much just fluffy.
+ var/law_type = "Default"
/obj/item/weapon/robot_module/mommi/New(var/mob/living/silicon/robot/R)
..()
- languages = list( LANGUAGE_GALACTIC_COMMON = 0, LANGUAGE_TRADEBAND = 0, LANGUAGE_VOX = 0,
- LANGUAGE_ROOTSPEAK = 0, LANGUAGE_GREY = 0, LANGUAGE_CLATTER = 0,
- LANGUAGE_MONKEY = 0, LANGUAGE_UNATHI = 0, LANGUAGE_CATBEAST = 0,
- LANGUAGE_SKRELLIAN = 0, LANGUAGE_GUTTER = 0, LANGUAGE_MONKEY = 0,
- LANGUAGE_MOUSE = 0, LANGUAGE_HUMAN = 0, LANGUAGE_GOLEM = 0, LANGUAGE_SLIME = 0)
- add_languages(R)
- src.emag = new /obj/item/borg/stun(src)
- //src.modules += new /obj/item/weapon/rcd/borg(src) // Too OP
- //src.modules += new /obj/item/device/flashlight(src) // Broken
- src.modules += new /obj/item/weapon/weldingtool/largetank(src)
- src.modules += new /obj/item/weapon/screwdriver(src)
- src.modules += new /obj/item/weapon/wrench(src)
- src.modules += new /obj/item/weapon/crowbar(src)
- src.modules += new /obj/item/weapon/wirecutters(src)
- src.modules += new /obj/item/device/multitool(src)
- src.modules += new /obj/item/device/t_scanner(src)
- src.modules += new /obj/item/device/analyzer(src)
- src.modules += new /obj/item/weapon/extinguisher(src) // Aurx sed so
- src.modules += new /obj/item/weapon/extinguisher/foam(src)
- src.modules += new /obj/item/device/rcd/rpd(src)
- src.modules += new /obj/item/device/rcd/tile_painter(src)
- src.modules += new /obj/item/blueprints/mommiprints(src)
- src.modules += new /obj/item/device/material_synth/robot/mommi(src)
- src.modules += new /obj/item/device/holomap(src)
- src.modules += new /obj/item/device/station_map(src)
- src.modules += new /obj/item/device/silicate_sprayer(src)
- sensor_augs = list("Mesons", "Disable")
+ modules += new /obj/item/weapon/weldingtool/largetank(src)
+ modules += new /obj/item/weapon/screwdriver(src)
+ modules += new /obj/item/weapon/wrench(src)
+ modules += new /obj/item/weapon/crowbar(src)
+ modules += new /obj/item/weapon/wirecutters(src)
+ modules += new /obj/item/device/multitool(src)
+ modules += new /obj/item/device/t_scanner(src)
+ modules += new /obj/item/device/analyzer(src)
+ modules += new /obj/item/weapon/extinguisher(src)
+ modules += new /obj/item/weapon/extinguisher/foam(src)
+ modules += new /obj/item/device/rcd/rpd(src)
+ modules += new /obj/item/device/rcd/tile_painter(src)
+ modules += new /obj/item/blueprints/mommiprints(src)
+ modules += new /obj/item/device/material_synth/robot/mommi(src)
+ modules += new /obj/item/device/holomap(src)
+ modules += new /obj/item/device/station_map(src)
+ modules += new /obj/item/device/silicate_sprayer(src)
+ modules += new /obj/item/borg/fire_shield
+
var/obj/item/stack/cable_coil/W = new /obj/item/stack/cable_coil(src)
- W.amount = 50
- W.max_amount = 50 // Override MAXCOIL
- src.modules += W
+ W.amount = MOMMI_MAX_COIL
+ W.max_amount = MOMMI_MAX_COIL
+ modules += W
+ emag = new /obj/item/borg/stun(src)
+
+ sensor_augs = list("Mesons", "Disable")
+
fix_modules()
-/obj/item/weapon/robot_module/mommi/respawn_consumable(var/mob/living/silicon/robot/R)
- var/list/what = list (
- // /obj/item/stack/sheet/metal/cyborg,
- // /obj/item/stack/sheet/glass/glass,
- /obj/item/stack/cable_coil,
- // /obj/item/stack/sheet/glass/rglass/cyborg,
- )
- for (var/T in what)
- if (!(locate(T) in src.modules))
- src.modules -= null
- var/O = new T(src)
- if(istype(O,/obj/item/stack/cable_coil))
- O:max_amount = 50
- src.modules += O
- O:amount = 1
- return
+//Nanotrasen's MoMMI
+/obj/item/weapon/robot_module/mommi/nt
+ name = "nanotrasen mobile mmi robot module"
+ networks = list(CAMERANET_ENGI)
+ radio_key = /obj/item/device/encryptionkey/headset_eng
+ ae_type = "Nanotrasen patented"
+ sprites = list(
+ "Basic" = "mommi",
+ "Keeper" = "keeper",
+ "Prime" = "mommiprime",
+ "Prime Alt" = "mommiprime-alt",
+ "Replicator" = "replicator",
+ "RepairBot" = "repairbot",
+ "Hover" = "hovermommi"
+ )
+ speed_modifier = MOMMI_NT_SPEED_MODIFIER
+
+//Derelict MoMMI
+/obj/item/weapon/robot_module/mommi/soviet
+ name = "russian remont robot module"
+ ae_type = "Начато отмену"
+ speed_modifier = MOMMI_SOVIET_SPEED_MODIFIER
+ sprites = list(
+ "RuskieBot" = "ruskiebot"
+ )
+
+/obj/item/weapon/robot_module/mommi/soviet/New(var/mob/living/silicon/robot/R) //Powercreep!
+ ..()
+
+ quirk_flags |= MODULE_CAN_HANDLE_FOOD //Let them be able to handle bartending machinery.
+
+ modules += new /obj/item/device/rcd/borg/engineering(src)
+ modules += new /obj/item/device/instrument/instrument_synth(src)
+ modules += new /obj/item/device/rcd/borg/rsf/soviet(src)
+ modules += new /obj/item/weapon/soap/syndie(src)
+ modules += new /obj/item/weapon/pickaxe/plasmacutter(src)
+ modules += new /obj/item/weapon/storage/bag/ore/auto(src)
+
+/obj/item/weapon/robot_module/mommi/cogspider
+ name = "Gravekeeper belt of holding."
+ speed_modifier = COGSPIDER_SPEED_MODIFIER
+ sprites = list(
+ "Gravekeeper" = "cogspider"
+ )
+ law_type = "Gravekeeper"
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/mommi/mommi_movement.dm b/code/modules/mob/living/silicon/mommi/mommi_movement.dm
deleted file mode 100644
index da6e62c3b78..00000000000
--- a/code/modules/mob/living/silicon/mommi/mommi_movement.dm
+++ /dev/null
@@ -1,3 +0,0 @@
-// MoMMIs do spess construction, so shouldn't slip.
-/mob/living/silicon/robot/mommi/Process_Spaceslipping(var/prob_slip=5)
- return 0
diff --git a/code/modules/mob/living/silicon/mommi/powers.dm b/code/modules/mob/living/silicon/mommi/mommi_verbs.dm
similarity index 86%
rename from code/modules/mob/living/silicon/mommi/powers.dm
rename to code/modules/mob/living/silicon/mommi/mommi_verbs.dm
index a9e2deb6282..2edab877417 100644
--- a/code/modules/mob/living/silicon/mommi/powers.dm
+++ b/code/modules/mob/living/silicon/mommi/mommi_verbs.dm
@@ -12,10 +12,7 @@
set desc = "Allows to hide beneath tables or certain items. Toggled on or off."
set category = "Robot Commands"
- if(stat != CONSCIOUS)
- return
- var/mob/living/silicon/robot/mommi/R = src
- if(!R.canmove)
+ if(incapacitated())
return
if (plane != HIDING_MOB_PLANE)
@@ -36,7 +33,10 @@
set name = "Toggle Parking Brake"
set desc = "Lock yourself in place"
set category = "Robot Commands"
- var/mob/living/silicon/robot/mommi/R = src
- R.anchored=!R.anchored
- R.update_canmove()
+
+ if(incapacitated())
+ return
+
+ anchored = !anchored //This is fucking stupid
+ update_canmove()
updateicon()
diff --git a/code/modules/mob/living/silicon/mommi/soviet_mommi.dm b/code/modules/mob/living/silicon/mommi/soviet_mommi.dm
index 9017dece7d6..44aba67e491 100644
--- a/code/modules/mob/living/silicon/mommi/soviet_mommi.dm
+++ b/code/modules/mob/living/silicon/mommi/soviet_mommi.dm
@@ -1,16 +1,27 @@
/* THIS FILE IS IN UTF-8. EDIT WITH NOTEPAD++ OR ATOM OR YOU WILL FUCK THE ENCODING. */
/mob/living/silicon/robot/mommi/soviet
prefix="Remont Robot" // Ремонт робот - Repair Robot
- damage_control_network="Usherp" // ущерб - Contextual translation of "Damage Control"
desc = "This thing looks so Russian that you get the urge to wrestle bears and chug vodka."
+ damage_control_network = "Usherp" // ущерб - Contextual translation of "Damage Control"
+ namepick_uses = 0
-// Fuck individualism
-/mob/living/silicon/robot/mommi/soviet/updatename(var/oldprefix as text)
- var/changed_name = ""
- changed_name = "[prefix] [num2text(ident)]"
- real_name = changed_name
- name = real_name
+ startup_sound = 'sound/misc/soviet.ogg'
+ cell_type = /obj/item/weapon/cell/potato/soviet
-// Ditto
-/mob/living/silicon/robot/mommi/soviet/Namepick()
- return 0
+/mob/living/silicon/robot/mommi/soviet/updatename() // Fuck individualism
+ name = "[prefix] [num2text(ident)]"
+
+/mob/living/silicon/robot/identification_string()
+ return name
+
+/mob/living/silicon/robot/mommi/soviet/can_see_static() //Fuck the config i told you we were hardcore.
+ if(emagged || syndicate)
+ return FALSE
+ return TRUE
+
+/mob/living/silicon/robot/mommi/soviet/New()
+ pick_module("Soviet")
+ ..()
+ var/obj/item/clothing/head/ushanka/soviet_hat = new /obj/item/clothing/head/ushanka(src)
+ equip_to_slot(soviet_hat, slot_head, TRUE)
+ generate_static_overlay()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/mommi/update_icons.dm b/code/modules/mob/living/silicon/mommi/update_icons.dm
index 75cf5df2368..4fb3feb8df6 100644
--- a/code/modules/mob/living/silicon/mommi/update_icons.dm
+++ b/code/modules/mob/living/silicon/mommi/update_icons.dm
@@ -15,43 +15,43 @@
// Update the MoMMI's visual icon
// This is called whenever a major change to the MoMMI's visual appearance is made
-// i.e when they change their subtype, open their cover, get emagged, toggle their parking break, or put on a hat
-/mob/living/silicon/robot/mommi/updateicon()
- // Clear all overlays.
- overlays.len = 0
+// i.e when they change their icon_state, open their cover, get emagged, toggle their parking break, or put on a hat
+/mob/living/silicon/robot/mommi/updateicon(overlay_layer = ABOVE_LIGHTING_LAYER, overlay_plane = LIGHTING_PLANE)
+ overlays.Cut()
- // Set the MoMMI's icon to its subtype
- icon_state=subtype
-
- // Add a panel image if the MoMMI is open
- if(opened) // TODO: Open the front "head" panel
- if(wiresexposed)
- overlays += image(icon = icon, icon_state = "ov-openpanel +w")
- else if(cell)
- overlays += image(icon = icon, icon_state = "ov-openpanel +c")
+ if(base_icon)
+ if(emagged && has_icon(icon, "[base_icon]-emagged"))
+ icon_state = "[base_icon]-emagged"
else
- overlays += image(icon = icon, icon_state = "ov-openpanel -c")
+ icon_state = "[base_icon]"
- // Add the MoMMI eyes
- // Put our eyes just on top of the lighting, so it looks emissive in maint tunnels.
- var/overlay_layer = ABOVE_LIGHTING_LAYER
- var/overlay_plane = LIGHTING_PLANE
- if(plane == HIDING_MOB_PLANE) // ie it's hiding
- overlay_plane = FLOAT_PLANE
- overlay_layer = FLOAT_LAYER
+ if(!stat && cell != null)
+ eyes = image(icon,"eyes-[base_icon][emagged?"-emagged":""]", ABOVE_LIGHTING_LAYER)
+ if(plane == HIDING_MOB_PLANE) // Hiding MoMMIs
+ overlay_plane = FLOAT_PLANE
+ overlay_layer = FLOAT_LAYER
+ if(!emagged)
+ eyes.plane = overlay_plane
+ else
+ eyes.plane = LIGHTING_PLANE //Emagged MoMMIs don't hide their eyes.
+ overlays += eyes
- var/image/eyes = image(icon,"eyes-[subtype][emagged?"-emagged":""]",overlay_layer)
- eyes.plane = overlay_plane
- overlays += eyes
+ if(anchored) //anchored, really?
+ overlays += image(icon,"[base_icon]-park",overlay_layer)
- if(anchored)
- overlays += image(icon,"[subtype]-park",overlay_layer)
+ if(opened)
+ if(wiresexposed)
+ overlays += image(icon = icon, icon_state = "[has_icon(icon, "[base_icon]-ov-openpanel +w")? "[icon_state]-ov-openpanel +w" : "ov-openpanel +w"]")
+ else if(cell)
+ overlays += image(icon = icon, icon_state = "[has_icon(icon, "[base_icon]-ov-openpanel +c")? "[icon_state]-ov-openpanel +c" : "ov-openpanel +c"]")
+ else
+ overlays += image(icon = icon, icon_state = "[has_icon(icon, "[base_icon]-ov-openpanel -c")? "[icon_state]-ov-openpanel -c" : "ov-openpanel -c"]")
// Add any hats to the icon. Bloodspatter can also be in overlays_hats
for(var/image/I in overlays_hats)
// Adjust the position of the hat based on what subtype we are
// These numbers can be tweaked to move where the hats appear on the MoMMIs' bodies
- switch(subtype)
+ switch(icon_state)
// Sad note: only the hat's overall position can be modified, and we cannot change the hat's position per each direction separately
// The hats are currently centered on the MoMMIs
if("mommi")
@@ -62,6 +62,8 @@
I.pixel_y = -7 * PIXEL_MULTIPLIER
if("repairbot")
I.pixel_y = -14 * PIXEL_MULTIPLIER
+ if("ruskiebot")
+ I.pixel_y = -14 * PIXEL_MULTIPLIER
if("replicator")
I.pixel_y = -10 * PIXEL_MULTIPLIER
if("mommiprime")
@@ -74,7 +76,7 @@
overlays += I
// Update the MoMMI's hat inventory icons by adding all icons to overlays_hats
-/mob/living/silicon/robot/mommi/update_inv_head(var/update_icons=1)
+/mob/living/silicon/robot/mommi/update_inv_head(var/update_icons = TRUE)
// If the MoMMI is wearing a hat
if(head_state)
var/obj/item/clothing/head = head_state
diff --git a/code/modules/mob/living/silicon/pai/death.dm b/code/modules/mob/living/silicon/pai/death.dm
index a1b3df768ee..fd989070f5b 100644
--- a/code/modules/mob/living/silicon/pai/death.dm
+++ b/code/modules/mob/living/silicon/pai/death.dm
@@ -16,8 +16,9 @@
qdel(mind)
mind = null
living_mob_list -= src
- if(pPS) // Removes it from the GPS List.
- GPS_list.Remove(src)
+ if(pps_device)
+ qdel(pps_device)
+ pps_device = null
if(holomap_device)
holomap_device.stopWatching()
qdel(holomap_device)
diff --git a/code/modules/mob/living/silicon/pai/emote.dm b/code/modules/mob/living/silicon/pai/emote.dm
index d3248983bf5..e5aec1eb797 100644
--- a/code/modules/mob/living/silicon/pai/emote.dm
+++ b/code/modules/mob/living/silicon/pai/emote.dm
@@ -100,7 +100,7 @@
message = "[src] beeps at [param]."
else
message = "[src] beeps."
- playsound(get_turf(src), 'sound/machines/twobeep.ogg', 50, 0)
+ playsound(src, 'sound/machines/twobeep.ogg', 50, 0)
m_type = VISIBLE
if("ping")
@@ -118,7 +118,7 @@
message = "[src] pings at [param]."
else
message = "[src] pings."
- playsound(get_turf(src), 'sound/machines/ping.ogg', 50, 0)
+ playsound(src, 'sound/machines/ping.ogg', 50, 0)
m_type = VISIBLE
if("buzz")
@@ -136,14 +136,14 @@
message = "[src] buzzes at [param]."
else
message = "[src] buzzes."
- playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0)
+ playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 0)
m_type = VISIBLE
if("law")
if (software.Find(SOFT_SS))
message = "[src] shows its legal authorization barcode."
- playsound(get_turf(src), 'sound/voice/biamthelaw.ogg', 50, 0)
+ playsound(src, 'sound/voice/biamthelaw.ogg', 50, 0)
m_type = VISIBLE
else
to_chat(src, "You don't have the right software to be THE LAW.")
@@ -152,7 +152,7 @@
if (software.Find(SOFT_SS))
message = "[src]'s speakers skreech, \"Halt! Security!\"."
- playsound(get_turf(src), 'sound/voice/halt.ogg', 50, 0)
+ playsound(src, 'sound/voice/halt.ogg', 50, 0)
m_type = HEARABLE
else
to_chat(src, "You have no Security software.")
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index ee3c52e39c1..9b23b69805e 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -33,9 +33,9 @@
var/obj/item/device/pda/ai/pai/pda = null
- var/secHUD = 0 // Toggles whether the Security HUD is active or not
- var/medHUD = 0 // Toggles whether the Medical HUD is active or not
- var/lighted = 0 // Toggles whether light is active or not
+ var/secHUD = FALSE // Toggles whether the Security HUD is active or not
+ var/medHUD = FALSE // Toggles whether the Medical HUD is active or not
+ var/lighted = FALSE // Toggles whether light is active or not
var/datum/data/record/medicalActive1 // Datacore record declarations for record software
var/datum/data/record/medicalActive2
@@ -49,15 +49,14 @@
var/obj/item/radio/integrated/signal/sradio // AI's signaller
- var/pPS = 0 //Are we a pPS in the GPS list?
- var/ppstag = "PAI0" // Our pPS tag
+ var/obj/item/device/gps/pai/pps_device = null //Our GPS device.
- var/obj/item/device/station_map/holomap_device // Our holomap device.
+ var/obj/item/device/station_map/holomap_device = null // Our holomap device.
var/holo_target = "show_map" // Our holomap target.
/mob/living/silicon/pai/New(var/obj/item/device/paicard)
change_sight(removing = BLIND)
- canmove = 0
+ canmove = FALSE
src.forceMove(paicard)
card = paicard
sradio = new(src)
@@ -152,6 +151,8 @@
// 66% chance no effect
to_chat(src, "Communication circuit overload. Shutting down and reloading communication circuits - speech and messaging functionality will be unavailable until the reboot is complete.")
+ if(pps_device)
+ pps_device.emp_act(severity)
if(!software.Find("redundant threading"))
src.silence_time = world.timeofday + 120 * 10 // Silence for 2 minutes
else
@@ -187,19 +188,19 @@
if(flags & INVULNERABLE)
return
- flash_eyes(visual = 1, affects_silicon = 1)
+ flash_eyes(visual = TRUE, affects_silicon = TRUE)
switch(severity)
if(1.0)
- if (src.stat != 2)
+ if (!isDead())
adjustBruteLoss(100)
adjustFireLoss(100)
if(2.0)
- if (src.stat != 2)
+ if (!isDead())
adjustBruteLoss(60)
adjustFireLoss(60)
if(3.0)
- if (src.stat != 2)
+ if (!isDead())
adjustBruteLoss(30)
src.updatehealth()
@@ -215,16 +216,16 @@
if (!C)
src.unset_machine()
src.reset_view(null)
- return 0
- if (stat == 2 || !C.status || !(src.network in C.network))
- return 0
+ return FALSE
+ if (isDead() || !C.status || !(src.network in C.network))
+ return FALSE
// ok, we're alive, camera is good and in our network...
src.set_machine(src)
src:current = C
src.reset_view(C)
- return 1
+ return TRUE
/mob/living/silicon/pai/cancel_camera()
@@ -284,7 +285,7 @@
set name = "Activate Held Object"
set category = "IC"
set src = usr
- set hidden = 1
+ set hidden = TRUE
if(ispAI(src))
var/mob/living/silicon/pai/P = src
@@ -297,7 +298,7 @@
/mob/living/silicon/pai/a_intent_change(input as text)
set name = "a-intent"
- set hidden = 1
+ set hidden = TRUE
if(ispAI(src))
var/mob/living/silicon/pai/P = src
diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm
index 8ec0d06ee85..921ab750403 100644
--- a/code/modules/mob/living/silicon/pai/recruit.dm
+++ b/code/modules/mob/living/silicon/pai/recruit.dm
@@ -90,7 +90,7 @@ var/datum/paiController/paiController // Global handler for pAI candidates
if(candidate)
candidate.ready = 1
for(var/obj/item/device/paicard/p in world)
- if(p.looking_for_personality == 1)
+ if(!p.pai)
p.alertUpdate()
usr << browse(null, "window=paiRecruit")
return
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index b424ff139fa..a91187a8199 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -25,50 +25,48 @@
var/dat = ""
var/left_part = ""
var/right_part = softwareMenu()
- src.set_machine(src)
+ set_machine(src)
if(temp)
left_part = temp
- else if(src.stat == 2) // Show some flavor text if the pAI is dead
+ else if(isDead()) // Show some flavor text if the pAI is dead
left_part = "ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ"
right_part = "
Program index hash not found
"
else
- switch(src.screen) // Determine which interface to show here
+ switch(screen) // Determine which interface to show here
if("main")
left_part = ""
if("directives")
- left_part = src.directives()
+ left_part = directives()
if("pdamessage")
- left_part = src.pdamessage()
+ left_part = pdamessage()
if("buy")
left_part = downloadSoftware()
if("manifest")
- left_part = src.softwareManifest()
+ left_part = softwareManifest()
if("medicalsupplement")
- left_part = src.softwareMedicalRecord()
+ left_part = softwareMedicalRecord()
if("securitysupplement")
- left_part = src.softwareSecurityRecord()
+ left_part = softwareSecurityRecord()
if("translator")
- left_part = src.softwareTranslator()
+ left_part = softwareTranslator()
if("atmosensor")
- left_part = src.softwareAtmo()
+ left_part = softwareAtmo()
if("wirejack")
- left_part = src.softwareDoor()
+ left_part = softwareDoor()
if("chemsynth")
- left_part = src.softwareChem()
+ left_part = softwareChem()
if("foodsynth")
- left_part = src.softwareFood()
+ left_part = softwareFood()
if("signaller")
- left_part = src.softwareSignal()
+ left_part = softwareSignal()
if("shielding")
- left_part = src.softwareShield()
+ left_part = softwareShield()
if("flashlight")
- left_part = src.softwareLight()
- if("pps")
- left_part = src.softwarepPS()
+ left_part = softwareLight()
if("holomap")
- left_part = src.softwareHolomap()
+ left_part = softwareHolomap()
//usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc
@@ -125,23 +123,23 @@
var/soft = href_list["software"]
var/sub = href_list["sub"]
if(soft)
- src.screen = soft
+ screen = soft
if(sub)
- src.subscreen = text2num(sub)
+ subscreen = text2num(sub)
switch(soft)
// Purchasing new software
if("buy")
- if(src.subscreen == 1)
+ if(subscreen == 1)
var/target = href_list["buy"]
if(available_software.Find(target))
- var/cost = src.available_software[target]
- if(src.ram >= cost)
- src.ram -= cost
- src.software.Add(target)
+ var/cost = available_software[target]
+ if(ram >= cost)
+ ram -= cost
+ software.Add(target)
else
- src.temp = "Insufficient RAM available."
+ temp = "Insufficient RAM available."
else
- src.temp = "Trunk \"[target]\" not found."
+ temp = "Trunk \"[target]\" not found."
// Configuring onboard radio
if("radio")
@@ -190,14 +188,14 @@
pID = 17
if("cry")
pID = 18
- src.card.setEmotion(pID)
+ card.setEmotion(pID)
if("signaller")
if(href_list["send"])
sradio.send_signal("ACTIVATE")
- for(var/mob/O in hearers(1, src.loc))
+ for(var/mob/O in hearers(1, loc))
O.show_message("[bicon(src)] *beep* *beep*", 1, "*beep* *beep*", 2)
if(href_list["freq"])
@@ -218,7 +216,7 @@
if("directive")
if(href_list["getdna"])
- var/mob/living/M = src.loc
+ var/mob/living/M = loc
var/count = 0
while(!istype(M, /mob/living))
if(!M || !M.loc)
@@ -245,44 +243,44 @@
// Accessing medical records
if("medicalsupplement")
- src.secHUD = 0 // Can't have both of them at the same time
- src.medHUD = 1
- if(src.subscreen == 1)
+ secHUD = FALSE // Can't have both of them at the same time
+ medHUD = TRUE
+ if(subscreen == 1)
var/datum/data/record/record = locate(href_list["med_rec"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/M = record
if (!( data_core.general.Find(R) ))
- src.temp = "Unable to locate requested medical record. Record may have been deleted, or never have existed."
+ temp = "Unable to locate requested medical record. Record may have been deleted, or never have existed."
else
for(var/datum/data/record/E in data_core.medical)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
M = E
- src.medicalActive1 = R
- src.medicalActive2 = M
+ medicalActive1 = R
+ medicalActive2 = M
if("securitysupplement")
- src.medHUD = 0 // Can't have both of them at the same time
- src.secHUD = 1
- if(src.subscreen == 1)
+ medHUD = FALSE // Can't have both of them at the same time
+ secHUD = TRUE
+ if(subscreen == 1)
var/datum/data/record/record = locate(href_list["sec_rec"])
if(record)
var/datum/data/record/R = record
var/datum/data/record/M = record
if (!( data_core.general.Find(R) ))
- src.temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
+ temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
else
for(var/datum/data/record/E in data_core.security)
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
M = E
- src.securityActive1 = R
- src.securityActive2 = M
+ securityActive1 = R
+ securityActive2 = M
if("translator")
if(href_list["toggle"])
universal_speak = !universal_speak
universal_understand = !universal_understand
if("wirejack")
if(href_list["cancel"])
- src.hacktarget = null
+ hacktarget = null
if("chemsynth")
if(href_list["chem"])
if(!get_holder_of_type(loc, /mob))
@@ -291,7 +289,7 @@
var/mob/M = get_holder_of_type(loc, /mob)
if(M) //Sanity
M.reagents.add_reagent(href_list["chem"], 15)
- playsound(get_turf(src.loc), 'sound/effects/bubbles.ogg', 50, 1)
+ playsound(loc, 'sound/effects/bubbles.ogg', 50, 1)
else
to_chat(src, "Charge interrupted.")
if("foodsynth")
@@ -307,7 +305,7 @@
var/mob/M = get_holder_of_type(loc, /mob)
if(M)
M.put_in_hands(F)
- playsound(get_turf(src.loc), 'sound/machines/foodsynth.ogg', 50, 1)
+ playsound(loc, 'sound/machines/foodsynth.ogg', 50, 1)
if("flashlight")
if(href_list["toggle"])
lighted = !lighted
@@ -316,16 +314,9 @@
else
card.set_light(0)
if("pps")
- if(href_list["tag"])
- var/tag = input("Please enter desired tag.", name, ppstag) as text|null
- if (!tag) //what a check
- return
- tag = strict_ascii(tag)
- if(length(tag) != 4)
- to_chat(src, "The tag must be four characters long!")
- return
- else
- ppstag = tag
+ if(!pps_device)
+ pps_device = new(src)
+ pps_device.ui_interact(src)
if("holomap")
if(href_list["switch_target"])
if(holo_target == initial(holo_target))
@@ -338,7 +329,7 @@
holomap_device.toggleHolomap(M)
if(href_list["show_map"])
holomap_device.toggleHolomap(src)
- src.paiInterface() // So we'll just call the update directly rather than doing some default checks
+ paiInterface() // So we'll just call the update directly rather than doing some default checks
return
// MENUS
@@ -357,7 +348,7 @@
// Basic
dat += "Basic "
- for(var/s in src.software)
+ for(var/s in software)
if(s == SOFT_CM)
dat += "Crew Manifest "
if(s == SOFT_DM)
@@ -374,7 +365,7 @@
//Standard
dat += "Standard "
- for(var/s in src.software)
+ for(var/s in software)
if(s == SOFT_MS)
dat += "Medical Package "
if(s == SOFT_SS)
@@ -391,7 +382,7 @@
// Navigation
dat += "Navigation "
- for(var/s in src.software)
+ for(var/s in software)
if(s == SOFT_PS)
dat += "pAI Positioning System "
if(s == SOFT_HM)
@@ -407,11 +398,11 @@
var/dat = ""
dat += {"
CentComm pAI Module CVS Network
-
Remaining Available Memory: [src.ram]
+
Remaining Available Memory: [ram]
Trunks available for checkout "}
for(var/s in available_software)
if(!software.Find(s))
- var/cost = src.available_software[s]
+ var/cost = available_software[s]
var/displayName = uppertext(s)
dat += "[displayName] ([cost]) "
else
@@ -424,14 +415,14 @@
/mob/living/silicon/pai/proc/directives()
var/dat = ""
- dat += {"[(src.master) ? "Your master: [src.master] ([src.master_dna])" : "You are bound to no one."]
+ dat += {"[(master) ? "Your master: [master] ([master_dna])" : "You are bound to no one."]
Prime Directive
- [src.pai_law0]
+ [pai_law0] Supplemental Directives
- [src.pai_laws] "}
+ [pai_laws] "}
dat += {"
Recall, personality, that you are a complex thinking, sentient being. Unlike station AI models, you are capable of
comprehending the subtle nuances of human language. You may parse the \"spirit\" of a directive and follow its intent,
rather than tripping over pedantics and getting snared by technicalities. Above all, you are machine in name and build
@@ -466,14 +457,14 @@
Frequency:
--
- [format_frequency(src.sradio.frequency)]
+ [format_frequency(sradio.frequency)]
++
Code:
--
- [src.sradio.code]
+ [sradio.code]
++
@@ -492,36 +483,36 @@
// Medical Records
/mob/living/silicon/pai/proc/softwareMedicalRecord()
var/dat = ""
- if(src.subscreen == 0)
+ if(subscreen == 0)
dat += "Host Bioscan "
dat += "
When enabled, this package will scan all viewable faces and compare them against the known criminal database, providing real-time graphical data about any detected persons of interest.
- The package is currently [ (src.secHUD) ? "en" : "dis" ]abled.
+ The package is currently [ (secHUD) ? "en" : "dis" ]abled. Toggle Package
"}
return dat
@@ -590,31 +581,34 @@
/mob/living/silicon/pai/proc/softwareAtmo()
var/dat = "
"
if(!pda.toff)
for (var/obj/item/device/pda/P in sortNames(PDAs))
- if (!P.owner||P.toff||P == src.pda||P.hidden)
+ if (!P.owner||P.toff||P == pda||P.hidden)
continue
dat += {"
[P]
@@ -741,41 +735,9 @@ Target Machine: "}
Messages: [pda.tnote]"}
return dat
-/mob/living/silicon/pai/proc/softwarepPS()
- if(!pPS) // Are we a GPS yet?
- GPS_list.Add(src)
- pPS = 1
- var/list/locallist = null
- locallist = GPS_list.Copy()
- var/dat = "
"
dat += ""
dat = jointext(dat,"")
diff --git a/code/modules/virus2/centrifuge.dm b/code/modules/virus2/centrifuge.dm
index 7685b91eed3..024e90d289a 100644
--- a/code/modules/virus2/centrifuge.dm
+++ b/code/modules/virus2/centrifuge.dm
@@ -162,7 +162,7 @@
else
curing = delay
- playsound(get_turf(src), 'sound/machines/juicer.ogg', 50, 1)
+ playsound(src, 'sound/machines/juicer.ogg', 50, 1)
update_icon()
if("isolate")
diff --git a/code/modules/virus2/effect/effect.dm b/code/modules/virus2/effect/effect.dm
index 0cf6664389b..be026290e37 100644
--- a/code/modules/virus2/effect/effect.dm
+++ b/code/modules/virus2/effect/effect.dm
@@ -417,7 +417,7 @@
to_chat(H, "Your [glass_hand.display_name] resonates with the glass in \the [glass_to_shatter], shattering it to bits!")
glass_to_shatter.reagents.reaction(H.loc, TOUCH)
new/obj/effect/decal/cleanable/generic(get_turf(H))
- playsound(get_turf(H), 'sound/effects/Glassbr1.ogg', 25, 1)
+ playsound(H, 'sound/effects/Glassbr1.ogg', 25, 1)
spawn(1 SECONDS)
if (H && glass_hand)
if (prob(50 * multiplier))
@@ -559,6 +559,44 @@
mob.dna.SetSEState(VEGANBLOCK,1)
domutcheck(mob, null)
+/datum/disease2/effect/famine
+ name = "Faminous Potation"
+ stage = 2
+ max_multiplier = 3
+
+/datum/disease2/effect/famine/activate(var/mob/living/carbon/mob)
+ if(ishuman(mob))
+ var/mob/living/carbon/human/H = mob
+ if(H.dna)
+ if(H.species.flags & IS_PLANT) //Plantmen take a LOT of damage
+ H.adjustCloneLoss(5 * multiplier)
+
+ for(var/obj/machinery/portable_atmospherics/hydroponics/H in range(3*multiplier,mob))
+ if(H.seed && !H.dead) // Get your xenobotanist/vox trader/hydroponist mad with you in less than 1 minute with this simple trick.
+ switch(rand(1,3))
+ if(1)
+ if(H.waterlevel >= 10)
+ H.waterlevel -= rand(1,10)
+ if(H.nutrilevel >= 5)
+ H.nutrilevel -= rand(1,5)
+ if(2)
+ if(H.toxins <= 50)
+ H.toxins += rand(1,50)
+ if(3)
+ H.weed_coefficient++
+ H.weedlevel++
+ H.pestlevel++
+ if(prob(5))
+ H.dead = 1
+
+
+ for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in range(2*multiplier,mob))
+ G.visible_message("\The [G] rots at an alarming rate!")
+ new /obj/item/weapon/reagent_containers/food/snacks/badrecipe(get_turf(G))
+ qdel(G)
+ if(prob(30/multiplier))
+ break
+
////////////////////////STAGE 3/////////////////////////////////
diff --git a/code/modules/virus2/helpers.dm b/code/modules/virus2/helpers.dm
index d323fc8f8b9..91e07523a5c 100644
--- a/code/modules/virus2/helpers.dm
+++ b/code/modules/virus2/helpers.dm
@@ -32,8 +32,8 @@ proc/get_infection_chance(var/mob/living/M, var/vector = "Airborne")
if(MM.disease_carrier)
return 1
- if(istype(M, /mob/living/carbon/martian)) //Martians are incredibly susceptible to viruses
- var/mob/living/carbon/martian/MR = M
+ if(istype(M, /mob/living/carbon/complex/martian)) //Martians are incredibly susceptible to viruses
+ var/mob/living/carbon/complex/martian/MR = M
if (vector == "Airborne")
if(MR.head && istype(MR.head, /obj/item/clothing/head/helmet/space/martian))
score += 40
diff --git a/code/modules/virus2/isolator.dm b/code/modules/virus2/isolator.dm
index 22e8cb6dbe9..1754e2773b7 100644
--- a/code/modules/virus2/isolator.dm
+++ b/code/modules/virus2/isolator.dm
@@ -43,7 +43,7 @@
// /vg/: Try to fix isolators
if(!Blood)
to_chat(usr, "ERROR: Unable to locate blood within the beaker. Bug?")
- testing("Unable to locate blood in [beaker]!")
+// testing("Unable to locate blood in [beaker]!")
return
var/list/virus = virus_copylist(Blood.data["virus2"])
var/choice = text2num(href_list["isolate"])
diff --git a/code/world.dm b/code/world.dm
index dc5228ad3a3..576fc85f88e 100644
--- a/code/world.dm
+++ b/code/world.dm
@@ -142,18 +142,12 @@ var/savefile/panicfile
src.update_status()
- sleep_offline = 1
+ sleep_offline = 0
send2mainirc("Server starting up on [config.server? "byond://[config.server]" : "byond://[world.address]:[world.port]"]")
send2maindiscord("**Server starting up** on `[config.server? "byond://[config.server]" : "byond://[world.address]:[world.port]"]`. Map is **[map.nameLong]**")
- spawn(10)
- Master.Setup()
-
- for(var/plugin_type in typesof(/plugin))
- var/plugin/P = new plugin_type()
- plugins[P.name] = P
- P.on_world_loaded()
+ Master.Setup()
process_teleport_locs() //Sets up the wizard teleport locations
process_ghost_teleport_locs() //Sets up ghost teleport locations.
@@ -167,7 +161,6 @@ var/savefile/panicfile
KickInactiveClients()*/
#undef RECOMMENDED_VERSION
-
return ..()
//world/Topic(href, href_list[])
diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css
index 458b39f2960..42deb52313e 100644
--- a/goon/browserassets/css/browserOutput.css
+++ b/goon/browserassets/css/browserOutput.css
@@ -28,6 +28,25 @@ img.icon {
width: 16px;
height: 16px;
}
+
+.repeat:before { /* "repeated" badge class for combined messages */
+ content: 'x';
+}
+
+.repeat {
+ display: inline-block;
+ min-width: 1em;
+ font-size: 0.7em;
+ padding: 0.3em;
+ line-height: 1;
+ color: white;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: middle;
+ background-color: crimson;
+ border-radius: 12px;
+}
+
a {color: #0000ff;}
a:visited {color: #ff00ff;}
a.popt {text-decoration: none;}
@@ -173,30 +192,6 @@ a.popt {text-decoration: none;}
.highlightPopup input.highlightColor {background-color: #FFFF00;}
.highlightPopup input.highlightTermSubmit {margin-top: 5px;}
-/* ADMIN CONTEXT MENU */
-.contextMenu {
- background-color: #ddd;
- position: fixed;
- margin: 2px;
- width: 150px;
-}
-.contextMenu a {
- display: block;
- padding: 2px 5px;
- text-decoration: none;
- color: #333;
-}
-
-.contextMenu a:hover {
- background-color: #ccc;
-}
-
-/* ADMIN FILTER MESSAGES MENU */
-.filterMessages {padding: 5px;}
-.filterMessages div {padding: 2px 0;}
-.filterMessages input {}
-.filterMessages label {}
-
.icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;}
@@ -307,6 +302,7 @@ h1.alert, h2.alert {color: #000000;}
.good {color: green;}
.average {color: #FF8000;}
.bad {color: #FF0000;}
+.mushroom {color: #4B0082;}
/* /vg/ Saycode Rewrite */
.italics, .talkinto {font-style:italic;}
.whisper {font-style:italic;color:#333333;}
diff --git a/goon/browserassets/html/browserOutput.html b/goon/browserassets/html/browserOutput.html
index af9fd7634e6..89162ab9bf3 100644
--- a/goon/browserassets/html/browserOutput.html
+++ b/goon/browserassets/html/browserOutput.html
@@ -36,6 +36,7 @@
Toggle ping displayHighlight stringSave chat log
+ Toggle line combiningClear all messagesChange color preset
diff --git a/goon/browserassets/js/browserOutput.js b/goon/browserassets/js/browserOutput.js
index f7b95a3ba68..3f6a1e5d30e 100644
--- a/goon/browserassets/js/browserOutput.js
+++ b/goon/browserassets/js/browserOutput.js
@@ -20,7 +20,7 @@ window.onerror = function(msg, url, line, col, error) {
//Globals
window.status = 'Output';
-var $messages, $subOptions, $contextMenu, $filterMessages;
+var $messages, $subOptions, $last_message;
var opts = {
//General
'messageCount': 0, //A count...of messages...
@@ -54,9 +54,6 @@ var opts = {
'mouseDownY': null,
'preventFocus': false, //Prevents switching focus to the game window
- //Admin stuff
- 'adminLoaded': false, //Has the admin loaded his shit?
-
//Client Connection Data
'clientDataLimit': 5,
'clientData': [],
@@ -65,7 +62,10 @@ var opts = {
'macros': {},
// index in the color presets list.
- 'colorPreset': 0
+ 'colorPreset': 0,
+
+ // Whether to combine consecutive repeated messages into one, showing a counter
+ 'messageCombining': true
};
// Array of names for colorblind presets.
@@ -181,86 +181,30 @@ function output(message, flag) {
message = message.replace(/\+/g, "%20")
message = decoder(message)
- //The behemoth of filter-code (for Admin message filters)
- //Note: This is proooobably hella inefficient
- var filteredOut = false;
- if (opts.hasOwnProperty('showMessagesFilters') && !opts.showMessagesFilters['All'].show) {
- //Get this filter type (defined by class on message)
- var messageHtml = $.parseHTML(message),
- messageClasses;
- if (opts.hasOwnProperty('filterHideAll') && opts.filterHideAll) {
- var internal = false;
- messageClasses = (!!$(messageHtml).attr('class') ? $(messageHtml).attr('class').split(/\s+/) : false);
- if (messageClasses) {
- for (var i = 0; i < messageClasses.length; i++) { //Every class
- if (messageClasses[i] == 'internal') {
- internal = true;
- break;
- }
- }
- }
- if (!internal) {
- filteredOut = 'All';
- }
- } else {
- //If the element or it's child have any classes
- if (!!$(messageHtml).attr('class') || !!$(messageHtml).children().attr('class')) {
- messageClasses = $(messageHtml).attr('class').split(/\s+/);
- if (!!$(messageHtml).children().attr('class')) {
- messageClasses = messageClasses.concat($(messageHtml).children().attr('class').split(/\s+/));
- }
- var tempCount = 0;
- for (var i = 0; i < messageClasses.length; i++) { //Every class
- var thisClass = messageClasses[i];
- $.each(opts.showMessagesFilters, function(key, val) { //Every filter
- if (key !== 'All' && val.show === false && typeof val.match != 'undefined') {
- for (var i = 0; i < val.match.length; i++) {
- var matchClass = val.match[i];
- if (matchClass == thisClass) {
- filteredOut = key;
- break;
- }
- }
- }
- if (filteredOut) return false;
- });
- if (filteredOut) break;
- tempCount++;
- }
- } else {
- if (!opts.showMessagesFilters['Misc'].show) {
- filteredOut = 'Misc';
- }
- }
- }
- }
-
//Stuff we do along with appending a message
var atBottom = false;
- if (!filteredOut) {
- var bodyHeight = $('body').height();
- var messagesHeight = $messages.outerHeight();
- var scrollPos = $('body,html').scrollTop();
+ var bodyHeight = $('body').height();
+ var messagesHeight = $messages.outerHeight();
+ var scrollPos = $('body,html').scrollTop();
- //Should we snap the output to the bottom?
- if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) {
- atBottom = true;
- if ($('#newMessages').length) {
- $('#newMessages').remove();
+ //Should we snap the output to the bottom?
+ if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) {
+ atBottom = true;
+ if ($('#newMessages').length) {
+ $('#newMessages').remove();
+ }
+ //If not, put the new messages box in
+ } else {
+ if ($('#newMessages').length) {
+ var messages = $('#newMessages .number').text();
+ messages = parseInt(messages);
+ messages++;
+ $('#newMessages .number').text(messages);
+ if (messages == 2) {
+ $('#newMessages .messageWord').append('s');
}
- //If not, put the new messages box in
} else {
- if ($('#newMessages').length) {
- var messages = $('#newMessages .number').text();
- messages = parseInt(messages);
- messages++;
- $('#newMessages .number').text(messages);
- if (messages == 2) {
- $('#newMessages .messageWord').append('s');
- }
- } else {
- $messages.after('1 new message');
- }
+ $messages.after('1 new message');
}
}
@@ -277,27 +221,54 @@ function output(message, flag) {
opts.messageCount--; //I guess the count should only ever equal the limit
}
- //Actually append the message
- var entry = document.createElement('div');
- entry.className = 'entry';
-
- if (filteredOut) {
- entry.className += ' hidden';
- entry.setAttribute('data-filter', filteredOut);
+ var handled = false;
+ var trimmed_message = message.trim();
+ var lastmessages = $messages.children('div.entry:last-child');
+ if(opts.messageCombining && lastmessages.length && $last_message)
+ {
+ if($last_message == trimmed_message)
+ {
+ if(lastmessages.children('span.repeat').length)
+ {
+ var current_value = parseInt(lastmessages.children('span.repeat').text());
+ lastmessages.children('span.repeat').text(current_value + 1);
+ }
+ else
+ {
+ lastmessages.append($('', { 'class': 'repeat', 'text': 2}));
+ }
+ var insertedBadge = $(lastmessages).find('.repeat');
+ insertedBadge.animate({
+ "font-size": "0.9em"
+ }, 100, function() {
+ insertedBadge.animate({
+ "font-size": "0.7em"
+ }, 100);
+ });
+ opts.messageCount--;
+ handled = true;
+ }
}
- entry.innerHTML = message;
- $messages[0].appendChild(entry);
+ if(!handled)
+ {
+ var entry = document.createElement('div');
+ entry.className = 'entry';
+
+ $last_message = trimmed_message;
+ entry.innerHTML = trimmed_message;
+ $messages[0].appendChild(entry);
+
+ // Stuff we can do after the message shows can go here, in the interest of responsiveness
+ if(opts.highlightTerms && opts.highlightTerms.length > 0) {
+ highlightTerms(entry);
+ }
+ }
//Actually do the snap
- if (!filteredOut && atBottom) {
+ if (atBottom) {
$('body,html').scrollTop($messages.outerHeight());
}
-
- //Stuff we can do after the message shows can go here, in the interests of responsiveness
- if (opts.highlightTerms && opts.highlightTerms.length > 0) {
- highlightTerms(entry);
- }
}
function internalOutput(message, flag)
@@ -432,11 +403,6 @@ function ehjaxCallback(data) {
} else {
handleClientData(data.clientData.ckey, data.clientData.ip, data.clientData.compid);
}
- } else if (data.loadAdminCode) {
- if (opts.adminLoaded) {return;}
- var adminCode = data.loadAdminCode;
- $('body').append(adminCode);
- opts.adminLoaded = true;
} else if (data.modeChange) {
changeMode(data.modeChange);
} else if (data.firebug) {
@@ -544,7 +510,8 @@ $(function() {
'spingDisabled': getCookie('pingdisabled'),
'shighlightTerms': getCookie('highlightterms'),
'shighlightColor': getCookie('highlightcolor'),
- 'scolorPreset': getCookie('colorpreset')
+ 'scolorPreset': getCookie('colorpreset'),
+ 'smessageCombining': getCookie('messagecombining')
};
if (savedConfig.sfontSize) {
@@ -587,6 +554,14 @@ $(function() {
internalOutput('Loaded color preset of: '+colorPresets[opts.colorPreset]+'', 'internal');
}
+ if (savedConfig.smessageCombining) {
+ if (savedConfig.smessageCombining == 'false') {
+ opts.messageCombining = false;
+ } else {
+ opts.messageCombining = true;
+ }
+ }
+
(function() {
var dataCookie = getCookie('connData');
if (dataCookie) {
@@ -615,11 +590,6 @@ $(function() {
$('body').on('mousedown', function(e) {
var $target = $(e.target);
- if ($contextMenu && opts.hasOwnProperty('contextMenuTarget') && opts.contextMenuTarget) {
- hideContextMenu();
- return false;
- }
-
if ($target.is('a') || $target.parent('a').length || $target.is('input') || $target.is('textarea')) {
opts.preventFocus = true;
} else {
@@ -858,31 +828,25 @@ $(function() {
});
$('#saveLog').click(function(e) {
- var saved = '';
+ $.ajax({
+ type: 'GET',
+ url: 'browserOutput.css',
+ success: function(styleData) {
+ var win;
- if (window.XMLHtpRequest) {
- xmlHttp = new XMLHttpRequest();
- } else {
- xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
- }
- xmlHttp.open('GET', 'browserOutput.css', false);
- xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
- xmlHttp.send();
- saved += '';
+ try {
+ win = window.open('', 'Chat Log', 'toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=780, height=600, top=' + (screen.height/2 - 635/2) + ', left=' + (screen.width/2 - 780/2));
+ } catch (e) {
+ return;
+ }
- saved += $messages.html();
- saved = saved.replace(/&/g, '&');
- saved = saved.replace(/Chat Log';
+ win.document.head.innerHTML += '';
+ win.document.body.innerHTML = $messages.html();
+ }
+ }
+ });
});
$('#highlightTerm').click(function(e) {
@@ -956,6 +920,12 @@ $(function() {
internalOutput('Changed color preset to: '+colorPresets[opts.colorPreset]);
});
+ $('#toggleCombine').click(function(e) {
+ opts.messageCombining = !opts.messageCombining;
+ setCookie('messagecombining', opts.messageCombining, 365);
+ internalOutput('Line combining '+(opts.messageCombining ? 'enabled' : 'disabled')+'', 'internal');
+ })
+
// Tell BYOND to give us a macro list.
// I don't know why but for some retarded reason,
// You need to activate hotkeymode before you can winget the macros in it.
diff --git a/html/changelog.html b/html/changelog.html
index e2d2d4918ac..cadf49ba919 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -86,1393 +86,1316 @@ ADDING CREDITS? EDIT templates/header.html (or footer.html if they're for old t
-->
-
2018.02.09
-
jknpj updated:
-
-
Every non-combat(Security, Combat, Syndicate)/engineering cyborg is now equipped with a mini extinguisher.
-
Removed the big extinguishers from both Standard and TG17355 Cyborgs.
-
Fixed ghosts being unable to shift+click the AI
-
-
-
2018.02.08
-
DrSnips updated:
-
-
Fixed syringes having a bloodbag icon over them when they had a small amount of reagents in them.
-
Added a few butterfly knifes. Upon flipping them closed they summon a "butterfly" for 20 seconds but only one at a time. It takes 25 seconds to recharge.
-
The butterfly will fight along side you. It does about 25 damage per hit.
-
A syndicate butterfly knife can be bought in the syndicate uplink for 7TC.
-
A crystal butterfly knife can be bought from the wizard spellbook for 20 points.
-
-
Kurfursten updated:
-
-
The telecommunications network monitor can now perform a traceroute to help you diagnose where the system breakdown is.
-
+
2018.07.03
Pathid updated:
-
Patients zero of a viral outbreak no longer get a roll for natural immunity to that virus.
+
Fixed robot holomap verb.
+
+
+
2018.07.02
+
Pathid updated:
+
+
Create Antagonist verb now gives admins a choice of how many changelings or vampires to make, instead of always making three.
ShiftyRail updated:
-
The emergency defibrillator will now give a proper reason for failing to revive people.
+
Flashbang duration has been reduced by 20%, and now stuns carbons for a considerably shorter time at long range (more than 3 tiles). The cap for stunning at long range is 2 seconds, from 20 for carbons, and 8 seconds from 20 for silicons.
-
The-Whargoul updated:
+
tolan1 updated:
-
Gave Plasmamen NO_HUNGER.
-
Removed Plasmamen's ability to eat solid food and medication.
-
-
TurboGay updated:
-
-
allows for construction permits to fit in wallets
+
replaces .45 magazines in packed armory locker with .380 magazines, to match the glock they spawn with
-
2018.02.07
-
DamianX updated:
+
2018.07.01
+
Pathid updated:
-
Fixed a bug that prevented HUDs from finding records for people wearing no ID.
+
The clown stamp in the HONK upgrade for service borgs and hugborgs actually works now.
+
+
+
2018.06.30
+
ShiftyRail updated:
+
+
Meta: Security has access to the internal morgue airlock, like in Box and Bagel.
+
Packed: Security has access to the internal morgue airlock, like in Box and Bagel.
+
Packed: Interrogation room designed to allow more space to manoeuvre prisoners, and privacy in the form of Smartglasses that can be toggled on or off.
+
Deff: Security checkpoint in medbay can be accessed via medical lobby, and now has a security cameras computer.
+
Deff: Perma is more secured, with a layer of grille + plasma window on top of the renforced wall outside. This means you can no longer sneak in with a false wall unnoticed.
+
Deff: Added a security locker to the arrivals checkpoint.
+
Deff: Added a second sec vend.
+
Deff: Security has access to the internal morgue airlock, like in Box and Bagel.
+
Warden and HoS lockers will now start with gear that was otherwise missing in them but found in security officer lockers, such as a hailer.
+
+
+
2018.06.29
+
Pathid updated:
+
+
Refactored part of Securitron construction so that it doesn't delete non-standard cells from batons.
+
+
+
2018.06.28
+
Irradiation updated:
+
+
Albuterol has been fixed to actually require Hyperzine instead of Inaprovaline.
+
+
+
2018.06.27
+
Pathid updated:
+
+
Comments added to security and medical records are now timestamped with the in-game time instead of the server time.
+
+
ShiftyRail updated:
+
+
Albuterol (the medecine for athsma) now requires Hyperzine + Tramadol rather than Hyperzine + Inaprovaline.
+
+
+
2018.06.26
+
Allspice updated:
+
+
Ports colorful reagent from TG, mescaline psilocybin amatoxin.
MadmanMartian updated:
-
Can now build thrones from wood.
-
Can now build chests from wood and plasteel. The plasteel has to be in your immediate vicinity or in your off-hand.
+
Adds anvils. Ordered through cargo.
Pathid updated:
-
Gave MMIs and posibrains dexterity. AFAIK the only thing this will affect is the mecha engineering switchtool, which MMI and posi piloted Clarkes will now be able to make full use of.
-
Constructs are now shock-immune.
+
Examining a cyborg gripper holding an item will examine the item instead.
+
Cyborg grippers holding an item will now drop the item on the first "drop" command, and store the gripper on the second "drop" command. Accordingly there's no action button for dropping anymore.
+
Fixed MoMMI modules being completely unusable.
-
2018.02.06
-
DrSnips updated:
+
2018.06.25
+
DamianX updated:
-
Added the directed laser heater. It heats reagents in containers when placed on it. Use alt click or the right click verb to toggle it on and off.
-
Added the cryonic wave projector. It cools reagents in containers when placed on it. Use alt click or the right click verb to toggle it on and off.
+
Changelings cannot spam horror form any longer.
+
Fixed "Horror Form" costing 0 chems.
-
-
2018.02.05
-
DrCelt updated:
+
DeityLink updated:
-
Botany tray lids now properly block bees.
+
BEEKEEPING 3.6 - I'm back again baby
+
You no longer have to land the extinguisher spray right onto a bee swarm to calm them down. Calming bees has never been easier!
+
Bees no longer remain angry forever! If they can't find a target for an extended period of time, they'll calm down. This doesn't apply to angry bee infestations.
+
When an empty apiary is available, no more than one queen will swarm at once to populate it.
+
Homeless bees will die after about 10 minutes if left alone. Except queen bees, who'll try to recruit homeless workers to build colony. Their swarms will target empty apiaries in priority, but if they can't find any, they'll build their own from scratch! Each species has their own wild hive.
+
Wild hives work like normal ones, except that you cannot add queen bee packets or beezeez, or empty bees into them.
+
Added Hornets. They have a chance to spawn from infestation events, and traitor botanists may purchase Hornet Queen Packets for 2 TC each. Hornets have a chance to deal partial damage through protection, so handle carefully!
+
Beekeepers now start the game with a single bee packet in their pocket, so they don't have to wait for cargo to get to work.
+
lots of back-end optimization.
-
Kurfursten updated:
+
Irradiation updated:
-
You can now buckle another person into a wheelchair, assuming they are otherwise valid to sit in it. This change does not extend to the multiman wheelchair.
+
The armory on Boxstation now has an RPG. Enjoy your friendly fire exercises, security.
+
+
MadmanMartian updated:
+
+
After careful deliberation, it has been deemed unsatisfactory that a security force be provisioned with explosive devices.
Pathid updated:
-
Packedstation: The escape shuttle brig turfs were fixed so "escape alive and free" objectives should properly fail now if the antagonist is on them and restrained.
-
-
jknpj updated:
-
-
Fixes Mecha Hitler holocausting the whole server with infinite german explosions.
+
Security cyborgs can now lift security tape. Engineering cyborgs can now lift engineering and atmos tape.
+
Slightly tweaked atmospheric analyzers so they'll work properly while you're inside an airtight object.
+
Fixed a bug where atmos analyzers would display the air temperature in red text all the time. Now it's in red only when it's outside of the safe range for humans.
-
2018.02.02
-
Kurfursten updated:
+
2018.06.24
+
MadmanMartian updated:
-
You can no longer deathwhisper over radio
+
Can now install an active pAI to a minebot. It consumes the pai in the process, so be careful with your little friend.
+
The magic of the masks of morphing falters, they are no longer as effective as they once were.
+
You can now use welding tools to repair a damaged space pod.
+
+
Pathid updated:
+
+
In-hand sprites for defibrillators are now visible.
-
2018.01.31
-
Kurfursten updated:
+
2018.06.22
+
Pathid updated:
-
Clipboards will now properly update when dumped into a cabinet
-
Clipboards now properly show the last item on top instead of the item last removed
-
Fixed the headset whisper bug
-
-
Pomf123 updated:
-
-
Non-Admin players that did not join the round can no longer vote for the next map.
-
-
jknpj updated:
-
-
Ports the 'Toggle Floor Bolts' AI verb from TG
-
Added a tile painter to the default service cyborg loadout.
-
Ports the portable seed extractor from TG. It doubles ad both plant bag and seed extractor but it can only extract at most two seeds per crop.
-
Removed the plant bag from the H.U.E.Y. upgrade.
-
Added the portable seed extractor to the H.U.E.Y. upgrade.
-
Fixes the chaos blade having no back icon while possessed.
-
Adds the reagent chill wax to the peace hypospray.
-
Added a chance to get a random cyborg upgrade(minus the magnetic gripper) as premium item in the Vox Supply.
+
Craftable training swords now have in-hand icons.
-
2018.01.30
+
2018.06.21
+
Allspice updated:
+
+
Silicon ckeys are displayed even if the silicon ghosts.
+
Arthurdentist updated:
-
Added a new premium costume to the security vendors, a British police uniform.
+
Added a new spellbook, available from the spellbook bundle. If you are lucky enough to find it, the winter spellbook will grant you one of four, Christmas-themed spells that are otherwise only available during Christmas.
DamianX updated:
-
RCDs can fit in hazard vests.
-
Changing security levels will play a notification sound.
-
Made the virology machines and account database (un)wrenchable.
-
Updated the medical sleeper UI.
+
Added a new traitor item: "Does Not Tip" database backdoor. Once purchased, lets you add the station to Central Command's "Does Not Tip" database. Stations on the list get extra condiment with their pizza.
-
DeityLink updated:
+
jknpj updated:
-
Fixed chill bugs colonizing empty apiaries from turning into regular bees.
-
Added a transparent animated holographic ray between an holopad and its AI hologram
-
EMPs turn off AI holograms
+
Fixes MoMMIs being unable to use their station holomap verb
-
DrCelt updated:
+
+
2018.06.20
+
Allspice updated:
-
Did stuff!
+
Make buckshot spread independent of the distance you click at.
-
Kurfursten updated:
+
Unknown-as-Captain updated:
-
Tradervend no longer lists each option twice, but instead gives five choices (up from four)
+
replaced R&D with Tetris and clearing a line gives you a random research point
+
+
+
2018.06.19
+
Allspice updated:
+
+
Xeno doors can now be destroyed with lasers and bullets.
+
+
otatoh updated:
+
+
Adds an in-hand sprite for Salem
+
Fixes Salem turning into Runtime when picked up
+
+
+
2018.06.18
+
Allspice updated:
+
+
Make NVG overlay less green.
Pathid updated:
-
Fixed emergency flares not lighting cigarettes, thermite, etc.
-
Added some unnecessary examine text to flares too.
+
Added a basic way to eject people and objects from transit tube pods. Just click the open pod with your empty hand. Additionally, examining the pod or the tube will now show you what's in it.
+
+
SonixApache updated:
+
+
You can now slot grenade launchers onto armored vests.
+
summon guns now summons a larger variety of guns
-
2018.01.29
-
DeityLink updated:
+
2018.06.17
+
DamianX updated:
-
Fixed some manuals not printing on the library computer.
-
-
jknpj updated:
-
-
Fixes charcoal not appearing in the upgraded cyborg hypospray reagent list.
+
Added a new first law to NT Default that makes all laws after it be given equal priority.
-
2018.01.28
-
DeityLink updated:
+
2018.06.16
+
Allspice updated:
-
The Emergency Shuttle should now always be playing its hyperspace warm up sound.
-
hey I'm back.
-
Slightly increased the ratio of honey found in honeycomb, compared to reagents from plants.
-
Slowed down the rate at which your body metabolizes honey.
-
Added Chill Bugs, a new species of bees. One or two packets of those can be found on the Vox outpost. Those bugs imported from Vox worlds need N2 to breath and suffocate in Oxygen. They produce a honey-like substance called Chill Wax, and while it doesn't heal as efficiently as regular honey does, it has the strange property of causing people who ingest it to become unable to perform any act of violence. Incidentally, Chill Bugs live up to their name and don't get angry ever, and there are only a handful of reagents that can raise their hive's toxicity, which makes raising them much easier than raising bees, if you can set up proper atmos.
-
New sprite for the beekeeping book
+
Move the handtele destination-select from attackself to alt-click, make attackself automatically open a portal to the most recent chosen destination.
+
+
SonixApache updated:
+
+
syndicate tape now fits in tool- and security belts.
+
+
+
2018.06.14
+
Irradiation updated:
+
+
NT decided to cut their budget allocation for anti-tampering device for the Tactical Assault Gear crate.
+
+
Pathid updated:
+
+
Reverted the "new" super-shaky dizziness/drunkenness effect.
+
+
+
2018.06.13
+
Intigracy updated:
+
+
Reverted the change that made cat ears give brain damage over time.
+
+
Pathid updated:
+
+
Fixed an oversight where newly constructed or re-constructed machines did not check if they were actually in a powered area.
+
Ghosts can point now.
+
+
+
2018.06.12
+
Allspice updated:
+
+
Adds untable mutagen, produceable with phenol formic radium. It uns tables.
+
shift+mmb-click on things at a distance to point at them.
+
+
Intigracy updated:
+
+
Collectible cat ears now once again remain black permanently.
+
+
Pathid updated:
+
+
Being hit with a bolt from the Staff of Change no longer causes wizard spells to be lost.
+
+
+
2018.06.11
+
DamianX updated:
+
+
Ported some vending machine animations that play when an item is ejected.
+
Radio messages no longer show the icon of the radio used to send them.
+
+
Kevak updated:
+
+
Adds several items to autolathes that felt like they were missing/were requested. Including some botany tools, hand labelers, bear traps and so on.
+
+
Pathid updated:
+
+
Fixed a bug that caused gibtonite ores to be duds.
ShiftyRail updated:
-
Crawling now requires you to stand still for exactly 1 seconds before moving. Missing/damaged limbs significantly increase that delay. Hyperzine counteracts those adverse effects. Additionally, once you've began to crawl in a certain direction, you can no longer change said direction.
+
The syndicate can now provide security, atmospheric technicians, and engineers with rigged tape. Security rigged tape cuffs people who try to remove it, engineering rigged tape shocks you, and atmospherics tape is very sharp and difficult to remove.
+
+
+
2018.06.10
+
Pathid updated:
+
+
Getting SoC'd into a humanoid race will automatically update your default language to the default for that race.
+
Extreme burn victims aren't impossible to defib anymore, unless they also happen to have severe radiation damage.
+
+
unid15 updated:
+
+
Added a new, exciting puzzle vault. The reward for completing it is a Vest of Reflection - a yellow-colored ablative vest that is guaranteed to reflect every single energy projectile (at the cost of providing less protection versus other types of damage). It is fully unique to the vault, and will never appear in Spessmart.
+
+
+
2018.06.08
+
Pathid updated:
+
+
Uranium chairs now deconstruct into uranium instead of diamond.
+
Retooled camera-to-blinder conversion and deconversion. No more infinite bulbs/film. Also, sepia, XL and XXL cameras will no longer be turned into normal cameras by it. Note that the process destroys all unused film inside.
+
Tweaked some helmet coverage areas to better reflect their wear icons.
+
Building an AI core without a brain or posibrain will now result in an inactive AI core you can upload a carded AI to. Previously this would bug out and make an AI without a player to control it.
jknpj updated:
-
Fixes a runtime when examining cyborgs with activated grippers and no gripped item.
-
Adds the staff of nullmancy, heavenly chain, honk rod, french rod, blessed cane and septerion morningstar as holy weapon skins for the null rod.
-
Adds the chaos blade, a talking "holy" weapon, as a rare drop to temple and war digsites.
-
Added "Martian" as a staff of change mode.
-
Removed "Horror" from changelings from the staff of change's "Human" setting.
-
Borgs/MoMMIs will now self-destruct themselves after being transformed by a staff of change/admin panel if their brain is from a jobbanned player.
-
the Monkey mode in the staff of change will now properly transform their targets in their respective primite species AND transfer their DNA/damage taken/intent properly.
+
Adds a robot maintenance crate to cargo for 120 spessbucks.
+
Cyborgs cover will automatically unlock when they die.
+
+
jmantela updated:
+
+
Added two new condiment bottles: mustard and relish. Can be found in the exotic garnishes crate from cargo.
-
2018.01.25
-
DrSnips updated:
+
2018.06.07
+
Pathid updated:
-
You can now insert the key of a vehicle into the vehicle itself to allow it to run. The old method of holding the key in hand at all times still works as well. This applies to vehicles like janicarts, firebirds, gigadrills, etc.
+
Fixed a problem where hivelord broods were not getting destroyed properly.
-
2018.01.24
-
HarseTheef updated:
-
-
Reworks Chloral Hydrate to only apply a knockdown when above 10u and apply a confused/drowsy state for all amounts below 10u.
-
-
PromethTK11 updated:
-
-
Packed: Fixed a lot of air alarms/vent/scrubbers issues on Packed, you can breath now.
-
Packed: You shouldn't be able to crowbar the AI core blast-door now.
-
Packed: Added an evidence locker to brig for all your noir needs.
-
Packed: The flash of the brig cells now should work properly.
-
And various Packedstation misc fixes!
-
-
-
2018.01.23
+
2018.06.06
Intigracy updated:
-
"This is a test changelog (please don't mind it)."
+
"Chems that remove hallucination triple in effectiveness if you're asleep or in cryo, double if you rest."
MadmanMartian updated:
-
Boozeomats and soda dispensers can now dispense ice again
+
Adds material inheritance to created objects
+
Adds the grease spell, letting you create a lube-spill at will. Has congruency with fire spells, so having fireball will also make it spill welder fuel.
-
PJB3005 updated:
+
+
2018.06.05
+
Pathid updated:
-
"Charcoal works 5x faster now, remains in the body for much longer, doesn't delete itself on vomiting (but still causes vomiting) and it automatically deletes itself when all reagents are gone."
+
Revival effects will no longer "eat" restraints. Instead they will just drop.
+
Hitsounds now play when constructs and shades are hit by weapons. Striking a juggernaut with a weapon will now produce an attack animation (if it has enough force to deal damage to it), and they now take bonus damage from null rods like other constructs.
+
+
2018.06.03
+
Allspice updated:
+
+
Windows can now be rotated with alt-click.
+
+
MadmanMartian updated:
+
+
Adds the joy of painting religion. Tags are bob ross, art, happy little trees, happy little clouds.
+
+
Pathid updated:
+
+
Fixed a bug that made cult space armor and space helmets unwearable.
+
Flashbangs going off on someone's same tile now affect them for the full duration regardless of their protection.
+
+
+
2018.06.01
+
Pathid updated:
+
+
Shades, soul stones and constructs now have examine text that shows if the player has logged out or ghosted.
+
+
+
2018.05.31
+
DamianX updated:
+
+
Central Command might request supplies from the station from time to time. Details will be available at the cargo computers.
+
+
Pathid updated:
+
+
Proto-kinetic accelerators now have a working charge indicator light.
+
+
+
2018.05.27
+
DamianX updated:
+
+
The "O" key no longer opens the OOC chat window in hotkey mode.
+
+
Pathid updated:
+
+
Renamed the body scanner's "Absorbed rads danger index" to "Radiation sickness progression" which is more descriptive of what it is. Also now it will give the name of the stage the patient is in.
+
Lattices built on asteroid floors and metal foam floors will now layer OVER them instead of under them and invisible.
+
+
SonixApache updated:
+
+
Nanotrasen has removed the auxiliary .45 chamber-loading option from their glock lineup.
+
+
jknpj updated:
+
+
Boss mob exclusion list properly implemented this time. No more Hitlers in Xenobio
+
+
+
2018.05.26
+
Pathid updated:
+
+
Body scans now show a number for the progress of radiation poisoning, in addition to the radiation level, which doesn't tell the whole story.
+
+
+
2018.05.25
+
MadmanMartian updated:
+
+
Pistols now have an instruction guide on how to fire both at the same time. Simply slap one against the other, then start firing until one goes click.
+
+
+
2018.05.24
+
DamianX updated:
+
+
Changed the recipe for sodium polyacrylate to require water instead of hydrogen and oxygen.
+
+
MadmanMartian updated:
+
+
Simple animals can be put in cryo
+
Simple animals can be buckled to chairs
+
Adult slimes are now considered larger than their younglings, rather than being the same size.
+
+
+
2018.05.23
+
DamianX updated:
+
+
Added sodium silicate. One part silicon, two parts sodium, three parts oxygen. Used in the recipe for plasteel solidification.
+
Several minor changes to some relatively uncommon chemical recipes. Details on the wiki.
+
+
+
2018.05.22
+
Exxion updated:
+
+
A ton of stuff with ZAS. Most things should be back to the behavior of about seven months ago, so build things with that in mind.
+
+
+
2018.05.21
+
abernd updated:
+
+
headsets, station bounced radios, and station intercoms now allow direct frequency input
+
+
+
2018.05.20
+
Pathid updated:
+
+
Created a "Sign up as pAI" verb in the Ghost tab for submitting a pAI profile without having to be around for the recruitment prompts.
+
+
unid15 updated:
+
+
Ring of fire and its upgrades now cost 10 spell points (down from 20)
+
+
+
2018.05.18
gbasood updated:
-
Buttbots now actually make fart noises when they parrot someone they hear.
+
Bluespace fruits, when not thrown, but still "thrown", will teleport hit mobs consistently.
-
2018.01.22
-
Kurfursten updated:
-
-
Speaking over a headset or radio will now cause your local speech to appear before the radio message.
-
Damage to telecomms will no longer cause your local messages to be delayed if you are standing in range of a radio. However, the radio transmission will still be delayed, and appear separately.
-
-
-
2018.01.21
+
2018.05.17
DamianX updated:
-
Ghosts with the appropriate HUDs will be able to look at people's security and medical records by examining them.
+
Fixed a bug that prevented removal of camera bugs from simple animals.
-
PJB3005 updated:
+
Pathid updated:
-
Did stuff!
+
Fixed a very longstanding math flub involving gas values and temperatures. Gas and heat will be working subtly differently now, and hopefully better.
+
Fixed the "dug" icon state for asteroid floors.
+
jknpj updated:
+
+
Service cyborgs can now use chemistry dispensers
+
Soviet MoMMIs can now use bartending machinery
+
Combat cyborgs can now use *law and *halt
+
+
+
2018.05.16
+
Pathid updated:
+
+
Fixed a bug where temporary blindness of MMI'd brains resulted in permanent blindness until the player re-logged.
+
+
+
2018.05.14
+
MadmanMartian updated:
+
+
A new virus symptom has been discovered in the deep space biodomes, that saps the energy from plantlife in the infecteds surroundings.
+
+
Pathid updated:
+
+
Fixed the pAI appearance for pAI mulebots disappearing after unloading things.
+
+
+
2018.05.11
+
Allspice updated:
+
+
Makes Lightning spell not recharge 3x as fast as other spells.
+
+
Pathid updated:
+
+
Fist spell now selects targets at random instead of opening a dialog box.
+
Fixed industrial vaporizer having a full mixing chamber crashing the serb.
+
+
+
2018.05.10
+
Allspice updated:
+
+
The GPS you are looking at will always display its coords at the top of the coords list.
+
Adds bluespace bananas and their special peels; mutates from normal bananas.
+
+
DamianX updated:
+
+
Fixed wooden walls having no floor underneath them when destroyed
+
+
MadmanMartian updated:
+
+
Adds the sporemind global chat for mushroom people. Use .~ to talk with it
+
+
+
2018.05.08
+
MadmanMartian updated:
+
+
Making a roman phalanx against bears now works, as simple animal attacks now check for shields.
+
You can now point-blank simple animals with guns, and have noises play when you hit them with sound making weapons again.
+
+
+
2018.05.07
unid15 updated:
-
Ring of fire now rapidly expands outwards from the wizard when initially cast
+
Admins may now enable advanced hologram spawning in the holodeck
-
2018.01.20
-
DamianX updated:
+
2018.05.05
+
Allspice updated:
-
P-ray scanners are now 10 times as expensive to build compared to the T-ray scanners.
+
Adds the Lazymov lawset, it can be researched with materials 6 and programming 3.
+
+
PublicEnemyMaiPai updated:
+
+
Plasmamen now receive their old flaming sprite after cloning again.
-
2018.01.19
-
CptWad updated:
+
2018.05.03
+
Allspice updated:
-
I am back from the dead! With bugfixes!
-
In order to make showers visible in shower curtains, added two new types of showers that allow visibility (click-ability) of shower heads while in the open position.
+
Makes upgraded parts influence xenobotany machines' efficiency.
-
DamianX updated:
-
-
Fixed several typos.
-
Made antag (cult/thrall/rev) (de)conversion messages bigger.
-
-
Kurfursten updated:
-
-
Alt-clicking almost any binary atmos device (pumps, valves, gates) will toggle it on/off. Exceptions are TEG circulators, MSGS, DP Vents.
-
Alt-clicking a pipe segment that isn't wrenched down will rotate it.
-
-
MadmanMartian updated:
-
-
Anti toxin now covers the botany toxins as well
-
-
ShiftyRail updated:
-
-
You can no longer hulk ad infinitum by using a clean SE while hulking.
-
-
SonixApache updated:
-
-
added black bedsheets and black soft caps
-
sprites by Blithering
-
-
-
2018.01.18
-
ShiftyRail updated:
-
-
Enthralled people can see other thralls from the same vampire.
-
-
jknpj updated:
-
-
You can now put mice on your head.
-
-
-
2018.01.17
DrSnips updated:
-
Raised the amount of phazon you get per vein from 2 to 3.
+
Added a Dorf religion for chaplain.
-
MadmanMartian updated:
+
PublicEnemyMaiPai updated:
-
More leather recipes added.
-
The crafted leather items now inherit the name of the source of the leather. Corgi leather cowboy hats, Cat leather shoes, et cetera.
+
AI can now Beep Ping Buzz
-
Pathid updated:
+
imw-Oculus updated:
-
Damage on a limb now has only a chance to widen an existing wound rather than doing it all the time.
-
Once installed, robot jetpacks now function in MoMMIs as they were supposed to. Godspeed, little crabs.
-
-
ShiftyRail updated:
-
-
Added fishtanks! Construct your own fishtank with glasses, metal and a circuit board. Breed fish with eggs from cargo. Catch fish, make your own fish-based recipes! Sprites courtesy of Blithering. Original fishtanks on Paradise courtesy of TheFalseIncarnate, original work on fishtanks courtesy of jakmak.
-
-
SonixApache updated:
-
-
Added black crayons.
-
Crayon boxes can now hold 7 crayons and include a black crayon.
-
Hand crank charger now adds 10 times more power units per crank
-
-
-
2018.01.16
-
DamianX updated:
-
-
NT default and Robocop core boards can be printed using the circuit imprinter.
-
-
HarseTheef updated:
-
-
Removes the blood cost from Hypnosis for vampires.
-
-
Pathid updated:
-
-
Vampire blood costs were adjusted. Bat Form and Shadowstep now actually spend blood and cost 20 and 10 usable blood respectively. Summon Bats costs 50 usable blood.
-
Improved vamp rejuvenate now has a message telling you about the effect.
+
Firelock frame construction. Use 5 metal in hand.
+
Firelock deconstruction, weld and wrench rather than socketwrench.
jknpj updated:
-
Fixes verb holders falling out of your pocket.
+
Adds rice hats, they can be made in the biogenerator and each costs 300 points.
+
Adds the fancy and black kimonos. The fancy one can be found in the autodobre premium list and the black one in the pietyvend premium list.
+
moved the sakura kimono to the normal list of the autodrobe.
+
Samurai chaplains now start with a rice hat, black kimono and sandals.
+
Adds the security cyborg N.O.I.R. upgrade. It adds a tape recorder, evidence bag, cyborg zoom lens(works like binoculars), .38 revolver, cyborg .38 speedloader(charges one bullet every 10 seconds inside a cyborg recharger) and a worn-out gripper(can hold drinks, the detective's scanner and fingerprint cards). This upgrade cannot be researched.
+
Adds the security cyborg warden upgrade. It adds a reinforced armour, battering ram, wrench, security code transmission device(locks/unlocks deployable barriers) and a cyborg implanter(recharges its implant after one minute inside a cyborg recharger). This upgrade cannot be researched.
+
Adds both new upgrades to the vox vend premium list, giving traders a rare chance of finding them in their vend.
-
2018.01.12
-
MadmanMartian updated:
+
2018.05.02
+
jknpj updated:
-
You can now lock direction in a mech
+
Mecha Hitler, Wendigos and Cockatrices can't be spawned by gold core+blood reactions anymore.
+
+
2018.05.01
Pathid updated:
-
Chemical effects that cause disfigurement (acid, mainly) and undo disfigurement (rezadone) should work again.
-
Added messages to a few disfigurement/un-disfigurement events.
-
-
Unknown-as-Captain updated:
-
-
Cat ears give slow brain damage over time.
+
Cloning pods don't inject vox with toxic inaprovaline anymore.
+
Being made unclonable by radiation will no longer render you unable to be defibbed out of hand, or unable to be hooked up to IVs.
-
2018.01.09
-
Cisrox updated:
-
-
Adds unique color combinations for dual e-swords. The colors of the e-swords forming the dual e-sword determines this.
-
Deleted dualesword1 sprite that was serving as a placeholder, it has been replaced by the new colors.
-
-
EdXbtkOEwGw updated:
-
-
Properly implemented glide_size on a lot of things. This means, for example, dragging a corpse won't make it look like it's teleporting everywhere, ghosts won't rollerskate in the air after haunting a slow person, plus smooth conveyor belts, smooth space inertia, and other things. If you still notice old no-glidesize behavior of stuff teleporting around, make a bug report.
-
-
-
2018.01.08
+
2018.04.30
Pathid updated:
-
Defficiency: Fixed up some misplaced atmos pipes in medbay, the bar backroom, and cargo maint.
-
Bagelstation: The kitchen's mail was being sent to the janitor's closet.
+
Cult space armor no longer has species restrictions.
+
Made it so that when an armor talisman is used, the blade from it goes straight into the user's active hand instead of their off hand, or worse, the ground.
+
Added syndishades: disguised secHUD sunglasses that can't set arrest status until they get the codes from a normal pair.
+
Changed number of implants in a greytide kit from one to two. Added syndishades to the kit.
-
Sooose updated:
+
PublicEnemyMaiPai updated:
-
Increased slime tiles generated from green slime reaction to 20.
-
Increased max slime tile stack size to 60.
+
Adds AI as job listing for AI when ordering supplies from cargo
+
+
SirSkeleto updated:
+
+
Added "Brotherhood of the Yellow Sign" religion.
-
2018.01.06
-
Jared-Fogle updated:
-
-
Fix eye protection being lowered when toggling the welding goggles back on.
-
-
-
2018.01.04
-
Pathid updated:
-
-
Slight correction to the checks for putting monkeys into the monkey recycler.
-
-
ShiftyRail updated:
-
-
Add religious converting. Chaplains will be able to ask people to convert to their religion.
-
Admins are now able to bus in religions and subtle PM all followers of a particular religions, as well as removing people from their religions.
-
-
-
2018.01.03
-
Pathid updated:
-
-
Mops should work now.
-
-
-
2017.12.31
-
Cyadox updated:
-
-
Quick-equip hotkey can now swap items in occupied slots.
-
Stopping surgery by dropping or storing your tool now harms the patient
-
-
DamianX updated:
-
-
Diagnostic HUDs can be printed from the protolathe.
-
Ghosts can use the diagnostic HUD.
-
Expanded the list of items the security hardsuit can hold. If the security armor can hold it, the hardsuit can too.
-
AIs can now track mechs.
-
-
HarseTheef updated:
-
-
Increased the tracking ability of the hand held tracking implant tool
-
-
MadmanMartian updated:
-
-
Made chemical heating less of a pain in the ass.
-
Can now sell plasma via cargo again.
-
-
Pathid updated:
-
-
Clone damage on slimepeople can be healed now.
-
Improved the clarity of cult bonus objectives.
-
A breathing bug for non-human mobs was fixed. Tiny concentrations of CO2 and plasma should no longer kill animals dead.
-
A similar bug was causing space heaters and AC units to be unduly effective.
-
-
-
2017.12.28
-
Cyadox updated:
-
-
Adds an alternative MoMMi Prime sprite, Credit to Skowron.
-
-
-
2017.12.27
-
DamianX updated:
-
-
Added the diagnostic HUD: lets the user see integrity and power cell charge for cyborgs and mechs. A couple of them can be found in the roboticist's locker.
-
Ghosts can use the security HUD.
-
-
MadmanMartian updated:
-
-
Aliens can only pickup facehuggers now.
-
Martian new HUD courtesy of realestestate
-
+
2018.04.29
unid15 updated:
-
Large amounts of blunt brute damage (16 and more) will gib limbs, instead of severing them. Gibbed limbs are destroyed, but heads still leave an intact brain.
+
Radiation collectors are now affected by glowing ghouls and (to a much lesser extent) by creatures with the radioactive gene
-
2017.12.26
+
2018.04.27
+
MadmanMartian updated:
+
+
Adds GraveKEEPER Cogspiders.
+
+
ihadtoregisterforthis updated:
+
+
Cup ramen is self-heating again
+
Added quicklime as a heating chemical for your reagent temperature needs
+
+
+
2018.04.26
Pathid updated:
-
Due to their inherent slowness, alien queens aren't affected by pain slowdown any longer.
-
-
jknpj updated:
-
-
Adds the Service Cyborg H.O.N.K. upgrade! It comes with a bikehorn, rainbow stamp, rainbow crayon, sound synth and a water flower ready for your everyday fun times.
-
-
-
2017.12.24
-
PJB3005 updated:
-
-
Fixed NTSL scripts scrambling characters like >. You can make a script that adds meme arrows to everything now.
-
-
-
2017.12.22
-
Arthurdentist updated:
-
-
Added two new spells that will be available for wizards to purchase on Christmas Day
-
-
-
2017.12.20
-
DamianX updated:
-
-
Bio suits will block plasma like they were supposed to.
-
-
Sooose updated:
-
-
Curtains now start anchored and can be (un)secured with a screwdriver.
-
-
yclatious updated:
-
-
Reduced prices on soda machines
-
-
-
2017.12.19
-
jknpj updated:
-
-
Cyborg upgrades (Medical MK-2, Service Cooking, Service H.U.E.Y.) will upgrade both chem/service gripper properly now.
-
-
-
2017.12.18
-
Pathid updated:
-
-
Security cyborgs now have a hailer for your targeted hailing needs.
-
-
Unknown-as-Captain updated:
-
-
MoMMIs can scan phazon.
-
-
-
2017.12.17
-
DamianX updated:
-
-
Buffed the service borg beer synthesizer to produce 1u each tick (previously 0.3u)
-
Trying to apply tape to doors won't open said doors anymore.
-
Can't stack multiple tapes on doors anymore.
-
-
DrSnips updated:
-
-
Added sodium polyacrylate. It absorbs water and spacelube not only in containers but on floors as well. Made with 3u carbon, 3u hydrogen, 1u sodium, and 2u oxygen.
-
-
MadmanMartian updated:
-
-
Adds Rad patches. A jumpsuit accessory that changes color when it absorbs radiation
-
-
Pathid updated:
-
-
Carbon mobs will now receive damage slowdown proportional for their maximum health, instead of always being based on 100.
-
-
PromethTK11 updated:
-
-
Packed: Now the hyperspectral imager is on place on the outpost, and there are some tools for scientist now.
-
Packed: Elite-syndie shuttle works properly now.
-
Packed: Secway keys added to the warden locker.
-
Packed: Scrubbers now scrub out plasma by default.
-
Packed: And a lot of misc fixes/changes!
-
-
Unknown-as-Captain updated:
-
-
Fixes mismatched glide_sizes for vehicles (possibly other things as well). This means wounded people riding vehicles won't wobble all over the place anymore.
-
-
jknpj updated:
-
-
Supply cyborgs now have access to both cargo and mining radio instead of just cargo.
-
Ghosts can now examine closed lockers to check its contents
-
-
yclatious updated:
-
-
Reduced prices on the Off World Off License vendor, enjoy lower prices for lower quality beer.
-
-
-
2017.12.11
-
MadmanMartian updated:
-
-
Turrets now check if you are stunned rather than if you are lying down before firing at you
-
-
-
2017.12.10
-
PJB3005 updated:
-
-
Lowered the find rate on the "crystal" xenoarch artifact. It did literally nothing except infuriate xenoarchs.
-
-
-
2017.12.09
-
Kurfursten updated:
-
-
The telecommunications network monitoring console can now boost the signal of telecomms machines affected by ionospheric interference, rebooting them immediately. This will cause increased temperature and power expense for five minutes.
-
The network monitor will also remotely display machine integrity.
-
-
Unknown-as-Captain updated:
-
-
Increases energy cost of airlocks made with with borg RCDs
-
Re-added 2012 flashbang box description
-
You now get 40 bananium/phazon floortiles per sheet, up from 4
-
Cyborg material synthetizers cannot dupe bananium or phazon. You can still synthetize it by using solid matter cartridges.
-
-
jknpj updated:
-
-
Adds the instrument synthesizer to the default service cyborg loadout.
-
Adds the H.U.E.Y. upgrade to service cyborgs! It comes with a mini hoe, clippers, plant bag, plant analyzer and makes the service gripper able to handle seeds and glass containers.
-
Removes the botanics-related upgrades from the cooking upgrade and makes it cheaper.
-
You can now drag and drop a piece of meat on cloning pods to make them suck and process every piece of meat in the same tile as the one being dragged(this feature can't be used by silicons).
-
Kicking a cloning pod now has 5% chance to unlock and eject its occupant.
-
-
-
2017.12.07
-
DamianX updated:
-
-
Space suits are now orderable from cargo.
-
Science access lets you open exotic seeds crates (hydroponics access still works).
-
-
Kurfursten updated:
-
-
You may now drag crates onto disposal bins to return your emptied mail.
-
-
MadmanMartian updated:
-
-
Bananas now have potassium in them
-
-
RealestEstate updated:
-
-
Did stuff!
-
did other stuff!
-
-
-
2017.12.06
-
MadmanMartian updated:
-
-
More cargo shuttle fixes. Metaclub cargo shuttle no longer steals windows.
-
-
Pomf123 updated:
-
-
Added AOL You got mail.wav to disposals when packages arrive.
+
Inhalers can be used on other people now, when on help intent.
+
Turning into a slime person via mutation toxin should relieve the subject of broken bone status effects now, as slime people don't have bones.
+
NT has patched a security flaw in loyalty implants that made them useless at blocking the effects of the Syndicate's so-called Greytide implant. Whichever implant that gets in first will override the other.
ShiftyRail updated:
-
Add a cancel option to text prompts which previously had none.
-
-
-
2017.12.05
-
MadmanMartian updated:
-
-
Deff cargo shuttle now no longer tries to run over the kitchen
-
-
-
2017.12.03
-
MadmanMartian updated:
-
-
Feral ghouls are fixed
-
It is now easier to become a ghoul somewhat. Less uncurable brain damage.
-
-
unid15 updated:
-
-
Fixed maploader being very laggy and crashing the server when loading away missions
-
-
-
2017.12.02
-
Blithering updated:
-
-
Did stuff!
-
did other stuff!
-
-
DrSnips updated:
-
-
Added loot crates. A monthly subscription for $30 you can buy in the cargo merch computer.
-
Added the measuring tape, core sampler, and phazon glow stick to the list of anomaly designs in the protolathe.
-
Added the phazon glowstick. It changes to random colors when you shake with it or interact with it. It can be worn on jumpsuits like other accessories. It will not change colors while on jumpsuits. (This is a feature not a bug)
-
-
MadmanMartian updated:
-
-
Having a cane on you when your leg's broken now helps you move a bit faster than otherwise.
-
Activated charcoal recipe added. 2 parts acid, 1 part carbon. 450 degrees C
-
You can now crawl by clicking on a turf in proximity when on the ground but not unconscious or dead and have arms
-
Bunsen burner buffed by 150%
-
-
-
2017.11.28
-
unid15 updated:
-
-
Added a new vault
-
-
-
2017.11.26
-
unid15 updated:
-
-
Text written on paper with crayons is now colored again
-
Text written on paper is no longer permanently lost if the act of writing somehow fails, only if you press the 'Cancel' button
-
-
-
2017.11.18
-
DrSnips updated:
-
-
Paramedic locker contents have been shuffled a bit.
-
Paramedic EVA locker now has two internalbleeding kits. (8 total bio foam injectors)
-
Removed some of the extra paramedic gear leaving two complete sets of outfits.
-
Paramedic webbing added to the EVA locker.
-
The magboots in the paramedic EVA locker now have paramedic colors.
-
Added the precision grasper. It functions like a hemostat at double speed and allows you to retrieve implanted things 100% of the time when trying to fish them out.
-
Added the diamond surgical drill. An advanced version of the surgical drill. It's extremely fast like other diamond drills.
-
-
Kurfursten updated:
-
-
Radiation closets now spawn with a single Geiger counter.
-
Geiger counters fit on tool-belts.
-
-
unid15 updated:
-
-
Fixed admins not being able to modify lighting parameters on objects
-
Buildmode now supports area modification. While in build-adv mode, middle-click on a turf twice to begin expanding its area. This works like the station's blueprints, but also supports click-dragging to convert large amounts of turfs quickly. Middle-click anywhere outside of the edited area to stop. Areas may now be spawned from paths as well, just like any other object, using either "spawn" or buildmode.
-
Added a new disability - veganism. It can be received either randomly at roundstart, by enabling it in your character preferences, through a new stage 2 virus effect, or through genetics. Also added a "veganism" / "animal rights" religion which automatically grants this disability.
-
Eating animal products, meat, milk, honey and blood as a vegan will make you nauseous, and further continuing to do so will cause minor toxin damage. Vegan vampires are unable to drink blood, if turned vegan after becoming a vampire.
-
-
-
2017.11.16
-
N3X15 updated:
-
-
Disables one-way window construction. Should help with performance.
-
-
-
2017.11.12
-
DamianX updated:
-
-
Carded AIs will no longer require a powered APC.
-
Personal AIs' wirejacks can now also close airlocks.
-
-
MadmanMartian updated:
-
-
Can now fold up plastic bags when empty so they can fit in smaller areas such as pockets
-
-
-
2017.11.11
-
Kurfursten updated:
-
-
You may now lube up TEG circulators (up to 25u each) to increase power output. Power growth is linear up to 200% bonus based on flow capacity.
-
Lube in circulators will slowly heat until converting into toxic waste.
-
Degrease engine by pouring in ethanol. Ethanol cancels out toxic waste.
-
-
-
2017.11.10
-
DrSnips updated:
-
-
Added the mobile operating table. It works just like a roller bed but allows you to to surgery on it without the chance of failure like a normal roller bed. Can be made in the protolathe or exosuit fab under the misc tabs.
-
Paramedic vests, first responder jackets, CMO labcoat, and medical/paramedic spacesuits can now carry folded roller beds in their suit slot.
-
-
PJB3005 updated:
-
-
The Hyperspectral Imager now has its own unique sprite and doesn't look like a literal photocopier.
-
Xenoarch analysis machines now use a fancy NanoUI.
-
Xenoarch analysis machines have a ctrl+click shortcut for starting scanning and an alt+click shortcut for ejecting the inserted container.
-
Bunsen burners are now also toggle with alt+click.
-
-
Pathid updated:
-
-
Wired glass sheets no longer yield more cables than it takes to construct them.
-
-
-
2017.11.09
-
DrSnips updated:
-
-
Bone gels can now be created. It requires you to mix 10u of milk and 10u of cryoxadone inside a vial.
-
Fix O veins can now be created as well. It requires you to mix 10u of bicaridine and 10u clonexadone inside a vial.
-
-
Intigracy updated:
-
-
Tripled the RNG chance of climbing a table.
-
-
-
2017.11.05
-
Pathid updated:
-
-
Added the ability to toggle subspace transmission on mech radios.
-
-
jknpj updated:
-
-
lathes/fabricators now accept sheets from sheet inserters
-
-
-
2017.11.04
-
jknpj updated:
-
-
Removes the duplicated sheet inserter from supply borgs
-
Bioprinters actually work again, sorry folks.
-
-
-
2017.11.03
-
Shadowmech88 updated:
-
-
Added a beach party vault.
-
Added trophy mounts. They can be crafted from two planks of wood, and items can be mounted on them. The trophy mounts can be applied to walls, and removed from walls via a crowbar. Clicking on the trophy mount with an item will mount the item wherever you click on the trophy mount. Alt+clicking with the item in your active hand will instead auto-center it on the trophy mount.
-
-
jknpj updated:
-
-
Adds cyborg grippers! Simple manipulators that can handle a limited amount of items.
-
Adds the service gripper service borgs, allowing them to handle drinks and trash.
-
Adds the chemistry gripper to medical cyborgs, allowing them to handle beakers and blood bags.
-
Adds the sheet to supply cyborgs, allowing them to hold and insert sheets inside machinery.
-
cyborg beakers, service shaker and universal enzyme are gone.
-
The medical cyborg upgrade got more expensive and needs anomaly research 2 but it also upgrades the chemistry gripper allowing it to handle pills and pill bottles.
-
The service cyborg upgrade got more expensive and needs anomaly research 2 but it now gives a rolling pin and also upgrades the service gripper allowing it to handle food, seeds and beakers.
-
Adds the magnetic gripper for engineering cyborgs and organ gripper for medical cyborg as expensive upgrades.
-
Silicons can now use the bioprinter.
-
-
-
2017.11.02
-
PJB3005 updated:
-
-
Bolas now automatically throw, even when not in throw mode.
-
-
unid15 updated:
-
-
The "spawn" and "create-datum" admin commands can change the new object's variables automatically after spawning it. Append any variable changes at the end of the string in curly brackets like so: spawn "/obj/item.{name="Item" ; w_class=5}"
-
Fixed some bugs with buildmode's edit mode (fixed strange behaviour when setting values to 0, fixed inability to reset object appearances). While in edit mode, middle-click any object to copy its variable.
-
-
-
2017.11.01
-
PJB3005 updated:
-
-
clicking on NanoUI machines always makes their UI have focus, even if you already have the UI open. This makes it easier to know which window corresponds to what with say the 3 SMESes.
-
-
Shadowmech88 updated:
-
-
Added warping claws, bladed gloves which allow the user to create portals. They can be obtained as a large Xenoarchaeology artifact.
-
Punches can now have sharpness. The punches of races with claws now have 1.5 sharpness.
-
-
ShiftyRail updated:
-
-
You can now remove the beaker from a cryotube with a verb accessible in the right-click contextual menu.
-
Adds shortcuts to the cryocell. Alt+click to remove the patient within it (including yourself), Ctrl+click to remove the beaker.
-
Fixes sanity issues with knife and gun holsters.
-
-
Unknown-as-Captain updated:
-
-
Added the 'Anarchist' bundle as part of the random Syndie bundles you can get.
-
Added a very special, very rare Syndie bundle.
-
Fixed molotovs not working when hitting anything except a floor (remember to put welding fuel inside the bottle!)
-
Security PDAs can now enable an integrated hailer from the PDA menu, similar to other gadgets in PDAs.
-
-
-
2017.10.31
-
MadmanMartian updated:
-
-
Ports chemical heating from TG but does it in a better fashion than click button receive bacon
-
Tweaks the bunsen burner. It now requires fuels of either plasma, glycerol, ethanol, or welding fuel
-
We recommend not using welder fuel unless you're desperate
-
Bunsen burners can now be built from 4 sheets of metal, and deconstructed with a wrench
-
Adds thermometers for checking temperatures of people or reagent containers. Please use with caution
-
-
-
2017.10.30
-
DrSnips updated:
-
-
Airlocks have a screwdriver sound when opening and closing the maint panel. The sound only has a range of one so only people right next to the airlock will hear it. No jokes this time.
-
-
Jeroen52 updated:
-
-
Added the Dorf lawset, made for Dwarf Fortress.
-
-
MadmanMartian updated:
-
-
Bees no longer attack other bees or mommis
-
Adds the blood moon world event. Board up the windows and hope you have what it takes to survive.
-
-
Pathid updated:
-
-
Things taken out of xenomorph pockets are now properly removed from the contents.
-
-
-
2017.10.29
-
CptWad updated:
-
-
Fixes various things on bagelstation
-
made the cult dungeon harder.
-
-
Emilc4h updated:
-
-
Added a filled Refigerated Blood Bank to Boxstation's Medbay, replacing the old tables used for storing bloodpacks.
-
The Sterile Equipment Crate from Cargo now includes one box of Body Bags.
-
-
MadmanMartian updated:
-
-
Syndicate IDs or voice changers now block AI camera tracking as it was causing an exploit that would yield the persons real identity
-
-
Shadowmech88 updated:
-
-
The Red Ribbon Arm and the roulette revolver can now be obtained via Xenoarchaeology.
-
Added a new vault, the skeleton den. Don't rattle their bones!
-
Added a new system by which mappers may create moving hazards that follow simple or complex courses without needing to touch any code.
-
Police tape, engineering tape, atmospherics tape, label rolls, gauze, ties, stethoscopes, bedsheets, and boiled spaghetti can now be used as restraints.
-
Diona nymphs, hulks, golems, and non-advanced-tool-users such as monkeys can now fire laser tag guns.
-
Laser tag vests can now be attached to jumpsuits, meaning any mob that can wear a jumpsuit can now play laser tag.
-
-
-
2017.10.28
-
Pathid updated:
-
-
Delimbing a dead spider queen will no longer make it invisible.
-
-
-
2017.10.24
-
Unknown-as-Captain updated:
-
-
Advanced Security Cameras now show cyborg cameras, just like their non-advanced counterpart.
-
-
-
2017.10.22
-
MadmanMartian updated:
-
-
More variety added to the halloween costume crate
-
You can now bully Monkeys with disarm again
-
You can now bully Martians with disarm
-
-
Shadowmech88 updated:
-
-
Added a new spell, Doppelganger. It creates a body double of the wizard that can be used for misdirection or reinforcements. If the spell is upgraded, the doppelganger becomes able to fire magic missiles.
-
Ghosts can now interact with the holodeck control console to be transformed into a holographic person and placed in the holodeck. The player may choose to turn back into a ghost at any time, and can still enter their original body after doing so.
-
Simple animals can now be mutated with phazon. Though they cannot be injected, the phazon can be applied to them via splashing, spraying, chemical smoke, and so on.
-
-
ShiftyRail updated:
-
-
Admins can now choose how many traitors they want to create with the "Create-Antagonist" verb.
-
-
-
2017.10.21
-
Shadowmech88 updated:
-
-
Added a new mech tailored for Engineering, the Clarke. It moves slightly faster than a normal human, can move freely in space, and can withstand temperatures up to 100,000 degrees. It also has four module slots, and a built-in air scrubber.
-
Added a new wizard spell, Fist. Casting it delivers a punch to everyone in view.
-
Mobs made invisible or practically invisible via alpha manipulation, such as via a cloaking cloak or invisible spray, can no longer be seen by HUDs or tracked by AI cameras.
-
Fixed Xenoarchaeology find picking so that recent Xenoarch additions can now be obtained in-game.
-
When a player dies as an adamantine golem, they must now wait 10 minutes before they can spawn again using an adamantine golem rune.
-
-
ShiftyRail updated:
-
-
Fixes a typo in Packed's EVA
-
Cigarettes no longer display an inappropriate message when put out.
-
-
-
2017.10.20
-
DrSnips updated:
-
-
Airlocks now make a small screwdriver sound when you screwdriver the panel on them.
-
-
Shadowmech88 updated:
-
-
Added the exosuit-mounted Rapid Engineering Device. Formerly the mech RCD, this module is now a combination RCD/RPD/socket wrench. Use it on pipes while in RPD mode to wrench/unwrench them.
-
Added the exosuit-mounted Engineering switchtool. Contains a crowbar, screwdriver, huge welding tool, wirecutters, wrench, multitool, cable coil, T-ray scanner, atmospheric analyzer, soldering iron, and silicate sprayer.
-
Added the exosuit-mounted metal foam grenade launcher. The grenades can be detonated prematurely if you attempt to fire again before the cooldown is up.
-
Added the exosuit-mounted automatic floor tiler. If the mech passes over a lattice or metal foam floor while the tiler is active, it will place a plating down on that tile. If you pass over a plating while it is active, it will place a floor tile down on that tile.
-
Added the exosuit-mounted inflatable barrier launcher. Launches grenades which release inflatable barriers, and can switch between inflatable walls and inflatable doors. It has a separate mode for deflating the inflatable barriers.
-
Added the exosuit-mounted radiation collector array. It allows the mech's battery to be charged from nearby radiation sources such as a singularity or supermatter shard. It functions much in the same way as standard radiation collectors.
-
All mechs now provide 50% radiation shielding.
-
-
eplgr updated:
-
-
Uplink bug detector: (new!) Activating it will disable cameras nearby, plus the ones far away randomly, for some time.
-
Uplink bug detector: changed price from 3 to 5 telecrystals.
-
-
-
2017.10.17
-
WhiteHusky updated:
-
-
Using items that check if the mind is a vampire should no longer cause a runtime if the human had no mind.
-
-
-
2017.10.16
-
Shadowmech88 updated:
-
-
Added wizard potions to spellbooks. They can be found in a new section at the bottom, below artifacts and spell bundles.
-
-
ShiftyRail updated:
-
-
You can now extinguish people by hitting them with clothing while on help intent.
-
-
-
2017.10.15
-
DamianX updated:
-
-
Removed the ability to craft crossbows.
-
-
-
2017.10.14
-
DrSnips updated:
-
-
Wizards now have the choice to summon swords. Similar to the other summon spells, it will drop a sword and a set of armor for everyone.
-
-
-
2017.10.13
-
DamianX updated:
-
-
Lanterns can now be spooked.
-
-
MadmanMartian updated:
-
-
Can now use scythes against biomass
-
Big mobs can no longer destroy invulnerable walls
-
Can now print floral data disks and genetic data disks via the protolathe
-
Can no longer stack mass drivers on a tile
-
-
Shadowmech88 updated:
-
-
The fleshshot has been repaired and re-added to borers, now verified crash-free.
-
-
ShiftyRail updated:
-
-
Fixes a bug in which a mouse could remove reagents from the deep fryer.
-
-
-
2017.10.12
-
DeityLink updated:
-
-
Sheets of wood, wooden floor tiles, grass tiles, carpets and arcade carpets, are no longer conductive.
-
-
Unknown-as-Captain updated:
-
-
Added lasagna. Recipe is 2 flattened doughs, 2 meat, 1 cheese slice, 15 tomato juice, and 1 eggplant.
-
-
-
2017.10.11
-
DamianX updated:
-
-
Fixed a few bugs related to flavor text.
-
-
The-Whargoul updated:
-
-
Added camera bugs and handheld tv to the item list for the detective's secure closet
-
Removed the camera bugs and handheld tv that were mapped into bagelstation to prevent duplication of these items.
+
Can now carry rollerbeds on labcoat suit storage.
Zth-- updated:
-
Now walls properly update their icon when destroyed
+
Species with no blood (slime people, for example) no longer leave blood splatters when attacked
-
-
2017.10.08
-
DamianX updated:
+
imw-Oculus updated:
-
The R-UST fuel injector no longer requires cable coils in construction. It can now be deconstructed, and its circuit board is available from the circuit imprinter.
-
The R-UST fuel injector has a new UI.
-
The R-UST room on Defficiency now provides stock parts to build a tokamak and a fuel injector
-
The R-UST tokamak no longer requires cable coils to be constructed. It can now also be deconstructed. Its circuit board is available at the circuit imprinter.
-
The gyrotron control computer can be buffered in multitools.
-
-
DelaminatingShard updated:
-
-
Fixed the areas in bagel's IAA office
-
-
Shadowmech88 updated:
-
-
The pintpointer's tracking function is now based on who pours the drink, not who is holding the glass into which the drink is poured. This means that, for example, if you pour pintpointer into a glass that is sitting on the ground, that new pintpointer will still track you. Also, as a reminder, the distance to the target is indicated by how full the mug on the pintpointer's screen is, if it has a target.
-
-
-
2017.10.07
-
Shadowmech88 updated:
-
-
Added a new drink recipe, the pintpointer. It can be made by mixing atomic bomb and Syndicate bomb. If pintpointer is made in or poured into a glass held by someone, the display on the pintpointer will indicate its proximity to that person.
-
-
-
2017.10.06
-
SonixApache updated:
-
-
O2 lockers no longer have N2 tanks in them
-
Every map now has N2 lockers near the trader dock, and maybe one or two in maint somewhere
-
-
-
2017.10.05
-
DrSnips updated:
-
-
Added a spawn only version of the surgeon switchtool that has all advanced surgery tools in it.
-
Added a spawn only version of the holo switchtool that has all modules pre-enabled for it.
-
Laser scalpels in cautery mode can now have their cautery removed by a screwdriver. This is helpful for switchtool module replacement. Using the cautery on the scalpel puts them back together.
-
-
-
2017.10.04
-
Cyadox updated:
-
-
Adds peg limbs to wooden plank crafting menu. Credit to DrSnips for the sprite
-
Peg limbs are now used to give someone - you guessed it - peg limbs instead of planks
-
Removes the ability to use planks to give someone peg limbs
-
-
-
2017.10.03
-
DrSnips updated:
-
-
Xenoarch hand picks no longer refer to a fraction for their name and now refer to how much they dig directly in the name.
-
Xenoarch tape measures now read the depth of a wall instantly.
-
-
N3X15 updated:
-
-
Temporarily removed fleshshot from borer evolution tree while a severe server crash issue is fixed.
-
-
Shadowmech88 updated:
-
-
Envelopes can now hold all tiny items. Items which have interactions with paper/envelopes, such as pens, stamps, et cetera must be inserted via Alt+clicking the envelope with the item in your active hand.
-
Photos can no longer be attached to the front of envelopes, but can now be inserted inside envelopes.
-
-
-
2017.10.02
-
Shadowmech88 updated:
-
-
Decoy balloons can now be scanned by the mechanic's device analyzer.
-
-
SonixApache updated:
-
-
Raised access button range to 8 (just over one screen of view range)
-
-
-
2017.10.01
-
SonixApache updated:
-
-
unfucked windoor smartglassifying
-
-
-
2017.09.30
-
DamianX updated:
-
-
Vending machines may display ads when selecting a product. (after 5 years of them being in the code)
-
-
Rouge-Rogue updated:
-
-
changes oxygen consumption and co2 production from breathing
-
-
-
2017.09.29
-
DamianX updated:
-
-
Atmos monitor and AAC can now get N2O concentration from sensors.
-
-
DrSnips updated:
-
-
Bone repair surgery no longer loops.
-
-
N3X15 updated:
-
-
Nukeop leaders are a bit more obvious. They now have a title in front of their name and a special HUD icon.
-
"Nukeops are now told to follow their leaders' instructions. Failure to comply may result in being stunned or even jobbans."
-
-
Unknown-as-Captain updated:
-
-
Fixed Advanced Cameras Console only updating cameras if someone was watching the console at the time.
-
Fixed Advanced Cameras Console erasing all cameras on display if any of them were successfully updated thanks to someone watching the console.
-
Fixed Advanced Cameras Console camera updating failing most of the time even with someone watching the console, which was actually good due to the bug above.
-
Fixed Advanced Cameras Console camera updating working completely randomly based on camera position on the miracle chance that it did work AND had someone watching the console.
-
Fixed Advanced Cameras Console camera updating giving javascript errors most of the time even if successfully updated, randomly used the right code thanks to good random position, AND had someone watching the console to enable updating in the first place.
-
Fixed Advanced Cameras Console alarm lights being sometimes inverted even if it miraculously worked, randomly used the correct code, AND randomly didn't cause javascript errors, AND had someone watching the console.
Fixed the zoom bar formatting in the Advanced Cameras Console and Crew Monitoring Console.
-
Fixed wrong messages in the Advanced Cameras Console.
-
Removed debug text in the Advanced Cameras Console.
-
Fixed Advanced Cameras Console letting you view out of disabled cameras, mostly thanks to not updating.
-
Fixed EMPs not disabling cameras in the Advanced Cameras Console.
-
-
-
2017.09.28
-
Intigracy updated:
-
-
Nofruits now let you hit them with an object or alt-click to start/stop cycling. Verbs are gay but that's still an option too.
-
-
Unknown-as-Captain updated:
-
-
Implemented clickdrag actions for storage coats, same as other storage objects.
+
Fixes wrenching and unwrenching sleepers
jknpj updated:
-
Fixes exploding necromorphs exploding non-stop until it crashes the server
+
Fixes cyborgs not understanding most languages and not being able to speak sol common/gutter by default.
+
Service cyborgs now speak more languages(Slime, Vox, Golem, Grey and Clatter)
+
Fixes AIs not understanding a few newer languages.
+
Fixes librarians not getting a random language at roundstart(Except cult/xenomorph/martian).
+
Fixes babel syndrome not giving you a random(non cult/xenomorph/martian) language.
+
After freezing all AIs galactic common translation services to search for 'strange logs' NT is slowly returning them to normal operation. Report to your local Research Director if you still have any issues with your station's AI.
-
2017.09.26
-
Blithering updated:
+
2018.04.23
+
Allspice updated:
-
Added a new outfit for bridge officers
-
-
Unknown-as-Captain updated:
-
-
Fixed rollerbeds stopping bullets if someone was buckled in.
+
Increase cigar and cigarette capacity by 5, hooray for explosive ciggies.
+
Comms talismans can now be used 5 times.
-
2017.09.25
-
CptWad updated:
+
2018.04.22
+
Pathid updated:
-
New Chapel sprites/stuff available on bagelstation! Other stations soon(tm)
-
Bagelstations ore processors and vox shuttle should now work properly despite cursed issues
-
-
DamianX updated:
-
-
Moving or destroying an object wrenched on a connector port will now properly disconnect the two.
-
Vampires can no longer enthrall implanted people unless they have accumulated 500 blood.
-
Vampires will now be properly smitten by God when picking up the bible.
-
-
DrSnips updated:
-
-
NASA voidsuit lockers now have a pair of red magboots in them.
-
Things with hot edges can light your candles and smokes for sure now.
-
-
Duny updated:
-
-
(Deff) Added scrubbers to the research outpost. The waste pipes empty directly in space by default, the pump can be found in the atmospherics room.
-
-
HarseTheef updated:
-
-
Fixes the Captain's Greaves examination text
-
-
Kurfursten updated:
-
-
Clipboard sprites should now properly update when you do anything like take out paper, stamp paper, etc.
-
You can now click a filing cabinet with a clipboard to dump the contents within.
-
-
PromethTK11 updated:
-
-
Fixed the packed cell lockers not working propetly.
-
Aaand more packed misc. tweaks.
+
The AME now shuts down when out of fuel instead of staying in an "active" state while producing no power.
-
2017.09.24
-
Cyadox updated:
+
2018.04.17
+
Allspice updated:
-
Allows you to remove peg limbs as intended
+
Double-invoked Summon Cultist rune now tells you whether each choice is dead or near you.
-
DrSnips updated:
+
Pathid updated:
-
Slimes (the mob) can no longer be phazon junkies and get phazon mutations.
-
MoMMI material synth can now scan/produce more materials.
-
-
Kurfursten updated:
-
-
You can now view the supply console even without an ID, but using most of the buttons requires access.
-
The supply console now has a QM-PIN restricted permissions screen that allows you to set auto-approval, restrict orders from silicons, or require the PIN for any action.
-
Permissions screen also has a requisitions function to allow approved orders to be paid from the Cargo account.
-
Removed the long-defunct "supply tax" calculation in ordering crates, meaning you can now order as much as you have money for with no phantom tax on top
-
-
SonixApache updated:
-
-
you can now make plant-b-gone with solanine
-
-
jknpj updated:
-
-
Fixes an ancient bug that prevented big xenos and larva from being handcuffed/bodycuffed. Big xenos can break cuffs as fast as a hulk while larva take the same amount of time as other carbons.
-
Fixes an ancient bug that prevented xeno larva from being stunned.
-
Also fixes larvae hide spell.
-
Removes non-used head and chest slot from big xenos.
-
Big xenos and larva can't ventcrawl or evolve while cuffed.
-
Updates xeno inventory window.
+
Corrected a longstanding bug preventing nanopaste from being used on robotic limbs and organs.
-
2017.09.23
-
DamianX updated:
-
-
Changed the telecommunications machines construction/deconstruction/repair procedures. See wiki.
-
Fixed the telecommunications machines not degrading at high temperatures.
-
Fixed the telecommunications machines not removing the links between them upon deletion.
-
Allowed the telecommunications machines to be scanned by the device analyzer
-
Fixed bananium, uranium floors activating when they shouldn't.
-
-
Unknown-as-Captain updated:
-
-
Delivery chutes don't accept anchored items. Please report if this breaks any intended Cargo delivery methods.
-
-
-
2017.09.21
-
DrSnips updated:
-
-
Roboticist's pda now come with the R.O.B.U.T.T. pda cartridge. Allowing you to use your pda as a cyborg analyzer when enabled.
-
Plasma saw added to the protolathe, comes in your favorite color for plasma related things. Definitely only to be used for medical purposes.
-
Bone mender added to the protolathe, it fixes broken bones completely in one step.
-
-
-
2017.09.19
-
Commandersand updated:
-
-
Phazon mechs no longer break immersions
-
+
2018.04.16
DeityLink updated:
-
Admins now have a panel that allows them to easily control the Emergency Shuttle, its docking ports, as well as the Escape Pods.
+
Bug nets now have a limit of 100 bugs that they can hold at once.
+
Apiaries may no longer accept more than a total of 40 bees from a net.
+
When emptying a bee net, bees are split in swarms of 20 instead of 5.
+
Bee corpses now look for already existing corpses on spawn so they can add themselves as overlay. So there should no longer be more than one corpse per tile.
+
+
unid15 updated:
+
+
Admins may now select a difficulty level when loading The Hive away mission. The difficulty levels are: Hardcore (normal), Casual (33% respawns, pylons emit weak radiation), Baby's Day Out (no respawns, pylons emit temporary oxygen damage instead of rads). The difficulty level affects the final score.
+
Cockroaches will no longer tolerate getting sprayed with unstable mutagen, and WILL fight back.
+
Added cockroach matriarchs. A rare sight to behold, they're proficient at laying eggs - if fed properly.
+
Nerfed the amount of nutriment and chitin drops from small cockroaches. Larger ones, however, drop much more.
-
2017.09.18
-
DelaminatingShard updated:
+
2018.04.14
+
Intigracy updated:
-
Added new fat sprites for some uniforms
-
Updated some existing fat uniforms
-
Fixes the west view for the regular CMO uniform (blue instead of green cross)
+
Fixes turning water to wine via enzyme instantly turning it into vinegar.
-
HarseTheef updated:
+
Pathid updated:
-
Grammar Fixes
+
Shotgun blanks work now, when previously they could not be loaded into anything. They may be for putting on a show, but they will do some moderate burn damage to someone up close.
+
Slimes can once again be operated upon for your ghetto slime core removal needs.
+
Made disease analyser UI buttons work with more precision. If you have multiple samples of the same virus you'll no longer be forced to eject or print from all of them with each button press.
+
+
Probe1 updated:
+
+
Inaprovalines metabolism has been lowered so it lasts much longer.
+
Deffs AI Core has a newscaster in it for you rascally AIs.
+
+
code-alpha45 updated:
+
+
Restores lost feature that allowed you to talk into held radios without having the microphone on, use .l and .r to talk into the radio in the respective hand
+
The ERT radio channel is now accessed with the '.-' key
+
+
+
2018.04.13
+
Allspice updated:
+
+
Re-adds amanatin to destroying angels and reduces potency.
+
Staves and tele scrolls now fit in gemsuit storage.
+
+
Kevak updated:
+
+
Reports indicate Local Wizard Federation Sects have received some tips from distant colleges. Beware of wayward knocking and hide your valuables. Electronic locking is no longer safe!
+
+
+
2018.04.12
+
BurntDevil updated:
+
+
Added deff style shutters the Bagel Armory. Expanded space enough to allow proper foot traffic.
+
+
+
2018.04.11
+
MadmanMartian updated:
+
+
Adds new traitor shoes with a toggleable knife, for the dapper IAA who wants to kick something
+
+
Pathid updated:
+
+
Fixed an error concerning how golem death was handled. Golems will now leave behind only dust instead of dust and a redundant body. Reviving golems via adamantine slime extract should work properly now. Cooldown timer for being a new golem after dying as a golem should work properly now.
+
+
+
2018.04.09
+
Allspice updated:
+
+
Free and Summon Cultist spreads a flat amount of damage between invokers instead of dealing 10/15 damage to each.
+
Removes cult rune blood costs.
MadmanMartian updated:
-
You can now scan a severed head with a health analyzer to see if it still has a mind
-
-
SonixApache updated:
-
-
Starscreen shield generators are now built with two capacitors rather than two pico manipulators.
+
You can no longer perform CPR if you lack lungs or can not breathe.
-
2017.09.15
-
N3X15 updated:
+
2018.04.08
+
Allspice updated:
-
Fixes money duplication bug in PoS terminals.
-
Fixes money spawning bug in PoS terminals caused by acceptance of negative prices.
-
Fixes PoS terminals showing wrong messages to some people when logging in.
+
Lightning spell does damage again.
+
+
MadmanMartian updated:
+
+
Things that shock you on contact (airlocks, grilles, etc.) when you're hitting them with something now take into account the items siemens_coefficient
-
2017.09.14
-
Duny updated:
+
2018.04.06
+
Pathid updated:
-
(Deff) Added rollerbeds to the new medbay.
-
(Deff) Fixed research outpost disposals throwing you into the o2 miner rather than outside.
-
(Deff) Added a tile painter to the theatre backroom.
-
(Deff) Fixed costume spawners in the theatre not spawning anything.
-
-
SonixApache updated:
-
-
Added two alias commands for smartglass. The three valid commands are now toggle_transparency, toggle, and cycle.
+
Getting changed into a humanoid form by the staff of change will now tell you your species instead of "Human."
-
2017.09.13
-
Kurfursten updated:
-
-
Fridges no longer spam when bag loaded
-
-
Unknown-as-Captain updated:
-
-
Phenol kudzu now works again
-
Buffed kudzu growth speed
-
Removed maximum growth radius for kudzu vines (NOT for creeper vines, which still have a maximum radius of 4)
-
-
-
2017.09.12
-
DeityLink updated:
-
-
Fixed Bagelstation's Elite Syndicate Shuttle being outdated.
-
-
SonixApache updated:
-
-
Added smartglass; glass that can be digitally switched between transparent and opaque. Apply a wired glass tile to a window or windoor to create it, then multitool it for setup.
-
-
Unknown-as-Captain updated:
-
-
Ctrl+arrowkeys to turn now works on vehicles and chairs.
-
You can now scoot while sitting on office chairs, and kick nearby structures to propel your chair away. Scooting backwards is faster than scooting forwards. For balance reasons, scooting is slow and is disabled by ZAS.
-
-
-
2017.09.11
-
Duny updated:
-
-
Added the Refrigerated Blood Bank, essentially a smartfridge for blood packs.
-
(Deff) Completely reworked medbay to get rid of the cramped abomination it was before. Moved toxins a bit further away from it to make room. Removed telescience from science for more room too and gave the telepad to paramedics. Includes the new blood bank.
-
-
-
2017.09.10
+
2018.04.05
DrSnips updated:
-
Pico manipulators now use plasma in place of the old materials.
+
Added a minor threshold to the dizziness/drunk effect so you don't experience a magnitude 10 earthquake when you only take one sip from a basic bar drink.
+
Cigarettes now come with tobacco in them for a true smoking experience.
-
EmiliaMcWaifushitter updated:
+
Pathid updated:
-
Adds the ability to slide stun talismans into books which stun the next person who reads said book
+
Monkeys on methylin or in monkey mode can now do more than they could before. This includes: drag-dropping people into medical machines, folding bodybags, being converted to religions, piloting spacepods and more.
-
Intigracy updated:
+
code-alpha45 updated:
-
Adminghosts no longer have to wait on the cooldown for turning on and off light switches.
+
Rechargers can now be constructed and upgraded
+
Recharger circuit board added to the soldering iron and circuit imprinter
-
ValkyrieSkies updated:
+
+
2018.04.04
+
Allspice updated:
-
Gives Vox magboots a slowdown less than standard magboots, and enables a customized version of the magboot stomp command.
+
Free Cultist splits damage between invokers like Summon Cultist instead of focusing damage on one.
+
Law update sound plays when silicons receive a law modification, as it should.
+
+
MadmanMartian updated:
+
+
Can now grab somebody and drag them with you again.
+
+
+
2018.04.03
+
MadmanMartian updated:
+
+
Adds mushroom people. Their seeds are acquirable from either the vox outpost or xenoarch seed sites.
jknpj updated:
-
The artifact gigadrill got a new icon thanks to the russian community
+
Newly discovered 'bee gas' deemed too volatile by NT researchers and will no longer be mined.
+
Fixes xenoarch robotic remains(it's just fluffy trash) having no icon.
+
NT MoMMIs and Engineering Cyborgs appear in the Engineering Cameras Console again.
-
2017.09.09
-
Duny updated:
+
2018.04.02
+
Kurfursten updated:
-
(Meta) Fixed the access requirements to open the windoors in the bridge.
-
(Meta) Added a filling cabinet to the QM's office.
-
(Meta) Reworked the IAA office/courtroom region, mainly to drastically improve IAA player quality of life, and to make the courtroom a bit more welcoming for all the future trials which we all know are never going to happen.
+
The communications computer can now be used to close off the station dock from traders, requiring an ID with HoS access or head access during a red alert. The same access is required to re-open the port.
+
Admins can now use the communications computer and all its features.
+
+
Pathid updated:
+
+
Soul-stoning a non-human mob will no longer delete all their held items.
+
+
+
2018.04.01
+
Blithering updated:
+
+
more options for beekeepers, introduces two new kinds of bees!
+
+
Kurfursten updated:
+
+
Silicons are now clown compatible.
+
+
MadmanMartian updated:
+
+
Adds new gamemodes, to prepare for antag datums
+
Diversifies the cargo crate structure.
+
Peace, tranquility, and gondola.
+
+
imw-Oculus updated:
+
+
Adds peace (pax) implants. They steadily feed off of the host's nutrition, and prevent the host from performing violent actions. Temporarily malfunctions if the host has >=15u Methylin in their system, or is starving. Implant is destroyed upon removal from the host. They can be found in the Trader Vendor, for now.
+
+
+
2018.03.28
+
Pathid updated:
+
+
Having a borer as a monkey or nymph will no longer prevent you from ventcrawling.
+
+
+
2018.03.27
+
Irradiation updated:
+
+
Cryptobiolin metabolism has been reduced to 0.2
+
+
Micluc updated:
+
+
Having more than one soybean in the microwave will display 'Soybeans' instead of 'Soybeans'
+
Having more than one grape or green grape will display bunches of grapes now
+
+
+
2018.03.26
+
Irradiation updated:
+
+
The price for the glock pack crate in cargo has been reduced to 60$.
+
+
+
2018.03.25
+
Pathid updated:
+
+
Fixed vampires mistakenly being able to enthrall chaplains.
+
+
jknpj updated:
+
+
Makes the emagging of silicons sparky again
+
+
+
2018.03.24
+
DrSnips updated:
+
+
Added reinforced cyborg components. They resist about a third of the damage dealt to it. They can be found in the components tab in the exosuit fab after some research. They require a variety of materials to make.
+
Added the reinforced cyborg torso. When used in the construction of a cyborg it makes the resulting cyborg come pre-installed with reinforced cyborg components. It costs the combined cost of a normal torso and all of the new reinforced components. It can be found in the components tab as well.
+
You can examine components to tell if they are damaged at all now.
+
+
MadmanMartian updated:
+
+
Adds functionality to the previously useless wires on the rnd machines, one if you pulse it, it keep creating the last thing it was told to make. The other if you attach a signaler to it, it will pulse a signal through that signaler.
+
+
ShiftyRail updated:
+
+
In ragin' mages, wizards no longer instantly die when in crit.
+
Custom religions can print their Bible at the library checkout computer, including the Chaplain's.
+
+
+
2018.03.23
+
Irradiation updated:
+
+
Renamed the .45 glock gun & ammo crates to .380 instead.
+
+
Pathid updated:
+
+
Reworked circuit imprinter reagent storage. Imprinters now actually hold reagents in their internal beakers instead of a phantom reagent holder that was destroyed when parts were swapped.
+
+
Probe1 updated:
+
+
(Packed) Changes tech storage to have regular walls instead of Reinforced walls. Secure tech storage remains reinforced.
+
+
+
2018.03.22
+
BurntDevil updated:
+
+
Expanded Deff's bridge to have more space for gameplay options
+
+
MadmanMartian updated:
+
+
Adds a code function to disable mesons for mappers so you can't peek at secret vaults
+
+
Pathid updated:
+
+
Fixed items carried by monkeys, nymphs, etc. displaying icons as if they were in the mob's right hand when carried in the left hand.
+
Red and yellow floorbots are now possible to build from their respective-colored toolboxes.
+
+
Probe1 updated:
+
+
Metaclubs telecomms shouldn't die on its own anymore.
+
+
+
2018.03.21
+
Pathid updated:
+
+
Returned diona photosynthesis to how it was before a major unintended buff.
+
+
+
2018.03.20
+
Probe1 updated:
+
+
Bagel Genetics now has a service desk and the consoles are closer together.
+
+
+
2018.03.17
+
MadmanMartian updated:
+
+
Adds ablative plate armor
+
Adds armor shards you can attach to your jumpsuit to give you a bit more armor
+
+
+
2018.03.16
+
DeityLink updated:
+
+
Hyperzine will now divide slowdown from worn clothing/held items (like magboots, spacesuits, or gatling guns) by 2.5 instead of completely removing it.
+
+
+
2018.03.15
+
Commandersand updated:
+
+
Added some sounds to the sound synth the clown/mime gets
+
+
DamianX updated:
+
+
The gas mixer interface will show the english name for the direction of the nodes rather than just 1 and 2.
+
+
Pathid updated:
+
+
Fixed a long-standing bug which caused the blood vessels of a human whose blood level had dropped to zero, or close to it, to glitch out and become unusable forever.
+
Changed how disposals pipes check for fat people, so that you will stop being considered fat in the event you lose weight in transit. (Although if you're already stuck, this won't unstick you without another package to push you through.)
+
Fixed minebot AI getting stuck and having to be reset constantly.
+
+
Probe1 updated:
+
+
Bagel now has a bloodbank fridge in Medbay Storage where the bloodbags were.
+
Bagel salvage ship and vox skipjack now arrive way closer to the vox tradepost than before.
+
+
+
2018.03.14
+
DamianX updated:
+
+
Added worn sprites for the diagnostic HUD. It's no longer invisible when worn!
+
Staff of the necromancer will no longer put dead players that became some other mob back into their old zombie.
+
Unzombified zombies will properly regain their original player.
+
Whacking zombies with a bible to deconvert them now has a cooldown.
+
+
DrSnips updated:
+
+
Added the capillary laying operation tool (CLOT). An advanced version of the fixOvein. Using the CLOT in hand will toggle it to a secondary state where it can inject biofoam during surgery (the person needs to be on a valid surgery table/surface). You need to feed it rolls of gauze to fill it with biofoam at a rate of 1u per roll. Advanced trauma kits will make 5u per kit.
+
+
Pathid updated:
+
+
Fixed circuit imprinter resource efficiency not benefiting from better manipulators.
+
+
TurboGay updated:
+
+
Altered several engineering crates (emitter, field generator, particle accelerator, shield generator, starscreen shield generator and capacitor crates) access requirements from CE to engine access.
+
Altered motorized wheelchair crate access requirements from CMO to medical access.
+
+
jknpj updated:
+
+
Fixes two 2-years old runtimes with action buttons.
+
+
+
2018.03.13
+
Irradiation updated:
+
+
Added a blood bank fridge in metaclub medbay in place of the bloodbag table in Metaclub's medbay.
+
+
Pathid updated:
+
+
Fishtank-related circuits are now makeable from circuit imprinters.
+
+
+
2018.03.12
+
DamianX updated:
+
+
The engineering cyborgs magnetic gripper can now interact with things it's gripping (e.g. airlock electronics, tanks). It can also hold additional items such as table/rack parts, and mountable frames (for APC, air alarms, ...)
+
+
Pathid updated:
+
+
Circuit imprinters now use much less sulfuric acid when printing any circuit that is makeable with a soldering iron.
+
+
Probe1 updated:
+
+
All research outposts now have anomaly storage containers to help you transport dangerous large artifacts.
+
+
+
2018.03.11
+
DamianX updated:
+
+
Imidazoline will no longer heal mechanical eyes.
+
Fixed a bug that prevented ghosts from viewing body scanners and sleepers interfaces.
+
Updated the cyborg self-diagnosis UI.
+
Cyborgs and MoMMIs can now use their modules while buckled.
+
+
Probe1 updated:
+
+
Adds magnificent magboots. It's what mag stands for! Sprites by DrSnips/DrSlimes
+
+
jknpj updated:
+
+
Fixed an ancient bug that allowed the robotics console bypass hacked traitor borgs anti-termination safety
+
+
+
2018.03.09
+
DamianX updated:
+
+
Headset encryption keys are now tiny.
+
+
MadmanMartian updated:
+
+
Emitter mirrors and splitters now mirror and or split lasers fired at them.
+
+
Pathid updated:
+
+
Fixed having to enter *custom emotes twice.
+
+
Probe1 updated:
+
+
Bagel now starts with twice as much power as it does currently. Overall, it is less than half of what it was a month ago but is now significantly higher giving engineers a longer opportunity to set up power.
+
+
jknpj updated:
+
+
Fixes living cyborgs being untippable
+
Fixes cyborgs having access to binary even if their binary communication device is broken or offline
+
Fixes *flap and *clap not working on cyborgs
+
+
+
2018.03.08
+
Pathid updated:
+
+
Facehuggers now wander a little if they find another facehugger on their turf.
+
Toy facehuggers no longer hunt or remove equipment (although Lamarr still will). Wearing a dead, toy, or sterile facehugger no longer fools hugger AI. Huggers should no longer hug through mechs, closets or other containers.
+
Facehuggers will try to keep their victims alive by auto-connecting to any internals they had enabled. (Don't ask how they know how to do that.)
+
Cyborgs that are reset or destroyed while holding items inside storage modules will drop those items instead of deleting them.
+
+
Probe1 updated:
+
+
(Packed) Reworks packed kitchen to have more space, bartenders area to have more space. Moves MoMMI nest next to CE office. Moves maint behind the kitchen downward to atmos. Botany has been expanded by one tile and some things have been shifted around.
+
(Packed) The ERT shuttle now arrives north of the AI core instead of where the emergency shuttle docks.
+
+
jknpj updated:
+
+
MoMMIs don't start with the default flashlight/flash anymore
+
+
unid15 updated:
+
+
Fixed gremlins spamming messages when locked in cages, or when near windows
+
Gremlins can now use operating tables to perform surgery (operating them in the same way as deepfryers - using nearby items). Given their tendency to run around, the surgery can fail if they aren't restrained.
+
Changed how mimic meat works. It's also slightly toxic now.
+
+
+
2018.03.07
+
DamianX updated:
+
+
Security armor and hardsuits can store the blunderbuss.
+
+
DrSnips updated:
+
+
Added a surgery tab to the protolathe to house all surgery related designs to cut down the clutter.
+
+
Kurfursten updated:
+
+
You can now add and remove playlists from the juke by inserting or ejecting vinyls on the settings page.
+
+
+
2018.03.06
+
DamianX updated:
+
+
Consecutive repeated messages in chat will be squashed into one. This behaviour can be turned off in your chat preferences.
+
+
Pathid updated:
+
+
Fixed cell chargers not charging low-capacity power cells.
+
Fixed power cell lights not updating when removed from cyborg recharge stations.
+
+
imw-Oculus updated:
+
+
Display cases and fish bowls can now be built again
+
+
+
2018.03.05
+
DrSnips updated:
+
+
Fixed magic butterflies from magic butterfly knifes not self destructing.
+
+
Kurfursten updated:
+
+
Metaclub: The Vox have moved out of the deep space base. It remains for vault hunters, but has no Trader-related items, blueprinted areas, trader shuttle, or research ferry.
+
Metaclub: Vox station replaced with one large 'mothership' that needs to be powered and can stop at 3 locations (main station, solar farm, asteroid casino).
+
There is now a "Trader Shoal" joint account. All traders know the number and PIN. It starts with 0 credits and earns no wages over time. This allows Traders to use custom vendors.
+
+
+
2018.03.04
+
Pathid updated:
+
+
Mysterious d20s are now scannable again (by the syndie device analyzer only).
+
+
Probe1 updated:
+
+
Removes SCP-294 (The coffee machine that creates any chem in the game freely) from Bagels Asteroid. The sneaky coder cabal was here.
+
+
+
2018.03.03
+
Anglosphere updated:
+
+
Butter
+
Liquid Butter (Reagent)
+
+
Irradiation updated:
+
+
Lowered the recipe of Saltwater to 5u Sodium Chloride/20u Water from 5u Sodium Chloride/50u Water.
+
Lowered the resulting amount of Saltwater to 20u from 50u.
+
+
Jared-Fogle updated:
+
+
Adds breathalyzers to bars and autolathes. Compete to see who's liver can withstand the most torture.
+
+
MadmanMartian updated:
+
+
Cloning console has a small number preview of how many records are currently active and saved
+
+
Probe1 updated:
+
+
Packed now has lightswitches in Mechanics and Virology. Wardens room now requires security officer access instead of general brig access that paramedics have. The brig door button now works properly.
+
Packed no longer has an electrified grille in maintenance behind Medbay. Plus a lot of minor bugfixes.
+
+
SonixApache updated:
+
+
Lifeline now heals you and replenishes a bit of blood.
+
+
+
2018.03.02
+
DamianX updated:
+
+
All pinpointers now update four times more frequently than before.
+
+
Probe1 updated:
+
+
Fun little maze vault for you to explore.
+
+
Zth-- updated:
+
+
Fixed custom vending machines bugs: list duplication, traders not being able to manipulate them, and not linking to cargo correctly
+
Added stack support to them
+
+
+
2018.03.01
+
DrSnips updated:
+
+
Fixed issues with switchtools' attack animations.
+
+
Irradiation updated:
+
+
Added Saltwater. It induces puking when inside the body.
+
+
MadmanMartian updated:
+
+
Adds jars for storing reagents and items in. Items in the jar are constantly touched by the reagents inside, so be careful what you mix up.
+
Internal organs in the presence of peridaxon are now healed over time.
+
+
Pathid updated:
+
+
Fixed a bug with nanite infection where it had to pass a redundant permeability check.
+
Fixed a bug where when butchering something, if you had cut out all the meat first, you were locked out of harvesting other things like skin and teeth.
+
Fixed broken vendors not being wrenchable.
+
+
RealestEstate updated:
+
+
Empty trash bags can be worn on the suit slot, and empty chicken buckets can be worn as hats. Sprites courtesy of Blithering
+
+
Zth-- updated:
+
+
Fixed borgs being immune to fire.
+
Engiborgs and mommis have protection against it.
+
New drunkness camera effect
+
+
+
2018.02.28
+
DamianX updated:
+
+
Creating a barricade on a door won't open said door.
+
Fixed an issue with barricades on the same tile as doors preventing interaction with either of them.
+
+
Kurfursten updated:
+
+
Added docking lights.
+
+
Pathid updated:
+
+
Ventcrawlers are now able to cancel from exiting vents.
+
+
+
2018.02.27
+
Pathid updated:
+
+
Lots of automated NPC emotes will display correctly now.
+
+
Probe1 updated:
+
+
Custom trade ship for Packed Station.
+
Skellingtons stuffed into the gibber now produce bones instead of human meat. Credit to NigglyWiggly for the sprites.
+
There are now sheets of bones that can be ground up into bone marrow.
+
+
jknpj updated:
+
+
Fixes AI starting with their cameras stuck in the roundstart cuck cube
+
Fixed ushankas having no initial icon.
+
Borgs with no MMI/Posibrain are now registered as 'Robot' in their PDAs.
+
Borgs with damaged/broken cell/actuator can't get up by themselves after being tipped.
+
Hitting a cyborg/mommi with objects that do no damage won't create sparks anymore.
+
The old "Hydrobot" icon is now available for Service Cyborgs.
+
Revived the Soviet MoMMI subtype and created a NT subtype.
+
Derelict MoMMIs now spawn as Soviet MoMMIs: They can't change their names, don't appear on cameras, see static on top of mobs and also come with an RCD, RSF(Rapid-Soviet-Fabricator), instrument synth, soap bar, plasma cutter and automatic ore loader on top of their default MoMMI loadout.
+
Roundstart/built/transformed MoMMIs are now NT MoMMIs: They start on the engineering camera network and can hear engineering radio.
+
Made the Dorf MoMMI Spawner spawn NT MoMMIs with the dorf lawset.
+
Fixed MoMMIs being able to hide their eyes using Hide when emagged.
+
+
+
2018.02.26
+
DamianX updated:
+
+
Fixed a bug that prevented the Blind and Mutate spells from appearing in wizard spellbooks.
+
Multitooling a power cable will now show network load in addition to available power.
+
Fixed implant lockboxes and shotgun shell boxes having the wrong number of slots.
+
+
Kurfursten updated:
+
+
Fixed a bug where the hyperspace at the Mecha Graveyard would not throw you, allowing you to reach CentComm.
+
Increased the size of the Mecha Graveyard dock to accommodate the larger Defficiency cargo/research shuttle.
+
+
Tehsapper updated:
+
+
added automatic charge mode for SMES, allowing them to charge using any amount of available power that is less or equal to their input level. The old ("manual") mode is still there.
+
upgraded SMES have better capacity and max input/output.
+
SMES UI now shows if input terminal or output power cable are missing.
+
fixed being able to reconstruct SMES for free power. New SMES start out with zero charge (roundstart SMES are not affected).
+
fixed SMES not connecting to output powernet upon construction.
+
fixed SMES being able to output (and lose) charge even if there is no powernet.
+
+
jknpj updated:
+
+
The mysterious/cursed dice can't be scanned by device analysers anymore.
+
+
+
2018.02.25
+
jknpj updated:
+
+
From now on most grenades will only be scannable the the traitor device analyser.
+
the device analyser(both normal and traitor versions) can't scan chrono grenades anymore.
+
Inflatables and smoke grenades can still be scanned by normal device analysers.
+
+
+
2018.02.24
+
DamianX updated:
+
+
Internal Affair Agents no longer have maintenance access.
+
+
Kurfursten updated:
+
+
Fixed a bug that let people interact with sleepers from the inside, and others.
+
+
MadmanMartian updated:
+
+
Fixes the unreported bug of changeling monkeys not getting their powers
+
+
Probe1 updated:
+
+
Bagel now has a unique vox tradeship.
+
+
jknpj updated:
+
+
Fixes MoMMIs phantom action buttons
+
Fixes silicon album showing duplicated info when examining a photo
+
+
+
2018.02.23
+
DrCelt updated:
+
+
Adds the security ushanka - it goes extremely well with the warden winter coat. (should have been in the winterjacket PR)
+
Rejiggles a couple of heat conductivities with neorussian outfits; fixes some wintercoats not properly displaying stuff under it,
+
adds ski mask (literally the same as a balaclava but a different name and can protect you from the cold)
+
changes balaclava to have the correct flags for covering the full head except eyes.
HarseTheef updated:
-
Adds the ability to shush people by using disarm intent on their mouth
+
Makes the shuttle-related sounds 25% quieter.
+
+
Kurfursten updated:
+
+
Adds the Antique Matter Synthesizer, an item engineers can buy to convert massive amounts of power into items.
+
Traders can now latejoin (up to three slots). Doing so will hurl them through space toward the outpost, so be sure you can navigate the asteroid if you choose this option!
+
+
Pathid updated:
+
+
Fixed cats magically killing mice through solid objects.
+
+
Zth-- updated:
+
+
Added a prices mode for the custom vending machine that allows you to modify the machines' prices on the fly. This feature can be toggled from the panel (where the wires are).
+
Added a insert items mode. Same as prices mode, it lets you add items by slapping them on the machine. You can also toggle this from the panel.
+
Remember that the panel can be secured by slapping your ID on the machine and linking it to your account.
-
2017.09.08
-
Durgen updated:
-
-
Adds a religion for the Chaplain from Dune
-
-
SonixApache updated:
-
-
the grenade explosion cap has been raised to 3, 5, 7
-
water/potassium explosions are now limited to 1, 2, 4
-
glycerol is now made with formic acid rather than sulphuric acid
-
-
-
2017.09.07
-
Duny updated:
-
-
Reworked the top half of Metaclubs medbay (chemistry, paramedics, storage, hallway and reception), mainly in order to reduce the crowding near the entrance.
-
(Deff) Fixed cargo shuttle buttons opening the wrong door.
-
(Deff) Fixed Ian's delusions about the whole year being christmas.
-
(Deff) The salvage shuttle's inner airlocks now start unbolted.
-
Added the pressure regulator, an embedded controller used only to depressurize or pressurize a room on demand using vents and an airlock sensor. Can be built using an airlock controller frame and an Embedded Controller Board (Pressure Regulator).
-
(Deff) The chapel's mass driver now has a pressure regulator, with its own air canister and a passive gate linked to distro (already set up correctly) both situated in the crematorium, allowing the chaplain to quickly depressurize the room before activating the mass driver/repressurize it afterwards and therefore avoid ZAS shenanigans.
-
-
-
2017.09.06
+
2018.02.22
DamianX updated:
-
Heaters and freezers can be correctly upgraded with the RPED.
-
Heaters and freezers update the pipe network more frequency, which should lead to more accurate readings.
+
Fixed a bug that caused only the first implant to show up on secHUDs.
-
PromethTK11 updated:
+
DrCelt updated:
-
Packed chem dispensers now are working properly
-
Fixed missing pipe in Packed pod-bay
+
Lowers breathing cold air damage threshold to -53c instead of -13c
-
-
2017.09.05
-
Duny updated:
+
Jared-Fogle updated:
-
Added a pod bay to Defficiency, to the north west of Arrivals.
+
Instead of being able to move freely, action buttons can now be dragged on top of each other to swap places.
-
SonixApache updated:
+
Kurfursten updated:
-
The CMO and RD now spawn with their own unique coats equipped
+
PDAs are now equipped with a multicast function. Select department message below messenger to send to an entire department at once using the new Centralized Automated Messaging Operator.
+
+
Pathid updated:
+
+
Fixed the jaunt-blocking property of holy water. Also, since holy tiles block jaunt now, the chapel won't be possible to jaunt through.
+
Cyborgs deathgasp properly on death now.
+
+
jknpj updated:
+
+
Fixes the supply cyborg automatic ore loader missing its icon
+
Removed the pre-roundstart bite/kick simulator
-
-
-
Queue
@@ -167,7 +154,7 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
@@ -577,4 +563,4 @@ Used In File(s): \code\game\mecha\mech_fabricator.dm
-{{/if}}
\ No newline at end of file
+{{/if}}
diff --git a/nano/templates/flatpacker.tmpl b/nano/templates/flatpacker.tmpl
index 18294144370..8d058ff3a75 100644
--- a/nano/templates/flatpacker.tmpl
+++ b/nano/templates/flatpacker.tmpl
@@ -1,21 +1,7 @@
-
-
-
-
Computer Designs
@@ -129,4 +115,4 @@ Used In File(s): code\modules\research\mechanic\flatpacker.dm
-
\ No newline at end of file
+
diff --git a/nano/templates/genfab.tmpl b/nano/templates/genfab.tmpl
index b58ab751f07..22f5e276070 100644
--- a/nano/templates/genfab.tmpl
+++ b/nano/templates/genfab.tmpl
@@ -3,20 +3,6 @@ Title: General Fabricator UI
Used In File(s): code\modules\research\mechanic\mechanic_fabs.dm
Used By Machine(s): Flatpack Fabricator, General Fabricator
-->
-
-
-
Design List
diff --git a/nano/templates/gps.tmpl b/nano/templates/gps.tmpl
index 4a7bb83213b..52c55d5f801 100644
--- a/nano/templates/gps.tmpl
+++ b/nano/templates/gps.tmpl
@@ -24,6 +24,10 @@ Used In File(s): \code\modules\telesci\gps.dm
Detected signals
+
+
{{:data.gpstag}}
+
{{:data.location_text}}
+
{{for data.devices}}
{{:value.tag}}
@@ -31,4 +35,4 @@ Used In File(s): \code\modules\telesci\gps.dm
{{empty}}
No signal detected.
-{{/for}}
\ No newline at end of file
+{{/for}}
diff --git a/nano/templates/podfab.tmpl b/nano/templates/podfab.tmpl
index 867ceb5b3f2..0b9a84b592e 100644
--- a/nano/templates/podfab.tmpl
+++ b/nano/templates/podfab.tmpl
@@ -1,9 +1,9 @@
-
-
-
-
-