diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index 586d2d502be..73f9aee5342 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -954,6 +954,8 @@ var/global/list/humanoid_icon_cache = list() if(outfit) body.equipOutfit(outfit, TRUE) + SSoverlays.Flush() + var/icon/out_icon = icon('icons/effects/effects.dmi', "nothing") body.setDir(NORTH) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 2fa8d1a01a0..37439340cb4 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -186,15 +186,17 @@ Turf and target are seperate in case you want to teleport some distance from a t return 1 //Generalised helper proc for letting mobs rename themselves. Used to be clname() and ainame() -/mob/proc/rename_self(role) +/mob/proc/rename_self(role, client/C) + if(!C) + C = client var/oldname = real_name var/newname var/loop = 1 var/safety = 0 while(loop && safety < 5) - if(client && client.prefs.custom_names[role] && !safety) - newname = client.prefs.custom_names[role] + if(C && C.prefs.custom_names[role] && !safety) + newname = C.prefs.custom_names[role] else switch(role) if("clown") diff --git a/code/controllers/subsystem/jobs.dm b/code/controllers/subsystem/jobs.dm index 5af4109fdb8..9a3cddee03a 100644 --- a/code/controllers/subsystem/jobs.dm +++ b/code/controllers/subsystem/jobs.dm @@ -360,7 +360,15 @@ var/datum/subsystem/job/SSjob return 1 //Gives the player the stuff he should have with his rank -/datum/subsystem/job/proc/EquipRank(mob/living/H, rank, joined_late=0) +/datum/subsystem/job/proc/EquipRank(mob/M, rank, joined_late=0) + var/mob/new_player/N + var/mob/living/H + if(!joined_late) + N = M + H = N.new_character + else + H = M + var/datum/job/job = GetJob(rank) H.job = rank @@ -401,17 +409,21 @@ var/datum/subsystem/job/SSjob var/new_mob = job.equip(H) if(ismob(new_mob)) H = new_mob + if(!joined_late) + N.new_character = H + else + M = H - H << "You are the [rank]." - H << "As the [rank] you answer directly to [job.supervisors]. Special circumstances may change this." - H << "To speak on your departments radio, use the :h button. To see others, look closely at your headset." + M << "You are the [rank]." + M << "As the [rank] you answer directly to [job.supervisors]. Special circumstances may change this." + M << "To speak on your departments radio, use the :h button. To see others, look closely at your headset." if(job.req_admin_notify) - H << "You are playing a job that is important for Game Progression. If you have to disconnect, please notify the admins via adminhelp." + M << "You are playing a job that is important for Game Progression. If you have to disconnect, please notify the admins via adminhelp." if(config.minimal_access_threshold) - H << "As this station was initially staffed with a [config.jobs_have_minimal_access ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card." + M << "As this station was initially staffed with a [config.jobs_have_minimal_access ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card." if(job && H) - job.after_spawn(H) + job.after_spawn(H, M) return H diff --git a/code/controllers/subsystem/processing/overlays.dm b/code/controllers/subsystem/processing/overlays.dm index 1508142a8d9..9a93fbd4b4b 100644 --- a/code/controllers/subsystem/processing/overlays.dm +++ b/code/controllers/subsystem/processing/overlays.dm @@ -18,25 +18,29 @@ var/datum/subsystem/processing/overlays/SSoverlays /datum/subsystem/processing/overlays/Initialize() initialized = TRUE - for(var/I in processing) - var/atom/A = I - A.compile_overlays() - CHECK_TICK - processing.Cut() + Flush() ..() /datum/subsystem/processing/overlays/Recover() overlay_icon_state_caches = SSoverlays.overlay_icon_state_caches processing = SSoverlays.processing -/datum/subsystem/processing/overlays/fire() +/datum/subsystem/processing/overlays/fire(resumed = FALSE, mc_check = TRUE) while(processing.len) var/atom/thing = processing[processing.len] processing.len-- if(thing) thing.compile_overlays(FALSE) - if(MC_TICK_CHECK) - break + if(mc_check) + if(MC_TICK_CHECK) + break + else + CHECK_TICK + +/datum/subsystem/processing/overlays/proc/Flush() + if(processing.len) + testing("Flushing [processing.len] overlays") + fire(mc_check = FALSE) //pair this thread up with the MC to get extra compile time /atom/proc/compile_overlays() if(LAZYLEN(priority_overlays) && LAZYLEN(our_overlays)) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 9a73bc96828..45ad08bcf4f 100644 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -125,6 +125,8 @@ var/datum/subsystem/ticker/ticker declare_completion(force_ending) /datum/subsystem/ticker/proc/setup() + world << "Starting game..." + var/init_start = world.timeofday //Create and announce mode var/list/datum/game_mode/runnable_modes if(master_mode == "random" || master_mode == "secret") @@ -154,10 +156,13 @@ var/datum/subsystem/ticker/ticker SSjob.ResetOccupations() return 0 + CHECK_TICK //Configure mode and assign player to special mode stuff var/can_continue = 0 can_continue = src.mode.pre_setup() //Choose antagonists + CHECK_TICK SSjob.DivideOccupations() //Distribute jobs + CHECK_TICK if(!Debug2) if(!can_continue) @@ -169,6 +174,7 @@ var/datum/subsystem/ticker/ticker else message_admins("DEBUG: Bypassing prestart checks...") + CHECK_TICK if(hide_mode) var/list/modes = new for (var/datum/game_mode/M in runnable_modes) @@ -179,21 +185,30 @@ var/datum/subsystem/ticker/ticker else mode.announce() - current_state = GAME_STATE_PLAYING if(!config.ooc_during_round) toggle_ooc(0) // Turn it off - round_start_time = world.time + CHECK_TICK start_landmarks_list = shuffle(start_landmarks_list) //Shuffle the order of spawn points so they dont always predictably spawn bottom-up and right-to-left - create_characters() //Create player characters and transfer them + create_characters() //Create player characters collect_minds() equip_characters() + + SSoverlays.Flush() //Flush the majority of the shit + data_core.manifest() - Master.RoundStart() + transfer_characters() //transfer keys to the new mobs + + Master.RoundStart() //let the party begin... + + log_world("Game start took [(world.timeofday - init_start)/10]s") + round_start_time = world.time world << "Welcome to [station_name()], enjoy your stay!" world << sound('sound/AI/welcome.ogg') + + current_state = GAME_STATE_PLAYING if(SSevent.holidays) world << "and..." @@ -353,36 +368,39 @@ var/datum/subsystem/ticker/ticker for(var/mob/new_player/player in player_list) if(player.ready && player.mind) joined_player_list += player.ckey - if(player.mind.assigned_role=="AI") - player.close_spawn_windows() - player.AIize() - else - player.create_character() - qdel(player) + player.create_character(FALSE) else player.new_player_panel() - + CHECK_TICK /datum/subsystem/ticker/proc/collect_minds() for(var/mob/living/player in player_list) if(player.mind) ticker.minds += player.mind + CHECK_TICK /datum/subsystem/ticker/proc/equip_characters() var/captainless=1 - for(var/mob/living/carbon/human/player in player_list) - if(player && player.mind && player.mind.assigned_role) + for(var/mob/new_player/N in player_list) + var/mob/living/carbon/human/player = N.new_character + if(istype(player) && player.mind && player.mind.assigned_role) if(player.mind.assigned_role == "Captain") captainless=0 if(player.mind.assigned_role != player.mind.special_role) - SSjob.EquipRank(player, player.mind.assigned_role, 0) + SSjob.EquipRank(N, player.mind.assigned_role, 0) + CHECK_TICK if(captainless) - for(var/mob/M in player_list) - if(!isnewplayer(M)) - M << "Captainship not forced on anyone." - + for(var/mob/new_player/N in player_list) + if(N.new_character) + N << "Captainship not forced on anyone." + CHECK_TICK +/datum/subsystem/ticker/proc/transfer_characters() + for(var/mob/new_player/player in player_list) + if(player.transfer_character()) + qdel(player) + /datum/subsystem/ticker/proc/declare_completion() set waitfor = FALSE diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index f10a33b75e5..e8c3b7a8f08 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -66,8 +66,10 @@ return /datum/datacore/proc/manifest() - for(var/mob/living/carbon/human/H in player_list) - manifest_inject(H) + for(var/mob/new_player/N in player_list) + if(ishuman(N.new_character)) + manifest_inject(N.new_character, N.client) + CHECK_TICK /datum/datacore/proc/manifest_modify(name, assignment) var/datum/data/record/foundrecord = find_record("name", name, data_core.general) @@ -183,7 +185,7 @@ var/record_id_num = 1001 -/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H) +/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C) if(H.mind && (H.mind.assigned_role != H.mind.special_role)) var/assignment if(H.mind.assigned_role) @@ -194,7 +196,9 @@ var/record_id_num = 1001 assignment = "Unassigned" var/id = num2hex(record_id_num++,6) - var/image = get_id_photo(H) + if(!C) + C = H.client + var/image = get_id_photo(H, C) var/obj/item/weapon/photo/photo_front = new() var/obj/item/weapon/photo/photo_side = new() photo_front.photocreate(null, icon(image, dir = SOUTH)) @@ -262,7 +266,11 @@ var/record_id_num = 1001 locked += L return -/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H) +/datum/datacore/proc/get_id_photo(mob/living/carbon/human/H, client/C) var/datum/job/J = SSjob.GetJob(H.mind.assigned_role) - var/datum/preferences/P = H.client.prefs + var/datum/preferences/P + if(!C) + C = H.client + if(C) + P = C.prefs return get_flat_human_icon(null,J.outfit,P) diff --git a/code/modules/jobs/job_types/civilian.dm b/code/modules/jobs/job_types/civilian.dm index 283641ca7de..0eed62b3e11 100644 --- a/code/modules/jobs/job_types/civilian.dm +++ b/code/modules/jobs/job_types/civilian.dm @@ -17,6 +17,9 @@ Clown access = list(access_theatre) minimal_access = list(access_theatre) +/datum/job/clown/after_spawn(mob/living/carbon/human/H, mob/M) + H.rename_self("clown", M.client) + /datum/outfit/job/clown name = "Clown" jobtype = /datum/job/clown @@ -57,7 +60,6 @@ Clown return H.dna.add_mutation(CLOWNMUT) - H.rename_self("clown") /* Mime @@ -78,6 +80,9 @@ Mime access = list(access_theatre) minimal_access = list(access_theatre) +/datum/job/mime/after_spawn(mob/living/carbon/human/H, mob/M) + H.rename_self("mime", M.client) + /datum/outfit/job/mime name = "Mime" jobtype = /datum/job/mime @@ -106,8 +111,6 @@ Mime H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/mime/speak(null)) H.mind.miming = 1 - H.rename_self("mime") - /* Librarian */ diff --git a/code/modules/jobs/job_types/job.dm b/code/modules/jobs/job_types/job.dm index 506e12466b9..4b4a33d0acd 100644 --- a/code/modules/jobs/job_types/job.dm +++ b/code/modules/jobs/job_types/job.dm @@ -44,7 +44,9 @@ var/outfit = null //Only override this proc -/datum/job/proc/after_spawn(mob/living/carbon/human/H) +//H is usually a human unless an /equip override transformed it +/datum/job/proc/after_spawn(mob/living/H, mob/M) + //do actions on H but send messages to M as the key may not have been transferred_yet /datum/job/proc/announce(mob/living/carbon/human/H) @@ -52,7 +54,7 @@ announce_head(H, head_announce) -//But don't override this +//Don't override this unless the job transforms into a non-human (Silicons do this for example) /datum/job/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE, announce = TRUE) if(!H) return 0 diff --git a/code/modules/jobs/job_types/security.dm b/code/modules/jobs/job_types/security.dm index cae08cd353f..f436d8544c9 100644 --- a/code/modules/jobs/job_types/security.dm +++ b/code/modules/jobs/job_types/security.dm @@ -183,7 +183,7 @@ Security Officer var/list/available_depts = list(SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT_SCIENCE, SEC_DEPT_SUPPLY) -/datum/job/officer/after_spawn(mob/living/carbon/human/H) +/datum/job/officer/after_spawn(mob/living/carbon/human/H, mob/M) // Assign department security var/department if(H && H.client && H.client.prefs) @@ -255,9 +255,9 @@ var/list/available_depts = list(SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT else break if(department) - H << "You have been assigned to [department]!" + M << "You have been assigned to [department]!" else - H << "You have not been assigned to any department. Patrol the halls and help where needed." + M << "You have not been assigned to any department. Patrol the halls and help where needed." diff --git a/code/modules/jobs/job_types/silicon.dm b/code/modules/jobs/job_types/silicon.dm index c234b05fbd3..982d5cb934d 100644 --- a/code/modules/jobs/job_types/silicon.dm +++ b/code/modules/jobs/job_types/silicon.dm @@ -14,8 +14,17 @@ AI minimal_player_age = 30 /datum/job/ai/equip(mob/living/carbon/human/H) - if(!H) - return 0 + return H.AIize(FALSE) + +/datum/job/ai/after_spawn(mob/living/silicon/ai/AI, mob/M) + AI.rename_self("ai", M.client) + + //we may have been created after our borg + if(ticker.current_state == GAME_STATE_SETTING_UP) + for(var/mob/living/silicon/robot/R in silicon_mobs) + if(!R.connected_ai) + R.TryConnectToAI() + /datum/job/ai/config_check() if(config && config.allow_ai) @@ -37,6 +46,8 @@ Cyborg minimal_player_age = 21 /datum/job/cyborg/equip(mob/living/carbon/human/H) - if(!H) - return 0 - return H.Robotize() + return H.Robotize(FALSE, FALSE) + +/datum/job/cyborg/after_spawn(mob/living/silicon/robot/R, mob/M) + if(config.rename_cyborg) //name can't be set in robot/New without the client + R.rename_self("cyborg", M.client) \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 7f2cc3bce6f..c331d0d041b 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -114,13 +114,8 @@ if(lawupdate) make_laws() - connected_ai = select_active_ai_with_fewest_borgs() - if(connected_ai) - connected_ai.connected_robots += src - lawsync() - lawupdate = 1 - else - lawupdate = 0 + if(!TryConnectToAI()) + lawupdate = FALSE radio = new /obj/item/device/radio/borg(src) if(!scrambledcodes && !camera) @@ -1037,3 +1032,12 @@ riding_datum.unequip_buckle_inhands(user) riding_datum.restore_position(user) . = ..(user) + +/mob/living/silicon/robot/proc/TryConnectToAI() + connected_ai = select_active_ai_with_fewest_borgs() + if(connected_ai) + connected_ai.connected_robots += src + lawsync() + lawupdate = 1 + return TRUE + return FALSE \ No newline at end of file diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 146b0e6c359..2cd5bb75d79 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -13,6 +13,7 @@ canmove = 0 anchored = 1 // don't get pushed around + var/mob/living/new_character //for instant transfer once the round is set up /mob/new_player/New() tag = "mob_[next_mob_id++]" @@ -305,9 +306,9 @@ SSjob.AssignRole(src, rank, 1) - var/mob/living/character = create_character() //creates the human and transfers vars and mind + var/mob/living/character = create_character(TRUE) //creates the human and transfers vars and mind var/equip = SSjob.EquipRank(character, rank, 1) - if(iscyborg(equip)) //Borgs get borged in the equip, so we need to make sure we handle the new mob. + if(isliving(equip)) //Borgs get borged in the equip, so we need to make sure we handle the new mob. character = equip @@ -426,27 +427,33 @@ popup.open(0) // 0 is passed to open so that it doesn't use the onclose() proc -/mob/new_player/proc/create_character() +/mob/new_player/proc/create_character(transfer_after) spawning = 1 close_spawn_windows() - var/mob/living/carbon/human/new_character = new(loc) + var/mob/living/carbon/human/H = new(loc) if(config.force_random_names || jobban_isbanned(src, "appearance")) client.prefs.random_character() client.prefs.real_name = client.prefs.pref_species.random_name(gender,1) - client.prefs.copy_to(new_character) - new_character.dna.update_dna_identity() + client.prefs.copy_to(H) + H.dna.update_dna_identity() if(mind) mind.active = 0 //we wish to transfer the key manually - mind.transfer_to(new_character) //won't transfer key since the mind is not active + mind.transfer_to(H) //won't transfer key since the mind is not active - new_character.name = real_name + H.name = real_name - new_character.key = key //Manually transfer the key to log them in - new_character.stopLobbySound() + . = H + new_character = . + if(transfer_after) + transfer_character() - return new_character +/mob/new_player/proc/transfer_character() + . = new_character + if(.) + new_character.key = key //Manually transfer the key to log them in + new_character.stopLobbySound() /mob/new_player/proc/ViewManifest() var/dat = "" diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 02f0821bd54..7d3a79353f9 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -286,11 +286,6 @@ qdel(src) - -/mob/new_player/AIize() - spawning = 1 - return ..() - /mob/living/carbon/human/AIize() if (notransform) return @@ -311,7 +306,7 @@ invisibility = INVISIBILITY_MAXIMUM return ..() -/mob/proc/AIize() +/mob/proc/AIize(transfer_after = TRUE) if(client) stopLobbySound() @@ -334,13 +329,14 @@ if (sloc.name == "AI") loc_landmark = sloc.loc + if(!transfer_after) + mind.active = FALSE + . = new /mob/living/silicon/ai(loc_landmark, null, src) + qdel(src) - return - -//human -> robot -/mob/living/carbon/human/proc/Robotize(delete_items = 0) +/mob/living/carbon/human/proc/Robotize(delete_items = 0, transfer_after = TRUE) if (notransform) return for(var/obj/item/W in src) @@ -367,12 +363,13 @@ R.gender = gender R.invisibility = 0 - if(mind) //TODO + if(!transfer_after) + mind.active = FALSE mind.transfer_to(R) if(mind.special_role) R.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite") - else + else if(transfer_after) R.key = key if (config.rename_cyborg)