Merge branch 'master' of https://github.com/tgstation/tgstation into upstream-sync

This commit is contained in:
xPokee
2025-10-03 07:05:54 -04:00
517 changed files with 24339 additions and 21253 deletions
@@ -23,15 +23,16 @@
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, STAMINA = 0, OXY = 1)
/// Size of cloud produced from a dying spore
var/death_cloud_size = BLOBMOB_CLOUD_NONE
var/list/loot = list(/obj/item/food/spore_sack)
var/loot = /obj/item/food/spore_sack
/mob/living/basic/blob_minion/Initialize(mapload)
. = ..()
add_traits(list(TRAIT_BLOB_ALLY, TRAIT_MUTE), INNATE_TRAIT)
AddComponent(/datum/component/blob_minion, on_strain_changed = CALLBACK(src, PROC_REF(on_strain_updated)), new_death_cloud_size = death_cloud_size)
if(length(loot))
loot = string_list(loot)
if(loot)
if (islist(loot))
loot = string_list(loot)
AddElement(/datum/element/death_drops, loot)
/// Called when our blob overmind changes their variant, update some of our mob properties
@@ -124,7 +124,7 @@
icon_state = "blobpod_independent"
//we hate gold cores
gold_core_spawnable = NO_SPAWN
loot = list(/obj/item/food/spore_sack/independent)
loot = /obj/item/food/spore_sack/independent
/mob/living/basic/blob_minion/spore/independent/Initialize(mapload)
. = ..()
@@ -26,7 +26,7 @@
pressure_resistance = 50
mob_size = MOB_SIZE_LARGE
ai_controller = /datum/ai_controller/basic_controller/blobbernaut
loot = list()
loot = null
///The HUD given to blobbernauts, updated by the Blob itself
var/atom/movable/screen/healths/blob/overmind/overmind_hud
///The overlay for veins.
+12 -55
View File
@@ -18,28 +18,23 @@
mob_size = MOB_SIZE_HUGE
layer = LARGE_MOB_LAYER
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
/// List of loot if not killed by crusher.
var/list/loot
/// List of loot if killed by crusher.
var/list/crusher_loot
/// Achievement given to surrounding players when the megafauna is killed
var/achievement_type
/// Crusher achievement given to players when megafauna is killed
var/crusher_achievement_type
/// Score given to players when megafauna is killed
var/score_achievement_type
/// If the megafauna was actually killed (not just dying, then transforming into another type)
var/elimination = FALSE
/// Name for the GPS signal of the megafauna
var/gps_name = null
/// If this is a megafauna that is real (has achievements, gps signal)
var/true_spawn = TRUE
/// What crusher trophy this mob drops, if any
var/crusher_loot
/mob/living/basic/boss/Initialize(mapload)
. = ..()
AddElement(/datum/element/wall_tearer, tear_time = 1 SECONDS)
if(gps_name && true_spawn)
if(gps_name)
AddComponent(/datum/component/gps, gps_name)
if(crusher_loot)
AddElement(\
/datum/element/crusher_loot,\
trophy_type = crusher_loot,\
guaranteed_drop = 0.6,\
drop_immediately = basic_mob_flags & DEL_ON_DEATH,\
)
ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
add_traits(list(TRAIT_NO_TELEPORT, TRAIT_MARTIAL_ARTS_IMMUNE, TRAIT_LAVA_IMMUNE,TRAIT_ASHSTORM_IMMUNE, TRAIT_NO_FLOATING_ANIM), MEGAFAUNA_TRAIT)
AddComponent(/datum/component/seethrough_mob)
@@ -53,51 +48,13 @@
/mob/living/basic/boss/dust(just_ash, drop_items, force)
if(!force && health > 0)
return
loot.Cut()
crusher_loot.Cut()
return ..()
/mob/living/basic/boss/death(gibbed, list/force_grant)
if(gibbed) // in case they've been force dusted
return ..()
if(health > 0) // prevents instakills
/mob/living/basic/boss/death(gibbed)
if (health > 0 && !gibbed) // prevents instakills
return
var/datum/status_effect/crusher_damage/crusher_dmg = has_status_effect(/datum/status_effect/crusher_damage)
///Whether we killed the megafauna with primarily crusher damage or not
var/crusher_kill = (crusher_dmg && (crusher_dmg.total_damage >= floor(maxHealth * 0.6)))
if(true_spawn && !(flags_1 & ADMIN_SPAWNED_1))
var/tab = "megafauna_kills"
if(crusher_kill)
tab = "megafauna_kills_crusher"
if(!elimination) //used so the achievment only occurs for the last legion to die.
grant_achievement(achievement_type, score_achievement_type, crusher_kill, force_grant)
SSblackbox.record_feedback("tally", tab, 1, "[initial(name)]")
for(var/path in crusher_kill ? crusher_loot : loot) // using this instead of deathdrops and crusher_loot because we calculate differently and removing the element is ass
new path(drop_location())
return ..()
/// Grants medals and achievements to surrounding players
/mob/living/basic/boss/proc/grant_achievement(medaltype, scoretype, crusher_kill, list/grant_achievement = list())
if(!achievement_type || (flags_1 & ADMIN_SPAWNED_1) || !SSachievements.achievements_enabled) //Don't award medals if the medal type isn't set
return FALSE
if(!grant_achievement.len)
for(var/mob/living/victor in view(7,src))
grant_achievement += victor
for(var/mob/living/victor in grant_achievement)
if(victor.stat || !victor.client)
continue
victor.add_mob_memory(/datum/memory/megafauna_slayer, antagonist = src)
victor.client.give_award(/datum/award/achievement/boss/boss_killer, victor)
victor.client.give_award(achievement_type, victor)
if(crusher_kill && istype(victor.get_active_held_item(), /obj/item/kinetic_crusher))
victor.client.give_award(crusher_achievement_type, victor)
victor.client.give_award(/datum/award/score/boss_score, victor) //Score progression for bosses killed in general
victor.client.give_award(score_achievement_type, victor) //Score progression for specific boss killed
return TRUE
/mob/living/basic/boss/early_melee_attack(mob/living/target, list/modifiers, ignore_cooldown)
. = ..()
if(!. || !istype(target))
@@ -21,12 +21,8 @@
speed = 3.5 //dont make this any faster PLEASE
gps_name = "L-4 Biohazard Beacon"
ai_controller = /datum/ai_controller/basic_controller/thing_boss
loot = list(/obj/item/keycard/thing_boss)
crusher_loot = list(/obj/item/keycard/thing_boss, /obj/item/crusher_trophy/flesh_glob)
crusher_loot = /obj/item/crusher_trophy/flesh_glob
mouse_opacity = MOUSE_OPACITY_OPAQUE
achievement_type = /datum/award/achievement/boss/thething_kill
crusher_achievement_type = /datum/award/achievement/boss/thething_crusher
score_achievement_type = /datum/award/score/thething_score
/// Current phase of the boss fight
var/phase = 1
/// Time the Thing will be invulnerable between phases
@@ -45,6 +41,15 @@
/mob/living/basic/boss/thing/Initialize(mapload)
. = ..()
var/static/list/achievements = list(
/datum/award/achievement/boss/boss_killer,
/datum/award/achievement/boss/thething_kill,
/datum/award/score/boss_score,
/datum/award/score/thething_score,
)
AddElement(/datum/element/kill_achievement, achievements, /datum/award/achievement/boss/thething_crusher, /datum/memory/megafauna_slayer)
AddElement(/datum/element/death_drops, /obj/item/keycard/thing_boss, FALSE)
var/static/list/innate_actions = list(
/datum/action/cooldown/mob_cooldown/the_thing/decimate = BB_THETHING_DECIMATE,
/datum/action/cooldown/mob_cooldown/charge/the_thing = BB_THETHING_CHARGE,
@@ -57,12 +62,13 @@
AddElement(/datum/element/relay_attackers) // used to immediately aggro if shot from outside aggro range
RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(immediate_aggro))
maploaded = mapload
if(maploaded)
spawn_loc = loc
RegisterSignal(src, COMSIG_AI_BLACKBOARD_KEY_SET(BB_BASIC_MOB_CURRENT_TARGET), PROC_REF(target_gained))
RegisterSignal(src, COMSIG_AI_BLACKBOARD_KEY_CLEARED(BB_BASIC_MOB_CURRENT_TARGET), PROC_REF(target_lost))
SSqueuelinks.add_to_queue(src, RUIN_QUEUE, 0)
return INITIALIZE_HINT_LATELOAD
if(!maploaded)
return
spawn_loc = loc
RegisterSignal(src, COMSIG_AI_BLACKBOARD_KEY_SET(BB_BASIC_MOB_CURRENT_TARGET), PROC_REF(target_gained))
RegisterSignal(src, COMSIG_AI_BLACKBOARD_KEY_CLEARED(BB_BASIC_MOB_CURRENT_TARGET), PROC_REF(target_lost))
SSqueuelinks.add_to_queue(src, RUIN_QUEUE, 0)
return INITIALIZE_HINT_LATELOAD
/mob/living/basic/boss/thing/LateInitialize()
SSqueuelinks.pop_link(RUIN_QUEUE)
@@ -183,9 +189,9 @@
spawn_loc = null
return ..()
/mob/living/basic/boss/thing/with_ruin_loot
loot = list(/obj/item/organ/brain/cybernetic/ai) // the only, relevant main loot of the ruin, but if admin spawned the keycard is useless
crusher_loot = list(/obj/item/organ/brain/cybernetic/ai, /obj/item/crusher_trophy/flesh_glob)
/mob/living/basic/boss/thing/with_ruin_loot/Initialize(mapload)
. = ..()
AddElement(/datum/element/death_drops, /obj/item/organ/brain/cybernetic/ai, FALSE)
// special stuff for our ruin to make a cooler bossfight
+2 -3
View File
@@ -84,7 +84,7 @@ GLOBAL_LIST_INIT(command_strings, list(
var/list/current_pathed_turfs = list()
///The type of data HUD the bot uses. Diagnostic by default.
var/data_hud_type = DATA_HUD_DIAGNOSTIC
var/data_hud_type = TRAIT_DIAGNOSTIC_HUD
/// If true we will allow ghosts to control this mob
var/can_be_possessed = FALSE
/// Message to display upon possession
@@ -139,8 +139,7 @@ GLOBAL_LIST_INIT(command_strings, list(
//If a bot has its own HUD (for player bots), provide it.
if(!isnull(data_hud_type))
var/datum/atom_hud/datahud = GLOB.huds[data_hud_type]
datahud.show_to(src)
ADD_TRAIT(src, data_hud_type, INNATE_TRAIT)
if(mapload && is_station_level(z) && (bot_mode_flags & BOT_MODE_CAN_BE_SAPIENT) && (bot_mode_flags & BOT_MODE_ROUNDSTART_POSSESSION))
enable_possession(mapload = mapload)
+1 -4
View File
@@ -39,13 +39,10 @@
var/exenteration_cooldown_duration = 0.5 SECONDS
//aoe slash ability
var/datum/action/cooldown/mob_cooldown/bot/exenterate
var/list/remains = list(/obj/effect/gibspawner/robot)
/mob/living/basic/bot/dedbot/Initialize(mapload)
. = ..()
if(length(remains))
remains = string_list(remains)
AddElement(/datum/element/death_drops, remains)
AddElement(/datum/element/death_drops, /obj/effect/gibspawner/robot)
var/static/list/innate_actions = list(
SPIN_SLASH_ABILITY_TYPEPATH = BB_DEDBOT_SLASH,
)
@@ -12,7 +12,7 @@
bot_mode_flags = BOT_MODE_ON | BOT_MODE_REMOTE_ENABLED | BOT_MODE_CAN_BE_SAPIENT | BOT_MODE_AUTOPATROL | BOT_MODE_ROUNDSTART_POSSESSION
hackables = "sound control systems"
path_image_color = "#FF69B4"
data_hud_type = DATA_HUD_SECURITY_BASIC
data_hud_type = TRAIT_SECURITY_HUD_ID_ONLY
additional_access = /datum/id_trim/job/clown
possessed_message = "You are a honkbot! Make sure the crew are having a great time!"
///our voicelines
@@ -19,7 +19,7 @@
radio_key = /obj/item/encryptionkey/headset_med
radio_channel = RADIO_CHANNEL_MEDICAL
bot_type = MED_BOT
data_hud_type = DATA_HUD_MEDICAL_ADVANCED
data_hud_type = TRAIT_MEDICAL_HUD
hackables = "health processor circuits"
possessed_message = "You are a medbot! Ensure good health among the crew to the best of your ability!"
@@ -14,7 +14,7 @@
radio_key = /obj/item/encryptionkey/headset_service
radio_channel = RADIO_CHANNEL_SERVICE
bot_type = VIBE_BOT
data_hud_type = DATA_HUD_DIAGNOSTIC
data_hud_type = TRAIT_DIAGNOSTIC_HUD
path_image_color = "#2cac12"
possessed_message = "You are a vibebot! Maintain the station's vibes to the best of your ability!"
+31 -31
View File
@@ -1,6 +1,6 @@
/mob/living/basic/clown
name = "Clown"
desc = "A denizen of clown planet."
desc = "A denizen of Clown Planet."
icon = 'icons/mob/simple/clown_mobs.dmi'
icon_state = "clown"
icon_living = "clown"
@@ -32,8 +32,8 @@
var/list/loot = list(/obj/effect/gibspawner/human) // BUBBER EDIT CHANGE - Original: /obj/effect/mob_spawn/corpse/human/clown
///blackboard emote list
var/list/emotes = list(
BB_EMOTE_SAY = list("HONK", "Honk!", "Welcome to clown planet!"),
BB_EMOTE_HEAR = list("honks", "squeaks"),
BB_EMOTE_SAY = list("HONK!!", "Honk!", "Welcome to Clown Planet!"),
BB_EMOTE_HEAR = list("honks!", "squeaks!"),
BB_EMOTE_SOUND = list('sound/items/bikehorn.ogg'), //WE LOVE TO PARTY
BB_SPEAK_CHANCE = 5,
)
@@ -72,7 +72,7 @@
/mob/living/basic/clown/lube
name = "Living Lube"
desc = "A puddle of lube brought to life by the honkmother."
desc = "A puddle of lube brought to life by the Honkmother."
icon_state = "lube"
icon_living = "lube"
maxHealth = 50
@@ -84,8 +84,8 @@
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_SLIME
damage_coeff = list(BRUTE = 0.25, BURN = 1, TOX = 1, STAMINA = 1, OXY = 1)
emotes = list(
BB_EMOTE_SAY = list("HONK", "Honk!", "Welcome to clown planet!"),
BB_EMOTE_HEAR = list("bubbles", "oozes"),
BB_EMOTE_SAY = list("HONK!!", "Honk!", "Welcome to Clown Planet!"),
BB_EMOTE_HEAR = list("bubbles.", "oozes."),
)
waddles = FALSE
loot = list(
@@ -152,16 +152,16 @@
)
emotes = list(
BB_EMOTE_SAY = list(
"HONK",
"HONK!!",
"Honk!",
"I didn't ask for this",
"I feel constant and horrible pain",
"I was born out of mirthful pranking but I live in suffering",
"This body is a merciless and unforgiving prison",
"I didn't ask for this...",
"I feel constant and horrible pain!!",
"I was born out of mirthful pranking but I live in suffering!!",
"This body is a merciless and unforgiving prison!!",
"YA-HONK!!!",
),
BB_EMOTE_HEAR = list("honks", "contemplates its existence"),
BB_EMOTE_SEE = list("sweats", "jiggles"),
BB_EMOTE_HEAR = list("honks!", "contemplates its existence."),
BB_EMOTE_SEE = list("sweats.", "jiggles."),
BB_SPEAK_CHANCE = 5,
)
@@ -196,7 +196,7 @@
)
emotes = list(
BB_EMOTE_SAY = list("YA-HONK!!!"),
BB_EMOTE_HEAR = list("honks", "squeaks"),
BB_EMOTE_HEAR = list("honks!", "squeaks!"),
BB_SPEAK_CHANCE = 60,
)
@@ -234,9 +234,9 @@
/obj/item/clothing/mask/gas/clown_hat,
)
emotes = list(
BB_EMOTE_SAY = list("HONK", "Honk!", "HAUAUANK!!!", "GUUURRRRAAAHHH!!!"),
BB_EMOTE_HEAR = list("honks", "grunts"),
BB_EMOTE_SEE = list("sweats"),
BB_EMOTE_SAY = list("HONK!!", "Honk!", "HAUAUANK!!!", "GUUURRRRAAAHHH!!!"),
BB_EMOTE_HEAR = list("honks!", "grunts!"),
BB_EMOTE_SEE = list("sweats!"),
BB_SPEAK_CHANCE = 5,
)
@@ -265,8 +265,8 @@
/obj/item/clothing/mask/gas/clown_hat,
)
emotes = list(
BB_EMOTE_SAY = list("HONK", "Honk!", "Bruh", "cheeaaaahhh?"),
BB_EMOTE_SEE = list("asserts his dominance", "emasculates everyone implicitly"),
BB_EMOTE_SAY = list("HONK!!", "Honk!", "Bruh.", "cheeaaaahhh?"),
BB_EMOTE_SEE = list("asserts his dominance!", "emasculates everyone implicitly!"),
BB_SPEAK_CHANCE = 5,
)
@@ -292,8 +292,8 @@
/obj/item/clothing/mask/gas/clown_hat,
)
emotes = list(
BB_EMOTE_SAY = list("honk"),
BB_EMOTE_SEE = list("squirms", "writhes"),
BB_EMOTE_SAY = list("honk!"),
BB_EMOTE_SEE = list("squirms!", "writhes!"),
)
/mob/living/basic/clown/clownhulk/honkmunculus/Initialize(mapload)
@@ -333,9 +333,9 @@
/obj/item/clothing/mask/gas/clown_hat,
)
emotes = list(
BB_EMOTE_SAY = list("HONK!!!", "The Honkmother is merciful, so I must act out her wrath.", "parce mihi ad beatus honkmother placet mihi ut peccata committere,", "DIE!!!"),
BB_EMOTE_HEAR = list("honks", "grunts"),
BB_EMOTE_SEE = list("sweats"),
BB_EMOTE_SAY = list("HONK!!!", "The Honkmother is merciful, so I must act out her wrath.", "Parce mihi ad beatus honkmother placet mihi ut peccata committere.", "DIE!!!"),
BB_EMOTE_HEAR = list("honks!", "grunts!"),
BB_EMOTE_SEE = list("sweats!"),
BB_SPEAK_CHANCE = 5,
)
@@ -370,15 +370,15 @@
/obj/item/clothing/mask/gas/clown_hat,
)
emotes = list(
BB_EMOTE_SAY = list("aaaaaahhhhuuhhhuhhhaaaaa", "AAAaaauuuaaAAAaauuhhh", "huuuuuh... hhhhuuuooooonnnnkk", "HuaUAAAnKKKK"),
BB_EMOTE_SEE = list("squirms", "writhes", "pulsates", "froths", "oozes"),
BB_EMOTE_SAY = list("aaaaaahhhhuuhhhuhhhaaaaa...", "AAAaaauuuaaAAAaauuhhh!!", "huuuuuh... hhhhuuuooooonnnnkk...", "HuaUAAAnKKKK!!"),
BB_EMOTE_SEE = list("squirms!", "writhes!", "pulsates!", "froths!", "oozes!"),
BB_SPEAK_CHANCE = 10,
)
/mob/living/basic/clown/mutant/glutton
name = "banana glutton"
desc = "Something that was once a clown"
desc = "Something that was once a clown."
icon_state = "glutton"
icon_living = "glutton"
health = 200
@@ -401,8 +401,8 @@
/obj/effect/spawner/random/chance_for_freedom,
)
emotes = list(
BB_EMOTE_SAY = list("hey, buddy", "HONK!!!", "H-h-h-H-HOOOOONK!!!!", "HONKHONKHONK!!!", "HEY, BUCKO, GET BACK HERE!!!", "HOOOOOOOONK!!!"),
BB_EMOTE_SEE = list("jiggles", "wobbles"),
BB_EMOTE_SAY = list("hey, buddy!", "HONK!!!", "H-h-h-H-HOOOOONK!!!!", "HONKHONKHONK!!!", "HEY, BUCKO, GET BACK HERE!!!", "HOOOOOOOONK!!!"),
BB_EMOTE_SEE = list("jiggles!", "wobbles!"),
)
death_sound = 'sound/misc/sadtrombone.ogg'
waddles = FALSE
@@ -564,8 +564,8 @@
/obj/effect/spawner/random/peel_or_nana,
)
emotes = list(
BB_EMOTE_SAY = list("HONK", "Honk!", "YA-HONK!!!"),
BB_EMOTE_SEE = list("bites into the banana", "plucks a banana off its head", "photosynthesizes"),
BB_EMOTE_SAY = list("HONK!!", "Honk!", "YA-HONK!!!"),
BB_EMOTE_SEE = list("bites into the banana!", "plucks a banana off its head!", "photosynthesizes!"),
BB_EMOTE_SOUND = list('sound/items/bikehorn.ogg'),
)
@@ -49,18 +49,18 @@
var/smashes_walls = FALSE
/// The different flavors of goop constructs can drop, depending on theme.
var/static/list/remains_by_theme = list(
THEME_CULT = list(/obj/item/ectoplasm/construct),
THEME_HOLY = list(/obj/item/ectoplasm/angelic),
THEME_WIZARD = list(/obj/item/ectoplasm/mystic),
THEME_HERETIC = list(/obj/item/ectoplasm/construct),
THEME_CULT = /obj/item/ectoplasm/construct,
THEME_HOLY = /obj/item/ectoplasm/angelic,
THEME_WIZARD = /obj/item/ectoplasm/mystic,
THEME_HERETIC = /obj/item/ectoplasm/construct,
)
/mob/living/basic/construct/Initialize(mapload)
. = ..()
throw_alert("bloodsense", /atom/movable/screen/alert/bloodsense)
AddElement(/datum/element/simple_flying)
var/list/remains = string_list(remains_by_theme[theme])
if(length(remains))
var/remains = remains_by_theme[theme]
if(remains)
AddElement(/datum/element/death_drops, remains)
if(smashes_walls)
AddElement(/datum/element/wall_tearer, allow_reinforced = FALSE)
@@ -30,14 +30,11 @@
can_repair = TRUE
can_repair_self = TRUE
smashes_walls = TRUE
///The health HUD applied to this mob.
var/health_hud = DATA_HUD_MEDICAL_ADVANCED
/mob/living/basic/construct/artificer/Initialize(mapload)
. = ..()
AddElement(/datum/element/ai_retaliate)
var/datum/atom_hud/datahud = GLOB.huds[health_hud]
datahud.show_to(src)
ADD_TRAIT(src, TRAIT_MEDICAL_HUD, INNATE_TRAIT)
/// Hostile NPC version. Heals nearby constructs and cult structures, avoids targets that aren't extremely hurt.
/mob/living/basic/construct/artificer/hostile
+6 -5
View File
@@ -33,9 +33,10 @@
var/theme = THEME_CULT
/// The different flavors of goop shades can drop, depending on theme.
var/static/list/remains_by_theme = list(
THEME_CULT = list(/obj/item/ectoplasm/construct),
THEME_HOLY = list(/obj/item/ectoplasm/angelic),
THEME_WIZARD = list(/obj/item/ectoplasm/mystic),
THEME_CULT = /obj/item/ectoplasm/construct,
THEME_HOLY = /obj/item/ectoplasm/angelic,
THEME_WIZARD = /obj/item/ectoplasm/mystic,
THEME_HERETIC = /obj/item/ectoplasm/construct,
)
/mob/living/basic/shade/Initialize(mapload)
@@ -45,8 +46,8 @@
if(isnull(theme))
return
icon_state = "shade_[theme]"
var/list/remains = string_list(remains_by_theme[theme])
if(length(remains))
var/remains = remains_by_theme[theme]
if(remains)
AddElement(/datum/element/death_drops, remains)
/mob/living/basic/shade/update_icon_state()
@@ -45,8 +45,7 @@
/mob/living/basic/festivus/Initialize(mapload)
. = ..()
AddComponent(/datum/component/seethrough_mob)
var/static/list/death_loot = list(/obj/item/stack/rods)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/item/stack/rods)
AddComponent(/datum/component/aggro_emote, emote_list = string_list(list("growls")), emote_chance = 20)
grant_actions_by_list(list(/datum/action/cooldown/mob_cooldown/charge_apc = BB_FESTIVE_APC))
@@ -89,8 +89,7 @@
GLOB.parasites += src
src.theme = theme
theme?.apply(src)
var/list/death_loot = string_list(list(/obj/item/stack/sheet/mineral/wood))
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/effect/temp_visual/guardian/phase/out)
AddElement(/datum/element/simple_flying)
AddComponent(/datum/component/basic_inhands)
// life link
@@ -27,8 +27,7 @@
after_healed = CALLBACK(src, PROC_REF(after_healed)),\
)
var/datum/atom_hud/medsensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
medsensor.show_to(src)
ADD_TRAIT(src, TRAIT_MEDICAL_HUD, INNATE_TRAIT)
var/datum/action/cooldown/mob_cooldown/guardian_bluespace_beacon/teleport = new(src)
teleport.Grant(src)
@@ -34,5 +34,5 @@
/mob/living/basic/heretic_summon/Initialize(mapload)
. = ..()
AddElement(/datum/element/death_drops, string_list(list(/obj/effect/gibspawner/generic)))
AddElement(/datum/element/death_drops, /obj/effect/gibspawner/generic)
ADD_TRAIT(src, TRAIT_HERETIC_SUMMON, INNATE_TRAIT)
@@ -40,8 +40,7 @@
/mob/living/basic/heretic_summon/star_gazer/Initialize(mapload)
. = ..()
var/static/list/death_loot = list(/obj/effect/temp_visual/cosmic_domain)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/effect/temp_visual/cosmic_domain)
AddElement(/datum/element/death_explosion, 3, 6, 12)
AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE)
AddElement(/datum/element/wall_smasher, ENVIRONMENT_SMASH_RWALLS)
@@ -29,9 +29,8 @@
/mob/living/basic/mining/hivelord/Initialize(mapload)
. = ..()
var/static/list/death_loot = list(/obj/item/organ/monster_core/regenerative_core)
AddElement(/datum/element/relay_attackers)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/item/organ/monster_core/regenerative_core)
AddComponent(/datum/component/clickbox, icon_state = "hivelord", max_scale = INFINITY, dead_state = "hivelord_dead") // They writhe so much.
AddComponent(/datum/component/appearance_on_aggro, aggro_state = "hivelord_alert")
spawn_brood = new(src)
@@ -271,7 +271,7 @@ GLOBAL_LIST_EMPTY(raptor_population)
/mob/living/basic/raptor/green/Initialize(mapload)
. = ..()
AddElement(/datum/element/proficient_miner)
AddComponent(/datum/component/proficient_miner)
/mob/living/basic/raptor/white
name = "white raptor"
@@ -66,8 +66,7 @@
neutral_overlay = mutable_appearance(icon = 'icons/mob/silicon/aibots.dmi', icon_state = "mining_drone_grey")
combat_overlay = mutable_appearance(icon = 'icons/mob/silicon/aibots.dmi', icon_state = "mining_drone_offense_grey")
AddComponent(/datum/component/obeys_commands, pet_commands)
var/static/list/death_drops = list(/obj/effect/decal/cleanable/blood/gibs/robot_debris/old)
AddElement(/datum/element/death_drops, death_drops)
AddElement(/datum/element/death_drops, /obj/effect/decal/cleanable/blood/gibs/robot_debris/old)
add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE, TRAIT_MINING_AOE_IMMUNE), INNATE_TRAIT)
AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE)
@@ -131,7 +131,7 @@
/obj/effect/temp_visual/rising_rocket/Initialize(mapload)
. = ..()
playsound(src, 'sound/items/weapons/minebot_rocket.ogg', 100, FALSE)
animate(src, pixel_y = base_pixel_y + 500, time = duration, easing = EASE_IN)
animate(src, pixel_y = base_pixel_y + 500, time = duration, easing = QUAD_EASING|EASE_IN)
/obj/effect/temp_visual/falling_rocket
name = "Missile"
@@ -27,7 +27,7 @@
//Gondolas aren't affected by cold.
unsuitable_atmos_damage = 0
basic_mob_flags = DEL_ON_DEATH
basic_mob_flags = SENDS_DEATH_MOODLETS|DEL_ON_DEATH
///List of loot drops on death, since it deletes itself on death (like trooper).
var/list/loot = list(
+1 -7
View File
@@ -3,12 +3,6 @@
mob_size = MOB_SIZE_SMALL
mob_biotypes = MOB_ORGANIC|MOB_BEAST
blood_volume = BLOOD_VOLUME_NORMAL
basic_mob_flags = SENDS_DEATH_MOODLETS
/// if the mob is protected from being renamed by collars.
var/unique_pet = FALSE
/mob/living/basic/pet/death(gibbed)
. = ..()
add_memory_in_range(src, 7, /datum/memory/pet_died, deuteragonist = src) //Protagonist is the person memorizing it
@@ -86,8 +86,7 @@
attack_verb_simple = possible_weapons[weapon_of_choice]
attack_verb_continuous = "[attack_verb_simple]s"
var/static/list/death_loot = list(/obj/effect/mob_spawn/corpse/human/revolutionary)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/effect/mob_spawn/corpse/human/revolutionary)
apply_dynamic_human_appearance(src, mob_spawn_path = /obj/effect/mob_spawn/corpse/human/revolutionary, l_hand = weapon_of_choice)
gender = pick(MALE, FEMALE, PLURAL)
@@ -40,7 +40,7 @@
. = ..()
grant_actions_by_list(list(/datum/action/consume/fleshblob))
ADD_TRAIT(src, TRAIT_STRONG_GRABBER, INNATE_TRAIT)
AddElement(/datum/element/death_drops, string_list(list(/obj/effect/gibspawner/generic)))
AddElement(/datum/element/death_drops, /obj/effect/gibspawner/generic)
AddComponent(\
/datum/component/blood_walk, \
blood_type = /obj/effect/decal/cleanable/blood/trail_holder, \
@@ -38,8 +38,7 @@
/mob/living/basic/cybersun_ai_core/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_IMMOBILIZED, INNATE_TRAIT)
var/static/list/death_loot = list(/obj/effect/temp_visual/cybersun_ai_core_death)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/effect/temp_visual/cybersun_ai_core_death)
AddElement(/datum/element/relay_attackers)
var/static/list/innate_actions = list(
LIGHTNING_ABILITY_TYPEPATH = BB_CYBERSUN_CORE_LIGHTNING,
@@ -29,12 +29,9 @@
/mob/living/basic/dark_wizard/Initialize(mapload)
. = ..()
apply_dynamic_human_appearance(src, mob_spawn_path = /obj/effect/mob_spawn/corpse/human/wizard/dark, r_hand = /obj/item/staff)
add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE), INNATE_TRAIT)
var/corpse = string_list(list(/obj/effect/decal/remains/human))
AddElement(/datum/element/death_drops, corpse)
AddElement(/datum/element/death_drops, /obj/effect/decal/remains/human)
AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE)
AddElement(/datum/element/ai_retaliate)
@@ -44,7 +44,7 @@
/mob/living/basic/living_limb_flesh/Initialize(mapload, obj/item/bodypart/limb)
. = ..()
AddComponent(/datum/component/swarming, max_x = 8, max_y = 8)
AddElement(/datum/element/death_drops, string_list(list(/obj/effect/gibspawner/generic)))
AddElement(/datum/element/death_drops, /obj/effect/gibspawner/generic)
if(!isnull(limb))
register_to_limb(limb)
@@ -34,16 +34,13 @@
COOLDOWN_DECLARE(tantrum_time)
//length of aggro state
var/tantrum_time_duration = 3.5 SECONDS
var/list/remains = list(/obj/effect/gibspawner/robot)
/mob/living/basic/mad_piano/Initialize(mapload)
. = ..()
if(length(remains))
remains = string_list(remains)
AddElement(/datum/element/death_drops, remains)
var/static/list/connections = list(COMSIG_ATOM_ENTERED = PROC_REF(aggro_tantrum))
AddComponent(/datum/component/connect_range, tracked = src, connections = connections, range = 1, works_in_containers = FALSE)
AddElementTrait(TRAIT_WADDLING, INNATE_TRAIT, /datum/element/waddling)
AddElement(/datum/element/death_drops, /obj/effect/gibspawner/robot)
ADD_TRAIT(src, TRAIT_IMMOBILIZED, TRAIT_GENERIC)
ADD_TRAIT(src, TRAIT_PACIFISM, TRAIT_GENERIC)
name_calm = name
@@ -72,8 +72,7 @@
/mob/living/basic/stickman/ranged/Initialize(mapload)
. = ..()
var/static/list/stickman_drops = list(/obj/item/gun/ballistic/automatic/pistol/stickman)
AddElement(/datum/element/death_drops, stickman_drops)
AddElement(/datum/element/death_drops, /obj/item/gun/ballistic/automatic/pistol/stickman)
AddComponent(/datum/component/ranged_attacks, casing_type = /obj/item/ammo_casing/c9mm, projectile_sound = 'sound/misc/bang.ogg', cooldown_time = 5 SECONDS)
/datum/ai_controller/basic_controller/stickman/ranged
@@ -31,7 +31,7 @@
/mob/living/basic/zombie/Initialize(mapload)
. = ..()
apply_dynamic_human_appearance(src, outfit, /datum/species/zombie, bloody_slots = ITEM_SLOT_OCLOTHING)
AddElement(/datum/element/death_drops, string_list(list(/obj/effect/decal/remains/human)))
AddElement(/datum/element/death_drops, /obj/effect/decal/remains/human)
/mob/living/basic/zombie/melee_attack(atom/target, list/modifiers, ignore_cooldown)
. = ..()
@@ -104,7 +104,7 @@
var/datum/callback/retaliate_callback = CALLBACK(src, PROC_REF(ai_retaliate_behaviour))
chosen_hat_colour = pick_weight(gnome_hat_colours)
apply_colour()
AddElement(/datum/element/death_drops, string_list(list(/obj/effect/gibspawner/generic)))
AddElement(/datum/element/death_drops, /obj/effect/gibspawner/generic)
AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE)
AddComponent(/datum/component/ai_retaliate_advanced, retaliate_callback)
AddComponent(/datum/component/swarming)
@@ -46,8 +46,7 @@
/mob/living/basic/ghost/Initialize(mapload)
. = ..()
var/static/list/death_loot = list(/obj/item/ectoplasm)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/item/ectoplasm)
AddElement(/datum/element/simple_flying)
AddElement(/datum/element/ai_retaliate)
@@ -41,8 +41,7 @@
/mob/living/basic/hivebot/Initialize(mapload)
. = ..()
var/static/list/death_loot = list(/obj/effect/decal/cleanable/blood/gibs/robot_debris)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/effect/decal/cleanable/blood/gibs/robot_debris)
AddComponent(/datum/component/appearance_on_aggro, overlay_icon = icon, overlay_state = "[initial(icon_state)]_attack")
if(!ranged_attacker)
return
@@ -48,13 +48,11 @@
/mob/living/basic/lightgeist/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_MEDICAL_HUD, INNATE_TRAIT)
remove_verb(src, /mob/living/verb/pulled)
remove_verb(src, /mob/verb/me_verb)
var/datum/atom_hud/medical_sensor = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
medical_sensor.show_to(src)
AddElement(/datum/element/simple_flying)
AddComponent(\
/datum/component/healing_touch,\
@@ -36,8 +36,7 @@
/mob/living/basic/meteor_heart/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_IMMOBILIZED, INNATE_TRAIT)
var/static/list/death_loot = list(/obj/effect/temp_visual/meteor_heart_death)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/effect/temp_visual/meteor_heart_death)
AddElement(/datum/element/relay_attackers)
var/static/list/innate_actions = list(
@@ -101,5 +101,4 @@
/mob/living/basic/migo/hatsune/Initialize(mapload)
. = ..()
var/static/list/death_loot = list(/obj/item/instrument/piano_synth)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/item/instrument/piano_synth)
@@ -26,9 +26,6 @@
var/datum/action/cooldown/spell/conjure/wizard_summon_minions/summon
///spell to summon clones
var/datum/action/cooldown/spell/pointed/wizard_mimic/mimic
///the loot we will drop
var/static/list/dropped_loot = list(/obj/effect/temp_visual/paperwiz_dying)
/mob/living/basic/paper_wizard/Initialize(mapload)
. = ..()
@@ -46,7 +43,7 @@
grant_actions_by_list(innate_actions)
/mob/living/basic/paper_wizard/proc/grant_loot()
AddElement(/datum/element/death_drops, dropped_loot)
AddElement(/datum/element/death_drops, /obj/effect/temp_visual/paperwiz_dying)
/datum/ai_controller/basic_controller/paper_wizard
blackboard = list(
@@ -216,7 +216,7 @@
* * atom/lean_target - the target we try to add the spit to
*/
/mob/living/basic/regal_rat/proc/poison_target(atom/target)
if(isnull(target.reagents) || !target.is_injectable(src, allowmobs = TRUE))
if(isnull(target.reagents) || !target.is_injectable(src, /*allowmobs = */TRUE))
return FALSE
visible_message(
@@ -169,8 +169,6 @@
web_speed = 0.25
web_type = /datum/action/cooldown/mob_cooldown/lay_web/sealer
menu_description = "Avarage speed spider able to heal other spiders and itself together with a fast web laying capability, has low damage and health."
///The health HUD applied to the mob.
var/health_hud = DATA_HUD_MEDICAL_ADVANCED
///Used in the caves away mission.
/mob/living/basic/spider/giant/nurse/away_caves
@@ -179,8 +177,7 @@
/mob/living/basic/spider/giant/nurse/Initialize(mapload)
. = ..()
var/datum/atom_hud/datahud = GLOB.huds[health_hud]
datahud.show_to(src)
ADD_TRAIT(src, TRAIT_MEDICAL_HUD, INNATE_TRAIT)
AddComponent(/datum/component/healing_touch,\
heal_brute = 10,\
@@ -92,13 +92,10 @@
speed = 0.7
web_speed = 0.5
web_type = /datum/action/cooldown/mob_cooldown/lay_web/sealer
///The health HUD applied to the mob.
var/health_hud = DATA_HUD_MEDICAL_ADVANCED
/mob/living/basic/spider/growing/young/nurse/Initialize(mapload)
. = ..()
var/datum/atom_hud/datahud = GLOB.huds[health_hud]
datahud.show_to(src)
ADD_TRAIT(src, TRAIT_MEDICAL_HUD, INNATE_TRAIT)
AddComponent(/datum/component/healing_touch,\
heal_brute = 15,\
@@ -156,5 +156,4 @@
/mob/living/basic/statue/frosty/Initialize(mapload)
. = ..()
var/static/list/death_loot = list(/obj/item/dnainjector/geladikinesis)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/item/dnainjector/geladikinesis)
@@ -51,8 +51,7 @@
/mob/living/basic/wumborian_fugu/Initialize(mapload)
. = ..()
AddComponent(/datum/component/seethrough_mob)
var/static/list/death_loot = list(/obj/item/fugu_gland)
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/item/fugu_gland)
add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), ROUNDSTART_TRAIT)
expand = new(src)
expand.Grant(src)
+1 -2
View File
@@ -56,8 +56,7 @@
. = ..()
AddComponent(/datum/component/seethrough_mob)
AddElement(/datum/element/swabable, CELL_LINE_TABLE_PINE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5)
var/list/death_loot = string_list(list(/obj/item/stack/sheet/mineral/wood))
AddElement(/datum/element/death_drops, death_loot)
AddElement(/datum/element/death_drops, /obj/item/stack/sheet/mineral/wood)
AddComponent(/datum/component/aggro_emote, emote_list = string_list(list("growls")), emote_chance = 20)
/mob/living/basic/tree/Life(seconds_per_tick = SSMOBS_DT, times_fired)
@@ -38,8 +38,6 @@
var/minion_path = /mob/living/basic/cockroach/sewer
/// Command list given to minionised cockroaches
var/list/minion_commands
/// Cockroach death drops
var/static/list/death_drops = list(/obj/effect/decal/cleanable/insectguts)
/mob/living/basic/cockroach/Initialize(mapload)
var/turf/our_turf = get_turf(src)
@@ -50,7 +48,7 @@
minimum_survivable_temperature = 140 // 40kelvin below icebox temp
add_atom_colour("#66ccff", FIXED_COLOUR_PRIORITY)
. = ..()
AddElement(/datum/element/death_drops, death_drops)
AddElement(/datum/element/death_drops, /obj/effect/decal/cleanable/insectguts)
AddElement(/datum/element/swabable, cockroach_cell_line, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 7)
AddComponent( \
/datum/component/squashable, \
@@ -99,12 +97,10 @@
icon_dead = "bloodroach_no_animation"
health = 3
maxHealth = 3 // Wow!!
var/static/list/blood_drops = list(/obj/effect/decal/cleanable/blood/gibs/old)
/mob/living/basic/cockroach/bloodroach/Initialize(mapload)
. = ..()
// Overriding the static drops of parent
AddElement(/datum/element/death_drops, blood_drops)
AddElement(/datum/element/death_drops, /obj/effect/decal/cleanable/blood/gibs/old)
/mob/living/basic/cockroach/bloodroach/death(gibbed)
if(HAS_TRAIT(src, TRAIT_BUGKILLER_DEATH))
-3
View File
@@ -4,8 +4,6 @@
losebreath = 0
breathing_loop.stop() //This would've happened eventually but it's nice to make it stop immediatelly in this case
if(!gibbed)
add_memory_in_range(src, 7, /datum/memory/witnessed_death, protagonist = src)
reagents.end_metabolization(src)
. = ..()
@@ -18,7 +16,6 @@
BT.on_death()
/mob/living/carbon/gib(drop_bitflags=NONE)
add_memory_in_range(src, 7, /datum/memory/witness_gib, protagonist = src)
if(drop_bitflags & DROP_ITEMS)
for(var/obj/item/W in src)
if(dropItemToGround(W))
+2 -2
View File
@@ -180,7 +180,7 @@
if(appears_dead)
bleed_text += ", but it has pooled and is not flowing."
else
if(HAS_TRAIT(src, TRAIT_BLOODY_MESS))
if(HAS_TRAIT(src, TRAIT_BLOOD_FOUNTAIN))
bleed_text += " incredibly quickly"
bleed_text += "!"
@@ -230,7 +230,7 @@
living_user.add_mood_event("encountered_evil", /datum/mood_event/encountered_evil)
living_user.set_jitter_if_lower(15 SECONDS)
if(HAS_TRAIT(user, TRAIT_SPIRITUAL) && mind?.holy_role)
if(HAS_TRAIT(user, TRAIT_SPIRITUAL) && mind?.holy_role && user != src)
. += "[t_He] [t_has] a holy aura about [t_him]."
living_user.add_mood_event("religious_comfort", /datum/mood_event/religiously_comforted)
@@ -910,8 +910,22 @@ GLOBAL_LIST_EMPTY(features_by_species)
//Someone in a grapple is much more vulnerable to being harmed by punches.
var/grappled = (target.pulledby && target.pulledby.grab_state >= GRAB_AGGRESSIVE)
var/damage = rand(attacking_bodypart.unarmed_damage_low, attacking_bodypart.unarmed_damage_high)
// Our lower and upper unarmed damage values. Damage is rolled between these two values.
var/lower_unarmed_damage = attacking_bodypart.unarmed_damage_low
var/upper_unarmed_damage = attacking_bodypart.unarmed_damage_high
// The presence of TRAIT_STRENGTH increases our upper unarmed damage. This is a damage cap increase.
upper_unarmed_damage += HAS_TRAIT(user, TRAIT_STRENGTH) ? 2 : 0
// Out athletics skill is used to set our potential base damage roll. It won't increase our potential damage roll, but will make our unarmed attack more consistent.
// For a normal human arm, this would cap at 10, and for a normal human leg, this would go up to 14.
lower_unarmed_damage = min(lower_unarmed_damage + (user.mind?.get_skill_level(/datum/skill/athletics) || 0), upper_unarmed_damage)
// The actual damage roll. May still be augmented by further factors.
var/damage = rand(lower_unarmed_damage, upper_unarmed_damage)
// Limb accuracy is used to determine miss probabilities (higher the value, the less likely you are to miss), armor penetration (if entitled) and the possible result from a stagger combo hit.
var/limb_accuracy = attacking_bodypart.unarmed_effectiveness
// Limb sharpness determines the type of wounds this unarmed strike could possibly roll. By default, most limbs are blunt and have no sharpness.
var/limb_sharpness = attacking_bodypart.unarmed_sharpness
if(grappled)
@@ -950,7 +964,7 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/obj/item/bodypart/affecting = target.get_bodypart(hit_zone)
var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases
if(attacking_bodypart.unarmed_damage_low)
if(lower_unarmed_damage)
if((target.body_position == LYING_DOWN) || HAS_TRAIT(user, TRAIT_PERFECT_ATTACKER) || staggered || user_drunkenness && HAS_TRAIT(user, TRAIT_DRUNKEN_BRAWLER)) //kicks and attacks against staggered targets never miss (provided your species deals more than 0 damage). Drunken brawlers while drunk also don't miss
miss_chance = 0
else
@@ -1035,8 +1049,8 @@ GLOBAL_LIST_EMPTY(features_by_species)
/// Handles the stagger combo effect of our punch. Follows the same logic as the above proc, target is our owner, user is our attacker.
/datum/species/proc/stagger_combo(mob/living/carbon/human/user, mob/living/carbon/human/target, atk_verb = "hit", limb_accuracy = 0, armor_block = 0)
// Randomly determines the effects of our punch. Limb accuracy is a bonus, armor block is a defense
var/roll_them_bones = rand(-20, 20) + limb_accuracy - armor_block
// Randomly determines the effects of our punch. Limb accuracy is a bonus, armor block is a defense, attacker athletics provides a minor to significant bonus.
var/roll_them_bones = rand(-20, 20) + limb_accuracy - armor_block + ((user.mind?.get_skill_modifier(/datum/skill/athletics, SKILL_RANDS_MODIFIER) / 2) || 0)
switch(roll_them_bones)
if (-INFINITY to 0) //Mostly a gimmie, this one just keeps them staggered briefly
@@ -34,14 +34,9 @@
///Get all the clothing on a specific body part
/mob/living/carbon/human/proc/get_clothing_on_part(obj/item/bodypart/def_zone)
var/list/covering_part = list()
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id, wear_neck) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
for(var/bp in body_parts)
if(!bp)
continue
if(bp && istype(bp , /obj/item/clothing))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & def_zone.body_part)
covering_part += C
for(var/obj/item/clothing/equipped in get_equipped_items())
if(equipped.body_parts_covered & def_zone.body_part)
covering_part += equipped
return covering_part
/mob/living/carbon/human/bullet_act(obj/projectile/bullet, def_zone, piercing_hit = FALSE)
@@ -305,6 +305,9 @@
for(var/datum/quirk/original_quircks as anything in quirks)
clone.add_quirk(original_quircks.type, override_client = client, announce = FALSE)
for(var/personality_type in personalities)
clone.add_personality(personality_type)
clone.updateappearance(mutcolor_update = TRUE, mutations_overlay_update = TRUE)
return clone
@@ -55,6 +55,8 @@ GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
actions += "adjust_sensor"
if(jumpsuit.can_adjust)
actions += "adjust_jumpsuit"
if(length(jumpsuit.attached_accessories))
actions += "strip_accessory"
return actions
@@ -70,6 +72,8 @@ GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
do_adjust_jumpsuit(source, user, jumpsuit)
if("adjust_sensor")
do_adjust_sensor(source, user, jumpsuit)
if("strip_accessory")
do_strip_accessory(source, user, jumpsuit)
else
stack_trace("Unknown action key: [action_key] for [type]")
@@ -114,15 +118,43 @@ GLOBAL_LIST_INIT(strippable_human_items, create_strippable_list(list(
return
to_chat(source, span_notice("[user] is trying to adjust your [jumpsuit.name]'s sensor."))
if(!do_after(user, jumpsuit.strip_delay * 0.5, source)) // takes the same amount of time as adjusting it
if(!do_after(user, jumpsuit.strip_delay * 0.5, source) || !jumpsuit.set_sensor_mode(new_mode)) // takes the same amount of time as adjusting it
source.balloon_alert(user, "failed!")
return
source.balloon_alert(user, "changed sensors")
jumpsuit.sensor_mode = new_mode
to_chat(source, span_notice("[user] successfully adjusted your [jumpsuit.name]'s sensor."))
if(ishuman(source))
var/mob/living/carbon/human/humano = source
humano.update_suit_sensors()
/datum/strippable_item/mob_item_slot/jumpsuit/proc/do_strip_accessory(atom/source, mob/user, obj/item/clothing/under/jumpsuit)
var/list/accessory_choices = list()
for(var/obj/item/clothing/accessory/jumpsuit_accessory as anything in jumpsuit.attached_accessories)
if(!istype(jumpsuit_accessory))
continue
accessory_choices[jumpsuit_accessory.name] += jumpsuit_accessory
var/chosen_accessory_name = tgui_input_list(user, "Select which accessory to strip", "Select Accessory", accessory_choices)
var/obj/item/clothing/accessory/chosen_accessory = accessory_choices[chosen_accessory_name]
if(isnull(chosen_accessory))
return
if(!user.Adjacent(source))
source.balloon_alert(user, "can't reach!")
return
to_chat(source, span_notice("[user] is trying to take [chosen_accessory] off of [jumpsuit]!"))
if(!do_after(user, chosen_accessory.strip_delay, source))
source.balloon_alert(user, "failed!")
return
to_chat(source, span_notice("[user] has taken [chosen_accessory] off of [jumpsuit]."))
jumpsuit.remove_accessory(chosen_accessory)
jumpsuit.update_appearance()
chosen_accessory.forceMove(jumpsuit.drop_location())
if(!ismob(source))
return
var/mob/mob_source = source
mob_source.update_worn_undersuit()
/datum/strippable_item/mob_item_slot/suit
key = STRIPPABLE_ITEM_SUIT
@@ -192,7 +192,6 @@
if(w_uniform)
return
w_uniform = equipping
update_suit_sensors()
update_worn_undersuit()
if(ITEM_SLOT_LPOCKET)
l_store = equipping
@@ -234,7 +233,6 @@
update_worn_oversuit()
else if(item_dropping == w_uniform)
w_uniform = null
update_suit_sensors()
if(!QDELETED(src))
update_worn_undersuit()
if(invdrop)
@@ -3,6 +3,7 @@
id = SPECIES_ABDUCTOR
sexes = FALSE
inherent_traits = list(
TRAIT_ABDUCTOR_HUD,
TRAIT_CHUNKYFINGERS_IGNORE_BATON,
TRAIT_NEVER_WOUNDED,
TRAIT_NOBLOOD,
@@ -32,16 +33,6 @@
return "Abductors do not need to breathe, eat, do not have blood, a heart, stomach, or lungs and cannot be infected by human viruses. \
Their hardy physique prevents their skin from being wounded or dismembered, but their chunky tridactyl hands make it hard to operate human equipment."
/datum/species/abductor/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load, regenerate_icons)
. = ..()
var/datum/atom_hud/abductor_hud = GLOB.huds[DATA_HUD_ABDUCTOR]
abductor_hud.show_to(C)
/datum/species/abductor/on_species_loss(mob/living/carbon/C)
. = ..()
var/datum/atom_hud/abductor_hud = GLOB.huds[DATA_HUD_ABDUCTOR]
abductor_hud.hide_from(C)
/datum/species/abductor/get_species_description()
return "Abductors, colloquially known as \"Greys\" (or \"Grays\"), \
are, three fingered, pale skinned inquisitive aliens who can't communicate well to the average crew-member."
@@ -7,6 +7,7 @@
mutanttongue = /obj/item/organ/tongue/zombie
inherent_traits = list(
// SHARED WITH ALL ZOMBIES
TRAIT_BLOODY_MESS,
TRAIT_EASILY_WOUNDED,
TRAIT_EASYDISMEMBER,
TRAIT_FAKEDEATH,
@@ -102,6 +103,7 @@
inherent_traits = list(
// SHARED WITH ALL ZOMBIES
TRAIT_BLOODY_MESS,
TRAIT_EASILY_WOUNDED,
TRAIT_EASYDISMEMBER,
TRAIT_FAKEDEATH,
+48 -2
View File
@@ -17,6 +17,7 @@
if(stat != DEAD)
death(TRUE)
send_death_moodlets(/datum/mood_event/see_death)
ghostize()
spill_organs(drop_bitflags)
@@ -102,6 +103,8 @@
// keep us upright so the animation fits.
ADD_TRAIT(src, TRAIT_FORCED_STANDING, TRAIT_GENERIC)
send_death_moodlets(/datum/mood_event/see_death/dusted)
if(drop_items)
unequip_everything()
@@ -160,6 +163,47 @@
ash.pixel_z = -5
ash.pixel_w = rand(-1, 1)
/**
* Sends a moodlet to all nearby living mobs that are not blind or unconscious
* to indicate that they saw this mob die (and thus feel bad about it)
*
* Note: If the mob already has a death moodlet, and the same moodlet is applied, the existing moodlet will simply worsen.
* Note: If the mob has a death moodlet, and a worse moodlet is applied, the worse moodlet will take priority.
*
* Arguments:
* * moodlet - The type of moodlet to send. Defaults to [/datum/mood_event/see_death]
*/
/mob/living/proc/send_death_moodlets(datum/mood_event/moodlet = /datum/mood_event/see_death)
if(flags_1 & HOLOGRAM_1)
return
for(var/mob/living/nearby in viewers(src))
if(nearby.stat >= UNCONSCIOUS || nearby.is_blind())
continue
nearby.add_mood_event("saw_death", moodlet, src)
/mob/living/silicon/send_death_moodlets(datum/mood_event/moodlet)
return // You are a machine
/mob/living/basic/send_death_moodlets(datum/mood_event/moodlet)
if(!(basic_mob_flags & SENDS_DEATH_MOODLETS))
return
. = ..()
add_memory_in_range(src, 7, /datum/memory/pet_died, deuteragonist = src) //Protagonist is the person memorizing it
/mob/living/simple_animal/send_death_moodlets(datum/mood_event/moodlet)
return // I don't care about you anymore
/mob/living/carbon/human/send_death_moodlets(datum/mood_event/moodlet)
for(var/datum/surgery/organ_manipulation/manipulation in surgeries)
// This check exists so debraining someone doesn't make the surgeon super sad
if(manipulation.location == BODY_ZONE_HEAD && body_position == LYING_DOWN)
return
. = ..()
var/memory_type = ispath(moodlet, /datum/mood_event/see_death/gibbed) ? /datum/memory/witness_gib : /datum/memory/witnessed_death
add_memory_in_range(src, 7, memory_type, protagonist = src)
/*
* Called when the mob dies. Can also be called manually to kill a mob.
*
@@ -170,8 +214,10 @@
if(stat == DEAD)
return FALSE
if(!gibbed && (death_sound || death_message || (living_flags & ALWAYS_DEATHGASP)))
INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "deathgasp")
if(!gibbed)
if(death_sound || death_message || (living_flags & ALWAYS_DEATHGASP))
INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "deathgasp")
send_death_moodlets(/datum/mood_event/see_death)
set_stat(DEAD)
timeofdeath = world.time
+16
View File
@@ -70,6 +70,10 @@
RegisterSignal(src, COMSIG_MOVABLE_EDIT_UNIQUE_IMMERSE_OVERLAY, PROC_REF(edit_immerse_overlay))
RegisterSignal(src, SIGNAL_ADDTRAIT(TRAIT_BASIC_HEALTH_HUD_VISIBLE), PROC_REF(add_to_basic_health_hud))
RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_BASIC_HEALTH_HUD_VISIBLE), PROC_REF(remove_from_basic_health_hud))
/// Called when [TRAIT_KNOCKEDOUT] is added to the mob.
/mob/living/proc/on_knockedout_trait_gain(datum/source)
SIGNAL_HANDLER
@@ -297,3 +301,15 @@
/mob/living/proc/on_hearing_regain()
SIGNAL_HANDLER
refresh_looping_ambience()
/// When gaining [TRAIT_BASIC_HEALTH_HUD_VISIBLE], add to the basic health hud
/mob/living/proc/add_to_basic_health_hud(datum/source)
SIGNAL_HANDLER
var/datum/atom_hud/data/human/medical/basic/hud = GLOB.huds[DATA_HUD_MEDICAL_BASIC]
hud.add_atom_to_hud(src)
/// When losing [TRAIT_BASIC_HEALTH_HUD_VISIBLE], remove from the basic health hud
/mob/living/proc/remove_from_basic_health_hud(datum/source)
SIGNAL_HANDLER
var/datum/atom_hud/data/human/medical/basic/hud = GLOB.huds[DATA_HUD_MEDICAL_BASIC]
hud.remove_atom_from_hud(src)
+6 -5
View File
@@ -33,8 +33,9 @@
else
effect.be_replaced()
if(buckled)
buckled.unbuckle_mob(src,force=1)
clear_personalities() // must be done for the personalities which process
buckled?.unbuckle_mob(src,force=1)
remove_from_all_data_huds()
GLOB.mob_living_list -= src
@@ -43,7 +44,7 @@
QDEL_LIST(imaginary_group)
QDEL_LAZYLIST(diseases)
QDEL_LIST(surgeries)
QDEL_LIST(quirks)
QDEL_LAZYLIST(quirks)
return ..()
/mob/living/onZImpact(turf/impacted_turf, levels, impact_flags = NONE)
@@ -1329,7 +1330,7 @@
var/matrix/flipped_matrix = transform
flipped_matrix.b = -flipped_matrix.b
flipped_matrix.e = -flipped_matrix.e
animate(src, transform = flipped_matrix, time = 0.5 SECONDS, easing = EASE_OUT, flags = ANIMATION_PARALLEL)
animate(src, transform = flipped_matrix, time = 0.5 SECONDS, easing = SINE_EASING|EASE_OUT, flags = ANIMATION_PARALLEL)
add_offsets(NEGATIVE_GRAVITY_TRAIT, y_add = 4)
if(NEGATIVE_GRAVITY + 0.01 to 0)
if(!istype(gravity_alert, /atom/movable/screen/alert/weightless))
@@ -1354,7 +1355,7 @@
var/matrix/flipped_matrix = transform
flipped_matrix.b = -flipped_matrix.b
flipped_matrix.e = -flipped_matrix.e
animate(src, transform = flipped_matrix, time = 0.5 SECONDS, easing = EASE_OUT, flags = ANIMATION_PARALLEL)
animate(src, transform = flipped_matrix, time = 0.5 SECONDS, easing = SINE_EASING|EASE_OUT, flags = ANIMATION_PARALLEL)
remove_offsets(NEGATIVE_GRAVITY_TRAIT)
/mob/living/singularity_pull(atom/singularity, current_size)
+5 -1
View File
@@ -89,7 +89,11 @@
*/
var/incorporeal_move = FALSE
var/list/quirks = list()
/// Lazylist of all quirks the mob has. These are not singletons
var/list/quirks
/// Lazylist of all typepaths of personalities the mob has.
var/list/personalities
///a list of surgery datums. generally empty, they're added when the player wants them.
var/list/surgeries = list()
///Mob specific surgery speed modifier
@@ -51,7 +51,7 @@
//if true, we want to avoid any animation time, it'll tween and not rotate at all otherwise.
var/is_opposite_angle = REVERSE_ANGLE(lying_angle) == lying_prev
var/animate_time = is_opposite_angle ? 0 : UPDATE_TRANSFORM_ANIMATION_TIME
animate(src, transform = ntransform, time = animate_time, dir = final_dir, easing = (EASE_IN|EASE_OUT))
animate(src, transform = ntransform, time = animate_time, dir = final_dir, easing = SINE_EASING)
for (var/hud_key in hud_list)
var/image/hud_image = hud_list[hud_key]
if (istype(hud_image))
+10 -4
View File
@@ -81,16 +81,22 @@
//They aren't given a c_tag so they don't show up in camera consoles
builtInCamera = new(src)
var/static/list/alert_areas
if(isnull(alert_areas))
alert_areas = (GLOB.the_station_areas + typesof(/area/mine))
if(is_station_level(z))
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), SSmapping.levels_by_trait(ZTRAIT_STATION), alert_areas, camera_view = TRUE)
else
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), (SSmapping.levels_by_trait(ZTRAIT_STATION) + z), alert_areas, camera_view = TRUE)
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_TRIGGERED, PROC_REF(alarm_triggered))
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_CLEARED, PROC_REF(alarm_cleared))
ai_tracking_tool = new(src)
RegisterSignal(ai_tracking_tool, COMSIG_TRACKABLE_TRACKING_TARGET, PROC_REF(on_track_target))
RegisterSignal(ai_tracking_tool, COMSIG_TRACKABLE_GLIDE_CHANGED, PROC_REF(tracked_glidesize_changed))
add_traits(list(TRAIT_PULL_BLOCKED, TRAIT_AI_ACCESS, TRAIT_HANDS_BLOCKED, TRAIT_CAN_GET_AI_TRACKING_MESSAGE, TRAIT_LOUD_BINARY), INNATE_TRAIT)
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), list(z), camera_view = TRUE)
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_TRIGGERED, PROC_REF(alarm_triggered))
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_CLEARED, PROC_REF(alarm_cleared))
//Heads up to other binary chat listeners that a new AI is online and listening to Binary.
if(announce_init_to_others && !is_centcom_level(z)) //Skip new syndicate AIs and also new AIs on centcom Z
for(var/mob/McMobby as anything in GLOB.player_list)
@@ -12,7 +12,7 @@
mob_size = MOB_SIZE_LARGE
can_buckle_to = FALSE
silicon_huds = list(DATA_HUD_MEDICAL_BASIC, DATA_HUD_SECURITY_BASIC, DATA_HUD_DIAGNOSTIC, DATA_HUD_BOT_PATH)
silicon_huds = list(TRAIT_MEDICAL_HUD_SENSOR_ONLY, TRAIT_SECURITY_HUD_ID_ONLY, TRAIT_DIAGNOSTIC_HUD, TRAIT_BOT_PATH_HUD)
radio = /obj/item/radio/headset/silicon/ai
radiomod = ";" //AIs will, by default, state their laws on the internal radio.
@@ -52,3 +52,6 @@
. += "</span>"
. += ..()
/mob/living/silicon/robot/examine_descriptor(mob/user)
return "cyborg"
@@ -88,7 +88,13 @@
log_silicon("New cyborg [key_name(src)] created with [connected_ai ? "master AI: [key_name(connected_ai)]" : "no master AI"]")
log_current_laws()
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), list(z))
var/static/list/alert_areas
if(isnull(alert_areas))
alert_areas = (GLOB.the_station_areas + typesof(/area/mine))
if(is_station_level(z))
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), SSmapping.levels_by_trait(ZTRAIT_STATION), alert_areas)
else
alert_control = new(src, list(ALARM_ATMOS, ALARM_FIRE, ALARM_POWER, ALARM_CAMERA, ALARM_BURGLAR, ALARM_MOTION), (SSmapping.levels_by_trait(ZTRAIT_STATION) + z), alert_areas)
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_TRIGGERED, PROC_REF(alarm_triggered))
RegisterSignal(alert_control.listener, COMSIG_ALARM_LISTENER_CLEARED, PROC_REF(alarm_cleared))
alert_control.listener.RegisterSignal(src, COMSIG_LIVING_DEATH, TYPE_PROC_REF(/datum/alarm_listener, prevent_alarm_changes))
+8 -7
View File
@@ -40,7 +40,7 @@
///Are our siliconHUDs on? TRUE for yes, FALSE for no.
var/sensors_on = TRUE
var/list/silicon_huds = list(DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_SECURITY_ADVANCED, DATA_HUD_DIAGNOSTIC)
var/list/silicon_huds = list(TRAIT_MEDICAL_HUD, TRAIT_SECURITY_HUD, TRAIT_DIAGNOSTIC_HUD)
var/law_change_counter = 0
var/obj/machinery/camera/silicon/builtInCamera
@@ -419,15 +419,16 @@
/mob/living/silicon/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) //Secbots won't hunt silicon units
return -10
/// Innate, toggleable silicon HUDs
#define SILICON_HUD_TRAIT "silicon_hud"
/mob/living/silicon/proc/remove_sensors()
for (var/hud_type in silicon_huds)
var/datum/atom_hud/silicon_hud = GLOB.huds[hud_type]
silicon_hud.hide_from(src)
remove_traits(silicon_huds, SILICON_HUD_TRAIT)
/mob/living/silicon/proc/add_sensors()
for (var/hud_type in silicon_huds)
var/datum/atom_hud/silicon_hud = GLOB.huds[hud_type]
silicon_hud.show_to(src)
add_traits(silicon_huds, SILICON_HUD_TRAIT)
#undef SILICON_HUD_TRAIT
/mob/living/silicon/proc/toggle_sensors()
if(incapacitated)
@@ -94,7 +94,7 @@
var/turf/nearest_beacon_loc
///The type of data HUD the bot uses. Diagnostic by default.
var/data_hud_type = DATA_HUD_DIAGNOSTIC
var/data_hud_type = TRAIT_DIAGNOSTIC_HUD
var/datum/atom_hud/data/bot_path/private/path_hud
var/path_image_icon = 'icons/mob/silicon/aibots.dmi'
var/path_image_icon_state = "path_indicator"
@@ -191,8 +191,7 @@
//If a bot has its own HUD (for player bots), provide it.
if(!isnull(data_hud_type))
var/datum/atom_hud/datahud = GLOB.huds[data_hud_type]
datahud.show_to(src)
ADD_TRAIT(src, data_hud_type, INNATE_TRAIT)
if(path_hud)
path_hud.add_atom_to_hud(src)
path_hud.show_to(src)
@@ -20,7 +20,7 @@
radio_channel = RADIO_CHANNEL_SECURITY //Security channel
bot_type = SEC_BOT
bot_mode_flags = ~BOT_MODE_CAN_BE_SAPIENT
data_hud_type = DATA_HUD_SECURITY_ADVANCED
data_hud_type = TRAIT_SECURITY_HUD
hackables = "target identification systems"
path_image_color = COLOR_RED
possessed_message = "You are a securitron! Guard the station to the best of your ability!"
@@ -35,14 +35,14 @@
can_buckle_to = FALSE
/// Crusher loot dropped when the megafauna is killed with a crusher
var/list/crusher_loot
/// Should the crusher drop replace our main loot entirely?
var/replace_crusher_drop = FALSE
/// Achievement given to surrounding players when the megafauna is killed
var/achievement_type
/// Crusher achievement given to players when megafauna is killed
var/crusher_achievement_type
/// Score given to players when megafauna is killed
var/score_achievement_type
/// If the megafauna was actually killed (not just dying, then transforming into another type)
var/elimination = 0
/// Modifies attacks when at lower health
var/anger_modifier = 0
/// Name for the GPS signal of the megafauna
@@ -62,17 +62,32 @@
/mob/living/simple_animal/hostile/megafauna/Initialize(mapload)
. = ..()
AddComponent(\
/datum/component/basic_mob_attack_telegraph,\
display_telegraph_overlay = FALSE,\
telegraph_duration = attack_delay,\
)
AddComponent(/datum/component/seethrough_mob)
AddElement(/datum/element/simple_flying)
if (achievement_type || score_achievement_type)
var/list/achievements = list(/datum/award/achievement/boss/boss_killer, /datum/award/score/boss_score)
if (achievement_type)
achievements += achievement_type
if (score_achievement_type)
achievements += score_achievement_type
AddElement(/datum/element/kill_achievement, string_list(achievements), crusher_achievement_type, /datum/memory/megafauna_slayer)
if(gps_name && true_spawn)
AddComponent(/datum/component/gps, gps_name)
if(crusher_loot)
if (islist(crusher_loot))
crusher_loot = string_list(crusher_loot)
AddElement(\
/datum/element/crusher_loot,\
trophy_type = crusher_loot,\
guaranteed_drop = 0.6,\
replace_all = replace_crusher_drop,\
drop_immediately = del_on_death,\
)
ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
add_traits(list(TRAIT_NO_TELEPORT), MEGAFAUNA_TRAIT)
grant_actions_by_list(attack_action_types)
@@ -83,41 +98,14 @@
return ..()
return ..()
/mob/living/simple_animal/hostile/megafauna/death(gibbed, list/force_grant)
if(gibbed) // in case they've been force dusted
return ..()
if(health > 0) // prevents instakills
/mob/living/simple_animal/hostile/megafauna/death(gibbed)
if(health > 0 && !gibbed) // prevents instakills
return
var/datum/status_effect/crusher_damage/crusher_dmg = has_status_effect(/datum/status_effect/crusher_damage)
///Whether we killed the megafauna with primarily crusher damage or not
var/crusher_kill = FALSE
if(crusher_dmg && crusher_dmg.total_damage >= maxHealth * 0.6)
crusher_kill = TRUE
if(crusher_loot) // spawn crusher loot, if any
spawn_crusher_loot()
// SKYRAT EDIT ADDITION START - ASHWALKER TROPHIES
var/datum/status_effect/ashwalker_damage/ashie_damage = has_status_effect(/datum/status_effect/ashwalker_damage)
if(!crusher_kill && ashie_damage && crusher_loot && ashie_damage.total_damage >= maxHealth * 0.6)
spawn_crusher_loot()
// SKYRAT EDIT ADDITION END
if(true_spawn && !(flags_1 & ADMIN_SPAWNED_1))
var/tab = "megafauna_kills"
if(crusher_kill)
tab = "megafauna_kills_crusher"
if(!elimination) //used so the achievment only occurs for the last legion to die.
grant_achievement(achievement_type, score_achievement_type, crusher_kill, force_grant)
SSblackbox.record_feedback("tally", tab, 1, "[initial(name)]")
return ..()
/// Spawns crusher loot instead of normal loot
/mob/living/simple_animal/hostile/megafauna/proc/spawn_crusher_loot()
loot = crusher_loot
/mob/living/simple_animal/hostile/megafauna/gib()
if(health > 0)
return
return ..()
/mob/living/simple_animal/hostile/megafauna/singularity_act()
@@ -127,10 +115,7 @@
/mob/living/simple_animal/hostile/megafauna/dust(just_ash, drop_items, force)
if(!force && health > 0)
return
crusher_loot.Cut()
loot.Cut()
return ..()
/mob/living/simple_animal/hostile/megafauna/AttackingTarget(atom/attacked_target)
@@ -209,25 +194,6 @@
if(cooldown_updates[COOLDOWN_UPDATE_ADD_RANGED])
ranged_cooldown += cooldown_updates[COOLDOWN_UPDATE_ADD_RANGED]
/// Grants medals and achievements to surrounding players
/mob/living/simple_animal/hostile/megafauna/proc/grant_achievement(medaltype, scoretype, crusher_kill, list/grant_achievement = list())
if(!achievement_type || (flags_1 & ADMIN_SPAWNED_1) || !SSachievements.achievements_enabled) //Don't award medals if the medal type isn't set
return FALSE
if(!grant_achievement.len)
for(var/mob/living/L in view(7,src))
grant_achievement += L
for(var/mob/living/L in grant_achievement)
if(L.stat || !L.client)
continue
L.add_mob_memory(/datum/memory/megafauna_slayer, antagonist = src)
L.client.give_award(/datum/award/achievement/boss/boss_killer, L)
L.client.give_award(achievement_type, L)
if(crusher_kill && istype(L.get_active_held_item(), /obj/item/kinetic_crusher))
L.client.give_award(crusher_achievement_type, L)
L.client.give_award(/datum/award/score/boss_score, L) //Score progression for bosses killed in general
L.client.give_award(score_achievement_type, L) //Score progression for specific boss killed
return TRUE
/datum/action/innate/megafauna_attack
name = "Megafauna Attack"
button_icon = 'icons/mob/actions/actions_animal.dmi'
@@ -37,7 +37,7 @@ Difficulty: Medium
rapid_melee = 5 // starts fast because the saw's closed. gets reduced appropriately when extended, see their transform_weapon ability
pixel_x = -16
base_pixel_x = -16
crusher_loot = list(/obj/item/melee/cleaving_saw, /obj/item/gun/energy/recharge/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye, /obj/item/knife/hunting/wildhunter)
crusher_loot = list(/obj/item/crusher_trophy/miner_eye, /obj/item/knife/hunting/wildhunter)
loot = list(/obj/item/melee/cleaving_saw, /obj/item/gun/energy/recharge/kinetic_accelerator)
wander = FALSE
del_on_death = TRUE
@@ -188,11 +188,11 @@ Difficulty: Medium
if(dir & (EAST|WEST)) //Facing east or west
final_dir = pick(NORTH, SOUTH) //So you fall on your side rather than your face or ass
animate(src, transform = our_matrix, pixel_y = -6, dir = final_dir, time = 2, easing = EASE_IN|EASE_OUT)
animate(src, transform = our_matrix, pixel_y = -6, dir = final_dir, time = 2, easing = QUAD_EASING)
sleep(0.5 SECONDS)
animate(src, color = list("#A7A19E", "#A7A19E", "#A7A19E", list(0, 0, 0)), time = 10, easing = EASE_IN, flags = ANIMATION_PARALLEL)
animate(src, color = list("#A7A19E", "#A7A19E", "#A7A19E", list(0, 0, 0)), time = 10, easing = SINE_EASING|EASE_IN, flags = ANIMATION_PARALLEL)
sleep(0.4 SECONDS)
animate(src, alpha = 0, time = 6, easing = EASE_OUT, flags = ANIMATION_PARALLEL)
animate(src, alpha = 0, time = 6, easing = SINE_EASING|EASE_OUT, flags = ANIMATION_PARALLEL)
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance
guidance = TRUE
@@ -58,8 +58,9 @@ Difficulty: Hard
maptext_height = 96
maptext_width = 96
del_on_death = TRUE
crusher_loot = list(/obj/structure/closet/crate/necropolis/bubblegum/crusher)
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
crusher_loot = /obj/structure/closet/crate/necropolis/bubblegum/crusher
replace_crusher_drop = TRUE
blood_volume = BLOOD_VOLUME_MAXIMUM //BLEED FOR ME
gps_name = "Bloody Signal"
achievement_type = /datum/award/achievement/boss/bubblegum_kill
@@ -287,9 +288,9 @@ Difficulty: Hard
else
B.setDir(pick(GLOB.cardinals))
/mob/living/simple_animal/hostile/megafauna/bubblegum/grant_achievement(medaltype,scoretype)
/mob/living/simple_animal/hostile/megafauna/bubblegum/death(gibbed)
. = ..()
if(!(flags_1 & ADMIN_SPAWNED_1))
if(!gibbed && health > 0 && true_spawn && !(flags_1 & ADMIN_SPAWNED_1))
SSshuttle.shuttle_purchase_requirements_met[SHUTTLE_UNLOCK_BUBBLEGUM] = TRUE
/mob/living/simple_animal/hostile/megafauna/bubblegum/AttackingTarget(atom/attacked_target)
@@ -33,7 +33,6 @@ I'd rather there be something than the clockwork ruin be entirely empty though s
ranged = TRUE
gps_name = "Clockwork Signal"
loot = list(/obj/item/clockwork_alloy)
crusher_loot = list(/obj/item/clockwork_alloy)
wander = FALSE
del_on_death = TRUE
death_message = "falls, quickly decaying into centuries old dust."
@@ -51,8 +51,9 @@
achievement_type = /datum/award/achievement/boss/colossus_kill
crusher_achievement_type = /datum/award/achievement/boss/colossus_crusher
score_achievement_type = /datum/award/score/colussus_score
crusher_loot = list(/obj/structure/closet/crate/necropolis/colossus/crusher)
loot = list(/obj/structure/closet/crate/necropolis/colossus)
crusher_loot = /obj/structure/closet/crate/necropolis/colossus/crusher
replace_crusher_drop = TRUE
death_message = "disintegrates, leaving a glowing core in its wake."
death_sound = 'sound/effects/magic/demon_dies.ogg'
summon_line = "Your trial begins now."
@@ -32,7 +32,7 @@ Difficulty: Extremely Hard
move_to_delay = 20
gps_name = "Bloodchilling Signal"
ranged = TRUE
crusher_loot = list(/obj/effect/decal/remains/plasma, /obj/item/crusher_trophy/ice_block_talisman, /obj/item/ice_energy_crystal)
crusher_loot = /obj/item/crusher_trophy/ice_block_talisman
loot = list(/obj/effect/decal/remains/plasma, /obj/item/ice_energy_crystal)
wander = FALSE
del_on_death = TRUE
@@ -177,7 +177,7 @@ Difficulty: Extremely Hard
return
return ..()
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/death(gibbed, list/force_grant)
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/death(gibbed)
if(health > 0)
return
var/turf/T = get_turf(src)
@@ -56,8 +56,9 @@
base_pixel_x = -32
maptext_height = 64
maptext_width = 64
crusher_loot = list(/obj/structure/closet/crate/necropolis/dragon/crusher)
loot = list(/obj/structure/closet/crate/necropolis/dragon)
crusher_loot = /obj/structure/closet/crate/necropolis/dragon/crusher
replace_crusher_drop = TRUE
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30)
guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/ashdrake = 10)
initial_language_holder = /datum/language_holder/lizard/hear_common
@@ -312,7 +313,9 @@
mouse_opacity = MOUSE_OPACITY_ICON
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, STAMINA = 0, OXY = 1)
loot = list()
crusher_loot = list()
crusher_loot = null
achievement_type = null
score_achievement_type = null
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30)
attack_action_types = list()
@@ -326,8 +329,6 @@
. = ..()
lava_swoop?.enraged = FALSE // In case taking damage caused us to start deleting ourselves
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype)
return
#undef DRAKE_ENRAGED
#undef SWOOP_DAMAGEABLE
@@ -60,7 +60,7 @@ Difficulty: Hard
ranged_cooldown_time = 4 SECONDS
aggro_vision_range = 21 //so it can see to one side of the arena to the other
loot = list(/obj/item/hierophant_club)
crusher_loot = list(/obj/item/hierophant_club, /obj/item/crusher_trophy/vortex_talisman)
crusher_loot = /obj/item/crusher_trophy/vortex_talisman
wander = FALSE
gps_name = "Zealous Signal"
achievement_type = /datum/award/achievement/boss/hierophant_kill
@@ -366,14 +366,14 @@ Difficulty: Hard
for(var/t in RANGE_TURFS(1, source))
var/obj/effect/temp_visual/hierophant/blast/damaging/B = new(t, src, FALSE)
B.damage = 30
animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out
animate(src, alpha = 0, time = 2, easing = SINE_EASING|EASE_OUT) //fade out
SLEEP_CHECK_DEATH(1, src)
visible_message(span_hierophant_warning("[src] fades out!"))
ADD_TRAIT(src, TRAIT_UNDENSE, VANISHING_TRAIT)
SLEEP_CHECK_DEATH(2, src)
forceMove(T)
SLEEP_CHECK_DEATH(1, src)
animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN
animate(src, alpha = 255, time = 2, easing = SINE_EASING|EASE_IN) //fade IN
SLEEP_CHECK_DEATH(1, src)
REMOVE_TRAIT(src, TRAIT_UNDENSE, VANISHING_TRAIT)
visible_message(span_hierophant_warning("[src] fades in!"))
@@ -437,17 +437,14 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/death()
if(health > 0 || stat == DEAD)
return
else
set_stat(DEAD)
blinking = TRUE //we do a fancy animation, release a huge burst(), and leave our staff.
visible_message(span_hierophant("\"Mrmxmexmrk wipj-hiwxvygx wiuyirgi...\""))
visible_message(span_hierophant_warning("[src] shrinks, releasing a massive burst of energy!"))
var/list/stored_nearby = list()
for(var/mob/living/L in view(7,src))
stored_nearby += L // store the people to grant the achievements to once we die
hierophant_burst(null, get_turf(src), 10)
set_stat(CONSCIOUS) // deathgasp won't run if dead, stupid
..(force_grant = stored_nearby)
set_stat(DEAD)
blinking = TRUE //we do a fancy animation, release a huge burst(), and leave our staff.
visible_message(span_hierophant("\"Mrmxmexmrk wipj-hiwxvygx wiuyirgi...\""))
visible_message(span_hierophant_warning("[src] shrinks, releasing a massive burst of energy!"))
hierophant_burst(null, get_turf(src), 10)
set_stat(CONSCIOUS) // deathgasp won't run if dead, stupid
..()
/mob/living/simple_animal/hostile/megafauna/hierophant/celebrate_kill(mob/living/L)
visible_message(span_hierophant_warning("\"[pick(kill_phrases)]\""))
@@ -46,16 +46,14 @@
minimum_distance = 5
ranged_cooldown_time = 2 SECONDS
gps_name = "Echoing Signal"
achievement_type = /datum/award/achievement/boss/legion_kill
// Achievements not set as they're added only when the last skull is killed
crusher_achievement_type = /datum/award/achievement/boss/legion_crusher
score_achievement_type = /datum/award/score/legion_score
SET_BASE_PIXEL(-32, -16)
maptext_height = 96
maptext_width = 96
loot = list(/obj/item/stack/sheet/bone = 3)
vision_range = 13
wander = FALSE
elimination = TRUE
appearance_flags = LONG_GLIDE
mouse_opacity = MOUSE_OPACITY_ICON
var/size = LEGION_LARGE
@@ -175,7 +173,8 @@
break
if(last_legion)
loot = list(/obj/item/storm_staff)
elimination = FALSE
var/list/achievements = list(/datum/award/achievement/boss/boss_killer, /datum/award/score/boss_score, /datum/award/score/legion_score, /datum/award/achievement/boss/legion_kill)
AddElement(/datum/element/kill_achievement, string_list(achievements), crusher_achievement_type, /datum/memory/megafauna_slayer)
else if(prob(20)) //20% chance for sick lootz.
loot = list(/obj/structure/closet/crate/necropolis/tendril)
if(!true_spawn)
@@ -35,7 +35,7 @@ Difficulty: Hard
loot = list()
butcher_results = list()
guaranteed_butcher_results = list(/obj/item/wendigo_blood = 1, /obj/item/wendigo_skull = 1)
crusher_loot = list(/obj/item/crusher_trophy/wendigo_horn)
crusher_loot = /obj/item/crusher_trophy/wendigo_horn
wander = FALSE
del_on_death = FALSE
blood_volume = BLOOD_VOLUME_NORMAL
@@ -180,7 +180,7 @@ Difficulty: Hard
all_turfs -= stomp_turf
SLEEP_CHECK_DEATH(delay, owner)
/mob/living/simple_animal/hostile/megafauna/wendigo/death(gibbed, list/force_grant)
/mob/living/simple_animal/hostile/megafauna/wendigo/death(gibbed)
if(health > 0)
return
@@ -146,14 +146,14 @@
new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src)
for(var/t in RANGE_TURFS(1, source))
new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src)
animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out
animate(src, alpha = 0, time = 2, easing = SINE_EASING|EASE_OUT) //fade out
visible_message(span_hierophant_warning("[src] fades out!"))
ADD_TRAIT(src, TRAIT_UNDENSE, VANISHING_TRAIT)
addtimer(CALLBACK(src, PROC_REF(pandora_teleport_3), T), 0.2 SECONDS)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_3(turf/T)
forceMove(T)
animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN
animate(src, alpha = 255, time = 2, easing = CIRCULAR_EASING|EASE_IN) //fade IN
REMOVE_TRAIT(src, TRAIT_UNDENSE, VANISHING_TRAIT)
visible_message(span_hierophant_warning("[src] fades in!"))
@@ -361,17 +361,18 @@
. += "Health: [round((health / maxHealth) * 100)]% ([health]/[maxHealth])"
. += "Combat Mode: [combat_mode ? "On" : "Off"]"
/mob/living/simple_animal/proc/drop_loot()
/mob/living/simple_animal/proc/drop_loot(drop_loc)
if (!length(loot))
return
for(var/i in loot)
new i(drop_location())
new i(drop_loc)
loot.Cut()
/mob/living/simple_animal/death(gibbed)
drop_loot()
var/drop_loc = drop_location()
if(del_on_death)
..()
drop_loot(drop_loc)
//Prevent infinite loops if the mob Destroy() is overridden in such
//a manner as to cause a call to death() again //Pain
del_on_death = FALSE
@@ -383,7 +384,8 @@
if(flip_on_death)
transform = transform.Turn(180)
ADD_TRAIT(src, TRAIT_UNDENSE, BASIC_MOB_DEATH_TRAIT)
return ..()
. = ..()
drop_loot(drop_loc)
/mob/living/simple_animal/proc/CanAttack(atom/the_target)
if(!isatom(the_target)) // no
+22
View File
@@ -489,6 +489,26 @@
return quirk
return null
/// Helper to easily add a personality by a typepath
/mob/living/proc/add_personality(personality_type)
var/datum/personality/personality = SSpersonalities.personalities_by_type[personality_type]
personality.apply_to_mob(src)
/// Helper to easily add multiple personalities by a list of typepaths
/mob/living/proc/add_personalities(list/new_personalities)
for(var/personality_type in new_personalities)
add_personality(personality_type)
/// Helper to easily remove a personality by a typepath
/mob/living/proc/remove_personality(personality_type)
var/datum/personality/personality = SSpersonalities.personalities_by_type[personality_type]
personality.remove_from_mob(src)
/// Helper to clear all personalities from a mob
/mob/living/proc/clear_personalities()
for(var/personality_type in personalities)
remove_personality(personality_type)
/mob/living/proc/cure_husk(source)
REMOVE_TRAIT(src, TRAIT_HUSK, source)
if(HAS_TRAIT(src, TRAIT_HUSK))
@@ -527,6 +547,8 @@
emote("deathgasp")
station_timestamp_timeofdeath = station_time_timestamp()
if(!HAS_TRAIT(src, TRAIT_FAKEDEATH) && !silent)
send_death_moodlets(/datum/mood_event/see_death)
add_traits(list(TRAIT_FAKEDEATH, TRAIT_DEATHCOMA), source)
///Unignores all slowdowns that lack the IGNORE_NOSLOW flag.