Anomaly core modules for modsuits (#23154)

* firewall

* shielded part 1

* WIP: Anomaly core modules for modsuits

* icons, vortex

* cryogrenade, nerfs teslawall

* message admins moment

* Update uplink_nuclear.dm

* rnd designs

* now uses the flayer icon state

* Apply suggestions from code review

Co-authored-by: Ryan <80364400+Sirryan2002@users.noreply.github.com>

* early returns, barricade types, and comments, oh my

* Apply suggestions from code review

Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>

* updates desc, remove comment, removes /hardsuit/

---------

Co-authored-by: Ryan <80364400+Sirryan2002@users.noreply.github.com>
Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>
This commit is contained in:
Qwertytoforty
2024-01-21 19:17:18 +00:00
committed by GitHub
co-authored by Ryan Henri215
parent db578cdc6f
commit 192b8224b8
33 changed files with 699 additions and 243 deletions
+15 -1
View File
@@ -187,6 +187,20 @@
/obj/item/mod/module/jetpack/advanced,
)
/obj/item/mod/control/pre_equipped/safeguard/gamma
applied_cell = /obj/item/stock_parts/cell/hyper
applied_modules = list(
/obj/item/mod/module/storage/large_capacity,
/obj/item/mod/module/flashlight,
/obj/item/mod/module/dispenser/mirage,
/obj/item/mod/module/jetpack/advanced,
/obj/item/mod/module/holster,
/obj/item/mod/module/energy_shield/gamma,
)
default_pins = list(
/obj/item/mod/module/jetpack/advanced,
)
/obj/item/mod/control/pre_equipped/magnate
theme = /datum/mod_theme/magnate
applied_cell = /obj/item/stock_parts/cell/hyper
@@ -332,7 +346,7 @@
/obj/item/mod/control/pre_equipped/responsory/security
insignia_type = /obj/item/mod/module/insignia/security
additional_module = /obj/item/mod/module/dispenser/mirage
additional_module = /obj/item/mod/module/anomaly_locked/firewall/prebuilt //Defence and flaming hot offence. Good for reflective blob, xenos, antagonists with guns
/obj/item/mod/control/pre_equipped/responsory/engineer
insignia_type = /obj/item/mod/module/insignia/engineer
+150
View File
@@ -409,3 +409,153 @@
/obj/item/mod/module/ert_camera/on_suit_deactivation(deleting = FALSE)
QDEL_NULL(camera)
///Energy Shield - Gives you a rechargeable energy shield that nullifies attacks.
/obj/item/mod/module/energy_shield
name = "MOD energy shield module"
desc = "A personal, protective forcefield typically seen in military applications. \
This advanced deflector shield is essentially a scaled down version of those seen on starships, \
and the power cost can be an easy indicator of this. However, it is capable of blocking nearly any incoming attack, \
though with its' low amount of separate charges, the user remains mortal."
icon_state = "energy_shield"
complexity = 3
idle_power_cost = DEFAULT_CHARGE_DRAIN * 0.5
use_power_cost = DEFAULT_CHARGE_DRAIN * 2
incompatible_modules = list(/obj/item/mod/module/energy_shield)
/// Max charges of the shield.
var/max_charges = 3
/// The time it takes for the first charge to recover.
var/recharge_start_delay = 20 SECONDS
/// How much time it takes for charges to recover after they started recharging.
var/charge_increment_delay = 1 SECONDS
/// How much charge is recovered per recovery.
var/charge_recovery = 1
/// Whether or not this shield can lose multiple charges.
var/lose_multiple_charges = FALSE
/// The item path to recharge this shield.
var/recharge_path = null
/// The icon file of the shield.
var/shield_icon_file = 'icons/effects/effects.dmi'
/// The icon_state of the shield.
var/shield_icon = "shield-red"
/// Charges the shield should start with.
var/charges
/obj/item/mod/module/energy_shield/Initialize(mapload)
. = ..()
charges = max_charges
/obj/item/mod/module/energy_shield/on_suit_activation()
mod.AddComponent(/datum/component/shielded, max_charges = max_charges, recharge_start_delay = recharge_start_delay, charge_increment_delay = charge_increment_delay, \
charge_recovery = charge_recovery, lose_multiple_charges = lose_multiple_charges, recharge_path = recharge_path, starting_charges = charges, shield_icon_file = shield_icon_file, shield_icon = shield_icon)
RegisterSignal(mod.wearer, COMSIG_HUMAN_CHECK_SHIELDS, PROC_REF(shield_reaction))
/obj/item/mod/module/energy_shield/on_suit_deactivation(deleting = FALSE)
var/datum/component/shielded/shield = mod.GetComponent(/datum/component/shielded)
charges = shield.current_charges
qdel(shield)
UnregisterSignal(mod.wearer, COMSIG_HUMAN_CHECK_SHIELDS)
/obj/item/mod/module/energy_shield/proc/shield_reaction(mob/living/carbon/human/owner,
atom/movable/hitby,
attack_text = "the attack",
final_block_chance = 0,
damage = 0,
attack_type = MELEE_ATTACK,
damage_type = BRUTE
)
SIGNAL_HANDLER
if(SEND_SIGNAL(mod, COMSIG_ITEM_HIT_REACT, owner, hitby, damage, attack_type) & COMPONENT_BLOCK_SUCCESSFUL)
drain_power(use_power_cost)
return SHIELD_BLOCK
return NONE
/obj/item/mod/module/energy_shield/gamma
shield_icon = "shield-old"
/obj/item/mod/module/anomaly_locked/teslawall
name = "MOD arc-shield module" // temp
desc = "A module that uses a flux core to project an unstable protective shield." //change
icon_state = "tesla"
complexity = 3
idle_power_cost = DEFAULT_CHARGE_DRAIN * 3
use_power_cost = DEFAULT_CHARGE_DRAIN * 75
accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/flux)
incompatible_modules = list(/obj/item/mod/module/energy_shield, /obj/item/mod/module/anomaly_locked)
///Copy paste of shielded code wheeeey
/// Max charges of the shield.
var/max_charges = 80 // Less charges because not gamma / this one is real shocking
/// The time it takes for the first charge to recover.
var/recharge_start_delay = 10 SECONDS
/// How much time it takes for charges to recover after they started recharging.
var/charge_increment_delay = 10 SECONDS
/// How much charge is recovered per recovery.
var/charge_recovery = 20
/// Whether or not this shield can lose multiple charges.
var/lose_multiple_charges = TRUE
/// The item path to recharge this shield.
var/recharge_path = null
/// The icon file of the shield.
var/shield_icon_file = 'icons/effects/effects.dmi'
/// The icon_state of the shield.
var/shield_icon = "electricity3"
/// Charges the shield should start with.
var/charges
/// Teslawall specific variables.
var/zap_flags = ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE
var/zap_range = 5
var/power = 12500
var/shock_damage = 30
/obj/item/mod/module/anomaly_locked/teslawall/Initialize(mapload)
. = ..()
charges = max_charges
/obj/item/mod/module/anomaly_locked/teslawall/on_suit_activation()
mod.AddComponent(/datum/component/shielded, max_charges = max_charges, recharge_start_delay = recharge_start_delay, charge_increment_delay = charge_increment_delay, \
charge_recovery = charge_recovery, lose_multiple_charges = lose_multiple_charges, show_charge_as_alpha = lose_multiple_charges, recharge_path = recharge_path, starting_charges = charges, shield_icon_file = shield_icon_file, shield_icon = shield_icon)
RegisterSignal(mod.wearer, COMSIG_HUMAN_CHECK_SHIELDS, PROC_REF(shield_reaction))
ADD_TRAIT(mod.wearer, TRAIT_SHOCKIMMUNE, UNIQUE_TRAIT_SOURCE(src))
/obj/item/mod/module/anomaly_locked/teslawall/on_suit_deactivation(deleting = FALSE)
var/datum/component/shielded/shield = mod.GetComponent(/datum/component/shielded)
charges = shield.current_charges
qdel(shield)
UnregisterSignal(mod.wearer, COMSIG_HUMAN_CHECK_SHIELDS)
REMOVE_TRAIT(mod.wearer, TRAIT_SHOCKIMMUNE, UNIQUE_TRAIT_SOURCE(src))
/obj/item/mod/module/anomaly_locked/teslawall/proc/shield_reaction(mob/living/carbon/human/owner,
atom/movable/hitby,
attack_text = "the attack",
final_block_chance = 0,
damage = 0,
attack_type = MELEE_ATTACK,
damage_type = BRUTE
)
SIGNAL_HANDLER
if(SEND_SIGNAL(mod, COMSIG_ITEM_HIT_REACT, owner, hitby, damage, attack_type) & COMPONENT_BLOCK_SUCCESSFUL)
drain_power(use_power_cost)
arc_flash(owner, hitby, damage, attack_type)
return SHIELD_BLOCK
return NONE
/obj/item/mod/module/anomaly_locked/teslawall/proc/arc_flash(mob/owner, atom/movable/hitby, damage, attack_type)
if((attack_type == PROJECTILE_ATTACK || attack_type == THROWN_PROJECTILE_ATTACK) && prob(33))
tesla_zap(owner, zap_range, power, zap_flags)
return
if(isitem(hitby))
if(isliving(hitby.loc))
var/mob/living/M = hitby.loc
M.electrocute_act(shock_damage, owner, flags = SHOCK_NOGLOVES)
M.KnockDown(3 SECONDS)
else if(isliving(hitby))
var/mob/living/M = hitby
M.electrocute_act(shock_damage, owner, flags = SHOCK_NOGLOVES)
M.KnockDown(3 SECONDS)
/obj/item/mod/module/anomaly_locked/teslawall/prebuilt
prebuilt = TRUE
removable = FALSE // No switching it into another suit / no free anomaly core
@@ -166,3 +166,126 @@
/// Remove the image from the modsuit wearer's screen
/obj/effect/temp_visual/sonar_ping/proc/remove_mind(mob/living/looker)
looker?.client?.images -= modsuit_image
///Firewall. Deployable dropwall that lights projectiles on fire.
/obj/item/mod/module/anomaly_locked/firewall
name = "MOD firewall module"
desc = "A module that uses a pyroclastic core to make immolating dropwalls."
icon_state = "firewall"
overlay_state_inactive = "module_mirage_grenade"
module_type = MODULE_ACTIVE
complexity = 3
use_power_cost = DEFAULT_CHARGE_DRAIN * 5
cooldown_time = 20 SECONDS
accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/pyro)
/// Path we dispense.
var/dispense_type = /obj/item/grenade/barrier/dropwall/firewall
/obj/item/mod/module/anomaly_locked/firewall/on_use()
. = ..()
if(!.)
return
var/obj/item/dispensed = new dispense_type(mod.wearer.loc)
mod.wearer.put_in_hands(dispensed)
playsound(src, 'sound/machines/click.ogg', 100, TRUE)
drain_power(use_power_cost)
var/obj/item/grenade/grenade = dispensed
grenade.attack_self(mod.wearer)
return grenade
/obj/item/mod/module/anomaly_locked/firewall/prebuilt
prebuilt = TRUE
removable = FALSE // No switching it into another suit / no free anomaly core
/// Vortex arm mounted shotgun. Fucks up reality in front of it, very power draining. Compeating with the vortex arm and stealth armor after all
/obj/item/mod/module/anomaly_locked/vortex_shotgun
name = "MOD vortex shotgun module"
desc = "A module that uses a vortex core to rend the fabric of space time in front of it."
icon_state = "vortex"
module_type = MODULE_ACTIVE
complexity = 3
use_power_cost = DEFAULT_CHARGE_DRAIN * 750
device = /obj/item/gun/energy/vortex_shotgun
accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/vortex)
/obj/item/mod/module/anomaly_locked/vortex_shotgun/Initialize(mapload)
. = ..()
RegisterSignal(device, COMSIG_GUN_FIRED, PROC_REF(on_gun_fire))
/obj/item/mod/module/anomaly_locked/vortex_shotgun/proc/on_gun_fire()
SIGNAL_HANDLER
if(!drain_power(use_power_cost)) //Drain the rest dry
drain_power(mod.core.check_charge())
/obj/item/mod/module/anomaly_locked/vortex_shotgun/prebuilt
prebuilt = TRUE
removable = FALSE // No switching it into another suit / no free anomaly core
///Cryogrenade. Freezes foes in place, cools them
/obj/item/mod/module/anomaly_locked/cryogrenade
name = "MOD Cryogrenade module"
desc = "A module that uses a cryogenic core to make freezing grenades."
icon_state = "cryogrenade"
overlay_state_inactive = "module_mirage_grenade"
module_type = MODULE_ACTIVE
complexity = 3
use_power_cost = DEFAULT_CHARGE_DRAIN * 5
cooldown_time = 20 SECONDS
accepted_anomalies = list(/obj/item/assembly/signaler/anomaly/cryo)
/// Path we dispense.
var/dispense_type = /obj/item/grenade/cryogrenade_mod
/obj/item/mod/module/anomaly_locked/cryogrenade/on_use()
. = ..()
if(!.)
return
var/obj/item/dispensed = new dispense_type(mod.wearer.loc)
mod.wearer.put_in_hands(dispensed)
playsound(src, 'sound/machines/click.ogg', 100, TRUE)
drain_power(use_power_cost)
var/obj/item/grenade/grenade = dispensed
grenade.attack_self(mod.wearer)
return grenade
/obj/item/mod/module/anomaly_locked/cryogrenade/prebuilt
prebuilt = TRUE
removable = FALSE // No switching it into another suit / no free anomaly core
/obj/item/grenade/cryogrenade_mod
name = "cryogenic grenade"
desc = "A very cold grenade."
icon = 'icons/obj/grenade.dmi'
icon_state = "gluon"
item_state = "grenade"
var/freeze_range = 4
var/stamina_damage = 60
var/body_adjustment = -230
var/reagent_volume = 15
/// Mob that threw the grenade.
var/mob/living/thrower
/obj/item/grenade/cryogrenade_mod/Destroy()
thrower = null
return ..()
/obj/item/grenade/cryogrenade_mod/attack_self(mob/user)
. = ..()
thrower = user
/obj/item/grenade/cryogrenade_mod/prime()
update_mob()
playsound(loc, 'sound/effects/empulse.ogg', 50, TRUE)
for(var/turf/simulated/floor/T in view(freeze_range, loc))
T.MakeSlippery(TURF_WET_ICE)
for(var/mob/living/carbon/C in T)
if(C == thrower)
continue
C.adjustStaminaLoss(stamina_damage)
C.adjust_bodytemperature(body_adjustment)
C.apply_status_effect(/datum/status_effect/freon)
if(C.reagents)
C.reagents.add_reagent("frostoil", reagent_volume)
C.reagents.add_reagent("ice", reagent_volume)
qdel(src)