diff --git a/baystation12.dme b/baystation12.dme index 9ad0f589c3..9a80618226 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -943,11 +943,13 @@ #include "code\modules\events\comms_blackout.dm" #include "code\modules\events\communications_blackout.dm" #include "code\modules\events\disease_outbreak.dm" +#include "code\modules\events\dust.dm" #include "code\modules\events\electrical_storm.dm" #include "code\modules\events\event.dm" #include "code\modules\events\event_container.dm" #include "code\modules\events\event_dynamic.dm" #include "code\modules\events\event_manager.dm" +#include "code\modules\events\gravity.dm" #include "code\modules\events\grid_check.dm" #include "code\modules\events\infestation.dm" #include "code\modules\events\ion_storm.dm" diff --git a/code/defines/procs/announce.dm b/code/defines/procs/announce.dm index 3e5454d8ac..9db7092928 100644 --- a/code/defines/procs/announce.dm +++ b/code/defines/procs/announce.dm @@ -15,17 +15,17 @@ log = do_log newscast = do_newscast -/datum/announcement/priority/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0) +/datum/announcement/priority/New(var/do_log = 1, var/new_sound = 'sound/misc/notice2.ogg', var/do_newscast = 0) ..(do_log, new_sound, do_newscast) title = "Priority Announcement" announcement_type = "Priority Announcement" -/datum/announcement/priority/command/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0) +/datum/announcement/priority/command/New(var/do_log = 1, var/new_sound = 'sound/misc/notice2.ogg', var/do_newscast = 0) ..(do_log, new_sound, do_newscast) title = "[command_name()] Update" announcement_type = "[command_name()] Update" -/datum/announcement/priority/security/New(var/do_log = 1, var/new_sound = sound('sound/misc/notice2.ogg'), var/do_newscast = 0) +/datum/announcement/priority/security/New(var/do_log = 1, var/new_sound = 'sound/misc/notice2.ogg', var/do_newscast = 0) ..(do_log, new_sound, do_newscast) title = "Security Announcement" announcement_type = "Security Announcement" @@ -33,8 +33,8 @@ /datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast) if(!message) return - var/tmp/message_title = new_title ? new_title : title - var/tmp/message_sound = new_sound ? sound(new_sound) : sound + var/message_title = new_title ? new_title : title + var/message_sound = new_sound ? new_sound : sound message = sanitize(message, extra = 0) message_title = sanitizeSafe(message_title) @@ -102,8 +102,8 @@ datum/announcement/proc/Sound(var/message_sound) PlaySound(message_sound) datum/announcement/priority/Sound(var/message_sound) - if(sound) - world << sound + if(message_sound) + world << message_sound datum/announcement/priority/command/Sound(var/message_sound) PlaySound(message_sound) diff --git a/code/game/antagonist/antagonist_build.dm b/code/game/antagonist/antagonist_build.dm index f0f92c62b7..34631d36fb 100644 --- a/code/game/antagonist/antagonist_build.dm +++ b/code/game/antagonist/antagonist_build.dm @@ -28,7 +28,9 @@ // This could use work. if(flags & ANTAG_CLEAR_EQUIPMENT) for(var/obj/item/thing in player.contents) - del(thing) + player.drop_from_inventory(thing) + if(thing.loc != player) + del(thing) return 1 if(flags & ANTAG_SET_APPEARANCE) @@ -80,6 +82,7 @@ /datum/antagonist/proc/create_id(var/assignment, var/mob/living/carbon/human/player) var/obj/item/weapon/card/id/W = new id_type(player) + if(!W) return W.name = "[player.real_name]'s ID Card" W.access |= default_access W.assignment = "[assignment]" diff --git a/code/game/antagonist/outsider/deathsquad.dm b/code/game/antagonist/outsider/deathsquad.dm index 05fb6d1ec9..73c2c7fd78 100644 --- a/code/game/antagonist/outsider/deathsquad.dm +++ b/code/game/antagonist/outsider/deathsquad.dm @@ -44,8 +44,9 @@ var/datum/antagonist/deathsquad/deathsquad player.implant_loyalty(player) var/obj/item/weapon/card/id/id = create_id("Asset Protection", player) - id.access |= get_all_accesses() - id.icon_state = "centcom" + if(id) + id.access |= get_all_accesses() + id.icon_state = "centcom" create_radio(DTH_FREQ, player) /datum/antagonist/deathsquad/apply(var/datum/mind/player) diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm index 9bfdf9f0b6..e1fda4965c 100644 --- a/code/game/dna/dna2_helpers.dm +++ b/code/game/dna/dna2_helpers.dm @@ -165,7 +165,7 @@ if((0 < beard) && (beard <= facial_hair_styles_list.len)) H.f_style = facial_hair_styles_list[beard] - H.update_body(0) + H.force_update_limbs() H.update_hair() return 1 diff --git a/code/game/gamemodes/events/dust.dm b/code/game/gamemodes/events/dust.dm index f2c510b9b9..2e8b3b1328 100644 --- a/code/game/gamemodes/events/dust.dm +++ b/code/game/gamemodes/events/dust.dm @@ -80,10 +80,11 @@ The "dust" will damage the hull of the station causin minor hull breaches. startx = (TRANSITIONEDGE+1) endy = rand(TRANSITIONEDGE,world.maxy-TRANSITIONEDGE) endx = world.maxx-TRANSITIONEDGE - var/goal = locate(endx, endy, 1) + var/z_level = pick(config.station_levels) + var/goal = locate(endx, endy, z_level) src.x = startx src.y = starty - src.z = pick(config.station_levels) + src.z = z_level spawn(0) walk_towards(src, goal, 1) return diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index 544776d144..8ad65194d1 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -98,8 +98,8 @@ var/global/datum/controller/gameticker/ticker src.mode = config.pick_mode(master_mode) if(!mode_started && !src.mode.can_start()) world << "Unable to start [mode.name]. Not enough players, [mode.required_players] players needed. Reverting to pre-game lobby." - del(mode) current_state = GAME_STATE_PREGAME + mode = null job_master.ResetOccupations() return 0 diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 9b5cfaa526..d537d113f9 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -189,7 +189,7 @@ var/obj/item/stack/stack = eating stack.use(max(1, round(total_used/mass_per_sheet))) // Always use at least 1 to prevent infinite materials. else - user.drop_item(O) + user.remove_from_mob(O) del(O) updateUsrDialog() diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index a038ece414..e56e544649 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -125,7 +125,7 @@ if(is_type_in_list(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already. user << "You attach \the [W] into the assembly inner circuits." upgrades += W - user.drop_item(W) + user.remove_from_mob(W) W.loc = src return diff --git a/code/game/machinery/seed_extractor.dm b/code/game/machinery/seed_extractor.dm index 4778ac13ea..4418586e9d 100644 --- a/code/game/machinery/seed_extractor.dm +++ b/code/game/machinery/seed_extractor.dm @@ -11,7 +11,7 @@ obj/machinery/seed_extractor/attackby(var/obj/item/O as obj, var/mob/user as mob // Fruits and vegetables. if(istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown) || istype(O, /obj/item/weapon/grown)) - user.drop_item(O) + user.remove_from_mob(O) var/datum/seed/new_seed_type if(istype(O, /obj/item/weapon/grown)) diff --git a/code/game/objects/structures/coathanger.dm b/code/game/objects/structures/coathanger.dm index ac3e89000c..a54c40b755 100644 --- a/code/game/objects/structures/coathanger.dm +++ b/code/game/objects/structures/coathanger.dm @@ -21,8 +21,7 @@ if (can_hang && !coat) user.visible_message("[user] hangs [W] on \the [src].", "You hang [W] on the \the [src]") coat = W - user.drop_item(src) - coat.loc = src + user.drop_from_inventory(coat, src) update_icon() else user << "You cannot hang [W] on [src]" diff --git a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm index 0728a9befa..8dacfa4c40 100644 --- a/code/game/objects/structures/crates_lockers/closets/fireaxe.dm +++ b/code/game/objects/structures/crates_lockers/closets/fireaxe.dm @@ -61,7 +61,7 @@ user << "\red Unwield the axe first." return fireaxe = O - user.drop_item(O) + user.remove_from_mob(O) src.contents += O user << "\blue You place the fire axe back in the [src.name]." update_icon() diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 6b857ae4cf..d14ddf1405 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -431,7 +431,7 @@ user.visible_message("The [src] was sliced apart by [user]!") destroy() - user.drop_item(src) + user.drop_item(src.loc) return /obj/structure/table/proc/straight_table_check(var/direction) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index d83d4da747..41c27789a2 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -84,7 +84,8 @@ var/list/admin_verbs_admin = list( /client/proc/empty_ai_core_toggle_latejoin, /client/proc/aooc, /client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */ - /client/proc/change_human_appearance_self /* Allows the human-based mob itself change its basic appearance */ + /client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */ + /client/proc/change_security_level ) var/list/admin_verbs_ban = list( /client/proc/unban_panel, @@ -762,6 +763,17 @@ var/list/admin_verbs_mentor = list( 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! +/client/proc/change_security_level() + set name = "Set security level" + set desc = "Sets the station security level" + set category = "Admin" + + if(!check_rights(R_ADMIN)) return + var sec_level = input(usr, "It's currently code [get_security_level()].", "Select Security Level") as null|anything in (list("green","blue","red","delta")-get_security_level()) + if(alert("Switch from code [get_security_level()] to code [sec_level]?","Change security level?","Yes","No") == "Yes") + set_security_level(sec_level) + log_admin("[key_name(usr)] changed the security level to code [sec_level].") + //---- bs12 verbs ---- diff --git a/code/modules/events/communications_blackout.dm b/code/modules/events/communications_blackout.dm index 181f66d9c0..fabfdd3336 100644 --- a/code/modules/events/communications_blackout.dm +++ b/code/modules/events/communications_blackout.dm @@ -12,7 +12,7 @@ A << "
" if(prob(30)) //most of the time, we don't want an announcement, so as to allow AIs to fake blackouts. - command_announcement.Announce(alert, new_sound = 'sound/misc/interference.ogg') + command_announcement.Announce(alert, new_sound = sound('sound/misc/interference.ogg', volume=50)) /datum/event/communications_blackout/start() diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm new file mode 100644 index 0000000000..12be475fc8 --- /dev/null +++ b/code/modules/events/dust.dm @@ -0,0 +1,22 @@ +/datum/event/dust + startWhen = 10 + endWhen = 30 + +/datum/event/dust/announce() + command_announcement.Announce("The station is now passing through a belt of space dust.", "Dust Alert") + +/datum/event/dust/start() + dust_swarm(get_severity()) + +/datum/event/dust/end() + command_announcement.Announce("The station has now passed through the belt of space dust.", "Dust Notice") + +/datum/event/dust/proc/get_severity() + switch(severity) + if(EVENT_LEVEL_MUNDANE) + return "weak" + if(EVENT_LEVEL_MODERATE) + return prob(80) ? "norm" : "strong" + if(EVENT_LEVEL_MAJOR) + return "super" + return "weak" diff --git a/code/modules/events/event.dm b/code/modules/events/event.dm index 408c85900e..0b69dc89bb 100644 --- a/code/modules/events/event.dm +++ b/code/modules/events/event.dm @@ -37,16 +37,6 @@ return total_weight -/datum/event_meta/alien/get_weight(var/list/active_with_role) - if(config.aliens_allowed) - return ..(active_with_role) - return 0 - -/datum/event_meta/ninja/get_weight(var/list/active_with_role) - if(config.ninjas_allowed) - return ..(active_with_role) - return 0 - /datum/event //NOTE: Times are measured in master controller ticks! var/startWhen = 0 //When in the lifetime to call start(). var/announceWhen = 0 //When in the lifetime to call announce(). diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index df392cfada..54e2da314e 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -124,14 +124,15 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT available_events = list( // Severity level, event name, even type, base weight, role weights, one shot, min weight, max weight. Last two only used if set and non-zero new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Nothing", /datum/event/nothing, 100), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "PDA Spam", /datum/event/pda_spam, 0, list(ASSIGNMENT_ANY = 4), 0, 25, 50), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Lotto", /datum/event/money_lotto, 0, list(ASSIGNMENT_ANY = 1), 1, 5, 15), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Hacker", /datum/event/money_hacker, 0, list(ASSIGNMENT_ANY = 4), 1, 10, 25), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Economic News", /datum/event/economic_event, 300), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mundane News", /datum/event/mundane_news, 300), - new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Lost Carp", /datum/event/carp_migration, 20, list(ASSIGNMENT_SECURITY = 10), 1), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Brand Intelligence",/datum/event/brand_intelligence,20, list(ASSIGNMENT_JANITOR = 25), 1), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Economic News", /datum/event/economic_event, 300), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Hacker", /datum/event/money_hacker, 0, list(ASSIGNMENT_ANY = 4), 1, 10, 25), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Money Lotto", /datum/event/money_lotto, 0, list(ASSIGNMENT_ANY = 1), 1, 5, 15), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Lost Carp", /datum/event/carp_migration, 20, list(ASSIGNMENT_SECURITY = 10), 1), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Mundane News", /datum/event/mundane_news, 300), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "PDA Spam", /datum/event/pda_spam, 0, list(ASSIGNMENT_ANY = 4), 0, 25, 50), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Space Dust", /datum/event/dust , 30, list(ASSIGNMENT_ENGINEER = 5), 0, 0, 50), + new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Trivial News", /datum/event/trivial_news, 400), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Vermin Infestation",/datum/event/infestation, 100, list(ASSIGNMENT_JANITOR = 100)), new /datum/event_meta(EVENT_LEVEL_MUNDANE, "Wallrot", /datum/event/wallrot, 0, list(ASSIGNMENT_ENGINEER = 30, ASSIGNMENT_GARDENER = 50)), ) @@ -140,30 +141,32 @@ var/global/list/severity_to_string = list(EVENT_LEVEL_MUNDANE = "Mundane", EVENT severity = EVENT_LEVEL_MODERATE available_events = list( new /datum/event_meta(EVENT_LEVEL_MODERATE, "Nothing", /datum/event/nothing, 1230), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, 100, list(ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_SECURITY = 20), 1), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 20, list(ASSIGNMENT_SECURITY = 20)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space vines", /datum/event/spacevine, 200, list(ASSIGNMENT_ENGINEER = 10)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_shower, 0, list(ASSIGNMENT_ENGINEER = 20)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 500, list(ASSIGNMENT_AI = 150, ASSIGNMENT_SECURITY = 120)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 100)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 200, list(ASSIGNMENT_ENGINEER = 60)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 250, list(ASSIGNMENT_ENGINEER = 20, ASSIGNMENT_JANITOR = 150)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Radiation Storm", /datum/event/radiation_storm, 0, list(ASSIGNMENT_MEDICAL = 50), 1), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Appendicitis", /datum/event/spontaneous_appendicitis, 0, list(ASSIGNMENT_MEDICAL = 10), 1), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 150)), - new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Carp School", /datum/event/carp_migration, 100, list(ASSIGNMENT_ENGINEER = 10, ASSIGNMENT_SECURITY = 20), 1), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Communication Blackout", /datum/event/communications_blackout, 500, list(ASSIGNMENT_AI = 150, ASSIGNMENT_SECURITY = 120)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Electrical Storm", /datum/event/electrical_storm, 250, list(ASSIGNMENT_ENGINEER = 20, ASSIGNMENT_JANITOR = 150)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gravity Failure", /datum/event/gravity, 75, list(ASSIGNMENT_ENGINEER = 60)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Grid Check", /datum/event/grid_check, 200, list(ASSIGNMENT_SCIENTIST = 10)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ionstorm, 0, list(ASSIGNMENT_AI = 50, ASSIGNMENT_CYBORG = 50, ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_SCIENTIST = 5)), - new /datum/event_meta/alien(EVENT_LEVEL_MODERATE, "Random Antagonist", /datum/event/random_antag, 2.5, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Meteor Shower", /datum/event/meteor_shower, 0, list(ASSIGNMENT_ENGINEER = 20)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Prison Break", /datum/event/prison_break, 0, list(ASSIGNMENT_SECURITY = 100)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Radiation Storm", /datum/event/radiation_storm, 0, list(ASSIGNMENT_MEDICAL = 50), 1), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Random Antagonist", /datum/event/random_antag, 2.5, list(ASSIGNMENT_SECURITY = 1), 1, 0, 5), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Rogue Drones", /datum/event/rogue_drone, 20, list(ASSIGNMENT_SECURITY = 20)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Space Dust", /datum/event/dust, 30, list(ASSIGNMENT_ENGINEER = 5)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 150)), ) /datum/event_container/major severity = EVENT_LEVEL_MAJOR available_events = list( new /datum/event_meta(EVENT_LEVEL_MAJOR, "Nothing", /datum/event/nothing, 1320), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 3), 1), - new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 30), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 60), 1), + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 3), 1), new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 3), 1), + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Space Vines", /datum/event/spacevine, 0, list(ASSIGNMENT_ENGINEER = 15), 1), + new /datum/event_meta(EVENT_LEVEL_MAJOR, "Viral Infection", /datum/event/viral_infection, 0, list(ASSIGNMENT_MEDICAL = 30), 1), ) diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm index 2cc225eaf6..0dbe3a5017 100644 --- a/code/modules/events/event_dynamic.dm +++ b/code/modules/events/event_dynamic.dm @@ -201,7 +201,7 @@ var/list/event_last_fired = list() if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "medical robot module") active_with_role["Medical"]++ - if(M.mind.assigned_role in list("Chief Medical Officer", "Medical Doctor")) + if(M.mind.assigned_role in medical_positions) active_with_role["Medical"]++ if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "security robot module") diff --git a/code/modules/events/gravity.dm b/code/modules/events/gravity.dm new file mode 100644 index 0000000000..078e632842 --- /dev/null +++ b/code/modules/events/gravity.dm @@ -0,0 +1,24 @@ +/datum/event/gravity + announceWhen = 5 + +/datum/event/gravity/setup() + endWhen = rand(15, 60) + +/datum/event/gravity/announce() + command_announcement.Announce("Feedback surge detected in mass-distributions systems. Artificial gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes.", "Gravity Failure") + +/datum/event/gravity/start() + gravity_is_on = 0 + for(var/area/A in world) + if(A.z in config.station_levels) + A.gravitychange(gravity_is_on, A) + +/datum/event/gravity/end() + if(!gravity_is_on) + gravity_is_on = 1 + + for(var/area/A in world) + if(A.z in config.station_levels) + A.gravitychange(gravity_is_on, A) + + command_announcement.Announce("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.", "Gravity Restored") diff --git a/code/modules/events/meteors.dm b/code/modules/events/meteors.dm index 33bee714ff..45d59ca8cd 100644 --- a/code/modules/events/meteors.dm +++ b/code/modules/events/meteors.dm @@ -1,12 +1,10 @@ -//cael - two events here - //meteor storms are much heavier /datum/event/meteor_wave startWhen = 6 endWhen = 33 /datum/event/meteor_wave/setup() - endWhen = rand(10,25) * 3 + endWhen = rand(15,30) * 3 /datum/event/meteor_wave/announce() command_announcement.Announce("Meteors have been detected on collision course with the station.", "Meteor Alert", new_sound = 'sound/AI/meteors.ogg') @@ -26,7 +24,7 @@ var/waves = 1 /datum/event/meteor_shower/setup() - waves = rand(1,4) + waves = rand(2,5) /datum/event/meteor_shower/announce() command_announcement.Announce("The station is now in a meteor shower.", "Meteor Alert") diff --git a/code/modules/events/random_antagonist.dm b/code/modules/events/random_antagonist.dm index dbdaa70983..10f8778b3b 100644 --- a/code/modules/events/random_antagonist.dm +++ b/code/modules/events/random_antagonist.dm @@ -10,4 +10,4 @@ valid_types |= antag if(valid_types.len) var/datum/antagonist/antag = pick(valid_types) - antag.random_spawn() \ No newline at end of file + antag.random_spawn() diff --git a/code/modules/holodeck/HolodeckObjects.dm b/code/modules/holodeck/HolodeckObjects.dm index 07bdccef52..7200711b60 100644 --- a/code/modules/holodeck/HolodeckObjects.dm +++ b/code/modules/holodeck/HolodeckObjects.dm @@ -277,7 +277,7 @@ del(W) return else if (istype(W, /obj/item) && get_dist(src,user)<2) - user.drop_item(src) + user.drop_item(src.loc) visible_message("[user] dunks [W] into the [src]!", 3) return diff --git a/code/modules/hydroponics/seed_storage.dm b/code/modules/hydroponics/seed_storage.dm index 469896018e..0ee7c6175e 100644 --- a/code/modules/hydroponics/seed_storage.dm +++ b/code/modules/hydroponics/seed_storage.dm @@ -225,7 +225,7 @@ /obj/machinery/seed_storage/proc/add(var/obj/item/seeds/O as obj) if (istype(O.loc, /mob)) var/mob/user = O.loc - user.drop_item(O) + user.remove_from_mob(O) else if(istype(O.loc,/obj/item/weapon/storage)) var/obj/item/weapon/storage/S = O.loc S.remove_from_storage(O, src) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 97acaf86de..0d20e00166 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -151,7 +151,7 @@ var/list/slot_equipment_priority = list( \ remove_from_mob(W) if(!W) return 1 // self destroying objects (tk, grabs) - + W.forceMove(Target) update_icons() return 1 @@ -165,7 +165,7 @@ var/list/slot_equipment_priority = list( \ /mob/proc/drop_r_hand(var/atom/Target) return drop_from_inventory(r_hand, Target) -//Drops the item in our active hand. +//Drops the item in our active hand. TODO: rename this to drop_active_hand or something /mob/proc/drop_item(var/atom/Target) if(hand) return drop_l_hand(Target) else return drop_r_hand(Target) @@ -173,11 +173,11 @@ var/list/slot_equipment_priority = list( \ /* Removes the object from any slots the mob might have, calling the appropriate icon update proc. Does nothing else. - + DO NOT CALL THIS PROC DIRECTLY. It is meant to be called only by other inventory procs. It's probably okay to use it if you are transferring the item between slots on the same mob, but chances are you're safer calling remove_from_mob() or drop_from_inventory() anyways. - + As far as I can tell the proc exists so that mobs with different inventory slots can override the search through all the slots, without having to duplicate the rest of the item dropping. */ @@ -216,7 +216,7 @@ var/list/slot_equipment_priority = list( \ O.screen_loc = null if(istype(O, /obj/item)) var/obj/item/I = O - I.dropped() + I.dropped(src) return 1 diff --git a/code/modules/mob/living/carbon/brain/brain_item.dm b/code/modules/mob/living/carbon/brain/brain_item.dm index d2aa61e635..05ceed7916 100644 --- a/code/modules/mob/living/carbon/brain/brain_item.dm +++ b/code/modules/mob/living/carbon/brain/brain_item.dm @@ -2,6 +2,9 @@ name = "brain" health = 400 //They need to live awhile longer than other organs. desc = "A piece of juicy meat found in a person's head." + organ_tag = "brain" + parent_organ = "head" + vital = 1 icon_state = "brain2" force = 1.0 w_class = 2.0 @@ -46,7 +49,7 @@ /obj/item/organ/brain/removed(var/mob/living/user) - ..() + name = "[owner.real_name]'s brain" var/mob/living/simple_animal/borer/borer = owner.has_brain_worms() @@ -57,6 +60,8 @@ if(istype(B) && istype(owner)) B.transfer_identity(owner) + ..() + /obj/item/organ/brain/replaced(var/mob/living/target) if(target.key) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 63eba6e781..da10a9ea00 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -31,10 +31,9 @@ var/d = rand(round(I.force / 4), I.force) if(istype(src, /mob/living/carbon/human)) var/mob/living/carbon/human/H = src - var/organ = H.get_organ("chest") - if (istype(organ, /obj/item/organ/external)) - var/obj/item/organ/external/temp = organ - if(temp.take_damage(d, 0)) + var/obj/item/organ/external/organ = H.get_organ("chest") + if (istype(organ)) + if(organ.take_damage(d, 0)) H.UpdateDamageIcon() H.updatehealth() else @@ -328,7 +327,7 @@ if(!item) return //Grab processing has a chance of returning null - + src.remove_from_mob(item) item.loc = src.loc diff --git a/code/modules/mob/living/carbon/human/appearance.dm b/code/modules/mob/living/carbon/human/appearance.dm index 311942ca02..e2ef586f05 100644 --- a/code/modules/mob/living/carbon/human/appearance.dm +++ b/code/modules/mob/living/carbon/human/appearance.dm @@ -117,7 +117,7 @@ g_skin = green b_skin = blue - update_body() + force_update_limbs() return 1 /mob/living/carbon/human/proc/change_skin_tone(var/tone) @@ -126,7 +126,7 @@ s_tone = tone - update_body() + force_update_limbs() return 1 /mob/living/carbon/human/proc/update_dna() @@ -186,3 +186,8 @@ /proc/q() var/mob/living/carbon/human/H = usr H.change_appearance(APPEARANCE_ALL) + +/mob/living/carbon/human/proc/force_update_limbs() + for(var/obj/item/organ/external/O in organs) + O.sync_colour_to_human(src) + update_body(0) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 9c3057c52d..1e693fd63f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -20,6 +20,9 @@ else set_species() + if(species) + name = species.get_random_name(gender) + var/datum/reagents/R = new/datum/reagents(1000) reagents = R R.my_atom = src @@ -326,8 +329,8 @@ //Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable /mob/living/carbon/human/proc/get_face_name() - var/obj/item/organ/external/head/head = get_organ("head") - if( !head || head.disfigured || (head.status & ORGAN_DESTROYED) || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible + var/obj/item/organ/external/head = get_organ("head") + if(!head || head.disfigured || (head.status & ORGAN_DESTROYED) || !real_name || (HUSK in mutations) ) //disfigured. use id-name if possible return "Unknown" return real_name @@ -1119,8 +1122,6 @@ species = all_species[new_species] - species.create_organs(src) - if(species.language) add_language(species.language) @@ -1137,6 +1138,8 @@ g_skin = 0 b_skin = 0 + species.create_organs(src) + species.handle_post_spawn(src) maxHealth = species.total_health @@ -1361,3 +1364,8 @@ U << "You pop [S]'s [current_limb.joint] back in!" S << "[U] pops your [current_limb.joint] back in!" current_limb.undislocate() + +/mob/living/carbon/human/drop_from_inventory(var/obj/item/W, var/atom/Target = null) + if(W in organs) + return + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/species/outsider/vox.dm b/code/modules/mob/living/carbon/human/species/outsider/vox.dm index 853fb4e8d4..c037d81fb7 100644 --- a/code/modules/mob/living/carbon/human/species/outsider/vox.dm +++ b/code/modules/mob/living/carbon/human/species/outsider/vox.dm @@ -45,7 +45,7 @@ "heart" = /obj/item/organ/heart, "lungs" = /obj/item/organ/lungs, "liver" = /obj/item/organ/liver, - "kidneys" = /obj/item/organ/kidney, + "kidneys" = /obj/item/organ/kidneys, "brain" = /obj/item/organ/brain, "eyes" = /obj/item/organ/eyes, "stack" = /obj/item/organ/stack/vox diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 09f3360d45..b97e8ceed6 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -110,7 +110,7 @@ "heart" = /obj/item/organ/heart, "lungs" = /obj/item/organ/lungs, "liver" = /obj/item/organ/liver, - "kidneys" = /obj/item/organ/kidney, + "kidneys" = /obj/item/organ/kidneys, "brain" = /obj/item/organ/brain, "appendix" = /obj/item/organ/appendix, "eyes" = /obj/item/organ/eyes diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 00802c5da9..0bf4978297 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -967,6 +967,11 @@ default behaviour is: /mob/living/proc/slip(var/slipped_on,stun_duration=8) return 0 +/mob/living/carbon/drop_from_inventory(var/obj/item/W, var/atom/Target = null) + if(W in internal_organs) + return + ..() + /mob/living/carbon/proc/spin(spintime, speed) spawn() var/D = dir diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e4405c5767..482ec2e3a1 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -729,7 +729,7 @@ note dizziness decrements automatically in the mob's Life() proc. stat(null,"Location:\t([x], [y], [z])") stat(null,"CPU:\t[world.cpu]") stat(null,"Instances:\t[world.contents.len]") - if(statpanel("Status") && processScheduler.getIsRunning()) + if(statpanel("Status") && processScheduler && processScheduler.getIsRunning()) var/datum/controller/process/process process = processScheduler.getProcess("ticker") diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 90e201b382..1d67b712f5 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -473,6 +473,7 @@ //new_character.dna.UpdateSE() // Do the initial caching of the player's body icons. + new_character.force_update_limbs() new_character.regenerate_icons() new_character.key = key //Manually transfer the key to log them in diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index 5d307fffcf..f97df89080 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -235,12 +235,14 @@ var/list/organ_cache = list() owner.internal_organs_by_name[organ_tag] = null owner.internal_organs_by_name -= organ_tag + owner.internal_organs_by_name -= null owner.internal_organs -= src var/obj/item/organ/external/affected = owner.get_organ(parent_organ) if(affected) affected.internal_organs -= src loc = owner.loc + processing_objects |= src rejecting = null var/datum/reagent/blood/organ_blood = locate(/datum/reagent/blood) in reagents.reagent_list if(!organ_blood || !organ_blood.data["blood_DNA"]) @@ -269,6 +271,7 @@ var/list/organ_cache = list() transplant_data["blood_DNA"] = transplant_blood.data["blood_DNA"] owner = target + processing_objects -= src target.internal_organs |= src affected.internal_organs |= src target.internal_organs_by_name[organ_tag] = src diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index b6f14b64bc..d8ba25d750 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -3,13 +3,16 @@ ****************************************************/ /obj/item/organ/external name = "external" + min_broken_damage = 30 + max_damage = 0 + dir = SOUTH + organ_tag = "limb" + var/icon_name = null var/body_part = null var/icon_position = 0 - var/model var/force_icon - var/damage_state = "00" var/brute_dam = 0 var/burn_dam = 0 @@ -18,7 +21,7 @@ var/icon/mob_icon var/gendered_icon = 0 var/limb_name - var/disfigured = 1 + var/disfigured = 0 var/cannot_amputate var/cannot_break var/s_tone @@ -26,38 +29,25 @@ var/list/wounds = list() var/number_wounds = 0 // cache the number of wounds, which is NOT wounds.len! var/perma_injury = 0 - var/obj/item/organ/external/parent var/list/obj/item/organ/external/children - - // Internal organs of this body part - var/list/internal_organs = list() - + var/list/internal_organs = list() // Internal organs of this body part var/damage_msg = "\red You feel an intense pain" var/broken_description - var/open = 0 var/stage = 0 var/cavity = 0 var/sabotaged = 0 // If a prosthetic limb is emagged, it will detonate when it fails. var/encased // Needs to be opened with a saw to access the organs. - var/obj/item/hidden = null var/list/implants = list() - - // how often wounds should be updated, a higher number means less often - var/wound_update_accuracy = 1 - + var/wound_update_accuracy = 1 // how often wounds should be updated, a higher number means less often var/joint = "joint" // Descriptive string used in dislocation. var/amputation_point // Descriptive string used in amputation. var/dislocated = 0 // If you target a joint, you can dislocate the limb, causing temporary damage to the organ. var/can_grasp var/can_stand - min_broken_damage = 30 - max_damage = 0 - dir = SOUTH - /obj/item/organ/external/attackby(obj/item/weapon/W as obj, mob/user as mob) switch(stage) if(0) @@ -650,8 +640,8 @@ Note that amputating the affected organ does in fact remove the infection from t wounds.Cut() if(parent) var/datum/wound/W - if(max_damage < 50) - W = new/datum/wound/lost_limb/small(max_damage) + if(clean || max_damage < 50) + W = new/datum/wound/lost_limb/small(max_damage/2) else W = new/datum/wound/lost_limb(max_damage) parent.children -= src @@ -940,6 +930,7 @@ Note that amputating the affected organ does in fact remove the infection from t gendered_icon = 1 cannot_amputate = 1 parent_organ = null + encased = "ribcage" /obj/item/organ/external/groin name = "lower body" @@ -1061,9 +1052,11 @@ Note that amputating the affected organ does in fact remove the infection from t joint = "jaw" amputation_point = "neck" gendered_icon = 1 + encased = "skull" /obj/item/organ/external/head/removed() if(owner) + name = "[owner.real_name]'s head" owner.u_equip(owner.glasses) owner.u_equip(owner.head) owner.u_equip(owner.l_ear) diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index d5b6bf2a4e..b0e23df3d2 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -16,7 +16,9 @@ var/global/list/limb_icon_cache = list() /obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human) s_tone = null s_col = null - if(human.s_tone && (human.species.flags & HAS_SKIN_TONE)) + if(status & ORGAN_ROBOT) + return + if(!isnull(human.s_tone) && (human.species.flags & HAS_SKIN_TONE)) s_tone = human.s_tone if(human.species.flags & HAS_SKIN_COLOR) s_col = list(human.r_skin, human.g_skin, human.b_skin) diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index c552631abf..46e22e1e5f 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -44,7 +44,7 @@ organ_tag = "kidneys" parent_organ = "groin" -/obj/item/organ/kidney/process() +/obj/item/organ/kidneys/process() ..() @@ -61,7 +61,6 @@ else if(is_broken()) owner.adjustToxLoss(0.3 * PROCESS_ACCURACY) - /obj/item/organ/eyes name = "eyeballs" icon_state = "eyes" @@ -113,7 +112,7 @@ name = "liver" icon_state = "liver" organ_tag = "liver" - parent_organ = "chest" + parent_organ = "groin" /obj/item/organ/liver/process() @@ -175,6 +174,7 @@ name = "appendix" icon_state = "appendix" parent_organ = "groin" + organ_tag = "appendix" /obj/item/organ/appendix/removed() diff --git a/code/modules/projectiles/targeting.dm b/code/modules/projectiles/targeting.dm index 388b53a256..4e49a785e7 100644 --- a/code/modules/projectiles/targeting.dm +++ b/code/modules/projectiles/targeting.dm @@ -23,7 +23,7 @@ //Removing the lock and the buttons. /obj/item/weapon/gun/dropped(mob/user as mob) stop_aim() - if (user.client) + if(user && user.client) user.client.remove_gun_icons() return ..() @@ -47,7 +47,7 @@ /obj/item/weapon/gun/proc/PreFire(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, params) //Lets not spam it. if(lock_time > world.time - 2) return - + user.set_dir(get_cardinal_dir(src, A)) if(isliving(A) && !(A in aim_targets)) Aim(A) //Clicked a mob, aim at them @@ -58,7 +58,7 @@ if(isliving(M) && (M in view(user)) && !(M in aim_targets)) Aim(M) //Aha! Aim at them! return 1 - + return 0 //Aiming at the target mob. @@ -83,12 +83,12 @@ if(src != M.get_active_hand()) stop_aim() return - + //reflex firing is disabled when help intent is set if (M.a_intent == I_HELP) M << "\red You refrain from firing your [src] as your intent is set to help." return - + M.last_move_intent = world.time var/firing_check = can_hit(T,usr) //0 if it cannot hit them, 1 if it is capable of hitting, and 2 if a special check is preventing it from firing. if(firing_check > 0) diff --git a/code/modules/reagents/dispenser/dispenser2.dm b/code/modules/reagents/dispenser/dispenser2.dm index fb7299fcd9..8decba10d4 100644 --- a/code/modules/reagents/dispenser/dispenser2.dm +++ b/code/modules/reagents/dispenser/dispenser2.dm @@ -89,6 +89,10 @@ C.loc = loc else if(istype(W, /obj/item/weapon/reagent_containers/glass) || istype(W, /obj/item/weapon/reagent_containers/food)) + if(container) + user << "There is already \a [container] on \the [src]!" + return + var/obj/item/weapon/reagent_containers/RC = W if(!accept_drinking && istype(RC,/obj/item/weapon/reagent_containers/food)) @@ -172,4 +176,4 @@ /obj/machinery/chemical_dispenser/attack_hand(mob/user as mob) if(stat & BROKEN) return - ui_interact(user) \ No newline at end of file + ui_interact(user) diff --git a/code/modules/research/xenoarchaeology/tools/bunsen_burner.dm b/code/modules/research/xenoarchaeology/tools/bunsen_burner.dm index 2437eeb067..5a74061a23 100644 --- a/code/modules/research/xenoarchaeology/tools/bunsen_burner.dm +++ b/code/modules/research/xenoarchaeology/tools/bunsen_burner.dm @@ -14,9 +14,8 @@ if(held_container) user << "\red You must remove the [held_container] first." else - user.drop_item(src) held_container = W - held_container.loc = src + user.drop_from_inventory(held_container, src) user << "\blue You put the [held_container] onto the [src]." var/image/I = image("icon"=W, "layer"=FLOAT_LAYER) underlays += I diff --git a/code/modules/security levels/security levels.dm b/code/modules/security levels/security levels.dm index e96ed5b334..1892af891e 100644 --- a/code/modules/security levels/security levels.dm +++ b/code/modules/security levels/security levels.dm @@ -57,7 +57,7 @@ FA.overlays += image('icons/obj/monitors.dmi', "overlay_red") if(SEC_LEVEL_DELTA) - security_announcement_up.Announce("[config.alert_desc_delta]", "Attention! Delta security level reached!") + security_announcement_up.Announce("[config.alert_desc_delta]", "Attention! Delta security level reached!", new_sound = 'sound/effects/siren.ogg') security_level = SEC_LEVEL_DELTA for(var/obj/machinery/firealarm/FA in machines) if(FA.z in config.contact_levels) diff --git a/code/modules/surgery/organs_internal.dm b/code/modules/surgery/organs_internal.dm index cbfea6912e..8f5d7155dd 100644 --- a/code/modules/surgery/organs_internal.dm +++ b/code/modules/surgery/organs_internal.dm @@ -343,9 +343,11 @@ var/o_a = (O.gender == PLURAL) ? "" : "a " var/o_do = (O.gender == PLURAL) ? "don't" : "doesn't" - if(target.species.has_organ[O.organ_tag]) + if(O.organ_tag == "limb") + return 0 + else if(target.species.has_organ[O.organ_tag]) - if(!O.health) + if(O.is_damaged()) user << "\red \The [O.organ_tag] [o_is] in no state to be transplanted." return 2 @@ -355,7 +357,7 @@ user << "\red \The [target] already has [o_a][O.organ_tag]." return 2 - if(O && affected.name == O.parent_organ) + if(O && affected.limb_name == O.parent_organ) organ_compatible = 1 else user << "\red \The [O.organ_tag] [o_do] normally go in \the [affected.name]." @@ -377,9 +379,9 @@ var/obj/item/organ/external/affected = target.get_organ(target_zone) user.visible_message("\blue [user] has transplanted \the [tool] into [target]'s [affected.name].", \ "\blue You have transplanted \the [tool] into [target]'s [affected.name].") - user.drop_item(tool) var/obj/item/organ/O = tool if(istype(O)) + user.remove_from_mob(O) O.replaced(target,affected) fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) diff --git a/code/modules/surgery/robolimbs.dm b/code/modules/surgery/robolimbs.dm index 5b524288f9..e845d8bb7b 100644 --- a/code/modules/surgery/robolimbs.dm +++ b/code/modules/surgery/robolimbs.dm @@ -39,8 +39,11 @@ if(L.part) for(var/part_name in L.part) - if(!isnull(target.get_organ(part_name))) continue + if(!isnull(target.get_organ(part_name))) + continue var/list/organ_data = target.species.has_limbs["[target_zone]"] + if(!organ_data) + continue var/new_limb_type = organ_data["path"] var/obj/item/organ/external/new_limb = new new_limb_type(target) new_limb.robotize(L.model_info) diff --git a/tools/Event Probabilities/Event Probabilities.xls b/tools/Event Probabilities/Event Probabilities.xls new file mode 100644 index 0000000000..e8085e8d9d Binary files /dev/null and b/tools/Event Probabilities/Event Probabilities.xls differ