mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 23:27:34 +01:00
Merge branch 'master' of https://github.com/tgstation/tgstation into upstream-sync
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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!"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,\
|
||||
|
||||
+1
-4
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user