# Conflicts:
#	code/modules/ninja/suit/suit.dm
This commit is contained in:
zerothebigboy
2021-08-19 21:55:22 -04:00
708 changed files with 22153 additions and 13237 deletions
+1 -1
View File
@@ -91,7 +91,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
var/client/C = client
to_chat(C, "<span class='notice'>Sending you to [pick].</span>")
new /obj/screen/splash(C)
new /atom/movable/screen/splash(C)
mob_transforming = TRUE
sleep(29) //let the animation play
@@ -21,7 +21,7 @@
/mob/dead/new_player/Initialize()
if(client && SSticker.state == GAME_STATE_STARTUP)
var/obj/screen/splash/S = new(client, TRUE, TRUE)
var/atom/movable/screen/splash/S = new(client, TRUE, TRUE)
S.Fade(TRUE)
if(length(GLOB.newplayer_start))
@@ -567,7 +567,7 @@
if(job && !job.override_latejoin_spawn(character))
SSjob.SendToLateJoin(character)
if(!arrivals_docked)
var/obj/screen/splash/Spl = new(character.client, TRUE)
var/atom/movable/screen/splash/Spl = new(character.client, TRUE)
Spl.Fade(TRUE)
character.playsound_local(get_turf(character), 'sound/voice/ApproachingTG.ogg', 25)
@@ -436,13 +436,27 @@
/datum/sprite_accessory/tails/human/shark
name = "Shark"
icon_state = "shark"
icon_state = "carp"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/shark
name = "Shark"
icon_state = "carp"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/human/sharkalt
name = "Shark (alt)"
icon_state = "shark"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/human/sharkalt
name = "Shark (alt)"
icon_state = "shark"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_tails.dmi'
@@ -679,7 +693,7 @@
icon_state = "crow"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tail/cow
/datum/sprite_accessory/tails/mam_tails/cow
name = "Cow"
icon_state = "cow"
matrixed_sections = MATRIX_RED
@@ -897,11 +911,21 @@
/datum/sprite_accessory/tails/mam_tails/shark
name = "Shark"
icon_state = "shark"
icon_state = "carp"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/shark
name = "Shark"
icon_state = "carp"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails/mam_tails/sharkalt
name = "Shark (alt)"
icon_state = "shark"
matrixed_sections = MATRIX_RED
/datum/sprite_accessory/tails_animated/mam_tails_animated/sharkalt
name = "Shark (alt)"
icon_state = "shark"
matrixed_sections = MATRIX_RED
+1 -1
View File
@@ -447,7 +447,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(message)
to_chat(src, "<span class='ghostalert'>[message]</span>")
if(source)
var/obj/screen/alert/A = throw_alert("[REF(source)]_notify_cloning", /obj/screen/alert/notify_cloning)
var/atom/movable/screen/alert/A = throw_alert("[REF(source)]_notify_cloning", /atom/movable/screen/alert/notify_cloning)
if(A)
if(client && client.prefs && client.prefs.UI_style)
A.icon = ui_style2icon(client.prefs.UI_style)
+49 -27
View File
@@ -39,29 +39,35 @@
return
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_HUSK))) //cryosleep or husked people do not pump the blood.
//Blood regeneration if there is some space
if(blood_volume < BLOOD_VOLUME_NORMAL && !HAS_TRAIT(src, TRAIT_NOHUNGER))
if(integrating_blood > 0)
var/blood_integrated = max(integrating_blood - 1, 0)
var/blood_diff = integrating_blood - blood_integrated
integrating_blood = blood_integrated
if(blood_volume < BLOOD_VOLUME_MAXIMUM)
blood_volume += blood_diff
if(blood_volume < BLOOD_VOLUME_NORMAL)
var/nutrition_ratio = 0
switch(nutrition)
if(0 to NUTRITION_LEVEL_STARVING)
nutrition_ratio = 0.2
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
nutrition_ratio = 0.4
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
nutrition_ratio = 0.6
if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
nutrition_ratio = 0.8
else
nutrition_ratio = 1
if(satiety > 80)
nutrition_ratio *= 1.25
adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR)
blood_volume = min(BLOOD_VOLUME_NORMAL, blood_volume + 0.5 * nutrition_ratio)
if(!HAS_TRAIT(src, TRAIT_NOHUNGER))
switch(nutrition)
if(0 to NUTRITION_LEVEL_STARVING)
nutrition_ratio = 0.2
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
nutrition_ratio = 0.4
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
nutrition_ratio = 0.6
if(NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
nutrition_ratio = 0.8
else
nutrition_ratio = 1
if(satiety > 80)
nutrition_ratio *= 1.25
adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR)
blood_volume = min(BLOOD_VOLUME_NORMAL, blood_volume + 0.5 * nutrition_ratio)
//Effects of bloodloss
var/word = pick("dizzy","woozy","faint")
switch(blood_volume)
var/blood_effect_volume = blood_volume + integrating_blood
switch(blood_effect_volume)
if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS)
if(prob(10))
to_chat(src, "<span class='warning'>You feel terribly bloated.</span>")
@@ -94,14 +100,22 @@
bleed(temp_bleed)
//Makes a blood drop, leaking amt units of blood from the mob
/mob/living/carbon/proc/bleed(amt)
if(blood_volume)
/mob/living/carbon/proc/bleed(amt, force)
var/bled = FALSE //Have we bled amnt?
if(blood_volume > amt || force && blood_volume)
blood_volume = max(blood_volume - amt, 0)
if(isturf(src.loc)) //Blood loss still happens in locker, floor stays clean
if(amt >= 10)
add_splatter_floor(src.loc)
else
add_splatter_floor(src.loc, 1)
bled = TRUE
if(integrating_blood > amt || force && integrating_blood)
integrating_blood = max(integrating_blood - amt, 0)
bled = TRUE
if(!bled && !force) //If we are already cycling back through, don't do this again
bleed(amt, TRUE) //we cycle back through to try to bleed SOMETHING, not neccesarily the required amount
return
if(isturf(src.loc)) //Blood loss still happens in locker, floor stays clean
if(amt >= 10)
add_splatter_floor(src.loc)
else
add_splatter_floor(src.loc, TRUE)
/mob/living/carbon/human/bleed(amt)
amt *= physiology.bleed_mod
@@ -114,6 +128,7 @@
/mob/living/proc/restore_blood()
blood_volume = initial(blood_volume)
integrating_blood = 0
/mob/living/carbon/restore_blood()
blood_volume = (BLOOD_VOLUME_NORMAL * blood_ratio)
@@ -368,10 +383,17 @@
return
blood_ratio = 1
/mob/living/proc/AdjustBloodVol(var/value)
/mob/living/proc/AdjustBloodVol(value)
if(blood_ratio == value)
return
blood_ratio = value
if(ishuman(src))
var/mob/living/carbon/human/H = src
H.handle_blood()
/mob/living/proc/adjust_integration_blood(value, remove_actual_blood, force)
if(integrating_blood + value < 0 && remove_actual_blood)
blood_volume += value + integrating_blood
blood_volume = max(blood_volume, 0)
integrating_blood += value
integrating_blood = clamp(integrating_blood, 0, force ? INFINITY : (BLOOD_VOLUME_MAXIMUM - (integrating_blood + blood_volume)))
@@ -78,7 +78,7 @@
if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT)
//Body temperature is too hot.
throw_alert("alien_fire", /obj/screen/alert/alien_fire)
throw_alert("alien_fire", /atom/movable/screen/alert/alien_fire)
switch(bodytemperature)
if(360 to 400)
apply_damage(HEAT_DAMAGE_LEVEL_1, BURN)
@@ -7,7 +7,7 @@
meleeKnockdownPower = 75
meleeSlashHumanPower = 20
meleeSlashSAPower = 45
var/obj/screen/leap_icon = null
var/atom/movable/screen/leap_icon = null
/mob/living/carbon/alien/humanoid/hunter/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/small
+6 -6
View File
@@ -16,20 +16,20 @@
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME
//Partial pressure of the toxins in our breath
var/Toxins_pp = (breath.get_moles(/datum/gas/plasma)/breath.total_moles())*breath_pressure
var/Toxins_pp = (breath.get_moles(GAS_PLASMA)/breath.total_moles())*breath_pressure
if(Toxins_pp > tox_detect_threshold) // Detect toxins in air
adjustPlasma(breath.get_moles(/datum/gas/plasma)*250)
throw_alert("alien_tox", /obj/screen/alert/alien_tox)
adjustPlasma(breath.get_moles(GAS_PLASMA)*250)
throw_alert("alien_tox", /atom/movable/screen/alert/alien_tox)
toxins_used = breath.get_moles(/datum/gas/plasma)
toxins_used = breath.get_moles(GAS_PLASMA)
else
clear_alert("alien_tox")
//Breathe in toxins and out oxygen
breath.adjust_moles(/datum/gas/plasma, -toxins_used)
breath.adjust_moles(/datum/gas/oxygen, toxins_used)
breath.adjust_moles(GAS_PLASMA, -toxins_used)
breath.adjust_moles(GAS_O2, toxins_used)
//BREATH TEMPERATURE
handle_breath_temperature(breath)
@@ -85,7 +85,7 @@
owner.adjustOxyLoss(-heal_amt)
owner.adjustCloneLoss(-heal_amt)
if(owner.blood_volume && (owner.blood_volume < BLOOD_VOLUME_NORMAL))
owner.blood_volume += 5
owner.adjust_integration_blood(5)
else
owner.adjustPlasma(plasma_rate * 0.1)
@@ -141,7 +141,7 @@
owner.stuttering += 30
recent_queen_death = 1
owner.throw_alert("alien_noqueen", /obj/screen/alert/alien_vulnerable)
owner.throw_alert("alien_noqueen", /atom/movable/screen/alert/alien_vulnerable)
addtimer(CALLBACK(src, .proc/clear_queen_death), QUEEN_DEATH_DEBUFF_DURATION)
@@ -2,7 +2,7 @@
//The effects include: stun, knockdown, unconscious, sleeping, resting, jitteriness, dizziness, ear damage,
// eye damage, eye_blind, eye_blurry, druggy, TRAIT_BLIND trait, and TRAIT_NEARSIGHT trait.
/mob/living/carbon/alien/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
/mob/living/carbon/alien/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg, knocktofloor)
return //no
/////////////////////////////////// STUN ////////////////////////////////////
+39 -16
View File
@@ -57,7 +57,7 @@
var/oindex = active_hand_index
active_hand_index = held_index
if(hud_used)
var/obj/screen/inventory/hand/H
var/atom/movable/screen/inventory/hand/H
H = hud_used.hand_slots["[oindex]"]
if(H)
H.update_icon()
@@ -158,7 +158,7 @@
throw_mode_off()
if(!target || !isturf(loc))
return
if(istype(target, /obj/screen))
if(istype(target, /atom/movable/screen))
return
//CIT CHANGES - makes it impossible to throw while in stamina softcrit
@@ -358,10 +358,11 @@
return
I.item_flags |= BEING_REMOVED
breakouttime = I.breakouttime
var/datum/cuffbreak_checker/cuffbreak_checker = new(get_turf(src), istype(I, /obj/item/restraints)? I : null)
if(!cuff_break)
visible_message("<span class='warning'>[src] attempts to remove [I]!</span>")
to_chat(src, "<span class='notice'>You attempt to remove [I]... (This will take around [DisplayTimeText(breakouttime)] and you need to stand still.)</span>")
if(do_after(src, breakouttime, 0, target = src, required_mobility_flags = MOBILITY_RESIST))
if(do_after_advanced(src, breakouttime, src, NONE, CALLBACK(cuffbreak_checker, /datum/cuffbreak_checker.proc/check_movement), required_mobility_flags = MOBILITY_RESIST))
clear_cuffs(I, cuff_break)
else
to_chat(src, "<span class='warning'>You fail to remove [I]!</span>")
@@ -370,15 +371,36 @@
breakouttime = 50
visible_message("<span class='warning'>[src] is trying to break [I]!</span>")
to_chat(src, "<span class='notice'>You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)</span>")
if(do_after(src, breakouttime, 0, target = src, required_mobility_flags = MOBILITY_RESIST))
if(do_after_advanced(src, breakouttime, src, NONE, CALLBACK(cuffbreak_checker, /datum/cuffbreak_checker.proc/check_movement), required_mobility_flags = MOBILITY_RESIST))
clear_cuffs(I, cuff_break)
else
to_chat(src, "<span class='warning'>You fail to break [I]!</span>")
else if(cuff_break == INSTANT_CUFFBREAK)
clear_cuffs(I, cuff_break)
QDEL_NULL(cuffbreak_checker)
I.item_flags &= ~BEING_REMOVED
/datum/cuffbreak_checker
var/turf/last
var/obj/item/restraints/cuffs
/datum/cuffbreak_checker/New(turf/initial_turf, obj/item/restraints/R)
last = initial_turf
if(R)
cuffs = R
/datum/cuffbreak_checker/proc/check_movement(atom/user, delay, atom/target, time_left, do_after_flags, required_mobility_flags, required_combat_flags, mob_redirect, stage, initially_held_item, tool, list/passed_in)
if(get_turf(user) != last)
last = get_turf(user)
passed_in[1] = 0.5
if(cuffs && !cuffs.allow_breakout_movement)
return DO_AFTER_STOP
else
passed_in[1] = 1
return DO_AFTER_CONTINUE
/mob/living/carbon/proc/uncuff()
if (handcuffed)
var/obj/item/W = handcuffed
@@ -459,10 +481,6 @@
if(HAS_TRAIT(src, TRAIT_CLUMSY))
modifier -= 40 //Clumsy people are more likely to hit themselves -Honk!
//CIT CHANGES START HERE
else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
modifier -= 50
if(modifier < 100)
dropItemToGround(I)
//END OF CIT CHANGES
@@ -503,7 +521,7 @@
return ..()
/mob/living/carbon/proc/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1)
if((HAS_TRAIT(src, TRAIT_NOHUNGER) || HAS_TRAIT(src, TRAIT_TOXINLOVER)) && !force)
if(HAS_TRAIT(src, TRAIT_NOHUNGER) && !force)
return TRUE
if(nutrition < 100 && !blood && !force)
@@ -681,7 +699,7 @@
become_blind(EYES_COVERED)
else if(tinttotal >= TINT_DARKENED)
cure_blind(EYES_COVERED)
overlay_fullscreen("tint", /obj/screen/fullscreen/impaired, 2)
overlay_fullscreen("tint", /atom/movable/screen/fullscreen/impaired, 2)
else
cure_blind(EYES_COVERED)
clear_fullscreen("tint", 0)
@@ -757,10 +775,10 @@
visionseverity = 9
if(-INFINITY to -24)
visionseverity = 10
overlay_fullscreen("critvision", /obj/screen/fullscreen/crit/vision, visionseverity)
overlay_fullscreen("critvision", /atom/movable/screen/fullscreen/crit/vision, visionseverity)
else
clear_fullscreen("critvision")
overlay_fullscreen("crit", /obj/screen/fullscreen/crit, severity)
overlay_fullscreen("crit", /atom/movable/screen/fullscreen/crit, severity)
else
clear_fullscreen("crit")
clear_fullscreen("critvision")
@@ -784,7 +802,7 @@
severity = 6
if(45 to INFINITY)
severity = 7
overlay_fullscreen("oxy", /obj/screen/fullscreen/oxy, severity)
overlay_fullscreen("oxy", /atom/movable/screen/fullscreen/oxy, severity)
else
clear_fullscreen("oxy")
@@ -805,7 +823,7 @@
severity = 5
if(85 to INFINITY)
severity = 6
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
@@ -870,7 +888,7 @@
if(handcuffed)
drop_all_held_items()
stop_pulling()
throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed)
throw_alert("handcuffed", /atom/movable/screen/alert/restrained/handcuffed, new_master = src.handcuffed)
if(handcuffed.demoralize_criminals)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "handcuffed", /datum/mood_event/handcuffed)
else
@@ -949,7 +967,9 @@
/mob/living/carbon/ExtinguishMob()
for(var/X in get_equipped_items())
var/obj/item/I = X
I.acid_level = 0 //washes off the acid on our clothes
var/datum/component/acid/acid = I.GetComponent(/datum/component/acid)
if(acid)
acid.level = 0
I.extinguish() //extinguishes our clothes
..()
@@ -1253,3 +1273,6 @@
var/mob/living/carbon/C = usr
if(I.can_give())
C.give(src)
/mob/living/carbon/proc/functional_blood()
return blood_volume + integrating_blood
@@ -361,7 +361,7 @@
return embeds
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash, override_protection = 0)
/mob/living/carbon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0)
. = ..()
var/damage = override_protection ? intensity : intensity - get_eye_protection()
@@ -797,6 +797,7 @@
dna.remove_mutation(HM.name)
if(blood_volume < (BLOOD_VOLUME_NORMAL*blood_ratio))
blood_volume = (BLOOD_VOLUME_NORMAL*blood_ratio)
integrating_blood = 0
..()
/mob/living/carbon/human/check_weakness(obj/item/weapon, mob/living/attacker)
@@ -813,7 +814,7 @@
..()
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1)
if(blood && dna?.species && (NOBLOOD in dna.species.species_traits) && !HAS_TRAIT(src, TRAIT_TOXINLOVER))
if(blood && dna?.species && (NOBLOOD in dna.species.species_traits))
if(message)
visible_message("<span class='warning'>[src] dry heaves!</span>", \
"<span class='userdanger'>You try to throw up, but there's nothing in your stomach!</span>")
@@ -1027,10 +1028,10 @@
return
if(!HAS_TRAIT(src, TRAIT_IGNOREDAMAGESLOWDOWN)) //if we want to ignore slowdown from damage, but not from equipment
var/scaling = maxHealth / 100
var/health_deficiency = ((maxHealth / scaling) - (health / scaling) + (getStaminaLoss()*0.75))//CIT CHANGE - reduces the impact of staminaloss and makes stamina buffer influence it
var/health_deficiency = max(((maxHealth / scaling) - (health / scaling)), (getStaminaLoss()*0.75))
if(health_deficiency >= 40)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency-39) / 75)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency-39) / 25)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown, TRUE, (health_deficiency - 15) / 75)
add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying, TRUE, (health_deficiency - 15) / 25)
else
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown)
remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying)
@@ -1073,9 +1074,9 @@
if(HAS_TRAIT(src, TRAIT_TOXINLOVER))
return "<font color='#00ffff'>"
if(isplasmaman(src))
return "<font color='#800080'"
return "<font color='#800080'>"
if(isgolem(src))
return "<font color='#8b4513'"
return "<font color='#8b4513'>"
return "<font color='#18d855'>"
@@ -409,7 +409,7 @@
return
var/informed = FALSE
if(isrobotic(src))
apply_status_effect(/datum/status_effect/no_combat_mode/robotic_emp, severity / 20)
apply_status_effect(/datum/status_effect/robotic_emp, severity / 20)
severity *= 0.5
var/do_not_stun = FALSE
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
@@ -15,7 +15,6 @@
block_parry_data = /datum/block_parry_data/unarmed/human
default_block_parry_data = /datum/block_parry_data/unarmed/human
causes_dirt_buildup_on_floor = TRUE
//Hair colour and style
var/hair_color = "000"
@@ -52,6 +51,9 @@
var/obj/item/l_store = null
var/obj/item/s_store = null
/// When an braindead player has their equipment fiddled with, we log that info here for when they come back so they know who took their ID while they were DC'd for 30 seconds
var/list/afk_thefts
var/special_voice = "" // For changing our voice. Used by a symptom.
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
@@ -143,7 +145,7 @@
)
parry_efficiency_considered_successful = 0.01
parry_efficiency_to_counterattack = 0.01
parry_efficiency_to_counterattack = INFINITY // no counterattacks
parry_max_attacks = INFINITY
parry_failed_cooldown_duration = 1.5 SECONDS
parry_failed_stagger_duration = 1 SECONDS
@@ -182,3 +182,8 @@
destination.underwear = underwear
destination.undershirt = undershirt
destination.socks = socks
/mob/living/carbon/human/adjust_integration_blood(value, force)
if(NOBLOOD in dna.species.species_traits) //Can't lose blood if your species doesn't have any
return
. = ..()
@@ -90,13 +90,31 @@
//End bloody footprints
S.step_action()
if(movement_type & GROUND)
dirt_buildup()
/mob/living/carbon/human/Process_Spacemove(movement_dir = 0) //Temporary laziness thing. Will change to handles by species reee.
if(dna.species.space_move(src))
return TRUE
return ..()
/mob/living/carbon/human/dirt_buildup(strength)
/mob/living/carbon/human/proc/dirt_buildup(strength = 1)
if(!shoes || !(shoes.body_parts_covered & FEET))
return // barefoot advantage
return ..()
var/turf/open/T = loc
if(!istype(T) || !T.dirt_buildup_allowed)
return
var/area/A = T.loc
if(!A.dirt_buildup_allowed)
return
var/multiplier = CONFIG_GET(number/turf_dirty_multiplier)
strength *= multiplier
var/obj/effect/decal/cleanable/dirt/D = locate() in T
if(D)
D.dirty(strength)
else
T.dirtyness += strength
if(T.dirtyness >= (isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold))
D = new /obj/effect/decal/cleanable/dirt(T)
D.dirty(T.dirt_spawn_threshold - T.dirtyness)
T.dirtyness = 0 // reset.
@@ -56,7 +56,6 @@
ADD_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
ADD_TRAIT(H, TRAIT_ARMOR_BROKEN, SLIMEPUDDLE_TRAIT)
H.update_disabled_bodyparts(silent = TRUE) //silently update arms to be paralysed
@@ -99,7 +98,6 @@
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOPICKUP, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOUSE, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_SPRINT_LOCKED, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_COMBAT_MODE_LOCKED, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOBILITY_NOREST, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_ARMOR_BROKEN, SLIMEPUDDLE_TRAIT)
REMOVE_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT)
@@ -209,7 +209,7 @@
update_tint()
if(G.vision_correction)
if(HAS_TRAIT(src, TRAIT_NEARSIGHT))
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1)
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
if(!QDELETED(src))
+5 -5
View File
@@ -89,15 +89,15 @@
var/datum/species/S = dna.species
if(S.breathid == "o2")
throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy)
throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy)
else if(S.breathid == "tox")
throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox)
throw_alert("not_enough_tox", /atom/movable/screen/alert/not_enough_tox)
else if(S.breathid == "co2")
throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2)
throw_alert("not_enough_co2", /atom/movable/screen/alert/not_enough_co2)
else if(S.breathid == "n2")
throw_alert("not_enough_nitro", /obj/screen/alert/not_enough_nitro)
throw_alert("not_enough_nitro", /atom/movable/screen/alert/not_enough_nitro)
else if(S.breathid == "ch3br")
throw_alert("not_enough_ch3br", /obj/screen/alert/not_enough_ch3br)
throw_alert("not_enough_ch3br", /atom/movable/screen/alert/not_enough_ch3br)
return FALSE
else
@@ -2,3 +2,33 @@
..()
if(dna?.species?.has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
LoadComponent(/datum/component/field_of_vision, field_of_vision_type)
if(!LAZYLEN(afk_thefts))
return
var/list/print_msg = list()
print_msg += "<span class='info'>*---------*</span>"
print_msg += "<span class='userdanger'>As you snap back to consciousness, you recall people messing with your stuff...</span>"
afk_thefts = reverseRange(afk_thefts)
for(var/list/iter_theft as anything in afk_thefts)
if(!islist(iter_theft) || LAZYLEN(iter_theft) != AFK_THEFT_TIME)
stack_trace("[src] ([ckey]) returned to their body and had a null/malformed afk_theft entry. Contents: [json_encode(iter_theft)]")
continue
var/thief_name = iter_theft[AFK_THEFT_NAME]
var/theft_message = iter_theft[AFK_THEFT_MESSAGE]
var/time_since = world.time - iter_theft[AFK_THEFT_TIME]
if(time_since > AFK_THEFT_FORGET_DETAILS_TIME)
print_msg += "\t<span class='danger'><b>Someone [theft_message], but it was at least [DisplayTimeText(AFK_THEFT_FORGET_DETAILS_TIME)] ago.</b></span>"
else
print_msg += "\t<span class='danger'><b>[thief_name] [theft_message] roughly [DisplayTimeText(time_since, 10)] ago.</b></span>"
if(LAZYLEN(afk_thefts) >= AFK_THEFT_MAX_MESSAGES)
print_msg += "<span class='warning'>There may have been more, but that's all you can remember...</span>"
print_msg += "<span class='info'>*---------*</span>"
to_chat(src, print_msg.Join("\n"))
LAZYNULL(afk_thefts)
+26 -39
View File
@@ -439,6 +439,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
* * pref_load - Preferences to be loaded from character setup, loads in preferred mutant things like bodyparts, digilegs, skin color, etc.
*/
/datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
set waitfor = FALSE
// Drop the items the new species can't wear
for(var/slot_id in no_equip)
var/obj/item/thing = C.get_item_by_slot(slot_id)
@@ -679,7 +680,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/mutable_appearance/hair_overlay = mutable_appearance(layer = -HAIR_LAYER)
if(!hair_hidden && !H.getorgan(/obj/item/organ/brain)) //Applies the debrained overlay if there is no brain
if(!(NOBLOOD in species_traits))
hair_overlay.icon = 'icons/mob/hair.dmi'
hair_overlay.icon = 'icons/mob/human_parts.dmi'
hair_overlay.icon_state = "debrained"
else if(H.hair_style && (HAIR in species_traits))
@@ -1364,7 +1365,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.type == exotic_blood && !istype(exotic_blood, /datum/reagent/blood))
H.blood_volume = min(H.blood_volume + round(chem.volume, 0.1), BLOOD_VOLUME_MAXIMUM)
H.adjust_integration_blood(round(chem.volume, 0.1))
H.reagents.del_reagent(chem.type)
return TRUE
return FALSE
@@ -1458,13 +1459,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
switch(H.nutrition)
if(NUTRITION_LEVEL_FULL to INFINITY)
H.throw_alert("nutrition", /obj/screen/alert/fat)
H.throw_alert("nutrition", /atom/movable/screen/alert/fat)
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FULL)
H.clear_alert("nutrition")
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
H.throw_alert("nutrition", /obj/screen/alert/hungry)
H.throw_alert("nutrition", /atom/movable/screen/alert/hungry)
if(0 to NUTRITION_LEVEL_STARVING)
H.throw_alert("nutrition", /obj/screen/alert/starving)
H.throw_alert("nutrition", /atom/movable/screen/alert/starving)
/datum/species/proc/update_health_hud(mob/living/carbon/human/H)
return 0
@@ -1589,12 +1590,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/punchedbrute = target.getBruteLoss()
//CITADEL CHANGES - makes resting and disabled combat mode reduce punch damage, makes being out of combat mode result in you taking more damage
if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 1.2
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
damage *= 0.65
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
damage *= 0.8
//END OF CITADEL CHANGES
var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected))
@@ -1718,12 +1715,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
else
user.do_attack_animation(target, ATTACK_EFFECT_DISARM)
if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes disarmspam cause staminaloss, pugilists can do it almost effortlessly
if(!user.UseStaminaBuffer(1, warn = TRUE))
return
else
if(!user.UseStaminaBuffer(1, warn = TRUE))
return
if(!user.UseStaminaBuffer(1, warn = TRUE))
return
if(attacker_style && attacker_style.disarm_act(user,target))
return TRUE
@@ -1741,12 +1734,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
log_combat(user, target, "disarmed out of grab from")
return
var/randn = rand(1, 100)
if(SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) // CITADEL CHANGE
randn += -10 //CITADEL CHANGE - being out of combat mode makes it easier for you to get disarmed
if(!CHECK_MOBILITY(user, MOBILITY_STAND)) //CITADEL CHANGE
randn += 100 //CITADEL CHANGE - No kosher disarming if you're resting
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) //CITADEL CHANGE
randn += 25 //CITADEL CHANGE - Makes it harder to disarm outside of combat mode
if(user.pulling == target)
randn -= 20 //If you have the time to get someone in a grab, you should have a greater chance at snatching the thing in their hand. Will be made completely obsolete by the grab rework but i've got a poor track record for releasing big projects on time so w/e i guess
if(HAS_TRAIT(user, TRAIT_PUGILIST))
@@ -1951,9 +1940,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(IS_STAMCRIT(user))
to_chat(user, "<span class='warning'>You're too exhausted for that.</span>")
return
if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
to_chat(user, "<span class='warning'>You need combat mode to be active to that!</span>")
return
if(user.IsKnockdown() || user.IsParalyzed() || user.IsStun())
to_chat(user, "<span class='warning'>You can't seem to force yourself up right now!</span>")
return
@@ -1993,6 +1979,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(CHECK_MOBILITY(target, MOBILITY_STAND))
target.adjustStaminaLoss(5)
else
target.adjustStaminaLoss(target.getStaminaLoss() > 75? 5 : 75)
if(target.is_shove_knockdown_blocked())
return
@@ -2035,7 +2023,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target.visible_message("<span class='danger'>[user.name] shoves [target.name]!</span>",
"<span class='danger'>[user.name] shoves you!</span>", null, COMBAT_MESSAGE_RANGE, null,
user, "<span class='danger'>You shove [target.name]!</span>")
target.Stagger(SHOVE_STAGGER_DURATION)
var/obj/item/target_held_item = target.get_active_held_item()
if(!target.has_status_effect(STATUS_EFFECT_OFF_BALANCE))
if(target_held_item)
@@ -2182,19 +2169,19 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.adjust_bodytemperature(natural*(1/(thermal_protection+1)) + min(thermal_protection * (loc_temp - H.bodytemperature) / BODYTEMP_HEAT_DIVISOR, BODYTEMP_HEATING_MAX))
switch((loc_temp - H.bodytemperature)*thermal_protection)
if(-INFINITY to -50)
H.throw_alert("tempfeel", /obj/screen/alert/cold, 3)
H.throw_alert("tempfeel", /atom/movable/screen/alert/cold, 3)
if(-50 to -35)
H.throw_alert("tempfeel", /obj/screen/alert/cold, 2)
H.throw_alert("tempfeel", /atom/movable/screen/alert/cold, 2)
if(-35 to -20)
H.throw_alert("tempfeel", /obj/screen/alert/cold, 1)
H.throw_alert("tempfeel", /atom/movable/screen/alert/cold, 1)
if(-20 to 0) //This is the sweet spot where air is considered normal
H.clear_alert("tempfeel")
if(0 to 15) //When the air around you matches your body's temperature, you'll start to feel warm.
H.throw_alert("tempfeel", /obj/screen/alert/hot, 1)
H.throw_alert("tempfeel", /atom/movable/screen/alert/hot, 1)
if(15 to 30)
H.throw_alert("tempfeel", /obj/screen/alert/hot, 2)
H.throw_alert("tempfeel", /atom/movable/screen/alert/hot, 2)
if(30 to INFINITY)
H.throw_alert("tempfeel", /obj/screen/alert/hot, 3)
H.throw_alert("tempfeel", /atom/movable/screen/alert/hot, 3)
// +/- 50 degrees from 310K is the 'safe' zone, where no damage is dealt.
if(H.bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT && !HAS_TRAIT(H, TRAIT_RESISTHEAT))
@@ -2215,11 +2202,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if (burn_damage)
switch(burn_damage)
if(0 to 2)
H.throw_alert("temp", /obj/screen/alert/sweat, 1)
H.throw_alert("temp", /atom/movable/screen/alert/sweat, 1)
if(2 to 4)
H.throw_alert("temp", /obj/screen/alert/sweat, 2)
H.throw_alert("temp", /atom/movable/screen/alert/sweat, 2)
else
H.throw_alert("temp", /obj/screen/alert/sweat, 3)
H.throw_alert("temp", /atom/movable/screen/alert/sweat, 3)
burn_damage = burn_damage * heatmod * H.physiology.heat_mod
if (H.stat < UNCONSCIOUS && (prob(burn_damage) * 10) / 4) //40% for level 3 damage on humans
H.emote("scream")
@@ -2232,13 +2219,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/cold, multiplicative_slowdown = ((BODYTEMP_COLD_DAMAGE_LIMIT - H.bodytemperature) / COLD_SLOWDOWN_FACTOR))
switch(H.bodytemperature)
if(200 to BODYTEMP_COLD_DAMAGE_LIMIT)
H.throw_alert("temp", /obj/screen/alert/shiver, 1)
H.throw_alert("temp", /atom/movable/screen/alert/shiver, 1)
H.apply_damage(COLD_DAMAGE_LEVEL_1*coldmod*H.physiology.cold_mod, BURN)
if(120 to 200)
H.throw_alert("temp", /obj/screen/alert/shiver, 2)
H.throw_alert("temp", /atom/movable/screen/alert/shiver, 2)
H.apply_damage(COLD_DAMAGE_LEVEL_2*coldmod*H.physiology.cold_mod, BURN)
else
H.throw_alert("temp", /obj/screen/alert/shiver, 3)
H.throw_alert("temp", /atom/movable/screen/alert/shiver, 3)
H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod*H.physiology.cold_mod, BURN)
else
@@ -2253,21 +2240,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(HAZARD_HIGH_PRESSURE to INFINITY)
if(!HAS_TRAIT(H, TRAIT_RESISTHIGHPRESSURE))
H.adjustBruteLoss(min(((adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 ) * PRESSURE_DAMAGE_COEFFICIENT, MAX_HIGH_PRESSURE_DAMAGE) * H.physiology.pressure_mod)
H.throw_alert("pressure", /obj/screen/alert/highpressure, 2)
H.throw_alert("pressure", /atom/movable/screen/alert/highpressure, 2)
else
H.clear_alert("pressure")
if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE)
H.throw_alert("pressure", /obj/screen/alert/highpressure, 1)
H.throw_alert("pressure", /atom/movable/screen/alert/highpressure, 1)
if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE)
H.clear_alert("pressure")
if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE)
H.throw_alert("pressure", /obj/screen/alert/lowpressure, 1)
H.throw_alert("pressure", /atom/movable/screen/alert/lowpressure, 1)
else
if(HAS_TRAIT(H, TRAIT_RESISTLOWPRESSURE))
H.clear_alert("pressure")
else
H.adjustBruteLoss(LOW_PRESSURE_DAMAGE * H.physiology.pressure_mod)
H.throw_alert("pressure", /obj/screen/alert/lowpressure, 2)
H.throw_alert("pressure", /atom/movable/screen/alert/lowpressure, 2)
//////////
// FIRE //
@@ -6,7 +6,7 @@
species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None",
"insect_wings" = "None", "insect_fluff" = "None", "mam_snouts" = "None", "taur" = "None", "insect_markings" = "None")
"insect_wings" = "None", "insect_fluff" = "None", "mam_snouts" = "None", "taur" = "None", "insect_markings" = "None", "mam_body_markings" = list())
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
@@ -124,21 +124,21 @@
brutemod = 1.25
switch(get_charge(H))
if(ETHEREAL_CHARGE_NONE)
H.throw_alert("ethereal_charge", /obj/screen/alert/etherealcharge, 3)
H.throw_alert("ethereal_charge", /atom/movable/screen/alert/etherealcharge, 3)
if(ETHEREAL_CHARGE_NONE to ETHEREAL_CHARGE_LOWPOWER)
H.throw_alert("ethereal_charge", /obj/screen/alert/etherealcharge, 2)
H.throw_alert("ethereal_charge", /atom/movable/screen/alert/etherealcharge, 2)
if(H.health > 10.5)
apply_damage(0.65, TOX, null, null, H)
brutemod = 1.75
if(ETHEREAL_CHARGE_LOWPOWER to ETHEREAL_CHARGE_NORMAL)
H.throw_alert("ethereal_charge", /obj/screen/alert/etherealcharge, 1)
H.throw_alert("ethereal_charge", /atom/movable/screen/alert/etherealcharge, 1)
brutemod = 1.5
if(ETHEREAL_CHARGE_FULL to ETHEREAL_CHARGE_OVERLOAD)
H.throw_alert("ethereal_overcharge", /obj/screen/alert/ethereal_overcharge, 1)
H.throw_alert("ethereal_overcharge", /atom/movable/screen/alert/ethereal_overcharge, 1)
apply_damage(0.2, TOX, null, null, H)
brutemod = 1.5
if(ETHEREAL_CHARGE_OVERLOAD to ETHEREAL_CHARGE_DANGEROUS)
H.throw_alert("ethereal_overcharge", /obj/screen/alert/ethereal_overcharge, 2)
H.throw_alert("ethereal_overcharge", /atom/movable/screen/alert/ethereal_overcharge, 2)
apply_damage(0.65, TOX, null, null, H)
brutemod = 1.75
if(prob(10)) //10% each tick for ethereals to explosively release excess energy if it reaches dangerous levels
@@ -4,7 +4,7 @@
id = SPECIES_FELINID
limbs_id = SPECIES_HUMAN
mutant_bodyparts = list("mam_tail" = "Cat", "mam_ears" = "Cat", "deco_wings" = "None")
mutant_bodyparts = list("mam_tail" = "Cat", "mam_ears" = "Cat", "deco_wings" = "None", "mam_body_markings" = list())
mutantears = /obj/item/organ/ears/cat
mutanttail = /obj/item/organ/tail/cat
@@ -4,7 +4,7 @@
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None", "legs" = "Plantigrade")
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None", "legs" = "Plantigrade", "mam_body_markings" = list())
use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM
skinned_type = /obj/item/stack/sheet/animalhide/human
disliked_food = GROSS | RAW
@@ -53,16 +53,16 @@
exotic_blood_color = "#" + H.dna.features["mcolor"]
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for blooduskers
if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for bloodsuckers
return
if(!H.blood_volume)
H.blood_volume += 5
H.adjust_integration_blood(5)
H.adjustBruteLoss(5)
to_chat(H, "<span class='danger'>You feel empty!</span>")
if(H.blood_volume < (BLOOD_VOLUME_NORMAL * H.blood_ratio))
if(H.nutrition >= NUTRITION_LEVEL_STARVING)
H.blood_volume += 3
H.adjust_integration_blood(3)
H.nutrition -= 2.5
if(H.blood_volume < (BLOOD_VOLUME_OKAY*H.blood_ratio))
if(prob(5))
@@ -82,7 +82,7 @@
consumed_limb.drop_limb()
to_chat(H, "<span class='userdanger'>Your [consumed_limb] is drawn back into your body, unable to maintain its shape!</span>")
qdel(consumed_limb)
H.blood_volume += 20
H.adjust_integration_blood(20)
////////////////////////////////////////////////////////SLIMEPEOPLE///////////////////////////////////////////////////////////////////
@@ -151,7 +151,7 @@
if(prob(5))
to_chat(H, "<span class='notice'>You feel very bloated!</span>")
else if(H.nutrition >= NUTRITION_LEVEL_WELL_FED)
H.blood_volume += 3
H.adjust_integration_blood(3)
H.nutrition -= 2.5
..()
@@ -505,7 +505,7 @@
button_icon_state = "slimeeject"
..()
/datum/action/innate/integrate_extract/ApplyIcon(obj/screen/movable/action_button/current_button, force)
/datum/action/innate/integrate_extract/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force)
..(current_button, TRUE)
if(species && species.current_extract)
current_button.add_overlay(mutable_appearance(species.current_extract.icon, species.current_extract.icon_state))
@@ -559,7 +559,7 @@
return TRUE
return FALSE
/datum/action/innate/use_extract/ApplyIcon(obj/screen/movable/action_button/current_button, force)
/datum/action/innate/use_extract/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force)
..(current_button, TRUE)
if(species && species.current_extract)
current_button.add_overlay(mutable_appearance(species.current_extract.icon, species.current_extract.icon_state))
@@ -37,7 +37,7 @@
if((!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman)) && !atmos_sealed)
if(environment)
if(environment.total_moles())
if(environment.get_moles(/datum/gas/oxygen) >= 1) //Same threshhold that extinguishes fire
if(environment.get_moles(GAS_O2) >= 1) //Same threshhold that extinguishes fire
H.adjust_fire_stacks(0.5)
if(!H.on_fire && H.fire_stacks > 0)
H.visible_message("<span class='danger'>[H]'s body reacts with the atmosphere and bursts into flames!</span>","<span class='userdanger'>Your body reacts with the atmosphere and bursts into flame!</span>")
@@ -3,7 +3,7 @@
amount = dna.species.spec_stun(src,amount)
return ..()
/mob/living/carbon/human/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
/mob/living/carbon/human/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg, knocktofloor)
amount = dna.species.spec_stun(src,amount)
return ..()
@@ -128,7 +128,7 @@ There are several things that need to be remembered:
remove_overlay(UNIFORM_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_W_UNIFORM]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_W_UNIFORM]
inv.update_icon()
if(istype(w_uniform, /obj/item/clothing/under))
@@ -180,7 +180,7 @@ There are several things that need to be remembered:
remove_overlay(ID_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_ID]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_ID]
inv.update_icon()
var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER]
@@ -205,7 +205,7 @@ There are several things that need to be remembered:
remove_overlay(GLOVES_LAYER)
if(client && hud_used && hud_used.inv_slots[SLOT_GLOVES])
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLOVES]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_GLOVES]
inv.update_icon()
if(!gloves && bloody_hands)
@@ -242,7 +242,7 @@ There are several things that need to be remembered:
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_GLASSES]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_GLASSES]
inv.update_icon()
if(glasses)
@@ -269,7 +269,7 @@ There are several things that need to be remembered:
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_EARS]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_EARS]
inv.update_icon()
if(ears)
@@ -295,7 +295,7 @@ There are several things that need to be remembered:
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_SHOES]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_SHOES]
inv.update_icon()
if(dna.species.mutant_bodyparts["taur"])
@@ -330,7 +330,7 @@ There are several things that need to be remembered:
remove_overlay(SUIT_STORE_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_S_STORE]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_S_STORE]
inv.update_icon()
if(s_store)
@@ -357,7 +357,7 @@ There are several things that need to be remembered:
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
inv.update_icon()
if(head)
@@ -394,7 +394,7 @@ There are several things that need to be remembered:
remove_overlay(BELT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BELT]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_BELT]
inv.update_icon()
if(belt)
@@ -416,7 +416,7 @@ There are several things that need to be remembered:
remove_overlay(SUIT_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_SUIT]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_SUIT]
inv.update_icon()
if(wear_suit)
@@ -477,7 +477,7 @@ There are several things that need to be remembered:
/mob/living/carbon/human/update_inv_pockets()
if(client && hud_used)
var/obj/screen/inventory/inv
var/atom/movable/screen/inventory/inv
inv = hud_used.inv_slots[SLOT_L_STORE]
inv.update_icon()
@@ -506,7 +506,7 @@ There are several things that need to be remembered:
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
inv.update_icon()
if(wear_mask)
+1 -1
View File
@@ -183,7 +183,7 @@
if(!targets)
return
for(var/mob/living/carbon/C in targets)
var/obj/screen/alert/give/G = C.throw_alert("[src]", /obj/screen/alert/give)
var/atom/movable/screen/alert/give/G = C.throw_alert("[src]", /atom/movable/screen/alert/give)
if(!G)
return
G.setup(C, src, receiving)
+42 -41
View File
@@ -1,6 +1,6 @@
/mob/living/carbon/BiologicalLife(seconds, times_fired)
//Reagent processing needs to come before breathing, to prevent edge cases.
handle_organs()
handle_organs(seconds, times_fired)
. = ..() // if . is false, we are dead.
if(stat == DEAD)
stop_sound_channel(CHANNEL_HEARTBEAT)
@@ -23,7 +23,7 @@
handle_brain_damage()
if(stat != DEAD)
handle_liver()
handle_liver(seconds, times_fired)
if(stat != DEAD)
handle_corruption()
@@ -115,16 +115,18 @@
breath = loc_as_obj.handle_internal_lifeform(src, BREATH_VOLUME)
else if(isturf(loc)) //Breathe from loc as turf
var/breath_moles = 0
var/breath_ratio = 0
if(environment)
breath_moles = environment.total_moles()*BREATH_PERCENTAGE
breath_ratio = BREATH_VOLUME/environment.return_volume()
breath = loc.remove_air(breath_moles)
breath = loc.remove_air_ratio(breath_ratio)
else //Breathe from loc as obj again
if(istype(loc, /obj/))
var/obj/loc_as_obj = loc
loc_as_obj.handle_internal_lifeform(src,0)
if(breath)
breath.set_volume(BREATH_VOLUME)
check_breath(breath)
if(breath)
@@ -153,7 +155,7 @@
adjustOxyLoss(1)
failed_last_breath = 1
throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy)
throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy)
return 0
var/safe_oxy_min = 16
@@ -163,11 +165,11 @@
var/SA_para_min = 1
var/SA_sleep_min = 5
var/oxygen_used = 0
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME
var/O2_partialpressure = (breath.get_moles(/datum/gas/oxygen)/breath.total_moles())*breath_pressure
var/Toxins_partialpressure = (breath.get_moles(/datum/gas/plasma)/breath.total_moles())*breath_pressure
var/CO2_partialpressure = (breath.get_moles(/datum/gas/carbon_dioxide)/breath.total_moles())*breath_pressure
var/moles = breath.total_moles()
var/breath_pressure = (moles*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME
var/O2_partialpressure = ((breath.get_moles(GAS_O2)/moles)*breath_pressure) + (((breath.get_moles(GAS_PLUOXIUM)*8)/moles)*breath_pressure)
var/Toxins_partialpressure = (breath.get_moles(GAS_PLASMA)/moles)*breath_pressure
var/CO2_partialpressure = (breath.get_moles(GAS_CO2)/moles)*breath_pressure
//OXYGEN
@@ -181,7 +183,7 @@
adjustOxyLoss(8)
if(prob(20))
emote("cough")
throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy)
throw_alert("too_much_oxy", /atom/movable/screen/alert/too_much_oxy)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "suffocation", /datum/mood_event/suffocation)
if(O2_partialpressure < safe_oxy_min) //Not enough oxygen
@@ -191,11 +193,11 @@
var/ratio = 1 - O2_partialpressure/safe_oxy_min
adjustOxyLoss(min(5*ratio, 3))
failed_last_breath = 1
oxygen_used = breath.get_moles(/datum/gas/oxygen)*ratio
oxygen_used = breath.get_moles(GAS_O2)*ratio
else
adjustOxyLoss(3)
failed_last_breath = 1
throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy)
throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "suffocation", /datum/mood_event/suffocation)
else //Enough oxygen
@@ -203,12 +205,12 @@
o2overloadtime = 0 //reset our counter for this too
if(health >= crit_threshold)
adjustOxyLoss(-5)
oxygen_used = breath.get_moles(/datum/gas/oxygen)
oxygen_used = breath.get_moles(GAS_O2)
clear_alert("not_enough_oxy")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "suffocation")
breath.adjust_moles(/datum/gas/oxygen, -oxygen_used)
breath.adjust_moles(/datum/gas/carbon_dioxide, oxygen_used)
breath.adjust_moles(GAS_O2, -oxygen_used)
breath.adjust_moles(GAS_CO2, oxygen_used)
//CARBON DIOXIDE
if(CO2_partialpressure > safe_co2_max)
@@ -227,15 +229,15 @@
//TOXINS/PLASMA
if(Toxins_partialpressure > safe_tox_max)
var/ratio = (breath.get_moles(/datum/gas/plasma)/safe_tox_max) * 10
var/ratio = (breath.get_moles(GAS_PLASMA)/safe_tox_max) * 10
adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
throw_alert("too_much_tox", /atom/movable/screen/alert/too_much_tox)
else
clear_alert("too_much_tox")
//NITROUS OXIDE
if(breath.get_moles(/datum/gas/nitrous_oxide))
var/SA_partialpressure = (breath.get_moles(/datum/gas/nitrous_oxide)/breath.total_moles())*breath_pressure
if(breath.get_moles(GAS_NITROUS))
var/SA_partialpressure = (breath.get_moles(GAS_NITROUS)/breath.total_moles())*breath_pressure
if(SA_partialpressure > SA_para_min)
Unconscious(60)
if(SA_partialpressure > SA_sleep_min)
@@ -248,26 +250,26 @@
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "chemical_euphoria")
//BZ (Facepunch port of their Agent B)
if(breath.get_moles(/datum/gas/bz))
var/bz_partialpressure = (breath.get_moles(/datum/gas/bz)/breath.total_moles())*breath_pressure
if(breath.get_moles(GAS_BZ))
var/bz_partialpressure = (breath.get_moles(GAS_BZ)/breath.total_moles())*breath_pressure
if(bz_partialpressure > 1)
hallucination += 10
else if(bz_partialpressure > 0.01)
hallucination += 5
//TRITIUM
if(breath.get_moles(/datum/gas/tritium))
var/tritium_partialpressure = (breath.get_moles(/datum/gas/tritium)/breath.total_moles())*breath_pressure
if(breath.get_moles(GAS_TRITIUM))
var/tritium_partialpressure = (breath.get_moles(GAS_TRITIUM)/breath.total_moles())*breath_pressure
radiation += tritium_partialpressure/10
//NITRYL
if(breath.get_moles(/datum/gas/nitryl))
var/nitryl_partialpressure = (breath.get_moles(/datum/gas/nitryl)/breath.total_moles())*breath_pressure
if(breath.get_moles(GAS_NITRYL))
var/nitryl_partialpressure = (breath.get_moles(GAS_NITRYL)/breath.total_moles())*breath_pressure
adjustFireLoss(nitryl_partialpressure/4)
//MIASMA
if(breath.get_moles(/datum/gas/miasma))
var/miasma_partialpressure = (breath.get_moles(/datum/gas/miasma)/breath.total_moles())*breath_pressure
if(breath.get_moles(GAS_MIASMA))
var/miasma_partialpressure = (breath.get_moles(GAS_MIASMA)/breath.total_moles())*breath_pressure
if(miasma_partialpressure > MINIMUM_MOLES_DELTA_TO_MOVE)
if(prob(0.05 * miasma_partialpressure))
@@ -365,7 +367,7 @@
var/datum/gas_mixture/stank = new
stank.set_moles(/datum/gas/miasma,0.1)
stank.set_moles(GAS_MIASMA,0.1)
stank.set_temperature(BODYTEMP_NORMAL)
@@ -376,25 +378,25 @@
/mob/living/carbon/proc/handle_blood()
return
/mob/living/carbon/proc/handle_bodyparts()
/mob/living/carbon/proc/handle_bodyparts(seconds, times_fired)
for(var/I in bodyparts)
var/obj/item/bodypart/BP = I
if(BP.needs_processing)
. |= BP.on_life()
. |= BP.on_life(seconds, times_fired)
/mob/living/carbon/proc/handle_organs()
/mob/living/carbon/proc/handle_organs(seconds, times_fired)
if(stat != DEAD)
for(var/V in internal_organs)
var/obj/item/organ/O = V
if(O)
O.on_life()
O.on_life(seconds, times_fired)
else
if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || reagents.has_reagent(/datum/reagent/preservahyde, 1)) // No organ decay if the body contains formaldehyde. Or preservahyde.
return
for(var/V in internal_organs)
var/obj/item/organ/O = V
if(O)
O.on_death() //Needed so organs decay while inside the body.
O.on_death(seconds, times_fired) //Needed so organs decay while inside the body.
/mob/living/carbon/handle_diseases()
for(var/thing in diseases)
@@ -510,9 +512,8 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
//this updates all special effects: stun, sleeping, knockdown, druggy, stuttering, etc..
/mob/living/carbon/handle_status_effects()
..()
var/combat_mode = SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)
if(getStaminaLoss() && !HAS_TRAIT(src, TRAIT_NO_STAMINA_REGENERATION))
adjustStaminaLoss((!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? STAM_RECOVERY_STAM_CRIT : STAM_RECOVERY_RESTING) : STAM_RECOVERY_NORMAL) * (combat_mode? 0.25 : 1))
adjustStaminaLoss((!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? STAM_RECOVERY_STAM_CRIT : STAM_RECOVERY_RESTING) : STAM_RECOVERY_NORMAL))
if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && incomingstammult != 1)
incomingstammult = max(0.01, incomingstammult)
@@ -686,16 +687,16 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
//LIVER//
/////////
/mob/living/carbon/proc/handle_liver()
/mob/living/carbon/proc/handle_liver(seconds, times_fired)
var/obj/item/organ/liver/liver = getorganslot(ORGAN_SLOT_LIVER)
if((!dna && !liver) || (NOLIVER in dna.species.species_traits))
return
if(!liver || liver.organ_flags & ORGAN_FAILING)
liver_failure()
liver_failure(seconds, times_fired)
/mob/living/carbon/proc/liver_failure()
/mob/living/carbon/proc/liver_failure(seconds, times_fired)
reagents.end_metabolization(src, keep_liverless = TRUE) //Stops trait-based effects on reagents, to prevent permanent buffs
reagents.metabolize(src, can_overdose=FALSE, liverless = TRUE)
reagents.metabolize(src, seconds, times_fired, can_overdose=FALSE, liverless = TRUE)
if(HAS_TRAIT(src, TRAIT_STABLELIVER))
return
adjustToxLoss(4, TRUE, TRUE)
+10 -10
View File
@@ -80,13 +80,13 @@
if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT && !HAS_TRAIT(src, TRAIT_RESISTHEAT))
switch(bodytemperature)
if(360 to 400)
throw_alert("temp", /obj/screen/alert/hot, 1)
throw_alert("temp", /atom/movable/screen/alert/hot, 1)
apply_damage(HEAT_DAMAGE_LEVEL_1, BURN)
if(400 to 460)
throw_alert("temp", /obj/screen/alert/hot, 2)
throw_alert("temp", /atom/movable/screen/alert/hot, 2)
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
if(460 to INFINITY)
throw_alert("temp", /obj/screen/alert/hot, 3)
throw_alert("temp", /atom/movable/screen/alert/hot, 3)
if(on_fire)
apply_damage(HEAT_DAMAGE_LEVEL_3, BURN)
else
@@ -96,13 +96,13 @@
if(!istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
switch(bodytemperature)
if(200 to 260)
throw_alert("temp", /obj/screen/alert/cold, 1)
throw_alert("temp", /atom/movable/screen/alert/cold, 1)
apply_damage(COLD_DAMAGE_LEVEL_1, BURN)
if(120 to 200)
throw_alert("temp", /obj/screen/alert/cold, 2)
throw_alert("temp", /atom/movable/screen/alert/cold, 2)
apply_damage(COLD_DAMAGE_LEVEL_2, BURN)
if(-INFINITY to 120)
throw_alert("temp", /obj/screen/alert/cold, 3)
throw_alert("temp", /atom/movable/screen/alert/cold, 3)
apply_damage(COLD_DAMAGE_LEVEL_3, BURN)
else
clear_alert("temp")
@@ -117,16 +117,16 @@
switch(adjusted_pressure)
if(HAZARD_HIGH_PRESSURE to INFINITY)
adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) )
throw_alert("pressure", /obj/screen/alert/highpressure, 2)
throw_alert("pressure", /atom/movable/screen/alert/highpressure, 2)
if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE)
throw_alert("pressure", /obj/screen/alert/highpressure, 1)
throw_alert("pressure", /atom/movable/screen/alert/highpressure, 1)
if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE)
clear_alert("pressure")
if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE)
throw_alert("pressure", /obj/screen/alert/lowpressure, 1)
throw_alert("pressure", /atom/movable/screen/alert/lowpressure, 1)
else
adjustBruteLoss( LOW_PRESSURE_DAMAGE )
throw_alert("pressure", /obj/screen/alert/lowpressure, 2)
throw_alert("pressure", /atom/movable/screen/alert/lowpressure, 2)
return
@@ -173,4 +173,4 @@
if(prob(10))
var/obj/item/clothing/head/helmet/justice/escape/helmet = new(src)
equip_to_slot_or_del(helmet,SLOT_HEAD)
helmet.attack_self(src) // todo encapsulate toggle
INVOKE_ASYNC(helmet, /obj/item.proc/attack_self, src) // todo encapsulate toggle
@@ -51,7 +51,7 @@
overlays_standing[HANDCUFF_LAYER] = legcuffs
apply_overlay(LEGCUFF_LAYER)
throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = legcuffed)
throw_alert("legcuffed", /atom/movable/screen/alert/restrained/legcuffed, new_master = legcuffed)
//monkey HUD updates for items in our inventory
@@ -5,8 +5,8 @@
/mob/living/carbon/adjust_drugginess(amount)
druggy = max(druggy+amount, 0)
if(druggy)
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
overlay_fullscreen("high", /atom/movable/screen/fullscreen/high)
throw_alert("high", /atom/movable/screen/alert/high)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "high", /datum/mood_event/high)
sound_environment_override = SOUND_ENVIRONMENT_DRUGGED
else
@@ -18,8 +18,8 @@
/mob/living/carbon/set_drugginess(amount)
druggy = max(amount, 0)
if(druggy)
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
overlay_fullscreen("high", /atom/movable/screen/fullscreen/high)
throw_alert("high", /atom/movable/screen/alert/high)
else
clear_fullscreen("high")
clear_alert("high")
@@ -91,7 +91,7 @@
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_WEAR_MASK]
inv?.update_icon()
if(wear_mask)
@@ -105,7 +105,7 @@
remove_overlay(NECK_LAYER)
if(client && hud_used && hud_used.inv_slots[SLOT_NECK])
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_NECK]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_NECK]
inv.update_icon()
if(wear_neck)
@@ -119,7 +119,7 @@
remove_overlay(BACK_LAYER)
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_BACK]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_BACK]
inv?.update_icon()
if(back)
@@ -135,7 +135,7 @@
return
if(client && hud_used)
var/obj/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
var/atom/movable/screen/inventory/inv = hud_used.inv_slots[SLOT_HEAD]
inv?.update_icon()
if(head)
@@ -163,7 +163,7 @@
overlays_standing[LEGCUFF_LAYER] = legcuffs
apply_overlay(LEGCUFF_LAYER)
throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = legcuffed)
throw_alert("legcuffed", /atom/movable/screen/alert/restrained/legcuffed, new_master = legcuffed)
//mob HUD updates for items in our inventory
@@ -171,7 +171,7 @@
/mob/living/carbon/proc/update_hud_handcuffed()
if(hud_used)
for(var/hand in hud_used.hand_slots)
var/obj/screen/inventory/hand/H = hud_used.hand_slots[hand]
var/atom/movable/screen/inventory/hand/H = hud_used.hand_slots[hand]
if(H)
H.update_icon()
+1 -1
View File
@@ -141,7 +141,7 @@
ExtinguishMob()
return
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
if(!G.get_moles(/datum/gas/oxygen, 1))
if(!G.get_moles(GAS_O2, 1))
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
return
var/turf/location = get_turf(src)
+20 -7
View File
@@ -548,7 +548,7 @@
var/severity = 0
var/healthpercent = (health/maxHealth) * 100
if(hud_used?.healthdoll) //to really put you in the boots of a simplemob
var/obj/screen/healthdoll/living/livingdoll = hud_used.healthdoll
var/atom/movable/screen/healthdoll/living/livingdoll = hud_used.healthdoll
switch(healthpercent)
if(100 to INFINITY)
livingdoll.icon_state = "living0"
@@ -579,7 +579,7 @@
UNLINT(livingdoll.filters += filter(type="alpha", icon = mob_mask))
livingdoll.filters += filter(type="drop_shadow", size = -1)
if(severity > 0)
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
@@ -869,11 +869,11 @@
clear_alert("gravity")
else
if(has_gravity >= GRAVITY_DAMAGE_TRESHOLD)
throw_alert("gravity", /obj/screen/alert/veryhighgravity)
throw_alert("gravity", /atom/movable/screen/alert/veryhighgravity)
else
throw_alert("gravity", /obj/screen/alert/highgravity)
throw_alert("gravity", /atom/movable/screen/alert/highgravity)
else
throw_alert("gravity", /obj/screen/alert/weightless)
throw_alert("gravity", /atom/movable/screen/alert/weightless)
if(!override && !is_flying())
INVOKE_ASYNC(src, /atom/movable.proc/float, !has_gravity)
@@ -911,6 +911,12 @@
"<span class='userdanger'>[src] tries to remove your [what.name].</span>", target = src,
target_message = "<span class='danger'>You try to remove [who]'s [what.name].</span>")
what.add_fingerprint(src)
if(ishuman(who))
var/mob/living/carbon/human/victim_human = who
if(victim_human.key && !victim_human.client) // AKA braindead
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
var/list/new_entry = list(list(src.name, "tried unequipping your [what]", world.time))
LAZYADD(victim_human.afk_thefts, new_entry)
else
to_chat(src,"<span class='notice'>You try to remove [who]'s [what.name].</span>")
what.add_fingerprint(src)
@@ -957,6 +963,13 @@
to_chat(src, "<span class='warning'>\The [what.name] doesn't fit in that place!</span>")
return
if(ishuman(who))
var/mob/living/carbon/human/victim_human = who
if(victim_human.key && !victim_human.client) // AKA braindead
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
var/list/new_entry = list(list(src.name, "tried equipping you with [what]", world.time))
LAZYADD(victim_human.afk_thefts, new_entry)
who.visible_message("<span class='notice'>[src] tries to put [what] on [who].</span>",
"<span class='notice'>[src] tries to put [what] on you.</span>", target = src,
target_message = "<span class='notice'>You try to put [what] on [who].</span>")
@@ -995,7 +1008,7 @@
loc_temp = obj_temp
else if(isspaceturf(get_turf(src)))
var/turf/heat_turf = get_turf(src)
loc_temp = heat_turf.temperature
loc_temp = heat_turf.return_temperature()
return loc_temp
/mob/living/proc/get_standard_pixel_x_offset(lying = 0)
@@ -1146,7 +1159,7 @@
visible_message("<span class='warning'>[src] catches fire!</span>", \
"<span class='userdanger'>You're set on fire!</span>")
new/obj/effect/dummy/lighting_obj/moblight/fire(src)
throw_alert("fire", /obj/screen/alert/fire)
throw_alert("fire", /atom/movable/screen/alert/fire)
update_fire()
SEND_SIGNAL(src, COMSIG_LIVING_IGNITED,src)
return TRUE
+27 -22
View File
@@ -48,25 +48,23 @@
animate(src, pixel_x = get_standard_pixel_x_offset(), pixel_y = get_standard_pixel_y_offset(), time = 2.5, FALSE, SINE_EASING | EASE_IN)
/mob/living/proc/continue_starting_active_block()
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
return DO_AFTER_STOP
return (combat_flags & COMBAT_FLAG_ACTIVE_BLOCK_STARTING)? DO_AFTER_CONTINUE : DO_AFTER_STOP
/mob/living/get_standard_pixel_x_offset()
. = ..()
if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING))
if(dir & EAST)
. += 8
. += 4
if(dir & WEST)
. -= 8
. -= 4
/mob/living/get_standard_pixel_y_offset()
. = ..()
if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING))
if(dir & NORTH)
. += 8
. += 4
if(dir & SOUTH)
. -= 8
. -= 4
/**
* Proc called by keybindings to toggle active blocking.
@@ -100,11 +98,6 @@
if(!I.can_active_block())
to_chat(src, "<span class='warning'>[I] is either not capable of being used to actively block, or is not currently in a state that can! (Try wielding it if it's twohanded, for example.)</span>")
return
// QOL: Attempt to toggle on combat mode if it isn't already
SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
to_chat(src, "<span class='warning'>You must be in combat mode to actively block!</span>")
return FALSE
var/datum/block_parry_data/data = I.get_block_parry_data()
var/delay = data.block_start_delay
combat_flags |= COMBAT_FLAG_ACTIVE_BLOCK_STARTING
@@ -147,7 +140,7 @@
/**
* Calculates FINAL ATTACK DAMAGE after mitigation
*/
/obj/item/proc/active_block_calculate_final_damage(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
/obj/item/proc/active_block_calculate_final_damage(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, passive = FALSE)
var/datum/block_parry_data/data = get_block_parry_data()
var/absorption = data.attack_type_list_scan(data.block_damage_absorption_override, attack_type)
var/efficiency = data.attack_type_list_scan(data.block_damage_multiplier_override, attack_type)
@@ -156,7 +149,7 @@
if(isnull(absorption))
absorption = data.block_damage_absorption
if(isnull(efficiency))
efficiency = data.block_damage_multiplier
efficiency = data.block_damage_multiplier * (passive? (1 / data.block_automatic_mitigation_multiplier) : 1)
if(isnull(limit))
limit = data.block_damage_limit
// now we calculate damage to reduce.
@@ -172,7 +165,7 @@
return final_damage
/// Amount of stamina from damage blocked. Note that the damage argument is damage_blocked.
/obj/item/proc/active_block_stamina_cost(mob/living/owner, atom/object, damage_blocked, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
/obj/item/proc/active_block_stamina_cost(mob/living/owner, atom/object, damage_blocked, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, passive = FALSE)
var/datum/block_parry_data/data = get_block_parry_data()
var/efficiency = data.attack_type_list_scan(data.block_stamina_efficiency_override, attack_type)
if(isnull(efficiency))
@@ -182,7 +175,7 @@
multiplier = data.attack_type_list_scan(data.block_resting_stamina_penalty_multiplier_override, attack_type)
if(isnull(multiplier))
multiplier = data.block_resting_stamina_penalty_multiplier
return (damage_blocked / efficiency) * multiplier
return (damage_blocked / efficiency) * multiplier * (passive? data.block_automatic_stamina_multiplier : 1)
/// Apply the stamina damage to our user, notice how damage argument is stamina_amount.
/obj/item/proc/active_block_do_stamina_damage(mob/living/owner, atom/object, stamina_amount, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
@@ -214,6 +207,18 @@
return
/obj/item/proc/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
return directional_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, override_direction)
/obj/item/proc/can_passive_block()
if(!block_parry_data || !(item_flags & ITEM_CAN_BLOCK))
return FALSE
var/datum/block_parry_data/data = return_block_parry_datum(block_parry_data)
return data.block_automatic_enabled
/obj/item/proc/passive_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
return directional_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, override_direction, TRUE)
/obj/item/proc/directional_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction, passive = FALSE)
if(!can_active_block())
return BLOCK_NONE
var/datum/block_parry_data/data = get_block_parry_data()
@@ -228,12 +233,12 @@
incoming_direction = get_dir(get_turf(attacker) || get_turf(object), src)
if(!CHECK_MOBILITY(owner, MOBILITY_STAND) && !(data.block_resting_attack_types_anydir & attack_type) && (!(data.block_resting_attack_types_directional & attack_type) || !can_block_direction(owner.dir, incoming_direction)))
return BLOCK_NONE
else if(!can_block_direction(owner.dir, incoming_direction))
else if(!can_block_direction(owner.dir, incoming_direction, passive))
return BLOCK_NONE
block_return[BLOCK_RETURN_ACTIVE_BLOCK] = TRUE
var/final_damage = active_block_calculate_final_damage(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
var/final_damage = active_block_calculate_final_damage(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, passive)
var/damage_blocked = damage - final_damage
var/stamina_cost = active_block_stamina_cost(owner, object, damage_blocked, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
var/stamina_cost = active_block_stamina_cost(owner, object, damage_blocked, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return, passive)
active_block_do_stamina_damage(owner, object, stamina_cost, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
block_return[BLOCK_RETURN_ACTIVE_BLOCK_DAMAGE_MITIGATED] = damage - final_damage
block_return[BLOCK_RETURN_SET_DAMAGE_TO] = final_damage
@@ -261,9 +266,9 @@
/**
* Gets the block direction bitflags of what we can block.
*/
/obj/item/proc/blockable_directions()
/obj/item/proc/blockable_directions(passive = FALSE)
var/datum/block_parry_data/data = get_block_parry_data()
return data.can_block_directions
return (!isnull(data.block_automatic_directions) && passive)? data.block_automatic_directions : data.can_block_directions
/**
* Checks if we can block from a specific direction from our direction.
@@ -272,14 +277,14 @@
* * our_dir - our direction.
* * their_dir - their direction. Must be a single direction, or NONE for an attack from the same tile. This is incoming direction.
*/
/obj/item/proc/can_block_direction(our_dir, their_dir)
/obj/item/proc/can_block_direction(our_dir, their_dir, passive = FALSE)
their_dir = turn(their_dir, 180)
if(our_dir != NORTH)
var/turn_angle = dir2angle(our_dir)
// dir2angle(), ss13 proc is clockwise so dir2angle(EAST) == 90
// turn(), byond proc is counterclockwise so turn(NORTH, 90) == WEST
their_dir = turn(their_dir, turn_angle)
return (DIR2BLOCKDIR(their_dir) & blockable_directions())
return (DIR2BLOCKDIR(their_dir) & blockable_directions(passive))
/**
* can_block_direction but for "compound" directions to check all of them and return the number of directions that were blocked.
+164 -48
View File
@@ -14,18 +14,58 @@
/**
* Initiates a parrying sequence.
*/
/mob/living/proc/initiate_parry_sequence()
/mob/living/proc/initiate_parry_sequence(silent = FALSE, list/override_method_data)
if(parrying)
return // already parrying
return FALSE // already parrying
if(!(mobility_flags & MOBILITY_USE))
to_chat(src, "<span class='warning'>You can't move your arms!</span>")
return
if(!silent)
to_chat(src, "<span class='warning'>You can't move your arms!</span>")
return FALSE
if(!(combat_flags & COMBAT_FLAG_PARRY_CAPABLE))
to_chat(src, "<span class='warning'>You are not something that can parry attacks.</span>")
return
if(!silent)
to_chat(src, "<span class='warning'>You are not something that can parry attacks.</span>")
return FALSE
if(!(mobility_flags & MOBILITY_STAND))
to_chat(src, "<span class='warning'>You aren't able to parry without solid footing!</span>")
return
if(!silent)
to_chat(src, "<span class='warning'>You aren't able to parry without solid footing!</span>")
return FALSE
var/datum/block_parry_data/data
var/list/determined = override_method_data || determine_parry_method(FALSE, FALSE)
if(!islist(determined))
return FALSE
var/method = determined[1]
data = return_block_parry_datum(determined[2])
var/datum/tool = determined[3]
var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
// no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
// can always implement it later, whatever.
if((data.parry_respect_clickdelay && !CheckActionCooldown()) || ((parry_end_time_last + data.parry_cooldown) > world.time))
if(!silent)
to_chat(src, "<span class='warning'>You are not ready to parry (again)!</span>")
return FALSE
// Point of no return, make sure everything is set.
parrying = method
if(method == ITEM_PARRY)
active_parry_item = tool
if(!UseStaminaBuffer(data.parry_stamina_cost, TRUE))
return FALSE
parry_start_time = world.time
successful_parries = list()
successful_parry_counterattacks = list()
addtimer(CALLBACK(src, .proc/end_parry_sequence), full_parry_duration)
if(data.parry_flags & PARRY_LOCK_ATTACKING)
ADD_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_PARRY_TRAIT)
if(data.parry_flags & PARRY_LOCK_SPRINTING)
ADD_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_PARRY_TRAIT)
handle_parry_starting_effects(data)
return TRUE
/**
* Massive snowflake proc for getting something to parry with.
*
* @return list of [method, data, tool], where method is the parry method define, data is the block_parry_data var that must be run through return_block_parry_data, and tool is the concept/object/martial art/etc used.
*/
/mob/living/proc/determine_parry_method(silent = TRUE, autoparry = FALSE)
// Prioritize item, then martial art, then unarmed.
// yanderedev else if time
var/obj/item/using_item = get_active_held_item()
@@ -55,7 +95,8 @@
var/list/other_items = list()
var/list/override = list()
if(SEND_SIGNAL(src, COMSIG_LIVING_ACTIVE_PARRY_START, method, tool, other_items, override) & COMPONENT_PREVENT_PARRY_START)
to_chat(src, "<span class='warning'>Something is preventing you from parrying!</span>")
if(!silent)
to_chat(src, "<span class='warning'>Something is preventing you from parrying!</span>")
return
if(length(override))
var/datum/thing = override[1]
@@ -72,35 +113,10 @@
method = ITEM_PARRY
data = using_item.block_parry_data
if(!method)
to_chat(src, "<span class='warning'>You have nothing to parry with!</span>")
if(!silent)
to_chat(src, "<span class='warning'>You have nothing to parry with!</span>")
return FALSE
//QOL: Try to enable combat mode if it isn't already
SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE)
if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
to_chat(src, "<span class='warning'>You must be in combat mode to parry!</span>")
return FALSE
data = return_block_parry_datum(data)
var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown
// no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can.
// can always implement it later, whatever.
if((data.parry_respect_clickdelay && !CheckActionCooldown()) || ((parry_end_time_last + data.parry_cooldown) > world.time))
to_chat(src, "<span class='warning'>You are not ready to parry (again)!</span>")
return FALSE
// Point of no return, make sure everything is set.
parrying = method
if(method == ITEM_PARRY)
active_parry_item = using_item
if(!UseStaminaBuffer(data.parry_stamina_cost, TRUE))
return FALSE
parry_start_time = world.time
successful_parries = list()
addtimer(CALLBACK(src, .proc/end_parry_sequence), full_parry_duration)
if(data.parry_flags & PARRY_LOCK_ATTACKING)
ADD_TRAIT(src, TRAIT_MOBILITY_NOUSE, ACTIVE_PARRY_TRAIT)
if(data.parry_flags & PARRY_LOCK_SPRINTING)
ADD_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_PARRY_TRAIT)
handle_parry_starting_effects(data)
return TRUE
return list(method, data, tool)
/**
* Tries to find a backup parry item.
@@ -146,6 +162,7 @@
parry_start_time = 0
parry_end_time_last = world.time + (successful? 0 : data.parry_failed_cooldown_duration)
successful_parries = null
successful_parry_counterattacks = null
/**
* Handles starting effects for parrying.
@@ -178,17 +195,17 @@
/**
* Called when an attack is parried using this, whether or not the parry was successful.
*/
/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time, autoparry = FALSE)
/**
* Called when an attack is parried innately, whether or not the parry was successful.
*/
/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time, autoparry = FALSE)
/**
* Called when an attack is parried using this, whether or not the parry was successful.
*/
/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time, autoparry = FALSE)
/**
* Called when an attack is parried and block_parra_data indicates to use a proc to handle counterattack.
@@ -205,6 +222,94 @@
*/
/datum/martial_art/proc/active_parry_reflex_counter(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, parry_efficiency, list/effect_text)
/**
* Attempts to automatically parry an attacker.
*/
/mob/living/proc/attempt_auto_parry(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list())
// determine how we'll parry
var/list/determined = determine_parry_method(TRUE, TRUE)
if(!islist(determined))
return BLOCK_NONE
var/datum/block_parry_data/data = return_block_parry_datum(determined[2])
if(!data.parry_automatic_enabled || (last_autoparry > (world.time - data.autoparry_cooldown_absolute)))
return BLOCK_NONE
if(attack_type && !(attack_type & data.parry_attack_types))
return BLOCK_NONE
// before doing anything, check if the user moused over them properly
if(!client)
return BLOCK_NONE
var/found = attacker == client.mouseObject
if(!found)
for(var/i in client.moused_over_objects)
if(i == object)
if((client.moused_over_objects[i] + (data.autoparry_mouse_delay_maximum)) >= world.time)
found = TRUE
break
if(!found)
return BLOCK_NONE
// if that works, try to start parry
// first, check cooldowns
// now, depending on if we're doing a single simulation or a full sequence
last_autoparry = world.time
if(data.autoparry_sequence_simulation)
// for full sequence simulation
initiate_parry_sequence(TRUE, determined)
if(data.autoparry_sequence_start_time == -1)
parry_start_time = world.time - data.parry_time_windup
else
parry_start_time = world.time - data.autoparry_sequence_start_time
// recurse back to original
return run_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, FALSE)
else
// yes, this is mostly a copypaste of run_parry.
var/efficiency = data.attack_type_list_scan(data.autoparry_single_efficiency_override, attack_type)
if(isnull(efficiency))
efficiency = data.autoparry_single_efficiency
var/method = determined[1]
switch(method)
if(ITEM_PARRY)
var/obj/item/I = determined[3]
. = I.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
if(UNARMED_PARRY)
. = on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
if(MARTIAL_PARRY)
. = mind.martial_art.on_active_parry(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, null, TRUE)
if(!isnull(return_list[BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY])) // one of our procs overrode
efficiency = return_list[BLOCK_RETURN_OVERRIDE_PARRY_EFFICIENCY]
if(efficiency <= 0) // Do not allow automatically handled/standardized parries that increase damage for now.
return
. |= BLOCK_SHOULD_PARTIAL_MITIGATE
if(efficiency >= data.parry_efficiency_perfect)
. |= data.perfect_parry_block_return_flags
if(data.perfect_parry_block_return_list)
return_list |= data.perfect_parry_block_return_list
else if(efficiency >= data.parry_efficiency_considered_successful)
. |= data.imperfect_parry_block_return_flags
if(data.imperfect_parry_block_return_list)
return_list |= data.imperfect_parry_block_return_list
else
. |= data.failed_parry_block_return_flags
if(data.failed_parry_block_return_list)
return_list |= data.failed_parry_block_return_list
if(isnull(return_list[BLOCK_RETURN_MITIGATION_PERCENT])) // if one of the on_active_parry procs overrode. We don't have to worry about interference since parries are the first thing checked in the [do_run_block()] sequence.
return_list[BLOCK_RETURN_MITIGATION_PERCENT] = clamp(efficiency, 0, 100) // do not allow > 100% or < 0% for now.
if((return_list[BLOCK_RETURN_MITIGATION_PERCENT] >= 100) || (damage <= 0))
. |= BLOCK_SUCCESS
var/list/effect_text
var/pacifist_counter_check = TRUE
if(HAS_TRAIT(src, TRAIT_PACIFISM))
switch(parrying)
if(ITEM_PARRY)
pacifist_counter_check = (!active_parry_item.force || active_parry_item.damtype == STAMINA)
else
pacifist_counter_check = FALSE //Both martial and unarmed counter attacks generally are harmful, so no need to have the same line twice.
if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check && !return_list[BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK] && (!(attacker in successful_parry_counterattacks) && !data.parry_allow_repeated_counterattacks))
effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, data)
if(data.parry_flags & PARRY_DEFAULT_HANDLE_FEEDBACK)
handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text, data)
/**
* Gets the stage of our parry sequence we're currently in.
*/
@@ -235,12 +340,20 @@
return world.time - parry_start_time
/// same return values as normal blocking, called with absolute highest priority in the block "chain".
/mob/living/proc/run_parry(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list())
/mob/living/proc/run_parry(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), allow_auto = TRUE)
var/stage = get_parry_stage()
if(attack_type & ATTACK_TYPE_PARRY_COUNTERATTACK)
return BLOCK_NONE // don't infinite loop
if(stage != PARRY_ACTIVE)
return BLOCK_NONE
// If they're not currently parrying, attempt auto parry
if(stage == NOT_PARRYING)
if(!allow_auto || SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
return BLOCK_NONE
return attempt_auto_parry(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list)
else
return BLOCK_NONE
var/datum/block_parry_data/data = get_parry_data()
if(attack_type && (!(attack_type & data.parry_attack_types) || (attack_type & ATTACK_TYPE_PARRY_COUNTERATTACK))) // if this attack is from a parry do not parry it lest we infinite loop.
if(attack_type && !(attack_type & data.parry_attack_types))
return BLOCK_NONE
var/efficiency = data.get_parry_efficiency(attack_type, get_parry_time())
switch(parrying)
@@ -281,7 +394,7 @@
pacifist_counter_check = (!active_parry_item.force || active_parry_item.damtype == STAMINA)
else
pacifist_counter_check = FALSE //Both martial and unarmed counter attacks generally are harmful, so no need to have the same line twice.
if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check)
if(efficiency >= data.parry_efficiency_to_counterattack && pacifist_counter_check && !return_list[BLOCK_RETURN_FORCE_NO_PARRY_COUNTERATTACK] && (!(attacker in successful_parry_counterattacks) && !data.parry_allow_repeated_counterattacks))
effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency)
if(data.parry_flags & PARRY_DEFAULT_HANDLE_FEEDBACK)
handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text)
@@ -289,8 +402,9 @@
if(length(successful_parries) >= data.parry_max_attacks)
end_parry_sequence()
/mob/living/proc/handle_parry_feedback(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, list/effect_text)
var/datum/block_parry_data/data = get_parry_data()
/mob/living/proc/handle_parry_feedback(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, list/effect_text, datum/block_parry_data/data)
if(!data)
data = get_parry_data()
var/knockdown_check = FALSE
if(data.parry_data[PARRY_KNOCKDOWN_ATTACKER] && parry_efficiency >= data.parry_efficiency_to_counterattack)
knockdown_check = TRUE
@@ -299,12 +413,14 @@
visible_message("<span class='danger'>[src] parries [attack_text][length(effect_text)? ", [english_list(effect_text)] [attacker]" : ""][length(effect_text) && knockdown_check? " and" : ""][knockdown_check? " knocking them to the ground" : ""]!</span>")
/// Run counterattack if any
/mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency)
/mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, datum/block_parry_data/data)
if(!isliving(attacker))
return
var/mob/living/L = attacker
var/datum/block_parry_data/data = get_parry_data()
if(!data)
data = get_parry_data()
var/list/effect_text = list()
successful_parry_counterattacks |= attacker
// Always proc so items can override behavior easily
switch(parrying)
if(ITEM_PARRY)
+2
View File
@@ -37,6 +37,8 @@
var/results
if(I == active_block_item)
results = I.active_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list, attack_direction)
else if(I.can_passive_block() && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))
results = I.passive_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list, attack_direction)
else
results = I.run_block(src, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, return_list)
. |= results
@@ -75,7 +75,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/block_stamina_buffer_ratio = 1
/// Stamina dealt directly via UseStaminaBuffer() per SECOND of block.
var/block_stamina_cost_per_second = 1.5
var/block_stamina_cost_per_second = 1
/// Prevent stamina buffer regeneration while block?
var/block_no_stambuffer_regeneration = TRUE
/// Prevent stamina regeneration while block?
@@ -93,20 +93,31 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Sounds for blocking
var/list/block_sounds = list('sound/block_parry/block_metal1.ogg' = 1, 'sound/block_parry/block_metal1.ogg' = 1)
// Autoblock
// Other than for overrides, this mostly just reads from the above vars
/// Can this item automatically block?
var/block_automatic_enabled = TRUE
/// Directions that you can autoblock in. Null to default to normal directions.
var/block_automatic_directions = null
/// Effectiveness multiplier for automated block. Only applies to efficiency, absorption and limits stay the same!
var/block_automatic_mitigation_multiplier = 0.33
/// Stamina cost multiplier for automated block
var/block_automatic_stamina_multiplier = 1
/////////// PARRYING ////////////
/// Prioriry for [mob/do_run_block()] while we're being used to parry.
/// Priority for [mob/do_run_block()] while we're being used to parry.
// None - Parry is always highest priority!
/// Parry doesn't work if you aren't able to otherwise attack due to clickdelay
var/parry_respect_clickdelay = TRUE
var/parry_respect_clickdelay = FALSE
/// Parry stamina cost
var/parry_stamina_cost = 5
/// Attack types we can block
var/parry_attack_types = ALL
/// Parry flags
var/parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
var/parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK
/// Parry windup duration in deciseconds. 0 to this is windup, afterwards is main stage.
var/parry_time_windup = 2
var/parry_time_windup = 0
/// Parry spindown duration in deciseconds. main stage end to this is the spindown stage, afterwards the parry fully ends.
var/parry_time_spindown = 3
/// Main parry window in deciseconds. This is between [parry_time_windup] and [parry_time_spindown]
@@ -139,7 +150,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Efficiency must be at least this to be considered successful
var/parry_efficiency_considered_successful = 0.1
/// Efficiency must be at least this to run automatic counterattack
var/parry_efficiency_to_counterattack = 0.1
var/parry_efficiency_to_counterattack = INFINITY
/// Maximum attacks to parry successfully or unsuccessfully (but not efficiency < 0) during active period, hitting this immediately ends the sequence.
var/parry_max_attacks = INFINITY
/// Visual icon state override for parrying
@@ -153,7 +164,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
/// Stagger duration post-parry if you fail to parry an attack
var/parry_failed_stagger_duration = 3.5 SECONDS
/// Clickdelay duration post-parry if you fail to parry an attack
var/parry_failed_clickcd_duration = 2 SECONDS
var/parry_failed_clickcd_duration = 0 SECONDS
/// Parry cooldown post-parry if failed. This is ADDED to parry_cooldown!!!
var/parry_failed_cooldown_duration = 0 SECONDS
@@ -166,6 +177,29 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/perfect_parry_block_return_list
var/imperfect_parry_block_return_list
var/failed_parry_block_return_list
/// Allow multiple counterattacks per parry sequence. Bad idea.
var/parry_allow_repeated_counterattacks = FALSE
// Auto parry
// Anything not specified like cooldowns/clickdelay respecting is pulled from above.
/// Can this data automatically parry? This is off by default because this is something that requires thought to balance.
var/parry_automatic_enabled = FALSE
/// Hard autoparry cooldown
var/autoparry_cooldown_absolute = 7.5 SECONDS
/// Autoparry : Simulate a parry sequence starting at a certain tick, or simply simulate a single attack parry?
var/autoparry_sequence_simulation = FALSE
// Single attack simulation:
/// Single attack autoparry - efficiency
var/autoparry_single_efficiency = 75
/// Single attack autoparry - efficiency overrides by attack type, see above
var/list/autoparry_single_efficiency_override
// Parry sequence simulation:
/// Decisecond of sequence to start on. -1 to start to 0th tick of active parry window.
var/autoparry_sequence_start_time = -1
// Clickdelay/cooldown settings not included, as well as whether or not to lock attack/sprinting/etc. They will be pulled from the above.
/// ADVANCED - Autoparry requirement for time since last moused over for a specific object
var/autoparry_mouse_delay_maximum = 0.35 SECONDS
/**
* Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag.
@@ -308,6 +342,7 @@ GLOBAL_LIST_EMPTY(block_parry_data)
RENDER_VARIABLE_SIMPLE(parry_cooldown, "Deciseconds it has to be since the last time a parry sequence <b>ended</b> for you before you can parry again.")
RENDER_VARIABLE_SIMPLE(parry_failed_stagger_duration, "Deciseconds you are staggered for at the of the parry sequence if you do not successfully parry anything.")
RENDER_VARIABLE_SIMPLE(parry_failed_clickcd_duration, "Deciseconds you are put on attack cooldown at the end of the parry sequence if you do not successfully parry anything.")
dat += ""
dat += "</div></table>"
return dat.Join("")
#undef RENDER_VARIABLE_SIMPLE
+1 -1
View File
@@ -539,7 +539,7 @@
//called when the mob receives a bright flash
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash, override_protection = 0)
/mob/living/proc/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0)
if((override_protection || get_eye_protection() < intensity) && (override_blindness_check || !(HAS_TRAIT(src, TRAIT_BLIND))))
overlay_fullscreen("flash", type)
addtimer(CALLBACK(src, .proc/clear_fullscreen, "flash", 25), 25)
+5 -2
View File
@@ -50,8 +50,12 @@
var/obj/effect/abstract/parry/parry_visual_effect
/// world.time of last parry end
var/parry_end_time_last = 0
/// Last autoparry
var/last_autoparry = 0
/// Successful parries within the current parry cycle. It's a list of efficiency percentages.
var/list/successful_parries
/// Current parry counterattacks. Makes sure we can only counterattack someone once per parry.
var/list/successful_parry_counterattacks
var/confused = 0 //Makes the mob move in random directions.
@@ -63,8 +67,6 @@
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = FALSE //FALSE is off, INCORPOREAL_MOVE_BASIC is normal, INCORPOREAL_MOVE_SHADOW is for ninjas
//and INCORPOREAL_MOVE_JAUNT is blocked by holy water/salt
/// Do we make floors dirty as we move?
var/causes_dirt_buildup_on_floor = FALSE
var/list/roundstart_quirks = list()
@@ -110,6 +112,7 @@
var/stun_absorption = null //converted to a list of stun absorption sources this mob has when one is added
var/blood_volume = 0 //how much blood the mob has
var/integrating_blood = 0 //this is the variable you want to affect if you want to give the mob blood, this will slowly turn into normal blood, preventing some cheesyness, use adjust_integration_blood() instead of modifying directly
var/blood_ratio = 1 //How much blood the mob needs, in terms of ratio (i.e 1.2 will require BLOOD_VOLUME_NORMAL of 672) DO NOT GO ABOVE 3.55 Well, actually you can but, then they can't get enough blood.
var/obj/effect/proc_holder/ranged_ability //Any ranged ability the mob has, as a click override
@@ -102,31 +102,6 @@
if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
makeTrail(newloc, T, old_direction)
if(causes_dirt_buildup_on_floor && (movement_type & GROUND))
dirt_buildup()
/**
* Attempts to make the floor dirty.
*/
/mob/living/proc/dirt_buildup(strength = 1)
var/turf/open/T = loc
if(!istype(T) || !T.dirt_buildup_allowed)
return
var/area/A = T.loc
if(!A.dirt_buildup_allowed)
return
var/multiplier = CONFIG_GET(number/turf_dirty_multiplier)
strength *= multiplier
var/obj/effect/decal/cleanable/dirt/D = locate() in T
if(D)
D.dirty(strength)
else
T.dirtyness += strength
if(T.dirtyness >= (isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold))
D = new /obj/effect/decal/cleanable/dirt(T)
D.dirty(T.dirt_spawn_threshold - T.dirtyness)
T.dirtyness = 0 // reset.
/mob/living/Move_Pulled(atom/A)
. = ..()
if(!. || !isliving(A))
+1 -1
View File
@@ -3,7 +3,7 @@
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_SPRINT_LOCKED), .proc/update_sprint_lock)
/mob/living/proc/update_sprint_icon()
var/obj/screen/sprintbutton/S = locate() in hud_used?.static_inventory
var/atom/movable/screen/sprintbutton/S = locate() in hud_used?.static_inventory
S?.update_icon()
/mob/living/proc/update_hud_sprint_bar()
+28 -7
View File
@@ -267,16 +267,10 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
eavesdrop_range = EAVESDROP_EXTRA_RANGE
var/list/listening = get_hearers_in_view(message_range+eavesdrop_range, source)
var/list/the_dead = list()
var/list/yellareas //CIT CHANGE - adds the ability for yelling to penetrate walls and echo throughout areas
if(!eavesdrop_range && say_test(message) == "2") //CIT CHANGE - ditto
yellareas = get_areas_in_range(message_range*0.5, source) //CIT CHANGE - ditto
for(var/_M in GLOB.player_list)
var/mob/M = _M
if(M.stat != DEAD) //not dead, not important
if(yellareas) //CIT CHANGE - see above. makes yelling penetrate walls
var/area/A = get_area(M) //CIT CHANGE - ditto
if(istype(A) && A.ambientsounds != SPACE && (A in yellareas)) //CIT CHANGE - ditto
listening |= M //CIT CHANGE - ditto
continue
if(!M.client || !client) //client is so that ghosts don't have to listen to mice
continue
@@ -303,6 +297,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
AM.Hear(rendered, src, message_language, message, null, spans, message_mode, source)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
if(!eavesdrop_range && say_test(message) == "2") // Yell hook
process_yelling(listening, rendered, src, message_language, message, spans, message_mode, source)
//speech bubble
var/list/speech_bubble_recipients = list()
for(var/mob/M in listening)
@@ -312,6 +309,30 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
/atom/movable/proc/process_yelling(list/already_heard, rendered, atom/movable/speaker, datum/language/message_language, message, list/spans, message_mode, obj/source)
if(last_yell > (world.time - 10))
to_chat(src, "<span class='warning'>Your voice doesn't project as far as you try to yell in such quick succession.") // yeah no, no spamming an expensive floodfill.
return
last_yell = world.time
var/list/overhearing = list()
var/list/overhearing_text = list()
overhearing = yelling_wavefill(src, yell_power)
if(!overhearing.len)
overhearing_text = "none"
else
for(var/mob/M as anything in overhearing)
overhearing_text += key_name(M)
overhearing_text = english_list(overhearing_text)
log_say("YELL: [ismob(src)? key_name(src) : src] yelled [message] with overhearing mobs [overhearing_text]")
// overhearing = get_hearers_in_view(35, src) | get_hearers_in_range(5, src)
overhearing -= already_heard
if(!overhearing.len)
return
// to_chat(world, "DEBUG: overhearing [english_list(overhearing)]")
for(var/_AM in overhearing)
var/atom/movable/AM = _AM
AM.Hear(rendered, speaker, message_language, message, null, spans, message_mode, source)
/mob/proc/binarycheck()
return FALSE
+2 -1
View File
@@ -91,7 +91,7 @@
var/multicam_on = FALSE
var/obj/screen/movable/pic_in_pic/ai/master_multicam
var/atom/movable/screen/movable/pic_in_pic/ai/master_multicam
var/list/multicam_screens = list()
var/list/all_eyes = list()
var/max_multicams = 6
@@ -182,6 +182,7 @@
. = ..()
/mob/living/silicon/ai/proc/set_core_display_icon(input, client/C)
set waitfor = FALSE
if(client && !C)
C = client
if(!input && !C?.prefs?.preferred_ai_core_display)
+17 -17
View File
@@ -1,34 +1,34 @@
//Picture in picture
/obj/screen/movable/pic_in_pic/ai
/atom/movable/screen/movable/pic_in_pic/ai
var/mob/living/silicon/ai/ai
var/mutable_appearance/highlighted_background
var/highlighted = FALSE
var/mob/camera/aiEye/pic_in_pic/aiEye
/obj/screen/movable/pic_in_pic/ai/Initialize()
/atom/movable/screen/movable/pic_in_pic/ai/Initialize()
. = ..()
aiEye = new /mob/camera/aiEye/pic_in_pic()
aiEye.screen = src
/obj/screen/movable/pic_in_pic/ai/Destroy()
/atom/movable/screen/movable/pic_in_pic/ai/Destroy()
set_ai(null)
QDEL_NULL(aiEye)
return ..()
/obj/screen/movable/pic_in_pic/ai/Click()
/atom/movable/screen/movable/pic_in_pic/ai/Click()
..()
if(ai)
ai.select_main_multicam_window(src)
/obj/screen/movable/pic_in_pic/ai/make_backgrounds()
/atom/movable/screen/movable/pic_in_pic/ai/make_backgrounds()
..()
highlighted_background = new /mutable_appearance()
highlighted_background.icon = 'icons/misc/pic_in_pic.dmi'
highlighted_background.icon_state = "background_highlight"
highlighted_background.layer = SPACE_LAYER
/obj/screen/movable/pic_in_pic/ai/add_background()
/atom/movable/screen/movable/pic_in_pic/ai/add_background()
if((width > 0) && (height > 0))
var/matrix/M = matrix()
M.Scale(width + 0.5, height + 0.5)
@@ -37,35 +37,35 @@
standard_background.transform = M
add_overlay(highlighted ? highlighted_background : standard_background)
/obj/screen/movable/pic_in_pic/ai/set_view_size(width, height, do_refresh = TRUE)
/atom/movable/screen/movable/pic_in_pic/ai/set_view_size(width, height, do_refresh = TRUE)
aiEye.static_visibility_range = (round(max(width, height) / 2) + 1)
if(ai)
ai.camera_visibility(aiEye)
..()
/obj/screen/movable/pic_in_pic/ai/set_view_center(atom/target, do_refresh = TRUE)
/atom/movable/screen/movable/pic_in_pic/ai/set_view_center(atom/target, do_refresh = TRUE)
..()
aiEye.setLoc(get_turf(target))
/obj/screen/movable/pic_in_pic/ai/refresh_view()
/atom/movable/screen/movable/pic_in_pic/ai/refresh_view()
..()
aiEye.setLoc(get_turf(center))
/obj/screen/movable/pic_in_pic/ai/proc/highlight()
/atom/movable/screen/movable/pic_in_pic/ai/proc/highlight()
if(highlighted)
return
highlighted = TRUE
cut_overlay(standard_background)
add_overlay(highlighted_background)
/obj/screen/movable/pic_in_pic/ai/proc/unhighlight()
/atom/movable/screen/movable/pic_in_pic/ai/proc/unhighlight()
if(!highlighted)
return
highlighted = FALSE
cut_overlay(highlighted_background)
add_overlay(standard_background)
/obj/screen/movable/pic_in_pic/ai/proc/set_ai(mob/living/silicon/ai/new_ai)
/atom/movable/screen/movable/pic_in_pic/ai/proc/set_ai(mob/living/silicon/ai/new_ai)
if(ai)
ai.multicam_screens -= src
ai.all_eyes -= aiEye
@@ -120,7 +120,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
invisibility = INVISIBILITY_OBSERVER
mouse_opacity = MOUSE_OPACITY_ICON
icon_state = "ai_pip_camera"
var/obj/screen/movable/pic_in_pic/ai/screen
var/atom/movable/screen/movable/pic_in_pic/ai/screen
var/list/cameras_telegraphed = list()
var/telegraph_cameras = TRUE
var/telegraph_range = 7
@@ -204,7 +204,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
if(!silent)
to_chat(src, "<span class='warning'>Cannot place more than [max_multicams] multicamera windows.</span>")
return
var/obj/screen/movable/pic_in_pic/ai/C = new /obj/screen/movable/pic_in_pic/ai()
var/atom/movable/screen/movable/pic_in_pic/ai/C = new /atom/movable/screen/movable/pic_in_pic/ai()
C.set_view_size(3, 3, FALSE)
C.set_view_center(get_turf(eyeobj))
C.set_ai(src)
@@ -235,7 +235,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
reset_perspective(GLOB.ai_camera_room_landmark)
if(client)
for(var/V in multicam_screens)
var/obj/screen/movable/pic_in_pic/P = V
var/atom/movable/screen/movable/pic_in_pic/P = V
P.show_to(client)
/mob/living/silicon/ai/proc/end_multicam()
@@ -245,13 +245,13 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
select_main_multicam_window(null)
if(client)
for(var/V in multicam_screens)
var/obj/screen/movable/pic_in_pic/P = V
var/atom/movable/screen/movable/pic_in_pic/P = V
P.unshow_to(client)
reset_perspective()
to_chat(src, "<span class='notice'>Multiple-camera viewing mode deactivated.</span>")
/mob/living/silicon/ai/proc/select_main_multicam_window(obj/screen/movable/pic_in_pic/ai/P)
/mob/living/silicon/ai/proc/select_main_multicam_window(atom/movable/screen/movable/pic_in_pic/ai/P)
if(master_multicam == P)
return
@@ -1,4 +1,5 @@
/mob/living/silicon/examine(mob/user) //Displays a silicon's laws to ghosts
. = ..()
if(laws && isobserver(user))
. += "<b>[src] has the following laws:</b>"
for(var/law in laws.get_law_list(include_zeroth = TRUE))
+1 -1
View File
@@ -6,7 +6,7 @@
make_laws()
/mob/living/silicon/proc/post_lawchange(announce = TRUE)
throw_alert("newlaw", /obj/screen/alert/newlaw)
throw_alert("newlaw", /atom/movable/screen/alert/newlaw)
if(announce && last_lawchange_announce != world.time)
to_chat(src, "<b>Your laws have been changed.</b>")
addtimer(CALLBACK(src, .proc/show_laws), 0)
@@ -575,7 +575,7 @@
for(var/id in environment.get_gases())
var/gas_level = environment.get_moles(id)/total_moles
if(gas_level > 0.01)
dat += "[GLOB.meta_gas_names[id]]: [round(gas_level*100)]%<br>"
dat += "[GLOB.gas_data.names[id]]: [round(gas_level*100)]%<br>"
dat += "Temperature: [round(environment.return_temperature()-T0C)]&deg;C<br>"
dat += "<a href='byond://?src=[REF(src)];software=atmosensor;sub=0'>Refresh Reading</a> <br>"
dat += "<br>"
@@ -58,15 +58,15 @@
if(0.75 to INFINITY)
clear_alert("charge")
if(0.5 to 0.75)
throw_alert("charge", /obj/screen/alert/lowcell, 1)
throw_alert("charge", /atom/movable/screen/alert/lowcell, 1)
if(0.25 to 0.5)
throw_alert("charge", /obj/screen/alert/lowcell, 2)
throw_alert("charge", /atom/movable/screen/alert/lowcell, 2)
if(0.01 to 0.25)
throw_alert("charge", /obj/screen/alert/lowcell, 3)
throw_alert("charge", /atom/movable/screen/alert/lowcell, 3)
else
throw_alert("charge", /obj/screen/alert/emptycell)
throw_alert("charge", /atom/movable/screen/alert/emptycell)
else
throw_alert("charge", /obj/screen/alert/nocell)
throw_alert("charge", /atom/movable/screen/alert/nocell)
//Robots on fire
/mob/living/silicon/robot/handle_fire()
@@ -23,9 +23,9 @@
robot_modules_background.layer = HUD_LAYER //Objects that appear on screen are on layer ABOVE_HUD_LAYER, UI should be just below it.
robot_modules_background.plane = HUD_PLANE
inv1 = new /obj/screen/robot/module1()
inv2 = new /obj/screen/robot/module2()
inv3 = new /obj/screen/robot/module3()
inv1 = new /atom/movable/screen/robot/module1()
inv2 = new /atom/movable/screen/robot/module2()
inv3 = new /atom/movable/screen/robot/module3()
previous_health = health
@@ -598,7 +598,7 @@
if(wires.is_cut(WIRE_LOCKDOWN))
state = TRUE
if(state)
throw_alert("locked", /obj/screen/alert/locked)
throw_alert("locked", /atom/movable/screen/alert/locked)
else
clear_alert("locked")
locked_down = state
@@ -611,7 +611,7 @@
module.rebuild_modules()
update_icons()
if(emagged)
throw_alert("hacked", /obj/screen/alert/hacked)
throw_alert("hacked", /atom/movable/screen/alert/hacked)
else
clear_alert("hacked")
@@ -992,7 +992,8 @@
upgrades.Cut()
speed = 0
vtec = 0
vtec_disabled = FALSE
ionpulse = FALSE
revert_shell()
@@ -82,6 +82,18 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real
if(!opened)
return ..()
/mob/living/silicon/robot/disarm_shove(mob/living/carbon/human/H)
visible_message(span_danger("[src]'s motors grind as they are shoved by [H]!"))
vtec_disable(10 SECONDS)
/mob/living/silicon/robot/proc/vtec_disable(time)
var/datum/status_effect/vtec_disabled/V = has_status_effect(/datum/status_effect/vtec_disabled)
if(V)
V.duration = max(V.duration, world.time + time)
else
apply_status_effect(/datum/status_effect/vtec_disabled, time)
update_movespeed()
/mob/living/silicon/robot/fire_act()
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
IgniteMob()
@@ -26,15 +26,15 @@
var/previous_health
//Hud stuff
var/obj/screen/inv1 = null
var/obj/screen/inv2 = null
var/obj/screen/inv3 = null
var/obj/screen/lamp_button = null
var/obj/screen/thruster_button = null
var/obj/screen/hands = null
var/atom/movable/screen/inv1 = null
var/atom/movable/screen/inv2 = null
var/atom/movable/screen/inv3 = null
var/atom/movable/screen/lamp_button = null
var/atom/movable/screen/thruster_button = null
var/atom/movable/screen/hands = null
var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not
var/obj/screen/robot_modules_background
var/atom/movable/screen/robot_modules_background
//3 Modules can be activated at any one time.
var/obj/item/robot_module/module = null
@@ -61,7 +61,9 @@
var/alarms = list("Motion"=list(), "Fire"=list(), "Atmosphere"=list(), "Power"=list(), "Camera"=list(), "Burglar"=list())
var/speed = 0 // VTEC speed boost.
var/vtec = 0 // VTEC speed boost.
/// vtec shorted out
var/vtec_disabled = FALSE
var/magpulse = FALSE // Magboot-like effect.
var/ionpulse = FALSE // Jetpack-like effect.
var/ionpulse_on = FALSE // Jetpack-like effect.
@@ -88,14 +90,14 @@
///Lamp brightness. Starts at 3, but can be 1 - 5.
var/lamp_intensity = 3
///Lamp button reference
var/obj/screen/robot/lamp/lampButton
var/atom/movable/screen/robot/lamp/lampButton
var/sight_mode = 0
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_TRACK_HUD)
///The reference to the built-in tablet that borgs carry.
var/obj/item/modular_computer/tablet/integrated/modularInterface
var/obj/screen/robot/modPC/interfaceButton
var/atom/movable/screen/robot/modPC/interfaceButton
var/list/upgrades = list()
@@ -23,4 +23,4 @@
. = ..()
if(!resting && !(combat_flags & COMBAT_FLAG_SPRINT_ACTIVE))
. += 1
. += speed
. += vtec_disabled? 0 : vtec
@@ -79,6 +79,8 @@
M.visible_message("[M] pets [src].", \
"<span class='notice'>You pet [src].</span>", target = src,
target_message = "[M] pets you.")
if(INTENT_DISARM)
disarm_shove(M)
if(INTENT_GRAB)
grabbedby(M)
else
@@ -88,6 +90,9 @@
"<span class='warning'>[M] punches you, but doesn't leave a dent.</span>", null, COMBAT_MESSAGE_RANGE, null, M,
"<span class='danger'>You punch [src], but don't leave a dent.</span>")
/mob/living/silicon/proc/disarm_shove(mob/living/carbon/human/H)
visible_message(span_danger("[H] shoves [src], but doesn't manage to make much of an effect."))
/mob/living/silicon/attack_drone(mob/living/simple_animal/drone/M)
if(M.a_intent == INTENT_HARM)
return
@@ -139,6 +144,6 @@
P.on_hit(src, 0, def_zone)
return BULLET_ACT_HIT
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/static)
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/flash/static)
if(affect_silicon)
return ..()
@@ -33,7 +33,7 @@
/mob/living/simple_animal/bot/secbot/grievous/Initialize()
. = ..()
weapon = new baton_type(src)
weapon.attack_self(src)
INVOKE_ASYNC(weapon, /obj/item.proc/attack_self, src)
/mob/living/simple_animal/bot/secbot/grievous/Destroy()
QDEL_NULL(weapon)
@@ -753,6 +753,12 @@
else
return null
/mob/living/simple_animal/bot/mulebot/remove_air_ratio(ratio)
if(loc)
return loc.remove_air_ratio(ratio)
else
return null
/mob/living/simple_animal/bot/mulebot/do_resist()
. = ..()
if(load)
@@ -381,6 +381,7 @@
..()
/mob/living/simple_animal/pet/dog/corgi/Ian/proc/Read_Memory()
set waitfor = FALSE
if(fexists("data/npc_saves/Ian.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Ian.sav")
S["age"] >> age
@@ -55,7 +55,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
var/cooldown = 0
var/mob/living/carbon/summoner
var/range = 13 //how far from the user the spirit can be
var/toggle_button_type = /obj/screen/guardian/ToggleMode/Inactive //what sort of toggle button the hud uses
var/toggle_button_type = /atom/movable/screen/guardian/ToggleMode/Inactive //what sort of toggle button the hud uses
var/playstyle_string = "<span class='holoparasite bold'>You are a standard Guardian. You shouldn't exist!</span>"
var/magic_fluff_string = "<span class='holoparasite'>You draw the Coder, symbolizing bugs and errors. This shouldn't happen! Submit a bug report!</span>"
var/tech_fluff_string = "<span class='holoparasite'>BOOT SEQUENCE COMPLETE. ERROR MODULE LOADED. THIS SHOULDN'T HAPPEN. Submit a bug report!</span>"
@@ -11,11 +11,11 @@
tech_fluff_string = "<span class='holoparasite'>Boot sequence complete. Assassin modules loaded. Holoparasite swarm online.</span>"
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! Caught one! It's an assassin carp! Just when you thought it was safe to go back to the water... which is unhelpful, because we're in space.</span>"
toggle_button_type = /obj/screen/guardian/ToggleMode/Assassin
toggle_button_type = /atom/movable/screen/guardian/ToggleMode/Assassin
var/toggle = FALSE
var/stealthcooldown = 100
var/obj/screen/alert/canstealthalert
var/obj/screen/alert/instealthalert
var/atom/movable/screen/alert/canstealthalert
var/atom/movable/screen/alert/instealthalert
/mob/living/simple_animal/hostile/guardian/assassin/Initialize()
. = ..()
@@ -86,12 +86,12 @@
if(stealthcooldown <= world.time)
if(toggle)
if(!instealthalert)
instealthalert = throw_alert("instealth", /obj/screen/alert/instealth)
instealthalert = throw_alert("instealth", /atom/movable/screen/alert/instealth)
clear_alert("canstealth")
canstealthalert = null
else
if(!canstealthalert)
canstealthalert = throw_alert("canstealth", /obj/screen/alert/canstealth)
canstealthalert = throw_alert("canstealth", /atom/movable/screen/alert/canstealth)
clear_alert("instealth")
instealthalert = null
else
@@ -12,14 +12,14 @@
tech_fluff_string = "<span class='holoparasite'>Boot sequence complete. Charge modules loaded. Holoparasite swarm online.</span>"
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! Caught one! It's a charger carp, that likes running at people. But it doesn't have any legs...</span>"
var/charging = 0
var/obj/screen/alert/chargealert
var/atom/movable/screen/alert/chargealert
/mob/living/simple_animal/hostile/guardian/charger/BiologicalLife(seconds, times_fired)
if(!(. = ..()))
return
if(ranged_cooldown <= world.time)
if(!chargealert)
chargealert = throw_alert("charge", /obj/screen/alert/cancharge)
chargealert = throw_alert("charge", /atom/movable/screen/alert/cancharge)
else
clear_alert("charge")
chargealert = null
@@ -8,7 +8,7 @@
magic_fluff_string = "<span class='holoparasite'>..And draw the Guardian, a stalwart protector that never leaves the side of its charge.</span>"
tech_fluff_string = "<span class='holoparasite'>Boot sequence complete. Protector modules loaded. Holoparasite swarm online.</span>"
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! You caught one! Wait, no... it caught you! The fisher has become the fishy.</span>"
toggle_button_type = /obj/screen/guardian/ToggleMode
toggle_button_type = /atom/movable/screen/guardian/ToggleMode
var/toggle = FALSE
/mob/living/simple_animal/hostile/guardian/protector/ex_act(severity)
@@ -23,7 +23,7 @@
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! Caught one, it's a ranged carp. This fishy can watch people pee in the ocean.</span>"
see_invisible = SEE_INVISIBLE_LIVING
see_in_dark = 8
toggle_button_type = /obj/screen/guardian/ToggleMode
toggle_button_type = /atom/movable/screen/guardian/ToggleMode
var/list/snares = list()
var/toggle = FALSE
@@ -10,7 +10,7 @@
magic_fluff_string = "<span class='holoparasite'>..And draw the CMO, a potent force of life... and death.</span>"
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! You caught a support carp. It's a kleptocarp!</span>"
tech_fluff_string = "<span class='holoparasite'>Boot sequence complete. Support modules active. Holoparasite swarm online.</span>"
toggle_button_type = /obj/screen/guardian/ToggleMode
toggle_button_type = /atom/movable/screen/guardian/ToggleMode
var/obj/structure/receiving_pad/beacon
var/beacon_cooldown = 0
var/toggle = FALSE
@@ -133,6 +133,10 @@
chance_to_hold_onto_points = highest_cost*0.5
if(points != max_points && prob(chance_to_hold_onto_points))
return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!)
do_ability()
/datum/boss_active_timed_battle/proc/do_ability()
set waitfor = FALSE
if(!boss.client)
abilities = shuffle(abilities)
for(var/ab in abilities)
@@ -94,7 +94,7 @@
L.SetUnconscious(0, FALSE)
L.adjustOxyLoss(-50)// do CPR first
if(L.blood_volume <= 500) //bandage them up and give em some blood if they're bleeding
L.blood_volume += 30
L.adjust_integration_blood(30)
L.bleedsuppress = 0
if(L.getBruteLoss() >= 50)// first, did we beat them into crit? if so, heal that
var/healing = min(L.getBruteLoss(), 120)
@@ -364,11 +364,10 @@
/mob/living/simple_animal/hostile/proc/AttackingTarget()
SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target)
in_melee = TRUE
/* sorry for the simplemob vore fans
if(vore_active)
if(isliving(target))
var/mob/living/L = target
if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags,DEVOURABLE)) // aggressive check to ensure vore attacks can be made
if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags, DEVOURABLE) && CHECK_BITFIELD(L.vore_flags, MOBVORE)) // aggressive check to ensure vore attacks can be made
if(prob(voracious_chance))
vore_attack(src,L,src)
else
@@ -379,7 +378,6 @@
return target.attack_animal(src)
else
return target.attack_animal(src)
*/
return target.attack_animal(src)
/mob/living/simple_animal/hostile/proc/Aggro()
@@ -69,7 +69,7 @@
status_type = STATUS_EFFECT_MULTIPLE
alert_type = null
tick_interval = 1
var/obj/screen/seedling/seedling_screen_object
var/atom/movable/screen/seedling/seedling_screen_object
var/atom/target
@@ -81,7 +81,7 @@
/datum/status_effect/seedling_beam_indicator/on_apply()
if(owner.client)
seedling_screen_object = new /obj/screen/seedling()
seedling_screen_object = new /atom/movable/screen/seedling()
owner.client.screen += seedling_screen_object
tick()
return ..()
@@ -98,7 +98,7 @@
final.Turn(target_angle)
seedling_screen_object.transform = final
/obj/screen/seedling
/atom/movable/screen/seedling
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "seedling_beam_indicator"
screen_loc = "CENTER:-16,CENTER:-16"
@@ -40,8 +40,10 @@ Difficulty: Medium
ranged = 1
ranged_cooldown_time = 16
pixel_x = -16
crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka, /obj/item/crusher_trophy/miner_eye)
loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka)
crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka, /obj/item/crusher_trophy/miner_eye, /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe,
/obj/item/disk/design_disk/modkit_disc/bounty,/obj/item/disk/design_disk/modkit_disc/resonator_blast,/obj/item/disk/design_disk/modkit_disc/rapid_repeater)
loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka,/obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe,
/obj/item/disk/design_disk/modkit_disc/bounty,/obj/item/disk/design_disk/modkit_disc/resonator_blast,/obj/item/disk/design_disk/modkit_disc/rapid_repeater)
wander = FALSE
del_on_death = TRUE
blood_volume = BLOOD_VOLUME_NORMAL
@@ -26,8 +26,10 @@ Difficulty: Extremely Hard
speed = 20
move_to_delay = 20
ranged = TRUE
crusher_loot = list(/obj/effect/decal/remains/plasma, /obj/item/crusher_trophy/ice_block_talisman)
loot = list(/obj/effect/decal/remains/plasma)
crusher_loot = list(/obj/effect/decal/remains/plasma, /obj/item/crusher_trophy/ice_block_talisman, ,/obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe,
/obj/item/disk/design_disk/modkit_disc/bounty,/obj/item/disk/design_disk/modkit_disc/resonator_blast,/obj/item/disk/design_disk/modkit_disc/rapid_repeater)
loot = list(/obj/effect/decal/remains/plasma, ,/obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe,
/obj/item/disk/design_disk/modkit_disc/bounty,/obj/item/disk/design_disk/modkit_disc/resonator_blast,/obj/item/disk/design_disk/modkit_disc/rapid_repeater)
wander = FALSE
del_on_death = TRUE
blood_volume = BLOOD_VOLUME_NORMAL
@@ -337,11 +339,11 @@ Difficulty: Extremely Hard
id = "ice_block_talisman"
duration = 25
status_type = STATUS_EFFECT_REFRESH
alert_type = /obj/screen/alert/status_effect/ice_block_talisman
alert_type = /atom/movable/screen/alert/status_effect/ice_block_talisman
/// Stored icon overlay for the hit mob, removed when effect is removed
var/icon/cube
/obj/screen/alert/status_effect/ice_block_talisman
/atom/movable/screen/alert/status_effect/ice_block_talisman
name = "Frozen Solid"
desc = "You're frozen inside an ice cube, and cannot move!"
icon_state = "frozen"
@@ -102,23 +102,13 @@
consume_bait()
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/proc/consume_bait()
var/list/L = list()
for(var/obj/O in view(src, 9))
L += O
var/obj/item/stack/ore/diamond/diamonds = locate(/obj/item/stack/ore/diamond) in L
if(diamonds)
var/distanced = 0
distanced = get_dist(loc,diamonds.loc)
if(distanced <= 1 && diamonds)
qdel(diamonds)
src.visible_message("<span class='notice'>[src] consumes [diamonds], and it disappears! ...At least, you think.</span>")
var/obj/item/pen/survival/bait = locate(/obj/item/pen/survival) in L
if(bait)
var/distanceb = 0
distanceb = get_dist(loc,bait.loc)
if(distanceb <= 1 && bait)
qdel(bait)
visible_message("<span class='notice'>[src] examines [bait] closer, and telekinetically shatters the pen.</span>")
for(var/obj/O in view(1, src))
if(istype(O, /obj/item/stack/ore/diamond))
qdel(O)
src.visible_message("<span class='notice'>[src] consumes [O], and it disappears! ...At least, you think.</span>")
else if(istype(O, /obj/item/pen/survival))
qdel(O)
src.visible_message("<span class='notice'>[src] examines [O] closer, and telekinetically shatters the pen.</span>")
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random/Initialize()
. = ..()
@@ -113,7 +113,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
severity = 7
hud_used.healths.icon_state = "elite_health[severity]"
if(severity > 0)
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
overlay_fullscreen("brute", /atom/movable/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
@@ -35,14 +35,16 @@
coffer.Grant(src)
riot = new /datum/action/cooldown/riot
riot.Grant(src)
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
INVOKE_ASYNC(src, .proc/poll_for_player)
/mob/living/simple_animal/hostile/regalrat/proc/poll_for_player()
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Royal Rat, cheesey be his crown?", ROLE_SENTIENCE, null, FALSE, 100, POLL_IGNORE_SENTIENCE_POTION)
if(LAZYLEN(candidates) && !mind)
var/mob/dead/observer/C = pick(candidates)
key = C.key
notify_ghosts("All rise for the rat king, ascendant to the throne in \the [get_area(src)].", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE)
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/mob/living/simple_animal/hostile/regalrat/handle_automated_action()
if(prob(20))
riot.Trigger()
@@ -45,10 +45,10 @@
/mob/living/simple_animal/hostile/retaliate/clown/handle_temperature_damage()
if(bodytemperature < minbodytemp)
adjustBruteLoss(10)
throw_alert("temp", /obj/screen/alert/cold, 2)
throw_alert("temp", /atom/movable/screen/alert/cold, 2)
else if(bodytemperature > maxbodytemp)
adjustBruteLoss(15)
throw_alert("temp", /obj/screen/alert/hot, 3)
throw_alert("temp", /atom/movable/screen/alert/hot, 3)
else
clear_alert("temp")
@@ -50,12 +50,12 @@
if(isopenturf(loc))
var/turf/open/T = src.loc
if(T.air)
var/co2 = T.air.get_moles(/datum/gas/carbon_dioxide)
var/co2 = T.air.get_moles(GAS_CO2)
if(co2 > 0)
if(prob(25))
var/amt = min(co2, 9)
T.air.adjust_moles(/datum/gas/carbon_dioxide, -amt)
T.atmos_spawn_air("o2=[amt]")
T.air.adjust_moles(GAS_CO2, -amt)
T.atmos_spawn_air("o2=[amt];TEMP=293.15")
/mob/living/simple_animal/hostile/tree/AttackingTarget()
. = ..()
@@ -30,6 +30,7 @@
setup_visuals()
/mob/living/simple_animal/hostile/zombie/proc/setup_visuals()
set waitfor = FALSE
var/datum/preferences/dummy_prefs = new
dummy_prefs.pref_species = new /datum/species/zombie
dummy_prefs.be_random_body = TRUE
@@ -264,10 +264,10 @@
var/turf/open/ST = src.loc
if(ST.air)
var/tox = ST.air.get_moles(/datum/gas/plasma)
var/oxy = ST.air.get_moles(/datum/gas/oxygen)
var/n2 = ST.air.get_moles(/datum/gas/nitrogen)
var/co2 = ST.air.get_moles(/datum/gas/carbon_dioxide)
var/tox = ST.air.get_moles(GAS_PLASMA)
var/oxy = ST.air.get_moles(GAS_O2)
var/n2 = ST.air.get_moles(GAS_N2)
var/co2 = ST.air.get_moles(GAS_CO2)
if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
. = FALSE
@@ -554,7 +554,7 @@
var/oindex = active_hand_index
active_hand_index = hand_index
if(hud_used)
var/obj/screen/inventory/hand/H
var/atom/movable/screen/inventory/hand/H
H = hud_used.hand_slots["[hand_index]"]
if(H)
H.update_icon()
@@ -129,7 +129,7 @@
Tempstun = 0
if(stat != DEAD)
var/bz_percentage = environment.total_moles() ? (environment.get_moles(/datum/gas/bz) / environment.total_moles()) : 0
var/bz_percentage = environment.total_moles() ? (environment.get_moles(GAS_BZ) / environment.total_moles()) : 0
var/stasis = (bz_percentage >= 0.05 && bodytemperature < (T0C + 100)) || force_stasis
if(stat == CONSCIOUS && stasis)
@@ -129,7 +129,7 @@
coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
regenerate_icons()
/mob/living/simple_animal/slime/proc/update_name()
/mob/living/simple_animal/slime/update_name()
if(slime_name_regex.Find(name))
number = rand(1, 1000)
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
+1 -2
View File
@@ -35,11 +35,10 @@
return
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/out_of_combat_timer, out_of_combat_timer)
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/base_regeneration, base_regeneration)
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/combat_regeneration, combat_regeneration)
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/percent_regeneration_out_of_combat, percent_regeneration_out_of_combat)
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/post_action_penalty_delay, post_action_penalty_delay)
CONFIG_CACHE_ENTRY_AND_FETCH_VALUE(number/stamina_combat/post_action_penalty_factor, post_action_penalty_factor)
var/base_regen = (SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE))? base_regeneration : combat_regeneration
var/base_regen = base_regeneration
var/time_since_last_action = world.time - stamina_buffer_last_use
var/action_penalty = ((time_since_last_action) < (post_action_penalty_delay * 10))? post_action_penalty_factor : 1
var/out_of_combat_bonus = (time_since_last_action < (out_of_combat_timer * 10))? 0 : ((buffer_max * percent_regeneration_out_of_combat * 0.01))
+5 -3
View File
@@ -4,7 +4,8 @@
// ignore_castun = same logic as Paralyze() in general
// override_duration = If this is set, does Paralyze() for this duration.
// override_stam = If this is set, does this amount of stamina damage.
/mob/living/proc/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg)
// knocktofloor - whether to knock them to the ground
/mob/living/proc/DefaultCombatKnockdown(amount, updating = TRUE, ignore_canknockdown = FALSE, override_hardstun, override_stamdmg, knocktofloor = TRUE)
if(!iscarbon(src))
return Paralyze(amount, updating, ignore_canknockdown)
if(!ignore_canknockdown && !(status_flags & CANKNOCKDOWN))
@@ -13,7 +14,8 @@
buckled.unbuckle_mob(src)
var/drop_items = amount > 80 //80 is cutoff for old item dropping behavior
var/stamdmg = isnull(override_stamdmg)? (amount * 0.25) : override_stamdmg
KnockToFloor(drop_items, TRUE, updating)
if(knocktofloor)
KnockToFloor(drop_items, TRUE, updating)
adjustStaminaLoss(stamdmg)
if(!isnull(override_hardstun))
Paralyze(override_hardstun)
@@ -597,7 +599,7 @@
/mob/living/proc/become_nearsighted(source)
if(!HAS_TRAIT(src, TRAIT_NEARSIGHT))
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
overlay_fullscreen("nearsighted", /atom/movable/screen/fullscreen/impaired, 1)
ADD_TRAIT(src, TRAIT_NEARSIGHT, source)
/mob/living/proc/cure_husk(source)
+2 -2
View File
@@ -70,7 +70,7 @@
t += "<span class='danger'>Temperature: [environment.return_temperature()] \n</span>"
for(var/id in environment.get_gases())
if(environment.get_moles(id))
t+="<span class='notice'>[GLOB.meta_gas_names[id]]: [environment.get_moles(id)] \n</span>"
t+="<span class='notice'>[GLOB.gas_data.names[id]]: [environment.get_moles(id)] \n</span>"
to_chat(usr, t)
@@ -884,7 +884,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
/mob/proc/sync_lighting_plane_alpha()
if(hud_used)
var/obj/screen/plane_master/lighting/L = hud_used.plane_masters["[LIGHTING_PLANE]"]
var/atom/movable/screen/plane_master/lighting/L = hud_used.plane_masters["[LIGHTING_PLANE]"]
if (L)
L.alpha = lighting_alpha
+1 -1
View File
@@ -142,7 +142,7 @@
var/registered_z
var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly
var/list/alerts = list() // contains /atom/movable/screen/alert only // On /mob so clientless mobs will throw alerts properly
var/list/screens = list()
var/list/client_colours = list()
var/hud_type = /datum/hud
+1 -1
View File
@@ -362,7 +362,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
if(flashwindow)
window_flash(O.client)
if(source)
var/obj/screen/alert/notify_action/A = O.throw_alert("[REF(source)]_notify_action", /obj/screen/alert/notify_action)
var/atom/movable/screen/alert/notify_action/A = O.throw_alert("[REF(source)]_notify_action", /atom/movable/screen/alert/notify_action)
if(A)
if(O.client.prefs && O.client.prefs.UI_style)
A.icon = ui_style2icon(O.client.prefs.UI_style)
+10 -10
View File
@@ -95,7 +95,7 @@
. = ..()
if((direction & (direction - 1)) && mob.loc == n) //moved diagonally successfully
add_delay *= 2
add_delay *= SQRT_2
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay), FALSE)
move_delay += add_delay
if(.) // If mob is null here, we deserve the runtime
@@ -267,7 +267,7 @@
//1: r-leg 2: groin 3: l-leg
/client/proc/check_has_body_select()
return mob && mob.hud_used && mob.hud_used.zone_select && istype(mob.hud_used.zone_select, /obj/screen/zone_sel)
return mob && mob.hud_used && mob.hud_used.zone_select && istype(mob.hud_used.zone_select, /atom/movable/screen/zone_sel)
/client/verb/body_toggle_head()
set name = "body-toggle-head"
@@ -285,7 +285,7 @@
else
next_in_line = BODY_ZONE_HEAD
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(next_in_line, mob)
/client/verb/body_r_arm()
@@ -295,7 +295,7 @@
if(!check_has_body_select())
return
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_R_ARM, mob)
/client/verb/body_chest()
@@ -305,7 +305,7 @@
if(!check_has_body_select())
return
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_CHEST, mob)
/client/verb/body_l_arm()
@@ -315,7 +315,7 @@
if(!check_has_body_select())
return
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_L_ARM, mob)
/client/verb/body_r_leg()
@@ -325,7 +325,7 @@
if(!check_has_body_select())
return
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_R_LEG, mob)
/client/verb/body_groin()
@@ -335,7 +335,7 @@
if(!check_has_body_select())
return
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_PRECISE_GROIN, mob)
/client/verb/body_l_leg()
@@ -345,7 +345,7 @@
if(!check_has_body_select())
return
var/obj/screen/zone_sel/selector = mob.hud_used.zone_select
var/atom/movable/screen/zone_sel/selector = mob.hud_used.zone_select
selector.set_selected_zone(BODY_ZONE_L_LEG, mob)
/client/verb/toggle_walk_run()
@@ -364,7 +364,7 @@
return FALSE
m_intent = MOVE_INTENT_RUN
if(hud_used && hud_used.static_inventory)
for(var/obj/screen/mov_intent/selector in hud_used.static_inventory)
for(var/atom/movable/screen/mov_intent/selector in hud_used.static_inventory)
selector.update_icon()
/mob/verb/up()
+7 -26
View File
@@ -144,33 +144,14 @@
message = "<span class='emote'><b>[user]</b> <i>[user.say_emphasis(message)]</i></span>"
var/list/show_to = list()
var/list/processing = list()
var/safety = 25
var/list/processed = list()
for(var/obj/structure/table/T in range(user, 1))
processing |= T
for(var/i = 1; i <= processing.len; ++i)
var/obj/structure/table/T = processing[i]
if(safety-- <= 0)
to_chat(user, "Table scan aborted early, some people might have not received the message (max 25)")
break
if(get_dist(T, user) > 7)
continue // nah
processing |= T
for(var/mob/living/M in range(T, 1)) // no ghosts/cameramobs
show_to |= M
var/obj/structure/table/other
other = locate() in get_step(T, NORTH)
if(other)
processing |= other
other = locate() in get_step(T, SOUTH)
if(other)
processing |= other
other = locate() in get_step(T, WEST)
if(other)
processing |= other
other = locate() in get_step(T, EAST)
if(other)
processing |= other
if(processed[T])
continue
for(var/obj/structure/table/T2 in T.connected_floodfill(25))
processed[T2] = TRUE
for(var/mob/living/L in range(T2, 1))
show_to |= L
for(var/i in show_to)
var/mob/M = i
+4 -4
View File
@@ -52,8 +52,8 @@
/mob/proc/update_blindness()
if(eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness
if(stat == CONSCIOUS || stat == SOFT_CRIT)
throw_alert("blind", /obj/screen/alert/blind)
overlay_fullscreen("blind", /obj/screen/fullscreen/blind)
throw_alert("blind", /atom/movable/screen/alert/blind)
overlay_fullscreen("blind", /atom/movable/screen/fullscreen/blind)
// You are blind why should you be able to make out details like color, only shapes near you
// add_client_colour(/datum/client_colour/monochrome/blind)
else // CONSCIOUS no blind trait, no blindness
@@ -91,7 +91,7 @@
var/list/screens = list(hud_used.plane_masters["[GAME_PLANE]"], hud_used.plane_masters["[FLOOR_PLANE]"],
hud_used.plane_masters["[WALL_PLANE]"], hud_used.plane_masters["[ABOVE_WALL_PLANE]"])
for(var/A in screens)
var/obj/screen/plane_master/P = A
var/atom/movable/screen/plane_master/P = A
P.add_filter("blurry_eyes", 2, EYE_BLUR(clamp(eye_blurry*0.1,0.6,3)))
/mob/proc/remove_eyeblur()
@@ -100,7 +100,7 @@
var/list/screens = list(hud_used.plane_masters["[GAME_PLANE]"], hud_used.plane_masters["[FLOOR_PLANE]"],
hud_used.plane_masters["[WALL_PLANE]"], hud_used.plane_masters["[ABOVE_WALL_PLANE]"])
for(var/A in screens)
var/obj/screen/plane_master/P = A
var/atom/movable/screen/plane_master/P = A
P.remove_filter("blurry_eyes")
///Adjust the drugginess of a mob