mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-19 02:56:14 +01:00
Ports TG Anomalies (#18794)
* Anomalies * Tiles * Automatic changelog compile [ci skip] * Bioscramble * Reactive armour * Reactive * . * Automatic changelog compile [ci skip] * hallucination * Snowy * Bit of polishing * change * Cargo & Research * fimx * Anomaly stuffs * Bioscrambler + Terrible fire armour * Adjustment * Less spammy * Changes --------- Co-authored-by: vorestation-ci[bot] <199609141+vorestation-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -160,7 +160,8 @@
|
||||
body_parts_covered = CHEST
|
||||
armor = list(melee = 40, bullet = 30, laser = 30, energy = 10, bomb = 10, bio = 0, rad = 0)
|
||||
|
||||
|
||||
// Ooold, old reactive armor.
|
||||
/*
|
||||
//Reactive armor
|
||||
//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!)
|
||||
/obj/item/clothing/suit/armor/reactive
|
||||
@@ -211,7 +212,7 @@
|
||||
active = FALSE
|
||||
icon_state = "reactiveoff"
|
||||
..()
|
||||
|
||||
*/
|
||||
// Alien armor has a chance to completely block attacks.
|
||||
/obj/item/clothing/suit/armor/alien
|
||||
name = "alien enhancement vest"
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
/obj/item/clothing/suit/armor/reactive_armor_shell
|
||||
name = "reactive armor shell"
|
||||
desc = "An experimental suit of armor, awaiting installation of an anomaly core."
|
||||
icon_state = "reactiveoff"
|
||||
w_class = ITEMSIZE_COST_LARGE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive_armor_shell/attackby(obj/item/I, mob/user)
|
||||
. = ..()
|
||||
var/static/list/anomaly_armour_types = list(
|
||||
/obj/effect/anomaly/grav = /obj/item/clothing/suit/armor/reactive/repulse,
|
||||
/obj/effect/anomaly/flux = /obj/item/clothing/suit/armor/reactive/tesla,
|
||||
/obj/effect/anomaly/bluespace = /obj/item/clothing/suit/armor/reactive/teleport,
|
||||
//obj/effect/anomaly/bioscrambler = /obj/item/clothing/suit/armor/reactive/bioscrambling,
|
||||
/obj/effect/anomaly/hallucination = /obj/item/clothing/suit/armor/reactive/hallucinating,
|
||||
/obj/effect/anomaly/dimensional = /obj/item/clothing/suit/armor/reactive/barricade,
|
||||
/obj/effect/anomaly/pyro = /obj/item/clothing/suit/armor/reactive/fire
|
||||
)
|
||||
|
||||
if(istype(I, /obj/item/assembly/signaler/anomaly))
|
||||
var/obj/item/assembly/signaler/anomaly/anomaly = I
|
||||
var/armour_path = is_path_in_list(anomaly.anomaly_type, anomaly_armour_types, TRUE)
|
||||
if(!armour_path)
|
||||
armour_path = /obj/item/clothing/suit/armor/reactive/stealth
|
||||
to_chat(user, span_notice("You insert [anomaly] into the chest plate, and the armour gently hums to life."))
|
||||
new armour_path(get_turf(src))
|
||||
qdel(src)
|
||||
qdel(anomaly)
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive
|
||||
name = "reactive armor"
|
||||
desc = "Doesn't seem to do much for some reason."
|
||||
icon_state = "reactiveoff"
|
||||
blood_overlay_type = "armor"
|
||||
armor = list(melee = 40, bullet = 35, laser = 35, energy = 10, bomb = 10, bio = 0, rad = 0)
|
||||
var/hit_reaction_chance = 50
|
||||
///Whether the armor will try to react to hits (is it on)
|
||||
var/active = FALSE
|
||||
///This will be true for 30 seconds after an EMP, it makes the reaction effect dangerous to the user.
|
||||
var/bad_effect = FALSE
|
||||
///Message sent when the armor is emp'd. It is not the message for when the emp effect goes off.
|
||||
var/emp_message = span_warning("The reactive armor has been emp'd! Damn, now it's REALLY gonna not do much!")
|
||||
///Message sent when the armor is still on cooldown, but activates.
|
||||
var/cooldown_message = span_danger("The reactive armor fails to do much, as it is recharging! From what? Only the reactive armor knows.")
|
||||
///Duration of the cooldown specific to reactive armor for when it can activate again.
|
||||
var/reactivearmor_cooldown_duration = 10 SECONDS
|
||||
///The cooldown itself of the reactive armor for when it can activate again.
|
||||
var/reactivearmor_cooldown = 0
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/update_icon()
|
||||
. = ..()
|
||||
icon_state = "reactive[active ? null : "off"]"
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/attack_self(mob/user)
|
||||
active = !active
|
||||
to_chat(user, span_notice("[src] is now [active ? "active" : "inactive"]."))
|
||||
update_icon()
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/handle_shield(mob/user, damage, atom/damage_source, mob/attacker, def_zone, attack_text)
|
||||
if(!active || !prob(hit_reaction_chance))
|
||||
return FALSE
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
cooldown_activation(user)
|
||||
return FALSE
|
||||
if(bad_effect)
|
||||
return emp_activation(user, damage_source, attack_text, damage)
|
||||
else
|
||||
return reactive_activation(user, damage_source, attack_text, damage)
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/proc/cooldown_activation(var/mob/living/carbon/human/owner)
|
||||
owner.visible_message(cooldown_message)
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/proc/reactive_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
owner.visible_message(span_danger("The reactive armor doesn't do much! No surprises here."))
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/proc/emp_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
owner.visible_message(span_danger("The reactive armor doesn't do much, despite being emp'd! Besides giving off a special message, of course."))
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/emp_act(severity, recursive)
|
||||
. = ..()
|
||||
if(bad_effect || !active)
|
||||
return
|
||||
visible_message(emp_message)
|
||||
bad_effect = TRUE
|
||||
addtimer(VARSET_CALLBACK(src, bad_effect, FALSE), 30 SECONDS)
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/teleport
|
||||
name = "reactive teleport armor"
|
||||
desc = "Someone separated our Research Director from his own head!"
|
||||
emp_message = span_warning("The reactive armor's teleportation calculations begin spewing errors!")
|
||||
cooldown_message = span_danger("The reactive teleport system is still recharging! It fails to activate!")
|
||||
reactivearmor_cooldown_duration = 10 SECONDS
|
||||
var/tele_range = 6
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/teleport/reactive_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0)
|
||||
owner.visible_message(span_danger("The reactive teleport system flings [owner] clear of [attack_text]!"))
|
||||
playsound(get_turf(owner), 'sound/effects/phasein.ogg', 100, TRUE)
|
||||
do_teleport(owner, get_turf(owner), tele_range, no_effects = TRUE, channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/teleport/emp_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0)
|
||||
owner.visible_message(span_danger("The reactive teleport system flings itself clear of [attack_text], leaving someone behind in the process!"))
|
||||
owner.drop_from_inventory(src, get_turf(src))
|
||||
playsound(get_turf(owner),'sound/machines/buzz-sigh.ogg', 50, TRUE)
|
||||
playsound(get_turf(owner), 'sound/effects/phasein.ogg', 100, TRUE)
|
||||
do_teleport(src, get_turf(owner), tele_range, no_effects = TRUE, channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return FALSE
|
||||
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/repulse
|
||||
name = "reactive repulse armor"
|
||||
desc = "An experimental suit of armor that violently throws back attackers."
|
||||
cooldown_message = span_danger("The repulse generator is still recharging! It fails to generate a strong enough wave!")
|
||||
emp_message = span_warning("The repulse generator is reset to default settings...")
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/repulse/reactive_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
playsound(get_turf(owner),'sound/effects/repulse.ogg', 100, TRUE)
|
||||
owner.visible_message(span_danger("[src] blocks [attack_text], converting the attack into a wave of force!"))
|
||||
var/turf/owner_turf = get_turf(owner)
|
||||
var/list/thrown_items = list()
|
||||
for(var/atom/movable/repulsed in range(owner_turf, 5))
|
||||
if(repulsed == owner || repulsed.anchored || thrown_items[repulsed])
|
||||
continue
|
||||
var/throwtarget = get_edge_target_turf(owner_turf, get_dir(owner_turf, get_step_away(repulsed, owner_turf)))
|
||||
repulsed.throw_at(throwtarget, 10, 1)
|
||||
thrown_items[repulsed] = repulsed
|
||||
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/repulse/emp_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
playsound(get_turf(owner),'sound/effects/repulse.ogg', 100, TRUE)
|
||||
owner.visible_message(span_danger("[src] does not block [attack_text], and instead generates an attracting force!"))
|
||||
var/turf/owner_turf = get_turf(owner)
|
||||
var/list/thrown_items = list()
|
||||
for(var/atom/movable/repulsed in range(owner_turf, 5))
|
||||
if(repulsed == owner || repulsed.anchored || thrown_items[repulsed])
|
||||
continue
|
||||
repulsed.throw_at(owner, 10, 1)
|
||||
thrown_items[repulsed] = repulsed
|
||||
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return FALSE
|
||||
|
||||
|
||||
// Tesla
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/tesla
|
||||
name = "reactive tesla armor"
|
||||
desc = "An experimental suit of armor with sensitive detectors hooked up to a huge capacitor grid, with emitters strutting out of it. Zap."
|
||||
siemens_coefficient = -1
|
||||
cooldown_message = span_danger("The tesla capacitors on the reactive tesla armor are still recharging! The armor merely emits some sparks.")
|
||||
emp_message = span_warning("The tesla capacitors beep ominously for a moment.")
|
||||
clothing_traits = list(TRAIT_TESLA_SHOCKIMMUNE)
|
||||
/// How strong are the zaps we give off?
|
||||
var/zap_power = 2.5e4
|
||||
/// How far to the zaps we give off go?
|
||||
var/zap_range = 20
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/tesla/cooldown_activation(mob/living/carbon/human/owner)
|
||||
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
|
||||
sparks.set_up(1, 1, src)
|
||||
sparks.start()
|
||||
..()
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/tesla/reactive_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
owner.visible_message(span_danger("[src] blocks [attack_text], sending out arcs of lightning!"))
|
||||
tesla_zap(owner, zap_range, zap_power)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/tesla/emp_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
owner.visible_message(span_danger("[src] blocks [attack_text], but pulls a massive charge of energy into [owner] from the surrounding environment!"))
|
||||
REMOVE_CLOTHING_TRAIT(owner, TRAIT_TESLA_SHOCKIMMUNE)
|
||||
electrocute_mob(owner, get_area(src), src, 1)
|
||||
ADD_CLOTHING_TRAIT(owner, TRAIT_TESLA_SHOCKIMMUNE)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return TRUE
|
||||
|
||||
// Sure we could, but- Not really THAT useful. Give them the stealth one.
|
||||
/obj/item/clothing/suit/armor/reactive/bioscrambling
|
||||
|
||||
// Hallucinating
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/hallucinating
|
||||
name = "reactive hallucinating armor"
|
||||
desc = "An experimental suit of armor with sensitive detectors hooked up to the mind of the wearer, sending mind pulses that causes hallucinations around you."
|
||||
cooldown_message = span_danger("The connection is currently out of sync... Recalibrating.")
|
||||
emp_message = span_warning("You feel the backsurge of a mind pulse.")
|
||||
clothing_traits = list(TRAIT_MADNESS_IMMUNE)
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/hallucinating/cooldown_activation(mob/living/carbon/human/owner)
|
||||
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
|
||||
sparks.set_up(1, 1, src)
|
||||
sparks.start()
|
||||
..()
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/hallucinating/reactive_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
owner.visible_message(span_danger("[src] blocks [attack_text], sending out mental pulses!"))
|
||||
for(var/mob/living/carbon/human/hallucinator in viewers(5, get_turf(src)))
|
||||
if(hallucinator == owner)
|
||||
continue
|
||||
hallucinator.hallucination += 50
|
||||
if(prob(10))
|
||||
to_chat(hallucinator, span_danger("Your nose bleeds!"))
|
||||
hallucinator.drip(1)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/hallucinating/emp_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
owner.visible_message(span_danger("[src] blocks [attack_text], but pulls a massive charge of mental energy into [owner] from the surrounding environment!"))
|
||||
owner.hallucination += 75
|
||||
to_chat(owner, span_danger("Your nose bleeds!"))
|
||||
owner.drip(1)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return TRUE
|
||||
|
||||
// When the wearer gets hit, this armor will push people nearby and spawn some blocking objects.
|
||||
/obj/item/clothing/suit/armor/reactive/barricade
|
||||
name = "reactive barricade armor"
|
||||
desc = "An experimental suit of armor that generates barriers from another world when it detects its bearer is in danger."
|
||||
emp_message = span_warning("The reactive armor's dimensional coordinates are scrambled!")
|
||||
cooldown_message = span_danger("The reactive barrier system is still recharging! It fails to activate!")
|
||||
reactivearmor_cooldown_duration = 10 SECONDS
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/barricade/reactive_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
playsound(get_turf(owner),'sound/effects/repulse.ogg', 100, TRUE)
|
||||
owner.visible_message(span_danger("The reactive armor interposes matter from another world between [src] and [attack_text]!"))
|
||||
for (var/atom/movable/target in repulse_targets(owner))
|
||||
repulse(target, owner)
|
||||
|
||||
var/datum/armour_dimensional_theme/theme = new()
|
||||
theme.apply_random(get_turf(owner), dangerous = FALSE)
|
||||
qdel(theme)
|
||||
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/barricade/proc/repulse_targets(atom/source)
|
||||
var/list/push_targets = list()
|
||||
for (var/atom/movable/nearby_movable in view(1, source))
|
||||
if(nearby_movable == source)
|
||||
continue
|
||||
if(nearby_movable.anchored)
|
||||
continue
|
||||
push_targets += nearby_movable
|
||||
return push_targets
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/barricade/proc/repulse(atom/movable/victim, atom/source)
|
||||
var/dist_from_caster = get_dist(victim, source)
|
||||
|
||||
if(dist_from_caster == 0)
|
||||
return
|
||||
|
||||
if (isliving(victim))
|
||||
to_chat(victim, span_userdanger("You're thrown back by a wave of pressure!"))
|
||||
var/turf/throwtarget = get_edge_target_turf(source, get_dir(source, get_step_away(victim, source, 1)))
|
||||
victim.throw_at(throwtarget, 1, 1)
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/barricade/emp_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
owner.visible_message(span_danger("The reactive armor shunts matter from an unstable dimension!"))
|
||||
var/datum/armour_dimensional_theme/theme = new()
|
||||
theme.apply_random(get_turf(owner), dangerous = TRUE)
|
||||
qdel(theme)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return FALSE
|
||||
|
||||
// FIRE
|
||||
/obj/item/clothing/suit/armor/reactive/fire
|
||||
name = "reactive incendiary armor"
|
||||
desc = "An experimental suit of armor with a reactive sensor array rigged to a flame emitter. For the stylish pyromaniac."
|
||||
cooldown_message = span_danger("The reactive incendiary armor activates, but fails to send out flames as it is still recharging its flame jets!")
|
||||
emp_message = span_warning("The reactive incendiary armor's targeting system begins rebooting...")
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/fire/reactive_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
owner.visible_message(span_danger("[src] blocks [attack_text], sending out jets of flame!"))
|
||||
playsound(get_turf(owner), 'sound/magic/Fireball.ogg', 100, TRUE)
|
||||
for(var/mob/living/carbon_victim in range(6, get_turf(src)))
|
||||
if(carbon_victim != owner)
|
||||
carbon_victim.adjust_fire_stacks(8)
|
||||
carbon_victim.ignite_mob()
|
||||
owner.set_wet_stacks(20)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/fire/emp_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
owner.visible_message(span_danger("[src] just makes [attack_text] worse by spewing molten death on [owner]!"))
|
||||
playsound(get_turf(owner), 'sound/magic/Fireball.ogg', 100, TRUE)
|
||||
owner.adjust_fire_stacks(12)
|
||||
owner.ignite_mob()
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return FALSE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth
|
||||
name = "reactive stealth armor"
|
||||
desc = "An experimental suit of armor that renders the wearer invisible on detection of imminent harm, and creates a decoy that runs away from the owner. You can't fight what you can't see."
|
||||
cooldown_message = span_danger("The reactive stealth system activates, but is not charged enough to fully cloak!")
|
||||
emp_message = span_warning("The reactive stealth armor's threat assessment system crashes...")
|
||||
///when triggering while on cooldown will only flicker the alpha slightly. this is how much it removes.
|
||||
var/cooldown_alpha_removal = 50
|
||||
///cooldown alpha flicker- how long it takes to return to the original alpha
|
||||
var/cooldown_animation_time = 3 SECONDS
|
||||
///how long they will be fully stealthed
|
||||
var/stealth_time = 4 SECONDS
|
||||
///how long it will animate back the alpha to the original
|
||||
var/animation_time = 2 SECONDS
|
||||
var/in_stealth = FALSE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth/cooldown_activation(mob/living/carbon/human/owner)
|
||||
if(in_stealth)
|
||||
return
|
||||
owner.alpha = max(0, owner.alpha - cooldown_alpha_removal)
|
||||
animate(owner, alpha = initial(owner.alpha), time = cooldown_animation_time)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth/reactive_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text, final_block_chance, damage)
|
||||
var/mob/living/simple_mob/illusion/decoy = new(owner.loc)
|
||||
decoy.copy_appearance(owner)
|
||||
decoy.copy_overlays(owner, TRUE)
|
||||
var/datum/ai_holder/AI = decoy.ai_holder
|
||||
var/turf/rand_turf = pick(get_turf(orange(5, 10)))
|
||||
AI.give_destination(rand_turf)
|
||||
owner.alpha = 0
|
||||
in_stealth = TRUE
|
||||
owner.visible_message(span_danger("[owner] is hit by [attack_text] in the chest!"))
|
||||
addtimer(CALLBACK(src, PROC_REF(end_stealth), owner), stealth_time)
|
||||
decoy.say("*sidestep")
|
||||
addtimer(CALLBACK(src, PROC_REF(destroy_illusion), decoy), stealth_time)
|
||||
QDEL_IN(decoy, stealth_time)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth/proc/end_stealth(mob/living/carbon/human/owner)
|
||||
in_stealth = FALSE
|
||||
animate(owner, alpha = initial(owner.alpha), time = animation_time)
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth/proc/destroy_illusion(mob/illusion)
|
||||
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
|
||||
sparks.set_up(3, 3, illusion)
|
||||
sparks.start()
|
||||
QDEL_IN(illusion, animation_time)
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth/emp_activation(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0)
|
||||
if(!isliving(hitby))
|
||||
return FALSE
|
||||
var/mob/living/attacker = hitby
|
||||
owner.visible_message(span_danger("[src] activates, cloaking the wrong person!"))
|
||||
attacker.alpha = 0
|
||||
addtimer(VARSET_CALLBACK(attacker, alpha, initial(attacker.alpha)), 4 SECONDS)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return FALSE
|
||||
@@ -0,0 +1,96 @@
|
||||
#define MAX_BARRIERS 4
|
||||
#define MIN_BARRIERS 2
|
||||
|
||||
/datum/armour_dimensional_theme
|
||||
var/datum/material/material
|
||||
var/turf/replace_floor = /turf/simulated/floor/tiled
|
||||
var/turf/replace_wall = /turf/simulated/wall
|
||||
var/obj/barricade = /obj/structure/barricade
|
||||
var/barricade_anchored = TRUE
|
||||
|
||||
/datum/armour_dimensional_theme/proc/apply_random(turf/source, dangerous = FALSE)
|
||||
var/theme_type
|
||||
if(dangerous)
|
||||
theme_type = pick(subtypesof(/datum/armour_dimensional_theme/dangerous))
|
||||
else
|
||||
theme_type = pick(subtypesof(/datum/armour_dimensional_theme/safe))
|
||||
var/datum/armour_dimensional_theme/theme = new theme_type()
|
||||
theme.apply(source)
|
||||
qdel(theme)
|
||||
|
||||
/datum/armour_dimensional_theme/proc/apply(turf/source)
|
||||
var/obj/effect/effect/smoke/poof = new(source)
|
||||
poof.time_to_live = 2 SECONDS
|
||||
var/list/target_area = get_target_area(source)
|
||||
for (var/turf/target in target_area)
|
||||
convert_turf(target)
|
||||
place_barriers(source, target_area)
|
||||
|
||||
/datum/armour_dimensional_theme/proc/get_target_area(turf/source)
|
||||
var/list/target_area = RANGE_TURFS(1, source)
|
||||
for (var/turf/check_turf as anything in target_area)
|
||||
if(isspace(check_turf))
|
||||
target_area -= check_turf
|
||||
continue
|
||||
if(istype(get_area(check_turf), /area/holodeck))
|
||||
continue
|
||||
|
||||
return target_area
|
||||
|
||||
/datum/armour_dimensional_theme/proc/convert_turf(turf/to_convert)
|
||||
if(isfloorturf(to_convert))
|
||||
var/turf/simulated/floor/floor = to_convert
|
||||
floor.ChangeTurf(replace_floor)
|
||||
else if(iswall(to_convert))
|
||||
to_convert.ChangeTurf(replace_wall)
|
||||
|
||||
/datum/armour_dimensional_theme/proc/place_barriers(turf/source, list/target_area)
|
||||
target_area -= source
|
||||
for(var/turf/check_turf as anything in target_area)
|
||||
if (!check_turf.density)
|
||||
continue
|
||||
target_area -= check_turf
|
||||
|
||||
var/to_place = rand(MIN_BARRIERS, MAX_BARRIERS)
|
||||
var/list/custom_materials = list()
|
||||
if(material)
|
||||
custom_materials = list(GET_MATERIAL_REF(material) = SHEET_MATERIAL_AMOUNT)
|
||||
|
||||
while(target_area.len > 0 && to_place > 0)
|
||||
var/turf/place_turf = pick(target_area)
|
||||
place_barrier(place_turf, custom_materials)
|
||||
target_area -= place_turf
|
||||
to_place--
|
||||
|
||||
/datum/armour_dimensional_theme/proc/place_barrier(turf/source)
|
||||
var/obj/structure/barricade/placed_barricade = new barricade(source, material.name)
|
||||
if(!barricade_anchored)
|
||||
placed_barricade.anchored = FALSE
|
||||
|
||||
/datum/armour_dimensional_theme/safe
|
||||
|
||||
/datum/armour_dimensional_theme/safe/natural
|
||||
replace_wall = /turf/simulated/wall/wood
|
||||
replace_floor = /turf/simulated/floor/wood
|
||||
barricade = /obj/structure/barricade
|
||||
material = /datum/material/wood
|
||||
|
||||
/datum/armour_dimensional_theme/safe/snow
|
||||
replace_wall = /turf/simulated/wall/snowbrick
|
||||
replace_floor = /turf/simulated/floor/snow
|
||||
material = /datum/material/snow
|
||||
|
||||
/datum/armour_dimensional_theme/dangerous
|
||||
|
||||
/datum/armour_dimensional_theme/dangerous/radioactive
|
||||
replace_wall = /turf/simulated/wall/uranium
|
||||
replace_floor = /turf/simulated/floor/tiled/material/uranium
|
||||
material = /datum/material/uranium
|
||||
|
||||
/datum/armour_dimensional_theme/dangerous/phoron
|
||||
replace_wall = /turf/simulated/wall/phoron
|
||||
replace_floor = /turf/simulated/floor/tiled/material/phoron
|
||||
material = /datum/material/phoron
|
||||
|
||||
#undef MAX_BARRIERS
|
||||
#undef MIN_BARRIERS
|
||||
@@ -49,7 +49,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
|
||||
// Traditional hallucinations
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/mob/living/carbon/proc/handle_hallucinations()
|
||||
if(get_hallucination_component() || !client)
|
||||
if(get_hallucination_component() || !client || HAS_TRAIT(src, TRAIT_MADNESS_IMMUNE))
|
||||
return
|
||||
LoadComponent(/datum/component/hallucinations)
|
||||
|
||||
|
||||
@@ -663,6 +663,9 @@ var/list/mining_overlay_cache = list()
|
||||
M.make_jittery(50) //SHAKY this used to be 1000(seizure) but I toned it to 50 to be less aggressive.
|
||||
if(prob(25))
|
||||
excavate_find(prob(25), finds[1])
|
||||
if(prob(2))
|
||||
var/anomaly = pick(FLUX_ANOMALY, GRAVITATIONAL_ANOMALY, PYRO_ANOMALY, HALLUCINATION_ANOMALY)
|
||||
generate_anomaly(get_turf(src), anomaly, 1, FALSE)
|
||||
else if(rand(1,500) == 1)
|
||||
visible_message(span_notice("An old dusty crate was buried within!"))
|
||||
new /obj/structure/closet/crate/secure/loot(src)
|
||||
|
||||
@@ -1255,7 +1255,7 @@
|
||||
Paralyse(3)
|
||||
|
||||
if(hallucination)
|
||||
if(hallucination >= HALLUCINATION_THRESHOLD && !(species.flags & (NO_POISON|IS_PLANT|NO_HALLUCINATION)) )
|
||||
if(hallucination >= HALLUCINATION_THRESHOLD && !(species.flags & (NO_POISON|IS_PLANT|NO_HALLUCINATION)) && !HAS_TRAIT(src, TRAIT_MADNESS_IMMUNE))
|
||||
handle_hallucinations()
|
||||
/* Stop spinning the view, it breaks too much.
|
||||
if(client && prob(5))
|
||||
|
||||
@@ -301,6 +301,16 @@
|
||||
if(grav_pulling)
|
||||
supermatter_pull(src)
|
||||
|
||||
if(damage) // Start fucking things up
|
||||
if(get_integrity() < 85 && prob(5))
|
||||
generate_anomaly(get_ranged_target_turf(src, pick(GLOB.cardinal), rand(5, 10)), FLUX_ANOMALY)
|
||||
if(get_integrity() < 75 && prob(5))
|
||||
generate_anomaly(get_ranged_target_turf(src, pick(GLOB.cardinal), rand(5, 10)), HALLUCINATION_ANOMALY)
|
||||
if(get_integrity() < 50 && prob(2))
|
||||
generate_anomaly(get_ranged_target_turf(src, pick(GLOB.cardinal), rand(5, 10)), GRAVITATIONAL_ANOMALY)
|
||||
if(get_integrity() < 25 && prob(0.3))
|
||||
generate_anomaly(get_ranged_target_turf(src, pick(GLOB.cardinal), rand(5, 10)), PYRO_ANOMALY)
|
||||
|
||||
// Vary volume by power produced.
|
||||
if(power)
|
||||
// Volume will be 1 at no power, ~12.5 at ENERGY_NITROGEN, and 20+ at ENERGY_PHORON.
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/obj/item/assembly/signaler/anomaly
|
||||
name = "anomaly core"
|
||||
desc = "The neutralized core of an anomaly. It'd probably be valuable for research."
|
||||
icon_state = "anomaly_core"
|
||||
|
||||
var/anomaly_type = /obj/effect/anomaly
|
||||
var/worth = 250 // Pricey... Should be hard-ish to obtain.
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/Initialize(mapload)
|
||||
. = ..()
|
||||
if(worth)
|
||||
AddElement(/datum/element/sellable)
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return FALSE
|
||||
if(signal.encryption != code)
|
||||
return FALSE
|
||||
for(var/obj/effect/anomaly/anomaly in get_turf(src))
|
||||
anomaly.anomalyNeutralize()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/attack_self(mob/user)
|
||||
return
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/analyzer))
|
||||
to_chat(user, span_notice("Analyzing... [src]'s stabilized field is fluctuating along frequency [format_frequency(frequency)], code [code]."))
|
||||
return TRUE
|
||||
|
||||
if(istype(W, /obj/item/anomaly_releaser))
|
||||
var/obj/item/anomaly_releaser/releaser = W
|
||||
if(releaser.used)
|
||||
return FALSE
|
||||
if(!do_after(user, 3 SECONDS, src))
|
||||
return FALSE
|
||||
|
||||
var/obj/item/assembly/signaler/anomaly/core = src
|
||||
if(!core.anomaly_type)
|
||||
return FALSE
|
||||
|
||||
var/obj/effect/anomaly/anomaly = new core.anomaly_type(get_turf(core))
|
||||
anomaly.stabilize()
|
||||
|
||||
if(!releaser.infinite)
|
||||
releaser.icon_state = releaser.used_icon_state
|
||||
releaser.used = TRUE
|
||||
releaser.name = "used " + name
|
||||
qdel(src)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/flux
|
||||
name = "\improper flux anomaly core"
|
||||
desc = "The neutralized core of a flux anomaly. Touching it makes your skin tingle. It'd probably be valuable for research."
|
||||
icon_state = "flux_core"
|
||||
anomaly_type = /obj/effect/anomaly/flux
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/bluespace
|
||||
name = "\improper bluespace anomaly core"
|
||||
desc = "The neutralized core of a bluespace anomaly. It keeps phasing in and out of view. It'd probably be valuable for research."
|
||||
icon_state = "anomaly_core"
|
||||
anomaly_type = /obj/effect/anomaly/bluespace
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/grav
|
||||
name = "\improper gravitational anomaly core"
|
||||
desc = "The neutralized core of a gravitational anomaly. It feels much heavier than it looks. It'd probably be valuable for research."
|
||||
icon_state = "grav_core"
|
||||
anomaly_type = /obj/effect/anomaly/grav
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/dimensional
|
||||
name = "\improper dimensional anomaly core"
|
||||
desc = "The neutralized core of a dimensional anomaly. Objects reflected on its surface don't look quite right. It'd probably be valuable for research."
|
||||
icon_state = "dimensional_core"
|
||||
anomaly_type = /obj/effect/anomaly/dimensional
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/bioscrambler
|
||||
name = "\improper bioscrambler anomaly core"
|
||||
desc = "The neutralized core of a bioscrambler anomaly. It's squirming, as if moving. It'd probably be valuable for research."
|
||||
icon_state = "bioscrambler_core"
|
||||
anomaly_type = /obj/effect/anomaly/bioscrambler
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/hallucination
|
||||
name = "\improper hallucination anomaly core"
|
||||
desc = "The neutralized core of a hallucination anomaly. It seems to be moving, but it's probably your imagination. It'd probably be valuable for research."
|
||||
icon_state = "hallucination_core"
|
||||
anomaly_type = /obj/effect/anomaly/hallucination
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/pyro
|
||||
name = "\improper pyroclastic anomaly core"
|
||||
desc = "The neutralized core of a pyroclastic anomaly. It feels warm to the touch. It'd probably be valuable for research."
|
||||
icon_state = "pyro_core"
|
||||
anomaly_type = /obj/effect/anomaly/pyro
|
||||
@@ -276,3 +276,32 @@
|
||||
RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_BLUESPACE
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE | DEPARTMENT_BITFLAG_CARGO
|
||||
|
||||
/datum/design_techweb/anomaly_neutralizer
|
||||
name = "Anomaly Neutralizer"
|
||||
desc = "An advanced tool capable of instantly neutralizing anomalies, designed to capture the fleeting aberrations created by the engine."
|
||||
id = "anomaly_neutralizer"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_STEEL = SHEET_MATERIAL_AMOUNT, MAT_GOLD = SHEET_MATERIAL_AMOUNT, MAT_PHORON = SHEET_MATERIAL_AMOUNT * 2.5, MAT_URANIUM = SHEET_MATERIAL_AMOUNT)
|
||||
build_path = /obj/item/anomaly_neutralizer
|
||||
category = list(
|
||||
RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SCIENCE
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_SCIENCE
|
||||
|
||||
/datum/design_techweb/reactive_armour
|
||||
name = "Reactive Armor Shell"
|
||||
desc = "An experimental suit of armour capable of utilizing an implanted anomaly core to protect the user."
|
||||
id = "reactive_armour"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(
|
||||
MAT_STEEL = SHEET_MATERIAL_AMOUNT*5,
|
||||
MAT_URANIUM = SHEET_MATERIAL_AMOUNT*4,
|
||||
MAT_DIAMOND = SHEET_MATERIAL_AMOUNT*2.5,
|
||||
MAT_SILVER = SHEET_MATERIAL_AMOUNT*2.5,
|
||||
MAT_GOLD = SHEET_MATERIAL_AMOUNT*2.5
|
||||
)
|
||||
build_path = /obj/item/clothing/suit/armor/reactive_armor_shell
|
||||
category = list(
|
||||
RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SCIENCE
|
||||
)
|
||||
|
||||
@@ -108,9 +108,9 @@
|
||||
"xenoarch_multitool",
|
||||
"excavationdrill",
|
||||
"ano_scanner",
|
||||
// "anomaly_refinery",
|
||||
// "anomaly_neutralizer",
|
||||
// "reactive_armour",
|
||||
//"anomaly_refinery",
|
||||
"anomaly_neutralizer",
|
||||
"reactive_armour",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = TECHWEB_TIER_3_POINTS)
|
||||
announce_channels = list(CHANNEL_SCIENCE)
|
||||
|
||||
Reference in New Issue
Block a user