mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-26 22:50:26 +01:00
Basic Shades (#79469)
## About The Pull Request Makes shades into basic mobs. As they are solely player-controller and have no AI, this was a very simple conversion. Things of note: - I've made shades use the same "theme" system as constructs, to determine their drops and coloration - as opposed to these things being manually set by the type of soulstone they're held in. - I've reorganized files slightly, putting both constructs and shades in a new "cult" basic mob folder. That's more or less it. As I said, shades are simple. ## Why It's Good For The Game Basic-izes another mob and cleans up the code a little. Removes the last cult-related simplemob, too. ## Changelog 🆑 refactor: Shades now use the basic mob framework. Please report any bugs. /🆑
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
/mob/living/basic/construct
|
||||
icon = 'icons/mob/nonhuman-player/cult.dmi'
|
||||
gender = NEUTER
|
||||
basic_mob_flags = DEL_ON_DEATH
|
||||
combat_mode = TRUE
|
||||
mob_biotypes = MOB_MINERAL | MOB_SPECIAL
|
||||
faction = list(FACTION_CULT)
|
||||
unsuitable_atmos_damage = 0
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = INFINITY
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
|
||||
pressure_resistance = 100
|
||||
speed = 0
|
||||
unique_name = TRUE
|
||||
initial_language_holder = /datum/language_holder/construct
|
||||
death_message = "collapses in a shattered heap."
|
||||
|
||||
speak_emote = list("hisses")
|
||||
response_help_continuous = "thinks better of touching"
|
||||
response_help_simple = "think better of touching"
|
||||
response_disarm_continuous = "flails at"
|
||||
response_disarm_simple = "flail at"
|
||||
response_harm_continuous = "punches"
|
||||
response_harm_simple = "punch"
|
||||
melee_attack_cooldown = CLICK_CD_MELEE
|
||||
|
||||
// Vivid red, cause cult theme
|
||||
lighting_cutoff_red = 30
|
||||
lighting_cutoff_green = 5
|
||||
lighting_cutoff_blue = 20
|
||||
|
||||
/// List of spells that this construct can cast
|
||||
var/list/construct_spells = list()
|
||||
/// Flavor text shown to players when they spawn as this construct
|
||||
var/playstyle_string = "You are a generic construct. Your job is to not exist, and you should probably adminhelp this."
|
||||
/// The construct's master
|
||||
var/master = null
|
||||
/// Whether this construct is currently seeking nar nar
|
||||
var/seeking = FALSE
|
||||
/// Whether this construct can repair other constructs or cult buildings. Gets the healing_touch component if so.
|
||||
var/can_repair = FALSE
|
||||
/// Whether this construct can repair itself. Works independently of can_repair.
|
||||
var/can_repair_self = FALSE
|
||||
/// Theme controls color. THEME_CULT is red THEME_WIZARD is purple and THEME_HOLY is blue
|
||||
var/theme = THEME_CULT
|
||||
/// Can this construct destroy walls?
|
||||
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),
|
||||
)
|
||||
|
||||
/mob/living/basic/construct/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/simple_flying)
|
||||
var/list/remains = string_list(remains_by_theme[theme])
|
||||
if(length(remains))
|
||||
AddElement(/datum/element/death_drops, remains)
|
||||
if(smashes_walls)
|
||||
AddElement(/datum/element/wall_tearer, allow_reinforced = FALSE)
|
||||
if(can_repair)
|
||||
AddComponent(\
|
||||
/datum/component/healing_touch,\
|
||||
heal_brute = 5,\
|
||||
heal_burn = 0,\
|
||||
heal_time = 0,\
|
||||
valid_targets_typecache = typecacheof(list(/mob/living/basic/construct, /mob/living/basic/shade)),\
|
||||
valid_biotypes = MOB_MINERAL | MOB_SPIRIT,\
|
||||
self_targetting = can_repair_self ? HEALING_TOUCH_ANYONE : HEALING_TOUCH_NOT_SELF,\
|
||||
action_text = "%SOURCE% begins repairing %TARGET%'s dents.",\
|
||||
complete_text = "%TARGET%'s dents are repaired.",\
|
||||
show_health = TRUE,\
|
||||
heal_color = COLOR_CULT_RED,\
|
||||
)
|
||||
var/static/list/structure_types = typecacheof(list(/obj/structure/destructible/cult))
|
||||
AddElement(\
|
||||
/datum/element/structure_repair,\
|
||||
structure_types_typecache = structure_types,\
|
||||
)
|
||||
add_traits(list(TRAIT_HEALS_FROM_CULT_PYLONS, TRAIT_SPACEWALK), INNATE_TRAIT)
|
||||
grant_actions_by_list(construct_spells)
|
||||
|
||||
var/spell_count = 1
|
||||
for(var/datum/action/spell as anything in actions)
|
||||
if(!(spell.type in construct_spells))
|
||||
continue
|
||||
|
||||
var/pos = 2 + spell_count * 31
|
||||
if(construct_spells.len >= 4)
|
||||
pos -= 31 * (construct_spells.len - 4)
|
||||
spell.default_button_position = "6:[pos],4:-2" // Set the default position to this random position
|
||||
spell_count++
|
||||
update_action_buttons()
|
||||
|
||||
if(icon_state)
|
||||
add_overlay("glow_[icon_state]_[theme]")
|
||||
|
||||
/mob/living/basic/construct/Login()
|
||||
. = ..()
|
||||
if(!. || !client)
|
||||
return FALSE
|
||||
to_chat(src, span_bold(playstyle_string))
|
||||
|
||||
/mob/living/basic/construct/examine(mob/user)
|
||||
var/text_span
|
||||
switch(theme)
|
||||
if(THEME_CULT)
|
||||
text_span = "cult"
|
||||
if(THEME_WIZARD)
|
||||
text_span = "purple"
|
||||
if(THEME_HOLY)
|
||||
text_span = "blue"
|
||||
. = list("<span class='[text_span]'>This is [icon2html(src, user)] \a <b>[src]</b>!\n[desc]")
|
||||
if(health < maxHealth)
|
||||
if(health >= maxHealth/2)
|
||||
. += span_warning("[p_They()] look[p_s()] slightly dented.")
|
||||
else
|
||||
. += span_warning(span_bold("[p_They()] look[p_s()] severely dented!"))
|
||||
. += "</span>"
|
||||
return .
|
||||
|
||||
/mob/living/basic/construct/narsie_act()
|
||||
return
|
||||
|
||||
/mob/living/basic/construct/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
|
||||
return FALSE
|
||||
|
||||
/// Construct ectoplasm. Largely a placeholder, since the death drop element needs a unique list.
|
||||
/obj/item/ectoplasm/construct
|
||||
name = "blood-red ectoplasm"
|
||||
desc = "Has a pungent metallic smell."
|
||||
@@ -0,0 +1,82 @@
|
||||
/mob/living/basic/construct/artificer
|
||||
name = "Artificer"
|
||||
real_name = "Artificer"
|
||||
desc = "A bulbous construct dedicated to building and maintaining the Cult of Nar'Sie's armies."
|
||||
icon_state = "artificer"
|
||||
icon_living = "artificer"
|
||||
maxHealth = 50
|
||||
health = 50
|
||||
response_harm_continuous = "viciously beats"
|
||||
response_harm_simple = "viciously beat"
|
||||
obj_damage = 60
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 5
|
||||
attack_verb_continuous = "rams"
|
||||
attack_verb_simple = "ram"
|
||||
attack_sound = 'sound/weapons/punch2.ogg'
|
||||
construct_spells = list(
|
||||
/datum/action/cooldown/spell/aoe/magic_missile/lesser,
|
||||
/datum/action/cooldown/spell/conjure/construct/lesser,
|
||||
/datum/action/cooldown/spell/conjure/cult_floor,
|
||||
/datum/action/cooldown/spell/conjure/cult_wall,
|
||||
/datum/action/cooldown/spell/conjure/soulstone,
|
||||
/datum/action/innate/cult/create_rune/revive,
|
||||
)
|
||||
playstyle_string = "<b>You are an Artificer. You are incredibly weak and fragile, \
|
||||
but you are able to construct fortifications, use magic missile, and repair allied constructs, shades, \
|
||||
and yourself (by clicking on them). Additionally, <i>and most important of all,</i> you can create new constructs \
|
||||
by producing soulstones to capture souls, and shells to place those soulstones into.</b>"
|
||||
|
||||
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)
|
||||
|
||||
/// Hostile NPC version. Heals nearby constructs and cult structures, avoids targets that aren't extremely hurt.
|
||||
/mob/living/basic/construct/artificer/hostile
|
||||
ai_controller = /datum/ai_controller/basic_controller/artificer
|
||||
smashes_walls = FALSE
|
||||
melee_attack_cooldown = 2 SECONDS
|
||||
|
||||
// Alternate artificer themes
|
||||
/mob/living/basic/construct/artificer/angelic
|
||||
desc = "A bulbous construct dedicated to building and maintaining holy armies."
|
||||
theme = THEME_HOLY
|
||||
construct_spells = list(
|
||||
/datum/action/cooldown/spell/conjure/soulstone/purified,
|
||||
/datum/action/cooldown/spell/conjure/construct/lesser,
|
||||
/datum/action/cooldown/spell/aoe/magic_missile/lesser,
|
||||
/datum/action/innate/cult/create_rune/revive,
|
||||
)
|
||||
|
||||
/mob/living/basic/construct/artificer/angelic/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_ANGELIC, INNATE_TRAIT)
|
||||
|
||||
/mob/living/basic/construct/artificer/mystic
|
||||
theme = THEME_WIZARD
|
||||
construct_spells = list(
|
||||
/datum/action/cooldown/spell/conjure/cult_floor,
|
||||
/datum/action/cooldown/spell/conjure/cult_wall,
|
||||
/datum/action/cooldown/spell/conjure/soulstone/mystic,
|
||||
/datum/action/cooldown/spell/conjure/construct/lesser,
|
||||
/datum/action/cooldown/spell/aoe/magic_missile/lesser,
|
||||
/datum/action/innate/cult/create_rune/revive,
|
||||
)
|
||||
|
||||
/mob/living/basic/construct/artificer/noncult
|
||||
construct_spells = list(
|
||||
/datum/action/cooldown/spell/conjure/cult_floor,
|
||||
/datum/action/cooldown/spell/conjure/cult_wall,
|
||||
/datum/action/cooldown/spell/conjure/soulstone/noncult,
|
||||
/datum/action/cooldown/spell/conjure/construct/lesser,
|
||||
/datum/action/cooldown/spell/aoe/magic_missile/lesser,
|
||||
/datum/action/innate/cult/create_rune/revive,
|
||||
)
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Artificers
|
||||
*
|
||||
* Artificers will seek out and heal the most wounded construct or shade they can see.
|
||||
* If there is no one to heal, they will run away from any non-allied mobs.
|
||||
*/
|
||||
/datum/ai_controller/basic_controller/artificer
|
||||
blackboard = list(
|
||||
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/same_faction/construct,
|
||||
BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic,
|
||||
BB_TARGET_WOUNDED_ONLY = TRUE,
|
||||
)
|
||||
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/simple_find_wounded_target,
|
||||
/datum/ai_planning_subtree/basic_melee_attack_subtree,
|
||||
/datum/ai_planning_subtree/target_retaliate/to_flee,
|
||||
/datum/ai_planning_subtree/flee_target/from_flee_key,
|
||||
)
|
||||
|
||||
/**
|
||||
* Juggernauts
|
||||
*
|
||||
* Juggernauts slowly walk toward non-allied mobs and pummel them to death.
|
||||
*/
|
||||
/datum/ai_controller/basic_controller/juggernaut
|
||||
blackboard = list(
|
||||
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic,
|
||||
BB_TARGET_MINIMUM_STAT = HARD_CRIT,
|
||||
)
|
||||
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/simple_find_target,
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path,
|
||||
/datum/ai_planning_subtree/basic_melee_attack_subtree,
|
||||
)
|
||||
|
||||
/**
|
||||
* Proteons
|
||||
*
|
||||
* Proteons perform cowardly hit-and-run attacks, fleeing melee when struck but returning to fight again.
|
||||
*/
|
||||
/datum/ai_controller/basic_controller/proteon
|
||||
blackboard = list(
|
||||
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic,
|
||||
BB_TARGET_MINIMUM_STAT = HARD_CRIT,
|
||||
BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic,
|
||||
)
|
||||
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/target_retaliate/to_flee,
|
||||
/datum/ai_planning_subtree/flee_target/from_flee_key,
|
||||
/datum/ai_planning_subtree/simple_find_target,
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path,
|
||||
/datum/ai_planning_subtree/basic_melee_attack_subtree,
|
||||
)
|
||||
|
||||
/**
|
||||
* Wraiths
|
||||
*
|
||||
* Wraiths seek out the most injured non-allied mob to beat to death.
|
||||
*/
|
||||
/datum/ai_controller/basic_controller/wraith
|
||||
blackboard = list(
|
||||
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic,
|
||||
BB_TARGET_MINIMUM_STAT = HARD_CRIT,
|
||||
)
|
||||
|
||||
ai_movement = /datum/ai_movement/basic_avoidance
|
||||
idle_behavior = /datum/idle_behavior/idle_random_walk
|
||||
planning_subtrees = list(
|
||||
/datum/ai_planning_subtree/simple_find_wounded_target,
|
||||
/datum/ai_planning_subtree/attack_obstacle_in_path,
|
||||
/datum/ai_planning_subtree/basic_melee_attack_subtree,
|
||||
)
|
||||
|
||||
/// Targetting datum that will only allow mobs that constructs can heal.
|
||||
/datum/targetting_datum/basic/same_faction/construct
|
||||
target_wounded_key = BB_TARGET_WOUNDED_ONLY
|
||||
|
||||
/datum/targetting_datum/basic/same_faction/construct/can_attack(mob/living/living_mob, atom/the_target, vision_range, check_faction = TRUE)
|
||||
if(isconstruct(the_target) || istype(the_target, /mob/living/basic/shade))
|
||||
return ..()
|
||||
return FALSE
|
||||
@@ -0,0 +1,128 @@
|
||||
/mob/living/basic/construct/harvester
|
||||
name = "Harvester"
|
||||
real_name = "Harvester"
|
||||
desc = "A long, thin construct built to herald Nar'Sie's rise. It'll be all over soon."
|
||||
icon_state = "harvester"
|
||||
icon_living = "harvester"
|
||||
maxHealth = 40
|
||||
health = 40
|
||||
sight = SEE_MOBS
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 20
|
||||
attack_verb_continuous = "butchers"
|
||||
attack_verb_simple = "butcher"
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_vis_effect = ATTACK_EFFECT_SLASH
|
||||
construct_spells = list(
|
||||
/datum/action/cooldown/spell/aoe/area_conversion,
|
||||
/datum/action/cooldown/spell/forcewall/cult,
|
||||
)
|
||||
playstyle_string = "<B>You are a Harvester. You are incapable of directly killing humans, \
|
||||
but your attacks will remove their limbs: Bring those who still cling to this world \
|
||||
of illusion back to the Geometer so they may know Truth. Your form and any you are \
|
||||
pulling can pass through runed walls effortlessly.</B>"
|
||||
can_repair = TRUE
|
||||
slowed_by_drag = FALSE
|
||||
|
||||
/mob/living/basic/construct/harvester/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(\
|
||||
/datum/element/amputating_limbs,\
|
||||
surgery_time = 0,\
|
||||
surgery_verb = "slicing",\
|
||||
minimum_stat = CONSCIOUS,\
|
||||
)
|
||||
AddElement(/datum/element/wall_walker, /turf/closed/wall/mineral/cult)
|
||||
var/datum/action/innate/seek_prey/seek = new(src)
|
||||
seek.Grant(src)
|
||||
seek.Activate()
|
||||
|
||||
/// If the attack is a limbless carbon, abort the attack, paralyze them, and get a special message from Nar'Sie.
|
||||
/mob/living/basic/construct/harvester/resolve_unarmed_attack(atom/attack_target, list/modifiers)
|
||||
if(!iscarbon(attack_target))
|
||||
return ..()
|
||||
var/mob/living/carbon/carbon_target = attack_target
|
||||
|
||||
for(var/obj/item/bodypart/limb as anything in carbon_target.bodyparts)
|
||||
if(limb.body_part == HEAD || limb.body_part == CHEST)
|
||||
continue
|
||||
return ..() //if any arms or legs exist, attack
|
||||
|
||||
carbon_target.Paralyze(6 SECONDS)
|
||||
visible_message(span_danger("[src] knocks [carbon_target] down!"))
|
||||
to_chat(src, span_cultlarge("\"Bring [carbon_target.p_them()] to me.\""))
|
||||
|
||||
/datum/action/innate/seek_master
|
||||
name = "Seek your Master"
|
||||
desc = "You and your master share a soul-link that informs you of their location"
|
||||
background_icon_state = "bg_demon"
|
||||
overlay_icon_state = "bg_demon_border"
|
||||
|
||||
buttontooltipstyle = "cult"
|
||||
button_icon = "icons/mob/actions/actions_cult.dmi"
|
||||
button_icon_state = "cult_mark"
|
||||
/// Where is nar nar? Are we even looking?
|
||||
var/tracking = FALSE
|
||||
/// The construct we're attached to
|
||||
var/mob/living/basic/construct/the_construct
|
||||
|
||||
/datum/action/innate/seek_master/Grant(mob/living/player)
|
||||
the_construct = player
|
||||
..()
|
||||
|
||||
/datum/action/innate/seek_master/Activate()
|
||||
var/datum/antagonist/cult/cult_status = owner.mind.has_antag_datum(/datum/antagonist/cult)
|
||||
if(!cult_status)
|
||||
return
|
||||
var/datum/objective/eldergod/summon_objective = locate() in cult_status.cult_team.objectives
|
||||
|
||||
if(summon_objective.check_completion())
|
||||
the_construct.master = cult_status.cult_team.blood_target
|
||||
|
||||
if(!the_construct.master)
|
||||
to_chat(the_construct, span_cultitalic("You have no master to seek!"))
|
||||
the_construct.seeking = FALSE
|
||||
return
|
||||
if(tracking)
|
||||
tracking = FALSE
|
||||
the_construct.seeking = FALSE
|
||||
to_chat(the_construct, span_cultitalic("You are no longer tracking your master."))
|
||||
return
|
||||
else
|
||||
tracking = TRUE
|
||||
the_construct.seeking = TRUE
|
||||
to_chat(the_construct, span_cultitalic("You are now tracking your master."))
|
||||
|
||||
|
||||
/datum/action/innate/seek_prey
|
||||
name = "Seek the Harvest"
|
||||
desc = "None can hide from Nar'Sie, activate to track a survivor attempting to flee the red harvest!"
|
||||
button_icon = 'icons/mob/actions/actions_cult.dmi'
|
||||
background_icon_state = "bg_demon"
|
||||
overlay_icon_state = "bg_demon_border"
|
||||
|
||||
buttontooltipstyle = "cult"
|
||||
button_icon_state = "cult_mark"
|
||||
|
||||
/datum/action/innate/seek_prey/Activate()
|
||||
if(GLOB.cult_narsie == null)
|
||||
return
|
||||
var/mob/living/basic/construct/harvester/the_construct = owner
|
||||
|
||||
if(the_construct.seeking)
|
||||
desc = "None can hide from Nar'Sie, activate to track a survivor attempting to flee the red harvest!"
|
||||
button_icon_state = "cult_mark"
|
||||
the_construct.seeking = FALSE
|
||||
to_chat(the_construct, span_cultitalic("You are now tracking Nar'Sie, return to reap the harvest!"))
|
||||
return
|
||||
|
||||
if(!LAZYLEN(GLOB.cult_narsie.souls_needed))
|
||||
to_chat(the_construct, span_cultitalic("Nar'Sie has completed her harvest!"))
|
||||
return
|
||||
|
||||
the_construct.master = pick(GLOB.cult_narsie.souls_needed)
|
||||
var/mob/living/real_target = the_construct.master //We can typecast this way because Narsie only allows /mob/living into the souls list
|
||||
to_chat(the_construct, span_cultitalic("You are now tracking your prey, [real_target.real_name] - harvest [real_target.p_them()]!"))
|
||||
desc = "Activate to track Nar'Sie!"
|
||||
button_icon_state = "sintouch"
|
||||
the_construct.seeking = TRUE
|
||||
@@ -0,0 +1,61 @@
|
||||
/mob/living/basic/construct/juggernaut
|
||||
name = "Juggernaut"
|
||||
real_name = "Juggernaut"
|
||||
desc = "A massive, armored construct built to spearhead attacks and soak up enemy fire."
|
||||
icon_state = "juggernaut"
|
||||
icon_living = "juggernaut"
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
response_harm_continuous = "harmlessly punches"
|
||||
response_harm_simple = "harmlessly punch"
|
||||
obj_damage = 90
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 25
|
||||
attack_verb_continuous = "smashes their armored gauntlet into"
|
||||
attack_verb_simple = "smash your armored gauntlet into"
|
||||
speed = 2.5
|
||||
attack_sound = 'sound/weapons/punch3.ogg'
|
||||
status_flags = NONE
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
force_threshold = 10
|
||||
construct_spells = list(
|
||||
/datum/action/cooldown/spell/basic_projectile/juggernaut,
|
||||
/datum/action/cooldown/spell/forcewall/cult,
|
||||
/datum/action/innate/cult/create_rune/wall,
|
||||
)
|
||||
playstyle_string = span_bold("You are a Juggernaut. Though slow, your shell can withstand heavy punishment, create shield walls, rip apart enemies and walls alike, and even deflect energy weapons.")
|
||||
|
||||
smashes_walls = TRUE
|
||||
|
||||
/// Hostile NPC version. Pretty dumb, just attacks whoever is near.
|
||||
/mob/living/basic/construct/juggernaut/hostile
|
||||
ai_controller = /datum/ai_controller/basic_controller/juggernaut
|
||||
smashes_walls = FALSE
|
||||
melee_attack_cooldown = 2 SECONDS
|
||||
|
||||
/mob/living/basic/construct/juggernaut/bullet_act(obj/projectile/bullet)
|
||||
if(!istype(bullet, /obj/projectile/energy) && !istype(bullet, /obj/projectile/beam))
|
||||
return ..()
|
||||
if(!prob(40 - round(bullet.damage / 3))) // reflect chance
|
||||
return ..()
|
||||
|
||||
apply_damage(bullet.damage * 0.5, bullet.damage_type)
|
||||
visible_message(
|
||||
span_danger("The [bullet.name] is reflected by [src]'s armored shell!"),
|
||||
span_userdanger("The [bullet.name] is reflected by your armored shell!"),
|
||||
)
|
||||
|
||||
bullet.reflect(src)
|
||||
|
||||
return BULLET_ACT_FORCE_PIERCE // complete projectile permutation
|
||||
|
||||
// Alternate juggernaut themes
|
||||
/mob/living/basic/construct/juggernaut/angelic
|
||||
theme = THEME_HOLY
|
||||
|
||||
/mob/living/basic/construct/juggernaut/angelic/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_ANGELIC, INNATE_TRAIT)
|
||||
|
||||
/mob/living/basic/construct/juggernaut/mystic
|
||||
theme = THEME_WIZARD
|
||||
@@ -0,0 +1,39 @@
|
||||
/// Proteon - a very weak construct that only appears in NPC form in various ruins.
|
||||
/mob/living/basic/construct/proteon
|
||||
name = "Proteon"
|
||||
real_name = "Proteon"
|
||||
desc = "A weaker construct meant to scour ruins for objects of Nar'Sie's affection. Those barbed claws are no joke."
|
||||
icon_state = "proteon"
|
||||
icon_living = "proteon"
|
||||
maxHealth = 35
|
||||
health = 35
|
||||
melee_damage_lower = 8
|
||||
melee_damage_upper = 10
|
||||
attack_verb_continuous = "pinches"
|
||||
attack_verb_simple = "pinch"
|
||||
smashes_walls = TRUE
|
||||
attack_sound = 'sound/weapons/punch2.ogg'
|
||||
playstyle_string = span_bold("You are a Proteon. Your abilities in combat are outmatched by most combat constructs, but you are still fast and nimble. Run metal and supplies, and cooperate with your fellow cultists.")
|
||||
|
||||
/// Hostile NPC version
|
||||
/mob/living/basic/construct/proteon/hostile
|
||||
ai_controller = /datum/ai_controller/basic_controller/proteon
|
||||
smashes_walls = FALSE
|
||||
melee_attack_cooldown = 1.5 SECONDS
|
||||
|
||||
/mob/living/basic/construct/proteon/hostile/Initialize(mapload)
|
||||
. = ..()
|
||||
var/datum/callback/retaliate_callback = CALLBACK(src, PROC_REF(ai_retaliate_behaviour))
|
||||
AddComponent(/datum/component/ai_retaliate_advanced, retaliate_callback)
|
||||
|
||||
/// Set a timer to clear our retaliate list
|
||||
/mob/living/basic/construct/proteon/hostile/proc/ai_retaliate_behaviour(mob/living/attacker)
|
||||
if (!istype(attacker))
|
||||
return
|
||||
var/random_timer = rand(2 SECONDS, 4 SECONDS) //for unpredictability
|
||||
addtimer(CALLBACK(src, PROC_REF(clear_retaliate_list)), random_timer)
|
||||
|
||||
/mob/living/basic/construct/proteon/hostile/proc/clear_retaliate_list()
|
||||
if(!ai_controller.blackboard_key_exists(BB_BASIC_MOB_RETALIATE_LIST))
|
||||
return
|
||||
ai_controller.clear_blackboard_key(BB_BASIC_MOB_RETALIATE_LIST)
|
||||
@@ -0,0 +1,50 @@
|
||||
/mob/living/basic/construct/wraith
|
||||
name = "Wraith"
|
||||
real_name = "Wraith"
|
||||
desc = "A wicked, clawed shell constructed to assassinate enemies and sow chaos behind enemy lines."
|
||||
icon_state = "wraith"
|
||||
icon_living = "wraith"
|
||||
maxHealth = 65
|
||||
health = 65
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 20
|
||||
attack_verb_continuous = "slashes"
|
||||
attack_verb_simple = "slash"
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_vis_effect = ATTACK_EFFECT_SLASH
|
||||
construct_spells = list(
|
||||
/datum/action/cooldown/spell/jaunt/ethereal_jaunt/shift,
|
||||
/datum/action/innate/cult/create_rune/tele,
|
||||
)
|
||||
playstyle_string = span_bold("You are a Wraith. Though relatively fragile, you are fast, deadly, and can phase through walls. Your attacks will lower the cooldown on phasing, moreso for fatal blows.")
|
||||
|
||||
/mob/living/basic/construct/wraith/Initialize(mapload)
|
||||
. = ..()
|
||||
var/datum/action/cooldown/spell/jaunt/ethereal_jaunt/shift/jaunt = locate() in actions
|
||||
if(isnull(jaunt))
|
||||
return .
|
||||
AddComponent(/datum/component/recharging_attacks, recharged_action = jaunt)
|
||||
|
||||
/// Hostile NPC version. Attempts to kill the lowest-health mob it can see.
|
||||
/mob/living/basic/construct/wraith/hostile
|
||||
ai_controller = /datum/ai_controller/basic_controller/wraith
|
||||
melee_attack_cooldown = 1.5 SECONDS
|
||||
|
||||
// Alternate wraith themes
|
||||
/mob/living/basic/construct/wraith/angelic
|
||||
theme = THEME_HOLY
|
||||
construct_spells = list(
|
||||
/datum/action/cooldown/spell/jaunt/ethereal_jaunt/shift/angelic,
|
||||
/datum/action/innate/cult/create_rune/tele,
|
||||
)
|
||||
|
||||
/mob/living/basic/construct/wraith/angelic/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_ANGELIC, INNATE_TRAIT)
|
||||
|
||||
/mob/living/basic/construct/wraith/mystic
|
||||
theme = THEME_WIZARD
|
||||
construct_spells = list(
|
||||
/datum/action/cooldown/spell/jaunt/ethereal_jaunt/shift/mystic,
|
||||
/datum/action/innate/cult/create_rune/tele,
|
||||
)
|
||||
Reference in New Issue
Block a user