mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2025-12-18 14:12:20 +00:00
* Port ParadiseSS13/Paradise#2100 - Saycode refactor * Removed unused old carbon slimes code * Port ParadiseSS13/Paradise#5099 - Saycode part 2 * Ported ParadiseSS13/Paradise#7170's /datum/browser Check Known Languages * Port ParadiseSS13/Paradise#9240 - Get rid of alt_name in favor of GetAltName() * Port ParadiseSS13/Paradise#10330 - You can now use multiple languages in one message * Addressed Atermonera's review. Translators now print the full message if they find any languages within the message that the user doesn't understand, minus languages it cannot translate. Additionally, the combine_message proc has been significantly simplified by eliminating an ugly tree structure with the help of a little helper proc. The removal of the extra span inside each piece doesn't seem to have visually changed the messages in any other way than changing where the wordwrap happens, strangely enough. Must be something in IE's code being picky about invisible elements. On the bright side, it splits *later* than it did before, thus reducing the lines a message will take up by a tiny amount. Also, a bunch of things now have the 'filter_say' class from PolarisSS13/Polaris#6998. Since span classes with no definition are totally valid and just don't do anything, this PR does **not** depend on that PR being merged first. * Always gotta be one
688 lines
20 KiB
Plaintext
688 lines
20 KiB
Plaintext
// fun if you want to typecast humans/monkeys/etc without writing long path-filled lines.
|
|
/proc/isxenomorph(A)
|
|
if(istype(A, /mob/living/carbon/human))
|
|
var/mob/living/carbon/human/H = A
|
|
return istype(H.species, /datum/species/xenos)
|
|
return 0
|
|
|
|
/proc/issmall(A)
|
|
if(A && istype(A, /mob/living))
|
|
var/mob/living/L = A
|
|
return L.mob_size <= MOB_SMALL
|
|
return 0
|
|
|
|
//returns the number of size categories between two mob_sizes, rounded. Positive means A is larger than B
|
|
/proc/mob_size_difference(var/mob_size_A, var/mob_size_B)
|
|
return round(log(2, mob_size_A/mob_size_B), 1)
|
|
|
|
/mob/proc/can_wield_item(obj/item/W)
|
|
if(W.w_class >= ITEMSIZE_LARGE && issmall(src))
|
|
return FALSE //M is too small to wield this
|
|
return TRUE
|
|
|
|
/proc/istiny(A)
|
|
if(A && istype(A, /mob/living))
|
|
var/mob/living/L = A
|
|
return L.mob_size <= MOB_TINY
|
|
return 0
|
|
|
|
|
|
/proc/ismini(A)
|
|
if(A && istype(A, /mob/living))
|
|
var/mob/living/L = A
|
|
return L.mob_size <= MOB_MINISCULE
|
|
return 0
|
|
|
|
/mob/living/silicon/isSynthetic()
|
|
return 1
|
|
|
|
/mob/proc/isMonkey()
|
|
return 0
|
|
|
|
/mob/living/carbon/human/isMonkey()
|
|
return istype(species, /datum/species/monkey)
|
|
|
|
proc/isdeaf(A)
|
|
if(istype(A, /mob))
|
|
var/mob/M = A
|
|
return (M.sdisabilities & DEAF) || M.ear_deaf
|
|
return 0
|
|
|
|
/mob/proc/get_ear_protection()
|
|
return 0
|
|
|
|
/mob/proc/break_cloak()
|
|
return
|
|
|
|
/mob/proc/is_cloaked()
|
|
return FALSE
|
|
|
|
proc/hasorgans(A) // Fucking really??
|
|
return ishuman(A)
|
|
|
|
proc/iscuffed(A)
|
|
if(istype(A, /mob/living/carbon))
|
|
var/mob/living/carbon/C = A
|
|
if(C.handcuffed)
|
|
return 1
|
|
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/is_admin(var/mob/user)
|
|
return check_rights(R_ADMIN|R_EVENT, 0, user) != 0
|
|
|
|
|
|
/proc/hsl2rgb(h, s, l)
|
|
return //TODO: Implement
|
|
|
|
/*
|
|
Miss Chance
|
|
*/
|
|
|
|
/proc/check_zone(zone)
|
|
if(!zone) return BP_TORSO
|
|
switch(zone)
|
|
if(O_EYES)
|
|
zone = BP_HEAD
|
|
if(O_MOUTH)
|
|
zone = BP_HEAD
|
|
return zone
|
|
|
|
// Returns zone with a certain probability. If the probability fails, or no zone is specified, then a random body part is chosen.
|
|
// 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)
|
|
if (zone)
|
|
zone = check_zone(zone)
|
|
if (prob(probability))
|
|
return zone
|
|
|
|
var/ran_zone = zone
|
|
while (ran_zone == zone)
|
|
ran_zone = pick (
|
|
organ_rel_size[BP_HEAD]; BP_HEAD,
|
|
organ_rel_size[BP_TORSO]; BP_TORSO,
|
|
organ_rel_size[BP_GROIN]; BP_GROIN,
|
|
organ_rel_size[BP_L_ARM]; BP_L_ARM,
|
|
organ_rel_size[BP_R_ARM]; BP_R_ARM,
|
|
organ_rel_size[BP_L_LEG]; BP_L_LEG,
|
|
organ_rel_size[BP_R_LEG]; BP_R_LEG,
|
|
organ_rel_size[BP_L_HAND]; BP_L_HAND,
|
|
organ_rel_size[BP_R_HAND]; BP_R_HAND,
|
|
organ_rel_size[BP_L_FOOT]; BP_L_FOOT,
|
|
organ_rel_size[BP_R_FOOT]; BP_R_FOOT,
|
|
)
|
|
|
|
return ran_zone
|
|
|
|
// Emulates targetting a specific body part, and miss chances
|
|
// May return null if missed
|
|
// miss_chance_mod may be negative.
|
|
/proc/get_zone_with_miss_chance(zone, var/mob/target, var/miss_chance_mod = 0, var/ranged_attack=0)
|
|
zone = check_zone(zone)
|
|
|
|
if(!ranged_attack)
|
|
// you cannot miss if your target is prone or restrained
|
|
if(target.buckled || target.lying)
|
|
return zone
|
|
// if your target is being grabbed aggressively by someone you cannot miss either
|
|
for(var/obj/item/weapon/grab/G in target.grabbed_by)
|
|
if(G.state >= GRAB_AGGRESSIVE)
|
|
return zone
|
|
|
|
var/miss_chance = 10
|
|
if (zone in base_miss_chance)
|
|
miss_chance = base_miss_chance[zone]
|
|
if (zone == "eyes" || zone == "mouth")
|
|
miss_chance = base_miss_chance["head"]
|
|
miss_chance = max(miss_chance + miss_chance_mod, 0)
|
|
if(prob(miss_chance))
|
|
if(prob(70))
|
|
return null
|
|
return pick(base_miss_chance)
|
|
return zone
|
|
|
|
|
|
/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
|
|
var/intag = 0
|
|
while(p <= n)
|
|
var/char = copytext(te, p, p + 1)
|
|
if (char == "<") //let's try to not break tags
|
|
intag = !intag
|
|
if (intag || char == " " || prob(pr))
|
|
t = text("[][]", t, char)
|
|
else
|
|
t = text("[]*", t)
|
|
if (char == ">")
|
|
intag = !intag
|
|
p++
|
|
return t
|
|
|
|
/proc/stars_all(list/message_pieces, pr)
|
|
// eugh, we have to clone the list to avoid collateral damage due to the nature of these messages
|
|
. = list()
|
|
for(var/datum/multilingual_say_piece/S in message_pieces)
|
|
. += new /datum/multilingual_say_piece(S.speaking, stars(S.message))
|
|
|
|
proc/slur(phrase)
|
|
phrase = html_decode(phrase)
|
|
var/leng=length(phrase)
|
|
var/counter=length(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+="'"
|
|
//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(t)
|
|
|
|
|
|
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/ninjaspeak(n)
|
|
/*
|
|
The difference with stutter is that this proc can stutter more than 1 letter
|
|
The issue here is that anything that does not have a space is treated as one word (in many instances). For instance, "LOOKING," is a word, including the comma.
|
|
It's fairly easy to fix if dealing with single letters but not so much with compounds of letters./N
|
|
*/
|
|
var/te = html_decode(n)
|
|
var/t = ""
|
|
n = length(n)
|
|
var/p = 1
|
|
while(p <= n)
|
|
var/n_letter
|
|
var/n_mod = rand(1,4)
|
|
if(p+n_mod>n+1)
|
|
n_letter = copytext(te, p, n+1)
|
|
else
|
|
n_letter = copytext(te, p, p+n_mod)
|
|
if (prob(50))
|
|
if (prob(30))
|
|
n_letter = text("[n_letter]-[n_letter]-[n_letter]")
|
|
else
|
|
n_letter = text("[n_letter]-[n_letter]")
|
|
else
|
|
n_letter = text("[n_letter]")
|
|
t = text("[t][n_letter]")
|
|
p=p+n_mod
|
|
return sanitize(t)
|
|
|
|
|
|
/proc/shake_camera(mob/M, duration, strength=1)
|
|
if(!M || !M.client || M.shakecamera || M.stat || isEye(M) || isAI(M))
|
|
return
|
|
M.shakecamera = 1
|
|
spawn(1)
|
|
if(!M.client)
|
|
return
|
|
|
|
var/atom/oldeye=M.client.eye
|
|
var/aiEyeFlag = 0
|
|
if(istype(oldeye, /mob/observer/eye/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)
|
|
return 0
|
|
|
|
//converts intent-strings into numbers and back
|
|
var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT)
|
|
/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_HURT
|
|
|
|
//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(isliving(src) && !isrobot(src))
|
|
switch(input)
|
|
if(I_HELP,I_DISARM,I_GRAB,I_HURT)
|
|
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 = "intent_[a_intent]"
|
|
|
|
else if(isrobot(src))
|
|
switch(input)
|
|
if(I_HELP)
|
|
a_intent = I_HELP
|
|
if(I_HURT)
|
|
a_intent = I_HURT
|
|
if("right","left")
|
|
a_intent = intent_numeric(intent_numeric(a_intent) - 3)
|
|
if(hud_used && hud_used.action_intent)
|
|
if(a_intent == I_HURT)
|
|
hud_used.action_intent.icon_state = I_HURT
|
|
else
|
|
hud_used.action_intent.icon_state = I_HELP
|
|
|
|
proc/is_blind(A)
|
|
if(istype(A, /mob/living/carbon))
|
|
var/mob/living/carbon/C = A
|
|
if(C.sdisabilities & BLIND || C.blinded)
|
|
return 1
|
|
return 0
|
|
|
|
/proc/mobs_in_area(var/area/A)
|
|
var/list/mobs = new
|
|
for(var/mob/living/M in mob_list)
|
|
if(get_area(M) == A)
|
|
mobs += M
|
|
return mobs
|
|
|
|
//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
|
|
|
|
if(subject && subject.forbid_seeing_deadchat && !subject.client.holder)
|
|
return // Can't talk in deadchat if you can't see it.
|
|
|
|
for(var/mob/M in player_list)
|
|
if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights)) && M.is_preference_enabled(/datum/client_preference/show_dsay))
|
|
var/follow
|
|
var/lname
|
|
if(M.forbid_seeing_deadchat && !M.client.holder)
|
|
continue
|
|
|
|
if(subject)
|
|
if(M.is_key_ignored(subject.client.key)) // If we're ignored, do nothing.
|
|
continue
|
|
if(subject != M)
|
|
follow = "([ghost_follow_link(subject, M)]) "
|
|
if(M.stat != DEAD && M.client.holder)
|
|
follow = "([admin_jump_link(subject, M.client.holder)]) "
|
|
var/mob/observer/dead/DM
|
|
if(istype(subject, /mob/observer/dead))
|
|
DM = subject
|
|
if(M.client.holder) // 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'>" + create_text_tag("dead", "DEAD:", M.client) + " [lname][follow][message]</span>")
|
|
|
|
/proc/say_dead_object(var/message, var/obj/subject = null)
|
|
for(var/mob/M in player_list)
|
|
if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights)) && M.is_preference_enabled(/datum/client_preference/show_dsay))
|
|
var/follow
|
|
var/lname = "Game Master"
|
|
if(M.forbid_seeing_deadchat && !M.client.holder)
|
|
continue
|
|
|
|
if(subject)
|
|
lname = "[subject.name] ([subject.x],[subject.y],[subject.z])"
|
|
|
|
lname = "<span class='name'>[lname]</span> "
|
|
to_chat(M, "<span class='deadsay'>" + create_text_tag("event_dead", "EVENT:", M.client) + " [lname][follow][message]</span>")
|
|
|
|
//Announces that a ghost has joined/left, mainly for use with wizards
|
|
/proc/announce_ghost_joinleave(O, var/joined_ghosts = 1, var/message = "")
|
|
var/client/C
|
|
//Accept any type, sort what we want here
|
|
if(istype(O, /mob))
|
|
var/mob/M = O
|
|
if(M.client)
|
|
C = M.client
|
|
else if(istype(O, /client))
|
|
C = O
|
|
else if(istype(O, /datum/mind))
|
|
var/datum/mind/M = O
|
|
if(M.current && M.current.client)
|
|
C = M.current.client
|
|
else if(M.original && M.original.client)
|
|
C = M.original.client
|
|
|
|
if(C)
|
|
var/name
|
|
if(C.mob)
|
|
var/mob/M = C.mob
|
|
if(M.mind && M.mind.name)
|
|
name = M.mind.name
|
|
if(M.real_name && M.real_name != name)
|
|
if(name)
|
|
name += " ([M.real_name])"
|
|
else
|
|
name = M.real_name
|
|
if(!name)
|
|
name = (C.holder && C.holder.fakekey) ? C.holder.fakekey : C.key
|
|
if(joined_ghosts)
|
|
say_dead_direct("The ghost of <span class='name'>[name]</span> now [pick("skulks","lurks","prowls","creeps","stalks")] among the dead. [message]")
|
|
else
|
|
say_dead_direct("<span class='name'>[name]</span> no longer [pick("skulks","lurks","prowls","creeps","stalks")] in the realm of the dead. [message]")
|
|
|
|
/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/living/silicon/ai/switch_to_camera(var/obj/machinery/camera/C)
|
|
if(!C.can_use() || !is_in_chassis())
|
|
return 0
|
|
|
|
eyeobj.setLoc(C)
|
|
return 1
|
|
|
|
// Returns true if the mob has a client which has been active in the last given X minutes.
|
|
/mob/proc/is_client_active(var/active = 1)
|
|
return client && client.inactivity < active MINUTES
|
|
|
|
/mob/proc/can_eat()
|
|
return 1
|
|
|
|
/mob/proc/can_force_feed()
|
|
return 1
|
|
|
|
#define SAFE_PERP -50
|
|
/mob/living/proc/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
|
|
if(stat == DEAD)
|
|
return SAFE_PERP
|
|
|
|
return 0
|
|
|
|
/mob/living/carbon/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
|
|
if(handcuffed)
|
|
return SAFE_PERP
|
|
|
|
return ..()
|
|
|
|
/mob/living/carbon/human/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
|
|
var/threatcount = ..()
|
|
if(. == SAFE_PERP)
|
|
return SAFE_PERP
|
|
|
|
//Agent cards lower threatlevel.
|
|
var/obj/item/weapon/card/id/id = GetIdCard()
|
|
if(id && istype(id, /obj/item/weapon/card/id/syndicate))
|
|
threatcount -= 2
|
|
// A proper CentCom id is hard currency.
|
|
else if(id && istype(id, /obj/item/weapon/card/id/centcom))
|
|
return SAFE_PERP
|
|
|
|
if(check_access && !access_obj.allowed(src))
|
|
threatcount += 4
|
|
|
|
if(auth_weapons && !access_obj.allowed(src))
|
|
if(istype(l_hand, /obj/item/weapon/gun) || istype(l_hand, /obj/item/weapon/melee))
|
|
threatcount += 4
|
|
|
|
if(istype(r_hand, /obj/item/weapon/gun) || istype(r_hand, /obj/item/weapon/melee))
|
|
threatcount += 4
|
|
|
|
if(istype(belt, /obj/item/weapon/gun) || istype(belt, /obj/item/weapon/melee))
|
|
threatcount += 2
|
|
|
|
if(species.name != SPECIES_HUMAN)
|
|
threatcount += 2
|
|
|
|
if(check_records || check_arrest)
|
|
var/perpname = name
|
|
if(id)
|
|
perpname = id.registered_name
|
|
|
|
var/datum/data/record/R = find_security_record("name", perpname)
|
|
if(check_records && !R)
|
|
threatcount += 4
|
|
|
|
if(check_arrest && R && (R.fields["criminal"] == "*Arrest*"))
|
|
threatcount += 4
|
|
|
|
return threatcount
|
|
|
|
/mob/living/simple_mob/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
|
|
var/threatcount = ..()
|
|
if(. == SAFE_PERP)
|
|
return SAFE_PERP
|
|
|
|
if(has_AI() && ai_holder.hostile && faction != "neutral") // Otherwise Runtime gets killed.
|
|
threatcount += 4
|
|
return threatcount
|
|
|
|
// Beepsky will (try to) only beat 'bad' slimes.
|
|
/mob/living/simple_mob/slime/xenobio/assess_perp(var/obj/access_obj, var/check_access, var/auth_weapons, var/check_records, var/check_arrest)
|
|
var/threatcount = 0
|
|
|
|
if(stat == DEAD)
|
|
return SAFE_PERP
|
|
|
|
if(is_justified_to_discipline())
|
|
threatcount += 4
|
|
/*
|
|
if(discipline && !rabid)
|
|
if(!target_mob || istype(target_mob, /mob/living/carbon/human/monkey))
|
|
return SAFE_PERP
|
|
|
|
if(target_mob)
|
|
threatcount += 4
|
|
|
|
if(victim)
|
|
threatcount += 4
|
|
*/
|
|
if(has_AI())
|
|
var/datum/ai_holder/simple_mob/xenobio_slime/AI = ai_holder
|
|
if(AI.rabid)
|
|
threatcount = 10
|
|
|
|
return threatcount
|
|
|
|
#undef SAFE_PERP
|
|
|
|
|
|
//TODO: Integrate defence zones and targeting body parts with the actual organ system, move these into organ definitions.
|
|
|
|
//The base miss chance for the different defence zones
|
|
var/list/global/base_miss_chance = list(
|
|
"head" = 40,
|
|
"chest" = 10,
|
|
"groin" = 20,
|
|
"l_leg" = 20,
|
|
"r_leg" = 20,
|
|
"l_arm" = 20,
|
|
"r_arm" = 20,
|
|
"l_hand" = 50,
|
|
"r_hand" = 50,
|
|
"l_foot" = 50,
|
|
"r_foot" = 50,
|
|
)
|
|
|
|
//Used to weight organs when an organ is hit randomly (i.e. not a directed, aimed attack).
|
|
//Also used to weight the protection value that armour provides for covering that body part when calculating protection from full-body effects.
|
|
var/list/global/organ_rel_size = list(
|
|
"head" = 25,
|
|
"chest" = 70,
|
|
"groin" = 30,
|
|
"l_leg" = 25,
|
|
"r_leg" = 25,
|
|
"l_arm" = 25,
|
|
"r_arm" = 25,
|
|
"l_hand" = 10,
|
|
"r_hand" = 10,
|
|
"l_foot" = 10,
|
|
"r_foot" = 10,
|
|
)
|
|
|
|
/mob/proc/flash_eyes(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /obj/screen/fullscreen/flash)
|
|
return
|
|
|
|
//Recalculates what planes this mob can see using their plane_holder, for humans this is checking slots, for others, could be whatever.
|
|
/mob/proc/recalculate_vis()
|
|
return
|
|
|
|
//General HUD updates done regularly (health puppet things, etc)
|
|
/mob/proc/handle_regular_hud_updates()
|
|
return
|
|
|
|
//Handle eye things like the Byond SEE_TURFS, SEE_OBJS, etc.
|
|
/mob/proc/handle_vision()
|
|
return
|
|
|
|
//Icon is used to occlude things like huds from the faulty byond context menu.
|
|
// http://www.byond.com/forum/?post=2336679
|
|
var/global/image/backplane
|
|
/hook/startup/proc/generate_backplane()
|
|
backplane = image('icons/misc/win32.dmi')
|
|
backplane.alpha = 0
|
|
backplane.plane = -100
|
|
backplane.layer = MOB_LAYER-0.1
|
|
backplane.mouse_opacity = 0
|
|
|
|
return TRUE
|
|
|
|
/mob/proc/get_sound_env(var/pressure_factor)
|
|
if (pressure_factor < 0.5)
|
|
return SPACE
|
|
else
|
|
var/area/A = get_area(src)
|
|
return A.sound_env
|
|
|
|
/mob/proc/position_hud_item(var/obj/item/item, var/slot)
|
|
if(!istype(hud_used) || !slot || !LAZYLEN(hud_used.slot_info))
|
|
return
|
|
|
|
//They may have hidden their entire hud but the hands
|
|
if(!hud_used.hud_shown && slot > slot_r_hand)
|
|
item.screen_loc = null
|
|
return
|
|
|
|
//They may have hidden the icons in the bottom left with the hide button
|
|
if(!hud_used.inventory_shown && slot > slot_r_store)
|
|
item.screen_loc = null
|
|
return
|
|
|
|
var/screen_place = hud_used.slot_info["[slot]"]
|
|
if(!screen_place)
|
|
item.screen_loc = null
|
|
return
|
|
|
|
item.screen_loc = screen_place
|