AI PDA Message Log"
for(var/index in tnote)
if(index["sent"])
@@ -301,7 +300,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(usr.stat == 2)
usr << "You can't do that because you are dead!"
return
- JFLOG("AI Toggled Receiver")
toff = !toff
usr << "PDA sender/receiver toggled [(toff ? "Off" : "On")]!"
@@ -314,7 +312,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
usr << "You can't do that because you are dead!"
return
silent=!silent
- JFLOG("AI toggled the silent option")
usr << "PDA ringer toggled [(silent ? "Off" : "On")]!"
/obj/item/device/pda/ai/can_use()
@@ -325,7 +322,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
if ((honkamt > 0) && (prob(60)))//For clown virus.
honkamt--
playsound(loc, 'sound/items/bikehorn.ogg', 30, 1)
- JFLOG("[user] PDA honked")
return
@@ -528,15 +524,11 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/attack_self(mob/user as mob)
user.set_machine(src)
if(active_uplink_check(user))
- JFLOG("[user] activated a syndicate uplink in their PDA")
return
- JFLOG("[user] activated PDA")
ui_interact(user) //NanoUI requires this proc
return
/obj/item/device/pda/Topic(href, href_list)
- if (href_list["choice"]!="Return") // We really don't need to see ten thousand return actions.
- JFLOG("UI Action >>> HREF|[href] >>> HREF_LIST|[list2json(href_list)]")
if(href_list["cartmenu"] && !isnull(cartridge))
cartridge.Topic(href, href_list)
return 1
@@ -964,7 +956,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
if ( can_use(usr) )
if(id)
- JFLOG("[usr] removed ID:[id]")
remove_id()
else
usr << "This PDA does not have an ID in it."
@@ -981,7 +972,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
return
if ( can_use(usr) )
- JFLOG("[usr] removed pen")
var/obj/item/weapon/pen/O = locate() in src
if(O)
if (istype(loc, /mob))
@@ -1021,7 +1011,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/attackby(obj/item/C as obj, mob/user as mob, params)
..()
if(istype(C, /obj/item/weapon/cartridge) && !cartridge)
- JFLOG("[user] inserted Cartridge[cartridge]")
cartridge = C
user.drop_item()
cartridge.loc = src
@@ -1033,7 +1022,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
else if(istype(C, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/idcard = C
if(!idcard.registered_name)
- JFLOG("[user] tried to insert ID:[idcard] but it was rejected.")
user << "\The [src] rejects the ID."
return
if(!owner)
@@ -1042,14 +1030,12 @@ var/global/list/obj/item/device/pda/PDAs = list()
ownrank = idcard.rank
name = "PDA-[owner] ([ownjob])"
user << "Card scanned."
- JFLOG("[user] tried to insert ID:[idcard] and it was used to initialize this PDA.")
else
//Basic safety check. If either both objects are held by user or PDA is on ground and card is in hand.
if(((src in user.contents) && (C in user.contents)) || (istype(loc, /turf) && in_range(src, user) && (C in user.contents)) )
if( can_use(user) )//If they can still act.
id_check(user, 2)
user << "You put the ID into \the [src]'s slot."
- JFLOG("[user] inserted ID:[idcard].")
updateSelfDialog()//Update self dialog on success.
return //Return in case of failed check or when successful.
updateSelfDialog()//For the non-input related code.
@@ -1058,7 +1044,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
C.loc = src
pai = C
user << "You slot \the [C] into [src]."
- JFLOG("[user] inserted PAI:[pai]")
nanomanager.update_uis(src) // update all UIs attached to src
else if(istype(C, /obj/item/weapon/pen))
var/obj/item/weapon/pen/O = locate() in src
@@ -1067,7 +1052,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
else
user.drop_item()
C.loc = src
- JFLOG("[user] inserted PEN:[C]")
user << "You slide \the [C] into \the [src]."
return
@@ -1075,7 +1059,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
if (istype(C, /mob/living/carbon))
switch(scanmode)
if(1)
- JFLOG("[user] used the medical scanner on [C]")
for (var/mob/O in viewers(C, null))
O.show_message("\red [user] has analyzed [C]'s vitals!", 1)
@@ -1084,8 +1067,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
user.show_message("\blue \t Damage Specifics: [C.getOxyLoss() > 50 ? "\red" : "\blue"][C.getOxyLoss()]-[C.getToxLoss() > 50 ? "\red" : "\blue"][C.getToxLoss()]-[C.getFireLoss() > 50 ? "\red" : "\blue"][C.getFireLoss()]-[C.getBruteLoss() > 50 ? "\red" : "\blue"][C.getBruteLoss()]", 1)
user.show_message("\blue \t Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message("\blue \t Body Temperature: [C.bodytemperature-T0C]°C ([C.bodytemperature*1.8-459.67]°F)", 1)
- if(C.tod && (C.stat == DEAD || (C.status_flags & FAKEDEATH)))
- user.show_message("\blue \t Time of Death: [C.tod]")
+ if(C.timeofdeath && (C.stat == DEAD || (C.status_flags & FAKEDEATH)))
+ user.show_message("\blue \t Time of Death: [C.timeofdeath]")
if(istype(C, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C
var/list/damaged = H.get_damaged_organs(1,1)
@@ -1097,7 +1080,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
user.show_message("\blue \t Limbs are OK.",1)
if(2)
- JFLOG("[user] used the fingerprint scanner on [C]")
if (!istype(C:dna, /datum/dna))
user << "\blue No fingerprints found on [C]"
else
@@ -1113,7 +1095,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
user << "\blue Blood type: [C:blood_DNA[blood]]\nDNA: [blood]"
if(4)
- JFLOG("[user] used the radiation scanner on [C]")
for (var/mob/O in viewers(C, null))
O.show_message("\red [user] has analyzed [C]'s radiation levels!", 1)
@@ -1128,22 +1109,18 @@ var/global/list/obj/item/device/pda/PDAs = list()
switch(scanmode)
if(3)
- JFLOG("[user] used the reagent scanner on [A]")
- if(!isobj(A))
- return
if(!isnull(A.reagents))
if(A.reagents.reagent_list.len > 0)
var/reagents_length = A.reagents.reagent_list.len
- user << "\blue [reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found."
+ user << "[reagents_length] chemical agent[reagents_length > 1 ? "s" : ""] found."
for (var/re in A.reagents.reagent_list)
- user << "\blue \t [re]"
+ user << "\t [re]"
else
- user << "\blue No active chemical agents found in [A]."
+ user << "No active chemical agents found in [A]."
else
- user << "\blue No significant chemical agents found in [A]."
+ user << "No significant chemical agents found in [A]."
if(5)
- JFLOG("[user] used the air analysis scanner on [A]")
if (istype(A, /obj/item/weapon/tank))
var/obj/item/weapon/tank/T = A
atmosanalyzer_scan(T.air_contents, user, T)
@@ -1159,59 +1136,51 @@ var/global/list/obj/item/device/pda/PDAs = list()
else if (istype(A, /obj/item/weapon/flamethrower))
var/obj/item/weapon/flamethrower/T = A
if(T.ptank) atmosanalyzer_scan(T.ptank.air_contents, user, T)
+ else if (istype(A, /obj/machinery/portable_atmospherics/scrubber/huge))
+ var/obj/machinery/portable_atmospherics/scrubber/huge/T = A
+ atmosanalyzer_scan(T.air_contents, user, T)
+ else if (istype(A, /obj/machinery/atmospherics/unary/tank))
+ var/obj/machinery/atmospherics/unary/tank/T = A
+ atmosanalyzer_scan(T.air_contents, user, T)
if (!scanmode && istype(A, /obj/item/weapon/paper) && owner)
- JFLOG("[user] used the document scanner on [A]")
// JMO 20140705: Makes scanned document show up properly in the notes. Not pretty for formatted documents,
// as this will clobber the HTML, but at least it lets you scan a document. You can restore the original
// notes by editing the note again. (Was going to allow you to edit, but scanned documents are too long.)
var/raw_scan = (A:info)
var/formatted_scan = ""
// Scrub out the tags (replacing a few formatting ones along the way)
-
// Find the beginning and end of the first tag.
var/tag_start = findtext(raw_scan,"<")
var/tag_stop = findtext(raw_scan,">")
-
// Until we run out of complete tags...
while(tag_start&&tag_stop)
var/pre = copytext(raw_scan,1,tag_start) // Get the stuff that comes before the tag
var/tag = lowertext(copytext(raw_scan,tag_start+1,tag_stop)) // Get the tag so we can do intellegent replacement
var/tagend = findtext(tag," ") // Find the first space in the tag if there is one.
-
// Anything that's before the tag can just be added as is.
formatted_scan = formatted_scan+pre
-
// If we have a space after the tag (and presumably attributes) just crop that off.
if (tagend)
tag=copytext(tag,1,tagend)
-
if (tag=="p"||tag=="/p"||tag=="br") // Check if it's I vertical space tag.
formatted_scan=formatted_scan+" " // If so, add some padding in.
-
raw_scan = copytext(raw_scan,tag_stop+1) // continue on with the stuff after the tag
-
// Look for the next tag in what's left
tag_start = findtext(raw_scan,"<")
tag_stop = findtext(raw_scan,">")
-
// Anything that is left in the page. just tack it on to the end as is
formatted_scan=formatted_scan+raw_scan
-
// If there is something in there already, pad it out.
if (length(note)>0)
note = note + "
"
-
// Store the scanned document to the notes
note = "Scanned Document. Edit to restore previous notes/delete scan. ---------- " + formatted_scan + " "
// notehtml ISN'T set to allow user to get their old notes back. A better implementation would add a "scanned documents"
// feature to the PDA, which would better convey the availability of the feature, but this will work for now.
-
// Inform the user
user << "\blue Paper scanned and OCRed to notekeeper." //concept of scanning paper copyright brainoblivion 2009
-
-
/obj/item/device/pda/proc/explode() //This needs tuning.
if(!src.detonate) return
var/turf/T = get_turf(src.loc)
@@ -1224,12 +1193,10 @@ var/global/list/obj/item/device/pda/PDAs = list()
T.hotspot_expose(700,125)
explosion(T, -1, -1, 2, 3)
- JFLOG("Exploded")
qdel(src)
return
/obj/item/device/pda/Destroy()
- JFLOG("Destroyed")
PDAs -= src
if (src.id)
src.id.loc = get_turf(src.loc)
@@ -1249,7 +1216,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
M.stop_pulling()
M << "\blue You slipped on the PDA!"
- JFLOG("Clown PDA Slipped [M]")
playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
M.Stun(8)
M.Weaken(5)
@@ -1310,28 +1276,4 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/emp_act(severity)
for(var/atom/A in src)
A.emp_act(severity)
-
-/**
-*
-* JFLOG
-*
-* These functions as well as all the log statements are being used to gather user data for how
-* people are using the PDA files with the intent of revising them based on this data.
-*
-* They are being added on 28/03/2015 and the intent is to remove them in two weeks. If you're
-* reading this and it's substantially past that point, you should remove anything marked with
-* 'JFLOG'.
-*
-* All changes should be contained to PDA.dm except the creation function which is contained in
-* job_controller.dm.
-*
-* - Jack Fractal
-**/
-
-
-/obj/item/device/pda/proc/JFLOG_DescribeSelf()
- return "([src]|[cartridge ? cartridge.name : "None"])"
-
-/obj/item/device/pda/proc/JFLOG(message as text)
- if (config)
- log_pda("[JFLOG_DescribeSelf()] >>> [message]")
+
\ No newline at end of file
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index e44fb712774..670d02af975 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -174,7 +174,7 @@
/obj/item/weapon/cartridge/rd/initialize()
radio = new /obj/item/radio/integrated/signal(src)
- ..()
+ ..()
/obj/item/weapon/cartridge/captain
name = "Value-PAK Cartridge"
@@ -191,7 +191,7 @@
/obj/item/weapon/cartridge/captain/initialize()
radio = new /obj/item/radio/integrated/beepsky(src)
- ..()
+ ..()
/obj/item/weapon/cartridge/supervisor
name = "Easy-Record DELUXE"
@@ -282,7 +282,7 @@
/* Power Monitor (Mode: 43 / 433) */
- if(mode==43 || mode==433)
+ if(mode==43 || mode==433)
values["powermonitors"] = powermonitor_repository.powermonitor_data()
if (powmonitor && !isnull(powmonitor.powernet))
@@ -463,7 +463,7 @@
else
JaniData["user_loc"] = list("x" = 0, "y" = 0)
var/MopData[0]
- for(var/obj/item/weapon/mop/M in world)
+ for(var/obj/item/weapon/mop/M in janitorial_equipment)
var/turf/ml = get_turf(M)
if(ml)
if(ml.z != cl.z)
@@ -476,7 +476,7 @@
var/BucketData[0]
- for(var/obj/structure/mopbucket/B in world)
+ for(var/obj/structure/mopbucket/B in janitorial_equipment)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
@@ -488,7 +488,7 @@
BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CbotData[0]
- for(var/obj/machinery/bot/cleanbot/B in world)
+ for(var/obj/machinery/bot/cleanbot/B in aibots)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
@@ -500,7 +500,7 @@
if(!CbotData.len)
CbotData[++CbotData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CartData[0]
- for(var/obj/structure/stool/bed/chair/cart/janicart/B in world)
+ for(var/obj/structure/janitorialcart/B in janitorial_equipment)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index 42653c3ff1b..3d37f120bc6 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -77,6 +77,8 @@
/obj/item/device/flash/proc/flash_carbon(var/mob/living/carbon/M, var/mob/user = null, var/power = 5, convert = 1)
add_logs(M, user, "flashed", object="[src.name]")
+ if(M.weakeyes)
+ M.Weaken(3) //quick weaken bypasses eye protection but has no eye flash
var/safety = M:eyecheck()
if(safety <= 0)
M.confused += power
@@ -85,6 +87,9 @@
terrible_conversion_proc(M, user)
M.Stun(1)
user.visible_message("[user] blinds [M] with the [src.name]!")
+ if(M.weakeyes)
+ M.Stun(2)
+ M.visible_message("[M] gasps and shields their eyes!")
return 1
else
if(user)
diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm
index ec5f18283a8..ed55d931d8c 100644
--- a/code/game/objects/items/devices/laserpointer.dm
+++ b/code/game/objects/items/devices/laserpointer.dm
@@ -66,9 +66,9 @@
/obj/item/device/laser_pointer/afterattack(var/atom/target, var/mob/living/user, flag, params)
if(flag) //we're placing the object on a table or in backpack
return
- laser_act(target, user)
+ laser_act(target, user, params)
-/obj/item/device/laser_pointer/proc/laser_act(var/atom/target, var/mob/living/user)
+/obj/item/device/laser_pointer/proc/laser_act(var/atom/target, var/mob/living/user, var/params)
if( !(user in (viewers(7,target))) )
return
if (!diode)
@@ -96,11 +96,13 @@
//20% chance to actually hit the eyes
if(prob(effectchance * diode.rating))
- add_logs(user, C, "shone in the eyes", object="laser pointer")
+ add_logs(C, user, "shone in the eyes", object="laser pointer")
//eye target check
outmsg = "You blind [C] by shining [src] in their eyes."
+ if(C.weakeyes)
+ C.Stun(1)
var/eye_prot = C.eyecheck()
if(C.blinded || eye_prot >= 2)
eye_prot = 4
@@ -173,12 +175,19 @@
//laser pointer image
icon_state = "pointer_[pointer_icon_state]"
var/list/showto = list()
- for(var/mob/M in range(7,targloc))
+ for(var/mob/M in viewers(7,targloc))
if(M.client)
showto.Add(M.client)
var/image/I = image('icons/obj/projectiles.dmi',targloc,pointer_icon_state,10)
- I.pixel_x = target.pixel_x + rand(-5,5)
- I.pixel_y = target.pixel_y + rand(-5,5)
+ var/list/click_params = params2list(params)
+ if(click_params)
+ if(click_params["icon-x"])
+ I.pixel_x = (text2num(click_params["icon-x"]) - 16)
+ if(click_params["icon-y"])
+ I.pixel_y = (text2num(click_params["icon-y"]) - 16)
+ else
+ I.pixel_x = target.pixel_x + rand(-5,5)
+ I.pixel_y = target.pixel_y + rand(-5,5)
if(outmsg)
user << outmsg
@@ -204,4 +213,4 @@
energy = max_energy
recharging = 0
recharge_locked = 0
- ..()
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 19812645eea..976fed562c0 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -161,8 +161,8 @@ REAGENT SCANNER
user.show_message("\t Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message("\t Damage Specifics: [OX] - [TX] - [BU] - [BR]")
user.show_message("\blue Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
- if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
- user.show_message("\blue Time of Death: [M.tod]")
+ if(M.timeofdeath && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
+ user.show_message("\blue Time of Death: [M.timeofdeath]")
if(istype(M, /mob/living/carbon/human) && mode == 1)
var/mob/living/carbon/human/H = M
var/list/damaged = H.get_damaged_organs(1,1)
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 3d496ca3b86..0342dec3840 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -1,35 +1,36 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
-
/**********************************************************************
Cyborg Spec Items
***********************************************************************/
//Might want to move this into several files later but for now it works here
/obj/item/borg/stun
- name = "Electrified Arm"
- icon = 'icons/obj/decals.dmi'
- icon_state = "shock"
+ name = "electrified arm"
+ icon = 'icons/obj/items.dmi'
+ icon_state = "elecarm"
+ var/charge_cost = 30
+
+/obj/item/borg/stun/attack(mob/M, mob/living/silicon/robot/user)
+ var/mob/living/silicon/robot/R = user
+ if(R && R.cell && R.cell.charge > 0)
+ R.cell.use(charge_cost)
+ else
+ return
- attack(mob/M as mob, mob/living/silicon/robot/user as mob)
- M.attack_log += text("\[[time_stamp()]\] Has been attacked with [src.name] by [key_name(user)]")
- user.attack_log += text("\[[time_stamp()]\] Used the [src.name] to attack [key_name(M)]")
- if(M.ckey)
- msg_admin_attack("[key_name_admin(user)] used the [src.name] to attack [key_name_admin(M)]")
+ user.do_attack_animation(M)
+ M.Weaken(5)
+ if (M.stuttering < 5)
+ M.stuttering = 5
+ M.Stun(5)
- if(!iscarbon(user))
- M.LAssailant = null
- else
- M.LAssailant = user
+ M.visible_message("[user] has prodded [M] with [src]!", \
+ "[user] has prodded you with [src].")
+ playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
+
+ if(!iscarbon(user))
+ M.LAssailant = null
+ else
+ M.LAssailant = user
- user.cell.charge -= 30
-
- M.Weaken(5)
- if (M.stuttering < 5)
- M.stuttering = 5
- M.Stun(5)
-
- for(var/mob/O in viewers(M, null))
- if (O.client)
- O.show_message("\red [user] has prodded [M] with an electrically-charged arm!", 1, "\red You hear someone fall", 2)
+ add_logs(M, user, "stunned", src, "(INTENT: [uppertext(user.a_intent)])")
/obj/item/borg/overdrive
name = "Overdrive"
@@ -44,19 +45,16 @@
icon_state = "securearea"
var/sight_mode = null
-
/obj/item/borg/sight/xray
name = "X-ray Vision"
sight_mode = BORGXRAY
-
/obj/item/borg/sight/thermal
name = "Thermal Vision"
sight_mode = BORGTHERM
icon_state = "thermal"
icon = 'icons/obj/clothing/glasses.dmi'
-
/obj/item/borg/sight/meson
name = "Meson Vision"
sight_mode = BORGMESON
@@ -67,24 +65,22 @@
name = "Hud"
var/obj/item/clothing/glasses/hud/hud = null
-
/obj/item/borg/sight/hud/med
name = "medical hud"
icon_state = "healthhud"
icon = 'icons/obj/clothing/glasses.dmi'
- New()
- ..()
- hud = new /obj/item/clothing/glasses/hud/health(src)
- return
-
+/obj/item/borg/sight/hud/med/New()
+ ..()
+ hud = new /obj/item/clothing/glasses/hud/health(src)
+ return
/obj/item/borg/sight/hud/sec
name = "security hud"
icon_state = "securityhud"
icon = 'icons/obj/clothing/glasses.dmi'
- New()
- ..()
- hud = new /obj/item/clothing/glasses/hud/security(src)
- return
+/obj/item/borg/sight/hud/sec/New()
+ ..()
+ hud = new /obj/item/clothing/glasses/hud/security(src)
+ return
diff --git a/code/game/objects/items/weapons/cash.dm b/code/game/objects/items/weapons/cash.dm
index 4269ddb283d..8aadcc91e92 100644
--- a/code/game/objects/items/weapons/cash.dm
+++ b/code/game/objects/items/weapons/cash.dm
@@ -77,7 +77,7 @@ var/global/list/moneytypes=list(
stack_color = "#663200"
/obj/item/weapon/spacecash/c200
- icon_state = "cash100"
+ icon_state = "cash200"
worth = 200
stack_color = "#663200"
diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm
index e148d6bc7ff..40ac8e93bdd 100644
--- a/code/game/objects/items/weapons/flamethrower.dm
+++ b/code/game/objects/items/weapons/flamethrower.dm
@@ -66,7 +66,7 @@
var/turf/target_turf = get_turf(target)
if(target_turf)
var/turflist = getline(user, target_turf)
- add_logs(user, target, "flamethrowered", addition="at [target.x],[target.y],[target.z]")
+ add_logs(target, user, "flamethrowered", addition="at [target.x],[target.y],[target.z]")
flame_turf(turflist)
/obj/item/weapon/flamethrower/attackby(obj/item/W as obj, mob/user as mob, params)
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 7eca6aa719b..260160a63c3 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -36,11 +36,20 @@
ear_safety++
//Flash
+ var/eye_damage = rand(1,3)
+ if(M.weakeyes)
+ M.visible_message("[M] screams and collapses!")
+ M << "AAAAGH! IT BURNS!"
+ M.Weaken(15) //hella stunned
+ M.Stun(15)
+ eye_damage += 8
+
if(!eye_safety && ishuman(M))
var/mob/living/carbon/human/H = M
var/obj/item/organ/eyes/E = H.internal_organs_by_name["eyes"]
flick("e_flash", M.flash)
- if (E) E.damage += rand(1, 3)
+ if (E)
+ E.damage += eye_damage
M.Stun(max(10/distance, 3))
M.Weaken(max(10/distance, 3))
if (istype(E) && E.damage >= E.min_bruised_damage)
diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm
index 874f96271fe..05a367fc075 100644
--- a/code/game/objects/items/weapons/mop.dm
+++ b/code/game/objects/items/weapons/mop.dm
@@ -1,3 +1,5 @@
+#define is_cleanable(A) (istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/rune))
+
/obj/item/weapon/mop
desc = "The world of janitalia wouldn't be complete without a mop."
name = "mop"
@@ -12,18 +14,22 @@
var/mopping = 0
var/mopcount = 0
var/mopcap = 5
- var/mopspeed = 40
+ var/mopspeed = 30
/obj/item/weapon/mop/New()
create_reagents(mopcap)
+ janitorial_equipment += src
+/obj/item/weapon/mop/Destroy()
+ janitorial_equipment -= src
+ return ..()
/obj/item/weapon/mop/proc/clean(turf/simulated/A)
if(reagents.has_reagent("water", 1) || reagents.has_reagent("cleaner", 1) || reagents.has_reagent("holywater", 1))
A.clean_blood()
for(var/obj/effect/O in A)
- if(istype(O,/obj/effect/decal/cleanable) || istype(O,/obj/effect/overlay) || istype(O,/obj/effect/rune))
+ if(is_cleanable(O))
qdel(O)
reagents.reaction(A, TOUCH, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly.
reagents.remove_any(1) //reaction() doesn't use up the reagents
@@ -33,20 +39,20 @@
if(!proximity) return
if(reagents.total_volume < 1)
- user << "Your mop is dry!"
+ user << "Your mop is dry!"
return
var/turf/simulated/turf = A
- if(istype(A, /obj/effect/rune) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay))
+ if(is_cleanable(A))
turf = A.loc
A = null
if(istype(turf))
- user.visible_message("[user] begins to clean \the [turf] with [src].")
+ user.visible_message("[user] begins to clean \the [turf] with [src].", "You begin to clean \the [turf] with [src]...")
- if(do_after(user, mopspeed, target = src))
+ if(do_after(user, src.mopspeed, target = turf))
+ user << "You finish mopping."
clean(turf)
- user << "You have finished mopping!"
/obj/effect/attackby(obj/item/I, mob/user, params)
diff --git a/code/game/objects/items/weapons/soap.dm b/code/game/objects/items/weapons/soap.dm
index 7f5f6b7861e..4ebf6b257e8 100644
--- a/code/game/objects/items/weapons/soap.dm
+++ b/code/game/objects/items/weapons/soap.dm
@@ -16,11 +16,9 @@
icon_state = "soapnt"
/obj/item/weapon/soap/deluxe
- icon_state = "soapdeluxe"
-
-/obj/item/weapon/soap/deluxe/New()
desc = "A deluxe Waffle Co. brand bar of soap. Smells of comdoms."
- cleanspeed = 40 //same speed as mop because deluxe -- captain gets one of these
+ icon_state = "soapdeluxe"
+ cleanspeed = 40 //slightly better because deluxe -- captain gets one of these
/obj/item/weapon/soap/syndie
desc = "An untrustworthy bar of soap made of strong chemical agents that dissolve blood faster."
diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm
index e88e37afd6c..5b700bf7181 100644
--- a/code/game/objects/items/weapons/storage/bags.dm
+++ b/code/game/objects/items/weapons/storage/bags.dm
@@ -29,8 +29,8 @@
/obj/item/weapon/storage/bag/trash
name = "trash bag"
desc = "It's the heavy-duty black polymer kind. Time to take out the trash!"
- icon = 'icons/obj/trash.dmi'
- icon_state = "trashbag0"
+ icon = 'icons/obj/janitor.dmi'
+ icon_state = "trashbag"
item_state = "trashbag"
w_class = 4
@@ -46,12 +46,12 @@
/obj/item/weapon/storage/bag/trash/update_icon()
if(contents.len == 0)
- icon_state = "trashbag0"
+ icon_state = "[initial(icon_state)]"
else if(contents.len < 12)
- icon_state = "trashbag1"
+ icon_state = "[initial(icon_state)]1"
else if(contents.len < 21)
- icon_state = "trashbag2"
- else icon_state = "trashbag3"
+ icon_state = "[initial(icon_state)]2"
+ else icon_state = "[initial(icon_state)]3"
/obj/item/weapon/storage/bag/trash/cyborg
@@ -63,6 +63,13 @@
/obj/item/weapon/storage/bag/trash/cyborg/janicart_insert(mob/user, obj/structure/janitorialcart/J)
return
+/obj/item/weapon/storage/bag/trash/bluespace
+ name = "trash bag of holding"
+ desc = "The latest and greatest in custodial convenience, a trashbag that is capable of holding vast quantities of garbage."
+ icon_state = "bluetrashbag"
+ max_combined_w_class = 60
+ storage_slots = 60
+
// -----------------------------
// Plastic Bag
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 5d92705d1ed..f409324844b 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -359,8 +359,8 @@
/obj/item/weapon/storage/belt/bluespace
name = "Belt of Holding"
desc = "The greatest in pants-supporting technology."
- icon_state = "medicalbelt"
- item_state = "medical"
+ icon_state = "holdingbelt"
+ item_state = "holdingbelt"
storage_slots = 14
w_class = 4
max_w_class = 2
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index d22ca34cffa..24e030fbbc0 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -258,8 +258,8 @@
new /obj/item/weapon/implantcase/death_alarm(src)
new /obj/item/weapon/implantcase/death_alarm(src)
new /obj/item/weapon/implantcase/death_alarm(src)
+ new /obj/item/weapon/implantcase/death_alarm(src)
new /obj/item/weapon/implanter(src)
- new /obj/item/weapon/implantpad(src)
/obj/item/weapon/storage/box/rxglasses
diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm
index 14b51d03498..a23ba5ac92e 100644
--- a/code/game/objects/structures/inflatable.dm
+++ b/code/game/objects/structures/inflatable.dm
@@ -5,13 +5,13 @@
icon_state = "folded_wall"
w_class = 3.0
- attack_self(mob/user)
- playsound(loc, 'sound/items/zip.ogg', 75, 1)
- user << "\blue You inflate [src]."
- var/obj/structure/inflatable/R = new /obj/structure/inflatable(user.loc)
- src.transfer_fingerprints_to(R)
- R.add_fingerprint(user)
- qdel(src)
+/obj/item/inflatable/attack_self(mob/user)
+ playsound(loc, 'sound/items/zip.ogg', 75, 1)
+ user << "\blue You inflate [src]."
+ var/obj/structure/inflatable/R = new /obj/structure/inflatable(user.loc)
+ src.transfer_fingerprints_to(R)
+ R.add_fingerprint(user)
+ qdel(src)
/obj/structure/inflatable
name = "inflatable wall"
@@ -25,131 +25,130 @@
var/health = 50.0
+/obj/structure/inflatable/New(location)
+ ..()
+ air_update_turf(1)
- New(location)
- ..()
- air_update_turf()
+/obj/structure/inflatable/Destroy()
+ air_update_turf(1)
+ return ..()
- Destroy()
- air_update_turf()
- return ..()
+/obj/structure/inflatable/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
+ return 0
+
+/obj/structure/inflatable/CanAtmosPass(turf/T)
+ return !density
- CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- return 0
+/obj/structure/inflatable/bullet_act(var/obj/item/projectile/Proj)
+ health -= Proj.damage
+ ..()
+ if(health <= 0)
+ deflate(1)
+ return
- bullet_act(var/obj/item/projectile/Proj)
- health -= Proj.damage
- ..()
- if(health <= 0)
+/obj/structure/inflatable/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ qdel(src)
+ return
+ if(2.0)
deflate(1)
- return
-
-
- ex_act(severity)
- switch(severity)
- if(1.0)
- qdel(src)
- return
- if(2.0)
+ return
+ if(3.0)
+ if(prob(50))
deflate(1)
return
- if(3.0)
- if(prob(50))
- deflate(1)
- return
+/obj/structure/inflatable/blob_act()
+ deflate(1)
- blob_act()
+/obj/structure/inflatable/attack_hand(mob/user as mob)
+ add_fingerprint(user)
+ return
+
+/obj/structure/inflatable/proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime
+ health -= damage
+ if(health <= 0)
+ user.visible_message("[user] tears open [src]!")
+ deflate(1)
+ else //for nicer text~
+ user.visible_message("[user] tears at [src]!")
+
+/obj/structure/inflatable/attack_alien(mob/user as mob)
+ if(islarva(user))
+ return
+ attack_generic(user, 15)
+
+/obj/structure/inflatable/attack_animal(mob/user as mob)
+ if(!isanimal(user))
+ return
+ var/mob/living/simple_animal/M = user
+ if(M.melee_damage_upper <= 0)
+ return
+ attack_generic(M, M.melee_damage_upper)
+
+/obj/structure/inflatable/attack_slime(mob/user as mob)
+ var/mob/living/carbon/slime/S = user
+ if (!S.is_adult)
+ return
+ attack_generic(user, rand(10, 15))
+
+/obj/structure/inflatable/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
+ if(!istype(W))
+ return
+ if (can_puncture(W))
+ visible_message("\red [user] pierces [src] with [W]!")
+ deflate(1)
+ if(W.damtype == BRUTE || W.damtype == BURN)
+ hit(W.force)
+ ..()
+ return
+
+/obj/structure/inflatable/proc/hit(var/damage, var/sound_effect = 1)
+ health = max(0, health - damage)
+ if(sound_effect)
+ playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ if(health <= 0)
deflate(1)
- attack_hand(mob/user as mob)
- add_fingerprint(user)
- return
-
-
- proc/attack_generic(mob/user as mob, damage = 0) //used by attack_alien, attack_animal, and attack_slime
- health -= damage
- if(health <= 0)
- user.visible_message("[user] tears open [src]!")
- deflate(1)
- else //for nicer text~
- user.visible_message("[user] tears at [src]!")
-
- attack_alien(mob/user as mob)
- if(islarva(user)) return
- attack_generic(user, 15)
-
- attack_animal(mob/user as mob)
- if(!isanimal(user)) return
- var/mob/living/simple_animal/M = user
- if(M.melee_damage_upper <= 0) return
- attack_generic(M, M.melee_damage_upper)
-
-
- attack_slime(mob/user as mob)
- var/mob/living/carbon/slime/S = user
- if (!S.is_adult)
- return
- attack_generic(user, rand(10, 15))
-
-
- attackby(obj/item/weapon/W as obj, mob/user as mob, params)
- if(!istype(W)) return
-
- if (can_puncture(W))
- visible_message("\red [user] pierces [src] with [W]!")
- deflate(1)
- if(W.damtype == BRUTE || W.damtype == BURN)
- hit(W.force)
- ..()
- return
-
- proc/hit(var/damage, var/sound_effect = 1)
- health = max(0, health - damage)
- if(sound_effect)
- playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1)
- if(health <= 0)
- deflate(1)
-
-
- proc/deflate(var/violent=0)
- playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
- if(violent)
- visible_message("[src] rapidly deflates!")
- var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc)
+/obj/structure/inflatable/proc/deflate(var/violent=0)
+ playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
+ if(violent)
+ visible_message("[src] rapidly deflates!")
+ var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc)
+ src.transfer_fingerprints_to(R)
+ qdel(src)
+ else
+ //user << "\blue You slowly deflate the inflatable wall."
+ visible_message("[src] slowly deflates.")
+ spawn(50)
+ var/obj/item/inflatable/R = new /obj/item/inflatable(loc)
src.transfer_fingerprints_to(R)
qdel(src)
- else
- //user << "\blue You slowly deflate the inflatable wall."
- visible_message("[src] slowly deflates.")
- spawn(50)
- var/obj/item/inflatable/R = new /obj/item/inflatable(loc)
- src.transfer_fingerprints_to(R)
- qdel(src)
- verb/hand_deflate()
- set name = "Deflate"
- set category = "Object"
- set src in oview(1)
+/obj/structure/inflatable/verb/hand_deflate()
+ set name = "Deflate"
+ set category = "Object"
+ set src in oview(1)
- if(isobserver(usr)) //to stop ghosts from deflating
- return
+ if(usr.stat || usr.restrained())
+ return
- deflate()
+ deflate()
-/obj/item/inflatable/door/
+/obj/item/inflatable/door
name = "inflatable door"
desc = "A folded membrane which rapidly expands into a simple door on activation."
icon = 'icons/obj/inflatable.dmi'
icon_state = "folded_door"
- attack_self(mob/user)
- playsound(loc, 'sound/items/zip.ogg', 75, 1)
- user << "\blue You inflate [src]."
- var/obj/structure/inflatable/door/R = new /obj/structure/inflatable/door(user.loc)
- src.transfer_fingerprints_to(R)
- R.add_fingerprint(user)
- qdel(src)
+/obj/item/inflatable/door/attack_self(mob/user)
+ playsound(loc, 'sound/items/zip.ogg', 75, 1)
+ user << "\blue You inflate [src]."
+ var/obj/structure/inflatable/door/R = new /obj/structure/inflatable/door(user.loc)
+ src.transfer_fingerprints_to(R)
+ R.add_fingerprint(user)
+ qdel(src)
/obj/structure/inflatable/door //Based on mineral door code
name = "inflatable door"
@@ -163,94 +162,92 @@
var/state = 0 //closed, 1 == open
var/isSwitchingStates = 0
- //Bumped(atom/user)
- // ..()
- // if(!state)
- // return TryToSwitchState(user)
- // return
+/obj/structure/inflatable/door/attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral
+ if(isAI(user)) //so the AI can't open it
+ return
+ else if(isrobot(user)) //but cyborgs can
+ if(get_dist(user,src) <= 1) //not remotely though
+ return TryToSwitchState(user)
- attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral
- if(isAI(user)) //so the AI can't open it
- return
- else if(isrobot(user)) //but cyborgs can
- if(get_dist(user,src) <= 1) //not remotely though
- return TryToSwitchState(user)
+/obj/structure/inflatable/door/attack_hand(mob/user as mob)
+ return TryToSwitchState(user)
- attack_hand(mob/user as mob)
- return TryToSwitchState(user)
+/obj/structure/inflatable/door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
+ if(air_group)
+ return state
+ if(istype(mover, /obj/effect/beam))
+ return !opacity
+ return !density
+
+/obj/structure/inflatable/door/CanAtmosPass(turf/T)
+ return !density
- CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(air_group)
- return state
- if(istype(mover, /obj/effect/beam))
- return !opacity
- return !density
-
- proc/TryToSwitchState(atom/user)
- if(isSwitchingStates) return
- if(ismob(user))
- var/mob/M = user
- if(world.time - user.last_bumped <= 60) return //NOTE do we really need that?
- if(M.client)
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- if(!C.handcuffed)
- SwitchState()
- else
+/obj/structure/inflatable/door/proc/TryToSwitchState(atom/user)
+ if(isSwitchingStates)
+ return
+ if(ismob(user))
+ var/mob/M = user
+ if(world.time - user.last_bumped <= 60)
+ return //NOTE do we really need that?
+ if(M.client)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ if(!C.handcuffed)
SwitchState()
- else if(istype(user, /obj/mecha))
- SwitchState()
+ else
+ SwitchState()
+ else if(istype(user, /obj/mecha))
+ SwitchState()
- proc/SwitchState()
- if(state)
- Close()
- else
- Open()
- air_update_turf()
-
- proc/Open()
- isSwitchingStates = 1
- //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1)
- flick("door_opening",src)
- sleep(10)
- density = 0
- opacity = 0
- state = 1
- update_icon()
- isSwitchingStates = 0
-
- proc/Close()
- isSwitchingStates = 1
- //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1)
- flick("door_closing",src)
- sleep(10)
- density = 1
- opacity = 0
- state = 0
- update_icon()
- isSwitchingStates = 0
+/obj/structure/inflatable/door/proc/SwitchState()
+ if(state)
+ Close()
+ else
+ Open()
+ air_update_turf(1)
+/obj/structure/inflatable/door/proc/Open()
+ isSwitchingStates = 1
+ //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1)
+ flick("door_opening",src)
+ sleep(10)
+ density = 0
+ opacity = 0
+ state = 1
update_icon()
- if(state)
- icon_state = "door_open"
- else
- icon_state = "door_closed"
+ isSwitchingStates = 0
- deflate(var/violent=0)
- playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
- if(violent)
- visible_message("[src] rapidly deflates!")
- var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc)
+/obj/structure/inflatable/door/proc/Close()
+ isSwitchingStates = 1
+ //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1)
+ flick("door_closing",src)
+ sleep(10)
+ density = 1
+ opacity = 0
+ state = 0
+ update_icon()
+ isSwitchingStates = 0
+
+/obj/structure/inflatable/door/update_icon()
+ if(state)
+ icon_state = "door_open"
+ else
+ icon_state = "door_closed"
+
+/obj/structure/inflatable/door/deflate(var/violent=0)
+ playsound(loc, 'sound/machines/hiss.ogg', 75, 1)
+ if(violent)
+ visible_message("[src] rapidly deflates!")
+ var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc)
+ src.transfer_fingerprints_to(R)
+ else
+ visible_message("[src] slowly deflates.")
+ spawn(50)
+ var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc)
src.transfer_fingerprints_to(R)
- qdel(src)
- else
- //user << "\blue You slowly deflate the inflatable wall."
- visible_message("[src] slowly deflates.")
- spawn(50)
- var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc)
- src.transfer_fingerprints_to(R)
- qdel(src)
-
+
+ air_update_turf(1)
+ qdel(src)
/obj/item/inflatable/torn
name = "torn inflatable wall"
@@ -258,9 +255,9 @@
icon = 'icons/obj/inflatable.dmi'
icon_state = "folded_wall_torn"
- attack_self(mob/user)
- user << "\blue The inflatable wall is too torn to be inflated!"
- add_fingerprint(user)
+/obj/item/inflatable/torn/attack_self(mob/user)
+ user << "The inflatable wall is too torn to be inflated!"
+ add_fingerprint(user)
/obj/item/inflatable/door/torn
name = "torn inflatable door"
@@ -268,9 +265,9 @@
icon = 'icons/obj/inflatable.dmi'
icon_state = "folded_door_torn"
- attack_self(mob/user)
- user << "\blue The inflatable door is too torn to be inflated!"
- add_fingerprint(user)
+/obj/item/inflatable/door/torn/attack_self(mob/user)
+ user << "The inflatable door is too torn to be inflated!"
+ add_fingerprint(user)
/obj/item/weapon/storage/briefcase/inflatable
name = "inflatable barrier box"
@@ -280,12 +277,12 @@
max_combined_w_class = 21
w_class = 3
- New()
- ..()
- new /obj/item/inflatable/door(src)
- new /obj/item/inflatable/door(src)
- new /obj/item/inflatable/door(src)
- new /obj/item/inflatable(src)
- new /obj/item/inflatable(src)
- new /obj/item/inflatable(src)
- new /obj/item/inflatable(src)
\ No newline at end of file
+/obj/item/weapon/storage/briefcase/inflatable/New()
+ ..()
+ new /obj/item/inflatable/door(src)
+ new /obj/item/inflatable/door(src)
+ new /obj/item/inflatable/door(src)
+ new /obj/item/inflatable(src)
+ new /obj/item/inflatable(src)
+ new /obj/item/inflatable(src)
+ new /obj/item/inflatable(src)
diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm
index c9a624fad8c..9d8ed7ee3dc 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -1,54 +1,98 @@
-/obj/structure/stool/bed/chair/cart/
+//old style PIMP-CART
+/obj/structure/stool/bed/chair/janicart
+ name = "janicart"
+ desc = "A brave janitor cyborg gave its life to produce such an amazing combination of speed and utility."
icon = 'icons/obj/vehicles.dmi'
- anchored = 1
+ icon_state = "pussywagon"
+ anchored = 0
density = 1
- var/empstun = 0
- var/health = 100
- var/destroyed = 0
- var/move_delay = 1
- var/keytype = /obj/item/key
- var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread
+ var/obj/item/weapon/storage/bag/trash/mybag = null
+ var/callme = "pimpin' ride" //how do people refer to it?
+ var/move_delay = 0
+ var/floorbuffer = 0
+ var/keytype = /obj/item/key/janitor
-/obj/structure/stool/bed/chair/cart/process()
- if(empstun > 0)
- empstun--
- if(empstun < 0)
- empstun = 0
-
-/obj/structure/stool/bed/chair/cart/New()
- processing_objects |= src
+/obj/structure/stool/bed/chair/janicart/New()
handle_rotation()
-/obj/structure/stool/bed/chair/cart/examine(mob/user)
- if(..(user, 1))
- switch(health)
- if(75 to 99)
- usr << "\blue It appears slightly dented."
- if(40 to 74)
- usr << "\red It appears heavily dented."
- if(1 to 39)
- usr << "\red It appears severely dented."
- if((INFINITY * -1) to 0)
- usr << "It appears completely unsalvageable"
+/obj/structure/stool/bed/chair/janicart/Move(a, b, flag)
+ ..()
+ if(floorbuffer)
+ var/turf/tile = loc
+ if(isturf(tile))
+ tile.clean_blood()
+ if (istype(tile, /turf/simulated/floor))
+ var/turf/simulated/floor/F = tile
+ F.dirt = 0
+ for(var/A in tile)
+ if(istype(A, /obj/effect))
+ if(is_cleanable(A))
+ qdel(A)
-/obj/structure/stool/bed/chair/cart/attackby(obj/item/W, mob/user, params)
- if (istype(W, /obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/WT = W
- if (WT.remove_fuel(0))
- if(destroyed)
- user << "\red The [src.name] is destroyed beyond repair."
- add_fingerprint(user)
- user.visible_message("\blue [user] has fixed some of the dents on [src].", "\blue You fix some of the dents on \the [src]")
- health += 20
- HealthCheck()
- else
- user << "Need more welding fuel!"
+/obj/structure/stool/bed/chair/janicart/examine(mob/user)
+ ..()
+ if(floorbuffer)
+ user << "It has been upgraded with a floor buffer."
+
+
+/obj/structure/stool/bed/chair/janicart/attackby(obj/item/I, mob/user, params)
+ if(istype(I, keytype))
+ user << "Hold [I] in one of your hands while you drive this [callme]."
+ else if(istype(I, /obj/item/weapon/storage/bag/trash))
+ if(keytype == /obj/item/key/janitor)
+ if(!user.drop_item())
+ return
+ user << "You hook the trashbag onto the [callme]."
+ I.loc = src
+ mybag = I
+ else if(istype(I, /obj/item/janiupgrade))
+ if(keytype == /obj/item/key/janitor)
+ floorbuffer = 1
+ qdel(I)
+ user << "You upgrade the [callme] with the floor buffer."
+ update_icon()
+
+/obj/structure/stool/bed/chair/janicart/update_icon()
+ overlays.Cut()
+ if(mybag)
+ overlays += "cart_garbage"
+ if(floorbuffer)
+ overlays += "cart_buffer"
+
+/obj/structure/stool/bed/chair/janicart/attack_hand(mob/user)
+ if(mybag)
+ mybag.loc = get_turf(user)
+ user.put_in_hands(mybag)
+ mybag = null
+ update_icon()
+ else
+ ..()
+
+
+/obj/structure/stool/bed/chair/janicart/relaymove(mob/user, direction)
+ if(user.stat || user.stunned || user.weakened || user.paralysis)
+ unbuckle_mob()
+ if(istype(user.l_hand, keytype) || istype(user.r_hand, keytype))
+ if(!Process_Spacemove(direction) || !has_gravity(src.loc) || move_delay || !isturf(loc))
return
- if(istype(W, /obj/item/key))
- user << "Hold [W] in one of your hands while you drive this [name]."
+ step(src, direction)
+ update_mob()
+ handle_rotation()
+ if(istype(src.loc, /turf/simulated))
+ var/turf/simulated/T = src.loc
+ if(T.wet == 2) //Lube! Fall off!
+ playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
+ buckled_mob.Stun(7)
+ buckled_mob.Weaken(7)
+ unbuckle_mob()
+ step(src, dir)
+ move_delay = 1
+ spawn(2)
+ move_delay = 0
+ else
+ user << "You'll need the keys in one of your hands to drive this [callme]."
-
-/obj/structure/stool/bed/chair/cart/user_buckle_mob(mob/living/M, mob/user)
+/obj/structure/stool/bed/chair/janicart/user_buckle_mob(mob/living/M, mob/user)
if(user.incapacitated()) //user can't move the mob on the janicart's turf if incapacitated
return
for(var/atom/movable/A in get_turf(src)) //we check for obstacles on the turf.
@@ -59,19 +103,14 @@
..()
update_mob()
-/obj/structure/stool/bed/chair/cart/post_buckle_mob(mob/living/M)
- update_mob()
- return ..()
+/obj/structure/stool/bed/chair/janicart/unbuckle_mob()
+ if(buckled_mob)
+ buckled_mob.pixel_x = 0
+ buckled_mob.pixel_y = 0
+ ..()
-/obj/structure/stool/bed/chair/cart/unbuckle_mob()
- var/mob/living/M = ..()
- if(M)
- M.pixel_x = 0
- M.pixel_y = 0
- return M
-
-/obj/structure/stool/bed/chair/cart/handle_rotation()
- if(dir == SOUTH)
+/obj/structure/stool/bed/chair/janicart/handle_rotation()
+ if((dir == SOUTH) || (dir == WEST) || (dir == EAST))
layer = FLY_LAYER
else
layer = OBJ_LAYER
@@ -83,7 +122,8 @@
update_mob()
-/obj/structure/stool/bed/chair/cart/proc/update_mob()
+
+/obj/structure/stool/bed/chair/janicart/proc/update_mob()
if(buckled_mob)
buckled_mob.dir = dir
switch(dir)
@@ -91,190 +131,85 @@
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 7
if(WEST)
- buckled_mob.pixel_x = 13
+ buckled_mob.pixel_x = 12
buckled_mob.pixel_y = 7
if(NORTH)
buckled_mob.pixel_x = 0
buckled_mob.pixel_y = 4
if(EAST)
- buckled_mob.pixel_x = -13
+ buckled_mob.pixel_x = -12
buckled_mob.pixel_y = 7
-/obj/structure/stool/bed/chair/cart/emp_act(severity)
- switch(severity)
- if(1)
- src.empstun = (rand(5,10))
- if(2)
- src.empstun = (rand(1,5))
- src.visible_message("\red The [src.name]'s motor short circuits!")
- spark_system.attach(src)
- spark_system.set_up(5, 0, src)
- spark_system.start()
-
-/obj/structure/stool/bed/chair/cart/bullet_act(var/obj/item/projectile/Proj)
- var/hitrider = 0
- if(istype(Proj, /obj/item/projectile/ion))
- Proj.on_hit(src, 2)
- return
+/obj/structure/stool/bed/chair/janicart/bullet_act(obj/item/projectile/Proj)
if(buckled_mob)
- if(prob(75))
- hitrider = 1
- var/act = buckled_mob.bullet_act(Proj)
- if(act >= 0)
- visible_message("[buckled_mob.name] is hit by [Proj]!")
- if(istype(Proj, /obj/item/projectile/energy))
- unbuckle_mob()
- return
- if(istype(Proj, /obj/item/projectile/energy/electrode))
- if(prob(25))
- unbuckle_mob()
- visible_message("The [src.name] absorbs the [Proj]")
- if(!istype(buckled_mob, /mob/living/carbon/human))
- return buckled_mob.bullet_act(Proj)
- else
- var/mob/living/carbon/human/H = buckled_mob
- return H.electrocute_act(0, src, 1, 0)
- if(!hitrider)
- visible_message("[Proj] hits the [name]!")
- if(!Proj.nodamage && Proj.damage_type == BRUTE || Proj.damage_type == BURN)
- health -= Proj.damage
- HealthCheck()
-
-/obj/structure/stool/bed/chair/cart/proc/HealthCheck()
- if(health > 100) health = 100
- if(health <= 0 && !destroyed)
- destroyed = 1
- density = 0
- if(buckled_mob)
- unbuckle_mob()
- visible_message("The [name] explodes!")
- explosion(src.loc,-1,0,2,7,10)
- icon_state = "pussywagon_destroyed"
-
-/obj/structure/stool/bed/chair/cart/ex_act(severity)
- switch (severity)
- if(1.0)
- health -= 100
- if(2.0)
- health -= 75
- if(3.0)
- health -= 45
- HealthCheck()
-
-
-/////////////////////////////////////////////////////////////////////////
-
-/obj/structure/stool/bed/chair/cart/janicart
- name = "janicart"
- icon_state = "pussywagon"
- flags = OPENCONTAINER
- //copypaste sorry
- var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
- var/obj/item/weapon/storage/bag/trash/mybag = null
-
-/obj/structure/stool/bed/chair/cart/janicart/New()
- ..()
- var/datum/reagents/R = new/datum/reagents(100)
- reagents = R
- R.my_atom = src
-
-/obj/structure/stool/bed/chair/cart/janicart/examine(mob/user)
- if(!..(user, 1))
- return
-
- user << "\icon[src] This [name] contains [reagents.total_volume] unit\s of [reagents]!"
- if(mybag)
- user << "\A [mybag] is hanging on the [name]."
-
-/obj/structure/stool/bed/chair/cart/janicart/attackby(obj/item/W, mob/user, params)
- ..()
- if(istype(W, /obj/item/weapon/mop))
- if(reagents.total_volume >= 2)
- reagents.trans_to(W, 2)
- user << "You wet the mop in the pimpin' ride."
- playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
- if(reagents.total_volume < 1)
- user << "This pimpin' ride is out of water!"
- else if(istype(W, /obj/item/weapon/storage/bag/trash))
- user << "You hook the trashbag onto the pimpin' ride."
- user.drop_item()
- W.loc = src
- mybag = W
-
-
-/obj/structure/stool/bed/chair/cart/janicart/attack_hand(mob/user)
- if(mybag)
- mybag.loc = get_turf(user)
- user.put_in_hands(mybag)
- mybag = null
- else
- ..()
-
-
-/obj/structure/stool/bed/chair/cart/janicart/relaymove(mob/user, direction)
- if(user.stat || user.stunned || user.weakened || user.paralysis || destroyed)
- unbuckle_mob()
- return
- if(empstun > 0)
- if(user)
- user << "\red \the [src] is unresponsive."
- return
- if(istype(user.l_hand, keytype) || istype(user.r_hand, keytype))
- if(!Process_Spacemove(direction) || !has_gravity(src.loc) || move_delay || !isturf(loc))
- return
- step(src, direction)
- update_mob()
- handle_rotation()
- move_delay = 1
- spawn(2)
- move_delay = 0
- else
- user << "You'll need the keys in one of your hands to drive this pimpin' ride."
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
-/obj/structure/stool/bed/chair/cart/ambulance
- name = "ambulance"
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "docwagon"
- anchored = 0
- density = 1
-/var/brightness = 4
-/var/strobe = 0
-
-/obj/structure/stool/bed/chair/cart/ambulance/relaymove(mob/user, direction)
- if(user.stat || user.stunned || user.weakened || user.paralysis || destroyed)
- unbuckle_mob()
- return
- if(empstun > 0)
- if(user)
- user << "\red \the [src] is unresponsive."
- return
- if(istype(user.l_hand, keytype) || istype(user.r_hand, keytype))
- if(!Process_Spacemove(direction) || !has_gravity(src.loc) || move_delay || !isturf(loc))
- return
- step(src, direction)
- update_mob()
- handle_rotation()
- move_delay = 1
- spawn(2)
- move_delay = 0
- else
- user << "You'll need the keys in one of your hands to drive this ambulance."
-
+ buckled_mob.bullet_act(Proj)
/obj/item/key
name = "key"
- desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"."
+ desc = "A small grey key."
icon = 'icons/obj/vehicles.dmi'
- icon_state = "keys"
+ icon_state = "key"
w_class = 1
+/obj/item/key/janitor
+ desc = "A keyring with a small steel key, and a pink fob reading \"Pussy Wagon\"."
+ icon_state = "keyjanitor"
+
+/obj/item/key/security
+ desc = "A keyring with a small steel key, and a rubber stun baton accessory."
+ icon_state = "keysec"
+
/obj/item/key/ambulance
name = "ambulance key"
desc = "A keyring with a small steel key, and tag with a red cross on it."
icon_state = "keydoc"
+/obj/item/key/snowmobile
+ name = "snowmobile key"
+ desc = "A keyring with a small steel key, and tag with a red cross on it; clearly it's not implying you're going to the hospital for this..."
+ icon_state = "keydoc" //get a better icon, sometime.
+
+/obj/item/janiupgrade
+ name = "floor buffer upgrade"
+ desc = "An upgrade for mobile janicarts."
+ icon = 'icons/obj/vehicles.dmi'
+ icon_state = "upgrade"
+
+/obj/structure/stool/bed/chair/janicart/secway
+ name = "secway"
+ desc = "A brave security cyborg gave its life to help you look like a complete tool."
+ icon = 'icons/obj/vehicles.dmi'
+ icon_state = "secway"
+ callme = "secway"
+ keytype = /obj/item/key/security
+
+/obj/structure/stool/bed/chair/janicart/secway/update_mob()
+ if(buckled_mob)
+ buckled_mob.dir = dir
+ buckled_mob.pixel_y = 4
+
+
+/obj/structure/stool/bed/chair/janicart/ambulance
+ name = "ambulance"
+ desc = "For getting to patients in a hurry--or running them over."
+ icon = 'icons/obj/vehicles.dmi'
+ icon_state = "docwagon"
+ callme = "ambulance"
+ keytype = /obj/item/key/ambulance
+
+/obj/structure/stool/bed/chair/janicart/secway/snowmobile
+ name = "red snowmobile"
+ desc = "Wheeeeeeeeeeee."
+ icon = 'icons/obj/vehicles.dmi'
+ icon_state = "snowmobile"
+ callme = "snowmobile"
+
+/obj/structure/stool/bed/chair/janicart/secway/snowmobile/blue
+ name = "blue snowmobile"
+ icon_state = "bluesnowmobile"
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
//TG style Janicart
/obj/structure/janitorialcart
@@ -297,8 +232,13 @@
/obj/structure/janitorialcart/New()
create_reagents(100)
+ janitorial_equipment += src
+/obj/structure/janitorialcart/Destroy()
+ janitorial_equipment -= src
+ return ..()
+
/obj/structure/janitorialcart/proc/wet_mop(obj/item/weapon/mop, mob/user)
if(reagents.total_volume < 1)
user << "[src] is out of water!"
diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm
index f14e9ec246d..4988e7d465e 100644
--- a/code/game/objects/structures/mop_bucket.dm
+++ b/code/game/objects/structures/mop_bucket.dm
@@ -11,11 +11,16 @@
var/datum/reagents/R = new/datum/reagents(100)
reagents = R
R.my_atom = src
+ janitorial_equipment += src
/obj/structure/mopbucket/full/New()
..()
reagents.add_reagent("water", 100)
+/obj/structure/mopbucket/Destroy()
+ janitorial_equipment -= src
+ return ..()
+
/obj/structure/mopbucket/examine(mob/user)
if(..(user, 1))
usr << text("\icon[] [] contains [] units of water left!", src, src.name, src.reagents.total_volume)
diff --git a/code/game/objects/structures/safe.dm b/code/game/objects/structures/safe.dm
index 10b8d73a92b..c95f3aa2b09 100644
--- a/code/game/objects/structures/safe.dm
+++ b/code/game/objects/structures/safe.dm
@@ -23,11 +23,11 @@ FLOOR SAFES
/obj/structure/safe/New()
- tumbler_1_pos = rand(0, 72)
- tumbler_1_open = rand(0, 72)
+ tumbler_1_pos = rand(0, 71)
+ tumbler_1_open = rand(0, 71)
- tumbler_2_pos = rand(0, 72)
- tumbler_2_open = rand(0, 72)
+ tumbler_2_pos = rand(0, 71)
+ tumbler_2_open = rand(0, 71)
/obj/structure/safe/initialize()
@@ -39,14 +39,14 @@ FLOOR SAFES
I.loc = src
-/obj/structure/safe/proc/check_unlocked(mob/user as mob, canhear)
+/obj/structure/safe/proc/check_unlocked(mob/user, canhear)
if(user && canhear)
if(tumbler_1_pos == tumbler_1_open)
- user << "You hear a [pick("tonk", "krunk", "plunk")] from [src]."
+ user << "You hear a [pick("tonk", "krunk", "plunk")] from [src]."
if(tumbler_2_pos == tumbler_2_open)
- user << "You hear a [pick("tink", "krink", "plink")] from [src]."
+ user << "You hear a [pick("tink", "krink", "plink")] from [src]."
if(tumbler_1_pos == tumbler_1_open && tumbler_2_pos == tumbler_2_open)
- if(user) visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!")
+ if(user) visible_message("[pick("Spring", "Sprang", "Sproing", "Clunk", "Krunk")]!")
return 1
return 0
@@ -72,7 +72,7 @@ FLOOR SAFES
icon_state = initial(icon_state)
-/obj/structure/safe/attack_hand(mob/user as mob)
+/obj/structure/safe/attack_hand(mob/user)
user.set_machine(src)
var/dat = "
"
dat += "[open ? "Close" : "Open"] [src] | - [dial * 5] +"
@@ -101,7 +101,7 @@ FLOOR SAFES
updateUsrDialog()
return
else
- user << "You can't [open ? "close" : "open"] [src], the lock is engaged!"
+ user << "You can't [open ? "close" : "open"] [src], the lock is engaged!"
return
if(href_list["decrement"])
@@ -109,11 +109,11 @@ FLOOR SAFES
if(dial == tumbler_1_pos + 1 || dial == tumbler_1_pos - 71)
tumbler_1_pos = decrement(tumbler_1_pos)
if(canhear)
- user << "You hear a [pick("clack", "scrape", "clank")] from [src]."
+ user << "You hear a [pick("clack", "scrape", "clank")] from [src]."
if(tumbler_1_pos == tumbler_2_pos + 37 || tumbler_1_pos == tumbler_2_pos - 35)
tumbler_2_pos = decrement(tumbler_2_pos)
if(canhear)
- user << "You hear a [pick("click", "chink", "clink")] from [src]."
+ user << "You hear a [pick("click", "chink", "clink")] from [src]."
check_unlocked(user, canhear)
updateUsrDialog()
return
@@ -123,11 +123,11 @@ FLOOR SAFES
if(dial == tumbler_1_pos - 1 || dial == tumbler_1_pos + 71)
tumbler_1_pos = increment(tumbler_1_pos)
if(canhear)
- user << "You hear a [pick("clack", "scrape", "clank")] from [src]."
+ user << "You hear a [pick("clack", "scrape", "clank")] from [src]."
if(tumbler_1_pos == tumbler_2_pos - 37 || tumbler_1_pos == tumbler_2_pos + 35)
tumbler_2_pos = increment(tumbler_2_pos)
if(canhear)
- user << "You hear a [pick("click", "chink", "clink")] from [src]."
+ user << "You hear a [pick("click", "chink", "clink")] from [src]."
check_unlocked(user, canhear)
updateUsrDialog()
return
@@ -142,11 +142,13 @@ FLOOR SAFES
updateUsrDialog()
-/obj/structure/safe/attackby(obj/item/I as obj, mob/user as mob, params)
+/obj/structure/safe/attackby(obj/item/I, mob/user, params)
if(open)
if(I.w_class + space <= maxspace)
space += I.w_class
- user.drop_item()
+ if(!user.drop_item())
+ user << "\The [I] is stuck to your hand, you cannot put it in the safe!"
+ return
I.loc = src
user << "You put [I] in [src]."
updateUsrDialog()
@@ -156,14 +158,13 @@ FLOOR SAFES
return
else
if(istype(I, /obj/item/clothing/accessory/stethoscope))
- user << "Hold [I] in one of your hands while you manipulate the dial."
+ user << "Hold [I] in one of your hands while you manipulate the dial!"
return
obj/structure/safe/blob_act()
return
-
obj/structure/safe/ex_act(severity)
return
diff --git a/code/game/objects/structures/segway.dm b/code/game/objects/structures/segway.dm
deleted file mode 100644
index 4e781364af5..00000000000
--- a/code/game/objects/structures/segway.dm
+++ /dev/null
@@ -1,163 +0,0 @@
-/obj/structure/stool/bed/chair/segway
- name = "security segway"
- desc = "Gives the illusion of authority."
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "sec_seg_idle"
- anchored = 1
- density = 1
-
- var/health = 100
- var/delay = 3 //Move delay to simulate a speed
- var/allowMove = 1
- var/datum/global_iterator/space_move //Handling space movement (i.e. drift forever)
-
-/obj/structure/stool/bed/chair/segway/New()
- handle_rotation()
- space_move = new /datum/global_iterator/space_movement(null,0)
- return
-
-/obj/structure/stool/bed/chair/segway/user_buckle_mob(mob/living/M, mob/user)
- if(user.incapacitated()) //user can't move the mob on the janicart's turf if incapacitated
- return
- for(var/atom/movable/A in get_turf(src)) //we check for obstacles on the turf.
- if(A.density)
- if(A != src && A != M)
- return
- M.loc = loc //we move the mob on the janicart's turf before checking if we can buckle.
- ..()
-
-/obj/structure/stool/bed/chair/segway/relaymove(mob/user, direction)
- if(user.stat || user.stunned || user.weakened || user.paralysis)
- unbuckle_mob()
- icon_state = "sec_seg_idle"
- if(istype(user.l_hand, /obj/item/sec_seg_key) || istype(user.r_hand, /obj/item/sec_seg_key))
- if(!allowMove)
- return
- if(src.space_move.active())
- return
- allowMove = 0
- icon_state = "sec_seg_move"
- step(src, direction)
- update_mob()
- handle_rotation()
- if(istype(src.loc, /turf/space))
- src.space_move.start(list(src,direction))
- if(istype(src.loc, /turf/simulated))
- var/turf/simulated/T = src.loc
- if(T.wet == 2) //Lube! Fall off!
- playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
- buckled_mob.Stun(8)
- buckled_mob.Weaken(5)
- unbuckle_mob()
- step(src, dir)
- sleep(delay)
- allowMove = 1
- else
- user << "Requires key in hand to drive."
-
-/obj/structure/stool/bed/chair/segway/Move()
- . = ..()
-
-/obj/structure/stool/bed/chair/segway/Bump(var/atom/obstacle)
- if(istype(obstacle, /mob))
- step(obstacle, src.dir)
- else
- obstacle.Bumped(src)
- return
-
-/obj/structure/stool/bed/chair/segway/post_buckle_mob(mob/living/M)
- update_mob()
- add_fingerprint(M)
- M.pixel_x = 0
- M.pixel_y = 5
- return ..()
-
-/obj/structure/stool/bed/chair/segway/unbuckle_mob()
- var/mob/living/M = ..()
- if(M)
- M.pixel_x = 0
- M.pixel_y = 0
- return M
-
-/obj/structure/stool/bed/chair/segway/handle_rotation()
- if(dir == NORTH)
- layer = OBJ_LAYER
- else
- layer = FLY_LAYER
-
- update_mob()
-
-/obj/structure/stool/bed/chair/segway/proc/update_mob()
- if(buckled_mob)
- buckled_mob.dir = dir
-
-/obj/structure/stool/bed/chair/segway/bullet_act(var/obj/item/projectile/Proj)
- if(buckled_mob)
- return buckled_mob.bullet_act(Proj)
- else if(istype(Proj, /obj/item/projectile/beam))
- damage(Proj.damage)
-
-/obj/structure/stool/bed/chair/segway/proc/damage(amount)
- health -= amount
- if(health <= 0)
- if(buckled_mob)
- buckled_mob << "The [src.name] was destroyed!"
- qdel(src)
-
-/obj/item/sec_seg_key
- name = "security segway key"
- desc = "A key for a security segway. You feel the choice of keyring could be more professional."
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "keys" //Needs a proper sprite
- w_class = 1
-
-/datum/global_iterator/space_movement //moon_theme.mp3
- delay = 5
-
- process(var/obj/structure/stool/bed/chair/segway/seg as obj,direction)
- if(!step(seg, direction))
- src.stop()
-
-
-/obj/structure/stool/bed/chair/segway/snowmobile
- name = "red snowmobile"
- desc = "Wheeeeeeeeeeee."
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "snowmobile"
- anchored = 1
- density = 1
-
-/obj/structure/stool/bed/chair/segway/snowmobile/blue
- name = "blue snowmobile"
- desc = "Wheeeeeeeeeeee."
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "bluesnowmobile"
- anchored = 1
- density = 1
-
-/obj/structure/stool/bed/chair/segway/snowmobile/relaymove(mob/user, direction)
- if(user.stat || user.stunned || user.weakened || user.paralysis)
- unbuckle_mob()
- if(!allowMove)
- return
- if(src.space_move.active())
- return
- allowMove = 0
- step(src, direction)
- update_mob()
- handle_rotation()
- if(istype(src.loc, /turf/space))
- src.space_move.start(list(src,direction))
- if(istype(src.loc, /turf/simulated))
- damage(5)
- usr << "Your snowmobile takes damage from not being on snow!"
- var/turf/simulated/T = src.loc
- if(T && T.wet == 2) //Lube! Fall off!
- playsound(src, 'sound/misc/slip.ogg', 50, 1, -3)
- buckled_mob.Stun(8)
- buckled_mob.Weaken(5)
- unbuckle_mob()
- step(src, dir)
- sleep(delay)
- allowMove = 1
-
diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
index 03d74cee94e..51424aeb26e 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
@@ -5,10 +5,7 @@
anchored = 0
movable = 1
- var/driving = 0
- var/mob/living/pulling = null
- var/bloodiness
-
+ var/move_delay = null
/obj/structure/stool/bed/chair/wheelchair/handle_rotation()
overlays = null
@@ -18,139 +15,57 @@
buckled_mob.dir = dir
/obj/structure/stool/bed/chair/wheelchair/relaymove(mob/user, direction)
- if(user.stat || user.stunned || user.weakened || user.paralysis || user.lying || user.restrained())
- if(user==pulling)
- pulling = null
- user.pulledby = null
- user << "\red You lost your grip!"
- return
- if(user.pulling && (user == pulling))
- pulling = null
- user.pulledby = null
- return
if(propelled)
- return
- if(pulling && (get_dist(src, pulling) > 1))
- pulling = null
- user.pulledby = null
- if(user==pulling)
- return
- if(pulling && (get_dir(src.loc, pulling.loc) == direction))
- user << "\red You cannot go there."
- return
- if(pulling && buckled_mob && (buckled_mob == user))
- user << "\red You cannot drive while being pushed."
+ return 0
+
+ if(!Process_Spacemove(direction) || !has_gravity(src.loc) || !isturf(loc))
+ return 0
+
+ if(world.time < move_delay)
return
- if(istype(user.loc, /turf/space))
- return
+ move_delay = world.time
+ move_delay += 2 //wheelchairs are not infact sport bikes
- if(ishuman(user))
- var/mob/living/carbon/human/driver = user
- var/obj/item/organ/external/l_hand = driver.get_organ("l_hand")
- var/obj/item/organ/external/r_hand = driver.get_organ("r_hand")
- if((!l_hand || (l_hand.status & ORGAN_DESTROYED)) && (!r_hand || (r_hand.status & ORGAN_DESTROYED)))
- return // No hands to drive your chair? Tough luck!
-
- // Let's roll
- driving = 1
- var/turf/T = null
- //--1---Move occupant---1--//
if(buckled_mob)
- buckled_mob.buckled = null
- step(buckled_mob, direction)
- buckled_mob.buckled = src
- //--2----Move driver----2--//
- if(pulling)
- T = pulling.loc
- if(get_dist(src, pulling) >= 1)
- step(pulling, get_dir(pulling.loc, src.loc))
- //--3--Move wheelchair--3--//
- step(src, direction)
- if(buckled_mob) // Make sure it stays beneath the occupant
- Move(buckled_mob.loc)
- dir = direction
- handle_rotation()
- if(pulling) // Driver
- if(pulling.loc == src.loc) // We moved onto the wheelchair? Revert!
- pulling.forceMove(T)
- else
- spawn(0)
- if(get_dist(src, pulling) > 1) // We are too far away? Losing control.
- pulling = null
- user.pulledby = null
- pulling.dir = get_dir(pulling, src) // When everything is right, face the wheelchair
- if(bloodiness)
- create_track()
- driving = 0
+ if(buckled_mob.incapacitated())
+ return 0
-/obj/structure/stool/bed/chair/wheelchair/Move()
- ..()
- if(buckled_mob)
- var/mob/living/occupant = buckled_mob
- if(!driving)
- occupant.buckled = null
- occupant.Move(src.loc)
- occupant.buckled = src
- if (occupant && (src.loc != occupant.loc))
- if (propelled)
- for (var/mob/O in src.loc)
- if (O != occupant)
- Bump(O)
- else
- unbuckle_mob()
- if (pulling && (get_dist(src, pulling) > 1))
- pulling.pulledby = null
- pulling << "\red You lost your grip!"
- pulling = null
- else
- if (occupant && (src.loc != occupant.loc))
- forceMove(occupant.loc) // Failsafe to make sure the wheelchair stays beneath the occupant after driving
- handle_rotation()
+ if(ishuman(buckled_mob))
+ var/mob/living/carbon/human/driver = user
+ var/obj/item/organ/external/l_hand = driver.get_organ("l_hand")
+ var/obj/item/organ/external/r_hand = driver.get_organ("r_hand")
+ if((!l_hand || (l_hand.status & ORGAN_DESTROYED)) && (!r_hand || (r_hand.status & ORGAN_DESTROYED)))
+ return 0 // No hands to drive your chair? Tough luck!
-/obj/structure/stool/bed/chair/wheelchair/attack_hand(mob/user as mob)
- if (pulling)
- MouseDrop(usr)
- else
- user_unbuckle_mob(user, user)
- return
+ for(var/organ_name in list("l_hand","r_hand","l_arm","r_arm"))
+ var/obj/item/organ/external/E = driver.get_organ(organ_name)
+ if(!E || (E.status & ORGAN_DESTROYED))
+ move_delay += 4
+ else if(E.status & ORGAN_SPLINTED)
+ move_delay += 0.5
+ else if(E.status & ORGAN_BROKEN)
+ move_delay += 1.5
+
+ if(!buckled_mob.Move(get_step(buckled_mob, direction), direction))
+ loc = buckled_mob.loc //we gotta go back
+ last_move = buckled_mob.last_move
+ inertia_dir = last_move
+ buckled_mob.inertia_dir = last_move
+ . = 0
-/obj/structure/stool/bed/chair/wheelchair/MouseDrop(over_object, src_location, over_location)
- ..()
- if(over_object == usr && in_range(src, usr))
- if(!ishuman(usr)) return
- if(usr == buckled_mob)
- usr << "\red You realize you are unable to push the wheelchair you sit in."
- return
- if(!pulling)
- pulling = usr
- usr.pulledby = src
- if(usr.pulling)
- usr.stop_pulling()
- usr.dir = get_dir(usr, src)
- usr << "You grip \the [name]'s handles."
else
- if(usr != pulling)
- for(var/mob/O in viewers(pulling, null))
- O.show_message("\red [usr] breaks [pulling]'s grip on the wheelchair.", 1)
- else
- usr << "You let go of \the [name]'s handles."
- pulling.pulledby = null
- pulling = null
- return
+ . = 1
/obj/structure/stool/bed/chair/wheelchair/Bump(atom/A)
..()
if(!buckled_mob) return
- if(propelled || (pulling && (pulling.a_intent == I_HARM)))
+ if(propelled)
var/mob/living/occupant = buckled_mob
unbuckle_mob()
- if (pulling && (pulling.a_intent == "hurt"))
- occupant.throw_at(A, 3, 3, pulling)
- else if (propelled)
- occupant.throw_at(A, 3, propelled)
+ occupant.throw_at(A, 3, propelled)
occupant.apply_effect(6, STUN, 0)
occupant.apply_effect(6, WEAKEN, 0)
@@ -162,31 +77,5 @@
victim.apply_effect(6, WEAKEN, 0)
victim.apply_effect(6, STUTTER, 0)
victim.take_organ_damage(10)
- if(pulling)
- occupant.visible_message("[pulling] has thrusted \the [name] into \the [A], throwing \the [occupant] out of it!")
- pulling.attack_log += "\[[time_stamp()]\] Crashed [key_name(occupant)] [name] into \a [A]"
- occupant.attack_log += "\[[time_stamp()]\] Thrusted into \a [A] by [key_name(pulling)] with \the [name]"
- msg_admin_attack("[key_name_admin(pulling)] has thrusted [key_name_admin(occupant)] [name] into \a [A]")
- else
- occupant.visible_message("[occupant] crashed into \the [A]!")
-
-/obj/structure/stool/bed/chair/wheelchair/proc/create_track()
- var/obj/effect/decal/cleanable/blood/tracks/B = new(loc)
- var/newdir = get_dir(get_step(loc, dir), loc)
- if(newdir == dir)
- B.dir = newdir
- else
- newdir = newdir | dir
- if(newdir == 3)
- newdir = 1
- else if(newdir == 12)
- newdir = 4
- B.dir = newdir
- bloodiness--
-
-/obj/structure/stool/bed/chair/wheelchair/buckle_mob(mob/M as mob, mob/user as mob)
- if(M == pulling)
- pulling = null
- usr.pulledby = null
- ..()
\ No newline at end of file
+ occupant.visible_message("[occupant] crashed into \the [A]!")
\ No newline at end of file
diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm
index e3ddc913bb1..48cc9feccf7 100644
--- a/code/game/objects/structures/transit_tubes/station.dm
+++ b/code/game/objects/structures/transit_tubes/station.dm
@@ -15,6 +15,7 @@
var/const/OPEN_DURATION = 6
var/const/CLOSE_DURATION = 6
+ var/list/disallowed_mobs = list(/mob/living/silicon/ai)
/obj/structure/transit_tube/station/New()
..()
@@ -32,13 +33,13 @@
return 1
/obj/structure/transit_tube/station/Bumped(mob/AM as mob|obj)
- if(!pod_moving && icon_state == "open" && istype(AM, /mob))
+ if(!pod_moving && icon_state == "open" && istype(AM, /mob/living) && !is_type_in_list(AM, disallowed_mobs))
for(var/obj/structure/transit_tube_pod/pod in loc)
if(pod.contents.len)
AM << ""
return
else if(!pod.moving && pod.dir in directions())
- AM.loc = pod
+ AM.forceMove(pod)
return
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 44ee7ef52db..3262ac5ece2 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -299,7 +299,7 @@
var/turf/tile = loc
loc.clean_blood()
for(var/obj/effect/E in tile)
- if(istype(E,/obj/effect/rune) || istype(E,/obj/effect/decal/cleanable) || istype(E,/obj/effect/overlay))
+ if(is_cleanable(E))
qdel(E)
/obj/machinery/shower/process()
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index ec573e348a2..9cafaf48198 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -9,7 +9,7 @@
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
heat_capacity = 700000
- var/transition //These is used in transistions as a way to tell where on the "cube" of space you're transitioning from/to
+ var/destination_z
var/destination_x
var/destination_y
@@ -85,30 +85,15 @@
user << "\red The plating is going to need some support."
return
-
-// Ported from unstable r355
-
/turf/space/Entered(atom/movable/A as mob|obj)
..()
- if ((!(A) || src != A.loc)) return
+ if ((!(A) || src != A.loc))
+ return
- if(transition)
-
- if(A.z > MAX_Z) return //for away missions
-
- if(destination_x)
- A.x = destination_x
-
- if(destination_y)
- A.y = destination_y
-
- var/obj/item/flag/nation/fukkenflag = A.GetTypeInAllContents(/obj/item/flag/nation)
- if(fukkenflag)
- fukkenflag.loc = fukkenflag.startloc
- if(isliving(A))
- A << "The flag you were carrying was just returned to it's base. Nice try."
-
- A.z = text2num(transition)
+ if(destination_z)
+ A.x = destination_x
+ A.y = destination_y
+ A.z = destination_z
if(isliving(A))
var/mob/living/L = A
@@ -229,100 +214,5 @@
A.loc.Entered(A)
return
-
-/turf/space/proc/Assign_Destination()
-
- if(transition)
- if(x <= TRANSITIONEDGE) //west
- destination_x = world.maxx - TRANSITIONEDGE - 2
- else if (x >= (world.maxx - TRANSITIONEDGE - 1)) //east
- destination_x = TRANSITIONEDGE + 1
- else if (y <= TRANSITIONEDGE) //south
- destination_y = world.maxy - TRANSITIONEDGE - 2
- else if (y >= (world.maxy - TRANSITIONEDGE - 1)) //north
- destination_y = TRANSITIONEDGE + 1
-
-/*
- Set the space turf transitions for the "space cube"
- Connections:
- ___ ___
- /_A_/| /_F_/|
- | |C| | |E|
- |_B_|/ |_D_|/
- Note that all maps except F are oriented with north towards A. A and F are oriented with north towards D.
- The characters on the second cube should be upside down in this illustration, but aren't because of a lack of unicode support.
-*/
-proc/setup_map_transitions() //listamania
-
- var/list/unplaced_z_levels = accessable_z_levels
- var/list/free_zones = list("A", "B", "C", "D", "E", "F")
- var/list/zone_connections = list("D ","C ","B ","E ","A ","C ","F ","E ","A ","D ","F ","B ","A ","E ","F ","C ","A ","B ","F ","D ","D ","C ","B ","E") //This describes the borders of a cube based on free zones, really!
- var/text_zone_connections = list2text(zone_connections)
- var/list/final_zone_connections = list()
- var/list/turfs_needing_transition = list()
- var/list/turfs_needing_destinations = list()
- var/list/z_level_order = list()
- var/z_level
- var/placement
- var/total_processed = 0
-
- for(var/turf/space/S in world) //Define the transistions of the z levels
- total_processed++
- if (S.x == TRANSITIONEDGE || S.x == (world.maxx - TRANSITIONEDGE - 1) || S.y == TRANSITIONEDGE || S.y == (world.maxy - TRANSITIONEDGE - 1))
- turfs_needing_transition += S
-
- //if we've processed lots of turfs, switch to background processing to prevent being mistaken for an infinite loop
- if(total_processed > 450000)
- set background = 1
-
- while(free_zones.len != 0) //Assign the sides of the cube
- if(!unplaced_z_levels || !unplaced_z_levels.len) //if we're somehow unable to fill the cube, pad with deep space
- z_level = 6
- else
- z_level = pick(unplaced_z_levels)
- if(z_level > world.maxz) //A safety if one of the unplaced_z_levels doesn't actually exist
- z_level = 6
- placement = pick(free_zones)
- text_zone_connections = replacetext(text_zone_connections, placement, "[z_level]")
-
- for(var/turf/space/S in turfs_needing_transition) //pass the identity zone to the relevent turfs
- if(S.transition && prob(50)) //In z = 6 (deep space) it's a bit of a crapshoot in terms of navigation
- continue
- if(S.z == z_level)
- S.transition = num2text(z_level)
- if(!(S in turfs_needing_destinations))
- turfs_needing_destinations += S
- if(S.z != 6) //deep space turfs need to hang around in case they get reassigned a zone
- turfs_needing_transition -= S
-
- z_level_order += num2text(z_level)
- unplaced_z_levels -= z_level
- free_zones -= placement
-
- zone_connections = text2list(replacetext(text_zone_connections, " ", "\n")) //Convert the string back into a list
-
- final_zone_connections.len = z_level_order.len
-
- var/list/temp = list()
-
- for(var/j=1, j<= 24, j++)
- temp += zone_connections[j]
- if(temp.len == 4) //Chunks of cardinal directions
- final_zone_connections[z_level_order[j/4]] += temp
- temp = list()
-
- for(var/turf/space/S in turfs_needing_destinations) //replace the identity zone with the destination z-level
- var/list/directions = final_zone_connections[S.transition]
- if(S.x <= TRANSITIONEDGE)
- S.transition = directions[Z_WEST]
- else if(S.x >= (world.maxx - TRANSITIONEDGE - 1))
- S.transition = directions[Z_EAST]
- else if(S.y <= TRANSITIONEDGE)
- S.transition = directions[Z_SOUTH]
- else
- S.transition = directions[Z_NORTH]
-
- S.Assign_Destination()
-
/turf/space/singularity_act()
- return
\ No newline at end of file
+ return
diff --git a/code/modules/admin/DB ban/functions.dm b/code/modules/admin/DB ban/functions.dm
index 8cd511a3c9a..72cee4a7b4c 100644
--- a/code/modules/admin/DB ban/functions.dm
+++ b/code/modules/admin/DB ban/functions.dm
@@ -1,3 +1,4 @@
+#define MAX_ADMIN_BANS_PER_ADMIN 1
datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration = -1, var/reason, var/job = "", var/rounds = 0, var/banckey = null, var/banip = null, var/bancid = null)
@@ -10,14 +11,22 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
var/serverip = "[world.internet_address]:[world.port]"
var/bantype_pass = 0
var/bantype_str
+ var/maxadminbancheck //Used to limit the number of active bans of a certein type that each admin can give. Used to protect against abuse or mutiny.
+ var/announceinirc //When set, it announces the ban in irc. Intended to be a way to raise an alarm, so to speak.
+ var/blockselfban //Used to prevent the banning of yourself.
+ var/kickbannedckey //Defines whether this proc should kick the banned person, if they are connected (if banned_mob is defined).
+ //some ban types kick players after this proc passes (tempban, permaban), but some are specific to db_ban, so
+ //they should kick within this proc.
switch(bantype)
if(BANTYPE_PERMA)
bantype_str = "PERMABAN"
duration = -1
bantype_pass = 1
+ blockselfban = 1
if(BANTYPE_TEMP)
bantype_str = "TEMPBAN"
bantype_pass = 1
+ blockselfban = 1
if(BANTYPE_JOB_PERMA)
bantype_str = "JOB_PERMABAN"
duration = -1
@@ -29,6 +38,21 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
bantype_str = "APPEARANCE_BAN"
duration = -1
bantype_pass = 1
+ if(BANTYPE_ADMIN_PERMA)
+ bantype_str = "ADMIN_PERMABAN"
+ duration = -1
+ bantype_pass = 1
+ maxadminbancheck = 1
+ announceinirc = 1
+ blockselfban = 1
+ kickbannedckey = 1
+ if(BANTYPE_ADMIN_TEMP)
+ bantype_str = "ADMIN_TEMPBAN"
+ bantype_pass = 1
+ maxadminbancheck = 1
+ announceinirc = 1
+ blockselfban = 1
+ kickbannedckey = 1
if( !bantype_pass ) return
if( !istext(reason) ) return
@@ -66,6 +90,11 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
a_ckey = src.owner:ckey
a_computerid = src.owner:computer_id
a_ip = src.owner:address
+
+ if(blockselfban)
+ if(a_ckey == ckey)
+ usr << "You cannot apply this ban type on yourself."
+ return
var/who
for(var/client/C in clients)
@@ -82,6 +111,15 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
adminwho += ", [C]"
reason = sql_sanitize_text(reason)
+
+ if(maxadminbancheck)
+ var/DBQuery/adm_query = dbcon.NewQuery("SELECT count(id) AS num FROM [format_table_name("ban")] WHERE (a_ckey = '[a_ckey]') AND (bantype = 'ADMIN_PERMABAN' OR (bantype = 'ADMIN_TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+ adm_query.Execute()
+ if(adm_query.NextRow())
+ var/adm_bans = text2num(adm_query.item[1])
+ if(adm_bans >= MAX_ADMIN_BANS_PER_ADMIN)
+ usr << "You already logged [MAX_ADMIN_BANS_PER_ADMIN] admin ban(s) or more. Do not abuse this function!"
+ return
var/sql = "INSERT INTO [format_table_name("ban")] (`id`,`bantime`,`serverip`,`bantype`,`reason`,`job`,`duration`,`rounds`,`expiration_time`,`ckey`,`computerid`,`ip`,`a_ckey`,`a_computerid`,`a_ip`,`who`,`adminwho`,`edits`,`unbanned`,`unbanned_datetime`,`unbanned_ckey`,`unbanned_computerid`,`unbanned_ip`) VALUES (null, Now(), '[serverip]', '[bantype_str]', '[reason]', '[job]', [(duration)?"[duration]":"0"], [(rounds)?"[rounds]":"0"], Now() + INTERVAL [(duration>0) ? duration : 0] MINUTE, '[ckey]', '[computerid]', '[ip]', '[a_ckey]', '[a_computerid]', '[a_ip]', '[who]', '[adminwho]', '', null, null, null, null, null)"
var/DBQuery/query_insert = dbcon.NewQuery(sql)
@@ -89,7 +127,12 @@ datum/admins/proc/DB_ban_record(var/bantype, var/mob/banned_mob, var/duration =
usr << "\blue Ban saved to database."
message_admins("[key_name_admin(usr)] has added a [bantype_str] for [ckey] [(job)?"([job])":""] [(duration > 0)?"([duration] minutes)":""] with the reason: \"[reason]\" to the ban database.",1)
+ if(announceinirc)
+ send2irc("BAN ALERT","[a_ckey] applied a [bantype_str] on [ckey]")
+ if(kickbannedckey)
+ if(banned_mob && banned_mob.client && banned_mob.client.ckey == banckey)
+ del(banned_mob.client)
datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
@@ -114,6 +157,12 @@ datum/admins/proc/DB_ban_unban(var/ckey, var/bantype, var/job = "")
if(BANTYPE_APPEARANCE)
bantype_str = "APPEARANCE_BAN"
bantype_pass = 1
+ if(BANTYPE_ADMIN_PERMA)
+ bantype_str = "ADMIN_PERMABAN"
+ bantype_pass = 1
+ if(BANTYPE_ADMIN_TEMP)
+ bantype_str = "ADMIN_TEMPBAN"
+ bantype_pass = 1
if(BANTYPE_ANY_FULLBAN)
bantype_str = "ANY"
bantype_pass = 1
@@ -300,6 +349,8 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
output += ""
output += ""
output += ""
+ output += ""
+ output += ""
output += ""
output += "
"
diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm
index e6d258b3386..37c6a60bcdd 100644
--- a/code/modules/admin/IsBanned.dm
+++ b/code/modules/admin/IsBanned.dm
@@ -2,38 +2,42 @@
world/IsBanned(key,address,computer_id)
if (!key || !address || !computer_id)
log_access("Failed Login (invalid data): [key] [address]-[computer_id]")
- return list("reason"="invalid login data", "desc"="Your computer provided invalid or blank information to the server on connection (byond username, IP, and Computer ID.) Provided information for reference: Username:'[key]' IP:'[address]' Computer ID:'[computer_id]' If you continue to get this error, please restart byond or contact byond support.")
- if(ckey(key) in admin_datums)
- return ..()
+ return list("reason"="invalid login data", "desc"="Error: Could not check ban status, please try again. Error message: Your computer provided invalid or blank information to the server on connection (BYOND Username, IP, and Computer ID). Provided information for reference: Username: '[key]' IP: '[address]' Computer ID: '[computer_id]'. If you continue to get this error, please restart byond or contact byond support.")
+ var/admin = 0
+ var/ckey = ckey(key)
+ if((ckey in admin_datums) || (ckey in deadmins))
+ admin = 1
//Guest Checking
if(!guests_allowed && IsGuestKey(key))
- log_access("Failed Login: [key] - Guests not allowed")
+ log_access("Failed Login: [key] [computer_id] [address] - Guests not allowed")
// message_admins("\blue Failed Login: [key] - Guests not allowed")
- return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
+ return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a BYOND account.")
- //check if the IP address is a known TOR node
- if(config && config.ToRban && ToRban_isbanned(address))
- log_access("Failed Login: [src] - Banned: ToR")
- message_admins("\blue Failed Login: [src] - Banned: ToR")
+ //check if the IP address is a known Tor node
+ if(config.ToRban && ToRban_isbanned(address))
+ log_access("Failed Login: [key] [computer_id] [address] - Banned: Tor")
+ message_admins("Failed Login: [key] - Banned: Tor")
//ban their computer_id and ckey for posterity
- AddBan(ckey(key), computer_id, "Use of ToR", "Automated Ban", 0, 0)
- return list("reason"="Using ToR", "desc"="\nReason: The network you are using to connect has been banned.\nIf you believe this is a mistake, please request help at [config.banappeals]")
+ AddBan(ckey(key), computer_id, "Use of Tor", "Automated Ban", 0, 0)
+ var/mistakemessage = ""
+ if(config.banappeals)
+ mistakemessage = "\nIf you believe this is a mistake, please request help at [config.banappeals]."
+ return list("reason"="using Tor", "desc"="\nReason: The network you are using to connect has been banned.[mistakemessage]")
if(config.ban_legacy_system)
-
//Ban Checking
- . = CheckBan( ckey(key), computer_id, address )
+ . = CheckBan(ckey(key), computer_id, address)
if(.)
- log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
- message_admins("\blue Failed Login: [key] id:[computer_id] ip:[address] - Banned [.["reason"]]")
- return .
-
- return ..() //default pager ban stuff
-
+ if (admin)
+ log_admin("The admin [key] has been allowed to bypass a matching ban on [.["key"]]")
+ message_admins("The admin [key] has been allowed to bypass a matching ban on [.["key"]]")
+ addclientmessage(ckey,"You have been allowed to bypass a matching ban on [.["key"]].")
+ else
+ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
+ return .
else
-
var/ckeytext = ckey(key)
if(!establish_db_connection())
@@ -49,7 +53,7 @@ world/IsBanned(key,address,computer_id)
if(computer_id)
cidquery = " OR computerid = '[computer_id]' "
- var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR (bantype = 'TEMPBAN' AND expiration_time > Now())) AND isnull(unbanned)")
+ var/DBQuery/query = dbcon.NewQuery("SELECT ckey, ip, computerid, a_ckey, reason, expiration_time, duration, bantime, bantype FROM [format_table_name("ban")] WHERE (ckey = '[ckeytext]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)")
query.Execute()
@@ -63,18 +67,47 @@ world/IsBanned(key,address,computer_id)
var/duration = query.item[7]
var/bantime = query.item[8]
var/bantype = query.item[9]
-
+ if (bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN")
+ //admin bans MUST match on ckey to prevent cid-spoofing attacks
+ // as well as dynamic ip abuse
+ if (pckey != ckey)
+ continue
+ if (admin)
+ if (bantype == "ADMIN_PERMABAN" || bantype == "ADMIN_TEMPBAN")
+ log_admin("The admin [key] is admin banned, and has been disallowed access")
+ message_admins("The admin [key] is admin banned, and has been disallowed access")
+ else
+ log_admin("The admin [key] has been allowed to bypass a matching ban on [pckey]")
+ message_admins("The admin [key] has been allowed to bypass a matching ban on [pckey]")
+ addclientmessage(ckey,"You have been allowed to bypass a matching ban on [pckey].")
+ continue
var/expires = ""
if(text2num(duration) > 0)
- expires = "The ban is for [duration] minutes and expires on [expiration] (server time)."
- if(istext(bantype) && (bantype == "PERMABAN"))
- var/appealmsg = ""
- if(config && config.banappeals)
- appealmsg = " You may appeal it at [config.banappeals]."
- expires = "The ban is permanent.[appealmsg]"
+ expires = " The ban is for [duration] minutes and expires on [expiration] (server time)."
+ else
+ var/appealmessage = ""
+ if(config.banappeals)
+ appealmessage = " You may appeal it at [config.banappeals]."
+ expires = " The is a permanent ban.[appealmessage]"
- var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime]. [expires]"
+ var/desc = "\nReason: You, or another user of this computer or connection ([pckey]) is banned from playing here. The ban reason is:\n[reason]\nThis ban was applied by [ackey] on [bantime].[expires]"
- return list("reason"="[bantype]", "desc"="[desc]")
+ . = list("reason"="[bantype]", "desc"="[desc]")
- return ..() //default pager ban stuff
+ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
+ return .
+
+ . = ..() //default pager ban stuff
+ if (.)
+ //byond will not trigger isbanned() for "global" host bans,
+ //ie, ones where the "apply to this game only" checkbox is not checked (defaults to not checked)
+ //So it's safe to let admins walk thru host/sticky bans here
+ if (admin)
+ log_admin("The admin [key] has been allowed to bypass a matching host/sticky ban")
+ message_admins("The admin [key] has been allowed to bypass a matching host/sticky ban")
+ addclientmessage(ckey,"You have been allowed to bypass a matching host/sticky ban.")
+ return null
+ else
+ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["message"]]")
+
+ return .
diff --git a/code/modules/admin/admin_memo.dm b/code/modules/admin/admin_memo.dm
index 03fc3767b8e..355a82aa697 100644
--- a/code/modules/admin/admin_memo.dm
+++ b/code/modules/admin/admin_memo.dm
@@ -11,7 +11,7 @@
return
admin_memo_output(memotask)
-/client/proc/admin_memo_output(task, checkrights = 1)
+/client/proc/admin_memo_output(task, checkrights = 1, silent = 0)
if(checkrights && !check_rights(R_SERVER))
return
if(!task)
@@ -99,7 +99,7 @@
if(last_editor)
output += " Last edit by [last_editor] (Click here to see edit log)"
output += " [memotext] "
- if(!output)
+ if(!output && !silent)
src << "No memos found in database."
return
src << output
diff --git a/code/modules/admin/admin_report.dm b/code/modules/admin/admin_report.dm
index b0f43741d02..89b267cd348 100644
--- a/code/modules/admin/admin_report.dm
+++ b/code/modules/admin/admin_report.dm
@@ -118,7 +118,7 @@ client/proc/display_admin_reports()
usr << browse(output, "window=news;size=600x400")
-client/proc/Report(mob/M as mob in world)
+client/proc/Report(mob/M as mob in view())
set category = "Admin"
if(!src.holder)
return
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 5184f4e7dd2..e2b26e7c491 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -74,7 +74,8 @@ var/list/admin_verbs_admin = list(
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
- /client/proc/jobbans
+ /client/proc/jobbans,
+ /client/proc/stickybanpanel
)
var/list/admin_verbs_sounds = list(
/client/proc/play_local_sound,
@@ -225,6 +226,7 @@ var/list/admin_verbs_proccall = list (
admin_verbs_spawn,
admin_verbs_mod,
admin_verbs_mentor,
+ admin_verbs_proccall,
admin_verbs_show_debug_verbs,
/client/proc/readmin,
)
@@ -570,7 +572,7 @@ var/list/admin_verbs_proccall = list (
log_admin("[key_name(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].")
message_admins("[key_name_admin(usr)] gave [key_name(T)] a [greater] disease2 with infection chance [D.infectionchance].")
-/client/proc/make_sound(var/obj/O in world) // -- TLE
+/client/proc/make_sound(var/obj/O in view()) // -- TLE
set category = "Event"
set name = "Make Sound"
set desc = "Display a message to everyone who can hear the target"
@@ -639,7 +641,7 @@ var/list/admin_verbs_proccall = list (
set name = "De-admin self"
set category = "Admin"
- if(!check_rights(R_ADMIN|R_MOD))
+ if(!check_rights(R_ADMIN|R_MOD|R_MENTOR))
return
log_admin("[key_name(usr)] deadmined themself.")
diff --git a/code/modules/admin/stickyban.dm b/code/modules/admin/stickyban.dm
new file mode 100644
index 00000000000..474b7c76265
--- /dev/null
+++ b/code/modules/admin/stickyban.dm
@@ -0,0 +1,211 @@
+/datum/admins/proc/stickyban(action,data)
+ if(!check_rights(R_BAN))
+ return
+
+ switch (action)
+ if ("show")
+ stickyban_show()
+ return
+ if ("add")
+ var/list/ban = list()
+ var/ckey
+ ban["admin"] = usr.key
+ ban["type"] = list("sticky")
+ ban["reason"] = "(InGameBan)([usr.key])" //this will be displayed in dd only
+
+ if (data["ckey"])
+ ckey = ckey(data["ckey"])
+ else
+ ckey = input(usr,"Ckey","Ckey","") as text|null
+ if (!ckey)
+ return
+ ckey = ckey(ckey)
+ if (get_stickyban_from_ckey(ckey))
+ usr << "Error: Can not add a stickyban: User already has a current sticky ban"
+
+ if (data["reason"])
+ ban["message"] = data["reason"]
+ else
+ var/reason = input(usr,"Reason","Reason","Ban Evasion") as text|null
+ if (!reason)
+ return
+ ban["message"] = "[reason]"
+
+ world.SetConfig("ban", ckey, list2stickyban(ban))
+
+ log_admin("[key_name(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
+ message_admins("[key_name_admin(usr)] has stickybanned [ckey].\nReason: [ban["message"]]")
+
+ if ("remove")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+
+ var/ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: No sticky ban for [ckey] found!"
+ return
+ if (alert("Are you sure you want to remove the sticky ban on [ckey]?","Are you sure","Yes","No") == "No")
+ return
+ if (!get_stickyban_from_ckey(ckey))
+ usr << "Error: The ban disappeared."
+ return
+ world.SetConfig("ban", ckey, null)
+
+ log_admin("[key_name(usr)] removed [ckey]'s stickyban")
+ message_admins("[key_name_admin(usr)] removed [ckey]'s stickyban")
+
+ if ("remove_alt")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+ if (!data["alt"])
+ return
+ var/alt = ckey(data["alt"])
+ var/ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: No sticky ban for [ckey] found!"
+ return
+
+ var/found = 0
+ //we have to do it this way because byond keeps the case in its sticky ban matches WHY!!!
+ for (var/key in ban["keys"])
+ if (ckey(key) == alt)
+ found = 1
+ break
+
+ if (!found)
+ usr << "Error: [alt] is not linked to [ckey]'s sticky ban!"
+ return
+
+ if (alert("Are you sure you want to disassociate [alt] from [ckey]'s sticky ban? \nNote: Nothing stops byond from re-linking them","Are you sure","Yes","No") == "No")
+ return
+
+ //we have to do this again incase something changes
+ ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: The ban disappeared."
+ return
+
+ found = 0
+ for (var/key in ban["keys"])
+ if (ckey(key) == alt)
+ ban["keys"] -= key
+ found = 1
+ break
+
+ if (!found)
+ usr << "Error: [alt] link to [ckey]'s sticky ban disappeared."
+ return
+
+ world.SetConfig("ban",ckey,list2stickyban(ban))
+
+ log_admin("[key_name(usr)] has disassociated [alt] from [ckey]'s sticky ban")
+ message_admins("[key_name_admin(usr)] has disassociated [alt] from [ckey]'s sticky ban")
+
+ if ("edit")
+ if (!data["ckey"])
+ return
+ var/ckey = data["ckey"]
+ var/ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: No sticky ban for [ckey] found!"
+ return
+ var/oldreason = ban["message"]
+ var/reason = input(usr,"Reason","Reason","[ban["message"]]") as text|null
+ if (!reason || reason == oldreason)
+ return
+ //we have to do this again incase something changed while we waited for input
+ ban = get_stickyban_from_ckey(ckey)
+ if (!ban)
+ usr << "Error: The ban disappeared."
+ return
+ ban["message"] = "[reason]"
+
+ world.SetConfig("ban",ckey,list2stickyban(ban))
+
+ log_admin("[key_name(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
+ message_admins("[key_name_admin(usr)] has edited [ckey]'s sticky ban reason from [oldreason] to [reason]")
+
+ spawn(10)
+ stickyban_show()
+
+/datum/admins/proc/stickyban_gethtml(ckey, ban)
+ . = "\[-\][ckey] "
+ . += "[ban["message"]] \[Edit\] "
+ if (ban["admin"])
+ . += "[ban["admin"]] "
+ else
+ . += "LEGACY "
+ . += "Caught keys \n"
+ for (var/key in ban["keys"])
+ if (ckey(key) == ckey)
+ continue
+ . += "
\[+\]
+ [banhtml]
+
+ "}
+ usr << browse(html,"window=stickybans;size=700x400")
+
+/proc/get_stickyban_from_ckey(var/ckey)
+ if (!ckey)
+ return null
+ ckey = ckey(ckey)
+ . = null
+ for (var/key in world.GetConfig("ban"))
+ if (ckey(key) == ckey)
+ . = stickyban2list(world.GetConfig("ban",key))
+ break
+
+/proc/stickyban2list(var/ban)
+ if (!ban)
+ return null
+ . = params2list(ban)
+ .["keys"] = text2list(.["keys"], ",")
+ .["type"] = text2list(.["type"], ",")
+ .["IP"] = text2list(.["IP"], ",")
+ .["computer_id"] = text2list(.["computer_id"], ",")
+
+/proc/list2stickyban(var/list/ban)
+ if (!ban || !islist(ban))
+ return null
+ . = ban.Copy()
+ if (.["keys"])
+ .["keys"] = list2text(.["keys"], ",")
+ if (.["type"])
+ .["type"] = list2text(.["type"], ",")
+ if (.["IP"])
+ .["IP"] = list2text(.["IP"], ",")
+ if (.["computer_id"])
+ .["computer_id"] = list2text(.["computer_id"], ",")
+ . = list2params(.)
+
+/client/proc/stickybanpanel()
+ set name = "Sticky Ban Panel"
+ set category = "Admin"
+
+ if(!check_rights(R_BAN))
+ return
+
+ holder.stickyban_show()
+
\ No newline at end of file
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index cff4e611d65..b922b4979c8 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -25,6 +25,9 @@
message_admins("[key_name_admin(usr)] rejected [key_name_admin(C.mob)]'s admin help")
log_admin("[key_name(usr)] rejected [key_name(C.mob)]'s admin help")
+
+ if(href_list["stickyban"])
+ stickyban(href_list["stickyban"],href_list)
if(href_list["makeAntag"])
switch(href_list["makeAntag"])
@@ -123,6 +126,17 @@
return
banduration = null
banjob = null
+ if(BANTYPE_ADMIN_PERMA)
+ if(!banckey || !banreason)
+ usr << "Not enough parameters (Requires ckey and reason)"
+ return
+ banduration = null
+ banjob = null
+ if(BANTYPE_ADMIN_TEMP)
+ if(!banckey || !banreason || !banduration)
+ usr << "Not enough parameters (Requires ckey, reason and duration)"
+ return
+ banjob = null
var/mob/playermob
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 69999e89940..198e5c8a042 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -92,7 +92,6 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
//send this msg to all admins
var/admin_number_afk = 0
var/list/modholders = list()
- var/list/banholders = list()
var/list/adminholders = list()
for(var/client/X in admins)
if(check_rights(R_MOD|R_MENTOR, 0, X.mob))
@@ -103,8 +102,6 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
if(X.is_afk())
admin_number_afk++
adminholders += X
- if(check_rights(R_BAN, 0, X.mob))
- banholders += X
switch(selected_type)
if("Question")
@@ -113,15 +110,14 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
if(X.prefs.sound & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
X << msg
- else
- if(adminholders.len)
- for(var/client/X in adminholders)
- if(X.prefs.sound & SOUND_ADMINHELP)
- X << 'sound/effects/adminhelp.ogg'
- X << msg
- else if("Player Complaint")
- if(banholders.len)
- for(var/client/X in banholders)
+ if(adminholders.len)
+ for(var/client/X in adminholders)
+ if(X.prefs.sound & SOUND_ADMINHELP)
+ X << 'sound/effects/adminhelp.ogg'
+ X << msg
+ if("Player Complaint")
+ if(adminholders.len)
+ for(var/client/X in adminholders)
if(X.prefs.sound & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
X << msg
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index 542a02ee231..8fc24a175cd 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -83,11 +83,13 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!target)
usr << "Error: callproc(): owner of proc no longer exists."
return
+ message_admins("[key_name_admin(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
else
//this currently has no hascall protection. wasn't able to get it working.
- log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
+ message_admins("[key_name_admin(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
+ log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc
usr << "[procname] returned: [returnval ? returnval : "null"]"
@@ -115,7 +117,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!A || !IsValidSrc(A))
usr << "Error: callproc_datum(): owner of proc no longer exists."
return
- log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
+ message_admins("[key_name_admin(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
+ log_admin("[key_name(src)] called [A]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"]")
spawn()
var/returnval = call(A,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm
index 177f5f49f34..6c5db7cd1e6 100644
--- a/code/modules/admin/verbs/diagnostics.dm
+++ b/code/modules/admin/verbs/diagnostics.dm
@@ -1,6 +1,9 @@
/client/proc/air_status(turf/target as turf)
set category = "Debug"
set name = "Display Air Status"
+
+ if(!check_rights(R_DEBUG))
+ return
if(!isturf(target))
return
@@ -15,11 +18,22 @@
usr << "\blue @[target.x],[target.y]: O:[GM.oxygen] T:[GM.toxins] N:[GM.nitrogen] C:[GM.carbon_dioxide] w [GM.temperature] Kelvin, [GM.return_pressure()] kPa [(burning)?("\red BURNING"):(null)]"
for(var/datum/gas/trace_gas in GM.trace_gases)
usr << "[trace_gas.type]: [trace_gas.moles]"
+
+ message_admins("[key_name_admin(usr)] has checked the air status of [T]")
+ log_admin("[key_name(usr)] has checked the air status of [T]")
+
feedback_add_details("admin_verb","DAST") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/fix_next_move()
set category = "Debug"
set name = "Unfreeze Everyone"
+
+ if(!check_rights(R_DEBUG))
+ return
+
+ message_admins("[key_name_admin(usr)] has unfrozen everyone")
+ log_admin("[key_name(usr)] has unfrozen everyone")
+
var/largest_move_time = 0
var/largest_click_time = 0
var/mob/largest_move_mob = null
@@ -42,15 +56,20 @@
log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] next_click = [M.next_click] world.time = [world.time]")
M.next_move = 1
M.next_click = 0
+
message_admins("[key_name_admin(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [largest_move_time/10] seconds!", 1)
message_admins("[key_name_admin(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [largest_click_time/10] seconds!", 1)
message_admins("world.time = [world.time]", 1)
+
feedback_add_details("admin_verb","UFE") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
/client/proc/radio_report()
set category = "Debug"
set name = "Radio report"
+
+ if(!check_rights(R_DEBUG))
+ return
var/filters = list(
"1" = "RADIO_TO_AIRALARM",
@@ -83,15 +102,22 @@
output += " [device] "
usr << browse(output,"window=radioreport")
+
+ message_admins("[key_name_admin(usr)] has generated a radio report")
+ log_admin("[key_name(usr)] has generated a radio report")
+
feedback_add_details("admin_verb","RR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/reload_admins()
set name = "Reload Admins"
set category = "Debug"
- if(!check_rights(R_SERVER)) return
+ if(!check_rights(R_SERVER))
+ return
- message_admins("[usr] manually reloaded admins")
+ message_admins("[key_name_admin(usr)] has manually reloaded admins")
+ log_admin("[key_name(usr)] has manually reloaded admins")
+
load_admins()
feedback_add_details("admin_verb","RLDA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -100,15 +126,24 @@
set name = "Print Jobban Log"
set desc = "This spams all the active jobban entries for the current round to standard output."
set category = "Debug"
+
+ if(!check_rights(R_DEBUG))
+ return
usr << "Jobbans active in this round."
for(var/t in jobban_keylist)
usr << "[t]"
+
+ message_admins("[key_name_admin(usr)] has printed the jobban log")
+ log_admin("[key_name(usr)] has printed the jobban log")
/client/proc/print_jobban_old_filter()
set name = "Search Jobban Log"
set desc = "This searches all the active jobban entries for the current round and outputs the results to standard output."
set category = "Debug"
+
+ if(!check_rights(R_DEBUG))
+ return
var/filter = input("Contains what?","Filter") as text|null
if(!filter)
@@ -118,3 +153,6 @@
for(var/t in jobban_keylist)
if(findtext(t, filter))
usr << "[t]"
+
+ message_admins("[key_name_admin(usr)] has searched the jobban log for [filter]")
+ log_admin("[key_name(usr)] has searched the jobban log for [filter]")
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index f0532fbd254..134cc9ff3f5 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -323,8 +323,12 @@ var/list/forbidden_varedit_object_types = list(
for(var/p in forbidden_varedit_object_types)
if( istype(O,p) )
- usr << "\red It is forbidden to edit this object's variables."
+ usr << "It is forbidden to edit this object's variables."
return
+
+ if(istype(O, /client) && (param_var_name == "ckey" || param_var_name == "key"))
+ usr << "You cannot edit ckeys on client objects."
+ return
var/class
var/variable
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index a49cd02c06b..e047a9c6497 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -567,7 +567,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
message_admins("[key_name_admin(src)] has created a command report", 1)
feedback_add_details("admin_verb","CCR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in world)
+/client/proc/cmd_admin_delete(atom/O as obj|mob|turf in view())
set category = "Admin"
set name = "Delete"
@@ -596,7 +596,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
src << "[job.title]: [job.total_positions]"
feedback_add_details("admin_verb","LFS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in world)
+/client/proc/cmd_admin_explosion(atom/O as obj|mob|turf in view())
set category = "Event"
set name = "Explosion"
@@ -627,7 +627,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
else
return
-/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in world)
+/client/proc/cmd_admin_emp(atom/O as obj|mob|turf in view())
set category = "Special Verbs"
set name = "EM Pulse"
diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm
index 3e2910fa556..ce914b6c407 100644
--- a/code/modules/awaymissions/mission_code/wildwest.dm
+++ b/code/modules/awaymissions/mission_code/wildwest.dm
@@ -207,7 +207,7 @@
dead_mob_list -= C
living_mob_list += C
C.stat = CONSCIOUS
- C.tod = null
+ C.timeofdeath = 0
C.setToxLoss(0)
C.setOxyLoss(0)
C.setCloneLoss(0)
diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm
index 5212d6e84e8..cc3b54b6bde 100644
--- a/code/modules/client/client procs.dm
+++ b/code/modules/client/client procs.dm
@@ -272,7 +272,7 @@
if(holder)
add_admin_verbs()
- admin_memo_output("Show", 0)
+ admin_memo_output("Show", 0, 1)
// Forcibly enable hardware-accelerated graphics, as we need them for the lighting overlays.
// (but turn them off first, since sometimes BYOND doesn't turn them on properly otherwise)
@@ -282,15 +282,20 @@
winset(src, null, "command=\".configure graphics-hwmode on\"")
log_client_to_db()
+
+ if (ckey in clientmessages)
+ for (var/message in clientmessages[ckey])
+ src << message
+ clientmessages.Remove(ckey)
if (config && config.autoconvert_notes)
convert_notes_sql(ckey)
send_resources()
- //////////////
- //DISCONNECT//
- //////////////
+//////////////
+//DISCONNECT//
+//////////////
/client/Del()
if(holder)
holder.owner = null
diff --git a/code/modules/client/message.dm b/code/modules/client/message.dm
new file mode 100644
index 00000000000..6406a7d051a
--- /dev/null
+++ b/code/modules/client/message.dm
@@ -0,0 +1,9 @@
+var/list/clientmessages = list()
+
+proc/addclientmessage(var/ckey, var/message)
+ ckey = ckey(ckey)
+ if (!ckey || !message)
+ return
+ if (!(ckey in clientmessages))
+ clientmessages[ckey] = list()
+ clientmessages[ckey] += message
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index 06ac7184749..210b1ddea65 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -367,7 +367,7 @@ datum/preferences
dat += " Eyes "
dat += "Change Color
__
"
- if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People" || species == "Vulpkanin" || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins
+ if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user)) //admins can always fuck with this, because they are admins
dat += " Body Color "
dat += "Change Color
__
"
@@ -1028,7 +1028,7 @@ datum/preferences
if(species == "Human")
s_tone = random_skin_tone()
if("s_color")
- if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People" || species == "Wryn" || species == "Vulpkanin")
+ if(species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Wyrn", "Vulpkanin", "Machine"))
r_skin = rand(0,255)
g_skin = rand(0,255)
b_skin = rand(0,255)
@@ -1115,6 +1115,8 @@ datum/preferences
b_hair = 0//hex2num(copytext(new_hair, 6, 8))
s_tone = 0
+
+ body_accessory = null //no vulpatail on humans damnit
if("speciesprefs")//oldvox code
speciesprefs = !speciesprefs
@@ -1268,7 +1270,7 @@ datum/preferences
s_tone = 35 - max(min( round(new_s_tone), 220),1)
if("skin")
- if(species == "Unathi" || species == "Tajaran" || species == "Skrell" || species == "Slime People"|| species == "Vulpkanin" || body_accessory_by_species[species] || check_rights(R_ADMIN, 1, user))
+ if((species in list("Unathi", "Tajaran", "Skrell", "Slime People", "Vulpkanin", "Machine")) || body_accessory_by_species[species] || check_rights(R_ADMIN, 0, user))
var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference") as color|null
if(new_skin)
r_skin = hex2num(copytext(new_skin, 2, 4))
diff --git a/code/modules/client/preferences_mysql.dm b/code/modules/client/preferences_mysql.dm
index 38006797487..98c26df8ec8 100644
--- a/code/modules/client/preferences_mysql.dm
+++ b/code/modules/client/preferences_mysql.dm
@@ -264,10 +264,10 @@
job_karma_high='[job_karma_high]',
job_karma_med='[job_karma_med]',
job_karma_low='[job_karma_low]',
- flavor_text='[sql_sanitize_text(flavor_text)]',
- med_record='[sql_sanitize_text(med_record)]',
- sec_record='[sql_sanitize_text(sec_record)]',
- gen_record='[sql_sanitize_text(gen_record)]',
+ flavor_text='[sql_sanitize_text(html_decode(flavor_text))]',
+ med_record='[sql_sanitize_text(html_decode(med_record))]',
+ sec_record='[sql_sanitize_text(html_decode(sec_record))]',
+ gen_record='[sql_sanitize_text(html_decode(gen_record))]',
player_alt_titles='[playertitlelist]',
be_special='[be_special]',
disabilities='[disabilities]',
@@ -321,7 +321,7 @@
'[job_medsci_high]', '[job_medsci_med]', '[job_medsci_low]',
'[job_engsec_high]', '[job_engsec_med]', '[job_engsec_low]',
'[job_karma_high]', '[job_karma_med]', '[job_karma_low]',
- '[sql_sanitize_text(flavor_text)]', '[sql_sanitize_text(med_record)]', '[sql_sanitize_text(sec_record)]', '[sql_sanitize_text(gen_record)]',
+ '[sql_sanitize_text(html_encode(flavor_text))]', '[sql_sanitize_text(html_encode(med_record))]', '[sql_sanitize_text(html_encode(sec_record))]', '[sql_sanitize_text(html_encode(gen_record))]',
'[playertitlelist]', '[be_special]',
'[disabilities]', '[organlist]', '[rlimblist]', '[nanotrasen_relation]', '[speciesprefs]',
'[socks]', '[body_accessory]')
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 32b99189599..7bfa16b8ba8 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -5,7 +5,7 @@
desc = "A special containment suit designed to protect a plasmaman's volatile body from outside exposure and quickly extinguish it in emergencies."
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_casing,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank)
slowdown = 0
- armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 20)
+ armor = list(melee = 0, bullet = 0, laser = 0 ,energy = 0, bomb = 0, bio = 100, rad = 20)
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
@@ -16,9 +16,9 @@
icon_state = "plasmaman_suit"
item_state = "plasmaman_suit"
- var/next_extinguish=0
- var/extinguish_cooldown=10 SECONDS
- var/extinguishes_left=10 // Yeah yeah, reagents, blah blah blah. This should be simple.
+ var/next_extinguish = 0
+ var/extinguish_cooldown = 10 SECONDS
+ var/extinguishes_left = 10 // Yeah yeah, reagents, blah blah blah. This should be simple.
/obj/item/clothing/suit/space/eva/plasmaman/examine(mob/user)
..(user)
@@ -46,35 +46,26 @@
var/base_state = "plasmaman_helmet"
var/brightness_on = 4 //luminosity when on
var/on = 0
- var/no_light=0 // Disable the light on the atmos suit
action_button_name = "Toggle Helmet Light"
/obj/item/clothing/head/helmet/space/eva/plasmaman/attack_self(mob/user)
if(!isturf(user.loc))
- user << "You cannot turn the light on while in this [user.loc]" //To prevent some lighting anomalities.
- return
- if(no_light)
+ user << "You cannot turn the light on while in this [user.loc]." //To prevent some lighting anomalities.
return
+ toggle_light(user)
+
+/obj/item/clothing/head/helmet/space/eva/plasmaman/proc/toggle_light(mob/user)
on = !on
icon_state = "[base_state][on]"
- if(on) user.set_light(user.luminosity + brightness_on)
- else user.set_light(user.luminosity - brightness_on)
- user.update_inv_head()
-
-/obj/item/clothing/head/helmet/space/eva/plasmaman/pickup(mob/user)
- if(on)
- user.set_light(user.luminosity + brightness_on)
-// user.UpdateLuminosity()
+ if(on)
+ set_light(brightness_on)
+ else
set_light(0)
-/obj/item/clothing/head/helmet/space/eva/plasmaman/dropped(mob/user)
- if(on)
- user.set_light(user.luminosity - brightness_on)
-// user.UpdateLuminosity()
- set_light(brightness_on)
-
-
+ if(istype(user,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = user
+ H.update_inv_head()
// ENGINEERING
/obj/item/clothing/suit/space/eva/plasmaman/assistant
@@ -305,7 +296,7 @@
/obj/item/clothing/suit/space/eva/plasmaman/nuclear
name = "blood red plasmaman suit"
icon_state = "plasmaman_Nukeops"
- armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 60)
+ armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50)
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/weapon/gun,/obj/item/ammo_casing,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/restraints/handcuffs)
siemens_coefficient = 0.6
@@ -313,20 +304,5 @@
name = "blood red plasmaman helmet"
icon_state = "plasmaman_Nukeops_helmet0"
base_state = "plasmaman_Nukeops_helmet"
- armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 35, bio = 100, rad = 60)
+ armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50)
siemens_coefficient = 0.6
- var/obj/machinery/camera/camera
-
-/obj/item/clothing/head/helmet/space/eva/plasmaman/nuclear/attack_self(mob/user)
- if(camera)
- ..(user)
- else
- camera = new /obj/machinery/camera(src)
- camera.network = list("NUKE")
- cameranet.removeCamera(camera)
- camera.c_tag = user.name
- user << "User scanned as [camera.c_tag]. Camera activated."
-
-/obj/item/clothing/head/helmet/space/eva/plasmaman/nuclear/examine(mob/user)
- if(..(user, 1))
- user << "This helmet has a built-in camera. It's [camera ? "" : "in"]active."
\ No newline at end of file
diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm
index b3c5d19b6d7..8f1703a3325 100644
--- a/code/modules/clothing/spacesuits/rig.dm
+++ b/code/modules/clothing/spacesuits/rig.dm
@@ -27,20 +27,24 @@
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi',
)
- attack_self(mob/user)
- if(!isturf(user.loc))
- user << "You cannot turn the light on while in this [user.loc]" //To prevent some lighting anomalities.
- return
- on = !on
- icon_state = "rig[on]-[_color]"
-// item_state = "rig[on]-[color]"
+/obj/item/clothing/head/helmet/space/rig/attack_self(mob/user)
+ if(!isturf(user.loc))
+ user << "You cannot turn the light on while in this [user.loc]." //To prevent some lighting anomalities.
+ return
+ toggle_light(user)
- if(on) set_light(brightness_on)
- else set_light(0)
+/obj/item/clothing/head/helmet/space/rig/proc/toggle_light(mob/user)
+ on = !on
+ icon_state = "rig[on]-[_color]"
- if(istype(user,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = user
- H.update_inv_head()
+ if(on)
+ set_light(brightness_on)
+ else
+ set_light(0)
+
+ if(istype(user,/mob/living/carbon/human))
+ var/mob/living/carbon/human/H = user
+ H.update_inv_head()
/obj/item/clothing/suit/space/rig
name = "hardsuit"
@@ -98,7 +102,7 @@
else
M << "Your suit's helmet deploys with a hiss."
//TODO: Species check, skull damage for forcing an unfitting helmet on?
- helmet.loc = H
+ helmet.forceMove(H)
H.equip_to_slot(helmet, slot_head)
helmet.flags |= NODROP
@@ -107,7 +111,7 @@
M << "You are unable to deploy your suit's magboots as \the [H.shoes] are in the way."
else
M << "Your suit's boots deploy with a hiss."
- boots.loc = H
+ boots.forceMove(H)
H.equip_to_slot(boots, slot_shoes)
boots.flags |= NODROP
@@ -122,7 +126,7 @@
if(helmet && H.head == helmet)
helmet.flags &= ~NODROP
H.unEquip(helmet)
- helmet.loc = src
+ helmet.forceMove(src)
if(boots)
H = boots.loc
@@ -130,58 +134,15 @@
if(boots && H.shoes == boots)
boots.flags &= ~NODROP
H.unEquip(boots)
- boots.loc = src
-
-/*
-/obj/item/clothing/suit/space/rig/verb/get_mounted_device()
-
- set name = "Deploy Mounted Device"
- set category = "Object"
- set src in usr
-
- if(!can_mount)
- verbs -= /obj/item/clothing/suit/space/rig/verb/get_mounted_device
- verbs -= /obj/item/clothing/suit/space/rig/verb/stow_mounted_device
- return
-
- if(!istype(usr, /mob/living)) return
- if(usr.stat) return
-
- if(active_device)
- usr << "You already have \the [active_device] deployed."
- return
-
- if(!mounted_devices.len)
- usr << "You do not have any devices mounted on \the [src]."
- return
-
-/obj/item/clothing/suit/space/rig/verb/stow_mounted_device()
-
- set name = "Stow Mounted Device"
- set category = "Object"
- set src in usr
-
- if(!can_mount)
- verbs -= /obj/item/clothing/suit/space/rig/verb/get_mounted_device
- verbs -= /obj/item/clothing/suit/space/rig/verb/stow_mounted_device
- return
-
- if(!istype(usr, /mob/living)) return
-
- if(usr.stat) return
-
- if(!active_device)
- usr << "You have no device currently deployed."
- return
-*/
-
+ boots.forceMove(src)
+
/obj/item/clothing/suit/space/rig/verb/toggle_helmet()
-
set name = "Toggle Helmet"
set category = "Object"
set src in usr
- if(!istype(src.loc,/mob/living)) return
+ if(!isliving(usr))
+ return
if(!helmet)
usr << "There is no helmet installed."
@@ -197,23 +158,22 @@
helmet.flags &= ~NODROP
H.unEquip(helmet)
helmet.loc = src
- H << "\blue You retract your hardsuit helmet."
+ H << "You retract your hardsuit helmet."
else
if(H.head)
- H << "\red You cannot deploy your helmet while wearing another helmet."
+ H << "You cannot deploy your helmet while wearing another helmet."
return
//TODO: Species check, skull damage for forcing an unfitting helmet on?
helmet.loc = H
helmet.pickup(H)
H.equip_to_slot(helmet, slot_head)
helmet.flags |= NODROP
- H << "\blue You deploy your hardsuit helmet, sealing you off from the world."
+ H << "You deploy your hardsuit helmet, sealing you off from the world."
H.update_inv_head()
/obj/item/clothing/suit/space/rig/attackby(obj/item/W as obj, mob/user as mob, params)
-
- if(!istype(user,/mob/living)) return
-
+ if(!isliving(user))
+ return
if(istype(src.loc,/mob/living))
user << "How do you propose to modify a hardsuit while it is being worn?"
@@ -230,7 +190,7 @@
if(!boots)
user << "\The [src] does not have any boots installed."
else
- user << "You detatch \the [boots] from \the [src]'s boot mounts."
+ user << "You detach \the [boots] from \the [src]'s boot mounts."
boots.loc = get_turf(src)
boots = null
return
@@ -338,8 +298,9 @@
/obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user)
if(!isturf(user.loc))
- user << "You cannot toggle your helmet while in this [user.loc]" //To prevent some lighting anomalities.
+ user << "You cannot toggle your helmet while in this [user.loc]." //To prevent some lighting anomalities.
return
+
on = !on
if(on)
user << "You switch your helmet to travel mode. It will allow you to stand in zero pressure environments, at the cost of speed and armor."
@@ -484,7 +445,6 @@
heat_protection = HEAD //Uncomment to enable firesuit protection
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
-
/obj/item/clothing/suit/space/rig/atmos
desc = "A special suit that protects against hazardous, low pressure environments. Has improved thermal protection and minor radiation shielding."
icon_state = "rig-atmos"
diff --git a/code/modules/customitems/item_spawning.dm b/code/modules/customitems/item_spawning.dm
index e7e1e299f27..93c9733eae0 100644
--- a/code/modules/customitems/item_spawning.dm
+++ b/code/modules/customitems/item_spawning.dm
@@ -62,6 +62,7 @@
Item.loc = get_turf(M.loc)
HackProperties(Item,propadjust)
+ M.regenerate_icons()
// This is hacky, but since it's difficult as fuck to make a proper parser in BYOND without killing the server, here it is. - N3X
/proc/HackProperties(var/mob/living/carbon/human/M,var/obj/item/I,var/script)
diff --git a/code/modules/DetectiveWork/detective_work.dm b/code/modules/detective_work/detective_work.dm
similarity index 100%
rename from code/modules/DetectiveWork/detective_work.dm
rename to code/modules/detective_work/detective_work.dm
diff --git a/code/modules/DetectiveWork/evidence.dm b/code/modules/detective_work/evidence.dm
similarity index 100%
rename from code/modules/DetectiveWork/evidence.dm
rename to code/modules/detective_work/evidence.dm
diff --git a/code/modules/DetectiveWork/footprints_and_rag.dm b/code/modules/detective_work/footprints_and_rag.dm
similarity index 100%
rename from code/modules/DetectiveWork/footprints_and_rag.dm
rename to code/modules/detective_work/footprints_and_rag.dm
diff --git a/code/modules/DetectiveWork/scanner.dm b/code/modules/detective_work/scanner.dm
similarity index 100%
rename from code/modules/DetectiveWork/scanner.dm
rename to code/modules/detective_work/scanner.dm
diff --git a/code/modules/garbage collection/__gc_info.dm b/code/modules/garbage_collection/__gc_info.dm
similarity index 100%
rename from code/modules/garbage collection/__gc_info.dm
rename to code/modules/garbage_collection/__gc_info.dm
diff --git a/code/modules/garbage collection/garbage_collector.dm b/code/modules/garbage_collection/garbage_collector.dm
similarity index 100%
rename from code/modules/garbage collection/garbage_collector.dm
rename to code/modules/garbage_collection/garbage_collector.dm
diff --git a/code/modules/garbage collection/gc_testing.dm b/code/modules/garbage_collection/gc_testing.dm
similarity index 100%
rename from code/modules/garbage collection/gc_testing.dm
rename to code/modules/garbage_collection/gc_testing.dm
diff --git a/code/modules/genetics2/computer.dm b/code/modules/genetics2/computer.dm
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/code/modules/genetics2/genetree.dm b/code/modules/genetics2/genetree.dm
deleted file mode 100644
index aa8d1ba7571..00000000000
--- a/code/modules/genetics2/genetree.dm
+++ /dev/null
@@ -1,63 +0,0 @@
-// Management of available genes.
-
-/datum/genetree
- var/list/sectors=list()
- var/list/dependencies=list()
- var/list/dependants=list()
- var/obj/machinery/networked/biomass_controller/biomass = null
-
-/datum/genetree/New(var/obj/machinery/networked/biomass_controller/holder)
- biomass = holder
- // Build list of all sectors
- for(var/typepath in subtypesof(/datum/genetic_sector))
- var/datum/genetic_sector/sector = new typepath
- sectors[sector.id]=sector
-
- if(sector.prerequisites.len > 0)
- sector.locked=1
-
- // Make list of things that depend on this sector.
- dependencies[sector.id]=sector.prerequisites
-
- // Generate reverse dependencies
- for(var/dependee in sector.prerequisites)
- if(!(dependee in dependants))
- dependants[dependee]=list(sector.id)
- else
- var/list/D = dependants[dependee]
- D.Add(sector.name)
-
-/datum/genetree/proc/IsActive(var/sname)
- var/datum/genetic_sector/sector = sectors[sname]
- return sector.active
-
-/datum/genetree/proc/CanActivateSector(var/sname)
- var/datum/genetic_sector/sector = sectors[sname]
- for(var/dep in sector.prerequisites)
- if(!IsActive(sector.id))
- return 0
- return biomass.available >= sector.required_biomass
-
-// Does NOT check for biomass
-/datum/genetree/proc/ActivateSector(var/sname)
- var/datum/genetic_sector/sector = sectors[sname]
- sector.active = 1
- sector.OnActivate()
- for(var/subsect in dependants[sname])
- var/datum/genetic_sector/subsector = sectors[subsect]
- subsector.locked=0
-
-/datum/genetree/proc/CheckSectors()
- var/sectors_changed=0
- for(var/sname in sectors)
- var/datum/genetic_sector/sector = sectors[sname]
- var/pstate=sector.active
- sector.active=1
- for(var/prereq in sector.prerequisites)
- if(!IsActive(prereq))
- sector.active=0
- break
- if(pstate != sector.active)
- sectors_changed = 1
- if(sectors_changed)
- CheckSectors()
\ No newline at end of file
diff --git a/code/modules/genetics2/sectors.dm b/code/modules/genetics2/sectors.dm
deleted file mode 100644
index aec12619180..00000000000
--- a/code/modules/genetics2/sectors.dm
+++ /dev/null
@@ -1,110 +0,0 @@
-var/global/current_sector_id=0
-/datum/genetic_sector
- var/name = "UNKNOWN SECTOR"
- var/desc = "LOLIDK"
-
- var/id = ""
- var/uniqid = "" // 3-char ID, shown when locked.
- var/list/prerequisites = list()
- var/list/blocks_txt = list()
- var/list/blocks = list() // DO NOT FUCKING USE THIS
- var/required_biomass = 0 // In hominids (/mob/living/carbon)
- var/time_required = 300 // Decaseconds required to unlock
- var/time_researched = 0
- var/active=0 // Accessible
- var/locked=0 // Cannot be purchased (yet)
-
-/datum/genetic_sector/New()
- uniqid = add_zero2("[current_sector_id++]",3)
-
- // Set blocks
- for(var/blockname in blocks_txt)
- var/block = assigned_blocks[blockname]
- if(block)
- blocks += block
-
-///////////////////////////////////////
-// SECTORS
-///////////////////////////////////////
-
-/datum/genetic_sector/metabolism
- id = "metabolism"
- name = "Metabolism"
- desc = "Grants access to areas of DNA that affect how the body controls its temperature."
- required_biomass = 1
- time_required = 30 SECONDS
- blocks_txt=list(
- "COLD",
- "FIRE",
- "IMMOLATE",
- "SOBER",
- "MELT",
- "FAT"
- )
-
-/datum/genetic_sector/mind
- id = "mind"
- name = "Mental Aptitude"
- desc = "Reveals parts of DNA that affect mental capabilities"
- required_biomass = 2
- time_required = 30 SECONDS
- blocks_txt=list(
- "PSYRESIST",
- "HALLUCINATION",
- "TWITCH",
- "EPILEPSY",
- )
-
-/datum/genetic_sector/teleability
- id = "teleability"
- name = "Teleability"
- desc = "Activates unused portions of the brain that can affect people a great distance away."
- prerequisites = list("mind")
- required_biomass = 4
- time_required = 1 MINUTES
- blocks_txt = list(
- "REMOTEVIEW",
- "REMOTETALK",
- "CRYO",
- "EMPATH"
- )
-
-/datum/genetic_sector/telekinesis
- id = "telekinesis"
- name = "Telekinesis"
- desc = "Activates unused portions of the brain that can affect objects a great distance away."
- prerequisites = list("teleability")
- required_biomass = 5
- time_required = 2 MINUTES
- blocks_txt = list(
- "TELE",
- "FAKE"
- )
-
-/datum/genetic_sector/senses
- id = "senses"
- name = "Senses"
- desc = "Accesses genes that affect vision and hearing."
- prerequisites = list("mind")
- required_biomass = 4
- time_required = 30 SECONDS
- blocks_txt = list(
- "XRAY",
- "BLIND",
- "GLASSES",
- "EMPATH",
- "DEAF"
- )
-
-/datum/genetic_sector/respiration
- id = "respiration"
- name = "Respiration"
- desc = "Mess around with genes that affect breathing and lungs."
- prerequisites = list("metabolism")
- time_required = 1 MINUTES
- required_biomass = 4
- blocks_txt = list(
- "NOBREATH",
- "COUGH",
- "INCREASERUN",
- )
\ No newline at end of file
diff --git a/code/modules/icon generation/Bluespaced.dm b/code/modules/icon generation/Bluespaced.dm
deleted file mode 100644
index 697b9e97196..00000000000
--- a/code/modules/icon generation/Bluespaced.dm
+++ /dev/null
@@ -1,243 +0,0 @@
-/proc/bsi_cast_ray(icon/I, list/start, list/end)
-
- if(abs(start[1] - end[1]) > abs(start[2] - end[2]))
- var/dist = abs(start[1] - end[1]) * 2
-
- for(var/i = 1, i <= dist, i++)
- var/x = round((start[1] * i / dist) + (end[1] * (1 - i / dist)))
- var/y = round((start[2] * i / dist) + (end[2] * (1 - i / dist)))
-
- if(I.GetPixel(x, y) != null)
- return list(x, y)
-
- else
- var/dist = abs(start[2] - end[2]) * 2
-
- for(var/i = 1, i <= dist, i++)
- var/x = round((start[1] * i / dist) + (end[1] * (1 - i / dist)))
- var/y = round((start[2] * i / dist) + (end[2] * (1 - i / dist)))
-
- if(I.GetPixel(x, y) != null)
- return list(x, y)
-
- return null
-
-/proc/bsi_split_colors(color)
- if(color == null)
- return list(0, 0, 0, 0)
-
- var/list/colors = list(0, 0, 0, 0)
- colors[1] = hex2num(copytext(color, 2, 4))
- colors[2] = hex2num(copytext(color, 4, 6))
- colors[3] = hex2num(copytext(color, 6, 8))
- colors[4] = (length(color) > 7)? hex2num(copytext(color, 8, 10)) : 255
-
- return colors
-
-/proc/bsi_spread(icon/I, list/start_point)
- var/list/queue = list()
- queue[++queue.len] = start_point
-
- var/i = 0
-
- while(i++ < length(queue))
- var/x = queue[i][1]
- var/y = queue[i][2]
-
- var/list/pixel = bsi_split_colors(I.GetPixel(x, y))
- if(pixel[4] == 0)
- continue
-
- var/list/n = (y < I.Height())? bsi_split_colors(I.GetPixel(x, y + 1)) : list(0, 0, 0, 0)
- var/list/s = (y > 1)? bsi_split_colors(I.GetPixel(x, y - 1)) : list(0, 0, 0, 0)
- var/list/e = (x < I.Width())? bsi_split_colors(I.GetPixel(x + 1, y)) : list(0, 0, 0, 0)
- var/list/w = (x > 1)? bsi_split_colors(I.GetPixel(x - 1, y)) : list(0, 0, 0, 0)
-
- var/value = (i == 1)? 16 : max(n[1] - 1, e[1] - 1, s[1] - 1, w[1] - 1)
-
- if(prob(50))
- value = max(0, value - 1)
-
- if(prob(50))
- value = max(0, value - 1)
-
- if(prob(50))
- value = max(0, value - 1)
-
- if(value <= pixel[1])
- continue
-
- var/v2 = 256 - ((16 - value) * (16 - value))
-
- I.DrawBox(rgb(value, v2, pixel[4] - v2, pixel[4]), x, y)
-
- if(n[4] != 0 && n[1] < value - 1)
- queue[++queue.len] = list(x, y + 1)
-
- if(s[4] != 0 && s[1] < value - 1)
- queue[++queue.len] = list(x, y - 1)
-
- if(e[4] != 0 && e[1] < value - 1)
- queue[++queue.len] = list(x + 1, y)
-
- if(w[4] != 0 && w[1] < value - 1)
- queue[++queue.len] = list(x - 1, y)
-
-
-
-
-
-/proc/bsi_generate_mask(icon/source, state)
- var/icon/mask = icon(source, state)
-
- mask.MapColors(
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 1, 1,
- 0, 0, 0, 0)
-
- var/hits = 0
-
- for(var/i = 1, i <= 10, i++)
- var/point1
- var/point2
-
- if(prob(50))
- if(prob(50))
- point1 = list(rand(1, mask.Width()), mask.Height())
- point2 = list(rand(1, mask.Width()), 1)
-
- else
- point2 = list(rand(1, mask.Width()), mask.Height())
- point1 = list(rand(1, mask.Width()), 1)
-
- else
- if(prob(50))
- point1 = list(mask.Width(), rand(1, mask.Height()))
- point2 = list(1, rand(1, mask.Height()))
-
- else
- point2 = list(mask.Width(), rand(1, mask.Height()))
- point1 = list(1, rand(1, mask.Height()))
-
- var/hit = bsi_cast_ray(mask, point1, point2)
-
- if(hit == null)
- continue
-
- hits++
-
- bsi_spread(mask, hit)
-
- if(prob(20 + hits * 20))
- break
-
- if(hits == 0)
- return null
-
- else
- return mask
-
-/proc/generate_bluespace_icon(icon/source, state)
-
- var/icon/mask = bsi_generate_mask(source, state)
-
- if(mask == null)
- return source
-
- var/icon/unaffected = icon(mask)
- unaffected.MapColors(
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 1,
- 0, 0, 0, 0,
- 255, 255, 255, 0)
-
- var/icon/temp = icon(source, state) //Mask already contains the original alpha values, avoid squaring them
- temp.MapColors(
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 255)
-
- unaffected.Blend(temp, ICON_MULTIPLY)
-
- var/icon/bluespaced = icon(mask)
- bluespaced.MapColors(
- 0, 0, 0, 0,
- 0, 0, 0, 1,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 1, 1, 1, 0)
-
- bluespaced.Blend(icon(source, state), ICON_MULTIPLY)
-
- var/list/frames = list(
- list(0.000,20),
- list(0.020, 5),
- list(0.050, 4),
- list(0.080, 5),
- list(0.100,10),
- list(0.080, 5),
- list(0.050, 4),
- list(0.020, 5),
-
- list(0.000,20),
- list(0.020, 5),
- list(0.050, 4),
- list(0.080, 5),
- list(0.100,10),
- list(0.080, 5),
- list(0.050, 4),
- list(0.020, 5),
-
- list(0.000,20),
- list(0.020, 5),
- list(0.050, 4),
- list(0.080, 5),
- list(0.100,10),
- list(0.080, 5),
- list(0.050, 4),
- list(0.020, 5),
- )
-
- var/list/colors = list(
- list( 75, 75, 75, 0),
- list( 25, 25, 25, 0),
- list( 75, 75, 75, 0),
- list( 25, 25, 75, 0),
- list( 75, 75, 300, 0),
- list( 25, 25, 300, 0),
- list(255, 255, 255, 0),
- list( 0, 0, 0, 255),
- list( 0, 0, 0, 0),
- list( 0, 0, 0, 0),
- )
-
- for(var/i = 1, i <= rand(1, 5), i++)
- var/f = rand(1, length(frames))
-
- if(frames[f][2] > 1)
- frames[f][2]--
- frames.Insert(f, 0)
-
- frames[f] = list(0.8, 1)
-
- var/icon/result = generate_color_animation(bluespaced, colors, frames)
- result.Blend(unaffected, ICON_UNDERLAY)
-
- return result
-
-
-
-/atom/verb/test()
- set src in view()
- src.icon = generate_bluespace_icon(src.icon, src.icon_state)
-
-/mob/verb/bluespam()
- for(var/turf/t in view(5))
- var/obj/s = new /obj/square(t)
- s.icon = generate_bluespace_icon(s.icon, s.icon_state)
-
diff --git a/code/modules/icon generation/Icon_color_animation.dm b/code/modules/icon generation/Icon_color_animation.dm
deleted file mode 100644
index 1be1bfa28a9..00000000000
--- a/code/modules/icon generation/Icon_color_animation.dm
+++ /dev/null
@@ -1,96 +0,0 @@
-//----------------------------------------
-//
-// Return a copy of the provided icon,
-// after calling MapColors on it. The
-// color values are linearily interpolated
-// between the pairs provided, based on
-// the ratio argument.
-//
-//----------------------------------------
-
-/proc/MapColors_interpolate(icon/input, ratio,
- rr1, rg1, rb1, ra1, rr2, rg2, rb2, ra2,
- gr1, gg1, gb1, ga1, gr2, gg2, gb2, ga2,
- br1, bg1, bb1, ba1, br2, bg2, bb2, ba2,
- ar1, ag1, ab1, aa1, ar2, ag2, ab2, aa2,
- zr1, zg1, zb1, za1, zr2, zg2, zb2, za2)
- var/r = ratio
- var/i = 1 - ratio
- var/icon/I = icon(input)
-
- I.MapColors(
- (rr1 * r + rr2 * i) / 255.0, (rg1 * r + rg2 * i) / 255.0, (rb1 * r + rb2 * i) / 255.0, (ra1 * r + ra2 * i) / 255.0,
- (gr1 * r + gr2 * i) / 255.0, (gg1 * r + gg2 * i) / 255.0, (gb1 * r + gb2 * i) / 255.0, (ga1 * r + ga2 * i) / 255.0,
- (br1 * r + br2 * i) / 255.0, (bg1 * r + bg2 * i) / 255.0, (bb1 * r + bb2 * i) / 255.0, (ba1 * r + ba2 * i) / 255.0,
- (ar1 * r + ar2 * i) / 255.0, (ag1 * r + ag2 * i) / 255.0, (ab1 * r + ab2 * i) / 255.0, (aa1 * r + aa2 * i) / 255.0,
- (zr1 * r + zr2 * i) / 255.0, (zg1 * r + zg2 * i) / 255.0, (zb1 * r + zb2 * i) / 255.0, (za1 * r + za2 * i) / 255.0)
-
- return I
-
-
-
-
-//----------------------------------------
-//
-// Extension of the above that takes a
-// list of lists of color values, rather
-// than a large number of arguments.
-//
-//----------------------------------------
-
-/proc/MapColors_interpolate_list(icon/I, ratio, list/colors)
- var/list/c[10]
-
- //Provide default values for any missing colors (without altering the original list
- for(var/i = 1, i <= 10, i++)
- c[i] = list(0, 0, 0, (i == 7 || i == 8)? 255 : 0)
-
- if(istype(colors[i], /list))
- for(var/j = 1, j <= 4, j++)
- if(j <= length(colors[i]) && isnum(colors[i][j]))
- c[i][j] = colors[i][j]
-
- return MapColors_interpolate(I, ratio,
- colors[ 1][1], colors[ 1][2], colors[ 1][3], colors[ 1][4], // Red 1
- colors[ 2][1], colors[ 2][2], colors[ 2][3], colors[ 2][4], // Red 2
- colors[ 3][1], colors[ 3][2], colors[ 3][3], colors[ 3][4], // Green 1
- colors[ 4][1], colors[ 4][2], colors[ 4][3], colors[ 4][4], // Green 2
- colors[ 5][1], colors[ 5][2], colors[ 5][3], colors[ 5][4], // Blue 1
- colors[ 6][1], colors[ 6][2], colors[ 6][3], colors[ 6][4], // Blue 2
- colors[ 7][1], colors[ 7][2], colors[ 7][3], colors[ 7][4], // Alpha 1
- colors[ 8][1], colors[ 8][2], colors[ 8][3], colors[ 8][4], // Alpha 2
- colors[ 9][1], colors[ 9][2], colors[ 9][3], colors[ 9][4], // Added 1
- colors[10][1], colors[10][2], colors[10][3], colors[10][4]) // Added 2
-
-
-
-
-
-//----------------------------------------
-//
-// Take the source image, and return an animated
-// version, that transitions between the provided
-// color mappings, according to the provided
-// pattern.
-//
-// Colors should be in a format suitable for
-// MapColors_interpolate_list, and frames should
-// be a list of 'frames', where each frame is itself
-// a list, element 1 being the ratio of the first
-// color to the second, and element 2 being how
-// long the frame lasts, in tenths of a second.
-//
-//----------------------------------------
-
-/proc/generate_color_animation(icon/icon, list/colors, list/frames)
- var/icon/out = icon('icons/effects/uristrunes.dmi', "")
- var/frame_num = 1
-
- for(var/frame in frames)
- var/icon/I = MapColors_interpolate_list(icon, frame[1], colors)
- out.Insert(I, "", 2, frame_num++, 0, frame[2])
-
- return out
-
-
-
diff --git a/code/modules/icon generation/Uristrunes.dm b/code/modules/icon generation/Uristrunes.dm
deleted file mode 100644
index d9c129df8ed..00000000000
--- a/code/modules/icon generation/Uristrunes.dm
+++ /dev/null
@@ -1,268 +0,0 @@
-//----------------------------------------
-//
-// Take a source icon, convert into a mask,
-// then create a border around it.
-//
-// The output then uses the colors and
-// alpha values provided.
-//
-//----------------------------------------
-
-/proc/create_border_image(icon/input, border_color = "#000000", fill_color = "#000000", border_alpha = 255, fill_alpha = 255)
- var/icon/I = icon('icons/effects/uristrunes.dmi', "blank")
- I.Blend(input, ICON_OVERLAY)
-
- //Discard the image
- I.MapColors(0, 0, 0, 0, //-\ Ignore
- 0, 0, 0, 0, //--> The
- 0, 0, 0, 0, //-/ Colors
- 0,255, 0, 1, //Keep alpha channel, any pixel with non-zero alpha gets max green channel
- 0, 0, 0, 0)
-
- //Loop over the image, calculating the border value, and storing it in the red channel
- //Store border's alpha in the blue channel
- for(var/x = 1, x <= 32, x++)
- for(var/y = 1, y <= 32, y++)
- var/p = I.GetPixel(x, y)
-
- if(p == null)
- var/n = I.GetPixel(x, y + 1)
- var/s = I.GetPixel(x, y - 1)
- var/e = I.GetPixel(x + 1, y)
- var/w = I.GetPixel(x - 1, y)
- var/ne = I.GetPixel(x + 1, y + 1)
- var/se = I.GetPixel(x + 1, y - 1)
- var/nw = I.GetPixel(x - 1, y + 1)
- var/sw = I.GetPixel(x - 1, y - 1)
-
- var/sum_adj = ((n == "#00ff00"? 1 : 0) \
- + (s == "#00ff00"? 1 : 0) \
- + (e == "#00ff00"? 1 : 0) \
- + (w == "#00ff00"? 1 : 0))
-
- var/sum_diag = ((ne == "#00ff00"? 1 : 0) \
- + (se == "#00ff00"? 1 : 0) \
- + (nw == "#00ff00"? 1 : 0) \
- + (sw == "#00ff00"? 1 : 0))
-
-
- if(sum_adj)
- I.DrawBox(rgb(255, 0, 200, 0), x, y)
-
- else if(sum_diag)
- I.DrawBox(rgb(255, 0, 100, 0), x, y)
-
- else
- I.DrawBox(rgb(0, 0, 0, 0), x, y)
-
- else if(p != "#00ff00")
- var/a = 255
-
- if(length(p) == 9) // "#rrggbbaa", we want the aa
- a = hex2num(copytext(p, 8))
-
- I.DrawBox(rgb(255 - a, a, 255 - a, a), x, y)
-
- //Map the red and green channels to the desired output colors
- I.MapColors(border_color, fill_color, rgb(0, 0, 0, border_alpha), rgb(0, 0, 0, fill_alpha), "#00000000")
-
- return I
-
-
-
-
-//----------------------------------------
-//
-// Take a source icon, convert into a mask,
-// and border. Color them according to args,
-// and animate.
-//
-//----------------------------------------
-
-/proc/animate_rune_full(icon/input, rr1, rg1, rb1, ra1, rr2, rg2, rb2, ra2, br1, bg1, bb1, ba1, br2, bg2, bb2, ba2, ar1, ag1, ab1, aa1, ar2, ag2, ab2, aa2, or1, og1, ob1, oa1, or2, og2, ob2, oa2, frames)
-
- var/list/colors[10]
- colors[ 1] = list(rr1, rg1, rb1, ra1) //Rune color 1
- colors[ 2] = list(rr2, rg2, rb2, ra2) //Rune color 2
- colors[ 3] = list(br1, bg1, bb1, ba1) //Border color 1
- colors[ 4] = list(br2, bg2, bb2, ba2) //Border color 2
- colors[ 5] = list( 0, 0, 0, 0) //Unused
- colors[ 6] = list( 0, 0, 0, 0) //Unused
- colors[ 7] = list(ar1, ag1, ab1, aa1) //Alpha color 1
- colors[ 8] = list(ar2, ag2, ab2, aa2) //Alpha color 2
- colors[ 9] = list(or1, og1, ob1, oa1) //Added color 1
- colors[10] = list(or2, og2, ob2, oa2) //Added color 2
-
- var/icon/base = create_border_image(input, "#00ff0000", "#ff000000")
-
- return generate_color_animation(base, colors, frames)
-
-
-
-
-//----------------------------------------
-//
-// Calls the above, but accepts colors in
-// the form of "#RRGGBBAA", and provides
-// default values.
-//
-// Main limit is that it doesn't accept
-// negative values, which you probably
-// don't need anyway. Also missing a few
-// color inputs, which would also be rarely
-// used.
-//
-//----------------------------------------
-
-
-/proc/animate_rune(icon/input, rune_color = "#00000000", border_color = "#c8000000", rune_color2 = "#00000000", border_color2 = "#d8380000", alpha = 255, alpha2 = 255, frames = rune_animation)
- var/rr1 = hex2num(copytext(rune_color, 2, 4))
- var/rg1 = hex2num(copytext(rune_color, 4, 6))
- var/rb1 = hex2num(copytext(rune_color, 6, 8))
- var/ra1 = hex2num(copytext(rune_color, 8, 10))
- var/rr2 = hex2num(copytext(rune_color2, 2, 4))
- var/rg2 = hex2num(copytext(rune_color2, 4, 6))
- var/rb2 = hex2num(copytext(rune_color2, 6, 8))
- var/ra2 = hex2num(copytext(rune_color2, 8, 10))
- var/br1 = hex2num(copytext(border_color, 2, 4))
- var/bg1 = hex2num(copytext(border_color, 4, 6))
- var/bb1 = hex2num(copytext(border_color, 6, 8))
- var/ba1 = hex2num(copytext(border_color, 8, 10))
- var/br2 = hex2num(copytext(border_color2, 2, 4))
- var/bg2 = hex2num(copytext(border_color2, 4, 6))
- var/bb2 = hex2num(copytext(border_color2, 6, 8))
- var/ba2 = hex2num(copytext(border_color2, 8, 10))
-
- return animate_rune_full(input, rr1, rg1, rb1, ra1, rr2, rg2, rb2, ra2, br1, bg1, bb1, ba1, br2, bg2, bb2, ba2, 0, 0, 0, alpha, 0, 0, 0, alpha2, 0, 0, 0, 0, 0, 0, 0, 0, frames)
-
-
-/proc/inanimate_rune(icon/input, rune_color = "#00000000", border_color = "#c8000000")
- var/icon/base = create_border_image(input, "#00ff0000", "#ff000000")
-
- base.MapColors(rune_color, border_color, "#00000000", "#000000ff", "#00000000")
-
- return base
-
-var/list/rune_animation = list(
- list(0.000, 5),
- list(0.020, 1),
- list(0.050, 1),
- list(0.090, 1),
- list(0.140, 1),
- list(0.200, 1),
- list(0.270, 1),
- list(0.340, 1),
- list(0.420, 1),
- list(0.500, 1),
- list(0.590, 1),
- list(0.675, 1),
- list(0.750, 1),
- list(0.900, 1),
- list(1.000, 6),
- list(0.875, 1),
- list(0.750, 1),
- list(0.625, 1),
- list(0.500, 1),
- list(0.375, 1),
- list(0.250, 1),
- list(0.125, 1),
- )
-
-/var/list/rune_cache = list()
-
-/proc/get_rune(rune_bits, animated = 0)
- var/lookup = "[rune_bits]-[animated]"
-
- if(lookup in rune_cache)
- return rune_cache[lookup]
-
- var/icon/base = icon('icons/effects/uristrunes.dmi', "")
-
- for(var/i = 0, i < 10, i++)
- if(rune_bits & (1 << i))
- base.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY)
-
- var/icon/result
-
- if(animated == 1)
- result = animate_rune(base)
-
- else
- result = inanimate_rune(base)
-
- rune_cache[lookup] = result
- return result
-
-
-
-
-
-// Testing procs and Fun procs
-
-
-
-
-/mob/verb/create_rune()
- var/obj/o = new(locate(x, y, z))
- o.icon = get_rune(rand(1, 1023), 1)
-
-/mob/verb/runes_15x15()
- for(var/turf/t in range(7))
- var/obj/o = new /obj(t)
- o.icon = get_rune(rand(1, 1023), 1)
-
-
-/*
-/mob/verb/create_rune_custom(rune as num, color1 as color, border1 as color, color2 as color, border2 as color, alpha1 as num, alpha2 as num)
- var/icon/I = icon('icons/effects/uristrunes.dmi', "blank")
-
- for(var/i = 0, i < 10, i++)
- if(rune & (1 << i))
- I.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY)
-
- var/obj/o = new(locate(x, y, z))
- o.icon = animate_rune(I, color1, border1, color2, border2, alpha1, alpha2)
-
-/mob/verb/spam()
- for(var/turf/t in range(4))
- var/icon/I = icon('icons/effects/uristrunes.dmi', "blank")
-
- var/rune = rand(1, 1023)
- for(var/i = 0, i < 10, i++)
- if(rune & (1 << i))
- I.Blend(icon('icons/effects/uristrunes.dmi', "rune-[1 << i]"), ICON_OVERLAY)
-
- var/obj/o = new(t)
- o.icon = animate_rune_full(I, rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255),
- rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255),
- rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255),
- rand(0, 255), rand(0, 255), rand(0, 255), rand(-255, 255),
- 0, 0, 0, rand(0, 255),
- 0, 0, 0, rand(0, 255),
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- list(
- list(0.000, 5),
- list(0.020, 1),
- list(0.050, 1),
- list(0.090, 1),
- list(0.140, 1),
- list(0.200, 1),
- list(0.270, 1),
- list(0.340, 1),
- list(0.420, 1),
- list(0.500, 1),
- list(0.590, 1),
- list(0.675, 1),
- list(0.750, 1),
- list(0.900, 1),
- list(1.000, 6),
- list(0.875, 1),
- list(0.750, 1),
- list(0.625, 1),
- list(0.500, 1),
- list(0.375, 1),
- list(0.250, 1),
- list(0.125, 1),
- ))
-*/
\ No newline at end of file
diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm
index e355194ddfc..e81ade4287a 100644
--- a/code/modules/mining/equipment_locker.dm
+++ b/code/modules/mining/equipment_locker.dm
@@ -571,7 +571,7 @@
playsound(src,'sound/weapons/resonator_blast.ogg',50,1)
if(creator)
for(var/mob/living/L in src.loc)
- add_logs(creator, L, "used a resonator field on", object="resonator")
+ add_logs(L, creator, "used a resonator field on", object="resonator")
L << "The [src.name] ruptured with you in it!"
L.adjustBruteLoss(resonance_damage)
else
@@ -656,7 +656,7 @@
return
..()
-/mob/living/simple_animal/hostile/mining_drone/death()
+/mob/living/simple_animal/hostile/mining_drone/Die()
..()
visible_message("[src] is destroyed!")
new /obj/effect/decal/cleanable/blood/gibs/robot(src.loc)
@@ -707,11 +707,11 @@
/mob/living/simple_animal/hostile/mining_drone/proc/CollectOre()
var/obj/item/weapon/ore/O
for(O in src.loc)
- O.loc = src
+ O.forceMove(src)
for(var/dir in alldirs)
var/turf/T = get_step(src,dir)
for(O in T)
- O.loc = src
+ O.forceMove(src)
return
/mob/living/simple_animal/hostile/mining_drone/proc/DropOre()
@@ -719,7 +719,7 @@
return
for(var/obj/item/weapon/ore/O in contents)
contents -= O
- O.loc = src.loc
+ O.forceMove(loc)
return
/mob/living/simple_animal/hostile/mining_drone/adjustBruteLoss()
diff --git a/code/modules/mob/living/carbon/alien/alien_defenses.dm b/code/modules/mob/living/carbon/alien/alien_defenses.dm
index 8d0c36bc05d..ed98e221993 100644
--- a/code/modules/mob/living/carbon/alien/alien_defenses.dm
+++ b/code/modules/mob/living/carbon/alien/alien_defenses.dm
@@ -35,7 +35,7 @@ In all, this is a lot like the monkey code. /N
visible_message("[M.name] bites [src]!", \
"[M.name] bites [src]!")
adjustBruteLoss(damage)
- add_logs(M, src, "attacked", admin=0)
+ add_logs(src, M, "attacked", admin=0)
updatehealth()
else
M << "[name] is too injured for that."
@@ -67,4 +67,4 @@ In all, this is a lot like the monkey code. /N
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
adjustBruteLoss(damage)
- updatehealth()
+ updatehealth()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/death.dm b/code/modules/mob/living/carbon/alien/death.dm
index 40303b03543..693763e4960 100644
--- a/code/modules/mob/living/carbon/alien/death.dm
+++ b/code/modules/mob/living/carbon/alien/death.dm
@@ -53,7 +53,7 @@
if(client) blind.layer = 0
update_icons()
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
return ..(gibbed)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm
index a80a0d5892c..69d1eb600dc 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm
@@ -1,4 +1,7 @@
/mob/living/carbon/alien/humanoid/emote(var/act,var/m_type=1,var/message = null)
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/carbon/alien/larva/death.dm b/code/modules/mob/living/carbon/alien/larva/death.dm
index 67edcfd04ca..574b617ca58 100644
--- a/code/modules/mob/living/carbon/alien/larva/death.dm
+++ b/code/modules/mob/living/carbon/alien/larva/death.dm
@@ -9,8 +9,8 @@
update_canmove()
if(client) blind.layer = 0
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
living_mob_list -= src
return ..(gibbed)
diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm
index 12ad431f3c3..134350e2517 100644
--- a/code/modules/mob/living/carbon/alien/larva/emote.dm
+++ b/code/modules/mob/living/carbon/alien/larva/emote.dm
@@ -1,5 +1,7 @@
/mob/living/carbon/alien/larva/emote(var/act,var/m_type=1,var/message = null)
-
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/carbon/brain/death.dm b/code/modules/mob/living/carbon/brain/death.dm
index 17bf26de838..efcfac98624 100644
--- a/code/modules/mob/living/carbon/brain/death.dm
+++ b/code/modules/mob/living/carbon/brain/death.dm
@@ -11,8 +11,8 @@
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0) //mind. ?
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0) //mind. ?
return ..(gibbed)
diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm
index 0441eb00ac4..054a9b6e71c 100644
--- a/code/modules/mob/living/carbon/brain/emote.dm
+++ b/code/modules/mob/living/carbon/brain/emote.dm
@@ -1,4 +1,7 @@
/mob/living/carbon/brain/emote(var/act,var/m_type=1,var/message = null)
+ if(stat)
+ return
+
if(!(container && istype(container, /obj/item/device/mmi)))//No MMI, no emotes
return
diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm
index ff2b98d430f..bc0226f4597 100644
--- a/code/modules/mob/living/carbon/human/appearance.dm
+++ b/code/modules/mob/living/carbon/human/appearance.dm
@@ -110,7 +110,7 @@
return 1
/mob/living/carbon/human/proc/change_skin_color(var/red, var/green, var/blue)
- if(red == r_skin && green == g_skin && blue == b_skin || !(species.flags & HAS_SKIN_COLOR))
+ if(red == r_skin && green == g_skin && blue == b_skin || !(species.bodyflags & HAS_SKIN_COLOR))
return
r_skin = red
@@ -122,7 +122,7 @@
return 1
/mob/living/carbon/human/proc/change_skin_tone(var/tone)
- if(s_tone == tone || !(species.flags & HAS_SKIN_TONE))
+ if(s_tone == tone || !(species.bodyflags & HAS_SKIN_TONE))
return
s_tone = tone
@@ -182,4 +182,3 @@
valid_facial_hairstyles += facialhairstyle
return valid_facial_hairstyles
-
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index a9cf1ea1094..4307c6cbd0b 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -133,8 +133,8 @@
update_canmove()
if(client) blind.layer = 0
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
if(ticker && ticker.mode)
// log_to_dd("k")
sql_report_death(src)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 95e60ade252..338727330f5 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -1,4 +1,7 @@
/mob/living/carbon/human/emote(var/act,var/m_type=1,var/message = null)
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
@@ -334,8 +337,12 @@
m_type = 2
if ("deathgasp")
- message = "[src] seizes up and falls limp, \his eyes dead and lifeless..."
- m_type = 1
+ if (species.name == "Machine")
+ message = "[src] gives one shrill beep before falling limp, screen quickly flashing blue before shutting off entirely."
+ m_type = 1
+ else
+ message = "[src] seizes up and falls limp, \his eyes dead and lifeless..."
+ m_type = 1
if ("giggle")
if(miming)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 0e943d8c257..1b1964a000f 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -10,6 +10,11 @@
var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us.
/mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna=0)
+
+ if(!dna)
+ dna = new /datum/dna(null)
+ // Species name is handled by set_species()
+
if(!species)
if(new_species)
set_species(new_species,1)
@@ -36,9 +41,6 @@
..()
- if(dna)
- dna.real_name = real_name
-
prev_gender = gender // Debug for plural genders
make_blood()
@@ -46,8 +48,10 @@
faction |= "\ref[M]"
// Set up DNA.
- if(!delay_ready_dna)
+ if(!delay_ready_dna && dna)
dna.ready_dna(src)
+ dna.real_name = real_name
+ sync_organ_dna() //this shouldn't be necessaaaarrrryyyyyyyy
UpdateAppearance()
/mob/living/carbon/human/Destroy()
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index 4f404d1f314..c0587ddee86 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -22,15 +22,6 @@
update_revive()
return
-/mob/living/carbon/human/proc/update_revive() // handles revival through other means than cloning or adminbus (defib, IPC repair)
- stat = CONSCIOUS
- dead_mob_list -= src
- living_mob_list |= src
- mob_list |= src
- ear_deaf = 0
- tod = 0
- timeofdeath = 0
-
/mob/living/carbon/human/adjustBrainLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index eead644cc58..ef88db4a6dc 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -84,4 +84,4 @@
var/fire_dmi = 'icons/mob/OnFire.dmi'
var/fire_sprite = "Standing"
- var/datum/body_accessory/body_accessory = null
+ var/datum/body_accessory/body_accessory = null
\ 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 f61318e09c6..b54c7f5ee36 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -24,20 +24,10 @@
if(wear_suit)
tally += wear_suit.slowdown
- if(!buckled || (buckled && !istype(buckled, /obj/structure/stool/bed/chair/wheelchair)))
+ if(!buckled)
if(shoes)
tally += shoes.slowdown
- if(buckled && istype(buckled, /obj/structure/stool/bed/chair/wheelchair))
- for(var/organ_name in list("l_hand","r_hand","l_arm","r_arm"))
- var/obj/item/organ/external/E = get_organ(organ_name)
- if(!E || (E.status & ORGAN_DESTROYED))
- tally += 4
- else if(E.status & ORGAN_SPLINTED)
- tally += 0.5
- else if(E.status & ORGAN_BROKEN)
- tally += 1.5
-
if(shock_stage >= 10) tally += 3
if(back)
diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm
index 8889e5370da..7654b0d2e3b 100644
--- a/code/modules/mob/living/carbon/human/human_organs.dm
+++ b/code/modules/mob/living/carbon/human/human_organs.dm
@@ -144,4 +144,9 @@
//New are added for reagents to random organs.
for(var/datum/reagent/A in reagents.reagent_list)
var/obj/item/organ/O = pick(organs)
- O.trace_chemicals[A.name] = 100
\ No newline at end of file
+ O.trace_chemicals[A.name] = 100
+
+/mob/living/carbon/human/proc/sync_organ_dna()
+ var/list/all_bits = internal_organs|organs
+ for(var/obj/item/organ/O in all_bits)
+ O.set_dna(dna)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 875a3a85260..8967e1519d6 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -768,7 +768,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
light_amount = T.get_lumcount()*10
if(light_amount > species.light_dam && !incorporeal_move) //if there's enough light, start dying
if(species.light_effect_amp)
- adjustFireLoss(5) //This gets doubled by Shadowling's innate fire weakness, so it ends up being 10.
+ adjustFireLoss(4.7) //This gets multiplied by 1.5 due to Shadowling's innate fire weakness, so it ends up being about 7.
else
adjustFireLoss(1)
adjustBruteLoss(1)
@@ -968,7 +968,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
var/obj/item/organ/vision
if(species.vision_organ)
vision = internal_organs_by_name[species.vision_organ]
-
+
if(!species.vision_organ) // Presumably if a species has no vision organs, they see via some other means.
eye_blind = 0
blinded = 0
@@ -977,7 +977,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
eye_blind = 1
blinded = 1
eye_blurry = 1
- else
+ else
//blindness
if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own
blinded = 1
@@ -987,7 +987,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster
eye_blurry = max(eye_blurry-3, 0)
blinded = 1
-
+
//blurry sight
if(vision.is_bruised()) // Vision organs impaired? Permablurry.
eye_blurry = 1
@@ -1220,13 +1220,17 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
if(ANTAGHUD)
process_antag_hud(src)
-
-
-
else if(!seer)
see_in_dark = species.darksight
see_invisible = SEE_INVISIBLE_LIVING
-
+
+ if(vision_type)
+ see_in_dark = max(see_in_dark, vision_type.see_in_dark, species.darksight)
+ see_invisible = vision_type.see_invisible
+ if(vision_type.light_sensitive)
+ weakeyes = 1
+ sight |= vision_type.sight_flags
+
if(see_override) //Override all
see_invisible = see_override
diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm
index 14372e6c976..28862cf6cfc 100644
--- a/code/modules/mob/living/carbon/human/login.dm
+++ b/code/modules/mob/living/carbon/human/login.dm
@@ -5,5 +5,6 @@
src << "You can ventcrawl! Use alt+click on vents to quickly travel about the station."
update_pipe_vision()
update_hud()
- ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them.
+ if(ticker && ticker.mode)
+ ticker.mode.update_all_synd_icons() //This proc only sounds CPU-expensive on paper. It is O(n^2), but the outer for-loop only iterates through syndicates, which are only prsenet in nuke rounds and even when they exist, there's usually 6 of them.
return
diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm
index b525919b5bc..f3d61c038c7 100644
--- a/code/modules/mob/living/carbon/human/species/station.dm
+++ b/code/modules/mob/living/carbon/human/species/station.dm
@@ -59,7 +59,7 @@
/datum/species/unathi/handle_death(var/mob/living/carbon/human/H)
H.stop_tail_wagging(1)
-
+
/datum/species/unathi/equip(var/mob/living/carbon/human/H)
if(H.mind.assigned_role != "Clown")
H.unEquip(H.shoes)
@@ -105,7 +105,7 @@
/datum/species/tajaran/handle_death(var/mob/living/carbon/human/H)
H.stop_tail_wagging(1)
-
+
/datum/species/tajaran/equip(var/mob/living/carbon/human/H)
if(H.mind.assigned_role != "Clown")
H.unEquip(H.shoes)
@@ -219,7 +219,7 @@
i++
newname += pick(vox_name_syllables)
return capitalize(newname)
-
+
/datum/species/vox/equip(var/mob/living/carbon/human/H)
if(H.mind.assigned_role != "Clown" && H.mind.assigned_role != "Mime")
H.unEquip(H.wear_mask)
@@ -235,7 +235,7 @@
H.internal = H.l_hand
if (H.internals)
H.internals.icon_state = "internal1"
-
+
/*
/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H)
H.verbs += /mob/living/carbon/human/proc/leap
@@ -469,20 +469,20 @@
/datum/species/machine
name = "Machine"
name_plural = "Machines"
-
+
blurb = "Positronic intelligence really took off in the 26th century, and it is not uncommon to see independant, free-willed \
robots on many human stations, particularly in fringe systems where standards are slightly lax and public opinion less relevant \
to corporate operations. IPCs (Integrated Positronic Chassis) are a loose category of self-willed robots with a humanoid form, \
generally self-owned after being 'born' into servitude; they are reliable and dedicated workers, albeit more than slightly \
- inhuman in outlook and perspective."
-
+ inhuman in outlook and perspective."
+
icobase = 'icons/mob/human_races/r_machine.dmi'
deform = 'icons/mob/human_races/r_machine.dmi'
path = /mob/living/carbon/human/machine
default_language = "Galactic Common"
language = "Trinary"
unarmed_type = /datum/unarmed_attack/punch
-
+
eyes = "blank_eyes"
brute_mod = 2.5 // 100% * 2.5 * 0.6 (robolimbs) ~= 150%
burn_mod = 2.5 // So they take 50% extra damage from brute/burn overall.
@@ -500,20 +500,21 @@
flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | NO_DNA_RAD
clothing_flags = HAS_SOCKS
+ bodyflags = HAS_SKIN_COLOR
dietflags = 0 //IPCs can't eat, so no diet
blood_color = "#1F181F"
flesh_color = "#AAAAAA"
virus_immune = 1
can_revive_by_healing = 1
reagent_tag = PROCESS_SYN
-
+
has_organ = list(
"brain" = /obj/item/organ/mmi_holder/posibrain,
"cell" = /obj/item/organ/cell,
"optics" = /obj/item/organ/optical_sensor
)
- vision_organ = "optics"
+ vision_organ = "optics"
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest/ipc),
"groin" = list("path" = /obj/item/organ/external/groin/ipc),
@@ -532,7 +533,7 @@
H.h_style = ""
spawn(100)
if(H) H.update_hair()
-
+
/datum/species/machine/handle_post_spawn(var/mob/living/carbon/human/H)
..()
H.verbs += /mob/living/carbon/human/proc/change_monitor
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 4c99dd12895..86c2d79eb7b 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -238,15 +238,13 @@ var/global/list/damage_icon_parts = list()
var/hulk = (HULK in src.mutations)
var/skeleton = (SKELETON in src.mutations)
- var/g = (gender == FEMALE ? "f" : "m")
-
//CACHING: Generate an index key from visible bodyparts.
//0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic.
//Create a new, blank icon for our mob to use.
if(stand_icon)
qdel(stand_icon)
stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank")
- var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin]"
+ var/icon_key = ""
var/obj/item/organ/eyes/eyes = internal_organs_by_name["eyes"]
if(eyes)
@@ -265,6 +263,13 @@ var/global/list/damage_icon_parts = list()
else
icon_key += "1"
+ if(part)
+ icon_key += "[part.species.race_key]"
+ icon_key += "[part.dna.GetUIState(DNA_UI_GENDER)]"
+ icon_key += "[part.dna.GetUIValue(DNA_UI_SKIN_TONE)]"
+ if(part.s_col)
+ icon_key += "[rgb(part.s_col[1], part.s_col[2], part.s_col[3])]"
+
icon_key = "[icon_key][husk ? 1 : 0][fat ? 1 : 0][hulk ? 1 : 0][skeleton ? 1 : 0]"
var/icon/base_icon
@@ -868,8 +873,8 @@ var/global/list/damage_icon_parts = list()
var/image/I = image("icon" = r_hand.righthand_file, "icon_state"="[t_state]")
I = center_image(I, r_hand.inhand_x_dimension, r_hand.inhand_y_dimension)
- overlays_standing[R_HAND_LAYER] = I
-
+ overlays_standing[R_HAND_LAYER] = I
+
if (handcuffed) drop_r_hand()
else
overlays_standing[R_HAND_LAYER] = null
diff --git a/code/modules/mob/living/carbon/metroid/emote.dm b/code/modules/mob/living/carbon/metroid/emote.dm
index 2cbc139f5a1..3c95bea1a43 100644
--- a/code/modules/mob/living/carbon/metroid/emote.dm
+++ b/code/modules/mob/living/carbon/metroid/emote.dm
@@ -1,5 +1,6 @@
/mob/living/carbon/slime/emote(var/act, var/m_type=1, var/message = null)
-
+ if(stat)
+ return
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 6ead72a36f5..808f8b3e772 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -317,9 +317,16 @@
C.reagents.addiction_list.Cut()
hud_updateflag |= 1 << HEALTH_HUD
hud_updateflag |= 1 << STATUS_HUD
+
+/mob/living/proc/update_revive() // handles revival through other means than cloning or adminbus (defib, IPC repair)
+ stat = CONSCIOUS
+ dead_mob_list -= src
+ living_mob_list |= src
+ mob_list |= src
+ ear_deaf = 0
+ timeofdeath = 0
/mob/living/proc/rejuvenate()
-
// shut down various types of badness
setToxLoss(0)
setOxyLoss(0)
@@ -367,10 +374,9 @@
human_mob.decaylevel = 0
restore_all_organs()
- if(stat == 2)
+ if(stat == DEAD)
dead_mob_list -= src
living_mob_list += src
- tod = null
timeofdeath = 0
stat = CONSCIOUS
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index cf6204e710c..08a99c0dba2 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -34,8 +34,6 @@
var/atom/movable/cameraFollow = null
- var/tod = null // Time of death
-
var/on_fire = 0 //The "Are we on fire?" var
var/fire_stacks = 0 //Tracks how many stacks of fire we have on, max is usually 20
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index dfa05ddc5d0..fe96da3c35e 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -53,7 +53,7 @@
if (istype(loc, /obj/item/device/aicard))
loc.icon_state = "aicard-404"
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
return ..(gibbed)
diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm
index f7ead12e4cc..8c28d407ede 100644
--- a/code/modules/mob/living/silicon/emote.dm
+++ b/code/modules/mob/living/silicon/emote.dm
@@ -1,4 +1,7 @@
/mob/living/silicon/emote(var/act, var/m_type=1, var/message = null)
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm
index 8fccd74ff39..9cb442e3d37 100644
--- a/code/modules/mob/living/silicon/laws.dm
+++ b/code/modules/mob/living/silicon/laws.dm
@@ -12,7 +12,8 @@
/mob/living/silicon/proc/set_zeroth_law(var/law, var/law_borg)
laws_sanity_check()
laws.set_zeroth_law(law, law_borg)
- log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has given [src] the zeroth laws: [law]/[law_borg ? law_borg : "N/A"]")
/mob/living/silicon/robot/set_zeroth_law(var/law, var/law_borg)
..()
@@ -22,39 +23,43 @@
/mob/living/silicon/proc/add_ion_law(var/law)
laws_sanity_check()
laws.add_ion_law(law)
- log_and_message_admins("has given [src] the ion law: [law]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has given [src] the ion law: [law]")
/mob/living/silicon/proc/add_inherent_law(var/law)
laws_sanity_check()
laws.add_inherent_law(law)
- log_and_message_admins("has given [src] the inherent law: [law]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has given [src] the inherent law: [law]")
/mob/living/silicon/proc/add_supplied_law(var/number, var/law)
laws_sanity_check()
laws.add_supplied_law(number, law)
- log_and_message_admins("has given [src] the supplied law: [law]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has given [src] the supplied law: [law]")
/mob/living/silicon/proc/delete_law(var/datum/ai_law/law)
laws_sanity_check()
laws.delete_law(law)
- log_and_message_admins("has deleted a law belonging to [src]: [law.law]")
+ if(!isnull(usr) && law)
+ log_and_message_admins("has deleted a law belonging to [src]: [law.law]")
/mob/living/silicon/proc/clear_inherent_laws(var/silent = 0)
laws_sanity_check()
laws.clear_inherent_laws()
- if(!silent)
+ if(!silent && !isnull(usr))
log_and_message_admins("cleared the inherent laws of [src]")
/mob/living/silicon/proc/clear_ion_laws(var/silent = 0)
laws_sanity_check()
laws.clear_ion_laws()
- if(!silent)
+ if(!silent && !isnull(usr))
log_and_message_admins("cleared the ion laws of [src]")
/mob/living/silicon/proc/clear_supplied_laws(var/silent = 0)
laws_sanity_check()
laws.clear_supplied_laws()
- if(!silent)
+ if(!silent && !isnull(usr))
log_and_message_admins("cleared the supplied laws of [src]")
/mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws)
diff --git a/code/modules/mob/living/silicon/pai/emote.dm b/code/modules/mob/living/silicon/pai/emote.dm
index a8eeac8cbb7..2fce92f2883 100644
--- a/code/modules/mob/living/silicon/pai/emote.dm
+++ b/code/modules/mob/living/silicon/pai/emote.dm
@@ -1,4 +1,7 @@
/mob/living/silicon/pai/emote(var/act, var/m_type=1, var/message = null)
+ if(stat)
+ return
+
switch(act)
if ("help")
src << "ping, beep, buzz."
diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm
index d0469bc42dc..7eb1e62090c 100644
--- a/code/modules/mob/living/silicon/robot/component.dm
+++ b/code/modules/mob/living/silicon/robot/component.dm
@@ -1,14 +1,15 @@
// TODO: remove the robot.mmi and robot.cell variables and completely rely on the robot component system
-/datum/robot_component/var/name
-/datum/robot_component/var/installed = 0
-/datum/robot_component/var/powered = 0
-/datum/robot_component/var/toggled = 1
-/datum/robot_component/var/brute_damage = 0
-/datum/robot_component/var/electronics_damage = 0
-/datum/robot_component/var/energy_consumption = 0
-/datum/robot_component/var/max_damage = 30
-/datum/robot_component/var/mob/living/silicon/robot/owner
+/datum/robot_component
+ var/name = "Component"
+ var/installed = 0
+ var/powered = 1
+ var/toggled = 1
+ var/brute_damage = 0
+ var/electronics_damage = 0
+ var/energy_consumption = 0
+ var/max_damage = 30
+ var/mob/living/silicon/robot/owner
// The actual device object that has to be installed for this.
/datum/robot_component/var/external_type = null
@@ -206,8 +207,8 @@
user << "Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "fully disabled" : "[M.health - M.halloss]% functional"]"
user << "\t Key: Electronics/Brute"
user << "\t Damage Specifics: [BU] - [BR]"
- if(M.tod && M.stat == DEAD)
- user << "Time of Disable: [M.tod]"
+ if(M.timeofdeath && M.stat == DEAD)
+ user << "Time of Disable: [M.timeofdeath]"
var/mob/living/silicon/robot/H = M
var/list/damaged = H.get_damaged_components(1,1,1)
user << "Localized Damage:"
diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm
index cf9427242d8..cafb53d8621 100644
--- a/code/modules/mob/living/silicon/robot/death.dm
+++ b/code/modules/mob/living/silicon/robot/death.dm
@@ -62,8 +62,8 @@
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
update_icons()
- tod = worldtime2text() //weasellos time of death patch
- if(mind) mind.store_memory("Time of death: [tod]", 0)
+ timeofdeath = worldtime2text()
+ if(mind) mind.store_memory("Time of death: [timeofdeath]", 0)
sql_report_cyborg_death(src)
diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm
index 9c01f9ee5ec..45a086f0fe7 100644
--- a/code/modules/mob/living/silicon/robot/emote.dm
+++ b/code/modules/mob/living/silicon/robot/emote.dm
@@ -1,4 +1,7 @@
/mob/living/silicon/robot/emote(var/act, var/m_type=1, var/message = null)
+ if(stat)
+ return
+
var/param = null
if (findtext(act, "-", 1, null))
var/t1 = findtext(act, "-", 1, null)
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 3a8812a011b..f355b00ff2f 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -1146,7 +1146,7 @@ var/list/robot_verbs_default = list(
S.dirt = 0
for(var/A in tile)
if(istype(A, /obj/effect))
- if(istype(A, /obj/effect/rune) || istype(A, /obj/effect/decal/cleanable) || istype(A, /obj/effect/overlay))
+ if(is_cleanable(A))
qdel(A)
else if(istype(A, /obj/item))
var/obj/item/cleaned_item = A
diff --git a/code/modules/mob/living/silicon/subsystems.dm b/code/modules/mob/living/silicon/subsystems.dm
index 9a1c713ab72..fa3dcfd2cfa 100644
--- a/code/modules/mob/living/silicon/subsystems.dm
+++ b/code/modules/mob/living/silicon/subsystems.dm
@@ -81,7 +81,7 @@
set name = "Law Manager"
set category = "Subsystems"
- law_manager.ui_interact(usr, state = self_state)
+ law_manager.ui_interact(usr, state = conscious_state)
/********************
* Power Monitor *
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 221b8962ca8..a644ec9d7d3 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -639,11 +639,6 @@ var/list/slot_equipment_priority = list( \
flavor_text = msg
-/mob/proc/warn_flavor_changed()
- if(flavor_text && flavor_text != "") // don't spam people that don't use it!
- src << "
OOC Warning:
"
- src << "Your flavor text is likely out of date! Change"
-
/mob/proc/print_flavor_text(var/shrink = 1)
if (flavor_text && flavor_text != "")
var/msg = replacetext(flavor_text, "\n", " ")
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 312f9fb3ff1..4bc62d88f81 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -201,6 +201,7 @@
var/area/lastarea = null
var/digitalcamo = 0 // Can they be tracked by the AI?
+ var/weakeyes //Are they vulnerable to flashes?
var/list/radar_blips = list() // list of screen objects, radar blips
var/radar_open = 0 // nonzero is radar is open
@@ -232,4 +233,6 @@
var/last_movement = -100 // Last world.time the mob actually moved of its own accord.
- var/resize = 1 //Badminnery resize
\ No newline at end of file
+ var/resize = 1 //Badminnery resize
+
+ var/datum/vision_override/vision_type = null //Vision override datum.
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index 3830c9b2705..6f3bea0cef8 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -509,7 +509,7 @@
proc/has_admin_rights()
- return client.holder.rights & R_ADMIN
+ return check_rights(R_ADMIN, 0, src)
proc/is_species_whitelisted(datum/species/S)
if(!S) return 1
diff --git a/code/modules/nano/interaction/conscious.dm b/code/modules/nano/interaction/conscious.dm
new file mode 100644
index 00000000000..143bc24956f
--- /dev/null
+++ b/code/modules/nano/interaction/conscious.dm
@@ -0,0 +1,7 @@
+/*
+ This state only checks if user is conscious.
+*/
+/var/global/datum/topic_state/conscious_state/conscious_state = new()
+
+/datum/topic_state/conscious_state/can_use_topic(var/src_object, var/mob/user)
+ return user.stat == CONSCIOUS ? STATUS_INTERACTIVE : STATUS_CLOSE
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index 1a5808ec7d3..a93d2a278a8 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -21,7 +21,8 @@ var/list/organ_cache = list()
var/list/trace_chemicals = list() // traces of chemicals in the organ,
// links chemical IDs to number of ticks for which they'll stay in the blood
germ_level = 0
-
+ var/datum/dna/dna
+ var/datum/species/species
/obj/item/organ/Destroy()
if(!owner)
@@ -59,6 +60,12 @@ var/list/organ_cache = list()
max_damage = min_broken_damage * 2
if(istype(holder))
src.owner = holder
+ species = all_species["Human"]
+ if(holder.dna)
+ dna = holder.dna.Clone()
+ species = all_species[dna.species]
+ else
+ log_to_dd("[src] at [loc] spawned without a proper DNA.")
var/mob/living/carbon/human/H = holder
if(istype(H))
if(internal)
@@ -67,13 +74,19 @@ var/list/organ_cache = list()
if(E.internal_organs == null)
E.internal_organs = list()
E.internal_organs |= src
- if(H.dna)
+ if(dna)
if(!blood_DNA)
blood_DNA = list()
- blood_DNA[H.dna.unique_enzymes] = H.dna.b_type
+ blood_DNA[dna.unique_enzymes] = dna.b_type
if(internal)
holder.internal_organs |= src
+/obj/item/organ/proc/set_dna(var/datum/dna/new_dna)
+ if(new_dna)
+ dna = new_dna.Clone()
+ blood_DNA.Cut()
+ blood_DNA[dna.unique_enzymes] = dna.b_type
+
/obj/item/organ/proc/die()
if(status & ORGAN_ROBOT)
return
diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm
index 26ca1f5079a..e3e95e78df3 100644
--- a/code/modules/organs/organ_icon.dm
+++ b/code/modules/organs/organ_icon.dm
@@ -12,13 +12,25 @@ var/global/list/limb_icon_cache = list()
/obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human)
s_tone = null
s_col = null
- if(status & ORGAN_ROBOT)
+ if(status & ORGAN_ROBOT && !(species && species.name == "Machine")) //machine people get skin color
+ return
+ if(species && human.species && species.name != human.species.name)
return
if(!isnull(human.s_tone) && (human.species.bodyflags & HAS_SKIN_TONE))
s_tone = human.s_tone
if(human.species.bodyflags & HAS_SKIN_COLOR)
s_col = list(human.r_skin, human.g_skin, human.b_skin)
+/obj/item/organ/external/proc/sync_colour_to_dna()
+ s_tone = null
+ s_col = null
+ if(status & ORGAN_ROBOT)
+ return
+ if(!isnull(dna.GetUIValue(DNA_UI_SKIN_TONE)) && (species.flags & HAS_SKIN_TONE))
+ s_tone = dna.GetUIValue(DNA_UI_SKIN_TONE)
+ if(species.flags & HAS_SKIN_COLOR)
+ s_col = list(dna.GetUIValue(DNA_UI_SKIN_R), dna.GetUIValue(DNA_UI_SKIN_G), dna.GetUIValue(DNA_UI_SKIN_B))
+
/obj/item/organ/external/head/sync_colour_to_human(var/mob/living/carbon/human/human)
..()
var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"]
@@ -34,11 +46,11 @@ var/global/list/limb_icon_cache = list()
overlays.Cut()
if(!owner)
return
-
- if(owner.species.has_organ["eyes"])
+
+ if(species.has_organ["eyes"])
var/obj/item/organ/eyes/eyes = owner.internal_organs_by_name["eyes"]
- if(owner.species.eyes)
- var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', owner.species.eyes)
+ if(species.eyes)
+ var/icon/eyes_icon = new/icon('icons/mob/human_face.dmi', species.eyes)
if(eyes)
eyes_icon.Blend(rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3]), ICON_ADD)
else
@@ -46,14 +58,14 @@ var/global/list/limb_icon_cache = list()
mob_icon.Blend(eyes_icon, ICON_OVERLAY)
overlays |= eyes_icon
- if(owner.lip_style && (owner.species && (owner.species.flags & HAS_LIPS)))
+ if(owner.lip_style && (species && (species.flags & HAS_LIPS)))
var/icon/lip_icon = new/icon('icons/mob/human_face.dmi', "lips_[owner.lip_style]_s")
overlays |= lip_icon
mob_icon.Blend(lip_icon, ICON_OVERLAY)
if(owner.f_style)
var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[owner.f_style]
- if(facial_hair_style && facial_hair_style.species_allowed && (owner.species.name in facial_hair_style.species_allowed))
+ if(facial_hair_style && facial_hair_style.species_allowed && (species.name in facial_hair_style.species_allowed))
var/icon/facial_s = new/icon("icon" = facial_hair_style.icon, "icon_state" = "[facial_hair_style.icon_state]_s")
if(facial_hair_style.do_colouration)
facial_s.Blend(rgb(owner.r_facial, owner.g_facial, owner.b_facial), ICON_ADD)
@@ -61,7 +73,7 @@ var/global/list/limb_icon_cache = list()
if(owner.h_style && !(owner.head && (owner.head.flags & BLOCKHEADHAIR)))
var/datum/sprite_accessory/hair_style = hair_styles_list[owner.h_style]
- if(hair_style && (owner.species.name in hair_style.species_allowed))
+ if(hair_style && (species.name in hair_style.species_allowed))
var/icon/hair_s = new/icon("icon" = hair_style.icon, "icon_state" = "[hair_style.icon_state]_s")
if(hair_style.do_colouration)
hair_s.Blend(rgb(owner.r_hair, owner.g_hair, owner.b_hair), ICON_ADD)
@@ -74,26 +86,29 @@ var/global/list/limb_icon_cache = list()
var/gender
if(force_icon)
mob_icon = new /icon(force_icon, "[icon_name]")
+ if(species && species.name == "Machine") //snowflake for IPC's, sorry.
+ if(s_col && s_col.len >= 3)
+ mob_icon.Blend(rgb(s_col[1], s_col[2], s_col[3]), ICON_ADD)
else
- if(!owner)
+ if(!dna)
mob_icon = new /icon('icons/mob/human_races/r_human.dmi', "[icon_name][gendered_icon ? "_f" : ""]")
else
if(gendered_icon)
- if(owner.gender == FEMALE)
+ if(dna.GetUIState(DNA_UI_GENDER))
gender = "f"
else
gender = "m"
if(skeletal)
mob_icon = new /icon('icons/mob/human_races/r_skeleton.dmi', "[icon_name][gender ? "_[gender]" : ""]")
- else if (status & ORGAN_ROBOT)
+ else if(status & ORGAN_ROBOT)
mob_icon = new /icon('icons/mob/human_races/robotic.dmi', "[icon_name][gender ? "_[gender]" : ""]")
else
if (status & ORGAN_MUTATED)
- mob_icon = new /icon(owner.species.deform, "[icon_name][gender ? "_[gender]" : ""]")
+ mob_icon = new /icon(species.deform, "[icon_name][gender ? "_[gender]" : ""]")
else
- mob_icon = new /icon(owner.species.icobase, "[icon_name][gender ? "_[gender]" : ""]")
+ mob_icon = new /icon(species.icobase, "[icon_name][gender ? "_[gender]" : ""]")
if(status & ORGAN_DEAD)
mob_icon.ColorTone(rgb(10,50,0))
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 9e27818eb8b..c4170888d3d 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -60,6 +60,9 @@
consume(user)
return 1
+/obj/singularity/Process_Spacemove() //The singularity stops drifting for no man!
+ return 0
+
/obj/singularity/blob_act(severity)
return
@@ -268,8 +271,6 @@
step(src, movement_dir)
-/obj/singularity/Process_Spacemove() //The singularity stops drifting for no man!
- return 0
/obj/singularity/proc/check_turfs_in(var/direction = 0, var/step = 0)
if(!direction)
@@ -360,18 +361,13 @@
/obj/singularity/proc/toxmob()
var/toxrange = 10
- var/toxdamage = 4
var/radiation = 15
var/radiationmin = 3
- if (src.energy>200)
- toxdamage = round(((src.energy-150)/50)*4,1)
- radiation = round(((src.energy-150)/50)*5,1)
- radiationmin = round((radiation/5),1)//
+ if (energy>200)
+ radiation += round((energy-150)/10,1)
+ radiationmin = round((radiation/5),1)
for(var/mob/living/M in view(toxrange, src.loc))
M.apply_effect(rand(radiationmin,radiation), IRRADIATE)
- toxdamage = (toxdamage - (toxdamage*M.getarmor(null, "rad")))
- M.apply_effect(toxdamage, TOX)
- return
/obj/singularity/proc/combust_mobs()
@@ -382,6 +378,7 @@
C.IgniteMob()
return
+
/obj/singularity/proc/mezzer()
for(var/mob/living/carbon/M in oviewers(8, src))
if(istype(M, /mob/living/carbon/brain)) //Ignore brains
diff --git a/code/modules/procedural mapping/mapGenerator.dm b/code/modules/procedural_mapping/mapGenerator.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGenerator.dm
rename to code/modules/procedural_mapping/mapGenerator.dm
diff --git a/code/modules/procedural mapping/mapGeneratorModule.dm b/code/modules/procedural_mapping/mapGeneratorModule.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGeneratorModule.dm
rename to code/modules/procedural_mapping/mapGeneratorModule.dm
diff --git a/code/modules/procedural mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGeneratorModules/helpers.dm
rename to code/modules/procedural_mapping/mapGeneratorModules/helpers.dm
diff --git a/code/modules/procedural mapping/mapGeneratorModules/nature.dm b/code/modules/procedural_mapping/mapGeneratorModules/nature.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGeneratorModules/nature.dm
rename to code/modules/procedural_mapping/mapGeneratorModules/nature.dm
diff --git a/code/modules/procedural mapping/mapGeneratorReadme.dm b/code/modules/procedural_mapping/mapGeneratorReadme.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGeneratorReadme.dm
rename to code/modules/procedural_mapping/mapGeneratorReadme.dm
diff --git a/code/modules/procedural mapping/mapGenerators/asteroid.dm b/code/modules/procedural_mapping/mapGenerators/asteroid.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGenerators/asteroid.dm
rename to code/modules/procedural_mapping/mapGenerators/asteroid.dm
diff --git a/code/modules/procedural mapping/mapGenerators/nature.dm b/code/modules/procedural_mapping/mapGenerators/nature.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGenerators/nature.dm
rename to code/modules/procedural_mapping/mapGenerators/nature.dm
diff --git a/code/modules/procedural mapping/mapGenerators/syndicate.dm b/code/modules/procedural_mapping/mapGenerators/syndicate.dm
similarity index 100%
rename from code/modules/procedural mapping/mapGenerators/syndicate.dm
rename to code/modules/procedural_mapping/mapGenerators/syndicate.dm
diff --git a/code/modules/projectiles/guns/energy/temperature.dm b/code/modules/projectiles/guns/energy/temperature.dm
index 1f6f374aef0..8d33a9e2508 100644
--- a/code/modules/projectiles/guns/energy/temperature.dm
+++ b/code/modules/projectiles/guns/energy/temperature.dm
@@ -29,7 +29,7 @@
/obj/item/weapon/gun/energy/temperature/Destroy()
processing_objects.Remove(src)
- ..()
+ return ..()
/obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob)
diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm
index 46bb04ee636..e0127fe9862 100644
--- a/code/modules/reagents/Chemistry-Machinery.dm
+++ b/code/modules/reagents/Chemistry-Machinery.dm
@@ -218,15 +218,17 @@
if(istype(B, /obj/item/weapon/reagent_containers/glass) || istype(B, /obj/item/weapon/reagent_containers/food/drinks))
src.beaker = B
- user.drop_item()
- B.loc = src
- user << "You set [B] on the machine."
- nanomanager.update_uis(src) // update all UIs attached to src
- if(!icon_beaker)
- icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position.
- icon_beaker.pixel_x = rand(-10,5)
- overlays += icon_beaker
- return
+ if(user.drop_item())
+ B.forceMove(src)
+ user << "You set [B] on the machine."
+ nanomanager.update_uis(src) // update all UIs attached to src
+ if(!icon_beaker)
+ icon_beaker = image('icons/obj/chemical.dmi', src, "disp_beaker") //randomize beaker overlay position.
+ icon_beaker.pixel_x = rand(-10,5)
+ overlays += icon_beaker
+ return
+ else
+ user << "\The [B] is stuck to you!"
/obj/machinery/chem_dispenser/attackby(var/obj/item/weapon/B as obj, var/mob/user as mob, params)
..()
@@ -591,6 +593,8 @@
if(!condi)
var/count = 1
if (href_list["createpatch_multiple"]) count = isgoodnumber(input("Select the number of patches to make.", 10, patchamount) as num)
+ if(!count || count <= 0)
+ return
if (count > 20) count = 20 //Pevent people from creating huge stacks of patches easily. Maybe move the number to defines?
var/amount_per_patch = reagents.total_volume/count
if (amount_per_patch > 40) amount_per_patch = 40
diff --git a/code/modules/reagents/newchem/medicine.dm b/code/modules/reagents/newchem/medicine.dm
index a54072e9bbb..e79667be06e 100644
--- a/code/modules/reagents/newchem/medicine.dm
+++ b/code/modules/reagents/newchem/medicine.dm
@@ -633,6 +633,7 @@ datum/reagent/strange_reagent/reaction_mob(var/mob/living/M as mob, var/method=T
if(method == TOUCH)
if(M.stat == DEAD)
M.health = M.maxHealth
+ M.update_revive()
M.visible_message("[M] seems to rise from the dead!")
if(istype(M, /mob/living/carbon))
if(method == INGEST)
@@ -648,13 +649,12 @@ datum/reagent/strange_reagent/reaction_mob(var/mob/living/M as mob, var/method=T
M.visible_message("[M] doesn't appear to respond, perhaps try again later?")
if(!M.suiciding && !ghost && !(NOCLONE in M.mutations))
M.visible_message("[M] seems to rise from the dead!")
- M.stat = 1
M.setOxyLoss(0)
M.adjustBruteLoss(rand(0,15))
M.adjustToxLoss(rand(0,15))
M.adjustFireLoss(rand(0,15))
- dead_mob_list -= M
- living_mob_list |= list(M)
+ M.update_revive()
+ M.stat = UNCONSCIOUS
add_logs(M, M, "revived", object="strange reagent")
..()
return
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index aeda3fcbec3..7f9c3ee3c98 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -63,7 +63,7 @@
/obj/item/weapon/reagent_containers/proc/reagentlist(var/obj/item/weapon/reagent_containers/snack) //Attack logs for regents in pills
var/data
- if(snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries
+ if(snack && snack.reagents && snack.reagents.reagent_list && snack.reagents.reagent_list.len) //find a reagent list if there is and check if it has entries
for (var/datum/reagent/R in snack.reagents.reagent_list) //no reagents will be left behind
data += "[R.id]([R.volume] units); " //Using IDs because SOME chemicals(I'm looking at you, chlorhydrate-beer) have the same names as other chemicals.
return data
diff --git a/code/modules/research/designs/janitorial_designs.dm b/code/modules/research/designs/janitorial_designs.dm
index 76a469d04e6..8c575425ebe 100644
--- a/code/modules/research/designs/janitorial_designs.dm
+++ b/code/modules/research/designs/janitorial_designs.dm
@@ -11,6 +11,26 @@
build_path = /obj/item/weapon/mop/advanced
category = list("Janitorial")
+/datum/design/blutrash
+ name = "Trashbag of Holding"
+ desc = "An advanced trashabg with bluespace properties; capable of holding a plethora of garbage."
+ id = "blutrash"
+ req_tech = list("materials" = 5, "bluespace" = 3)
+ build_type = PROTOLATHE
+ materials = list(MAT_GOLD = 1500, MAT_URANIUM = 250, MAT_PLASMA = 1500)
+ build_path = /obj/item/weapon/storage/bag/trash/bluespace
+ category = list("Janitorial")
+
+/datum/design/buffer
+ name = "Floor Buffer Upgrade"
+ desc = "A floor buffer that can be attached to vehicular janicarts."
+ id = "buffer"
+ req_tech = list("materials" = 5, "engineering" = 3)
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 3000, MAT_GLASS = 200)
+ build_path = /obj/item/janiupgrade
+ category = list("Janitorial")
+
/datum/design/holosign
name = "Holographic Sign Projector"
desc = "A holograpic projector used to project various warning signs."
diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm
index 577397b70fc..9072217e4f7 100644
--- a/code/modules/research/rdconsole.dm
+++ b/code/modules/research/rdconsole.dm
@@ -184,7 +184,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(..())
return 1
- if(!allowed(usr))
+ if(!allowed(usr) && !isobserver(usr))
return 1
add_fingerprint(usr)
@@ -324,7 +324,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
use_power(250)
updateUsrDialog()
- else if(href_list["lock"]) //Lock the console from use by anyone without tox access.
+ else if(href_list["lock"]) //Lock the console from use by anyone without access.
if(src.allowed(usr))
screen = text2num(href_list["lock"])
else
@@ -606,7 +606,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
/obj/machinery/computer/rdconsole/attack_hand(mob/user as mob)
if(..())
return 1
- if(!allowed(user))
+ if(!allowed(user) && !isobserver(user))
user << "Access denied."
return 1
interact(user)
@@ -1115,26 +1115,26 @@ won't update every console in existence) but it's more of a hassle to do. Also,
dat += "
"
return dat
+
+/obj/machinery/computer/rdconsole/core
+ name = "Core R&D Console"
+ desc = "A console used to interface with R&D tools."
+ id = 1
/obj/machinery/computer/rdconsole/robotics
name = "Robotics R&D Console"
desc = "A console used to interface with R&D tools."
id = 2
req_access = list(access_robotics)
+
+/obj/machinery/computer/rdconsole/experiment
+ name = "E.X.P.E.R.I-MENTOR R&D Console"
+ desc = "A console used to interface with R&D tools."
+ id = 3
/obj/machinery/computer/rdconsole/mechanics
name = "Mechanics R&D Console"
desc = "A console used to interface with R&D tools."
id = 4
req_access = list(access_mechanic)
-
-/obj/machinery/computer/rdconsole/core
- name = "Core R&D Console"
- desc = "A console used to interface with R&D tools."
- id = 1
-
-/obj/machinery/computer/rdconsole/experiment
- name = "E.X.P.E.R.I-MENTOR R&D Console"
- desc = "A console used to interface with R&D tools."
- id = 3
\ No newline at end of file
diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm
index 67cf7cd9217..a520fe6ec92 100644
--- a/code/modules/research/server.dm
+++ b/code/modules/research/server.dm
@@ -335,16 +335,15 @@
emagged = 1
user << "\blue You you disable the security protocols"
src.updateUsrDialog()
-
-/obj/machinery/r_n_d/server/robotics
- name = "Robotics R&D Server"
- id_with_upload_string = "1;2"
- id_with_download_string = "1;2"
- server_id = 2
-
-
+
/obj/machinery/r_n_d/server/core
name = "Core R&D Server"
- id_with_upload_string = "1"
- id_with_download_string = "1"
+ id_with_upload_string = "1;3"
+ id_with_download_string = "1;3"
server_id = 1
+
+/obj/machinery/r_n_d/server/robotics
+ name = "Robotics and Mechanic R&D Server"
+ id_with_upload_string = "1;2;4"
+ id_with_download_string = "1;2;4"
+ server_id = 2
diff --git a/code/modules/security levels/keycard authentication.dm b/code/modules/security_levels/keycard authentication.dm
similarity index 96%
rename from code/modules/security levels/keycard authentication.dm
rename to code/modules/security_levels/keycard authentication.dm
index 7a9fd05da3e..0fbff9cd68a 100644
--- a/code/modules/security levels/keycard authentication.dm
+++ b/code/modules/security_levels/keycard authentication.dm
@@ -1,186 +1,186 @@
-/obj/machinery/keycard_auth
- name = "Keycard Authentication Device"
- desc = "This device is used to trigger station functions, which require more than one ID card to authenticate."
- icon = 'icons/obj/monitors.dmi'
- icon_state = "auth_off"
- var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made.
- var/event = ""
- var/screen = 1
- var/list/ert_chosen = list()
- var/confirmed = 0 //This variable is set by the device that confirms the request.
- var/confirm_delay = 20 //(2 seconds)
- var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device.
- var/obj/machinery/keycard_auth/event_source
- var/mob/event_triggered_by
- var/mob/event_confirmed_by
- var/ert_reason = "Reason for ERT"
- //1 = select event
- //2 = authenticate
- anchored = 1.0
- use_power = 1
- idle_power_usage = 2
- active_power_usage = 6
- power_channel = ENVIRON
-
-/obj/machinery/keycard_auth/attack_ai(mob/user as mob)
- user << "The station AI is not to interact with these devices."
- return
-
-/obj/machinery/keycard_auth/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
- if(stat & (NOPOWER|BROKEN))
- user << "This device is not powered."
- return
- if(istype(W,/obj/item/weapon/card/id))
- var/obj/item/weapon/card/id/ID = W
- if(access_keycard_auth in ID.access)
- if(active == 1)
- //This is not the device that made the initial request. It is the device confirming the request.
- if(event_source)
- event_source.confirmed = 1
- event_source.event_confirmed_by = usr
- else if(screen == 2)
- if(event == "Emergency Response Team" && ert_reason == "Reason for ERT")
- user << "Supply a reason for calling the ERT first!"
- return
- event_triggered_by = usr
- broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices
-
-/obj/machinery/keycard_auth/power_change()
- if(powered(ENVIRON))
- stat &= ~NOPOWER
- icon_state = "auth_off"
- else
- stat |= NOPOWER
-
-/obj/machinery/keycard_auth/attack_hand(mob/user as mob)
- if(!user.IsAdvancedToolUser())
- return 0
- ui_interact(user)
-
-/obj/machinery/keycard_auth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
- if(user.stat || stat & (NOPOWER|BROKEN))
- user << "This device is not powered."
- return
- if(busy)
- user << "This device is busy."
- return
-
- user.set_machine(src)
-
- var/data[0]
- data["screen"] = screen
- data["event"] = event
- data["ertreason"] = ert_reason
-
- ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
- if (!ui)
- ui = new(user, src, ui_key, "keycard_auth.tmpl", "Keycard Authentication Device UI", 520, 320)
- ui.set_initial_data(data)
- ui.open()
-
-/obj/machinery/keycard_auth/Topic(href, href_list)
- if(..())
- return
- if(busy)
- usr << "This device is busy."
- return
- if(usr.stat || stat & (BROKEN|NOPOWER))
- usr << "This device is without power."
- return
- if(href_list["triggerevent"])
- event = href_list["triggerevent"]
- screen = 2
- if(href_list["reset"])
- reset()
- if(href_list["ert"])
- ert_reason = input(usr, "Reason for ERT Call:", "", "")
-
- nanomanager.update_uis(src)
- add_fingerprint(usr)
- return
-
-/obj/machinery/keycard_auth/proc/reset()
- active = 0
- event = ""
- screen = 1
- confirmed = 0
- event_source = null
- icon_state = "auth_off"
- event_triggered_by = null
- event_confirmed_by = null
-
-/obj/machinery/keycard_auth/proc/broadcast_request()
- icon_state = "auth_on"
- for(var/obj/machinery/keycard_auth/KA in world)
- if(KA == src) continue
- KA.reset()
- spawn()
- KA.receive_request(src)
-
- sleep(confirm_delay)
- if(confirmed)
- confirmed = 0
- trigger_event(event)
- log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]")
- message_admins("[key_name_admin(event_triggered_by)] triggered and [key_name_admin(event_confirmed_by)] confirmed event [event]", 1)
- reset()
-
-/obj/machinery/keycard_auth/proc/receive_request(var/obj/machinery/keycard_auth/source)
- if(stat & (BROKEN|NOPOWER))
- return
- event_source = source
- busy = 1
- active = 1
- icon_state = "auth_on"
-
- sleep(confirm_delay)
-
- event_source = null
- icon_state = "auth_off"
- active = 0
- busy = 0
-
-/obj/machinery/keycard_auth/proc/trigger_event()
- switch(event)
- if("Red Alert")
- set_security_level(SEC_LEVEL_RED)
- feedback_inc("alert_keycard_auth_red",1)
- if("Grant Emergency Maintenance Access")
- make_maint_all_access()
- feedback_inc("alert_keycard_auth_maintGrant",1)
- if("Revoke Emergency Maintenance Access")
- revoke_maint_all_access()
- feedback_inc("alert_keycard_auth_maintRevoke",1)
- if("Emergency Response Team")
- if(is_ert_blocked())
- usr << "\red All Emergency Response Teams are dispatched and can not be called at this time."
- return
-
- usr << "ERT request transmitted."
- if(admins.len)
- ERT_Announce(ert_reason , event_triggered_by)
- ert_reason = "Reason for ERT"
- feedback_inc("alert_keycard_auth_ert",1)
- else
- trigger_armed_response_team(new /datum/response_team/amber) // No admins? No problem. Automatically send a code amber ERT.
-
-/obj/machinery/keycard_auth/proc/is_ert_blocked()
- return ticker.mode && ticker.mode.ert_disabled
-
-var/global/maint_all_access = 0
-
-/proc/make_maint_all_access()
- for(var/area/maintenance/A in world)
- for(var/obj/machinery/door/airlock/D in A)
- D.emergency = 1
- D.update_icon(0)
- minor_announcement.Announce("The maintenance access requirement has been revoked on all airlocks.")
- maint_all_access = 1
-
-/proc/revoke_maint_all_access()
- for(var/area/maintenance/A in world)
- for(var/obj/machinery/door/airlock/D in A)
- D.emergency = 0
- D.update_icon(0)
- minor_announcement.Announce("The maintenance access requirement has been readded on all maintenance airlocks.")
+/obj/machinery/keycard_auth
+ name = "Keycard Authentication Device"
+ desc = "This device is used to trigger station functions, which require more than one ID card to authenticate."
+ icon = 'icons/obj/monitors.dmi'
+ icon_state = "auth_off"
+ var/active = 0 //This gets set to 1 on all devices except the one where the initial request was made.
+ var/event = ""
+ var/screen = 1
+ var/list/ert_chosen = list()
+ var/confirmed = 0 //This variable is set by the device that confirms the request.
+ var/confirm_delay = 20 //(2 seconds)
+ var/busy = 0 //Busy when waiting for authentication or an event request has been sent from this device.
+ var/obj/machinery/keycard_auth/event_source
+ var/mob/event_triggered_by
+ var/mob/event_confirmed_by
+ var/ert_reason = "Reason for ERT"
+ //1 = select event
+ //2 = authenticate
+ anchored = 1.0
+ use_power = 1
+ idle_power_usage = 2
+ active_power_usage = 6
+ power_channel = ENVIRON
+
+/obj/machinery/keycard_auth/attack_ai(mob/user as mob)
+ user << "The station AI is not to interact with these devices."
+ return
+
+/obj/machinery/keycard_auth/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
+ if(stat & (NOPOWER|BROKEN))
+ user << "This device is not powered."
+ return
+ if(istype(W,/obj/item/weapon/card/id))
+ var/obj/item/weapon/card/id/ID = W
+ if(access_keycard_auth in ID.access)
+ if(active == 1)
+ //This is not the device that made the initial request. It is the device confirming the request.
+ if(event_source)
+ event_source.confirmed = 1
+ event_source.event_confirmed_by = usr
+ else if(screen == 2)
+ if(event == "Emergency Response Team" && ert_reason == "Reason for ERT")
+ user << "Supply a reason for calling the ERT first!"
+ return
+ event_triggered_by = usr
+ broadcast_request() //This is the device making the initial event request. It needs to broadcast to other devices
+
+/obj/machinery/keycard_auth/power_change()
+ if(powered(ENVIRON))
+ stat &= ~NOPOWER
+ icon_state = "auth_off"
+ else
+ stat |= NOPOWER
+
+/obj/machinery/keycard_auth/attack_hand(mob/user as mob)
+ if(!user.IsAdvancedToolUser())
+ return 0
+ ui_interact(user)
+
+/obj/machinery/keycard_auth/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
+ if(user.stat || stat & (NOPOWER|BROKEN))
+ user << "This device is not powered."
+ return
+ if(busy)
+ user << "This device is busy."
+ return
+
+ user.set_machine(src)
+
+ var/data[0]
+ data["screen"] = screen
+ data["event"] = event
+ data["ertreason"] = ert_reason
+
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ ui = new(user, src, ui_key, "keycard_auth.tmpl", "Keycard Authentication Device UI", 520, 320)
+ ui.set_initial_data(data)
+ ui.open()
+
+/obj/machinery/keycard_auth/Topic(href, href_list)
+ if(..())
+ return
+ if(busy)
+ usr << "This device is busy."
+ return
+ if(usr.stat || stat & (BROKEN|NOPOWER))
+ usr << "This device is without power."
+ return
+ if(href_list["triggerevent"])
+ event = href_list["triggerevent"]
+ screen = 2
+ if(href_list["reset"])
+ reset()
+ if(href_list["ert"])
+ ert_reason = input(usr, "Reason for ERT Call:", "", "")
+
+ nanomanager.update_uis(src)
+ add_fingerprint(usr)
+ return
+
+/obj/machinery/keycard_auth/proc/reset()
+ active = 0
+ event = ""
+ screen = 1
+ confirmed = 0
+ event_source = null
+ icon_state = "auth_off"
+ event_triggered_by = null
+ event_confirmed_by = null
+
+/obj/machinery/keycard_auth/proc/broadcast_request()
+ icon_state = "auth_on"
+ for(var/obj/machinery/keycard_auth/KA in world)
+ if(KA == src) continue
+ KA.reset()
+ spawn()
+ KA.receive_request(src)
+
+ sleep(confirm_delay)
+ if(confirmed)
+ confirmed = 0
+ trigger_event(event)
+ log_game("[key_name(event_triggered_by)] triggered and [key_name(event_confirmed_by)] confirmed event [event]")
+ message_admins("[key_name_admin(event_triggered_by)] triggered and [key_name_admin(event_confirmed_by)] confirmed event [event]", 1)
+ reset()
+
+/obj/machinery/keycard_auth/proc/receive_request(var/obj/machinery/keycard_auth/source)
+ if(stat & (BROKEN|NOPOWER))
+ return
+ event_source = source
+ busy = 1
+ active = 1
+ icon_state = "auth_on"
+
+ sleep(confirm_delay)
+
+ event_source = null
+ icon_state = "auth_off"
+ active = 0
+ busy = 0
+
+/obj/machinery/keycard_auth/proc/trigger_event()
+ switch(event)
+ if("Red Alert")
+ set_security_level(SEC_LEVEL_RED)
+ feedback_inc("alert_keycard_auth_red",1)
+ if("Grant Emergency Maintenance Access")
+ make_maint_all_access()
+ feedback_inc("alert_keycard_auth_maintGrant",1)
+ if("Revoke Emergency Maintenance Access")
+ revoke_maint_all_access()
+ feedback_inc("alert_keycard_auth_maintRevoke",1)
+ if("Emergency Response Team")
+ if(is_ert_blocked())
+ usr << "\red All Emergency Response Teams are dispatched and can not be called at this time."
+ return
+
+ usr << "ERT request transmitted."
+ if(admins.len)
+ ERT_Announce(ert_reason , event_triggered_by)
+ ert_reason = "Reason for ERT"
+ feedback_inc("alert_keycard_auth_ert",1)
+ else
+ trigger_armed_response_team(new /datum/response_team/amber) // No admins? No problem. Automatically send a code amber ERT.
+
+/obj/machinery/keycard_auth/proc/is_ert_blocked()
+ return ticker.mode && ticker.mode.ert_disabled
+
+var/global/maint_all_access = 0
+
+/proc/make_maint_all_access()
+ for(var/area/maintenance/A in world)
+ for(var/obj/machinery/door/airlock/D in A)
+ D.emergency = 1
+ D.update_icon(0)
+ minor_announcement.Announce("The maintenance access requirement has been revoked on all airlocks.")
+ maint_all_access = 1
+
+/proc/revoke_maint_all_access()
+ for(var/area/maintenance/A in world)
+ for(var/obj/machinery/door/airlock/D in A)
+ D.emergency = 0
+ D.update_icon(0)
+ minor_announcement.Announce("The maintenance access requirement has been readded on all maintenance airlocks.")
maint_all_access = 0
\ No newline at end of file
diff --git a/code/modules/security levels/security levels.dm b/code/modules/security_levels/security levels.dm
similarity index 97%
rename from code/modules/security levels/security levels.dm
rename to code/modules/security_levels/security levels.dm
index 5ac35d1188e..051d7b502cf 100644
--- a/code/modules/security levels/security levels.dm
+++ b/code/modules/security_levels/security levels.dm
@@ -1,184 +1,184 @@
-/var/security_level = 0
-//0 = code green
-//1 = code blue
-//2 = code red
-//3 = gamma
-//4 = epsilon
-//5 = code delta
-
-//config.alert_desc_blue_downto
-/var/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg'))
-/var/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1)
-
-/proc/set_security_level(var/level)
- switch(level)
- if("green")
- level = SEC_LEVEL_GREEN
- if("blue")
- level = SEC_LEVEL_BLUE
- if("red")
- level = SEC_LEVEL_RED
- if("gamma")
- level = SEC_LEVEL_GAMMA
- if("epsilon")
- level = SEC_LEVEL_EPSILON
- if("delta")
- level = SEC_LEVEL_DELTA
-
- //Will not be announced if you try to set to the same level as it already is
- if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level)
- switch(level)
- if(SEC_LEVEL_GREEN)
- security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.")
- security_level = SEC_LEVEL_GREEN
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_green")
-
- if(SEC_LEVEL_BLUE)
- if(security_level < SEC_LEVEL_BLUE)
- security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.")
- else
- security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.")
- security_level = SEC_LEVEL_BLUE
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue")
-
- if(SEC_LEVEL_RED)
- if(security_level < SEC_LEVEL_RED)
- security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
- else
- security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
- security_level = SEC_LEVEL_RED
-
- var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world
- if(R && (R.z in config.station_levels))
- R.locked = 0
- R.update_icon()
-
- var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
- if(CC)
- CC.post_status("alert", "redalert")
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_red")
-
- if(SEC_LEVEL_GAMMA)
- security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!")
- security_level = SEC_LEVEL_GAMMA
-
- move_gamma_ship()
-
- if(security_level < SEC_LEVEL_RED)
- for(var/obj/machinery/door/airlock/highsecurity/red/R in world)
- if((R.z in config.station_levels))
- R.locked = 0
- R.update_icon()
-
- for(var/obj/machinery/door/airlock/hatch/gamma/H in world)
- if((H.z in config.station_levels))
- H.locked = 0
- H.update_icon()
-
- var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
- if(CC)
- CC.post_status("alert", "redalert")
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_gamma")
- FA.update_icon()
-
- if(SEC_LEVEL_EPSILON)
- security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!")
- security_level = SEC_LEVEL_EPSILON
-
- var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
- if(CC)
- CC.post_status("alert", "redalert")
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon")
-
- if(SEC_LEVEL_DELTA)
- security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!")
- security_level = SEC_LEVEL_DELTA
-
- var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
- if(CC)
- CC.post_status("alert", "redalert")
-
- for(var/obj/machinery/firealarm/FA in world)
- if((FA.z in config.contact_levels))
- FA.overlays = list()
- FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta")
-
- else
- return
-
-/proc/get_security_level()
- switch(security_level)
- if(SEC_LEVEL_GREEN)
- return "green"
- if(SEC_LEVEL_BLUE)
- return "blue"
- if(SEC_LEVEL_RED)
- return "red"
- if(SEC_LEVEL_GAMMA)
- return "gamma"
- if(SEC_LEVEL_EPSILON)
- return "epsilon"
- if(SEC_LEVEL_DELTA)
- return "delta"
-
-/proc/num2seclevel(var/num)
- switch(num)
- if(SEC_LEVEL_GREEN)
- return "green"
- if(SEC_LEVEL_BLUE)
- return "blue"
- if(SEC_LEVEL_RED)
- return "red"
- if(SEC_LEVEL_GAMMA)
- return "gamma"
- if(SEC_LEVEL_EPSILON)
- return "epsilon"
- if(SEC_LEVEL_DELTA)
- return "delta"
-
-/proc/seclevel2num(var/seclevel)
- switch( lowertext(seclevel) )
- if("green")
- return SEC_LEVEL_GREEN
- if("blue")
- return SEC_LEVEL_BLUE
- if("red")
- return SEC_LEVEL_RED
- if("gamma")
- return SEC_LEVEL_GAMMA
- if("epsilon")
- return SEC_LEVEL_EPSILON
- if("delta")
- return SEC_LEVEL_DELTA
-
-
-/*DEBUG
-/mob/verb/set_thing0()
- set_security_level(0)
-/mob/verb/set_thing1()
- set_security_level(1)
-/mob/verb/set_thing2()
- set_security_level(2)
-/mob/verb/set_thing3()
- set_security_level(3)
+/var/security_level = 0
+//0 = code green
+//1 = code blue
+//2 = code red
+//3 = gamma
+//4 = epsilon
+//5 = code delta
+
+//config.alert_desc_blue_downto
+/var/datum/announcement/priority/security/security_announcement_up = new(do_log = 0, do_newscast = 1, new_sound = sound('sound/misc/notice1.ogg'))
+/var/datum/announcement/priority/security/security_announcement_down = new(do_log = 0, do_newscast = 1)
+
+/proc/set_security_level(var/level)
+ switch(level)
+ if("green")
+ level = SEC_LEVEL_GREEN
+ if("blue")
+ level = SEC_LEVEL_BLUE
+ if("red")
+ level = SEC_LEVEL_RED
+ if("gamma")
+ level = SEC_LEVEL_GAMMA
+ if("epsilon")
+ level = SEC_LEVEL_EPSILON
+ if("delta")
+ level = SEC_LEVEL_DELTA
+
+ //Will not be announced if you try to set to the same level as it already is
+ if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != security_level)
+ switch(level)
+ if(SEC_LEVEL_GREEN)
+ security_announcement_down.Announce("All threats to the station have passed. All weapons need to be holstered and privacy laws are once again fully enforced.","Attention! Security level lowered to green.")
+ security_level = SEC_LEVEL_GREEN
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_green")
+
+ if(SEC_LEVEL_BLUE)
+ if(security_level < SEC_LEVEL_BLUE)
+ security_announcement_up.Announce("The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible and random searches are permitted.","Attention! Security level elevated to blue.")
+ else
+ security_announcement_down.Announce("The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed.","Attention! Security level lowered to blue.")
+ security_level = SEC_LEVEL_BLUE
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue")
+
+ if(SEC_LEVEL_RED)
+ if(security_level < SEC_LEVEL_RED)
+ security_announcement_up.Announce("There is an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
+ else
+ security_announcement_down.Announce("The station's self-destruct mechanism has been deactivated, but there is still an immediate and serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised.","Attention! Code Red!")
+ security_level = SEC_LEVEL_RED
+
+ var/obj/machinery/door/airlock/highsecurity/red/R = locate(/obj/machinery/door/airlock/highsecurity/red) in world
+ if(R && (R.z in config.station_levels))
+ R.locked = 0
+ R.update_icon()
+
+ var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
+ if(CC)
+ CC.post_status("alert", "redalert")
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_red")
+
+ if(SEC_LEVEL_GAMMA)
+ security_announcement_up.Announce("Central Command has ordered the Gamma security level on the station. Security is to have weapons equipped at all times, and all civilians are to immediately seek their nearest head for transportation to a secure location. The station's Gamma armory has been unlocked and is ready for use.","Attention! Gamma security level activated!")
+ security_level = SEC_LEVEL_GAMMA
+
+ move_gamma_ship()
+
+ if(security_level < SEC_LEVEL_RED)
+ for(var/obj/machinery/door/airlock/highsecurity/red/R in world)
+ if((R.z in config.station_levels))
+ R.locked = 0
+ R.update_icon()
+
+ for(var/obj/machinery/door/airlock/hatch/gamma/H in world)
+ if((H.z in config.station_levels))
+ H.locked = 0
+ H.update_icon()
+
+ var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
+ if(CC)
+ CC.post_status("alert", "redalert")
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_gamma")
+ FA.update_icon()
+
+ if(SEC_LEVEL_EPSILON)
+ security_announcement_up.Announce("Central Command has ordered the Epsilon security level on the station. Consider all contracts terminated.","Attention! Epsilon security level activated!")
+ security_level = SEC_LEVEL_EPSILON
+
+ var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
+ if(CC)
+ CC.post_status("alert", "redalert")
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_epsilon")
+
+ if(SEC_LEVEL_DELTA)
+ security_announcement_up.Announce("The station's self-destruct mechanism has been engaged. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill.","Attention! Delta security level reached!")
+ security_level = SEC_LEVEL_DELTA
+
+ var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
+ if(CC)
+ CC.post_status("alert", "redalert")
+
+ for(var/obj/machinery/firealarm/FA in world)
+ if((FA.z in config.contact_levels))
+ FA.overlays = list()
+ FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta")
+
+ else
+ return
+
+/proc/get_security_level()
+ switch(security_level)
+ if(SEC_LEVEL_GREEN)
+ return "green"
+ if(SEC_LEVEL_BLUE)
+ return "blue"
+ if(SEC_LEVEL_RED)
+ return "red"
+ if(SEC_LEVEL_GAMMA)
+ return "gamma"
+ if(SEC_LEVEL_EPSILON)
+ return "epsilon"
+ if(SEC_LEVEL_DELTA)
+ return "delta"
+
+/proc/num2seclevel(var/num)
+ switch(num)
+ if(SEC_LEVEL_GREEN)
+ return "green"
+ if(SEC_LEVEL_BLUE)
+ return "blue"
+ if(SEC_LEVEL_RED)
+ return "red"
+ if(SEC_LEVEL_GAMMA)
+ return "gamma"
+ if(SEC_LEVEL_EPSILON)
+ return "epsilon"
+ if(SEC_LEVEL_DELTA)
+ return "delta"
+
+/proc/seclevel2num(var/seclevel)
+ switch( lowertext(seclevel) )
+ if("green")
+ return SEC_LEVEL_GREEN
+ if("blue")
+ return SEC_LEVEL_BLUE
+ if("red")
+ return SEC_LEVEL_RED
+ if("gamma")
+ return SEC_LEVEL_GAMMA
+ if("epsilon")
+ return SEC_LEVEL_EPSILON
+ if("delta")
+ return SEC_LEVEL_DELTA
+
+
+/*DEBUG
+/mob/verb/set_thing0()
+ set_security_level(0)
+/mob/verb/set_thing1()
+ set_security_level(1)
+/mob/verb/set_thing2()
+ set_security_level(2)
+/mob/verb/set_thing3()
+ set_security_level(3)
*/
\ No newline at end of file
diff --git a/code/modules/space_transition/space_transition.dm b/code/modules/space_transition/space_transition.dm
new file mode 100644
index 00000000000..81be4604193
--- /dev/null
+++ b/code/modules/space_transition/space_transition.dm
@@ -0,0 +1,187 @@
+//This is realisation of the working torus-looping randomized-per-round space map, this kills the cube
+
+#define Z_LEVEL_NORTH "1"
+#define Z_LEVEL_SOUTH "2"
+#define Z_LEVEL_EAST "4"
+#define Z_LEVEL_WEST "8"
+
+
+var/list/z_levels_list = list()
+
+/datum/space_level
+ var/name = "Your config settings failed, you need to fix this for the datum space levels to work"
+ var/list/neigbours
+ var/z_value = 1 //actual z placement
+ var/linked = 1
+ var/xi
+ var/yi //imaginary placements on the grid
+
+/datum/space_level/New()
+ neigbours = list()
+ var/list/L = list(Z_LEVEL_NORTH,Z_LEVEL_SOUTH,Z_LEVEL_EAST,Z_LEVEL_WEST)
+ for(var/A in L)
+ neigbours[A] = src
+
+/datum/space_level/proc/set_neigbours(list/L)
+ for(var/datum/point/P in L)
+ if(P.x == xi)
+ if(P.y == yi+1)
+ neigbours[Z_LEVEL_NORTH] = P.spl
+ P.spl.neigbours[Z_LEVEL_SOUTH] = src
+ else if(P.y == yi-1)
+ neigbours[Z_LEVEL_SOUTH] = P.spl
+ P.spl.neigbours[Z_LEVEL_NORTH] = src
+ else if(P.y == yi)
+ if(P.x == xi+1)
+ neigbours[Z_LEVEL_EAST] = P.spl
+ P.spl.neigbours[Z_LEVEL_WEST] = src
+ else if(P.x == xi-1)
+ neigbours[Z_LEVEL_WEST] = P.spl
+ P.spl.neigbours[Z_LEVEL_EAST] = src
+
+/datum/point //this is explicitly utilitarian datum type made specially for the space map generation and are absolutely unusable for anything else
+ var/list/neigbours = list()
+ var/x
+ var/y
+ var/datum/space_level/spl
+
+/datum/point/New(nx, ny, list/point_grid)
+ if(!point_grid)
+ qdel(src)
+ return
+ var/list/L = point_grid[1]
+ if(nx > point_grid.len || ny > L.len)
+ qdel(src)
+ return
+ x = nx
+ y = ny
+ if(point_grid[x][y])
+ return
+ point_grid[x][y] = src
+
+/datum/point/proc/set_neigbours(list/grid)
+ var/max_X = grid.len
+ var/list/max_Y = grid[1]
+ max_Y = max_Y.len
+ neigbours.Cut()
+ if(x+1 <= max_X)
+ neigbours |= grid[x+1][y]
+ if(x-1 >= 1)
+ neigbours |= grid[x-1][y]
+ if(y+1 <= max_Y)
+ neigbours |= grid[x][y+1]
+ if(y-1 >= 1)
+ neigbours |= grid[x][y-1]
+
+
+//config/space_levels.txt is where you define your zlevel datum names, their connection to actual z levels and if you want them connected to one another or not
+//Grammar: Name;z value;linked/unlinked
+//Name is the name of the datum, just for the sake of it
+//z value is to what actual map z level this datum is pointing
+//linked/unlinked decide if you want the z level in the general map or not, for example centcomm is not reachable
+//Each entry must be separated with a single empty line, no spaces outside the name
+//No comments in the file allowed
+
+/proc/setup_map_transitions() //listamania
+ var/list/SLS = file2list("config/space_levels.txt", "\n\n")
+ var/datum/space_level/D
+ var/list/config_settings[SLS.len][]
+ for(var/A in SLS)
+ config_settings[SLS.Find(A)] = text2list(A, ";")
+ var/conf_set_len = SLS.len
+ SLS.Cut()
+ for(var/A in config_settings)
+ D = new()
+ D.name = A[1]
+ D.z_value = text2num(A[2])
+ if(A[3] != "linked")
+ D.linked = 0
+ z_levels_list["[D.z_value]"] = D
+ else
+ SLS.Add(D)
+ var/list/point_grid[conf_set_len*2+1][conf_set_len*2+1]
+ var/list/grid = list()
+ var/datum/point/P
+ for(var/i = 1, i<=conf_set_len*2+1, i++)
+ for(var/j = 1, j<=conf_set_len*2+1, j++)
+ P = new/datum/point(i,j, point_grid)
+ point_grid[i][j] = P
+ grid.Add(P)
+ for(var/datum/point/pnt in grid)
+ pnt.set_neigbours(point_grid)
+ P = point_grid[conf_set_len][conf_set_len]
+ var/list/possible_points = list()
+ var/list/used_points = list()
+ grid.Cut()
+ while(SLS.len)
+ D = pick(SLS)
+ SLS.Remove(D)
+ D.xi = P.x
+ D.yi = P.y
+ P.spl = D
+ possible_points |= P.neigbours
+ used_points |= P
+ possible_points.Remove(used_points)
+ D.set_neigbours(used_points)
+ P = pick(possible_points)
+ grid["[D.z_value]"] = D
+
+ for(var/A in z_levels_list)
+ grid[A] = z_levels_list[A]
+
+ for(var/turf/space/S in world) //Define the transistions of the z levels
+ if(S.x <= TRANSITIONEDGE)
+ D = grid["[S.z]"]
+ if(D.neigbours[Z_LEVEL_WEST] != D)
+ D = D.neigbours[Z_LEVEL_WEST]
+ S.destination_z = D.z_value
+ else
+ while(D.neigbours[Z_LEVEL_EAST] != D)
+ D = D.neigbours[Z_LEVEL_EAST]
+ S.destination_z = D.z_value
+ S.destination_x = world.maxx - TRANSITIONEDGE - 2
+ S.destination_y = S.y
+
+ if(S.x >= (world.maxx - TRANSITIONEDGE - 1))
+ D = grid["[S.z]"]
+ if(D.neigbours[Z_LEVEL_EAST] != D)
+ D = D.neigbours[Z_LEVEL_EAST]
+ S.destination_z = D.z_value
+ else
+ while(D.neigbours[Z_LEVEL_WEST] != D)
+ D = D.neigbours[Z_LEVEL_WEST]
+ S.destination_z = D.z_value
+ S.destination_x = TRANSITIONEDGE + 2
+ S.destination_y = S.y
+
+ if(S.y <= TRANSITIONEDGE)
+ D = grid["[S.z]"]
+ if(D.neigbours[Z_LEVEL_SOUTH] != D)
+ D = D.neigbours[Z_LEVEL_SOUTH]
+ S.destination_z = D.z_value
+ else
+ while(D.neigbours[Z_LEVEL_NORTH] != D)
+ D = D.neigbours[Z_LEVEL_NORTH]
+ S.destination_z = D.z_value
+ S.destination_x = S.x
+ S.destination_y = world.maxy - TRANSITIONEDGE - 2
+
+ if(S.y >= (world.maxy - TRANSITIONEDGE - 1))
+ D = grid["[S.z]"]
+ if(D.neigbours[Z_LEVEL_NORTH] != D)
+ D = D.neigbours[Z_LEVEL_NORTH]
+ S.destination_z = D.z_value
+ else
+ while(D.neigbours[Z_LEVEL_SOUTH] != D)
+ D = D.neigbours[Z_LEVEL_SOUTH]
+ S.destination_z = D.z_value
+ S.destination_x = S.x
+ S.destination_y = TRANSITIONEDGE + 2
+
+ for(var/A in grid)
+ z_levels_list[A] = grid[A]
+
+#undef Z_LEVEL_NORTH
+#undef Z_LEVEL_SOUTH
+#undef Z_LEVEL_EAST
+#undef Z_LEVEL_WEST
diff --git a/code/modules/vehicle/train/trains/janicart.dm b/code/modules/vehicle/train/trains/janicart.dm
deleted file mode 100644
index a1fae332782..00000000000
--- a/code/modules/vehicle/train/trains/janicart.dm
+++ /dev/null
@@ -1,342 +0,0 @@
-/obj/vehicle/train/janitor/engine
- name = "janitor train tug"
- desc = "A ridable electric car designed for pulling janitor trolleys."
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "pussywagon" //mulebot icons until I get some proper icons
- on = 0
- powered = 1
- locked = 0
- layer = MOB_LAYER + 0.1
- load_item_visible = 1
- load_offset_x = 0
- load_offset_y = 7
-
- var/car_limit = 3 //how many cars an engine can pull before performance degrades
- active_engines = 1
- var/obj/item/weapon/key/janitor_train/key
- flags = OPENCONTAINER
- var/amount_per_transfer_from_this = 5 //shit I dunno, adding this so syringes stop runtime erroring. --NeoFite
- var/obj/item/weapon/storage/bag/trash/mybag = null
-
-/obj/item/weapon/key/janitor_train
- name = "key"
- desc = "A keyring with a small steel key, and a yellow fob reading \"Choo Choo!\"."
- icon = 'icons/obj/vehicles.dmi'
- icon_state = "keys"
- w_class = 1
-
-/obj/vehicle/train/janitor/trolley
- name = "janitor train trolley"
- icon = 'icons/obj/janitor.dmi'
- icon_state = "trashcart"
- anchored = 0
- passenger_allowed = 0
- locked = 0
- load_item_visible = 1
- load_offset_x = 1
- load_offset_y = 7
-
- var/openTop = 0
- var/organs = 0
-//-------------------------------------------
-// Standard procs
-//-------------------------------------------
-/obj/vehicle/train/janitor/engine/New()
- ..()
- cell = new /obj/item/weapon/stock_parts/cell/high
- verbs -= /atom/movable/verb/pull
- key = new()
- var/datum/reagents/R = new/datum/reagents(100)
- reagents = R
- R.my_atom = src
-
-/obj/vehicle/train/janitor/engine/Move()
- . = ..()
- handle_rotation()
- update_mob()
-
-/obj/vehicle/train/janitor/trolley/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
- if(openTop)
- W.loc = src
- user.visible_message("[user] puts [W] in [src].","You put [W] in [src].")
- if(istype(W,/obj/item/weapon/organ))
- organs = 1
- update_icon()
- else
- user << "The top is closed!"
-
-/obj/vehicle/train/janitor/trolley/attack_hand(mob/user)
- openTop = !openTop
- user.visible_message("[user] [openTop ? "opens" : "closes"] the top of [src].","You [openTop ? "open" : "close"] the the top of [src].")
- update_icon()
- ..()
-
-/obj/vehicle/train/janitor/trolley/update_icon()
- if(openTop)
- if(organs)
- icon_state = "trashcartopengib"
- else
- icon_state = "trashcartopen"
- else
- if(organs)
- icon_state = "trashcartgib"
- else
- icon_state = "trashcart"
-
-/obj/vehicle/train/janitor/engine/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
- if(istype(W, /obj/item/weapon/key/janitor_train))
- if(!key)
- user.drop_item()
- key = W
- W.loc = src
- verbs += /obj/vehicle/train/janitor/engine/verb/remove_key
- return
- else if(istype(W, /obj/item/weapon/mop))
- if(reagents.total_volume >= 2)
- reagents.trans_to(W, 2)
- user << "You wet the mop in the pimpin' ride."
- playsound(src.loc, 'sound/effects/slosh.ogg', 25, 1)
- if(reagents.total_volume < 1)
- user << "This pimpin' ride is out of water!"
- return
- else if(istype(W, /obj/item/weapon/storage/bag/trash))
- user << "You hook the trashbag onto the pimpin' ride."
- user.drop_item()
- W.loc = src
- mybag = W
- return
- ..()
-
-/obj/vehicle/train/janitor/engine/attack_hand(mob/user)
- if(mybag)
- mybag.loc = get_turf(user)
- user.put_in_hands(mybag)
- mybag = null
- else
- ..()
-
-/obj/vehicle/train/janitor/update_icon()
- if(open)
- //icon_state = "mulebot-hatch"
- icon_state = initial(icon_state)
- else
- icon_state = initial(icon_state)
-
-/obj/vehicle/train/janitor/engine/Emag(mob/user as mob)
- ..()
- flick("mulebot-emagged", src)
-
-/obj/vehicle/train/janitor/trolley/insert_cell(var/obj/item/weapon/stock_parts/cell/C, var/mob/living/carbon/human/H)
- return
-
-/obj/vehicle/train/janitor/engine/insert_cell(var/obj/item/weapon/stock_parts/cell/C, var/mob/living/carbon/human/H)
- ..()
- update_stats()
-
-/obj/vehicle/train/janitor/engine/remove_cell(var/mob/living/carbon/human/H)
- ..()
- update_stats()
-
-/obj/vehicle/train/janitor/engine/Bump(atom/Obstacle)
- var/obj/machinery/door/D = Obstacle
- var/mob/living/carbon/human/H = load
- if(istype(D) && istype(H))
- D.Bumped(H) //a little hacky, but hey, it works, and repects access rights
-
- ..()
-
-/obj/vehicle/train/janitor/trolley/Bump(atom/Obstacle)
- if(!lead)
- return //so people can't knock others over by pushing a trolley around
- ..()
-
-/obj/vehicle/train/janitor/engine/handle_rotation()
- if(dir == SOUTH)
- layer = FLY_LAYER
- else
- layer = OBJ_LAYER
-
-/obj/vehicle/train/janitor/engine/proc/update_mob()
- if(load)
- load.dir = dir
- switch(dir)
- if(SOUTH)
- load.pixel_x = 0
- load.pixel_y = 7
- if(WEST)
- load.pixel_x = 13
- load.pixel_y = 7
- if(NORTH)
- load.pixel_x = 0
- load.pixel_y = 4
- if(EAST)
- load.pixel_x = -13
- load.pixel_y = 7
-
-
-//-------------------------------------------
-// Train procs
-//-------------------------------------------
-/obj/vehicle/train/janitor/engine/turn_on()
- if(!key)
- return
- else
- ..()
- update_stats()
-
-/obj/vehicle/train/janitor/RunOver(var/mob/living/carbon/human/H)
- var/list/parts = list("head", "chest", "l_leg", "r_leg", "l_arm", "r_arm")
-
- H.apply_effects(5, 5)
- for(var/i = 0, i < rand(1,3), i++)
- H.apply_damage(rand(1,5), BRUTE, pick(parts))
-
-/obj/vehicle/train/janitor/trolley/RunOver(var/mob/living/carbon/human/H)
- ..()
- attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])")
-
-/obj/vehicle/train/janitor/engine/RunOver(var/mob/living/carbon/human/H)
- ..()
-
- if(is_train_head() && istype(load, /mob/living/carbon/human))
- var/mob/living/carbon/human/D = load
- D << "\red \b You ran over [H]!"
- visible_message("\red \The [src] ran over [H]!")
- attack_log += text("\[[time_stamp()]\] ran over [key_name(H)], driven by [key_name(D)]")
- msg_admin_attack("[key_name_admin(D)] ran over [key_name_admin(H)]")
- else
- attack_log += text("\[[time_stamp()]\] ran over [key_name(H)]")
-
-
-//-------------------------------------------
-// Interaction procs
-//-------------------------------------------
-/obj/vehicle/train/janitor/engine/relaymove(mob/user, direction)
- if(user != load)
- return 0
-
- if(is_train_head())
- if(direction == reverse_direction(dir))
- return 0
- if(Move(get_step(src, direction)))
- return 1
- return 0
- else
- return ..()
-
-
-/obj/vehicle/train/janitor/engine/examine(mob/user)
- if(!..(user, 1))
- return
-
- user << "\icon[src] This [name] contains [reagents.total_volume] unit\s of [reagents]!"
- if(mybag)
- user << "\A [mybag] is hanging on the [name]."
-
- user << "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition."
-
-/obj/vehicle/train/janitor/engine/verb/check_power()
- set name = "Check power level"
- set category = "Object"
- set src in view(1)
-
- if(!istype(usr, /mob/living/carbon/human))
- return
-
- if(!cell)
- usr << "There is no power cell installed in [src]."
- return
-
- usr << "The power meter reads [round(cell.percent(), 0.01)]%"
-
-/obj/vehicle/train/janitor/engine/verb/start_engine()
- set name = "Start engine"
- set category = "Object"
- set src in view(1)
-
- if(!istype(usr, /mob/living/carbon/human))
- return
-
- if(on)
- usr << "The engine is already running."
- return
-
- turn_on()
- if (on)
- usr << "You start [src]'s engine."
- else
- if(cell.charge < charge_use)
- usr << "[src] is out of power."
- else
- usr << "[src]'s engine won't start."
-
-/obj/vehicle/train/janitor/engine/verb/stop_engine()
- set name = "Stop engine"
- set category = "Object"
- set src in view(1)
-
- if(!istype(usr, /mob/living/carbon/human))
- return
-
- if(!on)
- usr << "The engine is already stopped."
- return
-
- turn_off()
- if (!on)
- usr << "You stop [src]'s engine."
-
-/obj/vehicle/train/janitor/engine/verb/remove_key()
- set name = "Remove key"
- set category = "Object"
- set src in view(1)
-
- if(!istype(usr, /mob/living/carbon/human))
- return
-
- if(!key || (load && load != usr))
- return
-
- if(on)
- turn_off()
-
- key.loc = usr.loc
- if(!usr.get_active_hand())
- usr.put_in_hands(key)
- key = null
-
- verbs -= /obj/vehicle/train/janitor/engine/verb/remove_key
-
-//-------------------------------------------
-// Loading/unloading procs
-//-------------------------------------------
-/obj/vehicle/train/janitor/trolley/load(var/atom/movable/C)
- return 0
-
-/obj/vehicle/train/janitor/engine/load(var/atom/movable/C)
- if(!ismob(C))
- return 0
-
- return ..()
-
-
-//-------------------------------------------------------
-// Stat update procs
-//
-// Update the trains stats for speed calculations.
-// The longer the train, the slower it will go. car_limit
-// sets the max number of cars one engine can pull at
-// full speed. Adding more cars beyond this will slow the
-// train proportionate to the length of the train. Adding
-// more engines increases this limit by car_limit per
-// engine.
-//-------------------------------------------------------
-
-/obj/vehicle/train/janitor/engine/proc/update_move_delay()
- if(!is_train_head() || !on)
- move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind
- else
- move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains
- move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines)
- move_delay += config.run_speed //base reference speed
- move_delay *= 1.05
diff --git a/code/stylesheet.dm b/code/stylesheet.dm
index ffd829c70b4..c0e951046fa 100644
--- a/code/stylesheet.dm
+++ b/code/stylesheet.dm
@@ -11,6 +11,8 @@ em {font-style: normal; font-weight: bold;}
.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover
{color: #638500;}
+.italics { font-style: italic;}
+
.prefix { font-weight: bold;}
.ooc { font-weight: bold;}
diff --git a/config/example/config.txt b/config/example/config.txt
index 33dd8659aae..076a0e80766 100644
--- a/config/example/config.txt
+++ b/config/example/config.txt
@@ -184,10 +184,10 @@ GUEST_BAN
## spawns a spellbook which gives object-type spells instead of verb-type spells for the wizard
# FEATURE_OBJECT_SPELL_SYSTEM
-##Toggle for having jobs load up from the .txt
+## Toggle for having jobs load up from the .txt
LOAD_JOBS_FROM_TXT
-##Remove the # mark infront of this to forbid admins from posssessing the singularity.
+## Remove the # mark infront of this to forbid admins from posssessing the singularity.
#FORBID_SINGULO_POSSESSION
## Remove the # to show a popup 'reply to' window to every non-admin that recieves an adminPM.
diff --git a/config/example/space_levels.txt b/config/example/space_levels.txt
new file mode 100644
index 00000000000..e724264daac
--- /dev/null
+++ b/config/example/space_levels.txt
@@ -0,0 +1,15 @@
+Main Station;1;linked
+
+Central Command;2;unlinked
+
+Telecommunications Satellite;3;linked
+
+Engineering Outpost;4;linked
+
+Mining Asteroid;5;linked
+
+Derelicted Station;6;linked
+
+Empty Area;7;linked
+
+Syndicate Station;8;unlinked
\ No newline at end of file
diff --git a/icons/mob/belt.dmi b/icons/mob/belt.dmi
index 75f2ccef866..24e7f335be8 100644
Binary files a/icons/mob/belt.dmi and b/icons/mob/belt.dmi differ
diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi
index 79d773f7627..a55b4a75ae2 100644
Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 826c5ea1f4f..dd6cf13fc1e 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi
index 38b93652f0e..119f3df0e37 100644
Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ
diff --git a/icons/obj/money.dmi b/icons/obj/money.dmi
index c052cb8ea93..7b8a5e09495 100644
Binary files a/icons/obj/money.dmi and b/icons/obj/money.dmi differ
diff --git a/icons/obj/pipe-item.dmi b/icons/obj/pipe-item.dmi
index 1ef48fbad13..34fedaa560f 100644
Binary files a/icons/obj/pipe-item.dmi and b/icons/obj/pipe-item.dmi differ
diff --git a/icons/obj/trash.dmi b/icons/obj/trash.dmi
index 1d0d126006b..600ecc9f8a5 100644
Binary files a/icons/obj/trash.dmi and b/icons/obj/trash.dmi differ
diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi
index 9d92dd02a81..63515f5b2e5 100644
Binary files a/icons/obj/vehicles.dmi and b/icons/obj/vehicles.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 76969b151fa..510d4864fbe 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -121,6 +121,7 @@
#include "code\ATMOSPHERICS\components\unary_devices\heat_source.dm"
#include "code\ATMOSPHERICS\components\unary_devices\outlet_injector.dm"
#include "code\ATMOSPHERICS\components\unary_devices\oxygen_generator.dm"
+#include "code\ATMOSPHERICS\components\unary_devices\passive_vent.dm"
#include "code\ATMOSPHERICS\components\unary_devices\portables_connector.dm"
#include "code\ATMOSPHERICS\components\unary_devices\tank.dm"
#include "code\ATMOSPHERICS\components\unary_devices\thermal_plate.dm"
@@ -186,6 +187,7 @@
#include "code\datums\spell.dm"
#include "code\datums\supplypacks.dm"
#include "code\datums\uplink_item.dm"
+#include "code\datums\vision_override.dm"
#include "code\datums\cache\air_alarm.dm"
#include "code\datums\cache\apc.dm"
#include "code\datums\cache\cache.dm"
@@ -813,7 +815,6 @@
#include "code\game\objects\structures\musician.dm"
#include "code\game\objects\structures\noticeboard.dm"
#include "code\game\objects\structures\safe.dm"
-#include "code\game\objects\structures\segway.dm"
#include "code\game\objects\structures\signs.dm"
#include "code\game\objects\structures\spirit_board.dm"
#include "code\game\objects\structures\tables_racks.dm"
@@ -907,6 +908,7 @@
#include "code\modules\admin\player_panel.dm"
#include "code\modules\admin\secrets.dm"
#include "code\modules\admin\sql_notes.dm"
+#include "code\modules\admin\stickyban.dm"
#include "code\modules\admin\topic.dm"
#include "code\modules\admin\ToRban.dm"
#include "code\modules\admin\watchlist.dm"
@@ -998,6 +1000,7 @@
#include "code\modules\client\client defines.dm"
#include "code\modules\client\client procs.dm"
#include "code\modules\client\global_cache.dm"
+#include "code\modules\client\message.dm"
#include "code\modules\client\preferences.dm"
#include "code\modules\client\preferences_mysql.dm"
#include "code\modules\client\preferences_spawnpoints.dm"
@@ -1091,10 +1094,10 @@
#include "code\modules\crafting\table.dm"
#include "code\modules\customitems\item_defines.dm"
#include "code\modules\customitems\item_spawning.dm"
-#include "code\modules\DetectiveWork\detective_work.dm"
-#include "code\modules\DetectiveWork\evidence.dm"
-#include "code\modules\DetectiveWork\footprints_and_rag.dm"
-#include "code\modules\DetectiveWork\scanner.dm"
+#include "code\modules\detective_work\detective_work.dm"
+#include "code\modules\detective_work\evidence.dm"
+#include "code\modules\detective_work\footprints_and_rag.dm"
+#include "code\modules\detective_work\scanner.dm"
#include "code\modules\economy\Accounts.dm"
#include "code\modules\economy\Accounts_DB.dm"
#include "code\modules\economy\ATM.dm"
@@ -1180,8 +1183,8 @@
#include "code\modules\food\recipes_microwave.dm"
#include "code\modules\food\recipes_oven.dm"
#include "code\modules\food\recipes_table.dm"
-#include "code\modules\garbage collection\garbage_collector.dm"
-#include "code\modules\garbage collection\gc_testing.dm"
+#include "code\modules\garbage_collection\garbage_collector.dm"
+#include "code\modules\garbage_collection\gc_testing.dm"
#include "code\modules\holiday\christmas.dm"
#include "code\modules\holiday\holiday.dm"
#include "code\modules\hydroponics\grown.dm"
@@ -1497,6 +1500,7 @@
#include "code\modules\nano\nanoui.dm"
#include "code\modules\nano\interaction\admin.dm"
#include "code\modules\nano\interaction\base.dm"
+#include "code\modules\nano\interaction\conscious.dm"
#include "code\modules\nano\interaction\contained.dm"
#include "code\modules\nano\interaction\default.dm"
#include "code\modules\nano\interaction\inventory.dm"
@@ -1585,14 +1589,14 @@
#include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm"
#include "code\modules\power\singularity\particle_accelerator\particle_power.dm"
#include "code\modules\power\supermatter\supermatter.dm"
-#include "code\modules\procedural mapping\mapGenerator.dm"
-#include "code\modules\procedural mapping\mapGeneratorModule.dm"
-#include "code\modules\procedural mapping\mapGeneratorReadme.dm"
-#include "code\modules\procedural mapping\mapGeneratorModules\helpers.dm"
-#include "code\modules\procedural mapping\mapGeneratorModules\nature.dm"
-#include "code\modules\procedural mapping\mapGenerators\asteroid.dm"
-#include "code\modules\procedural mapping\mapGenerators\nature.dm"
-#include "code\modules\procedural mapping\mapGenerators\syndicate.dm"
+#include "code\modules\procedural_mapping\mapGenerator.dm"
+#include "code\modules\procedural_mapping\mapGeneratorModule.dm"
+#include "code\modules\procedural_mapping\mapGeneratorReadme.dm"
+#include "code\modules\procedural_mapping\mapGeneratorModules\helpers.dm"
+#include "code\modules\procedural_mapping\mapGeneratorModules\nature.dm"
+#include "code\modules\procedural_mapping\mapGenerators\asteroid.dm"
+#include "code\modules\procedural_mapping\mapGenerators\nature.dm"
+#include "code\modules\procedural_mapping\mapGenerators\syndicate.dm"
#include "code\modules\projectiles\ammunition.dm"
#include "code\modules\projectiles\gun.dm"
#include "code\modules\projectiles\projectile.dm"
@@ -1804,8 +1808,8 @@
#include "code\modules\scripting\Parser\Parser.dm"
#include "code\modules\scripting\Scanner\Scanner.dm"
#include "code\modules\scripting\Scanner\Tokens.dm"
-#include "code\modules\security levels\keycard authentication.dm"
-#include "code\modules\security levels\security levels.dm"
+#include "code\modules\security_levels\keycard authentication.dm"
+#include "code\modules\security_levels\security levels.dm"
#include "code\modules\shieldgen\circuits_and_designs.dm"
#include "code\modules\shieldgen\energy_field.dm"
#include "code\modules\shieldgen\shield_capacitor.dm"
@@ -1822,6 +1826,7 @@
#include "code\modules\shuttles\shuttle_supply.dm"
#include "code\modules\shuttles\shuttles_multi.dm"
#include "code\modules\shuttles\whiteship.dm"
+#include "code\modules\space_transition\space_transition.dm"
#include "code\modules\store\items.dm"
#include "code\modules\store\store.dm"
#include "code\modules\surgery\bones.dm"
@@ -1848,7 +1853,6 @@
#include "code\modules\vehicle\vehicle.dm"
#include "code\modules\vehicle\train\train.dm"
#include "code\modules\vehicle\train\trains\ambulance.dm"
-#include "code\modules\vehicle\train\trains\janicart.dm"
#include "code\modules\vehicle\train\trains\cargo\cargo_train.dm"
#include "code\modules\vehicle\train\trains\cargo\cargo_subtypes\fourwheeler.dm"
#include "code\modules\vehicle\train\trains\cargo\cargo_subtypes\motorcycle.dm"