diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index 590474c2dbb..3aacb25c3fc 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -82,6 +82,8 @@ datum/controller/game_controller/proc/setup() for(var/i=0, i 20) // wait 20 secs for beacon response + if(awaiting_beacon > 40) // wait 40 secs for beacon response find_nearest_beacon() // then go to nearest instead return if(next_destination) @@ -583,7 +583,7 @@ obj/machinery/bot/proc/start_patrol() new_destination = "__nearest__" post_signal(beacon_freq, "findbeacon", "patrol") awaiting_beacon = 1 - spawn(100) + spawn(150) awaiting_beacon = 0 if(nearest_beacon) set_destination(nearest_beacon) diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm index 21fb72573e4..6fb65f8a705 100644 --- a/code/game/machinery/bots/ed209bot.dm +++ b/code/game/machinery/bots/ed209bot.dm @@ -67,7 +67,7 @@ icon_state = "[lasercolor]ed209[on]" set_weapon() //giving it the right projectile and firing sound. spawn(3) - var/datum/job/detective/J = new/datum/job/detective + var/datum/job/officer/J = new/datum/job/officer botcard.access = J.get_access() prev_access = botcard.access diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm index 5da885441de..fecf5cdcb26 100644 --- a/code/game/machinery/bots/secbot.dm +++ b/code/game/machinery/bots/secbot.dm @@ -86,7 +86,7 @@ icon_state = "[base_icon][on]" spawn(3) - var/datum/job/detective/J = new/datum/job/detective + var/datum/job/officer/J = new/datum/job/officer botcard.access = J.get_access() prev_access = botcard.access add_to_beacons(bot_filter) diff --git a/code/game/machinery/computer/ai_core.dm b/code/game/machinery/computer/ai_core.dm index 6b5d3abe41f..99751ab3296 100644 --- a/code/game/machinery/computer/ai_core.dm +++ b/code/game/machinery/computer/ai_core.dm @@ -156,11 +156,15 @@ if(istype(P, /obj/item/weapon/screwdriver)) playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1) user << "You connect the monitor." - if(!laws.inherent.len) //If laws isn't set to null but nobody supplied a board, the AI would normally be created lawless. We don't want that. - laws = null - var/mob/living/silicon/ai/A = new /mob/living/silicon/ai (loc, laws, brain) - if(A) //if there's no brain, the mob is deleted and a structure/AIcore is created - A.rename_self("ai", 1) + if(!brain) + var/open_for_latejoin = alert(user, "Would you like this core to be open for latejoining AIs?", "Latejoin", "Yes", "Yes", "No") == "Yes" + var/obj/structure/AIcore/deactivated/D = new(loc) + if(open_for_latejoin) + empty_playable_ai_cores += D + else + var/mob/living/silicon/ai/A = new /mob/living/silicon/ai ( loc, laws, brain ) + if(A) //if there's no brain, the mob is deleted and a structure/AIcore is created + A.rename_self("ai", 1) feedback_inc("cyborg_ais_created",1) del(src) @@ -171,10 +175,53 @@ anchored = 1 state = 20//So it doesn't interact based on the above. Not really necessary. - attackby(var/obj/item/device/aicard/A as obj, var/mob/user as mob) - if(istype(A, /obj/item/device/aicard))//Is it? - A.transfer_ai("INACTIVE","AICARD",src,user) - return +/obj/structure/AIcore/deactivated/attackby(var/obj/item/W, var/mob/user) + if(istype(W, /obj/item/device/aicard))//Is it? + var/obj/item/device/aicard/card = W + card.transfer_ai("INACTIVE","AICARD",src,user) + else if(istype(W, /obj/item/weapon/wrench)) + if(anchored) + user.visible_message("\blue \The [user] starts to unbolt \the [src] from the plating...") + if(!do_after(user,40)) + user.visible_message("\blue \The [user] decides not to unbolt \the [src].") + return + user.visible_message("\blue \The [user] finishes unfastening \the [src]!") + anchored = 0 + return + else + user.visible_message("\blue \The [user] starts to bolt \the [src] to the plating...") + if(!do_after(user,40)) + user.visible_message("\blue \The [user] decides not to bolt \the [src].") + return + user.visible_message("\blue \The [user] finishes fastening down \the [src]!") + anchored = 1 + return + else + return ..() + +/client/proc/empty_ai_core_toggle_latejoin() + set name = "Toggle AI Core Latejoin" + set category = "Admin" + + var/list/cores = list() + for(var/obj/structure/AIcore/deactivated/D in world) + cores["[D] ([D.loc.loc])"] = D + + if(!cores.len) + src << "No deactivated AI cores were found." + + var/id = input("Which core?", "Toggle AI Core Latejoin", null) as null|anything in cores + if(!id) return + + var/obj/structure/AIcore/deactivated/D = cores[id] + if(!D) return + + if(D in empty_playable_ai_cores) + empty_playable_ai_cores -= D + src << "\The [id] is now not available for latejoining AIs." + else + empty_playable_ai_cores += D + src << "\The [id] is now available for latejoining AIs." /* diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 3858b6c50aa..91dbbae40b3 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -6,9 +6,6 @@ * ~ Zuhayr */ -//Used for logging people entering cryosleep and important items they are carrying. -var/global/list/frozen_crew = list() -var/global/list/frozen_items = list() //Main cryopod console. @@ -18,15 +15,33 @@ var/global/list/frozen_items = list() icon = 'icons/obj/Cryogenic2.dmi' icon_state = "cellconsole" circuit = "/obj/item/weapon/circuitboard/cryopodcontrol" + density = 0 + interact_offline = 1 var/mode = null -/obj/machinery/computer/cryopod/attack_paw() - src.attack_hand() + //Used for logging people entering cryosleep and important items they are carrying. + var/list/frozen_crew = list() + var/list/frozen_items = list() + + var/storage_type = "crewmembers" + var/storage_name = "Cryogenic Oversight Control" + var/allow_items = 1 + +/obj/machinery/computer/cryopod/robot + name = "robotic storage console" + desc = "An interface between crew and the robotic storage systems" + icon = 'icons/obj/robot_storage.dmi' + icon_state = "console" + circuit = "/obj/item/weapon/circuitboard/robotstoragecontrol" + + storage_type = "cyborgs" + storage_name = "Robotic Storage Control" + allow_items = 0 /obj/machinery/computer/cryopod/attack_ai() src.attack_hand() -obj/machinery/computer/cryopod/attack_hand(mob/user = usr) +/obj/machinery/computer/cryopod/attack_hand(mob/user = usr) if(stat & (NOPOWER|BROKEN)) return @@ -38,17 +53,18 @@ obj/machinery/computer/cryopod/attack_hand(mob/user = usr) if (!( ticker )) return - dat += "

Cryogenic Oversight Control
" + dat += "

[storage_name]
" dat += "Welcome, [user.real_name].


" dat += "View storage log.
" - dat += "Recover object.
" - dat += "Recover all objects.
" - dat += "Revive crew.

" + if(allow_items) + dat += "View objects.
" + dat += "Recover object.
" + dat += "Recover all objects.
" user << browse(dat, "window=cryopod_console") onclose(user, "cryopod_console") -obj/machinery/computer/cryopod/Topic(href, href_list) +/obj/machinery/computer/cryopod/Topic(href, href_list) if(..()) return @@ -59,45 +75,56 @@ obj/machinery/computer/cryopod/Topic(href, href_list) if(href_list["log"]) - var/dat = "Recently stored crewmembers


" + var/dat = "Recently stored [storage_type]


" for(var/person in frozen_crew) dat += "[person]
" dat += "
" user << browse(dat, "window=cryolog") + if(href_list["view"]) + if(!allow_items) return + + var/dat = "Recently stored objects


