Files
Paradise/code/modules/mob/mob_helpers.dm
Fox McCloud f81a6c2157 Merge pull request #5137 from Kyep/ssd_alert
Makes looting/attacking SSD players more obvious
2016-07-22 10:01:10 -04:00

538 lines
17 KiB
Plaintext

/proc/issmall(A)
if(A && istype(A, /mob/living/carbon/human))
var/mob/living/carbon/human/H = A
if(H.species && H.species.is_small)
return 1
return 0
/proc/ispet(A)
if(istype(A, /mob/living/simple_animal))
var/mob/living/simple_animal/SA = A
if(SA.can_collar)
return 1
return 0
/mob/proc/isSynthetic()
return 0
/mob/living/carbon/human/isSynthetic()
// If they are 100% robotic, they count as synthetic.
for(var/obj/item/organ/external/E in organs)
if(!(E.status & ORGAN_ROBOT))
return 0
return 1
/proc/isloyal(A) //Checks to see if the person contains a mindshield implant, then checks that the implant is actually inside of them
for(var/obj/item/weapon/implant/loyalty/L in A)
if(L && L.implanted)
return 1
return 0
/proc/ismindslave(A) //Checks to see if the person contains a mindslave implant, then checks that the implant is actually inside of them
for(var/obj/item/weapon/implant/traitor/T in A)
if(T && T.implanted)
return 1
return 0
proc/isSSD(mob/M)
return istype(M) && M.player_logged
proc/isAntag(A)
if(istype(A, /mob/living/carbon))
var/mob/living/carbon/C = A
if(C.mind && C.mind.special_role)
return 1
return 0
proc/isNonCrewAntag(A)
if(!isAntag(A))
return 0
var/mob/living/carbon/C = A
var/special_role = C.mind.special_role
var/list/crew_roles = list("traitor", "Changeling", "Vampire", "Cultist", "Head Revolutionary", "Revolutionary", "malfunctioning AI", "Shadowling", "loyalist", "mutineer", "Response Team")
if((special_role in crew_roles))
return 0
return 1
proc/iscuffed(A)
if(istype(A, /mob/living/carbon))
var/mob/living/carbon/C = A
if(C.handcuffed)
return 1
return 0
proc/isdeaf(A)
if(istype(A, /mob))
var/mob/M = A
return (M.disabilities & DEAF) || M.ear_deaf
return 0
proc/hassensorlevel(A, var/level)
var/mob/living/carbon/human/H = A
if(istype(H) && istype(H.w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = H.w_uniform
return U.sensor_mode >= level
return 0
proc/getsensorlevel(A)
var/mob/living/carbon/human/H = A
if(istype(H) && istype(H.w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/U = H.w_uniform
return U.sensor_mode
return SUIT_SENSOR_OFF
/proc/check_zone(zone)
if(!zone) return "chest"
switch(zone)
if("eyes")
zone = "head"
if("mouth")
zone = "head"
return zone
// Returns zone with a certain probability.
// If the probability misses, returns "chest" instead.
// If "chest" was passed in as zone, then on a "miss" will return "head", "l_arm", or "r_arm"
// Do not use this if someone is intentionally trying to hit a specific body part.
// Use get_zone_with_miss_chance() for that.
/proc/ran_zone(zone, probability = 80)
zone = check_zone(zone)
if(prob(probability))
return zone
var/t = rand(1, 18) // randomly pick a different zone, or maybe the same one
switch(t)
if(1) return "head"
if(2) return "chest"
if(3 to 4) return "l_arm"
if(5 to 6) return "l_hand"
if(7 to 8) return "r_arm"
if(9 to 10) return "r_hand"
if(11 to 12) return "l_leg"
if(13 to 14) return "l_foot"
if(15 to 16) return "r_leg"
if(17 to 18) return "r_foot"
return zone
/proc/above_neck(zone)
var/list/zones = list("head", "mouth", "eyes")
if(zones.Find(zone))
return 1
else
return 0
/proc/stars(n, pr)
if(pr == null)
pr = 25
if(pr <= 0)
return null
else
if(pr >= 100)
return n
var/te = n
var/t = ""
n = length(n)
var/p = null
p = 1
while(p <= n)
if((copytext(te, p, p + 1) == " " || prob(pr)))
t = text("[][]", t, copytext(te, p, p + 1))
else
t = text("[]*", t)
p++
return t
proc/slur(phrase, var/list/slurletters = ("'"))//use a different list as an input if you want to make robots slur with $#@%! characters
phrase = html_decode(phrase)
var/leng=lentext(phrase)
var/counter=lentext(phrase)
var/newphrase=""
var/newletter=""
while(counter>=1)
newletter=copytext(phrase,(leng-counter)+1,(leng-counter)+2)
if(rand(1,3)==3)
if(lowertext(newletter)=="o") newletter="u"
if(lowertext(newletter)=="s") newletter="ch"
if(lowertext(newletter)=="a") newletter="ah"
if(lowertext(newletter)=="c") newletter="k"
switch(rand(1,15))
if(1,3,5,8) newletter="[lowertext(newletter)]"
if(2,4,6,15) newletter="[uppertext(newletter)]"
if(7) newletter+=pick(slurletters)
//if(9,10) newletter="<b>[newletter]</b>"
//if(11,12) newletter="<big>[newletter]</big>"
//if(13) newletter="<small>[newletter]</small>"
newphrase+="[newletter]"
counter-=1
return newphrase
/proc/stutter(n)
var/te = html_decode(n)
var/t = ""//placed before the message. Not really sure what it's for.
n = length(n)//length of the entire word
var/p = null
p = 1//1 is the start of any word
while(p <= n)//while P, which starts at 1 is less or equal to N which is the length.
var/n_letter = copytext(te, p, p + 1)//copies text from a certain distance. In this case, only one letter at a time.
if(prob(80) && (ckey(n_letter) in list("b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z")))
if(prob(10))
n_letter = text("[n_letter]-[n_letter]-[n_letter]-[n_letter]")//replaces the current letter with this instead.
else
if(prob(20))
n_letter = text("[n_letter]-[n_letter]-[n_letter]")
else
if(prob(5))
n_letter = null
else
n_letter = text("[n_letter]-[n_letter]")
t = text("[t][n_letter]")//since the above is ran through for each letter, the text just adds up back to the original word.
p++//for each letter p is increased to find where the next letter will be.
return sanitize(copytext(t,1,MAX_MESSAGE_LEN))
/proc/robostutter(n) //for robutts
var/te = html_decode(n)
var/t = ""//placed before the message. Not really sure what it's for.
n = length(n)//length of the entire word
var/p = null
p = 1//1 is the start of any word
while(p <= n)//while P, which starts at 1 is less or equal to N which is the length.
var/robotletter = pick("@", "!", "#", "$", "%", "&", "?") //for beep boop
var/n_letter = copytext(te, p, p + 1)//copies text from a certain distance. In this case, only one letter at a time.
if(prob(80) && (ckey(n_letter) in list("b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z")))
if(prob(10))
n_letter = text("[n_letter]-[robotletter]-[n_letter]-[n_letter]")//replaces the current letter with this instead.
else
if(prob(20))
n_letter = text("[n_letter]-[robotletter]-[n_letter]")
else
if(prob(5))
n_letter = robotletter
else
n_letter = text("[n_letter]-[n_letter]")
t = text("[t][n_letter]")//since the above is ran through for each letter, the text just adds up back to the original word.
p++//for each letter p is increased to find where the next letter will be.
return sanitize(copytext(t,1,MAX_MESSAGE_LEN))
proc/Gibberish(t, p)//t is the inputted message, and any value higher than 70 for p will cause letters to be replaced instead of added
/* Turn text into complete gibberish! */
var/returntext = ""
for(var/i = 1, i <= length(t), i++)
var/letter = copytext(t, i, i+1)
if(prob(50))
if(p >= 70)
letter = ""
for(var/j = 1, j <= rand(0, 2), j++)
letter += pick("#","@","*","&","%","$","/", "<", ">", ";","*","*","*","*","*","*","*")
returntext += letter
return returntext
proc/muffledspeech(phrase)
phrase = html_decode(phrase)
var/leng=lentext(phrase)
var/counter=lentext(phrase)
var/newphrase=""
var/newletter=""
while(counter>=1)
newletter=copytext(phrase,(leng-counter)+1,(leng-counter)+2)
if(newletter in list(" ", "!", "?", ".", ","))
//do nothing
else if(lowertext(newletter) in list("a", "e", "i", "o", "u", "y"))
newletter = "ph"
else
newletter = "m"
newphrase+="[newletter]"
counter-=1
return newphrase
/proc/shake_camera(mob/M, duration, strength=1)
if(!M || !M.client || M.shakecamera)
return
M.shakecamera = 1
spawn(1)
var/atom/oldeye=M.client.eye
var/aiEyeFlag = 0
if(istype(oldeye, /mob/camera/aiEye))
aiEyeFlag = 1
var/x
for(x=0; x<duration, x++)
if(aiEyeFlag)
M.client.eye = locate(dd_range(1,oldeye.loc.x+rand(-strength,strength),world.maxx),dd_range(1,oldeye.loc.y+rand(-strength,strength),world.maxy),oldeye.loc.z)
else
M.client.eye = locate(dd_range(1,M.loc.x+rand(-strength,strength),world.maxx),dd_range(1,M.loc.y+rand(-strength,strength),world.maxy),M.loc.z)
sleep(1)
M.client.eye=oldeye
M.shakecamera = 0
/proc/findname(msg)
for(var/mob/M in mob_list)
if(M.real_name == text("[msg]"))
return 1
return 0
/mob/proc/abiotic(var/full_body = 0)
if(full_body && ((src.l_hand && !(src.l_hand.flags & ABSTRACT)) || (src.r_hand && !(src.r_hand.flags & ABSTRACT)) || (src.back || src.wear_mask)))
return 1
if((src.l_hand && !(src.l_hand.flags & ABSTRACT)) || (src.r_hand && !(src.r_hand.flags & ABSTRACT)))
return 1
return 0
//converts intent-strings into numbers and back
var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM)
/proc/intent_numeric(argument)
if(istext(argument))
switch(argument)
if(I_HELP) return 0
if(I_DISARM) return 1
if(I_GRAB) return 2
else return 3
else
switch(argument)
if(0) return I_HELP
if(1) return I_DISARM
if(2) return I_GRAB
else return I_HARM
//change a mob's act-intent. Input the intent as a string such as "help" or use "right"/"left
/mob/verb/a_intent_change(input as text)
set name = "a-intent"
set hidden = 1
if(ishuman(src) || isalienadult(src) || isbrain(src))
switch(input)
if(I_HELP,I_DISARM,I_GRAB,I_HARM)
a_intent = input
if("right")
a_intent = intent_numeric((intent_numeric(a_intent)+1) % 4)
if("left")
a_intent = intent_numeric((intent_numeric(a_intent)+3) % 4)
if(hud_used && hud_used.action_intent)
hud_used.action_intent.icon_state = "[a_intent]"
else if(isrobot(src) || islarva(src))
switch(input)
if(I_HELP)
a_intent = I_HELP
if(I_HARM)
a_intent = I_HARM
if("right","left")
a_intent = intent_numeric(intent_numeric(a_intent) - 3)
if(hud_used && hud_used.action_intent)
if(a_intent == I_HARM)
hud_used.action_intent.icon_state = "harm"
else
hud_used.action_intent.icon_state = "help"
/mob/living/carbon/verb/mob_sleep()
set name = "Sleep"
set category = "IC"
if(usr.sleeping)
to_chat(usr, "\red You are already sleeping")
return
else
if(alert(src,"You sure you want to sleep for a while?","Sleep","Yes","No") == "Yes")
usr.sleeping = 20 //Short nap
/mob/living/verb/lay_down()
set name = "Rest"
set category = "IC"
resting = !resting
to_chat(src, "\blue You are now [resting ? "resting" : "getting up"]")
/proc/is_blind(A)
if(iscarbon(A))
var/mob/living/carbon/C = A
if(C.disabilities & BLIND || C.blinded)
return 1
return 0
/proc/get_multitool(mob/user as mob)
// Get tool
var/obj/item/device/multitool/P
if(isrobot(user) || ishuman(user))
P = user.get_active_hand()
else if(isAI(user))
var/mob/living/silicon/ai/AI=user
P = AI.aiMulti
if(!istype(P))
return null
return P
/proc/get_both_hands(mob/living/carbon/M)
return list(M.l_hand, M.r_hand)
//Direct dead say used both by emote and say
//It is somewhat messy. I don't know what to do.
//I know you can't see the change, but I rewrote the name code. It is significantly less messy now
/proc/say_dead_direct(var/message, var/mob/subject = null)
var/name
var/keyname
if(subject && subject.client)
var/client/C = subject.client
keyname = (C.holder && C.holder.fakekey) ? C.holder.fakekey : C.key
if(C.mob) //Most of the time this is the dead/observer mob; we can totally use him if there is no better name
var/mindname
var/realname = C.mob.real_name
if(C.mob.mind)
mindname = C.mob.mind.name
if(C.mob.mind.original && C.mob.mind.original.real_name)
realname = C.mob.mind.original.real_name
if(mindname && mindname != realname)
name = "[realname] died as [mindname]"
else
name = realname
for(var/mob/M in player_list)
if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || check_rights(R_ADMIN|R_MOD,0,M)) && (M.client.prefs.toggles & CHAT_DEAD))
var/follow
var/lname
if(subject)
if(subject != M)
follow = "([ghost_follow_link(subject, ghost=M)]) "
if(M.stat != DEAD && check_rights(R_ADMIN|R_MOD,0,M))
follow = "([admin_jump_link(subject, M.client.holder)]) "
var/mob/dead/observer/DM
if(istype(subject, /mob/dead/observer))
DM = subject
if(check_rights(R_ADMIN|R_MOD,0,M)) // What admins see
lname = "[keyname][(DM && DM.anonsay) ? "*" : (DM ? "" : "^")] ([name])"
else
if(DM && DM.anonsay) // If the person is actually observer they have the option to be anonymous
lname = "Ghost of [name]"
else if(DM) // Non-anons
lname = "[keyname] ([name])"
else // Everyone else (dead people who didn't ghost yet, etc.)
lname = name
lname = "<span class='name'>[lname]</span> "
to_chat(M, "<span class='deadsay'>[lname][follow][message]</span>")
/proc/notify_ghosts(var/message, var/ghost_sound = null, var/enter_link = null, var/atom/source = null, var/image/alert_overlay = null, var/attack_not_jump = 0) //Easy notification of ghosts.
for(var/mob/dead/observer/O in player_list)
if(O.client)
to_chat(O, "<span class='ghostalert'>[message][(enter_link) ? " [enter_link]" : ""]<span>")
if(ghost_sound)
O << sound(ghost_sound)
if(source)
var/obj/screen/alert/notify_jump/A = O.throw_alert("\ref[source]_notify_jump", /obj/screen/alert/notify_jump)
if(A)
if(O.client.prefs && O.client.prefs.UI_style)
A.icon = ui_style2icon(O.client.prefs.UI_style)
A.desc = message
A.attack_not_jump = attack_not_jump
A.jump_target = source
if(!alert_overlay)
var/old_layer = source.layer
source.layer = FLOAT_LAYER
A.overlays += source
source.layer = old_layer
else
alert_overlay.layer = FLOAT_LAYER
A.overlays += alert_overlay
/mob/proc/switch_to_camera(var/obj/machinery/camera/C)
if(!C.can_use() || stat || (get_dist(C, src) > 1 || machine != src || blinded || !canmove))
return 0
check_eye(src)
return 1
/mob/proc/rename_character(oldname, newname)
if(!newname)
return 0
real_name = newname
name = newname
if(mind)
mind.name = newname
if(dna)
dna.real_name = real_name
if(oldname)
//update the datacore records! This is goig to be a bit costly.
for(var/list/L in list(data_core.general,data_core.medical,data_core.security,data_core.locked))
for(var/datum/data/record/R in L)
if(R.fields["name"] == oldname)
R.fields["name"] = newname
break
//update our pda and id if we have them on our person
var/list/searching = GetAllContents(searchDepth = 3)
var/search_id = 1
var/search_pda = 1
for(var/A in searching)
if( search_id && istype(A,/obj/item/weapon/card/id) )
var/obj/item/weapon/card/id/ID = A
if(ID.registered_name == oldname)
ID.registered_name = newname
ID.name = "[newname]'s ID Card ([ID.assignment])"
if(!search_pda) break
search_id = 0
else if( search_pda && istype(A,/obj/item/device/pda) )
var/obj/item/device/pda/PDA = A
if(PDA.owner == oldname)
PDA.owner = newname
PDA.name = "PDA-[newname] ([PDA.ownjob])"
if(!search_id) break
search_pda = 0
//Fixes renames not being reflected in objective text
var/list/O = subtypesof(/datum/objective)
var/length
var/pos
for(var/datum/objective/objective in O)
if(objective.target != mind) continue
length = lentext(oldname)
pos = findtextEx(objective.explanation_text, oldname)
objective.explanation_text = copytext(objective.explanation_text, 1, pos)+newname+copytext(objective.explanation_text, pos+length)
return 1
/mob/proc/rename_self(var/role, var/allow_numbers=0)
spawn(0)
var/oldname = real_name
var/time_passed = world.time
var/newname
for(var/i=1,i<=3,i++) //we get 3 attempts to pick a suitable name.
newname = input(src, "You are a [role]. Would you like to change your name to something else? (You have 3 minutes to select a new name.)", "Name Change", oldname) as text
if((world.time - time_passed) > 1800)
alert(src, "Unfortunately, more than 3 minutes have passed for selecting your name. If you are a robot, use the Namepick verb; otherwise, adminhelp.", "Name Change")
return //took too long
newname = reject_bad_name(newname,allow_numbers) //returns null if the name doesn't meet some basic requirements. Tidies up a few other things like bad-characters.
for(var/mob/living/M in player_list)
if(M == src)
continue
if(!newname || M.real_name == newname)
newname = null
break
if(newname)
break //That's a suitable name!
to_chat(src, "Sorry, that [role]-name wasn't appropriate, please try another. It's possibly too long/short, has bad characters or is already taken.")
if(!newname) //we'll stick with the oldname then
return
rename_character(oldname, newname)