diff --git a/.travis.yml b/.travis.yml index 043755d6b93..566778c4c86 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ sudo: false env: BYOND_MAJOR="509" BYOND_MINOR="1318" - MACRO_COUNT=1004 + MACRO_COUNT=996 cache: directories: diff --git a/code/_helpers/game.dm b/code/_helpers/game.dm index 06b277257f1..d5a7b1ed46e 100644 --- a/code/_helpers/game.dm +++ b/code/_helpers/game.dm @@ -248,6 +248,34 @@ . |= M // Since we're already looping through mobs, why bother using |= ? This only slows things down. return . +/proc/get_mobs_and_objs_in_view_fast(var/turf/T, var/range) + var/list/results = list("objs" = list(), "mobs" = list()) + + var/list/hear = dview(range,T,INVISIBILITY_MAXIMUM) + var/list/hearturfs = list() + + for(var/I in hear) + if(ismob(I)) + var/mob/M = I + results["mobs"] += M + hearturfs += M.locs[1] + else if(isobj(I)) + var/obj/O = I + results["objs"] += I + hearturfs += O.locs[1] + + + for(var/mob/M in player_list) + if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) + results["mobs"] |= M + continue + if(M.loc && M.locs[1] in hearturfs) + results["mobs"] |= M + + return results + + + #define SIGN(X) ((X<0)?-1:1) proc diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index b770693a69a..0858ebc1a40 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -1039,10 +1039,9 @@ proc/get_mob_with_client_list() //gets the turf the atom is located in (or itself, if it is a turf). //returns null if the atom is not in a turf. -/proc/get_turf(atom/A) - if(!istype(A)) return - for(A, A && !isturf(A), A=A.loc); - return A +/proc/get_turf(atom/movable/A) + if(isturf(A)) return A + if(A && A.locs.len) return A.locs[1] /proc/get(atom/loc, type) while(loc) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 439d0199d71..f086a3e1dd6 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -907,7 +907,7 @@ /obj/item/seeds/sunflowerseed = 3,/obj/item/seeds/tomatoseed = 3,/obj/item/seeds/towermycelium = 3,/obj/item/seeds/wheatseed = 3,/obj/item/seeds/appleseed = 3, /obj/item/seeds/poppyseed = 3,/obj/item/seeds/sugarcaneseed = 3,/obj/item/seeds/ambrosiavulgarisseed = 3,/obj/item/seeds/peanutseed = 3,/obj/item/seeds/whitebeetseed = 3,/obj/item/seeds/watermelonseed = 3,/obj/item/seeds/limeseed = 3, /obj/item/seeds/lemonseed = 3,/obj/item/seeds/orangeseed = 3,/obj/item/seeds/grassseed = 3,/obj/item/seeds/cocoapodseed = 3,/obj/item/seeds/plumpmycelium = 2, - /obj/item/seeds/cabbageseed = 3,/obj/item/seeds/grapeseed = 3,/obj/item/seeds/pumpkinseed = 3,/obj/item/seeds/cherryseed = 3,/obj/item/seeds/plastiseed = 3,/obj/item/seeds/riceseed = 3) + /obj/item/seeds/cabbageseed = 3,/obj/item/seeds/grapeseed = 3,/obj/item/seeds/pumpkinseed = 3,/obj/item/seeds/cherryseed = 3,/obj/item/seeds/plastiseed = 3,/obj/item/seeds/riceseed = 3,/obj/item/seeds/lavenderseed = 3) contraband = list(/obj/item/seeds/amanitamycelium = 2,/obj/item/seeds/glowshroom = 2,/obj/item/seeds/libertymycelium = 2,/obj/item/seeds/mtearseed = 2, /obj/item/seeds/nettleseed = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/reishimycelium = 2,/obj/item/seeds/shandseed = 2,) premium = list(/obj/item/toy/waterflower = 1) diff --git a/code/game/objects/items/weapons/clown_items.dm b/code/game/objects/items/weapons/clown_items.dm index 0ccb1f1a242..7c8752c6d7d 100644 --- a/code/game/objects/items/weapons/clown_items.dm +++ b/code/game/objects/items/weapons/clown_items.dm @@ -34,6 +34,10 @@ //So this is a workaround. This also makes more sense from an IC standpoint. ~Carn if(user.client && (target in user.client.screen)) user << "You need to take that [target.name] off before cleaning it." + else if(istype(target,/obj/effect/decal/cleanable/blood)) + user << "You scrub \the [target.name] out." + target.clean_blood() + return //Blood is a cleanable decal, therefore needs to be accounted for before all cleanable decals. else if(istype(target,/obj/effect/decal/cleanable)) user << "You scrub \the [target.name] out." qdel(target) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 3c39c382fa2..8e6c2cd0d57 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -271,6 +271,9 @@ else new glasstype(loc) qdel(src) + else if(istype(W,/obj/item/frame) && anchored) + var/obj/item/frame/F = W + F.try_build(src) else user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(W.damtype == BRUTE || W.damtype == BURN) diff --git a/code/game/verbs/ooc.dm b/code/game/verbs/ooc.dm index fd9a37935eb..2308798345c 100644 --- a/code/game/verbs/ooc.dm +++ b/code/game/verbs/ooc.dm @@ -29,8 +29,6 @@ if(prefs.muted & MUTE_OOC) src << "You cannot use OOC (muted)." return - if(handle_spam_prevention(msg,MUTE_OOC)) - return if(findtext(msg, "byond://")) src << "Advertising other servers is not allowed." log_admin("[key_name(src)] has attempted to advertise in OOC: [msg]") @@ -99,8 +97,6 @@ if(prefs.muted & MUTE_OOC) src << "You cannot use OOC (muted)." return - if(handle_spam_prevention(msg, MUTE_OOC)) - return if(findtext(msg, "byond://")) src << "Advertising other servers is not allowed." log_admin("[key_name(src)] has attempted to advertise in OOC: [msg]") diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 504a8419bf8..8f8532590e8 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -17,9 +17,6 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey"," adminhelped = 1 //Determines if they get the message to reply by clicking the name. - if(src.handle_spam_prevention(msg,MUTE_ADMINHELP)) - return - //clean the input msg if(!msg) return diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index 898cc4e8350..bcb87f06d8d 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -56,9 +56,6 @@ else src << "Error: Private-Message: Client not found. They may have lost connection, so try using an adminhelp!" return - if (src.handle_spam_prevention(msg,MUTE_ADMINHELP)) - return - //clean the message if it's not sent by a high-rank admin //todo: sanitize for all??? if(!check_rights(R_SERVER|R_DEBUG,0)) diff --git a/code/modules/admin/verbs/deadsay.dm b/code/modules/admin/verbs/deadsay.dm index 11193a3f090..08eda6bb346 100644 --- a/code/modules/admin/verbs/deadsay.dm +++ b/code/modules/admin/verbs/deadsay.dm @@ -15,9 +15,6 @@ src << "You have deadchat muted." return - if (src.handle_spam_prevention(msg,MUTE_DEADCHAT)) - return - var/stafftype = uppertext(holder.rank) msg = sanitize(msg) diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm index 600549cdfab..23f5a75e2c3 100644 --- a/code/modules/admin/verbs/pray.dm +++ b/code/modules/admin/verbs/pray.dm @@ -13,8 +13,6 @@ if(usr.client.prefs.muted & MUTE_PRAY) usr << "\red You cannot pray (muted)." return - if(src.client.handle_spam_prevention(msg,MUTE_PRAY)) - return var/image/cross = image('icons/obj/storage.dmi',"bible") msg = "\blue \icon[cross] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) ([admin_jump_link(src, src)]) (CA) (SC): [msg]" diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 643483bb79a..336231e530b 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -74,21 +74,6 @@ ..() //redirect to hsrc.Topic() -/client/proc/handle_spam_prevention(var/message, var/mute_type) - if(config.automute_on && !holder && src.last_message == message) - src.last_message_count++ - if(src.last_message_count >= SPAM_TRIGGER_AUTOMUTE) - src << "\red You have exceeded the spam filter limit for identical messages. An auto-mute was applied." - cmd_admin_mute(src.mob, mute_type, 1) - return 1 - if(src.last_message_count >= SPAM_TRIGGER_WARNING) - src << "\red You are nearing the spam filter limit for identical messages." - return 0 - else - last_message = message - src.last_message_count = 0 - return 0 - //This stops files larger than UPLOAD_LIMIT being sent from client to server via input(), client.Import() etc. /client/AllowUpload(filename, filelength) if(filelength > UPLOAD_LIMIT) diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index 157d4acbd3b..6e88aabee5a 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -550,6 +550,25 @@ set_trait(TRAIT_WATER_CONSUMPTION, 6) set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.15) +/datum/seed/flower/lavender + name = "lavender" + seed_name = "lavender" + display_name = "lavender" + chems = list("nutriment" = list(1,20), "bicaridine" = list(1,10)) + +/datum/seed/flower/lavender/New() + ..() + set_trait(TRAIT_MATURATION,7) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,5) + set_trait(TRAIT_PRODUCT_ICON,"flower6") + set_trait(TRAIT_PRODUCT_COLOUR,"#B57EDC") + set_trait(TRAIT_PLANT_COLOUR,"#6B8C5E") + set_trait(TRAIT_PLANT_ICON,"flower4") + set_trait(TRAIT_IDEAL_LIGHT, 7) + set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.05) + set_trait(TRAIT_WATER_CONSUMPTION, 0.5) + //Grapes/varieties /datum/seed/grapes name = "grapes" diff --git a/code/modules/hydroponics/seed_packets.dm b/code/modules/hydroponics/seed_packets.dm index e14fbd792bb..7c1b70c4c7b 100644 --- a/code/modules/hydroponics/seed_packets.dm +++ b/code/modules/hydroponics/seed_packets.dm @@ -197,6 +197,9 @@ var/global/list/plant_seed_sprites = list() /obj/item/seeds/sunflowerseed seed_type = "sunflowers" +/obj/item/seeds/lavenderseed + seed_type = "lavender" + /obj/item/seeds/brownmold seed_type = "mold" diff --git a/code/modules/hydroponics/seed_storage.dm b/code/modules/hydroponics/seed_storage.dm index 448173104be..fe0a1789195 100644 --- a/code/modules/hydroponics/seed_storage.dm +++ b/code/modules/hydroponics/seed_storage.dm @@ -40,12 +40,91 @@ /obj/machinery/seed_storage/garden name = "Garden seed storage" scanner = list("stats") - starting_seeds = list(/obj/item/seeds/appleseed = 3, /obj/item/seeds/bananaseed = 3, /obj/item/seeds/berryseed = 3, /obj/item/seeds/cabbageseed = 3, /obj/item/seeds/carrotseed = 3, /obj/item/seeds/chantermycelium = 3, /obj/item/seeds/cherryseed = 3, /obj/item/seeds/chiliseed = 3, /obj/item/seeds/cocoapodseed = 3, /obj/item/seeds/cornseed = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/grapeseed = 3, /obj/item/seeds/grassseed = 3, /obj/item/seeds/replicapod = 3, /obj/item/seeds/lemonseed = 3, /obj/item/seeds/limeseed = 3, /obj/item/seeds/mtearseed = 2, /obj/item/seeds/orangeseed = 3, /obj/item/seeds/peanutseed = 3, /obj/item/seeds/plumpmycelium = 3, /obj/item/seeds/poppyseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/pumpkinseed = 3, /obj/item/seeds/riceseed = 3, /obj/item/seeds/soyaseed = 3, /obj/item/seeds/sugarcaneseed = 3, /obj/item/seeds/sunflowerseed = 3, /obj/item/seeds/shandseed = 2, /obj/item/seeds/tobaccoseed = 3, /obj/item/seeds/tomatoseed = 3, /obj/item/seeds/towermycelium = 3, /obj/item/seeds/watermelonseed = 3, /obj/item/seeds/wheatseed = 3, /obj/item/seeds/whitebeetseed = 3) + starting_seeds = list( + /obj/item/seeds/appleseed = 3, + /obj/item/seeds/bananaseed = 3, + /obj/item/seeds/berryseed = 3, + /obj/item/seeds/cabbageseed = 3, + /obj/item/seeds/carrotseed = 3, + /obj/item/seeds/chantermycelium = 3, + /obj/item/seeds/cherryseed = 3, + /obj/item/seeds/chiliseed = 3, + /obj/item/seeds/cocoapodseed = 3, + /obj/item/seeds/cornseed = 3, + /obj/item/seeds/eggplantseed = 3, + /obj/item/seeds/grapeseed = 3, + /obj/item/seeds/grassseed = 3, + /obj/item/seeds/replicapod = 3, + /obj/item/seeds/lemonseed = 3, + /obj/item/seeds/limeseed = 3, + /obj/item/seeds/mtearseed = 2, + /obj/item/seeds/orangeseed = 3, + /obj/item/seeds/peanutseed = 3, + /obj/item/seeds/plumpmycelium = 3, + /obj/item/seeds/poppyseed = 3, + /obj/item/seeds/potatoseed = 3, + /obj/item/seeds/pumpkinseed = 3, + /obj/item/seeds/riceseed = 3, + /obj/item/seeds/soyaseed = 3, + /obj/item/seeds/sugarcaneseed = 3, + /obj/item/seeds/sunflowerseed = 3, + /obj/item/seeds/shandseed = 2, + /obj/item/seeds/tobaccoseed = 3, + /obj/item/seeds/tomatoseed = 3, + /obj/item/seeds/towermycelium = 3, + /obj/item/seeds/watermelonseed = 3, + /obj/item/seeds/wheatseed = 3, + /obj/item/seeds/whitebeetseed = 3, + /obj/item/seeds/lavenderseed = 3 + ) /obj/machinery/seed_storage/xenobotany name = "Xenobotany seed storage" scanner = list("stats", "produce", "soil", "temperature", "light") - starting_seeds = list(/obj/item/seeds/ambrosiavulgarisseed = 3, /obj/item/seeds/appleseed = 3, /obj/item/seeds/amanitamycelium = 2, /obj/item/seeds/bananaseed = 3, /obj/item/seeds/berryseed = 3, /obj/item/seeds/cabbageseed = 3, /obj/item/seeds/carrotseed = 3, /obj/item/seeds/chantermycelium = 3, /obj/item/seeds/cherryseed = 3, /obj/item/seeds/chiliseed = 3, /obj/item/seeds/cocoapodseed = 3, /obj/item/seeds/cornseed = 3, /obj/item/seeds/replicapod = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/glowshroom = 2, /obj/item/seeds/grapeseed = 3, /obj/item/seeds/grassseed = 3, /obj/item/seeds/lemonseed = 3, /obj/item/seeds/libertymycelium = 2, /obj/item/seeds/limeseed = 3, /obj/item/seeds/mtearseed = 2, /obj/item/seeds/nettleseed = 2, /obj/item/seeds/orangeseed = 3, /obj/item/seeds/peanutseed = 3, /obj/item/seeds/plastiseed = 3, /obj/item/seeds/plumpmycelium = 3, /obj/item/seeds/poppyseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/pumpkinseed = 3, /obj/item/seeds/reishimycelium = 2, /obj/item/seeds/riceseed = 3, /obj/item/seeds/soyaseed = 3, /obj/item/seeds/sugarcaneseed = 3, /obj/item/seeds/sunflowerseed = 3, /obj/item/seeds/shandseed = 2, /obj/item/seeds/tobaccoseed = 3, /obj/item/seeds/tomatoseed = 3, /obj/item/seeds/towermycelium = 3, /obj/item/seeds/watermelonseed = 3, /obj/item/seeds/wheatseed = 3, /obj/item/seeds/whitebeetseed = 3) + starting_seeds = list( + /obj/item/seeds/ambrosiavulgarisseed = 3, + /obj/item/seeds/appleseed = 3, + /obj/item/seeds/amanitamycelium = 2, + /obj/item/seeds/bananaseed = 3, + /obj/item/seeds/berryseed = 3, + /obj/item/seeds/cabbageseed = 3, + /obj/item/seeds/carrotseed = 3, + /obj/item/seeds/chantermycelium = 3, + /obj/item/seeds/cherryseed = 3, + /obj/item/seeds/chiliseed = 3, + /obj/item/seeds/cocoapodseed = 3, + /obj/item/seeds/cornseed = 3, + /obj/item/seeds/replicapod = 3, + /obj/item/seeds/eggplantseed = 3, + /obj/item/seeds/glowshroom = 2, + /obj/item/seeds/grapeseed = 3, + /obj/item/seeds/grassseed = 3, + /obj/item/seeds/lemonseed = 3, + /obj/item/seeds/libertymycelium = 2, + /obj/item/seeds/limeseed = 3, + /obj/item/seeds/mtearseed = 2, + /obj/item/seeds/nettleseed = 2, + /obj/item/seeds/orangeseed = 3, + /obj/item/seeds/peanutseed = 3, + /obj/item/seeds/plastiseed = 3, + /obj/item/seeds/plumpmycelium = 3, + /obj/item/seeds/poppyseed = 3, + /obj/item/seeds/potatoseed = 3, + /obj/item/seeds/pumpkinseed = 3, + /obj/item/seeds/reishimycelium = 2, + /obj/item/seeds/riceseed = 3, + /obj/item/seeds/soyaseed = 3, + /obj/item/seeds/sugarcaneseed = 3, + /obj/item/seeds/sunflowerseed = 3, + /obj/item/seeds/shandseed = 2, + /obj/item/seeds/tobaccoseed = 3, + /obj/item/seeds/tomatoseed = 3, + /obj/item/seeds/towermycelium = 3, + /obj/item/seeds/watermelonseed = 3, + /obj/item/seeds/wheatseed = 3, + /obj/item/seeds/whitebeetseed = 3, + /obj/item/seeds/lavenderseed = 3 + ) /obj/machinery/seed_storage/attack_hand(mob/user as mob) user.set_machine(src) diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index 9dfd3deb44c..ada597f46bf 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -11,9 +11,6 @@ src << "\red You cannot talk in deadchat (muted)." return - if (src.client.handle_spam_prevention(message,MUTE_DEADCHAT)) - return - . = src.say_dead(message) @@ -33,9 +30,6 @@ src << "\red You cannot emote in deadchat (muted)." return - if(src.client.handle_spam_prevention(message, MUTE_DEADCHAT)) - return - . = src.emote_dead(message) /* diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index 223b01e1109..372409b4433 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -10,8 +10,8 @@ var/speech_verb = "says" // 'says', 'hisses', 'farts'. var/ask_verb = "asks" // Used when sentence ends in a ? var/exclaim_verb = "exclaims" // Used when sentence ends in a ! - var/whisper_verb = "whispers" // Optional. When not specified speech_verb + quietly/softly is used instead. - var/signlang_verb = list("signs") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags + var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead. + var/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags var/colour = "body" // CSS style to use for strings in this language. var/key = "x" // Character used to speak in language eg. :o for Unathi. var/flags = 0 // Various language flags. diff --git a/code/modules/mob/living/carbon/alien/emote.dm b/code/modules/mob/living/carbon/alien/emote.dm index 62fa2cf1082..e31a293047c 100644 --- a/code/modules/mob/living/carbon/alien/emote.dm +++ b/code/modules/mob/living/carbon/alien/emote.dm @@ -18,8 +18,6 @@ if (client.prefs.muted & MUTE_IC) src << "\red You cannot send IC messages (muted)." return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return if (stat) return if(!(message)) diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm index f29167f1f37..5725dd4ec7a 100644 --- a/code/modules/mob/living/carbon/brain/emote.dm +++ b/code/modules/mob/living/carbon/brain/emote.dm @@ -19,8 +19,6 @@ if (client.prefs.muted & MUTE_IC) src << "\red You cannot send IC messages (muted)." return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return if (stat) return if(!(message)) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 87c05245717..4488f65388b 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -112,8 +112,6 @@ if (client.prefs.muted & MUTE_IC) src << "\red You cannot send IC messages (muted)." return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return if (stat) return if(!(message)) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index e0451046ae5..01351dcf227 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -266,7 +266,6 @@ In most cases it makes more sense to use apply_damage() instead! And make sure t UpdateDamageIcon() BITSET(hud_updateflag, HEALTH_HUD) updatehealth() - speech_problem_flag = 1 //Heal MANY external organs, in random order @@ -288,7 +287,6 @@ In most cases it makes more sense to use apply_damage() instead! And make sure t parts -= picked updatehealth() BITSET(hud_updateflag, HEALTH_HUD) - speech_problem_flag = 1 if(update) UpdateDamageIcon() // damage MANY external organs, in random order diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 0a21d4d5bcf..390e7ee6c5f 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -69,8 +69,6 @@ var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life() - var/speech_problem_flag = 0 - var/miming = null //Toggle for the mime's abilities. var/special_voice = "" // For changing our voice. Used by a symptom. diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 0ecc6219fff..8eb61c57428 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -170,7 +170,6 @@ emote("cough") return if (disabilities & TOURETTES) - speech_problem_flag = 1 if ((prob(10) && paralysis <= 1)) Stun(10) spawn( 0 ) @@ -182,7 +181,6 @@ make_jittery(100) return if (disabilities & NERVOUS) - speech_problem_flag = 1 if (prob(10)) stuttering = max(10, stuttering) @@ -223,7 +221,6 @@ if(!gene.block) continue if(gene.is_active(src)) - speech_problem_flag = 1 gene.OnMobLife(src) radiation = Clamp(radiation,0,100) @@ -916,7 +913,6 @@ adjustHalLoss(-3) if(sleeping) - speech_problem_flag = 1 handle_dreams() if (mind) //Are they SSD? If so we'll keep them asleep but work off some of that sleep var in case of stoxin or similar. @@ -1663,28 +1659,11 @@ hud_list[SPECIALROLE_HUD] = holder hud_updateflag = 0 -/mob/living/carbon/human/handle_silent() - if(..()) - speech_problem_flag = 1 - return silent - -/mob/living/carbon/human/handle_slurring() - if(..()) - speech_problem_flag = 1 - return slurring - /mob/living/carbon/human/handle_stunned() if(!can_feel_pain()) stunned = 0 return 0 - if(..()) - speech_problem_flag = 1 - return stunned - -/mob/living/carbon/human/handle_stuttering() - if(..()) - speech_problem_flag = 1 - return stuttering + return ..() /mob/living/carbon/human/handle_fire() if(..()) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index cbfb88676a4..c87338d26cb 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -1,10 +1,10 @@ -/mob/living/carbon/human/say(var/message) +/mob/living/carbon/human/say(var/message,var/whispering=0) var/alt_name = "" if(name != GetVoice()) alt_name = "(as [get_id_name("Unknown")])" message = sanitize(message) - ..(message, alt_name = alt_name) + ..(message, alt_name = alt_name, whispering = whispering) /mob/living/carbon/human/proc/forcesay(list/append) if(stat == CONSCIOUS) @@ -125,29 +125,20 @@ return verb -/mob/living/carbon/human/handle_speech_problems(var/message, var/verb) +/mob/living/carbon/human/handle_speech_problems(var/list/message_data) if(silent || (sdisabilities & MUTE)) - message = "" - speech_problem_flag = 1 + message_data[1] = "" + . = 1 + else if(istype(wear_mask, /obj/item/clothing/mask)) var/obj/item/clothing/mask/M = wear_mask if(M.voicechange) - message = pick(M.say_messages) - verb = pick(M.say_verbs) - speech_problem_flag = 1 + message_data[1] = pick(M.say_messages) + message_data[2] = pick(M.say_verbs) + . = 1 - if(message != "") - var/list/parent = ..() - message = parent[1] - verb = parent[2] - if(parent[3]) - speech_problem_flag = 1 - - var/list/returns[3] - returns[1] = message - returns[2] = verb - returns[3] = speech_problem_flag - return returns + else + . = ..(message_data) /mob/living/carbon/human/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) switch(message_mode) @@ -190,9 +181,6 @@ if(has_radio) R.talk_into(src,message,null,verb,speaking) used_radios += R - if("whisper") - whisper_say(message, speaking, alt_name) - return 1 else if(message_mode) if(l_ear && istype(l_ear,/obj/item/device/radio)) diff --git a/code/modules/mob/living/carbon/human/whisper.dm b/code/modules/mob/living/carbon/human/whisper.dm deleted file mode 100644 index 157310291a4..00000000000 --- a/code/modules/mob/living/carbon/human/whisper.dm +++ /dev/null @@ -1,161 +0,0 @@ -//Lallander was here -/mob/living/carbon/human/whisper(message as text) - var/alt_name = "" - - if(say_disabled) //This is here to try to identify lag problems - usr << "\red Speech is currently admin-disabled." - return - - message = sanitize(message) - log_whisper("[src.name]/[src.key] : [message]") - - if (src.client) - if (src.client.prefs.muted & MUTE_IC) - src << "\red You cannot whisper (muted)." - return - - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return - - if (src.stat == 2) - return src.say_dead(message) - - if (src.stat) - return - - if(name != GetVoice()) - alt_name = "(as [get_id_name("Unknown")])" - - //parse the language code and consume it - var/datum/language/speaking = parse_language(message) - if (speaking) - message = copytext(message,2+length(speaking.key)) - - whisper_say(message, speaking, alt_name) - - -//This is used by both the whisper verb and human/say() to handle whispering -/mob/living/carbon/human/proc/whisper_say(var/message, var/datum/language/speaking = null, var/alt_name="", var/verb="whispers") - - if (is_muzzled()) - src << "You're muzzled and cannot speak!" - return - - var/message_range = 1 - var/eavesdropping_range = 2 - var/watching_range = 5 - var/italics = 1 - - var/not_heard //the message displayed to people who could not hear the whispering - if (speaking) - if (speaking.whisper_verb) - verb = speaking.whisper_verb - not_heard = "[verb] something" - else - var/adverb = pick("quietly", "softly") - verb = "[speaking.speech_verb] [adverb]" - not_heard = "[speaking.speech_verb] something [adverb]" - else - not_heard = "[verb] something" //TODO get rid of the null language and just prevent speech if language is null - - message = capitalize(trim(message)) - - if(speech_problem_flag) - var/list/handle_r = handle_speech_problems(message) - message = handle_r[1] - verb = handle_r[2] - if(verb == "yells loudly") - verb = "slurs emphatically" - else - var/adverb = pick("quietly", "softly") - verb = "[verb] [adverb]" - - speech_problem_flag = handle_r[3] - - if(!message || message=="") - return - - //looks like this only appears in whisper. Should it be elsewhere as well? Maybe handle_speech_problems? - var/voice_sub - if(istype(back,/obj/item/weapon/rig)) - var/obj/item/weapon/rig/rig = back - // todo: fix this shit - if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.voice) - voice_sub = rig.speech.voice_holder.voice - else - for(var/obj/item/gear in list(wear_mask,wear_suit,head)) - if(!gear) - continue - var/obj/item/voice_changer/changer = locate() in gear - if(changer && changer.active && changer.voice) - voice_sub = changer.voice - - if(voice_sub == "Unknown") - if(copytext(message, 1, 2) != "*") - var/list/temp_message = splittext(message, " ") - var/list/pick_list = list() - for(var/i = 1, i <= temp_message.len, i++) - pick_list += i - for(var/i=1, i <= abs(temp_message.len/3), i++) - var/H = pick(pick_list) - if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue - temp_message[H] = ninjaspeak(temp_message[H]) - pick_list -= H - message = jointext(temp_message, " ") - message = replacetext(message, "o", "¤") - message = replacetext(message, "p", "þ") - message = replacetext(message, "l", "£") - message = replacetext(message, "s", "§") - message = replacetext(message, "u", "µ") - message = replacetext(message, "b", "ß") - - var/list/listening = hearers(message_range, src) - listening |= src - - //ghosts - for (var/mob/M in dead_mob_list) //does this include players who joined as observers as well? - if (!(M.client)) - continue - if(M.stat == DEAD && M.is_preference_enabled(/datum/client_preference/ghost_ears)) - listening |= M - - //Pass whispers on to anything inside the immediate listeners. - for(var/mob/L in listening) - for(var/mob/C in L.contents) - if(istype(C,/mob/living)) - listening += C - - //pass on the message to objects that can hear us. - for (var/obj/O in view(message_range, src)) - spawn (0) - if (O) - O.hear_talk(src, message, verb, speaking) - - var/list/eavesdropping = hearers(eavesdropping_range, src) - eavesdropping -= src - eavesdropping -= listening - - var/list/watching = hearers(watching_range, src) - watching -= src - watching -= listening - watching -= eavesdropping - - //now mobs - var/speech_bubble_test = say_test(message) - var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]") - spawn(30) qdel(speech_bubble) - - for(var/mob/M in listening) - M << speech_bubble - M.hear_say(message, verb, speaking, alt_name, italics, src) - - if (eavesdropping.len) - var/new_message = stars(message) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less. - for(var/mob/M in eavesdropping) - M << speech_bubble - M.hear_say(new_message, verb, speaking, alt_name, italics, src) - - if (watching.len) - var/rendered = "[src.name] [not_heard]." - for (var/mob/M in watching) - M.show_message(rendered, 2) diff --git a/code/modules/mob/living/carbon/metroid/emote.dm b/code/modules/mob/living/carbon/metroid/emote.dm index a6ea5498cde..d82372e52ff 100644 --- a/code/modules/mob/living/carbon/metroid/emote.dm +++ b/code/modules/mob/living/carbon/metroid/emote.dm @@ -18,8 +18,6 @@ if (client.prefs.muted & MUTE_IC) src << "\red You cannot send IC messages (muted)." return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return if (stat) return if(!(message)) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index d9a8ad84b45..111604848ad 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -145,7 +145,7 @@ /mob/living/proc/handle_disabilities() //Eyes - if(disabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own + if(sdisabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own eye_blind = max(eye_blind, 1) else if(eye_blind) //blindness, heals slowly over time eye_blind = max(eye_blind-1,0) @@ -153,7 +153,7 @@ eye_blurry = max(eye_blurry-1, 0) //Ears - if(disabilities & DEAF) //disabled-deaf, doesn't get better on its own + if(sdisabilities & DEAF) //disabled-deaf, doesn't get better on its own setEarDamage(-1, max(ear_deaf, 1)) else // deafness heals slowly over time, unless ear_damage is over 100 diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index a0b8347d2d6..a2355b18200 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -82,27 +82,31 @@ proc/get_radio_key_from_channel(var/channel) /mob/living/proc/get_default_language() return default_language -/mob/living/proc/handle_speech_problems(var/message, var/verb) - var/list/returns[3] - var/speech_problem_flag = 0 +//Takes a list of the form list(message, verb, whispering) and modifies it as needed +//Returns 1 if a speech problem was applied, 0 otherwise +/mob/living/proc/handle_speech_problems(var/list/message_data) + var/message = message_data[1] + var/verb = message_data[2] + var/whispering = message_data[3] + . = 0 if((HULK in mutations) && health >= 25 && length(message)) message = "[uppertext(message)]!!!" verb = pick("yells","roars","hollers") - speech_problem_flag = 1 + whispering = 0 + . = 1 if(slurring) message = slur(message) verb = pick("slobbers","slurs") - speech_problem_flag = 1 + . = 1 if(stuttering) message = stutter(message) verb = pick("stammers","stutters") - speech_problem_flag = 1 + . = 1 - returns[1] = message - returns[2] = verb - returns[3] = speech_problem_flag - return returns + message_data[1] = message + message_data[2] = verb + message_data[2] = whispering /mob/living/proc/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) if(message_mode == "intercom") @@ -124,33 +128,42 @@ proc/get_radio_key_from_channel(var/channel) return "asks" return verb -/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="") +/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/whispering = 0) + //If you're muted for IC chat if(client) - if(client.prefs.muted & MUTE_IC) - src << "\red You cannot speak in IC (Muted)." + if((client.prefs.muted & MUTE_IC) || say_disabled) + src << "You cannot speak in IC (Muted)." return + //Redirect to say_dead if talker is dead if(stat) - if(stat == 2) + if(stat == DEAD) return say_dead(message) return + //Parse the mode var/message_mode = parse_message_mode(message, "headset") + //Maybe they are using say/whisper to do a quick emote, so do those switch(copytext(message,1,2)) if("*") return emote(copytext(message,2)) if("^") return custom_emote(1, copytext(message,2)) - //parse the radio code and consume it + //Parse the radio code and consume it if (message_mode) if (message_mode == "headset") message = copytext(message,2) //it would be really nice if the parse procs could do this for us. + else if (message_mode == "whisper") + whispering = 1 + message_mode = null + message = copytext(message,3) else message = copytext(message,3) + //Clean up any remaining space on the left message = trim_left(message) - //parse the language code and consume it + //Parse the language code and consume it if(!speaking) speaking = parse_language(message) if(speaking) @@ -158,42 +171,72 @@ proc/get_radio_key_from_channel(var/channel) else speaking = get_default_language() - // This is broadcast to all mobs with the language, - // irrespective of distance or anything else. + //HIVEMIND languages always send to all people with that language if(speaking && (speaking.flags & HIVEMIND)) speaking.broadcast(src,trim(message)) return 1 - verb = say_quote(message, speaking) - + //Self explanatory. if(is_muzzled()) src << "You're muzzled and cannot speak!" return + //Clean up any remaining junk on the left like spaces. message = trim_left(message) + //Autohiss handles auto-rolling tajaran R's and unathi S's/Z's + message = handle_autohiss(message, speaking) + + //Whisper vars + var/w_scramble_range = 5 //The range at which you get ***as*th**wi**** + var/w_adverb //An adverb prepended to the verb in whispers + var/w_not_heard //The message for people in watching range + + //Handle language-specific verbs and adverb setup if necessary + if(!whispering) //Just doing normal 'say' (for now, may change below) + verb = say_quote(message, speaking) + else if(whispering && speaking.whisper_verb) //Language has defined whisper verb + verb = speaking.whisper_verb + w_not_heard = "[verb] something" + else //Whispering but language has no whisper verb, use say verb + w_adverb = pick("quietly", "softly") + verb = speaking.speech_verb + w_not_heard = "[speaking.speech_verb] something [w_adverb]" + + //For speech disorders (hulk, slurring, stuttering) if(!(speaking && (speaking.flags & NO_STUTTER))) - message = handle_autohiss(message, speaking) + var/list/message_data = list(message, verb, whispering) + if(handle_speech_problems(message_data)) + message = message_data[1] + whispering = message_data[3] - var/list/handle_s = handle_speech_problems(message, verb) - message = handle_s[1] - verb = handle_s[2] + if(verb != message_data[2]) //They changed our verb + if(whispering) + w_adverb = pick("quietly", "softly") + verb = message_data[2] + //Whisper may have adverbs, add those if one was set + if(w_adverb) verb = "[verb] [w_adverb]" + + //If something nulled or emptied the message, forget it if(!message || message == "") return 0 + //Radio message handling var/list/obj/item/used_radios = new - if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)) + if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, whispering)) return 1 + //For languages with actual speech sounds var/list/handle_v = handle_speech_sound() var/sound/speech_sound = handle_v[1] var/sound_vol = handle_v[2] - var/italics = 0 + //Default range and italics, may be overridden past here var/message_range = world.view + var/italics = 0 - //speaking into radios + //Speaking into radios if(used_radios.len) italics = 1 message_range = 1 @@ -208,9 +251,13 @@ proc/get_radio_key_from_channel(var/channel) if (speech_sound) sound_vol *= 0.5 - var/turf/T = get_turf(src) + //Set vars if we're still whispering by this point + if(whispering) + italics = 1 + message_range = 1 + sound_vol *= 0.5 - //handle nonverbal and sign languages here + //Handle nonverbal and sign languages here if (speaking) if (speaking.flags & NONVERBAL) if (prob(30)) @@ -219,56 +266,64 @@ proc/get_radio_key_from_channel(var/channel) if (speaking.flags & SIGNLANG) return say_signlang(message, pick(speaking.signlang_verb), speaking) + //These will contain the main receivers of the message var/list/listening = list() var/list/listening_obj = list() + //Atmosphere calculations (speaker's side only, for now) + var/turf/T = get_turf(src) if(T) - //make sure the air can transmit speech - speaker's side + //Air is too thin to carry sound at all, contact speech only var/datum/gas_mixture/environment = T.return_air() var/pressure = (environment)? environment.return_pressure() : 0 if(pressure < SOUND_MINIMUM_PRESSURE) message_range = 1 - if (pressure < ONE_ATMOSPHERE*0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet + //Air is nearing minimum levels, make text italics as a hint, and muffle sound + if (pressure < ONE_ATMOSPHERE*0.4) italics = 1 - sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact + sound_vol *= 0.5 - //DO NOT FUCKING CHANGE THIS TO GET_OBJ_OR_MOB_AND_BULLSHIT() -- Hugs and Kisses ~Ccomp - var/list/hear = hear(message_range,T) - var/list/hearturfs = list() - - for(var/I in hear) - if(ismob(I)) - var/mob/M = I - listening += M - hearturfs += M.locs[1] - else if(isobj(I)) - var/obj/O = I - hearturfs += O.locs[1] - listening_obj |= O - - - for(var/mob/M in player_list) - if(M.stat == DEAD && M.client && M.is_preference_enabled(/datum/client_preference/ghost_ears)) - listening |= M - continue - if(M.loc && M.locs[1] in hearturfs) - listening |= M + //Obtain the mobs and objects in the message range + var/list/results = get_mobs_and_objs_in_view_fast(T, world.view) + listening = results["mobs"] + listening_obj = results["objs"] + else + return 1 //If we're in nullspace, then forget it. + //The 'post-say' static speech bubble var/speech_bubble_test = say_test(message) var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]") spawn(30) qdel(speech_bubble) + //Main 'say' and 'whisper' message delivery for(var/mob/M in listening) - M << speech_bubble - M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol) + spawn(0) //Using spawns to queue all the messages for AFTER this proc is done, and stop runtimes + if(M && src) //If we still exist, when the spawn processes + var/dst = get_dist(get_turf(M),get_turf(src)) + + if(dst <= message_range || M.stat == DEAD) //Inside normal message range, or dead with ears (handled in the view proc) + M << speech_bubble + 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 << speech_bubble + 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) + + //Object message delivery for(var/obj/O in listening_obj) spawn(0) - if(O) //It's possible that it could be deleted in the meantime. - O.hear_talk(src, message, verb, speaking) + if(O && src) //If we still exist, when the spawn processes + var/dst = get_dist(get_turf(O),get_turf(src)) + if(dst <= message_range) + O.hear_talk(src, message, verb, speaking) - log_say("[name]/[key] : [message]") + //Log the message to file + log_say("[name]/[key][whispering ? " (W)" : ""]: [message]") return 1 /mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language) diff --git a/code/modules/mob/living/silicon/robot/drone/drone_say.dm b/code/modules/mob/living/silicon/robot/drone/drone_say.dm index b0f89a70ea0..5cdcd3dbd8a 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_say.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_say.dm @@ -4,8 +4,6 @@ if(client.prefs.muted & MUTE_IC) src << "You cannot send IC messages (muted)." return 0 - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return 0 message = sanitize(message) diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 23b6cc0d67b..7f2102a8609 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -14,8 +14,6 @@ if(client.prefs.muted & MUTE_IC) src << "You cannot send IC messages (muted)." return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return if (stat) return if(!(message)) diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index ece00da5ee7..e2810ad6410 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -1,5 +1,5 @@ -/mob/living/silicon/say(var/message, var/sanitize = 1) - return ..(sanitize ? sanitize(message) : message) +/mob/living/silicon/say(var/message, var/sanitize = 1, var/whispering = 0) + return ..((sanitize ? sanitize(message) : message), whispering = whispering) /mob/living/silicon/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name) log_say("[key_name(src)] : [message]") diff --git a/code/modules/mob/living/simple_animal/borer/borer_captive.dm b/code/modules/mob/living/simple_animal/borer/borer_captive.dm index 2d6bfc34b3c..f07b9d32cee 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_captive.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_captive.dm @@ -9,8 +9,6 @@ if(client.prefs.muted & MUTE_IC) src << "\red You cannot speak in IC (muted)." return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return if(istype(src.loc,/mob/living/simple_animal/borer)) diff --git a/code/modules/mob/living/simple_animal/borer/say.dm b/code/modules/mob/living/simple_animal/borer/say.dm index 0d4cdad06ef..e76a02a7e23 100644 --- a/code/modules/mob/living/simple_animal/borer/say.dm +++ b/code/modules/mob/living/simple_animal/borer/say.dm @@ -16,8 +16,6 @@ if(client.prefs.muted & MUTE_IC) src << "\red You cannot speak in IC (muted)." return - if (src.client.handle_spam_prevention(message,MUTE_IC)) - return if (copytext(message, 1, 2) == "*") return emote(copytext(message, 2)) diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index ec47effabab..f7aaa52f78b 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -1,29 +1,15 @@ /mob/proc/say() return -/mob/verb/whisper() +/mob/verb/whisper(message as text) set name = "Whisper" set category = "IC" - return + + usr.say(message,whispering=1) /mob/verb/say_verb(message as text) set name = "Say" set category = "IC" - if(say_disabled) //This is here to try to identify lag problems - usr << "\red Speech is currently admin-disabled." - return - //Let's try to make users fix their errors - we try to detect single, out-of-place letters and 'unintended' words - /* - var/first_letter = copytext(message,1,2) - if((copytext(message,2,3) == " " && first_letter != "I" && first_letter != "A" && first_letter != ";") || cmptext(copytext(message,1,5), "say ") || cmptext(copytext(message,1,4), "me ") || cmptext(copytext(message,1,6), "looc ") || cmptext(copytext(message,1,5), "ooc ") || cmptext(copytext(message,2,6), "say ")) - var/response = alert(usr, "Do you really want to say this using the *say* verb?\n\n[message]\n", "Confirm your message", "Yes", "Edit message", "No") - if(response == "Edit message") - message = input(usr, "Please edit your message carefully:", "Edit message", message) - if(!message) - return - else if(response == "No") - return - */ set_typing_indicator(0) usr.say(message) @@ -62,7 +48,7 @@ /mob/proc/say_understands(var/mob/other,var/datum/language/speaking = null) - if (src.stat == 2) //Dead + if (src.stat == DEAD) return 1 //Universal speak makes everything understandable, for obvious reasons. diff --git a/html/changelog.html b/html/changelog.html index 8a5a9b67462..82e7175c069 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,19 @@ -->