" + for(var/obj/item/I in frozen_items) + dat += "[I.name]
" + dat += "
" + + user << browse(dat, "window=cryoitems") + else if(href_list["item"]) + if(!allow_items) return if(frozen_items.len == 0) - user << "\blue There is nothing to recover from storage." + user << "There is nothing to recover from storage." return - var/obj/item/I = input(usr, "Please choose which object to retrieve.","Object recovery",null) as obj in frozen_items - - if(!I || frozen_items.len == 0) - user << "\blue There is nothing to recover from storage." + var/obj/item/I = input(usr, "Please choose which object to retrieve.","Object recovery",null) as null|anything in frozen_items + if(!I) return - visible_message("\blue The console beeps happily as it disgorges \the [I].", 3) + if(!(I in frozen_items)) + user << "\The [I] is no longer in storage." + return + + visible_message("The console beeps happily as it disgorges \the [I].", 3) I.loc = get_turf(src) frozen_items -= I else if(href_list["allitems"]) + if(!allow_items) return if(frozen_items.len == 0) - user << "\blue There is nothing to recover from storage." + user << "There is nothing to recover from storage." return - visible_message("\blue The console beeps happily as it disgorges the desired objects.", 3) + visible_message("The console beeps happily as it disgorges the desired objects.", 3) for(var/obj/item/I in frozen_items) I.loc = get_turf(src) frozen_items -= I - else if(href_list["crew"]) - user << "\red Functionality unavailable at this time." - src.updateUsrDialog() return @@ -106,10 +133,15 @@ obj/machinery/computer/cryopod/Topic(href, href_list) build_path = "/obj/machinery/computer/cryopod" origin_tech = "programming=3" +/obj/item/weapon/circuitboard/robotstoragecontrol + name = "Circuit board (Robotic Storage Console)" + build_path = "/obj/machinery/computer/cryopod/robot" + origin_tech = "programming=3" + //Decorative structures to go alongside cryopods. /obj/structure/cryofeed - name = "\improper cryogenic feed" + name = "cryogenic feed" desc = "A bewildering tangle of machinery and pipes." icon = 'icons/obj/Cryogenic2.dmi' icon_state = "cryo_rear" @@ -131,19 +163,30 @@ obj/machinery/computer/cryopod/Topic(href, href_list) //Cryopods themselves. /obj/machinery/cryopod - name = "\improper cryogenic freezer" + name = "cryogenic freezer" desc = "A man-sized pod for entering suspended animation." icon = 'icons/obj/Cryogenic2.dmi' icon_state = "body_scanner_0" density = 1 anchored = 1 - var/mob/occupant = null // Person waiting to be despawned. - var/orient_right = null // Flips the sprite. - var/time_till_despawn = 9000 // 15 minutes-ish safe period before being despawned. - var/time_entered = 0 // Used to keep track of the safe period. + var/base_icon_state = "body_scanner_0" + var/occupied_icon_state = "body_scanner_1" + var/on_store_message = "has entered long-term storage." + var/on_store_name = "Cryogenic Oversight" + var/on_enter_occupant_message = "You feel cool air surround you. You go numb as your senses turn inward." + var/allow_occupant_types = list(/mob/living/carbon/human, /mob/living/carbon/monkey) + var/disallow_occupant_types = list() + + var/mob/occupant = null // Person waiting to be despawned. + var/orient_right = null // Flips the sprite. + var/time_till_despawn = 18000 // 30 minutes-ish safe period before being despawned. + var/time_entered = 0 // Used to keep track of the safe period. var/obj/item/device/radio/intercom/announce // + var/obj/machinery/computer/cryopod/control_computer + var/last_no_computer_message = 0 + // These items are preserved when the process() despawn proc occurs. var/list/preserve_items = list( /obj/item/weapon/hand_tele, @@ -156,133 +199,212 @@ obj/machinery/computer/cryopod/Topic(href, href_list) /obj/item/clothing/suit, /obj/item/clothing/shoes/magboots, /obj/item/blueprints, - /obj/item/clothing/head/helmet/space/ + /obj/item/clothing/head/helmet/space, + /obj/item/weapon/tank ) /obj/machinery/cryopod/right orient_right = 1 icon_state = "body_scanner_0-r" -/obj/machinery/cryopod/New() +/obj/machinery/cryopod/robot + name = "robotic storage unit" + desc = "A storage unit for robots." + icon = 'icons/obj/robot_storage.dmi' + icon_state = "pod_0" + base_icon_state = "pod_0" + occupied_icon_state = "pod_1" + on_store_message = "has entered robotic storage." + on_store_name = "Robotic Storage Oversight" + on_enter_occupant_message = "The storage unit broadcasts a sleep signal to you. Your systems start to shut down, and you enter low-power mode." + allow_occupant_types = list(/mob/living/silicon/robot) + disallow_occupant_types = list(/mob/living/silicon/robot/drone) +/obj/machinery/cryopod/robot/right + orient_right = 1 + icon_state = "pod_0-r" + +/obj/machinery/cryopod/New() announce = new /obj/item/device/radio/intercom(src) if(orient_right) - icon_state = "body_scanner_0-r" + icon_state = "[base_icon_state]-r" else - icon_state = "body_scanner_0" + icon_state = base_icon_state + ..() +/obj/machinery/cryopod/initialize() + ..() + + find_control_computer() + +/obj/machinery/cryopod/proc/find_control_computer(urgent=0) + control_computer = locate(/obj/machinery/computer/cryopod) in src.loc.loc + + // Don't send messages unless we *need* the computer, and less than five minutes have passed since last time we messaged + if(!control_computer && urgent && last_no_computer_message + 5*60*10 < world.time) + log_admin("Cryopod in [src.loc.loc] could not find control computer!") + message_admins("Cryopod in [src.loc.loc] could not find control computer!") + last_no_computer_message = world.time + + return control_computer != null + +/obj/machinery/cryopod/proc/check_occupant_allowed(mob/M) + var/correct_type = 0 + for(var/type in allow_occupant_types) + if(istype(M, type)) + correct_type = 1 + break + + if(!correct_type) return 0 + + for(var/type in disallow_occupant_types) + if(istype(M, type)) + return 0 + + return 1 + //Lifted from Unity stasis.dm and refactored. ~Zuhayr /obj/machinery/cryopod/process() if(occupant) - //Allow a ten minute gap between entering the pod and actually despawning. if(world.time - time_entered < time_till_despawn) return if(!occupant.client && occupant.stat<2) //Occupant is living and has no client. + if(!control_computer) + if(!find_control_computer(urgent=1)) + return - //Drop all items into the pod. - for(var/obj/item/W in occupant) - occupant.drop_from_inventory(W) - W.loc = src + despawn_occupant() - if(W.contents.len) //Make sure we catch anything not handled by del() on the items. - for(var/obj/item/O in W.contents) - O.loc = src +// This function can not be undone; do not call this unless you are sure +// Also make sure there is a valid control computer +/obj/machinery/cryopod/robot/despawn_occupant() + var/mob/living/silicon/robot/R = occupant + if(!istype(R)) return ..() + + R.contents -= R.mmi + del(R.mmi) + for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc + for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags + O.loc = R + del(I) + del(R.module) - //Delete all items not on the preservation list. - var/list/items = src.contents - items -= occupant // Don't delete the occupant - items -= announce // or the autosay radio. + return ..() - for(var/obj/item/W in items) - var/preserve = null - for(var/T in preserve_items) - if(istype(W,T)) - preserve = 1 - break +// This function can not be undone; do not call this unless you are sure +// Also make sure there is a valid control computer +/obj/machinery/cryopod/proc/despawn_occupant() + //Drop all items into the pod. + for(var/obj/item/W in occupant) + occupant.drop_from_inventory(W) + W.loc = src - if(!preserve) - del(W) - else - frozen_items += W + if(W.contents.len) //Make sure we catch anything not handled by del() on the items. + for(var/obj/item/O in W.contents) + if(istype(O,/obj/item/weapon/tank)) //Stop eating pockets, you fuck! + continue + O.loc = src - //Update any existing objectives involving this mob. - for(var/datum/objective/O in all_objectives) - if(istype(O,/datum/objective/mutiny) && O.target == occupant.mind) //We don't want revs to get objectives that aren't for heads of staff. Letting them win or lose based on cryo is silly so we remove the objective. - del(O) //TODO: Update rev objectives on login by head (may happen already?) ~ Z - else if(O.target && istype(O.target,/datum/mind)) - if(O.target == occupant.mind) - if(O.owner && O.owner.current) - O.owner.current << "\red You get the feeling your target is no longer within your reach. Time for Plan [pick(list("A","B","C","D","X","Y","Z"))]..." - O.target = null - spawn(1) //This should ideally fire after the occupant is deleted. - if(!O) return - O.find_target() - if(!(O.target)) - all_objectives -= O - O.owner.objectives -= O - del(O) + //Delete all items not on the preservation list. + var/list/items = src.contents + items -= occupant // Don't delete the occupant + items -= announce // or the autosay radio. - //Handle job slot/tater cleanup. - var/job = occupant.mind.assigned_role + for(var/obj/item/W in items) - job_master.FreeRole(job) + var/preserve = null + for(var/T in preserve_items) + if(istype(W,T)) + preserve = 1 + break - if(occupant.mind.objectives.len) - del(occupant.mind.objectives) - occupant.mind.special_role = null + if(!preserve) + del(W) + else + if(control_computer && control_computer.allow_items) + control_computer.frozen_items += W + W.loc = null else - if(ticker.mode.name == "AutoTraitor") - var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode - current_mode.possible_traitors.Remove(occupant) + W.loc = src.loc - // Delete them from datacore. + //Update any existing objectives involving this mob. + for(var/datum/objective/O in all_objectives) + // We don't want revs to get objectives that aren't for heads of staff. Letting + // them win or lose based on cryo is silly so we remove the objective. + if(istype(O,/datum/objective/mutiny) && O.target == occupant.mind) + del(O) + else if(O.target && istype(O.target,/datum/mind)) + if(O.target == occupant.mind) + if(O.owner && O.owner.current) + O.owner.current << "You get the feeling your target is no longer within your reach. Time for Plan [pick(list("A","B","C","D","X","Y","Z"))]..." + O.target = null + spawn(1) //This should ideally fire after the occupant is deleted. + if(!O) return + O.find_target() + if(!(O.target)) + all_objectives -= O + O.owner.objectives -= O + del(O) - if(PDA_Manifest.len) - PDA_Manifest.Cut() - for(var/datum/data/record/R in data_core.medical) - if ((R.fields["name"] == occupant.real_name)) - del(R) - for(var/datum/data/record/T in data_core.security) - if ((T.fields["name"] == occupant.real_name)) - del(T) - for(var/datum/data/record/G in data_core.general) - if ((G.fields["name"] == occupant.real_name)) - del(G) + //Handle job slot/tater cleanup. + var/job = occupant.mind.assigned_role - if(orient_right) - icon_state = "body_scanner_0-r" - else - icon_state = "body_scanner_0" + job_master.FreeRole(job) - //TODO: Check objectives/mode, update new targets if this mob is the target, spawn new antags? + if(occupant.mind.objectives.len) + del(occupant.mind.objectives) + occupant.mind.special_role = null + else + if(ticker.mode.name == "AutoTraitor") + var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode + current_mode.possible_traitors.Remove(occupant) - //This should guarantee that ghosts don't spawn. - occupant.ckey = null + // Delete them from datacore. - //Make an announcement and log the person entering storage. - frozen_crew += "[occupant.real_name]" + if(PDA_Manifest.len) + PDA_Manifest.Cut() + for(var/datum/data/record/R in data_core.medical) + if ((R.fields["name"] == occupant.real_name)) + del(R) + for(var/datum/data/record/T in data_core.security) + if ((T.fields["name"] == occupant.real_name)) + del(T) + for(var/datum/data/record/G in data_core.general) + if ((G.fields["name"] == occupant.real_name)) + del(G) - var/ailist[] = list() - for (var/mob/living/silicon/ai/A in living_mob_list) - ailist += A - if (ailist.len) - var/mob/living/silicon/ai/announcer = pick(ailist) - announcer.say(";[occupant.real_name] has entered long-term storage.") - else - announce.autosay("[occupant.real_name] has entered long-term storage.", "Cryogenic Oversight") + if(orient_right) + icon_state = "[base_icon_state]-r" + else + icon_state = base_icon_state + + //TODO: Check objectives/mode, update new targets if this mob is the target, spawn new antags? + + //This should guarantee that ghosts don't spawn. + occupant.ckey = null + + //Make an announcement and log the person entering storage. + control_computer.frozen_crew += "[occupant.real_name]" + + var/ailist[] = list() + for (var/mob/living/silicon/ai/A in living_mob_list) + ailist += A + if (ailist.len) + var/mob/living/silicon/ai/announcer = pick(ailist) + announcer.say(";[occupant.real_name] [on_store_message]") + else + announce.autosay("[occupant.real_name] [on_store_message]", "[on_store_name]") - visible_message("\blue The crypod hums and hisses as it moves [occupant.real_name] into storage.", 3) + visible_message("\The [src] hums and hisses as it moves [occupant.real_name] into storage.", 3) - // Delete the mob. - del(occupant) - occupant = null - - - return + // Delete the mob. + del(occupant) + occupant = null + name = initial(name) /obj/machinery/cryopod/attackby(var/obj/item/weapon/G as obj, var/mob/user as mob) @@ -290,17 +412,20 @@ obj/machinery/computer/cryopod/Topic(href, href_list) if(istype(G, /obj/item/weapon/grab)) if(occupant) - user << "\blue The cryo pod is in use." + user << "\The [src] is in use." return if(!ismob(G:affecting)) return + if(!check_occupant_allowed(G:affecting)) + return + var/willing = null //We don't want to allow people to be forced into despawning. var/mob/M = G:affecting if(M.client) - if(alert(M,"Would you like to enter cryosleep?",,"Yes","No") == "Yes") + if(alert(M,"Would you like to enter long-term storage?",,"Yes","No") == "Yes") if(!M || !G || !G:affecting) return willing = 1 else @@ -308,7 +433,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) if(willing) - visible_message("[user] starts putting [G:affecting:name] into the cryo pod.", 3) + visible_message("[user] starts putting [G:affecting:name] into \the [src].", 3) if(do_after(user, 20)) if(!M || !G || !G:affecting) return @@ -320,21 +445,23 @@ obj/machinery/computer/cryopod/Topic(href, href_list) M.client.eye = src if(orient_right) - icon_state = "body_scanner_1-r" + icon_state = "[occupied_icon_state]-r" else - icon_state = "body_scanner_1" + icon_state = occupied_icon_state - M << "\blue You feel cool air surround you. You go numb as your senses turn inward." - M << "\blue If you ghost, log out or close your client now, your character will shortly be permanently removed from the round." + M << "[on_enter_occupant_message]" + M << "If you ghost, log out or close your client now, your character will shortly be permanently removed from the round." occupant = M time_entered = world.time // Book keeping! - log_admin("[key_name_admin(M)] has entered a stasis pod.") - message_admins("\blue [key_name_admin(M)] has entered a stasis pod.") + var/turf/location = get_turf(src) + log_admin("[key_name_admin(M)] has entered a stasis pod. (JMP)") + message_admins("[key_name_admin(M)] has entered a stasis pod.") //Despawning occurs when process() is called with an occupant without a client. src.add_fingerprint(M) + /obj/machinery/cryopod/MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob) @@ -346,7 +473,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) return if(!ismob(O)) //humans only return - if(istype(O, /mob/living/simple_animal) || istype(O, /mob/living/silicon)) //animals and robutts dont fit + if(!check_occupant_allowed(O)) return if(!ishuman(user) && !isrobot(user)) //No ghosts or mice putting people into the sleeper return @@ -393,25 +520,24 @@ obj/machinery/computer/cryopod/Topic(href, href_list) L.client.eye = src if(orient_right) - icon_state = "body_scanner_1-r" + icon_state = "[occupied_icon_state]-r" else - icon_state = "body_scanner_1" + icon_state = occupied_icon_state - L << "\blue You feel cool air surround you. You go numb as your senses turn inward." - L << "\blue If you ghost, log out or close your client now, your character will shortly be permanently removed from the round." + L << "[on_enter_occupant_message]" + L << "If you ghost, log out or close your client now, your character will shortly be permanently removed from the round." occupant = L time_entered = world.time // Book keeping! - log_admin("[key_name_admin(L)] has entered a stasis pod.") - message_admins("\blue [key_name_admin(L)] has entered a stasis pod.") + log_admin("[key_name_admin(L)] has entered a stasis pod. (JMP)") + message_admins("[key_name_admin(L)] has entered a stasis pod.") //Despawning occurs when process() is called with an occupant without a client. src.add_fingerprint(L) return - /obj/machinery/cryopod/verb/eject() set name = "Eject Pod" set category = "Object" @@ -420,12 +546,22 @@ obj/machinery/computer/cryopod/Topic(href, href_list) return if(orient_right) - icon_state = "body_scanner_0-r" + icon_state = "[base_icon_state]-r" else - icon_state = "body_scanner_0" + icon_state = base_icon_state + + //Eject any items that aren't meant to be in the pod. + var/list/items = src.contents + if(occupant) items -= occupant + if(announce) items -= announce + + for(var/obj/item/W in items) + W.loc = get_turf(src) src.go_out() add_fingerprint(usr) + + name = initial(name) return /obj/machinery/cryopod/verb/move_inside() @@ -433,11 +569,11 @@ obj/machinery/computer/cryopod/Topic(href, href_list) set category = "Object" set src in oview(1) - if(usr.stat != 0 || !(ishuman(usr) || ismonkey(usr))) + if(usr.stat != 0 || !check_occupant_allowed(usr)) return if(src.occupant) - usr << "\blue The cryo pod is in use." + usr << "\The [src] is in use." return for(var/mob/living/carbon/slime/M in range(1,usr)) @@ -445,7 +581,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) usr << "You're too busy getting your life sucked out of you." return - visible_message("[usr] starts climbing into the cryo pod.", 3) + visible_message("[usr] starts climbing into \the [src].", 3) if(do_after(usr, 20)) @@ -453,7 +589,7 @@ obj/machinery/computer/cryopod/Topic(href, href_list) return if(src.occupant) - usr << "\blue The cryo pod is in use." + usr << "\The [src] is in use." return usr.stop_pulling() @@ -463,16 +599,17 @@ obj/machinery/computer/cryopod/Topic(href, href_list) src.occupant = usr if(orient_right) - icon_state = "body_scanner_1-r" + icon_state = "[occupied_icon_state]-r" else - icon_state = "body_scanner_1" + icon_state = occupied_icon_state - usr << "\blue You feel cool air surround you. You go numb as your senses turn inward." - usr << "\blue If you ghost, log out or close your client now, your character will shortly be permanently removed from the round." + usr << "[on_enter_occupant_message]" + usr << "If you ghost, log out or close your client now, your character will shortly be permanently removed from the round." occupant = usr time_entered = world.time src.add_fingerprint(usr) + name = "[name] ([usr.name])" return @@ -489,9 +626,9 @@ obj/machinery/computer/cryopod/Topic(href, href_list) occupant = null if(orient_right) - icon_state = "body_scanner_0-r" + icon_state = "[base_icon_state]-r" else - icon_state = "body_scanner_0" + icon_state = base_icon_state return diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index 6a959e5f9ee..2e00c5d99d8 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -39,6 +39,18 @@ if("JoinLate") latejoin += loc del(src) + + if("JoinLateGateway") + latejoin_gateway += loc + del(src) + + if("JoinLateCryo") + latejoin_cryo += loc + del(src) + + if("JoinLateCyborg") + latejoin_cyborg += loc + del(src) //prisoners if("prisonwarp") diff --git a/code/game/vehicles/spacepods/spacepod.dm b/code/game/vehicles/spacepods/spacepod.dm index 248868e1957..7d81ba1ebbd 100644 --- a/code/game/vehicles/spacepods/spacepod.dm +++ b/code/game/vehicles/spacepods/spacepod.dm @@ -75,6 +75,10 @@ if(P.damage && !P.nodamage) deal_damage(P.damage) +/obj/spacepod/blob_act() + deal_damage(30) + return + /obj/spacepod/attack_animal(mob/living/simple_animal/user as mob) if(user.melee_damage_upper == 0) user.emote("[user.friendly] [src]") diff --git a/code/global.dm b/code/global.dm index 9d23e32209e..28ed508a5f4 100644 --- a/code/global.dm +++ b/code/global.dm @@ -167,6 +167,9 @@ var/list/monkeystart = list() var/list/wizardstart = list() var/list/newplayer_start = list() var/list/latejoin = list() +var/list/latejoin_gateway = list() +var/list/latejoin_cryo = list() +var/list/latejoin_cyborg = list() var/list/prisonwarp = list() //prisoners go to these var/list/holdingfacility = list() //captured people go here var/list/xeno_spawn = list()//Aliens spawn at these. @@ -329,4 +332,7 @@ var/recall_time_limit=72000 var/global/list/alphabet_uppercase = list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z") // AI controlled bots -var/global/list/aibots = list() \ No newline at end of file +var/global/list/aibots = list() + +// Announcer intercom, because too much stuff creates an intercom for one message then hard del()s it. +var/global/obj/item/device/radio/intercom/global_announcer = new(null) \ No newline at end of file diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index ed8989c3302..727dfc58c61 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -64,7 +64,8 @@ var/list/admin_verbs_admin = list( /client/proc/man_up, /client/proc/global_man_up, /client/proc/delbook, - /client/proc/event_manager_panel + /client/proc/event_manager_panel, + /client/proc/empty_ai_core_toggle_latejoin ) var/list/admin_verbs_ban = list( /client/proc/unban_panel, diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 245f1df0710..12601237d79 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -91,6 +91,7 @@ datum/preferences var/be_random_name = 0 //whether we are a random name every round var/gender = MALE //gender of character (well duh) var/age = 30 //age of character + var/spawnpoint = "Arrivals Shuttle" //where this character will spawn (0-2). var/b_type = "A+" //blood type (not-chooseable) var/underwear = 1 //underwear type var/undershirt = 1 //undershirt type @@ -214,6 +215,7 @@ datum/preferences dat += "
" dat += "Gender: [gender == MALE ? "Male" : "Female"]
" dat += "Age: [age]" + //dat += "Spawn Point: [spawnpoint]" dat += "
Body " dat += "(®)" dat += "
" @@ -1293,6 +1295,17 @@ datum/preferences var/skin_style_name = input(user, "Select a new skin style") as null|anything in list("default1", "default2", "default3") if(!skin_style_name) return */ + +/* if("spawnpoint") + var/list/spawnkeys = list() + for(var/S in spawntypes) + spawnkeys += S + var/choice = input(user, "Where would you like to spawn when latejoining?") as null|anything in spawnkeys + if(!choice || !spawntypes[choice]) + spawnpoint = "Arrivals Shuttle" + return + spawnpoint = choice */ + else switch(href_list["preference"]) if("gender") diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 367874fd8ad..8e1c0e12964 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -121,6 +121,7 @@ S["age"] >> age S["species"] >> species S["language"] >> language + S["spawnpoint"] >> spawnpoint //colors to be consolidated into hex strings (requires some work with dna code) S["hair_red"] >> r_hair @@ -323,6 +324,7 @@ real_name = reject_bad_name(real_name) if(isnull(species)) species = "Human" if(isnull(language)) language = "None" + if(isnull(spawnpoint)) spawnpoint = "Arrivals Shuttle" if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation) if(!real_name) real_name = random_name(gender) be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name)) diff --git a/code/modules/client/preferences_spawnpoints.dm b/code/modules/client/preferences_spawnpoints.dm new file mode 100644 index 00000000000..ac0d5447e64 --- /dev/null +++ b/code/modules/client/preferences_spawnpoints.dm @@ -0,0 +1,57 @@ +var/list/spawntypes = list() + +/proc/populate_spawn_points() + spawntypes = list() + for(var/type in typesof(/datum/spawnpoint)-/datum/spawnpoint) + var/datum/spawnpoint/S = new type() + spawntypes[S.display_name] = S + +/datum/spawnpoint + var/msg //Message to display on the arrivals computer. + var/list/turfs //List of turfs to spawn on. + var/display_name //Name used in preference setup. + var/list/restrict_job = null + var/list/disallow_job = null + + proc/check_job_spawning(job) + if(restrict_job && !(job in restrict_job)) + return 0 + + if(disallow_job && (job in disallow_job)) + return 0 + + return 1 + +/datum/spawnpoint/arrivals + display_name = "Arrivals Shuttle" + msg = "has arrived on the station" + +/datum/spawnpoint/arrivals/New() + ..() + turfs = latejoin + +/datum/spawnpoint/gateway + display_name = "Gateway" + msg = "has completed translation from offsite gateway" + +/datum/spawnpoint/gateway/New() + ..() + turfs = latejoin_gateway + +/datum/spawnpoint/cryo + display_name = "Cryogenic Storage" + msg = "has completed cryogenic revival" + disallow_job = list("Cyborg") + +/datum/spawnpoint/cryo/New() + ..() + turfs = latejoin_cryo + +/datum/spawnpoint/cyborg + display_name = "Cyborg Storage" + msg = "has been activated from storage" + restrict_job = list("Cyborg") + +/datum/spawnpoint/cyborg/New() + ..() + turfs = latejoin_cyborg \ No newline at end of file diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm index f9c912ffcc8..ce7e86c94ca 100644 --- a/code/modules/clothing/spacesuits/rig.dm +++ b/code/modules/clothing/spacesuits/rig.dm @@ -501,7 +501,7 @@ icon_state = "rig0-singuloth" item_state = "singuloth_helm" _color = "singuloth" - armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 80) + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 100) /obj/item/clothing/suit/space/rig/singuloth icon_state = "rig-singuloth" @@ -509,4 +509,4 @@ desc = "This is a ceremonial armor from the chapter of the Singuloth Knights. It's made of pure forged adamantium." item_state = "singuloth_hardsuit" flags = FPRINT | TABLEPASS | STOPSPRESSUREDMAGE - armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 80) + armor = list(melee = 40, bullet = 5, laser = 20,energy = 5, bomb = 25, bio = 100, rad = 100) diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm index 7bf3efb8b97..dc292acf7e3 100644 --- a/code/modules/clothing/under/color.dm +++ b/code/modules/clothing/under/color.dm @@ -101,85 +101,73 @@ flags = FPRINT | TABLEPASS | ONESIZEFITSALL /obj/item/clothing/under/psyche - name = "psychedelic" + name = "psychedelic jumpsuit" desc = "Groovy!" icon_state = "psyche" _color = "psyche" /obj/item/clothing/under/color/lightblue - name = "lightblue" - desc = "lightblue" + name = "light blue jumpsuit" icon_state = "lightblue" _color = "lightblue" /obj/item/clothing/under/color/aqua - name = "aqua" - desc = "aqua" + name = "aqua jumpsuit" icon_state = "aqua" _color = "aqua" flags = FPRINT | TABLEPASS | ONESIZEFITSALL /obj/item/clothing/under/color/purple - name = "purple" - desc = "purple" + name = "purple jumpsuit" icon_state = "purple" item_state = "p_suit" _color = "purple" /obj/item/clothing/under/color/lightpurple - name = "lightpurple" - desc = "lightpurple" + name = "light purple jumpsuit" icon_state = "lightpurple" _color = "lightpurple" /obj/item/clothing/under/color/lightgreen - name = "lightgreen" - desc = "lightgreen" + name = "light green jumpsuit" icon_state = "lightgreen" _color = "lightgreen" /obj/item/clothing/under/color/lightblue - name = "lightblue" - desc = "lightblue" + name = "light blue jumpsuit" icon_state = "lightblue" _color = "lightblue" /obj/item/clothing/under/color/lightbrown - name = "lightbrown" - desc = "lightbrown" + name = "light brown jumpsuit" icon_state = "lightbrown" _color = "lightbrown" flags = FPRINT | TABLEPASS | ONESIZEFITSALL /obj/item/clothing/under/color/brown - name = "brown" - desc = "brown" + name = "brown jumpsuit" icon_state = "brown" _color = "brown" flags = FPRINT | TABLEPASS /obj/item/clothing/under/color/yellowgreen - name = "yellowgreen" - desc = "yellowgreen" + name = "yellow green jumpsuit" icon_state = "yellowgreen" _color = "yellowgreen" /obj/item/clothing/under/color/darkblue - name = "darkblue" - desc = "darkblue" + name = "dark blue jumpsuit" icon_state = "darkblue" _color = "darkblue" flags = FPRINT | TABLEPASS | ONESIZEFITSALL /obj/item/clothing/under/color/lightred - name = "lightred" - desc = "lightred" + name = "light red jumpsuit" icon_state = "lightred" _color = "lightred" /obj/item/clothing/under/color/darkred - name = "darkred" - desc = "darkred" + name = "dark red jumpsuit" icon_state = "darkred" _color = "darkred" flags = FPRINT | TABLEPASS | ONESIZEFITSALL diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 657713ca60a..f34da6c2e75 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -115,7 +115,7 @@ var/list/ai_list = list() if(!safety)//Only used by AIize() to successfully spawn an AI. if (!B)//If there is no player/brain inside. - new/obj/structure/AIcore/deactivated(loc)//New empty terminal. + empty_playable_ai_cores += new/obj/structure/AIcore/deactivated(loc)//New empty terminal. del(src)//Delete AI. return else diff --git a/code/modules/mob/living/silicon/ai/latejoin.dm b/code/modules/mob/living/silicon/ai/latejoin.dm new file mode 100644 index 00000000000..8c966d636c7 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/latejoin.dm @@ -0,0 +1,44 @@ +var/global/list/empty_playable_ai_cores = list() + +/hook/roundstart/proc/spawn_empty_ai() + for(var/obj/effect/landmark/start/S in landmarks_list) + if(S.name != "AI") + continue + if(locate(/mob/living) in S.loc) + continue + 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" + set desc = "Wipe your core. This is functionally equivalent to cryo or robotic storage, freeing up your job slot." + + if(ticker && ticker.mode && ticker.mode.name == "AI malfunction") + usr << "You cannot use this verb in malfunction. If you need to leave, please adminhelp." + return + + // Guard against misclicks, this isn't the sort of thing we want happening accidentally + if(alert("WARNING: This will immediately wipe your core and ghost you, removing your character from the round permanently (similar to cryo and robotic storage). Are you entirely sure you want to do this?", + "Wipe Core", "No", "No", "Yes") != "Yes") + return + + // We warned you. + empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(loc) + global_announcer.autosay("[src] has been moved to intelligence storage.", "Artificial Intelligence Oversight") + + //Handle job slot/tater cleanup. + var/job = mind.assigned_role + + job_master.FreeRole(job) + + if(mind.objectives.len) + del(mind.objectives) + mind.special_role = null + else + if(ticker.mode.name == "AutoTraitor") + var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode + current_mode.possible_traitors.Remove(src) + + del(src) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index a9e99e87e76..9ffc8e0a003 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -349,12 +349,15 @@ var/datum/paiController/paiController // Global handler for pAI candidates proc/requestRecruits() for(var/mob/dead/observer/O in player_list) if(O.client && O.client.prefs.be_special & BE_PAI) - if(check_recruit(O)) - O << "\blue A pAI card is looking for personalities. (Sign Up)" - //question(O.client) + if(player_old_enough_antag(O.client,BE_PAI)) + if(check_recruit(O)) + O << "\blue A pAI card is looking for personalities. (Sign Up)" + //question(O.client) proc/check_recruit(var/mob/dead/observer/O) if(jobban_isbanned(O, "pAI") || jobban_isbanned(O,"nonhumandept")) return 0 + if(!player_old_enough_antag(O.client,BE_PAI)) + return 0 if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted) return 0 if(O.client) diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 319dcd22e00..c8403d5b671 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -167,7 +167,7 @@ src << alert("You are currently not whitelisted to play [client.prefs.species].") return 0 - AttemptLateSpawn(href_list["SelectedJob"]) + AttemptLateSpawn(href_list["SelectedJob"],client.prefs.spawnpoint) return if(href_list["privacy_poll"]) @@ -272,7 +272,7 @@ proc/IsJobAvailable(rank) var/datum/job/job = job_master.GetJob(rank) if(!job) return 0 - if((job.current_positions >= job.total_positions) && job.total_positions != -1) return 0 + if(!job.is_position_available()) return 0 if(jobban_isbanned(src,rank)) return 0 if(!is_job_whitelisted(src, rank)) return 0 if(!job.player_old_enough(src.client)) return 0 @@ -290,7 +290,7 @@ return 1 - proc/AttemptLateSpawn(rank) + proc/AttemptLateSpawn(rank,var/spawning_at) if (src != usr) return 0 if(!ticker || ticker.current_state != GAME_STATE_PLAYING) @@ -305,11 +305,48 @@ job_master.AssignRole(src, rank, 1) - var/mob/living/carbon/human/character = create_character() //creates the human and transfers vars and mind + var/mob/living/character = create_character() //creates the human and transfers vars and mind EquipRacialItems(character) - job_master.EquipRank(character, rank, 1) //equips the human + character = job_master.EquipRank(character, rank, 1) //equips the human EquipCustomItems(character) - character.loc = pick(latejoin) + + // AIs don't need a spawnpoint, they must spawn at an empty core + if(character.mind.assigned_role == "AI") + + character = character.AIize(move=0) // AIize the character, but don't move them yet + + // IsJobAvailable for AI checks that there is an empty core available in this list + var/obj/structure/AIcore/deactivated/C = empty_playable_ai_cores[1] + empty_playable_ai_cores -= C + + character.loc = C.loc + + AnnounceCyborg(character, rank, "has been downloaded to the empty core in \the [character.loc.loc]") + ticker.mode.latespawn(character) + + del(C) + del(src) + return + + //Find our spawning point. + var/join_message + var/datum/spawnpoint/S + + if(spawning_at) + S = spawntypes[spawning_at] + + if(S && istype(S)) + if(S.check_job_spawning(rank)) + character.loc = pick(S.turfs) + join_message = S.msg + else + character << "Your chosen spawnpoint ([S.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead." + character.loc = pick(latejoin) + join_message = "has arrived on the station" + else + character.loc = pick(latejoin) + join_message = "has arrived on the station" + character.lastarea = get_area(loc) // Moving wheelchair if they have one if(character.buckled && istype(character.buckled, /obj/structure/stool/bed/chair/wheelchair)) @@ -321,14 +358,15 @@ if(character.mind.assigned_role != "Cyborg") data_core.manifest_inject(character) ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn - AnnounceArrival(character, rank) + AnnounceArrival(character, rank, join_message) callHook("latespawn", list(character)) else - character.Robotize() + AnnounceCyborg(character, rank, join_message) + callHook("latespawn", list(character)) del(src) - proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank) + proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message) if (ticker.current_state == GAME_STATE_PLAYING) var/ailist[] = list() for (var/mob/living/silicon/ai/A in living_mob_list) @@ -337,16 +375,35 @@ var/mob/living/silicon/ai/announcer = pick(ailist) if(character.mind) if((character.mind.assigned_role != "Cyborg") && (character.mind.special_role != "MODE")) + if(character.mind.role_alt_title) + rank = character.mind.role_alt_title var/arrivalmessage = announcer.arrivalmsg arrivalmessage = replacetext(arrivalmessage,"$name",character.real_name) arrivalmessage = replacetext(arrivalmessage,"$rank",rank ? "[rank]" : "visitor") announcer.say(";[arrivalmessage]") else - var/obj/item/device/radio/intercom/a = new /obj/item/device/radio/intercom(null)// BS12 EDIT Arrivals Announcement Computer, rather than the AI. - if(character.mind.role_alt_title) - rank = character.mind.role_alt_title - a.autosay("[character.real_name],[rank ? " [rank]," : " visitor," ] has arrived on the station.", "Arrivals Announcement Computer") - del(a) + if(character.mind) + if((character.mind.assigned_role != "Cyborg") && (character.mind.special_role != "MODE")) + if(character.mind.role_alt_title) + rank = character.mind.role_alt_title + global_announcer.autosay("[character.real_name],[rank ? " [rank]," : " visitor," ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") + + proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message) + if (ticker.current_state == GAME_STATE_PLAYING) + var/ailist[] = list() + for (var/mob/living/silicon/ai/A in living_mob_list) + ailist += A + if (ailist.len) + var/mob/living/silicon/ai/announcer = pick(ailist) + if(character.mind) + if((character.mind.special_role != "MODE")) + var/arrivalmessage = "A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"]." + announcer.say(";[arrivalmessage]") + else + if(character.mind) + if((character.mind.special_role != "MODE")) + // can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc. + global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer") proc/LateChoices() var/mills = world.time // 1/10 of a second, not real milliseconds but whatever diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index a5aad6e3999..29baaab6f11 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -61,13 +61,13 @@ spawning = 1 return ..() -/mob/living/carbon/human/AIize() +/mob/living/carbon/human/AIize(move=1) // 'move' argument needs defining here too because BYOND is dumb if (monkeyizing) return for(var/t in organs) del(t) - return ..() + return ..(move) /mob/living/carbon/AIize() if (monkeyizing) @@ -80,7 +80,7 @@ invisibility = 101 return ..() -/mob/proc/AIize() +/mob/proc/AIize(move=1) if(client) src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) // stop the jams for AIs var/mob/living/silicon/ai/O = new (loc,,,1)//No MMI but safety is in effect. @@ -93,28 +93,29 @@ else O.key = key - var/obj/loc_landmark - for(var/obj/effect/landmark/start/sloc in landmarks_list) - if (sloc.name != "AI") - continue - if (locate(/mob/living) in sloc.loc) - continue - loc_landmark = sloc - if (!loc_landmark) - for(var/obj/effect/landmark/tripai in landmarks_list) - if (tripai.name == "tripai") - if(locate(/mob/living) in tripai.loc) - continue - loc_landmark = tripai - if (!loc_landmark) - O << "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone." + if(move) + var/obj/loc_landmark for(var/obj/effect/landmark/start/sloc in landmarks_list) - if (sloc.name == "AI") - loc_landmark = sloc + if (sloc.name != "AI") + continue + if ((locate(/mob/living) in sloc.loc) || (locate(/obj/structure/AIcore) in sloc.loc)) + continue + loc_landmark = sloc + if (!loc_landmark) + for(var/obj/effect/landmark/tripai in landmarks_list) + if (tripai.name == "tripai") + if((locate(/mob/living) in tripai.loc) || (locate(/obj/structure/AIcore) in tripai.loc)) + continue + loc_landmark = tripai + if (!loc_landmark) + O << "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone." + for(var/obj/effect/landmark/start/sloc in landmarks_list) + if (sloc.name == "AI") + loc_landmark = sloc - O.loc = loc_landmark.loc - for (var/obj/item/device/radio/intercom/comm in O.loc) - comm.ai += O + O.loc = loc_landmark.loc + for (var/obj/item/device/radio/intercom/comm in O.loc) + comm.ai += O O << "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras)." O << "To look at other parts of the station, click on yourself to get a camera menu." @@ -131,9 +132,9 @@ O.job = "AI" O.rename_self("ai",1) - . = O - del(src) - + spawn(0) + del(src) + return O /mob/living/carbon/human/make_into_mask(var/should_gib = 0) for(var/t in organs) diff --git a/icons/obj/robot_storage.dmi b/icons/obj/robot_storage.dmi new file mode 100644 index 00000000000..5a996c01e7e Binary files /dev/null and b/icons/obj/robot_storage.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index acbc0a4ffad..96ab4aea9bc 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -77,7 +77,7 @@ macro "AZERTYoff" is-disabled = false elem name = "CTRL+4" - command = "a-intent hurt" + command = "a-intent harm" is-disabled = false elem name = "CTRL+A" @@ -509,7 +509,7 @@ macro "macro" is-disabled = false elem name = "CTRL+4" - command = "a-intent hurt" + command = "a-intent harm" is-disabled = false elem name = "CTRL+A+REP" diff --git a/maps/cyberiad.dmm b/maps/cyberiad.dmm index 3ceffa7cf23..70be5ffd1a6 100644 --- a/maps/cyberiad.dmm +++ b/maps/cyberiad.dmm @@ -1263,7 +1263,7 @@ "ayo" = (/obj/structure/stool/bed/chair/comfy/black,/turf/simulated/floor{tag = "icon-cult"; icon_state = "cult"; dir = 2},/area/lawoffice) "ayp" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 32; pixel_y = 0},/turf/simulated/floor{icon_state = "redcorner"; dir = 4},/area/hallway/primary/fore) "ayq" = (/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/floor/plating,/area/maintenance/fsmaint) -"ayr" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) +"ayr" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/effect/landmark{name = "JoinLateCryo"},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) "ays" = (/obj/machinery/cryopod,/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) "ayt" = (/obj/structure/cryofeed,/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) "ayu" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; on = 1},/turf/simulated/floor{icon_state = "neutral"; dir = 9},/area/crew_quarters/fitness) @@ -1316,7 +1316,7 @@ "azp" = (/obj/structure/stool/bed/chair/office/dark{dir = 8},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/obj/effect/landmark/start{name = "Internal Affairs Agent"},/turf/simulated/floor{tag = "icon-cult"; icon_state = "cult"; dir = 2},/area/lawoffice) "azq" = (/obj/machinery/atmospherics/unary/vent_scrubber{on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor{tag = "icon-cult"; icon_state = "cult"; dir = 2},/area/lawoffice) "azr" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/wall,/area) -"azs" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) +"azs" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 8; on = 1; scrub_N2O = 1; scrub_Toxins = 1},/obj/effect/landmark{name = "JoinLateCryo"},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) "azt" = (/turf/simulated/floor{dir = 8; icon_state = "neutral"},/area/crew_quarters/fitness) "azu" = (/obj/structure/disposalpipe/segment,/turf/simulated/floor,/area/crew_quarters/fitness) "azv" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = ""},/turf/simulated/floor,/area/crew_quarters/fitness) @@ -1370,7 +1370,7 @@ "aAr" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/turf/simulated/floor{icon_state = "redcorner"; dir = 4},/area/hallway/primary/fore) "aAs" = (/obj/structure/disposalpipe/segment,/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor/plating,/area/maintenance/fsmaint) "aAt" = (/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers{dir = 4; initialize_directions = 11; level = 1},/turf/simulated/wall,/area) -"aAu" = (/obj/machinery/light{dir = 8},/obj/item/device/radio/intercom{freerange = 0; frequency = 1459; name = "Station Intercom (General)"; pixel_x = -30},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) +"aAu" = (/obj/machinery/light{dir = 8},/obj/item/device/radio/intercom{freerange = 0; frequency = 1459; name = "Station Intercom (General)"; pixel_x = -30},/obj/effect/landmark{name = "JoinLateCryo"},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) "aAv" = (/obj/machinery/light{dir = 8},/turf/simulated/floor{dir = 8; icon_state = "neutral"},/area/crew_quarters/fitness) "aAw" = (/obj/structure/stool{pixel_y = 8},/turf/simulated/floor,/area/crew_quarters/fitness) "aAx" = (/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/effect/landmark/start{name = "Civilian"},/turf/simulated/floor/wood,/area/crew_quarters/fitness) @@ -1735,16 +1735,16 @@ "aHs" = (/obj/machinery/light/small{dir = 1},/obj/machinery/alarm{pixel_y = 23},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/turf/simulated/floor{icon_state = "vault"},/area/security/nuke_storage) "aHt" = (/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor{icon_state = "vault"; dir = 10},/area/security/nuke_storage) "aHu" = (/obj/machinery/status_display{density = 0; layer = 4; pixel_x = 0; pixel_y = 32},/obj/structure/filingcabinet,/obj/item/weapon/folder/documents,/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/security/nuke_storage) -"aHv" = (/obj/machinery/gateway{dir = 10},/turf/simulated/floor{icon_state = "vault"; dir = 4},/area/gateway) -"aHw" = (/obj/machinery/gateway{density = 0},/obj/structure/cable{d2 = 2; icon_state = "0-2"},/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/gateway) -"aHx" = (/obj/machinery/gateway{dir = 6},/turf/simulated/floor{icon_state = "vault"; dir = 1},/area/gateway) +"aHv" = (/obj/effect/landmark{name = "JoinLateCryo"},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) +"aHw" = (/obj/machinery/gateway{dir = 10},/obj/effect/landmark{name = "JoinLateGateway"},/turf/simulated/floor{icon_state = "vault"; dir = 4},/area/gateway) +"aHx" = (/obj/machinery/gateway{dir = 6},/obj/effect/landmark{name = "JoinLateGateway"},/turf/simulated/floor{icon_state = "vault"; dir = 1},/area/gateway) "aHy" = (/obj/structure/rack{dir = 8; layer = 2.9},/obj/item/weapon/tank/jetpack/carbondioxide,/turf/simulated/floor{icon_state = "dark"},/area/ai_monitored/storage/eva) "aHz" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/camera/motion{c_tag = "EVA West"; dir = 4; network = list("SS13")},/obj/structure/table/reinforced,/obj/item/device/assembly/signaler,/obj/item/device/assembly/signaler,/obj/item/weapon/storage/toolbox/electrical{pixel_x = 1; pixel_y = -1},/turf/simulated/floor{dir = 8; icon_state = "warning"},/area/ai_monitored/storage/eva) "aHA" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/turf/simulated/floor,/area/ai_monitored/storage/eva) "aHB" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"; pixel_x = 0; tag = ""},/obj/machinery/camera{c_tag = "EVA East"; dir = 8; network = list("SS13")},/obj/structure/table/reinforced,/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/metal{amount = 50},/obj/item/stack/sheet/metal{amount = 50},/turf/simulated/floor{dir = 4; icon_state = "warning"},/area/ai_monitored/storage/eva) "aHC" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced,/obj/structure/cable{d2 = 8; icon_state = "0-8"},/obj/structure/cable{d2 = 8; icon_state = "0-8"},/turf/simulated/floor/plating,/area/ai_monitored/storage/eva) "aHD" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8; initialize_directions = 11; level = 1},/turf/simulated/floor/plating,/area/maintenance/fsmaint) -"aHE" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) +"aHE" = (/obj/machinery/gateway{density = 0},/obj/structure/cable{d2 = 2; icon_state = "0-2"},/obj/effect/landmark{name = "JoinLateGateway"},/turf/simulated/floor{icon_state = "vault"; dir = 8},/area/gateway) "aHF" = (/obj/structure/sink{icon_state = "sink"; dir = 8; pixel_x = -12; pixel_y = 2},/obj/structure/mirror{pixel_x = -28},/obj/machinery/light{dir = 1},/turf/simulated/floor{icon_state = "freezerfloor"},/area/crew_quarters/toilet) "aHG" = (/turf/simulated/floor{icon_state = "freezerfloor"},/area/crew_quarters/toilet) "aHH" = (/obj/structure/urinal{pixel_y = 32},/turf/simulated/floor{icon_state = "freezerfloor"},/area/crew_quarters/toilet) @@ -7336,9 +7336,9 @@ "cLd" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating,/area/aisat/entrance) "cLe" = (/obj/structure/grille,/obj/structure/window/reinforced,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating,/area/aisat/entrance) "cLf" = (/obj/structure/transit_tube{icon_state = "N-S"},/turf/simulated/floor{tag = "icon-brown (EAST)"; icon_state = "brown"; dir = 4},/area/aisat/entrance) -"cLg" = (/obj/structure/table,/obj/item/device/radio{pixel_x = -6; pixel_y = 4},/obj/item/weapon/crowbar,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/obj/machinery/firealarm{dir = 2; pixel_y = 24},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) +"cLg" = (/obj/structure/table,/obj/item/device/radio{pixel_x = -6; pixel_y = 4},/obj/item/weapon/crowbar,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 6},/obj/machinery/alarm{pixel_y = 25; target_temperature = 283.15},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) "cLh" = (/obj/structure/closet/emcloset,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) -"cLi" = (/obj/structure/closet/emcloset,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/item/device/radio/intercom{dir = 4; name = "Station Intercom (General)"; pixel_x = 27},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) +"cLi" = (/obj/structure/closet/emcloset,/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/item/device/radio/intercom{dir = 4; name = "Station Intercom (General)"; pixel_x = 27},/obj/machinery/light_switch{pixel_x = 25; pixel_y = -9},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) "cLj" = (/obj/machinery/light{dir = 1; on = 1},/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/obj/effect/decal/warning_stripes/east,/obj/item/device/radio/intercom{broadcasting = 0; name = "Station Intercom (General)"; pixel_y = 20},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) "cLk" = (/obj/machinery/computer/teleporter,/turf/simulated/floor/plating,/area/aisat/entrance) "cLl" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) @@ -7347,14 +7347,14 @@ "cLo" = (/obj/machinery/bluespace_beacon,/obj/effect/decal/warning_stripes/east,/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) "cLp" = (/obj/machinery/teleport/station,/turf/simulated/floor/plating,/area/aisat/entrance) "cLq" = (/obj/machinery/light,/obj/structure/transit_tube/station{icon_state = "closed"; dir = 4},/obj/machinery/status_display{pixel_x = 0; pixel_y = -32},/turf/simulated/floor{tag = "icon-brown (EAST)"; icon_state = "brown"; dir = 4},/area/aisat/entrance) -"cLr" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/light_switch{pixel_y = -25},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) +"cLr" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/firealarm{dir = 1; pixel_y = -24},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) "cLs" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/poddoor/shutters{dir = 8; id = "teledoor"; name = "AI Satellite Teleport Access"},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) "cLt" = (/obj/machinery/door_control{desc = "A remote control-switch for the engineering security doors."; id = "teledoor"; name = "AI Satellite Teleport Shutters Control"; pixel_x = 0; pixel_y = -25; req_access_txt = "17;75"},/obj/effect/decal/warning_stripes/east,/obj/machinery/camera{c_tag = "Mini Satellite Teleporter"; dir = 1; network = list("SS13","MiniSat")},/obj/machinery/atmospherics/unary/vent_scrubber{on = 1; scrub_N2O = 1; scrub_Toxins = 1},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) "cLu" = (/obj/machinery/teleport/hub,/turf/simulated/floor/plating,/area/aisat/entrance) "cLv" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating,/area/aisat/entrance) "cLw" = (/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable{icon_state = "0-2"; pixel_y = 1; d2 = 2},/obj/machinery/power/apc{dir = 1; name = "AI Satellite Exterior APC"; pixel_y = 24},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) -"cLx" = (/obj/machinery/alarm{pixel_y = 25; target_temperature = 283.15},/obj/machinery/camera{c_tag = "Mini Satellite Entrance"; dir = 2; network = list("SS13","MiniSat")},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) -"cLy" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) +"cLx" = (/obj/machinery/camera{c_tag = "Mini Satellite Entrance"; dir = 2; network = list("SS13","MiniSat")},/obj/machinery/computer/cryopod/robot{pixel_y = 30},/obj/effect/landmark{name = "JoinLateCyborg"},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) +"cLy" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/cryopod/robot,/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) "cLz" = (/obj/machinery/door/airlock/external{name = "MiniSat External Access"; req_access = null; req_access_txt = "75;13"},/turf/simulated/floor/plating,/area/aisat) "cLA" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor/plating,/area/aisat/entrance) "cLB" = (/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 8; initialize_directions = 11; level = 1},/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; tag = ""},/turf/simulated/floor{dir = 5; icon_state = "dark"; tag = "icon-vault (NORTHEAST)"},/area/aisat/entrance) @@ -12548,6 +12548,8 @@ "eHp" = (/obj/machinery/light/small{dir = 4},/obj/item/clothing/head/helmet/space/syndicate/black/red,/turf/simulated/floor/airless,/area/derelict/bridge/ai_upload) "eHq" = (/obj/machinery/navbeacon{codes_txt = "patrol;next_patrol=4-Maint"; location = "3-SMine"},/obj/machinery/atmospherics/pipe/manifold/hidden,/turf/simulated/floor{icon_state = "asteroidfloor"; temperature = 273.15},/area/mine/laborcamp) "eHr" = (/obj/structure/table,/obj/item/weapon/folder/blue,/obj/item/weapon/stamp/hop,/obj/item/device/eftpos,/turf/simulated/floor,/area/crew_quarters/heads) +"eHs" = (/obj/structure/stool/bed,/obj/item/weapon/bedsheet/blue,/obj/machinery/camera{c_tag = "Brig Medbay"; dir = 2; network = list("SS13")},/turf/simulated/floor{icon_state = "white"},/area/security/medbay) +"eHt" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/obj/effect/landmark{name = "JoinLateCryo"},/turf/simulated/floor{icon_state = "white"},/area/crew_quarters/sleep) (1,1,1) = {" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -12625,7 +12627,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagragragragragragragragragraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWabWabWabWabWabWabWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiaffaffafhaaiaffaffafhaaiaaaaaiahyahzahAaaiafQahBahCabJahDahEahFahGaaqahHahIagFahJahKahLaaqahMahNahOahPahQahRahSahTahUahVahWahXahWahYaaiahwahwahwahwahwahwahwahwaaiaaaaaaahxahxahxahxahxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagragragragragragragragragraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWabWabWabWabWabWabWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiafhaffahZaaiafhaffaiaaaiaaiaaiaibaicaidaaiaaqaaqaaqaaqaieaifaigaihaaqaiiaijaikailaimainaaqaioaipaiqairaisaitaiuaivahUahVaiwahXaiwaixaaiahwahwahwahwahwahwahwahwaaiaaaaaaahxahxahxahxahxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagragragragragragragragragraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWabWabWabWabWabWabWaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaiaiyaizaiAaiBaiyaizaiAaiCaaiaaqaaqaaqaaJaaqaaqaaqaaqaiDaiEaiFaiGaiHaaiaiIaiJaiKaiLaiMaaqaaqaiNaiOaPFaiQaisaiRaiQaivaiSahVahTahTaiTaiUaiVahwahwahwahwahwahwahwahwaaiaaaaaaahxahxahxahxahxaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagragragragragragragragragraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWabWabWabWabWabWabWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiaiWaiXaiYaffaiZajaajbajcaaiajdajeajfajgajfajfajfaaqajhajiajjajkajlajmajnajoajpajqajrajsajtajuaiPaiPaiQajvajwajxajyajzajAajBajCajDahTajEahwahwahwahwahwahwahwahwaaiaaaaaaahxahxahxahxahxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajFaaaaaaaaaajFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagragragragragragragragragraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWabWabWabWabWabWabWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiaiWaiXaiYaffaiZajaajbajcaaiajdajeeHsajgajfajfajfaaqajhajiajjajkajlajmajnajoajpajqajrajsajtajuaiPaiPaiQajvajwajxajyajzajAajBajCajDahTajEahwahwahwahwahwahwahwahwaaiaaaaaaahxahxahxahxahxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajFaaaaaaaaaajFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagragragragragragragragragraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabWabWabWabWabWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiajGaffajHajIajJajKajLajMaaiajNajOajPajQajRajSajTaaqajUajVajWajXajlajYajZakaakbakcakdakeakfakgaiPakhakiakjakkaklakmaknakoahTahTahTakpaiVahwahwahwahwahwahwahwahwaaiaaaaaaahxahxahxahxahxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaakqakqakqacuacuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaajFajFajFajFajFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagragragragragragragragragraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaiakraksajHaffaktajKakuakvaaiakwakxakyakzakAakBajTaaqakCakDakEakFakGajmakHakIajpakJakKajsakLakMakNakNakOaisakPakQakRakSahTahWahXahTakTaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiaaaaaaahxahxahxahxahxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaakqaaaaabaaaakUaaaaaaaaaaaaaaaaaaaabaaaajFaaaaaaajFaaaaaaajFajFajFajFajFajFajFaaaaaaajFaaaaaaajFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagragragragragragragragragraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacuakVakWakWakWakXakYaaaaaaaaiaaiaaiaaiaaqaaqakZalaalbaaqaaqalcaldalealfalgalhaliaaqaljalkallajXalmaaqalnaloalpalqalraaqalsaltalualvalwalxalyalzalAalBahTaiwalCalDalEaaiaaiaaiaaiaaiaaiaaaaaaaaaaaaaaaaaaahxahxahxahxahxaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaakqaabalFaabakqaaaaaaaaaaaaaaaaaaaaaaaaajFajFajFajFaaaajFajFajFajFajFajFajFajFajFaaaajFajFajFajFaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -12650,13 +12652,13 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaayaaybaycaybayaaydayeaydayaaabaxBayfaygaaaaaaaaaaaaaaaaaaaaaacuacuacuacuaaaaaaaaaaaaaxDaaaaaaaaaaaaaaaaaaaaaacuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaabaabaabaabaabaabaaqayhayiaxHaaJawNaaqayjaykaylawRaymaxNaxNaynaxNayoayoawZaxNaxOauMauRaypaaqayqaxQayraysaytaaqayuayvaywayxayyayzayAayBayCayDayEayFayGayHayIayJayKayLayMayNayOayPayQayRaaqaxYaxZaxZaxZaxZaxZaxYaaiaabaaaaaaaaaaaaaaaaxuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaySaybayTaybaySaydayUaydaySayVayWayXayYayZayZazaayVayVaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaxDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazbazbazbazbazbazbazbazbazbaabaaqazcazdazeaxVazfabJazgazhaziazjawSazkaxNazlazmaznazoazpazqaxOauMauRauSaaqasgazrazsaysaytaaqaztayRayRayRayRayRayRayRayRayRayRazuazvazwazxazyazzazAazBazBazBazBazCazBazDazEaxZaxZaxZaxZaxZazEaaiaaiaaiaaaaaaaaaaaaaxuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaySazFazGazHaySazIazJazKaySaxCaxCazLazMazNazOazPazQayVaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxDaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaazRazSazTazUazVazWazXazYazbaabaaqazZaAaaAbaaqaAcaaqaAdaAeaAfaAgaAhaznaAiaAjaAkaAlaAmaAnaAoaApaAqavtaArabZaAsaAtaAuaysaytaaqaAvayRayRaAwaAwaAwayRayRayRayRaAxaAyaAzaAAaABaACaADaAEaAFaAGaAFaAFaAHaAFaAIaAJaxZaxZaxZaxZaxZaAKaALaAMaANaaaaaaaaaaaaaxuaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaySaAOaAPaAQaySaAOaAPaAQaySaARaASaASaxCaxCaxCaASaASawHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxDaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaabaabaaaaaaaabaATazSaAUaAVaAWaAXaAYaAYazbaaqaaqaxEabZabZabZaAZabZaBaabZabZabZaBbabZabZaaEabZabZabZabZabsaugaBcauRaBdaaqasgaosaBeaysaytaaqaztayRaAwaBfaBfaBgaAwayRaBhayRaBiaBjaBkaBlaBmaBnaBoaBpaBnaBqaBnaBnaBraBhaBsaANaxZaxZaxZaxZaxZaANaBtaBuaBvaaaaaaaaaaaaaxuaaaaaaaaaaaaaaaaaaaaaaaqaaqaBwaBxaBxaBxaBxaByaaqaaqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaySaAOaAPaAQaySaAOaAPaAQaySaARaASaASaxCaxCaxCaASaASawHaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaxDaaaaaaaaaaaaaaaaaaaaaaaaaabaaaaaaaabaabaaaaaaaabaATazSaAUaAVaAWaAXaAYaAYazbaaqaaqaxEabZabZabZaAZabZaBaabZabZabZaBbabZabZaaEabZabZabZabZabsaugaBcauRaBdaaqasgaosaHvaysaytaaqaztayRaAwaBfaBfaBgaAwayRaBhayRaBiaBjaBkaBlaBmaBnaBoaBpaBnaBqaBnaBnaBraBhaBsaANaxZaxZaxZaxZaxZaANaBtaBuaBvaaaaaaaaaaaaaxuaaaaaaaaaaaaaaaaaaaaaaaqaaqaBwaBxaBxaBxaBxaByaaqaaqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaayaaySaBzaBAayaaySaBBaBAayaaySaBCaySaySaySaySaySaASaxBaaaaaaaaaaaaaaaaaaaaaaabaaaaBDaBEaBDaabaabaabaabaaaaaaaaaaabazbazbazbazbaBFaBGaBGaBHazbazbazbazbaBIaAYaAYazbaBJaBKaBLaBMaBMaBNaBOaBPaBQaBQaBQaBQaBRaBQaBSaBTaBUaBQaBQaBVaBVaBWaBXaBYaBZabJaCaaosaCbaBeaBeaaqaztayRaAwaCcaCdaCeaAwayRayRaCfaCgaBjaChaCiayRayRaCjaCkayRaClayRayRaCmayRaCnaCoaxZaxZaxZaxZaxZaCoaCpaBuaBvaaaaaaaaaaaaaCqaaaaaaaaaaaaaaaaaaaaqaaqaCraCsaCtaCuaCvaCwaCxaCtaaqaaqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaCyaCzaCAaCzaCBaCzaCCaCzaCDaCEaCFaCFaCFaCFaCGaySaCHaxBaaaaabaabaaaaaaaaaaaaaabaaaaCIaCJaCKaabaaaaabaaaaaaaaaaaaaaaazbaCLaCMaCNaCMaCMaCMaCMaCOaCMaCMaCPaCQaCNaCRaCSaCSaCSaCSaCSaCSaCSaCTaaiaaiaaiaaiaiVabmaaiaCUaaiafaaiVaaiaaiaaiaaiaCVaCWaCXaCYaCZaAtaDaaDbaBeaDcaztayRaAwaDdaBfaBfaAwayRayRayRaDeaDfaDgaDhayRayRaCjaDiayRayRayRayRaDjayRaDkaDlaxZaxZaxZaxZaxZaDmaDnaDoaCoaaaaaaaaaaDpaDqaDpaaaaaaaaaaaqaaqaaqaDraCuaDsaCuaDtaDuaCuaCuaCuaDvaaqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaDwaDxaDyaDzaDAaDBaDCaDDaDEaDCaDFaDGaDCaDCaDHaySaxCayWaabaabaaaaaaaaaaaaaaaaabaDIaDJaDKaDLaDMaaaaabaaaaaaaaaaaaaaaazbaDNazbaDOaDPaDQaDQaDQaDRaDQaDQaDQaDSaDOaDTaDUaDUaDUaDUaDUaDUaDUaAYaaiaDVaDWaDXaDYaDZaEaaEbaEcaEdaEeaEfaDWaEgaaiaEhauRaEiaaqaEjaosaEkaElaElaEmaEnaEoaEpaEqaEqaEraEsaBnaEtaEsaEsaEuaEvaEwayRayRaExaEyaEzaEAaEAaEAaEBayRaECaEDaxZaxZaxZaxZaxZaEEaaiaaiaaiaaaaaaaaaaEFaEGaEFaaaaaaaaqaaqaEHaaqaEIaEJaEKaELaCuaCuaEMaENaCuaEOaaqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaySaEPaEQaEPaERaDyaDyaESaEPaEQaEPaETaEUaEVaEWaySaxCayVayVaEXayZayZayZayZazaayVaEYaEZaFaaFbaEYazbazbaFcaFdaFeazbazbazbaDNaFfaDOaaaaabaaaaabaaaaabaaaaabaaaaDOaDTaDUaFgaFhaFiaFjaFkaDUaAYaaiaFlaFlaFmaFnaFoaFpaFqaFpaFraFsaFtaFlaFlaaiaEhauRaFuaaqaEjaosaBeaysaytaaqaztaFvaFwaFxaFyaFzaFzaFAaFBaFzaFBaFCaFDaFEaFFaFGaFHaFIaFJaFKaFKaFKaFLayRaaqaFMaxZaxZaxZaxZaxZaFNaaiaabaaaaaaaaaaoHaFOaFPaFQaFRaaaaaqaFSaFTaFUaFVaFWaFXaCuaCuaCuaFYaFZaCuaGaaaqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabaabaySaEPaEQaEPaERaDyaDyaESaEPaEQaEPaETaEUaEVaEWaySaxCayVayVaEXayZayZayZayZazaayVaEYaEZaFaaFbaEYazbazbaFcaFdaFeazbazbazbaDNaFfaDOaaaaabaaaaabaaaaabaaaaabaaaaDOaDTaDUaFgaFhaFiaFjaFkaDUaAYaaiaFlaFlaFmaFnaFoaFpaFqaFpaFraFsaFtaFlaFlaaiaEhauRaFuaaqaEjaosaHvaysaytaaqaztaFvaFwaFxaFyaFzaFzaFAaFBaFzaFBaFCaFDaFEaFFaFGaFHaFIaFJaFKaFKaFKaFLayRaaqaFMaxZaxZaxZaxZaxZaFNaaiaabaaaaaaaaaaoHaFOaFPaFQaFRaaaaaqaFSaFTaFUaFVaFWaFXaCuaCuaCuaFYaFZaCuaGaaaqaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaaaaaaaaaaaaabaGbayaaGcaAPaGdaGeaGfaGgaGhaGdaAPaGiaGjayaaGkaGlaySaxCaxCaxCaxCaxCaxCaxCaxCaGmaGnaEYaGoaGpaGqaEYaGraGsaCMaCMaCMaCMaCMaGtaGuaGvaDOaabaGwaGwaGwaGwaGwaGwaGwaabaDOaDTaDUaGxaGyaGzaGAaGxaDUaAYaaiaaiaaiaaiaGBaGCaDWaGDaDWaGCaGEaaiaaiaaiaaiaEhauRaGFaaqaEjaosaAuaysaytaaqaAvaGGaaqaaqaaqaaqaaqaaqaaqaGHaaqaaqaaqaaqaaqaaqaGIaaqaGJaGKaGLaGMaGNaaqaaqaFMaxZaxZaxZaxZaxZaFNaaiaaaaaaaaaaaaaaiaGOaGPaGQaaiaaaaaqaGRaGSaaqaGTaGUaGVaGWaGXaGYaGZaHaaDtaaqaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaDwaEQaHbaHcaHcaHcaHcaHdaEQaDwaHeayaaHfaHgaySaHhaHhaHhaHhaHhaHhaHhaxCaHiaHjaEYaHkaHlaHmaEYaHnaHoaHnaHnaHnaHnaHnaHnaHnaHnaHpaaaaGwaHqaHraHsaHtaHuaGwaaaaDOaDTaDUaGxaHvaHwaHxaGxaDUaAYaaiaHyaHyaFmaHzaHAaFpaFqaFpaHAaHBaHCaFlaFlaaiaEhauRaEiaaqaHDaxQaHEaysaytaaqaztaGGaaqaHFaHGaHHaHHaaqaHIaHGaHJaaqaHKaHLaHMaaqaHNaaqaHOaHPaHPaHPaHQaaqaabaHRaHSaHSaHSaHSaHSaHTaabaaaaaaaagaaaaaiaHUaHVaHWaaiaaaaaqaHXaHYaaqaaqaaqaaqaaqaHZaaqaaqaaqaaqaaqaaqaaiaaiaaiaaiaaiaaiaaiaaiaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaDwaEQaHbaHcaHcaHcaHcaHdaEQaDwaHeayaaHfaHgaySaHhaHhaHhaHhaHhaHhaHhaxCaHiaHjaEYaHkaHlaHmaEYaHnaHoaHnaHnaHnaHnaHnaHnaHnaHnaHpaaaaGwaHqaHraHsaHtaHuaGwaaaaDOaDTaDUaGxaHwaHEaHxaGxaDUaAYaaiaHyaHyaFmaHzaHAaFpaFqaFpaHAaHBaHCaFlaFlaaiaEhauRaEiaaqaHDaxQeHtaysaytaaqaztaGGaaqaHFaHGaHHaHHaaqaHIaHGaHJaaqaHKaHLaHMaaqaHNaaqaHOaHPaHPaHPaHQaaqaabaHRaHSaHSaHSaHSaHSaHTaabaaaaaaaagaaaaaiaHUaHVaHWaaiaaaaaqaHXaHYaaqaaqaaqaaqaaqaHZaaqaaqaaqaaqaaqaaqaaiaaiaaiaaiaaiaaiaaiaaiaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIaaIbaIcaIbaIbaIdaIeaIbaIbaIcaIfaIgayaaERaIhaySaIiaIjaIkaIlaImaInaHhaxCaIoayVaEYaEYaIpaIqaHpaIraIsaItaIuaIvaIwaIxaIyaIzaIAaHpaabaGwaIBaICaIDaIEaIFaGwaabaDOaDTaDUaIGaIHaIIaIJaIKaDUaAYaaiaDVaDWaILaIMaGCaDWaINaDWaGCaIOaIPaDWaEgaaiaEhauRaIQaaqaEjazrazsaysaytaaqaIRaISaaqaITaHGaHGaHGaIUaIVaIWaIXaaqaIYaIZaJaaJbaJcaaqaJdaJeaJfaJeaJgaaqaaaaabaaaaabaaaaabaaaaabaaaaaaaaaaaaaaaaaiaJhaJiaJjaaiaJkaaqaaqaaqaaqaJlaJmaJnaJnaJoaJnaJpaJnaJqaJraJraJsaJraJraJraJraJtaJuaJvaaiaJwaaiaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaIaaIfaIbaJxaJyaJzaJAaJBaJCaJDaJEaJFaJGaJHaJIaEPaERaJJaySaJKaJLaJMaJNaJMaJOaJPaxCaJQaJRaJSaJTaJUaJVaJWaJXaJYaJZaJZaJZaKaaJZaJZaKbaKcaHpaaaaGwaKdaICaKeaIEaKfaGwaaaaDOaDTaDUaKgaKhaKiaKjaKkaDUaAYaaiaKlaKlaFmaKmaHAaFpaKnaFpaHAaKoaFtaKpaKpaaiaKqawzaKraaqaEjazrabZabZabZabZaKsaKtaKuaKvaKwabZabZabZaaEabZabsaKxaKyaKzaKAabZaKBaaqaaqaaqaaqaaqaaqaaqaaqaaqaaqaaiaaiaaiaaiaoHaoJaaiaaiaaiaaiaaiaaiaKCaamaaiaKDaKEaKFaKGaKHaKIaKJabZabZabZabZaaEaKKaKLabZabZaKMabZaBbabZabZaaEaKNaaqaaqaKOaaiaaiaaiaaiaaiaaiaaiaaiaaiaaiabAacOaaaaaaaaaaaaaaaaaaaaaaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaJHaKQaKRaKSaJGaKTaJzaKTaJzaKTaJzaKTaJGaKUaKVaGdaERaKWaySaKXaKYaKZaLaaLbaLcaHhaLdaLeaLfaLgaLhaLiaLjaHnaLkaJZaJZaJZaJZaJZaJZaJZaKbaLlaHpaabaGwaLmaLnaLoaLpaLqaGwaabaDOaDTaDUaLraLsaLtaLuaLvaDUaAYaaiaaiaaiaaiaLwaGCaDWaGDaDWaGCaLxaaiaaiaaiaaiaLyaLzaLAaaqaHDaLBaLCaLCaLCaLDaLEaADabJaLFaLGabJaLHabJaLIabJaLJaxXaLKaLLaLMaaqaLNaLOaLPaLQaLQaLOaLRaLSaLSaLSaLSaLSaLTaLUaLSaLVaLWaLXaLYaLZaMaaMaaMbaMcaMdaMdaMdaMeaJuaMfaMgaMhaMiaaqaMjaMkaMlaaJaaqaMmaaqaMnaMoaMpaMqaMraMsaMtaMuaMvaMwaMxaaiaMyaMzaMAaMBaMCaMDaMEaMFaMGaMHaaaaaaaaaaaaaaaaaaaaaaKPaKPaKPaKPaKPaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaMIaaaaaaaaaaaaaaaaaaaaaaaa diff --git a/paradise.dme b/paradise.dme index 74f82e2588c..47dbfeb97ed 100644 --- a/paradise.dme +++ b/paradise.dme @@ -922,6 +922,7 @@ #include "code\modules\client\client procs.dm" #include "code\modules\client\preferences.dm" #include "code\modules\client\preferences_mysql.dm" +#include "code\modules\client\preferences_spawnpoints.dm" #include "code\modules\client\preferences_toggles.dm" #include "code\modules\clothing\clothing.dm" #include "code\modules\clothing\glasses\glasses.dm" @@ -1256,6 +1257,7 @@ #include "code\modules\mob\living\silicon\ai\ai.dm" #include "code\modules\mob\living\silicon\ai\death.dm" #include "code\modules\mob\living\silicon\ai\examine.dm" +#include "code\modules\mob\living\silicon\ai\latejoin.dm" #include "code\modules\mob\living\silicon\ai\laws.dm" #include "code\modules\mob\living\silicon\ai\life.dm" #include "code\modules\mob\living\silicon\ai\login.dm"