//The chests dropped by mob spawner tendrils. Also contains associated loot. /obj/structure/closet/crate/necropolis name = "necropolis chest" desc = "It's watching you closely." icon_state = "necrocrate" resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF /obj/structure/closet/crate/necropolis/tendril desc = "It's watching you suspiciously." /obj/structure/closet/crate/necropolis/tendril/PopulateContents() var/loot = rand(1,27) switch(loot) if(1) new /obj/item/device/shared_storage/red(src) if(2) new /obj/item/clothing/suit/space/hardsuit/cult(src) if(3) new /obj/item/device/soulstone/anybody(src) if(4) new /obj/item/katana/cursed(src) if(5) new /obj/item/clothing/glasses/godeye(src) if(6) new /obj/item/reagent_containers/glass/bottle/potion/flight(src) if(7) new /obj/item/pickaxe/diamond(src) if(8) if(prob(50)) new /obj/item/disk/design_disk/modkit_disc/resonator_blast(src) else new /obj/item/disk/design_disk/modkit_disc/rapid_repeater(src) if(9) new /obj/item/organ/brain/alien(src) if(10) new /obj/item/organ/heart/cursed/wizard(src) if(11) new /obj/item/ship_in_a_bottle(src) if(12) new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker(src) if(13) new /obj/item/jacobs_ladder(src) if(14) new /obj/item/nullrod/scythe/talking(src) if(15) new /obj/item/nullrod/armblade(src) if(16) new /obj/item/guardiancreator(src) if(17) if(prob(50)) new /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe(src) else new /obj/item/disk/design_disk/modkit_disc/bounty(src) if(18) new /obj/item/device/warp_cube/red(src) if(19) new /obj/item/device/wisp_lantern(src) if(20) new /obj/item/device/immortality_talisman(src) if(21) new /obj/item/gun/magic/hook(src) if(22) new /obj/item/voodoo(src) if(23) new /obj/item/grenade/clusterbuster/inferno(src) if(24) new /obj/item/reagent_containers/food/drinks/bottle/holywater/hell(src) new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor(src) if(25) new /obj/item/spellbook/oneuse/summonitem(src) if(26) new /obj/item/book_of_babel(src) if(27) new /obj/item/borg/upgrade/modkit/lifesteal(src) new /obj/item/bedsheet/cult(src) //KA modkit design discs /obj/item/disk/design_disk/modkit_disc name = "KA Mod Disk" desc = "A design disc containing the design for a unique kinetic accelerator modkit." icon_state = "datadisk1" var/modkit_design = /datum/design/unique_modkit /obj/item/disk/design_disk/modkit_disc/Initialize() . = ..() blueprints[1] = new modkit_design /obj/item/disk/design_disk/modkit_disc/mob_and_turf_aoe name = "Offensive Mining Explosion Mod Disk" modkit_design = /datum/design/unique_modkit/offensive_turf_aoe /obj/item/disk/design_disk/modkit_disc/rapid_repeater name = "Rapid Repeater Mod Disk" modkit_design = /datum/design/unique_modkit/rapid_repeater /obj/item/disk/design_disk/modkit_disc/resonator_blast name = "Resonator Blast Mod Disk" modkit_design = /datum/design/unique_modkit/resonator_blast /obj/item/disk/design_disk/modkit_disc/bounty name = "Death Syphon Mod Disk" modkit_design = /datum/design/unique_modkit/bounty /datum/design/unique_modkit category = list("Mining Designs", "Cyborg Upgrade Modules") req_tech = list("materials" = 12) //can't be normally obtained build_type = PROTOLATHE | MECHFAB /datum/design/unique_modkit/offensive_turf_aoe name = "Kinetic Accelerator Offensive Mining Explosion Mod" desc = "A device which causes kinetic accelerators to fire AoE blasts that destroy rock and damage creatures." id = "hyperaoemod" materials = list(MAT_METAL = 7000, MAT_GLASS = 3000, MAT_SILVER = 3000, MAT_GOLD = 3000, MAT_DIAMOND = 4000) build_path = /obj/item/borg/upgrade/modkit/aoe/turfs/andmobs /datum/design/unique_modkit/rapid_repeater name = "Kinetic Accelerator Rapid Repeater Mod" desc = "A device which greatly reduces a kinetic accelerator's cooldown on striking a living target or rock, but greatly increases its base cooldown." id = "repeatermod" materials = list(MAT_METAL = 5000, MAT_GLASS = 5000, MAT_URANIUM = 8000, MAT_BLUESPACE = 2000) build_path = /obj/item/borg/upgrade/modkit/cooldown/repeater /datum/design/unique_modkit/resonator_blast name = "Kinetic Accelerator Resonator Blast Mod" desc = "A device which causes kinetic accelerators to fire shots that leave and detonate resonator blasts." id = "resonatormod" materials = list(MAT_METAL = 5000, MAT_GLASS = 5000, MAT_SILVER = 5000, MAT_URANIUM = 5000) build_path = /obj/item/borg/upgrade/modkit/resonator_blasts /datum/design/unique_modkit/bounty name = "Kinetic Accelerator Death Syphon Mod" desc = "A device which causes kinetic accelerators to permenantly gain damage against creature types killed with it." id = "bountymod" materials = list(MAT_METAL = 4000, MAT_SILVER = 4000, MAT_GOLD = 4000, MAT_BLUESPACE = 4000) reagents_list = list("blood" = 40) build_path = /obj/item/borg/upgrade/modkit/bounty //Spooky special loot //Wisp Lantern /obj/item/device/wisp_lantern name = "spooky lantern" desc = "This lantern gives off no light, but is home to a friendly wisp." icon = 'icons/obj/lighting.dmi' icon_state = "lantern-blue" item_state = "lantern" lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi' var/obj/effect/wisp/wisp /obj/item/device/wisp_lantern/attack_self(mob/user) if(!wisp) to_chat(user, "The wisp has gone missing!") return if(wisp.loc == src) to_chat(user, "You release the wisp. It begins to bob around your head.") user.sight |= SEE_MOBS icon_state = "lantern" wisp.orbit(user, 20) SSblackbox.add_details("wisp_lantern","Freed") else to_chat(user, "You return the wisp to the lantern.") if(wisp.orbiting) var/atom/A = wisp.orbiting.orbiting if(isliving(A)) var/mob/living/M = A M.sight &= ~SEE_MOBS to_chat(M, "Your vision returns to normal.") wisp.stop_orbit() wisp.loc = src icon_state = "lantern-blue" SSblackbox.add_details("wisp_lantern","Returned") /obj/item/device/wisp_lantern/Initialize() . = ..() wisp = new(src) /obj/item/device/wisp_lantern/Destroy() if(wisp) if(wisp.loc == src) qdel(wisp) else wisp.visible_message("[wisp] has a sad feeling for a moment, then it passes.") ..() /obj/effect/wisp name = "friendly wisp" desc = "Happy to light your way." icon = 'icons/obj/lighting.dmi' icon_state = "orb" luminosity = 7 layer = ABOVE_ALL_MOB_LAYER //Red/Blue Cubes /obj/item/device/warp_cube name = "blue cube" desc = "A mysterious blue cube." icon = 'icons/obj/lavaland/artefacts.dmi' icon_state = "blue_cube" var/teleport_color = "#3FBAFD" var/obj/item/device/warp_cube/linked var/teleporting = FALSE /obj/item/device/warp_cube/attack_self(mob/user) if(!linked) to_chat(user, "[src] fizzles uselessly.") return if(teleporting) return teleporting = TRUE linked.teleporting = TRUE var/turf/T = get_turf(src) new /obj/effect/temp_visual/warp_cube(T, user, teleport_color, TRUE) SSblackbox.add_details("warp_cube","[src.type]") new /obj/effect/temp_visual/warp_cube(get_turf(linked), user, linked.teleport_color, FALSE) var/obj/effect/warp_cube/link_holder = new /obj/effect/warp_cube(T) user.forceMove(link_holder) //mess around with loc so the user can't wander around sleep(2.5) if(QDELETED(user)) qdel(link_holder) return if(QDELETED(linked)) user.forceMove(get_turf(link_holder)) qdel(link_holder) return link_holder.forceMove(get_turf(linked)) sleep(2.5) if(QDELETED(user)) qdel(link_holder) return teleporting = FALSE if(!QDELETED(linked)) linked.teleporting = FALSE user.forceMove(get_turf(link_holder)) qdel(link_holder) /obj/item/device/warp_cube/red name = "red cube" desc = "A mysterious red cube." icon_state = "red_cube" teleport_color = "#FD3F48" /obj/item/device/warp_cube/red/Initialize() . = ..() if(!linked) var/obj/item/device/warp_cube/blue = new(src.loc) linked = blue blue.linked = src /obj/effect/warp_cube mouse_opacity = MOUSE_OPACITY_TRANSPARENT /obj/effect/warp_cube/ex_act(severity, target) return //Meat Hook /obj/item/gun/magic/hook name = "meat hook" desc = "Mid or feed." ammo_type = /obj/item/ammo_casing/magic/hook icon_state = "hook" item_state = "chain" lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' fire_sound = 'sound/weapons/batonextend.ogg' max_charges = 1 flags_1 = NOBLUDGEON_1 force = 18 /obj/item/ammo_casing/magic/hook name = "hook" desc = "a hook." projectile_type = /obj/item/projectile/hook caliber = "hook" icon_state = "hook" /obj/item/projectile/hook name = "hook" icon_state = "hook" icon = 'icons/obj/lavaland/artefacts.dmi' pass_flags = PASSTABLE damage = 25 armour_penetration = 100 damage_type = BRUTE hitsound = 'sound/effects/splat.ogg' knockdown = 30 var/chain /obj/item/projectile/hook/fire(setAngle) if(firer) chain = firer.Beam(src, icon_state = "chain", time = INFINITY, maxdistance = INFINITY) ..() //TODO: root the firer until the chain returns /obj/item/projectile/hook/on_hit(atom/target) . = ..() if(ismovableatom(target)) var/atom/movable/A = target if(A.anchored) return A.visible_message("[A] is snagged by [firer]'s hook!") new /datum/forced_movement(A, get_turf(firer), 5, TRUE) //TODO: keep the chain beamed to A //TODO: needs a callback to delete the chain /obj/item/projectile/hook/Destroy() qdel(chain) return ..() //Immortality Talisman /obj/item/device/immortality_talisman name = "Immortality Talisman" desc = "A dread talisman that can render you completely invulnerable." icon = 'icons/obj/lavaland/artefacts.dmi' icon_state = "talisman" actions_types = list(/datum/action/item_action/immortality) var/cooldown = 0 /datum/action/item_action/immortality name = "Immortality" /obj/item/device/immortality_talisman/Destroy(force) if(force) . = ..() else return QDEL_HINT_LETMELIVE /obj/item/device/immortality_talisman/attack_self(mob/user) if(cooldown < world.time) SSblackbox.add_details("immortality_talisman","Activated") // usage cooldown = world.time + 600 user.visible_message("[user] vanishes from reality, leaving a hole in [user.p_their()] place!") var/obj/effect/immortality_talisman/Z = new(get_turf(src.loc)) Z.name = "hole in reality" Z.desc = "It's shaped an awful lot like [user.name]." Z.setDir(user.dir) user.forceMove(Z) user.notransform = 1 user.status_flags |= GODMODE addtimer(CALLBACK(src, .proc/return_to_reality, user, Z), 100) /obj/item/device/immortality_talisman/proc/return_to_reality(mob/user, obj/effect/immortality_talisman/Z) user.status_flags &= ~GODMODE user.notransform = 0 user.forceMove(get_turf(Z)) user.visible_message("[user] pops back into reality!") Z.can_destroy = TRUE qdel(Z) /obj/effect/immortality_talisman icon_state = "blank" icon = 'icons/effects/effects.dmi' var/can_destroy = FALSE /obj/effect/immortality_talisman/attackby() return /obj/effect/immortality_talisman/ex_act() return /obj/effect/immortality_talisman/singularity_pull() return 0 /obj/effect/immortality_talisman/Destroy(force) if(!can_destroy && !force) return QDEL_HINT_LETMELIVE else . = ..() //Shared Bag //Internal /obj/item/storage/backpack/shared name = "paradox bag" desc = "Somehow, it's in two places at once." max_combined_w_class = 60 max_w_class = WEIGHT_CLASS_NORMAL //External /obj/item/device/shared_storage name = "paradox bag" desc = "Somehow, it's in two places at once." icon = 'icons/obj/storage.dmi' icon_state = "cultpack" slot_flags = SLOT_BACK var/obj/item/storage/backpack/shared/bag /obj/item/device/shared_storage/red name = "paradox bag" desc = "Somehow, it's in two places at once." /obj/item/device/shared_storage/red/Initialize() . = ..() if(!bag) var/obj/item/storage/backpack/shared/S = new(src) var/obj/item/device/shared_storage/blue = new(src.loc) src.bag = S blue.bag = S /obj/item/device/shared_storage/attackby(obj/item/W, mob/user, params) if(bag) bag.loc = user bag.attackby(W, user, params) /obj/item/device/shared_storage/attack_hand(mob/living/carbon/user) if(!iscarbon(user)) return if(loc == user && user.back && user.back == src) if(bag) bag.loc = user bag.attack_hand(user) else ..() /obj/item/device/shared_storage/MouseDrop(atom/over_object) if(iscarbon(usr) || isdrone(usr)) var/mob/M = usr if(!over_object) return if(ismecha(usr.loc)) return if(!M.incapacitated()) playsound(loc, "rustle", 50, 1, -5) if(istype(over_object, /obj/screen/inventory/hand)) var/obj/screen/inventory/hand/H = over_object M.putItemFromInventoryInHandIfPossible(src, H.held_index) add_fingerprint(usr) //Book of Babel /obj/item/book_of_babel name = "Book of Babel" desc = "An ancient tome written in countless tongues." icon = 'icons/obj/library.dmi' icon_state = "book1" w_class = 2 /obj/item/book_of_babel/attack_self(mob/user) to_chat(user, "You flip through the pages of the book, quickly and conveniently learning every language in existence. Somewhat less conveniently, the aging book crumbles to dust in the process. Whoops.") user.grant_all_languages(omnitongue=TRUE) new /obj/effect/decal/cleanable/ash(get_turf(user)) qdel(src) //Boat /obj/vehicle/lavaboat name = "lava boat" desc = "A boat used for traversing lava." icon_state = "goliath_boat" icon = 'icons/obj/lavaland/dragonboat.dmi' resistance_flags = LAVA_PROOF | FIRE_PROOF /obj/vehicle/lavaboat/buckle_mob(mob/living/M, force = 0, check_loc = 1) . = ..() riding_datum = new/datum/riding/boat /obj/item/oar name = "oar" icon = 'icons/obj/vehicles.dmi' icon_state = "oar" item_state = "oar" lefthand_file = 'icons/mob/inhands/misc/lavaland_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/lavaland_righthand.dmi' desc = "Not to be confused with the kind Research hassles you for." force = 12 w_class = WEIGHT_CLASS_NORMAL resistance_flags = LAVA_PROOF | FIRE_PROOF /datum/crafting_recipe/oar name = "goliath bone oar" result = /obj/item/oar reqs = list(/obj/item/stack/sheet/bone = 2) time = 15 category = CAT_PRIMAL /datum/crafting_recipe/boat name = "goliath hide boat" result = /obj/vehicle/lavaboat reqs = list(/obj/item/stack/sheet/animalhide/goliath_hide = 3) time = 50 category = CAT_PRIMAL //Dragon Boat /obj/item/ship_in_a_bottle name = "ship in a bottle" desc = "A tiny ship inside a bottle." icon = 'icons/obj/lavaland/artefacts.dmi' icon_state = "ship_bottle" /obj/item/ship_in_a_bottle/attack_self(mob/user) to_chat(user, "You're not sure how they get the ships in these things, but you're pretty sure you know how to get it out.") playsound(user.loc, 'sound/effects/glassbr1.ogg', 100, 1) new /obj/vehicle/lavaboat/dragon(get_turf(src)) qdel(src) /obj/vehicle/lavaboat/dragon name = "mysterious boat" desc = "This boat moves where you will it, without the need for an oar." icon_state = "dragon_boat" /obj/vehicle/lavaboat/dragon/buckle_mob(mob/living/M, force = 0, check_loc = 1) ..() riding_datum = new/datum/riding/boat/dragon //Potion of Flight /obj/item/reagent_containers/glass/bottle/potion icon = 'icons/obj/lavaland/artefacts.dmi' icon_state = "potionflask" /obj/item/reagent_containers/glass/bottle/potion/flight name = "strange elixir" desc = "A flask with an almost-holy aura emitting from it. The label on the bottle says: 'erqo'hyy tvi'rf lbh jv'atf'." list_reagents = list("flightpotion" = 5) /obj/item/reagent_containers/glass/bottle/potion/update_icon() if(reagents.total_volume) icon_state = "potionflask" else icon_state = "potionflask_empty" /datum/reagent/flightpotion name = "Flight Potion" id = "flightpotion" description = "Strange mutagenic compound of unknown origins." reagent_state = LIQUID color = "#FFEBEB" /datum/reagent/flightpotion/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1) if(iscarbon(M) && M.stat != DEAD) if(!ishumanbasic(M) || reac_volume < 5) // implying xenohumans are holy if(method == INGEST && show_message) to_chat(M, "You feel nothing but a terrible aftertaste.") return ..() to_chat(M, "A terrible pain travels down your back as wings burst out!") M.set_species(/datum/species/angel) playsound(M.loc, 'sound/items/poster_ripped.ogg', 50, 1, -1) M.adjustBruteLoss(20) M.emote("scream") ..() /obj/item/jacobs_ladder name = "jacob's ladder" desc = "A celestial ladder that violates the laws of physics." icon = 'icons/obj/structures.dmi' icon_state = "ladder00" /obj/item/jacobs_ladder/attack_self(mob/user) var/turf/T = get_turf(src) var/ladder_x = T.x var/ladder_y = T.y to_chat(user, "You unfold the ladder. It extends much farther than you were expecting.") for(var/i in 1 to world.maxz) if(i == ZLEVEL_CENTCOM || i == ZLEVEL_TRANSIT) continue var/turf/T2 = locate(ladder_x, ladder_y, i) new /obj/structure/ladder/unbreakable/jacob(T2) qdel(src) /obj/structure/ladder/unbreakable/jacob name = "jacob's ladder" desc = "An indestructible celestial ladder that violates the laws of physics." auto_connect = TRUE ///Bosses //Miniboss Miner /obj/item/melee/transforming/cleaving_saw name = "cleaving saw" desc = "This saw, effective at drawing the blood of beasts, transforms into a long cleaver that makes use of centrifugal force." force = 12 force_on = 20 //force when active throwforce = 20 throwforce_on = 20 icon = 'icons/obj/lavaland/artefacts.dmi' lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi' righthand_file = 'icons/mob/inhands/64x64_righthand.dmi' inhand_x_dimension = 64 inhand_y_dimension = 64 icon_state = "cleaving_saw" icon_state_on = "cleaving_saw_open" slot_flags = SLOT_BELT attack_verb_off = list("attacked", "sawed", "sliced", "torn", "ripped", "diced", "cut") attack_verb_on = list("cleaved", "swiped", "slashed", "chopped") hitsound = 'sound/weapons/bladeslice.ogg' hitsound_on = 'sound/weapons/bladeslice.ogg' w_class = WEIGHT_CLASS_BULKY sharpness = IS_SHARP faction_bonus_force = 30 nemesis_factions = list("mining", "boss") var/transform_cooldown var/swiping = FALSE /obj/item/melee/transforming/cleaving_saw/examine(mob/user) ..() to_chat(user, "It is [active ? "open, and will cleave enemies in a wide arc":"closed, and can be used for rapid consecutive attacks that cause beastly enemies to bleed"].
\ Both modes will build up existing bleed effects, doing a burst of high damage if the bleed is built up high enough.
\ Transforming it immediately after an attack causes the next attack to come out faster.
") /obj/item/melee/transforming/cleaving_saw/suicide_act(mob/user) user.visible_message("[user] is [active ? "closing [src] on [user.p_their()] neck" : "opening [src] into [user.p_their()] chest"]! It looks like [user.p_theyre()] trying to commit suicide!") transform_cooldown = 0 transform_weapon(user, TRUE) return BRUTELOSS /obj/item/melee/transforming/cleaving_saw/transform_weapon(mob/living/user, supress_message_text) if(transform_cooldown > world.time) return FALSE . = ..() if(.) transform_cooldown = world.time + (CLICK_CD_MELEE * 0.5) user.changeNext_move(CLICK_CD_MELEE * 0.25) /obj/item/melee/transforming/cleaving_saw/transform_messages(mob/living/user, supress_message_text) if(!supress_message_text) if(active) to_chat(user, "You open [src]. It will now cleave enemies in a wide arc.") else to_chat(user, "You close [src]. It will now attack rapidly and cause beastly enemies to bleed.") playsound(user, 'sound/magic/clockwork/fellowship_armory.ogg', 35, TRUE, frequency = 90000 - (active * 30000)) /obj/item/melee/transforming/cleaving_saw/clumsy_transform_effect(mob/living/user) if(user.disabilities & CLUMSY && prob(50)) to_chat(user, "You accidentally cut yourself with [src], like a doofus!") user.take_bodypart_damage(10) /obj/item/melee/transforming/cleaving_saw/melee_attack_chain(mob/user, atom/target, params) ..() if(!active) user.changeNext_move(CLICK_CD_MELEE * 0.5) //when closed, it attacks very rapidly /obj/item/melee/transforming/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target) var/datum/status_effect/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED) if(!B) if(!active) //This isn't in the above if-check so that the else doesn't care about active target.apply_status_effect(STATUS_EFFECT_SAWBLEED) else B.add_bleed(B.bleed_buildup) /obj/item/melee/transforming/cleaving_saw/attack(mob/living/target, mob/living/carbon/human/user) if(!active || swiping || !target.density || get_turf(target) == get_turf(user)) if(!active) faction_bonus_force = 0 ..() if(!active) faction_bonus_force = initial(faction_bonus_force) else var/turf/user_turf = get_turf(user) var/dir_to_target = get_dir(user_turf, get_turf(target)) swiping = TRUE var/static/list/cleaving_saw_cleave_angles = list(0, -45, 45) //so that the animation animates towards the target clicked and not towards a side target for(var/i in cleaving_saw_cleave_angles) var/turf/T = get_step(user_turf, turn(dir_to_target, i)) for(var/mob/living/L in T) if(user.Adjacent(L) && L.density) melee_attack_chain(user, L) swiping = FALSE //Dragon /obj/structure/closet/crate/necropolis/dragon name = "dragon chest" /obj/structure/closet/crate/necropolis/dragon/PopulateContents() var/loot = rand(1,4) switch(loot) if(1) new /obj/item/melee/ghost_sword(src) if(2) new /obj/item/lava_staff(src) if(3) new /obj/item/spellbook/oneuse/sacredflame(src) new /obj/item/gun/magic/wand/fireball(src) if(4) new /obj/item/dragons_blood(src) /obj/structure/closet/crate/necropolis/dragon/crusher name = "firey dragon chest" /obj/structure/closet/crate/necropolis/dragon/crusher/PopulateContents() ..() new /obj/item/crusher_trophy/tail_spike(src) /obj/item/melee/ghost_sword name = "\improper spectral blade" desc = "A rusted and dulled blade. It doesn't look like it'd do much damage. It glows weakly." icon_state = "spectral" item_state = "spectral" lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' flags_1 = CONDUCT_1 sharpness = IS_SHARP w_class = WEIGHT_CLASS_BULKY force = 1 throwforce = 1 hitsound = 'sound/effects/ghost2.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "rended") var/summon_cooldown = 0 var/list/mob/dead/observer/spirits /obj/item/melee/ghost_sword/Initialize() . = ..() spirits = list() START_PROCESSING(SSobj, src) GLOB.poi_list |= src /obj/item/melee/ghost_sword/Destroy() for(var/mob/dead/observer/G in spirits) G.invisibility = GLOB.observer_default_invisibility spirits.Cut() STOP_PROCESSING(SSobj, src) GLOB.poi_list -= src . = ..() /obj/item/melee/ghost_sword/attack_self(mob/user) if(summon_cooldown > world.time) to_chat(user, "You just recently called out for aid. You don't want to annoy the spirits.") return to_chat(user, "You call out for aid, attempting to summon spirits to your side.") notify_ghosts("[user] is raising [user.p_their()] [src], calling for your help!", enter_link="(Click to help)", source = user, action=NOTIFY_ORBIT) summon_cooldown = world.time + 600 /obj/item/melee/ghost_sword/Topic(href, href_list) if(href_list["orbit"]) var/mob/dead/observer/ghost = usr if(istype(ghost)) ghost.ManualFollow(src) /obj/item/melee/ghost_sword/process() ghost_check() /obj/item/melee/ghost_sword/proc/ghost_check() var/ghost_counter = 0 var/turf/T = get_turf(src) var/list/contents = T.GetAllContents() var/mob/dead/observer/current_spirits = list() var/list/orbiters = list() for(var/thing in contents) var/atom/A = thing if (A.orbiters) orbiters += A.orbiters for(var/thing in orbiters) var/datum/orbit/O = thing if (isobserver(O.orbiter)) var/mob/dead/observer/G = O.orbiter ghost_counter++ G.invisibility = 0 current_spirits |= G for(var/mob/dead/observer/G in spirits - current_spirits) G.invisibility = GLOB.observer_default_invisibility spirits = current_spirits return ghost_counter /obj/item/melee/ghost_sword/attack(mob/living/target, mob/living/carbon/human/user) force = 0 var/ghost_counter = ghost_check() force = Clamp((ghost_counter * 4), 0, 75) user.visible_message("[user] strikes with the force of [ghost_counter] vengeful spirits!") ..() /obj/item/melee/ghost_sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) var/ghost_counter = ghost_check() final_block_chance += Clamp((ghost_counter * 5), 0, 75) owner.visible_message("[owner] is protected by a ring of [ghost_counter] ghosts!") return ..() //Blood /obj/item/dragons_blood name = "bottle of dragons blood" desc = "You're not actually going to drink this, are you?" icon = 'icons/obj/wizard.dmi' icon_state = "vial" /obj/item/dragons_blood/attack_self(mob/living/carbon/human/user) if(!istype(user)) return var/mob/living/carbon/human/H = user var/random = rand(1,4) switch(random) if(1) to_chat(user, "Your appearance morphs to that of a very small humanoid ash dragon! You get to look like a freak without the cool abilities.") H.dna.features = list("mcolor" = "A02720", "tail_lizard" = "Dark Tiger", "tail_human" = "None", "snout" = "Sharp", "horns" = "Curled", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "Long", "body_markings" = "Dark Tiger Body", "legs" = "Digitigrade Legs") H.eye_color = "fee5a3" H.set_species(/datum/species/lizard) if(2) to_chat(user, "Your flesh begins to melt! Miraculously, you seem fine otherwise.") H.set_species(/datum/species/skeleton) if(3) to_chat(user, "Power courses through you! You can now shift your form at will.") if(user.mind) var/obj/effect/proc_holder/spell/targeted/shapeshift/dragon/D = new user.mind.AddSpell(D) if(4) to_chat(user, "You feel like you could walk straight through lava now.") H.weather_immunities |= "lava" playsound(user.loc,'sound/items/drink.ogg', rand(10,50), 1) qdel(src) /datum/disease/transformation/dragon name = "dragon transformation" cure_text = "nothing" cures = list("adminordrazine") agent = "dragon's blood" desc = "What do dragons have to do with Space Station 13?" stage_prob = 20 severity = BIOHAZARD visibility_flags = 0 stage1 = list("Your bones ache.") stage2 = list("Your skin feels scaly.") stage3 = list("You have an overwhelming urge to terrorize some peasants.", "Your teeth feel sharper.") stage4 = list("Your blood burns.") stage5 = list("You're a fucking dragon. However, any previous allegiances you held still apply. It'd be incredibly rude to eat your still human friends for no reason.") new_form = /mob/living/simple_animal/hostile/megafauna/dragon/lesser //Lava Staff /obj/item/lava_staff name = "staff of lava" desc = "The ability to fill the emergency shuttle with lava. What more could you want out of life?" icon_state = "staffofstorms" item_state = "staffofstorms" lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' icon = 'icons/obj/guns/magic.dmi' slot_flags = SLOT_BACK w_class = WEIGHT_CLASS_BULKY force = 25 damtype = BURN resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF hitsound = 'sound/weapons/sear.ogg' var/turf_type = /turf/open/lava/smooth var/transform_string = "lava" var/reset_turf_type = /turf/open/floor/plating/asteroid/basalt var/reset_string = "basalt" var/create_cooldown = 100 var/create_delay = 30 var/reset_cooldown = 50 var/timer = 0 var/banned_turfs /obj/item/lava_staff/Initialize() . = ..() banned_turfs = typecacheof(list(/turf/open/space/transit, /turf/closed)) /obj/item/lava_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters) ..() if(timer > world.time) return if(is_type_in_typecache(target, banned_turfs)) return if(target in view(user.client.view, get_turf(user))) var/turf/open/T = get_turf(target) if(!istype(T)) return if(!istype(T, turf_type)) var/obj/effect/temp_visual/lavastaff/L = new /obj/effect/temp_visual/lavastaff(T) L.alpha = 0 animate(L, alpha = 255, time = create_delay) user.visible_message("[user] points [src] at [T]!") timer = world.time + create_delay + 1 if(do_after(user, create_delay, target = T)) var/old_name = T.name if(T.TerraformTurf(turf_type)) user.visible_message("[user] turns \the [old_name] into [transform_string]!") message_admins("[key_name_admin(user)] fired the lava staff at [get_area(target)]. [ADMIN_COORDJMP(T)]") log_game("[key_name(user)] fired the lava staff at [get_area(target)] [COORD(T)].") timer = world.time + create_cooldown playsound(T,'sound/magic/fireball.ogg', 200, 1) else timer = world.time qdel(L) else var/old_name = T.name if(T.TerraformTurf(reset_turf_type)) user.visible_message("[user] turns \the [old_name] into [reset_string]!") timer = world.time + reset_cooldown playsound(T,'sound/magic/fireball.ogg', 200, 1) /obj/effect/temp_visual/lavastaff icon_state = "lavastaff_warn" duration = 50 //Bubblegum /obj/structure/closet/crate/necropolis/bubblegum name = "bubblegum chest" /obj/structure/closet/crate/necropolis/bubblegum/PopulateContents() var/loot = rand(1,3) switch(loot) if(1) new /obj/item/mayhem(src) if(2) new /obj/item/blood_contract(src) if(3) new /obj/item/gun/magic/staff/spellblade(src) /obj/structure/closet/crate/necropolis/bubblegum/crusher name = "bloody bubblegum chest" /obj/structure/closet/crate/necropolis/bubblegum/crusher/PopulateContents() ..() new /obj/item/crusher_trophy/demon_claws(src) /obj/item/mayhem name = "mayhem in a bottle" desc = "A magically infused bottle of blood, the scent of which will drive anyone nearby into a murderous frenzy." icon = 'icons/obj/wizard.dmi' icon_state = "vial" /obj/item/mayhem/attack_self(mob/user) for(var/mob/living/carbon/human/H in range(7,user)) var/obj/effect/mine/pickup/bloodbath/B = new(H) INVOKE_ASYNC(B, /obj/effect/mine/pickup/bloodbath/.proc/mineEffect, H) to_chat(user, "You shatter the bottle!") playsound(user.loc, 'sound/effects/glassbr1.ogg', 100, 1) qdel(src) /obj/item/blood_contract name = "blood contract" icon = 'icons/obj/wizard.dmi' icon_state = "scroll2" color = "#FF0000" desc = "Mark your target for death. " var/used = FALSE /obj/item/blood_contract/attack_self(mob/user) if(used) return used = TRUE var/choice = input(user,"Who do you want dead?","Choose Your Victim") as null|anything in GLOB.player_list if(!(isliving(choice))) to_chat(user, "[choice] is already dead!") used = FALSE return if(choice == user) to_chat(user, "You feel like writing your own name into a cursed death warrant would be unwise.") used = FALSE return else var/mob/living/L = choice message_admins("[L] has been marked for death!") var/datum/objective/survive/survive = new survive.owner = L.mind L.mind.objectives += survive add_logs(user, L, "took out a blood contract on", src) to_chat(L, "You've been marked for death! Don't let the demons get you!") L.add_atom_colour("#FF0000", ADMIN_COLOUR_PRIORITY) var/obj/effect/mine/pickup/bloodbath/B = new(L) INVOKE_ASYNC(B, /obj/effect/mine/pickup/bloodbath/.proc/mineEffect, L) for(var/mob/living/carbon/human/H in GLOB.player_list) if(H == L) continue to_chat(H, "You have an overwhelming desire to kill [L]. [L.p_they(TRUE)] [L.p_have()] been marked red! Go kill [L.p_them()]!") H.put_in_hands_or_del(new /obj/item/kitchen/knife/butcher(H)) qdel(src) //Colossus /obj/structure/closet/crate/necropolis/colossus name = "colossus chest" /obj/structure/closet/crate/necropolis/colossus/PopulateContents() var/list/choices = subtypesof(/obj/machinery/anomalous_crystal) var/random_crystal = pick(choices) new random_crystal(src) new /obj/item/organ/vocal_cords/colossus(src) /obj/structure/closet/crate/necropolis/colossus/crusher name = "angelic colossus chest" /obj/structure/closet/crate/necropolis/colossus/crusher/PopulateContents() ..() new /obj/item/crusher_trophy/blaster_tubes(src) //Hierophant /obj/item/hierophant_club name = "hierophant club" desc = "The strange technology of this large club allows various nigh-magical feats. It used to beat you, but now you can set the beat." icon_state = "hierophant_club_ready_beacon" item_state = "hierophant_club_ready_beacon" icon = 'icons/obj/lavaland/artefacts.dmi' lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi' righthand_file = 'icons/mob/inhands/64x64_righthand.dmi' inhand_x_dimension = 64 inhand_y_dimension = 64 slot_flags = SLOT_BACK w_class = WEIGHT_CLASS_BULKY force = 15 attack_verb = list("clubbed", "beat", "pummeled") hitsound = 'sound/weapons/sonic_jackhammer.ogg' actions_types = list(/datum/action/item_action/vortex_recall, /datum/action/item_action/toggle_unfriendly_fire) var/cooldown_time = 20 //how long the cooldown between non-melee ranged attacks is var/chaser_cooldown = 81 //how long the cooldown between firing chasers at mobs is var/chaser_timer = 0 //what our current chaser cooldown is var/chaser_speed = 0.8 //how fast our chasers are var/timer = 0 //what our current cooldown is var/blast_range = 13 //how long the cardinal blast's walls are var/obj/effect/hierophant/beacon //the associated beacon we teleport to var/teleporting = FALSE //if we ARE teleporting var/friendly_fire_check = FALSE //if the blasts we make will consider our faction against the faction of hit targets /obj/item/hierophant_club/examine(mob/user) ..() to_chat(user, "The[beacon ? " beacon is not currently":"re is a beacon"] attached.") /obj/item/hierophant_club/suicide_act(mob/living/user) say("Xverwpsgexmrk...") user.visible_message("[user] holds [src] into the air! It looks like [user.p_theyre()] trying to commit suicide!") new/obj/effect/temp_visual/hierophant/telegraph(get_turf(user)) playsound(user,'sound/machines/airlockopen.ogg', 75, TRUE) user.visible_message("[user] fades out, leaving their belongings behind!") for(var/obj/item/I in user) if(I != src) user.dropItemToGround(I) for(var/turf/T in RANGE_TURFS(1, user)) var/obj/effect/temp_visual/hierophant/blast/B = new(T, user, TRUE) B.damage = 0 user.dropItemToGround(src) //Drop us last, so it goes on top of their stuff qdel(user) /obj/item/hierophant_club/afterattack(atom/target, mob/user, proximity_flag, click_parameters) ..() var/turf/T = get_turf(target) if(!T || timer > world.time) return calculate_anger_mod(user) timer = world.time + CLICK_CD_MELEE //by default, melee attacks only cause melee blasts, and have an accordingly short cooldown if(proximity_flag) INVOKE_ASYNC(src, .proc/aoe_burst, T, user) add_logs(user, target, "fired 3x3 blast at", src) else if(ismineralturf(target) && get_dist(user, target) < 6) //target is minerals, we can hit it(even if we can't see it) INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user) timer = world.time + cooldown_time else if(target in view(5, get_turf(user))) //if the target is in view, hit it timer = world.time + cooldown_time if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one! chaser_timer = world.time + chaser_cooldown var/obj/effect/temp_visual/hierophant/chaser/C = new(get_turf(user), user, target, chaser_speed, friendly_fire_check) C.damage = 30 C.monster_damage_boost = FALSE add_logs(user, target, "fired a chaser at", src) else INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user) //otherwise, just do cardinal blast add_logs(user, target, "fired cardinal blast at", src) else to_chat(user, "That target is out of range!" ) timer = world.time INVOKE_ASYNC(src, .proc/prepare_icon_update) /obj/item/hierophant_club/proc/calculate_anger_mod(mob/user) //we get stronger as the user loses health chaser_cooldown = initial(chaser_cooldown) cooldown_time = initial(cooldown_time) chaser_speed = initial(chaser_speed) blast_range = initial(blast_range) if(isliving(user)) var/mob/living/L = user var/health_percent = L.health / L.maxHealth chaser_cooldown += round(health_percent * 20) //two tenths of a second for each missing 10% of health cooldown_time += round(health_percent * 10) //one tenth of a second for each missing 10% of health chaser_speed = max(chaser_speed + health_percent, 0.5) //one tenth of a second faster for each missing 10% of health blast_range -= round(health_percent * 10) //one additional range for each missing 10% of health /obj/item/hierophant_club/update_icon() icon_state = "hierophant_club[timer <= world.time ? "_ready":""][(beacon && !QDELETED(beacon)) ? "":"_beacon"]" item_state = icon_state if(ismob(loc)) var/mob/M = loc M.update_inv_hands() M.update_inv_back() /obj/item/hierophant_club/proc/prepare_icon_update() update_icon() sleep(timer - world.time) update_icon() /obj/item/hierophant_club/ui_action_click(mob/user, action) if(istype(action, /datum/action/item_action/toggle_unfriendly_fire)) //toggle friendly fire... friendly_fire_check = !friendly_fire_check to_chat(user, "You toggle friendly fire [friendly_fire_check ? "off":"on"]!") return if(timer > world.time) return if(!user.is_holding(src)) //you need to hold the staff to teleport to_chat(user, "You need to hold the club in your hands to [beacon ? "teleport with it":"detach the beacon"]!") return if(!beacon || QDELETED(beacon)) if(isturf(user.loc)) user.visible_message("[user] starts fiddling with [src]'s pommel...", \ "You start detaching the hierophant beacon...") timer = world.time + 51 INVOKE_ASYNC(src, .proc/prepare_icon_update) if(do_after(user, 50, target = user) && !beacon) var/turf/T = get_turf(user) playsound(T,'sound/magic/blind.ogg', 200, 1, -4) new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, user) beacon = new/obj/effect/hierophant(T) user.update_action_buttons_icon() user.visible_message("[user] places a strange machine beneath [user.p_their()] feet!", \ "You detach the hierophant beacon, allowing you to teleport yourself and any allies to it at any time!\n\ You can remove the beacon to place it again by striking it with the club.") else timer = world.time INVOKE_ASYNC(src, .proc/prepare_icon_update) else to_chat(user, "You need to be on solid ground to detach the beacon!") return if(get_dist(user, beacon) <= 2) //beacon too close abort to_chat(user, "You are too close to the beacon to teleport to it!") return if(is_blocked_turf(get_turf(beacon), TRUE)) to_chat(user, "The beacon is blocked by something, preventing teleportation!") return if(!isturf(user.loc)) to_chat(user, "You don't have enough space to teleport from here!") return teleporting = TRUE //start channel user.update_action_buttons_icon() user.visible_message("[user] starts to glow faintly...") timer = world.time + 50 INVOKE_ASYNC(src, .proc/prepare_icon_update) beacon.icon_state = "hierophant_tele_on" var/obj/effect/temp_visual/hierophant/telegraph/edge/TE1 = new /obj/effect/temp_visual/hierophant/telegraph/edge(user.loc) var/obj/effect/temp_visual/hierophant/telegraph/edge/TE2 = new /obj/effect/temp_visual/hierophant/telegraph/edge(beacon.loc) if(do_after(user, 40, target = user) && user && beacon) var/turf/T = get_turf(beacon) var/turf/source = get_turf(user) if(is_blocked_turf(T, TRUE)) teleporting = FALSE to_chat(user, "The beacon is blocked by something, preventing teleportation!") user.update_action_buttons_icon() timer = world.time INVOKE_ASYNC(src, .proc/prepare_icon_update) beacon.icon_state = "hierophant_tele_off" return new /obj/effect/temp_visual/hierophant/telegraph(T, user) new /obj/effect/temp_visual/hierophant/telegraph(source, user) playsound(T,'sound/magic/wand_teleport.ogg', 200, 1) playsound(source,'sound/machines/airlockopen.ogg', 200, 1) if(!do_after(user, 3, target = user) || !user || !beacon || QDELETED(beacon)) //no walking away shitlord teleporting = FALSE if(user) user.update_action_buttons_icon() timer = world.time INVOKE_ASYNC(src, .proc/prepare_icon_update) if(beacon) beacon.icon_state = "hierophant_tele_off" return if(is_blocked_turf(T, TRUE)) teleporting = FALSE to_chat(user, "The beacon is blocked by something, preventing teleportation!") user.update_action_buttons_icon() timer = world.time INVOKE_ASYNC(src, .proc/prepare_icon_update) beacon.icon_state = "hierophant_tele_off" return add_logs(user, beacon, "teleported self from ([source.x],[source.y],[source.z]) to") new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, user) new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, user) for(var/t in RANGE_TURFS(1, T)) var/obj/effect/temp_visual/hierophant/blast/B = new /obj/effect/temp_visual/hierophant/blast(t, user, TRUE) //blasts produced will not hurt allies B.damage = 30 for(var/t in RANGE_TURFS(1, source)) var/obj/effect/temp_visual/hierophant/blast/B = new /obj/effect/temp_visual/hierophant/blast(t, user, TRUE) //but absolutely will hurt enemies B.damage = 30 for(var/mob/living/L in range(1, source)) INVOKE_ASYNC(src, .proc/teleport_mob, source, L, T, user) //regardless, take all mobs near us along sleep(6) //at this point the blasts detonate if(beacon) beacon.icon_state = "hierophant_tele_off" else qdel(TE1) qdel(TE2) timer = world.time INVOKE_ASYNC(src, .proc/prepare_icon_update) if(beacon) beacon.icon_state = "hierophant_tele_off" teleporting = FALSE if(user) user.update_action_buttons_icon() /obj/item/hierophant_club/proc/teleport_mob(turf/source, mob/M, turf/target, mob/user) var/turf/turf_to_teleport_to = get_step(target, get_dir(source, M)) //get position relative to caster if(!turf_to_teleport_to || is_blocked_turf(turf_to_teleport_to, TRUE)) return animate(M, alpha = 0, time = 2, easing = EASE_OUT) //fade out sleep(1) if(!M) return M.visible_message("[M] fades out!") sleep(2) if(!M) return M.forceMove(turf_to_teleport_to) sleep(1) if(!M) return animate(M, alpha = 255, time = 2, easing = EASE_IN) //fade IN sleep(1) if(!M) return M.visible_message("[M] fades in!") if(user != M) add_logs(user, M, "teleported", null, "from ([source.x],[source.y],[source.z])") /obj/item/hierophant_club/proc/cardinal_blasts(turf/T, mob/living/user) //fire cardinal cross blasts with a delay if(!T) return new /obj/effect/temp_visual/hierophant/telegraph/cardinal(T, user) playsound(T,'sound/effects/bin_close.ogg', 200, 1) sleep(2) new /obj/effect/temp_visual/hierophant/blast(T, user, friendly_fire_check) for(var/d in GLOB.cardinals) INVOKE_ASYNC(src, .proc/blast_wall, T, d, user) /obj/item/hierophant_club/proc/blast_wall(turf/T, dir, mob/living/user) //make a wall of blasts blast_range tiles long if(!T) return var/range = blast_range var/turf/previousturf = T var/turf/J = get_step(previousturf, dir) for(var/i in 1 to range) if(!J) return var/obj/effect/temp_visual/hierophant/blast/B = new(J, user, friendly_fire_check) B.damage = 30 B.monster_damage_boost = FALSE previousturf = J J = get_step(previousturf, dir) /obj/item/hierophant_club/proc/aoe_burst(turf/T, mob/living/user) //make a 3x3 blast around a target if(!T) return new /obj/effect/temp_visual/hierophant/telegraph(T, user) playsound(T,'sound/effects/bin_close.ogg', 200, 1) sleep(2) for(var/t in RANGE_TURFS(1, T)) var/obj/effect/temp_visual/hierophant/blast/B = new(t, user, friendly_fire_check) B.damage = 15 //keeps monster damage boost due to lower damage