Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into Ghommie-cit265
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
//Brain Traumas are the new actual brain damage. Brain damage itself acts as a way to acquire traumas: every time brain damage is dealt, there's a chance of receiving a trauma.
|
||||
//This chance gets higher the higher the mob's brainloss is. Removing traumas is a separate thing from removing brain damage: you can get restored to full brain operativity,
|
||||
//but keep the quirks, until repaired by mannitol (for mild/special ones) or brain surgery (for severe ones).
|
||||
// but keep the quirks, until repaired by neurine, surgery, lobotomy or magic; depending on the resilience
|
||||
// of the trauma.
|
||||
|
||||
/datum/brain_trauma
|
||||
var/name = "Brain Trauma"
|
||||
var/desc = "A trauma caused by brain damage, which causes issues to the patient."
|
||||
var/scan_desc = "a generic brain trauma" //description when detected by a health scanner
|
||||
var/scan_desc = "generic brain trauma" //description when detected by a health scanner
|
||||
var/mob/living/carbon/owner //the poor bastard
|
||||
var/obj/item/organ/brain/brain //the poor bastard's brain
|
||||
var/gain_text = "<span class='notice'>You feel traumatized.</span>"
|
||||
@@ -12,15 +14,21 @@
|
||||
var/can_gain = TRUE
|
||||
var/random_gain = TRUE //can this be gained through random traumas?
|
||||
var/resilience = TRAUMA_RESILIENCE_BASIC //how hard is this to cure?
|
||||
var/clonable = TRUE // will this transfer if the brain is cloned?
|
||||
|
||||
/datum/brain_trauma/Destroy()
|
||||
brain.traumas -= src
|
||||
if(brain && brain.traumas)
|
||||
brain.traumas -= src
|
||||
if(owner)
|
||||
on_lose()
|
||||
brain = null
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
/datum/brain_trauma/proc/on_clone()
|
||||
if(clonable)
|
||||
return new type
|
||||
|
||||
//Called on life ticks
|
||||
/datum/brain_trauma/proc/on_life()
|
||||
return
|
||||
@@ -33,17 +41,24 @@
|
||||
/datum/brain_trauma/proc/on_gain()
|
||||
to_chat(owner, gain_text)
|
||||
RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/handle_hearing)
|
||||
|
||||
//Called when removed from a mob
|
||||
/datum/brain_trauma/proc/on_lose(silent)
|
||||
if(!silent)
|
||||
to_chat(owner, lose_text)
|
||||
UnregisterSignal(owner, COMSIG_MOB_SAY)
|
||||
UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
|
||||
|
||||
//Called when hearing a spoken message
|
||||
/datum/brain_trauma/proc/on_hear(message, speaker, message_language, raw_message, radio_freq)
|
||||
return message
|
||||
/datum/brain_trauma/proc/handle_hearing(datum/source, list/hearing_args)
|
||||
UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
|
||||
|
||||
//Called when speaking
|
||||
/datum/brain_trauma/proc/handle_speech(datum/source, list/speech_args)
|
||||
UnregisterSignal(owner, COMSIG_MOB_SAY)
|
||||
|
||||
|
||||
//Called when hugging. expand into generally interacting, where future coders could switch the intent?
|
||||
/datum/brain_trauma/proc/on_hug(mob/living/hugger, mob/living/hugged)
|
||||
return
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
gain_text = ""
|
||||
lose_text = ""
|
||||
resilience = TRAUMA_RESILIENCE_SURGERY
|
||||
|
||||
var/hypnotic_phrase = ""
|
||||
var/regex/target_phrase
|
||||
|
||||
@@ -44,18 +45,17 @@
|
||||
"You feel a part of your mind repeating this over and over. You need to follow these words.",\
|
||||
"Something about this sounds... right, for some reason. You feel like you should follow these words.",\
|
||||
"These words keep echoing in your mind. You find yourself completely fascinated by them.")]</span>")
|
||||
if(!HAS_TRAIT(owner, "hypnotherapy"))
|
||||
to_chat(owner, "<span class='boldwarning'>You've been hypnotized by this sentence. You must follow these words. If it isn't a clear order, you can freely interpret how to do so,\
|
||||
to_chat(owner, "<span class='boldwarning'>You've been hypnotized by this sentence. You must follow these words. If it isn't a clear order, you can freely interpret how to do so,\
|
||||
as long as you act like the words are your highest priority.</span>")
|
||||
else
|
||||
to_chat(owner, "<span class='boldwarning'>You've been hypnotized by this sentence. You feel an incredible desire to follow these words, but are able to resist it somewhat. If it isn't a clear order, you can freely interpret how to do so,\
|
||||
however this does not take precedence over your other objectives.</span>")
|
||||
var/obj/screen/alert/hypnosis/hypno_alert = owner.throw_alert("hypnosis", /obj/screen/alert/hypnosis)
|
||||
hypno_alert.desc = "\"[hypnotic_phrase]\"... your mind seems to be fixated on this concept."
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/hypnosis/on_lose()
|
||||
message_admins("[ADMIN_LOOKUPFLW(owner)] is no longer hypnotized with the phrase '[hypnotic_phrase]'.")
|
||||
log_game("[key_name(owner)] is no longer hypnotized with the phrase '[hypnotic_phrase]'.")
|
||||
to_chat(owner, "<span class='userdanger'>You suddenly snap out of your fixation. The phrase '[hypnotic_phrase]' no longer feels important to you.</span>")
|
||||
to_chat(owner, "<span class='userdanger'>You suddenly snap out of your hypnosis. The phrase '[hypnotic_phrase]' no longer feels important to you.</span>")
|
||||
owner.clear_alert("hypnosis")
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/hypnosis/on_life()
|
||||
@@ -67,6 +67,5 @@
|
||||
if(2)
|
||||
new /datum/hallucination/chat(owner, TRUE, FALSE, "<span class='hypnophrase'>[hypnotic_phrase]</span>")
|
||||
|
||||
/datum/brain_trauma/hypnosis/on_hear(message, speaker, message_language, raw_message, radio_freq)
|
||||
message = target_phrase.Replace(message, "<span class='hypnophrase'>$1</span>")
|
||||
return message
|
||||
/datum/brain_trauma/hypnosis/handle_hearing(datum/source, list/hearing_args)
|
||||
hearing_args[HEARING_RAW_MESSAGE] = target_phrase.Replace(hearing_args[HEARING_RAW_MESSAGE], "<span class='hypnophrase'>$1</span>")
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
var/friend_initialized = FALSE
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/on_gain()
|
||||
var/mob/living/M = owner
|
||||
if(M.stat == DEAD || !M.client)
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
make_friend()
|
||||
get_ghost()
|
||||
@@ -43,7 +47,7 @@
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/proc/get_ghost()
|
||||
set waitfor = FALSE
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s imaginary friend?", ROLE_PAI, null, null, 75, friend)
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s imaginary friend?", ROLE_PAI, null, null, 75, friend, POLL_IGNORE_IMAGINARYFRIEND)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
C.transfer_ckey(friend, FALSE)
|
||||
@@ -74,26 +78,34 @@
|
||||
|
||||
/mob/camera/imaginary_friend/Login()
|
||||
..()
|
||||
to_chat(src, "<span class='notice'><b>You are the imaginary friend of [owner]!</b></span>")
|
||||
to_chat(src, "<span class='notice'>You are absolutely loyal to your friend, no matter what.</span>")
|
||||
to_chat(src, "<span class='notice'>You cannot directly influence the world around you, but you can see what [owner] cannot.</span>")
|
||||
greet()
|
||||
Show()
|
||||
|
||||
/mob/camera/imaginary_friend/proc/greet()
|
||||
to_chat(src, "<span class='notice'><b>You are the imaginary friend of [owner]!</b></span>")
|
||||
to_chat(src, "<span class='notice'>You are absolutely loyal to your friend, no matter what.</span>")
|
||||
to_chat(src, "<span class='notice'>You cannot directly influence the world around you, but you can see what [owner] cannot.</span>")
|
||||
|
||||
/mob/camera/imaginary_friend/Initialize(mapload, _trauma)
|
||||
. = ..()
|
||||
var/gender = pick(MALE, FEMALE)
|
||||
real_name = random_unique_name(gender)
|
||||
name = real_name
|
||||
|
||||
trauma = _trauma
|
||||
owner = trauma.owner
|
||||
copy_known_languages_from(owner, TRUE)
|
||||
human_image = get_flat_human_icon(null, pick(SSjob.occupations))
|
||||
|
||||
setup_friend()
|
||||
|
||||
join = new
|
||||
join.Grant(src)
|
||||
hide = new
|
||||
hide.Grant(src)
|
||||
|
||||
/mob/camera/imaginary_friend/proc/setup_friend()
|
||||
var/gender = pick(MALE, FEMALE)
|
||||
real_name = random_unique_name(gender)
|
||||
name = real_name
|
||||
human_image = get_flat_human_icon(null, pick(SSjob.occupations))
|
||||
|
||||
/mob/camera/imaginary_friend/proc/Show()
|
||||
if(!client) //nobody home
|
||||
return
|
||||
@@ -132,7 +144,7 @@
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, "You cannot send IC messages (muted).")
|
||||
return
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
if (!(ignore_spam || forced) && src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
|
||||
friend_talk(message)
|
||||
@@ -218,4 +230,42 @@
|
||||
var/mob/camera/imaginary_friend/I = owner
|
||||
I.hidden = !I.hidden
|
||||
I.Show()
|
||||
update_status()
|
||||
update_status()
|
||||
|
||||
//down here is the trapped mind
|
||||
//like imaginary friend but a lot less imagination and more like mind prison//
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/trapped_owner
|
||||
name = "Trapped Victim"
|
||||
desc = "Patient appears to be targeted by an invisible entity."
|
||||
gain_text = ""
|
||||
lose_text = ""
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/trapped_owner/make_friend()
|
||||
friend = new /mob/camera/imaginary_friend/trapped(get_turf(owner), src)
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/trapped_owner/reroll_friend() //no rerolling- it's just the last owner's hell
|
||||
if(friend.client) //reconnected
|
||||
return
|
||||
friend_initialized = FALSE
|
||||
QDEL_NULL(friend)
|
||||
qdel(src)
|
||||
|
||||
/datum/brain_trauma/special/imaginary_friend/trapped_owner/get_ghost() //no randoms
|
||||
return
|
||||
|
||||
/mob/camera/imaginary_friend/trapped
|
||||
name = "figment of imagination?"
|
||||
real_name = "figment of imagination?"
|
||||
desc = "The previous host of this body."
|
||||
|
||||
/mob/camera/imaginary_friend/trapped/greet()
|
||||
to_chat(src, "<span class='notice'><b>You have managed to hold on as a figment of the new host's imagination!</b></span>")
|
||||
to_chat(src, "<span class='notice'>All hope is lost for you, but at least you may interact with your host. You do not have to be loyal to them.</span>")
|
||||
to_chat(src, "<span class='notice'>You cannot directly influence the world around you, but you can see what the host cannot.</span>")
|
||||
|
||||
/mob/camera/imaginary_friend/trapped/setup_friend()
|
||||
real_name = "[owner.real_name]?"
|
||||
name = real_name
|
||||
human_image = icon('icons/mob/lavaland/lavaland_monsters.dmi', icon_state = "curseblob")
|
||||
|
||||
@@ -64,21 +64,21 @@
|
||||
name = "Speech Impediment"
|
||||
desc = "Patient is unable to form coherent sentences."
|
||||
scan_desc = "communication disorder"
|
||||
gain_text = "" //mutation will handle the text
|
||||
lose_text = ""
|
||||
gain_text = "<span class='danger'>You can't seem to form any coherent thoughts!</span>"
|
||||
lose_text = "<span class='danger'>Your mind feels more clear.</span>"
|
||||
|
||||
/datum/brain_trauma/mild/speech_impediment/on_gain()
|
||||
ADD_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, TRAUMA_TRAIT)
|
||||
. = ..()
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/speech_impediment/on_lose()
|
||||
REMOVE_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, TRAUMA_TRAIT)
|
||||
. = ..()
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/concussion
|
||||
name = "Concussion"
|
||||
desc = "Patient's brain is concussed."
|
||||
scan_desc = "a concussion"
|
||||
scan_desc = "concussion"
|
||||
gain_text = "<span class='warning'>Your head hurts!</span>"
|
||||
lose_text = "<span class='notice'>The pressure inside your head starts fading.</span>"
|
||||
|
||||
@@ -157,54 +157,108 @@
|
||||
gain_text = "<span class='warning'>Your muscles feel oddly faint.</span>"
|
||||
lose_text = "<span class='notice'>You feel in control of your muscles again.</span>"
|
||||
|
||||
/datum/brain_trauma/mild/muscle_spasms/on_life()
|
||||
if(prob(7))
|
||||
switch(rand(1,5))
|
||||
if(1)
|
||||
if(owner.canmove && !isspaceturf(owner.loc))
|
||||
to_chat(owner, "<span class='warning'>Your leg spasms!</span>")
|
||||
step(owner, pick(GLOB.cardinals))
|
||||
if(2)
|
||||
if(owner.incapacitated())
|
||||
return
|
||||
var/obj/item/I = owner.get_active_held_item()
|
||||
if(I)
|
||||
to_chat(owner, "<span class='warning'>Your fingers spasm!</span>")
|
||||
owner.log_message("used [I] due to a Muscle Spasm", LOG_ATTACK)
|
||||
I.attack_self(owner)
|
||||
if(3)
|
||||
var/prev_intent = owner.a_intent
|
||||
owner.a_intent = INTENT_HARM
|
||||
|
||||
var/range = 1
|
||||
if(istype(owner.get_active_held_item(), /obj/item/gun)) //get targets to shoot at
|
||||
range = 7
|
||||
|
||||
var/list/mob/living/targets = list()
|
||||
for(var/mob/M in oview(owner, range))
|
||||
if(isliving(M))
|
||||
targets += M
|
||||
if(LAZYLEN(targets))
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
owner.log_message(" attacked someone due to a Muscle Spasm") //the following attack will log itself
|
||||
owner.ClickOn(pick(targets))
|
||||
owner.a_intent = prev_intent
|
||||
if(4)
|
||||
var/prev_intent = owner.a_intent
|
||||
owner.a_intent = INTENT_HARM
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
owner.log_message("attacked [owner.p_them()]self to a Muscle Spasm", LOG_ATTACK)
|
||||
owner.ClickOn(owner)
|
||||
owner.a_intent = prev_intent
|
||||
if(5)
|
||||
if(owner.incapacitated())
|
||||
return
|
||||
var/obj/item/I = owner.get_active_held_item()
|
||||
var/list/turf/targets = list()
|
||||
for(var/turf/T in oview(owner, 3))
|
||||
targets += T
|
||||
if(LAZYLEN(targets) && I)
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
owner.log_message("threw [I] due to a Muscle Spasm", LOG_ATTACK)
|
||||
owner.throw_item(pick(targets))
|
||||
/datum/brain_trauma/mild/muscle_spasms/on_gain()
|
||||
owner.apply_status_effect(STATUS_EFFECT_SPASMS)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/muscle_spasms/on_lose()
|
||||
owner.remove_status_effect(STATUS_EFFECT_SPASMS)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/nervous_cough
|
||||
name = "Nervous Cough"
|
||||
desc = "Patient feels a constant need to cough."
|
||||
scan_desc = "nervous cough"
|
||||
gain_text = "<span class='warning'>Your throat itches incessantly...</span>"
|
||||
lose_text = "<span class='notice'>Your throat stops itching.</span>"
|
||||
|
||||
/datum/brain_trauma/mild/nervous_cough/on_life()
|
||||
if(prob(12) && !HAS_TRAIT(owner, TRAIT_SOOTHED_THROAT))
|
||||
if(prob(5))
|
||||
to_chat(owner, "<span notice='warning'>[pick("You have a coughing fit!", "You can't stop coughing!")]</span>")
|
||||
owner.Stun(20)
|
||||
owner.emote("cough")
|
||||
addtimer(CALLBACK(owner, /mob/.proc/emote, "cough"), 6)
|
||||
addtimer(CALLBACK(owner, /mob/.proc/emote, "cough"), 12)
|
||||
owner.emote("cough")
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/mild/expressive_aphasia
|
||||
name = "Expressive Aphasia"
|
||||
desc = "Patient is affected by partial loss of speech leading to a reduced vocabulary."
|
||||
scan_desc = "inability to form complex sentences"
|
||||
gain_text = "<span class='warning'>You lose your grasp on complex words.</span>"
|
||||
lose_text = "<span class='notice'>You feel your vocabulary returning to normal again.</span>"
|
||||
|
||||
var/static/list/common_words = world.file2list("strings/1000_most_common.txt")
|
||||
|
||||
/datum/brain_trauma/mild/expressive_aphasia/handle_speech(datum/source, list/speech_args)
|
||||
var/message = speech_args[SPEECH_MESSAGE]
|
||||
if(message)
|
||||
var/list/message_split = splittext(message, " ")
|
||||
var/list/new_message = list()
|
||||
|
||||
for(var/word in message_split)
|
||||
var/suffix = copytext(word,-1)
|
||||
|
||||
// Check if we have a suffix and break it out of the word
|
||||
if(suffix in list("." , "," , ";" , "!" , ":" , "?"))
|
||||
word = copytext(word,1,-1)
|
||||
else
|
||||
suffix = ""
|
||||
|
||||
word = html_decode(word)
|
||||
|
||||
if(lowertext(word) in common_words)
|
||||
new_message += word + suffix
|
||||
else
|
||||
if(prob(30) && message_split.len > 2)
|
||||
new_message += pick("uh","erm")
|
||||
break
|
||||
else
|
||||
var/list/charlist = string2charlist(word) // Stupid shit code
|
||||
shuffle_inplace(charlist)
|
||||
charlist.len = round(charlist.len * 0.5,1)
|
||||
new_message += html_encode(jointext(charlist,"")) + suffix
|
||||
|
||||
message = jointext(new_message, " ")
|
||||
|
||||
speech_args[SPEECH_MESSAGE] = trim(message)
|
||||
|
||||
/datum/brain_trauma/mild/mind_echo
|
||||
name = "Mind Echo"
|
||||
desc = "Patient's language neurons do not terminate properly, causing previous speech patterns to occasionally resurface spontaneously."
|
||||
scan_desc = "looping neural pattern"
|
||||
gain_text = "<span class='warning'>You feel a faint echo of your thoughts...</span>"
|
||||
lose_text = "<span class='notice'>The faint echo fades away.</span>"
|
||||
var/list/hear_dejavu = list()
|
||||
var/list/speak_dejavu = list()
|
||||
|
||||
/datum/brain_trauma/mild/mind_echo/handle_hearing(datum/source, list/hearing_args)
|
||||
if(owner == hearing_args[HEARING_SPEAKER])
|
||||
return
|
||||
if(hear_dejavu.len >= 5)
|
||||
if(prob(25))
|
||||
var/deja_vu = pick_n_take(hear_dejavu)
|
||||
var/static/regex/quoted_spoken_message = regex("\".+\"", "gi")
|
||||
hearing_args[HEARING_RAW_MESSAGE] = quoted_spoken_message.Replace(hearing_args[HEARING_RAW_MESSAGE], "\"[deja_vu]\"") //Quotes included to avoid cases where someone says part of their name
|
||||
return
|
||||
if(hear_dejavu.len >= 15)
|
||||
if(prob(50))
|
||||
popleft(hear_dejavu) //Remove the oldest
|
||||
hear_dejavu += hearing_args[HEARING_RAW_MESSAGE]
|
||||
else
|
||||
hear_dejavu += hearing_args[HEARING_RAW_MESSAGE]
|
||||
|
||||
/datum/brain_trauma/mild/mind_echo/handle_speech(datum/source, list/speech_args)
|
||||
if(speak_dejavu.len >= 5)
|
||||
if(prob(25))
|
||||
var/deja_vu = pick_n_take(speak_dejavu)
|
||||
speech_args[SPEECH_MESSAGE] = deja_vu
|
||||
return
|
||||
if(speak_dejavu.len >= 15)
|
||||
if(prob(50))
|
||||
popleft(speak_dejavu) //Remove the oldest
|
||||
speak_dejavu += speech_args[SPEECH_MESSAGE]
|
||||
else
|
||||
speak_dejavu += speech_args[SPEECH_MESSAGE]
|
||||
@@ -2,8 +2,8 @@
|
||||
name = "Phobia"
|
||||
desc = "Patient is unreasonably afraid of something."
|
||||
scan_desc = "phobia"
|
||||
gain_text = ""
|
||||
lose_text = ""
|
||||
gain_text = "<span class='warning'>You start finding default values very unnerving...</span>"
|
||||
lose_text = "<span class='notice'>You no longer feel afraid of default values.</span>"
|
||||
var/phobia_type
|
||||
var/next_check = 0
|
||||
var/next_scare = 0
|
||||
@@ -14,8 +14,10 @@
|
||||
var/list/trigger_turfs
|
||||
var/list/trigger_species
|
||||
|
||||
/datum/brain_trauma/mild/phobia/New(specific_type)
|
||||
phobia_type = specific_type
|
||||
/datum/brain_trauma/mild/phobia/New(new_phobia_type)
|
||||
if(new_phobia_type)
|
||||
phobia_type = new_phobia_type
|
||||
|
||||
if(!phobia_type)
|
||||
phobia_type = pick(SStraumas.phobia_types)
|
||||
|
||||
@@ -29,6 +31,11 @@
|
||||
trigger_species = SStraumas.phobia_species[phobia_type]
|
||||
..()
|
||||
|
||||
|
||||
/datum/brain_trauma/mild/phobia/on_clone()
|
||||
if(clonable)
|
||||
return new type(phobia_type)
|
||||
|
||||
/datum/brain_trauma/mild/phobia/on_life()
|
||||
..()
|
||||
if(HAS_TRAIT(owner, TRAIT_FEARLESS))
|
||||
@@ -44,6 +51,12 @@
|
||||
if(is_type_in_typecache(O, trigger_objs))
|
||||
freak_out(O)
|
||||
return
|
||||
for(var/mob/living/carbon/human/HU in seen_atoms) //check equipment for trigger items
|
||||
for(var/X in HU.get_all_slots() | HU.held_items)
|
||||
var/obj/I = X
|
||||
if(!QDELETED(I) && is_type_in_typecache(I, trigger_objs))
|
||||
freak_out(I)
|
||||
return
|
||||
|
||||
if(LAZYLEN(trigger_turfs))
|
||||
for(var/turf/T in seen_atoms)
|
||||
@@ -51,45 +64,41 @@
|
||||
freak_out(T)
|
||||
return
|
||||
|
||||
if(LAZYLEN(trigger_mobs) || LAZYLEN(trigger_objs))
|
||||
seen_atoms -= owner //make sure they aren't afraid of themselves.
|
||||
if(LAZYLEN(trigger_mobs) || LAZYLEN(trigger_species))
|
||||
for(var/mob/M in seen_atoms)
|
||||
if(is_type_in_typecache(M, trigger_mobs))
|
||||
freak_out(M)
|
||||
return
|
||||
|
||||
else if(ishuman(M)) //check their equipment for trigger items
|
||||
else if(ishuman(M)) //check their species
|
||||
var/mob/living/carbon/human/H = M
|
||||
|
||||
if(LAZYLEN(trigger_species) && H.dna && H.dna.species && is_type_in_typecache(H.dna.species, trigger_species))
|
||||
freak_out(H)
|
||||
return
|
||||
|
||||
for(var/X in H.get_all_slots() | H.held_items)
|
||||
var/obj/I = X
|
||||
if(!QDELETED(I) && is_type_in_typecache(I, trigger_objs))
|
||||
freak_out(I)
|
||||
return
|
||||
|
||||
/datum/brain_trauma/mild/phobia/on_hear(message, speaker, message_language, raw_message, radio_freq)
|
||||
/datum/brain_trauma/mild/phobia/handle_hearing(datum/source, list/hearing_args)
|
||||
if(!owner.can_hear() || world.time < next_scare) //words can't trigger you if you can't hear them *taps head*
|
||||
return message
|
||||
return
|
||||
if(HAS_TRAIT(owner, TRAIT_FEARLESS))
|
||||
return message
|
||||
return
|
||||
for(var/word in trigger_words)
|
||||
var/reg = regex("(\\b|\\A)[REGEX_QUOTE(word)]'?s*(\\b|\\Z)", "i")
|
||||
var/regex/reg = regex("(\\b|\\A)[REGEX_QUOTE(word)]'?s*(\\b|\\Z)", "i")
|
||||
|
||||
if(findtext(raw_message, reg))
|
||||
if(findtext(hearing_args[HEARING_RAW_MESSAGE], reg))
|
||||
addtimer(CALLBACK(src, .proc/freak_out, null, word), 10) //to react AFTER the chat message
|
||||
hearing_args[HEARING_RAW_MESSAGE] = reg.Replace(hearing_args[HEARING_RAW_MESSAGE], "<span class='phobia'>$1</span>")
|
||||
break
|
||||
return message
|
||||
|
||||
/datum/brain_trauma/mild/phobia/handle_speech(datum/source, list/speech_args)
|
||||
if(HAS_TRAIT(owner, TRAIT_FEARLESS))
|
||||
return
|
||||
for(var/word in trigger_words)
|
||||
var/reg = regex("(\\b|\\A)[REGEX_QUOTE(word)]'?s*(\\b|\\Z)", "i")
|
||||
var/regex/reg = regex("(\\b|\\A)[REGEX_QUOTE(word)]'?s*(\\b|\\Z)", "i")
|
||||
|
||||
if(findtext(speech_args[SPEECH_MESSAGE], reg))
|
||||
to_chat(owner, "<span class='warning'>You can't bring yourself to say the word \"[word]\"!</span>")
|
||||
to_chat(owner, "<span class='warning'>You can't bring yourself to say the word \"<span class='phobia'>[word]</span>\"!</span>")
|
||||
speech_args[SPEECH_MESSAGE] = ""
|
||||
|
||||
/datum/brain_trauma/mild/phobia/proc/freak_out(atom/reason, trigger_word)
|
||||
@@ -125,6 +134,76 @@
|
||||
owner.Jitter(10)
|
||||
owner.stuttering += 10
|
||||
|
||||
// Defined phobia types for badminry, not included in the RNG trauma pool to avoid diluting.
|
||||
|
||||
/datum/brain_trauma/mild/phobia/spiders
|
||||
phobia_type = "spiders"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/space
|
||||
phobia_type = "space"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/security
|
||||
phobia_type = "security"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/clowns
|
||||
phobia_type = "clowns"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/greytide
|
||||
phobia_type = "greytide"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/lizards
|
||||
phobia_type = "lizards"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/skeletons
|
||||
phobia_type = "skeletons"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/snakes
|
||||
phobia_type = "snakes"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/robots
|
||||
phobia_type = "robots"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/doctors
|
||||
phobia_type = "doctors"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/authority
|
||||
phobia_type = "authority"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/supernatural
|
||||
phobia_type = "the supernatural"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/aliens
|
||||
phobia_type = "aliens"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/strangers
|
||||
phobia_type = "strangers"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/birds
|
||||
phobia_type = "birds"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/falling
|
||||
phobia_type = "falling"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/anime
|
||||
phobia_type = "anime"
|
||||
random_gain = FALSE
|
||||
|
||||
/datum/brain_trauma/mild/phobia/conspiracies
|
||||
phobia_type = "conspiracies"
|
||||
random_gain = FALSE
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
owner.update_disabled_bodyparts()
|
||||
|
||||
/datum/brain_trauma/severe/paralysis/paraplegic
|
||||
//can_gain = FALSE maybe breaks.
|
||||
random_gain = FALSE
|
||||
paralysis_type = "legs"
|
||||
resilience = TRAUMA_RESILIENCE_ABSOLUTE
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
/datum/brain_trauma/severe/monophobia
|
||||
name = "Monophobia"
|
||||
desc = "Patient feels sick and distressed when not around other people, leading to potentially lethal levels of stress."
|
||||
scan_desc = "severe monophobia"
|
||||
scan_desc = "monophobia"
|
||||
gain_text = ""
|
||||
lose_text = "<span class='notice'>You feel like you could be safe on your own.</span>"
|
||||
var/stress = 0
|
||||
@@ -168,7 +168,7 @@
|
||||
if(stress > 10 && (prob(5)))
|
||||
stress_reaction()
|
||||
else
|
||||
stress -= 4
|
||||
stress = max(stress - 4, 0)
|
||||
|
||||
/datum/brain_trauma/severe/monophobia/proc/check_alone()
|
||||
if(HAS_TRAIT(owner, TRAIT_BLIND))
|
||||
|
||||
@@ -22,6 +22,14 @@
|
||||
else
|
||||
speak("neutral", prob(25))
|
||||
|
||||
/datum/brain_trauma/special/godwoken/on_gain()
|
||||
ADD_TRAIT(owner, TRAIT_HOLY, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/special/godwoken/on_lose()
|
||||
REMOVE_TRAIT(owner, TRAIT_HOLY, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/special/godwoken/proc/speak(type, include_owner = FALSE)
|
||||
var/message
|
||||
switch(type)
|
||||
@@ -36,7 +44,7 @@
|
||||
else
|
||||
message = pick_list_replacements(BRAIN_DAMAGE_FILE, "god_neutral")
|
||||
|
||||
playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 200, 1, 5)
|
||||
playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 200, TRUE, 5)
|
||||
voice_of_god(message, owner, list("colossus","yell"), 2.5, include_owner, FALSE)
|
||||
|
||||
/datum/brain_trauma/special/bluespace_prophet
|
||||
@@ -134,7 +142,101 @@
|
||||
|
||||
/datum/brain_trauma/special/psychotic_brawling/bath_salts
|
||||
name = "Chemical Violent Psychosis"
|
||||
random_gain = FALSE
|
||||
clonable = FALSE
|
||||
|
||||
/datum/brain_trauma/special/tenacity
|
||||
name = "Tenacity"
|
||||
desc = "Patient is psychologically unaffected by pain and injuries, and can remain standing far longer than a normal person."
|
||||
scan_desc = "traumatic neuropathy"
|
||||
gain_text = "<span class='warning'>You suddenly stop feeling pain.</span>"
|
||||
lose_text = "<span class='warning'>You realize you can feel pain again.</span>"
|
||||
|
||||
/datum/brain_trauma/special/tenacity/on_gain()
|
||||
ADD_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAUMA_TRAIT)
|
||||
ADD_TRAIT(owner, TRAIT_NOHARDCRIT, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/special/tenacity/on_lose()
|
||||
REMOVE_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAUMA_TRAIT)
|
||||
REMOVE_TRAIT(owner, TRAIT_NOHARDCRIT, TRAUMA_TRAIT)
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/special/death_whispers
|
||||
name = "Functional Cerebral Necrosis"
|
||||
desc = "Patient's brain is stuck in a functional near-death state, causing occasional moments of lucid hallucinations, which are often interpreted as the voices of the dead."
|
||||
scan_desc = "chronic functional necrosis"
|
||||
gain_text = "<span class='warning'>You feel dead inside.</span>"
|
||||
lose_text = "<span class='notice'>You feel alive again.</span>"
|
||||
var/active = FALSE
|
||||
|
||||
/datum/brain_trauma/special/death_whispers/on_life()
|
||||
..()
|
||||
if(!active && prob(2))
|
||||
whispering()
|
||||
|
||||
/datum/brain_trauma/special/death_whispers/on_lose()
|
||||
if(active)
|
||||
cease_whispering()
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/special/death_whispers/proc/whispering()
|
||||
ADD_TRAIT(owner, TRAIT_SIXTHSENSE, TRAUMA_TRAIT)
|
||||
active = TRUE
|
||||
addtimer(CALLBACK(src, .proc/cease_whispering), rand(50, 300))
|
||||
|
||||
/datum/brain_trauma/special/death_whispers/proc/cease_whispering()
|
||||
REMOVE_TRAIT(owner, TRAIT_SIXTHSENSE, TRAUMA_TRAIT)
|
||||
active = FALSE
|
||||
|
||||
/datum/brain_trauma/special/existential_crisis
|
||||
name = "Existential Crisis"
|
||||
desc = "Patient's hold on reality becomes faint, causing occasional bouts of non-existence."
|
||||
scan_desc = "existential crisis"
|
||||
gain_text = "<span class='notice'>You feel less real.</span>"
|
||||
lose_text = "<span class='warning'>You feel more substantial again.</span>"
|
||||
var/obj/effect/abstract/sync_holder/veil/veil
|
||||
var/next_crisis = 0
|
||||
|
||||
/datum/brain_trauma/special/existential_crisis/on_life()
|
||||
..()
|
||||
if(!veil && world.time > next_crisis && prob(3))
|
||||
if(isturf(owner.loc))
|
||||
fade_out()
|
||||
|
||||
/datum/brain_trauma/special/existential_crisis/on_lose()
|
||||
if(veil)
|
||||
fade_in()
|
||||
..()
|
||||
|
||||
/datum/brain_trauma/special/existential_crisis/proc/fade_out()
|
||||
if(veil)
|
||||
return
|
||||
var/duration = rand(50, 450)
|
||||
veil = new(owner.drop_location())
|
||||
to_chat(owner, "<span class='warning'>[pick("You stop thinking for a moment. Therefore you are not.",\
|
||||
"To be or not to be...",\
|
||||
"Why exist?",\
|
||||
"You stop keeping it real.",\
|
||||
"Your grip on existence slips.",\
|
||||
"Do you even exist?",\
|
||||
"You simply fade away.")]</span>")
|
||||
owner.forceMove(veil)
|
||||
SEND_SIGNAL(owner, COMSIG_MOVABLE_SECLUDED_LOCATION)
|
||||
for(var/thing in owner)
|
||||
var/atom/movable/AM = thing
|
||||
SEND_SIGNAL(AM, COMSIG_MOVABLE_SECLUDED_LOCATION)
|
||||
next_crisis = world.time + 600
|
||||
addtimer(CALLBACK(src, .proc/fade_in), duration)
|
||||
|
||||
/datum/brain_trauma/special/existential_crisis/proc/fade_in()
|
||||
QDEL_NULL(veil)
|
||||
to_chat(owner, "<span class='notice'>You fade back into reality.</span>")
|
||||
next_crisis = world.time + 600
|
||||
|
||||
//base sync holder is in desynchronizer.dm
|
||||
/obj/effect/abstract/sync_holder/veil
|
||||
name = "non-existence"
|
||||
desc = "Existence is just a state of mind."
|
||||
|
||||
/datum/brain_trauma/special/beepsky
|
||||
name = "Criminal"
|
||||
@@ -142,6 +244,7 @@
|
||||
scan_desc = "criminal mind"
|
||||
gain_text = "<span class='warning'>Justice is coming for you.</span>"
|
||||
lose_text = "<span class='notice'>You were absolved for your crimes.</span>"
|
||||
clonable = FALSE
|
||||
random_gain = FALSE
|
||||
var/obj/effect/hallucination/simple/securitron/beepsky
|
||||
|
||||
@@ -201,4 +304,4 @@
|
||||
|
||||
/obj/effect/hallucination/simple/securitron/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess,src)
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
var/mob/living/split_personality/owner_backseat
|
||||
|
||||
/datum/brain_trauma/severe/split_personality/on_gain()
|
||||
var/mob/living/M = owner
|
||||
if(M.stat == DEAD) //No use assigning people to a corpse
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
make_backseats()
|
||||
get_ghost()
|
||||
@@ -23,7 +27,7 @@
|
||||
|
||||
/datum/brain_trauma/severe/split_personality/proc/get_ghost()
|
||||
set waitfor = FALSE
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", ROLE_PAI, null, null, 75, stranger_backseat)
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", ROLE_PAI, null, null, 75, stranger_backseat, POLL_IGNORE_SPLITPERSONALITY)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
C.transfer_ckey(stranger_backseat, FALSE)
|
||||
@@ -191,13 +195,13 @@
|
||||
/datum/brain_trauma/severe/split_personality/brainwashing/on_life()
|
||||
return //no random switching
|
||||
|
||||
/datum/brain_trauma/severe/split_personality/brainwashing/on_hear(message, speaker, message_language, raw_message, radio_freq)
|
||||
if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == speaker)
|
||||
return message
|
||||
/datum/brain_trauma/severe/split_personality/brainwashing/handle_hearing(datum/source, list/hearing_args)
|
||||
if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER])
|
||||
return
|
||||
var/message = hearing_args[HEARING_RAW_MESSAGE]
|
||||
if(findtext(message, codeword))
|
||||
message = replacetext(message, codeword, "<span class='warning'>[codeword]</span>")
|
||||
hearing_args[HEARING_RAW_MESSAGE] = replacetext(message, codeword, "<span class='warning'>[codeword]</span>")
|
||||
addtimer(CALLBACK(src, /datum/brain_trauma/severe/split_personality.proc/switch_personalities), 10)
|
||||
return message
|
||||
|
||||
/datum/brain_trauma/severe/split_personality/brainwashing/handle_speech(datum/source, list/speech_args)
|
||||
if(findtext(speech_args[SPEECH_MESSAGE], codeword))
|
||||
|
||||
@@ -184,6 +184,7 @@
|
||||
|
||||
// The type arg is casted so initial works, you shouldn't be passing a real instance into this
|
||||
/datum/proc/GetComponent(datum/component/c_type)
|
||||
RETURN_TYPE(c_type)
|
||||
if(initial(c_type.dupe_mode) == COMPONENT_DUPE_ALLOWED)
|
||||
stack_trace("GetComponent was called to get a component of which multiple copies could be on an object. This can easily break and should be changed. Type: \[[c_type]\]")
|
||||
var/list/dc = datum_components
|
||||
|
||||
@@ -29,21 +29,21 @@
|
||||
var/obj/item/typecast = upgrade_item
|
||||
upgrade_name = initial(typecast.name)
|
||||
|
||||
/datum/component/armor_plate/proc/examine(datum/source, mob/user)
|
||||
/datum/component/armor_plate/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
//upgrade_item could also be typecast here instead
|
||||
if(ismecha(parent))
|
||||
if(amount)
|
||||
if(amount < maxamount)
|
||||
to_chat(user, "<span class='notice'>Its armor is enhanced with [amount] [upgrade_name].</span>")
|
||||
examine_list += "<span class='notice'>Its armor is enhanced with [amount] [upgrade_name].</span>"
|
||||
else
|
||||
to_chat(user, "<span class='notice'>It's wearing a fearsome carapace entirely composed of [upgrade_name] - its pilot must be an experienced monster hunter.</span>")
|
||||
examine_list += "<span class='notice'>It's wearing a fearsome carapace entirely composed of [upgrade_name] - its pilot must be an experienced monster hunter.</span>"
|
||||
else
|
||||
to_chat(user, "<span class='notice'>It has attachment points for strapping monster hide on for added protection.</span>")
|
||||
examine_list += "<span class='notice'>It has attachment points for strapping monster hide on for added protection.</span>"
|
||||
else
|
||||
if(amount)
|
||||
to_chat(user, "<span class='notice'>It has been strengthened with [amount]/[maxamount] [upgrade_name].</span>")
|
||||
examine_list += "<span class='notice'>It has been strengthened with [amount]/[maxamount] [upgrade_name].</span>"
|
||||
else
|
||||
to_chat(user, "<span class='notice'>It can be strengthened with up to [maxamount] [upgrade_name].</span>")
|
||||
examine_list += "<span class='notice'>It can be strengthened with up to [maxamount] [upgrade_name].</span>"
|
||||
|
||||
/datum/component/armor_plate/proc/applyplate(datum/source, obj/item/I, mob/user, params)
|
||||
if(!istype(I,upgrade_item))
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
var/bonus_modifier = 0 //percentage increase to bonus item chance
|
||||
var/butcher_sound = 'sound/weapons/slice.ogg' //sound played when butchering
|
||||
var/butchering_enabled = TRUE
|
||||
var/can_be_blunt = FALSE
|
||||
|
||||
/datum/component/butchering/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled)
|
||||
/datum/component/butchering/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled, _can_be_blunt)
|
||||
if(_speed)
|
||||
speed = _speed
|
||||
if(_effectiveness)
|
||||
@@ -16,6 +17,22 @@
|
||||
butcher_sound = _butcher_sound
|
||||
if(disabled)
|
||||
butchering_enabled = FALSE
|
||||
if(_can_be_blunt)
|
||||
can_be_blunt = _can_be_blunt
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/onItemAttack)
|
||||
|
||||
/datum/component/butchering/proc/onItemAttack(obj/item/source, mob/living/M, mob/living/user)
|
||||
if(user.a_intent == INTENT_HARM && M.stat == DEAD && (M.butcher_results || M.guaranteed_butcher_results)) //can we butcher it?
|
||||
if(butchering_enabled && (can_be_blunt || source.get_sharpness()))
|
||||
INVOKE_ASYNC(src, .proc/startButcher, source, M, user)
|
||||
return COMPONENT_ITEM_NO_ATTACK
|
||||
|
||||
/datum/component/butchering/proc/startButcher(obj/item/source, mob/living/M, mob/living/user)
|
||||
to_chat(user, "<span class='notice'>You begin to butcher [M]...</span>")
|
||||
playsound(M.loc, butcher_sound, 50, TRUE, -1)
|
||||
if(do_mob(user, M, speed) && M.Adjacent(source))
|
||||
Butcher(user, M)
|
||||
|
||||
/datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat)
|
||||
var/turf/T = meat.drop_location()
|
||||
@@ -50,3 +67,23 @@
|
||||
|
||||
/datum/component/butchering/proc/ButcherEffects(mob/living/meat) //extra effects called on butchering, override this via subtypes
|
||||
return
|
||||
|
||||
///Special snowflake component only used for the recycler.
|
||||
/datum/component/butchering/recycler
|
||||
|
||||
/datum/component/butchering/recycler/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled, _can_be_blunt)
|
||||
if(!istype(parent, /obj/machinery/recycler)) //EWWW
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
. = ..()
|
||||
if(. == COMPONENT_INCOMPATIBLE)
|
||||
return
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/onCrossed)
|
||||
|
||||
/datum/component/butchering/recycler/proc/onCrossed(datum/source, mob/living/L)
|
||||
if(!istype(L))
|
||||
return
|
||||
var/obj/machinery/recycler/eater = parent
|
||||
if(eater.safety_mode || (eater.stat & (BROKEN|NOPOWER))) //I'm so sorry.
|
||||
return
|
||||
if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results))
|
||||
Butcher(parent, L)
|
||||
@@ -19,9 +19,9 @@
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY,.proc/action)
|
||||
update_parent(index)
|
||||
|
||||
/datum/component/construction/proc/examine(datum/source, mob/user)
|
||||
/datum/component/construction/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
if(desc)
|
||||
to_chat(user, desc)
|
||||
examine_list += desc
|
||||
|
||||
/datum/component/construction/proc/on_step()
|
||||
if(index > steps.len)
|
||||
|
||||
@@ -71,5 +71,5 @@
|
||||
if(strength >= cleanable)
|
||||
qdel(src)
|
||||
|
||||
/datum/component/decal/proc/examine(datum/source, mob/user)
|
||||
to_chat(user, description)
|
||||
/datum/component/decal/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
examine_list += description
|
||||
@@ -1,30 +0,0 @@
|
||||
// An item worn in the ear slot with this component will heal your ears each
|
||||
// Life() tick, even if normally your ears would be too damaged to heal.
|
||||
|
||||
/datum/component/earhealing
|
||||
var/mob/living/carbon/wearer
|
||||
|
||||
/datum/component/earhealing/Initialize()
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED), .proc/equippedChanged)
|
||||
|
||||
/datum/component/earhealing/proc/equippedChanged(datum/source, mob/living/carbon/user, slot)
|
||||
if (slot == SLOT_EARS && istype(user))
|
||||
if (!wearer)
|
||||
START_PROCESSING(SSobj, src)
|
||||
wearer = user
|
||||
else
|
||||
if (wearer)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
wearer = null
|
||||
|
||||
/datum/component/earhealing/process()
|
||||
if (!wearer)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return
|
||||
if(!HAS_TRAIT(wearer, TRAIT_DEAF))
|
||||
var/obj/item/organ/ears/ears = wearer.getorganslot(ORGAN_SLOT_EARS)
|
||||
if (ears)
|
||||
ears.deaf = max(ears.deaf - 1, (ears.damage < ears.maxHealth ? 0 : 1)) // Do not clear deafness if our ears are too damaged
|
||||
ears.damage = max(ears.damage - 0.1, 0)
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
/datum/component/lockon_aiming
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED
|
||||
var/lock_icon = 'icons/mob/blob.dmi'
|
||||
var/lock_icon = 'icons/mob/cameramob.dmi'
|
||||
var/lock_icon_state = "marker"
|
||||
var/mutable_appearance/lock_appearance
|
||||
var/list/image/lock_images
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
for(var/i in parent)
|
||||
RegisterSignal(i, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react)
|
||||
|
||||
/datum/component/magnetic_catch/proc/examine(datum/source, mob/user)
|
||||
to_chat(user, "It has been installed with inertia dampening to prevent coffee spills.")
|
||||
/datum/component/magnetic_catch/proc/examine(datum/source, mob/user, list/examine_list)
|
||||
examine_list += "It has been installed with inertia dampening to prevent coffee spills."
|
||||
|
||||
/datum/component/magnetic_catch/proc/crossed_react(datum/source, atom/movable/thing)
|
||||
RegisterSignal(thing, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react, TRUE)
|
||||
|
||||
@@ -49,13 +49,13 @@
|
||||
var/mat_path = possible_mats[id]
|
||||
materials[id] = new mat_path()
|
||||
|
||||
/datum/component/material_container/proc/OnExamine(datum/source, mob/user)
|
||||
/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
|
||||
if(show_on_examine)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = materials[I]
|
||||
var/amt = amount(M.id)
|
||||
if(amt)
|
||||
to_chat(user, "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>")
|
||||
examine_list += "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>"
|
||||
|
||||
/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user)
|
||||
var/list/tc = allowed_typecache
|
||||
|
||||
@@ -125,6 +125,9 @@
|
||||
screen_obj.icon_state = "mood[mood_level]"
|
||||
|
||||
/datum/component/mood/process() //Called on SSmood process
|
||||
if(QDELETED(parent)) // workaround to an obnoxious sneaky periodical runtime.
|
||||
qdel(src)
|
||||
return
|
||||
var/mob/living/owner = parent
|
||||
|
||||
switch(mood_level)
|
||||
@@ -245,11 +248,11 @@
|
||||
var/datum/hud/hud = owner.hud_used
|
||||
screen_obj = new
|
||||
hud.infodisplay += screen_obj
|
||||
RegisterSignal(hud, COMSIG_PARENT_QDELETED, .proc/unmodify_hud)
|
||||
RegisterSignal(hud, COMSIG_PARENT_QDELETING, .proc/unmodify_hud)
|
||||
RegisterSignal(screen_obj, COMSIG_CLICK, .proc/hud_click)
|
||||
|
||||
/datum/component/mood/proc/unmodify_hud(datum/source)
|
||||
if(!screen_obj)
|
||||
if(!screen_obj || !parent)
|
||||
return
|
||||
var/mob/living/owner = parent
|
||||
var/datum/hud/hud = owner.hud_used
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
RegisterSignal(parent, COMSIG_MOB_ALLOWED, .proc/check_access)
|
||||
RegisterSignal(parent, COMSIG_LIVING_ELECTROCUTE_ACT, .proc/on_shock)
|
||||
RegisterSignal(parent, COMSIG_LIVING_MINOR_SHOCK, .proc/on_minor_shock)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_HEAR, .proc/on_hear)
|
||||
RegisterSignal(parent, COMSIG_SPECIES_GAIN, .proc/check_viable_biotype)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SIGNAL, .proc/receive_signal)
|
||||
|
||||
@@ -191,11 +190,6 @@
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_death(gibbed)
|
||||
|
||||
/datum/component/nanites/proc/on_hear(datum/source, message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
|
||||
/datum/component/nanites/proc/receive_signal(datum/source, code, source = "an unidentified source")
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
hl3_release_date = _half_life
|
||||
can_contaminate = _can_contaminate
|
||||
|
||||
if(istype(parent, /atom))
|
||||
if(istype(parent, /atom))
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/rad_examine)
|
||||
if(istype(parent, /obj/item))
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/rad_attack)
|
||||
@@ -58,7 +58,7 @@
|
||||
else
|
||||
strength = max(strength, arguments[1])
|
||||
|
||||
/datum/component/radioactive/proc/rad_examine(datum/source, mob/user, atom/thing)
|
||||
/datum/component/radioactive/proc/rad_examine(datum/source, mob/user, list/examine_list)
|
||||
var/atom/master = parent
|
||||
var/list/out = list()
|
||||
if(get_dist(master, user) <= 1)
|
||||
@@ -72,7 +72,7 @@
|
||||
out += "[out ? " and it " : "[master] "]hurts to look at."
|
||||
else
|
||||
out += "."
|
||||
to_chat(user, out.Join())
|
||||
examine_list += out.Join()
|
||||
|
||||
/datum/component/radioactive/proc/rad_attack(datum/source, atom/movable/target, mob/living/user)
|
||||
radiation_pulse(parent, strength/20)
|
||||
|
||||
@@ -310,10 +310,10 @@
|
||||
if(!user.put_in_hands(inhand, TRUE))
|
||||
qdel(inhand) // it isn't going to be added to offhands anyway
|
||||
break
|
||||
LAZYADD(equipped, src)
|
||||
LAZYADD(equipped, inhand)
|
||||
var/amount_equipped = LAZYLEN(equipped)
|
||||
if(amount_equipped)
|
||||
LAZYADD(offhands[L], amount_equipped)
|
||||
LAZYADD(offhands[L], equipped)
|
||||
if(amount_equipped >= amount_required)
|
||||
return TRUE
|
||||
unequip_buckle_inhands(L)
|
||||
|
||||
@@ -98,9 +98,9 @@
|
||||
remove_verbs()
|
||||
. = ..()
|
||||
|
||||
/datum/component/simple_rotation/proc/ExamineMessage(datum/source, mob/user)
|
||||
/datum/component/simple_rotation/proc/ExamineMessage(datum/source, mob/user, list/examine_list)
|
||||
if(rotation_flags & ROTATION_ALTCLICK)
|
||||
to_chat(user, "<span class='notice'>Alt-click to rotate it clockwise.</span>")
|
||||
examine_list += "<span class='notice'>Alt-click to rotate it clockwise.</span>"
|
||||
|
||||
/datum/component/simple_rotation/proc/HandRot(datum/source, mob/user, rotation = default_rotation_direction)
|
||||
if(!can_be_rotated.Invoke(user, rotation) || !can_user_rotate.Invoke(user, rotation))
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
if(!ismovableatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_Z_CHANGED), .proc/check_in_bounds)
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_SECLUDED_LOCATION), .proc/relocate)
|
||||
RegisterSignal(parent, list(COMSIG_PARENT_PREQDELETED), .proc/check_deletion)
|
||||
RegisterSignal(parent, list(COMSIG_ITEM_IMBUE_SOUL), .proc/check_soul_imbue)
|
||||
src.inform_admins = inform_admins
|
||||
@@ -32,6 +33,7 @@
|
||||
|
||||
var/atom/movable/AM = parent
|
||||
AM.forceMove(targetturf)
|
||||
to_chat(get(parent, /mob), "<span class='danger'>You can't help but feel that you just lost something back there...</span>")
|
||||
// move the disc, so ghosts remain orbiting it even if it's "destroyed"
|
||||
return targetturf
|
||||
|
||||
@@ -40,7 +42,6 @@
|
||||
return
|
||||
else
|
||||
var/turf/currentturf = get_turf(src)
|
||||
to_chat(get(parent, /mob), "<span class='danger'>You can't help but feel that you just lost something back there...</span>")
|
||||
var/turf/targetturf = relocate()
|
||||
log_game("[parent] has been moved out of bounds in [loc_name(currentturf)]. Moving it to [loc_name(targetturf)].")
|
||||
if(inform_admins)
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
var/screen_start_x = 4 //These two are where the storage starts being rendered, screen_loc wise.
|
||||
var/screen_start_y = 2
|
||||
//End
|
||||
|
||||
|
||||
var/limited_random_access = FALSE //Quick if statement in accessible_items to determine if we care at all about what people can access at once.
|
||||
var/limited_random_access_stack_position = 0 //If >0, can only access top <x> items
|
||||
var/limited_random_access_stack_bottom_up = FALSE //If TRUE, above becomes bottom <x> items
|
||||
@@ -309,6 +309,7 @@
|
||||
else
|
||||
var/datum/numbered_display/ND = .[I.type]
|
||||
ND.number++
|
||||
. = sortTim(., /proc/cmp_numbered_displays_name_asc, associative = TRUE)
|
||||
|
||||
//This proc determines the size of the inventory to be displayed. Please touch it only if you know what you're doing.
|
||||
/datum/component/storage/proc/orient2hud(mob/user, maxcolumns)
|
||||
@@ -646,9 +647,9 @@
|
||||
if(M == viewing)
|
||||
to_chat(usr, "<span class='notice'>You put [I] [insert_preposition]to [parent].</span>")
|
||||
else if(in_range(M, viewing)) //If someone is standing close enough, they can tell what it is...
|
||||
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", 1)
|
||||
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", MSG_VISUAL)
|
||||
else if(I && I.w_class >= 3) //Otherwise they can only see large or normal items from a distance...
|
||||
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", 1)
|
||||
viewing.show_message("<span class='notice'>[M] puts [I] [insert_preposition]to [parent].</span>", MSG_VISUAL)
|
||||
|
||||
/datum/component/storage/proc/update_icon()
|
||||
if(isobj(parent))
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
var/mob/vr_M = parent
|
||||
mastermind = M.mind
|
||||
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED), .proc/game_over)
|
||||
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING), .proc/game_over)
|
||||
RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/switch_player)
|
||||
RegisterSignal(mastermind, COMSIG_MIND_TRANSFER, .proc/switch_player)
|
||||
you_die_in_the_game_you_die_for_real = yolo
|
||||
@@ -32,7 +32,7 @@
|
||||
current_mind = M.mind
|
||||
quit_action.Grant(M)
|
||||
RegisterSignal(quit_action, COMSIG_ACTION_TRIGGER, .proc/revert_to_reality)
|
||||
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED), .proc/game_over)
|
||||
RegisterSignal(M, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING), .proc/game_over)
|
||||
RegisterSignal(M, COMSIG_MOB_GHOSTIZE, .proc/be_a_quitter)
|
||||
RegisterSignal(M, COMSIG_MOB_KEY_CHANGE, .proc/pass_me_the_remote)
|
||||
RegisterSignal(current_mind, COMSIG_MIND_TRANSFER, .proc/pass_me_the_remote)
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
/datum/component/virtual_reality/UnregisterFromParent()
|
||||
quit_action.Remove(parent)
|
||||
UnregisterSignal(parent, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETED, COMSIG_MOB_KEY_CHANGE, COMSIG_MOB_GHOSTIZE))
|
||||
UnregisterSignal(parent, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING, COMSIG_MOB_KEY_CHANGE, COMSIG_MOB_GHOSTIZE))
|
||||
UnregisterSignal(current_mind, COMSIG_MIND_TRANSFER)
|
||||
UnregisterSignal(quit_action, COMSIG_ACTION_TRIGGER)
|
||||
current_mind = null
|
||||
|
||||
@@ -174,3 +174,13 @@
|
||||
/datum/dog_fashion/back/deathsquad
|
||||
name = "Trooper REAL_NAME"
|
||||
desc = "That's not red paint. That's real corgi blood."
|
||||
|
||||
/datum/dog_fashion/head/colour
|
||||
name = "Stylish REAL_NAME"
|
||||
desc = "From the tips of their paws to the top of their head, they look like a made bed."
|
||||
emote_see = list("tries to tap dances.","looks sadly at others outfits...","barks at bad fashion!")
|
||||
|
||||
/datum/dog_fashion/head/telegram
|
||||
name = "Messenger REAL_NAME"
|
||||
desc = "Dont shoot the messenger..."
|
||||
emote_see = list("licks an envelope.","looks ready to set off to send a letter...","works on barking!")
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/datum/element
|
||||
var/element_flags = NONE
|
||||
/**
|
||||
* The index of the first attach argument to consider for duplicate elements
|
||||
* Is only used when flags contains ELEMENT_BESPOKE
|
||||
* This is infinity so you must explicitly set this
|
||||
*/
|
||||
var/id_arg_index = INFINITY
|
||||
|
||||
/datum/element/proc/Attach(datum/target)
|
||||
if(type == /datum/element)
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
if(element_flags & ELEMENT_DETACH)
|
||||
RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach)
|
||||
|
||||
/datum/element/proc/Detach(datum/source, force)
|
||||
UnregisterSignal(source, COMSIG_PARENT_QDELETING)
|
||||
|
||||
/datum/element/Destroy(force)
|
||||
if(!force)
|
||||
return QDEL_HINT_LETMELIVE
|
||||
SSdcs.elements_by_type -= type
|
||||
return ..()
|
||||
|
||||
//DATUM PROCS
|
||||
|
||||
/datum/proc/AddElement(eletype, ...)
|
||||
var/datum/element/ele = SSdcs.GetElement(arglist(args))
|
||||
args[1] = src
|
||||
if(ele.Attach(arglist(args)) == ELEMENT_INCOMPATIBLE)
|
||||
CRASH("Incompatible [eletype] assigned to a [type]! args: [json_encode(args)]")
|
||||
|
||||
/**
|
||||
* Finds the singleton for the element type given and detaches it from src
|
||||
* You only need additional arguments beyond the type if you're using ELEMENT_BESPOKE
|
||||
*/
|
||||
/datum/proc/RemoveElement(eletype, ...)
|
||||
var/datum/element/ele = SSdcs.GetElement(arglist(args))
|
||||
ele.Detach(src)
|
||||
@@ -1,13 +1,15 @@
|
||||
/datum/component/cleaning
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
/datum/element/cleaning/Attach(datum/target)
|
||||
. = ..()
|
||||
if(!ismovableatom(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/Clean)
|
||||
|
||||
/datum/component/cleaning/Initialize()
|
||||
if(!ismovableatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Clean)
|
||||
/datum/element/cleaning/Detach(datum/target)
|
||||
. = ..()
|
||||
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
/datum/component/cleaning/proc/Clean()
|
||||
var/atom/movable/AM = parent
|
||||
/datum/element/cleaning/proc/Clean(datum/source)
|
||||
var/atom/movable/AM = source
|
||||
var/turf/T = AM.loc
|
||||
SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
|
||||
for(var/A in T)
|
||||
@@ -43,4 +45,4 @@
|
||||
cleaned_human.clean_blood()
|
||||
cleaned_human.wash_cream()
|
||||
cleaned_human.regenerate_icons()
|
||||
to_chat(cleaned_human, "<span class='danger'>[src] cleans your face!</span>")
|
||||
to_chat(cleaned_human, "<span class='danger'>[src] cleans your face!</span>")
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
/datum/element/earhealing
|
||||
element_flags = ELEMENT_DETACH
|
||||
var/list/user_by_item = list()
|
||||
|
||||
/datum/element/earhealing/New()
|
||||
START_PROCESSING(SSdcs, src)
|
||||
|
||||
/datum/element/earhealing/Attach(datum/target)
|
||||
. = ..()
|
||||
if(!isitem(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
RegisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED), .proc/equippedChanged)
|
||||
|
||||
/datum/element/earhealing/Detach(datum/target)
|
||||
. = ..()
|
||||
UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
|
||||
user_by_item -= target
|
||||
|
||||
/datum/element/earhealing/proc/equippedChanged(datum/source, mob/living/carbon/user, slot)
|
||||
if(slot == SLOT_EARS && istype(user))
|
||||
user_by_item[source] = user
|
||||
else
|
||||
user_by_item -= source
|
||||
|
||||
/datum/element/earhealing/process()
|
||||
for(var/i in user_by_item)
|
||||
var/mob/living/carbon/user = user_by_item[i]
|
||||
if(HAS_TRAIT(user, TRAIT_DEAF))
|
||||
continue
|
||||
var/obj/item/organ/ears/ears = user.getorganslot(ORGAN_SLOT_EARS)
|
||||
if(!ears)
|
||||
continue
|
||||
ears.deaf = max(ears.deaf - 0.25, (ears.damage < ears.maxHealth ? 0 : 1)) // Do not clear deafness if our ears are too damaged
|
||||
ears.damage = max(ears.damage - 0.025, 0)
|
||||
CHECK_TICK
|
||||
@@ -1,6 +1,3 @@
|
||||
#define EMOTE_VISIBLE 1
|
||||
#define EMOTE_AUDIBLE 2
|
||||
|
||||
/datum/emote
|
||||
var/key = "" //What calls the emote
|
||||
var/key_third_person = "" //This will also call the emote
|
||||
|
||||
@@ -198,7 +198,7 @@ GLOBAL_LIST_EMPTY(explosions)
|
||||
var/list/items = list()
|
||||
for(var/I in T)
|
||||
var/atom/A = I
|
||||
if (!A.prevent_content_explosion()) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
|
||||
if (!(A.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
|
||||
items += A.GetAllContents()
|
||||
for(var/O in items)
|
||||
var/atom/A = O
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
var/restraining = 0 //used in cqc's disarm_act to check if the disarmed is being restrained and so whether they should be put in a chokehold or not
|
||||
var/help_verb
|
||||
var/no_guns = FALSE
|
||||
var/pacifism_check = TRUE //are the martial arts combos/attacks unable to be used by pacifist.
|
||||
var/allow_temp_override = TRUE //if this martial art can be overridden by temporary martial arts
|
||||
|
||||
/datum/martial_art/proc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/datum/martial_art/boxing
|
||||
name = "Boxing"
|
||||
id = MARTIALART_BOXING
|
||||
pacifism_check = FALSE //Let's pretend pacifists can boxe the heck out of other people, it only deals stamina damage right now.
|
||||
|
||||
/datum/martial_art/boxing/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
to_chat(A, "<span class='warning'>Can't disarm while boxing!</span>")
|
||||
@@ -16,14 +17,15 @@
|
||||
|
||||
var/atk_verb = pick("left hook","right hook","straight punch")
|
||||
|
||||
var/damage = rand(5, 8) + A.dna.species.punchdamagelow
|
||||
if(!damage)
|
||||
var/damage = rand(10, 13)
|
||||
var/extra_damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh)
|
||||
if(extra_damage == A.dna.species.punchdamagelow)
|
||||
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
|
||||
D.visible_message("<span class='warning'>[A] has attempted to [atk_verb] [D]!</span>", \
|
||||
"<span class='userdanger'>[A] has attempted to [atk_verb] [D]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
log_combat(A, D, "attempted to hit", atk_verb)
|
||||
return 0
|
||||
|
||||
return TRUE
|
||||
damage += extra_damage
|
||||
|
||||
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
|
||||
var/armor_block = D.run_armor_check(affecting, "melee")
|
||||
|
||||
@@ -124,6 +124,8 @@
|
||||
add_to_streak("G",D)
|
||||
if(check_streak(A,D))
|
||||
return TRUE
|
||||
if(A == D) // no self grab.
|
||||
return FALSE
|
||||
if(A.grab_state >= GRAB_AGGRESSIVE)
|
||||
D.grabbedby(A, 1)
|
||||
else
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
owner.visible_message("<span class='danger'>[owner] assumes a neutral stance.</span>", "<b><i>Your next attack is cleared.</i></b>")
|
||||
H.mind.martial_art.streak = ""
|
||||
else
|
||||
if(HAS_TRAIT(H, TRAIT_PACIFISM))
|
||||
to_chat(H, "<span class='warning'>You don't want to harm other people!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[owner] assumes the Neck Chop stance!</span>", "<b><i>Your next attack will be a Neck Chop.</i></b>")
|
||||
H.mind.martial_art.streak = "neck_chop"
|
||||
|
||||
@@ -36,6 +39,9 @@
|
||||
owner.visible_message("<span class='danger'>[owner] assumes a neutral stance.</span>", "<b><i>Your next attack is cleared.</i></b>")
|
||||
H.mind.martial_art.streak = ""
|
||||
else
|
||||
if(HAS_TRAIT(H, TRAIT_PACIFISM))
|
||||
to_chat(H, "<span class='warning'>You don't want to harm other people!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[owner] assumes the Leg Sweep stance!</span>", "<b><i>Your next attack will be a Leg Sweep.</i></b>")
|
||||
H.mind.martial_art.streak = "leg_sweep"
|
||||
|
||||
@@ -53,6 +59,9 @@
|
||||
owner.visible_message("<span class='danger'>[owner] assumes a neutral stance.</span>", "<b><i>Your next attack is cleared.</i></b>")
|
||||
H.mind.martial_art.streak = ""
|
||||
else
|
||||
if(HAS_TRAIT(H, TRAIT_PACIFISM))
|
||||
to_chat(H, "<span class='warning'>You don't want to harm other people!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[owner] assumes the Lung Punch stance!</span>", "<b><i>Your next attack will be a Lung Punch.</i></b>")
|
||||
H.mind.martial_art.streak = "quick_choke"//internal name for lung punch
|
||||
|
||||
@@ -145,8 +154,6 @@
|
||||
return 1
|
||||
|
||||
/datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
|
||||
if(check_streak(A,D))
|
||||
return 1
|
||||
var/obj/item/I = null
|
||||
if(prob(60))
|
||||
I = D.get_active_held_item()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/datum/martial_art/psychotic_brawling
|
||||
name = "Psychotic Brawling"
|
||||
id = MARTIALART_PSYCHOBRAWL
|
||||
pacifism_check = FALSE //Quite uncontrollable and unpredictable, people will still end up harming others with it.
|
||||
|
||||
/datum/martial_art/psychotic_brawling/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
return psycho_attack(A,D)
|
||||
|
||||
@@ -105,6 +105,8 @@
|
||||
add_to_streak("G",D)
|
||||
if(check_streak(A,D))
|
||||
return 1
|
||||
if(A == D) //no self grab stun
|
||||
return FALSE
|
||||
if(A.grab_state >= GRAB_AGGRESSIVE)
|
||||
D.grabbedby(A, 1)
|
||||
else
|
||||
|
||||
@@ -49,6 +49,9 @@
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>")
|
||||
return
|
||||
if(HAS_TRAIT(owner, TRAIT_PACIFISM))
|
||||
to_chat(owner, "<span class='warning'>You are too HIPPIE to WRESTLE other living beings!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[owner] prepares to BODY SLAM!</span>", "<b><i>Your next attack will be a BODY SLAM.</i></b>")
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.mind.martial_art.streak = "slam"
|
||||
@@ -61,6 +64,9 @@
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>")
|
||||
return
|
||||
if(HAS_TRAIT(owner, TRAIT_PACIFISM))
|
||||
to_chat(owner, "<span class='warning'>You are too HIPPIE to WRESTLE other living beings!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[owner] prepares to THROW!</span>", "<b><i>Your next attack will be a THROW.</i></b>")
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.mind.martial_art.streak = "throw"
|
||||
@@ -73,6 +79,9 @@
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>")
|
||||
return
|
||||
if(HAS_TRAIT(owner, TRAIT_PACIFISM))
|
||||
to_chat(owner, "<span class='warning'>You are too HIPPIE to WRESTLE other living beings!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[owner] prepares to KICK!</span>", "<b><i>Your next attack will be a KICK.</i></b>")
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.mind.martial_art.streak = "kick"
|
||||
@@ -85,6 +94,9 @@
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>")
|
||||
return
|
||||
if(HAS_TRAIT(owner, TRAIT_PACIFISM))
|
||||
to_chat(owner, "<span class='warning'>You are too HIPPIE to WRESTLE other living beings!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[owner] prepares to STRIKE!</span>", "<b><i>Your next attack will be a STRIKE.</i></b>")
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.mind.martial_art.streak = "strike"
|
||||
@@ -97,6 +109,9 @@
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't WRESTLE while you're OUT FOR THE COUNT.</span>")
|
||||
return
|
||||
if(HAS_TRAIT(owner, TRAIT_PACIFISM))
|
||||
to_chat(owner, "<span class='warning'>You are too HIPPIE to WRESTLE other living beings!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[owner] prepares to LEG DROP!</span>", "<b><i>Your next attack will be a LEG DROP.</i></b>")
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.mind.martial_art.streak = "drop"
|
||||
@@ -433,8 +448,8 @@
|
||||
/datum/martial_art/wrestling/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
|
||||
if(check_streak(A,D))
|
||||
return 1
|
||||
if(A.pulling == D)
|
||||
return 1
|
||||
if(A.pulling == D || A == D) // don't stun grab yoursel
|
||||
return FALSE
|
||||
A.start_pulling(D)
|
||||
D.visible_message("<span class='danger'>[A] gets [D] in a cinch!</span>", \
|
||||
"<span class='userdanger'>[A] gets [D] in a cinch!</span>")
|
||||
|
||||
+4
-1
@@ -91,7 +91,10 @@
|
||||
if(current) // remove ourself from our old body's mind variable
|
||||
current.mind = null
|
||||
SStgui.on_transfer(current, new_character)
|
||||
|
||||
if(iscarbon(current))
|
||||
var/mob/living/carbon/C = current
|
||||
if(C.combatmode)
|
||||
C.toggle_combat_mode(TRUE, TRUE)
|
||||
if(!language_holder)
|
||||
var/datum/language_holder/mob_holder = new_character.get_language_holder(shadow = FALSE)
|
||||
language_holder = mob_holder.copy(src)
|
||||
|
||||
@@ -53,3 +53,63 @@
|
||||
mood_change = -20
|
||||
timeout = 300
|
||||
//special_screen_obj = "mood_happiness_bad" Originally in tg
|
||||
|
||||
/datum/mood_event/eigenstate
|
||||
mood_change = -3
|
||||
description = "<span class='warning'>Where the hell am I? Is this an alternative dimension ?</span>\n"
|
||||
|
||||
/datum/mood_event/enthrall
|
||||
mood_change = 5
|
||||
|
||||
/datum/mood_event/enthrall/add_effects(message)
|
||||
description = "<span class='nicegreen'>[message]</span>\n"
|
||||
|
||||
/datum/mood_event/enthrallpraise
|
||||
mood_change = 10
|
||||
timeout = 1 MINUTES
|
||||
|
||||
/datum/mood_event/enthrallpraise/add_effects(message)
|
||||
description = "<span class='nicegreen'>[message]</span>\n"
|
||||
|
||||
/datum/mood_event/enthrallscold
|
||||
mood_change = -10
|
||||
timeout = 1 MINUTES
|
||||
|
||||
/datum/mood_event/enthrallscold/add_effects(message)
|
||||
description = "<span class='warning'>[message]</span>\n"//aaa I'm not kinky enough for this
|
||||
|
||||
/datum/mood_event/enthrallmissing1
|
||||
mood_change = -5
|
||||
|
||||
/datum/mood_event/enthrallmissing1/add_effects(message)
|
||||
description = "<span class='warning'>[message]</span>\n"
|
||||
|
||||
/datum/mood_event/enthrallmissing2
|
||||
mood_change = -10
|
||||
|
||||
/datum/mood_event/enthrallmissing2/add_effects(message)
|
||||
description = "<span class='warning'>[message]</span>\n"
|
||||
|
||||
/datum/mood_event/enthrallmissing3
|
||||
mood_change = -15
|
||||
|
||||
/datum/mood_event/enthrallmissing3/add_effects(message)
|
||||
description = "<span class='warning'>[message]</span>\n"
|
||||
|
||||
/datum/mood_event/enthrallmissing4
|
||||
mood_change = -25
|
||||
|
||||
/datum/mood_event/enthrallmissing4/add_effects(message)
|
||||
description = "<span class='warning'>[message]</span>\n"
|
||||
|
||||
/datum/mood_event/InLove
|
||||
mood_change = 10
|
||||
|
||||
/datum/mood_event/InLove/add_effects(message)
|
||||
description = "<span class='nicegreen'>[message]</span>\n"
|
||||
|
||||
/datum/mood_event/MissingLove
|
||||
mood_change = -10
|
||||
|
||||
/datum/mood_event/MissingLove/add_effects(message)
|
||||
description = "<span class='warning'>[message]</span>\n"
|
||||
|
||||
@@ -176,3 +176,25 @@
|
||||
|
||||
/datum/mood_event/revenant_blight/add_effects()
|
||||
description = "<span class='umbra'>Just give up, [pick("no one will miss you", "there is nothing you can do to help", "even a clown would be more useful than you", "does it even matter in the end?")]...</span>\n"
|
||||
|
||||
/datum/mood_event/plushjack
|
||||
description = "<span class='warning'>I have butchered a plush recently.</span>\n"
|
||||
mood_change = -1
|
||||
timeout = 2 MINUTES
|
||||
|
||||
/datum/mood_event/plush_nostuffing
|
||||
description = "<span class='warning'>A plush I tried to pet had no stuffing...</span>\n"
|
||||
mood_change = -1
|
||||
timeout = 2 MINUTES
|
||||
|
||||
//Cursed stuff below
|
||||
|
||||
/datum/mood_event/emptypred
|
||||
description = "<span class='nicegreen'>I had to let someone out.</span>\n"
|
||||
mood_change = -2
|
||||
timeout = 1 MINUTES
|
||||
|
||||
/datum/mood_event/emptyprey
|
||||
description = "<span class='nicegreen'>It feels quite cold out here.</span>\n"
|
||||
mood_change = -2
|
||||
timeout = 1 MINUTES
|
||||
|
||||
@@ -113,3 +113,38 @@
|
||||
|
||||
/datum/mood_event/happy_empath/add_effects(var/mob/happytarget)
|
||||
description = "<span class='nicegreen'>[happytarget.name]'s happiness is infectious!</span>\n"
|
||||
|
||||
/datum/mood_event/headpat
|
||||
description = "<span class='nicegreen'>Headpats are nice.</span>\n"
|
||||
mood_change = 2
|
||||
timeout = 2 MINUTES
|
||||
|
||||
/datum/mood_event/hugbox
|
||||
description = "<span class='nicegreen'>I hugged a box of hugs recently.</span>\n"
|
||||
mood_change = 1
|
||||
timeout = 2 MINUTES
|
||||
|
||||
/datum/mood_event/plushpet
|
||||
description = "<span class='nicegreen'>I pet a plush recently.</span>\n"
|
||||
mood_change = 1
|
||||
timeout = 3000
|
||||
|
||||
/datum/mood_event/plushplay
|
||||
description = "<span class='nicegreen'>I've played with plushes recently.</span>\n"
|
||||
mood_change = 3
|
||||
timeout = 3000
|
||||
|
||||
//Cursed stuff below.
|
||||
|
||||
/datum/mood_event/orgasm
|
||||
description = "<span class='userlove'>I came!</span>\n" //funny meme haha
|
||||
mood_change = 3
|
||||
timeout = 100 SECONDS
|
||||
|
||||
/datum/mood_event/fedpred
|
||||
description = "<span class='nicegreen'>I've devoured someone!</span>\n"
|
||||
mood_change = 3
|
||||
|
||||
/datum/mood_event/fedprey
|
||||
description = "<span class='nicegreen'>It feels quite cozy in here.</span>\n"
|
||||
mood_change = 3
|
||||
|
||||
@@ -28,16 +28,16 @@
|
||||
var/can_be_admin_equipped = TRUE // Set to FALSE if your outfit requires runtime parameters
|
||||
var/list/chameleon_extras //extra types for chameleon outfit changes, mostly guns
|
||||
|
||||
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
|
||||
//to be overridden for customization depending on client prefs,species etc
|
||||
return
|
||||
|
||||
/datum/outfit/proc/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
/datum/outfit/proc/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
|
||||
//to be overridden for toggling internals, id binding, access etc
|
||||
return
|
||||
|
||||
/datum/outfit/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
pre_equip(H, visualsOnly)
|
||||
/datum/outfit/proc/equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
|
||||
pre_equip(H, visualsOnly, preference_source)
|
||||
|
||||
//Start with uniform,suit,backpack for additional slots
|
||||
if(uniform)
|
||||
@@ -103,7 +103,7 @@
|
||||
var/obj/item/clothing/suit/space/hardsuit/HS = H.wear_suit
|
||||
HS.ToggleHelmet()
|
||||
|
||||
post_equip(H, visualsOnly)
|
||||
post_equip(H, visualsOnly, preference_source)
|
||||
|
||||
if(!visualsOnly)
|
||||
apply_fingerprints(H)
|
||||
|
||||
@@ -541,6 +541,38 @@
|
||||
icon_state = "ichorial_stain"
|
||||
alerttooltipstyle = "clockcult"
|
||||
|
||||
|
||||
//GOLEM GANG
|
||||
|
||||
/datum/status_effect/strandling //get it, strand as in durathread strand + strangling = strandling hahahahahahahahahahhahahaha i want to die
|
||||
id = "strandling"
|
||||
status_type = STATUS_EFFECT_UNIQUE
|
||||
alert_type = /obj/screen/alert/status_effect/strandling
|
||||
|
||||
/datum/status_effect/strandling/on_apply()
|
||||
ADD_TRAIT(owner, TRAIT_MAGIC_CHOKE, "dumbmoron")
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/strandling/on_remove()
|
||||
REMOVE_TRAIT(owner, TRAIT_MAGIC_CHOKE, "dumbmoron")
|
||||
return ..()
|
||||
|
||||
/obj/screen/alert/status_effect/strandling
|
||||
name = "Choking strand"
|
||||
desc = "A magical strand of Durathread is wrapped around your neck, preventing you from breathing! Click this icon to remove the strand."
|
||||
icon_state = "his_grace"
|
||||
alerttooltipstyle = "hisgrace"
|
||||
|
||||
/obj/screen/alert/status_effect/strandling/Click(location, control, params)
|
||||
. = ..()
|
||||
to_chat(mob_viewer, "<span class='notice'>You attempt to remove the durathread strand from around your neck.</span>")
|
||||
if(do_after(mob_viewer, 35, null, mob_viewer))
|
||||
if(isliving(mob_viewer))
|
||||
var/mob/living/L = mob_viewer
|
||||
to_chat(mob_viewer, "<span class='notice'>You succesfuly remove the durathread strand.</span>")
|
||||
L.remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
|
||||
|
||||
|
||||
datum/status_effect/pacify
|
||||
id = "pacify"
|
||||
status_type = STATUS_EFFECT_REPLACE
|
||||
@@ -567,8 +599,7 @@ datum/status_effect/pacify
|
||||
tick_interval = 10
|
||||
examine_text = "<span class='warning'>SUBJECTPRONOUN seems slow and unfocused.</span>"
|
||||
var/stun = TRUE
|
||||
var/triggered = FALSE
|
||||
alert_type = null
|
||||
alert_type = /obj/screen/alert/status_effect/trance
|
||||
|
||||
/obj/screen/alert/status_effect/trance
|
||||
name = "Trance"
|
||||
@@ -576,17 +607,6 @@ datum/status_effect/pacify
|
||||
icon_state = "high"
|
||||
|
||||
/datum/status_effect/trance/tick()
|
||||
if(HAS_TRAIT(owner, "hypnotherapy"))
|
||||
if(triggered == TRUE)
|
||||
UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/hypnotize)
|
||||
ADD_TRAIT(owner, TRAIT_MUTE, "trance")
|
||||
if(!owner.has_quirk(/datum/quirk/monochromatic))
|
||||
owner.add_client_colour(/datum/client_colour/monochrome)
|
||||
to_chat(owner, "<span class='warning'>[pick("You feel your thoughts slow down...", "You suddenly feel extremely dizzy...", "You feel like you're in the middle of a dream...","You feel incredibly relaxed...")]</span>")
|
||||
triggered = FALSE
|
||||
else
|
||||
return
|
||||
if(stun)
|
||||
owner.Stun(60, TRUE, TRUE)
|
||||
owner.dizziness = 20
|
||||
@@ -594,47 +614,88 @@ datum/status_effect/pacify
|
||||
/datum/status_effect/trance/on_apply()
|
||||
if(!iscarbon(owner))
|
||||
return FALSE
|
||||
if(HAS_TRAIT(owner, "hypnotherapy"))
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/listen)
|
||||
return TRUE
|
||||
alert_type = /obj/screen/alert/status_effect/trance
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/hypnotize)
|
||||
ADD_TRAIT(owner, TRAIT_MUTE, "trance")
|
||||
if(!owner.has_quirk(/datum/quirk/monochromatic))
|
||||
owner.add_client_colour(/datum/client_colour/monochrome)
|
||||
owner.add_client_colour(/datum/client_colour/monochrome/trance)
|
||||
owner.visible_message("[stun ? "<span class='warning'>[owner] stands still as [owner.p_their()] eyes seem to focus on a distant point.</span>" : ""]", \
|
||||
"<span class='warning'>[pick("You feel your thoughts slow down...", "You suddenly feel extremely dizzy...", "You feel like you're in the middle of a dream...","You feel incredibly relaxed...")]</span>")
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/trance/on_creation(mob/living/new_owner, _duration, _stun = TRUE, source_quirk = FALSE)//hypnoquirk makes no visible message, prevents self antag messages, and places phrase below objectives.
|
||||
/datum/status_effect/trance/on_creation(mob/living/new_owner, _duration, _stun = TRUE)
|
||||
duration = _duration
|
||||
stun = _stun
|
||||
if(source_quirk == FALSE && HAS_TRAIT(owner, "hypnotherapy"))
|
||||
REMOVE_TRAIT(owner, "hypnotherapy", ROUNDSTART_TRAIT)
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/trance/on_remove()
|
||||
UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
|
||||
REMOVE_TRAIT(owner, TRAIT_MUTE, "trance")
|
||||
owner.dizziness = 0
|
||||
if(!owner.has_quirk(/datum/quirk/monochromatic))
|
||||
owner.remove_client_colour(/datum/client_colour/monochrome)
|
||||
owner.remove_client_colour(/datum/client_colour/monochrome/trance)
|
||||
to_chat(owner, "<span class='warning'>You snap out of your trance!</span>")
|
||||
|
||||
/datum/status_effect/trance/proc/listen(datum/source, message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
to_chat(owner, "<span class='notice'><i>[speaker] accidentally sets off your implanted trigger, sending you into a hypnotic daze!</i></span>")
|
||||
triggered = TRUE
|
||||
|
||||
/datum/status_effect/trance/proc/hypnotize(datum/source, message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
/datum/status_effect/trance/proc/hypnotize(datum/source, list/hearing_args)
|
||||
if(!owner.can_hear())
|
||||
return
|
||||
if(speaker == owner)
|
||||
if(hearing_args[HEARING_SPEAKER] == owner)
|
||||
return
|
||||
var/mob/living/carbon/C = owner
|
||||
C.cure_trauma_type(/datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY) //clear previous hypnosis
|
||||
if(HAS_TRAIT(C, "hypnotherapy"))
|
||||
addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, raw_message, TRUE), 10)
|
||||
else
|
||||
addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, raw_message), 10)
|
||||
addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, hearing_args[HEARING_RAW_MESSAGE]), 10)
|
||||
addtimer(CALLBACK(C, /mob/living.proc/Stun, 60, TRUE, TRUE), 15) //Take some time to think about it
|
||||
qdel(src)
|
||||
|
||||
/datum/status_effect/spasms
|
||||
id = "spasms"
|
||||
status_type = STATUS_EFFECT_MULTIPLE
|
||||
alert_type = null
|
||||
|
||||
/datum/status_effect/spasms/tick()
|
||||
if(prob(15))
|
||||
switch(rand(1,5))
|
||||
if(1)
|
||||
if((!owner.lying && !owner.buckled) && isturf(owner.loc))
|
||||
to_chat(owner, "<span class='warning'>Your leg spasms!</span>")
|
||||
step(owner, pick(GLOB.cardinals))
|
||||
if(2)
|
||||
if(owner.incapacitated())
|
||||
return
|
||||
var/obj/item/I = owner.get_active_held_item()
|
||||
if(I)
|
||||
to_chat(owner, "<span class='warning'>Your fingers spasm!</span>")
|
||||
owner.log_message("used [I] due to a Muscle Spasm", LOG_ATTACK)
|
||||
I.attack_self(owner)
|
||||
if(3)
|
||||
var/prev_intent = owner.a_intent
|
||||
owner.a_intent = INTENT_HARM
|
||||
|
||||
var/range = 1
|
||||
if(istype(owner.get_active_held_item(), /obj/item/gun)) //get targets to shoot at
|
||||
range = 7
|
||||
|
||||
var/list/mob/living/targets = list()
|
||||
for(var/mob/M in oview(owner, range))
|
||||
if(isliving(M))
|
||||
targets += M
|
||||
if(LAZYLEN(targets))
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
owner.log_message(" attacked someone due to a Muscle Spasm", LOG_ATTACK) //the following attack will log itself
|
||||
owner.ClickOn(pick(targets))
|
||||
owner.a_intent = prev_intent
|
||||
if(4)
|
||||
var/prev_intent = owner.a_intent
|
||||
owner.a_intent = INTENT_HARM
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
owner.log_message("attacked [owner.p_them()]self to a Muscle Spasm", LOG_ATTACK)
|
||||
owner.ClickOn(owner)
|
||||
owner.a_intent = prev_intent
|
||||
if(5)
|
||||
if(owner.incapacitated())
|
||||
return
|
||||
var/obj/item/I = owner.get_active_held_item()
|
||||
var/list/turf/targets = list()
|
||||
for(var/turf/T in oview(owner, 3))
|
||||
targets += T
|
||||
if(LAZYLEN(targets) && I)
|
||||
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
|
||||
owner.log_message("threw [I] due to a Muscle Spasm", LOG_ATTACK)
|
||||
owner.throw_item(pick(targets))
|
||||
@@ -69,3 +69,17 @@
|
||||
/datum/status_effect/in_love/tick()
|
||||
if(date)
|
||||
new /obj/effect/temp_visual/love_heart/invisible(get_turf(date.loc), owner)
|
||||
|
||||
/datum/status_effect/throat_soothed
|
||||
id = "throat_soothed"
|
||||
duration = 60 SECONDS
|
||||
status_type = STATUS_EFFECT_REFRESH
|
||||
alert_type = null
|
||||
|
||||
/datum/status_effect/throat_soothed/on_apply()
|
||||
. = ..()
|
||||
ADD_TRAIT(owner, TRAIT_SOOTHED_THROAT, "[STATUS_EFFECT_TRAIT]_[id]")
|
||||
|
||||
/datum/status_effect/throat_soothed/on_remove()
|
||||
. = ..()
|
||||
REMOVE_TRAIT(owner, TRAIT_SOOTHED_THROAT, "[STATUS_EFFECT_TRAIT]_[id]")
|
||||
@@ -64,6 +64,12 @@
|
||||
owner = null
|
||||
qdel(src)
|
||||
|
||||
/datum/status_effect/proc/refresh()
|
||||
var/original_duration = initial(duration)
|
||||
if(original_duration == -1)
|
||||
return
|
||||
duration = world.time + original_duration
|
||||
|
||||
//clickdelay/nextmove modifiers!
|
||||
/datum/status_effect/proc/nextmove_modifier()
|
||||
return 1
|
||||
@@ -92,6 +98,9 @@
|
||||
if(S.id == initial(S1.id) && S.status_type)
|
||||
if(S.status_type == STATUS_EFFECT_REPLACE)
|
||||
S.be_replaced()
|
||||
else if(S.status_type == STATUS_EFFECT_REFRESH)
|
||||
S.refresh()
|
||||
return
|
||||
else
|
||||
return
|
||||
var/list/arguments = args.Copy()
|
||||
|
||||
Reference in New Issue
Block a user