diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index ec035c4e288..1d2fdc3ea56 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -789,6 +789,7 @@ #define COMSIG_XENOABILITY_PSYCHIC_LINK "xenoability_psychic_link" #define COMSIG_XENOABILITY_CARNAGE "xenoability_carnage" #define COMSIG_XENOABILITY_FEAST "xenoability_feast" +#define COMSIG_XENOABILITY_OPPOSE "xenoability_oppose" #define COMSIG_XENOABILITY_ACIDCHARGE "xenoability_acidcharge" #define COMSIG_XENOABILITY_BULLHEADBUTT "xenoability_bullheadbutt" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 45ebbf713dc..464840878c4 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -643,6 +643,8 @@ GLOBAL_LIST_INIT(xenoupgradetiers, list(XENO_UPGRADE_BASETYPE, XENO_UPGRADE_INVA #define GORGER_CARNAGE_HEAL 0.2 #define GORGER_CARNAGE_MOVEMENT -0.5 #define GORGER_FEAST_DURATION -1 // lasts indefinitely, self-cancelled when insufficient plasma left +#define GORGER_OPPOSE_COST 80 +#define GORGER_OPPOSE_HEAL 0.2 // in % //carrier defines #define CARRIER_HUGGER_THROW_SPEED 2 diff --git a/code/datums/keybinding/xeno.dm b/code/datums/keybinding/xeno.dm index bbc16c25300..fbc0ba47d04 100644 --- a/code/datums/keybinding/xeno.dm +++ b/code/datums/keybinding/xeno.dm @@ -512,6 +512,13 @@ keybind_signal = COMSIG_XENOABILITY_REJUVENATE hotkey_keys = list("R") +/datum/keybinding/xeno/oppose + name = "oppose" + full_name = "Gorger: Oppose" + description = "Violently suffuse the nearby ground with stored blood, staggering nearby marines and healing nearby xenomorphs." + keybind_signal = COMSIG_XENOABILITY_OPPOSE + hotkey_keys = list("G") + /datum/keybinding/xeno/psychic_link name = "psychic link" full_name = "Gorger: Psychic Link" diff --git a/code/game/objects/effects/temporary_visuals/temporary_visual.dm b/code/game/objects/effects/temporary_visuals/temporary_visual.dm index 538979f04a1..fba9a1a80e2 100644 --- a/code/game/objects/effects/temporary_visuals/temporary_visual.dm +++ b/code/game/objects/effects/temporary_visuals/temporary_visual.dm @@ -138,3 +138,17 @@ GLOBAL_DATUM_INIT(flare_particles, /particles/flare_smoke, new) pixel_x = rand(-12, 12) pixel_y = rand(-9, 0) +/obj/effect/temp_visual/oppose_shatter + icon = 'icons/effects/96x96.dmi' + icon_state = "oppose_shatter" + name = "veined terrain" + desc = "blood rushes below the ground, forcing it upwards." + layer = PODDOOR_OPEN_LAYER + pixel_x = -32 + pixel_y = -32 + duration = 3 SECONDS + alpha = 200 + +/obj/effect/temp_visual/oppose_shatter/Initialize(mapload) + . = ..() + animate(src, alpha = 0, time = 3 SECONDS) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/gorger/abilities_gorger.dm b/code/modules/mob/living/carbon/xenomorph/castes/gorger/abilities_gorger.dm index a7a30e4927a..07b698c2659 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/gorger/abilities_gorger.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/gorger/abilities_gorger.dm @@ -137,6 +137,7 @@ return owner_xeno.face_atom(target_human) owner_xeno.emote("roar") + owner_xeno.AdjustImmobilized(0.5 SECONDS) ADD_TRAIT(owner_xeno, TRAIT_HANDS_BLOCKED, src) for(var/i = 0; i < GORGER_DRAIN_INSTANCES; i++) target_human.Immobilize(GORGER_DRAIN_DELAY) @@ -165,6 +166,10 @@ // *************************************** // *********** Transfusion // *************************************** + +/obj/effect/ebeam/transfusion + name = "blood transfusion beam" + /datum/action/ability/activable/xeno/transfusion name = "Transfusion" action_icon_state = "transfusion" @@ -203,8 +208,12 @@ to_chat(owner, span_notice("We can only help living sisters.")) return FALSE target_health = target_xeno.health + var/datum/beam/transfuse_beam = owner.beam(target_xeno, icon_state= "lichbeam", beam_type = /obj/effect/ebeam/essence_link) + transfuse_beam.visuals.alpha = 127 if(!do_after(owner, 1 SECONDS, IGNORE_LOC_CHANGE, target_xeno, BUSY_ICON_FRIENDLY, BUSY_ICON_MEDICAL, extra_checks = CALLBACK(src, PROC_REF(extra_health_check), target_xeno))) + QDEL_NULL(transfuse_beam) return FALSE + QDEL_NULL(transfuse_beam) return TRUE ///An extra check for the do_mob in can_use_ability. If the target isn't immobile and has lost health, the ability is cancelled. The ability is also cancelled if the target is knocked into crit DURING the do_mob. @@ -219,7 +228,11 @@ var/mob/living/carbon/xenomorph/target_xeno = target var/heal_amount = target_xeno.maxHealth * GORGER_TRANSFUSION_HEAL HEAL_XENO_DAMAGE(target_xeno, heal_amount, FALSE) + if(owner.client) + var/datum/personal_statistics/personal_statistics = GLOB.personal_statistics_list[owner.ckey] + personal_statistics.heals++ adjustOverheal(target_xeno, heal_amount) + new /obj/effect/temp_visual/healing(get_turf(target_xeno)) if(target_xeno.overheal) target_xeno.balloon_alert(owner_xeno, "Overheal: [target_xeno.overheal]/[target_xeno.xeno_caste.overheal_max]") add_cooldown() @@ -411,6 +424,88 @@ return FALSE return can_use_ability(target, TRUE) +// *************************************** +// *********** oppose +// *************************************** +/particles/oppose_aoe + icon = 'icons/effects/particles/generic_particles.dmi' + icon_state = list("cross" = 1, "x" = 1, "rectangle" = 1, "up_arrow" = 1, "down_arrow" = 1, "square" = 1) + width = 500 + height = 500 + count = 2000 + spawning = 50 + gravity = list(0, 0.1) + color = LIGHT_COLOR_BLOOD_MAGIC + lifespan = 13 + fade = 3 + fadein = 5 + scale = 0.8 + friction = generator(GEN_NUM, 0.1, 0.15) + spin = generator(GEN_NUM, -20, 20) + +/datum/action/ability/activable/xeno/oppose + name = "Oppose" + action_icon_state = "stomp" + action_icon = 'icons/Xeno/actions.dmi' + desc = "Violently suffuse the ground with stored blood. A marine on your tile is staggered and injured, ajacent marines are staggered, and any nearby xenos are healed, including you." + cooldown_duration = 30 SECONDS + ability_cost = GORGER_OPPOSE_COST + keybinding_signals = list( + KEYBINDING_NORMAL = COMSIG_XENOABILITY_OPPOSE, + ) + keybind_flags = ABILITY_KEYBIND_USE_ABILITY + +/datum/action/ability/activable/xeno/oppose/use_ability(atom/A) + . = ..() + var/mob/living/carbon/xenomorph/owner_xeno = owner + add_cooldown() + succeed_activate() + + playsound(owner_xeno.loc, 'sound/effects/bang.ogg', 25, 0) + owner_xeno.visible_message(span_xenodanger("[owner_xeno] smashes her fists into the ground!"), \ + span_xenodanger("We smash our fists into the ground!")) + + owner_xeno.create_stomp() //Adds the visual effects. Wom wom wom + new /obj/effect/temp_visual/oppose_shatter(get_turf(owner_xeno)) //shatter displays stagger range + + var/obj/effect/abstract/particle_holder/aoe_particles = new(owner.loc, /particles/oppose_aoe) //particles display heal range + aoe_particles.particles.position = generator(GEN_SQUARE, 0, 16 + 3*32, LINEAR_RAND) + addtimer(CALLBACK(src, PROC_REF(stop_particles), aoe_particles), 0.5 SECONDS) + + var/list/oppose_range = range(3) + for(var/mob/living/M in oppose_range) + if(M.stat == DEAD) + continue + var/distance = get_dist(M, owner_xeno) + if(owner_xeno.issamexenohive(M)) //Xenos in range will be healed and overhealed, including you. + var/mob/living/carbon/xenomorph/target_xeno = M + var/heal_amount = M.maxHealth * GORGER_OPPOSE_HEAL + HEAL_XENO_DAMAGE(target_xeno, heal_amount, FALSE) + adjustOverheal(target_xeno, heal_amount) + new /obj/effect/temp_visual/healing(get_turf(target_xeno)) + if(owner.client) + var/datum/personal_statistics/personal_statistics = GLOB.personal_statistics_list[owner.ckey] + personal_statistics.heals++ + else if(distance == 0) //if we're right on top of them, they take actual damage + M.take_overall_damage(20, BRUTE, MELEE, updating_health = TRUE, max_limbs = 3) + to_chat(M, span_highdanger("[owner_xeno] slams her fists into you, crushing you to the ground!")) + M.adjust_stagger(2 SECONDS) + M.adjust_slowdown(3) + shake_camera(M, 3, 3) + else if(distance == 1) //marines will only be staggerslowed if they're one tile away from you + shake_camera(M, 2, 2) + to_chat(M, span_highdanger("Blood shatters the ground around you!")) + M.adjust_stagger(2 SECONDS) + M.adjust_slowdown(3) + +///Stops particle spawning, then gives existing particles time to fade out before deleting them. +/datum/action/ability/activable/xeno/oppose/proc/stop_particles(obj/effect/abstract/particle_holder/aoe_particles) + aoe_particles.particles.spawning = 0 + QDEL_IN(aoe_particles, 3 SECONDS) + +/datum/action/ability/activable/xeno/oppose/ai_should_use(atom/target) + return FALSE + // *************************************** // *********** Feast // *************************************** diff --git a/code/modules/mob/living/carbon/xenomorph/castes/gorger/castedatum_gorger.dm b/code/modules/mob/living/carbon/xenomorph/castes/gorger/castedatum_gorger.dm index 01a67ccd8cd..684e0ad8ed3 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/gorger/castedatum_gorger.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/gorger/castedatum_gorger.dm @@ -42,6 +42,7 @@ drain_plasma_gain = 75 carnage_plasma_gain = 150 feast_plasma_drain = 20 + blood_drained = 30 actions = list( /datum/action/ability/xeno_action/xeno_resting, @@ -51,6 +52,7 @@ /datum/action/ability/activable/xeno/drain, /datum/action/ability/activable/xeno/transfusion, /datum/action/ability/activable/xeno/carnage, + /datum/action/ability/activable/xeno/oppose, /datum/action/ability/activable/xeno/feast, /datum/action/ability/activable/xeno/devour, ) @@ -73,5 +75,6 @@ /datum/action/ability/activable/xeno/rejuvenate, /datum/action/ability/activable/xeno/carnage, /datum/action/ability/activable/xeno/feast, + /datum/action/ability/activable/xeno/oppose, /datum/action/ability/activable/xeno/devour, ) diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm index eb0b5f97959..b8c7ece9f79 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_defines.dm @@ -156,6 +156,8 @@ var/carnage_plasma_gain = 0 ///Amount of plasma drained each tick while feast buff is actuve var/feast_plasma_drain = 0 + ///Amount of blood we drain from our target when draining blood + var/blood_drained = 0 // *** Queen Abilities *** // ///Amount of leaders allowed diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index 6deca04d367..4e1b5c4d5e1 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