"
@@ -624,6 +626,9 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
if(job.admin_only)
continue
+ if(job.hidden_from_job_prefs)
+ continue
+
index += 1
if((index >= limit) || (job.title in splitJobs))
if((index < limit) && (lastJob != null))
@@ -2001,6 +2006,11 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
windowflashing = !windowflashing
if("afk_watch")
+ if(!afk_watch)
+ to_chat(user, "You will now get put into cryo dorms after [config.auto_cryo_afk] minutes. \
+ Then after [config.auto_despawn_afk] minutes you will be fully despawned. You will receive a visual and auditory warning before you will be put into cryodorms.")
+ else
+ to_chat(user, "Automatic cryoing turned off.")
afk_watch = !afk_watch
if("UIcolor")
@@ -2071,6 +2081,11 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
load_preferences(user)
load_character(user)
+ if("clear")
+ if(!saved || real_name != input("This will clear the current slot permanently. Please enter the character's full name to confirm."))
+ return FALSE
+ clear_character_slot(user)
+
if("open_load_dialog")
if(!IsGuestKey(user.key))
open_load_dialog(user)
diff --git a/code/modules/client/preference/preferences_mysql.dm b/code/modules/client/preference/preferences_mysql.dm
index 94f724b77a6..e889ec5a181 100644
--- a/code/modules/client/preference/preferences_mysql.dm
+++ b/code/modules/client/preference/preferences_mysql.dm
@@ -96,7 +96,7 @@
UI_style_alpha='[UI_style_alpha]',
be_role='[sanitizeSQL(list2params(be_special))]',
default_slot='[default_slot]',
- toggles='[num2text(toggles, Ceiling(log(10, (TOGGLES_TOTAL))))]',
+ toggles='[num2text(toggles, CEILING(log(10, (TOGGLES_TOTAL)), 1))]',
atklog='[atklog]',
sound='[sound]',
randomslot='[randomslot]',
@@ -121,6 +121,7 @@
return 1
/datum/preferences/proc/load_character(client/C,slot)
+ saved = FALSE
if(!slot) slot = default_slot
slot = sanitize_integer(slot, 1, max_save_slots, initial(default_slot))
@@ -262,6 +263,8 @@
loadout_gear = params2list(query.item[51])
autohiss_mode = text2num(query.item[52])
+ saved = TRUE
+
//Sanitize
var/datum/species/SP = GLOB.all_species[species]
metadata = sanitize_text(metadata, initial(metadata))
@@ -474,6 +477,8 @@
log_game("SQL ERROR during character slot saving. Error : \[[err]\]\n")
message_admins("SQL ERROR during character slot saving. Error : \[[err]\]\n")
return
+
+ saved = TRUE
return 1
/datum/preferences/proc/load_random_character_slot(client/C)
@@ -495,3 +500,20 @@
load_character(C,pick(saves))
return 1
+/datum/preferences/proc/clear_character_slot(client/C)
+ . = FALSE
+ // Is there a character in that slot?
+ var/DBQuery/query = GLOB.dbcon.NewQuery("SELECT slot FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' AND slot='[default_slot]'")
+ query.Execute()
+ if(!query.RowCount())
+ return
+
+ var/DBQuery/query2 = GLOB.dbcon.NewQuery("DELETE FROM [format_table_name("characters")] WHERE ckey='[C.ckey]' AND slot='[default_slot]'")
+ if(!query2.Execute())
+ var/err = query2.ErrorMsg()
+ log_game("SQL ERROR during character slot clearing. Error : \[[err]\]\n")
+ message_admins("SQL ERROR during character slot clearing. Error : \[[err]\]\n")
+ return
+
+ saved = FALSE
+ return TRUE
diff --git a/code/modules/client/preference/preferences_toggles.dm b/code/modules/client/preference/preferences_toggles.dm
index 5534e18e253..0f4317e3ce2 100644
--- a/code/modules/client/preference/preferences_toggles.dm
+++ b/code/modules/client/preference/preferences_toggles.dm
@@ -30,7 +30,8 @@
set name = "Show/Hide RadioChatter"
set category = "Preferences"
set desc = "Toggle seeing radiochatter from radios and speakers"
- if(!holder) return
+ if(!check_rights(R_ADMIN))
+ return
prefs.toggles ^= CHAT_RADIO
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from radios or speakers")
@@ -49,7 +50,8 @@
set name = "Hear/Silence Admin Bwoinks"
set category = "Preferences"
set desc = "Toggle hearing a notification when admin PMs are recieved"
- if(!holder) return
+ if(!check_rights(R_ADMIN))
+ return
prefs.sound ^= SOUND_ADMINHELP
prefs.save_preferences(src)
to_chat(usr, "You will [(prefs.sound & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.")
@@ -59,7 +61,7 @@
set name = "Hear/Silence Mentorhelp Bwoinks"
set category = "Preferences"
set desc = "Toggle hearing a notification when mentorhelps are recieved"
- if(!holder)
+ if(!check_rights(R_ADMIN|R_MENTOR))
return
prefs.sound ^= SOUND_MENTORHELP
prefs.save_preferences(src)
@@ -296,7 +298,7 @@
to_chat(src, "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTPDA) ? "see all PDA messages" : "no longer see PDA messages"].")
prefs.save_preferences(src)
feedback_add_details("admin_verb","TGP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
+
/client/verb/silence_current_midi()
set name = "Silence Current Midi"
set category = "Preferences"
diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm
index da0873f162f..38b49314667 100644
--- a/code/modules/clothing/chameleon.dm
+++ b/code/modules/clothing/chameleon.dm
@@ -9,6 +9,10 @@
..()
initialize_outfits()
+/datum/action/chameleon_outfit/Destroy()
+ STOP_PROCESSING(SSprocessing, src)
+ return ..()
+
/datum/action/chameleon_outfit/proc/initialize_outfits()
var/static/list/standard_outfit_options
if(!standard_outfit_options)
@@ -140,29 +144,29 @@
UpdateButtonIcon()
/datum/action/item_action/chameleon/change/proc/update_item(obj/item/picked_item)
- // Species-related variables are lists, which can not be retrieved using initial(). As such, we need to instantiate the picked item.
- var/obj/item/P = new picked_item(null)
-
- target.name = P.name
- target.desc = P.desc
- target.icon_state = P.icon_state
+ target.name = initial(picked_item.name)
+ target.desc = initial(picked_item.desc)
+ target.icon_state = initial(picked_item.icon_state)
if(isitem(target))
var/obj/item/I = target
- I.item_state = P.item_state
- I.item_color = P.item_color
+ I.item_state = initial(picked_item.item_state)
+ I.item_color = initial(picked_item.item_color)
- I.icon_override = P.icon_override
- I.sprite_sheets = P.sprite_sheets
+ I.icon_override = initial(picked_item.icon_override)
+ if(initial(picked_item.sprite_sheets))
+ // Species-related variables are lists, which can not be retrieved using initial(). As such, we need to instantiate the picked item.
+ var/obj/item/P = new picked_item(null)
+ I.sprite_sheets = P.sprite_sheets
+ qdel(P)
- if(istype(I, /obj/item/clothing) && istype(P, /obj/item/clothing))
+ if(istype(I, /obj/item/clothing) && istype(initial(picked_item), /obj/item/clothing))
var/obj/item/clothing/CL = I
- var/obj/item/clothing/PCL = P
- CL.flags_cover = PCL.flags_cover
+ var/obj/item/clothing/PCL = picked_item
+ CL.flags_cover = initial(PCL.flags_cover)
- target.icon = P.icon
- qdel(P)
+ target.icon = initial(picked_item.icon)
/datum/action/item_action/chameleon/change/Trigger()
if(!IsAvailable())
@@ -198,7 +202,7 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/under/chameleon/Initialize()
+/obj/item/clothing/under/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/under
@@ -206,11 +210,15 @@
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/under, /obj/item/clothing/under/color, /obj/item/clothing/under/rank), only_root_path = TRUE)
chameleon_action.initialize_disguises()
+/obj/item/clothing/under/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/clothing/under/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/clothing/under/chameleon/broken/Initialize()
+/obj/item/clothing/under/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -229,7 +237,7 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/suit/chameleon/Initialize()
+/obj/item/clothing/suit/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/suit
@@ -237,11 +245,15 @@
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/suit/armor/abductor), only_root_path = TRUE)
chameleon_action.initialize_disguises()
+/obj/item/clothing/suit/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/clothing/suit/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/clothing/suit/chameleon/broken/Initialize()
+/obj/item/clothing/suit/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -261,7 +273,7 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/glasses/chameleon/Initialize()
+/obj/item/clothing/glasses/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/glasses
@@ -269,11 +281,15 @@
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
+/obj/item/clothing/glasses/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/clothing/glasses/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/clothing/glasses/chameleon/broken/Initialize()
+/obj/item/clothing/glasses/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -289,7 +305,7 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/glasses/hud/security/chameleon/Initialize()
+/obj/item/clothing/glasses/hud/security/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/glasses
@@ -297,11 +313,15 @@
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
+/obj/item/clothing/glasses/hud/security/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/clothing/glasses/hud/security/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/clothing/glasses/hud/security/chameleon/broken/Initialize()
+/obj/item/clothing/glasses/hud/security/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -316,7 +336,7 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/gloves/chameleon/Initialize()
+/obj/item/clothing/gloves/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/gloves
@@ -324,11 +344,15 @@
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/gloves, /obj/item/clothing/gloves/color), only_root_path = TRUE)
chameleon_action.initialize_disguises()
+/obj/item/clothing/gloves/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/clothing/gloves/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/clothing/gloves/chameleon/broken/Initialize()
+/obj/item/clothing/gloves/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -347,7 +371,7 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/head/chameleon/Initialize()
+/obj/item/clothing/head/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/head
@@ -355,11 +379,15 @@
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
+/obj/item/clothing/head/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/clothing/head/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/clothing/head/chameleon/broken/Initialize()
+/obj/item/clothing/head/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -389,7 +417,7 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/mask/chameleon/Initialize()
+/obj/item/clothing/mask/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
@@ -402,13 +430,14 @@
/obj/item/clothing/mask/chameleon/Destroy()
QDEL_NULL(voice_changer)
+ QDEL_NULL(chameleon_action)
return ..()
/obj/item/clothing/mask/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/clothing/mask/chameleon/broken/Initialize()
+/obj/item/clothing/mask/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -423,7 +452,7 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/clothing/shoes/chameleon/Initialize()
+/obj/item/clothing/shoes/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/shoes
@@ -431,6 +460,10 @@
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
+/obj/item/clothing/shoes/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/clothing/shoes/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
@@ -442,7 +475,7 @@
desc = "A pair of black shoes."
flags = NOSLIP
-/obj/item/clothing/shoes/chameleon/noslip/broken/Initialize()
+/obj/item/clothing/shoes/chameleon/noslip/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -455,18 +488,22 @@
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/storage/backpack/chameleon/Initialize()
+/obj/item/storage/backpack/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/storage/backpack
chameleon_action.chameleon_name = "Backpack"
chameleon_action.initialize_disguises()
+/obj/item/storage/backpack/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/storage/backpack/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/storage/backpack/chameleon/broken/Initialize()
+/obj/item/storage/backpack/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -475,7 +512,7 @@
desc = "Holds tools."
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/storage/belt/chameleon/Initialize()
+/obj/item/storage/belt/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
@@ -483,11 +520,15 @@
chameleon_action.chameleon_name = "Belt"
chameleon_action.initialize_disguises()
+/obj/item/storage/belt/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/storage/belt/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/storage/belt/chameleon/broken/Initialize()
+/obj/item/storage/belt/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -495,18 +536,22 @@
name = "radio headset"
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/radio/headset/chameleon/Initialize()
+/obj/item/radio/headset/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/radio/headset
chameleon_action.chameleon_name = "Headset"
chameleon_action.initialize_disguises()
+/obj/item/radio/headset/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/radio/headset/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/radio/headset/chameleon/broken/Initialize()
+/obj/item/radio/headset/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -514,7 +559,7 @@
name = "PDA"
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/pda/chameleon/Initialize()
+/obj/item/pda/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/pda
@@ -522,24 +567,32 @@
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/pda/heads), only_root_path = TRUE)
chameleon_action.initialize_disguises()
+/obj/item/pda/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
/obj/item/pda/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
-/obj/item/pda/chameleon/broken/Initialize()
+/obj/item/pda/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/stamp/chameleon
var/datum/action/item_action/chameleon/change/chameleon_action
-/obj/item/stamp/chameleon/Initialize()
+/obj/item/stamp/chameleon/Initialize(mapload)
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/stamp
chameleon_action.chameleon_name = "Stamp"
chameleon_action.initialize_disguises()
-/obj/item/stamp/chameleon/broken/Initialize()
+/obj/item/stamp/chameleon/Destroy()
+ QDEL_NULL(chameleon_action)
+ return ..()
+
+/obj/item/stamp/chameleon/broken/Initialize(mapload)
. = ..()
chameleon_action.emp_randomise(INFINITY)
diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm
index d34584ff425..7ac87e5d5bc 100644
--- a/code/modules/clothing/head/soft_caps.dm
+++ b/code/modules/clothing/head/soft_caps.dm
@@ -113,7 +113,7 @@
/obj/item/clothing/head/soft/sec/corp
name = "corporate security cap"
- desc = "It's baseball hat in corpotate colours."
+ desc = "It's a baseball hat in corporate colours."
icon_state = "corpsoft"
item_color = "corp"
diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm
index 0bf54e8692f..5bf6b90c98e 100644
--- a/code/modules/clothing/shoes/colour.dm
+++ b/code/modules/clothing/shoes/colour.dm
@@ -86,21 +86,25 @@
name = "orange shoes"
icon_state = "orange"
item_color = "orange"
+ var/obj/item/restraints/handcuffs/shackles
-/obj/item/clothing/shoes/orange/attack_self(mob/user as mob)
- if(src.chained)
- src.chained = null
- src.slowdown = SHOES_SLOWDOWN
- new /obj/item/restraints/handcuffs( user.loc )
- src.icon_state = "orange"
- return
+/obj/item/clothing/shoes/orange/Destroy()
+ QDEL_NULL(shackles)
+ return ..()
-/obj/item/clothing/shoes/orange/attackby(obj/H, loc, params)
- ..()
- if(istype(H, /obj/item/restraints/handcuffs) && !chained && !(H.flags & NODROP))
- if(src.icon_state != "orange") return
- qdel(H)
- src.chained = 1
- src.slowdown = 15
- src.icon_state = "orange1"
- return
+/obj/item/clothing/shoes/orange/attack_self(mob/user)
+ if(shackles)
+ user.put_in_hands(shackles)
+ shackles = null
+ slowdown = SHOES_SLOWDOWN
+ icon_state = "orange"
+
+/obj/item/clothing/shoes/orange/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/restraints/handcuffs) && !shackles)
+ if(user.drop_item())
+ I.forceMove(src)
+ shackles = I
+ slowdown = 15
+ icon_state = "orange1"
+ return
+ return ..()
diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm
index 916cb8e89d4..129b07af36e 100644
--- a/code/modules/clothing/shoes/magboots.dm
+++ b/code/modules/clothing/shoes/magboots.dm
@@ -73,16 +73,15 @@ obj/item/clothing/shoes/magboots/syndie/advance //For the Syndicate Strike Team
shoe_sound = "clownstep"
origin_tech = "magnets=4;syndicate=2"
var/enabled_waddle = TRUE
- var/datum/component/waddle
/obj/item/clothing/shoes/magboots/clown/equipped(mob/user, slot)
. = ..()
if(slot == slot_shoes && enabled_waddle)
- waddle = user.AddComponent(/datum/component/waddling)
+ user.AddElement(/datum/element/waddling)
/obj/item/clothing/shoes/magboots/clown/dropped(mob/user)
. = ..()
- QDEL_NULL(waddle)
+ user.RemoveElement(/datum/element/waddling)
/obj/item/clothing/shoes/magboots/clown/CtrlClick(mob/living/user)
if(!isliving(user))
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index 6858355f876..962cfed80c5 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -71,16 +71,15 @@
var/footstep = 1 //used for squeeks whilst walking
shoe_sound = "clownstep"
var/enabled_waddle = TRUE
- var/datum/component/waddle
/obj/item/clothing/shoes/clown_shoes/equipped(mob/user, slot)
. = ..()
if(slot == slot_shoes && enabled_waddle)
- waddle = user.AddComponent(/datum/component/waddling)
+ user.AddElement(/datum/element/waddling)
/obj/item/clothing/shoes/clown_shoes/dropped(mob/user)
. = ..()
- QDEL_NULL(waddle)
+ user.RemoveElement(/datum/element/waddling)
/obj/item/clothing/shoes/clown_shoes/CtrlClick(mob/living/user)
if(!isliving(user))
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 5a01c9f6f55..1198792c980 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -531,7 +531,7 @@
/obj/item/clothing/suit/space/hardsuit/shielded/process()
if(world.time > recharge_cooldown && current_charges < max_charges)
- current_charges = Clamp((current_charges + recharge_rate), 0, max_charges)
+ current_charges = clamp((current_charges + recharge_rate), 0, max_charges)
playsound(loc, 'sound/magic/charge.ogg', 50, TRUE)
if(current_charges == max_charges)
playsound(loc, 'sound/machines/ding.ogg', 50, TRUE)
diff --git a/code/modules/clothing/spacesuits/rig/modules/combat.dm b/code/modules/clothing/spacesuits/rig/modules/combat.dm
deleted file mode 100644
index 6b9d07a332d..00000000000
--- a/code/modules/clothing/spacesuits/rig/modules/combat.dm
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Contains
- * /obj/item/rig_module/grenade_launcher
- * /obj/item/rig_module/mounted
- * /obj/item/rig_module/mounted/taser
- * /obj/item/rig_module/shield
- * /obj/item/rig_module/fabricator
- * /obj/item/rig_module/device/flash
- */
-
-/obj/item/rig_module/device/flash
- name = "mounted flash"
- desc = "You are the law."
- icon_state = "flash"
- interface_name = "mounted flash"
- interface_desc = "Stuns your target by blinding them with a bright light."
- device_type = /obj/item/flash
-
-/obj/item/rig_module/grenade_launcher
-
- name = "mounted grenade launcher"
- desc = "A shoulder-mounted micro-explosive dispenser."
- selectable = 1
- icon_state = "grenade"
-
- interface_name = "integrated grenade launcher"
- interface_desc = "Discharges loaded grenades against the wearer's location."
-
- var/fire_force = 30
- var/fire_distance = 10
-
- charges = list(
- list("flashbang", "flashbang", /obj/item/grenade/flashbang, 3),
- list("smoke bomb", "smoke bomb", /obj/item/grenade/smokebomb, 3),
- list("EMP grenade", "EMP grenade", /obj/item/grenade/empgrenade, 3),
- )
-
-/obj/item/rig_module/grenade_launcher/accepts_item(var/obj/item/input_device, var/mob/living/user)
-
- if(!istype(input_device) || !istype(user))
- return 0
-
- var/datum/rig_charge/accepted_item
- for(var/charge in charges)
- var/datum/rig_charge/charge_datum = charges[charge]
- if(input_device.type == charge_datum.product_type)
- accepted_item = charge_datum
- break
-
- if(!accepted_item)
- return 0
-
- if(accepted_item.charges >= 5)
- to_chat(user, "Another grenade of that type will not fit into the module.")
- return 0
-
- to_chat(user, "You slot \the [input_device] into the suit module.")
- user.unEquip(input_device)
- qdel(input_device)
- accepted_item.charges++
- return 1
-
-/obj/item/rig_module/grenade_launcher/engage(atom/target)
-
- if(!..())
- return 0
-
- if(!target)
- return 0
-
- var/mob/living/carbon/human/H = holder.wearer
-
- if(!charge_selected)
- to_chat(H, "You have not selected a grenade type.")
- return 0
-
- var/datum/rig_charge/charge = charges[charge_selected]
-
- if(!charge)
- return 0
-
- if(charge.charges <= 0)
- to_chat(H, "Insufficient grenades!")
- return 0
-
- charge.charges--
- var/obj/item/grenade/new_grenade = new charge.product_type(get_turf(H))
- H.visible_message("[H] launches \a [new_grenade]!")
- new_grenade.throw_at(target,fire_force,fire_distance)
- new_grenade.prime()
-
-/obj/item/rig_module/mounted
-
- name = "mounted laser cannon"
- desc = "A shoulder-mounted battery-powered laser cannon mount."
- selectable = 1
- usable = 1
- module_cooldown = 0
- icon_state = "lcannon"
-
- engage_string = "Configure"
-
- interface_name = "mounted laser cannon"
- interface_desc = "A shoulder-mounted cell-powered laser cannon."
-
- var/gun_type = /obj/item/gun/energy/lasercannon/mounted
- var/obj/item/gun/gun
-
-/obj/item/rig_module/mounted/New()
- ..()
- gun = new gun_type(src)
-
-/obj/item/rig_module/mounted/engage(atom/target)
-
- if(!..())
- return 0
-
- if(!target)
- gun.attack_self(holder.wearer)
- return 1
-
- gun.afterattack(target,holder.wearer)
- return 1
-
-/obj/item/rig_module/mounted/egun
-
- name = "mounted energy gun"
- desc = "A forearm-mounted energy projector."
- icon_state = "egun"
-
- interface_name = "mounted energy gun"
- interface_desc = "A forearm-mounted suit-powered energy gun."
-
- gun_type = /obj/item/gun/energy/gun/mounted
-
-/obj/item/rig_module/mounted/taser
-
- name = "mounted taser"
- desc = "A palm-mounted nonlethal energy projector."
- icon_state = "taser"
-
- usable = 0
-
- suit_overlay_active = "mounted-taser"
- suit_overlay_inactive = "mounted-taser"
-
- interface_name = "mounted energy gun"
- interface_desc = "A shoulder-mounted cell-powered energy gun."
-
- gun_type = /obj/item/gun/energy/taser/mounted
-
-/obj/item/rig_module/mounted/energy_blade
-
- name = "energy blade projector"
- desc = "A powerful cutting beam projector."
- icon_state = "eblade"
-
- activate_string = "Project Blade"
- deactivate_string = "Cancel Blade"
-
- interface_name = "spider fang blade"
- interface_desc = "A lethal energy projector that can shape a blade projected from the hand of the wearer or launch radioactive darts."
-
- usable = 0
- selectable = 1
- toggleable = 1
- use_power_cost = 50
- active_power_cost = 10
- passive_power_cost = 0
-
- gun_type = /obj/item/gun/energy/kinetic_accelerator/crossbow/ninja
-
-/obj/item/rig_module/mounted/energy_blade/process()
-
- if(holder && holder.wearer)
- if(!(locate(/obj/item/melee/energy/blade) in holder.wearer))
- deactivate()
- return 0
-
- return ..()
-
-/obj/item/rig_module/mounted/energy_blade/activate()
-
- ..()
-
- var/mob/living/M = holder.wearer
-
- if(M.l_hand && M.r_hand)
- to_chat(M, "Your hands are full.")
- deactivate()
- return
-
- var/obj/item/melee/energy/blade/blade = new(M)
- M.put_in_hands(blade)
-
-/obj/item/rig_module/mounted/energy_blade/deactivate()
-
- ..()
-
- var/mob/living/M = holder.wearer
-
- if(!M)
- return
-
- for(var/obj/item/melee/energy/blade/blade in M.contents)
- M.unEquip(blade)
- qdel(blade)
-
-/obj/item/rig_module/fabricator
-
- name = "matter fabricator"
- desc = "A self-contained microfactory system for hardsuit integration."
- selectable = 1
- usable = 1
- use_power_cost = 15
- icon_state = "enet"
-
- engage_string = "Fabricate Tile"
-
- interface_name = "death blossom launcher"
- interface_desc = "An integrated microfactory that produces floor tiles from thin air and electricity."
-
- var/fabrication_type = /obj/item/stack/tile/plasteel
- var/fire_force = 30
- var/fire_distance = 10
-
-/obj/item/rig_module/fabricator/engage(atom/target)
-
- if(!..())
- return 0
-
- var/mob/living/H = holder.wearer
-
- if(target)
- var/obj/item/firing = new fabrication_type()
- firing.forceMove(get_turf(src))
- H.visible_message("[H] launches \a [firing]!")
- firing.throw_at(target,fire_force,fire_distance)
- else
- if(H.l_hand && H.r_hand)
- to_chat(H, "Your hands are full.")
- else
- var/obj/item/new_weapon = new fabrication_type()
- new_weapon.forceMove(H)
- to_chat(H, "You quickly fabricate \a [new_weapon].")
- H.put_in_hands(new_weapon)
-
- return 1
diff --git a/code/modules/clothing/spacesuits/rig/modules/computer.dm b/code/modules/clothing/spacesuits/rig/modules/computer.dm
deleted file mode 100644
index 749e12e8053..00000000000
--- a/code/modules/clothing/spacesuits/rig/modules/computer.dm
+++ /dev/null
@@ -1,496 +0,0 @@
-/*
- * Contains
- * /obj/item/rig_module/ai_container
- * /obj/item/rig_module/datajack
- * /obj/item/rig_module/power_sink
- * /obj/item/rig_module/electrowarfare_suite
- */
-
-/obj/item/ai_verbs
- name = "AI verb holder"
-
-/obj/item/ai_verbs/verb/hardsuit_interface()
- set category = "Hardsuit"
- set name = "Open Hardsuit Interface"
- set src in usr
-
- if(!usr.loc || !usr.loc.loc || !istype(usr.loc.loc, /obj/item/rig_module))
- to_chat(usr, "You are not loaded into a hardsuit.")
- return
-
- var/obj/item/rig_module/module = usr.loc.loc
- if(!module.holder)
- to_chat(usr, "Your module is not installed in a hardsuit.")
- return
-
- module.holder.ui_interact(usr, state = GLOB.contained_state)
-
-/obj/item/rig_module/ai_container
-
- name = "IIS module"
- desc = "An integrated intelligence system module suitable for most hardsuits."
- icon_state = "IIS"
- toggleable = 1
- usable = 1
- disruptive = 0
- activates_on_touch = 1
-
- engage_string = "Eject AI"
- activate_string = "Enable Dataspike"
- deactivate_string = "Disable Dataspike"
-
- interface_name = "integrated intelligence system"
- interface_desc = "A socket that supports a range of artificial intelligence systems."
-
- var/mob/integrated_ai // Direct reference to the actual mob held in the suit.
- var/obj/item/ai_card // Reference to the MMI, posibrain, intellicard or pAI card previously holding the AI.
- var/obj/item/ai_verbs/verb_holder
-
-/mob
- var/get_rig_stats = 0
-
-/obj/item/rig_module/ai_container/process()
- if(integrated_ai)
- var/obj/item/rig/rig = get_rig()
- if(rig && rig.ai_override_enabled)
- integrated_ai.get_rig_stats = 1
- else
- integrated_ai.get_rig_stats = 0
-
-/obj/item/rig_module/ai_container/proc/update_verb_holder()
- if(!verb_holder)
- verb_holder = new(src)
- if(integrated_ai)
- verb_holder.forceMove(integrated_ai)
- else
- verb_holder.forceMove(src)
-
-/obj/item/rig_module/ai_container/accepts_item(var/obj/item/input_device, var/mob/living/user)
-
- // Check if there's actually an AI to deal with.
- var/mob/living/silicon/ai/target_ai
- if(istype(input_device, /mob/living/silicon/ai))
- target_ai = input_device
- else
- target_ai = locate(/mob/living/silicon/ai) in input_device.contents
-
- var/obj/item/aicard/card = ai_card
-
- // Downloading from/loading to a terminal.
- if(istype(input_device,/obj/machinery/computer/aifixer) || istype(input_device,/mob/living/silicon/ai) || istype(input_device,/obj/structure/AIcore/deactivated))
-
- // If we're stealing an AI, make sure we have a card for it.
- if(!card)
- card = new /obj/item/aicard(src)
-
- // Terminal interaction only works with an intellicarded AI.
- if(!istype(card))
- return 0
-
- // Since we've explicitly checked for three types, this should be safe.
- card.afterattack(input_device, user, 1)
-
- // If the transfer failed we can delete the card.
- if(locate(/mob/living/silicon/ai) in card)
- ai_card = card
- integrated_ai = locate(/mob/living/silicon/ai) in card
- else
- eject_ai()
- update_verb_holder()
- return 1
-
- if(istype(input_device,/obj/item/aicard))
- // We are carding the AI in our suit.
- if(integrated_ai)
- var/obj/item/aicard/ext_card = input_device
- ext_card.afterattack(integrated_ai, user, 1)
- // If the transfer was successful, we can clear out our vars.
- if(integrated_ai.loc != src)
- integrated_ai = null
- eject_ai()
- else
- // You're using an empty card on an empty suit, idiot.
- if(!target_ai)
- return 0
- integrate_ai(input_device,user)
- return 1
-
- // Okay, it wasn't a terminal being touched, check for all the simple insertions.
- if(input_device.type in list(/obj/item/paicard, /obj/item/mmi, /obj/item/mmi/robotic_brain))
- if(integrated_ai)
- integrated_ai.attackby(input_device,user)
- // If the transfer was successful, we can clear out our vars.
- if(integrated_ai.loc != src)
- integrated_ai = null
- eject_ai()
- else
- integrate_ai(input_device,user)
- return 1
-
- return 0
-
-/obj/item/rig_module/ai_container/engage(atom/target)
-
- if(!..())
- return 0
-
- var/mob/living/carbon/human/H = holder.wearer
-
- if(!target)
- if(ai_card)
- if(istype(ai_card,/obj/item/aicard))
- ai_card.ui_interact(H, state = GLOB.deep_inventory_state)
- else
- eject_ai(H)
- update_verb_holder()
- return 1
-
- if(accepts_item(target,H))
- return 1
-
- return 0
-
-/obj/item/rig_module/ai_container/removed()
- eject_ai()
- ..()
-
-/obj/item/rig_module/ai_container/proc/eject_ai(var/mob/user)
-
- if(ai_card)
- if(istype(ai_card, /obj/item/aicard))
- if(integrated_ai && !integrated_ai.stat)
- if(user)
- to_chat(user, "You cannot eject your currently stored AI. Purge it manually.")
- return 0
- to_chat(user, "You purge the remaining scraps of data from your previous AI, freeing it for use.")
- QDEL_NULL(integrated_ai)
- QDEL_NULL(ai_card)
- else if(user)
- user.put_in_hands(ai_card)
- else
- ai_card.forceMove(get_turf(src))
- ai_card = null
- integrated_ai = null
- update_verb_holder()
-
-
-
-/obj/item/rig_module/ai_container/proc/integrate_ai(var/obj/item/ai,var/mob/user)
- if(!ai) return
-
- // The ONLY THING all the different AI systems have in common is that they all store the mob inside an item.
- var/mob/living/ai_mob = locate(/mob/living) in ai.contents
- if(ai_mob)
- if(ai_mob.key && ai_mob.client)
- if(istype(ai, /obj/item/aicard))
- var/mob/living/silicon/ai/ROBUTT = ai_mob
- if(istype(ROBUTT))
- if(!ai_card)
- ai_card = new /obj/item/aicard(src)
-
- var/obj/item/aicard/source_card = ai
- var/obj/item/aicard/target_card = ai_card
- if(istype(source_card) && istype(target_card))
- ROBUTT.forceMove(target_card)
- ROBUTT.aiRestorePowerRoutine = 0//So the AI initially has power.
- ROBUTT.control_disabled = 1//Can't control things remotely if you're stuck in a card!
- ROBUTT.aiRadio.disabledAi = 1 //No talking on the built-in radio for you either!
- source_card.update_state()
- target_card.update_state()
- else
- return 0
-
- else
- user.unEquip(ai)
- ai.forceMove(src)
- ai_card = ai
- to_chat(ai_mob, "You have been transferred to \the [holder]'s [src].")
- to_chat(user, "You load [ai_mob] into \the [holder]'s [src].")
-
- integrated_ai = ai_mob
-
- if(!(locate(integrated_ai) in ai_card))
- integrated_ai = null
- eject_ai()
- else
- to_chat(user, "There is no active AI within \the [ai].")
- else
- to_chat(user, "There is no active AI within \the [ai].")
- update_verb_holder()
-
-/obj/item/rig_module/datajack
-
- name = "datajack module"
- desc = "A simple induction datalink module."
- icon_state = "datajack"
- toggleable = 1
- activates_on_touch = 1
- usable = 0
-
- activate_string = "Enable Datajack"
- deactivate_string = "Disable Datajack"
-
- interface_name = "contact datajack"
- interface_desc = "An induction-powered high-throughput datalink suitable for hacking encrypted networks."
- var/list/stored_research
-
-/obj/item/rig_module/datajack/New()
- ..()
- stored_research = list()
-
-/obj/item/rig_module/datajack/engage(atom/target)
-
- if(!..())
- return 0
-
- if(target)
- var/mob/living/carbon/human/H = holder.wearer
- if(!accepts_item(target,H))
- return 0
- return 1
-
-/obj/item/rig_module/datajack/accepts_item(var/obj/item/input_device, var/mob/living/user)
-
- if(istype(input_device,/obj/item/disk/tech_disk))
- to_chat(user, "You slot the disk into [src].")
- var/obj/item/disk/tech_disk/disk = input_device
- if(disk.stored)
- if(load_data(disk.stored))
- to_chat(user, "Download successful; disk erased.")
- disk.stored = null
- else
- to_chat(user, "The disk is corrupt. It is useless to you.")
- else
- to_chat(user, "The disk is blank. It is useless to you.")
- return 1
-
- // I fucking hate R&D code. This typecheck spam would be totally unnecessary in a sane setup.
- else if(istype(input_device,/obj/machinery))
- var/datum/research/incoming_files
- if(istype(input_device,/obj/machinery/computer/rdconsole))
- var/obj/machinery/computer/rdconsole/input_machine = input_device
- incoming_files = input_machine.files
- else if(istype(input_device,/obj/machinery/r_n_d/server))
- var/obj/machinery/r_n_d/server/input_machine = input_device
- incoming_files = input_machine.files
- else if(istype(input_device,/obj/machinery/mecha_part_fabricator))
- var/obj/machinery/mecha_part_fabricator/input_machine = input_device
- incoming_files = input_machine.files
-
- if(!incoming_files || !incoming_files.known_tech || !incoming_files.known_tech.len)
- to_chat(user, "Memory failure. There is nothing accessible stored on this terminal.")
- else
- // Maybe consider a way to drop all your data into a target repo in the future.
- if(load_data(incoming_files.known_tech))
- to_chat(user, "Download successful; local and remote repositories synchronized.")
- else
- to_chat(user, "Scan complete. There is nothing useful stored on this terminal.")
- return 1
- return 0
-
-/obj/item/rig_module/datajack/proc/load_data(var/incoming_data)
-
- if(islist(incoming_data))
- for(var/entry in incoming_data)
- load_data(entry)
- return 1
-
- if(istype(incoming_data, /datum/tech))
- var/data_found
- var/datum/tech/new_data = incoming_data
- for(var/datum/tech/current_data in stored_research)
- if(current_data.id == new_data.id)
- data_found = 1
- if(current_data.level < new_data.level)
- current_data.level = new_data.level
- break
- if(!data_found)
- stored_research += incoming_data
- return 1
- return 0
-
-/obj/item/rig_module/electrowarfare_suite
-
- name = "electrowarfare module"
- desc = "A bewilderingly complex bundle of fiber optics and chips."
- icon_state = "ewar"
- toggleable = 1
- usable = 0
-
- activate_string = "Enable Countermeasures"
- deactivate_string = "Disable Countermeasures"
-
- interface_name = "electrowarfare system"
- interface_desc = "An active counter-electronic warfare suite that disrupts AI tracking."
-
-/obj/item/rig_module/electrowarfare_suite/activate()
-
- if(!..())
- return
-
- // This is not the best way to handle this, but I don't want it to mess with ling camo
- var/mob/living/M = holder.wearer
- M.digitalcamo++
-
-/obj/item/rig_module/electrowarfare_suite/deactivate()
-
- if(!..())
- return
-
- var/mob/living/M = holder.wearer
- M.digitalcamo = max(0,(M.digitalcamo-1))
-
-/* //Not easily compatible with our current powernet, and is
-/obj/item/rig_module/power_sink // quite stupid anyways, iyam
-
- name = "hardsuit power sink"
- desc = "An heavy-duty power sink."
- icon_state = "powersink"
- toggleable = 1
- activates_on_touch = 1
- disruptive = 0
-
- activate_string = "Enable Power Sink"
- deactivate_string = "Disable Power Sink"
-
- interface_name = "niling d-sink"
- interface_desc = "Colloquially known as a power siphon, this module drains power through the suit hands into the suit battery."
-
- var/atom/interfaced_with // Currently draining power from this device.
- var/total_power_drained = 0
- var/drain_loc
-
-/obj/item/rig_module/power_sink/deactivate()
-
- if(interfaced_with)
- if(holder && holder.wearer)
- to_chat(holder.wearer, "Your power sink retracts as the module deactivates.")
- drain_complete()
- interfaced_with = null
- total_power_drained = 0
- return ..()
-
-/obj/item/rig_module/power_sink/activate()
- interfaced_with = null
- total_power_drained = 0
- return ..()
-
-/obj/item/rig_module/power_sink/engage(atom/target)
-
- if(!..())
- return 0
-
- //Target wasn't supplied or we're already draining.
- if(interfaced_with)
- return 0
-
- if(!target)
- return 1
-
- // Are we close enough?
- var/mob/living/carbon/human/H = holder.wearer
- if(!target.Adjacent(H))
- return 0
-
- // Is it a valid power source?
- if(target.drain_power(1) <= 0)
- return 0
-
- to_chat(H, "You begin draining power from [target]!")
- interfaced_with = target
- drain_loc = interfaced_with.loc
-
- holder.spark_system.start()
- playsound(H.loc, 'sound/effects/sparks2.ogg', 50, 1)
-
- return 1
-
-/obj/item/rig_module/power_sink/accepts_item(var/obj/item/input_device, var/mob/living/user)
- var/can_drain = input_device.drain_power(1)
- if(can_drain > 0)
- engage(input_device)
- return 1
- return 0
-
-/obj/item/rig_module/power_sink/process()
-
- if(!interfaced_with)
- return ..()
-
- var/mob/living/carbon/human/H
- if(holder && holder.wearer)
- H = holder.wearer
-
- if(!H || !istype(H))
- return 0
-
- holder.spark_system.start()
- playsound(H.loc, 'sound/effects/sparks2.ogg', 50, 1)
-
- if(!holder.cell)
- to_chat(H, "Your power sink flashes an error; there is no cell in your rig.")
- drain_complete(H)
- return
-
- if(!interfaced_with || !interfaced_with.Adjacent(H) || !(interfaced_with.loc == drain_loc))
- to_chat(H, "Your power sink retracts into its casing.")
- drain_complete(H)
- return
-
- if(holder.cell.fully_charged())
- to_chat(H, "Your power sink flashes an amber light; your rig cell is full.")
- drain_complete(H)
- return
-
- // Attempts to drain up to 40kW, determines this value from remaining cell capacity to ensure we don't drain too much..
- var/to_drain = min(40000, ((holder.cell.maxcharge - holder.cell.charge) / CELLRATE))
- var/target_drained = interfaced_with.drain_power(0,0,to_drain)
- if(target_drained <= 0)
- to_chat(H, "Your power sink flashes a red light; there is no power left in [interfaced_with].")
- drain_complete(H)
- return
-
- holder.cell.give(target_drained * CELLRATE)
- total_power_drained += target_drained
-
- return 1
-
-/obj/item/rig_module/power_sink/proc/drain_complete(var/mob/living/M)
-
- if(!interfaced_with)
- to_chat(if(M) M, "Total power drained: [round(total_power_drained/1000)]kJ.")
- else
- to_chat(if(M) M, "Total power drained from [interfaced_with]: [round(total_power_drained/1000)]kJ.")
- interfaced_with.drain_power(0,1,0) // Damage the victim.
-
- drain_loc = null
- interfaced_with = null
- total_power_drained = 0*/
-
-/*
-//Maybe make this use power when active or something
-/obj/item/rig_module/emp_shielding
- name = "\improper EMP dissipation module"
- desc = "A bewilderingly complex bundle of fiber optics and chips."
- toggleable = 1
- usable = 0
-
- activate_string = "Enable active EMP shielding"
- deactivate_string = "Disable active EMP shielding"
-
- interface_name = "active EMP shielding system"
- interface_desc = "A highly experimental system that augments the hardsuit's existing EM shielding."
- var/protection_amount = 20
-
-/obj/item/rig_module/emp_shielding/activate()
- if(!..())
- return
-
- holder.emp_protection += protection_amount
-
-/obj/item/rig_module/emp_shielding/deactivate()
- if(!..())
- return
-
- holder.emp_protection = max(0,(holder.emp_protection - protection_amount))
-*/
diff --git a/code/modules/clothing/spacesuits/rig/modules/handheld.dm b/code/modules/clothing/spacesuits/rig/modules/handheld.dm
deleted file mode 100644
index 31f9400afc2..00000000000
--- a/code/modules/clothing/spacesuits/rig/modules/handheld.dm
+++ /dev/null
@@ -1,50 +0,0 @@
-
-/obj/item/rig_module/handheld
- name = "mounted device"
- desc = "Some kind of hardsuit extension."
- usable = 0
- selectable = 0
- toggleable = 1
- disruptive = 0
- activate_string = "Deploy"
- deactivate_string = "Retract"
-
- var/device_type
- var/obj/item
-
-/obj/item/rig_module/handheld/activate()
- if(!..())
- return
-
- if(!holder.wearer.put_in_hands(device))
- to_chat(holder.wearer, "You need a free hand to hold \the [device].")
- active = 0
- return
-
- to_chat(holder.wearer, "You deploy \the [device].")
-
-
-/obj/item/rig_module/handheld/deactivate()
- if(!..())
- return
- if(ismob(device.loc)) //Better check for the holder, instead of assuming the rigwearer has it.
- var/mob/M = device.loc //Helps in case the code fails to keep the module in one place, this should still return it.
- M.unEquip(device, 1)
-
- device.loc = src
- to_chat(holder.wearer, "You retract \the [device].")
-
-/obj/item/rig_module/handheld/New()
- ..()
- if(device_type)
- device = new device_type(src)
- device.flags |= NODROP //We don't want to drop it while it's active/inhand.
- activate_string += " [device]"
- deactivate_string += " [device]"
-
-/obj/item/rig_module/handheld/horn
- name = "mounted bikehorn"
- desc = "For tactical honking"
- interface_name = "mounted bikehorn"
- interface_desc = "Honks"
- device_type = /obj/item/bikehorn
diff --git a/code/modules/clothing/spacesuits/rig/modules/modules.dm b/code/modules/clothing/spacesuits/rig/modules/modules.dm
deleted file mode 100644
index 53330341bfe..00000000000
--- a/code/modules/clothing/spacesuits/rig/modules/modules.dm
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Rigsuit upgrades/abilities.
- */
-
-/datum/rig_charge
- var/short_name = "undef"
- var/display_name = "undefined"
- var/product_type = "undefined"
- var/charges = 0
-
-/obj/item/rig_module
- name = "hardsuit upgrade"
- desc = "It looks pretty sciency."
- icon = 'icons/obj/rig_modules.dmi'
- icon_state = "module"
-
- toolspeed = 1
-
- var/damage = 0
- var/obj/item/rig/holder
-
- var/module_cooldown = 10
- var/next_use = 0
-
- var/toggleable // Set to 1 for the device to show up as an active effect.
- var/usable // Set to 1 for the device to have an on-use effect.
- var/selectable // Set to 1 to be able to assign the device as primary system.
- var/redundant // Set to 1 to ignore duplicate module checking when installing.
- var/permanent // If set, the module can't be removed.
- var/disruptive = 1 // Can disrupt by other effects.
- var/activates_on_touch // If set, unarmed attacks will call engage() on the target.
-
- var/active // Basic module status
- var/disruptable // Will deactivate if some other powers are used.
-
- var/use_power_cost = 0 // Power used when single-use ability called.
- var/active_power_cost = 0 // Power used when turned on.
- var/passive_power_cost = 0 // Power used when turned off.
-
- var/list/charges // Associative list of charge types and remaining numbers.
- var/charge_selected // Currently selected option used for charge dispensing.
-
- // Icons.
- var/suit_overlay
- var/suit_overlay_active // If set, drawn over icon and mob when effect is active.
- var/suit_overlay_inactive // As above, inactive.
- var/suit_overlay_used // As above, when engaged.
-
- //Display fluff
- var/interface_name = "hardsuit upgrade"
- var/interface_desc = "A generic hardsuit upgrade."
- var/engage_string = "Engage"
- var/activate_string = "Activate"
- var/deactivate_string = "Deactivate"
-
- var/list/stat_rig_module/stat_modules = new()
-
-/obj/item/rig_module/examine(mob/user)
- . = ..()
- switch(damage)
- if(0)
- . += "It is undamaged."
- if(1)
- . += "It is badly damaged."
- if(2)
- . += "It is almost completely destroyed."
-
-/obj/item/rig_module/attackby(obj/item/W as obj, mob/user as mob)
-
- if(istype(W,/obj/item/stack/nanopaste))
-
- if(damage == 0)
- to_chat(user, "There is no damage to mend.")
- return
-
- to_chat(user, "You start mending the damaged portions of \the [src]...")
-
- if(!do_after(user, 30 * W.toolspeed, target = src) || !W || !src)
- return
-
- var/obj/item/stack/nanopaste/paste = W
- damage = 0
- to_chat(user, "You mend the damage to [src] with [W].")
- paste.use(1)
- return
-
- else if(istype(W,/obj/item/stack/cable_coil))
-
- switch(damage)
- if(0)
- to_chat(user, "There is no damage to mend.")
- return
- if(2)
- to_chat(user, "There is no damage that you are capable of mending with such crude tools.")
- return
-
- var/obj/item/stack/cable_coil/cable = W
- if(!cable.amount >= 5)
- to_chat(user, "You need five units of cable to repair \the [src].")
- return
-
- to_chat(user, "You start mending the damaged portions of \the [src]...")
- if(!do_after(user, 30 * W.toolspeed, target = src) || !W || !src)
- return
-
- damage = 1
- to_chat(user, "You mend some of damage to [src] with [W], but you will need more advanced tools to fix it completely.")
- cable.use(5)
- return
- ..()
-
-/obj/item/rig_module/New()
- ..()
- if(suit_overlay_inactive)
- suit_overlay = suit_overlay_inactive
-
- if(charges && charges.len)
- var/list/processed_charges = list()
- for(var/list/charge in charges)
- var/datum/rig_charge/charge_dat = new
-
- charge_dat.short_name = charge[1]
- charge_dat.display_name = charge[2]
- charge_dat.product_type = charge[3]
- charge_dat.charges = charge[4]
-
- if(!charge_selected) charge_selected = charge_dat.short_name
- processed_charges[charge_dat.short_name] = charge_dat
-
- charges = processed_charges
-
- stat_modules += new/stat_rig_module/activate(src)
- stat_modules += new/stat_rig_module/deactivate(src)
- stat_modules += new/stat_rig_module/engage(src)
- stat_modules += new/stat_rig_module/select(src)
- stat_modules += new/stat_rig_module/charge(src)
-
-// Called when the module is installed into a suit.
-/obj/item/rig_module/proc/installed(var/obj/item/rig/new_holder)
- holder = new_holder
- return
-
-//Proc for one-use abilities like teleport.
-/obj/item/rig_module/proc/engage()
-
- if(damage >= 2)
- to_chat(usr, "The [interface_name] is damaged beyond use!")
- return 0
-
- if(world.time < next_use)
- to_chat(usr, "You cannot use the [interface_name] again so soon.")
- return 0
-
- if(!holder || (!(holder.flags & NODROP)))
- to_chat(usr, "The suit is not initialized.")
- return 0
-
- if(usr.lying || usr.stat || usr.stunned || usr.paralysis || usr.IsWeakened())
- to_chat(usr, "You cannot use the suit in this state.")
- return 0
-
- if(holder.wearer && holder.wearer.lying)
- to_chat(usr, "The suit cannot function while the wearer is prone.")
- return 0
-
- if(holder.security_check_enabled && !holder.check_suit_access(usr))
- to_chat(usr, "Access denied.")
- return 0
-
- if(!holder.check_power_cost(usr, use_power_cost, 0, src, (istype(usr,/mob/living/silicon ? 1 : 0) ) ) )
- return 0
-
- next_use = world.time + module_cooldown
-
- return 1
-
-// Proc for toggling on active abilities.
-/obj/item/rig_module/proc/activate()
-
- if(active || !engage())
- return 0
-
- active = 1
-
- spawn(1)
- if(suit_overlay_active)
- suit_overlay = suit_overlay_active
- else
- suit_overlay = null
- holder.update_icon()
-
- return 1
-
-// Proc for toggling off active abilities.
-/obj/item/rig_module/proc/deactivate()
-
- if(!active)
- return 0
-
- active = 0
-
- spawn(1)
- if(suit_overlay_inactive)
- suit_overlay = suit_overlay_inactive
- else
- suit_overlay = null
- if(holder)
- holder.update_icon()
-
- return 1
-
-// Called when the module is uninstalled from a suit.
-/obj/item/rig_module/proc/removed()
- deactivate()
- holder = null
- return
-
-// Called by the hardsuit each rig process tick.
-/obj/item/rig_module/process()
- if(active)
- return active_power_cost
- else
- return passive_power_cost
-
-// Called by holder rigsuit attackby()
-// Checks if an item is usable with this module and handles it if it is
-/obj/item/rig_module/proc/accepts_item(var/obj/item/input_device)
- return 0
-
-/mob/proc/SetupStat(var/obj/item/rig/R)
- if(R && (R.flags & NODROP) && R.installed_modules.len && statpanel("Hardsuit Modules"))
- var/cell_status = R.cell ? "[R.cell.charge]/[R.cell.maxcharge]" : "ERROR"
- stat("Suit charge", cell_status)
- for(var/obj/item/rig_module/module in R.installed_modules)
- {
- for(var/stat_rig_module/SRM in module.stat_modules)
- if(SRM.CanUse())
- stat(SRM.module.interface_name,SRM)
- }
-
-/stat_rig_module
- parent_type = /atom/movable
- var/module_mode = ""
- var/obj/item/rig_module/module
-
-/stat_rig_module/New(var/obj/item/rig_module/module)
- ..()
- src.module = module
-
-/stat_rig_module/proc/AddHref(var/list/href_list)
- return
-
-/stat_rig_module/proc/CanUse()
- return 0
-
-/stat_rig_module/Click()
- if(CanUse())
- var/list/href_list = list(
- "interact_module" = module.holder.installed_modules.Find(module),
- "module_mode" = module_mode
- )
- AddHref(href_list)
- module.holder.Topic(usr, href_list)
-
-/stat_rig_module/DblClick()
- return Click()
-
-/stat_rig_module/activate/New(var/obj/item/rig_module/module)
- ..()
- name = module.activate_string
- if(module.active_power_cost)
- name += " ([module.active_power_cost*10]A)"
- module_mode = "activate"
-
-/stat_rig_module/activate/CanUse()
- return module.toggleable && !module.active
-
-/stat_rig_module/deactivate/New(var/obj/item/rig_module/module)
- ..()
- name = module.deactivate_string
- // Show cost despite being 0, if it means changing from an active cost.
- if(module.active_power_cost || module.passive_power_cost)
- name += " ([module.passive_power_cost*10]P)"
-
- module_mode = "deactivate"
-
-/stat_rig_module/deactivate/CanUse()
- return module.toggleable && module.active
-
-/stat_rig_module/engage/New(var/obj/item/rig_module/module)
- ..()
- name = module.engage_string
- if(module.use_power_cost)
- name += " ([module.use_power_cost*10]E)"
- module_mode = "engage"
-
-/stat_rig_module/engage/CanUse()
- return module.usable
-
-/stat_rig_module/select/New()
- ..()
- name = "Select"
- module_mode = "select"
-
-/stat_rig_module/select/CanUse()
- if(module.selectable)
- name = module.holder.selected_module == module ? "Selected" : "Select"
- return 1
- return 0
-
-/stat_rig_module/charge/New()
- ..()
- name = "Change Charge"
- module_mode = "select_charge_type"
-
-/stat_rig_module/charge/AddHref(var/list/href_list)
- var/charge_index = module.charges.Find(module.charge_selected)
- if(!charge_index)
- charge_index = 0
- else
- charge_index = charge_index == module.charges.len ? 1 : charge_index+1
-
- href_list["charge_type"] = module.charges[charge_index]
-
-/stat_rig_module/charge/CanUse()
- if(module.charges && module.charges.len)
- var/datum/rig_charge/charge = module.charges[module.charge_selected]
- name = "[charge.display_name] ([charge.charges]C) - Change"
- return 1
- return 0
diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm
deleted file mode 100644
index 6e4b588ac24..00000000000
--- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Contains
- * /obj/item/rig_module/stealth_field
- * /obj/item/rig_module/teleporter
- * /obj/item/rig_module/fabricator/energy_net
- * /obj/item/rig_module/self_destruct
- */
-
-/obj/item/rig_module/stealth_field
-
- name = "active camouflage module"
- desc = "A robust hardsuit-integrated stealth module."
- icon_state = "cloak"
-
- toggleable = 1
- disruptable = 1
- disruptive = 0
-
- use_power_cost = 50
- active_power_cost = 10
- passive_power_cost = 0
- module_cooldown = 30
-
- activate_string = "Enable Cloak"
- deactivate_string = "Disable Cloak"
-
- interface_name = "integrated stealth system"
- interface_desc = "An integrated active camouflage system."
-
- suit_overlay_active = "stealth_active"
- suit_overlay_inactive = "stealth_inactive"
-
-/obj/item/rig_module/stealth_field/activate()
-
- if(!..())
- return 0
-
- var/mob/living/carbon/human/H = holder.wearer
-
- to_chat(H, "You are now invisible to normal detection.")
- H.invisibility = INVISIBILITY_LEVEL_TWO
-
- H.visible_message("[H.name] vanishes into thin air!",1)
-
-/obj/item/rig_module/stealth_field/deactivate()
-
- if(!..())
- return 0
-
- var/mob/living/carbon/human/H = holder.wearer
-
- to_chat(H, "You are now visible.")
- H.invisibility = 0
-
- new /obj/effect/temp_visual/dir_setting/ninja(get_turf(H), H.dir)
-
- for(var/mob/O in oviewers(H))
- O.show_message("[H.name] appears from thin air!",1)
- playsound(get_turf(H), 'sound/effects/stealthoff.ogg', 75, 1)
-
-
-/obj/item/rig_module/teleporter
-
- name = "teleportation module"
- desc = "A complex, sleek-looking, hardsuit-integrated teleportation module."
- icon_state = "teleporter"
- use_power_cost = 40
- redundant = 1
- usable = 1
- selectable = 1
-
- engage_string = "Emergency Leap"
-
- interface_name = "VOID-shift phase projector"
- interface_desc = "An advanced teleportation system. It is capable of pinpoint precision or random leaps forward."
-
-/obj/item/rig_module/teleporter/proc/phase_in(var/mob/M,var/turf/T)
-
- if(!M || !T)
- return
-
- holder.spark_system.start()
- playsound(T, 'sound/effects/phasein.ogg', 25, 1)
- playsound(T, 'sound/effects/sparks2.ogg', 50, 1)
- new /obj/effect/temp_visual/dir_setting/ninja/phase(T, M.dir)
-
-/obj/item/rig_module/teleporter/proc/phase_out(var/mob/M,var/turf/T)
-
- if(!M || !T)
- return
-
- playsound(T, "sparks", 50, 1)
- new /obj/effect/temp_visual/dir_setting/ninja/phase/out(T, M.dir)
-
-/obj/item/rig_module/teleporter/engage(var/atom/target, var/notify_ai)
-
- if(!..()) return 0
-
- var/mob/living/carbon/human/H = holder.wearer
-
- if(!istype(H.loc, /turf))
- to_chat(H, "You cannot teleport out of your current location.")
- return 0
-
- var/turf/T
- if(target)
- T = get_turf(target)
- else
- T = get_teleport_loc(get_turf(H), H, rand(5, 9))
-
- /*if(!T || T.density)
- to_chat(H, "You cannot teleport into solid walls.")
- return 0*///Who the fuck cares? Ninjas in walls are cool.
-
- if(!is_teleport_allowed(T.z))
- to_chat(H, "You cannot use your teleporter on this Z-level.")
- return 0
-
- phase_out(H,get_turf(H))
- H.forceMove(T)
- phase_in(H,get_turf(H))
-
- for(var/obj/item/grab/G in H.contents)
- if(G.affecting)
- phase_out(G.affecting,get_turf(G.affecting))
- G.affecting.forceMove(locate(T.x+rand(-1,1),T.y+rand(-1,1),T.z))
- phase_in(G.affecting,get_turf(G.affecting))
-
- return 1
-
-/*
-/obj/item/rig_module/fabricator/energy_net
-
- name = "net projector"
- desc = "Some kind of complex energy projector with a hardsuit mount."
- icon_state = "enet"
-
- interface_name = "energy net launcher"
- interface_desc = "An advanced energy-patterning projector used to capture targets."
-
- engage_string = "Fabricate Net"
-
- fabrication_type = /obj/item/energy_net
- use_power_cost = 70
-
-/obj/item/rig_module/fabricator/energy_net/engage(atom/target)
-
- if(holder && holder.wearer)
- if(..(target) && target)
- holder.wearer.Beam(target,"n_beam",,10)
- return 1
- return 0*/
-
-/obj/item/rig_module/self_destruct
-
- name = "self-destruct module"
- desc = "Oh my God, Captain. A bomb."
- icon_state = "deadman"
- usable = 1
- active = 1
- permanent = 1
-
- engage_string = "Detonate"
-
- interface_name = "dead man's switch"
- interface_desc = "An integrated self-destruct module. When the wearer dies, so does the surrounding area. Do not press this button."
-
-/obj/item/rig_module/self_destruct/activate()
- return
-
-/obj/item/rig_module/self_destruct/deactivate()
- return
-
-/obj/item/rig_module/self_destruct/process()
-
- // Not being worn, leave it alone.
- if(!holder || !holder.wearer || !holder.wearer.wear_suit == holder)
- return 0
-
- //OH SHIT.
- if(holder.wearer.stat == 2)
- engage()
-
-/obj/item/rig_module/self_destruct/engage()
- explosion(get_turf(src), 1, 2, 4, 5)
- if(holder && holder.wearer)
- holder.wearer.unEquip(src)
- qdel(holder)
- qdel(src)
-
-/obj/item/rig_module/self_destruct/small/engage()
- explosion(get_turf(src), 0, 0, 3, 4)
- if(holder && holder.wearer)
- holder.wearer.unEquip(src)
- qdel(holder)
- qdel(src)
diff --git a/code/modules/clothing/spacesuits/rig/modules/utility.dm b/code/modules/clothing/spacesuits/rig/modules/utility.dm
deleted file mode 100644
index 4b19d2a7753..00000000000
--- a/code/modules/clothing/spacesuits/rig/modules/utility.dm
+++ /dev/null
@@ -1,476 +0,0 @@
-/* Contains:
- * /obj/item/rig_module/device
- * /obj/item/rig_module/device/plasmacutter
- * /obj/item/rig_module/device/healthscanner
- * /obj/item/rig_module/device/drill
- * /obj/item/rig_module/device/orescanner
- * /obj/item/rig_module/device/rcd
- * /obj/item/rig_module/device/anomaly_scanner
- * /obj/item/rig_module/maneuvering_jets
- * /obj/item/rig_module/foam_sprayer
- * /obj/item/rig_module/device/broadcaster
- * /obj/item/rig_module/chem_dispenser
- * /obj/item/rig_module/chem_dispenser/injector
- * /obj/item/rig_module/voice
- * /obj/item/rig_module/device/paperdispenser
- * /obj/item/rig_module/device/pen
- * /obj/item/rig_module/device/stamp
- */
-
-/obj/item/rig_module/device
- name = "mounted device"
- desc = "Some kind of hardsuit mount."
- usable = 0
- selectable = 1
- toggleable = 0
- disruptive = 0
-
- var/device_type
- var/obj/item/device
-
-/obj/item/rig_module/device/plasmacutter
- name = "hardsuit plasma cutter"
- desc = "A lethal-looking industrial cutter."
- icon_state = "plasmacutter"
- interface_name = "plasma cutter"
- interface_desc = "A self-sustaining plasma arc capable of cutting through walls."
- suit_overlay_active = "plasmacutter"
- suit_overlay_inactive = "plasmacutter"
-
- device_type = /obj/item/gun/energy/plasmacutter
-
-/obj/item/rig_module/device/healthscanner
- name = "health scanner module"
- desc = "A hardsuit-mounted health scanner."
- icon_state = "scanner"
- interface_name = "health scanner"
- interface_desc = "Shows an informative health readout when used on a subject."
-
- device_type = /obj/item/healthanalyzer
-
-/obj/item/rig_module/device/drill
- name = "hardsuit drill mount"
- desc = "A very heavy diamond-tipped drill."
- icon_state = "drill"
- interface_name = "mounted drill"
- interface_desc = "A diamond-tipped industrial drill."
- suit_overlay_active = "mounted-drill"
- suit_overlay_inactive = "mounted-drill"
- device_type = /obj/item/pickaxe/drill/diamonddrill
-
-/obj/item/rig_module/device/orescanner
- name = "ore scanner module"
- desc = "A clunky old ore scanner."
- icon_state = "scanner"
- interface_name = "ore detector"
- interface_desc = "A sonar system for detecting large masses of ore."
- engage_string = "Begin Scan"
- usable = 1
- selectable = 0
- device_type = /obj/item/mining_scanner
-/*
-/obj/item/rig_module/device/rcd
- name = "RCD mount"
- desc = "A cell-powered rapid construction device for a hardsuit."
- icon_state = "rcd"
- interface_name = "mounted RCD"
- interface_desc = "A device for building or removing walls. Cell-powered."
- usable = 1
- engage_string = "Configure RCD"
-
- device_type = /obj/item/rcd/mounted
-*/
-/obj/item/rig_module/device/New()
- ..()
- if(device_type)
- device = new device_type(src)
- device.flags |= ABSTRACT //Abstract in the sense that it's not an item that stands alone, but rather is just there to let the module act like it.
-
-/obj/item/rig_module/device/engage(atom/target)
- if(!..() || !device)
- return 0
-
- if(!target)
- device.attack_self(holder.wearer)
- return 1
-
- var/turf/T = get_turf(target)
- if(istype(T) && !T.Adjacent(get_turf(src)))
- return 0
-
- var/resolved = target.attackby(device,holder.wearer)
- if(!resolved && device && target)
- device.afterattack(target,holder.wearer,1)
- return 1
-
-
-
-/obj/item/rig_module/chem_dispenser
- name = "mounted chemical dispenser"
- desc = "A complex web of tubing and needles suitable for hardsuit use."
- icon_state = "injector"
- usable = 1
- selectable = 0
- toggleable = 0
- disruptive = 0
-
- engage_string = "Inject"
-
- interface_name = "integrated chemical dispenser"
- interface_desc = "Dispenses loaded chemicals directly into the wearer's bloodstream."
-
- charges = list(
- list("saline-glucose", "salglu_solution", 0, 80),
- list("salicylic acid", "sal_acid", 0, 80),
- list("salbutamol", "salbutamol", 0, 80),
- list("antibiotics", "spaceacillin", 0, 80),
- list("charcoal", "charcoal", 0, 80),
- list("nutrients", "nutriment", 0, 80),
- list("potasssium iodide","potass_iodide", 0, 80),
- list("radium", "radium", 0, 80)
- )
-
- var/max_reagent_volume = 80 //Used when refilling.
-
-/obj/item/rig_module/chem_dispenser/ninja
- interface_desc = "Dispenses loaded chemicals directly into the wearer's bloodstream. This variant is made to be extremely light and flexible."
-
- //just over a syringe worth of each. Want more? Go refill. Gives the ninja another reason to have to show their face.
- charges = list(
- list("saline-glucose", "salglu_solution", 0, 20),
- list("salicylic acid", "sal_acid", 0, 20),
- list("salbutamol", "salbutamol", 0, 20),
- list("antibiotics", "spaceacillin", 0, 20),
- list("charcoal", "charcoal", 0, 20),
- list("nutrients", "nutriment", 0, 80),
- list("potasssium iodide","potass_iodide", 0, 20),
- list("radium", "radium", 0, 20)
- )
-
-
-/obj/item/rig_module/chem_dispenser/accepts_item(var/obj/item/input_item, var/mob/living/user)
-
- if(!input_item.is_open_container())
- return 0
-
- if(!input_item.reagents || !input_item.reagents.total_volume)
- to_chat(user, "\The [input_item] is empty.")
- return 0
-
- // Magical chemical filtration system, do not question it.
- var/total_transferred = 0
- for(var/datum/reagent/R in input_item.reagents.reagent_list)
- for(var/chargetype in charges)
- var/datum/rig_charge/charge = charges[chargetype]
- if(charge.display_name == R.id)
-
- var/chems_to_transfer = R.volume
-
- if((charge.charges + chems_to_transfer) > max_reagent_volume)
- chems_to_transfer = max_reagent_volume - charge.charges
-
- charge.charges += chems_to_transfer
- input_item.reagents.remove_reagent(R.id, chems_to_transfer)
- total_transferred += chems_to_transfer
-
- break
-
- if(total_transferred)
- to_chat(user, "You transfer [total_transferred] units into the suit reservoir.")
- else
- to_chat(user, "None of the reagents seem suitable.")
- return 1
-
-/obj/item/rig_module/chem_dispenser/engage(atom/target)
-
- if(!..())
- return 0
-
- var/mob/living/carbon/human/H = holder.wearer
-
- if(!charge_selected)
- to_chat(H, "You have not selected a chemical type.")
- return 0
-
- var/datum/rig_charge/charge = charges[charge_selected]
-
- if(!charge)
- return 0
-
- var/chems_to_use = 10
- if(charge.charges <= 0)
- to_chat(H, "Insufficient chems!")
- return 0
- else if(charge.charges < chems_to_use)
- chems_to_use = charge.charges
-
- var/mob/living/carbon/target_mob
- if(target)
- if(istype(target,/mob/living/carbon))
- target_mob = target
- else
- return 0
- else
- target_mob = H
-
- if(target_mob != H)
- to_chat(H, "You inject [target_mob] with [chems_to_use] unit\s of [charge.display_name].")
- to_chat(target_mob, "You feel a rushing in your veins as [chems_to_use] unit\s of [charge.display_name] [chems_to_use == 1 ? "is" : "are"] injected.")
- target_mob.reagents.add_reagent(charge.display_name, chems_to_use)
-
- charge.charges -= chems_to_use
- if(charge.charges < 0) charge.charges = 0
-
- return 1
-
-/obj/item/rig_module/chem_dispenser/combat
-
- name = "combat chemical injector"
- desc = "A complex web of tubing and needles suitable for hardsuit use."
-
- charges = list(
- list("synaptizine", "synaptizine", 0, 30),
- list("hydrocodone", "hydrocodone", 0, 30),
- list("nutrients", "nutriment", 0, 80),
- )
-
- interface_name = "combat chem dispenser"
- interface_desc = "Dispenses loaded chemicals directly into the bloodstream."
-
-
-/obj/item/rig_module/chem_dispenser/injector
-
- name = "mounted chemical injector"
- desc = "A complex web of tubing and a large needle suitable for hardsuit use."
- usable = 0
- selectable = 1
- disruptive = 1
-
- interface_name = "mounted chem injector"
- interface_desc = "Dispenses loaded chemicals via an arm-mounted injector."
-
-/obj/item/rig_module/voice
-
- name = "hardsuit voice synthesiser"
- desc = "A speaker box and sound processor."
- icon_state = "megaphone"
- usable = 1
- selectable = 0
- toggleable = 0
- disruptive = 0
-
- engage_string = "Configure Synthesiser"
-
- interface_name = "voice synthesiser"
- interface_desc = "A flexible and powerful voice modulator system."
-
- var/obj/item/voice_changer/voice_holder
-
-/obj/item/rig_module/voice/New()
- ..()
- voice_holder = new(src)
- voice_holder.active = FALSE
-
-/obj/item/rig_module/voice/installed()
- ..()
- holder.speech = src
-
-/obj/item/rig_module/voice/engage()
- if(!..())
- return 0
-
- var/choice= input("Would you like to toggle the synthesiser or set the name?") as null|anything in list("Enable","Disable","Set Name")
-
- if(!choice)
- return 0
-
- switch(choice)
- if("Enable")
- active = TRUE
- voice_holder.active = TRUE
- to_chat(usr, "You enable the speech synthesiser.")
- if("Disable")
- active = FALSE
- voice_holder.active = FALSE
- to_chat(usr, "You disable the speech synthesiser.")
- if("Set Name")
- var/raw_choice = sanitize(input(usr, "Please enter a new name.") as text|null, MAX_NAME_LEN)
- if(!raw_choice)
- return FALSE
- voice_holder.voice = raw_choice
- to_chat(usr, "You are now mimicking [voice_holder.voice].")
- return 1
-
-/obj/item/rig_module/maneuvering_jets
-
- name = "hardsuit maneuvering jets"
- desc = "A compact gas thruster system for a hardsuit."
- icon_state = "thrusters"
- usable = 1
- toggleable = 1
- selectable = 0
- disruptive = 0
-
- suit_overlay_active = "maneuvering_active"
- suit_overlay_inactive = null //"maneuvering_inactive"
-
- engage_string = "Toggle Stabilizers"
- activate_string = "Activate Thrusters"
- deactivate_string = "Deactivate Thrusters"
-
- interface_name = "maneuvering jets"
- interface_desc = "An inbuilt EVA maneuvering system that runs off the rig air supply."
-
- var/obj/item/tank/jetpack/rig/jets
-
-/obj/item/rig_module/maneuvering_jets/engage()
- if(!..())
- return 0
- jets.toggle_stabilization(usr)
- return 1
-
-/obj/item/rig_module/maneuvering_jets/activate()
-
- if(active)
- return 0
-
- active = 1
-
- spawn(1)
- if(suit_overlay_active)
- suit_overlay = suit_overlay_active
- else
- suit_overlay = null
- holder.update_icon()
-
- jets.turn_on()
- return 1
-
-/obj/item/rig_module/maneuvering_jets/deactivate()
- if(!..())
- return 0
- jets.turn_off()
- return 1
-
-/obj/item/rig_module/maneuvering_jets/New()
- ..()
- jets = new(src)
-
-/obj/item/rig_module/maneuvering_jets/installed()
- ..()
- jets.holder = holder
- jets.ion_trail.set_up(holder)
-
-/obj/item/rig_module/maneuvering_jets/removed()
- ..()
- jets.holder = null
- jets.ion_trail.set_up(jets)
-
-/obj/item/rig_module/foam_sprayer
-
-/obj/item/rig_module/device/paperdispenser
- name = "hardsuit paper dispenser"
- desc = "Crisp sheets."
- icon_state = "paper"
- interface_name = "paper dispenser"
- interface_desc = "Dispenses warm, clean, and crisp sheets of paper."
- engage_string = "Dispense"
- usable = 1
- selectable = 0
- device_type = /obj/item/paper_bin
-
-/obj/item/rig_module/device/paperdispenser/engage(atom/target)
-
- if(!..() || !device)
- return 0
-
- if(!target)
- device.attack_hand(holder.wearer)
- return 1
-
-/obj/item/rig_module/device/pen
- name = "mounted pen"
- desc = "For mecha John Hancocks."
- icon_state = "pen"
- interface_name = "mounted pen"
- interface_desc = "Signatures with style(tm)."
- engage_string = "Change color"
- usable = 1
- device_type = /obj/item/pen/multi
-
-/obj/item/rig_module/device/stamp
- name = "mounted internal affairs stamp"
- desc = "DENIED."
- icon_state = "stamp"
- interface_name = "mounted stamp"
- interface_desc = "Leave your mark."
- engage_string = "Toggle stamp type"
- usable = 1
- var/obj/iastamp //Theese were just vars, but any device would need to be an object
- var/obj/deniedstamp //Stops assigning non-objects to theese vars, which probably would break quite a bit.
-
-/obj/item/rig_module/device/stamp/New()
- ..()
- iastamp = new /obj/item/stamp/law(src)
- deniedstamp = new /obj/item/stamp/denied(src)
- iastamp.flags |= ABSTRACT
- deniedstamp.flags |= ABSTRACT
- device = iastamp
-
-/obj/item/rig_module/device/stamp/engage(atom/target)
- if(!..() || !device)
- return 0
-
- if(!target)
- if(device == iastamp)
- device = deniedstamp
- to_chat(holder.wearer, "Switched to denied stamp.")
- else if(device == deniedstamp)
- device = iastamp
- to_chat(holder.wearer, "Switched to internal affairs stamp.")
- return 1
-
-/obj/item/rig_module/welding_tank
- name = "welding fuel tank"
- desc = "A bluespace welding fuel storage tank for a rigsuit."
- icon_state = "welding_tank"
- interface_name = "mounted welding fuel tank"
- interface_desc = "A minitaure fuel tank used for storage of welding fuel, built into a hardsuit."
- engage_string = "Dispense fuel"
- usable = 1
-
- var/max_fuel = 300
-
-/obj/item/rig_module/welding_tank/New()
- ..()
-
- create_reagents(max_fuel)
- reagents.add_reagent("fuel", max_fuel)
-
-/obj/item/rig_module/welding_tank/engage(atom/target)
- if(!..() || !reagents)
- return 0
-
- if(!target)
- if(get_fuel() >= 0)
- var/obj/item/weldingtool/W = holder.wearer.get_active_hand()
- if(istype(W))
- fill_welder(W)
- else
- W = holder.wearer.get_inactive_hand()
- if(istype(W))
- fill_welder(W)
- else
- to_chat(holder.wearer, "Your welding tank is out of fuel!")
- else
- to_chat(holder.wearer, "You need to have a welding tool in one of your hands to dispense fuel.")
-
-/obj/item/rig_module/welding_tank/proc/fill_welder(obj/item/weldingtool/W)
- if(!istype(W))
- return
- W.refill(holder.wearer, src, W.maximum_fuel)
- if(!reagents.get_reagent_amount("fuel"))
- to_chat(holder.wearer, "You hear a faint dripping as your hardsuit welding tank completely empties.")
-
-/obj/item/rig_module/welding_tank/proc/get_fuel()
- return reagents.get_reagent_amount("fuel")
diff --git a/code/modules/clothing/spacesuits/rig/modules/vision.dm b/code/modules/clothing/spacesuits/rig/modules/vision.dm
deleted file mode 100644
index 33ae007ceee..00000000000
--- a/code/modules/clothing/spacesuits/rig/modules/vision.dm
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Contains
- * /obj/item/rig_module/vision
- * /obj/item/rig_module/vision/multi
- * /obj/item/rig_module/vision/meson
- * /obj/item/rig_module/vision/thermal
- * /obj/item/rig_module/vision/nvg
- * /obj/item/rig_module/vision/medhud
- * /obj/item/rig_module/vision/sechud
- */
-
-/datum/rig_vision
- var/mode
- var/obj/item/clothing/glasses/glasses
-
-/datum/rig_vision/nvg
- mode = "night vision"
-/datum/rig_vision/nvg/New()
- glasses = new /obj/item/clothing/glasses/night
-
-/datum/rig_vision/thermal
- mode = "thermal scanner"
-/datum/rig_vision/thermal/New()
- glasses = new /obj/item/clothing/glasses/thermal
-
-/datum/rig_vision/meson
- mode = "meson scanner"
-/datum/rig_vision/meson/New()
- glasses = new /obj/item/clothing/glasses/meson
-
-/datum/rig_vision/sechud
- mode = "security HUD"
-/datum/rig_vision/sechud/New()
- glasses = new /obj/item/clothing/glasses/hud/security
-
-/datum/rig_vision/medhud
- mode = "medical HUD"
-/datum/rig_vision/medhud/New()
- glasses = new /obj/item/clothing/glasses/hud/health
-
-/obj/item/rig_module/vision
-
- name = "hardsuit visor"
- desc = "A layered, translucent visor system for a hardsuit."
- icon_state = "optics"
-
- interface_name = "optical scanners"
- interface_desc = "An integrated multi-mode vision system."
-
- usable = 1
- toggleable = 1
- disruptive = 0
-
- engage_string = "Cycle Visor Mode"
- activate_string = "Enable Visor"
- deactivate_string = "Disable Visor"
-
- var/datum/rig_vision/vision
- var/list/vision_modes = list(
- /datum/rig_vision/nvg,
- /datum/rig_vision/thermal,
- /datum/rig_vision/meson
- )
-
- var/vision_index
-
-/obj/item/rig_module/vision/multi
-
- name = "hardsuit optical package"
- desc = "A complete visor system of optical scanners and vision modes."
- icon_state = "fulloptics"
-
-
- interface_name = "multi optical visor"
- interface_desc = "An integrated multi-mode vision system."
-
- vision_modes = list(/datum/rig_vision/meson,
- /datum/rig_vision/nvg,
- /datum/rig_vision/thermal,
- /datum/rig_vision/sechud,
- /datum/rig_vision/medhud)
-
-/obj/item/rig_module/vision/meson
-
- name = "hardsuit meson scanner"
- desc = "A layered, translucent visor system for a hardsuit."
- icon_state = "meson"
-
- usable = 0
-
- interface_name = "meson scanner"
- interface_desc = "An integrated meson scanner."
-
- vision_modes = list(/datum/rig_vision/meson)
-
-/obj/item/rig_module/vision/thermal
-
- name = "hardsuit thermal scanner"
- desc = "A layered, translucent visor system for a hardsuit."
- icon_state = "thermal"
-
- usable = 0
-
- interface_name = "thermal scanner"
- interface_desc = "An integrated thermal scanner."
-
- vision_modes = list(/datum/rig_vision/thermal)
-
-/obj/item/rig_module/vision/nvg
-
- name = "hardsuit night vision interface"
- desc = "A multi input night vision system for a hardsuit."
- icon_state = "night"
-
- usable = 0
-
- interface_name = "night vision interface"
- interface_desc = "An integrated night vision system."
-
- vision_modes = list(/datum/rig_vision/nvg)
-
-/obj/item/rig_module/vision/sechud
-
- name = "hardsuit security hud"
- desc = "A simple tactical information system for a hardsuit."
- icon_state = "securityhud"
-
- usable = 0
-
- interface_name = "security HUD"
- interface_desc = "An integrated security heads up display."
-
- vision_modes = list(/datum/rig_vision/sechud)
-
-/obj/item/rig_module/vision/medhud
-
- name = "hardsuit medical hud"
- desc = "A simple medical status indicator for a hardsuit."
- icon_state = "healthhud"
-
- usable = 0
-
- interface_name = "medical HUD"
- interface_desc = "An integrated medical heads up display."
-
- vision_modes = list(/datum/rig_vision/medhud)
-
-
-// There should only ever be one vision module installed in a suit.
-/obj/item/rig_module/vision/installed()
- ..()
- holder.visor = src
-
-/obj/item/rig_module/vision/engage()
-
- var/starting_up = !active
-
- if(!..() || !vision_modes)
- return 0
-
- // Don't cycle if this engage() is being called by activate().
- if(starting_up)
- to_chat(holder.wearer, "You activate your visual sensors.")
- return 1
-
- if(vision_modes.len > 1)
- vision_index++
- if(vision_index > vision_modes.len)
- vision_index = 1
- vision = vision_modes[vision_index]
-
- to_chat(holder.wearer, "You cycle your sensors to [vision.mode] mode.")
- else
- to_chat(holder.wearer, "Your sensors only have one mode.")
- return 1
-
-/obj/item/rig_module/vision/New()
- ..()
-
- if(!vision_modes)
- return
-
- vision_index = 1
- var/list/processed_vision = list()
-
- for(var/vision_mode in vision_modes)
- var/datum/rig_vision/vision_datum = new vision_mode
- if(!vision) vision = vision_datum
- processed_vision += vision_datum
-
- vision_modes = processed_vision
diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm
deleted file mode 100644
index cd4ac697406..00000000000
--- a/code/modules/clothing/spacesuits/rig/rig.dm
+++ /dev/null
@@ -1,1060 +0,0 @@
-#define ONLY_DEPLOY 1
-#define ONLY_RETRACT 2
-#define SEAL_DELAY 30
-
-/*
- * Defines the behavior of hardsuits/rigs/power armour.
- */
-
-/obj/item/rig
-
- name = "hardsuit control module"
- icon = 'icons/obj/rig_modules.dmi'
- desc = "A back-mounted hardsuit deployment and control mechanism."
- slot_flags = SLOT_BACK
- req_one_access = list()
- req_access = list()
- w_class = WEIGHT_CLASS_BULKY
-
- // These values are passed on to all component pieces.
- armor = list(melee = 10, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 75)
- min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
- max_heat_protection_temperature = SPACE_SUIT_MAX_TEMP_PROTECT
- siemens_coefficient = 0.2
- permeability_coefficient = 0.1
-
- var/interface_path = "hardsuit.tmpl"
- var/ai_interface_path = "hardsuit.tmpl"
- var/interface_title = "Hardsuit Controller"
- var/wearer_move_delay //Used for AI moving.
- var/ai_controlled_move_delay = 10
-
- // Keeps track of what this rig should spawn with.
- var/suit_type = "hardsuit"
- var/list/initial_modules
- var/chest_type = /obj/item/clothing/suit/space/new_rig
- var/helm_type = /obj/item/clothing/head/helmet/space/new_rig
- var/boot_type = /obj/item/clothing/shoes/magboots/rig
- var/glove_type = /obj/item/clothing/gloves/rig
- var/cell_type = /obj/item/stock_parts/cell/high
- var/air_type = /obj/item/tank/oxygen
-
- //Component/device holders.
- var/obj/item/tank/air_supply // Air tank, if any.
- var/obj/item/clothing/shoes/magboots/boots = null // Deployable boots, if any.
- var/obj/item/clothing/shoes/under_boots = null //Boots that are between the feet and the rig boots, if any.
- var/obj/item/clothing/suit/space/new_rig/chest // Deployable chestpiece, if any.
- var/obj/item/clothing/head/helmet/space/new_rig/helmet = null // Deployable helmet, if any.
- var/obj/item/clothing/gloves/rig/gloves = null // Deployable gauntlets, if any.
- var/obj/item/stock_parts/cell/cell // Power supply, if any.
- var/obj/item/rig_module/selected_module = null // Primary system (used with middle-click)
- var/obj/item/rig_module/vision/visor // Kinda shitty to have a var for a module, but saves time.
- var/obj/item/rig_module/voice/speech // As above.
- var/mob/living/carbon/human/wearer // The person currently wearing the rig.
- var/image/mob_icon // Holder for on-mob icon.
- var/list/installed_modules = list() // Power consumption/use bookkeeping.
-
- // Rig status vars.
- var/open = 0 // Access panel status.
- var/locked = 1 // Lock status.
- var/subverted = 0
- var/interface_locked = 0
- var/control_overridden = 0
- var/ai_override_enabled = 0
- var/security_check_enabled = 1
- var/malfunctioning = 0
- var/malfunction_delay = 0
- var/electrified = 0
- var/locked_down = 0
-
- var/seal_delay = SEAL_DELAY
- var/sealing // Keeps track of seal status independantly of NODROP.
- var/offline = 1 // Should we be applying suit maluses?
- var/offline_slowdown = 3 // If the suit is deployed and unpowered, it sets slowdown to this.
- var/active_slowdown = 3 // How much the deployed suit slows down if powered.
- var/vision_restriction
- var/offline_vision_restriction = 1 // 0 - none, 1 - welder vision, 2 - blind. Maybe move this to helmets.
- var/airtight = 1 //If set, will adjust AIRTIGHT and STOPSPRESSUREDMAGE flags on components. Otherwise it should leave them untouched.
-
- var/emp_protection = 0
- var/has_emergency_release = 1 //Allows suit to be removed from outside.
-
- // Wiring! How exciting.
- var/datum/wires/rig/wires
- var/datum/effect_system/spark_spread/spark_system
-
-/obj/item/rig/examine(mob/user)
- . = list("This is [src].")
- . += "[desc]"
- if(wearer)
- for(var/obj/item/piece in list(helmet,gloves,chest,boots))
- if(!piece || piece.loc != wearer)
- continue
- . += "[bicon(piece)] \The [piece] [piece.gender == PLURAL ? "are" : "is"] deployed."
-
- if(loc == usr)
- . += "The maintenance panel is [open ? "open" : "closed"]."
- . += "Hardsuit systems are [offline ? "offline" : "online"]."
-
-/obj/item/rig/get_cell()
- return cell
-
-/obj/item/rig/New()
- ..()
-
- item_state = icon_state
- wires = new(src)
-
- if((!req_access || !req_access.len) && (!req_one_access || !req_one_access.len))
- locked = 0
-
- spark_system = new()
- spark_system.set_up(5, 0, src)
- spark_system.attach(src)
-
- START_PROCESSING(SSobj, src)
-
- if(initial_modules && initial_modules.len)
- for(var/path in initial_modules)
- var/obj/item/rig_module/module = new path(src)
- installed_modules += module
- module.installed(src)
-
- // Create and initialize our various segments.
- if(cell_type)
- cell = new cell_type(src)
- if(air_type)
- air_supply = new air_type(src)
- if(glove_type)
- gloves = new glove_type(src)
- verbs |= /obj/item/rig/proc/toggle_gauntlets
- if(helm_type)
- helmet = new helm_type(src)
- verbs |= /obj/item/rig/proc/toggle_helmet
- helmet.item_color="[initial(icon_state)]_sealed" //For the lightswitching to know the correct string to manipulate
- if(boot_type)
- boots = new boot_type(src)
- verbs |= /obj/item/rig/proc/toggle_boots
- boots.magboot_state="[initial(icon_state)]_sealed" //For the magboot (de)activation to know the correct string to manipulate
- if(chest_type)
- chest = new chest_type(src)
- if(allowed)
- chest.allowed = allowed
- chest.slowdown = offline_slowdown
- chest.holder = src
- verbs |= /obj/item/rig/proc/toggle_chest
-
- for(var/obj/item/piece in list(gloves,helmet,boots,chest))
- if(!istype(piece))
- continue
- piece.name = "[suit_type] [initial(piece.name)]"
- piece.desc = "It seems to be part of a [src.name]."
- piece.icon_state = "[initial(icon_state)]"
- piece.min_cold_protection_temperature = min_cold_protection_temperature
- piece.max_heat_protection_temperature = max_heat_protection_temperature
- if(piece.siemens_coefficient > siemens_coefficient) //So that insulated gloves keep their insulation.
- piece.siemens_coefficient = siemens_coefficient
- piece.permeability_coefficient = permeability_coefficient
- if(islist(armor))
- var/list/L = armor
- piece.armor = L.Copy()
-
- update_icon(1)
-
-/obj/item/rig/Destroy()
- for(var/obj/item/piece in list(gloves,boots,helmet,chest))
- var/mob/living/M = piece.loc
- if(istype(M))
- M.unEquip(piece)
- qdel(piece)
- STOP_PROCESSING(SSobj, src)
- QDEL_NULL(wires)
- QDEL_NULL(spark_system)
- return ..()
-
-/obj/item/rig/proc/suit_is_deployed()
- if(!istype(wearer) || src.loc != wearer || wearer.back != src)
- return 0
- if(helm_type && !(helmet && wearer.head == helmet))
- return 0
- if(glove_type && !(gloves && wearer.gloves == gloves))
- return 0
- if(boot_type && !(boots && wearer.shoes == boots))
- return 0
- if(chest_type && !(chest && wearer.wear_suit == chest))
- return 0
- return 1
-
-/obj/item/rig/proc/reset()
- offline = 2
- flags &= ~NODROP
- if(helmet && helmet.on)
- helmet.toggle_light(wearer)
- if(boots && boots.magpulse)
- boots.attack_self(wearer)
- for(var/obj/item/piece in list(helmet,boots,gloves,chest))
- if(!piece) continue
- piece.icon_state = "[initial(icon_state)]"
- if(airtight)
- piece.flags &= ~(STOPSPRESSUREDMAGE | AIRTIGHT)
- update_icon(1)
-
-/obj/item/rig/proc/seal(mob/living/user)
- if(sealing)
- return 0
-
- if(!wearer || !user)
- return
-
- var/sealed = (flags & NODROP)
- if(sealed)
- to_chat(user, "\The [src] is already sealed!")
- return 0
-
- if(!check_power_cost(user, 1)) //need power to seal the suit
- return 0
-
- var/failed_to_seal = FALSE
-
- if(!suit_is_deployed())
- to_chat(user, "\The [src] cannot seal, as it is not fully deployed!")
- return 0
-
- flags |= NODROP
- sealing = TRUE
-
- to_chat(user, "\The [src] begins to tighten it's seals.")
- wearer.visible_message("\The [wearer]'s suit emits a quiet hum as it begins to tighten it's seals.",
- "With a quiet hum, your suit begins to seal.")
-
- if(seal_delay && !do_after(user, seal_delay, target = wearer))
- to_chat(user, "You must remain still to seal \the [src]!")
- failed_to_seal = TRUE
-
- if(!failed_to_seal)
- deploy(user)
-
- var/list/pieces_data = list(list(wearer.shoes, boots, "boots", boot_type),
- list(wearer.gloves, gloves, "gloves", glove_type),
- list(wearer.head, helmet, "helmet", helm_type),
- list(wearer.wear_suit, chest, "chest", chest_type))
-
- for(var/list/piece_data in pieces_data)
- var/obj/item/user_piece = piece_data[1]
- var/obj/item/correct_piece = piece_data[2]
- var/msg_type = piece_data[3]
- var/piece_type = piece_data[4]
-
- if(!user_piece || !piece_type)
- continue
-
- if(user_piece != correct_piece)
- to_chat(user, "\The [user_piece] is blocking \the [src] from deploying.")
- failed_to_seal = TRUE
-
- if(seal_delay && !do_after(user, seal_delay, needhand = 0, target = wearer))
- to_chat(user, "You must remain still to seal \the [src]!")
- failed_to_seal = TRUE
-
- if(failed_to_seal)
- break
-
- correct_piece.icon_state = "[initial(icon_state)]_sealed"
- switch(msg_type)
- if("boots")
- to_chat(wearer, "\The [correct_piece] seal around your feet.")
- correct_piece.icon_state = "[initial(icon_state)]_sealed0" //Solution to not need a sprite for off, on, and unused magboots.
- if(user != wearer)
- to_chat(user, "\The [correct_piece] has been sealed.")
- wearer.update_inv_shoes()
- if("gloves")
- to_chat(wearer, "\The [correct_piece] tighten around your fingers and wrists.")
- if(user != wearer)
- to_chat(user, "\The [correct_piece] has been sealed.")
- wearer.update_inv_gloves()
- if("chest")
- to_chat(wearer, "\The [correct_piece] cinches tight again your chest.")
- if(user != wearer)
- to_chat(user, "\The [correct_piece] has been sealed.")
- wearer.update_inv_wear_suit()
- if("helmet")
- to_chat(wearer, "\The [correct_piece] hisses closed.")
- correct_piece.icon_state = "[initial(icon_state)]_sealed0" //Solution to not need a sprite for off, on, and unused helmet light.
- if(user != wearer)
- to_chat(user, "\The [correct_piece] has been sealed.")
- wearer.update_inv_head()
- if(helmet)
- helmet.update_light(wearer)
-
- correct_piece.armor["bio"] = 100
-
- sealing = FALSE
-
- if(failed_to_seal)
- for(var/obj/item/piece in list(helmet, boots, gloves, chest))
- if(!piece)
- continue
- piece.icon_state = "[initial(icon_state)]"
- flags &= ~NODROP
- if(airtight)
- update_component_sealed()
- update_icon(1)
- return 0
-
- if(user != wearer)
- to_chat(user, "\The [src] has been loosened.")
- to_chat(wearer, "Your entire suit tightens around you as the components lock into place.")
- if(airtight)
- update_component_sealed()
- update_icon(1)
-
-/obj/item/rig/proc/unseal(mob/living/user)
- if(sealing)
- return 0
-
- if(!wearer || !user)
- return
-
- var/sealed = (flags & NODROP)
- if(!sealed)
- to_chat(user, "\The [src] is already unsealed!")
- return 0
-
- sealing = TRUE
-
- var/failed_to_seal = FALSE
-
- if(!suit_is_deployed())
- to_chat(user, "\The [src] cannot unseal, as it is not fully deployed!")
- failed_to_seal = TRUE
-
- if(!failed_to_seal)
- if(user != wearer)
- to_chat(user, "\The [src] begins to loosen it's seals.")
- wearer.visible_message("\The [wearer]'s suit emits a quiet hum as it begins to loosen it's seals.",
- "With a quiet hum, your suit begins to unseal.")
-
- if(seal_delay && !do_after(user, seal_delay, target = wearer))
- to_chat(user, "You must remain still to unseal \the [src]!")
- failed_to_seal = TRUE
-
- if(!failed_to_seal)
- var/list/pieces_data = list(list(wearer.shoes, boots, "boots", boot_type),
- list(wearer.gloves, gloves, "gloves", glove_type),
- list(wearer.head, helmet, "helmet", helm_type),
- list(wearer.wear_suit, chest, "chest", chest_type))
-
- for(var/list/piece_data in pieces_data)
- var/obj/item/user_piece = piece_data[1]
- var/obj/item/correct_piece = piece_data[2]
- var/msg_type = piece_data[3]
- var/piece_type = piece_data[4]
-
- if(!correct_piece || !piece_type)
- continue
-
- if(user_piece != correct_piece)
- to_chat(user, "\The [user_piece] is blocking \the [src] from deploying.")
- failed_to_seal = TRUE
-
- if(seal_delay && !do_after(user, seal_delay, needhand = 0, target = wearer))
- to_chat(user, "You must remain still to unseal \the [src]!")
- failed_to_seal = TRUE
-
- if(failed_to_seal)
- break
-
- correct_piece.icon_state = "[initial(icon_state)]"
- switch(msg_type)
- if("boots")
- to_chat(wearer, "\The [correct_piece] relax [correct_piece.p_their()] grip on your legs.")
- if(user != wearer)
- to_chat(user, "\The [correct_piece] has been unsealed.")
- wearer.update_inv_shoes()
- if("gloves")
- to_chat(wearer, "\The [correct_piece] become loose around your fingers.")
- if(user != wearer)
- to_chat(user, "\The [correct_piece] has been unsealed.")
- wearer.update_inv_gloves()
- if("chest")
- to_chat(wearer, "\The [correct_piece] releases your chest.")
- if(user != wearer)
- to_chat(user, "\The [correct_piece] has been unsealed.")
- wearer.update_inv_wear_suit()
- if("helmet")
- to_chat(wearer, "\The [correct_piece] hisses open.")
- if(user != wearer)
- to_chat(user, "\The [correct_piece] has been unsealed.")
- wearer.update_inv_head()
- if(helmet)
- helmet.update_light(wearer)
-
- correct_piece.armor["bio"] = armor["bio"]
-
- sealing = FALSE
-
- if(failed_to_seal)
- for(var/obj/item/piece in list(gloves, chest))
- if(!piece)
- continue
- piece.icon_state = "[initial(icon_state)]_sealed"
- if(helmet)
- helmet.icon_state = "[initial(icon_state)]_sealed[helmet.on]"
- if(boots)
- boots.icon_state = "[initial(icon_state)]_sealed[boots.magpulse]"
- if(airtight)
- update_component_sealed()
- update_icon(1)
- return 0
-
- if(user != wearer)
- to_chat(user, "\The [src] has been unsealed.")
- to_chat(wearer, "Your entire suit loosens as the components relax.")
-
- flags &= ~NODROP
-
- for(var/obj/item/rig_module/module in installed_modules)
- module.deactivate()
-
- if(airtight)
- update_component_sealed()
- update_icon(1)
-
-/obj/item/rig/proc/update_component_sealed()
- if(istype(boots) && !(flags & NODROP) && boots.magpulse) //If we have (active) boots and unsealed the suit, we deactivate the magboots.
- boots.attack_self(wearer)
- if(istype(helmet) && !(flags & NODROP) && helmet.on) //If we have an (active) headlamp and unsealed the suit, we deactivate the headlamp.
- helmet.toggle_light(wearer)
- for(var/obj/item/piece in list(helmet,boots,gloves,chest))
- if(!(flags & NODROP))
- piece.flags &= ~(STOPSPRESSUREDMAGE | AIRTIGHT)
- else
- piece.flags |= STOPSPRESSUREDMAGE | AIRTIGHT
-
-/obj/item/rig/process()
- // If we've lost any parts, grab them back.
- var/mob/living/M
- for(var/obj/item/piece in list(gloves,boots,helmet,chest))
- if(piece.loc != src && !(wearer && piece.loc == wearer))
- if(istype(piece.loc, /mob/living))
- M = piece.loc
- M.unEquip(piece)
- piece.forceMove(src)
-
- if(cell && cell.charge > 0 && electrified > 0)
- electrified--
-
- if(malfunction_delay > 0)
- malfunction_delay--
- else if(malfunctioning)
- malfunctioning--
- malfunction()
-
- if(!istype(wearer) || loc != wearer || wearer.back != src || !(flags & NODROP) || !cell || cell.charge <= 0)
- if(!cell || cell.charge <= 0)
- if(electrified > 0)
- electrified = 0
- if(!offline)
- if(istype(wearer))
- if(flags & NODROP)
- if(offline_slowdown < 3)
- to_chat(wearer, "Your suit beeps stridently, and suddenly goes dead.")
- else
- to_chat(wearer, "Your suit beeps stridently, and suddenly you're wearing a leaden mass of metal and plastic composites instead of a powered suit.")
- if(offline_vision_restriction == 1)
- to_chat(wearer, "The suit optics flicker and die, leaving you with restricted vision.")
- else if(offline_vision_restriction == 2)
- to_chat(wearer, "The suit optics drop out completely, drowning you in darkness.")
- if(!offline)
- offline = 1
- if(istype(wearer) && wearer.wearing_rig)
- wearer.wearing_rig = null
- else
- if(offline)
- offline = 0
- if(istype(wearer) && !wearer.wearing_rig)
- wearer.wearing_rig = src
- chest.slowdown = active_slowdown
-
- if(offline)
- if(offline == 1)
- for(var/obj/item/rig_module/module in installed_modules)
- module.deactivate()
- offline = 2
- chest.slowdown = offline_slowdown
- return
-
-
- for(var/obj/item/rig_module/module in installed_modules)
- cell.use(module.process()*10)
-
-/obj/item/rig/proc/check_power_cost(var/mob/living/user, var/cost, var/use_unconcious, var/obj/item/rig_module/mod, var/user_is_ai)
- if(!istype(user))
- return 0
-
- var/fail_msg
-
- if(!user_is_ai)
- var/mob/living/carbon/human/H = user
- if(istype(H) && H.back != src)
- fail_msg = "You must be wearing \the [src] to do this."
- else if(user.incorporeal_move)
- fail_msg = "You must be solid to do this."
- if(sealing)
- fail_msg = "The hardsuit is in the process of adjusting seals and cannot be activated."
- else if(!fail_msg && ((use_unconcious && user.stat > 1) || (!use_unconcious && user.stat)))
- fail_msg = "You are in no fit state to do that."
- else if(!cell)
- fail_msg = "There is no cell installed in the suit."
- else if(cost && cell.charge < cost * 10) //TODO: Cellrate?
- fail_msg = "Not enough stored power."
-
- if(fail_msg)
- to_chat(user, "[fail_msg]")
- return 0
-
- // This is largely for cancelling stealth and whatever.
- if(mod && mod.disruptive)
- for(var/obj/item/rig_module/module in (installed_modules - mod))
- if(module.active && module.disruptable)
- module.deactivate()
-
- cell.use(cost*10)
- return 1
-
-/obj/item/rig/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.inventory_state)
- if(!user)
- return
-
- ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, ((src.loc != user) ? ai_interface_path : interface_path), interface_title, 480, 550, state = state)
- ui.open()
- ui.set_auto_update(1)
-
-/obj/item/rig/ui_data(mob/user, ui_key = "main", datum/topic_state/state = GLOB.inventory_state)
- var/data[0]
-
- data["primarysystem"] = null
- if(selected_module)
- data["primarysystem"] = "[selected_module.interface_name]"
-
- data["ai"] = 0
- if(src.loc != user)
- data["ai"] = 1
-
- var/is_sealed = (flags & NODROP) //1 if NODROP, 0 if no-nodrop
- data["seals"] = "[!is_sealed]" //1 if not NODROP (unsealed), 0 if NODROP (sealed)
- data["sealing"] = "[src.sealing]"
- data["helmet"] = (helmet ? "[helmet.name]" : "None.")
- data["gauntlets"] = (gloves ? "[gloves.name]" : "None.")
- data["boots"] = (boots ? "[boots.name]" : "None.")
- data["chest"] = (chest ? "[chest.name]" : "None.")
-
- data["charge"] = cell ? round(cell.charge,1) : 0
- data["maxcharge"] = cell ? cell.maxcharge : 0
- data["chargestatus"] = cell ? Floor((cell.charge/cell.maxcharge)*50) : 0
-
- data["emagged"] = subverted
- data["coverlock"] = locked
- data["interfacelock"] = interface_locked
- data["aicontrol"] = control_overridden
- data["aioverride"] = ai_override_enabled
- data["securitycheck"] = security_check_enabled
- data["malf"] = malfunction_delay
-
-
- var/list/module_list = list()
- var/i = 1
- for(var/obj/item/rig_module/module in installed_modules)
- var/list/module_data = list(
- "index" = i,
- "name" = "[module.interface_name]",
- "desc" = "[module.interface_desc]",
- "can_use" = "[module.usable]",
- "can_select" = "[module.selectable]",
- "can_toggle" = "[module.toggleable]",
- "is_active" = "[module.active]",
- "engagecost" = module.use_power_cost*10,
- "activecost" = module.active_power_cost*10,
- "passivecost" = module.passive_power_cost*10,
- "engagestring" = module.engage_string,
- "activatestring" = module.activate_string,
- "deactivatestring" = module.deactivate_string,
- "damage" = module.damage
- )
-
- if(module.charges && module.charges.len)
-
- module_data["charges"] = list()
- var/datum/rig_charge/selected = module.charges[module.charge_selected]
- module_data["chargetype"] = selected ? "[selected.display_name]" : "none"
-
- for(var/chargetype in module.charges)
- var/datum/rig_charge/charge = module.charges[chargetype]
- module_data["charges"] += list(list("caption" = "[chargetype] ([charge.charges])", "index" = "[chargetype]"))
-
- module_list += list(module_data)
- i++
-
- if(module_list.len)
- data["modules"] = module_list
-
- return data
-
-/obj/item/rig/update_icon(var/update_mob_icon)
-
- //TODO: Maybe consider a cache for this (use mob_icon as blank canvas, use suit icon overlay).
- overlays.Cut()
- if(!mob_icon || update_mob_icon)
- var/species_icon = 'icons/mob/rig_back.dmi'
- // Since setting mob_icon will override the species checks in
- // update_inv_wear_suit(), handle species checks here.
- if(wearer && sprite_sheets && sprite_sheets[wearer.dna.species.name])
- species_icon = sprite_sheets[wearer.dna.species.name]
- mob_icon = image("icon" = species_icon, "icon_state" = "[icon_state]")
-
- if(installed_modules.len)
- for(var/obj/item/rig_module/module in installed_modules)
- if(module.suit_overlay)
- chest.overlays += image("icon" = 'icons/mob/rig_modules.dmi', "icon_state" = "[module.suit_overlay]", "dir" = SOUTH)
-
- if(wearer)
- wearer.update_inv_shoes()
- wearer.update_inv_gloves()
- wearer.update_inv_head()
- wearer.update_inv_wear_suit()
- wearer.update_inv_back()
- return
-
-/obj/item/rig/proc/check_suit_access(var/mob/living/carbon/human/user)
-
- if(!security_check_enabled)
- return 1
-
- if(istype(user))
- if(malfunction_check(user))
- return 0
- if(user.back != src)
- return 0
- else if(!src.allowed(user))
- to_chat(user, "Unauthorized user. Access denied.")
- return 0
-
- else if(!ai_override_enabled)
- to_chat(user, "Synthetic access disabled. Please consult hardware provider.")
- return 0
-
- return 1
-
-/obj/item/rig/Topic(href,href_list)
- if(!check_suit_access(usr))
- return 0
-
- if(href_list["toggle_piece"])
- if(ishuman(usr) && (usr.stat || usr.stunned || usr.lying))
- return 0
- toggle_piece(href_list["toggle_piece"], usr)
- else if(href_list["toggle_seals"])
- if(flags & NODROP)
- unseal(usr)
- else
- seal(usr)
- else if(href_list["interact_module"])
- var/module_index = text2num(href_list["interact_module"])
-
- if(module_index > 0 && module_index <= installed_modules.len)
- var/obj/item/rig_module/module = installed_modules[module_index]
- switch(href_list["module_mode"])
- if("activate")
- module.activate()
- if("deactivate")
- module.deactivate()
- if("engage")
- module.engage()
- if("select")
- selected_module = module
- if("select_charge_type")
- module.charge_selected = href_list["charge_type"]
- else if(href_list["toggle_ai_control"])
- ai_override_enabled = !ai_override_enabled
- notify_ai("Synthetic suit control has been [ai_override_enabled ? "enabled" : "disabled"].")
- else if(href_list["toggle_suit_lock"])
- locked = !locked
-
- usr.set_machine(src)
- add_fingerprint(usr)
- return 0
-
-/obj/item/rig/proc/notify_ai(var/message)
- if(!message || !installed_modules || !installed_modules.len)
- return
- for(var/obj/item/rig_module/module in installed_modules)
- for(var/mob/living/silicon/ai/ai in module.contents)
- if(ai && ai.client && !ai.stat)
- to_chat(ai, "[message]")
-
-/obj/item/rig/equipped(mob/living/carbon/human/M, slot)
- ..()
- if(!istype(M) || slot != slot_back)
- return //we don't care about picking up/nonhumans
-
- spawn(1) //equipped() is called BEFORE the item is actually set as the slot
-
- if(seal_delay > 0 && istype(M) && M.back == src)
- M.visible_message("[M] starts putting on \the [src]...", "You start putting on \the [src]...")
- if(!do_after(M, seal_delay, target = M))
- if(M && M.back == src)
- M.unEquip(src)
- M.put_in_hands(src)
- return
-
- if(istype(M) && M.back == src)
- M.visible_message("[M] struggles into \the [src].", "You struggle into \the [src].")
- wearer = M
- wearer.wearing_rig = src
- if(has_emergency_release)
- M.verbs |= /obj/item/rig/proc/emergency_release
- update_icon()
-
-/obj/item/rig/proc/toggle_piece(var/piece, var/mob/living/user, var/deploy_mode, var/force)
- if(!istype(wearer) || wearer.back != src)
- if(force) //can only force retracting sorry
- for(var/obj/item/uneq_piece in list(helmet, gloves, boots, chest))
- if(uneq_piece)
- if(isliving(uneq_piece.loc))
- var/mob/living/L = uneq_piece.loc
- L.unEquip(uneq_piece, 1)
- if(uneq_piece == boots)
- if(under_boots)
- if(L.equip_to_slot_if_possible(under_boots, slot_shoes))
- under_boots = null
- else
- to_chat(user, "Somehow, your [under_boots] got stuck to the [boots], and were retracted with them. ((This shouldn't happen, bug report this.))")
- uneq_piece.forceMove(src)
- return 0
-
- if(sealing || !cell || !cell.charge)
- return 0
-
- if(!(deploy_mode == ONLY_RETRACT && force)) //This should be the case while stripping, stripping does trigger the if statement below.
- if(user == wearer && user.incapacitated()) // If the user isn't wearing the suit it's probably an AI.
- return 0
-
- var/obj/item/check_slot
- var/equip_to
- var/obj/item/use_obj
-
- switch(piece)
- if("helmet")
- equip_to = slot_head
- use_obj = helmet
- check_slot = wearer.head
- if("gauntlets")
- equip_to = slot_gloves
- use_obj = gloves
- check_slot = wearer.gloves
- if("boots")
- equip_to = slot_shoes
- use_obj = boots
- check_slot = wearer.shoes
- if("chest")
- equip_to = slot_wear_suit
- use_obj = chest
- check_slot = wearer.wear_suit
-
- if(use_obj)
- if(check_slot == use_obj && deploy_mode != ONLY_DEPLOY) //user is wearing it, retract it if not forced to deploy
- if((flags & NODROP) && equip_to != slot_head && !force) //you can only retract the helmet if the suit isn't unsealed
- to_chat(user, "You can't retract \the [use_obj] while the suit is sealed!")
- return
-
- var/mob/living/to_strip
- if(wearer)
- to_strip = wearer
- else if(isliving(use_obj.loc))
- to_strip = use_obj.loc
-
- if(to_strip)
- to_strip.unEquip(use_obj, 1)
- if(use_obj == boots)
- if(under_boots)
- if(to_strip.equip_to_slot_if_possible(under_boots, slot_shoes))
- under_boots = null
- else
- to_chat(user, "Somehow, your [under_boots] got stuck to the [boots], and were retracted with them. ((This shouldn't happen, bug report this.))")
- use_obj.forceMove(src)
- if(wearer)
- to_chat(wearer, "Your [use_obj] [use_obj.gender == PLURAL ? "retract" : "retracts"] swiftly.")
-
- else if(deploy_mode != ONLY_RETRACT)
- if(check_slot)
- if(check_slot != use_obj) //If use_obj is already in check_slot, silently bail. Otherwise, tell the user why the part didn't deploy.
- if(use_obj == boots)
- under_boots = check_slot
- wearer.unEquip(under_boots)
- under_boots.forceMove(src)
- else
- to_chat(wearer, "You are unable to deploy \the [piece] as \the [check_slot] [check_slot.gender == PLURAL ? "are" : "is"] in the way.")
- return
- use_obj.forceMove(wearer)
- if(!wearer.equip_to_slot_if_possible(use_obj, equip_to, FALSE, TRUE))
- use_obj.forceMove(src)
- else
- if(wearer)
- to_chat(wearer, "Your [use_obj.name] [use_obj.gender == PLURAL ? "deploy" : "deploys"] swiftly.")
-
- if(piece == "helmet" && helmet)
- helmet.update_light(wearer)
-
-/obj/item/rig/proc/deploy(mob/user)
- if(!wearer || !user)
- return 0
-
- if(flags & NODROP) //We need to check if we have the part, the person is wearing something in the parts slot, and if yes, are they the same.
- if(helmet && wearer.head && wearer.head != helmet)
- to_chat(user, "\The [wearer.head] is blocking \the [src] from deploying!")
- return 0
- if(gloves && wearer.gloves && wearer.gloves != gloves)
- to_chat(user, "\The [wearer.gloves] is preventing \the [src] from deploying!")
- return 0
- /*if(boots && wearer.shoes && wearer.shoes != boots)
- to_chat(user, "\The [wearer.shoes] is preventing \the [src] from deploying!")
- return 0*/
- if(chest && wearer.wear_suit && wearer.wear_suit != chest)
- to_chat(user, "\The [wearer.wear_suit] is preventing \the [src] from deploying!")
- return 0
-
-
- for(var/piece in list("helmet", "gauntlets", "chest", "boots"))
- toggle_piece(piece, user, ONLY_DEPLOY)
-
-/obj/item/rig/dropped(var/mob/user)
- ..()
- user.verbs -= /obj/item/rig/proc/emergency_release
- for(var/piece in list("helmet","gauntlets","chest","boots"))
- toggle_piece(piece, user, ONLY_RETRACT, 1)
- if(wearer)
- wearer.wearing_rig = null
- wearer = null
-
-//Todo
-/obj/item/rig/proc/malfunction()
- return 0
-
-/obj/item/rig/emp_act(severity_class)
- //set malfunctioning
- if(emp_protection < 30) //for ninjas, really.
- malfunctioning += 10
- if(malfunction_delay <= 0)
- malfunction_delay = max(malfunction_delay, round(30/severity_class))
-
- //drain some charge
- if(cell) cell.emp_act(severity_class + 15)
-
- //possibly damage some modules
- take_hit((100/severity_class), "electrical pulse", 1)
-
-/obj/item/rig/proc/shock(mob/user)
- if(get_dist(src, user) <= 1) //Needs to be adjecant to the rig to get shocked.
- if(electrocute_mob(user, cell, src)) //electrocute_mob() handles removing charge from the cell, no need to do that here.
- spark_system.start()
- if(user.stunned)
- return 1
- return 0
-
-/obj/item/rig/proc/take_hit(damage, source, is_emp=0)
-
- if(!installed_modules.len)
- return
-
- var/chance
- if(!is_emp)
- chance = 2*max(0, damage - (chest? chest.breach_threshold : 0))
- else
- //Want this to be roughly independant of the number of modules, meaning that X emp hits will disable Y% of the suit's modules on average.
- //that way people designing hardsuits don't have to worry (as much) about how adding that extra module will affect emp resiliance by 'soaking' hits for other modules
- chance = 2*max(0, damage - emp_protection)*min(installed_modules.len/15, 1)
-
- if(!prob(chance))
- return
-
- //deal addition damage to already damaged module first.
- //This way the chances of a module being disabled aren't so remote.
- var/list/valid_modules = list()
- var/list/damaged_modules = list()
- for(var/obj/item/rig_module/module in installed_modules)
- if(module.damage < 2)
- valid_modules |= module
- if(module.damage > 0)
- damaged_modules |= module
-
- var/obj/item/rig_module/dam_module = null
- if(damaged_modules.len)
- dam_module = pick(damaged_modules)
- else if(valid_modules.len)
- dam_module = pick(valid_modules)
-
- if(!dam_module) return
-
- dam_module.damage++
-
- if(!source)
- source = "hit"
-
- if(wearer)
- if(dam_module.damage >= 2)
- to_chat(wearer, "The [source] has disabled your [dam_module.interface_name]!")
- else
- to_chat(wearer, "The [source] has damaged your [dam_module.interface_name]!")
- dam_module.deactivate()
-
-/obj/item/rig/proc/malfunction_check(var/mob/living/carbon/human/user)
- if(malfunction_delay)
- if(offline)
- to_chat(user, "The suit is completely unresponsive.")
- else
- to_chat(user, "ERROR: Hardware fault. Rebooting interface...")
- return 1
- return 0
-
-/obj/item/rig/proc/ai_can_move_suit(var/mob/user, var/check_user_module = 0, var/check_for_ai = 0)
-
- if(check_for_ai)
- if(!(locate(/obj/item/rig_module/ai_container) in contents))
- return 0
- var/found_ai
- for(var/obj/item/rig_module/ai_container/module in contents)
- if(module.damage >= 2)
- continue
- if(module.integrated_ai && module.integrated_ai.client && !module.integrated_ai.stat)
- found_ai = 1
- break
- if(!found_ai)
- return 0
-
- if(check_user_module)
- if(!user || !user.loc || !user.loc.loc)
- return 0
- var/obj/item/rig_module/ai_container/module = user.loc.loc
- if(!istype(module) || module.damage >= 2)
- to_chat(user, "Your host module is unable to interface with the suit.")
- return 0
-
- if(offline || !cell || !cell.charge || locked_down)
- if(user)
- to_chat(user, "Your host rig is unpowered and unresponsive.")
- return 0
- if(!wearer || wearer.back != src)
- if(user)
- to_chat(user, "Your host rig is not being worn.")
- return 0
- if(!wearer.stat && !control_overridden && !ai_override_enabled)
- if(user)
- to_chat(user, "You are locked out of the suit servo controller.")
- return 0
- return 1
-
-/obj/item/rig/proc/force_rest(var/mob/user)
- if(!ai_can_move_suit(user, check_user_module = 1))
- return
- wearer.lay_down()
- to_chat(user, "\The [wearer] is now [wearer.resting ? "resting" : "getting up"].")
-
-/obj/item/rig/proc/forced_move(var/direction, var/mob/user)
-
- // Why is all this shit in client/Move()? Who knows?
- if(world.time < wearer_move_delay)
- return
-
- if(!wearer || !wearer.loc || !ai_can_move_suit(user, check_user_module = 1))
- return
-
- //This is sota the goto stop mobs from moving var
- if(wearer.notransform || !wearer.canmove)
- return
-
- if(!wearer.lastarea)
- wearer.lastarea = get_area(wearer.loc)
-
- if((istype(wearer.loc, /turf/space)) || (wearer.lastarea.has_gravity == 0))
- if(!wearer.Process_Spacemove(0))
- return 0
-
- if(malfunctioning)
- direction = pick(GLOB.cardinal)
-
- // Inside an object, tell it we moved.
- if(isobj(wearer.loc) || ismob(wearer.loc))
- var/atom/O = wearer.loc
- return O.relaymove(wearer, direction)
-
- if(isturf(wearer.loc))
- if(wearer.restrained())//Why being pulled while cuffed prevents you from moving
- for(var/mob/M in range(wearer, 1))
- if(M.pulling == wearer)
- if(!M.restrained() && M.stat == 0 && M.canmove && wearer.Adjacent(M))
- to_chat(user, "Your host is restrained! They can't move!")
- return 0
- else
- M.stop_pulling()
-
- // AIs are a bit slower than regular and ignore move intent.
- wearer_move_delay = world.time + ai_controlled_move_delay
-
- if(wearer.buckled) //if we're buckled to something, tell it we moved.
- return wearer.buckled.relaymove(wearer, direction)
-
- if(cell.use(200)) //Arbitrary, TODO
- wearer.Move(get_step(get_turf(wearer),direction),direction)
-
-// This returns the rig if you are contained inside one, but not if you are wearing it
-/atom/proc/get_rig()
- if(loc)
- return loc.get_rig()
- return null
-
-/obj/item/rig/get_rig()
- return src
-
-/mob/living/carbon/human/get_rig()
- if(istype(back,/obj/item/rig))
- return back
- else
- return null
-
-/obj/item/rig/proc/emergency_release()
- set name = "Suit Emergency Release"
- set desc = "Activate the suits emergency release system."
- set category = "Object"
- set src in oview(1)
- var/obj/item/rig/T = get_rig()
- return T.do_emergency_release(usr)
-
-/obj/item/rig/proc/do_emergency_release(var/mob/living/user)
- if(!can_touch(user, wearer) || !has_emergency_release)
- return can_touch(user,wearer)
- usr.visible_message("[user] starts activating \the [src] emergency seals release!")
- if(!do_after(user, 240, target = wearer))
- to_chat(user, "You need to focus on activating the emergency release.")
- return 0
- usr.visible_message("[user] activated \the [src] emergency seals release!")
- malfunctioning += 1
- malfunction_delay = 30
- unseal(user)
- return 1
-
-/obj/item/rig/proc/can_touch(var/mob/user, var/mob/wearer)
- if(!user)
- return 0
- if(!wearer.Adjacent(user))
- return 0
- if(user.restrained())
- to_chat(user, "You need your hands free for this.")
- return 0
- if(user.stat || user.paralysis || user.sleeping || user.lying || user.IsWeakened())
- return 0
- return 1
-#undef ONLY_DEPLOY
-#undef ONLY_RETRACT
-#undef SEAL_DELAY
diff --git a/code/modules/clothing/spacesuits/rig/rig_armormod.dm b/code/modules/clothing/spacesuits/rig/rig_armormod.dm
deleted file mode 100644
index 68daec45b5a..00000000000
--- a/code/modules/clothing/spacesuits/rig/rig_armormod.dm
+++ /dev/null
@@ -1,21 +0,0 @@
-/obj/item/clothing/suit/space/new_rig/calc_breach_damage()
- ..()
- holder.update_armor() //New dammage, new armormultiplikator.
- return damage
-
-/obj/item/rig/proc/update_armor()
- var/multi = 1 //Multiplicative modification to the armor, maybe add an additive later on
- if(chest)
- multi *= (100 - chest.damage) / 100 //If we have some breaches, lower the armor value.
-
- //TODO check for other armor mods, likely modules, which need to be coded.
-
- for(var/obj/item/piece in list(gloves, helmet, boots, chest))
- if(!istype(piece)) //Do we have the piece
- continue
- if(islist(armor)) //Did we even give them some armor, if this is the case, the list should be initialized from New()
- var/list/L = armor
- for(var/armortype in L)
- piece.armor[armortype] = L[armortype]*multi
-
-//Perfect place to also add something like shield modules, or any other hit_reaction modules check.
diff --git a/code/modules/clothing/spacesuits/rig/rig_attackby.dm b/code/modules/clothing/spacesuits/rig/rig_attackby.dm
deleted file mode 100644
index b48e17b2c41..00000000000
--- a/code/modules/clothing/spacesuits/rig/rig_attackby.dm
+++ /dev/null
@@ -1,196 +0,0 @@
-/obj/item/rig/attackby(obj/item/W as obj, mob/user as mob)
-
- if(!istype(user,/mob/living)) return 0
-
- if(electrified != 0)
- if(shock(user)) //Handles removing charge from the cell, as well. No need to do that here.
- return
-
- // Pass repair items on to the chestpiece.
- if(chest && (istype(W,/obj/item/stack) || istype(W, /obj/item/weldingtool)))
- return chest.attackby(W,user)
-
- // Lock or unlock the access panel.
- if(W.GetID())
- if(subverted)
- locked = 0
- to_chat(user, "It looks like the locking system has been shorted out.")
- return
-
- if((!req_access || !req_access.len) && (!req_one_access || !req_one_access.len))
- locked = 0
- to_chat(user, "\The [src] doesn't seem to have a locking mechanism.")
- return
-
- if(security_check_enabled && !src.allowed(user))
- to_chat(user, "Access denied.")
- return
-
- locked = !locked
- to_chat(user, "You [locked ? "lock" : "unlock"] \the [src] access panel.")
- return
-
- else if(istype(W,/obj/item/crowbar))
-
- if(!open && locked)
- to_chat(user, "The access panel is locked shut.")
- return
-
- open = !open
- to_chat(user, "You [open ? "open" : "close"] the access panel.")
- return
-
- if(open)
-
- // Hacking.
- if(istype(W,/obj/item/wirecutters) || istype(W,/obj/item/multitool))
- if(open)
- wires.Interact(user)
- else
- to_chat(user, "You can't reach the wiring.")
- return
- // Air tank.
- if(istype(W,/obj/item/tank)) //Todo, some kind of check for suits without integrated air supplies.
-
- if(air_supply)
- to_chat(user, "\The [src] already has a tank installed.")
- return
-
- user.unEquip(W)
- air_supply = W
- W.forceMove(src)
- to_chat(user, "You slot [W] into [src] and tighten the connecting valve.")
- return
-
- // Check if this is a hardsuit upgrade or a modification.
- else if(istype(W,/obj/item/rig_module))
-
- if(istype(src.loc,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = src.loc
- if(H.back == src)
- to_chat(user, "You can't install a hardsuit module while the suit is being worn.")
- return 1
-
- if(!installed_modules) installed_modules = list()
- if(installed_modules.len)
- for(var/obj/item/rig_module/installed_mod in installed_modules)
- if(!installed_mod.redundant && istype(installed_mod,W))
- to_chat(user, "The hardsuit already has a module of that class installed.")
- return 1
-
- var/obj/item/rig_module/mod = W
- to_chat(user, "You begin installing \the [mod] into \the [src].")
- if(!do_after(user, 40 * W.toolspeed, target = src))
- return
- if(!user || !W)
- return
- to_chat(user, "You install \the [mod] into \the [src].")
- user.unEquip(mod)
- installed_modules |= mod
- mod.forceMove(src)
- mod.installed(src)
- update_icon()
- return 1
-
- else if(!cell && istype(W,/obj/item/stock_parts/cell))
-
- to_chat(user, "You jack \the [W] into \the [src]'s battery mount.")
- user.unEquip(W)
- W.forceMove(src)
- src.cell = W
- return
-
- else if(istype(W,/obj/item/wrench))
-
- if(!air_supply)
- to_chat(user, "There is not tank to remove.")
- return
-
- if(user.r_hand && user.l_hand)
- air_supply.forceMove(get_turf(user))
- else
- user.put_in_hands(air_supply)
- to_chat(user, "You detach and remove \the [air_supply].")
- air_supply = null
- return
-
- else if(istype(W,/obj/item/screwdriver))
-
- var/list/current_mounts = list()
- if(cell) current_mounts += "cell"
- if(installed_modules && installed_modules.len) current_mounts += "system module"
-
- var/to_remove = input("Which would you like to modify?") as null|anything in current_mounts
- if(!to_remove)
- return
-
- if(istype(src.loc,/mob/living/carbon/human) && to_remove != "cell")
- var/mob/living/carbon/human/H = src.loc
- if(H.back == src)
- to_chat(user, "You can't remove an installed device while the hardsuit is being worn.")
- return
-
- switch(to_remove)
-
- if("cell")
-
- if(cell)
- to_chat(user, "You detatch \the [cell] from \the [src]'s battery mount.")
- for(var/obj/item/rig_module/module in installed_modules)
- module.deactivate()
- if(user.r_hand && user.l_hand)
- cell.forceMove(get_turf(user))
- else
- user.put_in_hands(cell)
- cell = null
- else
- to_chat(user, "There is nothing loaded in that mount.")
-
- if("system module")
-
- var/list/possible_removals = list()
- for(var/obj/item/rig_module/module in installed_modules)
- if(module.permanent)
- continue
- possible_removals[module.name] = module
-
- if(!possible_removals.len)
- to_chat(user, "There are no installed modules to remove.")
- return
-
- var/removal_choice = input("Which module would you like to remove?") as null|anything in possible_removals
- if(!removal_choice)
- return
-
- var/obj/item/rig_module/removed = possible_removals[removal_choice]
- to_chat(user, "You detatch \the [removed] from \the [src].")
- removed.forceMove(get_turf(src))
- removed.removed()
- installed_modules -= removed
- update_icon()
-
- return
-
- // If we've gotten this far, all we have left to do before we pass off to root procs
- // is check if any of the loaded modules want to use the item we've been given.
- for(var/obj/item/rig_module/module in installed_modules)
- if(module.accepts_item(W,user)) //Item is handled in this proc
- return
- ..()
-
-
-/obj/item/rig/attack_hand(var/mob/user)
-
- if(electrified != 0)
- if(shock(user)) //Handles removing charge from the cell, as well. No need to do that here.
- return
- ..()
-
-/obj/item/rig/emag_act(var/remaining_charges, var/mob/user)
- if(!subverted)
- req_access.Cut()
- req_one_access.Cut()
- locked = 0
- subverted = 1
- to_chat(user, "You short out the access protocol for the suit.")
- return 1
diff --git a/code/modules/clothing/spacesuits/rig/rig_pieces.dm b/code/modules/clothing/spacesuits/rig/rig_pieces.dm
deleted file mode 100644
index 246e3beb10f..00000000000
--- a/code/modules/clothing/spacesuits/rig/rig_pieces.dm
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Defines the helmets, gloves and shoes for rigs.
- */
-
-/obj/item/clothing/head/helmet/space/new_rig
- name = "helmet"
- flags = BLOCKHAIR | THICKMATERIAL | NODROP
- flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEMASK
- body_parts_covered = HEAD
- heat_protection = HEAD
- cold_protection = HEAD
- var/brightness_on = 4
- var/on = 0
- sprite_sheets = list(
- "Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
- "Skrell" = 'icons/mob/species/skrell/helmet.dmi',
- "Unathi" = 'icons/mob/species/unathi/helmet.dmi'
- )
- species_restricted = null
- actions_types = list(/datum/action/item_action/toggle_helmet_light)
-
- flash_protect = 2
-
-/obj/item/clothing/head/helmet/space/new_rig/attack_self(mob/user)
- if(!isturf(user.loc))
- to_chat(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/new_rig/proc/toggle_light(mob/user)
- if(flags & AIRTIGHT) //Could also check for STOPSPRESSUREDMAGE, but one is enough, both get toggled when the seal gets toggled.
-
- on = !on
- icon_state = "[item_color][on]"
-
- if(on)
- set_light(brightness_on)
- else
- set_light(0)
- else
- to_chat(user, "You cannot turn the light on while the suit isn't sealed.")
-
- if(istype(user,/mob/living/carbon/human))
- var/mob/living/carbon/human/H = user
- H.update_inv_head()
-
-/obj/item/clothing/gloves/rig
- name = "gauntlets"
- flags = THICKMATERIAL | NODROP
- body_parts_covered = HANDS
- heat_protection = HANDS
- cold_protection = HANDS
- species_restricted = null
- gender = PLURAL
-
-/obj/item/clothing/shoes/magboots/rig
- name = "boots"
- flags = NODROP
- body_parts_covered = FEET
- cold_protection = FEET
- heat_protection = FEET
- species_restricted = null
- gender = PLURAL
-
-/obj/item/clothing/shoes/magboots/rig/attack_self(mob/user)
- if(flags & AIRTIGHT) //Could also check for STOPSPRESSUREDMAGE, but one is enough, both get toggled when the seal gets toggled.
- ..(user)
- else
- to_chat(user, "You cannot activate mag-pulse traction system while the suit is not sealed.")
-
-/obj/item/clothing/suit/space/new_rig
- name = "chestpiece"
- allowed = list(/obj/item/flashlight,/obj/item/tank)
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- flags_inv = HIDEJUMPSUIT|HIDETAIL
- flags = STOPSPRESSUREDMAGE | THICKMATERIAL | AIRTIGHT | NODROP
- slowdown = 0
- breach_threshold = 20
- resilience = 0.2
- can_breach = 1
- var/obj/item/rig/holder
- sprite_sheets = list(
- "Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
- "Unathi" = 'icons/mob/species/unathi/suit.dmi'
- )
-
-//TODO: move this to modules
-/obj/item/clothing/head/helmet/space/new_rig/proc/prevent_track()
- return 0
-
-/obj/item/clothing/gloves/rig/Touch(var/atom/A, var/proximity)
-
- if(!A || !proximity)
- return 0
-
- var/mob/living/carbon/human/H = loc
- if(!istype(H) || !H.back)
- return 0
-
- var/obj/item/rig/suit = H.back
- if(!suit || !istype(suit) || !suit.installed_modules.len)
- return 0
-
- for(var/obj/item/rig_module/module in suit.installed_modules)
- if(module.active && module.activates_on_touch)
- if(module.engage(A))
- return 1
-
- return 0
-
-//Rig pieces for non-spacesuit based rigs
-
-/obj/item/clothing/head/lightrig
- name = "mask"
- body_parts_covered = HEAD
- heat_protection = HEAD
- cold_protection = HEAD
- flags = THICKMATERIAL|AIRTIGHT
-
-/obj/item/clothing/suit/lightrig
- name = "suit"
- allowed = list(/obj/item/flashlight)
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
- flags_inv = HIDEJUMPSUIT
- flags = THICKMATERIAL
-
-/obj/item/clothing/shoes/lightrig
- name = "boots"
- body_parts_covered = FEET
- cold_protection = FEET
- heat_protection = FEET
- species_restricted = null
- gender = PLURAL
-
-/obj/item/clothing/gloves/lightrig
- name = "gloves"
- flags = THICKMATERIAL
- body_parts_covered = HANDS
- heat_protection = HANDS
- cold_protection = HANDS
- species_restricted = null
- gender = PLURAL
diff --git a/code/modules/clothing/spacesuits/rig/rig_verbs.dm b/code/modules/clothing/spacesuits/rig/rig_verbs.dm
deleted file mode 100644
index 4a71f6c67bc..00000000000
--- a/code/modules/clothing/spacesuits/rig/rig_verbs.dm
+++ /dev/null
@@ -1,335 +0,0 @@
-// Interface for humans.
-/obj/item/rig/verb/hardsuit_interface()
- set name = "Open Hardsuit Interface"
- set desc = "Open the hardsuit system interface."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(wearer && wearer.back == src)
- ui_interact(usr)
-
-/obj/item/rig/verb/toggle_vision()
- set name = "Toggle Visor"
- set desc = "Turns your rig visor off or on."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- if(!check_power_cost(usr))
- return
-
- if(!(flags & NODROP))
- to_chat(usr, "The suit is not active.")
- return
-
- if(!check_suit_access(usr))
- return
-
- if(!visor)
- to_chat(usr, "The hardsuit does not have a configurable visor.")
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- if(!visor.active)
- visor.activate()
- else
- visor.deactivate()
-
-/obj/item/rig/proc/toggle_helmet()
- set name = "Toggle Helmet"
- set desc = "Deploys or retracts your helmet."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- if(!check_suit_access(usr))
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- toggle_piece("helmet", usr)
-
-/obj/item/rig/proc/toggle_chest()
- set name = "Toggle Chestpiece"
- set desc = "Deploys or retracts your chestpiece."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(!check_suit_access(usr))
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- toggle_piece("chest", usr)
-
-/obj/item/rig/proc/toggle_gauntlets()
- set name = "Toggle Gauntlets"
- set desc = "Deploys or retracts your gauntlets."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- if(!check_suit_access(usr))
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- toggle_piece("gauntlets", usr)
-
-/obj/item/rig/proc/toggle_boots()
- set name = "Toggle Boots"
- set desc = "Deploys or retracts your boots."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- if(!check_suit_access(usr))
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- toggle_piece("boots", usr)
-
-/obj/item/rig/verb/deploy_suit()
- set name = "Deploy Hardsuit"
- set desc = "Deploys helmet, gloves and boots all at once."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- if(!check_suit_access(usr))
- return
-
- if(!check_power_cost(usr))
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- deploy(wearer, usr)
-
-/obj/item/rig/verb/toggle_seals_verb()
- set name = "Toggle Hardsuit Seals"
- set desc = "Seals or unseals your rig."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- if(!check_suit_access(usr))
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- if(flags & NODROP)
- unseal(usr)
- else
- seal(usr)
-
-/obj/item/rig/verb/switch_vision_mode()
- set name = "Switch Vision Mode"
- set desc = "Switches between available vision modes."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(malfunction_check(usr))
- return
-
- if(!check_power_cost(usr, 0, 0, 0, 0))
- return
-
- if(!(flags & NODROP))
- to_chat(usr, "The suit is not active.")
- return
-
- if(!visor)
- to_chat(usr, "The hardsuit does not have a configurable visor.")
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- if(!visor.active)
- visor.activate()
-
- if(!visor.active)
- to_chat(usr, "The visor is suffering a hardware fault and cannot be configured.")
- return
-
- visor.engage()
-
-/obj/item/rig/verb/alter_voice()
- set name = "Configure Voice Synthesiser"
- set desc = "Toggles or configures your voice synthesizer."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(malfunction_check(usr))
- return
-
- if(!(flags & NODROP))
- to_chat(usr, "The suit is not active.")
- return
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- if(!speech)
- to_chat(usr, "The hardsuit does not have a speech synthesiser.")
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- speech.engage()
-
-/obj/item/rig/verb/select_module()
- set name = "Select Module"
- set desc = "Selects a module as your primary system."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(malfunction_check(usr))
- return
-
- if(!check_power_cost(usr, 0, 0, 0, 0))
- return
-
- if(!(flags & NODROP))
- to_chat(usr, "The suit is not active.")
- return
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- var/list/selectable = list()
- for(var/obj/item/rig_module/module in installed_modules)
- if(module.selectable)
- selectable |= module
-
- var/obj/item/rig_module/module = input("Which module do you wish to select?") as null|anything in selectable
-
- if(!istype(module))
- selected_module = null
- to_chat(usr, "Primary system is now: deselected.")
- return
-
- selected_module = module
- to_chat(usr, "Primary system is now: [selected_module.interface_name].")
-
-/obj/item/rig/verb/toggle_module()
- set name = "Toggle Module"
- set desc = "Toggle a system module."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(malfunction_check(usr))
- return
-
- if(!check_power_cost(usr, 0, 0, 0, 0))
- return
-
- if(!(flags & NODROP))
- to_chat(usr, "The suit is not active.")
- return
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- var/list/selectable = list()
- for(var/obj/item/rig_module/module in installed_modules)
- if(module.toggleable)
- selectable |= module
-
- var/obj/item/rig_module/module = input("Which module do you wish to toggle?") as null|anything in selectable
-
- if(!istype(module))
- return
-
- if(module.active)
- to_chat(usr, "You attempt to deactivate \the [module.interface_name].")
- module.deactivate()
- else
- to_chat(usr, "You attempt to activate \the [module.interface_name].")
- module.activate()
-
-/obj/item/rig/verb/engage_module()
- set name = "Engage Module"
- set desc = "Engages a system module."
- set category = "Hardsuit"
- set src = usr.contents
-
- if(malfunction_check(usr))
- return
-
- if(!(flags & NODROP))
- to_chat(usr, "The suit is not active.")
- return
-
- if(!istype(wearer) || !wearer.back == src)
- to_chat(usr, "The hardsuit is not being worn.")
- return
-
- if(!check_power_cost(usr, 0, 0, 0, 0))
- return
-
- var/mob/M = usr
- if(M.incapacitated())
- return
-
- var/list/selectable = list()
- for(var/obj/item/rig_module/module in installed_modules)
- if(module.usable)
- selectable |= module
-
- var/obj/item/rig_module/module = input("Which module do you wish to engage?") as null|anything in selectable
-
- if(!istype(module))
- return
-
- to_chat(usr, "You attempt to engage the [module.interface_name].")
- module.engage()
diff --git a/code/modules/clothing/spacesuits/rig/rig_wiring.dm b/code/modules/clothing/spacesuits/rig/rig_wiring.dm
deleted file mode 100644
index 9d3108ac016..00000000000
--- a/code/modules/clothing/spacesuits/rig/rig_wiring.dm
+++ /dev/null
@@ -1,70 +0,0 @@
-/datum/wires/rig
- random = 1
- holder_type = /obj/item/rig
- wire_count = 5
-
-#define RIG_SECURITY 1
-#define RIG_AI_OVERRIDE 2
-#define RIG_SYSTEM_CONTROL 4
-#define RIG_INTERFACE_LOCK 8
-#define RIG_INTERFACE_SHOCK 16
-/*
- * Rig security can be snipped to disable ID access checks on rig.
- * Rig AI override can be pulsed to toggle whether or not the AI can take control of the suit.
- * System control can be pulsed to toggle some malfunctions.
- * Interface lock can be pulsed to toggle whether or not the interface can be accessed.
- */
-
-/datum/wires/rig/UpdateCut(var/index, var/mended)
-
- var/obj/item/rig/rig = holder
- switch(index)
- if(RIG_SECURITY)
- if(mended)
- rig.req_access = initial(rig.req_access)
- rig.req_one_access = initial(rig.req_one_access)
- if(RIG_INTERFACE_SHOCK)
- rig.electrified = mended ? 0 : -1
- rig.shock(usr,100)
-
-/datum/wires/rig/UpdatePulsed(var/index)
-
- var/obj/item/rig/rig = holder
- switch(index)
- if(RIG_SECURITY)
- rig.security_check_enabled = !rig.security_check_enabled
- rig.visible_message("\The [rig] twitches as several suit locks [rig.security_check_enabled?"close":"open"].")
- if(RIG_AI_OVERRIDE)
- rig.ai_override_enabled = !rig.ai_override_enabled
- rig.visible_message("A small red light on [rig] [rig.ai_override_enabled?"goes dead":"flickers on"].")
- if(RIG_SYSTEM_CONTROL)
- rig.malfunctioning += 10
- if(rig.malfunction_delay <= 0)
- rig.malfunction_delay = 20
- rig.shock(usr,100)
- if(RIG_INTERFACE_LOCK)
- rig.interface_locked = !rig.interface_locked
- rig.visible_message("\The [rig] clicks audibly as the software interface [rig.interface_locked?"darkens":"brightens"].")
- if(RIG_INTERFACE_SHOCK)
- if(rig.electrified != -1)
- rig.electrified = 30
- rig.shock(usr,100)
-
-/datum/wires/rig/GetWireName(index)
- switch(index)
- if(RIG_SECURITY)
- return "ID check"
- if(RIG_AI_OVERRIDE)
- return "AI control"
- if(RIG_SYSTEM_CONTROL)
- return "System control"
- if(RIG_INTERFACE_LOCK)
- return "Interface lock"
- if(RIG_INTERFACE_SHOCK)
- return "Electrification"
-
-/datum/wires/rig/CanUse(var/mob/living/L)
- var/obj/item/rig/rig = holder
- if(rig.open)
- return 1
- return 0
diff --git a/code/modules/clothing/spacesuits/rig/suits/alien.dm b/code/modules/clothing/spacesuits/rig/suits/alien.dm
deleted file mode 100644
index 25c784ba7dd..00000000000
--- a/code/modules/clothing/spacesuits/rig/suits/alien.dm
+++ /dev/null
@@ -1,46 +0,0 @@
-/obj/item/rig/unathi
- name = "NT breacher chassis control module"
- desc = "A cheap NT knock-off of an Unathi battle-rig. Looks like a fish, moves like a fish, steers like a cow."
- suit_type = "NT breacher"
- icon_state = "breacher_rig_cheap"
- armor = list(melee = 30, bullet = 30, laser = 30, energy = 30, bomb = 45, bio = 100, rad = 50)
- emp_protection = -20
- active_slowdown = 6
- offline_slowdown = 10
- vision_restriction = 1
- offline_vision_restriction = 2
-
- chest_type = /obj/item/clothing/suit/space/new_rig/unathi
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/unathi
- glove_type = /obj/item/clothing/gloves/rig/unathi
- boot_type = /obj/item/clothing/shoes/magboots/rig/unathi
-
-/obj/item/rig/unathi/fancy
- name = "breacher chassis control module"
- desc = "An authentic Unathi breacher chassis. Huge, bulky and absurdly heavy. It must be like wearing a tank."
- suit_type = "breacher chassis"
- icon_state = "breacher_rig"
- armor = list(melee = 45, bullet = 45, laser = 45, energy = 45, bomb = 45, bio = 100, rad = 75) //Takes TEN TIMES as much damage to stop someone in a breacher. In exchange, it's slow. //Whoever made this was on meth
- vision_restriction = 0
-
-/obj/item/clothing/head/helmet/space/new_rig/unathi
- icon = 'icons/obj/clothing/species/unathi/hats.dmi'
- species_restricted = list("Unathi")
-
-/obj/item/clothing/suit/space/new_rig/unathi
- icon = 'icons/obj/clothing/species/unathi/suits.dmi'
- species_restricted = list("Unathi")
-
-/obj/item/clothing/gloves/rig/unathi
- icon = 'icons/obj/clothing/species/unathi/gloves.dmi'
- species_restricted = list("Unathi")
- sprite_sheets = list(
- "Unathi" = 'icons/mob/species/unathi/gloves.dmi'
- )
-
-/obj/item/clothing/shoes/magboots/rig/unathi
- icon = 'icons/obj/clothing/species/unathi/shoes.dmi'
- species_restricted = list("Unathi")
- sprite_sheets = list(
- "Unathi" = 'icons/mob/species/unathi/feet.dmi'
- )
diff --git a/code/modules/clothing/spacesuits/rig/suits/combat.dm b/code/modules/clothing/spacesuits/rig/suits/combat.dm
deleted file mode 100644
index cc05c8af2f7..00000000000
--- a/code/modules/clothing/spacesuits/rig/suits/combat.dm
+++ /dev/null
@@ -1,28 +0,0 @@
-/obj/item/clothing/head/helmet/space/new_rig/combat
-
-/obj/item/rig/combat
- name = "combat hardsuit control module"
- desc = "A sleek and dangerous hardsuit for active combat."
- icon_state = "security_rig"
- suit_type = "combat hardsuit"
- armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
- active_slowdown = 1
- offline_slowdown = 3
- offline_vision_restriction = 1
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/combat
- allowed = list(/obj/item/gun,/obj/item/flashlight,/obj/item/tank,/obj/item/melee/baton)
-
-
-/obj/item/rig/combat/equipped
-
-
- initial_modules = list(
- /obj/item/rig_module/mounted,
- /obj/item/rig_module/vision/thermal,
- /obj/item/rig_module/grenade_launcher,
- /obj/item/rig_module/ai_container,
- // /obj/item/rig_module/power_sink,
- /obj/item/rig_module/electrowarfare_suite,
- /obj/item/rig_module/chem_dispenser/combat
- )
diff --git a/code/modules/clothing/spacesuits/rig/suits/ert_suits.dm b/code/modules/clothing/spacesuits/rig/suits/ert_suits.dm
deleted file mode 100644
index 5485e1fe882..00000000000
--- a/code/modules/clothing/spacesuits/rig/suits/ert_suits.dm
+++ /dev/null
@@ -1,81 +0,0 @@
-/obj/item/clothing/head/helmet/space/new_rig/ert
-
-/obj/item/rig/ert
- name = "ERT-C hardsuit control module"
- desc = "A suit worn by the commander of an Emergency Response Team. Has blue highlights. Armoured and space ready."
- suit_type = "ERT commander"
- icon_state = "ert_commander_rig"
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/ert
-
- req_access = list(ACCESS_CENT_SPECOPS)
-
- armor = list(melee = 45, bullet = 25, laser = 30, energy = 10, bomb = 25, bio = 100, rad = 50)
- allowed = list(/obj/item/flashlight, /obj/item/tank, /obj/item/t_scanner, /obj/item/rcd, /obj/item/crowbar, \
- /obj/item/screwdriver, /obj/item/weldingtool, /obj/item/wirecutters, /obj/item/wrench, /obj/item/multitool, \
- /obj/item/radio, /obj/item/analyzer,/obj/item/storage/briefcase/inflatable, /obj/item/melee/baton, /obj/item/gun, \
- /obj/item/storage/firstaid, /obj/item/reagent_containers/hypospray, /obj/item/roller)
-
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- /obj/item/rig_module/maneuvering_jets,
- /obj/item/rig_module/datajack,
- )
-
-/obj/item/rig/ert/engineer
- name = "ERT-E suit control module"
- desc = "A suit worn by the engineering division of an Emergency Response Team. Has orange highlights. Armoured and space ready."
- suit_type = "ERT engineer"
- icon_state = "ert_engineer_rig"
- siemens_coefficient = 0
-
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- /obj/item/rig_module/maneuvering_jets,
- /obj/item/rig_module/device/plasmacutter,
- // /obj/item/rig_module/device/rcd
- )
-
-/obj/item/rig/ert/medical
- name = "ERT-M suit control module"
- desc = "A suit worn by the medical division of an Emergency Response Team. Has white highlights. Armoured and space ready."
- suit_type = "ERT medic"
- icon_state = "ert_medical_rig"
-
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- /obj/item/rig_module/maneuvering_jets,
- /obj/item/rig_module/device/healthscanner,
- /obj/item/rig_module/chem_dispenser/injector
- )
-
-/obj/item/rig/ert/security
- name = "ERT-S suit control module"
- desc = "A suit worn by the security division of an Emergency Response Team. Has red highlights. Armoured and space ready."
- suit_type = "ERT security"
- icon_state = "ert_security_rig"
-
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- /obj/item/rig_module/maneuvering_jets,
- /obj/item/rig_module/grenade_launcher,
- /obj/item/rig_module/mounted/egun,
- )
-
-/obj/item/rig/ert/assetprotection
- name = "Heavy Asset Protection suit control module"
- desc = "A heavy suit worn by the highest level of Asset Protection, don't mess with the person wearing this. Armoured and space ready."
- suit_type = "heavy asset protection"
- icon_state = "asset_protection_rig"
-
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- /obj/item/rig_module/maneuvering_jets,
- /obj/item/rig_module/grenade_launcher,
- /obj/item/rig_module/vision/multi,
- /obj/item/rig_module/mounted/egun,
- /obj/item/rig_module/chem_dispenser/injector,
- /obj/item/rig_module/device/plasmacutter,
- // /obj/item/rig_module/device/rcd,
- /obj/item/rig_module/datajack
- )
diff --git a/code/modules/clothing/spacesuits/rig/suits/light.dm b/code/modules/clothing/spacesuits/rig/suits/light.dm
deleted file mode 100644
index d76691daf57..00000000000
--- a/code/modules/clothing/spacesuits/rig/suits/light.dm
+++ /dev/null
@@ -1,120 +0,0 @@
-// Light rigs are not space-capable, but don't suffer excessive slowdown or sight issues when depowered.
-/obj/item/rig/light
- name = "light suit control module"
- desc = "A lighter, less armoured rig suit."
- icon_state = "ninja_rig"
- suit_type = "light suit"
- allowed = list(/obj/item/gun,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/restraints/handcuffs,/obj/item/tank,/obj/item/stock_parts/cell)
- emp_protection = 10
- active_slowdown = 0
- flags = STOPSPRESSUREDMAGE | THICKMATERIAL
- offline_slowdown = 0
- offline_vision_restriction = 0
-
- chest_type = /obj/item/clothing/suit/space/new_rig/light
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/light
- boot_type = /obj/item/clothing/shoes/magboots/rig/light
- glove_type = /obj/item/clothing/gloves/rig/light
-
-/obj/item/clothing/suit/space/new_rig/light
- name = "suit"
- breach_threshold = 18 //comparable to voidsuits
-
-/obj/item/clothing/gloves/rig/light
- name = "gloves"
-
-/obj/item/clothing/shoes/magboots/rig/light
- name = "shoes"
-
-/obj/item/clothing/head/helmet/space/new_rig/light
- name = "hood"
-
-/obj/item/rig/light/hacker
- name = "cybersuit control module"
- suit_type = "cyber"
- desc = "An advanced powered armour suit with many cyberwarfare enhancements. Comes with built-in insulated gloves for safely tampering with electronics."
- icon_state = "hacker_rig"
-
- req_access = list(ACCESS_SYNDICATE)
-
- airtight = 0
- seal_delay = 5 //not being vaccum-proof has an upside I guess
-
- helm_type = /obj/item/clothing/head/lightrig/hacker
- chest_type = /obj/item/clothing/suit/lightrig/hacker
- glove_type = /obj/item/clothing/gloves/lightrig/hacker
- boot_type = /obj/item/clothing/shoes/lightrig/hacker
-
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- // /obj/item/rig_module/power_sink,
- /obj/item/rig_module/datajack,
- /obj/item/rig_module/electrowarfare_suite,
- /obj/item/rig_module/voice,
- /obj/item/rig_module/vision,
- )
-
-//The cybersuit is not space-proof. It does however, have good siemens_coefficient values
-/obj/item/clothing/head/lightrig/hacker
- name = "HUD"
- siemens_coefficient = 0.4
- flags = 0
-
-/obj/item/clothing/suit/lightrig/hacker
- siemens_coefficient = 0.4
-
-/obj/item/clothing/shoes/lightrig/hacker
- siemens_coefficient = 0.4
- flags = NOSLIP //All the other rigs have magboots anyways, hopefully gives the hacker suit something more going for it.
-
-/obj/item/clothing/gloves/lightrig/hacker
- siemens_coefficient = 0
-
-/obj/item/rig/light/ninja
- name = "ominous suit control module"
- suit_type = "ominous"
- desc = "A unique, vaccum-proof suit of nano-enhanced armor designed specifically for Spider Clan assassins."
- icon_state = "ninja_rig"
- armor = list(melee = 50, bullet = 15, laser = 30, energy = 10, bomb = 25, bio = 100, rad = 30)
- emp_protection = 40 //change this to 30 if too high.
- active_slowdown = 0
-
- chest_type = /obj/item/clothing/suit/space/new_rig/light/ninja
- glove_type = /obj/item/clothing/gloves/rig/light/ninja
-
- req_access = list(ACCESS_SYNDICATE)
-
- initial_modules = list(
- /obj/item/rig_module/teleporter,
- /obj/item/rig_module/stealth_field,
- /obj/item/rig_module/mounted/energy_blade,
- /obj/item/rig_module/vision,
- /obj/item/rig_module/voice,
- /obj/item/rig_module/chem_dispenser,
- /obj/item/rig_module/grenade_launcher,
- /obj/item/rig_module/fabricator,
- /obj/item/rig_module/ai_container,
- // /obj/item/rig_module/power_sink,
- /obj/item/rig_module/datajack,
- /obj/item/rig_module/self_destruct
- )
-
-/obj/item/clothing/gloves/rig/light/ninja
- name = "insulated gloves"
- siemens_coefficient = 0
-
-/obj/item/clothing/suit/space/new_rig/light/ninja
- breach_threshold = 38 //comparable to regular hardsuits
-
-/obj/item/rig/light/stealth
- name = "stealth suit control module"
- suit_type = "stealth"
- desc = "A highly advanced and expensive suit designed for covert operations."
- icon_state = "ninja_rig" //supposed to be "stealth_rig", but as it currently only has a semi-copied ninja rig sprite, we can just use them directly.
-
- req_access = list(ACCESS_SYNDICATE)
-
- initial_modules = list(
- /obj/item/rig_module/stealth_field,
- /obj/item/rig_module/vision
- )
diff --git a/code/modules/clothing/spacesuits/rig/suits/merc.dm b/code/modules/clothing/spacesuits/rig/suits/merc.dm
deleted file mode 100644
index 95abba52df9..00000000000
--- a/code/modules/clothing/spacesuits/rig/suits/merc.dm
+++ /dev/null
@@ -1,32 +0,0 @@
-/obj/item/clothing/head/helmet/space/new_rig/merc
-
-/obj/item/rig/merc
- name = "crimson hardsuit control module"
- desc = "A blood-red hardsuit featuring some fairly illegal technology."
- icon_state = "merc_rig"
- suit_type = "crimson hardsuit"
- armor = list(melee = 40, bullet = 50, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 50)
- active_slowdown = 1
- offline_slowdown = 3
- offline_vision_restriction = 1
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/merc
- allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/gun,/obj/item/ammo_casing,/obj/item/melee/baton,/obj/item/melee/energy/sword,/obj/item/restraints/handcuffs)
-
- initial_modules = list(
- /obj/item/rig_module/mounted,
- /obj/item/rig_module/vision/thermal,
- /obj/item/rig_module/grenade_launcher,
- /obj/item/rig_module/ai_container,
- // /obj/item/rig_module/power_sink,
- /obj/item/rig_module/electrowarfare_suite,
- /obj/item/rig_module/chem_dispenser/combat,
- // /obj/item/rig_module/fabricator/energy_net
- )
-
-//Has most of the modules removed
-/obj/item/rig/merc/empty
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- /obj/item/rig_module/electrowarfare_suite, //might as well
- )
diff --git a/code/modules/clothing/spacesuits/rig/suits/station.dm b/code/modules/clothing/spacesuits/rig/suits/station.dm
deleted file mode 100644
index c4bbd059fae..00000000000
--- a/code/modules/clothing/spacesuits/rig/suits/station.dm
+++ /dev/null
@@ -1,223 +0,0 @@
-/obj/item/clothing/head/helmet/space/new_rig/industrial
-
-/obj/item/clothing/head/helmet/space/new_rig/ce
-
-/obj/item/clothing/head/helmet/space/new_rig/eva
-
-/obj/item/clothing/head/helmet/space/new_rig/hazmat
-
-/obj/item/clothing/head/helmet/space/new_rig/medical
-
-/obj/item/clothing/head/helmet/space/new_rig/hazard
-
-/obj/item/rig/internalaffairs
- name = "augmented tie"
- suit_type = "augmented suit"
- desc = "Prepare for paperwork."
- icon_state = "internalaffairs_rig"
- armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
- siemens_coefficient = 0.9
- active_slowdown = 0
- offline_slowdown = 0
- offline_vision_restriction = 0
-
- allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/storage/briefcase,/obj/item/storage/secure/briefcase)
-
- req_access = list()
- req_one_access = list()
-
- glove_type = null
- helm_type = null
- boot_type = null
-
-/obj/item/rig/internalaffairs/equipped
-
- req_access = list(ACCESS_LAWYER)
-
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- /obj/item/rig_module/device/flash,
- /obj/item/rig_module/device/paperdispenser,
- /obj/item/rig_module/device/pen,
- /obj/item/rig_module/device/stamp
- )
-
- glove_type = null
- helm_type = null
- boot_type = null
-
-/obj/item/rig/industrial
- name = "industrial suit control module"
- suit_type = "industrial hardsuit"
- desc = "A heavy, powerful rig used by construction crews and mining corporations."
- icon_state = "engineering_rig"
- armor = list(melee = 10, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 75)
- active_slowdown = 3
- offline_slowdown = 10
- offline_vision_restriction = 2
- emp_protection = -20
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/industrial
-
- allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/storage/bag/ore,/obj/item/t_scanner,/obj/item/pickaxe, /obj/item/rcd)
-
- req_access = list()
- req_one_access = list()
-
-
-/obj/item/rig/industrial/equipped
-
- initial_modules = list(
- /obj/item/rig_module/device/plasmacutter,
- /obj/item/rig_module/device/drill,
- /obj/item/rig_module/device/orescanner,
- // /obj/item/rig_module/device/rcd,
- /obj/item/rig_module/vision/meson
- )
-
-/obj/item/rig/eva
- name = "EVA suit control module"
- suit_type = "EVA hardsuit"
- desc = "A light rig for repairs and maintenance to the outside of habitats and vessels."
- icon_state = "eva_rig"
- active_slowdown = 0
- offline_slowdown = 1
- offline_vision_restriction = 1
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/eva
-
- allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/storage/toolbox,/obj/item/storage/briefcase/inflatable,/obj/item/t_scanner,/obj/item/rcd)
-
- req_access = list()
- req_one_access = list()
-
-/obj/item/rig/eva/equipped
-
- initial_modules = list(
- /obj/item/rig_module/device/plasmacutter,
- /obj/item/rig_module/maneuvering_jets,
- // /obj/item/rig_module/device/rcd,
- /obj/item/rig_module/vision/meson
- )
-
-//Chief Engineer's rig. This is sort of a halfway point between the old hardsuits (voidsuits) and the rig class.
-/obj/item/rig/ce
-
- name = "advanced voidsuit control module"
- suit_type = "advanced voidsuit"
- desc = "An advanced voidsuit that protects against hazardous, low pressure environments. Shines with a high polish."
- icon_state = "ce_rig"
- armor = list(melee = 40, bullet = 5, laser = 10, energy = 5, bomb = 50, bio = 100, rad = 90)
- active_slowdown = 0
- offline_slowdown = 0
- offline_vision_restriction = 0
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/ce
-
- allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/storage/bag/ore,/obj/item/t_scanner,/obj/item/pickaxe, /obj/item/rcd)
-
-
- req_access = list()
- req_one_access = list()
-
- boot_type = null
- glove_type = null
-
-/obj/item/rig/ce/equipped
-
- req_access = list(ACCESS_CE)
-
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- /obj/item/rig_module/maneuvering_jets,
- /obj/item/rig_module/device/plasmacutter,
- // /obj/item/rig_module/device/rcd,
- /obj/item/rig_module/vision/meson
- )
-
- chest_type = /obj/item/clothing/suit/space/new_rig/ce
- boot_type = null
- glove_type = null
-
-/obj/item/clothing/suit/space/new_rig/ce
- heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
-
-/obj/item/rig/hazmat
-
- name = "AMI control module"
- suit_type = "hazmat hardsuit"
- desc = "An Anomalous Material Interaction hardsuit that protects against the strangest energies the universe can throw at it."
- icon_state = "science_rig"
- active_slowdown = 1
- offline_vision_restriction = 1
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/hazmat
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/ert
-
- allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/pickaxe,/obj/item/healthanalyzer,/obj/item/gps,/obj/item/radio/beacon)
-
- req_access = list()
- req_one_access = list()
-
-/obj/item/rig/hazmat/equipped
-
- req_access = list(ACCESS_RD)
-
- initial_modules = list(
- /obj/item/rig_module/ai_container,
- /obj/item/rig_module/maneuvering_jets)
-
-/obj/item/rig/medical
-
- name = "rescue suit control module"
- suit_type = "rescue hardsuit"
- desc = "A durable suit designed for medical rescue in high risk areas."
- icon_state = "medical_rig"
- armor = list(melee = 10, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 50)
- active_slowdown = 1
- offline_vision_restriction = 1
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/medical
-
- allowed = list(/obj/item/flashlight,/obj/item/tank,/obj/item/storage/firstaid,/obj/item/healthanalyzer,/obj/item/stack/medical,/obj/item/roller )
-
- req_access = list()
- req_one_access = list()
-
-/obj/item/rig/medical/equipped
-
- initial_modules = list(
- /obj/item/rig_module/chem_dispenser/injector,
- /obj/item/rig_module/maneuvering_jets,
- /obj/item/rig_module/device/healthscanner,
- /obj/item/rig_module/vision/medhud
- )
-
-/obj/item/rig/hazard
- name = "hazard hardsuit control module"
- suit_type = "hazard hardsuit"
- desc = "A Security hardsuit designed for prolonged EVA in dangerous environments."
- icon_state = "hazard_rig"
- armor = list(melee = 30, bullet = 15, laser = 30, energy = 10, bomb = 10, bio = 100, rad = 50)
- active_slowdown = 1
- offline_slowdown = 3
- offline_vision_restriction = 1
-
- helm_type = /obj/item/clothing/head/helmet/space/new_rig/hazard
-
- allowed = list(/obj/item/gun,/obj/item/flashlight,/obj/item/tank,/obj/item/melee/baton)
-
- req_access = list()
- req_one_access = list()
-
-
-/obj/item/rig/hazard/equipped
-
- initial_modules = list(
- /obj/item/rig_module/vision/sechud,
- /obj/item/rig_module/maneuvering_jets,
- /obj/item/rig_module/grenade_launcher,
- /obj/item/rig_module/mounted/taser
- )
diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm
index b417df89426..76bcd87921d 100644
--- a/code/modules/clothing/under/accessories/accessory.dm
+++ b/code/modules/clothing/under/accessories/accessory.dm
@@ -37,8 +37,13 @@
var/mob/M = has_suit.loc
A.Grant(M)
- for(var/armor_type in armor)
- has_suit.armor[armor_type] += armor[armor_type]
+ if (islist(has_suit.armor) || isnull(has_suit.armor)) // This proc can run before /obj/Initialize has run for U and src,
+ has_suit.armor = getArmor(arglist(has_suit.armor)) // we have to check that the armor list has been transformed into a datum before we try to call a proc on it
+ // This is safe to do as /obj/Initialize only handles setting up the datum if actually needed.
+ if (islist(armor) || isnull(armor))
+ armor = getArmor(arglist(armor))
+
+ has_suit.armor = has_suit.armor.attachArmor(armor)
if(user)
to_chat(user, "You attach [src] to [has_suit].")
@@ -56,8 +61,7 @@
var/mob/M = has_suit.loc
A.Remove(M)
- for(var/armor_type in armor)
- has_suit.armor[armor_type] -= armor[armor_type]
+ has_suit.armor = has_suit.armor.detachArmor(armor)
has_suit = null
if(user)
@@ -314,6 +318,36 @@
if(isliving(user))
user.visible_message("[user] invades [M]'s personal space, thrusting [src] into [M.p_their()] face insistently.","You invade [M]'s personal space, thrusting [src] into [M.p_their()] face insistently. You are the law.")
+//////////////
+//OBJECTION!//
+//////////////
+
+/obj/item/clothing/accessory/lawyers_badge
+ name = "attorney's badge"
+ desc = "Fills you with the conviction of JUSTICE. Lawyers tend to want to show it to everyone they meet."
+ icon_state = "lawyerbadge"
+ item_state = "lawyerbadge"
+ item_color = "lawyerbadge"
+ var/cached_bubble_icon = null
+
+/obj/item/clothing/accessory/lawyers_badge/attack_self(mob/user)
+ if(prob(1))
+ user.say("The testimony contradicts the evidence!")
+ user.visible_message("[user] shows [user.p_their()] attorney's badge.", "You show your attorney's badge.")
+
+/obj/item/clothing/accessory/lawyers_badge/on_attached(obj/item/clothing/under/S, mob/user)
+ ..()
+ if(has_suit && ismob(has_suit.loc))
+ var/mob/M = has_suit.loc
+ cached_bubble_icon = M.bubble_icon
+ M.bubble_icon = "lawyer"
+
+/obj/item/clothing/accessory/lawyers_badge/on_removed(mob/user)
+ if(has_suit && ismob(has_suit.loc))
+ var/mob/M = has_suit.loc
+ M.bubble_icon = cached_bubble_icon
+ ..()
+
///////////
//SCARVES//
///////////
diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm
index a9c47e760e7..a0d6823fe80 100644
--- a/code/modules/crafting/craft.dm
+++ b/code/modules/crafting/craft.dm
@@ -128,7 +128,7 @@
continue main_loop
return FALSE
for(var/obj/item/T in tools_used)
- if(!T.tool_start_check(user, 0)) //Check if all our tools are valid for their use
+ if(!T.tool_start_check(null, user, 0)) //Check if all our tools are valid for their use
return FALSE
return TRUE
diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm
index f8d2029651d..530b9095f75 100644
--- a/code/modules/customitems/item_defines.dm
+++ b/code/modules/customitems/item_defines.dm
@@ -48,7 +48,7 @@
var/mob/living/carbon/human/target = M
- if(ismachine(target))
+ if(ismachineperson(target))
to_chat(user, "[target] has no skin, how do you expect to tattoo [target.p_them()]?")
return
@@ -349,7 +349,7 @@
to_chat(user, "You modify the appearance of [target].")
var/obj/item/clothing/mask/gas/M = target
M.name = "Prescription Gas Mask"
- M.desc = "It looks heavily modified, but otherwise functions as a gas mask. The words “Property of Yon-Dale” can be seen on the inner band."
+ M.desc = "It looks heavily modified, but otherwise functions as a gas mask. The words \"Property of Yon-Dale\" can be seen on the inner band."
M.icon = 'icons/obj/custom_items.dmi'
M.icon_state = "gas_tariq"
M.sprite_sheets = list(
diff --git a/code/modules/detective_work/footprints_and_rag.dm b/code/modules/detective_work/footprints_and_rag.dm
index 2646d03fb0f..bfc9d0aa824 100644
--- a/code/modules/detective_work/footprints_and_rag.dm
+++ b/code/modules/detective_work/footprints_and_rag.dm
@@ -18,7 +18,6 @@
amount_per_transfer_from_this = 5
possible_transfer_amounts = list(5)
volume = 5
- can_be_placed_into = null
flags = NOBLUDGEON
container_type = OPENCONTAINER
has_lid = FALSE
diff --git a/code/modules/economy/Accounts_DB.dm b/code/modules/economy/Accounts_DB.dm
index 6995e260500..aafc91cb849 100644
--- a/code/modules/economy/Accounts_DB.dm
+++ b/code/modules/economy/Accounts_DB.dm
@@ -159,7 +159,7 @@ GLOBAL_VAR(current_date_string)
var/account_name = href_list["holder_name"]
var/starting_funds = max(text2num(href_list["starting_funds"]), 0)
- starting_funds = Clamp(starting_funds, 0, GLOB.station_account.money) // Not authorized to put the station in debt.
+ starting_funds = clamp(starting_funds, 0, GLOB.station_account.money) // Not authorized to put the station in debt.
starting_funds = min(starting_funds, fund_cap) // Not authorized to give more than the fund cap.
var/datum/money_account/M = create_account(account_name, starting_funds, src)
diff --git a/code/modules/economy/utils.dm b/code/modules/economy/utils.dm
index f7d6992e31f..4d7273cd719 100644
--- a/code/modules/economy/utils.dm
+++ b/code/modules/economy/utils.dm
@@ -5,7 +5,7 @@
////////////////////////
/proc/get_money_account(var/account_number, var/from_z=-1)
- for(var/obj/machinery/computer/account_database/DB in world)
+ for(var/obj/machinery/computer/account_database/DB in GLOB.machines)
if(from_z > -1 && DB.z != from_z) continue
if((DB.stat & NOPOWER) || !DB.activated ) continue
var/datum/money_account/acct = DB.get_account(account_number)
diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm
index 5e39295113c..8c01d5c7cc2 100644
--- a/code/modules/events/alien_infestation.dm
+++ b/code/modules/events/alien_infestation.dm
@@ -17,7 +17,7 @@
playercount = length(GLOB.clients)//grab playercount when event starts not when game starts
if(playercount >= highpop_trigger) //spawn with 4 if highpop
spawncount = 4
- for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world)
+ for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in SSair.atmos_machinery)
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
if(temp_vent.parent.other_atmosmch.len > 50) //Stops Aliens getting stuck in small networks. See: Security, Virology
vents += temp_vent
diff --git a/code/modules/events/anomaly_bluespace.dm b/code/modules/events/anomaly_bluespace.dm
index 2924effa0de..929612cf6f9 100644
--- a/code/modules/events/anomaly_bluespace.dm
+++ b/code/modules/events/anomaly_bluespace.dm
@@ -18,7 +18,7 @@
// Calculate new position (searches through beacons in world)
var/obj/item/radio/beacon/chosen
var/list/possible = list()
- for(var/obj/item/radio/beacon/W in world)
+ for(var/obj/item/radio/beacon/W in GLOB.global_radios)
if(!is_station_level(W.z))
continue
possible += W
diff --git a/code/modules/events/anomaly_pyro.dm b/code/modules/events/anomaly_pyro.dm
index 79e7c7b8434..0a5dc14bc3a 100644
--- a/code/modules/events/anomaly_pyro.dm
+++ b/code/modules/events/anomaly_pyro.dm
@@ -15,7 +15,7 @@
if(!newAnomaly)
kill()
return
- if(IsMultiple(activeFor, 5))
+ if(ISMULTIPLE(activeFor, 5))
newAnomaly.anomalyEffect()
/datum/event/anomaly/anomaly_pyro/end()
diff --git a/code/modules/events/apc_overload.dm b/code/modules/events/apc_overload.dm
index a773e71a173..13cabe81b3c 100644
--- a/code/modules/events/apc_overload.dm
+++ b/code/modules/events/apc_overload.dm
@@ -36,7 +36,8 @@
// break APC_BREAK_PROBABILITY% of all of the APCs on the station
var/affected_apc_count = 0
- for(var/obj/machinery/power/apc/C in GLOB.apcs)
+ for(var/thing in GLOB.apcs)
+ var/obj/machinery/power/apc/C = thing
// skip any APCs that are too critical to break
var/area/current_area = get_area(C)
if((current_area.type in skipped_areas_apc) || !is_station_level(C.z))
diff --git a/code/modules/events/apc_short.dm b/code/modules/events/apc_short.dm
index b128fe6c2e9..c19b6cbe8b7 100644
--- a/code/modules/events/apc_short.dm
+++ b/code/modules/events/apc_short.dm
@@ -36,7 +36,8 @@
// break APC_BREAK_PROBABILITY% of all of the APCs on the station
var/affected_apc_count = 0
- for(var/obj/machinery/power/apc/C in GLOB.apcs)
+ for(var/thing in GLOB.apcs)
+ var/obj/machinery/power/apc/C = thing
// skip any APCs that are too critical to disable
var/area/current_area = get_area(C)
if((current_area.type in skipped_areas_apc) || !is_station_level(C.z))
@@ -58,7 +59,17 @@
log_and_message_admins("APC Short event shorted out [affected_apc_count] APCs.")
/proc/power_restore(announce=TRUE)
- power_restore_quick(announce)
+ if(announce)
+ GLOB.event_announcement.Announce("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal", new_sound = 'sound/AI/poweron.ogg')
+
+ // recharge the APCs
+ for(var/thing in GLOB.apcs)
+ var/obj/machinery/power/apc/A = thing
+ if(!is_station_level(A.z))
+ continue
+ var/obj/item/stock_parts/cell/C = A.get_cell()
+ if(C)
+ C.give(C.maxcharge)
/proc/power_restore_quick(announce=TRUE)
if(announce)
diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm
index d3b7cf012b8..8d91635c458 100644
--- a/code/modules/events/brand_intelligence.dm
+++ b/code/modules/events/brand_intelligence.dm
@@ -55,12 +55,12 @@
kill()
return
- if(IsMultiple(activeFor, 4))
+ if(ISMULTIPLE(activeFor, 4))
var/obj/machinery/vending/rebel = pick(vendingMachines)
vendingMachines.Remove(rebel)
infectedMachines.Add(rebel)
rebel.shut_up = 0
rebel.shoot_inventory = 1
- if(IsMultiple(activeFor, 8))
+ if(ISMULTIPLE(activeFor, 8))
originMachine.speak(pick(rampant_speeches))
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index fb12a258c2d..fb02033b802 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -30,7 +30,8 @@
/datum/event/carp_migration/proc/spawn_fish(num_groups, group_size_min = 3, group_size_max = 5)
var/list/spawn_locations = list()
- for(var/obj/effect/landmark/C in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/C = thing
if(C.name == "carpspawn")
spawn_locations.Add(C.loc)
spawn_locations = shuffle(spawn_locations)
diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm
index 2d83372d625..52baf0fe05c 100644
--- a/code/modules/events/communications_blackout.dm
+++ b/code/modules/events/communications_blackout.dm
@@ -17,7 +17,7 @@
/datum/event/communications_blackout/start()
// This only affects the cores, relays should be unaffected imo
for(var/obj/machinery/tcomms/core/T in GLOB.tcomms_machines)
- T.disable_machine()
+ T.start_ion()
// Bring it back sometime between 3-5 minutes. This uses deciseconds, so 1800 and 3000 respecticely.
- // Note that because this is a strict enable not a toggle, the crew or AI can re-enable the machine themselves
- addtimer(CALLBACK(T, /obj/machinery/tcomms.proc/enable_machine), rand(1800, 3000))
+ // The AI cannot disable this, it must be waited for
+ addtimer(CALLBACK(T, /obj/machinery/tcomms.proc/end_ion), rand(1800, 3000))
diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm
index 563ef98697d..a11ef107a8f 100644
--- a/code/modules/events/dust.dm
+++ b/code/modules/events/dust.dm
@@ -16,7 +16,7 @@
density = 1
anchored = 1
var/strength = 2 //ex_act severity number
- var/life = 2 //how many things we hit before del(src)
+ var/life = 2 //how many things we hit before qdel(src)
var/atom/goal = null
/obj/effect/space_dust/weak
diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm
index 755e2e2d47a..7304469f408 100644
--- a/code/modules/events/electrical_storm.dm
+++ b/code/modules/events/electrical_storm.dm
@@ -10,7 +10,8 @@
for(var/i=1, i <= lightsoutAmount, i++)
var/list/possibleEpicentres = list()
- for(var/obj/effect/landmark/newEpicentre in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/newEpicentre = thing
if(newEpicentre.name == "lightsout" && !(newEpicentre in epicentreList))
possibleEpicentres += newEpicentre
if(possibleEpicentres.len)
@@ -21,7 +22,8 @@
if(!epicentreList.len)
return
- for(var/obj/effect/landmark/epicentre in epicentreList)
- for(var/obj/machinery/power/apc/apc in range(epicentre,lightsoutRange))
+ for(var/thing in epicentreList)
+ var/obj/effect/landmark/epicentre = thing
+ for(var/obj/machinery/power/apc/apc in range(epicentre, lightsoutRange))
apc.overload_lighting()
diff --git a/code/modules/events/event_procs.dm b/code/modules/events/event_procs.dm
index c5b7c893c26..cc00f05723f 100644
--- a/code/modules/events/event_procs.dm
+++ b/code/modules/events/event_procs.dm
@@ -1,9 +1,9 @@
/client/proc/forceEvent(var/type in SSevents.allEvents)
- set name = "Trigger Event (Debug Only)"
+ set name = "Trigger Event"
set category = "Debug"
- if(!holder)
+ if(!check_rights(R_EVENT))
return
if(ispath(type))
diff --git a/code/modules/events/holidays/AprilFools.dm b/code/modules/events/holidays/AprilFools.dm
deleted file mode 100644
index 562e6b98e0d..00000000000
--- a/code/modules/events/holidays/AprilFools.dm
+++ /dev/null
@@ -1 +0,0 @@
-//placeholder for holiday stuff
diff --git a/code/modules/events/holidays/Christmas.dm b/code/modules/events/holidays/Christmas.dm
deleted file mode 100644
index e04471482a5..00000000000
--- a/code/modules/events/holidays/Christmas.dm
+++ /dev/null
@@ -1,61 +0,0 @@
-/proc/Christmas_Game_Start()
- for(var/obj/structure/flora/tree/pine/xmas in world)
- if(!is_station_level(xmas.z)) continue
- for(var/turf/simulated/floor/T in orange(1,xmas))
- for(var/i=1,i<=rand(1,5),i++)
- new /obj/item/a_gift(T)
- for(var/mob/living/simple_animal/corgi/Ian/Ian in GLOB.mob_list)
- Ian.place_on_head(new /obj/item/clothing/head/helmet/space/santahat(Ian))
-
-/proc/ChristmasEvent()
- for(var/obj/structure/flora/tree/pine/xmas in world)
- var/mob/living/simple_animal/hostile/tree/evil_tree = new /mob/living/simple_animal/hostile/tree(xmas.loc)
- evil_tree.icon_state = xmas.icon_state
- evil_tree.icon_living = evil_tree.icon_state
- evil_tree.icon_dead = evil_tree.icon_state
- evil_tree.icon_gib = evil_tree.icon_state
- qdel(xmas)
-
-/obj/item/toy/xmas_cracker
- name = "xmas cracker"
- icon = 'icons/obj/christmas.dmi'
- icon_state = "cracker"
- desc = "Directions for use: Requires two people, one to pull each end."
- var/cracked = 0
-
-/obj/item/toy/xmas_cracker/New()
- ..()
-
-/obj/item/toy/xmas_cracker/attack(mob/target, mob/user)
- if( !cracked && istype(target,/mob/living/carbon/human) && (target.stat == CONSCIOUS) && !target.get_active_hand() )
- target.visible_message("[user] and [target] pop \an [src]! *pop*", "You pull \an [src] with [target]! *pop*", "You hear a *pop*.")
- var/obj/item/paper/Joke = new /obj/item/paper(user.loc)
- Joke.name = "[pick("awful","terrible","unfunny")] joke"
- Joke.info = pick("What did one snowman say to the other?\n\n'Is it me or can you smell carrots?'",
- "Why couldn't the snowman get laid?\n\nHe was frigid!",
- "Where are santa's helpers educated?\n\nNowhere, they're ELF-taught.",
- "What happened to the man who stole advent calanders?\n\nHe got 25 days.",
- "What does Santa get when he gets stuck in a chimney?\n\nClaus-trophobia.",
- "Where do you find chili beans?\n\nThe north pole.",
- "What do you get from eating tree decorations?\n\nTinsilitis!",
- "What do snowmen wear on their heads?\n\nIce caps!",
- "Why is Christmas just like life on ss13?\n\nYou do all the work and the fat guy gets all the credit.",
- "Why doesn�t Santa have any children?\n\nBecause he only comes down the chimney.")
- new /obj/item/clothing/head/festive(target.loc)
- user.update_icons()
- cracked = 1
- icon_state = "cracker1"
- var/obj/item/toy/xmas_cracker/other_half = new /obj/item/toy/xmas_cracker(target)
- other_half.cracked = 1
- other_half.icon_state = "cracker2"
- target.put_in_active_hand(other_half)
- playsound(user, 'sound/effects/snap.ogg', 50, 1)
- return 1
- return ..()
-
-/obj/item/clothing/head/festive
- name = "festive paper hat"
- icon_state = "xmashat"
- desc = "A crappy paper hat that you are REQUIRED to wear."
- flags_inv = 0
- armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
diff --git a/code/modules/events/holidays/Easter.dm b/code/modules/events/holidays/Easter.dm
deleted file mode 100644
index 562e6b98e0d..00000000000
--- a/code/modules/events/holidays/Easter.dm
+++ /dev/null
@@ -1 +0,0 @@
-//placeholder for holiday stuff
diff --git a/code/modules/events/holidays/Holidays.dm b/code/modules/events/holidays/Holidays.dm
deleted file mode 100644
index 5bc49001e3a..00000000000
--- a/code/modules/events/holidays/Holidays.dm
+++ /dev/null
@@ -1,183 +0,0 @@
-//Uncommenting ALLOW_HOLIDAYS in config.txt will enable Holidays
-GLOBAL_VAR_INIT(Holiday) // I didnt update the rest of this code because this file hasnt been ticked in years, and holiday code got overhauled
- // If it really needs fixing, yell at me, -aa
-
-//Just thinking ahead! Here's the foundations to a more robust Holiday event system.
-//It's easy as hell to add stuff. Just set Holiday to something using the switch(or something else)
-//then use if(Holiday == "MyHoliday") to make stuff happen on that specific day only
-//Please, Don't spam stuff up with easter eggs, I'd rather somebody just delete this than people cause
-//the game to lag even more in the name of one-day content.
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-//ALSO, MOST IMPORTANTLY: Don't add stupid stuff! Discuss bonus content with Project-Heads first please!//
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-// ~Carn
-
-/hook/startup/proc/updateHoliday()
- Get_Holiday()
- return 1
-
-//sets up the Holiday global variable. Shouldbe called on game configuration or something.
-/proc/Get_Holiday()
- if(!Holiday) return // Holiday stuff was not enabled in the config!
-
- Holiday = null // reset our switch now so we can recycle it as our Holiday name
-
- var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year
- var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
- var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
-
- //Main switch. If any of these are too dumb/inappropriate, or you have better ones, feel free to change whatever
- switch(MM)
- if(1) //Jan
- switch(DD)
- if(1) Holiday = "New Year's Day"
-
- if(2) //Feb
- switch(DD)
- if(2) Holiday = "Groundhog Day"
- if(14) Holiday = "Valentine's Day"
- if(17) Holiday = "Random Acts of Kindness Day"
-
- if(3) //Mar
- switch(DD)
- if(14) Holiday = "Pi Day"
- if(17) Holiday = "St. Patrick's Day"
- if(27)
- if(YY == 16)
- Holiday = "Easter"
- if(31)
- if(YY == 13)
- Holiday = "Easter"
-
- if(4) //Apr
- switch(DD)
- if(1)
- Holiday = "April Fool's Day"
- if(YY == 18 && prob(50)) Holiday = "Easter"
- if(5)
- if(YY == 15) Holiday = "Easter"
- if(16)
- if(YY == 17) Holiday = "Easter"
- if(20)
- Holiday = "Four-Twenty"
- if(YY == 14 && prob(50)) Holiday = "Easter"
- if(22) Holiday = "Earth Day"
-
- if(5) //May
- switch(DD)
- if(1) Holiday = "Labour Day"
- if(4) Holiday = "FireFighter's Day"
- if(12) Holiday = "Owl and Pussycat Day" //what a dumb day of observence...but we -do- have costumes already :3
-
- if(6) //Jun
-
- if(7) //Jul
- switch(DD)
- if(1) Holiday = "Doctor's Day"
- if(2) Holiday = "UFO Day"
- if(8) Holiday = "Writer's Day"
- if(30) Holiday = "Friendship Day"
-
- if(8) //Aug
- switch(DD)
- if(5) Holiday = "Beer Day"
-
- if(9) //Sep
- switch(DD)
- if(19) Holiday = "Talk-Like-a-Pirate Day"
- if(28) Holiday = "Stupid-Questions Day"
-
- if(10) //Oct
- switch(DD)
- if(4) Holiday = "Animal's Day"
- if(7) Holiday = "Smiling Day"
- if(16) Holiday = "Boss' Day"
- if(31) Holiday = "Halloween"
-
- if(11) //Nov
- switch(DD)
- if(1) Holiday = "Vegan Day"
- if(13) Holiday = "Kindness Day"
- if(19) Holiday = "Flowers Day"
- if(21) Holiday = "Saying-'Hello' Day"
-
- if(12) //Dec
- switch(DD)
- if(10) Holiday = "Human-Rights Day"
- if(14) Holiday = "Monkey Day"
- if(21) if(YY==12) Holiday = "End of the World"
- if(22) Holiday = "Orgasming Day" //lol. These all actually exist
- if(24) Holiday = "Christmas Eve"
- if(25) Holiday = "Christmas"
- if(26) Holiday = "Boxing Day"
- if(31) Holiday = "New Year's Eve"
-
- if(!Holiday)
- //Friday the 13th
- if(DD == 13)
- if(time2text(world.timeofday, "DDD") == "Fri")
- Holiday = "Friday the 13th"
-
-//Allows GA and GM to set the Holiday variable
-/client/proc/Set_Holiday(T as text|null)
- set name = ".Set Holiday"
- set category = "Event"
- set desc = "Force-set the Holiday variable to make the game think it's a certain day."
- if(!check_rights(R_SERVER)) return
-
- Holiday = T
- //get a new station name
- station_name = null
- station_name()
- //update our hub status
- world.update_status()
- Holiday_Game_Start()
-
- message_admins("ADMIN: Event: [key_name_admin(src)] force-set Holiday to \"[Holiday]\"")
- log_admin("[key_name(src)] force-set Holiday to \"[Holiday]\"")
-
-
-//Run at the start of a round
-/proc/Holiday_Game_Start()
- if(Holiday)
- to_chat(world, "and...")
- to_chat(world, "Happy [Holiday] Everybody!")
- switch(Holiday) //special holidays
- if("Easter")
- //do easter stuff
- if("Christmas Eve","Christmas")
- Christmas_Game_Start()
-
- return
-
-//Nested in the random events loop. Will be triggered every 2 minutes
-/proc/Holiday_Random_Event()
- switch(Holiday) //special holidays
-
- if("",null) //no Holiday today! Back to work!
- return
-
- if("Easter") //I'll make this into some helper procs at some point
-/* var/list/turf/simulated/floor/Floorlist = list()
- for(var/turf/simulated/floor/T)
- if(T.contents)
- Floorlist += T
- var/turf/simulated/floor/F = Floorlist[rand(1,Floorlist.len)]
- Floorlist = null
- var/obj/structure/closet/C = locate(/obj/structure/closet) in F
- var/obj/item/reagent_containers/food/snacks/chocolateegg/wrapped/Egg
- if( C ) Egg = new(C)
- else Egg = new(F)
-*/
-/* var/list/obj/containers = list()
- for(var/obj/item/storage/S in world)
- if(!is_station_level(S.z)) continue
- containers += S
-
- message_admins("DEBUG: Event: Egg spawned at [Egg.loc] ([Egg.x],[Egg.y],[Egg.z])")*/
- if("End of the World")
- if(prob(eventchance)) GameOver()
-
- if("Christmas","Christmas Eve")
- if(prob(eventchance)) ChristmasEvent()
diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm
index 90718ef2928..2c718580d2c 100644
--- a/code/modules/events/ion_storm.dm
+++ b/code/modules/events/ion_storm.dm
@@ -493,7 +493,7 @@
/proc/generate_static_ion_law()
var/list/players = list()
for(var/mob/living/carbon/human/player in GLOB.player_list)
- if( !player.mind || player.mind.assigned_role == player.mind.special_role || player.client.inactivity > MinutesToTicks(10))
+ if( !player.mind || player.mind.assigned_role == player.mind.special_role || player.client.inactivity > 10 MINUTES)
continue
players += player.real_name
var/random_player = "The Captain"
diff --git a/code/modules/events/mass_hallucination.dm b/code/modules/events/mass_hallucination.dm
index 196642ce39c..b8f45023a27 100644
--- a/code/modules/events/mass_hallucination.dm
+++ b/code/modules/events/mass_hallucination.dm
@@ -2,7 +2,13 @@
announceWhen = rand(0, 20)
/datum/event/mass_hallucination/start()
- for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
+ if(H.stat == DEAD)
+ continue
+ var/turf/T = get_turf(H)
+ if(!is_station_level(T.z))
+ continue
var/armor = H.getarmor(type = "rad")
if((RADIMMUNE in H.dna.species.species_traits) || armor >= 75) // Leave radiation-immune species/rad armored players completely unaffected
continue
diff --git a/code/modules/events/money_hacker.dm b/code/modules/events/money_hacker.dm
index 928b35e84ea..ba50cbbfd8f 100644
--- a/code/modules/events/money_hacker.dm
+++ b/code/modules/events/money_hacker.dm
@@ -23,7 +23,7 @@ GLOBAL_VAR_INIT(account_hack_attempted, 0)
Notifications will be sent as updates occur. "
var/my_department = "[station_name()] firewall subroutines"
- for(var/obj/machinery/message_server/MS in world)
+ for(var/obj/machinery/message_server/MS in GLOB.machines)
if(!MS.active) continue
MS.send_rc_message("Head of Personnel's Desk", my_department, message, "", "", 2)
@@ -38,7 +38,7 @@ GLOBAL_VAR_INIT(account_hack_attempted, 0)
if(!isnull(affected_account) && !affected_account.suspended)
message = "The hack attempt has succeeded."
- var/lost = affected_account.money * (MINIMUM_PERCENTAGE_LOSS + rand(0,VARIABLE_LOSS) / 10);
+ var/lost = affected_account.money * (MINIMUM_PERCENTAGE_LOSS + rand(0,VARIABLE_LOSS) / 10)
affected_account.phantom_charge(lost)
@@ -64,7 +64,7 @@ GLOBAL_VAR_INIT(account_hack_attempted, 0)
var/my_department = "[station_name()] firewall subroutines"
- for(var/obj/machinery/message_server/MS in world)
+ for(var/obj/machinery/message_server/MS in GLOB.machines)
if(!MS.active) continue
MS.send_rc_message("Head of Personnel's Desk", my_department, message, "", "", 2)
diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm
index 35c976fa2f9..748d39f2080 100644
--- a/code/modules/events/prison_break.dm
+++ b/code/modules/events/prison_break.dm
@@ -47,7 +47,7 @@
if(areas && areas.len > 0)
var/my_department = "[station_name()] firewall subroutines"
var/rc_message = "An unknown malicious program has been detected in the [english_list(areaName)] lighting and airlock control systems at [station_time_timestamp()]. Systems will be fully compromised within approximately three minutes. Direct intervention is required immediately. "
- for(var/obj/machinery/message_server/MS in world)
+ for(var/obj/machinery/message_server/MS in GLOB.machines)
MS.send_rc_message("Engineering", my_department, rc_message, "", "", 2)
for(var/mob/living/silicon/ai/A in GLOB.player_list)
to_chat(A, "Malicious program detected in the [english_list(areaName)] lighting and airlock control systems by [my_department].")
diff --git a/code/modules/events/rogue_drones.dm b/code/modules/events/rogue_drones.dm
index e2a7dc739c3..02fa69b7c3e 100644
--- a/code/modules/events/rogue_drones.dm
+++ b/code/modules/events/rogue_drones.dm
@@ -6,7 +6,8 @@
/datum/event/rogue_drone/start()
//spawn them at the same place as carp
var/list/possible_spawns = list()
- for(var/obj/effect/landmark/C in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/C = thing
if(C.name == "carpspawn")
possible_spawns.Add(C)
diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm
index 918746f4595..ab8a405785f 100644
--- a/code/modules/events/sentience.dm
+++ b/code/modules/events/sentience.dm
@@ -10,7 +10,7 @@
for(var/mob/living/simple_animal/L in GLOB.alive_mob_list)
var/turf/T = get_turf(L)
- if (T.z != 1)
+ if (!is_station_level(T.z))
continue
if(!(L in GLOB.player_list) && !L.mind && (L.sentience_type == sentience_type))
potential += L
diff --git a/code/modules/events/slaughterevent.dm b/code/modules/events/slaughterevent.dm
index 999303bf069..91918894cfd 100644
--- a/code/modules/events/slaughterevent.dm
+++ b/code/modules/events/slaughterevent.dm
@@ -16,13 +16,15 @@
var/datum/mind/player_mind = new /datum/mind(key_of_slaughter)
player_mind.active = 1
var/list/spawn_locs = list()
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(isturf(L.loc))
switch(L.name)
if("revenantspawn")
spawn_locs += L.loc
if(!spawn_locs) //If we can't find any revenant spawns, try the carp spawns
- for(var/obj/effect/landmark/L in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/L = thing
if(isturf(L.loc))
switch(L.name)
if("carpspawn")
@@ -31,7 +33,7 @@
spawn_locs += get_turf(player_mind.current)
if(!spawn_locs) //If we can't find THAT, then just retry
return kill()
- var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(pick(spawn_locs))
+ var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(pick(spawn_locs))
var/mob/living/simple_animal/slaughter/S = new /mob/living/simple_animal/slaughter/(holder)
S.holder = holder
player_mind.transfer_to(S)
diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm
index e09e1efb705..694f8e98c89 100644
--- a/code/modules/events/spider_infestation.dm
+++ b/code/modules/events/spider_infestation.dm
@@ -15,7 +15,7 @@ GLOBAL_VAR_INIT(sent_spiders_to_station, 0)
/datum/event/spider_infestation/start()
var/list/vents = list()
- for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in world)
+ for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in SSair.atmos_machinery)
if(is_station_level(temp_vent.loc.z) && !temp_vent.welded)
if(temp_vent.parent.other_atmosmch.len > 50)
vents += temp_vent
diff --git a/code/modules/events/spider_terror.dm b/code/modules/events/spider_terror.dm
index 75b86d20cb0..79acc49fe73 100644
--- a/code/modules/events/spider_terror.dm
+++ b/code/modules/events/spider_terror.dm
@@ -1,3 +1,4 @@
+#define TS_HIGHPOP_TRIGGER 80
/datum/event/spider_terror
announceWhen = 240
@@ -22,23 +23,32 @@
if(temp_vent.parent.other_atmosmch.len > 50)
vents += temp_vent
var/spider_type
- var/infestation_type = pick(1, 2, 3, 4, 5)
+ var/infestation_type
+ if((length(GLOB.clients)) < TS_HIGHPOP_TRIGGER)
+ infestation_type = pick(1, 2, 3, 4)
+ else
+ infestation_type = pick(2, 3, 4, 5)
switch(infestation_type)
if(1)
+ // Weakest, only used during lowpop.
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/green
spawncount = 5
if(2)
- spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/white
- spawncount = 2
- if(3)
+ // Fairly weak. Dangerous in single combat but has little staying power. Always gets whittled down.
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/prince
spawncount = 1
+ if(3)
+ // Variable. Depends how many they infect.
+ spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/white
+ spawncount = 2
if(4)
- spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/queen
- spawncount = 1
- if(5)
+ // Pretty strong.
spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/princess
spawncount = 2
+ if(5)
+ // Strongest, only used during highpop.
+ spider_type = /mob/living/simple_animal/hostile/poison/terror_spider/queen
+ spawncount = 1
while(spawncount >= 1 && vents.len)
var/obj/machinery/atmospherics/unary/vent_pump/vent = pick(vents)
@@ -60,3 +70,6 @@
new spider_type(vent.loc)
spawncount--
+
+#undef TS_HIGHPOP_TRIGGER
+
diff --git a/code/modules/events/traders.dm b/code/modules/events/traders.dm
index 4159885e993..0beeb3691e2 100644
--- a/code/modules/events/traders.dm
+++ b/code/modules/events/traders.dm
@@ -24,7 +24,8 @@ GLOBAL_LIST_INIT(unused_trade_stations, list("sol"))
return
var/list/spawnlocs = list()
- for(var/obj/effect/landmark/landmark in GLOB.landmarks_list)
+ for(var/thing in GLOB.landmarks_list)
+ var/obj/effect/landmark/landmark = thing
if(landmark.name == "traderstart_[station]")
spawnlocs += get_turf(landmark)
if(!spawnlocs.len)
diff --git a/code/modules/flufftext/Dreaming.dm b/code/modules/flufftext/Dreaming.dm
index d4c06fdc3a3..a24b73ae56c 100644
--- a/code/modules/flufftext/Dreaming.dm
+++ b/code/modules/flufftext/Dreaming.dm
@@ -19,7 +19,7 @@
var/list/newlist = dreamlist.Copy()
for(var/i in 1 to newlist.len)
newlist[i] = replacetext(newlist[i], "\[DREAMER\]", "[user.name]")
- return dreamlist
+ return newlist
//NIGHTMARES
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 51ac13d4e13..21b99acb910 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -149,10 +149,12 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/fake_flood/process()
if(!target)
qdel(src)
+ return
if(next_expand <= world.time)
radius++
if(radius > FAKE_FLOOD_MAX_RADIUS)
qdel(src)
+ return
Expand()
if((get_turf(target) in flood_turfs) && !target.internal)
target.hallucinate("fake_alert", "too_much_tox")
@@ -460,8 +462,9 @@ Gunshots/explosions/opening doors/less rare audio (done)
target = T
var/image/A = null
var/kind = force_kind ? force_kind : pick("clown", "corgi", "carp", "skeleton", "demon","zombie")
- for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
- if(H == target)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
+ if(H.stat == DEAD || H == target)
continue
if(skip_nearby && (H in view(target)))
continue
@@ -539,7 +542,8 @@ Gunshots/explosions/opening doors/less rare audio (done)
var/mob/living/carbon/human/clone = null
var/clone_weapon = null
- for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
if(H.stat || H.lying)
continue
clone = H
@@ -751,8 +755,10 @@ GLOBAL_LIST_INIT(non_fakeattack_weapons, list(/obj/item/gun/projectile, /obj/ite
target.client.images.Remove(speech_overlay)
else // Radio talk
var/list/humans = list()
- for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
- humans += H
+ for(var/thing in GLOB.human_list)
+ var/mob/living/carbon/human/H = thing
+ if(H.stat != DEAD)
+ humans += H
person = pick(humans)
target.hear_radio(message_to_multilingual(pick(radio_messages), pick(person.languages)), speaker = person, part_a = "\[[get_frequency_name(PUB_FREQ)]\] ", part_b = " ")
qdel(src)
diff --git a/code/modules/food_and_drinks/drinks/bottler/bottler.dm b/code/modules/food_and_drinks/drinks/bottler/bottler.dm
index b1667fc6a00..d7f1736bb4a 100644
--- a/code/modules/food_and_drinks/drinks/bottler/bottler.dm
+++ b/code/modules/food_and_drinks/drinks/bottler/bottler.dm
@@ -82,7 +82,6 @@
else //If it doesn't qualify in the above checks, we don't want it. Inform the person so they (ideally) stop trying to put the nuke disc in.
to_chat(user, "You aren't sure this is able to be processed by the machine.")
return 0
- return ..()
/obj/machinery/bottler/wrench_act(mob/user, obj/item/I)
. = TRUE
diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
index 90929175eba..f77d4b60ab4 100644
--- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm
+++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
@@ -72,8 +72,8 @@
if(istype(H.head, /obj/item/clothing/head) && affecting == "head")
// If their head has an armor value, assign headarmor to it, else give it 0.
- if(H.head.armor["melee"])
- headarmor = H.head.armor["melee"]
+ if(H.head.armor.getRating("melee"))
+ headarmor = H.head.armor.getRating("melee")
else
headarmor = 0
else
@@ -115,7 +115,7 @@
//The reagents in the bottle splash all over the target, thanks for the idea Nodrak
SplashReagents(target)
- //Finally, smash the bottle. This kills (del) the bottle.
+ //Finally, smash the bottle. This kills (qdel) the bottle.
smash(target, user)
/obj/item/reagent_containers/food/drinks/bottle/proc/SplashReagents(mob/M)
@@ -124,6 +124,13 @@
reagents.reaction(M, REAGENT_TOUCH)
reagents.clear_reagents()
+/obj/item/reagent_containers/food/drinks/bottle/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(!reagents.total_volume)
+ C.stored_comms["glass"] += 3
+ qdel(src)
+ return TRUE
+ return ..()
+
//Keeping this here for now, I'll ask if I should keep it here.
/obj/item/broken_bottle
name = "Broken Bottle"
@@ -141,6 +148,11 @@
var/icon/broken_outline = icon('icons/obj/drinks.dmi', "broken")
sharp = 1
+/obj/item/broken_bottle/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ C.stored_comms["glass"] += 3
+ qdel(src)
+ return TRUE
+
/obj/item/reagent_containers/food/drinks/bottle/gin
name = "Griffeater Gin"
desc = "A bottle of high quality gin, produced in the New London Space Station."
diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm
index 27f0919a3ce..2180f9a0f63 100644
--- a/code/modules/food_and_drinks/food.dm
+++ b/code/modules/food_and_drinks/food.dm
@@ -33,6 +33,9 @@
deltimer(ant_timer)
return ..()
+/obj/item/reagent_containers/food/set_APTFT()
+ set hidden = TRUE
+
/obj/item/reagent_containers/food/proc/check_for_ants()
if(!antable)
return
diff --git a/code/modules/food_and_drinks/food/foods/bread.dm b/code/modules/food_and_drinks/food/foods/bread.dm
index d888a532c01..55255658233 100644
--- a/code/modules/food_and_drinks/food/foods/bread.dm
+++ b/code/modules/food_and_drinks/food/foods/bread.dm
@@ -166,6 +166,15 @@
list_reagents = list("nutriment" = 2, "vitamin" = 2)
tastes = list("bread" = 2)
+/obj/item/reagent_containers/food/snacks/toast
+ name = "Toast"
+ desc = "Yeah! Toast!"
+ icon_state = "toast"
+ filling_color = "#B2580E"
+ bitesize = 3
+ list_reagents = list("nutriment" = 3)
+ tastes = list("toast" = 2)
+
/obj/item/reagent_containers/food/snacks/jelliedtoast
name = "Jellied Toast"
desc = "A slice of bread covered with delicious jam."
@@ -198,3 +207,5 @@
trash = /obj/item/trash/waffles
filling_color = "#E6DEB5"
list_reagents = list("nutriment" = 8, "vitamin" = 1)
+
+
diff --git a/code/modules/food_and_drinks/food/foods/desserts.dm b/code/modules/food_and_drinks/food/foods/desserts.dm
index 9e8ded0bd1b..67034e164ce 100644
--- a/code/modules/food_and_drinks/food/foods/desserts.dm
+++ b/code/modules/food_and_drinks/food/foods/desserts.dm
@@ -17,10 +17,10 @@
update_icon()
/obj/item/reagent_containers/food/snacks/icecream/update_icon()
- overlays.Cut()
- var/image/filling = image('icons/obj/kitchen.dmi', src, "icecream_color")
- filling.icon += mix_color_from_reagents(reagents.reagent_list)
- overlays += filling
+ cut_overlays()
+ var/mutable_appearance/filling = mutable_appearance('icons/obj/kitchen.dmi', "icecream_color")
+ filling.color = mix_color_from_reagents(reagents.reagent_list)
+ add_overlay(filling)
/obj/item/reagent_containers/food/snacks/icecream/icecreamcone
name = "ice cream cone"
diff --git a/code/modules/food_and_drinks/food/foods/seafood.dm b/code/modules/food_and_drinks/food/foods/seafood.dm
index b74ab0c3149..d4134ebe516 100644
--- a/code/modules/food_and_drinks/food/foods/seafood.dm
+++ b/code/modules/food_and_drinks/food/foods/seafood.dm
@@ -129,7 +129,7 @@
tastes = list("shrimp" = 1, "batter" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Ebi_maki
- name = "ebi makiroll"
+ name = "ebi maki roll"
desc = "A large unsliced roll of Ebi Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "Ebi_maki"
@@ -149,7 +149,7 @@
tastes = list("shrimp" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Ikura_maki
- name = "ikura makiroll"
+ name = "ikura maki roll"
desc = "A large unsliced roll of Ikura Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "Ikura_maki"
@@ -169,7 +169,7 @@
tastes = list("salmon roe" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Sake_maki
- name = "sake makiroll"
+ name = "sake maki roll"
desc = "A large unsliced roll of Sake Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "Sake_maki"
@@ -189,7 +189,7 @@
tastes = list("raw salmon" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/SmokedSalmon_maki
- name = "smoked salmon makiroll"
+ name = "smoked salmon maki roll"
desc = "A large unsliced roll of Smoked Salmon Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "SmokedSalmon_maki"
@@ -209,7 +209,7 @@
tastes = list("smoked salmon" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Tamago_maki
- name = "tamago makiroll"
+ name = "tamago maki roll"
desc = "A large unsliced roll of Tamago Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "Tamago_maki"
@@ -229,7 +229,7 @@
tastes = list("egg" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Inari_maki
- name = "inari makiroll"
+ name = "inari maki roll"
desc = "A large unsliced roll of Inari Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "Inari_maki"
@@ -249,7 +249,7 @@
tastes = list("fried tofu" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Masago_maki
- name = "masago makiroll"
+ name = "masago maki roll"
desc = "A large unsliced roll of Masago Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "Masago_maki"
@@ -269,7 +269,7 @@
tastes = list("goldfish roe" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Tobiko_maki
- name = "tobiko makiroll"
+ name = "tobiko maki roll"
desc = "A large unsliced roll of Tobkio Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "Tobiko_maki"
@@ -289,7 +289,7 @@
tastes = list("shark roe" = 1, "rice" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/TobikoEgg_maki
- name = "tobiko and egg makiroll"
+ name = "tobiko and egg maki roll"
desc = "A large unsliced roll of Tobkio and Egg Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "TobikoEgg_maki"
@@ -309,7 +309,7 @@
tastes = list("shark roe" = 1, "rice" = 1, "egg" = 1, "seaweed" = 1)
/obj/item/reagent_containers/food/snacks/sliceable/Tai_maki
- name = "tai makiroll"
+ name = "tai maki roll"
desc = "A large unsliced roll of Tai Sushi."
icon = 'icons/obj/food/seafood.dmi'
icon_state = "Tai_maki"
diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
index 7d17ac07720..db078675db1 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm
@@ -278,11 +278,6 @@
if(!UserOverride)
add_attack_logs(user, occupant, "Gibbed in [src]", !!occupant.ckey ? ATKLOG_FEW : ATKLOG_ALL)
- if(!iscarbon(user))
- occupant.LAssailant = null
- else
- occupant.LAssailant = user
-
else //this looks ugly but it's better than a copy-pasted startgibbing proc override
occupant.create_attack_log("Was gibbed by an autogibber (\the [src])")
add_attack_logs(src, occupant, "gibbed")
diff --git a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm
index 69eda1e4269..0e9ecbaa7e4 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat.dm
@@ -43,10 +43,9 @@
return
if(istype(I, /obj/item/reagent_containers/food/snacks/icecream))
if(!I.reagents.has_reagent("sprinkles"))
- if(I.reagents.total_volume > 29) I.reagents.remove_any(1)
- I.reagents.add_reagent("sprinkles",1)
- var/image/sprinkles = image('icons/obj/kitchen.dmi', src, "sprinkles")
- I.overlays += sprinkles
+ if(I.reagents.total_volume > 29)
+ I.reagents.remove_any(1)
+ I.reagents.add_reagent("sprinkles", 1)
I.name += " with sprinkles"
I.desc += ". This also has sprinkles."
else
diff --git a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat_2.dm b/code/modules/food_and_drinks/kitchen_machinery/icecream_vat_2.dm
deleted file mode 100644
index c1602a14251..00000000000
--- a/code/modules/food_and_drinks/kitchen_machinery/icecream_vat_2.dm
+++ /dev/null
@@ -1,256 +0,0 @@
-#define ICECREAM_VANILLA 1
-#define FLAVOUR_CHOCOLATE 2
-#define FLAVOUR_STRAWBERRY 3
-#define FLAVOUR_BLUE 4
-#define CONE_WAFFLE 5
-#define CONE_CHOC 6
-#define INGR_MILK 7
-#define INGR_FLOUR 8
-#define INGR_SUGAR 9
-#define INGR_ICE 10
-#define MUCK 11
-
-GLOBAL_LIST_INIT(ingredients_source, list(
-"berryjuice" = FLAVOUR_STRAWBERRY,\
-"cocoa" = FLAVOUR_CHOCOLATE,\
-"singulo" = FLAVOUR_BLUE,\
-"milk" = INGR_MILK,\
-"soymilk" = INGR_MILK,\
-"ice" = INGR_ICE,\
-"flour" = INGR_FLOUR,\
-"sugar" = INGR_SUGAR,\
-))
-
-/proc/get_icecream_flavour_string(var/flavour_type)
- switch(flavour_type)
- if(FLAVOUR_CHOCOLATE)
- return "chocolate"
- if(FLAVOUR_STRAWBERRY)
- return "strawberry"
- if(FLAVOUR_BLUE)
- return "blue"
- if(CONE_WAFFLE)
- return "waffle"
- if(CONE_CHOC)
- return "chocolate"
- if(INGR_MILK)
- return "milk"
- if(INGR_FLOUR)
- return "flour"
- if(INGR_SUGAR)
- return "sugar"
- if(INGR_ICE)
- return "ice"
- if(MUCK)
- return "muck"
- else
- return "vanilla"
-
-/obj/machinery/icecream_vat
- name = "icecream vat"
- desc = "Ding-aling ding dong. Get your Nanotrasen-approved ice cream!"
- icon = 'icons/obj/kitchen.dmi'
- icon_state = "icecream_vat"
- density = 1
- anchored = 0
- max_integrity = 300
- var/list/ingredients = list()
- var/dispense_flavour = 1
- var/obj/item/reagent_containers/glass/held_container
-
-/obj/machinery/icecream_vat/New()
- ..()
- create_reagents(50)
- while(ingredients.len < 11)
- ingredients.Add(5)
-
-/obj/machinery/icecream_vat/attack_hand(mob/user)
- user.set_machine(src)
- interact(user)
-
-/obj/machinery/icecream_vat/interact(mob/user)
- var/dat
- dat += "Dispense vanilla icecream There is [ingredients[ICECREAM_VANILLA]] scoops of vanilla icecream left (made from milk and ice). "
- dat += "Dispense strawberry icecream There is [ingredients[FLAVOUR_STRAWBERRY]] dollops of strawberry flavouring left (obtained from berry juice. "
- dat += "Dispense chocolate icecream There is [ingredients[FLAVOUR_CHOCOLATE]] dollops of chocolate flavouring left (obtained from cocoa powder). "
- dat += "Dispense blue icecream There is [ingredients[FLAVOUR_BLUE]] dollops of blue flavouring left (obtained from bluespace tomato singulo). "
- dat += " "
- dat += "Dispense waffle cones There are [ingredients[CONE_WAFFLE]] waffle cones left. "
- dat += "Dispense chocolate cones There are [ingredients[CONE_CHOC]] chocolate cones left. "
- dat += " "
- dat += "Make waffle cones There is [ingredients[INGR_FLOUR]]/[ingredients[INGR_SUGAR]] of flour and sugar left. "
- dat += "Make chocolate cones There is [ingredients[FLAVOUR_CHOCOLATE]]/[ingredients[CONE_WAFFLE]] of chocolate flavouring and waffle cones left. "
- dat += "Make vanilla icecream There is [ingredients[INGR_MILK]]/[ingredients[INGR_ICE]] of milk and ice left. "
- dat += " "
- if(held_container)
- dat += "Eject [held_container] "
- else
- dat += "No beaker inserted. "
- dat += "Refresh Close"
-
- var/datum/browser/popup = new(user, "icecreamvat", name, 600, 400)
- popup.set_content(dat)
- popup.open(0)
-
-/obj/machinery/icecream_vat/attackby(obj/item/O, mob/user, params)
- if(istype(O, /obj/item/reagent_containers))
- if(istype(O, /obj/item/reagent_containers/food/snacks/icecream))
- var/obj/item/reagent_containers/food/snacks/icecream/I = O
- if(!I.ice_creamed)
- if(ingredients[ICECREAM_VANILLA] > 0)
- var/flavour_name = get_icecream_flavour_string(dispense_flavour)
- if(dispense_flavour < 11 && ingredients[dispense_flavour] > 0)
- visible_message("[bicon(src)] [user] scoops delicious [flavour_name] flavoured icecream into [I].")
- ingredients[dispense_flavour] -= 1
- ingredients[ICECREAM_VANILLA] -= 1
-
- I.add_ice_cream(dispense_flavour)
- if(held_container)
- held_container.reagents.trans_to(I, 10)
- if(I.reagents.total_volume < 10)
- I.reagents.add_reagent("sugar", 10 - I.reagents.total_volume)
- else
- to_chat(user, "There is not enough [flavour_name] flavouring left! Insert more of the required ingredients.")
- else
- to_chat(user, "There is not enough icecream left! Insert more milk and ice.")
- else
- to_chat(user, "[O] already has icecream in it.")
- else if(istype(O, /obj/item/reagent_containers/glass))
- if(held_container)
- to_chat(user, "You must remove [held_container] from [src] first.")
- else
- if(!user.drop_item())
- to_chat(user, "\The [O] is stuck to your hand!")
- return
- O.forceMove(src)
- to_chat(user, "You insert [O] into [src].")
- held_container = O
- else
- var/obj/item/reagent_containers/R = O
- if(R.reagents)
- visible_message("[user] has emptied all of [R] into [src].")
- for(var/datum/reagent/current_reagent in R.reagents.reagent_list)
- if(GLOB.ingredients_source[current_reagent.id])
- add(GLOB.ingredients_source[current_reagent.id], current_reagent.volume / 2)
- else
- add(MUCK, current_reagent.volume / 5)
- R.reagents.clear_reagents()
- return 1
- else
- return ..()
-
-/obj/machinery/icecream_vat/proc/add(var/add_type, var/amount)
- if(add_type <= ingredients.len)
- ingredients[add_type] += amount
- updateDialog()
-
-/obj/machinery/icecream_vat/proc/make(var/mob/user, var/make_type)
- switch(make_type)
- if(CONE_WAFFLE)
- if(ingredients[INGR_FLOUR] > 0 && ingredients[INGR_SUGAR] > 0)
- var/amount = max( min(ingredients[INGR_FLOUR], ingredients[INGR_SUGAR]), 5)
- ingredients[INGR_FLOUR] -= amount
- ingredients[INGR_SUGAR] -= amount
- ingredients[CONE_WAFFLE] += amount
- visible_message("[user] cooks up some waffle cones.")
- else
- to_chat(user, "You require sugar and flour to make waffle cones.")
- if(CONE_CHOC)
- if(ingredients[FLAVOUR_CHOCOLATE] > 0 && ingredients[CONE_WAFFLE] > 0)
- var/amount = min(ingredients[CONE_WAFFLE], ingredients[FLAVOUR_CHOCOLATE])
- ingredients[CONE_WAFFLE] -= amount
- ingredients[FLAVOUR_CHOCOLATE] -= amount
- ingredients[CONE_CHOC] += amount
- visible_message("[user] cooks up some chocolate cones.")
- else
- to_chat(user, "You require waffle cones and chocolate flavouring to make chocolate cones.")
- if(ICECREAM_VANILLA)
- if(ingredients[INGR_ICE] > 0 && ingredients[INGR_MILK] > 0)
- var/amount = min(ingredients[INGR_ICE], ingredients[INGR_MILK])
- ingredients[INGR_ICE] -= amount
- ingredients[INGR_MILK] -= amount
- ingredients[ICECREAM_VANILLA] += amount
- visible_message("[user] whips up some vanilla icecream.")
- else
- to_chat(user, "You require milk and ice to make vanilla icecream.")
- updateDialog()
-
-/obj/machinery/icecream_vat/Topic(href, href_list)
- if(..())
- return
- if(href_list["dispense"])
- dispense_flavour = text2num(href_list["dispense"])
- visible_message("[usr] sets [src] to dispense [get_icecream_flavour_string(dispense_flavour)] flavoured icecream.")
-
- if(href_list["cone"])
- var/dispense_cone = text2num(href_list["cone"])
- if(ingredients[dispense_cone] <= ingredients.len)
- var/cone_name = get_icecream_flavour_string(dispense_cone)
- if(ingredients[dispense_cone] >= 1)
- ingredients[dispense_cone] -= 1
- var/obj/item/reagent_containers/food/snacks/icecream/I = new(loc)
- I.cone_type = cone_name
- I.icon_state = "icecream_cone_[cone_name]"
- I.desc = "Delicious [cone_name] cone, but no ice cream."
- visible_message("[usr] dispenses a crunchy [cone_name] cone from [src].")
- else
- to_chat(usr, "There are no [cone_name] cones left!")
- updateDialog()
-
- if(href_list["make"])
- make( usr, text2num(href_list["make"]) )
- updateDialog()
-
- if(href_list["eject"])
- if(held_container)
- held_container.forceMove(loc)
- held_container = null
- updateDialog()
-
- if(href_list["refresh"])
- updateDialog()
-
- if(href_list["close"])
- usr.unset_machine()
- usr << browse(null,"window=icecreamvat")
- return
-
-/obj/machinery/icecream_vat/deconstruct(disassembled = TRUE)
- if(!(flags & NODECONSTRUCT))
- new /obj/item/stack/sheet/metal(loc, 4)
- qdel(src)
-
-
-/obj/item/reagent_containers/food/snacks/icecream
- name = "ice cream cone"
- desc = "Delicious waffle cone, but no ice cream."
- icon = 'icons/obj/kitchen.dmi'
- icon_state = "icecream_cone"
- layer = 3.1
- var/ice_creamed = 0
- var/cone_type
- bitesize = 3
-
-/obj/item/reagent_containers/food/snacks/icecream/New()
- ..()
- create_reagents(20)
- reagents.add_reagent("nutriment", 5)
-
-/obj/item/reagent_containers/food/snacks/icecream/proc/add_ice_cream(var/flavour)
- var/flavour_name = get_icecream_flavour_string(flavour)
- name = "[flavour_name] icecream"
- overlays += "icecream_[flavour_name]"
- desc = "Delicious [cone_type] cone with a dollop of [flavour_name] ice cream."
- ice_creamed = 1
-
-#undef ICECREAM_VANILLA
-#undef FLAVOUR_CHOCOLATE
-#undef FLAVOUR_STRAWBERRY
-#undef FLAVOUR_BLUE
-#undef CONE_WAFFLE
-#undef CONE_CHOC
-#undef INGR_MILK
-#undef INGR_FLOUR
-#undef INGR_SUGAR
-#undef INGR_ICE
-#undef MUCK
diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
index 61f887e44bc..6891ab578bc 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm
@@ -175,7 +175,7 @@
if(default_unfasten_wrench(user, O))
return
- default_deconstruction_crowbar(user, O)
+ default_deconstruction_crowbar(user, O)
var/obj/item/what = O
diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
index 756d2cf77ef..f179de1459a 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm
@@ -1,51 +1,73 @@
-/* SmartFridge. Much todo
-*/
+#define SMART_FRIDGE_LOCK_SHORTED -1
+
+/**
+ * # Smart Fridge
+ *
+ * Stores items of a specified type.
+ */
/obj/machinery/smartfridge
name = "\improper SmartFridge"
icon = 'icons/obj/vending.dmi'
icon_state = "smartfridge"
layer = 2.9
- density = 1
- anchored = 1
+ density = TRUE
+ anchored = TRUE
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 100
+ /// The maximum number of items the fridge can hold. Multiplicated by the matter bin component's rating.
var/max_n_of_items = 1500
- var/item_quants = list()
+ /// Associative list (/text => /number) tracking the amounts of a specific item held by the fridge.
+ var/list/item_quants
+ /// How long in ticks the fridge is electrified for. Decrements every process.
var/seconds_electrified = 0
+ /// Whether the fridge should randomly shoot held items at a nearby living target or not.
var/shoot_inventory = FALSE
+ /// Whether the fridge is locked. Used for the secure variant of the fridge.
var/locked = FALSE
+ /// Whether the fridge requires ID scanning. Used for the secure variant of the fridge.
var/scan_id = TRUE
+ /// Whether the fridge is considered secure. Used for wiring and display.
var/is_secure = FALSE
+ /// Whether the fridge can dry its' contents. Used for display.
var/can_dry = FALSE
+ /// Whether the fridge is currently drying. Used by [drying racks][/obj/machinery/smartfridge/drying_rack].
var/drying = FALSE
+ /// Whether the fridge's contents are visible on the world icon.
var/visible_contents = TRUE
- var/datum/wires/smartfridge/wires = null
+ /// The wires controlling the fridge.
+ var/datum/wires/smartfridge/wires
+ /// Typecache of accepted item types, init it in [/obj/machinery/smartfridge/Initialize].
+ var/list/accepted_items_typecache
-/obj/machinery/smartfridge/New()
- ..()
+/obj/machinery/smartfridge/Initialize(mapload)
+ . = ..()
+ item_quants = list()
+ // Reagents
create_reagents()
reagents.set_reacting(FALSE)
+ // Components
component_parts = list()
var/obj/item/circuitboard/smartfridge/board = new(null)
board.set_type(type)
component_parts += board
component_parts += new /obj/item/stock_parts/matter_bin(null)
RefreshParts()
-
-/obj/machinery/smartfridge/RefreshParts()
- for(var/obj/item/stock_parts/matter_bin/B in component_parts)
- max_n_of_items = 1500 * B.rating
-
-/obj/machinery/smartfridge/secure
- is_secure = 1
-
-/obj/machinery/smartfridge/New()
- ..()
+ // Wires
if(is_secure)
wires = new/datum/wires/smartfridge/secure(src)
else
wires = new/datum/wires/smartfridge(src)
+ // Accepted items
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/reagent_containers/food/snacks/grown,
+ /obj/item/seeds,
+ /obj/item/grown,
+ ))
+
+/obj/machinery/smartfridge/RefreshParts()
+ for(var/obj/item/stock_parts/matter_bin/B in component_parts)
+ max_n_of_items = 1500 * B.rating
/obj/machinery/smartfridge/Destroy()
QDEL_NULL(wires)
@@ -53,154 +75,6 @@
A.forceMove(loc)
return ..()
-/obj/machinery/smartfridge/proc/accept_check(obj/item/O)
- if(istype(O,/obj/item/reagent_containers/food/snacks/grown/) || istype(O,/obj/item/seeds/) || istype(O,/obj/item/grown/))
- return 1
- return 0
-
-/obj/machinery/smartfridge/seeds
- name = "\improper MegaSeed Servitor"
- desc = "When you need seeds fast!"
- icon = 'icons/obj/vending.dmi'
- icon_state = "seeds"
-
-/obj/machinery/smartfridge/seeds/accept_check(obj/item/O)
- if(istype(O,/obj/item/seeds/))
- return 1
- return 0
-
-/obj/machinery/smartfridge/medbay
- name = "\improper Refrigerated Medicine Storage"
- desc = "A refrigerated storage unit for storing medicine and chemicals."
- icon_state = "smartfridge" //To fix the icon in the map editor.
-
-/obj/machinery/smartfridge/medbay/accept_check(obj/item/O)
- if(istype(O,/obj/item/reagent_containers/glass))
- return 1
- if(istype(O,/obj/item/reagent_containers/iv_bag))
- return 1
- if(istype(O,/obj/item/storage/pill_bottle))
- return 1
- if(ispill(O))
- return 1
- return 0
-
-/obj/machinery/smartfridge/secure/extract
- name = "\improper Slime Extract Storage"
- desc = "A refrigerated storage unit for slime extracts"
- req_access_txt = "47"
-
-/obj/machinery/smartfridge/secure/extract/accept_check(obj/item/O)
- if(istype(O,/obj/item/slime_extract))
- return 1
- return 0
-
-/obj/machinery/smartfridge/secure/medbay
- name = "\improper Secure Refrigerated Medicine Storage"
- desc = "A refrigerated storage unit for storing medicine and chemicals."
- icon_state = "smartfridge" //To fix the icon in the map editor.
- req_one_access_txt = "5;33"
-
-/obj/machinery/smartfridge/secure/medbay/accept_check(obj/item/O)
- if(istype(O,/obj/item/reagent_containers/glass))
- return 1
- if(istype(O,/obj/item/reagent_containers/iv_bag))
- return 1
- if(istype(O,/obj/item/storage/pill_bottle))
- return 1
- if(ispill(O))
- return 1
- return 0
-
-/obj/machinery/smartfridge/secure/chemistry
- name = "\improper Smart Chemical Storage"
- desc = "A refrigerated storage unit for medicine and chemical storage."
- icon_state = "smartfridge" //To fix the icon in the map editor.
- req_access_txt = "33"
- var/list/spawn_meds = list()
-
-/obj/machinery/smartfridge/secure/chemistry/New()
- ..()
- for(var/typekey in spawn_meds)
- var/amount = spawn_meds[typekey]
- if(isnull(amount)) amount = 1
- while(amount)
- var/obj/item/I = new typekey(src)
- if(item_quants[I.name])
- item_quants[I.name]++
- else
- item_quants[I.name] = 1
- SSnanoui.update_uis(src)
- amount--
- update_icon()
-
-/obj/machinery/smartfridge/secure/chemistry/accept_check(obj/item/O)
- if(istype(O,/obj/item/storage/pill_bottle) || istype(O,/obj/item/reagent_containers))
- return 1
- return 0
-
-/obj/machinery/smartfridge/secure/chemistry/preloaded
- spawn_meds = list(
- /obj/item/reagent_containers/food/pill/epinephrine = 12,
- /obj/item/reagent_containers/food/pill/charcoal = 5,
- /obj/item/reagent_containers/glass/bottle/epinephrine = 1,
- /obj/item/reagent_containers/glass/bottle/charcoal = 1)
-
-/obj/machinery/smartfridge/secure/chemistry/preloaded/syndicate
- req_access_txt = null
- req_access = list(ACCESS_SYNDICATE)
-
-/obj/machinery/smartfridge/disks
- name = "disk compartmentalizer"
- desc = "A machine capable of storing a variety of disks. Denoted by most as the DSU (disk storage unit)."
- icon_state = "disktoaster"
- pass_flags = PASSTABLE
- visible_contents = FALSE
-
-/obj/machinery/smartfridge/disks/accept_check(obj/item/O)
- return istype(O, /obj/item/disk)
-
-// ----------------------------
-// Virology Medical Smartfridge
-// ----------------------------
-/obj/machinery/smartfridge/secure/chemistry/virology
- name = "Smart Virus Storage"
- desc = "A refrigerated storage unit for volatile sample storage."
- req_access_txt = "39"
- spawn_meds = list(/obj/item/reagent_containers/syringe/antiviral = 4,
- /obj/item/reagent_containers/glass/bottle/cold = 1,
- /obj/item/reagent_containers/glass/bottle/flu_virion = 1,
- /obj/item/reagent_containers/glass/bottle/mutagen = 1,
- /obj/item/reagent_containers/glass/bottle/plasma = 1,
- /obj/item/reagent_containers/glass/bottle/diphenhydramine = 1)
-
-/obj/machinery/smartfridge/secure/chemistry/virology/accept_check(obj/item/O)
- if(istype(O, /obj/item/reagent_containers/syringe) || istype(O, /obj/item/reagent_containers/glass/bottle) || istype(O, /obj/item/reagent_containers/glass/beaker))
- return 1
- return 0
-
-/obj/machinery/smartfridge/secure/chemistry/virology/preloaded
- spawn_meds = list(
- /obj/item/reagent_containers/syringe/antiviral = 4,
- /obj/item/reagent_containers/glass/bottle/cold = 1,
- /obj/item/reagent_containers/glass/bottle/flu_virion = 1,
- /obj/item/reagent_containers/glass/bottle/mutagen = 1,
- /obj/item/reagent_containers/glass/bottle/plasma = 1,
- /obj/item/reagent_containers/glass/bottle/reagent/synaptizine = 1,
- /obj/item/reagent_containers/glass/bottle/reagent/formaldehyde = 1)
-
-/obj/machinery/smartfridge/secure/chemistry/virology/preloaded/syndicate
- req_access_txt = null
- req_access = list(ACCESS_SYNDICATE)
-
-/obj/machinery/smartfridge/drinks
- name = "\improper Drink Showcase"
- desc = "A refrigerated storage unit for tasty tasty alcohol."
-
-/obj/machinery/smartfridge/drinks/accept_check(obj/item/O)
- if(istype(O,/obj/item/reagent_containers/glass) || istype(O,/obj/item/reagent_containers/food/drinks) || istype(O,/obj/item/reagent_containers/food/condiment))
- return 1
-
/obj/machinery/smartfridge/process()
if(stat & (BROKEN|NOPOWER))
return
@@ -216,52 +90,57 @@
update_icon()
/obj/machinery/smartfridge/update_icon()
+ var/prefix = initial(icon_state)
if(stat & (BROKEN|NOPOWER))
- icon_state = "[initial(icon_state)]-off"
+ icon_state = "[prefix]-off"
else if(visible_contents)
- switch(contents.len)
+ switch(length(contents))
if(0)
- icon_state = "[initial(icon_state)]"
+ icon_state = "[prefix]"
if(1 to 25)
- icon_state = "[initial(icon_state)]1"
+ icon_state = "[prefix]1"
if(26 to 75)
- icon_state = "[initial(icon_state)]2"
+ icon_state = "[prefix]2"
if(76 to INFINITY)
- icon_state = "[initial(icon_state)]3"
+ icon_state = "[prefix]3"
else
- icon_state = "[initial(icon_state)]"
+ icon_state = "[prefix]"
-/*******************
-* Item Adding
-********************/
-
-/obj/machinery/smartfridge/default_deconstruction_screwdriver(mob/user, obj/item/screwdriver/S)
- . = ..(user, icon_state, icon_state, S)
+// Interactions
+/obj/machinery/smartfridge/screwdriver_act(mob/living/user, obj/item/I)
+ . = default_deconstruction_screwdriver(user, icon_state, icon_state, I)
+ if(!.)
+ return
overlays.Cut()
if(panel_open)
overlays += image(icon, "[initial(icon_state)]-panel")
-/obj/machinery/smartfridge/attackby(obj/item/O, var/mob/user)
- if(default_deconstruction_screwdriver(user, O))
- return
-
- if(exchange_parts(user, O))
- return
-
- if(default_unfasten_wrench(user, O))
+/obj/machinery/smartfridge/wrench_act(mob/living/user, obj/item/I)
+ . = default_unfasten_wrench(user, I)
+ if(.)
power_change()
- return
- if(default_deconstruction_crowbar(user, O))
- return
+/obj/machinery/smartfridge/crowbar_act(mob/living/user, obj/item/I)
+ . = default_deconstruction_crowbar(user, I)
- if(istype(O, /obj/item/multitool)||istype(O, /obj/item/wirecutters))
- if(panel_open)
- attack_hand(user)
- return
+/obj/machinery/smartfridge/wirecutter_act(mob/living/user, obj/item/I)
+ if(panel_open)
+ attack_hand(user)
+ return TRUE
+ return ..()
- if(stat & NOPOWER)
+/obj/machinery/smartfridge/multitool_act(mob/living/user, obj/item/I)
+ if(panel_open)
+ attack_hand(user)
+ return TRUE
+ return ..()
+
+/obj/machinery/smartfridge/attackby(obj/item/O, var/mob/user)
+ if(exchange_parts(user, O))
+ SSnanoui.update_uis(src)
+ return
+ if(stat & (BROKEN|NOPOWER))
to_chat(user, "\The [src] is unpowered and useless.")
return
@@ -269,92 +148,63 @@
user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].")
SSnanoui.update_uis(src)
update_icon()
-
else if(istype(O, /obj/item/storage/bag))
var/obj/item/storage/bag/P = O
- var/plants_loaded = 0
+ var/items_loaded = 0
for(var/obj/G in P.contents)
if(load(G, user))
- plants_loaded++
- if(plants_loaded)
+ items_loaded++
+ if(items_loaded)
user.visible_message("[user] loads \the [src] with \the [P].", "You load \the [src] with \the [P].")
- if(P.contents.len > 0)
- to_chat(user, "Some items are refused.")
-
- SSnanoui.update_uis(src)
- update_icon()
-
+ SSnanoui.update_uis(src)
+ update_icon()
+ var/failed = length(P.contents)
+ if(failed)
+ to_chat(user, "[failed] item\s [failed == 1 ? "is" : "are"] refused.")
else if(!istype(O, /obj/item/card/emag))
to_chat(user, "\The [src] smartly refuses [O].")
- return 1
-
-/obj/machinery/smartfridge/proc/load(obj/I, mob/user)
- if(accept_check(I))
- if(contents.len >= max_n_of_items)
- to_chat(user, "\The [src] is full.")
- return 0
- else
- if(istype(I.loc, /obj/item/storage))
- var/obj/item/storage/S = I.loc
- S.remove_from_storage(I, src)
- else if(istype(I.loc, /mob))
- var/mob/M = I.loc
- if(M.get_active_hand() == I)
- if(!M.drop_item())
- to_chat(user, "\The [I] is stuck to you!")
- return 0
- else
- M.unEquip(I)
- I.forceMove(src)
- else
- I.forceMove(src)
-
- if(item_quants[I.name])
- item_quants[I.name]++
- else
- item_quants[I.name] = 1
- return 1
- return 0
+ return TRUE
/obj/machinery/smartfridge/attack_ai(mob/user)
- return 0
+ return FALSE
/obj/machinery/smartfridge/attack_ghost(mob/user)
return attack_hand(user)
/obj/machinery/smartfridge/attack_hand(mob/user)
- if(stat & (NOPOWER|BROKEN))
+ if(stat & (BROKEN|NOPOWER))
return
wires.Interact(user)
ui_interact(user)
+ return ..()
//Drag pill bottle to fridge to empty it into the fridge
/obj/machinery/smartfridge/MouseDrop_T(obj/over_object, mob/user)
if(!istype(over_object, /obj/item/storage/pill_bottle)) //Only pill bottles, please
return
-
- if(stat & NOPOWER)
+ if(stat & (BROKEN|NOPOWER))
to_chat(user, "\The [src] is unpowered and useless.")
return
var/obj/item/storage/box/pillbottles/P = over_object
+ if(!length(P.contents))
+ to_chat(user, "\The [P] is empty.")
+ return
+
var/items_loaded = 0
for(var/obj/G in P.contents)
if(load(G, user))
items_loaded++
if(items_loaded)
- user.visible_message( \
- "[user] empties \the [P] into \the [src].", \
- "You empty \the [P] into \the [src].")
- if(P.contents.len > 0)
- to_chat(user, "Some items are refused.")
- SSnanoui.update_uis(src)
+ user.visible_message("[user] empties \the [P] into \the [src].", "You empty \the [P] into \the [src].")
+ SSnanoui.update_uis(src)
+ update_icon()
+ var/failed = length(P.contents)
+ if(failed)
+ to_chat(user, "[failed] item\s [failed == 1 ? "is" : "are"] refused.")
-/*******************
-* SmartFridge Menu
-********************/
-
-/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
+// UI
+/obj/machinery/smartfridge/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = TRUE)
user.set_machine(src)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
@@ -374,13 +224,13 @@
data["drying"] = drying
var/list/items[0]
- for(var/i=1 to length(item_quants))
+ for(var/i in 1 to length(item_quants))
var/K = item_quants[i]
var/count = item_quants[K]
if(count > 0)
items.Add(list(list("display_name" = html_encode(capitalize(K)), "vend" = i, "quantity" = count)))
- if(items.len > 0)
+ if(length(items))
data["contents"] = items
return data
@@ -402,6 +252,8 @@
if(href_list["vend"])
var/index = text2num(href_list["vend"])
var/amount = text2num(href_list["amount"])
+ if(isnull(index) || !ISINDEXSAFE(item_quants, index) || isnull(amount))
+ return FALSE
var/K = item_quants[index]
var/count = item_quants[K]
@@ -429,36 +281,343 @@
if(i <= 0)
return TRUE
return TRUE
+
return FALSE
+/**
+ * Tries to load an item if it is accepted by [/obj/machinery/smartfridge/proc/accept_check].
+ *
+ * Arguments:
+ * * I - The item to load.
+ * * user - The user trying to load the item.
+ */
+/obj/machinery/smartfridge/proc/load(obj/I, mob/user)
+ if(accept_check(I))
+ if(length(contents) >= max_n_of_items)
+ to_chat(user, "\The [src] is full.")
+ return FALSE
+ else
+ if(istype(I.loc, /obj/item/storage))
+ var/obj/item/storage/S = I.loc
+ S.remove_from_storage(I, src)
+ else if(ismob(I.loc))
+ var/mob/M = I.loc
+ if(M.get_active_hand() == I)
+ if(!M.drop_item())
+ to_chat(user, "\The [I] is stuck to you!")
+ return FALSE
+ else
+ M.unEquip(I)
+ I.forceMove(src)
+ else
+ I.forceMove(src)
+
+ item_quants[I.name] += 1
+ return TRUE
+ return FALSE
+
+/**
+ * Tries to shoot a random at a nearby living mob.
+ */
/obj/machinery/smartfridge/proc/throw_item()
- var/obj/throw_item = null
- var/mob/living/target = locate() in view(7,src)
+ var/obj/item/throw_item = null
+ var/mob/living/target = locate() in view(7, src)
if(!target)
- return 0
+ return FALSE
for(var/O in item_quants)
if(item_quants[O] <= 0) //Try to use a record that actually has something to dump.
continue
-
item_quants[O]--
- for(var/obj/T in contents)
- if(T.name == O)
- T.forceMove(loc)
- throw_item = T
+ for(var/obj/I in contents)
+ if(I.name == O)
+ I.forceMove(loc)
+ throw_item = I
update_icon()
break
- break
if(!throw_item)
- return 0
- spawn(0)
- throw_item.throw_at(target,16,3,src)
- visible_message("[src] launches [throw_item.name] at [target.name]!")
- return 1
+ return FALSE
-// ----------------------------
-// Drying Rack 'smartfridge'
-// ----------------------------
+ INVOKE_ASYNC(throw_item, /atom/movable.proc/throw_at, target, 16, 3, src)
+ visible_message("[src] launches [throw_item.name] at [target.name]!")
+ return TRUE
+
+/**
+ * Returns whether the smart fridge can accept the given item.
+ *
+ * By default checks if the item is in [the typecache][/obj/machinery/smartfridge/var/accepted_items_typecache].
+ * Arguments:
+ * * O - The item to check.
+ */
+/obj/machinery/smartfridge/proc/accept_check(obj/item/O)
+ return is_type_in_typecache(O, accepted_items_typecache)
+
+/**
+ * # Secure Fridge
+ *
+ * Secure variant of the [Smart Fridge][/obj/machinery/smartfridge].
+ * Can be emagged and EMP'd to short the lock.
+ */
+/obj/machinery/smartfridge/secure
+ is_secure = TRUE
+
+/obj/machinery/smartfridge/secure/emag_act(mob/user)
+ emagged = TRUE
+ locked = SMART_FRIDGE_LOCK_SHORTED
+ to_chat(user, "You short out the product lock on \the [src].")
+
+/obj/machinery/smartfridge/secure/emp_act(severity)
+ if(!emagged && locked != SMART_FRIDGE_LOCK_SHORTED && prob(40 / severity))
+ playsound(loc, 'sound/effects/sparks4.ogg', 60, TRUE)
+ emagged = TRUE
+ locked = SMART_FRIDGE_LOCK_SHORTED
+
+/obj/machinery/smartfridge/secure/Topic(href, href_list)
+ if(stat & (BROKEN|NOPOWER))
+ return FALSE
+
+ if(href_list["vend"] && (usr.contents.Find(src) || Adjacent(usr)))
+ if(!emagged && locked != SMART_FRIDGE_LOCK_SHORTED && scan_id && !allowed(usr))
+ to_chat(usr, "Access denied.")
+ SSnanoui.update_uis(src)
+ return FALSE
+
+ return ..()
+
+/**
+ * # Seed Storage
+ *
+ * Seeds variant of the [Smart Fridge][/obj/machinery/smartfridge].
+ * Formerly known as MegaSeed Servitor, but renamed to avoid confusion with the [vending machine][/obj/machinery/vending/hydroseeds].
+ */
+/obj/machinery/smartfridge/seeds
+ name = "\improper Seed Storage"
+ desc = "When you need seeds fast!"
+ icon = 'icons/obj/vending.dmi'
+ icon_state = "seeds"
+
+/obj/machinery/smartfridge/seeds/Initialize(mapload)
+ . = ..()
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/seeds
+ ))
+
+/**
+ * # Refrigerated Medicine Storage
+ *
+ * Medical variant of the [Smart Fridge][/obj/machinery/smartfridge].
+ */
+/obj/machinery/smartfridge/medbay
+ name = "\improper Refrigerated Medicine Storage"
+ desc = "A refrigerated storage unit for storing medicine and chemicals."
+ icon_state = "smartfridge" //To fix the icon in the map editor.
+
+/obj/machinery/smartfridge/medbay/Initialize(mapload)
+ . = ..()
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/reagent_containers/glass,
+ /obj/item/reagent_containers/iv_bag,
+ /obj/item/reagent_containers/applicator,
+ /obj/item/storage/pill_bottle,
+ /obj/item/reagent_containers/food/pill,
+ ))
+
+/**
+ * # Slime Extract Storage
+ *
+ * Secure, Xenobiology variant of the [Smart Fridge][/obj/machinery/smartfridge].
+ */
+/obj/machinery/smartfridge/secure/extract
+ name = "\improper Slime Extract Storage"
+ desc = "A refrigerated storage unit for slime extracts"
+
+/obj/machinery/smartfridge/secure/extract/Initialize(mapload)
+ . = ..()
+ req_access_txt = "[ACCESS_RESEARCH]"
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/slime_extract
+ ))
+
+/**
+ * # Secure Refrigerated Medicine Storage
+ *
+ * Secure, Medical variant of the [Smart Fridge][/obj/machinery/smartfridge].
+ */
+/obj/machinery/smartfridge/secure/medbay
+ name = "\improper Secure Refrigerated Medicine Storage"
+ desc = "A refrigerated storage unit for storing medicine and chemicals."
+ icon_state = "smartfridge" //To fix the icon in the map editor.
+ req_one_access_txt = "5;33"
+
+/obj/machinery/smartfridge/secure/medbay/Initialize(mapload)
+ . = ..()
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/reagent_containers/glass,
+ /obj/item/reagent_containers/iv_bag,
+ /obj/item/reagent_containers/applicator,
+ /obj/item/storage/pill_bottle,
+ /obj/item/reagent_containers/food/pill,
+ ))
+
+/**
+ * # Smart Chemical Storage
+ *
+ * Secure, Chemistry variant of the [Smart Fridge][/obj/machinery/smartfridge].
+ */
+/obj/machinery/smartfridge/secure/chemistry
+ name = "\improper Smart Chemical Storage"
+ desc = "A refrigerated storage unit for medicine and chemical storage."
+ icon_state = "smartfridge" //To fix the icon in the map editor.
+ /// Associative list (/obj/item => /number) representing the items the fridge should initially contain.
+ var/list/spawn_meds
+
+/obj/machinery/smartfridge/secure/chemistry/Initialize(mapload)
+ . = ..()
+ req_access_txt = "[ACCESS_CHEMISTRY]"
+ // Spawn initial chemicals
+ if(mapload)
+ LAZYINITLIST(spawn_meds)
+ for(var/typekey in spawn_meds)
+ var/amount = spawn_meds[typekey] || 1
+ while(amount--)
+ var/obj/item/I = new typekey(src)
+ item_quants[I.name] += 1
+ update_icon()
+ // Accepted items
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/storage/pill_bottle,
+ /obj/item/reagent_containers,
+ ))
+
+/**
+ * # Smart Chemical Storage (Preloaded)
+ *
+ * A [Smart Chemical Storage][/obj/machinery/smartfridge/secure/chemistry] but with some items already in.
+ */
+/obj/machinery/smartfridge/secure/chemistry/preloaded
+ // I exist!
+
+/obj/machinery/smartfridge/secure/chemistry/preloaded/Initialize(mapload)
+ spawn_meds = list(
+ /obj/item/reagent_containers/food/pill/epinephrine = 12,
+ /obj/item/reagent_containers/food/pill/charcoal = 5,
+ /obj/item/reagent_containers/glass/bottle/epinephrine = 1,
+ /obj/item/reagent_containers/glass/bottle/charcoal = 1,
+ )
+ . = ..()
+
+/**
+ * # Smart Chemical Storage (Preloaded, Syndicate)
+ *
+ * A [Smart Chemical Storage (Preloaded)][/obj/machinery/smartfridge/secure/chemistry/preloaded] but with exclusive access to Syndicate.
+ */
+/obj/machinery/smartfridge/secure/chemistry/preloaded/syndicate
+ req_access_txt = null
+
+/obj/machinery/smartfridge/secure/chemistry/preloaded/syndicate/Initialize(mapload)
+ . = ..()
+ req_access = list(ACCESS_SYNDICATE)
+
+/**
+ * # Disk Compartmentalizer
+ *
+ * Disk variant of the [Smart Fridge][/obj/machinery/smartfridge].
+ */
+/obj/machinery/smartfridge/disks
+ name = "disk compartmentalizer"
+ desc = "A machine capable of storing a variety of disks. Denoted by most as the DSU (disk storage unit)."
+ icon_state = "disktoaster"
+ pass_flags = PASSTABLE
+ visible_contents = FALSE
+
+/obj/machinery/smartfridge/disks/Initialize(mapload)
+ . = ..()
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/disk,
+ ))
+
+/**
+ * # Smart Virus Storage
+ *
+ * Secure, Virology variant of the [Smart Chemical Storage][/obj/machinery/smartfridge/secure/chemistry].
+ * Comes with some items.
+ */
+/obj/machinery/smartfridge/secure/chemistry/virology
+ name = "\improper Smart Virus Storage"
+ desc = "A refrigerated storage unit for volatile sample storage."
+
+/obj/machinery/smartfridge/secure/chemistry/virology/Initialize(mapload)
+ spawn_meds = list(
+ /obj/item/reagent_containers/syringe/antiviral = 4,
+ /obj/item/reagent_containers/glass/bottle/cold = 1,
+ /obj/item/reagent_containers/glass/bottle/flu_virion = 1,
+ /obj/item/reagent_containers/glass/bottle/mutagen = 1,
+ /obj/item/reagent_containers/glass/bottle/plasma = 1,
+ /obj/item/reagent_containers/glass/bottle/diphenhydramine = 1
+ )
+ . = ..()
+ req_access_txt = "[ACCESS_VIROLOGY]"
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/reagent_containers/syringe,
+ /obj/item/reagent_containers/glass/bottle,
+ /obj/item/reagent_containers/glass/beaker,
+ ))
+
+/**
+ * # Smart Virus Storage (Preloaded)
+ *
+ * A [Smart Virus Storage][/obj/machinery/smartfridge/secure/chemistry/virology] but with some additional items.
+ */
+/obj/machinery/smartfridge/secure/chemistry/virology/preloaded
+ // I exist!
+
+/obj/machinery/smartfridge/secure/chemistry/virology/preloaded/Initialize(mapload)
+ spawn_meds = list(
+ /obj/item/reagent_containers/syringe/antiviral = 4,
+ /obj/item/reagent_containers/glass/bottle/cold = 1,
+ /obj/item/reagent_containers/glass/bottle/flu_virion = 1,
+ /obj/item/reagent_containers/glass/bottle/mutagen = 1,
+ /obj/item/reagent_containers/glass/bottle/plasma = 1,
+ /obj/item/reagent_containers/glass/bottle/reagent/synaptizine = 1,
+ /obj/item/reagent_containers/glass/bottle/reagent/formaldehyde = 1
+ )
+ . = ..()
+
+/**
+ * # Smart Virus Storage (Preloaded, Syndicate)
+ *
+ * A [Smart Virus Storage (Preloaded)][/obj/machinery/smartfridge/secure/chemistry/virology/preloaded] but with exclusive access to Syndicate.
+ */
+/obj/machinery/smartfridge/secure/chemistry/virology/preloaded/syndicate
+ req_access_txt = null
+
+/obj/machinery/smartfridge/secure/chemistry/virology/preloaded/syndicate/Initialize(mapload)
+ . = ..()
+ req_access = list(ACCESS_SYNDICATE)
+
+/**
+ * # Drink Showcase
+ *
+ * Drink variant of the [Smart Fridge][/obj/machinery/smartfridge].
+ */
+/obj/machinery/smartfridge/drinks
+ name = "\improper Drink Showcase"
+ desc = "A refrigerated storage unit for tasty tasty alcohol."
+
+/obj/machinery/smartfridge/drinks/Initialize(mapload)
+ . = ..()
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/reagent_containers/glass,
+ /obj/item/reagent_containers/food/drinks,
+ /obj/item/reagent_containers/food/condiment,
+ ))
+
+/**
+ * # Drying Rack
+ *
+ * Variant of the [Smart Fridge][/obj/machinery/smartfridge] for drying stuff.
+ * Doesn't have components.
+ */
/obj/machinery/smartfridge/drying_rack
name = "drying rack"
desc = "A wooden contraption, used to dry plant products, food and leather."
@@ -470,11 +629,16 @@
can_dry = TRUE
visible_contents = FALSE
-/obj/machinery/smartfridge/drying_rack/New()
- ..()
- if(component_parts && component_parts.len)
- component_parts.Cut()
+/obj/machinery/smartfridge/drying_rack/Initialize(mapload)
+ . = ..()
+ // Remove components, this is wood duh
+ QDEL_LIST(component_parts)
component_parts = null
+ // Accepted items
+ accepted_items_typecache = typecacheof(list(
+ /obj/item/reagent_containers/food/snacks,
+ /obj/item/stack/sheet/wetleather,
+ ))
/obj/machinery/smartfridge/drying_rack/on_deconstruction()
new /obj/item/stack/sheet/wood(loc, 10)
@@ -483,34 +647,6 @@
/obj/machinery/smartfridge/drying_rack/RefreshParts()
return
-/obj/machinery/smartfridge/drying_rack/default_deconstruction_screwdriver()
- return
-
-/obj/machinery/smartfridge/drying_rack/exchange_parts()
- return
-
-/obj/machinery/smartfridge/drying_rack/spawn_frame()
- return
-
-/obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(user, obj/item/crowbar/C, ignore_panel = 1)
- ..()
-
-/obj/machinery/smartfridge/drying_rack/Topic(href, href_list)
- if(..())
- return 1
- if(href_list["dryingOn"])
- drying = TRUE
- use_power = ACTIVE_POWER_USE
- update_icon()
- return 1
-
- if(href_list["dryingOff"])
- drying = FALSE
- use_power = IDLE_POWER_USE
- update_icon()
- return 1
- return 0
-
/obj/machinery/smartfridge/drying_rack/power_change()
if(powered() && anchored)
stat &= ~NOPOWER
@@ -519,35 +655,67 @@
toggle_drying(TRUE)
update_icon()
-/obj/machinery/smartfridge/drying_rack/load(obj/I, mob/user) //For updating the filled overlay
+/obj/machinery/smartfridge/drying_rack/screwdriver_act(mob/living/user, obj/item/I)
+ return
+
+/obj/machinery/smartfridge/drying_rack/exchange_parts()
+ return
+
+/obj/machinery/smartfridge/drying_rack/spawn_frame()
+ return
+
+/obj/machinery/smartfridge/drying_rack/crowbar_act(mob/living/user, obj/item/I)
+ . = default_deconstruction_crowbar(user, I, TRUE)
+
+/obj/machinery/smartfridge/drying_rack/emp_act(severity)
+ ..()
+ atmos_spawn_air(LINDA_SPAWN_HEAT)
+
+/obj/machinery/smartfridge/drying_rack/Topic(href, href_list)
if(..())
+ return TRUE
+
+ if(href_list["dryingOn"])
+ drying = TRUE
+ use_power = ACTIVE_POWER_USE
update_icon()
- return 1
+ return TRUE
+
+ if(href_list["dryingOff"])
+ drying = FALSE
+ use_power = IDLE_POWER_USE
+ update_icon()
+ return TRUE
+
+ return FALSE
/obj/machinery/smartfridge/drying_rack/update_icon()
..()
-
overlays.Cut()
if(drying)
overlays += "drying_rack_drying"
- if(contents.len)
+ if(length(contents))
overlays += "drying_rack_filled"
/obj/machinery/smartfridge/drying_rack/process()
..()
- if(drying)
- if(rack_dry())//no need to update unless something got dried
- update_icon()
+ if(drying && rack_dry())//no need to update unless something got dried
+ update_icon()
/obj/machinery/smartfridge/drying_rack/accept_check(obj/item/O)
+ . = ..()
+ // If it's a food, reject non driable ones
if(istype(O, /obj/item/reagent_containers/food/snacks))
var/obj/item/reagent_containers/food/snacks/S = O
- if(S.dried_type)
- return TRUE
- if(istype(O, /obj/item/stack/sheet/wetleather))
- return TRUE
- return FALSE
+ if(!S.dried_type)
+ return FALSE
+/**
+ * Toggles the drying process.
+ *
+ * Arguments:
+ * * forceoff - Whether to force turn off the drying rack.
+ */
/obj/machinery/smartfridge/drying_rack/proc/toggle_drying(forceoff)
if(drying || forceoff)
drying = FALSE
@@ -557,6 +725,9 @@
use_power = ACTIVE_POWER_USE
update_icon()
+/**
+ * Called in [/obj/machinery/smartfridge/drying_rack/process] to dry the contents.
+ */
/obj/machinery/smartfridge/drying_rack/proc/rack_dry()
for(var/obj/item/reagent_containers/food/snacks/S in contents)
if(S.dried_type == S.type)//if the dried type is the same as the object's type, don't bother creating a whole new item...
@@ -580,30 +751,4 @@
return TRUE
return FALSE
-/obj/machinery/smartfridge/drying_rack/emp_act(severity)
- ..()
- atmos_spawn_air(LINDA_SPAWN_HEAT)
-
-/************************
-* Secure SmartFridges
-*************************/
-/obj/machinery/smartfridge/secure/emag_act(mob/user)
- emagged = 1
- locked = -1
- to_chat(user, "You short out the product lock on [src].")
-
-/obj/machinery/smartfridge/secure/emp_act(severity)
- if(prob(40/severity) && (!emagged) && (locked != -1))
- playsound(loc, 'sound/effects/sparks4.ogg', 60, 1)
- emagged = 1
- locked = -1
-
-/obj/machinery/smartfridge/secure/Topic(href, href_list)
- if(stat & (NOPOWER|BROKEN))
- return 0
- if(usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf)))
- if(!allowed(usr) && !emagged && locked != -1 && href_list["vend"])
- to_chat(usr, "Access denied.")
- SSnanoui.update_uis(src)
- return 0
- return ..()
+#undef SMART_FRIDGE_LOCK_SHORTED
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm
index db7774fa41f..1aa33cab232 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_table.dm
@@ -90,7 +90,7 @@
subcategory = CAT_SUSHI
/datum/crafting_recipe/Ebi_maki
- name = "Ebi Makiroll"
+ name = "Ebi Maki Roll"
reqs = list(
/obj/item/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/reagent_containers/food/snacks/boiled_shrimp = 4,
@@ -111,7 +111,7 @@
subcategory = CAT_SUSHI
/datum/crafting_recipe/Ikura_maki
- name = "Ikura Makiroll"
+ name = "Ikura Maki Roll"
reqs = list(
/obj/item/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/fish_eggs/salmon = 4,
@@ -132,7 +132,7 @@
subcategory = CAT_SUSHI
/datum/crafting_recipe/Inari_maki
- name = "Inari Makiroll"
+ name = "Inari Maki Roll"
reqs = list(
/obj/item/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/reagent_containers/food/snacks/fried_tofu = 4,
@@ -153,7 +153,7 @@
subcategory = CAT_SUSHI
/datum/crafting_recipe/Sake_maki
- name = "Sake Makiroll"
+ name = "Sake Maki Roll"
reqs = list(
/obj/item/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/reagent_containers/food/snacks/salmonmeat = 4,
@@ -174,7 +174,7 @@
subcategory = CAT_SUSHI
/datum/crafting_recipe/SmokedSalmon_maki
- name = "Smoked Salmon Makiroll"
+ name = "Smoked Salmon Maki Roll"
reqs = list(
/obj/item/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/reagent_containers/food/snacks/salmonsteak = 4,
@@ -195,7 +195,7 @@
subcategory = CAT_SUSHI
/datum/crafting_recipe/Masago_maki
- name = "Masago Makiroll"
+ name = "Masago Maki Roll"
reqs = list(
/obj/item/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/fish_eggs/goldfish = 4,
@@ -216,7 +216,7 @@
subcategory = CAT_SUSHI
/datum/crafting_recipe/Tobiko_maki
- name = "Tobiko Makiroll"
+ name = "Tobiko Maki Roll"
reqs = list(
/obj/item/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/fish_eggs/shark = 4,
@@ -237,18 +237,7 @@
subcategory = CAT_SUSHI
/datum/crafting_recipe/TobikoEgg_maki
- name = "Tobiko Makiroll"
- reqs = list(
- /obj/item/reagent_containers/food/snacks/sushi_Tobiko = 4,
- /obj/item/reagent_containers/food/snacks/egg = 4,
- )
- pathtools = list(/obj/item/kitchen/sushimat)
- result = /obj/item/reagent_containers/food/snacks/sliceable/TobikoEgg_maki
- category = CAT_FOOD
- subcategory = CAT_SUSHI
-
-/datum/crafting_recipe/Sake_maki
- name = "Sake Makiroll"
+ name = "Tobiko and Egg Maki Roll"
reqs = list(
/obj/item/reagent_containers/food/snacks/sushi_Tobiko = 4,
/obj/item/reagent_containers/food/snacks/egg = 4,
@@ -269,7 +258,7 @@
subcategory = CAT_SUSHI
/datum/crafting_recipe/Tai_maki
- name = "Tai Makiroll"
+ name = "Tai Maki Roll"
reqs = list(
/obj/item/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/reagent_containers/food/snacks/catfishmeat = 4,
diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm
index 7be44052729..9a7c8cca075 100644
--- a/code/modules/games/cards.dm
+++ b/code/modules/games/cards.dm
@@ -438,7 +438,7 @@
overlays += I
return
- var/offset = Floor(20/cards.len + 1)
+ var/offset = FLOOR(20/cards.len + 1, 1)
var/matrix/M = matrix()
if(direction)
diff --git a/code/modules/hydroponics/beekeeping/honeycomb.dm b/code/modules/hydroponics/beekeeping/honeycomb.dm
index 23bc55dfea2..1d086bae0f0 100644
--- a/code/modules/hydroponics/beekeeping/honeycomb.dm
+++ b/code/modules/hydroponics/beekeeping/honeycomb.dm
@@ -17,6 +17,8 @@
pixel_y = rand(8,-8)
update_icon()
+/obj/item/reagent_containers/honeycomb/set_APTFT()
+ set hidden = TRUE
/obj/item/reagent_containers/honeycomb/update_icon()
overlays.Cut()
diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm
index c1b5e471315..bb25025cb7f 100644
--- a/code/modules/hydroponics/biogenerator.dm
+++ b/code/modules/hydroponics/biogenerator.dm
@@ -327,7 +327,7 @@
else if(href_list["create"])
var/amount = (text2num(href_list["amount"]))
//Can't be outside these (if you change this keep a sane limit)
- amount = Clamp(amount, 1, 10)
+ amount = clamp(amount, 1, 10)
var/datum/design/D = locate(href_list["create"])
create_product(D, amount)
updateUsrDialog()
diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm
index d39a0168f14..7ce64f40b20 100644
--- a/code/modules/hydroponics/gene_modder.dm
+++ b/code/modules/hydroponics/gene_modder.dm
@@ -71,7 +71,7 @@
for(var/obj/item/stock_parts/micro_laser/ML in component_parts)
var/wratemod = ML.rating * 2.5
- min_wrate = Floor(10-wratemod) // 7,5,2,0 Clamps at 0 and 10 You want this low
+ min_wrate = FLOOR(10-wratemod, 1) // 7,5,2,0 Clamps at 0 and 10 You want this low
min_wchance = 67-(ML.rating*16) // 48,35,19,3 Clamps at 0 and 67 You want this low
for(var/obj/item/circuitboard/plantgenes/vaultcheck in component_parts)
if(istype(vaultcheck, /obj/item/circuitboard/plantgenes/vault)) // TRAIT_DUMB BOTANY TUTS
diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm
index d86f6f8f4c5..bad8813ea01 100644
--- a/code/modules/hydroponics/grown.dm
+++ b/code/modules/hydroponics/grown.dm
@@ -40,7 +40,7 @@
for(var/datum/plant_gene/trait/T in seed.genes)
T.on_new(src, newloc)
seed.prepare_result(src)
- transform *= TransformUsingVariable(seed.potency, 100, 0.5) //Makes the resulting produce's sprite larger or smaller based on potency!
+ transform *= TRANSFORM_USING_VARIABLE(seed.potency, 100) + 0.5 //Makes the resulting produce's sprite larger or smaller based on potency!
add_juice()
/obj/item/reagent_containers/food/snacks/grown/Destroy()
@@ -117,6 +117,7 @@
/obj/item/reagent_containers/food/snacks/grown/throw_impact(atom/hit_atom)
if(!..()) //was it caught by a mob?
if(seed)
+ log_action(thrownby, hit_atom, "Thrown [src] at")
for(var/datum/plant_gene/trait/T in seed.genes)
T.on_throw_impact(src, hit_atom)
if(seed.get_gene(/datum/plant_gene/trait/squash))
@@ -147,24 +148,18 @@
qdel(src)
-/obj/item/reagent_containers/food/snacks/grown/On_Consume()
- if(iscarbon(usr))
+/obj/item/reagent_containers/food/snacks/grown/On_Consume(mob/M, mob/user)
+ if(iscarbon(M))
if(seed)
for(var/datum/plant_gene/trait/T in seed.genes)
- T.on_consume(src, usr)
+ T.on_consume(src, M)
..()
-/obj/item/reagent_containers/food/snacks/grown/Crossed(atom/movable/AM, oldloc)
- if(seed)
- for(var/datum/plant_gene/trait/T in seed.genes)
- T.on_cross(src, AM)
- ..()
-
-/obj/item/reagent_containers/food/snacks/grown/on_trip(mob/living/carbon/human/H)
- . = ..()
- if(. && seed)
- for(var/datum/plant_gene/trait/T in seed.genes)
- T.on_slip(src, H)
+/obj/item/reagent_containers/food/snacks/grown/after_slip(mob/living/carbon/human/H)
+ if(!seed)
+ return
+ for(var/datum/plant_gene/trait/T in seed.genes)
+ T.on_slip(src, H)
// Glow gene procs
/obj/item/reagent_containers/food/snacks/grown/generate_trash(atom/location)
@@ -174,6 +169,11 @@
return
return ..()
+/obj/item/reagent_containers/food/snacks/grown/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ C.stored_comms["wood"] += 4
+ qdel(src)
+ return TRUE
+
// For item-containing growns such as eggy or gatfruit
/obj/item/reagent_containers/food/snacks/grown/shell/attack_self(mob/user)
user.unEquip(src)
@@ -190,3 +190,17 @@
D.consume(src)
else
return ..()
+
+/obj/item/reagent_containers/food/snacks/grown/proc/log_action(mob/user, atom/target, what_done)
+ var/reagent_str = reagents.log_list()
+ var/genes_str = "No genes"
+ if(seed && length(seed.genes))
+ var/list/plant_gene_names = list()
+ for(var/thing in seed.genes)
+ var/datum/plant_gene/G = thing
+ if(G.dangerous)
+ plant_gene_names += G.name
+ genes_str = english_list(plant_gene_names)
+
+ add_attack_logs(user, target, "[what_done] ([reagent_str] | [genes_str])")
+
diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm
index dc78ff71335..0552f78ee92 100644
--- a/code/modules/hydroponics/grown/banana.dm
+++ b/code/modules/hydroponics/grown/banana.dm
@@ -118,12 +118,10 @@
/obj/item/grown/bananapeel/specialpeel //used by /obj/item/clothing/shoes/clown_shoes/banana_shoes
name = "synthesized banana peel"
desc = "A synthetic banana peel."
- trip_stun = 2
- trip_weaken = 2
- trip_chance = 100
- trip_walksafe = FALSE
- trip_verb = TV_SLIP
-/obj/item/grown/bananapeel/specialpeel/on_trip(mob/living/carbon/human/H)
- if(..())
- qdel(src)
+/obj/item/grown/bananapeel/specialpeel/ComponentInitialize()
+ AddComponent(/datum/component/slippery, src, 2, 2, 100, 0, FALSE)
+
+/obj/item/grown/bananapeel/specialpeel/after_slip(mob/living/carbon/human/H)
+ . = ..()
+ qdel(src)
diff --git a/code/modules/hydroponics/growninedible.dm b/code/modules/hydroponics/growninedible.dm
index 14a4b42ca5f..f10b286469a 100644
--- a/code/modules/hydroponics/growninedible.dm
+++ b/code/modules/hydroponics/growninedible.dm
@@ -28,7 +28,7 @@
if(istype(src, seed.product)) // no adding reagents if it is just a trash item
seed.prepare_result(src)
- transform *= TransformUsingVariable(seed.potency, 100, 0.5)
+ transform *= TRANSFORM_USING_VARIABLE(seed.potency, 100) + 0.5
add_juice()
/obj/item/grown/Destroy()
@@ -50,18 +50,11 @@
return 1
return 0
-
-/obj/item/grown/Crossed(atom/movable/AM, oldloc)
- if(seed)
- for(var/datum/plant_gene/trait/T in seed.genes)
- T.on_cross(src, AM)
- ..()
-
-/obj/item/grown/on_trip(mob/living/carbon/human/H)
- . = ..()
- if(. && seed)
- for(var/datum/plant_gene/trait/T in seed.genes)
- T.on_slip(src, H)
+/obj/item/grown/after_slip(mob/living/carbon/human/H)
+ if(!seed)
+ return
+ for(var/datum/plant_gene/trait/T in seed.genes)
+ T.on_slip(src, H)
/obj/item/grown/throw_impact(atom/hit_atom)
if(!..()) //was it caught by a mob?
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index 0f41ba4b602..1be8f11527d 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -888,7 +888,7 @@
/obj/machinery/hydroponics/wrench_act(mob/user, obj/item/I)
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
if(wrenchable)
if(using_irrigation)
@@ -949,36 +949,36 @@
/// Tray Setters - The following procs adjust the tray or plants variables, and make sure that the stat doesn't go out of bounds.///
/obj/machinery/hydroponics/proc/adjustNutri(adjustamt)
- nutrilevel = Clamp(nutrilevel + adjustamt, 0, maxnutri)
+ nutrilevel = clamp(nutrilevel + adjustamt, 0, maxnutri)
plant_hud_set_nutrient()
/obj/machinery/hydroponics/proc/adjustWater(adjustamt)
- waterlevel = Clamp(waterlevel + adjustamt, 0, maxwater)
+ waterlevel = clamp(waterlevel + adjustamt, 0, maxwater)
plant_hud_set_water()
if(adjustamt>0)
adjustToxic(-round(adjustamt/4))//Toxicity dilutation code. The more water you put in, the lesser the toxin concentration.
/obj/machinery/hydroponics/proc/adjustHealth(adjustamt)
if(myseed && !dead)
- plant_health = Clamp(plant_health + adjustamt, 0, myseed.endurance)
+ plant_health = clamp(plant_health + adjustamt, 0, myseed.endurance)
plant_hud_set_health()
/obj/machinery/hydroponics/proc/adjustToxic(adjustamt)
- toxic = Clamp(toxic + adjustamt, 0, 100)
+ toxic = clamp(toxic + adjustamt, 0, 100)
plant_hud_set_toxin()
/obj/machinery/hydroponics/proc/adjustPests(adjustamt)
- pestlevel = Clamp(pestlevel + adjustamt, 0, 10)
+ pestlevel = clamp(pestlevel + adjustamt, 0, 10)
plant_hud_set_pest()
/obj/machinery/hydroponics/proc/adjustWeeds(adjustamt)
- weedlevel = Clamp(weedlevel + adjustamt, 0, 10)
+ weedlevel = clamp(weedlevel + adjustamt, 0, 10)
plant_hud_set_weed()
/obj/machinery/hydroponics/proc/spawnplant() // why would you put strange reagent in a hydro tray you monster I bet you also feed them blood
var/list/livingplants = list(/mob/living/simple_animal/hostile/tree, /mob/living/simple_animal/hostile/killertomato)
var/chosen = pick(livingplants)
- var/mob/living/simple_animal/hostile/C = new chosen
+ var/mob/living/simple_animal/hostile/C = new chosen(get_turf(src))
C.faction = list("plants")
/obj/machinery/hydroponics/proc/become_self_sufficient() // Ambrosia Gaia effect
diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm
index d20413d6331..c2f4914351c 100644
--- a/code/modules/hydroponics/plant_genes.dm
+++ b/code/modules/hydroponics/plant_genes.dm
@@ -1,5 +1,7 @@
/datum/plant_gene
var/name
+ /// Used to determine if the trait should be logged when the holder is used
+ var/dangerous = FALSE
/datum/plant_gene/proc/get_name() // Used for manipulator display and gene disk name.
return name
@@ -175,9 +177,6 @@
/datum/plant_gene/trait/proc/on_consume(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/target)
return
-/datum/plant_gene/trait/proc/on_cross(obj/item/reagent_containers/food/snacks/grown/G, atom/target)
- return
-
/datum/plant_gene/trait/proc/on_slip(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/target)
return
@@ -197,6 +196,7 @@
name = "Liquid Contents"
examine_line = "It has a lot of liquid contents inside."
origin_tech = list("biotech" = 5)
+ dangerous = TRUE
/datum/plant_gene/trait/slip
// Makes plant slippery, unless it has a grown-type trash. Then the trash gets slippery.
@@ -204,6 +204,7 @@
name = "Slippery Skin"
rate = 0.1
examine_line = "It has a very slippery skin."
+ dangerous = TRUE
/datum/plant_gene/trait/slip/on_new(obj/item/reagent_containers/food/snacks/grown/G, newloc)
. = ..()
@@ -217,11 +218,7 @@
stun_len = min(stun_len, 7) // No fun allowed
- G.trip_stun = stun_len
- G.trip_weaken = stun_len
- G.trip_chance = 100
- G.trip_verb = TV_SLIP
- G.trip_walksafe = FALSE
+ G.AddComponent(/datum/component/slippery, G, stun_len, stun_len, 100, 0, FALSE)
/datum/plant_gene/trait/cell_charge
// Cell recharging trait. Charges all mob's power cells to (potency*rate)% mark when eaten.
@@ -231,6 +228,7 @@
name = "Electrical Activity"
rate = 0.2
origin_tech = list("powerstorage" = 5)
+ dangerous = TRUE
/datum/plant_gene/trait/cell_charge/on_slip(obj/item/reagent_containers/food/snacks/grown/G, mob/living/carbon/C)
var/power = G.seed.potency*rate
@@ -305,6 +303,7 @@
name = "Bluespace Activity"
rate = 0.1
origin_tech = list("bluespace" = 5)
+ dangerous = TRUE
/datum/plant_gene/trait/teleport/on_squash(obj/item/reagent_containers/food/snacks/grown/G, atom/target)
if(isliving(target))
@@ -392,6 +391,7 @@
/datum/plant_gene/trait/stinging
name = "Hypodermic Prickles"
+ dangerous = TRUE
/datum/plant_gene/trait/stinging/on_throw_impact(obj/item/reagent_containers/food/snacks/grown/G, atom/target)
if(isliving(target) && G.reagents && G.reagents.total_volume)
@@ -405,6 +405,7 @@
/datum/plant_gene/trait/smoke
name = "gaseous decomposition"
+ dangerous = TRUE
/datum/plant_gene/trait/smoke/on_squash(obj/item/reagent_containers/food/snacks/grown/G, atom/target)
var/datum/effect_system/smoke_spread/chem/S = new
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index 8cfc9b7d5f0..08ccac07062 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -182,7 +182,7 @@
/// Setters procs ///
/obj/item/seeds/proc/adjust_yield(adjustamt)
if(yield != -1) // Unharvestable shouldn't suddenly turn harvestable
- yield = Clamp(yield + adjustamt, 0, 10)
+ yield = clamp(yield + adjustamt, 0, 10)
if(yield <= 0 && get_gene(/datum/plant_gene/trait/plant_type/fungal_metabolism))
yield = 1 // Mushrooms always have a minimum yield of 1.
@@ -191,39 +191,39 @@
C.value = yield
/obj/item/seeds/proc/adjust_lifespan(adjustamt)
- lifespan = Clamp(lifespan + adjustamt, 10, 100)
+ lifespan = clamp(lifespan + adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/lifespan)
if(C)
C.value = lifespan
/obj/item/seeds/proc/adjust_endurance(adjustamt)
- endurance = Clamp(endurance + adjustamt, 10, 100)
+ endurance = clamp(endurance + adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/endurance)
if(C)
C.value = endurance
/obj/item/seeds/proc/adjust_production(adjustamt)
if(yield != -1)
- production = Clamp(production + adjustamt, 1, 10)
+ production = clamp(production + adjustamt, 1, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/production)
if(C)
C.value = production
/obj/item/seeds/proc/adjust_potency(adjustamt)
if(potency != -1)
- potency = Clamp(potency + adjustamt, 0, 100)
+ potency = clamp(potency + adjustamt, 0, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/potency)
if(C)
C.value = potency
/obj/item/seeds/proc/adjust_weed_rate(adjustamt)
- weed_rate = Clamp(weed_rate + adjustamt, 0, 10)
+ weed_rate = clamp(weed_rate + adjustamt, 0, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_rate)
if(C)
C.value = weed_rate
/obj/item/seeds/proc/adjust_weed_chance(adjustamt)
- weed_chance = Clamp(weed_chance + adjustamt, 0, 67)
+ weed_chance = clamp(weed_chance + adjustamt, 0, 67)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_chance)
if(C)
C.value = weed_chance
@@ -232,7 +232,7 @@
/obj/item/seeds/proc/set_yield(adjustamt)
if(yield != -1) // Unharvestable shouldn't suddenly turn harvestable
- yield = Clamp(adjustamt, 0, 10)
+ yield = clamp(adjustamt, 0, 10)
if(yield <= 0 && get_gene(/datum/plant_gene/trait/plant_type/fungal_metabolism))
yield = 1 // Mushrooms always have a minimum yield of 1.
@@ -241,39 +241,39 @@
C.value = yield
/obj/item/seeds/proc/set_lifespan(adjustamt)
- lifespan = Clamp(adjustamt, 10, 100)
+ lifespan = clamp(adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/lifespan)
if(C)
C.value = lifespan
/obj/item/seeds/proc/set_endurance(adjustamt)
- endurance = Clamp(adjustamt, 10, 100)
+ endurance = clamp(adjustamt, 10, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/endurance)
if(C)
C.value = endurance
/obj/item/seeds/proc/set_production(adjustamt)
if(yield != -1)
- production = Clamp(adjustamt, 1, 10)
+ production = clamp(adjustamt, 1, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/production)
if(C)
C.value = production
/obj/item/seeds/proc/set_potency(adjustamt)
if(potency != -1)
- potency = Clamp(adjustamt, 0, 100)
+ potency = clamp(adjustamt, 0, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/potency)
if(C)
C.value = potency
/obj/item/seeds/proc/set_weed_rate(adjustamt)
- weed_rate = Clamp(adjustamt, 0, 10)
+ weed_rate = clamp(adjustamt, 0, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_rate)
if(C)
C.value = weed_rate
/obj/item/seeds/proc/set_weed_chance(adjustamt)
- weed_chance = Clamp(adjustamt, 0, 67)
+ weed_chance = clamp(adjustamt, 0, 67)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_chance)
if(C)
C.value = weed_chance
diff --git a/code/modules/karma/karma.dm b/code/modules/karma/karma.dm
index f7d8b12f80c..837e3a21104 100644
--- a/code/modules/karma/karma.dm
+++ b/code/modules/karma/karma.dm
@@ -230,7 +230,7 @@ GLOBAL_LIST_EMPTY(karma_spenders)
dat += "Unlock Barber -- 5KP "
else
dat += "Barber - Unlocked "
- if(!("Brig Physican" in joblist))
+ if(!("Brig Physician" in joblist))
dat += "Unlock Brig Physician -- 5KP "
else
dat += "Brig Physician - Unlocked "
diff --git a/code/modules/library/admin.dm b/code/modules/library/admin.dm
index db907fc20ba..b56aa6994cf 100644
--- a/code/modules/library/admin.dm
+++ b/code/modules/library/admin.dm
@@ -3,8 +3,7 @@
set desc = "Permamently deletes a book from the database."
set category = "Admin"
- if(!holder)
- to_chat(src, "Only administrators may use this command.")
+ if(!check_rights(R_ADMIN))
return
var/isbn = input("ISBN number?", "Delete Book") as num | null
@@ -25,8 +24,7 @@
set desc = "View books flagged for content."
set category = "Admin"
- if(!holder)
- to_chat(src, "Only administrators may use this command.")
+ if(!check_rights(R_ADMIN))
return
holder.view_flagged_books()
diff --git a/code/modules/library/computers/checkout.dm b/code/modules/library/computers/checkout.dm
index 31eebc5d05c..934234f645e 100644
--- a/code/modules/library/computers/checkout.dm
+++ b/code/modules/library/computers/checkout.dm
@@ -95,7 +95,7 @@
dat += "ERROR: Unable to contact External Archive. Please contact your system administrator for assistance."
else
num_results = src.get_num_results()
- num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
+ num_pages = CEILING(num_results/LIBRARY_BOOKS_PER_PAGE, 1)
dat += {""}
@@ -207,7 +207,7 @@
var/obj/item/barcodescanner/scanner = W
scanner.computer = src
to_chat(user, "[scanner]'s associated machine has been set to [src].")
- audible_message("[src] lets out a low, short blip.", 2)
+ audible_message("[src] lets out a low, short blip.", hearing_distance = 2)
return 1
else
return ..()
@@ -224,13 +224,13 @@
else
var/pn = text2num(href_list["pagenum"])
if(!isnull(pn))
- page_num = Clamp(pn, 1, num_pages)
+ page_num = clamp(pn, 1, num_pages)
if(href_list["page"])
if(num_pages == 0)
page_num = 1
else
- page_num = Clamp(text2num(href_list["page"]), 1, num_pages)
+ page_num = clamp(text2num(href_list["page"]), 1, num_pages)
if(href_list["settitle"])
var/newtitle = input("Enter a title to search for:") as text|null
if(newtitle)
@@ -252,7 +252,7 @@
if(href_list["search"])
num_results = src.get_num_results()
- num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
+ num_pages = CEILING(num_results/LIBRARY_BOOKS_PER_PAGE, 1)
page_num = 1
screenstate = 4
@@ -413,7 +413,7 @@
return
if(bibledelay)
- audible_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"")
+ visible_message("[src]'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"")
else
bibledelay = 1
spawn(60)
@@ -463,4 +463,5 @@
B.author = newbook.author
B.dat = newbook.content
B.icon_state = "book[rand(1,16)]"
+ B.has_drm = TRUE
visible_message("[src]'s printer hums as it produces a completely bound book. How did it do that?")
diff --git a/code/modules/library/computers/public.dm b/code/modules/library/computers/public.dm
index f94369b11b7..3c5116bc074 100644
--- a/code/modules/library/computers/public.dm
+++ b/code/modules/library/computers/public.dm
@@ -75,7 +75,7 @@
else
var/pn = text2num(href_list["pagenum"])
if(!isnull(pn))
- page_num = Clamp(pn, 1, num_pages)
+ page_num = clamp(pn, 1, num_pages)
if(href_list["settitle"])
var/newtitle = input("Enter a title to search for:") as text|null
@@ -100,11 +100,11 @@
if(num_pages == 0)
page_num = 1
else
- page_num = Clamp(text2num(href_list["page"]), 1, num_pages)
+ page_num = clamp(text2num(href_list["page"]), 1, num_pages)
if(href_list["search"])
num_results = src.get_num_results()
- num_pages = Ceiling(num_results/LIBRARY_BOOKS_PER_PAGE)
+ num_pages = CEILING(num_results/LIBRARY_BOOKS_PER_PAGE, 1)
page_num = 1
screenstate = 1
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index a7dd148b51a..e74625c8715 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -151,6 +151,8 @@
var/carved = 0 // Has the book been hollowed out for use as a secret storage item?
var/forbidden = 0 // Prevent ordering of this book. (0=no, 1=yes, 2=emag only)
var/obj/item/store // What's in the book?
+ /// Book DRM. If this var is TRUE, it cannot be scanned and re-uploaded
+ var/has_drm = FALSE
/obj/item/book/attack_self(var/mob/user as mob)
if(carved)
diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm
index 65fadaa9b45..0c23a0c5800 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -3,11 +3,6 @@
GLOBAL_DATUM_INIT(library_catalog, /datum/library_catalog, new())
GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "Adult", "Reference", "Religion"))
-
-/hook/startup/proc/load_manuals()
- GLOB.library_catalog.initialize()
- return 1
-
/*
* Borrowbook datum
*/
@@ -65,7 +60,7 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
/datum/library_catalog
var/list/cached_books = list()
-/datum/library_catalog/proc/initialize()
+/datum/library_catalog/New()
var/newid=1
for(var/typepath in subtypesof(/obj/item/book/manual))
var/obj/item/book/B = new typepath(null)
@@ -155,6 +150,11 @@ GLOBAL_LIST_INIT(library_section_names, list("Any", "Fiction", "Non-Fiction", "A
power_change()
return
if(istype(I, /obj/item/book))
+ // NT with those pesky DRM schemes
+ var/obj/item/book/B = I
+ if(B.has_drm)
+ atom_say("Copyrighted material detected. Scanner is unable to copy book to memory.")
+ return FALSE
user.drop_item()
I.forceMove(src)
return 1
diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm
index ff4bc517979..fa848700557 100644
--- a/code/modules/lighting/lighting_atom.dm
+++ b/code/modules/lighting/lighting_atom.dm
@@ -38,7 +38,7 @@
if(!light_power || !light_range) // We won't emit light anyways, destroy the light source.
QDEL_NULL(light)
else
- if(!ismovableatom(loc)) // We choose what atom should be the top atom of the light here.
+ if(!ismovable(loc)) // We choose what atom should be the top atom of the light here.
. = src
else
. = loc
diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm
index bc521114d56..57302b5b168 100644
--- a/code/modules/lighting/lighting_corner.dm
+++ b/code/modules/lighting/lighting_corner.dm
@@ -25,7 +25,7 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
var/cache_b = LIGHTING_SOFT_THRESHOLD
var/cache_mx = 0
-/datum/lighting_corner/New(var/turf/new_turf, var/diagonal)
+/datum/lighting_corner/New(turf/new_turf, diagonal)
. = ..()
masters = list()
masters[new_turf] = turn(diagonal, 180)
@@ -79,15 +79,16 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
active = FALSE
var/turf/T
var/thing
- for (thing in masters)
+ for(thing in masters)
T = thing
if(T.lighting_object)
active = TRUE
+ return
// God that was a mess, now to do the rest of the corner code! Hooray!
-/datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b)
+/datum/lighting_corner/proc/update_lumcount(delta_r, delta_g, delta_b)
- if((abs(delta_r)+abs(delta_g)+abs(delta_b)) == 0)
+ if(!(delta_r || delta_g || delta_b)) // 0 is falsey ok
return
lum_r += delta_r
@@ -96,10 +97,10 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
if(!needs_update)
needs_update = TRUE
- GLOB.lighting_update_corners += src
+ SSlighting.corners_queue += src
/datum/lighting_corner/proc/update_objects()
- // Cache these values a head of time so 4 individual lighting objects don't all calculate them individually.
+ // Cache these values ahead of time so 4 individual lighting objects don't all calculate them individually.
var/lum_r = src.lum_r
var/lum_g = src.lum_g
var/lum_b = src.lum_b
@@ -122,19 +123,18 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
#endif
cache_mx = round(mx, LIGHTING_ROUND_VALUE)
- for (var/TT in masters)
+ for(var/TT in masters)
var/turf/T = TT
- if(T.lighting_object)
- if(!T.lighting_object.needs_update)
- T.lighting_object.needs_update = TRUE
- GLOB.lighting_update_objects += T.lighting_object
+ if(T.lighting_object && !T.lighting_object.needs_update)
+ T.lighting_object.needs_update = TRUE
+ SSlighting.objects_queue += T.lighting_object
/datum/lighting_corner/dummy/New()
return
-/datum/lighting_corner/Destroy(var/force)
+/datum/lighting_corner/Destroy(force)
if(!force)
return QDEL_HINT_LETMELIVE
diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm
index ea3e954fa6e..168a95c07f2 100644
--- a/code/modules/lighting/lighting_object.dm
+++ b/code/modules/lighting/lighting_object.dm
@@ -5,7 +5,7 @@
icon = LIGHTING_ICON
icon_state = "transparent"
- color = LIGHTING_BASE_MATRIX
+ color = null //we manually set color in init instead
plane = LIGHTING_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
layer = LIGHTING_LAYER
@@ -18,6 +18,9 @@
/atom/movable/lighting_object/Initialize(mapload)
. = ..()
verbs.Cut()
+ //We avoid setting this in the base as if we do then the parent atom handling will add_atom_color it and that
+ //is totally unsuitable for this object, as we are always changing it's colour manually
+ color = LIGHTING_BASE_MATRIX
myturf = loc
if(myturf.lighting_object)
@@ -29,11 +32,11 @@
S.update_starlight()
needs_update = TRUE
- GLOB.lighting_update_objects += src
+ SSlighting.objects_queue += src
-/atom/movable/lighting_object/Destroy(var/force)
+/atom/movable/lighting_object/Destroy(force)
if(force)
- GLOB.lighting_update_objects -= src
+ SSlighting.objects_queue -= src
if(loc != myturf)
var/turf/oldturf = get_turf(myturf)
var/turf/newturf = get_turf(loc)
@@ -143,6 +146,6 @@
return
// Override here to prevent things accidentally moving around overlays.
-/atom/movable/lighting_object/forceMove(atom/destination, var/no_tp=FALSE, var/harderforce = FALSE)
+/atom/movable/lighting_object/forceMove(atom/destination, no_tp = FALSE, harderforce = FALSE)
if(harderforce)
. = ..()
diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm
index fc87a855dc4..9398bd9683c 100644
--- a/code/modules/lighting/lighting_source.dm
+++ b/code/modules/lighting/lighting_source.dm
@@ -29,7 +29,7 @@
var/needs_update = LIGHTING_NO_UPDATE // Whether we are queued for an update.
-/datum/light_source/New(var/atom/owner, var/atom/top)
+/datum/light_source/New(atom/owner, atom/top)
source_atom = owner // Set our new owner.
LAZYADD(source_atom.light_sources, src)
top_atom = top
@@ -56,7 +56,7 @@
LAZYREMOVE(top_atom.light_sources, src)
if(needs_update)
- GLOB.lighting_update_lights -= src
+ SSlighting.sources_queue -= src
. = ..()
@@ -65,13 +65,13 @@
// Actually that'd be great if you could!
#define EFFECT_UPDATE(level) \
if(needs_update == LIGHTING_NO_UPDATE) \
- GLOB.lighting_update_lights += src; \
+ SSlighting.sources_queue += src; \
if(needs_update < level) \
needs_update = level; \
// This proc will cause the light source to update the top atom, and add itself to the update queue.
-/datum/light_source/proc/update(var/atom/new_top_atom)
+/datum/light_source/proc/update(atom/new_top_atom)
// This top atom is different.
if(new_top_atom && new_top_atom != top_atom)
if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom.
@@ -141,7 +141,7 @@
effect_str = null
-/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
+/datum/light_source/proc/recalc_corner(datum/lighting_corner/C)
LAZYINITLIST(effect_str)
if(effect_str[C]) // Already have one.
REMOVE_CORNER(C)
@@ -220,13 +220,14 @@
var/oldlum = source_turf.luminosity
source_turf.luminosity = CEILING(light_range, 1)
for(T in view(CEILING(light_range, 1), source_turf))
- if((!IS_DYNAMIC_LIGHTING(T) && !T.light_sources) || T.has_opaque_atom)
+ if((!IS_DYNAMIC_LIGHTING(T) && !T.light_sources))
continue
- if(!T.lighting_corners_initialised)
- T.generate_missing_corners()
- for(thing in T.corners)
- C = thing
- corners[C] = 0
+ if(!T.has_opaque_atom)
+ if(!T.lighting_corners_initialised)
+ T.generate_missing_corners()
+ for(thing in T.corners)
+ C = thing
+ corners[C] = 0
turfs += T
source_turf.luminosity = oldlum
diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm
index f368ff5ac4b..5483eebf4e1 100644
--- a/code/modules/lighting/lighting_turf.dm
+++ b/code/modules/lighting/lighting_turf.dm
@@ -57,7 +57,7 @@
C.active = TRUE
// Used to get a scaled lumcount.
-/turf/proc/get_lumcount(var/minlum = 0, var/maxlum = 1)
+/turf/proc/get_lumcount(minlum = 0, maxlum = 1)
if(!lighting_object)
return 1
@@ -102,7 +102,7 @@
recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates.
reconsider_lights()
-/turf/proc/change_area(var/area/old_area, var/area/new_area)
+/turf/proc/change_area(area/old_area, area/new_area)
if(SSlighting.initialized)
if(new_area.dynamic_lighting != old_area.dynamic_lighting)
if(new_area.dynamic_lighting)
diff --git a/code/modules/logic/converter.dm b/code/modules/logic/converter.dm
deleted file mode 100644
index c54e3fe4882..00000000000
--- a/code/modules/logic/converter.dm
+++ /dev/null
@@ -1,143 +0,0 @@
-
-//////////////////////////////////
-// Converter Gate //
-//////////////////////////////////
-
-/*
- This gate is special enough to warrant its own file, as it overrides a lot of the logic_gate procs as well as adds a new one.
- - CONVERT Gates convert signaler and logic signals, to allow logic gates to actually be used in tandem with assemblies and station equipment like doors.
- - While technically a mono-input device, the input and output are actually completely different types of signals, and thus incompatible without this gate.
- - A signaler must be attached manually before the gate is fully functional, and will retain any frequency and code settings it had when attached.
- - You can adjust these settings through a link in the multitool menu, but the receiving mode is automatically controlled by the converter.
- - While attached, the ability to manually send the signal on the signaler through its menu is also disabled, to avoid messing up the logic system.
-*/
-
-//CONVERT Gate
-/obj/machinery/logic_gate/convert
- name = "CONVERT Gate"
- desc = "Converts signals between radio and logic types, allowing for signaller input/output from logic systems."
- icon_state = "logic_convert"
- mono_input = 1
-
- var/logic_output = 0 //When set to 1, the logic signal is the output. When set to 0, the logic signal is the input.
- var/obj/item/assembly/signaler/attached_signaler = null
-
-/obj/machinery/logic_gate/convert/handle_logic()
- output_state = input1_state
- return
-
-/obj/machinery/logic_gate/convert/attackby(obj/item/O, mob/user, params)
- if(tamperproof) //Extra precaution to avoid people attaching/removing signalers from tamperproofed converters
- return
- if(istype(O, /obj/item/assembly/signaler))
- var/obj/item/assembly/signaler/S = O
- if(S.secured)
- to_chat(user, "The [S] is already secured.")
- return
- if(attached_signaler)
- to_chat(user, "There is already a device attached, remove it first.")
- return
- user.unEquip(S)
- S.forceMove(src)
- S.holder = src
- S.toggle_secure()
- if(logic_output) //Make sure we are set to receive if the converter is set to output logic, and send if the converter is set to accept logic input
- S.receiving = 1
- else
- S.receiving = 0
- attached_signaler = S
- to_chat(user, "You attach \the [S] to the I/O connection port and secure it.")
- return
- if(attached_signaler && istype(O, /obj/item/screwdriver)) //Makes sure we remove the attached signaler before we can open up and deconstruct the machine
- var/obj/item/assembly/signaler/S = attached_signaler
- attached_signaler = null
- S.forceMove(get_turf(src))
- S.holder = null
- S.toggle_secure()
- to_chat(user, "You unsecure and detach \the [S] from the I/O connection port.")
- return
- return ..()
-
-/obj/machinery/logic_gate/convert/multitool_menu(var/mob/user, var/obj/item/multitool/P)
- var/logic_state_string
- var/menu_contents = {"
-
- "}
- if(logic_output)
- switch(output_state)
- if(LOGIC_OFF)
- logic_state_string = "OFF"
- if(LOGIC_ON)
- logic_state_string = "ON"
- if(LOGIC_FLICKER)
- logic_state_string = "FLICKER"
- else
- logic_state_string = "ERROR: UNKNOWN STATE"
- menu_contents += {"
- - Output: [format_tag("ID Tag","output_id_tag")]
- - Output State: [logic_state_string]
- "}
- else
- switch(input1_state)
- if(LOGIC_OFF)
- logic_state_string = "OFF"
- if(LOGIC_ON)
- logic_state_string = "ON"
- if(LOGIC_FLICKER)
- logic_state_string = "FLICKER"
- else
- logic_state_string = "ERROR: UNKNOWN STATE"
- menu_contents += {"
- - Input: [format_tag("ID Tag","input1_id_tag")]
- - Input State: [logic_state_string]
- "}
- menu_contents += {"
- - Logic Signal Designation: [logic_output ? "Output" : "Input"]
- "}
- if(attached_signaler)
- menu_contents += "- Adjust Signaler Settings
"
- else
- menu_contents += "- NO SIGNALER ATTACHED!
"
- menu_contents += {"
-
- "}
- return menu_contents
-
-/obj/machinery/logic_gate/convert/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
- ..()
- if("toggle_logic" in href_list)
- logic_output = !logic_output
- if(attached_signaler) //If we have a signaler attached, make sure we update it to send/receive when we change the logic signal desgination
- if(logic_output)
- attached_signaler.receiving = 1
- else
- attached_signaler.receiving = 0
- if(("adjust_signaler" in href_list) && attached_signaler) //Make sure that we have a signaler attached to handle this one, otherwise ignore this command
- attached_signaler.interact(user, 1)
- update_multitool_menu(user)
-
-/obj/machinery/logic_gate/convert/receive_signal(datum/signal/signal, receive_method, receive_param)
- if(logic_output)
- if(attached_signaler)
- attached_signaler.receive_signal(signal)
- return
- else
- ..()
-
-/obj/machinery/logic_gate/convert/handle_output()
- if(logic_output)
- ..()
- else
- if(attached_signaler && (output_state == LOGIC_ON || output_state == LOGIC_FLICKER))
- attached_signaler.signal()
- return
-
-/obj/machinery/logic_gate/convert/proc/process_activation(var/obj/item/D)
- if(!logic_output) //Don't bother if our input is a logic signal
- return
- if(D == attached_signaler) //Ignore if we somehow got called by a device that isn't what we have attached
- input1_state = LOGIC_FLICKER
- spawn(LOGIC_FLICKER_TIME)
- if(input1_state == LOGIC_FLICKER)
- input1_state = LOGIC_OFF
- return
diff --git a/code/modules/logic/dual_input.dm b/code/modules/logic/dual_input.dm
deleted file mode 100644
index b8f915ff46d..00000000000
--- a/code/modules/logic/dual_input.dm
+++ /dev/null
@@ -1,100 +0,0 @@
-
-//////////////////////////////////
-// Dual-Input Gates //
-//////////////////////////////////
-
-
-// OR Gate
-/obj/machinery/logic_gate/or
- name = "OR Gate"
- desc = "Outputs ON when at least one input is ON."
- icon_state = "logic_or"
-
-/obj/machinery/logic_gate/or/handle_logic()
- if(input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER || input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER)
- if(input1_state == LOGIC_ON || input2_state == LOGIC_ON) //continuous signal takes priority in determining what to output
- output_state = LOGIC_ON
- else
- output_state = LOGIC_FLICKER
- else //Both inputs were off, so input is off
- output_state = LOGIC_OFF
- return
-
-// AND Gate
-/obj/machinery/logic_gate/and
- name = "AND Gate"
- desc = "Outputs ON only when both inputs are ON."
- icon_state = "logic_and"
-
-/obj/machinery/logic_gate/and/handle_logic()
- if((input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER) && (input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER))
- if(input1_state == LOGIC_ON && input2_state == LOGIC_ON) //only output a continuous signal when both inputs are continuous signals
- output_state = LOGIC_ON
- else
- output_state = LOGIC_FLICKER
- else //At least one input was off, so output is off
- output_state = LOGIC_OFF
- return
-
-// NAND Gate
-/obj/machinery/logic_gate/nand
- name = "NAND Gate"
- desc = "Outputs OFF only when both inputs are ON."
- output_state = LOGIC_ON
- icon_state = "logic_nand"
-
-/obj/machinery/logic_gate/nand/handle_logic()
- if((input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER) && (input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER))
- output_state = LOGIC_OFF //Both inputs are ON/FLICKER, so output is off
- else
- output_state = LOGIC_ON //This can only output continuous signals
- return
-
-// NOR Gate
-/obj/machinery/logic_gate/nor
- name = "NOR Gate"
- desc = "Outputs OFF when at least one input is ON."
- icon_state = "logic_nor"
- output_state = LOGIC_ON
-
-/obj/machinery/logic_gate/nor/handle_logic()
- if(input1_state == LOGIC_OFF && input2_state == LOGIC_OFF) //Both inputs are OFF, so output is ON
- output_state = LOGIC_ON //This can only output continuous signals
- else
- output_state = LOGIC_OFF
- return
-
-// XOR Gate
-/obj/machinery/logic_gate/xor
- name = "XOR Gate"
- desc = "Outputs ON when only one input is ON."
- icon_state = "logic_xor"
-
-/obj/machinery/logic_gate/xor/handle_logic()
- if((input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER) && (input2_state == LOGIC_OFF)) //Only input1 is ON/FLICKER, so output matches input1
- output_state = input1_state
- else if((input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER) && (input1_state == LOGIC_OFF)) //Only input2 is ON/FLICKER, so output matches input2
- output_state = input2_state
- else //Both inputs are ON or OFF, so output is OFF
- output_state = LOGIC_OFF
- return
-
-
-// XNOR Gate
-/obj/machinery/logic_gate/xnor
- name = "XNOR Gate"
- desc = "Outputs ON when both inputs are ON or OFF."
- icon_state = "logic_xnor"
- output_state = LOGIC_ON
-
-/obj/machinery/logic_gate/xnor/handle_logic()
- if((input1_state == LOGIC_ON || input1_state == LOGIC_FLICKER) && (input2_state == LOGIC_ON || input2_state == LOGIC_FLICKER)) //Both inputs are ON/FLICKER
- if(input1_state == LOGIC_ON && input2_state == LOGIC_ON) //Only continuous signal when both inputs are ON
- output_state = LOGIC_ON
- else //If at least one input is FLICKER, output FLICKER
- output_state = LOGIC_FLICKER
- else if(input1_state == LOGIC_OFF && input2_state == LOGIC_OFF) //Both inputs are OFF
- output_state = LOGIC_ON //Always continuous in this case
- else //Only one input is ON/FLICKER
- output_state = LOGIC_OFF
- return
diff --git a/code/modules/logic/logic_base.dm b/code/modules/logic/logic_base.dm
deleted file mode 100644
index 542cb09bc7f..00000000000
--- a/code/modules/logic/logic_base.dm
+++ /dev/null
@@ -1,284 +0,0 @@
-
-/obj/machinery/logic_gate
- name = "Logic Base"
- desc = "This does nothing except connect to things. Highly illogical, report to a coder at once if you see this in-game."
- icon = 'icons/obj/computer3.dmi'
- icon_state = "serverframe"
- density = 1
- anchored = 1
-
- settagwhitelist = list("input1_id_tag", "input2_id_tag", "output_id_tag")
-
- var/tamperproof = 0 //if set, will make the machine unable to be destroyed, adjusted, etc. via in-game interaction (USE ONLY FOR MAPPING STUFF)
- var/mono_input = 0 //if set, will ignore input2
-
- var/datum/radio_frequency/radio_connection
- var/frequency = 0
-
- /*
- Some notes on Input/Output:
- - Multiple things can be linked to the same input or output tag, just like how wires can connect multiple sources and receivers.
- - For inputs, only the last signal received BEFORE a process() call will be used in the logic handling.
- - Input states are updated immediately whenever an input signal is received, so it is possible to update multiple times within a single process cycle.
- - This means if you have multiple connected inputs, but the last signal received before the process() call is OFF, it won't matter if the others are both ON.
- - For this reason, please set up your logic properly. You can theoretically chain these infinitely, so there's no need to link multiple things to a single input.
- - For outputs, the signal will attempt to be sent out every process() call, to ensure newly connected things are updated within one process cycle
- - Connecting an output to multiple inputs should not cause issues, as long as you don't have multiple connections to a given input (see previous notes on inputs).
- - The output state is determined immediately preceeding the signal broadcast, using the input states at the time of the process() call, not when a signal is received.
- - Because of how the process cycle works, it is possible that it may take multiple cycles for a signal to fully propogate through a logic chain.
- - This is because machines attempt to process in the order they were added to the scheduler.
- - Building the logic gates at the end of the chain first may cause delays in signal propogation.
- If you take all this into consideration when linking and using logic machinery, you should have no unexpected issues with input/output. Your design flaws are on you though.
- */
-
- var/input1_id_tag = null
- var/input1_state = LOGIC_OFF
- var/input2_id_tag = null
- var/input2_state = LOGIC_OFF
- var/output_id_tag = null
- var/output_state = LOGIC_OFF
-
-/obj/machinery/logic_gate/New()
- if(tamperproof) //doing this during New so we don't have to worry about forgetting to set these vars during editting / defining
- resistance_flags |= ACID_PROOF
- ..()
- if(SSradio)
- set_frequency(frequency)
- component_parts = list()
- var/obj/item/circuitboard/logic_gate/LG = new(null)
- LG.set_type(type)
- component_parts += LG
- component_parts += new /obj/item/stack/cable_coil(null, 1)
-
-/obj/machinery/logic_gate/Initialize()
- ..()
- set_frequency(frequency)
-
-/obj/machinery/logic_gate/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, RADIO_LOGIC)
- return
-
-/obj/machinery/logic_gate/Destroy()
- if(SSradio)
- SSradio.remove_object(src, frequency)
- radio_connection = null
- return ..()
-
-/obj/machinery/logic_gate/process()
- handle_logic()
- handle_output() //All output will send for at least one cycle, and will attempt to send every cycle. Hopefully this won't be too taxing.
- return
-
-/obj/machinery/logic_gate/proc/handle_logic()
- return
-
-/obj/machinery/logic_gate/proc/handle_output()
- if(!radio_connection) //can't output without this
- return
-
- if(output_id_tag == null) //Don't output to an undefined id_tag
- return
-
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
- "tag" = output_id_tag,
- "sigtype" = "logic",
- "state" = output_state,
- )
-
- radio_connection.post_signal(src, signal, filter = RADIO_LOGIC)
-
-/obj/machinery/logic_gate/receive_signal(datum/signal/signal, receive_method, receive_param)
- if(!signal.data["tag"] || ((signal.data["tag"] != input1_id_tag) && (signal.data["tag"] != input2_id_tag)) || (signal.data["sigtype"] != "logic"))
- //If the signal lacks tag data, the signal's tag data doesn't match either input id tag, or is not a "logic" signal, ignore it since it's not for us
- return
-
- if(signal.data["tag"] == input1_id_tag) //If the signal is for input1
- if(signal.data["state"] == input1_state) //If we already match, ignore the new signal since nothing changes
- return
- if(signal.data["state"] == LOGIC_OFF) //Shut it down and keep it off
- input1_state = LOGIC_OFF
- return
- if(signal.data["state"] == LOGIC_ON) //Turn it on and keep it on
- input1_state = LOGIC_ON
- return
- if(signal.data["state"] == LOGIC_FLICKER) //Turn it on then turn it off
- if(input1_state == LOGIC_ON) //An existing continuous ON state overrides new flicker signals
- return
- input1_state = LOGIC_FLICKER
- spawn(LOGIC_FLICKER_TIME)
- if(input1_state == LOGIC_FLICKER) //Make sure we didn't get a new continuous signal set while we waited (those take priority)
- input1_state = LOGIC_OFF
- return
-
- //Now, you may be wondering why I included those returns.
- //The answer is "If you link both inputs to the same source, you're an idiot and deserve to have it break", so yeah. Deal with it.
-
- if(mono_input)
- //We only care about input1, so if we didn't receive a signal for that, we're done.
- return
-
- if(signal.data["tag"] == input2_id_tag) //If the signal is for input2 (reaching this point assumes mono_input is not set)
- if(signal.data["state"] == input2_state) //If we already match, ignore the new signal since nothing changes
- return
- if(signal.data["state"] == LOGIC_OFF) //Shut it down and keep it off
- input2_state = LOGIC_OFF
- return
- if(signal.data["state"] == LOGIC_ON) //Turn it on and keep it on
- input2_state = LOGIC_ON
- return
- if(signal.data["state"] == LOGIC_FLICKER) //Turn it on then turn it off
- if(input2_state == LOGIC_ON) //An existing continuous ON state overrides new flicker signals
- return
- input2_state = LOGIC_FLICKER
- spawn(LOGIC_FLICKER_TIME)
- if(input2_state == LOGIC_FLICKER) //Make sure we didn't get a new continuous signal set while we waited (those take priority)
- input2_state = LOGIC_OFF
- return
-
-/obj/machinery/logic_gate/multitool_menu(var/mob/user, var/obj/item/multitool/P)
- var/input1_state_string
- var/input2_state_string
- var/output_state_string
-
- switch(input1_state)
- if(LOGIC_OFF)
- input1_state_string = "OFF"
- if(LOGIC_ON)
- input1_state_string = "ON"
- if(LOGIC_FLICKER)
- input1_state_string = "FLICKER"
- else
- input1_state_string = "ERROR: UNKNOWN STATE"
-
- switch(input2_state)
- if(LOGIC_OFF)
- input2_state_string = "OFF"
- if(LOGIC_ON)
- input2_state_string = "ON"
- if(LOGIC_FLICKER)
- input2_state_string = "FLICKER"
- else
- input2_state_string = "ERROR: UNKNOWN STATE"
-
- switch(output_state)
- if(LOGIC_OFF)
- output_state_string = "OFF"
- if(LOGIC_ON)
- output_state_string = "ON"
- if(LOGIC_FLICKER)
- output_state_string = "FLICKER"
- else
- output_state_string = "ERROR: UNKNOWN STATE"
- var/menu_contents = {"
-
- - Input: [format_tag("ID Tag","input1_id_tag")]
- - Input State: [input1_state_string]
- "}
- if(!mono_input)
- menu_contents = {"
- - Input 1: [format_tag("ID Tag","input1_id_tag")]
- - Input 1 State: [input1_state_string]
- - Input 2: [format_tag("ID Tag","input2_id_tag")]
- - Input 2 State: [input2_state_string]
- "}
- menu_contents += {"
- - Output: [format_tag("ID Tag","output_id_tag")]
- - Output State: [output_state_string]
-
- "}
- return menu_contents
-
-/obj/machinery/logic_gate/convert/multitool_topic(var/mob/user,var/list/href_list,var/obj/O)
- ..()
- update_multitool_menu(user)
-
-/obj/machinery/logic_gate/attackby(obj/item/O, mob/user, params)
- if(tamperproof)
- to_chat(user, "The [src] appears to be tamperproofed! You can't interact with it!")
- return 0
- if(istype(O, /obj/item/multitool))
- update_multitool_menu(user)
- return 1
- if(istype(O, /obj/item/screwdriver))
- panel_open = !panel_open
- to_chat(user, "You [panel_open ? "open" : "close"] the access panel.")
- return 1
- if(panel_open && istype(O, /obj/item/crowbar))
- default_deconstruction_crowbar(user, O)
- return 1
- return ..()
-
-//////////////////////////////////////
-// Attack procs //
-//////////////////////////////////////
-
-/obj/machinery/logic_gate/attack_ai(mob/user)
- if(tamperproof)
- to_chat(user, "The [src] appears to be tamperproofed! You can't interface with it!")
- return 0
- add_hiddenprint(user)
- return ui_interact(user)
-
-/obj/machinery/logic_gate/attack_ghost(mob/user)
- if(tamperproof)
- to_chat(user, "The [src] appears to be tamperproofed! You can't haunt it!")
- return 0
- return ui_interact(user)
-
-/obj/machinery/logic_gate/attack_hand(mob/user)
- if(tamperproof)
- to_chat(user, "The [src] appears to be tamperproofed! You can't interact with it!")
- return 0
- . = ..()
- if(.)
- return 0
- return interact(user)
-
-/obj/machinery/logic_gate/attack_alien(mob/user) //No xeno logic, that's too silly.
- to_chat(user, "The [src] appears to be too complex! You can't comprehend it and back off in fear!")
- return 0
-
-/obj/machinery/logic_gate/attack_animal(mob/user) //No animal logic either.
- to_chat(user, "The [src] appears to be beyond your comprehension! You can't fathom it!")
- return 0
-
-/obj/machinery/logic_gate/attack_slime(mob/user) //No slime logic. Seriously.
- to_chat(user, "The [src] appears to be beyond your gelatinous understanding! You ignore it!")
- return 0
-
-/obj/machinery/logic_gate/emp_act(severity)
- if(tamperproof)
- return 0
- ..()
-
-/obj/machinery/logic_gate/ex_act(severity)
- if(tamperproof)
- return 0
- ..()
-
-/obj/machinery/logic_gate/blob_act(obj/structure/blob/B)
- if(!tamperproof)
- return ..()
-
-/obj/machinery/logic_gate/singularity_act()
- if(tamperproof)
- //This is some top-level tamperproofing right here, that's for sure. It can even defy a singularity!
- return 0
- ..()
-
-/obj/machinery/logic_gate/bullet_act()
- if(tamperproof)
- return 0
- ..()
-
-/obj/machinery/logic_gate/tesla_act(var/power)
- if(tamperproof)
- tesla_zap(src, 3, power) //If we're tamperproof, we'll just bounce the full shock of the tesla zap we got hit by, so it continues on normally without diminishing
- return 0
- ..()
diff --git a/code/modules/logic/mono_input.dm b/code/modules/logic/mono_input.dm
deleted file mode 100644
index 58b76232fa0..00000000000
--- a/code/modules/logic/mono_input.dm
+++ /dev/null
@@ -1,62 +0,0 @@
-
-//////////////////////////////////
-// Mono-Input Gates //
-//////////////////////////////////
-
-//NOT Gate
-/obj/machinery/logic_gate/not
- name = "NOT Gate"
- desc = "Accepts one input and outputs the reverse state."
- icon_state = "logic_not"
- mono_input = 1 //NOT Gates are the simplest logic gate because they only utilize one input.
- output_state = LOGIC_ON //Starts with an active output, since the input will be OFF at start
-/*
- A quick note regarding NOT Gates:
- - Connecting multiple things to the input of a NOT Gate can cause weird behaviour due to updating both when it receives a signal and when it calls process().
- - This means it will attempt to output once for every logic machine connected to its input's own process() call.
- - It will then attempt to output an additional time based on the current state when it comes to its own process() call.
- - For this reason, it is HIGHLY RECOMMENDED that you only connect a single signal source to the input of a NOT Gate to avoid signal spasms.
- - Connecting multiple things to the output of a NOT Gate should not cause this unusual behavior.
-*/
-/obj/machinery/logic_gate/not/handle_logic() //Our output will always be a continuous signal, even with a FLICKER, it just will update the output when the FLICKER ends
- if(input1_state == LOGIC_ON) //Output is OFF while input is ON
- output_state = LOGIC_OFF
- else if(input1_state == LOGIC_FLICKER) //Output is OFF while input is FLICKER, then output returns to ON when input returns to OFF
- output_state = LOGIC_OFF
- spawn(LOGIC_FLICKER_TIME + 1) //Call handle_logic again after this delay (the input should update from the spawn(LOGIC_FLICKER_TIME) in receive_signal() by then)
- handle_logic()
- else //Output is ON while input is OFF
- output_state = LOGIC_ON
- handle_output()
- return
-
-//STATUS Gate
-/obj/machinery/logic_gate/status
- name = "Status Gate"
- desc = "Accepts one input and outputs the same state, showing a colored light based on current state."
- icon_state = "logic_status"
- mono_input = 1 //STATUS Gate doesn't actually perform logic operations, but instead acts as a testing conduit.
-
-/*
- STATUS Gates are largely a diagnostics tool, but I'm sure someone will still make a logic gate rave with them anyways.
- - There is no need to actually connect an output for these to work, they just need an input to sample from.
- - STATUS Gates attempt to update their lights whenever they receive a signal.
-*/
-
-/obj/machinery/logic_gate/status/receive_signal(datum/signal/signal, receive_method, receive_params)
- ..()
- handle_logic() //STATUS Gate calls handle_logic() when it receives a signal to update its light and output_state
-
-/obj/machinery/logic_gate/status/handle_logic()
- output_state = input1_state //Output is equal to input, since it is simply a connection with an attached light
- if(output_state == LOGIC_OFF) //Red light when OFF
- set_light(2,2,"#ff0000")
- return
- if(output_state == LOGIC_ON) //Green light when ON
- set_light(2,2,"#009933")
- return
- if(output_state == LOGIC_FLICKER) //Orange light when FLICKER, then update after LOGIC_FLICKER_TIME + 1 to reflect the changed state
- set_light(2,2,"#ff9900")
- spawn(LOGIC_FLICKER_TIME + 1)
- handle_logic()
- return
diff --git a/code/modules/martial_arts/martial.dm b/code/modules/martial_arts/martial.dm
index 478438c47cb..8969463be1d 100644
--- a/code/modules/martial_arts/martial.dm
+++ b/code/modules/martial_arts/martial.dm
@@ -195,6 +195,9 @@
icon = 'icons/obj/library.dmi'
icon_state = "cqcmanual"
+/obj/item/CQC_manual/chef
+ desc = "A small, black manual. Written on the back it says: Bringing the home advantage with you."
+
/obj/item/CQC_manual/attack_self(mob/living/carbon/human/user)
if(!istype(user) || !user)
return
@@ -275,7 +278,6 @@
return
else
return ..()
- return ..()
/obj/item/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(wielded)
diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm
index 9b74c922a6b..044b78a04bc 100644
--- a/code/modules/mining/abandonedcrates.dm
+++ b/code/modules/mining/abandonedcrates.dm
@@ -82,7 +82,7 @@
new /obj/item/clothing/head/corgi(src)
if(67 to 68)
for(var/i in 1 to rand(4, 7))
- var /newitem = pick(subtypesof(/obj/item/stock_parts))
+ var/newitem = pick(subtypesof(/obj/item/stock_parts))
new newitem(src)
if(69 to 70)
new /obj/item/stack/ore/bluespace_crystal(src, 5)
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index f21978db625..4af48e7050a 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -65,6 +65,8 @@
user.drop_l_hand()
return
var/datum/status_effect/crusher_damage/C = target.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(!C)
+ C = target.apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
var/target_health = target.health
..()
for(var/t in trophies)
@@ -101,6 +103,8 @@
if(!CM || CM.hammer_synced != src || !L.remove_status_effect(STATUS_EFFECT_CRUSHERMARK))
return
var/datum/status_effect/crusher_damage/C = L.has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(!C)
+ C = L.apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
var/target_health = L.health
for(var/t in trophies)
var/obj/item/crusher_trophy/T = t
diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm
index 44462dedfda..43cce5904e3 100644
--- a/code/modules/mining/equipment/wormhole_jaunter.dm
+++ b/code/modules/mining/equipment/wormhole_jaunter.dm
@@ -26,7 +26,7 @@
/obj/item/wormhole_jaunter/proc/get_destinations(mob/user)
var/list/destinations = list()
- for(var/obj/item/radio/beacon/B in world)
+ for(var/obj/item/radio/beacon/B in GLOB.global_radios)
var/turf/T = get_turf(B)
if(is_station_level(T.z))
destinations += B
diff --git a/code/modules/mining/lavaland/loot/ashdragon_loot.dm b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
index e9728bc7901..21bc247b0df 100644
--- a/code/modules/mining/lavaland/loot/ashdragon_loot.dm
+++ b/code/modules/mining/lavaland/loot/ashdragon_loot.dm
@@ -81,7 +81,7 @@
var/mob/dead/observer/current_spirits = list()
for(var/mob/dead/observer/O in GLOB.player_list)
- if((O.following in contents))
+ if((O.orbiting in contents))
ghost_counter++
O.invisibility = 0
current_spirits |= O
@@ -97,13 +97,13 @@
force = 0
var/ghost_counter = ghost_check()
- force = Clamp((ghost_counter * 4), 0, 75)
+ force = clamp((ghost_counter * 4), 0, 75)
user.visible_message("[user] strikes with the force of [ghost_counter] vengeful spirits!")
..()
/obj/item/melee/ghost_sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
var/ghost_counter = ghost_check()
- final_block_chance += Clamp((ghost_counter * 5), 0, 75)
+ final_block_chance += clamp((ghost_counter * 5), 0, 75)
owner.visible_message("[owner] is protected by a ring of [ghost_counter] ghosts!")
return ..()
@@ -120,18 +120,13 @@
return
var/mob/living/carbon/human/H = user
- var/random = rand(1,3)
+ var/random = rand(1,2)
switch(random)
if(1)
to_chat(user, "Your flesh begins to melt! Miraculously, you seem fine otherwise.")
H.set_species(/datum/species/skeleton)
if(2)
- to_chat(user, "Power courses through you! You can now shift your form at will.")
- if(user.mind)
- var/obj/effect/proc_holder/spell/targeted/shapeshift/dragon/D = new
- user.mind.AddSpell(D)
- if(3)
to_chat(user, "You feel like you could walk straight through lava now.")
H.weather_immunities |= "lava"
diff --git a/code/modules/mining/lavaland/loot/bubblegum_loot.dm b/code/modules/mining/lavaland/loot/bubblegum_loot.dm
index fa7791edb9e..4ee2c76a419 100644
--- a/code/modules/mining/lavaland/loot/bubblegum_loot.dm
+++ b/code/modules/mining/lavaland/loot/bubblegum_loot.dm
@@ -82,7 +82,7 @@
B.mineEffect(L)
for(var/mob/living/carbon/human/H in GLOB.player_list)
- if(H == L)
+ if(H.stat == DEAD || H == L)
continue
to_chat(H, "You have an overwhelming desire to kill [L]. [L.p_they(TRUE)] [L.p_have()] been marked red! Go kill [L.p_them()]!")
H.put_in_hands(new /obj/item/kitchen/knife/butcher(H))
diff --git a/code/modules/mining/lavaland/loot/hierophant_loot.dm b/code/modules/mining/lavaland/loot/hierophant_loot.dm
index a3f6e738380..fc81e6399ae 100644
--- a/code/modules/mining/lavaland/loot/hierophant_loot.dm
+++ b/code/modules/mining/lavaland/loot/hierophant_loot.dm
@@ -93,7 +93,7 @@
blast_range = initial(blast_range)
if(isliving(user))
var/mob/living/L = user
- var/health_percent = L.health / L.maxHealth
+ var/health_percent = max(L.health / L.maxHealth, 0) // Don't go negative
chaser_cooldown += round(health_percent * 20) //two tenths of a second for each missing 10% of health
cooldown_time += round(health_percent * 10) //one tenth of a second for each missing 10% of health
chaser_speed = max(chaser_speed + health_percent, 0.5) //one tenth of a second faster for each missing 10% of health
diff --git a/code/modules/mining/lavaland/loot/tendril_loot.dm b/code/modules/mining/lavaland/loot/tendril_loot.dm
index f54bc974f7e..0af08e40c74 100644
--- a/code/modules/mining/lavaland/loot/tendril_loot.dm
+++ b/code/modules/mining/lavaland/loot/tendril_loot.dm
@@ -383,7 +383,10 @@
var/mob/living/L = target
if(!L.anchored)
L.visible_message("[L] is snagged by [firer]'s hook!")
+ var/old_density = L.density
+ L.density = FALSE // Ensures the hook does not hit the target multiple times
L.forceMove(get_turf(firer))
+ L.density = old_density
/obj/item/projectile/hook/Destroy()
QDEL_NULL(chain)
diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm
index 50cb7d09801..579df861c19 100644
--- a/code/modules/mining/machine_processing.dm
+++ b/code/modules/mining/machine_processing.dm
@@ -98,7 +98,7 @@
/obj/machinery/mineral/processing_unit/Destroy()
CONSOLE = null
QDEL_NULL(files)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
return ..()
@@ -120,7 +120,7 @@
CONSOLE.updateUsrDialog()
/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/material_amount = materials.get_item_material_amount(O)
if(!materials.has_space(material_amount))
unload_mineral(O)
@@ -132,7 +132,7 @@
/obj/machinery/mineral/processing_unit/proc/get_machine_data()
var/dat = "Smelter control console
"
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
dat += "[M.name]: [M.amount] cm³"
@@ -165,7 +165,7 @@
return dat
/obj/machinery/mineral/processing_unit/proc/smelt_ore()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/datum/material/mat = materials.materials[selected_material]
if(mat)
var/sheets_to_remove = (mat.amount >= (MINERAL_MATERIAL_AMOUNT * SMELT_AMOUNT) ) ? SMELT_AMOUNT : round(mat.amount / MINERAL_MATERIAL_AMOUNT)
@@ -187,7 +187,7 @@
on = FALSE
return
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.use_amount(alloy.materials, amount)
generate_mineral(alloy.build_path)
@@ -198,7 +198,7 @@
var/build_amount = SMELT_AMOUNT
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in D.materials)
var/M = D.materials[mat_id]
diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm
index ed955efda2c..9630395e0cd 100644
--- a/code/modules/mining/machine_redemption.dm
+++ b/code/modules/mining/machine_redemption.dm
@@ -67,7 +67,7 @@
/obj/machinery/mineral/ore_redemption/Destroy()
QDEL_NULL(files)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
return ..()
@@ -92,7 +92,7 @@
if(O && O.refined_type)
points += O.points * point_upgrade * O.amount
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/material_amount = materials.get_item_material_amount(O)
if(!material_amount)
@@ -111,7 +111,7 @@
var/build_amount = 0
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in D.materials)
var/M = D.materials[mat_id]
var/datum/material/redemption_mat = materials.materials[mat_id]
@@ -147,7 +147,7 @@
var/has_minerals = FALSE
var/mineral_name = null
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT
@@ -221,7 +221,7 @@
. = TRUE
if(!powered())
return
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
input_dir = turn(input_dir, -90)
output_dir = turn(output_dir, -90)
@@ -251,7 +251,7 @@
else
dat += "No ID inserted. Insert ID.
"
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
if(M.amount)
@@ -302,7 +302,7 @@
/obj/machinery/mineral/ore_redemption/Topic(href, href_list)
if(..())
return
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(href_list["eject_id"])
usr.put_in_hands(inserted_id)
inserted_id = null
diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm
index 1198e2fb9d3..dbaa24fef34 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -101,7 +101,7 @@
if(user.a_intent != INTENT_HELP)
return
. = TRUE
- if(!I.tool_start_check(user, 0))
+ if(!I.tool_start_check(src, user, 0))
return
I.melee_attack_chain(user, stored_gun)
diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm
index 9fb73229ba7..9cabe4ac486 100644
--- a/code/modules/mining/mint.dm
+++ b/code/modules/mining/mint.dm
@@ -23,7 +23,7 @@
if(!T)
return
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/obj/item/stack/sheet/O in T)
materials.insert_stack(O, O.amount)
@@ -32,7 +32,7 @@
return
var/dat = "Coin Press "
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
if(!M.amount && chosen != mat_id)
@@ -65,12 +65,12 @@
if(processing == 1)
to_chat(usr, "The machine is processing.")
return
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(href_list["choose"])
if(materials.materials[href_list["choose"]])
chosen = href_list["choose"]
if(href_list["chooseAmt"])
- coinsToProduce = Clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000)
+ coinsToProduce = clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000)
if(href_list["makeCoins"])
var/temp_coins = coinsToProduce
processing = TRUE
diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm
index 8737fdf21b3..c01d04beba8 100644
--- a/code/modules/mining/ores_coins.dm
+++ b/code/modules/mining/ores_coins.dm
@@ -273,7 +273,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
icon_state = "Gibtonite active"
var/turf/bombturf = get_turf(src)
var/notify_admins = 0
- if(z != 5)//Only annoy the admins ingame if we're triggered off the mining zlevel
+ if(!is_mining_level(z))//Only annoy the admins ingame if we're triggered off the mining zlevel
notify_admins = 1
if(notify_admins)
diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm
index 39931a60fb2..090e5ddac1e 100644
--- a/code/modules/mob/camera/camera.dm
+++ b/code/modules/mob/camera/camera.dm
@@ -14,3 +14,8 @@
/mob/camera/experience_pressure_difference()
return
+
+/mob/camera/forceMove(atom/destination)
+ var/oldloc = loc
+ loc = destination
+ Moved(oldloc, NONE)
diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm
index 24f129ee387..f60777a97ff 100644
--- a/code/modules/mob/dead/dead.dm
+++ b/code/modules/mob/dead/dead.dm
@@ -15,7 +15,7 @@
onTransitZ(old_turf?.z, new_turf?.z)
var/oldloc = loc
loc = destination
- Moved(oldloc, NONE, TRUE)
+ Moved(oldloc, NONE)
/mob/dead/onTransitZ(old_z,new_z)
..()
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index dc7c2b4439e..31ff0098335 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -23,7 +23,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
//If you died in the game and are a ghsot - this will remain as null.
//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
universal_speak = TRUE
- var/atom/movable/following = null
var/image/ghostimage = null //this mobs ghost image, for deleting and stuff
var/ghostvision = TRUE //is the ghost able to see things humans can't?
var/seedarkness = TRUE
@@ -54,7 +53,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
if(ismob(body))
T = get_turf(body) //Where is the body located?
attack_log_old = body.attack_log_old //preserve our attack logs by copying them to our ghost
- logs = body.logs.Copy()
var/mutable_appearance/MA = copy_appearance(body)
if(body.mind && body.mind.name)
@@ -230,7 +228,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Move(NewLoc, direct)
update_parallax_contents()
- following = null
setDir(direct)
ghostimage.setDir(dir)
@@ -412,7 +409,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
forceMove(pick(L))
update_parallax_contents()
- following = null
/mob/dead/observer/verb/follow()
set category = "Ghost"
@@ -424,7 +420,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
A.on_close(CALLBACK(src, .proc/ManualFollow))
// This is the ghost's follow verb with an argument
-/mob/dead/observer/proc/ManualFollow(var/atom/movable/target)
+/mob/dead/observer/proc/ManualFollow(atom/movable/target)
if(!target || !isobserver(usr))
return
@@ -432,7 +428,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return
if(target != src)
- if(following && following == target)
+ if(orbiting && orbiting == target)
return
var/icon/I = icon(target.icon,target.icon_state,target.dir)
@@ -458,7 +454,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
else //Circular
rot_seg = 36 //360/10 bby, smooth enough aproximation of a circle
- following = target
to_chat(src, "Now following [target]")
orbit(target,orbitsize, FALSE, 20, rot_seg)
@@ -485,7 +480,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
A.forceMove(T)
M.update_parallax_contents()
- following = null
return
to_chat(A, "This mob is not located in the game world.")
@@ -616,7 +610,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Topic(href, href_list)
if(usr != src)
return
- ..()
if(href_list["track"])
var/atom/target = locate(href_list["track"])
@@ -630,7 +623,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(href_list["jump"])
var/mob/target = locate(href_list["jump"])
- var/mob/A = usr;
+ var/mob/A = usr
to_chat(A, "Teleporting to [target]...")
//var/mob/living/silicon/ai/A = locate(href_list["track2"]) in GLOB.mob_list
if(target && target != usr)
@@ -643,7 +636,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(!client)
return
forceMove(T)
- following = null
if(href_list["reenter"])
reenter_corpse()
diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm
index 5f18a27adc9..99e0af0ca6a 100644
--- a/code/modules/mob/emote.dm
+++ b/code/modules/mob/emote.dm
@@ -135,7 +135,7 @@
if(message)
for(var/mob/M in GLOB.player_list)
- if(istype(M, /mob/new_player))
+ if(isnewplayer(M))
continue
if(check_rights(R_ADMIN|R_MOD, 0, M) && M.get_preference(CHAT_DEAD)) // Show the emote to admins/mods
diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index 2b07e10291f..410c485f15e 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -47,7 +47,7 @@
. = trim(. + trim(msg))
. += "\""
-/mob/proc/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency)
+/mob/proc/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
if(!client)
return 0
@@ -74,7 +74,7 @@
return 0
var/speaker_name = speaker.name
- if(ishuman(speaker))
+ if(use_voice && ishuman(speaker))
var/mob/living/carbon/human/H = speaker
speaker_name = H.GetVoice()
@@ -99,9 +99,9 @@
if(speaker == src)
to_chat(src, "You cannot hear yourself speak!")
else
- to_chat(src, "[speaker_name][speaker.GetAltName()] talks but you cannot hear [speaker.p_them()].")
+ to_chat(src, "[speaker.name] talks but you cannot hear [speaker.p_them()].")
else
- to_chat(src, "[speaker_name][speaker.GetAltName()] [track][message]")
+ to_chat(src, "[speaker_name][use_voice ? speaker.GetAltName() : ""] [track][message]")
if(speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z))
var/turf/source = speaker? get_turf(speaker) : get_turf(src)
playsound_local(source, speech_sound, sound_vol, 1, sound_frequency)
diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm
index 7f3a7049558..a46268daf50 100644
--- a/code/modules/mob/language.dm
+++ b/code/modules/mob/language.dm
@@ -33,7 +33,7 @@
for(var/i = 0;i0;x--)
+ for(var/x = rand(FLOOR(syllable_count/2, 1),syllable_count);x>0;x--)
new_name += pick(syllables)
full_name += " [capitalize(lowertext(new_name))]"
@@ -767,17 +767,6 @@
desc = "Bark bark bark."
key = "vu"
-/datum/language/zombie
- name = "Zombie"
- desc = "BRAAAAAAINS!"
- speech_verb = "moans"
- whisper_verb = "mutters"
- exclaim_verb = "wails"
- colour = "zombie"
- key = "zom"
- flags = RESTRICTED
- syllables = list("BRAAAAAAAAAAAAAAAAINS", "BRAAINS", "BRAINS")
-
/mob/proc/grant_all_babel_languages()
for(var/la in GLOB.all_languages)
var/datum/language/new_language = GLOB.all_languages[la]
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index 247e0bcbab2..f6354b61940 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -2,6 +2,7 @@
name = "alien"
voice_name = "alien"
speak_emote = list("hisses")
+ bubble_icon = "alien"
icon = 'icons/mob/alien.dmi'
gender = NEUTER
dna = null
@@ -226,7 +227,7 @@ Des: Removes all infected images from the alien.
/mob/living/carbon/alien/handle_footstep(turf/T)
if(..())
- if(T.footstep_sounds["xeno"])
+ if(T.footstep_sounds && T.footstep_sounds["xeno"])
var/S = pick(T.footstep_sounds["xeno"])
if(S)
if(m_intent == MOVE_INTENT_RUN)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
index 1ea256357e9..58bdb3a9ecc 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
@@ -136,14 +136,11 @@ Doesn't work on other aliens/AI.*/
set category = "Alien"
if(powerc())
- if(stomach_contents.len)
+ if(LAZYLEN(stomach_contents))
for(var/mob/M in src)
- if(M in stomach_contents)
- stomach_contents.Remove(M)
- M.forceMove(loc)
- //Paralyse(10)
- src.visible_message("[src] hurls out the contents of [p_their()] stomach!")
- return
+ LAZYREMOVE(stomach_contents, M)
+ M.forceMove(drop_location())
+ visible_message("[src] hurls out the contents of [p_their()] stomach!")
/mob/living/carbon/proc/getPlasma()
var/obj/item/organ/internal/xenos/plasmavessel/vessel = get_int_organ(/obj/item/organ/internal/xenos/plasmavessel)
@@ -167,4 +164,4 @@ Doesn't work on other aliens/AI.*/
adjustPlasma(-amount)
return 1
- return 0
+ return 0
diff --git a/code/modules/mob/living/carbon/alien/humanoid/empress.dm b/code/modules/mob/living/carbon/alien/humanoid/empress.dm
index 63514686f3d..a28b3f33a53 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/empress.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/empress.dm
@@ -6,6 +6,7 @@
icon_state = "alienq_s"
status_flags = CANPARALYSE
mob_size = MOB_SIZE_LARGE
+ bubble_icon = "alienroyal"
large = 1
ventcrawler = 0
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm
index e7f783acd72..3174879caac 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm
@@ -55,7 +55,7 @@
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("[M] has attempted to disarm [src]!")
-/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
+/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!no_effect && !visual_effect_icon)
visual_effect_icon = ATTACK_EFFECT_CLAW
..()
diff --git a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm
index 69e12b6ae19..d13dab884b2 100644
--- a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm
+++ b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm
@@ -31,7 +31,7 @@
step_away(src, user, 15)
return TRUE
-/mob/living/carbon/alien/larva/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
+/mob/living/carbon/alien/larva/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!no_effect && !visual_effect_icon)
visual_effect_icon = ATTACK_EFFECT_BITE
..()
diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm
index 496a12cbf82..7acf07f4471 100644
--- a/code/modules/mob/living/carbon/alien/larva/life.dm
+++ b/code/modules/mob/living/carbon/alien/larva/life.dm
@@ -16,7 +16,7 @@
death()
return
- if(paralysis || sleeping || getOxyLoss() > 50 || (HEALTH_THRESHOLD_CRIT <= health && check_death_method()))
+ if(paralysis || sleeping || getOxyLoss() > 50 || (health <= HEALTH_THRESHOLD_CRIT && check_death_method()))
if(stat == CONSCIOUS)
KnockOut()
create_debug_log("fell unconscious, trigger reason: [reason]")
diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm
index 16014e7c353..a17d7b8ebbd 100644
--- a/code/modules/mob/living/carbon/brain/MMI.dm
+++ b/code/modules/mob/living/carbon/brain/MMI.dm
@@ -226,13 +226,6 @@
brainmob.emp_damage += rand(0,10)
..()
-/obj/item/mmi/relaymove(var/mob/user, var/direction)
- if(user.stat || user.stunned)
- return
- var/obj/item/rig/rig = src.get_rig()
- if(rig)
- rig.forced_move(direction, user)
-
/obj/item/mmi/Destroy()
if(isrobot(loc))
var/mob/living/silicon/robot/borg = loc
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 74c5a71c94b..98585262518 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -2,6 +2,10 @@
var/canEnterVentWith = "/obj/item/implant=0&/obj/item/clothing/mask/facehugger=0&/obj/item/radio/borg=0&/obj/machinery/camera=0"
var/datum/middleClickOverride/middleClickOverride = null
+/mob/living/carbon/Initialize(mapload)
+ . = ..()
+ GLOB.carbon_list += src
+
/mob/living/carbon/Destroy()
// This clause is here due to items falling off from limb deletion
for(var/obj/item in get_all_slots())
@@ -14,11 +18,11 @@
if(B)
B.leave_host()
qdel(B)
+ GLOB.carbon_list -= src
return ..()
/mob/living/carbon/handle_atom_del(atom/A)
- if(A in processing_patches)
- processing_patches -= A
+ LAZYREMOVE(processing_patches, A)
return ..()
/mob/living/carbon/blob_act(obj/structure/blob/B)
@@ -46,41 +50,40 @@
/mob/living/carbon/var/last_stomach_attack //defining this here because no one would look in carbon_defines for it
-/mob/living/carbon/relaymove(var/mob/user, direction)
- if(user in src.stomach_contents)
- if(last_stomach_attack + STOMACH_ATTACK_DELAY > world.time) return
+/mob/living/carbon/relaymove(mob/user, direction)
+ if(LAZYLEN(stomach_contents))
+ if(user in stomach_contents)
+ if(last_stomach_attack + STOMACH_ATTACK_DELAY > world.time)
+ return
- last_stomach_attack = world.time
- for(var/mob/M in hearers(4, src))
- if(M.client)
- M.show_message(text("You hear something rumbling inside [src]'s stomach..."), 2)
-
- var/obj/item/I = user.get_active_hand()
- if(I && I.force)
- var/d = rand(round(I.force / 4), I.force)
-
- if(istype(src, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = src
- var/obj/item/organ/external/organ = H.get_organ("chest")
- if(istype(organ))
- if(organ.receive_damage(d, 0))
- H.UpdateDamageIcon()
-
- H.updatehealth("stomach attack")
-
- else
- src.take_organ_damage(d)
-
- for(var/mob/M in viewers(user, null))
+ last_stomach_attack = world.time
+ for(var/mob/M in hearers(4, src))
if(M.client)
- M.show_message(text("[user] attacks [src]'s stomach wall with the [I.name]!"), 2)
- playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1)
+ M.show_message(text("You hear something rumbling inside [src]'s stomach..."), 2)
- if(prob(src.getBruteLoss() - 50))
- for(var/atom/movable/A in stomach_contents)
- A.forceMove(drop_location())
- stomach_contents.Remove(A)
- src.gib()
+ var/obj/item/I = user.get_active_hand()
+ if(I && I.force)
+ var/d = rand(round(I.force / 4), I.force)
+
+ if(istype(src, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = src
+ var/obj/item/organ/external/organ = H.get_organ("chest")
+ if(istype(organ))
+ if(organ.receive_damage(d, 0))
+ H.UpdateDamageIcon()
+
+ H.updatehealth("stomach attack")
+
+ else
+ take_organ_damage(d)
+
+ for(var/mob/M in viewers(user, null))
+ if(M.client)
+ M.show_message(text("[user] attacks [src]'s stomach wall with the [I.name]!"), 2)
+ playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1)
+
+ if(prob(getBruteLoss() - 50))
+ gib()
#undef STOMACH_ATTACK_DELAY
@@ -135,9 +138,8 @@
I.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
for(var/mob/M in src)
- if(M in src.stomach_contents)
- src.stomach_contents.Remove(M)
- M.forceMove(get_turf(src))
+ LAZYREMOVE(stomach_contents, M)
+ M.forceMove(drop_location())
visible_message("[M] bursts out of [src]!")
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
@@ -870,7 +872,6 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
unEquip(I)
I.dropped()
return
- return 1
else
to_chat(src, "You fail to remove [I]!")
@@ -977,25 +978,30 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
/mob/living/carbon/proc/slip(description, stun, weaken, tilesSlipped, walkSafely, slipAny, slipVerb = "slip")
if(flying || buckled || (walkSafely && m_intent == MOVE_INTENT_WALK))
- return 0
+ return FALSE
+
if((lying) && (!(tilesSlipped)))
- return 0
+ return FALSE
+
if(!(slipAny))
if(istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
if(isobj(H.shoes) && H.shoes.flags & NOSLIP)
- return 0
+ return FALSE
+
if(tilesSlipped)
- for(var/t = 0, t<=tilesSlipped, t++)
- spawn (t) step(src, src.dir)
+ for(var/i in 1 to tilesSlipped)
+ spawn(i)
+ step(src, dir)
+
stop_pulling()
to_chat(src, "You [slipVerb]ped on [description]!")
- playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
+ playsound(loc, 'sound/misc/slip.ogg', 50, 1, -3)
// Something something don't run with scissors
moving_diagonally = 0 //If this was part of diagonal move slipping will stop it.
Stun(stun)
Weaken(weaken)
- return 1
+ return TRUE
/mob/living/carbon/proc/can_eat(flags = 255)
return 1
@@ -1060,10 +1066,6 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
/mob/living/carbon/proc/forceFedAttackLog(var/obj/item/reagent_containers/food/toEat, mob/user)
add_attack_logs(user, src, "Fed [toEat]. Reagents: [toEat.reagents.log_list(toEat)]", toEat.reagents.harmless_helper() ? ATKLOG_ALMOSTALL : null)
- if(!iscarbon(user))
- LAssailant = null
- else
- LAssailant = user
/*TO DO - If/when stomach organs are introduced, override this at the human level sending the item to the stomach
@@ -1196,3 +1198,18 @@ so that different stomachs can handle things in different ways VB*/
I.acid_level = 0 //washes off the acid on our clothes
I.extinguish() //extinguishes our clothes
..()
+
+/mob/living/carbon/clean_blood(clean_hands = TRUE, clean_mask = TRUE, clean_feet = TRUE)
+ if(head)
+ if(head.clean_blood())
+ update_inv_head()
+ if(head.flags_inv & HIDEMASK)
+ clean_mask = FALSE
+ if(wear_suit)
+ if(wear_suit.clean_blood())
+ update_inv_wear_suit()
+ if(wear_suit.flags_inv & HIDESHOES)
+ clean_feet = FALSE
+ if(wear_suit.flags_inv & HIDEGLOVES)
+ clean_hands = FALSE
+ ..(clean_hands, clean_mask, clean_feet)
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 75bd6d2664a..e0cba0b0281 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -12,7 +12,7 @@
visible_message("[src] catches [AM]!")
throw_mode_off()
return TRUE
- ..()
+ return ..()
/mob/living/carbon/water_act(volume, temperature, source, method = REAGENT_TOUCH)
. = ..()
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index 97ecf4dd08b..667fd86204e 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -1,11 +1,10 @@
/mob/living/carbon
gender = MALE
pressure_resistance = 15
- var/list/stomach_contents = list()
- var/list/processing_patches = list()
+ var/list/stomach_contents
+ var/list/processing_patches
var/list/internal_organs = list()
var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access.
- var/antibodies = 0
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
diff --git a/code/modules/mob/living/carbon/human/body_accessories.dm b/code/modules/mob/living/carbon/human/body_accessories.dm
index 043a704ab0c..1583bc62c70 100644
--- a/code/modules/mob/living/carbon/human/body_accessories.dm
+++ b/code/modules/mob/living/carbon/human/body_accessories.dm
@@ -1,17 +1,5 @@
GLOBAL_LIST_INIT(body_accessory_by_name, list("None" = null))
-
-/hook/startup/proc/initalize_body_accessories()
-
- __init_body_accessory(/datum/body_accessory/body)
- __init_body_accessory(/datum/body_accessory/tail)
-
- if(GLOB.body_accessory_by_name.len)
- if(initialize_body_accessory_by_species())
- return TRUE
-
- return FALSE //fail if no bodies are found
-
GLOBAL_LIST_INIT(body_accessory_by_species, list("None" = null))
/proc/initialize_body_accessory_by_species()
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 6b7a0a2b15d..4a0b9ea55b1 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -6,7 +6,7 @@
canmove = 0
icon = null
invisibility = 101
- if(!isSynthetic())
+ if(!ismachineperson(src))
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
@@ -32,12 +32,11 @@
E.droplimb(DROPLIMB_SHARP)
for(var/mob/M in src)
- if(M in stomach_contents)
- stomach_contents.Remove(M)
- M.forceMove(get_turf(src))
+ LAZYREMOVE(stomach_contents, M)
+ M.forceMove(drop_location())
visible_message("[M] bursts out of [src]!")
- if(!isSynthetic())
+ if(!ismachineperson(src))
flick("gibbed-h", animation)
hgibs(loc, dna)
else
@@ -106,18 +105,10 @@
//Handle species-specific deaths.
dna.species.handle_death(gibbed, src)
- if(ishuman(LAssailant))
- var/mob/living/carbon/human/H=LAssailant
- if(H.mind)
- H.mind.kills += "[key_name(src)]"
-
if(SSticker && SSticker.mode)
// log_world("k")
sql_report_death(src)
- if(wearing_rig)
- wearing_rig.notify_ai("Warning: user death event. Mobility control passed to integrated intelligence system.")
-
/mob/living/carbon/human/update_revive()
. = ..()
if(. && healthdoll)
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index a34f02bc868..b69c13987b9 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -34,7 +34,7 @@
//Cooldown-inducing emotes
if("ping", "pings", "buzz", "buzzes", "beep", "beeps", "yes", "no", "buzz2")
var/found_machine_head = FALSE
- if(ismachine(src)) //Only Machines can beep, ping, and buzz, yes, no, and make a silly sad trombone noise.
+ if(ismachineperson(src)) //Only Machines can beep, ping, and buzz, yes, no, and make a silly sad trombone noise.
on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm
found_machine_head = TRUE
else
@@ -139,10 +139,18 @@
//WHO THE FUCK THOUGHT THAT WAS A GOOD FUCKING IDEA!?!?
if("howl", "howls")
- var/M = handle_emote_param(param) //Check to see if the param is valid (mob with the param name is in view).
- message = "[src] howls[M ? " at [M]" : ""]!"
- playsound(loc, 'sound/goonstation/voice/howl.ogg', 100, 1, 10, frequency = get_age_pitch())
- m_type = 2
+ var/M = handle_emote_param(param)
+ if(miming)
+ message = "[src] acts out a howl[M ? " at [M]" : ""]!"
+ m_type = 1
+ else
+ if(!muzzled)
+ message = "[src] howls[M ? " at [M]" : ""]!"
+ playsound(loc, 'sound/goonstation/voice/howl.ogg', 100, 1, 10, frequency = get_age_pitch())
+ m_type = 2
+ else
+ message = "[src] makes a very loud noise[M ? " at [M]" : ""]."
+ m_type = 2
if("growl", "growls")
var/M = handle_emote_param(param)
@@ -300,14 +308,14 @@
m_type = 1
if("bow", "bows")
- if(!buckled)
+ if(!restrained())
var/M = handle_emote_param(param)
message = "[src] bows[M ? " to [M]" : ""]."
m_type = 1
if("salute", "salutes")
- if(!buckled)
+ if(!restrained())
var/M = handle_emote_param(param)
message = "[src] salutes[M ? " to [M]" : ""]."
@@ -939,7 +947,7 @@
if("Skrell")
emotelist += "\nSkrell specific emotes :- warble(s)"
- if(ismachine(src))
+ if(ismachineperson(src))
emotelist += "\nMachine specific emotes :- beep(s)-(none)/mob, buzz(es)-none/mob, no-(none)/mob, ping(s)-(none)/mob, yes-(none)/mob, buzz2-(none)/mob"
else
var/obj/item/organ/external/head/H = get_organ("head") // If you have a robotic head, you can make beep-boop noises
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index b67e01924c8..60891563ad2 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -208,7 +208,7 @@
if(!E)
wound_flavor_text["[organ_tag]"] = "[p_they(TRUE)] [p_are()] missing [p_their()] [organ_descriptor].\n"
else
- if(!isSynthetic())
+ if(!ismachineperson(src))
if(E.is_robotic())
wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a robotic [E.name]!\n"
@@ -252,7 +252,7 @@
var/temp = getBruteLoss() //no need to calculate each of these twice
if(temp)
- var/brute_message = !isSynthetic() ? "bruising" : "denting"
+ var/brute_message = !ismachineperson(src) ? "bruising" : "denting"
if(temp < 30)
msg += "[p_they(TRUE)] [p_have()] minor [brute_message ].\n"
else
@@ -301,13 +301,13 @@
else if(nutrition >= NUTRITION_LEVEL_FAT)
msg += "[p_they(TRUE)] [p_are()] quite chubby.\n"
- if(!isSynthetic() && blood_volume < BLOOD_VOLUME_SAFE)
+ if(!ismachineperson(src) && blood_volume < BLOOD_VOLUME_SAFE)
msg += "[p_they(TRUE)] [p_have()] pale skin.\n"
if(bleedsuppress)
msg += "[p_they(TRUE)] [p_are()] bandaged with something.\n"
else if(bleed_rate)
- var/bleed_message = !isSynthetic() ? "bleeding" : "leaking"
+ var/bleed_message = !ismachineperson(src) ? "bleeding" : "leaking"
msg += "[p_they(TRUE)] [p_are()] [bleed_message]!\n"
if(reagents.has_reagent("teslium"))
@@ -341,7 +341,7 @@
if(decaylevel == 3)
msg += "[p_they(TRUE)] [p_are()] rotting and blackened, the skin sloughing off. The smell is indescribably foul.\n"
if(decaylevel == 4)
- msg += "[p_they(TRUE)] [p_are()] mostly dessicated now, with only bones remaining of what used to be a person.\n"
+ msg += "[p_they(TRUE)] [p_are()] mostly desiccated now, with only bones remaining of what used to be a person.\n"
if(hasHUD(user,"security"))
var/perpname = get_visible_name(TRUE)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 828dc25322c..e07930f1241 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -5,7 +5,6 @@
icon = 'icons/mob/human.dmi'
icon_state = "body_m_s"
deathgasp_on_death = TRUE
- var/obj/item/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call.
/mob/living/carbon/human/New(loc)
icon = null // This is now handled by overlays -- we just keep an icon for the sake of the map editor.
@@ -18,7 +17,7 @@
dna = new /datum/dna(null)
// Species name is handled by set_species()
- ..()
+ . = ..()
set_species(new_species, 1, delay_icon_update = 1, skip_same_check = TRUE)
@@ -41,6 +40,7 @@
sync_organ_dna(1)
UpdateAppearance()
+ GLOB.human_list += src
/mob/living/carbon/human/OpenCraftingMenu()
handcrafting.ui_interact(src)
@@ -60,61 +60,62 @@
SSmobs.cubemonkeys -= src
QDEL_LIST(bodyparts)
splinted_limbs.Cut()
+ GLOB.human_list -= src
/mob/living/carbon/human/dummy
real_name = "Test Dummy"
status_flags = GODMODE|CANPUSH
/mob/living/carbon/human/skrell/Initialize(mapload)
- ..(mapload, /datum/species/skrell)
+ . = ..(mapload, /datum/species/skrell)
/mob/living/carbon/human/tajaran/Initialize(mapload)
- ..(mapload, /datum/species/tajaran)
+ . = ..(mapload, /datum/species/tajaran)
/mob/living/carbon/human/vulpkanin/Initialize(mapload)
- ..(mapload, /datum/species/vulpkanin)
+ . = ..(mapload, /datum/species/vulpkanin)
/mob/living/carbon/human/unathi/Initialize(mapload)
- ..(mapload, /datum/species/unathi)
+ . = ..(mapload, /datum/species/unathi)
/mob/living/carbon/human/vox/Initialize(mapload)
- ..(mapload, /datum/species/vox)
+ . = ..(mapload, /datum/species/vox)
/mob/living/carbon/human/voxarmalis/Initialize(mapload)
- ..(mapload, /datum/species/vox/armalis)
+ . = ..(mapload, /datum/species/vox/armalis)
/mob/living/carbon/human/skeleton/Initialize(mapload)
- ..(mapload, /datum/species/skeleton)
+ . = ..(mapload, /datum/species/skeleton)
/mob/living/carbon/human/kidan/Initialize(mapload)
- ..(mapload, /datum/species/kidan)
+ . = ..(mapload, /datum/species/kidan)
/mob/living/carbon/human/plasma/Initialize(mapload)
- ..(mapload, /datum/species/plasmaman)
+ . = ..(mapload, /datum/species/plasmaman)
/mob/living/carbon/human/slime/Initialize(mapload)
- ..(mapload, /datum/species/slime)
+ . = ..(mapload, /datum/species/slime)
/mob/living/carbon/human/grey/Initialize(mapload)
- ..(mapload, /datum/species/grey)
+ . = ..(mapload, /datum/species/grey)
/mob/living/carbon/human/abductor/Initialize(mapload)
- ..(mapload, /datum/species/abductor)
+ . = ..(mapload, /datum/species/abductor)
/mob/living/carbon/human/diona/Initialize(mapload)
- ..(mapload, /datum/species/diona)
+ . = ..(mapload, /datum/species/diona)
/mob/living/carbon/human/pod_diona/Initialize(mapload)
- ..(mapload, /datum/species/diona/pod)
+ . = ..(mapload, /datum/species/diona/pod)
/mob/living/carbon/human/machine/Initialize(mapload)
- ..(mapload, /datum/species/machine)
+ . = ..(mapload, /datum/species/machine)
/mob/living/carbon/human/machine/created
name = "Integrated Robotic Chassis"
/mob/living/carbon/human/machine/created/Initialize(mapload)
- ..()
+ . = ..()
rename_character(null, "Integrated Robotic Chassis ([rand(1, 9999)])")
update_dna()
for(var/obj/item/organ/external/E in bodyparts)
@@ -127,34 +128,34 @@
death()
/mob/living/carbon/human/shadow/Initialize(mapload)
- ..(mapload, /datum/species/shadow)
+ . = ..(mapload, /datum/species/shadow)
/mob/living/carbon/human/golem/Initialize(mapload)
- ..(mapload, /datum/species/golem)
+ . = ..(mapload, /datum/species/golem)
/mob/living/carbon/human/wryn/Initialize(mapload)
- ..(mapload, /datum/species/wryn)
+ . = ..(mapload, /datum/species/wryn)
/mob/living/carbon/human/nucleation/Initialize(mapload)
- ..(mapload, /datum/species/nucleation)
+ . = ..(mapload, /datum/species/nucleation)
/mob/living/carbon/human/drask/Initialize(mapload)
- ..(mapload, /datum/species/drask)
+ . = ..(mapload, /datum/species/drask)
/mob/living/carbon/human/monkey/Initialize(mapload)
- ..(mapload, /datum/species/monkey)
+ . = ..(mapload, /datum/species/monkey)
/mob/living/carbon/human/farwa/Initialize(mapload)
- ..(mapload, /datum/species/monkey/tajaran)
+ . = ..(mapload, /datum/species/monkey/tajaran)
/mob/living/carbon/human/wolpin/Initialize(mapload)
- ..(mapload, /datum/species/monkey/vulpkanin)
+ . = ..(mapload, /datum/species/monkey/vulpkanin)
/mob/living/carbon/human/neara/Initialize(mapload)
- ..(mapload, /datum/species/monkey/skrell)
+ . = ..(mapload, /datum/species/monkey/skrell)
/mob/living/carbon/human/stok/Initialize(mapload)
- ..(mapload, /datum/species/monkey/unathi)
+ . = ..(mapload, /datum/species/monkey/unathi)
/mob/living/carbon/human/Stat()
..()
@@ -180,13 +181,6 @@
stat("Tank Pressure", internal.air_contents.return_pressure())
stat("Distribution Pressure", internal.distribute_pressure)
- if(istype(back, /obj/item/rig))
- var/obj/item/rig/suit = back
- var/cell_status = "ERROR"
- if(suit.cell)
- cell_status = "[suit.cell.charge]/[suit.cell.maxcharge]"
- stat(null, "Suit charge: [cell_status]")
-
// I REALLY need to split up status panel things into datums
var/mob/living/simple_animal/borer/B = has_brain_worms()
if(B && B.controlling)
@@ -961,16 +955,6 @@
var/obj/item/clothing/mask/MT = src.wear_mask
tinted += MT.tint
- //god help me
- if(istype(back, /obj/item/rig))
- var/obj/item/rig/O = back
- if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & HEAD))
- if((O.offline && O.offline_vision_restriction == 1) || (!O.offline && O.vision_restriction == 1))
- tinted = 2
- if((O.offline && O.offline_vision_restriction == 2) || (!O.offline && O.vision_restriction == 2))
- tinted = 3
- //im so sorry
-
return tinted
@@ -1160,18 +1144,6 @@
custom_pain("You feel a stabbing pain in your chest!")
L.damage = L.min_bruised_damage
-//returns 1 if made bloody, returns 0 otherwise
-
-/mob/living/carbon/human/clean_blood(var/clean_feet)
- .=..()
- if(clean_feet && !shoes && istype(feet_blood_DNA, /list) && feet_blood_DNA.len)
- feet_blood_color = null
- qdel(feet_blood_DNA)
- bloody_feet = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_NOT_BLOODY = 0)
- blood_state = BLOOD_STATE_NOT_BLOODY
- update_inv_shoes()
- return 1
-
/mob/living/carbon/human/cuff_resist(obj/item/I)
if(HULK in mutations)
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
@@ -1699,14 +1671,14 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
/mob/living/carbon/human/forceFed(var/obj/item/reagent_containers/food/toEat, mob/user, fullness)
if(!check_has_mouth())
- if(!((istype(toEat, /obj/item/reagent_containers/food/drinks) && (ismachine(src)))))
+ if(!((istype(toEat, /obj/item/reagent_containers/food/drinks) && (ismachineperson(src)))))
to_chat(user, "Where do you intend to put \the [toEat]? \The [src] doesn't have a mouth!")
return 0
return ..()
/mob/living/carbon/human/selfDrink(var/obj/item/reagent_containers/food/drinks/toDrink)
if(!check_has_mouth())
- if(!ismachine(src))
+ if(!ismachineperson(src))
to_chat(src, "Where do you intend to put \the [src]? You don't have a mouth!")
return 0
else
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index 89aa7854264..621d8330761 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -30,7 +30,7 @@
if(dna.species && amount > 0)
if(use_brain_mod)
amount = amount * dna.species.brain_mod
- sponge.damage = Clamp(sponge.damage + amount, 0, 120)
+ sponge.damage = clamp(sponge.damage + amount, 0, 120)
if(sponge.damage >= 120)
visible_message("[src] goes limp, [p_their()] facial expression utterly blank.")
death()
@@ -48,7 +48,7 @@
if(dna.species && amount > 0)
if(use_brain_mod)
amount = amount * dna.species.brain_mod
- sponge.damage = Clamp(amount, 0, 120)
+ sponge.damage = clamp(amount, 0, 120)
if(sponge.damage >= 120)
visible_message("[src] goes limp, [p_their()] facial expression utterly blank.")
death()
@@ -129,13 +129,6 @@
O.heal_damage(0, -amount, internal = 0, robo_repair = O.is_robotic(), updating_health = updating_health)
return STATUS_UPDATE_HEALTH
-
-/mob/living/carbon/human/Paralyse(amount)
- // Notify our AI if they can now control the suit.
- if(wearing_rig && !stat && paralysis < amount) //We are passing out right this second.
- wearing_rig.notify_ai("Warning: user consciousness failure. Mobility control passed to integrated intelligence system.")
- return ..()
-
/mob/living/carbon/human/adjustCloneLoss(amount)
if(dna.species && amount > 0)
amount = amount * dna.species.clone_mod
@@ -342,7 +335,5 @@ This function restores all organs.
..(damage, damagetype, def_zone, blocked)
return 1
- //Handle BRUTE and BURN damage
- handle_suit_punctures(damagetype, damage)
//Handle species apply_damage procs
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, sharp, used_weapon)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 82b61a04391..6141ad02f9f 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -84,7 +84,7 @@ emp_act
E.heal_damage(rembrute,0,0,1)
rembrute = nrembrute
user.visible_message("[user] patches some dents on [src]'s [E.name] with [I].")
- if(bleed_rate && isSynthetic())
+ if(bleed_rate && ismachineperson(src))
bleed_rate = 0
user.visible_message("[user] patches some leaks on [src] with [I].")
if(IgniteMob())
@@ -134,7 +134,7 @@ emp_act
if(bp && istype(bp ,/obj/item/clothing))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & def_zone.body_part)
- protection += C.armor[type]
+ protection += C.armor.getRating(type)
return protection
@@ -185,19 +185,19 @@ emp_act
var/block_chance_modifier = round(damage / -3)
if(l_hand && !istype(l_hand, /obj/item/clothing))
- var/final_block_chance = l_hand.block_chance - (Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
+ var/final_block_chance = l_hand.block_chance - (clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(l_hand.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(r_hand && !istype(r_hand, /obj/item/clothing))
- var/final_block_chance = r_hand.block_chance - (Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts
+ var/final_block_chance = r_hand.block_chance - (clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts
if(r_hand.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(wear_suit)
- var/final_block_chance = wear_suit.block_chance - (Clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
+ var/final_block_chance = wear_suit.block_chance - (clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
if(wear_suit.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(w_uniform)
- var/final_block_chance = w_uniform.block_chance - (Clamp((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
+ var/final_block_chance = w_uniform.block_chance - (clamp((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
if(w_uniform.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
return 0
@@ -387,11 +387,6 @@ emp_act
to_chat(user, "You hack off a chunk of meat from [name]")
if(!meatleft)
add_attack_logs(user, src, "Chopped up into meat")
- if(!iscarbon(user))
- LAssailant = null
- else
- LAssailant = user
-
qdel(src)
var/obj/item/organ/external/affecting = get_organ(ran_zone(user.zone_selected))
@@ -536,17 +531,6 @@ emp_act
w_uniform.add_mob_blood(source)
update_inv_w_uniform()
-/mob/living/carbon/human/proc/handle_suit_punctures(var/damtype, var/damage)
-
- if(!wear_suit) return
- if(!istype(wear_suit,/obj/item/clothing/suit/space)) return
- if(damtype != BURN && damtype != BRUTE) return
-
- var/obj/item/clothing/suit/space/SS = wear_suit
- var/penetrated_dam = max(0,(damage - max(0,(SS.breach_threshold - SS.damage))))
-
- if(penetrated_dam) SS.create_breaches(damtype, penetrated_dam)
-
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
if(HAS_TRAIT(user, TRAIT_PACIFISM))
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index 60b6da987dd..3d365afa940 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -37,7 +37,6 @@ GLOBAL_DATUM_INIT(default_martial_art, /datum/martial_art, new())
var/obj/item/s_store = null
var/icon/stand_icon = null
- var/icon/lying_icon = null
var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life()
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 85bf001a206..7cb33bce249 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -16,12 +16,6 @@
else if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit))
var/obj/item/clothing/suit/space/hardsuit/C = wear_suit
thrust = C.jetpack
- else if(istype(back,/obj/item/rig))
- var/obj/item/rig/rig = back
- for(var/obj/item/rig_module/maneuvering_jets/module in rig.installed_modules)
- thrust = module.jets
- break
-
if(thrust)
if((movement_dir || thrust.stabilizers) && thrust.allow_thrust(0.01, src))
return 1
@@ -81,7 +75,7 @@
/mob/living/carbon/human/handle_footstep(turf/T)
if(..())
- if(T.footstep_sounds["human"])
+ if(T.footstep_sounds && T.footstep_sounds["human"])
var/S = pick(T.footstep_sounds["human"])
if(S)
if(m_intent == MOVE_INTENT_RUN)
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index c74340d0901..15dfe74880e 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -197,7 +197,7 @@
if(!(RADIMMUNE in dna.species.species_traits))
if(radiation)
- radiation = Clamp(radiation, 0, 200)
+ radiation = clamp(radiation, 0, 200)
var/autopsy_damage = 0
switch(radiation)
@@ -302,14 +302,6 @@
if(!(head && head.flags & AIRTIGHT)) //if NOT (head AND head.flags CONTAIN AIRTIGHT)
null_internals = 1 //not wearing a mask or suitable helmet
- if(istype(back, /obj/item/rig)) //wearing a rigsuit
- var/obj/item/rig/rig = back //needs to be typecasted because this doesn't use get_rig() for some reason
- if(rig.offline && (rig.air_supply && internal == rig.air_supply)) //if rig IS offline AND (rig HAS air_supply AND internal IS air_supply)
- null_internals = 1 //offline suits do not breath
-
- else if(rig.air_supply && internal == rig.air_supply) //if rig HAS air_supply AND internal IS rig air_supply
- skip_contents_check = 1 //skip contents.Find() check, the oxygen is valid even being outside of the mob
-
if(!contents.Find(internal) && (!skip_contents_check)) //if internal NOT IN contents AND skip_contents_check IS false
null_internals = 1 //not a rigsuit and your oxygen is gone
@@ -635,7 +627,7 @@
else
overeatduration -= 2
- if(!ismachine(src) && nutrition < NUTRITION_LEVEL_HYPOGLYCEMIA) //Gosh damn snowflakey IPCs
+ if(!ismachineperson(src) && nutrition < NUTRITION_LEVEL_HYPOGLYCEMIA) //Gosh damn snowflakey IPCs
var/datum/disease/D = new /datum/disease/critical/hypoglycemia
ForceContractDisease(D)
@@ -697,7 +689,7 @@
alcohol_strength /= sober_str
var/obj/item/organ/internal/liver/L
- if(!isSynthetic())
+ if(!ismachineperson(src))
L = get_int_organ(/obj/item/organ/internal/liver)
if(L)
alcohol_strength *= L.alcohol_intensity
@@ -719,7 +711,7 @@
AdjustConfused(3 / sober_str)
if(alcohol_strength >= blur_start) //blurry eyes
EyeBlurry(10 / sober_str)
- if(!isSynthetic()) //stuff only for non-synthetics
+ if(!ismachineperson(src)) //stuff only for non-synthetics
if(alcohol_strength >= vomit_start) //vomiting
if(prob(8))
fakevomit()
diff --git a/code/modules/mob/living/carbon/human/npcs.dm b/code/modules/mob/living/carbon/human/npcs.dm
index 41c108dadb9..9dcf83f2e9a 100644
--- a/code/modules/mob/living/carbon/human/npcs.dm
+++ b/code/modules/mob/living/carbon/human/npcs.dm
@@ -7,7 +7,7 @@
species_exception = list(/datum/species/monkey)
/mob/living/carbon/human/monkey/punpun/Initialize(mapload)
- ..()
+ . = ..()
name = "Pun Pun"
real_name = name
equip_to_slot(new /obj/item/clothing/under/punpun(src), slot_w_uniform)
diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm
index 98edb60c6bf..957b0828725 100644
--- a/code/modules/mob/living/carbon/human/say.dm
+++ b/code/modules/mob/living/carbon/human/say.dm
@@ -62,11 +62,6 @@
return ..()
/mob/living/carbon/human/proc/HasVoiceChanger()
- if(istype(back, /obj/item/rig))
- var/obj/item/rig/rig = back
- if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.voice)
- return rig.speech.voice_holder.voice
-
for(var/obj/item/gear in list(wear_mask, wear_suit, head))
if(!gear)
continue
@@ -134,11 +129,9 @@
S.message = "[S.message]"
verb = translator.speech_verb
return list("verb" = verb)
- if(mind)
- span = mind.speech_span
if((COMIC in mutations) \
|| (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) \
- || GetComponent(/datum/component/jestosterone))
+ || HAS_TRAIT(src, TRAIT_JESTER))
span = "sans"
if(WINGDINGS in mutations)
diff --git a/code/modules/mob/living/carbon/human/species/_species.dm b/code/modules/mob/living/carbon/human/species/_species.dm
index 21695e25e78..a8e1eee5f52 100644
--- a/code/modules/mob/living/carbon/human/species/_species.dm
+++ b/code/modules/mob/living/carbon/human/species/_species.dm
@@ -53,7 +53,6 @@
var/stun_mod = 1 // If a species is more/less impacated by stuns/weakens/paralysis
var/speed_mod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
var/blood_damage_type = OXY //What type of damage does this species take if it's low on blood?
- var/obj/item/mutanthands
var/total_health = 100
var/punchdamagelow = 0 //lowest possible punch damage
var/punchdamagehigh = 9 //highest possible punch damage
@@ -346,30 +345,17 @@
switch(damagetype)
if(BRUTE)
- H.damageoverlaytemp = 20
damage = damage * brute_mod
+ if(damage)
+ H.damageoverlaytemp = 20
if(organ.receive_damage(damage, 0, sharp, used_weapon))
H.UpdateDamageIcon()
- if(H.LAssailant && ishuman(H.LAssailant)) //superheros still get the comical hit markers
- var/mob/living/carbon/human/A = H.LAssailant
- if(A.mind && (A.mind in (SSticker.mode.superheroes) || SSticker.mode.supervillains || SSticker.mode.greyshirts))
- var/list/attack_bubble_recipients = list()
- var/mob/living/user
- for(var/mob/O in viewers(user, src))
- if(O.client && O.has_vision(information_only=TRUE))
- attack_bubble_recipients.Add(O.client)
- spawn(0)
- var/image/dmgIcon = image('icons/effects/hit_blips.dmi', src, "dmg[rand(1,2)]",MOB_LAYER+1)
- dmgIcon.pixel_x = (!H.lying) ? rand(-3,3) : rand(-11,12)
- dmgIcon.pixel_y = (!H.lying) ? rand(-11,9) : rand(-10,1)
- flick_overlay(dmgIcon, attack_bubble_recipients, 9)
-
-
if(BURN)
- H.damageoverlaytemp = 20
damage = damage * burn_mod
+ if(damage)
+ H.damageoverlaytemp = 20
if(organ.receive_damage(0, damage, sharp, used_weapon))
H.UpdateDamageIcon()
@@ -443,6 +429,9 @@
else
target.LAssailant = user
+ target.lastattacker = user.real_name
+ target.lastattackerckey = user.ckey
+
var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh)
damage += attack.damage
if(!damage)
@@ -530,9 +519,6 @@
/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art) //Handles any species-specific attackhand events.
if(!istype(M))
return
- if(H.frozen)
- to_chat(M, "Do not touch Admin-Frozen people.")
- return
if(istype(M))
var/obj/item/organ/external/temp = M.bodyparts_by_name["r_hand"]
@@ -828,20 +814,6 @@ It'll return null if the organ doesn't correspond, so include null checks when u
if(!isnull(hat.lighting_alpha))
H.lighting_alpha = min(hat.lighting_alpha, H.lighting_alpha)
- if(istype(H.back, /obj/item/rig)) ///aghhh so snowflakey
- var/obj/item/rig/rig = H.back
- if(rig.visor)
- if(!rig.helmet || (H.head && rig.helmet == H.head))
- if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses)
- var/obj/item/clothing/glasses/G = rig.visor.vision.glasses
- if(istype(G))
- H.sight |= G.vision_flags
- H.see_in_dark = max(G.see_in_dark, H.see_in_dark)
- H.see_invisible = min(G.invis_view, H.see_invisible)
-
- if(!isnull(G.lighting_alpha))
- H.lighting_alpha = min(G.lighting_alpha, H.lighting_alpha)
-
if(H.vision_type)
H.sight |= H.vision_type.sight_flags
H.see_in_dark = max(H.see_in_dark, H.vision_type.see_in_dark)
diff --git a/code/modules/mob/living/carbon/human/species/golem.dm b/code/modules/mob/living/carbon/human/species/golem.dm
index 9f4a27a3c41..7ff32e38644 100644
--- a/code/modules/mob/living/carbon/human/species/golem.dm
+++ b/code/modules/mob/living/carbon/human/species/golem.dm
@@ -636,12 +636,11 @@
H.mutations.Add(COMIC)
H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/bikehorn(H), slot_l_store)
- H.AddComponent(/datum/component/waddling)
+ H.AddElement(/datum/element/waddling)
/datum/species/golem/bananium/on_species_loss(mob/living/carbon/C)
. = ..()
- GET_COMPONENT_FROM(waddling, /datum/component/waddling, C)
- waddling.Destroy()
+ C.RemoveElement(/datum/element/waddling)
/datum/species/golem/bananium/get_random_name()
var/clown_name = pick(GLOB.clown_names)
diff --git a/code/modules/mob/living/carbon/human/species/shadow.dm b/code/modules/mob/living/carbon/human/species/shadow.dm
index 63f062b8bc8..be2a7f44229 100644
--- a/code/modules/mob/living/carbon/human/species/shadow.dm
+++ b/code/modules/mob/living/carbon/human/species/shadow.dm
@@ -39,10 +39,10 @@
/datum/action/innate/shadow/darkvision/Activate()
var/mob/living/carbon/human/H = owner
if(!H.vision_type)
- H.vision_type = new /datum/vision_override/nightvision
+ H.set_sight(/datum/vision_override/nightvision)
to_chat(H, "You adjust your vision to pierce the darkness.")
else
- H.vision_type = null
+ H.set_sight(null)
to_chat(H, "You adjust your vision to recognize the shadows.")
/datum/species/shadow/on_species_gain(mob/living/carbon/human/H)
diff --git a/code/modules/mob/living/carbon/human/species/zombies.dm b/code/modules/mob/living/carbon/human/species/zombies.dm
deleted file mode 100644
index 1f1c4d979b7..00000000000
--- a/code/modules/mob/living/carbon/human/species/zombies.dm
+++ /dev/null
@@ -1,102 +0,0 @@
-#define REGENERATION_DELAY 60 // After taking damage, how long it takes for automatic regeneration to begin
-
-/datum/species/zombie
- // 1spooky
- name = "High-Functioning Zombie"
- name_plural = "High-Functioning Zombies"
- icobase = 'icons/mob/human_races/r_zombie.dmi'
- deform = 'icons/mob/human_races/r_def_zombie.dmi'
- dies_at_threshold = TRUE
- language = "Zombie"
- species_traits = list(NO_BLOOD, NOZOMBIE, NOTRANSSTING, NO_BREATHE, RADIMMUNE, NO_SCAN)
- var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
- warning_low_pressure = -1
- hazard_low_pressure = -1
- hazard_high_pressure = 999999999
- warning_high_pressure = 999999999
- cold_level_1 = -1
- cold_level_2 = -1
- cold_level_3 = -1
- tox_mod = 0
- flesh_color = "#00FF00" // for green examine text
- bodyflags = HAS_SKIN_COLOR
- dietflags = DIET_CARN
- has_organ = list(
- "heart" = /obj/item/organ/internal/heart,
- "lungs" = /obj/item/organ/internal/lungs,
- "liver" = /obj/item/organ/internal/liver,
- "kidneys" = /obj/item/organ/internal/kidneys,
- "brain" = /obj/item/organ/internal/brain,
- "appendix" = /obj/item/organ/internal/appendix,
- "eyes" = /obj/item/organ/internal/eyes,
- "ears" = /obj/item/organ/internal/ears)
-
-
-/datum/species/zombie/infectious
- name = "Infectious Zombie"
- mutanthands = /obj/item/zombie_hand
- icobase = 'icons/mob/human_races/r_zombie.dmi'
- deform = 'icons/mob/human_races/r_def_zombie.dmi'
- brute_mod = 0.8 // 120 damage to KO a zombie, which kills it
- burn_mod = 0.8
- clone_mod = 0.8
- brain_mod = 0.8
- stamina_mod = 0.8
- speed_mod = 1.6
- default_language = "Zombie"
- var/heal_rate = 1
- var/regen_cooldown = 0
-
-/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H, amount)
- . = min(20, amount)
-
-/datum/species/zombie/infectious/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, sharp = 0, obj/used_weapon = null)
- . = ..()
- if(damage)
- regen_cooldown = world.time + REGENERATION_DELAY
-
-/datum/species/zombie/infectious/handle_life(mob/living/carbon/human/H)
- . = ..()
- H.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW
-
- //Zombies never actually die, they just fall down until they regenerate enough to rise back up.
- //They must be restrained, beheaded or gibbed to stop being a threat.
- if(regen_cooldown < world.time)
- var/heal_amt = heal_rate
- if(H.InCritical())
- heal_amt *= 2
- H.heal_overall_damage(heal_amt,heal_amt)
- H.adjustToxLoss(-heal_amt)
- if(!H.InCritical() && prob(4))
- playsound(H, pick(spooks), 50, TRUE, 10)
-
-//Congrats you somehow died so hard you stopped being a zombie
-/datum/species/zombie/infectious/handle_death(gibbed, mob/living/carbon/C)
- . = ..()
- var/obj/item/organ/internal/zombie_infection/infection
- infection = C.get_organ_slot("zombie_infection")
- if(infection)
- qdel(infection)
-
-/datum/species/zombie/infectious/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
- . = ..()
- // Deal with the source of this zombie corruption
- // Infection organ needs to be handled separately from mutant_organs
- // because it persists through species transitions
- if(mutanthands)
- H.drop_l_hand()
- H.drop_r_hand()
- H.put_in_hands(new mutanthands())
- H.put_in_hands(new mutanthands())
- var/obj/item/organ/internal/zombie_infection/infection
- infection = H.get_organ_slot("zombie_infection")
- if(!infection)
- infection = new()
- infection.insert(H)
-
-/datum/species/zombie/infectious/on_species_loss(mob/living/carbon/human/C, datum/species/old_species)
- QDEL_NULL(C.r_hand)
- QDEL_NULL(C.l_hand)
- return ..()
-
-#undef REGENERATION_DELAY
diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm
index 2cce48d51c2..f5496652dad 100644
--- a/code/modules/mob/living/carbon/human/update_icons.dm
+++ b/code/modules/mob/living/carbon/human/update_icons.dm
@@ -273,10 +273,10 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[UNDERWEAR_LAYER] = mutable_appearance(underwear_standing, layer = -UNDERWEAR_LAYER)
apply_overlay(UNDERWEAR_LAYER)
- if(lip_style && (LIPS in dna.species.species_traits))
- var/icon/lips = icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "lips_[lip_style]_s")
- lips.Blend(lip_color, ICON_ADD)
- standing += mutable_appearance(lips, layer = -BODY_LAYER)
+ if(lip_style && (LIPS in dna.species.species_traits))
+ var/mutable_appearance/lips = mutable_appearance('icons/mob/human_face.dmi', "lips_[lip_style]_s")
+ lips.color = lip_color
+ standing += lips
overlays_standing[BODY_LAYER] = standing
apply_overlay(BODY_LAYER)
@@ -376,7 +376,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
//base icons
var/icon/hair_standing = new /icon('icons/mob/human_face.dmi',"bald_s")
- if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic())))
+ if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(ismachineperson(src))))
var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style]
if(hair_style && hair_style.species_allowed)
if((head_organ.dna.species.name in hair_style.species_allowed) || (head_organ.dna.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics...
@@ -964,10 +964,6 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
var/mutable_appearance/standing
if(back.icon_override)
standing = mutable_appearance(back.icon_override, "[back.icon_state]", layer = -BACK_LAYER)
- else if(istype(back, /obj/item/rig))
- //If this is a rig and a mob_icon is set, it will take species into account in the rig update_icon() proc.
- var/obj/item/rig/rig = back
- standing = rig.mob_icon
else if(back.sprite_sheets && back.sprite_sheets[dna.species.name])
standing = mutable_appearance(back.sprite_sheets[dna.species.name], "[back.icon_state]", layer = -BACK_LAYER)
else
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 66e2e60f144..c11eaca5293 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -11,6 +11,10 @@
if(stat != DEAD)
handle_organs()
+ //stuff in the stomach
+ if(LAZYLEN(stomach_contents))
+ handle_stomach(times_fired)
+
. = ..()
if(QDELETED(src))
@@ -122,7 +126,7 @@
var/O2_partialpressure = (breath.oxygen/breath.total_moles())*breath_pressure
var/Toxins_partialpressure = (breath.toxins/breath.total_moles())*breath_pressure
var/CO2_partialpressure = (breath.carbon_dioxide/breath.total_moles())*breath_pressure
-
+ var/SA_partialpressure = (breath.sleeping_agent/breath.total_moles())*breath_pressure
//OXYGEN
if(O2_partialpressure < safe_oxy_min) //Not enough oxygen
@@ -162,22 +166,20 @@
//TOXINS/PLASMA
if(Toxins_partialpressure > safe_tox_max)
var/ratio = (breath.toxins/safe_tox_max) * 10
- adjustToxLoss(Clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
+ adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
else
clear_alert("too_much_tox")
//TRACE GASES
- if(breath.trace_gases.len)
- for(var/datum/gas/sleeping_agent/SA in breath.trace_gases)
- var/SA_partialpressure = (SA.moles/breath.total_moles())*breath_pressure
- if(SA_partialpressure > SA_para_min)
- Paralyse(3)
- if(SA_partialpressure > SA_sleep_min)
- AdjustSleeping(2, bound_lower = 0, bound_upper = 10)
- else if(SA_partialpressure > 0.01)
- if(prob(20))
- emote(pick("giggle","laugh"))
+ if(breath.sleeping_agent)
+ if(SA_partialpressure > SA_para_min)
+ Paralyse(3)
+ if(SA_partialpressure > SA_sleep_min)
+ AdjustSleeping(2, bound_lower = 0, bound_upper = 10)
+ else if(SA_partialpressure > 0.01)
+ if(prob(20))
+ emote(pick("giggle","laugh"))
//BREATH TEMPERATURE
handle_breath_temperature(breath)
@@ -245,7 +247,7 @@
adjustToxLoss(3)
updatehealth("handle mutations and radiation(75-100)")
- radiation = Clamp(radiation, 0, 100)
+ radiation = clamp(radiation, 0, 100)
/mob/living/carbon/handle_chemicals_in_body()
@@ -256,14 +258,15 @@
if(times_fired % 20==2) //dry off a bit once every 20 ticks or so
wetlevel = max(wetlevel - 1,0)
-/mob/living/carbon/handle_stomach(times_fired)
- for(var/mob/living/M in stomach_contents)
+/mob/living/carbon/proc/handle_stomach(times_fired)
+ for(var/thing in stomach_contents)
+ var/mob/living/M = thing
if(M.loc != src)
- stomach_contents.Remove(M)
+ LAZYREMOVE(stomach_contents, M)
continue
if(stat != DEAD)
if(M.stat == DEAD)
- stomach_contents.Remove(M)
+ LAZYREMOVE(stomach_contents, M)
qdel(M)
continue
if(times_fired % 3 == 1)
@@ -478,7 +481,7 @@
P.reagents.remove_any(applied_amount * 0.5)
else
if(!P.reagents || P.reagents.total_volume <= 0)
- processing_patches -= P
+ LAZYREMOVE(processing_patches, P)
qdel(P)
/mob/living/carbon/proc/handle_germs()
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index 6d020ccdad1..3062ef461f9 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -58,9 +58,6 @@
handle_fire()
- //stuff in the stomach
- handle_stomach(times_fired)
-
update_gravity(mob_has_gravity())
if(pulling)
@@ -117,9 +114,6 @@
/mob/living/proc/handle_environment(datum/gas_mixture/environment)
return
-/mob/living/proc/handle_stomach(times_fired)
- return
-
/mob/living/proc/update_pulling()
if(incapacitated())
stop_pulling()
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 3cdd6c37180..c05aae7e664 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -80,8 +80,9 @@
//Even if we don't push/swap places, we "touched" them, so spread fire
spreadFire(M)
- if(now_pushing)
- return 1
+ // No pushing if we're already pushing past something, or if the mob we're pushing into is anchored.
+ if(now_pushing || M.anchored)
+ return TRUE
//Should stop you pushing a restrained person out of the way
if(isliving(M))
@@ -89,7 +90,7 @@
if(L.pulledby && L.pulledby != src && L.restrained())
if(!(world.time % 5))
to_chat(src, "[L] is restrained, you cannot push past.")
- return 1
+ return TRUE
if(L.pulling)
if(ismob(L.pulling))
@@ -97,28 +98,28 @@
if(P.restrained())
if(!(world.time % 5))
to_chat(src, "[L] is restrained, you cannot push past.")
- return 1
+ return TRUE
if(moving_diagonally) //no mob swap during diagonal moves.
- return 1
+ return TRUE
if(a_intent == INTENT_HELP) // Help intent doesn't mob swap a mob pulling a structure
if(isstructure(M.pulling) || isstructure(pulling))
- return 1
+ return TRUE
if(!M.buckled && !M.has_buckled_mobs())
var/mob_swap
//the puller can always swap with it's victim if on grab intent
if(M.pulledby == src && a_intent == INTENT_GRAB)
- mob_swap = 1
+ mob_swap = TRUE
//restrained people act if they were on 'help' intent to prevent a person being pulled from being seperated from their puller
else if((M.restrained() || M.a_intent == INTENT_HELP) && (restrained() || a_intent == INTENT_HELP))
- mob_swap = 1
+ mob_swap = TRUE
if(mob_swap)
//switch our position with M
if(loc && !loc.Adjacent(M.loc))
- return 1
- now_pushing = 1
+ return TRUE
+ now_pushing = TRUE
var/oldloc = loc
var/oldMloc = M.loc
@@ -135,18 +136,18 @@
if(!M_passmob)
M.pass_flags &= ~PASSMOB
- now_pushing = 0
- return 1
+ now_pushing = FALSE
+ return TRUE
// okay, so we didn't switch. but should we push?
// not if he's not CANPUSH of course
if(!(M.status_flags & CANPUSH))
- return 1
+ return TRUE
//anti-riot equipment is also anti-push
if(M.r_hand && (prob(M.r_hand.block_chance * 2)) && !istype(M.r_hand, /obj/item/clothing))
- return 1
+ return TRUE
if(M.l_hand && (prob(M.l_hand.block_chance * 2)) && !istype(M.l_hand, /obj/item/clothing))
- return 1
+ return TRUE
//Called when we bump into an obj
/mob/living/proc/ObjBump(obj/O)
@@ -196,13 +197,6 @@
AM.setDir(current_dir)
now_pushing = FALSE
-/mob/living/Stat()
- . = ..()
- if(. && get_rig_stats)
- var/obj/item/rig/rig = get_rig()
- if(rig)
- SetupStat(rig)
-
/mob/living/proc/can_track(mob/living/user)
//basic fast checks go first. When overriding this proc, I recommend calling ..() at the end.
var/turf/T = get_turf(src)
@@ -703,9 +697,6 @@
*/////////////////////
/mob/living/proc/resist_grab()
var/resisting = 0
- for(var/obj/O in requests)
- qdel(O)
- resisting++
for(var/X in grabbed_by)
var/obj/item/grab/G = X
resisting++
@@ -761,7 +752,8 @@
clear_alert("weightless")
else
throw_alert("weightless", /obj/screen/alert/weightless)
- float(!has_gravity)
+ if(!flying)
+ float(!has_gravity)
/mob/living/proc/float(on)
if(throwing)
@@ -846,8 +838,7 @@
spawn_dust()
gib()
-/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
- end_pixel_y = get_standard_pixel_y_offset(lying)
+/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!used_item)
used_item = get_active_hand()
..()
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 33b10e37deb..4da8aa97e06 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -79,9 +79,9 @@
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
if(throwforce && w_class)
- return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
+ return clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
- return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
+ return clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
@@ -113,7 +113,7 @@
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor, is_sharp(I), I)
if(I.thrownby)
- add_attack_logs(I.thrownby, src, "Hit with thrown [I]")
+ add_attack_logs(I.thrownby, src, "Hit with thrown [I]", !I.throwforce ? ATKLOG_ALMOSTALL : null) // Only message if the person gets damages
else
return 1
else
@@ -175,7 +175,7 @@
return
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
- fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20)
+ fire_stacks = clamp(fire_stacks + add_fire_stacks, -20, 20)
if(on_fire && fire_stacks <= 0)
ExtinguishMob()
@@ -260,8 +260,6 @@
add_attack_logs(user, src, "Grabbed passively", ATKLOG_ALL)
var/obj/item/grab/G = new /obj/item/grab(user, src)
- if(buckled)
- to_chat(user, "You cannot grab [src]; [p_they()] [p_are()] buckled in!")
if(!G) //the grab will delete itself in New if src is anchored
return 0
user.put_in_active_hand(G)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index c272952b6bf..d4546f4f6bc 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -61,7 +61,7 @@ proc/get_radio_key_from_channel(var/channel)
return default_language
/mob/living/proc/handle_speech_problems(list/message_pieces, var/verb)
- var/robot = isSynthetic()
+ var/robot = ismachineperson(src)
for(var/datum/multilingual_say_piece/S in message_pieces)
if(S.speaking && S.speaking.flags & NO_STUTTER)
continue
@@ -269,12 +269,12 @@ proc/get_radio_key_from_channel(var/channel)
M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol, sound_frequency)
if(M.client)
speech_bubble_recipients.Add(M.client)
- spawn(0)
- if(loc && !isturf(loc))
- var/atom/A = loc //Non-turf, let it handle the speech bubble
- A.speech_bubble("hR[speech_bubble_test]", A, speech_bubble_recipients)
- else //Turf, leave speech bubbles to the mob
- speech_bubble("h[speech_bubble_test]", src, speech_bubble_recipients)
+
+ if(loc && !isturf(loc))
+ var/atom/A = loc //Non-turf, let it handle the speech bubble
+ A.speech_bubble("[A.bubble_icon][speech_bubble_test]", A, speech_bubble_recipients)
+ else //Turf, leave speech bubbles to the mob
+ speech_bubble("[bubble_icon][speech_bubble_test]", src, speech_bubble_recipients)
for(var/obj/O in listening_obj)
spawn(0)
@@ -336,7 +336,8 @@ proc/get_radio_key_from_channel(var/channel)
var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting
S.speaking.broadcast(src, S.message)
return 1
-
+ // Log it here since it skips the default way say handles it
+ create_log(SAY_LOG, "(whisper) '[message]'")
whisper_say(message_pieces)
// for weird circumstances where you're inside an atom that is also you, like pai's
@@ -450,21 +451,18 @@ proc/get_radio_key_from_channel(var/channel)
var/speech_bubble_test = say_test(message)
for(var/mob/M in listening)
- M.hear_say(message_pieces, verb, italics, src)
+ M.hear_say(message_pieces, verb, italics, src, use_voice = FALSE)
if(M.client)
speech_bubble_recipients.Add(M.client)
if(eavesdropping.len)
stars_all(message_pieces) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less.
for(var/mob/M in eavesdropping)
- M.hear_say(message_pieces, verb, italics, src)
+ M.hear_say(message_pieces, verb, italics, src, use_voice = FALSE)
if(M.client)
speech_bubble_recipients.Add(M.client)
- spawn(0)
- var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER + 1)
- I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
- flick_overlay(I, speech_bubble_recipients, 30)
+ speech_bubble("[bubble_icon][speech_bubble_test]", src, speech_bubble_recipients)
if(watching.len)
var/rendered = "[name] [not_heard]."
@@ -473,7 +471,7 @@ proc/get_radio_key_from_channel(var/channel)
return 1
-/mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
- var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, MOB_LAYER + 1)
+/mob/living/speech_bubble(bubble_state = "", bubble_loc = src, list/bubble_recipients = list())
+ var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, FLY_LAYER)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
- flick_overlay(I, bubble_recipients, 30)
+ INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, bubble_recipients, 30)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 85c4ceac427..7f6ed094dce 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -63,6 +63,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
//MALFUNCTION
var/datum/module_picker/malf_picker
+ var/datum/action/innate/ai/choose_modules/modules_action
var/list/datum/AI_Module/current_modules = list()
var/can_dominate_mechs = 0
var/shunted = 0 //1 if the AI is currently shunted. Used to differentiate between shunted and ghosted/braindead
@@ -243,7 +244,8 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
/mob/living/silicon/ai/proc/show_borg_info()
stat(null, text("Connected cyborgs: [connected_robots.len]"))
- for(var/mob/living/silicon/robot/R in connected_robots)
+ for(var/thing in connected_robots)
+ var/mob/living/silicon/robot/R = thing
var/robot_status = "Nominal"
if(R.stat || !R.client)
robot_status = "OFFLINE"
@@ -251,8 +253,9 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
robot_status = "DEPOWERED"
// Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
var/area/A = get_area(R)
+ var/area_name = A ? sanitize(A.name) : "Unknown"
stat(null, text("[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge] / [R.cell.maxcharge]" : "Empty"] | \
- Module: [R.designation] | Loc: [sanitize(A.name)] | Status: [robot_status]"))
+ Module: [R.designation] | Loc: [area_name] | Status: [robot_status]"))
/mob/living/silicon/ai/rename_character(oldname, newname)
if(!..(oldname, newname))
@@ -849,13 +852,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
to_chat(src, "Switched to [network] camera network.")
//End of code by Mord_Sith
-
-/mob/living/silicon/ai/proc/choose_modules()
- set category = "Malfunction"
- set name = "Choose Module"
-
- malf_picker.use(src)
-
/mob/living/silicon/ai/proc/ai_statuschange()
set category = "AI Commands"
set name = "AI Status"
@@ -1026,15 +1022,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
return
-/mob/living/silicon/ai/proc/corereturn()
- set category = "Malfunction"
- set name = "Return to Main Core"
-
- var/obj/machinery/power/apc/apc = loc
- if(!istype(apc))
- to_chat(src, "You are already in your Main Core.")
- return
- apc.malfvacate()
//Toggles the luminosity and applies it by re-entereing the camera.
/mob/living/silicon/ai/proc/toggle_camera_light()
@@ -1179,16 +1166,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
/mob/living/silicon/ai/can_buckle()
return FALSE
-// Pass lying down or getting up to our pet human, if we're in a rig.
-/mob/living/silicon/ai/lay_down()
- set name = "Rest"
- set category = "IC"
-
- resting = 0
- var/obj/item/rig/rig = get_rig()
- if(rig)
- rig.force_rest(src)
-
/mob/living/silicon/ai/switch_to_camera(obj/machinery/camera/C)
if(!C.can_use() || !is_in_chassis())
return FALSE
@@ -1242,8 +1219,17 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
to_chat(src, "In the top right corner of the screen you will find the Malfunctions tab, where you can purchase various abilities, from upgraded surveillance to station ending doomsday devices.")
to_chat(src, "You are also capable of hacking APCs, which grants you more points to spend on your Malfunction powers. The drawback is that a hacked APC will give you away if spotted by the crew. Hacking an APC takes 60 seconds.")
view_core() //A BYOND bug requires you to be viewing your core before your verbs update
- verbs += /mob/living/silicon/ai/proc/choose_modules
malf_picker = new /datum/module_picker
+ modules_action = new(malf_picker)
+ modules_action.Grant(src)
+
+///Removes all malfunction-related /datum/action's from the target AI.
+/mob/living/silicon/ai/proc/remove_malf_abilities()
+ QDEL_NULL(modules_action)
+ for(var/datum/AI_Module/AM in current_modules)
+ for(var/datum/action/A in actions)
+ if(istype(A, initial(AM.power_type)))
+ qdel(A)
/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target)
if(!istype(target))
diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm
index 641b1a2af0f..717f9700316 100644
--- a/code/modules/mob/living/silicon/ai/death.dm
+++ b/code/modules/mob/living/silicon/ai/death.dm
@@ -34,7 +34,7 @@
spawn(10)
explosion(src.loc, 3, 6, 12, 15)
- for(var/obj/machinery/ai_status_display/O in world) //change status
+ for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 2
if(istype(loc, /obj/item/aicard))
diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm
index 4b124c364c2..03e56a5e26e 100644
--- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm
@@ -67,9 +67,6 @@
// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists.
/datum/camerachunk/proc/update()
-
- set background = BACKGROUND_ENABLED
-
var/list/newVisibleTurfs = list()
for(var/camera in cameras)
diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm
index d23fedb09bc..faacf9ba359 100644
--- a/code/modules/mob/living/silicon/ai/freelook/eye.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm
@@ -142,7 +142,7 @@
acceleration = !acceleration
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
-/mob/camera/aiEye/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency)
+/mob/camera/aiEye/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
if(relay_speech)
if(istype(ai))
ai.relay_speech(speaker, message_pieces, verb)
diff --git a/code/modules/mob/living/silicon/ai/latejoin.dm b/code/modules/mob/living/silicon/ai/latejoin.dm
index 75e8854b45c..e1be5450811 100644
--- a/code/modules/mob/living/silicon/ai/latejoin.dm
+++ b/code/modules/mob/living/silicon/ai/latejoin.dm
@@ -1,15 +1,5 @@
GLOBAL_LIST_EMPTY(empty_playable_ai_cores)
-/hook/roundstart/proc/spawn_empty_ai()
- for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
- if(S.name != "AI")
- continue
- if(locate(/mob/living) in S.loc)
- continue
- GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(get_turf(S))
-
- return 1
-
/mob/living/silicon/ai/verb/wipe_core()
set name = "Wipe Core"
set category = "OOC"
diff --git a/code/modules/mob/living/silicon/ai/logout.dm b/code/modules/mob/living/silicon/ai/logout.dm
index a8060abd15c..d9dac308870 100644
--- a/code/modules/mob/living/silicon/ai/logout.dm
+++ b/code/modules/mob/living/silicon/ai/logout.dm
@@ -1,6 +1,6 @@
/mob/living/silicon/ai/Logout()
..()
- for(var/obj/machinery/ai_status_display/O in world) //change status
+ for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 0
src.view_core()
return
diff --git a/code/modules/mob/living/silicon/decoy/death.dm b/code/modules/mob/living/silicon/decoy/death.dm
index 9e58001f47b..74db72978e0 100644
--- a/code/modules/mob/living/silicon/decoy/death.dm
+++ b/code/modules/mob/living/silicon/decoy/death.dm
@@ -4,7 +4,7 @@
if(!.)
return FALSE
icon_state = "ai-crash"
- for(var/obj/machinery/ai_status_display/O in world) //change status
+ for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
if(atoms_share_level(O, src))
O.mode = 2
gib()
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 6677c77f310..db95f18c210 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -435,9 +435,6 @@
// Pass lying down or getting up to our pet human, if we're in a rig.
if(stat == CONSCIOUS && istype(loc,/obj/item/paicard))
resting = 0
- var/obj/item/rig/rig = get_rig()
- if(istype(rig))
- rig.force_rest(src)
else
resting = !resting
to_chat(src, "You are now [resting ? "resting" : "getting up"]")
diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm
index f52da9942e4..920dff8a8c2 100644
--- a/code/modules/mob/living/silicon/pai/recruit.dm
+++ b/code/modules/mob/living/silicon/pai/recruit.dm
@@ -1,6 +1,6 @@
// Recruiting observers to play as pAIs
-GLOBAL_DATUM(paiController, /datum/paiController) // Global handler for pAI candidates
+GLOBAL_DATUM_INIT(paiController, /datum/paiController, new) // Global handler for pAI candidates
/datum/paiCandidate
var/name
@@ -10,12 +10,6 @@ GLOBAL_DATUM(paiController, /datum/paiController) // Global handler for pAI cand
var/comments
var/ready = 0
-
-/hook/startup/proc/paiControllerSetup()
- GLOB.paiController = new /datum/paiController()
- return 1
-
-
/datum/paiController
var/list/pai_candidates = list()
var/list/asked = list()
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index 3b51048452e..574dcda3230 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -13,19 +13,6 @@ GLOBAL_LIST_INIT(pai_emotions, list(
GLOBAL_LIST_EMPTY(pai_software_by_key)
GLOBAL_LIST_EMPTY(default_pai_software)
-/hook/startup/proc/populate_pai_software_list()
- var/r = 1 // I would use ., but it'd sacrifice runtime detection
- for(var/type in subtypesof(/datum/pai_software))
- var/datum/pai_software/P = new type()
- if(GLOB.pai_software_by_key[P.id])
- var/datum/pai_software/O = GLOB.pai_software_by_key[P.id]
- to_chat(world, "pAI software module [P.name] has the same key as [O.name]!")
- r = 0
- continue
- GLOB.pai_software_by_key[P.id] = P
- if(P.default)
- GLOB.default_pai_software[P.id] = P
- return r
/mob/living/silicon/pai/New()
..()
diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm
index 26b5683d1a3..2a1662b064d 100644
--- a/code/modules/mob/living/silicon/robot/component.dm
+++ b/code/modules/mob/living/silicon/robot/component.dm
@@ -227,7 +227,7 @@
throw_speed = 5
throw_range = 10
origin_tech = "magnets=1;biotech=1"
- var/mode = 1;
+ var/mode = 1
/obj/item/robotanalyzer/attack(mob/living/M as mob, mob/living/user as mob)
if(( (CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50))
@@ -253,7 +253,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
to_chat(user, "You can't analyze non-robotic things!")
return
-
+
switch(scan_type)
if("robot")
var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss()
@@ -269,7 +269,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
to_chat(user, "Localized Damage:")
if(!LAZYLEN(damaged) && !LAZYLEN(missing))
to_chat(user, "\t Components are OK.")
- else
+ else
if(LAZYLEN(damaged))
for(var/datum/robot_component/org in damaged)
user.show_message(text("\t []: [][] - [] - [] - []", \
@@ -282,7 +282,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
if(LAZYLEN(missing))
for(var/datum/robot_component/org in missing)
user.show_message("\t [capitalize(org.name)]: MISSING")
-
+
if(H.emagged && prob(5))
to_chat(user, "\t ERROR: INTERNAL SYSTEMS COMPROMISED")
@@ -313,7 +313,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
if(!organ_found)
to_chat(user, "No prosthetics located.")
- if(H.isSynthetic())
+ if(ismachineperson(H))
to_chat(user, "Internal Fluid Level:[H.blood_volume]/[H.max_blood]")
if(H.bleed_rate)
to_chat(user, "Warning:External component leak detected!")
diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm
index 1d856245c28..5cc6e50fd06 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone.dm
@@ -6,6 +6,7 @@
icon_state = "repairbot"
maxHealth = 35
health = 35
+ bubble_icon = "machine"
universal_speak = 0
universal_understand = 1
gender = NEUTER
@@ -13,6 +14,7 @@
braintype = "Robot"
lawupdate = 0
density = 0
+ has_camera = FALSE
req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
ventcrawler = 2
magpulse = 1
@@ -34,6 +36,14 @@
var/reboot_cooldown = 60 // one minute
var/last_reboot
var/emagged_time
+ var/list/pullable_drone_items = list(
+ /obj/item/pipe,
+ /obj/structure/disposalconstruct,
+ /obj/item/stack/cable_coil,
+ /obj/item/stack/rods,
+ /obj/item/stack/sheet,
+ /obj/item/stack/tile
+ )
holder_type = /obj/item/holder/drone
// var/sprite[0]
@@ -68,6 +78,10 @@
verbs -= /mob/living/silicon/robot/verb/Namepick
module = new /obj/item/robot_module/drone(src)
+ //Allows Drones to hear the Engineering channel.
+ module.channels = list("Engineering" = 1)
+ radio.recalculateChannels()
+
//Grab stacks.
stack_metal = locate(/obj/item/stack/sheet/metal/cyborg) in src.module
stack_wood = locate(/obj/item/stack/sheet/wood) in src.module
@@ -82,7 +96,7 @@
scanner.Grant(src)
update_icons()
-/mob/living/silicon/robot/drone/init()
+/mob/living/silicon/robot/drone/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/drone()
connected_ai = null
@@ -145,7 +159,7 @@
user.visible_message("\the [user] swipes [user.p_their()] ID card through [src], attempting to reboot it.", "You swipe your ID card through [src], attempting to reboot it.")
last_reboot = world.time / 10
var/drones = 0
- for(var/mob/living/silicon/robot/drone/D in world)
+ for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
if(D.key && D.client)
drones++
if(drones < config.max_maint_drones)
@@ -153,15 +167,17 @@
return
else
- user.visible_message("\the [user] swipes [user.p_their()] ID card through [src], attempting to shut it down.", "You swipe your ID card through \the [src], attempting to shut it down.")
+ var/confirm = alert("Using your ID on a Maintenance Drone will shut it down, are you sure you want to do this?", "Disable Drone", "Yes", "No")
+ if(confirm == ("Yes") && (user in range(3, src)))
+ user.visible_message("\the [user] swipes [user.p_their()] ID card through [src], attempting to shut it down.", "You swipe your ID card through \the [src], attempting to shut it down.")
- if(emagged)
- return
+ if(emagged)
+ return
- if(allowed(W))
- shut_down()
- else
- to_chat(user, "Access denied.")
+ if(allowed(W))
+ shut_down()
+ else
+ to_chat(user, "Access denied.")
return
@@ -322,8 +338,9 @@
/mob/living/silicon/robot/drone/start_pulling(atom/movable/AM, state, force = pull_force, show_message = FALSE)
- if(istype(AM,/obj/item/pipe) || istype(AM,/obj/structure/disposalconstruct))
+ if(is_type_in_list(AM, pullable_drone_items))
..(AM, force = INFINITY) // Drone power! Makes them able to drag pipes and such
+
else if(istype(AM,/obj/item))
var/obj/item/O = AM
if(O.w_class > WEIGHT_CLASS_SMALL)
@@ -354,3 +371,20 @@
/mob/living/simple_animal/drone/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
if(affect_silicon)
return ..()
+
+/mob/living/silicon/robot/drone/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(!client && istype(user, /mob/living/silicon/robot/drone))
+ to_chat(user, "You begin decompiling the other drone.")
+ if(!do_after(user, 5 SECONDS, target = loc))
+ to_chat(user, "You need to remain still while decompiling such a large object.")
+ return
+ if(QDELETED(src) || QDELETED(user))
+ return ..()
+ to_chat(user, "You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.")
+ new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
+ C.stored_comms["metal"] += 15
+ C.stored_comms["glass"] += 15
+ C.stored_comms["wood"] += 5
+ qdel(src)
+ return TRUE
+ return ..()
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_console.dm b/code/modules/mob/living/silicon/robot/drone/drone_console.dm
index 80d9f4d1ba3..d961d8e1c62 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_console.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_console.dm
@@ -34,7 +34,7 @@
var/dat
dat += "Maintenance Units "
- for(var/mob/living/silicon/robot/drone/D in world)
+ for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
dat += " [D.real_name] ([D.stat == 2 ? "INACTIVE" : "ACTIVE"])"
dat += " Cell charge: [D.cell.charge]/[D.cell.maxcharge]."
dat += " Currently located in: [get_area(D)]."
@@ -74,7 +74,7 @@
else if(href_list["ping"])
to_chat(usr, "You issue a maintenance request for all active drones, highlighting [drone_call_area].")
- for(var/mob/living/silicon/robot/drone/D in world)
+ for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
if(D.client && D.stat == 0)
to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].")
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
index 7958f983805..16e81f53276 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm
@@ -8,7 +8,6 @@
//Has a list of items that it can hold.
var/list/can_hold = list(
- /obj/item/stock_parts/cell,
/obj/item/firealarm_electronics,
/obj/item/airalarm_electronics,
/obj/item/airlock_electronics,
@@ -24,6 +23,8 @@
/obj/item/mounted/frame/firealarm,
/obj/item/mounted/frame/newscaster_frame,
/obj/item/mounted/frame/intercom,
+ /obj/item/mounted/frame/extinguisher,
+ /obj/item/mounted/frame/light_switch,
/obj/item/rack_parts,
/obj/item/camera_assembly,
/obj/item/tank,
@@ -64,7 +65,7 @@
..()
can_hold = typecacheof(can_hold)
-/obj/item/gripper/verb/drop_item()
+/obj/item/gripper/verb/drop_item_gripped()
set name = "Drop Gripped Item"
set desc = "Release an item from your magnetic gripper."
set category = "Drone"
@@ -151,15 +152,13 @@
var/list/stored_comms = list(
"metal" = 0,
"glass" = 0,
- "wood" = 0,
- "plastic" = 0
+ "wood" = 0
)
/obj/item/matter_decompiler/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
return
-/obj/item/matter_decompiler/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
-
+/obj/item/matter_decompiler/afterattack(atom/target, mob/living/user, proximity, params)
if(!proximity) return //Not adjacent.
//We only want to deal with using this on turfs. Specific items aren't important.
@@ -168,101 +167,11 @@
return
//Used to give the right message.
- var/grabbed_something = 0
+ var/grabbed_something = FALSE
- for(var/mob/M in T)
- if(istype(M,/mob/living/simple_animal/lizard) || istype(M,/mob/living/simple_animal/mouse))
- src.loc.visible_message("[src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.","It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.")
- new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
- qdel(M)
- stored_comms["wood"]++
- stored_comms["wood"]++
- stored_comms["plastic"]++
- stored_comms["plastic"]++
- return
-
- else if(istype(M,/mob/living/silicon/robot/drone) && !M.client)
-
- var/mob/living/silicon/robot/drone/D = src.loc
-
- if(!istype(D))
- return
-
- to_chat(D, "You begin decompiling the other drone.")
-
- if(!do_after(D, 50, target = target))
- to_chat(D, "You need to remain still while decompiling such a large object.")
- return
-
- if(!M || !D) return
-
- to_chat(D, "You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.")
-
- qdel(M)
- new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
-
- stored_comms["metal"] += 15
- stored_comms["glass"] += 15
- stored_comms["wood"] += 5
- stored_comms["plastic"] += 5
-
- return
- else
- continue
-
- for(var/obj/W in T)
- //Different classes of items give different commodities.
- if(istype(W,/obj/item/cigbutt))
- stored_comms["plastic"]++
- else if(istype(W,/obj/structure/spider/spiderling))
- stored_comms["wood"]++
- stored_comms["wood"]++
- stored_comms["plastic"]++
- stored_comms["plastic"]++
- else if(istype(W,/obj/item/light))
- var/obj/item/light/L = W
- if(L.status >= 2) //In before someone changes the inexplicably local defines. ~ Z
- stored_comms["metal"]++
- stored_comms["glass"]++
- else
- continue
- else if(istype(W,/obj/effect/decal/remains/robot))
- stored_comms["metal"]++
- stored_comms["metal"]++
- stored_comms["plastic"]++
- stored_comms["plastic"]++
- stored_comms["glass"]++
- else if(istype(W,/obj/item/trash))
- stored_comms["metal"]++
- stored_comms["plastic"]++
- stored_comms["plastic"]++
- else if(istype(W,/obj/effect/decal/cleanable/blood/gibs/robot))
- stored_comms["metal"]++
- stored_comms["metal"]++
- stored_comms["glass"]++
- stored_comms["glass"]++
- else if(istype(W,/obj/item/ammo_casing))
- stored_comms["metal"]++
- else if(istype(W,/obj/item/shard))
- stored_comms["glass"]++
- stored_comms["glass"]++
- stored_comms["glass"]++
- else if(istype(W,/obj/item/reagent_containers/food/snacks/grown))
- stored_comms["wood"]++
- stored_comms["wood"]++
- stored_comms["wood"]++
- stored_comms["wood"]++
- else if(istype(W,/obj/item/broken_bottle))
- stored_comms["glass"]++
- stored_comms["glass"]++
- stored_comms["glass"]++
- else if(istype(W,/obj/item/light/tube) || istype(W,/obj/item/light/bulb))
- stored_comms["glass"]++
- else
- continue
-
- qdel(W)
- grabbed_something = 1
+ for(var/atom/movable/A in T)
+ if(A.decompile_act(src, user)) // Each decompileable mob or obj needs to have this defined
+ grabbed_something = TRUE
if(grabbed_something)
to_chat(user, "You deploy your decompiler and clear out the contents of \the [T].")
@@ -353,11 +262,5 @@
stack_wood = new /obj/item/stack/sheet/wood(src.module)
stack_wood.amount = 1
stack = stack_wood
- if("plastic")
- if(!stack_plastic)
- stack_plastic = new /obj/item/stack/sheet/plastic(src.module)
- stack_plastic.amount = 1
- stack = stack_plastic
-
stack.amount++
decompiler.stored_comms[type]--
diff --git a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
index 50463b17bec..023cced9cdb 100644
--- a/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
+++ b/code/modules/mob/living/silicon/robot/drone/drone_manufacturer.dm
@@ -52,7 +52,7 @@
/obj/machinery/drone_fabricator/proc/count_drones()
var/drones = 0
- for(var/mob/living/silicon/robot/drone/D in world)
+ for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
if(D.key && D.client)
drones++
return drones
@@ -142,7 +142,7 @@
if(alert("Are you sure you want to respawn as a drone?", "Are you sure?", "Yes", "No") != "Yes")
return
- for(var/obj/machinery/drone_fabricator/DF in world)
+ for(var/obj/machinery/drone_fabricator/DF in GLOB.machines)
if(DF.stat & NOPOWER || !DF.produce_drones)
continue
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index afdab2f5649..07080e694bf 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -36,7 +36,7 @@
if(is_component_functioning("power cell") && cell.charge)
if(cell.charge <= 100)
uneq_all()
- var/amt = Clamp((lamp_intensity - 2) * 2,1,cell.charge) //Always try to use at least one charge per tick, but allow it to completely drain the cell.
+ var/amt = clamp((lamp_intensity - 2) * 2,1,cell.charge) //Always try to use at least one charge per tick, but allow it to completely drain the cell.
cell.use(amt) //Usage table: 1/tick if off/lowest setting, 4 = 4/tick, 6 = 8/tick, 8 = 12/tick, 10 = 16/tick
else
uneq_all()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 2eb1e4669ab..7f1a18ac22d 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -9,6 +9,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
icon_state = "robot"
maxHealth = 100
health = 100
+ bubble_icon = "robot"
universal_understand = 1
deathgasp_on_death = TRUE
@@ -16,8 +17,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/custom_name = ""
var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best
-//Hud stuff
-
+ //Hud stuff
var/obj/screen/inv1 = null
var/obj/screen/inv2 = null
var/obj/screen/inv3 = null
@@ -27,7 +27,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not
var/obj/screen/robot_modules_background
-//3 Modules can be activated at any one time.
+ //3 Modules can be activated at any one time.
var/obj/item/robot_module/module = null
var/module_active = null
var/module_state_1 = null
@@ -57,6 +57,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/is_emaggable = TRUE
var/eye_protection = 0
var/ear_protection = 0
+ var/damage_protection = 0
+ var/emp_protection = FALSE
+ var/xeno_disarm_chance = 85
var/list/force_modules = list()
var/allow_rename = TRUE
@@ -82,11 +85,11 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/lockcharge //Used when locking down a borg to preserve cell charge
var/speed = 0 //Cause sec borgs gotta go fast //No they dont!
var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them.
+ var/has_camera = TRUE
var/pdahide = 0 //Used to hide the borg from the messenger list
var/tracking_entities = 0 //The number of known entities currently accessing the internal camera
var/braintype = "Cyborg"
var/base_icon = ""
- var/crisis = 0
var/modules_break = TRUE
var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting.
@@ -97,6 +100,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD)
+ var/default_cell_type = /obj/item/stock_parts/cell/high
var/magpulse = 0
var/ionpulse = 0 // Jetpack-like effect.
var/ionpulse_on = 0 // Jetpack-like effect.
@@ -108,7 +112,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
/mob/living/silicon/robot/get_cell()
return cell
-/mob/living/silicon/robot/New(loc,var/syndie = 0,var/unfinished = 0, var/alien = 0)
+/mob/living/silicon/robot/New(loc, syndie = FALSE, unfinished = FALSE, alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
@@ -130,9 +134,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
radio = new /obj/item/radio/borg(src)
common_radio = radio
- init()
+ init(ai_to_sync_to = ai_to_sync_to)
- if(!scrambledcodes && !camera)
+ if(has_camera && !camera)
camera = new /obj/machinery/camera(src)
camera.c_tag = real_name
camera.network = list("SS13","Robots")
@@ -144,7 +148,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
mmi.icon_state = "boris"
if(!cell) // Make sure a new cell gets created *before* executing initialize_components(). The cell component needs an existing cell for it to get set up properly
- cell = new /obj/item/stock_parts/cell/high(src)
+ cell = new default_cell_type(src)
initialize_components()
//if(!unfinished)
@@ -168,14 +172,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
scanner = new(src)
scanner.Grant(src)
-/mob/living/silicon/robot/proc/init(var/alien=0)
+/mob/living/silicon/robot/proc/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
make_laws()
additional_law_channels["Binary"] = ":b "
- var/new_ai = select_active_ai_with_fewest_borgs()
- if(new_ai)
+ var/found_ai = ai_to_sync_to
+ if(!found_ai)
+ found_ai = select_active_ai_with_fewest_borgs()
+ if(found_ai)
lawupdate = 1
- connect_to_ai(new_ai)
+ connect_to_ai(found_ai)
else
lawupdate = 0
@@ -235,7 +241,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(custom_name)
return 0
if(!allow_rename)
- to_chat(src, "Rename functionality is not enabled on this unit.");
+ to_chat(src, "Rename functionality is not enabled on this unit.")
return 0
rename_self(braintype, 1)
@@ -288,12 +294,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
/mob/living/silicon/robot/proc/pick_module()
if(module)
return
- var/list/modules = list("Standard", "Engineering", "Medical", "Miner", "Janitor", "Service", "Security")
+ var/list/modules = list("Generalist", "Engineering", "Medical", "Miner", "Janitor", "Service", "Security")
if(islist(force_modules) && force_modules.len)
modules = force_modules.Copy()
- if(GLOB.security_level == (SEC_LEVEL_GAMMA || SEC_LEVEL_EPSILON) || crisis)
- to_chat(src, "Crisis mode active. The combat module is now available.")
- modules += "Combat"
if(mmi != null && mmi.alien)
modules = list("Hunter")
modtype = input("Please, select a module!", "Robot", null, null) as null|anything in modules
@@ -306,9 +309,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return
switch(modtype)
- if("Standard")
+ if("Generalist")
module = new /obj/item/robot_module/standard(src)
- module.channels = list("Service" = 1)
+ module.channels = list("Engineering" = 1, "Medical" = 1, "Security" = 1, "Service" = 1)
module_sprites["Basic"] = "robot_old"
module_sprites["Android"] = "droid"
module_sprites["Default"] = "Standard"
@@ -337,6 +340,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
module_sprites["Standard"] = "Standard-Mine"
module_sprites["Noble-DIG"] = "Noble-DIG"
module_sprites["Cricket"] = "Cricket-MINE"
+ module_sprites["Lavaland"] = "lavaland"
if("Medical")
module = new /obj/item/robot_module/medical(src)
@@ -353,6 +357,17 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
status_flags &= ~CANPUSH
if("Security")
+ if(!weapons_unlock)
+ var/count_secborgs = 0
+ for(var/mob/living/silicon/robot/R in GLOB.alive_mob_list)
+ if(R && R.stat != DEAD && R.module && istype(R.module, /obj/item/robot_module/security))
+ count_secborgs++
+ var/max_secborgs = 2
+ if(GLOB.security_level == SEC_LEVEL_GREEN)
+ max_secborgs = 1
+ if(count_secborgs >= max_secborgs)
+ to_chat(src, "There are too many Security cyborgs active. Please choose another module.")
+ return
module = new /obj/item/robot_module/security(src)
module.channels = list("Security" = 1)
module_sprites["Basic"] = "secborg"
@@ -387,10 +402,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
module_sprites["Noble-CLN"] = "Noble-CLN"
module_sprites["Cricket"] = "Cricket-JANI"
- if("Combat")
- module = new /obj/item/robot_module/combat(src)
+ if("Destroyer") // Rolling Borg
+ module = new /obj/item/robot_module/destroyer(src)
module.channels = list("Security" = 1)
icon_state = "droidcombat"
+ status_flags &= ~CANPUSH
+
+ if("Combat") // Gamma ERT
+ module = new /obj/item/robot_module/combat(src)
+ icon_state = "ertgamma"
+ status_flags &= ~CANPUSH
if("Hunter")
module = new /obj/item/robot_module/alien/hunter(src)
@@ -442,6 +463,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
ionpulse = FALSE
magpulse = FALSE
add_language("Robot Talk", 1)
+ if("lava" in weather_immunities) // Remove the lava-immunity effect given by a printable upgrade
+ weather_immunities -= "lava"
status_flags |= CANPUSH
@@ -916,7 +939,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return 0
/mob/living/silicon/robot/update_icons()
-
overlays.Cut()
if(stat != DEAD && !(paralysis || stunned || IsWeakened() || low_power_mode)) //Not dead, not stunned.
if(custom_panel in custom_eye_names)
@@ -925,36 +947,24 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
overlays += "eyes-[icon_state]"
else
overlays -= "eyes"
-
if(opened)
var/panelprefix = "ov"
if(custom_sprite) //Custom borgs also have custom panels, heh
panelprefix = "[ckey]"
-
if(custom_panel in custom_panel_names) //For default borgs with different panels
panelprefix = custom_panel
-
if(wiresexposed)
overlays += "[panelprefix]-openpanel +w"
else if(cell)
overlays += "[panelprefix]-openpanel +c"
else
overlays += "[panelprefix]-openpanel -c"
-
- var/combat = list("Combat")
- if(modtype in combat)
- if(base_icon == "")
- base_icon = icon_state
- if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
- icon_state = "[base_icon]-roll"
- else
- icon_state = base_icon
- if(module)
- for(var/obj/item/borg/combat/shield/S in module.modules)
- if(activated(S))
- overlays += "[base_icon]-shield"
+ borg_icons()
update_fire()
+/mob/living/silicon/robot/proc/borg_icons() // Exists so that robot/destroyer can override it
+ return
+
/mob/living/silicon/robot/proc/installed_modules()
if(weapon_lock)
to_chat(src, "Weapon lock active, unable to use modules! Count:[weaponlock_time]")
@@ -1140,7 +1150,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(module)
if(module.type == /obj/item/robot_module/janitor)
var/turf/tile = loc
- if(isturf(tile))
+ if(stat != DEAD && isturf(tile))
var/floor_only = TRUE
for(var/A in tile)
if(istype(A, /obj/effect))
@@ -1309,56 +1319,52 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
..()
update_module_icon()
+/mob/living/silicon/robot/emp_act(severity)
+ if(emp_protection)
+ return
+ ..()
+ switch(severity)
+ if(1)
+ disable_component("comms", 160)
+ if(2)
+ disable_component("comms", 60)
+
/mob/living/silicon/robot/deathsquad
base_icon = "nano_bloodhound"
icon_state = "nano_bloodhound"
designation = "SpecOps"
lawupdate = 0
scrambledcodes = 1
+ has_camera = FALSE
req_one_access = list(ACCESS_CENT_SPECOPS)
ionpulse = 1
magpulse = 1
pdahide = 1
eye_protection = 2 // Immunity to flashes and the visual part of flashbangs
ear_protection = 1 // Immunity to the audio part of flashbangs
+ damage_protection = 10 // Reduce all incoming damage by this number
+ xeno_disarm_chance = 20
allow_rename = FALSE
modtype = "Commando"
faction = list("nanotrasen")
is_emaggable = FALSE
+ default_cell_type = /obj/item/stock_parts/cell/bluespace
-/mob/living/silicon/robot/deathsquad/New(loc)
- ..()
- cell = new /obj/item/stock_parts/cell/hyper(src)
-
-/mob/living/silicon/robot/deathsquad/init()
+/mob/living/silicon/robot/deathsquad/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/deathsquad
module = new /obj/item/robot_module/deathsquad(src)
-
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
radio = new /obj/item/radio/borg/deathsquad(src)
radio.recalculateChannels()
-
playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0)
-/mob/living/silicon/robot/combat
- base_icon = "droidcombat"
- icon_state = "droidcombat"
- modtype = "Combat"
- designation = "Combat"
+/mob/living/silicon/robot/deathsquad/bullet_act(var/obj/item/projectile/P)
+ if(istype(P) && P.is_reflectable && P.starting)
+ visible_message("The [P.name] gets reflected by [src]!", "The [P.name] gets reflected by [src]!")
+ P.reflect_back(src)
+ return -1
+ return ..(P)
-/mob/living/silicon/robot/combat/init()
- ..()
- module = new /obj/item/robot_module/combat(src)
- module.channels = list("Security" = 1)
- //languages
- module.add_languages(src)
- //subsystems
- module.add_subsystems_and_actions(src)
-
- status_flags &= ~CANPUSH
-
- radio.config(module.channels)
- notify_ai(2)
/mob/living/silicon/robot/ert
designation = "ERT"
@@ -1366,24 +1372,24 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
scrambledcodes = 1
req_one_access = list(ACCESS_CENT_SPECOPS)
ionpulse = 1
-
force_modules = list("Engineering", "Medical", "Security")
static_radio_channels = 1
allow_rename = FALSE
weapons_unlock = TRUE
+ default_cell_type = /obj/item/stock_parts/cell/super
+ var/eprefix = "Amber"
-/mob/living/silicon/robot/ert/init()
+/mob/living/silicon/robot/ert/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/ert_override
radio = new /obj/item/radio/borg/ert(src)
radio.recalculateChannels()
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
-/mob/living/silicon/robot/ert/New(loc, cyborg_unlock)
+/mob/living/silicon/robot/ert/New(loc)
..(loc)
- cell = new /obj/item/stock_parts/cell/hyper(src)
var/rnum = rand(1,1000)
- var/borgname = "ERT [rnum]"
+ var/borgname = "[eprefix] ERT [rnum]"
name = borgname
custom_name = borgname
real_name = name
@@ -1392,22 +1398,67 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
mind.original = src
mind.assigned_role = SPECIAL_ROLE_ERT
mind.special_role = SPECIAL_ROLE_ERT
- if(cyborg_unlock)
- crisis = 1
if(!(mind in SSticker.minds))
SSticker.minds += mind
SSticker.mode.ert += mind
-/mob/living/silicon/robot/ert/gamma
- crisis = 1
-/mob/living/silicon/robot/emp_act(severity)
- ..()
- switch(severity)
- if(1)
- disable_component("comms", 160)
- if(2)
- disable_component("comms", 60)
+/mob/living/silicon/robot/ert/red
+ eprefix = "Red"
+ default_cell_type = /obj/item/stock_parts/cell/hyper
+
+/mob/living/silicon/robot/ert/gamma
+ default_cell_type = /obj/item/stock_parts/cell/bluespace
+ force_modules = list("Combat", "Engineering", "Medical")
+ damage_protection = 5 // Reduce all incoming damage by this number
+ eprefix = "Gamma"
+ magpulse = 1
+ xeno_disarm_chance = 40
+
+
+/mob/living/silicon/robot/destroyer
+ // admin-only borg, the seraph / special ops officer of borgs
+ base_icon = "droidcombat"
+ icon_state = "droidcombat"
+ modtype = "Destroyer"
+ designation = "Destroyer"
+ lawupdate = 0
+ scrambledcodes = 1
+ has_camera = FALSE
+ req_one_access = list(ACCESS_CENT_SPECOPS)
+ ionpulse = 1
+ magpulse = 1
+ pdahide = 1
+ eye_protection = 2 // Immunity to flashes and the visual part of flashbangs
+ ear_protection = 1 // Immunity to the audio part of flashbangs
+ emp_protection = TRUE // Immunity to EMP, due to heavy shielding
+ damage_protection = 20 // Reduce all incoming damage by this number. Very high in the case of /destroyer borgs, since it is an admin-only borg.
+ xeno_disarm_chance = 10
+ default_cell_type = /obj/item/stock_parts/cell/bluespace
+
+/mob/living/silicon/robot/destroyer/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
+ aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
+ additional_law_channels["Binary"] = ":b "
+ laws = new /datum/ai_laws/deathsquad
+ module = new /obj/item/robot_module/destroyer(src)
+ module.add_languages(src)
+ module.add_subsystems_and_actions(src)
+ status_flags &= ~CANPUSH
+ if(radio)
+ qdel(radio)
+ radio = new /obj/item/radio/borg/ert/specops(src)
+ radio.recalculateChannels()
+ playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0)
+
+/mob/living/silicon/robot/destroyer/borg_icons()
+ if(base_icon == "")
+ base_icon = icon_state
+ if(module_active && istype(module_active,/obj/item/borg/destroyer/mobility))
+ icon_state = "[base_icon]-roll"
+ else
+ icon_state = base_icon
+ overlays += "[base_icon]-shield"
+
/mob/living/silicon/robot/extinguish_light()
update_headlamp(1, 150)
diff --git a/code/modules/mob/living/silicon/robot/robot_damage.dm b/code/modules/mob/living/silicon/robot/robot_damage.dm
index f4290d764d6..b7b81ed40b7 100644
--- a/code/modules/mob/living/silicon/robot/robot_damage.dm
+++ b/code/modules/mob/living/silicon/robot/robot_damage.dm
@@ -76,29 +76,6 @@
if(!LAZYLEN(components))
return
- //Combat shielding absorbs a percentage of damage directly into the cell.
- var/obj/item/borg/combat/shield/shield
- if(module_state_1 && istype(module_state_1, /obj/item/borg/combat/shield))
- shield = module_state_1
- else if(module_state_2 && istype(module_state_2, /obj/item/borg/combat/shield))
- shield = module_state_2
- else if(module_state_3 && istype(module_state_3, /obj/item/borg/combat/shield))
- shield = module_state_3
- if(shield)
- //Shields absorb a certain percentage of damage based on their power setting.
- var/absorb_brute = brute * shield.shield_level
- var/absorb_burn = burn * shield.shield_level
- var/cost = (absorb_brute+absorb_burn) * 100
-
- cell.charge -= cost
- if(cell.charge <= 0)
- cell.charge = 0
- to_chat(src, "Your shield has overloaded!")
- else
- brute -= absorb_brute
- burn -= absorb_burn
- to_chat(src, "Your shield absorbs some of the impact!")
-
var/datum/robot_component/armour/A = get_armour()
if(A)
A.take_damage(brute, burn, sharp, updating_health)
@@ -127,32 +104,15 @@
updatehealth("heal overall damage")
/mob/living/silicon/robot/take_overall_damage(brute = 0, burn = 0, updating_health = TRUE, used_weapon = null, sharp = 0)
- if(status_flags & GODMODE) return //godmode
+ if(status_flags & GODMODE)
+ return
+
+ if(damage_protection)
+ brute = clamp(brute - damage_protection, 0, brute)
+ burn = clamp(burn - damage_protection, 0, burn)
+
var/list/datum/robot_component/parts = get_damageable_components()
- //Combat shielding absorbs a percentage of damage directly into the cell.
- var/obj/item/borg/combat/shield/shield
- if(module_state_1 && istype(module_state_1, /obj/item/borg/combat/shield))
- shield = module_state_1
- else if(module_state_2 && istype(module_state_2, /obj/item/borg/combat/shield))
- shield = module_state_2
- else if(module_state_3 && istype(module_state_3, /obj/item/borg/combat/shield))
- shield = module_state_3
- if(shield)
- //Shields absorb a certain percentage of damage based on their power setting.
- var/absorb_brute = brute * shield.shield_level
- var/absorb_burn = burn * shield.shield_level
- var/cost = (absorb_brute+absorb_burn) * 100
-
- cell.charge -= cost
- if(cell.charge <= 0)
- cell.charge = 0
- to_chat(src, "Your shield has overloaded!")
- else
- brute -= absorb_brute
- burn -= absorb_burn
- to_chat(src, "Your shield absorbs some of the impact!")
-
var/datum/robot_component/armour/A = get_armour()
if(A)
A.take_damage(brute, burn, sharp)
diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm
index 9b4f1089f46..8445a399582 100644
--- a/code/modules/mob/living/silicon/robot/robot_defense.dm
+++ b/code/modules/mob/living/silicon/robot/robot_defense.dm
@@ -2,7 +2,7 @@
if(M.a_intent == INTENT_DISARM)
if(!lying)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
- if(prob(85))
+ if(prob(xeno_disarm_chance))
Stun(7)
step(src, get_dir(M,src))
spawn(5)
diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm
index 92115986b2e..b1abb49d2ef 100644
--- a/code/modules/mob/living/silicon/robot/robot_items.dm
+++ b/code/modules/mob/living/silicon/robot/robot_items.dm
@@ -73,24 +73,7 @@
/obj/item/borg
var/powerneeded // Percentage of power remaining required to run item
-/obj/item/borg/combat/shield
- name = "personal shielding"
- desc = "A powerful experimental module that turns aside or absorbs incoming attacks at the cost of charge."
- icon = 'icons/obj/decals.dmi'
- icon_state = "shock"
- powerneeded = 25
- var/shield_level = 0.5 //Percentage of damage absorbed by the shield.
-
-/obj/item/borg/combat/shield/verb/set_shield_level()
- set name = "Set shield level"
- set category = "Object"
- set src in range(0)
-
- var/N = input("How much damage should the shield absorb?") in list("5","10","25","50","75","100")
- if(N)
- shield_level = text2num(N)/100
-
-/obj/item/borg/combat/mobility
+/obj/item/borg/destroyer/mobility
name = "mobility module"
desc = "By retracting limbs and tucking in its head, a combat android can roll at high speeds."
icon = 'icons/obj/decals.dmi'
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 3260775c674..8e8c67693c5 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -118,20 +118,48 @@
return
/obj/item/robot_module/standard
- name = "standard robot module"
+ // if station is fine, assist with constructing station goal room, cleaning, and repairing cables chewed by rats
+ // if medical crisis, assist by providing basic healthcare, retrieving corpses, and monitoring crew lifesigns
+ // if eng crisis, assist by helping repair hull breaches
+ // if sec crisis, assist by opening doors for sec and providing backup zipties on patrols
+ name = "generalist robot module"
module_type = "Standard"
+ subsystems = list(/mob/living/silicon/proc/subsystem_power_monitor, /mob/living/silicon/proc/subsystem_crew_monitor)
+ stacktypes = list(
+ /obj/item/stack/sheet/metal/cyborg = 50,
+ /obj/item/stack/cable_coil/cyborg = 50,
+ /obj/item/stack/rods/cyborg = 60,
+ /obj/item/stack/tile/plasteel = 20
+ )
/obj/item/robot_module/standard/New()
..()
- modules += new /obj/item/melee/baton/loaded(src)
- modules += new /obj/item/extinguisher(src)
- modules += new /obj/item/wrench/cyborg(src)
+ // sec
+ modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
+ // janitorial
+ modules += new /obj/item/soap/nanotrasen(src)
+ modules += new /obj/item/lightreplacer/cyborg(src)
+ // eng
modules += new /obj/item/crowbar/cyborg(src)
+ modules += new /obj/item/wrench/cyborg(src)
+ modules += new /obj/item/extinguisher(src) // for firefighting, and propulsion in space
+ modules += new /obj/item/weldingtool/largetank/cyborg(src)
+ // mining
+ modules += new /obj/item/pickaxe(src)
+ modules += new /obj/item/t_scanner/adv_mining_scanner(src)
+ modules += new /obj/item/storage/bag/ore/cyborg(src)
+ // med
modules += new /obj/item/healthanalyzer(src)
+ modules += new /obj/item/reagent_containers/borghypo/basic(src)
+ modules += new /obj/item/roller_holder(src) // for taking the injured to medbay without worsening their injuries or leaving a blood trail the whole way
emag = new /obj/item/melee/energy/sword/cyborg(src)
-
+ for(var/G in stacktypes)
+ var/obj/item/stack/sheet/M = new G(src)
+ M.amount = stacktypes[G]
+ modules += M
fix_modules()
+
/obj/item/robot_module/medical
name = "medical robot module"
module_type = "Medical"
@@ -259,6 +287,7 @@
modules += new /obj/item/mop/advanced/cyborg(src)
modules += new /obj/item/lightreplacer/cyborg(src)
modules += new /obj/item/holosign_creator(src)
+ modules += new /obj/item/extinguisher/mini(src)
emag = new /obj/item/reagent_containers/spray(src)
emag.reagents.add_reagent("lube", 250)
@@ -483,25 +512,44 @@
fix_modules()
-/obj/item/robot_module/combat
- name = "combat robot module"
+/obj/item/robot_module/destroyer
+ name = "destroyer robot module"
module_type = "Malf"
module_actions = list(
/datum/action/innate/robot_sight/thermal,
)
+/obj/item/robot_module/destroyer/New()
+ ..()
+
+ modules += new /obj/item/gun/energy/immolator/multi/cyborg(src) // See comments on /robot_module/combat below
+ modules += new /obj/item/melee/baton/loaded(src) // secondary weapon, for things immune to burn, immune to ranged weapons, or for arresting low-grade threats
+ modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
+ modules += new /obj/item/pickaxe/drill/jackhammer(src) // for breaking walls to execute flanking moves
+ modules += new /obj/item/borg/destroyer/mobility(src)
+ emag = null
+ fix_modules()
+
+
+/obj/item/robot_module/combat
+ name = "combat robot module"
+ module_type = "Malf"
+ module_actions = list()
+
/obj/item/robot_module/combat/New()
..()
+ modules += new /obj/item/gun/energy/immolator/multi/cyborg(src) // primary weapon, strong at close range (ie: against blob/terror/xeno), but consumes a lot of energy per shot.
+ // Borg gets 40 shots of this weapon. Gamma Sec ERT gets 10.
+ // So, borg has way more burst damage, but also takes way longer to recharge / get back in the fight once depleted. Has to find a borg recharger and sit in it for ages.
+ // Organic gamma sec ERT carries alternate weapons, including a box of flashbangs, and can load up on a huge number of guns from science. Borg cannot do either.
+ // Overall, gamma borg has higher skill floor but lower skill ceiling.
+ modules += new /obj/item/melee/baton/loaded(src) // secondary weapon, for things immune to burn, immune to ranged weapons, or for arresting low-grade threats
modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
- modules += new /obj/item/gun/energy/gun/cyborg(src)
- modules += new /obj/item/pickaxe/drill/jackhammer(src)
- modules += new /obj/item/borg/combat/shield(src)
- modules += new /obj/item/borg/combat/mobility(src)
- modules += new /obj/item/wrench/cyborg(src)
- emag = new /obj/item/gun/energy/lasercannon/cyborg(src)
-
+ modules += new /obj/item/pickaxe/drill/jackhammer(src) // for breaking walls to execute flanking moves
+ emag = null
fix_modules()
+
/obj/item/robot_module/alien/hunter
name = "alien hunter module"
module_type = "Standard"
diff --git a/code/modules/mob/living/silicon/robot/robot_movement.dm b/code/modules/mob/living/silicon/robot/robot_movement.dm
index 4b645b02849..1d3e1cade6d 100644
--- a/code/modules/mob/living/silicon/robot/robot_movement.dm
+++ b/code/modules/mob/living/silicon/robot/robot_movement.dm
@@ -9,7 +9,7 @@
/mob/living/silicon/robot/movement_delay()
. = ..()
. += speed
- if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
+ if(module_active && istype(module_active,/obj/item/borg/destroyer/mobility))
. -= 3
. += config.robot_delay
diff --git a/code/modules/mob/living/silicon/robot/syndicate.dm b/code/modules/mob/living/silicon/robot/syndicate.dm
index f5ac3e5532b..f5b58696059 100644
--- a/code/modules/mob/living/silicon/robot/syndicate.dm
+++ b/code/modules/mob/living/silicon/robot/syndicate.dm
@@ -3,8 +3,10 @@
icon_state = "syndie_bloodhound"
lawupdate = 0
scrambledcodes = 1
+ has_camera = FALSE
pdahide = 1
faction = list("syndicate")
+ bubble_icon = "syndibot"
designation = "Syndicate Assault"
modtype = "Syndicate"
req_access = list(ACCESS_SYNDICATE)
@@ -19,7 +21,7 @@
..()
cell = new /obj/item/stock_parts/cell/hyper(src)
-/mob/living/silicon/robot/syndicate/init()
+/mob/living/silicon/robot/syndicate/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/syndicate_override
module = new /obj/item/robot_module/syndicate(src)
@@ -45,7 +47,7 @@
Your energy saw functions as a circular saw, but can be activated to deal more damage, and your operative pinpointer will find and locate fellow nuclear operatives. \
Help the operatives secure the disk at all costs!"
-/mob/living/silicon/robot/syndicate/medical/init()
+/mob/living/silicon/robot/syndicate/medical/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
..()
module = new /obj/item/robot_module/syndicate_medical(src)
@@ -65,7 +67,7 @@
Be aware that physical contact or taking damage will break your disguise. \
Help the operatives secure the disk at all costs!"
-/mob/living/silicon/robot/syndicate/saboteur/init()
+/mob/living/silicon/robot/syndicate/saboteur/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
..()
module = new /obj/item/robot_module/syndicate_saboteur(src)
diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm
index 6457afc87d4..c923e0912b7 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -2,7 +2,9 @@
gender = NEUTER
robot_talk_understand = 1
voice_name = "synthesized voice"
+ bubble_icon = "machine"
has_unlimited_silicon_privilege = 1
+ weather_immunities = list("ash")
var/syndicate = 0
var/const/MAIN_CHANNEL = "Main Frequency"
var/lawchannel = MAIN_CHANNEL // Default channel on which to state laws
@@ -283,7 +285,7 @@
/mob/living/silicon/proc/receive_alarm(var/datum/alarm_handler/alarm_handler, var/datum/alarm/alarm, was_raised)
if(!next_alarm_notice)
- next_alarm_notice = world.time + SecondsToTicks(10)
+ next_alarm_notice = world.time + 10 SECONDS
var/list/alarms = queued_alarms[alarm_handler]
if(was_raised)
diff --git a/code/modules/mob/living/silicon/subsystems.dm b/code/modules/mob/living/silicon/subsystems.dm
index 5f00beff1e4..d18d41a40cf 100644
--- a/code/modules/mob/living/silicon/subsystems.dm
+++ b/code/modules/mob/living/silicon/subsystems.dm
@@ -2,7 +2,7 @@
var/register_alarms = 1
var/datum/nano_module/alarm_monitor/all/alarm_monitor
var/datum/nano_module/atmos_control/atmos_control
- var/datum/nano_module/crew_monitor/crew_monitor
+ var/datum/tgui_module/crew_monitor/crew_monitor
var/datum/nano_module/law_manager/law_manager
var/datum/nano_module/power_monitor/silicon/power_monitor
@@ -71,8 +71,7 @@
/mob/living/silicon/proc/subsystem_crew_monitor()
set category = "Subsystems"
set name = "Crew Monitor"
-
- crew_monitor.ui_interact(usr, state = GLOB.self_state)
+ crew_monitor.tgui_interact(usr, state = GLOB.tgui_self_state)
/****************
* Law Manager *
diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm
index 2cfc5e746dc..b42f3275997 100644
--- a/code/modules/mob/living/simple_animal/animal_defense.dm
+++ b/code/modules/mob/living/simple_animal/animal_defense.dm
@@ -118,7 +118,7 @@
/mob/living/simple_animal/blob_act(obj/structure/blob/B)
adjustBruteLoss(20)
-/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
+/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
if(!no_effect && !visual_effect_icon && melee_damage_upper)
if(melee_damage_upper < 10)
visual_effect_icon = ATTACK_EFFECT_PUNCH
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 962b4722f39..e51dc527832 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -18,7 +18,7 @@
speak_emote = list("states")
friendly = "boops"
-
+ bubble_icon = "machine"
faction = list("neutral", "silicon")
var/obj/machinery/bot_core/bot_core = null
@@ -63,6 +63,7 @@
var/new_destination // pending new destination (waiting for beacon response)
var/destination // destination description tag
var/next_destination // the next destination in the patrol route
+ var/ignorelistcleanuptimer = 1 // This ticks up every automated action, at 300 we clean the ignore list
var/robot_arm = /obj/item/robot_parts/r_arm
var/blockcount = 0 //number of times retried a blocked path
@@ -254,6 +255,15 @@
/mob/living/simple_animal/bot/handle_automated_action()
diag_hud_set_botmode()
+ if(ignorelistcleanuptimer % 300 == 0) // Every 300 actions, clean up the ignore list from old junk
+ for(var/uid in ignore_list)
+ var/atom/referredatom = locateUID(uid)
+ if(!referredatom || QDELETED(referredatom))
+ ignore_list -= uid
+ ignorelistcleanuptimer = 1
+ else
+ ignorelistcleanuptimer++
+
if(!on)
return
@@ -439,14 +449,15 @@ Example usage: patient = scan(/mob/living/carbon/human, oldpatient, 1)
The proc would return a human next to the bot to be set to the patient var.
Pass the desired type path itself, declaring a temporary var beforehand is not required.
*/
-/mob/living/simple_animal/bot/proc/scan(scan_type, old_target, scan_range = DEFAULT_SCAN_RANGE)
+/mob/living/simple_animal/bot/proc/scan(atom/scan_type, atom/old_target, scan_range = DEFAULT_SCAN_RANGE)
var/final_result
for(var/scan in shuffle(view(scan_range, src))) //Search for something in range!
- if(!istype(scan, scan_type)) //Check that the thing we found is the type we want!
+ var/atom/A = scan
+ if(!istype(A, scan_type)) //Check that the thing we found is the type we want!
continue //If not, keep searching!
- if( (scan in ignore_list) || (scan == old_target) ) //Filter for blacklisted elements, usually unreachable or previously processed oness
+ if((A.UID() in ignore_list) || (A == old_target) ) //Filter for blacklisted elements, usually unreachable or previously processed oness
continue
- var/scan_result = process_scan(scan) //Some bots may require additional processing when a result is selected.
+ var/scan_result = process_scan(A) //Some bots may require additional processing when a result is selected.
if(scan_result)
final_result = scan_result
else
@@ -454,17 +465,16 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r
return final_result
//When the scan finds a target, run bot specific processing to select it for the next step. Empty by default.
-/mob/living/simple_animal/bot/proc/process_scan(scan_target)
+/mob/living/simple_animal/bot/proc/process_scan(atom/scan_target)
return scan_target
-/mob/living/simple_animal/bot/proc/add_to_ignore(subject)
+/mob/living/simple_animal/bot/proc/add_to_ignore(atom/A)
if(ignore_list.len < 50) //This will help keep track of them, so the bot is always trying to reach a blocked spot.
- ignore_list |= subject
- else if(ignore_list.len >= subject) //If the list is full, insert newest, delete oldest.
- ignore_list -= ignore_list[1]
- ignore_list |= subject
-
+ ignore_list |= A.UID()
+ else //If the list is full, insert newest, delete oldest.
+ ignore_list.Cut(1, 2)
+ ignore_list |= A.UID()
/*
Movement proc for stepping a bot through a path generated through A-star.
Pass a positive integer as an argument to override a bot's default speed.
@@ -746,7 +756,7 @@ Pass a positive integer as an argument to override a bot's default speed.
// send a radio signal with multiple data key/values
/mob/living/simple_animal/bot/proc/post_signal_multiple(var/freq, var/list/keyval)
- if(z != 1) //Bot control will only work on station.
+ if(!is_station_level(z)) //Bot control will only work on station.
return
var/datum/radio_frequency/frequency = SSradio.return_frequency(freq)
if(!frequency)
diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
index f9747238138..4cb4a532d6b 100644
--- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm
@@ -50,7 +50,7 @@
/mob/living/simple_animal/bot/cleanbot/bot_reset()
..()
- ignore_list = list() //Allows the bot to clean targets it previously ignored due to being unreachable.
+ ignore_list.Cut() //Allows the bot to clean targets it previously ignored due to being unreachable.
target = null
oldloc = null
@@ -106,7 +106,7 @@
audible_message("[src] makes an excited beeping booping sound!")
if(!target) //Search for cleanables it can see.
- target = scan(/obj/effect/decal/cleanable/)
+ target = scan(/obj/effect/decal/cleanable)
if(!target && auto_patrol) //Search for cleanables it can see.
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm
index 024e2b5f304..e18672ffa20 100644
--- a/code/modules/mob/living/simple_animal/bot/construction.dm
+++ b/code/modules/mob/living/simple_animal/bot/construction.dm
@@ -474,8 +474,7 @@
return
build_step++
to_chat(user, "You complete the Securitron! Beep boop.")
- var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot
- S.forceMove(get_turf(src))
+ var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot(get_turf(src))
S.name = created_name
S.robot_arm = robot_arm
qdel(I)
@@ -512,7 +511,7 @@
//General Griefsky
else if((istype(I, /obj/item/wrench)) && (build_step == 3))
- var/obj/item/griefsky_assembly/A = new /obj/item/griefsky_assembly
+ var/obj/item/griefsky_assembly/A = new /obj/item/griefsky_assembly(get_turf(src))
user.put_in_hands(A)
to_chat(user, "You adjust the arm slots for extra weapons!.")
user.unEquip(src, 1)
@@ -540,8 +539,7 @@
if(!user.unEquip(I))
return
to_chat(user, "You complete General Griefsky!.")
- var/mob/living/simple_animal/bot/secbot/griefsky/S = new /mob/living/simple_animal/bot/secbot/griefsky
- S.forceMove(get_turf(src))
+ new /mob/living/simple_animal/bot/secbot/griefsky(get_turf(src))
qdel(I)
qdel(src)
@@ -556,8 +554,7 @@
if(!user.unEquip(I))
return
to_chat(user, "You complete Genewul Giftskee!.")
- var/mob/living/simple_animal/bot/secbot/griefsky/toy/S = new /mob/living/simple_animal/bot/secbot/griefsky/toy
- S.forceMove(get_turf(src))
+ new /mob/living/simple_animal/bot/secbot/griefsky/toy(get_turf(src))
qdel(I)
qdel(src)
diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm
index 5b0ea28a72a..df96cae3b6b 100644
--- a/code/modules/mob/living/simple_animal/bot/floorbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm
@@ -56,7 +56,7 @@
..()
target = null
oldloc = null
- ignore_list = list()
+ ignore_list.Cut()
nagged = 0
anchored = FALSE
update_icon()
@@ -270,7 +270,7 @@
return 1
//Floorbots, having several functions, need sort out special conditions here.
-/mob/living/simple_animal/bot/floorbot/process_scan(scan_target)
+/mob/living/simple_animal/bot/floorbot/process_scan(atom/scan_target)
var/result
var/turf/simulated/floor/F
switch(process_type)
diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm
index d9097a82d2e..62c133fffd7 100644
--- a/code/modules/mob/living/simple_animal/bot/honkbot.dm
+++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm
@@ -33,7 +33,7 @@
/obj/machinery/bot_core/honkbot
req_one_access = list(ACCESS_CLOWN, ACCESS_ROBOTICS, ACCESS_MIME)
-/mob/living/simple_animal/bot/honkbot/Initialize()
+/mob/living/simple_animal/bot/honkbot/Initialize(mapload)
. = ..()
update_icon()
auto_patrol = TRUE
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index 728b050dd54..f1278918898 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -323,13 +323,13 @@
/mob/living/simple_animal/bot/mulebot/proc/buzz(type)
switch(type)
if(SIGH)
- audible_message("[src] makes a sighing buzz.", "You hear an electronic buzzing sound.")
+ audible_message("[src] makes a sighing buzz.")
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
if(ANNOYED)
- audible_message("[src] makes an annoyed buzzing sound.", "You hear an electronic buzzing sound.")
+ audible_message("[src] makes an annoyed buzzing sound.")
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
if(DELIGHT)
- audible_message("[src] makes a delighted ping!", "You hear a ping.")
+ audible_message("[src] makes a delighted ping!")
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
@@ -601,7 +601,7 @@
/mob/living/simple_animal/bot/mulebot/proc/at_target()
if(!reached_target)
radio_channel = "Supply" //Supply channel
- audible_message("[src] makes a chiming sound!", "You hear a chime.")
+ audible_message("[src] makes a chiming sound!")
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
reached_target = 1
diff --git a/code/modules/mob/living/simple_animal/corpse.dm b/code/modules/mob/living/simple_animal/corpse.dm
index 10460d11e65..8d0ad5d0e2b 100644
--- a/code/modules/mob/living/simple_animal/corpse.dm
+++ b/code/modules/mob/living/simple_animal/corpse.dm
@@ -103,9 +103,9 @@
name = "Space Wizard Corpse"
outfit = /datum/outfit/wizardcorpse
-/obj/effect/mob_spawn/human/corpse/clownoff/Initialize()
+/obj/effect/mob_spawn/human/corpse/clownoff/Initialize(mapload)
mob_name = "[pick(GLOB.wizard_first)], [pick(GLOB.wizard_second)]"
- ..()
+ . = ..()
/datum/outfit/wizardcorpse
name = "Space Wizard Corpse"
diff --git a/code/modules/mob/living/simple_animal/damage_procs.dm b/code/modules/mob/living/simple_animal/damage_procs.dm
index 6ba69de6a61..fdcbf95216b 100644
--- a/code/modules/mob/living/simple_animal/damage_procs.dm
+++ b/code/modules/mob/living/simple_animal/damage_procs.dm
@@ -3,7 +3,7 @@
if(status_flags & GODMODE)
return FALSE
var/oldbruteloss = bruteloss
- bruteloss = Clamp(bruteloss + amount, 0, maxHealth)
+ bruteloss = clamp(bruteloss + amount, 0, maxHealth)
if(oldbruteloss == bruteloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index 24818d07652..f44244b7eae 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -123,6 +123,7 @@
for(var/mob/living/simple_animal/mouse/M in view(1, src))
if(!M.stat && Adjacent(M))
custom_emote(1, "splats \the [M]!")
+ M.death()
M.splat()
movement_target = null
stop_automated_movement = 0
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index 4b29e703116..07a21af8a0b 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -153,16 +153,16 @@
if(def_zone)
if(def_zone == "head")
if(inventory_head)
- armorval = inventory_head.armor[type]
+ armorval = inventory_head.armor.getRating(type)
else
if(inventory_back)
- armorval = inventory_back.armor[type]
+ armorval = inventory_back.armor.getRating(type)
return armorval
else
if(inventory_head)
- armorval += inventory_head.armor[type]
+ armorval += inventory_head.armor.getRating(type)
if(inventory_back)
- armorval += inventory_back.armor[type]
+ armorval += inventory_back.armor.getRating(type)
return armorval * 0.5
/mob/living/simple_animal/pet/dog/corgi/attackby(obj/item/O, mob/user, params)
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index ea8e949f1c7..58e3ad54089 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -126,6 +126,7 @@
gold_core_spawnable = FRIENDLY_SPAWN
blood_volume = BLOOD_VOLUME_NORMAL
var/obj/item/udder/udder = null
+ gender = FEMALE
/mob/living/simple_animal/cow/Initialize()
udder = new()
diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm
index 96688963b73..566791786f6 100644
--- a/code/modules/mob/living/simple_animal/friendly/lizard.dm
+++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm
@@ -23,3 +23,14 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 1)
can_collar = 1
gold_core_spawnable = FRIENDLY_SPAWN
+
+/mob/living/simple_animal/lizard/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(!istype(user, /mob/living/silicon/robot/drone))
+ user.visible_message("[user] sucks [src] into its decompiler. There's a horrible crunching noise.", \
+ "It's a bit of a struggle, but you manage to suck [src] into your decompiler. It makes a series of visceral crunching noises.")
+ new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
+ C.stored_comms["wood"] += 2
+ C.stored_comms["glass"] += 2
+ qdel(src)
+ return TRUE
+ return ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 481c3dc7910..be3f985db2e 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -80,15 +80,6 @@
icon_resting = "mouse_[mouse_color]_sleep"
desc = "It's a small [mouse_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself."
-/mob/living/simple_animal/mouse/proc/splat()
- src.health = 0
- src.stat = DEAD
- src.icon_dead = "mouse_[mouse_color]_splat"
- src.icon_state = "mouse_[mouse_color]_splat"
- layer = MOB_LAYER
- if(client)
- client.time_died_as_mouse = world.time
-
/mob/living/simple_animal/mouse/attack_hand(mob/living/carbon/human/M as mob)
if(M.a_intent == INTENT_HELP)
get_scooped(M)
@@ -113,6 +104,10 @@
desc = "It's toast."
death()
+/mob/living/simple_animal/mouse/proc/splat()
+ icon_dead = "mouse_[mouse_color]_splat"
+ icon_state = "mouse_[mouse_color]_splat"
+
/mob/living/simple_animal/mouse/death(gibbed)
// Only execute the below if we successfully died
playsound(src, squeak_sound, 40, 1)
@@ -237,3 +232,14 @@
gold_core_spawnable = NO_SPAWN
can_collar = 0
butcher_results = list(/obj/item/stack/sheet/metal = 1)
+
+/mob/living/simple_animal/mouse/decompile_act(obj/item/matter_decompiler/C, mob/user)
+ if(!(istype(user, /mob/living/silicon/robot/drone)))
+ user.visible_message("[user] sucks [src] into its decompiler. There's a horrible crunching noise.", \
+ "It's a bit of a struggle, but you manage to suck [src] into your decompiler. It makes a series of visceral crunching noises.")
+ new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
+ C.stored_comms["wood"] += 2
+ C.stored_comms["glass"] += 2
+ qdel(src)
+ return TRUE
+ return ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/penguin.dm b/code/modules/mob/living/simple_animal/friendly/penguin.dm
index dc00e252661..08321b1bb5a 100644
--- a/code/modules/mob/living/simple_animal/friendly/penguin.dm
+++ b/code/modules/mob/living/simple_animal/friendly/penguin.dm
@@ -18,7 +18,7 @@
/mob/living/simple_animal/pet/penguin/Initialize(mapload)
. = ..()
- AddComponent(/datum/component/waddling)
+ AddElement(/datum/element/waddling)
/mob/living/simple_animal/pet/penguin/emperor
name = "Emperor penguin"
diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
index 7a1227960f4..877d542fa2b 100644
--- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
+++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
@@ -123,8 +123,6 @@
if(health >= maxHealth)
to_chat(user, "[src] does not need repairing!")
return
- to_chat(user, "Unable to repair with the maintenance panel closed!")
- return
. = TRUE
if(!I.use_tool(src, user, volume = I.tool_volume))
return
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index 038b3b3d221..7c7b4dd6a2f 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -20,6 +20,7 @@
melee_damage_upper = 25
attacktext = "slashes"
speak_emote = list("hisses")
+ bubble_icon = "alien"
a_intent = INTENT_HARM
attack_sound = 'sound/weapons/bladeslice.ogg'
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
@@ -127,6 +128,7 @@
icon_state = "queen_s"
icon_living = "queen_s"
icon_dead = "queen_dead"
+ bubble_icon = "alienroyal"
move_to_delay = 4
maxHealth = 400
health = 400
@@ -153,7 +155,7 @@
icon_dead = "maid_dead"
/mob/living/simple_animal/hostile/alien/maid/AttackingTarget()
- if(ismovableatom(target))
+ if(ismovable(target))
if(istype(target, /obj/effect/decal/cleanable))
visible_message("\The [src] cleans up \the [target].")
qdel(target)
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index c1e7548d9a3..3419279ffe5 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -60,6 +60,7 @@
/mob/living/simple_animal/hostile/poison/bees/New()
..()
generate_bee_visuals()
+ AddComponent(/datum/component/swarming)
/mob/living/simple_animal/hostile/poison/bees/Destroy()
beegent = null
@@ -94,6 +95,10 @@
for(var/mob/A in searched_for)
. += A
+// All bee sprites are made up of overlays. They do not have any special sprite overlays for items placed on them, such as collars, so this proc is unneeded.
+/mob/living/simple_animal/hostile/poison/bees/regenerate_icons()
+ return
+
/mob/living/simple_animal/hostile/poison/bees/proc/generate_bee_visuals()
overlays.Cut()
diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
index 8d2ba52709f..c093c8e3d36 100644
--- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm
+++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm
@@ -25,23 +25,20 @@
var/list/human_overlays = list()
/mob/living/simple_animal/hostile/headcrab/Life(seconds, times_fired)
- if(..())
+ if(..() && !stat)
if(!is_zombie && isturf(src.loc))
for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile
if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD))
Zombify(H)
break
- var/cycles = 4
- if(cycles >= 4)
+ if(times_fired % 4 == 0)
for(var/mob/living/simple_animal/K in oview(src, 1)) //Only for corpse right next to/on same tile
if(K.stat == DEAD || (!K.check_death_method() && K.health <= HEALTH_THRESHOLD_DEAD))
- visible_message("[src] consumes [target] whole!")
+ visible_message("[src] consumes [K] whole!")
if(health < maxHealth)
health += 10
qdel(K)
break
- cycles = 0
- cycles++
/mob/living/simple_animal/hostile/headcrab/OpenFire(atom/A)
if(check_friendly_fire)
@@ -62,8 +59,8 @@
is_zombie = TRUE
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
- if(A.armor && A.armor["melee"])
- maxHealth += A.armor["melee"] //That zombie's got armor, I want armor!
+ if(A.armor && A.armor.getRating("melee"))
+ maxHealth += A.armor.getRating("melee") //That zombie's got armor, I want armor!
maxHealth += 200
health = maxHealth
name = "zombie"
@@ -93,7 +90,6 @@
if(is_zombie)
qdel(src)
-
/mob/living/simple_animal/hostile/headcrab/handle_automated_speech() // This way they have different screams when attacking, sometimes. Might be seen as sphagetthi code though.
if(speak_chance)
if(rand(0,200) < speak_chance)
@@ -106,7 +102,6 @@
M.loc = get_turf(src)
return ..()
-
/mob/living/simple_animal/hostile/headcrab/update_icons()
. = ..()
if(is_zombie)
diff --git a/code/modules/mob/living/simple_animal/hostile/headslug.dm b/code/modules/mob/living/simple_animal/hostile/headslug.dm
index 801514a3256..6800598fc7f 100644
--- a/code/modules/mob/living/simple_animal/hostile/headslug.dm
+++ b/code/modules/mob/living/simple_animal/hostile/headslug.dm
@@ -72,7 +72,7 @@
/obj/item/organ/internal/body_egg/changeling_egg/proc/Pop()
var/mob/living/carbon/human/monkey/M = new(owner)
- owner.stomach_contents += M
+ LAZYADD(owner.stomach_contents, M)
for(var/obj/item/organ/internal/I in src)
I.insert(M, 1)
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index d2a97949c8e..c6f3ac845e3 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -25,6 +25,7 @@
gold_core_spawnable = HOSTILE_SPAWN
loot = list(/obj/effect/decal/cleanable/blood/gibs/robot)
deathmessage = "blows apart!"
+ bubble_icon = "machine"
del_on_death = 1
/mob/living/simple_animal/hostile/hivebot/range
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index c9139ea7bfd..469ff0cc7e1 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -116,8 +116,8 @@ Difficulty: Hard
if(charging)
return
- anger_modifier = Clamp(((maxHealth - health)/60),0,20)
- enrage_time = initial(enrage_time) * Clamp(anger_modifier / 20, 0.5, 1)
+ anger_modifier = clamp(((maxHealth - health)/60),0,20)
+ enrage_time = initial(enrage_time) * clamp(anger_modifier / 20, 0.5, 1)
ranged_cooldown = world.time + 50
if(client)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index 7f1b3942d94..b8c72d7cf84 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -83,7 +83,7 @@ Difficulty: Very Hard
chosen_attack_num = 4
/mob/living/simple_animal/hostile/megafauna/colossus/OpenFire()
- anger_modifier = Clamp(((maxHealth - health)/50),0,20)
+ anger_modifier = clamp(((maxHealth - health)/50),0,20)
ranged_cooldown = world.time + 120
if(client)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
index e97b7671b67..50531f976e9 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm
@@ -103,7 +103,7 @@ Difficulty: Medium
if(swooping)
return
- anger_modifier = Clamp(((maxHealth - health)/50),0,20)
+ anger_modifier = clamp(((maxHealth - health)/50),0,20)
ranged_cooldown = world.time + ranged_cooldown_time
if(client)
@@ -254,7 +254,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/dragon/proc/line_target(var/offset, var/range, var/atom/at = target)
if(!at)
return
- var/angle = Atan2(at.x - src.x, at.y - src.y) + offset
+ var/angle = ATAN2(at.x - src.x, at.y - src.y) + offset
var/turf/T = get_turf(src)
for(var/i in 1 to range)
var/turf/check = locate(src.x + cos(angle) * i, src.y + sin(angle) * i, src.z)
@@ -344,10 +344,10 @@ Difficulty: Medium
//ensure swoop direction continuity.
if(negative)
- if(IsInRange(x, initial_x + 1, initial_x + DRAKE_SWOOP_DIRECTION_CHANGE_RANGE))
+ if(ISINRANGE(x, initial_x + 1, initial_x + DRAKE_SWOOP_DIRECTION_CHANGE_RANGE))
negative = FALSE
else
- if(IsInRange(x, initial_x - DRAKE_SWOOP_DIRECTION_CHANGE_RANGE, initial_x - 1))
+ if(ISINRANGE(x, initial_x - DRAKE_SWOOP_DIRECTION_CHANGE_RANGE, initial_x - 1))
negative = TRUE
new /obj/effect/temp_visual/dragon_flight/end(loc, negative)
new /obj/effect/temp_visual/dragon_swoop(loc)
@@ -534,7 +534,7 @@ obj/effect/temp_visual/fireball
duration = 9
pixel_z = 270
-/obj/effect/temp_visual/fireball/Initialize()
+/obj/effect/temp_visual/fireball/Initialize(mapload)
. = ..()
animate(src, pixel_z = 0, time = duration)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 716f5436223..65d056188a8 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -452,6 +452,7 @@ Difficulty: Hard
else
burst_range = 3
INVOKE_ASYNC(src, .proc/burst, get_turf(src), 0.25) //melee attacks on living mobs cause it to release a fast burst if on cooldown
+ OpenFire()
else
devour(L)
else
@@ -481,7 +482,7 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/calculate_rage() //how angry we are overall
did_reset = FALSE //oh hey we're doing SOMETHING, clearly we might need to heal if we recall
- anger_modifier = Clamp(((maxHealth - health) / 42),0,50)
+ anger_modifier = clamp(((maxHealth - health) / 42),0,50)
burst_range = initial(burst_range) + round(anger_modifier * 0.08)
beam_range = initial(beam_range) + round(anger_modifier * 0.12)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index 4ce66ccd1d5..eed05d55e91 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -43,7 +43,6 @@
. = ..()
if(internal_type && true_spawn)
internal = new internal_type(src)
- apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
for(var/action_type in attack_action_types)
var/datum/action/innate/megafauna_attack/attack_action = new action_type()
attack_action.Grant(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm
index 848a285abf4..fbf65ccfa9b 100644
--- a/code/modules/mob/living/simple_animal/hostile/mimic.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm
@@ -48,8 +48,8 @@
var/attempt_open = 0
// Pickup loot
-/mob/living/simple_animal/hostile/mimic/crate/Initialize()
- ..()
+/mob/living/simple_animal/hostile/mimic/crate/Initialize(mapload)
+ . = ..()
for(var/obj/item/I in loc)
I.loc = src
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
index ca9b632e06a..a5248e98bb6 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
@@ -90,6 +90,7 @@
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, .proc/death), 100)
+ AddComponent(/datum/component/swarming)
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
index 7c7200e8588..a888fa7ee9a 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
@@ -23,10 +23,6 @@
var/icon_aggro = null
var/crusher_drop_mod = 25
-/mob/living/simple_animal/hostile/asteroid/Initialize(mapload)
- . = ..()
- apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
-
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
if(vision_range != aggro_vision_range)
diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
index e8ce4027b4e..89164167005 100644
--- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm
+++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm
@@ -31,7 +31,7 @@
deathmessage = "wails as its form turns into a pulpy mush."
death_sound = 'sound/voice/hiss6.ogg'
-/mob/living/simple_animal/hostile/netherworld/migo/Initialize()
+/mob/living/simple_animal/hostile/netherworld/migo/Initialize(mapload)
. = ..()
migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/voice/bcreep.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/mpatchedup.ogg', 'sound/voice/mfeelbetter.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heartbeat.ogg', 'sound/effects/hyperspace_begin.ogg', 'sound/effects/hyperspace_end.ogg', 'sound/goonstation/effects/screech.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/goonstation/misc/airraid_loop.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/chainsaw.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gunshots/gunshot_silenced.ogg', 'sound/weapons/gunshots/gunshot.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlock_close.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlock_open.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/ambience/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/outbreak5.ogg', 'sound/ai/outbreak7.ogg', 'sound/ai/poweroff.ogg', 'sound/ai/radiation.ogg', 'sound/ai/shuttlecalled.ogg', 'sound/ai/shuttledock.ogg', 'sound/ai/shuttlerecalled.ogg', 'sound/ai/aimalf.ogg', 'sound/ambience/ambigen1.ogg', 'sound/ambience/ambigen3.ogg', 'sound/ambience/ambigen4.ogg', 'sound/ambience/ambigen5.ogg', 'sound/ambience/ambigen6.ogg', 'sound/ambience/ambigen10.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg') //hahahaha fuck you code divers
@@ -82,14 +82,14 @@
/obj/structure/spawner/nether/examine(mob/user)
. = ..()
- if(isskeleton(user) || iszombie(user))
+ if(isskeleton(user))
. += "A direct link to another dimension full of creatures very happy to see you. You can see your house from here!"
else
. += "A direct link to another dimension full of creatures not very happy to see you. Entering the link would be a very bad idea."
/obj/structure/spawner/nether/attack_hand(mob/user)
. = ..()
- if(isskeleton(user) || iszombie(user))
+ if(isskeleton(user))
to_chat(user, "You don't feel like going home yet...")
else
user.visible_message("[user] is violently pulled into the link!", \
diff --git a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
index fd569984920..07f26031ed5 100644
--- a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
+++ b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
@@ -335,7 +335,7 @@
//Jiggle the whole worm forwards towards the next segment
-/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
+/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
..()
if(previousWorm)
previousWorm.do_attack_animation(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 23970e88826..decfc7146cf 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -260,7 +260,7 @@
alert_on_shield_breach = TRUE
/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/Initialize(mapload)
- ..()
+ . = ..()
if(prob(50))
// 50% chance of switching to extremely dangerous ranged variant
melee_damage_lower = 10
@@ -349,7 +349,8 @@
icon = 'icons/mob/critter.dmi'
icon_state = "viscerator_attack"
icon_living = "viscerator_attack"
- pass_flags = PASSTABLE
+ pass_flags = PASSTABLE | PASSMOB
+ a_intent = INTENT_HARM
health = 15
maxHealth = 15
obj_damage = 0
@@ -362,6 +363,11 @@
minbodytemp = 0
mob_size = MOB_SIZE_TINY
flying = 1
+ bubble_icon = "syndibot"
gold_core_spawnable = HOSTILE_SPAWN
del_on_death = 1
deathmessage = "is smashed into pieces!"
+
+/mob/living/simple_animal/hostile/viscerator/Initialize(mapload)
+ . = ..()
+ AddComponent(/datum/component/swarming)
diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm
index 047219a151b..6f33c51b246 100644
--- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm
+++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/princess.dm
@@ -15,7 +15,7 @@
ai_target_method = TS_DAMAGE_SIMPLE
icon_state = "terror_princess1"
icon_living = "terror_princess1"
- icon_dead = "terror_princess_dead1"
+ icon_dead = "terror_princess1_dead"
maxHealth = 150
health = 150
regen_points_per_hp = 1 // always regens very fast
@@ -51,7 +51,7 @@
if(fed == 0)
icon_state = "terror_princess1"
icon_living = "terror_princess1"
- icon_dead = "terror_princess_dead1"
+ icon_dead = "terror_princess1_dead"
desc = "An enormous spider. It looks strangely cute and fluffy, with soft pink fur covering most of its body."
else if(fed == 1)
icon_state = "terror_princess2"
diff --git a/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm b/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm
index 241cceb3d2c..bf3c98bb86a 100644
--- a/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm
+++ b/code/modules/mob/living/simple_animal/hostile/terror_spiders/queen.dm
@@ -168,7 +168,7 @@
neststep = 4
else
spider_lastspawn = world.time
- var/spiders_left_to_spawn = Clamp( (spider_max_per_nest - CountSpiders()), 1, 10)
+ var/spiders_left_to_spawn = clamp( (spider_max_per_nest - CountSpiders()), 1, 10)
DoLayTerrorEggs(pick(spider_types_standard), spiders_left_to_spawn)
if(4)
// Nest should be full. Otherwise, start replenishing nest (stage 5).
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index 41786017ea2..97dbd831dd0 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -710,7 +710,7 @@
ears.talk_into(src, message_pieces, message_mode, verb)
used_radios += ears
-/mob/living/simple_animal/parrot/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency)
+/mob/living/simple_animal/parrot/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
if(speaker != src && prob(50))
parrot_hear(html_decode(multilingual_to_message(message_pieces)))
..()
diff --git a/code/modules/mob/living/simple_animal/posessed_object.dm b/code/modules/mob/living/simple_animal/posessed_object.dm
index 9372412b211..729790d098c 100644
--- a/code/modules/mob/living/simple_animal/posessed_object.dm
+++ b/code/modules/mob/living/simple_animal/posessed_object.dm
@@ -27,7 +27,7 @@
. += "[src] appears to be having trouble staying afloat!"
-/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
+/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
..()
animate_ghostly_presence(src, -1, 20, 1) // Restart the floating animation after the attack animation, as it will be cancelled.
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index ada8ed9896b..d4f8e7c4c3d 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -144,7 +144,7 @@
/mob/living/simple_animal/updatehealth(reason = "none given")
..(reason)
- health = Clamp(health, 0, maxHealth)
+ health = clamp(health, 0, maxHealth)
med_hud_set_health()
/mob/living/simple_animal/StartResting(updating = 1)
@@ -615,3 +615,8 @@
if(pcollar && collar_type)
add_overlay("[collar_type]collar")
add_overlay("[collar_type]tag")
+
+/mob/living/simple_animal/Login()
+ ..()
+ walk(src, 0) // if mob is moving under ai control, then stop AI movement
+
diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm
index bd9d001f12f..3f978abbfbb 100644
--- a/code/modules/mob/living/simple_animal/slime/powers.dm
+++ b/code/modules/mob/living/simple_animal/slime/powers.dm
@@ -190,7 +190,7 @@
step_away(M,src)
M.Friends = Friends.Copy()
babies += M
- M.mutation_chance = Clamp(mutation_chance+(rand(5,-5)),0,100)
+ M.mutation_chance = clamp(mutation_chance+(rand(5,-5)),0,100)
feedback_add_details("slime_babies_born", "slimebirth_[replacetext(M.colour," ","_")]")
var/mob/living/simple_animal/slime/new_slime = pick(babies)
diff --git a/code/modules/mob/living/simple_animal/slime/say.dm b/code/modules/mob/living/simple_animal/slime/say.dm
index 74241dc676c..8679d64a699 100644
--- a/code/modules/mob/living/simple_animal/slime/say.dm
+++ b/code/modules/mob/living/simple_animal/slime/say.dm
@@ -9,7 +9,7 @@
return verb
-/mob/living/simple_animal/slime/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency)
+/mob/living/simple_animal/slime/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
if(speaker != src && !stat)
if(speaker in Friends)
speech_buffer = list()
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 5a07f933fd7..1b67b53119a 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -17,6 +17,7 @@
response_harm = "stomps on"
emote_see = list("jiggles", "bounces in place")
speak_emote = list("blorbles")
+ bubble_icon = "slime"
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index 5345bda5b94..c222f76eadb 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -28,6 +28,7 @@
/mob/Login()
GLOB.player_list |= src
+ last_known_ckey = ckey
update_Login_details()
world.update_status()
diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm
index 8bdb0d89332..91bf5f0ab9c 100644
--- a/code/modules/mob/logout.dm
+++ b/code/modules/mob/logout.dm
@@ -1,5 +1,6 @@
/mob/Logout()
SSnanoui.user_logout(src) // this is used to clean up (remove) this user's Nano UIs
+ SStgui.on_logout(src) // Cleanup any TGUIs the user has open
unset_machine()
GLOB.player_list -= src
log_access_out(src)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 235996e571f..82c9cfdc065 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -19,11 +19,10 @@
for(var/datum/alternate_appearance/AA in viewing_alternate_appearances)
AA.viewers -= src
viewing_alternate_appearances = null
- logs.Cut()
- ..()
- return QDEL_HINT_HARDDEL
+ LAssailant = null
+ return ..()
-/mob/Initialize()
+/mob/Initialize(mapload)
GLOB.mob_list += src
if(stat == DEAD)
GLOB.dead_mob_list += src
@@ -31,7 +30,7 @@
GLOB.alive_mob_list += src
set_focus(src)
prepare_huds()
- ..()
+ . = ..()
/atom/proc/prepare_huds()
hud_list = list()
@@ -42,6 +41,7 @@
hud_list[hud] = list()
else
var/image/I = image('icons/mob/hud.dmi', src, "")
+ I.appearance_flags = RESET_COLOR | RESET_TRANSFORM
hud_list[hud] = I
/mob/proc/generate_name()
@@ -64,8 +64,8 @@
t+= "Oxygen: [environment.oxygen] \n"
t+= "Plasma : [environment.toxins] \n"
t+= "Carbon Dioxide: [environment.carbon_dioxide] \n"
- for(var/datum/gas/trace_gas in environment.trace_gases)
- to_chat(usr, "[trace_gas.type]: [trace_gas.moles] \n")
+ t+= "N2O: [environment.sleeping_agent] \n"
+ t+= "Agent B: [environment.agent_b] \n"
usr.show_message(t, 1)
@@ -126,14 +126,12 @@
// self_message (optional) is what the src mob hears.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
-/mob/audible_message(var/message, var/deaf_message, var/hearing_distance, var/self_message)
+/mob/audible_message(message, deaf_message, hearing_distance)
var/range = 7
if(hearing_distance)
range = hearing_distance
var/msg = message
for(var/mob/M in get_mobs_in_view(range, src))
- if(self_message && M == src)
- msg = self_message
M.show_message(msg, 2, deaf_message, 1)
// based on say code
@@ -155,12 +153,12 @@
// message is the message output to anyone who can hear.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
-/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance)
+/atom/proc/audible_message(message, deaf_message, hearing_distance)
var/range = 7
if(hearing_distance)
range = hearing_distance
for(var/mob/M in get_mobs_in_view(range, src))
- M.show_message( message, 2, deaf_message, 1)
+ M.show_message(message, 2, deaf_message, 1)
/mob/proc/findname(msg)
for(var/mob/M in GLOB.mob_list)
@@ -753,7 +751,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
if(client.holder && (client.holder.rights & R_ADMIN))
is_admin = 1
- else if(stat != DEAD || istype(src, /mob/new_player))
+ else if(stat != DEAD || isnewplayer(src))
to_chat(usr, "You must be observing to use this!")
return
@@ -764,7 +762,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
var/list/namecounts = list()
var/list/creatures = list()
- for(var/obj/O in world) //EWWWWWWWWWWWWWWWWWWWWWWWW ~needs to be optimised
+ for(var/obj/O in GLOB.poi_list)
if(!O.loc)
continue
if(istype(O, /obj/item/disk/nuclear))
@@ -881,6 +879,9 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
return
if(!Adjacent(usr))
return
+ if(IsFrozen(src) && !is_admin(usr))
+ to_chat(usr, "Interacting with admin-frozen players is not permitted.")
+ return
if(isLivingSSD(src) && M.client && M.client.send_ssd_warning(src))
return
show_inv(usr)
@@ -1098,7 +1099,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
var/mob/living/simple_animal/mouse/host
var/obj/machinery/atmospherics/unary/vent_pump/vent_found
var/list/found_vents = list()
- for(var/obj/machinery/atmospherics/unary/vent_pump/v in world)
+ for(var/obj/machinery/atmospherics/unary/vent_pump/v in SSair.atmos_machinery)
if(!v.welded && v.z == src.z)
found_vents.Add(v)
if(found_vents.len)
@@ -1236,10 +1237,13 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
create_log_in_list(debug_log, text, collapse, world.timeofday)
/mob/proc/create_log(log_type, what, target = null, turf/where = get_turf(src))
- LAZYINITLIST(logs[log_type])
- var/list/log_list = logs[log_type]
+ if(!ckey)
+ return
+ var/real_ckey = ckey
+ if(ckey[1] == "@") // Admin aghosting will do this
+ real_ckey = copytext(ckey, 2)
var/datum/log_record/record = new(log_type, src, what, target, where, world.time)
- log_list.Add(record)
+ GLOB.logging.add_log(real_ckey, record)
/proc/create_log_in_list(list/target, text, collapse = TRUE, last_log)//forgive me code gods for this shitcode proc
//this proc enables lovely stuff like an attack log that looks like this: "[18:20:29-18:20:45]21x John Smith attacked Andrew Jackson with a crowbar."
@@ -1298,8 +1302,6 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
.["Add Organ"] = "?_src_=vars;addorgan=[UID()]"
.["Remove Organ"] = "?_src_=vars;remorgan=[UID()]"
- .["Fix NanoUI"] = "?_src_=vars;fix_nano=[UID()]"
-
.["Add Verb"] = "?_src_=vars;addverb=[UID()]"
.["Remove Verb"] = "?_src_=vars;remverb=[UID()]"
@@ -1356,6 +1358,12 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
+/mob/proc/set_sight(datum/vision_override/O)
+ QDEL_NULL(vision_type)
+ if(O) //in case of null
+ vision_type = new O
+ update_sight()
+
/mob/proc/sync_lighting_plane_alpha()
if(hud_used)
var/obj/screen/plane_master/lighting/L = hud_used.plane_masters["[LIGHTING_PLANE]"]
@@ -1383,3 +1391,29 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
///Force set the mob nutrition
/mob/proc/set_nutrition(change)
nutrition = max(0, change)
+
+/mob/clean_blood(clean_hands = TRUE, clean_mask = TRUE, clean_feet = TRUE)
+ . = ..()
+ if(bloody_hands && clean_hands)
+ bloody_hands = 0
+ update_inv_gloves()
+ if(l_hand)
+ if(l_hand.clean_blood())
+ update_inv_l_hand()
+ if(r_hand)
+ if(r_hand.clean_blood())
+ update_inv_r_hand()
+ if(back)
+ if(back.clean_blood())
+ update_inv_back()
+ if(wear_mask && clean_mask)
+ if(wear_mask.clean_blood())
+ update_inv_wear_mask()
+ if(clean_feet)
+ feet_blood_color = null
+ qdel(feet_blood_DNA)
+ bloody_feet = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_NOT_BLOODY = 0)
+ blood_state = BLOOD_STATE_NOT_BLOODY
+ update_inv_shoes()
+ update_icons() //apply the now updated overlays to the mob
+
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index dc77610b97e..80404460b50 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -31,12 +31,12 @@
var/use_me = 1 //Allows all mobs to use the me verb by default, will have to manually specify they cannot
var/damageoverlaytemp = 0
var/computer_id = null
- var/lastattacker = null
- var/lastattacked = null
+ var/lastattacker = null // real name of the person doing the attacking
+ var/lastattackerckey = null // their ckey
var/list/attack_log_old = list( )
var/list/debug_log = null
- var/list/logs = list() // Logs for each log type defined in __DEFINES/logs.dm
+ var/last_known_ckey = null // Used in logging
var/last_log = 0
var/obj/machinery/machine = null
@@ -50,7 +50,6 @@
var/med_record = ""
var/sec_record = ""
var/gen_record = ""
- var/bhunger = 0 //Carbon
var/lying = 0
var/lying_prev = 0
var/lastpuke = 0
@@ -61,8 +60,7 @@
var/emote_type = 1 // Define emote default type, 1 for seen emotes, 2 for heard emotes
var/name_archive //For admin things like possession
- var/timeofdeath = 0.0//Living
-
+ var/timeofdeath = 0 //Living
var/bodytemperature = 310.055 //98.7 F
var/flying = 0
@@ -71,22 +69,22 @@
var/hunger_drain = HUNGER_FACTOR // how quickly the mob gets hungry; largely utilized by species.
var/overeatduration = 0 // How long this guy is overeating //Carbon
- var/intent = null//Living
+ var/intent = null //Living
var/shakecamera = 0
- var/a_intent = INTENT_HELP//Living
- var/m_intent = MOVE_INTENT_RUN//Living
+ var/a_intent = INTENT_HELP //Living
+ var/m_intent = MOVE_INTENT_RUN //Living
var/lastKnownIP = null
/// movable atoms buckled to this mob
- var/atom/movable/buckled = null//Living
+ var/atom/movable/buckled = null //Living
/// movable atom we are buckled to
var/atom/movable/buckling
- var/obj/item/l_hand = null//Living
- var/obj/item/r_hand = null//Living
- var/obj/item/back = null//Human/Monkey
- var/obj/item/tank/internal = null//Human/Monkey
- var/obj/item/storage/s_active = null//Carbon
- var/obj/item/clothing/mask/wear_mask = null//Carbon
+ var/obj/item/l_hand = null //Living
+ var/obj/item/r_hand = null //Living
+ var/obj/item/back = null //Human
+ var/obj/item/tank/internal = null //Human
+ var/obj/item/storage/s_active = null //Carbon
+ var/obj/item/clothing/mask/wear_mask = null //Carbon
var/datum/hud/hud_used = null
@@ -95,7 +93,6 @@
var/research_scanner = 0 //For research scanner equipped mobs. Enable to show research data when examining.
var/list/grabbed_by = list()
- var/list/requests = list()
var/lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
var/list/mapobjs = list()
@@ -103,9 +100,9 @@
var/emote_cd = 0 // Used to supress emote spamming. 1 if on CD, 2 if disabled by admin (manually set), else 0
- var/job = null//Living
+ var/job = null //Living
- var/datum/dna/dna = null//Carbon
+ var/datum/dna/dna = null //Carbon
var/radiation = 0 //Carbon
var/list/mutations = list() //Carbon -- Doohl
@@ -179,8 +176,6 @@
var/turf/listed_turf = null //the current turf being examined in the stat panel
var/list/shouldnt_see = list() //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes
- var/kills = 0
-
var/stance_damage = 0 //Whether this mob's ability to stand has been affected
var/list/active_genes = list()
diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm
index f595f6b4839..37e116b4376 100644
--- a/code/modules/mob/mob_grab.dm
+++ b/code/modules/mob/mob_grab.dm
@@ -53,12 +53,11 @@
hud.master = src
//check if assailant is grabbed by victim as well
- if(assailant.grabbed_by)
- for(var/obj/item/grab/G in assailant.grabbed_by)
- if(G.assailant == affecting && G.affecting == assailant)
- G.dancing = 1
- G.adjust_position()
- dancing = 1
+ for(var/obj/item/grab/G in assailant.grabbed_by)
+ if(G.assailant == affecting && G.affecting == assailant)
+ G.dancing = 1
+ G.adjust_position()
+ dancing = 1
clean_grabbed_by(assailant, affecting)
adjust_position()
@@ -276,7 +275,7 @@
assailant.visible_message("[assailant] has reinforced [assailant.p_their()] grip on [affecting] (now neck)!")
state = GRAB_NECK
icon_state = "grabbed+1"
- assailant.setDir(get_dir(assailant, affecting))
+
add_attack_logs(assailant, affecting, "Neck grabbed", ATKLOG_ALL)
if(!iscarbon(assailant))
affecting.LAssailant = null
@@ -296,7 +295,7 @@
assailant.next_move = world.time + 10
if(!affecting.get_organ_slot("breathing_tube"))
affecting.AdjustLoseBreath(1)
- affecting.setDir(WEST)
+
adjust_position()
//This is used to make sure the victim hasn't managed to yackety sax away before using the grab.
@@ -409,7 +408,7 @@
add_attack_logs(attacker, affecting, "Devoured")
affecting.forceMove(user)
- attacker.stomach_contents.Add(affecting)
+ LAZYADD(attacker.stomach_contents, affecting)
qdel(src)
/obj/item/grab/proc/checkvalid(var/mob/attacker, var/mob/prey) //does all the checking for the attack proc to see if a mob can eat another with the grab
@@ -433,9 +432,10 @@
/obj/item/grab/Destroy()
if(affecting)
- affecting.pixel_x = 0
- affecting.pixel_y = 0 //used to be an animate, not quick enough for del'ing
- affecting.layer = initial(affecting.layer)
+ if(!affecting.buckled)
+ affecting.pixel_x = 0
+ affecting.pixel_y = 0 //used to be an animate, not quick enough for qdel'ing
+ affecting.layer = initial(affecting.layer)
affecting.grabbed_by -= src
affecting = null
if(assailant)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index df2a39c0930..5fb5bcb06c8 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -12,14 +12,6 @@
return 1
return 0
-/mob/proc/isSynthetic()
- return 0
-
-/mob/living/carbon/human/isSynthetic()
- if(ismachine(src))
- return TRUE
- return FALSE
-
/mob/proc/get_screen_colour()
/mob/proc/update_client_colour(var/time = 10) //Update the mob's client.color with an animation the specified time in length.
@@ -467,7 +459,7 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
name = realname
for(var/mob/M in GLOB.player_list)
- if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || check_rights(R_ADMIN|R_MOD,0,M)) && M.get_preference(CHAT_DEAD))
+ if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || check_rights(R_ADMIN|R_MOD,0,M)) && M.get_preference(CHAT_DEAD))
var/follow
var/lname
if(subject)
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 471ddc42557..4797c685fe1 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -26,25 +26,6 @@
else
to_chat(usr, "This mob type cannot throw items.")
-
-/client/verb/drop_item()
- set hidden = 1
- if(!isrobot(mob))
- mob.drop_item_v()
- return
-
-
-/* /client/Center()
- /* No 3D movement in 2D spessman game. dir 16 is Z Up
- if(isobj(mob.loc))
- var/obj/O = mob.loc
- if(mob.canmove)
- return O.relaymove(mob, 16)
- */
- return
- */
-
-
/client/proc/Move_object(direct)
if(mob && mob.control_object)
if(mob.control_object.density)
@@ -186,7 +167,7 @@
if(newdir)
direct = newdir
n = get_step(mob, direct)
-
+
. = mob.SelfMove(n, direct, delay)
mob.setDir(direct)
diff --git a/code/modules/mob/mob_transformation_simple.dm b/code/modules/mob/mob_transformation_simple.dm
index c3ec68c9793..1e704ea3449 100644
--- a/code/modules/mob/mob_transformation_simple.dm
+++ b/code/modules/mob/mob_transformation_simple.dm
@@ -4,7 +4,7 @@
//Note that this proc does NOT do MMI related stuff!
/mob/proc/change_mob_type(var/new_type = null, var/turf/location = null, var/new_name = null as text, var/delete_old_mob = 0 as num, var/forcekey = 0)
- if(istype(src,/mob/new_player))
+ if(isnewplayer(src))
to_chat(usr, "cannot convert players who have not entered yet.")
return
diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm
index af3d439df59..f53daba6626 100644
--- a/code/modules/mob/new_player/new_player.dm
+++ b/code/modules/mob/new_player/new_player.dm
@@ -12,8 +12,13 @@
stat = 2
canmove = 0
-/mob/new_player/New()
+/mob/new_player/Initialize(mapload)
+ SHOULD_CALL_PARENT(FALSE)
+ if(initialized)
+ stack_trace("Warning: [src]([type]) initialized multiple times!")
+ initialized = TRUE
GLOB.mob_list += src
+ return INITIALIZE_HINT_NORMAL
/mob/new_player/verb/new_player_panel()
set src = usr
@@ -205,6 +210,7 @@
if(!client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed.
observer.verbs -= /mob/dead/observer/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
observer.key = key
+ QDEL_NULL(mind)
GLOB.respawnable_list += observer
qdel(src)
return 1
diff --git a/code/modules/mob/new_player/poll.dm b/code/modules/mob/new_player/poll.dm
index f67c53c9941..2e109d36d34 100644
--- a/code/modules/mob/new_player/poll.dm
+++ b/code/modules/mob/new_player/poll.dm
@@ -90,9 +90,9 @@
if(adminonly)
question = "(Admin only poll) " + question
- var output = ""
+ var/output = ""
if(polltype == POLLTYPE_MULTI || polltype == POLLTYPE_OPTION)
- select_query = GLOB.dbcon.NewQuery("SELECT text, percentagecalc, (SELECT COUNT(optionid) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id GROUP BY optionid) AS votecount FROM [format_table_name("poll_option")] WHERE pollid = [pollid]");
+ select_query = GLOB.dbcon.NewQuery("SELECT text, percentagecalc, (SELECT COUNT(optionid) FROM [format_table_name("poll_vote")] WHERE optionid = poll_option.id GROUP BY optionid) AS votecount FROM [format_table_name("poll_option")] WHERE pollid = [pollid]")
select_query.Execute()
var/list/options = list()
var/total_votes = 1
@@ -177,7 +177,7 @@
output += " |