Merge branch 'master' into convert-tickets

This commit is contained in:
farie82
2020-07-30 18:26:09 +02:00
committed by GitHub
152 changed files with 650 additions and 460 deletions
+3 -3
View File
@@ -826,7 +826,7 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
return
if(holder)
admin_log_and_message_admins("is altering the appearance of [H].")
log_and_message_admins("is altering the appearance of [H].")
H.change_appearance(APPEARANCE_ALL, usr, usr, check_species_whitelist = 0)
feedback_add_details("admin_verb","CHAA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -857,10 +857,10 @@ GLOBAL_LIST_INIT(admin_verbs_ticket, list(
switch(alert("Do you wish for [H] to be allowed to select non-whitelisted races?","Alter Mob Appearance","Yes","No","Cancel"))
if("Yes")
admin_log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, without whitelisting of races.")
log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, without whitelisting of races.")
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 0)
if("No")
admin_log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, with whitelisting of races.")
log_and_message_admins("has allowed [H] to change [H.p_their()] appearance, with whitelisting of races.")
H.change_appearance(APPEARANCE_ALL, H.loc, check_species_whitelist = 1)
feedback_add_details("admin_verb","CMAS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+12 -6
View File
@@ -2589,14 +2589,16 @@
if("monkey")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","M")
for(var/mob/living/carbon/human/H in GLOB.mob_list)
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/H = thing
spawn(0)
H.monkeyize()
ok = 1
if("corgi")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","M")
for(var/mob/living/carbon/human/H in GLOB.mob_list)
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/H = thing
spawn(0)
H.corgize()
ok = 1
@@ -2667,7 +2669,8 @@
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","PW")
message_admins("<span class='notice'>[key_name_admin(usr)] teleported all players to the prison station.</span>", 1)
for(var/mob/living/carbon/human/H in GLOB.mob_list)
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/H = thing
var/turf/loc = find_loc(H)
var/security = 0
if(!is_station_level(loc.z) || GLOB.prisonwarped.Find(H))
@@ -3000,7 +3003,8 @@
if("manifest")
var/dat = "<B>Showing Crew Manifest.</B><HR>"
dat += "<table cellspacing=5><tr><th>Name</th><th>Position</th></tr>"
for(var/mob/living/carbon/human/H in GLOB.mob_list)
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/H = thing
if(H.ckey)
dat += text("<tr><td>[]</td><td>[]</td></tr>", H.name, H.get_assignment())
dat += "</table>"
@@ -3010,7 +3014,8 @@
if("DNA")
var/dat = "<B>Showing DNA from blood.</B><HR>"
dat += "<table cellspacing=5><tr><th>Name</th><th>DNA</th><th>Blood Type</th></tr>"
for(var/mob/living/carbon/human/H in GLOB.mob_list)
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/H = thing
if(H.dna && H.ckey)
dat += "<tr><td>[H]</td><td>[H.dna.unique_enzymes]</td><td>[H.dna.blood_type]</td></tr>"
dat += "</table>"
@@ -3018,7 +3023,8 @@
if("fingerprints")
var/dat = "<B>Showing Fingerprints.</B><HR>"
dat += "<table cellspacing=5><tr><th>Name</th><th>Fingerprints</th></tr>"
for(var/mob/living/carbon/human/H in GLOB.mob_list)
for(var/thing in GLOB.human_list)
var/mob/living/carbon/human/H = thing
if(H.ckey)
if(H.dna && H.dna.uni_identity)
dat += "<tr><td>[H]</td><td>[md5(H.dna.uni_identity)]</td></tr>"
+1 -1
View File
@@ -78,5 +78,5 @@
C.verbs -= msay
to_chat(C, "<b>Mentor chat has been disabled.</b>")
admin_log_and_message_admins("toggled mentor chat [enabling ? "on" : "off"].")
log_and_message_admins("toggled mentor chat [enabling ? "on" : "off"].")
feedback_add_details("admin_verb", "TMC")
+1 -1
View File
@@ -643,7 +643,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
for(var/areatype in areas_without_camera)
to_chat(world, "* [areatype]")
/client/proc/cmd_admin_dress(var/mob/living/carbon/human/M in GLOB.mob_list)
/client/proc/cmd_admin_dress(mob/living/carbon/human/M in GLOB.human_list)
set category = "Event"
set name = "Select equipment"
+1 -1
View File
@@ -84,7 +84,7 @@
var/obj/item/slot_item_hand = H.get_item_by_slot(slot_r_hand)
H.unEquip(slot_item_hand)
var /obj/item/multisword/pure_evil/multi = new(H)
var/obj/item/multisword/pure_evil/multi = new(H)
H.equip_to_slot_or_del(multi, slot_r_hand)
var/obj/item/card/id/W = new(H)
+8 -3
View File
@@ -826,7 +826,10 @@ Traitors and the like can also be revived with the previous role mostly intact.
else
SSshuttle.emergency.canRecall = FALSE
SSshuttle.emergency.request()
if(seclevel2num(get_security_level()) >= SEC_LEVEL_RED)
SSshuttle.emergency.request(coefficient = 0.5, redAlert = TRUE)
else
SSshuttle.emergency.request()
feedback_add_details("admin_verb","CSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-called the emergency shuttle.")
@@ -979,7 +982,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/role_string
var/obj_count = 0
var/obj_string = ""
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(!isLivingSSD(H))
continue
mins_ssd = round((world.time - H.last_logout) / 600)
@@ -1016,7 +1020,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
msg += "AFK Players:<BR><TABLE border='1'>"
msg += "<TR><TD><B>Key</B></TD><TD><B>Real Name</B></TD><TD><B>Job</B></TD><TD><B>Mins AFK</B></TD><TD><B>Special Role</B></TD><TD><B>Area</B></TD><TD><B>PPN</B></TD><TD><B>Cryo</B></TD></TR>"
var/mins_afk
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.client == null || H.stat == DEAD) // No clientless or dead
continue
mins_afk = round(H.client.inactivity / 600)
@@ -194,7 +194,7 @@
to_chat(user, "<span class='notice'>The demons do not respond to your summon. Perhaps you should try again later.</span>")
/obj/item/antag_spawner/slaughter_demon/spawn_antag(client/C, turf/T, type = "", mob/user)
var /obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(T)
var/mob/living/simple_animal/slaughter/S = new demon_type(holder)
S.vialspawned = TRUE
S.holder = holder
@@ -41,9 +41,8 @@
A.common_radio.channels.Remove("Syndicate") // De-traitored AIs can still state laws over the syndicate channel without this
A.laws.sorted_laws = A.laws.inherent_laws.Copy() // AI's 'notify laws' button will still state a law 0 because sorted_laws contains it
A.show_laws()
A.malf_picker.remove_malf_verbs(A)
A.verbs -= /mob/living/silicon/ai/proc/choose_modules
qdel(A.malf_picker)
A.remove_malf_abilities()
QDEL_NULL(A.malf_picker)
if(owner.som)
var/datum/mindslaves/slaved = owner.som
@@ -400,7 +399,7 @@
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
var/responses = jointext(GLOB.syndicate_code_response, ", ")
var message = "<br><b>The code phrases were:</b> <span class='bluetext'>[phrases]</span><br>\
var/message = "<br><b>The code phrases were:</b> <span class='bluetext'>[phrases]</span><br>\
<b>The code responses were:</b> <span class='redtext'>[responses]</span><br>"
return message
@@ -154,6 +154,9 @@
display_name = "corset, blue"
path = /obj/item/clothing/accessory/corset/blue
/datum/gear/accessory/armband/job
subtype_path = /datum/gear/accessory/armband/job
subtype_cost_overlap = FALSE
/datum/gear/accessory/armband_red
display_name = "armband"
@@ -163,37 +166,37 @@
display_name = "armband, blue-yellow"
path = /obj/item/clothing/accessory/armband/yb
/datum/gear/accessory/armband_sec
/datum/gear/accessory/armband/job/sec
display_name = " armband, security"
path = /obj/item/clothing/accessory/armband/sec
allowed_roles = list("Head of Security", "Warden", "Detective", "Security Officer", "Brig Physician", "Security Pod Pilot")
/datum/gear/accessory/armband_cargo
/datum/gear/accessory/armband/job/cargo
display_name = "cargo armband"
path = /obj/item/clothing/accessory/armband/cargo
allowed_roles = list("Quartermaster","Cargo Technician", "Shaft Miner")
/datum/gear/accessory/armband_medical
/datum/gear/accessory/armband/job/medical
display_name = "armband, medical"
path = /obj/item/clothing/accessory/armband/med
allowed_roles = list("Chief Medical Officer", "Medical Doctor", "Coroner", "Paramedic", "Brig Physician")
/datum/gear/accessory/armband_emt
/datum/gear/accessory/armband/job/emt
display_name = "armband, EMT"
path = /obj/item/clothing/accessory/armband/medgreen
allowed_roles = list("Paramedic", "Brig Physician")
/datum/gear/accessory/armband_engineering
/datum/gear/accessory/armband/job/engineering
display_name = "armband, engineering"
path = /obj/item/clothing/accessory/armband/engine
allowed_roles = list("Chief Engineer","Station Engineer", "Life Support Specialist")
/datum/gear/accessory/armband_hydro
/datum/gear/accessory/armband/job/hydro
display_name = "armband, hydroponics"
path = /obj/item/clothing/accessory/armband/hydro
allowed_roles = list("Botanist")
/datum/gear/accessory/armband_sci
/datum/gear/accessory/armband/job/sci
display_name = "armband, science"
path = /obj/item/clothing/accessory/armband/science
allowed_roles = list("Research Director","Scientist", "Roboticist")
@@ -42,11 +42,6 @@
display_name = "fedora, brown"
path = /obj/item/clothing/head/fedora/brownfedora
/datum/gear/hat/beretsec
display_name = "security beret"
path = /obj/item/clothing/head/beret/sec
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
/datum/gear/hat/capcsec
display_name = "security corporate cap"
path = /obj/item/clothing/head/soft/sec/corp
@@ -113,32 +108,54 @@
display_name = "cowboy hat, pink"
path = /obj/item/clothing/head/cowboyhat/pink
/datum/gear/hat/pr_beret
//Berets Refactor
//Defining all Job Berets as no-overlap
//Somehow this doesn't break the DB.
/datum/gear/hat/beret/job
subtype_path = /datum/gear/hat/beret/job
subtype_cost_overlap = FALSE
/datum/gear/hat/beret/purple
display_name = "beret, purple"
path = /obj/item/clothing/head/beret/purple_normal
/datum/gear/hat/bl_beret
/datum/gear/hat/beret/black
display_name = "beret, black"
path = /obj/item/clothing/head/beret/black
/datum/gear/hat/blu_beret
/datum/gear/hat/beret/blue
display_name = "beret, blue"
path = /obj/item/clothing/head/beret/blue
/datum/gear/hat/red_beret
/datum/gear/hat/beret/red
display_name = "beret, red"
path = /obj/item/clothing/head/beret
/datum/gear/hat/sci_beret
/datum/gear/hat/beret/job/sec
display_name = "security beret"
path = /obj/item/clothing/head/beret/sec
allowed_roles = list("Head of Security", "Warden", "Security Officer", "Security Pod Pilot")
/datum/gear/hat/beret/job/sci
display_name = "science beret"
path = /obj/item/clothing/head/beret/sci
allowed_roles = list("Research Director", "Scientist")
/datum/gear/hat/med_beret
/datum/gear/hat/beret/job/med
display_name = "medical beret"
path = /obj/item/clothing/head/beret/med
allowed_roles = list("Chief Medical Officer", "Medical Doctor" , "Virologist", "Brig Physician" , "Coroner")
/datum/gear/hat/beret/job/eng
display_name = "engineering beret"
path = /obj/item/clothing/head/beret/eng
allowed_roles = list("Chief Engineer", "Station Engineer")
/datum/gear/hat/beret/job/atmos
display_name = "atmospherics beret"
path = /obj/item/clothing/head/beret/atmos
allowed_roles = list("Chief Engineer", "Life Support Specialist")
/datum/gear/hat/surgicalcap_purple
display_name = "surgical cap, purple"
path = /obj/item/clothing/head/surgery/purple
@@ -175,32 +175,36 @@
display_name = "regal shawl"
path = /obj/item/clothing/suit/mantle/regal
/datum/gear/suit/captain_cloak
/datum/gear/suit/mantle/job
subtype_path = /datum/gear/suit/mantle/job
subtype_cost_overlap = FALSE
/datum/gear/suit/mantle/job/captain
display_name = "mantle, captain"
path = /obj/item/clothing/suit/mantle/armor/captain
allowed_roles = list("Captain")
/datum/gear/suit/ce_mantle
/datum/gear/suit/mantle/job/ce
display_name = "mantle, chief engineer"
path = /obj/item/clothing/suit/mantle/chief_engineer
allowed_roles = list("Chief Engineer")
/datum/gear/suit/cmo_mantle
/datum/gear/suit/mantle/job/cmo
display_name = "mantle, chief medical officer"
path = /obj/item/clothing/suit/mantle/labcoat/chief_medical_officer
allowed_roles = list("Chief Medical Officer")
/datum/gear/suit/armored_shawl
/datum/gear/suit/mantle/job/hos
display_name = "mantle, head of security"
path = /obj/item/clothing/suit/mantle/armor
allowed_roles = list("Head of Security")
/datum/gear/suit/hop_shawl
/datum/gear/suit/mantle/job/hop
display_name = "mantle, head of personnel"
path = /obj/item/clothing/suit/mantle/armor/head_of_personnel
allowed_roles = list("Head of Personnel")
/datum/gear/suit/rd_mantle
/datum/gear/suit/mantle/job/rd
display_name = "mantle, research director"
path = /obj/item/clothing/suit/mantle/labcoat
allowed_roles = list("Research Director")
+1 -1
View File
@@ -349,7 +349,7 @@
to_chat(user, "<span class='notice'>You modify the appearance of [target].</span>")
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(
+11 -1
View File
@@ -59,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)
+4 -1
View File
@@ -2,7 +2,10 @@
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/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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -33,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)
+20 -7
View File
@@ -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
+9 -5
View File
@@ -460,8 +460,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 +540,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 +753,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 = "<span class='[SSradio.frequency_span_class(PUB_FREQ)]'><b>\[[get_frequency_name(PUB_FREQ)]\]</b> <span class='name'>", part_b = "</span> <span class='message'>")
qdel(src)
@@ -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."
+5
View File
@@ -168,6 +168,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)
@@ -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?")
+2
View File
@@ -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)
+5
View File
@@ -150,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
+1 -1
View File
@@ -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)
@@ -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, "<span class='userdanger'>You have an overwhelming desire to kill [L]. [L.p_they(TRUE)] [L.p_have()] been marked red! Go kill [L.p_them()]!</span>")
H.put_in_hands(new /obj/item/kitchen/knife/butcher(H))
@@ -383,7 +383,10 @@
var/mob/living/L = target
if(!L.anchored)
L.visible_message("<span class='danger'>[L] is snagged by [firer]'s hook!</span>")
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)
+1 -1
View File
@@ -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)
@@ -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)
@@ -134,8 +134,6 @@
S.message = "<span class='[span]'>[S.message]</span>"
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) \
|| HAS_TRAIT(src, TRAIT_JESTER))
@@ -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)
+11 -17
View File
@@ -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
@@ -851,13 +852,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
to_chat(src, "<span class='notice'>Switched to [network] camera network.</span>")
//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"
@@ -1028,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, "<span class='notice'>You are already in your Main Core.</span>")
return
apc.malfvacate()
//Toggles the luminosity and applies it by re-entereing the camera.
/mob/living/silicon/ai/proc/toggle_camera_light()
@@ -1244,8 +1229,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))
@@ -354,3 +354,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, "<span class='warning'>You begin decompiling the other drone.</span>")
if(!do_after(user, 5 SECONDS, target = loc))
to_chat(user, "<span class='warning'>You need to remain still while decompiling such a large object.</span>")
return
if(QDELETED(src) || QDELETED(user))
return ..()
to_chat(user, "<span class='warning'>You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.</span>")
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 ..()
@@ -151,15 +151,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 +166,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("<span class='notice'>[src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.</span>","<span class='warning'>It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.</span>")
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, "<span class='warning'>You begin decompiling the other drone.</span>")
if(!do_after(D, 50, target = target))
to_chat(D, "<span class='warning'>You need to remain still while decompiling such a large object.</span>")
return
if(!M || !D) return
to_chat(D, "<span class='warning'>You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.</span>")
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, "<span class='notice'>You deploy your decompiler and clear out the contents of \the [T].</span>")
@@ -353,11 +261,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]--
@@ -1150,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))
@@ -756,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)
@@ -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("<span class='notice'>[user] sucks [src] into its decompiler. There's a horrible crunching noise.</span>", \
"<span class='warning'>It's a bit of a struggle, but you manage to suck [src] into your decompiler. It makes a series of visceral crunching noises.</span>")
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 ..()
@@ -234,3 +234,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("<span class='notice'>[user] sucks [src] into its decompiler. There's a horrible crunching noise.</span>", \
"<span class='warning'>It's a bit of a struggle, but you manage to suck [src] into your decompiler. It makes a series of visceral crunching noises.</span>")
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 ..()
@@ -31,8 +31,7 @@
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("<span class='danger'>[src] consumes [K] whole!</span>")
@@ -40,8 +39,6 @@
health += 10
qdel(K)
break
cycles = 0
cycles++
/mob/living/simple_animal/hostile/headcrab/OpenFire(atom/A)
if(check_friendly_fire)
@@ -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)
@@ -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
+1 -1
View File
@@ -90,7 +90,7 @@
if(adminonly)
question = "(<font color='#997700'>Admin only poll</font>) " + question
var output = "<!DOCTYPE html><html><body>"
var/output = "<!DOCTYPE html><html><body>"
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.Execute()
+2 -5
View File
@@ -82,14 +82,11 @@
O.notify_ai(1)
if(O.mind && O.mind.assigned_role == "Cyborg")
if(O.mind.role_alt_title == "Android")
if(O.mind.role_alt_title == "Robot")
O.mmi = new /obj/item/mmi/robotic_brain(O)
else if(O.mind.role_alt_title == "Robot")
O.mmi = null //Robots do not have removable brains.
else
O.mmi = new /obj/item/mmi(O)
if(O.mmi) O.mmi.transfer_identity(src) //Does not transfer key/client.
O.mmi.transfer_identity(src) //Does not transfer key/client.
O.update_pipe_vision()
+8 -4
View File
@@ -108,7 +108,7 @@
maptext_x = 10
if(100)
maptext_x = 8
maptext = "[current_number]" //Finally, apply the maptext
maptext = "<font face='Small Fonts'>[ticket_number]</font>"
/obj/machinery/ticket_machine/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/hand_labeler_refill))
@@ -151,8 +151,8 @@
to_chat(user, "<span class='notice'>You take a ticket from [src], looks like you're ticket number #[ticket_number]...</span>")
var/obj/item/ticket_machine_ticket/theirticket = new /obj/item/ticket_machine_ticket(get_turf(src))
theirticket.name = "Ticket #[ticket_number]"
theirticket.maptext = "<font color='#000000'>[ticket_number]</font>"
theirticket.saved_maptext = "<font color='#000000'>[ticket_number]</font>"
theirticket.maptext = "<font color='#000000' face='Small Fonts'>[ticket_number]</font>"
theirticket.saved_maptext = "<font color='#000000' face='Small Fonts'>[ticket_number]</font>"
theirticket.ticket_number = ticket_number
theirticket.source = src
theirticket.owner = user.UID()
@@ -167,9 +167,13 @@
user.adjust_fire_stacks(1)
user.IgniteMob()
// Stop AI penetrating the bureaucracy
/obj/machinery/ticket_machine/attack_ai(mob/user)
return
/obj/item/ticket_machine_ticket
name = "Ticket"
desc = "A ticket which shows your place in the Head of Personnel's line. Made from Nanotrasen patented NanoPaper®. Though solid, its form seems to shimmer slightly. Feels (and burns) just like the real thing."
desc = "A ticket which shows your place in the Head of Personnel's line. Made from Nanotrasen patented NanoPaper. Though solid, its form seems to shimmer slightly. Feels (and burns) just like the real thing."
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "ticket"
maptext_x = 7
+2 -1
View File
@@ -1052,7 +1052,8 @@
occupier.eyeobj.name = "[occupier.name] (AI Eye)"
if(malf.parent)
qdel(malf)
occupier.verbs += /mob/living/silicon/ai/proc/corereturn
var/datum/action/innate/ai/return_to_core/R = new
R.Grant(occupier)
occupier.cancel_camera()
if((seclevel2num(get_security_level()) == SEC_LEVEL_DELTA) && malf.nuking)
for(var/obj/item/pinpointer/point in GLOB.pinpointer_list)
+6
View File
@@ -634,6 +634,12 @@
shatter()
return ..()
/obj/item/light/decompile_act(obj/item/matter_decompiler/C, mob/user)
C.stored_comms["glass"] += 1
C.stored_comms["metal"] += 1
qdel(src)
return TRUE
/obj/item/light/tube
name = "light tube"
desc = "A replacement light tube."
@@ -424,7 +424,7 @@
update_icon()
if(istype(loc, /mob/living/carbon))
var /mob/living/carbon/M = loc
var/mob/living/carbon/M = loc
if(src == M.machine)
update_dat()
M << browse("<TITLE>Temperature Gun Configuration</TITLE><HR>[dat]", "window=tempgun;size=510x102")
+2 -1
View File
@@ -65,7 +65,8 @@
/obj/item/gun/syringe/attackby(obj/item/A, mob/user, params, show_msg = TRUE)
if(istype(A, /obj/item/reagent_containers/syringe))
if(length(syringes) < max_syringes)
var/in_clip = length(syringes) + (chambered.BB ? 1 : 0)
if(in_clip < max_syringes)
if(!user.unEquip(A))
return
to_chat(user, "<span class='notice'>You load [A] into \the [src]!</span>")
@@ -38,7 +38,7 @@
/datum/chemical_reaction/slimemonkey/on_reaction(datum/reagents/holder)
feedback_add_details("slime_cores_used","[type]")
for(var/i = 1, i <= 3, i++)
var /obj/item/reagent_containers/food/snacks/monkeycube/M = new /obj/item/reagent_containers/food/snacks/monkeycube
var/obj/item/reagent_containers/food/snacks/monkeycube/M = new /obj/item/reagent_containers/food/snacks/monkeycube
M.forceMove(get_turf(holder.my_atom))
//Green
@@ -42,6 +42,13 @@
var/image/lid = image(icon, src, "lid_bottle")
overlays += lid
/obj/item/reagent_containers/glass/bottle/decompile_act(obj/item/matter_decompiler/C, mob/user)
if(!reagents.total_volume)
C.stored_comms["glass"] += 3
qdel(src)
return TRUE
return ..()
/obj/item/reagent_containers/glass/bottle/toxin
name = "toxin bottle"
desc = "A small bottle containing toxic compounds."
+1 -1
View File
@@ -265,7 +265,7 @@
update()
return
/obj/machinery/disposal/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
/obj/machinery/disposal/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "DisposalBin", name, 300, 250, master_ui, state)
+2 -2
View File
@@ -9,10 +9,10 @@
/obj/machinery/computer/shuttle/ert/Topic(href, href_list)
if(href_list["move"])
var/authorized_roles = list(SPECIAL_ROLE_ERT, SPECIAL_ROLE_DEATHSQUAD)
if(!((usr.mind.assigned_role in authorized_roles) || is_admin(usr)))
if(!((usr.mind?.assigned_role in authorized_roles) || is_admin(usr)))
message_admins("Potential ERT shuttle hijack, ERT shuttle moved by unauthorized user: [key_name_admin(usr)]")
..()
/obj/machinery/computer/camera_advanced/shuttle_docker/ert
name = "specops navigation computer"
@@ -61,3 +61,16 @@ GLOBAL_LIST_INIT(default_map_traits, MAP_TRANSITION_CONFIG)
/proc/level_name_to_num(name)
var/datum/space_level/S = GLOB.space_manager.get_zlev_by_name(name)
return S.zpos
/**
* Proc to get a list of all the linked-together Z-Levels
*
* Returns a list of zlevel numbers which can be accessed from travelling space naturally
*/
/proc/get_all_linked_levels_zpos()
var/list/znums = list()
for(var/i in GLOB.space_manager.z_list)
var/datum/space_level/SL = GLOB.space_manager.z_list[i]
if(SL.linkage == CROSSLINKED)
znums |= SL.zpos
return znums
+2 -2
View File
@@ -14,13 +14,13 @@
if("track")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
var/mob/living/carbon/human/H = locate(params["track"]) in GLOB.mob_list
var/mob/living/carbon/human/H = locate(params["track"]) in GLOB.human_list
if(hassensorlevel(H, SUIT_SENSOR_TRACKING))
AI.ai_actual_track(H)
return TRUE
/datum/tgui_module/crew_monitor/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
/datum/tgui_module/crew_monitor/tgui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/tgui_state/state = GLOB.tgui_default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
// The 557 may seem random, but its the perfectsize for margins on the nanomap