mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-20 19:44:09 +01:00
adds the proteon orb. (heretic requirement) (#27705)
* adds the proteon orb. * oops * Update code/datums/components/ghost_direct_control.dm Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Signed-off-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Charlie Nolan <funnyman3595@gmail.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> * revert that * Update code/game/objects/structures/monster_spawner.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> * lewcs stuff * Update code/game/objects/structures/monster_spawner.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> * Update monster_spawner.dm --------- Signed-off-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Co-authored-by: Charlie Nolan <funnyman3595@gmail.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
This commit is contained in:
@@ -43,7 +43,7 @@ SUBSYSTEM_DEF(ghost_spawns)
|
||||
* * source - The atom, atom prototype, icon or mutable appearance to display as an icon in the alert
|
||||
* * role_cleanname - The name override to display to clients
|
||||
*/
|
||||
/datum/controller/subsystem/ghost_spawns/proc/poll_candidates(question = "Would you like to play a special role?", role, antag_age_check = FALSE, poll_time = 30 SECONDS, ignore_respawnability = FALSE, min_hours = 0, flash_window = TRUE, check_antaghud = TRUE, source, role_cleanname, reason)
|
||||
/datum/controller/subsystem/ghost_spawns/proc/poll_candidates(question = "Would you like to play a special role?", role, antag_age_check = FALSE, poll_time = 30 SECONDS, ignore_respawnability = FALSE, min_hours = 0, flash_window = TRUE, check_antaghud = TRUE, source, role_cleanname, reason, dont_play_notice_sound = FALSE)
|
||||
log_debug("Polling candidates [role ? "for [role_cleanname || get_roletext(role)]" : "\"[question]\""] for [poll_time / 10] seconds")
|
||||
|
||||
// Start firing
|
||||
@@ -63,8 +63,8 @@ SUBSYSTEM_DEF(ghost_spawns)
|
||||
for(var/mob/M in (GLOB.player_list))
|
||||
if(!is_eligible(M, role, antag_age_check, role, min_hours, check_antaghud))
|
||||
continue
|
||||
|
||||
SEND_SOUND(M, notice_sound)
|
||||
if(!dont_play_notice_sound)
|
||||
SEND_SOUND(M, notice_sound)
|
||||
if(flash_window)
|
||||
window_flash(M.client)
|
||||
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/**
|
||||
* Component which lets ghosts click on a mob to take control of it
|
||||
*/
|
||||
/datum/component/ghost_direct_control
|
||||
/// Message to display upon successful possession
|
||||
var/assumed_control_message
|
||||
/// Type of ban you can get to prevent you from accepting this role
|
||||
var/ban_type
|
||||
/// Any extra checks which need to run before we take over
|
||||
var/datum/callback/extra_control_checks
|
||||
/// Callback run after someone successfully takes over the body
|
||||
var/datum/callback/after_assumed_control
|
||||
/// If we're currently awaiting the results of a ghost poll
|
||||
var/awaiting_ghosts = FALSE
|
||||
/// Is this an antagonist spawner, so we check ROLE_SYNDICATE
|
||||
var/is_antag_spawner
|
||||
|
||||
/datum/component/ghost_direct_control/Initialize(
|
||||
ban_type = ROLE_SENTIENT,
|
||||
role_name = null,
|
||||
poll_question = null,
|
||||
poll_candidates = TRUE,
|
||||
poll_length = 10 SECONDS,
|
||||
assumed_control_message = null,
|
||||
datum/callback/extra_control_checks,
|
||||
datum/callback/after_assumed_control,
|
||||
is_antag_spawner = TRUE,
|
||||
)
|
||||
. = ..()
|
||||
if(!isliving(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.ban_type = ban_type
|
||||
src.assumed_control_message = assumed_control_message || "You are [parent]!"
|
||||
src.extra_control_checks = extra_control_checks
|
||||
src.after_assumed_control = after_assumed_control
|
||||
src.is_antag_spawner = is_antag_spawner
|
||||
|
||||
|
||||
if(poll_candidates)
|
||||
INVOKE_ASYNC(src, PROC_REF(request_ghost_control), poll_question, role_name || "[parent]", poll_length)
|
||||
|
||||
/datum/component/ghost_direct_control/RegisterWithParent()
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_ATOM_ATTACK_GHOST, PROC_REF(on_ghost_clicked))
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, PROC_REF(on_examined))
|
||||
RegisterSignal(parent, COMSIG_MOB_LOGIN, PROC_REF(on_login))
|
||||
|
||||
/datum/component/ghost_direct_control/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_ATOM_ATTACK_GHOST, COMSIG_PARENT_EXAMINE, COMSIG_MOB_LOGIN))
|
||||
return ..()
|
||||
|
||||
/datum/component/ghost_direct_control/Destroy(force)
|
||||
extra_control_checks = null
|
||||
after_assumed_control = null
|
||||
return ..()
|
||||
|
||||
/// Inform ghosts that they can possess this
|
||||
/datum/component/ghost_direct_control/proc/on_examined(datum/source, mob/user, list/examine_text)
|
||||
SIGNAL_HANDLER //COMSIG_PARENT_EXAMINE
|
||||
if(!isobserver(user))
|
||||
return
|
||||
var/mob/living/our_mob = parent
|
||||
if(our_mob.stat == DEAD || our_mob.key || awaiting_ghosts)
|
||||
return
|
||||
examine_text += "<span class='boldnotice'>You could take control of this mob by clicking on it.</span>"
|
||||
|
||||
/// Send out a request for a brain
|
||||
/datum/component/ghost_direct_control/proc/request_ghost_control(poll_question, role_name, poll_length)
|
||||
awaiting_ghosts = TRUE
|
||||
var/list/candidates = SSghost_spawns.poll_candidates(
|
||||
question = poll_question,
|
||||
role = ban_type,
|
||||
poll_time = poll_length,
|
||||
source = parent,
|
||||
role_cleanname = role_name,
|
||||
flash_window = FALSE,
|
||||
dont_play_notice_sound = TRUE
|
||||
)
|
||||
awaiting_ghosts = FALSE
|
||||
var/mob/chosen_one = null
|
||||
if(length(candidates))
|
||||
chosen_one = pick(candidates)
|
||||
|
||||
if(isnull(chosen_one))
|
||||
return
|
||||
assume_direct_control(chosen_one)
|
||||
|
||||
/// A ghost clicked on us, they want to get in this body
|
||||
/datum/component/ghost_direct_control/proc/on_ghost_clicked(mob/our_mob, mob/dead/observer/hopeful_ghost)
|
||||
SIGNAL_HANDLER // COMSIG_ATOM_ATTACK_GHOST
|
||||
if(our_mob.key)
|
||||
qdel(src)
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
if(!hopeful_ghost.client)
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
if(awaiting_ghosts)
|
||||
to_chat(hopeful_ghost, "<span class='warning'>Ghost candidate selection currently in progress!</span>")
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
if(!SSticker.HasRoundStarted())
|
||||
to_chat(hopeful_ghost, "<span class='warning'>You cannot assume control of this until after the round has started!</span>")
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
INVOKE_ASYNC(src, PROC_REF(attempt_possession), our_mob, hopeful_ghost)
|
||||
return COMPONENT_CANCEL_ATTACK_CHAIN
|
||||
|
||||
/// We got far enough to establish that this mob is a valid target, let's try to posssess it
|
||||
/datum/component/ghost_direct_control/proc/attempt_possession(mob/our_mob, mob/dead/observer/hopeful_ghost)
|
||||
var/ghost_asked = tgui_alert(usr, "Become [our_mob]?", "Are you sure?", list("Yes", "No"))
|
||||
if(ghost_asked != "Yes" || QDELETED(our_mob))
|
||||
return
|
||||
assume_direct_control(hopeful_ghost)
|
||||
|
||||
/// Grant possession of our mob, component is now no longer required
|
||||
/datum/component/ghost_direct_control/proc/assume_direct_control(mob/harbinger)
|
||||
if(QDELETED(src))
|
||||
to_chat(harbinger, "<span class='warning'>Offer to possess creature has expired!</span>")
|
||||
return
|
||||
if(jobban_isbanned(harbinger, ban_type) || jobban_isbanned(harbinger, ROLE_SENTIENT) || (is_antag_spawner && jobban_isbanned(harbinger, ROLE_SYNDICATE)))
|
||||
to_chat(harbinger, "<span class='warning'>You are banned from playing as this role!</span>")
|
||||
return
|
||||
var/mob/living/new_body = parent
|
||||
if(new_body.stat == DEAD)
|
||||
to_chat(harbinger, "<span class='warning'>This body has passed away, it is of no use!</span>")
|
||||
return
|
||||
if(new_body.key)
|
||||
to_chat(harbinger, "<span class='warning'>[parent] has already become sapient!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
if(extra_control_checks && !extra_control_checks.Invoke(harbinger))
|
||||
return
|
||||
|
||||
// doesn't transfer mind because that transfers antag datum as well
|
||||
new_body.key = harbinger.key
|
||||
|
||||
// Already qdels due to below proc but just in case
|
||||
if(!QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
/// When someone assumes control, get rid of our component
|
||||
/datum/component/ghost_direct_control/proc/on_login(mob/harbinger)
|
||||
SIGNAL_HANDLER //COMSIG_MOB_LOGIN
|
||||
// This proc is called the very moment .key is set, so we need to force mind to initialize here if we want the invoke to affect the mind of the mob
|
||||
if(isnull(harbinger.mind))
|
||||
harbinger.mind_initialize()
|
||||
to_chat(harbinger, "<span class='boldnotice'>[assumed_control_message]</span>")
|
||||
after_assumed_control?.Invoke(harbinger)
|
||||
qdel(src)
|
||||
@@ -51,6 +51,7 @@
|
||||
L.nest = src
|
||||
L.faction = src.faction
|
||||
P.visible_message("<span class='danger'>[L] [spawn_text] [P].</span>")
|
||||
P.on_mob_spawn(L)
|
||||
|
||||
/datum/component/spawner/proc/rally_spawned_mobs(parent, mob/living/target)
|
||||
SIGNAL_HANDLER // COMSIG_SPAWNER_SET_TARGET
|
||||
|
||||
@@ -1438,3 +1438,7 @@ GLOBAL_LIST_EMPTY(blood_splatter_icons)
|
||||
*/
|
||||
/atom/proc/relaydrive(mob/living/user, direction)
|
||||
return !(SEND_SIGNAL(src, COMSIG_RIDDEN_DRIVER_MOVE, user, direction) & COMPONENT_DRIVER_BLOCK_MOVE)
|
||||
|
||||
/// Used with the spawner component to do something when a mob is spawned.
|
||||
/atom/proc/on_mob_spawn(mob/created_mob)
|
||||
return
|
||||
|
||||
@@ -42,6 +42,10 @@
|
||||
var/harvester_icon_state = "harvester"
|
||||
var/harvester_dead_state = "shade_dead"
|
||||
|
||||
//Proteon Construct
|
||||
var/proteon_name = "Proteon"
|
||||
var/proteon_icon_state = "proteon"
|
||||
var/proteon_dead_state = "shade_dead"
|
||||
//Shade Spirit
|
||||
var/shade_name = "Shade"
|
||||
var/shade_icon_state = "shade2"
|
||||
@@ -211,6 +215,8 @@
|
||||
return harvester_name
|
||||
if("wraith")
|
||||
return wraith_name
|
||||
if("proteon")
|
||||
return proteon_name
|
||||
if("shade")
|
||||
return shade_name
|
||||
|
||||
@@ -230,6 +236,8 @@
|
||||
return harvester_icon_state
|
||||
if("wraith")
|
||||
return wraith_icon_state
|
||||
if("proteon")
|
||||
return proteon_icon_state
|
||||
if("shade")
|
||||
return shade_icon_state
|
||||
if("forge")
|
||||
|
||||
@@ -829,3 +829,88 @@
|
||||
icon = 'icons/obj/biomass.dmi'
|
||||
icon_state = "rift"
|
||||
color = "red"
|
||||
|
||||
#define GATEWAY_TURF_SCAN_RANGE 40
|
||||
GLOBAL_LIST_EMPTY(proteon_portals)
|
||||
|
||||
/obj/item/proteon_orb
|
||||
name = "summoning orb"
|
||||
desc = "An eerie translucent orb that feels impossibly light. Legends say summoning orbs are created from corrupted scrying orbs. If you hold it close to your ears, you can hear the screams of the damned."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state ="scrying_orb"
|
||||
light_range = 3
|
||||
light_color = LIGHT_COLOR_RED
|
||||
new_attack_chain = TRUE
|
||||
/// A nice blood colour matrix
|
||||
var/list/blood_color_matrix = list(1.25,-0.1,-0.1,0, 0,0.15,0,0, 0,0,0.15,0, 0,0,0,1, 0,0,0,0)
|
||||
|
||||
|
||||
/obj/item/proteon_orb/Initialize(mapload)
|
||||
. = ..()
|
||||
color = blood_color_matrix
|
||||
|
||||
|
||||
/obj/item/proteon_orb/examine(mob/user)
|
||||
. = ..()
|
||||
if(!IS_CULTIST(user) && isliving(user))
|
||||
var/mob/living/living_user = user
|
||||
living_user.adjustBrainLoss(5)
|
||||
. += "<span class='danger'>It hurts just to look at it. Better keep away.</span>"
|
||||
else
|
||||
. += "<span class='cult'>It can be used to create a gateway to Nar'Sie's domain, which will summon weak, sentient constructs over time.</span>"
|
||||
|
||||
/obj/item/proteon_orb/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/list/portals_to_scan = GLOB.proteon_portals
|
||||
|
||||
if(!IS_CULTIST(user))
|
||||
to_chat(user, "<span class='cultlarge'>\"You want to enter my domain? Go ahead.\"</span>")
|
||||
portals_to_scan = null // narsie wants to have some fun and the veil wont stop her
|
||||
|
||||
for(var/obj/structure/spawner/sentient/proteon_spawner/P as anything in portals_to_scan)
|
||||
if(get_dist(P, src) <= 40)
|
||||
to_chat(user, "<span class='cult'><b>There's a gateway too close nearby. The veil is not yet weak enough to allow such close rips in its fabric.</b></span>")
|
||||
return
|
||||
to_chat(user, "<span class='cultitalic'><b>You focus on [src] and direct it into the ground. It rumbles...</b></span>")
|
||||
|
||||
var/turf/hole_spot = get_turf(user)
|
||||
if(!isfloorturf(hole_spot))
|
||||
to_chat(user, "<span class='notice'>This is not a suitable spot.</span>")
|
||||
return
|
||||
|
||||
INVOKE_ASYNC(hole_spot, TYPE_PROC_REF(/turf/simulated/floor, quake_gateway), user)
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
* Bespoke proc that happens when a proteon orb is activated, creating a gateway.
|
||||
* If activated by a non-cultist, they get an unusual game over.
|
||||
*/
|
||||
/turf/simulated/floor/proc/quake_gateway(mob/living/user)
|
||||
ChangeTurf(/turf/simulated/floor/engine/cult)
|
||||
Shake(4, 4, 5 SECONDS)
|
||||
var/fucked = FALSE
|
||||
if(!IS_CULTIST(user))
|
||||
fucked = TRUE
|
||||
user.notransform = TRUE
|
||||
user.add_atom_colour(LIGHT_COLOR_RED, TEMPORARY_COLOUR_PRIORITY)
|
||||
user.visible_message("<span class='cult'><b>Dark tendrils appear from the ground and root [user] in place!</b></span>")
|
||||
sleep(5 SECONDS) // can we still use these or. i mean its async
|
||||
new /obj/structure/spawner/sentient/proteon_spawner(src)
|
||||
visible_message("<span class='cult'><b>A mysterious hole appears out of nowhere!</b></span>")
|
||||
if(!fucked || QDELETED(user))
|
||||
return
|
||||
if(get_turf(user) != src) // they get away. for now
|
||||
user.notransform = FALSE
|
||||
user.visible_message("<span class='cult'><b>[user] is pulled into the portal through an infinitesmally minuscule hole, shredding [user.p_their()] body!</b></span>")
|
||||
add_attack_logs(user, user, "Killed themselfs via use of a proteon orb as a non cultist", ATKLOG_ALL)
|
||||
user.gib() // total destruction
|
||||
sleep(5 SECONDS)
|
||||
user.visible_message("<span class='cultitalic'>An unusually large construct appears through the portal!</span>")
|
||||
var/mob/living/simple_animal/hostile/construct/proteon/hostile/remnant = new(get_step_rand(src))
|
||||
remnant.name = "[user]" // no, they do not become it
|
||||
remnant.appearance_flags += PIXEL_SCALE
|
||||
remnant.transform *= 1.5
|
||||
|
||||
#undef GATEWAY_TURF_SCAN_RANGE
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
/obj/structure/spawner/syndicate
|
||||
name = "warp beacon"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
@@ -74,3 +75,87 @@
|
||||
name = "basilisk den"
|
||||
desc = "A den housing a nest of basilisks, bring a coat."
|
||||
mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk)
|
||||
|
||||
/obj/structure/spawner/sentient
|
||||
var/role_name = "A sentient mob"
|
||||
var/assumed_control_message = "You are a sentient mob from a badly coded spawner"
|
||||
|
||||
/obj/structure/spawner/sentient/Initialize(mapload)
|
||||
. = ..()
|
||||
notify_ghosts("\A [name] has been created in \the [get_area(src)]!", source = src, title = "Sentient Spawner Created", flashwindow = FALSE
|
||||
)
|
||||
|
||||
/obj/structure/spawner/sentient/on_mob_spawn(mob/created_mob)
|
||||
created_mob.AddComponent(\
|
||||
/datum/component/ghost_direct_control,\
|
||||
role_name = src.role_name,\
|
||||
assumed_control_message = src.assumed_control_message,\
|
||||
after_assumed_control = CALLBACK(src, PROC_REF(became_player_controlled)),\
|
||||
)
|
||||
|
||||
/obj/structure/spawner/sentient/proc/became_player_controlled(mob/proteon)
|
||||
return
|
||||
|
||||
/obj/structure/spawner/sentient/proteon_spawner
|
||||
name = "eldritch gateway"
|
||||
desc = "A dizzying structure that somehow links into Nar'Sie's own domain. The screams of the damned echo continously."
|
||||
icon = 'icons/obj/cult.dmi'
|
||||
icon_state = "hole"
|
||||
light_power = 2
|
||||
light_color = LIGHT_COLOR_RED
|
||||
max_integrity = 50
|
||||
density = FALSE
|
||||
max_mobs = 2
|
||||
spawn_time = 15 SECONDS
|
||||
mob_types = list(/mob/living/simple_animal/hostile/construct/proteon/hostile)
|
||||
spawn_text = "arises from"
|
||||
faction = list("cult")
|
||||
role_name = "A proteon cult construct"
|
||||
assumed_control_message = null
|
||||
/// The GPS inside the spawner, lets security find them, especially if someone is space basing them.
|
||||
var/obj/item/gps/internal/proteon/gps
|
||||
|
||||
/obj/structure/spawner/sentient/proteon_spawner/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.proteon_portals += src
|
||||
gps = new /obj/item/gps/internal/proteon(src)
|
||||
|
||||
/obj/structure/spawner/sentient/proteon_spawner/Destroy()
|
||||
GLOB.proteon_portals -= src
|
||||
QDEL_NULL(gps)
|
||||
return ..()
|
||||
|
||||
/obj/structure/spawner/sentient/proteon_spawner/examine_status(mob/user)
|
||||
if(IS_CULTIST(user) || !isliving(user))
|
||||
return "<span class='cult'>It's at <b>[round(obj_integrity * 100 / max_integrity)]%</b> stability.</span>"
|
||||
return ..()
|
||||
|
||||
/obj/structure/spawner/sentient/proteon_spawner/examine(mob/user)
|
||||
. = ..()
|
||||
if(!IS_CULTIST(user) && isliving(user))
|
||||
var/mob/living/living_user = user
|
||||
living_user.adjustBrainLoss(5)
|
||||
. += "<span class='userdanger'>The voices of the damned echo relentlessly in your mind, continously rebounding on the walls of your self the more you focus on [src]. Your head pounds, better keep away...</span>"
|
||||
else
|
||||
. += "<span class='cult'>The gateway will create one weak proteon construct every [spawn_time * 0.1] seconds, up to a total of [max_mobs], that may be controlled by the spirits of the dead.</span>"
|
||||
|
||||
/obj/structure/spawner/sentient/proteon_spawner/became_player_controlled(mob/living/simple_animal/hostile/construct/proteon/hostile/proteon)
|
||||
proteon.mind.add_antag_datum(/datum/antagonist/cultist)
|
||||
proteon.add_filter("awoken_proteon", 3, list("type" = "outline", "color" = LIGHT_COLOR_RED, "size" = 2))
|
||||
visible_message("<span class='cult'>[proteon] awakens, glowing an eerie red as it stirs from its stupor!</span>")
|
||||
addtimer(CALLBACK(src, PROC_REF(remove_wake_outline), proteon), 8 SECONDS)
|
||||
|
||||
/obj/structure/spawner/sentient/proteon_spawner/proc/remove_wake_outline(mob/proteon)
|
||||
proteon.remove_filter("awoken_proteon")
|
||||
proteon.add_filter("sentient_proteon", 3, list("type" = "outline", "color" = LIGHT_COLOR_RED, "size" = 2, "alpha" = 40))
|
||||
|
||||
/obj/structure/spawner/sentient/proteon_spawner/obj_destruction(damage_flag)
|
||||
playsound(src, 'sound/hallucinations/veryfar_noise.ogg', 75)
|
||||
visible_message("<span class='cult'><b>[src] completely falls apart, the screams of the damned reaching a feverous pitch before slowly fading away into nothing.</b></span>")
|
||||
return ..()
|
||||
|
||||
/obj/item/gps/internal/proteon
|
||||
local = FALSE // Let security find the cult bases in space with it.
|
||||
icon_state = null
|
||||
gpstag = "Eldritch Signal"
|
||||
desc = "You (can)'t just BSA a hole into hell!"
|
||||
|
||||
@@ -327,6 +327,31 @@
|
||||
AIStatus = AI_ON
|
||||
environment_smash = 1 //only token destruction, don't smash the cult wall NO STOP
|
||||
|
||||
/mob/living/simple_animal/hostile/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
|
||||
obj_damage = 20 // Bit better at breaking stuff than cult ghosts, but only *barely*
|
||||
retreat_distance = 4 // AI proteons will rapidly move in and out of combat to avoid conflict, but will still target and follow you.
|
||||
attacktext = "pinches"
|
||||
environment_smash = ENVIRONMENT_SMASH_STRUCTURES // No you can not break down all the walls of the station
|
||||
attack_sound = 'sound/weapons/punch2.ogg'
|
||||
playstyle_string = "<b>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.</b>"
|
||||
construct_type = "proteon"
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/proteon/Initialize(mapload)
|
||||
. = ..()
|
||||
add_overlay("glow_proteon_cult")
|
||||
|
||||
// This is the type you will run into, spawned by the proteon spawner
|
||||
/mob/living/simple_animal/hostile/construct/proteon/hostile
|
||||
AIStatus = AI_ON
|
||||
|
||||
/mob/living/simple_animal/hostile/construct/proc/make_holy()
|
||||
if(holy) // Already holy-fied
|
||||
|
||||
@@ -52,7 +52,9 @@
|
||||
RegisterSignal(src, COMSIG_MOB_LOGIN, TYPE_PROC_REF(/mob/living/simple_animal/hostile/poison/terror_spider/prince, give_spell))
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/prince/proc/give_spell()
|
||||
SIGNAL_HANDLER
|
||||
SIGNAL_HANDLER //COMSIG_MOB_LOGIN
|
||||
if(isnull(mind))
|
||||
mind_initialize()
|
||||
var/datum/spell/spell = new /datum/spell/princely_charge()
|
||||
mind.AddSpell(spell)
|
||||
UnregisterSignal(src, COMSIG_MOB_LOGIN)
|
||||
|
||||
@@ -475,7 +475,3 @@ GLOBAL_LIST_EMPTY(ts_infected_list)
|
||||
. = ..()
|
||||
if(pulling && !ismob(pulling) && pulling.density)
|
||||
. += 6 // Drastic move speed penalty for dragging anything that is not a mob or a non dense object
|
||||
|
||||
/mob/living/simple_animal/hostile/poison/terror_spider/Login()
|
||||
. = ..()
|
||||
SEND_SIGNAL(src, COMSIG_MOB_LOGIN)
|
||||
|
||||
@@ -81,3 +81,4 @@
|
||||
update_client_colour(0)
|
||||
update_morgue()
|
||||
client.init_verbs()
|
||||
SEND_SIGNAL(src, COMSIG_MOB_LOGIN)
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 137 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 45 KiB |
@@ -448,6 +448,7 @@
|
||||
#include "code\datums\components\emissive_blocker.dm"
|
||||
#include "code\datums\components\footstep.dm"
|
||||
#include "code\datums\components\fullauto.dm"
|
||||
#include "code\datums\components\ghost_direct_control.dm"
|
||||
#include "code\datums\components\label.dm"
|
||||
#include "code\datums\components\largeobjecttransparency.dm"
|
||||
#include "code\datums\components\material_container.dm"
|
||||
|
||||
Reference in New Issue
Block a user