From 3c8a649300e80bd73b17fc095590fe7de53e8232 Mon Sep 17 00:00:00 2001 From: SuperSlayer Date: Mon, 11 Apr 2022 17:59:30 +0300 Subject: [PATCH 01/36] Coggers --- code/__DEFINES/role_preferences.dm | 2 + .../dynamic/dynamic_rulesets_midround.dm | 46 ++ .../antagonists/space_dragon/space_dragon.dm | 63 ++- code/modules/events/space_dragon.dm | 12 +- .../simple_animal/hostile/megafauna/drake.dm | 73 --- .../simple_animal/hostile/space_dragon.dm | 533 ++++++++++++++++++ icons/mob/actions/actions_space_dragon.dmi | Bin 0 -> 959 bytes icons/mob/spacedragon.dmi | Bin 5523 -> 6712 bytes icons/obj/carp_rift.dmi | Bin 0 -> 4319 bytes sound/ai/spanomalies.ogg | Bin 0 -> 40469 bytes yogstation.dme | 1 + 11 files changed, 628 insertions(+), 102 deletions(-) create mode 100644 code/modules/mob/living/simple_animal/hostile/space_dragon.dm create mode 100644 icons/mob/actions/actions_space_dragon.dmi create mode 100644 icons/obj/carp_rift.dmi create mode 100644 sound/ai/spanomalies.ogg diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index e1228b1506c4..1caac6a3e145 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -51,6 +51,7 @@ #define ROLE_VAMPIRICACCIDENT "Vampiric Accident" #define ROLE_BLOODSUCKERBREAKOUT "Bloodsucker Breakout" #define ROLE_MONSTERHUNTER "Monster Hunter" +#define ROLE_SPACE_DRAGON "Space Dragon" //Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR. //The gamemode specific ones are just so the gamemodes can query whether a player is old enough @@ -91,6 +92,7 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_FUGITIVE, ROLE_BLOODSUCKER = /datum/game_mode/bloodsucker, ROLE_MONSTERHUNTER, + ROLE_SPACE_DRAGON, )) //Job defines for what happens when you fail to qualify for any job during job selection diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index 2f6e916fd7ce..18ee89fc6516 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -459,6 +459,52 @@ log_game("DYNAMIC: [key_name(S)] was spawned as a Nightmare by the midround ruleset.") return S + + +////////////////////////////////////////////// +// // +// SPACE DRAGON (GHOST) // +// // +////////////////////////////////////////////// + +/datum/dynamic_ruleset/midround/from_ghosts/space_dragon + name = "Space Dragon" + antag_datum = /datum/antagonist/space_dragon + antag_flag = "Space Dragon" + antag_flag_override = ROLE_SPACE_DRAGON + enemy_roles = list("Security Officer", "Detective", "Head of Security", "Captain") + required_enemies = list(2,2,1,1,1,1,1,0,0,0) + required_candidates = 1 + weight = 4 + cost = 10 + requirements = list(101,101,101,80,60,50,30,20,10,10) + repeatable = TRUE + var/list/spawn_locs = list() + +/datum/dynamic_ruleset/midround/from_ghosts/space_dragon/execute() + for(var/obj/effect/landmark/carpspawn/C in GLOB.landmarks_list) + spawn_locs += (C.loc) + if(!spawn_locs.len) + message_admins("No valid spawn locations found, aborting...") + return MAP_ERROR + . = ..() + +/datum/dynamic_ruleset/midround/from_ghosts/space_dragon/generate_ruleset_body(mob/applicant) + var/datum/mind/player_mind = new /datum/mind(applicant.key) + player_mind.active = TRUE + + var/mob/living/simple_animal/hostile/space_dragon/S = new (pick(spawn_locs)) + player_mind.transfer_to(S) + player_mind.assigned_role = "Space Dragon" + player_mind.special_role = "Space Dragon" + player_mind.add_antag_datum(/datum/antagonist/space_dragon) + + playsound(S, 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1) + message_admins("[ADMIN_LOOKUPFLW(S)] has been made into a Space Dragon by the midround ruleset.") + log_game("DYNAMIC: [key_name(S)] was spawned as a Space Dragon by the midround ruleset.") + priority_announce("A large organic energy flux has been recorded near of [station_name()], please stand-by.", "Lifesign Alert") + return S + ////////////////////////////////////////////// // // // VAMPIRE // diff --git a/code/modules/antagonists/space_dragon/space_dragon.dm b/code/modules/antagonists/space_dragon/space_dragon.dm index 5e75a740ace3..627ab7dfb4fa 100644 --- a/code/modules/antagonists/space_dragon/space_dragon.dm +++ b/code/modules/antagonists/space_dragon/space_dragon.dm @@ -1,32 +1,51 @@ /datum/antagonist/space_dragon name = "Space Dragon" - show_in_antagpanel = FALSE + roundend_category = "space dragons" + antagpanel_category = "Space Dragon" + job_rank = ROLE_SPACE_DRAGON + show_in_antagpanel = TRUE show_name_in_check_antagonists = TRUE - show_to_ghosts = TRUE + var/list/datum/mind/carp = list() /datum/antagonist/space_dragon/greet() - to_chat(owner, "I am Space Dragon, ex-space carp, and defender of the secrets of constellation, Draco.") - to_chat(owner, "Fabulous secret powers were revealed to me the day I held aloft a wizard's staff of change and said 'By the power of Draco, I have the power!'") - to_chat(owner, "The wizard was turned into the short-lived Pastry Cat while I became Space Dragon, the most powerful beast in the universe.") - to_chat(owner, "Clicking a tile will shoot fire onto that tile.") - to_chat(owner, "Using Tail Sweep will let me get the better of those who come too close.") - to_chat(owner, "Attacking dead bodies will allow me to gib them to restore health.") - to_chat(owner, "From the wizard's writings, he had been studying this station and its hierarchy. From this, I know who leads the station, and will kill them so the station underlings see me as their new leader.") + to_chat(owner, "Endless time and space we have moved through. We do not remember from where we came, we do not know where we will go. All space belongs to us.\n\ + Space is an empty void, of which our kind is the apex predator, and there was little to rival our claim to this title.\n\ + But now, we find intruders spread out amongst our claim, willing to fight our teeth with magics unimaginable, their dens like lights flicking in the depths of space.\n\ + Today, we will snuff out one of those lights.") + to_chat(owner, "You have five minutes to find a safe location to place down the first rift. If you take longer than five minutes to place a rift, you will be returned from whence you came.") owner.announce_objectives() SEND_SOUND(owner.current, sound('sound/magic/demon_attack1.ogg')) - + /datum/antagonist/space_dragon/proc/forge_objectives() - var/current_heads = SSjob.get_all_heads() - var/datum/objective/assassinate/killchosen = new - killchosen.owner = owner - var/datum/mind/selected = pick(current_heads) - killchosen.target = selected - killchosen.update_explanation_text() - objectives += killchosen - var/datum/objective/survive/survival = new - survival.owner = owner - objectives += survival - + var/datum/objective/summon_carp/summon = new() + summon.dragon = src + objectives += summon + /datum/antagonist/space_dragon/on_gain() forge_objectives() - . = ..() \ No newline at end of file + . = ..() + +/datum/objective/summon_carp + var/datum/antagonist/space_dragon/dragon + explanation_text = "Summon and protect the rifts to flood the station with carp." + +/datum/antagonist/space_dragon/roundend_report() + var/list/parts = list() + var/datum/objective/summon_carp/S = locate() in objectives + if(S.check_completion()) + parts += "The [name] has succeeded! Station space has been reclaimed by the space carp!" + parts += printplayer(owner) + var/objectives_complete = TRUE + if(objectives.len) + parts += printobjectives(objectives) + for(var/datum/objective/objective in objectives) + if(!objective.check_completion()) + objectives_complete = FALSE + break + if(objectives_complete) + parts += "The [name] was successful!" + else + parts += "The [name] has failed!" + parts += "The [name] was assisted by:" + parts += printplayerlist(carp) + return "
[parts.Join("
")]
" \ No newline at end of file diff --git a/code/modules/events/space_dragon.dm b/code/modules/events/space_dragon.dm index a6100cba7edc..918e98d62472 100644 --- a/code/modules/events/space_dragon.dm +++ b/code/modules/events/space_dragon.dm @@ -3,9 +3,8 @@ typepath = /datum/round_event/ghost_role/space_dragon max_occurrences = 1 weight = 8 - earliest_start = 70 MINUTES - min_players = 30 - dynamic_should_hijack = TRUE + weight = 5 + earliest_start = 35 MINUTES /datum/round_event/ghost_role/space_dragon minimum_required = 1 @@ -13,10 +12,10 @@ announceWhen = 10 /datum/round_event/ghost_role/space_dragon/announce(fake) - priority_announce("It appears a lifeform with magical traces is approaching [station_name()], please stand-by.", "Lifesign Alert") + priority_announce("A large organic energy flux has been recorded near of [station_name()], please stand-by.", "Lifesign Alert") /datum/round_event/ghost_role/space_dragon/spawn_role() - var/list/candidates = get_candidates(ROLE_ALIEN, null, ROLE_ALIEN) + var/list/candidates = get_candidates(ROLE_SPACE_DRAGON, null, ROLE_SPACE_DRAGON) if(!candidates.len) return NOT_ENOUGH_PLAYERS @@ -32,7 +31,7 @@ message_admins("No valid spawn locations found, aborting...") return MAP_ERROR - var/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/S = new ((pick(spawn_locs))) + var/mob/living/simple_animal/hostile/space_dragon/S = new (pick(spawn_locs)) player_mind.transfer_to(S) player_mind.assigned_role = "Space Dragon" player_mind.special_role = "Space Dragon" @@ -42,4 +41,3 @@ log_game("[key_name(S)] was spawned as a Space Dragon by an event.") spawned_mobs += S return SUCCESSFUL_SPAWN - diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 3ab550e0e6a7..d9b58270219a 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -605,76 +605,3 @@ obj/effect/temp_visual/fireball lava_pools(10, 2) // less pools but longer delay before spawns player_cooldown = world.time + 200 // needs seperate cooldown or cant use fire attacks -/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon - name = "space dragon" - maxHealth = 250 - health = 250 - faction = list("neutral") - desc = "A space carp turned dragon by vile magic. Has the same ferocity of a space carp, but also a much more enabling body." - icon = 'icons/mob/spacedragon.dmi' - icon_state = "spacedragon" - icon_living = "spacedragon" - icon_dead = "spacedragon_dead" - obj_damage = 80 - melee_damage_upper = 35 - melee_damage_lower = 35 - speed = 0 - mouse_opacity = MOUSE_OPACITY_ICON - loot = list() - crusher_loot = list() - 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/carpdragon = 10) - move_force = MOVE_FORCE_NORMAL - move_resist = MOVE_FORCE_NORMAL - pull_force = MOVE_FORCE_NORMAL - environment_smash = ENVIRONMENT_SMASH_WALLS - deathmessage = "screeches as its wings turn to dust and it collapses on the floor, life estinguished." - attack_action_types = list() - small_sprite_type = /datum/action/small_sprite/megafauna/spacedragon - music_component = null - -/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/Initialize() - var/obj/effect/proc_holder/spell/aoe_turf/repulse/spacedragon/repulse_action = new /obj/effect/proc_holder/spell/aoe_turf/repulse/spacedragon(src) - repulse_action.action.Grant(src) - mob_spell_list += repulse_action - . = ..() - -/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/proc/fire_stream(var/atom/at = target) - playsound(get_turf(src),'sound/magic/fireball.ogg', 200, 1) - SLEEP_CHECK_DEATH(0) - var/range = 20 - var/list/turfs = list() - turfs = line_target(0, range, at) - INVOKE_ASYNC(src, .proc/fire_line, turfs) - -/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/OpenFire() - if(swooping) - return - ranged_cooldown = world.time + ranged_cooldown_time - fire_stream() - -/obj/effect/proc_holder/spell/aoe_turf/repulse/spacedragon - name = "Tail Sweep" - desc = "Throw back attackers with a sweep of your tail." - sound = 'sound/magic/tail_swing.ogg' - charge_max = 200 - clothes_req = FALSE - antimagic_allowed = TRUE - range = 1 - cooldown_min = 200 - invocation_type = "none" - sparkle_path = /obj/effect/temp_visual/dir_setting/tailsweep - action_icon = 'icons/mob/actions/actions_xeno.dmi' - action_icon_state = "tailsweep" - action_background_icon_state = "bg_alien" - anti_magic_check = FALSE - -/obj/effect/proc_holder/spell/aoe_turf/repulse/spacedragon/cast(list/targets,mob/user = usr) - if(iscarbon(user)) - var/mob/living/carbon/C = user - playsound(C.loc,'sound/effects/hit_punch.ogg', 80, 1, 1) - C.spin(6,1) - ..(targets, user, 60) - -/mob/living/simple_animal/hostile/megafauna/dragon/space_dragon/AltClickOn(atom/movable/A) - return diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm new file mode 100644 index 000000000000..96dff232c165 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -0,0 +1,533 @@ +/** + * # Space Dragon + * + * A space-faring leviathan-esque monster which breathes fire and summons carp. Spawned during its respective midround antagonist event. + * + * A space-faring monstrosity who has the ability to breathe dangerous fire breath and uses its powerful wings to knock foes away. + * Normally spawned as an antagonist during the Space Dragon event, Space Dragon's main goal is to open three rifts from which to pull a great tide of carp onto the station. + * Space Dragon can summon only one rift at a time, and can do so anywhere a blob is allowed to spawn. In order to trigger his victory condition, Space Dragon must summon and defend three rifts while they charge. + * Space Dragon, when spawned, has five minutes to summon the first rift. Failing to do so will cause Space Dragon to return from whence he came. + * When the rift spawns, ghosts can interact with it to spawn in as space carp to help complete the mission. One carp is granted when the rift is first summoned, with an extra one every 40 seconds. + * Once the victory condition is met, the shuttle is called and all current rifts are allowed to spawn infinite sentient space carp. + * If a charging rift is destroyed, Space Dragon will be incredibly slowed, and the endlag on his gust attack is greatly increased on each use. + * Space Dragon has the following abilities to assist him with his objective: + * - Can shoot fire in straight line, dealing 30 burn damage and setting those suseptible on fire. + * - Can use his wings to temporarily stun and knock back any nearby mobs. This attack has no cooldown, but instead has endlag after the attack where Space Dragon cannot act. This endlag's time decreases over time, but is added to every time he uses the move. + * - Can swallow mob corpses to heal for half their max health. Any corpses swallowed are stored within him, and will be regurgitated on death. + * - Can tear through any type of wall. This takes 4 seconds for most walls, and 12 seconds for reinforced walls. + */ +/mob/living/simple_animal/hostile/space_dragon + name = "Space Dragon" + desc = "A vile leviathan-esque creature that flies in the most unnatural way. Slightly looks similar to a space carp." + maxHealth = 400 + health = 400 + a_intent = INTENT_HARM + speed = 0 + attacktext = "chomps" + attack_sound = 'sound/magic/demon_attack1.ogg' + deathsound = 'sound/magic/demon_dies.ogg' + icon = 'icons/mob/spacedragon.dmi' + icon_state = "spacedragon" + icon_living = "spacedragon" + icon_dead = "spacedragon_dead" + obj_damage = 50 + environment_smash = ENVIRONMENT_SMASH_NONE + flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1 + melee_damage_upper = 35 + melee_damage_lower = 35 + armour_penetration = 30 + pixel_x = -16 + turns_per_move = 5 + spacewalk = TRUE + spacewalk = TRUE + spacewalk = TRUE + ranged = TRUE + mouse_opacity = MOUSE_OPACITY_ICON + butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30) + deathmessage = "screeches as its wings turn to dust and it collapses on the floor, life estinguished." + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minbodytemp = 0 + 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. + var/tiredness_mult = 1 + /// Determines whether or not Space Dragon is in the middle of using wing guat. If set to true, prevents him from moving and doing certain actions. + var/using_special = 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 togglable small sprite action + var/small_sprite_type = /datum/action/small_sprite/megafauna/spacedragon + /// The innate ability to use wing gust + var/datum/action/innate/space_dragon/gustAttack/gust + /// The innate ability to summon rifts + var/datum/action/innate/space_dragon/summonRift/rift + +/mob/living/simple_animal/hostile/space_dragon/Initialize(mapload) + . = ..() + if(small_sprite_type) + var/datum/action/small_sprite/small_action = new small_sprite_type() + small_action.Grant(src) + gust = new + gust.Grant(src) + rift = new + rift.Grant(src) + +/mob/living/simple_animal/hostile/space_dragon/Life(mapload) + . = ..() + tiredness = max(tiredness - 1, 0) + if(rifts_charged == 3 && !objective_complete) + victory() + if(riftTimer == -1) + return + riftTimer = min(riftTimer + 1, maxRiftTimer + 1) + if(riftTimer == (maxRiftTimer - 60)) + to_chat(src, "You have a minute left to summon the rift! Get to it!") + return + if(riftTimer == maxRiftTimer) + to_chat(src, "You've failed to summon the rift in a timely manner! You're being pulled back from whence you came!") + destroy_rifts() + QDEL_NULL(src) + +/mob/living/simple_animal/hostile/space_dragon/AttackingTarget() + if(using_special) + return + if(target == src) + to_chat(src, "You almost bite yourself, but then decide against it.") + return + if(istype(target, /turf/closed/wall)) + var/turf/closed/wall/thewall = target + to_chat(src, "You begin tearing through the wall...") + playsound(src, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE) + var/timetotear = 40 + if(istype(target, /turf/closed/wall/r_wall)) + timetotear = 120 + if(do_after(src, timetotear, target = thewall)) + if(istype(thewall, /turf/open)) + return + thewall.dismantle_wall(1) + playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE) + return + if(isliving(target)) //Swallows corpses like a snake to regain health. + var/mob/living/L = target + if(L.stat == DEAD) + to_chat(src, "You begin to swallow [L] whole...") + if(do_after(src, 30, target = L)) + if(eat(L)) + adjustHealth(-L.maxHealth * 0.5) + return + . = ..() + if(istype(target, /obj/mecha)) + var/obj/mecha/M = target + M.take_damage(50, BRUTE, "melee", 1) + +/mob/living/simple_animal/hostile/space_dragon/Move() + if(!using_special) + ..() + +/mob/living/simple_animal/hostile/space_dragon/OpenFire() + if(using_special) + return + ranged_cooldown = world.time + ranged_cooldown_time + fire_stream() + +/mob/living/simple_animal/hostile/space_dragon/death(gibbed) + empty_contents() + if(!objective_complete) + destroy_rifts() + ..() + +/mob/living/simple_animal/hostile/space_dragon/wabbajack_act(mob/living/new_mob) + empty_contents() + . = ..() + +/** + * Determines a line of turfs from sources's position to the target with length range. + * + * Determines a line of turfs from the source's position to the target with length range. + * The line will extend on past the target if the range is large enough, and not reach the target if range is small enough. + * Arguments: + * * offset - whether or not to aim slightly to the left or right of the target + * * range - how many turfs should we go out for + * * atom/at - The target + */ +/mob/living/simple_animal/hostile/space_dragon/proc/line_target(offset, range, atom/at = target) + if(!at) + return + var/angle = ATAN2(at.x - src.x, at.y - src.y) + offset + var/turf/T = get_turf(src) + for(var/i in 1 to range) + var/turf/check = locate(src.x + cos(angle) * i, src.y + sin(angle) * i, src.z) + if(!check) + break + T = check + return (getline(src, T) - get_turf(src)) + +/** + * Spawns fire at each position in a line from the source to the target. + * + * Spawns fire at each position in a line from the source to the target. + * Stops if it comes into contact with a solid wall, a window, or a door. + * Delays the spawning of each fire by 1.5 deciseconds. + * Arguments: + * * atom/at - The target + */ +/mob/living/simple_animal/hostile/space_dragon/proc/fire_stream(var/atom/at = target) + playsound(get_turf(src),'sound/magic/fireball.ogg', 200, TRUE) + var/range = 20 + var/list/turfs = list() + turfs = line_target(0, range, at) + var/delayFire = -1.5 + for(var/turf/T in turfs) + if(istype(T, /turf/closed)) + return + for(var/obj/structure/window/W in T.contents) + return + for(var/obj/machinery/door/D in T.contents) + if(D.density) + return + delayFire += 1.5 + addtimer(CALLBACK(src, .proc/dragon_fire_line, T), delayFire) + +/** + * What occurs on each tile to actually create the fire. + * + * Creates a fire on the given turf. + * It creates a hotspot on the given turf, damages any living mob with 30 burn damage, and damages mechs by 50. + * It can only hit any given target once. + * Arguments: + * * turf/T - The turf to trigger the effects on. + */ +mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) + var/list/hit_list = list() + hit_list += src + new /obj/effect/hotspot(T) + T.hotspot_expose(700,50,1) + for(var/mob/living/L in T.contents) + if(L in hit_list) + continue + hit_list += L + L.adjustFireLoss(30) + to_chat(L, "You're hit by [src]'s fire breath!") + // deals damage to mechs + for(var/obj/mecha/M in T.contents) + if(M in hit_list) + continue + hit_list += M + M.take_damage(50, BRUTE, "melee", 1) + +/** + * Handles consuming and storing consumed things inside Space Dragon + * + * Plays a sound and then stores the consumed thing inside Space Dragon. + * Used in AttackingTarget(), paired with a heal should it succeed. + * Arguments: + * * atom/movable/A - The thing being consumed + */ +/mob/living/simple_animal/hostile/space_dragon/proc/eat(atom/movable/A) + if(A && A.loc != src) + playsound(src, 'sound/magic/demon_attack1.ogg', 100, TRUE) + visible_message("[src] swallows [A] whole!") + A.forceMove(src) + return TRUE + return FALSE + +/** + * Disperses the contents of the mob on the surrounding tiles. + * + * Randomly places the contents of the mob onto surrounding tiles. + * Has a 10% chance to place on the same tile as the mob. + */ +/mob/living/simple_animal/hostile/space_dragon/proc/empty_contents() + for(var/atom/movable/AM in src) + AM.forceMove(loc) + if(prob(90)) + step(AM, pick(GLOB.alldirs)) + +/** + * Resets Space Dragon's status after using wing gust. + * + * Resets Space Dragon's status after using wing gust. + * If it isn't dead by the time it calls this method, reset the sprite back to the normal living sprite. + * Also sets the using_special variable to FALSE, allowing Space Dragon to move and attack freely again. + */ +/mob/living/simple_animal/hostile/space_dragon/proc/reset_status() + if(stat != DEAD) + icon_state = "spacedragon" + using_special = FALSE + +/** + * 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. + * Depowered simply resets him back to his default state. + */ +/mob/living/simple_animal/hostile/space_dragon/proc/rift_empower(is_empowered) + if(is_empowered) + fully_heal() + color = "#FF0000" + set_varspeed(-0.5) + addtimer(CALLBACK(src, .proc/rift_empower, FALSE), 300) + else + color = "#FFFFFF" + set_varspeed(0) + +/** + * 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. + */ +/mob/living/simple_animal/hostile/space_dragon/proc/destroy_rifts() + for(var/obj/structure/carp_rift/rift in rift_list) + rift.dragon = null + rift_list -= rift + if(!QDELETED(rift)) + QDEL_NULL(rift) + rifts_charged = 0 + +/** + * Handles wing gust from the windup all the way to the endlag at the end. + * + * Handles the wing gust attack from start to finish, based on the timer. + * When intially triggered, starts at 0. Until the timer reaches 10, increase Space Dragon's y position by 2 and call back to the function in 1.5 deciseconds. + * When the timer is at 10, trigger the attack. Change Space Dragon's sprite. reset his y position, and push all living creatures back in a 3 tile radius and stun them for 5 seconds. + * Stay in the ending state for how much our tiredness dictates and add to our tiredness. + * Arguments: + * * timer - The timer used for the windup. + */ +/mob/living/simple_animal/hostile/space_dragon/proc/useGust(timer) + if(timer != 10) + pixel_y = pixel_y + 2; + addtimer(CALLBACK(src, .proc/useGust, timer + 1), 1.5) + return + pixel_y = 0 + icon_state = "spacedragon_gust_2" + playsound(src, 'sound/effects/gravhit.ogg', 100, TRUE) + var/gust_locs = spiral_range_turfs(3, get_turf(src)) + var/list/hit_things = list() + for(var/turf/T in gust_locs) + for(var/mob/living/L in T.contents) + if(L == src) + continue + hit_things += L + visible_message("[L] is knocked back by the gust!") + to_chat(L, "You're knocked back by the gust!") + var/dir_to_target = get_dir(get_turf(src), get_turf(L)) + var/throwtarget = get_edge_target_turf(target, dir_to_target) + L.safe_throw_at(throwtarget, 10, 1, src) + L.Paralyze(50) + addtimer(CALLBACK(src, .proc/reset_status), 4 + ((tiredness * tiredness_mult) / 10)) + tiredness = tiredness + (30 * 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 + 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 + sound_to_playing_players('sound/machines/alarm.ogg') + sleep(100) + priority_announce("A large amount of lifeforms have been detected approaching [station_name()] at extreme speeds. Evacuation of the remamining crew will begin immediately.", "Central Command Spacial Corps") + sleep(50) + SSshuttle.emergency.request(null, set_coefficient = 0.3) + +/datum/action/innate/space_dragon + background_icon_state = "bg_default" + icon_icon = 'icons/mob/actions/actions_space_dragon.dmi' + +/datum/action/innate/space_dragon/gustAttack + name = "Gust Attack" + button_icon_state = "gust_attack" + desc = "Use your wings to knock back foes with gusts of air, pushing them away and stunning them. Using this too often will leave you vulnerable for longer periods of time." + +/datum/action/innate/space_dragon/gustAttack/Activate() + var/mob/living/simple_animal/hostile/space_dragon/S = owner + if(S.using_special) + return + S.using_special = TRUE + S.icon_state = "spacedragon_gust" + S.useGust(0) + +/datum/action/innate/space_dragon/summonRift + name = "Summon Rift" + button_icon_state = "carp_rift" + desc = "Summon a rift to bring forth a horde of space carp." + +/datum/action/innate/space_dragon/summonRift/Activate() + var/mob/living/simple_animal/hostile/space_dragon/S = owner + if(S.using_special) + return + var/area/A = get_area(S) + if(!A.valid_territory) + to_chat(S, "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, "You've already summoned a rift in this area! You have to summon again somewhere else!") + return + to_chat(S, "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, "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" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + max_integrity = 300 + icon = 'icons/obj/carp_rift.dmi' + icon_state = "carp_rift" + light_color = LIGHT_COLOR_BLUE + light_range = 10 + anchored = TRUE + density = FALSE + /// The amount of time the rift has charged for. + var/time_charged = 0 + /// The maximum charge the rift can have. It actually goes to max_charge + 1, as to prevent constantly retriggering the effects on full charge. + var/max_charge = 240 + /// How many carp spawns it has available. + var/carp_stored = 0 + /// A reference to the Space Dragon that created it. + var/mob/living/simple_animal/hostile/space_dragon/dragon + +/obj/structure/carp_rift/Initialize(mapload) + . = ..() + carp_stored = 1 + time_charged = 1 + START_PROCESSING(SSobj, src) + +/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) + to_chat(dragon, "The rift has been destroyed! You have failed, and find yourself brought down by the weight of your failure.") + dragon.set_varspeed(5) + dragon.tiredness_mult = 5 + dragon.destroy_rifts() + playsound(src, 'sound/vehicles/rocketlaunch.ogg', 100, TRUE) + return ..() + +/obj/structure/carp_rift/process() + time_charged = min(time_charged + 1, max_charge + 1) + update_check() + for(var/mob/living/simple_animal/hostile/hostilehere in loc) + if("carp" in hostilehere.faction) + hostilehere.adjustHealth(-10) + var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(hostilehere)) + H.color = "#0000FF" + if(time_charged < max_charge) + desc = "A rift akin to the ones space carp use to travel long distances. It seems to be [(time_charged / max_charge) * 100]% charged." + if(carp_stored == 0) + icon_state = "carp_rift" + light_color = LIGHT_COLOR_BLUE + else + icon_state = "carp_rift_carpspawn" + light_color = LIGHT_COLOR_PURPLE + else + var/spawncarp = rand(1,40) + if(spawncarp == 1) + new /mob/living/simple_animal/hostile/carp(loc) + +/obj/structure/carp_rift/attack_ghost(mob/user) + . = ..() + 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 40, 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(time_charged % 40 == 0 && time_charged != max_charge) + carp_stored++ + notify_ghosts("The carp rift can summon an additional carp!", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Carp Spawn Available") + if(time_charged == (max_charge - 120)) + var/area/A = get_area(src) + priority_announce("A rift is causing an unnaturally large energy flux in [A.map_name]. Stop it at all costs!", "Central Command Spacial Corps", 'sound/ai/spanomalies.ogg') + if(time_charged == max_charge) + var/area/A = get_area(src) + priority_announce("Spatial object has reached peak energy charge in [A.map_name], please stand-by.", "Central Command Spacial Corps") + obj_integrity = INFINITY + desc = "A rift akin to the ones space carp use to travel long distances. This one is fully charged, and is capable of bringing many carp to the station's location." + icon_state = "carp_rift_charged" + light_color = LIGHT_COLOR_YELLOW + armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + resistance_flags = INDESTRUCTIBLE + dragon.rifts_charged += 1 + if(dragon.rifts_charged != 3) + dragon.rift = new + dragon.rift.Grant(dragon) + dragon.riftTimer = 0 + dragon.rift_empower(TRUE) + +/** + * 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/carp_ask = alert("Become a carp?", "Help bring forth the horde?", "Yes", "No") + if(carp_ask == "No" || !src || QDELETED(src) || QDELETED(user)) + return FALSE + if(carp_stored == 0) + to_chat(user, "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.key = user.key + var/datum/antagonist/space_dragon/S = dragon.mind.has_antag_datum(/datum/antagonist/space_dragon) + if(S) + S.carp += newcarp.mind + to_chat(newcarp, "You have arrived in order to assist the space dragon with securing the rift. Do not jeopardize the mission, and protect the rift at all costs!") + carp_stored -= 1 + return TRUE \ No newline at end of file diff --git a/icons/mob/actions/actions_space_dragon.dmi b/icons/mob/actions/actions_space_dragon.dmi new file mode 100644 index 0000000000000000000000000000000000000000..a4e33eef1eb2595726197ba77f747577a53b4054 GIT binary patch literal 959 zcmV;w13>(VP)V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRLOex7wuvIWN;^NFm z%}mcIfpCgT5=&AQY!#G}6N?Jsi!#$nl(;xkGK-28Y!wW-IMa#}b5kK~Wd&D17X=qz zPc8twU>n5_N#LLW00Rd}L_t(oh3%G4XcJi+$3Mw5Gi^GF=AUgs?6zVHrOjH4E)+yi zPkIqSH`h4|%c2K8h~mLZ_prCcv$@G^4;}2+)#!6!oYjK`MvM^ym@cldyaa&&U(tZuDyQ?0A1}ij3+qXT2~c*X~)N5cMZf7 zc!1ya#f8z$~8VosR3swz%t^RuU+I}F=$h9O( zQxH$^2hjKO!IdM;n3hgb&OQUcy=fRvWDM%>0T`S-Fau;%g_xZZ{3A|>#nstLF}Qjv|u_I+W^2c;LpuJ+yh`}Il5{Uva^?YS6%sNBK9E4A>_yy zk|#uAAvx@ij%x7)AypywC39PgaHWvKD5lBIUZz&jSgkIzT3x1A(WvS4_IvSVi-z)WJVzq0_M95herBtZYf!Sw~`g#HJx1+ZEz z<8u3O2qKak#NiZhI0Ym*h~({~x?JcifcEAIfsx&~gF|=+CK25}M7Iy2+e_cJgZ%sO z5&+$v;45GSm@)ITvK5~Le)Db`dQ{5JPn7fXNE^b4y#cy6MgVZReJnn`g|s0IK>zSh z_kohCaNEq>^b0ih@?-w!=)KU;#7zLn6GD44hn`NNr<1G{Uek;>atgpH3xl&Z1*(Fs zDjeBmvhen2Szdd@i+#0eUThcQx){j*x3hY(M`c6Rh(U-?hr)eNDQZ| z2XFL81hGdSoIG$5_|wWgps98)rF#J-{q*i0LtlylNV0DsJTi3yNT>?e?fBW=2O1rm z43A7*^#ljz0Ky|vcY&ha&f5ZLKxBa9fr0VA0zbs=087B>cD$(9>tFT!e4&2+Yuejh h1OK(Yud|>N`T(kOUAI_@?NI;#002ovPDHLkV1ma%zKZ|= literal 0 HcmV?d00001 diff --git a/icons/mob/spacedragon.dmi b/icons/mob/spacedragon.dmi index 4549ea9ea283a27903386ca375f559b72d99d8b5..a1f3d4d782bc9d69b9332df425ada45f83e08c0a 100644 GIT binary patch literal 6712 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 delta 5448 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 diff --git a/icons/obj/carp_rift.dmi b/icons/obj/carp_rift.dmi new file mode 100644 index 0000000000000000000000000000000000000000..9a07b3b16f866b919b3a997a6c44a6cb1d204e98 GIT binary patch literal 4319 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 literal 0 HcmV?d00001 diff --git a/sound/ai/spanomalies.ogg b/sound/ai/spanomalies.ogg new file mode 100644 index 0000000000000000000000000000000000000000..7680726f15336b80b1b8d9ac6b223c56924badbe GIT binary patch literal 40469 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 literal 0 HcmV?d00001 diff --git a/yogstation.dme b/yogstation.dme index 005a7affed43..434908c962d4 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -2509,6 +2509,7 @@ #include "code\modules\mob\living\simple_animal\hostile\russian.dm" #include "code\modules\mob\living\simple_animal\hostile\skeleton.dm" #include "code\modules\mob\living\simple_animal\hostile\smspider.dm" +#include "code\modules\mob\living\simple_animal\hostile\space_dragon.dm" #include "code\modules\mob\living\simple_animal\hostile\statue.dm" #include "code\modules\mob\living\simple_animal\hostile\stickman.dm" #include "code\modules\mob\living\simple_animal\hostile\syndicate.dm" From 9c31c5baea007010392b8da79807bfc60fb293e6 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Tue, 12 Apr 2022 08:06:42 +0300 Subject: [PATCH 02/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 96dff232c165..7add4e77afdd 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -39,8 +39,6 @@ pixel_x = -16 turns_per_move = 5 spacewalk = TRUE - spacewalk = TRUE - spacewalk = TRUE ranged = TRUE mouse_opacity = MOUSE_OPACITY_ICON butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30) @@ -530,4 +528,4 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) S.carp += newcarp.mind to_chat(newcarp, "You have arrived in order to assist the space dragon with securing the rift. Do not jeopardize the mission, and protect the rift at all costs!") carp_stored -= 1 - return TRUE \ No newline at end of file + return TRUE From af21da0a112ad5c0fd5b3f447c43217d8c930284 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Sun, 17 Apr 2022 08:05:40 +0300 Subject: [PATCH 03/36] Update code/modules/events/space_dragon.dm Co-authored-by: Jamie D <993128+JamieD1@users.noreply.github.com> --- code/modules/events/space_dragon.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/events/space_dragon.dm b/code/modules/events/space_dragon.dm index 918e98d62472..5343a0637970 100644 --- a/code/modules/events/space_dragon.dm +++ b/code/modules/events/space_dragon.dm @@ -5,7 +5,6 @@ weight = 8 weight = 5 earliest_start = 35 MINUTES - /datum/round_event/ghost_role/space_dragon minimum_required = 1 role_name = "Space Dragon" From e4ee1c6bf5d33cfd1de0ea6fc79196d8d33a72f8 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Sun, 17 Apr 2022 08:07:41 +0300 Subject: [PATCH 04/36] Update space_dragon.dm --- code/modules/events/space_dragon.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/events/space_dragon.dm b/code/modules/events/space_dragon.dm index 5343a0637970..fffa1c71180e 100644 --- a/code/modules/events/space_dragon.dm +++ b/code/modules/events/space_dragon.dm @@ -2,9 +2,10 @@ name = "Spawn Space Dragon" typepath = /datum/round_event/ghost_role/space_dragon max_occurrences = 1 - weight = 8 weight = 5 earliest_start = 35 MINUTES + min_players = 30 + /datum/round_event/ghost_role/space_dragon minimum_required = 1 role_name = "Space Dragon" From 9a2dcd5a83ae7ce689a44656199bad16eaa4d7d7 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Sun, 17 Apr 2022 14:43:33 +0300 Subject: [PATCH 05/36] Update space_dragon.dm --- code/modules/events/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/events/space_dragon.dm b/code/modules/events/space_dragon.dm index fffa1c71180e..4924f3b4405b 100644 --- a/code/modules/events/space_dragon.dm +++ b/code/modules/events/space_dragon.dm @@ -4,7 +4,7 @@ max_occurrences = 1 weight = 5 earliest_start = 35 MINUTES - min_players = 30 + min_players = 30 /datum/round_event/ghost_role/space_dragon minimum_required = 1 From 92f65fdba25e0dead1b0f493a07477d879019215 Mon Sep 17 00:00:00 2001 From: Jamie D <993128+JamieD1@users.noreply.github.com> Date: Thu, 21 Apr 2022 14:09:06 +0100 Subject: [PATCH 06/36] Update code/modules/events/space_dragon.dm --- code/modules/events/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/events/space_dragon.dm b/code/modules/events/space_dragon.dm index 4924f3b4405b..2e9237d0cc70 100644 --- a/code/modules/events/space_dragon.dm +++ b/code/modules/events/space_dragon.dm @@ -3,7 +3,7 @@ typepath = /datum/round_event/ghost_role/space_dragon max_occurrences = 1 weight = 5 - earliest_start = 35 MINUTES + earliest_start = 60 MINUTES min_players = 30 /datum/round_event/ghost_role/space_dragon From 62098b557062d67e5c10e3fdbc61c192506408fa Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 18 May 2022 16:21:10 +0300 Subject: [PATCH 07/36] Work normally please --- .../simple_animal/hostile/space_dragon.dm | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 7add4e77afdd..718aca642dd8 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -1,3 +1,6 @@ +/// The darkness threshold for space dragon when choosing a color + #define DARKNESS_THRESHOLD 0.5 + /** * # Space Dragon * @@ -71,6 +74,9 @@ /// The innate ability to summon rifts var/datum/action/innate/space_dragon/summonRift/rift + /// The color of the space dragon. + var/chosen_color + /mob/living/simple_animal/hostile/space_dragon/Initialize(mapload) . = ..() if(small_sprite_type) @@ -81,9 +87,23 @@ rift = new rift.Grant(src) +/mob/living/simple_animal/hostile/space_dragon/Login() + . = ..() + if(!chosen_color) + dragon_name() + color_selection() + /mob/living/simple_animal/hostile/space_dragon/Life(mapload) . = ..() tiredness = max(tiredness - 1, 0) + for(var/mob/living/consumed_mob in src) + if(consumed_mob.stat == DEAD) + continue + playsound(src, 'sound/effects/splat.ogg', 50, TRUE) + visible_message("[src] vomits up [consumed_mob]!") + consumed_mob.forceMove(loc) + consumed_mob.Paralyze(50) + if(rifts_charged == 3 && !objective_complete) victory() if(riftTimer == -1) @@ -95,6 +115,8 @@ if(riftTimer == maxRiftTimer) to_chat(src, "You've failed to summon the rift in a timely manner! You're being pulled back from whence you came!") destroy_rifts() + add_overlay() + QDEL_NULL(src) /mob/living/simple_animal/hostile/space_dragon/AttackingTarget() @@ -529,3 +551,62 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) to_chat(newcarp, "You have arrived in order to assist the space dragon with securing the rift. Do not jeopardize the mission, and protect the rift at all costs!") carp_stored -= 1 return TRUE + +/** + * Allows space dragon to choose its own name. + * + * Prompts the space dragon to choose a name, which it will then apply to itself. + * If the name is invalid, will re-prompt the dragon until a proper name is chosen. + */ + /mob/living/simple_animal/hostile/space_dragon/proc/dragon_name() + var/chosen_name = sanitize_name(reject_bad_text(stripped_input(src, "What would you like your name to be?", "Choose Your Name", real_name, MAX_NAME_LEN))) + if(!chosen_name) + to_chat(src, "Not a valid name, please try again.") + dragon_name() + return + visible_message("Your name is now [chosen_name], the feared Space Dragon.") + fully_replace_character_name(null, chosen_name) + + /** + * Allows space dragon to choose a color for itself. + * + * Prompts the space dragon to choose a color, from which it will then apply to itself. + * If an invalid color is given, will re-prompt the dragon until a proper color is chosen. + */ + /mob/living/simple_animal/hostile/space_dragon/proc/color_selection() + chosen_color = input(src,"What would you like your color to be?","Choose Your Color", COLOR_WHITE) as color|null + if(!chosen_color) //redo proc until we get a color + to_chat(src, "Not a valid color, please try again.") + color_selection() + return + var/temp_hsv = RGBtoHSV(chosen_color) + if(chosen_color == COLOR_BLACK) + chosen_color = COLOR_WHITE + else if(ReadHSV(temp_hsv)[3] < DARKNESS_THRESHOLD) + to_chat(src, "Invalid color. Your color is not bright enough.") + color_selection() + return + add_atom_colour(chosen_color, FIXED_COLOUR_PRIORITY) + add_dragon_overlay() + + /** + * Adds the proper overlay to the space dragon. + * + * Clears the current overlay on space dragon and adds a proper one for whatever animation he's in. + */ + /mob/living/simple_animal/hostile/space_dragon/proc/add_dragon_overlay() + cut_overlays() + if(stat == DEAD) + var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_dead") + overlay.appearance_flags = RESET_COLOR + add_overlay(overlay) + return + if(!using_special) + var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_base") + overlay.appearance_flags = RESET_COLOR + add_overlay(overlay) + return + if(using_special) + var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_gust") + overlay.appearance_flags = RESET_COLOR + add_overlay(overlay) From cfcb351036b92220b7ee1a60062ac214f086ff29 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 18 May 2022 16:26:04 +0300 Subject: [PATCH 08/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 718aca642dd8..5030a362ee15 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -1,5 +1,5 @@ /// The darkness threshold for space dragon when choosing a color - #define DARKNESS_THRESHOLD 0.5 +#define DARKNESS_THRESHOLD 0.5 /** * # Space Dragon From f4b77bd100bc516d63260e7764f9da0893e0a328 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 18 May 2022 16:31:41 +0300 Subject: [PATCH 09/36] Update space_dragon.dm --- .../modules/mob/living/simple_animal/hostile/space_dragon.dm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 5030a362ee15..571f345a2fa0 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -67,6 +67,8 @@ var/rifts_charged = 0 /// Whether or not Space Dragon has completed their objective, and thus triggered the ending sequence. var/objective_complete = FALSE + /// The color of the space dragon. + var/chosen_color /// The togglable small sprite action var/small_sprite_type = /datum/action/small_sprite/megafauna/spacedragon /// The innate ability to use wing gust @@ -74,9 +76,6 @@ /// The innate ability to summon rifts var/datum/action/innate/space_dragon/summonRift/rift - /// The color of the space dragon. - var/chosen_color - /mob/living/simple_animal/hostile/space_dragon/Initialize(mapload) . = ..() if(small_sprite_type) From b5b2397bfa0e80fb991928f9192ecc1e145a19ee Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 18 May 2022 16:35:32 +0300 Subject: [PATCH 10/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 571f345a2fa0..f3f3f9cf702e 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -67,8 +67,10 @@ var/rifts_charged = 0 /// Whether or not Space Dragon has completed their objective, and thus triggered the ending sequence. var/objective_complete = FALSE - /// The color of the space dragon. + + /// The color of the space dragon.dragon. var/chosen_color + /// The togglable small sprite action var/small_sprite_type = /datum/action/small_sprite/megafauna/spacedragon /// The innate ability to use wing gust From a78c7628fcd33c798b70cf865f90dde4b898234b Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 18 May 2022 16:39:03 +0300 Subject: [PATCH 11/36] Update space_dragon.dm --- .../mob/living/simple_animal/hostile/space_dragon.dm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index f3f3f9cf702e..87b75b7d9249 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -51,6 +51,8 @@ maxbodytemp = 1500 faction = list("carp") pressure_resistance = 200 + /// The color of the space dragon.dragon. + var/chosen_color /// 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. @@ -67,10 +69,6 @@ var/rifts_charged = 0 /// Whether or not Space Dragon has completed their objective, and thus triggered the ending sequence. var/objective_complete = FALSE - - /// The color of the space dragon.dragon. - var/chosen_color - /// The togglable small sprite action var/small_sprite_type = /datum/action/small_sprite/megafauna/spacedragon /// The innate ability to use wing gust From 733929bc7e7afb7fe1e474c0a2e1eb6af7350c5a Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 18 May 2022 16:43:12 +0300 Subject: [PATCH 12/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 87b75b7d9249..8f86014f475d 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -51,7 +51,6 @@ maxbodytemp = 1500 faction = list("carp") pressure_resistance = 200 - /// The color of the space dragon.dragon. var/chosen_color /// Current time since the the last rift was activated. If set to -1, does not increment. var/riftTimer = 0 From fde841974cd00ec2f661fe2898ac61466089fa79 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 18 May 2022 16:57:15 +0300 Subject: [PATCH 13/36] Update code/modules/mob/living/simple_animal/hostile/space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 8f86014f475d..aabe12a0e64b 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -557,7 +557,7 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) * If the name is invalid, will re-prompt the dragon until a proper name is chosen. */ /mob/living/simple_animal/hostile/space_dragon/proc/dragon_name() - var/chosen_name = sanitize_name(reject_bad_text(stripped_input(src, "What would you like your name to be?", "Choose Your Name", real_name, MAX_NAME_LEN))) + var/chosen_name = reject_bad_text(stripped_input(src, "What would you like your name to be?", "Choose Your Name", real_name, MAX_NAME_LEN)) if(!chosen_name) to_chat(src, "Not a valid name, please try again.") dragon_name() From 85861626592c96ed02070d25aeb5c93601140d3b Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 08:06:40 +0300 Subject: [PATCH 14/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index aabe12a0e64b..92d94841db0a 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -113,8 +113,7 @@ if(riftTimer == maxRiftTimer) to_chat(src, "You've failed to summon the rift in a timely manner! You're being pulled back from whence you came!") destroy_rifts() - add_overlay() - + add_overlay() QDEL_NULL(src) /mob/living/simple_animal/hostile/space_dragon/AttackingTarget() From 86795773cb8c5c2930dacd4b33261ef0c010e89c Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 08:08:03 +0300 Subject: [PATCH 15/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 92d94841db0a..826388134c14 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -113,8 +113,8 @@ if(riftTimer == maxRiftTimer) to_chat(src, "You've failed to summon the rift in a timely manner! You're being pulled back from whence you came!") destroy_rifts() - add_overlay() QDEL_NULL(src) + add_overlay() /mob/living/simple_animal/hostile/space_dragon/AttackingTarget() if(using_special) From 1b13159df22d02fe3f2c6a3a90c01069126432e2 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 08:13:14 +0300 Subject: [PATCH 16/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 826388134c14..ac4a5136fb9a 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -51,6 +51,7 @@ maxbodytemp = 1500 faction = list("carp") pressure_resistance = 200 + var/chosen_color /// Current time since the the last rift was activated. If set to -1, does not increment. var/riftTimer = 0 From 415ca20df555b55d654100310c46943c8bb1aa0d Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 15:10:40 +0300 Subject: [PATCH 17/36] Update space_dragon.dm --- .../mob/living/simple_animal/hostile/space_dragon.dm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index ac4a5136fb9a..8bfb5ec3ee54 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -52,7 +52,7 @@ faction = list("carp") pressure_resistance = 200 - var/chosen_color + var/picked_color /// 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. @@ -572,19 +572,19 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) * If an invalid color is given, will re-prompt the dragon until a proper color is chosen. */ /mob/living/simple_animal/hostile/space_dragon/proc/color_selection() - chosen_color = input(src,"What would you like your color to be?","Choose Your Color", COLOR_WHITE) as color|null - if(!chosen_color) //redo proc until we get a color + picked_color = input(src,"What would you like your color to be?","Choose Your Color", COLOR_WHITE) as color|null + if(!picked_color) //redo proc until we get a color to_chat(src, "Not a valid color, please try again.") color_selection() return var/temp_hsv = RGBtoHSV(chosen_color) - if(chosen_color == COLOR_BLACK) - chosen_color = COLOR_WHITE + if(picked_color == COLOR_BLACK) + picked_color = COLOR_WHITE else if(ReadHSV(temp_hsv)[3] < DARKNESS_THRESHOLD) to_chat(src, "Invalid color. Your color is not bright enough.") color_selection() return - add_atom_colour(chosen_color, FIXED_COLOUR_PRIORITY) + add_atom_colour(picked_color, FIXED_COLOUR_PRIORITY) add_dragon_overlay() /** From e6053e6174e7be0a875c14b6de70118cf27b9c31 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 15:17:09 +0300 Subject: [PATCH 18/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 8bfb5ec3ee54..b51ce2375e7d 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -608,3 +608,6 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_gust") overlay.appearance_flags = RESET_COLOR add_overlay(overlay) + + +#undefine DARKNESS_THRESHOLD From f5dea2e36847cf668821a5290a65e319558ecb91 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 15:19:50 +0300 Subject: [PATCH 19/36] Update code/modules/mob/living/simple_animal/hostile/space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index b51ce2375e7d..3438e276f45b 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -88,7 +88,7 @@ /mob/living/simple_animal/hostile/space_dragon/Login() . = ..() - if(!chosen_color) + if(!picked_color) dragon_name() color_selection() From a39e844f3291090b6e364b967bfd56bbd27efba6 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 17:41:31 +0300 Subject: [PATCH 20/36] Update space_dragon.dm --- .../simple_animal/hostile/space_dragon.dm | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 3438e276f45b..5dcabc559cd1 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -1,5 +1,5 @@ /// The darkness threshold for space dragon when choosing a color -#define DARKNESS_THRESHOLD 0.5 +///#define DARKNESS_THRESHOLD 0.5 /** * # Space Dragon @@ -52,7 +52,7 @@ faction = list("carp") pressure_resistance = 200 - var/picked_color + ///var/picked_color /// 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. @@ -88,9 +88,9 @@ /mob/living/simple_animal/hostile/space_dragon/Login() . = ..() - if(!picked_color) - dragon_name() - color_selection() + ///if(!picked_color) + dragon_name() + ///color_selection() /mob/living/simple_animal/hostile/space_dragon/Life(mapload) . = ..() @@ -571,21 +571,22 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) * Prompts the space dragon to choose a color, from which it will then apply to itself. * If an invalid color is given, will re-prompt the dragon until a proper color is chosen. */ - /mob/living/simple_animal/hostile/space_dragon/proc/color_selection() - picked_color = input(src,"What would you like your color to be?","Choose Your Color", COLOR_WHITE) as color|null - if(!picked_color) //redo proc until we get a color - to_chat(src, "Not a valid color, please try again.") - color_selection() - return - var/temp_hsv = RGBtoHSV(chosen_color) - if(picked_color == COLOR_BLACK) - picked_color = COLOR_WHITE - else if(ReadHSV(temp_hsv)[3] < DARKNESS_THRESHOLD) - to_chat(src, "Invalid color. Your color is not bright enough.") - color_selection() - return - add_atom_colour(picked_color, FIXED_COLOUR_PRIORITY) - add_dragon_overlay() +///Commented untill i will find the way to fucking fix this shit +/// /mob/living/simple_animal/hostile/space_dragon/proc/color_selection() + ///picked_color = input(src,"What would you like your color to be?","Choose Your Color", COLOR_WHITE) as color|null + ///if(!picked_color) //redo proc until we get a color + ///to_chat(src, "Not a valid color, please try again.") + ///color_selection() + ///return + ///var/temp_hsv = RGBtoHSV(chosen_color) + ///if(picked_color == COLOR_BLACK) + ///picked_color = COLOR_WHITE + ///else if(ReadHSV(temp_hsv)[3] < DARKNESS_THRESHOLD) + ///to_chat(src, "Invalid color. Your color is not bright enough.") + ///color_selection() + ///return + ///add_atom_colour(picked_color, FIXED_COLOUR_PRIORITY) + ///add_dragon_overlay() /** * Adds the proper overlay to the space dragon. @@ -610,4 +611,4 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) add_overlay(overlay) -#undefine DARKNESS_THRESHOLD +///#undefine DARKNESS_THRESHOLD From 681e416e3fc80d0a0d7961a6558add0dace466a9 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 17:47:06 +0300 Subject: [PATCH 21/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 5dcabc559cd1..079deb3a9fbb 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -556,7 +556,7 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) * Prompts the space dragon to choose a name, which it will then apply to itself. * If the name is invalid, will re-prompt the dragon until a proper name is chosen. */ - /mob/living/simple_animal/hostile/space_dragon/proc/dragon_name() +/mob/living/simple_animal/hostile/space_dragon/proc/dragon_name() var/chosen_name = reject_bad_text(stripped_input(src, "What would you like your name to be?", "Choose Your Name", real_name, MAX_NAME_LEN)) if(!chosen_name) to_chat(src, "Not a valid name, please try again.") From 6cfd8230191b92e2b1395463b2fba04f5a648d99 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 17:49:10 +0300 Subject: [PATCH 22/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 079deb3a9fbb..fb1958221c71 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -97,7 +97,7 @@ tiredness = max(tiredness - 1, 0) for(var/mob/living/consumed_mob in src) if(consumed_mob.stat == DEAD) - continue + continue playsound(src, 'sound/effects/splat.ogg', 50, TRUE) visible_message("[src] vomits up [consumed_mob]!") consumed_mob.forceMove(loc) From 4df8df777881add2b5aa316e13ff926aa3ff5556 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Thu, 19 May 2022 17:55:03 +0300 Subject: [PATCH 23/36] Update code/modules/mob/living/simple_animal/hostile/space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index fb1958221c71..079deb3a9fbb 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -97,7 +97,7 @@ tiredness = max(tiredness - 1, 0) for(var/mob/living/consumed_mob in src) if(consumed_mob.stat == DEAD) - continue + continue playsound(src, 'sound/effects/splat.ogg', 50, TRUE) visible_message("[src] vomits up [consumed_mob]!") consumed_mob.forceMove(loc) From 31e2a5ed21d370fbafb652d428b7e084071ea050 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Fri, 20 May 2022 10:29:32 +0300 Subject: [PATCH 24/36] Update space_dragon.dm --- .../simple_animal/hostile/space_dragon.dm | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 079deb3a9fbb..7add4e77afdd 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -1,6 +1,3 @@ -/// The darkness threshold for space dragon when choosing a color -///#define DARKNESS_THRESHOLD 0.5 - /** * # Space Dragon * @@ -51,8 +48,6 @@ maxbodytemp = 1500 faction = list("carp") pressure_resistance = 200 - - ///var/picked_color /// 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. @@ -86,23 +81,9 @@ rift = new rift.Grant(src) -/mob/living/simple_animal/hostile/space_dragon/Login() - . = ..() - ///if(!picked_color) - dragon_name() - ///color_selection() - /mob/living/simple_animal/hostile/space_dragon/Life(mapload) . = ..() tiredness = max(tiredness - 1, 0) - for(var/mob/living/consumed_mob in src) - if(consumed_mob.stat == DEAD) - continue - playsound(src, 'sound/effects/splat.ogg', 50, TRUE) - visible_message("[src] vomits up [consumed_mob]!") - consumed_mob.forceMove(loc) - consumed_mob.Paralyze(50) - if(rifts_charged == 3 && !objective_complete) victory() if(riftTimer == -1) @@ -115,7 +96,6 @@ to_chat(src, "You've failed to summon the rift in a timely manner! You're being pulled back from whence you came!") destroy_rifts() QDEL_NULL(src) - add_overlay() /mob/living/simple_animal/hostile/space_dragon/AttackingTarget() if(using_special) @@ -549,66 +529,3 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) to_chat(newcarp, "You have arrived in order to assist the space dragon with securing the rift. Do not jeopardize the mission, and protect the rift at all costs!") carp_stored -= 1 return TRUE - -/** - * Allows space dragon to choose its own name. - * - * Prompts the space dragon to choose a name, which it will then apply to itself. - * If the name is invalid, will re-prompt the dragon until a proper name is chosen. - */ -/mob/living/simple_animal/hostile/space_dragon/proc/dragon_name() - var/chosen_name = reject_bad_text(stripped_input(src, "What would you like your name to be?", "Choose Your Name", real_name, MAX_NAME_LEN)) - if(!chosen_name) - to_chat(src, "Not a valid name, please try again.") - dragon_name() - return - visible_message("Your name is now [chosen_name], the feared Space Dragon.") - fully_replace_character_name(null, chosen_name) - - /** - * Allows space dragon to choose a color for itself. - * - * Prompts the space dragon to choose a color, from which it will then apply to itself. - * If an invalid color is given, will re-prompt the dragon until a proper color is chosen. - */ -///Commented untill i will find the way to fucking fix this shit -/// /mob/living/simple_animal/hostile/space_dragon/proc/color_selection() - ///picked_color = input(src,"What would you like your color to be?","Choose Your Color", COLOR_WHITE) as color|null - ///if(!picked_color) //redo proc until we get a color - ///to_chat(src, "Not a valid color, please try again.") - ///color_selection() - ///return - ///var/temp_hsv = RGBtoHSV(chosen_color) - ///if(picked_color == COLOR_BLACK) - ///picked_color = COLOR_WHITE - ///else if(ReadHSV(temp_hsv)[3] < DARKNESS_THRESHOLD) - ///to_chat(src, "Invalid color. Your color is not bright enough.") - ///color_selection() - ///return - ///add_atom_colour(picked_color, FIXED_COLOUR_PRIORITY) - ///add_dragon_overlay() - - /** - * Adds the proper overlay to the space dragon. - * - * Clears the current overlay on space dragon and adds a proper one for whatever animation he's in. - */ - /mob/living/simple_animal/hostile/space_dragon/proc/add_dragon_overlay() - cut_overlays() - if(stat == DEAD) - var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_dead") - overlay.appearance_flags = RESET_COLOR - add_overlay(overlay) - return - if(!using_special) - var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_base") - overlay.appearance_flags = RESET_COLOR - add_overlay(overlay) - return - if(using_special) - var/mutable_appearance/overlay = mutable_appearance(icon, "overlay_gust") - overlay.appearance_flags = RESET_COLOR - add_overlay(overlay) - - -///#undefine DARKNESS_THRESHOLD From 45a1f7c5cb652d370627aa6026357ed9cbb2fefe Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Fri, 20 May 2022 12:17:17 +0300 Subject: [PATCH 25/36] Update space_dragon.dm --- .../simple_animal/hostile/space_dragon.dm | 102 ++++++++++++------ 1 file changed, 72 insertions(+), 30 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 7add4e77afdd..33d8862b434f 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -1,3 +1,10 @@ +/// 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 + /** * # Space Dragon * @@ -24,6 +31,7 @@ a_intent = INTENT_HARM speed = 0 attacktext = "chomps" + mob_size = MOB_SIZE_LARGE attack_sound = 'sound/magic/demon_attack1.ogg' deathsound = 'sound/magic/demon_dies.ogg' icon = 'icons/mob/spacedragon.dmi' @@ -347,7 +355,7 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) main_objective.completed = TRUE sound_to_playing_players('sound/machines/alarm.ogg') sleep(100) - priority_announce("A large amount of lifeforms have been detected approaching [station_name()] at extreme speeds. Evacuation of the remamining crew will begin immediately.", "Central Command Spacial Corps") + priority_announce("A large amount of lifeforms have been detected approaching [station_name()] at extreme speeds. Evacuation of the remamining crew will begin immediately.", "Central Command Spatial Corps") sleep(50) SSshuttle.emergency.request(null, set_coefficient = 0.3) @@ -415,23 +423,36 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) max_integrity = 300 icon = 'icons/obj/carp_rift.dmi' icon_state = "carp_rift" - light_color = LIGHT_COLOR_BLUE + light_color = LIGHT_COLOR_PURPLE light_range = 10 anchored = TRUE density = FALSE /// The amount of time the rift has charged for. var/time_charged = 0 - /// The maximum charge the rift can have. It actually goes to max_charge + 1, as to prevent constantly retriggering the effects on full charge. + /// The maximum charge the rift can have. var/max_charge = 240 /// How many carp spawns it has available. - var/carp_stored = 0 + 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 time since an extra carp was added to the ghost role spawning pool. + var/last_carp_inc = 0 + +/obj/structure/carp_rift/examine(mob/user) + . = ..() + if(time_charged < max_charge) + . += "It seems to be [(time_charged / max_charge) * 100]% charged." + else + . += "This one is fully charged, and is capable of bringing many carp to the station's location." + + if(isobserver(user)) + . += "It has [carp_stored] carp available to spawn as." + /obj/structure/carp_rift/Initialize(mapload) . = ..() - carp_stored = 1 - time_charged = 1 START_PROCESSING(SSobj, src) /obj/structure/carp_rift/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) @@ -448,25 +469,20 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) return ..() /obj/structure/carp_rift/process() - time_charged = min(time_charged + 1, max_charge + 1) - update_check() for(var/mob/living/simple_animal/hostile/hostilehere in loc) if("carp" in hostilehere.faction) hostilehere.adjustHealth(-10) var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(hostilehere)) H.color = "#0000FF" - if(time_charged < max_charge) - desc = "A rift akin to the ones space carp use to travel long distances. It seems to be [(time_charged / max_charge) * 100]% charged." - if(carp_stored == 0) - icon_state = "carp_rift" - light_color = LIGHT_COLOR_BLUE - else - icon_state = "carp_rift_carpspawn" - light_color = LIGHT_COLOR_PURPLE - else - var/spawncarp = rand(1,40) - if(spawncarp == 1) - new /mob/living/simple_animal/hostile/carp(loc) + // If we're fully charged, just start mass spawning carp. + if(charge_state == CHARGE_COMPLETED && DT_PROB(1.25, delta_time)) + new /mob/living/simple_animal/hostile/carp(loc) + 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) . = ..() @@ -481,19 +497,28 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) * 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(time_charged % 40 == 0 && time_charged != max_charge) + // 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 >= 40) 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") - if(time_charged == (max_charge - 120)) - var/area/A = get_area(src) - priority_announce("A rift is causing an unnaturally large energy flux in [A.map_name]. Stop it at all costs!", "Central Command Spacial Corps", 'sound/ai/spanomalies.ogg') - if(time_charged == max_charge) + last_carp_inc -= 40 + + // 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 [A.map_name], please stand-by.", "Central Command Spacial Corps") obj_integrity = INFINITY - desc = "A rift akin to the ones space carp use to travel long distances. This one is fully charged, and is capable of bringing many carp to the station's location." icon_state = "carp_rift_charged" - light_color = LIGHT_COLOR_YELLOW + set_light_color(LIGHT_COLOR_YELLOW) + update_light() armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) resistance_flags = INDESTRUCTIBLE dragon.rifts_charged += 1 @@ -502,6 +527,15 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) dragon.rift.Grant(dragon) dragon.riftTimer = 0 dragon.rift_empower(TRUE) + // 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 Spatial Corps", 'sound/ai/spanomalies.ogg') + /** * Used to create carp controlled by ghosts when the option is available. @@ -513,12 +547,12 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) * * 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 + if(carp_stored <= 0)//Not enough carp points return FALSE var/carp_ask = alert("Become a carp?", "Help bring forth the horde?", "Yes", "No") if(carp_ask == "No" || !src || QDELETED(src) || QDELETED(user)) return FALSE - if(carp_stored == 0) + if(carp_stored <= 0) to_chat(user, "The rift already summoned enough carp!") return FALSE var/mob/living/simple_animal/hostile/carp/newcarp = new /mob/living/simple_animal/hostile/carp(loc) @@ -527,5 +561,13 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) if(S) S.carp += newcarp.mind to_chat(newcarp, "You have arrived in order to assist the space dragon with securing the rift. Do not jeopardize the mission, and protect the rift at all costs!") - carp_stored -= 1 + 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 From 7b1c980c09e804f02bf14ec43c566f57983bb322 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Fri, 20 May 2022 12:22:39 +0300 Subject: [PATCH 26/36] Update space_dragon.dm --- .../simple_animal/hostile/space_dragon.dm | 103 ++++++------------ 1 file changed, 31 insertions(+), 72 deletions(-) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 33d8862b434f..ad86459e44c6 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -1,10 +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 - /** * # Space Dragon * @@ -31,7 +24,6 @@ a_intent = INTENT_HARM speed = 0 attacktext = "chomps" - mob_size = MOB_SIZE_LARGE attack_sound = 'sound/magic/demon_attack1.ogg' deathsound = 'sound/magic/demon_dies.ogg' icon = 'icons/mob/spacedragon.dmi' @@ -41,6 +33,7 @@ obj_damage = 50 environment_smash = ENVIRONMENT_SMASH_NONE flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1 + mob_size = MOB_SIZE_LARGE melee_damage_upper = 35 melee_damage_lower = 35 armour_penetration = 30 @@ -355,7 +348,7 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) main_objective.completed = TRUE sound_to_playing_players('sound/machines/alarm.ogg') sleep(100) - priority_announce("A large amount of lifeforms have been detected approaching [station_name()] at extreme speeds. Evacuation of the remamining crew will begin immediately.", "Central Command Spatial Corps") + priority_announce("A large amount of lifeforms have been detected approaching [station_name()] at extreme speeds. Evacuation of the remamining crew will begin immediately.", "Central Command Spacial Corps") sleep(50) SSshuttle.emergency.request(null, set_coefficient = 0.3) @@ -423,36 +416,23 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) max_integrity = 300 icon = 'icons/obj/carp_rift.dmi' icon_state = "carp_rift" - light_color = LIGHT_COLOR_PURPLE + light_color = LIGHT_COLOR_BLUE light_range = 10 anchored = TRUE density = FALSE /// The amount of time the rift has charged for. var/time_charged = 0 - /// The maximum charge the rift can have. + /// The maximum charge the rift can have. It actually goes to max_charge + 1, as to prevent constantly retriggering the effects on full charge. var/max_charge = 240 /// How many carp spawns it has available. - var/carp_stored = 1 + var/carp_stored = 0 /// 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 time since an extra carp was added to the ghost role spawning pool. - var/last_carp_inc = 0 - -/obj/structure/carp_rift/examine(mob/user) - . = ..() - if(time_charged < max_charge) - . += "It seems to be [(time_charged / max_charge) * 100]% charged." - else - . += "This one is fully charged, and is capable of bringing many carp to the station's location." - - if(isobserver(user)) - . += "It has [carp_stored] carp available to spawn as." - /obj/structure/carp_rift/Initialize(mapload) . = ..() + carp_stored = 1 + time_charged = 1 START_PROCESSING(SSobj, src) /obj/structure/carp_rift/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) @@ -469,20 +449,25 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) return ..() /obj/structure/carp_rift/process() + time_charged = min(time_charged + 1, max_charge + 1) + update_check() for(var/mob/living/simple_animal/hostile/hostilehere in loc) if("carp" in hostilehere.faction) hostilehere.adjustHealth(-10) var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(hostilehere)) H.color = "#0000FF" - // If we're fully charged, just start mass spawning carp. - if(charge_state == CHARGE_COMPLETED && DT_PROB(1.25, delta_time)) - new /mob/living/simple_animal/hostile/carp(loc) - 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() + if(time_charged < max_charge) + desc = "A rift akin to the ones space carp use to travel long distances. It seems to be [(time_charged / max_charge) * 100]% charged." + if(carp_stored == 0) + icon_state = "carp_rift" + light_color = LIGHT_COLOR_BLUE + else + icon_state = "carp_rift_carpspawn" + light_color = LIGHT_COLOR_PURPLE + else + var/spawncarp = rand(1,40) + if(spawncarp == 1) + new /mob/living/simple_animal/hostile/carp(loc) /obj/structure/carp_rift/attack_ghost(mob/user) . = ..() @@ -497,28 +482,19 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) * 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 >= 40) + if(time_charged % 40 == 0 && time_charged != max_charge) 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 -= 40 - - // Is the rift now fully charged? - if(time_charged >= max_charge) - charge_state = CHARGE_COMPLETED + if(time_charged == (max_charge - 120)) + var/area/A = get_area(src) + priority_announce("A rift is causing an unnaturally large energy flux in [A.map_name]. Stop it at all costs!", "Central Command Spacial Corps", 'sound/ai/spanomalies.ogg') + if(time_charged == max_charge) var/area/A = get_area(src) priority_announce("Spatial object has reached peak energy charge in [A.map_name], please stand-by.", "Central Command Spacial Corps") obj_integrity = INFINITY + desc = "A rift akin to the ones space carp use to travel long distances. This one is fully charged, and is capable of bringing many carp to the station's location." icon_state = "carp_rift_charged" - set_light_color(LIGHT_COLOR_YELLOW) - update_light() + light_color = LIGHT_COLOR_YELLOW armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) resistance_flags = INDESTRUCTIBLE dragon.rifts_charged += 1 @@ -527,15 +503,6 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) dragon.rift.Grant(dragon) dragon.riftTimer = 0 dragon.rift_empower(TRUE) - // 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 Spatial Corps", 'sound/ai/spanomalies.ogg') - /** * Used to create carp controlled by ghosts when the option is available. @@ -547,12 +514,12 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) * * 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 + if(carp_stored == 0)//Not enough carp points return FALSE var/carp_ask = alert("Become a carp?", "Help bring forth the horde?", "Yes", "No") if(carp_ask == "No" || !src || QDELETED(src) || QDELETED(user)) return FALSE - if(carp_stored <= 0) + if(carp_stored == 0) to_chat(user, "The rift already summoned enough carp!") return FALSE var/mob/living/simple_animal/hostile/carp/newcarp = new /mob/living/simple_animal/hostile/carp(loc) @@ -561,13 +528,5 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) if(S) S.carp += newcarp.mind to_chat(newcarp, "You have arrived in order to assist the space dragon with securing the rift. Do not jeopardize the mission, and protect the rift 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() + carp_stored -= 1 return TRUE - -#undef CHARGE_ONGOING -#undef CHARGE_FINALWARNING -#undef CHARGE_COMPLETED From 57c6e4b320839a8175faedb8a131befeb88b7477 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Fri, 20 May 2022 13:30:36 +0300 Subject: [PATCH 27/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index ad86459e44c6..cca435353082 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -349,6 +349,8 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) sound_to_playing_players('sound/machines/alarm.ogg') sleep(100) priority_announce("A large amount of lifeforms have been detected approaching [station_name()] at extreme speeds. Evacuation of the remamining crew will begin immediately.", "Central Command Spacial Corps") + for(var/obj/structure/carp_rift/rift in rift_list) + rift.carp_stored = 999999 sleep(50) SSshuttle.emergency.request(null, set_coefficient = 0.3) @@ -420,6 +422,7 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) light_range = 10 anchored = TRUE density = FALSE + layer = MASSIVE_OBJ_LAYER /// The amount of time the rift has charged for. var/time_charged = 0 /// The maximum charge the rift can have. It actually goes to max_charge + 1, as to prevent constantly retriggering the effects on full charge. From 79f290cabd5f18ffc12ba66ec029a83da5c08bb2 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Fri, 20 May 2022 16:28:40 +0300 Subject: [PATCH 28/36] Carpdragon hide --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index cca435353082..95a85c79dbe1 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -43,6 +43,7 @@ ranged = TRUE mouse_opacity = MOUSE_OPACITY_ICON 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/carpdragon = 10) deathmessage = "screeches as its wings turn to dust and it collapses on the floor, life estinguished." atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 From 1076f4f92de9abe5e2f08199c5e2df0ac3d99a7b Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:13:05 +0300 Subject: [PATCH 29/36] Update code/modules/antagonists/space_dragon/space_dragon.dm Co-authored-by: Anvilman6 <54463777+Anvilman6@users.noreply.github.com> --- code/modules/antagonists/space_dragon/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/antagonists/space_dragon/space_dragon.dm b/code/modules/antagonists/space_dragon/space_dragon.dm index 627ab7dfb4fa..12c63e60a857 100644 --- a/code/modules/antagonists/space_dragon/space_dragon.dm +++ b/code/modules/antagonists/space_dragon/space_dragon.dm @@ -9,7 +9,7 @@ /datum/antagonist/space_dragon/greet() to_chat(owner, "Endless time and space we have moved through. We do not remember from where we came, we do not know where we will go. All space belongs to us.\n\ - Space is an empty void, of which our kind is the apex predator, and there was little to rival our claim to this title.\n\ + Space is an empty void, in which our kind is the apex predator, and there is little to rival our claim to this title.\n\ But now, we find intruders spread out amongst our claim, willing to fight our teeth with magics unimaginable, their dens like lights flicking in the depths of space.\n\ Today, we will snuff out one of those lights.") to_chat(owner, "You have five minutes to find a safe location to place down the first rift. If you take longer than five minutes to place a rift, you will be returned from whence you came.") From e7d9fe5ff40003c7940ae8410d79e2935340b7f0 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:13:18 +0300 Subject: [PATCH 30/36] Update code/modules/antagonists/space_dragon/space_dragon.dm Co-authored-by: Anvilman6 <54463777+Anvilman6@users.noreply.github.com> --- code/modules/antagonists/space_dragon/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/antagonists/space_dragon/space_dragon.dm b/code/modules/antagonists/space_dragon/space_dragon.dm index 12c63e60a857..cc6568f81ddc 100644 --- a/code/modules/antagonists/space_dragon/space_dragon.dm +++ b/code/modules/antagonists/space_dragon/space_dragon.dm @@ -10,7 +10,7 @@ /datum/antagonist/space_dragon/greet() to_chat(owner, "Endless time and space we have moved through. We do not remember from where we came, we do not know where we will go. All space belongs to us.\n\ Space is an empty void, in which our kind is the apex predator, and there is little to rival our claim to this title.\n\ - But now, we find intruders spread out amongst our claim, willing to fight our teeth with magics unimaginable, their dens like lights flicking in the depths of space.\n\ + But now, we find intruders spread out amongst our claim! They are willing to fight our teeth with magics unimaginable, in their strange metal dens flickering in the depths of space.\n\ Today, we will snuff out one of those lights.") to_chat(owner, "You have five minutes to find a safe location to place down the first rift. If you take longer than five minutes to place a rift, you will be returned from whence you came.") owner.announce_objectives() From 44be8878dda6ea23be9fee0799c9281b395f2b7f Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:13:25 +0300 Subject: [PATCH 31/36] Update code/modules/antagonists/space_dragon/space_dragon.dm Co-authored-by: Anvilman6 <54463777+Anvilman6@users.noreply.github.com> --- code/modules/antagonists/space_dragon/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/antagonists/space_dragon/space_dragon.dm b/code/modules/antagonists/space_dragon/space_dragon.dm index cc6568f81ddc..502067004df8 100644 --- a/code/modules/antagonists/space_dragon/space_dragon.dm +++ b/code/modules/antagonists/space_dragon/space_dragon.dm @@ -11,7 +11,7 @@ to_chat(owner, "Endless time and space we have moved through. We do not remember from where we came, we do not know where we will go. All space belongs to us.\n\ Space is an empty void, in which our kind is the apex predator, and there is little to rival our claim to this title.\n\ But now, we find intruders spread out amongst our claim! They are willing to fight our teeth with magics unimaginable, in their strange metal dens flickering in the depths of space.\n\ - Today, we will snuff out one of those lights.") + Today, we will remind them of our power.") to_chat(owner, "You have five minutes to find a safe location to place down the first rift. If you take longer than five minutes to place a rift, you will be returned from whence you came.") owner.announce_objectives() SEND_SOUND(owner.current, sound('sound/magic/demon_attack1.ogg')) From 170b20b467745714a620e3c8545ef725a18a0423 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:13:31 +0300 Subject: [PATCH 32/36] Update code/modules/events/space_dragon.dm Co-authored-by: Anvilman6 <54463777+Anvilman6@users.noreply.github.com> --- code/modules/events/space_dragon.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/events/space_dragon.dm b/code/modules/events/space_dragon.dm index 2e9237d0cc70..6b43677d18c8 100644 --- a/code/modules/events/space_dragon.dm +++ b/code/modules/events/space_dragon.dm @@ -12,7 +12,7 @@ announceWhen = 10 /datum/round_event/ghost_role/space_dragon/announce(fake) - priority_announce("A large organic energy flux has been recorded near of [station_name()], please stand-by.", "Lifesign Alert") + priority_announce("A large organic energy flux has been recorded in the vicinity of [station_name()], please stand-by.", "Lifesign Alert") /datum/round_event/ghost_role/space_dragon/spawn_role() var/list/candidates = get_candidates(ROLE_SPACE_DRAGON, null, ROLE_SPACE_DRAGON) From 6748972285cf420908970b1b6c0ce6c949cec3a8 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Wed, 15 Jun 2022 21:13:40 +0300 Subject: [PATCH 33/36] Update code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm Co-authored-by: Anvilman6 <54463777+Anvilman6@users.noreply.github.com> --- code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index a0d255b896c4..18b22a97b8bf 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -505,7 +505,7 @@ playsound(S, 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1) message_admins("[ADMIN_LOOKUPFLW(S)] has been made into a Space Dragon by the midround ruleset.") log_game("DYNAMIC: [key_name(S)] was spawned as a Space Dragon by the midround ruleset.") - priority_announce("A large organic energy flux has been recorded near of [station_name()], please stand-by.", "Lifesign Alert") + priority_announce("A large organic energy flux has been recorded in the vicinity of [station_name()], please stand-by.", "Lifesign Alert") return S ////////////////////////////////////////////// From 428eeded80d3de129317f092b0751808210737dd Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Mon, 27 Jun 2022 14:10:42 +0300 Subject: [PATCH 34/36] Update space_dragon.dm --- code/modules/mob/living/simple_animal/hostile/space_dragon.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index 95a85c79dbe1..cfe46c3b079b 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -21,6 +21,7 @@ desc = "A vile leviathan-esque creature that flies in the most unnatural way. Slightly looks similar to a space carp." maxHealth = 400 health = 400 + health_doll_icon = "spacedragon" a_intent = INTENT_HARM speed = 0 attacktext = "chomps" From 5f56bf6c57b4125ea2c982b3c33e871e2c0cbd93 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Mon, 27 Jun 2022 14:45:51 +0300 Subject: [PATCH 35/36] #61539 --- .../living/simple_animal/animal_defense.dm | 40 +++++++++++++------ .../simple_animal/hostile/space_dragon.dm | 14 +++++++ 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 9acf14f480e8..3703a7a17488 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -136,22 +136,36 @@ var/bomb_armor = getarmor(null, "bomb") switch (severity) if (EXPLODE_DEVASTATE) - if(prob(bomb_armor)) - adjustBruteLoss(500) - else - gib() - return + ex_act_devastate() if (EXPLODE_HEAVY) - var/bloss = 60 - if(prob(bomb_armor)) - bloss = bloss / 1.5 - adjustBruteLoss(bloss) + ex_act_heavy() if (EXPLODE_LIGHT) - var/bloss = 30 - if(prob(bomb_armor)) - bloss = bloss / 1.5 - adjustBruteLoss(bloss) + ex_act_light() + +/// Called when a devastating explosive acts on this mob +/mob/living/simple_animal/proc/ex_act_devastate() + var/bomb_armor = getarmor(null, BOMB) + if(prob(bomb_armor)) + adjustBruteLoss(500) + else + gib() + +/// Called when a heavy explosive acts on this mob +/mob/living/simple_animal/proc/ex_act_heavy() + var/bomb_armor = getarmor(null, BOMB) + var/bloss = 60 + if(prob(bomb_armor)) + bloss = bloss / 1.5 + adjustBruteLoss(bloss) + +/// Called when a light explosive acts on this mob +/mob/living/simple_animal/proc/ex_act_light() + var/bomb_armor = getarmor(null, BOMB) + var/bloss = 30 + if(prob(bomb_armor)) + bloss = bloss / 1.5 + adjustBruteLoss(bloss) /mob/living/simple_animal/blob_act(obj/structure/blob/B) adjustBruteLoss(20) diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm index cfe46c3b079b..7f98cf25f52f 100644 --- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm +++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm @@ -73,6 +73,10 @@ var/datum/action/innate/space_dragon/gustAttack/gust /// The innate ability to summon rifts var/datum/action/innate/space_dragon/summonRift/rift + /// Minimum devastation damage dealt coefficient based on max health + var/devastation_damage_min_percentage = 0.4 + /// Maximum devastation damage dealt coefficient based on max health + var/devastation_damage_max_percentage = 0.75 /mob/living/simple_animal/hostile/space_dragon/Initialize(mapload) . = ..() @@ -100,6 +104,10 @@ destroy_rifts() QDEL_NULL(src) +/mob/living/simple_animal/hostile/space_dragon/ex_act_devastate() + var/damage_coefficient = rand(devastation_damage_min_percentage, devastation_damage_max_percentage) + adjustBruteLoss(initial(maxHealth)*damage_coefficient) + /mob/living/simple_animal/hostile/space_dragon/AttackingTarget() if(using_special) return @@ -535,3 +543,9 @@ mob/living/simple_animal/hostile/space_dragon/proc/dragon_fire_line(turf/T) to_chat(newcarp, "You have arrived in order to assist the space dragon with securing the rift. Do not jeopardize the mission, and protect the rift at all costs!") carp_stored -= 1 return TRUE + +// 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)) \ No newline at end of file From 0ac81e10a467d31d4240172bba129305298985e1 Mon Sep 17 00:00:00 2001 From: SuperSlayer <91609255+TymurShatillo@users.noreply.github.com> Date: Mon, 27 Jun 2022 14:54:14 +0300 Subject: [PATCH 36/36] Update animal_defense.dm --- code/modules/mob/living/simple_animal/animal_defense.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 3703a7a17488..763ef6b0a97b 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -133,7 +133,6 @@ ..() if(QDELETED(src)) return - var/bomb_armor = getarmor(null, "bomb") switch (severity) if (EXPLODE_DEVASTATE) ex_act_devastate()