diff --git a/code/datums/action.dm b/code/datums/action.dm index a65294fa40..cf1046ca8f 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -591,3 +591,50 @@ var/mob/M = owner var/datum/language_holder/H = M.get_language_holder() H.open_language_menu(usr) + +/datum/action/innate/dash + name = "Dash" + desc = "Teleport to the targeted location." + icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon_state = "jetboot" + var/charged = TRUE + var/charge_rate = 250 + var/mob/living/carbon/human/holder + var/obj/item/dashing_item + var/dash_sound = 'sound/magic/blink.ogg' + var/recharge_sound = 'sound/magic/charge.ogg' + var/beam_effect = "blur" + var/phasein = /obj/effect/temp_visual/dir_setting/ninja/phase + var/phaseout = /obj/effect/temp_visual/dir_setting/ninja/phase/out + +/datum/action/innate/dash/Grant(mob/user, obj/dasher) + . = ..() + dashing_item = dasher + holder = user + +/datum/action/innate/dash/IsAvailable() + if(charged) + return TRUE + else + return FALSE + +/datum/action/innate/dash/Activate() + dashing_item.attack_self(holder) //Used to toggle dash behavior in the dashing item + +/datum/action/innate/dash/proc/Teleport(mob/user, atom/target) + var/turf/T = get_turf(target) + if(target in view(user.client.view, get_turf(user))) + var/obj/spot1 = new phaseout(get_turf(user), user.dir) + user.forceMove(T) + playsound(T, dash_sound, 25, 1) + var/obj/spot2 = new phasein(get_turf(user), user.dir) + spot1.Beam(spot2,beam_effect,time=20) + charged = FALSE + holder.update_action_buttons_icon() + addtimer(CALLBACK(src, .proc/charge), charge_rate) + +/datum/action/innate/dash/proc/charge() + charged = TRUE + holder.update_action_buttons_icon() + playsound(dashing_item, recharge_sound, 50, 1) + to_chat(holder, "[dashing_item] is ready for another jaunt.") \ No newline at end of file diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 25b04b4312..20d218f767 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -384,3 +384,31 @@ if(islist(owner.stun_absorption) && owner.stun_absorption["blooddrunk"]) owner.stun_absorption -= "blooddrunk" +/datum/status_effect/sword_spin + id = "Bastard Sword Spin" + duration = 50 + tick_interval = 8 + alert_type = null + + +/datum/status_effect/sword_spin/on_apply() + owner.visible_message("[owner] begins swinging the sword with inhuman strength!") + var/oldcolor = owner.color + owner.color = "#ff0000" + owner.add_stun_absorption("bloody bastard sword", duration, 2, "doesn't even flinch as the sword's power courses through them!", "You shrug off the stun!", " glowing with a blazing red aura!") + owner.spin(duration,1) + animate(owner, color = oldcolor, time = duration, easing = EASE_IN) + addtimer(CALLBACK(owner, /atom/proc/update_atom_colour), duration) + playsound(owner, 'sound/weapons/fwoosh.wav', 75, 0) + return ..() + + +/datum/status_effect/sword_spin/tick() + playsound(owner, 'sound/weapons/fwoosh.wav', 75, 0) + var/obj/item/slashy + slashy = owner.get_active_held_item() + for(var/mob/living/M in orange(1,owner)) + slashy.attack(M, owner) + +/datum/status_effect/sword_spin/on_remove() + owner.visible_message("[owner]'s inhuman strength dissipates and the sword's runes grow cold!") diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 55f8ece5e6..876cace14d 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -72,6 +72,170 @@ if(is_servant_of_ratvar(C) && C.reagents) C.reagents.add_reagent("heparin", 1) +/obj/item/twohanded/required/cult_bastard + name = "bloody bastard sword" + desc = "An enormous sword used by Nar-Sien cultists to rapidly harvest the souls of non-believers." + w_class = WEIGHT_CLASS_HUGE + block_chance = 50 + throwforce = 20 + force = 35 + armour_penetration = 45 + throw_speed = 1 + throw_range = 3 + sharpness = IS_SHARP + light_color = "#ff0000" + attack_verb = list("cleaved", "slashed", "torn", "hacked", "ripped", "diced", "carved") + icon_state = "cultbastard" + item_state = "cultbastard" + hitsound = 'sound/weapons/bladeslice.ogg' + lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi' + righthand_file = 'icons/mob/inhands/64x64_righthand.dmi' + inhand_x_dimension = 64 + inhand_y_dimension = 64 + actions_types = list() + flags_2 = SLOWS_WHILE_IN_HAND_2 + var/datum/action/innate/dash/cult/jaunt + var/datum/action/innate/cult/spin2win/linked_action + var/spinning = FALSE + var/spin_cooldown = 250 + var/list/shards = list() + var/dash_toggled = TRUE + +/obj/item/twohanded/required/cult_bastard/Initialize() + . = ..() + set_light(4) + jaunt = new(src) + linked_action = new(src) + +/obj/item/twohanded/required/cult_bastard/can_be_pulled(user) + return FALSE + +/obj/item/twohanded/required/cult_bastard/attack_self(mob/user) + dash_toggled = !dash_toggled + if(dash_toggled) + to_chat(loc, "You raise the [src] and prepare to jaunt with it.") + else + to_chat(loc, "You lower the [src] and prepare to swing it normally.") + +/obj/item/twohanded/required/cult_bastard/pickup(mob/living/user) + . = ..() + if(!iscultist(user)) + if(!is_servant_of_ratvar(user)) + to_chat(user, "\"I wouldn't advise that.\"") + to_chat(user, "An overwhelming sense of nausea overpowers you!") + user.Dizzy(80) + user.Knockdown(30) + return + else + to_chat(user, "\"One of Ratvar's toys is trying to play with things [user.p_they()] shouldn't. Cute.\"") + to_chat(user, "A horrible force yanks at your arm!") + user.emote("scream") + user.apply_damage(30, BRUTE, pick("l_arm", "r_arm")) + user.Knockdown(50) + return + jaunt.Grant(user, src) + linked_action.Grant(user, src) + user.update_icons() + +/obj/item/twohanded/required/cult_bastard/dropped(mob/user) + . = ..() + linked_action.Remove(user) + jaunt.Remove(user) + user.update_icons() + +/obj/item/twohanded/required/cult_bastard/IsReflect() + if(spinning) + playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) + return TRUE + else + ..() + +/obj/item/twohanded/required/cult_bastard/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + if(prob(final_block_chance)) + if(attack_type == PROJECTILE_ATTACK) + owner.visible_message("[owner] deflects [attack_text] with [src]!") + playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 100, 1) + return TRUE + else + playsound(src, 'sound/weapons/parry.ogg', 75, 1) + owner.visible_message("[owner] parries [attack_text] with [src]!") + return TRUE + return FALSE + +/obj/item/twohanded/required/cult_bastard/afterattack(atom/target, mob/user, proximity, click_parameters) + . = ..() + if(dash_toggled && jaunt.IsAvailable()) + jaunt.Teleport(user, target) + return + if(!proximity) + return + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(H.stat != CONSCIOUS) + var/obj/item/device/soulstone/SS = new /obj/item/device/soulstone(src) + SS.attack(H, user) + shards += SS + return + if(istype(target, /obj/structure/constructshell) && contents.len) + var/obj/item/device/soulstone/SS = contents[1] + if(istype(SS) && SS.transfer_soul("CONSTRUCT",target,user)) + qdel(SS) + +/datum/action/innate/dash/cult + name = "Rend the Veil" + desc = "Use the sword to shear open the flimsy fabric of this reality and teleport to your target." + icon_icon = 'icons/mob/actions/actions_cult.dmi' + button_icon_state = "phaseshift" + dash_sound = 'sound/magic/enter_blood.ogg' + recharge_sound = 'sound/magic/exit_blood.ogg' + beam_effect = "sendbeam" + phasein = /obj/effect/temp_visual/dir_setting/cult/phase + phaseout = /obj/effect/temp_visual/dir_setting/cult/phase/out + +/datum/action/innate/dash/cult/IsAvailable() + if(iscultist(holder) && charged) + return TRUE + else + return FALSE + + + +/datum/action/innate/cult/spin2win + name = "Geometer's Fury" + desc = "You draw on the power of the sword's ancient runes, spinning it wildly around you as you become immune to most attacks." + background_icon_state = "bg_demon" + button_icon_state = "sintouch" + var/cooldown = 0 + var/mob/living/carbon/human/holder + var/obj/item/twohanded/required/cult_bastard/sword + +/datum/action/innate/cult/spin2win/Grant(mob/user, obj/bastard) + . = ..() + sword = bastard + holder = user + +/datum/action/innate/cult/spin2win/IsAvailable() + if(iscultist(holder) && cooldown <= world.time) + return TRUE + else + return FALSE + +/datum/action/innate/cult/spin2win/Activate() + cooldown = world.time + sword.spin_cooldown + holder.changeNext_move(50) + holder.apply_status_effect(/datum/status_effect/sword_spin) + sword.spinning = TRUE + sword.block_chance = 100 + sword.slowdown += 1.5 + addtimer(CALLBACK(src, .proc/stop_spinning), 50) + holder.update_action_buttons_icon() + +/datum/action/innate/cult/spin2win/proc/stop_spinning() + sword.spinning = FALSE + sword.block_chance = 50 + sword.slowdown -= 1.5 + sleep(sword.spin_cooldown) + holder.update_action_buttons_icon() /obj/item/restraints/legcuffs/bola/cult name = "nar'sien bola" diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index c1ccf9a368..0144872c17 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -100,15 +100,21 @@ if(cooldowntime > world.time) to_chat(user, "The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].") return - var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Nar-Sien Hardsuit") + var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Bastard Sword") var/pickedtype switch(choice) if("Shielded Robe") pickedtype = /obj/item/clothing/suit/hooded/cultrobes/cult_shield if("Flagellant's Robe") pickedtype = /obj/item/clothing/suit/hooded/cultrobes/berserker - if("Nar-Sien Hardsuit") - pickedtype = /obj/item/clothing/suit/space/hardsuit/cult + if("Bastard Sword") + if((world.time - SSticker.round_start_time) >= 12000) + pickedtype = /obj/item/twohanded/required/cult_bastard + else + cooldowntime = 12000 - (world.time - SSticker.round_start_time) + to_chat(user, "The forge fires are not yet hot enough for this weapon, give it another [DisplayTimeText(cooldowntime - world.time)].") + cooldowntime = 0 + return if(src && !QDELETED(src) && anchored && pickedtype && Adjacent(user) && !user.incapacitated() && iscultist(user) && cooldowntime <= world.time) cooldowntime = world.time + 2400 var/obj/item/N = new pickedtype(get_turf(src)) diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index df57ded774..149c2ae912 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -199,7 +199,6 @@ SSticker.mode.cult -= A.mind SSticker.mode.update_cult_icons_removed(A.mind) qdel(T) - user.drop_item() qdel(src) else to_chat(user, "Creation failed!: The soul stone is empty! Go kill someone!") diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index dc6993cdbe..28856e17d8 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -156,6 +156,24 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", var/unholy2clean = A.reagents.get_reagent_amount("unholywater") A.reagents.del_reagent("unholywater") A.reagents.add_reagent("holywater",unholy2clean) + if(istype(A, /obj/item/twohanded/required/cult_bastard)) + var/obj/item/twohanded/required/cult_bastard/sword = A + to_chat(user, "You begin to exorcise [sword].") + playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,1) + if(do_after(user, 40, target = sword)) + playsound(src,'sound/effects/pray_chaplain.ogg',60,1) + for(var/obj/item/device/soulstone/SS in sword.shards) + SS.usability = TRUE + for(var/mob/living/simple_animal/shade/EX in SS) + SSticker.mode.remove_cultist(EX.mind, 1, 0) + EX.icon_state = "ghost1" + EX.name = "Purified [EX.name]" + SS.release_shades(user) + qdel(SS) + new /obj/item/nullrod/claymore(get_turf(sword)) + user.visible_message("[user] has purified the [sword]!!") + qdel(sword) + /obj/item/storage/book/bible/booze desc = "To be applied to the head repeatedly." diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi index a9a952733a..1b450ab3e0 100644 Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi index bff96a991b..bbeddf9152 100644 Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi index 94c0c03835..b5ac65c2a8 100644 Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ diff --git a/sound/weapons/fwoosh.wav b/sound/weapons/fwoosh.wav new file mode 100644 index 0000000000..1723c4e9b8 Binary files /dev/null and b/sound/weapons/fwoosh.wav differ diff --git a/sound/weapons/parry.ogg b/sound/weapons/parry.ogg new file mode 100644 index 0000000000..1f86716337 Binary files /dev/null and b/sound/weapons/parry.ogg differ