mirror of
https://github.com/quotefox/Hyper-Station-13.git
synced 2026-07-18 19:22:43 +01:00
Merge branch 'master' into misc-recreation
This commit is contained in:
@@ -107,21 +107,21 @@
|
||||
|
||||
/datum/bounty/item/medical/advhealthscaner
|
||||
name = "Advanced Health Analyzer"
|
||||
description = "A ERT Medical unit needs the new 'advanced health analyzer', for a mission at a Station 4. Can you send some?."
|
||||
description = "An ERT Medical unit needs the new 'advanced health analyzer' for a mission at a Station 4. Can you send some?."
|
||||
reward = 3000
|
||||
required_count = 5
|
||||
wanted_types = list(/obj/item/healthanalyzer/advanced)
|
||||
|
||||
/datum/bounty/item/medical/wallmounts
|
||||
name = "Defibrillator wall mounts"
|
||||
description = "New Space OSHA regulation state that are new cloning medical wing needs a few 'Easy to access defibrillartors'. Can you send a few before we get a lawsuit?"
|
||||
description = "New Safety Review Board regulations state that our new medical wing needs 'easy to access defibrillators'. Can you send a few before we get a lawsuit?"
|
||||
reward = 2000
|
||||
required_count = 3
|
||||
wanted_types = list(/obj/machinery/defibrillator_mount)
|
||||
|
||||
/datum/bounty/item/medical/defibrillator
|
||||
name = "New defibillators"
|
||||
description = "After years of storage are defibrillator units have become more liabilities then we want. Please send us some new ones to replace these old ones."
|
||||
name = "New defibrillators"
|
||||
description = "After years of storage our defibrillator units have become more of a liability then we want. Please send us some new ones to replace them."
|
||||
reward = 2250
|
||||
required_count = 5
|
||||
wanted_types = list(/obj/item/defibrillator)
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
|
||||
/datum/supply_pack/security/russianclothing
|
||||
name = "Russian Surplus Clothing"
|
||||
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproff armor, a few union suits and some warm hats!"
|
||||
desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproof armor, a few union suits and some warm hats!"
|
||||
contraband = TRUE
|
||||
cost = 5750 // Its basicly sec suits, good boots/gloves
|
||||
contains = list(/obj/item/clothing/suit/security/officer/russian,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
var/removeDontImproveChance = 10 //chance the randomly created law replaces a random law instead of simply being added
|
||||
var/shuffleLawsChance = 10 //chance the AI's laws are shuffled afterwards
|
||||
var/botEmagChance = 10
|
||||
var/announceEvent = ION_RANDOM // -1 means don't announce, 0 means have it randomly announce, 1 means it is announced
|
||||
var/announceEvent = 1 // -1 means don't announce, 0 means have it randomly announce, 1 means it is announced
|
||||
var/ionMessage = null
|
||||
var/ionAnnounceChance = 33
|
||||
announceWhen = 1
|
||||
|
||||
@@ -448,7 +448,7 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
|
||||
return FALSE
|
||||
|
||||
/datum/holiday/ramadan/getStationPrefix()
|
||||
return pick("Harm","Halaal","Jihad","Muslim")
|
||||
return pick("Fasting","Enlightenment","Prayer","Muslim")
|
||||
|
||||
/datum/holiday/ramadan/end
|
||||
name = "End of Ramadan"
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
update_damage_overlays()
|
||||
else
|
||||
adjustStaminaLoss(damage * hit_percent)
|
||||
//citadel code
|
||||
if(AROUSAL)
|
||||
adjustArousalLoss(damage * hit_percent)
|
||||
return TRUE
|
||||
@@ -62,7 +61,6 @@
|
||||
amount += BP.burn_dam
|
||||
return amount
|
||||
|
||||
|
||||
/mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
|
||||
if (!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL))
|
||||
return FALSE
|
||||
|
||||
@@ -729,8 +729,19 @@
|
||||
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#000000")
|
||||
cut_overlay(MA)
|
||||
|
||||
//medical scan animation
|
||||
/mob/living/carbon/human/proc/scan_animation()
|
||||
var/mutable_appearance/scan_anim
|
||||
scan_anim = mutable_appearance(icon, "mediscan")
|
||||
add_overlay(scan_anim)
|
||||
addtimer(CALLBACK(src, .proc/end_scan_animation, scan_anim), 10)
|
||||
flick(icon,src)
|
||||
|
||||
/mob/living/carbon/human/proc/end_scan_animation(mutable_appearance/MA)
|
||||
cut_overlay(MA)
|
||||
|
||||
/mob/living/carbon/human/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
if(incapacitated() || lying )
|
||||
if(incapacitated())
|
||||
to_chat(src, "<span class='warning'>You can't do that right now!</span>")
|
||||
return FALSE
|
||||
if(!Adjacent(M) && (M.loc != src))
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
if(STAMINA)
|
||||
return getStaminaLoss()
|
||||
|
||||
|
||||
/mob/living/proc/apply_damages(brute = 0, burn = 0, tox = 0, oxy = 0, clone = 0, def_zone = null, blocked = FALSE, stamina = 0, brain = 0)
|
||||
if(blocked >= 100)
|
||||
return 0
|
||||
@@ -230,6 +229,9 @@
|
||||
/mob/living/proc/setStaminaLoss(amount, updating_stamina = TRUE, forced = FALSE)
|
||||
return
|
||||
|
||||
/mob/living/proc/adjustPainLoss(amount, updating_health = TRUE, forced = FALSE)
|
||||
return
|
||||
|
||||
// heal ONE external organ, organ gets randomly selected from damaged ones.
|
||||
/mob/living/proc/heal_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE)
|
||||
adjustBruteLoss(-brute, FALSE) //zero as argument for no instant health update
|
||||
|
||||
@@ -160,15 +160,6 @@
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
stat_allowed = UNCONSCIOUS
|
||||
|
||||
/datum/emote/living/gasp/run_emote(mob/user, params)
|
||||
. = ..()
|
||||
if(. && ishuman(user))
|
||||
var/mob/living/carbon/C = user
|
||||
if(user.gender == FEMALE)
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/gasp_female1.ogg', 'hyperstation/sound/voice/emotes/gasp_female2.ogg', 'hyperstation/sound/voice/emotes/gasp_female3.ogg', 'hyperstation/sound/voice/emotes/gasp_female4.ogg', 'hyperstation/sound/voice/emotes/gasp_female5.ogg', 'hyperstation/sound/voice/emotes/gasp_female6.ogg', 'hyperstation/sound/voice/emotes/gasp_female7.ogg'), 50, 1)
|
||||
else
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/gasp_male1.ogg', 'hyperstation/sound/voice/emotes/gasp_male2.ogg', 'hyperstation/sound/voice/emotes/gasp_male3.ogg', 'hyperstation/sound/voice/emotes/gasp_male4.ogg', 'hyperstation/sound/voice/emotes/gasp_male5.ogg', 'hyperstation/sound/voice/emotes/gasp_male6.ogg', 'hyperstation/sound/voice/emotes/gasp_male7.ogg'), 50, 1)
|
||||
|
||||
/datum/emote/living/giggle
|
||||
key = "giggle"
|
||||
key_third_person = "giggles"
|
||||
@@ -176,17 +167,6 @@
|
||||
message_mime = "giggles silently!"
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
|
||||
/datum/emote/living/giggle/run_emote(mob/user, params)
|
||||
. = ..()
|
||||
if(. && ishuman(user))
|
||||
var/mob/living/carbon/C = user
|
||||
if(!C.mind || C.mind.miming)
|
||||
return
|
||||
if(user.gender == FEMALE)
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/female_giggle1.ogg', 'hyperstation/sound/voice/emotes/female_giggle2.ogg'), 50, 1)
|
||||
else
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/male_laugh3b.ogg'), 50, 1)
|
||||
|
||||
/datum/emote/living/glare
|
||||
key = "glare"
|
||||
key_third_person = "glares"
|
||||
@@ -249,11 +229,6 @@
|
||||
'sound/voice/catpeople/nyahehe.ogg'),
|
||||
50, 1)
|
||||
return
|
||||
if(ishumanbasic(C))
|
||||
if(user.gender == FEMALE)
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/female_laugh1.ogg', 'hyperstation/sound/voice/emotes/female_laugh2.ogg', 'hyperstation/sound/voice/emotes/female_laugh3.ogg', 'hyperstation/sound/voice/emotes/female_laugh4.ogg'), 50, 1)
|
||||
else
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/male_laugh1.ogg', 'hyperstation/sound/voice/emotes/male_laugh1b.ogg', 'hyperstation/sound/voice/emotes/male_laugh2.ogg', 'hyperstation/sound/voice/emotes/male_laugh2b.ogg',/*'hyperstation/sound/voice/emotes/male_laugh3.ogg',*/'hyperstation/sound/voice/emotes/male_laugh3b.ogg', 'hyperstation/sound/voice/emotes/male_laugh4.ogg'), 50, 1)
|
||||
|
||||
/datum/emote/living/look
|
||||
key = "look"
|
||||
@@ -330,11 +305,6 @@
|
||||
var/mob/living/carbon/C = user
|
||||
if(!C.mind || C.mind.miming)
|
||||
return
|
||||
if(ishumanbasic(C))
|
||||
if(user.gender == FEMALE)
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/sigh_female.ogg'), 50, 1)
|
||||
else
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/sigh_male.ogg'), 50, 1)
|
||||
|
||||
/datum/emote/living/sit
|
||||
key = "sit"
|
||||
@@ -364,11 +334,6 @@
|
||||
var/mob/living/carbon/C = user
|
||||
if(!C.mind || C.mind.miming)//mimes can't sneeze because fuck you that's why
|
||||
return
|
||||
if(ishumanbasic(C))
|
||||
if(user.gender == FEMALE)
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/sneezef1.ogg', 'hyperstation/sound/voice/emotes/sneezef2.ogg'), 50, 1)
|
||||
else
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/sneezem1.ogg', 'hyperstation/sound/voice/emotes/sneezem2.ogg'), 50, 1)
|
||||
|
||||
/datum/emote/living/smug
|
||||
key = "smug"
|
||||
@@ -462,11 +427,6 @@
|
||||
var/mob/living/carbon/C = user
|
||||
if(!C.mind || C.mind.miming)
|
||||
return
|
||||
if(ishumanbasic(C))
|
||||
if(user.gender == FEMALE)
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/whimper_female1.ogg', 'hyperstation/sound/voice/emotes/whimper_female2.ogg', 'hyperstation/sound/voice/emotes/whimper_female3.ogg'), 50, 1)
|
||||
else
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/whimper_male1.ogg', 'hyperstation/sound/voice/emotes/whimper_male2.ogg', 'hyperstation/sound/voice/emotes/whimper_male3.ogg'), 50, 1)
|
||||
|
||||
/datum/emote/living/wsmile
|
||||
key = "wsmile"
|
||||
@@ -485,11 +445,6 @@
|
||||
var/mob/living/carbon/C = user
|
||||
if(!C.mind || C.mind.miming)
|
||||
return
|
||||
if(ishumanbasic(C))
|
||||
if(user.gender == FEMALE)
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/female_yawn1.ogg', 'hyperstation/sound/voice/emotes/female_yawn2.ogg', 'hyperstation/sound/voice/emotes/female_yawn3.ogg'), 50, 1)
|
||||
else
|
||||
playsound(C, pick('hyperstation/sound/voice/emotes/male_yawn1.ogg', 'hyperstation/sound/voice/emotes/male_yawn2.ogg'), 50, 1)
|
||||
|
||||
/datum/emote/living/custom
|
||||
key = "me"
|
||||
|
||||
@@ -502,6 +502,10 @@
|
||||
var/obj/effect/proc_holder/spell/spell = S
|
||||
spell.updateButtonIcon()
|
||||
|
||||
if(iscarbon(src)) //pain cooldown
|
||||
var/mob/living/carbon/C = src
|
||||
C.pain_cooldown = 20
|
||||
|
||||
//proc used to completely heal a mob.
|
||||
/mob/living/proc/fully_heal(admin_revive = 0)
|
||||
restore_blood()
|
||||
@@ -542,6 +546,13 @@
|
||||
for(var/organ in C.internal_organs)
|
||||
var/obj/item/organ/O = organ
|
||||
O.setOrganDamage(0)
|
||||
//Heal pain
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C = src
|
||||
for(var/obj/item/bodypart/X in C.bodyparts)
|
||||
X.pain_dam = 0
|
||||
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_LIVING_FULLY_HEAL, admin_revive)
|
||||
|
||||
//fuck shitcode I hate shitcode
|
||||
@@ -1086,7 +1097,11 @@
|
||||
lying = 90*buckle_lying
|
||||
else if(!lying)
|
||||
if(resting)
|
||||
lying = pick(90, 270) // Cit change - makes resting not force you to drop your held items
|
||||
if(dir == 2 || dir == 4)
|
||||
lying = 90
|
||||
else
|
||||
lying = 270
|
||||
|
||||
if(has_gravity()) // Cit change - Ditto
|
||||
playsound(src, "bodyfall", 50, 1) // Cit change - Ditto!
|
||||
else if(ko || move_and_fall || (!has_legs && !ignore_legs) || chokehold)
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
disabler = FALSE
|
||||
update_icons() //PUT THE GUN AWAY
|
||||
else if(istype(O,/obj/item/dogborg/sleeper))
|
||||
sleeper_g = FALSE
|
||||
sleeper_r = FALSE
|
||||
sleeper_state = BORGBELLY_NONE
|
||||
update_icons()
|
||||
var/obj/item/dogborg/sleeper/S = O
|
||||
S.go_out() //this should stop edgecase deletions
|
||||
|
||||
@@ -654,10 +654,14 @@
|
||||
if(disabler)
|
||||
add_overlay("disabler")//ditto
|
||||
|
||||
if(sleeper_g && module.sleeper_overlay)
|
||||
add_overlay("[module.sleeper_overlay]_g[sleeper_nv ? "_nv" : ""]")
|
||||
if(sleeper_r && module.sleeper_overlay)
|
||||
add_overlay("[module.sleeper_overlay]_r[sleeper_nv ? "_nv" : ""]")
|
||||
if(module.sleeper_overlay)
|
||||
var/sleeper_overlay_state = ""
|
||||
switch(sleeper_state)
|
||||
if(BORGBELLY_NONE) sleeper_overlay_state = ""
|
||||
if(BORGBELLY_GREEN) sleeper_overlay_state = "_g"
|
||||
if(BORGBELLY_RED) sleeper_overlay_state = "_r"
|
||||
add_overlay("[module.sleeper_overlay][sleeper_overlay_state]")
|
||||
|
||||
if(module.dogborg == TRUE)
|
||||
if(resting)
|
||||
cut_overlays()
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
#define GREMLIN_VENT_CHANCE 1.75
|
||||
|
||||
//Gremlins
|
||||
//Small monsters that don't attack humans or other animals. Instead they mess with electronics, computers and machinery
|
||||
|
||||
//List of objects that gremlins can't tamper with (because nobody coded an interaction for it)
|
||||
//List starts out empty. Whenever a gremlin finds a machine that it couldn't tamper with, the machine's type is added here, and all machines of such type are ignored from then on (NOT SUBTYPES)
|
||||
GLOBAL_LIST(bad_gremlin_items)
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin
|
||||
name = "gremlin"
|
||||
desc = "This tiny creature finds great joy in discovering and using technology. Nothing excites it more than pushing random buttons on a computer to see what it might do."
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "gremlin"
|
||||
icon_living = "gremlin"
|
||||
icon_dead = "gremlin_dead"
|
||||
|
||||
var/body_color
|
||||
|
||||
var/in_vent = FALSE
|
||||
|
||||
health = 20
|
||||
maxHealth = 20
|
||||
search_objects = 3 //Completely ignore mobs
|
||||
|
||||
//Tampering is handled by the 'npc_tamper()' obj proc
|
||||
wanted_objects = list(
|
||||
/obj/machinery,
|
||||
/obj/item/reagent_containers/food,
|
||||
/obj/structure/sink
|
||||
)
|
||||
|
||||
var/obj/machinery/atmospherics/components/unary/vent_pump/entry_vent
|
||||
var/obj/machinery/atmospherics/components/unary/vent_pump/exit_vent
|
||||
|
||||
dextrous = TRUE
|
||||
possible_a_intents = list(INTENT_HELP, INTENT_GRAB, INTENT_DISARM, INTENT_HARM)
|
||||
faction = list("meme", "gremlin")
|
||||
speed = 0.5
|
||||
gold_core_spawnable = 2
|
||||
unique_name = TRUE
|
||||
|
||||
//Ensure gremlins don't attack other mobs
|
||||
melee_damage_upper = 0
|
||||
melee_damage_lower = 0
|
||||
attack_sound = null
|
||||
obj_damage = 0
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
|
||||
//List of objects that we don't even want to try to tamper with
|
||||
//Subtypes of these are calculated too
|
||||
var/list/unwanted_objects = list(/obj/machinery/atmospherics/pipe, /turf, /obj/structure) //ensure gremlins dont try to fuck with walls / normal pipes / glass / etc
|
||||
|
||||
var/min_next_vent = 0
|
||||
|
||||
//Amount of ticks spent pathing to the target. If it gets above a certain amount, assume that the target is unreachable and stop
|
||||
var/time_chasing_target = 0
|
||||
|
||||
//If you're going to make gremlins slower, increase this value - otherwise gremlins will abandon their targets too early
|
||||
var/max_time_chasing_target = 2
|
||||
|
||||
var/next_eat = 0
|
||||
|
||||
//Last 20 heard messages are remembered by gremlins, and will be used to generate messages for comms console tampering, etc...
|
||||
var/list/hear_memory = list()
|
||||
var/const/max_hear_memory = 20
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/Initialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
|
||||
ADD_TRAIT(src, TRAIT_SHOCKIMMUNE, INNATE_TRAIT)
|
||||
access_card = new /obj/item/card/id(src)
|
||||
var/datum/job/captain/C = new /datum/job/captain
|
||||
access_card.access = C.get_access()
|
||||
if(!body_color)
|
||||
body_color = pick(list("orange","blue","purple", "green", "crystal"))
|
||||
AddElement(/datum/element/mob_holder, "gremlin_[body_color]")
|
||||
icon_state = "gremlin_[body_color]"
|
||||
icon_living = "gremlin_[body_color]"
|
||||
icon_dead = "gremlin_[body_color]_dead"
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/AttackingTarget()
|
||||
var/is_hungry = world.time >= next_eat || prob(25)
|
||||
if(istype(target, /obj/item/reagent_containers/food) && is_hungry) //eat food if we're hungry or bored
|
||||
visible_message("<span class='danger'>[src] hungrily devours [target]!</span>")
|
||||
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
|
||||
qdel(target)
|
||||
LoseTarget()
|
||||
next_eat = world.time + rand(700, 3000) //anywhere from 70 seconds to 5 minutes until the gremlin is hungry again
|
||||
return
|
||||
if(istype(target, /obj))
|
||||
var/obj/M = target
|
||||
tamper(M)
|
||||
if(prob(50)) //50% chance to move to the next machine
|
||||
LoseTarget()
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode)
|
||||
. = ..()
|
||||
if(message)
|
||||
hear_memory.Insert(1, raw_message)
|
||||
if(hear_memory.len > max_hear_memory)
|
||||
hear_memory.Cut(hear_memory.len)
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/proc/generate_markov_input()
|
||||
var/result = ""
|
||||
|
||||
for(var/memory in hear_memory)
|
||||
result += memory + " "
|
||||
|
||||
return result
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/proc/generate_markov_chain()
|
||||
return markov_chain(generate_markov_input(), rand(2,5), rand(100,700)) //The numbers are chosen arbitarily
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/proc/tamper(obj/M)
|
||||
switch(M.npc_tamper_act(src))
|
||||
if(NPC_TAMPER_ACT_FORGET)
|
||||
visible_message(pick(
|
||||
"<span class='notice'>\The [src] plays around with \the [M], but finds it rather boring.</span>",
|
||||
"<span class='notice'>\The [src] tries to think of some more ways to screw \the [M] up, but fails miserably.</span>",
|
||||
"<span class='notice'>\The [src] decides to ignore \the [M], and starts looking for something more fun.</span>"))
|
||||
|
||||
LAZYADD(GLOB.bad_gremlin_items,M.type)
|
||||
return FALSE
|
||||
if(NPC_TAMPER_ACT_NOMSG)
|
||||
//Don't create a visible message
|
||||
return TRUE
|
||||
|
||||
else
|
||||
visible_message(pick(
|
||||
"<span class='danger'>\The [src]'s eyes light up as \he tampers with \the [M].</span>",
|
||||
"<span class='danger'>\The [src] twists some knobs around on \the [M] and bursts into laughter!</span>",
|
||||
"<span class='danger'>\The [src] presses a few buttons on \the [M] and giggles mischievously.</span>",
|
||||
"<span class='danger'>\The [src] rubs its hands devilishly and starts messing with \the [M].</span>",
|
||||
"<span class='danger'>\The [src] turns a small valve on \the [M].</span>"))
|
||||
|
||||
//Add a clue for detectives to find. The clue is only added if no such clue already existed on that machine
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/CanAttack(atom/new_target)
|
||||
if(LAZYFIND(GLOB.bad_gremlin_items,new_target.type))
|
||||
return FALSE
|
||||
if(is_type_in_list(new_target, unwanted_objects))
|
||||
return FALSE
|
||||
if(istype(new_target, /obj/machinery))
|
||||
var/obj/machinery/M = new_target
|
||||
if(M.stat) //Unpowered or broken
|
||||
return FALSE
|
||||
else if(istype(new_target, /obj/machinery/door/firedoor))
|
||||
var/obj/machinery/door/firedoor/F = new_target
|
||||
//Only tamper with firelocks that are closed, opening them!
|
||||
if(!F.density)
|
||||
return FALSE
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/death(gibbed)
|
||||
walk(src,0)
|
||||
QDEL_NULL(access_card)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/Life()
|
||||
. = ..()
|
||||
if(!health || stat == DEAD)
|
||||
return
|
||||
//Don't try to path to one target for too long. If it takes longer than a certain amount of time, assume it can't be reached and find a new one
|
||||
if(!client) //don't do this shit if there's a client, they're capable of ventcrawling manually
|
||||
if(in_vent)
|
||||
target = null
|
||||
if(entry_vent && get_dist(src, entry_vent) <= 1)
|
||||
var/list/vents = list()
|
||||
var/datum/pipeline/entry_vent_parent = entry_vent.parents[1]
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in entry_vent_parent.other_atmosmch)
|
||||
vents += temp_vent
|
||||
if(!vents.len)
|
||||
entry_vent = null
|
||||
in_vent = FALSE
|
||||
return
|
||||
exit_vent = pick(vents)
|
||||
visible_message("<span class='notice'>[src] crawls into the ventilation ducts!</span>")
|
||||
|
||||
loc = exit_vent
|
||||
var/travel_time = round(get_dist(loc, exit_vent.loc) / 2)
|
||||
addtimer(CALLBACK(src, .proc/exit_vents), travel_time) //come out at exit vent in 2 to 20 seconds
|
||||
|
||||
|
||||
if(world.time > min_next_vent && !entry_vent && !in_vent && prob(GREMLIN_VENT_CHANCE)) //small chance to go into a vent
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_pump/v in view(7,src))
|
||||
if(!v.welded)
|
||||
entry_vent = v
|
||||
in_vent = TRUE
|
||||
walk_to(src, entry_vent)
|
||||
break
|
||||
if(!target)
|
||||
time_chasing_target = 0
|
||||
else
|
||||
if(++time_chasing_target > max_time_chasing_target)
|
||||
LoseTarget()
|
||||
time_chasing_target = 0
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/EscapeConfinement()
|
||||
if(istype(loc, /obj) && CanAttack(loc)) //If we're inside a machine, screw with it
|
||||
var/obj/M = loc
|
||||
tamper(M)
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/proc/exit_vents()
|
||||
if(!exit_vent || exit_vent.welded)
|
||||
loc = entry_vent
|
||||
entry_vent = null
|
||||
return
|
||||
loc = exit_vent.loc
|
||||
entry_vent = null
|
||||
exit_vent = null
|
||||
in_vent = FALSE
|
||||
var/area/new_area = get_area(loc)
|
||||
message_admins("[src] came out at [new_area][ADMIN_JMP(loc)]!")
|
||||
if(new_area)
|
||||
new_area.Entered(src)
|
||||
visible_message("<span class='notice'>[src] climbs out of the ventilation ducts!</span>")
|
||||
min_next_vent = world.time + 900 //90 seconds between ventcrawls
|
||||
|
||||
//This allows player-controlled gremlins to tamper with machinery
|
||||
/mob/living/simple_animal/hostile/gremlin/UnarmedAttack(var/atom/A)
|
||||
if(istype(A, /obj/machinery) || istype(A, /obj/structure))
|
||||
tamper(A)
|
||||
if(istype(target, /obj/item/reagent_containers/food)) //eat food
|
||||
visible_message("<span class='danger'>[src] hungrily devours [target]!</span>", "<span class='danger'>You hungrily devour [target]!</span>")
|
||||
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
|
||||
qdel(target)
|
||||
LoseTarget()
|
||||
next_eat = world.time + rand(700, 3000) //anywhere from 70 seconds to 5 minutes until the gremlin is hungry again
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/IsAdvancedToolUser()
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/proc/divide()
|
||||
//Health is halved and then reduced by 2. A new gremlin is spawned with the same health as the parent
|
||||
//Need to have at least 6 health for this, otherwise resulting health would be less than 1
|
||||
if(health < 7.5)
|
||||
return
|
||||
|
||||
visible_message("<span class='notice'>\The [src] splits into two!</span>")
|
||||
var/mob/living/simple_animal/hostile/gremlin/G = new /mob/living/simple_animal/hostile/gremlin(get_turf(src))
|
||||
|
||||
if(mind)
|
||||
mind.transfer_to(G)
|
||||
|
||||
health = round(health * 0.5) - 2
|
||||
maxHealth = health
|
||||
resize *= 0.9
|
||||
|
||||
G.health = health
|
||||
G.maxHealth = maxHealth
|
||||
|
||||
/mob/living/simple_animal/hostile/gremlin/traitor
|
||||
health = 85
|
||||
maxHealth = 85
|
||||
gold_core_spawnable = 0
|
||||
@@ -0,0 +1,214 @@
|
||||
/obj/proc/npc_tamper_act(mob/living/L)
|
||||
return NPC_TAMPER_ACT_FORGET
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/npc_tamper_act(mob/living/L)
|
||||
if(prob(50)) //Turn on/off
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(L)]", INVESTIGATE_ATMOS)
|
||||
else //Change pressure
|
||||
target_pressure = rand(0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(L)]", INVESTIGATE_ATMOS)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/pump/npc_tamper_act(mob/living/L)
|
||||
if(prob(50)) //Turn on/off
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(L)]", INVESTIGATE_ATMOS)
|
||||
else //Change pressure
|
||||
target_pressure = rand(0, MAX_OUTPUT_PRESSURE)
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(L)]", INVESTIGATE_ATMOS)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/volume_pump/npc_tamper_act(mob/living/L)
|
||||
if(prob(50)) //Turn on/off
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(L)]", INVESTIGATE_ATMOS)
|
||||
else //Change pressure
|
||||
transfer_rate = rand(0, MAX_TRANSFER_RATE)
|
||||
investigate_log("was set to [transfer_rate] L/s by [key_name(L)]", INVESTIGATE_ATMOS)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/valve/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/space_heater/npc_tamper_act(mob/living/L)
|
||||
var/list/choose_modes = list("standby", "heat", "cool")
|
||||
if(prob(50))
|
||||
choose_modes -= mode
|
||||
mode = pick(choose_modes)
|
||||
else
|
||||
on = !on
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/shield_gen/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/firealarm/npc_tamper_act(mob/living/L)
|
||||
alarm()
|
||||
|
||||
/obj/machinery/airalarm/npc_tamper_act(mob/living/L)
|
||||
if(panel_open)
|
||||
wires.npc_tamper(L)
|
||||
else
|
||||
panel_open = !panel_open
|
||||
|
||||
/obj/machinery/ignition_switch/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/flasher_button/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/crema_switch/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/camera/npc_tamper_act(mob/living/L)
|
||||
if(!panel_open)
|
||||
panel_open = !panel_open
|
||||
if(wires)
|
||||
wires.npc_tamper(L)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/npc_tamper_act(mob/living/L)
|
||||
if(prob(50))
|
||||
if(beaker)
|
||||
beaker.forceMove(loc)
|
||||
beaker = null
|
||||
else
|
||||
if(occupant)
|
||||
if(state_open)
|
||||
if (close_machine() == usr)
|
||||
on = TRUE
|
||||
else
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/door_control/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/door/airlock/npc_tamper_act(mob/living/L)
|
||||
//Open the firelocks as well, otherwise they block the way for our gremlin which isn't fun
|
||||
for(var/obj/machinery/door/firedoor/F in get_turf(src))
|
||||
if(F.density)
|
||||
F.npc_tamper_act(L)
|
||||
|
||||
if(prob(40)) //40% - mess with wires
|
||||
if(!panel_open)
|
||||
panel_open = !panel_open
|
||||
if(wires)
|
||||
wires.npc_tamper(L)
|
||||
else //60% - just open it
|
||||
open()
|
||||
|
||||
/obj/machinery/gibber/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/light_switch/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/turretid/npc_tamper_act(mob/living/L)
|
||||
enabled = rand(0, 1)
|
||||
lethal = rand(0, 1)
|
||||
updateTurrets()
|
||||
|
||||
/obj/machinery/vending/npc_tamper_act(mob/living/L)
|
||||
if(!panel_open)
|
||||
panel_open = !panel_open
|
||||
if(wires)
|
||||
wires.npc_tamper(L)
|
||||
|
||||
/obj/machinery/shower/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
|
||||
/obj/machinery/deepfryer/npc_tamper_act(mob/living/L)
|
||||
//Deepfry a random nearby item
|
||||
var/list/pickable_items = list()
|
||||
|
||||
for(var/obj/item/I in range(1, L))
|
||||
pickable_items.Add(I)
|
||||
|
||||
if(!pickable_items.len)
|
||||
return
|
||||
|
||||
var/obj/item/I = pick(pickable_items)
|
||||
|
||||
attackby(I, L) //shove the item in, even if it can't be deepfried normally
|
||||
|
||||
/obj/machinery/power/apc/npc_tamper_act(mob/living/L)
|
||||
if(!panel_open)
|
||||
panel_open = !panel_open
|
||||
if(wires)
|
||||
wires.npc_tamper(L)
|
||||
|
||||
/obj/machinery/power/rad_collector/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/power/emitter/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/particle_accelerator/control_box/npc_tamper_act(mob/living/L)
|
||||
if(!panel_open)
|
||||
panel_open = !panel_open
|
||||
if(wires)
|
||||
wires.npc_tamper(L)
|
||||
|
||||
/obj/machinery/computer/communications/npc_tamper_act(mob/living/user)
|
||||
if(!authenticated)
|
||||
if(prob(20)) //20% chance to log in
|
||||
authenticated = TRUE
|
||||
|
||||
else //Already logged in
|
||||
if(prob(50)) //50% chance to log off
|
||||
authenticated = FALSE
|
||||
else if(istype(user, /mob/living/simple_animal/hostile/gremlin)) //make a hilarious public message
|
||||
var/mob/living/simple_animal/hostile/gremlin/G = user
|
||||
var/result = G.generate_markov_chain()
|
||||
|
||||
if(result)
|
||||
if(prob(85))
|
||||
SScommunications.make_announcement(G, FALSE, result)
|
||||
var/turf/T = get_turf(G)
|
||||
log_say("[key_name(usr)] ([ADMIN_JMP(T)]) has made a captain announcement: [result]")
|
||||
message_admins("[key_name_admin(G)] has made a captain announcement.", 1)
|
||||
else
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_IDLE)
|
||||
SSshuttle.requestEvac(G, result)
|
||||
else if(SSshuttle.emergency.mode == SHUTTLE_ESCAPE)
|
||||
SSshuttle.cancelEvac(G)
|
||||
|
||||
/obj/machinery/button/door/npc_tamper_act(mob/living/L)
|
||||
attack_hand(L)
|
||||
|
||||
/obj/machinery/sleeper/npc_tamper_act(mob/living/L)
|
||||
if(prob(75))
|
||||
inject_chem(pick(available_chems))
|
||||
else
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/power/smes/npc_tamper_act(mob/living/L)
|
||||
if(prob(50)) //mess with input
|
||||
input_level = rand(0, input_level_max)
|
||||
else //mess with output
|
||||
output_level = rand(0, output_level_max)
|
||||
|
||||
/obj/machinery/syndicatebomb/npc_tamper_act(mob/living/L) //suicide bomber gremlins
|
||||
if(!open_panel)
|
||||
open_panel = !open_panel
|
||||
if(wires)
|
||||
wires.npc_tamper(L)
|
||||
|
||||
/obj/machinery/computer/bank_machine/npc_tamper_act(mob/living/L)
|
||||
siphoning = !siphoning
|
||||
|
||||
/obj/machinery/computer/slot_machine/npc_tamper_act(mob/living/L)
|
||||
spin(L)
|
||||
|
||||
/obj/structure/sink/npc_tamper_act(mob/living/L)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/gremlin))
|
||||
visible_message("<span class='danger'>\The [L] climbs into \the [src] and turns the faucet on!</span>")
|
||||
|
||||
var/mob/living/simple_animal/hostile/gremlin/G = L
|
||||
G.divide()
|
||||
|
||||
return NPC_TAMPER_ACT_NOMSG
|
||||
@@ -0,0 +1,44 @@
|
||||
/datum/round_event_control/gremlin
|
||||
name = "Spawn Gremlins"
|
||||
typepath = /datum/round_event/gremlin
|
||||
weight = 15
|
||||
max_occurrences = 2
|
||||
earliest_start = 20 MINUTES
|
||||
min_players = 5
|
||||
|
||||
|
||||
|
||||
/datum/round_event/gremlin
|
||||
var/static/list/acceptable_spawns = list("xeno_spawn", "generic event spawn", "blobstart", "Assistant")
|
||||
|
||||
/datum/round_event/gremlin/announce()
|
||||
priority_announce("Bioscans indicate that some gremlins entered through the vents. Deal with them!", "Gremlin Alert", 'sound/ai/beep.ogg')
|
||||
|
||||
/datum/round_event/gremlin/start()
|
||||
|
||||
var/list/spawn_locs = list()
|
||||
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
if(isturf(L.loc) && !isspaceturf(L.loc))
|
||||
if(L.name in acceptable_spawns)
|
||||
spawn_locs += L.loc
|
||||
if(!spawn_locs.len) //If we can't find any gremlin spawns, try the xeno spawns
|
||||
for(var/obj/effect/landmark/L in GLOB.landmarks_list)
|
||||
if(isturf(L.loc))
|
||||
switch(L.name)
|
||||
if("Assistant")
|
||||
spawn_locs += L.loc
|
||||
if(!spawn_locs.len) //If we can't find THAT, then just give up and cry
|
||||
return MAP_ERROR
|
||||
|
||||
var/gremlins_to_spawn = rand(2,5)
|
||||
var/list/gremlin_areas = list()
|
||||
for(var/i = 0, i <= gremlins_to_spawn, i++)
|
||||
var/spawnat = pick(spawn_locs)
|
||||
spawn_locs -= spawnat
|
||||
gremlin_areas += get_area(spawnat)
|
||||
new /mob/living/simple_animal/hostile/gremlin(spawnat)
|
||||
var/grems = gremlin_areas.Join(", ")
|
||||
message_admins("Gremlins have been spawned at the areas: [grems]")
|
||||
log_game("Gremlins have been spawned at the areas: [grems]")
|
||||
return SUCCESSFUL_SPAWN
|
||||
@@ -197,7 +197,7 @@
|
||||
var/static_power_used = 0
|
||||
var/brightness = 8 // luminosity when on, also used in power calculation
|
||||
var/bulb_power = 1 // basically the alpha of the emitted light source
|
||||
var/bulb_colour = "#FFFFFF" // befault colour of the light.
|
||||
var/bulb_colour = "#ffefda" // befault colour of the light.
|
||||
var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN
|
||||
var/flickering = FALSE
|
||||
var/light_type = /obj/item/light/tube // the type of light item
|
||||
@@ -212,13 +212,13 @@
|
||||
|
||||
var/nightshift_enabled = FALSE //Currently in night shift mode?
|
||||
var/nightshift_allowed = TRUE //Set to FALSE to never let this light get switched to night mode.
|
||||
var/nightshift_brightness = 8
|
||||
var/nightshift_brightness = 7
|
||||
var/nightshift_light_power = 0.45
|
||||
var/nightshift_light_color = "#FFDDCC"
|
||||
var/nightshift_light_color = "#dafcff"
|
||||
|
||||
var/emergency_mode = FALSE // if true, the light is in emergency mode
|
||||
var/no_emergency = FALSE // if true, this light cannot ever have an emergency mode
|
||||
var/bulb_emergency_brightness_mul = 0.25 // multiplier for this light's base brightness in emergency power mode
|
||||
var/bulb_emergency_brightness_mul = 0.6 // multiplier for this light's base brightness in emergency power mode
|
||||
var/bulb_emergency_colour = "#FF3232" // determines the colour of the light while it's in emergency mode
|
||||
var/bulb_emergency_pow_mul = 0.75 // the multiplier for determining the light's power in emergency mode
|
||||
var/bulb_emergency_pow_min = 0.5 // the minimum value for the light's power in emergency mode
|
||||
|
||||
@@ -36,6 +36,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
*/
|
||||
|
||||
/datum/reagent/consumable/ethanol/on_mob_life(mob/living/carbon/C)
|
||||
C.adjustPainLoss(-0.25*REM, 0) //alchol dulls pain
|
||||
if(C.drunkenness < volume * boozepwr * ALCOHOL_THRESHOLD_MODIFIER)
|
||||
var/booze_power = boozepwr
|
||||
if(HAS_TRAIT(C, TRAIT_ALCOHOL_TOLERANCE)) //we're an accomplished drinker
|
||||
|
||||
@@ -1001,3 +1001,5 @@
|
||||
glass_desc = "A Summer time drink that can be frozen and eaten or Drinked from a glass!"
|
||||
glass_name = "Orange Creamsicle"
|
||||
hydration = 4
|
||||
|
||||
|
||||
|
||||
@@ -391,6 +391,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
|
||||
/datum/reagent/medicine/mine_salve/on_mob_life(mob/living/carbon/C)
|
||||
C.hal_screwyhud = SCREWYHUD_HEALTHY
|
||||
C.adjustBruteLoss(-0.25*REM, 0)
|
||||
C.adjustPainLoss(-1*REM, 0)
|
||||
C.adjustFireLoss(-0.25*REM, 0)
|
||||
C.adjustStaminaLoss(-0.5*REM, 0)
|
||||
..()
|
||||
@@ -698,7 +699,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
|
||||
|
||||
/datum/reagent/medicine/morphine
|
||||
name = "Morphine"
|
||||
description = "A painkiller that allows the patient to move at full speed even in bulky objects. Causes drowsiness and eventually unconsciousness in high doses. Overdose will cause a variety of effects, ranging from minor to lethal."
|
||||
description = "A painkiller. Causes drowsiness and eventually unconsciousness in high doses. Overdose will cause a variety of effects, ranging from minor to lethal."
|
||||
reagent_state = LIQUID
|
||||
color = "#A9FBFB"
|
||||
metabolization_rate = 0.5 * REAGENTS_METABOLISM
|
||||
@@ -706,23 +707,8 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
|
||||
addiction_threshold = 25
|
||||
pH = 8.96
|
||||
|
||||
/datum/reagent/medicine/morphine/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
L.ignore_slowdown(type)
|
||||
|
||||
/datum/reagent/medicine/morphine/on_mob_end_metabolize(mob/living/L)
|
||||
L.unignore_slowdown(type)
|
||||
..()
|
||||
|
||||
/datum/reagent/medicine/morphine/on_mob_life(mob/living/carbon/M)
|
||||
switch(current_cycle)
|
||||
if(11)
|
||||
to_chat(M, "<span class='warning'>You start to feel tired...</span>" )
|
||||
if(12 to 24)
|
||||
M.drowsyness += 1
|
||||
if(24 to INFINITY)
|
||||
M.Sleeping(40, 0)
|
||||
. = 1
|
||||
M.adjustPainLoss(-3*REM, 0)// very good pain killer.
|
||||
..()
|
||||
|
||||
/datum/reagent/medicine/morphine/overdose_process(mob/living/M)
|
||||
@@ -1022,6 +1008,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
|
||||
|
||||
/datum/reagent/medicine/bicaridine/on_mob_life(mob/living/carbon/M)
|
||||
M.adjustBruteLoss(-2*REM, 0)
|
||||
M.adjustPainLoss(-1*REM, 0) //stabilize pain at threshold. and bring it down faster if above.
|
||||
..()
|
||||
. = 1
|
||||
|
||||
|
||||
@@ -158,10 +158,10 @@
|
||||
var/altered_height
|
||||
altered_height = input(user, "Choose your desired sprite size:\n([MIN_BODYSIZE]-400%)", "Height Alteration") as num|null
|
||||
if(altered_height)
|
||||
H.size_multiplier = (max(min( round(text2num(altered_height)),400),MIN_BODYSIZE))/100
|
||||
H.size_multiplier = (max(min( round(text2num(altered_height)),1000),MIN_BODYSIZE))/100
|
||||
playsound(user.loc, pshoom_or_beepboopblorpzingshadashwoosh, 40, 1)
|
||||
do_sparks(5, FALSE, user.loc)
|
||||
H.visible_message("<span class='danger'>[pick("[H] shifts in size!", "[H] alters in height!", "[H] reshapes into a new stature!")]</span>")
|
||||
|
||||
else
|
||||
return
|
||||
return
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
var/burnstate = 0
|
||||
var/brute_dam = 0
|
||||
var/burn_dam = 0
|
||||
var/pain_dam = 0
|
||||
var/stamina_dam = 0
|
||||
var/max_stamina_damage = 0
|
||||
var/max_damage = 0
|
||||
@@ -193,6 +194,9 @@
|
||||
brute_dam += brute
|
||||
burn_dam += burn
|
||||
|
||||
if(status == BODYPART_ORGANIC) //pain is only applied to organic organs, because nerves.
|
||||
pain_dam += (brute+burn)*1.2 //add the total damage applied to the limb as pain damage, build pain quicker, because sudden pain is more.. painful.
|
||||
|
||||
//We've dealt the physical damages, if there's room lets apply the stamina damage.
|
||||
var/current_damage = get_damage(TRUE) //This time around, count stamina loss too.
|
||||
var/available_damage = max_damage - current_damage
|
||||
|
||||
@@ -172,9 +172,14 @@
|
||||
|
||||
// lipstick
|
||||
if(lip_style)
|
||||
var/image/lips_overlay = image('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER, SOUTH)
|
||||
lips_overlay.color = lip_color
|
||||
. += lips_overlay
|
||||
if (species_id == "human")
|
||||
var/image/lips_overlay = image('icons/mob/human_face.dmi', "lips_[lip_style]", -BODY_LAYER, SOUTH)
|
||||
lips_overlay.color = lip_color
|
||||
. += lips_overlay
|
||||
else //for animal species, because they have slightly bigger heads.
|
||||
var/image/lips_overlay = image('icons/mob/human_face.dmi', "lips_[lip_style]_mam", -BODY_LAYER, SOUTH)
|
||||
lips_overlay.color = lip_color
|
||||
. += lips_overlay
|
||||
|
||||
// eyes
|
||||
var/image/eyes_overlay = image('icons/mob/human_face.dmi', "eyes", -BODY_LAYER, SOUTH)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
//make incision
|
||||
/datum/surgery_step/incise
|
||||
name = "make incision"
|
||||
implements = list(TOOL_SCALPEL = 100, /obj/item/melee/transforming/energy/sword = 75, /obj/item/kitchen/knife = 65,
|
||||
/obj/item/shard = 45, /obj/item = 30) // 30% success with any sharp item.
|
||||
implements = list(TOOL_SCALPEL = 100, /obj/item/melee/transforming/energy/sword = 85, /obj/item/kitchen/knife = 75,
|
||||
/obj/item/shard = 65, /obj/item = 40) // 40% success with any sharp item. (Hyper change, raised chances with basic items, because if user is awake it has a higher chance to fail)
|
||||
time = 16
|
||||
|
||||
/datum/surgery_step/incise/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
var/list/chems_needed = list() //list of chems needed to complete the step. Even on success, the step will have no effect if there aren't the chems required in the mob.
|
||||
var/require_all_chems = TRUE //any on the list or all on the list?
|
||||
var/silicons_obey_prob = FALSE
|
||||
var/pain_failure = 10 //how painful it is if you fail.
|
||||
|
||||
/datum/surgery_step/proc/try_op(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
|
||||
var/success = FALSE
|
||||
@@ -62,14 +63,21 @@
|
||||
var/prob_chance = 100
|
||||
if(implement_type) //this means it isn't a require hand or any item step.
|
||||
prob_chance = implements[implement_type]
|
||||
|
||||
prob_chance *= surgery.get_propability_multiplier()
|
||||
|
||||
//if human and awake
|
||||
if (ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(H.stat == 0) //victorian surgery
|
||||
prob_chance = prob_chance *0.65 //deminish your chances, they are awake!
|
||||
|
||||
if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail)
|
||||
if(success(user, target, target_zone, tool, surgery))
|
||||
advance = TRUE
|
||||
else
|
||||
if(failure(user, target, target_zone, tool, surgery))
|
||||
advance = TRUE
|
||||
advance = FALSE
|
||||
if(advance && !repeatable)
|
||||
surgery.status++
|
||||
if(surgery.status > surgery.steps.len)
|
||||
@@ -83,15 +91,18 @@
|
||||
"[user] begins to perform surgery on [target].")
|
||||
|
||||
/datum/surgery_step/proc/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
display_results(user, target, "<span class='notice'>You succeed.</span>",
|
||||
"[user] succeeds!",
|
||||
display_results(user, target, "<span class='notice'>You complete the procedure.</span>",
|
||||
"[user] completes the procedure!",
|
||||
"[user] finishes.")
|
||||
return TRUE
|
||||
|
||||
/datum/surgery_step/proc/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
|
||||
display_results(user, target, "<span class='warning'>You screw up!</span>",
|
||||
"<span class='warning'>[user] screws up!</span>",
|
||||
display_results(user, target, "<span class='warning'>You failed the procedure!</span>",
|
||||
"<span class='warning'>[user] failed the procedure!</span>",
|
||||
"[user] finishes.", TRUE) //By default the patient will notice if the wrong thing has been cut
|
||||
if (ishuman(target)) //pain on humans for messing up.
|
||||
var/obj/item/bodypart/L = target.get_bodypart(target_zone)
|
||||
L.pain_dam += pain_failure
|
||||
return FALSE
|
||||
|
||||
/datum/surgery_step/proc/tool_check(mob/user, obj/item/tool)
|
||||
|
||||
@@ -46,7 +46,8 @@
|
||||
/obj/item/seeds/tower = 3,
|
||||
/obj/item/seeds/watermelon = 3,
|
||||
/obj/item/seeds/wheat = 3,
|
||||
/obj/item/seeds/whitebeet = 3)
|
||||
/obj/item/seeds/whitebeet = 3,
|
||||
/obj/item/seeds/kalyna = 3) //Hyperstation addition
|
||||
|
||||
contraband=list(/obj/item/seeds/amanita = 2,
|
||||
/obj/item/seeds/glowshroom = 2,
|
||||
|
||||
Reference in New Issue
Block a user