Shielding Auras (#8760)

Ports Baystation12/Baystation12#19992 and Baystation12/Baystation12#27266.

    Added a personal shield device to the traitor tools uplink.
    Added a radiant shielding aura spell to Battlemage and Cleric.
    Added an exosuit shield drone to the mechfab.

This works, but I'm not entirely happy with the sprites. The personal shield has no on-mob shimmer, it uses a mindbatterer grenade as an icon sprite. The wizard radiant spell uses a pretty big and janky sprite as an on-mob, and the exosuit's shield sprite doesn't follow the dir the mech faces, but that one I can maybe fix on my own. If anyone knows about that last one, lemme know, Bay had code for it that we do not.
This commit is contained in:
Geeves
2020-05-15 22:37:27 +02:00
committed by GitHub
parent 3a4dc8e0f2
commit 097ea6cfbc
27 changed files with 439 additions and 128 deletions
+5
View File
@@ -762,6 +762,9 @@
#include "code\game\objects\items.dm"
#include "code\game\objects\objs.dm"
#include "code\game\objects\structures.dm"
#include "code\game\objects\auras\auras.dm"
#include "code\game\objects\auras\personal_shield.dm"
#include "code\game\objects\auras\radiant_aura.dm"
#include "code\game\objects\effects\aliens.dm"
#include "code\game\objects\effects\bump_teleporter.dm"
#include "code\game\objects\effects\effect_system.dm"
@@ -840,6 +843,7 @@
#include "code\game\objects\items\devices\multitool.dm"
#include "code\game\objects\items\devices\oxycandle.dm"
#include "code\game\objects\items\devices\paicard.dm"
#include "code\game\objects\items\devices\personal_shield.dm"
#include "code\game\objects\items\devices\pin_extractor.dm"
#include "code\game\objects\items\devices\pipe_painter.dm"
#include "code\game\objects\items\devices\powersink.dm"
@@ -2642,6 +2646,7 @@
#include "code\modules\spell_system\spells\spell_list\self\conjure\golem.dm"
#include "code\modules\spell_system\spells\spell_list\self\conjure\grove.dm"
#include "code\modules\spell_system\spells\spell_list\self\conjure\plant_sanctuary.dm"
#include "code\modules\spell_system\spells\spell_list\self\conjure\radiant_aura.dm"
#include "code\modules\spell_system\spells\spell_list\self\conjure\summon_carp.dm"
#include "code\modules\spell_system\spells\spell_list\self\conjure\summon_demon_creature.dm"
#include "code\modules\spell_system\spells\spell_list\self\conjure\summon_ed_swarm.dm"
+3 -1
View File
@@ -21,6 +21,7 @@
#define SCREEN_LAYER 22 //Mob HUD/effects layer
#define CINEMA_LAYER 23
#define MECH_UNDER_LAYER 4
#define MECH_BASE_LAYER 4.01
#define MECH_INTERMEDIATE_LAYER 4.02
#define MECH_PILOT_LAYER 4.03
@@ -28,4 +29,5 @@
#define MECH_COCKPIT_LAYER 4.05
#define MECH_ARM_LAYER 4.06
#define MECH_DECAL_LAYER 4.07
#define MECH_GEAR_LAYER 4.08
#define MECH_GEAR_LAYER 4.08
#define MECH_ABOVE_LAYER 4.09
+8 -1
View File
@@ -344,4 +344,11 @@
// Surgery Stuff
#define SURGERY_SUCCESS 2 // Proceed with surgery
#define SURGERY_FAIL 1 // Autofail surgery
#define SURGERY_IGNORE 0 // Ignore surgery completely and just attack
#define SURGERY_IGNORE 0 // Ignore surgery completely and just attack
#define AURA_CANCEL 1
#define AURA_FALSE 2
#define AURA_TYPE_BULLET "Bullet"
#define AURA_TYPE_WEAPON "Weapon"
#define AURA_TYPE_THROWN "Thrown"
#define AURA_TYPE_LIFE "Life"
+2
View File
@@ -91,6 +91,8 @@ avoid code duplication. This includes items that may sometimes act as a standard
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
user.do_attack_animation(M)
if(!user.aura_check(AURA_TYPE_WEAPON, src, user))
return FALSE
var/hit_zone = M.resolve_item_attack(src, user, target_zone)
if(hit_zone)
+6
View File
@@ -68,6 +68,12 @@
item_cost = 6
path = /obj/item/card/emag
/datum/uplink_item/item/tools/personal_shield
name = "Personal Shield"
desc = "A personal shield that, when kept in your hand and activated, will protect its user from five projectile shots."
item_cost = 6
path = /obj/item/device/personal_shield
/datum/uplink_item/item/tools/hacking_tool
name = "Door Hacking Tool"
item_cost = 6
+31
View File
@@ -0,0 +1,31 @@
/*Auras are simple: They are simple overriders for attackbys, bullet_act, damage procs, etc. They also tick after their respective mob.
They should be used for undeterminate mob effects, like for instance a toggle-able forcefield, or indestructability as long as you don't move.
They should also be used for when you want to effect the ENTIRE mob, like having an armor buff or showering candy everytime you walk.
*/
/obj/aura
var/mob/living/user
/obj/aura/Destroy()
if(user)
user.remove_aura(src)
return ..()
/obj/aura/proc/added_to(var/mob/living/target)
user = target
user.add_aura(src)
/obj/aura/proc/removed()
user = null
/obj/aura/proc/life_tick()
return FALSE
/obj/aura/attackby(obj/item/I, mob/user)
return FALSE
/obj/aura/bullet_act(obj/item/projectile/P, def_zone)
return FALSE
/obj/aura/hitby(atom/movable/M, speed)
return FALSE
@@ -0,0 +1,34 @@
/obj/aura/personal_shield
name = "personal shield"
/obj/aura/personal_shield/added_to(mob/living/L)
..()
playsound(user, 'sound/weapons/flash.ogg', 35, 1)
to_chat(user, SPAN_NOTICE("You feel your body prickle as \the [src] comes online."))
/obj/aura/personal_shield/bullet_act(obj/item/projectile/P, var/def_zone)
user.visible_message(SPAN_WARNING("\The [user]'s [src.name] flashes before \the [P] can hit them!"))
flick("shield_impact", src)
playsound(user, 'sound/effects/basscannon.ogg', 35, TRUE)
return AURA_FALSE|AURA_CANCEL
/obj/aura/personal_shield/removed()
to_chat(user, SPAN_WARNING("\The [src] goes offline!"))
playsound(user, 'sound/mecha/internaldmgalarm.ogg', 25, TRUE)
..()
/obj/aura/personal_shield/device
var/obj/item/device/personal_shield/shield
/obj/aura/personal_shield/device/bullet_act()
. = ..()
if(shield)
shield.take_charge()
/obj/aura/personal_shield/device/proc/set_shield(var/user_shield)
shield = user_shield
/obj/aura/personal_shield/device/Destroy()
shield = null
return ..()
+21
View File
@@ -0,0 +1,21 @@
/obj/aura/radiant_aura
name = "radiant aura"
icon = 'icons/effects/effects.dmi'
icon_state = "at_shield1"
alpha = 75
layer = ABOVE_MOB_LAYER
/obj/aura/radiant_aura/added_to(mob/living/user)
..()
to_chat(user, SPAN_NOTICE("A bubble of light appears around you, exuding protection and warmth."))
set_light(6, 6, COLOR_AMBER)
/obj/aura/radiant_aura/Destroy()
to_chat(user, SPAN_WARNING("Your protective aura dissipates, leaving you feeling cold and unsafe."))
return ..()
/obj/aura/radiant_aura/bullet_act(obj/item/projectile/P, var/def_zone)
if(P.check_armour == LASER)
user.visible_message(SPAN_WARNING("\The [P] refracts, bending into \the [user]'s aura."))
return AURA_FALSE
return FALSE
@@ -0,0 +1,64 @@
/obj/item/device/personal_shield
name = "personal shield"
desc = "Truely a life-saver: this device protects its user from being hit by objects moving very, very fast, though only for a few shots."
icon = 'icons/obj/device.dmi'
icon_state = "batterer"
var/next_recharge
var/uses = 5
var/obj/aura/personal_shield/device/shield
/obj/item/device/personal_shield/examine(mob/user, distance)
..()
if(Adjacent(user))
to_chat(user, SPAN_NOTICE("\The [src] can absorb [uses] more shot\s."))
/obj/item/device/personal_shield/Initialize()
. = ..()
START_PROCESSING(SSprocessing, src)
/obj/item/device/personal_shield/process()
if(next_recharge < world.time)
uses = min(5, uses + 1)
if(uses == 1)
update_icon()
next_recharge = world.time + 1 MINUTE
/obj/item/device/personal_shield/attack_self(mob/living/user)
if(uses && !shield)
shield = new /obj/aura/personal_shield/device(user)
shield.added_to(user)
shield.set_shield(src)
else
dissipate()
/obj/item/device/personal_shield/Move()
dissipate()
return ..()
/obj/item/device/personal_shield/forceMove()
dissipate()
return ..()
/obj/item/device/personal_shield/proc/take_charge()
uses--
if(!uses)
to_chat(shield.user, FONT_LARGE(SPAN_WARNING("\The [src] begins to spark as it breaks!")))
QDEL_NULL(shield)
update_icon()
return
/obj/item/device/personal_shield/update_icon()
if(uses)
icon_state = "batterer"
else
icon_state = "battererburnt"
/obj/item/device/personal_shield/Destroy()
dissipate()
STOP_PROCESSING(SSprocessing, src)
return ..()
/obj/item/device/personal_shield/proc/dissipate()
if(shield?.user)
to_chat(shield.user, FONT_LARGE(SPAN_WARNING("\The [src] fades around you, dissipating.")))
QDEL_NULL(shield)
@@ -287,3 +287,157 @@
if(istype(C))
return C.charge/C.maxcharge
return null
/obj/item/mecha_equipment/shield
name = "exosuit shield droid"
desc = "The Hephaestus Armature system is a well liked energy deflector system designed to stop any projectile before it has a chance to become a threat."
icon_state = "shield_droid"
var/obj/aura/mechshield/aura
var/max_charge = 150
var/charge = 150
var/last_recharge = 0
var/charging_rate = 7500 * CELLRATE
var/cooldown = 3.5 SECONDS // Time until we can recharge again after a blocked impact
restricted_hardpoints = list(HARDPOINT_BACK)
restricted_software = list(MECH_SOFTWARE_WEAPONS)
/obj/item/mecha_equipment/shield/installed(mob/living/heavy_vehicle/_owner)
. = ..()
aura = new /obj/aura/mechshield(_owner)
aura.added_to(_owner)
aura.set_holder(src)
/obj/item/mecha_equipment/shield/uninstalled()
QDEL_NULL(aura)
. = ..()
/obj/item/mecha_equipment/shield/attack_self(mob/user)
. = ..()
if(.)
toggle()
/obj/item/mecha_equipment/shield/proc/stop_damage(var/damage)
var/difference = damage - charge
charge = Clamp(charge - damage, 0, max_charge)
last_recharge = world.time
if(difference > 0)
for(var/mob/pilot in owner.pilots)
to_chat(pilot, FONT_LARGE(SPAN_WARNING("Warning: Deflector shield failure detected, shutting down.")))
toggle()
playsound(get_turf(owner),'sound/mecha/internaldmgalarm.ogg', 35, TRUE)
return difference
else
return FALSE
/obj/item/mecha_equipment/shield/proc/toggle()
if(!aura)
return
aura.toggle()
aura.dir = owner.dir
if(aura.dir == NORTH)
aura.layer = MECH_UNDER_LAYER
else
aura.layer = ABOVE_MOB_LAYER
playsound(owner,'sound/weapons/flash.ogg', 35, TRUE)
update_icon()
if(aura.active)
START_PROCESSING(SSprocessing, src)
else
STOP_PROCESSING(SSprocessing, src)
owner.update_icon()
/obj/item/mecha_equipment/shield/update_icon()
. = ..()
if(!aura)
return
if(aura.active)
icon_state = "shield_droid_a"
else
icon_state = "shield_droid"
/obj/item/mecha_equipment/shield/process()
if(charge >= max_charge)
return
if((world.time - last_recharge) < cooldown)
return
var/obj/item/cell/cell = owner.get_cell()
var/actual_required_power = Clamp(max_charge - charge, 0, charging_rate)
charge += cell.use(actual_required_power)
/obj/item/mecha_equipment/shield/get_hardpoint_status_value()
return charge / max_charge
/obj/item/mecha_equipment/shield/get_hardpoint_maptext()
return "[(aura && aura.active) ? "ONLINE" : "OFFLINE"]: [round((charge / max_charge) * 100)]%"
/obj/aura/mechshield
icon = 'icons/mecha/shield.dmi'
name = "mechshield"
var/obj/item/mecha_equipment/shield/shields
var/active = FALSE
layer = ABOVE_MOB_LAYER
pixel_x = 8
pixel_y = 4
mouse_opacity = 0
/obj/aura/mechshield/added_to(mob/living/target)
..()
target.vis_contents += src
dir = target.dir
/obj/aura/mechshield/proc/set_holder(var/obj/item/mecha_equipment/shield/holder)
shields = holder
/obj/aura/mechshield/Destroy()
if(user)
user.vis_contents -= src
shields = null
. = ..()
/obj/aura/mechshield/proc/toggle()
active = !active
update_icon()
if(active)
flick("shield_raise", src)
else
flick("shield_drop", src)
/obj/aura/mechshield/update_icon()
. = ..()
if(active)
icon_state = "shield"
else
icon_state = "shield_null"
/obj/aura/mechshield/bullet_act(obj/item/projectile/P, var/def_zone)
if(!active)
return
if(shields?.charge)
P.damage = shields.stop_damage(P.damage)
user.visible_message(SPAN_WARNING("\The [shields.owner]'s shields flash and crackle."))
flick("shield_impact", src)
playsound(user, 'sound/effects/basscannon.ogg', 35, TRUE)
//light up the night.
new /obj/effect/effect/smoke/illumination(get_turf(src), 5, 4, 1, "#ffffff")
if(P.damage <= 0)
return AURA_FALSE|AURA_CANCEL
spark(get_turf(src), 5, global.alldirs)
playsound(get_turf(src), "sparks", 25, TRUE)
/obj/aura/mechshield/hitby(atom/movable/M, var/speed)
. = ..()
if(!active)
return
if(shields.charge && speed <= 5)
user.visible_message(SPAN_WARNING("\The [shields.owner]'s shields flash briefly as they deflect \the [M]."))
flick("shield_impact", src)
playsound(user, 'sound/effects/basscannon.ogg', 10, TRUE)
return AURA_FALSE|AURA_CANCEL
//Too fast!
@@ -307,6 +307,14 @@
playsound(src.loc,legs.mech_turn_sound,40,1)
next_move = world.time + legs.turn_delay
set_dir(direction)
if(istype(hardpoints[HARDPOINT_BACK], /obj/item/mecha_equipment/shield))
var/obj/item/mecha_equipment/shield/S = hardpoints[HARDPOINT_BACK]
if(S.aura)
S.aura.dir = direction
if(S.aura.dir == NORTH)
S.aura.layer = MECH_UNDER_LAYER
else
S.aura.layer = ABOVE_MOB_LAYER
update_icon()
/mob/living/heavy_vehicle/Move()
-124
View File
@@ -1,124 +0,0 @@
/mob/living/exosuit
movement_handlers = list(
/datum/movement_handler/mob/space/exosuit,
/datum/movement_handler/mob/exosuit
)
/mob/living/exosuit/Move()
. = ..()
if(. && !istype(loc, /turf/space) && legs.mech_step_sound)
playsound(src.loc, mech_step_sound, 40, 1)
//Override this and space move once a way to travel vertically is in
///mob/living/exosuit/can_ztravel()
// if(Allow_Spacemove()) //Handle here
// return 1
// for(var/turf/simulated/T in trange(1,src))
// if(T.density)
// return 1
/mob/living/exosuit/can_fall(var/anchor_bypass = FALSE, var/turf/location_override = src.loc)
//mechs are always anchored, so falling should always ignore it
if(..(TRUE, location_override))
return !(can_overcome_gravity())
/datum/movement_handler/mob/exosuit
expected_host_type = /mob/living/exosuit
var/next_move
/datum/movement_handler/mob/exosuit/MayMove(var/mob/mover, var/is_external)
var/mob/living/exosuit/exosuit = host
if(world.time < next_move)
return MOVEMENT_STOP
if((!(mover in exosuit.pilots) && mover != exosuit) || exosuit.incapacitated() || mover.incapacitated())
return MOVEMENT_STOP
if(!exosuit.legs)
to_chat(mover, "<span class='warning'>\The [exosuit] has no means of propulsion!</span>")
next_move = world.time + 3 // Just to stop them from getting spammed with messages.
return MOVEMENT_STOP
if(!exosuit.legs.motivator || !exosuit.legs.motivator.is_functional())
to_chat(mover, "<span class='warning'>Your motivators are damaged! You can't move!</span>")
next_move = world.time + 15
return MOVEMENT_STOP
if(exosuit.maintenance_protocols)
to_chat(mover, "<span class='warning'>Maintenance protocols are in effect.</span>")
next_move = world.time + 3 // Just to stop them from getting spammed with messages.
return MOVEMENT_STOP
if(exosuit.lockdown)
to_chat(mover, span("warning", "You cannot move while the exosuit's lockdown mode is active."))
next_move = world.time + 3 // Just to stop them from getting spammed with messages.
return MOVEMENT_STOP
var/obj/item/cell/C = exosuit.get_cell()
if(!C || !C.check_charge(exosuit.legs.power_use * CELLRATE))
to_chat(mover, "<span class='warning'>The power indicator flashes briefly.</span>")
next_move = world.time + 3 //On fast exosuits this got annoying fast
return MOVEMENT_STOP
next_move = world.time + (exosuit.legs ? exosuit.legs.move_delay : 3)
return MOVEMENT_PROCEED
/datum/movement_handler/mob/exosuit/DoMove(var/direction, var/mob/mover, var/is_external)
var/mob/living/exosuit/exosuit = host
var/moving_dir = direction
var/failed = FALSE
if(exosuit.emp_damage >= EMP_MOVE_DISRUPT && prob(30))
failed = TRUE
if(failed)
moving_dir = pick(cardinal - exosuit.dir)
exosuit.get_cell().use(exosuit.legs.power_use * CELLRATE)
if(exosuit.dir != moving_dir)
playsound(exosuit.loc, exosuit.mech_turn_sound, 40,1)
exosuit.set_dir(moving_dir)
next_move = world.time + exosuit.legs.turn_delay
else
var/turf/target_loc = get_step(exosuit, direction)
if(target_loc && exosuit.legs && exosuit.legs.can_move_on(exosuit.loc, target_loc) && exosuit.MayEnterTurf(target_loc))
exosuit.Move(target_loc)
return MOVEMENT_HANDLED
/datum/movement_handler/mob/space/exosuit
expected_host_type = /mob/living/exosuit
// Space movement
/datum/movement_handler/mob/space/exosuit/DoMove(var/direction, var/mob/mover)
if(!mob.check_solid_ground())
mob.anchored = FALSE
var/allowmove = mob.Allow_Spacemove(0)
if(!allowmove)
return MOVEMENT_HANDLED
else if(allowmove == -1 && mob.handle_spaceslipping()) //Check to see if we slipped
return MOVEMENT_HANDLED
else
mob.inertia_dir = 0 //If not then we can reset inertia and move
else mob.anchored = TRUE
/datum/movement_handler/mob/space/exosuit/MayMove(var/mob/mover, var/is_external)
if((mover != host) && is_external)
return MOVEMENT_PROCEED
if(!mob.check_solid_ground())
if(!mob.Allow_Spacemove(0))
return MOVEMENT_STOP
return MOVEMENT_PROCEED
/mob/living/exosuit/lost_in_space()
for(var/atom/movable/AM in contents)
if(!AM.lost_in_space())
return FALSE
return !pilots.len
/mob/living/exosuit/fall_damage()
return 100 //Exosuits are big and heavy
/mob/living/exosuit/handle_fall_effect(var/turf/landing)
// Return here if for any reason you shouldnt take damage
..()
var/damage = 30 //Enough to cause a malfunction if unlucky
apply_damage(rand(0, damage), BRUTE, BP_R_LEG) //Any leg is good, will damage both
@@ -11,6 +11,7 @@
h_l_hand = /obj/item/mecha_equipment/mounted_system/taser/laser
h_r_hand = /obj/item/mecha_equipment/mounted_system/taser/ion
h_back = /obj/item/mecha_equipment/shield
/obj/item/mech_component/manipulators/heavy
name = "heavy arms"
@@ -149,6 +149,11 @@ There are several things that need to be remembered:
if(species.has_floating_eyes)
ovr += species.get_eyes(src)
for(var/aura in auras)
var/obj/aura/A = aura
var/icon/aura_overlay = icon(A.icon, icon_state = A.icon_state)
ovr += aura_overlay
add_overlay(ovr)
if (lying_prev != lying || size_multiplier != 1)
+2
View File
@@ -25,6 +25,8 @@
//Random events (vomiting etc)
handle_random_events()
aura_check(AURA_TYPE_LIFE)
. = 1
//Handle temperature/pressure differences between body and environment
+22
View File
@@ -906,3 +906,25 @@ default behaviour is:
Paralyse(rand(8,16))
make_jittery(rand(150,200))
adjustHalLoss(rand(50,60))
/mob/living/update_icons()
for(var/aura in auras)
var/obj/aura/A = aura
var/icon/aura_overlay = icon(A.icon, icon_state = A.icon_state)
add_overlay(aura_overlay)
/mob/living/proc/add_aura(var/obj/aura/aura)
LAZYDISTINCTADD(auras, aura)
update_icons()
return TRUE
/mob/living/proc/remove_aura(var/obj/aura/aura)
LAZYREMOVE(auras, aura)
update_icons()
return TRUE
/mob/living/Destroy()
if(auras)
for(var/a in auras)
remove_aura(a)
return ..()
+24
View File
@@ -100,6 +100,28 @@
P.on_hit(src, absorb, def_zone)
return absorb
/mob/living/proc/aura_check(var/type)
if(!auras)
return TRUE
. = TRUE
var/list/newargs = args - args[1]
for(var/a in auras)
var/obj/aura/aura = a
var/result = 0
switch(type)
if(AURA_TYPE_WEAPON)
result = aura.attackby(arglist(newargs))
if(AURA_TYPE_BULLET)
result = aura.bullet_act(arglist(newargs))
if(AURA_TYPE_THROWN)
result = aura.hitby(arglist(newargs))
if(AURA_TYPE_LIFE)
result = aura.life_tick()
if(result & AURA_FALSE)
. = FALSE
if(result & AURA_CANCEL)
break
//For visuals, blood splatters and so on.
/mob/living/proc/bullet_impact_visuals(var/obj/item/projectile/P, var/def_zone, var/damage)
var/list/impact_sounds = LAZYACCESS(P.impact_sounds, get_bullet_impact_effect_type(def_zone))
@@ -170,6 +192,8 @@
//this proc handles being hit by a thrown atom
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve
if(!aura_check(AURA_TYPE_THROWN, AM, speed))
return
if(istype(AM,/obj/))
var/obj/O = AM
var/dtype = O.damtype
+2 -1
View File
@@ -69,4 +69,5 @@
var/burn_mod = 1
var/brute_mod = 1
var/limb_breaking = FALSE // used to limit people from queuing up limb-breaks
var/limb_breaking = FALSE // used to limit people from queuing up limb-breaks
var/list/obj/aura/auras //Basically a catch-all aura/force-field thing.
+2
View File
@@ -174,6 +174,8 @@
var/result = PROJECTILE_FORCE_MISS
if(hit_zone)
def_zone = hit_zone //set def_zone, so if the projectile ends up hitting someone else later (to be implemented), it is more likely to hit the same part
if(!target_mob.aura_check(AURA_TYPE_BULLET, src, def_zone))
return TRUE
result = target_mob.bullet_act(src, def_zone)
if(result == PROJECTILE_FORCE_MISS && (can_miss == 0)) //if you're shooting at point blank you can't miss.
@@ -267,4 +267,11 @@
/datum/design/item/mechfab/exosuit/passenger_compartment
name = "Mounted Passenger Compartment"
materials = list(DEFAULT_WALL_MATERIAL = 10000)
build_path = /obj/item/mecha_equipment/sleeper/passenger_compartment
build_path = /obj/item/mecha_equipment/sleeper/passenger_compartment
/datum/design/item/mechfab/exosuit/mechshields
name = "Energy Shield Drone"
time = 90
materials = list(MATERIAL_STEEL = 20000, MATERIAL_SILVER = 12000, MATERIAL_GOLD = 12000)
req_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 4, TECH_POWER = 4, TECH_COMBAT = 2)
build_path = /obj/item/mecha_equipment/shield
@@ -22,6 +22,7 @@
/spell/aoe_turf/conjure/mirage = 1,
/spell/targeted/shapeshift/corrupt_form = 1,
/spell/targeted/flesh_to_stone = 1,
/spell/radiant_aura = 1,
/spell/noclothes = 1,
/obj/structure/closet/wizard/armor = 1,
/obj/item/gun/energy/staff/focus = 1,
@@ -24,6 +24,7 @@
/spell/aoe_turf/knock = 1,
/spell/targeted/equip_item/holy_relic = 1,
/spell/aoe_turf/conjure/grove/sanctuary = 1,
/spell/radiant_aura = 1,
/spell/targeted/projectile/dumbfire/fireball = 2,
/spell/aoe_turf/conjure/forcewall = 1,
/spell/targeted/subjugation = 1,
@@ -0,0 +1,27 @@
/spell/radiant_aura
name = "Radiant Aura"
desc = "Form a protective layer of light around you, making you immune to laser fire."
school = "transmutation"
feedback = "ra"
invocation_type = SpI_EMOTE
invocation = "conjures a sphere of fire around themselves."
school = "conjuration"
spell_flags = NEEDSCLOTHES
charge_max = 300
cooldown_min = 200
level_max = list(Sp_TOTAL = 2, Sp_SPEED = 2, Sp_POWER = 0)
cast_sound = 'sound/effects/snap.ogg'
duration = 250
hud_state = "gen_immolate"
/spell/radiant_aura/choose_targets()
return list(holder)
/spell/radiant_aura/cast(var/list/targets, mob/user)
var/obj/aura/radiant_aura/A = new /obj/aura/radiant_aura(user)
A.added_to(user)
QDEL_IN(A, duration)
/spell/radiant_aura/starlight
spell_flags = 0
charge_max = 400
+8
View File
@@ -0,0 +1,8 @@
author: Geeves
delete-after: True
changes:
- rscadd: "Added a personal shield device to the traitor tools uplink."
- rscadd: "Added a radiant shielding aura spell to Battlemage and Cleric."
- rscadd: "Added an exosuit shield drone to the mechfab."
Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 18 KiB