mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 02:09:41 +00:00
350 lines
12 KiB
Plaintext
350 lines
12 KiB
Plaintext
/atom/movable/proc/get_mob()
|
|
if(buckled_mobs) return buckled_mobs.Copy()
|
|
|
|
/obj/mecha/get_mob()
|
|
return occupant
|
|
|
|
/obj/vehicle_old/train/get_mob()
|
|
return buckled_mobs
|
|
|
|
/mob/get_mob()
|
|
return src
|
|
|
|
/mob/living/bot/mulebot/get_mob()
|
|
if(load && isliving(load))
|
|
return list(src, load)
|
|
return src
|
|
|
|
/proc/mobs_in_view(range, source)
|
|
var/list/mobs = list()
|
|
for(var/atom/movable/AM in view(range, source))
|
|
var/M = AM.get_mob()
|
|
if(M)
|
|
mobs += M
|
|
|
|
return mobs
|
|
|
|
/// This gets a list of mobs ALL around us as if we had xray vision and can see through walls.
|
|
/// Currently only used in portable_turret.dm if you wish to see an example of how to use it.
|
|
/proc/mobs_in_xray_view(range, source)
|
|
var/list/mobs = list()
|
|
for(var/atom/movable/AM in orange(range, source))
|
|
var/M = AM.get_mob()
|
|
if(M)
|
|
mobs += M
|
|
|
|
return mobs
|
|
/proc/random_hair_style(gender, species = SPECIES_HUMAN)
|
|
var/h_style = "Bald"
|
|
|
|
var/list/valid_hairstyles = list()
|
|
for(var/hairstyle in GLOB.hair_styles_list)
|
|
var/datum/sprite_accessory/S = GLOB.hair_styles_list[hairstyle]
|
|
if(gender == MALE && S.gender == FEMALE)
|
|
continue
|
|
if(gender == FEMALE && S.gender == MALE)
|
|
continue
|
|
if(S.name == DEVELOPER_WARNING_NAME)
|
|
continue
|
|
if( !(species in S.species_allowed))
|
|
continue
|
|
valid_hairstyles[hairstyle] = GLOB.hair_styles_list[hairstyle]
|
|
|
|
if(valid_hairstyles.len)
|
|
h_style = pick(valid_hairstyles)
|
|
|
|
return h_style
|
|
|
|
/proc/random_facial_hair_style(gender, species = SPECIES_HUMAN)
|
|
var/f_style = "Shaved"
|
|
|
|
var/list/valid_facialhairstyles = list()
|
|
for(var/facialhairstyle in GLOB.facial_hair_styles_list)
|
|
var/datum/sprite_accessory/S = GLOB.facial_hair_styles_list[facialhairstyle]
|
|
if(gender == MALE && S.gender == FEMALE)
|
|
continue
|
|
if(gender == FEMALE && S.gender == MALE)
|
|
continue
|
|
if(S.name == DEVELOPER_WARNING_NAME)
|
|
continue
|
|
if( !(species in S.species_allowed))
|
|
continue
|
|
|
|
valid_facialhairstyles[facialhairstyle] = GLOB.facial_hair_styles_list[facialhairstyle]
|
|
|
|
if(valid_facialhairstyles.len)
|
|
f_style = pick(valid_facialhairstyles)
|
|
|
|
return f_style
|
|
|
|
/proc/sanitize_name(name, species = SPECIES_HUMAN, robot = 0)
|
|
var/datum/species/current_species
|
|
if(species)
|
|
current_species = GLOB.all_species[species]
|
|
|
|
return current_species ? current_species.sanitize_name(name, robot) : sanitizeName(name, MAX_NAME_LEN, robot)
|
|
|
|
/proc/random_name(gender, species = SPECIES_HUMAN)
|
|
|
|
var/datum/species/current_species
|
|
if(species)
|
|
current_species = GLOB.all_species[species]
|
|
|
|
if(!current_species || current_species.name_language == null)
|
|
if(gender==FEMALE)
|
|
return capitalize(pick(GLOB.first_names_female)) + " " + capitalize(pick(GLOB.last_names))
|
|
else
|
|
return capitalize(pick(GLOB.first_names_male)) + " " + capitalize(pick(GLOB.last_names))
|
|
else
|
|
return current_species.get_random_name(gender)
|
|
|
|
/proc/random_skin_tone()
|
|
switch(pick(60;"caucasian", 15;"afroamerican", 10;"african", 10;"latino", 5;"albino"))
|
|
if("caucasian") . = -10
|
|
if("afroamerican") . = -115
|
|
if("african") . = -165
|
|
if("latino") . = -55
|
|
if("albino") . = 34
|
|
else . = rand(-185,34)
|
|
return min(max( .+rand(-25, 25), -185),34)
|
|
|
|
/proc/skintone2racedescription(tone)
|
|
switch (tone)
|
|
if(30 to INFINITY) return "albino"
|
|
if(20 to 30) return "pale"
|
|
if(5 to 15) return "light skinned"
|
|
if(-10 to 5) return "white"
|
|
if(-25 to -10) return "tan"
|
|
if(-45 to -25) return "darker skinned"
|
|
if(-65 to -45) return "brown"
|
|
if(-INFINITY to -65) return "black"
|
|
else return "unknown"
|
|
|
|
/proc/age2agedescription(age)
|
|
switch(age)
|
|
if(0 to 1) return "infant"
|
|
if(1 to 3) return "toddler"
|
|
if(3 to 13) return "child"
|
|
if(13 to 19) return "teenager"
|
|
if(19 to 30) return "young adult"
|
|
if(30 to 45) return "adult"
|
|
if(45 to 60) return "middle-aged"
|
|
if(60 to 70) return "aging"
|
|
if(70 to INFINITY) return "elderly"
|
|
else return "unknown"
|
|
|
|
/proc/RoundHealth(health)
|
|
var/list/icon_states = cached_icon_states(GLOB.ingame_hud_med)
|
|
for(var/icon_state in icon_states)
|
|
if(health >= text2num(icon_state))
|
|
return icon_state
|
|
return icon_states[icon_states.len] // If we had no match, return the last element
|
|
|
|
/*
|
|
Proc for attack log creation, because really why not
|
|
1 argument is the actor
|
|
2 argument is the target of action
|
|
3 is the description of action(like punched, throwed, or any other verb)
|
|
4 should it make adminlog note or not
|
|
5 is the tool with which the action was made(usually item) 5 and 6 are very similar(5 have "by " before it, that it) and are separated just to keep things in a bit more in order
|
|
6 is additional information, anything that needs to be added
|
|
*/
|
|
|
|
/proc/add_attack_logs(mob/user, mob/target, what_done, var/admin_notify = TRUE)
|
|
if(islist(target)) //Multi-victim adding
|
|
var/list/targets = target
|
|
for(var/mob/M in targets)
|
|
add_attack_logs(user,M,what_done,admin_notify)
|
|
return
|
|
|
|
var/user_str = key_name(user)
|
|
var/target_str = key_name(target)
|
|
|
|
if(ismob(user))
|
|
user.attack_log += text("\[[time_stamp()]\] [span_red("Attacked [target_str]: [what_done]")]")
|
|
if(ismob(target))
|
|
target.attack_log += text("\[[time_stamp()]\] [span_orange("Attacked by [user_str]: [what_done]")]")
|
|
log_combat(user, target, what_done)
|
|
if(admin_notify)
|
|
msg_admin_attack("[key_name_admin(user)] vs [target_str]: [what_done]")
|
|
|
|
//checks whether this item is a module of the robot it is located in.
|
|
/proc/is_robot_module(var/obj/item/thing)
|
|
if (!thing || !isrobot(thing.loc))
|
|
return 0
|
|
var/mob/living/silicon/robot/R = thing.loc
|
|
return (thing in R.module.modules)
|
|
|
|
/proc/get_exposed_defense_zone(var/atom/movable/target)
|
|
var/obj/item/grab/G = locate() in target
|
|
if(G && G.state >= GRAB_NECK) //works because mobs are currently not allowed to upgrade to NECK if they are grabbing two people.
|
|
return pick(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_FOOT, BP_R_FOOT, BP_L_ARM, BP_R_ARM, BP_L_LEG, BP_R_LEG)
|
|
else
|
|
return pick(BP_TORSO, BP_GROIN)
|
|
|
|
/**
|
|
* Timed action involving one mob user. Target is optional.
|
|
*
|
|
* Checks that `user` does not move, change hands, get stunned, etc. for the
|
|
* given `delay`. Returns `TRUE` on success or `FALSE` on failure.
|
|
*
|
|
* @param {mob} user - The mob performing the action.
|
|
*
|
|
* @param {number} delay - The time in deciseconds. Use the SECONDS define for readability. `1 SECONDS` is 10 deciseconds.
|
|
*
|
|
* @param {atom} target - The target of the action. This is where the progressbar will display.
|
|
*
|
|
* @param {flag} timed_action_flags - Flags to control the behavior of the timed action.
|
|
*
|
|
* @param {boolean} progress - Whether to display a progress bar / cogbar.
|
|
*
|
|
* @param {datum/callback} extra_checks - Additional checks to perform before the action is executed.
|
|
*
|
|
* @param {string} interaction_key - The assoc key under which the do_after is capped, with max_interact_count being the cap. Interaction key will default to target if not set.
|
|
*
|
|
* @param {number} max_interact_count - The maximum amount of interactions allowed.
|
|
*
|
|
* @param {boolean} hidden - By default, any action 1 second or longer shows a cog over the user while it is in progress. If hidden is set to TRUE, the cog will not be shown.
|
|
*
|
|
* @param {icon} icon - The icon file of the cog. Default: 'icons/effects/progressbar.dmi'
|
|
*
|
|
* @param {iconstate} iconstate - The icon state of the cog. Default: "Cog"
|
|
*
|
|
* @param {string} target_zone - The target zone of the user. See _defines/mobs.dm. If the user swaps from this zone, we break the do_after
|
|
*
|
|
* @param {number} max_distance - The maximum distance we can be away from the target before the do_after breaks. Default to 1.
|
|
*/
|
|
/proc/do_after(mob/user, delay, atom/target, timed_action_flags = NONE, progress = TRUE, datum/callback/extra_checks, interaction_key, max_interact_count = 1, hidden = FALSE, icon = 'icons/effects/progressbar.dmi', iconstate = "cog", target_zone, max_distance = null)
|
|
if(!user)
|
|
return FALSE
|
|
if(!isnum(delay))
|
|
CRASH("do_after was passed a non-number delay: [delay || "null"].")
|
|
|
|
if(!isatom(target))
|
|
CRASH("do_after was given a non-atom target! [target]")
|
|
|
|
if(!interaction_key && target)
|
|
interaction_key = target //Use the direct ref to the target
|
|
if(interaction_key) //Do we have a interaction_key now?
|
|
var/current_interaction_count = LAZYACCESS(user.do_afters, interaction_key) || 0
|
|
if(current_interaction_count >= max_interact_count) //We are at our peak
|
|
return
|
|
LAZYSET(user.do_afters, interaction_key, current_interaction_count + 1)
|
|
|
|
var/atom/user_loc = user.loc
|
|
var/atom/target_loc = target?.loc
|
|
|
|
var/drifting = FALSE
|
|
/* //We don't have a drift handler yet, sadly.
|
|
if(!isnull(user.drift_handler))
|
|
drifting = TRUE*/
|
|
|
|
var/holding = user.get_active_hand()
|
|
/* //Disabling for now. Meant to be used for modifier slowdowns.
|
|
if(!(timed_action_flags & IGNORE_SLOWDOWNS))
|
|
var/slowdown = user.calculate_item_encumbrance()
|
|
if(slowdown)
|
|
//Let's not be TOO evil. You can be up to 4x faster, but never more than 3x slower.
|
|
delay *= CLAMP(slowdown, 0.25, 3)
|
|
*/
|
|
var/datum/progressbar/progbar
|
|
var/datum/cogbar/cog
|
|
|
|
if(progress)
|
|
if(user.client)
|
|
progbar = new(user, delay, target || user)
|
|
|
|
if(!hidden && delay >= 1 SECONDS)
|
|
cog = new(user, icon, iconstate)
|
|
|
|
SEND_SIGNAL(user, COMSIG_DO_AFTER_BEGAN)
|
|
|
|
var/endtime = world.time + delay
|
|
var/starttime = world.time
|
|
. = TRUE
|
|
while (world.time < endtime)
|
|
stoplag(1)
|
|
|
|
if(!QDELETED(progbar))
|
|
progbar.update(world.time - starttime)
|
|
|
|
/*if(drifting && isnull(user.drift_handler)) //We don't have a drift handler yet, sadly.
|
|
drifting = FALSE
|
|
user_loc = user.loc*/
|
|
|
|
if(QDELETED(user) \
|
|
|| (!(timed_action_flags & IGNORE_USER_LOC_CHANGE) && !drifting && user.loc != user_loc) \
|
|
|| (!(timed_action_flags & IGNORE_HELD_ITEM) && user.get_active_hand() != holding) \
|
|
|| (!(timed_action_flags & IGNORE_INCAPACITATED) && HAS_TRAIT(user, TRAIT_INCAPACITATED)) \
|
|
|| (max_distance && target && get_dist(user, target) > max_distance) \
|
|
|| (target_zone && user.zone_sel?.selecting != target_zone) \
|
|
|| (extra_checks && !extra_checks.Invoke()))
|
|
. = FALSE
|
|
break
|
|
|
|
if(target && (user != target) && \
|
|
(QDELETED(target) \
|
|
|| (!(timed_action_flags & IGNORE_TARGET_LOC_CHANGE) && target.loc != target_loc)))
|
|
. = FALSE
|
|
break
|
|
|
|
if(!QDELETED(progbar))
|
|
progbar.end_progress()
|
|
|
|
cog?.remove()
|
|
|
|
if(interaction_key)
|
|
var/reduced_interaction_count = (LAZYACCESS(user.do_afters, interaction_key) || 0) - 1
|
|
if(reduced_interaction_count > 0) // Not done yet!
|
|
LAZYSET(user.do_afters, interaction_key, reduced_interaction_count)
|
|
return
|
|
// all out, let's clear er out fully
|
|
LAZYREMOVE(user.do_afters, interaction_key)
|
|
SEND_SIGNAL(user, COMSIG_DO_AFTER_ENDED)
|
|
|
|
/atom/proc/living_mobs(var/range = world.view, var/count_held = FALSE) //CHOMPEdit Start
|
|
var/list/viewers = oviewers(src,range)
|
|
if(count_held)
|
|
viewers = viewers(src,range)
|
|
var/list/living = list()
|
|
for(var/mob/living/L in viewers)
|
|
living += L
|
|
if(count_held)
|
|
for(var/obj/item/holder/H in L.contents)
|
|
if(istype(H.held_mob, /mob/living))
|
|
living += H.held_mob //CHOMPEdit End
|
|
return living
|
|
|
|
/atom/proc/human_mobs(var/range = world.view)
|
|
var/list/viewers = oviewers(src,range)
|
|
var/list/humans = list()
|
|
for(var/mob/living/carbon/human/H in viewers)
|
|
humans += H
|
|
|
|
return humans
|
|
|
|
/proc/cached_character_icon(var/mob/desired)
|
|
var/cachekey = "\ref[desired][desired.real_name]"
|
|
|
|
if(GLOB.cached_character_icons[cachekey])
|
|
. = GLOB.cached_character_icons[cachekey]
|
|
else
|
|
. = getCompoundIcon(desired)
|
|
GLOB.cached_character_icons[cachekey] = .
|
|
|
|
/proc/not_has_ooc_text(mob/user)
|
|
if (CONFIG_GET(flag/allow_metadata) && (!user.client?.prefs?.read_preference(/datum/preference/text/living/ooc_notes) || length(user.client.prefs.read_preference(/datum/preference/text/living/ooc_notes)) < 15))
|
|
to_chat(user, span_warning("Please set informative OOC notes related to RP/ERP preferences. Set them using the 'OOC Notes' button on the 'General' tab in character setup."))
|
|
return TRUE
|
|
return FALSE
|
|
|
|
///Makes a call in the context of a different usr. Use sparingly
|
|
/world/proc/push_usr(mob/user_mob, datum/callback/invoked_callback, ...)
|
|
var/temp = usr
|
|
usr = user_mob
|
|
if (length(args) > 2)
|
|
. = invoked_callback.Invoke(arglist(args.Copy(3)))
|
|
else
|
|
. = invoked_callback.Invoke()
|
|
usr = temp
|