diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 8de2255c79..ea1397b680 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -376,6 +376,9 @@ // Hellhound strain flags #define HELLHOUND_NORMAL "Normal" +// Boss strain flags +#define BOSS_NORMAL "Normal" + var/list/default_onmob_icons = list( WEAR_L_HAND = 'icons/mob/humans/onmob/items_lefthand_0.dmi', WEAR_R_HAND = 'icons/mob/humans/onmob/items_righthand_0.dmi', diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index 878a591357..f6b1253b0e 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -650,6 +650,8 @@ #define ALL_XENO_CASTES list(XENO_CASTE_LARVA, XENO_CASTE_PREDALIEN_LARVA, XENO_CASTE_FACEHUGGER, XENO_CASTE_LESSER_DRONE, XENO_CASTE_DRONE, XENO_CASTE_RUNNER, XENO_CASTE_SENTINEL, XENO_CASTE_DEFENDER, XENO_CASTE_BURROWER, XENO_CASTE_CARRIER, XENO_CASTE_HIVELORD, XENO_CASTE_LURKER, XENO_CASTE_WARRIOR, XENO_CASTE_SPITTER, XENO_CASTE_BOILER, XENO_CASTE_PRAETORIAN, XENO_CASTE_CRUSHER, XENO_CASTE_RAVAGER, XENO_CASTE_QUEEN, XENO_CASTE_PREDALIEN, XENO_CASTE_HELLHOUND) +#define XENO_CASTE_XENOSURGE_BOSS_BOT "Interceptor" + // Checks if two hives are allied to each other. // PARAMETERS: // source_hive integer the hive to check the alliance of diff --git a/code/game/objects/effects/decals/cleanable/blood/blood.dm b/code/game/objects/effects/decals/cleanable/blood/blood.dm index 918797608b..aa5c0172af 100644 --- a/code/game/objects/effects/decals/cleanable/blood/blood.dm +++ b/code/game/objects/effects/decals/cleanable/blood/blood.dm @@ -178,3 +178,6 @@ if (step_to(src, get_step(src, direction), 0)) break + +/obj/effect/decal/cleanable/blood/oil + basecolor = "#220707" diff --git a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm index f27616508d..97962e340a 100644 --- a/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm +++ b/code/modules/mob/living/carbon/xenomorph/Xenomorph.dm @@ -343,6 +343,14 @@ var/atom/movable/vis_obj/xeno_wounds/wound_icon_holder var/atom/movable/vis_obj/xeno_pack/backpack_icon_holder + //Xenosurge vars that go here for same reasons as above + var/boss_type = 0 + //below should be safely disregarded if type is not set to 1 + var/boss_stage = 1 + var/explosion_damage = 30 + var/aoe_delay = 40 + var/missile_storm_missiles = 25 + /mob/living/carbon/xenomorph/Initialize(mapload, mob/living/carbon/xenomorph/oldXeno, h_number, ai_hard_off = FALSE) var/area/A = get_area(src) if(A && A.statistic_exempt) @@ -1054,7 +1062,7 @@ . = ..() if (. & IGNITE_IGNITED) RegisterSignal(src, COMSIG_XENO_PRE_HEAL, PROC_REF(cancel_heal)) - if(!caste || !(caste.fire_immunity & FIRE_IMMUNITY_NO_DAMAGE) || fire_reagent.fire_penetrating) + if(!caste || !(caste.fire_immunity & FIRE_IMMUNITY_NO_DAMAGE) || fire_reagent.fire_penetrating||boss_type == 1) INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "roar") /mob/living/carbon/xenomorph/ExtinguishMob() diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/boss/boss_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/boss/boss_abilities.dm new file mode 100644 index 0000000000..cebc4119d0 --- /dev/null +++ b/code/modules/mob/living/carbon/xenomorph/abilities/boss/boss_abilities.dm @@ -0,0 +1,22 @@ +/datum/action/xeno_action/activable/surge_proj + name = "Living Target Sweep" + action_icon_state = "runner_bonespur" + ability_name = "Living Target Sweep" + macro_path = /datum/action/xeno_action/verb/surge_proj + action_type = XENO_ACTION_CLICK + ability_primacy = XENO_PRIMARY_ACTION_1 + xeno_cooldown = 60 + plasma_cost = 0 + + var/ammo_type = /datum/ammo/xeno/surge_proj + + +/datum/action/xeno_action/activable/rapid_missles + name = "Missile Barrage" + action_icon_state = "runner_bonespur" + ability_name = "missile barrage" + macro_path = /datum/action/xeno_action/verb/rapid_missles + action_type = XENO_ACTION_CLICK + ability_primacy = XENO_PRIMARY_ACTION_2 + xeno_cooldown = 60 + plasma_cost = 0 diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/boss/boss_macros.dm b/code/modules/mob/living/carbon/xenomorph/abilities/boss/boss_macros.dm new file mode 100644 index 0000000000..5d1d204f7f --- /dev/null +++ b/code/modules/mob/living/carbon/xenomorph/abilities/boss/boss_macros.dm @@ -0,0 +1,13 @@ +/datum/action/xeno_action/verb/surge_proj() + set category = "Alien" + set name = "Living Target Sweep" + set hidden = TRUE + var/action_name = "Living Target Sweep" + handle_xeno_macro(src, action_name) + +/datum/action/xeno_action/verb/rapid_missles() + set category = "Alien" + set name = "Missile Barrage" + set hidden = TRUE + var/action_name = "Missile Barrage" + handle_xeno_macro(src, action_name) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/boss/boss_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/boss/boss_powers.dm new file mode 100644 index 0000000000..0580ea2f25 --- /dev/null +++ b/code/modules/mob/living/carbon/xenomorph/abilities/boss/boss_powers.dm @@ -0,0 +1,161 @@ +/mob/living/carbon/human/proc/warning_ping() + to_chat(src, SPAN_BOLDWARNING("A Surge is targeting you with a special attack!")) + overlays += (image('icons/effects/surge_hit_warning.dmi', "aoe")) + sleep(40) + overlays -= (image('icons/effects/surge_hit_warning.dmi', "aoe")) + +/datum/action/xeno_action/activable/surge_proj/use_ability(atom/affected_atom) + var/mob/living/carbon/xenomorph/xeno = owner + if (!istype(xeno)) + return + + if (!action_cooldown_check()) + return + var/list/mobs_in_range = list() + for(var/mob/living/carbon/human/target in range("15x15",xeno)) + if(mobs_in_range.Find(target) == 0) + mobs_in_range.Add(target) + if(mobs_in_range.len == 0) + to_chat(xeno, SPAN_WARNING("No potential targets in visible range")) + return + for(var/mob/living/carbon/human/target_to_warn in mobs_in_range) + INVOKE_ASYNC(target_to_warn, TYPE_PROC_REF(/mob/living/carbon/human/, warning_ping)) + xeno.overlays += (image('icons/effects/surge_hit_warning_64.dmi', "aoe_surge")) + xeno.anchored = 1 + if(xeno.armor_deflection > 20) xeno.armor_deflection = 20 + sleep(xeno.aoe_delay) + xeno.overlays -= (image('icons/effects/surge_hit_warning_64.dmi', "aoe_surge")) + xeno.anchored = 0 + xeno.armor_deflection = initial(xeno.armor_deflection) + var/list/mobs_in_view = list() + for(var/mob/living/carbon/human/target in view("15x15",xeno)) + if(mobs_in_view.Find(target) == 0) + mobs_in_view.Add(target) + for(var/mob/living/carbon/human/target_to_shoot in mobs_in_range) + if(mobs_in_view.Find(target_to_shoot) != 0) + var/turf/target = get_turf(target_to_shoot) + var/obj/projectile/projectile = new /obj/projectile(xeno.loc, create_cause_data(initial(xeno.caste_type), xeno)) + var/datum/ammo/ammo_datum = GLOB.ammo_list[ammo_type] + projectile.generate_bullet(ammo_datum) + projectile.fire_at(target, xeno, xeno, ammo_datum.max_range, ammo_datum.shell_speed) + apply_cooldown() + return ..() + +/obj/item/prop/big_warning_ping + name = "warning ping" + opacity = FALSE + mouse_opacity = FALSE + anchored = TRUE + indestructible = TRUE + layer = ABOVE_MOB_LAYER + pixel_x = -80 + pixel_y = -80 + icon = 'icons/effects/surge_hit_warning_160.dmi' + icon_state = "big_boom" + +/turf/proc/warning_ping() + var/obj/item/prop/big_warning_ping/ping = new(src) + sleep(60) + qdel(ping) + +/obj/item/prop/missile_storm_up + name = "going up" + opacity = FALSE + mouse_opacity = FALSE + anchored = TRUE + indestructible = TRUE + layer = ABOVE_MOB_LAYER + icon = 'icons/effects/missile_storm.dmi' + icon_state = "up" + + +/obj/item/prop/missile_storm_up/proc/animate_takeoff() + animate(src,pixel_y=384,time = 10,easing=QUAD_EASING|EASE_IN) + sleep(11) + qdel(src) + +/obj/item/prop/missile_storm_up/Initialize(mapload, ...) + . = ..() + pixel_x = pick(-8,-2,2,8) + INVOKE_ASYNC(src, TYPE_PROC_REF(/obj/item/prop/missile_storm_up/, animate_takeoff)) + +/obj/item/prop/missile_storm_down + name = "going down" + opacity = FALSE + mouse_opacity = FALSE + anchored = TRUE + indestructible = TRUE + layer = ABOVE_MOB_LAYER + icon = 'icons/effects/missile_storm.dmi' + icon_state = "down" + + +/obj/item/prop/missile_storm_down/proc/animate_landing() + animate(src,pixel_y=0,time = 10,easing=QUAD_EASING|EASE_IN) + sleep(11) + qdel(src) + +/obj/item/prop/missile_storm_down/Initialize(mapload, ...) + . = ..() + pixel_y = 384 + pixel_x = pick(-8,-2,2,8) + INVOKE_ASYNC(src, TYPE_PROC_REF(/obj/item/prop/missile_storm_down/, animate_landing)) + +/datum/action/xeno_action/activable/rapid_missles/proc/fire_animation() + var/mob/living/carbon/xenomorph/xeno = owner + var/spawned_props = 1 + var/sound_cycle = 0 + while(spawned_props <= xeno.missile_storm_missiles) + var/turf/owner_turf = get_turf(owner) + if(sound_cycle == 8) sound_cycle = 0 + if(sound_cycle == 0) playsound(owner_turf,'sound/surge/rockets_launching.ogg', 80) + new /obj/item/prop/missile_storm_up(owner_turf) + spawned_props += 1 + sleep(2) + sound_cycle += 2 + xeno.armor_deflection = 100 + xeno.anchored = FALSE + +/datum/action/xeno_action/activable/rapid_missles/proc/hit_animation(turf/turf_to_hit_animate) + var/mob/living/carbon/xenomorph/xeno = owner + new /obj/item/prop/missile_storm_down(turf_to_hit_animate) + sleep(13) + var/datum/cause_data/cause_data = create_cause_data("surge bombardment") + cell_explosion(turf_to_hit_animate, xeno.explosion_damage, (xeno.explosion_damage / 2), EXPLOSION_FALLOFF_SHAPE_LINEAR, null, cause_data) + + +/datum/action/xeno_action/activable/rapid_missles/proc/fire_loop(turf/target_turf) + var/list/turfs_to_hit = list() + for (var/turf/turf in range("5x5", target_turf)) + if(turfs_to_hit.Find(turf) == 0) + turfs_to_hit += turf + while(turfs_to_hit.len > 0) + var/turf/turf_to_hit = pick(turfs_to_hit) + turfs_to_hit -= turf_to_hit + INVOKE_ASYNC(src, TYPE_PROC_REF(/datum/action/xeno_action/activable/rapid_missles, hit_animation), turf_to_hit) + sleep(rand(1,5)) + +/datum/action/xeno_action/activable/rapid_missles/use_ability(atom/affected_atom) + var/mob/living/carbon/xenomorph/xeno = owner + if (!istype(xeno)) + return + if (!action_cooldown_check()) + return + var/turf/turf_center = get_turf(affected_atom) + var/list/mobs_in_range = list() + xeno.anchored = 1 + if(xeno.armor_deflection > 20) xeno.armor_deflection = 20 + for(var/mob/living/carbon/human/target in range("15x15",turf_center)) + if(mobs_in_range.Find(target) == 0) + mobs_in_range.Add(target) + if(mobs_in_range.len != 0) + to_chat(mobs_in_range,SPAN_BOLDWARNING("The [usr] launches a series of rockets into the air! Look out for impact markers!")) + INVOKE_ASYNC(src, TYPE_PROC_REF(/datum/action/xeno_action/activable/rapid_missles, fire_animation)) + turf_center.warning_ping() + INVOKE_ASYNC(src, TYPE_PROC_REF(/datum/action/xeno_action/activable/rapid_missles, fire_loop), turf_center) + sleep(100) + xeno.anchored = 0 + xeno.armor_deflection = initial(xeno.armor_deflection) + + apply_cooldown() + return ..() diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_abilities.dm index 7b6a15b44f..88b227144d 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_abilities.dm @@ -53,25 +53,3 @@ var/minimal_acid = 200 -/datum/action/xeno_action/activable/surge_proj - name = "Surge - Projectile AOE" - action_icon_state = "runner_bonespur" - ability_name = "surge aoe proj" - macro_path = /datum/action/xeno_action/verb/surge_proj - action_type = XENO_ACTION_CLICK - ability_primacy = XENO_PRIMARY_ACTION_2 - xeno_cooldown = 60 - plasma_cost = 0 - - var/ammo_type = /datum/ammo/xeno/surge_proj - - -/datum/action/xeno_action/activable/rapid_missles - name = "Missile Barrage" - action_icon_state = "runner_bonespur" - ability_name = "missile barrage" - macro_path = /datum/action/xeno_action/verb/rapid_missles - action_type = XENO_ACTION_CLICK - ability_primacy = XENO_PRIMARY_ACTION_2 - xeno_cooldown = 60 - plasma_cost = 0 diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_macros.dm b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_macros.dm index 52b767667f..6f6475bd7e 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_macros.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_macros.dm @@ -26,16 +26,3 @@ var/action_name = "For the Hive!" handle_xeno_macro(src, action_name) -/datum/action/xeno_action/verb/surge_proj() - set category = "Alien" - set name = "Surge AoE" - set hidden = TRUE - var/action_name = "Surge AoE" - handle_xeno_macro(src, action_name) - -/datum/action/xeno_action/verb/rapid_missles() - set category = "Alien" - set name = "Missile Barrage" - set hidden = TRUE - var/action_name = "Missile Barrage" - handle_xeno_macro(src, action_name) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_powers.dm index 31e89d6fa9..06bf3e0e2e 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/runner/runner_powers.dm @@ -214,161 +214,3 @@ xeno.adjust_effect(behavior_delegate.caboom_timer * -2 - (behavior_delegate.caboom_timer - behavior_delegate.caboom_left + 2) * xeno.life_slow_reduction * 0.5, SUPERSLOW) to_chat(xeno, SPAN_XENOWARNING("You remove all your explosive acid before it combusted.")) - - -/mob/living/carbon/human/proc/warning_ping() - to_chat(src, SPAN_BOLDWARNING("A Surge is targeting you with a special attack!")) - overlays += (image('icons/effects/surge_hit_warning.dmi', "aoe")) - sleep(40) - overlays -= (image('icons/effects/surge_hit_warning.dmi', "aoe")) - -/datum/action/xeno_action/activable/surge_proj/use_ability(atom/affected_atom) - var/mob/living/carbon/xenomorph/xeno = owner - if (!istype(xeno)) - return - - if (!action_cooldown_check()) - return - var/list/mobs_in_range = list() - for(var/mob/living/carbon/human/target in range("15x15",xeno)) - if(mobs_in_range.Find(target) == 0) - mobs_in_range.Add(target) - if(mobs_in_range.len == 0) - to_chat(xeno, SPAN_WARNING("No potential targets in visible range")) - return - for(var/mob/living/carbon/human/target_to_warn in mobs_in_range) - INVOKE_ASYNC(target_to_warn, TYPE_PROC_REF(/mob/living/carbon/human/, warning_ping)) - xeno.overlays += (image('icons/effects/surge_hit_warning_64.dmi', "aoe_surge")) - xeno.anchored = 1 - xeno.armor_deflection = 200 - sleep(40) - xeno.overlays -= (image('icons/effects/surge_hit_warning_64.dmi', "aoe_surge")) - xeno.anchored = 0 - xeno.armor_deflection = initial(xeno.armor_deflection) - xeno.can_block_movement = 1 - var/list/mobs_in_view = list() - for(var/mob/living/carbon/human/target in view("15x15",xeno)) - if(mobs_in_view.Find(target) == 0) - mobs_in_view.Add(target) - for(var/mob/living/carbon/human/target_to_shoot in mobs_in_range) - if(mobs_in_view.Find(target_to_shoot) != 0) - var/turf/target = get_turf(target_to_shoot) - var/obj/projectile/projectile = new /obj/projectile(xeno.loc, create_cause_data(initial(xeno.caste_type), xeno)) - var/datum/ammo/ammo_datum = GLOB.ammo_list[ammo_type] - projectile.generate_bullet(ammo_datum) - projectile.fire_at(target, xeno, xeno, ammo_datum.max_range, ammo_datum.shell_speed) - apply_cooldown() - return ..() - -/obj/item/prop/big_warning_ping - name = "warning ping" - opacity = FALSE - mouse_opacity = FALSE - anchored = TRUE - indestructible = TRUE - layer = ABOVE_MOB_LAYER - pixel_x = -80 - pixel_y = -80 - icon = 'icons/effects/surge_hit_warning_160.dmi' - icon_state = "big_boom" - -/turf/proc/warning_ping() - var/obj/item/prop/big_warning_ping/ping = new(src) - sleep(60) - qdel(ping) - -/obj/item/prop/missile_storm_up - name = "going up" - opacity = FALSE - mouse_opacity = FALSE - anchored = TRUE - indestructible = TRUE - layer = ABOVE_MOB_LAYER - icon = 'icons/effects/missile_storm.dmi' - icon_state = "up" - - -/obj/item/prop/missile_storm_up/proc/animate_takeoff() - var/new_pixel_x = pixel_x + 48 - animate(src, pixel_x=new_pixel_x,pixel_y=384,time = 10,easing=QUAD_EASING|EASE_IN) - sleep(11) - qdel(src) - -/obj/item/prop/missile_storm_up/Initialize(mapload, ...) - . = ..() - pixel_x += rand(-10,10) - INVOKE_ASYNC(src, TYPE_PROC_REF(/obj/item/prop/missile_storm_up/, animate_takeoff)) - -/obj/item/prop/missile_storm_down - name = "going down" - opacity = FALSE - mouse_opacity = FALSE - anchored = TRUE - indestructible = TRUE - layer = ABOVE_MOB_LAYER - icon = 'icons/effects/missile_storm.dmi' - icon_state = "down" - - -/obj/item/prop/missile_storm_down/proc/animate_landing() - var/new_pixel_x = pixel_x + 48 - animate(src, pixel_x=new_pixel_x,pixel_y=0,time = 10,easing=QUAD_EASING|EASE_IN) - sleep(11) - qdel(src) - -/obj/item/prop/missile_storm_down/Initialize(mapload, ...) - . = ..() - pixel_y = 384 - pixel_x += rand(-10,10) - pixel_x -= -48 - INVOKE_ASYNC(src, TYPE_PROC_REF(/obj/item/prop/missile_storm_down/, animate_landing)) - -/datum/action/xeno_action/activable/rapid_missles/proc/fire_animation() - var/mob/living/carbon/xenomorph/xeno = owner - var/turf/owner_turf = get_turf(owner) - xeno.anchored = TRUE - xeno.armor_deflection = 100 - var/spawned_props = 1 - while(spawned_props <= 25) - new /obj/item/prop/missile_storm_up(owner_turf) - spawned_props += 1 - sleep(rand(1,3)) - xeno.armor_deflection = initial(xeno.armor_deflection) - xeno.anchored = FALSE - -/datum/action/xeno_action/activable/rapid_missles/proc/hit_animation(turf/turf_to_hit_animate) - new /obj/item/prop/missile_storm_down(turf_to_hit_animate) - sleep(13) - var/datum/cause_data/cause_data = create_cause_data("surge bombardment") - cell_explosion(turf_to_hit_animate, 50, 15, EXPLOSION_FALLOFF_SHAPE_LINEAR, null, cause_data) - - -/datum/action/xeno_action/activable/rapid_missles/proc/fire_loop(turf/target_turf) - var/list/turfs_to_hit = list() - for (var/turf/turf in range("5x5", target_turf)) - if(turfs_to_hit.Find(turf) == 0) - turfs_to_hit += turf - while(turfs_to_hit.len > 0) - var/turf/turf_to_hit = pick(turfs_to_hit) - turfs_to_hit -= turf_to_hit - INVOKE_ASYNC(src, TYPE_PROC_REF(/datum/action/xeno_action/activable/rapid_missles, hit_animation), turf_to_hit) - sleep(rand(1,5)) - -/datum/action/xeno_action/activable/rapid_missles/use_ability(atom/affected_atom) - var/mob/living/carbon/xenomorph/xeno = owner - if (!istype(xeno)) - return - if (!action_cooldown_check()) - return - var/turf/turf_center = get_turf(affected_atom) - var/list/mobs_in_range = list() - for(var/mob/living/carbon/human/target in range("15x15",turf_center)) - if(mobs_in_range.Find(target) == 0) - mobs_in_range.Add(target) - if(mobs_in_range.len != 0) - to_chat(mobs_in_range,SPAN_BOLDWARNING("The [usr] launches a series of rockets into the air! Look out for impact markers!")) - INVOKE_ASYNC(src, TYPE_PROC_REF(/datum/action/xeno_action/activable/rapid_missles, fire_animation)) - turf_center.warning_ping() - INVOKE_ASYNC(src, TYPE_PROC_REF(/datum/action/xeno_action/activable/rapid_missles, fire_loop), turf_center) - apply_cooldown() - return ..() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm index c128cc8b26..6e4660881e 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Runner.dm @@ -55,7 +55,7 @@ /datum/action/xeno_action/activable/tail_stab, /datum/action/xeno_action/onclick/xenohide, /datum/action/xeno_action/activable/pounce/runner, - /datum/action/xeno_action/activable/rapid_missles/, + /datum/action/xeno_action/activable/runner_skillshot, /datum/action/xeno_action/onclick/toggle_long_range/runner, /datum/action/xeno_action/onclick/tacmap, ) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/boss_bot.dm b/code/modules/mob/living/carbon/xenomorph/castes/boss_bot.dm new file mode 100644 index 0000000000..f3a688cac1 --- /dev/null +++ b/code/modules/mob/living/carbon/xenomorph/castes/boss_bot.dm @@ -0,0 +1,55 @@ +/datum/caste_datum/boss_bot + caste_type = XENO_CASTE_XENOSURGE_BOSS_BOT + caste_desc = "An agile defense platform, saturating the battlefield with defensive fire." + tier = 4 + melee_damage_lower = 25 + melee_damage_upper = 40 + melee_vehicle_damage = 40 + plasma_gain = XENO_PLASMA_GAIN_TIER_1 + plasma_max = XENO_NO_PLASMA + armor_deflection = 100 + max_health = 3000 + evasion = XENO_EVASION_NONE + speed = 1 + xeno_explosion_resistance = XENO_EXPLOSIVE_ARMOR_TIER_10 + fire_immunity = FIRE_IMMUNITY_NO_IGNITE + attack_delay = -4 + tackle_min = 4 + tackle_max = 5 + tackle_chance = 40 + tacklestrength_min = 4 + tacklestrength_max = 4 + minimap_icon = "runner" + + +/mob/living/carbon/xenomorph/boss_bot + caste_type = XENO_CASTE_XENOSURGE_BOSS_BOT + name = "BALTHEUS-6 Pursuit Wrepons Platform" + desc = "A heavilly modified automated weapons platform of unknown make." + icon = 'icons/Surge/boss_bot/boss.dmi' + icon_state = "Boss Walking" + icon_size = 64 + layer = MOB_LAYER + plasma_types = list(PLASMA_CATECHOLAMINE) + tier = 1 + pixel_x = -8 + old_x = -8 + base_pixel_x = 0 + base_pixel_y = 0 + pull_speed = -0.5 + viewsize = 12 + wall_smash = 1 + universal_understand = 1 + universal_speak = 1 + langchat_color = "#ff1313" + + + mob_size = MOB_SIZE_XENO_SMALL + + base_actions = list( + /datum/action/xeno_action/activable/surge_proj, + /datum/action/xeno_action/activable/rapid_missles/, + ) + mutation_type = BOSS_NORMAL + icon_xeno = 'icons/Surge/boss_bot/boss.dmi' + icon_xenonid = 'icons/Surge/boss_bot/boss.dmi' diff --git a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm index e372b03e68..f9df49000a 100644 --- a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm +++ b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm @@ -248,39 +248,48 @@ if(radius > 1 || prob(chance)) var/decal_chance = 50 + if(prob(decal_chance)) - var/obj/effect/decal/cleanable/blood/xeno/decal = locate(/obj/effect/decal/cleanable/blood/xeno) in T - if(!decal) //Let's not stack blood, it just makes lagggggs. - add_splatter_floor(T) //Drop some on the ground first. - else - if(decal.random_icon_states && length(decal.random_icon_states) > 0) //If there's already one, just randomize it so it changes. - decal.icon_state = pick(decal.random_icon_states) - - var/splash_chance = 40 //Base chance of getting splashed. Decreases with # of victims. - var/i = 0 //Tally up our victims. - - for(var/mob/living/carbon/human/victim in orange(radius, src)) //Loop through all nearby victims, including the tile. - splash_chance = 65 - (i * 5) - if(victim.loc == loc) - splash_chance += 30 //Same tile? BURN - if(victim.species?.acid_blood_dodge_chance) - splash_chance -= victim.species.acid_blood_dodge_chance - - if(splash_chance > 0 && prob(splash_chance)) //Success! - var/dmg = list("damage" = acid_blood_damage) - if(SEND_SIGNAL(src, COMSIG_XENO_DEAL_ACID_DAMAGE, victim, dmg) & COMPONENT_BLOCK_DAMAGE) - continue - i++ - victim.visible_message(SPAN_DANGER("\The [victim] is scalded with hissing green blood!"), \ - SPAN_DANGER("You are splattered with sizzling blood! IT BURNS!")) - if(prob(60) && !victim.stat && victim.pain.feels_pain) - INVOKE_ASYNC(victim, TYPE_PROC_REF(/mob, emote), "scream") //Topkek - victim.apply_armoured_damage(dmg["damage"], ARMOR_BIO, BURN) //Sizzledam! This automagically burns a random existing body part. - victim.add_blood(get_blood_color(), BLOOD_BODY) - acid_splash_last = world.time - handle_blood_splatter(get_dir(src, victim), 1 SECONDS) - playsound(victim, "acid_sizzle", 25, TRUE) - animation_flash_color(victim, "#FF0000") //pain hit flicker + if(boss_type == 0) + var/obj/effect/decal/cleanable/blood/xeno/decal = locate(/obj/effect/decal/cleanable/blood/xeno) in T + if(!decal) //Let's not stack blood, it just makes lagggggs. + add_splatter_floor(T) //Drop some on the ground first. + else + if(decal.random_icon_states && length(decal.random_icon_states) > 0) //If there's already one, just randomize it so it changes. + decal.icon_state = pick(decal.random_icon_states) + if(boss_type == 1) + var/obj/effect/decal/cleanable/blood/oil/decal = locate(/obj/effect/decal/cleanable/blood/xeno) in T + if(!decal) + add_splatter_floor(T) + else + if(decal.random_icon_states && length(decal.random_icon_states) > 0) //If there's already one, just randomize it so it changes. + decal.icon_state = pick(decal.random_icon_states) + if(boss_type == 0) + var/splash_chance = 40 //Base chance of getting splashed. Decreases with # of victims. + var/i = 0 //Tally up our victims. + + for(var/mob/living/carbon/human/victim in orange(radius, src)) //Loop through all nearby victims, including the tile. + splash_chance = 65 - (i * 5) + if(victim.loc == loc) + splash_chance += 30 //Same tile? BURN + if(victim.species?.acid_blood_dodge_chance) + splash_chance -= victim.species.acid_blood_dodge_chance + + if(splash_chance > 0 && prob(splash_chance)) //Success! + var/dmg = list("damage" = acid_blood_damage) + if(SEND_SIGNAL(src, COMSIG_XENO_DEAL_ACID_DAMAGE, victim, dmg) & COMPONENT_BLOCK_DAMAGE) + continue + i++ + victim.visible_message(SPAN_DANGER("\The [victim] is scalded with hissing green blood!"), \ + SPAN_DANGER("You are splattered with sizzling blood! IT BURNS!")) + if(prob(60) && !victim.stat && victim.pain.feels_pain) + INVOKE_ASYNC(victim, TYPE_PROC_REF(/mob, emote), "scream") //Topkek + victim.apply_armoured_damage(dmg["damage"], ARMOR_BIO, BURN) //Sizzledam! This automagically burns a random existing body part. + victim.add_blood(get_blood_color(), BLOOD_BODY) + acid_splash_last = world.time + handle_blood_splatter(get_dir(src, victim), 1 SECONDS) + playsound(victim, "acid_sizzle", 25, TRUE) + animation_flash_color(victim, "#FF0000") //pain hit flicker /mob/living/carbon/xenomorph/get_target_lock(access_to_check) if(isnull(access_to_check)) diff --git a/code/modules/mob/living/carbon/xenomorph/death.dm b/code/modules/mob/living/carbon/xenomorph/death.dm index e7366df07f..fee13c2ecb 100644 --- a/code/modules/mob/living/carbon/xenomorph/death.dm +++ b/code/modules/mob/living/carbon/xenomorph/death.dm @@ -79,8 +79,10 @@ playsound(loc,'sound/voice/predalien_death.ogg', 25, TRUE) else if(isfacehugger(src)) playsound(loc, 'sound/voice/alien_facehugger_dies.ogg', 25, TRUE) - else + else if(boss_type == 0) playsound(loc, prob(50) == 1 ? 'sound/voice/alien_death.ogg' : 'sound/voice/alien_death2.ogg', 25, 1) + else + playsound(loc, 'sound/effects/metal_crash.ogg') var/area/A = get_area(src) if(hive && hive.living_xeno_queen) xeno_message("Hive: [src] has died[A? " at [sanitize_area(A.name)]":""]! [banished ? "They were banished from the hive." : ""]", death_fontsize, hivenumber) diff --git a/code/modules/mob/living/carbon/xenomorph/life.dm b/code/modules/mob/living/carbon/xenomorph/life.dm index b5ad08e97a..728d59fc9f 100644 --- a/code/modules/mob/living/carbon/xenomorph/life.dm +++ b/code/modules/mob/living/carbon/xenomorph/life.dm @@ -84,7 +84,8 @@ drop_inv_item_on_ground(G) if(!caste || !(caste.fire_immunity & FIRE_IMMUNITY_NO_DAMAGE) || fire_reagent.fire_penetrating) apply_damage(armor_damage_reduction(GLOB.xeno_fire, PASSIVE_BURN_DAM_CALC(fire_reagent.intensityfire, fire_reagent.durationfire, fire_stacks) * caste.fire_vulnerability_mult), BURN) - INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), pick("roar", "needhelp")) + if(boss_type == 0) + INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), pick("roar", "needhelp")) #undef PASSIVE_BURN_DAM_CALC diff --git a/colonialmarines.dme b/colonialmarines.dme index ece3897f81..8c23eca5d4 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -2000,6 +2000,9 @@ #include "code\modules\mob\living\carbon\xenomorph\abilities\boiler\boiler_abilities.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\boiler\boiler_macros.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\boiler\boiler_powers.dm" +#include "code\modules\mob\living\carbon\xenomorph\abilities\boss\boss_abilities.dm" +#include "code\modules\mob\living\carbon\xenomorph\abilities\boss\boss_macros.dm" +#include "code\modules\mob\living\carbon\xenomorph\abilities\boss\boss_powers.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\burrower\burrower_abilities.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\burrower\burrower_macros.dm" #include "code\modules\mob\living\carbon\xenomorph\abilities\burrower\burrower_powers.dm" @@ -2053,6 +2056,7 @@ #include "code\modules\mob\living\carbon\xenomorph\ai\movement\linger.dm" #include "code\modules\mob\living\carbon\xenomorph\ai\movement\lurking.dm" #include "code\modules\mob\living\carbon\xenomorph\castes\Boiler.dm" +#include "code\modules\mob\living\carbon\xenomorph\castes\boss_bot.dm" #include "code\modules\mob\living\carbon\xenomorph\castes\Burrower.dm" #include "code\modules\mob\living\carbon\xenomorph\castes\Carrier.dm" #include "code\modules\mob\living\carbon\xenomorph\castes\Crusher.dm" diff --git a/icons/Surge/boss_bot/boss.dmi b/icons/Surge/boss_bot/boss.dmi new file mode 100644 index 0000000000..6ad6d88fe6 Binary files /dev/null and b/icons/Surge/boss_bot/boss.dmi differ diff --git a/icons/Surge/boss_bot/boss_proj.dmi b/icons/Surge/boss_bot/boss_proj.dmi new file mode 100644 index 0000000000..94250c1d3c Binary files /dev/null and b/icons/Surge/boss_bot/boss_proj.dmi differ diff --git a/icons/Surge/effects/boss_boom.dmi b/icons/Surge/effects/boss_boom.dmi new file mode 100644 index 0000000000..eb34cf47fe Binary files /dev/null and b/icons/Surge/effects/boss_boom.dmi differ diff --git a/sound/surge/rockets_launching.ogg b/sound/surge/rockets_launching.ogg new file mode 100644 index 0000000000..72957b93b8 Binary files /dev/null and b/sound/surge/rockets_launching.ogg differ