Space Dragon Antag Datum Refactor Take 2 (#68988)

* Space Dragon Antag Datum Refactor Take 2

Space Dragon's antag datum and the mob has been separated, so it is now possible to have non-dragon space dragons, with customizable spawned mobs and factions.
This commit is contained in:
IndieanaJones
2022-08-21 22:08:09 -04:00
committed by GitHub
parent af74d229e8
commit ed4ffde5f4
5 changed files with 368 additions and 343 deletions
+2 -1
View File
@@ -97,7 +97,8 @@
if(!do_after(user, CARP_MIX_DNA_TIMER))
return
var/mob/living/simple_animal/hostile/space_dragon/new_dragon = user.change_mob_type(/mob/living/simple_animal/hostile/space_dragon, location = loc, delete_old_mob = TRUE)
new_dragon.permanant_empower()
new_dragon.add_filter("anger_glow", 3, list("type" = "outline", "color" = "#ff330030", "size" = 5))
new_dragon.add_movespeed_modifier(/datum/movespeed_modifier/dragon_rage)
priority_announce("A large organic energy flux has been recorded near of [station_name()], please stand-by.", "Lifesign Alert")
qdel(src)
@@ -0,0 +1,239 @@
/// The carp rift is currently charging.
#define CHARGE_ONGOING 0
/// The carp rift is currently charging and has output a final warning.
#define CHARGE_FINALWARNING 1
/// The carp rift is now fully charged.
#define CHARGE_COMPLETED 2
/datum/action/innate/summon_rift
name = "Summon Rift"
desc = "Summon a rift to bring forth a horde of space carp."
background_icon_state = "bg_default"
icon_icon = 'icons/mob/actions/actions_space_dragon.dmi'
button_icon_state = "carp_rift"
/datum/action/innate/summon_rift/Activate()
var/datum/antagonist/space_dragon/dragon = owner.mind?.has_antag_datum(/datum/antagonist/space_dragon)
if(!dragon)
return
var/area/rift_location = get_area(owner)
if(!(rift_location.area_flags & VALID_TERRITORY))
to_chat(owner, span_warning("You can't summon a rift here! Try summoning somewhere secure within the station!"))
return
for(var/obj/structure/carp_rift/rift as anything in dragon.rift_list)
var/area/used_location = get_area(rift)
if(used_location == rift_location)
to_chat(owner, span_warning("You've already summoned a rift in this area! You have to summon again somewhere else!"))
return
owner.balloon_alert(owner, "You begin to open a rift...")
if(!do_after(owner, 10 SECONDS, target = owner))
return
if(locate(/obj/structure/carp_rift) in owner.loc)
return
var/obj/structure/carp_rift/new_rift = new(get_turf(owner))
playsound(owner.loc, 'sound/vehicles/rocketlaunch.ogg', 100, TRUE)
dragon.riftTimer = -1
new_rift.dragon = dragon
dragon.rift_list += new_rift
to_chat(owner, span_boldwarning("The rift has been summoned. Prevent the crew from destroying it at all costs!"))
notify_ghosts("The Space Dragon has opened a rift!", source = new_rift, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Carp Rift Opened")
qdel(src)
/**
* # Carp Rift
*
* The portals Space Dragon summons to bring carp onto the station.
*
* The portals Space Dragon summons to bring carp onto the station. His main objective is to summon 3 of them and protect them from being destroyed.
* The portals can summon sentient space carp in limited amounts. The portal also changes color based on whether or not a carp spawn is available.
* Once it is fully charged, it becomes indestructible, and intermitently spawns non-sentient carp. It is still destroyed if Space Dragon dies.
*/
/obj/structure/carp_rift
name = "carp rift"
desc = "A rift akin to the ones space carp use to travel long distances."
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 100, BOMB = 50, BIO = 100, FIRE = 100, ACID = 100)
max_integrity = 300
icon = 'icons/obj/carp_rift.dmi'
icon_state = "carp_rift_carpspawn"
light_color = LIGHT_COLOR_PURPLE
light_range = 10
anchored = TRUE
density = FALSE
plane = MASSIVE_OBJ_PLANE
/// The amount of time the rift has charged for.
var/time_charged = 0
/// The maximum charge the rift can have.
var/max_charge = 300
/// How many carp spawns it has available.
var/carp_stored = 1
/// A reference to the Space Dragon antag that created it.
var/datum/antagonist/space_dragon/dragon
/// Current charge state of the rift.
var/charge_state = CHARGE_ONGOING
/// The interval for adding additional space carp spawns to the rift.
var/carp_interval = 60
/// The time since an extra carp was added to the ghost role spawning pool.
var/last_carp_inc = 0
/// A list of all the ckeys which have used this carp rift to spawn in as carps.
var/list/ckey_list = list()
/obj/structure/carp_rift/Initialize(mapload)
. = ..()
AddComponent( \
/datum/component/aura_healing, \
range = 0, \
simple_heal = 5, \
limit_to_trait = TRAIT_HEALS_FROM_CARP_RIFTS, \
healing_color = COLOR_BLUE, \
)
START_PROCESSING(SSobj, src)
// Carp rifts always take heavy explosion damage. Discourages the use of maxcaps
// and favours more weaker explosives to destroy the portal
// as they have the same effect on the portal.
/obj/structure/carp_rift/ex_act(severity, target)
return ..(min(EXPLODE_HEAVY, severity))
/obj/structure/carp_rift/examine(mob/user)
. = ..()
if(time_charged < max_charge)
. += span_notice("It seems to be [(time_charged / max_charge) * 100]% charged.")
else
. += span_warning("This one is fully charged. In this state, it is poised to transport a much larger amount of carp than normal.")
if(isobserver(user))
. += span_notice("It has [carp_stored] carp available to spawn as.")
/obj/structure/carp_rift/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
playsound(src, 'sound/magic/lightningshock.ogg', 50, TRUE)
/obj/structure/carp_rift/Destroy()
STOP_PROCESSING(SSobj, src)
if(charge_state != CHARGE_COMPLETED)
if(dragon)
to_chat(dragon.owner.current, span_boldwarning("A rift has been destroyed! You have failed, and find yourself weakened."))
dragon.destroy_rifts()
dragon = null
return ..()
/obj/structure/carp_rift/process(delta_time)
// If we're fully charged, just start mass spawning carp and move around.
if(charge_state == CHARGE_COMPLETED)
if(DT_PROB(1.25, delta_time) && dragon)
var/mob/living/newcarp = new dragon.ai_to_spawn(loc)
newcarp.faction = dragon.owner.current.faction.Copy()
if(DT_PROB(1.5, delta_time))
var/rand_dir = pick(GLOB.cardinals)
SSmove_manager.move_to(src, get_step(src, rand_dir), 1)
return
// Increase time trackers and check for any updated states.
time_charged = min(time_charged + delta_time, max_charge)
last_carp_inc += delta_time
update_check()
/obj/structure/carp_rift/attack_ghost(mob/user)
. = ..()
if(.)
return
summon_carp(user)
/**
* Does a series of checks based on the portal's status.
*
* Performs a number of checks based on the current charge of the portal, and triggers various effects accordingly.
* If the current charge is a multiple of carp_interval, add an extra carp spawn.
* If we're halfway charged, announce to the crew our location in a CENTCOM announcement.
* If we're fully charged, tell the crew we are, change our color to yellow, become invulnerable, and give Space Dragon the ability to make another rift, if he hasn't summoned 3 total.
*/
/obj/structure/carp_rift/proc/update_check()
// If the rift is fully charged, there's nothing to do here anymore.
if(charge_state == CHARGE_COMPLETED)
return
// Can we increase the carp spawn pool size?
if(last_carp_inc >= carp_interval)
carp_stored++
icon_state = "carp_rift_carpspawn"
if(light_color != LIGHT_COLOR_PURPLE)
set_light_color(LIGHT_COLOR_PURPLE)
update_light()
notify_ghosts("The carp rift can summon an additional carp!", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Carp Spawn Available")
last_carp_inc -= carp_interval
// Is the rift now fully charged?
if(time_charged >= max_charge)
charge_state = CHARGE_COMPLETED
var/area/A = get_area(src)
priority_announce("Spatial object has reached peak energy charge in [initial(A.name)], please stand-by.", "Central Command Wildlife Observations")
atom_integrity = INFINITY
icon_state = "carp_rift_charged"
set_light_color(LIGHT_COLOR_YELLOW)
update_light()
armor = list(MELEE = 100, BULLET = 100, LASER = 100, ENERGY = 100, BOMB = 100, BIO = 100, FIRE = 100, ACID = 100)
resistance_flags = INDESTRUCTIBLE
dragon.rifts_charged += 1
if(dragon.rifts_charged != 3 && !dragon.objective_complete)
var/datum/action/innate/summon_rift/rift = new()
rift.Grant(dragon.owner.current)
dragon.riftTimer = 0
dragon.rift_empower()
// Early return, nothing to do after this point.
return
// Do we need to give a final warning to the station at the halfway mark?
if(charge_state < CHARGE_FINALWARNING && time_charged >= (max_charge * 0.5))
charge_state = CHARGE_FINALWARNING
var/area/A = get_area(src)
priority_announce("A rift is causing an unnaturally large energy flux in [initial(A.name)]. Stop it at all costs!", "Central Command Wildlife Observations", ANNOUNCER_SPANOMALIES)
/**
* Used to create carp controlled by ghosts when the option is available.
*
* Creates a carp for the ghost to control if we have a carp spawn available.
* Gives them prompt to control a carp, and if our circumstances still allow if when they hit yes, spawn them in as a carp.
* Also add them to the list of carps in Space Dragon's antgonist datum, so they'll be displayed as having assisted him on round end.
* Arguments:
* * mob/user - The ghost which will take control of the carp.
*/
/obj/structure/carp_rift/proc/summon_carp(mob/user)
if(carp_stored <= 0)//Not enough carp points
return FALSE
var/is_listed = FALSE
if (user.ckey in ckey_list)
if(carp_stored == 1)
to_chat(user, span_warning("You've already become a carp using this rift! Either wait for a backlog of carp spawns or until the next rift!"))
return FALSE
is_listed = TRUE
var/carp_ask = tgui_alert(user, "Become a carp?", "Carp Rift", list("Yes", "No"))
if(carp_ask != "Yes" || QDELETED(src) || QDELETED(user))
return FALSE
if(carp_stored <= 0)
to_chat(user, span_warning("The rift already summoned enough carp!"))
return FALSE
if(!dragon)
return
var/mob/living/newcarp = new dragon.minion_to_spawn(loc)
newcarp.faction = dragon.owner.current.faction
newcarp.AddElement(/datum/element/nerfed_pulling, GLOB.typecache_general_bad_things_to_easily_move)
newcarp.AddElement(/datum/element/prevent_attacking_of_types, GLOB.typecache_general_bad_hostile_attack_targets, "this tastes awful!")
if(!is_listed)
ckey_list += user.ckey
newcarp.key = user.key
newcarp.set_name()
dragon.carp += newcarp.mind
to_chat(newcarp, span_boldwarning("You have arrived in order to assist the space dragon with securing the rifts. Do not jeopardize the mission, and protect the rifts at all costs!"))
carp_stored--
if(carp_stored <= 0 && charge_state < CHARGE_COMPLETED)
icon_state = "carp_rift"
set_light_color(LIGHT_COLOR_BLUE)
update_light()
return TRUE
#undef CHARGE_ONGOING
#undef CHARGE_FINALWARNING
#undef CHARGE_COMPLETED
@@ -10,6 +10,20 @@
var/list/datum/mind/carp = list()
/// The innate ability to summon rifts
var/datum/action/innate/summon_rift/rift_ability
/// Current time since the the last rift was activated. If set to -1, does not increment.
var/riftTimer = 0
/// Maximum amount of time which can pass without a rift before Space Dragon despawns.
var/maxRiftTimer = 300
/// A list of all of the rifts created by Space Dragon. Used for setting them all to infinite carp spawn when Space Dragon wins, and removing them when Space Dragon dies.
var/list/obj/structure/carp_rift/rift_list = list()
/// How many rifts have been successfully charged
var/rifts_charged = 0
/// Whether or not Space Dragon has completed their objective, and thus triggered the ending sequence.
var/objective_complete = FALSE
/// What mob to spawn from ghosts using this dragon's rifts
var/minion_to_spawn = /mob/living/simple_animal/hostile/carp
/// What AI mobs to spawn from this dragon's rifts
var/ai_to_spawn = /mob/living/simple_animal/hostile/carp
/datum/antagonist/space_dragon/greet()
. = ..()
@@ -31,10 +45,21 @@
. = ..()
rift_ability = new
rift_ability.Grant(owner.current)
owner.current.faction |= "carp"
RegisterSignal(owner.current, COMSIG_LIVING_LIFE, .proc/rift_checks)
RegisterSignal(owner.current, COMSIG_LIVING_DEATH, .proc/destroy_rifts)
/datum/antagonist/space_dragon/on_removal()
. = ..()
rift_ability.Remove(owner.current)
owner.current.faction -= "carp"
UnregisterSignal(owner.current, COMSIG_LIVING_LIFE)
UnregisterSignal(owner.current, COMSIG_LIVING_DEATH)
rift_list = null
/datum/antagonist/space_dragon/Destroy()
rift_list = null
return ..()
/datum/antagonist/space_dragon/get_preview_icon()
var/icon/icon = icon('icons/mob/spacedragon.dmi', "spacedragon")
@@ -47,6 +72,104 @@
return icon
/**
* Checks to see if we need to do anything with the current state of the dragon's rifts.
*
* A simple update check which sees if we need to do anything based on the current state of the dragon's rifts.
*
*/
/datum/antagonist/space_dragon/proc/rift_checks()
if((rifts_charged == 3 || (SSshuttle.emergency.mode == SHUTTLE_DOCKED && rifts_charged > 0)) && !objective_complete)
victory()
return
if(riftTimer == -1)
return
riftTimer = min(riftTimer + 1, maxRiftTimer + 1)
if(riftTimer == (maxRiftTimer - 60))
to_chat(owner.current, span_boldwarning("You have a minute left to summon the rift! Get to it!"))
return
if(riftTimer >= maxRiftTimer)
to_chat(owner.current, span_boldwarning("You've failed to summon the rift in a timely manner! You're being pulled back from whence you came!"))
destroy_rifts()
SEND_SOUND(owner.current, sound('sound/magic/demon_dies.ogg'))
QDEL_NULL(owner.current)
/**
* Destroys all of Space Dragon's current rifts.
*
* QDeletes all the current rifts after removing their references to other objects.
* Currently, the only reference they have is to the Dragon which created them, so we clear that before deleting them.
* Currently used when Space Dragon dies or one of his rifts is destroyed.
*/
/datum/antagonist/space_dragon/proc/destroy_rifts()
if(objective_complete)
return
rifts_charged = 0
owner.current.add_movespeed_modifier(/datum/movespeed_modifier/dragon_depression)
riftTimer = -1
SEND_SOUND(owner.current, sound('sound/vehicles/rocketlaunch.ogg'))
for(var/obj/structure/carp_rift/rift as anything in rift_list)
rift.dragon = null
rift_list -= rift
if(!QDELETED(rift))
QDEL_NULL(rift)
/**
* Sets up Space Dragon's victory for completing the objectives.
*
* Triggers when Space Dragon completes his objective.
* Calls the shuttle with a coefficient of 3, making it impossible to recall.
* Sets all of his rifts to allow for infinite sentient carp spawns
* Also plays appropiate sounds and CENTCOM messages.
*/
/datum/antagonist/space_dragon/proc/victory()
objective_complete = TRUE
permanant_empower()
var/datum/objective/summon_carp/main_objective = locate() in objectives
if(main_objective)
main_objective.completed = TRUE
priority_announce("A large amount of lifeforms have been detected approaching [station_name()] at extreme speeds. \
Remaining crew are advised to evacuate as soon as possible.", "Central Command Wildlife Observations")
sound_to_playing_players('sound/creatures/space_dragon_roar.ogg')
for(var/obj/structure/carp_rift/rift as anything in rift_list)
rift.carp_stored = 999999
rift.time_charged = rift.max_charge
/**
* Gives Space Dragon their the rift speed buff permanantly and fully heals the user.
*
* Gives Space Dragon the enraged speed buff from charging rifts permanantly.
* Only happens in circumstances where Space Dragon completes their objective.
* Also gives them a full heal.
*/
/datum/antagonist/space_dragon/proc/permanant_empower()
owner.current.fully_heal()
owner.current.add_filter("anger_glow", 3, list("type" = "outline", "color" = "#ff330030", "size" = 5))
owner.current.add_movespeed_modifier(/datum/movespeed_modifier/dragon_rage)
/**
* Handles Space Dragon's temporary empowerment after boosting a rift.
*
* Empowers and depowers Space Dragon after a successful rift charge.
* Empowered, Space Dragon regains all his health and becomes temporarily faster for 30 seconds, along with being tinted red.
*/
/datum/antagonist/space_dragon/proc/rift_empower()
owner.current.fully_heal()
owner.current.add_filter("anger_glow", 3, list("type" = "outline", "color" = "#ff330030", "size" = 5))
owner.current.add_movespeed_modifier(/datum/movespeed_modifier/dragon_rage)
addtimer(CALLBACK(src, .proc/rift_depower), 30 SECONDS)
/**
* Removes Space Dragon's rift speed buff.
*
* Removes Space Dragon's speed buff from charging a rift. This is only called
* in rift_empower, which uses a timer to call this after 30 seconds. Also
* removes the red glow from Space Dragon which is synonymous with the speed buff.
*/
/datum/antagonist/space_dragon/proc/rift_depower()
owner.current.remove_filter("anger_glow")
owner.current.remove_movespeed_modifier(/datum/movespeed_modifier/dragon_rage)
/datum/objective/summon_carp
var/datum/antagonist/space_dragon/dragon
explanation_text = "Summon and protect the rifts to flood the station with carp."
@@ -68,6 +191,7 @@
parts += "<span class='greentext big'>The [name] was successful!</span>"
else
parts += "<span class='redtext big'>The [name] has failed!</span>"
parts += "<span class='header'>The [name] was assisted by:</span>"
parts += printplayerlist(carp)
if(carp.len)
parts += "<span class='header'>The [name] was assisted by:</span>"
parts += printplayerlist(carp)
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
@@ -1,9 +1,3 @@
/// The carp rift is currently charging.
#define CHARGE_ONGOING 0
/// The carp rift is currently charging and has output a final warning.
#define CHARGE_FINALWARNING 1
/// The carp rift is now fully charged.
#define CHARGE_COMPLETED 2
/// The darkness threshold for space dragon when choosing a color
#define DARKNESS_THRESHOLD 50
@@ -67,10 +61,6 @@
maxbodytemp = 1500
faction = list("carp")
pressure_resistance = 200
/// Current time since the the last rift was activated. If set to -1, does not increment.
var/riftTimer = 0
/// Maximum amount of time which can pass without a rift before Space Dragon despawns.
var/maxRiftTimer = 300
/// How much endlag using Wing Gust should apply. Each use of wing gust increments this, and it decreases over time.
var/tiredness = 0
/// A multiplier to how much each use of wing gust should add to the tiredness variable. Set to 5 if the current rift is destroyed.
@@ -83,12 +73,6 @@
var/using_special = FALSE
/// Determines whether or not Space Dragon is currently tearing through a wall.
var/tearing_wall = FALSE
/// A list of all of the rifts created by Space Dragon. Used for setting them all to infinite carp spawn when Space Dragon wins, and removing them when Space Dragon dies.
var/list/obj/structure/carp_rift/rift_list = list()
/// How many rifts have been successfully charged
var/rifts_charged = 0
/// Whether or not Space Dragon has completed their objective, and thus triggered the ending sequence.
var/objective_complete = FALSE
/// The ability to make your sprite smaller
var/datum/action/small_sprite/space_dragon/small_sprite
/// The color of the space dragon.
@@ -130,21 +114,6 @@
visible_message(span_danger("[src] vomits up [consumed_mob]!"))
consumed_mob.forceMove(loc)
consumed_mob.Paralyze(50)
if(!mind.has_antag_datum(/datum/antagonist/space_dragon))
return
if((rifts_charged == 3 || (SSshuttle.emergency.mode == SHUTTLE_DOCKED && rifts_charged > 0)) && !objective_complete)
victory()
if(riftTimer == -1)
return
riftTimer = min(riftTimer + 1, maxRiftTimer + 1)
if(riftTimer == (maxRiftTimer - 60))
to_chat(src, span_boldwarning("You have a minute left to summon the rift! Get to it!"))
return
if(riftTimer >= maxRiftTimer)
to_chat(src, span_boldwarning("You've failed to summon the rift in a timely manner! You're being pulled back from whence you came!"))
death(TRUE)
playsound(src, 'sound/magic/demon_dies.ogg', 100, TRUE)
qdel(src)
/mob/living/simple_animal/hostile/space_dragon/AttackingTarget()
if(using_special)
@@ -202,8 +171,6 @@
/mob/living/simple_animal/hostile/space_dragon/death(gibbed)
empty_contents()
if(!objective_complete)
destroy_rifts()
..()
add_dragon_overlay()
UnregisterSignal(small_sprite, COMSIG_ACTION_TRIGGER)
@@ -392,59 +359,6 @@
using_special = FALSE
add_dragon_overlay()
/**
* Handles Space Dragon's temporary empowerment after boosting a rift.
*
* Empowers and depowers Space Dragon after a successful rift charge.
* Empowered, Space Dragon regains all his health and becomes temporarily faster for 30 seconds, along with being tinted red.
*/
/mob/living/simple_animal/hostile/space_dragon/proc/rift_empower()
fully_heal()
add_filter("anger_glow", 3, list("type" = "outline", "color" = "#ff330030", "size" = 5))
add_movespeed_modifier(/datum/movespeed_modifier/dragon_rage)
addtimer(CALLBACK(src, .proc/rift_depower), 30 SECONDS)
/**
* Gives Space Dragon their the rift speed buff permanantly.
*
* Gives Space Dragon the enraged speed buff from charging rifts permanantly.
* Only happens in circumstances where Space Dragon completes their objective.
*/
/mob/living/simple_animal/hostile/space_dragon/proc/permanant_empower()
fully_heal()
add_filter("anger_glow", 3, list("type" = "outline", "color" = "#ff330030", "size" = 5))
add_movespeed_modifier(/datum/movespeed_modifier/dragon_rage)
/**
* Removes Space Dragon's rift speed buff.
*
* Removes Space Dragon's speed buff from charging a rift. This is only called
* in rift_empower, which uses a timer to call this after 30 seconds. Also
* removes the red glow from Space Dragon which is synonymous with the speed buff.
*/
/mob/living/simple_animal/hostile/space_dragon/proc/rift_depower()
remove_filter("anger_glow")
remove_movespeed_modifier(/datum/movespeed_modifier/dragon_rage)
/**
* Destroys all of Space Dragon's current rifts.
*
* QDeletes all the current rifts after removing their references to other objects.
* Currently, the only reference they have is to the Dragon which created them, so we clear that before deleting them.
* Currently used when Space Dragon dies or one of his rifts is destroyed.
*/
/mob/living/simple_animal/hostile/space_dragon/proc/destroy_rifts()
rifts_charged = 0
add_movespeed_modifier(/datum/movespeed_modifier/dragon_depression)
riftTimer = -1
tiredness_mult = 5
playsound(src, 'sound/vehicles/rocketlaunch.ogg', 100, TRUE)
for(var/obj/structure/carp_rift/rift in rift_list)
rift.dragon = null
rift_list -= rift
if(!QDELETED(rift))
QDEL_NULL(rift)
/**
* Handles wing gust from the windup all the way to the endlag at the end.
*
@@ -483,258 +397,4 @@
addtimer(CALLBACK(src, .proc/reset_status), 4 + ((tiredness * tiredness_mult) / 10))
tiredness = tiredness + (gust_tiredness * tiredness_mult)
/**
* Sets up Space Dragon's victory for completing the objectives.
*
* Triggers when Space Dragon completes his objective.
* Calls the shuttle with a coefficient of 3, making it impossible to recall.
* Sets all of his rifts to allow for infinite sentient carp spawns
* Also plays appropiate sounds and CENTCOM messages.
*/
/mob/living/simple_animal/hostile/space_dragon/proc/victory()
objective_complete = TRUE
permanant_empower()
var/datum/antagonist/space_dragon/S = mind.has_antag_datum(/datum/antagonist/space_dragon)
if(S)
var/datum/objective/summon_carp/main_objective = locate() in S.objectives
if(main_objective)
main_objective.completed = TRUE
priority_announce("A large amount of lifeforms have been detected approaching [station_name()] at extreme speeds. \
Remaining crew are advised to evacuate as soon as possible.", "Central Command Wildlife Observations")
sound_to_playing_players('sound/creatures/space_dragon_roar.ogg')
for(var/obj/structure/carp_rift/rift in rift_list)
rift.carp_stored = 999999
rift.time_charged = rift.max_charge
/datum/action/innate/summon_rift
name = "Summon Rift"
desc = "Summon a rift to bring forth a horde of space carp."
background_icon_state = "bg_default"
icon_icon = 'icons/mob/actions/actions_space_dragon.dmi'
button_icon_state = "carp_rift"
/datum/action/innate/summon_rift/Activate()
var/mob/living/simple_animal/hostile/space_dragon/S = owner
if(S.using_special)
return
if(S.riftTimer == -1)
to_chat(S, span_warning("Your death has left you unable to summon rifts!"))
return
var/area/A = get_area(S)
if(!(A.area_flags & VALID_TERRITORY))
to_chat(S, span_warning("You can't summon a rift here! Try summoning somewhere secure within the station!"))
return
for(var/obj/structure/carp_rift/rift in S.rift_list)
var/area/RA = get_area(rift)
if(RA == A)
to_chat(S, span_warning("You've already summoned a rift in this area! You have to summon again somewhere else!"))
return
to_chat(S, span_warning("You begin to open a rift..."))
if(do_after(S, 100, target = S))
for(var/obj/structure/carp_rift/c in S.loc.contents)
return
var/obj/structure/carp_rift/CR = new /obj/structure/carp_rift(S.loc)
playsound(S, 'sound/vehicles/rocketlaunch.ogg', 100, TRUE)
S.riftTimer = -1
CR.dragon = S
S.rift_list += CR
to_chat(S, span_boldwarning("The rift has been summoned. Prevent the crew from destroying it at all costs!"))
notify_ghosts("The Space Dragon has opened a rift!", source = CR, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Carp Rift Opened")
qdel(src)
/**
* # Carp Rift
*
* The portals Space Dragon summons to bring carp onto the station.
*
* The portals Space Dragon summons to bring carp onto the station. His main objective is to summon 3 of them and protect them from being destroyed.
* The portals can summon sentient space carp in limited amounts. The portal also changes color based on whether or not a carp spawn is available.
* Once it is fully charged, it becomes indestructible, and intermitently spawns non-sentient carp. It is still destroyed if Space Dragon dies.
*/
/obj/structure/carp_rift
name = "carp rift"
desc = "A rift akin to the ones space carp use to travel long distances."
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 100, BOMB = 50, BIO = 0, FIRE = 100, ACID = 100)
max_integrity = 300
icon = 'icons/obj/carp_rift.dmi'
icon_state = "carp_rift_carpspawn"
light_color = LIGHT_COLOR_PURPLE
light_range = 10
anchored = TRUE
density = FALSE
plane = MASSIVE_OBJ_PLANE
/// The amount of time the rift has charged for.
var/time_charged = 0
/// The maximum charge the rift can have.
var/max_charge = 300
/// How many carp spawns it has available.
var/carp_stored = 1
/// A reference to the Space Dragon that created it.
var/mob/living/simple_animal/hostile/space_dragon/dragon
/// Current charge state of the rift.
var/charge_state = CHARGE_ONGOING
/// The interval for adding additional space carp spawns to the rift.
var/carp_interval = 60
/// The time since an extra carp was added to the ghost role spawning pool.
var/last_carp_inc = 0
/// A list of all the ckeys which have used this carp rift to spawn in as carps.
var/list/ckey_list = list()
/obj/structure/carp_rift/Initialize(mapload)
. = ..()
AddComponent( \
/datum/component/aura_healing, \
range = 0, \
simple_heal = 5, \
limit_to_trait = TRAIT_HEALS_FROM_CARP_RIFTS, \
healing_color = COLOR_BLUE, \
)
START_PROCESSING(SSobj, src)
// Carp rifts always take heavy explosion damage. Discourages the use of maxcaps
// and favours more weaker explosives to destroy the portal
// as they have the same effect on the portal.
/obj/structure/carp_rift/ex_act(severity, target)
return ..(min(EXPLODE_HEAVY, severity))
/obj/structure/carp_rift/examine(mob/user)
. = ..()
if(time_charged < max_charge)
. += span_notice("It seems to be [(time_charged / max_charge) * 100]% charged.")
else
. += span_warning("This one is fully charged. In this state, it is poised to transport a much larger amount of carp than normal.")
if(isobserver(user))
. += span_notice("It has [carp_stored] carp available to spawn as.")
/obj/structure/carp_rift/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
playsound(src, 'sound/magic/lightningshock.ogg', 50, TRUE)
/obj/structure/carp_rift/Destroy()
STOP_PROCESSING(SSobj, src)
if(time_charged != max_charge + 1)
dragon?.destroy_rifts()
if(dragon)
to_chat(dragon, span_boldwarning("A rift has been destroyed! You have failed, and find yourself weakened."))
return ..()
/obj/structure/carp_rift/process(delta_time)
// If we're fully charged, just start mass spawning carp and move around.
if(charge_state == CHARGE_COMPLETED)
if(DT_PROB(1.25, delta_time))
new /mob/living/simple_animal/hostile/carp(loc)
if(DT_PROB(1.5, delta_time))
var/rand_dir = pick(GLOB.cardinals)
Move(get_step(src, rand_dir), rand_dir)
return
// Increase time trackers and check for any updated states.
time_charged = min(time_charged + delta_time, max_charge)
last_carp_inc += delta_time
update_check()
/obj/structure/carp_rift/attack_ghost(mob/user)
. = ..()
if(.)
return
summon_carp(user)
/**
* Does a series of checks based on the portal's status.
*
* Performs a number of checks based on the current charge of the portal, and triggers various effects accordingly.
* If the current charge is a multiple of carp_interval, add an extra carp spawn.
* If we're halfway charged, announce to the crew our location in a CENTCOM announcement.
* If we're fully charged, tell the crew we are, change our color to yellow, become invulnerable, and give Space Dragon the ability to make another rift, if he hasn't summoned 3 total.
*/
/obj/structure/carp_rift/proc/update_check()
// If the rift is fully charged, there's nothing to do here anymore.
if(charge_state == CHARGE_COMPLETED)
return
// Can we increase the carp spawn pool size?
if(last_carp_inc >= carp_interval)
carp_stored++
icon_state = "carp_rift_carpspawn"
if(light_color != LIGHT_COLOR_PURPLE)
set_light_color(LIGHT_COLOR_PURPLE)
update_light()
notify_ghosts("The carp rift can summon an additional carp!", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Carp Spawn Available")
last_carp_inc -= carp_interval
// Is the rift now fully charged?
if(time_charged >= max_charge)
charge_state = CHARGE_COMPLETED
var/area/A = get_area(src)
priority_announce("Spatial object has reached peak energy charge in [initial(A.name)], please stand-by.", "Central Command Wildlife Observations")
atom_integrity = INFINITY
icon_state = "carp_rift_charged"
set_light_color(LIGHT_COLOR_YELLOW)
update_light()
armor = list(MELEE = 100, BULLET = 100, LASER = 100, ENERGY = 100, BOMB = 100, BIO = 100, FIRE = 100, ACID = 100)
resistance_flags = INDESTRUCTIBLE
dragon.rifts_charged += 1
if(dragon.rifts_charged != 3 && !dragon.objective_complete)
var/datum/action/innate/summon_rift/rift = new()
rift.Grant(dragon)
dragon.riftTimer = 0
dragon.rift_empower()
// Early return, nothing to do after this point.
return
// Do we need to give a final warning to the station at the halfway mark?
if(charge_state < CHARGE_FINALWARNING && time_charged >= (max_charge * 0.5))
charge_state = CHARGE_FINALWARNING
var/area/A = get_area(src)
priority_announce("A rift is causing an unnaturally large energy flux in [initial(A.name)]. Stop it at all costs!", "Central Command Wildlife Observations", ANNOUNCER_SPANOMALIES)
/**
* Used to create carp controlled by ghosts when the option is available.
*
* Creates a carp for the ghost to control if we have a carp spawn available.
* Gives them prompt to control a carp, and if our circumstances still allow if when they hit yes, spawn them in as a carp.
* Also add them to the list of carps in Space Dragon's antgonist datum, so they'll be displayed as having assisted him on round end.
* Arguments:
* * mob/user - The ghost which will take control of the carp.
*/
/obj/structure/carp_rift/proc/summon_carp(mob/user)
if(carp_stored <= 0)//Not enough carp points
return FALSE
var/is_listed = FALSE
if (user.ckey in ckey_list)
if(carp_stored == 1)
to_chat(user, span_warning("You've already become a carp using this rift! Either wait for a backlog of carp spawns or until the next rift!"))
return FALSE
is_listed = TRUE
var/carp_ask = tgui_alert(user, "Become a carp?", "Carp Rift", list("Yes", "No"))
if(carp_ask != "Yes" || !src || QDELETED(src) || QDELETED(user))
return FALSE
if(carp_stored <= 0)
to_chat(user, span_warning("The rift already summoned enough carp!"))
return FALSE
var/mob/living/simple_animal/hostile/carp/newcarp = new /mob/living/simple_animal/hostile/carp(loc)
newcarp.AddElement(/datum/element/nerfed_pulling, GLOB.typecache_general_bad_things_to_easily_move)
newcarp.AddElement(/datum/element/prevent_attacking_of_types, GLOB.typecache_general_bad_hostile_attack_targets, "this tastes awful!")
if(!is_listed)
ckey_list += user.ckey
newcarp.key = user.key
newcarp.set_name()
var/datum/antagonist/space_dragon/S = dragon?.mind?.has_antag_datum(/datum/antagonist/space_dragon)
if(S)
S.carp += newcarp.mind
to_chat(newcarp, span_boldwarning("You have arrived in order to assist the space dragon with securing the rifts. Do not jeopardize the mission, and protect the rifts at all costs!"))
carp_stored--
if(carp_stored <= 0 && charge_state < CHARGE_COMPLETED)
icon_state = "carp_rift"
set_light_color(LIGHT_COLOR_BLUE)
update_light()
return TRUE
#undef CHARGE_ONGOING
#undef CHARGE_FINALWARNING
#undef CHARGE_COMPLETED
#undef DARKNESS_THRESHOLD
+1
View File
@@ -2324,6 +2324,7 @@
#include "code\modules\antagonists\slaughter\slaughter.dm"
#include "code\modules\antagonists\slaughter\slaughter_antag.dm"
#include "code\modules\antagonists\slaughter\slaughterevent.dm"
#include "code\modules\antagonists\space_dragon\carp_rift.dm"
#include "code\modules\antagonists\space_dragon\space_dragon.dm"
#include "code\modules\antagonists\space_ninja\space_ninja.dm"
#include "code\modules\antagonists\survivalist\survivalist.dm"