// fun if you want to typecast humans/monkeys/etc without writing long path-filled lines. /proc/isxenomorph(A) if(ishuman(A)) var/mob/living/carbon/human/H = A return istype(H.species, /datum/species/xenos) return 0 /proc/issmall(A) if(A && isliving(A)) 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 && isliving(A)) var/mob/living/L = A return L.mob_size <= MOB_TINY return 0 /proc/ismini(A) if(A && isliving(A)) 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 /** * Moved into its own file as part of port from CHOMP. * /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, var/force_hit = FALSE) 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/grab/G in target.grabbed_by) if(G.state >= GRAB_AGGRESSIVE) return zone if(force_hit) 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) CHOMPEDIT - removing baymiss if(prob(miss_chance_mod)) //CHOMPADD - removing baymiss. Checking the miss chance for legacy. This should only be affected by special cases and evasion. return null if(prob(miss_chance)) //if(prob(70)) // return null CHOMPEDIT - removing baymiss 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,9)) if(1,3,5,8) newletter="[lowertext(newletter)]" //if(2,4,6,15) newletter="[uppertext(newletter)]" if(2,4,6,9) newletter="[uppertext(newletter)]" if(7) newletter+="'" //if(9,10) newletter=span_bold("[newletter]") //if(11,12) newletter="[newletter]" //if(13) newletter="[newletter]" 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 || duration < 1) return var/client/C = M.client var/oldx = C.pixel_x var/oldy = C.pixel_y var/max = strength * world.icon_size var/min = -(strength * world.icon_size) for(var/i in 0 to duration - 1) if(i == 0) animate(C, pixel_x = rand(min, max), pixel_y = rand(min, max), time = 1) else animate(pixel_x = rand(min, max), pixel_y = rand(min, max), time = 1) animate(pixel_x = oldx, pixel_y = oldy, time = 1) /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 I_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 = list() for(var/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 && ((!isnewplayer(M) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights && M.client?.prefs?.read_preference(/datum/preference/toggle/holder/show_staff_dsay))) && M.client?.prefs?.read_preference(/datum/preference/toggle/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(isobserver(subject)) 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_name("[lname]") + " " to_chat(M, span_deadsay("" + create_text_tag("dead", "DEAD:", M.client) + " [lname][follow][message]")) /proc/say_dead_object(var/message, var/obj/subject = null) for(var/mob/M in player_list) if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights && M.client?.prefs?.read_preference(/datum/preference/toggle/holder/show_staff_dsay))) && M.client?.prefs?.read_preference(/datum/preference/toggle/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_name("[lname]") + " " to_chat(M, span_deadsay("" + create_text_tag("event_dead", "EVENT:", M.client) + " [lname][follow][message]")) //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_name("[name]") + " now [pick("skulks","lurks","prowls","creeps","stalks")] among the dead. [message]") //ChompEDIT - Removed for ghost privacy log_and_message_admins("[name] entered ghost/observe mode. [message]") //ChompEDIT else //say_dead_direct(span_name("[name]") + " no longer [pick("skulks","lurks","prowls","creeps","stalks")] in the realm of the dead. [message]") //ChompEDIT - Removed for ghost privacy log_and_message_admins("[name] left ghost/observe mode. [message]") //ChompEDIT /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/card/id/id = GetIdCard() if(id && istype(id, /obj/item/card/id/syndicate)) threatcount -= 2 // A proper CentCom id is hard currency. else if(id && istype(id, /obj/item/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/gun) || istype(l_hand, /obj/item/melee) && !istype(l_hand, /obj/item/gun/energy/floragun) && !istype(l_hand, /obj/item/gun/energy/sizegun) && !istype(l_hand, /obj/item/gun/launcher/confetti_cannon) && !istype(l_hand, /obj/item/gun/energy/lasertag)) //CHOMP Edit: Specific guns to the exclusion list. threatcount += 4 if(istype(r_hand, /obj/item/gun) || istype(r_hand, /obj/item/melee)) threatcount += 4 if(istype(belt, /obj/item/gun) || istype(belt, /obj/item/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( BP_HEAD = 40, BP_TORSO = 10, BP_GROIN = 20, BP_L_LEG = 20, BP_R_LEG = 20, BP_L_ARM = 20, BP_R_ARM = 20, BP_L_HAND = 50, BP_R_HAND = 50, BP_L_FOOT = 50, BP_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( BP_HEAD = 25, BP_TORSO = 70, BP_GROIN = 30, BP_L_LEG = 25, BP_R_LEG = 25, BP_L_ARM = 25, BP_R_ARM = 25, BP_L_HAND = 10, BP_R_HAND = 10, BP_L_FOOT = 10, BP_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 /mob/proc/can_feed() return TRUE