/obj/projectile/magic name = "bolt" icon_state = "energy" damage = 0 damage_type = OXY nodamage = TRUE armour_penetration = 100 flag = MAGIC /obj/projectile/magic/death name = "bolt of death" icon_state = "pulse1_bl" /obj/projectile/magic/death/on_hit(mob/living/target) . = ..() if(!istype(target)) return if(target.anti_magic_check()) target.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK if(target.mob_biotypes & MOB_UNDEAD) //negative energy heals the undead if(target.revive(full_heal = TRUE, admin_revive = TRUE)) target.grab_ghost(force = TRUE) // even suicides to_chat(target, span_notice("You rise with a start, you're undead!!!")) else if(target.stat != DEAD) to_chat(target, span_notice("You feel great!")) return target.death() /obj/projectile/magic/resurrection name = "bolt of resurrection" icon_state = "ion" damage = 0 damage_type = OXY nodamage = TRUE /obj/projectile/magic/resurrection/on_hit(mob/living/carbon/target) . = ..() if(isliving(target)) if(target.anti_magic_check()) target.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK if(target.mob_biotypes & MOB_UNDEAD) //positive energy harms the undead target.death(0) else if(target.revive(full_heal = TRUE, admin_revive = TRUE)) target.grab_ghost(force = TRUE) // even suicides to_chat(target, span_notice("You rise with a start, you're alive!!!")) else if(target.stat != DEAD) to_chat(target, span_notice("You feel great!")) /obj/projectile/magic/teleport name = "bolt of teleportation" icon_state = "bluespace" damage = 0 damage_type = OXY nodamage = TRUE var/inner_tele_radius = 0 var/outer_tele_radius = 6 /obj/projectile/magic/teleport/on_hit(mob/target) . = ..() if(ismob(target)) var/mob/M = target if(M.anti_magic_check()) M.visible_message(span_warning("[src] fizzles on contact with [target]!")) return BULLET_ACT_BLOCK var/teleammount = 0 var/teleloc = target if(!isturf(target)) teleloc = target.loc for(var/atom/movable/stuff in teleloc) if(!stuff.anchored && stuff.loc && !isobserver(stuff)) if(do_teleport(stuff, stuff, 10, channel = TELEPORT_CHANNEL_MAGIC)) teleammount++ var/datum/effect_system/smoke_spread/smoke = new smoke.set_up(max(round(4 - teleammount),0), stuff.loc) //Smoke drops off if a lot of stuff is moved for the sake of sanity smoke.start() /obj/projectile/magic/safety name = "bolt of safety" icon_state = "bluespace" damage = 0 damage_type = OXY nodamage = TRUE /obj/projectile/magic/safety/on_hit(atom/target) . = ..() if(ismob(target)) var/mob/M = target if(M.anti_magic_check()) M.visible_message(span_warning("[src] fizzles on contact with [target]!")) return BULLET_ACT_BLOCK if(isturf(target)) return BULLET_ACT_HIT var/turf/origin_turf = get_turf(target) var/turf/destination_turf = find_safe_turf() if(do_teleport(target, destination_turf, channel=TELEPORT_CHANNEL_MAGIC)) for(var/t in list(origin_turf, destination_turf)) var/datum/effect_system/smoke_spread/smoke = new smoke.set_up(0, t) smoke.start() /obj/projectile/magic/door name = "bolt of door creation" icon_state = "energy" damage = 0 damage_type = OXY nodamage = TRUE var/list/door_types = list(/obj/structure/mineral_door/wood, /obj/structure/mineral_door/iron, /obj/structure/mineral_door/silver, /obj/structure/mineral_door/gold, /obj/structure/mineral_door/uranium, /obj/structure/mineral_door/sandstone, /obj/structure/mineral_door/transparent/plasma, /obj/structure/mineral_door/transparent/diamond) /obj/projectile/magic/door/on_hit(atom/target) . = ..() if(istype(target, /obj/machinery/door)) OpenDoor(target) else var/turf/T = get_turf(target) if(isclosedturf(T) && !isindestructiblewall(T)) CreateDoor(T) /obj/projectile/magic/door/proc/CreateDoor(turf/T) var/door_type = pick(door_types) var/obj/structure/mineral_door/D = new door_type(T) T.ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) D.Open() /obj/projectile/magic/door/proc/OpenDoor(obj/machinery/door/D) if(istype(D, /obj/machinery/door/airlock)) var/obj/machinery/door/airlock/A = D A.locked = FALSE D.open() /obj/projectile/magic/change name = "bolt of change" icon_state = "ice_1" damage = 0 damage_type = BURN nodamage = TRUE /obj/projectile/magic/change/on_hit(atom/change) . = ..() if(isliving(change)) var/mob/living/M = change if(M.anti_magic_check()) M.visible_message(span_warning("[src] fizzles on contact with [M]!")) qdel(src) return BULLET_ACT_BLOCK M.wabbajack() qdel(src) /obj/projectile/magic/animate name = "bolt of animation" icon_state = "red_1" damage = 0 damage_type = BURN nodamage = TRUE /obj/projectile/magic/animate/on_hit(atom/target, blocked = FALSE) target.animate_atom_living(firer) ..() /atom/proc/animate_atom_living(mob/living/owner = null) if((isitem(src) || isstructure(src)) && !is_type_in_list(src, GLOB.protected_objects)) if(istype(src, /obj/structure/statue/petrified)) var/obj/structure/statue/petrified/P = src if(P.petrified_mob) var/mob/living/L = P.petrified_mob var/mob/living/simple_animal/hostile/statue/S = new(P.loc, owner) S.name = "statue of [L.name]" if(owner) S.faction = list("[REF(owner)]") S.icon = P.icon S.icon_state = P.icon_state S.copy_overlays(P, TRUE) S.color = P.color S.atom_colours = P.atom_colours.Copy() if(L.mind) L.mind.transfer_to(S) if(owner) to_chat(S, span_userdanger("You are an animate statue. You cannot move when monitored, but are nearly invincible and deadly when unobserved! Do not harm [owner], your creator.")) P.forceMove(S) return else var/obj/O = src if(istype(O, /obj/item/gun)) new /mob/living/simple_animal/hostile/mimic/copy/ranged(drop_location(), src, owner) else new /mob/living/simple_animal/hostile/mimic/copy(drop_location(), src, owner) else if(istype(src, /mob/living/simple_animal/hostile/mimic/copy)) // Change our allegiance! var/mob/living/simple_animal/hostile/mimic/copy/C = src if(owner) C.ChangeOwner(owner) /obj/projectile/magic/spellblade name = "blade energy" icon_state = "lavastaff" damage = 15 damage_type = BURN flag = MAGIC dismemberment = 50 nodamage = FALSE /obj/projectile/magic/spellblade/on_hit(target) if(ismob(target)) var/mob/M = target if(M.anti_magic_check()) M.visible_message(span_warning("[src] vanishes on contact with [target]!")) qdel(src) return BULLET_ACT_BLOCK . = ..() /obj/projectile/magic/arcane_barrage name = "arcane bolt" icon_state = "arcane_barrage" damage = 20 damage_type = BURN nodamage = FALSE armour_penetration = 0 flag = MAGIC hitsound = 'sound/weapons/barragespellhit.ogg' /obj/projectile/magic/arcane_barrage/on_hit(target) if(ismob(target)) var/mob/M = target if(M.anti_magic_check()) M.visible_message(span_warning("[src] vanishes on contact with [target]!")) qdel(src) return BULLET_ACT_BLOCK . = ..() /obj/projectile/magic/locker name = "locker bolt" icon_state = "locker" nodamage = TRUE flag = MAGIC var/weld = TRUE var/created = FALSE //prevents creation of more then one locker if it has multiple hits var/locker_suck = TRUE var/obj/structure/closet/decay/locker_temp_instance /obj/projectile/magic/locker/Initialize() . = ..() locker_temp_instance = new(src) /obj/projectile/magic/locker/prehit_pierce(atom/A) . = ..() if(isliving(A) && locker_suck) var/mob/living/M = A if(M.anti_magic_check()) // no this doesn't check if ..() returned to phase through do I care no it's magic ain't gotta explain shit M.visible_message(span_warning("[src] vanishes on contact with [A]!")) return PROJECTILE_DELETE_WITHOUT_HITTING if(!locker_temp_instance.insertion_allowed(M)) return M.forceMove(src) return PROJECTILE_PIERCE_PHASE /obj/projectile/magic/locker/on_hit(target) if(created) return ..() if(LAZYLEN(contents)) for(var/atom/movable/AM in contents) locker_temp_instance.insert(AM) locker_temp_instance.welded = weld locker_temp_instance.update_appearance() created = TRUE return ..() /obj/projectile/magic/locker/Destroy() locker_suck = FALSE for(var/atom/movable/AM in contents) AM.forceMove(get_turf(src)) . = ..() /obj/structure/closet/decay breakout_time = 600 icon_welded = null icon_state = "cursed" var/weakened_icon = "decursed" var/auto_destroy = TRUE /obj/structure/closet/decay/Initialize() . = ..() if(auto_destroy) addtimer(CALLBACK(src, .proc/bust_open), 5 MINUTES) /obj/structure/closet/decay/after_weld(weld_state) if(weld_state) unmagify() ///Fade away into nothing /obj/structure/closet/decay/proc/decay() animate(src, alpha = 0, time = 30) addtimer(CALLBACK(GLOBAL_PROC, .proc/qdel, src), 30) /obj/structure/closet/decay/open(mob/living/user, force = FALSE) . = ..() if(.) unmagify() ///Give it the lesser magic icon and tell it to delete itself /obj/structure/closet/decay/proc/unmagify() icon_state = weakened_icon update_appearance() addtimer(CALLBACK(src, .proc/decay), 15 SECONDS) /obj/projectile/magic/flying name = "bolt of flying" icon_state = "flight" /obj/projectile/magic/flying/on_hit(target) . = ..() if(isliving(target)) var/mob/living/L = target if(L.anti_magic_check()) L.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK var/atom/throw_target = get_edge_target_turf(L, angle2dir(Angle)) L.throw_at(throw_target, 200, 4) /obj/projectile/magic/bounty name = "bolt of bounty" icon_state = "bounty" /obj/projectile/magic/bounty/on_hit(target) . = ..() if(isliving(target)) var/mob/living/L = target if(L.anti_magic_check() || !firer) L.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK L.apply_status_effect(STATUS_EFFECT_BOUNTY, firer) /obj/projectile/magic/antimagic name = "bolt of antimagic" icon_state = "antimagic" /obj/projectile/magic/antimagic/on_hit(target) . = ..() if(isliving(target)) var/mob/living/L = target if(L.anti_magic_check()) L.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK L.apply_status_effect(STATUS_EFFECT_ANTIMAGIC) /obj/projectile/magic/fetch name = "bolt of fetching" icon_state = "fetch" /obj/projectile/magic/fetch/on_hit(target) . = ..() if(isliving(target)) var/mob/living/L = target if(L.anti_magic_check() || !firer) L.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK var/atom/throw_target = get_edge_target_turf(L, get_dir(L, firer)) L.throw_at(throw_target, 200, 4) /obj/projectile/magic/sapping name = "bolt of sapping" icon_state = "sapping" /obj/projectile/magic/sapping/on_hit(target) . = ..() if(ismob(target)) var/mob/M = target if(M.anti_magic_check()) M.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, src, /datum/mood_event/sapped) /obj/projectile/magic/necropotence name = "bolt of necropotence" icon_state = "necropotence" /obj/projectile/magic/necropotence/on_hit(target) . = ..() if(isliving(target)) var/mob/living/L = target if(L.anti_magic_check() || !L.mind) L.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK to_chat(L, span_danger("Your body feels drained and there is a burning pain in your chest.")) L.maxHealth -= 20 L.health = min(L.health, L.maxHealth) if(L.maxHealth <= 0) to_chat(L, span_userdanger("Your weakened soul is completely consumed by the [src]!")) return for(var/obj/effect/proc_holder/spell/spell in L.mind.spell_list) spell.charge_counter = spell.charge_max spell.recharging = FALSE spell.update_appearance() /obj/projectile/magic/wipe name = "bolt of possession" icon_state = "wipe" /obj/projectile/magic/wipe/on_hit(target) . = ..() if(iscarbon(target)) var/mob/living/carbon/M = target if(M.anti_magic_check()) M.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK for(var/x in M.get_traumas())//checks to see if the victim is already going through possession if(istype(x, /datum/brain_trauma/special/imaginary_friend/trapped_owner)) M.visible_message(span_warning("[src] vanishes on contact with [target]!")) return BULLET_ACT_BLOCK to_chat(M, span_warning("Your mind has been opened to possession!")) possession_test(M) return BULLET_ACT_HIT /obj/projectile/magic/wipe/proc/possession_test(mob/living/carbon/M) var/datum/brain_trauma/special/imaginary_friend/trapped_owner/trauma = M.gain_trauma(/datum/brain_trauma/special/imaginary_friend/trapped_owner) var/poll_message = "Do you want to play as [M.real_name]?" if(M.mind) poll_message = "[poll_message] Job:[M.mind.assigned_role.title]." if(M.mind && M.mind.special_role) poll_message = "[poll_message] Status:[M.mind.special_role]." else if(M.mind) var/datum/antagonist/A = M.mind.has_antag_datum(/datum/antagonist/) if(A) poll_message = "[poll_message] Status:[A.name]." var/list/mob/dead/observer/candidates = pollCandidatesForMob(poll_message, ROLE_PAI, FALSE, 100, M) if(M.stat == DEAD)//boo. return if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) to_chat(M, span_boldnotice("You have been noticed by a ghost and it has possessed you!")) var/oldkey = M.key M.ghostize(0) M.key = C.key trauma.friend.key = oldkey trauma.friend.reset_perspective(null) trauma.friend.Show() trauma.friend_initialized = TRUE else to_chat(M, span_notice("Your mind has managed to go unnoticed in the spirit world.")) qdel(trauma) /obj/projectile/magic/aoe name = "Area Bolt" desc = "What the fuck does this do?!" damage = 0 var/proxdet = TRUE /obj/projectile/magic/aoe/Range() if(proxdet) for(var/mob/living/L in range(1, get_turf(src))) if(L.stat != DEAD && L != firer && !L.anti_magic_check()) return Bump(L) ..() /obj/projectile/magic/aoe/lightning name = "lightning bolt" icon_state = "tesla_projectile" //Better sprites are REALLY needed and appreciated!~ damage = 15 damage_type = BURN nodamage = FALSE speed = 0.3 flag = MAGIC var/zap_power = 20000 var/zap_range = 15 var/zap_flags = ZAP_MOB_DAMAGE | ZAP_MOB_STUN | ZAP_OBJ_DAMAGE var/chain var/mob/living/caster /obj/projectile/magic/aoe/lightning/fire(setAngle) if(caster) chain = caster.Beam(src, icon_state = "lightning[rand(1, 12)]") ..() /obj/projectile/magic/aoe/lightning/on_hit(target) . = ..() if(ismob(target)) var/mob/M = target if(M.anti_magic_check()) visible_message(span_warning("[src] fizzles on contact with [target]!")) qdel(src) return BULLET_ACT_BLOCK tesla_zap(src, zap_range, zap_power, zap_flags) qdel(src) /obj/projectile/magic/aoe/lightning/no_zap zap_power = 10000 zap_range = 4 zap_flags = ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE /obj/projectile/magic/aoe/lightning/Destroy() qdel(chain) . = ..() /obj/projectile/magic/aoe/fireball name = "bolt of fireball" icon_state = "fireball" damage = 10 damage_type = BRUTE nodamage = FALSE //explosion values var/exp_heavy = 0 var/exp_light = 2 var/exp_flash = 3 var/exp_fire = 2 /obj/projectile/magic/aoe/fireball/on_hit(target) . = ..() if(ismob(target)) var/mob/living/M = target if(M.anti_magic_check()) visible_message(span_warning("[src] vanishes into smoke on contact with [target]!")) return BULLET_ACT_BLOCK M.take_overall_damage(0,10) //between this 10 burn, the 10 brute, the explosion brute, and the onfire burn, your at about 65 damage if you stop drop and roll immediately var/turf/T = get_turf(target) explosion(T, devastation_range = -1, heavy_impact_range = exp_heavy, light_impact_range = exp_light, flame_range = exp_fire, flash_range = exp_flash, adminlog = FALSE) //still magic related, but a different path /obj/projectile/temp/chill name = "bolt of chills" icon_state = "ice_2" damage = 0 damage_type = BURN nodamage = FALSE armour_penetration = 100 temperature = -200 // Cools you down greatly per hit flag = MAGIC /obj/projectile/magic/nothing name = "bolt of nothing"