diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 9343a4590f..bb17deacf4 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -10,7 +10,7 @@ #define CANPUSH 0x8 #define LEAPING 0x10 #define HIDING 0x20 -#define PASSEMOTES 0x32 // Mob has a cortical borer or holders inside of it that need to see emotes. +#define PASSEMOTES 0x40 // Mob has a cortical borer or holders inside of it that need to see emotes. #define GODMODE 0x1000 #define FAKEDEATH 0x2000 // Replaces stuff like changeling.changeling_fakedeath. #define DISFIGURED 0x4000 // Set but never checked. Remove this sometime and replace occurences with the appropriate organ code diff --git a/code/_helpers/logging.dm b/code/_helpers/logging.dm index f9b7a6e3ef..6644cc2efe 100644 --- a/code/_helpers/logging.dm +++ b/code/_helpers/logging.dm @@ -25,6 +25,11 @@ if (config.log_admin) diary << "\[[time_stamp()]]ADMIN: [text][log_end]" +/proc/log_adminpm(text, client/source, client/dest) + admin_log.Add(text) + if (config.log_admin) + diary << "\[[time_stamp()]]ADMINPM: [key_name(source)]->[key_name(dest)]: [html_decode(text)][log_end]" + /proc/log_debug(text) if (config.log_debug) debug_log << "\[[time_stamp()]]DEBUG: [text][log_end]" diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index ab8111000d..0da6c3c3d5 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -33,7 +33,7 @@ H.restore_all_organs(ignore_prosthetic_prefs=1) //Covers things like fractures and other things not covered by the above. H.restore_blood() H.mutations.Remove(HUSK) - H.status_flags -= DISFIGURED + H.status_flags &= ~DISFIGURED H.update_icons_body() for(var/limb in H.organs_by_name) var/obj/item/organ/external/current_limb = H.organs_by_name[limb] diff --git a/code/game/objects/items/devices/communicator/UI.dm b/code/game/objects/items/devices/communicator/UI.dm index cbdae90c90..f2d3fd39b6 100644 --- a/code/game/objects/items/devices/communicator/UI.dm +++ b/code/game/objects/items/devices/communicator/UI.dm @@ -134,11 +134,7 @@ if(href_list["rename"]) var/new_name = sanitizeSafe(input(usr,"Please enter your name.","Communicator",usr.name) ) if(new_name) - owner = new_name - name = "[owner]'s [initial(name)]" - if(camera) - camera.name = name - camera.c_tag = name + register_device(new_name) if(href_list["toggle_visibility"]) switch(network_visibility) diff --git a/code/game/objects/items/devices/communicator/communicator.dm b/code/game/objects/items/devices/communicator/communicator.dm index f809bcb9b2..7342988916 100644 --- a/code/game/objects/items/devices/communicator/communicator.dm +++ b/code/game/objects/items/devices/communicator/communicator.dm @@ -75,12 +75,12 @@ var/global/list/obj/item/device/communicator/all_communicators = list() //This is a pretty terrible way of doing this. spawn(5 SECONDS) //Wait for our mob to finish spawning. if(ismob(loc)) - register_device(loc) + register_device(loc.name) initialize_exonet(loc) else if(istype(loc, /obj/item/weapon/storage)) var/obj/item/weapon/storage/S = loc if(ismob(S.loc)) - register_device(S.loc) + register_device(S.loc.name) initialize_exonet(S.loc) // Proc: examine() @@ -268,12 +268,12 @@ var/global/list/obj/item/device/communicator/all_communicators = list() // Proc: register_device() // Parameters: 1 (user - the person to use their name for) // Description: Updates the owner's name and the device's name. -/obj/item/device/communicator/proc/register_device(mob/user) - if(!user) +/obj/item/device/communicator/proc/register_device(new_name) + if(!new_name) return - owner = user.name + owner = new_name - name = "[owner]'s [initial(name)]" + name = "[new_name]'s [initial(name)]" if(camera) camera.name = name camera.c_tag = name diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index a9075a8430..a31748d676 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -6,7 +6,7 @@ var/global/floorIsLava = 0 //////////////////////////////// /proc/message_admins(var/msg) msg = "ADMIN LOG: [msg]" - log_adminwarn(msg) + //log_adminwarn(msg) //log_and_message_admins is for this for(var/client/C in admins) if((R_ADMIN|R_MOD) & C.holder.rights) C << msg diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index dcaa745485..4ff94877f4 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -104,7 +104,7 @@ if(C.is_preference_enabled(/datum/client_preference/holder/play_adminhelp_ping)) C << 'sound/effects/adminhelp.ogg' - log_admin("PM: [key_name(src)]->[key_name(C)]: [msg]") + log_adminpm(msg,src,C) send2adminirc("Reply: [key_name(src)]->[key_name(C)]: [html_decode(msg)]") //we don't use message_admins here because the sender/receiver might get it too diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index ea8f029b88..1fc3b1d8ba 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -741,7 +741,15 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O dat += "Language: [current_species.species_language]
" dat += "" if(current_species.spawn_flags & SPECIES_CAN_JOIN) - dat += "
Often present on human stations." + switch(current_species.rarity_value) + if(1 to 2) + dat += "
Often present on human stations." + if(3 to 4) + dat += "
Rarely present on human stations." + if(5) + dat += "
Unheard of on human stations." + else + dat += "
May be present on human stations." if(current_species.spawn_flags & SPECIES_IS_WHITELISTED) dat += "
Whitelist restricted." if(!current_species.has_organ[O_HEART]) diff --git a/code/modules/client/preference_setup/occupation/occupation.dm b/code/modules/client/preference_setup/occupation/occupation.dm index 18e1be05f4..1a09ee6ae9 100644 --- a/code/modules/client/preference_setup/occupation/occupation.dm +++ b/code/modules/client/preference_setup/occupation/occupation.dm @@ -94,7 +94,7 @@ if(job.minimum_character_age && user.client && (user.client.prefs.age < job.minimum_character_age)) . += "[rank] \[MINIMUM CHARACTER AGE: [job.minimum_character_age]]" continue - if((pref.job_civilian_low & ASSISTANT) && (rank != "Assistant")) + if((pref.job_civilian_low & ASSISTANT) && job.flag != ASSISTANT) . += "[rank]" continue if((rank in command_positions) || (rank == "AI"))//Bold head jobs @@ -106,7 +106,7 @@ . += "" - if(rank == "Assistant")//Assistant is special + if(job.flag == ASSISTANT)//Assistant is special if(pref.job_civilian_low & ASSISTANT) . += " \[Yes]" else @@ -180,7 +180,7 @@ if(!job) return 0 - if(role == "Assistant") + if(job.flag == ASSISTANT) if(pref.job_civilian_low & job.flag) pref.job_civilian_low &= ~job.flag else diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index ff8d0d94c6..ee815fd558 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -57,7 +57,7 @@ if (!..()) return 0 - if(species_restricted && istype(M,/mob/living/carbon/human)) + if(LAZYLEN(species_restricted) && istype(M,/mob/living/carbon/human)) var/exclusive = null var/wearable = null var/mob/living/carbon/human/H = M diff --git a/code/modules/mob/animations.dm b/code/modules/mob/animations.dm index 9074357afa..edffbb5a87 100644 --- a/code/modules/mob/animations.dm +++ b/code/modules/mob/animations.dm @@ -167,7 +167,17 @@ note dizziness decrements automatically in the mob's Life() proc. /mob/living/do_attack_animation(atom/A) ..() - is_floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. + //Check for clients with pref enabled + var/list/viewing = list() + for(var/m in viewers(A)) + var/mob/M = m + var/client/C = M.client + if(C && C.is_preference_enabled(/datum/client_preference/attack_icons)) + viewing += M.client + + //Animals attacking each other in the distance, probably. Forgeddaboutit. + if(!viewing.len) + return FALSE // What icon do we use for the attack? var/obj/used_item @@ -180,6 +190,9 @@ note dizziness decrements automatically in the mob's Life() proc. if(!used_item && !(attack_icon && attack_icon_state)) return FALSE //Didn't find an item, not doing animation. + // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement. + is_floating = 0 + var/image/I if(used_item) //Found an in-hand item to animate @@ -192,13 +205,7 @@ note dizziness decrements automatically in the mob's Life() proc. I = image(attack_icon, A, attack_icon_state, A.layer + 1) I.dir = dir - //Check for clients with pref enabled - var/list/viewing = list() - for(var/m in viewers(A)) - var/mob/M = m - var/client/C = M.client - if(C && C.is_preference_enabled(/datum/client_preference/attack_icons)) - viewing += M.client + // Show the overlay to the clients flick_overlay(I, viewing, 5, TRUE) // 5 ticks/half a second // Set the direction of the icon animation. diff --git a/code/modules/mob/freelook/chunk.dm b/code/modules/mob/freelook/chunk.dm index 7c50bd3135..41439b4adc 100644 --- a/code/modules/mob/freelook/chunk.dm +++ b/code/modules/mob/freelook/chunk.dm @@ -100,6 +100,7 @@ for(var/turf in visRemoved) var/turf/t = turf if(obscuredTurfs[t]) + LAZYINITLIST(t.obfuscations) if(!t.obfuscations[obfuscation.type]) var/image/ob_image = image(obfuscation.icon, t, obfuscation.icon_state, OBFUSCATION_LAYER) ob_image.plane = PLANE_FULLSCREEN @@ -141,6 +142,7 @@ for(var/turf in obscuredTurfs) var/turf/t = turf + LAZYINITLIST(t.obfuscations) if(!t.obfuscations[obfuscation.type]) var/image/ob_image = image(obfuscation.icon, t, obfuscation.icon_state, OBFUSCATION_LAYER) ob_image.plane = PLANE_FULLSCREEN diff --git a/code/modules/mob/freelook/update_triggers.dm b/code/modules/mob/freelook/update_triggers.dm index 482025426e..0b31e24cce 100644 --- a/code/modules/mob/freelook/update_triggers.dm +++ b/code/modules/mob/freelook/update_triggers.dm @@ -8,7 +8,7 @@ VN.updateVisibility(A, opacity_check) /turf - var/list/image/obfuscations = new() + var/list/image/obfuscations /turf/drain_power() return -1 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b92ab58641..7184308306 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -94,6 +94,8 @@ stat("Chemical Storage", mind.changeling.chem_charges) stat("Genetic Damage Time", mind.changeling.geneticdamage) stat("Re-Adaptations", "[mind.changeling.readapts]/[mind.changeling.max_readapts]") + if(species) + species.Stat(src) /mob/living/carbon/human/ex_act(severity) if(!blinded) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index b5aef7ac1f..3ce0c85ef1 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1131,7 +1131,7 @@ else sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS) - see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING + see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : see_invisible_default if(XRAY in mutations) sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS @@ -1143,7 +1143,7 @@ if(R && R.word1 == cultwords["see"] && R.word2 == cultwords["hell"] && R.word3 == cultwords["join"]) see_invisible = SEE_INVISIBLE_CULT else - see_invisible = SEE_INVISIBLE_LIVING + see_invisible = see_invisible_default seer = 0 if(!seedarkness) @@ -1154,7 +1154,7 @@ else sight = species.get_vision_flags(src) see_in_dark = species.darksight - see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING + see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : see_invisible_default var/tmp/glasses_processed = 0 var/obj/item/weapon/rig/rig = back @@ -1175,7 +1175,7 @@ if(!glasses_processed && (species.get_vision_flags(src) > 0)) sight |= species.get_vision_flags(src) if(!seer && !glasses_processed && seedarkness) - see_invisible = SEE_INVISIBLE_LIVING + see_invisible = see_invisible_default if(healths) if (chem_effects[CE_PAINKILLER] > 100) @@ -1355,7 +1355,7 @@ if(G.see_invisible >= 0) see_invisible = G.see_invisible else if(!druggy && !seer) - see_invisible = SEE_INVISIBLE_LIVING + see_invisible = see_invisible_default /mob/living/carbon/human/handle_random_events() if(inStasisNow()) diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 39b8460907..787ec95719 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -422,3 +422,7 @@ // Used to override normal fall behaviour. Use only when the species does fall down a level. /datum/species/proc/fall_impact_special(var/mob/living/carbon/human/H, var/atom/A) return FALSE + +// Allow species to display interesting information in the human stat panels +/datum/species/proc/Stat(var/mob/living/carbon/human/H) + return diff --git a/code/modules/mob/living/carbon/metroid/life.dm b/code/modules/mob/living/carbon/metroid/life.dm index 0f393a9417..5cf6395b7d 100644 --- a/code/modules/mob/living/carbon/metroid/life.dm +++ b/code/modules/mob/living/carbon/metroid/life.dm @@ -100,7 +100,7 @@ src.lying = 1 src.blinded = 1 else - if (src.paralysis || src.stunned || src.weakened || (status_flags && FAKEDEATH)) //Stunned etc. + if (src.paralysis || src.stunned || src.weakened || (status_flags & FAKEDEATH)) //Stunned etc. if (src.stunned > 0) src.stat = 0 if (src.weakened > 0) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 23dbb6fc09..9739e596b8 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -55,5 +55,7 @@ var/glow_intensity = null var/glow_color = "#FFFFFF" // The color they're glowing! + var/see_invisible_default = SEE_INVISIBLE_LIVING + var/list/hud_list //Holder for health hud, status hud, wanted hud, etc (not like inventory slots) var/has_huds = FALSE //Whether or not we should bother initializing the above list diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index d022ef71b8..9e4ede05a1 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -298,11 +298,14 @@ proc/get_radio_key_from_channel(var/channel) else return 1 //If we're in nullspace, then forget it. + //Remember the speech images so we can remove them later and they can get GC'd + var/list/images_to_clients = list() + //The 'post-say' static speech bubble var/speech_bubble_test = say_test(message) var/speech_type = speech_bubble_appearance() var/image/speech_bubble = image('icons/mob/talk.dmi',src,"[speech_type][speech_bubble_test]") - spawn(30) qdel(speech_bubble) + images_to_clients[speech_bubble] = list() // Attempt Multi-Z Talking var/mob/above = src.shadow @@ -311,7 +314,7 @@ proc/get_radio_key_from_channel(var/channel) if(ST) var/list/results = get_mobs_and_objs_in_view_fast(ST, world.view) var/image/z_speech_bubble = image('icons/mob/talk.dmi', above, "h[speech_bubble_test]") - spawn(30) qdel(z_speech_bubble) + images_to_clients[z_speech_bubble] = list() for(var/item in results["mobs"]) if(item != above && !(item in listening)) listening[item] = z_speech_bubble @@ -326,12 +329,17 @@ proc/get_radio_key_from_channel(var/channel) var/dst = get_dist(get_turf(M),get_turf(src)) if(dst <= message_range || (M.stat == DEAD && !forbid_seeing_deadchat)) //Inside normal message range, or dead with ears (handled in the view proc) - M << (listening[M] || speech_bubble) // Send the image attached to shadow mob if available + if(M.client) + var/image/I1 = listening[M] || speech_bubble + images_to_clients[I1] |= M.client + M << I1 M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol) - if(whispering) //Don't even bother with these unless whispering if(dst > message_range && dst <= w_scramble_range) //Inside whisper scramble range - M << (listening[M] || speech_bubble) // Send the image attached to shadow mob if available + if(M.client) + var/image/I2 = listening[M] || speech_bubble + images_to_clients[I2] |= M.client + M << I2 M.hear_say(stars(message), verb, speaking, alt_name, italics, src, speech_sound, sound_vol*0.2) if(dst > w_scramble_range && dst <= world.view) //Inside whisper 'visible' range M.show_message("[src.name] [w_not_heard].", 2) @@ -344,6 +352,17 @@ proc/get_radio_key_from_channel(var/channel) if(dst <= message_range) O.hear_talk(src, message, verb, speaking) + //Remove all those images. At least it's just ONE spawn this time. + spawn(30) + for(var/img in images_to_clients) + var/image/I = img + var/list/clients_from_image = images_to_clients[I] + for(var/client in clients_from_image) + var/client/C = client + if(C) //Could have disconnected after message sent, before removing bubble. + C.images -= I + qdel(I) + //Log the message to file if(whispering) log_whisper(message,src) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 2bdcf1b912..2b11059ff9 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -258,7 +258,7 @@ var/list/ai_verbs_default = list( aiPDA.name = pickedName + " (" + aiPDA.ownjob + ")" if(aiCommunicator) - aiCommunicator.register_device(src) + aiCommunicator.register_device(src.name) /* The AI Power supply is a dummy object used for powering the AI since only machinery should be using power. diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 589f410f01..be725f353d 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -210,7 +210,7 @@ /mob/living/silicon/robot/proc/setup_communicator() if (!communicator) communicator = new/obj/item/device/communicator/integrated(src) - communicator.register_device(src, "[modtype] [braintype]") + communicator.register_device(src.name, "[modtype] [braintype]") //If there's an MMI in the robot, have it ejected when the mob goes away. --NEO //Improved /N diff --git a/code/modules/multiz/zshadow.dm b/code/modules/multiz/zshadow.dm index 10af55f5a3..85685b3d6a 100644 --- a/code/modules/multiz/zshadow.dm +++ b/code/modules/multiz/zshadow.dm @@ -56,6 +56,7 @@ overlays = M.overlays transform = M.transform dir = M.dir + invisibility = M.invisibility if(shadow) shadow.sync_icon(src)