mirror of
https://github.com/PolarisSS13/Polaris.git
synced 2026-08-29 08:09:34 +01:00
Merge remote-tracking branch 'upstream/master' into tgui4.0-and-camera-console
This commit is contained in:
@@ -54,6 +54,14 @@
|
||||
var/emp_modifier // Added to the EMP strength, which is an inverse scale from 1 to 4, with 1 being the strongest EMP. 5 is a nullification.
|
||||
var/explosion_modifier // Added to the bomb strength, which is an inverse scale from 1 to 3, with 1 being gibstrength. 4 is a nullification.
|
||||
|
||||
// Note that these are combined with the mob's real armor values additatively. You can also omit specific armor types.
|
||||
var/list/armor_percent = null // List of armor values to add to the holder when doing armor calculations. This is for percentage based armor. E.g. 50 = half damage.
|
||||
var/list/armor_flat = null // Same as above but only for flat armor calculations. E.g. 5 = 5 less damage (this comes after percentage).
|
||||
// Unlike armor, this is multiplicative. Two 50% protection modifiers will be combined into 75% protection (assuming no base protection on the mob).
|
||||
var/heat_protection = null // Modifies how 'heat' protection is calculated, like wearing a firesuit. 1 = full protection.
|
||||
var/cold_protection = null // Ditto, but for cold, like wearing a winter coat.
|
||||
var/siemens_coefficient = null // Similar to above two vars but 0 = full protection, to be consistant with siemens numbers everywhere else.
|
||||
|
||||
var/vision_flags // Vision flags to add to the mob. SEE_MOB, SEE_OBJ, etc.
|
||||
|
||||
/datum/modifier/New(var/new_holder, var/new_origin)
|
||||
@@ -185,10 +193,14 @@
|
||||
|
||||
// Checks if the mob has a modifier type.
|
||||
/mob/living/proc/has_modifier_of_type(var/modifier_type)
|
||||
return get_modifier_of_type(modifier_type) ? TRUE : FALSE
|
||||
|
||||
// Gets the first instance of a specific modifier type or subtype.
|
||||
/mob/living/proc/get_modifier_of_type(var/modifier_type)
|
||||
for(var/datum/modifier/M in modifiers)
|
||||
if(istype(M, modifier_type))
|
||||
return TRUE
|
||||
return FALSE
|
||||
return M
|
||||
return null
|
||||
|
||||
// This displays the actual 'numbers' that a modifier is doing. Should only be shown in OOC contexts.
|
||||
// When adding new effects, be sure to update this as well.
|
||||
|
||||
@@ -397,4 +397,33 @@ the artifact triggers the rage.
|
||||
|
||||
/datum/modifier/outline_test/tick()
|
||||
animate(filter_instance, size = 3, time = 0.25 SECONDS)
|
||||
animate(size = 1, 0.25 SECONDS)
|
||||
animate(size = 1, 0.25 SECONDS)
|
||||
|
||||
|
||||
// Acts as a psuedo-godmode, yet probably is more reliable than the actual var for it nowdays.
|
||||
// Can't protect from instantly killing things like singulos.
|
||||
/datum/modifier/invulnerable
|
||||
name = "invulnerable"
|
||||
desc = "You are almost immune to harm, for a little while at least."
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
|
||||
disable_duration_percent = 0
|
||||
incoming_damage_percent = 0
|
||||
// bleeding_rate_percent = 0
|
||||
pain_immunity = TRUE
|
||||
armor_percent = list("melee" = 2000, "bullet" = 2000, "laser" = 2000, "bomb" = 2000, "energy" = 2000, "bio" = 2000, "rad" = 2000)
|
||||
heat_protection = 1.0
|
||||
cold_protection = 1.0
|
||||
siemens_coefficient = 0.0
|
||||
|
||||
// Reduces resistance to "elements".
|
||||
// Note that most things that do give resistance gives 100% protection,
|
||||
// and due to multiplicitive stacking, this modifier won't do anything to change that.
|
||||
/datum/modifier/elemental_vulnerability
|
||||
name = "elemental vulnerability"
|
||||
desc = "You're more vulnerable to extreme temperatures and electricity."
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
|
||||
heat_protection = -0.5
|
||||
cold_protection = -0.5
|
||||
siemens_coefficient = 1.5
|
||||
@@ -120,27 +120,32 @@
|
||||
|
||||
// People covered in blood is also bad.
|
||||
// Feel free to trim down if its too expensive CPU wise.
|
||||
if(istype(thing, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = thing
|
||||
var/self_multiplier = H == holder ? 2 : 1
|
||||
var/human_blood_fear_amount = 0
|
||||
if(!H.gloves && H.bloody_hands && H.hand_blood_color != SYNTH_BLOOD_COLOUR)
|
||||
human_blood_fear_amount += 1
|
||||
if(!H.shoes && H.feet_blood_color && H.feet_blood_color != SYNTH_BLOOD_COLOUR)
|
||||
human_blood_fear_amount += 1
|
||||
if(isliving(thing))
|
||||
var/mob/living/L = thing
|
||||
if(L.alpha <= FAKE_INVIS_ALPHA_THRESHOLD) // Can't fear something you can't (easily) see.
|
||||
continue
|
||||
|
||||
// List of slots. Some slots like pockets are omitted due to not being visible, if H isn't the holder.
|
||||
var/list/clothing_slots = list(H.back, H.wear_mask, H.l_hand, H.r_hand, H.wear_id, H.glasses, H.gloves, H.head, H.shoes, H.belt, H.wear_suit, H.w_uniform, H.s_store, H.l_ear, H.r_ear)
|
||||
if(H == holder)
|
||||
clothing_slots += list(H.l_store, H.r_store)
|
||||
|
||||
for(var/obj/item/clothing/C in clothing_slots)
|
||||
if(C.blood_DNA && C.blood_color && C.blood_color != SYNTH_BLOOD_COLOUR)
|
||||
if(istype(thing, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = thing
|
||||
var/self_multiplier = H == holder ? 2 : 1
|
||||
var/human_blood_fear_amount = 0
|
||||
if(!H.gloves && H.bloody_hands && H.hand_blood_color != SYNTH_BLOOD_COLOUR)
|
||||
human_blood_fear_amount += 1
|
||||
if(!H.shoes && H.feet_blood_color && H.feet_blood_color != SYNTH_BLOOD_COLOUR)
|
||||
human_blood_fear_amount += 1
|
||||
|
||||
// This is divided, since humans can wear so many items at once.
|
||||
human_blood_fear_amount = round( (human_blood_fear_amount * self_multiplier) / 3, 1)
|
||||
fear_amount += human_blood_fear_amount
|
||||
// List of slots. Some slots like pockets are omitted due to not being visible, if H isn't the holder.
|
||||
var/list/clothing_slots = list(H.back, H.wear_mask, H.l_hand, H.r_hand, H.wear_id, H.glasses, H.gloves, H.head, H.shoes, H.belt, H.wear_suit, H.w_uniform, H.s_store, H.l_ear, H.r_ear)
|
||||
if(H == holder)
|
||||
clothing_slots += list(H.l_store, H.r_store)
|
||||
|
||||
for(var/obj/item/clothing/C in clothing_slots)
|
||||
if(C.blood_DNA && C.blood_color && C.blood_color != SYNTH_BLOOD_COLOUR)
|
||||
human_blood_fear_amount += 1
|
||||
|
||||
// This is divided, since humans can wear so many items at once.
|
||||
human_blood_fear_amount = round( (human_blood_fear_amount * self_multiplier) / 3, 1)
|
||||
fear_amount += human_blood_fear_amount
|
||||
|
||||
// Bloody objects are also bad.
|
||||
if(istype(thing, /obj))
|
||||
@@ -207,12 +212,18 @@
|
||||
if(istype(thing, /obj/structure/snowman/spider)) //Snow spiders are also spooky so people can be assholes with those too.
|
||||
fear_amount += 1
|
||||
|
||||
if(istype(thing, /mob/living/simple_mob/animal/giant_spider)) // Actual giant spiders are the scariest of them all.
|
||||
var/mob/living/simple_mob/animal/giant_spider/S = thing
|
||||
if(S.stat == DEAD) // Dead giant spiders are less scary than alive ones.
|
||||
fear_amount += 4
|
||||
else
|
||||
fear_amount += 8
|
||||
if(isliving(thing))
|
||||
var/mob/living/L = thing
|
||||
if(L.alpha <= FAKE_INVIS_ALPHA_THRESHOLD) // Can't fear something you can't (easily) see.
|
||||
continue
|
||||
|
||||
if(istype(L, /mob/living/simple_mob/animal/giant_spider)) // Actual giant spiders are the scariest of them all.
|
||||
var/mob/living/simple_mob/animal/giant_spider/S = L
|
||||
|
||||
if(S.stat == DEAD) // Dead giant spiders are less scary than alive ones.
|
||||
fear_amount += 4
|
||||
else
|
||||
fear_amount += 8
|
||||
return fear_amount
|
||||
|
||||
|
||||
@@ -425,25 +436,29 @@
|
||||
if(istype(thing, /obj/item/clothing/head/collectable/slime)) // Some hats are spooky so people can be assholes with them.
|
||||
fear_amount += 1
|
||||
|
||||
if(istype(thing, /mob/living/simple_mob/slime)) // An actual predatory specimen!
|
||||
var/mob/living/simple_mob/slime/S = thing
|
||||
if(S.stat == DEAD) // Dead slimes are somewhat less spook.
|
||||
fear_amount += 4
|
||||
if(istype(S, /mob/living/simple_mob/slime/xenobio))
|
||||
var/mob/living/simple_mob/slime/xenobio/X = S
|
||||
if(X.is_adult == TRUE) //big boy
|
||||
fear_amount += 8
|
||||
if(isliving(thing))
|
||||
var/mob/living/L = thing
|
||||
if(L.alpha <= FAKE_INVIS_ALPHA_THRESHOLD) // Can't fear something you can't (easily) see.
|
||||
continue
|
||||
if(istype(L, /mob/living/simple_mob/slime)) // An actual predatory specimen!
|
||||
var/mob/living/simple_mob/slime/S = L
|
||||
if(S.stat == DEAD) // Dead slimes are somewhat less spook.
|
||||
fear_amount += 4
|
||||
if(istype(S, /mob/living/simple_mob/slime/xenobio))
|
||||
var/mob/living/simple_mob/slime/xenobio/X = S
|
||||
if(X.is_adult == TRUE) //big boy
|
||||
fear_amount += 8
|
||||
else
|
||||
fear_amount += 6
|
||||
else
|
||||
fear_amount += 6
|
||||
else
|
||||
fear_amount += 10 // It's huge and feral.
|
||||
fear_amount += 10 // It's huge and feral.
|
||||
|
||||
if(istype(thing, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/S = thing
|
||||
if(istype(S.species, /datum/species/skrell)) //Skrell ARE slimey.
|
||||
fear_amount += 1
|
||||
if(istype(S.species, /datum/species/shapeshifter/promethean))
|
||||
fear_amount += 4
|
||||
if(istype(L, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/S = L
|
||||
if(istype(S.species, /datum/species/skrell)) //Skrell ARE slimey.
|
||||
fear_amount += 1
|
||||
if(istype(S.species, /datum/species/shapeshifter/promethean))
|
||||
fear_amount += 4
|
||||
|
||||
return fear_amount
|
||||
|
||||
@@ -525,13 +540,17 @@
|
||||
if(istype(thing, /obj/item/weapon/gun/launcher/syringe))
|
||||
fear_amount += 6
|
||||
|
||||
if(istype(thing, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = thing
|
||||
if(H.l_hand && istype(H.l_hand, /obj/item/weapon/reagent_containers/syringe) || H.r_hand && istype(H.r_hand, /obj/item/weapon/reagent_containers/syringe))
|
||||
fear_amount += 10
|
||||
if(isliving(thing))
|
||||
var/mob/living/L = thing
|
||||
if(L.alpha <= FAKE_INVIS_ALPHA_THRESHOLD) // Can't fear something you can't (easily) see.
|
||||
continue
|
||||
if(istype(L, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.l_hand && istype(H.l_hand, /obj/item/weapon/reagent_containers/syringe) || H.r_hand && istype(H.r_hand, /obj/item/weapon/reagent_containers/syringe))
|
||||
fear_amount += 10
|
||||
|
||||
if(H.l_ear && istype(H.l_ear, /obj/item/weapon/reagent_containers/syringe) || H.r_ear && istype(H.r_ear, /obj/item/weapon/reagent_containers/syringe))
|
||||
fear_amount +=10
|
||||
if(H.l_ear && istype(H.l_ear, /obj/item/weapon/reagent_containers/syringe) || H.r_ear && istype(H.r_ear, /obj/item/weapon/reagent_containers/syringe))
|
||||
fear_amount +=10
|
||||
|
||||
|
||||
return fear_amount
|
||||
|
||||
@@ -6,3 +6,6 @@
|
||||
plane_holder.set_vis(VIS_CLOAKED, TRUE)
|
||||
plane_holder.set_vis(VIS_AI_EYE, TRUE)
|
||||
plane = PLANE_GHOSTS
|
||||
if(cleanup_timer)
|
||||
deltimer(cleanup_timer)
|
||||
cleanup_timer = null
|
||||
@@ -3,3 +3,5 @@
|
||||
spawn(0)
|
||||
if(src && !key) //we've transferred to another mob. This ghost should be deleted.
|
||||
qdel(src)
|
||||
else
|
||||
cleanup_timer = QDEL_IN(src, 10 MINUTES)
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
"Beepsky" = "secbot"
|
||||
)
|
||||
var/last_revive_notification = null // world.time of last notification, used to avoid spamming players from defibs or cloners.
|
||||
var/cleanup_timer // Refernece to a timer that will delete this mob if no client returns
|
||||
|
||||
/mob/observer/dead/New(mob/body)
|
||||
sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
|
||||
@@ -129,6 +130,7 @@
|
||||
if(!name) //To prevent nameless ghosts
|
||||
name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
|
||||
real_name = name
|
||||
animate(src, pixel_y = 2, time = 10, loop = -1)
|
||||
..()
|
||||
|
||||
/mob/observer/dead/Topic(href, href_list)
|
||||
@@ -152,6 +154,13 @@
|
||||
if(new_stat != DEAD)
|
||||
CRASH("It is best if observers stay dead, thank you.")
|
||||
|
||||
/mob/observer/dead/examine_icon()
|
||||
var/icon/I = get_cached_examine_icon(src)
|
||||
if(!I)
|
||||
I = getFlatIcon(src, defdir = SOUTH, no_anim = TRUE)
|
||||
set_cached_examine_icon(src, I, 200 SECONDS)
|
||||
return I
|
||||
|
||||
/*
|
||||
Transfer_mind is there to check if mob is being deleted/not going to have a body.
|
||||
Works together with spawning an observer, noted above.
|
||||
@@ -220,6 +229,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
var/mob/observer/dead/ghost = ghostize(0) // 0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
|
||||
if(ghost)
|
||||
ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly.
|
||||
ghost.set_respawn_timer()
|
||||
announce_ghost_joinleave(ghost)
|
||||
|
||||
/mob/observer/dead/can_use_hands() return 0
|
||||
@@ -290,6 +300,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
var/response = alert(src, "If you turn this on, you will not be able to take any part in the round.","Are you sure you want to turn this feature on?","Yes","No")
|
||||
if(response == "No") return
|
||||
can_reenter_corpse = FALSE
|
||||
set_respawn_timer(-1) // Foreeeever
|
||||
if(!has_enabled_antagHUD && !client.holder)
|
||||
has_enabled_antagHUD = TRUE
|
||||
|
||||
@@ -306,6 +317,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
to_chat(usr, "Not when you're not dead!")
|
||||
return
|
||||
|
||||
if(!A)
|
||||
A = input(usr, "Select an area:", "Ghost Teleport") as null|anything in return_sorted_areas()
|
||||
if(!A)
|
||||
return
|
||||
|
||||
usr.forceMove(pick(get_area_turfs(A)))
|
||||
usr.on_mob_jump()
|
||||
|
||||
@@ -314,6 +330,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
set name = "Follow" // "Haunt"
|
||||
set desc = "Follow and haunt a mob."
|
||||
|
||||
if(!input)
|
||||
input = input(usr, "Select a mob:", "Ghost Follow") as null|anything in getmobs()
|
||||
if(!input)
|
||||
return
|
||||
|
||||
var/target = getmobs()[input]
|
||||
if(!target) return
|
||||
ManualFollow(target)
|
||||
@@ -347,6 +368,45 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
forceMove(T)
|
||||
sleep(15)
|
||||
|
||||
var/icon/I = icon(target.icon,target.icon_state,target.dir)
|
||||
|
||||
var/orbitsize = (I.Width()+I.Height())*0.5
|
||||
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
|
||||
|
||||
var/rot_seg
|
||||
|
||||
/* We don't have this pref yet
|
||||
switch(ghost_orbit)
|
||||
if(GHOST_ORBIT_TRIANGLE)
|
||||
rot_seg = 3
|
||||
if(GHOST_ORBIT_SQUARE)
|
||||
rot_seg = 4
|
||||
if(GHOST_ORBIT_PENTAGON)
|
||||
rot_seg = 5
|
||||
if(GHOST_ORBIT_HEXAGON)
|
||||
rot_seg = 6
|
||||
else //Circular
|
||||
rot_seg = 36 //360/10 bby, smooth enough aproximation of a circle
|
||||
*/
|
||||
|
||||
orbit(target, orbitsize, FALSE, 20, rot_seg)
|
||||
|
||||
/mob/observer/dead/orbit()
|
||||
set_dir(2) //reset dir so the right directional sprites show up
|
||||
return ..()
|
||||
|
||||
/mob/observer/dead/stop_orbit(datum/component/orbiter/orbits)
|
||||
. = ..()
|
||||
//restart our floating animation after orbit is done.
|
||||
pixel_y = 0
|
||||
pixel_x = 0
|
||||
transform = null
|
||||
animate(src, pixel_y = 2, time = 10, loop = -1)
|
||||
|
||||
/mob/observer/dead/proc/stop_following()
|
||||
following = null
|
||||
stop_orbit()
|
||||
|
||||
/mob/proc/update_following()
|
||||
. = get_turf(src)
|
||||
for(var/mob/observer/dead/M in following_mobs)
|
||||
@@ -361,7 +421,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
|
||||
/mob/Destroy()
|
||||
for(var/mob/observer/dead/M in following_mobs)
|
||||
M.following = null
|
||||
M.stop_following()
|
||||
following_mobs = null
|
||||
return ..()
|
||||
|
||||
@@ -369,7 +429,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(ismob(following))
|
||||
var/mob/M = following
|
||||
M.following_mobs -= src
|
||||
following = null
|
||||
stop_following()
|
||||
return ..()
|
||||
|
||||
/mob/Moved(atom/old_loc, direction, forced = FALSE)
|
||||
@@ -394,35 +454,28 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
set category = "Ghost"
|
||||
set name = "Jump to Mob"
|
||||
set desc = "Teleport to a mob"
|
||||
set popup_menu = FALSE
|
||||
|
||||
if(istype(usr, /mob/observer/dead)) //Make sure they're an observer!
|
||||
var/target = getmobs()[input]
|
||||
if (!target)//Make sure we actually have a target
|
||||
return
|
||||
else
|
||||
var/mob/M = target //Destination mob
|
||||
var/turf/T = get_turf(M) //Turf of the destination mob
|
||||
|
||||
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
|
||||
forceMove(T)
|
||||
following = null
|
||||
else
|
||||
to_chat(src, "This mob is not located in the game world.")
|
||||
/*
|
||||
/mob/observer/dead/verb/boo()
|
||||
set category = "Ghost"
|
||||
set name = "Boo!"
|
||||
set desc= "Scare your crew members because of boredom!"
|
||||
|
||||
if(bootime > world.time) return
|
||||
var/obj/machinery/light/L = locate(/obj/machinery/light) in view(1, src)
|
||||
if(L)
|
||||
L.flicker()
|
||||
bootime = world.time + 600
|
||||
if(!istype(usr, /mob/observer/dead)) //Make sure they're an observer!
|
||||
return
|
||||
//Maybe in the future we can add more <i>spooky</i> code here!
|
||||
return
|
||||
*/
|
||||
|
||||
if(!input)
|
||||
input = input(usr, "Select a mob:", "Ghost Jump") as null|anything in getmobs()
|
||||
if(!input)
|
||||
return
|
||||
|
||||
var/target = getmobs()[input]
|
||||
if (!target)//Make sure we actually have a target
|
||||
return
|
||||
else
|
||||
var/mob/M = target //Destination mob
|
||||
var/turf/T = get_turf(M) //Turf of the destination mob
|
||||
|
||||
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
|
||||
forceMove(T)
|
||||
stop_following()
|
||||
else
|
||||
to_chat(src, "This mob is not located in the game world.")
|
||||
|
||||
/mob/observer/dead/memory()
|
||||
set hidden = 1
|
||||
@@ -433,7 +486,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
to_chat(src, "<font color='red'>You are dead! You have no mind to store memory!</font>")
|
||||
|
||||
/mob/observer/dead/Post_Incorpmove()
|
||||
following = null
|
||||
stop_following()
|
||||
|
||||
/mob/observer/dead/verb/analyze_air()
|
||||
set name = "Analyze Air"
|
||||
@@ -801,13 +854,19 @@ mob/observer/dead/MayRespawn(var/feedback = 0)
|
||||
set category = "Ghost"
|
||||
set name = "Blank pAI alert"
|
||||
set desc = "Flash an indicator light on available blank pAI devices for a smidgen of hope."
|
||||
if(usr.client.prefs.be_special & BE_PAI)
|
||||
|
||||
if(usr.client.prefs?.be_special & BE_PAI)
|
||||
var/count = 0
|
||||
for(var/obj/item/device/paicard/p in all_pai_cards)
|
||||
var/obj/item/device/paicard/PP = p
|
||||
if(PP.pai == null)
|
||||
count++
|
||||
PP.overlays += "pai-ghostalert"
|
||||
spawn(54)
|
||||
PP.overlays.Cut()
|
||||
to_chat(usr,"<span class='notice'>Flashing the displays of [count] unoccupied PAIs.</span>")
|
||||
else
|
||||
to_chat(usr,"<span class='warning'>You have 'Be pAI' disabled in your character prefs, so we can't help you.</span>")
|
||||
|
||||
/mob/observer/dead/speech_bubble_appearance()
|
||||
return "ghost"
|
||||
@@ -824,15 +883,7 @@ mob/observer/dead/MayRespawn(var/feedback = 0)
|
||||
if(message)
|
||||
to_chat(src, "<span class='ghostalert'><font size=4>[message]</font></span>")
|
||||
if(source)
|
||||
var/obj/screen/alert/A = throw_alert("\ref[source]_notify_revive", /obj/screen/alert/notify_cloning)
|
||||
if(A)
|
||||
if(client && client.prefs && client.prefs.UI_style)
|
||||
A.icon = ui_style2icon(client.prefs.UI_style)
|
||||
A.desc = message
|
||||
var/old_layer = source.layer
|
||||
source.layer = FLOAT_LAYER
|
||||
A.overlays += source
|
||||
source.layer = old_layer
|
||||
throw_alert("\ref[source]_notify_revive", /obj/screen/alert/notify_cloning, new_master = source)
|
||||
to_chat(src, "<span class='ghostalert'><a href=?src=[REF(src)];reenter=1>(Click to re-enter)</a></span>")
|
||||
if(sound)
|
||||
SEND_SOUND(src, sound(sound))
|
||||
|
||||
@@ -100,7 +100,8 @@
|
||||
if(mind) mind.store_memory("Time of death: [stationtime2text()]", 0)
|
||||
living_mob_list -= src
|
||||
dead_mob_list |= src
|
||||
|
||||
|
||||
set_respawn_timer()
|
||||
updateicon()
|
||||
handle_regular_hud_updates()
|
||||
handle_vision()
|
||||
|
||||
@@ -241,20 +241,20 @@
|
||||
M.Weaken(5)
|
||||
..()
|
||||
|
||||
/mob/living/bot/mulebot/proc/runOver(var/mob/living/carbon/human/H)
|
||||
if(istype(H)) // No safety checks - WILL run over lying humans. Stop ERPing in the maint!
|
||||
visible_message("<span class='warning'>[src] drives over [H]!</span>")
|
||||
/mob/living/bot/mulebot/proc/runOver(var/mob/living/M)
|
||||
if(istype(M)) // At this point, MULEBot has somehow crossed over onto your tile with you still on it. CRRRNCH.
|
||||
visible_message("<span class='warning'>[src] drives over [M]!</span>")
|
||||
playsound(src, 'sound/effects/splat.ogg', 50, 1)
|
||||
|
||||
var/damage = rand(5, 7)
|
||||
H.apply_damage(2 * damage, BRUTE, BP_HEAD)
|
||||
H.apply_damage(2 * damage, BRUTE, BP_TORSO)
|
||||
H.apply_damage(0.5 * damage, BRUTE, BP_L_LEG)
|
||||
H.apply_damage(0.5 * damage, BRUTE, BP_R_LEG)
|
||||
H.apply_damage(0.5 * damage, BRUTE, BP_L_ARM)
|
||||
H.apply_damage(0.5 * damage, BRUTE, BP_R_ARM)
|
||||
M.apply_damage(2 * damage, BRUTE, BP_HEAD)
|
||||
M.apply_damage(2 * damage, BRUTE, BP_TORSO)
|
||||
M.apply_damage(0.5 * damage, BRUTE, BP_L_LEG)
|
||||
M.apply_damage(0.5 * damage, BRUTE, BP_R_LEG)
|
||||
M.apply_damage(0.5 * damage, BRUTE, BP_L_ARM)
|
||||
M.apply_damage(0.5 * damage, BRUTE, BP_R_ARM)
|
||||
|
||||
blood_splatter(src, H, 1)
|
||||
blood_splatter(src, M, 1)
|
||||
..()
|
||||
|
||||
/mob/living/bot/mulebot/relaymove(var/mob/user, var/direction)
|
||||
|
||||
@@ -253,20 +253,14 @@
|
||||
return
|
||||
|
||||
// called when something steps onto a human
|
||||
// this handles mulebots and vehicles
|
||||
// and now mobs on fire
|
||||
// this handles mobs on fire - mulebot and vehicle code has been relocated to /mob/living/Crossed()
|
||||
/mob/living/carbon/human/Crossed(var/atom/movable/AM)
|
||||
if(AM.is_incorporeal())
|
||||
return
|
||||
if(istype(AM, /mob/living/bot/mulebot))
|
||||
var/mob/living/bot/mulebot/MB = AM
|
||||
MB.runOver(src)
|
||||
|
||||
if(istype(AM, /obj/vehicle))
|
||||
var/obj/vehicle/V = AM
|
||||
V.RunOver(src)
|
||||
|
||||
spread_fire(AM)
|
||||
|
||||
..() // call parent because we moved behavior to parent
|
||||
|
||||
// Get rank from ID, ID inside PDA, PDA, ID in wallet, etc.
|
||||
/mob/living/carbon/human/proc/get_authentification_rank(var/if_no_id = "No id", var/if_no_job = "No job")
|
||||
@@ -1566,6 +1560,13 @@
|
||||
else
|
||||
layer = HIDING_LAYER
|
||||
|
||||
/mob/living/carbon/human/examine_icon()
|
||||
var/icon/I = get_cached_examine_icon(src)
|
||||
if(!I)
|
||||
I = getFlatIcon(src, defdir = SOUTH, no_anim = TRUE)
|
||||
set_cached_examine_icon(src, I, 50 SECONDS)
|
||||
return I
|
||||
|
||||
/mob/living/carbon/human/proc/get_display_species()
|
||||
//Shows species in tooltip
|
||||
//Beepboops get special text if obviously beepboop
|
||||
@@ -1637,8 +1638,8 @@
|
||||
if(species?.flags & NO_BLOOD)
|
||||
bloodtrail = 0
|
||||
else
|
||||
var/blood_volume = round((vessel.get_reagent_amount("blood")/species.blood_volume)*100)
|
||||
if(blood_volume < BLOOD_VOLUME_SURVIVE)
|
||||
var/blood_volume = vessel.get_reagent_amount("blood")
|
||||
if(blood_volume < species?.blood_volume*species?.blood_level_fatal)
|
||||
bloodtrail = 0 //Most of it's gone already, just leave it be
|
||||
else
|
||||
vessel.remove_reagent("blood", 1)
|
||||
@@ -1646,4 +1647,24 @@
|
||||
if(istype(loc, /turf/simulated))
|
||||
var/turf/T = loc
|
||||
T.add_blood(src)
|
||||
. = ..()
|
||||
. = ..()
|
||||
|
||||
// Tries to turn off item-based things that let you see through walls, like mesons.
|
||||
// Certain stuff like genetic xray vision is allowed to be kept on.
|
||||
/mob/living/carbon/human/disable_spoiler_vision()
|
||||
// Glasses.
|
||||
if(istype(glasses, /obj/item/clothing/glasses))
|
||||
var/obj/item/clothing/glasses/goggles = glasses
|
||||
if(goggles.active && (goggles.vision_flags & (SEE_TURFS|SEE_OBJS)))
|
||||
goggles.toggle_active(src)
|
||||
to_chat(src, span("warning", "Your [goggles.name] have suddenly turned off!"))
|
||||
|
||||
// RIGs.
|
||||
var/obj/item/weapon/rig/rig = get_rig()
|
||||
if(istype(rig) && rig.visor?.active && rig.visor.vision?.glasses)
|
||||
var/obj/item/clothing/glasses/rig_goggles = rig.visor.vision.glasses
|
||||
if(rig_goggles.vision_flags & (SEE_TURFS|SEE_OBJS))
|
||||
rig.visor.deactivate()
|
||||
to_chat(src, span("warning", "\The [rig]'s visor has shuddenly deactivated!"))
|
||||
|
||||
..()
|
||||
|
||||
@@ -133,6 +133,12 @@ emp_act
|
||||
if(istype(C) && (C.body_parts_covered & def_zone.body_part)) // Is that body part being targeted covered?
|
||||
siemens_coefficient *= C.siemens_coefficient
|
||||
|
||||
// Modifiers.
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
if(!isnull(M.siemens_coefficient))
|
||||
siemens_coefficient *= M.siemens_coefficient
|
||||
|
||||
return siemens_coefficient
|
||||
|
||||
// Similar to above but is for the mob's overall protection, being the average of all slots.
|
||||
@@ -150,11 +156,11 @@ emp_act
|
||||
if(fire_stacks < 0) // Water makes you more conductive.
|
||||
siemens_value *= 1.5
|
||||
|
||||
return (siemens_value/max(total, 1))
|
||||
return (siemens_value / max(total, 1))
|
||||
|
||||
// Returns a number between 0 to 1, with 1 being total protection.
|
||||
/mob/living/carbon/human/get_shock_protection()
|
||||
return between(0, 1-get_siemens_coefficient_average(), 1)
|
||||
return min(1 - get_siemens_coefficient_average(), 1) // Don't go above 1, but negatives are fine.
|
||||
|
||||
// Returns a list of clothing that is currently covering def_zone.
|
||||
/mob/living/carbon/human/proc/get_clothing_list_organ(var/obj/item/organ/external/def_zone, var/type)
|
||||
@@ -173,6 +179,13 @@ emp_act
|
||||
var/list/protective_gear = def_zone.get_covering_clothing()
|
||||
for(var/obj/item/clothing/gear in protective_gear)
|
||||
protection += gear.armor[type]
|
||||
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
var/modifier_armor = LAZYACCESS(M.armor_percent, type)
|
||||
if(modifier_armor)
|
||||
protection += modifier_armor
|
||||
|
||||
return protection
|
||||
|
||||
/mob/living/carbon/human/proc/getsoak_organ(var/obj/item/organ/external/def_zone, var/type)
|
||||
@@ -182,6 +195,13 @@ emp_act
|
||||
var/list/protective_gear = def_zone.get_covering_clothing()
|
||||
for(var/obj/item/clothing/gear in protective_gear)
|
||||
soaked += gear.armorsoak[type]
|
||||
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
var/modifier_armor = LAZYACCESS(M.armor_flat, type)
|
||||
if(modifier_armor)
|
||||
soaked += modifier_armor
|
||||
|
||||
return soaked
|
||||
|
||||
// Checked in borer code
|
||||
|
||||
@@ -682,10 +682,13 @@
|
||||
if(bodytemperature >= species.heat_level_2)
|
||||
if(bodytemperature >= species.heat_level_3)
|
||||
burn_dam = HEAT_DAMAGE_LEVEL_3
|
||||
throw_alert("temp", /obj/screen/alert/hot, 3)
|
||||
else
|
||||
burn_dam = HEAT_DAMAGE_LEVEL_2
|
||||
throw_alert("temp", /obj/screen/alert/hot, 2)
|
||||
else
|
||||
burn_dam = HEAT_DAMAGE_LEVEL_1
|
||||
throw_alert("temp", /obj/screen/alert/hot, 1)
|
||||
|
||||
take_overall_damage(burn=burn_dam, used_weapon = "High Body Temperature")
|
||||
|
||||
@@ -709,6 +712,8 @@
|
||||
|
||||
take_overall_damage(burn=cold_dam, used_weapon = "Low Body Temperature")
|
||||
|
||||
else clear_alert("temp")
|
||||
|
||||
// Account for massive pressure differences. Done by Polymorph
|
||||
// Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense!
|
||||
if(status_flags & GODMODE)
|
||||
@@ -823,7 +828,19 @@
|
||||
|
||||
/mob/living/carbon/human/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to.
|
||||
var/thermal_protection_flags = get_heat_protection_flags(temperature)
|
||||
return get_thermal_protection(thermal_protection_flags)
|
||||
|
||||
. = get_thermal_protection(thermal_protection_flags)
|
||||
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
|
||||
|
||||
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
if(!isnull(M.heat_protection))
|
||||
. *= 1 - M.heat_protection
|
||||
|
||||
// Code that calls this expects 1 = immunity so we need to invert again.
|
||||
. = 1 - .
|
||||
. = min(., 1.0)
|
||||
|
||||
/mob/living/carbon/human/get_cold_protection(temperature)
|
||||
if(COLD_RESISTANCE in mutations)
|
||||
@@ -831,7 +848,20 @@
|
||||
|
||||
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
|
||||
var/thermal_protection_flags = get_cold_protection_flags(temperature)
|
||||
return get_thermal_protection(thermal_protection_flags)
|
||||
|
||||
. = get_thermal_protection(thermal_protection_flags)
|
||||
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
|
||||
|
||||
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
if(!isnull(M.cold_protection))
|
||||
// Invert the modifier values so they align with the current working value.
|
||||
. *= 1 - M.cold_protection
|
||||
|
||||
// Code that calls this expects 1 = immunity so we need to invert again.
|
||||
. = 1 - .
|
||||
. = min(., 1.0)
|
||||
|
||||
/mob/living/carbon/human/proc/get_thermal_protection(var/flags)
|
||||
.=0
|
||||
@@ -1298,6 +1328,11 @@
|
||||
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
||||
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : see_invisible_default
|
||||
|
||||
// Do this early so certain stuff gets turned off before vision is assigned.
|
||||
var/area/A = get_area(src)
|
||||
if(A?.no_spoilers)
|
||||
disable_spoiler_vision()
|
||||
|
||||
if(XRAY in mutations)
|
||||
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
|
||||
see_in_dark = 8
|
||||
@@ -1568,7 +1603,7 @@
|
||||
if(Pump)
|
||||
temp += Pump.standard_pulse_level - PULSE_NORM
|
||||
|
||||
if(round(vessel.get_reagent_amount("blood")) <= BLOOD_VOLUME_BAD) //how much blood do we have
|
||||
if(round(vessel.get_reagent_amount("blood")) <= species.blood_volume*species.blood_level_danger) //how much blood do we have
|
||||
temp = temp + 3 //not enough :(
|
||||
|
||||
if(status_flags & FAKEDEATH)
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
var/short_sighted // Permanent weldervision.
|
||||
var/blood_volume = 560 // Initial blood volume.
|
||||
var/bloodloss_rate = 1 // Multiplier for how fast a species bleeds out. Higher = Faster
|
||||
var/blood_level_safe = 0.85 //"Safe" blood level; above this, you're OK
|
||||
var/blood_level_warning = 0.75 //"Warning" blood level; above this, you're a bit woozy and will have low-level oxydamage (no more than 20, or 15 with inap)
|
||||
var/blood_level_danger = 0.6 //"Danger" blood level; above this, you'll rapidly take up to 50 oxyloss, and it will then steadily accumulate at a lower rate
|
||||
var/blood_level_fatal = 0.4 //"Fatal" blood level; below this, you take extremely high oxydamage
|
||||
var/hunger_factor = 0.05 // Multiplier for hunger.
|
||||
var/active_regen_mult = 1 // Multiplier for 'Regenerate' power speed, in human_powers.dm
|
||||
|
||||
|
||||
@@ -84,8 +84,16 @@
|
||||
heat_discomfort_strings = list(
|
||||
"Your feathers prickle in the heat.",
|
||||
"You feel uncomfortably warm.",
|
||||
"Your hands and feet feel hot as your body tries to regulate heat",
|
||||
)
|
||||
cold_discomfort_level = 180
|
||||
cold_discomfort_strings = list(
|
||||
"You feel a bit chilly.",
|
||||
"You fluff up your feathers against the cold.",
|
||||
"You move your arms closer to your body to shield yourself from the cold.",
|
||||
"You press your ears against your head to conserve heat",
|
||||
"You start to feel the cold on your skin",
|
||||
)
|
||||
|
||||
minimum_breath_pressure = 12 //Smaller, so needs less air
|
||||
|
||||
|
||||
@@ -309,7 +309,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
|
||||
base_icon.MapColors(rgb(tone[1],0,0),rgb(0,tone[2],0),rgb(0,0,tone[3]))
|
||||
|
||||
//Handle husk overlay.
|
||||
if(husk && ("overlay_husk" in icon_states(species.icobase)))
|
||||
if(husk && ("overlay_husk" in cached_icon_states(species.icobase)))
|
||||
var/icon/mask = new(base_icon)
|
||||
var/icon/husk_over = new(species.icobase,"overlay_husk")
|
||||
mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0)
|
||||
|
||||
@@ -44,7 +44,10 @@
|
||||
|
||||
//Check if we're on fire
|
||||
handle_fire()
|
||||
|
||||
|
||||
// Handle re-running ambience to mobs if they've remained in an area.
|
||||
handle_ambience()
|
||||
|
||||
//stuff in the stomach
|
||||
handle_stomach()
|
||||
|
||||
@@ -88,6 +91,12 @@
|
||||
/mob/living/proc/handle_stomach()
|
||||
return
|
||||
|
||||
/mob/living/proc/handle_ambience() // If you're in an ambient area and have not moved out of it for x time, we're going to play ambience again to you, to help break up the silence.
|
||||
if(world.time >= (lastareachange + 30 SECONDS)) // Every 30 seconds, we're going to run a 35% chance to play ambience.
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
A.play_ambience(src)
|
||||
|
||||
/mob/living/proc/update_pulling()
|
||||
if(pulling)
|
||||
if(incapacitated())
|
||||
@@ -118,11 +127,17 @@
|
||||
/mob/living/proc/handle_stunned()
|
||||
if(stunned)
|
||||
AdjustStunned(-1)
|
||||
throw_alert("stunned", /obj/screen/alert/stunned)
|
||||
else
|
||||
clear_alert("stunned")
|
||||
return stunned
|
||||
|
||||
/mob/living/proc/handle_weakened()
|
||||
if(weakened)
|
||||
AdjustWeakened(-1)
|
||||
throw_alert("weakened", /obj/screen/alert/weakened)
|
||||
else
|
||||
clear_alert("weakened")
|
||||
return weakened
|
||||
|
||||
/mob/living/proc/handle_stuttering()
|
||||
@@ -138,6 +153,9 @@
|
||||
/mob/living/proc/handle_drugged()
|
||||
if(druggy)
|
||||
druggy = max(druggy-1, 0)
|
||||
throw_alert("high", /obj/screen/alert/high)
|
||||
else
|
||||
clear_alert("high")
|
||||
return druggy
|
||||
|
||||
/mob/living/proc/handle_slurring()
|
||||
@@ -148,11 +166,17 @@
|
||||
/mob/living/proc/handle_paralysed()
|
||||
if(paralysis)
|
||||
AdjustParalysis(-1)
|
||||
throw_alert("paralyzed", /obj/screen/alert/paralyzed)
|
||||
else
|
||||
clear_alert("paralyzed")
|
||||
return paralysis
|
||||
|
||||
/mob/living/proc/handle_confused()
|
||||
if(confused)
|
||||
AdjustConfused(-1)
|
||||
throw_alert("confused", /obj/screen/alert/confused)
|
||||
else
|
||||
clear_alert("confused")
|
||||
return confused
|
||||
|
||||
/mob/living/proc/handle_disabilities()
|
||||
|
||||
@@ -196,6 +196,19 @@ default behaviour is:
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
// Called when something steps onto us. This allows for mulebots and vehicles to run things over. <3
|
||||
/mob/living/Crossed(var/atom/movable/AM) // Transplanting this from /mob/living/carbon/human/Crossed()
|
||||
if(AM == src || AM.is_incorporeal()) // We're not going to run over ourselves or ghosts
|
||||
return
|
||||
|
||||
if(istype(AM, /mob/living/bot/mulebot))
|
||||
var/mob/living/bot/mulebot/MB = AM
|
||||
MB.runOver(src)
|
||||
|
||||
if(istype(AM, /obj/vehicle))
|
||||
var/obj/vehicle/V = AM
|
||||
V.RunOver(src)
|
||||
|
||||
/mob/living/verb/succumb()
|
||||
set hidden = 1
|
||||
if ((src.health < 0 && src.health > (5-src.getMaxHealth()))) // Health below Zero but above 5-away-from-death, as before, but variable
|
||||
@@ -1363,3 +1376,8 @@ default behaviour is:
|
||||
clear_alert("weightless")
|
||||
else
|
||||
throw_alert("weightless", /obj/screen/alert/weightless)
|
||||
|
||||
// Tries to turn off things that let you see through walls, like mesons.
|
||||
// Each mob does vision a bit differently so this is just for inheritence and also so overrided procs can make the vision apply instantly if they call `..()`.
|
||||
/mob/living/proc/disable_spoiler_vision()
|
||||
handle_vision()
|
||||
@@ -29,4 +29,5 @@ var/global/list/empty_playable_ai_cores = list()
|
||||
global_announcer.autosay("[src] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
|
||||
|
||||
//Handle job slot/tater cleanup.
|
||||
set_respawn_timer()
|
||||
clear_client()
|
||||
@@ -34,6 +34,8 @@
|
||||
scan_type = "robot"
|
||||
else if(istype(M, /mob/living/carbon/human))
|
||||
scan_type = "prosthetics"
|
||||
else if(istype(M, /obj/mecha))
|
||||
scan_type = "mecha"
|
||||
else
|
||||
to_chat(user, "<font color='red'>You can't analyze non-robotic things!</font>")
|
||||
return
|
||||
@@ -95,5 +97,37 @@
|
||||
if(!organ_found)
|
||||
to_chat(user, "No prosthetics located.")
|
||||
|
||||
if("mecha")
|
||||
|
||||
var/obj/mecha/Mecha = M
|
||||
|
||||
var/integrity = Mecha.health/initial(Mecha.health)*100
|
||||
var/cell_charge = Mecha.get_charge()
|
||||
var/tank_pressure = Mecha.internal_tank ? round(Mecha.internal_tank.return_pressure(),0.01) : "None"
|
||||
var/tank_temperature = Mecha.internal_tank ? Mecha.internal_tank.return_temperature() : "Unknown"
|
||||
var/cabin_pressure = round(Mecha.return_pressure(),0.01)
|
||||
|
||||
var/output = {"<span class='notice'>Analyzing Results for \the [Mecha]:</span><br>
|
||||
<b>Chassis Integrity: </b> [integrity]%<br>
|
||||
<b>Powercell charge: </b>[isnull(cell_charge)?"No powercell installed":"[Mecha.cell.percent()]%"]<br>
|
||||
<b>Air source: </b>[Mecha.use_internal_tank?"Internal Airtank":"Environment"]<br>
|
||||
<b>Airtank pressure: </b>[tank_pressure]kPa<br>
|
||||
<b>Airtank temperature: </b>[tank_temperature]K|[tank_temperature - T0C]°C<br>
|
||||
<b>Cabin pressure: </b>[cabin_pressure>WARNING_HIGH_PRESSURE ? "<font color='red'>[cabin_pressure]</font>": cabin_pressure]kPa<br>
|
||||
<b>Cabin temperature: </b> [Mecha.return_temperature()]K|[Mecha.return_temperature() - T0C]°C<br>
|
||||
<b>DNA Lock: </b> [Mecha.dna?"Mecha.dna":"Not Found"]<br>
|
||||
"}
|
||||
|
||||
to_chat(user, output)
|
||||
to_chat(user, "<hr>")
|
||||
to_chat(user, "<span class='notice'>Internal Diagnostics:</span>")
|
||||
for(var/slot in Mecha.internal_components)
|
||||
var/obj/item/mecha_parts/component/MC = Mecha.internal_components[slot]
|
||||
to_chat(user, "[MC?"[slot]: [MC] <span class='notice'>[round((MC.integrity / MC.max_integrity) * 100, 0.1)]%</span> integrity. [MC.get_efficiency() * 100] Operational capacity.":"<span class='warning'>[slot]: Component Not Found</span>"]")
|
||||
|
||||
to_chat(user, "<hr>")
|
||||
to_chat(user, "<span class='notice'>General Statistics:</span>")
|
||||
to_chat(user, "<span class='notice'>Movement Weight: [Mecha.get_step_delay()]</span><br>")
|
||||
|
||||
src.add_fingerprint(user)
|
||||
return
|
||||
|
||||
@@ -153,7 +153,13 @@
|
||||
/mob/living/silicon/robot/handle_regular_hud_updates()
|
||||
var/fullbright = FALSE
|
||||
var/seemeson = FALSE
|
||||
if (src.stat == 2 || (XRAY in mutations) || (src.sight_mode & BORGXRAY))
|
||||
|
||||
var/area/A = get_area(src)
|
||||
if(A?.no_spoilers)
|
||||
disable_spoiler_vision()
|
||||
|
||||
|
||||
if (src.stat == DEAD || (XRAY in mutations) || (src.sight_mode & BORGXRAY))
|
||||
src.sight |= SEE_TURFS
|
||||
src.sight |= SEE_MOBS
|
||||
src.sight |= SEE_OBJS
|
||||
@@ -187,13 +193,14 @@
|
||||
src.sight &= ~SEE_OBJS
|
||||
src.see_in_dark = 8
|
||||
src.see_invisible = SEE_INVISIBLE_NOLIGHTING
|
||||
else if (src.stat != 2)
|
||||
else if (src.stat != DEAD)
|
||||
src.sight &= ~SEE_MOBS
|
||||
src.sight &= ~SEE_TURFS
|
||||
src.sight &= ~SEE_OBJS
|
||||
src.see_in_dark = 8 // see_in_dark means you can FAINTLY see in the dark, humans have a range of 3 or so, tajaran have it at 8
|
||||
src.see_invisible = SEE_INVISIBLE_LIVING // This is normal vision (25), setting it lower for normal vision means you don't "see" things like darkness since darkness
|
||||
// has a "invisible" value of 15
|
||||
|
||||
plane_holder.set_vis(VIS_FULLBRIGHT,fullbright)
|
||||
plane_holder.set_vis(VIS_MESONS,seemeson)
|
||||
..()
|
||||
|
||||
@@ -1099,3 +1099,19 @@
|
||||
if(module_active && istype(module_active,/obj/item/weapon/gripper))
|
||||
var/obj/item/weapon/gripper/G = module_active
|
||||
G.drop_item_nm()
|
||||
|
||||
/mob/living/silicon/robot/disable_spoiler_vision()
|
||||
if(sight_mode & (BORGMESON|BORGMATERIAL|BORGXRAY)) // Whyyyyyyyy have seperate defines.
|
||||
var/i = 0
|
||||
// Borg inventory code is very . . interesting and as such, unequiping a specific item requires jumping through some (for) loops.
|
||||
var/current_selection_index = get_selected_module() // Will be 0 if nothing is selected.
|
||||
for(var/thing in list(module_state_1, module_state_2, module_state_3))
|
||||
i++
|
||||
if(istype(thing, /obj/item/borg/sight))
|
||||
var/obj/item/borg/sight/S = thing
|
||||
if(S.sight_mode & (BORGMESON|BORGMATERIAL|BORGXRAY))
|
||||
select_module(i)
|
||||
uneq_active()
|
||||
|
||||
if(current_selection_index) // Select what the player had before if possible.
|
||||
select_module(current_selection_index)
|
||||
@@ -140,7 +140,18 @@
|
||||
|
||||
// Cold stuff.
|
||||
/mob/living/simple_mob/get_cold_protection()
|
||||
return cold_resist
|
||||
. = cold_resist
|
||||
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
|
||||
|
||||
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
if(!isnull(M.cold_protection))
|
||||
. *= 1 - M.cold_protection
|
||||
|
||||
// Code that calls this expects 1 = immunity so we need to invert again.
|
||||
. = 1 - .
|
||||
. = min(., 1.0)
|
||||
|
||||
|
||||
// Fire stuff. Not really exciting at the moment.
|
||||
@@ -154,7 +165,18 @@
|
||||
return
|
||||
|
||||
/mob/living/simple_mob/get_heat_protection()
|
||||
return heat_resist
|
||||
. = heat_resist
|
||||
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
|
||||
|
||||
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
if(!isnull(M.heat_protection))
|
||||
. *= 1 - M.heat_protection
|
||||
|
||||
// Code that calls this expects 1 = immunity so we need to invert again.
|
||||
. = 1 - .
|
||||
. = min(., 1.0)
|
||||
|
||||
// Electricity
|
||||
/mob/living/simple_mob/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null)
|
||||
@@ -170,7 +192,18 @@
|
||||
s.start()
|
||||
|
||||
/mob/living/simple_mob/get_shock_protection()
|
||||
return shock_resist
|
||||
. = shock_resist
|
||||
. = 1 - . // Invert from 1 = immunity to 0 = immunity.
|
||||
|
||||
// Doing it this way makes multiplicative stacking not get out of hand, so two modifiers that give 0.5 protection will be combined to 0.75 in the end.
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
if(!isnull(M.siemens_coefficient))
|
||||
. *= M.siemens_coefficient
|
||||
|
||||
// Code that calls this expects 1 = immunity so we need to invert again.
|
||||
. = 1 - .
|
||||
. = min(., 1.0)
|
||||
|
||||
// Shot with taser/stunvolver
|
||||
/mob/living/simple_mob/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null)
|
||||
@@ -218,17 +251,29 @@
|
||||
// Armor
|
||||
/mob/living/simple_mob/getarmor(def_zone, attack_flag)
|
||||
var/armorval = armor[attack_flag]
|
||||
if(!armorval)
|
||||
return 0
|
||||
else
|
||||
return armorval
|
||||
if(isnull(armorval))
|
||||
armorval = 0
|
||||
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
var/modifier_armor = LAZYACCESS(M.armor_percent, attack_flag)
|
||||
if(modifier_armor)
|
||||
armorval += modifier_armor
|
||||
|
||||
return armorval
|
||||
|
||||
/mob/living/simple_mob/getsoak(def_zone, attack_flag)
|
||||
var/armorval = armor_soak[attack_flag]
|
||||
if(!armorval)
|
||||
return 0
|
||||
else
|
||||
return armorval
|
||||
if(isnull(armorval))
|
||||
armorval = 0
|
||||
|
||||
for(var/thing in modifiers)
|
||||
var/datum/modifier/M = thing
|
||||
var/modifier_armor = LAZYACCESS(M.armor_flat, attack_flag)
|
||||
if(modifier_armor)
|
||||
armorval += modifier_armor
|
||||
|
||||
return armorval
|
||||
|
||||
// Lightning
|
||||
/mob/living/simple_mob/lightning_act()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/mob/living/simple_mob/instantiate_hud(var/datum/hud/hud)
|
||||
if(!client)
|
||||
return //Why bother.
|
||||
/mob/living/simple_mob/create_mob_hud(datum/hud/HUD)
|
||||
..()
|
||||
|
||||
var/ui_style = 'icons/mob/screen1_animal.dmi'
|
||||
if(ui_icons)
|
||||
@@ -14,9 +13,9 @@
|
||||
var/list/hotkeybuttons = list()
|
||||
var/list/slot_info = list()
|
||||
|
||||
hud.adding = adding
|
||||
hud.other = other
|
||||
hud.hotkeybuttons = hotkeybuttons
|
||||
HUD.adding = adding
|
||||
HUD.other = other
|
||||
HUD.hotkeybuttons = hotkeybuttons
|
||||
|
||||
var/list/hud_elements = list()
|
||||
var/obj/screen/using
|
||||
@@ -65,8 +64,8 @@
|
||||
using.screen_loc = ui_acti
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
hud.action_intent = using
|
||||
HUD.adding += using
|
||||
HUD.action_intent = using
|
||||
|
||||
hud_elements |= using
|
||||
|
||||
@@ -82,8 +81,8 @@
|
||||
using.screen_loc = ui_acti
|
||||
using.alpha = ui_alpha
|
||||
using.layer = LAYER_HUD_ITEM //These sit on the intent box
|
||||
hud.adding += using
|
||||
hud.help_intent = using
|
||||
HUD.adding += using
|
||||
HUD.help_intent = using
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
@@ -94,8 +93,8 @@
|
||||
using.screen_loc = ui_acti
|
||||
using.alpha = ui_alpha
|
||||
using.layer = LAYER_HUD_ITEM
|
||||
hud.adding += using
|
||||
hud.disarm_intent = using
|
||||
HUD.adding += using
|
||||
HUD.disarm_intent = using
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
@@ -106,8 +105,8 @@
|
||||
using.screen_loc = ui_acti
|
||||
using.alpha = ui_alpha
|
||||
using.layer = LAYER_HUD_ITEM
|
||||
hud.adding += using
|
||||
hud.grab_intent = using
|
||||
HUD.adding += using
|
||||
HUD.grab_intent = using
|
||||
|
||||
ico = new(ui_style, "black")
|
||||
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
|
||||
@@ -118,8 +117,8 @@
|
||||
using.screen_loc = ui_acti
|
||||
using.alpha = ui_alpha
|
||||
using.layer = LAYER_HUD_ITEM
|
||||
hud.adding += using
|
||||
hud.hurt_intent = using
|
||||
HUD.adding += using
|
||||
HUD.hurt_intent = using
|
||||
|
||||
//Move intent (walk/run)
|
||||
using = new /obj/screen()
|
||||
@@ -129,8 +128,8 @@
|
||||
using.screen_loc = ui_movi
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
hud.move_intent = using
|
||||
HUD.adding += using
|
||||
HUD.move_intent = using
|
||||
|
||||
//Resist button
|
||||
using = new /obj/screen()
|
||||
@@ -140,7 +139,7 @@
|
||||
using.screen_loc = ui_pull_resist
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.hotkeybuttons += using
|
||||
HUD.hotkeybuttons += using
|
||||
|
||||
//Pull button
|
||||
pullin = new /obj/screen()
|
||||
@@ -148,7 +147,7 @@
|
||||
pullin.icon_state = "pull0"
|
||||
pullin.name = "pull"
|
||||
pullin.screen_loc = ui_pull_resist
|
||||
hud.hotkeybuttons += pullin
|
||||
HUD.hotkeybuttons += pullin
|
||||
hud_elements |= pullin
|
||||
|
||||
//Health status
|
||||
@@ -159,8 +158,6 @@
|
||||
healths.screen_loc = ui_health
|
||||
hud_elements |= healths
|
||||
|
||||
|
||||
|
||||
pain = new /obj/screen( null )
|
||||
|
||||
zone_sel = new /obj/screen/zone_sel( null )
|
||||
@@ -181,7 +178,7 @@
|
||||
using.screen_loc = ui_drop_throw
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.hotkeybuttons += using
|
||||
HUD.hotkeybuttons += using
|
||||
|
||||
//Equip detail
|
||||
using = new /obj/screen()
|
||||
@@ -191,7 +188,7 @@
|
||||
using.screen_loc = ui_equip
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
HUD.adding += using
|
||||
|
||||
//Hand slots themselves
|
||||
inv_box = new /obj/screen/inventory/hand()
|
||||
@@ -205,8 +202,8 @@
|
||||
inv_box.slot_id = slot_r_hand
|
||||
inv_box.color = ui_color
|
||||
inv_box.alpha = ui_alpha
|
||||
hud.r_hand_hud_object = inv_box
|
||||
hud.adding += inv_box
|
||||
HUD.r_hand_hud_object = inv_box
|
||||
HUD.adding += inv_box
|
||||
slot_info["[slot_r_hand]"] = inv_box.screen_loc
|
||||
|
||||
inv_box = new /obj/screen/inventory/hand()
|
||||
@@ -220,8 +217,8 @@
|
||||
inv_box.slot_id = slot_l_hand
|
||||
inv_box.color = ui_color
|
||||
inv_box.alpha = ui_alpha
|
||||
hud.l_hand_hud_object = inv_box
|
||||
hud.adding += inv_box
|
||||
HUD.l_hand_hud_object = inv_box
|
||||
HUD.adding += inv_box
|
||||
slot_info["[slot_l_hand]"] = inv_box.screen_loc
|
||||
|
||||
//Swaphand titlebar
|
||||
@@ -232,7 +229,7 @@
|
||||
using.screen_loc = ui_swaphand1
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
HUD.adding += using
|
||||
|
||||
using = new /obj/screen/inventory()
|
||||
using.name = "hand"
|
||||
@@ -241,7 +238,7 @@
|
||||
using.screen_loc = ui_swaphand2
|
||||
using.color = ui_color
|
||||
using.alpha = ui_alpha
|
||||
hud.adding += using
|
||||
HUD.adding += using
|
||||
|
||||
//Throw button
|
||||
throw_icon = new /obj/screen()
|
||||
@@ -251,15 +248,13 @@
|
||||
throw_icon.screen_loc = ui_drop_throw
|
||||
throw_icon.color = ui_color
|
||||
throw_icon.alpha = ui_alpha
|
||||
hud.hotkeybuttons += throw_icon
|
||||
HUD.hotkeybuttons += throw_icon
|
||||
hud_elements |= throw_icon
|
||||
|
||||
extra_huds(hud,ui_style,hud_elements)
|
||||
extra_huds(HUD, HUD.ui_style, hud_elements)
|
||||
|
||||
client.screen = list()
|
||||
|
||||
client.screen += hud_elements
|
||||
client.screen += adding + hotkeybuttons
|
||||
client.screen += client.void
|
||||
|
||||
return
|
||||
if(client)
|
||||
client.screen = list()
|
||||
client.screen += hud_elements
|
||||
client.screen += adding + hotkeybuttons
|
||||
client.screen += client.void
|
||||
|
||||
@@ -54,4 +54,4 @@
|
||||
/obj/item/weapon/reagent_containers/food/snacks/meat/crab
|
||||
name = "meat"
|
||||
desc = "A chunk of meat."
|
||||
icon_state = "crustacean-meat"
|
||||
icon_state = "crustacean-meat"
|
||||
@@ -31,6 +31,17 @@
|
||||
/turf/simulated/floor/water
|
||||
)
|
||||
|
||||
var/randomize_location = TRUE
|
||||
|
||||
/mob/living/simple_mob/animal/passive/fish/Initialize()
|
||||
..()
|
||||
|
||||
if(!default_pixel_x && randomize_location)
|
||||
default_pixel_x = rand(-12, 12)
|
||||
|
||||
if(!default_pixel_y && randomize_location)
|
||||
default_pixel_y = rand(-6, 10)
|
||||
|
||||
// Makes the AI unable to willingly go on land.
|
||||
/mob/living/simple_mob/animal/passive/fish/IMove(newloc)
|
||||
if(is_type_in_list(newloc, suitable_turf_types))
|
||||
@@ -39,6 +50,11 @@
|
||||
|
||||
// Take damage if we are not in water
|
||||
/mob/living/simple_mob/animal/passive/fish/handle_breathing()
|
||||
if(istype(loc, /obj/item/glass_jar/fish))
|
||||
var/obj/item/glass_jar/fish/F = loc
|
||||
if(F.filled)
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(T && !is_type_in_list(T, suitable_turf_types))
|
||||
if(prob(50))
|
||||
@@ -178,8 +194,8 @@
|
||||
dorsal_image.color = dorsal_color
|
||||
belly_image.color = belly_color
|
||||
|
||||
overlays += dorsal_image
|
||||
overlays += belly_image
|
||||
add_overlay(dorsal_image)
|
||||
add_overlay(belly_image)
|
||||
|
||||
/datum/category_item/catalogue/fauna/rockfish
|
||||
name = "Sivian Fauna - Rock Puffer"
|
||||
@@ -234,6 +250,7 @@
|
||||
/mob/living/simple_mob/animal/passive/fish/rockfish/Initialize()
|
||||
..()
|
||||
head_color = rgb(rand(min_red,max_red), rand(min_green,max_green), rand(min_blue,max_blue))
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_mob/animal/passive/fish/rockfish/update_icon()
|
||||
overlays.Cut()
|
||||
@@ -245,7 +262,7 @@
|
||||
|
||||
head_image.color = head_color
|
||||
|
||||
overlays += head_image
|
||||
add_overlay(head_image)
|
||||
|
||||
/datum/category_item/catalogue/fauna/solarfish
|
||||
name = "Sivian Fauna - Solar Fin"
|
||||
|
||||
@@ -231,4 +231,14 @@
|
||||
name = "Spice"
|
||||
real_name = "Spice" //Intended to hold the name without altering it.
|
||||
gender = FEMALE
|
||||
desc = "It's a tamaskan, the name Spice can be found on its collar."
|
||||
desc = "It's a tamaskan, the name Spice can be found on its collar."
|
||||
|
||||
// Brittany Spaniel
|
||||
|
||||
/mob/living/simple_mob/animal/passive/dog/brittany
|
||||
name = "brittany"
|
||||
real_name = "brittany"
|
||||
desc = "It's a brittany spaniel."
|
||||
icon_state = "brittany"
|
||||
icon_living = "brittany"
|
||||
icon_dead = "brittany_dead"
|
||||
@@ -167,3 +167,4 @@
|
||||
holder.face_atom(A)
|
||||
|
||||
F.energy = max(0, F.energy - 1) // The AI will eventually flee.
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// Complete chumps but a little bit hardier than mice.
|
||||
|
||||
/datum/category_item/catalogue/fauna/hare
|
||||
name = "Sivian Fauna - Ice Hare"
|
||||
desc = "Classification: S Lepus petropellis\
|
||||
<br><br>\
|
||||
Hard-skinned, horned herbivores common on the glacial regions of Sif. \
|
||||
The Ice Hare lives in colonies of up to thirty individuals dug beneath thick ice sheets for protection from many burrowing predators. \
|
||||
Their diet consists of mostly moss and lichens, though this is supplemented with the consumption of hard mineral pebbles, which it swallows whole, \
|
||||
which form the small, hard, 'ice-like' scales of the animal. \
|
||||
The Ice Hare is almost completely harmless to sapients, with relatively blunt claws and a weak jaw. Its main forms of self-defense are its speed, \
|
||||
and two sharp head spikes whose 'ear-like' appearance gave the species its common name."
|
||||
value = CATALOGUER_REWARD_EASY
|
||||
|
||||
/mob/living/simple_mob/animal/passive/hare
|
||||
name = "ice hare"
|
||||
real_name = "ice hare"
|
||||
desc = "A small horned herbivore with a tough 'ice-like' hide."
|
||||
tt_desc = "S Lepus petropellis" //Sivian hare rockskin
|
||||
catalogue_data = list(/datum/category_item/catalogue/fauna/hare)
|
||||
|
||||
icon_state = "hare"
|
||||
icon_living = "hare"
|
||||
icon_dead = "hare_dead"
|
||||
icon_rest = "hare_rest"
|
||||
|
||||
maxHealth = 20
|
||||
health = 20
|
||||
|
||||
armor = list(
|
||||
"melee" = 30,
|
||||
"bullet" = 5,
|
||||
"laser" = 5,
|
||||
"energy" = 0,
|
||||
"bomb" = 10,
|
||||
"bio" = 0,
|
||||
"rad" = 0
|
||||
)
|
||||
|
||||
armor_soak = list(
|
||||
"melee" = 5,
|
||||
"bullet" = 0,
|
||||
"laser" = 0,
|
||||
"energy" = 0,
|
||||
"bomb" = 0,
|
||||
"bio" = 0,
|
||||
"rad" = 0
|
||||
)
|
||||
|
||||
movement_cooldown = 2
|
||||
|
||||
mob_size = MOB_SMALL
|
||||
pass_flags = PASSTABLE
|
||||
layer = MOB_LAYER
|
||||
density = 0
|
||||
|
||||
response_help = "pets"
|
||||
response_disarm = "nudges"
|
||||
response_harm = "kicks"
|
||||
|
||||
meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
|
||||
|
||||
say_list_type = /datum/say_list/hare
|
||||
|
||||
/datum/say_list/hare
|
||||
speak = list("Snrf...","Crk!")
|
||||
emote_hear = list("crackles","sniffles")
|
||||
emote_see = list("stomps the ground", "sniffs the air", "chews on something")
|
||||
@@ -0,0 +1,143 @@
|
||||
//Very similar to frostflies, but with a non-lethal gas and less damaging, but less easy to protect from, projectiles.
|
||||
|
||||
/datum/category_item/catalogue/fauna/tymisian
|
||||
name = "Binman Fauna - Tymisian Moth"
|
||||
desc = "Classification: B Carabidae glacios \
|
||||
<br><br>\
|
||||
A meter-long fuzzy insect from the planet Binma. \
|
||||
A native of the Binman contintents of Telarus and Dalomee, the Tymisian Moth usually lives in communal \
|
||||
groups of upwards of thirty individuals, known as 'spuzzes', and typically breeds up to three times in its \
|
||||
fifteen year natural lifespan. \
|
||||
<br>\
|
||||
Though strictly herbivorous, the moth has an acute sense of smell which it uses to detect potential predators. \
|
||||
Impressively, the moth secretes an oily substance which it uses to coat collected material stored in 'soft pockets' \
|
||||
beneath each wing, which in turn attracts colonies of pungent bacteria. \
|
||||
When threatened, the moth will release this dust, which has a disorienting effect on most Binman species, as well as all known sapients. \
|
||||
<br>\
|
||||
The Tymisian Moth is considered an invasive species on Sif, and is believed to have been established from an illegally \
|
||||
released pet collection. Though less dangerous than in its native environment, the moth has nonetheless established a \
|
||||
similar symbiotic relationship with Sivian bacteria for its defense mechanism, and is still to be considered quite dangerous. \
|
||||
<br>\
|
||||
As an invasive species, individuals encountering the Tymisian Moth on Sif are requested to report the sighting to local wildlife \
|
||||
services, and remove or destroy the creature if it is safe to do so."
|
||||
value = CATALOGUER_REWARD_MEDIUM
|
||||
|
||||
/mob/living/simple_mob/animal/sif/tymisian
|
||||
name = "Tymisian Moth"
|
||||
desc = "A huge, fuzzy insect with a disorienting dust."
|
||||
tt_desc = "B Lepidoptera cinereus"
|
||||
catalogue_data = list(/datum/category_item/catalogue/fauna/tymisian)
|
||||
|
||||
faction = "spiders" //Hostile to most mobs, not all.
|
||||
|
||||
icon_state = "moth"
|
||||
icon_living = "moth"
|
||||
icon_dead = "moth_dead"
|
||||
icon_rest = "moth_dead"
|
||||
icon = 'icons/mob/animal.dmi'
|
||||
|
||||
maxHealth = 80
|
||||
health = 80
|
||||
|
||||
hovering = TRUE
|
||||
|
||||
movement_cooldown = 0.5
|
||||
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 10
|
||||
base_attack_cooldown = 1.5 SECONDS
|
||||
attacktext = list("nipped", "bit", "pinched")
|
||||
|
||||
projectiletype = /obj/item/projectile/energy/blob
|
||||
|
||||
special_attack_cooldown = 10 SECONDS
|
||||
special_attack_min_range = 0
|
||||
special_attack_max_range = 6
|
||||
|
||||
var/energy = 100
|
||||
var/max_energy = 100
|
||||
|
||||
var/datum/effect/effect/system/smoke_spread/mothspore/smoke_spore
|
||||
|
||||
say_list_type = /datum/say_list/tymisian
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/ranged/kiting/threatening/frostfly //Uses frostfly AI, since so similar mechanically
|
||||
|
||||
/datum/say_list/tymisian
|
||||
speak = list("Zzzz.", "Rrr...", "Zzt?")
|
||||
emote_see = list("grooms itself","sprinkles dust from its wings", "rubs its mandibles")
|
||||
emote_hear = list("chitters", "clicks", "rattles")
|
||||
|
||||
say_understood = list("Ssst.")
|
||||
say_cannot = list("Zzrt.")
|
||||
say_maybe_target = list("Rr?")
|
||||
say_got_target = list("Rrrrt!")
|
||||
say_threaten = list("Kszsz.","Kszzt...","Kzzi!")
|
||||
say_stand_down = list("Sss.","Zt.","! clicks.")
|
||||
say_escalate = list("Rszt!")
|
||||
|
||||
threaten_sound = 'sound/effects/spray3.ogg'
|
||||
stand_down_sound = 'sound/effects/squelch1.ogg'
|
||||
|
||||
|
||||
/obj/effect/effect/smoke/elemental/mothspore
|
||||
name = "spore cloud"
|
||||
desc = "A dust cloud filled with disorienting bacterial spores."
|
||||
color = "#80AB82"
|
||||
|
||||
/obj/effect/effect/smoke/elemental/mothspore/affect(mob/living/L) //Similar to a very weak flash, but depends on breathing instead of eye protection.
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
if(C.stat != DEAD)
|
||||
if(C.needs_to_breathe())
|
||||
var/spore_strength = 5
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
H.Confuse(spore_strength)
|
||||
H.eye_blurry = max(H.eye_blurry, spore_strength)
|
||||
H.adjustHalLoss(10 * (spore_strength / 5))
|
||||
|
||||
/datum/effect/effect/system/smoke_spread/mothspore
|
||||
smoke_type = /obj/effect/effect/smoke/elemental/mothspore
|
||||
|
||||
/mob/living/simple_mob/animal/sif/tymisian/do_special_attack(atom/A)
|
||||
. = TRUE
|
||||
switch(a_intent)
|
||||
if(I_DISARM)
|
||||
if(energy < 20)
|
||||
return FALSE
|
||||
|
||||
energy -= 20
|
||||
|
||||
if(smoke_spore)
|
||||
smoke_spore.set_up(7,0,src)
|
||||
smoke_spore.start()
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_mob/animal/sif/tymisian/Initialize()
|
||||
..()
|
||||
smoke_spore = new
|
||||
verbs += /mob/living/proc/ventcrawl
|
||||
verbs += /mob/living/proc/hide
|
||||
|
||||
/mob/living/simple_mob/animal/sif/tymisian/handle_special()
|
||||
..()
|
||||
|
||||
if(energy < max_energy)
|
||||
energy++
|
||||
|
||||
/mob/living/simple_mob/animal/sif/tymisian/Stat()
|
||||
..()
|
||||
if(client.statpanel == "Status")
|
||||
statpanel("Status")
|
||||
if(emergency_shuttle)
|
||||
var/eta_status = emergency_shuttle.get_status_panel_eta()
|
||||
if(eta_status)
|
||||
stat(null, eta_status)
|
||||
stat("Energy", energy)
|
||||
|
||||
/mob/living/simple_mob/animal/sif/tymisian/should_special_attack(atom/A)
|
||||
if(energy >= 20)
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -0,0 +1,51 @@
|
||||
/datum/category_item/catalogue/fauna/pillbug
|
||||
name = "Sivian Fauna - Fire Bug"
|
||||
desc = "Classification: S Armadillidiidae calidi \
|
||||
<br><br>\
|
||||
A 10 inch long, hard-shelled insect with a natural adaption to living around terrestrial lava vents. \
|
||||
The fire bug's hard shell offers extremely effective protection against most threats, \
|
||||
though the species is almost completely docile, and will prefer to continue grazing on its diet of volcanic micro-flora \
|
||||
rather than defend itself in most situations.\
|
||||
<br>\
|
||||
The fire bug is a curiosity to most on the frontier, offering little in the way of meaningful food or resources, \
|
||||
though at least one Sivian fashion designer has used their iridescent red shells to create striking, hand-made garments."
|
||||
value = CATALOGUER_REWARD_EASY
|
||||
|
||||
/mob/living/simple_mob/animal/passive/pillbug
|
||||
name = "fire bug"
|
||||
desc = "A tiny plated bug found in Sif's volcanic regions."
|
||||
tt_desc = "S Armadillidiidae calidi"
|
||||
catalogue_data = list(/datum/category_item/catalogue/fauna/pillbug)
|
||||
|
||||
icon_state = "pillbug"
|
||||
icon_living = "pillbug"
|
||||
icon_dead = "pillbug_dead"
|
||||
|
||||
health = 15
|
||||
maxHealth = 15
|
||||
mob_size = MOB_MINISCULE
|
||||
|
||||
response_help = "gently touches"
|
||||
response_disarm = "rolls over"
|
||||
response_harm = "stomps on"
|
||||
|
||||
armor = list(
|
||||
"melee" = 30,
|
||||
"bullet" = 10,
|
||||
"laser" = 50,
|
||||
"energy" = 50,
|
||||
"bomb" = 30,
|
||||
"bio" = 100,
|
||||
"rad" = 100
|
||||
)
|
||||
|
||||
// The frostfly's body is incredibly cold at all times, natural resistance to things trying to burn it.
|
||||
armor_soak = list(
|
||||
"melee" = 10,
|
||||
"bullet" = 0,
|
||||
"laser" = 10,
|
||||
"energy" = 10,
|
||||
"bomb" = 0,
|
||||
"bio" = 0,
|
||||
"rad" = 0
|
||||
)
|
||||
@@ -0,0 +1,61 @@
|
||||
// Somewhere between a fox and a weasel. Doesn't mess with stuff significantly bigger than it, but you don't want to get on its bad side.
|
||||
|
||||
/datum/category_item/catalogue/fauna/siffet
|
||||
name = "Sivian Fauna - Siffet"
|
||||
desc = "Classification: S Pruinaeictis velocis\
|
||||
<br><br>\
|
||||
The Siffet, or Sivian Frost Weasel is a small, solitary predator known for its striking ability to take down prey up to twice their size. \
|
||||
The majority of the Siffet's adult life is spent in isolation, prowling large territories in Sif's tundra regions, \
|
||||
only seeking out other individuals during the summer mating season, when deadly battles for dominance are common. \
|
||||
Though mostly docile towards adult humans and other large sapients, the Siffet has been known to target children and smaller species as prey, \
|
||||
and a provoked Siffet can be a danger to even the most experienced handler due to its quick movement and surprisingly powerful jaws. \
|
||||
The Siffet is sometimes hunted for its remarkably soft pelt, though most is obtained through fur farming."
|
||||
value = CATALOGUER_REWARD_MEDIUM
|
||||
|
||||
/mob/living/simple_mob/animal/sif/siffet
|
||||
name = "siffet"
|
||||
desc = "A small, solitary predator with silky fur. Despite its size, the Siffet is ferocious when provoked."
|
||||
tt_desc = "S Pruinaeictis velocis" //Sivian frost weasel, fast
|
||||
catalogue_data = list(/datum/category_item/catalogue/fauna/siffet)
|
||||
|
||||
faction = "siffet"
|
||||
|
||||
mob_size = MOB_SMALL
|
||||
|
||||
icon_state = "siffet"
|
||||
icon_living = "siffet"
|
||||
icon_dead = "siffet_dead"
|
||||
icon = 'icons/mob/animal.dmi'
|
||||
|
||||
maxHealth = 60
|
||||
health = 60
|
||||
|
||||
movement_cooldown = 0
|
||||
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 15
|
||||
base_attack_cooldown = 1 SECOND
|
||||
attack_sharp = 1
|
||||
attacktext = list("sliced", "snapped", "gnawed")
|
||||
|
||||
say_list_type = /datum/say_list/siffet
|
||||
ai_holder_type = /datum/ai_holder/simple_mob/siffet
|
||||
|
||||
/datum/say_list/siffet
|
||||
speak = list("Yap!", "Heh!", "Huff.")
|
||||
emote_see = list("sniffs its surroundings","flicks its ears", "scratches the ground")
|
||||
emote_hear = list("chatters", "huffs")
|
||||
|
||||
/datum/ai_holder/simple_mob/siffet
|
||||
hostile = TRUE
|
||||
retaliate = TRUE
|
||||
|
||||
/datum/ai_holder/simple_mob/siffet/post_melee_attack(atom/A) //Evasive
|
||||
if(holder.Adjacent(A))
|
||||
holder.IMove(get_step(holder, pick(alldirs)))
|
||||
holder.face_atom(A)
|
||||
|
||||
/mob/living/simple_mob/animal/sif/siffet/IIsAlly(mob/living/L)
|
||||
. = ..()
|
||||
if(!. && L.mob_size > 10) //Attacks things it considers small enough to take on, otherwise only attacks if attacked.
|
||||
return TRUE
|
||||
+43
-33
@@ -333,46 +333,56 @@
|
||||
return
|
||||
*/
|
||||
|
||||
/mob/proc/set_respawn_timer(var/time)
|
||||
// Try to figure out what time to use
|
||||
|
||||
// Special cases, can never respawn
|
||||
if(ticker?.mode?.deny_respawn)
|
||||
time = -1
|
||||
else if(!config.abandon_allowed)
|
||||
time = -1
|
||||
else if(!config.respawn)
|
||||
time = -1
|
||||
|
||||
// Special case for observing before game start
|
||||
else if(ticker?.current_state <= GAME_STATE_SETTING_UP)
|
||||
time = 1 MINUTE
|
||||
|
||||
// Wasn't given a time, use the config time
|
||||
else if(!time)
|
||||
time = config.respawn_time
|
||||
|
||||
var/keytouse = ckey
|
||||
// Try harder to find a key to use
|
||||
if(!keytouse && key)
|
||||
keytouse = ckey(key)
|
||||
else if(!keytouse && mind?.key)
|
||||
keytouse = ckey(mind.key)
|
||||
|
||||
GLOB.respawn_timers[keytouse] = world.time + time
|
||||
|
||||
/mob/observer/dead/set_respawn_timer()
|
||||
if(config.antag_hud_restricted && has_enabled_antagHUD)
|
||||
..(-1)
|
||||
else
|
||||
return // Don't set it, no need
|
||||
|
||||
/mob/verb/abandon_mob()
|
||||
set name = "Respawn"
|
||||
set name = "Return to Menu"
|
||||
set category = "OOC"
|
||||
|
||||
if (!( config.abandon_allowed ))
|
||||
to_chat(usr, "<span class='notice'>Respawn is disabled.</span>")
|
||||
return
|
||||
if ((stat != 2 || !( ticker )))
|
||||
if(stat != DEAD || !ticker)
|
||||
to_chat(usr, "<span class='notice'><B>You must be dead to use this!</B></span>")
|
||||
return
|
||||
if (ticker.mode && ticker.mode.deny_respawn) //BS12 EDIT
|
||||
to_chat(usr, "<span class='notice'>Respawn is disabled for this roundtype.</span>")
|
||||
return
|
||||
else
|
||||
var/deathtime = world.time - src.timeofdeath
|
||||
if(istype(src,/mob/observer/dead))
|
||||
var/mob/observer/dead/G = src
|
||||
if(G.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
|
||||
to_chat(usr, "<font color='blue'><B>By using the antagHUD you forfeit the ability to join the round.</B></font>")
|
||||
return
|
||||
var/deathtimeminutes = round(deathtime / 600)
|
||||
var/pluralcheck = "minute"
|
||||
if(deathtimeminutes == 0)
|
||||
pluralcheck = ""
|
||||
else if(deathtimeminutes == 1)
|
||||
pluralcheck = " [deathtimeminutes] minute and"
|
||||
else if(deathtimeminutes > 1)
|
||||
pluralcheck = " [deathtimeminutes] minutes and"
|
||||
var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10,1)
|
||||
to_chat(usr, "You have been dead for[pluralcheck] [deathtimeseconds] seconds.")
|
||||
|
||||
if ((deathtime < (5 * 600)) && (ticker && ticker.current_state > GAME_STATE_PREGAME))
|
||||
to_chat(usr, "You must wait 5 minutes to respawn!")
|
||||
// Final chance to abort "respawning"
|
||||
if(mind && timeofdeath) // They had spawned before
|
||||
var/choice = alert(usr, "Returning to the menu will prevent your character from being revived in-round. Are you sure?", "Confirmation", "No, wait", "Yes, leave")
|
||||
if(choice == "No, wait")
|
||||
return
|
||||
else
|
||||
to_chat(usr, "You can respawn now, enjoy your new life!")
|
||||
|
||||
log_game("[usr.name]/[usr.key] used abandon mob.")
|
||||
|
||||
to_chat(usr, "<font color='blue'><B>Make sure to play a different character, and please roleplay correctly!</B></font>")
|
||||
|
||||
// Beyond this point, you're going to respawn
|
||||
to_chat(usr, config.respawn_message)
|
||||
|
||||
if(!client)
|
||||
log_game("[usr.key] AM failed due to disconnect.")
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
var/status_flags = CANSTUN|CANWEAKEN|CANPARALYSE|CANPUSH //bitflags defining which status effects can be inflicted (replaces canweaken, canstun, etc)
|
||||
|
||||
var/area/lastarea = null
|
||||
var/lastareachange = null
|
||||
|
||||
var/digitalcamo = 0 // Can they be tracked by the AI?
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
return result
|
||||
|
||||
// Can't control ourselves when drifting
|
||||
if(isspace(loc) || my_mob.lastarea?.has_gravity == 0)
|
||||
if((isspace(loc) || my_mob.lastarea?.has_gravity == 0) && !my_mob.in_enclosed_vehicle) //If(In space or last area had no gravity) or(you in vehicle)
|
||||
if(!my_mob.Process_Spacemove(0))
|
||||
return 0
|
||||
|
||||
@@ -292,7 +292,7 @@
|
||||
// It's just us and another person
|
||||
if(grablist.len == 1)
|
||||
var/mob/M = grablist[1]
|
||||
if(!my_mob.Adjacent(M)) //Oh no, we moved away
|
||||
if(M && !my_mob.Adjacent(M)) //Oh no, we moved away
|
||||
M.Move(pre_move_loc, get_dir(M, pre_move_loc), total_delay) //Have them step towards where we were
|
||||
|
||||
// It's a grab chain
|
||||
|
||||
@@ -9,7 +9,7 @@ var/obj/effect/lobby_image = new /obj/effect/lobby_image
|
||||
|
||||
/obj/effect/lobby_image/Initialize()
|
||||
icon = using_map.lobby_icon
|
||||
var/known_icon_states = icon_states(icon)
|
||||
var/known_icon_states = cached_icon_states(icon)
|
||||
for(var/lobby_screen in using_map.lobby_screens)
|
||||
if(!(lobby_screen in known_icon_states))
|
||||
error("Lobby screen '[lobby_screen]' did not exist in the icon set [icon].")
|
||||
|
||||
@@ -120,8 +120,9 @@
|
||||
new_player_panel_proc()
|
||||
|
||||
if(href_list["observe"])
|
||||
var/alert_time = ticker?.current_state <= GAME_STATE_SETTING_UP ? 1 : round(config.respawn_time/10/60)
|
||||
|
||||
if(alert(src,"Are you sure you wish to observe? You will have to wait 5 minutes before being able to respawn!","Player Setup","Yes","No") == "Yes")
|
||||
if(alert(src,"Are you sure you wish to observe? You will have to wait up to [alert_time] minute\s before being able to spawn into the game!","Player Setup","Yes","No") == "Yes")
|
||||
if(!client) return 1
|
||||
|
||||
//Make a new mannequin quickly, and allow the observer to take the appearance
|
||||
@@ -143,7 +144,6 @@
|
||||
observer.forceMove(O.loc)
|
||||
else
|
||||
to_chat(src, "<span class='danger'>Could not locate an observer spawn point. Use the Teleport verb to jump to the station map.</span>")
|
||||
observer.timeofdeath = world.time // Set the time of death so that the respawn timer works correctly.
|
||||
|
||||
announce_ghost_joinleave(src)
|
||||
|
||||
@@ -154,6 +154,7 @@
|
||||
if(!client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed.
|
||||
observer.verbs -= /mob/observer/dead/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
|
||||
observer.key = key
|
||||
observer.set_respawn_timer(time_till_respawn()) // Will keep their existing time if any, or return 0 and pass 0 into set_respawn_timer which will use the defaults
|
||||
qdel(src)
|
||||
|
||||
return 1
|
||||
@@ -163,6 +164,12 @@
|
||||
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
|
||||
to_chat(usr, "<font color='red'>The round is either not ready, or has already finished...</font>")
|
||||
return
|
||||
var/time_till_respawn = time_till_respawn()
|
||||
if(time_till_respawn == -1) // Special case, never allowed to respawn
|
||||
to_chat(usr, "<span class='warning'>Respawning is not allowed!</span>")
|
||||
else if(time_till_respawn) // Nonzero time to respawn
|
||||
to_chat(usr, "<span class='warning'>You can't respawn yet! You need to wait another [round(time_till_respawn/10/60, 0.1)] minutes.</span>")
|
||||
return
|
||||
LateChoices()
|
||||
|
||||
if(href_list["manifest"])
|
||||
@@ -331,6 +338,23 @@
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/mob/new_player/proc/time_till_respawn()
|
||||
if(!ckey)
|
||||
return -1 // What?
|
||||
|
||||
var/timer = GLOB.respawn_timers[ckey]
|
||||
// No timer at all
|
||||
if(!timer)
|
||||
return 0
|
||||
// Special case, infinite timer
|
||||
if(timer == -1)
|
||||
return -1
|
||||
// Timer expired
|
||||
if(timer <= world.time)
|
||||
GLOB.respawn_timers -= ckey
|
||||
return 0
|
||||
// Timer still going
|
||||
return timer - world.time
|
||||
|
||||
/mob/new_player/proc/IsJobAvailable(rank)
|
||||
var/datum/job/job = job_master.GetJob(rank)
|
||||
|
||||
@@ -1126,23 +1126,23 @@
|
||||
|
||||
//Skrell 'hairstyles'
|
||||
skr_tentacle_veryshort
|
||||
name = "Skrell Very Short Tentacles"
|
||||
icon_state = "skrell_hair_veryshort"
|
||||
name = "Skrell Short Tentacles"
|
||||
icon_state = "skrell_hair_short"
|
||||
species_allowed = list(SPECIES_SKRELL)
|
||||
gender = MALE
|
||||
|
||||
skr_tentacle_short
|
||||
name = "Skrell Short Tentacles"
|
||||
icon_state = "skrell_hair_short"
|
||||
species_allowed = list(SPECIES_SKRELL)
|
||||
|
||||
skr_tentacle_average
|
||||
name = "Skrell Average Tentacles"
|
||||
icon_state = "skrell_hair_average"
|
||||
species_allowed = list(SPECIES_SKRELL)
|
||||
|
||||
skr_tentacle_verylong
|
||||
skr_tentacle_average
|
||||
name = "Skrell Long Tentacles"
|
||||
icon_state = "skrell_hair_long"
|
||||
species_allowed = list(SPECIES_SKRELL)
|
||||
|
||||
skr_tentacle_verylong
|
||||
name = "Skrell Very Long Tentacles"
|
||||
icon_state = "skrell_hair_verylong"
|
||||
species_allowed = list(SPECIES_SKRELL)
|
||||
gender = FEMALE
|
||||
|
||||
Reference in New Issue
Block a user